Compare commits

...

164 Commits

Author SHA1 Message Date
Maxim Dounin c48f20f8e1 release-1.2.9 tag 2013-05-13 14:43:06 +04:00
Maxim Dounin fd23ea994f nginx-1.2.9-RELEASE 2013-05-13 14:41:51 +04:00
Maxim Dounin f0a27ab36b Fixed chunk size parsing. 2013-05-13 13:19:28 +04:00
Maxim Dounin a1c31e0478 Version bump. 2013-05-13 13:18:31 +04:00
Maxim Dounin 59cd30a63c release-1.2.8 tag 2013-04-02 12:34:39 +00:00
Maxim Dounin b2c279cbd3 nginx-1.2.8-RELEASE 2013-04-02 12:34:21 +00:00
Maxim Dounin 8a93bc9885 Merge of r5138: use of NGX_FILE_ERROR.
Use NGX_FILE_ERROR for handling file operations errors.

On Win32 platforms 0 is used to indicate errors in file operations, so
comparing against either -1 or NGX_OK is not portable.

This was not much of an issue in patched code, since only ngx_fd_info() test
is actually reachable on Win32 and in worst case it might result in bogus
error log entry.

Patch by Piotr Sikora.
2013-03-29 18:18:42 +00:00
Maxim Dounin f413543bd7 Merge of r5133, r5134: peer.free() and peer.get() balance.
*) Upstream: only call peer.free() if peer.get() selected a peer.

*) Upstream: removed double-free workarounds in peer.free() methods.
2013-03-29 18:16:27 +00:00
Maxim Dounin d8df7da54f Merge of r5130, r5131, r5132: support for Mercurial repositories.
*) Misc: switch to single export operation in "zip" target.

   While exporting parts of the tree might be better in some cases, it
   is awfully slow overseas, and also requires unlocking ssh key multiple
   times.  Exporting the whole repo and removing directories not needed for
   zip is faster here.

   It is also a required step before we can switch to Mercurial.

*) Misc: removed unused "snapshot" target.

*) Misc: support for Mercurial repositories.
2013-03-29 18:09:06 +00:00
Maxim Dounin 2d197a9d39 Merge of r5129: split clients configuration parsing.
Split clients: check length when parsing configuration.
2013-03-29 17:59:41 +00:00
Maxim Dounin 76f856f25c Merge of r5127: language in a comment.
Fixed language in a comment preceding ngx_http_index_handler().
2013-03-29 17:53:47 +00:00
Maxim Dounin d67e76612e Merge of r5117, r5123: allocation errors handing during upgrade.
*) Core: guard against failed allocation during binary upgrade.
   Patch by Piotr Sikora.

*) Core: fixed resource leak if binary upgrade fails due to no memory.
   Found by Coverity (CID 992320).
2013-03-29 17:51:00 +00:00
Maxim Dounin 335b5f73e7 Merge of r5113, r5114: upstream: resolve errors handling.
Upstream: call ngx_http_run_posted_requests() on resolve errors.

If proxy_pass to a host with dynamic resolution was used to handle
a subrequest, and host resolution failed, the main request wasn't run
till something else happened on the connection.  E.g. request to "/zzz"
with the following configuration hanged:

    addition_types *;
    resolver 8.8.8.8;

    location /test {
        set $ihost xxx;
        proxy_pass http://$ihost;
    }

    location /zzz {
        add_after_body /test;
        return 200 "test";
    }

Report and original version of the patch by Lanshun Zhou,
http://mailman.nginx.org/pipermail/nginx-devel/2013-March/003476.html.
2013-03-29 17:34:45 +00:00
Maxim Dounin f7b63912de Merge of r5109, r5128: removed unused prototype and macro.
*) Removed unused prototype of ngx_http_find_server_conf().
   This function prototype and its implementation was added in r90,
   but the implementation was removed in r97.

*) Removed unused ngx_http_clear_variable() macro.
2013-03-29 17:23:36 +00:00
Maxim Dounin ec0e4cae5f Merge of r5098: mp4: fixed handling of too small mdat atoms.
Mp4: fixed handling of too small mdat atoms (ticket #266).

Patch by Gernot Vormayr (with minor changes).
2013-03-29 17:20:59 +00:00
Maxim Dounin 1a3988af90 Merge of r5083: fixed potential segfault in keepalive handler.
Fixed potential segfault in ngx_http_keepalive_handler().

In case of error in the read event handling we close a connection
by calling ngx_http_close_connection(), that also destroys connection
pool. Thereafter, an attempt to free a buffer (added in r4892) that
was allocated from the pool could cause SIGSEGV and is meaningless
as well (the buffer already freed with the pool).
2013-03-29 17:19:11 +00:00
Maxim Dounin b90ec1b1a2 Merge of r5082: SSL: retry "sess_id" and "id" allocations.
SSL: retry "sess_id" and "id" allocations.

In case of fully populated SSL session cache with no memory left for
new allocations, ngx_ssl_new_session() will try to expire the oldest
non-expired session and retry, but only in case when slab allocation
fails for "cached_sess", not when slab allocation fails for either
"sess_id" or "id", which can happen for number of reasons and results
in new session not being cached.

Patch fixes this by adding retry logic to "sess_id" & "id" allocations.

Patch by Piotr Sikora.
2013-03-29 17:17:45 +00:00
Maxim Dounin f121aa193d Merge of r5078: removed zero termination of shm zone names.
It was added in r2717 and no longer needed since r2721,
where the termination was added to ngx_shm_alloc() and
ngx_init_zone_pool().  Since then it only corrupted error
messages about invalid zones.
2013-03-29 17:15:34 +00:00
Maxim Dounin 50d44774c9 Merge of r5071: rebuild perl module on headers change.
Configure: rebuild perl module nginx.so if headers are changed.

Note: the "-p" argument of cp(1) dropped intentionally, to force nginx.so
rebuild.  It is considered too boring to properly list all dependencies
in Makefile.PL.
2013-03-29 17:13:45 +00:00
Maxim Dounin afd35712b2 Merge of r5070: fixed false memset warning on Linux.
Fixed false memset warning on Linux with -O3 (ticket #275).

Prodded by John Leach.
2013-03-29 17:11:09 +00:00
Maxim Dounin 8aa292d874 Version bump. 2013-03-29 15:29:29 +00:00
Maxim Dounin 9b39f14093 release-1.2.7 tag 2013-02-12 13:40:46 +00:00
Maxim Dounin d46e5d23bc nginx-1.2.7-RELEASE 2013-02-12 13:40:16 +00:00
Maxim Dounin 2b5c4f50a5 Merge of r5005, r5031, r5066: PCRE and OpenSSL for win32 builds. 2013-02-11 23:57:13 +00:00
Maxim Dounin 58def725c3 Merge of r5027, r5028, r5029: fastcgi_keep_conn fixes.
*) FastCGI: fixed wrong connection close with fastcgi_keep_conn.

   With fastcgi_keep_conn it was possible that connection was closed after
   FCGI_STDERR record with zero padding and without any further data read
   yet.  This happended as f->state was set to ngx_http_fastcgi_st_padding
   and then "break" happened, resulting in p->length being set to
   f->padding, i.e. 0 (which in turn resulted in connection close).

   Fix is to make sure we continue the loop after f->state is set.

*) FastCGI: unconditional state transitions.  Checks for f->padding
   before state transitions make code hard to follow, remove them and
   make sure we always do another loop iteration after f->state is
   set to ngx_http_fastcgi_st_padding.

*) FastCGI: proper handling of split fastcgi end request.  If fastcgi
   end request record was split between several network packets, with
   fastcgi_keep_conn it was possible that connection was saved in
   incorrect state (e.g. with padding bytes not yet read).
2013-02-11 16:11:14 +00:00
Maxim Dounin c751f174f5 Merge of r5018: secure link: fixed configuration inheritance.
The "secure_link_secret" directive was always inherited from the outer
configuration level even when "secure_link" and "secure_link_md5" were
specified on the inner level.
2013-02-11 16:09:35 +00:00
Maxim Dounin aaf45df542 Merge of r5017: fixed null dereference with resolver and poll.
Events: fixed null pointer dereference with resolver and poll.

A POLLERR signalled by poll() without POLLIN/POLLOUT, as seen on
Linux, would generate both read and write events, but there's no
write event handler for resolver events.  A fix is to only call
event handler of an active event.
2013-02-11 16:06:39 +00:00
Maxim Dounin f0ddd86389 Merge of r5014, r5015, r5016, r5030: geoip ipv6 support.
*) Configure: fixed style of include directories.

*) Configure: fixed GeoIP library detection.

*) GeoIP: IPv6 support.  When using IPv6 databases, IPv4 addresses are
   looked up as IPv4-mapped IPv6 addresses.  Mostly based on a patch
   by Gregor Kališnik (ticket #250).

*) GeoIP: removed pseudo-support of "proxy" and "netspeed" databases.
2013-02-11 15:34:30 +00:00
Maxim Dounin 5b114fb135 Merge of r5013: proxy: fixed proxy_method to always add space.
Before the patch if proxy_method was specified at http{} level the code
to add trailing space wasn't executed, resulting in incorrect requests
to upstream.
2013-02-11 15:31:10 +00:00
Maxim Dounin c03f5f6e9d Merge of r5012: configure: removed redundant variable assignment. 2013-02-11 15:28:50 +00:00
Maxim Dounin 52a3d34650 Merge of r5004, r5019-r5025: ssl fixes.
*) SSL: speedup loading of configs with many ssl servers.  The patch
   saves one EC_KEY_generate_key() call per server{} block by informing
   OpenSSL about SSL_OP_SINGLE_ECDH_USE we are going to use before
   the SSL_CTX_set_tmp_ecdh() call.

   For a configuration file with 10k simple server{} blocks with SSL
   enabled this change reduces startup time from 18s to 5s on a slow
   test box here.

*) SSL: removed conditions that always hold true.

*) SSL: resetting of flush flag after the data was written.  There is
   no need to flush next chunk of data if it does not contain a buffer
   with the flush or last_buf flags set.

*) SSL: preservation of flush flag for buffered data.  Previously,
   if SSL buffer was not sent we lost information that the data
   must be flushed.

*) SSL: calculation of buffer size moved closer to its usage.
   No functional changes.

*) SSL: avoid calling SSL_write() with zero data size.  According to
   documentation, calling SSL_write() with num=0 bytes to be sent
   results in undefined behavior.

   We don't currently call ngx_ssl_send_chain() with empty chain and
   buffer.  This check handles the case of a chain with total data size
   that is a multiple of NGX_SSL_BUFSIZE, and with the special buffer
   at the end.

   In practice such cases resulted in premature connection close and
   critical error "SSL_write() failed (SSL:)" in the error log.

*) SSL: take into account data in the buffer while limiting output.
   In some rare cases this can result in a more smooth sending rate.

*) SSL: fixed ngx_ssl_handshake() with level-triggered event methods.
   Missing calls to ngx_handle_write_event() and ngx_handle_read_event()
   resulted in a CPU hog during SSL handshake if an level-triggered event
   method (e.g. select) was used.
2013-02-11 15:12:06 +00:00
Maxim Dounin 0672b092b5 Merge of r5001: year 2013. 2013-02-11 15:00:43 +00:00
Maxim Dounin 471fb4c2bd Merge of r4999, r5003: detect duplicate "events" and "keepalive".
*) Upstream keepalive: detect duplicate "keepalive" directive.  A
   failure to detect duplicate "keepalive" directive resulted in
   stack exhaustion.

*) Events: added check for duplicate "events" directive.
2013-02-11 14:58:25 +00:00
Maxim Dounin 328b544313 Merge of r4992: off-by-one with 32/64 upstream backup servers.
Fixed off-by-one during upstream state resetting when switching to
backup servers if there were exactly 32 (64 on 64-bit platforms)
backup servers configured.

Based on patch by Thomas Chen (ticket #257).
2013-02-11 14:56:14 +00:00
Maxim Dounin 0a74b1021d Merge of r4991: fixed proxied HEAD requests with gzip enabled.
Fixed HEAD requests handling when proxying is used (ticket #261).
2013-02-11 14:39:49 +00:00
Maxim Dounin 7cc223cc54 Merge of r4985, r4986, r4987, r4988, r4989, r5002: access_log gzip.
*) Access log: fixed redundant buffer reallocation.  Previously a new
   buffer was allocated for every "access_log" directive with the same
   file path and "buffer=" parameters, while only one buffer per file
   is used.

*) Reopening log files code moved to a separate function.  The code
   refactored in a way to call custom handler that can do appropriate
   cleanup work (if any), like flushing buffers, finishing compress
   streams, finalizing connections to log daemon, etc..

*) Access log: the "flush" parameter of the "access_log" directive.

*) Configure: added the NGX_ZLIB define.  This was introduced for
   conditional compilation of the code that requires the zlib library.

*) Access log: the "gzip" parameter of the "access_log" directive.
   Note: this requires zlib version 1.2.0.4 or above to work.

*) The data pointer in ngx_open_file_t objects must be initialized.
   Uninitialized pointer may result in arbitrary segfaults if access_log
   is used without buffer and without variables in file path.
   Patch by Tatsuhiko Kubo (ticket #268).
2013-02-11 14:34:00 +00:00
Maxim Dounin 203cbb1be3 Merge of r4979, r4982: image filter configuration inheritance.
*) Image filter: configuration inheritance fixes.

   The image_filter_jpeg_quality, image_filter_sharpen and
   "image_filter rotate" were inherited incorrectly if a directive
   with variables was defined, and then redefined to a literal value,
   i.e. in configurations like

       image_filter_jpeg_quality $arg_q;

       location / {
           image_filter_jpeg_quality 50;
       }

   Patch by Ian Babrou, with minor changes.

*) Image filter: fixed image_filter rotate inheritance.

   Configurations like

       location /i/ {
           image_filter resize 200 200;
           image_filter rotate 180;

           location /i/foo/ {
               image_filter resize 200 200;
           }
      }

   resulted in rotation incorrectly applied in the location /i/foo,
   without any way to clear it.  Fix is to handle conf->angle/conf->acv
   consistently with other filter variables and do not try to inherit
   them if there are transformations defined for current location.
2013-02-11 13:59:08 +00:00
Maxim Dounin 7523ea7129 Merge of r4976: let add_header affect 201 responses (ticket #125). 2013-02-11 13:52:13 +00:00
Maxim Dounin 1b90454245 Merge of r4983: crypt_r() error handling fixed.
The crypt_r() function returns NULL on errors, check it explicitly instead
of assuming errno will remain 0 if there are no errors (per POSIX, the
setting of errno after a successful call to a function is unspecified
unless the description of that function specifies that errno shall not
be modified).

Additionally, dropped unneeded ngx_set_errno(0) and fixed error handling
of memory allocation after normal crypt(), which was inapropriate and
resulted in null pointer dereference on allocation failures.
2013-02-11 12:37:06 +00:00
Maxim Dounin ff0b21baff Merge of r4974: avoid sending "100 Continue" on 413.
Avoid sending "100 Continue" on 413 Request Entity Too Large.

Patch by Igor Sysoev.
2013-02-11 12:35:49 +00:00
Maxim Dounin b404c3bbbb Merge of r4993, r4994, r4997, r5000: geo ipv6 support.
*) Geo: IPv6 support.  The "ranges" mode is still limited to IPv4 only.

*) Geo: properly initialize ngx_cidr_t when dealing with "default".

*) Geo: made "default" affect both IPv4 and IPv6 when using prefixes.
   Previously, "default" was equivalent to specifying 0.0.0.0/0, now
   it's equivalent to specifying both 0.0.0.0/0 and ::/0 (if support
   for IPv6 is enabled) with the same value.

*) Geo: improved code readability.
2013-02-11 12:31:43 +00:00
Maxim Dounin a618295c0e Merge of r4968, r4969, r4977, r4980, r4981, r4990: geo fixes.
*) Geo: improved ngx_http_geo_block() code readability.

*) Geo: fixed the "ranges" without ranges case.  The following
   configuration returned an empty value for $geo:

       geo $geo {
           ranges;
           default default;
       }

*) Fixed return type of internal function that allocates radix tree nodes.

*) There's no need to normalize address returned by ngx_ptocidr().

*) Geo: ensure that default entry is always present.  If 0.0.0.0/32 entry
   was present and there was no explicit "default", we failed to add an
   empty string as a default value.

*) Trailing whitespace fix.
2013-02-11 12:26:33 +00:00
Maxim Dounin f2d783ed9e Merge of r4967: ngx_write_fd() and ngx_read_fd() errors handling.
The ngx_write_fd() and ngx_read_fd() functions return -1 in case of error,
so the incorrect comparison with NGX_FILE_ERROR (which is 0 on windows
platforms) might result in inaccurate error message in the error log.

Also the ngx_errno global variable is being set only if the returned value
is -1.
2013-02-10 03:55:18 +00:00
Maxim Dounin b8a75f4268 Merge of r4966: gzip: fixed zlib memLevel adjusting.
An incorrect memLevel (lower than 1) might be passed to deflateInit2() if the
"gzip_hash" directive is set to a value less than the value of "gzip_window"
directive. This resulted in "deflateInit2() failed: -2" alert and an empty
reply.
2013-02-10 03:52:26 +00:00
Maxim Dounin 91692bed55 Merge of r4965: upstream: fixed SIGSEGV with the "if" directive.
Configuration like

    location / {
        set $true 1;

        if ($true) {
            proxy_pass http://backend;
        }

        if ($true) {
            # nothing
        }
    }

resulted in segmentation fault due to NULL pointer dereference as the
upstream configuration wasn't initialized in an implicit location created
by the last if(), but the r->content_handler was set due to first if().

Instead of committing a suicide by dereferencing a NULL pointer, return
500 (Internal Server Error) in such cases, i.e. if uscf is NULL.  Better
fix would be to avoid such cases by fixing the "if" directive handling,
but it's out of scope of this patch.

Prodded by Piotr Sikora.
2013-02-10 03:27:15 +00:00
Maxim Dounin 6b356b1d1b Merge of r4963: proxy: better error message about unexpected data.
Requested by Igor Sysoev.
2013-02-10 03:22:58 +00:00
Maxim Dounin aecf7f8171 Merge of r4962: limit_rate fix.
Limit rate: fixed integer overflow in limit calculation (ticket #256).

Patch by Alexey Antropov.
2013-02-10 03:20:00 +00:00
Maxim Dounin 18429a3d73 Merge of r4961: configure: better check for PCRE JIT.
On Mac OS X system toolchain by default prefers include files
from /usr/local/include, but libraries from /usr/lib.  This might result in
various problems, in particular the one outlined below.

If the PCRE library is installed into /usr/local/, this results in pcre.h
being used from /usr/local/include (with PCRE_CONFIG_JIT defined), but
libpcre from /usr/lib (as shipped with the OS, without pcre_free_study()
symbol).  As a result build fails as we use pcre_free_study() function
if we try to compile with PCRE JIT support.

Obvious workaround to the root cause is to ask compiler to prefer
library from /usr/local/lib via ./configure --with-ld-opt="-L/usr/local/lib".
On the other hand, in any case it would be good to check if the function
we are going to use is available, hence the change.

See thread here for details:
http://mailman.nginx.org/pipermail/nginx-devel/2012-December/003074.html

Prodded by Piotr Sikora.
2013-02-10 03:18:08 +00:00
Maxim Dounin 13351e7337 Merge of r4948, r4949, r4964, r4973, r5011: variables.
*) Allow the complex value to be defined as an empty string.
   This makes conversion from strings to complex values possible
   without the loss of functionality.

*) The "auth_basic" directive gained support of variables.

*) Fixed variable syntax checking in "set", "geo", "limit_conn_zone",
   and "perl_set" directives.

*) Added checks that disallow adding a variable with an empty name.
   Added variable name syntax checks to "geo" and "map" directives.

*) Variables $pipe, $request_length, $time_iso8601, and $time_local.
   Log module counterparts are preserved for efficiency.
   Based on patch by Kiril Kalchev.
2013-02-10 03:08:42 +00:00
Maxim Dounin 756bbd758d Merge of r4947: xslt: prevented infinite loop.
If XSLT transformation failed and error 500 was handled in the same
location, an infinite loop occured that exhausted the stack.
2013-02-10 03:00:55 +00:00
Maxim Dounin 3fb9abaf6e Merge of r4946, r4978: perl.
*) Fixed build with embedded perl in certain setups (ticket #48).

*) Brought the link to ngx_http_perl_module documentation up to date.
2013-02-10 02:58:03 +00:00
Maxim Dounin 1c191e08c3 Merge of r4945, r4984: ngx_inet.[ch] minor fixes.
*) Fixed the NGX_SOCKADDR_STRLEN macro definition.
   The ngx_sock_ntop() function, when told to print both address and port,
   prints IPv6 address in square brackets, followed by colon and port.

*) Properly initialize "struct in6_addr" with zeroes.
2013-02-10 02:56:03 +00:00
Maxim Dounin 6c09adb37b Merge of r4944: removed GLOB_NOSORT glob option.
This will result in alphabetical sorting of included files if
the "include" directive with wildcards is used.

Note that the behaviour is now different from that on Windows, where
alphabetical sorting is not guaranteed for FindFirsFile()/FindNextFile()
(used to be alphabetical on NTFS, but not on FAT).

Approved by Igor Sysoev, prodded by many.
2013-02-09 21:27:37 +00:00
Maxim Dounin 087012ee7e Version bump. 2013-02-09 21:07:06 +00:00
Maxim Dounin abebd71985 release-1.2.6 tag 2012-12-11 14:26:07 +00:00
Maxim Dounin 6c47f561ba nginx-1.2.6-RELEASE 2012-12-11 14:24:23 +00:00
Maxim Dounin 089dd2f9ba Merge of r4921, r4922, r4923, r4924, r4925: request body fixes.
*) Request body: fixed "501 Not Implemented" error handling.

   It is not about "Method" but a generic message, and is expected to be used
   e.g. if specified Transfer-Encoding is not supported.  Fixed message to
   match RFC 2616.

   Additionally, disable keepalive on such errors as we won't be able to read
   request body correctly if we don't understand Transfer-Encoding used.

*) Request body: $request_body variable generalization.

   The $request_body variable was assuming there can't be more than two
   buffers.  While this is currently true due to request body reading
   implementation details, this is not a good thing to depend on and may
   change in the future.

*) Request body: code duplication reduced, no functional changes.

   The r->request_body_in_file_only with empty body case is now handled in
   ngx_http_write_request_body().

*) Request body: fixed socket leak on errors.

   The r->main->count reference counter was always incremented in
   ngx_http_read_client_request_body(), while it is only needs to be
   incremented on positive returns.

*) Request body: properly handle events while discarding body.

   An attempt to call ngx_handle_read_event() before actually reading
   data from a socket might result in read event being disabled, which is
   wrong.  Catched by body.t test on Solaris.
2012-12-11 13:18:50 +00:00
Maxim Dounin 3428ae9ab1 Merge of r4933, r4933: shared memory fixes.
*) Fixed location of debug message in ngx_shmtx_lock().

*) Core: don't reuse shared memory zone that changed ownership (ticket #210).

   nginx doesn't allow the same shared memory zone to be used for different
   purposes, but failed to check this on reconfiguration.  If a shared memory
   zone was used for another purpose in the new configuration, nginx attempted
   to reuse it and crashed.
2012-12-10 18:17:32 +00:00
Maxim Dounin 6bb2bf4cf6 Merge of r4920, r4939: ngx_write_chain_to_file() fixes.
*) Core: added debug logging of writev() in ngx_write_chain_to_file().

*) Core: fixed ngx_write_chain_to_file() with IOV_MAX reached.

   Catched by dav_chunked.t on Solaris.  In released versions this might
   potentially result in corruption of complex protocol responses if they
   were written to disk and there were more distinct buffers than IOV_MAX
   in a single write.
2012-12-10 18:04:54 +00:00
Maxim Dounin 572153c4a4 Merge of r4919: fixed segfault on PUT in dav module.
Dav: fixed segfault on PUT if body was already read (ticket #238).

If request body reading happens with different options it's possible
that there will be no r->request_body->temp_file available (or even
no r->request_body available if body was discarded).  Return internal
server error in this case instead of committing suicide by dereferencing
a null pointer.
2012-12-10 17:51:10 +00:00
Maxim Dounin ae14505582 Merge of r4918: cache manager startup with many listen sockets.
Fixed failure to start cache manager and cache loader processes
if there were more than 512 listening sockets in configuration.
2012-12-10 17:46:51 +00:00
Maxim Dounin aa94ea5dea Merge of r4915, r4916, r4917: upstream minor fixes.
*) Upstream: honor the "down" flag for a single server.

   If an upstream block was defined with the only server marked as
   "down", e.g.

       upstream u {
           server 127.0.0.1:8080 down;
       }

   an attempt was made to contact the server despite the "down" flag.
   It is believed that immediate 502 response is better in such a
   case, and it's also consistent with what is currently done in case
   of multiple servers all marked as "down".

*) Upstream: better detection of connect() failures with kqueue.

   Pending EOF might be reported on both read and write events, whichever
   comes first, so check both of them.

   Patch by Yichun Zhang (agentzh), slightly modified.
2012-12-10 16:35:32 +00:00
Maxim Dounin 02615df1bb Merge of r4914: variables $request_time and $msec.
Log module counterparts are preserved for efficiency.
2012-12-10 16:03:56 +00:00
Maxim Dounin 032c4f2425 Merge of r4913: fixed CPU affinity on respawn of dead workers.
Worker processes are now made aware of their sequential number needed
to select CPU affinity mask.  This replaces a workaround from r4865.
2012-12-10 16:00:55 +00:00
Maxim Dounin 4be8258166 Version bump. 2012-12-10 15:43:41 +00:00
Maxim Dounin 8bf9560e56 release-1.2.5 tag 2012-11-13 13:35:19 +00:00
Maxim Dounin e487de6fa9 nginx-1.2.5-RELEASE 2012-11-13 13:34:59 +00:00
Maxim Dounin 071831dc3d Merge of r4896: event pipe: fixed handling of buf_to_file data.
Input filter might free a buffer if there is no data in it, and in case
of first buffer (used for cache header and request header, aka p->buf_to_file)
this resulted in cache corruption.  Buffer memory was reused to read upstream
response before headers were written to disk.

Fix is to avoid moving pointers in ngx_event_pipe_add_free_buf() to a buffer
start if we were asked to free a buffer used by p->buf_to_file.

This fixes occasional cache file corruption, usually resulted
in "cache file ... has md5 collision" alerts.

Reported by Anatoli Marinov.
2012-11-13 11:24:14 +00:00
Maxim Dounin e1fd544763 Merge of r4892: keepalive memory usage optimization.
The ngx_http_keepalive_handler() function is now trying to not
keep c->buffer's memory for idle connections.

This behaviour is consistent with the ngx_http_set_keepalive()
function and it should decrease memory usage in some cases (especially
if epoll/rtsig is used).
2012-11-13 11:21:31 +00:00
Maxim Dounin 41b2b12346 Merge of r4891: worker_processes auto.
Core: the "auto" parameter of the "worker_processes" directive.

The parameter will set the number of worker processes to the
autodetected number of available CPU cores.
2012-11-13 11:00:37 +00:00
Maxim Dounin 5e727f5775 Merge of r4886, r4887, r4894: log variables generalization:
*) Log: $apache_bytes_sent removed.  It was renamed to $body_bytes_sent
   in nginx 0.3.10 and the old name is deprecated since then.

*) Variable $bytes_sent.  It replicates variable $bytes_sent as previously
   available in log module only.  Patch by Benjamin Grössing (with minor
   changes).

*) Variables $connection and $connection_requests.  Log module
   counterparts are removed as they aren't used often and there is no
   need to preserve them for efficiency.
2012-11-13 10:45:23 +00:00
Maxim Dounin c6276b4150 Merge of r4885: ssl_verify_client optional_no_ca.
SSL: the "ssl_verify_client" directive parameter "optional_no_ca".

This parameter allows to don't require certificate to be signed by
a trusted CA, e.g. if CA certificate isn't known in advance, like in
WebID protocol.

Note that it doesn't add any security unless the certificate is actually
checked to be trusted by some external means (e.g. by a backend).

Patch by Mike Kazantsev, Eric O'Connor.
2012-11-13 10:42:16 +00:00
Maxim Dounin a07ab9ad54 Merge of r4872, r4893: resolver cached addresses random rotation.
Resolver: cached addresses are returned with random rotation now.

This ensures balancing when working with dynamically resolved upstream
servers with multiple addresses.

Based on patch by Anton Jouline.
2012-11-12 18:47:07 +00:00
Maxim Dounin f4fd2d59a3 Merge of r4870, r4871, r4890, r4895: minor fixes.
*) Made sure to initialize the entire ngx_file_t structure.
   Found by Coverity.

*) Correct plural form for "path" in the whole source base.

*) Removed conditional compilation from waitpid() error test.

   There are reports that call to a signal handler for an exited process
   despite waitpid() already called for the process may happen on Linux
   as well.

*) Style, parentheses instead of braces in misc/GNUMakefile.
2012-11-12 18:39:51 +00:00
Maxim Dounin 1c640c946f Merge of r4868, r4869: SSL minor fixes.
*) SSL: fixed compression workaround to remove all methods.

   Previous code used sk_SSL_COMP_delete(ssl_comp_methods, i) while iterating
   stack from 0 to n, resulting in removal of only even compression methods.

   In real life this change is a nop, as there is only one compression method
   which is enabled by default in OpenSSL.

*) SSL: added version checks for ssl compression workaround.

   The SSL_COMP_get_compression_methods() is only available as an API
   function in OpenSSL 0.9.8+, require it explicitly to unbreak build
   with OpenSSL 0.9.7.
2012-11-12 18:00:32 +00:00
Maxim Dounin 7988f4aca5 Merge of r4866, r4867: configure fixes.
*) Configure: help updated to list upstream keepalive and least_conn.
   Patch by Joshua Zhu.

*) Configure: additional test for ExtUtils::Embed perl module presence.
   Now perl configure will correctly fail if ExtUtils::Embed perl module
   is not present in the system (found on Amazon Linux AMI, as of
   release 2012.03).
2012-11-12 17:57:57 +00:00
Maxim Dounin 8541966db2 Merge of r4865: clearing of cpu_affinity after process spawn.
This fixes unwanted/incorrect cpu_affinity use on dead worker processes
respawn.  While this is not ideal, it's expected to be better when previous
situation where multiple processes were spawn with identical CPU affinity
set.

Reported by Charles Chen.
2012-11-12 17:54:49 +00:00
Maxim Dounin 3cf301db77 Version bump. 2012-11-12 17:03:38 +00:00
Maxim Dounin 3676939732 release-1.2.4 tag 2012-09-25 13:43:03 +00:00
Maxim Dounin 7965a30a78 nginx-1.2.4-RELEASE 2012-09-25 13:42:43 +00:00
Maxim Dounin ee1acd5389 Stable: removed gunzip module from win32 helper target.
Gunzip filter isn't merged into stable branch.
2012-09-25 10:41:22 +00:00
Maxim Dounin 3cc0fe30d8 Merge of r4835, r4841: improved welcome and 50x error pages. 2012-09-24 19:14:17 +00:00
Maxim Dounin 8a90b57fc9 Merge of r4833: limit req: fix of rbtree node insertion.
Limit req: fix of rbtree node insertion on hash collisions.

The rbtree used in ngx_http_limit_req_module has two level of keys, the top is
hash, and the next is the value string itself. However, when inserting a new
node, only hash has been set, while the value string has been left empty.

The bug was introduced in r4419 (1.1.14).
Found by Charles Chen.
2012-09-24 19:11:45 +00:00
Maxim Dounin 917a5c0a6f Merge of r4829: fixed strict aliasing with ipv6 (ticket #201).
Fixed strict aliasing bugs when dealing with IPv4-mapped IPv6
addresses.
2012-09-24 19:06:48 +00:00
Maxim Dounin 8831af3698 Merge of r4828: "include" with wildcards in map and types blocks.
The "include" directive should be able to include multiple files if
given a filename mask.  Fixed this to work for "include" directives
inside the "map" or "types" blocks.  The "include" directive inside
the "geo" block is still not fixed.
2012-09-24 19:05:02 +00:00
Maxim Dounin 2b64e62233 Merge of r4817: geo: fixed handling of ranges without default set.
The bug had appeared in 0.8.43 (r3653).  Patch by Weibin Yao.
2012-09-24 19:02:16 +00:00
Maxim Dounin 8cc4f6248a Merge of r4815: map: fixed optimization of variables as values.
Previous code incorrectly used ctx->var_values as an array of pointers to
ngx_http_variable_value_t, but the array contains structures, not pointers.
Additionally, ctx->var_values inspection failed to properly set var on
match.
2012-09-24 19:00:02 +00:00
Maxim Dounin 6286f9c062 Merge of r4813, r4814, r4818, r4819, r4820, r4823: mail fixes.
*) Corrected the directive name in the ngx_mail_auth_http_module
   error message.

*) Don't let the well-known port in the "listen" directive to
   override the already set "protocol".

*) Fixed sorting of listen addresses (ticket #187).  For http module
   this problem was already fixed in r4756.

*) Removed a stale "AF_INET only" comment.  IPv6 client connections
   in mail modules have been supported since r2856.

*) Fixed handling of AF_UNIX addresses in "listen".  This makes AF_UNIX
   addresses in mail officially supported.

*) Whitespace fix.
2012-09-24 18:58:13 +00:00
Maxim Dounin be844866bb Merge of r4785, r4795, r4811, r4812, r4816, r4822: coverity.
*) Resolver: fixed possible memory leak in ngx_resolver_create().

*) Explicitly ignore returned value from unlink() in ngx_open_tempfile().

*) Explicitly ignore returned value from close() in ngx_event_core_init_conf().

*) Added three missing checks for NULL after ngx_array_push() calls.

*) Crypt: fixed handling of corrupted SSHA entries in password file.

*) Mark logically dead code with corresponding comment.

Found by / prodded by Coverity.
2012-09-24 18:54:28 +00:00
Maxim Dounin e1e56351f1 Merge of r4784: fixed the -p parameter handling.
Ensure that the path supplied always ends with a `/' except when empty.
An empty value now corresponds to the current directory instead of `/'.
2012-09-24 18:50:25 +00:00
Maxim Dounin 38df2aa726 Merge of r4842: fixed make macros to use parentheses.
Configure: fixed make macros to use parentheses instead of braces.
Parentheses are more portable, in particular they are understood by
nmake while braces aren't.
2012-09-24 18:46:50 +00:00
Maxim Dounin b22f4fb6f0 Merge of r4779, r4840, r4843, r4844: win32 changes.
*) Fixed build with Visual Studio 2005 Express.

   It is available via winetricks which makes it still usable, and has
   an old crtdefs.h which uses _CRT_SECURE_NO_DEPRECATE instead of
   _CRT_SECURE_NO_WARNINGS to suppress warnings.

   Reported by HAYASHI Kentaro,
   http://mailman.nginx.org/pipermail/nginx-devel/2012-August/002542.html

*) Configure: provide inflate() when building zlib on win32.

*) Helper target "win32" to run configure for win32 builds.

*) Updated zlib used for win32 builds.
2012-09-24 18:37:14 +00:00
Maxim Dounin cc1bb6ebdf Merge of r4778, r4782, r4783, r4824, r4830, r4834: minor fixes.
*) Reorder checks in ngx_shared_memory_add() for more consistent
   error messages.

*) Added "const" to ngx_memcpy() with NGX_MEMCPY_LIMIT defined.  This
   fixes warning produced during compilation of the ngx_http_geoip_module
   due to const qualifier being discarded.

*) Fixed possible use of old cached times if runtime went backwards.

   If ngx_time_sigsafe_update() updated only ngx_cached_err_log_time, and
   then clock was adjusted backwards, the cached_time[slot].sec might
   accidentally match current seconds on next ngx_time_update() call,
   resulting in various cached times not being updated.

   Fix is to clear the cached_time[slot].sec to explicitly mark cached times
   are stale and need updating.

