Merge branch 'nginx' (nginx-1.11.7). Change-Id: I85676807130d1ebe5fcbadd82e096b32401ec02f Signed-off-by: Piotr Sikora <piotrsikora@google.com>
diff --git a/.hgtags b/.hgtags index d4acb78..ffd9d06 100644 --- a/.hgtags +++ b/.hgtags
@@ -405,3 +405,4 @@ 953512ca02c6f63b4fcbbc3e10d0d9835896bf99 release-1.11.4 5253015a339aaca0a3111473d3e931b6d4752393 release-1.11.5 5e371426b3bcba4312ce08606194b89b758927d1 release-1.11.6 +5c8f60faf33ca8926473d2da27b4c3c417bd4630 release-1.11.7
diff --git a/BUILD b/BUILD index efc249a..1d3b91a 100644 --- a/BUILD +++ b/BUILD
@@ -1468,5 +1468,5 @@ preinst = "@nginx_pkgoss//:debian_preinst", prerm = "@nginx_pkgoss//:debian_prerm", section = "httpd", - version = "1.11.6", + version = "1.11.7", )
diff --git a/auto/lib/perl/conf b/auto/lib/perl/conf index 959690a..8310936 100644 --- a/auto/lib/perl/conf +++ b/auto/lib/perl/conf
@@ -12,9 +12,9 @@ if test -n "$NGX_PERL_VER"; then echo " + perl version: $NGX_PERL_VER" - if [ "`$NGX_PERL -e 'use 5.006001; print "OK"'`" != "OK" ]; then + if [ "`$NGX_PERL -e 'use 5.008006; print "OK"'`" != "OK" ]; then echo - echo "$0: error: perl 5.6.1 or higher is required" + echo "$0: error: perl 5.8.6 or higher is required" echo exit 1; @@ -76,7 +76,7 @@ else echo - echo "$0: error: perl 5.6.1 or higher is required" + echo "$0: error: perl 5.8.6 or higher is required" echo exit 1;
diff --git a/auto/make b/auto/make index 84d2668..7ddd100 100644 --- a/auto/make +++ b/auto/make
@@ -156,7 +156,7 @@ ngx_all_srcs="$ngx_all_srcs $MISC_SRCS" -if test -n "$NGX_ADDON_SRCS"; then +if test -n "$NGX_ADDON_SRCS$DYNAMIC_MODULES"; then cat << END >> $NGX_MAKEFILE @@ -499,17 +499,6 @@ ngx_perl_cc="$ngx_perl_cc \$(ALL_INCS)" fi -ngx_obj_deps="\$(CORE_DEPS)" -if [ $HTTP != NO ]; then - ngx_obj_deps="$ngx_obj_deps \$(HTTP_DEPS)" -fi -if [ $MAIL != NO ]; then - ngx_obj_deps="$ngx_obj_deps \$(MAIL_DEPS)" -fi -if [ $STREAM != NO ]; then - ngx_obj_deps="$ngx_obj_deps \$(STREAM_DEPS)" -fi - for ngx_module in $DYNAMIC_MODULES do eval ngx_module_srcs="\$${ngx_module}_SRCS" @@ -665,7 +654,7 @@ cat << END >> $NGX_MAKEFILE -$ngx_obj: $ngx_obj_deps$ngx_cont$ngx_src +$ngx_obj: \$(ADDON_DEPS)$ngx_cont$ngx_src $ngx_perl_cc$ngx_tab$ngx_objout$ngx_obj$ngx_tab$ngx_src$NGX_AUX END @@ -673,7 +662,7 @@ cat << END >> $NGX_MAKEFILE -$ngx_obj: $ngx_obj_deps$ngx_cont$ngx_src +$ngx_obj: \$(ADDON_DEPS)$ngx_cont$ngx_src $ngx_cc$ngx_tab$ngx_objout$ngx_obj$ngx_tab$ngx_src$NGX_AUX END
diff --git a/auto/module b/auto/module index 3b00a07..a2b578d 100644 --- a/auto/module +++ b/auto/module
@@ -35,6 +35,10 @@ CORE_INCS="$CORE_INCS $ngx_module_incs" fi + if test -n "$ngx_module_deps"; then + NGX_ADDON_DEPS="$NGX_ADDON_DEPS $ngx_module_deps" + fi + libs= for lib in $ngx_module_libs do
diff --git a/auto/modules b/auto/modules index 3b052ab..7b4f2fe 100644 --- a/auto/modules +++ b/auto/modules
@@ -1252,7 +1252,7 @@ elif [ $MAIL = DYNAMIC ]; then ngx_module_name=$MAIL_MODULES ngx_module_incs= - ngx_module_deps=$MAIL_DEPS + ngx_module_deps= ngx_module_srcs=$MAIL_SRCS ngx_module_libs= ngx_module_link=DYNAMIC @@ -1272,7 +1272,7 @@ elif [ $STREAM = DYNAMIC ]; then ngx_module_name=$STREAM_MODULES ngx_module_incs= - ngx_module_deps=$STREAM_DEPS + ngx_module_deps= ngx_module_srcs=$STREAM_SRCS ngx_module_libs= ngx_module_link=DYNAMIC
diff --git a/build.bzl b/build.bzl index 79fc28c..c3de23b 100644 --- a/build.bzl +++ b/build.bzl
@@ -668,7 +668,7 @@ name = "nginx_pkgoss", build_file_content = _PKGOSS_BUILD_FILE.format(nginx = nginx) + _PKGOSS_BUILD_FILE_TAIL, - commit = "f0a74a54c8948c668fe477f7fafb0f3a175ee19a", # nginx-1.11.6 + commit = "4a0aa6d52a93ef2ed0712edc3a67ac345caa9e14", # nginx-1.11.7 remote = "https://nginx.googlesource.com/nginx-pkgoss", )
diff --git a/docs/xml/nginx/changes.xml b/docs/xml/nginx/changes.xml index 1376338..0a440e4 100644 --- a/docs/xml/nginx/changes.xml +++ b/docs/xml/nginx/changes.xml
@@ -5,6 +5,100 @@ <change_log title="nginx"> +<changes ver="1.11.7" date="13.12.2016"> + +<change type="change"> +<para lang="ru"> +переменная $ssl_client_verify теперь +в случае ошибки проверки клиентского сертификата +содержит строку с описанием ошибки, +например, "FAILED:certificate has expired". +</para> +<para lang="en"> +now in case of a client certificate verification error +the $ssl_client_verify variable contains a string with the failure reason, +for example, "FAILED:certificate has expired". +</para> +</change> + +<change type="feature"> +<para lang="ru"> +переменные $ssl_ciphers, $ssl_curves, +$ssl_client_v_start, $ssl_client_v_end и $ssl_client_v_remain. +</para> +<para lang="en"> +the $ssl_ciphers, $ssl_curves, +$ssl_client_v_start, $ssl_client_v_end, and $ssl_client_v_remain variables. +</para> +</change> + +<change type="feature"> +<para lang="ru"> +параметр volatile директивы map. +</para> +<para lang="en"> +the "volatile" parameter of the "map" directive. +</para> +</change> + +<change type="bugfix"> +<para lang="ru"> +при сборке динамических модулей +не учитывались заданные для модуля зависимости. +</para> +<para lang="en"> +dependencies specified for a module +were ignored while building dynamic modules. +</para> +</change> + +<change type="bugfix"> +<para lang="ru"> +при использовании HTTP/2 и директив limit_req или auth_request +тело запроса могло быть повреждено; +ошибка появилась в 1.11.0. +</para> +<para lang="en"> +when using HTTP/2 and the "limit_req" or "auth_request" directives +client request body might be corrupted; +the bug had appeared in 1.11.0. +</para> +</change> + +<change type="bugfix"> +<para lang="ru"> +при использовании HTTP/2 в рабочем процессе мог произойти segmentation fault; +ошибка появилась в 1.11.3. +</para> +<para lang="en"> +a segmentation fault might occur in a worker process when using HTTP/2; +the bug had appeared in 1.11.3. +</para> +</change> + +<change type="bugfix"> +<para lang="ru"> +в модуле ngx_http_mp4_module.<br/> +Спасибо Congcong Hu. +</para> +<para lang="en"> +in the ngx_http_mp4_module.<br/> +Thanks to Congcong Hu. +</para> +</change> + +<change type="bugfix"> +<para lang="ru"> +в модуле ngx_http_perl_module. +</para> +<para lang="en"> +in the ngx_http_perl_module. +</para> +</change> + +</changes> + + <changes ver="1.11.6" date="15.11.2016"> <change type="change">
diff --git a/src/core/nginx.c b/src/core/nginx.c index 624608e..5e68f7d 100644 --- a/src/core/nginx.c +++ b/src/core/nginx.c
@@ -16,6 +16,7 @@ static void ngx_show_version_info(void); static ngx_int_t ngx_add_inherited_sockets(ngx_cycle_t *cycle); +static void ngx_cleanup_environment(void *data); static ngx_int_t ngx_get_options(int argc, char *const *argv); static ngx_int_t ngx_process_options(ngx_cycle_t *cycle); static ngx_int_t ngx_save_argv(ngx_cycle_t *cycle, int argc, char *const *argv); @@ -511,10 +512,11 @@ char ** ngx_set_environment(ngx_cycle_t *cycle, ngx_uint_t *last) { - char **p, **env; - ngx_str_t *var; - ngx_uint_t i, n; - ngx_core_conf_t *ccf; + char **p, **env; + ngx_str_t *var; + ngx_uint_t i, n; + ngx_core_conf_t *ccf; + ngx_pool_cleanup_t *cln; ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); @@ -566,14 +568,25 @@ if (last) { env = ngx_alloc((*last + n + 1) * sizeof(char *), cycle->log); + if (env == NULL) { + return NULL; + } + *last = n; } else { - env = ngx_palloc(cycle->pool, (n + 1) * sizeof(char *)); - } + cln = ngx_pool_cleanup_add(cycle->pool, 0); + if (cln == NULL) { + return NULL; + } - if (env == NULL) { - return NULL; + env = ngx_alloc((n + 1) * sizeof(char *), cycle->log); + if (env == NULL) { + return NULL; + } + + cln->handler = ngx_cleanup_environment; + cln->data = env; } n = 0; @@ -607,6 +620,25 @@ } +static void +ngx_cleanup_environment(void *data) +{ + char **env = data; + + if (environ == env) { + + /* + * if the environment is still used, as it happens on exit, + * the only option is to leak it + */ + + return; + } + + ngx_free(env); +} + + ngx_pid_t ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv) {
diff --git a/src/core/nginx.h b/src/core/nginx.h index 9f545d3..c8fb05f 100644 --- a/src/core/nginx.h +++ b/src/core/nginx.h
@@ -13,8 +13,8 @@ #define NGINX_NAME "nginx" #endif -#define nginx_version 1011006 -#define NGINX_VERSION "1.11.6" +#define nginx_version 1011007 +#define NGINX_VERSION "1.11.7" #define NGINX_VER NGINX_NAME "/" NGINX_VERSION #ifdef NGX_BUILD
diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c index a57991c..5e95628 100644 --- a/src/core/ngx_cycle.c +++ b/src/core/ngx_cycle.c
@@ -37,7 +37,7 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) { void *rv; - char **senv, **env; + char **senv; ngx_uint_t i, n; ngx_log_t *log; ngx_time_t *tp; @@ -750,20 +750,9 @@ if (ngx_process == NGX_PROCESS_MASTER || ngx_is_init_cycle(old_cycle)) { - /* - * perl_destruct() frees environ, if it is not the same as it was at - * perl_construct() time, therefore we save the previous cycle - * environment before ngx_conf_parse() where it will be changed. - */ - - env = environ; - environ = senv; - ngx_destroy_pool(old_cycle->pool); cycle->old_cycle = NULL; - environ = env; - return cycle; }
diff --git a/src/core/ngx_output_chain.c b/src/core/ngx_output_chain.c index f784578..7f5dc78 100644 --- a/src/core/ngx_output_chain.c +++ b/src/core/ngx_output_chain.c
@@ -512,7 +512,7 @@ size = ngx_buf_size(src); size = ngx_min(size, dst->end - dst->pos); - sendfile = ctx->sendfile & !ctx->directio; + sendfile = ctx->sendfile && !ctx->directio; #if (NGX_SENDFILE_LIMIT)
diff --git a/src/core/ngx_slab.c b/src/core/ngx_slab.c index 56e7765..66faecc 100644 --- a/src/core/ngx_slab.c +++ b/src/core/ngx_slab.c
@@ -41,6 +41,19 @@ #endif +#define ngx_slab_slots(pool) \ + (ngx_slab_page_t *) ((u_char *) (pool) + sizeof(ngx_slab_pool_t)) + +#define ngx_slab_page_type(page) ((page)->prev & NGX_SLAB_PAGE_MASK) + +#define ngx_slab_page_prev(page) \ + (ngx_slab_page_t *) ((page)->prev & ~NGX_SLAB_PAGE_MASK) + +#define ngx_slab_page_addr(pool, page) \ + ((((page) - (pool)->pages) << ngx_pagesize_shift) \ + + (uintptr_t) (pool)->start) + + #if (NGX_DEBUG_MALLOC) #define ngx_slab_junk(p, size) ngx_memset(p, 0xA5, size) @@ -76,7 +89,7 @@ size_t size; ngx_int_t m; ngx_uint_t i, n, pages; - ngx_slab_page_t *slots; + ngx_slab_page_t *slots, *page; /* STUB */ if (ngx_slab_max_size == 0) { @@ -90,15 +103,17 @@ pool->min_size = 1 << pool->min_shift; - p = (u_char *) pool + sizeof(ngx_slab_pool_t); + slots = ngx_slab_slots(pool); + + p = (u_char *) slots; size = pool->end - p; ngx_slab_junk(p, size); - slots = (ngx_slab_page_t *) p; n = ngx_pagesize_shift - pool->min_shift; for (i = 0; i < n; i++) { + /* only "next" is used in list head */ slots[i].slab = 0; slots[i].next = &slots[i]; slots[i].prev = 0; @@ -106,30 +121,40 @@ p += n * sizeof(ngx_slab_page_t); + pool->stats = (ngx_slab_stat_t *) p; + ngx_memzero(pool->stats, n * sizeof(ngx_slab_stat_t)); + + p += n * sizeof(ngx_slab_stat_t); + + size -= n * (sizeof(ngx_slab_page_t) + sizeof(ngx_slab_stat_t)); + pages = (ngx_uint_t) (size / (ngx_pagesize + sizeof(ngx_slab_page_t))); - ngx_memzero(p, pages * sizeof(ngx_slab_page_t)); - pool->pages = (ngx_slab_page_t *) p; + ngx_memzero(pool->pages, pages * sizeof(ngx_slab_page_t)); + page = pool->pages; + + /* only "next" is used in list head */ + pool->free.slab = 0; + pool->free.next = page; pool->free.prev = 0; - pool->free.next = (ngx_slab_page_t *) p; - pool->pages->slab = pages; - pool->pages->next = &pool->free; - pool->pages->prev = (uintptr_t) &pool->free; + page->slab = pages; + page->next = &pool->free; + page->prev = (uintptr_t) &pool->free; - pool->start = (u_char *) - ngx_align_ptr((uintptr_t) p + pages * sizeof(ngx_slab_page_t), - ngx_pagesize); + pool->start = ngx_align_ptr(p + pages * sizeof(ngx_slab_page_t), + ngx_pagesize); m = pages - (pool->end - pool->start) / ngx_pagesize; if (m > 0) { pages -= m; - pool->pages->slab = pages; + page->slab = pages; } pool->last = pool->pages + pages; + pool->pfree = pages; pool->log_nomem = 1; pool->log_ctx = &pool->zero; @@ -168,8 +193,7 @@ 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; + p = ngx_slab_page_addr(pool, page); } else { p = 0; @@ -184,166 +208,140 @@ slot = shift - pool->min_shift; } else { - size = pool->min_size; shift = pool->min_shift; slot = 0; } + pool->stats[slot].reqs++; + ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, ngx_cycle->log, 0, "slab alloc: %uz slot: %ui", size, slot); - slots = (ngx_slab_page_t *) ((u_char *) pool + sizeof(ngx_slab_pool_t)); + slots = ngx_slab_slots(pool); page = slots[slot].next; if (page->next != page) { if (shift < ngx_slab_exact_shift) { - do { - p = (page - pool->pages) << ngx_pagesize_shift; - bitmap = (uintptr_t *) (pool->start + p); + bitmap = (uintptr_t *) ngx_slab_page_addr(pool, page); - map = (1 << (ngx_pagesize_shift - shift)) - / (sizeof(uintptr_t) * 8); + map = (ngx_pagesize >> shift) / (sizeof(uintptr_t) * 8); - for (n = 0; n < map; n++) { + for (n = 0; n < map; n++) { - if (bitmap[n] != NGX_SLAB_BUSY) { + if (bitmap[n] != NGX_SLAB_BUSY) { - for (m = 1, i = 0; m; m <<= 1, i++) { - if ((bitmap[n] & m)) { - continue; - } - - bitmap[n] |= m; - - i = ((n * sizeof(uintptr_t) * 8) << shift) - + (i << shift); - - if (bitmap[n] == NGX_SLAB_BUSY) { - for (n = n + 1; n < map; n++) { - if (bitmap[n] != NGX_SLAB_BUSY) { - p = (uintptr_t) bitmap + i; - - goto done; - } - } - - prev = (ngx_slab_page_t *) - (page->prev & ~NGX_SLAB_PAGE_MASK); - prev->next = page->next; - page->next->prev = page->prev; - - page->next = NULL; - page->prev = NGX_SLAB_SMALL; - } - - p = (uintptr_t) bitmap + i; - - goto done; + for (m = 1, i = 0; m; m <<= 1, i++) { + if (bitmap[n] & m) { + continue; } + + bitmap[n] |= m; + + i = (n * sizeof(uintptr_t) * 8 + i) << shift; + + p = (uintptr_t) bitmap + i; + + pool->stats[slot].used++; + + if (bitmap[n] == NGX_SLAB_BUSY) { + for (n = n + 1; n < map; n++) { + if (bitmap[n] != NGX_SLAB_BUSY) { + goto done; + } + } + + prev = ngx_slab_page_prev(page); + prev->next = page->next; + page->next->prev = page->prev; + + page->next = NULL; + page->prev = NGX_SLAB_SMALL; + } + + goto done; } } - - page = page->next; - - } while (page); + } } else if (shift == ngx_slab_exact_shift) { - do { - if (page->slab != NGX_SLAB_BUSY) { - - for (m = 1, i = 0; m; m <<= 1, i++) { - if ((page->slab & m)) { - continue; - } - - page->slab |= m; - - if (page->slab == NGX_SLAB_BUSY) { - prev = (ngx_slab_page_t *) - (page->prev & ~NGX_SLAB_PAGE_MASK); - prev->next = page->next; - page->next->prev = page->prev; - - page->next = NULL; - page->prev = NGX_SLAB_EXACT; - } - - p = (page - pool->pages) << ngx_pagesize_shift; - p += i << shift; - p += (uintptr_t) pool->start; - - goto done; - } + for (m = 1, i = 0; m; m <<= 1, i++) { + if (page->slab & m) { + continue; } - page = page->next; + page->slab |= m; - } while (page); + if (page->slab == NGX_SLAB_BUSY) { + prev = ngx_slab_page_prev(page); + prev->next = page->next; + page->next->prev = page->prev; + + page->next = NULL; + page->prev = NGX_SLAB_EXACT; + } + + p = ngx_slab_page_addr(pool, page) + (i << shift); + + pool->stats[slot].used++; + + goto done; + } } else { /* shift > ngx_slab_exact_shift */ - n = ngx_pagesize_shift - (page->slab & NGX_SLAB_SHIFT_MASK); - n = 1 << n; - n = ((uintptr_t) 1 << n) - 1; - mask = n << NGX_SLAB_MAP_SHIFT; + mask = ((uintptr_t) 1 << (ngx_pagesize >> shift)) - 1; + mask <<= NGX_SLAB_MAP_SHIFT; - do { - if ((page->slab & NGX_SLAB_MAP_MASK) != mask) { - - for (m = (uintptr_t) 1 << NGX_SLAB_MAP_SHIFT, i = 0; - m & mask; - m <<= 1, i++) - { - if ((page->slab & m)) { - continue; - } - - page->slab |= m; - - if ((page->slab & NGX_SLAB_MAP_MASK) == mask) { - prev = (ngx_slab_page_t *) - (page->prev & ~NGX_SLAB_PAGE_MASK); - prev->next = page->next; - page->next->prev = page->prev; - - page->next = NULL; - page->prev = NGX_SLAB_BIG; - } - - p = (page - pool->pages) << ngx_pagesize_shift; - p += i << shift; - p += (uintptr_t) pool->start; - - goto done; - } + for (m = (uintptr_t) 1 << NGX_SLAB_MAP_SHIFT, i = 0; + m & mask; + m <<= 1, i++) + { + if (page->slab & m) { + continue; } - page = page->next; + page->slab |= m; - } while (page); + if ((page->slab & NGX_SLAB_MAP_MASK) == mask) { + prev = ngx_slab_page_prev(page); + prev->next = page->next; + page->next->prev = page->prev; + + page->next = NULL; + page->prev = NGX_SLAB_BIG; + } + + p = ngx_slab_page_addr(pool, page) + (i << shift); + + pool->stats[slot].used++; + + goto done; + } } + + ngx_slab_error(pool, NGX_LOG_ALERT, "ngx_slab_alloc(): page is busy"); + ngx_debug_point(); } page = ngx_slab_alloc_pages(pool, 1); if (page) { if (shift < ngx_slab_exact_shift) { - p = (page - pool->pages) << ngx_pagesize_shift; - bitmap = (uintptr_t *) (pool->start + p); + bitmap = (uintptr_t *) ngx_slab_page_addr(pool, page); - s = 1 << shift; - n = (1 << (ngx_pagesize_shift - shift)) / 8 / s; + n = (ngx_pagesize >> shift) / ((1 << shift) * 8); if (n == 0) { n = 1; } - bitmap[0] = (2 << n) - 1; + /* "n" elements for bitmap, plus one requested */ + bitmap[0] = ((uintptr_t) 2 << n) - 1; - map = (1 << (ngx_pagesize_shift - shift)) / (sizeof(uintptr_t) * 8); + map = (ngx_pagesize >> shift) / (sizeof(uintptr_t) * 8); for (i = 1; i < map; i++) { bitmap[i] = 0; @@ -355,8 +353,11 @@ slots[slot].next = page; - p = ((page - pool->pages) << ngx_pagesize_shift) + s * n; - p += (uintptr_t) pool->start; + pool->stats[slot].total += (ngx_pagesize >> shift) - n; + + p = ngx_slab_page_addr(pool, page) + (n << shift); + + pool->stats[slot].used++; goto done; @@ -368,8 +369,11 @@ slots[slot].next = page; - p = (page - pool->pages) << ngx_pagesize_shift; - p += (uintptr_t) pool->start; + pool->stats[slot].total += sizeof(uintptr_t) * 8; + + p = ngx_slab_page_addr(pool, page); + + pool->stats[slot].used++; goto done; @@ -381,8 +385,11 @@ slots[slot].next = page; - p = (page - pool->pages) << ngx_pagesize_shift; - p += (uintptr_t) pool->start; + pool->stats[slot].total += ngx_pagesize >> shift; + + p = ngx_slab_page_addr(pool, page); + + pool->stats[slot].used++; goto done; } @@ -390,6 +397,8 @@ p = 0; + pool->stats[slot].fails++; + done: ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, ngx_cycle->log, 0, @@ -444,7 +453,7 @@ { size_t size; uintptr_t slab, m, *bitmap; - ngx_uint_t n, type, slot, shift, map; + ngx_uint_t i, n, type, slot, shift, map; ngx_slab_page_t *slots, *page; ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, ngx_cycle->log, 0, "slab free: %p", p); @@ -457,7 +466,7 @@ n = ((u_char *) p - pool->start) >> ngx_pagesize_shift; page = &pool->pages[n]; slab = page->slab; - type = page->prev & NGX_SLAB_PAGE_MASK; + type = ngx_slab_page_type(page); switch (type) { @@ -471,17 +480,16 @@ } n = ((uintptr_t) p & (ngx_pagesize - 1)) >> shift; - m = (uintptr_t) 1 << (n & (sizeof(uintptr_t) * 8 - 1)); - n /= (sizeof(uintptr_t) * 8); + m = (uintptr_t) 1 << (n % (sizeof(uintptr_t) * 8)); + n /= sizeof(uintptr_t) * 8; bitmap = (uintptr_t *) ((uintptr_t) p & ~((uintptr_t) ngx_pagesize - 1)); if (bitmap[n] & m) { + slot = shift - pool->min_shift; if (page->next == NULL) { - slots = (ngx_slab_page_t *) - ((u_char *) pool + sizeof(ngx_slab_pool_t)); - slot = shift - pool->min_shift; + slots = ngx_slab_slots(pool); page->next = slots[slot].next; slots[slot].next = page; @@ -492,7 +500,7 @@ bitmap[n] &= ~m; - n = (1 << (ngx_pagesize_shift - shift)) / 8 / (1 << shift); + n = (ngx_pagesize >> shift) / ((1 << shift) * 8); if (n == 0) { n = 1; @@ -502,16 +510,18 @@ goto done; } - map = (1 << (ngx_pagesize_shift - shift)) / (sizeof(uintptr_t) * 8); + map = (ngx_pagesize >> shift) / (sizeof(uintptr_t) * 8); - for (n = 1; n < map; n++) { - if (bitmap[n]) { + for (i = 1; i < map; i++) { + if (bitmap[i]) { goto done; } } ngx_slab_free_pages(pool, page, 1); + pool->stats[slot].total -= (ngx_pagesize >> shift) - n; + goto done; } @@ -528,10 +538,10 @@ } if (slab & m) { + slot = ngx_slab_exact_shift - pool->min_shift; + if (slab == NGX_SLAB_BUSY) { - slots = (ngx_slab_page_t *) - ((u_char *) pool + sizeof(ngx_slab_pool_t)); - slot = ngx_slab_exact_shift - pool->min_shift; + slots = ngx_slab_slots(pool); page->next = slots[slot].next; slots[slot].next = page; @@ -548,6 +558,8 @@ ngx_slab_free_pages(pool, page, 1); + pool->stats[slot].total -= sizeof(uintptr_t) * 8; + goto done; } @@ -566,11 +578,10 @@ + NGX_SLAB_MAP_SHIFT); if (slab & m) { + slot = shift - pool->min_shift; if (page->next == NULL) { - slots = (ngx_slab_page_t *) - ((u_char *) pool + sizeof(ngx_slab_pool_t)); - slot = shift - pool->min_shift; + slots = ngx_slab_slots(pool); page->next = slots[slot].next; slots[slot].next = page; @@ -587,6 +598,8 @@ ngx_slab_free_pages(pool, page, 1); + pool->stats[slot].total -= ngx_pagesize >> shift; + goto done; } @@ -598,7 +611,7 @@ goto wrong_chunk; } - if (slab == NGX_SLAB_PAGE_FREE) { + if (!(slab & NGX_SLAB_PAGE_START)) { ngx_slab_error(pool, NGX_LOG_ALERT, "ngx_slab_free(): page is already free"); goto fail; @@ -626,6 +639,8 @@ done: + pool->stats[slot].used--; + ngx_slab_junk(p, size); return; @@ -678,6 +693,8 @@ page->next = NULL; page->prev = NGX_SLAB_PAGE; + pool->pfree -= pages; + if (--pages == 0) { return page; } @@ -706,9 +723,10 @@ ngx_slab_free_pages(ngx_slab_pool_t *pool, ngx_slab_page_t *page, ngx_uint_t pages) { - ngx_uint_t type; ngx_slab_page_t *prev, *join; + pool->pfree += pages; + page->slab = pages--; if (pages) { @@ -716,7 +734,7 @@ } if (page->next) { - prev = (ngx_slab_page_t *) (page->prev & ~NGX_SLAB_PAGE_MASK); + prev = ngx_slab_page_prev(page); prev->next = page->next; page->next->prev = page->prev; } @@ -724,15 +742,14 @@ join = page + page->slab; if (join < pool->last) { - type = join->prev & NGX_SLAB_PAGE_MASK; - if (type == NGX_SLAB_PAGE) { + if (ngx_slab_page_type(join) == NGX_SLAB_PAGE) { if (join->next != NULL) { pages += join->slab; page->slab += join->slab; - prev = (ngx_slab_page_t *) (join->prev & ~NGX_SLAB_PAGE_MASK); + prev = ngx_slab_page_prev(join); prev->next = join->next; join->next->prev = join->prev; @@ -745,19 +762,18 @@ if (page > pool->pages) { join = page - 1; - type = join->prev & NGX_SLAB_PAGE_MASK; - if (type == NGX_SLAB_PAGE) { + if (ngx_slab_page_type(join) == NGX_SLAB_PAGE) { if (join->slab == NGX_SLAB_PAGE_FREE) { - join = (ngx_slab_page_t *) (join->prev & ~NGX_SLAB_PAGE_MASK); + join = ngx_slab_page_prev(join); } if (join->next != NULL) { pages += join->slab; join->slab += page->slab; - prev = (ngx_slab_page_t *) (join->prev & ~NGX_SLAB_PAGE_MASK); + prev = ngx_slab_page_prev(join); prev->next = join->next; join->next->prev = join->prev;
diff --git a/src/core/ngx_slab.h b/src/core/ngx_slab.h index 2922a80..eff893c 100644 --- a/src/core/ngx_slab.h +++ b/src/core/ngx_slab.h
@@ -23,6 +23,15 @@ typedef struct { + ngx_uint_t total; + ngx_uint_t used; + + ngx_uint_t reqs; + ngx_uint_t fails; +} ngx_slab_stat_t; + + +typedef struct { ngx_shmtx_sh_t lock; size_t min_size; @@ -32,6 +41,9 @@ ngx_slab_page_t *last; ngx_slab_page_t free; + ngx_slab_stat_t *stats; + ngx_uint_t pfree; + u_char *start; u_char *end;
diff --git a/src/event/modules/ngx_devpoll_module.c b/src/event/modules/ngx_devpoll_module.c index 88d89b6..cbc009c 100644 --- a/src/event/modules/ngx_devpoll_module.c +++ b/src/event/modules/ngx_devpoll_module.c
@@ -483,13 +483,11 @@ fd, event_list[i].events, revents); } - if ((revents & (POLLERR|POLLHUP|POLLNVAL)) - && (revents & (POLLIN|POLLOUT)) == 0) - { + if (revents & (POLLERR|POLLHUP|POLLNVAL)) { + /* - * if the error events were returned without POLLIN or POLLOUT, - * then add these flags to handle the events at least in one - * active handler + * if the error events were returned, add POLLIN and POLLOUT + * to handle the events at least in one active handler */ revents |= POLLIN|POLLOUT;
diff --git a/src/event/modules/ngx_epoll_module.c b/src/event/modules/ngx_epoll_module.c index 3d8fd31..b74865a 100644 --- a/src/event/modules/ngx_epoll_module.c +++ b/src/event/modules/ngx_epoll_module.c
@@ -871,6 +871,13 @@ ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "epoll_wait() error on fd:%d ev:%04XD", c->fd, revents); + + /* + * if the error events were returned, add EPOLLIN and EPOLLOUT + * to handle the events at least in one active handler + */ + + revents |= EPOLLIN|EPOLLOUT; } #if 0 @@ -881,18 +888,6 @@ } #endif - if ((revents & (EPOLLERR|EPOLLHUP)) - && (revents & (EPOLLIN|EPOLLOUT)) == 0) - { - /* - * if the error events were returned without EPOLLIN or EPOLLOUT, - * then add these flags to handle the events at least in one - * active handler - */ - - revents |= EPOLLIN|EPOLLOUT; - } - if ((revents & EPOLLIN) && rev->active) { #if (NGX_HAVE_EPOLLRDHUP)
diff --git a/src/event/modules/ngx_eventport_module.c b/src/event/modules/ngx_eventport_module.c index aef1810..cc4af09 100644 --- a/src/event/modules/ngx_eventport_module.c +++ b/src/event/modules/ngx_eventport_module.c
@@ -552,13 +552,11 @@ (int) event_list[i].portev_object, revents); } - if ((revents & (POLLERR|POLLHUP|POLLNVAL)) - && (revents & (POLLIN|POLLOUT)) == 0) - { + if (revents & (POLLERR|POLLHUP|POLLNVAL)) { + /* - * if the error events were returned without POLLIN or POLLOUT, - * then add these flags to handle the events at least in one - * active handler + * if the error events were returned, add POLLIN and POLLOUT + * to handle the events at least in one active handler */ revents |= POLLIN|POLLOUT;
diff --git a/src/event/modules/ngx_poll_module.c b/src/event/modules/ngx_poll_module.c index d4777d0..d0a0e8f 100644 --- a/src/event/modules/ngx_poll_module.c +++ b/src/event/modules/ngx_poll_module.c
@@ -355,13 +355,11 @@ continue; } - if ((revents & (POLLERR|POLLHUP|POLLNVAL)) - && (revents & (POLLIN|POLLOUT)) == 0) - { + if (revents & (POLLERR|POLLHUP|POLLNVAL)) { + /* - * if the error events were returned without POLLIN or POLLOUT, - * then add these flags to handle the events at least in one - * active handler + * if the error events were returned, add POLLIN and POLLOUT + * to handle the events at least in one active handler */ revents |= POLLIN|POLLOUT;
diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c index 9a257b5..d75b7f0 100644 --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c
@@ -59,6 +59,12 @@ static ngx_int_t ngx_ssl_check_name(ngx_str_t *name, ASN1_STRING *str); #endif +static time_t ngx_ssl_parse_time( +#if OPENSSL_VERSION_NUMBER > 0x10100000L + const +#endif + ASN1_TIME *asn1time); + static void *ngx_openssl_create_conf(ngx_cycle_t *cycle); static char *ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static void ngx_openssl_exit(ngx_cycle_t *cycle); @@ -106,6 +112,7 @@ int ngx_ssl_session_ticket_keys_index; int ngx_ssl_certificate_index; int ngx_ssl_next_certificate_index; +int ngx_ssl_certificate_name_index; int ngx_ssl_stapling_index; @@ -193,6 +200,14 @@ return NGX_ERROR; } + ngx_ssl_certificate_name_index = X509_get_ex_new_index(0, NULL, NULL, NULL, + NULL); + + if (ngx_ssl_certificate_name_index == -1) { + ngx_ssl_error(NGX_LOG_ALERT, log, 0, "X509_get_ex_new_index() failed"); + return NGX_ERROR; + } + ngx_ssl_stapling_index = X509_get_ex_new_index(0, NULL, NULL, NULL, NULL); if (ngx_ssl_stapling_index == -1) { @@ -385,6 +400,15 @@ return NGX_ERROR; } + if (X509_set_ex_data(x509, ngx_ssl_certificate_name_index, cert->data) + == 0) + { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_set_ex_data() failed"); + X509_free(x509); + BIO_free(bio); + return NGX_ERROR; + } + if (X509_set_ex_data(x509, ngx_ssl_next_certificate_index, SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index)) == 0) @@ -3273,6 +3297,158 @@ ngx_int_t +ngx_ssl_get_ciphers(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) +{ +#ifdef SSL_CTRL_GET_RAW_CIPHERLIST + + int n, i, bytes; + size_t len; + u_char *ciphers, *p; + const SSL_CIPHER *cipher; + + bytes = SSL_get0_raw_cipherlist(c->ssl->connection, NULL); + n = SSL_get0_raw_cipherlist(c->ssl->connection, &ciphers); + + if (n <= 0) { + s->len = 0; + return NGX_OK; + } + + len = 0; + n /= bytes; + + for (i = 0; i < n; i++) { + cipher = SSL_CIPHER_find(c->ssl->connection, ciphers + i * bytes); + + if (cipher) { + len += ngx_strlen(SSL_CIPHER_get_name(cipher)); + + } else { + len += sizeof("0x") - 1 + bytes * (sizeof("00") - 1); + } + + len += sizeof(":") - 1; + } + + s->data = ngx_pnalloc(pool, len); + if (s->data == NULL) { + return NGX_ERROR; + } + + p = s->data; + + for (i = 0; i < n; i++) { + cipher = SSL_CIPHER_find(c->ssl->connection, ciphers + i * bytes); + + if (cipher) { + p = ngx_sprintf(p, "%s", SSL_CIPHER_get_name(cipher)); + + } else { + p = ngx_sprintf(p, "0x"); + p = ngx_hex_dump(p, ciphers + i * bytes, bytes); + } + + *p++ = ':'; + } + + p--; + + s->len = p - s->data; + +#else + + u_char buf[4096]; + + if (SSL_get_shared_ciphers(c->ssl->connection, (char *) buf, 4096) + == NULL) + { + s->len = 0; + return NGX_OK; + } + + s->len = ngx_strlen(buf); + s->data = ngx_pnalloc(pool, s->len); + if (s->data == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(s->data, buf, s->len); + +#endif + + return NGX_OK; +} + + +ngx_int_t +ngx_ssl_get_curves(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) +{ +#ifdef SSL_CTRL_GET_CURVES + + int *curves, n, i, nid; + u_char *p; + size_t len; + + n = SSL_get1_curves(c->ssl->connection, NULL); + + if (n <= 0) { + s->len = 0; + return NGX_OK; + } + + curves = ngx_palloc(pool, n * sizeof(int)); + + n = SSL_get1_curves(c->ssl->connection, curves); + len = 0; + + for (i = 0; i < n; i++) { + nid = curves[i]; + + if (nid & TLSEXT_nid_unknown) { + len += sizeof("0x0000") - 1; + + } else { + len += ngx_strlen(OBJ_nid2sn(nid)); + } + + len += sizeof(":") - 1; + } + + s->data = ngx_pnalloc(pool, len); + if (s->data == NULL) { + return NGX_ERROR; + } + + p = s->data; + + for (i = 0; i < n; i++) { + nid = curves[i]; + + if (nid & TLSEXT_nid_unknown) { + p = ngx_sprintf(p, "0x%04xd", nid & 0xffff); + + } else { + p = ngx_sprintf(p, "%s", OBJ_nid2sn(nid)); + } + + *p++ = ':'; + } + + p--; + + s->len = p - s->data; + +#else + + s->len = 0; + +#endif + + return NGX_OK; +} + + +ngx_int_t ngx_ssl_get_session_id(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) { u_char *buf; @@ -3702,28 +3878,210 @@ ngx_int_t ngx_ssl_get_client_verify(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) { - X509 *cert; - - if (SSL_get_verify_result(c->ssl->connection) != X509_V_OK) { - ngx_str_set(s, "FAILED"); - return NGX_OK; - } + X509 *cert; + long rc; + const char *str; cert = SSL_get_peer_certificate(c->ssl->connection); - - if (cert) { - ngx_str_set(s, "SUCCESS"); - - } else { + if (cert == NULL) { ngx_str_set(s, "NONE"); + return NGX_OK; } X509_free(cert); + rc = SSL_get_verify_result(c->ssl->connection); + + if (rc == X509_V_OK) { + ngx_str_set(s, "SUCCESS"); + return NGX_OK; + } + + str = X509_verify_cert_error_string(rc); + + s->data = ngx_pnalloc(pool, sizeof("FAILED:") - 1 + ngx_strlen(str)); + if (s->data == NULL) { + return NGX_ERROR; + } + + s->len = ngx_sprintf(s->data, "FAILED:%s", str) - s->data; + return NGX_OK; } +ngx_int_t +ngx_ssl_get_client_v_start(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) +{ + BIO *bio; + X509 *cert; + size_t len; + + s->len = 0; + + cert = SSL_get_peer_certificate(c->ssl->connection); + if (cert == NULL) { + return NGX_OK; + } + + bio = BIO_new(BIO_s_mem()); + if (bio == NULL) { + X509_free(cert); + return NGX_ERROR; + } + +#if OPENSSL_VERSION_NUMBER > 0x10100000L + ASN1_TIME_print(bio, X509_get0_notBefore(cert)); +#else + ASN1_TIME_print(bio, X509_get_notBefore(cert)); +#endif + + len = BIO_pending(bio); + + s->len = len; + s->data = ngx_pnalloc(pool, len); + if (s->data == NULL) { + BIO_free(bio); + X509_free(cert); + return NGX_ERROR; + } + + BIO_read(bio, s->data, len); + BIO_free(bio); + X509_free(cert); + + return NGX_OK; +} + + +ngx_int_t +ngx_ssl_get_client_v_end(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) +{ + BIO *bio; + X509 *cert; + size_t len; + + s->len = 0; + + cert = SSL_get_peer_certificate(c->ssl->connection); + if (cert == NULL) { + return NGX_OK; + } + + bio = BIO_new(BIO_s_mem()); + if (bio == NULL) { + X509_free(cert); + return NGX_ERROR; + } + +#if OPENSSL_VERSION_NUMBER > 0x10100000L + ASN1_TIME_print(bio, X509_get0_notAfter(cert)); +#else + ASN1_TIME_print(bio, X509_get_notAfter(cert)); +#endif + + len = BIO_pending(bio); + + s->len = len; + s->data = ngx_pnalloc(pool, len); + if (s->data == NULL) { + BIO_free(bio); + X509_free(cert); + return NGX_ERROR; + } + + BIO_read(bio, s->data, len); + BIO_free(bio); + X509_free(cert); + + return NGX_OK; +} + + +ngx_int_t +ngx_ssl_get_client_v_remain(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) +{ + X509 *cert; + time_t now, end; + + s->len = 0; + + cert = SSL_get_peer_certificate(c->ssl->connection); + if (cert == NULL) { + return NGX_OK; + } + +#if OPENSSL_VERSION_NUMBER > 0x10100000L + end = ngx_ssl_parse_time(X509_get0_notAfter(cert)); +#else + end = ngx_ssl_parse_time(X509_get_notAfter(cert)); +#endif + + if (end == (time_t) NGX_ERROR) { + X509_free(cert); + return NGX_OK; + } + + now = ngx_time(); + + if (end < now + 86400) { + ngx_str_set(s, "0"); + X509_free(cert); + return NGX_OK; + } + + s->data = ngx_pnalloc(pool, NGX_TIME_T_LEN); + if (s->data == NULL) { + X509_free(cert); + return NGX_ERROR; + } + + s->len = ngx_sprintf(s->data, "%T", (end - now) / 86400) - s->data; + + X509_free(cert); + + return NGX_OK; +} + + +static time_t +ngx_ssl_parse_time( +#if OPENSSL_VERSION_NUMBER > 0x10100000L + const +#endif + ASN1_TIME *asn1time) +{ + BIO *bio; + u_char *value; + size_t len; + time_t time; + + /* + * OpenSSL doesn't provide a way to convert ASN1_TIME + * into time_t. To do this, we use ASN1_TIME_print(), + * which uses the "MMM DD HH:MM:SS YYYY [GMT]" format (e.g., + * "Feb 3 00:55:52 2015 GMT"), and parse the result. + */ + + bio = BIO_new(BIO_s_mem()); + if (bio == NULL) { + return NGX_ERROR; + } + + /* fake weekday prepended to match C asctime() format */ + + BIO_write(bio, "Tue ", sizeof("Tue ") - 1); + ASN1_TIME_print(bio, asn1time); + len = BIO_get_mem_data(bio, (char **) &value); + + time = ngx_parse_http_time(value, len); + + BIO_free(bio); + + return time; +} + + static void * ngx_openssl_create_conf(ngx_cycle_t *cycle) {
diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h index d233c02..c022307 100644 --- a/src/event/ngx_event_openssl.h +++ b/src/event/ngx_event_openssl.h
@@ -191,6 +191,10 @@ ngx_str_t *s); ngx_int_t ngx_ssl_get_cipher_name(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s); +ngx_int_t ngx_ssl_get_ciphers(ngx_connection_t *c, ngx_pool_t *pool, + ngx_str_t *s); +ngx_int_t ngx_ssl_get_curves(ngx_connection_t *c, ngx_pool_t *pool, + ngx_str_t *s); ngx_int_t ngx_ssl_get_session_id(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s); ngx_int_t ngx_ssl_get_session_reused(ngx_connection_t *c, ngx_pool_t *pool, @@ -215,6 +219,12 @@ ngx_str_t *s); ngx_int_t ngx_ssl_get_client_verify(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s); +ngx_int_t ngx_ssl_get_client_v_start(ngx_connection_t *c, ngx_pool_t *pool, + ngx_str_t *s); +ngx_int_t ngx_ssl_get_client_v_end(ngx_connection_t *c, ngx_pool_t *pool, + ngx_str_t *s); +ngx_int_t ngx_ssl_get_client_v_remain(ngx_connection_t *c, ngx_pool_t *pool, + ngx_str_t *s); ngx_int_t ngx_ssl_handshake(ngx_connection_t *c); @@ -236,6 +246,7 @@ extern int ngx_ssl_session_ticket_keys_index; extern int ngx_ssl_certificate_index; extern int ngx_ssl_next_certificate_index; +extern int ngx_ssl_certificate_name_index; extern int ngx_ssl_stapling_index;
diff --git a/src/event/ngx_event_openssl_stapling.c b/src/event/ngx_event_openssl_stapling.c index 09fab76..2100516 100644 --- a/src/event/ngx_event_openssl_stapling.c +++ b/src/event/ngx_event_openssl_stapling.c
@@ -31,6 +31,8 @@ X509 *cert; X509 *issuer; + u_char *name; + time_t valid; time_t refresh; @@ -45,6 +47,8 @@ X509 *cert; X509 *issuer; + u_char *name; + ngx_uint_t naddrs; ngx_addr_t *addrs; @@ -57,14 +61,14 @@ ngx_msec_t timeout; - void (*handler)(ngx_ssl_ocsp_ctx_t *r); + void (*handler)(ngx_ssl_ocsp_ctx_t *ctx); void *data; ngx_buf_t *request; ngx_buf_t *response; ngx_peer_connection_t peer; - ngx_int_t (*process)(ngx_ssl_ocsp_ctx_t *r); + ngx_int_t (*process)(ngx_ssl_ocsp_ctx_t *ctx); ngx_uint_t state; @@ -173,6 +177,8 @@ staple->timeout = 60000; staple->verify = verify; staple->cert = cert; + staple->name = X509_get_ex_data(staple->cert, + ngx_ssl_certificate_name_index); if (file->len) { /* use OCSP response from the file */ @@ -354,7 +360,9 @@ if (rc == 0) { ngx_log_error(NGX_LOG_WARN, ssl->log, 0, - "\"ssl_stapling\" ignored, issuer certificate not found"); + "\"ssl_stapling\" ignored, " + "issuer certificate not found for certificate \"%s\"", + staple->name); X509_STORE_CTX_free(store_ctx); return NGX_DECLINED; } @@ -374,9 +382,9 @@ ngx_ssl_stapling_responder(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_ssl_stapling_t *staple, ngx_str_t *responder) { - ngx_url_t u; char *s; ngx_str_t rsp; + ngx_url_t u; STACK_OF(OPENSSL_STRING) *aia; if (responder->len == 0) { @@ -387,7 +395,8 @@ if (aia == NULL) { ngx_log_error(NGX_LOG_WARN, ssl->log, 0, "\"ssl_stapling\" ignored, " - "no OCSP responder URL in the certificate"); + "no OCSP responder URL in the certificate \"%s\"", + staple->name); return NGX_DECLINED; } @@ -399,7 +408,8 @@ if (s == NULL) { ngx_log_error(NGX_LOG_WARN, ssl->log, 0, "\"ssl_stapling\" ignored, " - "no OCSP responder URL in the certificate"); + "no OCSP responder URL in the certificate \"%s\"", + staple->name); X509_email_free(aia); return NGX_DECLINED; } @@ -432,7 +442,9 @@ } else { ngx_log_error(NGX_LOG_WARN, ssl->log, 0, "\"ssl_stapling\" ignored, " - "invalid URL prefix in OCSP responder \"%V\"", &u.url); + "invalid URL prefix in OCSP responder \"%V\" " + "in the certificate \"%s\"", + &u.url, staple->name); return NGX_DECLINED; } @@ -440,7 +452,9 @@ if (u.err) { ngx_log_error(NGX_LOG_WARN, ssl->log, 0, "\"ssl_stapling\" ignored, " - "%s in OCSP responder \"%V\"", u.err, &u.url); + "%s in OCSP responder \"%V\" " + "in the certificate \"%s\"", + u.err, &u.url, staple->name); return NGX_DECLINED; } @@ -547,6 +561,7 @@ ctx->cert = staple->cert; ctx->issuer = staple->issuer; + ctx->name = staple->name; ctx->addrs = staple->addrs; ctx->host = staple->host; @@ -757,10 +772,10 @@ static time_t ngx_ssl_stapling_time(ASN1_GENERALIZEDTIME *asn1time) { + BIO *bio; u_char *value; size_t len; time_t time; - BIO *bio; /* * OpenSSL doesn't provide a way to convert ASN1_GENERALIZEDTIME @@ -1005,7 +1020,7 @@ static void ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx) { - ngx_int_t rc; + ngx_int_t rc; ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0, "ssl ocsp connect"); @@ -1103,10 +1118,10 @@ static void ngx_ssl_ocsp_read_handler(ngx_event_t *rev) { - ssize_t n, size; - ngx_int_t rc; - ngx_ssl_ocsp_ctx_t *ctx; - ngx_connection_t *c; + ssize_t n, size; + ngx_int_t rc; + ngx_connection_t *c; + ngx_ssl_ocsp_ctx_t *ctx; c = rev->data; ctx = c->data; @@ -1310,12 +1325,11 @@ rc = ngx_ssl_ocsp_parse_status_line(ctx); if (rc == NGX_OK) { -#if 0 - ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0, - "ssl ocsp status line \"%*s\"", - ctx->response->pos - ctx->response->start, - ctx->response->start); -#endif + ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ctx->log, 0, + "ssl ocsp status %ui \"%*s\"", + ctx->code, + ctx->header_end - ctx->header_start, + ctx->header_start); ctx->process = ngx_ssl_ocsp_process_headers; return ctx->process(ctx); @@ -1476,6 +1490,7 @@ if (++ctx->count == 3) { state = sw_space_after_status; + ctx->header_start = p - 2; } break; @@ -1493,6 +1508,7 @@ state = sw_almost_done; break; case LF: + ctx->header_end = p; goto done; default: return NGX_ERROR; @@ -1506,6 +1522,7 @@ state = sw_almost_done; break; case LF: + ctx->header_end = p; goto done; } break; @@ -1514,6 +1531,7 @@ case sw_almost_done: switch (ch) { case LF: + ctx->header_end = p - 1; goto done; default: return NGX_ERROR; @@ -1608,10 +1626,11 @@ return ctx->process(ctx); } + static ngx_int_t ngx_ssl_ocsp_parse_header_line(ngx_ssl_ocsp_ctx_t *ctx) { - u_char c, ch, *p; + u_char c, ch, *p; enum { sw_start = 0, sw_name, @@ -1821,12 +1840,27 @@ if (log->action) { p = ngx_snprintf(buf, len, " while %s", log->action); len -= p - buf; + buf = p; } ctx = log->data; if (ctx) { - p = ngx_snprintf(p, len, ", responder: %V", &ctx->host); + p = ngx_snprintf(buf, len, ", responder: %V", &ctx->host); + len -= p - buf; + buf = p; + } + + if (ctx && ctx->peer.name) { + p = ngx_snprintf(buf, len, ", peer: %V", ctx->peer.name); + len -= p - buf; + buf = p; + } + + if (ctx && ctx->name) { + p = ngx_snprintf(buf, len, ", certificate: \"%s\"", ctx->name); + len -= p - buf; + buf = p; } return p; @@ -1846,6 +1880,7 @@ return NGX_OK; } + ngx_int_t ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_resolver_t *resolver, ngx_msec_t resolver_timeout)
diff --git a/src/http/modules/ngx_http_map_module.c b/src/http/modules/ngx_http_map_module.c index 732aa5d..2fc9be9 100644 --- a/src/http/modules/ngx_http_map_module.c +++ b/src/http/modules/ngx_http_map_module.c
@@ -26,7 +26,8 @@ ngx_http_variable_value_t *default_value; ngx_conf_t *cf; - ngx_uint_t hostnames; /* unsigned hostnames:1 */ + unsigned hostnames:1; + unsigned no_cacheable:1; } ngx_http_map_conf_ctx_t; @@ -265,6 +266,7 @@ ctx.default_value = NULL; ctx.cf = &save; ctx.hostnames = 0; + ctx.no_cacheable = 0; save = *cf; cf->pool = pool; @@ -281,6 +283,10 @@ return rv; } + if (ctx.no_cacheable) { + var->flags |= NGX_HTTP_VAR_NOCACHEABLE; + } + map->default_value = ctx.default_value ? ctx.default_value: &ngx_http_variable_null_value; @@ -393,8 +399,16 @@ { ctx->hostnames = 1; return NGX_CONF_OK; + } - } else if (cf->args->nelts != 2) { + if (cf->args->nelts == 1 + && ngx_strcmp(value[0].data, "volatile") == 0) + { + ctx->no_cacheable = 1; + return NGX_CONF_OK; + } + + if (cf->args->nelts != 2) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid number of the map parameters"); return NGX_CONF_ERROR;
diff --git a/src/http/modules/ngx_http_mp4_module.c b/src/http/modules/ngx_http_mp4_module.c index 8f2920f..f3c0fdd 100644 --- a/src/http/modules/ngx_http_mp4_module.c +++ b/src/http/modules/ngx_http_mp4_module.c
@@ -1229,7 +1229,9 @@ atom_header = mp4->mdat_atom_header; - if ((uint64_t) atom_data_size > (uint64_t) 0xffffffff) { + if ((uint64_t) atom_data_size + > (uint64_t) 0xffffffff - sizeof(ngx_mp4_atom_header_t)) + { atom_size = 1; atom_header_size = sizeof(ngx_mp4_atom_header64_t); ngx_mp4_set_64value(atom_header + sizeof(ngx_mp4_atom_header_t),
diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c index e75f5d8..2771ac1 100644 --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c
@@ -276,6 +276,12 @@ { ngx_string("ssl_cipher"), NULL, ngx_http_ssl_static_variable, (uintptr_t) ngx_ssl_get_cipher_name, NGX_HTTP_VAR_CHANGEABLE, 0 }, + { ngx_string("ssl_ciphers"), NULL, ngx_http_ssl_variable, + (uintptr_t) ngx_ssl_get_ciphers, NGX_HTTP_VAR_CHANGEABLE, 0 }, + + { ngx_string("ssl_curves"), NULL, ngx_http_ssl_variable, + (uintptr_t) ngx_ssl_get_curves, NGX_HTTP_VAR_CHANGEABLE, 0 }, + { ngx_string("ssl_session_id"), NULL, ngx_http_ssl_variable, (uintptr_t) ngx_ssl_get_session_id, NGX_HTTP_VAR_CHANGEABLE, 0 }, @@ -313,6 +319,15 @@ { ngx_string("ssl_client_verify"), NULL, ngx_http_ssl_variable, (uintptr_t) ngx_ssl_get_client_verify, NGX_HTTP_VAR_CHANGEABLE, 0 }, + { ngx_string("ssl_client_v_start"), NULL, ngx_http_ssl_variable, + (uintptr_t) ngx_ssl_get_client_v_start, NGX_HTTP_VAR_CHANGEABLE, 0 }, + + { ngx_string("ssl_client_v_end"), NULL, ngx_http_ssl_variable, + (uintptr_t) ngx_ssl_get_client_v_end, NGX_HTTP_VAR_CHANGEABLE, 0 }, + + { ngx_string("ssl_client_v_remain"), NULL, ngx_http_ssl_variable, + (uintptr_t) ngx_ssl_get_client_v_remain, NGX_HTTP_VAR_CHANGEABLE, 0 }, + { ngx_null_string, NULL, NULL, 0, 0, 0 } };
diff --git a/src/http/modules/perl/ngx_http_perl_module.c b/src/http/modules/perl/ngx_http_perl_module.c index f9a9a84..2796319 100644 --- a/src/http/modules/perl/ngx_http_perl_module.c +++ b/src/http/modules/perl/ngx_http_perl_module.c
@@ -207,6 +207,7 @@ dTHXa(pmcf->perl); PERL_SET_CONTEXT(pmcf->perl); + PERL_SET_INTERP(pmcf->perl); if (ctx->next == NULL) { plcf = ngx_http_get_module_loc_conf(r, ngx_http_perl_module); @@ -322,6 +323,7 @@ dTHXa(pmcf->perl); PERL_SET_CONTEXT(pmcf->perl); + PERL_SET_INTERP(pmcf->perl); rc = ngx_http_perl_call_handler(aTHX_ r, pmcf->nginx, pv->sub, NULL, &pv->handler, &value); @@ -387,6 +389,7 @@ dTHXa(pmcf->perl); PERL_SET_CONTEXT(pmcf->perl); + PERL_SET_INTERP(pmcf->perl); #if 0 @@ -568,6 +571,7 @@ dTHXa(perl); PERL_SET_CONTEXT(perl); + PERL_SET_INTERP(perl); perl_construct(perl); @@ -828,6 +832,7 @@ PerlInterpreter *perl = data; PERL_SET_CONTEXT(perl); + PERL_SET_INTERP(perl); (void) perl_destruct(perl); @@ -936,6 +941,7 @@ dTHXa(pmcf->perl); PERL_SET_CONTEXT(pmcf->perl); + PERL_SET_INTERP(pmcf->perl); ngx_http_perl_eval_anon_sub(aTHX_ &value[1], &plcf->sub); @@ -1007,6 +1013,7 @@ dTHXa(pmcf->perl); PERL_SET_CONTEXT(pmcf->perl); + PERL_SET_INTERP(pmcf->perl); ngx_http_perl_eval_anon_sub(aTHX_ &value[2], &pv->sub); @@ -1039,6 +1046,7 @@ if (pmcf) { dTHXa(pmcf->perl); PERL_SET_CONTEXT(pmcf->perl); + PERL_SET_INTERP(pmcf->perl); /* set worker's $$ */
diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c index 8301630..f3050f1 100644 --- a/src/http/v2/ngx_http_v2.c +++ b/src/http/v2/ngx_http_v2.c
@@ -286,7 +286,6 @@ : ngx_http_v2_state_preface; ngx_queue_init(&h2c->waiting); - ngx_queue_init(&h2c->posted); ngx_queue_init(&h2c->dependencies); ngx_queue_init(&h2c->closed); @@ -420,9 +419,7 @@ ngx_http_v2_write_handler(ngx_event_t *wev) { ngx_int_t rc; - ngx_queue_t *q; ngx_connection_t *c; - ngx_http_v2_stream_t *stream; ngx_http_v2_connection_t *h2c; c = wev->data; @@ -457,26 +454,6 @@ return; } - while (!ngx_queue_empty(&h2c->posted)) { - q = ngx_queue_head(&h2c->posted); - - ngx_queue_remove(q); - - stream = ngx_queue_data(q, ngx_http_v2_stream_t, queue); - - stream->handled = 0; - - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, - "run http2 stream %ui", stream->node->id); - - wev = stream->request->connection->write; - - wev->active = 0; - wev->ready = 1; - - wev->handler(wev); - } - h2c->blocked = 0; if (rc == NGX_AGAIN) { @@ -2254,7 +2231,7 @@ stream = ngx_queue_data(q, ngx_http_v2_stream_t, queue); - stream->handled = 0; + stream->waiting = 0; wev = stream->request->connection->write; @@ -3575,6 +3552,11 @@ rb->buf = ngx_create_temp_buf(r->pool, (size_t) len); } else { + if (stream->preread) { + /* enforce writing preread buffer to file */ + r->request_body_in_file_only = 1; + } + rb->buf = ngx_calloc_buf(r->pool); if (rb->buf != NULL) { @@ -4271,7 +4253,7 @@ continue; } - stream->handled = 0; + stream->waiting = 0; r = stream->request; fc = r->connection;
diff --git a/src/http/v2/ngx_http_v2.h b/src/http/v2/ngx_http_v2.h index 63bbdad..cddfccd 100644 --- a/src/http/v2/ngx_http_v2.h +++ b/src/http/v2/ngx_http_v2.h
@@ -137,7 +137,6 @@ ngx_http_v2_out_frame_t *last_out; - ngx_queue_t posted; ngx_queue_t dependencies; ngx_queue_t closed; @@ -192,7 +191,7 @@ ngx_pool_t *pool; - unsigned handled:1; + unsigned waiting:1; unsigned blocked:1; unsigned exhausted:1; unsigned in_closed:1;
diff --git a/src/http/v2/ngx_http_v2_filter_module.c b/src/http/v2/ngx_http_v2_filter_module.c index c4606e8..bfe1815 100644 --- a/src/http/v2/ngx_http_v2_filter_module.c +++ b/src/http/v2/ngx_http_v2_filter_module.c
@@ -1248,11 +1248,11 @@ ngx_queue_t *q; ngx_http_v2_stream_t *s; - if (stream->handled) { + if (stream->waiting) { return; } - stream->handled = 1; + stream->waiting = 1; for (q = ngx_queue_last(&h2c->waiting); q != ngx_queue_sentinel(&h2c->waiting); @@ -1442,20 +1442,29 @@ ngx_http_v2_handle_stream(ngx_http_v2_connection_t *h2c, ngx_http_v2_stream_t *stream) { + ngx_event_t *wev; ngx_connection_t *fc; - if (stream->handled || stream->blocked) { + if (stream->waiting || stream->blocked) { return; } fc = stream->request->connection; - if (!fc->error && (stream->exhausted || fc->write->delayed)) { + if (!fc->error && stream->exhausted) { return; } - stream->handled = 1; - ngx_queue_insert_tail(&h2c->posted, &stream->queue); + wev = fc->write; + + wev->active = 0; + wev->ready = 1; + + if (!fc->error && wev->delayed) { + return; + } + + ngx_post_event(wev, &ngx_posted_events); } @@ -1465,11 +1474,13 @@ ngx_http_v2_stream_t *stream = data; size_t window; + ngx_event_t *wev; + ngx_queue_t *q; ngx_http_v2_out_frame_t *frame, **fn; ngx_http_v2_connection_t *h2c; - if (stream->handled) { - stream->handled = 0; + if (stream->waiting) { + stream->waiting = 0; ngx_queue_remove(&stream->queue); } @@ -1503,9 +1514,26 @@ fn = &frame->next; } - if (h2c->send_window == 0 && window && !ngx_queue_empty(&h2c->waiting)) { - ngx_queue_add(&h2c->posted, &h2c->waiting); - ngx_queue_init(&h2c->waiting); + if (h2c->send_window == 0 && window) { + + while (!ngx_queue_empty(&h2c->waiting)) { + q = ngx_queue_head(&h2c->waiting); + + ngx_queue_remove(q); + + stream = ngx_queue_data(q, ngx_http_v2_stream_t, queue); + + stream->waiting = 0; + + wev = stream->request->connection->write; + + wev->active = 0; + wev->ready = 1; + + if (!wev->delayed) { + ngx_post_event(wev, &ngx_posted_events); + } + } } h2c->send_window += window;
diff --git a/src/stream/ngx_stream_map_module.c b/src/stream/ngx_stream_map_module.c index 47a15be..ef06b2d 100644 --- a/src/stream/ngx_stream_map_module.c +++ b/src/stream/ngx_stream_map_module.c
@@ -26,7 +26,8 @@ ngx_stream_variable_value_t *default_value; ngx_conf_t *cf; - ngx_uint_t hostnames; /* unsigned hostnames:1 */ + unsigned hostnames:1; + unsigned no_cacheable:1; } ngx_stream_map_conf_ctx_t; @@ -264,6 +265,7 @@ ctx.default_value = NULL; ctx.cf = &save; ctx.hostnames = 0; + ctx.no_cacheable = 0; save = *cf; cf->pool = pool; @@ -280,6 +282,10 @@ return rv; } + if (ctx.no_cacheable) { + var->flags |= NGX_STREAM_VAR_NOCACHEABLE; + } + map->default_value = ctx.default_value ? ctx.default_value: &ngx_stream_variable_null_value; @@ -392,8 +398,16 @@ { ctx->hostnames = 1; return NGX_CONF_OK; + } - } else if (cf->args->nelts != 2) { + if (cf->args->nelts == 1 + && ngx_strcmp(value[0].data, "volatile") == 0) + { + ctx->no_cacheable = 1; + return NGX_CONF_OK; + } + + if (cf->args->nelts != 2) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid number of the map parameters"); return NGX_CONF_ERROR;
diff --git a/src/stream/ngx_stream_ssl_module.c b/src/stream/ngx_stream_ssl_module.c index d00718b..9191641 100644 --- a/src/stream/ngx_stream_ssl_module.c +++ b/src/stream/ngx_stream_ssl_module.c
@@ -182,6 +182,12 @@ { ngx_string("ssl_cipher"), NULL, ngx_stream_ssl_static_variable, (uintptr_t) ngx_ssl_get_cipher_name, NGX_STREAM_VAR_CHANGEABLE, 0 }, + { ngx_string("ssl_ciphers"), NULL, ngx_stream_ssl_variable, + (uintptr_t) ngx_ssl_get_ciphers, NGX_STREAM_VAR_CHANGEABLE, 0 }, + + { ngx_string("ssl_curves"), NULL, ngx_stream_ssl_variable, + (uintptr_t) ngx_ssl_get_curves, NGX_STREAM_VAR_CHANGEABLE, 0 }, + { ngx_string("ssl_session_id"), NULL, ngx_stream_ssl_variable, (uintptr_t) ngx_ssl_get_session_id, NGX_STREAM_VAR_CHANGEABLE, 0 },