From savetherbtz at gmail.com Mon Jun 1 00:45:46 2015 From: savetherbtz at gmail.com (Alexey Ivanov) Date: Sun, 31 May 2015 17:45:46 -0700 Subject: problems when use fastcgi_pass to deliver request to backend In-Reply-To: <35AFFAB0BF4E8B41BD040AD35CA32BEC4806B8A6DF@mailbox.feinno.com> References: <35AFFAB0BF4E8B41BD040AD35CA32BEC4806B8A6DD@mailbox.feinno.com> <35AFFAB0BF4E8B41BD040AD35CA32BEC4806B8A6DF@mailbox.feinno.com> Message-ID: <13283EBD-477E-4D82-8A71-A626A8B0ED29@gmail.com> If your backend can?t handle 10k connections then you should limit them there. Forwarding requests to the backend that can not handle the request is generally a bad idea[1] an it is usually better to fail the request or make them wait for a available backend on proxy itself. Nginx can retry requests if it gets timeout or RST (connection refused) from a backend[2]. That combined with tcp_abort_on_overflow[3], listen(2) backlog argument and maybe some application limits should be enough to fix your problem. [1] http://genius.com/James-somers-herokus-ugly-secret-annotated [2] http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_next_upstream [3] https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt > On May 29, 2015, at 3:48 AM, ?? wrote: > > Thanks for reply, > I had read all the Discussions you suggested. > The main reason is that multiplexing seems useless when using ?keep alive? feature and backend is fast enough. > It?s true! But real world is more sophisticated. > > Our system is very big, and over 5k machines are providing services. In Our system, nginx proxy_pass http request to http applications by using ?keep alive?, it works well, over 10 k requests were processed per second and tcp connections between nginx and backend were blow 100. But, sometimes, response time become 1-10s or more for a while, because maybe a db server fail over or network shrink. Over 10k tcp connection need to be setup as we see. > our backend is written by java, connections cannot be setup all a sudden, and memory needed is big , GC collections became bottleneck, GC keep on working even if db server or network resumed to normal, and backend server did not work orderly any more, I observed these things several times. > > If multiplexing, no more connections are needed and memory needed is far small under such a circumstance. We use multiplexing everywhere in our java applications, It can prove my idea. > > Nginx is needed for sure for client http access, so I study fastcgi to solve above problem, but nginx does support fastcgi multiplexing, which can trigger the same problem. > > As a conclusion, a big production system really need that nginx pass request to backend by multiplexing. Can you make nginx developing team work on it? > > > > ???: Sergey Brester [mailto:serg.brester at sebres.de] > ????: 2015?5?29? 16:40 > ???: nginx-devel at nginx.org > ??: ?? > ??: Re: ??: problems when use fastcgi_pass to deliver request to backend > > Hi, > > It's called fastcgi multiplexing and nginx currently does not implement that (and I don't know . > > There were already several discussions about that, so read here, please. > > Short, very fast fastcgi processing may be implemented without multiplexing (should be event-driven also). > > Regards, > sebres. > > > > Am 29.05.2015 09:58, schrieb ??: > > > /* we support the single request per connection */ > 2573 > > 2574 > case ngx_http_fastcgi_st_request_id_hi: > 2575 > if (ch != 0) { > 2576 > ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, > 2577 > "upstream sent unexpected FastCGI " > 2578 > "request id high byte: %d", ch); > 2579 > return NGX_ERROR; > 2580 > } > 2581 > state = ngx_http_fastcgi_st_request_id_lo; > 2582 > break; > 2583 > > 2584 > case ngx_http_fastcgi_st_request_id_lo: > 2585 > if (ch != 1) { > 2586 > ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, > 2587 > "upstream sent unexpected FastCGI " > 2588 > "request id low byte: %d", ch); > 2589 > return NGX_ERROR; > 2590 > } > 2591 > state = ngx_http_fastcgi_st_content_length_hi; > 2592 > break; > By reading source code, I saw the reason , so can nginx support multi request per connection in future? > > ???: ?? > ????: 2015?5?29? 11:37 > ???: 'nginx-devel at nginx.org' > ??: problems when use fastcgi_pass to deliver request to backend > > Hi, > I write a fastcgi server and use nginx to pass request to my server. It works till now. > But I find a problem. Nginx always set requestId = 1 when sending fastcgi record. > I was a little upset for this, cause according to fastcgi protocol, web server can send fastcgi records belonging to different request simultaneously, and requestIds are different and keep unique. I really need this feature, because requests can be handled simultaneously just over one connetion. > Can I find a way out? > > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 842 bytes Desc: Message signed with OpenPGP using GPGMail URL: From vbart at nginx.com Mon Jun 1 13:58:33 2015 From: vbart at nginx.com (Valentin Bartenev) Date: Mon, 01 Jun 2015 13:58:33 +0000 Subject: [nginx] Fixed spelling in change logs. Message-ID: details: http://hg.nginx.org/nginx/rev/ab78c12412ce branches: changeset: 6162:ab78c12412ce user: Valentin Bartenev date: Mon Jun 01 16:58:07 2015 +0300 description: Fixed spelling in change logs. diffstat: docs/xml/nginx/changes.xml | 26 +++++++++++++------------- 1 files changed, 13 insertions(+), 13 deletions(-) diffs (96 lines): diff -r e034af368274 -r ab78c12412ce docs/xml/nginx/changes.xml --- a/docs/xml/nginx/changes.xml Fri May 29 09:26:33 2015 +0300 +++ b/docs/xml/nginx/changes.xml Mon Jun 01 16:58:07 2015 +0300 @@ -278,7 +278,7 @@ Thanks to Sven Peter, Franck Levionnois, ?????????? ??????? ??????? -??? ????????????? ???????? "hash ... consistent" ? ????? upstream.
+??? ????????????? ????????? "hash ... consistent" ? ????? upstream.
??????? Wai Keen Woon.
@@ -4977,7 +4977,7 @@ responses from cache might hang. ?????? ????????? ? 1.1.9. -a segmentation fault occured in a worker process if AIO was used on Linux; +a segmentation fault occurred in a worker process if AIO was used on Linux; the bug had appeared in 1.1.9.
@@ -5927,7 +5927,7 @@ Thanks to Maxim Dounin. ??????? Lanshun Zhou. -in parameter validaiton of a "proxy_pass" directive with variables.
+in parameter validation of a "proxy_pass" directive with variables.
Thanks to Lanshun Zhou.
@@ -14899,7 +14899,7 @@ the bug had appeared in 0.5.21. if server has more than about ten locations, then regex locations -might be choosen not in that order as they were specified. +might be chosen not in that order as they were specified. @@ -15185,7 +15185,7 @@ in the HTTPS protocol in the "proxy_pass ?????????? ?????? ?????????????? ????????. -in some cases non-cachable variables (such as $uri variable) +in some cases non-cacheable variables (such as $uri variable) returned old cached value. @@ -15252,12 +15252,12 @@ the bug had appeared in 0.5.15. ???????? ??????-?????? ???????????? ??????????????????? SMTP-????????????? ? -????????? smtp_auth, smtp_capablities ? xclient.
+????????? smtp_auth, smtp_capabilities ? xclient.
??????? ?????? ????????? ? ??????? ??????.
the mail proxy supports authenticated SMTP proxying and -the "smtp_auth", "smtp_capablities", and "xclient" directives.
+the "smtp_auth", "smtp_capabilities", and "xclient" directives.
Thanks to Anton Yuzhaninov and Maxim Dounin.
@@ -18760,7 +18760,7 @@ the ngx_http_perl_module. ????????? valid_referers ????????? ???????????? ???????? ?????? ??? URI. -the "valid_referers" directive allows the referreres without URI part. +the "valid_referers" directive allows the referrers without URI part. @@ -19080,10 +19080,10 @@ the "so_keepalive" directive in IMAP/POP nginx ?????? ???????? abort() ??? ??????????? ?????????? ?????????? -?????? ??? ?????? ?????? ? ?????????? ????????? debug_points. - - -if there are unclosed connection nginx now calls abort() only on gracefull +?????? ??? ??????? ?????? ? ?????????? ????????? debug_points. + + +if there are unclosed connection nginx now calls abort() only on graceful quit and active "debug_points" directive. @@ -20862,7 +20862,7 @@ if many parts or the big parts were incl ??????? ??????????? ??? ??????? ?????. -if all backends had returned the 404 reponse and the "http_404" parameter of +if all backends had returned the 404 response and the "http_404" parameter of the "proxy_next_upstream" or "fastcgi_next_upstream" directives was used, then nginx started to request all backends again. From mdounin at mdounin.ru Mon Jun 1 15:38:12 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 1 Jun 2015 18:38:12 +0300 Subject: zero size buf in output In-Reply-To: References: Message-ID: <20150601153812.GS26357@mdounin.ru> Hello! On Fri, May 29, 2015 at 11:21:28AM +0100, Carlos Eduardo Ferreira Rodrigues wrote: > Hi, > > Another issue I started seeing after moving to 1.8.0 is messages like these in the error log: > > 2015/05/29 09:29:40 [alert] 16116#0: *82677257 zero size buf in output t:0 r:0 f:0 00007FF33C18F6D0 00007FF33C18F6D0-00007FF33C19F2B6 0000000000000000 0-0 while sending to client [...] > > I've seen a mention of this as having been fixed a few versions ago, but it seems to have returned. The message indicate that something is incorrectly created a buffer in the output chain. If you are able to reproduce this without 3rd party modules, please provide more details, see hints here: http://wiki.nginx.org/Debugging If this only appears with 3rd party modules, it may be better idea to find out which module causes this and report this to the module author. -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Mon Jun 1 16:04:46 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 1 Jun 2015 19:04:46 +0300 Subject: Kernel stall while testing high-speed HTTPS traffic. In-Reply-To: <55676BFF.9020800@candelatech.com> References: <55676BFF.9020800@candelatech.com> Message-ID: <20150601160446.GT26357@mdounin.ru> Hello! On Thu, May 28, 2015 at 12:26:55PM -0700, Ben Greear wrote: > We are seeing problems with Nginx (mostly)locking up the server when > running high loads of HTTPS traffic. > > This scenario we had nginx configured to > bind to eth3 but our ssh sessions on eth0 were frozen during this condition as well. > The system restores itself after a few minutes, (the load generation would > have stopped after a minute or two of lockup, that may be what lets things > recover). [...] > === Scenario === > Load testing box has a direct connection to eth3->eth3 over 10Gbps port. > > Curl clients using https, keepalive, requesting a 1MB file: > 1000 clients @ 0.25 req/sec = 243 req/sec, 2.2Gbps tx, load 8.3 > 400 clients @ 0.65 req/sec = 260 req/sec, 2.2Gbps tx, load 9.2 [...] > directio 1m; As you are testing with 1m file, and have "directio 1m" in your configuration, you are probably reading your files straigh off the disk, bypassing filesystem caches. Given the fact that you are using default output_buffers, this is likely to cause lots of disk IO requests with such a workload, and likely cause the problem you see. Adding something like "output_buffers 1 1m;" and/or removing "directio" should help. (Note that you won't see the problem with plain HTTP, as you have sendfile enabled in your config, likely resulting in more effecient disk usage. The problem appears with HTTPS because sendfile() can't be used with encrypted connections.) (Either way, this topic looks unrelated to nginx-devel at .) -- Maxim Dounin http://nginx.org/ From vbart at nginx.com Mon Jun 1 18:10:11 2015 From: vbart at nginx.com (Valentin Bartenev) Date: Mon, 01 Jun 2015 18:10:11 +0000 Subject: [nginx] Fixed excessive memory usage while parsing configuration. Message-ID: details: http://hg.nginx.org/nginx/rev/4e71788460fa branches: changeset: 6163:4e71788460fa user: Valentin Bartenev date: Mon Jun 01 21:08:56 2015 +0300 description: Fixed excessive memory usage while parsing configuration. The b->pos points to the next symbol here. Reported by ilexshen. diffstat: src/core/ngx_conf_file.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r ab78c12412ce -r 4e71788460fa src/core/ngx_conf_file.c --- a/src/core/ngx_conf_file.c Mon Jun 01 16:58:07 2015 +0300 +++ b/src/core/ngx_conf_file.c Mon Jun 01 21:08:56 2015 +0300 @@ -680,7 +680,7 @@ ngx_conf_read_token(ngx_conf_t *cf) return NGX_ERROR; } - word->data = ngx_pnalloc(cf->pool, b->pos - start + 1); + word->data = ngx_pnalloc(cf->pool, b->pos - 1 - start + 1); if (word->data == NULL) { return NGX_ERROR; } From mat999 at gmail.com Tue Jun 2 01:04:43 2015 From: mat999 at gmail.com (SplitIce) Date: Tue, 2 Jun 2015 11:04:43 +1000 Subject: [RFC] event/openssl: Add dynamic record size support for serving ssl trafic In-Reply-To: References: <34abb03e.16155.14d244dae6f.Coremail.gzchenym@126.com> Message-ID: Mark, >From memory SSL_CIPHER_is_AES is a BoringSSL addition isnt it? I did a quick look over the OpenSSL source and it does not seem like its been added either. I havent had a chance to compile this yet to confirm it, but if correct then this is not compatible with OpenSSL and possibly other SSL libraries. Regards, Mathew On Thu, May 28, 2015 at 2:43 AM, W-Mark Kubacki wrote: > 2015-05-05 15:39 GMT+02:00 chen : > > > > This is v1 of the patchset the implementing the feature SSL Dynamic > Record > > Sizing, inspiring by Google Front End [?] > > > > Any comments is welcome. > > Nice! I've implemented that for Golang in the past and have ported it > to C for you today. > > Although a single initial packet might seem more attractive in > benchmarks, I found that sending two results in better catching parts > of HEAD ? which is what we want. Then you will notice some dancing > around IW4, by which we've already sent about 5683 octets. Enough for > me for a making a tradeoff here. > > 16k as ssl->buffer_size results in partially filled packets. A better > default value could minimize the overhead (<0.5%) for that trailing > PDUs. > > SSL libraries really should provide a function for computing overhead. > > -- > Mark > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -------------- next part -------------- An HTML attachment was scrubbed... URL: From mat999 at gmail.com Tue Jun 2 01:07:07 2015 From: mat999 at gmail.com (SplitIce) Date: Tue, 2 Jun 2015 11:07:07 +1000 Subject: [RFC] event/openssl: Add dynamic record size support for serving ssl trafic In-Reply-To: References: <34abb03e.16155.14d244dae6f.Coremail.gzchenym@126.com> Message-ID: Shortly after sending my response I found the commit for BoringSSL adding the function. https://boringssl.googlesource.com/boringssl/+/4d4bff89bb8ec345d289412f0f7f135c6e51b1a6%5E!/ On Thu, May 28, 2015 at 2:43 AM, W-Mark Kubacki wrote: > 2015-05-05 15:39 GMT+02:00 chen : > > > > This is v1 of the patchset the implementing the feature SSL Dynamic > Record > > Sizing, inspiring by Google Front End [?] > > > > Any comments is welcome. > > Nice! I've implemented that for Golang in the past and have ported it > to C for you today. > > Although a single initial packet might seem more attractive in > benchmarks, I found that sending two results in better catching parts > of HEAD ? which is what we want. Then you will notice some dancing > around IW4, by which we've already sent about 5683 octets. Enough for > me for a making a tradeoff here. > > 16k as ssl->buffer_size results in partially filled packets. A better > default value could minimize the overhead (<0.5%) for that trailing > PDUs. > > SSL libraries really should provide a function for computing overhead. > > -- > Mark > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -------------- next part -------------- An HTML attachment was scrubbed... URL: From linsu at feinno.com Tue Jun 2 04:04:47 2015 From: linsu at feinno.com (=?utf-8?B?5p6X6LCh?=) Date: Tue, 2 Jun 2015 12:04:47 +0800 Subject: =?UTF-8?Q?=E7=AD=94=E5=A4=8D=3A_problems_when_use_fastcgi=5Fpass_to_delive?= =?UTF-8?Q?r_request_to_backend?= In-Reply-To: <13283EBD-477E-4D82-8A71-A626A8B0ED29@gmail.com> References: <35AFFAB0BF4E8B41BD040AD35CA32BEC4806B8A6DD@mailbox.feinno.com> <35AFFAB0BF4E8B41BD040AD35CA32BEC4806B8A6DF@mailbox.feinno.com> <13283EBD-477E-4D82-8A71-A626A8B0ED29@gmail.com> Message-ID: <35AFFAB0BF4E8B41BD040AD35CA32BEC4806B8A6EF@mailbox.feinno.com> Thanks for your reply. Let me make the question more clear. Assume that backend receive 10 k request per second, backend can give response within 10 ms, then 100 connection is needed, If backend for some reason response over 1s, 10k connections have to be created within 1s, I don't think there exists such a backend can handle this, even it is nginx. We surely can make flow control on backend, but It's a sorrow most of these requests have to be dropped. If multiplexing is provided, things can go like this: If backend for some reason response over 1s, requests can flow into backend as usual by 1 or more connections, backend can queued requests(usually 50k) as much as possible under the control of its own memory health permission for later handling. As we can see, a 5 seconds slow down can be overcame smoothly by multiplexing, but without multiplexing most of client receive error response. in real production world, a sudden client request summit or a backend sudden slow down often happens, multiplexing is very beneficial for backend to do work smoothly and provide more output. I really think nginx need fastcgi multiplexing . -----????----- ???: Alexey Ivanov [mailto:savetherbtz at gmail.com] ????: 2015?6?1? 8:46 ???: nginx-devel at nginx.org ??: Sergey Brester; ???; ??; ???; RCS-Tech; ?? ??: Re: problems when use fastcgi_pass to deliver request to backend If your backend can?t handle 10k connections then you should limit them there. Forwarding requests to the backend that can not handle the request is generally a bad idea[1] an it is usually better to fail the request or make them wait for a available backend on proxy itself. Nginx can retry requests if it gets timeout or RST (connection refused) from a backend[2]. That combined with tcp_abort_on_overflow[3], listen(2) backlog argument and maybe some application limits should be enough to fix your problem. [1] http://genius.com/James-somers-herokus-ugly-secret-annotated [2] http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_next_upstream [3] https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt > On May 29, 2015, at 3:48 AM, ?? wrote: > > Thanks for reply, > I had read all the Discussions you suggested. > The main reason is that multiplexing seems useless when using ?keep alive? feature and backend is fast enough. > It?s true! But real world is more sophisticated. > > Our system is very big, and over 5k machines are providing services. In Our system, nginx proxy_pass http request to http applications by using ?keep alive?, it works well, over 10 k requests were processed per second and tcp connections between nginx and backend were blow 100. But, sometimes, response time become 1-10s or more for a while, because maybe a db server fail over or network shrink. Over 10k tcp connection need to be setup as we see. > our backend is written by java, connections cannot be setup all a sudden, and memory needed is big , GC collections became bottleneck, GC keep on working even if db server or network resumed to normal, and backend server did not work orderly any more, I observed these things several times. > > If multiplexing, no more connections are needed and memory needed is far small under such a circumstance. We use multiplexing everywhere in our java applications, It can prove my idea. > > Nginx is needed for sure for client http access, so I study fastcgi to solve above problem, but nginx does support fastcgi multiplexing, which can trigger the same problem. > > As a conclusion, a big production system really need that nginx pass request to backend by multiplexing. Can you make nginx developing team work on it? > > > > ???: Sergey Brester [mailto:serg.brester at sebres.de] > ????: 2015?5?29? 16:40 > ???: nginx-devel at nginx.org > ??: ?? > ??: Re: ??: problems when use fastcgi_pass to deliver request to backend > > Hi, > > It's called fastcgi multiplexing and nginx currently does not implement that (and I don't know . > > There were already several discussions about that, so read here, please. > > Short, very fast fastcgi processing may be implemented without multiplexing (should be event-driven also). > > Regards, > sebres. > > > > Am 29.05.2015 09:58, schrieb ??: > > > /* we support the single request per connection */ > 2573 > > 2574 > case ngx_http_fastcgi_st_request_id_hi: > 2575 > if (ch != 0) { > 2576 > ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, > 2577 > "upstream sent unexpected FastCGI " > 2578 > "request id high byte: %d", ch); > 2579 > return NGX_ERROR; > 2580 > } > 2581 > state = ngx_http_fastcgi_st_request_id_lo; > 2582 > break; > 2583 > > 2584 > case ngx_http_fastcgi_st_request_id_lo: > 2585 > if (ch != 1) { > 2586 > ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, > 2587 > "upstream sent unexpected FastCGI " > 2588 > "request id low byte: %d", ch); > 2589 > return NGX_ERROR; > 2590 > } > 2591 > state = ngx_http_fastcgi_st_content_length_hi; > 2592 > break; > By reading source code, I saw the reason , so can nginx support multi request per connection in future? > > ???: ?? > ????: 2015?5?29? 11:37 > ???: 'nginx-devel at nginx.org' > ??: problems when use fastcgi_pass to deliver request to backend > > Hi, > I write a fastcgi server and use nginx to pass request to my server. It works till now. > But I find a problem. Nginx always set requestId = 1 when sending fastcgi record. > I was a little upset for this, cause according to fastcgi protocol, web server can send fastcgi records belonging to different request simultaneously, and requestIds are different and keep unique. I really need this feature, because requests can be handled simultaneously just over one connetion. > Can I find a way out? > > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel From wmark+nginx at hurrikane.de Tue Jun 2 18:14:45 2015 From: wmark+nginx at hurrikane.de (W-Mark Kubacki) Date: Tue, 2 Jun 2015 20:14:45 +0200 Subject: [RFC] event/openssl: Add dynamic record size support for serving ssl trafic In-Reply-To: References: <34abb03e.16155.14d244dae6f.Coremail.gzchenym@126.com> Message-ID: 2015-06-02 3:04 GMT+02:00 SplitIce : > From memory SSL_CIPHER_is_AES is a BoringSSL addition isnt it? I did a quick > look over the OpenSSL source and it does not seem like its been added > either. > > I havent had a chance to compile this yet to confirm it, but if correct then > this is not compatible with OpenSSL and possibly other SSL libraries. My bad. It's a draft and, as you've found out, can be trivially fixed. https://github.com/openssl/openssl/blob/c3d734701cd57575856bf9b542446811518dd28c/ssl/ssl_ciph.c#L596-L615 https://boringssl.googlesource.com/boringssl/+/4d4bff89bb8ec345d289412f0f7f135c6e51b1a6%5E!/ -- Mark From ru at nginx.com Wed Jun 3 05:23:59 2015 From: ru at nginx.com (Ruslan Ermilov) Date: Wed, 03 Jun 2015 05:23:59 +0000 Subject: [nginx] Fixed misspellings of the word "dependencies". Message-ID: details: http://hg.nginx.org/nginx/rev/4e5dda15f18f branches: changeset: 6164:4e5dda15f18f user: Ruslan Ermilov date: Wed Jun 03 08:23:35 2015 +0300 description: Fixed misspellings of the word "dependencies". diffstat: auto/make | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diffs (39 lines): diff -r 4e71788460fa -r 4e5dda15f18f auto/make --- a/auto/make Mon Jun 01 21:08:56 2015 +0300 +++ b/auto/make Wed Jun 03 08:23:35 2015 +0300 @@ -50,7 +50,7 @@ END ngx_all_srcs="$CORE_SRCS" -# the core dependences and include paths +# the core dependencies and include paths ngx_deps=`echo $CORE_DEPS $NGX_AUTO_CONFIG_H $NGX_PCH \ | sed -e "s/ *\([^ ][^ ]*\)/$ngx_regex_cont\1/g" \ @@ -70,7 +70,7 @@ CORE_INCS = $ngx_include_opt$ngx_incs END -# the http dependences and include paths +# the http dependencies and include paths if [ $HTTP = YES ]; then @@ -96,7 +96,7 @@ END fi -# the mail dependences and include paths +# the mail dependencies and include paths if [ $MAIL = YES ]; then @@ -122,7 +122,7 @@ END fi -# the stream dependences and include paths +# the stream dependencies and include paths if [ $STREAM = YES ]; then From pluknet at nginx.com Wed Jun 3 18:08:55 2015 From: pluknet at nginx.com (Sergey Kandaurov) Date: Wed, 03 Jun 2015 18:08:55 +0000 Subject: [nginx] Event pipe: call ngx_handle_read_event() with a proper f... Message-ID: details: http://hg.nginx.org/nginx/rev/d811f22033ad branches: changeset: 6165:d811f22033ad user: Sergey Kandaurov date: Wed Jun 03 19:12:26 2015 +0300 description: Event pipe: call ngx_handle_read_event() with a proper flags type. The change was missed in f69d1aab6a0f. diffstat: src/event/ngx_event_pipe.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (13 lines): diff -r 4e5dda15f18f -r d811f22033ad src/event/ngx_event_pipe.c --- a/src/event/ngx_event_pipe.c Wed Jun 03 08:23:35 2015 +0300 +++ b/src/event/ngx_event_pipe.c Wed Jun 03 19:12:26 2015 +0300 @@ -22,8 +22,8 @@ static ngx_int_t ngx_event_pipe_drain_ch ngx_int_t ngx_event_pipe(ngx_event_pipe_t *p, ngx_int_t do_write) { - u_int flags; ngx_int_t rc; + ngx_uint_t flags; ngx_event_t *rev, *wev; for ( ;; ) { From agwa at andrewayer.name Thu Jun 4 23:06:38 2015 From: agwa at andrewayer.name (Andrew Ayer) Date: Thu, 4 Jun 2015 16:06:38 -0700 Subject: [PATCH] OCSP stapling: never return an expired OCSP response (ticket #425) Message-ID: <20150604160638.0212fb16ebd9cf53dc83cae0@andrewayer.name> # HG changeset patch # User Andrew Ayer # Date 1433458802 25200 # Node ID f231e66871bcac1aa6db81e6153f818b417f8338 # Parent d811f22033ad2eb5c70dc4bbdda31c949a127ddb OCSP stapling: never return an expired OCSP response (ticket #425) Previously, once an OCSP response was cached, it would be sent to clients until a new response replaced it, even if the response expired. This is bad, since Firefox displays an interstitial SSL error when it receives an expired stapled OCSP response, and Chrome is planning to do the same as well. With this change, nginx now caches the expiration time of the OCSP response, and re-checks it before sending the response to the client. If the response is expired, it's immediately cleared from the cache, which prevents it from being returned, and triggers an immediate update from the OCSP responder. diff -r d811f22033ad -r f231e66871bc src/event/ngx_event_openssl_stapling.c --- a/src/event/ngx_event_openssl_stapling.c Wed Jun 03 19:12:26 2015 +0300 +++ b/src/event/ngx_event_openssl_stapling.c Thu Jun 04 16:00:02 2015 -0700 @@ -18,6 +18,9 @@ ngx_str_t staple; ngx_msec_t timeout; + ASN1_GENERALIZEDTIME *thisupdate; + ASN1_GENERALIZEDTIME *nextupdate; + ngx_resolver_t *resolver; ngx_msec_t resolver_timeout; @@ -462,6 +465,27 @@ staple = data; rc = SSL_TLSEXT_ERR_NOACK; + if (staple->thisupdate && staple->nextupdate + && OCSP_check_validity(staple->thisupdate, + staple->nextupdate, 300, -1) != 1) + { + ngx_ssl_error(NGX_LOG_ERR, c->log, 0, "OCSP_check_validity() failed"); + /* + * free the cached response so that we immediately try to retrieve + * a new one instead of waiting until the cache expires + */ + if (staple->staple.data) { + ngx_free(staple->staple.data); + staple->staple.data = NULL; + } + staple->staple.len = 0; + staple->valid = 0; + ASN1_GENERALIZEDTIME_free(staple->thisupdate); + staple->thisupdate = NULL; + ASN1_GENERALIZEDTIME_free(staple->nextupdate); + staple->nextupdate = NULL; + } + if (staple->staple.len) { /* we have to copy ocsp response as OpenSSL will free it by itself */ @@ -629,6 +653,26 @@ goto error; } + if (staple->thisupdate) { + ASN1_GENERALIZEDTIME_free(staple->thisupdate); + } + staple->thisupdate = M_ASN1_GENERALIZEDTIME_dup(thisupdate); + if (staple->thisupdate == NULL) { + ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0, + "M_ASN1_GENERALIZEDTIME_dup() failed"); + goto error; + } + + if (staple->nextupdate) { + ASN1_GENERALIZEDTIME_free(staple->nextupdate); + } + staple->nextupdate = M_ASN1_GENERALIZEDTIME_dup(nextupdate); + if (staple->nextupdate == NULL) { + ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0, + "M_ASN1_GENERALIZEDTIME_dup() failed"); + goto error; + } + OCSP_CERTID_free(id); OCSP_BASICRESP_free(basic); OCSP_RESPONSE_free(ocsp); @@ -692,6 +736,13 @@ X509_free(staple->issuer); } + if (staple->thisupdate) { + ASN1_GENERALIZEDTIME_free(staple->thisupdate); + } + if (staple->nextupdate) { + ASN1_GENERALIZEDTIME_free(staple->nextupdate); + } + if (staple->staple.data) { ngx_free(staple->staple.data); } From mdounin at mdounin.ru Fri Jun 5 14:10:54 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 05 Jun 2015 14:10:54 +0000 Subject: [nginx] Style. Message-ID: details: http://hg.nginx.org/nginx/rev/ac52b46ebab5 branches: changeset: 6166:ac52b46ebab5 user: Maxim Dounin date: Fri Jun 05 17:10:34 2015 +0300 description: Style. diffstat: src/event/ngx_event.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diffs (14 lines): diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c --- a/src/event/ngx_event.c +++ b/src/event/ngx_event.c @@ -927,8 +927,9 @@ ngx_events_block(ngx_conf_t *cf, ngx_com *cf = pcf; - if (rv != NGX_CONF_OK) + if (rv != NGX_CONF_OK) { return rv; + } for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_EVENT_MODULE) { From arut at nginx.com Fri Jun 5 17:47:51 2015 From: arut at nginx.com (Roman Arutyunyan) Date: Fri, 05 Jun 2015 17:47:51 +0000 Subject: [nginx] Upstream keepalive: reduced diffs to the plus version of... Message-ID: details: http://hg.nginx.org/nginx/rev/87d48f8793b6 branches: changeset: 6167:87d48f8793b6 user: Roman Arutyunyan date: Thu Jun 04 23:46:44 2015 +0300 description: Upstream keepalive: reduced diffs to the plus version of nginx. diffstat: src/http/modules/ngx_http_upstream_keepalive_module.c | 81 +++++++++--------- 1 files changed, 42 insertions(+), 39 deletions(-) diffs (149 lines): diff -r ac52b46ebab5 -r 87d48f8793b6 src/http/modules/ngx_http_upstream_keepalive_module.c --- a/src/http/modules/ngx_http_upstream_keepalive_module.c Fri Jun 05 17:10:34 2015 +0300 +++ b/src/http/modules/ngx_http_upstream_keepalive_module.c Thu Jun 04 23:46:44 2015 +0300 @@ -25,6 +25,18 @@ typedef struct { typedef struct { ngx_http_upstream_keepalive_srv_conf_t *conf; + ngx_queue_t queue; + ngx_connection_t *connection; + + socklen_t socklen; + u_char sockaddr[NGX_SOCKADDRLEN]; + +} ngx_http_upstream_keepalive_cache_t; + + +typedef struct { + ngx_http_upstream_keepalive_srv_conf_t *conf; + ngx_http_upstream_t *upstream; void *data; @@ -40,18 +52,6 @@ typedef struct { } ngx_http_upstream_keepalive_peer_data_t; -typedef struct { - ngx_http_upstream_keepalive_srv_conf_t *conf; - - ngx_queue_t queue; - ngx_connection_t *connection; - - socklen_t socklen; - u_char sockaddr[NGX_SOCKADDRLEN]; - -} ngx_http_upstream_keepalive_cache_t; - - static ngx_int_t ngx_http_upstream_init_keepalive_peer(ngx_http_request_t *r, ngx_http_upstream_srv_conf_t *us); static ngx_int_t ngx_http_upstream_get_keepalive_peer(ngx_peer_connection_t *pc, @@ -63,7 +63,6 @@ static void ngx_http_upstream_keepalive_ static void ngx_http_upstream_keepalive_close_handler(ngx_event_t *ev); static void ngx_http_upstream_keepalive_close(ngx_connection_t *c); - #if (NGX_HTTP_SSL) static ngx_int_t ngx_http_upstream_keepalive_set_session( ngx_peer_connection_t *pc, void *data); @@ -244,24 +243,28 @@ ngx_http_upstream_get_keepalive_peer(ngx ngx_queue_remove(q); ngx_queue_insert_head(&kp->conf->free, q); - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, - "get keepalive peer: using connection %p", c); - - c->idle = 0; - c->sent = 0; - c->log = pc->log; - c->read->log = pc->log; - c->write->log = pc->log; - c->pool->log = pc->log; - - pc->connection = c; - pc->cached = 1; - - return NGX_DONE; + goto found; } } return NGX_OK; + +found: + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, + "get keepalive peer: using connection %p", c); + + c->idle = 0; + c->sent = 0; + c->log = pc->log; + c->read->log = pc->log; + c->write->log = pc->log; + c->pool->log = pc->log; + + pc->connection = c; + pc->cached = 1; + + return NGX_DONE; } @@ -322,8 +325,9 @@ ngx_http_upstream_free_keepalive_peer(ng item = ngx_queue_data(q, ngx_http_upstream_keepalive_cache_t, queue); } + ngx_queue_insert_head(&kp->conf->cache, q); + item->connection = c; - ngx_queue_insert_head(&kp->conf->cache, q); pc->connection = NULL; @@ -470,10 +474,9 @@ ngx_http_upstream_keepalive_create_conf( * * conf->original_init_upstream = NULL; * conf->original_init_peer = NULL; + * conf->max_cached = 0; */ - conf->max_cached = 1; - return conf; } @@ -487,18 +490,10 @@ ngx_http_upstream_keepalive(ngx_conf_t * ngx_int_t n; ngx_str_t *value; - uscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module); - - if (kcf->original_init_upstream) { + if (kcf->max_cached) { return "is duplicate"; } - kcf->original_init_upstream = uscf->peer.init_upstream - ? uscf->peer.init_upstream - : ngx_http_upstream_init_round_robin; - - uscf->peer.init_upstream = ngx_http_upstream_init_keepalive; - /* read options */ value = cf->args->elts; @@ -514,5 +509,13 @@ ngx_http_upstream_keepalive(ngx_conf_t * kcf->max_cached = n; + uscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module); + + kcf->original_init_upstream = uscf->peer.init_upstream + ? uscf->peer.init_upstream + : ngx_http_upstream_init_round_robin; + + uscf->peer.init_upstream = ngx_http_upstream_init_keepalive; + return NGX_CONF_OK; } From mdounin at mdounin.ru Fri Jun 5 19:29:20 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 05 Jun 2015 19:29:20 +0000 Subject: [nginx] Added the REQUEST_SCHEME parameter. Message-ID: details: http://hg.nginx.org/nginx/rev/62869a9b2e7d branches: changeset: 6168:62869a9b2e7d user: Maxim Dounin date: Fri Jun 05 22:23:26 2015 +0300 description: Added the REQUEST_SCHEME parameter. The REQUEST_SCHEME parameter was introduced in Apache 2.3.11 and seems to be used by some scripts now. It looks more logical than previously used HTTPS. diffstat: conf/fastcgi.conf | 1 + conf/fastcgi_params | 1 + conf/scgi_params | 1 + conf/uwsgi_params | 1 + 4 files changed, 4 insertions(+), 0 deletions(-) diffs (44 lines): diff --git a/conf/fastcgi.conf b/conf/fastcgi.conf --- a/conf/fastcgi.conf +++ b/conf/fastcgi.conf @@ -10,6 +10,7 @@ fastcgi_param REQUEST_URI $reque fastcgi_param DOCUMENT_URI $document_uri; fastcgi_param DOCUMENT_ROOT $document_root; fastcgi_param SERVER_PROTOCOL $server_protocol; +fastcgi_param REQUEST_SCHEME $scheme; fastcgi_param HTTPS $https if_not_empty; fastcgi_param GATEWAY_INTERFACE CGI/1.1; diff --git a/conf/fastcgi_params b/conf/fastcgi_params --- a/conf/fastcgi_params +++ b/conf/fastcgi_params @@ -9,6 +9,7 @@ fastcgi_param REQUEST_URI $reque fastcgi_param DOCUMENT_URI $document_uri; fastcgi_param DOCUMENT_ROOT $document_root; fastcgi_param SERVER_PROTOCOL $server_protocol; +fastcgi_param REQUEST_SCHEME $scheme; fastcgi_param HTTPS $https if_not_empty; fastcgi_param GATEWAY_INTERFACE CGI/1.1; diff --git a/conf/scgi_params b/conf/scgi_params --- a/conf/scgi_params +++ b/conf/scgi_params @@ -8,6 +8,7 @@ scgi_param DOCUMENT_URI $document scgi_param DOCUMENT_ROOT $document_root; scgi_param SCGI 1; scgi_param SERVER_PROTOCOL $server_protocol; +scgi_param REQUEST_SCHEME $scheme; scgi_param HTTPS $https if_not_empty; scgi_param REMOTE_ADDR $remote_addr; diff --git a/conf/uwsgi_params b/conf/uwsgi_params --- a/conf/uwsgi_params +++ b/conf/uwsgi_params @@ -8,6 +8,7 @@ uwsgi_param REQUEST_URI $request uwsgi_param PATH_INFO $document_uri; uwsgi_param DOCUMENT_ROOT $document_root; uwsgi_param SERVER_PROTOCOL $server_protocol; +uwsgi_param REQUEST_SCHEME $scheme; uwsgi_param HTTPS $https if_not_empty; uwsgi_param REMOTE_ADDR $remote_addr; From code at bluebot.org Sat Jun 6 03:18:52 2015 From: code at bluebot.org (Jon Nalley) Date: Fri, 05 Jun 2015 22:18:52 -0500 Subject: [PATCH] Adds $orig_remote_addr in realip module Message-ID: # HG changeset patch # User Jon Nalley # Date 1433560679 18000 # Fri Jun 05 22:17:59 2015 -0500 # Node ID b7c07ccca1f9be7038379cfd1077fb5885b3f388 # Parent 62869a9b2e7d1b2b698cb1ca67ad664b37171113 Adds $orig_remote_addr in realip module. When the realip module sets $remote_addr, the connecting IP is no longer available for logging etc. This change preserves the connecting IP as $orig_remote_addr. diff -r 62869a9b2e7d -r b7c07ccca1f9 src/http/modules/ngx_http_realip_module.c --- a/src/http/modules/ngx_http_realip_module.c Fri Jun 05 22:23:26 2015 +0300 +++ b/src/http/modules/ngx_http_realip_module.c Fri Jun 05 22:17:59 2015 -0500 @@ -33,6 +33,10 @@ } ngx_http_realip_ctx_t; +static ngx_int_t + ngx_http_realip_orig_remote_addr_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_realip_add_variables(ngx_conf_t *cf); static ngx_int_t ngx_http_realip_handler(ngx_http_request_t *r); static ngx_int_t ngx_http_realip_set_addr(ngx_http_request_t *r, ngx_addr_t *addr); @@ -75,7 +79,7 @@ static ngx_http_module_t ngx_http_realip_module_ctx = { - NULL, /* preconfiguration */ + ngx_http_realip_add_variables, /* preconfiguration */ ngx_http_realip_init, /* postconfiguration */ NULL, /* create main configuration */ @@ -105,6 +109,15 @@ }; +static ngx_http_variable_t ngx_http_realip_vars[] = { + + { ngx_string("orig_remote_addr"), NULL, + ngx_http_realip_orig_remote_addr_variable, 0, NGX_HTTP_VAR_NOHASH, 0 }, + + { ngx_null_string, NULL, NULL, 0, 0, 0 } +}; + + static ngx_int_t ngx_http_realip_handler(ngx_http_request_t *r) { @@ -369,6 +382,55 @@ } +static ngx_int_t +ngx_http_realip_orig_remote_addr_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_http_realip_ctx_t *ctx; + + ctx = ngx_http_get_module_ctx(r, ngx_http_realip_module); + + if (ctx == NULL) { + v->not_found = 1; + return NGX_OK; + } + + v->len = ctx->addr_text.len; + v->data = ngx_pnalloc(r->pool, v->len); + + if (v->data == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(v->data, ctx->addr_text.data, v->len); + + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_realip_add_variables(ngx_conf_t *cf) +{ + ngx_http_variable_t *var, *v; + + for (v = ngx_http_realip_vars; v->name.len; v++) { + var = ngx_http_add_variable(cf, &v->name, v->flags); + if (var == NULL) { + return NGX_ERROR; + } + + var->get_handler = v->get_handler; + var->data = v->data; + } + + return NGX_OK; +} + + static void * ngx_http_realip_create_loc_conf(ngx_conf_t *cf) { From ru at nginx.com Sat Jun 6 04:57:54 2015 From: ru at nginx.com (Ruslan Ermilov) Date: Sat, 06 Jun 2015 04:57:54 +0000 Subject: [nginx] Stream: fixed "reuseport" to actually work. Message-ID: details: http://hg.nginx.org/nginx/rev/f654addf0eea branches: changeset: 6169:f654addf0eea user: Ruslan Ermilov date: Fri Jun 05 23:03:13 2015 +0300 description: Stream: fixed "reuseport" to actually work. diffstat: src/stream/ngx_stream.c | 7 +++++++ src/stream/ngx_stream.h | 3 +++ 2 files changed, 10 insertions(+), 0 deletions(-) diffs (37 lines): diff -r 62869a9b2e7d -r f654addf0eea src/stream/ngx_stream.c --- a/src/stream/ngx_stream.c Fri Jun 05 22:23:26 2015 +0300 +++ b/src/stream/ngx_stream.c Fri Jun 05 23:03:13 2015 +0300 @@ -314,6 +314,9 @@ found: #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) addr->ipv6only = listen->ipv6only; #endif +#if (NGX_HAVE_REUSEPORT) + addr->reuseport = listen->reuseport; +#endif return NGX_OK; } @@ -386,6 +389,10 @@ ngx_stream_optimize_servers(ngx_conf_t * ls->ipv6only = addr[i].ipv6only; #endif +#if (NGX_HAVE_REUSEPORT) + ls->reuseport = addr[i].reuseport; +#endif + stport = ngx_palloc(cf->pool, sizeof(ngx_stream_port_t)); if (stport == NULL) { return NGX_CONF_ERROR; diff -r 62869a9b2e7d -r f654addf0eea src/stream/ngx_stream.h --- a/src/stream/ngx_stream.h Fri Jun 05 22:23:26 2015 +0300 +++ b/src/stream/ngx_stream.h Fri Jun 05 23:03:13 2015 +0300 @@ -109,6 +109,9 @@ typedef struct { #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) unsigned ipv6only:1; #endif +#if (NGX_HAVE_REUSEPORT) + unsigned reuseport:1; +#endif unsigned so_keepalive:2; #if (NGX_HAVE_KEEPALIVE_TUNABLE) int tcp_keepidle; From mdounin at mdounin.ru Sat Jun 6 12:47:59 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sat, 6 Jun 2015 15:47:59 +0300 Subject: [PATCH] Adds $orig_remote_addr in realip module In-Reply-To: References: Message-ID: <20150606124759.GZ26357@mdounin.ru> Hello! On Fri, Jun 05, 2015 at 10:18:52PM -0500, Jon Nalley wrote: > # HG changeset patch > # User Jon Nalley > # Date 1433560679 18000 > # Fri Jun 05 22:17:59 2015 -0500 > # Node ID b7c07ccca1f9be7038379cfd1077fb5885b3f388 > # Parent 62869a9b2e7d1b2b698cb1ca67ad664b37171113 > Adds $orig_remote_addr in realip module. > > When the realip module sets $remote_addr, the connecting IP is > no longer available for logging etc. This change preserves the > connecting IP as $orig_remote_addr. [...] > +static ngx_int_t > +ngx_http_realip_orig_remote_addr_variable(ngx_http_request_t *r, > + ngx_http_variable_value_t *v, uintptr_t data) > +{ > + ngx_http_realip_ctx_t *ctx; > + > + ctx = ngx_http_get_module_ctx(r, ngx_http_realip_module); Ruslan already explained that this approach is wrong and won't work. http://mailman.nginx.org/pipermail/nginx-devel/2015-May/006965.html -- Maxim Dounin http://nginx.org/ From code at bluebot.org Sat Jun 6 13:46:07 2015 From: code at bluebot.org (Jon Nalley) Date: Sat, 6 Jun 2015 08:46:07 -0500 Subject: [PATCH] Adds $orig_remote_addr in realip module In-Reply-To: <20150606124759.GZ26357@mdounin.ru> References: <20150606124759.GZ26357@mdounin.ru> Message-ID: Hi, I saw Ruslan's comments and responded (hoping to get a better understanding of the problem). http://mailman.nginx.org/pipermail/nginx-devel/2015-May/006974.html I had assumed that the issue with my prior patch was assigning the pointer from the context rather than copying the data. From mdounin at mdounin.ru Mon Jun 8 00:32:13 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 8 Jun 2015 03:32:13 +0300 Subject: [PATCH] Adds $orig_remote_addr in realip module In-Reply-To: References: <20150606124759.GZ26357@mdounin.ru> Message-ID: <20150608003212.GA26357@mdounin.ru> Hello! On Sat, Jun 06, 2015 at 08:46:07AM -0500, Jon Nalley wrote: > Hi, > > I saw Ruslan's comments and responded (hoping to get a better > understanding of the problem). > > http://mailman.nginx.org/pipermail/nginx-devel/2015-May/006974.html > > I had assumed that the issue with my prior patch was assigning the > pointer from the context rather than copying the data. Your assumption was wrong. The problem is simple: you can't use contexts as long as stored data must survive internal redirects. Try logging your variable and check how it works for requests to index files, in a configuration like this: log_format test "remote_addr:$remote_addr orig:$orig_remote_addr"; access_log /dev/stderr test; set_real_ip_from 127.0.0.1/32; location / { index index.html; # assuming index.html exists } You'll see it won't work with requests to "/", since an internal redirect to "/index.html" happens and clears module contexts. -- Maxim Dounin http://nginx.org/ From code at bluebot.org Mon Jun 8 16:41:40 2015 From: code at bluebot.org (Jon Nalley) Date: Mon, 8 Jun 2015 11:41:40 -0500 Subject: [PATCH] Adds $orig_remote_addr in realip module In-Reply-To: <20150608003212.GA26357@mdounin.ru> References: <20150606124759.GZ26357@mdounin.ru> <20150608003212.GA26357@mdounin.ru> Message-ID: Hi, On Sun, Jun 7, 2015 at 7:32 PM, Maxim Dounin wrote: > Your assumption was wrong. The problem is simple: you can't use > contexts as long as stored data must survive internal > redirects. > > Try logging your variable and check how it works for requests to > index files Thanks for the explanation and the test case! I will look for an alternative solution. From serg.brester at sebres.de Mon Jun 8 19:56:16 2015 From: serg.brester at sebres.de (Sergey Brester) Date: Mon, 08 Jun 2015 21:56:16 +0200 Subject: Fwd: Windows shmem fix: makes shared memory fully ASLR and DEP compliant (ea. cache zone, limit zone, etc.) In-Reply-To: <20150422162929.GD32429@mdounin.ru> References: <706ca3a5ec658ea41fb9975f90ab9ab4@sebres.de> <20150422162929.GD32429@mdounin.ru> Message-ID: Hi, Back to my wish to fix a problem with multiple workers under windows... Since we successful implemented shared memory on windows, it may be used for proper sharing a socket descriptor for multiple workers. Possible scenario can be found in this MSDN-article: https://msdn.microsoft.com/en-en/library/windows/desktop/ms741565%28v=vs.85%29.aspx I need some help, to make the changes more nginx conform: I have not yet decided which process will create/share a socket (duplicate handle and set it to shared memory). The idea was to create from master in ngx_event_process_init an initial shared memory with empty socket descriptors. The first worker inside ngx_open_listening_sockets may create a socket and duplicate a handle to share it with all other workers (save it to shared memory). The first problem would be the way windows does it - the (source) process should know each target process handle to duplicate a socket handle for it. So if a new worker will be created, it should "receive" a new shared handle, duplicated specially for him. So if not possible to do that somehow, only master process can create a socket and duplicate handle for each worker, before create him. But this will make the whole solution more complicated as now. Another way is, to create child with CreateProcess and bInheritHandles=1, and then save the first created socket handle in shared memory, but the problem would be - all handles created from childs will be shared also (files, channels, etc.), so if some handle will be not proper closed before end of some process - it will be a leak, as long as all processes including master are not terminated. Any ideas are welcome. Regards, sebres. 22.04.2015 18:29, Maxim Dounin: >> BTW(1): I have interest to fix a problem with multiple workers under >> windows (ex.: >> http://forum.nginx.org/read.php?2,188714,188714#msg-188714 [1] [1]). >> @Maxim Dounin: can you possibly give me more information, what you >> mean here, resp. what it currently depends on (see >> http://forum.nginx.org/read.php?2,188714,212568#msg-212568 [2] [2]). > > The most obvious problem with multiple workers on Windows is > listening sockets. As of now, if you start multiple workers on > windows, nginx will open multiple listening sockets - one in each > worker process. These are independant sockets, each opened with > SO_REUSEADDR, and only one of these sockets will be able to accept > connections. > > Possible solution to the problem would be to pass listening sockets > from a master process to worker processes via handle inheritance > as available in Windows: > > http://msdn.microsoft.com/en-us/library/windows/desktop/ms683463(v=vs.85).aspx > [3] > Links: ------ [1] http://forum.nginx.org/read.php?2,188714,188714#msg-188714 [2] http://forum.nginx.org/read.php?2,188714,212568#msg-212568 [3] http://msdn.microsoft.com/en-us/library/windows/desktop/ms683463(v=vs.85).aspx From ru at nginx.com Mon Jun 8 20:30:02 2015 From: ru at nginx.com (Ruslan Ermilov) Date: Mon, 08 Jun 2015 20:30:02 +0000 Subject: [nginx] Stream: embed ngx_stream_listen_t into ngx_stream_conf_a... Message-ID: details: http://hg.nginx.org/nginx/rev/c13091e6292c branches: changeset: 6170:c13091e6292c user: Ruslan Ermilov date: Mon Jun 08 23:11:42 2015 +0300 description: Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t. diffstat: src/stream/ngx_stream.c | 74 ++++++++++++++----------------------- src/stream/ngx_stream.h | 36 ++++++----------- src/stream/ngx_stream_core_module.c | 14 ++++--- 3 files changed, 49 insertions(+), 75 deletions(-) diffs (292 lines): diff -r f654addf0eea -r c13091e6292c src/stream/ngx_stream.c --- a/src/stream/ngx_stream.c Fri Jun 05 23:03:13 2015 +0300 +++ b/src/stream/ngx_stream.c Mon Jun 08 23:11:42 2015 +0300 @@ -239,13 +239,13 @@ ngx_stream_add_ports(ngx_conf_t *cf, ngx struct sockaddr_in6 *sin6; #endif - sa = (struct sockaddr *) &listen->sockaddr; + sa = &listen->u.sockaddr; switch (sa->sa_family) { #if (NGX_HAVE_INET6) case AF_INET6: - sin6 = (struct sockaddr_in6 *) sa; + sin6 = &listen->u.sockaddr_in6; p = sin6->sin6_port; break; #endif @@ -257,7 +257,7 @@ ngx_stream_add_ports(ngx_conf_t *cf, ngx #endif default: /* AF_INET */ - sin = (struct sockaddr_in *) sa; + sin = &listen->u.sockaddr_in; p = sin->sin_port; break; } @@ -297,26 +297,7 @@ found: return NGX_ERROR; } - addr->sockaddr = (struct sockaddr *) &listen->sockaddr; - addr->socklen = listen->socklen; - addr->ctx = listen->ctx; - addr->bind = listen->bind; - addr->wildcard = listen->wildcard; - addr->so_keepalive = listen->so_keepalive; -#if (NGX_HAVE_KEEPALIVE_TUNABLE) - addr->tcp_keepidle = listen->tcp_keepidle; - addr->tcp_keepintvl = listen->tcp_keepintvl; - addr->tcp_keepcnt = listen->tcp_keepcnt; -#endif -#if (NGX_STREAM_SSL) - addr->ssl = listen->ssl; -#endif -#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) - addr->ipv6only = listen->ipv6only; -#endif -#if (NGX_HAVE_REUSEPORT) - addr->reuseport = listen->reuseport; -#endif + addr->opt = *listen; return NGX_OK; } @@ -346,8 +327,8 @@ ngx_stream_optimize_servers(ngx_conf_t * * to the "*:port" only and ignore the other bindings */ - if (addr[last - 1].wildcard) { - addr[last - 1].bind = 1; + if (addr[last - 1].opt.wildcard) { + addr[last - 1].opt.bind = 1; bind_wildcard = 1; } else { @@ -358,12 +339,13 @@ ngx_stream_optimize_servers(ngx_conf_t * while (i < last) { - if (bind_wildcard && !addr[i].bind) { + if (bind_wildcard && !addr[i].opt.bind) { i++; continue; } - ls = ngx_create_listening(cf, addr[i].sockaddr, addr[i].socklen); + ls = ngx_create_listening(cf, &addr[i].opt.u.sockaddr, + addr[i].opt.socklen); if (ls == NULL) { return NGX_CONF_ERROR; } @@ -372,25 +354,25 @@ ngx_stream_optimize_servers(ngx_conf_t * ls->handler = ngx_stream_init_connection; ls->pool_size = 256; - cscf = addr->ctx->srv_conf[ngx_stream_core_module.ctx_index]; + cscf = addr->opt.ctx->srv_conf[ngx_stream_core_module.ctx_index]; ls->logp = cscf->error_log; ls->log.data = &ls->addr_text; ls->log.handler = ngx_accept_log_error; - ls->keepalive = addr[i].so_keepalive; + ls->keepalive = addr[i].opt.so_keepalive; #if (NGX_HAVE_KEEPALIVE_TUNABLE) - ls->keepidle = addr[i].tcp_keepidle; - ls->keepintvl = addr[i].tcp_keepintvl; - ls->keepcnt = addr[i].tcp_keepcnt; + ls->keepidle = addr[i].opt.tcp_keepidle; + ls->keepintvl = addr[i].opt.tcp_keepintvl; + ls->keepcnt = addr[i].opt.tcp_keepcnt; #endif #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) - ls->ipv6only = addr[i].ipv6only; + ls->ipv6only = addr[i].opt.ipv6only; #endif #if (NGX_HAVE_REUSEPORT) - ls->reuseport = addr[i].reuseport; + ls->reuseport = addr[i].opt.reuseport; #endif stport = ngx_palloc(cf->pool, sizeof(ngx_stream_port_t)); @@ -451,15 +433,15 @@ ngx_stream_add_addrs(ngx_conf_t *cf, ngx for (i = 0; i < stport->naddrs; i++) { - sin = (struct sockaddr_in *) addr[i].sockaddr; + sin = &addr[i].opt.u.sockaddr_in; addrs[i].addr = sin->sin_addr.s_addr; - addrs[i].conf.ctx = addr[i].ctx; + addrs[i].conf.ctx = addr[i].opt.ctx; #if (NGX_STREAM_SSL) - addrs[i].conf.ssl = addr[i].ssl; + addrs[i].conf.ssl = addr[i].opt.ssl; #endif - len = ngx_sock_ntop(addr[i].sockaddr, addr[i].socklen, buf, + len = ngx_sock_ntop(&addr[i].opt.u.sockaddr, addr[i].opt.socklen, buf, NGX_SOCKADDR_STRLEN, 1); p = ngx_pnalloc(cf->pool, len); @@ -500,15 +482,15 @@ ngx_stream_add_addrs6(ngx_conf_t *cf, ng for (i = 0; i < stport->naddrs; i++) { - sin6 = (struct sockaddr_in6 *) addr[i].sockaddr; + sin6 = &addr[i].opt.u.sockaddr_in6; addrs6[i].addr6 = sin6->sin6_addr; - addrs6[i].conf.ctx = addr[i].ctx; + addrs6[i].conf.ctx = addr[i].opt.ctx; #if (NGX_STREAM_SSL) - addrs6[i].conf.ssl = addr[i].ssl; + addrs6[i].conf.ssl = addr[i].opt.ssl; #endif - len = ngx_sock_ntop(addr[i].sockaddr, addr[i].socklen, buf, + len = ngx_sock_ntop(&addr[i].opt.u.sockaddr, addr[i].opt.socklen, buf, NGX_SOCKADDR_STRLEN, 1); p = ngx_pnalloc(cf->pool, len); @@ -536,22 +518,22 @@ ngx_stream_cmp_conf_addrs(const void *on first = (ngx_stream_conf_addr_t *) one; second = (ngx_stream_conf_addr_t *) two; - if (first->wildcard) { + if (first->opt.wildcard) { /* a wildcard must be the last resort, shift it to the end */ return 1; } - if (second->wildcard) { + if (second->opt.wildcard) { /* a wildcard must be the last resort, shift it to the end */ return -1; } - if (first->bind && !second->bind) { + if (first->opt.bind && !second->opt.bind) { /* shift explicit bind()ed addresses to the start */ return -1; } - if (!first->bind && second->bind) { + if (!first->opt.bind && second->opt.bind) { /* shift explicit bind()ed addresses to the start */ return 1; } diff -r f654addf0eea -r c13091e6292c src/stream/ngx_stream.h --- a/src/stream/ngx_stream.h Fri Jun 05 23:03:13 2015 +0300 +++ b/src/stream/ngx_stream.h Mon Jun 08 23:11:42 2015 +0300 @@ -31,7 +31,18 @@ typedef struct { typedef struct { - u_char sockaddr[NGX_SOCKADDRLEN]; + union { + struct sockaddr sockaddr; + struct sockaddr_in sockaddr_in; +#if (NGX_HAVE_INET6) + struct sockaddr_in6 sockaddr_in6; +#endif +#if (NGX_HAVE_UNIX_DOMAIN) + struct sockaddr_un sockaddr_un; +#endif + u_char sockaddr_data[NGX_SOCKADDRLEN]; + } u; + socklen_t socklen; /* server ctx */ @@ -96,28 +107,7 @@ typedef struct { typedef struct { - struct sockaddr *sockaddr; - socklen_t socklen; - - ngx_stream_conf_ctx_t *ctx; - - unsigned bind:1; - unsigned wildcard:1; -#if (NGX_STREAM_SSL) - unsigned ssl:1; -#endif -#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) - unsigned ipv6only:1; -#endif -#if (NGX_HAVE_REUSEPORT) - unsigned reuseport:1; -#endif - unsigned so_keepalive:2; -#if (NGX_HAVE_KEEPALIVE_TUNABLE) - int tcp_keepidle; - int tcp_keepintvl; - int tcp_keepcnt; -#endif + ngx_stream_listen_t opt; } ngx_stream_conf_addr_t; diff -r f654addf0eea -r c13091e6292c src/stream/ngx_stream_core_module.c --- a/src/stream/ngx_stream_core_module.c Fri Jun 05 23:03:13 2015 +0300 +++ b/src/stream/ngx_stream_core_module.c Mon Jun 08 23:11:42 2015 +0300 @@ -272,7 +272,7 @@ ngx_stream_core_listen(ngx_conf_t *cf, n for (i = 0; i < cmcf->listen.nelts; i++) { - sa = (struct sockaddr *) ls[i].sockaddr; + sa = &ls[i].u.sockaddr; if (sa->sa_family != u.family) { continue; @@ -284,7 +284,7 @@ ngx_stream_core_listen(ngx_conf_t *cf, n case AF_INET6: off = offsetof(struct sockaddr_in6, sin6_addr); len = 16; - sin6 = (struct sockaddr_in6 *) sa; + sin6 = &ls[i].u.sockaddr_in6; port = sin6->sin6_port; break; #endif @@ -300,12 +300,14 @@ ngx_stream_core_listen(ngx_conf_t *cf, n default: /* AF_INET */ off = offsetof(struct sockaddr_in, sin_addr); len = 4; - sin = (struct sockaddr_in *) sa; + sin = &ls[i].u.sockaddr_in; port = sin->sin_port; break; } - if (ngx_memcmp(ls[i].sockaddr + off, u.sockaddr + off, len) != 0) { + if (ngx_memcmp(ls[i].u.sockaddr_data + off, u.sockaddr + off, len) + != 0) + { continue; } @@ -325,7 +327,7 @@ ngx_stream_core_listen(ngx_conf_t *cf, n ngx_memzero(ls, sizeof(ngx_stream_listen_t)); - ngx_memcpy(ls->sockaddr, u.sockaddr, u.socklen); + ngx_memcpy(&ls->u.sockaddr, u.sockaddr, u.socklen); ls->socklen = u.socklen; ls->wildcard = u.wildcard; @@ -347,7 +349,7 @@ ngx_stream_core_listen(ngx_conf_t *cf, n struct sockaddr *sa; u_char buf[NGX_SOCKADDR_STRLEN]; - sa = (struct sockaddr *) ls->sockaddr; + sa = &ls->u.sockaddr; if (sa->sa_family == AF_INET6) { From ru at nginx.com Mon Jun 8 20:30:04 2015 From: ru at nginx.com (Ruslan Ermilov) Date: Mon, 08 Jun 2015 20:30:04 +0000 Subject: [nginx] Mail: embed ngx_mail_listen_t into ngx_mail_conf_addr_t. Message-ID: details: http://hg.nginx.org/nginx/rev/f61049c80458 branches: changeset: 6171:f61049c80458 user: Ruslan Ermilov date: Mon Jun 08 23:11:58 2015 +0300 description: Mail: embed ngx_mail_listen_t into ngx_mail_conf_addr_t. diffstat: src/mail/ngx_mail.c | 69 ++++++++++++++++------------------------ src/mail/ngx_mail.h | 33 +++++++----------- src/mail/ngx_mail_core_module.c | 14 ++++--- 3 files changed, 48 insertions(+), 68 deletions(-) diffs (281 lines): diff -r c13091e6292c -r f61049c80458 src/mail/ngx_mail.c --- a/src/mail/ngx_mail.c Mon Jun 08 23:11:42 2015 +0300 +++ b/src/mail/ngx_mail.c Mon Jun 08 23:11:58 2015 +0300 @@ -238,13 +238,13 @@ ngx_mail_add_ports(ngx_conf_t *cf, ngx_a struct sockaddr_in6 *sin6; #endif - sa = (struct sockaddr *) &listen->sockaddr; + sa = &listen->u.sockaddr; switch (sa->sa_family) { #if (NGX_HAVE_INET6) case AF_INET6: - sin6 = (struct sockaddr_in6 *) sa; + sin6 = &listen->u.sockaddr_in6; p = sin6->sin6_port; break; #endif @@ -256,7 +256,7 @@ ngx_mail_add_ports(ngx_conf_t *cf, ngx_a #endif default: /* AF_INET */ - sin = (struct sockaddr_in *) sa; + sin = &listen->u.sockaddr_in; p = sin->sin_port; break; } @@ -296,23 +296,7 @@ found: return NGX_ERROR; } - addr->sockaddr = (struct sockaddr *) &listen->sockaddr; - addr->socklen = listen->socklen; - addr->ctx = listen->ctx; - addr->bind = listen->bind; - addr->wildcard = listen->wildcard; - addr->so_keepalive = listen->so_keepalive; -#if (NGX_HAVE_KEEPALIVE_TUNABLE) - addr->tcp_keepidle = listen->tcp_keepidle; - addr->tcp_keepintvl = listen->tcp_keepintvl; - addr->tcp_keepcnt = listen->tcp_keepcnt; -#endif -#if (NGX_MAIL_SSL) - addr->ssl = listen->ssl; -#endif -#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) - addr->ipv6only = listen->ipv6only; -#endif + addr->opt = *listen; return NGX_OK; } @@ -342,8 +326,8 @@ ngx_mail_optimize_servers(ngx_conf_t *cf * to the "*:port" only and ignore the other bindings */ - if (addr[last - 1].wildcard) { - addr[last - 1].bind = 1; + if (addr[last - 1].opt.wildcard) { + addr[last - 1].opt.bind = 1; bind_wildcard = 1; } else { @@ -354,12 +338,13 @@ ngx_mail_optimize_servers(ngx_conf_t *cf while (i < last) { - if (bind_wildcard && !addr[i].bind) { + if (bind_wildcard && !addr[i].opt.bind) { i++; continue; } - ls = ngx_create_listening(cf, addr[i].sockaddr, addr[i].socklen); + ls = ngx_create_listening(cf, &addr[i].opt.u.sockaddr, + addr[i].opt.socklen); if (ls == NULL) { return NGX_CONF_ERROR; } @@ -368,21 +353,21 @@ ngx_mail_optimize_servers(ngx_conf_t *cf ls->handler = ngx_mail_init_connection; ls->pool_size = 256; - cscf = addr->ctx->srv_conf[ngx_mail_core_module.ctx_index]; + cscf = addr->opt.ctx->srv_conf[ngx_mail_core_module.ctx_index]; ls->logp = cscf->error_log; ls->log.data = &ls->addr_text; ls->log.handler = ngx_accept_log_error; - ls->keepalive = addr[i].so_keepalive; + ls->keepalive = addr[i].opt.so_keepalive; #if (NGX_HAVE_KEEPALIVE_TUNABLE) - ls->keepidle = addr[i].tcp_keepidle; - ls->keepintvl = addr[i].tcp_keepintvl; - ls->keepcnt = addr[i].tcp_keepcnt; + ls->keepidle = addr[i].opt.tcp_keepidle; + ls->keepintvl = addr[i].opt.tcp_keepintvl; + ls->keepcnt = addr[i].opt.tcp_keepcnt; #endif #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) - ls->ipv6only = addr[i].ipv6only; + ls->ipv6only = addr[i].opt.ipv6only; #endif mport = ngx_palloc(cf->pool, sizeof(ngx_mail_port_t)); @@ -439,15 +424,15 @@ ngx_mail_add_addrs(ngx_conf_t *cf, ngx_m for (i = 0; i < mport->naddrs; i++) { - sin = (struct sockaddr_in *) addr[i].sockaddr; + sin = &addr[i].opt.u.sockaddr_in; addrs[i].addr = sin->sin_addr.s_addr; - addrs[i].conf.ctx = addr[i].ctx; + addrs[i].conf.ctx = addr[i].opt.ctx; #if (NGX_MAIL_SSL) - addrs[i].conf.ssl = addr[i].ssl; + addrs[i].conf.ssl = addr[i].opt.ssl; #endif - len = ngx_sock_ntop(addr[i].sockaddr, addr[i].socklen, buf, + len = ngx_sock_ntop(&addr[i].opt.u.sockaddr, addr[i].opt.socklen, buf, NGX_SOCKADDR_STRLEN, 1); p = ngx_pnalloc(cf->pool, len); @@ -488,15 +473,15 @@ ngx_mail_add_addrs6(ngx_conf_t *cf, ngx_ for (i = 0; i < mport->naddrs; i++) { - sin6 = (struct sockaddr_in6 *) addr[i].sockaddr; + sin6 = &addr[i].opt.u.sockaddr_in6; addrs6[i].addr6 = sin6->sin6_addr; - addrs6[i].conf.ctx = addr[i].ctx; + addrs6[i].conf.ctx = addr[i].opt.ctx; #if (NGX_MAIL_SSL) - addrs6[i].conf.ssl = addr[i].ssl; + addrs6[i].conf.ssl = addr[i].opt.ssl; #endif - len = ngx_sock_ntop(addr[i].sockaddr, addr[i].socklen, buf, + len = ngx_sock_ntop(&addr[i].opt.u.sockaddr, addr[i].opt.socklen, buf, NGX_SOCKADDR_STRLEN, 1); p = ngx_pnalloc(cf->pool, len); @@ -524,22 +509,22 @@ ngx_mail_cmp_conf_addrs(const void *one, first = (ngx_mail_conf_addr_t *) one; second = (ngx_mail_conf_addr_t *) two; - if (first->wildcard) { + if (first->opt.wildcard) { /* a wildcard must be the last resort, shift it to the end */ return 1; } - if (second->wildcard) { + if (second->opt.wildcard) { /* a wildcard must be the last resort, shift it to the end */ return -1; } - if (first->bind && !second->bind) { + if (first->opt.bind && !second->opt.bind) { /* shift explicit bind()ed addresses to the start */ return -1; } - if (!first->bind && second->bind) { + if (!first->opt.bind && second->opt.bind) { /* shift explicit bind()ed addresses to the start */ return 1; } diff -r c13091e6292c -r f61049c80458 src/mail/ngx_mail.h --- a/src/mail/ngx_mail.h Mon Jun 08 23:11:42 2015 +0300 +++ b/src/mail/ngx_mail.h Mon Jun 08 23:11:58 2015 +0300 @@ -27,7 +27,18 @@ typedef struct { typedef struct { - u_char sockaddr[NGX_SOCKADDRLEN]; + union { + struct sockaddr sockaddr; + struct sockaddr_in sockaddr_in; +#if (NGX_HAVE_INET6) + struct sockaddr_in6 sockaddr_in6; +#endif +#if (NGX_HAVE_UNIX_DOMAIN) + struct sockaddr_un sockaddr_un; +#endif + u_char sockaddr_data[NGX_SOCKADDRLEN]; + } u; + socklen_t socklen; /* server ctx */ @@ -89,25 +100,7 @@ typedef struct { typedef struct { - struct sockaddr *sockaddr; - socklen_t socklen; - - ngx_mail_conf_ctx_t *ctx; - - unsigned bind:1; - unsigned wildcard:1; -#if (NGX_MAIL_SSL) - unsigned ssl:1; -#endif -#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) - unsigned ipv6only:1; -#endif - unsigned so_keepalive:2; -#if (NGX_HAVE_KEEPALIVE_TUNABLE) - int tcp_keepidle; - int tcp_keepintvl; - int tcp_keepcnt; -#endif + ngx_mail_listen_t opt; } ngx_mail_conf_addr_t; diff -r c13091e6292c -r f61049c80458 src/mail/ngx_mail_core_module.c --- a/src/mail/ngx_mail_core_module.c Mon Jun 08 23:11:42 2015 +0300 +++ b/src/mail/ngx_mail_core_module.c Mon Jun 08 23:11:58 2015 +0300 @@ -325,7 +325,7 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx for (i = 0; i < cmcf->listen.nelts; i++) { - sa = (struct sockaddr *) ls[i].sockaddr; + sa = &ls[i].u.sockaddr; if (sa->sa_family != u.family) { continue; @@ -337,7 +337,7 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx case AF_INET6: off = offsetof(struct sockaddr_in6, sin6_addr); len = 16; - sin6 = (struct sockaddr_in6 *) sa; + sin6 = &ls[i].u.sockaddr_in6; port = ntohs(sin6->sin6_port); break; #endif @@ -353,12 +353,14 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx default: /* AF_INET */ off = offsetof(struct sockaddr_in, sin_addr); len = 4; - sin = (struct sockaddr_in *) sa; + sin = &ls[i].u.sockaddr_in; port = ntohs(sin->sin_port); break; } - if (ngx_memcmp(ls[i].sockaddr + off, u.sockaddr + off, len) != 0) { + if (ngx_memcmp(ls[i].u.sockaddr_data + off, u.sockaddr + off, len) + != 0) + { continue; } @@ -378,7 +380,7 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx ngx_memzero(ls, sizeof(ngx_mail_listen_t)); - ngx_memcpy(ls->sockaddr, u.sockaddr, u.socklen); + ngx_memcpy(&ls->u.sockaddr, u.sockaddr, u.socklen); ls->socklen = u.socklen; ls->wildcard = u.wildcard; @@ -421,7 +423,7 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx struct sockaddr *sa; u_char buf[NGX_SOCKADDR_STRLEN]; - sa = (struct sockaddr *) ls->sockaddr; + sa = &ls->u.sockaddr; if (sa->sa_family == AF_INET6) { From ru at nginx.com Mon Jun 8 20:30:07 2015 From: ru at nginx.com (Ruslan Ermilov) Date: Mon, 08 Jun 2015 20:30:07 +0000 Subject: [nginx] Stream: listen backlog=. Message-ID: details: http://hg.nginx.org/nginx/rev/3e8cddcff381 branches: changeset: 6172:3e8cddcff381 user: Ruslan Ermilov date: Mon Jun 08 23:13:33 2015 +0300 description: Stream: listen backlog=. diffstat: src/stream/ngx_stream.c | 2 ++ src/stream/ngx_stream.h | 1 + src/stream/ngx_stream_core_module.c | 14 ++++++++++++++ 3 files changed, 17 insertions(+), 0 deletions(-) diffs (54 lines): diff -r f61049c80458 -r 3e8cddcff381 src/stream/ngx_stream.c --- a/src/stream/ngx_stream.c Mon Jun 08 23:11:58 2015 +0300 +++ b/src/stream/ngx_stream.c Mon Jun 08 23:13:33 2015 +0300 @@ -360,6 +360,8 @@ ngx_stream_optimize_servers(ngx_conf_t * ls->log.data = &ls->addr_text; ls->log.handler = ngx_accept_log_error; + ls->backlog = addr[i].opt.backlog; + ls->keepalive = addr[i].opt.so_keepalive; #if (NGX_HAVE_KEEPALIVE_TUNABLE) ls->keepidle = addr[i].opt.tcp_keepidle; diff -r f61049c80458 -r 3e8cddcff381 src/stream/ngx_stream.h --- a/src/stream/ngx_stream.h Mon Jun 08 23:11:58 2015 +0300 +++ b/src/stream/ngx_stream.h Mon Jun 08 23:13:33 2015 +0300 @@ -65,6 +65,7 @@ typedef struct { int tcp_keepintvl; int tcp_keepcnt; #endif + int backlog; } ngx_stream_listen_t; diff -r f61049c80458 -r 3e8cddcff381 src/stream/ngx_stream_core_module.c --- a/src/stream/ngx_stream_core_module.c Mon Jun 08 23:11:58 2015 +0300 +++ b/src/stream/ngx_stream_core_module.c Mon Jun 08 23:13:33 2015 +0300 @@ -330,6 +330,7 @@ ngx_stream_core_listen(ngx_conf_t *cf, n ngx_memcpy(&ls->u.sockaddr, u.sockaddr, u.socklen); ls->socklen = u.socklen; + ls->backlog = NGX_LISTEN_BACKLOG; ls->wildcard = u.wildcard; ls->ctx = cf->ctx; @@ -344,6 +345,19 @@ ngx_stream_core_listen(ngx_conf_t *cf, n continue; } + if (ngx_strncmp(value[i].data, "backlog=", 8) == 0) { + ls->backlog = ngx_atoi(value[i].data + 8, value[i].len - 8); + ls->bind = 1; + + if (ls->backlog == NGX_ERROR || ls->backlog == 0) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid backlog \"%V\"", &value[i]); + return NGX_CONF_ERROR; + } + + continue; + } + if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) { #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) struct sockaddr *sa; From ru at nginx.com Mon Jun 8 20:30:09 2015 From: ru at nginx.com (Ruslan Ermilov) Date: Mon, 08 Jun 2015 20:30:09 +0000 Subject: [nginx] Mail: listen backlog=. Message-ID: details: http://hg.nginx.org/nginx/rev/1729d8d3eb3a branches: changeset: 6173:1729d8d3eb3a user: Ruslan Ermilov date: Mon Jun 08 23:13:56 2015 +0300 description: Mail: listen backlog=. diffstat: src/mail/ngx_mail.c | 2 ++ src/mail/ngx_mail.h | 1 + src/mail/ngx_mail_core_module.c | 14 ++++++++++++++ 3 files changed, 17 insertions(+), 0 deletions(-) diffs (54 lines): diff -r 3e8cddcff381 -r 1729d8d3eb3a src/mail/ngx_mail.c --- a/src/mail/ngx_mail.c Mon Jun 08 23:13:33 2015 +0300 +++ b/src/mail/ngx_mail.c Mon Jun 08 23:13:56 2015 +0300 @@ -359,6 +359,8 @@ ngx_mail_optimize_servers(ngx_conf_t *cf ls->log.data = &ls->addr_text; ls->log.handler = ngx_accept_log_error; + ls->backlog = addr[i].opt.backlog; + ls->keepalive = addr[i].opt.so_keepalive; #if (NGX_HAVE_KEEPALIVE_TUNABLE) ls->keepidle = addr[i].opt.tcp_keepidle; diff -r 3e8cddcff381 -r 1729d8d3eb3a src/mail/ngx_mail.h --- a/src/mail/ngx_mail.h Mon Jun 08 23:13:33 2015 +0300 +++ b/src/mail/ngx_mail.h Mon Jun 08 23:13:56 2015 +0300 @@ -58,6 +58,7 @@ typedef struct { int tcp_keepintvl; int tcp_keepcnt; #endif + int backlog; } ngx_mail_listen_t; diff -r 3e8cddcff381 -r 1729d8d3eb3a src/mail/ngx_mail_core_module.c --- a/src/mail/ngx_mail_core_module.c Mon Jun 08 23:13:33 2015 +0300 +++ b/src/mail/ngx_mail_core_module.c Mon Jun 08 23:13:56 2015 +0300 @@ -383,6 +383,7 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx ngx_memcpy(&ls->u.sockaddr, u.sockaddr, u.socklen); ls->socklen = u.socklen; + ls->backlog = NGX_LISTEN_BACKLOG; ls->wildcard = u.wildcard; ls->ctx = cf->ctx; @@ -418,6 +419,19 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx continue; } + if (ngx_strncmp(value[i].data, "backlog=", 8) == 0) { + ls->backlog = ngx_atoi(value[i].data + 8, value[i].len - 8); + ls->bind = 1; + + if (ls->backlog == NGX_ERROR || ls->backlog == 0) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid backlog \"%V\"", &value[i]); + return NGX_CONF_ERROR; + } + + continue; + } + if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) { #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) struct sockaddr *sa; From mdounin at mdounin.ru Mon Jun 8 20:35:29 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 8 Jun 2015 23:35:29 +0300 Subject: [PATCH] OCSP stapling: never return an expired OCSP response (ticket #425) In-Reply-To: <20150604160638.0212fb16ebd9cf53dc83cae0@andrewayer.name> References: <20150604160638.0212fb16ebd9cf53dc83cae0@andrewayer.name> Message-ID: <20150608203529.GJ26357@mdounin.ru> Hello! On Thu, Jun 04, 2015 at 04:06:38PM -0700, Andrew Ayer wrote: > # HG changeset patch > # User Andrew Ayer > # Date 1433458802 25200 > # Node ID f231e66871bcac1aa6db81e6153f818b417f8338 > # Parent d811f22033ad2eb5c70dc4bbdda31c949a127ddb > OCSP stapling: never return an expired OCSP response (ticket #425) > > Previously, once an OCSP response was cached, it would be sent to > clients until a new response replaced it, even if the response expired. > This is bad, since Firefox displays an interstitial SSL error when it > receives an expired stapled OCSP response, and Chrome is planning to do > the same as well. > > With this change, nginx now caches the expiration time of the OCSP > response, and re-checks it before sending the response to the client. > If the response is expired, it's immediately cleared from the cache, > which prevents it from being returned, and triggers an immediate update > from the OCSP responder. > > diff -r d811f22033ad -r f231e66871bc src/event/ngx_event_openssl_stapling.c > --- a/src/event/ngx_event_openssl_stapling.c Wed Jun 03 19:12:26 2015 +0300 > +++ b/src/event/ngx_event_openssl_stapling.c Thu Jun 04 16:00:02 2015 -0700 > @@ -18,6 +18,9 @@ > ngx_str_t staple; > ngx_msec_t timeout; > > + ASN1_GENERALIZEDTIME *thisupdate; > + ASN1_GENERALIZEDTIME *nextupdate; > + > ngx_resolver_t *resolver; > ngx_msec_t resolver_timeout; > > @@ -462,6 +465,27 @@ > staple = data; > rc = SSL_TLSEXT_ERR_NOACK; > > + if (staple->thisupdate && staple->nextupdate > + && OCSP_check_validity(staple->thisupdate, > + staple->nextupdate, 300, -1) != 1) > + { I can't say I like this approach. This way, we preserve strings and do complex string operations on each handshake. And half of these operations are not needed at all, as we already checked thisupdate. The nextupdate time should be really converted to time_t and compared normally instead. I understand that OpenSSL's API is rather limited here, and doesn't provide an easy way to do the conversion. Looks like the only correct way to do it is to print a time using the ASN1_GENERALIZEDTIME_print() function, and then parse the result. Below are patches to do this. First two are preparatory: they remove unused ngx_http_get_time() declaration and move ngx_http_parse_time() to core level. Last one introduce actual changes to stapling code. # HG changeset patch # User Maxim Dounin # Date 1433793592 -10800 # Mon Jun 08 22:59:52 2015 +0300 # Node ID d66d1233dc74c3ca8561cdeb24ac9a618802f813 # Parent f654addf0eea52247dd6a1646ea2255b47e0e84f Removed unused ngx_http_get_time() declaration. diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h --- a/src/http/ngx_http.h +++ b/src/http/ngx_http.h @@ -149,8 +149,6 @@ void ngx_http_clean_header(ngx_http_requ time_t ngx_http_parse_time(u_char *value, size_t len); -size_t ngx_http_get_time(char *buf, time_t t); - ngx_int_t ngx_http_discard_request_body(ngx_http_request_t *r); # HG changeset patch # User Maxim Dounin # Date 1433794645 -10800 # Mon Jun 08 23:17:25 2015 +0300 # Node ID c098aa9b73fe4713092be070d39b565c1610c568 # Parent d66d1233dc74c3ca8561cdeb24ac9a618802f813 Moved ngx_http_parse_time() to core, renamed accordingly. The function is now called ngx_parse_http_time(), and can be used by any code to parse HTTP-style date and time. In particular, it will be used for OCSP Stapling. For compatibility, a macro ngx_http_parse_time() provided for a while. diff --git a/auto/sources b/auto/sources --- a/auto/sources +++ b/auto/sources @@ -19,6 +19,7 @@ CORE_DEPS="src/core/nginx.h \ src/core/ngx_queue.h \ src/core/ngx_string.h \ src/core/ngx_parse.h \ + src/core/ngx_parse_time.h \ src/core/ngx_inet.h \ src/core/ngx_file.h \ src/core/ngx_crc.h \ @@ -53,6 +54,7 @@ CORE_SRCS="src/core/nginx.c \ src/core/ngx_output_chain.c \ src/core/ngx_string.c \ src/core/ngx_parse.c \ + src/core/ngx_parse_time.c \ src/core/ngx_inet.c \ src/core/ngx_file.c \ src/core/ngx_crc32.c \ @@ -303,7 +305,6 @@ HTTP_SRCS="src/http/ngx_http.c \ src/http/ngx_http_script.c \ src/http/ngx_http_upstream.c \ src/http/ngx_http_upstream_round_robin.c \ - src/http/ngx_http_parse_time.c \ src/http/modules/ngx_http_static_module.c \ src/http/modules/ngx_http_index_module.c \ src/http/modules/ngx_http_chunked_filter_module.c \ diff --git a/src/core/ngx_core.h b/src/core/ngx_core.h --- a/src/core/ngx_core.h +++ b/src/core/ngx_core.h @@ -54,6 +54,7 @@ typedef void (*ngx_connection_handler_pt #include #include #include +#include #include #include #include diff --git a/src/http/ngx_http_parse_time.c b/src/core/ngx_parse_time.c rename from src/http/ngx_http_parse_time.c rename to src/core/ngx_parse_time.c --- a/src/http/ngx_http_parse_time.c +++ b/src/core/ngx_parse_time.c @@ -7,13 +7,12 @@ #include #include -#include static ngx_uint_t mday[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; time_t -ngx_http_parse_time(u_char *value, size_t len) +ngx_parse_http_time(u_char *value, size_t len) { u_char *p, *end; ngx_int_t month; diff --git a/src/core/ngx_parse_time.h b/src/core/ngx_parse_time.h new file mode 100644 --- /dev/null +++ b/src/core/ngx_parse_time.h @@ -0,0 +1,22 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_PARSE_TIME_H_INCLUDED_ +#define _NGX_PARSE_TIME_H_INCLUDED_ + + +#include +#include + + +time_t ngx_parse_http_time(u_char *value, size_t len); + +/* compatibility */ +#define ngx_http_parse_time(value, len) ngx_parse_http_time(value, len) + + +#endif /* _NGX_PARSE_TIME_H_INCLUDED_ */ diff --git a/src/http/modules/ngx_http_dav_module.c b/src/http/modules/ngx_http_dav_module.c --- a/src/http/modules/ngx_http_dav_module.c +++ b/src/http/modules/ngx_http_dav_module.c @@ -255,7 +255,7 @@ ngx_http_dav_put_handler(ngx_http_reques ext.log = r->connection->log; if (r->headers_in.date) { - date = ngx_http_parse_time(r->headers_in.date->value.data, + date = ngx_parse_http_time(r->headers_in.date->value.data, r->headers_in.date->value.len); if (date != NGX_ERROR) { diff --git a/src/http/modules/ngx_http_headers_filter_module.c b/src/http/modules/ngx_http_headers_filter_module.c --- a/src/http/modules/ngx_http_headers_filter_module.c +++ b/src/http/modules/ngx_http_headers_filter_module.c @@ -498,7 +498,7 @@ ngx_http_set_last_modified(ngx_http_requ } r->headers_out.last_modified_time = - (value->len) ? ngx_http_parse_time(value->data, value->len) : -1; + (value->len) ? ngx_parse_http_time(value->data, value->len) : -1; return NGX_OK; } diff --git a/src/http/modules/ngx_http_not_modified_filter_module.c b/src/http/modules/ngx_http_not_modified_filter_module.c --- a/src/http/modules/ngx_http_not_modified_filter_module.c +++ b/src/http/modules/ngx_http_not_modified_filter_module.c @@ -118,7 +118,7 @@ ngx_http_test_if_unmodified(ngx_http_req return 0; } - iums = ngx_http_parse_time(r->headers_in.if_unmodified_since->value.data, + iums = ngx_parse_http_time(r->headers_in.if_unmodified_since->value.data, r->headers_in.if_unmodified_since->value.len); ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, @@ -148,7 +148,7 @@ ngx_http_test_if_modified(ngx_http_reque return 1; } - ims = ngx_http_parse_time(r->headers_in.if_modified_since->value.data, + ims = ngx_parse_http_time(r->headers_in.if_modified_since->value.data, r->headers_in.if_modified_since->value.len); ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, diff --git a/src/http/modules/ngx_http_range_filter_module.c b/src/http/modules/ngx_http_range_filter_module.c --- a/src/http/modules/ngx_http_range_filter_module.c +++ b/src/http/modules/ngx_http_range_filter_module.c @@ -204,7 +204,7 @@ ngx_http_range_header_filter(ngx_http_re goto next_filter; } - if_range_time = ngx_http_parse_time(if_range->data, if_range->len); + if_range_time = ngx_parse_http_time(if_range->data, if_range->len); ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http ir:%d lm:%d", diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h --- a/src/http/ngx_http.h +++ b/src/http/ngx_http.h @@ -148,9 +148,6 @@ ngx_int_t ngx_http_filter_finalize_reque void ngx_http_clean_header(ngx_http_request_t *r); -time_t ngx_http_parse_time(u_char *value, size_t len); - - ngx_int_t ngx_http_discard_request_body(ngx_http_request_t *r); void ngx_http_discarded_request_body_handler(ngx_http_request_t *r); void ngx_http_block_reading(ngx_http_request_t *r); diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -2195,7 +2195,7 @@ ngx_http_gzip_ok(ngx_http_request_t *r) return NGX_DECLINED; } - expires = ngx_http_parse_time(e->value.data, e->value.len); + expires = ngx_parse_http_time(e->value.data, e->value.len); if (expires == NGX_ERROR) { return NGX_DECLINED; } @@ -2203,7 +2203,7 @@ ngx_http_gzip_ok(ngx_http_request_t *r) d = r->headers_out.date; if (d) { - date = ngx_http_parse_time(d->value.data, d->value.len); + date = ngx_parse_http_time(d->value.data, d->value.len); if (date == NGX_ERROR) { return NGX_DECLINED; } diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -3731,7 +3731,7 @@ ngx_http_upstream_store(ngx_http_request if (u->headers_in.last_modified) { - lm = ngx_http_parse_time(u->headers_in.last_modified->value.data, + lm = ngx_parse_http_time(u->headers_in.last_modified->value.data, u->headers_in.last_modified->value.len); if (lm != NGX_ERROR) { @@ -4128,7 +4128,7 @@ ngx_http_upstream_process_last_modified( #if (NGX_HTTP_CACHE) if (u->cacheable) { - u->headers_in.last_modified_time = ngx_http_parse_time(h->value.data, + u->headers_in.last_modified_time = ngx_parse_http_time(h->value.data, h->value.len); } @@ -4292,7 +4292,7 @@ ngx_http_upstream_process_expires(ngx_ht return NGX_OK; } - expires = ngx_http_parse_time(h->value.data, h->value.len); + expires = ngx_parse_http_time(h->value.data, h->value.len); if (expires == NGX_ERROR || expires < ngx_time()) { u->cacheable = 0; # HG changeset patch # User Maxim Dounin # Date 1433794648 -10800 # Mon Jun 08 23:17:28 2015 +0300 # Node ID 0dd6345e0e89ace4fca58230f75e4db4a09951bf # Parent c098aa9b73fe4713092be070d39b565c1610c568 OCSP stapling: avoid sending expired responses (ticket #425). diff --git a/src/event/ngx_event_openssl_stapling.c b/src/event/ngx_event_openssl_stapling.c --- a/src/event/ngx_event_openssl_stapling.c +++ b/src/event/ngx_event_openssl_stapling.c @@ -32,6 +32,7 @@ typedef struct { X509 *issuer; time_t valid; + time_t refresh; unsigned verify:1; unsigned loading:1; @@ -93,6 +94,8 @@ static int ngx_ssl_certificate_status_ca static void ngx_ssl_stapling_update(ngx_ssl_stapling_t *staple); static void ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx); +static time_t ngx_ssl_stapling_time(ASN1_GENERALIZEDTIME *asn1time); + static void ngx_ssl_stapling_cleanup(void *data); static ngx_ssl_ocsp_ctx_t *ngx_ssl_ocsp_start(void); @@ -462,7 +465,9 @@ ngx_ssl_certificate_status_callback(ngx_ staple = data; rc = SSL_TLSEXT_ERR_NOACK; - if (staple->staple.len) { + if (staple->staple.len + && staple->valid >= ngx_time()) + { /* we have to copy ocsp response as OpenSSL will free it by itself */ p = OPENSSL_malloc(staple->staple.len); @@ -490,7 +495,7 @@ ngx_ssl_stapling_update(ngx_ssl_stapling ngx_ssl_ocsp_ctx_t *ctx; if (staple->host.len == 0 - || staple->loading || staple->valid >= ngx_time()) + || staple->loading || staple->refresh >= ngx_time()) { return; } @@ -532,6 +537,7 @@ ngx_ssl_stapling_ocsp_handler(ngx_ssl_oc u_char *p; int n; size_t len; + time_t now, valid; ngx_str_t response; X509_STORE *store; STACK_OF(X509) *chain; @@ -542,6 +548,7 @@ ngx_ssl_stapling_ocsp_handler(ngx_ssl_oc ASN1_GENERALIZEDTIME *thisupdate, *nextupdate; staple = ctx->data; + now = ngx_time(); ocsp = NULL; basic = NULL; id = NULL; @@ -629,17 +636,28 @@ ngx_ssl_stapling_ocsp_handler(ngx_ssl_oc goto error; } + valid = ngx_ssl_stapling_time(nextupdate); + if (valid == (time_t) NGX_ERROR) { + ngx_log_error(NGX_LOG_ERR, ctx->log, 0, + "invalid nextUpdate time in certificate status"); + goto error; + } + OCSP_CERTID_free(id); OCSP_BASICRESP_free(basic); OCSP_RESPONSE_free(ocsp); + id = NULL; + basic = NULL; + ocsp = NULL; + /* copy the response to memory not in ctx->pool */ response.len = len; response.data = ngx_alloc(response.len, ctx->log); if (response.data == NULL) { - goto done; + goto error; } ngx_memcpy(response.data, ctx->response->pos, response.len); @@ -653,11 +671,10 @@ ngx_ssl_stapling_ocsp_handler(ngx_ssl_oc } staple->staple = response; - -done: + staple->valid = valid; staple->loading = 0; - staple->valid = ngx_time() + 3600; /* ssl_stapling_valid */ + staple->refresh = ngx_max(ngx_min(valid, now + 3600), now + 300); ngx_ssl_ocsp_done(ctx); return; @@ -665,7 +682,7 @@ done: error: staple->loading = 0; - staple->valid = ngx_time() + 300; /* ssl_stapling_err_valid */ + staple->refresh = now + 300; if (id) { OCSP_CERTID_free(id); @@ -683,6 +700,40 @@ error: } +static time_t +ngx_ssl_stapling_time(ASN1_GENERALIZEDTIME *asn1time) +{ + u_char *value; + size_t len; + time_t time; + BIO *bio; + + /* + * OpenSSL doesn't provide a way to convert ASN1_GENERALIZEDTIME + * into time_t. To do this, we use ASN1_GENERALIZEDTIME_print(), + * which uses the "MMM DD HH:MM:SS YYYY [GMT]" format (e.g., + * "Feb 3 00:55:52 2015 GMT"), and parse the result. + */ + + bio = BIO_new(BIO_s_mem()); + if (bio == NULL) { + return NGX_ERROR; + } + + /* fake weekday prepended to match C asctime() format */ + + BIO_write(bio, "Tue ", sizeof("Tue ") - 1); + ASN1_GENERALIZEDTIME_print(bio, asn1time); + len = BIO_get_mem_data(bio, &value); + + time = ngx_parse_http_time(value, len); + + BIO_free(bio); + + return time; +} + + static void ngx_ssl_stapling_cleanup(void *data) { -- Maxim Dounin http://nginx.org/ From damien at platform.sh Mon Jun 8 23:08:30 2015 From: damien at platform.sh (Damien Tournoud) Date: Tue, 09 Jun 2015 01:08:30 +0200 Subject: [PATCH] HTTP: Add the $upstream_cache_age variable, allowing better HTTP/1.1 compliance Message-ID: <04fab8a5fbac9a350c75.1433804910@flylight.local> # HG changeset patch # User Damien Tournoud # Date 1433803821 -7200 # Tue Jun 09 00:50:21 2015 +0200 # Node ID 04fab8a5fbac9a350c7552ac81569a5deb641240 # Parent 1729d8d3eb3acbb79b1b0c1d60b411aacc4f8461 HTTP: Add the $upstream_cache_age variable, allowing better HTTP/1.1 compliance. Nginx, when used as a proxy cache, doesn't have any practical ways to issue a `Age:` header, signaling to downstream clients the age of objects that it serves from the cache. This patch adds a $upstream_cache_age variable, that can be used to issue such a header like: add_header Age "$upstream_cache_age"; The header is based on `r->cache->date`, so it gets reset with revalidations, which I think is a reasonable behavior. In other to make the variable useful, I had to where it is set in `ngx_http_upstream_send_response()` (in the MISS path), so that it is set before sending the headers. diff -r 1729d8d3eb3a -r 04fab8a5fbac src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c Mon Jun 08 23:13:56 2015 +0300 +++ b/src/http/ngx_http_upstream.c Tue Jun 09 00:50:21 2015 +0200 @@ -23,6 +23,8 @@ ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_upstream_cache_etag(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_upstream_cache_age(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); #endif static void ngx_http_upstream_init_request(ngx_http_request_t *r); @@ -393,6 +395,10 @@ ngx_http_upstream_cache_etag, 0, NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 }, + { ngx_string("upstream_cache_age"), NULL, + ngx_http_upstream_cache_age, 0, + NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 }, + #endif { ngx_null_string, NULL, NULL, 0, 0, 0 } @@ -2647,6 +2653,15 @@ ngx_connection_t *c; ngx_http_core_loc_conf_t *clcf; +#if (NGX_HTTP_CACHE) + time_t now; + now = ngx_time(); + + if (r->cache) { + r->cache->date = now; + } +#endif + rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->post_action) { @@ -2787,9 +2802,7 @@ } if (u->cacheable) { - time_t now, valid; - - now = ngx_time(); + time_t valid; valid = r->cache->valid_sec; @@ -2802,7 +2815,6 @@ } if (valid) { - r->cache->date = now; r->cache->body_start = (u_short) (u->buffer.pos - u->buffer.start); if (u->headers_in.status_n == NGX_HTTP_OK @@ -5248,6 +5260,39 @@ return NGX_OK; } + +static ngx_int_t +ngx_http_upstream_cache_age(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + u_char *p; + time_t now; + + now = ngx_time(); + + if (r->upstream == NULL + || r->upstream->cacheable == 0 + || r->cache->date > now) + { + v->not_found = 1; + return NGX_OK; + } + + p = ngx_pnalloc(r->pool, NGX_TIME_T_LEN); + if (p == NULL) { + return NGX_ERROR; + } + + v->len = ngx_sprintf(p, "%T", now - r->cache->date) - p; + + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = p; + + return NGX_OK; +} + #endif From damien at platform.sh Mon Jun 8 23:12:18 2015 From: damien at platform.sh (Damien Tournoud) Date: Tue, 9 Jun 2015 01:12:18 +0200 Subject: [PATCH] HTTP: Add the $upstream_cache_age variable, allowing better HTTP/1.1 compliance In-Reply-To: <04fab8a5fbac9a350c75.1433804910@flylight.local> References: <04fab8a5fbac9a350c75.1433804910@flylight.local> Message-ID: On Tue, Jun 9, 2015 at 1:08 AM, Damien Tournoud wrote: > In other to make the variable useful, I had to where it is set > in `ngx_http_upstream_send_response()` (in the MISS path), > so that it is set before sending the headers. > (It's late, and I'm contributing to a project that actively discourages contributions by using Mercurial and mandating submissions to be sent to a subscribe-only mailing-list. I forgot the name of that project.) So, here is the non-jibberish version: In order to make the variable useful, I had to move where it is set in `ngx_http_upstream_send_response()` (in the MISS path), so that it is set before sending the headers. Damien -------------- next part -------------- An HTML attachment was scrubbed... URL: From vl at nginx.com Tue Jun 9 10:27:09 2015 From: vl at nginx.com (Vladimir Homutov) Date: Tue, 09 Jun 2015 10:27:09 +0000 Subject: [nginx] Stream: added postconfiguration method to stream modules. Message-ID: details: http://hg.nginx.org/nginx/rev/68c106e6fa0a branches: changeset: 6174:68c106e6fa0a user: Vladimir Homutov date: Tue Jun 09 13:00:45 2015 +0300 description: Stream: added postconfiguration method to stream modules. diffstat: src/stream/ngx_stream.c | 14 ++++++++++++++ src/stream/ngx_stream.h | 2 ++ src/stream/ngx_stream_core_module.c | 2 ++ src/stream/ngx_stream_proxy_module.c | 2 ++ src/stream/ngx_stream_ssl_module.c | 2 ++ src/stream/ngx_stream_upstream.c | 2 ++ src/stream/ngx_stream_upstream_hash_module.c | 2 ++ src/stream/ngx_stream_upstream_least_conn_module.c | 2 ++ src/stream/ngx_stream_upstream_zone_module.c | 2 ++ 9 files changed, 30 insertions(+), 0 deletions(-) diffs (120 lines): diff -r 1729d8d3eb3a -r 68c106e6fa0a src/stream/ngx_stream.c --- a/src/stream/ngx_stream.c Mon Jun 08 23:13:56 2015 +0300 +++ b/src/stream/ngx_stream.c Tue Jun 09 13:00:45 2015 +0300 @@ -204,6 +204,20 @@ ngx_stream_block(ngx_conf_t *cf, ngx_com } } + for (m = 0; ngx_modules[m]; m++) { + if (ngx_modules[m]->type != NGX_STREAM_MODULE) { + continue; + } + + module = ngx_modules[m]->ctx; + + if (module->postconfiguration) { + if (module->postconfiguration(cf) != NGX_OK) { + return NGX_CONF_ERROR; + } + } + } + *cf = pcf; diff -r 1729d8d3eb3a -r 68c106e6fa0a src/stream/ngx_stream.h --- a/src/stream/ngx_stream.h Mon Jun 08 23:13:56 2015 +0300 +++ b/src/stream/ngx_stream.h Tue Jun 09 13:00:45 2015 +0300 @@ -148,6 +148,8 @@ struct ngx_stream_session_s { typedef struct { + ngx_int_t (*postconfiguration)(ngx_conf_t *cf); + void *(*create_main_conf)(ngx_conf_t *cf); char *(*init_main_conf)(ngx_conf_t *cf, void *conf); diff -r 1729d8d3eb3a -r 68c106e6fa0a src/stream/ngx_stream_core_module.c --- a/src/stream/ngx_stream_core_module.c Mon Jun 08 23:13:56 2015 +0300 +++ b/src/stream/ngx_stream_core_module.c Tue Jun 09 13:00:45 2015 +0300 @@ -50,6 +50,8 @@ static ngx_command_t ngx_stream_core_co static ngx_stream_module_t ngx_stream_core_module_ctx = { + NULL, /* postconfiguration */ + ngx_stream_core_create_main_conf, /* create main configuration */ NULL, /* init main configuration */ diff -r 1729d8d3eb3a -r 68c106e6fa0a src/stream/ngx_stream_proxy_module.c --- a/src/stream/ngx_stream_proxy_module.c Mon Jun 08 23:13:56 2015 +0300 +++ b/src/stream/ngx_stream_proxy_module.c Tue Jun 09 13:00:45 2015 +0300 @@ -246,6 +246,8 @@ static ngx_command_t ngx_stream_proxy_c static ngx_stream_module_t ngx_stream_proxy_module_ctx = { + NULL, /* postconfiguration */ + NULL, /* create main configuration */ NULL, /* init main configuration */ diff -r 1729d8d3eb3a -r 68c106e6fa0a src/stream/ngx_stream_ssl_module.c --- a/src/stream/ngx_stream_ssl_module.c Mon Jun 08 23:13:56 2015 +0300 +++ b/src/stream/ngx_stream_ssl_module.c Tue Jun 09 13:00:45 2015 +0300 @@ -132,6 +132,8 @@ static ngx_command_t ngx_stream_ssl_com static ngx_stream_module_t ngx_stream_ssl_module_ctx = { + NULL, /* postconfiguration */ + NULL, /* create main configuration */ NULL, /* init main configuration */ diff -r 1729d8d3eb3a -r 68c106e6fa0a src/stream/ngx_stream_upstream.c --- a/src/stream/ngx_stream_upstream.c Mon Jun 08 23:13:56 2015 +0300 +++ b/src/stream/ngx_stream_upstream.c Tue Jun 09 13:00:45 2015 +0300 @@ -39,6 +39,8 @@ static ngx_command_t ngx_stream_upstrea static ngx_stream_module_t ngx_stream_upstream_module_ctx = { + NULL, /* postconfiguration */ + ngx_stream_upstream_create_main_conf, /* create main configuration */ ngx_stream_upstream_init_main_conf, /* init main configuration */ diff -r 1729d8d3eb3a -r 68c106e6fa0a src/stream/ngx_stream_upstream_hash_module.c --- a/src/stream/ngx_stream_upstream_hash_module.c Mon Jun 08 23:13:56 2015 +0300 +++ b/src/stream/ngx_stream_upstream_hash_module.c Tue Jun 09 13:00:45 2015 +0300 @@ -76,6 +76,8 @@ static ngx_command_t ngx_stream_upstrea static ngx_stream_module_t ngx_stream_upstream_hash_module_ctx = { + NULL, /* postconfiguration */ + NULL, /* create main configuration */ NULL, /* init main configuration */ diff -r 1729d8d3eb3a -r 68c106e6fa0a src/stream/ngx_stream_upstream_least_conn_module.c --- a/src/stream/ngx_stream_upstream_least_conn_module.c Mon Jun 08 23:13:56 2015 +0300 +++ b/src/stream/ngx_stream_upstream_least_conn_module.c Tue Jun 09 13:00:45 2015 +0300 @@ -32,6 +32,8 @@ static ngx_command_t ngx_stream_upstrea static ngx_stream_module_t ngx_stream_upstream_least_conn_module_ctx = { + NULL, /* postconfiguration */ + NULL, /* create main configuration */ NULL, /* init main configuration */ diff -r 1729d8d3eb3a -r 68c106e6fa0a src/stream/ngx_stream_upstream_zone_module.c --- a/src/stream/ngx_stream_upstream_zone_module.c Mon Jun 08 23:13:56 2015 +0300 +++ b/src/stream/ngx_stream_upstream_zone_module.c Tue Jun 09 13:00:45 2015 +0300 @@ -32,6 +32,8 @@ static ngx_command_t ngx_stream_upstrea static ngx_stream_module_t ngx_stream_upstream_zone_module_ctx = { + NULL, /* postconfiguration */ + NULL, /* create main configuration */ NULL, /* init main configuration */ From vl at nginx.com Tue Jun 9 10:27:11 2015 From: vl at nginx.com (Vladimir Homutov) Date: Tue, 09 Jun 2015 10:27:11 +0000 Subject: [nginx] Stream: access module. Message-ID: details: http://hg.nginx.org/nginx/rev/8807a2369b1a branches: changeset: 6175:8807a2369b1a user: Vladimir Homutov date: Thu Jun 04 13:04:12 2015 +0300 description: Stream: access module. stream { server { ... allow 127.0.0.1; deny all; } } diffstat: auto/modules | 5 + auto/options | 3 + auto/sources | 3 + src/stream/ngx_stream.h | 4 + src/stream/ngx_stream_access_module.c | 451 ++++++++++++++++++++++++++++++++++ src/stream/ngx_stream_handler.c | 37 +- 6 files changed, 491 insertions(+), 12 deletions(-) diffs (truncated from 583 to 300 lines): diff -r 68c106e6fa0a -r 8807a2369b1a auto/modules --- a/auto/modules Tue Jun 09 13:00:45 2015 +0300 +++ b/auto/modules Thu Jun 04 13:04:12 2015 +0300 @@ -514,6 +514,11 @@ if [ $STREAM = YES ]; then STREAM_SRCS="$STREAM_SRCS $STREAM_SSL_SRCS" fi + if [ $STREAM_ACCESS = YES ]; then + modules="$modules $STREAM_ACCESS_MODULE" + STREAM_SRCS="$STREAM_SRCS $STREAM_ACCESS_SRCS" + fi + if [ $STREAM_UPSTREAM_HASH = YES ]; then modules="$modules $STREAM_UPSTREAM_HASH_MODULE" STREAM_SRCS="$STREAM_SRCS $STREAM_UPSTREAM_HASH_SRCS" diff -r 68c106e6fa0a -r 8807a2369b1a auto/options --- a/auto/options Tue Jun 09 13:00:45 2015 +0300 +++ b/auto/options Thu Jun 04 13:04:12 2015 +0300 @@ -113,6 +113,7 @@ MAIL_SMTP=YES STREAM=NO STREAM_SSL=NO +STREAM_ACCESS=YES STREAM_UPSTREAM_HASH=YES STREAM_UPSTREAM_LEAST_CONN=YES STREAM_UPSTREAM_ZONE=YES @@ -282,6 +283,7 @@ use the \"--with-mail_ssl_module\" optio --with-stream) STREAM=YES ;; --with-stream_ssl_module) STREAM_SSL=YES ;; + --without-stream_access_module) STREAM_ACCESS=NO ;; --without-stream_upstream_hash_module) STREAM_UPSTREAM_HASH=NO ;; --without-stream_upstream_least_conn_module) @@ -450,6 +452,7 @@ cat << END --with-stream enable TCP proxy module --with-stream_ssl_module enable ngx_stream_ssl_module + --without-stream_access_module disable ngx_stream_access_module --without-stream_upstream_hash_module disable ngx_stream_upstream_hash_module --without-stream_upstream_least_conn_module diff -r 68c106e6fa0a -r 8807a2369b1a auto/sources --- a/auto/sources Tue Jun 09 13:00:45 2015 +0300 +++ b/auto/sources Thu Jun 04 13:04:12 2015 +0300 @@ -567,6 +567,9 @@ STREAM_SSL_MODULE="ngx_stream_ssl_module STREAM_SSL_DEPS="src/stream/ngx_stream_ssl_module.h" STREAM_SSL_SRCS="src/stream/ngx_stream_ssl_module.c" +STREAM_ACCESS_MODULE=ngx_stream_access_module +STREAM_ACCESS_SRCS=src/stream/ngx_stream_access_module.c + STREAM_UPSTREAM_HASH_MODULE=ngx_stream_upstream_hash_module STREAM_UPSTREAM_HASH_SRCS=src/stream/ngx_stream_upstream_hash_module.c diff -r 68c106e6fa0a -r 8807a2369b1a src/stream/ngx_stream.h --- a/src/stream/ngx_stream.h Tue Jun 09 13:00:45 2015 +0300 +++ b/src/stream/ngx_stream.h Thu Jun 04 13:04:12 2015 +0300 @@ -112,9 +112,13 @@ typedef struct { } ngx_stream_conf_addr_t; +typedef ngx_int_t (*ngx_stream_access_pt)(ngx_stream_session_t *s); + + typedef struct { ngx_array_t servers; /* ngx_stream_core_srv_conf_t */ ngx_array_t listen; /* ngx_stream_listen_t */ + ngx_stream_access_pt access_handler; } ngx_stream_core_main_conf_t; diff -r 68c106e6fa0a -r 8807a2369b1a src/stream/ngx_stream_access_module.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/stream/ngx_stream_access_module.c Thu Jun 04 13:04:12 2015 +0300 @@ -0,0 +1,451 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + + +typedef struct { + in_addr_t mask; + in_addr_t addr; + ngx_uint_t deny; /* unsigned deny:1; */ +} ngx_stream_access_rule_t; + +#if (NGX_HAVE_INET6) + +typedef struct { + struct in6_addr addr; + struct in6_addr mask; + ngx_uint_t deny; /* unsigned deny:1; */ +} ngx_stream_access_rule6_t; + +#endif + +#if (NGX_HAVE_UNIX_DOMAIN) + +typedef struct { + ngx_uint_t deny; /* unsigned deny:1; */ +} ngx_stream_access_rule_un_t; + +#endif + +typedef struct { + ngx_array_t *rules; /* array of ngx_stream_access_rule_t */ +#if (NGX_HAVE_INET6) + ngx_array_t *rules6; /* array of ngx_stream_access_rule6_t */ +#endif +#if (NGX_HAVE_UNIX_DOMAIN) + ngx_array_t *rules_un; /* array of ngx_stream_access_rule_un_t */ +#endif +} ngx_stream_access_srv_conf_t; + + +static ngx_int_t ngx_stream_access_handler(ngx_stream_session_t *s); +static ngx_int_t ngx_stream_access_inet(ngx_stream_session_t *s, + ngx_stream_access_srv_conf_t *ascf, in_addr_t addr); +#if (NGX_HAVE_INET6) +static ngx_int_t ngx_stream_access_inet6(ngx_stream_session_t *s, + ngx_stream_access_srv_conf_t *ascf, u_char *p); +#endif +#if (NGX_HAVE_UNIX_DOMAIN) +static ngx_int_t ngx_stream_access_unix(ngx_stream_session_t *s, + ngx_stream_access_srv_conf_t *ascf); +#endif +static ngx_int_t ngx_stream_access_found(ngx_stream_session_t *s, + ngx_uint_t deny); +static char *ngx_stream_access_rule(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); +static void *ngx_stream_access_create_srv_conf(ngx_conf_t *cf); +static char *ngx_stream_access_merge_srv_conf(ngx_conf_t *cf, + void *parent, void *child); +static ngx_int_t ngx_stream_access_init(ngx_conf_t *cf); + + +static ngx_command_t ngx_stream_access_commands[] = { + + { ngx_string("allow"), + NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, + ngx_stream_access_rule, + NGX_STREAM_SRV_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("deny"), + NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, + ngx_stream_access_rule, + NGX_STREAM_SRV_CONF_OFFSET, + 0, + NULL }, + + ngx_null_command +}; + + + +static ngx_stream_module_t ngx_stream_access_module_ctx = { + ngx_stream_access_init, /* postconfiguration */ + + NULL, /* create main configuration */ + NULL, /* init main configuration */ + + ngx_stream_access_create_srv_conf, /* create server configuration */ + ngx_stream_access_merge_srv_conf /* merge server configuration */ +}; + + +ngx_module_t ngx_stream_access_module = { + NGX_MODULE_V1, + &ngx_stream_access_module_ctx, /* module context */ + ngx_stream_access_commands, /* module directives */ + NGX_STREAM_MODULE, /* module type */ + NULL, /* init master */ + NULL, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + + +static ngx_int_t +ngx_stream_access_handler(ngx_stream_session_t *s) +{ + struct sockaddr_in *sin; + ngx_stream_access_srv_conf_t *ascf; +#if (NGX_HAVE_INET6) + u_char *p; + in_addr_t addr; + struct sockaddr_in6 *sin6; +#endif + + ascf = ngx_stream_get_module_srv_conf(s, ngx_stream_access_module); + + switch (s->connection->sockaddr->sa_family) { + + case AF_INET: + if (ascf->rules) { + sin = (struct sockaddr_in *) s->connection->sockaddr; + return ngx_stream_access_inet(s, ascf, sin->sin_addr.s_addr); + } + break; + +#if (NGX_HAVE_INET6) + + case AF_INET6: + sin6 = (struct sockaddr_in6 *) s->connection->sockaddr; + p = sin6->sin6_addr.s6_addr; + + if (ascf->rules && IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { + addr = p[12] << 24; + addr += p[13] << 16; + addr += p[14] << 8; + addr += p[15]; + return ngx_stream_access_inet(s, ascf, htonl(addr)); + } + + if (ascf->rules6) { + return ngx_stream_access_inet6(s, ascf, p); + } + + break; + +#endif + +#if (NGX_HAVE_UNIX_DOMAIN) + + case AF_UNIX: + if (ascf->rules_un) { + return ngx_stream_access_unix(s, ascf); + } + + break; + +#endif + } + + return NGX_DECLINED; +} + + +static ngx_int_t +ngx_stream_access_inet(ngx_stream_session_t *s, + ngx_stream_access_srv_conf_t *ascf, in_addr_t addr) +{ + ngx_uint_t i; + ngx_stream_access_rule_t *rule; + + rule = ascf->rules->elts; + for (i = 0; i < ascf->rules->nelts; i++) { + + ngx_log_debug3(NGX_LOG_DEBUG_STREAM, s->connection->log, 0, + "access: %08XD %08XD %08XD", + addr, rule[i].mask, rule[i].addr); + + if ((addr & rule[i].mask) == rule[i].addr) { + return ngx_stream_access_found(s, rule[i].deny); + } + } + + return NGX_DECLINED; +} + + +#if (NGX_HAVE_INET6) + +static ngx_int_t +ngx_stream_access_inet6(ngx_stream_session_t *s, + ngx_stream_access_srv_conf_t *ascf, u_char *p) +{ + ngx_uint_t n; + ngx_uint_t i; + ngx_stream_access_rule6_t *rule6; + + rule6 = ascf->rules6->elts; + for (i = 0; i < ascf->rules6->nelts; i++) { + +#if (NGX_DEBUG) + { + size_t cl, ml, al; + u_char ct[NGX_INET6_ADDRSTRLEN]; + u_char mt[NGX_INET6_ADDRSTRLEN]; + u_char at[NGX_INET6_ADDRSTRLEN]; + + cl = ngx_inet6_ntop(p, ct, NGX_INET6_ADDRSTRLEN); + ml = ngx_inet6_ntop(rule6[i].mask.s6_addr, mt, NGX_INET6_ADDRSTRLEN); + al = ngx_inet6_ntop(rule6[i].addr.s6_addr, at, NGX_INET6_ADDRSTRLEN); + + ngx_log_debug6(NGX_LOG_DEBUG_STREAM, s->connection->log, 0, From mdounin at mdounin.ru Tue Jun 9 12:44:47 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 9 Jun 2015 15:44:47 +0300 Subject: Fwd: Windows shmem fix: makes shared memory fully ASLR and DEP compliant (ea. cache zone, limit zone, etc.) In-Reply-To: References: <706ca3a5ec658ea41fb9975f90ab9ab4@sebres.de> <20150422162929.GD32429@mdounin.ru> Message-ID: <20150609124447.GK26357@mdounin.ru> Hello! On Mon, Jun 08, 2015 at 09:56:16PM +0200, Sergey Brester wrote: > Hi, > > Back to my wish to fix a problem with multiple workers under windows... > > Since we successful implemented shared memory on windows, it may be used for > proper sharing a socket descriptor for multiple workers. > > Possible scenario can be found in this MSDN-article: > > https://msdn.microsoft.com/en-en/library/windows/desktop/ms741565%28v=vs.85%29.aspx > > I need some help, to make the changes more nginx conform: > > I have not yet decided which process will create/share a socket (duplicate > handle and set it to shared memory). The idea was to create from master in > ngx_event_process_init an initial shared memory with empty socket > descriptors. The first worker inside ngx_open_listening_sockets may create a > socket and duplicate a handle to share it with all other workers (save it to > shared memory). > > The first problem would be the way windows does it - the (source) process > should know each target process handle to duplicate a socket handle for it. > So if a new worker will be created, it should "receive" a new shared handle, > duplicated specially for him. > > So if not possible to do that somehow, only master process can create a > socket and duplicate handle for each worker, before create him. But this > will make the whole solution more complicated as now. This doesn't looks like an approach which will work well with nginx. I would rather recommend trying to use normal handle inheritance, as previously suggested. > Another way is, to create child with CreateProcess and bInheritHandles=1, > and then save the first created socket handle in shared memory, but the Instead of shared memory consider using an environment variable, much like it's done for inherited sockets. > problem would be - all handles created from childs will be shared also > (files, channels, etc.), so if some handle will be not proper closed before > end of some process - it will be a leak, as long as all processes including > master are not terminated. I don't see how CreateProcess() bInheritHandles affects handles created by worker processes. It is documented to only control whether inheritable handles will be inherited by a new process or not. Either way, worker processes are not expected to start other processes, so you probably shouldn't care at all. -- Maxim Dounin http://nginx.org/ From serg.brester at sebres.de Tue Jun 9 13:43:09 2015 From: serg.brester at sebres.de (Sergey Brester) Date: Tue, 09 Jun 2015 15:43:09 +0200 Subject: Fwd: Windows shmem fix: makes shared memory fully ASLR and DEP compliant (ea. cache zone, limit zone, etc.) In-Reply-To: <20150609124447.GK26357@mdounin.ru> References: <706ca3a5ec658ea41fb9975f90ab9ab4@sebres.de> <20150422162929.GD32429@mdounin.ru> <20150609124447.GK26357@mdounin.ru> Message-ID: 09.06.2015 14:44, Maxim Dounin: > > I don't see how CreateProcess() bInheritHandles affects handles > created by worker processes. It is documented to only control > whether inheritable handles will be inherited by a new process or > not. Either way, worker processes are not expected to start other > processes, so you probably shouldn't care at all. The problem is, some handles are frequently default inheritable in windows. And if any process in combination parent/children was exited (ex. creashed) without closing this handle - it would be not closed, as long as last process of this "group" is still alive (can potentially inherit this leak handle). Very bad thing is this "bInheritHandles", have very bad experience with it. From mdounin at mdounin.ru Tue Jun 9 14:20:09 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 9 Jun 2015 17:20:09 +0300 Subject: Fwd: Windows shmem fix: makes shared memory fully ASLR and DEP compliant (ea. cache zone, limit zone, etc.) In-Reply-To: References: <706ca3a5ec658ea41fb9975f90ab9ab4@sebres.de> <20150422162929.GD32429@mdounin.ru> <20150609124447.GK26357@mdounin.ru> Message-ID: <20150609142009.GO26357@mdounin.ru> Hello! On Tue, Jun 09, 2015 at 03:43:09PM +0200, Sergey Brester wrote: > 09.06.2015 14:44, Maxim Dounin: > > >I don't see how CreateProcess() bInheritHandles affects handles > >created by worker processes. It is documented to only control > >whether inheritable handles will be inherited by a new process or > >not. Either way, worker processes are not expected to start other > >processes, so you probably shouldn't care at all. > > The problem is, some handles are frequently default inheritable in windows. > And if any process in combination parent/children was exited (ex. creashed) > without closing this handle - it would be not closed, as long as last > process of this "group" is still alive (can potentially inherit this leak > handle). You mean - one process exited without closing the handle, all other processes closed the handle - and the handle is still open? If this is really happens, this is probably a bug in Windows. Either way, it doesn't looks blocking for nginx, as opens only a small number of handles in the master process, and in most cases we want them to be shared among all processes. > Very bad thing is this "bInheritHandles", have very bad experience with it. The bInheritHandles switch looks more or less like what fork() does with file descriptors on Unix, and related problems are very well known (and mitigated with things like FD_CLOEXEC and/or careful use of file descriptors). -- Maxim Dounin http://nginx.org/ From serg.brester at sebres.de Tue Jun 9 14:37:56 2015 From: serg.brester at sebres.de (Sergey Brester) Date: Tue, 09 Jun 2015 16:37:56 +0200 Subject: Fwd: Windows shmem fix: makes shared memory fully ASLR and DEP compliant (ea. cache zone, limit zone, etc.) In-Reply-To: References: <706ca3a5ec658ea41fb9975f90ab9ab4@sebres.de> <20150422162929.GD32429@mdounin.ru> <20150609124447.GK26357@mdounin.ru> Message-ID: <0a976d7f7536c592cb3e792004d08add@sebres.de> 09.06.2015 15:43, Sergey Brester: > 09.06.2015 14:44, Maxim Dounin: > >> I don't see how CreateProcess() bInheritHandles affects handles >> created by worker processes. It is documented to only control whether >> inheritable handles will be inherited by a new process or not. Either >> way, worker processes are not expected to start other processes, so >> you probably shouldn't care at all. > > The problem is, some handles are frequently default inheritable in > windows. And if any process in combination parent/children was exited > (ex. creashed) without closing this handle - it would be not closed, as > long as last process of this "group" is still alive (can potentially > inherit this leak handle). > > Very bad thing is this "bInheritHandles", have very bad experience with > it. Additionally, I have tested in the meantime the solution with createprocess/bInheritHandles=1. Select in each child will fail with WSAEINVAL "select() failed (10022: An invalid argument was supplied)", despite the flag WSA_FLAG_NO_HANDLE_INHERIT in master was not specified by creating of listening socket. Don't forget LSPs (Layered Service Providers) - although depricated but, when certain LSPs are installed, the inherited handles can't be used in the child. But I try to dig deeper... From mdounin at mdounin.ru Tue Jun 9 15:00:33 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 9 Jun 2015 18:00:33 +0300 Subject: [PATCH] HTTP: Add the $upstream_cache_age variable, allowing better HTTP/1.1 compliance In-Reply-To: References: <04fab8a5fbac9a350c75.1433804910@flylight.local> Message-ID: <20150609150033.GQ26357@mdounin.ru> Hello! On Tue, Jun 09, 2015 at 01:12:18AM +0200, Damien Tournoud wrote: > On Tue, Jun 9, 2015 at 1:08 AM, Damien Tournoud wrote: > > > In other to make the variable useful, I had to where it is set > > in `ngx_http_upstream_send_response()` (in the MISS path), > > so that it is set before sending the headers. > > > > (It's late, and I'm contributing to a project that actively discourages > contributions by using Mercurial and mandating submissions to be sent to a > subscribe-only mailing-list. I forgot the name of that project.) > > So, here is the non-jibberish version: > > In order to make the variable useful, I had to move where it is set > in `ngx_http_upstream_send_response()` (in the MISS path), > so that it is set before sending the headers. Please see this (and the thread): http://mailman.nginx.org/pipermail/nginx-devel/2014-October/006030.html -- Maxim Dounin http://nginx.org/ From damien at platform.sh Tue Jun 9 15:13:43 2015 From: damien at platform.sh (Damien Tournoud) Date: Tue, 9 Jun 2015 17:13:43 +0200 Subject: [PATCH] HTTP: Add the $upstream_cache_age variable, allowing better HTTP/1.1 compliance In-Reply-To: <20150609150033.GQ26357@mdounin.ru> References: <04fab8a5fbac9a350c75.1433804910@flylight.local> <20150609150033.GQ26357@mdounin.ru> Message-ID: On Tue, Jun 9, 2015 at 5:00 PM, Maxim Dounin wrote: > Please see this (and the thread): > http://mailman.nginx.org/pipermail/nginx-devel/2014-October/006030.html Good point. So would it be acceptable to: (1) add a new header processor for the "Age" header; (2) update `r->cache->date` and `r->cache->valid_sec` at the two places where it is set (miss + revalidation), to take into account the age of the upstream object. I'm not sure what `->date` is used for right now, so I don't know if it is ok to change its semantics like this (from "date when the object was last fetched / revalidated from upstream" to "date the object was created in the upstream")... I assume it is for expiring cached entry, but I'm not clear with that. Damien -------------- next part -------------- An HTML attachment was scrubbed... URL: From ru at nginx.com Wed Jun 10 09:30:19 2015 From: ru at nginx.com (Ruslan Ermilov) Date: Wed, 10 Jun 2015 09:30:19 +0000 Subject: [nginx] Configure: moved NGX_SBIN_PATH variable initialization. Message-ID: details: http://hg.nginx.org/nginx/rev/c983c8dea44c branches: changeset: 6176:c983c8dea44c user: Ruslan Ermilov date: Wed Jun 10 12:25:31 2015 +0300 description: Configure: moved NGX_SBIN_PATH variable initialization. It's now initialized in auto/options like the rest of variables for system paths. As a side effect, the currently unused macro NGX_SBIN_PATH now gets the correct value. diffstat: auto/install | 4 ---- auto/options | 1 + 2 files changed, 1 insertions(+), 4 deletions(-) diffs (25 lines): diff -r 8807a2369b1a -r c983c8dea44c auto/install --- a/auto/install Thu Jun 04 13:04:12 2015 +0300 +++ b/auto/install Wed Jun 10 12:25:31 2015 +0300 @@ -20,10 +20,6 @@ case ".$NGX_SBIN_PATH" in ./*) ;; - .) - NGX_SBIN_PATH=$NGX_PREFIX/sbin/nginx - ;; - *) NGX_SBIN_PATH=$NGX_PREFIX/$NGX_SBIN_PATH ;; diff -r 8807a2369b1a -r c983c8dea44c auto/options --- a/auto/options Thu Jun 04 13:04:12 2015 +0300 +++ b/auto/options Wed Jun 10 12:25:31 2015 +0300 @@ -525,6 +525,7 @@ if [ ".$NGX_PLATFORM" = ".win32" ]; then fi +NGX_SBIN_PATH=${NGX_SBIN_PATH:-sbin/nginx} NGX_CONF_PATH=${NGX_CONF_PATH:-conf/nginx.conf} NGX_CONF_PREFIX=`dirname $NGX_CONF_PATH` NGX_PID_PATH=${NGX_PID_PATH:-logs/nginx.pid} From ru at nginx.com Wed Jun 10 09:30:22 2015 From: ru at nginx.com (Ruslan Ermilov) Date: Wed, 10 Jun 2015 09:30:22 +0000 Subject: [nginx] Configure: search OpenSSL in a bunch of standard places. Message-ID: details: http://hg.nginx.org/nginx/rev/4d25ec8f0adb branches: changeset: 6177:4d25ec8f0adb user: Ruslan Ermilov date: Wed Jun 10 12:25:45 2015 +0300 description: Configure: search OpenSSL in a bunch of standard places. diffstat: auto/lib/openssl/conf | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 48 insertions(+), 0 deletions(-) diffs (58 lines): diff -r c983c8dea44c -r 4d25ec8f0adb auto/lib/openssl/conf --- a/auto/lib/openssl/conf Wed Jun 10 12:25:31 2015 +0300 +++ b/auto/lib/openssl/conf Wed Jun 10 12:25:45 2015 +0300 @@ -55,6 +55,54 @@ else ngx_feature_test="SSL_library_init()" . auto/feature + if [ $ngx_found = no ]; then + + # FreeBSD port + + ngx_feature="OpenSSL library in /usr/local/" + ngx_feature_path="/usr/local/include" + + if [ $NGX_RPATH = YES ]; then + ngx_feature_libs="-R/usr/local/lib -L/usr/local/lib -lssl -lcrypto" + else + ngx_feature_libs="-L/usr/local/lib -lssl -lcrypto" + fi + + . auto/feature + fi + + if [ $ngx_found = no ]; then + + # NetBSD port + + ngx_feature="OpenSSL library in /usr/pkg/" + ngx_feature_path="/usr/pkg/include" + + if [ $NGX_RPATH = YES ]; then + ngx_feature_libs="-R/usr/pkg/lib -L/usr/pkg/lib -lssl -lcrypto" + else + ngx_feature_libs="-L/usr/pkg/lib -lssl -lcrypto" + fi + + . auto/feature + fi + + if [ $ngx_found = no ]; then + + # MacPorts + + ngx_feature="OpenSSL library in /opt/local/" + ngx_feature_path="/opt/local/include" + + if [ $NGX_RPATH = YES ]; then + ngx_feature_libs="-R/opt/local/lib -L/opt/local/lib -lssl -lcrypto" + else + ngx_feature_libs="-L/opt/local/lib -lssl -lcrypto" + fi + + . auto/feature + fi + if [ $ngx_found = yes ]; then have=NGX_SSL . auto/have CORE_LIBS="$CORE_LIBS $ngx_feature_libs $NGX_LIBDL" From vbart at nginx.com Wed Jun 10 16:19:00 2015 From: vbart at nginx.com (Valentin Bartenev) Date: Wed, 10 Jun 2015 16:19:00 +0000 Subject: [nginx] Configure: added gcc5 to the list of known GCC versions. Message-ID: details: http://hg.nginx.org/nginx/rev/c041f1e0655f branches: changeset: 6178:c041f1e0655f user: Valentin Bartenev date: Wed Jun 10 19:18:20 2015 +0300 description: Configure: added gcc5 to the list of known GCC versions. diffstat: auto/cc/gcc | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 4d25ec8f0adb -r c041f1e0655f auto/cc/gcc --- a/auto/cc/gcc Wed Jun 10 12:25:45 2015 +0300 +++ b/auto/cc/gcc Wed Jun 10 19:18:20 2015 +0300 @@ -153,7 +153,7 @@ CFLAGS="$CFLAGS -Wall -Wpointer-arith" case "$NGX_GCC_VER" in - 3.* | 4.* ) + [3-5].*) # we have a lot of the unused function arguments CFLAGS="$CFLAGS -Wno-unused-parameter" # 4.2.1 shows the warning in wrong places From serg.brester at sebres.de Wed Jun 10 19:48:28 2015 From: serg.brester at sebres.de (Sergey Brester) Date: Wed, 10 Jun 2015 21:48:28 +0200 Subject: Fix windows issue with multiple workers Message-ID: <64cd3e82b8271b1240c588dc6fece3bb@sebres.de> Hi, enclosed you will find an attached changeset, that contains fix for windows issue with multiple workers (once listening - only one made any work). If someone needs a git version of it: https://github.com/sebres/nginx/pull/1/files [1] Here [2] you may find a benchmark comparison for that (1 worker column - measured before fix). -- Shortly about fix algorithm (changes related are marked as [*], unchanged - [-]): - master process create all listener; - [cycle] master process create a worker; * [win32] master calls `ngx_share_listening_sockets`: each listener share (inheritance) info for pid of this worker ("cloned" via WSADuplicateSocket), that will be saved in shmem; - master process wait until worker will send an event "worker_nnn"; * [win32] worker process executes `ngx_get_listening_share_info` to obtain shared info, protocol structure that can be used to create a new socket descriptor for a shared socket; * [win32] worker process creates all listener sockets using given shared info of master; - worker process sets an event "worker_nnn"; - master process create next worker, repeat [cycle]. -- @Maxim Dounin: 1) your suggested way with shared handle and bInheritHandle does not work, because of: [quote] Sockets. No error is returned, but the duplicate handle may not be recognized by Winsock at the target process. Also, using DUPLICATEHANDLE interferes with internal reference counting on the underlying object. To duplicate a socket handle, use the WSADUPLICATESOCKET function. [/quote] 2) proposal to use an environment instead of shared memory can not work also, because sharing via WSADuplicateSocket should already know a pid of target process, that uses this handle - specially shared for each worker. BTW, using of `accept_mutex` was disallowed for win32, cause of possible deadlock if grabbed by a process which can't accept connections. Because, this is fixed now, I have removed this "restriction" in separated commit. But I think, accept_mutex is not needed in win32 resp. with accept_mutex it is much slower as without him. So, whats about set default of `accept_mutex` to `off` on windows platform? BTW[2], I have executed extensive tests of this fix, also with reloading (increase/decrease `worker_processes`), restarting, as well as auto-restarting of worker, if it was "crashed" (ex.: have sporadically killed some worker). Regards, Serg G. Brester (aka sebres). Links: ------ [1] https://github.com/sebres/nginx/pull/1/files [2] https://github.com/sebres/nginx/pull/1 -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: _sb-win-multi-worker.patch Type: text/x-diff Size: 13065 bytes Desc: not available URL: From piotr at cloudflare.com Thu Jun 11 02:19:29 2015 From: piotr at cloudflare.com (Piotr Sikora) Date: Wed, 10 Jun 2015 19:19:29 -0700 Subject: [PATCH 1 of 2] Configure: fix tests with multi-level relative build directory Message-ID: <4ee03ff4811708bafd07.1433989169@piotrs-macbook-pro.local> # HG changeset patch # User Piotr Sikora # Date 1433989099 25200 # Wed Jun 10 19:18:19 2015 -0700 # Node ID 4ee03ff4811708bafd07e84c5a71165a52b38299 # Parent c041f1e0655f786db5cf1a3e79ca1f464fec0258 Configure: fix tests with multi-level relative build directory. Signed-off-by: Piotr Sikora diff -r c041f1e0655f -r 4ee03ff48117 auto/unix --- a/auto/unix Wed Jun 10 19:18:20 2015 +0300 +++ b/auto/unix Wed Jun 10 19:18:19 2015 -0700 @@ -510,7 +510,7 @@ case "$NGX_AUTO_CONFIG_H" in NGX_INCLUDE_AUTO_CONFIG_H="#include \"$NGX_AUTO_CONFIG_H\"" ;; *) - NGX_INCLUDE_AUTO_CONFIG_H="#include \"../$NGX_AUTO_CONFIG_H\"" + NGX_INCLUDE_AUTO_CONFIG_H="#include \"$PWD/$NGX_AUTO_CONFIG_H\"" ;; esac From piotr at cloudflare.com Thu Jun 11 02:19:30 2015 From: piotr at cloudflare.com (Piotr Sikora) Date: Wed, 10 Jun 2015 19:19:30 -0700 Subject: [PATCH 2 of 2] Configure: create missing intermediates for build directory In-Reply-To: <4ee03ff4811708bafd07.1433989169@piotrs-macbook-pro.local> References: <4ee03ff4811708bafd07.1433989169@piotrs-macbook-pro.local> Message-ID: # HG changeset patch # User Piotr Sikora # Date 1433989099 25200 # Wed Jun 10 19:18:19 2015 -0700 # Node ID f160d72d2dadc117b8e2dc25eca3d39a346a8eb8 # Parent 4ee03ff4811708bafd07e84c5a71165a52b38299 Configure: create missing intermediates for build directory. Signed-off-by: Piotr Sikora diff -r 4ee03ff48117 -r f160d72d2dad auto/configure --- a/auto/configure Wed Jun 10 19:18:19 2015 -0700 +++ b/auto/configure Wed Jun 10 19:18:19 2015 -0700 @@ -11,7 +11,7 @@ export LC_ALL . auto/init . auto/sources -test -d $NGX_OBJS || mkdir $NGX_OBJS +test -d $NGX_OBJS || mkdir -p $NGX_OBJS echo > $NGX_AUTO_HEADERS_H echo > $NGX_AUTOCONF_ERR From ru at nginx.com Thu Jun 11 08:51:57 2015 From: ru at nginx.com (Ruslan Ermilov) Date: Thu, 11 Jun 2015 11:51:57 +0300 Subject: [PATCH 1 of 2] Configure: fix tests with multi-level relative build directory In-Reply-To: <4ee03ff4811708bafd07.1433989169@piotrs-macbook-pro.local> References: <4ee03ff4811708bafd07.1433989169@piotrs-macbook-pro.local> Message-ID: <20150611085157.GE42406@lo0.su> On Wed, Jun 10, 2015 at 07:19:29PM -0700, Piotr Sikora wrote: > # HG changeset patch > # User Piotr Sikora > # Date 1433989099 25200 > # Wed Jun 10 19:18:19 2015 -0700 > # Node ID 4ee03ff4811708bafd07e84c5a71165a52b38299 > # Parent c041f1e0655f786db5cf1a3e79ca1f464fec0258 > Configure: fix tests with multi-level relative build directory. > > Signed-off-by: Piotr Sikora > > diff -r c041f1e0655f -r 4ee03ff48117 auto/unix > --- a/auto/unix Wed Jun 10 19:18:20 2015 +0300 > +++ b/auto/unix Wed Jun 10 19:18:19 2015 -0700 > @@ -510,7 +510,7 @@ case "$NGX_AUTO_CONFIG_H" in > NGX_INCLUDE_AUTO_CONFIG_H="#include \"$NGX_AUTO_CONFIG_H\"" > ;; > *) > - NGX_INCLUDE_AUTO_CONFIG_H="#include \"../$NGX_AUTO_CONFIG_H\"" > + NGX_INCLUDE_AUTO_CONFIG_H="#include \"$PWD/$NGX_AUTO_CONFIG_H\"" > ;; > esac How's this instead? diff --git a/auto/unix b/auto/unix --- a/auto/unix +++ b/auto/unix @@ -505,14 +505,7 @@ ngx_param=NGX_PTR_SIZE; ngx_value=$ngx_s # POSIX types -case "$NGX_AUTO_CONFIG_H" in - /*) - NGX_INCLUDE_AUTO_CONFIG_H="#include \"$NGX_AUTO_CONFIG_H\"" - ;; - *) - NGX_INCLUDE_AUTO_CONFIG_H="#include \"../$NGX_AUTO_CONFIG_H\"" - ;; -esac +NGX_INCLUDE_AUTO_CONFIG_H="#include \"ngx_auto_config.h\"" ngx_type="uint64_t"; ngx_types="u_int64_t"; . auto/types/typedef From ru at nginx.com Thu Jun 11 08:52:22 2015 From: ru at nginx.com (Ruslan Ermilov) Date: Thu, 11 Jun 2015 11:52:22 +0300 Subject: [PATCH 2 of 2] Configure: create missing intermediates for build directory In-Reply-To: References: <4ee03ff4811708bafd07.1433989169@piotrs-macbook-pro.local> Message-ID: <20150611085222.GF42406@lo0.su> On Wed, Jun 10, 2015 at 07:19:30PM -0700, Piotr Sikora wrote: > # HG changeset patch > # User Piotr Sikora > # Date 1433989099 25200 > # Wed Jun 10 19:18:19 2015 -0700 > # Node ID f160d72d2dadc117b8e2dc25eca3d39a346a8eb8 > # Parent 4ee03ff4811708bafd07e84c5a71165a52b38299 > Configure: create missing intermediates for build directory. > > Signed-off-by: Piotr Sikora > > diff -r 4ee03ff48117 -r f160d72d2dad auto/configure > --- a/auto/configure Wed Jun 10 19:18:19 2015 -0700 > +++ b/auto/configure Wed Jun 10 19:18:19 2015 -0700 > @@ -11,7 +11,7 @@ export LC_ALL > . auto/init > . auto/sources > > -test -d $NGX_OBJS || mkdir $NGX_OBJS > +test -d $NGX_OBJS || mkdir -p $NGX_OBJS > > echo > $NGX_AUTO_HEADERS_H > echo > $NGX_AUTOCONF_ERR Looks good. From piotr at cloudflare.com Thu Jun 11 10:43:55 2015 From: piotr at cloudflare.com (Piotr Sikora) Date: Thu, 11 Jun 2015 03:43:55 -0700 Subject: [PATCH 1 of 2] Configure: fix tests with multi-level relative build directory In-Reply-To: <20150611085157.GE42406@lo0.su> References: <4ee03ff4811708bafd07.1433989169@piotrs-macbook-pro.local> <20150611085157.GE42406@lo0.su> Message-ID: Hey Ruslan, > How's this instead? > > diff --git a/auto/unix b/auto/unix > --- a/auto/unix > +++ b/auto/unix > @@ -505,14 +505,7 @@ ngx_param=NGX_PTR_SIZE; ngx_value=$ngx_s > > # POSIX types > > -case "$NGX_AUTO_CONFIG_H" in > - /*) > - NGX_INCLUDE_AUTO_CONFIG_H="#include \"$NGX_AUTO_CONFIG_H\"" > - ;; > - *) > - NGX_INCLUDE_AUTO_CONFIG_H="#include \"../$NGX_AUTO_CONFIG_H\"" > - ;; > -esac > +NGX_INCLUDE_AUTO_CONFIG_H="#include \"ngx_auto_config.h\"" > > ngx_type="uint64_t"; ngx_types="u_int64_t"; . auto/types/typedef Works for me :) Best regards, Piotr Sikora From serg.brester at sebres.de Thu Jun 11 13:03:34 2015 From: serg.brester at sebres.de (Sergey Brester) Date: Thu, 11 Jun 2015 15:03:34 +0200 Subject: Fix windows issue with multiple workers In-Reply-To: <64cd3e82b8271b1240c588dc6fece3bb@sebres.de> References: <64cd3e82b8271b1240c588dc6fece3bb@sebres.de> Message-ID: <9366842bbb332d4b9dafdd7ba4c01742@sebres.de> Hi, I've forgotten to free the shmem, thus enclosed an amendment with clean-up, relative last changeset. Regards, sebres. 10.06.2015 21:48, Sergey Brester: > Hi, > > enclosed you will find an attached changeset, that contains fix for windows issue with multiple workers (once listening - only one made any work). > > If someone needs a git version of it: > > https://github.com/sebres/nginx/pull/1/files [2] > > Here [3] you may find a benchmark comparison for that (1 worker column - measured before fix). > > -- > > Shortly about fix algorithm (changes related are marked as [*], unchanged - [-]): > > - master process create all listener; > > - [cycle] master process create a worker; > > * [win32] master calls `ngx_share_listening_sockets`: each listener share (inheritance) info for pid of this worker ("cloned" via WSADuplicateSocket), that will be saved in shmem; > > - master process wait until worker will send an event "worker_nnn"; > > * [win32] worker process executes `ngx_get_listening_share_info` to obtain shared info, protocol structure that can be used to create a new socket descriptor for a shared socket; > > * [win32] worker process creates all listener sockets using given shared info of master; > > - worker process sets an event "worker_nnn"; > > - master process create next worker, repeat [cycle]. > > -- > > @Maxim Dounin: > 1) your suggested way with shared handle and bInheritHandle does not work, because of: > [quote] > Sockets. No error is returned, but the duplicate handle may not be recognized by Winsock at the target process. Also, using DUPLICATEHANDLE interferes with internal reference counting on the underlying object. > To duplicate a socket handle, use the WSADUPLICATESOCKET function. > [/quote] > > 2) proposal to use an environment instead of shared memory can not work also, because sharing via WSADuplicateSocket should already know a pid of target process, that uses this handle - specially shared for each worker. > > BTW, using of `accept_mutex` was disallowed for win32, cause of possible deadlock if grabbed by a process which can't accept connections. Because, this is fixed now, I have removed this "restriction" in separated commit. > But I think, accept_mutex is not needed in win32 resp. with accept_mutex it is much slower as without him. So, whats about set default of `accept_mutex` to `off` on windows platform? > > BTW[2], I have executed extensive tests of this fix, also with reloading (increase/decrease `worker_processes`), restarting, as well as auto-restarting of worker, if it was "crashed" (ex.: have sporadically killed some worker). > > Regards, > Serg G. Brester (aka sebres). > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel [1] Links: ------ [1] http://mailman.nginx.org/mailman/listinfo/nginx-devel [2] https://github.com/sebres/nginx/pull/1/files [3] https://github.com/sebres/nginx/pull/1 -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: _sb-win-multi-worker-add-2.patch Type: text/x-diff Size: 2093 bytes Desc: not available URL: From mdounin at mdounin.ru Thu Jun 11 14:18:16 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 11 Jun 2015 17:18:16 +0300 Subject: [PATCH 1 of 2] Configure: fix tests with multi-level relative build directory In-Reply-To: <20150611085157.GE42406@lo0.su> References: <4ee03ff4811708bafd07.1433989169@piotrs-macbook-pro.local> <20150611085157.GE42406@lo0.su> Message-ID: <20150611141816.GH26357@mdounin.ru> Hello! On Thu, Jun 11, 2015 at 11:51:57AM +0300, Ruslan Ermilov wrote: > On Wed, Jun 10, 2015 at 07:19:29PM -0700, Piotr Sikora wrote: > > # HG changeset patch > > # User Piotr Sikora > > # Date 1433989099 25200 > > # Wed Jun 10 19:18:19 2015 -0700 > > # Node ID 4ee03ff4811708bafd07e84c5a71165a52b38299 > > # Parent c041f1e0655f786db5cf1a3e79ca1f464fec0258 > > Configure: fix tests with multi-level relative build directory. > > > > Signed-off-by: Piotr Sikora > > > > diff -r c041f1e0655f -r 4ee03ff48117 auto/unix > > --- a/auto/unix Wed Jun 10 19:18:20 2015 +0300 > > +++ b/auto/unix Wed Jun 10 19:18:19 2015 -0700 > > @@ -510,7 +510,7 @@ case "$NGX_AUTO_CONFIG_H" in > > NGX_INCLUDE_AUTO_CONFIG_H="#include \"$NGX_AUTO_CONFIG_H\"" > > ;; > > *) > > - NGX_INCLUDE_AUTO_CONFIG_H="#include \"../$NGX_AUTO_CONFIG_H\"" > > + NGX_INCLUDE_AUTO_CONFIG_H="#include \"$PWD/$NGX_AUTO_CONFIG_H\"" > > ;; > > esac > > How's this instead? > > diff --git a/auto/unix b/auto/unix > --- a/auto/unix > +++ b/auto/unix > @@ -505,14 +505,7 @@ ngx_param=NGX_PTR_SIZE; ngx_value=$ngx_s > > # POSIX types > > -case "$NGX_AUTO_CONFIG_H" in > - /*) > - NGX_INCLUDE_AUTO_CONFIG_H="#include \"$NGX_AUTO_CONFIG_H\"" > - ;; > - *) > - NGX_INCLUDE_AUTO_CONFIG_H="#include \"../$NGX_AUTO_CONFIG_H\"" > - ;; > -esac > +NGX_INCLUDE_AUTO_CONFIG_H="#include \"ngx_auto_config.h\"" > > ngx_type="uint64_t"; ngx_types="u_int64_t"; . auto/types/typedef Shouldn't it be just a string in auto/types/sizeof then? -- Maxim Dounin http://nginx.org/ From piotr at cloudflare.com Thu Jun 11 18:33:58 2015 From: piotr at cloudflare.com (Piotr Sikora) Date: Thu, 11 Jun 2015 11:33:58 -0700 Subject: [PATCH 1 of 2] Configure: fix tests with multi-level relative build directory In-Reply-To: <20150611141816.GH26357@mdounin.ru> References: <4ee03ff4811708bafd07.1433989169@piotrs-macbook-pro.local> <20150611085157.GE42406@lo0.su> <20150611141816.GH26357@mdounin.ru> Message-ID: Hey Maxim, > Shouldn't it be just a string in auto/types/sizeof then? That was my original thought as well, but maybe there are nginx+ or 3rd-party modules that rely on NGX_INCLUDE_AUTO_CONFIG_H? I'm not sure whether it should make a difference, really. Best regards, Piotr Sikora From mdounin at mdounin.ru Thu Jun 11 18:56:42 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 11 Jun 2015 18:56:42 +0000 Subject: [nginx] Removed unused ngx_http_get_time() declaration. Message-ID: details: http://hg.nginx.org/nginx/rev/c61210e2e081 branches: changeset: 6179:c61210e2e081 user: Maxim Dounin date: Thu Jun 11 20:42:24 2015 +0300 description: Removed unused ngx_http_get_time() declaration. diffstat: src/http/ngx_http.h | 2 -- 1 files changed, 0 insertions(+), 2 deletions(-) diffs (12 lines): diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h --- a/src/http/ngx_http.h +++ b/src/http/ngx_http.h @@ -149,8 +149,6 @@ void ngx_http_clean_header(ngx_http_requ time_t ngx_http_parse_time(u_char *value, size_t len); -size_t ngx_http_get_time(char *buf, time_t t); - ngx_int_t ngx_http_discard_request_body(ngx_http_request_t *r); From mdounin at mdounin.ru Thu Jun 11 18:56:45 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 11 Jun 2015 18:56:45 +0000 Subject: [nginx] Moved ngx_http_parse_time() to core, renamed accordingly. Message-ID: details: http://hg.nginx.org/nginx/rev/8b6fa4842133 branches: changeset: 6180:8b6fa4842133 user: Maxim Dounin date: Thu Jun 11 20:42:31 2015 +0300 description: Moved ngx_http_parse_time() to core, renamed accordingly. The function is now called ngx_parse_http_time(), and can be used by any code to parse HTTP-style date and time. In particular, it will be used for OCSP stapling. For compatibility, a macro to map ngx_http_parse_time() to the new name provided for a while. diffstat: auto/sources | 3 +- src/core/ngx_core.h | 1 + src/core/ngx_parse_time.c | 3 +- src/core/ngx_parse_time.h | 22 ++++++++++++++++++ src/http/modules/ngx_http_dav_module.c | 2 +- src/http/modules/ngx_http_headers_filter_module.c | 2 +- src/http/modules/ngx_http_not_modified_filter_module.c | 4 +- src/http/modules/ngx_http_range_filter_module.c | 2 +- src/http/ngx_http.h | 3 -- src/http/ngx_http_core_module.c | 4 +- src/http/ngx_http_upstream.c | 6 ++-- 11 files changed, 36 insertions(+), 16 deletions(-) diffs (206 lines): diff --git a/auto/sources b/auto/sources --- a/auto/sources +++ b/auto/sources @@ -19,6 +19,7 @@ CORE_DEPS="src/core/nginx.h \ src/core/ngx_queue.h \ src/core/ngx_string.h \ src/core/ngx_parse.h \ + src/core/ngx_parse_time.h \ src/core/ngx_inet.h \ src/core/ngx_file.h \ src/core/ngx_crc.h \ @@ -53,6 +54,7 @@ CORE_SRCS="src/core/nginx.c \ src/core/ngx_output_chain.c \ src/core/ngx_string.c \ src/core/ngx_parse.c \ + src/core/ngx_parse_time.c \ src/core/ngx_inet.c \ src/core/ngx_file.c \ src/core/ngx_crc32.c \ @@ -303,7 +305,6 @@ HTTP_SRCS="src/http/ngx_http.c \ src/http/ngx_http_script.c \ src/http/ngx_http_upstream.c \ src/http/ngx_http_upstream_round_robin.c \ - src/http/ngx_http_parse_time.c \ src/http/modules/ngx_http_static_module.c \ src/http/modules/ngx_http_index_module.c \ src/http/modules/ngx_http_chunked_filter_module.c \ diff --git a/src/core/ngx_core.h b/src/core/ngx_core.h --- a/src/core/ngx_core.h +++ b/src/core/ngx_core.h @@ -54,6 +54,7 @@ typedef void (*ngx_connection_handler_pt #include #include #include +#include #include #include #include diff --git a/src/http/ngx_http_parse_time.c b/src/core/ngx_parse_time.c rename from src/http/ngx_http_parse_time.c rename to src/core/ngx_parse_time.c --- a/src/http/ngx_http_parse_time.c +++ b/src/core/ngx_parse_time.c @@ -7,13 +7,12 @@ #include #include -#include static ngx_uint_t mday[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; time_t -ngx_http_parse_time(u_char *value, size_t len) +ngx_parse_http_time(u_char *value, size_t len) { u_char *p, *end; ngx_int_t month; diff --git a/src/core/ngx_parse_time.h b/src/core/ngx_parse_time.h new file mode 100644 --- /dev/null +++ b/src/core/ngx_parse_time.h @@ -0,0 +1,22 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_PARSE_TIME_H_INCLUDED_ +#define _NGX_PARSE_TIME_H_INCLUDED_ + + +#include +#include + + +time_t ngx_parse_http_time(u_char *value, size_t len); + +/* compatibility */ +#define ngx_http_parse_time(value, len) ngx_parse_http_time(value, len) + + +#endif /* _NGX_PARSE_TIME_H_INCLUDED_ */ diff --git a/src/http/modules/ngx_http_dav_module.c b/src/http/modules/ngx_http_dav_module.c --- a/src/http/modules/ngx_http_dav_module.c +++ b/src/http/modules/ngx_http_dav_module.c @@ -255,7 +255,7 @@ ngx_http_dav_put_handler(ngx_http_reques ext.log = r->connection->log; if (r->headers_in.date) { - date = ngx_http_parse_time(r->headers_in.date->value.data, + date = ngx_parse_http_time(r->headers_in.date->value.data, r->headers_in.date->value.len); if (date != NGX_ERROR) { diff --git a/src/http/modules/ngx_http_headers_filter_module.c b/src/http/modules/ngx_http_headers_filter_module.c --- a/src/http/modules/ngx_http_headers_filter_module.c +++ b/src/http/modules/ngx_http_headers_filter_module.c @@ -498,7 +498,7 @@ ngx_http_set_last_modified(ngx_http_requ } r->headers_out.last_modified_time = - (value->len) ? ngx_http_parse_time(value->data, value->len) : -1; + (value->len) ? ngx_parse_http_time(value->data, value->len) : -1; return NGX_OK; } diff --git a/src/http/modules/ngx_http_not_modified_filter_module.c b/src/http/modules/ngx_http_not_modified_filter_module.c --- a/src/http/modules/ngx_http_not_modified_filter_module.c +++ b/src/http/modules/ngx_http_not_modified_filter_module.c @@ -118,7 +118,7 @@ ngx_http_test_if_unmodified(ngx_http_req return 0; } - iums = ngx_http_parse_time(r->headers_in.if_unmodified_since->value.data, + iums = ngx_parse_http_time(r->headers_in.if_unmodified_since->value.data, r->headers_in.if_unmodified_since->value.len); ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, @@ -148,7 +148,7 @@ ngx_http_test_if_modified(ngx_http_reque return 1; } - ims = ngx_http_parse_time(r->headers_in.if_modified_since->value.data, + ims = ngx_parse_http_time(r->headers_in.if_modified_since->value.data, r->headers_in.if_modified_since->value.len); ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, diff --git a/src/http/modules/ngx_http_range_filter_module.c b/src/http/modules/ngx_http_range_filter_module.c --- a/src/http/modules/ngx_http_range_filter_module.c +++ b/src/http/modules/ngx_http_range_filter_module.c @@ -204,7 +204,7 @@ ngx_http_range_header_filter(ngx_http_re goto next_filter; } - if_range_time = ngx_http_parse_time(if_range->data, if_range->len); + if_range_time = ngx_parse_http_time(if_range->data, if_range->len); ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http ir:%d lm:%d", diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h --- a/src/http/ngx_http.h +++ b/src/http/ngx_http.h @@ -148,9 +148,6 @@ ngx_int_t ngx_http_filter_finalize_reque void ngx_http_clean_header(ngx_http_request_t *r); -time_t ngx_http_parse_time(u_char *value, size_t len); - - ngx_int_t ngx_http_discard_request_body(ngx_http_request_t *r); void ngx_http_discarded_request_body_handler(ngx_http_request_t *r); void ngx_http_block_reading(ngx_http_request_t *r); diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -2195,7 +2195,7 @@ ngx_http_gzip_ok(ngx_http_request_t *r) return NGX_DECLINED; } - expires = ngx_http_parse_time(e->value.data, e->value.len); + expires = ngx_parse_http_time(e->value.data, e->value.len); if (expires == NGX_ERROR) { return NGX_DECLINED; } @@ -2203,7 +2203,7 @@ ngx_http_gzip_ok(ngx_http_request_t *r) d = r->headers_out.date; if (d) { - date = ngx_http_parse_time(d->value.data, d->value.len); + date = ngx_parse_http_time(d->value.data, d->value.len); if (date == NGX_ERROR) { return NGX_DECLINED; } diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -3731,7 +3731,7 @@ ngx_http_upstream_store(ngx_http_request if (u->headers_in.last_modified) { - lm = ngx_http_parse_time(u->headers_in.last_modified->value.data, + lm = ngx_parse_http_time(u->headers_in.last_modified->value.data, u->headers_in.last_modified->value.len); if (lm != NGX_ERROR) { @@ -4128,7 +4128,7 @@ ngx_http_upstream_process_last_modified( #if (NGX_HTTP_CACHE) if (u->cacheable) { - u->headers_in.last_modified_time = ngx_http_parse_time(h->value.data, + u->headers_in.last_modified_time = ngx_parse_http_time(h->value.data, h->value.len); } @@ -4292,7 +4292,7 @@ ngx_http_upstream_process_expires(ngx_ht return NGX_OK; } - expires = ngx_http_parse_time(h->value.data, h->value.len); + expires = ngx_parse_http_time(h->value.data, h->value.len); if (expires == NGX_ERROR || expires < ngx_time()) { u->cacheable = 0; From mdounin at mdounin.ru Thu Jun 11 18:56:47 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 11 Jun 2015 18:56:47 +0000 Subject: [nginx] OCSP stapling: avoid sending expired responses (ticket #... Message-ID: details: http://hg.nginx.org/nginx/rev/6893a1007a7c branches: changeset: 6181:6893a1007a7c user: Maxim Dounin date: Thu Jun 11 20:42:39 2015 +0300 description: OCSP stapling: avoid sending expired responses (ticket #425). diffstat: src/event/ngx_event_openssl_stapling.c | 68 +++++++++++++++++++++++++++++++--- 1 files changed, 62 insertions(+), 6 deletions(-) diffs (154 lines): diff --git a/src/event/ngx_event_openssl_stapling.c b/src/event/ngx_event_openssl_stapling.c --- a/src/event/ngx_event_openssl_stapling.c +++ b/src/event/ngx_event_openssl_stapling.c @@ -32,6 +32,7 @@ typedef struct { X509 *issuer; time_t valid; + time_t refresh; unsigned verify:1; unsigned loading:1; @@ -93,6 +94,8 @@ static int ngx_ssl_certificate_status_ca static void ngx_ssl_stapling_update(ngx_ssl_stapling_t *staple); static void ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx); +static time_t ngx_ssl_stapling_time(ASN1_GENERALIZEDTIME *asn1time); + static void ngx_ssl_stapling_cleanup(void *data); static ngx_ssl_ocsp_ctx_t *ngx_ssl_ocsp_start(void); @@ -462,7 +465,9 @@ ngx_ssl_certificate_status_callback(ngx_ staple = data; rc = SSL_TLSEXT_ERR_NOACK; - if (staple->staple.len) { + if (staple->staple.len + && staple->valid >= ngx_time()) + { /* we have to copy ocsp response as OpenSSL will free it by itself */ p = OPENSSL_malloc(staple->staple.len); @@ -490,7 +495,7 @@ ngx_ssl_stapling_update(ngx_ssl_stapling ngx_ssl_ocsp_ctx_t *ctx; if (staple->host.len == 0 - || staple->loading || staple->valid >= ngx_time()) + || staple->loading || staple->refresh >= ngx_time()) { return; } @@ -532,6 +537,7 @@ ngx_ssl_stapling_ocsp_handler(ngx_ssl_oc u_char *p; int n; size_t len; + time_t now, valid; ngx_str_t response; X509_STORE *store; STACK_OF(X509) *chain; @@ -542,6 +548,7 @@ ngx_ssl_stapling_ocsp_handler(ngx_ssl_oc ASN1_GENERALIZEDTIME *thisupdate, *nextupdate; staple = ctx->data; + now = ngx_time(); ocsp = NULL; basic = NULL; id = NULL; @@ -629,17 +636,28 @@ ngx_ssl_stapling_ocsp_handler(ngx_ssl_oc goto error; } + valid = ngx_ssl_stapling_time(nextupdate); + if (valid == (time_t) NGX_ERROR) { + ngx_log_error(NGX_LOG_ERR, ctx->log, 0, + "invalid nextUpdate time in certificate status"); + goto error; + } + OCSP_CERTID_free(id); OCSP_BASICRESP_free(basic); OCSP_RESPONSE_free(ocsp); + id = NULL; + basic = NULL; + ocsp = NULL; + /* copy the response to memory not in ctx->pool */ response.len = len; response.data = ngx_alloc(response.len, ctx->log); if (response.data == NULL) { - goto done; + goto error; } ngx_memcpy(response.data, ctx->response->pos, response.len); @@ -653,11 +671,15 @@ ngx_ssl_stapling_ocsp_handler(ngx_ssl_oc } staple->staple = response; + staple->valid = valid; -done: + /* + * refresh before the response expires, + * but not earlier than in 5 minutes, and at least in an hour + */ staple->loading = 0; - staple->valid = ngx_time() + 3600; /* ssl_stapling_valid */ + staple->refresh = ngx_max(ngx_min(valid - 300, now + 3600), now + 300); ngx_ssl_ocsp_done(ctx); return; @@ -665,7 +687,7 @@ done: error: staple->loading = 0; - staple->valid = ngx_time() + 300; /* ssl_stapling_err_valid */ + staple->refresh = now + 300; if (id) { OCSP_CERTID_free(id); @@ -683,6 +705,40 @@ error: } +static time_t +ngx_ssl_stapling_time(ASN1_GENERALIZEDTIME *asn1time) +{ + u_char *value; + size_t len; + time_t time; + BIO *bio; + + /* + * OpenSSL doesn't provide a way to convert ASN1_GENERALIZEDTIME + * into time_t. To do this, we use ASN1_GENERALIZEDTIME_print(), + * which uses the "MMM DD HH:MM:SS YYYY [GMT]" format (e.g., + * "Feb 3 00:55:52 2015 GMT"), and parse the result. + */ + + bio = BIO_new(BIO_s_mem()); + if (bio == NULL) { + return NGX_ERROR; + } + + /* fake weekday prepended to match C asctime() format */ + + BIO_write(bio, "Tue ", sizeof("Tue ") - 1); + ASN1_GENERALIZEDTIME_print(bio, asn1time); + len = BIO_get_mem_data(bio, &value); + + time = ngx_parse_http_time(value, len); + + BIO_free(bio); + + return time; +} + + static void ngx_ssl_stapling_cleanup(void *data) { From ru at nginx.com Thu Jun 11 20:29:38 2015 From: ru at nginx.com (Ruslan Ermilov) Date: Thu, 11 Jun 2015 23:29:38 +0300 Subject: [PATCH 1 of 2] Configure: fix tests with multi-level relative build directory In-Reply-To: <20150611141816.GH26357@mdounin.ru> References: <4ee03ff4811708bafd07.1433989169@piotrs-macbook-pro.local> <20150611085157.GE42406@lo0.su> <20150611141816.GH26357@mdounin.ru> Message-ID: <20150611202938.GJ42406@lo0.su> On Thu, Jun 11, 2015 at 05:18:16PM +0300, Maxim Dounin wrote: > On Thu, Jun 11, 2015 at 11:51:57AM +0300, Ruslan Ermilov wrote: > > > On Wed, Jun 10, 2015 at 07:19:29PM -0700, Piotr Sikora wrote: > > > # HG changeset patch > > > # User Piotr Sikora > > > # Date 1433989099 25200 > > > # Wed Jun 10 19:18:19 2015 -0700 > > > # Node ID 4ee03ff4811708bafd07e84c5a71165a52b38299 > > > # Parent c041f1e0655f786db5cf1a3e79ca1f464fec0258 > > > Configure: fix tests with multi-level relative build directory. > > > > > > Signed-off-by: Piotr Sikora > > > > > > diff -r c041f1e0655f -r 4ee03ff48117 auto/unix > > > --- a/auto/unix Wed Jun 10 19:18:20 2015 +0300 > > > +++ b/auto/unix Wed Jun 10 19:18:19 2015 -0700 > > > @@ -510,7 +510,7 @@ case "$NGX_AUTO_CONFIG_H" in > > > NGX_INCLUDE_AUTO_CONFIG_H="#include \"$NGX_AUTO_CONFIG_H\"" > > > ;; > > > *) > > > - NGX_INCLUDE_AUTO_CONFIG_H="#include \"../$NGX_AUTO_CONFIG_H\"" > > > + NGX_INCLUDE_AUTO_CONFIG_H="#include \"$PWD/$NGX_AUTO_CONFIG_H\"" > > > ;; > > > esac > > > > How's this instead? > > > > diff --git a/auto/unix b/auto/unix > > --- a/auto/unix > > +++ b/auto/unix > > @@ -505,14 +505,7 @@ ngx_param=NGX_PTR_SIZE; ngx_value=$ngx_s > > > > # POSIX types > > > > -case "$NGX_AUTO_CONFIG_H" in > > - /*) > > - NGX_INCLUDE_AUTO_CONFIG_H="#include \"$NGX_AUTO_CONFIG_H\"" > > - ;; > > - *) > > - NGX_INCLUDE_AUTO_CONFIG_H="#include \"../$NGX_AUTO_CONFIG_H\"" > > - ;; > > -esac > > +NGX_INCLUDE_AUTO_CONFIG_H="#include \"ngx_auto_config.h\"" > > > > ngx_type="uint64_t"; ngx_types="u_int64_t"; . auto/types/typedef > > Shouldn't it be just a string in auto/types/sizeof then? Originally I've implemented it exactly like you say, but then thought that I'd probably worth to preserve the optimization -- i.e. we only include ngx_auto_config.h for types that we might have typedef'ed earlier. From mdounin at mdounin.ru Fri Jun 12 00:21:15 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 12 Jun 2015 03:21:15 +0300 Subject: [PATCH 1 of 2] Configure: fix tests with multi-level relative build directory In-Reply-To: <20150611202938.GJ42406@lo0.su> References: <4ee03ff4811708bafd07.1433989169@piotrs-macbook-pro.local> <20150611085157.GE42406@lo0.su> <20150611141816.GH26357@mdounin.ru> <20150611202938.GJ42406@lo0.su> Message-ID: <20150612002115.GI26357@mdounin.ru> Hello! On Thu, Jun 11, 2015 at 11:29:38PM +0300, Ruslan Ermilov wrote: > On Thu, Jun 11, 2015 at 05:18:16PM +0300, Maxim Dounin wrote: > > On Thu, Jun 11, 2015 at 11:51:57AM +0300, Ruslan Ermilov wrote: > > > > > On Wed, Jun 10, 2015 at 07:19:29PM -0700, Piotr Sikora wrote: > > > > # HG changeset patch > > > > # User Piotr Sikora > > > > # Date 1433989099 25200 > > > > # Wed Jun 10 19:18:19 2015 -0700 > > > > # Node ID 4ee03ff4811708bafd07e84c5a71165a52b38299 > > > > # Parent c041f1e0655f786db5cf1a3e79ca1f464fec0258 > > > > Configure: fix tests with multi-level relative build directory. > > > > > > > > Signed-off-by: Piotr Sikora > > > > > > > > diff -r c041f1e0655f -r 4ee03ff48117 auto/unix > > > > --- a/auto/unix Wed Jun 10 19:18:20 2015 +0300 > > > > +++ b/auto/unix Wed Jun 10 19:18:19 2015 -0700 > > > > @@ -510,7 +510,7 @@ case "$NGX_AUTO_CONFIG_H" in > > > > NGX_INCLUDE_AUTO_CONFIG_H="#include \"$NGX_AUTO_CONFIG_H\"" > > > > ;; > > > > *) > > > > - NGX_INCLUDE_AUTO_CONFIG_H="#include \"../$NGX_AUTO_CONFIG_H\"" > > > > + NGX_INCLUDE_AUTO_CONFIG_H="#include \"$PWD/$NGX_AUTO_CONFIG_H\"" > > > > ;; > > > > esac > > > > > > How's this instead? > > > > > > diff --git a/auto/unix b/auto/unix > > > --- a/auto/unix > > > +++ b/auto/unix > > > @@ -505,14 +505,7 @@ ngx_param=NGX_PTR_SIZE; ngx_value=$ngx_s > > > > > > # POSIX types > > > > > > -case "$NGX_AUTO_CONFIG_H" in > > > - /*) > > > - NGX_INCLUDE_AUTO_CONFIG_H="#include \"$NGX_AUTO_CONFIG_H\"" > > > - ;; > > > - *) > > > - NGX_INCLUDE_AUTO_CONFIG_H="#include \"../$NGX_AUTO_CONFIG_H\"" > > > - ;; > > > -esac > > > +NGX_INCLUDE_AUTO_CONFIG_H="#include \"ngx_auto_config.h\"" > > > > > > ngx_type="uint64_t"; ngx_types="u_int64_t"; . auto/types/typedef > > > > Shouldn't it be just a string in auto/types/sizeof then? > > Originally I've implemented it exactly like you say, > but then thought that I'd probably worth to preserve > the optimization -- i.e. we only include ngx_auto_config.h > for types that we might have typedef'ed earlier. Well, I'm fine either way. Feel free to commit. -- Maxim Dounin http://nginx.org/ From savetherbtz at gmail.com Fri Jun 12 10:26:04 2015 From: savetherbtz at gmail.com (Alexey Ivanov) Date: Fri, 12 Jun 2015 03:26:04 -0700 Subject: Error counters in nginx Message-ID: Hi. I have a feature request: from system administrator point of view it would be nice to have counters for each type of error log message. For example right now nginx error.log consists of myriad of different error message formats: open() ?%s? failed directory index of ?%s? is forbidden SSL_write() failed SSL_do_handshake() zero size but in output chain client intended to send too large body To plot that stuff on a dashboard sysadmin needs to increase error_log verbosity, write custom daemon that tails it and then manually write parser for every ?interesting? log entry. It would be nice if `ngx_log_error()` did all that work for us. So that one could just specify following config: location /error_status { error_status_format csv; error_status; } and then following command? $ curl localhost/error_status ...would return: core.zero_size_buf,2 http.module.autoindex.open.failed,3 http.core.directory_listing_forbidden,5 http.core.body_too_large,7 ssl.alerts.downstream.recv.certificate_expired,11 ssl.alerts.downstream.sent.close_notify,13 ssl.write.failed,17 ssl.handshake.failed,19 Apache Traffic Server for example has an abstraction for error stats so we quickly implemented statistics for various TLS alerts[1] received from clients/upstreams (after that rolling out of preferred ciphersuite list changes and openssl upgrades became basically painless). FreeBSD for example has a nice kernel API for counters: counter(9)[2]. Similar approach can be applied to nginx: with each worker maintaining it?s counters in separate part of shared memory, so updates to them can be lockless (and even non-atomic because there is no preemption inside one worker). So questions are: * Would Nginx Inc. be interested in adding such functionality? * How much it interferes with Nginx Plus selling points? If somebody else writes that code, will it be possible to "upstream? it? [1] https://issues.apache.org/jira/browse/TS-3007 [2] https://www.freebsd.org/cgi/man.cgi?query=counter&apropos=0&sektion=9&manpath=FreeBSD+11-current&format=html -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 842 bytes Desc: Message signed with OpenPGP using GPGMail URL: From serg.brester at sebres.de Fri Jun 12 10:41:44 2015 From: serg.brester at sebres.de (Sergey Brester) Date: Fri, 12 Jun 2015 12:41:44 +0200 Subject: Fix windows issue with multiple workers In-Reply-To: <9366842bbb332d4b9dafdd7ba4c01742@sebres.de> References: <64cd3e82b8271b1240c588dc6fece3bb@sebres.de> <9366842bbb332d4b9dafdd7ba4c01742@sebres.de> Message-ID: Hi, enclosed a further changeset with "backwards compatibility" to 1 worker processing (without inheritance as before fix), if single worker configured + a little bit code review. P.S. github updated also. Regards, sebres. 11.06.2015 15:03, Sergey Brester: > Hi, > > I've forgotten to free the shmem, thus enclosed an amendment with clean-up, relative last changeset. > > Regards, > sebres. -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: _sb-win-multi-worker-add-3.patch Type: text/x-diff Size: 9107 bytes Desc: not available URL: From 1989.gaurav at googlemail.com Mon Jun 15 06:28:46 2015 From: 1989.gaurav at googlemail.com (gaurav gupta) Date: Mon, 15 Jun 2015 11:58:46 +0530 Subject: Nginx HSM integration for SSL termination Message-ID: Hello Folks, Currently we store ssl private keys in file on production servers. We are looking to move SSL keys to HSM for security reasons so private key never leave HSM. After heart bleed, I found lot of suggestions to move SSL keys to HSM so keys are inaccessible, but could not find any direct integration for nginx. On some search I found Dmitri's patch http://forum.nginx.org/read.php?29,251983,255297#msg-255297 to support engine Keyform to load SSL key. I was able to get it working and work like magic, But as far as I understand its still loaded in memory every time nginx starts. Benefit of loading ssl key from HSM is that key is not stored in plain text file, but its still in memory. Can you please suggest how can we use HSM to perform Asym crypto operations as well so private key never leave HSM. PS: I found accessl https://github.com/gozdal/accessl which makes use of openssl engine mechanism to offload Key storage and crypto operations. -- Thanks & Regards, Gaurav Gupta "Quality is never an accident. It is always result of intelligent effort" - John Ruskin -------------- next part -------------- An HTML attachment was scrubbed... URL: From sorin.v.manole at gmail.com Mon Jun 15 08:20:15 2015 From: sorin.v.manole at gmail.com (Sorin Manole) Date: Mon, 15 Jun 2015 11:20:15 +0300 Subject: Client closed connection: 400 vs 499 Message-ID: Hello, It seems that if the client closes the connection during a requests there are time when the request is logged as 400 and other times as 499. Is there a reason for the difference? Serving of the error page cannot be it because the connection is closed anyway. Thanks. Examples of 400: http://lxr.nginx.org/source/src/http/ngx_http_request.c#1358 ngx_http_read_request_header http://lxr.nginx.org/source/src/http/ngx_http_request_body.c#0289 ngx_http_do_read_client_request_body Examples of 499: http://lxr.nginx.org/source/src/http/ngx_http_request.c#2715 ngx_http_test_reading All closed connection events in ngx_http_upstream.c -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Mon Jun 15 14:12:44 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 15 Jun 2015 17:12:44 +0300 Subject: Nginx HSM integration for SSL termination In-Reply-To: References: Message-ID: <20150615141244.GK26357@mdounin.ru> Hello! On Mon, Jun 15, 2015 at 11:58:46AM +0530, gaurav gupta wrote: > Hello Folks, > > Currently we store ssl private keys in file on production servers. We are > looking to move SSL keys to HSM for security reasons so private key never > leave HSM. After heart bleed, I found lot of suggestions to move SSL keys > to HSM so keys are inaccessible, but could not find any direct integration > for nginx. > > On some search I found Dmitri's patch > http://forum.nginx.org/read.php?29,251983,255297#msg-255297 to support > engine Keyform to load SSL key. I was able to get it working and work like > magic, But as far as I understand its still loaded in memory every time > nginx starts. Benefit of loading ssl key from HSM is that key is not stored > in plain text file, but its still in memory. > > Can you please suggest how can we use HSM to perform Asym crypto operations > as well so private key never leave HSM. > > PS: I found accessl https://github.com/gozdal/accessl which makes use of > openssl engine mechanism to offload Key storage and crypto operations. The patch in question was committed in 1.7.9, and available all recent versions of nginx. It allows to load keys from arbitrary OpenSSL engines, and what "load" means depends on the engine used. That is, it's up to OpenSSL engine to avoid actual loading of keys into memory. -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Mon Jun 15 14:25:51 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 15 Jun 2015 17:25:51 +0300 Subject: Client closed connection: 400 vs 499 In-Reply-To: References: Message-ID: <20150615142550.GM26357@mdounin.ru> Hello! On Mon, Jun 15, 2015 at 11:20:15AM +0300, Sorin Manole wrote: > Hello, > > It seems that if the client closes the connection during a requests there > are time when the request is logged as 400 and other times as 499. > > Is there a reason for the difference? Serving of the error page cannot be > it because the connection is closed anyway. The "400" code means that no correct request was received - that is, client sent a bad request. The "499" code means that nginx got a request, but wasn't able to send a response. That is, client closed connection before we started sending a response. This, in particular, may happen if a backend is slow and nginx isn't able to return a response before the client times out. The difference may be important when looking into logs. -- Maxim Dounin http://nginx.org/ From 1989.gaurav at googlemail.com Mon Jun 15 14:28:27 2015 From: 1989.gaurav at googlemail.com (gaurav gupta) Date: Mon, 15 Jun 2015 19:58:27 +0530 Subject: Nginx HSM integration for SSL termination In-Reply-To: <20150615141244.GK26357@mdounin.ru> References: <20150615141244.GK26357@mdounin.ru> Message-ID: Hello Maxim, Thanks for your prompt response. OpenSSL engine responsible for the behavior makes lot of sense. I am sorry since "pkey = ENGINE_load_private_key(engine, (char *) last, 0, 0);" confused me and made me assume that its getting loaded during startup. I am using engine_pkcs11 to integrate with HSM. I will dive deeper in the engine code to understand and tweak behavior. Thanks again for your help. On Mon, Jun 15, 2015 at 7:42 PM, Maxim Dounin wrote: > Hello! > > On Mon, Jun 15, 2015 at 11:58:46AM +0530, gaurav gupta wrote: > > > Hello Folks, > > > > Currently we store ssl private keys in file on production servers. We are > > looking to move SSL keys to HSM for security reasons so private key never > > leave HSM. After heart bleed, I found lot of suggestions to move SSL keys > > to HSM so keys are inaccessible, but could not find any direct > integration > > for nginx. > > > > On some search I found Dmitri's patch > > http://forum.nginx.org/read.php?29,251983,255297#msg-255297 to support > > engine Keyform to load SSL key. I was able to get it working and work > like > > magic, But as far as I understand its still loaded in memory every time > > nginx starts. Benefit of loading ssl key from HSM is that key is not > stored > > in plain text file, but its still in memory. > > > > Can you please suggest how can we use HSM to perform Asym crypto > operations > > as well so private key never leave HSM. > > > > PS: I found accessl https://github.com/gozdal/accessl which makes use of > > openssl engine mechanism to offload Key storage and crypto operations. > > The patch in question was committed in 1.7.9, and available all > recent versions of nginx. It allows to load keys from arbitrary > OpenSSL engines, and what "load" means depends on the engine used. > That is, it's up to OpenSSL engine to avoid actual loading of keys > into memory. > > -- > Maxim Dounin > http://nginx.org/ > -- Thanks & Regards, Gaurav Gupta 7676-999-350 "Quality is never an accident. It is always result of intelligent effort" - John Ruskin -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Mon Jun 15 17:30:39 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 15 Jun 2015 17:30:39 +0000 Subject: [nginx] Updated OpenSSL used for win32 builds. Message-ID: details: http://hg.nginx.org/nginx/rev/07e416ece597 branches: changeset: 6182:07e416ece597 user: Maxim Dounin date: Mon Jun 15 20:20:12 2015 +0300 description: Updated OpenSSL used for win32 builds. diffstat: misc/GNUmakefile | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff --git a/misc/GNUmakefile b/misc/GNUmakefile --- a/misc/GNUmakefile +++ b/misc/GNUmakefile @@ -5,7 +5,7 @@ NGINX = nginx-$(VER) TEMP = tmp OBJS = objs.msvc8 -OPENSSL = openssl-1.0.1m +OPENSSL = openssl-1.0.1o ZLIB = zlib-1.2.8 PCRE = pcre-8.35 From vl at nginx.com Tue Jun 16 06:04:07 2015 From: vl at nginx.com (Vladimir Homutov) Date: Tue, 16 Jun 2015 06:04:07 +0000 Subject: [nginx] Stream: the "proxy_bind" directive. Message-ID: details: http://hg.nginx.org/nginx/rev/4dcffe43a7ea branches: changeset: 6183:4dcffe43a7ea user: Vladimir Homutov date: Tue Jun 16 09:02:45 2015 +0300 description: Stream: the "proxy_bind" directive. diffstat: src/stream/ngx_stream_proxy_module.c | 57 ++++++++++++++++++++++++++++++++++++ 1 files changed, 57 insertions(+), 0 deletions(-) diffs (106 lines): diff -r 07e416ece597 -r 4dcffe43a7ea src/stream/ngx_stream_proxy_module.c --- a/src/stream/ngx_stream_proxy_module.c Mon Jun 15 20:20:12 2015 +0300 +++ b/src/stream/ngx_stream_proxy_module.c Tue Jun 16 09:02:45 2015 +0300 @@ -21,6 +21,7 @@ typedef struct { size_t upstream_buf_size; ngx_uint_t next_upstream_tries; ngx_flag_t next_upstream; + ngx_addr_t *local; #if (NGX_STREAM_SSL) ngx_flag_t ssl_enable; @@ -64,6 +65,8 @@ static char *ngx_stream_proxy_merge_srv_ void *child); static char *ngx_stream_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +static char *ngx_stream_proxy_bind(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); #if (NGX_STREAM_SSL) @@ -97,6 +100,13 @@ static ngx_command_t ngx_stream_proxy_c 0, NULL }, + { ngx_string("proxy_bind"), + NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, + ngx_stream_proxy_bind, + NGX_STREAM_SRV_CONF_OFFSET, + 0, + NULL }, + { ngx_string("proxy_connect_timeout"), NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, ngx_conf_set_msec_slot, @@ -301,6 +311,8 @@ ngx_stream_proxy_handler(ngx_stream_sess u->peer.log = c->log; u->peer.log_error = NGX_ERROR_ERR; + u->peer.local = pscf->local; + uscf = pscf->upstream; if (uscf->peer.init(s, uscf) != NGX_OK) { @@ -1093,6 +1105,7 @@ ngx_stream_proxy_create_srv_conf(ngx_con conf->upstream_buf_size = NGX_CONF_UNSET_SIZE; conf->next_upstream_tries = NGX_CONF_UNSET_UINT; conf->next_upstream = NGX_CONF_UNSET; + conf->local = NGX_CONF_UNSET_PTR; #if (NGX_STREAM_SSL) conf->ssl_enable = NGX_CONF_UNSET; @@ -1133,6 +1146,8 @@ ngx_stream_proxy_merge_srv_conf(ngx_conf ngx_conf_merge_value(conf->next_upstream, prev->next_upstream, 1); + ngx_conf_merge_ptr_value(conf->local, prev->local, NULL); + #if (NGX_STREAM_SSL) ngx_conf_merge_value(conf->ssl_enable, prev->ssl_enable, 0); @@ -1290,3 +1305,45 @@ ngx_stream_proxy_pass(ngx_conf_t *cf, ng return NGX_CONF_OK; } + + +static char * +ngx_stream_proxy_bind(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_stream_proxy_srv_conf_t *pscf = conf; + + ngx_int_t rc; + ngx_str_t *value; + + if (pscf->local != NGX_CONF_UNSET_PTR) { + return "is duplicate"; + } + + value = cf->args->elts; + + if (ngx_strcmp(value[1].data, "off") == 0) { + pscf->local = NULL; + return NGX_CONF_OK; + } + + pscf->local = ngx_palloc(cf->pool, sizeof(ngx_addr_t)); + if (pscf->local == NULL) { + return NGX_CONF_ERROR; + } + + rc = ngx_parse_addr(cf->pool, pscf->local, value[1].data, value[1].len); + + switch (rc) { + case NGX_OK: + pscf->local->name = value[1]; + return NGX_CONF_OK; + + case NGX_DECLINED: + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid address \"%V\"", &value[1]); + /* fall through */ + + default: + return NGX_CONF_ERROR; + } +} From witekfl at gazeta.pl Tue Jun 16 09:06:50 2015 From: witekfl at gazeta.pl (Witold Filipczyk) Date: Tue, 16 Jun 2015 11:06:50 +0200 Subject: Content-Type Message-ID: <20150616090650.GA2672@fujitsu> Hi, breaks proper Content-Type detection. At least in the 1.6.3 version. From luky-37 at hotmail.com Tue Jun 16 10:37:39 2015 From: luky-37 at hotmail.com (Lukas Tribus) Date: Tue, 16 Jun 2015 12:37:39 +0200 Subject: Content-Type In-Reply-To: <20150616090650.GA2672@fujitsu> References: <20150616090650.GA2672@fujitsu> Message-ID: > Hi, > header('Content-Type: text/html;'); Thats invalid. Either: text/html; charset=iso-8859-1 or text/html but not with a trailing semicolon. > breaks proper Content-Type detection. ... in a Browser, you mean? > At least in the 1.6.3 version. What has nginx to do with it and why is this posted on nginx-devel? Unless you are posting a patch, you should post to the nginx mailing list. Lukas From arut at nginx.com Tue Jun 16 10:47:33 2015 From: arut at nginx.com (Roman Arutyunyan) Date: Tue, 16 Jun 2015 10:47:33 +0000 Subject: [nginx] Stream: client-side PROXY protocol. Message-ID: details: http://hg.nginx.org/nginx/rev/fa663739e115 branches: changeset: 6184:fa663739e115 user: Roman Arutyunyan date: Tue Jun 16 13:45:16 2015 +0300 description: Stream: client-side PROXY protocol. The new directive "proxy_protocol" toggles sending out PROXY protocol header to upstream once connection is established. diffstat: src/core/ngx_proxy_protocol.c | 49 ++++++++++++++ src/core/ngx_proxy_protocol.h | 2 + src/stream/ngx_stream_proxy_module.c | 119 ++++++++++++++++++++++++++++++++++- src/stream/ngx_stream_upstream.h | 2 + 4 files changed, 170 insertions(+), 2 deletions(-) diffs (267 lines): diff -r 4dcffe43a7ea -r fa663739e115 src/core/ngx_proxy_protocol.c --- a/src/core/ngx_proxy_protocol.c Tue Jun 16 09:02:45 2015 +0300 +++ b/src/core/ngx_proxy_protocol.c Tue Jun 16 13:45:16 2015 +0300 @@ -89,3 +89,52 @@ invalid: return NULL; } + + +u_char * +ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf, u_char *last) +{ + ngx_uint_t port, lport; + + if (last - buf < NGX_PROXY_PROTOCOL_MAX_HEADER) { + return NULL; + } + + if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) { + return NULL; + } + + switch (c->sockaddr->sa_family) { + + case AF_INET: + buf = ngx_cpymem(buf, "PROXY TCP4 ", sizeof("PROXY TCP4 ") - 1); + + port = ntohs(((struct sockaddr_in *) c->sockaddr)->sin_port); + lport = ntohs(((struct sockaddr_in *) c->local_sockaddr)->sin_port); + + break; + +#if (NGX_HAVE_INET6) + case AF_INET6: + buf = ngx_cpymem(buf, "PROXY TCP6 ", sizeof("PROXY TCP6 ") - 1); + + port = ntohs(((struct sockaddr_in6 *) c->sockaddr)->sin6_port); + lport = ntohs(((struct sockaddr_in6 *) c->local_sockaddr)->sin6_port); + + break; +#endif + + default: + return ngx_cpymem(buf, "PROXY UNKNOWN" CRLF, + sizeof("PROXY UNKNOWN" CRLF) - 1); + } + + buf += ngx_sock_ntop(c->sockaddr, c->socklen, buf, last - buf, 0); + + *buf++ = ' '; + + buf += ngx_sock_ntop(c->local_sockaddr, c->local_socklen, buf, last - buf, + 0); + + return ngx_slprintf(buf, last, " %ui %ui" CRLF, port, lport); +} diff -r 4dcffe43a7ea -r fa663739e115 src/core/ngx_proxy_protocol.h --- a/src/core/ngx_proxy_protocol.h Tue Jun 16 09:02:45 2015 +0300 +++ b/src/core/ngx_proxy_protocol.h Tue Jun 16 13:45:16 2015 +0300 @@ -18,6 +18,8 @@ u_char *ngx_proxy_protocol_parse(ngx_connection_t *c, u_char *buf, u_char *last); +u_char *ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf, + u_char *last); #endif /* _NGX_PROXY_PROTOCOL_H_INCLUDED_ */ diff -r 4dcffe43a7ea -r fa663739e115 src/stream/ngx_stream_proxy_module.c --- a/src/stream/ngx_stream_proxy_module.c Tue Jun 16 09:02:45 2015 +0300 +++ b/src/stream/ngx_stream_proxy_module.c Tue Jun 16 13:45:16 2015 +0300 @@ -21,6 +21,7 @@ typedef struct { size_t upstream_buf_size; ngx_uint_t next_upstream_tries; ngx_flag_t next_upstream; + ngx_flag_t proxy_protocol; ngx_addr_t *local; #if (NGX_STREAM_SSL) @@ -67,6 +68,7 @@ static char *ngx_stream_proxy_pass(ngx_c void *conf); static char *ngx_stream_proxy_bind(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +static ngx_int_t ngx_stream_proxy_send_proxy_protocol(ngx_stream_session_t *s); #if (NGX_STREAM_SSL) @@ -156,6 +158,13 @@ static ngx_command_t ngx_stream_proxy_c offsetof(ngx_stream_proxy_srv_conf_t, next_upstream_timeout), NULL }, + { ngx_string("proxy_protocol"), + NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_STREAM_SRV_CONF_OFFSET, + offsetof(ngx_stream_proxy_srv_conf_t, proxy_protocol), + NULL }, + #if (NGX_STREAM_SSL) { ngx_string("proxy_ssl"), @@ -328,6 +337,8 @@ ngx_stream_proxy_handler(ngx_stream_sess u->peer.tries = pscf->next_upstream_tries; } + u->proxy_protocol = pscf->proxy_protocol; + p = ngx_pnalloc(c->pool, pscf->downstream_buf_size); if (p == NULL) { ngx_stream_proxy_finalize(s, NGX_ERROR); @@ -342,6 +353,29 @@ ngx_stream_proxy_handler(ngx_stream_sess c->write->handler = ngx_stream_proxy_downstream_handler; c->read->handler = ngx_stream_proxy_downstream_handler; + if (u->proxy_protocol +#if (NGX_STREAM_SSL) + && pscf->ssl == NULL +#endif + && pscf->downstream_buf_size >= NGX_PROXY_PROTOCOL_MAX_HEADER + ) + { + /* optimization for a typical case */ + + ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0, + "stream proxy send PROXY protocol header"); + + p = ngx_proxy_protocol_write(c, u->downstream_buf.last, + u->downstream_buf.end); + if (p == NULL) { + ngx_stream_proxy_finalize(s, NGX_ERROR); + return; + } + + u->downstream_buf.last = p; + u->proxy_protocol = 0; + } + if (ngx_stream_proxy_process(s, 0, 0) != NGX_OK) { return; } @@ -417,10 +451,18 @@ ngx_stream_proxy_init_upstream(ngx_strea ngx_stream_upstream_t *u; ngx_stream_proxy_srv_conf_t *pscf; + u = s->upstream; + + if (u->proxy_protocol) { + if (ngx_stream_proxy_send_proxy_protocol(s) != NGX_OK) { + return; + } + + u->proxy_protocol = 0; + } + pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module); - u = s->upstream; - pc = u->peer.connection; #if (NGX_STREAM_SSL) @@ -474,6 +516,76 @@ ngx_stream_proxy_init_upstream(ngx_strea } +static ngx_int_t +ngx_stream_proxy_send_proxy_protocol(ngx_stream_session_t *s) +{ + u_char *p; + ssize_t n, size; + ngx_connection_t *c, *pc; + ngx_stream_upstream_t *u; + ngx_stream_proxy_srv_conf_t *pscf; + u_char buf[NGX_PROXY_PROTOCOL_MAX_HEADER]; + + c = s->connection; + + ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0, + "stream proxy send PROXY protocol header"); + + p = ngx_proxy_protocol_write(c, buf, buf + NGX_PROXY_PROTOCOL_MAX_HEADER); + if (p == NULL) { + ngx_stream_proxy_finalize(s, NGX_ERROR); + return NGX_ERROR; + } + + u = s->upstream; + + pc = u->peer.connection; + + size = p - buf; + + n = pc->send(pc, buf, size); + + if (n == NGX_AGAIN) { + if (ngx_handle_write_event(pc->write, 0) != NGX_OK) { + ngx_stream_proxy_finalize(s, NGX_ERROR); + return NGX_ERROR; + } + + pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module); + + ngx_add_timer(pc->write, pscf->timeout); + + pc->write->handler = ngx_stream_proxy_connect_handler; + + return NGX_AGAIN; + } + + if (n == NGX_ERROR) { + ngx_stream_proxy_finalize(s, NGX_DECLINED); + return NGX_ERROR; + } + + if (n != size) { + + /* + * PROXY protocol specification: + * The sender must always ensure that the header + * is sent at once, so that the transport layer + * maintains atomicity along the path to the receiver. + */ + + ngx_log_error(NGX_LOG_ERR, c->log, 0, + "could not send PROXY protocol header at once"); + + ngx_stream_proxy_finalize(s, NGX_DECLINED); + + return NGX_ERROR; + } + + return NGX_OK; +} + + #if (NGX_STREAM_SSL) static char * @@ -1105,6 +1217,7 @@ ngx_stream_proxy_create_srv_conf(ngx_con conf->upstream_buf_size = NGX_CONF_UNSET_SIZE; conf->next_upstream_tries = NGX_CONF_UNSET_UINT; conf->next_upstream = NGX_CONF_UNSET; + conf->proxy_protocol = NGX_CONF_UNSET; conf->local = NGX_CONF_UNSET_PTR; #if (NGX_STREAM_SSL) @@ -1146,6 +1259,8 @@ ngx_stream_proxy_merge_srv_conf(ngx_conf ngx_conf_merge_value(conf->next_upstream, prev->next_upstream, 1); + ngx_conf_merge_value(conf->proxy_protocol, prev->proxy_protocol, 0); + ngx_conf_merge_ptr_value(conf->local, prev->local, NULL); #if (NGX_STREAM_SSL) diff -r 4dcffe43a7ea -r fa663739e115 src/stream/ngx_stream_upstream.h --- a/src/stream/ngx_stream_upstream.h Tue Jun 16 09:02:45 2015 +0300 +++ b/src/stream/ngx_stream_upstream.h Tue Jun 16 13:45:16 2015 +0300 @@ -86,6 +86,8 @@ typedef struct { #if (NGX_STREAM_SSL) ngx_str_t ssl_name; #endif + ngx_uint_t proxy_protocol; + /* unsigned proxy_protocol:1; */ } ngx_stream_upstream_t; From arut at nginx.com Tue Jun 16 10:47:35 2015 From: arut at nginx.com (Roman Arutyunyan) Date: Tue, 16 Jun 2015 10:47:35 +0000 Subject: [nginx] Core: renamed ngx_proxy_protocol_parse to ngx_proxy_prot... Message-ID: details: http://hg.nginx.org/nginx/rev/a420cb1c170b branches: changeset: 6185:a420cb1c170b user: Roman Arutyunyan date: Tue Jun 16 13:45:19 2015 +0300 description: Core: renamed ngx_proxy_protocol_parse to ngx_proxy_protocol_read. The new name is consistent with the ngx_proxy_protocol_write function. diffstat: src/core/ngx_proxy_protocol.c | 2 +- src/core/ngx_proxy_protocol.h | 2 +- src/http/ngx_http_request.c | 4 ++-- src/http/ngx_http_spdy.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diffs (57 lines): diff -r fa663739e115 -r a420cb1c170b src/core/ngx_proxy_protocol.c --- a/src/core/ngx_proxy_protocol.c Tue Jun 16 13:45:16 2015 +0300 +++ b/src/core/ngx_proxy_protocol.c Tue Jun 16 13:45:19 2015 +0300 @@ -10,7 +10,7 @@ u_char * -ngx_proxy_protocol_parse(ngx_connection_t *c, u_char *buf, u_char *last) +ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last) { size_t len; u_char ch, *p, *addr; diff -r fa663739e115 -r a420cb1c170b src/core/ngx_proxy_protocol.h --- a/src/core/ngx_proxy_protocol.h Tue Jun 16 13:45:16 2015 +0300 +++ b/src/core/ngx_proxy_protocol.h Tue Jun 16 13:45:19 2015 +0300 @@ -16,7 +16,7 @@ #define NGX_PROXY_PROTOCOL_MAX_HEADER 107 -u_char *ngx_proxy_protocol_parse(ngx_connection_t *c, u_char *buf, +u_char *ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last); u_char *ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf, u_char *last); diff -r fa663739e115 -r a420cb1c170b src/http/ngx_http_request.c --- a/src/http/ngx_http_request.c Tue Jun 16 13:45:16 2015 +0300 +++ b/src/http/ngx_http_request.c Tue Jun 16 13:45:19 2015 +0300 @@ -467,7 +467,7 @@ ngx_http_wait_request_handler(ngx_event_ if (hc->proxy_protocol) { hc->proxy_protocol = 0; - p = ngx_proxy_protocol_parse(c, b->pos, b->last); + p = ngx_proxy_protocol_read(c, b->pos, b->last); if (p == NULL) { ngx_http_close_connection(c); @@ -675,7 +675,7 @@ ngx_http_ssl_handshake(ngx_event_t *rev) if (hc->proxy_protocol) { hc->proxy_protocol = 0; - p = ngx_proxy_protocol_parse(c, buf, buf + n); + p = ngx_proxy_protocol_read(c, buf, buf + n); if (p == NULL) { ngx_http_close_connection(c); diff -r fa663739e115 -r a420cb1c170b src/http/ngx_http_spdy.c --- a/src/http/ngx_http_spdy.c Tue Jun 16 13:45:16 2015 +0300 +++ b/src/http/ngx_http_spdy.c Tue Jun 16 13:45:19 2015 +0300 @@ -866,7 +866,7 @@ ngx_http_spdy_proxy_protocol(ngx_http_sp log = sc->connection->log; log->action = "reading PROXY protocol"; - pos = ngx_proxy_protocol_parse(sc->connection, pos, end); + pos = ngx_proxy_protocol_read(sc->connection, pos, end); log->action = "processing SPDY"; From witekfl at gazeta.pl Tue Jun 16 11:35:55 2015 From: witekfl at gazeta.pl (Witold Filipczyk) Date: Tue, 16 Jun 2015 13:35:55 +0200 Subject: Content-Type [PATCH] In-Reply-To: References: <20150616090650.GA2672@fujitsu> Message-ID: <20150616113555.GA25267@fujitsu> On Tue, Jun 16, 2015 at 12:37:39PM +0200, Lukas Tribus wrote: > > Hi, > > > header('Content-Type: text/html;'); > > Thats invalid. Either: > text/html; charset=iso-8859-1 > or > text/html > > but not with a trailing semicolon. Content-Type is used in many places in nginx, for example in the sub module. In the above example, the content-type is cheated. # HG changeset patch # User Witold Filipczyk # Date 1434454090 -7200 # Tue Jun 16 13:28:10 2015 +0200 # Node ID 8ac7373110ad140bbed0b9eef3add41b769c0ba6 # Parent cca856715722ff7f6de9e741fedd0d2759b26b74 Mark the first semicolon as the end of the Content-Type. diff -r cca856715722 -r 8ac7373110ad src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c Wed May 20 22:44:00 2015 +0300 +++ b/src/http/ngx_http_upstream.c Tue Jun 16 13:28:10 2015 +0200 @@ -4568,6 +4568,7 @@ ngx_uint_t offset) { u_char *p, *last; + int semicolon = 0; r->headers_out.content_type_len = h->value.len; r->headers_out.content_type = h->value; @@ -4579,7 +4580,10 @@ continue; } - last = p; + if (!semicolon) { + semicolon = 1; + r->headers_out.content_type_len = p - h->value.data; + } while (*++p == ' ') { /* void */ } @@ -4593,8 +4597,6 @@ p += 8; - r->headers_out.content_type_len = last - h->value.data; - if (*p == '"') { p++; } From vbart at nginx.com Tue Jun 16 11:50:36 2015 From: vbart at nginx.com (Valentin V. Bartenev) Date: Tue, 16 Jun 2015 14:50:36 +0300 Subject: Content-Type [PATCH] In-Reply-To: <20150616113555.GA25267@fujitsu> References: <20150616090650.GA2672@fujitsu> <20150616113555.GA25267@fujitsu> Message-ID: <1795904.aMkntbl2Ii@vbart-workstation> On Tuesday 16 June 2015 13:35:55 Witold Filipczyk wrote: > On Tue, Jun 16, 2015 at 12:37:39PM +0200, Lukas Tribus wrote: > > > Hi, > > > > > header('Content-Type: text/html;'); > > > > Thats invalid. Either: > > text/html; charset=iso-8859-1 > > or > > text/html > > > > but not with a trailing semicolon. > > Content-Type is used in many places in nginx, for example in the sub module. > In the above example, the content-type is cheated. > [..] As already pointed out "text/html;" isn't a valid media type. See RFC 7231: https://tools.ietf.org/html/rfc7231#section-3.1.1.1 Please fix your application. wbr, Valentin V. Bartenev From vl at nginx.com Tue Jun 16 12:48:58 2015 From: vl at nginx.com (Vladimir Homutov) Date: Tue, 16 Jun 2015 12:48:58 +0000 Subject: [nginx] Core: added support for writing to stdout. Message-ID: details: http://hg.nginx.org/nginx/rev/db138b3b645e branches: changeset: 6186:db138b3b645e user: Vladimir Homutov date: Tue Jun 16 15:47:40 2015 +0300 description: Core: added support for writing to stdout. diffstat: src/core/ngx_log.h | 7 +++++++ src/os/unix/ngx_files.h | 1 + src/os/win32/ngx_files.h | 1 + 3 files changed, 9 insertions(+), 0 deletions(-) diffs (39 lines): diff -r a420cb1c170b -r db138b3b645e src/core/ngx_log.h --- a/src/core/ngx_log.h Tue Jun 16 13:45:19 2015 +0300 +++ b/src/core/ngx_log.h Tue Jun 16 15:47:40 2015 +0300 @@ -255,6 +255,13 @@ ngx_write_stderr(char *text) } +static ngx_inline void +ngx_write_stdout(char *text) +{ + (void) ngx_write_fd(ngx_stdout, text, ngx_strlen(text)); +} + + extern ngx_module_t ngx_errlog_module; extern ngx_uint_t ngx_use_stderr; diff -r a420cb1c170b -r db138b3b645e src/os/unix/ngx_files.h --- a/src/os/unix/ngx_files.h Tue Jun 16 13:45:19 2015 +0300 +++ b/src/os/unix/ngx_files.h Tue Jun 16 15:47:40 2015 +0300 @@ -368,6 +368,7 @@ size_t ngx_fs_bsize(u_char *name); #endif +#define ngx_stdout STDOUT_FILENO #define ngx_stderr STDERR_FILENO #define ngx_set_stderr(fd) dup2(fd, STDERR_FILENO) #define ngx_set_stderr_n "dup2(STDERR_FILENO)" diff -r a420cb1c170b -r db138b3b645e src/os/win32/ngx_files.h --- a/src/os/win32/ngx_files.h Tue Jun 16 13:45:19 2015 +0300 +++ b/src/os/win32/ngx_files.h Tue Jun 16 15:47:40 2015 +0300 @@ -264,6 +264,7 @@ ngx_int_t ngx_directio_off(ngx_fd_t fd); size_t ngx_fs_bsize(u_char *name); +#define ngx_stdout GetStdHandle(STD_OUTPUT_HANDLE) #define ngx_stderr GetStdHandle(STD_ERROR_HANDLE) #define ngx_set_stderr(fd) SetStdHandle(STD_ERROR_HANDLE, fd) #define ngx_set_stderr_n "SetStdHandle(STD_ERROR_HANDLE)" From vl at nginx.com Tue Jun 16 12:49:00 2015 From: vl at nginx.com (Vladimir Homutov) Date: Tue, 16 Jun 2015 12:49:00 +0000 Subject: [nginx] Core: store and dump processed configuration. Message-ID: details: http://hg.nginx.org/nginx/rev/1b7e246e6b38 branches: changeset: 6187:1b7e246e6b38 user: Vladimir Homutov date: Thu May 14 18:54:27 2015 +0300 description: Core: store and dump processed configuration. If the -T option is passed, additionally to configuration test, configuration files are output to stdout. In the debug mode, configuration files are kept in memory and can be accessed using a debugger. diffstat: src/core/nginx.c | 30 ++++++++++++++++++++++++++++-- src/core/ngx_conf_file.c | 45 +++++++++++++++++++++++++++++++++++++++++++-- src/core/ngx_conf_file.h | 7 +++++++ src/core/ngx_cycle.c | 8 ++++++++ src/core/ngx_cycle.h | 2 ++ 5 files changed, 88 insertions(+), 4 deletions(-) diffs (221 lines): diff -r db138b3b645e -r 1b7e246e6b38 src/core/nginx.c --- a/src/core/nginx.c Tue Jun 16 15:47:40 2015 +0300 +++ b/src/core/nginx.c Thu May 14 18:54:27 2015 +0300 @@ -176,9 +176,11 @@ static char **ngx_os_environ; int ngx_cdecl main(int argc, char *const *argv) { - ngx_int_t i; + ngx_buf_t *b; ngx_log_t *log; + ngx_uint_t i; ngx_cycle_t *cycle, init_cycle; + ngx_conf_dump_t *cd; ngx_core_conf_t *ccf; ngx_debug_init(); @@ -196,7 +198,7 @@ main(int argc, char *const *argv) if (ngx_show_help) { ngx_write_stderr( - "Usage: nginx [-?hvVtq] [-s signal] [-c filename] " + "Usage: nginx [-?hvVtTq] [-s signal] [-c filename] " "[-p prefix] [-g directives]" NGX_LINEFEED NGX_LINEFEED "Options:" NGX_LINEFEED @@ -205,6 +207,8 @@ main(int argc, char *const *argv) " -V : show version and configure options then exit" NGX_LINEFEED " -t : test configuration and exit" NGX_LINEFEED + " -T : test configuration, dump it and exit" + NGX_LINEFEED " -q : suppress non-error messages " "during configuration testing" NGX_LINEFEED " -s signal : send signal to a master process: " @@ -333,6 +337,23 @@ main(int argc, char *const *argv) cycle->conf_file.data); } + if (ngx_dump_config) { + cd = cycle->config_dump.elts; + + for (i = 0; i < cycle->config_dump.nelts; i++) { + + ngx_write_stdout("# configuration file "); + (void) ngx_write_fd(ngx_stdout, cd[i].name.data, + cd[i].name.len); + ngx_write_stdout(":" NGX_LINEFEED); + + b = cd[i].buffer; + + (void) ngx_write_fd(ngx_stdout, b->pos, b->last - b->pos); + ngx_write_stdout(NGX_LINEFEED); + } + } + return 0; } @@ -689,6 +710,11 @@ ngx_get_options(int argc, char *const *a ngx_test_config = 1; break; + case 'T': + ngx_test_config = 1; + ngx_dump_config = 1; + break; + case 'q': ngx_quiet_mode = 1; break; diff -r db138b3b645e -r 1b7e246e6b38 src/core/ngx_conf_file.c --- a/src/core/ngx_conf_file.c Tue Jun 16 15:47:40 2015 +0300 +++ b/src/core/ngx_conf_file.c Thu May 14 18:54:27 2015 +0300 @@ -101,10 +101,13 @@ char * ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename) { char *rv; + u_char *p; + off_t size; ngx_fd_t fd; ngx_int_t rc; - ngx_buf_t buf; + ngx_buf_t buf, *tbuf; ngx_conf_file_t *prev, conf_file; + ngx_conf_dump_t *cd; enum { parse_file = 0, parse_block, @@ -158,6 +161,39 @@ ngx_conf_parse(ngx_conf_t *cf, ngx_str_t type = parse_file; + if (ngx_dump_config +#if (NGX_DEBUG) + || 1 +#endif + ) + { + p = ngx_pstrdup(cf->cycle->pool, filename); + if (p == NULL) { + goto failed; + } + + size = ngx_file_size(&cf->conf_file->file.info); + + tbuf = ngx_create_temp_buf(cf->cycle->pool, (size_t) size); + if (tbuf == NULL) { + goto failed; + } + + cd = ngx_array_push(&cf->cycle->config_dump); + if (cd == NULL) { + goto failed; + } + + cd->name.len = filename->len; + cd->name.data = p; + cd->buffer = tbuf; + + cf->conf_file->dump = tbuf; + + } else { + cf->conf_file->dump = NULL; + } + } else if (cf->conf_file->file.fd != NGX_INVALID_FILE) { type = parse_block; @@ -437,7 +473,7 @@ ngx_conf_read_token(ngx_conf_t *cf) ngx_uint_t found, need_space, last_space, sharp_comment, variable; ngx_uint_t quoted, s_quoted, d_quoted, start_line; ngx_str_t *word; - ngx_buf_t *b; + ngx_buf_t *b, *dump; found = 0; need_space = 0; @@ -450,6 +486,7 @@ ngx_conf_read_token(ngx_conf_t *cf) cf->args->nelts = 0; b = cf->conf_file->buffer; + dump = cf->conf_file->dump; start = b->pos; start_line = cf->conf_file->line; @@ -531,6 +568,10 @@ ngx_conf_read_token(ngx_conf_t *cf) b->pos = b->start + len; b->last = b->pos + n; start = b->start; + + if (dump) { + dump->last = ngx_cpymem(dump->last, b->pos, size); + } } ch = *b->pos++; diff -r db138b3b645e -r 1b7e246e6b38 src/core/ngx_conf_file.h --- a/src/core/ngx_conf_file.h Tue Jun 16 15:47:40 2015 +0300 +++ b/src/core/ngx_conf_file.h Thu May 14 18:54:27 2015 +0300 @@ -146,10 +146,17 @@ typedef struct { typedef struct { ngx_file_t file; ngx_buf_t *buffer; + ngx_buf_t *dump; ngx_uint_t line; } ngx_conf_file_t; +typedef struct { + ngx_str_t name; + ngx_buf_t *buffer; +} ngx_conf_dump_t; + + typedef char *(*ngx_conf_handler_pt)(ngx_conf_t *cf, ngx_command_t *dummy, void *conf); diff -r db138b3b645e -r 1b7e246e6b38 src/core/ngx_cycle.c --- a/src/core/ngx_cycle.c Tue Jun 16 15:47:40 2015 +0300 +++ b/src/core/ngx_cycle.c Thu May 14 18:54:27 2015 +0300 @@ -24,6 +24,7 @@ static ngx_pool_t *ngx_temp_pool; static ngx_event_t ngx_cleaner_event; ngx_uint_t ngx_test_config; +ngx_uint_t ngx_dump_config; ngx_uint_t ngx_quiet_mode; @@ -124,6 +125,13 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) cycle->paths.pool = pool; + if (ngx_array_init(&cycle->config_dump, pool, 1, sizeof(ngx_conf_dump_t)) + != NGX_OK) + { + ngx_destroy_pool(pool); + return NULL; + } + if (old_cycle->open_files.part.nelts) { n = old_cycle->open_files.part.nelts; for (part = old_cycle->open_files.part.next; part; part = part->next) { diff -r db138b3b645e -r 1b7e246e6b38 src/core/ngx_cycle.h --- a/src/core/ngx_cycle.h Tue Jun 16 15:47:40 2015 +0300 +++ b/src/core/ngx_cycle.h Thu May 14 18:54:27 2015 +0300 @@ -52,6 +52,7 @@ struct ngx_cycle_s { ngx_array_t listening; ngx_array_t paths; + ngx_array_t config_dump; ngx_list_t open_files; ngx_list_t shared_memory; @@ -124,6 +125,7 @@ extern volatile ngx_cycle_t *ngx_cycle; extern ngx_array_t ngx_old_cycles; extern ngx_module_t ngx_core_module; extern ngx_uint_t ngx_test_config; +extern ngx_uint_t ngx_dump_config; extern ngx_uint_t ngx_quiet_mode; From vl at nginx.com Tue Jun 16 13:29:12 2015 From: vl at nginx.com (Vladimir Homutov) Date: Tue, 16 Jun 2015 13:29:12 +0000 Subject: [nginx] Documentation: added -T option description to the man page. Message-ID: details: http://hg.nginx.org/nginx/rev/f08e80409dfd branches: changeset: 6188:f08e80409dfd user: Vladimir Homutov date: Tue Jun 16 16:28:56 2015 +0300 description: Documentation: added -T option description to the man page. diffstat: docs/man/nginx.8 | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) diffs (30 lines): diff -r 1b7e246e6b38 -r f08e80409dfd docs/man/nginx.8 --- a/docs/man/nginx.8 Thu May 14 18:54:27 2015 +0300 +++ b/docs/man/nginx.8 Tue Jun 16 16:28:56 2015 +0300 @@ -25,7 +25,7 @@ .\" SUCH DAMAGE. .\" .\" -.Dd March 6, 2012 +.Dd June 16, 2015 .Dt NGINX 8 .Os .Sh NAME @@ -33,7 +33,7 @@ .Nd "HTTP and reverse proxy server, mail proxy server" .Sh SYNOPSIS .Nm -.Op Fl ?hqtVv +.Op Fl ?hqTtVv .Op Fl c Ar file .Op Fl g Ar directives .Op Fl p Ar prefix @@ -87,6 +87,8 @@ Do not run, just test the configuration .Nm checks the configuration file syntax and then tries to open files referenced in the configuration file. +.It Fl T +Same as -t, but additionally dumps configuration files to stdout. .It Fl V Print the .Nm From ru at nginx.com Tue Jun 16 13:52:33 2015 From: ru at nginx.com (Ruslan Ermilov) Date: Tue, 16 Jun 2015 13:52:33 +0000 Subject: [nginx] Polished the recent change to the manpage. Message-ID: details: http://hg.nginx.org/nginx/rev/54b10b289f0f branches: changeset: 6189:54b10b289f0f user: Ruslan Ermilov date: Tue Jun 16 16:52:13 2015 +0300 description: Polished the recent change to the manpage. diffstat: docs/man/nginx.8 | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diffs (14 lines): diff -r f08e80409dfd -r 54b10b289f0f docs/man/nginx.8 --- a/docs/man/nginx.8 Tue Jun 16 16:28:56 2015 +0300 +++ b/docs/man/nginx.8 Tue Jun 16 16:52:13 2015 +0300 @@ -88,7 +88,9 @@ Do not run, just test the configuration checks the configuration file syntax and then tries to open files referenced in the configuration file. .It Fl T -Same as -t, but additionally dumps configuration files to stdout. +Same as +.Fl t , +but additionally dump configuration files to standard output. .It Fl V Print the .Nm From mdounin at mdounin.ru Tue Jun 16 15:03:39 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 16 Jun 2015 15:03:39 +0000 Subject: [nginx] nginx-1.9.2-RELEASE Message-ID: details: http://hg.nginx.org/nginx/rev/3a32d6e7404a branches: changeset: 6190:3a32d6e7404a user: Maxim Dounin date: Tue Jun 16 17:49:39 2015 +0300 description: nginx-1.9.2-RELEASE diffstat: docs/xml/nginx/changes.xml | 83 ++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 83 insertions(+), 0 deletions(-) diffs (93 lines): diff --git a/docs/xml/nginx/changes.xml b/docs/xml/nginx/changes.xml --- a/docs/xml/nginx/changes.xml +++ b/docs/xml/nginx/changes.xml @@ -5,6 +5,89 @@ + + + + +???????? backlog ????????? listen +? ???????? ??????-??????? ? ?????? stream. + + +the "backlog" parameter of the "listen" directives +of the mail proxy and stream modules. + + + + + +????????? allow ? deny ? ?????? stream. + + +the "allow" and "deny" directives in the stream module. + + + + + +????????? proxy_bind ? ?????? stream. + + +the "proxy_bind" directive in the stream module. + + + + + +????????? proxy_protocol ? ?????? stream. + + +the "proxy_protocol" directive in the stream module. + + + + + +???? -T. + + +the -T switch. + + + + + +???????? REQUEST_SCHEME ???????? ? ??????????? ???????????????? ????? +fastcgi.conf, fastcgi_params, scgi_params ? uwsgi_params. + + +the REQUEST_SCHEME parameter added to the fastcgi.conf, fastcgi_params, +scgi_params, and uwsgi_params standard configuration files. + + + + + +???????? reuseport ????????? listen ? ?????? stream +?? ???????. + + +the "reuseport" parameter of the "listen" directive of the stream module +did not work. + + + + + +OCSP stapling ? ????????? ??????? ??? ??????? ?????????? OCSP-?????. + + +OCSP stapling might return an expired OCSP response in some cases. + + + + + + From mdounin at mdounin.ru Tue Jun 16 15:03:42 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 16 Jun 2015 15:03:42 +0000 Subject: [nginx] release-1.9.2 tag Message-ID: details: http://hg.nginx.org/nginx/rev/f96689414078 branches: changeset: 6191:f96689414078 user: Maxim Dounin date: Tue Jun 16 17:49:40 2015 +0300 description: release-1.9.2 tag diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -384,3 +384,4 @@ 2b3b737b5456c05cd63d3d834f4fb4d3776953d0 3ef00a71f56420a9c3e9cec311c9a2109a015d67 release-1.7.12 53d850fe292f157d2fb999c52788ec1dc53c91ed release-1.9.0 884a967c369f73ab16ea859670d690fb094d3850 release-1.9.1 +3a32d6e7404a79a0973bcd8d0b83181c5bf66074 release-1.9.2 From vl at nginx.com Tue Jun 16 20:36:52 2015 From: vl at nginx.com (Vladimir Homutov) Date: Tue, 16 Jun 2015 20:36:52 +0000 Subject: [nginx] Version bump. Message-ID: details: http://hg.nginx.org/nginx/rev/7863b167dbf9 branches: changeset: 6192:7863b167dbf9 user: Vladimir Homutov date: Tue Jun 16 23:31:31 2015 +0300 description: Version bump. diffstat: src/core/nginx.h | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (14 lines): diff -r f96689414078 -r 7863b167dbf9 src/core/nginx.h --- a/src/core/nginx.h Tue Jun 16 17:49:40 2015 +0300 +++ b/src/core/nginx.h Tue Jun 16 23:31:31 2015 +0300 @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1009002 -#define NGINX_VERSION "1.9.2" +#define nginx_version 1009003 +#define NGINX_VERSION "1.9.3" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD From vl at nginx.com Tue Jun 16 20:36:55 2015 From: vl at nginx.com (Vladimir Homutov) Date: Tue, 16 Jun 2015 20:36:55 +0000 Subject: [nginx] Disabled duplicate http, mail, and stream blocks. Message-ID: details: http://hg.nginx.org/nginx/rev/78c06e5e1d76 branches: changeset: 6193:78c06e5e1d76 user: Vladimir Homutov date: Tue Jun 16 23:28:38 2015 +0300 description: Disabled duplicate http, mail, and stream blocks. Such configurations have very limited use, introduce various problems and are not officially supported. diffstat: src/http/ngx_http.c | 4 ++++ src/mail/ngx_mail.c | 4 ++++ src/stream/ngx_stream.c | 4 ++++ 3 files changed, 12 insertions(+), 0 deletions(-) diffs (42 lines): diff -r 7863b167dbf9 -r 78c06e5e1d76 src/http/ngx_http.c --- a/src/http/ngx_http.c Tue Jun 16 23:31:31 2015 +0300 +++ b/src/http/ngx_http.c Tue Jun 16 23:28:38 2015 +0300 @@ -128,6 +128,10 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma ngx_http_core_srv_conf_t **cscfp; ngx_http_core_main_conf_t *cmcf; + if (*(ngx_http_conf_ctx_t **) conf) { + return "is duplicate"; + } + /* the main http context */ ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)); diff -r 7863b167dbf9 -r 78c06e5e1d76 src/mail/ngx_mail.c --- a/src/mail/ngx_mail.c Tue Jun 16 23:31:31 2015 +0300 +++ b/src/mail/ngx_mail.c Tue Jun 16 23:28:38 2015 +0300 @@ -76,6 +76,10 @@ ngx_mail_block(ngx_conf_t *cf, ngx_comma ngx_mail_core_srv_conf_t **cscfp; ngx_mail_core_main_conf_t *cmcf; + if (*(ngx_mail_conf_ctx_t **) conf) { + return "is duplicate"; + } + /* the main mail context */ ctx = ngx_pcalloc(cf->pool, sizeof(ngx_mail_conf_ctx_t)); diff -r 7863b167dbf9 -r 78c06e5e1d76 src/stream/ngx_stream.c --- a/src/stream/ngx_stream.c Tue Jun 16 23:31:31 2015 +0300 +++ b/src/stream/ngx_stream.c Tue Jun 16 23:28:38 2015 +0300 @@ -76,6 +76,10 @@ ngx_stream_block(ngx_conf_t *cf, ngx_com ngx_stream_core_srv_conf_t **cscfp; ngx_stream_core_main_conf_t *cmcf; + if (*(ngx_stream_conf_ctx_t **) conf) { + return "is duplicate"; + } + /* the main stream context */ ctx = ngx_pcalloc(cf->pool, sizeof(ngx_stream_conf_ctx_t)); From mdounin at mdounin.ru Wed Jun 17 02:27:33 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 17 Jun 2015 05:27:33 +0300 Subject: Fix windows issue with multiple workers In-Reply-To: <64cd3e82b8271b1240c588dc6fece3bb@sebres.de> References: <64cd3e82b8271b1240c588dc6fece3bb@sebres.de> Message-ID: <20150617022733.GG26357@mdounin.ru> Hello! On Wed, Jun 10, 2015 at 09:48:28PM +0200, Sergey Brester wrote: [...] > @Maxim Dounin: > 1) your suggested way with shared handle and bInheritHandle does not > work, because of: > [quote] > Sockets. No error is returned, but the duplicate handle may not be > recognized by Winsock at the target process. Also, using DUPLICATEHANDLE > interferes with internal reference counting on the underlying object. > To duplicate a socket handle, use the WSADUPLICATESOCKET function. > [/quote] The quote is from DuplicateHandle() description, which is irrelevant to the approach suggested. Sockets are inheritable between processes, including listen ones. Simple test code below, as adapted from the accept() MSDN example, demonstrates that the approach is working. #include #include #include #pragma comment(lib, "Ws2_32.lib") int main(int argc, char *argv[]) { int rc; u_long code; SOCKET listen_socket, s; WSADATA wsaData; struct sockaddr_in sin; STARTUPINFO si; PROCESS_INFORMATION pi; char command[256]; rc = WSAStartup(MAKEWORD(2, 2), &wsaData); if (rc != NO_ERROR) { printf("WSAStartup() failed: %d\n", rc); return 2; } if (argc == 2) { listen_socket = atoi(argv[1]); printf("Inherited socket: %d\n", listen_socket); goto accept; } listen_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (listen_socket == INVALID_SOCKET) { printf("socket failed with error: %ld\n", WSAGetLastError()); return 1; } printf("Listen socket: %d\n", listen_socket); sin.sin_family = AF_INET; sin.sin_addr.s_addr = inet_addr("127.0.0.1"); sin.sin_port = htons(8080); if (bind(listen_socket, (SOCKADDR *) &sin, sizeof(sin)) == SOCKET_ERROR) { printf("bind() failed: %ld\n", WSAGetLastError()); return 1; } if (listen(listen_socket, 1) == SOCKET_ERROR) { printf("listen() failed: %ld\n", WSAGetLastError()); return 1; } if (argc == 1) { ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); ZeroMemory(&pi, sizeof(pi)); _snprintf(command, sizeof(command), "%s %d", argv[0], listen_socket); if (CreateProcess(NULL, command, NULL, NULL, 1, 0, NULL, NULL, &si, &pi) == 0) { printf("CreateProcess() failed: %ld\n", GetLastError()); return 1; } WaitForSingleObject(pi.hProcess, INFINITE); if (GetExitCodeProcess(pi.hProcess, &code) == 0) { printf("GetExitCodeProcess() failed: %ld\n", GetLastError()); return 1; } printf("Child process exited: %d\n", code); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); } accept: printf("Waiting for client to connect...\n"); s = accept(listen_socket, NULL, NULL); if (s == INVALID_SOCKET) { printf("accept() failed: %ld\n", WSAGetLastError()); return 1; } printf("Client connected\n"); return 0; } -- Maxim Dounin http://nginx.org/ From serg.brester at sebres.de Wed Jun 17 07:58:46 2015 From: serg.brester at sebres.de (Sergey Brester) Date: Wed, 17 Jun 2015 09:58:46 +0200 Subject: Fix windows issue with multiple workers In-Reply-To: <20150617022733.GG26357@mdounin.ru> References: <64cd3e82b8271b1240c588dc6fece3bb@sebres.de> <20150617022733.GG26357@mdounin.ru> Message-ID: Hi, Yes, for exactly one child process... For example, same (modified for multiprocessing) code does not work on my mashine (win7 x64) for 2nd (3th etc.) process (with error 10022 = INVARG). I think the handle schould be then duplicated, and see MSDN (https://msdn.microsoft.com/en-us/library/windows/desktop/ms724251.aspx) Sockets. No error is returned, but the duplicate handle may not be recognized by Winsock at the target process. Also, using DuplicateHandle interferes with internal reference counting on the underlying object. To duplicate a socket handle, use the WSADuplicateSocket function. Regards, sebres. . Am 17.06.2015 04:27, schrieb Maxim Dounin: > Hello! > > On Wed, Jun 10, 2015 at 09:48:28PM +0200, Sergey Brester wrote: > > [...] > >> @Maxim Dounin: 1) your suggested way with shared handle and >> bInheritHandle does not work, because of: [quote] Sockets. No error is >> returned, but the duplicate handle may not be recognized by Winsock at >> the target process. Also, using DUPLICATEHANDLE interferes with >> internal reference counting on the underlying object. To duplicate a >> socket handle, use the WSADUPLICATESOCKET function. [/quote] > > The quote is from DuplicateHandle() description, which is > irrelevant to the approach suggested. Sockets are inheritable > between processes, including listen ones. > > Simple test code below, as adapted from the accept() MSDN example, > demonstrates that the approach is working. > > #include > #include > #include > > #pragma comment(lib, "Ws2_32.lib") > > int > main(int argc, char *argv[]) > { > int rc; > u_long code; > SOCKET listen_socket, s; > WSADATA wsaData; > struct sockaddr_in sin; > STARTUPINFO si; > PROCESS_INFORMATION pi; > char command[256]; > > rc = WSAStartup(MAKEWORD(2, 2), &wsaData); > if (rc != NO_ERROR) { > printf("WSAStartup() failed: %dn", rc); > return 2; > } > > if (argc == 2) { > listen_socket = atoi(argv[1]); > printf("Inherited socket: %dn", listen_socket); > goto accept; > } > > listen_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); > if (listen_socket == INVALID_SOCKET) { > printf("socket failed with error: %ldn", WSAGetLastError()); > return 1; > } > > printf("Listen socket: %dn", listen_socket); > > sin.sin_family = AF_INET; > sin.sin_addr.s_addr = inet_addr("127.0.0.1"); > sin.sin_port = htons(8080); > > if (bind(listen_socket, (SOCKADDR *) &sin, sizeof(sin)) == > SOCKET_ERROR) { > printf("bind() failed: %ldn", WSAGetLastError()); > return 1; > } > > if (listen(listen_socket, 1) == SOCKET_ERROR) { > printf("listen() failed: %ldn", WSAGetLastError()); > return 1; > } > > if (argc == 1) { > ZeroMemory(&si, sizeof(si)); > si.cb = sizeof(si); > ZeroMemory(&pi, sizeof(pi)); > > _snprintf(command, sizeof(command), "%s %d", argv[0], listen_socket); > > if (CreateProcess(NULL, command, > NULL, NULL, 1, 0, NULL, NULL, > &si, &pi) > == 0) > { > printf("CreateProcess() failed: %ldn", GetLastError()); > return 1; > } > > WaitForSingleObject(pi.hProcess, INFINITE); > > if (GetExitCodeProcess(pi.hProcess, &code) == 0) { > printf("GetExitCodeProcess() failed: %ldn", GetLastError()); > return 1; > } > > printf("Child process exited: %dn", code); > > CloseHandle(pi.hProcess); > CloseHandle(pi.hThread); > } > > accept: > > printf("Waiting for client to connect...n"); > > s = accept(listen_socket, NULL, NULL); > if (s == INVALID_SOCKET) { > printf("accept() failed: %ldn", WSAGetLastError()); > return 1; > } > > printf("Client connectedn"); > > return 0; > } From ru at nginx.com Wed Jun 17 11:17:37 2015 From: ru at nginx.com (Ruslan Ermilov) Date: Wed, 17 Jun 2015 11:17:37 +0000 Subject: [nginx] Configure: fix tests with multi-level relative build dir... Message-ID: details: http://hg.nginx.org/nginx/rev/acba1656c474 branches: changeset: 6194:acba1656c474 user: Ruslan Ermilov date: Wed Jun 17 14:15:27 2015 +0300 description: Configure: fix tests with multi-level relative build directory. Based on a patch by Piotr Sikora. diffstat: auto/unix | 9 +-------- 1 files changed, 1 insertions(+), 8 deletions(-) diffs (19 lines): diff -r 78c06e5e1d76 -r acba1656c474 auto/unix --- a/auto/unix Tue Jun 16 23:28:38 2015 +0300 +++ b/auto/unix Wed Jun 17 14:15:27 2015 +0300 @@ -505,14 +505,7 @@ ngx_param=NGX_PTR_SIZE; ngx_value=$ngx_s # POSIX types -case "$NGX_AUTO_CONFIG_H" in - /*) - NGX_INCLUDE_AUTO_CONFIG_H="#include \"$NGX_AUTO_CONFIG_H\"" - ;; - *) - NGX_INCLUDE_AUTO_CONFIG_H="#include \"../$NGX_AUTO_CONFIG_H\"" - ;; -esac +NGX_INCLUDE_AUTO_CONFIG_H="#include \"ngx_auto_config.h\"" ngx_type="uint64_t"; ngx_types="u_int64_t"; . auto/types/typedef From ru at nginx.com Wed Jun 17 11:17:40 2015 From: ru at nginx.com (Ruslan Ermilov) Date: Wed, 17 Jun 2015 11:17:40 +0000 Subject: [nginx] Configure: create missing intermediates for build direct... Message-ID: details: http://hg.nginx.org/nginx/rev/e69d5e9be292 branches: changeset: 6195:e69d5e9be292 user: Piotr Sikora date: Wed Jun 10 19:18:19 2015 -0700 description: Configure: create missing intermediates for build directory. Signed-off-by: Piotr Sikora diffstat: auto/configure | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r acba1656c474 -r e69d5e9be292 auto/configure --- a/auto/configure Wed Jun 17 14:15:27 2015 +0300 +++ b/auto/configure Wed Jun 10 19:18:19 2015 -0700 @@ -11,7 +11,7 @@ export LC_ALL . auto/init . auto/sources -test -d $NGX_OBJS || mkdir $NGX_OBJS +test -d $NGX_OBJS || mkdir -p $NGX_OBJS echo > $NGX_AUTO_HEADERS_H echo > $NGX_AUTOCONF_ERR From mdounin at mdounin.ru Wed Jun 17 12:29:41 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 17 Jun 2015 15:29:41 +0300 Subject: Fix windows issue with multiple workers In-Reply-To: References: <64cd3e82b8271b1240c588dc6fece3bb@sebres.de> <20150617022733.GG26357@mdounin.ru> Message-ID: <20150617122941.GJ26357@mdounin.ru> Hello! On Wed, Jun 17, 2015 at 09:58:46AM +0200, Sergey Brester wrote: > Yes, for exactly one child process... The code in question uses the socket in two process, parent and child. > For example, same (modified for multiprocessing) code does not work on my > mashine (win7 x64) for 2nd (3th etc.) process (with error 10022 = INVARG). I > think the handle schould be then duplicated, and see MSDN > (https://msdn.microsoft.com/en-us/library/windows/desktop/ms724251.aspx) If something "modified" doesn't work for you - please be exact and provide the code which doesn't work. Below is the version of the code modified to accept connections in 6 processes simulteniously, and it works fine here. #include #include #include #pragma comment(lib, "Ws2_32.lib") int main(int argc, char *argv[]) { int rc, i; u_long code; SOCKET listen_socket, s; WSADATA wsaData; struct sockaddr_in sin; STARTUPINFO si; PROCESS_INFORMATION pi; char command[256]; rc = WSAStartup(MAKEWORD(2, 2), &wsaData); if (rc != NO_ERROR) { printf("WSAStartup() failed: %d\n", rc); return 2; } if (argc == 2) { listen_socket = atoi(argv[1]); printf("Inherited socket: %d\n", listen_socket); goto accept; } if (argc != 1) { printf("Invalid number of arguments\n"); return 1; } listen_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (listen_socket == INVALID_SOCKET) { printf("socket failed with error: %ld\n", WSAGetLastError()); return 1; } printf("Listen socket: %d\n", listen_socket); sin.sin_family = AF_INET; sin.sin_addr.s_addr = inet_addr("127.0.0.1"); sin.sin_port = htons(8080); if (bind(listen_socket, (SOCKADDR *) &sin, sizeof(sin)) == SOCKET_ERROR) { printf("bind() failed: %ld\n", WSAGetLastError()); return 1; } if (listen(listen_socket, 1) == SOCKET_ERROR) { printf("listen() failed: %ld\n", WSAGetLastError()); return 1; } for (i = 0; i < 5; i++) { ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); ZeroMemory(&pi, sizeof(pi)); _snprintf(command, sizeof(command), "%s %d", argv[0], listen_socket); if (CreateProcess(NULL, command, NULL, NULL, 1, 0, NULL, NULL, &si, &pi) == 0) { printf("CreateProcess() failed: %ld\n", GetLastError()); return 1; } #if 0 WaitForSingleObject(pi.hProcess, INFINITE); if (GetExitCodeProcess(pi.hProcess, &code) == 0) { printf("GetExitCodeProcess() failed: %ld\n", GetLastError()); return 1; } printf("Child process exited: %d\n", code); #endif CloseHandle(pi.hProcess); CloseHandle(pi.hThread); } accept: printf("Waiting for client to connect...\n"); s = accept(listen_socket, NULL, NULL); if (s == INVALID_SOCKET) { printf("accept() failed: %ld\n", WSAGetLastError()); return 1; } printf("Client connected\n"); return 0; } -- Maxim Dounin http://nginx.org/ From serg.brester at sebres.de Wed Jun 17 14:01:17 2015 From: serg.brester at sebres.de (Sergey Brester) Date: Wed, 17 Jun 2015 16:01:17 +0200 Subject: Fix windows issue with multiple workers In-Reply-To: <20150617122941.GJ26357@mdounin.ru> References: <64cd3e82b8271b1240c588dc6fece3bb@sebres.de> <20150617022733.GG26357@mdounin.ru> <20150617122941.GJ26357@mdounin.ru> Message-ID: Hmm, strange - almost same code, but it does not work... only first child can accept connections. Which version of windows are you using for test? Am 17.06.2015 14:29, schrieb Maxim Dounin: > Hello! > > On Wed, Jun 17, 2015 at 09:58:46AM +0200, Sergey Brester wrote: > >> Yes, for exactly one child process... > > The code in question uses the socket in two process, parent and > child. > >> For example, same (modified for multiprocessing) code does not work on >> my mashine (win7 x64) for 2nd (3th etc.) process (with error 10022 = >> INVARG). I think the handle schould be then duplicated, and see MSDN >> (https://msdn.microsoft.com/en-us/library/windows/desktop/ms724251.aspx >> [1]) > > If something "modified" doesn't work for you - please be exact and > provide the code which doesn't work. > > Below is the version of the code modified to accept connections in > 6 processes simulteniously, and it works fine here. > > #include > #include > #include > > #pragma comment(lib, "Ws2_32.lib") > > int > main(int argc, char *argv[]) > { > int rc, i; > u_long code; > SOCKET listen_socket, s; > WSADATA wsaData; > struct sockaddr_in sin; > STARTUPINFO si; > PROCESS_INFORMATION pi; > char command[256]; > > rc = WSAStartup(MAKEWORD(2, 2), &wsaData); > if (rc != NO_ERROR) { > printf("WSAStartup() failed: %dn", rc); > return 2; > } > > if (argc == 2) { > listen_socket = atoi(argv[1]); > printf("Inherited socket: %dn", listen_socket); > goto accept; > } > if (argc != 1) { > printf("Invalid number of argumentsn"); > return 1; > } > > listen_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); > if (listen_socket == INVALID_SOCKET) { > printf("socket failed with error: %ldn", WSAGetLastError()); > return 1; > } > > printf("Listen socket: %dn", listen_socket); > > sin.sin_family = AF_INET; > sin.sin_addr.s_addr = inet_addr("127.0.0.1"); > sin.sin_port = htons(8080); > > if (bind(listen_socket, (SOCKADDR *) &sin, sizeof(sin)) == > SOCKET_ERROR) { > printf("bind() failed: %ldn", WSAGetLastError()); > return 1; > } > > if (listen(listen_socket, 1) == SOCKET_ERROR) { > printf("listen() failed: %ldn", WSAGetLastError()); > return 1; > } > > for (i = 0; i < 5; i++) { > ZeroMemory(&si, sizeof(si)); > si.cb = sizeof(si); > ZeroMemory(&pi, sizeof(pi)); > > _snprintf(command, sizeof(command), "%s %d", argv[0], listen_socket); > > if (CreateProcess(NULL, command, > NULL, NULL, 1, 0, NULL, NULL, > &si, &pi) > == 0) > { > printf("CreateProcess() failed: %ldn", GetLastError()); > return 1; > } > > #if 0 > WaitForSingleObject(pi.hProcess, INFINITE); > > if (GetExitCodeProcess(pi.hProcess, &code) == 0) { > printf("GetExitCodeProcess() failed: %ldn", GetLastError()); > return 1; > } > > printf("Child process exited: %dn", code); > #endif > > CloseHandle(pi.hProcess); > CloseHandle(pi.hThread); > } > > accept: > > printf("Waiting for client to connect...n"); > > s = accept(listen_socket, NULL, NULL); > if (s == INVALID_SOCKET) { > printf("accept() failed: %ldn", WSAGetLastError()); > return 1; > } > > printf("Client connectedn"); > > return 0; > } Links: ------ [1] https://msdn.microsoft.com/en-us/library/windows/desktop/ms724251.aspx From mdounin at mdounin.ru Wed Jun 17 14:52:40 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 17 Jun 2015 17:52:40 +0300 Subject: Fix windows issue with multiple workers In-Reply-To: References: <64cd3e82b8271b1240c588dc6fece3bb@sebres.de> <20150617022733.GG26357@mdounin.ru> <20150617122941.GJ26357@mdounin.ru> Message-ID: <20150617145240.GN26357@mdounin.ru> Hello! On Wed, Jun 17, 2015 at 04:01:17PM +0200, Sergey Brester wrote: > Hmm, strange - almost same code, but it does not work... only first child > can accept connections. Have you tried exactly the code I provided? "Almost the same" is a usual difference between working and non-working code. > Which version of windows are you using for test? Works fine at least in Windows 7 and Windows 8.1 VMs here, both 32-bit. I have no 64-bit Windows on hand to test, but if it doesn't work for you specifically on 64-bit Windows, this may be some minor bug in the test code related to type casting. -- Maxim Dounin http://nginx.org/ From pluknet at nginx.com Wed Jun 17 15:01:09 2015 From: pluknet at nginx.com (Sergey Kandaurov) Date: Wed, 17 Jun 2015 15:01:09 +0000 Subject: [nginx] Resolver: canceled resend timer on empty resend queues. Message-ID: details: http://hg.nginx.org/nginx/rev/c3ec43580a48 branches: changeset: 6196:c3ec43580a48 user: Sergey Kandaurov date: Wed Jun 17 17:57:34 2015 +0300 description: Resolver: canceled resend timer on empty resend queues. This is specifically useful on graceful shutdown. diffstat: src/core/ngx_resolver.c | 20 ++++++++++++++++++++ 1 files changed, 20 insertions(+), 0 deletions(-) diffs (51 lines): diff -r e69d5e9be292 -r c3ec43580a48 src/core/ngx_resolver.c --- a/src/core/ngx_resolver.c Wed Jun 10 19:18:19 2015 -0700 +++ b/src/core/ngx_resolver.c Wed Jun 17 17:57:34 2015 +0300 @@ -71,6 +71,7 @@ static ngx_int_t ngx_resolver_create_add static void ngx_resolver_resend_handler(ngx_event_t *ev); static time_t ngx_resolver_resend(ngx_resolver_t *r, ngx_rbtree_t *tree, ngx_queue_t *queue); +static ngx_uint_t ngx_resolver_resend_empty(ngx_resolver_t *r); static void ngx_resolver_read_response(ngx_event_t *rev); static void ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf, size_t n); @@ -463,6 +464,10 @@ done: ngx_resolver_free_locked(r, ctx); /* unlock alloc mutex */ + + if (r->event->timer_set && ngx_resolver_resend_empty(r)) { + ngx_del_timer(r->event); + } } @@ -1016,6 +1021,10 @@ done: ngx_resolver_free_locked(r, ctx); /* unlock alloc mutex */ + + if (r->event->timer_set && ngx_resolver_resend_empty(r)) { + ngx_del_timer(r->event); + } } @@ -1225,6 +1234,17 @@ ngx_resolver_resend(ngx_resolver_t *r, n } +static ngx_uint_t +ngx_resolver_resend_empty(ngx_resolver_t *r) +{ + return ngx_queue_empty(&r->name_resend_queue) +#if (NGX_HAVE_INET6) + && ngx_queue_empty(&r->addr6_resend_queue) +#endif + && ngx_queue_empty(&r->addr_resend_queue); +} + + static void ngx_resolver_read_response(ngx_event_t *rev) { From kaustubh.deo at gmail.com Wed Jun 17 18:17:06 2015 From: kaustubh.deo at gmail.com (Kaustubh Deorukhkar) Date: Wed, 17 Jun 2015 23:47:06 +0530 Subject: Breaking content generation phase into multiple phases or adding custom events in content phase Message-ID: Hi, I am working on a custom module where I need to use a third party library and make sync/async calls to APIs. I do not have control over what the library does internally but any async API call on library would call a callback which indicates that content generation phase continue with forming response and sending it back to client. Here is psuedo code: - content_handler_called -- some_initializations -- Call library Async API with callback -- nginx should continue processing other events ... -- some point of time the callback is triggered, which should resume the request say by raising a custom event in nginx event loop so nginx can process remaining part of request. As i understand nginx works primarily on events based on sockets but in this case invocation of this library api cannot generate any socket events. Question is how do I pause the current request processing so nginx can continue with other requests and when api callback is trigger, nginx should be able to resume the request processing. Looking at some other modules I found 1> mysql module intercepts the socket calls of libmysqlclient 2> we can use additional socket to communicate between API callback and nginx event loop. 3> I believe openresty lua module should be achieving similar async behavior for content handler phase. 1 is not possible, 2 is a bit bad due to additional sockets. Anyone can throw some light how openresty lua module achieves this? We want to avoid upstream server model if this is already possible with nginx. Is there some mechanism to trigger custom events. Is the nginx event loop thread safe if we have some mechanism to trigger custom events? Hoping for inputs. Thanks in advance!! Kaustubh -------------- next part -------------- An HTML attachment was scrubbed... URL: From agentzh at gmail.com Thu Jun 18 03:27:36 2015 From: agentzh at gmail.com (Yichun Zhang (agentzh)) Date: Thu, 18 Jun 2015 11:27:36 +0800 Subject: Breaking content generation phase into multiple phases or adding custom events in content phase In-Reply-To: References: Message-ID: Hello! On Thu, Jun 18, 2015 at 2:17 AM, Kaustubh Deorukhkar wrote: > I am working on a custom module where I need to use a third party library > and make sync/async calls to APIs. I do not have control over what the > library does internally but any async API call on library would call a > callback which indicates that content generation phase continue with forming > response and sending it back to client. > If you MUST use this 3rd-party library, then you can check out our ngx_drizzle [1] (for nonblocking MySQL communication via libdrizzle) and ngx_postgres [2] (for nonblocking PostgreSQL communication via libpq) for such 3rd-party library integration examples (both of them are production ready for years. But in retrospect, it took a *lot* of developer efforts to get them exactly right due to the inherent limitations in nginx's upstream mechanism and you MAY run into bugs in 3rd-party libraries when using edge-triggered (ET) events (well, we had to work around such issues in libpq, at least). The recommended way is to re-implement the wire protocol for I/O directly in Lua atop the cosocket API [3] provided by the ngx_lua module (or better, use the openresty bundle directly), in the same spirit of the existing lua-resty-mysql [4] and lua-resty-redis [5] libraries out there. > We want to avoid upstream server model if this is already possible with > nginx. > Both ngx_postgres an ngx_drizzle on based on a good part of the stock nginx's upstream mechanism. It's easier to reuse it than coding everything from scratch if you stick with that road. It's worth mentioning that the cosocket mechanism in ngx_lua is a *parallel* implementation to the official upstream thing and overcomes all those limitations in "upstream" and makes things much cleaner and nicer at least on the Lua land. Still, we inherit most (if not all) of the good stuff from the "upstream" facility. You can check out the picture below for some ideas: http://agentzh.org/misc/slides/nginx-conf-2014/images/cosocket.png Best regards, -agentzh [1] https://github.com/openresty/drizzle-nginx-module [2] https://github.com/FRiCKLE/ngx_postgres [3] https://github.com/openresty/lua-nginx-module#ngxsockettcp [4] https://github.com/openresty/lua-resty-mysql [5] https://github.com/openresty/lua-resty-redis From serg.brester at sebres.de Thu Jun 18 09:23:37 2015 From: serg.brester at sebres.de (Sergey Brester) Date: Thu, 18 Jun 2015 11:23:37 +0200 Subject: Fix windows issue with multiple workers In-Reply-To: <20150617145240.GN26357@mdounin.ru> References: <64cd3e82b8271b1240c588dc6fece3bb@sebres.de> <20150617022733.GG26357@mdounin.ru> <20150617122941.GJ26357@mdounin.ru> <20150617145240.GN26357@mdounin.ru> Message-ID: <4312e66540f56c374ecca7634480ddc4@sebres.de> So, in VM it work for me also. I'm assuming that something on my windows work-pc has prevented to inherit listener in this way (driver, LSPs installed (Layered Service Providers), antivirus or something else)... But, why don't you want to use a suggested solution of me? If I will realize the way with "easy" inheritance (with "bInheritHandle" through CreateProcess), it will be not really easier, because: - we have several listener to share, so we should tell all this handles to child process; - bInheritHandle=True in CreateProcess can be a potential risk by not closed handles, if process crashed, and that are not only sockets - thus will arise so-called zombi-handles as half-open (dropped) or half-closed. But for sockets are listening it is extrem. Here is an example when this situation is encountered (* - listener, which process does not exist): netstat /ano | grep 0.0:80 * TCP 0.0.0.0:80 0.0.0.0:0 LISTENING 3824 TCP 0.0.0.0:80 0.0.0.0:0 LISTENING 4378 taskkill /F /PID 3824 ERROR: The process "3824" not found. Unfortunately, it is not guaranteed that new process 4378 accepts connections (because "zombi" listener of 3824 can block it). But also not so good are another zombies, like not closed temp-files, lock-files, pipes etc. You can talk long about "that would be windows bugs", but that are facts. And thus it is instable. Apart from, does not work at all on some mashines (like my work-pc). And the way with WSADuplicateSocket self Microsoft recommends in various articles. If you still want to use the solution with "bInheritHandle", I suggest a compromise: I will make it with selectable option (resp. defines like NGX_WIN32_DUPLICATE_LISTEN and NGX_WIN32_INHERIT_LISTEN). Please tell me your decision. Regards, sebres. Am 17.06.2015 16:52, schrieb Maxim Dounin: > Hello! > > On Wed, Jun 17, 2015 at 04:01:17PM +0200, Sergey Brester wrote: > >> Hmm, strange - almost same code, but it does not work... only first >> child can accept connections. > > Have you tried exactly the code I provided? "Almost the same" > is a usual difference between working and non-working code. > >> Which version of windows are you using for test? > > Works fine at least in Windows 7 and Windows 8.1 VMs here, both > 32-bit. I have no 64-bit Windows on hand to test, but if it > doesn't work for you specifically on 64-bit Windows, this may be > some minor bug in the test code related to type casting. From piotr at cloudflare.com Thu Jun 18 10:39:27 2015 From: piotr at cloudflare.com (Piotr Sikora) Date: Thu, 18 Jun 2015 03:39:27 -0700 Subject: [PATCH] SSL: mark connections as non-reusable before SSL handshake Message-ID: # HG changeset patch # User Piotr Sikora # Date 1434623800 25200 # Thu Jun 18 03:36:40 2015 -0700 # Node ID cda1075a9536257e510b452df084e4cc396ab25d # Parent c3ec43580a48114dfd28186f43e773fcfe211337 SSL: mark connections as non-reusable before SSL handshake. Previously, connections were marked as non-reusable after SSL handshake returned NGX_AGAIN. This meant that SSL callbacks that were using nginx connections could drain the connection on which SSL handshake was being performed on. Signed-off-by: Piotr Sikora diff -r c3ec43580a48 -r cda1075a9536 src/http/ngx_http_request.c --- a/src/http/ngx_http_request.c Wed Jun 17 17:57:34 2015 +0300 +++ b/src/http/ngx_http_request.c Thu Jun 18 03:36:40 2015 -0700 @@ -715,6 +715,8 @@ ngx_http_ssl_handshake(ngx_event_t *rev) return; } + ngx_reusable_connection(c, 0); + rc = ngx_ssl_handshake(c); if (rc == NGX_AGAIN) { @@ -723,8 +725,6 @@ ngx_http_ssl_handshake(ngx_event_t *rev) ngx_add_timer(rev, c->listening->post_accept_timeout); } - ngx_reusable_connection(c, 0); - c->ssl->handler = ngx_http_ssl_handshake_handler; return; } From piotr at cloudflare.com Thu Jun 18 10:39:31 2015 From: piotr at cloudflare.com (Piotr Sikora) Date: Thu, 18 Jun 2015 03:39:31 -0700 Subject: [PATCH] SSL: avoid SSL_CTX_set_tmp_rsa_callback() call with LibreSSL Message-ID: # HG changeset patch # User Piotr Sikora # Date 1434623801 25200 # Thu Jun 18 03:36:41 2015 -0700 # Node ID e0d2520ed65517b581f2565160a89ba93f4f3630 # Parent c3ec43580a48114dfd28186f43e773fcfe211337 SSL: avoid SSL_CTX_set_tmp_rsa_callback() call with LibreSSL. Signed-off-by: Piotr Sikora diff -r c3ec43580a48 -r e0d2520ed655 src/stream/ngx_stream_ssl_module.c --- a/src/stream/ngx_stream_ssl_module.c Wed Jun 17 17:57:34 2015 +0300 +++ b/src/stream/ngx_stream_ssl_module.c Thu Jun 18 03:36:41 2015 -0700 @@ -276,7 +276,9 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); } +#ifndef LIBRESSL_VERSION_NUMBER SSL_CTX_set_tmp_rsa_callback(conf->ssl.ctx, ngx_ssl_rsa512_key_callback); +#endif if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) { return NGX_CONF_ERROR; From piotr at cloudflare.com Thu Jun 18 10:39:34 2015 From: piotr at cloudflare.com (Piotr Sikora) Date: Thu, 18 Jun 2015 03:39:34 -0700 Subject: [PATCH] SSL: guard use of SSLEAY_VERSION_NUMBER Message-ID: <4e0b02f89144cd774e21.1434623974@Piotrs-MacBook-Pro.local> # HG changeset patch # User Piotr Sikora # Date 1434623802 25200 # Thu Jun 18 03:36:42 2015 -0700 # Node ID 4e0b02f89144cd774e213458c1d8f71b59ace1f9 # Parent c3ec43580a48114dfd28186f43e773fcfe211337 SSL: guard use of SSLEAY_VERSION_NUMBER. It has been removed from BoringSSL, which isn't versioned anyway. OPENSSL_VERSION_TEXT can be used to print "built with BoringSSL". Signed-off-by: Piotr Sikora diff -r c3ec43580a48 -r 4e0b02f89144 src/core/nginx.c --- a/src/core/nginx.c Wed Jun 17 17:57:34 2015 +0300 +++ b/src/core/nginx.c Thu Jun 18 03:36:42 2015 -0700 @@ -233,16 +233,22 @@ main(int argc, char *const *argv) #endif #if (NGX_SSL) - if (SSLeay() == SSLEAY_VERSION_NUMBER) { - ngx_write_stderr("built with " OPENSSL_VERSION_TEXT - NGX_LINEFEED); - } else { + +#ifdef SSLEAY_VERSION_NUMBER + if (SSLeay() != SSLEAY_VERSION_NUMBER) { ngx_write_stderr("built with " OPENSSL_VERSION_TEXT " (running with "); ngx_write_stderr((char *) (uintptr_t) SSLeay_version(SSLEAY_VERSION)); ngx_write_stderr(")" NGX_LINEFEED); + + } else +#endif + { + ngx_write_stderr("built with " OPENSSL_VERSION_TEXT + NGX_LINEFEED); } + #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME ngx_write_stderr("TLS SNI support enabled" NGX_LINEFEED); #else From piotr at cloudflare.com Thu Jun 18 10:39:37 2015 From: piotr at cloudflare.com (Piotr Sikora) Date: Thu, 18 Jun 2015 03:39:37 -0700 Subject: [PATCH] SSL: guard use of SSL_R_BLOCK_CIPHER_PAD_IS_WRONG Message-ID: <2cf1105061a2e952865f.1434623977@Piotrs-MacBook-Pro.local> # HG changeset patch # User Piotr Sikora # Date 1434623802 25200 # Thu Jun 18 03:36:42 2015 -0700 # Node ID 2cf1105061a2e952865f81ffad560c5e9b0843fa # Parent c3ec43580a48114dfd28186f43e773fcfe211337 SSL: guard use of SSL_R_BLOCK_CIPHER_PAD_IS_WRONG. It has been removed from BoringSSL. Signed-off-by: Piotr Sikora diff -r c3ec43580a48 -r 2cf1105061a2 src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c Wed Jun 17 17:57:34 2015 +0300 +++ b/src/event/ngx_event_openssl.c Thu Jun 18 03:36:42 2015 -0700 @@ -1905,7 +1905,9 @@ ngx_ssl_connection_error(ngx_connection_ /* handshake failures */ if (n == SSL_R_BAD_CHANGE_CIPHER_SPEC /* 103 */ +#ifdef SSL_R_BLOCK_CIPHER_PAD_IS_WRONG || n == SSL_R_BLOCK_CIPHER_PAD_IS_WRONG /* 129 */ +#endif || n == SSL_R_DIGEST_CHECK_FAILED /* 149 */ || n == SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST /* 151 */ || n == SSL_R_EXCESSIVE_MESSAGE_SIZE /* 152 */ From piotr at cloudflare.com Thu Jun 18 10:39:40 2015 From: piotr at cloudflare.com (Piotr Sikora) Date: Thu, 18 Jun 2015 03:39:40 -0700 Subject: [PATCH] SSL: cast hostname in SSL_set_tlsext_host_name() Message-ID: <175c159113f26dac29f2.1434623980@Piotrs-MacBook-Pro.local> # HG changeset patch # User Piotr Sikora # Date 1434623803 25200 # Thu Jun 18 03:36:43 2015 -0700 # Node ID 175c159113f26dac29f246b01a9195d90551ee3c # Parent c3ec43580a48114dfd28186f43e773fcfe211337 SSL: cast hostname in SSL_set_tlsext_host_name(). Both OpenSSL and LibreSSL use macros and type casts to implement SSL_{CTX_}set_* functions, but BoringSSL promoted them to proper functions, so they require parameters with correct types now. Signed-off-by: Piotr Sikora diff -r c3ec43580a48 -r 175c159113f2 src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c Wed Jun 17 17:57:34 2015 +0300 +++ b/src/http/ngx_http_upstream.c Thu Jun 18 03:36:43 2015 -0700 @@ -1657,7 +1657,9 @@ ngx_http_upstream_ssl_name(ngx_http_requ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "upstream SSL server name: \"%s\"", name.data); - if (SSL_set_tlsext_host_name(c->ssl->connection, name.data) == 0) { + if (SSL_set_tlsext_host_name(c->ssl->connection, (const char *) name.data) + == 0) + { ngx_ssl_error(NGX_LOG_ERR, r->connection->log, 0, "SSL_set_tlsext_host_name(\"%s\") failed", name.data); return NGX_ERROR; diff -r c3ec43580a48 -r 175c159113f2 src/stream/ngx_stream_proxy_module.c --- a/src/stream/ngx_stream_proxy_module.c Wed Jun 17 17:57:34 2015 +0300 +++ b/src/stream/ngx_stream_proxy_module.c Thu Jun 18 03:36:43 2015 -0700 @@ -792,7 +792,8 @@ ngx_stream_proxy_ssl_name(ngx_stream_ses ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0, "upstream SSL server name: \"%s\"", name.data); - if (SSL_set_tlsext_host_name(u->peer.connection->ssl->connection, name.data) + if (SSL_set_tlsext_host_name(u->peer.connection->ssl->connection, + (const char *) name.data) == 0) { ngx_ssl_error(NGX_LOG_ERR, s->connection->log, 0, From jefftk at google.com Thu Jun 18 11:06:34 2015 From: jefftk at google.com (Jeff Kaufman) Date: Thu, 18 Jun 2015 07:06:34 -0400 Subject: Breaking content generation phase into multiple phases or adding custom events in content phase In-Reply-To: References: Message-ID: ngx_pagespeed does this by giving nginx a pipe to watch, setting up a handler for that pipe, calling an async api that uses threads, then the from the callback writing a byte to the pipe. Now when the async code finishes we're back on the nginx event loop in the pipe's handler. On Wed, Jun 17, 2015 at 11:27 PM, Yichun Zhang (agentzh) wrote: > Hello! > > On Thu, Jun 18, 2015 at 2:17 AM, Kaustubh Deorukhkar wrote: >> I am working on a custom module where I need to use a third party library >> and make sync/async calls to APIs. I do not have control over what the >> library does internally but any async API call on library would call a >> callback which indicates that content generation phase continue with forming >> response and sending it back to client. >> > > If you MUST use this 3rd-party library, then you can check out our > ngx_drizzle [1] (for nonblocking MySQL communication via libdrizzle) > and ngx_postgres [2] (for nonblocking PostgreSQL communication via > libpq) for such 3rd-party library integration examples (both of them > are production ready for years. > > But in retrospect, it took a *lot* of developer efforts to get them > exactly right due to the inherent limitations in nginx's upstream > mechanism and you MAY run into bugs in 3rd-party libraries when using > edge-triggered (ET) events (well, we had to work around such issues in > libpq, at least). > > The recommended way is to re-implement the wire protocol for I/O > directly in Lua atop the cosocket API [3] provided by the ngx_lua > module (or better, use the openresty bundle directly), in the same > spirit of the existing lua-resty-mysql [4] and lua-resty-redis [5] > libraries out there. > >> We want to avoid upstream server model if this is already possible with >> nginx. >> > > Both ngx_postgres an ngx_drizzle on based on a good part of the stock > nginx's upstream mechanism. It's easier to reuse it than coding > everything from scratch if you stick with that road. > > It's worth mentioning that the cosocket mechanism in ngx_lua is a > *parallel* implementation to the official upstream thing and overcomes > all those limitations in "upstream" and makes things much cleaner and > nicer at least on the Lua land. Still, we inherit most (if not all) of > the good stuff from the "upstream" facility. You can check out the > picture below for some ideas: > > http://agentzh.org/misc/slides/nginx-conf-2014/images/cosocket.png > > Best regards, > -agentzh > > [1] https://github.com/openresty/drizzle-nginx-module > [2] https://github.com/FRiCKLE/ngx_postgres > [3] https://github.com/openresty/lua-nginx-module#ngxsockettcp > [4] https://github.com/openresty/lua-resty-mysql > [5] https://github.com/openresty/lua-resty-redis > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel From vl at nginx.com Thu Jun 18 11:18:40 2015 From: vl at nginx.com (Vladimir Homutov) Date: Thu, 18 Jun 2015 11:18:40 +0000 Subject: [nginx] Stream: connection limiting module. Message-ID: details: http://hg.nginx.org/nginx/rev/0dcef374b8bb branches: changeset: 6197:0dcef374b8bb user: Vladimir Homutov date: Thu Jun 18 14:17:30 2015 +0300 description: Stream: connection limiting module. stream { limit_conn_zone $binary_remote_addr zone=perip:1m; limit_conn_log_level error; server { ... limit_conn perip 1; } } diffstat: auto/modules | 5 + auto/options | 4 + auto/sources | 3 + src/stream/ngx_stream.h | 1 + src/stream/ngx_stream_handler.c | 9 + src/stream/ngx_stream_limit_conn_module.c | 632 ++++++++++++++++++++++++++++++ 6 files changed, 654 insertions(+), 0 deletions(-) diffs (truncated from 722 to 300 lines): diff -r c3ec43580a48 -r 0dcef374b8bb auto/modules --- a/auto/modules Wed Jun 17 17:57:34 2015 +0300 +++ b/auto/modules Thu Jun 18 14:17:30 2015 +0300 @@ -514,6 +514,11 @@ if [ $STREAM = YES ]; then STREAM_SRCS="$STREAM_SRCS $STREAM_SSL_SRCS" fi + if [ $STREAM_LIMIT_CONN = YES ]; then + modules="$modules $STREAM_LIMIT_CONN_MODULE" + STREAM_SRCS="$STREAM_SRCS $STREAM_LIMIT_CONN_SRCS" + fi + if [ $STREAM_ACCESS = YES ]; then modules="$modules $STREAM_ACCESS_MODULE" STREAM_SRCS="$STREAM_SRCS $STREAM_ACCESS_SRCS" diff -r c3ec43580a48 -r 0dcef374b8bb auto/options --- a/auto/options Wed Jun 17 17:57:34 2015 +0300 +++ b/auto/options Thu Jun 18 14:17:30 2015 +0300 @@ -113,6 +113,7 @@ MAIL_SMTP=YES STREAM=NO STREAM_SSL=NO +STREAM_LIMIT_CONN=YES STREAM_ACCESS=YES STREAM_UPSTREAM_HASH=YES STREAM_UPSTREAM_LEAST_CONN=YES @@ -283,6 +284,8 @@ use the \"--with-mail_ssl_module\" optio --with-stream) STREAM=YES ;; --with-stream_ssl_module) STREAM_SSL=YES ;; + --without-stream_limit_conn_module) + STREAM_LIMIT_CONN=NO ;; --without-stream_access_module) STREAM_ACCESS=NO ;; --without-stream_upstream_hash_module) STREAM_UPSTREAM_HASH=NO ;; @@ -452,6 +455,7 @@ cat << END --with-stream enable TCP proxy module --with-stream_ssl_module enable ngx_stream_ssl_module + --without-stream_limit_conn_module disable ngx_stream_limit_conn_module --without-stream_access_module disable ngx_stream_access_module --without-stream_upstream_hash_module disable ngx_stream_upstream_hash_module diff -r c3ec43580a48 -r 0dcef374b8bb auto/sources --- a/auto/sources Wed Jun 17 17:57:34 2015 +0300 +++ b/auto/sources Thu Jun 18 14:17:30 2015 +0300 @@ -568,6 +568,9 @@ STREAM_SSL_MODULE="ngx_stream_ssl_module STREAM_SSL_DEPS="src/stream/ngx_stream_ssl_module.h" STREAM_SSL_SRCS="src/stream/ngx_stream_ssl_module.c" +STREAM_LIMIT_CONN_MODULE=ngx_stream_limit_conn_module +STREAM_LIMIT_CONN_SRCS=src/stream/ngx_stream_limit_conn_module.c + STREAM_ACCESS_MODULE=ngx_stream_access_module STREAM_ACCESS_SRCS=src/stream/ngx_stream_access_module.c diff -r c3ec43580a48 -r 0dcef374b8bb src/stream/ngx_stream.h --- a/src/stream/ngx_stream.h Wed Jun 17 17:57:34 2015 +0300 +++ b/src/stream/ngx_stream.h Thu Jun 18 14:17:30 2015 +0300 @@ -118,6 +118,7 @@ typedef ngx_int_t (*ngx_stream_access_pt typedef struct { ngx_array_t servers; /* ngx_stream_core_srv_conf_t */ ngx_array_t listen; /* ngx_stream_listen_t */ + ngx_stream_access_pt limit_conn_handler; ngx_stream_access_pt access_handler; } ngx_stream_core_main_conf_t; diff -r c3ec43580a48 -r 0dcef374b8bb src/stream/ngx_stream_handler.c --- a/src/stream/ngx_stream_handler.c Wed Jun 17 17:57:34 2015 +0300 +++ b/src/stream/ngx_stream_handler.c Thu Jun 18 14:17:30 2015 +0300 @@ -147,6 +147,15 @@ ngx_stream_init_connection(ngx_connectio cmcf = ngx_stream_get_module_main_conf(s, ngx_stream_core_module); + if (cmcf->limit_conn_handler) { + rc = cmcf->limit_conn_handler(s); + + if (rc != NGX_DECLINED) { + ngx_stream_close_connection(c); + return; + } + } + if (cmcf->access_handler) { rc = cmcf->access_handler(s); diff -r c3ec43580a48 -r 0dcef374b8bb src/stream/ngx_stream_limit_conn_module.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/stream/ngx_stream_limit_conn_module.c Thu Jun 18 14:17:30 2015 +0300 @@ -0,0 +1,632 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + + +typedef struct { + u_char color; + u_char len; + u_short conn; + u_char data[1]; +} ngx_stream_limit_conn_node_t; + + +typedef struct { + ngx_shm_zone_t *shm_zone; + ngx_rbtree_node_t *node; +} ngx_stream_limit_conn_cleanup_t; + + +typedef struct { + ngx_rbtree_t *rbtree; +} ngx_stream_limit_conn_ctx_t; + + +typedef struct { + ngx_shm_zone_t *shm_zone; + ngx_uint_t conn; +} ngx_stream_limit_conn_limit_t; + + +typedef struct { + ngx_array_t limits; + ngx_uint_t log_level; +} ngx_stream_limit_conn_conf_t; + + +static ngx_rbtree_node_t *ngx_stream_limit_conn_lookup(ngx_rbtree_t *rbtree, + ngx_str_t *key, uint32_t hash); +static void ngx_stream_limit_conn_cleanup(void *data); +static ngx_inline void ngx_stream_limit_conn_cleanup_all(ngx_pool_t *pool); + +static void *ngx_stream_limit_conn_create_conf(ngx_conf_t *cf); +static char *ngx_stream_limit_conn_merge_conf(ngx_conf_t *cf, void *parent, + void *child); +static char *ngx_stream_limit_conn_zone(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); +static char *ngx_stream_limit_conn(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); +static ngx_int_t ngx_stream_limit_conn_init(ngx_conf_t *cf); + + +static ngx_conf_enum_t ngx_stream_limit_conn_log_levels[] = { + { ngx_string("info"), NGX_LOG_INFO }, + { ngx_string("notice"), NGX_LOG_NOTICE }, + { ngx_string("warn"), NGX_LOG_WARN }, + { ngx_string("error"), NGX_LOG_ERR }, + { ngx_null_string, 0 } +}; + + +static ngx_command_t ngx_stream_limit_conn_commands[] = { + + { ngx_string("limit_conn_zone"), + NGX_STREAM_MAIN_CONF|NGX_CONF_TAKE2, + ngx_stream_limit_conn_zone, + 0, + 0, + NULL }, + + { ngx_string("limit_conn"), + NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE2, + ngx_stream_limit_conn, + NGX_STREAM_SRV_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("limit_conn_log_level"), + NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_enum_slot, + NGX_STREAM_SRV_CONF_OFFSET, + offsetof(ngx_stream_limit_conn_conf_t, log_level), + &ngx_stream_limit_conn_log_levels }, + + ngx_null_command +}; + + +static ngx_stream_module_t ngx_stream_limit_conn_module_ctx = { + ngx_stream_limit_conn_init, /* postconfiguration */ + + NULL, /* create main configuration */ + NULL, /* init main configuration */ + + ngx_stream_limit_conn_create_conf, /* create server configuration */ + ngx_stream_limit_conn_merge_conf, /* merge server configuration */ +}; + + +ngx_module_t ngx_stream_limit_conn_module = { + NGX_MODULE_V1, + &ngx_stream_limit_conn_module_ctx, /* module context */ + ngx_stream_limit_conn_commands, /* module directives */ + NGX_STREAM_MODULE, /* module type */ + NULL, /* init master */ + NULL, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + + +static ngx_int_t +ngx_stream_limit_conn_handler(ngx_stream_session_t *s) +{ + size_t n; + uint32_t hash; + ngx_str_t key; + ngx_uint_t i; + ngx_slab_pool_t *shpool; + ngx_rbtree_node_t *node; + ngx_pool_cleanup_t *cln; + struct sockaddr_in *sin; +#if (NGX_HAVE_INET6) + struct sockaddr_in6 *sin6; +#endif + ngx_stream_limit_conn_ctx_t *ctx; + ngx_stream_limit_conn_node_t *lc; + ngx_stream_limit_conn_conf_t *lccf; + ngx_stream_limit_conn_limit_t *limits; + ngx_stream_limit_conn_cleanup_t *lccln; + + switch (s->connection->sockaddr->sa_family) { + + case AF_INET: + sin = (struct sockaddr_in *) s->connection->sockaddr; + + key.len = sizeof(in_addr_t); + key.data = (u_char *) &sin->sin_addr; + + break; + +#if (NGX_HAVE_INET6) + case AF_INET6: + sin6 = (struct sockaddr_in6 *) s->connection->sockaddr; + + key.len = sizeof(struct in6_addr); + key.data = sin6->sin6_addr.s6_addr; + + break; +#endif + + default: + return NGX_DECLINED; + } + + hash = ngx_crc32_short(key.data, key.len); + + lccf = ngx_stream_get_module_srv_conf(s, ngx_stream_limit_conn_module); + limits = lccf->limits.elts; + + for (i = 0; i < lccf->limits.nelts; i++) { + ctx = limits[i].shm_zone->data; + + shpool = (ngx_slab_pool_t *) limits[i].shm_zone->shm.addr; + + ngx_shmtx_lock(&shpool->mutex); + + node = ngx_stream_limit_conn_lookup(ctx->rbtree, &key, hash); + + if (node == NULL) { + + n = offsetof(ngx_rbtree_node_t, color) + + offsetof(ngx_stream_limit_conn_node_t, data) + + key.len; + + node = ngx_slab_alloc_locked(shpool, n); + + if (node == NULL) { + ngx_shmtx_unlock(&shpool->mutex); + ngx_stream_limit_conn_cleanup_all(s->connection->pool); + return NGX_ABORT; + } + + lc = (ngx_stream_limit_conn_node_t *) &node->color; + + node->key = hash; + lc->len = (u_char) key.len; + lc->conn = 1; + ngx_memcpy(lc->data, key.data, key.len); + + ngx_rbtree_insert(ctx->rbtree, node); + + } else { + + lc = (ngx_stream_limit_conn_node_t *) &node->color; + + if ((ngx_uint_t) lc->conn >= limits[i].conn) { + + ngx_shmtx_unlock(&shpool->mutex); + From ru at nginx.com Thu Jun 18 14:34:09 2015 From: ru at nginx.com (Ruslan Ermilov) Date: Thu, 18 Jun 2015 14:34:09 +0000 Subject: [nginx] Upstream: fixed shared upstreams on win32. Message-ID: details: http://hg.nginx.org/nginx/rev/311d232ad803 branches: changeset: 6198:311d232ad803 user: Ruslan Ermilov date: Tue Jun 16 00:43:00 2015 +0300 description: Upstream: fixed shared upstreams on win32. diffstat: src/http/modules/ngx_http_upstream_zone_module.c | 43 +++++++++++++++++------ src/http/ngx_http_upstream_round_robin.h | 1 + src/stream/ngx_stream_upstream_round_robin.h | 1 + src/stream/ngx_stream_upstream_zone_module.c | 43 +++++++++++++++++------ 4 files changed, 64 insertions(+), 24 deletions(-) diffs (264 lines): diff -r 0dcef374b8bb -r 311d232ad803 src/http/modules/ngx_http_upstream_zone_module.c --- a/src/http/modules/ngx_http_upstream_zone_module.c Thu Jun 18 14:17:30 2015 +0300 +++ b/src/http/modules/ngx_http_upstream_zone_module.c Tue Jun 16 00:43:00 2015 +0300 @@ -14,8 +14,8 @@ static char *ngx_http_upstream_zone(ngx_ void *conf); static ngx_int_t ngx_http_upstream_init_zone(ngx_shm_zone_t *shm_zone, void *data); -static ngx_int_t ngx_http_upstream_zone_copy_peers(ngx_slab_pool_t *shpool, - ngx_http_upstream_srv_conf_t *uscf); +static ngx_http_upstream_rr_peers_t *ngx_http_upstream_zone_copy_peers( + ngx_slab_pool_t *shpool, ngx_http_upstream_srv_conf_t *uscf); static ngx_command_t ngx_http_upstream_zone_commands[] = { @@ -121,13 +121,29 @@ ngx_http_upstream_init_zone(ngx_shm_zone size_t len; ngx_uint_t i; ngx_slab_pool_t *shpool; + ngx_http_upstream_rr_peers_t *peers, **peersp; ngx_http_upstream_srv_conf_t *uscf, **uscfp; ngx_http_upstream_main_conf_t *umcf; shpool = (ngx_slab_pool_t *) shm_zone->shm.addr; + umcf = shm_zone->data; + uscfp = umcf->upstreams.elts; if (shm_zone->shm.exists) { - return NGX_ERROR; + peers = shpool->data; + + for (i = 0; i < umcf->upstreams.nelts; i++) { + uscf = uscfp[i]; + + if (uscf->shm_zone != shm_zone) { + continue; + } + + uscf->peer.data = peers; + peers = peers->zone_next; + } + + return NGX_OK; } len = sizeof(" in upstream zone \"\"") + shm_zone->shm.name.len; @@ -143,8 +159,7 @@ ngx_http_upstream_init_zone(ngx_shm_zone /* copy peers to shared memory */ - umcf = shm_zone->data; - uscfp = umcf->upstreams.elts; + peersp = (ngx_http_upstream_rr_peers_t **) &shpool->data; for (i = 0; i < umcf->upstreams.nelts; i++) { uscf = uscfp[i]; @@ -153,16 +168,20 @@ ngx_http_upstream_init_zone(ngx_shm_zone continue; } - if (ngx_http_upstream_zone_copy_peers(shpool, uscf) != NGX_OK) { + peers = ngx_http_upstream_zone_copy_peers(shpool, uscf); + if (peers == NULL) { return NGX_ERROR; } + + *peersp = peers; + peersp = &peers->zone_next; } return NGX_OK; } -static ngx_int_t +static ngx_http_upstream_rr_peers_t * ngx_http_upstream_zone_copy_peers(ngx_slab_pool_t *shpool, ngx_http_upstream_srv_conf_t *uscf) { @@ -171,7 +190,7 @@ ngx_http_upstream_zone_copy_peers(ngx_sl peers = ngx_slab_alloc(shpool, sizeof(ngx_http_upstream_rr_peers_t)); if (peers == NULL) { - return NGX_ERROR; + return NULL; } ngx_memcpy(peers, uscf->peer.data, sizeof(ngx_http_upstream_rr_peers_t)); @@ -183,7 +202,7 @@ ngx_http_upstream_zone_copy_peers(ngx_sl peer = ngx_slab_calloc_locked(shpool, sizeof(ngx_http_upstream_rr_peer_t)); if (peer == NULL) { - return NGX_ERROR; + return NULL; } ngx_memcpy(peer, *peerp, sizeof(ngx_http_upstream_rr_peer_t)); @@ -197,7 +216,7 @@ ngx_http_upstream_zone_copy_peers(ngx_sl backup = ngx_slab_alloc(shpool, sizeof(ngx_http_upstream_rr_peers_t)); if (backup == NULL) { - return NGX_ERROR; + return NULL; } ngx_memcpy(backup, peers->next, sizeof(ngx_http_upstream_rr_peers_t)); @@ -209,7 +228,7 @@ ngx_http_upstream_zone_copy_peers(ngx_sl peer = ngx_slab_calloc_locked(shpool, sizeof(ngx_http_upstream_rr_peer_t)); if (peer == NULL) { - return NGX_ERROR; + return NULL; } ngx_memcpy(peer, *peerp, sizeof(ngx_http_upstream_rr_peer_t)); @@ -223,5 +242,5 @@ done: uscf->peer.data = peers; - return NGX_OK; + return peers; } diff -r 0dcef374b8bb -r 311d232ad803 src/http/ngx_http_upstream_round_robin.h --- a/src/http/ngx_http_upstream_round_robin.h Thu Jun 18 14:17:30 2015 +0300 +++ b/src/http/ngx_http_upstream_round_robin.h Tue Jun 16 00:43:00 2015 +0300 @@ -58,6 +58,7 @@ struct ngx_http_upstream_rr_peers_s { #if (NGX_HTTP_UPSTREAM_ZONE) ngx_slab_pool_t *shpool; ngx_atomic_t rwlock; + ngx_http_upstream_rr_peers_t *zone_next; #endif ngx_uint_t total_weight; diff -r 0dcef374b8bb -r 311d232ad803 src/stream/ngx_stream_upstream_round_robin.h --- a/src/stream/ngx_stream_upstream_round_robin.h Thu Jun 18 14:17:30 2015 +0300 +++ b/src/stream/ngx_stream_upstream_round_robin.h Tue Jun 16 00:43:00 2015 +0300 @@ -58,6 +58,7 @@ struct ngx_stream_upstream_rr_peers_s { #if (NGX_STREAM_UPSTREAM_ZONE) ngx_slab_pool_t *shpool; ngx_atomic_t rwlock; + ngx_stream_upstream_rr_peers_t *zone_next; #endif ngx_uint_t total_weight; diff -r 0dcef374b8bb -r 311d232ad803 src/stream/ngx_stream_upstream_zone_module.c --- a/src/stream/ngx_stream_upstream_zone_module.c Thu Jun 18 14:17:30 2015 +0300 +++ b/src/stream/ngx_stream_upstream_zone_module.c Tue Jun 16 00:43:00 2015 +0300 @@ -14,8 +14,8 @@ static char *ngx_stream_upstream_zone(ng void *conf); static ngx_int_t ngx_stream_upstream_init_zone(ngx_shm_zone_t *shm_zone, void *data); -static ngx_int_t ngx_stream_upstream_zone_copy_peers(ngx_slab_pool_t *shpool, - ngx_stream_upstream_srv_conf_t *uscf); +static ngx_stream_upstream_rr_peers_t *ngx_stream_upstream_zone_copy_peers( + ngx_slab_pool_t *shpool, ngx_stream_upstream_srv_conf_t *uscf); static ngx_command_t ngx_stream_upstream_zone_commands[] = { @@ -117,13 +117,29 @@ ngx_stream_upstream_init_zone(ngx_shm_zo size_t len; ngx_uint_t i; ngx_slab_pool_t *shpool; + ngx_stream_upstream_rr_peers_t *peers, **peersp; ngx_stream_upstream_srv_conf_t *uscf, **uscfp; ngx_stream_upstream_main_conf_t *umcf; shpool = (ngx_slab_pool_t *) shm_zone->shm.addr; + umcf = shm_zone->data; + uscfp = umcf->upstreams.elts; if (shm_zone->shm.exists) { - return NGX_ERROR; + peers = shpool->data; + + for (i = 0; i < umcf->upstreams.nelts; i++) { + uscf = uscfp[i]; + + if (uscf->shm_zone != shm_zone) { + continue; + } + + uscf->peer.data = peers; + peers = peers->zone_next; + } + + return NGX_OK; } len = sizeof(" in upstream zone \"\"") + shm_zone->shm.name.len; @@ -139,8 +155,7 @@ ngx_stream_upstream_init_zone(ngx_shm_zo /* copy peers to shared memory */ - umcf = shm_zone->data; - uscfp = umcf->upstreams.elts; + peersp = (ngx_stream_upstream_rr_peers_t **) &shpool->data; for (i = 0; i < umcf->upstreams.nelts; i++) { uscf = uscfp[i]; @@ -149,16 +164,20 @@ ngx_stream_upstream_init_zone(ngx_shm_zo continue; } - if (ngx_stream_upstream_zone_copy_peers(shpool, uscf) != NGX_OK) { + peers = ngx_stream_upstream_zone_copy_peers(shpool, uscf); + if (peers == NULL) { return NGX_ERROR; } + + *peersp = peers; + peersp = &peers->zone_next; } return NGX_OK; } -static ngx_int_t +static ngx_stream_upstream_rr_peers_t * ngx_stream_upstream_zone_copy_peers(ngx_slab_pool_t *shpool, ngx_stream_upstream_srv_conf_t *uscf) { @@ -167,7 +186,7 @@ ngx_stream_upstream_zone_copy_peers(ngx_ peers = ngx_slab_alloc(shpool, sizeof(ngx_stream_upstream_rr_peers_t)); if (peers == NULL) { - return NGX_ERROR; + return NULL; } ngx_memcpy(peers, uscf->peer.data, sizeof(ngx_stream_upstream_rr_peers_t)); @@ -179,7 +198,7 @@ ngx_stream_upstream_zone_copy_peers(ngx_ peer = ngx_slab_calloc_locked(shpool, sizeof(ngx_stream_upstream_rr_peer_t)); if (peer == NULL) { - return NGX_ERROR; + return NULL; } ngx_memcpy(peer, *peerp, sizeof(ngx_stream_upstream_rr_peer_t)); @@ -193,7 +212,7 @@ ngx_stream_upstream_zone_copy_peers(ngx_ backup = ngx_slab_alloc(shpool, sizeof(ngx_stream_upstream_rr_peers_t)); if (backup == NULL) { - return NGX_ERROR; + return NULL; } ngx_memcpy(backup, peers->next, sizeof(ngx_stream_upstream_rr_peers_t)); @@ -205,7 +224,7 @@ ngx_stream_upstream_zone_copy_peers(ngx_ peer = ngx_slab_calloc_locked(shpool, sizeof(ngx_stream_upstream_rr_peer_t)); if (peer == NULL) { - return NGX_ERROR; + return NULL; } ngx_memcpy(peer, *peerp, sizeof(ngx_stream_upstream_rr_peer_t)); @@ -219,5 +238,5 @@ done: uscf->peer.data = peers; - return NGX_OK; + return peers; } From mdounin at mdounin.ru Thu Jun 18 19:55:12 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 18 Jun 2015 22:55:12 +0300 Subject: Fix windows issue with multiple workers In-Reply-To: <4312e66540f56c374ecca7634480ddc4@sebres.de> References: <64cd3e82b8271b1240c588dc6fece3bb@sebres.de> <20150617022733.GG26357@mdounin.ru> <20150617122941.GJ26357@mdounin.ru> <20150617145240.GN26357@mdounin.ru> <4312e66540f56c374ecca7634480ddc4@sebres.de> Message-ID: <20150618195512.GW26357@mdounin.ru> Hello! On Thu, Jun 18, 2015 at 11:23:37AM +0200, Sergey Brester wrote: > So, in VM it work for me also. > > I'm assuming that something on my windows work-pc has prevented to inherit > listener in this way (driver, LSPs installed (Layered Service Providers), > antivirus or something else)... Quick search suggests that yes, some LSPs can break socket handle inheritance, see, e.g.: http://stackoverflow.com/questions/11847793/are-tcp-socket-handles-inheritable http://stackoverflow.com/questions/12058911/can-tcp-socket-handles-be-set-not-inheritable We probably want to dig a bit more into this, to make sure common LSPs can be easily switched off to won't interfere with nginx. > But, why don't you want to use a suggested solution of me? As I already tried to explain, the approach with inherited sockets is basically identical to what nginx does on UNIX with fork(). There are no reasons to keep things different if you can do it similarly on both platforms. As long as the problem with LSPs isn't common and/or solvable, I would prefer the inherited sockets approach to the alternatives. This approach is also required to upgrade executable on the fly (though supporting this on Windows will likely require more work). > If I will realize the way with "easy" inheritance (with "bInheritHandle" > through CreateProcess), it will be not really easier, because: > > - we have several listener to share, so we should tell all this handles to > child process; That's already implemented, see above. > - bInheritHandle=True in CreateProcess can be a potential risk by not closed > handles, if process crashed, and that are not only sockets - thus will arise > so-called zombi-handles as half-open (dropped) or half-closed. But for > sockets are listening it is extrem. Here is an example when this situation > is encountered (* - listener, which process does not exist): > > netstat /ano | grep 0.0:80 > * TCP 0.0.0.0:80 0.0.0.0:0 LISTENING 3824 > TCP 0.0.0.0:80 0.0.0.0:0 LISTENING 4378 > > taskkill /F /PID 3824 > ERROR: The process "3824" not found. As far as I understand, this just means that the process that created the socket already exited. It doesn't mean that the socket isn't used at all - as long as you properly track inherited sockets. And this is what nginx already knows how to do. > Unfortunately, it is not guaranteed that new process 4378 accepts > connections (because "zombi" listener of 3824 can block it). > But also not so good are another zombies, like not closed temp-files, > lock-files, pipes etc. As far as I understand, no other handles are inheritable by default, sockets are the only exception. > You can talk long about "that would be windows bugs", but that are facts. > And thus it is instable. Apart from, does not work at all on some mashines > (like my work-pc). > And the way with WSADuplicateSocket self Microsoft recommends in various > articles. So, the only real problem seems to be LSPs. > If you still want to use the solution with "bInheritHandle", I suggest a > compromise: > I will make it with selectable option (resp. defines like > NGX_WIN32_DUPLICATE_LISTEN and NGX_WIN32_INHERIT_LISTEN). The goal is to minimize code bloat, not maximize it. -- Maxim Dounin http://nginx.org/ From agentzh at gmail.com Fri Jun 19 03:06:22 2015 From: agentzh at gmail.com (Yichun Zhang (agentzh)) Date: Fri, 19 Jun 2015 11:06:22 +0800 Subject: Breaking content generation phase into multiple phases or adding custom events in content phase In-Reply-To: References: Message-ID: Hello! On Thu, Jun 18, 2015 at 7:06 PM, Jeff Kaufman wrote: > ngx_pagespeed does this by giving nginx a pipe to watch, setting up a > handler for that pipe, calling an async api that uses threads, then > the from the callback writing a byte to the pipe. Now when the async > code finishes we're back on the nginx event loop in the pipe's > handler. > Extra OS threads add their own complexity and overhead (killing C10K, for example), which I think we should avoid wherever we can (well, disk I/O cannot be nonblocking and we should only use thread pools for that). Well, just my 2 cents. Regards, -agentzh From jefftk at google.com Fri Jun 19 12:35:27 2015 From: jefftk at google.com (Jeff Kaufman) Date: Fri, 19 Jun 2015 08:35:27 -0400 Subject: Breaking content generation phase into multiple phases or adding custom events in content phase In-Reply-To: References: Message-ID: The two other things that ngx_pagespeed needs to use OS threads for: * image optimization: blocking the nginx event loop to recompress large images gives you very visible stalls * background optimization: we want to return whatever we have to the user, and then go on optimizing resources this request referenced in the background But yes, this (and parsing all the html as it flows through) does keep you from hitting C10K. I'm currently playing with some designs for a lighter version of PageSpeed that drops optimizations that can't be implemented efficiently or 100% safely, and I think it should be able to support nearly as many clients as standard nginx. It would still use a background thread for image optimization, though. On Thu, Jun 18, 2015 at 11:06 PM, Yichun Zhang (agentzh) wrote: > Hello! > > On Thu, Jun 18, 2015 at 7:06 PM, Jeff Kaufman wrote: >> ngx_pagespeed does this by giving nginx a pipe to watch, setting up a >> handler for that pipe, calling an async api that uses threads, then >> the from the callback writing a byte to the pipe. Now when the async >> code finishes we're back on the nginx event loop in the pipe's >> handler. >> > > Extra OS threads add their own complexity and overhead (killing C10K, > for example), which I think we should avoid wherever we can (well, > disk I/O cannot be nonblocking and we should only use thread pools for > that). > > Well, just my 2 cents. > > Regards, > -agentzh > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel From nmav at redhat.com Fri Jun 19 13:49:48 2015 From: nmav at redhat.com (Nikos Mavrogiannopoulos) Date: Fri, 19 Jun 2015 15:49:48 +0200 Subject: patch to allow loading PKCS #11 URLs Message-ID: <1434721788.3290.23.camel@redhat.com> Hello, The attached patch allows loading PKCS #11 URLs in the ssl_certificate_key. That is, one only needs to specify: ssl_certificate_key "pkcs11:model=SoftHSM%20v2serial=f0490bea35;pin -value=1234" to access a key in a HSM. That's the only step required. That extends the previous approach which is generic, but tedious, and requires modifying openssl config files shared with other apps. See [0] for comparison. This works with the latest engine_pkcs11, and p11-kit (which takes care of module registration). Note that PKCS #11 URLs, described in RFC7512, are becoming the way to specify keys stored in PKCS #11 modules. engine_pkcs11 supports them already, as well as gnutls natively. See also fedora's stance on them [1]. regards, Nikos [0]. http://mailman.nginx.org/pipermail/nginx-devel/2014-October/006151.html [1]. https://fedoraproject.org/wiki/Packaging:SSLCertificateHandling -------------- next part -------------- A non-text attachment was scrubbed... Name: nginx-pkcs11.patch Type: text/x-patch Size: 2174 bytes Desc: not available URL: From mdounin at mdounin.ru Fri Jun 19 14:07:07 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 19 Jun 2015 17:07:07 +0300 Subject: patch to allow loading PKCS #11 URLs In-Reply-To: <1434721788.3290.23.camel@redhat.com> References: <1434721788.3290.23.camel@redhat.com> Message-ID: <20150619140707.GY26357@mdounin.ru> Hello! On Fri, Jun 19, 2015 at 03:49:48PM +0200, Nikos Mavrogiannopoulos wrote: > > Hello, > The attached patch allows loading PKCS #11 URLs in the > ssl_certificate_key. > > That is, one only needs to specify: > ssl_certificate_key "pkcs11:model=SoftHSM%20v2serial=f0490bea35;pin > -value=1234" > > to access a key in a HSM. That's the only step required. > That extends the previous approach which is generic, but tedious, and > requires modifying openssl config files shared with other apps. > See [0] for comparison. Have you tried ssl_certificate_key "engine:pkcs11:model=SoftHSM%20v2serial=f0490bea35;pin-value=1234"; instead? I don't see how it's different from the code you propose. -- Maxim Dounin http://nginx.org/ From nmav at redhat.com Fri Jun 19 14:39:48 2015 From: nmav at redhat.com (Nikos Mavrogiannopoulos) Date: Fri, 19 Jun 2015 16:39:48 +0200 Subject: patch to allow loading PKCS #11 URLs In-Reply-To: <20150619140707.GY26357@mdounin.ru> References: <1434721788.3290.23.camel@redhat.com> <20150619140707.GY26357@mdounin.ru> Message-ID: <1434724788.3290.28.camel@redhat.com> On Fri, 2015-06-19 at 17:07 +0300, Maxim Dounin wrote: > > Have you tried > ssl_certificate_key > "engine:pkcs11:model=SoftHSM%20v2serial=f0490bea35;pin-value=1234"; > instead? > I don't see how it's different from the code you propose. Hi, Yes, I've tried it. It would be specified as: "engine:pkcs11:pkcs11:model=SoftHSM%20v2serial=f0490bea35;pin -value=1234"; But doesn't work, because it doesn't initialize the pkcs11 engine. Furthermore, the "engine:pkcs11:pkcs11:" approach defeats the purpose of PKCS #11 URLs which is to use the same string to identify the same keys on all applications. regards, Nikos From mdounin at mdounin.ru Fri Jun 19 18:39:47 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 19 Jun 2015 18:39:47 +0000 Subject: [nginx] Stream: avoid SSL_CTX_set_tmp_rsa_callback() call with L... Message-ID: details: http://hg.nginx.org/nginx/rev/4b703a5a4631 branches: changeset: 6199:4b703a5a4631 user: Piotr Sikora date: Thu Jun 18 03:36:41 2015 -0700 description: Stream: avoid SSL_CTX_set_tmp_rsa_callback() call with LibreSSL. Signed-off-by: Piotr Sikora diffstat: src/stream/ngx_stream_ssl_module.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diffs (13 lines): diff --git a/src/stream/ngx_stream_ssl_module.c b/src/stream/ngx_stream_ssl_module.c --- a/src/stream/ngx_stream_ssl_module.c +++ b/src/stream/ngx_stream_ssl_module.c @@ -276,7 +276,9 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); } +#ifndef LIBRESSL_VERSION_NUMBER SSL_CTX_set_tmp_rsa_callback(conf->ssl.ctx, ngx_ssl_rsa512_key_callback); +#endif if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) { return NGX_CONF_ERROR; From mdounin at mdounin.ru Fri Jun 19 18:40:17 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 19 Jun 2015 21:40:17 +0300 Subject: [PATCH] SSL: avoid SSL_CTX_set_tmp_rsa_callback() call with LibreSSL In-Reply-To: References: Message-ID: <20150619184017.GD26357@mdounin.ru> Hello! On Thu, Jun 18, 2015 at 03:39:31AM -0700, Piotr Sikora wrote: > # HG changeset patch > # User Piotr Sikora > # Date 1434623801 25200 > # Thu Jun 18 03:36:41 2015 -0700 > # Node ID e0d2520ed65517b581f2565160a89ba93f4f3630 > # Parent c3ec43580a48114dfd28186f43e773fcfe211337 > SSL: avoid SSL_CTX_set_tmp_rsa_callback() call with LibreSSL. > > Signed-off-by: Piotr Sikora > > diff -r c3ec43580a48 -r e0d2520ed655 src/stream/ngx_stream_ssl_module.c > --- a/src/stream/ngx_stream_ssl_module.c Wed Jun 17 17:57:34 2015 +0300 > +++ b/src/stream/ngx_stream_ssl_module.c Thu Jun 18 03:36:41 2015 -0700 > @@ -276,7 +276,9 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf > SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); > } > > +#ifndef LIBRESSL_VERSION_NUMBER > SSL_CTX_set_tmp_rsa_callback(conf->ssl.ctx, ngx_ssl_rsa512_key_callback); > +#endif > > if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) { > return NGX_CONF_ERROR; Committed with a minor change to commit log, thanks! -- Maxim Dounin http://nginx.org/ From andrew.holway at otternetworks.de Sun Jun 21 12:13:16 2015 From: andrew.holway at otternetworks.de (Andrew Holway) Date: Sun, 21 Jun 2015 14:13:16 +0200 Subject: unsubscribe Message-ID: On Fri, Jun 19, 2015 at 8:40 PM, Maxim Dounin wrote: > Hello! > > On Thu, Jun 18, 2015 at 03:39:31AM -0700, Piotr Sikora wrote: > > > # HG changeset patch > > # User Piotr Sikora > > # Date 1434623801 25200 > > # Thu Jun 18 03:36:41 2015 -0700 > > # Node ID e0d2520ed65517b581f2565160a89ba93f4f3630 > > # Parent c3ec43580a48114dfd28186f43e773fcfe211337 > > SSL: avoid SSL_CTX_set_tmp_rsa_callback() call with LibreSSL. > > > > Signed-off-by: Piotr Sikora > > > > diff -r c3ec43580a48 -r e0d2520ed655 src/stream/ngx_stream_ssl_module.c > > --- a/src/stream/ngx_stream_ssl_module.c Wed Jun 17 17:57:34 2015 > +0300 > > +++ b/src/stream/ngx_stream_ssl_module.c Thu Jun 18 03:36:41 2015 > -0700 > > @@ -276,7 +276,9 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf > > SSL_CTX_set_options(conf->ssl.ctx, > SSL_OP_CIPHER_SERVER_PREFERENCE); > > } > > > > +#ifndef LIBRESSL_VERSION_NUMBER > > SSL_CTX_set_tmp_rsa_callback(conf->ssl.ctx, > ngx_ssl_rsa512_key_callback); > > +#endif > > > > if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) { > > return NGX_CONF_ERROR; > > Committed with a minor change to commit log, thanks! > > -- > Maxim Dounin > http://nginx.org/ > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -- Otter Networks UG http://otternetworks.de fon: +49 30 54 88 5197 Gotenstra?e 17 10829 Berlin -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Sun Jun 21 13:25:31 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sun, 21 Jun 2015 16:25:31 +0300 Subject: [PATCH] SSL: mark connections as non-reusable before SSL handshake In-Reply-To: References: Message-ID: <20150621132531.GG26357@mdounin.ru> Hello! On Thu, Jun 18, 2015 at 03:39:27AM -0700, Piotr Sikora wrote: > # HG changeset patch > # User Piotr Sikora > # Date 1434623800 25200 > # Thu Jun 18 03:36:40 2015 -0700 > # Node ID cda1075a9536257e510b452df084e4cc396ab25d > # Parent c3ec43580a48114dfd28186f43e773fcfe211337 > SSL: mark connections as non-reusable before SSL handshake. > > Previously, connections were marked as non-reusable after SSL handshake > returned NGX_AGAIN. This meant that SSL callbacks that were using nginx > connections could drain the connection on which SSL handshake was being > performed on. > > Signed-off-by: Piotr Sikora > > diff -r c3ec43580a48 -r cda1075a9536 src/http/ngx_http_request.c > --- a/src/http/ngx_http_request.c Wed Jun 17 17:57:34 2015 +0300 > +++ b/src/http/ngx_http_request.c Thu Jun 18 03:36:40 2015 -0700 > @@ -715,6 +715,8 @@ ngx_http_ssl_handshake(ngx_event_t *rev) > return; > } > > + ngx_reusable_connection(c, 0); > + > rc = ngx_ssl_handshake(c); > > if (rc == NGX_AGAIN) { > @@ -723,8 +725,6 @@ ngx_http_ssl_handshake(ngx_event_t *rev) > ngx_add_timer(rev, c->listening->post_accept_timeout); > } > > - ngx_reusable_connection(c, 0); > - > c->ssl->handler = ngx_http_ssl_handshake_handler; > return; > } As far as I understand, this change isn't useable with an unmodified nginx (and introduces some minor pessimization in an unlikely case when first ngx_ssl_handshake() will not return NGX_AGAIN). -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Mon Jun 22 01:11:32 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 22 Jun 2015 04:11:32 +0300 Subject: patch to allow loading PKCS #11 URLs In-Reply-To: <1434724788.3290.28.camel@redhat.com> References: <1434721788.3290.23.camel@redhat.com> <20150619140707.GY26357@mdounin.ru> <1434724788.3290.28.camel@redhat.com> Message-ID: <20150622011131.GH26357@mdounin.ru> Hello! On Fri, Jun 19, 2015 at 04:39:48PM +0200, Nikos Mavrogiannopoulos wrote: > On Fri, 2015-06-19 at 17:07 +0300, Maxim Dounin wrote: > > > > Have you tried > > ssl_certificate_key > > "engine:pkcs11:model=SoftHSM%20v2serial=f0490bea35;pin-value=1234"; > > instead? > > I don't see how it's different from the code you propose. > > Hi, > Yes, I've tried it. It would be specified as: > "engine:pkcs11:pkcs11:model=SoftHSM%20v2serial=f0490bea35;pin > -value=1234"; > > But doesn't work, because it doesn't initialize the pkcs11 engine. Shouldn't initialization of an engine be added to "engine:..." handling then? (Just a side note: your patch has ENGINE_init() but no ENGINE_finish(). It looks like a leak.) > Furthermore, the "engine:pkcs11:pkcs11:" approach defeats the purpose > of PKCS #11 URLs which is to use the same string to identify the same > keys on all applications. The goal of the "engine:..." syntax is to allow nginx to load keys from arbitrary engines. With this approach you can use PKCS #11 URLs as identifiers for engines which support them - though you have to write a prefix "engine::" to instruct nginx to load a key from a named engine rather than a file. So I don't think that the current approach "defeats the purpose" somehow - it's just a bit more chatty than it can be assuming nginx knows for sure that the only engine useable for PKCS #11 URLs is pkcs11. -- Maxim Dounin http://nginx.org/ From kaustubh.deo at gmail.com Mon Jun 22 06:17:54 2015 From: kaustubh.deo at gmail.com (Kaustubh Deorukhkar) Date: Mon, 22 Jun 2015 11:47:54 +0530 Subject: Breaking content generation phase into multiple phases or adding custom events in content phase Message-ID: Thanks Yichun and Jeff for your inputs and sorry for late ack. I had a brief look at ngx_drizzle, I see that it needs the library to expose underlying fd, which is not possible in our case, but looks an interesting solution. The other cosocket API mechanism seem to be using unix domain socket as per the docs, so this would be similar to using pipe/socket to handle async apis where the callback could trigger event on the pipe/socket. Please correct me if am missing something? (never worked on lua :) ) Use case is very similar to image optimization case in pagespeed. I am guessing cosocket approach can also fit here? @Jeff regarding using pipes to trigger event, does it create one pipe per request or just one pipe where say module can - trigger the async API, - queue the nginx_request and proceed with other requests, (not sure this is possible with nginx?, as i think nginx handler cannot return something like NGX_AGAIN to resume handler where it called async api) - when there is event on pipe, nginx pipe_event_handler can figure out which request's data is ready and respond Easiest approach I can think of is to use domain socket in upstream form, but wanted to avoid as it it would mean additional socket descriptor per request. If you can help understand at design level w.r.t nginx, will be faster to adapt :) Thanks again!! -------------- next part -------------- An HTML attachment was scrubbed... URL: From nmav at redhat.com Mon Jun 22 09:06:02 2015 From: nmav at redhat.com (Nikos Mavrogiannopoulos) Date: Mon, 22 Jun 2015 11:06:02 +0200 Subject: patch to allow loading PKCS #11 URLs In-Reply-To: <20150622011131.GH26357@mdounin.ru> References: <1434721788.3290.23.camel@redhat.com> <20150619140707.GY26357@mdounin.ru> <1434724788.3290.28.camel@redhat.com> <20150622011131.GH26357@mdounin.ru> Message-ID: <1434963962.3453.19.camel@redhat.com> On Mon, 2015-06-22 at 04:11 +0300, Maxim Dounin wrote: > > > Hi, > > Yes, I've tried it. It would be specified as: > > "engine:pkcs11:pkcs11:model=SoftHSM%20v2serial=f0490bea35;pin > > -value=1234"; > > > > But doesn't work, because it doesn't initialize the pkcs11 engine. > Shouldn't initialization of an engine be added to "engine:..." > handling then? Hi, I am not sure how the original engine approach was intended to work. My understanding from the mail I quoted was that it required the engine to be enabled via the openssl.cnf file. That's why I didn't touch that part. I could update that part as well if you think it would be a nice addition. > (Just a side note: your patch has ENGINE_init() but no > ENGINE_finish(). It looks like a leak.) I'm not very familiar with the nginx code base and that could be indeed an issue. Where would that finish be called? The engine initialization for pkcs11 should stay up for the lifetime of all connections. > > Furthermore, the "engine:pkcs11:pkcs11:" approach defeats the > > purpose > > of PKCS #11 URLs which is to use the same string to identify the > > same > > keys on all applications. > The goal of the "engine:..." syntax is to allow nginx to load keys > from arbitrary engines. With this approach you can use PKCS #11 > URLs as identifiers for engines which support them - though you > have to write a prefix "engine::" to instruct nginx to load > a key from a named engine rather than a file. So I don't think > that the current approach "defeats the purpose" somehow - it's > just a bit more chatty than it can be assuming nginx knows for > sure that the only engine useable for PKCS #11 URLs is pkcs11. Note that supporting the "pkcs11:" urls directly, has the advantage that it doesn't make nginx dependent on any engine to support PKCS #11. The current support relies on engine_pkcs11, which is a 3rd party module (not in openssl distribution). It should be future-proof to have a way to load PKCS #11 modules which is independent of the backend used by nginx. So you could change the internal backend (for example to use libp11 directly), without requiring all nginx users to change their configuration files and remove the "engine:pkcs11:" part from their keys. It would of course be good to keep the engine support there for the users that may need other modules than pkcs11, but for HSMs, all crypto card providers do ship a PKCS #11 module. So I would expect that the need for PKCS #11 support would overshadow the need for any other engine supported by openssl. regards, Nikos From serg.brester at sebres.de Mon Jun 22 09:33:45 2015 From: serg.brester at sebres.de (Sergey Brester) Date: Mon, 22 Jun 2015 11:33:45 +0200 Subject: Fix windows issue with multiple workers In-Reply-To: <20150618195512.GW26357@mdounin.ru> References: <64cd3e82b8271b1240c588dc6fece3bb@sebres.de> <20150617022733.GG26357@mdounin.ru> <20150617122941.GJ26357@mdounin.ru> <20150617145240.GN26357@mdounin.ru> <4312e66540f56c374ecca7634480ddc4@sebres.de> <20150618195512.GW26357@mdounin.ru> Message-ID: <680084dda6088a45ed7c0fb369dcf8d0@sebres.de> Hi, enclosed you will find an amend fix as replacement to "_sb-win-multi-worker-add-3.patch" (just forgotten to save after renaming NGX_SINGLE_WORKER <-> NGX_CONF_UNSET_PTR, before it was commited). 18.06.2015 21:55, Maxim Dounin: > As I already tried to explain, the approach with inherited sockets > is basically identical to what nginx does on UNIX with fork(). > There are no reasons to keep things different if you can do it > similarly on both platforms. But it's not even roughly similar, see "win32/ngx_process.c" + "win32/ngx_process_cycle.c" in comparission to unix... This is already at all a biggish difference to unix. > The goal is to minimize code bloat, not maximize it. Let me think a bit, how I can make it a little smaller, or unite some code-pieces with unix. Regards, sebres. -------------- next part -------------- A non-text attachment was scrubbed... Name: _sb-win-multi-worker-add-3b.patch Type: text/x-diff Size: 9120 bytes Desc: not available URL: From piotr at cloudflare.com Mon Jun 22 21:33:31 2015 From: piotr at cloudflare.com (Piotr Sikora) Date: Mon, 22 Jun 2015 14:33:31 -0700 Subject: [PATCH] SSL: mark connections as non-reusable before SSL handshake In-Reply-To: <20150621132531.GG26357@mdounin.ru> References: <20150621132531.GG26357@mdounin.ru> Message-ID: Hey Maxim, > As far as I understand, this change isn't useable with an > unmodified nginx It is, since nginx modules are free to install those SSL callbacks (for example: ngx_lua's ssl_certificate_by_lua). > (and introduces some minor pessimization in an > unlikely case when first ngx_ssl_handshake() will not return > NGX_AGAIN). Since SSL/TLS handshake requires at least 1 RTT (even in case of session resumption), the only case in which ngx_ssl_handshake() wouldn't return NGX_AGAIN is when the handshake failed based on ClientHello (no shared ciphers, inappropriate fallback, etc.), in which case the connection will be closed and ngx_reusable_connection(c, 0) will be called from ngx_close_connection() anyway. Calling ngx_reusable_connection(c, 0) twice is basically a no-op, so I don't really consider this a pessimization. Best regards, Piotr Sikora From jefftk at google.com Tue Jun 23 09:56:09 2015 From: jefftk at google.com (Jeff Kaufman) Date: Tue, 23 Jun 2015 05:56:09 -0400 Subject: Breaking content generation phase into multiple phases or adding custom events in content phase In-Reply-To: References: Message-ID: On Mon, Jun 22, 2015 at 2:17 AM, Kaustubh Deorukhkar wrote: > @Jeff regarding using pipes to trigger event, does it create one pipe per > request or just one pipe. ngx_pagespeed originally used a pipe per request, which was simpler, but then switched to one pipe for everything for efficiency. Here's the commit where we switched between them, which should be good for understanding how the two work: https://github.com/pagespeed/ngx_pagespeed/pull/876/files From arut at nginx.com Tue Jun 23 17:19:40 2015 From: arut at nginx.com (Roman Arutyunyan) Date: Tue, 23 Jun 2015 17:19:40 +0000 Subject: [nginx] Stream: common handler for upstream and downstream. Message-ID: details: http://hg.nginx.org/nginx/rev/abee77018d3a branches: changeset: 6200:abee77018d3a user: Roman Arutyunyan date: Tue Jun 23 20:17:47 2015 +0300 description: Stream: common handler for upstream and downstream. diffstat: src/stream/ngx_stream_proxy_module.c | 49 +++++++++++++++-------------------- 1 files changed, 21 insertions(+), 28 deletions(-) diffs (80 lines): diff -r 4b703a5a4631 -r abee77018d3a src/stream/ngx_stream_proxy_module.c --- a/src/stream/ngx_stream_proxy_module.c Thu Jun 18 03:36:41 2015 -0700 +++ b/src/stream/ngx_stream_proxy_module.c Tue Jun 23 20:17:47 2015 +0300 @@ -52,6 +52,8 @@ static void ngx_stream_proxy_connect(ngx static void ngx_stream_proxy_init_upstream(ngx_stream_session_t *s); static void ngx_stream_proxy_upstream_handler(ngx_event_t *ev); static void ngx_stream_proxy_downstream_handler(ngx_event_t *ev); +static void ngx_stream_proxy_process_connection(ngx_event_t *ev, + ngx_uint_t from_upstream); static void ngx_stream_proxy_connect_handler(ngx_event_t *ev); static ngx_int_t ngx_stream_proxy_test_connect(ngx_connection_t *c); static ngx_int_t ngx_stream_proxy_process(ngx_stream_session_t *s, @@ -815,12 +817,27 @@ done: static void ngx_stream_proxy_downstream_handler(ngx_event_t *ev) { + ngx_stream_proxy_process_connection(ev, ev->write); +} + + +static void +ngx_stream_proxy_upstream_handler(ngx_event_t *ev) +{ + ngx_stream_proxy_process_connection(ev, !ev->write); +} + + +static void +ngx_stream_proxy_process_connection(ngx_event_t *ev, ngx_uint_t from_upstream) +{ ngx_connection_t *c; ngx_stream_session_t *s; ngx_stream_upstream_t *u; c = ev->data; s = c->data; + u = s->upstream; if (ev->timedout) { ngx_connection_error(c, NGX_ETIMEDOUT, "connection timed out"); @@ -828,35 +845,11 @@ ngx_stream_proxy_downstream_handler(ngx_ return; } - u = s->upstream; + if (from_upstream && u->upstream_buf.start == NULL) { + return; + } - if (!ev->write) { - ngx_stream_proxy_process(s, 0, 0); - - } else if (u->upstream_buf.start) { - ngx_stream_proxy_process(s, 1, 1); - } -} - - -static void -ngx_stream_proxy_upstream_handler(ngx_event_t *ev) -{ - ngx_connection_t *c; - ngx_stream_session_t *s; - ngx_stream_upstream_t *u; - - c = ev->data; - s = c->data; - - u = s->upstream; - - if (ev->write) { - ngx_stream_proxy_process(s, 0, 1); - - } else if (u->upstream_buf.start) { - ngx_stream_proxy_process(s, 1, 0); - } + ngx_stream_proxy_process(s, from_upstream, ev->write); } From arut at nginx.com Tue Jun 23 17:19:43 2015 From: arut at nginx.com (Roman Arutyunyan) Date: Tue, 23 Jun 2015 17:19:43 +0000 Subject: [nginx] Stream: upstream and downstream limit rates. Message-ID: details: http://hg.nginx.org/nginx/rev/24488e6db782 branches: changeset: 6201:24488e6db782 user: Roman Arutyunyan date: Tue Jun 23 20:17:48 2015 +0300 description: Stream: upstream and downstream limit rates. diffstat: src/stream/ngx_stream_proxy_module.c | 125 ++++++++++++++++++++++++++++++---- src/stream/ngx_stream_upstream.h | 1 + 2 files changed, 111 insertions(+), 15 deletions(-) diffs (257 lines): diff -r abee77018d3a -r 24488e6db782 src/stream/ngx_stream_proxy_module.c --- a/src/stream/ngx_stream_proxy_module.c Tue Jun 23 20:17:47 2015 +0300 +++ b/src/stream/ngx_stream_proxy_module.c Tue Jun 23 20:17:48 2015 +0300 @@ -18,7 +18,9 @@ typedef struct { ngx_msec_t timeout; ngx_msec_t next_upstream_timeout; size_t downstream_buf_size; + size_t downstream_limit_rate; size_t upstream_buf_size; + size_t upstream_limit_rate; ngx_uint_t next_upstream_tries; ngx_flag_t next_upstream; ngx_flag_t proxy_protocol; @@ -132,6 +134,13 @@ static ngx_command_t ngx_stream_proxy_c offsetof(ngx_stream_proxy_srv_conf_t, downstream_buf_size), NULL }, + { ngx_string("proxy_downstream_limit_rate"), + NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_STREAM_SRV_CONF_OFFSET, + offsetof(ngx_stream_proxy_srv_conf_t, downstream_limit_rate), + NULL }, + { ngx_string("proxy_upstream_buffer"), NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, ngx_conf_set_size_slot, @@ -139,6 +148,13 @@ static ngx_command_t ngx_stream_proxy_c offsetof(ngx_stream_proxy_srv_conf_t, upstream_buf_size), NULL }, + { ngx_string("proxy_upstream_limit_rate"), + NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_STREAM_SRV_CONF_OFFSET, + offsetof(ngx_stream_proxy_srv_conf_t, upstream_limit_rate), + NULL }, + { ngx_string("proxy_next_upstream"), NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG, ngx_conf_set_flag_slot, @@ -340,6 +356,7 @@ ngx_stream_proxy_handler(ngx_stream_sess } u->proxy_protocol = pscf->proxy_protocol; + u->start_sec = ngx_time(); p = ngx_pnalloc(c->pool, pscf->downstream_buf_size); if (p == NULL) { @@ -831,17 +848,56 @@ ngx_stream_proxy_upstream_handler(ngx_ev static void ngx_stream_proxy_process_connection(ngx_event_t *ev, ngx_uint_t from_upstream) { - ngx_connection_t *c; - ngx_stream_session_t *s; - ngx_stream_upstream_t *u; + ngx_connection_t *c, *pc; + ngx_stream_session_t *s; + ngx_stream_upstream_t *u; + ngx_stream_proxy_srv_conf_t *pscf; c = ev->data; s = c->data; u = s->upstream; if (ev->timedout) { - ngx_connection_error(c, NGX_ETIMEDOUT, "connection timed out"); - ngx_stream_proxy_finalize(s, NGX_DECLINED); + + if (ev->delayed) { + + ev->timedout = 0; + ev->delayed = 0; + + if (!ev->ready) { + if (ngx_handle_read_event(ev, 0) != NGX_OK) { + ngx_stream_proxy_finalize(s, NGX_ERROR); + return; + } + + if (u->upstream_buf.start) { + pc = u->peer.connection; + + if (!c->read->delayed && !pc->read->delayed) { + pscf = ngx_stream_get_module_srv_conf(s, + ngx_stream_proxy_module); + ngx_add_timer(c->write, pscf->timeout); + } + } + + return; + } + + } else { + ngx_connection_error(c, NGX_ETIMEDOUT, "connection timed out"); + ngx_stream_proxy_finalize(s, NGX_DECLINED); + return; + } + + } else if (ev->delayed) { + + ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0, + "stream connection delayed"); + + if (ngx_handle_read_event(ev, 0) != NGX_OK) { + ngx_stream_proxy_finalize(s, NGX_ERROR); + } + return; } @@ -930,10 +986,12 @@ static ngx_int_t ngx_stream_proxy_process(ngx_stream_session_t *s, ngx_uint_t from_upstream, ngx_uint_t do_write) { - size_t size; + off_t *received, limit; + size_t size, limit_rate; ssize_t n; ngx_buf_t *b; ngx_uint_t flags; + ngx_msec_t delay; ngx_connection_t *c, *pc, *src, *dst; ngx_log_handler_pt handler; ngx_stream_upstream_t *u; @@ -944,15 +1002,21 @@ ngx_stream_proxy_process(ngx_stream_sess c = s->connection; pc = u->upstream_buf.start ? u->peer.connection : NULL; + pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module); + if (from_upstream) { src = pc; dst = c; b = &u->upstream_buf; + limit_rate = pscf->upstream_limit_rate; + received = &u->received; } else { src = c; dst = pc; b = &u->downstream_buf; + limit_rate = pscf->downstream_limit_rate; + received = &s->received; } for ( ;; ) { @@ -983,7 +1047,23 @@ ngx_stream_proxy_process(ngx_stream_sess size = b->end - b->last; - if (size && src->read->ready) { + if (size && src->read->ready && !src->read->delayed) { + + if (limit_rate) { + limit = (off_t) limit_rate * (ngx_time() - u->start_sec + 1) + - *received; + + if (limit <= 0) { + src->read->delayed = 1; + delay = (ngx_msec_t) (- limit * 1000 / limit_rate + 1); + ngx_add_timer(src->read, delay); + break; + } + + if (size > (size_t) limit) { + size = limit; + } + } n = src->recv(src, b->last, size); @@ -992,15 +1072,19 @@ ngx_stream_proxy_process(ngx_stream_sess } if (n > 0) { - if (from_upstream) { - u->received += n; + if (limit_rate) { + delay = (ngx_msec_t) (n * 1000 / limit_rate); - } else { - s->received += n; + if (delay > 0) { + src->read->delayed = 1; + ngx_add_timer(src->read, delay); + } } + *received += n; + b->last += n; do_write = 1; - b->last += n; + continue; } @@ -1012,8 +1096,6 @@ ngx_stream_proxy_process(ngx_stream_sess break; } - pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module); - if (src->read->eof && (b->pos == b->last || (dst && dst->read->eof))) { handler = c->log->handler; c->log->handler = NULL; @@ -1044,7 +1126,12 @@ ngx_stream_proxy_process(ngx_stream_sess return NGX_ERROR; } - ngx_add_timer(c->read, pscf->timeout); + if (!c->read->delayed && !pc->read->delayed) { + ngx_add_timer(c->write, pscf->timeout); + + } else if (c->write->timer_set) { + ngx_del_timer(c->write); + } } return NGX_OK; @@ -1207,7 +1294,9 @@ ngx_stream_proxy_create_srv_conf(ngx_con conf->timeout = NGX_CONF_UNSET_MSEC; conf->next_upstream_timeout = NGX_CONF_UNSET_MSEC; conf->downstream_buf_size = NGX_CONF_UNSET_SIZE; + conf->downstream_limit_rate = NGX_CONF_UNSET_SIZE; conf->upstream_buf_size = NGX_CONF_UNSET_SIZE; + conf->upstream_limit_rate = NGX_CONF_UNSET_SIZE; conf->next_upstream_tries = NGX_CONF_UNSET_UINT; conf->next_upstream = NGX_CONF_UNSET; conf->proxy_protocol = NGX_CONF_UNSET; @@ -1244,9 +1333,15 @@ ngx_stream_proxy_merge_srv_conf(ngx_conf ngx_conf_merge_size_value(conf->downstream_buf_size, prev->downstream_buf_size, 16384); + ngx_conf_merge_size_value(conf->downstream_limit_rate, + prev->downstream_limit_rate, 0); + ngx_conf_merge_size_value(conf->upstream_buf_size, prev->upstream_buf_size, 16384); + ngx_conf_merge_size_value(conf->upstream_limit_rate, + prev->upstream_limit_rate, 0); + ngx_conf_merge_uint_value(conf->next_upstream_tries, prev->next_upstream_tries, 0); diff -r abee77018d3a -r 24488e6db782 src/stream/ngx_stream_upstream.h --- a/src/stream/ngx_stream_upstream.h Tue Jun 23 20:17:47 2015 +0300 +++ b/src/stream/ngx_stream_upstream.h Tue Jun 23 20:17:48 2015 +0300 @@ -83,6 +83,7 @@ typedef struct { ngx_buf_t downstream_buf; ngx_buf_t upstream_buf; off_t received; + time_t start_sec; #if (NGX_STREAM_SSL) ngx_str_t ssl_name; #endif From piotr at cloudflare.com Wed Jun 24 03:37:02 2015 From: piotr at cloudflare.com (Piotr Sikora) Date: Tue, 23 Jun 2015 20:37:02 -0700 Subject: [PATCH] Core: add $nginx_build variable Message-ID: <3bbe405ecafcec573957.1435117022@Piotrs-MacBook-Pro.local> # HG changeset patch # User Piotr Sikora # Date 1435116970 25200 # Tue Jun 23 20:36:10 2015 -0700 # Node ID 3bbe405ecafcec573957a5afd9f2a75be19d52f0 # Parent 24488e6db782e24b9a30ba31f0b719204e582918 Core: add $nginx_build variable. Signed-off-by: Piotr Sikora diff -r 24488e6db782 -r 3bbe405ecafc src/http/ngx_http_variables.c --- a/src/http/ngx_http_variables.c Tue Jun 23 20:17:48 2015 +0300 +++ b/src/http/ngx_http_variables.c Tue Jun 23 20:36:10 2015 -0700 @@ -123,6 +123,8 @@ static ngx_int_t ngx_http_variable_conne static ngx_int_t ngx_http_variable_nginx_version(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_nginx_build(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_hostname(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_pid(ngx_http_request_t *r, @@ -316,6 +318,9 @@ static ngx_http_variable_t ngx_http_cor { ngx_string("nginx_version"), NULL, ngx_http_variable_nginx_version, 0, 0, 0 }, + { ngx_string("nginx_build"), NULL, ngx_http_variable_nginx_build, + 0, 0, 0 }, + { ngx_string("hostname"), NULL, ngx_http_variable_hostname, 0, 0, 0 }, @@ -2122,6 +2127,28 @@ ngx_http_variable_nginx_version(ngx_http static ngx_int_t +ngx_http_variable_nginx_build(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ +#ifdef NGX_BUILD + + v->len = sizeof(NGX_BUILD) - 1; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = (u_char *) NGX_BUILD; + +#else + + v->not_found = 1; + +#endif + + return NGX_OK; +} + + +static ngx_int_t ngx_http_variable_hostname(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { From kaustubh.deo at gmail.com Wed Jun 24 04:01:27 2015 From: kaustubh.deo at gmail.com (Kaustubh Deorukhkar) Date: Wed, 24 Jun 2015 09:31:27 +0530 Subject: Breaking content generation phase into multiple phases or adding custom events in content phase Message-ID: Thanks Jeff for the reference, will have a look! -------------- next part -------------- An HTML attachment was scrubbed... URL: From nmav at redhat.com Wed Jun 24 13:26:17 2015 From: nmav at redhat.com (Nikos Mavrogiannopoulos) Date: Wed, 24 Jun 2015 15:26:17 +0200 Subject: patch to allow loading PKCS #11 URLs In-Reply-To: <1434963962.3453.19.camel@redhat.com> References: <1434721788.3290.23.camel@redhat.com> <20150619140707.GY26357@mdounin.ru> <1434724788.3290.28.camel@redhat.com> <20150622011131.GH26357@mdounin.ru> <1434963962.3453.19.camel@redhat.com> Message-ID: <1435152377.14697.45.camel@redhat.com> On Mon, 2015-06-22 at 11:06 +0200, Nikos Mavrogiannopoulos wrote: > > The current support relies on engine_pkcs11, which is a 3rd party > module (not in openssl distribution). It should be future-proof to > have > a way to load PKCS #11 modules which is independent of the backend > used > by nginx. So you could change the internal backend (for example to > use > libp11 directly), without requiring all nginx users to change their > configuration files and remove the "engine:pkcs11:" part from their > keys. To add to this, it seems that the current PKCS #11 support in nginx is broken. It will only work with softhsm which is a simplistic soft module. Hardware HSMs, and more advanced soft HSMs like caml-crush require strict PKCS #11 adherence which neither engine_pkcs11 or nginx have. That is, they require the reinitialization of any open PKCS #11 modules and object handles after a fork. I think, the simplest way is to solve that within engine_pkcs11 with an atfork handler and reinitialization on re-use... but that would be quite messy. For more info see: https://bugzilla.redhat.com/show_bug.cgi?id=1235284 https://github.com/ANSSI-FR/caml-crush/issues/15 regards, Nikos From Ondrej.Novy at firma.seznam.cz Wed Jun 24 13:40:19 2015 From: Ondrej.Novy at firma.seznam.cz (Novy, Ondrej) Date: Wed, 24 Jun 2015 13:40:19 +0000 Subject: geoip_check_cache option Message-ID: Hi, I need to enable GEOIP_CHECK_CACHE in GeoIP lib, used in geoip nginx extension. I added option to do so. Patch attached. Thanks. Ond?ej Nov? vedouc? t?mu v?voje gsm: +420 777 963 207 Ondrej.Novy at firma.seznam.cz http://www.seznam.cz/ Seznam.cz, a.s., Business park - Lond?nsk? n?m. 856/2, 639 00 Brno -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: geoip_check_cache.patch Type: application/octet-stream Size: 3218 bytes Desc: geoip_check_cache.patch URL: From arut at nginx.com Thu Jun 25 09:40:13 2015 From: arut at nginx.com (Roman Arutyunyan) Date: Thu, 25 Jun 2015 09:40:13 +0000 Subject: [nginx] Stream: upstream "connected" flag. Message-ID: details: http://hg.nginx.org/nginx/rev/6345822f0abb branches: changeset: 6202:6345822f0abb user: Roman Arutyunyan date: Thu Jun 25 12:36:52 2015 +0300 description: Stream: upstream "connected" flag. Once upstream is connected, the upstream buffer is allocated. Previously, the proxy module used the buffer allocation status to check if upstream is connected. Now it's enough to check the flag. diffstat: src/stream/ngx_stream_proxy_module.c | 8 +++++--- src/stream/ngx_stream_upstream.h | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diffs (53 lines): diff -r 24488e6db782 -r 6345822f0abb src/stream/ngx_stream_proxy_module.c --- a/src/stream/ngx_stream_proxy_module.c Tue Jun 23 20:17:48 2015 +0300 +++ b/src/stream/ngx_stream_proxy_module.c Thu Jun 25 12:36:52 2015 +0300 @@ -524,6 +524,8 @@ ngx_stream_proxy_init_upstream(ngx_strea u->upstream_buf.pos = p; u->upstream_buf.last = p; + u->connected = 1; + pc->read->handler = ngx_stream_proxy_upstream_handler; pc->write->handler = ngx_stream_proxy_upstream_handler; @@ -870,7 +872,7 @@ ngx_stream_proxy_process_connection(ngx_ return; } - if (u->upstream_buf.start) { + if (u->connected) { pc = u->peer.connection; if (!c->read->delayed && !pc->read->delayed) { @@ -901,7 +903,7 @@ ngx_stream_proxy_process_connection(ngx_ return; } - if (from_upstream && u->upstream_buf.start == NULL) { + if (from_upstream && !u->connected) { return; } @@ -1000,7 +1002,7 @@ ngx_stream_proxy_process(ngx_stream_sess u = s->upstream; c = s->connection; - pc = u->upstream_buf.start ? u->peer.connection : NULL; + pc = u->connected ? u->peer.connection : NULL; pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module); diff -r 24488e6db782 -r 6345822f0abb src/stream/ngx_stream_upstream.h --- a/src/stream/ngx_stream_upstream.h Tue Jun 23 20:17:48 2015 +0300 +++ b/src/stream/ngx_stream_upstream.h Thu Jun 25 12:36:52 2015 +0300 @@ -87,8 +87,8 @@ typedef struct { #if (NGX_STREAM_SSL) ngx_str_t ssl_name; #endif - ngx_uint_t proxy_protocol; - /* unsigned proxy_protocol:1; */ + unsigned connected:1; + unsigned proxy_protocol:1; } ngx_stream_upstream_t; From code at bluebot.org Thu Jun 25 19:51:15 2015 From: code at bluebot.org (Jon Nalley) Date: Thu, 25 Jun 2015 14:51:15 -0500 Subject: [PATCH] Adds $orig_remote_addr in realip module Message-ID: <894a268769bf9b3c806a.1435261875@metis.bluebot> # HG changeset patch # User Jon Nalley # Date 1435261685 18000 # Thu Jun 25 14:48:05 2015 -0500 # Node ID 894a268769bf9b3c806a9506ea1e8daf2dac3841 # Parent 6345822f0abb70807f635989b6c2df7852a55bd9 Adds $orig_remote_addr in realip module When the realip module sets $remote_addr, the connecting IP is no longer available for logging etc. This change preserves the connecting IP as $orig_remote_addr. diff -r 6345822f0abb -r 894a268769bf src/core/ngx_connection.h --- a/src/core/ngx_connection.h Thu Jun 25 12:36:52 2015 +0300 +++ b/src/core/ngx_connection.h Thu Jun 25 14:48:05 2015 -0500 @@ -145,6 +145,10 @@ socklen_t socklen; ngx_str_t addr_text; +#if (NGX_HTTP_REALIP) + ngx_str_t orig_addr_text; +#endif + ngx_str_t proxy_protocol_addr; #if (NGX_SSL) diff -r 6345822f0abb -r 894a268769bf src/http/modules/ngx_http_realip_module.c --- a/src/http/modules/ngx_http_realip_module.c Thu Jun 25 12:36:52 2015 +0300 +++ b/src/http/modules/ngx_http_realip_module.c Thu Jun 25 14:48:05 2015 -0500 @@ -29,10 +29,13 @@ ngx_connection_t *connection; struct sockaddr *sockaddr; socklen_t socklen; - ngx_str_t addr_text; } ngx_http_realip_ctx_t; +static ngx_int_t + ngx_http_realip_orig_remote_addr_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_realip_add_variables(ngx_conf_t *cf); static ngx_int_t ngx_http_realip_handler(ngx_http_request_t *r); static ngx_int_t ngx_http_realip_set_addr(ngx_http_request_t *r, ngx_addr_t *addr); @@ -75,7 +78,7 @@ static ngx_http_module_t ngx_http_realip_module_ctx = { - NULL, /* preconfiguration */ + ngx_http_realip_add_variables, /* preconfiguration */ ngx_http_realip_init, /* postconfiguration */ NULL, /* create main configuration */ @@ -105,6 +108,15 @@ }; +static ngx_http_variable_t ngx_http_realip_vars[] = { + + { ngx_string("orig_remote_addr"), NULL, + ngx_http_realip_orig_remote_addr_variable, 0, NGX_HTTP_VAR_NOHASH, 0 }, + + { ngx_null_string, NULL, NULL, 0, 0, 0 } +}; + + static ngx_int_t ngx_http_realip_handler(ngx_http_request_t *r) { @@ -261,7 +273,7 @@ ctx->connection = c; ctx->sockaddr = c->sockaddr; ctx->socklen = c->socklen; - ctx->addr_text = c->addr_text; + c->orig_addr_text = c->addr_text; c->sockaddr = addr->sockaddr; c->socklen = addr->socklen; @@ -283,7 +295,7 @@ c->sockaddr = ctx->sockaddr; c->socklen = ctx->socklen; - c->addr_text = ctx->addr_text; + c->addr_text = c->orig_addr_text; } @@ -369,6 +381,43 @@ } +static ngx_int_t +ngx_http_realip_orig_remote_addr_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_connection_t *c; + + c = r->connection; + + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = c->orig_addr_text.data; + v->len = c->orig_addr_text.len; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_realip_add_variables(ngx_conf_t *cf) +{ + ngx_http_variable_t *var, *v; + + for (v = ngx_http_realip_vars; v->name.len; v++) { + var = ngx_http_add_variable(cf, &v->name, v->flags); + if (var == NULL) { + return NGX_ERROR; + } + + var->get_handler = v->get_handler; + var->data = v->data; + } + + return NGX_OK; +} + + static void * ngx_http_realip_create_loc_conf(ngx_conf_t *cf) { From vbart at nginx.com Fri Jun 26 13:23:30 2015 From: vbart at nginx.com (Valentin V. Bartenev) Date: Fri, 26 Jun 2015 16:23:30 +0300 Subject: [PATCH] Adds $orig_remote_addr in realip module In-Reply-To: <894a268769bf9b3c806a.1435261875@metis.bluebot> References: <894a268769bf9b3c806a.1435261875@metis.bluebot> Message-ID: <6298125.v2tLQqgB7i@vbart-workstation> On Thursday 25 June 2015 14:51:15 Jon Nalley wrote: > # HG changeset patch > # User Jon Nalley > # Date 1435261685 18000 > # Thu Jun 25 14:48:05 2015 -0500 > # Node ID 894a268769bf9b3c806a9506ea1e8daf2dac3841 > # Parent 6345822f0abb70807f635989b6c2df7852a55bd9 > Adds $orig_remote_addr in realip module > > When the realip module sets $remote_addr, the connecting IP is > no longer available for logging etc. This change preserves the > connecting IP as $orig_remote_addr. > > diff -r 6345822f0abb -r 894a268769bf src/core/ngx_connection.h > --- a/src/core/ngx_connection.h Thu Jun 25 12:36:52 2015 +0300 > +++ b/src/core/ngx_connection.h Thu Jun 25 14:48:05 2015 -0500 > @@ -145,6 +145,10 @@ > socklen_t socklen; > ngx_str_t addr_text; > > +#if (NGX_HTTP_REALIP) > + ngx_str_t orig_addr_text; > +#endif > + > ngx_str_t proxy_protocol_addr; > The realip module works on a per request basis, so storing this information inside the connection structure looks wrong to me. wbr, Valentin V. Bartenev From george at ucdn.com Fri Jun 26 14:47:02 2015 From: george at ucdn.com (George .) Date: Fri, 26 Jun 2015 17:47:02 +0300 Subject: wrong $bytes_sent on nginx-1.8.0 if aio threads is enabled In-Reply-To: <5552150.qNeIUJE5qs@vbart-workstation> References: <5552150.qNeIUJE5qs@vbart-workstation> Message-ID: Hi all, I'd like to ask if there are plans somebody to fix the issue with wrong $bytes_sent in aio threads mode. If no, is there a chance to get some hit or direction, so I can try fix it myself and contribute to better and bug free nginx? Thanks in advance, George On Fri, May 15, 2015 at 11:37 PM, Valentin V. Bartenev wrote: > On Friday 15 May 2015 17:45:44 George . wrote: > > Hi, > > > > I found following bug in nginx-1.8.0: > > > > if aio is configured with threads support - sometime (one in thousands > > requests) $bytes_sent contains only length of the header. I'm attaching > my > > nginx.conf, build params and simple python script I'm using the reproduce > > this issue. > > > > Here is the output of test script when the problem appears: > > . > > . > > . > > received: 101700000 from access_log : 101700000 on 26 iteration > > 127.0.0.1 - - [15/May/2015 17:27:45] "GET /test HTTP/1.0" 200 - > > 127.0.0.1 - - [15/May/2015 17:27:47] "GET /test HTTP/1.0" 200 - > > received: 101700000 from access_log : 101700000 on 27 iteration > > 127.0.0.1 - - [15/May/2015 17:27:58] "GET /test HTTP/1.0" 200 - > > 127.0.0.1 - - [15/May/2015 17:28:00] "GET /test HTTP/1.0" 200 - > > received: 101700000 from access_log : 101690000 on 28 iteration > > test failed!! > > > > also in access_log file" > > > > . > > . > > . > > 10170 GET /test HTTP/1.1 > > 10170 GET /test HTTP/1.1 > > 10170 GET /test HTTP/1.1 > > 170 GET /test HTTP/1.1 > > 10170 GET /test HTTP/1.1 > > 10170 GET /test HTTP/1.1 > > . > > . > > > > Thank you for the report. > > It caused by a race condition between sendfile() task completion > and connection close notifications. If the latter comes first, > nginx logs that client prematurely closed connection. > > Unfortunately, it's not easy to fix. I'll look at it later. > > wbr, Valentin V. Bartenev > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -------------- next part -------------- An HTML attachment was scrubbed... URL: From adi at hexapodia.org Mon Jun 29 22:55:25 2015 From: adi at hexapodia.org (Andy Isaacson) Date: Mon, 29 Jun 2015 15:55:25 -0700 Subject: [PATCH] Add support for tcp_user_timeout in http listen directive Message-ID: <20150629225525.GG12581@hexapodia.org> # HG changeset patch # User Andy Isaacson # Date 1435618451 25200 # Mon Jun 29 15:54:11 2015 -0700 # Node ID c11304760218324ea55de7250a613af8f13e431b # Parent b95e70ae6bcdbae99a967df01e1011839f19ee0e Add support for tcp_user_timeout in http listen directive This commit adds support for a new tcp_user_timeout= parameter to the listen directive. When enabled and set to a value greater than zero, the TCP_USER_TIMEOUT sockopt is set. From tcp(7): This specifies the maximum amount of time in milliseconds that transmitted data may remain unacknowledged before TCP will forcibly close the corresponding connection and return ETIMEDOUT to the application. Without this capability, a HTTP longpoll connection can remain active for up to 950 seconds after the last ACK from the client. Note that the tcp_user_timeout value is specified in (integer) seconds, but the setsockopt API is specified in milliseconds. This capability is similar to the systemwide configuration net.ipv4.tcp_retries2 on Linux, but more flexible and per-socket. diff -r b95e70ae6bcd -r c11304760218 auto/unix --- a/auto/unix Thu Sep 05 16:53:02 2013 +0400 +++ b/auto/unix Mon Jun 29 15:54:11 2015 -0700 @@ -330,6 +330,18 @@ . auto/feature +ngx_feature="TCP_USER_TIMEOUT" +ngx_feature_name="NGX_HAVE_TCP_USER_TIMEOUT" +ngx_feature_run=no +ngx_feature_incs="#include + #include + #include " +ngx_feature_path= +ngx_feature_libs= +ngx_feature_test="setsockopt(0, IPPROTO_TCP, TCP_USER_TIMEOUT, NULL, 0)" +. auto/feature + + ngx_feature="TCP_KEEPIDLE" ngx_feature_name="NGX_HAVE_KEEPALIVE_TUNABLE" ngx_feature_run=no diff -r b95e70ae6bcd -r c11304760218 src/core/ngx_connection.h --- a/src/core/ngx_connection.h Thu Sep 05 16:53:02 2013 +0400 +++ b/src/core/ngx_connection.h Mon Jun 29 15:54:11 2015 -0700 @@ -80,6 +80,10 @@ int setfib; #endif +#if (NGX_HAVE_TCP_USER_TIMEOUT) + int tcp_user_timeout; +#endif + }; diff -r b95e70ae6bcd -r c11304760218 src/event/ngx_event_accept.c --- a/src/event/ngx_event_accept.c Thu Sep 05 16:53:02 2013 +0400 +++ b/src/event/ngx_event_accept.c Mon Jun 29 15:54:11 2015 -0700 @@ -284,6 +284,23 @@ } } +#if (NGX_HAVE_TCP_USER_TIMEOUT) +#ifdef TCP_USER_TIMEOUT + if (ls->tcp_user_timeout) { + int value = ls->tcp_user_timeout; + + if (setsockopt(s, IPPROTO_TCP, TCP_USER_TIMEOUT, &value, + sizeof(int)) + == -1) + { + ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno, + "setsockopt(TCP_USER_TIMEOUT, %d) for %V failed", + value, c->addr_text); + } + } +#endif +#endif + #if (NGX_DEBUG) { diff -r b95e70ae6bcd -r c11304760218 src/http/ngx_http.c --- a/src/http/ngx_http.c Thu Sep 05 16:53:02 2013 +0400 +++ b/src/http/ngx_http.c Mon Jun 29 15:54:11 2015 -0700 @@ -1800,6 +1800,10 @@ ls->deferred_accept = addr->opt.deferred_accept; #endif +#if (NGX_HAVE_TCP_USER_TIMEOUT && defined TCP_USER_TIMEOUT) + ls->tcp_user_timeout = addr->opt.tcp_user_timeout; +#endif + #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) ls->ipv6only = addr->opt.ipv6only; #endif diff -r b95e70ae6bcd -r c11304760218 src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c Thu Sep 05 16:53:02 2013 +0400 +++ b/src/http/ngx_http_core_module.c Mon Jun 29 15:54:11 2015 -0700 @@ -4085,6 +4085,31 @@ continue; } + if (ngx_strncmp(value[n].data, "tcp_user_timeout=", 17) == 0) { +#if (NGX_HAVE_TCP_USER_TIMEOUT && defined TCP_USER_TIMEOUT) + int timeout_sec = ngx_atoi(value[n].data + 17, value[n].len - 17); + + /* + * convert from seconds (in config file) to milliseconds (for + * setsockopt) + */ + lsopt.tcp_user_timeout = timeout_sec * 1000; + + if (lsopt.tcp_user_timeout < 0) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "Invalid tcp_user_timeout \"%V\"", + &value[n]); + return NGX_CONF_ERROR; + } +#else + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "tcp_user_timeout \"%V\" is not supported on " + "this platform, ignored", + &value[n]); +#endif + continue; + } + if (ngx_strcmp(value[n].data, "deferred") == 0) { #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) lsopt.deferred_accept = 1; diff -r b95e70ae6bcd -r c11304760218 src/http/ngx_http_core_module.h --- a/src/http/ngx_http_core_module.h Thu Sep 05 16:53:02 2013 +0400 +++ b/src/http/ngx_http_core_module.h Mon Jun 29 15:54:11 2015 -0700 @@ -102,6 +102,10 @@ ngx_uint_t deferred_accept; #endif +#if (NGX_HAVE_TCP_USER_TIMEOUT && defined TCP_USER_TIMEOUT) + int tcp_user_timeout; +#endif + u_char addr[NGX_SOCKADDR_STRLEN + 1]; } ngx_http_listen_opt_t;