*) Radix tree preallocation fix.  The preallocation size was calculated
   incorrectly and was always 8 due to sizeof(ngx_radix_tree_t) accidentally
   used instead of sizeof(ngx_radix_node_t).

*) Fixed overflow if ngx_slab_alloc() is called with very big "size"
   argument.

*) Write filter: replaced unneeded loop with one to free chains.
   Noted by Gabor Lekeny.
2012-09-24 18:34:04 +00:00
Maxim Dounin 97047b74c5 Merge of r4777, r4780, r4831, r4832: release process changes.
*) Simplified makefile that builds CHANGES.

*) Removed the need in Perl to generate ZIP archive of nginx/Windows.

*) Converted DOS-style newlines in dump.xslt.

*) Pass changes.xml thru xmllint when generating CHANGES and CHANGES.ru.
2012-09-24 18:30:26 +00:00
Maxim Dounin ad80992b26 Version bump. 2012-09-24 18:24:07 +00:00
Maxim Dounin 083596dbb0 release-1.2.3 tag 2012-08-07 12:36:19 +00:00
Maxim Dounin 05b8ccb52b nginx-1.2.3-RELEASE 2012-08-07 12:35:56 +00:00
Maxim Dounin 17a5184e3a Merge of r4739: s/ngx_shmtx_destory/ngx_shmtx_destroy/. 2012-08-06 18:09:23 +00:00
Maxim Dounin ffe8787e23 Merge of r4775: updated PCRE used for win32 builds. 2012-08-06 17:38:12 +00:00
Maxim Dounin f20d1bae3f Merge of r4771: ngx_http_find_virtual_server() fix.
The ngx_http_find_virtual_server() function should return NGX_DECLINED
if virtual server not found.
2012-08-06 17:36:30 +00:00
Maxim Dounin 52df349abc Merge of r4770: hide_headers/pass_headers inheritance fix.
Hide headers and pass headers arrays might not be inherited correctly
into a nested location, e.g. in configuration like

    server {
        proxy_hide_header X-Foo;
        location / {
            location /nested/ {
                proxy_pass_header X-Pad;
            }
        }
    }

the X-Foo header wasn't hidden in the location /nested/.

Reported by Konstantin Svist,
http://mailman.nginx.org/pipermail/nginx-ru/2012-July/047555.html
2012-08-06 17:34:08 +00:00
Maxim Dounin 5ff6b77a01 Merge of r4769: better diagnostics for directives in wrong context. 2012-08-06 17:31:32 +00:00
Maxim Dounin 77dc045e9e Merge of r4766, r4767: ngx_http_upstream_add() changes.
*) Fixed to return NULL if an error occurs.

*) Microoptimization: replaced an expression known to be constant with
   the constant value.
2012-08-06 17:20:01 +00:00
Maxim Dounin af87c31654 Merge of r4765: reduced the number of preprocessor directives. 2012-08-06 17:15:23 +00:00
Maxim Dounin 726a071b0f Merge of r4764: debug_connection with a domain name change.
When "debug_connection" is configured with a domain name, only the first
resolved address was used.  Now all addresses will be used.
2012-08-06 17:13:20 +00:00
Maxim Dounin 201d0da810 Merge of r4763: added the Clang compiler support.
The -Werror is commented out to not break builds on Linux.
2012-08-06 17:10:35 +00:00
Maxim Dounin d833679582 Merge of r4760, r4761: -Wmissing-prototypes.
Fixed compilation with -Wmissing-prototypes.  Added a commented
out -Wmissing-prototypes to CFLAGS.  It is commented out to not break
builds with 3rd party modules.
2012-08-06 17:07:28 +00:00
Maxim Dounin 09e0f2a76e Merge of r4759, r4762, r4768: configure minor fixes.
*) Replaced a number of "else if" with "elif".

*) Made sure to run configure in a "C" locale.  Otherwise, we may fail
   to properly detect a version of compiler.

*) Removed extraneous GCC warning flags.
2012-08-06 17:03:01 +00:00
Maxim Dounin f03effbc47 Merge of r4758: win32: fixed cpu hog after process startup failure.
If ngx_spawn_process() failed while starting a process, the process
handle was closed but left non-NULL in the ngx_processes[] array.
The handle later was used in WaitForMultipleObjects() (if there
were multiple worker processes configured and at least one worker
process was started successfully), resulting in infinite loop.

Reported by Ricardo Villalobos Guevara:
http://mailman.nginx.org/pipermail/nginx-devel/2012-July/002494.html
2012-08-06 16:24:22 +00:00
Maxim Dounin 26960680e4 Merge of r4757: debugging messages in limit_conn.
Fixed debugging messages to account that limit_zone was renamed to limit_conn.
2012-08-06 16:19:35 +00:00
Maxim Dounin 9e518898de Version bump. 2012-08-06 16:06:36 +00:00
Maxim Dounin 41e1ea0222 Merge of r4756: fixed listen addresses sorting (ticket #187)
Fixed sorting of listen addresses so that wildcard address is always at
the end.  Failure to do so could result in several listen sockets to be
created instead of only one listening on wildcard address.

Reported by Roman Odaisky.
2012-08-06 16:03:56 +00:00
Maxim Dounin ff331a2988 Merge of r4754: synchronized the license text.
Synchronized the license text with the FreeBSD's bsd-style-copyright.
2012-08-06 15:52:02 +00:00
Maxim Dounin f3d9aa2da4 Merge of r4741: fixed "make" used instead of "${MAKE}". 2012-08-06 15:47:15 +00:00
Maxim Dounin 9fff8c5dcb Merge of r4740: fixed $request_length for pipelined requests. 2012-08-06 15:45:44 +00:00
Maxim Dounin 5fa264d72a Merge of r4738: struct flock initialization.
Made sure to initialize the entire "struct flock" allocated on stack.
2012-08-06 15:31:49 +00:00
Maxim Dounin e119c8f3cf Merge of r4737: r->uri_changed in a named location fix.
Reset r->uri_changed in a named location (ticket #184).
2012-08-06 15:20:03 +00:00
Maxim Dounin 73f3836c3c Merge of r4736: typo fixed. 2012-08-06 14:58:36 +00:00
Maxim Dounin dbb1cff8cf Merge of r4713: map hostnames fix (ticket #182).
The final dot wasn't stripped before looking up in a map of hostnames.
2012-08-06 14:04:06 +00:00
Maxim Dounin a42b00b2a7 release-1.2.2 tag 2012-07-03 10:48:54 +00:00
Maxim Dounin 4cf4cdb56c nginx-1.2.2-RELEASE 2012-07-03 10:48:31 +00:00
Maxim Dounin d39b505182 Merge of r4698: X-Forwarded-For conditionals.
Fixed compile-time conditionals used to detect if X-Forwarded-For support
is needed.

Note: compatibility shims were added during merge to avoid possible
breakage of 3rd party modules.  At least cache purge module was broken
by the original commit, as it used to rely on NGX_HTTP_PROXY define.
2012-07-02 17:41:52 +00:00
Maxim Dounin cbdfd188c8 Merge of r4697: disabled gzip in OpenSSL prior to 1.0.0.
Disabled gzip compression in OpenSSL prior to 1.0.0 version.
This saves about 522K per connection.
2012-07-02 17:25:51 +00:00
Maxim Dounin dc9d9c6cd3 Merge of r4693: fixed "sendmsg() failed" alerts on HP-UX.
HP-UX needs _HPUX_ALT_XOPEN_SOCKET_API to be defined to be able to
use various POSIX versions of networking functions.  Notably sendmsg()
resulted in "sendmsg() failed (9: Bad file number)" alerts without it.

See xopen_networking(7) for more details.
2012-07-02 17:22:31 +00:00
Maxim Dounin 083c85ab73 Merge of r4691: changed default alignment to 16.
This fixes alignment problems observerd on ARMs, and likely also needed
for MIPSes.  Unless we know alignment is not required just assume we
need 16, which appears to be safe default for all architectures.

See here for details:
http://mailman.nginx.org/pipermail/nginx/2012-June/034139.html
2012-07-02 17:08:26 +00:00
Maxim Dounin 683fa7f420 Merge of r4690: conflicting wildcard server names fix.
With previous code wildcard names were added to hash even if conflict
was detected.  This resulted in identical names in hash and segfault
later in ngx_hash_wildcard_init().
2012-07-02 16:59:34 +00:00
Maxim Dounin 9c9360a7b5 Merge of r4688, r4689, r4706:
*) Mp4: fixed non-keyframe seeks in some cases (ticket #175).

   Number of entries in stsc atom was wrong if we've added an entry to
   split a chunk.

   Additionally, there is no need to add an entry if we are going to split
   last chunk in an entry, it's enough to update the entry we already have.
   Previously new entry was added and old one was left as is, resulting in
   incorrect entry with zero chunks which might confuse some software.

*) Mp4: fixed streaming if moov atom is at buffer edge.
2012-07-02 16:56:53 +00:00
Maxim Dounin 1e7eedc24f Merge of r4686, r4687: $status variable.
Contains response status code as a 3-digit integer
(with leading zeroes if necessary), or one of the following values:

    000 - response status code has not yet been assigned
    009 - HTTP/0.9 request is being processed
2012-07-02 16:53:36 +00:00
Maxim Dounin 38f17f5d60 Merge of r4682, r4694, r4699, r4704, r4705: minor nits.
*) Fixed spelling of "endianness", and called it "byte ordering" in the
   user visible part.

*) Fixed return type of ngx_strerror_init().

*) Fixed a harmless error in spelling of "Connection: close" when computing
   the response header length.

*) Style.

*) Added code to look up Google perftools in /opt/local/, for MacPorts.
2012-07-02 16:51:02 +00:00
Maxim Dounin ac21ef1276 Merge of r4655, r4656, r4657, r4695, r4696: upstream changes.
*) Upstream: least_conn balancer module.

*) Upstream: weights and IPv6 support in ip_hash balancer.

*) Upstream keepalive: "single" parameter deprecated.
2012-07-02 16:41:13 +00:00
Maxim Dounin 2523334c94 Merge of r4654, r4672, r4684, r4685, r4692: resolver changes.
*) Resolver: fixed format specification.
   Patch by Yichun Zhang (agentzh).

*) Support for IPv6 literals and an optional port in resolver.

*) Fixed crash in ngx_resolver_cleanup_tree().

   If sending a DNS request fails with an error (e.g., when mistakenly
   trying to send it to a local IP broadcast), such a request is not
   deleted if there are clients waiting on it.  However, it was still
   erroneously removed from the queue.  Later ngx_resolver_cleanup_tree()
   attempted to remove it from the queue again that resulted in a NULL
   pointer dereference.

*) When "resolver" is configured with a domain name, only the first
   resolved address was used.  Now all addresses will be used.

*) Fixed segfault with poll and resolver used.

   Poll event method needs ngx_cycle->files to work, and use of
   ngx_exit_cycle without files set caused null pointer dereference in
   resolver's cleanup on udp socket close.
2012-07-02 16:23:14 +00:00
Maxim Dounin 3bf1461a8f Merge of r4671: support for IPv6 literals in proxy_pass and so on. 2012-07-02 16:16:27 +00:00
Maxim Dounin 09b92ff5bb Merge of r4653: ngx_inet.c code reduction.
Code reduction (no functional changes).
2012-07-02 16:11:02 +00:00
Maxim Dounin d1c053b9b8 Merge of r4652: ssl without buffer should not set c->buffered.
Removed mistaken setting of NGX_SSL_BUFFERED flag in ngx_ssl_send_chain()
if SSL buffer is not used.
2012-07-02 15:51:02 +00:00
Maxim Dounin a9cc91bacf Merge of r4651: proxy_cookie_* fix.
Fixed returned value handling from the cookie rewrite handler.

If the "proxy_cookie_domain" or "proxy_cookie_path" directive is used and there
are no matches in Set-Cookie header then ngx_http_proxy_rewrite_cookie() returns
NGX_DECLINED to indicate that the header was not rewritten. Returning this value
further from the upstream headers copy handler resulted in 500 error response.

See here for report:
http://mailman.nginx.org/pipermail/nginx/2012-May/033858.html
2012-07-02 15:43:50 +00:00
Maxim Dounin 5eb5790e06 Merge of r4648, r4649, r4650: memory leak with $geoip_org.
Patch by Denis F. Latypoff (slightly modified).
2012-07-02 15:41:31 +00:00
Maxim Dounin 7f911295fa Merge of r4647: xslt reuse.
Fixed the reuse of parsed DTDs and XSLTs.

Patch by Kuramoto Eiji.
2012-07-02 15:39:28 +00:00
Maxim Dounin 8f1738a9df Merge of r4646: jemalloc 3.0.0 compatibility.
Fixed compilation with -DNGX_DEBUG_MALLOC on FreeBSD 10.

After jemalloc 3.0.0 import there is no _malloc_options symbol, it has
been replaced with the malloc_conf one with a different syntax.
2012-07-02 15:37:49 +00:00
Maxim Dounin 1dec0cfafb Merge of r4644:
Fixed potential null pointer dereference in ngx_resolver_create().
While here, improved error message.
2012-07-02 15:35:22 +00:00
Maxim Dounin da29cd1feb Merge of r4643:
Removed historical and now redundant syntax pre-checks in ngx_parse_url().
2012-07-02 15:33:35 +00:00
Maxim Dounin 747599d1f9 Merge of r4642:
Fixed core variables dynamic access after reconfiguration.

If variable was indexed in previous configuration but not in current
one, the NGX_HTTP_VAR_INDEXED flag was left set and confused
ngx_http_get_variable().

Patch by Yichun Zhang (agentzh), slightly modified.
2012-07-02 14:42:08 +00:00
Maxim Dounin 3356787783 Merge of r4639, r4640: C++ fixes.
Fixed the ngx_regex.h header file compatibility with C++.  Fixed
building --with-cpp_test_module on some systems.
2012-06-29 17:32:43 +00:00
Maxim Dounin fefcbf1738 Merge of r4636, r4637, r4638: config sanity checks.
*) Added syntax checking of the second parameter of the "split_clients"
   directive.

*) Capped the status code that may be returned with "return" and
   "try_files".

*) Zero padded the returned and logged HTTP status code, and fixed possible
   buffer overrun in $status handling.
2012-06-29 17:28:41 +00:00
Maxim Dounin 541f213465 Merge of r4645: fixed warning during nginx.xs compilation. 2012-06-26 14:40:23 +00:00
Maxim Dounin 36a18fdd06 Fixed misc/GNUmakefile to properly tag on stable-1.2 branch. 2012-06-25 15:41:17 +00:00
Maxim Dounin f01e1b9226 Version bump. 2012-06-25 15:40:29 +00:00
Maxim Dounin f8448034d4 Retagged release-1.2.1 properly. 2012-06-25 15:35:27 +00:00
Maxim Dounin e8b9c34064 nginx-1.2.1-RELEASE 2012-06-05 14:01:45 +00:00
Maxim Dounin da99f76591 Merge of r4674, r4675, r4676: win32 fixes.
*) Win32: disallowed access to various non-canonical name variants.

   This includes trailings dots and spaces, NTFS streams (and short names, as
   previously checked).  The checks are now also done in ngx_file_info(), thus
   allowing to use the "try_files" directive to protect external scripts.

*) Win32: normalization of trailing dot inside uri.

   Windows treats "/directory./" identical to "/directory/".  Do the same
   when working on Windows.  Note that the behaviour is different from one
   with last path component (where multiple spaces and dots are ignored by
   Windows).

*) Win32: uris with ":$" are now rejected.

   There are too many problems with special NTFS streams, notably "::$data",
   "::$index_allocation" and ":$i30:$index_allocation".

   For now we don't reject all URIs with ":" like Apache does as there are no
   good reasons seen yet, and there are multiple programs using it in URLs
   (e.g. MediaWiki).
2012-06-05 13:52:37 +00:00
Maxim Dounin 5924995822 Merge of r4632: updated openssl used for win32 builds. 2012-06-05 13:17:05 +00:00
Maxim Dounin 62b2d07640 Merge of r4630: fixed c->sent with unbuffered ssl.
Update c->sent in ngx_ssl_send_chain() even if SSL buffer is not used.
2012-06-04 12:00:38 +00:00
Maxim Dounin 2ae26f4d08 Merge of r4614, r4624-r4629, r4631: proxy recursive changes.
*) Added IPv6 and UNIX-domain socket support in "debug_connection"
   directive.

*) New function ngx_http_get_forwarded_addr() to look up real client
   address.

   On input it takes an original address, string in the X-Forwarded-For format
   and its length, list of trusted proxies, and a flag indicating to perform
   the recursive search.  On output it returns NGX_OK and the "deepest" valid
   address in a chain, or NGX_DECLINED.  It supports AF_INET and AF_INET6.
   Additionally, original address and/or proxy may be specified as AF_UNIX.

*) Realip: chains of trusted proxies and IPv6 support.

   The module now supports recursive search of client address through
   the chain of trusted proxies, controlled by the "real_ip_recursive"
   directive (closes #2).  It also gets full IPv6 support (closes #44)
   and canonical value of the $client_addr variable on address change.

   Example:

       real_ip_header X-Forwarded-For;
       set_real_ip_from 127.0.0.0/8;
       set_real_ip_from ::1;
       set_real_ip_from unix:;
       real_ip_recursive on;

*) Geo: chains of trusted proxies and partial IPv6 support.

   The module now supports recursive search of client address through
   the chain of trusted proxies, controlled by the "proxy_recursive"
   directive in the "geo" block.  It also gets partial IPv6 support:
   now proxies may be specified with IPv6 addresses.

   Example:

       geo $test {
           ...
           proxy 127.0.0.1;
           proxy ::1;
           proxy_recursive;
       }

   There's also a slight change in behavior.  When original client
   address (as specified by the "geo" directive) is one of the
   trusted proxies, and the value of the X-Forwarded-For request
   header cannot not be parsed as a valid address, an original client
   address will be used for lookup.  Previously, 255.255.255.255 was
   used in this case.

*) Geoip: trusted proxies support and partial IPv6 support.

   The module now supports recursive search of client address through the
   chain of trusted proxies (closes #100), in the same scope as the geo
   module.  Proxies are listed by the "geoip_proxy" directive, recursive
   search is enabled by the "geoip_proxy_recursive" directive.  IPv6 is
   partially supported: proxies may be specified with IPv6 addresses.

   Example:

        geoip_country .../GeoIP.dat;
        geoip_proxy 127.0.0.1;
        geoip_proxy ::1;
        geoip_proxy 10.0.0.0/8;
        geoip_proxy_recursive on;
2012-06-04 11:58:12 +00:00
Maxim Dounin 42a882727b Merge of r4622, r4623: balancing changes.
*) Upstream: smooth weighted round-robin balancing.

   For edge case weights like { 5, 1, 1 } we now produce { a, a, b, a, c, a, a }
   sequence instead of { c, b, a, a, a, a, a } produced previously.

   Algorithm is as follows: on each peer selection we increase current_weight
   of each eligible peer by its weight, select peer with greatest current_weight
   and reduce its current_weight by total number of weight points distributed
   among peers.

   In case of { 5, 1, 1 } weights this gives the following sequence of
   current_weight's:

        a  b  c
        0  0  0  (initial state)

        5  1  1  (a selected)
       -2  1  1

        3  2  2  (a selected)
       -4  2  2

        1  3  3  (b selected)
        1 -4  3

        6 -3  4  (a selected)
       -1 -3  4

        4 -2  5  (c selected)
        4 -2 -2

        9 -1 -1  (a selected)
        2 -1 -1

        7  0  0  (a selected)
        0  0  0

   To preserve weight reduction in case of failures the effective_weight
   variable was introduced, which usually matches peer's weight, but is
   reduced temporarily on peer failures.

   This change also fixes loop with backup servers and proxy_next_upstream
   http_404 (ticket #47), and skipping alive upstreams in some cases if there
   are multiple dead ones (ticket #64).

*) Upstream: fixed ip_hash rebalancing with the "down" flag.

   Due to weight being set to 0 for down peers, order of peers after sorting
   wasn't the same as without the "down" flag (with down peers at the end),
   resulting in client rebalancing for clients on other servers.  The only
   rebalancing which should happen after adding "down" to a server is one
   for clients on the server.

   The problem was introduced in r1377 (which fixed endless loop by setting
   weight to 0 for down servers).  The loop is no longer possible with new
   smooth algorithm, so preserving original weight is safe.
2012-06-04 11:21:58 +00:00
Maxim Dounin e28d5925d1 Merge of r4621, r4641: filter_finalize fixes.
*) Fixed possible request hang with filter finalization.

   With r->filter_finalize set the ngx_http_finalize_connection() wasn't
   called from ngx_http_finalize_request() called with NGX_OK, resulting in
   r->main->count not being decremented, thus causing request hang in some
   rare situations.

   Patch by Yichun Zhang (agentzh).

*) Fixed segfault with filter_finalize introduced in r4621 (1.3.0).

See the following thread for more details:
http://mailman.nginx.org/pipermail/nginx-devel/2012-May/002190.html
2012-06-04 11:15:46 +00:00
Maxim Dounin 27c1abba1a Merge of r4619: accept moderation on EMFILE/ENFILE.
In case of EMFILE/ENFILE returned from accept() we disable accept events,
and (in case of no accept mutex used) arm timer to re-enable them later.
With accept mutex we just drop it, and rely on normal accept mutex handling
to re-enable accept events once it's acquired again.

As we now handle errors in question, logging level was changed to "crit"
(instead of "alert" used for unknown errors).

Note: the code might call ngx_enable_accept_events() multiple times if
there are many listen sockets.  The ngx_enable_accept_events() function was
modified to check if connection is already active (via c->read->active) and
skip it then, thus making multiple calls safe.
2012-06-04 11:10:36 +00:00
Maxim Dounin 11d364307b Merge of r4618: rewrite escaping fix (ticket #162).
The following code resulted in incorrect escaping of uri and possible
segfault:

    location / {
        rewrite ^(.*) $1?c=$1;
        return 200 "$uri";
    }

If there were arguments in a rewrite's replacement string, and length was
actually calculated (due to duplicate captures as in the example above,
or variables present), the is_args flag was set and incorrectly copied
after length calculation.  This resulted in escaping applied to the uri part
of the replacement, resulting in incorrect escaping.  Additionally, buffer
was allocated without escaping expected, thus this also resulted in buffer
overrun and possible segfault.
2012-06-04 11:07:19 +00:00
Maxim Dounin 8340edcb7e Merge of r4617: fastcgi padding fix.
Fastcgi: fixed padding handling on fixed-size records.

Padding was incorrectly ignored on end request, empty stdout and stderr
fastcgi records.  This resulted in protocol desynchronization if fastcgi
application used these records with padding for some reason.

Reported by Ilia Vinokurov.
2012-06-04 11:00:34 +00:00
Maxim Dounin 4e320f9b77 Merge of r4616: r->state fix.
Added r->state reset on fastcgi/scgi/uwsgi request start.

Failing to do so results in problems if 400 or 414 requests are
redirected to fastcgi/scgi/uwsgi upstream, as well as after invalid
headers got from upstream.  This was already fixed for proxy in r3478,
but fastcgi (the only affected protocol at that time) was missed.

Reported by Matthieu Tourne.
2012-06-04 10:54:48 +00:00
Maxim Dounin 333be9fe57 Merge of r4615: write handler reset in ngx_http_named_location().
On internal redirects this happens via ngx_http_handler() call, which is
not called on named location redirect.  As a result incorrect write handler
remained (if previously set) and this might cause incorrect behaviour (likely
request hang).

Patch by Yichun Zhang (agentzh).
2012-06-04 10:52:43 +00:00
Maxim Dounin 75dbcedba1 Merge of r4613: removed surplus condition. 2012-06-04 10:33:38 +00:00
Maxim Dounin 65107cfd1c Merge of r4612: proper subrequest handling in various modules. 2012-06-04 10:27:00 +00:00
Maxim Dounin 87b4323b47 Merge of r4611, r4620: resolver fixes.
*) Fixed segmentation fault in ngx_resolver_create_name_query().

   If name passed for resolution was { 0, NULL } (e.g. as a result
   of name server returning CNAME pointing to ".") pointer wrapped
   to (void *) -1 resulting in segmentation fault on an attempt to
   dereference it.

   Reported by Lanshun Zhou.

*) Resolver: protection from duplicate responses.

   If we already had CNAME in resolver node (i.e. rn->cnlen and rn->u.cname
   set), and got additional response with A record, it resulted in rn->cnlen
   set and rn->u.cname overwritten by rn->u.addr (or rn->u.addrs), causing
   segmentation fault later in ngx_resolver_free_node() on an attempt to free
   overwritten rn->u.cname.  The opposite (i.e. CNAME got after A) might cause
   similar problems as well.
2012-06-04 10:15:55 +00:00
Maxim Dounin 0af9b00afa Version bump. 2012-06-04 10:00:39 +00:00
Maxim Dounin 68e599aca7 stable-1.2 branch 2012-04-26 11:18:21 +00:00
145 changed files with 4965 additions and 1527 deletions

98
auto/cc/clang Normal file
View File

@ -0,0 +1,98 @@
# Copyright (C) Nginx, Inc.
# clang
NGX_CLANG_VER=`$CC -v 2>&1 | grep 'clang version' 2>&1 \
| sed -e 's/^.*clang version \(.*\)/\1/'`
echo " + clang version: $NGX_CLANG_VER"
have=NGX_COMPILER value="\"clang $NGX_CLANG_VER\"" . auto/define
CC_TEST_FLAGS="-pipe"
# optimizations
#NGX_CLANG_OPT="-O2"
#NGX_CLANG_OPT="-Oz"
NGX_CLANG_OPT="-O"
case $CPU in
pentium)
# optimize for Pentium
CPU_OPT="-march=pentium"
NGX_CPU_CACHE_LINE=32
;;
pentiumpro | pentium3)
# optimize for Pentium Pro, Pentium II and Pentium III
CPU_OPT="-march=pentiumpro"
NGX_CPU_CACHE_LINE=32
;;
pentium4)
# optimize for Pentium 4
CPU_OPT="-march=pentium4"
NGX_CPU_CACHE_LINE=128
;;
athlon)
# optimize for Athlon
CPU_OPT="-march=athlon"
NGX_CPU_CACHE_LINE=64
;;
opteron)
# optimize for Opteron
CPU_OPT="-march=opteron"
NGX_CPU_CACHE_LINE=64
;;
esac
CC_AUX_FLAGS="$CC_AUX_FLAGS $CPU_OPT"
CFLAGS="$CFLAGS -pipe $CPU_OPT"
if [ ".$PCRE_OPT" = "." ]; then
PCRE_OPT="-O2 -pipe $CPU_OPT"
else
PCRE_OPT="$PCRE_OPT -pipe"
fi
if [ ".$MD5_OPT" = "." ]; then
MD5_OPT="-O2 -pipe $CPU_OPT"
else
MD5_OPT="$MD5_OPT -pipe"
fi
if [ ".$ZLIB_OPT" = "." ]; then
ZLIB_OPT="-O2 -pipe $CPU_OPT"
else
ZLIB_OPT="$ZLIB_OPT -pipe"
fi
# warnings
CFLAGS="$CFLAGS $NGX_CLANG_OPT -Wall -Wextra -Wpointer-arith"
#CFLAGS="$CFLAGS -Wmissing-prototypes"
# we have a lot of unused function arguments
CFLAGS="$CFLAGS -Wno-unused-parameter"
# stop on warning
#CFLAGS="$CFLAGS -Werror"
# debug
CFLAGS="$CFLAGS -g"
if [ ".$CPP" = "." ]; then
CPP="$CC -E"
fi

View File

@ -56,6 +56,12 @@ else
. auto/cc/gcc
;;
clang)
# Clang C compiler
. auto/cc/clang
;;
icc)
# Intel C++ compiler 7.1, 8.0, 8.1

View File

@ -149,15 +149,13 @@ CFLAGS="$CFLAGS ${NGX_GCC_OPT:--O} -W"
CFLAGS="$CFLAGS -Wall -Wpointer-arith"
#CFLAGS="$CFLAGS -Wconversion"
#CFLAGS="$CFLAGS -Winline"
#CFLAGS="$CFLAGS -Wmissing-prototypes"
case "$NGX_GCC_VER" in
3.* | 4.* )
# we have a lot of the unused function arguments
CFLAGS="$CFLAGS -Wno-unused-parameter"
CFLAGS="$CFLAGS -Wunused-function"
CFLAGS="$CFLAGS -Wunused-variable"
CFLAGS="$CFLAGS -Wunused-value"
# 4.2.1 shows the warning in wrong places
#CFLAGS="$CFLAGS -Wunreachable-code"
;;

View File

@ -73,9 +73,6 @@ CFLAGS="$CFLAGS -WX"
# disable logo
CFLAGS="$CFLAGS -nologo"
LINK="\$(CC)"
# the link flags
CORE_LINK="$CORE_LINK -link -verbose:lib"

View File

@ -32,14 +32,14 @@ if [ "$CC" = cl ]; then
NGX_CC_NAME=msvc10
echo " + using Microsoft Visual C++ 10 compiler"
else if `$NGX_WINE $CC -v 2>&1 \
elif `$NGX_WINE $CC -v 2>&1 \
| grep '^Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14' \
>/dev/null 2>&1`; then
NGX_CC_NAME=msvc8
echo " + using Microsoft Visual C++ 8 compiler"
else if `$NGX_WINE $CC -v 2>&1 \
elif `$NGX_WINE $CC -v 2>&1 \
| grep '^Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13' \
>/dev/null 2>&1`; then
@ -50,52 +50,40 @@ if [ "$CC" = cl ]; then
NGX_CC_NAME=msvc
echo " + using Microsoft Visual C++ compiler"
fi
fi
fi
else
if [ "$CC" = wcl386 ]; then
elif [ "$CC" = wcl386 ]; then
NGX_CC_NAME=owc
echo " + using Open Watcom C compiler"
else
if [ "$CC" = bcc32 ]; then
elif [ "$CC" = bcc32 ]; then
NGX_CC_NAME=bcc
echo " + using Borland C++ compiler"
else
if `$CC -V 2>&1 | grep '^Intel(R) C' >/dev/null 2>&1`; then
elif `$CC -V 2>&1 | grep '^Intel(R) C' >/dev/null 2>&1`; then
NGX_CC_NAME=icc
echo " + using Intel C++ compiler"
else
if `$CC -v 2>&1 | grep 'gcc version' >/dev/null 2>&1`; then
elif `$CC -v 2>&1 | grep 'gcc version' >/dev/null 2>&1`; then
NGX_CC_NAME=gcc
echo " + using GNU C compiler"
else
if `$CC -V 2>&1 | grep 'Sun C' >/dev/null 2>&1`; then
elif `$CC -v 2>&1 | grep 'clang version' >/dev/null 2>&1`; then
NGX_CC_NAME=clang
echo " + using Clang C compiler"
elif `$CC -V 2>&1 | grep 'Sun C' >/dev/null 2>&1`; then
NGX_CC_NAME=sunc
echo " + using Sun C compiler"
else
if `$CC -V 2>&1 | grep '^Compaq C' >/dev/null 2>&1`; then
elif `$CC -V 2>&1 | grep '^Compaq C' >/dev/null 2>&1`; then
NGX_CC_NAME=ccc
echo " + using Compaq C compiler"
else
if `$CC -V 2>&1 | grep '^aCC: ' >/dev/null 2>&1`; then
elif `$CC -V 2>&1 | grep '^aCC: ' >/dev/null 2>&1`; then
NGX_CC_NAME=acc
echo " + using HP aC++ compiler"
else
NGX_CC_NAME=unknown
fi # acc
fi # ccc
fi # sunc
fi # icc
fi # gcc
fi # bcc
fi # owc
fi # msvc
fi

3
auto/configure vendored
View File

@ -4,6 +4,9 @@
# Copyright (C) Nginx, Inc.
LC_ALL=C
export LC_ALL
. auto/options
. auto/init
. auto/sources

View File

@ -3,9 +3,9 @@
# Copyright (C) Nginx, Inc.
echo $ngx_n "checking for system endianess ...$ngx_c"
echo $ngx_n "checking for system byte ordering ...$ngx_c"
echo >> $NGX_ERR
echo "checking for system endianess" >> $NGX_ERR
echo "checking for system byte ordering" >> $NGX_ERR
cat << END > $NGX_AUTOTEST.c
@ -28,10 +28,10 @@ eval "$ngx_test >> $NGX_AUTOCONF_ERR 2>&1"
if [ -x $NGX_AUTOTEST ]; then
if $NGX_AUTOTEST >/dev/null 2>&1; then
echo " little endianess"
echo " little endian"
have=NGX_HAVE_LITTLE_ENDIAN . auto/have
else
echo " big endianess"
echo " big endian"
fi
rm $NGX_AUTOTEST*
@ -40,6 +40,6 @@ else
rm $NGX_AUTOTEST*
echo
echo "$0: error: can not detect system endianess"
echo "$0: error: cannot detect system byte ordering"
exit 1
fi

View File

@ -8,7 +8,7 @@ if [ $USE_PERL = YES ]; then
cat << END >> $NGX_MAKEFILE
install_perl_modules:
cd $NGX_OBJS/src/http/modules/perl && make install
cd $NGX_OBJS/src/http/modules/perl && \$(MAKE) install
END
NGX_INSTALL_PERL_MODULES=install_perl_modules

View File

@ -6,7 +6,7 @@
ngx_feature="GeoIP library"
ngx_feature_name=
ngx_feature_run=no
ngx_feature_incs=
ngx_feature_incs="#include <GeoIP.h>"
ngx_feature_path=
ngx_feature_libs="-lGeoIP"
ngx_feature_test="GeoIP_open(NULL, 0)"
@ -18,6 +18,7 @@ if [ $ngx_found = no ]; then
# FreeBSD port
ngx_feature="GeoIP 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 -lGeoIP"
@ -34,7 +35,7 @@ if [ $ngx_found = no ]; then
# NetBSD port
ngx_feature="GeoIP library in /usr/pkg/"
ngx_feature_path="/usr/pkg/include/"
ngx_feature_path="/usr/pkg/include"
if [ $NGX_RPATH = YES ]; then
ngx_feature_libs="-R/usr/pkg/lib -L/usr/pkg/lib -lGeoIP"
@ -64,8 +65,22 @@ fi
if [ $ngx_found = yes ]; then
CORE_INCS="$CORE_INCS $ngx_feature_path"
CORE_LIBS="$CORE_LIBS $ngx_feature_libs"
if [ $NGX_IPV6 = YES ]; then
ngx_feature="GeoIP IPv6 support"
ngx_feature_name="NGX_HAVE_GEOIP_V6"
ngx_feature_run=no
ngx_feature_incs="#include <stdio.h>
#include <GeoIP.h>"
#ngx_feature_path=
#ngx_feature_libs=
ngx_feature_test="printf(\"%d\", GEOIP_CITY_EDITION_REV0_V6);"
. auto/feature
fi
else
cat << END

View File

@ -29,6 +29,22 @@ if [ $ngx_found = no ]; then
fi
if [ $ngx_found = no ]; then
# MacPorts
ngx_feature="Google perftools in /opt/local/"
if [ $NGX_RPATH = YES ]; then
ngx_feature_libs="-R/opt/local/lib -L/opt/local/lib -lprofiler"
else
ngx_feature_libs="-L/opt/local/lib -lprofiler"
fi
. auto/feature
fi
if [ $ngx_found = yes ]; then
CORE_LIBS="$CORE_LIBS $ngx_feature_libs"

View File

@ -6,7 +6,7 @@
cat << END >> $NGX_MAKEFILE
$NGX_LIBATOMIC/src/libatomic_ops.a: $NGX_LIBATOMIC/Makefile
cd $NGX_LIBATOMIC && make
cd $NGX_LIBATOMIC && \$(MAKE)
$NGX_LIBATOMIC/Makefile: $NGX_MAKEFILE
cd $NGX_LIBATOMIC && ./configure

View File

@ -35,7 +35,7 @@ if [ $ngx_found = no ]; then
# NetBSD port
ngx_feature="GD library in /usr/pkg/"
ngx_feature_path="/usr/pkg/include/"
ngx_feature_path="/usr/pkg/include"
if [ $NGX_RPATH = YES ]; then
ngx_feature_libs="-R/usr/pkg/lib -L/usr/pkg/lib -lgd"

View File

@ -172,6 +172,7 @@ else
ngx_feature="PCRE JIT support"
ngx_feature_name="NGX_HAVE_PCRE_JIT"
ngx_feature_test="int jit = 0;
pcre_free_study(NULL);
pcre_config(PCRE_CONFIG_JIT, &jit);
if (jit != 1) return 1;"
. auto/feature

View File

@ -12,7 +12,7 @@ NGX_PERL_VER=`$NGX_PERL -v 2>&1 | grep '^This is perl' 2>&1 \
if test -n "$NGX_PERL_VER"; then
echo " + perl version: $NGX_PERL_VER"
if [ "`echo 'use 5.006001; print "OK"' | $NGX_PERL 2>&1`" != OK ]; then
if [ "`$NGX_PERL -e 'use 5.006001; print "OK"'`" != "OK" ]; then
echo
echo "$0: error: perl 5.6.1 or higher is required"
echo
@ -20,6 +20,14 @@ if test -n "$NGX_PERL_VER"; then
exit 1;
fi
if [ "`$NGX_PERL -MExtUtils::Embed -e 'print "OK"'`" != "OK" ]; then
echo
echo "$0: error: perl module ExtUtils::Embed is required"
echo
exit 1;
fi
NGX_PERL_CFLAGS="$CFLAGS `$NGX_PERL -MExtUtils::Embed -e ccopts`"
NGX_PM_CFLAGS=`$NGX_PERL -MExtUtils::Embed -e ccopts`

View File

@ -6,13 +6,14 @@
cat << END >> $NGX_MAKEFILE
$NGX_OBJS/src/http/modules/perl/blib/arch/auto/nginx/nginx.so: \
\$(CORE_DEPS) \$(HTTP_DEPS) \
src/http/modules/perl/nginx.pm \
src/http/modules/perl/nginx.xs \
src/http/modules/perl/ngx_http_perl_module.h \
$NGX_OBJS/src/http/modules/perl/Makefile
cp -p src/http/modules/perl/nginx.* $NGX_OBJS/src/http/modules/perl/
cp src/http/modules/perl/nginx.* $NGX_OBJS/src/http/modules/perl/
cd $NGX_OBJS/src/http/modules/perl && make
cd $NGX_OBJS/src/http/modules/perl && \$(MAKE)
rm -rf $NGX_OBJS/install_perl
@ -26,9 +27,7 @@ $NGX_OBJS/src/http/modules/perl/Makefile: \
cd $NGX_OBJS/src/http/modules/perl \
&& NGX_PM_CFLAGS="\$(NGX_PM_CFLAGS) -g $NGX_CC_OPT" \
NGX_PCRE=$PCRE \
NGX_OBJS=$NGX_OBJS \
NGX_OPENSSL=$OPENSSL \
NGX_INCS="$CORE_INCS $NGX_OBJS $HTTP_INCS" \
$NGX_PERL Makefile.PL \
LIB=$NGX_PERL_MODULES \
INSTALLSITEMAN3DIR=$NGX_PERL_MODULES_MAN

View File

@ -9,11 +9,13 @@ if [ $ZLIB != NONE ]; then
case "$NGX_CC_NAME" in
msvc* | owc* | bcc)
have=NGX_ZLIB . auto/have
LINK_DEPS="$LINK_DEPS $ZLIB/zlib.lib"
CORE_LIBS="$CORE_LIBS $ZLIB/zlib.lib"
;;
icc*)
have=NGX_ZLIB . auto/have
LINK_DEPS="$LINK_DEPS $ZLIB/libz.a"
# to allow -ipo optimization we link with the *.o but not library
@ -30,6 +32,7 @@ if [ $ZLIB != NONE ]; then
;;
*)
have=NGX_ZLIB . auto/have
LINK_DEPS="$LINK_DEPS $ZLIB/libz.a"
CORE_LIBS="$CORE_LIBS $ZLIB/libz.a"
#CORE_LIBS="$CORE_LIBS -L $ZLIB -lz"
@ -45,7 +48,7 @@ else
# FreeBSD, Solaris, Linux
ngx_feature="zlib library"
ngx_feature_name=
ngx_feature_name="NGX_ZLIB"
ngx_feature_run=no
ngx_feature_incs="#include <zlib.h>"
ngx_feature_path=

View File

@ -8,8 +8,10 @@ CFLAGS = -q -O2 -tWM -w-8004 -w-8012 $(CPU_OPT)
zlib.lib:
cd $(ZLIB)
bcc32 -c $(CFLAGS) adler32.c crc32.c deflate.c trees.c zutil.c \
compress.c
bcc32 -c $(CFLAGS) adler32.c crc32.c deflate.c \
trees.c zutil.c compress.c \
inflate.c inffast.c inftrees.c
tlib zlib.lib +adler32.obj +crc32.obj +deflate.obj \
+trees.obj +zutil.obj +compress.obj
+trees.obj +zutil.obj +compress.obj \
+inflate.obj +inffast.obj +inftrees.obj

View File

@ -8,7 +8,10 @@ CFLAGS = -nologo -O2 -Ob1 -Oi -Gs $(LIBC) $(CPU_OPT)
zlib.lib:
cd $(ZLIB)
cl -c $(CFLAGS) adler32.c crc32.c deflate.c trees.c zutil.c compress.c
cl -c $(CFLAGS) adler32.c crc32.c deflate.c \
trees.c zutil.c compress.c \
inflate.c inffast.c inftrees.c
link -lib -out:zlib.lib adler32.obj crc32.obj deflate.obj \
trees.obj zutil.obj compress.obj
trees.obj zutil.obj compress.obj \
inflate.obj inffast.obj inftrees.obj

View File

@ -9,6 +9,6 @@ zlib.lib:
cd $(ZLIB)
wcl386 -c $(CFLAGS) adler32.c crc32.c deflate.c trees.c zutil.c &
compress.c
compress.c inflate.c inffast.c inftrees.c
wlib -n zlib.lib adler32.obj crc32.obj deflate.obj trees.obj &
zutil.obj compress.obj
zutil.obj compress.obj inflate.obj inffast.obj inftrees.obj

View File

@ -49,7 +49,7 @@ END
ngx_all_srcs="$CORE_SRCS"
# the core dependences and include pathes
# the core dependences and include paths
ngx_deps=`echo $CORE_DEPS $NGX_AUTO_CONFIG_H $NGX_PCH \
| sed -e "s/ *\([^ ][^ ]*\)/$ngx_regex_cont\1/g" \
@ -69,7 +69,7 @@ CORE_INCS = $ngx_include_opt$ngx_incs
END
# the http dependences and include pathes
# the http dependences and include paths
if [ $HTTP = YES ]; then
@ -95,7 +95,7 @@ END
fi
# the mail dependences and include pathes
# the mail dependences and include paths
if [ $MAIL = YES ]; then

View File

@ -223,6 +223,7 @@ fi
if [ $HTTP_REALIP = YES ]; then
have=NGX_HTTP_REALIP . auto/have
have=NGX_HTTP_X_FORWARDED_FOR . auto/have
HTTP_MODULES="$HTTP_MODULES $HTTP_REALIP_MODULE"
HTTP_SRCS="$HTTP_SRCS $HTTP_REALIP_SRCS"
fi
@ -234,11 +235,13 @@ fi
if [ $HTTP_GEO = YES ]; then
have=NGX_HTTP_GEO . auto/have
have=NGX_HTTP_X_FORWARDED_FOR . auto/have
HTTP_MODULES="$HTTP_MODULES $HTTP_GEO_MODULE"
HTTP_SRCS="$HTTP_SRCS $HTTP_GEO_SRCS"
fi
if [ $HTTP_GEOIP = YES ]; then
have=NGX_HTTP_X_FORWARDED_FOR . auto/have
HTTP_MODULES="$HTTP_MODULES $HTTP_GEOIP_MODULE"
HTTP_SRCS="$HTTP_SRCS $HTTP_GEOIP_SRCS"
fi
@ -274,6 +277,7 @@ fi
if [ $HTTP_PROXY = YES ]; then
have=NGX_HTTP_PROXY . auto/have
have=NGX_HTTP_X_FORWARDED_FOR . auto/have
#USE_MD5=YES
HTTP_MODULES="$HTTP_MODULES $HTTP_PROXY_MODULE"
HTTP_DEPS="$HTTP_DEPS $HTTP_PROXY_DEPS"
@ -345,6 +349,11 @@ if [ $HTTP_UPSTREAM_IP_HASH = YES ]; then
HTTP_SRCS="$HTTP_SRCS $HTTP_UPSTREAM_IP_HASH_SRCS"
fi
if [ $HTTP_UPSTREAM_LEAST_CONN = YES ]; then
HTTP_MODULES="$HTTP_MODULES $HTTP_UPSTREAM_LEAST_CONN_MODULE"
HTTP_SRCS="$HTTP_SRCS $HTTP_UPSTREAM_LEAST_CONN_SRCS"
fi
if [ $HTTP_UPSTREAM_KEEPALIVE = YES ]; then
HTTP_MODULES="$HTTP_MODULES $HTTP_UPSTREAM_KEEPALIVE_MODULE"
HTTP_SRCS="$HTTP_SRCS $HTTP_UPSTREAM_KEEPALIVE_SRCS"
@ -458,6 +467,7 @@ fi
if [ $NGX_CPP_TEST = YES ]; then
NGX_MISC_SRCS="$NGX_MISC_SRCS $NGX_CPP_TEST_SRCS"
CORE_LIBS="$CORE_LIBS -lstdc++"
fi

View File

@ -96,6 +96,7 @@ HTTP_FLV=NO
HTTP_MP4=NO
HTTP_GZIP_STATIC=NO
HTTP_UPSTREAM_IP_HASH=YES
HTTP_UPSTREAM_LEAST_CONN=YES
HTTP_UPSTREAM_KEEPALIVE=YES
# STUB
@ -243,6 +244,8 @@ use the \"--without-http_limit_conn_module\" option instead"
--without-http_empty_gif_module) HTTP_EMPTY_GIF=NO ;;
--without-http_browser_module) HTTP_BROWSER=NO ;;
--without-http_upstream_ip_hash_module) HTTP_UPSTREAM_IP_HASH=NO ;;
--without-http_upstream_least_conn_module)
HTTP_UPSTREAM_LEAST_CONN=NO ;;
--without-http_upstream_keepalive_module) HTTP_UPSTREAM_KEEPALIVE=NO ;;
--with-http_perl_module) HTTP_PERL=YES ;;
@ -382,6 +385,10 @@ cat << END
--without-http_browser_module disable ngx_http_browser_module
--without-http_upstream_ip_hash_module
disable ngx_http_upstream_ip_hash_module
--without-http_upstream_least_conn_module
disable ngx_http_upstream_least_conn_module
--without-http_upstream_keepalive_module
disable ngx_http_upstream_keepalive_module
--with-http_perl_module enable ngx_http_perl_module
--with-perl_modules_path=PATH set Perl modules path

View File

@ -48,6 +48,7 @@ case "$NGX_PLATFORM" in
CORE_DEPS="$UNIX_DEPS $POSIX_DEPS"
CORE_SRCS="$UNIX_SRCS"
CC_AUX_FLAGS="$CC_AUX_FLAGS -D_XOPEN_SOURCE -D_XOPEN_SOURCE_EXTENDED=1"
CC_AUX_FLAGS="$CC_AUX_FLAGS -D_HPUX_ALT_XOPEN_SOCKET_API"
;;
OSF1:*)
@ -93,6 +94,7 @@ case "$NGX_MACHINE" in
;;
*)
have=NGX_ALIGNMENT value=16 . auto/define
NGX_MACH_CACHE_LINE=32
;;

View File

@ -479,6 +479,11 @@ HTTP_UPSTREAM_IP_HASH_MODULE=ngx_http_upstream_ip_hash_module
HTTP_UPSTREAM_IP_HASH_SRCS=src/http/modules/ngx_http_upstream_ip_hash_module.c
HTTP_UPSTREAM_LEAST_CONN_MODULE=ngx_http_upstream_least_conn_module
HTTP_UPSTREAM_LEAST_CONN_SRCS=" \
src/http/modules/ngx_http_upstream_least_conn_module.c"
HTTP_UPSTREAM_KEEPALIVE_MODULE=ngx_http_upstream_keepalive_module
HTTP_UPSTREAM_KEEPALIVE_SRCS=" \
src/http/modules/ngx_http_upstream_keepalive_module.c"

View File

@ -464,7 +464,7 @@ ngx_type="rlim_t"; ngx_types="int"; . auto/types/typedef
. auto/types/uintptr_t
. auto/endianess
. auto/endianness
ngx_type="size_t"; . auto/types/sizeof
ngx_param=NGX_MAX_SIZE_T_VALUE; ngx_value=$ngx_max_value; . auto/types/value

View File

@ -5,24 +5,6 @@ NGINX= nginx-$(VER)
TEMP= tmp
CP= $(HOME)/java
define XSLScript
java -cp $(CP)/xsls/saxon.jar:$(CP)/xsls/xsls.jar \
com.pault.StyleSheet \
-x com.pault.XX -y com.pault.XX \
$(1) docs/xsls/dump.xsls \
| sed 's/ *$$//;/^ *$$/N;/\n *$$/D' > $(2)
if [ ! -s $(2) ]; then rm $(2); fi; test -s $(2)
endef
define XSLT
xmllint --noout --valid $2
xsltproc -o $3 \
$(shell echo $4 \\
| sed -e "s/\([^= ]*\)=\([^= ]*\)/--param \1 \"'\2'\"/g") \
$1 $2
endef
all: changes
@ -30,28 +12,36 @@ changes: $(TEMP)/$(NGINX)/CHANGES.ru \
$(TEMP)/$(NGINX)/CHANGES
$(TEMP)/$(NGINX)/CHANGES.ru: docs/xml/nginx/changes.xml \
$(TEMP)/$(NGINX)/CHANGES.ru: docs/dtd/changes.dtd \
docs/xml/nginx/changes.xml \
docs/xml/change_log_conf.xml \
docs/xslt/changes.xslt
test -d $(TEMP)/$(NGINX) || mkdir -p $(TEMP)/$(NGINX)
mkdir -p $(TEMP)/$(NGINX)
xmllint --noout --valid docs/xml/nginx/changes.xml
xsltproc --stringparam lang ru \
-o $(TEMP)/$(NGINX)/CHANGES.ru \
docs/xslt/changes.xslt docs/xml/nginx/changes.xml
-o $@ docs/xslt/changes.xslt docs/xml/nginx/changes.xml
$(TEMP)/$(NGINX)/CHANGES: docs/xml/nginx/changes.xml \
$(TEMP)/$(NGINX)/CHANGES: docs/dtd/changes.dtd \
docs/xml/nginx/changes.xml \
docs/xml/change_log_conf.xml \
docs/xslt/changes.xslt
test -d $(TEMP)/$(NGINX) || mkdir -p $(TEMP)/$(NGINX)
mkdir -p $(TEMP)/$(NGINX)
xmllint --noout --valid docs/xml/nginx/changes.xml
xsltproc --stringparam lang en \
-o $(TEMP)/$(NGINX)/CHANGES \
docs/xslt/changes.xslt docs/xml/nginx/changes.xml
-o $@ docs/xslt/changes.xslt docs/xml/nginx/changes.xml
docs/xslt/changes.xslt: docs/xsls/changes.xsls
docs/xslt/changes.xslt: docs/xsls/changes.xsls docs/xsls/dump.xsls
$(call XSLScript, docs/xsls/changes.xsls, $@)
java -cp $(CP)/xsls/saxon.jar:$(CP)/xsls/xsls.jar \
com.pault.StyleSheet \
-x com.pault.XX -y com.pault.XX \
$< docs/xsls/dump.xsls \
| sed 's/ *$$//;/^ *$$/N;/\n *$$/D' > $@
if [ ! -s $@ ]; then rm $@; fi; test -s $@

View File

@ -12,10 +12,10 @@
>
<!ELEMENT change (para)* >
<!ATTLIST change type (bugfix | feature | change | workaround) #IMPLIED >
<!ATTLIST change type (bugfix | feature | change | security | workaround) #IMPLIED >
<!ELEMENT para (#PCDATA | at | br | nobr)* >
<!ATTLIST para lang (ru | en) #IMPLIED >
<!ATTLIST para lang (ru | en) #REQUIRED >
<!ELEMENT at EMPTY >
<!ELEMENT br EMPTY >

View File

@ -1,18 +1,21 @@
<!DOCTYPE html>
<html>
<head>
<title>The page is temporarily unavailable</title>
<title>Error</title>
<style>
body { font-family: Tahoma, Verdana, Arial, sans-serif; }
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body bgcolor="white" text="black">
<table width="100%" height="100%">
<tr>
<td align="center" valign="middle">
The page you are looking for is temporarily unavailable.<br/>
Please try again later.
</td>
</tr>
</table>
<body>
<h1>An error occurred.</h1>
<p>Sorry, the page you are looking for is currently unavailable.<br/>
Please try again later.</p>
<p>If you are the system administrator of this resource then you should check
the <a href="http://nginx.org/r/error_log">error log</a> for details.</p>
<p><em>Faithfully yours, nginx.</em></p>
</body>
</html>

View File

@ -1,8 +1,25 @@
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body bgcolor="white" text="black">
<center><h1>Welcome to nginx!</h1></center>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>

View File

@ -1,6 +1,6 @@
.\"
.\" Copyright (c) 2010 Sergey A. Osokin
.\" Copyright (c) 2011,2012 Nginx, Inc.
.\" Copyright (C) 2010 Sergey A. Osokin
.\" Copyright (C) Nginx, Inc.
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without

View File

@ -1,6 +1,7 @@
/*
* Copyright (C) 2002-2012 Igor Sysoev
* Copyright (C) 2011,2012 Nginx, Inc.
* Copyright (C) 2002-2013 Igor Sysoev
* Copyright (C) 2011-2013 Nginx, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -11,10 +12,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)

View File

@ -2,11 +2,965 @@
<!DOCTYPE change_log SYSTEM "../../dtd/changes.dtd" >
<change_log link="/nginx/changes.html" path="/nginx/" root=".."
title="nginx">
<change_log title="nginx">
<title lang="ru">Изменения в nginx</title>
<title lang="en">nginx changelog</title>
<changes ver="1.2.9" date="13.05.2013">
<change type="security">
<para lang="ru">
содержимое памяти рабочего процесса могло быть отправлено клиенту,
если HTTP-бэкенд возвращал специально созданный ответ (CVE-2013-2070);
ошибка появилась в 1.1.4.
</para>
<para lang="en">
contents of worker process memory might be sent to a client
if HTTP backend returned specially crafted response (CVE-2013-2070);
the bug had appeared in 1.1.4.
</para>
</change>
</changes>
<changes ver="1.2.8" date="02.04.2013">
<change type="bugfix">
<para lang="ru">
при использовании директивы "ssl_session_cache shared"
новые сессии могли не сохраняться,
если заканчивалось место в разделяемой памяти.<br/>
Спасибо Piotr Sikora.
</para>
<para lang="en">
new sessions were not always stored
if the "ssl_session_cache shared" directive was used
and there was no free space in shared memory.<br/>
Thanks to Piotr Sikora.
</para>
</change>
<change type="bugfix">
<para lang="ru">
ответы могли зависать,
если использовались подзапросы
и при обработке подзапроса происходила DNS-ошибка.<br/>
Спасибо Lanshun Zhou.
</para>
<para lang="en">
responses might hang
if subrequests were used
and a DNS error happened during subrequest processing.<br/>
Thanks to Lanshun Zhou.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в модуле ngx_http_mp4_module.<br/>
Спасибо Gernot Vormayr.
</para>
<para lang="en">
in the ngx_http_mp4_module.<br/>
Thanks to Gernot Vormayr.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в процедуре учёта использования бэкендов.
</para>
<para lang="en">
in backend usage accounting.
</para>
</change>
</changes>
<changes ver="1.2.7" date="12.02.2013">
<change type="change">
<para lang="ru">
теперь при использовании директивы include с маской на Unix-системах
включаемые файлы сортируются в алфавитном порядке.
</para>
<para lang="en">
now if the "include" directive with mask is used on Unix systems,
included files are sorted in alphabetical order.
</para>
</change>
<change type="change">
<para lang="ru">
директива add_header добавляет строки в ответы с кодом 201.
</para>
<para lang="en">
the "add_header" directive adds headers to 201 responses.
</para>
</change>
<change type="feature">
<para lang="ru">
директива geo теперь поддерживает IPv6 адреса в формате CIDR.
</para>
<para lang="en">
the "geo" directive now supports IPv6 addresses in CIDR notation.
</para>
</change>
<change type="feature">
<para lang="ru">
параметры flush и gzip в директиве access_log.
</para>
<para lang="en">
the "flush" and "gzip" parameters of the "access_log" directive.
</para>
</change>
<change type="feature">
<para lang="ru">
директива auth_basic поддерживает переменные.
</para>
<para lang="en">
variables support in the "auth_basic" directive.
</para>
</change>
<change type="feature">
<para lang="ru">
переменные $pipe, $request_length, $time_iso8601 и $time_local
теперь можно использовать не только в директиве log_format.<br/>
Спасибо Kiril Kalchev.
</para>
<para lang="en">
the $pipe, $request_length, $time_iso8601, and $time_local variables
can now be used not only in the "log_format" directive.
Thanks to Kiril Kalchev.
</para>
</change>
<change type="feature">
<para lang="ru">
поддержка IPv6 в модуле ngx_http_geoip_module.<br/>
Спасибо Gregor Kališnik.
</para>
<para lang="en">
IPv6 support in the ngx_http_geoip_module.<br/>
Thanks to Gregor Kališnik.
</para>
</change>
<change type="bugfix">
<para lang="ru">
nginx в некоторых случаях не собирался с модулем ngx_http_perl_module.
</para>
<para lang="en">
nginx could not be built with the ngx_http_perl_module in some cases.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в рабочем процессе мог произойти segmentation fault,
если использовался модуль ngx_http_xslt_module.
</para>
<para lang="en">
a segmentation fault might occur in a worker process
if the ngx_http_xslt_module was used.
</para>
</change>
<change type="bugfix">
<para lang="ru">
nginx мог не собираться на MacOSX.<br/>
Спасибо Piotr Sikora.
</para>
<para lang="en">
nginx could not be built on MacOSX in some cases.<br/>
Thanks to Piotr Sikora.
</para>
</change>
<change type="bugfix">
<para lang="ru">
при использовании директивы limit_rate с большими значениями скорости
на 32-битных системах ответ мог возвращаться не целиком.<br/>
Спасибо Алексею Антропову.
</para>
<para lang="en">
the "limit_rate" directive with high rates
might result in truncated responses on 32-bit platforms.<br/>
Thanks to Alexey Antropov.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в рабочем процессе мог произойти segmentation fault,
если использовалась директива if.<br/>
Спасибо Piotr Sikora.
</para>
<para lang="en">
a segmentation fault might occur in a worker process
if the "if" directive was used.<br/>
Thanks to Piotr Sikora.
</para>
</change>
<change type="bugfix">
<para lang="ru">
ответ "100 Continue" выдавался
вместе с ответом "413 Request Entity Too Large".
</para>
<para lang="en">
a "100 Continue" response was issued
with "413 Request Entity Too Large" responses.
</para>
</change>
<change type="bugfix">
<para lang="ru">
директивы image_filter, image_filter_jpeg_quality и image_filter_sharpen
могли наследоваться некорректно.<br/>
Спасибо Ивану Боброву.
</para>
<para lang="en">
the "image_filter", "image_filter_jpeg_quality"
and "image_filter_sharpen" directives
might be inherited incorrectly.<br/>
Thanks to Ian Babrou.
</para>
</change>
<change type="bugfix">
<para lang="ru">
при использовании директивы auth_basic под Linux
могли возникать ошибки "crypt_r() failed".
</para>
<para lang="en">
"crypt_r() failed" errors might appear
if the "auth_basic" directive was used on Linux.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в обработке backup-серверов.<br/>
Спасибо Thomas Chen.
</para>
<para lang="en">
in backup servers handling.<br/>
Thanks to Thomas Chen.
</para>
</change>
<change type="bugfix">
<para lang="ru">
при проксировании HEAD-запросов мог возвращаться некорректный ответ,
если использовалась директива gzip.
</para>
<para lang="en">
proxied HEAD requests might return incorrect response
if the "gzip" directive was used.
</para>
</change>
<change type="bugfix">
<para lang="ru">
на старте или во время переконфигурации происходил segmentation fault,
если директива keepalive была указана несколько раз
в одном блоке upstream.
</para>
<para lang="en">
a segmentation fault occurred on start or during reconfiguration
if the "keepalive" directive was specified more than once
in a single upstream block.
</para>
</change>
<change type="bugfix">
<para lang="ru">
директива proxy_method работала неверно, если была указана на уровне http.
</para>
<para lang="en">
in the "proxy_method" directive.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в рабочем процессе мог произойти segmentation fault,
если использовался resolver и метод poll.
</para>
<para lang="en">
a segmentation fault might occur in a worker process
if resolver was used with the poll method.
</para>
</change>
<change type="bugfix">
<para lang="ru">
nginx мог нагружать процессор во время SSL handshake с бэкендом
при использовании методов обработки соединений select, poll и /dev/poll.
</para>
<para lang="en">
nginx might hog CPU during SSL handshake with a backend
if the select, poll, or /dev/poll methods were used.
</para>
</change>
<change type="bugfix">
<para lang="ru">
ошибка "[crit] SSL_write() failed (SSL:)".
</para>
<para lang="en">
the "[crit] SSL_write() failed (SSL:)" error.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в директиве fastcgi_keep_conn.
</para>
<para lang="en">
in the "fastcgi_keep_conn" directive.
</para>
</change>
</changes>
<changes ver="1.2.6" date="11.12.2012">
<change type="feature">
<para lang="ru">
переменные $request_time и $msec
теперь можно использовать не только в директиве log_format.
</para>
<para lang="en">
the $request_time and $msec variables
can now be used not only in the "log_format" directive.
</para>
</change>
<change type="bugfix">
<para lang="ru">
cache manager и cache loader могли не запускаться,
если использовалось более 512 listen-сокетов.
</para>
<para lang="en">
cache manager and cache loader processes might not be able to start
if more than 512 listen sockets were used.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в модуле ngx_http_dav_module.
</para>
<para lang="en">
in the ngx_http_dav_module.
</para>
</change>
</changes>
<changes ver="1.2.5" date="13.11.2012">
<change type="feature">
<para lang="ru">
параметр optional_no_ca директивы ssl_verify_client.<br/>
Спасибо Михаилу Казанцеву и Eric O'Connor.
</para>
<para lang="en">
the "optional_no_ca" parameter of the "ssl_verify_client" directive.<br/>
Thanks to Mike Kazantsev and Eric O'Connor.
</para>
</change>
<change type="feature">
<para lang="ru">
переменные $bytes_sent, $connection и $connection_requests
теперь можно использовать не только в директиве log_format.<br/>
Спасибо Benjamin Grössing.
</para>
<para lang="en">
the $bytes_sent, $connection, and $connection_requests variables
can now be used not only in the "log_format" directive.<br/>
Thanks to Benjamin Grössing.
</para>
</change>
<change type="feature">
<para lang="ru">
теперь resolver случайным образом меняет порядок
возвращаемых закэшированных адресов.<br/>
Спасибо Антону Жулину.
</para>
<para lang="en">
resolver now randomly rotates addresses
returned from cache.<br/>
Thanks to Anton Jouline.
</para>
</change>
<change type="feature">
<para lang="ru">
параметр auto директивы worker_processes.
</para>
<para lang="en">
the "auto" parameter of the "worker_processes" directive.
</para>
</change>
<change type="bugfix">
<para lang="ru">
сообщения "cache file ... has md5 collision".
</para>
<para lang="en">
"cache file ... has md5 collision" alert.
</para>
</change>
<change type="bugfix">
<para lang="ru">
совместимость с OpenSSL 0.9.7.
</para>
<para lang="en">
OpenSSL 0.9.7 compatibility.
</para>
</change>
</changes>
<changes ver="1.2.4" date="25.09.2012">
<change type="bugfix">
<para lang="ru">
в директиве "limit_req";
ошибка появилась в 1.1.14.<br/>
Спасибо Charles Chen.
</para>
<para lang="en">
in the "limit_req" directive;
the bug had appeared in 1.1.14.<br/>
Thanks to Charles Chen.
</para>
</change>
<change type="bugfix">
<para lang="ru">
nginx не собирался gcc 4.7 с оптимизацией -O2
если использовался параметр --with-ipv6.
</para>
<para lang="en">
nginx could not be built by gcc 4.7 with -O2 optimization
if the --with-ipv6 option was used.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в рабочем процессе мог произойти segmentation fault,
если в директиве map в качестве значений использовались переменные.
</para>
<para lang="en">
a segmentation fault might occur in a worker process
if the "map" directive was used with variables as values.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в рабочем процессе мог произойти segmentation fault
при использовании директивы geo с параметром ranges,
но без параметра default; ошибка появилась в 0.8.43.<br/>
Спасибо Zhen Chen и Weibin Yao.
</para>
<para lang="en">
a segmentation fault might occur in a worker process
if the "geo" directive was used with the "ranges" parameter
but without the "default" parameter; the bug had appeared in 0.8.43.<br/>
Thanks to Zhen Chen and Weibin Yao.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в обработке параметра командной строки -p.
</para>
<para lang="en">
in the -p command-line parameter handling.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в почтовом прокси-сервере.
</para>
<para lang="en">
in the mail proxy server.
</para>
</change>
<change type="bugfix">
<para lang="ru">
незначительных потенциальных ошибок.<br/>
Спасибо Coverity.
</para>
<para lang="en">
of minor potential bugs.<br/>
Thanks to Coverity.
</para>
</change>
<change type="bugfix">
<para lang="ru">
nginx/Windows не собирался с Visual Studio 2005 Express.<br/>
Спасибо HAYASHI Kentaro.
</para>
<para lang="en">
nginx/Windows could not be built with Visual Studio 2005 Express.<br/>
Thanks to HAYASHI Kentaro.
</para>
</change>
</changes>
<changes ver="1.2.3" date="07.08.2012">
<change type="feature">
<para lang="ru">
поддержка компилятора Clang.
</para>
<para lang="en">
the Clang compiler support.
</para>
</change>
<change type="bugfix">
<para lang="ru">
могли создаваться лишние слушающие сокеты.<br/>
Спасибо Роману Одайскому.
</para>
<para lang="en">
extra listening sockets might be created.<br/>
Thanks to Roman Odaisky.
</para>
</change>
<change type="bugfix">
<para lang="ru">
nginx/Windows мог нагружать процессор, если при запуске рабочего процесса
происходила ошибка.<br/>
Спасибо Ricardo Villalobos Guevara.
</para>
<para lang="en">
nginx/Windows might hog CPU if a worker process failed to start.<br/>
Thanks to Ricardo Villalobos Guevara.
</para>
</change>
<change type="bugfix">
<para lang="ru">
директивы proxy_pass_header, fastcgi_pass_header, scgi_pass_header,
uwsgi_pass_header, proxy_hide_header, fastcgi_hide_header,
scgi_hide_header и uwsgi_hide_header
могли наследоваться некорректно.
</para>
<para lang="en">
the "proxy_pass_header", "fastcgi_pass_header", "scgi_pass_header",
"uwsgi_pass_header", "proxy_hide_header", "fastcgi_hide_header",
"scgi_hide_header", and "uwsgi_hide_header" directives
might be inherited incorrectly.
</para>
</change>
<change type="bugfix">
<para lang="ru">
при использовании директивы map с параметром hostnames
не игнорировалась конечная точка в исходном значении.
</para>
<para lang="en">
trailing dot in a source value was not ignored
if the "map" directive was used with the "hostnames" parameter.
</para>
</change>
<change type="bugfix">
<para lang="ru">
для обработки запроса мог использоваться неверный location,
если переход в именованный location происходил
после изменения URI с помощью директивы rewrite.
</para>
<para lang="en">
incorrect location might be used to process a request
if a URI was changed via a "rewrite" directive
before an internal redirect to a named location.
</para>
</change>
</changes>
<changes ver="1.2.2" date="03.07.2012">
<change type="change">
<para lang="ru">
параметр single директивы keepalive теперь игнорируется.
</para>
<para lang="en">
the "single" parameter of the "keepalive" directive is now ignored.
</para>
</change>
<change type="change">
<para lang="ru">
сжатие SSL теперь отключено
в том числе при использовании OpenSSL cтарее 1.0.0.
</para>
<para lang="en">
SSL compression is now disabled when using all versions of OpenSSL,
including ones prior to 1.0.0.
</para>
</change>
<change type="feature">
<para lang="ru">
директивы proxy_pass, fastcgi_pass, scgi_pass, uwsgi_pass и
директива server в блоке upstream
теперь поддерживают IPv6-адреса.
</para>
<para lang="en">
the "proxy_pass", "fastcgi_pass", "scgi_pass", "uwsgi_pass" directives, and
the "server" directive inside the "upstream" block,
now support IPv6 addresses.
</para>
</change>
<change type="feature">
<para lang="ru">
в директиве resolver теперь можно указывать порт и
задавать IPv6-адреса DNS-серверов.
</para>
<para lang="en">
the "resolver" directive now supports IPv6 addresses and
an optional port specification.
</para>
</change>
<change type="feature">
<para lang="ru">
директива least_conn в блоке upstream.
</para>
<para lang="en">
the "least_conn" directive inside the "upstream" block.
</para>
</change>
<change type="feature">
<para lang="ru">
при использовании директивы ip_hash
теперь можно задавать веса серверов.
</para>
<para lang="en">
it is now possible to specify a weight for servers
while using the "ip_hash" directive.
</para>
</change>
<change type="feature">
<para lang="ru">
директиву "ip_hash" теперь можно использовать для балансировки IPv6 клиентов.
</para>
<para lang="en">
it is now possible to use the "ip_hash" directive to balance IPv6 clients.
</para>
</change>
<change type="feature">
<para lang="ru">
переменную $status теперь можно использовать не только в директиве log_format.
</para>
<para lang="en">
the $status variable can now be used not only in the "log_format" directive.
</para>
</change>
<change type="bugfix">
<para lang="ru">
nginx не собирался с модулем ngx_cpp_test_module;
ошибка появилась в 1.1.12.
</para>
<para lang="en">
nginx could not be built with ngx_cpp_test_module;
the bug had appeared in 1.1.12.
</para>
</change>
<change type="bugfix">
<para lang="ru">
доступ к переменным из SSI и встроенного перла мог не работать после
переконфигурации.<br/>
Спасибо Yichun Zhang.
</para>
<para lang="en">
access to variables from SSI and embedded perl module might not work after
reconfiguration.<br/>
Thanks to Yichun Zhang.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в модуле ngx_http_xslt_filter_module.<br/>
Спасибо Kuramoto Eiji.
</para>
<para lang="en">
in the ngx_http_xslt_filter_module.<br/>
Thanks to Kuramoto Eiji.
</para>
</change>
<change type="bugfix">
<para lang="ru">
утечки памяти при использовании переменной $geoip_org.<br/>
Спасибо Денису Латыпову.
</para>
<para lang="en">
memory leak if $geoip_org variable was used.<br/>
Thanks to Denis F. Latypoff.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в директивах proxy_cookie_domain и proxy_cookie_path.
</para>
<para lang="en">
in the "proxy_cookie_domain" and "proxy_cookie_path" directives.
</para>
</change>
<change type="bugfix">
<para lang="ru">
при завершении рабочего процесса мог произойти segmentation fault,
если использовалась директива resolver.
</para>
<para lang="en">
a segmentation fault might occur in a worker process on shutdown
if the "resolver" directive was used.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в рабочем процессе мог произойти segmentation fault,
если использовался модуль ngx_http_mp4_module.
</para>
<para lang="en">
a segmentation fault might occur in a worker process
if the ngx_http_mp4_module was used.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в модуле ngx_http_mp4_module.
</para>
<para lang="en">
in the ngx_http_mp4_module.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в рабочем процессе мог произойти segmentation fault,
если использовались конфликтующие имена серверов с масками.
</para>
<para lang="en">
a segmentation fault might occur in a worker process
if conflicting wildcard server names were used.
</para>
</change>
<change type="bugfix">
<para lang="ru">
на платформе ARM nginx мог аварийно завершаться по сигналу SIGBUS.
</para>
<para lang="en">
nginx might be terminated abnormally on a SIGBUS signal on ARM platform.
</para>
</change>
<change type="bugfix">
<para lang="ru">
во время переконфигурации на HP-UX в лог
записывался alert "sendmsg() failed (9: Bad file number)".
</para>
<para lang="en">
an alert "sendmsg() failed (9: Bad file number)" on HP-UX
while reconfiguration.
</para>
</change>
</changes>
<changes ver="1.2.1" date="05.06.2012">
<change type="security">
<para lang="ru">
теперь nginx/Windows игнорирует точку в конце компонента URI
и не разрешает URI, содержащие последовательность ":$".<br/>
Спасибо Владимиру Кочеткову, Positive Research Center.
</para>
<para lang="en">
now nginx/Windows ignores trailing dot in URI path component, and
does not allow URIs with ":$" in it.<br/>
Thanks to Vladimir Kochetkov, Positive Research Center.
</para>
</change>
<change type="feature">
<para lang="ru">
директива debug_connection теперь поддерживает IPv6-адреса
и параметр "unix:".
</para>
<para lang="en">
the "debug_connection" directive now supports IPv6 addresses
and the "unix:" parameter.
</para>
</change>
<change type="feature">
<para lang="ru">
директива set_real_ip_from и параметр proxy
директивы geo теперь поддерживают IPv6-адреса.
</para>
<para lang="en">
the "set_real_ip_from" directive and the "proxy" parameter
of the "geo" directive now support IPv6 addresses.
</para>
</change>
<change type="feature">
<para lang="ru">
директивы real_ip_recursive, geoip_proxy и geoip_proxy_recursive.
</para>
<para lang="en">
the "real_ip_recursive", "geoip_proxy", and "geoip_proxy_recursive" directives.
</para>
</change>
<change type="feature">
<para lang="ru">
параметр proxy_recursive директивы geo.
</para>
<para lang="en">
the "proxy_recursive" parameter of the "geo" directive.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в рабочем процессе мог произойти segmentation fault,
если использовалась директива resolver.
</para>
<para lang="en">
a segmentation fault might occur in a worker process
if the "resolver" directive was used.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в рабочем процессе мог произойти segmentation fault,
если использовались директивы fastcgi_pass, scgi_pass или uwsgi_pass
и бэкенд возвращал некорректный ответ.
</para>
<para lang="en">
a segmentation fault might occur in a worker process
if the "fastcgi_pass", "scgi_pass", or "uwsgi_pass" directives were used
and backend returned incorrect response.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в рабочем процессе мог произойти segmentation fault,
если использовалась директива rewrite и в новых аргументах запроса в строке
замены использовались переменные.
</para>
<para lang="en">
a segmentation fault might occur in a worker process
if the "rewrite" directive was used and new request arguments
in a replacement used variables.
</para>
</change>
<change type="bugfix">
<para lang="ru">
nginx мог нагружать процессор,
если было достигнуто ограничение на количество открытых файлов.
</para>
<para lang="en">
nginx might hog CPU
if the open file resource limit was reached.
</para>
</change>
<change type="bugfix">
<para lang="ru">
при использовании директивы proxy_next_upstream с параметром http_404
nginx мог бесконечно перебирать бэкенды, если в блоке upstream был
хотя бы один сервер с флагом backup.
</para>
<para lang="en">
nginx might loop infinitely over backends
if the "proxy_next_upstream" directive with the "http_404" parameter was used
and there were backup servers specified in an upstream block.
</para>
</change>
<change type="bugfix">
<para lang="ru">
при использовании директивы ip_hash
установка параметра down директивы server
могла приводить к ненужному перераспределению клиентов между бэкендами.
</para>
<para lang="en">
adding the "down" parameter of the "server" directive
might cause unneeded client redistribution among backend servers
if the "ip_hash" directive was used.
</para>
</change>
<change type="bugfix">
<para lang="ru">
утечки сокетов.<br/>
Спасибо Yichun Zhang.
</para>
<para lang="en">
socket leak.<br/>
Thanks to Yichun Zhang.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в модуле ngx_http_fastcgi_module.
</para>
<para lang="en">
in the ngx_http_fastcgi_module.
</para>
</change>
</changes>
<changes ver="1.2.0" date="23.04.2012">

View File

@ -1,29 +1,29 @@
X:stylesheet {
X:output method="xml"
X:param indent-increment="' '";
X:template noname(indent="'&#xA;'") = "*" {
!{$indent}
X:if "name()='xsl:template'" {
!{$indent}
}
X:copy {
X:copy-of "@*"
!!( indent = "concat($indent, $indent-increment)" );
X:if "./* " { !{$indent} }
}
}
X:template = "comment()|processing-instruction()" {
X:copy;
}
<!--
X:template ="text()[normalize-space(.)='']" {}
-->
}
X:stylesheet {
X:output method="xml"
X:param indent-increment="' '";
X:template noname(indent="'&#xA;'") = "*" {
!{$indent}
X:if "name()='xsl:template'" {
!{$indent}
}
X:copy {
X:copy-of "@*"
!!( indent = "concat($indent, $indent-increment)" );
X:if "./* " { !{$indent} }
}
}
X:template = "comment()|processing-instruction()" {
X:copy;
}
<!--
X:template ="text()[normalize-space(.)='']" {}
-->
}

View File

@ -6,15 +6,12 @@ TEMP = tmp
REPO = $(shell svn info | sed -n 's/^Repository Root: //p')
OBJS = objs.msvc8
OPENSSL = openssl-1.0.0i
ZLIB = zlib-1.2.5
PCRE = pcre-8.30
OPENSSL = openssl-1.0.1e
ZLIB = zlib-1.2.7
PCRE = pcre-8.32
release:
rm -rf $(TEMP)
svn export -rHEAD . $(TEMP)/$(NGINX)
release: export
mv $(TEMP)/$(NGINX)/auto/configure $(TEMP)/$(NGINX)
@ -39,70 +36,102 @@ release:
tar -c -z -f $(NGINX).tar.gz --directory $(TEMP) $(NGINX)
export:
rm -rf $(TEMP)
if [ -d .svn ]; then \
svn export -rHEAD . $(TEMP)/$(NGINX); \
else \
hg archive -X '.hg*' $(TEMP)/$(NGINX); \
fi
RELEASE:
if [ -d .svn ]; then \
$(MAKE) -f misc/GNUmakefile RELEASE.svn; \
else \
$(MAKE) -f misc/GNUmakefile RELEASE.hg; \
fi
$(MAKE) -f misc/GNUmakefile release
RELEASE.hg:
hg ci -m nginx-$(VER)-RELEASE
hg tag -m "release-$(VER) tag" release-$(VER)
RELEASE.svn:
test -d $(TEMP) || mkdir -p $(TEMP)
echo "nginx-$(VER)-RELEASE" > $(TEMP)/message
svn ci -F $(TEMP)/message
echo "release-$(VER) tag" > $(TEMP)/message
svn copy $(REPO)/trunk $(REPO)/tags/release-$(VER) \
svn copy $(REPO)/branches/stable-1.2 \
$(REPO)/tags/release-$(VER) \
-F $(TEMP)/message
svn up
$(MAKE) -f misc/GNUmakefile release
win32:
./auto/configure \
--with-cc=cl \
--builddir=$(OBJS) \
--with-debug \
--prefix= \
--conf-path=conf/nginx.conf \
--pid-path=logs/nginx.pid \
--http-log-path=logs/access.log \
--error-log-path=logs/error.log \
--sbin-path=nginx.exe \
--http-client-body-temp-path=temp/client_body_temp \
--http-proxy-temp-path=temp/proxy_temp \
--http-fastcgi-temp-path=temp/fastcgi_temp \
--http-scgi-temp-path=temp/scgi_temp \
--http-uwsgi-temp-path=temp/uwsgi_temp \
--with-cc-opt=-DFD_SETSIZE=1024 \
--with-pcre=$(OBJS)/lib/$(PCRE) \
--with-zlib=$(OBJS)/lib/$(ZLIB) \
--with-select_module \
--with-http_realip_module \
--with-http_addition_module \
--with-http_sub_module \
--with-http_dav_module \
--with-http_stub_status_module \
--with-http_flv_module \
--with-http_mp4_module \
--with-http_gzip_static_module \
--with-http_random_index_module \
--with-http_secure_link_module \
--with-mail \
--with-openssl=$(OBJS)/lib/$(OPENSSL) \
--with-openssl-opt=enable-tlsext \
--with-http_ssl_module \
--with-mail_ssl_module \
--with-ipv6
snapshot:
rm -rf $(TEMP)
mkdir -p $(TEMP)
svn export . $(TEMP)/$(NGINX)
mv $(TEMP)/$(NGINX)/auto/configure $(TEMP)/$(NGINX)
# delete incomplete sources
rm $(TEMP)/$(NGINX)/src/event/ngx_event_acceptex.c
rm $(TEMP)/$(NGINX)/src/event/ngx_event_connectex.c
rm $(TEMP)/$(NGINX)/src/event/modules/ngx_iocp_module.*
rm -r $(TEMP)/$(NGINX)/src/os/win32
rm -r $(TEMP)/$(NGINX)/src/mysql
mv $(TEMP)/$(NGINX)/docs/text/LICENSE $(TEMP)/$(NGINX)
mv $(TEMP)/$(NGINX)/docs/text/README $(TEMP)/$(NGINX)
mv $(TEMP)/$(NGINX)/docs/html $(TEMP)/$(NGINX)
mv $(TEMP)/$(NGINX)/docs/man $(TEMP)/$(NGINX)
$(MAKE) -f docs/GNUmakefile changes
rm -r $(TEMP)/$(NGINX)/docs
rm -r $(TEMP)/$(NGINX)/misc
tar -c -z -f $(NGINX).tar.gz --directory $(TEMP) $(NGINX)
zip:
rm -rf $(TEMP)
zip: export
rm -f $(NGINX).zip
mkdir -p $(TEMP)/$(NGINX)/docs
mkdir -p $(TEMP)/$(NGINX)/docs.new
mkdir -p $(TEMP)/$(NGINX)/logs
mkdir -p $(TEMP)/$(NGINX)/temp
svn export -rHEAD conf $(TEMP)/$(NGINX)/conf/
perl -pi -e 's/$$/\r/' $(TEMP)/$(NGINX)/conf/*
sed -i '' -e "s/$$/`printf '\r'`/" $(TEMP)/$(NGINX)/conf/*
svn export -rHEAD contrib $(TEMP)/$(NGINX)/contrib/
svn export -rHEAD docs/html $(TEMP)/$(NGINX)/html/
mv $(TEMP)/$(NGINX)/docs/text/LICENSE $(TEMP)/$(NGINX)/docs.new
mv $(TEMP)/$(NGINX)/docs/text/README $(TEMP)/$(NGINX)/docs.new
mv $(TEMP)/$(NGINX)/docs/html $(TEMP)/$(NGINX)
$(MAKE) -f docs/GNUmakefile changes
rm -r $(TEMP)/$(NGINX)/docs
mv $(TEMP)/$(NGINX)/docs.new $(TEMP)/$(NGINX)/docs
cp -p $(OBJS)/nginx.exe $(TEMP)/$(NGINX)
cp -p docs/text/LICENSE $(TEMP)/$(NGINX)/docs/
cp -p docs/text/README $(TEMP)/$(NGINX)/docs/
$(MAKE) -f docs/GNUmakefile changes
mv $(TEMP)/$(NGINX)/CHANGES* $(TEMP)/$(NGINX)/docs/
cp -p $(OBJS)/lib/$(OPENSSL)/LICENSE \
@ -111,13 +140,17 @@ zip:
cp -p $(OBJS)/lib/$(PCRE)/LICENCE \
$(TEMP)/$(NGINX)/docs/PCRE.LICENCE
perl -ne 'print if /^ \(C\) 1995-20/ .. /^ jloup\@gzip.org/' \
sed -ne '/^ (C) 1995-20/,/^ jloup@gzip\.org/p' \
$(OBJS)/lib/$(ZLIB)/README \
> $(TEMP)/$(NGINX)/docs/zlib.LICENSE
touch -r $(OBJS)/lib/$(ZLIB)/README \
$(TEMP)/$(NGINX)/docs/zlib.LICENSE
rm -r $(TEMP)/$(NGINX)/auto
rm -r $(TEMP)/$(NGINX)/misc
rm -r $(TEMP)/$(NGINX)/src
cd $(TEMP) && zip -r ../$(NGINX).zip $(NGINX)

View File

@ -21,6 +21,8 @@ static char *ngx_set_env(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static char *ngx_set_priority(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static char *ngx_set_cpu_affinity(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_set_worker_processes(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static ngx_conf_enum_t ngx_debug_points[] = {
@ -69,9 +71,9 @@ static ngx_command_t ngx_core_commands[] = {
{ ngx_string("worker_processes"),
NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
ngx_set_worker_processes,
0,
0,
offsetof(ngx_core_conf_t, worker_processes),
NULL },
{ ngx_string("debug_points"),
@ -592,6 +594,10 @@ ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv)
var = ngx_alloc(sizeof(NGINX_VAR)
+ cycle->listening.nelts * (NGX_INT32_LEN + 1) + 2,
cycle->log);
if (var == NULL) {
ngx_free(env);
return NGX_INVALID_PID;
}
p = ngx_cpymem(var, NGINX_VAR "=", sizeof(NGINX_VAR));
@ -631,7 +637,7 @@ ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv)
ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
if (ngx_rename_file(ccf->pid.data, ccf->oldpid.data) != NGX_OK) {
if (ngx_rename_file(ccf->pid.data, ccf->oldpid.data) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
ngx_rename_file_n " %s to %s failed "
"before executing new binary process \"%s\"",
@ -646,7 +652,9 @@ ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv)
pid = ngx_execute(cycle, &ctx);
if (pid == NGX_INVALID_PID) {
if (ngx_rename_file(ccf->oldpid.data, ccf->pid.data) != NGX_OK) {
if (ngx_rename_file(ccf->oldpid.data, ccf->pid.data)
== NGX_FILE_ERROR)
{
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
ngx_rename_file_n " %s back to %s failed after "
"an attempt to execute new binary process \"%s\"",
@ -836,7 +844,7 @@ ngx_process_options(ngx_cycle_t *cycle)
len = ngx_strlen(ngx_prefix);
p = ngx_prefix;
if (!ngx_path_separator(*p)) {
if (len && !ngx_path_separator(p[len - 1])) {
p = ngx_pnalloc(cycle->pool, len + 1);
if (p == NULL) {
return NGX_ERROR;
@ -1329,3 +1337,32 @@ ngx_get_cpu_affinity(ngx_uint_t n)
return ccf->cpu_affinity[ccf->cpu_affinity_n - 1];
}
static char *
ngx_set_worker_processes(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_str_t *value;
ngx_core_conf_t *ccf;
ccf = (ngx_core_conf_t *) conf;
if (ccf->worker_processes != NGX_CONF_UNSET) {
return "is duplicate";
}
value = (ngx_str_t *) cf->args->elts;
if (ngx_strcmp(value[1].data, "auto") == 0) {
ccf->worker_processes = ngx_ncpu;
return NGX_CONF_OK;
}
ccf->worker_processes = ngx_atoi(value[1].data, value[1].len);
if (ccf->worker_processes == NGX_ERROR) {
return "invalid value";
}
return NGX_CONF_OK;
}

View File

@ -9,8 +9,8 @@
#define _NGINX_H_INCLUDED_
#define nginx_version 1002000
#define NGINX_VERSION "1.2.0"
#define nginx_version 1002009
#define NGINX_VERSION "1.2.9"
#define NGINX_VER "nginx/" NGINX_VERSION
#define NGINX_VAR "NGINX"

View File

@ -12,7 +12,6 @@
static ngx_int_t ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last);
static ngx_int_t ngx_conf_read_token(ngx_conf_t *cf);
static char *ngx_conf_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static ngx_int_t ngx_conf_test_full_name(ngx_str_t *name);
static void ngx_conf_flush_files(ngx_cycle_t *cycle);
@ -134,7 +133,7 @@ ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename)
cf->conf_file = &conf_file;
if (ngx_fd_info(fd, &cf->conf_file->file.info) == -1) {
if (ngx_fd_info(fd, &cf->conf_file->file.info) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_EMERG, cf->log, ngx_errno,
ngx_fd_info_n " \"%s\" failed", filename->data);
}
@ -282,24 +281,16 @@ ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last)
{
char *rv;
void *conf, **confp;
ngx_uint_t i, multi;
ngx_uint_t i, found;
ngx_str_t *name;
ngx_command_t *cmd;
name = cf->args->elts;
multi = 0;
found = 0;
for (i = 0; ngx_modules[i]; i++) {
/* look up the directive in the appropriate modules */
if (ngx_modules[i]->type != NGX_CONF_MODULE
&& ngx_modules[i]->type != cf->module_type)
{
continue;
}
cmd = ngx_modules[i]->commands;
if (cmd == NULL) {
continue;
@ -315,16 +306,18 @@ ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last)
continue;
}
found = 1;
if (ngx_modules[i]->type != NGX_CONF_MODULE
&& ngx_modules[i]->type != cf->module_type)
{
continue;
}
/* is the directive's location right ? */
if (!(cmd->type & cf->cmd_type)) {
if (cmd->type & NGX_CONF_MULTI) {
multi = 1;
continue;
}
goto not_allowed;
continue;
}
if (!(cmd->type & NGX_CONF_BLOCK) && last != NGX_OK) {
@ -408,17 +401,16 @@ ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last)
}
}
if (multi == 0) {
if (found) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"unknown directive \"%s\"", name->data);
"\"%s\" directive is not allowed here", name->data);
return NGX_ERROR;
}
not_allowed:
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"\"%s\" directive is not allowed here", name->data);
"unknown directive \"%s\"", name->data);
return NGX_ERROR;
invalid:
@ -738,7 +730,7 @@ ngx_conf_read_token(ngx_conf_t *cf)
}
static char *
char *
ngx_conf_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
char *rv;
@ -953,7 +945,8 @@ ngx_conf_open_file(ngx_cycle_t *cycle, ngx_str_t *name)
file->name = *name;
}
file->buffer = NULL;
file->flush = NULL;
file->data = NULL;
return file;
}
@ -962,7 +955,6 @@ ngx_conf_open_file(ngx_cycle_t *cycle, ngx_str_t *name)
static void
ngx_conf_flush_files(ngx_cycle_t *cycle)
{
ssize_t n, len;
ngx_uint_t i;
ngx_list_part_t *part;
ngx_open_file_t *file;
@ -983,23 +975,8 @@ ngx_conf_flush_files(ngx_cycle_t *cycle)
i = 0;
}
len = file[i].pos - file[i].buffer;
if (file[i].buffer == NULL || len == 0) {
continue;
}
n = ngx_write_fd(file[i].fd, file[i].buffer, len);
if (n == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
ngx_write_fd_n " to \"%s\" failed",
file[i].name.data);
} else if (n != len) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
ngx_write_fd_n " to \"%s\" was incomplete: %z of %uz",
file[i].name.data, n, len);
if (file[i].flush) {
file[i].flush(&file[i], cycle->log);
}
}
}
@ -1448,12 +1425,16 @@ ngx_conf_set_bitmask_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
#if 0
char *
ngx_conf_unsupported(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
return "unsupported on this platform";
}
#endif
char *
ngx_conf_deprecated(ngx_conf_t *cf, void *post, void *data)

View File

@ -45,7 +45,7 @@
#define NGX_CONF_ANY 0x00000400
#define NGX_CONF_1MORE 0x00000800
#define NGX_CONF_2MORE 0x00001000
#define NGX_CONF_MULTI 0x00002000
#define NGX_CONF_MULTI 0x00000000 /* compatibility */
#define NGX_DIRECT_CONF 0x00010000
@ -91,17 +91,8 @@ struct ngx_open_file_s {
ngx_fd_t fd;
ngx_str_t name;
u_char *buffer;
u_char *pos;
u_char *last;
#if 0
/* e.g. append mode, error_log */
ngx_uint_t flags;
/* e.g. reopen db file */
ngx_uint_t (*handler)(void *data, ngx_open_file_t *file);
void (*flush)(ngx_open_file_t *file, ngx_log_t *log);
void *data;
#endif
};
@ -317,6 +308,7 @@ char *ngx_conf_check_num_bounds(ngx_conf_t *cf, void *post, void *data);
char *ngx_conf_param(ngx_conf_t *cf);
char *ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename);
char *ngx_conf_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
ngx_int_t ngx_conf_full_name(ngx_cycle_t *cycle, ngx_str_t *name,

View File

@ -412,7 +412,7 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle)
}
if (ngx_test_config) {
if (ngx_delete_file(name) == -1) {
if (ngx_delete_file(name) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
ngx_delete_file_n " %s failed", name);
}
@ -739,7 +739,7 @@ ngx_close_listening_sockets(ngx_cycle_t *cycle)
{
u_char *name = ls[i].addr_text.data + sizeof("unix:") - 1;
if (ngx_delete_file(name) == -1) {
if (ngx_delete_file(name) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
ngx_delete_file_n " %s failed", name);
}
@ -749,6 +749,8 @@ ngx_close_listening_sockets(ngx_cycle_t *cycle)
ls[i].fd = (ngx_socket_t) -1;
}
cycle->listening.nelts = 0;
}

View File

@ -6,6 +6,7 @@
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_crypt.h>
#include <ngx_md5.h>
#if (NGX_HAVE_SHA1)
#include <ngx_sha1.h>
@ -193,6 +194,7 @@ static ngx_int_t
ngx_crypt_ssha(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted)
{
size_t len;
ngx_int_t rc;
ngx_str_t encoded, decoded;
ngx_sha1_t sha1;
@ -203,12 +205,18 @@ ngx_crypt_ssha(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted)
encoded.data = salt + sizeof("{SSHA}") - 1;
encoded.len = ngx_strlen(encoded.data);
decoded.data = ngx_pnalloc(pool, ngx_base64_decoded_length(encoded.len));
len = ngx_max(ngx_base64_decoded_length(encoded.len), 20);
decoded.data = ngx_pnalloc(pool, len);
if (decoded.data == NULL) {
return NGX_ERROR;
}
ngx_decode_base64(&decoded, &encoded);
rc = ngx_decode_base64(&decoded, &encoded);
if (rc != NGX_OK || decoded.len < 20) {
decoded.len = 20;
}
/* update SHA1 from key and salt */

View File

@ -118,18 +118,18 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
}
n = old_cycle->pathes.nelts ? old_cycle->pathes.nelts : 10;
n = old_cycle->paths.nelts ? old_cycle->paths.nelts : 10;
cycle->pathes.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *));
if (cycle->pathes.elts == NULL) {
cycle->paths.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *));
if (cycle->paths.elts == NULL) {
ngx_destroy_pool(pool);
return NULL;
}
cycle->pathes.nelts = 0;
cycle->pathes.size = sizeof(ngx_path_t *);
cycle->pathes.nalloc = n;
cycle->pathes.pool = pool;
cycle->paths.nelts = 0;
cycle->paths.size = sizeof(ngx_path_t *);
cycle->paths.nalloc = n;
cycle->paths.pool = pool;
if (old_cycle->open_files.part.nelts) {
@ -334,7 +334,7 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
}
if (ngx_create_pathes(cycle, ccf->user) != NGX_OK) {
if (ngx_create_paths(cycle, ccf->user) != NGX_OK) {
goto failed;
}
@ -447,7 +447,9 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
continue;
}
if (shm_zone[i].shm.size == oshm_zone[n].shm.size) {
if (shm_zone[i].tag == oshm_zone[n].tag
&& shm_zone[i].shm.size == oshm_zone[n].shm.size)
{
shm_zone[i].shm.addr = oshm_zone[n].shm.addr;
if (shm_zone[i].init(&shm_zone[i], oshm_zone[n].data)
@ -677,7 +679,7 @@ old_shm_zone_done:
ngx_log_error(NGX_LOG_WARN, cycle->log, 0,
"deleting socket %s", name);
if (ngx_delete_file(name) == -1) {
if (ngx_delete_file(name) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
ngx_delete_file_n " %s failed", name);
}
@ -1038,6 +1040,8 @@ ngx_signal_process(ngx_cycle_t *cycle, char *sig)
ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
ngx_memzero(&file, sizeof(ngx_file_t));
file.name = ccf->pid;
file.log = cycle->log;
@ -1111,7 +1115,6 @@ ngx_test_lockfile(u_char *file, ngx_log_t *log)
void
ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user)
{
ssize_t n, len;
ngx_fd_t fd;
ngx_uint_t i;
ngx_list_part_t *part;
@ -1135,24 +1138,8 @@ ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user)
continue;
}
len = file[i].pos - file[i].buffer;
if (file[i].buffer && len != 0) {
n = ngx_write_fd(file[i].fd, file[i].buffer, len);
if (n == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
ngx_write_fd_n " to \"%s\" failed",
file[i].name.data);
} else if (n != len) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
ngx_write_fd_n " to \"%s\" was incomplete: %z of %uz",
file[i].name.data, n, len);
}
file[i].pos = file[i].buffer;
if (file[i].flush) {
file[i].flush(&file[i], cycle->log);
}
fd = ngx_open_file(file[i].name.data, NGX_FILE_APPEND,
@ -1285,14 +1272,6 @@ ngx_shared_memory_add(ngx_conf_t *cf, ngx_str_t *name, size_t size, void *tag)
continue;
}
if (size && size != shm_zone[i].shm.size) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"the size %uz of shared memory zone \"%V\" "
"conflicts with already declared size %uz",
size, &shm_zone[i].shm.name, shm_zone[i].shm.size);
return NULL;
}
if (tag != shm_zone[i].tag) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"the shared memory zone \"%V\" is "
@ -1301,6 +1280,14 @@ ngx_shared_memory_add(ngx_conf_t *cf, ngx_str_t *name, size_t size, void *tag)
return NULL;
}
if (size && size != shm_zone[i].shm.size) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"the size %uz of shared memory zone \"%V\" "
"conflicts with already declared size %uz",
size, &shm_zone[i].shm.name, shm_zone[i].shm.size);
return NULL;
}
return &shm_zone[i];
}

View File

@ -48,7 +48,7 @@ struct ngx_cycle_s {
ngx_queue_t reusable_connections_queue;
ngx_array_t listening;
ngx_array_t pathes;
ngx_array_t paths;
ngx_list_t open_files;
ngx_list_t shared_memory;

View File

@ -412,8 +412,8 @@ ngx_add_path(ngx_conf_t *cf, ngx_path_t **slot)
path = *slot;
p = cf->cycle->pathes.elts;
for (i = 0; i < cf->cycle->pathes.nelts; i++) {
p = cf->cycle->paths.elts;
for (i = 0; i < cf->cycle->paths.nelts; i++) {
if (p[i]->name.len == path->name.len
&& ngx_strcmp(p[i]->name.data, path->name.data) == 0)
{
@ -457,7 +457,7 @@ ngx_add_path(ngx_conf_t *cf, ngx_path_t **slot)
}
}
p = ngx_array_push(&cf->cycle->pathes);
p = ngx_array_push(&cf->cycle->paths);
if (p == NULL) {
return NGX_ERROR;
}
@ -469,14 +469,14 @@ ngx_add_path(ngx_conf_t *cf, ngx_path_t **slot)
ngx_int_t
ngx_create_pathes(ngx_cycle_t *cycle, ngx_uid_t user)
ngx_create_paths(ngx_cycle_t *cycle, ngx_uid_t user)
{
ngx_err_t err;
ngx_uint_t i;
ngx_path_t **path;
path = cycle->pathes.elts;
for (i = 0; i < cycle->pathes.nelts; i++) {
path = cycle->paths.elts;
for (i = 0; i < cycle->paths.nelts; i++) {
if (ngx_create_dir(path[i]->name.data, 0700) == NGX_FILE_ERROR) {
err = ngx_errno;
@ -732,14 +732,14 @@ ngx_copy_file(u_char *from, u_char *to, ngx_copy_file_t *cf)
n = ngx_read_fd(fd, buf, len);
if (n == NGX_FILE_ERROR) {
if (n == -1) {
ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
ngx_read_fd_n " \"%s\" failed", from);
goto failed;
}
if ((size_t) n != len) {
ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
ngx_log_error(NGX_LOG_ALERT, cf->log, 0,
ngx_read_fd_n " has read only %z of %uz from %s",
n, size, from);
goto failed;
@ -747,14 +747,14 @@ ngx_copy_file(u_char *from, u_char *to, ngx_copy_file_t *cf)
n = ngx_write_fd(nfd, buf, len);
if (n == NGX_FILE_ERROR) {
if (n == -1) {
ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
ngx_write_fd_n " \"%s\" failed", to);
goto failed;
}
if ((size_t) n != len) {
ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
ngx_log_error(NGX_LOG_ALERT, cf->log, 0,
ngx_write_fd_n " has written only %z of %uz to %s",
n, size, to);
goto failed;

View File

@ -130,7 +130,7 @@ void ngx_create_hashed_filename(ngx_path_t *path, u_char *file, size_t len);
ngx_int_t ngx_create_path(ngx_file_t *file, ngx_path_t *path);
ngx_err_t ngx_create_full_path(u_char *dir, ngx_uint_t access);
ngx_int_t ngx_add_path(ngx_conf_t *cf, ngx_path_t **slot);
ngx_int_t ngx_create_pathes(ngx_cycle_t *cycle, ngx_uid_t user);
ngx_int_t ngx_create_paths(ngx_cycle_t *cycle, ngx_uid_t user);
ngx_int_t ngx_ext_rename_file(ngx_str_t *src, ngx_str_t *to,
ngx_ext_rename_file_t *ext);
ngx_int_t ngx_copy_file(u_char *from, u_char *to, ngx_copy_file_t *cf);

View File

@ -924,17 +924,6 @@ wildcard:
}
hk = ngx_array_push(hwc);
if (hk == NULL) {
return NGX_ERROR;
}
hk->key.len = last - 1;
hk->key.data = p;
hk->key_hash = 0;
hk->value = value;
/* check conflicts in wildcard hash */
name = keys->elts;
@ -972,5 +961,18 @@ wildcard:
ngx_memcpy(name->data, key->data + skip, name->len);
/* add to wildcard hash */
hk = ngx_array_push(hwc);
if (hk == NULL) {
return NGX_ERROR;
}
hk->key.len = last - 1;
hk->key.data = p;
hk->key_hash = 0;
hk->value = value;
return NGX_OK;
}

View File

@ -465,7 +465,7 @@ ngx_parse_addr(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text, size_t len)
* prevent MSVC8 warning:
* potentially uninitialized local variable 'inaddr6' used
*/
ngx_memzero(inaddr6.s6_addr, sizeof(struct in6_addr));
ngx_memzero(&inaddr6, sizeof(struct in6_addr));
#endif
inaddr = ngx_inet_addr(text, len);
@ -522,11 +522,6 @@ ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u)
return ngx_parse_unix_domain_url(pool, u);
}
if ((p[0] == ':' || p[0] == '/') && !u->listen) {
u->err = "invalid host";
return NGX_ERROR;
}
if (p[0] == '[') {
return ngx_parse_inet6_url(pool, u);
}
@ -639,10 +634,7 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u)
args = ngx_strlchr(host, last, '?');
if (args) {
if (uri == NULL) {
uri = args;
} else if (args < uri) {
if (uri == NULL || args < uri) {
uri = args;
}
}
@ -668,11 +660,6 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u)
len = last - port;
if (len == 0) {
u->err = "invalid port";
return NGX_ERROR;
}
n = ngx_atoi(port, len);
if (n < 1 || n > 65535) {
@ -779,11 +766,7 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u)
return NGX_OK;
}
if (ngx_inet_resolve_host(pool, u) != NGX_OK) {
return NGX_ERROR;
}
return NGX_OK;
return ngx_inet_resolve_host(pool, u);
}
@ -825,6 +808,8 @@ ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u)
u->uri.len = last - uri;
u->uri.data = uri;
last = uri;
}
if (*port == ':') {
@ -832,11 +817,6 @@ ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u)
len = last - port;
if (len == 0) {
u->err = "invalid port";
return NGX_ERROR;
}
n = ngx_atoi(port, len);
if (n < 1 || n > 65535) {
@ -862,8 +842,8 @@ ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u)
return NGX_ERROR;
}
u->host.len = len;
u->host.data = host;
u->host.len = len + 2;
u->host.data = host - 1;
if (ngx_inet6_addr(host, len, sin6->sin6_addr.s6_addr) != NGX_OK) {
u->err = "invalid IPv6 address";
@ -874,17 +854,38 @@ ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u)
u->wildcard = 1;
}
u->family = AF_INET6;
if (u->no_resolve) {
return NGX_OK;
}
if (u->no_port) {
u->port = u->default_port;
sin6->sin6_port = htons(u->default_port);
}
u->family = AF_INET6;
u->naddrs = 1;
u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
if (u->addrs == NULL) {
return NGX_ERROR;
}
sin6 = ngx_pcalloc(pool, sizeof(struct sockaddr_in6));
if (sin6 == NULL) {
return NGX_ERROR;
}
ngx_memcpy(sin6, u->sockaddr, sizeof(struct sockaddr_in6));
u->addrs[0].sockaddr = (struct sockaddr *) sin6;
u->addrs[0].socklen = sizeof(struct sockaddr_in6);
p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1);
if (p == NULL) {
return NGX_ERROR;
}
u->addrs[0].name.len = ngx_sprintf(p, "%V:%d",
&u->host, u->port) - p;
u->addrs[0].name.data = p;
return NGX_OK;
#else

View File

@ -30,7 +30,7 @@
#if (NGX_HAVE_UNIX_DOMAIN)
#define NGX_SOCKADDR_STRLEN (sizeof("unix:") - 1 + NGX_UNIX_ADDRSTRLEN)
#else
#define NGX_SOCKADDR_STRLEN (NGX_INET6_ADDRSTRLEN + sizeof(":65535") - 1)
#define NGX_SOCKADDR_STRLEN (NGX_INET6_ADDRSTRLEN + sizeof("[]:65535") - 1)
#endif
#if (NGX_HAVE_UNIX_DOMAIN)

View File

@ -9,7 +9,7 @@
#include <ngx_core.h>
static void *ngx_radix_alloc(ngx_radix_tree_t *tree);
static ngx_radix_node_t *ngx_radix_alloc(ngx_radix_tree_t *tree);
ngx_radix_tree_t *
@ -60,7 +60,7 @@ ngx_radix_tree_create(ngx_pool_t *pool, ngx_int_t preallocate)
*/
if (preallocate == -1) {
switch (ngx_pagesize / sizeof(ngx_radix_tree_t)) {
switch (ngx_pagesize / sizeof(ngx_radix_node_t)) {
/* amd64 */
case 128:
@ -263,13 +263,210 @@ ngx_radix32tree_find(ngx_radix_tree_t *tree, uint32_t key)
}
static void *
#if (NGX_HAVE_INET6)
ngx_int_t
ngx_radix128tree_insert(ngx_radix_tree_t *tree, u_char *key, u_char *mask,
uintptr_t value)
{
u_char bit;
ngx_uint_t i;
ngx_radix_node_t *node, *next;
i = 0;
bit = 0x80;
node = tree->root;
next = tree->root;
while (bit & mask[i]) {
if (key[i] & bit) {
next = node->right;
} else {
next = node->left;
}
if (next == NULL) {
break;
}
bit >>= 1;
node = next;
if (bit == 0) {
if (++i == 16) {
break;
}
bit = 0x80;
}
}
if (next) {
if (node->value != NGX_RADIX_NO_VALUE) {
return NGX_BUSY;
}
node->value = value;
return NGX_OK;
}
while (bit & mask[i]) {
next = ngx_radix_alloc(tree);
if (next == NULL) {
return NGX_ERROR;
}
next->right = NULL;
next->left = NULL;
next->parent = node;
next->value = NGX_RADIX_NO_VALUE;
if (key[i] & bit) {
node->right = next;
} else {
node->left = next;
}
bit >>= 1;
node = next;
if (bit == 0) {
if (++i == 16) {
break;
}
bit = 0x80;
}
}
node->value = value;
return NGX_OK;
}
ngx_int_t
ngx_radix128tree_delete(ngx_radix_tree_t *tree, u_char *key, u_char *mask)
{
u_char bit;
ngx_uint_t i;
ngx_radix_node_t *node;
i = 0;
bit = 0x80;
node = tree->root;
while (node && (bit & mask[i])) {
if (key[i] & bit) {
node = node->right;
} else {
node = node->left;
}
bit >>= 1;
if (bit == 0) {
if (++i == 16) {
break;
}
bit = 0x80;
}
}
if (node == NULL) {
return NGX_ERROR;
}
if (node->right || node->left) {
if (node->value != NGX_RADIX_NO_VALUE) {
node->value = NGX_RADIX_NO_VALUE;
return NGX_OK;
}
return NGX_ERROR;
}
for ( ;; ) {
if (node->parent->right == node) {
node->parent->right = NULL;
} else {
node->parent->left = NULL;
}
node->right = tree->free;
tree->free = node;
node = node->parent;
if (node->right || node->left) {
break;
}
if (node->value != NGX_RADIX_NO_VALUE) {
break;
}
if (node->parent == NULL) {
break;
}
}
return NGX_OK;
}
uintptr_t
ngx_radix128tree_find(ngx_radix_tree_t *tree, u_char *key)
{
u_char bit;
uintptr_t value;
ngx_uint_t i;
ngx_radix_node_t *node;
i = 0;
bit = 0x80;
value = NGX_RADIX_NO_VALUE;
node = tree->root;
while (node) {
if (node->value != NGX_RADIX_NO_VALUE) {
value = node->value;
}
if (key[i] & bit) {
node = node->right;
} else {
node = node->left;
}
bit >>= 1;
if (bit == 0) {
i++;
bit = 0x80;
}
}
return value;
}
#endif
static ngx_radix_node_t *
ngx_radix_alloc(ngx_radix_tree_t *tree)
{
char *p;
ngx_radix_node_t *p;
if (tree->free) {
p = (char *) tree->free;
p = tree->free;
tree->free = tree->free->right;
return p;
}
@ -283,7 +480,7 @@ ngx_radix_alloc(ngx_radix_tree_t *tree)
tree->size = ngx_pagesize;
}
p = tree->start;
p = (ngx_radix_node_t *) tree->start;
tree->start += sizeof(ngx_radix_node_t);
tree->size -= sizeof(ngx_radix_node_t);

View File

@ -36,11 +36,20 @@ typedef struct {
ngx_radix_tree_t *ngx_radix_tree_create(ngx_pool_t *pool,
ngx_int_t preallocate);
ngx_int_t ngx_radix32tree_insert(ngx_radix_tree_t *tree,
uint32_t key, uint32_t mask, uintptr_t value);
ngx_int_t ngx_radix32tree_delete(ngx_radix_tree_t *tree,
uint32_t key, uint32_t mask);
uintptr_t ngx_radix32tree_find(ngx_radix_tree_t *tree, uint32_t key);
#if (NGX_HAVE_INET6)
ngx_int_t ngx_radix128tree_insert(ngx_radix_tree_t *tree,
u_char *key, u_char *mask, uintptr_t value);
ngx_int_t ngx_radix128tree_delete(ngx_radix_tree_t *tree,
u_char *key, u_char *mask);
uintptr_t ngx_radix128tree_find(ngx_radix_tree_t *tree, u_char *key);
#endif
#endif /* _NGX_RADIX_TREE_H_INCLUDED_ */

View File

@ -152,7 +152,7 @@ ngx_regex_compile(ngx_regex_compile_t *rc)
return NGX_ERROR;
}
rc->regex->pcre = re;
rc->regex->code = re;
/* do not study at runtime */
@ -367,7 +367,7 @@ ngx_regex_module_init(ngx_cycle_t *cycle)
i = 0;
}
elts[i].regex->extra = pcre_study(elts[i].regex->pcre, opt, &errstr);
elts[i].regex->extra = pcre_study(elts[i].regex->code, opt, &errstr);
if (errstr != NULL) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
@ -380,7 +380,7 @@ ngx_regex_module_init(ngx_cycle_t *cycle)
int jit, n;
jit = 0;
n = pcre_fullinfo(elts[i].regex->pcre, elts[i].regex->extra,
n = pcre_fullinfo(elts[i].regex->code, elts[i].regex->extra,
PCRE_INFO_JIT, &jit);
if (n != 0 || jit != 1) {

View File

@ -21,7 +21,7 @@
typedef struct {
pcre *pcre;
pcre *code;
pcre_extra *extra;
} ngx_regex_t;
@ -50,7 +50,7 @@ void ngx_regex_init(void);
ngx_int_t ngx_regex_compile(ngx_regex_compile_t *rc);
#define ngx_regex_exec(re, s, captures, size) \
pcre_exec(re->pcre, re->extra, (const char *) (s)->data, (s)->len, 0, 0, \
pcre_exec(re->code, re->extra, (const char *) (s)->data, (s)->len, 0, 0, \
captures, size)
#define ngx_regex_exec_n "pcre_exec()"

View File

@ -88,6 +88,8 @@ static void *ngx_resolver_calloc(ngx_resolver_t *r, size_t size);
static void ngx_resolver_free(ngx_resolver_t *r, void *p);
static void ngx_resolver_free_locked(ngx_resolver_t *r, void *p);
static void *ngx_resolver_dup(ngx_resolver_t *r, void *src, size_t size);
static in_addr_t *ngx_resolver_rotate(ngx_resolver_t *r, in_addr_t *src,
ngx_uint_t n);
static u_char *ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t len);
@ -96,7 +98,7 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n)
{
ngx_str_t s;
ngx_url_t u;
ngx_uint_t i;
ngx_uint_t i, j;
ngx_resolver_t *r;
ngx_pool_cleanup_t *cln;
ngx_udp_connection_t *uc;
@ -113,15 +115,6 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n)
return NULL;
}
if (n) {
if (ngx_array_init(&r->udp_connections, cf->pool, n,
sizeof(ngx_udp_connection_t))
!= NGX_OK)
{
return NULL;
}
}
cln->data = r;
r->event = ngx_calloc(sizeof(ngx_event_t), cf->log);
@ -153,6 +146,15 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n)
r->log = &cf->cycle->new_log;
r->log_level = NGX_LOG_ERR;
if (n) {
if (ngx_array_init(&r->udp_connections, cf->pool, n,
sizeof(ngx_udp_connection_t))
!= NGX_OK)
{
return NULL;
}
}
for (i = 0; i < n; i++) {
if (ngx_strncmp(names[i].data, "valid=", 6) == 0) {
s.len = names[i].len - 6;
@ -171,24 +173,31 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n)
ngx_memzero(&u, sizeof(ngx_url_t));
u.host = names[i];
u.port = 53;
u.url = names[i];
u.default_port = 53;
if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
if (u.err) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"%s in resolver \"%V\"",
u.err, &u.url);
}
if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V: %s", &u.host, u.err);
return NULL;
}
uc = ngx_array_push(&r->udp_connections);
uc = ngx_array_push_n(&r->udp_connections, u.naddrs);
if (uc == NULL) {
return NULL;
}
ngx_memzero(uc, sizeof(ngx_udp_connection_t));
ngx_memzero(uc, u.naddrs * sizeof(ngx_udp_connection_t));
uc->sockaddr = u.addrs->sockaddr;
uc->socklen = u.addrs->socklen;
uc->server = u.addrs->name;
for (j = 0; j < u.naddrs; j++) {
uc[j].sockaddr = u.addrs[j].sockaddr;
uc[j].socklen = u.addrs[j].socklen;
uc[j].server = u.addrs[j].name;
}
}
return r;
@ -438,8 +447,7 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)
if (naddrs != 1) {
addr = 0;
addrs = ngx_resolver_dup(r, rn->u.addrs,
naddrs * sizeof(in_addr_t));
addrs = ngx_resolver_rotate(r, rn->u.addrs, naddrs);
if (addrs == NULL) {
return NGX_ERROR;
}
@ -513,8 +521,10 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)
/* lock alloc mutex */
ngx_resolver_free_locked(r, rn->query);
rn->query = NULL;
if (rn->query) {
ngx_resolver_free_locked(r, rn->query);
rn->query = NULL;
}
if (rn->cnlen) {
ngx_resolver_free_locked(r, rn->u.cname);
@ -970,12 +980,11 @@ ngx_resolver_resend(ngx_resolver_t *r, ngx_rbtree_t *tree, ngx_queue_t *queue)
if (rn->waiting) {
if (ngx_resolver_send_query(r, rn) == NGX_OK) {
(void) ngx_resolver_send_query(r, rn);
rn->expire = now + r->resend_timeout;
rn->expire = now + r->resend_timeout;
ngx_queue_insert_head(queue, &rn->queue);
}
ngx_queue_insert_head(queue, q);
continue;
}
@ -1033,7 +1042,7 @@ ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf, size_t n)
nan = (query->nan_hi << 8) + query->nan_lo;
ngx_log_debug6(NGX_LOG_DEBUG_CORE, r->log, 0,
"resolver DNS response %ui fl:%04Xui %ui/%ui/%ui/%ui",
"resolver DNS response %ui fl:%04Xui %ui/%ui/%ud/%ud",
ident, flags, nqs, nan,
(query->nns_hi << 8) + query->nns_lo,
(query->nar_hi << 8) + query->nar_lo);
@ -1409,6 +1418,9 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
ngx_resolver_free(r, addrs);
}
ngx_resolver_free(r, rn->query);
rn->query = NULL;
return;
} else if (cname) {
@ -1441,6 +1453,9 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
(void) ngx_resolve_name_locked(r, ctx);
}
ngx_resolver_free(r, rn->query);
rn->query = NULL;
return;
}
@ -1834,6 +1849,10 @@ ngx_resolver_create_name_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx)
p--;
*p-- = '\0';
if (ctx->name.len == 0) {
return NGX_DECLINED;
}
for (s = ctx->name.data + ctx->name.len - 1; s >= ctx->name.data; s--) {
if (*s != '.') {
*p = *s;
@ -2117,6 +2136,32 @@ ngx_resolver_dup(ngx_resolver_t *r, void *src, size_t size)
}
static in_addr_t *
ngx_resolver_rotate(ngx_resolver_t *r, in_addr_t *src, ngx_uint_t n)
{
void *dst, *p;
ngx_uint_t j;
dst = ngx_resolver_alloc(r, n * sizeof(in_addr_t));
if (dst == NULL) {
return dst;
}
j = ngx_random() % n;
if (j == 0) {
ngx_memcpy(dst, src, n * sizeof(in_addr_t));
return dst;
}
p = ngx_cpymem(dst, &src[j], (n - j) * sizeof(in_addr_t));
ngx_memcpy(p, src, j * sizeof(in_addr_t));
return dst;
}
char *
ngx_resolver_strerror(ngx_int_t err)
{
@ -2172,7 +2217,7 @@ ngx_udp_connect(ngx_udp_connection_t *uc)
ngx_socket_t s;
ngx_connection_t *c;
s = ngx_socket(AF_INET, SOCK_DGRAM, 0);
s = ngx_socket(uc->sockaddr->sa_family, SOCK_DGRAM, 0);
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, &uc->log, 0, "UDP socket %d", s);

View File

@ -44,7 +44,7 @@ ngx_shmtx_create(ngx_shmtx_t *mtx, ngx_shmtx_sh_t *addr, u_char *name)
void
ngx_shmtx_destory(ngx_shmtx_t *mtx)
ngx_shmtx_destroy(ngx_shmtx_t *mtx)
{
#if (NGX_HAVE_POSIX_SEM)
@ -117,11 +117,11 @@ ngx_shmtx_lock(ngx_shmtx_t *mtx)
"sem_wait() failed while waiting on shmtx");
break;
}
ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
"shmtx awoke");
}
ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
"shmtx awoke");
continue;
}
@ -208,7 +208,7 @@ ngx_shmtx_create(ngx_shmtx_t *mtx, ngx_shmtx_sh_t *addr, u_char *name)
return NGX_OK;
}
ngx_shmtx_destory(mtx);
ngx_shmtx_destroy(mtx);
}
mtx->fd = ngx_open_file(name, NGX_FILE_RDWR, NGX_FILE_CREATE_OR_OPEN,
@ -232,7 +232,7 @@ ngx_shmtx_create(ngx_shmtx_t *mtx, ngx_shmtx_sh_t *addr, u_char *name)
void
ngx_shmtx_destory(ngx_shmtx_t *mtx)
ngx_shmtx_destroy(ngx_shmtx_t *mtx)
{
if (ngx_close_file(mtx->fd) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno,

View File

@ -39,7 +39,7 @@ typedef struct {
ngx_int_t ngx_shmtx_create(ngx_shmtx_t *mtx, ngx_shmtx_sh_t *addr,
u_char *name);
void ngx_shmtx_destory(ngx_shmtx_t *mtx);
void ngx_shmtx_destroy(ngx_shmtx_t *mtx);
ngx_uint_t ngx_shmtx_trylock(ngx_shmtx_t *mtx);
void ngx_shmtx_lock(ngx_shmtx_t *mtx);
void ngx_shmtx_unlock(ngx_shmtx_t *mtx);

View File

@ -45,9 +45,7 @@
#define ngx_slab_junk(p, size) ngx_memset(p, 0xA5, size)
#else
#if (NGX_HAVE_DEBUG_MALLOC)
#elif (NGX_HAVE_DEBUG_MALLOC)
#define ngx_slab_junk(p, size) \
if (ngx_debug_malloc) ngx_memset(p, 0xA5, size)
@ -58,8 +56,6 @@
#endif
#endif
static ngx_slab_page_t *ngx_slab_alloc_pages(ngx_slab_pool_t *pool,
ngx_uint_t pages);
static void ngx_slab_free_pages(ngx_slab_pool_t *pool, ngx_slab_page_t *page,
@ -166,8 +162,8 @@ ngx_slab_alloc_locked(ngx_slab_pool_t *pool, size_t size)
ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, ngx_cycle->log, 0,
"slab alloc: %uz", size);
page = ngx_slab_alloc_pages(pool, (size + ngx_pagesize - 1)
>> ngx_pagesize_shift);
page = ngx_slab_alloc_pages(pool, (size >> ngx_pagesize_shift)
+ ((size % ngx_pagesize) ? 1 : 0));
if (page) {
p = (page - pool->pages) << ngx_pagesize_shift;
p += (uintptr_t) pool->start;

View File

@ -1827,7 +1827,7 @@ ngx_sort(void *base, size_t n, size_t size,
#if (NGX_MEMCPY_LIMIT)
void *
ngx_memcpy(void *dst, void *src, size_t n)
ngx_memcpy(void *dst, const void *src, size_t n)
{
if (n > NGX_MEMCPY_LIMIT) {
ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, "memcpy %uz bytes", n);

View File

@ -89,7 +89,7 @@ ngx_strlchr(u_char *p, u_char *last, u_char c)
#if (NGX_MEMCPY_LIMIT)
void *ngx_memcpy(void *dst, void *src, size_t n);
void *ngx_memcpy(void *dst, const void *src, size_t n);
#define ngx_cpymem(dst, src, n) (((u_char *) ngx_memcpy(dst, src, n)) + (n))
#else

View File

@ -211,6 +211,10 @@ ngx_time_sigsafe_update(void)
slot++;
}
tp = &cached_time[slot];
tp->sec = 0;
ngx_gmtime(sec + cached_gmtoff * 60, &tm);
p = &cached_err_log_time[slot][0];

View File

@ -44,16 +44,25 @@ struct epoll_event {
epoll_data_t data;
};
int epoll_create(int size);
int epoll_create(int size)
{
return -1;
}
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
{
return -1;
}
int epoll_wait(int epfd, struct epoll_event *events, int nevents, int timeout);
int epoll_wait(int epfd, struct epoll_event *events, int nevents, int timeout)
{
return -1;
@ -76,11 +85,6 @@ struct io_event {
};
int eventfd(u_int initval)
{
return -1;
}
#endif
#endif

View File

@ -15,6 +15,12 @@
#define ushort_t u_short
#define uint_t u_int
#ifndef CLOCK_REALTIME
#define CLOCK_REALTIME 0
typedef int clockid_t;
typedef void * timer_t;
#endif
/* Solaris declarations */
#define PORT_SOURCE_AIO 1
@ -24,7 +30,9 @@
#define PORT_SOURCE_ALERT 5
#define PORT_SOURCE_MQ 6
#ifndef ETIME
#define ETIME 64
#endif
#define SIGEV_PORT 4
@ -50,39 +58,62 @@ typedef struct itimerspec { /* definition per POSIX.4 */
#endif
int port_create(void);
int port_create(void)
{
return -1;
}
int port_associate(int port, int source, uintptr_t object, int events,
void *user);
int port_associate(int port, int source, uintptr_t object, int events,
void *user)
{
return -1;
}
int port_dissociate(int port, int source, uintptr_t object);
int port_dissociate(int port, int source, uintptr_t object)
{
return -1;
}
int port_getn(int port, port_event_t list[], uint_t max, uint_t *nget,
struct timespec *timeout);
int port_getn(int port, port_event_t list[], uint_t max, uint_t *nget,
struct timespec *timeout)
{
return -1;
}
int timer_create(clockid_t clock_id, struct sigevent *evp, timer_t *timerid);
int timer_create(clockid_t clock_id, struct sigevent *evp, timer_t *timerid)
{
return -1;
}
int timer_settime(timer_t timerid, int flags, const struct itimerspec *value,
struct itimerspec *ovalue);
int timer_settime(timer_t timerid, int flags, const struct itimerspec *value,
struct itimerspec *ovalue)
{
return -1;
}
int timer_delete(timer_t timerid);
int timer_delete(timer_t timerid)
{
return -1;

View File

@ -371,7 +371,7 @@ ngx_poll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags)
found = 0;
if (revents & POLLIN) {
if ((revents & POLLIN) && c->read->active) {
found = 1;
ev = c->read;
@ -388,7 +388,7 @@ ngx_poll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags)
ngx_locked_post_event(ev, queue);
}
if (revents & POLLOUT) {
if ((revents & POLLOUT) && c->write->active) {
found = 1;
ev = c->write;

View File

@ -12,6 +12,13 @@
#if (NGX_TEST_BUILD_RTSIG)
#if (NGX_DARWIN)
#define SIGRTMIN 33
#define si_fd __pad[0]
#else
#ifdef SIGRTMIN
#define si_fd _reason.__spare__.__spare2__[0]
#else
@ -19,10 +26,15 @@
#define si_fd __spare__[0]
#endif
#endif
#define F_SETSIG 10
#define KERN_RTSIGNR 30
#define KERN_RTSIGMAX 31
int sigtimedwait(const sigset_t *set, siginfo_t *info,
const struct timespec *timeout);
int sigtimedwait(const sigset_t *set, siginfo_t *info,
const struct timespec *timeout)
{

View File

@ -567,7 +567,7 @@ ngx_event_module_init(ngx_cycle_t *cycle)
#if !(NGX_WIN32)
void
static void
ngx_timer_signal_handler(int signo)
{
ngx_event_timer_alarm = 1;
@ -892,6 +892,10 @@ ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_conf_t pcf;
ngx_event_module_t *m;
if (*(void **) conf) {
return "is duplicate";
}
/* count the number of the event modules and set up their indices */
ngx_event_max_module = 0;
@ -1062,53 +1066,91 @@ ngx_event_debug_connection(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
#if (NGX_DEBUG)
ngx_event_conf_t *ecf = conf;
ngx_int_t rc;
ngx_str_t *value;
ngx_event_debug_t *dc;
struct hostent *h;
ngx_cidr_t cidr;
ngx_int_t rc;
ngx_str_t *value;
ngx_url_t u;
ngx_cidr_t c, *cidr;
ngx_uint_t i;
struct sockaddr_in *sin;
#if (NGX_HAVE_INET6)
struct sockaddr_in6 *sin6;
#endif
value = cf->args->elts;
dc = ngx_array_push(&ecf->debug_connection);
if (dc == NULL) {
return NGX_CONF_ERROR;
}
#if (NGX_HAVE_UNIX_DOMAIN)
rc = ngx_ptocidr(&value[1], &cidr);
if (rc == NGX_DONE) {
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
"low address bits of %V are meaningless", &value[1]);
rc = NGX_OK;
}
if (rc == NGX_OK) {
/* AF_INET only */
if (cidr.family != AF_INET) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"\"debug_connection\" supports IPv4 only");
if (ngx_strcmp(value[1].data, "unix:") == 0) {
cidr = ngx_array_push(&ecf->debug_connection);
if (cidr == NULL) {
return NGX_CONF_ERROR;
}
dc->mask = cidr.u.in.mask;
dc->addr = cidr.u.in.addr;
cidr->family = AF_UNIX;
return NGX_CONF_OK;
}
#endif
rc = ngx_ptocidr(&value[1], &c);
if (rc != NGX_ERROR) {
if (rc == NGX_DONE) {
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
"low address bits of %V are meaningless",
&value[1]);
}
cidr = ngx_array_push(&ecf->debug_connection);
if (cidr == NULL) {
return NGX_CONF_ERROR;
}
*cidr = c;
return NGX_CONF_OK;
}
h = gethostbyname((char *) value[1].data);
ngx_memzero(&u, sizeof(ngx_url_t));
u.host = value[1];
if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) {
if (u.err) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"%s in debug_connection \"%V\"",
u.err, &u.host);
}
if (h == NULL || h->h_addr_list[0] == NULL) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"host \"%s\" not found", value[1].data);
return NGX_CONF_ERROR;
}
dc->mask = 0xffffffff;
dc->addr = *(in_addr_t *)(h->h_addr_list[0]);
cidr = ngx_array_push_n(&ecf->debug_connection, u.naddrs);
if (cidr == NULL) {
return NGX_CONF_ERROR;
}
ngx_memzero(cidr, u.naddrs * sizeof(ngx_cidr_t));
for (i = 0; i < u.naddrs; i++) {
cidr[i].family = u.addrs[i].sockaddr->sa_family;
switch (cidr[i].family) {
#if (NGX_HAVE_INET6)
case AF_INET6:
sin6 = (struct sockaddr_in6 *) u.addrs[i].sockaddr;
cidr[i].u.in6.addr = sin6->sin6_addr;
ngx_memset(cidr[i].u.in6.mask.s6_addr, 0xff, 16);
break;
#endif
default: /* AF_INET */
sin = (struct sockaddr_in *) u.addrs[i].sockaddr;
cidr[i].u.in.addr = sin->sin_addr.s_addr;
cidr[i].u.in.mask = 0xffffffff;
break;
}
}
#else
@ -1142,7 +1184,7 @@ ngx_event_core_create_conf(ngx_cycle_t *cycle)
#if (NGX_DEBUG)
if (ngx_array_init(&ecf->debug_connection, cycle->pool, 4,
sizeof(ngx_event_debug_t)) == NGX_ERROR)
sizeof(ngx_cidr_t)) == NGX_ERROR)
{
return NULL;
}
@ -1176,7 +1218,7 @@ ngx_event_core_init_conf(ngx_cycle_t *cycle, void *conf)
fd = epoll_create(100);
if (fd != -1) {
close(fd);
(void) close(fd);
module = &ngx_epoll_module;
} else if (ngx_errno != NGX_ENOSYS) {

View File

@ -221,12 +221,6 @@ struct ngx_event_aio_s {
#endif
typedef struct {
in_addr_t mask;
in_addr_t addr;
} ngx_event_debug_t;
typedef struct {
ngx_int_t (*add)(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags);
ngx_int_t (*del)(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags);

View File

@ -21,6 +21,7 @@ ngx_event_accept(ngx_event_t *ev)
socklen_t socklen;
ngx_err_t err;
ngx_log_t *log;
ngx_uint_t level;
ngx_socket_t s;
ngx_event_t *rev, *wev;
ngx_listening_t *ls;
@ -31,6 +32,14 @@ ngx_event_accept(ngx_event_t *ev)
static ngx_uint_t use_accept4 = 1;
#endif
if (ev->timedout) {
if (ngx_enable_accept_events((ngx_cycle_t *) ngx_cycle) != NGX_OK) {
return;
}
ev->timedout = 0;
}
ecf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_event_core_module);
if (ngx_event_flags & NGX_USE_RTSIG_EVENT) {
@ -70,10 +79,17 @@ ngx_event_accept(ngx_event_t *ev)
return;
}
level = NGX_LOG_ALERT;
if (err == NGX_ECONNABORTED) {
level = NGX_LOG_ERR;
} else if (err == NGX_EMFILE || err == NGX_ENFILE) {
level = NGX_LOG_CRIT;
}
#if (NGX_HAVE_ACCEPT4)
ngx_log_error((ngx_uint_t) ((err == NGX_ECONNABORTED) ?
NGX_LOG_ERR : NGX_LOG_ALERT),
ev->log, err,
ngx_log_error(level, ev->log, err,
use_accept4 ? "accept4() failed" : "accept() failed");
if (use_accept4 && err == NGX_ENOSYS) {
@ -82,9 +98,7 @@ ngx_event_accept(ngx_event_t *ev)
continue;
}
#else
ngx_log_error((ngx_uint_t) ((err == NGX_ECONNABORTED) ?
NGX_LOG_ERR : NGX_LOG_ALERT),
ev->log, err, "accept() failed");
ngx_log_error(level, ev->log, err, "accept() failed");
#endif
if (err == NGX_ECONNABORTED) {
@ -97,6 +111,26 @@ ngx_event_accept(ngx_event_t *ev)
}
}
if (err == NGX_EMFILE || err == NGX_ENFILE) {
if (ngx_disable_accept_events((ngx_cycle_t *) ngx_cycle)
!= NGX_OK)
{
return;
}
if (ngx_use_accept_mutex) {
if (ngx_accept_mutex_held) {
ngx_shmtx_unlock(&ngx_accept_mutex);
ngx_accept_mutex_held = 0;
}
ngx_accept_disabled = 1;
} else {
ngx_add_timer(ev, ecf->accept_mutex_delay);
}
}
return;
}
@ -252,17 +286,56 @@ ngx_event_accept(ngx_event_t *ev)
#if (NGX_DEBUG)
{
in_addr_t i;
ngx_event_debug_t *dc;
struct sockaddr_in *sin;
struct sockaddr_in *sin;
ngx_cidr_t *cidr;
ngx_uint_t i;
#if (NGX_HAVE_INET6)
struct sockaddr_in6 *sin6;
ngx_uint_t n;
#endif
sin = (struct sockaddr_in *) sa;
dc = ecf->debug_connection.elts;
cidr = ecf->debug_connection.elts;
for (i = 0; i < ecf->debug_connection.nelts; i++) {
if ((sin->sin_addr.s_addr & dc[i].mask) == dc[i].addr) {
log->log_level = NGX_LOG_DEBUG_CONNECTION|NGX_LOG_DEBUG_ALL;
if (cidr[i].family != c->sockaddr->sa_family) {
goto next;
}
switch (cidr[i].family) {
#if (NGX_HAVE_INET6)
case AF_INET6:
sin6 = (struct sockaddr_in6 *) c->sockaddr;
for (n = 0; n < 16; n++) {
if ((sin6->sin6_addr.s6_addr[n]
& cidr[i].u.in6.mask.s6_addr[n])
!= cidr[i].u.in6.addr.s6_addr[n])
{
goto next;
}
}
break;
#endif
#if (NGX_HAVE_UNIX_DOMAIN)
case AF_UNIX:
break;
#endif
default: /* AF_INET */
sin = (struct sockaddr_in *) c->sockaddr;
if ((sin->sin_addr.s_addr & cidr[i].u.in.mask)
!= cidr[i].u.in.addr)
{
goto next;
}
break;
}
log->log_level = NGX_LOG_DEBUG_CONNECTION|NGX_LOG_DEBUG_ALL;
break;
next:
continue;
}
}
@ -344,6 +417,10 @@ ngx_enable_accept_events(ngx_cycle_t *cycle)
c = ls[i].connection;
if (c->read->active) {
continue;
}
if (ngx_event_flags & NGX_USE_RTSIG_EVENT) {
if (ngx_add_conn(c) == NGX_ERROR) {

View File

@ -94,6 +94,26 @@ ngx_ssl_init(ngx_log_t *log)
OpenSSL_add_all_algorithms();
#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
#ifndef SSL_OP_NO_COMPRESSION
{
/*
* Disable gzip compression in OpenSSL prior to 1.0.0 version,
* this saves about 522K per connection.
*/
int n;
STACK_OF(SSL_COMP) *ssl_comp_methods;
ssl_comp_methods = SSL_COMP_get_compression_methods();
n = sk_SSL_COMP_num(ssl_comp_methods);
while (n--) {
(void) sk_SSL_COMP_pop(ssl_comp_methods);
}
}
#endif
#endif
ngx_ssl_connection_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
if (ngx_ssl_connection_index == -1) {
@ -508,10 +528,10 @@ ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name)
return NGX_ERROR;
}
SSL_CTX_set_tmp_ecdh(ssl->ctx, ecdh);
SSL_CTX_set_options(ssl->ctx, SSL_OP_SINGLE_ECDH_USE);
SSL_CTX_set_tmp_ecdh(ssl->ctx, ecdh);
EC_KEY_free(ecdh);
#endif
#endif
@ -673,6 +693,10 @@ ngx_ssl_handshake(ngx_connection_t *c)
return NGX_ERROR;
}
if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
return NGX_ERROR;
}
return NGX_AGAIN;
}
@ -681,6 +705,10 @@ ngx_ssl_handshake(ngx_connection_t *c)
c->read->handler = ngx_ssl_handshake_handler;
c->write->handler = ngx_ssl_handshake_handler;
if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
return NGX_ERROR;
}
if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
return NGX_ERROR;
}
@ -990,11 +1018,11 @@ ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
}
if (n == NGX_AGAIN) {
c->buffered |= NGX_SSL_BUFFERED;
return in;
}
in->buf->pos += n;
c->sent += n;
if (in->buf->pos == in->buf->last) {
in = in->next;
@ -1033,8 +1061,8 @@ ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
buf->end = buf->start + NGX_SSL_BUFSIZE;
}
send = 0;
flush = (in == NULL) ? 1 : 0;
send = buf->last - buf->pos;
flush = (in == NULL) ? 1 : buf->flush;
for ( ;; ) {
@ -1056,7 +1084,6 @@ ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
if (send + size > limit) {
size = (ssize_t) (limit - send);
flush = 1;
}
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
@ -1073,10 +1100,16 @@ ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
}
}
if (!flush && send < limit && buf->last < buf->end) {
break;
}
size = buf->last - buf->pos;
if (!flush && buf->last < buf->end && c->ssl->buffer) {
break;
if (size == 0) {
buf->flush = 0;
c->buffered &= ~NGX_SSL_BUFFERED;
return in;
}
n = ngx_ssl_write(c, buf->pos, size);
@ -1086,8 +1119,7 @@ ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
}
if (n == NGX_AGAIN) {
c->buffered |= NGX_SSL_BUFFERED;
return in;
break;
}
buf->pos += n;
@ -1097,16 +1129,18 @@ ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
break;
}
if (buf->pos == buf->last) {
buf->pos = buf->start;
buf->last = buf->start;
}
flush = 0;
buf->pos = buf->start;
buf->last = buf->start;
if (in == NULL || send == limit) {
break;
}
}
buf->flush = flush;
if (buf->pos < buf->last) {
c->buffered |= NGX_SSL_BUFFERED;
@ -1682,8 +1716,18 @@ ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess)
}
sess_id = ngx_slab_alloc_locked(shpool, sizeof(ngx_ssl_sess_id_t));
if (sess_id == NULL) {
goto failed;
/* drop the oldest non-expired session and try once more */
ngx_ssl_expire_sessions(cache, shpool, 0);
sess_id = ngx_slab_alloc_locked(shpool, sizeof(ngx_ssl_sess_id_t));
if (sess_id == NULL) {
goto failed;
}
}
#if (NGX_PTR_SIZE == 8)
@ -1693,8 +1737,18 @@ ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess)
#else
id = ngx_slab_alloc_locked(shpool, sess->session_id_length);
if (id == NULL) {
goto failed;
/* drop the oldest non-expired session and try once more */
ngx_ssl_expire_sessions(cache, shpool, 0);
id = ngx_slab_alloc_locked(shpool, sess->session_id_length);
if (id == NULL) {
goto failed;
}
}
#endif

View File

@ -120,6 +120,13 @@ ngx_int_t ngx_ssl_set_session(ngx_connection_t *c, ngx_ssl_session_t *session);
#define ngx_ssl_get_server_conf(ssl_ctx) \
SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_server_conf_index)
#define ngx_ssl_verify_error_optional(n) \
(n == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT \
|| n == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN \
|| n == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY \
|| n == X509_V_ERR_CERT_UNTRUSTED \
|| n == X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE)
ngx_int_t ngx_ssl_get_protocol(ngx_connection_t *c, ngx_pool_t *pool,
ngx_str_t *s);

View File

@ -946,8 +946,15 @@ ngx_event_pipe_add_free_buf(ngx_event_pipe_t *p, ngx_buf_t *b)
return NGX_ERROR;
}
b->pos = b->start;
b->last = b->start;
if (p->buf_to_file && b->start == p->buf_to_file->start) {
b->pos = p->buf_to_file->last;
b->last = p->buf_to_file->last;
} else {
b->pos = b->start;
b->last = b->start;
}
b->shadow = NULL;
cl->buf = b;

View File

@ -20,8 +20,8 @@ typedef struct {
typedef struct {
ngx_str_t realm;
ngx_http_complex_value_t user_file;
ngx_http_complex_value_t *realm;
ngx_http_complex_value_t user_file;
} ngx_http_auth_basic_loc_conf_t;
@ -35,22 +35,19 @@ static void *ngx_http_auth_basic_create_loc_conf(ngx_conf_t *cf);
static char *ngx_http_auth_basic_merge_loc_conf(ngx_conf_t *cf,
void *parent, void *child);
static ngx_int_t ngx_http_auth_basic_init(ngx_conf_t *cf);
static char *ngx_http_auth_basic(ngx_conf_t *cf, void *post, void *data);
static char *ngx_http_auth_basic_user_file(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static ngx_conf_post_handler_pt ngx_http_auth_basic_p = ngx_http_auth_basic;
static ngx_command_t ngx_http_auth_basic_commands[] = {
{ ngx_string("auth_basic"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF
|NGX_CONF_TAKE1,
ngx_conf_set_str_slot,
ngx_http_set_complex_value_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_auth_basic_loc_conf_t, realm),
&ngx_http_auth_basic_p },
NULL },
{ ngx_string("auth_basic_user_file"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF
@ -103,7 +100,7 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r)
ngx_fd_t fd;
ngx_int_t rc;
ngx_err_t err;
ngx_str_t pwd, user_file;
ngx_str_t pwd, realm, user_file;
ngx_uint_t i, level, login, left, passwd;
ngx_file_t file;
ngx_http_auth_basic_ctx_t *ctx;
@ -117,7 +114,15 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r)
alcf = ngx_http_get_module_loc_conf(r, ngx_http_auth_basic_module);
if (alcf->realm.len == 0 || alcf->user_file.value.len == 0) {
if (alcf->realm == NULL || alcf->user_file.value.data == NULL) {
return NGX_DECLINED;
}
if (ngx_http_complex_value(r, alcf->realm, &realm) != NGX_OK) {
return NGX_ERROR;
}
if (realm.len == 3 && ngx_strncmp(realm.data, "off", 3) == 0) {
return NGX_DECLINED;
}
@ -125,7 +130,7 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r)
if (ctx) {
return ngx_http_auth_basic_crypt_handler(r, ctx, &ctx->passwd,
&alcf->realm);
&realm);
}
rc = ngx_http_auth_basic_user(r);
@ -135,7 +140,7 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r)
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"no user/password was provided for basic authentication");
return ngx_http_auth_basic_set_realm(r, &alcf->realm);
return ngx_http_auth_basic_set_realm(r, &realm);
}
if (rc == NGX_ERROR) {
@ -233,7 +238,7 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r)
pwd.data = &buf[passwd];
return ngx_http_auth_basic_crypt_handler(r, NULL, &pwd,
&alcf->realm);
&realm);
}
break;
@ -271,14 +276,14 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r)
ngx_cpystrn(pwd.data, &buf[passwd], pwd.len + 1);
return ngx_http_auth_basic_crypt_handler(r, NULL, &pwd, &alcf->realm);
return ngx_http_auth_basic_crypt_handler(r, NULL, &pwd, &realm);
}
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"user \"%V\" was not found in \"%V\"",
&r->headers_in.user, &user_file);
return ngx_http_auth_basic_set_realm(r, &alcf->realm);
return ngx_http_auth_basic_set_realm(r, &realm);
}
@ -344,14 +349,29 @@ ngx_http_auth_basic_crypt_handler(ngx_http_request_t *r,
static ngx_int_t
ngx_http_auth_basic_set_realm(ngx_http_request_t *r, ngx_str_t *realm)
{
size_t len;
u_char *basic, *p;
r->headers_out.www_authenticate = ngx_list_push(&r->headers_out.headers);
if (r->headers_out.www_authenticate == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
len = sizeof("Basic realm=\"\"") - 1 + realm->len;
basic = ngx_pnalloc(r->pool, len);
if (basic == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
p = ngx_cpymem(basic, "Basic realm=\"", sizeof("Basic realm=\"") - 1);
p = ngx_cpymem(p, realm->data, realm->len);
*p = '"';
r->headers_out.www_authenticate->hash = 1;
ngx_str_set(&r->headers_out.www_authenticate->key, "WWW-Authenticate");
r->headers_out.www_authenticate->value = *realm;
r->headers_out.www_authenticate->value.data = basic;
r->headers_out.www_authenticate->value.len = len;
return NGX_HTTP_UNAUTHORIZED;
}
@ -386,11 +406,11 @@ ngx_http_auth_basic_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_http_auth_basic_loc_conf_t *prev = parent;
ngx_http_auth_basic_loc_conf_t *conf = child;
if (conf->realm.data == NULL) {
if (conf->realm == NULL) {
conf->realm = prev->realm;
}
if (conf->user_file.value.len == 0) {
if (conf->user_file.value.data == NULL) {
conf->user_file = prev->user_file;
}
@ -417,37 +437,6 @@ ngx_http_auth_basic_init(ngx_conf_t *cf)
}
static char *
ngx_http_auth_basic(ngx_conf_t *cf, void *post, void *data)
{
ngx_str_t *realm = data;
size_t len;
u_char *basic, *p;
if (ngx_strcmp(realm->data, "off") == 0) {
ngx_str_set(realm, "");
return NGX_CONF_OK;
}
len = sizeof("Basic realm=\"") - 1 + realm->len + 1;
basic = ngx_pnalloc(cf->pool, len);
if (basic == NULL) {
return NGX_CONF_ERROR;
}
p = ngx_cpymem(basic, "Basic realm=\"", sizeof("Basic realm=\"") - 1);
p = ngx_cpymem(p, realm->data, realm->len);
*p = '"';
realm->len = len;
realm->data = basic;
return NGX_CONF_OK;
}
static char *
ngx_http_auth_basic_user_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
@ -456,7 +445,7 @@ ngx_http_auth_basic_user_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_str_t *value;
ngx_http_compile_complex_value_t ccv;
if (alcf->user_file.value.len) {
if (alcf->user_file.value.data) {
return "is duplicate";
}

View File

@ -489,8 +489,11 @@ ngx_http_autoindex_handler(ngx_http_request_t *r)
}
b->last = ngx_cpymem(b->last, "</a>", sizeof("</a>") - 1);
ngx_memset(b->last, ' ', NGX_HTTP_AUTOINDEX_NAME_LEN - len);
b->last += NGX_HTTP_AUTOINDEX_NAME_LEN - len;
if (NGX_HTTP_AUTOINDEX_NAME_LEN - len > 0) {
ngx_memset(b->last, ' ', NGX_HTTP_AUTOINDEX_NAME_LEN - len);
b->last += NGX_HTTP_AUTOINDEX_NAME_LEN - len;
}
}
*b->last++ = ' ';

View File

@ -209,6 +209,11 @@ ngx_http_dav_put_handler(ngx_http_request_t *r)
ngx_ext_rename_file_t ext;
ngx_http_dav_loc_conf_t *dlcf;
if (r->request_body == NULL || r->request_body->temp_file == NULL) {
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
return;
}
ngx_http_map_uri_to_path(r, &path, &root, 0);
path.len--;

View File

@ -619,6 +619,7 @@ ngx_http_fastcgi_handler(ngx_http_request_t *r)
u->process_header = ngx_http_fastcgi_process_header;
u->abort_request = ngx_http_fastcgi_abort_request;
u->finalize_request = ngx_http_fastcgi_finalize_request;
r->state = 0;
u->buffering = 1;
@ -1194,6 +1195,8 @@ ngx_http_fastcgi_reinit_request(ngx_http_request_t *r)
f->fastcgi_stdout = 0;
f->large_stderr = 0;
r->state = 0;
return NGX_OK;
}
@ -1353,7 +1356,7 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r)
}
} else {
f->state = ngx_http_fastcgi_st_version;
f->state = ngx_http_fastcgi_st_padding;
}
continue;
@ -1590,11 +1593,7 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r)
f->length -= u->buffer.pos - start;
if (f->length == 0) {
if (f->padding) {
f->state = ngx_http_fastcgi_st_padding;
} else {
f->state = ngx_http_fastcgi_st_version;
}
f->state = ngx_http_fastcgi_st_padding;
}
if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
@ -1619,6 +1618,9 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r)
}
part = ngx_array_push(f->split_parts);
if (part == NULL) {
return NGX_ERROR;
}
part->start = part_start;
part->end = part_end;
@ -1686,7 +1688,7 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
}
if (f->type == NGX_HTTP_FASTCGI_STDOUT && f->length == 0) {
f->state = ngx_http_fastcgi_st_version;
f->state = ngx_http_fastcgi_st_padding;
if (!flcf->keep_conn) {
p->upstream_done = 1;
@ -1699,23 +1701,40 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
}
if (f->type == NGX_HTTP_FASTCGI_END_REQUEST) {
f->state = ngx_http_fastcgi_st_version;
p->upstream_done = 1;
if (flcf->keep_conn) {
r->upstream->keepalive = 1;
}
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
"http fastcgi sent end request");
break;
if (!flcf->keep_conn) {
p->upstream_done = 1;
break;
}
continue;
}
}
if (f->state == ngx_http_fastcgi_st_padding) {
if (f->type == NGX_HTTP_FASTCGI_END_REQUEST) {
if (f->pos + f->padding < f->last) {
p->upstream_done = 1;
break;
}
if (f->pos + f->padding == f->last) {
p->upstream_done = 1;
r->upstream->keepalive = 1;
break;
}
f->padding -= f->last - f->pos;
break;
}
if (f->pos + f->padding < f->last) {
f->state = ngx_http_fastcgi_st_version;
f->pos += f->padding;
@ -1767,17 +1786,27 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
"FastCGI sent in stderr: \"%*s\"",
m + 1 - msg, msg);
if (f->pos == f->last) {
break;
}
} else {
f->state = ngx_http_fastcgi_st_version;
f->state = ngx_http_fastcgi_st_padding;
}
continue;
}
if (f->type == NGX_HTTP_FASTCGI_END_REQUEST) {
if (f->pos + f->length <= f->last) {
f->state = ngx_http_fastcgi_st_padding;
f->pos += f->length;
continue;
}
f->length -= f->last - f->pos;
break;
}
/* f->type == NGX_HTTP_FASTCGI_STDOUT */
@ -1831,33 +1860,14 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, p->log, 0,
"input buf #%d %p", b->num, b->pos);
if (f->pos + f->length < f->last) {
if (f->padding) {
f->state = ngx_http_fastcgi_st_padding;
} else {
f->state = ngx_http_fastcgi_st_version;
}
if (f->pos + f->length <= f->last) {
f->state = ngx_http_fastcgi_st_padding;
f->pos += f->length;
b->last = f->pos;
continue;
}
if (f->pos + f->length == f->last) {
if (f->padding) {
f->state = ngx_http_fastcgi_st_padding;
} else {
f->state = ngx_http_fastcgi_st_version;
}
b->last = f->last;
break;
}
f->length -= f->last - f->pos;
b->last = f->last;
@ -2989,7 +2999,7 @@ ngx_http_fastcgi_cache_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
value = cf->args->elts;
if (flcf->cache_key.value.len) {
if (flcf->cache_key.value.data) {
return "is duplicate";
}

View File

@ -235,7 +235,7 @@ ngx_http_flv_handler(ngx_http_request_t *r)
b->file_last = of.size;
b->in_file = b->file_last ? 1: 0;
b->last_buf = 1;
b->last_buf = (r == r->main) ? 1 : 0;
b->last_in_chain = 1;
b->file->fd = of.fd;

View File

@ -17,6 +17,14 @@ typedef struct {
} ngx_http_geo_range_t;
typedef struct {
ngx_radix_tree_t *tree;
#if (NGX_HAVE_INET6)
ngx_radix_tree_t *tree6;
#endif
} ngx_http_geo_trees_t;
typedef struct {
ngx_http_geo_range_t **low;
ngx_http_variable_value_t *default_value;
@ -35,6 +43,9 @@ typedef struct {
ngx_str_t *net;
ngx_http_geo_high_ranges_t high;
ngx_radix_tree_t *tree;
#if (NGX_HAVE_INET6)
ngx_radix_tree_t *tree6;
#endif
ngx_rbtree_t rbtree;
ngx_rbtree_node_t sentinel;
ngx_array_t *proxies;
@ -51,25 +62,27 @@ typedef struct {
unsigned outside_entries:1;
unsigned allow_binary_include:1;
unsigned binary_include:1;
unsigned proxy_recursive:1;
} ngx_http_geo_conf_ctx_t;
typedef struct {
union {
ngx_radix_tree_t *tree;
ngx_http_geo_trees_t trees;
ngx_http_geo_high_ranges_t high;
} u;
ngx_array_t *proxies;
unsigned proxy_recursive:1;
ngx_int_t index;
} ngx_http_geo_ctx_t;
static in_addr_t ngx_http_geo_addr(ngx_http_request_t *r,
ngx_http_geo_ctx_t *ctx);
static in_addr_t ngx_http_geo_real_addr(ngx_http_request_t *r,
ngx_http_geo_ctx_t *ctx);
static ngx_int_t ngx_http_geo_addr(ngx_http_request_t *r,
ngx_http_geo_ctx_t *ctx, ngx_addr_t *addr);
static ngx_int_t ngx_http_geo_real_addr(ngx_http_request_t *r,
ngx_http_geo_ctx_t *ctx, ngx_addr_t *addr);
static char *ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static char *ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf);
static char *ngx_http_geo_range(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
@ -80,6 +93,8 @@ static ngx_uint_t ngx_http_geo_delete_range(ngx_conf_t *cf,
ngx_http_geo_conf_ctx_t *ctx, in_addr_t start, in_addr_t end);
static char *ngx_http_geo_cidr(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
ngx_str_t *value);
static char *ngx_http_geo_cidr_add(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
ngx_cidr_t *cidr, ngx_str_t *value, ngx_str_t *net);
static ngx_http_variable_value_t *ngx_http_geo_value(ngx_conf_t *cf,
ngx_http_geo_conf_ctx_t *ctx, ngx_str_t *value);
static char *ngx_http_geo_add_proxy(ngx_conf_t *cf,
@ -143,7 +158,7 @@ typedef struct {
u_char GEORNG[6];
u_char version;
u_char ptr_size;
uint32_t endianess;
uint32_t endianness;
uint32_t crc32;
} ngx_http_geo_header_t;
@ -153,7 +168,7 @@ static ngx_http_geo_header_t ngx_http_geo_header = {
};
/* AF_INET only */
/* geo range is AF_INET only */
static ngx_int_t
ngx_http_geo_cidr_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
@ -161,10 +176,56 @@ ngx_http_geo_cidr_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
{
ngx_http_geo_ctx_t *ctx = (ngx_http_geo_ctx_t *) data;
in_addr_t inaddr;
ngx_addr_t addr;
struct sockaddr_in *sin;
ngx_http_variable_value_t *vv;
#if (NGX_HAVE_INET6)
u_char *p;
struct in6_addr *inaddr6;
#endif
vv = (ngx_http_variable_value_t *)
ngx_radix32tree_find(ctx->u.tree, ngx_http_geo_addr(r, ctx));
if (ngx_http_geo_addr(r, ctx, &addr) != NGX_OK) {
vv = (ngx_http_variable_value_t *)
ngx_radix32tree_find(ctx->u.trees.tree, INADDR_NONE);
goto done;
}
switch (addr.sockaddr->sa_family) {
#if (NGX_HAVE_INET6)
case AF_INET6:
inaddr6 = &((struct sockaddr_in6 *) addr.sockaddr)->sin6_addr;
p = inaddr6->s6_addr;
if (IN6_IS_ADDR_V4MAPPED(inaddr6)) {
inaddr = p[12] << 24;
inaddr += p[13] << 16;
inaddr += p[14] << 8;
inaddr += p[15];
vv = (ngx_http_variable_value_t *)
ngx_radix32tree_find(ctx->u.trees.tree, inaddr);
} else {
vv = (ngx_http_variable_value_t *)
ngx_radix128tree_find(ctx->u.trees.tree6, p);
}
break;
#endif
default: /* AF_INET */
sin = (struct sockaddr_in *) addr.sockaddr;
inaddr = ntohl(sin->sin_addr.s_addr);
vv = (ngx_http_variable_value_t *)
ngx_radix32tree_find(ctx->u.trees.tree, inaddr);
break;
}
done:
*v = *vv;
@ -181,25 +242,65 @@ ngx_http_geo_range_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
{
ngx_http_geo_ctx_t *ctx = (ngx_http_geo_ctx_t *) data;
in_addr_t addr;
in_addr_t inaddr;
ngx_addr_t addr;
ngx_uint_t n;
struct sockaddr_in *sin;
ngx_http_geo_range_t *range;
#if (NGX_HAVE_INET6)
u_char *p;
struct in6_addr *inaddr6;
#endif
*v = *ctx->u.high.default_value;
addr = ngx_http_geo_addr(r, ctx);
if (ngx_http_geo_addr(r, ctx, &addr) == NGX_OK) {
range = ctx->u.high.low[addr >> 16];
switch (addr.sockaddr->sa_family) {
if (range) {
n = addr & 0xffff;
do {
if (n >= (ngx_uint_t) range->start && n <= (ngx_uint_t) range->end)
{
*v = *range->value;
break;
#if (NGX_HAVE_INET6)
case AF_INET6:
inaddr6 = &((struct sockaddr_in6 *) addr.sockaddr)->sin6_addr;
if (IN6_IS_ADDR_V4MAPPED(inaddr6)) {
p = inaddr6->s6_addr;
inaddr = p[12] << 24;
inaddr += p[13] << 16;
inaddr += p[14] << 8;
inaddr += p[15];
} else {
inaddr = INADDR_NONE;
}
} while ((++range)->value);
break;
#endif
default: /* AF_INET */
sin = (struct sockaddr_in *) addr.sockaddr;
inaddr = ntohl(sin->sin_addr.s_addr);
break;
}
} else {
inaddr = INADDR_NONE;
}
if (ctx->u.high.low) {
range = ctx->u.high.low[inaddr >> 16];
if (range) {
n = inaddr & 0xffff;
do {
if (n >= (ngx_uint_t) range->start
&& n <= (ngx_uint_t) range->end)
{
*v = *range->value;
break;
}
} while ((++range)->value);
}
}
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
@ -209,90 +310,43 @@ ngx_http_geo_range_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
}
static in_addr_t
ngx_http_geo_addr(ngx_http_request_t *r, ngx_http_geo_ctx_t *ctx)
static ngx_int_t
ngx_http_geo_addr(ngx_http_request_t *r, ngx_http_geo_ctx_t *ctx,
ngx_addr_t *addr)
{
u_char *p, *ip;
size_t len;
in_addr_t addr;
ngx_uint_t i, n;
ngx_in_cidr_t *proxies;
ngx_table_elt_t *xfwd;
addr = ngx_http_geo_real_addr(r, ctx);
if (ngx_http_geo_real_addr(r, ctx, addr) != NGX_OK) {
return NGX_ERROR;
}
xfwd = r->headers_in.x_forwarded_for;
if (xfwd == NULL || ctx->proxies == NULL) {
return addr;
if (xfwd != NULL && ctx->proxies != NULL) {
(void) ngx_http_get_forwarded_addr(r, addr, xfwd->value.data,
xfwd->value.len, ctx->proxies,
ctx->proxy_recursive);
}
proxies = ctx->proxies->elts;
n = ctx->proxies->nelts;
for (i = 0; i < n; i++) {
if ((addr & proxies[i].mask) == proxies[i].addr) {
len = xfwd->value.len;
ip = xfwd->value.data;
for (p = ip + len - 1; p > ip; p--) {
if (*p == ' ' || *p == ',') {
p++;
len -= p - ip;
ip = p;
break;
}
}
return ntohl(ngx_inet_addr(ip, len));
}
}
return addr;
return NGX_OK;
}
static in_addr_t
ngx_http_geo_real_addr(ngx_http_request_t *r, ngx_http_geo_ctx_t *ctx)
static ngx_int_t
ngx_http_geo_real_addr(ngx_http_request_t *r, ngx_http_geo_ctx_t *ctx,
ngx_addr_t *addr)
{
struct sockaddr_in *sin;
ngx_http_variable_value_t *v;
#if (NGX_HAVE_INET6)
u_char *p;
in_addr_t addr;
struct sockaddr_in6 *sin6;
#endif
if (ctx->index == -1) {
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http geo started: %V", &r->connection->addr_text);
switch (r->connection->sockaddr->sa_family) {
addr->sockaddr = r->connection->sockaddr;
addr->socklen = r->connection->socklen;
/* addr->name = r->connection->addr_text; */
case AF_INET:
sin = (struct sockaddr_in *) r->connection->sockaddr;
return ntohl(sin->sin_addr.s_addr);
#if (NGX_HAVE_INET6)
case AF_INET6:
sin6 = (struct sockaddr_in6 *) r->connection->sockaddr;
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
p = sin6->sin6_addr.s6_addr;
addr = p[12] << 24;
addr += p[13] << 16;
addr += p[14] << 8;
addr += p[15];
return addr;
}
#endif
}
return INADDR_NONE;
return NGX_OK;
}
v = ngx_http_get_flushed_variable(r, ctx->index);
@ -301,13 +355,17 @@ ngx_http_geo_real_addr(ngx_http_request_t *r, ngx_http_geo_ctx_t *ctx)
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http geo not found");
return 0;
return NGX_ERROR;
}
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http geo started: %v", v);
return ntohl(ngx_inet_addr(v->data, v->len));
if (ngx_parse_addr(r->pool, addr, v->data, v->len) == NGX_OK) {
return NGX_OK;
}
return NGX_ERROR;
}
@ -315,7 +373,6 @@ static char *
ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
char *rv;
void **p;
size_t len;
ngx_str_t *value, name;
ngx_uint_t i;
@ -325,6 +382,9 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_http_variable_t *var;
ngx_http_geo_ctx_t *geo;
ngx_http_geo_conf_ctx_t ctx;
#if (NGX_HAVE_INET6)
static struct in6_addr zero;
#endif
value = cf->args->elts;
@ -334,6 +394,13 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
name = value[1];
if (name.data[0] != '$') {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid variable name \"%V\"", &name);
return NGX_CONF_ERROR;
}
name.len--;
name.data++;
@ -345,6 +412,13 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
name = value[2];
if (name.data[0] != '$') {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid variable name \"%V\"", &name);
return NGX_CONF_ERROR;
}
name.len--;
name.data++;
@ -388,10 +462,11 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
*cf = save;
geo->proxies = ctx.proxies;
geo->proxy_recursive = ctx.proxy_recursive;
if (ctx.high.low) {
if (ctx.ranges) {
if (!ctx.binary_include) {
if (ctx.high.low && !ctx.binary_include) {
for (i = 0; i < 0x10000; i++) {
a = (ngx_array_t *) ctx.high.low[i];
@ -406,8 +481,8 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
p = (void **) ngx_cpymem(ctx.high.low[i], a->elts, len);
*p = NULL;
ngx_memcpy(ctx.high.low[i], a->elts, len);
ctx.high.low[i][a->nelts].value = NULL;
ctx.data_size += len + sizeof(void *);
}
@ -420,15 +495,15 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
}
if (ctx.high.default_value == NULL) {
ctx.high.default_value = &ngx_http_variable_null_value;
}
geo->u.high = ctx.high;
var->get_handler = ngx_http_geo_range_variable;
var->data = (uintptr_t) geo;
if (ctx.high.default_value == NULL) {
ctx.high.default_value = &ngx_http_variable_null_value;
}
ngx_destroy_pool(ctx.temp_pool);
ngx_destroy_pool(pool);
@ -440,7 +515,18 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
}
geo->u.tree = ctx.tree;
geo->u.trees.tree = ctx.tree;
#if (NGX_HAVE_INET6)
if (ctx.tree6 == NULL) {
ctx.tree6 = ngx_radix_tree_create(cf->pool, -1);
if (ctx.tree6 == NULL) {
return NGX_CONF_ERROR;
}
}
geo->u.trees.tree6 = ctx.tree6;
#endif
var->get_handler = ngx_http_geo_cidr_variable;
var->data = (uintptr_t) geo;
@ -448,16 +534,23 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_destroy_pool(ctx.temp_pool);
ngx_destroy_pool(pool);
if (ngx_radix32tree_find(ctx.tree, 0) != NGX_RADIX_NO_VALUE) {
return rv;
}
if (ngx_radix32tree_insert(ctx.tree, 0, 0,
(uintptr_t) &ngx_http_variable_null_value)
== NGX_ERROR)
{
return NGX_CONF_ERROR;
}
/* NGX_BUSY is okay (default was set explicitly) */
#if (NGX_HAVE_INET6)
if (ngx_radix128tree_insert(ctx.tree6, zero.s6_addr, zero.s6_addr,
(uintptr_t) &ngx_http_variable_null_value)
== NGX_ERROR)
{
return NGX_CONF_ERROR;
}
#endif
}
return rv;
@ -480,7 +573,12 @@ ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
if (ngx_strcmp(value[0].data, "ranges") == 0) {
if (ctx->tree) {
if (ctx->tree
#if (NGX_HAVE_INET6)
|| ctx->tree6
#endif
)
{
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"the \"ranges\" directive must be "
"the first directive inside \"geo\" block");
@ -493,6 +591,12 @@ ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
goto done;
}
else if (ngx_strcmp(value[0].data, "proxy_recursive") == 0) {
ctx->proxy_recursive = 1;
rv = NGX_CONF_OK;
goto done;
}
}
if (cf->args->nelts != 2) {
@ -912,11 +1016,10 @@ static char *
ngx_http_geo_cidr(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
ngx_str_t *value)
{
ngx_int_t rc, del;
ngx_str_t *net;
ngx_uint_t i;
ngx_cidr_t cidr;
ngx_http_variable_value_t *val, *old;
char *rv;
ngx_int_t rc, del;
ngx_str_t *net;
ngx_cidr_t cidr;
if (ctx->tree == NULL) {
ctx->tree = ngx_radix_tree_create(ctx->pool, -1);
@ -925,47 +1028,108 @@ ngx_http_geo_cidr(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
}
}
if (ngx_strcmp(value[0].data, "default") == 0) {
cidr.u.in.addr = 0;
cidr.u.in.mask = 0;
net = &value[0];
} else {
if (ngx_strcmp(value[0].data, "delete") == 0) {
net = &value[1];
del = 1;
} else {
net = &value[0];
del = 0;
}
if (ngx_http_geo_cidr_value(cf, net, &cidr) != NGX_OK) {
#if (NGX_HAVE_INET6)
if (ctx->tree6 == NULL) {
ctx->tree6 = ngx_radix_tree_create(ctx->pool, -1);
if (ctx->tree6 == NULL) {
return NGX_CONF_ERROR;
}
}
#endif
if (del) {
if (ngx_radix32tree_delete(ctx->tree, cidr.u.in.addr,
cidr.u.in.mask)
!= NGX_OK)
{
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
"no network \"%V\" to delete", net);
}
if (ngx_strcmp(value[0].data, "default") == 0) {
cidr.family = AF_INET;
cidr.u.in.addr = 0;
cidr.u.in.mask = 0;
return NGX_CONF_OK;
rv = ngx_http_geo_cidr_add(cf, ctx, &cidr, &value[1], &value[0]);
if (rv != NGX_CONF_OK) {
return rv;
}
#if (NGX_HAVE_INET6)
cidr.family = AF_INET6;
ngx_memzero(&cidr.u.in6, sizeof(ngx_in6_cidr_t));
rv = ngx_http_geo_cidr_add(cf, ctx, &cidr, &value[1], &value[0]);
if (rv != NGX_CONF_OK) {
return rv;
}
#endif
return NGX_CONF_OK;
}
val = ngx_http_geo_value(cf, ctx, &value[1]);
if (ngx_strcmp(value[0].data, "delete") == 0) {
net = &value[1];
del = 1;
} else {
net = &value[0];
del = 0;
}
if (ngx_http_geo_cidr_value(cf, net, &cidr) != NGX_OK) {
return NGX_CONF_ERROR;
}
if (cidr.family == AF_INET) {
cidr.u.in.addr = ntohl(cidr.u.in.addr);
cidr.u.in.mask = ntohl(cidr.u.in.mask);
}
if (del) {
switch (cidr.family) {
#if (NGX_HAVE_INET6)
case AF_INET6:
rc = ngx_radix128tree_delete(ctx->tree6,
cidr.u.in6.addr.s6_addr,
cidr.u.in6.mask.s6_addr);
break;
#endif
default: /* AF_INET */
rc = ngx_radix32tree_delete(ctx->tree, cidr.u.in.addr,
cidr.u.in.mask);
break;
}
if (rc != NGX_OK) {
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
"no network \"%V\" to delete", net);
}
return NGX_CONF_OK;
}
return ngx_http_geo_cidr_add(cf, ctx, &cidr, &value[1], net);
}
static char *
ngx_http_geo_cidr_add(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
ngx_cidr_t *cidr, ngx_str_t *value, ngx_str_t *net)
{
ngx_int_t rc;
ngx_http_variable_value_t *val, *old;
val = ngx_http_geo_value(cf, ctx, value);
if (val == NULL) {
return NGX_CONF_ERROR;
}
for (i = 2; i; i--) {
rc = ngx_radix32tree_insert(ctx->tree, cidr.u.in.addr, cidr.u.in.mask,
(uintptr_t) val);
switch (cidr->family) {
#if (NGX_HAVE_INET6)
case AF_INET6:
rc = ngx_radix128tree_insert(ctx->tree6, cidr->u.in6.addr.s6_addr,
cidr->u.in6.mask.s6_addr,
(uintptr_t) val);
if (rc == NGX_OK) {
return NGX_CONF_OK;
}
@ -977,18 +1141,66 @@ ngx_http_geo_cidr(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
/* rc == NGX_BUSY */
old = (ngx_http_variable_value_t *)
ngx_radix32tree_find(ctx->tree, cidr.u.in.addr & cidr.u.in.mask);
ngx_radix128tree_find(ctx->tree6,
cidr->u.in6.addr.s6_addr);
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
"duplicate network \"%V\", value: \"%v\", old value: \"%v\"",
net, val, old);
"duplicate network \"%V\", value: \"%v\", old value: \"%v\"",
net, val, old);
rc = ngx_radix32tree_delete(ctx->tree, cidr.u.in.addr, cidr.u.in.mask);
rc = ngx_radix128tree_delete(ctx->tree6,
cidr->u.in6.addr.s6_addr,
cidr->u.in6.mask.s6_addr);
if (rc == NGX_ERROR) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid radix tree");
return NGX_CONF_ERROR;
}
rc = ngx_radix128tree_insert(ctx->tree6, cidr->u.in6.addr.s6_addr,
cidr->u.in6.mask.s6_addr,
(uintptr_t) val);
break;
#endif
default: /* AF_INET */
rc = ngx_radix32tree_insert(ctx->tree, cidr->u.in.addr,
cidr->u.in.mask, (uintptr_t) val);
if (rc == NGX_OK) {
return NGX_CONF_OK;
}
if (rc == NGX_ERROR) {
return NGX_CONF_ERROR;
}
/* rc == NGX_BUSY */
old = (ngx_http_variable_value_t *)
ngx_radix32tree_find(ctx->tree, cidr->u.in.addr);
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
"duplicate network \"%V\", value: \"%v\", old value: \"%v\"",
net, val, old);
rc = ngx_radix32tree_delete(ctx->tree,
cidr->u.in.addr, cidr->u.in.mask);
if (rc == NGX_ERROR) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid radix tree");
return NGX_CONF_ERROR;
}
rc = ngx_radix32tree_insert(ctx->tree, cidr->u.in.addr,
cidr->u.in.mask, (uintptr_t) val);
break;
}
if (rc == NGX_OK) {
return NGX_CONF_OK;
}
return NGX_CONF_ERROR;
@ -1052,10 +1264,10 @@ static char *
ngx_http_geo_add_proxy(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
ngx_cidr_t *cidr)
{
ngx_in_cidr_t *c;
ngx_cidr_t *c;
if (ctx->proxies == NULL) {
ctx->proxies = ngx_array_create(ctx->pool, 4, sizeof(ngx_in_cidr_t));
ctx->proxies = ngx_array_create(ctx->pool, 4, sizeof(ngx_cidr_t));
if (ctx->proxies == NULL) {
return NGX_CONF_ERROR;
}
@ -1066,8 +1278,7 @@ ngx_http_geo_add_proxy(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
return NGX_CONF_ERROR;
}
c->addr = cidr->u.in.addr;
c->mask = cidr->u.in.mask;
*c = *cidr;
return NGX_CONF_OK;
}
@ -1079,6 +1290,7 @@ ngx_http_geo_cidr_value(ngx_conf_t *cf, ngx_str_t *net, ngx_cidr_t *cidr)
ngx_int_t rc;
if (ngx_strcmp(net->data, "255.255.255.255") == 0) {
cidr->family = AF_INET;
cidr->u.in.addr = 0xffffffff;
cidr->u.in.mask = 0xffffffff;
@ -1092,19 +1304,11 @@ ngx_http_geo_cidr_value(ngx_conf_t *cf, ngx_str_t *net, ngx_cidr_t *cidr)
return NGX_ERROR;
}
if (cidr->family != AF_INET) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "\"geo\" supports IPv4 only");
return NGX_ERROR;
}
if (rc == NGX_DONE) {
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
"low address bits of %V are meaningless", net);
}
cidr->u.in.addr = ntohl(cidr->u.in.addr);
cidr->u.in.mask = ntohl(cidr->u.in.mask);
return NGX_OK;
}

View File

@ -13,20 +13,56 @@
#include <GeoIPCity.h>
#define NGX_GEOIP_COUNTRY_CODE 0
#define NGX_GEOIP_COUNTRY_CODE3 1
#define NGX_GEOIP_COUNTRY_NAME 2
typedef struct {
GeoIP *country;
GeoIP *org;
GeoIP *city;
GeoIP *country;
GeoIP *org;
GeoIP *city;
ngx_array_t *proxies; /* array of ngx_cidr_t */
ngx_flag_t proxy_recursive;
#if (NGX_HAVE_GEOIP_V6)
unsigned country_v6:1;
unsigned org_v6:1;
unsigned city_v6:1;
#endif
} ngx_http_geoip_conf_t;
typedef struct {
ngx_str_t *name;
uintptr_t data;
ngx_str_t *name;
uintptr_t data;
} ngx_http_geoip_var_t;
typedef const char *(*ngx_http_geoip_variable_handler_pt)(GeoIP *, u_long addr);
typedef const char *(*ngx_http_geoip_variable_handler_pt)(GeoIP *,
u_long addr);
ngx_http_geoip_variable_handler_pt ngx_http_geoip_country_functions[] = {
GeoIP_country_code_by_ipnum,
GeoIP_country_code3_by_ipnum,
GeoIP_country_name_by_ipnum,
};
#if (NGX_HAVE_GEOIP_V6)
typedef const char *(*ngx_http_geoip_variable_handler_v6_pt)(GeoIP *,
geoipv6_t addr);
ngx_http_geoip_variable_handler_v6_pt ngx_http_geoip_country_v6_functions[] = {
GeoIP_country_code_by_ipnum_v6,
GeoIP_country_code3_by_ipnum_v6,
GeoIP_country_name_by_ipnum_v6,
};
#endif
static ngx_int_t ngx_http_geoip_country_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
@ -44,12 +80,17 @@ static GeoIPRecord *ngx_http_geoip_get_city_record(ngx_http_request_t *r);
static ngx_int_t ngx_http_geoip_add_variables(ngx_conf_t *cf);
static void *ngx_http_geoip_create_conf(ngx_conf_t *cf);
static char *ngx_http_geoip_init_conf(ngx_conf_t *cf, void *conf);
static char *ngx_http_geoip_country(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_http_geoip_org(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_http_geoip_city(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_http_geoip_proxy(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static ngx_int_t ngx_http_geoip_cidr_value(ngx_conf_t *cf, ngx_str_t *net,
ngx_cidr_t *cidr);
static void ngx_http_geoip_cleanup(void *data);
@ -76,6 +117,20 @@ static ngx_command_t ngx_http_geoip_commands[] = {
0,
NULL },
{ ngx_string("geoip_proxy"),
NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
ngx_http_geoip_proxy,
NGX_HTTP_MAIN_CONF_OFFSET,
0,
NULL },
{ ngx_string("geoip_proxy_recursive"),
NGX_HTTP_MAIN_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
NGX_HTTP_MAIN_CONF_OFFSET,
offsetof(ngx_http_geoip_conf_t, proxy_recursive),
NULL },
ngx_null_command
};
@ -85,7 +140,7 @@ static ngx_http_module_t ngx_http_geoip_module_ctx = {
NULL, /* postconfiguration */
ngx_http_geoip_create_conf, /* create main configuration */
NULL, /* init main configuration */
ngx_http_geoip_init_conf, /* init main configuration */
NULL, /* create server configuration */
NULL, /* merge server configuration */
@ -115,19 +170,19 @@ static ngx_http_variable_t ngx_http_geoip_vars[] = {
{ ngx_string("geoip_country_code"), NULL,
ngx_http_geoip_country_variable,
(uintptr_t) GeoIP_country_code_by_ipnum, 0, 0 },
NGX_GEOIP_COUNTRY_CODE, 0, 0 },
{ ngx_string("geoip_country_code3"), NULL,
ngx_http_geoip_country_variable,
(uintptr_t) GeoIP_country_code3_by_ipnum, 0, 0 },
NGX_GEOIP_COUNTRY_CODE3, 0, 0 },
{ ngx_string("geoip_country_name"), NULL,
ngx_http_geoip_country_variable,
(uintptr_t) GeoIP_country_name_by_ipnum, 0, 0 },
NGX_GEOIP_COUNTRY_NAME, 0, 0 },
{ ngx_string("geoip_org"), NULL,
ngx_http_geoip_org_variable,
(uintptr_t) GeoIP_name_by_ipnum, 0, 0 },
0, 0, 0 },
{ ngx_string("geoip_city_continent_code"), NULL,
ngx_http_geoip_city_variable,
@ -182,49 +237,118 @@ static ngx_http_variable_t ngx_http_geoip_vars[] = {
static u_long
ngx_http_geoip_addr(ngx_http_request_t *r)
ngx_http_geoip_addr(ngx_http_request_t *r, ngx_http_geoip_conf_t *gcf)
{
struct sockaddr_in *sin;
#if (NGX_HAVE_INET6)
u_char *p;
u_long addr;
struct sockaddr_in6 *sin6;
#endif
ngx_addr_t addr;
ngx_table_elt_t *xfwd;
struct sockaddr_in *sin;
switch (r->connection->sockaddr->sa_family) {
addr.sockaddr = r->connection->sockaddr;
addr.socklen = r->connection->socklen;
/* addr.name = r->connection->addr_text; */
case AF_INET:
sin = (struct sockaddr_in *) r->connection->sockaddr;
return ntohl(sin->sin_addr.s_addr);
xfwd = r->headers_in.x_forwarded_for;
#if (NGX_HAVE_INET6)
case AF_INET6:
sin6 = (struct sockaddr_in6 *) r->connection->sockaddr;
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
p = sin6->sin6_addr.s6_addr;
addr = p[12] << 24;
addr += p[13] << 16;
addr += p[14] << 8;
addr += p[15];
return addr;
}
#endif
if (xfwd != NULL && gcf->proxies != NULL) {
(void) ngx_http_get_forwarded_addr(r, &addr, xfwd->value.data,
xfwd->value.len, gcf->proxies,
gcf->proxy_recursive);
}
return INADDR_NONE;
#if (NGX_HAVE_INET6)
if (addr.sockaddr->sa_family == AF_INET6) {
u_char *p;
in_addr_t inaddr;
struct in6_addr *inaddr6;
inaddr6 = &((struct sockaddr_in6 *) addr.sockaddr)->sin6_addr;
if (IN6_IS_ADDR_V4MAPPED(inaddr6)) {
p = inaddr6->s6_addr;
inaddr = p[12] << 24;
inaddr += p[13] << 16;
inaddr += p[14] << 8;
inaddr += p[15];
return inaddr;
}
}
#endif
if (addr.sockaddr->sa_family != AF_INET) {
return INADDR_NONE;
}
sin = (struct sockaddr_in *) addr.sockaddr;
return ntohl(sin->sin_addr.s_addr);
}
#if (NGX_HAVE_GEOIP_V6)
static geoipv6_t
ngx_http_geoip_addr_v6(ngx_http_request_t *r, ngx_http_geoip_conf_t *gcf)
{
ngx_addr_t addr;
ngx_table_elt_t *xfwd;
in_addr_t addr4;
struct in6_addr addr6;
struct sockaddr_in *sin;
struct sockaddr_in6 *sin6;
addr.sockaddr = r->connection->sockaddr;
addr.socklen = r->connection->socklen;
/* addr.name = r->connection->addr_text; */
xfwd = r->headers_in.x_forwarded_for;
if (xfwd != NULL && gcf->proxies != NULL) {
(void) ngx_http_get_forwarded_addr(r, &addr, xfwd->value.data,
xfwd->value.len, gcf->proxies,
gcf->proxy_recursive);
}
switch (addr.sockaddr->sa_family) {
case AF_INET:
/* Produce IPv4-mapped IPv6 address. */
sin = (struct sockaddr_in *) addr.sockaddr;
addr4 = ntohl(sin->sin_addr.s_addr);
ngx_memzero(&addr6, sizeof(struct in6_addr));
addr6.s6_addr[10] = 0xff;
addr6.s6_addr[11] = 0xff;
addr6.s6_addr[12] = addr4 >> 24;
addr6.s6_addr[13] = addr4 >> 16;
addr6.s6_addr[14] = addr4 >> 8;
addr6.s6_addr[15] = addr4;
return addr6;
case AF_INET6:
sin6 = (struct sockaddr_in6 *) addr.sockaddr;
return sin6->sin6_addr;
default:
return in6addr_any;
}
}
#endif
static ngx_int_t
ngx_http_geoip_country_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{
ngx_http_geoip_variable_handler_pt handler =
(ngx_http_geoip_variable_handler_pt) data;
ngx_http_geoip_variable_handler_pt handler =
ngx_http_geoip_country_functions[data];
#if (NGX_HAVE_GEOIP_V6)
ngx_http_geoip_variable_handler_v6_pt handler_v6 =
ngx_http_geoip_country_v6_functions[data];
#endif
const char *val;
ngx_http_geoip_conf_t *gcf;
@ -235,7 +359,13 @@ ngx_http_geoip_country_variable(ngx_http_request_t *r,
goto not_found;
}
val = handler(gcf->country, ngx_http_geoip_addr(r));
#if (NGX_HAVE_GEOIP_V6)
val = gcf->country_v6
? handler_v6(gcf->country, ngx_http_geoip_addr_v6(r, gcf))
: handler(gcf->country, ngx_http_geoip_addr(r, gcf));
#else
val = handler(gcf->country, ngx_http_geoip_addr(r, gcf));
#endif
if (val == NULL) {
goto not_found;
@ -261,10 +391,8 @@ static ngx_int_t
ngx_http_geoip_org_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{
ngx_http_geoip_variable_handler_pt handler =
(ngx_http_geoip_variable_handler_pt) data;
const char *val;
size_t len;
char *val;
ngx_http_geoip_conf_t *gcf;
gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip_module);
@ -273,17 +401,35 @@ ngx_http_geoip_org_variable(ngx_http_request_t *r,
goto not_found;
}
val = handler(gcf->org, ngx_http_geoip_addr(r));
#if (NGX_HAVE_GEOIP_V6)
val = gcf->org_v6
? GeoIP_name_by_ipnum_v6(gcf->org,
ngx_http_geoip_addr_v6(r, gcf))
: GeoIP_name_by_ipnum(gcf->org,
ngx_http_geoip_addr(r, gcf));
#else
val = GeoIP_name_by_ipnum(gcf->org, ngx_http_geoip_addr(r, gcf));
#endif
if (val == NULL) {
goto not_found;
}
v->len = ngx_strlen(val);
len = ngx_strlen(val);
v->data = ngx_pnalloc(r->pool, len);
if (v->data == NULL) {
ngx_free(val);
return NGX_ERROR;
}
ngx_memcpy(v->data, val, len);
v->len = len;
v->valid = 1;
v->no_cacheable = 0;
v->not_found = 0;
v->data = (u_char *) val;
ngx_free(val);
return NGX_OK;
@ -453,7 +599,15 @@ ngx_http_geoip_get_city_record(ngx_http_request_t *r)
gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip_module);
if (gcf->city) {
return GeoIP_record_by_ipnum(gcf->city, ngx_http_geoip_addr(r));
#if (NGX_HAVE_GEOIP_V6)
return gcf->city_v6
? GeoIP_record_by_ipnum_v6(gcf->city,
ngx_http_geoip_addr_v6(r, gcf))
: GeoIP_record_by_ipnum(gcf->city,
ngx_http_geoip_addr(r, gcf));
#else
return GeoIP_record_by_ipnum(gcf->city, ngx_http_geoip_addr(r, gcf));
#endif
}
return NULL;
@ -490,6 +644,8 @@ ngx_http_geoip_create_conf(ngx_conf_t *cf)
return NULL;
}
conf->proxy_recursive = NGX_CONF_UNSET;
cln = ngx_pool_cleanup_add(cf->pool, 0);
if (cln == NULL) {
return NULL;
@ -502,6 +658,17 @@ ngx_http_geoip_create_conf(ngx_conf_t *cf)
}
static char *
ngx_http_geoip_init_conf(ngx_conf_t *cf, void *conf)
{
ngx_http_geoip_conf_t *gcf = conf;
ngx_conf_init_value(gcf->proxy_recursive, 0);
return NGX_CONF_OK;
}
static char *
ngx_http_geoip_country(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
@ -538,11 +705,16 @@ ngx_http_geoip_country(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
switch (gcf->country->databaseType) {
case GEOIP_COUNTRY_EDITION:
case GEOIP_PROXY_EDITION:
case GEOIP_NETSPEED_EDITION:
return NGX_CONF_OK;
#if (NGX_HAVE_GEOIP_V6)
case GEOIP_COUNTRY_EDITION_V6:
gcf->country_v6 = 1;
return NGX_CONF_OK;
#endif
default:
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid GeoIP database \"%V\" type:%d",
@ -594,6 +766,16 @@ ngx_http_geoip_org(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_OK;
#if (NGX_HAVE_GEOIP_V6)
case GEOIP_ISP_EDITION_V6:
case GEOIP_ORG_EDITION_V6:
case GEOIP_DOMAIN_EDITION_V6:
case GEOIP_ASNUM_EDITION_V6:
gcf->org_v6 = 1;
return NGX_CONF_OK;
#endif
default:
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid GeoIP database \"%V\" type:%d",
@ -643,6 +825,14 @@ ngx_http_geoip_city(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_OK;
#if (NGX_HAVE_GEOIP_V6)
case GEOIP_CITY_EDITION_REV0_V6:
case GEOIP_CITY_EDITION_REV1_V6:
gcf->city_v6 = 1;
return NGX_CONF_OK;
#endif
default:
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid GeoIP City database \"%V\" type:%d",
@ -652,6 +842,66 @@ ngx_http_geoip_city(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
static char *
ngx_http_geoip_proxy(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_geoip_conf_t *gcf = conf;
ngx_str_t *value;
ngx_cidr_t cidr, *c;
value = cf->args->elts;
if (ngx_http_geoip_cidr_value(cf, &value[1], &cidr) != NGX_OK) {
return NGX_CONF_ERROR;
}
if (gcf->proxies == NULL) {
gcf->proxies = ngx_array_create(cf->pool, 4, sizeof(ngx_cidr_t));
if (gcf->proxies == NULL) {
return NGX_CONF_ERROR;
}
}
c = ngx_array_push(gcf->proxies);
if (c == NULL) {
return NGX_CONF_ERROR;
}
*c = cidr;
return NGX_CONF_OK;
}
static ngx_int_t
ngx_http_geoip_cidr_value(ngx_conf_t *cf, ngx_str_t *net, ngx_cidr_t *cidr)
{
ngx_int_t rc;
if (ngx_strcmp(net->data, "255.255.255.255") == 0) {
cidr->family = AF_INET;
cidr->u.in.addr = 0xffffffff;
cidr->u.in.mask = 0xffffffff;
return NGX_OK;
}
rc = ngx_ptocidr(net, cidr);
if (rc == NGX_ERROR) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid network \"%V\"", net);
return NGX_ERROR;
}
if (rc == NGX_DONE) {
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
"low address bits of %V are meaningless", net);
}
return NGX_OK;
}
static void
ngx_http_geoip_cleanup(void *data)
{

View File

@ -320,7 +320,7 @@ ngx_http_gzip_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
ctx = ngx_http_get_module_ctx(r, ngx_http_gzip_filter_module);
if (ctx == NULL || ctx->done) {
if (ctx == NULL || ctx->done || r->header_only) {
return ngx_http_next_body_filter(r, in);
}
@ -497,6 +497,10 @@ ngx_http_gzip_filter_memory(ngx_http_request_t *r, ngx_http_gzip_ctx_t *ctx)
wbits--;
memlevel--;
}
if (memlevel < 1) {
memlevel = 1;
}
}
ctx->wbits = wbits;

View File

@ -245,7 +245,7 @@ ngx_http_gzip_static_handler(ngx_http_request_t *r)
b->file_last = of.size;
b->in_file = b->file_last ? 1 : 0;
b->last_buf = 1;
b->last_buf = (r == r->main) ? 1 : 0;
b->last_in_chain = 1;
b->file->fd = of.fd;

View File

@ -149,6 +149,7 @@ ngx_http_headers_filter(ngx_http_request_t *r)
if ((conf->expires == NGX_HTTP_EXPIRES_OFF && conf->headers == NULL)
|| r != r->main
|| (r->headers_out.status != NGX_HTTP_OK
&& r->headers_out.status != NGX_HTTP_CREATED
&& r->headers_out.status != NGX_HTTP_NO_CONTENT
&& r->headers_out.status != NGX_HTTP_PARTIAL_CONTENT
&& r->headers_out.status != NGX_HTTP_MOVED_PERMANENTLY

View File

@ -1169,10 +1169,22 @@ ngx_http_image_filter_create_conf(ngx_conf_t *cf)
return NULL;
}
/*
* set by ngx_pcalloc():
*
* conf->width = 0;
* conf->height = 0;
* conf->angle = 0;
* conf->wcv = NULL;
* conf->hcv = NULL;
* conf->acv = NULL;
* conf->jqcv = NULL;
* conf->shcv = NULL;
*/
conf->filter = NGX_CONF_UNSET_UINT;
conf->jpeg_quality = NGX_CONF_UNSET_UINT;
conf->sharpen = NGX_CONF_UNSET_UINT;
conf->angle = NGX_CONF_UNSET_UINT;
conf->transparency = NGX_CONF_UNSET;
conf->buffer_size = NGX_CONF_UNSET_SIZE;
@ -1195,27 +1207,29 @@ ngx_http_image_filter_merge_conf(ngx_conf_t *cf, void *parent, void *child)
conf->filter = prev->filter;
conf->width = prev->width;
conf->height = prev->height;
conf->angle = prev->angle;
conf->wcv = prev->wcv;
conf->hcv = prev->hcv;
conf->acv = prev->acv;
}
}
/* 75 is libjpeg default quality */
ngx_conf_merge_uint_value(conf->jpeg_quality, prev->jpeg_quality, 75);
if (conf->jpeg_quality == NGX_CONF_UNSET_UINT) {
if (conf->jqcv == NULL) {
conf->jqcv = prev->jqcv;
/* 75 is libjpeg default quality */
ngx_conf_merge_uint_value(conf->jpeg_quality, prev->jpeg_quality, 75);
if (conf->jqcv == NULL) {
conf->jqcv = prev->jqcv;
}
}
ngx_conf_merge_uint_value(conf->sharpen, prev->sharpen, 0);
if (conf->sharpen == NGX_CONF_UNSET_UINT) {
ngx_conf_merge_uint_value(conf->sharpen, prev->sharpen, 0);
if (conf->shcv == NULL) {
conf->shcv = prev->shcv;
}
ngx_conf_merge_uint_value(conf->angle, prev->angle, 0);
if (conf->acv == NULL) {
conf->acv = prev->acv;
if (conf->shcv == NULL) {
conf->shcv = prev->shcv;
}
}
ngx_conf_merge_value(conf->transparency, prev->transparency, 1);

View File

@ -85,12 +85,12 @@ ngx_module_t ngx_http_index_module = {
/*
* Try to open/test the first index file before the test of directory
* existence because valid requests should be much more than invalid ones.
* If the file open()/stat() would fail, then the directory stat() should
* be more quickly because some data is already cached in the kernel.
* existence because valid requests should prevail over invalid ones.
* If open()/stat() of a file will fail then stat() of a directory
* should be faster because kernel may have already cached some data.
* Besides, Win32 may return ERROR_PATH_NOT_FOUND (NGX_ENOTDIR) at once.
* Unix has ENOTDIR error, however, it's less helpful than Win32's one:
* it only indicates that path contains an usual file in place of directory.
* Unix has ENOTDIR error; however, it's less helpful than Win32's one:
* it only indicates that path points to a regular file, not a directory.
*/
static ngx_int_t

View File

@ -238,7 +238,7 @@ ngx_http_limit_conn_handler(ngx_http_request_t *r)
}
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"limit zone: %08XD %d", node->key, lc->conn);
"limit conn: %08XD %d", node->key, lc->conn);
ngx_shmtx_unlock(&shpool->mutex);
@ -358,7 +358,7 @@ ngx_http_limit_conn_cleanup(void *data)
ngx_shmtx_lock(&shpool->mutex);
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, lccln->shm_zone->shm.log, 0,
"limit zone cleanup: %08XD %d", node->key, lc->conn);
"limit conn cleanup: %08XD %d", node->key, lc->conn);
lc->conn--;
@ -721,6 +721,10 @@ ngx_http_limit_conn(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
limit = ngx_array_push(&lccf->limits);
if (limit == NULL) {
return NGX_CONF_ERROR;
}
limit->conn = n;
limit->shm_zone = shm_zone;

View File

@ -444,17 +444,17 @@ ngx_http_limit_req_lookup(ngx_http_limit_req_limit_t *limit, ngx_uint_t hash,
node->key = hash;
ngx_rbtree_insert(&ctx->sh->rbtree, node);
lr = (ngx_http_limit_req_node_t *) &node->color;
ngx_queue_insert_head(&ctx->sh->queue, &lr->queue);
lr->len = (u_char) len;
lr->excess = 0;
ngx_memcpy(lr->data, data, len);
ngx_rbtree_insert(&ctx->sh->rbtree, node);
ngx_queue_insert_head(&ctx->sh->queue, &lr->queue);
if (account) {
lr->last = now;
lr->count = 0;
@ -937,6 +937,9 @@ ngx_http_limit_req(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
limit = ngx_array_push(&lrcf->limits);
if (limit == NULL) {
return NGX_CONF_ERROR;
}
limit->shm_zone = shm_zone;
limit->burst = burst * 1000;

View File

@ -9,6 +9,10 @@
#include <ngx_core.h>
#include <ngx_http.h>
#if (NGX_ZLIB)
#include <zlib.h>
#endif
typedef struct ngx_http_log_op_s ngx_http_log_op_t;
@ -40,6 +44,17 @@ typedef struct {
} ngx_http_log_main_conf_t;
typedef struct {
u_char *start;
u_char *pos;
u_char *last;
ngx_event_t *event;
ngx_msec_t flush;
ngx_int_t gzip;
} ngx_http_log_buf_t;
typedef struct {
ngx_array_t *lengths;
ngx_array_t *values;
@ -78,10 +93,17 @@ static void ngx_http_log_write(ngx_http_request_t *r, ngx_http_log_t *log,
static ssize_t ngx_http_log_script_write(ngx_http_request_t *r,
ngx_http_log_script_t *script, u_char **name, u_char *buf, size_t len);
static u_char *ngx_http_log_connection(ngx_http_request_t *r, u_char *buf,
ngx_http_log_op_t *op);
static u_char *ngx_http_log_connection_requests(ngx_http_request_t *r,
u_char *buf, ngx_http_log_op_t *op);
#if (NGX_ZLIB)
static ssize_t ngx_http_log_gzip(ngx_fd_t fd, u_char *buf, size_t len,
ngx_int_t level, ngx_log_t *log);
static void *ngx_http_log_gzip_alloc(void *opaque, u_int items, u_int size);
static void ngx_http_log_gzip_free(void *opaque, void *address);
#endif
static void ngx_http_log_flush(ngx_open_file_t *file, ngx_log_t *log);
static void ngx_http_log_flush_handler(ngx_event_t *ev);
static u_char *ngx_http_log_pipe(ngx_http_request_t *r, u_char *buf,
ngx_http_log_op_t *op);
static u_char *ngx_http_log_time(ngx_http_request_t *r, u_char *buf,
@ -136,7 +158,7 @@ static ngx_command_t ngx_http_log_commands[] = {
{ ngx_string("access_log"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|NGX_HTTP_LMT_CONF|NGX_CONF_TAKE123,
|NGX_HTTP_LMT_CONF|NGX_CONF_1MORE,
ngx_http_log_set_log,
NGX_HTTP_LOC_CONF_OFFSET,
0,
@ -194,9 +216,6 @@ static ngx_str_t ngx_http_combined_fmt =
static ngx_http_log_var_t ngx_http_log_vars[] = {
{ ngx_string("connection"), NGX_ATOMIC_T_LEN, ngx_http_log_connection },
{ ngx_string("connection_requests"), NGX_INT_T_LEN,
ngx_http_log_connection_requests },
{ ngx_string("pipe"), 1, ngx_http_log_pipe },
{ ngx_string("time_local"), sizeof("28/Sep/1970:12:00:00 +0600") - 1,
ngx_http_log_time },
@ -205,12 +224,10 @@ static ngx_http_log_var_t ngx_http_log_vars[] = {
{ ngx_string("msec"), NGX_TIME_T_LEN + 4, ngx_http_log_msec },
{ ngx_string("request_time"), NGX_TIME_T_LEN + 4,
ngx_http_log_request_time },
{ ngx_string("status"), 3, ngx_http_log_status },
{ ngx_string("status"), NGX_INT_T_LEN, ngx_http_log_status },
{ ngx_string("bytes_sent"), NGX_OFF_T_LEN, ngx_http_log_bytes_sent },
{ ngx_string("body_bytes_sent"), NGX_OFF_T_LEN,
ngx_http_log_body_bytes_sent },
{ ngx_string("apache_bytes_sent"), NGX_OFF_T_LEN,
ngx_http_log_body_bytes_sent },
{ ngx_string("request_length"), NGX_SIZE_T_LEN,
ngx_http_log_request_length },
@ -218,15 +235,15 @@ static ngx_http_log_var_t ngx_http_log_vars[] = {
};
ngx_int_t
static ngx_int_t
ngx_http_log_handler(ngx_http_request_t *r)
{
u_char *line, *p;
size_t len;
ngx_uint_t i, l;
ngx_http_log_t *log;
ngx_open_file_t *file;
ngx_http_log_op_t *op;
ngx_http_log_buf_t *buffer;
ngx_http_log_loc_conf_t *lcf;
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
@ -267,21 +284,25 @@ ngx_http_log_handler(ngx_http_request_t *r)
len += NGX_LINEFEED_SIZE;
file = log[l].file;
buffer = log[l].file ? log[l].file->data : NULL;
if (file && file->buffer) {
if (buffer) {
if (len > (size_t) (file->last - file->pos)) {
if (len > (size_t) (buffer->last - buffer->pos)) {
ngx_http_log_write(r, &log[l], file->buffer,
file->pos - file->buffer);
ngx_http_log_write(r, &log[l], buffer->start,
buffer->pos - buffer->start);
file->pos = file->buffer;
buffer->pos = buffer->start;
}
if (len <= (size_t) (file->last - file->pos)) {
if (len <= (size_t) (buffer->last - buffer->pos)) {
p = file->pos;
p = buffer->pos;
if (buffer->event && p == buffer->start) {
ngx_add_timer(buffer->event, buffer->flush);
}
for (i = 0; i < log[l].format->ops->nelts; i++) {
p = op[i].run(r, p, &op[i]);
@ -289,10 +310,14 @@ ngx_http_log_handler(ngx_http_request_t *r)
ngx_linefeed(p);
file->pos = p;
buffer->pos = p;
continue;
}
if (buffer->event && buffer->event->timer_set) {
ngx_del_timer(buffer->event);
}
}
line = ngx_pnalloc(r->pool, len);
@ -319,14 +344,29 @@ static void
ngx_http_log_write(ngx_http_request_t *r, ngx_http_log_t *log, u_char *buf,
size_t len)
{
u_char *name;
time_t now;
ssize_t n;
ngx_err_t err;
u_char *name;
time_t now;
ssize_t n;
ngx_err_t err;
#if (NGX_ZLIB)
ngx_http_log_buf_t *buffer;
#endif
if (log->script == NULL) {
name = log->file->name.data;
#if (NGX_ZLIB)
buffer = log->file->data;
if (buffer && buffer->gzip) {
n = ngx_http_log_gzip(log->file->fd, buf, len, buffer->gzip,
r->connection->log);
} else {
n = ngx_write_fd(log->file->fd, buf, len);
}
#else
n = ngx_write_fd(log->file->fd, buf, len);
#endif
} else {
name = NULL;
@ -474,6 +514,194 @@ ngx_http_log_script_write(ngx_http_request_t *r, ngx_http_log_script_t *script,
}
#if (NGX_ZLIB)
static ssize_t
ngx_http_log_gzip(ngx_fd_t fd, u_char *buf, size_t len, ngx_int_t level,
ngx_log_t *log)
{
int rc, wbits, memlevel;
u_char *out;
size_t size;
ssize_t n;
z_stream zstream;
ngx_err_t err;
ngx_pool_t *pool;
wbits = MAX_WBITS;
memlevel = MAX_MEM_LEVEL - 1;
while ((ssize_t) len < ((1 << (wbits - 1)) - 262)) {
wbits--;
memlevel--;
}
/*
* This is a formula from deflateBound() for conservative upper bound of
* compressed data plus 18 bytes of gzip wrapper.
*/
size = len + ((len + 7) >> 3) + ((len + 63) >> 6) + 5 + 18;
ngx_memzero(&zstream, sizeof(z_stream));
pool = ngx_create_pool(256, log);
if (pool == NULL) {
/* simulate successful logging */
return len;
}
pool->log = log;
zstream.zalloc = ngx_http_log_gzip_alloc;
zstream.zfree = ngx_http_log_gzip_free;
zstream.opaque = pool;
out = ngx_pnalloc(pool, size);
if (out == NULL) {
goto done;
}
zstream.next_in = buf;
zstream.avail_in = len;
zstream.next_out = out;
zstream.avail_out = size;
rc = deflateInit2(&zstream, (int) level, Z_DEFLATED, wbits + 16, memlevel,
Z_DEFAULT_STRATEGY);
if (rc != Z_OK) {
ngx_log_error(NGX_LOG_ALERT, log, 0, "deflateInit2() failed: %d", rc);
goto done;
}
ngx_log_debug4(NGX_LOG_DEBUG_HTTP, log, 0,
"deflate in: ni:%p no:%p ai:%ud ao:%ud",
zstream.next_in, zstream.next_out,
zstream.avail_in, zstream.avail_out);
rc = deflate(&zstream, Z_FINISH);
if (rc != Z_STREAM_END) {
ngx_log_error(NGX_LOG_ALERT, log, 0,
"deflate(Z_FINISH) failed: %d", rc);
goto done;
}
ngx_log_debug5(NGX_LOG_DEBUG_HTTP, log, 0,
"deflate out: ni:%p no:%p ai:%ud ao:%ud rc:%d",
zstream.next_in, zstream.next_out,
zstream.avail_in, zstream.avail_out,
rc);
size -= zstream.avail_out;
rc = deflateEnd(&zstream);
if (rc != Z_OK) {
ngx_log_error(NGX_LOG_ALERT, log, 0, "deflateEnd() failed: %d", rc);
goto done;
}
n = ngx_write_fd(fd, out, size);
if (n != (ssize_t) size) {
err = (n == -1) ? ngx_errno : 0;
ngx_destroy_pool(pool);
ngx_set_errno(err);
return -1;
}
done:
ngx_destroy_pool(pool);
/* simulate successful logging */
return len;
}
static void *
ngx_http_log_gzip_alloc(void *opaque, u_int items, u_int size)
{
ngx_pool_t *pool = opaque;
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pool->log, 0,
"gzip alloc: n:%ud s:%ud", items, size);
return ngx_palloc(pool, items * size);
}
static void
ngx_http_log_gzip_free(void *opaque, void *address)
{
#if 0
ngx_pool_t *pool = opaque;
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pool->log, 0, "gzip free: %p", address);
#endif
}
#endif
static void
ngx_http_log_flush(ngx_open_file_t *file, ngx_log_t *log)
{
size_t len;
ssize_t n;
ngx_http_log_buf_t *buffer;
buffer = file->data;
len = buffer->pos - buffer->start;
if (len == 0) {
return;
}
#if (NGX_ZLIB)
if (buffer->gzip) {
n = ngx_http_log_gzip(file->fd, buffer->start, len, buffer->gzip, log);
} else {
n = ngx_write_fd(file->fd, buffer->start, len);
}
#else
n = ngx_write_fd(file->fd, buffer->start, len);
#endif
if (n == -1) {
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
ngx_write_fd_n " to \"%s\" failed",
file->name.data);
} else if ((size_t) n != len) {
ngx_log_error(NGX_LOG_ALERT, log, 0,
ngx_write_fd_n " to \"%s\" was incomplete: %z of %uz",
file->name.data, n, len);
}
buffer->pos = buffer->start;
if (buffer->event && buffer->event->timer_set) {
ngx_del_timer(buffer->event);
}
}
static void
ngx_http_log_flush_handler(ngx_event_t *ev)
{
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0,
"http log buffer flush handler");
ngx_http_log_flush(ev->data, ev->log);
}
static u_char *
ngx_http_log_copy_short(ngx_http_request_t *r, u_char *buf,
ngx_http_log_op_t *op)
@ -501,22 +729,6 @@ ngx_http_log_copy_long(ngx_http_request_t *r, u_char *buf,
}
static u_char *
ngx_http_log_connection(ngx_http_request_t *r, u_char *buf,
ngx_http_log_op_t *op)
{
return ngx_sprintf(buf, "%uA", r->connection->number);
}
static u_char *
ngx_http_log_connection_requests(ngx_http_request_t *r, u_char *buf,
ngx_http_log_op_t *op)
{
return ngx_sprintf(buf, "%ui", r->connection->requests);
}
static u_char *
ngx_http_log_pipe(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
{
@ -584,16 +796,13 @@ ngx_http_log_status(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
status = r->headers_out.status;
} else if (r->http_version == NGX_HTTP_VERSION_9) {
*buf++ = '0';
*buf++ = '0';
*buf++ = '9';
return buf;
status = 9;
} else {
status = 0;
}
return ngx_sprintf(buf, "%ui", status);
return ngx_sprintf(buf, "%03ui", status);
}
@ -876,10 +1085,13 @@ ngx_http_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_log_loc_conf_t *llcf = conf;
ssize_t buf;
ssize_t size;
ngx_int_t gzip;
ngx_uint_t i, n;
ngx_str_t *value, name;
ngx_msec_t flush;
ngx_str_t *value, name, s;
ngx_http_log_t *log;
ngx_http_log_buf_t *buffer;
ngx_http_log_fmt_t *fmt;
ngx_http_log_main_conf_t *lmcf;
ngx_http_script_compile_t sc;
@ -964,54 +1176,152 @@ ngx_http_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
&& ngx_strcasecmp(fmt[i].name.data, name.data) == 0)
{
log->format = &fmt[i];
goto buffer;
break;
}
}
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"unknown log format \"%V\"", &name);
return NGX_CONF_ERROR;
if (log->format == NULL) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"unknown log format \"%V\"", &name);
return NGX_CONF_ERROR;
}
buffer:
size = 0;
flush = 0;
gzip = 0;
if (cf->args->nelts == 4) {
if (ngx_strncmp(value[3].data, "buffer=", 7) != 0) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid parameter \"%V\"", &value[3]);
return NGX_CONF_ERROR;
for (i = 3; i < cf->args->nelts; i++) {
if (ngx_strncmp(value[i].data, "buffer=", 7) == 0) {
s.len = value[i].len - 7;
s.data = value[i].data + 7;
size = ngx_parse_size(&s);
if (size == NGX_ERROR || size == 0) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid buffer size \"%V\"", &s);
return NGX_CONF_ERROR;
}
continue;
}
if (ngx_strncmp(value[i].data, "flush=", 6) == 0) {
s.len = value[i].len - 6;
s.data = value[i].data + 6;
flush = ngx_parse_time(&s, 0);
if (flush == (ngx_msec_t) NGX_ERROR || flush == 0) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid flush time \"%V\"", &s);
return NGX_CONF_ERROR;
}
continue;
}
if (ngx_strncmp(value[i].data, "gzip", 4) == 0
&& (value[i].len == 4 || value[i].data[4] == '='))
{
#if (NGX_ZLIB)
if (size == 0) {
size = 64 * 1024;
}
if (value[i].len == 4) {
gzip = Z_BEST_SPEED;
continue;
}
s.len = value[i].len - 5;
s.data = value[i].data + 5;
gzip = ngx_atoi(s.data, s.len);
if (gzip < 1 || gzip > 9) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid compression level \"%V\"", &s);
return NGX_CONF_ERROR;
}
continue;
#else
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"nginx was built without zlib support");
return NGX_CONF_ERROR;
#endif
}
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid parameter \"%V\"", &value[i]);
return NGX_CONF_ERROR;
}
if (flush && size == 0) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"no buffer is defined for access_log \"%V\"",
&value[1]);
return NGX_CONF_ERROR;
}
if (size) {
if (log->script) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"buffered logs cannot have variables in name");
return NGX_CONF_ERROR;
}
name.len = value[3].len - 7;
name.data = value[3].data + 7;
if (log->file->data) {
buffer = log->file->data;
buf = ngx_parse_size(&name);
if (buffer->last - buffer->start != size
|| buffer->flush != flush
|| buffer->gzip != gzip)
{
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"access_log \"%V\" already defined "
"with conflicting parameters",
&value[1]);
return NGX_CONF_ERROR;
}
if (buf == NGX_ERROR) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid buffer value \"%V\"", &name);
return NGX_CONF_OK;
}
buffer = ngx_pcalloc(cf->pool, sizeof(ngx_http_log_buf_t));
if (buffer == NULL) {
return NGX_CONF_ERROR;
}
if (log->file->buffer && log->file->last - log->file->pos != buf) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"access_log \"%V\" already defined "
"with different buffer size", &value[1]);
buffer->start = ngx_pnalloc(cf->pool, size);
if (buffer->start == NULL) {
return NGX_CONF_ERROR;
}
log->file->buffer = ngx_palloc(cf->pool, buf);
if (log->file->buffer == NULL) {
return NGX_CONF_ERROR;
buffer->pos = buffer->start;
buffer->last = buffer->start + size;
if (flush) {
buffer->event = ngx_pcalloc(cf->pool, sizeof(ngx_event_t));
if (buffer->event == NULL) {
return NGX_CONF_ERROR;
}
buffer->event->data = log->file;
buffer->event->handler = ngx_http_log_flush_handler;
buffer->event->log = &cf->cycle->new_log;
buffer->flush = flush;
}
log->file->pos = log->file->buffer;
log->file->last = log->file->buffer + buf;
buffer->gzip = gzip;
log->file->flush = ngx_http_log_flush;
log->file->data = buffer;
}
return NGX_CONF_OK;
@ -1146,12 +1456,6 @@ ngx_http_log_compile_format(ngx_conf_t *cf, ngx_array_t *flushes,
goto invalid;
}
if (ngx_strncmp(var.data, "apache_bytes_sent", 17) == 0) {
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
"use \"$body_bytes_sent\" instead of "
"\"$apache_bytes_sent\"");
}
for (v = ngx_http_log_vars; v->name.len; v++) {
if (v->name.len == var.len

View File

@ -110,7 +110,6 @@ ngx_http_map_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
{
ngx_http_map_ctx_t *map = (ngx_http_map_ctx_t *) data;
size_t len;
ngx_str_t val;
ngx_http_variable_value_t *value;
@ -121,10 +120,8 @@ ngx_http_map_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
return NGX_ERROR;
}
len = val.len;
if (len && map->hostnames && val.data[len - 1] == '.') {
len--;
if (map->hostnames && val.len > 0 && val.data[val.len - 1] == '.') {
val.len--;
}
value = ngx_http_map_find(r, &map->map, &val);
@ -212,6 +209,13 @@ ngx_http_map_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
name = value[2];
if (name.data[0] != '$') {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid variable name \"%V\"", &name);
return NGX_CONF_ERROR;
}
name.len--;
name.data++;
@ -281,6 +285,8 @@ ngx_http_map_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
map->default_value = ctx.default_value ? ctx.default_value:
&ngx_http_variable_null_value;
map->hostnames = ctx.hostnames;
hash.key = ngx_hash_key_lc;
hash.max_size = mcf->hash_max_size;
hash.bucket_size = mcf->hash_bucket_size;
@ -370,7 +376,7 @@ static char *
ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
{
ngx_int_t rc, index;
ngx_str_t *value, file, name;
ngx_str_t *value, name;
ngx_uint_t i, key;
ngx_http_map_conf_ctx_t *ctx;
ngx_http_variable_value_t *var, **vp;
@ -392,15 +398,7 @@ ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
}
if (ngx_strcmp(value[0].data, "include") == 0) {
file = value[1];
if (ngx_conf_full_name(cf->cycle, &file, 1) != NGX_OK) {
return NGX_CONF_ERROR;
}
ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);
return ngx_conf_parse(cf, &file);
return ngx_conf_include(cf, dummy, conf);
}
if (value[1].data[0] == '$') {
@ -417,11 +415,12 @@ ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
for (i = 0; i < ctx->var_values.nelts; i++) {
if (index == (ngx_int_t) var[i].data) {
var = &var[i];
goto found;
}
}
var = ngx_palloc(ctx->keys.pool, sizeof(ngx_http_variable_value_t));
var = ngx_array_push(&ctx->var_values);
if (var == NULL) {
return NGX_CONF_ERROR;
}
@ -432,13 +431,6 @@ ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
var->len = 0;
var->data = (u_char *) index;
vp = ngx_array_push(&ctx->var_values);
if (vp == NULL) {
return NGX_CONF_ERROR;
}
*vp = var;
goto found;
}

View File

@ -616,7 +616,7 @@ ngx_http_mp4_handler(ngx_http_request_t *r)
b->file_last = of.size;
b->in_file = b->file_last ? 1 : 0;
b->last_buf = 1;
b->last_buf = (r == r->main) ? 1 : 0;
b->last_in_chain = 1;
b->file->fd = of.fd;
@ -750,6 +750,13 @@ ngx_http_mp4_process(ngx_http_mp4_file_t *mp4)
*prev = &mp4->mdat_atom;
if (start_offset > mp4->mdat_data.buf->file_last) {
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
"start time is out mp4 mdat atom in \"%s\"",
mp4->file.name.data);
return NGX_ERROR;
}
adjustment = mp4->ftyp_size + mp4->moov_size
+ ngx_http_mp4_update_mdat_atom(mp4, start_offset)
- start_offset;
@ -1024,6 +1031,10 @@ ngx_http_mp4_read_moov_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
+ NGX_HTTP_MP4_MOOV_BUFFER_EXCESS * no_mdat;
}
if (ngx_http_mp4_read(mp4, (size_t) atom_data_size) != NGX_OK) {
return NGX_ERROR;
}
mp4->trak.elts = &mp4->traks;
mp4->trak.size = sizeof(ngx_http_mp4_trak_t);
mp4->trak.nalloc = 2;
@ -1044,6 +1055,12 @@ ngx_http_mp4_read_moov_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
mp4->buffer_start = mp4->buffer_pos;
mp4->buffer_size = NGX_HTTP_MP4_MOOV_BUFFER_EXCESS;
if (mp4->buffer_start + mp4->buffer_size > mp4->buffer_end) {
mp4->buffer = NULL;
mp4->buffer_pos = NULL;
mp4->buffer_end = NULL;
}
} else {
/* skip atoms after moov atom */
mp4->offset = mp4->end;
@ -2488,7 +2505,13 @@ found:
ngx_mp4_set_32value(entry->chunk, 1);
if (trak->chunk_samples) {
if (trak->chunk_samples && next_chunk - trak->start_chunk == 2) {
/* last chunk in the entry */
ngx_mp4_set_32value(entry->samples, samples - trak->chunk_samples);
} else if (trak->chunk_samples) {
first = &trak->stsc_chunk_entry;
ngx_mp4_set_32value(first->chunk, 1);
@ -2504,6 +2527,7 @@ found:
ngx_mp4_set_32value(entry->chunk, 2);
entries++;
atom_size += sizeof(ngx_mp4_stsc_entry_t);
}

View File

@ -836,7 +836,7 @@ ngx_http_proxy_create_key(ngx_http_request_t *r)
return NGX_ERROR;
}
if (plcf->cache_key.value.len) {
if (plcf->cache_key.value.data) {
if (ngx_http_complex_value(r, &plcf->cache_key, key) != NGX_OK) {
return NGX_ERROR;
@ -1610,7 +1610,8 @@ ngx_http_proxy_copy_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
p->upstream_done = 1;
ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
"upstream sent too much data");
"upstream sent more data than specified in "
"\"Content-Length\" header");
}
return NGX_OK;
@ -1864,6 +1865,10 @@ data:
}
if (ctx->size < 0 || ctx->length < 0) {
goto invalid;
}
return rc;
done:
@ -2607,7 +2612,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
* conf->upstream.store_lengths = NULL;
* conf->upstream.store_values = NULL;
*
* conf->method = NULL;
* conf->method = { 0, NULL };
* conf->headers_source = NULL;
* conf->headers_set_len = NULL;
* conf->headers_set = NULL;
@ -2906,10 +2911,11 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
#endif
if (conf->method.len == 0) {
conf->method = prev->method;
ngx_conf_merge_str_value(conf->method, prev->method, "");
} else {
if (conf->method.len
&& conf->method.data[conf->method.len - 1] != ' ')
{
conf->method.data[conf->method.len] = ' ';
conf->method.len++;
}
@ -3918,7 +3924,7 @@ ngx_http_proxy_cache_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
value = cf->args->elts;
if (plcf->cache_key.value.len) {
if (plcf->cache_key.value.data) {
return "is duplicate";
}

View File

@ -16,13 +16,11 @@
typedef struct {
ngx_array_t *from; /* array of ngx_in_cidr_t */
ngx_array_t *from; /* array of ngx_cidr_t */
ngx_uint_t type;
ngx_uint_t hash;
ngx_str_t header;
#if (NGX_HAVE_UNIX_DOMAIN)
ngx_uint_t unixsock; /* unsigned unixsock:2; */
#endif
ngx_flag_t recursive;
} ngx_http_realip_loc_conf_t;
@ -35,8 +33,8 @@ typedef struct {
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, u_char *ip,
size_t len);
static ngx_int_t ngx_http_realip_set_addr(ngx_http_request_t *r,
ngx_addr_t *addr);
static void ngx_http_realip_cleanup(void *data);
static char *ngx_http_realip_from(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
@ -63,6 +61,13 @@ static ngx_command_t ngx_http_realip_commands[] = {
0,
NULL },
{ ngx_string("real_ip_recursive"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_realip_loc_conf_t, recursive),
NULL },
ngx_null_command
};
@ -105,10 +110,9 @@ ngx_http_realip_handler(ngx_http_request_t *r)
u_char *ip, *p;
size_t len;
ngx_uint_t i, hash;
ngx_addr_t addr;
ngx_list_part_t *part;
ngx_table_elt_t *header;
struct sockaddr_in *sin;
ngx_in_cidr_t *from;
ngx_connection_t *c;
ngx_http_realip_ctx_t *ctx;
ngx_http_realip_loc_conf_t *rlcf;
@ -121,12 +125,7 @@ ngx_http_realip_handler(ngx_http_request_t *r)
rlcf = ngx_http_get_module_loc_conf(r, ngx_http_realip_module);
if (rlcf->from == NULL
#if (NGX_HAVE_UNIX_DOMAIN)
&& !rlcf->unixsock
#endif
)
{
if (rlcf->from == NULL) {
return NGX_DECLINED;
}
@ -152,15 +151,6 @@ ngx_http_realip_handler(ngx_http_request_t *r)
len = r->headers_in.x_forwarded_for->value.len;
ip = r->headers_in.x_forwarded_for->value.data;
for (p = ip + len - 1; p > ip; p--) {
if (*p == ' ' || *p == ',') {
p++;
len -= p - ip;
ip = p;
break;
}
}
break;
default: /* NGX_HTTP_REALIP_HEADER */
@ -204,42 +194,27 @@ found:
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "realip: \"%s\"", ip);
/* AF_INET only */
addr.sockaddr = c->sockaddr;
addr.socklen = c->socklen;
/* addr.name = c->addr_text; */
if (c->sockaddr->sa_family == AF_INET) {
sin = (struct sockaddr_in *) c->sockaddr;
from = rlcf->from->elts;
for (i = 0; i < rlcf->from->nelts; i++) {
ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
"realip: %08XD %08XD %08XD",
sin->sin_addr.s_addr, from[i].mask, from[i].addr);
if ((sin->sin_addr.s_addr & from[i].mask) == from[i].addr) {
return ngx_http_realip_set_addr(r, ip, len);
}
}
if (ngx_http_get_forwarded_addr(r, &addr, ip, len, rlcf->from,
rlcf->recursive)
== NGX_OK)
{
return ngx_http_realip_set_addr(r, &addr);
}
#if (NGX_HAVE_UNIX_DOMAIN)
if (c->sockaddr->sa_family == AF_UNIX && rlcf->unixsock) {
return ngx_http_realip_set_addr(r, ip, len);
}
#endif
return NGX_DECLINED;
}
static ngx_int_t
ngx_http_realip_set_addr(ngx_http_request_t *r, u_char *ip, size_t len)
ngx_http_realip_set_addr(ngx_http_request_t *r, ngx_addr_t *addr)
{
size_t len;
u_char *p;
ngx_int_t rc;
ngx_addr_t addr;
u_char text[NGX_SOCKADDR_STRLEN];
ngx_connection_t *c;
ngx_pool_cleanup_t *cln;
ngx_http_realip_ctx_t *ctx;
@ -254,15 +229,9 @@ ngx_http_realip_set_addr(ngx_http_request_t *r, u_char *ip, size_t len)
c = r->connection;
rc = ngx_parse_addr(c->pool, &addr, ip, len);
switch (rc) {
case NGX_DECLINED:
return NGX_DECLINED;
case NGX_ERROR:
len = ngx_sock_ntop(addr->sockaddr, text, NGX_SOCKADDR_STRLEN, 0);
if (len == 0) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
default: /* NGX_OK */
break;
}
p = ngx_pnalloc(c->pool, len);
@ -270,7 +239,7 @@ ngx_http_realip_set_addr(ngx_http_request_t *r, u_char *ip, size_t len)
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
ngx_memcpy(p, ip, len);
ngx_memcpy(p, text, len);
cln->handler = ngx_http_realip_cleanup;
@ -279,8 +248,8 @@ ngx_http_realip_set_addr(ngx_http_request_t *r, u_char *ip, size_t len)
ctx->socklen = c->socklen;
ctx->addr_text = c->addr_text;
c->sockaddr = addr.sockaddr;
c->socklen = addr.socklen;
c->sockaddr = addr->sockaddr;
c->socklen = addr->socklen;
c->addr_text.len = len;
c->addr_text.data = p;
@ -310,34 +279,33 @@ ngx_http_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_int_t rc;
ngx_str_t *value;
ngx_cidr_t cidr;
ngx_in_cidr_t *from;
ngx_cidr_t *cidr;
value = cf->args->elts;
#if (NGX_HAVE_UNIX_DOMAIN)
if (ngx_strcmp(value[1].data, "unix:") == 0) {
rlcf->unixsock = 1;
return NGX_CONF_OK;
}
#endif
if (rlcf->from == NULL) {
rlcf->from = ngx_array_create(cf->pool, 2,
sizeof(ngx_in_cidr_t));
sizeof(ngx_cidr_t));
if (rlcf->from == NULL) {
return NGX_CONF_ERROR;
}
}
from = ngx_array_push(rlcf->from);
if (from == NULL) {
cidr = ngx_array_push(rlcf->from);
if (cidr == NULL) {
return NGX_CONF_ERROR;
}
rc = ngx_ptocidr(&value[1], &cidr);
#if (NGX_HAVE_UNIX_DOMAIN)
if (ngx_strcmp(value[1].data, "unix:") == 0) {
cidr->family = AF_UNIX;
return NGX_CONF_OK;
}
#endif
rc = ngx_ptocidr(&value[1], cidr);
if (rc == NGX_ERROR) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"",
@ -345,20 +313,11 @@ ngx_http_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
if (cidr.family != AF_INET) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"\"set_real_ip_from\" supports IPv4 only");
return NGX_CONF_ERROR;
}
if (rc == NGX_DONE) {
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
"low address bits of %V are meaningless", &value[1]);
}
from->mask = cidr.u.in.mask;
from->addr = cidr.u.in.addr;
return NGX_CONF_OK;
}
@ -409,9 +368,7 @@ ngx_http_realip_create_loc_conf(ngx_conf_t *cf)
*/
conf->type = NGX_CONF_UNSET_UINT;
#if (NGX_HAVE_UNIX_DOMAIN)
conf->unixsock = 2;
#endif
conf->recursive = NGX_CONF_UNSET;
return conf;
}
@ -427,13 +384,8 @@ ngx_http_realip_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
conf->from = prev->from;
}
#if (NGX_HAVE_UNIX_DOMAIN)
if (conf->unixsock == 2) {
conf->unixsock = (prev->unixsock == 2) ? 0 : prev->unixsock;
}
#endif
ngx_conf_merge_uint_value(conf->type, prev->type, NGX_HTTP_REALIP_XREALIP);
ngx_conf_merge_value(conf->recursive, prev->recursive, 0);
if (conf->header.len == 0) {
conf->hash = prev->hash;

View File

@ -485,6 +485,12 @@ ngx_http_rewrite_return(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
} else {
if (ret->status > 999) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid return code \"%V\"", &value[1]);
return NGX_CONF_ERROR;
}
if (cf->args->nelts == 2) {
return NGX_CONF_OK;
}

View File

@ -434,6 +434,7 @@ ngx_http_scgi_handler(ngx_http_request_t *r)
u->process_header = ngx_http_scgi_process_status_line;
u->abort_request = ngx_http_scgi_abort_request;
u->finalize_request = ngx_http_scgi_finalize_request;
r->state = 0;
u->buffering = scf->upstream.buffering;
@ -843,6 +844,7 @@ ngx_http_scgi_reinit_request(ngx_http_request_t *r)
status->end = NULL;
r->upstream->process_header = ngx_http_scgi_process_status_line;
r->state = 0;
return NGX_OK;
}
@ -1763,7 +1765,7 @@ ngx_http_scgi_cache_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
value = cf->args->elts;
if (scf->cache_key.value.len) {
if (scf->cache_key.value.data) {
return "is duplicate";
}

View File

@ -111,7 +111,7 @@ ngx_http_secure_link_variable(ngx_http_request_t *r,
conf = ngx_http_get_module_loc_conf(r, ngx_http_secure_link_module);
if (conf->secret.len) {
if (conf->secret.data) {
return ngx_http_secure_link_old_variable(r, conf, v, data);
}
@ -318,7 +318,16 @@ ngx_http_secure_link_merge_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_http_secure_link_conf_t *prev = parent;
ngx_http_secure_link_conf_t *conf = child;
ngx_conf_merge_str_value(conf->secret, prev->secret, "");
if (conf->secret.data) {
if (conf->variable || conf->md5) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"\"secure_link_secret\" cannot be mixed with "
"\"secure_link\" and \"secure_link_md5\"");
return NGX_CONF_ERROR;
}
return NGX_CONF_OK;
}
if (conf->variable == NULL) {
conf->variable = prev->variable;
@ -328,6 +337,10 @@ ngx_http_secure_link_merge_conf(ngx_conf_t *cf, void *parent, void *child)
conf->md5 = prev->md5;
}
if (conf->variable == NULL && conf->md5 == NULL) {
conf->secret = prev->secret;
}
return NGX_CONF_OK;
}

View File

@ -138,6 +138,13 @@ ngx_conf_split_clients_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
name = value[2];
if (name.data[0] != '$') {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid variable name \"%V\"", &name);
return NGX_CONF_ERROR;
}
name.len--;
name.data++;
@ -211,7 +218,7 @@ ngx_http_split_clients(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
part->percent = 0;
} else {
if (value[0].data[value[0].len - 1] != '%') {
if (value[0].len == 0 || value[0].data[value[0].len - 1] != '%') {
goto invalid;
}

View File

@ -1024,6 +1024,7 @@ ngx_http_ssi_parse(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx)
switch (state) {
case ssi_start_state:
/* not reached */
break;
case ssi_tag_state:

View File

@ -48,6 +48,7 @@ static ngx_conf_enum_t ngx_http_ssl_verify[] = {
{ ngx_string("off"), 0 },
{ ngx_string("on"), 1 },
{ ngx_string("optional"), 2 },
{ ngx_string("optional_no_ca"), 3 },
{ ngx_null_string, 0 }
};
@ -466,7 +467,7 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
if (conf->verify) {
if (conf->client_certificate.len == 0) {
if (conf->client_certificate.len == 0 && conf->verify != 3) {
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
"no ssl_client_certificate for ssl_client_verify");
return NGX_CONF_ERROR;
@ -592,7 +593,6 @@ ngx_http_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
for (j = sizeof("shared:") - 1; j < value[i].len; j++) {
if (value[i].data[j] == ':') {
value[i].data[j] = '\0';
break;
}

View File

@ -121,7 +121,7 @@ static ngx_int_t ngx_http_status_handler(ngx_http_request_t *r)
r->headers_out.status = NGX_HTTP_OK;
r->headers_out.content_length_n = b->last - b->pos;
b->last_buf = 1;
b->last_buf = (r == r->main) ? 1 : 0;
rc = ngx_http_send_header(r);

View File

@ -627,7 +627,7 @@ ngx_http_sub_filter(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_str_t *value;
ngx_http_compile_complex_value_t ccv;
if (slcf->match.len) {
if (slcf->match.data) {
return "is duplicate";
}
@ -687,7 +687,7 @@ ngx_http_sub_merge_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_value(conf->once, prev->once, 1);
ngx_conf_merge_str_value(conf->match, prev->match, "");
if (conf->value.value.len == 0) {
if (conf->value.value.data == NULL) {
conf->value = prev->value;
}

View File

@ -16,7 +16,8 @@ typedef struct {
ngx_uint_t hash;
u_char addr[3];
u_char addrlen;
u_char *addr;
u_char tries;
@ -76,7 +77,10 @@ ngx_module_t ngx_http_upstream_ip_hash_module = {
};
ngx_int_t
static u_char ngx_http_upstream_ip_hash_pseudo_addr[3];
static ngx_int_t
ngx_http_upstream_init_ip_hash(ngx_conf_t *cf, ngx_http_upstream_srv_conf_t *us)
{
if (ngx_http_upstream_init_round_robin(cf, us) != NGX_OK) {
@ -93,8 +97,10 @@ static ngx_int_t
ngx_http_upstream_init_ip_hash_peer(ngx_http_request_t *r,
ngx_http_upstream_srv_conf_t *us)
{
u_char *p;
struct sockaddr_in *sin;
#if (NGX_HAVE_INET6)
struct sockaddr_in6 *sin6;
#endif
ngx_http_upstream_ip_hash_peer_data_t *iphp;
iphp = ngx_palloc(r->pool, sizeof(ngx_http_upstream_ip_hash_peer_data_t));
@ -110,20 +116,25 @@ ngx_http_upstream_init_ip_hash_peer(ngx_http_request_t *r,
r->upstream->peer.get = ngx_http_upstream_get_ip_hash_peer;
/* AF_INET only */
if (r->connection->sockaddr->sa_family == AF_INET) {
switch (r->connection->sockaddr->sa_family) {
case AF_INET:
sin = (struct sockaddr_in *) r->connection->sockaddr;
p = (u_char *) &sin->sin_addr.s_addr;
iphp->addr[0] = p[0];
iphp->addr[1] = p[1];
iphp->addr[2] = p[2];
iphp->addr = (u_char *) &sin->sin_addr.s_addr;
iphp->addrlen = 3;
break;
} else {
iphp->addr[0] = 0;
iphp->addr[1] = 0;
iphp->addr[2] = 0;
#if (NGX_HAVE_INET6)
case AF_INET6:
sin6 = (struct sockaddr_in6 *) r->connection->sockaddr;
iphp->addr = (u_char *) &sin6->sin6_addr.s6_addr;
iphp->addrlen = 16;
break;
#endif
default:
iphp->addr = ngx_http_upstream_ip_hash_pseudo_addr;
iphp->addrlen = 3;
}
iphp->hash = 89;
@ -140,6 +151,7 @@ ngx_http_upstream_get_ip_hash_peer(ngx_peer_connection_t *pc, void *data)
ngx_http_upstream_ip_hash_peer_data_t *iphp = data;
time_t now;
ngx_int_t w;
uintptr_t m;
ngx_uint_t i, n, p, hash;
ngx_http_upstream_rr_peer_t *peer;
@ -162,11 +174,25 @@ ngx_http_upstream_get_ip_hash_peer(ngx_peer_connection_t *pc, void *data)
for ( ;; ) {
for (i = 0; i < 3; i++) {
for (i = 0; i < iphp->addrlen; i++) {
hash = (hash * 113 + iphp->addr[i]) % 6271;
}
p = hash % iphp->rrp.peers->number;
if (!iphp->rrp.peers->weighted) {
p = hash % iphp->rrp.peers->number;
} else {
w = hash % iphp->rrp.peers->total_weight;
for (i = 0; i < iphp->rrp.peers->number; i++) {
w -= iphp->rrp.peers->peer[i].weight;
if (w < 0) {
break;
}
}
p = i;
}
n = p / (8 * sizeof(uintptr_t));
m = (uintptr_t) 1 << p % (8 * sizeof(uintptr_t));
@ -229,6 +255,7 @@ ngx_http_upstream_ip_hash(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
uscf->peer.init_upstream = ngx_http_upstream_init_ip_hash;
uscf->flags = NGX_HTTP_UPSTREAM_CREATE
|NGX_HTTP_UPSTREAM_WEIGHT
|NGX_HTTP_UPSTREAM_MAX_FAILS
|NGX_HTTP_UPSTREAM_FAIL_TIMEOUT
|NGX_HTTP_UPSTREAM_DOWN;

View File

@ -12,7 +12,6 @@
typedef struct {
ngx_uint_t max_cached;
ngx_uint_t single; /* unsigned:1 */
ngx_queue_t cache;
ngx_queue_t free;
@ -38,8 +37,6 @@ typedef struct {
ngx_event_save_peer_session_pt original_save_session;
#endif
ngx_uint_t failed; /* unsigned:1 */
} ngx_http_upstream_keepalive_peer_data_t;
@ -221,38 +218,11 @@ ngx_http_upstream_get_keepalive_peer(ngx_peer_connection_t *pc, void *data)
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0,
"get keepalive peer");
kp->failed = 0;
/* single pool of cached connections */
if (kp->conf->single && !ngx_queue_empty(&kp->conf->cache)) {
q = ngx_queue_head(&kp->conf->cache);
item = ngx_queue_data(q, ngx_http_upstream_keepalive_cache_t, queue);
c = item->connection;
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->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;
}
/* ask balancer */
rc = kp->original_get_peer(pc, kp->data);
if (kp->conf->single || rc != NGX_OK) {
if (rc != NGX_OK) {
return rc;
}
@ -308,18 +278,12 @@ ngx_http_upstream_free_keepalive_peer(ngx_peer_connection_t *pc, void *data,
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0,
"free keepalive peer");
/* remember failed state - peer.free() may be called more than once */
if (state & NGX_PEER_FAILED) {
kp->failed = 1;
}
/* cache valid connections */
u = kp->upstream;
c = pc->connection;
if (kp->failed
if (state & NGX_PEER_FAILED
|| c == NULL
|| c->read->eof
|| c->read->error
@ -528,6 +492,10 @@ ngx_http_upstream_keepalive(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
kcf = ngx_http_conf_upstream_srv_conf(uscf,
ngx_http_upstream_keepalive_module);
if (kcf->original_init_upstream) {
return "is duplicate";
}
kcf->original_init_upstream = uscf->peer.init_upstream
? uscf->peer.init_upstream
: ngx_http_upstream_init_round_robin;
@ -552,7 +520,8 @@ ngx_http_upstream_keepalive(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
for (i = 2; i < cf->args->nelts; i++) {
if (ngx_strcmp(value[i].data, "single") == 0) {
kcf->single = 1;
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
"the \"single\" parameter is deprecated");
continue;
}

View File

@ -0,0 +1,400 @@
/*
* Copyright (C) Maxim Dounin
* Copyright (C) Nginx, Inc.
*/
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
typedef struct {
ngx_uint_t *conns;
} ngx_http_upstream_least_conn_conf_t;
typedef struct {
/* the round robin data must be first */
ngx_http_upstream_rr_peer_data_t rrp;
ngx_uint_t *conns;
ngx_event_get_peer_pt get_rr_peer;
ngx_event_free_peer_pt free_rr_peer;
} ngx_http_upstream_lc_peer_data_t;
static ngx_int_t ngx_http_upstream_init_least_conn_peer(ngx_http_request_t *r,
ngx_http_upstream_srv_conf_t *us);
static ngx_int_t ngx_http_upstream_get_least_conn_peer(
ngx_peer_connection_t *pc, void *data);
static void ngx_http_upstream_free_least_conn_peer(ngx_peer_connection_t *pc,
void *data, ngx_uint_t state);
static void *ngx_http_upstream_least_conn_create_conf(ngx_conf_t *cf);
static char *ngx_http_upstream_least_conn(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static ngx_command_t ngx_http_upstream_least_conn_commands[] = {
{ ngx_string("least_conn"),
NGX_HTTP_UPS_CONF|NGX_CONF_NOARGS,
ngx_http_upstream_least_conn,
0,
0,
NULL },
ngx_null_command
};
static ngx_http_module_t ngx_http_upstream_least_conn_module_ctx = {
NULL, /* preconfiguration */
NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
ngx_http_upstream_least_conn_create_conf, /* create server configuration */
NULL, /* merge server configuration */
NULL, /* create location configuration */
NULL /* merge location configuration */
};
ngx_module_t ngx_http_upstream_least_conn_module = {
NGX_MODULE_V1,
&ngx_http_upstream_least_conn_module_ctx, /* module context */
ngx_http_upstream_least_conn_commands, /* module directives */
NGX_HTTP_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_http_upstream_init_least_conn(ngx_conf_t *cf,
ngx_http_upstream_srv_conf_t *us)
{
ngx_uint_t n;
ngx_http_upstream_rr_peers_t *peers;
ngx_http_upstream_least_conn_conf_t *lcf;
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cf->log, 0,
"init least conn");
if (ngx_http_upstream_init_round_robin(cf, us) != NGX_OK) {
return NGX_ERROR;
}
peers = us->peer.data;
n = peers->number;
if (peers->next) {
n += peers->next->number;
}
lcf = ngx_http_conf_upstream_srv_conf(us,
ngx_http_upstream_least_conn_module);
lcf->conns = ngx_pcalloc(cf->pool, sizeof(ngx_uint_t) * n);
if (lcf->conns == NULL) {
return NGX_ERROR;
}
us->peer.init = ngx_http_upstream_init_least_conn_peer;
return NGX_OK;
}
static ngx_int_t
ngx_http_upstream_init_least_conn_peer(ngx_http_request_t *r,
ngx_http_upstream_srv_conf_t *us)
{
ngx_http_upstream_lc_peer_data_t *lcp;
ngx_http_upstream_least_conn_conf_t *lcf;
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"init least conn peer");
lcf = ngx_http_conf_upstream_srv_conf(us,
ngx_http_upstream_least_conn_module);
lcp = ngx_palloc(r->pool, sizeof(ngx_http_upstream_lc_peer_data_t));
if (lcp == NULL) {
return NGX_ERROR;
}
lcp->conns = lcf->conns;
r->upstream->peer.data = &lcp->rrp;
if (ngx_http_upstream_init_round_robin_peer(r, us) != NGX_OK) {
return NGX_ERROR;
}
r->upstream->peer.get = ngx_http_upstream_get_least_conn_peer;
r->upstream->peer.free = ngx_http_upstream_free_least_conn_peer;
lcp->get_rr_peer = ngx_http_upstream_get_round_robin_peer;
lcp->free_rr_peer = ngx_http_upstream_free_round_robin_peer;
return NGX_OK;
}
static ngx_int_t
ngx_http_upstream_get_least_conn_peer(ngx_peer_connection_t *pc, void *data)
{
ngx_http_upstream_lc_peer_data_t *lcp = data;
time_t now;
uintptr_t m;
ngx_int_t rc, total;
ngx_uint_t i, n, p, many;
ngx_http_upstream_rr_peer_t *peer, *best;
ngx_http_upstream_rr_peers_t *peers;
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
"get least conn peer, try: %ui", pc->tries);
if (lcp->rrp.peers->single) {
return lcp->get_rr_peer(pc, &lcp->rrp);
}
pc->cached = 0;
pc->connection = NULL;
now = ngx_time();
peers = lcp->rrp.peers;
best = NULL;
total = 0;
#if (NGX_SUPPRESS_WARN)
many = 0;
p = 0;
#endif
for (i = 0; i < peers->number; i++) {
n = i / (8 * sizeof(uintptr_t));
m = (uintptr_t) 1 << i % (8 * sizeof(uintptr_t));
if (lcp->rrp.tried[n] & m) {
continue;
}
peer = &peers->peer[i];
if (peer->down) {
continue;
}
if (peer->max_fails
&& peer->fails >= peer->max_fails
&& now - peer->checked <= peer->fail_timeout)
{
continue;
}
/*
* select peer with least number of connections; if there are
* multiple peers with the same number of connections, select
* based on round-robin
*/
if (best == NULL
|| lcp->conns[i] * best->weight < lcp->conns[p] * peer->weight)
{
best = peer;
many = 0;
p = i;
} else if (lcp->conns[i] * best->weight
== lcp->conns[p] * peer->weight)
{
many = 1;
}
}
if (best == NULL) {
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0,
"get least conn peer, no peer found");
goto failed;
}
if (many) {
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0,
"get least conn peer, many");
for (i = p; i < peers->number; i++) {
n = i / (8 * sizeof(uintptr_t));
m = (uintptr_t) 1 << i % (8 * sizeof(uintptr_t));
if (lcp->rrp.tried[n] & m) {
continue;
}
peer = &peers->peer[i];
if (peer->down) {
continue;
}
if (lcp->conns[i] * best->weight != lcp->conns[p] * peer->weight) {
continue;
}
if (peer->max_fails
&& peer->fails >= peer->max_fails
&& now - peer->checked <= peer->fail_timeout)
{
continue;
}
peer->current_weight += peer->effective_weight;
total += peer->effective_weight;
if (peer->effective_weight < peer->weight) {
peer->effective_weight++;
}
if (peer->current_weight > best->current_weight) {
best = peer;
p = i;
}
}
}
best->current_weight -= total;
best->checked = now;
pc->sockaddr = best->sockaddr;
pc->socklen = best->socklen;
pc->name = &best->name;
lcp->rrp.current = p;
n = p / (8 * sizeof(uintptr_t));
m = (uintptr_t) 1 << p % (8 * sizeof(uintptr_t));
lcp->rrp.tried[n] |= m;
lcp->conns[p]++;
if (pc->tries == 1 && peers->next) {
pc->tries += peers->next->number;
}
return NGX_OK;
failed:
if (peers->next) {
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0,
"get least conn peer, backup servers");
lcp->conns += peers->number;
lcp->rrp.peers = peers->next;
pc->tries = lcp->rrp.peers->number;
n = (lcp->rrp.peers->number + (8 * sizeof(uintptr_t) - 1))
/ (8 * sizeof(uintptr_t));
for (i = 0; i < n; i++) {
lcp->rrp.tried[i] = 0;
}
rc = ngx_http_upstream_get_least_conn_peer(pc, lcp);
if (rc != NGX_BUSY) {
return rc;
}
}
/* all peers failed, mark them as live for quick recovery */
for (i = 0; i < peers->number; i++) {
peers->peer[i].fails = 0;
}
pc->name = peers->name;
return NGX_BUSY;
}
static void
ngx_http_upstream_free_least_conn_peer(ngx_peer_connection_t *pc,
void *data, ngx_uint_t state)
{
ngx_http_upstream_lc_peer_data_t *lcp = data;
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
"free least conn peer %ui %ui", pc->tries, state);
if (lcp->rrp.peers->single) {
lcp->free_rr_peer(pc, &lcp->rrp, state);
return;
}
lcp->conns[lcp->rrp.current]--;
lcp->free_rr_peer(pc, &lcp->rrp, state);
}
static void *
ngx_http_upstream_least_conn_create_conf(ngx_conf_t *cf)
{
ngx_http_upstream_least_conn_conf_t *conf;
conf = ngx_pcalloc(cf->pool,
sizeof(ngx_http_upstream_least_conn_conf_t));
if (conf == NULL) {
return NULL;
}
/*
* set by ngx_pcalloc():
*
* conf->conns = NULL;
*/
return conf;
}
static char *
ngx_http_upstream_least_conn(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_upstream_srv_conf_t *uscf;
uscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module);
uscf->peer.init_upstream = ngx_http_upstream_init_least_conn;
uscf->flags = NGX_HTTP_UPSTREAM_CREATE
|NGX_HTTP_UPSTREAM_WEIGHT
|NGX_HTTP_UPSTREAM_MAX_FAILS
|NGX_HTTP_UPSTREAM_FAIL_TIMEOUT
|NGX_HTTP_UPSTREAM_DOWN
|NGX_HTTP_UPSTREAM_BACKUP;
return NGX_CONF_OK;
}

View File

@ -467,6 +467,7 @@ ngx_http_uwsgi_handler(ngx_http_request_t *r)
u->process_header = ngx_http_uwsgi_process_status_line;
u->abort_request = ngx_http_uwsgi_abort_request;
u->finalize_request = ngx_http_uwsgi_finalize_request;
r->state = 0;
u->buffering = uwcf->upstream.buffering;
@ -883,6 +884,7 @@ ngx_http_uwsgi_reinit_request(ngx_http_request_t *r)
status->end = NULL;
r->upstream->process_header = ngx_http_uwsgi_process_status_line;
r->state = 0;
return NGX_OK;
}
@ -1805,7 +1807,7 @@ ngx_http_uwsgi_cache_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
value = cf->args->elts;
if (uwcf->cache_key.value.len) {
if (uwcf->cache_key.value.data) {
return "is duplicate";
}

View File

@ -307,7 +307,7 @@ ngx_http_xslt_send(ngx_http_request_t *r, ngx_http_xslt_filter_ctx_t *ctx,
ctx->done = 1;
if (b == NULL) {
return ngx_http_filter_finalize_request(r, NULL,
return ngx_http_filter_finalize_request(r, &ngx_http_xslt_filter_module,
NGX_HTTP_INTERNAL_SERVER_ERROR);
}
@ -315,7 +315,7 @@ ngx_http_xslt_send(ngx_http_request_t *r, ngx_http_xslt_filter_ctx_t *ctx,
if (cln == NULL) {
ngx_free(b->pos);
return ngx_http_filter_finalize_request(r, NULL,
return ngx_http_filter_finalize_request(r, &ngx_http_xslt_filter_module,
NGX_HTTP_INTERNAL_SERVER_ERROR);
}
@ -810,7 +810,7 @@ ngx_http_xslt_entities(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
file = xmcf->dtd_files.elts;
for (i = 0; i < xmcf->dtd_files.nelts; i++) {
if (ngx_strcmp(file[i].name, &value[1].data) == 0) {
if (ngx_strcmp(file[i].name, value[1].data) == 0) {
xlcf->dtd = file[i].data;
return NGX_CONF_OK;
}
@ -884,7 +884,7 @@ ngx_http_xslt_stylesheet(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
file = xmcf->sheet_files.elts;
for (i = 0; i < xmcf->sheet_files.nelts; i++) {
if (ngx_strcmp(file[i].name, &value[1].data) == 0) {
if (ngx_strcmp(file[i].name, value[1].data) == 0) {
sheet->stylesheet = file[i].data;
goto found;
}

Some files were not shown because too many files have changed in this diff Show More