From fc45a6a844a5ea3a46e20f66c2592ad3bbd5998c Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Mon, 27 Jul 2015 17:49:49 +0300 Subject: [PATCH 001/600] Disable PIE hardening flag A quick fix for solving wheezy linking problem in perl's shared library. --- debian/rules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/rules b/debian/rules index 34223d8..1fd85db 100755 --- a/debian/rules +++ b/debian/rules @@ -1,7 +1,7 @@ #!/usr/bin/make -f export DH_VERBOSE=1 -export DEB_BUILD_MAINT_OPTIONS=hardening=+all +export DEB_BUILD_MAINT_OPTIONS=hardening=+all,-pie debian_cflags:=$(shell dpkg-buildflags --get CFLAGS) $(shell dpkg-buildflags --get CPPFLAGS) debian_ldflags:=$(shell dpkg-buildflags --get LDFLAGS) From 64a08ca81c7e01ed606486be2b464ab8991cabd4 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Mon, 27 Jul 2015 17:15:57 +0300 Subject: [PATCH 002/600] Release 1.9.3-1~bpo7+1 --- debian/changelog | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/debian/changelog b/debian/changelog index 8e64506..90f38ff 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +nginx (1.9.3-1~bpo7+1) wheezy-backports-sloppy; urgency=medium + + * Rebuild for jessie-backports-sloppy. + * Drop PIE from hardening flags. Solves linking issue in wheezy. + + -- Christos Trochalakis Mon, 27 Jul 2015 17:15:27 +0300 + nginx (1.9.3-1) unstable; urgency=medium [ Christos Trochalakis] From fba932f24fa105edaf3b928e82acc55a9759ed61 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Mon, 24 Aug 2015 15:17:09 +0300 Subject: [PATCH 003/600] Imported Upstream version 1.9.4 --- CHANGES | 34 +- CHANGES.ru | 35 +- src/core/nginx.h | 4 +- src/core/ngx_connection.c | 46 +- src/core/ngx_connection.h | 1 + src/core/ngx_hash.c | 10 +- src/core/ngx_open_file_cache.c | 2 +- src/http/modules/ngx_http_fastcgi_module.c | 1 - src/http/modules/ngx_http_map_module.c | 10 +- src/http/modules/ngx_http_sub_filter_module.c | 569 ++++++++++++------ .../ngx_http_upstream_keepalive_module.c | 4 + .../modules/ngx_http_upstream_zone_module.c | 2 +- src/http/modules/perl/nginx.xs | 18 +- src/http/ngx_http_core_module.c | 10 +- src/mail/ngx_mail_core_module.c | 3 +- src/os/unix/ngx_process_cycle.c | 19 +- src/stream/ngx_stream.h | 1 + src/stream/ngx_stream_core_module.c | 13 +- src/stream/ngx_stream_handler.c | 23 +- src/stream/ngx_stream_proxy_module.c | 92 ++- src/stream/ngx_stream_upstream_zone_module.c | 2 +- 21 files changed, 631 insertions(+), 268 deletions(-) diff --git a/CHANGES b/CHANGES index 01130f8..120c31d 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,36 @@ +Changes with nginx 1.9.4 18 Aug 2015 + + *) Change: the "proxy_downstream_buffer" and "proxy_upstream_buffer" + directives of the stream module are replaced with the + "proxy_buffer_size" directive. + + *) Feature: the "tcp_nodelay" directive in the stream module. + + *) Feature: multiple "sub_filter" directives can be used simultaneously. + + *) Feature: variables support in the search string of the "sub_filter" + directive. + + *) Workaround: configuration testing might fail under Linux OpenVZ. + Thanks to Gena Makhomed. + + *) Bugfix: old worker processes might hog CPU after reconfiguration with + a large number of worker_connections. + + *) Bugfix: a segmentation fault might occur in a worker process if the + "try_files" and "alias" directives were used inside a location given + by a regular expression; the bug had appeared in 1.7.1. + + *) Bugfix: the "try_files" directive inside a nested location given by a + regular expression worked incorrectly if the "alias" directive was + used in the outer location. + + *) Bugfix: in hash table initialization error handling. + + *) Bugfix: nginx could not be built with Visual Studio 2015. + + Changes with nginx 1.9.3 14 Jul 2015 *) Change: duplicate "http", "mail", and "stream" blocks are now @@ -57,7 +89,7 @@ Changes with nginx 1.9.1 26 May 2015 *) Change: some long deprecated directives are not supported anymore. *) Feature: the "reuseport" parameter of the "listen" directive. - Thanks to Sepherosa Ziehau and Yingqi Lu. + Thanks to Yingqi Lu at Intel and Sepherosa Ziehau. *) Feature: the $upstream_connect_time variable. diff --git a/CHANGES.ru b/CHANGES.ru index 25dfd22..09a0fe7 100644 --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,37 @@ +Изменения в nginx 1.9.4 18.08.2015 + + *) Изменение: директивы proxy_downstream_buffer и proxy_upstream_buffer + в модуле stream заменены директивой proxy_buffer_size. + + *) Добавление: директива tcp_nodelay в модуле stream. + + *) Добавление: теперь можно указать несколько директив sub_filter + одновременно. + + *) Добавление: директива sub_filter поддерживает переменные в строке + поиска. + + *) Изменение: тестирование конфигурации могло не работать под Linux + OpenVZ. + Спасибо Геннадию Махомеду. + + *) Исправление: после переконфигурации старые рабочие процессы могли + сильно нагружать процессор при больших значениях worker_connections. + + *) Исправление: при совместном использовании директив try_files и alias + внутри location'а, заданного регулярным выражением, в рабочем + процессе мог произойти segmentation fault; ошибка появилась в 1.7.1. + + *) Исправление: директива try_files внутри вложенного location'а, + заданного регулярным выражением, работала неправильно, если во + внешнем location'е использовалась директива alias. + + *) Исправление: в обработке ошибок при построении хэш-таблиц. + + *) Исправление: nginx не собирался с Visual Studio 2015. + + Изменения в nginx 1.9.3 14.07.2015 *) Изменение: дублирующиеся блоки http, mail и stream теперь запрещены. @@ -56,7 +89,7 @@ поддерживаются. *) Добавление: параметр reuseport директивы listen. - Спасибо Sepherosa Ziehau и Yingqi Lu. + Спасибо Yingqi Lu из Intel и Sepherosa Ziehau. *) Добавление: переменная $upstream_connect_time. diff --git a/src/core/nginx.h b/src/core/nginx.h index dfb90ea..a655f30 100644 --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1009003 -#define NGINX_VERSION "1.9.3" +#define nginx_version 1009004 +#define NGINX_VERSION "1.9.4" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c index 04a365a..9f2675b 100644 --- a/src/core/ngx_connection.c +++ b/src/core/ngx_connection.c @@ -567,9 +567,19 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle) #endif if (listen(s, ls[i].backlog) == -1) { - ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, - "listen() to %V, backlog %d failed", - &ls[i].addr_text, ls[i].backlog); + err = ngx_socket_errno; + + /* + * on OpenVZ after suspend/resume EADDRINUSE + * may be returned by listen() instead of bind(), see + * https://bugzilla.openvz.org/show_bug.cgi?id=2470 + */ + + if (err != NGX_EADDRINUSE || !ngx_test_config) { + ngx_log_error(NGX_LOG_EMERG, log, err, + "listen() to %V, backlog %d failed", + &ls[i].addr_text, ls[i].backlog); + } if (ngx_close_socket(s) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, @@ -577,7 +587,15 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle) &ls[i].addr_text); } - return NGX_ERROR; + if (err != NGX_EADDRINUSE) { + return NGX_ERROR; + } + + if (!ngx_test_config) { + failed = 1; + } + + continue; } ls[i].listen = 1; @@ -1145,6 +1163,26 @@ ngx_drain_connections(void) } +void +ngx_close_idle_connections(ngx_cycle_t *cycle) +{ + ngx_uint_t i; + ngx_connection_t *c; + + c = cycle->connections; + + for (i = 0; i < cycle->connection_n; i++) { + + /* THREAD: lock */ + + if (c[i].fd != -1 && c[i].idle) { + c[i].close = 1; + c[i].read->handler(c[i].read); + } + } +} + + ngx_int_t ngx_connection_local_sockaddr(ngx_connection_t *c, ngx_str_t *s, ngx_uint_t port) diff --git a/src/core/ngx_connection.h b/src/core/ngx_connection.h index a49aa95..c3aca7f 100644 --- a/src/core/ngx_connection.h +++ b/src/core/ngx_connection.h @@ -215,6 +215,7 @@ ngx_int_t ngx_open_listening_sockets(ngx_cycle_t *cycle); void ngx_configure_listening_sockets(ngx_cycle_t *cycle); void ngx_close_listening_sockets(ngx_cycle_t *cycle); void ngx_close_connection(ngx_connection_t *c); +void ngx_close_idle_connections(ngx_cycle_t *cycle); ngx_int_t ngx_connection_local_sockaddr(ngx_connection_t *c, ngx_str_t *s, ngx_uint_t port); ngx_int_t ngx_connection_error(ngx_connection_t *c, ngx_err_t err, char *text); diff --git a/src/core/ngx_hash.c b/src/core/ngx_hash.c index e707c09..1a5d0be 100644 --- a/src/core/ngx_hash.c +++ b/src/core/ngx_hash.c @@ -257,11 +257,19 @@ ngx_hash_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names, ngx_uint_t nelts) ngx_uint_t i, n, key, size, start, bucket_size; ngx_hash_elt_t *elt, **buckets; + if (hinit->max_size == 0) { + ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0, + "could not build %s, you should " + "increase %s_max_size: %i", + hinit->name, hinit->name, hinit->max_size); + return NGX_ERROR; + } + for (n = 0; n < nelts; n++) { if (hinit->bucket_size < NGX_HASH_ELT_SIZE(&names[n]) + sizeof(void *)) { ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0, - "could not build the %s, you should " + "could not build %s, you should " "increase %s_bucket_size: %i", hinit->name, hinit->name, hinit->bucket_size); return NGX_ERROR; diff --git a/src/core/ngx_open_file_cache.c b/src/core/ngx_open_file_cache.c index 4df2134..f8bb2e3 100644 --- a/src/core/ngx_open_file_cache.c +++ b/src/core/ngx_open_file_cache.c @@ -128,7 +128,7 @@ ngx_open_file_cache_cleanup(void *data) if (cache->current) { ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, - "%ui items still leave in open file cache", + "%ui items still left in open file cache", cache->current); } diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c index f3f78e8..668719f 100644 --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -1770,7 +1770,6 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r) #if (NGX_HTTP_CACHE) if (f->large_stderr && r->cache) { - u_char *start; ssize_t len; ngx_http_fastcgi_header_t *fh; diff --git a/src/http/modules/ngx_http_map_module.c b/src/http/modules/ngx_http_map_module.c index 3245e04..2b80d0f 100644 --- a/src/http/modules/ngx_http_map_module.c +++ b/src/http/modules/ngx_http_map_module.c @@ -375,7 +375,7 @@ ngx_http_map_cmp_dns_wildcards(const void *one, const void *two) static char * ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) { - ngx_int_t rc, index; + ngx_int_t rv, index; ngx_str_t *value, name; ngx_uint_t i, key; ngx_http_map_conf_ctx_t *ctx; @@ -546,19 +546,19 @@ found: value[0].data++; } - rc = ngx_hash_add_key(&ctx->keys, &value[0], var, + rv = ngx_hash_add_key(&ctx->keys, &value[0], var, (ctx->hostnames) ? NGX_HASH_WILDCARD_KEY : 0); - if (rc == NGX_OK) { + if (rv == NGX_OK) { return NGX_CONF_OK; } - if (rc == NGX_DECLINED) { + if (rv == NGX_DECLINED) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid hostname or wildcard \"%V\"", &value[0]); } - if (rc == NGX_BUSY) { + if (rv == NGX_BUSY) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "conflicting parameter \"%V\"", &value[0]); } diff --git a/src/http/modules/ngx_http_sub_filter_module.c b/src/http/modules/ngx_http_sub_filter_module.c index e6a34a7..0a4ff6d 100644 --- a/src/http/modules/ngx_http_sub_filter_module.c +++ b/src/http/modules/ngx_http_sub_filter_module.c @@ -11,8 +11,32 @@ typedef struct { - ngx_str_t match; + ngx_http_complex_value_t match; ngx_http_complex_value_t value; +} ngx_http_sub_pair_t; + + +typedef struct { + ngx_str_t match; + ngx_http_complex_value_t *value; +} ngx_http_sub_match_t; + + +typedef struct { + ngx_uint_t min_match_len; + ngx_uint_t max_match_len; + + u_char index[257]; + u_char shift[256]; +} ngx_http_sub_tables_t; + + +typedef struct { + ngx_uint_t dynamic; /* unsigned dynamic:1; */ + + ngx_array_t *pairs; + + ngx_http_sub_tables_t *tables; ngx_hash_t types; @@ -20,17 +44,11 @@ typedef struct { ngx_flag_t last_modified; ngx_array_t *types_keys; + ngx_array_t *matches; } ngx_http_sub_loc_conf_t; -typedef enum { - sub_start_state = 0, - sub_match_state, -} ngx_http_sub_state_e; - - typedef struct { - ngx_str_t match; ngx_str_t saved; ngx_str_t looked; @@ -48,12 +66,20 @@ typedef struct { ngx_chain_t *busy; ngx_chain_t *free; - ngx_str_t sub; + ngx_str_t *sub; + ngx_uint_t applied; - ngx_uint_t state; + ngx_int_t offset; + ngx_uint_t index; + + ngx_http_sub_tables_t *tables; + ngx_array_t *matches; } ngx_http_sub_ctx_t; +static ngx_uint_t ngx_http_sub_cmp_index; + + static ngx_int_t ngx_http_sub_output(ngx_http_request_t *r, ngx_http_sub_ctx_t *ctx); static ngx_int_t ngx_http_sub_parse(ngx_http_request_t *r, @@ -64,6 +90,9 @@ static char * ngx_http_sub_filter(ngx_conf_t *cf, ngx_command_t *cmd, static void *ngx_http_sub_create_conf(ngx_conf_t *cf); static char *ngx_http_sub_merge_conf(ngx_conf_t *cf, void *parent, void *child); +static void ngx_http_sub_init_tables(ngx_http_sub_tables_t *tables, + ngx_http_sub_match_t *match, ngx_uint_t n); +static ngx_int_t ngx_http_sub_cmp_matches(const void *one, const void *two); static ngx_int_t ngx_http_sub_filter_init(ngx_conf_t *cf); @@ -139,12 +168,16 @@ static ngx_http_output_body_filter_pt ngx_http_next_body_filter; static ngx_int_t ngx_http_sub_header_filter(ngx_http_request_t *r) { - ngx_http_sub_ctx_t *ctx; + ngx_str_t *m; + ngx_uint_t i, j, n; + ngx_http_sub_ctx_t *ctx; + ngx_http_sub_pair_t *pairs; + ngx_http_sub_match_t *matches; ngx_http_sub_loc_conf_t *slcf; slcf = ngx_http_get_module_loc_conf(r, ngx_http_sub_filter_module); - if (slcf->match.len == 0 + if (slcf->pairs == NULL || r->headers_out.content_length_n == 0 || ngx_http_test_content_type(r, &slcf->types) == NULL) { @@ -156,19 +189,76 @@ ngx_http_sub_header_filter(ngx_http_request_t *r) return NGX_ERROR; } - ctx->saved.data = ngx_pnalloc(r->pool, slcf->match.len); - if (ctx->saved.data == NULL) { - return NGX_ERROR; - } + if (slcf->dynamic == 0) { + ctx->tables = slcf->tables; + ctx->matches = slcf->matches; - ctx->looked.data = ngx_pnalloc(r->pool, slcf->match.len); - if (ctx->looked.data == NULL) { - return NGX_ERROR; + } else { + pairs = slcf->pairs->elts; + n = slcf->pairs->nelts; + + matches = ngx_pcalloc(r->pool, sizeof(ngx_http_sub_match_t) * n); + if (matches == NULL) { + return NGX_ERROR; + } + + j = 0; + for (i = 0; i < n; i++) { + matches[j].value = &pairs[i].value; + + if (pairs[i].match.lengths == NULL) { + matches[j].match = pairs[i].match.value; + j++; + continue; + } + + m = &matches[j].match; + if (ngx_http_complex_value(r, &pairs[i].match, m) != NGX_OK) { + return NGX_ERROR; + } + + if (m->len == 0) { + continue; + } + + ngx_strlow(m->data, m->data, m->len); + j++; + } + + if (j == 0) { + return ngx_http_next_header_filter(r); + } + + ctx->matches = ngx_pnalloc(r->pool, sizeof(ngx_array_t)); + if (ctx->matches == NULL) { + return NGX_ERROR; + } + + ctx->matches->elts = matches; + ctx->matches->nelts = j; + + ctx->tables = ngx_pnalloc(r->pool, sizeof(ngx_http_sub_tables_t)); + if (ctx->tables == NULL) { + return NGX_ERROR; + } + + ngx_http_sub_init_tables(ctx->tables, ctx->matches->elts, + ctx->matches->nelts); } ngx_http_set_ctx(r, ctx, ngx_http_sub_filter_module); - ctx->match = slcf->match; + ctx->saved.data = ngx_pnalloc(r->pool, ctx->tables->max_match_len - 1); + if (ctx->saved.data == NULL) { + return NGX_ERROR; + } + + ctx->looked.data = ngx_pnalloc(r->pool, ctx->tables->max_match_len - 1); + if (ctx->looked.data == NULL) { + return NGX_ERROR; + } + + ctx->offset = ctx->tables->min_match_len - 1; ctx->last_out = &ctx->out; r->filter_need_in_memory = 1; @@ -194,8 +284,10 @@ ngx_http_sub_body_filter(ngx_http_request_t *r, ngx_chain_t *in) { ngx_int_t rc; ngx_buf_t *b; + ngx_str_t *sub; ngx_chain_t *cl; ngx_http_sub_ctx_t *ctx; + ngx_http_sub_match_t *match; ngx_http_sub_loc_conf_t *slcf; ctx = ngx_http_get_module_ctx(r, ngx_http_sub_filter_module); @@ -242,18 +334,10 @@ ngx_http_sub_body_filter(ngx_http_request_t *r, ngx_chain_t *in) ctx->pos = ctx->buf->pos; } - if (ctx->state == sub_start_state) { - ctx->copy_start = ctx->pos; - ctx->copy_end = ctx->pos; - } - b = NULL; while (ctx->pos < ctx->buf->last) { - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "saved: \"%V\" state: %d", &ctx->saved, ctx->state); - rc = ngx_http_sub_parse(r, ctx); ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, @@ -320,20 +404,6 @@ ngx_http_sub_body_filter(ngx_http_request_t *r, ngx_chain_t *in) ctx->last_out = &cl->next; } - if (ctx->state == sub_start_state) { - ctx->copy_start = ctx->pos; - ctx->copy_end = ctx->pos; - - } else { - ctx->copy_start = NULL; - ctx->copy_end = NULL; - } - - if (ctx->looked.len > (size_t) (ctx->pos - ctx->buf->pos)) { - ctx->saved.len = ctx->looked.len - (ctx->pos - ctx->buf->pos); - ngx_memcpy(ctx->saved.data, ctx->looked.data, ctx->saved.len); - } - if (rc == NGX_AGAIN) { continue; } @@ -352,19 +422,30 @@ ngx_http_sub_body_filter(ngx_http_request_t *r, ngx_chain_t *in) slcf = ngx_http_get_module_loc_conf(r, ngx_http_sub_filter_module); - if (ctx->sub.data == NULL) { + if (ctx->sub == NULL) { + ctx->sub = ngx_pcalloc(r->pool, sizeof(ngx_str_t) + * ctx->matches->nelts); + if (ctx->sub == NULL) { + return NGX_ERROR; + } + } - if (ngx_http_complex_value(r, &slcf->value, &ctx->sub) + sub = &ctx->sub[ctx->index]; + + if (sub->data == NULL) { + match = ctx->matches->elts; + + if (ngx_http_complex_value(r, match[ctx->index].value, sub) != NGX_OK) { return NGX_ERROR; } } - if (ctx->sub.len) { + if (sub->len) { b->memory = 1; - b->pos = ctx->sub.data; - b->last = ctx->sub.data + ctx->sub.len; + b->pos = sub->data; + b->last = sub->data + sub->len; } else { b->sync = 1; @@ -373,7 +454,8 @@ ngx_http_sub_body_filter(ngx_http_request_t *r, ngx_chain_t *in) *ctx->last_out = cl; ctx->last_out = &cl->next; - ctx->once = slcf->once; + ctx->index = 0; + ctx->once = slcf->once && (++ctx->applied == ctx->matches->nelts); continue; } @@ -428,9 +510,6 @@ ngx_http_sub_body_filter(ngx_http_request_t *r, ngx_chain_t *in) } ctx->buf = NULL; - - ctx->saved.len = ctx->looked.len; - ngx_memcpy(ctx->saved.data, ctx->looked.data, ctx->looked.len); } if (ctx->out == NULL && ctx->busy == NULL) { @@ -513,158 +592,142 @@ ngx_http_sub_output(ngx_http_request_t *r, ngx_http_sub_ctx_t *ctx) static ngx_int_t ngx_http_sub_parse(ngx_http_request_t *r, ngx_http_sub_ctx_t *ctx) { - u_char *p, *last, *copy_end, ch, match; - size_t looked, i; - ngx_http_sub_state_e state; + u_char *p, *last, *pat, *pat_end, c; + ngx_str_t *m; + ngx_int_t offset, start, next, end, len, rc; + ngx_uint_t shift, i, j; + ngx_http_sub_match_t *match; + ngx_http_sub_tables_t *tables; + ngx_http_sub_loc_conf_t *slcf; + + slcf = ngx_http_get_module_loc_conf(r, ngx_http_sub_filter_module); + tables = ctx->tables; + + offset = ctx->offset; + end = ctx->buf->last - ctx->pos; if (ctx->once) { - ctx->copy_start = ctx->pos; - ctx->copy_end = ctx->buf->last; - ctx->pos = ctx->buf->last; - ctx->looked.len = 0; - - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "once"); - - return NGX_AGAIN; + /* sets start and next to end */ + offset = end + (ngx_int_t) tables->min_match_len - 1; + goto again; } - state = ctx->state; - looked = ctx->looked.len; - last = ctx->buf->last; - copy_end = ctx->copy_end; + while (offset < end) { - for (p = ctx->pos; p < last; p++) { + c = offset < 0 ? ctx->looked.data[ctx->looked.len + offset] + : ctx->pos[offset]; - ch = *p; - ch = ngx_tolower(ch); - - if (state == sub_start_state) { - - /* the tight loop */ - - match = ctx->match.data[0]; - - for ( ;; ) { - if (ch == match) { - - if (ctx->match.len == 1) { - ctx->pos = p + 1; - ctx->copy_end = p; - - return NGX_OK; - } - - copy_end = p; - ctx->looked.data[0] = *p; - looked = 1; - state = sub_match_state; - - goto match_started; - } - - if (++p == last) { - break; - } - - ch = *p; - ch = ngx_tolower(ch); - } - - ctx->state = state; - ctx->pos = p; - ctx->looked.len = looked; - ctx->copy_end = p; - - if (ctx->copy_start == NULL) { - ctx->copy_start = ctx->buf->pos; - } - - return NGX_AGAIN; - - match_started: + c = ngx_tolower(c); + shift = tables->shift[c]; + if (shift > 0) { + offset += shift; continue; } - /* state == sub_match_state */ + /* a potential match */ - if (ch == ctx->match.data[looked]) { - ctx->looked.data[looked] = *p; - looked++; + start = offset - (ngx_int_t) tables->min_match_len + 1; + match = ctx->matches->elts; - if (looked == ctx->match.len) { + i = ngx_max(tables->index[c], ctx->index); + j = tables->index[c + 1]; - ctx->state = sub_start_state; - ctx->pos = p + 1; - ctx->looked.len = 0; - ctx->saved.len = 0; - ctx->copy_end = copy_end; + while (i != j) { - if (ctx->copy_start == NULL && copy_end) { - ctx->copy_start = ctx->buf->pos; - } - - return NGX_OK; + if (slcf->once && ctx->sub && ctx->sub[i].data) { + goto next; } - } else { - /* - * check if there is another partial match in previously - * matched substring to catch cases like "aab" in "aaab" - */ + m = &match[i].match; - ctx->looked.data[looked] = *p; - looked++; + pat = m->data; + pat_end = m->data + m->len; - for (i = 1; i < looked; i++) { - if (ngx_strncasecmp(ctx->looked.data + i, - ctx->match.data, looked - i) - == 0) - { - break; - } - } - - if (i < looked) { - if (ctx->saved.len > i) { - ctx->saved.len = i; - } - - if ((size_t) (p + 1 - ctx->buf->pos) >= looked - i) { - copy_end = p + 1 - (looked - i); - } - - ngx_memmove(ctx->looked.data, ctx->looked.data + i, looked - i); - looked = looked - i; + if (start >= 0) { + p = ctx->pos + start; } else { - copy_end = p; - looked = 0; - state = sub_start_state; + last = ctx->looked.data + ctx->looked.len; + p = last + start; + + while (p < last && pat < pat_end) { + if (ngx_tolower(*p) != *pat) { + goto next; + } + + p++; + pat++; + } + + p = ctx->pos; } - if (ctx->saved.len) { + while (p < ctx->buf->last && pat < pat_end) { + if (ngx_tolower(*p) != *pat) { + goto next; + } + p++; - goto out; + pat++; } + + ctx->index = i; + + if (pat != pat_end) { + /* partial match */ + goto again; + } + + ctx->offset = offset + (ngx_int_t) m->len; + next = start + (ngx_int_t) m->len; + end = ngx_max(next, 0); + rc = NGX_OK; + + goto done; + + next: + + i++; } + + offset++; + ctx->index = 0; } - ctx->saved.len = 0; +again: -out: + ctx->offset = offset; + start = offset - (ngx_int_t) tables->min_match_len + 1; + next = start; + rc = NGX_AGAIN; - ctx->state = state; - ctx->pos = p; - ctx->looked.len = looked; +done: - ctx->copy_end = (state == sub_start_state) ? p : copy_end; + /* send [ - looked.len, start ] to client */ - if (ctx->copy_start == NULL && ctx->copy_end) { - ctx->copy_start = ctx->buf->pos; - } + ctx->saved.len = ctx->looked.len + ngx_min(start, 0); + ngx_memcpy(ctx->saved.data, ctx->looked.data, ctx->saved.len); - return NGX_AGAIN; + ctx->copy_start = ctx->pos; + ctx->copy_end = ctx->pos + ngx_max(start, 0); + + /* save [ next, end ] in looked */ + + len = ngx_min(next, 0); + p = ctx->looked.data; + p = ngx_movemem(p, p + ctx->looked.len + len, - len); + + len = ngx_max(next, 0); + p = ngx_cpymem(p, ctx->pos + len, end - len); + ctx->looked.len = p - ctx->looked.data; + + /* update position */ + + ctx->pos += end; + ctx->offset -= end; + + return rc; } @@ -674,23 +737,60 @@ ngx_http_sub_filter(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ngx_http_sub_loc_conf_t *slcf = conf; ngx_str_t *value; + ngx_http_sub_pair_t *pair; ngx_http_compile_complex_value_t ccv; - if (slcf->match.data) { - return "is duplicate"; - } - value = cf->args->elts; + if (value[1].len == 0) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "empty search pattern"); + return NGX_CONF_ERROR; + } + + if (slcf->pairs == NULL) { + slcf->pairs = ngx_array_create(cf->pool, 1, + sizeof(ngx_http_sub_pair_t)); + if (slcf->pairs == NULL) { + return NGX_CONF_ERROR; + } + } + + if (slcf->pairs->nelts == 255) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "number of search patterns exceeds 255"); + return NGX_CONF_ERROR; + } + ngx_strlow(value[1].data, value[1].data, value[1].len); - slcf->match = value[1]; + pair = ngx_array_push(slcf->pairs); + if (pair == NULL) { + return NGX_CONF_ERROR; + } + + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[1]; + ccv.complex_value = &pair->match; + + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + + if (ccv.complex_value->lengths != NULL) { + slcf->dynamic = 1; + + } else { + ngx_strlow(pair->match.value.data, pair->match.value.data, + pair->match.value.len); + } ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); ccv.cf = cf; ccv.value = &value[2]; - ccv.complex_value = &slcf->value; + ccv.complex_value = &pair->value; if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { return NGX_CONF_ERROR; @@ -713,9 +813,12 @@ ngx_http_sub_create_conf(ngx_conf_t *cf) /* * set by ngx_pcalloc(): * - * conf->match = { 0, NULL }; + * conf->dynamic = 0; + * conf->pairs = NULL; + * conf->tables = NULL; * conf->types = { NULL }; * conf->types_keys = NULL; + * conf->matches = NULL; */ slcf->once = NGX_CONF_UNSET; @@ -728,17 +831,15 @@ ngx_http_sub_create_conf(ngx_conf_t *cf) static char * ngx_http_sub_merge_conf(ngx_conf_t *cf, void *parent, void *child) { - ngx_http_sub_loc_conf_t *prev = parent; - ngx_http_sub_loc_conf_t *conf = child; + ngx_uint_t i, n; + ngx_http_sub_pair_t *pairs; + ngx_http_sub_match_t *matches; + ngx_http_sub_loc_conf_t *prev = parent; + ngx_http_sub_loc_conf_t *conf = child; ngx_conf_merge_value(conf->once, prev->once, 1); - ngx_conf_merge_str_value(conf->match, prev->match, ""); ngx_conf_merge_value(conf->last_modified, prev->last_modified, 0); - if (conf->value.value.data == NULL) { - conf->value = prev->value; - } - if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types, &prev->types_keys, &prev->types, ngx_http_html_default_types) @@ -747,10 +848,108 @@ ngx_http_sub_merge_conf(ngx_conf_t *cf, void *parent, void *child) return NGX_CONF_ERROR; } + if (conf->pairs == NULL) { + conf->dynamic = prev->dynamic; + conf->pairs = prev->pairs; + conf->matches = prev->matches; + conf->tables = prev->tables; + + } else if (conf->dynamic == 0){ + pairs = conf->pairs->elts; + n = conf->pairs->nelts; + + matches = ngx_pnalloc(cf->pool, sizeof(ngx_http_sub_match_t) * n); + if (matches == NULL) { + return NGX_CONF_ERROR; + } + + for (i = 0; i < n; i++) { + matches[i].match = pairs[i].match.value; + matches[i].value = &pairs[i].value; + } + + conf->matches = ngx_pnalloc(cf->pool, sizeof(ngx_array_t)); + if (conf->matches == NULL) { + return NGX_CONF_ERROR; + } + + conf->matches->elts = matches; + conf->matches->nelts = n; + + conf->tables = ngx_palloc(cf->pool, sizeof(ngx_http_sub_tables_t)); + if (conf->tables == NULL) { + return NGX_CONF_ERROR; + } + + ngx_http_sub_init_tables(conf->tables, conf->matches->elts, + conf->matches->nelts); + } + return NGX_CONF_OK; } +static void +ngx_http_sub_init_tables(ngx_http_sub_tables_t *tables, + ngx_http_sub_match_t *match, ngx_uint_t n) +{ + u_char c; + ngx_uint_t i, j, min, max, ch; + + min = match[0].match.len; + max = match[0].match.len; + + for (i = 1; i < n; i++) { + min = ngx_min(min, match[i].match.len); + max = ngx_max(max, match[i].match.len); + } + + tables->min_match_len = min; + tables->max_match_len = max; + + ngx_http_sub_cmp_index = tables->min_match_len - 1; + ngx_sort(match, n, sizeof(ngx_http_sub_match_t), ngx_http_sub_cmp_matches); + + min = ngx_min(min, 255); + ngx_memset(tables->shift, min, 256); + + ch = 0; + + for (i = 0; i < n; i++) { + + for (j = 0; j < min; j++) { + c = match[i].match.data[tables->min_match_len - 1 - j]; + tables->shift[c] = ngx_min(tables->shift[c], (u_char) j); + } + + c = match[i].match.data[tables->min_match_len - 1]; + while (ch <= c) { + tables->index[ch++] = (u_char) i; + } + } + + while (ch < 257) { + tables->index[ch++] = (u_char) n; + } +} + + +static ngx_int_t +ngx_http_sub_cmp_matches(const void *one, const void *two) +{ + ngx_int_t c1, c2; + ngx_http_sub_match_t *first, *second; + + first = (ngx_http_sub_match_t *) one; + second = (ngx_http_sub_match_t *) two; + + c1 = first->match.data[ngx_http_sub_cmp_index]; + c2 = second->match.data[ngx_http_sub_cmp_index]; + + return c1 - c2; +} + + static ngx_int_t ngx_http_sub_filter_init(ngx_conf_t *cf) { diff --git a/src/http/modules/ngx_http_upstream_keepalive_module.c b/src/http/modules/ngx_http_upstream_keepalive_module.c index 768881e..51887b4 100644 --- a/src/http/modules/ngx_http_upstream_keepalive_module.c +++ b/src/http/modules/ngx_http_upstream_keepalive_module.c @@ -302,6 +302,10 @@ ngx_http_upstream_free_keepalive_peer(ngx_peer_connection_t *pc, void *data, goto invalid; } + if (ngx_terminate || ngx_exiting) { + goto invalid; + } + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { goto invalid; } diff --git a/src/http/modules/ngx_http_upstream_zone_module.c b/src/http/modules/ngx_http_upstream_zone_module.c index 7169c36..7e5bd74 100644 --- a/src/http/modules/ngx_http_upstream_zone_module.c +++ b/src/http/modules/ngx_http_upstream_zone_module.c @@ -159,7 +159,7 @@ ngx_http_upstream_init_zone(ngx_shm_zone_t *shm_zone, void *data) /* copy peers to shared memory */ - peersp = (ngx_http_upstream_rr_peers_t **) &shpool->data; + peersp = (ngx_http_upstream_rr_peers_t **) (void *) &shpool->data; for (i = 0; i < umcf->upstreams.nelts; i++) { uscf = uscfp[i]; diff --git a/src/http/modules/perl/nginx.xs b/src/http/modules/perl/nginx.xs index 71f17a8..6716620 100644 --- a/src/http/modules/perl/nginx.xs +++ b/src/http/modules/perl/nginx.xs @@ -98,6 +98,9 @@ ngx_http_perl_output(ngx_http_request_t *r, ngx_buf_t *b) MODULE = nginx PACKAGE = nginx +PROTOTYPES: DISABLE + + void status(r, code) CODE: @@ -268,19 +271,16 @@ header_in(r, key) } #endif - if (hh->offset) { + ph = (ngx_table_elt_t **) ((char *) &r->headers_in + hh->offset); - ph = (ngx_table_elt_t **) ((char *) &r->headers_in + hh->offset); + if (*ph) { + ngx_http_perl_set_targ((*ph)->value.data, (*ph)->value.len); - if (*ph) { - ngx_http_perl_set_targ((*ph)->value.data, (*ph)->value.len); - - goto done; - } - - XSRETURN_UNDEF; + goto done; } + XSRETURN_UNDEF; + multi: /* Cookie, X-Forwarded-For */ diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index d423d8b..22400ca 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -1239,7 +1239,9 @@ ngx_http_core_try_files_phase(ngx_http_request_t *r, *e.pos = '\0'; - if (alias && ngx_strncmp(name, clcf->name.data, alias) == 0) { + if (alias && alias != NGX_MAX_SIZE_T_VALUE + && ngx_strncmp(name, r->uri.data, alias) == 0) + { ngx_memmove(name, name + alias, len - alias); path.len -= alias; } @@ -1322,6 +1324,8 @@ ngx_http_core_try_files_phase(ngx_http_request_t *r, } } else { + name = r->uri.data; + r->uri.len = alias + path.len; r->uri.data = ngx_pnalloc(r->pool, r->uri.len); if (r->uri.data == NULL) { @@ -1329,8 +1333,8 @@ ngx_http_core_try_files_phase(ngx_http_request_t *r, return NGX_OK; } - p = ngx_copy(r->uri.data, clcf->name.data, alias); - ngx_memcpy(p, name, path.len); + p = ngx_copy(r->uri.data, name, alias); + ngx_memcpy(p, path.data, path.len); } ngx_http_set_exten(r); diff --git a/src/mail/ngx_mail_core_module.c b/src/mail/ngx_mail_core_module.c index 271afc4..c219296 100644 --- a/src/mail/ngx_mail_core_module.c +++ b/src/mail/ngx_mail_core_module.c @@ -434,8 +434,7 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) { #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) - struct sockaddr *sa; - u_char buf[NGX_SOCKADDR_STRLEN]; + u_char buf[NGX_SOCKADDR_STRLEN]; sa = &ls->u.sockaddr; diff --git a/src/os/unix/ngx_process_cycle.c b/src/os/unix/ngx_process_cycle.c index c69932e..5da0911 100644 --- a/src/os/unix/ngx_process_cycle.c +++ b/src/os/unix/ngx_process_cycle.c @@ -728,9 +728,6 @@ ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data) { ngx_int_t worker = (intptr_t) data; - ngx_uint_t i; - ngx_connection_t *c; - ngx_process = NGX_PROCESS_WORKER; ngx_worker = worker; @@ -741,19 +738,6 @@ ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data) for ( ;; ) { if (ngx_exiting) { - - c = cycle->connections; - - for (i = 0; i < cycle->connection_n; i++) { - - /* THREAD: lock */ - - if (c[i].fd != -1 && c[i].idle) { - c[i].close = 1; - c[i].read->handler(c[i].read); - } - } - ngx_event_cancel_timers(); if (ngx_event_timer_rbtree.root == ngx_event_timer_rbtree.sentinel) @@ -781,8 +765,9 @@ ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data) ngx_setproctitle("worker process is shutting down"); if (!ngx_exiting) { - ngx_close_listening_sockets(cycle); ngx_exiting = 1; + ngx_close_listening_sockets(cycle); + ngx_close_idle_connections(cycle); } } diff --git a/src/stream/ngx_stream.h b/src/stream/ngx_stream.h index 266101c..21953e9 100644 --- a/src/stream/ngx_stream.h +++ b/src/stream/ngx_stream.h @@ -132,6 +132,7 @@ typedef struct { u_char *file_name; ngx_int_t line; ngx_log_t *error_log; + ngx_flag_t tcp_nodelay; } ngx_stream_core_srv_conf_t; diff --git a/src/stream/ngx_stream_core_module.c b/src/stream/ngx_stream_core_module.c index 246f55c..4fe6818 100644 --- a/src/stream/ngx_stream_core_module.c +++ b/src/stream/ngx_stream_core_module.c @@ -45,6 +45,13 @@ static ngx_command_t ngx_stream_core_commands[] = { 0, NULL }, + { ngx_string("tcp_nodelay"), + NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_STREAM_SRV_CONF_OFFSET, + offsetof(ngx_stream_core_srv_conf_t, tcp_nodelay), + NULL }, + ngx_null_command }; @@ -122,6 +129,7 @@ ngx_stream_core_create_srv_conf(ngx_conf_t *cf) cscf->file_name = cf->conf_file->file.name.data; cscf->line = cf->conf_file->line; + cscf->tcp_nodelay = NGX_CONF_UNSET; return cscf; } @@ -148,6 +156,8 @@ ngx_stream_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) } } + ngx_conf_merge_value(conf->tcp_nodelay, prev->tcp_nodelay, 1); + return NGX_CONF_OK; } @@ -362,8 +372,7 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) { #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) - struct sockaddr *sa; - u_char buf[NGX_SOCKADDR_STRLEN]; + u_char buf[NGX_SOCKADDR_STRLEN]; sa = &ls->u.sockaddr; diff --git a/src/stream/ngx_stream_handler.c b/src/stream/ngx_stream_handler.c index 7b635fa..b3edb68 100644 --- a/src/stream/ngx_stream_handler.c +++ b/src/stream/ngx_stream_handler.c @@ -23,6 +23,7 @@ static void ngx_stream_ssl_handshake_handler(ngx_connection_t *c); void ngx_stream_init_connection(ngx_connection_t *c) { + int tcp_nodelay; u_char text[NGX_SOCKADDR_STRLEN]; size_t len; ngx_int_t rc; @@ -165,6 +166,24 @@ ngx_stream_init_connection(ngx_connection_t *c) } } + if (cscf->tcp_nodelay && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) { + ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0, "tcp_nodelay"); + + tcp_nodelay = 1; + + if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, + (const void *) &tcp_nodelay, sizeof(int)) == -1) + { + ngx_connection_error(c, ngx_socket_errno, + "setsockopt(TCP_NODELAY) failed"); + ngx_stream_close_connection(c); + return; + } + + c->tcp_nodelay = NGX_TCP_NODELAY_SET; + } + + #if (NGX_STREAM_SSL) { ngx_stream_ssl_conf_t *sslcf; @@ -309,9 +328,11 @@ ngx_stream_log_error(ngx_log_t *log, u_char *buf, size_t len) p = ngx_snprintf(buf, len, ", client: %V, server: %V", &s->connection->addr_text, &s->connection->listening->addr_text); + len -= p - buf; + buf = p; if (s->log_handler) { - return s->log_handler(log, p, len); + p = s->log_handler(log, buf, len); } return p; diff --git a/src/stream/ngx_stream_proxy_module.c b/src/stream/ngx_stream_proxy_module.c index 68af5a8..ea142e7 100644 --- a/src/stream/ngx_stream_proxy_module.c +++ b/src/stream/ngx_stream_proxy_module.c @@ -17,9 +17,8 @@ typedef struct { ngx_msec_t connect_timeout; ngx_msec_t timeout; ngx_msec_t next_upstream_timeout; - size_t downstream_buf_size; + size_t buffer_size; size_t upload_rate; - size_t upstream_buf_size; size_t download_rate; ngx_uint_t next_upstream_tries; ngx_flag_t next_upstream; @@ -97,6 +96,15 @@ static ngx_conf_bitmask_t ngx_stream_proxy_ssl_protocols[] = { #endif +static ngx_conf_deprecated_t ngx_conf_deprecated_proxy_downstream_buffer = { + ngx_conf_deprecated, "proxy_downstream_buffer", "proxy_buffer_size" +}; + +static ngx_conf_deprecated_t ngx_conf_deprecated_proxy_upstream_buffer = { + ngx_conf_deprecated, "proxy_upstream_buffer", "proxy_buffer_size" +}; + + static ngx_command_t ngx_stream_proxy_commands[] = { { ngx_string("proxy_pass"), @@ -127,12 +135,26 @@ static ngx_command_t ngx_stream_proxy_commands[] = { offsetof(ngx_stream_proxy_srv_conf_t, timeout), NULL }, + { ngx_string("proxy_buffer_size"), + NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_STREAM_SRV_CONF_OFFSET, + offsetof(ngx_stream_proxy_srv_conf_t, buffer_size), + NULL }, + { ngx_string("proxy_downstream_buffer"), NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, ngx_conf_set_size_slot, NGX_STREAM_SRV_CONF_OFFSET, - offsetof(ngx_stream_proxy_srv_conf_t, downstream_buf_size), - NULL }, + offsetof(ngx_stream_proxy_srv_conf_t, buffer_size), + &ngx_conf_deprecated_proxy_downstream_buffer }, + + { ngx_string("proxy_upstream_buffer"), + NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_STREAM_SRV_CONF_OFFSET, + offsetof(ngx_stream_proxy_srv_conf_t, buffer_size), + &ngx_conf_deprecated_proxy_upstream_buffer }, { ngx_string("proxy_upload_rate"), NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, @@ -141,13 +163,6 @@ static ngx_command_t ngx_stream_proxy_commands[] = { offsetof(ngx_stream_proxy_srv_conf_t, upload_rate), NULL }, - { ngx_string("proxy_upstream_buffer"), - NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_size_slot, - NGX_STREAM_SRV_CONF_OFFSET, - offsetof(ngx_stream_proxy_srv_conf_t, upstream_buf_size), - NULL }, - { ngx_string("proxy_download_rate"), NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, ngx_conf_set_size_slot, @@ -358,14 +373,14 @@ ngx_stream_proxy_handler(ngx_stream_session_t *s) u->proxy_protocol = pscf->proxy_protocol; u->start_sec = ngx_time(); - p = ngx_pnalloc(c->pool, pscf->downstream_buf_size); + p = ngx_pnalloc(c->pool, pscf->buffer_size); if (p == NULL) { ngx_stream_proxy_finalize(s, NGX_ERROR); return; } u->downstream_buf.start = p; - u->downstream_buf.end = p + pscf->downstream_buf_size; + u->downstream_buf.end = p + pscf->buffer_size; u->downstream_buf.pos = p; u->downstream_buf.last = p; @@ -376,8 +391,7 @@ ngx_stream_proxy_handler(ngx_stream_session_t *s) #if (NGX_STREAM_SSL) && pscf->ssl == NULL #endif - && pscf->downstream_buf_size >= NGX_PROXY_PROTOCOL_MAX_HEADER - ) + && pscf->buffer_size >= NGX_PROXY_PROTOCOL_MAX_HEADER) { /* optimization for a typical case */ @@ -464,13 +478,35 @@ ngx_stream_proxy_connect(ngx_stream_session_t *s) static void ngx_stream_proxy_init_upstream(ngx_stream_session_t *s) { + int tcp_nodelay; u_char *p; ngx_connection_t *c, *pc; ngx_log_handler_pt handler; ngx_stream_upstream_t *u; + ngx_stream_core_srv_conf_t *cscf; ngx_stream_proxy_srv_conf_t *pscf; u = s->upstream; + pc = u->peer.connection; + + cscf = ngx_stream_get_module_srv_conf(s, ngx_stream_core_module); + + if (cscf->tcp_nodelay && pc->tcp_nodelay == NGX_TCP_NODELAY_UNSET) { + ngx_log_debug0(NGX_LOG_DEBUG_STREAM, pc->log, 0, "tcp_nodelay"); + + tcp_nodelay = 1; + + if (setsockopt(pc->fd, IPPROTO_TCP, TCP_NODELAY, + (const void *) &tcp_nodelay, sizeof(int)) == -1) + { + ngx_connection_error(pc, ngx_socket_errno, + "setsockopt(TCP_NODELAY) failed"); + ngx_stream_proxy_next_upstream(s); + return; + } + + pc->tcp_nodelay = NGX_TCP_NODELAY_SET; + } if (u->proxy_protocol) { if (ngx_stream_proxy_send_proxy_protocol(s) != NGX_OK) { @@ -482,8 +518,6 @@ ngx_stream_proxy_init_upstream(ngx_stream_session_t *s) pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module); - pc = u->peer.connection; - #if (NGX_STREAM_SSL) if (pscf->ssl && pc->ssl == NULL) { ngx_stream_proxy_ssl_init_connection(s); @@ -494,18 +528,18 @@ ngx_stream_proxy_init_upstream(ngx_stream_session_t *s) c = s->connection; if (c->log->log_level >= NGX_LOG_INFO) { - ngx_str_t s; + ngx_str_t str; u_char addr[NGX_SOCKADDR_STRLEN]; - s.len = NGX_SOCKADDR_STRLEN; - s.data = addr; + str.len = NGX_SOCKADDR_STRLEN; + str.data = addr; - if (ngx_connection_local_sockaddr(pc, &s, 1) == NGX_OK) { + if (ngx_connection_local_sockaddr(pc, &str, 1) == NGX_OK) { handler = c->log->handler; c->log->handler = NULL; ngx_log_error(NGX_LOG_INFO, c->log, 0, "proxy %V connected to %V", - &s, u->peer.name); + &str, u->peer.name); c->log->handler = handler; } @@ -513,14 +547,14 @@ ngx_stream_proxy_init_upstream(ngx_stream_session_t *s) c->log->action = "proxying connection"; - p = ngx_pnalloc(c->pool, pscf->upstream_buf_size); + p = ngx_pnalloc(c->pool, pscf->buffer_size); if (p == NULL) { ngx_stream_proxy_finalize(s, NGX_ERROR); return; } u->upstream_buf.start = p; - u->upstream_buf.end = p + pscf->upstream_buf_size; + u->upstream_buf.end = p + pscf->buffer_size; u->upstream_buf.pos = p; u->upstream_buf.last = p; @@ -1295,9 +1329,8 @@ ngx_stream_proxy_create_srv_conf(ngx_conf_t *cf) conf->connect_timeout = NGX_CONF_UNSET_MSEC; conf->timeout = NGX_CONF_UNSET_MSEC; conf->next_upstream_timeout = NGX_CONF_UNSET_MSEC; - conf->downstream_buf_size = NGX_CONF_UNSET_SIZE; + conf->buffer_size = NGX_CONF_UNSET_SIZE; conf->upload_rate = NGX_CONF_UNSET_SIZE; - conf->upstream_buf_size = NGX_CONF_UNSET_SIZE; conf->download_rate = NGX_CONF_UNSET_SIZE; conf->next_upstream_tries = NGX_CONF_UNSET_UINT; conf->next_upstream = NGX_CONF_UNSET; @@ -1332,15 +1365,12 @@ ngx_stream_proxy_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_msec_value(conf->next_upstream_timeout, prev->next_upstream_timeout, 0); - ngx_conf_merge_size_value(conf->downstream_buf_size, - prev->downstream_buf_size, 16384); + ngx_conf_merge_size_value(conf->buffer_size, + prev->buffer_size, 16384); ngx_conf_merge_size_value(conf->upload_rate, prev->upload_rate, 0); - ngx_conf_merge_size_value(conf->upstream_buf_size, - prev->upstream_buf_size, 16384); - ngx_conf_merge_size_value(conf->download_rate, prev->download_rate, 0); diff --git a/src/stream/ngx_stream_upstream_zone_module.c b/src/stream/ngx_stream_upstream_zone_module.c index 87ddc03..ffc9e8a 100644 --- a/src/stream/ngx_stream_upstream_zone_module.c +++ b/src/stream/ngx_stream_upstream_zone_module.c @@ -155,7 +155,7 @@ ngx_stream_upstream_init_zone(ngx_shm_zone_t *shm_zone, void *data) /* copy peers to shared memory */ - peersp = (ngx_stream_upstream_rr_peers_t **) &shpool->data; + peersp = (ngx_stream_upstream_rr_peers_t **) (void *) &shpool->data; for (i = 0; i < umcf->upstreams.nelts; i++) { uscf = uscfp[i]; From a26063750ff282f1ad214846d19d17326e06a0a8 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Mon, 24 Aug 2015 15:19:12 +0300 Subject: [PATCH 004/600] New upstream release (1.9.4) --- debian/changelog | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/debian/changelog b/debian/changelog index 8e64506..9cde120 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +nginx (1.9.4-1) UNRELEASED; urgency=medium + + [ Christos Trochalakis] + * New upstream release. + + -- Christos Trochalakis Mon, 24 Aug 2015 15:19:01 +0300 + nginx (1.9.3-1) unstable; urgency=medium [ Christos Trochalakis] From f539cc0a49a4a5046ff511ee9215efbe2f31f3cf Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Wed, 22 Jul 2015 10:46:53 +0300 Subject: [PATCH 005/600] Fix licence ordering --- debian/copyright | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/debian/copyright b/debian/copyright index 9b123d1..a386770 100644 --- a/debian/copyright +++ b/debian/copyright @@ -30,6 +30,16 @@ Files: contrib/geo2nginx.pl Copyright: 2005, Andrei Nigmatulin License: BSD-2-clause +Files: debian/* +Copyright: 2007-2009, Fabio Tranchitella + 2008, Jose Parrella + 2009-2014, Kartik Mistry + 2010-2014, Michael Lustfield + 2011 Dmitry E. Oboukhov + 2011-2013, Cyril Lavier + 2013-2014, Christos Trochalakis +License: BSD-2-clause + Files: debian/modules/headers-more-nginx-module/* Copyright: Copyright (c) 2009-2014, Yichun "agentzh" Zhang (章亦春) , CloudFlare Inc. Copyright (c) 2010-2013, Bernd Dorn @@ -89,16 +99,6 @@ Files: debian/modules/ngx_http_substitutions_filter_module/* Copyright: Copyright (C) 2014 by Weibin Yao License: BSD-2-clause -Files: debian/* -Copyright: 2007-2009, Fabio Tranchitella - 2008, Jose Parrella - 2009-2014, Kartik Mistry - 2010-2014, Michael Lustfield - 2011 Dmitry E. Oboukhov - 2011-2013, Cyril Lavier - 2013-2014, Christos Trochalakis -License: BSD-2-clause - License: BSD-2-clause All rights reserved. . From a9600e2b4d49f207a36128797b30280a1d0f80ec Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Thu, 6 Aug 2015 15:40:05 +0300 Subject: [PATCH 006/600] Update debian/copyright for nginx source --- debian/copyright | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/debian/copyright b/debian/copyright index a386770..0edb73b 100644 --- a/debian/copyright +++ b/debian/copyright @@ -7,23 +7,20 @@ Copyright: 2002-2014 Igor Sysoev 2011-2014 Nginx, Inc. Maxim Dounin Valentin V. Bartenev + Roman Arutyunyan + Ruslan Ermilov License: BSD-2-clause Files: src/core/ngx_murmurhash.c Copyright: Copyright (C) Austin Appleby License: BSD-2-clause -Files: src/core/ngx_proxy_protocol.h - src/core/ngx_proxy_protocol.c -Copyright: Copyright (C) Roman Arutyunyan - Copyright (C) Nginx, Inc. -License: BSD-2-clause - Files: src/http/modules/ngx_http_scgi_module.c src/http/modules/ngx_http_uwsgi_module.c Copyright: Copyright (C) Igor Sysoev Copyright (C) Nginx, Inc. - Copyright (C) Manlio Perillo (manlio.perillo@gmail.com) + 2009-2010 Unbit S.a.s. + 2008 Manlio Perillo (manlio.perillo@gmail.com) License: BSD-2-clause Files: contrib/geo2nginx.pl From a8ef8abc7b0ea981cd14705f39ed247e26f243dc Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Mon, 24 Aug 2015 15:57:08 +0300 Subject: [PATCH 007/600] Release 1.9.4-1 --- debian/changelog | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index 9cde120..004eaa2 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,9 +1,11 @@ -nginx (1.9.4-1) UNRELEASED; urgency=medium +nginx (1.9.4-1) unstable; urgency=medium [ Christos Trochalakis] * New upstream release. + * debian/copyright: + + Fix licence order. - -- Christos Trochalakis Mon, 24 Aug 2015 15:19:01 +0300 + -- Christos Trochalakis Mon, 24 Aug 2015 16:23:20 +0300 nginx (1.9.3-1) unstable; urgency=medium From 3efc8819263ce2868b629fe53df139603bd614ee Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Fri, 25 Sep 2015 14:02:47 +0300 Subject: [PATCH 008/600] Imported Upstream version 1.9.5 --- CHANGES | 30 + CHANGES.ru | 31 + auto/make | 2 +- auto/modules | 18 +- auto/options | 6 +- auto/sources | 18 +- src/core/nginx.h | 4 +- src/core/ngx_connection.h | 2 +- src/core/ngx_hash.c | 4 + src/http/modules/ngx_http_rewrite_module.c | 2 +- src/http/modules/ngx_http_ssl_module.c | 24 +- src/http/modules/ngx_http_sub_filter_module.c | 3 +- src/http/ngx_http.c | 31 +- src/http/ngx_http.h | 8 +- src/http/ngx_http_copy_filter_module.c | 2 +- src/http/ngx_http_core_module.c | 47 +- src/http/ngx_http_core_module.h | 8 +- src/http/ngx_http_file_cache.c | 21 +- src/http/ngx_http_request.c | 40 +- src/http/ngx_http_request.h | 9 +- src/http/ngx_http_request_body.c | 12 +- src/http/ngx_http_spdy.c | 3701 --------------- src/http/ngx_http_spdy.h | 261 -- src/http/ngx_http_spdy_filter_module.c | 1222 ----- src/http/ngx_http_spdy_module.c | 408 -- src/http/ngx_http_upstream.c | 33 +- src/http/v2/ngx_http_v2.c | 4036 +++++++++++++++++ src/http/v2/ngx_http_v2.h | 333 ++ src/http/v2/ngx_http_v2_filter_module.c | 1291 ++++++ src/http/v2/ngx_http_v2_huff_decode.c | 2714 +++++++++++ src/http/v2/ngx_http_v2_huff_encode.c | 10 + src/http/v2/ngx_http_v2_module.c | 469 ++ .../ngx_http_v2_module.h} | 19 +- src/http/v2/ngx_http_v2_table.c | 349 ++ src/os/unix/ngx_files.c | 13 +- 35 files changed, 9453 insertions(+), 5728 deletions(-) delete mode 100644 src/http/ngx_http_spdy.c delete mode 100644 src/http/ngx_http_spdy.h delete mode 100644 src/http/ngx_http_spdy_filter_module.c delete mode 100644 src/http/ngx_http_spdy_module.c create mode 100644 src/http/v2/ngx_http_v2.c create mode 100644 src/http/v2/ngx_http_v2.h create mode 100644 src/http/v2/ngx_http_v2_filter_module.c create mode 100644 src/http/v2/ngx_http_v2_huff_decode.c create mode 100644 src/http/v2/ngx_http_v2_huff_encode.c create mode 100644 src/http/v2/ngx_http_v2_module.c rename src/http/{ngx_http_spdy_module.h => v2/ngx_http_v2_module.h} (58%) create mode 100644 src/http/v2/ngx_http_v2_table.c diff --git a/CHANGES b/CHANGES index 120c31d..47d33a4 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,34 @@ +Changes with nginx 1.9.5 22 Sep 2015 + + *) Feature: the ngx_http_v2_module (replaces ngx_http_spdy_module). + Thanks to Dropbox and Automattic for sponsoring this work. + + *) Change: now the "output_buffers" directive uses two buffers by + default. + + *) Change: now nginx limits subrequests recursion, not simultaneous + subrequests. + + *) Change: now nginx checks the whole cache key when returning a + response from cache. + Thanks to Gena Makhomed and Sergey Brester. + + *) Bugfix: "header already sent" alerts might appear in logs when using + cache; the bug had appeared in 1.7.5. + + *) Bugfix: "writev() failed (4: Interrupted system call)" errors might + appear in logs when using CephFS and the "timer_resolution" directive + on Linux. + + *) Bugfix: in invalid configurations handling. + Thanks to Markus Linnala. + + *) Bugfix: a segmentation fault occurred in a worker process if the + "sub_filter" directive was used at http level; the bug had appeared + in 1.9.4. + + Changes with nginx 1.9.4 18 Aug 2015 *) Change: the "proxy_downstream_buffer" and "proxy_upstream_buffer" diff --git a/CHANGES.ru b/CHANGES.ru index 09a0fe7..b95c33d 100644 --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,35 @@ +Изменения в nginx 1.9.5 22.09.2015 + + *) Добавление: модуль ngx_http_v2_module (заменяет модуль + ngx_http_spdy_module). + Спасибо Dropbox и Automattic за спонсирование разработки. + + *) Изменение: теперь по умолчанию директива output_buffers использует + два буфера. + + *) Изменение: теперь nginx ограничивает максимальную вложенность + подзапросов, а не количество одновременных подзапросов. + + *) Изменение: теперь при возврате ответов из кэша nginx проверяет ключ + полностью. + Спасибо Геннадию Махомеду и Сергею Брестеру. + + *) Исправление: при использовании кэша в логах могли появляться + сообщения "header already sent"; ошибка появилась в 1.7.5. + + *) Исправление: при использовании CephFS и директивы timer_resolution на + Linux в логах могли появляться сообщения "writev() failed (4: + Interrupted system call)". + + *) Исправление: в обработке ошибок конфигурации. + Спасибо Markus Linnala. + + *) Исправление: при использовании директивы sub_filter на уровне http в + рабочем процессе происходил segmentation fault; ошибка появилась в + 1.9.4. + + Изменения в nginx 1.9.4 18.08.2015 *) Изменение: директивы proxy_downstream_buffer и proxy_upstream_buffer diff --git a/auto/make b/auto/make index 78d0422..dca011c 100644 --- a/auto/make +++ b/auto/make @@ -7,7 +7,7 @@ echo "creating $NGX_MAKEFILE" mkdir -p $NGX_OBJS/src/core $NGX_OBJS/src/event $NGX_OBJS/src/event/modules \ $NGX_OBJS/src/os/unix $NGX_OBJS/src/os/win32 \ - $NGX_OBJS/src/http $NGX_OBJS/src/http/modules \ + $NGX_OBJS/src/http $NGX_OBJS/src/http/v2 $NGX_OBJS/src/http/modules \ $NGX_OBJS/src/http/modules/perl \ $NGX_OBJS/src/mail \ $NGX_OBJS/src/stream \ diff --git a/auto/modules b/auto/modules index 60a060d..5c734e1 100644 --- a/auto/modules +++ b/auto/modules @@ -94,7 +94,7 @@ fi # ngx_http_write_filter # ngx_http_header_filter # ngx_http_chunked_filter -# ngx_http_spdy_filter +# ngx_http_v2_filter # ngx_http_range_header_filter # ngx_http_gzip_filter # ngx_http_postpone_filter @@ -115,8 +115,8 @@ HTTP_FILTER_MODULES="$HTTP_WRITE_FILTER_MODULE \ $HTTP_HEADER_FILTER_MODULE \ $HTTP_CHUNKED_FILTER_MODULE" -if [ $HTTP_SPDY = YES ]; then - HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_SPDY_FILTER_MODULE" +if [ $HTTP_V2 = YES ]; then + HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_V2_FILTER_MODULE" fi HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_RANGE_HEADER_FILTER_MODULE" @@ -180,12 +180,12 @@ if [ $HTTP_USERID = YES ]; then fi -if [ $HTTP_SPDY = YES ]; then - have=NGX_HTTP_SPDY . auto/have - USE_ZLIB=YES - HTTP_MODULES="$HTTP_MODULES $HTTP_SPDY_MODULE" - HTTP_DEPS="$HTTP_DEPS $HTTP_SPDY_DEPS" - HTTP_SRCS="$HTTP_SRCS $HTTP_SPDY_SRCS" +if [ $HTTP_V2 = YES ]; then + have=NGX_HTTP_V2 . auto/have + HTTP_MODULES="$HTTP_MODULES $HTTP_V2_MODULE" + HTTP_INCS="$HTTP_INCS $HTTP_V2_INCS" + HTTP_DEPS="$HTTP_DEPS $HTTP_V2_DEPS" + HTTP_SRCS="$HTTP_SRCS $HTTP_V2_SRCS" fi HTTP_MODULES="$HTTP_MODULES $HTTP_STATIC_MODULE" diff --git a/auto/options b/auto/options index e70d1a0..efc8943 100644 --- a/auto/options +++ b/auto/options @@ -58,7 +58,7 @@ HTTP_CACHE=YES HTTP_CHARSET=YES HTTP_GZIP=YES HTTP_SSL=NO -HTTP_SPDY=NO +HTTP_V2=NO HTTP_SSI=YES HTTP_POSTPONE=NO HTTP_REALIP=NO @@ -210,7 +210,7 @@ do --http-scgi-temp-path=*) NGX_HTTP_SCGI_TEMP_PATH="$value" ;; --with-http_ssl_module) HTTP_SSL=YES ;; - --with-http_spdy_module) HTTP_SPDY=YES ;; + --with-http_v2_module) HTTP_V2=YES ;; --with-http_realip_module) HTTP_REALIP=YES ;; --with-http_addition_module) HTTP_ADDITION=YES ;; --with-http_xslt_module) HTTP_XSLT=YES ;; @@ -378,7 +378,7 @@ cat << END --with-ipv6 enable IPv6 support --with-http_ssl_module enable ngx_http_ssl_module - --with-http_spdy_module enable ngx_http_spdy_module + --with-http_v2_module enable ngx_http_v2_module --with-http_realip_module enable ngx_http_realip_module --with-http_addition_module enable ngx_http_addition_module --with-http_xslt_module enable ngx_http_xslt_module diff --git a/auto/sources b/auto/sources index 3d89e2d..2abbc60 100644 --- a/auto/sources +++ b/auto/sources @@ -317,13 +317,17 @@ HTTP_POSTPONE_FILTER_SRCS=src/http/ngx_http_postpone_filter_module.c HTTP_FILE_CACHE_SRCS=src/http/ngx_http_file_cache.c -HTTP_SPDY_MODULE=ngx_http_spdy_module -HTTP_SPDY_FILTER_MODULE=ngx_http_spdy_filter_module -HTTP_SPDY_DEPS="src/http/ngx_http_spdy.h \ - src/http/ngx_http_spdy_module.h" -HTTP_SPDY_SRCS="src/http/ngx_http_spdy.c \ - src/http/ngx_http_spdy_module.c \ - src/http/ngx_http_spdy_filter_module.c" +HTTP_V2_MODULE=ngx_http_v2_module +HTTP_V2_FILTER_MODULE=ngx_http_v2_filter_module +HTTP_V2_INCS="src/http/v2" +HTTP_V2_DEPS="src/http/v2/ngx_http_v2.h \ + src/http/v2/ngx_http_v2_module.h" +HTTP_V2_SRCS="src/http/v2/ngx_http_v2.c \ + src/http/v2/ngx_http_v2_table.c \ + src/http/v2/ngx_http_v2_huff_decode.c \ + src/http/v2/ngx_http_v2_huff_encode.c \ + src/http/v2/ngx_http_v2_module.c \ + src/http/v2/ngx_http_v2_filter_module.c" HTTP_CHARSET_FILTER_MODULE=ngx_http_charset_filter_module diff --git a/src/core/nginx.h b/src/core/nginx.h index a655f30..34a6a80 100644 --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1009004 -#define NGINX_VERSION "1.9.4" +#define nginx_version 1009005 +#define NGINX_VERSION "1.9.5" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD diff --git a/src/core/ngx_connection.h b/src/core/ngx_connection.h index c3aca7f..977f028 100644 --- a/src/core/ngx_connection.h +++ b/src/core/ngx_connection.h @@ -118,7 +118,7 @@ typedef enum { #define NGX_LOWLEVEL_BUFFERED 0x0f #define NGX_SSL_BUFFERED 0x01 -#define NGX_SPDY_BUFFERED 0x02 +#define NGX_HTTP_V2_BUFFERED 0x02 struct ngx_connection_s { diff --git a/src/core/ngx_hash.c b/src/core/ngx_hash.c index 1a5d0be..151e643 100644 --- a/src/core/ngx_hash.c +++ b/src/core/ngx_hash.c @@ -743,6 +743,10 @@ ngx_hash_add_key(ngx_hash_keys_arrays_t *ha, ngx_str_t *key, void *value, if (key->data[i] == '.' && key->data[i + 1] == '.') { return NGX_DECLINED; } + + if (key->data[i] == '\0') { + return NGX_DECLINED; + } } if (key->len > 1 && key->data[0] == '.') { diff --git a/src/http/modules/ngx_http_rewrite_module.c b/src/http/modules/ngx_http_rewrite_module.c index f241196..754512f 100644 --- a/src/http/modules/ngx_http_rewrite_module.c +++ b/src/http/modules/ngx_http_rewrite_module.c @@ -612,7 +612,7 @@ ngx_http_rewrite_if(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) save = *cf; cf->ctx = ctx; - if (pclcf->name.len == 0) { + if (cf->cmd_type == NGX_HTTP_SRV_CONF) { if_code->loc_conf = NULL; cf->cmd_type = NGX_HTTP_SIF_CONF; diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c index d6a1794..7b051ea 100644 --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -326,10 +326,10 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out, #if (NGX_DEBUG) unsigned int i; #endif -#if (NGX_HTTP_SPDY) +#if (NGX_HTTP_V2) ngx_http_connection_t *hc; #endif -#if (NGX_HTTP_SPDY || NGX_DEBUG) +#if (NGX_HTTP_V2 || NGX_DEBUG) ngx_connection_t *c; c = ngx_ssl_get_connection(ssl_conn); @@ -342,12 +342,13 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out, } #endif -#if (NGX_HTTP_SPDY) +#if (NGX_HTTP_V2) hc = c->data; - if (hc->addr_conf->spdy) { - srv = (unsigned char *) NGX_SPDY_NPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE; - srvlen = sizeof(NGX_SPDY_NPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE) - 1; + if (hc->addr_conf->http2) { + srv = + (unsigned char *) NGX_HTTP_V2_ALPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE; + srvlen = sizeof(NGX_HTTP_V2_ALPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE) - 1; } else #endif @@ -378,22 +379,23 @@ static int ngx_http_ssl_npn_advertised(ngx_ssl_conn_t *ssl_conn, const unsigned char **out, unsigned int *outlen, void *arg) { -#if (NGX_HTTP_SPDY || NGX_DEBUG) +#if (NGX_HTTP_V2 || NGX_DEBUG) ngx_connection_t *c; c = ngx_ssl_get_connection(ssl_conn); ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "SSL NPN advertised"); #endif -#if (NGX_HTTP_SPDY) +#if (NGX_HTTP_V2) { ngx_http_connection_t *hc; hc = c->data; - if (hc->addr_conf->spdy) { - *out = (unsigned char *) NGX_SPDY_NPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE; - *outlen = sizeof(NGX_SPDY_NPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE) - 1; + if (hc->addr_conf->http2) { + *out = + (unsigned char *) NGX_HTTP_V2_NPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE; + *outlen = sizeof(NGX_HTTP_V2_NPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE) - 1; return SSL_TLSEXT_ERR_OK; } diff --git a/src/http/modules/ngx_http_sub_filter_module.c b/src/http/modules/ngx_http_sub_filter_module.c index 0a4ff6d..8ba75ed 100644 --- a/src/http/modules/ngx_http_sub_filter_module.c +++ b/src/http/modules/ngx_http_sub_filter_module.c @@ -853,8 +853,9 @@ ngx_http_sub_merge_conf(ngx_conf_t *cf, void *parent, void *child) conf->pairs = prev->pairs; conf->matches = prev->matches; conf->tables = prev->tables; + } - } else if (conf->dynamic == 0){ + if (conf->pairs && conf->dynamic == 0 && conf->tables == NULL) { pairs = conf->pairs->elts; n = conf->pairs->nelts; diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c index 6b0a48f..d09e3f0 100644 --- a/src/http/ngx_http.c +++ b/src/http/ngx_http.c @@ -1233,8 +1233,8 @@ ngx_http_add_addresses(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, #if (NGX_HTTP_SSL) ngx_uint_t ssl; #endif -#if (NGX_HTTP_SPDY) - ngx_uint_t spdy; +#if (NGX_HTTP_V2) + ngx_uint_t http2; #endif /* @@ -1290,8 +1290,8 @@ ngx_http_add_addresses(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, #if (NGX_HTTP_SSL) ssl = lsopt->ssl || addr[i].opt.ssl; #endif -#if (NGX_HTTP_SPDY) - spdy = lsopt->spdy || addr[i].opt.spdy; +#if (NGX_HTTP_V2) + http2 = lsopt->http2 || addr[i].opt.http2; #endif if (lsopt->set) { @@ -1324,8 +1324,8 @@ ngx_http_add_addresses(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, #if (NGX_HTTP_SSL) addr[i].opt.ssl = ssl; #endif -#if (NGX_HTTP_SPDY) - addr[i].opt.spdy = spdy; +#if (NGX_HTTP_V2) + addr[i].opt.http2 = http2; #endif return NGX_OK; @@ -1357,14 +1357,17 @@ ngx_http_add_address(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, } } -#if (NGX_HTTP_SPDY && NGX_HTTP_SSL \ +#if (NGX_HTTP_V2 && NGX_HTTP_SSL \ && !defined TLSEXT_TYPE_application_layer_protocol_negotiation \ && !defined TLSEXT_TYPE_next_proto_neg) - if (lsopt->spdy && lsopt->ssl) { + + if (lsopt->http2 && lsopt->ssl) { ngx_conf_log_error(NGX_LOG_WARN, cf, 0, - "nginx was built without OpenSSL ALPN or NPN " - "support, SPDY is not enabled for %s", lsopt->addr); + "nginx was built with OpenSSL that lacks ALPN " + "and NPN support, HTTP/2 is not enabled for %s", + lsopt->addr); } + #endif addr = ngx_array_push(&port->addrs); @@ -1856,8 +1859,8 @@ ngx_http_add_addrs(ngx_conf_t *cf, ngx_http_port_t *hport, #if (NGX_HTTP_SSL) addrs[i].conf.ssl = addr[i].opt.ssl; #endif -#if (NGX_HTTP_SPDY) - addrs[i].conf.spdy = addr[i].opt.spdy; +#if (NGX_HTTP_V2) + addrs[i].conf.http2 = addr[i].opt.http2; #endif addrs[i].conf.proxy_protocol = addr[i].opt.proxy_protocol; @@ -1921,8 +1924,8 @@ ngx_http_add_addrs6(ngx_conf_t *cf, ngx_http_port_t *hport, #if (NGX_HTTP_SSL) addrs6[i].conf.ssl = addr[i].opt.ssl; #endif -#if (NGX_HTTP_SPDY) - addrs6[i].conf.spdy = addr[i].opt.spdy; +#if (NGX_HTTP_V2) + addrs6[i].conf.http2 = addr[i].opt.http2; #endif if (addr[i].hash.buckets == NULL diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h index 844f502..19cb680 100644 --- a/src/http/ngx_http.h +++ b/src/http/ngx_http.h @@ -20,8 +20,8 @@ typedef struct ngx_http_file_cache_s ngx_http_file_cache_t; typedef struct ngx_http_log_ctx_s ngx_http_log_ctx_t; typedef struct ngx_http_chunked_s ngx_http_chunked_t; -#if (NGX_HTTP_SPDY) -typedef struct ngx_http_spdy_stream_s ngx_http_spdy_stream_t; +#if (NGX_HTTP_V2) +typedef struct ngx_http_v2_stream_s ngx_http_v2_stream_t; #endif typedef ngx_int_t (*ngx_http_header_handler_pt)(ngx_http_request_t *r, @@ -38,8 +38,8 @@ typedef u_char *(*ngx_http_log_handler_pt)(ngx_http_request_t *r, #include #include -#if (NGX_HTTP_SPDY) -#include +#if (NGX_HTTP_V2) +#include #endif #if (NGX_HTTP_CACHE) #include diff --git a/src/http/ngx_http_copy_filter_module.c b/src/http/ngx_http_copy_filter_module.c index 0f908ad..c6d03ee 100644 --- a/src/http/ngx_http_copy_filter_module.c +++ b/src/http/ngx_http_copy_filter_module.c @@ -327,7 +327,7 @@ ngx_http_copy_filter_merge_conf(ngx_conf_t *cf, void *parent, void *child) ngx_http_copy_filter_conf_t *prev = parent; ngx_http_copy_filter_conf_t *conf = child; - ngx_conf_merge_bufs_value(conf->bufs, prev->bufs, 1, 32768); + ngx_conf_merge_bufs_value(conf->bufs, prev->bufs, 2, 32768); return NULL; } diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index 22400ca..36f00f6 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -2132,13 +2132,6 @@ ngx_http_gzip_ok(ngx_http_request_t *r) return NGX_DECLINED; } -#if (NGX_HTTP_SPDY) - if (r->spdy_stream) { - r->gzip_ok = 1; - return NGX_OK; - } -#endif - ae = r->headers_in.accept_encoding; if (ae == NULL) { return NGX_DECLINED; @@ -2427,12 +2420,19 @@ ngx_http_subrequest(ngx_http_request_t *r, ngx_http_core_srv_conf_t *cscf; ngx_http_postponed_request_t *pr, *p; - r->main->subrequests--; - - if (r->main->subrequests == 0) { + if (r->subrequests == 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "subrequests cycle while processing \"%V\"", uri); - r->main->subrequests = 1; + return NGX_ERROR; + } + + /* + * 1000 is reserved for other purposes. + */ + if (r->main->count >= 65535 - 1000) { + ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0, + "request reference counter overflow " + "while processing \"%V\"", uri); return NGX_ERROR; } @@ -2473,8 +2473,8 @@ ngx_http_subrequest(ngx_http_request_t *r, sr->request_body = r->request_body; -#if (NGX_HTTP_SPDY) - sr->spdy_stream = r->spdy_stream; +#if (NGX_HTTP_V2) + sr->stream = r->stream; #endif sr->method = NGX_HTTP_GET; @@ -2537,6 +2537,7 @@ ngx_http_subrequest(ngx_http_request_t *r, sr->main_filter_need_in_memory = r->main_filter_need_in_memory; sr->uri_changes = NGX_HTTP_MAX_URI_CHANGES + 1; + sr->subrequests = r->subrequests - 1; tp = ngx_timeofday(); sr->start_sec = tp->sec; @@ -3188,7 +3189,7 @@ ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) pclcf = pctx->loc_conf[ngx_http_core_module.ctx_index]; - if (pclcf->name.len) { + if (cf->cmd_type == NGX_HTTP_LOC_CONF) { /* nested location */ @@ -4195,18 +4196,26 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) #endif } - if (ngx_strcmp(value[n].data, "spdy") == 0) { -#if (NGX_HTTP_SPDY) - lsopt.spdy = 1; + if (ngx_strcmp(value[n].data, "http2") == 0) { +#if (NGX_HTTP_V2) + lsopt.http2 = 1; continue; #else ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "the \"spdy\" parameter requires " - "ngx_http_spdy_module"); + "the \"http2\" parameter requires " + "ngx_http_v2_module"); return NGX_CONF_ERROR; #endif } + if (ngx_strcmp(value[n].data, "spdy") == 0) { + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, + "invalid parameter \"spdy\": " + "ngx_http_spdy_module was superseded " + "by ngx_http_v2_module"); + continue; + } + if (ngx_strncmp(value[n].data, "so_keepalive=", 13) == 0) { if (ngx_strcmp(&value[n].data[13], "on") == 0) { diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h index e6be5ac..7dec9e1 100644 --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -79,8 +79,8 @@ typedef struct { #if (NGX_HTTP_SSL) unsigned ssl:1; #endif -#if (NGX_HTTP_SPDY) - unsigned spdy:1; +#if (NGX_HTTP_V2) + unsigned http2:1; #endif #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) unsigned ipv6only:1; @@ -248,8 +248,8 @@ struct ngx_http_addr_conf_s { #if (NGX_HTTP_SSL) unsigned ssl:1; #endif -#if (NGX_HTTP_SPDY) - unsigned spdy:1; +#if (NGX_HTTP_V2) + unsigned http2:1; #endif unsigned proxy_protocol:1; }; diff --git a/src/http/ngx_http_file_cache.c b/src/http/ngx_http_file_cache.c index fc14761..6633918 100644 --- a/src/http/ngx_http_file_cache.c +++ b/src/http/ngx_http_file_cache.c @@ -521,9 +521,12 @@ wakeup: static ngx_int_t ngx_http_file_cache_read(ngx_http_request_t *r, ngx_http_cache_t *c) { + u_char *p; time_t now; ssize_t n; + ngx_str_t *key; ngx_int_t rc; + ngx_uint_t i; ngx_http_file_cache_t *cache; ngx_http_file_cache_header_t *h; @@ -547,12 +550,27 @@ ngx_http_file_cache_read(ngx_http_request_t *r, ngx_http_cache_t *c) return NGX_DECLINED; } - if (h->crc32 != c->crc32) { + if (h->crc32 != c->crc32 || h->header_start != c->header_start) { ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0, "cache file \"%s\" has md5 collision", c->file.name.data); return NGX_DECLINED; } + p = c->buf->pos + sizeof(ngx_http_file_cache_header_t) + + sizeof(ngx_http_file_cache_key); + + key = c->keys.elts; + for (i = 0; i < c->keys.nelts; i++) { + if (ngx_memcmp(p, key[i].data, key[i].len) != 0) { + ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0, + "cache file \"%s\" has md5 collision", + c->file.name.data); + return NGX_DECLINED; + } + + p += key[i].len; + } + if ((size_t) h->body_start > c->body_start) { ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0, "cache file \"%s\" has too long header", @@ -583,7 +601,6 @@ ngx_http_file_cache_read(ngx_http_request_t *r, ngx_http_cache_t *c) c->last_modified = h->last_modified; c->date = h->date; c->valid_msec = h->valid_msec; - c->header_start = h->header_start; c->body_start = h->body_start; c->etag.len = h->etag_len; c->etag.data = h->etag; diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c index cd5f302..9da972e 100644 --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -312,9 +312,9 @@ ngx_http_init_connection(ngx_connection_t *c) rev->handler = ngx_http_wait_request_handler; c->write->handler = ngx_http_empty_handler; -#if (NGX_HTTP_SPDY) - if (hc->addr_conf->spdy) { - rev->handler = ngx_http_spdy_init; +#if (NGX_HTTP_V2) + if (hc->addr_conf->http2) { + rev->handler = ngx_http_v2_init; } #endif @@ -764,13 +764,12 @@ ngx_http_ssl_handshake_handler(ngx_connection_t *c) c->ssl->no_wait_shutdown = 1; -#if (NGX_HTTP_SPDY \ +#if (NGX_HTTP_V2 \ && (defined TLSEXT_TYPE_application_layer_protocol_negotiation \ || defined TLSEXT_TYPE_next_proto_neg)) { - unsigned int len; - const unsigned char *data; - static const ngx_str_t spdy = ngx_string(NGX_SPDY_NPN_NEGOTIATED); + unsigned int len; + const unsigned char *data; #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation SSL_get0_alpn_selected(c->ssl->connection, &data, &len); @@ -785,8 +784,8 @@ ngx_http_ssl_handshake_handler(ngx_connection_t *c) SSL_get0_next_proto_negotiated(c->ssl->connection, &data, &len); #endif - if (len == spdy.len && ngx_strncmp(data, spdy.data, spdy.len) == 0) { - ngx_http_spdy_init(c->read); + if (len == 2 && data[0] == 'h' && data[1] == '2') { + ngx_http_v2_init(c->read); return; } } @@ -2338,7 +2337,6 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc) if (r == c->data) { r->main->count--; - r->main->subrequests++; if (!r->logged) { @@ -2500,8 +2498,8 @@ ngx_http_finalize_connection(ngx_http_request_t *r) { ngx_http_core_loc_conf_t *clcf; -#if (NGX_HTTP_SPDY) - if (r->spdy_stream) { +#if (NGX_HTTP_V2) + if (r->stream) { ngx_http_close_request(r, 0); return; } @@ -2566,8 +2564,8 @@ ngx_http_set_write_handler(ngx_http_request_t *r) ngx_http_test_reading; r->write_event_handler = ngx_http_writer; -#if (NGX_HTTP_SPDY) - if (r->spdy_stream) { +#if (NGX_HTTP_V2) + if (r->stream) { return NGX_OK; } #endif @@ -2657,8 +2655,8 @@ ngx_http_writer(ngx_http_request_t *r) if (r->buffered || r->postponed || (r == r->main && c->buffered)) { -#if (NGX_HTTP_SPDY) - if (r->spdy_stream) { +#if (NGX_HTTP_V2) + if (r->stream) { return; } #endif @@ -2725,9 +2723,9 @@ ngx_http_test_reading(ngx_http_request_t *r) ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http test reading"); -#if (NGX_HTTP_SPDY) +#if (NGX_HTTP_V2) - if (r->spdy_stream) { + if (r->stream) { if (c->error) { err = 0; goto closed; @@ -3400,9 +3398,9 @@ ngx_http_close_request(ngx_http_request_t *r, ngx_int_t rc) return; } -#if (NGX_HTTP_SPDY) - if (r->spdy_stream) { - ngx_http_spdy_close_stream(r->spdy_stream, rc); +#if (NGX_HTTP_V2) + if (r->stream) { + ngx_http_v2_close_stream(r->stream, rc); return; } #endif diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h index 3954de3..967032a 100644 --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -10,7 +10,7 @@ #define NGX_HTTP_MAX_URI_CHANGES 10 -#define NGX_HTTP_MAX_SUBREQUESTS 200 +#define NGX_HTTP_MAX_SUBREQUESTS 50 /* must be 2^n */ #define NGX_HTTP_LC_HEADER_LEN 32 @@ -23,6 +23,7 @@ #define NGX_HTTP_VERSION_9 9 #define NGX_HTTP_VERSION_10 1000 #define NGX_HTTP_VERSION_11 1001 +#define NGX_HTTP_VERSION_20 2000 #define NGX_HTTP_UNKNOWN 0x0001 #define NGX_HTTP_GET 0x0002 @@ -431,16 +432,16 @@ struct ngx_http_request_s { ngx_uint_t err_status; ngx_http_connection_t *http_connection; -#if (NGX_HTTP_SPDY) - ngx_http_spdy_stream_t *spdy_stream; +#if (NGX_HTTP_V2) + ngx_http_v2_stream_t *stream; #endif ngx_http_log_handler_pt log_handler; ngx_http_cleanup_t *cleanup; + unsigned count:16; unsigned subrequests:8; - unsigned count:8; unsigned blocked:8; unsigned aio:1; diff --git a/src/http/ngx_http_request_body.c b/src/http/ngx_http_request_body.c index 9c16984..77e92e3 100644 --- a/src/http/ngx_http_request_body.c +++ b/src/http/ngx_http_request_body.c @@ -40,10 +40,10 @@ ngx_http_read_client_request_body(ngx_http_request_t *r, r->main->count++; -#if (NGX_HTTP_SPDY) - if (r->spdy_stream && r == r->main) { +#if (NGX_HTTP_V2) + if (r->stream && r == r->main) { r->request_body_no_buffering = 0; - rc = ngx_http_spdy_read_request_body(r, post_handler); + rc = ngx_http_v2_read_request_body(r, post_handler); goto done; } #endif @@ -570,9 +570,9 @@ ngx_http_discard_request_body(ngx_http_request_t *r) ngx_int_t rc; ngx_event_t *rev; -#if (NGX_HTTP_SPDY) - if (r->spdy_stream && r == r->main) { - r->spdy_stream->skip_data = NGX_SPDY_DATA_DISCARD; +#if (NGX_HTTP_V2) + if (r->stream && r == r->main) { + r->stream->skip_data = NGX_HTTP_V2_DATA_DISCARD; return NGX_OK; } #endif diff --git a/src/http/ngx_http_spdy.c b/src/http/ngx_http_spdy.c deleted file mode 100644 index 21c5217..0000000 --- a/src/http/ngx_http_spdy.c +++ /dev/null @@ -1,3701 +0,0 @@ - -/* - * Copyright (C) Nginx, Inc. - * Copyright (C) Valentin V. Bartenev - */ - - -#include -#include -#include -#include - -#include - - -#if (NGX_HAVE_LITTLE_ENDIAN && NGX_HAVE_NONALIGNED) - -#define ngx_str5cmp(m, c0, c1, c2, c3, c4) \ - *(uint32_t *) m == (c3 << 24 | c2 << 16 | c1 << 8 | c0) \ - && m[4] == c4 - -#else - -#define ngx_str5cmp(m, c0, c1, c2, c3, c4) \ - m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3 && m[4] == c4 - -#endif - - -#if (NGX_HAVE_NONALIGNED) - -#define ngx_spdy_frame_parse_uint16(p) ntohs(*(uint16_t *) (p)) -#define ngx_spdy_frame_parse_uint32(p) ntohl(*(uint32_t *) (p)) - -#else - -#define ngx_spdy_frame_parse_uint16(p) ((p)[0] << 8 | (p)[1]) -#define ngx_spdy_frame_parse_uint32(p) \ - ((p)[0] << 24 | (p)[1] << 16 | (p)[2] << 8 | (p)[3]) - -#endif - -#define ngx_spdy_frame_parse_sid(p) \ - (ngx_spdy_frame_parse_uint32(p) & 0x7fffffff) -#define ngx_spdy_frame_parse_delta(p) \ - (ngx_spdy_frame_parse_uint32(p) & 0x7fffffff) - - -#define ngx_spdy_ctl_frame_check(h) \ - (((h) & 0xffff0000) == ngx_spdy_ctl_frame_head(0)) -#define ngx_spdy_data_frame_check(h) \ - (!((h) & (uint32_t) NGX_SPDY_CTL_BIT << 31)) - -#define ngx_spdy_ctl_frame_type(h) ((h) & 0x0000ffff) -#define ngx_spdy_frame_flags(p) ((p) >> 24) -#define ngx_spdy_frame_length(p) ((p) & 0x00ffffff) -#define ngx_spdy_frame_id(p) ((p) & 0x00ffffff) - - -#define NGX_SPDY_SKIP_HEADERS_BUFFER_SIZE 4096 -#define NGX_SPDY_CTL_FRAME_BUFFER_SIZE 16 - -#define NGX_SPDY_PROTOCOL_ERROR 1 -#define NGX_SPDY_INVALID_STREAM 2 -#define NGX_SPDY_REFUSED_STREAM 3 -#define NGX_SPDY_UNSUPPORTED_VERSION 4 -#define NGX_SPDY_CANCEL 5 -#define NGX_SPDY_INTERNAL_ERROR 6 -#define NGX_SPDY_FLOW_CONTROL_ERROR 7 -#define NGX_SPDY_STREAM_IN_USE 8 -#define NGX_SPDY_STREAM_ALREADY_CLOSED 9 -/* deprecated 10 */ -#define NGX_SPDY_FRAME_TOO_LARGE 11 - -#define NGX_SPDY_SETTINGS_MAX_STREAMS 4 -#define NGX_SPDY_SETTINGS_INIT_WINDOW 7 - -#define NGX_SPDY_SETTINGS_FLAG_PERSIST 0x01 -#define NGX_SPDY_SETTINGS_FLAG_PERSISTED 0x02 - -#define NGX_SPDY_MAX_WINDOW NGX_MAX_INT32_VALUE -#define NGX_SPDY_CONNECTION_WINDOW 65536 -#define NGX_SPDY_INIT_STREAM_WINDOW 65536 -#define NGX_SPDY_STREAM_WINDOW NGX_SPDY_MAX_WINDOW - -typedef struct { - ngx_uint_t hash; - u_char len; - u_char header[7]; - ngx_int_t (*handler)(ngx_http_request_t *r); -} ngx_http_spdy_request_header_t; - - -static void ngx_http_spdy_read_handler(ngx_event_t *rev); -static void ngx_http_spdy_write_handler(ngx_event_t *wev); -static void ngx_http_spdy_handle_connection(ngx_http_spdy_connection_t *sc); - -static u_char *ngx_http_spdy_proxy_protocol(ngx_http_spdy_connection_t *sc, - u_char *pos, u_char *end); -static u_char *ngx_http_spdy_state_head(ngx_http_spdy_connection_t *sc, - u_char *pos, u_char *end); -static u_char *ngx_http_spdy_state_syn_stream(ngx_http_spdy_connection_t *sc, - u_char *pos, u_char *end); -static u_char *ngx_http_spdy_state_headers(ngx_http_spdy_connection_t *sc, - u_char *pos, u_char *end); -static u_char *ngx_http_spdy_state_headers_skip(ngx_http_spdy_connection_t *sc, - u_char *pos, u_char *end); -static u_char *ngx_http_spdy_state_headers_error(ngx_http_spdy_connection_t *sc, - u_char *pos, u_char *end); -static u_char *ngx_http_spdy_state_window_update(ngx_http_spdy_connection_t *sc, - u_char *pos, u_char *end); -static u_char *ngx_http_spdy_state_data(ngx_http_spdy_connection_t *sc, - u_char *pos, u_char *end); -static u_char *ngx_http_spdy_state_read_data(ngx_http_spdy_connection_t *sc, - u_char *pos, u_char *end); -static u_char *ngx_http_spdy_state_rst_stream(ngx_http_spdy_connection_t *sc, - u_char *pos, u_char *end); -static u_char *ngx_http_spdy_state_ping(ngx_http_spdy_connection_t *sc, - u_char *pos, u_char *end); -static u_char *ngx_http_spdy_state_skip(ngx_http_spdy_connection_t *sc, - u_char *pos, u_char *end); -static u_char *ngx_http_spdy_state_settings(ngx_http_spdy_connection_t *sc, - u_char *pos, u_char *end); -static u_char *ngx_http_spdy_state_complete(ngx_http_spdy_connection_t *sc, - u_char *pos, u_char *end); -static u_char *ngx_http_spdy_state_save(ngx_http_spdy_connection_t *sc, - u_char *pos, u_char *end, ngx_http_spdy_handler_pt handler); - -static u_char *ngx_http_spdy_state_inflate_error( - ngx_http_spdy_connection_t *sc, int rc); -static u_char *ngx_http_spdy_state_protocol_error( - ngx_http_spdy_connection_t *sc); -static u_char *ngx_http_spdy_state_internal_error( - ngx_http_spdy_connection_t *sc); - -static ngx_int_t ngx_http_spdy_send_window_update( - ngx_http_spdy_connection_t *sc, ngx_uint_t sid, ngx_uint_t delta); -static ngx_int_t ngx_http_spdy_send_rst_stream(ngx_http_spdy_connection_t *sc, - ngx_uint_t sid, ngx_uint_t status, ngx_uint_t priority); -static ngx_int_t ngx_http_spdy_send_settings(ngx_http_spdy_connection_t *sc); -static ngx_int_t ngx_http_spdy_settings_frame_handler( - ngx_http_spdy_connection_t *sc, ngx_http_spdy_out_frame_t *frame); -static ngx_http_spdy_out_frame_t *ngx_http_spdy_get_ctl_frame( - ngx_http_spdy_connection_t *sc, size_t size, ngx_uint_t priority); -static ngx_int_t ngx_http_spdy_ctl_frame_handler( - ngx_http_spdy_connection_t *sc, ngx_http_spdy_out_frame_t *frame); - -static ngx_http_spdy_stream_t *ngx_http_spdy_create_stream( - ngx_http_spdy_connection_t *sc, ngx_uint_t id, ngx_uint_t priority); -static ngx_http_spdy_stream_t *ngx_http_spdy_get_stream_by_id( - ngx_http_spdy_connection_t *sc, ngx_uint_t sid); -#define ngx_http_spdy_streams_index_size(sscf) (sscf->streams_index_mask + 1) -#define ngx_http_spdy_stream_index(sscf, sid) \ - ((sid >> 1) & sscf->streams_index_mask) - -static ngx_int_t ngx_http_spdy_parse_header(ngx_http_request_t *r); -static ngx_int_t ngx_http_spdy_alloc_large_header_buffer(ngx_http_request_t *r); - -static ngx_int_t ngx_http_spdy_handle_request_header(ngx_http_request_t *r); -static ngx_int_t ngx_http_spdy_parse_method(ngx_http_request_t *r); -static ngx_int_t ngx_http_spdy_parse_scheme(ngx_http_request_t *r); -static ngx_int_t ngx_http_spdy_parse_host(ngx_http_request_t *r); -static ngx_int_t ngx_http_spdy_parse_path(ngx_http_request_t *r); -static ngx_int_t ngx_http_spdy_parse_version(ngx_http_request_t *r); - -static ngx_int_t ngx_http_spdy_construct_request_line(ngx_http_request_t *r); -static void ngx_http_spdy_run_request(ngx_http_request_t *r); -static ngx_int_t ngx_http_spdy_init_request_body(ngx_http_request_t *r); - -static ngx_int_t ngx_http_spdy_terminate_stream(ngx_http_spdy_connection_t *sc, - ngx_http_spdy_stream_t *stream, ngx_uint_t status); - -static void ngx_http_spdy_close_stream_handler(ngx_event_t *ev); - -static void ngx_http_spdy_handle_connection_handler(ngx_event_t *rev); -static void ngx_http_spdy_keepalive_handler(ngx_event_t *rev); -static void ngx_http_spdy_finalize_connection(ngx_http_spdy_connection_t *sc, - ngx_int_t rc); - -static ngx_int_t ngx_http_spdy_adjust_windows(ngx_http_spdy_connection_t *sc, - ssize_t delta); - -static void ngx_http_spdy_pool_cleanup(void *data); - -static void *ngx_http_spdy_zalloc(void *opaque, u_int items, u_int size); -static void ngx_http_spdy_zfree(void *opaque, void *address); - - -static const u_char ngx_http_spdy_dict[] = { - 0x00, 0x00, 0x00, 0x07, 0x6f, 0x70, 0x74, 0x69, /* - - - - o p t i */ - 0x6f, 0x6e, 0x73, 0x00, 0x00, 0x00, 0x04, 0x68, /* o n s - - - - h */ - 0x65, 0x61, 0x64, 0x00, 0x00, 0x00, 0x04, 0x70, /* e a d - - - - p */ - 0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x03, 0x70, /* o s t - - - - p */ - 0x75, 0x74, 0x00, 0x00, 0x00, 0x06, 0x64, 0x65, /* u t - - - - d e */ - 0x6c, 0x65, 0x74, 0x65, 0x00, 0x00, 0x00, 0x05, /* l e t e - - - - */ - 0x74, 0x72, 0x61, 0x63, 0x65, 0x00, 0x00, 0x00, /* t r a c e - - - */ - 0x06, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x00, /* - a c c e p t - */ - 0x00, 0x00, 0x0e, 0x61, 0x63, 0x63, 0x65, 0x70, /* - - - a c c e p */ - 0x74, 0x2d, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, /* t - c h a r s e */ - 0x74, 0x00, 0x00, 0x00, 0x0f, 0x61, 0x63, 0x63, /* t - - - - a c c */ - 0x65, 0x70, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, /* e p t - e n c o */ - 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x0f, /* d i n g - - - - */ - 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, 0x6c, /* a c c e p t - l */ - 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x00, /* a n g u a g e - */ - 0x00, 0x00, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x70, /* - - - a c c e p */ - 0x74, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, /* t - r a n g e s */ - 0x00, 0x00, 0x00, 0x03, 0x61, 0x67, 0x65, 0x00, /* - - - - a g e - */ - 0x00, 0x00, 0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x77, /* - - - a l l o w */ - 0x00, 0x00, 0x00, 0x0d, 0x61, 0x75, 0x74, 0x68, /* - - - - a u t h */ - 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, /* o r i z a t i o */ - 0x6e, 0x00, 0x00, 0x00, 0x0d, 0x63, 0x61, 0x63, /* n - - - - c a c */ - 0x68, 0x65, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, /* h e - c o n t r */ - 0x6f, 0x6c, 0x00, 0x00, 0x00, 0x0a, 0x63, 0x6f, /* o l - - - - c o */ - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, /* n n e c t i o n */ - 0x00, 0x00, 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, /* - - - - c o n t */ - 0x65, 0x6e, 0x74, 0x2d, 0x62, 0x61, 0x73, 0x65, /* e n t - b a s e */ - 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, 0x6e, 0x74, /* - - - - c o n t */ - 0x65, 0x6e, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, /* e n t - e n c o */ - 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, /* d i n g - - - - */ - 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, /* c o n t e n t - */ - 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, /* l a n g u a g e */ - 0x00, 0x00, 0x00, 0x0e, 0x63, 0x6f, 0x6e, 0x74, /* - - - - c o n t */ - 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x65, 0x6e, 0x67, /* e n t - l e n g */ - 0x74, 0x68, 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, /* t h - - - - c o */ - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x6f, /* n t e n t - l o */ - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, /* c a t i o n - - */ - 0x00, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, /* - - c o n t e n */ - 0x74, 0x2d, 0x6d, 0x64, 0x35, 0x00, 0x00, 0x00, /* t - m d 5 - - - */ - 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, /* - c o n t e n t */ - 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, /* - r a n g e - - */ - 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, /* - - c o n t e n */ - 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x00, 0x00, /* t - t y p e - - */ - 0x00, 0x04, 0x64, 0x61, 0x74, 0x65, 0x00, 0x00, /* - - d a t e - - */ - 0x00, 0x04, 0x65, 0x74, 0x61, 0x67, 0x00, 0x00, /* - - e t a g - - */ - 0x00, 0x06, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, /* - - e x p e c t */ - 0x00, 0x00, 0x00, 0x07, 0x65, 0x78, 0x70, 0x69, /* - - - - e x p i */ - 0x72, 0x65, 0x73, 0x00, 0x00, 0x00, 0x04, 0x66, /* r e s - - - - f */ - 0x72, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x04, 0x68, /* r o m - - - - h */ - 0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x08, 0x69, /* o s t - - - - i */ - 0x66, 0x2d, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, /* f - m a t c h - */ - 0x00, 0x00, 0x11, 0x69, 0x66, 0x2d, 0x6d, 0x6f, /* - - - i f - m o */ - 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2d, 0x73, /* d i f i e d - s */ - 0x69, 0x6e, 0x63, 0x65, 0x00, 0x00, 0x00, 0x0d, /* i n c e - - - - */ - 0x69, 0x66, 0x2d, 0x6e, 0x6f, 0x6e, 0x65, 0x2d, /* i f - n o n e - */ - 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, 0x00, 0x00, /* m a t c h - - - */ - 0x08, 0x69, 0x66, 0x2d, 0x72, 0x61, 0x6e, 0x67, /* - i f - r a n g */ - 0x65, 0x00, 0x00, 0x00, 0x13, 0x69, 0x66, 0x2d, /* e - - - - i f - */ - 0x75, 0x6e, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, /* u n m o d i f i */ - 0x65, 0x64, 0x2d, 0x73, 0x69, 0x6e, 0x63, 0x65, /* e d - s i n c e */ - 0x00, 0x00, 0x00, 0x0d, 0x6c, 0x61, 0x73, 0x74, /* - - - - l a s t */ - 0x2d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, /* - m o d i f i e */ - 0x64, 0x00, 0x00, 0x00, 0x08, 0x6c, 0x6f, 0x63, /* d - - - - l o c */ - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, /* a t i o n - - - */ - 0x0c, 0x6d, 0x61, 0x78, 0x2d, 0x66, 0x6f, 0x72, /* - m a x - f o r */ - 0x77, 0x61, 0x72, 0x64, 0x73, 0x00, 0x00, 0x00, /* w a r d s - - - */ - 0x06, 0x70, 0x72, 0x61, 0x67, 0x6d, 0x61, 0x00, /* - p r a g m a - */ - 0x00, 0x00, 0x12, 0x70, 0x72, 0x6f, 0x78, 0x79, /* - - - p r o x y */ - 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, /* - a u t h e n t */ - 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, /* i c a t e - - - */ - 0x13, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2d, 0x61, /* - p r o x y - a */ - 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, /* u t h o r i z a */ - 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x05, /* t i o n - - - - */ - 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, 0x00, /* r a n g e - - - */ - 0x07, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x72, /* - r e f e r e r */ - 0x00, 0x00, 0x00, 0x0b, 0x72, 0x65, 0x74, 0x72, /* - - - - r e t r */ - 0x79, 0x2d, 0x61, 0x66, 0x74, 0x65, 0x72, 0x00, /* y - a f t e r - */ - 0x00, 0x00, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, /* - - - s e r v e */ - 0x72, 0x00, 0x00, 0x00, 0x02, 0x74, 0x65, 0x00, /* r - - - - t e - */ - 0x00, 0x00, 0x07, 0x74, 0x72, 0x61, 0x69, 0x6c, /* - - - t r a i l */ - 0x65, 0x72, 0x00, 0x00, 0x00, 0x11, 0x74, 0x72, /* e r - - - - t r */ - 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x2d, 0x65, /* a n s f e r - e */ - 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x00, /* n c o d i n g - */ - 0x00, 0x00, 0x07, 0x75, 0x70, 0x67, 0x72, 0x61, /* - - - u p g r a */ - 0x64, 0x65, 0x00, 0x00, 0x00, 0x0a, 0x75, 0x73, /* d e - - - - u s */ - 0x65, 0x72, 0x2d, 0x61, 0x67, 0x65, 0x6e, 0x74, /* e r - a g e n t */ - 0x00, 0x00, 0x00, 0x04, 0x76, 0x61, 0x72, 0x79, /* - - - - v a r y */ - 0x00, 0x00, 0x00, 0x03, 0x76, 0x69, 0x61, 0x00, /* - - - - v i a - */ - 0x00, 0x00, 0x07, 0x77, 0x61, 0x72, 0x6e, 0x69, /* - - - w a r n i */ - 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, 0x77, 0x77, /* n g - - - - w w */ - 0x77, 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, /* w - a u t h e n */ - 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, /* t i c a t e - - */ - 0x00, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, /* - - m e t h o d */ - 0x00, 0x00, 0x00, 0x03, 0x67, 0x65, 0x74, 0x00, /* - - - - g e t - */ - 0x00, 0x00, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, /* - - - s t a t u */ - 0x73, 0x00, 0x00, 0x00, 0x06, 0x32, 0x30, 0x30, /* s - - - - 2 0 0 */ - 0x20, 0x4f, 0x4b, 0x00, 0x00, 0x00, 0x07, 0x76, /* - O K - - - - v */ - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x00, /* e r s i o n - - */ - 0x00, 0x08, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, /* - - H T T P - 1 */ - 0x2e, 0x31, 0x00, 0x00, 0x00, 0x03, 0x75, 0x72, /* - 1 - - - - u r */ - 0x6c, 0x00, 0x00, 0x00, 0x06, 0x70, 0x75, 0x62, /* l - - - - p u b */ - 0x6c, 0x69, 0x63, 0x00, 0x00, 0x00, 0x0a, 0x73, /* l i c - - - - s */ - 0x65, 0x74, 0x2d, 0x63, 0x6f, 0x6f, 0x6b, 0x69, /* e t - c o o k i */ - 0x65, 0x00, 0x00, 0x00, 0x0a, 0x6b, 0x65, 0x65, /* e - - - - k e e */ - 0x70, 0x2d, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x00, /* p - a l i v e - */ - 0x00, 0x00, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, /* - - - o r i g i */ - 0x6e, 0x31, 0x30, 0x30, 0x31, 0x30, 0x31, 0x32, /* n 1 0 0 1 0 1 2 */ - 0x30, 0x31, 0x32, 0x30, 0x32, 0x32, 0x30, 0x35, /* 0 1 2 0 2 2 0 5 */ - 0x32, 0x30, 0x36, 0x33, 0x30, 0x30, 0x33, 0x30, /* 2 0 6 3 0 0 3 0 */ - 0x32, 0x33, 0x30, 0x33, 0x33, 0x30, 0x34, 0x33, /* 2 3 0 3 3 0 4 3 */ - 0x30, 0x35, 0x33, 0x30, 0x36, 0x33, 0x30, 0x37, /* 0 5 3 0 6 3 0 7 */ - 0x34, 0x30, 0x32, 0x34, 0x30, 0x35, 0x34, 0x30, /* 4 0 2 4 0 5 4 0 */ - 0x36, 0x34, 0x30, 0x37, 0x34, 0x30, 0x38, 0x34, /* 6 4 0 7 4 0 8 4 */ - 0x30, 0x39, 0x34, 0x31, 0x30, 0x34, 0x31, 0x31, /* 0 9 4 1 0 4 1 1 */ - 0x34, 0x31, 0x32, 0x34, 0x31, 0x33, 0x34, 0x31, /* 4 1 2 4 1 3 4 1 */ - 0x34, 0x34, 0x31, 0x35, 0x34, 0x31, 0x36, 0x34, /* 4 4 1 5 4 1 6 4 */ - 0x31, 0x37, 0x35, 0x30, 0x32, 0x35, 0x30, 0x34, /* 1 7 5 0 2 5 0 4 */ - 0x35, 0x30, 0x35, 0x32, 0x30, 0x33, 0x20, 0x4e, /* 5 0 5 2 0 3 - N */ - 0x6f, 0x6e, 0x2d, 0x41, 0x75, 0x74, 0x68, 0x6f, /* o n - A u t h o */ - 0x72, 0x69, 0x74, 0x61, 0x74, 0x69, 0x76, 0x65, /* r i t a t i v e */ - 0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, /* - I n f o r m a */ - 0x74, 0x69, 0x6f, 0x6e, 0x32, 0x30, 0x34, 0x20, /* t i o n 2 0 4 - */ - 0x4e, 0x6f, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x65, /* N o - C o n t e */ - 0x6e, 0x74, 0x33, 0x30, 0x31, 0x20, 0x4d, 0x6f, /* n t 3 0 1 - M o */ - 0x76, 0x65, 0x64, 0x20, 0x50, 0x65, 0x72, 0x6d, /* v e d - P e r m */ - 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x34, /* a n e n t l y 4 */ - 0x30, 0x30, 0x20, 0x42, 0x61, 0x64, 0x20, 0x52, /* 0 0 - B a d - R */ - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x34, 0x30, /* e q u e s t 4 0 */ - 0x31, 0x20, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, /* 1 - U n a u t h */ - 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x34, 0x30, /* o r i z e d 4 0 */ - 0x33, 0x20, 0x46, 0x6f, 0x72, 0x62, 0x69, 0x64, /* 3 - F o r b i d */ - 0x64, 0x65, 0x6e, 0x34, 0x30, 0x34, 0x20, 0x4e, /* d e n 4 0 4 - N */ - 0x6f, 0x74, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, /* o t - F o u n d */ - 0x35, 0x30, 0x30, 0x20, 0x49, 0x6e, 0x74, 0x65, /* 5 0 0 - I n t e */ - 0x72, 0x6e, 0x61, 0x6c, 0x20, 0x53, 0x65, 0x72, /* r n a l - S e r */ - 0x76, 0x65, 0x72, 0x20, 0x45, 0x72, 0x72, 0x6f, /* v e r - E r r o */ - 0x72, 0x35, 0x30, 0x31, 0x20, 0x4e, 0x6f, 0x74, /* r 5 0 1 - N o t */ - 0x20, 0x49, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, /* - I m p l e m e */ - 0x6e, 0x74, 0x65, 0x64, 0x35, 0x30, 0x33, 0x20, /* n t e d 5 0 3 - */ - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, /* S e r v i c e - */ - 0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, /* U n a v a i l a */ - 0x62, 0x6c, 0x65, 0x4a, 0x61, 0x6e, 0x20, 0x46, /* b l e J a n - F */ - 0x65, 0x62, 0x20, 0x4d, 0x61, 0x72, 0x20, 0x41, /* e b - M a r - A */ - 0x70, 0x72, 0x20, 0x4d, 0x61, 0x79, 0x20, 0x4a, /* p r - M a y - J */ - 0x75, 0x6e, 0x20, 0x4a, 0x75, 0x6c, 0x20, 0x41, /* u n - J u l - A */ - 0x75, 0x67, 0x20, 0x53, 0x65, 0x70, 0x74, 0x20, /* u g - S e p t - */ - 0x4f, 0x63, 0x74, 0x20, 0x4e, 0x6f, 0x76, 0x20, /* O c t - N o v - */ - 0x44, 0x65, 0x63, 0x20, 0x30, 0x30, 0x3a, 0x30, /* D e c - 0 0 - 0 */ - 0x30, 0x3a, 0x30, 0x30, 0x20, 0x4d, 0x6f, 0x6e, /* 0 - 0 0 - M o n */ - 0x2c, 0x20, 0x54, 0x75, 0x65, 0x2c, 0x20, 0x57, /* - - T u e - - W */ - 0x65, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x75, 0x2c, /* e d - - T h u - */ - 0x20, 0x46, 0x72, 0x69, 0x2c, 0x20, 0x53, 0x61, /* - F r i - - S a */ - 0x74, 0x2c, 0x20, 0x53, 0x75, 0x6e, 0x2c, 0x20, /* t - - S u n - - */ - 0x47, 0x4d, 0x54, 0x63, 0x68, 0x75, 0x6e, 0x6b, /* G M T c h u n k */ - 0x65, 0x64, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, /* e d - t e x t - */ - 0x68, 0x74, 0x6d, 0x6c, 0x2c, 0x69, 0x6d, 0x61, /* h t m l - i m a */ - 0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67, 0x2c, 0x69, /* g e - p n g - i */ - 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x67, /* m a g e - j p g */ - 0x2c, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67, /* - i m a g e - g */ - 0x69, 0x66, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, /* i f - a p p l i */ - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, /* c a t i o n - x */ - 0x6d, 0x6c, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, /* m l - a p p l i */ - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, /* c a t i o n - x */ - 0x68, 0x74, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, /* h t m l - x m l */ - 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, /* - t e x t - p l */ - 0x61, 0x69, 0x6e, 0x2c, 0x74, 0x65, 0x78, 0x74, /* a i n - t e x t */ - 0x2f, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, /* - j a v a s c r */ - 0x69, 0x70, 0x74, 0x2c, 0x70, 0x75, 0x62, 0x6c, /* i p t - p u b l */ - 0x69, 0x63, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, /* i c p r i v a t */ - 0x65, 0x6d, 0x61, 0x78, 0x2d, 0x61, 0x67, 0x65, /* e m a x - a g e */ - 0x3d, 0x67, 0x7a, 0x69, 0x70, 0x2c, 0x64, 0x65, /* - g z i p - d e */ - 0x66, 0x6c, 0x61, 0x74, 0x65, 0x2c, 0x73, 0x64, /* f l a t e - s d */ - 0x63, 0x68, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, /* c h c h a r s e */ - 0x74, 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x63, /* t - u t f - 8 c */ - 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x69, /* h a r s e t - i */ - 0x73, 0x6f, 0x2d, 0x38, 0x38, 0x35, 0x39, 0x2d, /* s o - 8 8 5 9 - */ - 0x31, 0x2c, 0x75, 0x74, 0x66, 0x2d, 0x2c, 0x2a, /* 1 - u t f - - - */ - 0x2c, 0x65, 0x6e, 0x71, 0x3d, 0x30, 0x2e /* - e n q - 0 - */ -}; - - -static ngx_http_spdy_request_header_t ngx_http_spdy_request_headers[] = { - { 0, 6, "method", ngx_http_spdy_parse_method }, - { 0, 6, "scheme", ngx_http_spdy_parse_scheme }, - { 0, 4, "host", ngx_http_spdy_parse_host }, - { 0, 4, "path", ngx_http_spdy_parse_path }, - { 0, 7, "version", ngx_http_spdy_parse_version }, -}; - -#define NGX_SPDY_REQUEST_HEADERS \ - (sizeof(ngx_http_spdy_request_headers) \ - / sizeof(ngx_http_spdy_request_header_t)) - - -void -ngx_http_spdy_init(ngx_event_t *rev) -{ - int rc; - ngx_connection_t *c; - ngx_pool_cleanup_t *cln; - ngx_http_connection_t *hc; - ngx_http_spdy_srv_conf_t *sscf; - ngx_http_spdy_main_conf_t *smcf; - ngx_http_spdy_connection_t *sc; - - c = rev->data; - hc = c->data; - - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "init spdy request"); - - c->log->action = "processing SPDY"; - - smcf = ngx_http_get_module_main_conf(hc->conf_ctx, ngx_http_spdy_module); - - if (smcf->recv_buffer == NULL) { - smcf->recv_buffer = ngx_palloc(ngx_cycle->pool, smcf->recv_buffer_size); - if (smcf->recv_buffer == NULL) { - ngx_http_close_connection(c); - return; - } - } - - sc = ngx_pcalloc(c->pool, sizeof(ngx_http_spdy_connection_t)); - if (sc == NULL) { - ngx_http_close_connection(c); - return; - } - - sc->connection = c; - sc->http_connection = hc; - - sc->send_window = NGX_SPDY_CONNECTION_WINDOW; - sc->recv_window = NGX_SPDY_CONNECTION_WINDOW; - - sc->init_window = NGX_SPDY_INIT_STREAM_WINDOW; - - sc->handler = hc->proxy_protocol ? ngx_http_spdy_proxy_protocol - : ngx_http_spdy_state_head; - - sc->zstream_in.zalloc = ngx_http_spdy_zalloc; - sc->zstream_in.zfree = ngx_http_spdy_zfree; - sc->zstream_in.opaque = sc; - - rc = inflateInit(&sc->zstream_in); - if (rc != Z_OK) { - ngx_log_error(NGX_LOG_ALERT, c->log, 0, - "inflateInit() failed: %d", rc); - ngx_http_close_connection(c); - return; - } - - sc->zstream_out.zalloc = ngx_http_spdy_zalloc; - sc->zstream_out.zfree = ngx_http_spdy_zfree; - sc->zstream_out.opaque = sc; - - sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_spdy_module); - - rc = deflateInit2(&sc->zstream_out, (int) sscf->headers_comp, - Z_DEFLATED, 11, 4, Z_DEFAULT_STRATEGY); - - if (rc != Z_OK) { - ngx_log_error(NGX_LOG_ALERT, c->log, 0, - "deflateInit2() failed: %d", rc); - ngx_http_close_connection(c); - return; - } - - rc = deflateSetDictionary(&sc->zstream_out, ngx_http_spdy_dict, - sizeof(ngx_http_spdy_dict)); - if (rc != Z_OK) { - ngx_log_error(NGX_LOG_ALERT, c->log, 0, - "deflateSetDictionary() failed: %d", rc); - ngx_http_close_connection(c); - return; - } - - sc->pool = ngx_create_pool(sscf->pool_size, sc->connection->log); - if (sc->pool == NULL) { - ngx_http_close_connection(c); - return; - } - - cln = ngx_pool_cleanup_add(c->pool, sizeof(ngx_pool_cleanup_file_t)); - if (cln == NULL) { - ngx_http_close_connection(c); - return; - } - - cln->handler = ngx_http_spdy_pool_cleanup; - cln->data = sc; - - sc->streams_index = ngx_pcalloc(sc->pool, - ngx_http_spdy_streams_index_size(sscf) - * sizeof(ngx_http_spdy_stream_t *)); - if (sc->streams_index == NULL) { - ngx_http_close_connection(c); - return; - } - - if (ngx_http_spdy_send_settings(sc) == NGX_ERROR) { - ngx_http_close_connection(c); - return; - } - - if (ngx_http_spdy_send_window_update(sc, 0, NGX_SPDY_MAX_WINDOW - - sc->recv_window) - == NGX_ERROR) - { - ngx_http_close_connection(c); - return; - } - - sc->recv_window = NGX_SPDY_MAX_WINDOW; - - ngx_queue_init(&sc->waiting); - ngx_queue_init(&sc->posted); - - c->data = sc; - - rev->handler = ngx_http_spdy_read_handler; - c->write->handler = ngx_http_spdy_write_handler; - - ngx_http_spdy_read_handler(rev); -} - - -static void -ngx_http_spdy_read_handler(ngx_event_t *rev) -{ - u_char *p, *end; - size_t available; - ssize_t n; - ngx_connection_t *c; - ngx_http_spdy_main_conf_t *smcf; - ngx_http_spdy_connection_t *sc; - - c = rev->data; - sc = c->data; - - if (rev->timedout) { - ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); - ngx_http_spdy_finalize_connection(sc, NGX_HTTP_REQUEST_TIME_OUT); - return; - } - - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "spdy read handler"); - - sc->blocked = 1; - - smcf = ngx_http_get_module_main_conf(sc->http_connection->conf_ctx, - ngx_http_spdy_module); - - available = smcf->recv_buffer_size - 2 * NGX_SPDY_STATE_BUFFER_SIZE; - - do { - p = smcf->recv_buffer; - - ngx_memcpy(p, sc->buffer, NGX_SPDY_STATE_BUFFER_SIZE); - end = p + sc->buffer_used; - - n = c->recv(c, end, available); - - if (n == NGX_AGAIN) { - break; - } - - if (n == 0 && (sc->incomplete || sc->processing)) { - ngx_log_error(NGX_LOG_INFO, c->log, 0, - "client prematurely closed connection"); - } - - if (n == 0 || n == NGX_ERROR) { - ngx_http_spdy_finalize_connection(sc, - NGX_HTTP_CLIENT_CLOSED_REQUEST); - return; - } - - end += n; - - sc->buffer_used = 0; - sc->incomplete = 0; - - do { - p = sc->handler(sc, p, end); - - if (p == NULL) { - return; - } - - } while (p != end); - - } while (rev->ready); - - if (ngx_handle_read_event(rev, 0) != NGX_OK) { - ngx_http_spdy_finalize_connection(sc, NGX_HTTP_INTERNAL_SERVER_ERROR); - return; - } - - if (sc->last_out && ngx_http_spdy_send_output_queue(sc) == NGX_ERROR) { - ngx_http_spdy_finalize_connection(sc, NGX_HTTP_CLIENT_CLOSED_REQUEST); - return; - } - - sc->blocked = 0; - - if (sc->processing) { - if (rev->timer_set) { - ngx_del_timer(rev); - } - return; - } - - ngx_http_spdy_handle_connection(sc); -} - - -static void -ngx_http_spdy_write_handler(ngx_event_t *wev) -{ - ngx_int_t rc; - ngx_queue_t *q; - ngx_connection_t *c; - ngx_http_spdy_stream_t *stream; - ngx_http_spdy_connection_t *sc; - - c = wev->data; - sc = c->data; - - if (wev->timedout) { - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, - "spdy write event timed out"); - ngx_http_spdy_finalize_connection(sc, NGX_HTTP_CLIENT_CLOSED_REQUEST); - return; - } - - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "spdy write handler"); - - sc->blocked = 1; - - rc = ngx_http_spdy_send_output_queue(sc); - - if (rc == NGX_ERROR) { - ngx_http_spdy_finalize_connection(sc, NGX_HTTP_CLIENT_CLOSED_REQUEST); - return; - } - - while (!ngx_queue_empty(&sc->posted)) { - q = ngx_queue_head(&sc->posted); - - ngx_queue_remove(q); - - stream = ngx_queue_data(q, ngx_http_spdy_stream_t, queue); - - stream->handled = 0; - - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, - "run spdy stream %ui", stream->id); - - wev = stream->request->connection->write; - wev->handler(wev); - } - - sc->blocked = 0; - - if (rc == NGX_AGAIN) { - return; - } - - ngx_http_spdy_handle_connection(sc); -} - - -ngx_int_t -ngx_http_spdy_send_output_queue(ngx_http_spdy_connection_t *sc) -{ - int tcp_nodelay; - ngx_chain_t *cl; - ngx_event_t *wev; - ngx_connection_t *c; - ngx_http_core_loc_conf_t *clcf; - ngx_http_spdy_out_frame_t *out, *frame, *fn; - - c = sc->connection; - - if (c->error) { - return NGX_ERROR; - } - - wev = c->write; - - if (!wev->ready) { - return NGX_OK; - } - - cl = NULL; - out = NULL; - - for (frame = sc->last_out; frame; frame = fn) { - frame->last->next = cl; - cl = frame->first; - - fn = frame->next; - frame->next = out; - out = frame; - - ngx_log_debug5(NGX_LOG_DEBUG_HTTP, c->log, 0, - "spdy frame out: %p sid:%ui prio:%ui bl:%d len:%uz", - out, out->stream ? out->stream->id : 0, out->priority, - out->blocked, out->length); - } - - cl = c->send_chain(c, cl, 0); - - if (cl == NGX_CHAIN_ERROR) { - goto error; - } - - clcf = ngx_http_get_module_loc_conf(sc->http_connection->conf_ctx, - ngx_http_core_module); - - if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) { - goto error; - } - - if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) { - if (ngx_tcp_push(c->fd) == -1) { - ngx_connection_error(c, ngx_socket_errno, ngx_tcp_push_n " failed"); - goto error; - } - - c->tcp_nopush = NGX_TCP_NOPUSH_UNSET; - tcp_nodelay = ngx_tcp_nodelay_and_tcp_nopush ? 1 : 0; - - } else { - tcp_nodelay = 1; - } - - if (tcp_nodelay - && clcf->tcp_nodelay - && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) - { - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay"); - - if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, - (const void *) &tcp_nodelay, sizeof(int)) - == -1) - { -#if (NGX_SOLARIS) - /* Solaris returns EINVAL if a socket has been shut down */ - c->log_error = NGX_ERROR_IGNORE_EINVAL; -#endif - - ngx_connection_error(c, ngx_socket_errno, - "setsockopt(TCP_NODELAY) failed"); - - c->log_error = NGX_ERROR_INFO; - goto error; - } - - c->tcp_nodelay = NGX_TCP_NODELAY_SET; - } - - if (cl) { - ngx_add_timer(wev, clcf->send_timeout); - - } else { - if (wev->timer_set) { - ngx_del_timer(wev); - } - } - - for ( /* void */ ; out; out = fn) { - fn = out->next; - - if (out->handler(sc, out) != NGX_OK) { - out->blocked = 1; - out->priority = NGX_SPDY_HIGHEST_PRIORITY; - break; - } - - ngx_log_debug4(NGX_LOG_DEBUG_HTTP, c->log, 0, - "spdy frame sent: %p sid:%ui bl:%d len:%uz", - out, out->stream ? out->stream->id : 0, - out->blocked, out->length); - } - - frame = NULL; - - for ( /* void */ ; out; out = fn) { - fn = out->next; - out->next = frame; - frame = out; - } - - sc->last_out = frame; - - return NGX_OK; - -error: - - c->error = 1; - - if (!sc->blocked) { - ngx_post_event(wev, &ngx_posted_events); - } - - return NGX_ERROR; -} - - -static void -ngx_http_spdy_handle_connection(ngx_http_spdy_connection_t *sc) -{ - ngx_connection_t *c; - ngx_http_spdy_srv_conf_t *sscf; - - if (sc->last_out || sc->processing) { - return; - } - - c = sc->connection; - - if (c->error) { - ngx_http_close_connection(c); - return; - } - - if (c->buffered) { - return; - } - - sscf = ngx_http_get_module_srv_conf(sc->http_connection->conf_ctx, - ngx_http_spdy_module); - if (sc->incomplete) { - ngx_add_timer(c->read, sscf->recv_timeout); - return; - } - - if (ngx_terminate || ngx_exiting) { - ngx_http_close_connection(c); - return; - } - - ngx_destroy_pool(sc->pool); - - sc->pool = NULL; - sc->free_ctl_frames = NULL; - sc->free_fake_connections = NULL; - -#if (NGX_HTTP_SSL) - if (c->ssl) { - ngx_ssl_free_buffer(c); - } -#endif - - c->destroyed = 1; - c->idle = 1; - ngx_reusable_connection(c, 1); - - c->write->handler = ngx_http_empty_handler; - c->read->handler = ngx_http_spdy_keepalive_handler; - - if (c->write->timer_set) { - ngx_del_timer(c->write); - } - - ngx_add_timer(c->read, sscf->keepalive_timeout); -} - - -static u_char * -ngx_http_spdy_proxy_protocol(ngx_http_spdy_connection_t *sc, u_char *pos, - u_char *end) -{ - ngx_log_t *log; - - log = sc->connection->log; - log->action = "reading PROXY protocol"; - - pos = ngx_proxy_protocol_read(sc->connection, pos, end); - - log->action = "processing SPDY"; - - if (pos == NULL) { - return ngx_http_spdy_state_protocol_error(sc); - } - - return ngx_http_spdy_state_complete(sc, pos, end); -} - - -static u_char * -ngx_http_spdy_state_head(ngx_http_spdy_connection_t *sc, u_char *pos, - u_char *end) -{ - uint32_t head, flen; - ngx_uint_t type; - - if (end - pos < NGX_SPDY_FRAME_HEADER_SIZE) { - return ngx_http_spdy_state_save(sc, pos, end, - ngx_http_spdy_state_head); - } - - head = ngx_spdy_frame_parse_uint32(pos); - - pos += sizeof(uint32_t); - - flen = ngx_spdy_frame_parse_uint32(pos); - - sc->flags = ngx_spdy_frame_flags(flen); - sc->length = ngx_spdy_frame_length(flen); - - pos += sizeof(uint32_t); - - ngx_log_debug3(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, - "process spdy frame head:%08XD f:%Xd l:%uz", - head, sc->flags, sc->length); - - if (ngx_spdy_ctl_frame_check(head)) { - type = ngx_spdy_ctl_frame_type(head); - - switch (type) { - - case NGX_SPDY_SYN_STREAM: - return ngx_http_spdy_state_syn_stream(sc, pos, end); - - case NGX_SPDY_SYN_REPLY: - ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0, - "client sent unexpected SYN_REPLY frame"); - return ngx_http_spdy_state_protocol_error(sc); - - case NGX_SPDY_RST_STREAM: - return ngx_http_spdy_state_rst_stream(sc, pos, end); - - case NGX_SPDY_SETTINGS: - return ngx_http_spdy_state_settings(sc, pos, end); - - case NGX_SPDY_PING: - return ngx_http_spdy_state_ping(sc, pos, end); - - case NGX_SPDY_GOAWAY: - return ngx_http_spdy_state_skip(sc, pos, end); /* TODO */ - - case NGX_SPDY_HEADERS: - ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0, - "client sent unexpected HEADERS frame"); - return ngx_http_spdy_state_protocol_error(sc); - - case NGX_SPDY_WINDOW_UPDATE: - return ngx_http_spdy_state_window_update(sc, pos, end); - - default: - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, - "spdy control frame with unknown type %ui", type); - return ngx_http_spdy_state_skip(sc, pos, end); - } - } - - if (ngx_spdy_data_frame_check(head)) { - sc->stream = ngx_http_spdy_get_stream_by_id(sc, head); - return ngx_http_spdy_state_data(sc, pos, end); - } - - ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0, - "client sent invalid frame"); - - return ngx_http_spdy_state_protocol_error(sc); -} - - -static u_char * -ngx_http_spdy_state_syn_stream(ngx_http_spdy_connection_t *sc, u_char *pos, - u_char *end) -{ - ngx_uint_t sid, prio; - ngx_http_spdy_stream_t *stream; - ngx_http_spdy_srv_conf_t *sscf; - - if (end - pos < NGX_SPDY_SYN_STREAM_SIZE) { - return ngx_http_spdy_state_save(sc, pos, end, - ngx_http_spdy_state_syn_stream); - } - - if (sc->length <= NGX_SPDY_SYN_STREAM_SIZE) { - ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0, - "client sent SYN_STREAM frame with incorrect length %uz", - sc->length); - - return ngx_http_spdy_state_protocol_error(sc); - } - - sc->length -= NGX_SPDY_SYN_STREAM_SIZE; - - sid = ngx_spdy_frame_parse_sid(pos); - prio = pos[8] >> 5; - - pos += NGX_SPDY_SYN_STREAM_SIZE; - - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, - "spdy SYN_STREAM frame sid:%ui prio:%ui", sid, prio); - - if (sid % 2 == 0 || sid <= sc->last_sid) { - ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0, - "client sent SYN_STREAM frame " - "with invalid Stream-ID %ui", sid); - - stream = ngx_http_spdy_get_stream_by_id(sc, sid); - - if (stream) { - if (ngx_http_spdy_terminate_stream(sc, stream, - NGX_SPDY_PROTOCOL_ERROR) - != NGX_OK) - { - return ngx_http_spdy_state_internal_error(sc); - } - } - - return ngx_http_spdy_state_protocol_error(sc); - } - - sc->last_sid = sid; - - sscf = ngx_http_get_module_srv_conf(sc->http_connection->conf_ctx, - ngx_http_spdy_module); - - if (sc->processing >= sscf->concurrent_streams) { - - ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0, - "concurrent streams exceeded %ui", sc->processing); - - if (ngx_http_spdy_send_rst_stream(sc, sid, NGX_SPDY_REFUSED_STREAM, - prio) - != NGX_OK) - { - return ngx_http_spdy_state_internal_error(sc); - } - - return ngx_http_spdy_state_headers_skip(sc, pos, end); - } - - stream = ngx_http_spdy_create_stream(sc, sid, prio); - if (stream == NULL) { - return ngx_http_spdy_state_internal_error(sc); - } - - stream->in_closed = (sc->flags & NGX_SPDY_FLAG_FIN) ? 1 : 0; - - stream->request->request_length = NGX_SPDY_FRAME_HEADER_SIZE - + NGX_SPDY_SYN_STREAM_SIZE - + sc->length; - - sc->stream = stream; - - return ngx_http_spdy_state_headers(sc, pos, end); -} - - -static u_char * -ngx_http_spdy_state_headers(ngx_http_spdy_connection_t *sc, u_char *pos, - u_char *end) -{ - int z; - size_t size; - ngx_buf_t *buf; - ngx_int_t rc; - ngx_http_request_t *r; - - size = end - pos; - - if (size == 0) { - return ngx_http_spdy_state_save(sc, pos, end, - ngx_http_spdy_state_headers); - } - - if (size > sc->length) { - size = sc->length; - } - - r = sc->stream->request; - - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "process spdy header block %uz of %uz", size, sc->length); - - buf = r->header_in; - - sc->zstream_in.next_in = pos; - sc->zstream_in.avail_in = size; - sc->zstream_in.next_out = buf->last; - - /* one byte is reserved for null-termination of the last header value */ - sc->zstream_in.avail_out = buf->end - buf->last - 1; - - z = inflate(&sc->zstream_in, Z_NO_FLUSH); - - if (z == Z_NEED_DICT) { - z = inflateSetDictionary(&sc->zstream_in, ngx_http_spdy_dict, - sizeof(ngx_http_spdy_dict)); - - if (z != Z_OK) { - if (z == Z_DATA_ERROR) { - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "client sent SYN_STREAM frame with header " - "block encoded using wrong dictionary: %ul", - (u_long) sc->zstream_in.adler); - - return ngx_http_spdy_state_protocol_error(sc); - } - - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "inflateSetDictionary() failed: %d", z); - - return ngx_http_spdy_state_internal_error(sc); - } - - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "spdy inflateSetDictionary(): %d", z); - - z = sc->zstream_in.avail_in ? inflate(&sc->zstream_in, Z_NO_FLUSH) - : Z_OK; - } - - ngx_log_debug5(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "spdy inflate out: ni:%p no:%p ai:%ud ao:%ud rc:%d", - sc->zstream_in.next_in, sc->zstream_in.next_out, - sc->zstream_in.avail_in, sc->zstream_in.avail_out, - z); - - if (z != Z_OK) { - return ngx_http_spdy_state_inflate_error(sc, z); - } - - sc->length -= sc->zstream_in.next_in - pos; - pos = sc->zstream_in.next_in; - - buf->last = sc->zstream_in.next_out; - - if (r->headers_in.headers.part.elts == NULL) { - - if (buf->last - buf->pos < NGX_SPDY_NV_NUM_SIZE) { - - if (sc->length == 0) { - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "premature end of spdy header block"); - - return ngx_http_spdy_state_headers_error(sc, pos, end); - } - - return ngx_http_spdy_state_save(sc, pos, end, - ngx_http_spdy_state_headers); - } - - sc->entries = ngx_spdy_frame_parse_uint32(buf->pos); - - buf->pos += NGX_SPDY_NV_NUM_SIZE; - - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "spdy header block has %ui entries", - sc->entries); - - if (ngx_list_init(&r->headers_in.headers, r->pool, 20, - sizeof(ngx_table_elt_t)) - != NGX_OK) - { - ngx_http_spdy_close_stream(sc->stream, - NGX_HTTP_INTERNAL_SERVER_ERROR); - return ngx_http_spdy_state_headers_skip(sc, pos, end); - } - - if (ngx_array_init(&r->headers_in.cookies, r->pool, 2, - sizeof(ngx_table_elt_t *)) - != NGX_OK) - { - ngx_http_spdy_close_stream(sc->stream, - NGX_HTTP_INTERNAL_SERVER_ERROR); - return ngx_http_spdy_state_headers_skip(sc, pos, end); - } - } - - while (sc->entries) { - - rc = ngx_http_spdy_parse_header(r); - - switch (rc) { - - case NGX_DONE: - sc->entries--; - - case NGX_OK: - break; - - case NGX_AGAIN: - - if (sc->zstream_in.avail_in) { - - rc = ngx_http_spdy_alloc_large_header_buffer(r); - - if (rc == NGX_DECLINED) { - ngx_http_finalize_request(r, - NGX_HTTP_REQUEST_HEADER_TOO_LARGE); - return ngx_http_spdy_state_headers_skip(sc, pos, end); - } - - if (rc != NGX_OK) { - ngx_http_spdy_close_stream(sc->stream, - NGX_HTTP_INTERNAL_SERVER_ERROR); - return ngx_http_spdy_state_headers_skip(sc, pos, end); - } - - /* null-terminate the last processed header name or value */ - *buf->pos = '\0'; - - buf = r->header_in; - - sc->zstream_in.next_out = buf->last; - - /* one byte is reserved for null-termination */ - sc->zstream_in.avail_out = buf->end - buf->last - 1; - - z = inflate(&sc->zstream_in, Z_NO_FLUSH); - - ngx_log_debug5(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "spdy inflate out: ni:%p no:%p ai:%ud ao:%ud rc:%d", - sc->zstream_in.next_in, sc->zstream_in.next_out, - sc->zstream_in.avail_in, sc->zstream_in.avail_out, - z); - - if (z != Z_OK) { - return ngx_http_spdy_state_inflate_error(sc, z); - } - - sc->length -= sc->zstream_in.next_in - pos; - pos = sc->zstream_in.next_in; - - buf->last = sc->zstream_in.next_out; - - continue; - } - - if (sc->length == 0) { - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "premature end of spdy header block"); - - return ngx_http_spdy_state_headers_error(sc, pos, end); - } - - return ngx_http_spdy_state_save(sc, pos, end, - ngx_http_spdy_state_headers); - - case NGX_HTTP_PARSE_INVALID_HEADER: - ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); - return ngx_http_spdy_state_headers_skip(sc, pos, end); - - default: /* NGX_ERROR */ - return ngx_http_spdy_state_headers_error(sc, pos, end); - } - - /* a header line has been parsed successfully */ - - rc = ngx_http_spdy_handle_request_header(r); - - if (rc != NGX_OK) { - if (rc == NGX_HTTP_PARSE_INVALID_HEADER) { - ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); - return ngx_http_spdy_state_headers_skip(sc, pos, end); - } - - if (rc != NGX_ABORT) { - ngx_http_spdy_close_stream(sc->stream, - NGX_HTTP_INTERNAL_SERVER_ERROR); - } - - return ngx_http_spdy_state_headers_skip(sc, pos, end); - } - } - - if (buf->pos != buf->last || sc->zstream_in.avail_in) { - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "incorrect number of spdy header block entries"); - - return ngx_http_spdy_state_headers_error(sc, pos, end); - } - - if (sc->length) { - return ngx_http_spdy_state_save(sc, pos, end, - ngx_http_spdy_state_headers); - } - - /* null-terminate the last header value */ - *buf->pos = '\0'; - - ngx_http_spdy_run_request(r); - - return ngx_http_spdy_state_complete(sc, pos, end); -} - - -static u_char * -ngx_http_spdy_state_headers_skip(ngx_http_spdy_connection_t *sc, u_char *pos, - u_char *end) -{ - int n; - size_t size; - u_char buffer[NGX_SPDY_SKIP_HEADERS_BUFFER_SIZE]; - - if (sc->length == 0) { - return ngx_http_spdy_state_complete(sc, pos, end); - } - - size = end - pos; - - if (size == 0) { - return ngx_http_spdy_state_save(sc, pos, end, - ngx_http_spdy_state_headers_skip); - } - - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, - "spdy header block skip %uz of %uz", size, sc->length); - - sc->zstream_in.next_in = pos; - sc->zstream_in.avail_in = (size < sc->length) ? size : sc->length; - - while (sc->zstream_in.avail_in) { - sc->zstream_in.next_out = buffer; - sc->zstream_in.avail_out = NGX_SPDY_SKIP_HEADERS_BUFFER_SIZE; - - n = inflate(&sc->zstream_in, Z_NO_FLUSH); - - ngx_log_debug5(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, - "spdy inflate out: ni:%p no:%p ai:%ud ao:%ud rc:%d", - sc->zstream_in.next_in, sc->zstream_in.next_out, - sc->zstream_in.avail_in, sc->zstream_in.avail_out, - n); - - if (n != Z_OK) { - return ngx_http_spdy_state_inflate_error(sc, n); - } - } - - pos = sc->zstream_in.next_in; - - if (size < sc->length) { - sc->length -= size; - return ngx_http_spdy_state_save(sc, pos, end, - ngx_http_spdy_state_headers_skip); - } - - return ngx_http_spdy_state_complete(sc, pos, end); -} - - -static u_char * -ngx_http_spdy_state_headers_error(ngx_http_spdy_connection_t *sc, u_char *pos, - u_char *end) -{ - ngx_http_spdy_stream_t *stream; - - stream = sc->stream; - - ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0, - "client sent SYN_STREAM frame for stream %ui " - "with invalid header block", stream->id); - - if (ngx_http_spdy_send_rst_stream(sc, stream->id, NGX_SPDY_PROTOCOL_ERROR, - stream->priority) - != NGX_OK) - { - return ngx_http_spdy_state_internal_error(sc); - } - - stream->out_closed = 1; - - ngx_http_spdy_close_stream(stream, NGX_HTTP_BAD_REQUEST); - - return ngx_http_spdy_state_headers_skip(sc, pos, end); -} - - -static u_char * -ngx_http_spdy_state_window_update(ngx_http_spdy_connection_t *sc, u_char *pos, - u_char *end) -{ - size_t delta; - ngx_uint_t sid; - ngx_event_t *wev; - ngx_queue_t *q; - ngx_http_spdy_stream_t *stream; - - if (end - pos < NGX_SPDY_WINDOW_UPDATE_SIZE) { - return ngx_http_spdy_state_save(sc, pos, end, - ngx_http_spdy_state_window_update); - } - - if (sc->length != NGX_SPDY_WINDOW_UPDATE_SIZE) { - ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0, - "client sent WINDOW_UPDATE frame " - "with incorrect length %uz", sc->length); - - return ngx_http_spdy_state_protocol_error(sc); - } - - sid = ngx_spdy_frame_parse_sid(pos); - - pos += NGX_SPDY_SID_SIZE; - - delta = ngx_spdy_frame_parse_delta(pos); - - pos += NGX_SPDY_DELTA_SIZE; - - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, - "spdy WINDOW_UPDATE sid:%ui delta:%uz", sid, delta); - - if (sid) { - stream = ngx_http_spdy_get_stream_by_id(sc, sid); - - if (stream == NULL) { - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, - "unknown spdy stream"); - - return ngx_http_spdy_state_complete(sc, pos, end); - } - - if (stream->send_window > (ssize_t) (NGX_SPDY_MAX_WINDOW - delta)) { - - ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0, - "client violated flow control for stream %ui: " - "received WINDOW_UPDATE frame with delta %uz " - "not allowed for window %z", - sid, delta, stream->send_window); - - if (ngx_http_spdy_terminate_stream(sc, stream, - NGX_SPDY_FLOW_CONTROL_ERROR) - == NGX_ERROR) - { - return ngx_http_spdy_state_internal_error(sc); - } - - return ngx_http_spdy_state_complete(sc, pos, end); - } - - stream->send_window += delta; - - if (stream->exhausted) { - stream->exhausted = 0; - - wev = stream->request->connection->write; - - if (!wev->timer_set) { - wev->delayed = 0; - wev->handler(wev); - } - } - - } else { - sc->send_window += delta; - - if (sc->send_window > NGX_SPDY_MAX_WINDOW) { - ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0, - "client violated connection flow control: " - "received WINDOW_UPDATE frame with delta %uz " - "not allowed for window %uz", - delta, sc->send_window); - - return ngx_http_spdy_state_protocol_error(sc); - } - - while (!ngx_queue_empty(&sc->waiting)) { - q = ngx_queue_head(&sc->waiting); - - ngx_queue_remove(q); - - stream = ngx_queue_data(q, ngx_http_spdy_stream_t, queue); - - stream->handled = 0; - - wev = stream->request->connection->write; - - if (!wev->timer_set) { - wev->delayed = 0; - wev->handler(wev); - - if (sc->send_window == 0) { - break; - } - } - } - } - - return ngx_http_spdy_state_complete(sc, pos, end); -} - - -static u_char * -ngx_http_spdy_state_data(ngx_http_spdy_connection_t *sc, u_char *pos, - u_char *end) -{ - ngx_http_spdy_stream_t *stream; - - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, - "spdy DATA frame"); - - if (sc->length > sc->recv_window) { - ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0, - "client violated connection flow control: " - "received DATA frame length %uz, available window %uz", - sc->length, sc->recv_window); - - return ngx_http_spdy_state_protocol_error(sc); - } - - sc->recv_window -= sc->length; - - if (sc->recv_window < NGX_SPDY_MAX_WINDOW / 4) { - - if (ngx_http_spdy_send_window_update(sc, 0, - NGX_SPDY_MAX_WINDOW - - sc->recv_window) - == NGX_ERROR) - { - return ngx_http_spdy_state_internal_error(sc); - } - - sc->recv_window = NGX_SPDY_MAX_WINDOW; - } - - stream = sc->stream; - - if (stream == NULL) { - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, - "unknown spdy stream"); - - return ngx_http_spdy_state_skip(sc, pos, end); - } - - if (sc->length > stream->recv_window) { - ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0, - "client violated flow control for stream %ui: " - "received DATA frame length %uz, available window %uz", - stream->id, sc->length, stream->recv_window); - - if (ngx_http_spdy_terminate_stream(sc, stream, - NGX_SPDY_FLOW_CONTROL_ERROR) - == NGX_ERROR) - { - return ngx_http_spdy_state_internal_error(sc); - } - - return ngx_http_spdy_state_skip(sc, pos, end); - } - - stream->recv_window -= sc->length; - - if (stream->recv_window < NGX_SPDY_STREAM_WINDOW / 4) { - - if (ngx_http_spdy_send_window_update(sc, stream->id, - NGX_SPDY_STREAM_WINDOW - - stream->recv_window) - == NGX_ERROR) - { - return ngx_http_spdy_state_internal_error(sc); - } - - stream->recv_window = NGX_SPDY_STREAM_WINDOW; - } - - if (stream->in_closed) { - ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0, - "client sent DATA frame for half-closed stream %ui", - stream->id); - - if (ngx_http_spdy_terminate_stream(sc, stream, - NGX_SPDY_STREAM_ALREADY_CLOSED) - == NGX_ERROR) - { - return ngx_http_spdy_state_internal_error(sc); - } - - return ngx_http_spdy_state_skip(sc, pos, end); - } - - return ngx_http_spdy_state_read_data(sc, pos, end); -} - - -static u_char * -ngx_http_spdy_state_read_data(ngx_http_spdy_connection_t *sc, u_char *pos, - u_char *end) -{ - size_t size; - ssize_t n; - ngx_buf_t *buf; - ngx_int_t rc; - ngx_temp_file_t *tf; - ngx_http_request_t *r; - ngx_http_spdy_stream_t *stream; - ngx_http_request_body_t *rb; - ngx_http_core_loc_conf_t *clcf; - - stream = sc->stream; - - if (stream == NULL) { - return ngx_http_spdy_state_skip(sc, pos, end); - } - - if (stream->skip_data) { - - if (sc->flags & NGX_SPDY_FLAG_FIN) { - stream->in_closed = 1; - } - - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, - "skipping spdy DATA frame, reason: %d", - stream->skip_data); - - return ngx_http_spdy_state_skip(sc, pos, end); - } - - size = end - pos; - - if (size > sc->length) { - size = sc->length; - } - - r = stream->request; - - if (r->request_body == NULL - && ngx_http_spdy_init_request_body(r) != NGX_OK) - { - stream->skip_data = NGX_SPDY_DATA_INTERNAL_ERROR; - return ngx_http_spdy_state_skip(sc, pos, end); - } - - rb = r->request_body; - tf = rb->temp_file; - buf = rb->buf; - - if (size) { - rb->rest += size; - - if (r->headers_in.content_length_n != -1 - && r->headers_in.content_length_n < rb->rest) - { - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "client intended to send body data " - "larger than declared"); - - stream->skip_data = NGX_SPDY_DATA_ERROR; - goto error; - - } else { - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - - if (clcf->client_max_body_size - && clcf->client_max_body_size < rb->rest) - { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "client intended to send " - "too large chunked body: %O bytes", rb->rest); - - stream->skip_data = NGX_SPDY_DATA_ERROR; - goto error; - } - } - - sc->length -= size; - - if (tf) { - buf->start = pos; - buf->pos = pos; - - pos += size; - - buf->end = pos; - buf->last = pos; - - n = ngx_write_chain_to_temp_file(tf, rb->bufs); - - /* TODO: n == 0 or not complete and level event */ - - if (n == NGX_ERROR) { - stream->skip_data = NGX_SPDY_DATA_INTERNAL_ERROR; - goto error; - } - - tf->offset += n; - - } else { - buf->last = ngx_cpymem(buf->last, pos, size); - pos += size; - } - - r->request_length += size; - } - - if (sc->length) { - return ngx_http_spdy_state_save(sc, pos, end, - ngx_http_spdy_state_read_data); - } - - if (sc->flags & NGX_SPDY_FLAG_FIN) { - - stream->in_closed = 1; - - if (r->headers_in.content_length_n < 0) { - r->headers_in.content_length_n = rb->rest; - - } else if (r->headers_in.content_length_n != rb->rest) { - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "client prematurely closed stream: " - "only %O out of %O bytes of request body received", - rb->rest, r->headers_in.content_length_n); - - stream->skip_data = NGX_SPDY_DATA_ERROR; - goto error; - } - - if (tf) { - ngx_memzero(buf, sizeof(ngx_buf_t)); - - buf->in_file = 1; - buf->file_last = tf->file.offset; - buf->file = &tf->file; - - rb->buf = NULL; - } - - if (rb->post_handler) { - r->read_event_handler = ngx_http_block_reading; - rb->post_handler(r); - } - } - - return ngx_http_spdy_state_complete(sc, pos, end); - -error: - - if (rb->post_handler) { - - if (stream->skip_data == NGX_SPDY_DATA_ERROR) { - rc = (r->headers_in.content_length_n == -1) - ? NGX_HTTP_REQUEST_ENTITY_TOO_LARGE - : NGX_HTTP_BAD_REQUEST; - - } else { - rc = NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - ngx_http_finalize_request(r, rc); - } - - return ngx_http_spdy_state_skip(sc, pos, end); -} - - -static u_char * -ngx_http_spdy_state_rst_stream(ngx_http_spdy_connection_t *sc, u_char *pos, - u_char *end) -{ - ngx_uint_t sid, status; - ngx_event_t *ev; - ngx_connection_t *fc; - ngx_http_spdy_stream_t *stream; - - if (end - pos < NGX_SPDY_RST_STREAM_SIZE) { - return ngx_http_spdy_state_save(sc, pos, end, - ngx_http_spdy_state_rst_stream); - } - - if (sc->length != NGX_SPDY_RST_STREAM_SIZE) { - ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0, - "client sent RST_STREAM frame with incorrect length %uz", - sc->length); - - return ngx_http_spdy_state_protocol_error(sc); - } - - sid = ngx_spdy_frame_parse_sid(pos); - - pos += NGX_SPDY_SID_SIZE; - - status = ngx_spdy_frame_parse_uint32(pos); - - pos += sizeof(uint32_t); - - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, - "spdy RST_STREAM sid:%ui st:%ui", sid, status); - - stream = ngx_http_spdy_get_stream_by_id(sc, sid); - - if (stream == NULL) { - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, - "unknown spdy stream"); - - return ngx_http_spdy_state_complete(sc, pos, end); - } - - stream->in_closed = 1; - stream->out_closed = 1; - - fc = stream->request->connection; - fc->error = 1; - - switch (status) { - - case NGX_SPDY_CANCEL: - ngx_log_error(NGX_LOG_INFO, fc->log, 0, - "client canceled stream %ui", sid); - break; - - case NGX_SPDY_INTERNAL_ERROR: - ngx_log_error(NGX_LOG_INFO, fc->log, 0, - "client terminated stream %ui due to internal error", - sid); - break; - - default: - ngx_log_error(NGX_LOG_INFO, fc->log, 0, - "client terminated stream %ui with status %ui", - sid, status); - break; - } - - ev = fc->read; - ev->handler(ev); - - return ngx_http_spdy_state_complete(sc, pos, end); -} - - -static u_char * -ngx_http_spdy_state_ping(ngx_http_spdy_connection_t *sc, u_char *pos, - u_char *end) -{ - u_char *p; - ngx_buf_t *buf; - ngx_http_spdy_out_frame_t *frame; - - if (end - pos < NGX_SPDY_PING_SIZE) { - return ngx_http_spdy_state_save(sc, pos, end, - ngx_http_spdy_state_ping); - } - - if (sc->length != NGX_SPDY_PING_SIZE) { - ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0, - "client sent PING frame with incorrect length %uz", - sc->length); - - return ngx_http_spdy_state_protocol_error(sc); - } - - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, - "spdy PING frame"); - - frame = ngx_http_spdy_get_ctl_frame(sc, NGX_SPDY_PING_SIZE, - NGX_SPDY_HIGHEST_PRIORITY); - if (frame == NULL) { - return ngx_http_spdy_state_internal_error(sc); - } - - buf = frame->first->buf; - - p = buf->pos; - - p = ngx_spdy_frame_write_head(p, NGX_SPDY_PING); - p = ngx_spdy_frame_write_flags_and_len(p, 0, NGX_SPDY_PING_SIZE); - - p = ngx_cpymem(p, pos, NGX_SPDY_PING_SIZE); - - buf->last = p; - - ngx_http_spdy_queue_frame(sc, frame); - - pos += NGX_SPDY_PING_SIZE; - - return ngx_http_spdy_state_complete(sc, pos, end); -} - - -static u_char * -ngx_http_spdy_state_skip(ngx_http_spdy_connection_t *sc, u_char *pos, - u_char *end) -{ - size_t size; - - size = end - pos; - - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, - "spdy frame skip %uz of %uz", size, sc->length); - - if (size < sc->length) { - sc->length -= size; - return ngx_http_spdy_state_save(sc, end, end, - ngx_http_spdy_state_skip); - } - - return ngx_http_spdy_state_complete(sc, pos + sc->length, end); -} - - -static u_char * -ngx_http_spdy_state_settings(ngx_http_spdy_connection_t *sc, u_char *pos, - u_char *end) -{ - ngx_uint_t fid, val; - - if (sc->entries == 0) { - - if (end - pos < NGX_SPDY_SETTINGS_NUM_SIZE) { - return ngx_http_spdy_state_save(sc, pos, end, - ngx_http_spdy_state_settings); - } - - sc->entries = ngx_spdy_frame_parse_uint32(pos); - - pos += NGX_SPDY_SETTINGS_NUM_SIZE; - sc->length -= NGX_SPDY_SETTINGS_NUM_SIZE; - - if (sc->length < sc->entries * NGX_SPDY_SETTINGS_PAIR_SIZE) { - ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0, - "client sent SETTINGS frame with incorrect " - "length %uz or number of entries %ui", - sc->length, sc->entries); - - return ngx_http_spdy_state_protocol_error(sc); - } - - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, - "spdy SETTINGS frame has %ui entries", sc->entries); - } - - while (sc->entries) { - if (end - pos < NGX_SPDY_SETTINGS_PAIR_SIZE) { - return ngx_http_spdy_state_save(sc, pos, end, - ngx_http_spdy_state_settings); - } - - sc->entries--; - sc->length -= NGX_SPDY_SETTINGS_PAIR_SIZE; - - fid = ngx_spdy_frame_parse_uint32(pos); - - pos += NGX_SPDY_SETTINGS_FID_SIZE; - - val = ngx_spdy_frame_parse_uint32(pos); - - pos += NGX_SPDY_SETTINGS_VAL_SIZE; - - ngx_log_debug3(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, - "spdy SETTINGS entry fl:%ui id:%ui val:%ui", - ngx_spdy_frame_flags(fid), ngx_spdy_frame_id(fid), val); - - if (ngx_spdy_frame_flags(fid) == NGX_SPDY_SETTINGS_FLAG_PERSISTED) { - continue; - } - - switch (ngx_spdy_frame_id(fid)) { - - case NGX_SPDY_SETTINGS_INIT_WINDOW: - - if (val > NGX_SPDY_MAX_WINDOW) { - ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0, - "client sent SETTINGS frame with " - "incorrect INIT_WINDOW value: %ui", val); - - return ngx_http_spdy_state_protocol_error(sc); - } - - if (ngx_http_spdy_adjust_windows(sc, val - sc->init_window) - != NGX_OK) - { - return ngx_http_spdy_state_internal_error(sc); - } - - sc->init_window = val; - - continue; - } - } - - return ngx_http_spdy_state_complete(sc, pos, end); -} - - -static u_char * -ngx_http_spdy_state_complete(ngx_http_spdy_connection_t *sc, u_char *pos, - u_char *end) -{ - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, - "spdy frame complete pos:%p end:%p", pos, end); - - if (pos > end) { - ngx_log_error(NGX_LOG_ALERT, sc->connection->log, 0, - "receive buffer overrun"); - - ngx_debug_point(); - return ngx_http_spdy_state_internal_error(sc); - } - - sc->handler = ngx_http_spdy_state_head; - sc->stream = NULL; - - return pos; -} - - -static u_char * -ngx_http_spdy_state_save(ngx_http_spdy_connection_t *sc, - u_char *pos, u_char *end, ngx_http_spdy_handler_pt handler) -{ - size_t size; - - ngx_log_debug3(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, - "spdy frame state save pos:%p end:%p handler:%p", - pos, end, handler); - - size = end - pos; - - if (size > NGX_SPDY_STATE_BUFFER_SIZE) { - ngx_log_error(NGX_LOG_ALERT, sc->connection->log, 0, - "state buffer overflow: %uz bytes required", size); - - ngx_debug_point(); - return ngx_http_spdy_state_internal_error(sc); - } - - ngx_memcpy(sc->buffer, pos, NGX_SPDY_STATE_BUFFER_SIZE); - - sc->buffer_used = size; - sc->handler = handler; - sc->incomplete = 1; - - return end; -} - - -static u_char * -ngx_http_spdy_state_inflate_error(ngx_http_spdy_connection_t *sc, int rc) -{ - if (rc == Z_DATA_ERROR || rc == Z_STREAM_END) { - ngx_log_error(NGX_LOG_INFO, sc->connection->log, 0, - "client sent SYN_STREAM frame with " - "corrupted header block, inflate() failed: %d", rc); - - return ngx_http_spdy_state_protocol_error(sc); - } - - ngx_log_error(NGX_LOG_ERR, sc->connection->log, 0, - "inflate() failed: %d", rc); - - return ngx_http_spdy_state_internal_error(sc); -} - - -static u_char * -ngx_http_spdy_state_protocol_error(ngx_http_spdy_connection_t *sc) -{ - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, - "spdy state protocol error"); - - if (sc->stream) { - sc->stream->out_closed = 1; - ngx_http_spdy_close_stream(sc->stream, NGX_HTTP_BAD_REQUEST); - } - - ngx_http_spdy_finalize_connection(sc, NGX_HTTP_CLIENT_CLOSED_REQUEST); - - return NULL; -} - - -static u_char * -ngx_http_spdy_state_internal_error(ngx_http_spdy_connection_t *sc) -{ - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, - "spdy state internal error"); - - if (sc->stream) { - sc->stream->out_closed = 1; - ngx_http_spdy_close_stream(sc->stream, NGX_HTTP_INTERNAL_SERVER_ERROR); - } - - ngx_http_spdy_finalize_connection(sc, NGX_HTTP_INTERNAL_SERVER_ERROR); - - return NULL; -} - - -static ngx_int_t -ngx_http_spdy_send_window_update(ngx_http_spdy_connection_t *sc, ngx_uint_t sid, - ngx_uint_t delta) -{ - u_char *p; - ngx_buf_t *buf; - ngx_http_spdy_out_frame_t *frame; - - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, - "spdy send WINDOW_UPDATE sid:%ui delta:%ui", sid, delta); - - frame = ngx_http_spdy_get_ctl_frame(sc, NGX_SPDY_WINDOW_UPDATE_SIZE, - NGX_SPDY_HIGHEST_PRIORITY); - if (frame == NULL) { - return NGX_ERROR; - } - - buf = frame->first->buf; - - p = buf->pos; - - p = ngx_spdy_frame_write_head(p, NGX_SPDY_WINDOW_UPDATE); - p = ngx_spdy_frame_write_flags_and_len(p, 0, NGX_SPDY_WINDOW_UPDATE_SIZE); - - p = ngx_spdy_frame_write_sid(p, sid); - p = ngx_spdy_frame_aligned_write_uint32(p, delta); - - buf->last = p; - - ngx_http_spdy_queue_frame(sc, frame); - - return NGX_OK; -} - - -static ngx_int_t -ngx_http_spdy_send_rst_stream(ngx_http_spdy_connection_t *sc, ngx_uint_t sid, - ngx_uint_t status, ngx_uint_t priority) -{ - u_char *p; - ngx_buf_t *buf; - ngx_http_spdy_out_frame_t *frame; - - if (sc->connection->error) { - return NGX_OK; - } - - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, - "spdy send RST_STREAM sid:%ui st:%ui", sid, status); - - frame = ngx_http_spdy_get_ctl_frame(sc, NGX_SPDY_RST_STREAM_SIZE, - priority); - if (frame == NULL) { - return NGX_ERROR; - } - - buf = frame->first->buf; - - p = buf->pos; - - p = ngx_spdy_frame_write_head(p, NGX_SPDY_RST_STREAM); - p = ngx_spdy_frame_write_flags_and_len(p, 0, NGX_SPDY_RST_STREAM_SIZE); - - p = ngx_spdy_frame_write_sid(p, sid); - p = ngx_spdy_frame_aligned_write_uint32(p, status); - - buf->last = p; - - ngx_http_spdy_queue_frame(sc, frame); - - return NGX_OK; -} - - -#if 0 -static ngx_int_t -ngx_http_spdy_send_goaway(ngx_http_spdy_connection_t *sc) -{ - u_char *p; - ngx_buf_t *buf; - ngx_http_spdy_out_frame_t *frame; - - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, - "spdy send GOAWAY sid:%ui", sc->last_sid); - - frame = ngx_http_spdy_get_ctl_frame(sc, NGX_SPDY_GOAWAY_SIZE, - NGX_SPDY_HIGHEST_PRIORITY); - if (frame == NULL) { - return NGX_ERROR; - } - - buf = frame->first->buf; - - p = buf->pos; - - p = ngx_spdy_frame_write_head(p, NGX_SPDY_GOAWAY); - p = ngx_spdy_frame_write_flags_and_len(p, 0, NGX_SPDY_GOAWAY_SIZE); - - p = ngx_spdy_frame_write_sid(p, sc->last_sid); - - buf->last = p; - - ngx_http_spdy_queue_frame(sc, frame); - - return NGX_OK; -} -#endif - - -static ngx_int_t -ngx_http_spdy_send_settings(ngx_http_spdy_connection_t *sc) -{ - u_char *p; - ngx_buf_t *buf; - ngx_chain_t *cl; - ngx_http_spdy_srv_conf_t *sscf; - ngx_http_spdy_out_frame_t *frame; - - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, - "spdy send SETTINGS frame"); - - frame = ngx_palloc(sc->pool, sizeof(ngx_http_spdy_out_frame_t)); - if (frame == NULL) { - return NGX_ERROR; - } - - cl = ngx_alloc_chain_link(sc->pool); - if (cl == NULL) { - return NGX_ERROR; - } - - buf = ngx_create_temp_buf(sc->pool, NGX_SPDY_FRAME_HEADER_SIZE - + NGX_SPDY_SETTINGS_NUM_SIZE - + 2 * NGX_SPDY_SETTINGS_PAIR_SIZE); - if (buf == NULL) { - return NGX_ERROR; - } - - buf->last_buf = 1; - - cl->buf = buf; - cl->next = NULL; - - frame->first = cl; - frame->last = cl; - frame->handler = ngx_http_spdy_settings_frame_handler; - frame->stream = NULL; -#if (NGX_DEBUG) - frame->length = NGX_SPDY_SETTINGS_NUM_SIZE - + 2 * NGX_SPDY_SETTINGS_PAIR_SIZE; -#endif - frame->priority = NGX_SPDY_HIGHEST_PRIORITY; - frame->blocked = 0; - - p = buf->pos; - - p = ngx_spdy_frame_write_head(p, NGX_SPDY_SETTINGS); - p = ngx_spdy_frame_write_flags_and_len(p, NGX_SPDY_FLAG_CLEAR_SETTINGS, - NGX_SPDY_SETTINGS_NUM_SIZE - + 2 * NGX_SPDY_SETTINGS_PAIR_SIZE); - - p = ngx_spdy_frame_aligned_write_uint32(p, 2); - - sscf = ngx_http_get_module_srv_conf(sc->http_connection->conf_ctx, - ngx_http_spdy_module); - - p = ngx_spdy_frame_write_flags_and_id(p, 0, NGX_SPDY_SETTINGS_MAX_STREAMS); - p = ngx_spdy_frame_aligned_write_uint32(p, sscf->concurrent_streams); - - p = ngx_spdy_frame_write_flags_and_id(p, 0, NGX_SPDY_SETTINGS_INIT_WINDOW); - p = ngx_spdy_frame_aligned_write_uint32(p, NGX_SPDY_STREAM_WINDOW); - - buf->last = p; - - ngx_http_spdy_queue_frame(sc, frame); - - return NGX_OK; -} - - -ngx_int_t -ngx_http_spdy_settings_frame_handler(ngx_http_spdy_connection_t *sc, - ngx_http_spdy_out_frame_t *frame) -{ - ngx_buf_t *buf; - - buf = frame->first->buf; - - if (buf->pos != buf->last) { - return NGX_AGAIN; - } - - ngx_free_chain(sc->pool, frame->first); - - return NGX_OK; -} - - -static ngx_http_spdy_out_frame_t * -ngx_http_spdy_get_ctl_frame(ngx_http_spdy_connection_t *sc, size_t length, - ngx_uint_t priority) -{ - ngx_chain_t *cl; - ngx_http_spdy_out_frame_t *frame; - - frame = sc->free_ctl_frames; - - if (frame) { - sc->free_ctl_frames = frame->next; - - cl = frame->first; - cl->buf->pos = cl->buf->start; - - } else { - frame = ngx_palloc(sc->pool, sizeof(ngx_http_spdy_out_frame_t)); - if (frame == NULL) { - return NULL; - } - - cl = ngx_alloc_chain_link(sc->pool); - if (cl == NULL) { - return NULL; - } - - cl->buf = ngx_create_temp_buf(sc->pool, - NGX_SPDY_CTL_FRAME_BUFFER_SIZE); - if (cl->buf == NULL) { - return NULL; - } - - cl->buf->last_buf = 1; - - frame->first = cl; - frame->last = cl; - frame->handler = ngx_http_spdy_ctl_frame_handler; - frame->stream = NULL; - } - -#if (NGX_DEBUG) - if (length > NGX_SPDY_CTL_FRAME_BUFFER_SIZE - NGX_SPDY_FRAME_HEADER_SIZE) { - ngx_log_error(NGX_LOG_ALERT, sc->pool->log, 0, - "requested control frame is too large: %uz", length); - return NULL; - } - - frame->length = length; -#endif - - frame->priority = priority; - frame->blocked = 0; - - return frame; -} - - -static ngx_int_t -ngx_http_spdy_ctl_frame_handler(ngx_http_spdy_connection_t *sc, - ngx_http_spdy_out_frame_t *frame) -{ - ngx_buf_t *buf; - - buf = frame->first->buf; - - if (buf->pos != buf->last) { - return NGX_AGAIN; - } - - frame->next = sc->free_ctl_frames; - sc->free_ctl_frames = frame; - - return NGX_OK; -} - - -static ngx_http_spdy_stream_t * -ngx_http_spdy_create_stream(ngx_http_spdy_connection_t *sc, ngx_uint_t id, - ngx_uint_t priority) -{ - ngx_log_t *log; - ngx_uint_t index; - ngx_event_t *rev, *wev; - ngx_connection_t *fc; - ngx_http_log_ctx_t *ctx; - ngx_http_request_t *r; - ngx_http_spdy_stream_t *stream; - ngx_http_core_srv_conf_t *cscf; - ngx_http_spdy_srv_conf_t *sscf; - - fc = sc->free_fake_connections; - - if (fc) { - sc->free_fake_connections = fc->data; - - rev = fc->read; - wev = fc->write; - log = fc->log; - ctx = log->data; - - } else { - fc = ngx_palloc(sc->pool, sizeof(ngx_connection_t)); - if (fc == NULL) { - return NULL; - } - - rev = ngx_palloc(sc->pool, sizeof(ngx_event_t)); - if (rev == NULL) { - return NULL; - } - - wev = ngx_palloc(sc->pool, sizeof(ngx_event_t)); - if (wev == NULL) { - return NULL; - } - - log = ngx_palloc(sc->pool, sizeof(ngx_log_t)); - if (log == NULL) { - return NULL; - } - - ctx = ngx_palloc(sc->pool, sizeof(ngx_http_log_ctx_t)); - if (ctx == NULL) { - return NULL; - } - - ctx->connection = fc; - ctx->request = NULL; - } - - ngx_memcpy(log, sc->connection->log, sizeof(ngx_log_t)); - - log->data = ctx; - - ngx_memzero(rev, sizeof(ngx_event_t)); - - rev->data = fc; - rev->ready = 1; - rev->handler = ngx_http_spdy_close_stream_handler; - rev->log = log; - - ngx_memcpy(wev, rev, sizeof(ngx_event_t)); - - wev->write = 1; - - ngx_memcpy(fc, sc->connection, sizeof(ngx_connection_t)); - - fc->data = sc->http_connection; - fc->read = rev; - fc->write = wev; - fc->sent = 0; - fc->log = log; - fc->buffered = 0; - fc->sndlowat = 1; - fc->tcp_nodelay = NGX_TCP_NODELAY_DISABLED; - - r = ngx_http_create_request(fc); - if (r == NULL) { - return NULL; - } - - r->valid_location = 1; - - fc->data = r; - sc->connection->requests++; - - cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); - - r->header_in = ngx_create_temp_buf(r->pool, - cscf->client_header_buffer_size); - if (r->header_in == NULL) { - ngx_http_free_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); - return NULL; - } - - r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE; - - stream = ngx_pcalloc(r->pool, sizeof(ngx_http_spdy_stream_t)); - if (stream == NULL) { - ngx_http_free_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); - return NULL; - } - - r->spdy_stream = stream; - - stream->id = id; - stream->request = r; - stream->connection = sc; - - stream->send_window = sc->init_window; - stream->recv_window = NGX_SPDY_STREAM_WINDOW; - - stream->priority = priority; - - sscf = ngx_http_get_module_srv_conf(r, ngx_http_spdy_module); - - index = ngx_http_spdy_stream_index(sscf, id); - - stream->index = sc->streams_index[index]; - sc->streams_index[index] = stream; - - sc->processing++; - - return stream; -} - - -static ngx_http_spdy_stream_t * -ngx_http_spdy_get_stream_by_id(ngx_http_spdy_connection_t *sc, - ngx_uint_t sid) -{ - ngx_http_spdy_stream_t *stream; - ngx_http_spdy_srv_conf_t *sscf; - - sscf = ngx_http_get_module_srv_conf(sc->http_connection->conf_ctx, - ngx_http_spdy_module); - - stream = sc->streams_index[ngx_http_spdy_stream_index(sscf, sid)]; - - while (stream) { - if (stream->id == sid) { - return stream; - } - - stream = stream->index; - } - - return NULL; -} - - -static ngx_int_t -ngx_http_spdy_parse_header(ngx_http_request_t *r) -{ - u_char *p, *end, ch; - ngx_uint_t hash; - ngx_http_core_srv_conf_t *cscf; - - enum { - sw_name_len = 0, - sw_name, - sw_value_len, - sw_value - } state; - - state = r->state; - - p = r->header_in->pos; - end = r->header_in->last; - - switch (state) { - - case sw_name_len: - - if (end - p < NGX_SPDY_NV_NLEN_SIZE) { - return NGX_AGAIN; - } - - r->lowcase_index = ngx_spdy_frame_parse_uint32(p); - - if (r->lowcase_index == 0) { - return NGX_ERROR; - } - - /* null-terminate the previous header value */ - *p = '\0'; - - p += NGX_SPDY_NV_NLEN_SIZE; - - r->invalid_header = 0; - - state = sw_name; - - /* fall through */ - - case sw_name: - - if ((ngx_uint_t) (end - p) < r->lowcase_index) { - break; - } - - cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); - - r->header_name_start = p; - r->header_name_end = p + r->lowcase_index; - - if (p[0] == ':') { - p++; - } - - hash = 0; - - for ( /* void */ ; p != r->header_name_end; p++) { - - ch = *p; - - hash = ngx_hash(hash, ch); - - if ((ch >= 'a' && ch <= 'z') - || (ch == '-') - || (ch >= '0' && ch <= '9') - || (ch == '_' && cscf->underscores_in_headers)) - { - continue; - } - - switch (ch) { - case '\0': - case LF: - case CR: - case ':': - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "client sent invalid header name: \"%*s\"", - r->lowcase_index, r->header_name_start); - - return NGX_HTTP_PARSE_INVALID_HEADER; - } - - if (ch >= 'A' && ch <= 'Z') { - return NGX_ERROR; - } - - r->invalid_header = 1; - } - - r->header_hash = hash; - - state = sw_value_len; - - /* fall through */ - - case sw_value_len: - - if (end - p < NGX_SPDY_NV_VLEN_SIZE) { - break; - } - - r->lowcase_index = ngx_spdy_frame_parse_uint32(p); - - /* null-terminate header name */ - *p = '\0'; - - p += NGX_SPDY_NV_VLEN_SIZE; - - state = sw_value; - - /* fall through */ - - case sw_value: - - if ((ngx_uint_t) (end - p) < r->lowcase_index) { - break; - } - - r->header_start = p; - - while (r->lowcase_index--) { - ch = *p; - - if (ch == '\0') { - - if (p == r->header_start) { - return NGX_ERROR; - } - - r->header_end = p; - r->header_in->pos = p + 1; - - r->state = sw_value; - - return NGX_OK; - } - - if (ch == CR || ch == LF) { - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "client sent header \"%*s\" with " - "invalid value: \"%*s\\%c...\"", - r->header_name_end - r->header_name_start, - r->header_name_start, - p - r->header_start, - r->header_start, - ch == CR ? 'r' : 'n'); - - return NGX_HTTP_PARSE_INVALID_HEADER; - } - - p++; - } - - r->header_end = p; - r->header_in->pos = p; - - r->state = 0; - - return NGX_DONE; - } - - r->header_in->pos = p; - r->state = state; - - return NGX_AGAIN; -} - - -static ngx_int_t -ngx_http_spdy_alloc_large_header_buffer(ngx_http_request_t *r) -{ - u_char *old, *new, *p; - size_t rest; - ngx_buf_t *buf; - ngx_http_spdy_stream_t *stream; - ngx_http_core_srv_conf_t *cscf; - - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "spdy alloc large header buffer"); - - stream = r->spdy_stream; - - cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); - - if (stream->header_buffers - == (ngx_uint_t) cscf->large_client_header_buffers.num) - { - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "client sent too large request"); - - return NGX_DECLINED; - } - - rest = r->header_in->last - r->header_in->pos; - - /* - * One more byte is needed for null-termination - * and another one for further progress. - */ - if (rest > cscf->large_client_header_buffers.size - 2) { - p = r->header_in->pos; - - if (rest > NGX_MAX_ERROR_STR - 300) { - rest = NGX_MAX_ERROR_STR - 300; - } - - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "client sent too long header name or value: \"%*s...\"", - rest, p); - - return NGX_DECLINED; - } - - buf = ngx_create_temp_buf(r->pool, cscf->large_client_header_buffers.size); - if (buf == NULL) { - return NGX_ERROR; - } - - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "spdy large header alloc: %p %uz", - buf->pos, buf->end - buf->last); - - old = r->header_in->pos; - new = buf->pos; - - if (rest) { - buf->last = ngx_cpymem(new, old, rest); - } - - r->header_in = buf; - - stream->header_buffers++; - - return NGX_OK; -} - - -static ngx_int_t -ngx_http_spdy_handle_request_header(ngx_http_request_t *r) -{ - ngx_uint_t i; - ngx_table_elt_t *h; - ngx_http_core_srv_conf_t *cscf; - ngx_http_spdy_request_header_t *sh; - - if (r->invalid_header) { - cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); - - if (cscf->ignore_invalid_headers) { - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "client sent invalid header: \"%*s\"", - r->header_end - r->header_name_start, - r->header_name_start); - return NGX_OK; - } - - } - - if (r->header_name_start[0] == ':') { - r->header_name_start++; - - for (i = 0; i < NGX_SPDY_REQUEST_HEADERS; i++) { - sh = &ngx_http_spdy_request_headers[i]; - - if (sh->hash != r->header_hash - || sh->len != r->header_name_end - r->header_name_start - || ngx_strncmp(sh->header, r->header_name_start, sh->len) != 0) - { - continue; - } - - return sh->handler(r); - } - - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "client sent invalid header name: \":%*s\"", - r->header_end - r->header_name_start, - r->header_name_start); - - return NGX_HTTP_PARSE_INVALID_HEADER; - } - - h = ngx_list_push(&r->headers_in.headers); - if (h == NULL) { - return NGX_ERROR; - } - - h->hash = r->header_hash; - - h->key.len = r->header_name_end - r->header_name_start; - h->key.data = r->header_name_start; - - h->value.len = r->header_end - r->header_start; - h->value.data = r->header_start; - - h->lowcase_key = h->key.data; - - return NGX_OK; -} - - -void -ngx_http_spdy_request_headers_init(void) -{ - ngx_uint_t i; - ngx_http_spdy_request_header_t *h; - - for (i = 0; i < NGX_SPDY_REQUEST_HEADERS; i++) { - h = &ngx_http_spdy_request_headers[i]; - h->hash = ngx_hash_key(h->header, h->len); - } -} - - -static ngx_int_t -ngx_http_spdy_parse_method(ngx_http_request_t *r) -{ - size_t k, len; - ngx_uint_t n; - const u_char *p, *m; - - /* - * This array takes less than 256 sequential bytes, - * and if typical CPU cache line size is 64 bytes, - * it is prefetched for 4 load operations. - */ - static const struct { - u_char len; - const u_char method[11]; - uint32_t value; - } tests[] = { - { 3, "GET", NGX_HTTP_GET }, - { 4, "POST", NGX_HTTP_POST }, - { 4, "HEAD", NGX_HTTP_HEAD }, - { 7, "OPTIONS", NGX_HTTP_OPTIONS }, - { 8, "PROPFIND", NGX_HTTP_PROPFIND }, - { 3, "PUT", NGX_HTTP_PUT }, - { 5, "MKCOL", NGX_HTTP_MKCOL }, - { 6, "DELETE", NGX_HTTP_DELETE }, - { 4, "COPY", NGX_HTTP_COPY }, - { 4, "MOVE", NGX_HTTP_MOVE }, - { 9, "PROPPATCH", NGX_HTTP_PROPPATCH }, - { 4, "LOCK", NGX_HTTP_LOCK }, - { 6, "UNLOCK", NGX_HTTP_UNLOCK }, - { 5, "PATCH", NGX_HTTP_PATCH }, - { 5, "TRACE", NGX_HTTP_TRACE } - }, *test; - - if (r->method_name.len) { - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "client sent duplicate :method header"); - - return NGX_HTTP_PARSE_INVALID_HEADER; - } - - len = r->header_end - r->header_start; - - r->method_name.len = len; - r->method_name.data = r->header_start; - - test = tests; - n = sizeof(tests) / sizeof(tests[0]); - - do { - if (len == test->len) { - p = r->method_name.data; - m = test->method; - k = len; - - do { - if (*p++ != *m++) { - goto next; - } - } while (--k); - - r->method = test->value; - return NGX_OK; - } - - next: - test++; - - } while (--n); - - p = r->method_name.data; - - do { - if ((*p < 'A' || *p > 'Z') && *p != '_') { - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "client sent invalid method: \"%V\"", - &r->method_name); - - return NGX_HTTP_PARSE_INVALID_HEADER; - } - - p++; - - } while (--len); - - return NGX_OK; -} - - -static ngx_int_t -ngx_http_spdy_parse_scheme(ngx_http_request_t *r) -{ - if (r->schema_start) { - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "client sent duplicate :schema header"); - - return NGX_HTTP_PARSE_INVALID_HEADER; - } - - r->schema_start = r->header_start; - r->schema_end = r->header_end; - - return NGX_OK; -} - - -static ngx_int_t -ngx_http_spdy_parse_host(ngx_http_request_t *r) -{ - ngx_table_elt_t *h; - - if (r->headers_in.host) { - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "client sent duplicate :host header"); - - return NGX_HTTP_PARSE_INVALID_HEADER; - } - - h = ngx_list_push(&r->headers_in.headers); - if (h == NULL) { - return NGX_ERROR; - } - - r->headers_in.host = h; - - h->hash = r->header_hash; - - h->key.len = r->header_name_end - r->header_name_start; - h->key.data = r->header_name_start; - - h->value.len = r->header_end - r->header_start; - h->value.data = r->header_start; - - h->lowcase_key = h->key.data; - - return NGX_OK; -} - - -static ngx_int_t -ngx_http_spdy_parse_path(ngx_http_request_t *r) -{ - if (r->unparsed_uri.len) { - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "client sent duplicate :path header"); - - return NGX_HTTP_PARSE_INVALID_HEADER; - } - - r->uri_start = r->header_start; - r->uri_end = r->header_end; - - if (ngx_http_parse_uri(r) != NGX_OK) { - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "client sent invalid URI: \"%*s\"", - r->uri_end - r->uri_start, r->uri_start); - - return NGX_HTTP_PARSE_INVALID_HEADER; - } - - if (ngx_http_process_request_uri(r) != NGX_OK) { - /* - * request has been finalized already - * in ngx_http_process_request_uri() - */ - return NGX_ABORT; - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_http_spdy_parse_version(ngx_http_request_t *r) -{ - u_char *p, ch; - - if (r->http_protocol.len) { - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "client sent duplicate :version header"); - - return NGX_HTTP_PARSE_INVALID_HEADER; - } - - p = r->header_start; - - if (r->header_end - p < 8 || !(ngx_str5cmp(p, 'H', 'T', 'T', 'P', '/'))) { - goto invalid; - } - - ch = *(p + 5); - - if (ch < '1' || ch > '9') { - goto invalid; - } - - r->http_major = ch - '0'; - - for (p += 6; p != r->header_end - 2; p++) { - - ch = *p; - - if (ch == '.') { - break; - } - - if (ch < '0' || ch > '9') { - goto invalid; - } - - r->http_major = r->http_major * 10 + ch - '0'; - } - - if (*p != '.') { - goto invalid; - } - - ch = *(p + 1); - - if (ch < '0' || ch > '9') { - goto invalid; - } - - r->http_minor = ch - '0'; - - for (p += 2; p != r->header_end; p++) { - - ch = *p; - - if (ch < '0' || ch > '9') { - goto invalid; - } - - r->http_minor = r->http_minor * 10 + ch - '0'; - } - - r->http_protocol.len = r->header_end - r->header_start; - r->http_protocol.data = r->header_start; - r->http_version = r->http_major * 1000 + r->http_minor; - - return NGX_OK; - -invalid: - - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "client sent invalid http version: \"%*s\"", - r->header_end - r->header_start, r->header_start); - - return NGX_HTTP_PARSE_INVALID_HEADER; -} - - -static ngx_int_t -ngx_http_spdy_construct_request_line(ngx_http_request_t *r) -{ - u_char *p; - - if (r->method_name.len == 0 - || r->unparsed_uri.len == 0 - || r->http_protocol.len == 0) - { - ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); - return NGX_ERROR; - } - - r->request_line.len = r->method_name.len + 1 - + r->unparsed_uri.len + 1 - + r->http_protocol.len; - - p = ngx_pnalloc(r->pool, r->request_line.len + 1); - if (p == NULL) { - ngx_http_spdy_close_stream(r->spdy_stream, - NGX_HTTP_INTERNAL_SERVER_ERROR); - return NGX_ERROR; - } - - r->request_line.data = p; - - p = ngx_cpymem(p, r->method_name.data, r->method_name.len); - - *p++ = ' '; - - p = ngx_cpymem(p, r->unparsed_uri.data, r->unparsed_uri.len); - - *p++ = ' '; - - ngx_memcpy(p, r->http_protocol.data, r->http_protocol.len + 1); - - /* some modules expect the space character after method name */ - r->method_name.data = r->request_line.data; - - return NGX_OK; -} - - -static void -ngx_http_spdy_run_request(ngx_http_request_t *r) -{ - ngx_uint_t i; - ngx_list_part_t *part; - ngx_table_elt_t *h; - ngx_http_header_t *hh; - ngx_http_core_main_conf_t *cmcf; - - if (ngx_http_spdy_construct_request_line(r) != NGX_OK) { - return; - } - - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "spdy http request line: \"%V\"", &r->request_line); - - cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); - - part = &r->headers_in.headers.part; - h = part->elts; - - for (i = 0 ;; i++) { - - if (i >= part->nelts) { - if (part->next == NULL) { - break; - } - - part = part->next; - h = part->elts; - i = 0; - } - - hh = ngx_hash_find(&cmcf->headers_in_hash, h[i].hash, - h[i].lowcase_key, h[i].key.len); - - if (hh && hh->handler(r, &h[i], hh->offset) != NGX_OK) { - return; - } - - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "spdy http header: \"%V: %V\"", &h[i].key, &h[i].value); - } - - r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE; - - if (ngx_http_process_request_header(r) != NGX_OK) { - return; - } - - if (r->headers_in.content_length_n > 0 && r->spdy_stream->in_closed) { - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "client prematurely closed stream"); - - r->spdy_stream->skip_data = NGX_SPDY_DATA_ERROR; - - ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); - return; - } - - ngx_http_process_request(r); -} - - -static ngx_int_t -ngx_http_spdy_init_request_body(ngx_http_request_t *r) -{ - ngx_buf_t *buf; - ngx_temp_file_t *tf; - ngx_http_request_body_t *rb; - ngx_http_core_loc_conf_t *clcf; - - rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t)); - if (rb == NULL) { - return NGX_ERROR; - } - - r->request_body = rb; - - if (r->spdy_stream->in_closed) { - return NGX_OK; - } - - rb->rest = r->headers_in.content_length_n; - - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - - if (r->request_body_in_file_only - || rb->rest > (off_t) clcf->client_body_buffer_size - || rb->rest < 0) - { - tf = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t)); - if (tf == NULL) { - return NGX_ERROR; - } - - tf->file.fd = NGX_INVALID_FILE; - tf->file.log = r->connection->log; - tf->path = clcf->client_body_temp_path; - tf->pool = r->pool; - tf->warn = "a client request body is buffered to a temporary file"; - tf->log_level = r->request_body_file_log_level; - tf->persistent = r->request_body_in_persistent_file; - tf->clean = r->request_body_in_clean_file; - - if (r->request_body_file_group_access) { - tf->access = 0660; - } - - rb->temp_file = tf; - - if (r->spdy_stream->in_closed - && ngx_create_temp_file(&tf->file, tf->path, tf->pool, - tf->persistent, tf->clean, tf->access) - != NGX_OK) - { - return NGX_ERROR; - } - - buf = ngx_calloc_buf(r->pool); - if (buf == NULL) { - return NGX_ERROR; - } - - } else { - - if (rb->rest == 0) { - return NGX_OK; - } - - buf = ngx_create_temp_buf(r->pool, (size_t) rb->rest); - if (buf == NULL) { - return NGX_ERROR; - } - } - - rb->buf = buf; - - rb->bufs = ngx_alloc_chain_link(r->pool); - if (rb->bufs == NULL) { - return NGX_ERROR; - } - - rb->bufs->buf = buf; - rb->bufs->next = NULL; - - rb->rest = 0; - - return NGX_OK; -} - - -ngx_int_t -ngx_http_spdy_read_request_body(ngx_http_request_t *r, - ngx_http_client_body_handler_pt post_handler) -{ - ngx_http_spdy_stream_t *stream; - - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "spdy read request body"); - - stream = r->spdy_stream; - - switch (stream->skip_data) { - - case NGX_SPDY_DATA_DISCARD: - post_handler(r); - return NGX_OK; - - case NGX_SPDY_DATA_ERROR: - if (r->headers_in.content_length_n == -1) { - return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE; - } else { - return NGX_HTTP_BAD_REQUEST; - } - - case NGX_SPDY_DATA_INTERNAL_ERROR: - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - if (!r->request_body && ngx_http_spdy_init_request_body(r) != NGX_OK) { - stream->skip_data = NGX_SPDY_DATA_INTERNAL_ERROR; - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - if (stream->in_closed) { - post_handler(r); - return NGX_OK; - } - - r->request_body->post_handler = post_handler; - - r->read_event_handler = ngx_http_test_reading; - r->write_event_handler = ngx_http_request_empty_handler; - - return NGX_AGAIN; -} - - -static ngx_int_t -ngx_http_spdy_terminate_stream(ngx_http_spdy_connection_t *sc, - ngx_http_spdy_stream_t *stream, ngx_uint_t status) -{ - ngx_event_t *rev; - ngx_connection_t *fc; - - if (ngx_http_spdy_send_rst_stream(sc, stream->id, status, - NGX_SPDY_HIGHEST_PRIORITY) - == NGX_ERROR) - { - return NGX_ERROR; - } - - stream->out_closed = 1; - - fc = stream->request->connection; - fc->error = 1; - - rev = fc->read; - rev->handler(rev); - - return NGX_OK; -} - - -static void -ngx_http_spdy_close_stream_handler(ngx_event_t *ev) -{ - ngx_connection_t *fc; - ngx_http_request_t *r; - - fc = ev->data; - r = fc->data; - - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "spdy close stream handler"); - - ngx_http_spdy_close_stream(r->spdy_stream, 0); -} - - -void -ngx_http_spdy_close_stream(ngx_http_spdy_stream_t *stream, ngx_int_t rc) -{ - ngx_event_t *ev; - ngx_connection_t *fc; - ngx_http_spdy_stream_t **index, *s; - ngx_http_spdy_srv_conf_t *sscf; - ngx_http_spdy_connection_t *sc; - - sc = stream->connection; - - ngx_log_debug3(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, - "spdy close stream %ui, queued %ui, processing %ui", - stream->id, stream->queued, sc->processing); - - fc = stream->request->connection; - - if (stream->queued) { - fc->write->handler = ngx_http_spdy_close_stream_handler; - return; - } - - if (!stream->out_closed) { - if (ngx_http_spdy_send_rst_stream(sc, stream->id, - NGX_SPDY_INTERNAL_ERROR, - stream->priority) - != NGX_OK) - { - sc->connection->error = 1; - } - } - - if (sc->stream == stream) { - sc->stream = NULL; - } - - sscf = ngx_http_get_module_srv_conf(sc->http_connection->conf_ctx, - ngx_http_spdy_module); - - index = sc->streams_index + ngx_http_spdy_stream_index(sscf, stream->id); - - for ( ;; ) { - s = *index; - - if (s == NULL) { - break; - } - - if (s == stream) { - *index = s->index; - break; - } - - index = &s->index; - } - - ngx_http_free_request(stream->request, rc); - - ev = fc->read; - - if (ev->active || ev->disabled) { - ngx_log_error(NGX_LOG_ALERT, sc->connection->log, 0, - "fake read event was activated"); - } - - if (ev->timer_set) { - ngx_del_timer(ev); - } - - if (ev->posted) { - ngx_delete_posted_event(ev); - } - - ev = fc->write; - - if (ev->active || ev->disabled) { - ngx_log_error(NGX_LOG_ALERT, sc->connection->log, 0, - "fake write event was activated"); - } - - if (ev->timer_set) { - ngx_del_timer(ev); - } - - if (ev->posted) { - ngx_delete_posted_event(ev); - } - - fc->data = sc->free_fake_connections; - sc->free_fake_connections = fc; - - sc->processing--; - - if (sc->processing || sc->blocked) { - return; - } - - ev = sc->connection->read; - - ev->handler = ngx_http_spdy_handle_connection_handler; - ngx_post_event(ev, &ngx_posted_events); -} - - -static void -ngx_http_spdy_handle_connection_handler(ngx_event_t *rev) -{ - ngx_connection_t *c; - - rev->handler = ngx_http_spdy_read_handler; - - if (rev->ready) { - ngx_http_spdy_read_handler(rev); - return; - } - - c = rev->data; - - ngx_http_spdy_handle_connection(c->data); -} - - -static void -ngx_http_spdy_keepalive_handler(ngx_event_t *rev) -{ - ngx_connection_t *c; - ngx_http_spdy_srv_conf_t *sscf; - ngx_http_spdy_connection_t *sc; - - c = rev->data; - - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "spdy keepalive handler"); - - if (rev->timedout || c->close) { - ngx_http_close_connection(c); - return; - } - -#if (NGX_HAVE_KQUEUE) - - if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { - if (rev->pending_eof) { - c->log->handler = NULL; - ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno, - "kevent() reported that client %V closed " - "keepalive connection", &c->addr_text); -#if (NGX_HTTP_SSL) - if (c->ssl) { - c->ssl->no_send_shutdown = 1; - } -#endif - ngx_http_close_connection(c); - return; - } - } - -#endif - - c->destroyed = 0; - c->idle = 0; - ngx_reusable_connection(c, 0); - - sc = c->data; - - sscf = ngx_http_get_module_srv_conf(sc->http_connection->conf_ctx, - ngx_http_spdy_module); - - sc->pool = ngx_create_pool(sscf->pool_size, sc->connection->log); - if (sc->pool == NULL) { - ngx_http_close_connection(c); - return; - } - - sc->streams_index = ngx_pcalloc(sc->pool, - ngx_http_spdy_streams_index_size(sscf) - * sizeof(ngx_http_spdy_stream_t *)); - if (sc->streams_index == NULL) { - ngx_http_close_connection(c); - return; - } - - c->write->handler = ngx_http_spdy_write_handler; - - rev->handler = ngx_http_spdy_read_handler; - ngx_http_spdy_read_handler(rev); -} - - -static void -ngx_http_spdy_finalize_connection(ngx_http_spdy_connection_t *sc, - ngx_int_t rc) -{ - ngx_uint_t i, size; - ngx_event_t *ev; - ngx_connection_t *c, *fc; - ngx_http_request_t *r; - ngx_http_spdy_stream_t *stream; - ngx_http_spdy_srv_conf_t *sscf; - - c = sc->connection; - - if (!sc->processing) { - ngx_http_close_connection(c); - return; - } - - c->error = 1; - c->read->handler = ngx_http_empty_handler; - c->write->handler = ngx_http_empty_handler; - - sc->last_out = NULL; - - sc->blocked = 1; - - sscf = ngx_http_get_module_srv_conf(sc->http_connection->conf_ctx, - ngx_http_spdy_module); - - size = ngx_http_spdy_streams_index_size(sscf); - - for (i = 0; i < size; i++) { - stream = sc->streams_index[i]; - - while (stream) { - stream->handled = 0; - - r = stream->request; - fc = r->connection; - - fc->error = 1; - - if (stream->queued) { - stream->queued = 0; - - ev = fc->write; - ev->delayed = 0; - - } else { - ev = fc->read; - } - - stream = stream->index; - - ev->eof = 1; - ev->handler(ev); - } - } - - sc->blocked = 0; - - if (sc->processing) { - return; - } - - ngx_http_close_connection(c); -} - - -static ngx_int_t -ngx_http_spdy_adjust_windows(ngx_http_spdy_connection_t *sc, ssize_t delta) -{ - ngx_uint_t i, size; - ngx_event_t *wev; - ngx_http_spdy_stream_t *stream, *sn; - ngx_http_spdy_srv_conf_t *sscf; - - sscf = ngx_http_get_module_srv_conf(sc->http_connection->conf_ctx, - ngx_http_spdy_module); - - size = ngx_http_spdy_streams_index_size(sscf); - - for (i = 0; i < size; i++) { - - for (stream = sc->streams_index[i]; stream; stream = sn) { - sn = stream->index; - - if (delta > 0 - && stream->send_window - > (ssize_t) (NGX_SPDY_MAX_WINDOW - delta)) - { - if (ngx_http_spdy_terminate_stream(sc, stream, - NGX_SPDY_FLOW_CONTROL_ERROR) - == NGX_ERROR) - { - return NGX_ERROR; - } - - continue; - } - - stream->send_window += delta; - - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, - "spdy:%ui adjust window:%z", - stream->id, stream->send_window); - - if (stream->send_window > 0 && stream->exhausted) { - stream->exhausted = 0; - - wev = stream->request->connection->write; - - if (!wev->timer_set) { - wev->delayed = 0; - wev->handler(wev); - } - } - } - } - - return NGX_OK; -} - - -static void -ngx_http_spdy_pool_cleanup(void *data) -{ - ngx_http_spdy_connection_t *sc = data; - - if (sc->pool) { - ngx_destroy_pool(sc->pool); - } -} - - -static void * -ngx_http_spdy_zalloc(void *opaque, u_int items, u_int size) -{ - ngx_http_spdy_connection_t *sc = opaque; - - return ngx_palloc(sc->connection->pool, items * size); -} - - -static void -ngx_http_spdy_zfree(void *opaque, void *address) -{ -#if 0 - ngx_http_spdy_connection_t *sc = opaque; - - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, - "spdy zfree: %p", address); -#endif -} diff --git a/src/http/ngx_http_spdy.h b/src/http/ngx_http_spdy.h deleted file mode 100644 index df24495..0000000 --- a/src/http/ngx_http_spdy.h +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright (C) Nginx, Inc. - * Copyright (C) Valentin V. Bartenev - */ - - -#ifndef _NGX_HTTP_SPDY_H_INCLUDED_ -#define _NGX_HTTP_SPDY_H_INCLUDED_ - - -#include -#include -#include - -#include - - -#define NGX_SPDY_VERSION 3 - -#define NGX_SPDY_NPN_ADVERTISE "\x08spdy/3.1" -#define NGX_SPDY_NPN_NEGOTIATED "spdy/3.1" - -#define NGX_SPDY_STATE_BUFFER_SIZE 16 - -#define NGX_SPDY_CTL_BIT 1 - -#define NGX_SPDY_SYN_STREAM 1 -#define NGX_SPDY_SYN_REPLY 2 -#define NGX_SPDY_RST_STREAM 3 -#define NGX_SPDY_SETTINGS 4 -#define NGX_SPDY_PING 6 -#define NGX_SPDY_GOAWAY 7 -#define NGX_SPDY_HEADERS 8 -#define NGX_SPDY_WINDOW_UPDATE 9 - -#define NGX_SPDY_FRAME_HEADER_SIZE 8 - -#define NGX_SPDY_SID_SIZE 4 -#define NGX_SPDY_DELTA_SIZE 4 - -#define NGX_SPDY_SYN_STREAM_SIZE 10 -#define NGX_SPDY_SYN_REPLY_SIZE 4 -#define NGX_SPDY_RST_STREAM_SIZE 8 -#define NGX_SPDY_PING_SIZE 4 -#define NGX_SPDY_GOAWAY_SIZE 8 -#define NGX_SPDY_WINDOW_UPDATE_SIZE 8 -#define NGX_SPDY_NV_NUM_SIZE 4 -#define NGX_SPDY_NV_NLEN_SIZE 4 -#define NGX_SPDY_NV_VLEN_SIZE 4 -#define NGX_SPDY_SETTINGS_NUM_SIZE 4 -#define NGX_SPDY_SETTINGS_FID_SIZE 4 -#define NGX_SPDY_SETTINGS_VAL_SIZE 4 - -#define NGX_SPDY_SETTINGS_PAIR_SIZE \ - (NGX_SPDY_SETTINGS_FID_SIZE + NGX_SPDY_SETTINGS_VAL_SIZE) - -#define NGX_SPDY_HIGHEST_PRIORITY 0 -#define NGX_SPDY_LOWEST_PRIORITY 7 - -#define NGX_SPDY_FLAG_FIN 0x01 -#define NGX_SPDY_FLAG_UNIDIRECTIONAL 0x02 -#define NGX_SPDY_FLAG_CLEAR_SETTINGS 0x01 - -#define NGX_SPDY_MAX_FRAME_SIZE ((1 << 24) - 1) - -#define NGX_SPDY_DATA_DISCARD 1 -#define NGX_SPDY_DATA_ERROR 2 -#define NGX_SPDY_DATA_INTERNAL_ERROR 3 - - -typedef struct ngx_http_spdy_connection_s ngx_http_spdy_connection_t; -typedef struct ngx_http_spdy_out_frame_s ngx_http_spdy_out_frame_t; - - -typedef u_char *(*ngx_http_spdy_handler_pt) (ngx_http_spdy_connection_t *sc, - u_char *pos, u_char *end); - -struct ngx_http_spdy_connection_s { - ngx_connection_t *connection; - ngx_http_connection_t *http_connection; - - ngx_uint_t processing; - - size_t send_window; - size_t recv_window; - size_t init_window; - - ngx_queue_t waiting; - - u_char buffer[NGX_SPDY_STATE_BUFFER_SIZE]; - size_t buffer_used; - ngx_http_spdy_handler_pt handler; - - z_stream zstream_in; - z_stream zstream_out; - - ngx_pool_t *pool; - - ngx_http_spdy_out_frame_t *free_ctl_frames; - ngx_connection_t *free_fake_connections; - - ngx_http_spdy_stream_t **streams_index; - - ngx_http_spdy_out_frame_t *last_out; - - ngx_queue_t posted; - - ngx_http_spdy_stream_t *stream; - - ngx_uint_t entries; - size_t length; - u_char flags; - - ngx_uint_t last_sid; - - unsigned blocked:1; - unsigned incomplete:1; -}; - - -struct ngx_http_spdy_stream_s { - ngx_uint_t id; - ngx_http_request_t *request; - ngx_http_spdy_connection_t *connection; - ngx_http_spdy_stream_t *index; - - ngx_uint_t header_buffers; - ngx_uint_t queued; - - /* - * A change to SETTINGS_INITIAL_WINDOW_SIZE could cause the - * send_window to become negative, hence it's signed. - */ - ssize_t send_window; - size_t recv_window; - - ngx_http_spdy_out_frame_t *free_frames; - ngx_chain_t *free_data_headers; - ngx_chain_t *free_bufs; - - ngx_queue_t queue; - - unsigned priority:3; - unsigned handled:1; - unsigned blocked:1; - unsigned exhausted:1; - unsigned in_closed:1; - unsigned out_closed:1; - unsigned skip_data:2; -}; - - -struct ngx_http_spdy_out_frame_s { - ngx_http_spdy_out_frame_t *next; - ngx_chain_t *first; - ngx_chain_t *last; - ngx_int_t (*handler)(ngx_http_spdy_connection_t *sc, - ngx_http_spdy_out_frame_t *frame); - - ngx_http_spdy_stream_t *stream; - size_t length; - - ngx_uint_t priority; - unsigned blocked:1; - unsigned fin:1; -}; - - -static ngx_inline void -ngx_http_spdy_queue_frame(ngx_http_spdy_connection_t *sc, - ngx_http_spdy_out_frame_t *frame) -{ - ngx_http_spdy_out_frame_t **out; - - for (out = &sc->last_out; *out; out = &(*out)->next) - { - /* - * NB: higher values represent lower priorities. - */ - if (frame->priority >= (*out)->priority) { - break; - } - } - - frame->next = *out; - *out = frame; -} - - -static ngx_inline void -ngx_http_spdy_queue_blocked_frame(ngx_http_spdy_connection_t *sc, - ngx_http_spdy_out_frame_t *frame) -{ - ngx_http_spdy_out_frame_t **out; - - for (out = &sc->last_out; *out; out = &(*out)->next) - { - if ((*out)->blocked) { - break; - } - } - - frame->next = *out; - *out = frame; -} - - -void ngx_http_spdy_init(ngx_event_t *rev); -void ngx_http_spdy_request_headers_init(void); - -ngx_int_t ngx_http_spdy_read_request_body(ngx_http_request_t *r, - ngx_http_client_body_handler_pt post_handler); - -void ngx_http_spdy_close_stream(ngx_http_spdy_stream_t *stream, ngx_int_t rc); - -ngx_int_t ngx_http_spdy_send_output_queue(ngx_http_spdy_connection_t *sc); - - -#define ngx_spdy_frame_aligned_write_uint16(p, s) \ - (*(uint16_t *) (p) = htons((uint16_t) (s)), (p) + sizeof(uint16_t)) - -#define ngx_spdy_frame_aligned_write_uint32(p, s) \ - (*(uint32_t *) (p) = htonl((uint32_t) (s)), (p) + sizeof(uint32_t)) - -#if (NGX_HAVE_NONALIGNED) - -#define ngx_spdy_frame_write_uint16 ngx_spdy_frame_aligned_write_uint16 -#define ngx_spdy_frame_write_uint32 ngx_spdy_frame_aligned_write_uint32 - -#else - -#define ngx_spdy_frame_write_uint16(p, s) \ - ((p)[0] = (u_char) ((s) >> 8), \ - (p)[1] = (u_char) (s), \ - (p) + sizeof(uint16_t)) - -#define ngx_spdy_frame_write_uint32(p, s) \ - ((p)[0] = (u_char) ((s) >> 24), \ - (p)[1] = (u_char) ((s) >> 16), \ - (p)[2] = (u_char) ((s) >> 8), \ - (p)[3] = (u_char) (s), \ - (p) + sizeof(uint32_t)) - -#endif - - -#define ngx_spdy_ctl_frame_head(t) \ - ((uint32_t) NGX_SPDY_CTL_BIT << 31 | NGX_SPDY_VERSION << 16 | (t)) - -#define ngx_spdy_frame_write_head(p, t) \ - ngx_spdy_frame_aligned_write_uint32(p, ngx_spdy_ctl_frame_head(t)) - -#define ngx_spdy_frame_write_flags_and_len(p, f, l) \ - ngx_spdy_frame_aligned_write_uint32(p, (f) << 24 | (l)) -#define ngx_spdy_frame_write_flags_and_id(p, f, i) \ - ngx_spdy_frame_aligned_write_uint32(p, (f) << 24 | (i)) - -#define ngx_spdy_frame_write_sid ngx_spdy_frame_aligned_write_uint32 -#define ngx_spdy_frame_write_window ngx_spdy_frame_aligned_write_uint32 - -#endif /* _NGX_HTTP_SPDY_H_INCLUDED_ */ diff --git a/src/http/ngx_http_spdy_filter_module.c b/src/http/ngx_http_spdy_filter_module.c deleted file mode 100644 index 377e935..0000000 --- a/src/http/ngx_http_spdy_filter_module.c +++ /dev/null @@ -1,1222 +0,0 @@ - -/* - * Copyright (C) Nginx, Inc. - * Copyright (C) Valentin V. Bartenev - */ - - -#include -#include -#include -#include -#include - -#include - - -#define ngx_http_spdy_nv_nsize(h) (NGX_SPDY_NV_NLEN_SIZE + sizeof(h) - 1) -#define ngx_http_spdy_nv_vsize(h) (NGX_SPDY_NV_VLEN_SIZE + sizeof(h) - 1) - -#define ngx_http_spdy_nv_write_num ngx_spdy_frame_write_uint32 -#define ngx_http_spdy_nv_write_nlen ngx_spdy_frame_write_uint32 -#define ngx_http_spdy_nv_write_vlen ngx_spdy_frame_write_uint32 - -#define ngx_http_spdy_nv_write_name(p, h) \ - ngx_cpymem(ngx_http_spdy_nv_write_nlen(p, sizeof(h) - 1), h, sizeof(h) - 1) - -#define ngx_http_spdy_nv_write_val(p, h) \ - ngx_cpymem(ngx_http_spdy_nv_write_vlen(p, sizeof(h) - 1), h, sizeof(h) - 1) - - -static ngx_chain_t *ngx_http_spdy_send_chain(ngx_connection_t *fc, - ngx_chain_t *in, off_t limit); - -static ngx_inline ngx_int_t ngx_http_spdy_filter_send( - ngx_connection_t *fc, ngx_http_spdy_stream_t *stream); -static ngx_inline ngx_int_t ngx_http_spdy_flow_control( - ngx_http_spdy_connection_t *sc, ngx_http_spdy_stream_t *stream); -static void ngx_http_spdy_waiting_queue(ngx_http_spdy_connection_t *sc, - ngx_http_spdy_stream_t *stream); - -static ngx_chain_t *ngx_http_spdy_filter_get_shadow( - ngx_http_spdy_stream_t *stream, ngx_buf_t *buf, off_t offset, off_t size); -static ngx_http_spdy_out_frame_t *ngx_http_spdy_filter_get_data_frame( - ngx_http_spdy_stream_t *stream, size_t len, ngx_chain_t *first, - ngx_chain_t *last); - -static ngx_int_t ngx_http_spdy_syn_frame_handler( - ngx_http_spdy_connection_t *sc, ngx_http_spdy_out_frame_t *frame); -static ngx_int_t ngx_http_spdy_data_frame_handler( - ngx_http_spdy_connection_t *sc, ngx_http_spdy_out_frame_t *frame); -static ngx_inline void ngx_http_spdy_handle_frame( - ngx_http_spdy_stream_t *stream, ngx_http_spdy_out_frame_t *frame); -static ngx_inline void ngx_http_spdy_handle_stream( - ngx_http_spdy_connection_t *sc, ngx_http_spdy_stream_t *stream); - -static void ngx_http_spdy_filter_cleanup(void *data); - -static ngx_int_t ngx_http_spdy_filter_init(ngx_conf_t *cf); - - -static ngx_http_module_t ngx_http_spdy_filter_module_ctx = { - NULL, /* preconfiguration */ - ngx_http_spdy_filter_init, /* postconfiguration */ - - NULL, /* create main configuration */ - NULL, /* init main configuration */ - - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - - NULL, /* create location configuration */ - NULL /* merge location configuration */ -}; - - -ngx_module_t ngx_http_spdy_filter_module = { - NGX_MODULE_V1, - &ngx_http_spdy_filter_module_ctx, /* module context */ - NULL, /* 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_http_output_header_filter_pt ngx_http_next_header_filter; - - -static ngx_int_t -ngx_http_spdy_header_filter(ngx_http_request_t *r) -{ - int rc; - size_t len; - u_char *p, *buf, *last; - ngx_buf_t *b; - ngx_str_t host; - ngx_uint_t i, j, count, port; - ngx_chain_t *cl; - ngx_list_part_t *part, *pt; - ngx_table_elt_t *header, *h; - ngx_connection_t *c; - ngx_http_cleanup_t *cln; - ngx_http_core_loc_conf_t *clcf; - ngx_http_core_srv_conf_t *cscf; - ngx_http_spdy_stream_t *stream; - ngx_http_spdy_out_frame_t *frame; - ngx_http_spdy_connection_t *sc; - struct sockaddr_in *sin; -#if (NGX_HAVE_INET6) - struct sockaddr_in6 *sin6; -#endif - u_char addr[NGX_SOCKADDR_STRLEN]; - - if (!r->spdy_stream) { - return ngx_http_next_header_filter(r); - } - - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "spdy header filter"); - - if (r->header_sent) { - return NGX_OK; - } - - r->header_sent = 1; - - if (r != r->main) { - return NGX_OK; - } - - c = r->connection; - - if (r->method == NGX_HTTP_HEAD) { - r->header_only = 1; - } - - switch (r->headers_out.status) { - - case NGX_HTTP_OK: - case NGX_HTTP_PARTIAL_CONTENT: - break; - - case NGX_HTTP_NOT_MODIFIED: - r->header_only = 1; - break; - - case NGX_HTTP_NO_CONTENT: - r->header_only = 1; - - ngx_str_null(&r->headers_out.content_type); - - r->headers_out.content_length = NULL; - r->headers_out.content_length_n = -1; - - /* fall through */ - - default: - r->headers_out.last_modified_time = -1; - r->headers_out.last_modified = NULL; - } - - len = NGX_SPDY_NV_NUM_SIZE - + ngx_http_spdy_nv_nsize(":version") - + ngx_http_spdy_nv_vsize("HTTP/1.1") - + ngx_http_spdy_nv_nsize(":status") - + (r->headers_out.status_line.len - ? NGX_SPDY_NV_VLEN_SIZE + r->headers_out.status_line.len - : ngx_http_spdy_nv_vsize("418")); - - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - - if (r->headers_out.server == NULL) { - len += ngx_http_spdy_nv_nsize("server"); - len += clcf->server_tokens ? ngx_http_spdy_nv_vsize(NGINX_VER) - : ngx_http_spdy_nv_vsize("nginx"); - } - - if (r->headers_out.date == NULL) { - len += ngx_http_spdy_nv_nsize("date") - + ngx_http_spdy_nv_vsize("Wed, 31 Dec 1986 10:00:00 GMT"); - } - - if (r->headers_out.content_type.len) { - len += ngx_http_spdy_nv_nsize("content-type") - + NGX_SPDY_NV_VLEN_SIZE + r->headers_out.content_type.len; - - if (r->headers_out.content_type_len == r->headers_out.content_type.len - && r->headers_out.charset.len) - { - len += sizeof("; charset=") - 1 + r->headers_out.charset.len; - } - } - - if (r->headers_out.content_length == NULL - && r->headers_out.content_length_n >= 0) - { - len += ngx_http_spdy_nv_nsize("content-length") - + NGX_SPDY_NV_VLEN_SIZE + NGX_OFF_T_LEN; - } - - if (r->headers_out.last_modified == NULL - && r->headers_out.last_modified_time != -1) - { - len += ngx_http_spdy_nv_nsize("last-modified") - + ngx_http_spdy_nv_vsize("Wed, 31 Dec 1986 10:00:00 GMT"); - } - - if (r->headers_out.location - && r->headers_out.location->value.len - && r->headers_out.location->value.data[0] == '/') - { - r->headers_out.location->hash = 0; - - if (clcf->server_name_in_redirect) { - cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); - host = cscf->server_name; - - } else if (r->headers_in.server.len) { - host = r->headers_in.server; - - } else { - host.len = NGX_SOCKADDR_STRLEN; - host.data = addr; - - if (ngx_connection_local_sockaddr(c, &host, 0) != NGX_OK) { - return NGX_ERROR; - } - } - - switch (c->local_sockaddr->sa_family) { - -#if (NGX_HAVE_INET6) - case AF_INET6: - sin6 = (struct sockaddr_in6 *) c->local_sockaddr; - port = ntohs(sin6->sin6_port); - break; -#endif -#if (NGX_HAVE_UNIX_DOMAIN) - case AF_UNIX: - port = 0; - break; -#endif - default: /* AF_INET */ - sin = (struct sockaddr_in *) c->local_sockaddr; - port = ntohs(sin->sin_port); - break; - } - - len += ngx_http_spdy_nv_nsize("location") - + ngx_http_spdy_nv_vsize("https://") - + host.len - + r->headers_out.location->value.len; - - if (clcf->port_in_redirect) { - -#if (NGX_HTTP_SSL) - if (c->ssl) - port = (port == 443) ? 0 : port; - else -#endif - port = (port == 80) ? 0 : port; - - } else { - port = 0; - } - - if (port) { - len += sizeof(":65535") - 1; - } - - } else { - ngx_str_null(&host); - port = 0; - } - - part = &r->headers_out.headers.part; - header = part->elts; - - for (i = 0; /* void */; i++) { - - if (i >= part->nelts) { - if (part->next == NULL) { - break; - } - - part = part->next; - header = part->elts; - i = 0; - } - - if (header[i].hash == 0) { - continue; - } - - len += NGX_SPDY_NV_NLEN_SIZE + header[i].key.len - + NGX_SPDY_NV_VLEN_SIZE + header[i].value.len; - } - - buf = ngx_alloc(len, r->pool->log); - if (buf == NULL) { - return NGX_ERROR; - } - - last = buf + NGX_SPDY_NV_NUM_SIZE; - - last = ngx_http_spdy_nv_write_name(last, ":version"); - last = ngx_http_spdy_nv_write_val(last, "HTTP/1.1"); - - last = ngx_http_spdy_nv_write_name(last, ":status"); - - if (r->headers_out.status_line.len) { - last = ngx_http_spdy_nv_write_vlen(last, - r->headers_out.status_line.len); - last = ngx_cpymem(last, r->headers_out.status_line.data, - r->headers_out.status_line.len); - } else { - last = ngx_http_spdy_nv_write_vlen(last, 3); - last = ngx_sprintf(last, "%03ui", r->headers_out.status); - } - - count = 2; - - if (r->headers_out.server == NULL) { - last = ngx_http_spdy_nv_write_name(last, "server"); - last = clcf->server_tokens - ? ngx_http_spdy_nv_write_val(last, NGINX_VER) - : ngx_http_spdy_nv_write_val(last, "nginx"); - - count++; - } - - if (r->headers_out.date == NULL) { - last = ngx_http_spdy_nv_write_name(last, "date"); - - last = ngx_http_spdy_nv_write_vlen(last, ngx_cached_http_time.len); - - last = ngx_cpymem(last, ngx_cached_http_time.data, - ngx_cached_http_time.len); - - count++; - } - - if (r->headers_out.content_type.len) { - - last = ngx_http_spdy_nv_write_name(last, "content-type"); - - p = last + NGX_SPDY_NV_VLEN_SIZE; - - last = ngx_cpymem(p, r->headers_out.content_type.data, - r->headers_out.content_type.len); - - if (r->headers_out.content_type_len == r->headers_out.content_type.len - && r->headers_out.charset.len) - { - last = ngx_cpymem(last, "; charset=", sizeof("; charset=") - 1); - - last = ngx_cpymem(last, r->headers_out.charset.data, - r->headers_out.charset.len); - - /* update r->headers_out.content_type for possible logging */ - - r->headers_out.content_type.len = last - p; - r->headers_out.content_type.data = p; - } - - (void) ngx_http_spdy_nv_write_vlen(p - NGX_SPDY_NV_VLEN_SIZE, - r->headers_out.content_type.len); - - count++; - } - - if (r->headers_out.content_length == NULL - && r->headers_out.content_length_n >= 0) - { - last = ngx_http_spdy_nv_write_name(last, "content-length"); - - p = last + NGX_SPDY_NV_VLEN_SIZE; - - last = ngx_sprintf(p, "%O", r->headers_out.content_length_n); - - (void) ngx_http_spdy_nv_write_vlen(p - NGX_SPDY_NV_VLEN_SIZE, - last - p); - - count++; - } - - if (r->headers_out.last_modified == NULL - && r->headers_out.last_modified_time != -1) - { - last = ngx_http_spdy_nv_write_name(last, "last-modified"); - - p = last + NGX_SPDY_NV_VLEN_SIZE; - - last = ngx_http_time(p, r->headers_out.last_modified_time); - - (void) ngx_http_spdy_nv_write_vlen(p - NGX_SPDY_NV_VLEN_SIZE, - last - p); - - count++; - } - - if (host.data) { - - last = ngx_http_spdy_nv_write_name(last, "location"); - - p = last + NGX_SPDY_NV_VLEN_SIZE; - - last = ngx_cpymem(p, "http", sizeof("http") - 1); - -#if (NGX_HTTP_SSL) - if (c->ssl) { - *last++ ='s'; - } -#endif - - *last++ = ':'; *last++ = '/'; *last++ = '/'; - - last = ngx_cpymem(last, host.data, host.len); - - if (port) { - last = ngx_sprintf(last, ":%ui", port); - } - - last = ngx_cpymem(last, r->headers_out.location->value.data, - r->headers_out.location->value.len); - - /* update r->headers_out.location->value for possible logging */ - - r->headers_out.location->value.len = last - p; - r->headers_out.location->value.data = p; - ngx_str_set(&r->headers_out.location->key, "location"); - - (void) ngx_http_spdy_nv_write_vlen(p - NGX_SPDY_NV_VLEN_SIZE, - r->headers_out.location->value.len); - - count++; - } - - part = &r->headers_out.headers.part; - header = part->elts; - - for (i = 0; /* void */; i++) { - - if (i >= part->nelts) { - if (part->next == NULL) { - break; - } - - part = part->next; - header = part->elts; - i = 0; - } - - if (header[i].hash == 0 || header[i].hash == 2) { - continue; - } - - last = ngx_http_spdy_nv_write_nlen(last, header[i].key.len); - - ngx_strlow(last, header[i].key.data, header[i].key.len); - last += header[i].key.len; - - p = last + NGX_SPDY_NV_VLEN_SIZE; - - last = ngx_cpymem(p, header[i].value.data, header[i].value.len); - - pt = part; - h = header; - - for (j = i + 1; /* void */; j++) { - - if (j >= pt->nelts) { - if (pt->next == NULL) { - break; - } - - pt = pt->next; - h = pt->elts; - j = 0; - } - - if (h[j].hash == 0 || h[j].hash == 2 - || h[j].key.len != header[i].key.len - || ngx_strncasecmp(header[i].key.data, h[j].key.data, - header[i].key.len)) - { - continue; - } - - if (h[j].value.len) { - if (last != p) { - *last++ = '\0'; - } - - last = ngx_cpymem(last, h[j].value.data, h[j].value.len); - } - - h[j].hash = 2; - } - - (void) ngx_http_spdy_nv_write_vlen(p - NGX_SPDY_NV_VLEN_SIZE, - last - p); - - count++; - } - - (void) ngx_http_spdy_nv_write_num(buf, count); - - stream = r->spdy_stream; - sc = stream->connection; - - len = last - buf; - - b = ngx_create_temp_buf(r->pool, NGX_SPDY_FRAME_HEADER_SIZE - + NGX_SPDY_SYN_REPLY_SIZE - + deflateBound(&sc->zstream_out, len)); - if (b == NULL) { - ngx_free(buf); - return NGX_ERROR; - } - - b->last += NGX_SPDY_FRAME_HEADER_SIZE + NGX_SPDY_SYN_REPLY_SIZE; - - sc->zstream_out.next_in = buf; - sc->zstream_out.avail_in = len; - sc->zstream_out.next_out = b->last; - sc->zstream_out.avail_out = b->end - b->last; - - rc = deflate(&sc->zstream_out, Z_SYNC_FLUSH); - - ngx_free(buf); - - if (rc != Z_OK) { - ngx_log_error(NGX_LOG_ALERT, c->log, 0, "deflate() failed: %d", rc); - return NGX_ERROR; - } - - ngx_log_debug5(NGX_LOG_DEBUG_HTTP, c->log, 0, - "spdy deflate out: ni:%p no:%p ai:%ud ao:%ud rc:%d", - sc->zstream_out.next_in, sc->zstream_out.next_out, - sc->zstream_out.avail_in, sc->zstream_out.avail_out, - rc); - - b->last = sc->zstream_out.next_out; - - p = b->pos; - p = ngx_spdy_frame_write_head(p, NGX_SPDY_SYN_REPLY); - - len = b->last - b->pos; - - r->header_size = len; - - len -= NGX_SPDY_FRAME_HEADER_SIZE; - - if (r->header_only) { - b->last_buf = 1; - p = ngx_spdy_frame_write_flags_and_len(p, NGX_SPDY_FLAG_FIN, len); - - } else { - p = ngx_spdy_frame_write_flags_and_len(p, 0, len); - } - - (void) ngx_spdy_frame_write_sid(p, stream->id); - - cl = ngx_alloc_chain_link(r->pool); - if (cl == NULL) { - return NGX_ERROR; - } - - cl->buf = b; - cl->next = NULL; - - frame = ngx_palloc(r->pool, sizeof(ngx_http_spdy_out_frame_t)); - if (frame == NULL) { - return NGX_ERROR; - } - - frame->first = cl; - frame->last = cl; - frame->handler = ngx_http_spdy_syn_frame_handler; - frame->stream = stream; - frame->length = len; - frame->priority = stream->priority; - frame->blocked = 1; - frame->fin = r->header_only; - - ngx_log_debug3(NGX_LOG_DEBUG_HTTP, stream->request->connection->log, 0, - "spdy:%ui create SYN_REPLY frame %p: len:%uz", - stream->id, frame, frame->length); - - ngx_http_spdy_queue_blocked_frame(sc, frame); - - cln = ngx_http_cleanup_add(r, 0); - if (cln == NULL) { - return NGX_ERROR; - } - - cln->handler = ngx_http_spdy_filter_cleanup; - cln->data = stream; - - stream->queued = 1; - - c->send_chain = ngx_http_spdy_send_chain; - c->need_last_buf = 1; - - return ngx_http_spdy_filter_send(c, stream); -} - - -static ngx_chain_t * -ngx_http_spdy_send_chain(ngx_connection_t *fc, ngx_chain_t *in, off_t limit) -{ - off_t size, offset; - size_t rest, frame_size; - ngx_chain_t *cl, *out, **ln; - ngx_http_request_t *r; - ngx_http_spdy_stream_t *stream; - ngx_http_spdy_loc_conf_t *slcf; - ngx_http_spdy_out_frame_t *frame; - ngx_http_spdy_connection_t *sc; - - r = fc->data; - stream = r->spdy_stream; - -#if (NGX_SUPPRESS_WARN) - size = 0; -#endif - - while (in) { - size = ngx_buf_size(in->buf); - - if (size || in->buf->last_buf) { - break; - } - - in = in->next; - } - - if (in == NULL) { - - if (stream->queued) { - fc->write->delayed = 1; - } else { - fc->buffered &= ~NGX_SPDY_BUFFERED; - } - - return NULL; - } - - sc = stream->connection; - - if (size && ngx_http_spdy_flow_control(sc, stream) == NGX_DECLINED) { - fc->write->delayed = 1; - return in; - } - - if (limit == 0 || limit > (off_t) sc->send_window) { - limit = sc->send_window; - } - - if (limit > stream->send_window) { - limit = (stream->send_window > 0) ? stream->send_window : 0; - } - - if (in->buf->tag == (ngx_buf_tag_t) &ngx_http_spdy_filter_get_shadow) { - cl = ngx_alloc_chain_link(r->pool); - if (cl == NULL) { - return NGX_CHAIN_ERROR; - } - - cl->buf = in->buf; - in->buf = cl->buf->shadow; - - offset = ngx_buf_in_memory(in->buf) - ? (cl->buf->pos - in->buf->pos) - : (cl->buf->file_pos - in->buf->file_pos); - - cl->next = stream->free_bufs; - stream->free_bufs = cl; - - } else { - offset = 0; - } - -#if (NGX_SUPPRESS_WARN) - cl = NULL; -#endif - - slcf = ngx_http_get_module_loc_conf(r, ngx_http_spdy_module); - - frame_size = (limit <= (off_t) slcf->chunk_size) ? (size_t) limit - : slcf->chunk_size; - - for ( ;; ) { - ln = &out; - rest = frame_size; - - while ((off_t) rest >= size) { - - if (offset) { - cl = ngx_http_spdy_filter_get_shadow(stream, in->buf, - offset, size); - if (cl == NULL) { - return NGX_CHAIN_ERROR; - } - - offset = 0; - - } else { - cl = ngx_alloc_chain_link(r->pool); - if (cl == NULL) { - return NGX_CHAIN_ERROR; - } - - cl->buf = in->buf; - } - - *ln = cl; - ln = &cl->next; - - rest -= (size_t) size; - in = in->next; - - if (in == NULL) { - frame_size -= rest; - rest = 0; - break; - } - - size = ngx_buf_size(in->buf); - } - - if (rest) { - cl = ngx_http_spdy_filter_get_shadow(stream, in->buf, - offset, rest); - if (cl == NULL) { - return NGX_CHAIN_ERROR; - } - - cl->buf->flush = 0; - cl->buf->last_buf = 0; - - *ln = cl; - - offset += rest; - size -= rest; - } - - frame = ngx_http_spdy_filter_get_data_frame(stream, frame_size, - out, cl); - if (frame == NULL) { - return NGX_CHAIN_ERROR; - } - - ngx_http_spdy_queue_frame(sc, frame); - - sc->send_window -= frame_size; - - stream->send_window -= frame_size; - stream->queued++; - - if (in == NULL) { - break; - } - - limit -= frame_size; - - if (limit == 0) { - break; - } - - if (limit < (off_t) slcf->chunk_size) { - frame_size = (size_t) limit; - } - } - - if (offset) { - cl = ngx_http_spdy_filter_get_shadow(stream, in->buf, offset, size); - if (cl == NULL) { - return NGX_CHAIN_ERROR; - } - - in->buf = cl->buf; - ngx_free_chain(r->pool, cl); - } - - if (ngx_http_spdy_filter_send(fc, stream) == NGX_ERROR) { - return NGX_CHAIN_ERROR; - } - - if (in && ngx_http_spdy_flow_control(sc, stream) == NGX_DECLINED) { - fc->write->delayed = 1; - } - - return in; -} - - -static ngx_chain_t * -ngx_http_spdy_filter_get_shadow(ngx_http_spdy_stream_t *stream, ngx_buf_t *buf, - off_t offset, off_t size) -{ - ngx_buf_t *chunk; - ngx_chain_t *cl; - - cl = ngx_chain_get_free_buf(stream->request->pool, &stream->free_bufs); - if (cl == NULL) { - return NULL; - } - - chunk = cl->buf; - - ngx_memcpy(chunk, buf, sizeof(ngx_buf_t)); - - chunk->tag = (ngx_buf_tag_t) &ngx_http_spdy_filter_get_shadow; - chunk->shadow = buf; - - if (ngx_buf_in_memory(chunk)) { - chunk->pos += offset; - chunk->last = chunk->pos + size; - } - - if (chunk->in_file) { - chunk->file_pos += offset; - chunk->file_last = chunk->file_pos + size; - } - - return cl; -} - - -static ngx_http_spdy_out_frame_t * -ngx_http_spdy_filter_get_data_frame(ngx_http_spdy_stream_t *stream, - size_t len, ngx_chain_t *first, ngx_chain_t *last) -{ - u_char *p; - ngx_buf_t *buf; - ngx_uint_t flags; - ngx_chain_t *cl; - ngx_http_spdy_out_frame_t *frame; - - - frame = stream->free_frames; - - if (frame) { - stream->free_frames = frame->next; - - } else { - frame = ngx_palloc(stream->request->pool, - sizeof(ngx_http_spdy_out_frame_t)); - if (frame == NULL) { - return NULL; - } - } - - flags = last->buf->last_buf ? NGX_SPDY_FLAG_FIN : 0; - - ngx_log_debug4(NGX_LOG_DEBUG_HTTP, stream->request->connection->log, 0, - "spdy:%ui create DATA frame %p: len:%uz flags:%ui", - stream->id, frame, len, flags); - - cl = ngx_chain_get_free_buf(stream->request->pool, - &stream->free_data_headers); - if (cl == NULL) { - return NULL; - } - - buf = cl->buf; - - if (buf->start) { - p = buf->start; - buf->pos = p; - - p += NGX_SPDY_SID_SIZE; - - (void) ngx_spdy_frame_write_flags_and_len(p, flags, len); - - } else { - p = ngx_palloc(stream->request->pool, NGX_SPDY_FRAME_HEADER_SIZE); - if (p == NULL) { - return NULL; - } - - buf->pos = p; - buf->start = p; - - p = ngx_spdy_frame_write_sid(p, stream->id); - p = ngx_spdy_frame_write_flags_and_len(p, flags, len); - - buf->last = p; - buf->end = p; - - buf->tag = (ngx_buf_tag_t) &ngx_http_spdy_filter_get_data_frame; - buf->memory = 1; - } - - cl->next = first; - first = cl; - - last->buf->flush = 1; - - frame->first = first; - frame->last = last; - frame->handler = ngx_http_spdy_data_frame_handler; - frame->stream = stream; - frame->length = len; - frame->priority = stream->priority; - frame->blocked = 0; - frame->fin = last->buf->last_buf; - - return frame; -} - - -static ngx_inline ngx_int_t -ngx_http_spdy_filter_send(ngx_connection_t *fc, ngx_http_spdy_stream_t *stream) -{ - stream->blocked = 1; - - if (ngx_http_spdy_send_output_queue(stream->connection) == NGX_ERROR) { - fc->error = 1; - return NGX_ERROR; - } - - stream->blocked = 0; - - if (stream->queued) { - fc->buffered |= NGX_SPDY_BUFFERED; - fc->write->delayed = 1; - return NGX_AGAIN; - } - - fc->buffered &= ~NGX_SPDY_BUFFERED; - - return NGX_OK; -} - - -static ngx_inline ngx_int_t -ngx_http_spdy_flow_control(ngx_http_spdy_connection_t *sc, - ngx_http_spdy_stream_t *stream) -{ - if (stream->send_window <= 0) { - stream->exhausted = 1; - return NGX_DECLINED; - } - - if (sc->send_window == 0) { - ngx_http_spdy_waiting_queue(sc, stream); - return NGX_DECLINED; - } - - return NGX_OK; -} - - -static void -ngx_http_spdy_waiting_queue(ngx_http_spdy_connection_t *sc, - ngx_http_spdy_stream_t *stream) -{ - ngx_queue_t *q; - ngx_http_spdy_stream_t *s; - - if (stream->handled) { - return; - } - - stream->handled = 1; - - for (q = ngx_queue_last(&sc->waiting); - q != ngx_queue_sentinel(&sc->waiting); - q = ngx_queue_prev(q)) - { - s = ngx_queue_data(q, ngx_http_spdy_stream_t, queue); - - /* - * NB: higher values represent lower priorities. - */ - if (stream->priority >= s->priority) { - break; - } - } - - ngx_queue_insert_after(q, &stream->queue); -} - - -static ngx_int_t -ngx_http_spdy_syn_frame_handler(ngx_http_spdy_connection_t *sc, - ngx_http_spdy_out_frame_t *frame) -{ - ngx_buf_t *buf; - ngx_http_spdy_stream_t *stream; - - buf = frame->first->buf; - - if (buf->pos != buf->last) { - return NGX_AGAIN; - } - - stream = frame->stream; - - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, - "spdy:%ui SYN_REPLY frame %p was sent", stream->id, frame); - - ngx_free_chain(stream->request->pool, frame->first); - - ngx_http_spdy_handle_frame(stream, frame); - - ngx_http_spdy_handle_stream(sc, stream); - - return NGX_OK; -} - - -static ngx_int_t -ngx_http_spdy_data_frame_handler(ngx_http_spdy_connection_t *sc, - ngx_http_spdy_out_frame_t *frame) -{ - ngx_buf_t *buf; - ngx_chain_t *cl, *ln; - ngx_http_spdy_stream_t *stream; - - stream = frame->stream; - - cl = frame->first; - - if (cl->buf->tag == (ngx_buf_tag_t) &ngx_http_spdy_filter_get_data_frame) { - - if (cl->buf->pos != cl->buf->last) { - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, - "spdy:%ui DATA frame %p was sent partially", - stream->id, frame); - - return NGX_AGAIN; - } - - ln = cl->next; - - cl->next = stream->free_data_headers; - stream->free_data_headers = cl; - - if (cl == frame->last) { - goto done; - } - - cl = ln; - } - - for ( ;; ) { - if (cl->buf->tag == (ngx_buf_tag_t) &ngx_http_spdy_filter_get_shadow) { - buf = cl->buf->shadow; - - if (ngx_buf_in_memory(buf)) { - buf->pos = cl->buf->pos; - } - - if (buf->in_file) { - buf->file_pos = cl->buf->file_pos; - } - } - - if (ngx_buf_size(cl->buf) != 0) { - - if (cl != frame->first) { - frame->first = cl; - ngx_http_spdy_handle_stream(sc, stream); - } - - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, - "spdy:%ui DATA frame %p was sent partially", - stream->id, frame); - - return NGX_AGAIN; - } - - ln = cl->next; - - if (cl->buf->tag == (ngx_buf_tag_t) &ngx_http_spdy_filter_get_shadow) { - cl->next = stream->free_bufs; - stream->free_bufs = cl; - - } else { - ngx_free_chain(stream->request->pool, cl); - } - - if (cl == frame->last) { - goto done; - } - - cl = ln; - } - -done: - - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, sc->connection->log, 0, - "spdy:%ui DATA frame %p was sent", stream->id, frame); - - stream->request->header_size += NGX_SPDY_FRAME_HEADER_SIZE; - - ngx_http_spdy_handle_frame(stream, frame); - - ngx_http_spdy_handle_stream(sc, stream); - - return NGX_OK; -} - - -static ngx_inline void -ngx_http_spdy_handle_frame(ngx_http_spdy_stream_t *stream, - ngx_http_spdy_out_frame_t *frame) -{ - ngx_http_request_t *r; - - r = stream->request; - - r->connection->sent += NGX_SPDY_FRAME_HEADER_SIZE + frame->length; - - if (frame->fin) { - stream->out_closed = 1; - } - - frame->next = stream->free_frames; - stream->free_frames = frame; - - stream->queued--; -} - - -static ngx_inline void -ngx_http_spdy_handle_stream(ngx_http_spdy_connection_t *sc, - ngx_http_spdy_stream_t *stream) -{ - ngx_event_t *wev; - - if (stream->handled || stream->blocked || stream->exhausted) { - return; - } - - wev = stream->request->connection->write; - - /* - * This timer can only be set if the stream was delayed because of rate - * limit. In that case the event should be triggered by the timer. - */ - - if (!wev->timer_set) { - wev->delayed = 0; - - stream->handled = 1; - ngx_queue_insert_tail(&sc->posted, &stream->queue); - } -} - - -static void -ngx_http_spdy_filter_cleanup(void *data) -{ - ngx_http_spdy_stream_t *stream = data; - - size_t delta; - ngx_http_spdy_out_frame_t *frame, **fn; - ngx_http_spdy_connection_t *sc; - - if (stream->handled) { - stream->handled = 0; - ngx_queue_remove(&stream->queue); - } - - if (stream->queued == 0) { - return; - } - - delta = 0; - sc = stream->connection; - fn = &sc->last_out; - - for ( ;; ) { - frame = *fn; - - if (frame == NULL) { - break; - } - - if (frame->stream == stream && !frame->blocked) { - *fn = frame->next; - - delta += frame->length; - - if (--stream->queued == 0) { - break; - } - - continue; - } - - fn = &frame->next; - } - - if (sc->send_window == 0 && delta && !ngx_queue_empty(&sc->waiting)) { - ngx_queue_add(&sc->posted, &sc->waiting); - ngx_queue_init(&sc->waiting); - } - - sc->send_window += delta; -} - - -static ngx_int_t -ngx_http_spdy_filter_init(ngx_conf_t *cf) -{ - ngx_http_next_header_filter = ngx_http_top_header_filter; - ngx_http_top_header_filter = ngx_http_spdy_header_filter; - - return NGX_OK; -} diff --git a/src/http/ngx_http_spdy_module.c b/src/http/ngx_http_spdy_module.c deleted file mode 100644 index 5178a36..0000000 --- a/src/http/ngx_http_spdy_module.c +++ /dev/null @@ -1,408 +0,0 @@ - -/* - * Copyright (C) Nginx, Inc. - * Copyright (C) Valentin V. Bartenev - */ - - -#include -#include -#include -#include - - -static ngx_int_t ngx_http_spdy_add_variables(ngx_conf_t *cf); - -static ngx_int_t ngx_http_spdy_variable(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data); -static ngx_int_t ngx_http_spdy_request_priority_variable(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data); - -static ngx_int_t ngx_http_spdy_module_init(ngx_cycle_t *cycle); - -static void *ngx_http_spdy_create_main_conf(ngx_conf_t *cf); -static char *ngx_http_spdy_init_main_conf(ngx_conf_t *cf, void *conf); -static void *ngx_http_spdy_create_srv_conf(ngx_conf_t *cf); -static char *ngx_http_spdy_merge_srv_conf(ngx_conf_t *cf, void *parent, - void *child); -static void *ngx_http_spdy_create_loc_conf(ngx_conf_t *cf); -static char *ngx_http_spdy_merge_loc_conf(ngx_conf_t *cf, void *parent, - void *child); - -static char *ngx_http_spdy_recv_buffer_size(ngx_conf_t *cf, void *post, - void *data); -static char *ngx_http_spdy_pool_size(ngx_conf_t *cf, void *post, void *data); -static char *ngx_http_spdy_streams_index_mask(ngx_conf_t *cf, void *post, - void *data); -static char *ngx_http_spdy_chunk_size(ngx_conf_t *cf, void *post, void *data); - - -static ngx_conf_num_bounds_t ngx_http_spdy_headers_comp_bounds = { - ngx_conf_check_num_bounds, 0, 9 -}; - -static ngx_conf_post_t ngx_http_spdy_recv_buffer_size_post = - { ngx_http_spdy_recv_buffer_size }; -static ngx_conf_post_t ngx_http_spdy_pool_size_post = - { ngx_http_spdy_pool_size }; -static ngx_conf_post_t ngx_http_spdy_streams_index_mask_post = - { ngx_http_spdy_streams_index_mask }; -static ngx_conf_post_t ngx_http_spdy_chunk_size_post = - { ngx_http_spdy_chunk_size }; - - -static ngx_command_t ngx_http_spdy_commands[] = { - - { ngx_string("spdy_recv_buffer_size"), - NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, - ngx_conf_set_size_slot, - NGX_HTTP_MAIN_CONF_OFFSET, - offsetof(ngx_http_spdy_main_conf_t, recv_buffer_size), - &ngx_http_spdy_recv_buffer_size_post }, - - { ngx_string("spdy_pool_size"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_size_slot, - NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_http_spdy_srv_conf_t, pool_size), - &ngx_http_spdy_pool_size_post }, - - { ngx_string("spdy_max_concurrent_streams"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_num_slot, - NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_http_spdy_srv_conf_t, concurrent_streams), - NULL }, - - { ngx_string("spdy_streams_index_size"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_num_slot, - NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_http_spdy_srv_conf_t, streams_index_mask), - &ngx_http_spdy_streams_index_mask_post }, - - { ngx_string("spdy_recv_timeout"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_http_spdy_srv_conf_t, recv_timeout), - NULL }, - - { ngx_string("spdy_keepalive_timeout"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_http_spdy_srv_conf_t, keepalive_timeout), - NULL }, - - { ngx_string("spdy_headers_comp"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_num_slot, - NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_http_spdy_srv_conf_t, headers_comp), - &ngx_http_spdy_headers_comp_bounds }, - - { ngx_string("spdy_chunk_size"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_size_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_spdy_loc_conf_t, chunk_size), - &ngx_http_spdy_chunk_size_post }, - - ngx_null_command -}; - - -static ngx_http_module_t ngx_http_spdy_module_ctx = { - ngx_http_spdy_add_variables, /* preconfiguration */ - NULL, /* postconfiguration */ - - ngx_http_spdy_create_main_conf, /* create main configuration */ - ngx_http_spdy_init_main_conf, /* init main configuration */ - - ngx_http_spdy_create_srv_conf, /* create server configuration */ - ngx_http_spdy_merge_srv_conf, /* merge server configuration */ - - ngx_http_spdy_create_loc_conf, /* create location configuration */ - ngx_http_spdy_merge_loc_conf /* merge location configuration */ -}; - - -ngx_module_t ngx_http_spdy_module = { - NGX_MODULE_V1, - &ngx_http_spdy_module_ctx, /* module context */ - ngx_http_spdy_commands, /* module directives */ - NGX_HTTP_MODULE, /* module type */ - NULL, /* init master */ - ngx_http_spdy_module_init, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static ngx_http_variable_t ngx_http_spdy_vars[] = { - - { ngx_string("spdy"), NULL, - ngx_http_spdy_variable, 0, 0, 0 }, - - { ngx_string("spdy_request_priority"), NULL, - ngx_http_spdy_request_priority_variable, 0, 0, 0 }, - - { ngx_null_string, NULL, NULL, 0, 0, 0 } -}; - - -static ngx_int_t -ngx_http_spdy_add_variables(ngx_conf_t *cf) -{ - ngx_http_variable_t *var, *v; - - for (v = ngx_http_spdy_vars; v->name.len; v++) { - var = ngx_http_add_variable(cf, &v->name, v->flags); - if (var == NULL) { - return NGX_ERROR; - } - - var->get_handler = v->get_handler; - var->data = v->data; - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_http_spdy_variable(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data) -{ - if (r->spdy_stream) { - v->len = sizeof("3.1") - 1; - v->valid = 1; - v->no_cacheable = 0; - v->not_found = 0; - v->data = (u_char *) "3.1"; - - return NGX_OK; - } - - *v = ngx_http_variable_null_value; - - return NGX_OK; -} - - -static ngx_int_t -ngx_http_spdy_request_priority_variable(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data) -{ - if (r->spdy_stream) { - v->len = 1; - v->valid = 1; - v->no_cacheable = 0; - v->not_found = 0; - - v->data = ngx_pnalloc(r->pool, 1); - if (v->data == NULL) { - return NGX_ERROR; - } - - v->data[0] = '0' + (u_char) r->spdy_stream->priority; - - return NGX_OK; - } - - *v = ngx_http_variable_null_value; - - return NGX_OK; -} - - -static ngx_int_t -ngx_http_spdy_module_init(ngx_cycle_t *cycle) -{ - ngx_http_spdy_request_headers_init(); - - return NGX_OK; -} - - -static void * -ngx_http_spdy_create_main_conf(ngx_conf_t *cf) -{ - ngx_http_spdy_main_conf_t *smcf; - - smcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_spdy_main_conf_t)); - if (smcf == NULL) { - return NULL; - } - - smcf->recv_buffer_size = NGX_CONF_UNSET_SIZE; - - return smcf; -} - - -static char * -ngx_http_spdy_init_main_conf(ngx_conf_t *cf, void *conf) -{ - ngx_http_spdy_main_conf_t *smcf = conf; - - ngx_conf_init_size_value(smcf->recv_buffer_size, 256 * 1024); - - return NGX_CONF_OK; -} - - -static void * -ngx_http_spdy_create_srv_conf(ngx_conf_t *cf) -{ - ngx_http_spdy_srv_conf_t *sscf; - - sscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_spdy_srv_conf_t)); - if (sscf == NULL) { - return NULL; - } - - sscf->pool_size = NGX_CONF_UNSET_SIZE; - - sscf->concurrent_streams = NGX_CONF_UNSET_UINT; - sscf->streams_index_mask = NGX_CONF_UNSET_UINT; - - sscf->recv_timeout = NGX_CONF_UNSET_MSEC; - sscf->keepalive_timeout = NGX_CONF_UNSET_MSEC; - - sscf->headers_comp = NGX_CONF_UNSET; - - return sscf; -} - - -static char * -ngx_http_spdy_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) -{ - ngx_http_spdy_srv_conf_t *prev = parent; - ngx_http_spdy_srv_conf_t *conf = child; - - ngx_conf_merge_size_value(conf->pool_size, prev->pool_size, 4096); - - ngx_conf_merge_uint_value(conf->concurrent_streams, - prev->concurrent_streams, 100); - - ngx_conf_merge_uint_value(conf->streams_index_mask, - prev->streams_index_mask, 32 - 1); - - ngx_conf_merge_msec_value(conf->recv_timeout, - prev->recv_timeout, 30000); - ngx_conf_merge_msec_value(conf->keepalive_timeout, - prev->keepalive_timeout, 180000); - - ngx_conf_merge_value(conf->headers_comp, prev->headers_comp, 0); - - return NGX_CONF_OK; -} - - -static void * -ngx_http_spdy_create_loc_conf(ngx_conf_t *cf) -{ - ngx_http_spdy_loc_conf_t *slcf; - - slcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_spdy_loc_conf_t)); - if (slcf == NULL) { - return NULL; - } - - slcf->chunk_size = NGX_CONF_UNSET_SIZE; - - return slcf; -} - - -static char * -ngx_http_spdy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) -{ - ngx_http_spdy_loc_conf_t *prev = parent; - ngx_http_spdy_loc_conf_t *conf = child; - - ngx_conf_merge_size_value(conf->chunk_size, prev->chunk_size, 8 * 1024); - - return NGX_CONF_OK; -} - - -static char * -ngx_http_spdy_recv_buffer_size(ngx_conf_t *cf, void *post, void *data) -{ - size_t *sp = data; - - if (*sp <= 2 * NGX_SPDY_STATE_BUFFER_SIZE) { - return "value is too small"; - } - - return NGX_CONF_OK; -} - - -static char * -ngx_http_spdy_pool_size(ngx_conf_t *cf, void *post, void *data) -{ - size_t *sp = data; - - if (*sp < NGX_MIN_POOL_SIZE) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "the pool size must be no less than %uz", - NGX_MIN_POOL_SIZE); - return NGX_CONF_ERROR; - } - - if (*sp % NGX_POOL_ALIGNMENT) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "the pool size must be a multiple of %uz", - NGX_POOL_ALIGNMENT); - return NGX_CONF_ERROR; - } - - return NGX_CONF_OK; -} - - -static char * -ngx_http_spdy_streams_index_mask(ngx_conf_t *cf, void *post, void *data) -{ - ngx_uint_t *np = data; - - ngx_uint_t mask; - - mask = *np - 1; - - if (*np == 0 || (*np & mask)) { - return "must be a power of two"; - } - - *np = mask; - - return NGX_CONF_OK; -} - - -static char * -ngx_http_spdy_chunk_size(ngx_conf_t *cf, void *post, void *data) -{ - size_t *sp = data; - - if (*sp == 0) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "the spdy chunk size cannot be zero"); - return NGX_CONF_ERROR; - } - - if (*sp > NGX_SPDY_MAX_FRAME_SIZE) { - *sp = NGX_SPDY_MAX_FRAME_SIZE; - } - - return NGX_CONF_OK; -} diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c index 4b0332a..1530596 100644 --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -475,8 +475,8 @@ ngx_http_upstream_init(ngx_http_request_t *r) ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http init upstream, client timer: %d", c->read->timer_set); -#if (NGX_HTTP_SPDY) - if (r->spdy_stream) { +#if (NGX_HTTP_V2) + if (r->stream) { ngx_http_upstream_init_request(r); return; } @@ -534,15 +534,24 @@ ngx_http_upstream_init_request(ngx_http_request_t *r) r->write_event_handler = ngx_http_request_empty_handler; - if (rc == NGX_DONE) { - return; - } - if (rc == NGX_ERROR) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } + if (rc == NGX_OK) { + rc = ngx_http_upstream_cache_send(r, u); + + if (rc == NGX_DONE) { + return; + } + + if (rc == NGX_HTTP_UPSTREAM_INVALID_HEADER) { + rc = NGX_DECLINED; + r->cached = 0; + } + } + if (rc != NGX_DECLINED) { ngx_http_finalize_request(r, rc); return; @@ -837,13 +846,7 @@ ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u) case NGX_OK: - rc = ngx_http_upstream_cache_send(r, u); - - if (rc != NGX_HTTP_UPSTREAM_INVALID_HEADER) { - return rc; - } - - break; + return NGX_OK; case NGX_HTTP_CACHE_STALE: @@ -1148,8 +1151,8 @@ ngx_http_upstream_check_broken_connection(ngx_http_request_t *r, return; } -#if (NGX_HTTP_SPDY) - if (r->spdy_stream) { +#if (NGX_HTTP_V2) + if (r->stream) { return; } #endif diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c new file mode 100644 index 0000000..bf07997 --- /dev/null +++ b/src/http/v2/ngx_http_v2.c @@ -0,0 +1,4036 @@ + +/* + * Copyright (C) Nginx, Inc. + * Copyright (C) Valentin V. Bartenev + */ + + +#include +#include +#include +#include + + +/* errors */ +#define NGX_HTTP_V2_NO_ERROR 0x0 +#define NGX_HTTP_V2_PROTOCOL_ERROR 0x1 +#define NGX_HTTP_V2_INTERNAL_ERROR 0x2 +#define NGX_HTTP_V2_FLOW_CTRL_ERROR 0x3 +#define NGX_HTTP_V2_SETTINGS_TIMEOUT 0x4 +#define NGX_HTTP_V2_STREAM_CLOSED 0x5 +#define NGX_HTTP_V2_SIZE_ERROR 0x6 +#define NGX_HTTP_V2_REFUSED_STREAM 0x7 +#define NGX_HTTP_V2_CANCEL 0x8 +#define NGX_HTTP_V2_COMP_ERROR 0x9 +#define NGX_HTTP_V2_CONNECT_ERROR 0xa +#define NGX_HTTP_V2_ENHANCE_YOUR_CALM 0xb +#define NGX_HTTP_V2_INADEQUATE_SECURITY 0xc +#define NGX_HTTP_V2_HTTP_1_1_REQUIRED 0xd + +/* frame sizes */ +#define NGX_HTTP_V2_RST_STREAM_SIZE 4 +#define NGX_HTTP_V2_PRIORITY_SIZE 5 +#define NGX_HTTP_V2_PING_SIZE 8 +#define NGX_HTTP_V2_GOAWAY_SIZE 8 +#define NGX_HTTP_V2_WINDOW_UPDATE_SIZE 4 + +#define NGX_HTTP_V2_STREAM_ID_SIZE 4 + +#define NGX_HTTP_V2_SETTINGS_PARAM_SIZE 6 + +/* settings fields */ +#define NGX_HTTP_V2_HEADER_TABLE_SIZE_SETTING 0x1 +#define NGX_HTTP_V2_MAX_STREAMS_SETTING 0x3 +#define NGX_HTTP_V2_INIT_WINDOW_SIZE_SETTING 0x4 +#define NGX_HTTP_V2_MAX_FRAME_SIZE_SETTING 0x5 + +#define NGX_HTTP_V2_FRAME_BUFFER_SIZE 24 + +#define NGX_HTTP_V2_DEFAULT_FRAME_SIZE (1 << 14) + +#define NGX_HTTP_V2_MAX_WINDOW ((1U << 31) - 1) +#define NGX_HTTP_V2_DEFAULT_WINDOW 65535 + +#define NGX_HTTP_V2_ROOT (void *) -1 + + +static void ngx_http_v2_read_handler(ngx_event_t *rev); +static void ngx_http_v2_write_handler(ngx_event_t *wev); +static void ngx_http_v2_handle_connection(ngx_http_v2_connection_t *h2c); + +static u_char *ngx_http_v2_state_proxy_protocol(ngx_http_v2_connection_t *h2c, + u_char *pos, u_char *end); +static u_char *ngx_http_v2_state_preface(ngx_http_v2_connection_t *h2c, + u_char *pos, u_char *end); +static u_char *ngx_http_v2_state_preface_end(ngx_http_v2_connection_t *h2c, + u_char *pos, u_char *end); +static u_char *ngx_http_v2_state_head(ngx_http_v2_connection_t *h2c, + u_char *pos, u_char *end); +static u_char *ngx_http_v2_state_data(ngx_http_v2_connection_t *h2c, + u_char *pos, u_char *end); +static u_char *ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, + u_char *pos, u_char *end); +static u_char *ngx_http_v2_state_headers(ngx_http_v2_connection_t *h2c, + u_char *pos, u_char *end); +static u_char *ngx_http_v2_state_header_block(ngx_http_v2_connection_t *h2c, + u_char *pos, u_char *end); +static u_char *ngx_http_v2_state_field_len(ngx_http_v2_connection_t *h2c, + u_char *pos, u_char *end); +static u_char *ngx_http_v2_state_field_huff(ngx_http_v2_connection_t *h2c, + u_char *pos, u_char *end); +static u_char *ngx_http_v2_state_field_raw(ngx_http_v2_connection_t *h2c, + u_char *pos, u_char *end); +static u_char *ngx_http_v2_state_field_skip(ngx_http_v2_connection_t *h2c, + u_char *pos, u_char *end); +static u_char *ngx_http_v2_state_process_header(ngx_http_v2_connection_t *h2c, + u_char *pos, u_char *end); +static u_char *ngx_http_v2_state_header_complete(ngx_http_v2_connection_t *h2c, + u_char *pos, u_char *end); +static u_char *ngx_http_v2_handle_continuation(ngx_http_v2_connection_t *h2c, + u_char *pos, u_char *end, ngx_http_v2_handler_pt handler); +static u_char *ngx_http_v2_state_priority(ngx_http_v2_connection_t *h2c, + u_char *pos, u_char *end); +static u_char *ngx_http_v2_state_rst_stream(ngx_http_v2_connection_t *h2c, + u_char *pos, u_char *end); +static u_char *ngx_http_v2_state_settings(ngx_http_v2_connection_t *h2c, + u_char *pos, u_char *end); +static u_char *ngx_http_v2_state_settings_params(ngx_http_v2_connection_t *h2c, + u_char *pos, u_char *end); +static u_char *ngx_http_v2_state_push_promise(ngx_http_v2_connection_t *h2c, + u_char *pos, u_char *end); +static u_char *ngx_http_v2_state_ping(ngx_http_v2_connection_t *h2c, + u_char *pos, u_char *end); +static u_char *ngx_http_v2_state_goaway(ngx_http_v2_connection_t *h2c, + u_char *pos, u_char *end); +static u_char *ngx_http_v2_state_window_update(ngx_http_v2_connection_t *h2c, + u_char *pos, u_char *end); +static u_char *ngx_http_v2_state_continuation(ngx_http_v2_connection_t *h2c, + u_char *pos, u_char *end); +static u_char *ngx_http_v2_state_complete(ngx_http_v2_connection_t *h2c, + u_char *pos, u_char *end); +static u_char *ngx_http_v2_state_skip_padded(ngx_http_v2_connection_t *h2c, + u_char *pos, u_char *end); +static u_char *ngx_http_v2_state_skip(ngx_http_v2_connection_t *h2c, + u_char *pos, u_char *end); +static u_char *ngx_http_v2_state_skip_headers(ngx_http_v2_connection_t *h2c, + u_char *pos, u_char *end); +static u_char *ngx_http_v2_state_save(ngx_http_v2_connection_t *h2c, + u_char *pos, u_char *end, ngx_http_v2_handler_pt handler); +static u_char *ngx_http_v2_connection_error(ngx_http_v2_connection_t *h2c, + ngx_uint_t err); + +static ngx_int_t ngx_http_v2_parse_int(ngx_http_v2_connection_t *h2c, + u_char **pos, u_char *end, ngx_uint_t prefix); + +static ngx_http_v2_stream_t *ngx_http_v2_create_stream( + ngx_http_v2_connection_t *h2c); +static ngx_http_v2_node_t *ngx_http_v2_get_node_by_id( + ngx_http_v2_connection_t *h2c, ngx_uint_t sid, ngx_uint_t alloc); +static ngx_http_v2_node_t *ngx_http_v2_get_closed_node( + ngx_http_v2_connection_t *h2c); +#define ngx_http_v2_index_size(h2scf) (h2scf->streams_index_mask + 1) +#define ngx_http_v2_index(h2scf, sid) ((sid >> 1) & h2scf->streams_index_mask) + +static ngx_int_t ngx_http_v2_send_settings(ngx_http_v2_connection_t *h2c, + ngx_uint_t ack); +static ngx_int_t ngx_http_v2_settings_frame_handler( + ngx_http_v2_connection_t *h2c, ngx_http_v2_out_frame_t *frame); +static ngx_int_t ngx_http_v2_send_window_update(ngx_http_v2_connection_t *h2c, + ngx_uint_t sid, size_t window); +static ngx_int_t ngx_http_v2_send_rst_stream(ngx_http_v2_connection_t *h2c, + ngx_uint_t sid, ngx_uint_t status); + +static ngx_http_v2_out_frame_t *ngx_http_v2_get_frame( + ngx_http_v2_connection_t *h2c, size_t length, ngx_uint_t type, + u_char flags, ngx_uint_t sid); +static ngx_int_t ngx_http_v2_frame_handler(ngx_http_v2_connection_t *h2c, + ngx_http_v2_out_frame_t *frame); + +static ngx_int_t ngx_http_v2_validate_header(ngx_http_request_t *r, + ngx_http_v2_header_t *header); +static ngx_int_t ngx_http_v2_pseudo_header(ngx_http_request_t *r, + ngx_http_v2_header_t *header); +static ngx_int_t ngx_http_v2_parse_path(ngx_http_request_t *r, + ngx_http_v2_header_t *header); +static ngx_int_t ngx_http_v2_parse_method(ngx_http_request_t *r, + ngx_http_v2_header_t *header); +static ngx_int_t ngx_http_v2_parse_scheme(ngx_http_request_t *r, + ngx_http_v2_header_t *header); +static ngx_int_t ngx_http_v2_parse_authority(ngx_http_request_t *r, + ngx_http_v2_header_t *header); +static ngx_int_t ngx_http_v2_construct_request_line(ngx_http_request_t *r); +static ngx_int_t ngx_http_v2_cookie(ngx_http_request_t *r, + ngx_http_v2_header_t *header); +static ngx_int_t ngx_http_v2_construct_cookie_header(ngx_http_request_t *r); +static void ngx_http_v2_run_request(ngx_http_request_t *r); +static ngx_int_t ngx_http_v2_init_request_body(ngx_http_request_t *r); + +static ngx_int_t ngx_http_v2_terminate_stream(ngx_http_v2_connection_t *h2c, + ngx_http_v2_stream_t *stream, ngx_uint_t status); +static void ngx_http_v2_close_stream_handler(ngx_event_t *ev); +static void ngx_http_v2_handle_connection_handler(ngx_event_t *rev); +static void ngx_http_v2_idle_handler(ngx_event_t *rev); +static void ngx_http_v2_finalize_connection(ngx_http_v2_connection_t *h2c, + ngx_uint_t status); + +static ngx_int_t ngx_http_v2_adjust_windows(ngx_http_v2_connection_t *h2c, + ssize_t delta); +static void ngx_http_v2_set_dependency(ngx_http_v2_connection_t *h2c, + ngx_http_v2_node_t *node, ngx_uint_t depend, ngx_uint_t exclusive); +static void ngx_http_v2_node_children_update(ngx_http_v2_node_t *node); + +static void ngx_http_v2_pool_cleanup(void *data); + + +static ngx_http_v2_handler_pt ngx_http_v2_frame_states[] = { + ngx_http_v2_state_data, + ngx_http_v2_state_headers, + ngx_http_v2_state_priority, + ngx_http_v2_state_rst_stream, + ngx_http_v2_state_settings, + ngx_http_v2_state_push_promise, + ngx_http_v2_state_ping, + ngx_http_v2_state_goaway, + ngx_http_v2_state_window_update, + ngx_http_v2_state_continuation +}; + +#define NGX_HTTP_V2_FRAME_STATES \ + (sizeof(ngx_http_v2_frame_states) / sizeof(ngx_http_v2_handler_pt)) + + +void +ngx_http_v2_init(ngx_event_t *rev) +{ + ngx_connection_t *c; + ngx_pool_cleanup_t *cln; + ngx_http_connection_t *hc; + ngx_http_v2_srv_conf_t *h2scf; + ngx_http_v2_main_conf_t *h2mcf; + ngx_http_v2_connection_t *h2c; + + c = rev->data; + hc = c->data; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "init http2 connection"); + + c->log->action = "processing HTTP/2 connection"; + + h2mcf = ngx_http_get_module_main_conf(hc->conf_ctx, ngx_http_v2_module); + + if (h2mcf->recv_buffer == NULL) { + h2mcf->recv_buffer = ngx_palloc(ngx_cycle->pool, + h2mcf->recv_buffer_size); + if (h2mcf->recv_buffer == NULL) { + ngx_http_close_connection(c); + return; + } + } + + h2c = ngx_pcalloc(c->pool, sizeof(ngx_http_v2_connection_t)); + if (h2c == NULL) { + ngx_http_close_connection(c); + return; + } + + h2c->connection = c; + h2c->http_connection = hc; + + h2c->send_window = NGX_HTTP_V2_DEFAULT_WINDOW; + h2c->recv_window = NGX_HTTP_V2_MAX_WINDOW; + + h2c->init_window = NGX_HTTP_V2_DEFAULT_WINDOW; + + h2c->frame_size = NGX_HTTP_V2_DEFAULT_FRAME_SIZE; + + h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); + + h2c->pool = ngx_create_pool(h2scf->pool_size, h2c->connection->log); + if (h2c->pool == NULL) { + ngx_http_close_connection(c); + return; + } + + cln = ngx_pool_cleanup_add(c->pool, sizeof(ngx_pool_cleanup_file_t)); + if (cln == NULL) { + ngx_http_close_connection(c); + return; + } + + cln->handler = ngx_http_v2_pool_cleanup; + cln->data = h2c; + + h2c->streams_index = ngx_pcalloc(c->pool, ngx_http_v2_index_size(h2scf) + * sizeof(ngx_http_v2_node_t *)); + if (h2c->streams_index == NULL) { + ngx_http_close_connection(c); + return; + } + + if (ngx_http_v2_send_settings(h2c, 0) == NGX_ERROR) { + ngx_http_close_connection(c); + return; + } + + if (ngx_http_v2_send_window_update(h2c, 0, NGX_HTTP_V2_MAX_WINDOW + - NGX_HTTP_V2_DEFAULT_WINDOW) + == NGX_ERROR) + { + ngx_http_close_connection(c); + return; + } + + h2c->state.handler = hc->proxy_protocol ? ngx_http_v2_state_proxy_protocol + : 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); + + c->data = h2c; + + rev->handler = ngx_http_v2_read_handler; + c->write->handler = ngx_http_v2_write_handler; + + ngx_http_v2_read_handler(rev); +} + + +static void +ngx_http_v2_read_handler(ngx_event_t *rev) +{ + u_char *p, *end; + size_t available; + ssize_t n; + ngx_connection_t *c; + ngx_http_v2_main_conf_t *h2mcf; + ngx_http_v2_connection_t *h2c; + + c = rev->data; + h2c = c->data; + + if (rev->timedout) { + ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); + ngx_http_v2_finalize_connection(h2c, NGX_HTTP_V2_PROTOCOL_ERROR); + return; + } + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http2 read handler"); + + h2c->blocked = 1; + + h2mcf = ngx_http_get_module_main_conf(h2c->http_connection->conf_ctx, + ngx_http_v2_module); + + available = h2mcf->recv_buffer_size - 2 * NGX_HTTP_V2_STATE_BUFFER_SIZE; + + do { + p = h2mcf->recv_buffer; + + ngx_memcpy(p, h2c->state.buffer, NGX_HTTP_V2_STATE_BUFFER_SIZE); + end = p + h2c->state.buffer_used; + + n = c->recv(c, end, available); + + if (n == NGX_AGAIN) { + break; + } + + if (n == 0 && (h2c->state.incomplete || h2c->processing)) { + ngx_log_error(NGX_LOG_INFO, c->log, 0, + "client prematurely closed connection"); + } + + if (n == 0 || n == NGX_ERROR) { + c->error = 1; + ngx_http_v2_finalize_connection(h2c, 0); + return; + } + + end += n; + + h2c->state.buffer_used = 0; + h2c->state.incomplete = 0; + + do { + p = h2c->state.handler(h2c, p, end); + + if (p == NULL) { + return; + } + + } while (p != end); + + } while (rev->ready); + + if (ngx_handle_read_event(rev, 0) != NGX_OK) { + ngx_http_v2_finalize_connection(h2c, NGX_HTTP_V2_INTERNAL_ERROR); + return; + } + + if (h2c->last_out && ngx_http_v2_send_output_queue(h2c) == NGX_ERROR) { + ngx_http_v2_finalize_connection(h2c, 0); + return; + } + + h2c->blocked = 0; + + if (h2c->processing) { + if (rev->timer_set) { + ngx_del_timer(rev); + } + + return; + } + + ngx_http_v2_handle_connection(h2c); +} + + +static void +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; + h2c = c->data; + + if (wev->timedout) { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http2 write event timed out"); + c->error = 1; + ngx_http_v2_finalize_connection(h2c, 0); + return; + } + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http2 write handler"); + + h2c->blocked = 1; + + rc = ngx_http_v2_send_output_queue(h2c); + + if (rc == NGX_ERROR) { + ngx_http_v2_finalize_connection(h2c, 0); + 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->handler(wev); + } + + h2c->blocked = 0; + + if (rc == NGX_AGAIN) { + return; + } + + ngx_http_v2_handle_connection(h2c); +} + + +ngx_int_t +ngx_http_v2_send_output_queue(ngx_http_v2_connection_t *h2c) +{ + int tcp_nodelay; + ngx_chain_t *cl; + ngx_event_t *wev; + ngx_connection_t *c; + ngx_http_v2_out_frame_t *out, *frame, *fn; + ngx_http_core_loc_conf_t *clcf; + + c = h2c->connection; + + if (c->error) { + return NGX_ERROR; + } + + wev = c->write; + + if (!wev->ready) { + return NGX_OK; + } + + cl = NULL; + out = NULL; + + for (frame = h2c->last_out; frame; frame = fn) { + frame->last->next = cl; + cl = frame->first; + + fn = frame->next; + frame->next = out; + out = frame; + + ngx_log_debug4(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http2 frame out: %p sid:%ui bl:%d len:%uz", + out, out->stream ? out->stream->node->id : 0, + out->blocked, out->length); + } + + cl = c->send_chain(c, cl, 0); + + if (cl == NGX_CHAIN_ERROR) { + goto error; + } + + clcf = ngx_http_get_module_loc_conf(h2c->http_connection->conf_ctx, + ngx_http_core_module); + + if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) { + goto error; + } + + if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) { + if (ngx_tcp_push(c->fd) == -1) { + ngx_connection_error(c, ngx_socket_errno, ngx_tcp_push_n " failed"); + goto error; + } + + c->tcp_nopush = NGX_TCP_NOPUSH_UNSET; + tcp_nodelay = ngx_tcp_nodelay_and_tcp_nopush ? 1 : 0; + + } else { + tcp_nodelay = 1; + } + + if (tcp_nodelay + && clcf->tcp_nodelay + && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) + { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay"); + + if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, + (const void *) &tcp_nodelay, sizeof(int)) + == -1) + { +#if (NGX_SOLARIS) + /* Solaris returns EINVAL if a socket has been shut down */ + c->log_error = NGX_ERROR_IGNORE_EINVAL; +#endif + + ngx_connection_error(c, ngx_socket_errno, + "setsockopt(TCP_NODELAY) failed"); + + c->log_error = NGX_ERROR_INFO; + goto error; + } + + c->tcp_nodelay = NGX_TCP_NODELAY_SET; + } + + if (cl) { + ngx_add_timer(wev, clcf->send_timeout); + + } else { + if (wev->timer_set) { + ngx_del_timer(wev); + } + } + + for ( /* void */ ; out; out = fn) { + fn = out->next; + + if (out->handler(h2c, out) != NGX_OK) { + out->blocked = 1; + break; + } + + ngx_log_debug4(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http2 frame sent: %p sid:%ui bl:%d len:%uz", + out, out->stream ? out->stream->node->id : 0, + out->blocked, out->length); + } + + frame = NULL; + + for ( /* void */ ; out; out = fn) { + fn = out->next; + out->next = frame; + frame = out; + } + + h2c->last_out = frame; + + return NGX_OK; + +error: + + c->error = 1; + + if (!h2c->blocked) { + ngx_post_event(wev, &ngx_posted_events); + } + + return NGX_ERROR; +} + + +static void +ngx_http_v2_handle_connection(ngx_http_v2_connection_t *h2c) +{ + ngx_connection_t *c; + ngx_http_v2_srv_conf_t *h2scf; + + if (h2c->last_out || h2c->processing) { + return; + } + + c = h2c->connection; + + if (c->error) { + ngx_http_close_connection(c); + return; + } + + if (c->buffered) { + return; + } + + h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, + ngx_http_v2_module); + if (h2c->state.incomplete) { + ngx_add_timer(c->read, h2scf->recv_timeout); + return; + } + + if (ngx_terminate || ngx_exiting) { + ngx_http_close_connection(c); + return; + } + + ngx_destroy_pool(h2c->pool); + + h2c->pool = NULL; + h2c->free_frames = NULL; + h2c->free_fake_connections = NULL; + +#if (NGX_HTTP_SSL) + if (c->ssl) { + ngx_ssl_free_buffer(c); + } +#endif + + c->destroyed = 1; + c->idle = 1; + ngx_reusable_connection(c, 1); + + c->write->handler = ngx_http_empty_handler; + c->read->handler = ngx_http_v2_idle_handler; + + if (c->write->timer_set) { + ngx_del_timer(c->write); + } + + ngx_add_timer(c->read, h2scf->idle_timeout); +} + + +static u_char * +ngx_http_v2_state_proxy_protocol(ngx_http_v2_connection_t *h2c, u_char *pos, + u_char *end) +{ + ngx_log_t *log; + + log = h2c->connection->log; + log->action = "reading PROXY protocol"; + + pos = ngx_proxy_protocol_read(h2c->connection, pos, end); + + log->action = "processing HTTP/2 connection"; + + if (pos == NULL) { + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR); + } + + return ngx_http_v2_state_preface(h2c, pos, end); +} + + +static u_char * +ngx_http_v2_state_preface(ngx_http_v2_connection_t *h2c, u_char *pos, + u_char *end) +{ + static const u_char preface[] = "PRI * HTTP/2.0\r\n"; + + if ((size_t) (end - pos) < sizeof(preface) - 1) { + return ngx_http_v2_state_save(h2c, pos, end, ngx_http_v2_state_preface); + } + + if (ngx_memcmp(pos, preface, sizeof(preface) - 1) != 0) { + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "invalid http2 connection preface \"%*s\"", + sizeof(preface) - 1, pos); + + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR); + } + + return ngx_http_v2_state_preface_end(h2c, pos + sizeof(preface) - 1, end); +} + + +static u_char * +ngx_http_v2_state_preface_end(ngx_http_v2_connection_t *h2c, u_char *pos, + u_char *end) +{ + static const u_char preface[] = "\r\nSM\r\n\r\n"; + + if ((size_t) (end - pos) < sizeof(preface) - 1) { + return ngx_http_v2_state_save(h2c, pos, end, + ngx_http_v2_state_preface_end); + } + + if (ngx_memcmp(pos, preface, sizeof(preface) - 1) != 0) { + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "invalid http2 connection preface \"%*s\"", + sizeof(preface) - 1, pos); + + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR); + } + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "http2 preface verified"); + + return ngx_http_v2_state_head(h2c, pos + sizeof(preface) - 1, end); +} + + +static u_char * +ngx_http_v2_state_head(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end) +{ + uint32_t head; + ngx_uint_t type; + + if (end - pos < NGX_HTTP_V2_FRAME_HEADER_SIZE) { + return ngx_http_v2_state_save(h2c, pos, end, ngx_http_v2_state_head); + } + + head = ngx_http_v2_parse_uint32(pos); + + h2c->state.length = ngx_http_v2_parse_length(head); + h2c->state.flags = pos[4]; + + h2c->state.sid = ngx_http_v2_parse_sid(&pos[5]); + + pos += NGX_HTTP_V2_FRAME_HEADER_SIZE; + + type = ngx_http_v2_parse_type(head); + + ngx_log_debug4(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "process http2 frame type:%ui f:%Xd l:%uz sid:%ui", + type, h2c->state.flags, h2c->state.length, h2c->state.sid); + + if (type >= NGX_HTTP_V2_FRAME_STATES) { + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "http2 frame with unknown type %ui", type); + return ngx_http_v2_state_skip(h2c, pos, end); + } + + return ngx_http_v2_frame_states[type](h2c, pos, end); +} + + +static u_char * +ngx_http_v2_state_data(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end) +{ + ngx_http_v2_node_t *node; + ngx_http_v2_stream_t *stream; + + if (h2c->state.flags & NGX_HTTP_V2_PADDED_FLAG) { + + if (h2c->state.length == 0) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent padded DATA frame " + "with incorrect length: %uz", + h2c->state.length); + + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR); + } + + if (end - pos == 0) { + return ngx_http_v2_state_save(h2c, pos, end, + ngx_http_v2_state_data); + } + + h2c->state.padding = *pos++; + h2c->state.length--; + + if (h2c->state.padding > h2c->state.length) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent padded DATA frame " + "with incorrect length: %uz, padding: %uz", + h2c->state.length, h2c->state.padding); + + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR); + } + + h2c->state.length -= h2c->state.padding; + } + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "http2 DATA frame"); + + if (h2c->state.length > h2c->recv_window) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client violated connection flow control: " + "received DATA frame length %uz, available window %uz", + h2c->state.length, h2c->recv_window); + + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_FLOW_CTRL_ERROR); + } + + h2c->recv_window -= h2c->state.length; + + if (h2c->recv_window < NGX_HTTP_V2_MAX_WINDOW / 4) { + + if (ngx_http_v2_send_window_update(h2c, 0, NGX_HTTP_V2_MAX_WINDOW + - h2c->recv_window) + == NGX_ERROR) + { + return ngx_http_v2_connection_error(h2c, + NGX_HTTP_V2_INTERNAL_ERROR); + } + + h2c->recv_window = NGX_HTTP_V2_MAX_WINDOW; + } + + node = ngx_http_v2_get_node_by_id(h2c, h2c->state.sid, 0); + + if (node == NULL || node->stream == NULL) { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "unknown http2 stream"); + + return ngx_http_v2_state_skip_padded(h2c, pos, end); + } + + stream = node->stream; + + if (h2c->state.length > stream->recv_window) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client violated flow control for stream %ui: " + "received DATA frame length %uz, available window %uz", + node->id, h2c->state.length, stream->recv_window); + + if (ngx_http_v2_terminate_stream(h2c, stream, + NGX_HTTP_V2_FLOW_CTRL_ERROR) + == NGX_ERROR) + { + return ngx_http_v2_connection_error(h2c, + NGX_HTTP_V2_INTERNAL_ERROR); + } + + return ngx_http_v2_state_skip_padded(h2c, pos, end); + } + + stream->recv_window -= h2c->state.length; + + if (stream->recv_window < NGX_HTTP_V2_MAX_WINDOW / 4) { + + if (ngx_http_v2_send_window_update(h2c, node->id, + NGX_HTTP_V2_MAX_WINDOW + - stream->recv_window) + == NGX_ERROR) + { + return ngx_http_v2_connection_error(h2c, + NGX_HTTP_V2_INTERNAL_ERROR); + } + + stream->recv_window = NGX_HTTP_V2_MAX_WINDOW; + } + + if (stream->in_closed) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent DATA frame for half-closed stream %ui", + node->id); + + if (ngx_http_v2_terminate_stream(h2c, stream, + NGX_HTTP_V2_STREAM_CLOSED) + == NGX_ERROR) + { + return ngx_http_v2_connection_error(h2c, + NGX_HTTP_V2_INTERNAL_ERROR); + } + + return ngx_http_v2_state_skip_padded(h2c, pos, end); + } + + h2c->state.stream = stream; + + return ngx_http_v2_state_read_data(h2c, pos, end); +} + + +static u_char * +ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos, + u_char *end) +{ + size_t size; + ssize_t n; + ngx_buf_t *buf; + ngx_int_t rc; + ngx_temp_file_t *tf; + ngx_http_request_t *r; + ngx_http_v2_stream_t *stream; + ngx_http_request_body_t *rb; + ngx_http_core_loc_conf_t *clcf; + + stream = h2c->state.stream; + + if (stream == NULL) { + return ngx_http_v2_state_skip_padded(h2c, pos, end); + } + + if (stream->skip_data) { + stream->in_closed = h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "skipping http2 DATA frame, reason: %d", + stream->skip_data); + + return ngx_http_v2_state_skip_padded(h2c, pos, end); + } + + size = end - pos; + + if (size > h2c->state.length) { + size = h2c->state.length; + } + + r = stream->request; + + if (r->request_body == NULL + && ngx_http_v2_init_request_body(r) != NGX_OK) + { + stream->skip_data = NGX_HTTP_V2_DATA_INTERNAL_ERROR; + return ngx_http_v2_state_skip_padded(h2c, pos, end); + } + + rb = r->request_body; + tf = rb->temp_file; + buf = rb->buf; + + if (size) { + rb->rest += size; + + if (r->headers_in.content_length_n != -1 + && r->headers_in.content_length_n < rb->rest) + { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client intended to send body data " + "larger than declared"); + + stream->skip_data = NGX_HTTP_V2_DATA_ERROR; + goto error; + + } else { + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + if (clcf->client_max_body_size + && clcf->client_max_body_size < rb->rest) + { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "client intended to send " + "too large chunked body: %O bytes", rb->rest); + + stream->skip_data = NGX_HTTP_V2_DATA_ERROR; + goto error; + } + } + + h2c->state.length -= size; + + if (tf) { + buf->start = pos; + buf->pos = pos; + + pos += size; + + buf->end = pos; + buf->last = pos; + + n = ngx_write_chain_to_temp_file(tf, rb->bufs); + + /* TODO: n == 0 or not complete and level event */ + + if (n == NGX_ERROR) { + stream->skip_data = NGX_HTTP_V2_DATA_INTERNAL_ERROR; + goto error; + } + + tf->offset += n; + + } else { + buf->last = ngx_cpymem(buf->last, pos, size); + pos += size; + } + + r->request_length += size; + } + + if (h2c->state.length) { + return ngx_http_v2_state_save(h2c, pos, end, + ngx_http_v2_state_read_data); + } + + if (h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG) { + stream->in_closed = 1; + + if (r->headers_in.content_length_n < 0) { + r->headers_in.content_length_n = rb->rest; + + } else if (r->headers_in.content_length_n != rb->rest) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client prematurely closed stream: " + "only %O out of %O bytes of request body received", + rb->rest, r->headers_in.content_length_n); + + stream->skip_data = NGX_HTTP_V2_DATA_ERROR; + goto error; + } + + if (tf) { + ngx_memzero(buf, sizeof(ngx_buf_t)); + + buf->in_file = 1; + buf->file_last = tf->file.offset; + buf->file = &tf->file; + + rb->buf = NULL; + } + + if (rb->post_handler) { + r->read_event_handler = ngx_http_block_reading; + rb->post_handler(r); + } + } + + if (h2c->state.padding) { + return ngx_http_v2_state_skip_padded(h2c, pos, end); + } + + return ngx_http_v2_state_complete(h2c, pos, end); + +error: + + if (rb->post_handler) { + + if (stream->skip_data == NGX_HTTP_V2_DATA_ERROR) { + rc = (r->headers_in.content_length_n == -1) + ? NGX_HTTP_REQUEST_ENTITY_TOO_LARGE : NGX_HTTP_BAD_REQUEST; + + } else { + rc = NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + ngx_http_finalize_request(r, rc); + } + + return ngx_http_v2_state_skip_padded(h2c, pos, end); +} + + +static u_char * +ngx_http_v2_state_headers(ngx_http_v2_connection_t *h2c, u_char *pos, + u_char *end) +{ + size_t size; + ngx_uint_t padded, priority, depend, dependency, excl, weight; + ngx_http_v2_node_t *node; + ngx_http_v2_stream_t *stream; + ngx_http_v2_srv_conf_t *h2scf; + + padded = h2c->state.flags & NGX_HTTP_V2_PADDED_FLAG; + priority = h2c->state.flags & NGX_HTTP_V2_PRIORITY_FLAG; + + size = 0; + + if (padded) { + size++; + } + + if (priority) { + size += sizeof(uint32_t) + 1; + } + + if (h2c->state.length < size) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent HEADERS frame with incorrect length %uz", + h2c->state.length); + + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR); + } + + if (h2c->state.length == size) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent HEADERS frame with empty header block"); + + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR); + } + + if ((size_t) (end - pos) < size) { + return ngx_http_v2_state_save(h2c, pos, end, + ngx_http_v2_state_headers); + } + + h2c->state.length -= size; + + if (padded) { + h2c->state.padding = *pos++; + + if (h2c->state.padding > h2c->state.length) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent padded HEADERS frame " + "with incorrect length: %uz, padding: %uz", + h2c->state.length, h2c->state.padding); + + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR); + } + + h2c->state.length -= h2c->state.padding; + } + + depend = 0; + excl = 0; + weight = 16; + + if (priority) { + dependency = ngx_http_v2_parse_uint32(pos); + + depend = dependency & 0x7fffffff; + excl = dependency >> 31; + weight = pos[4] + 1; + + pos += sizeof(uint32_t) + 1; + } + + ngx_log_debug4(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "http2 HEADERS frame sid:%ui on %ui excl:%ui weight:%ui", + h2c->state.sid, depend, excl, weight); + + if (h2c->state.sid % 2 == 0 || h2c->state.sid <= h2c->last_sid) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent HEADERS frame with incorrect identifier " + "%ui, the last was %ui", h2c->state.sid, h2c->last_sid); + + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR); + } + + h2c->last_sid = h2c->state.sid; + + h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, + ngx_http_v2_module); + + h2c->state.header_limit = h2scf->max_header_size; + + if (h2c->processing >= h2scf->concurrent_streams) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "concurrent streams exceeded %ui", h2c->processing); + + if (ngx_http_v2_send_rst_stream(h2c, h2c->state.sid, + NGX_HTTP_V2_REFUSED_STREAM) + != NGX_OK) + { + return ngx_http_v2_connection_error(h2c, + NGX_HTTP_V2_INTERNAL_ERROR); + } + + return ngx_http_v2_state_skip_headers(h2c, pos, end); + } + + node = ngx_http_v2_get_node_by_id(h2c, h2c->state.sid, 1); + + if (node == NULL) { + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR); + } + + if (node->parent) { + ngx_queue_remove(&node->reuse); + h2c->closed_nodes--; + } + + stream = ngx_http_v2_create_stream(h2c); + if (stream == NULL) { + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR); + } + + stream->in_closed = h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG; + stream->node = node; + + node->stream = stream; + + h2c->state.stream = stream; + h2c->state.pool = stream->request->pool; + + if (priority || node->parent == NULL) { + node->weight = weight; + ngx_http_v2_set_dependency(h2c, node, depend, excl); + } + + return ngx_http_v2_state_header_block(h2c, pos, end); +} + + +static u_char * +ngx_http_v2_state_header_block(ngx_http_v2_connection_t *h2c, u_char *pos, + u_char *end) +{ + u_char ch; + ngx_int_t value; + ngx_uint_t indexed, size_update, prefix; + ngx_http_v2_srv_conf_t *h2scf; + + if (end - pos < 1) { + return ngx_http_v2_state_save(h2c, pos, end, + ngx_http_v2_state_header_block); + } + + if (!(h2c->state.flags & NGX_HTTP_V2_END_HEADERS_FLAG) + && h2c->state.length < NGX_HTTP_V2_INT_OCTETS) + { + return ngx_http_v2_handle_continuation(h2c, pos, end, + ngx_http_v2_state_header_block); + } + + size_update = 0; + indexed = 0; + + ch = *pos; + + if (ch >= (1 << 7)) { + /* indexed header field */ + indexed = 1; + prefix = ngx_http_v2_prefix(7); + + } else if (ch >= (1 << 6)) { + /* literal header field with incremental indexing */ + h2c->state.index = 1; + prefix = ngx_http_v2_prefix(6); + + } else if (ch >= (1 << 5)) { + /* dynamic table size update */ + size_update = 1; + prefix = ngx_http_v2_prefix(5); + + } else if (ch >= (1 << 4)) { + /* literal header field never indexed */ + prefix = ngx_http_v2_prefix(4); + + } else { + /* literal header field without indexing */ + prefix = ngx_http_v2_prefix(3); + } + + value = ngx_http_v2_parse_int(h2c, &pos, end, prefix); + + if (value < 0) { + if (value == NGX_AGAIN) { + return ngx_http_v2_state_save(h2c, pos, end, + ngx_http_v2_state_header_block); + } + + if (value == NGX_DECLINED) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent header block with too long %s value", + size_update ? "size update" : "header index"); + + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_COMP_ERROR); + } + + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent header block with incorrect length"); + + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR); + } + + if (indexed) { + if (ngx_http_v2_get_indexed_header(h2c, value, 0) != NGX_OK) { + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_COMP_ERROR); + } + + return ngx_http_v2_state_process_header(h2c, pos, end); + } + + if (size_update) { + if (ngx_http_v2_table_size(h2c, value) != NGX_OK) { + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_COMP_ERROR); + } + + return ngx_http_v2_state_header_complete(h2c, pos, end); + } + + h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, + ngx_http_v2_module); + + h2c->state.field_limit = h2scf->max_field_size; + + if (value == 0) { + h2c->state.parse_name = 1; + + } else { + if (ngx_http_v2_get_indexed_header(h2c, value, 1) != NGX_OK) { + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_COMP_ERROR); + } + + h2c->state.field_limit -= h2c->state.header.name.len; + } + + h2c->state.parse_value = 1; + + return ngx_http_v2_state_field_len(h2c, pos, end); +} + + +static u_char * +ngx_http_v2_state_field_len(ngx_http_v2_connection_t *h2c, u_char *pos, + u_char *end) +{ + size_t alloc; + ngx_int_t len; + ngx_uint_t huff; + + if (!(h2c->state.flags & NGX_HTTP_V2_END_HEADERS_FLAG) + && h2c->state.length < NGX_HTTP_V2_INT_OCTETS) + { + return ngx_http_v2_handle_continuation(h2c, pos, end, + ngx_http_v2_state_field_len); + } + + if (h2c->state.length < 1) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent header block with incorrect length"); + + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR); + } + + if (end - pos < 1) { + return ngx_http_v2_state_save(h2c, pos, end, + ngx_http_v2_state_field_len); + } + + huff = *pos >> 7; + len = ngx_http_v2_parse_int(h2c, &pos, end, ngx_http_v2_prefix(7)); + + if (len < 0) { + if (len == NGX_AGAIN) { + return ngx_http_v2_state_save(h2c, pos, end, + ngx_http_v2_state_field_len); + } + + if (len == NGX_DECLINED) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent header field with too long length value"); + + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_COMP_ERROR); + } + + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent header block with incorrect length"); + + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR); + } + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "http2 hpack %s string length: %i", + huff ? "encoded" : "raw", len); + + if ((size_t) len > h2c->state.field_limit) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client exceeded http2_max_field_size limit"); + + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_ENHANCE_YOUR_CALM); + } + + h2c->state.field_limit -= len; + h2c->state.field_rest = len; + + if (h2c->state.stream == NULL && !h2c->state.index) { + return ngx_http_v2_state_field_skip(h2c, pos, end); + } + + alloc = (huff ? len * 8 / 5 : len) + 1; + + h2c->state.field_start = ngx_pnalloc(h2c->state.pool, alloc); + if (h2c->state.field_start == NULL) { + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR); + } + + h2c->state.field_end = h2c->state.field_start; + + if (huff) { + return ngx_http_v2_state_field_huff(h2c, pos, end); + } + + return ngx_http_v2_state_field_raw(h2c, pos, end); +} + + +static u_char * +ngx_http_v2_state_field_huff(ngx_http_v2_connection_t *h2c, u_char *pos, + u_char *end) +{ + size_t size; + + size = end - pos; + + if (size > h2c->state.field_rest) { + size = h2c->state.field_rest; + } + + if (size > h2c->state.length) { + size = h2c->state.length; + } + + h2c->state.length -= size; + h2c->state.field_rest -= size; + + if (ngx_http_v2_huff_decode(&h2c->state.field_state, pos, size, + &h2c->state.field_end, + h2c->state.field_rest == 0, + h2c->connection->log) + != NGX_OK) + { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent invalid encoded header field"); + + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_COMP_ERROR); + } + + pos += size; + + if (h2c->state.field_rest == 0) { + *h2c->state.field_end = '\0'; + return ngx_http_v2_state_process_header(h2c, pos, end); + } + + if (h2c->state.length) { + return ngx_http_v2_state_save(h2c, pos, end, + ngx_http_v2_state_field_huff); + } + + if (h2c->state.flags & NGX_HTTP_V2_END_HEADERS_FLAG) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent header field with incorrect length"); + + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR); + } + + return ngx_http_v2_handle_continuation(h2c, pos, end, + ngx_http_v2_state_field_huff); +} + + +static u_char * +ngx_http_v2_state_field_raw(ngx_http_v2_connection_t *h2c, u_char *pos, + u_char *end) +{ + size_t size; + + size = end - pos; + + if (size > h2c->state.field_rest) { + size = h2c->state.field_rest; + } + + if (size > h2c->state.length) { + size = h2c->state.length; + } + + h2c->state.length -= size; + h2c->state.field_rest -= size; + + h2c->state.field_end = ngx_cpymem(h2c->state.field_end, pos, size); + + pos += size; + + if (h2c->state.field_rest == 0) { + *h2c->state.field_end = '\0'; + return ngx_http_v2_state_process_header(h2c, pos, end); + } + + if (h2c->state.length) { + return ngx_http_v2_state_save(h2c, pos, end, + ngx_http_v2_state_field_raw); + } + + if (h2c->state.flags & NGX_HTTP_V2_END_HEADERS_FLAG) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent header field with incorrect length"); + + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR); + } + + return ngx_http_v2_handle_continuation(h2c, pos, end, + ngx_http_v2_state_field_raw); +} + + +static u_char * +ngx_http_v2_state_field_skip(ngx_http_v2_connection_t *h2c, u_char *pos, + u_char *end) +{ + size_t size; + + size = end - pos; + + if (size > h2c->state.field_rest) { + size = h2c->state.field_rest; + } + + if (size > h2c->state.length) { + size = h2c->state.length; + } + + h2c->state.length -= size; + h2c->state.field_rest -= size; + + pos += size; + + if (h2c->state.field_rest == 0) { + return ngx_http_v2_state_process_header(h2c, pos, end); + } + + if (h2c->state.length) { + return ngx_http_v2_state_save(h2c, pos, end, + ngx_http_v2_state_field_skip); + } + + if (h2c->state.flags & NGX_HTTP_V2_END_HEADERS_FLAG) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent header field with incorrect length"); + + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR); + } + + return ngx_http_v2_handle_continuation(h2c, pos, end, + ngx_http_v2_state_field_skip); +} + + +static u_char * +ngx_http_v2_state_process_header(ngx_http_v2_connection_t *h2c, u_char *pos, + u_char *end) +{ + size_t len; + ngx_int_t rc; + ngx_table_elt_t *h; + ngx_http_header_t *hh; + ngx_http_request_t *r; + ngx_http_v2_header_t *header; + ngx_http_core_srv_conf_t *cscf; + ngx_http_core_main_conf_t *cmcf; + + static ngx_str_t cookie = ngx_string("cookie"); + + header = &h2c->state.header; + + if (h2c->state.parse_name) { + h2c->state.parse_name = 0; + + header->name.len = h2c->state.field_end - h2c->state.field_start; + header->name.data = h2c->state.field_start; + + return ngx_http_v2_state_field_len(h2c, pos, end); + } + + if (h2c->state.parse_value) { + h2c->state.parse_value = 0; + + header->value.len = h2c->state.field_end - h2c->state.field_start; + header->value.data = h2c->state.field_start; + } + + len = header->name.len + header->value.len; + + if (len > h2c->state.header_limit) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client exceeded http2_max_header_size limit"); + + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_ENHANCE_YOUR_CALM); + } + + h2c->state.header_limit -= len; + + if (h2c->state.index) { + if (ngx_http_v2_add_header(h2c, header) != NGX_OK) { + return ngx_http_v2_connection_error(h2c, + NGX_HTTP_V2_INTERNAL_ERROR); + } + + h2c->state.index = 0; + } + + if (h2c->state.stream == NULL) { + return ngx_http_v2_state_header_complete(h2c, pos, end); + } + + r = h2c->state.stream->request; + + /* TODO Optimization: validate headers while parsing. */ + if (ngx_http_v2_validate_header(r, header) != NGX_OK) { + if (ngx_http_v2_terminate_stream(h2c, h2c->state.stream, + NGX_HTTP_V2_PROTOCOL_ERROR) + == NGX_ERROR) + { + return ngx_http_v2_connection_error(h2c, + NGX_HTTP_V2_INTERNAL_ERROR); + } + + goto error; + } + + if (header->name.data[0] == ':') { + rc = ngx_http_v2_pseudo_header(r, header); + + if (rc == NGX_OK) { + return ngx_http_v2_state_header_complete(h2c, pos, end); + } + + if (rc == NGX_ABORT) { + goto error; + } + + if (rc == NGX_DECLINED) { + if (ngx_http_v2_terminate_stream(h2c, h2c->state.stream, + NGX_HTTP_V2_PROTOCOL_ERROR) + == NGX_ERROR) + { + return ngx_http_v2_connection_error(h2c, + NGX_HTTP_V2_INTERNAL_ERROR); + } + + goto error; + } + + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR); + } + + if (r->invalid_header) { + cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); + + if (cscf->ignore_invalid_headers) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent invalid header: \"%V\"", &header->name); + + return ngx_http_v2_state_header_complete(h2c, pos, end); + } + } + + if (header->name.len == cookie.len + && ngx_memcmp(header->name.data, cookie.data, cookie.len) == 0) + { + if (ngx_http_v2_cookie(r, header) != NGX_OK) { + return ngx_http_v2_connection_error(h2c, + NGX_HTTP_V2_INTERNAL_ERROR); + } + + return ngx_http_v2_state_header_complete(h2c, pos, end); + } + + h = ngx_list_push(&r->headers_in.headers); + if (h == NULL) { + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR); + } + + h->key.len = header->name.len; + h->key.data = header->name.data; + + /* TODO Optimization: precalculate hash and hadnler for indexed headers. */ + h->hash = ngx_hash_key(h->key.data, h->key.len); + + h->value.len = header->value.len; + h->value.data = header->value.data; + + h->lowcase_key = h->key.data; + + cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); + + hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash, + h->lowcase_key, h->key.len); + + if (hh && hh->handler(r, h, hh->offset) != NGX_OK) { + goto error; + } + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http2 http header: \"%V: %V\"", &h->key, &h->value); + + return ngx_http_v2_state_header_complete(h2c, pos, end); + +error: + + h2c->state.stream = NULL; + h2c->state.pool = NULL; + + return ngx_http_v2_state_header_complete(h2c, pos, end); +} + + +static u_char * +ngx_http_v2_state_header_complete(ngx_http_v2_connection_t *h2c, u_char *pos, + u_char *end) +{ + ngx_http_v2_stream_t *stream; + + if (h2c->state.length) { + h2c->state.handler = h2c->state.pool ? ngx_http_v2_state_header_block + : ngx_http_v2_state_skip_headers; + return pos; + } + + if (!(h2c->state.flags & NGX_HTTP_V2_END_HEADERS_FLAG)) { + return ngx_http_v2_handle_continuation(h2c, pos, end, + ngx_http_v2_state_header_complete); + } + + stream = h2c->state.stream; + + if (stream) { + ngx_http_v2_run_request(stream->request); + + } else if (h2c->state.pool) { + ngx_destroy_pool(h2c->state.pool); + } + + h2c->state.pool = NULL; + + if (h2c->state.padding) { + return ngx_http_v2_state_skip_padded(h2c, pos, end); + } + + return ngx_http_v2_state_complete(h2c, pos, end); +} + + +static u_char * +ngx_http_v2_handle_continuation(ngx_http_v2_connection_t *h2c, u_char *pos, + u_char *end, ngx_http_v2_handler_pt handler) +{ + u_char *p; + size_t len; + uint32_t head; + + len = h2c->state.length; + + if ((size_t) (end - pos) < len + NGX_HTTP_V2_FRAME_HEADER_SIZE) { + return ngx_http_v2_state_save(h2c, pos, end, handler); + } + + p = pos + len; + + head = ngx_http_v2_parse_uint32(p); + + if (ngx_http_v2_parse_type(head) != NGX_HTTP_V2_CONTINUATION_FRAME) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent inappropriate frame while CONTINUATION was expected"); + + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR); + } + + h2c->state.length += ngx_http_v2_parse_length(head); + h2c->state.flags |= p[4]; + + if (h2c->state.sid != ngx_http_v2_parse_sid(&p[5])) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent CONTINUATION frame with incorrect identifier"); + + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR); + } + + p = pos; + pos += NGX_HTTP_V2_FRAME_HEADER_SIZE; + + ngx_memcpy(pos, p, len); + + h2c->state.handler = handler; + return pos; +} + + +static u_char * +ngx_http_v2_state_priority(ngx_http_v2_connection_t *h2c, u_char *pos, + u_char *end) +{ + ngx_uint_t depend, dependency, excl, weight; + ngx_http_v2_node_t *node; + + if (h2c->state.length != NGX_HTTP_V2_PRIORITY_SIZE) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent PRIORITY frame with incorrect length %uz", + h2c->state.length); + + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR); + } + + if (end - pos < NGX_HTTP_V2_PRIORITY_SIZE) { + return ngx_http_v2_state_save(h2c, pos, end, + ngx_http_v2_state_priority); + } + + dependency = ngx_http_v2_parse_uint32(pos); + + depend = dependency & 0x7fffffff; + excl = dependency >> 31; + weight = pos[4] + 1; + + pos += NGX_HTTP_V2_PRIORITY_SIZE; + + ngx_log_debug4(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "http2 PRIORITY frame sid:%ui on %ui excl:%ui weight:%ui", + h2c->state.sid, depend, excl, weight); + + if (h2c->state.sid == 0) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent PRIORITY frame with incorrect identifier"); + + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR); + } + + if (depend == h2c->state.sid) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent PRIORITY frame for stream %ui " + "with incorrect dependancy", h2c->state.sid); + + node = ngx_http_v2_get_node_by_id(h2c, h2c->state.sid, 0); + + if (node && node->stream) { + if (ngx_http_v2_terminate_stream(h2c, node->stream, + NGX_HTTP_V2_PROTOCOL_ERROR) + == NGX_ERROR) + { + return ngx_http_v2_connection_error(h2c, + NGX_HTTP_V2_INTERNAL_ERROR); + } + + } else { + if (ngx_http_v2_send_rst_stream(h2c, h2c->state.sid, + NGX_HTTP_V2_PROTOCOL_ERROR) + == NGX_ERROR) + { + return ngx_http_v2_connection_error(h2c, + NGX_HTTP_V2_INTERNAL_ERROR); + } + } + + return ngx_http_v2_state_complete(h2c, pos, end); + } + + node = ngx_http_v2_get_node_by_id(h2c, h2c->state.sid, 1); + + if (node == NULL) { + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR); + } + + node->weight = weight; + + if (node->stream == NULL) { + if (node->parent == NULL) { + h2c->closed_nodes++; + + } else { + ngx_queue_remove(&node->reuse); + } + + ngx_queue_insert_tail(&h2c->closed, &node->reuse); + } + + ngx_http_v2_set_dependency(h2c, node, depend, excl); + + return ngx_http_v2_state_complete(h2c, pos, end); +} + + +static u_char * +ngx_http_v2_state_rst_stream(ngx_http_v2_connection_t *h2c, u_char *pos, + u_char *end) +{ + ngx_uint_t status; + ngx_event_t *ev; + ngx_connection_t *fc; + ngx_http_v2_node_t *node; + ngx_http_v2_stream_t *stream; + + if (h2c->state.length != NGX_HTTP_V2_RST_STREAM_SIZE) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent RST_STREAM frame with incorrect length %uz", + h2c->state.length); + + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR); + } + + if (end - pos < NGX_HTTP_V2_RST_STREAM_SIZE) { + return ngx_http_v2_state_save(h2c, pos, end, + ngx_http_v2_state_rst_stream); + } + + status = ngx_http_v2_parse_uint32(pos); + + pos += NGX_HTTP_V2_RST_STREAM_SIZE; + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "http2 RST_STREAM frame, sid:%ui status:%ui", + h2c->state.sid, status); + + if (h2c->state.sid == 0) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent RST_STREAM frame with incorrect identifier"); + + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR); + } + + node = ngx_http_v2_get_node_by_id(h2c, h2c->state.sid, 0); + + if (node == NULL || node->stream == NULL) { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "unknown http2 stream"); + + return ngx_http_v2_state_complete(h2c, pos, end); + } + + stream = node->stream; + + stream->in_closed = 1; + stream->out_closed = 1; + + fc = stream->request->connection; + fc->error = 1; + + switch (status) { + + case NGX_HTTP_V2_CANCEL: + ngx_log_error(NGX_LOG_INFO, fc->log, 0, + "client canceled stream %ui", h2c->state.sid); + break; + + case NGX_HTTP_V2_INTERNAL_ERROR: + ngx_log_error(NGX_LOG_INFO, fc->log, 0, + "client terminated stream %ui due to internal error", + h2c->state.sid); + break; + + default: + ngx_log_error(NGX_LOG_INFO, fc->log, 0, + "client terminated stream %ui with status %ui", + h2c->state.sid, status); + break; + } + + ev = fc->read; + ev->handler(ev); + + return ngx_http_v2_state_complete(h2c, pos, end); +} + + +static u_char * +ngx_http_v2_state_settings(ngx_http_v2_connection_t *h2c, u_char *pos, + u_char *end) +{ + if (h2c->state.flags == NGX_HTTP_V2_ACK_FLAG) { + + if (h2c->state.length != 0) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent SETTINGS frame with the ACK flag " + "and nonzero length"); + + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR); + } + + /* TODO settings acknowledged */ + + return ngx_http_v2_state_complete(h2c, pos, end); + } + + if (h2c->state.length % NGX_HTTP_V2_SETTINGS_PARAM_SIZE) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent SETTINGS frame with incorrect length %uz", + h2c->state.length); + + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR); + } + + ngx_http_v2_send_settings(h2c, 1); + + return ngx_http_v2_state_settings_params(h2c, pos, end); +} + + +static u_char * +ngx_http_v2_state_settings_params(ngx_http_v2_connection_t *h2c, u_char *pos, + u_char *end) +{ + ngx_uint_t id, value; + + while (h2c->state.length) { + if (end - pos < NGX_HTTP_V2_SETTINGS_PARAM_SIZE) { + return ngx_http_v2_state_save(h2c, pos, end, + ngx_http_v2_state_settings_params); + } + + h2c->state.length -= NGX_HTTP_V2_SETTINGS_PARAM_SIZE; + + id = ngx_http_v2_parse_uint16(pos); + value = ngx_http_v2_parse_uint32(&pos[2]); + + switch (id) { + + case NGX_HTTP_V2_INIT_WINDOW_SIZE_SETTING: + + if (value > NGX_HTTP_V2_MAX_WINDOW) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent SETTINGS frame with incorrect " + "INITIAL_WINDOW_SIZE value %ui", value); + + return ngx_http_v2_connection_error(h2c, + NGX_HTTP_V2_FLOW_CTRL_ERROR); + } + + if (ngx_http_v2_adjust_windows(h2c, value - h2c->init_window) + != NGX_OK) + { + return ngx_http_v2_connection_error(h2c, + NGX_HTTP_V2_INTERNAL_ERROR); + } + + h2c->init_window = value; + break; + + case NGX_HTTP_V2_MAX_FRAME_SIZE_SETTING: + if (value > NGX_HTTP_V2_MAX_FRAME_SIZE + || value < NGX_HTTP_V2_DEFAULT_FRAME_SIZE) + { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent SETTINGS frame with incorrect " + "MAX_FRAME_SIZE value %ui", value); + + return ngx_http_v2_connection_error(h2c, + NGX_HTTP_V2_PROTOCOL_ERROR); + } + + h2c->frame_size = value; + break; + + default: + break; + } + + pos += NGX_HTTP_V2_SETTINGS_PARAM_SIZE; + } + + return ngx_http_v2_state_complete(h2c, pos, end); +} + + +static u_char * +ngx_http_v2_state_push_promise(ngx_http_v2_connection_t *h2c, u_char *pos, + u_char *end) +{ + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent PUSH_PROMISE frame"); + + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR); +} + + +static u_char * +ngx_http_v2_state_ping(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end) +{ + ngx_buf_t *buf; + ngx_http_v2_out_frame_t *frame; + + if (h2c->state.length != NGX_HTTP_V2_PING_SIZE) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent PING frame with incorrect length %uz", + h2c->state.length); + + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR); + } + + if (end - pos < NGX_HTTP_V2_PING_SIZE) { + return ngx_http_v2_state_save(h2c, pos, end, ngx_http_v2_state_ping); + } + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "http2 PING frame, flags: %ui", h2c->state.flags); + + if (h2c->state.flags & NGX_HTTP_V2_ACK_FLAG) { + return ngx_http_v2_state_skip(h2c, pos, end); + } + + frame = ngx_http_v2_get_frame(h2c, NGX_HTTP_V2_PING_SIZE, + NGX_HTTP_V2_PING_FRAME, + NGX_HTTP_V2_ACK_FLAG, 0); + if (frame == NULL) { + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR); + } + + buf = frame->first->buf; + + buf->last = ngx_cpymem(buf->last, pos, NGX_HTTP_V2_PING_SIZE); + + ngx_http_v2_queue_blocked_frame(h2c, frame); + + return ngx_http_v2_state_complete(h2c, pos + NGX_HTTP_V2_PING_SIZE, end); +} + + +static u_char * +ngx_http_v2_state_goaway(ngx_http_v2_connection_t *h2c, u_char *pos, + u_char *end) +{ +#if (NGX_DEBUG) + ngx_uint_t last_sid, error; +#endif + + if (h2c->state.length < NGX_HTTP_V2_GOAWAY_SIZE) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent GOAWAY frame " + "with incorrect length %uz", h2c->state.length); + + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR); + } + + if (end - pos < NGX_HTTP_V2_GOAWAY_SIZE) { + return ngx_http_v2_state_save(h2c, pos, end, ngx_http_v2_state_goaway); + } + +#if (NGX_DEBUG) + h2c->state.length -= NGX_HTTP_V2_GOAWAY_SIZE; + + last_sid = ngx_http_v2_parse_sid(pos); + error = ngx_http_v2_parse_uint32(&pos[4]); + + pos += NGX_HTTP_V2_GOAWAY_SIZE; + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "http2 GOAWAY frame: last sid %ui, error %ui", + last_sid, error); +#endif + + return ngx_http_v2_state_skip(h2c, pos, end); +} + + +static u_char * +ngx_http_v2_state_window_update(ngx_http_v2_connection_t *h2c, u_char *pos, + u_char *end) +{ + size_t window; + ngx_event_t *wev; + ngx_queue_t *q; + ngx_http_v2_node_t *node; + ngx_http_v2_stream_t *stream; + + if (h2c->state.length != NGX_HTTP_V2_WINDOW_UPDATE_SIZE) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent WINDOW_UPDATE frame " + "with incorrect length %uz", h2c->state.length); + + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR); + } + + if (end - pos < NGX_HTTP_V2_WINDOW_UPDATE_SIZE) { + return ngx_http_v2_state_save(h2c, pos, end, + ngx_http_v2_state_window_update); + } + + window = ngx_http_v2_parse_window(pos); + + pos += NGX_HTTP_V2_WINDOW_UPDATE_SIZE; + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "http2 WINDOW_UPDATE frame sid:%ui window:%uz", + h2c->state.sid, window); + + if (h2c->state.sid) { + node = ngx_http_v2_get_node_by_id(h2c, h2c->state.sid, 0); + + if (node == NULL || node->stream == NULL) { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "unknown http2 stream"); + + return ngx_http_v2_state_complete(h2c, pos, end); + } + + stream = node->stream; + + if (window > (size_t) (NGX_HTTP_V2_MAX_WINDOW - stream->send_window)) { + + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client violated flow control for stream %ui: " + "received WINDOW_UPDATE frame " + "with window increment %uz " + "not allowed for window %z", + h2c->state.sid, window, stream->send_window); + + if (ngx_http_v2_terminate_stream(h2c, stream, + NGX_HTTP_V2_FLOW_CTRL_ERROR) + == NGX_ERROR) + { + return ngx_http_v2_connection_error(h2c, + NGX_HTTP_V2_INTERNAL_ERROR); + } + + return ngx_http_v2_state_complete(h2c, pos, end); + } + + stream->send_window += window; + + if (stream->exhausted) { + stream->exhausted = 0; + + wev = stream->request->connection->write; + + if (!wev->timer_set) { + wev->delayed = 0; + wev->handler(wev); + } + } + + return ngx_http_v2_state_complete(h2c, pos, end); + } + + if (window > NGX_HTTP_V2_MAX_WINDOW - h2c->send_window) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client violated connection flow control: " + "received WINDOW_UPDATE frame " + "with window increment %uz " + "not allowed for window %uz", + window, h2c->send_window); + + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_FLOW_CTRL_ERROR); + } + + h2c->send_window += 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->handled = 0; + + wev = stream->request->connection->write; + + if (!wev->timer_set) { + wev->delayed = 0; + wev->handler(wev); + + if (h2c->send_window == 0) { + break; + } + } + } + + return ngx_http_v2_state_complete(h2c, pos, end); +} + + +static u_char * +ngx_http_v2_state_continuation(ngx_http_v2_connection_t *h2c, u_char *pos, + u_char *end) +{ + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent unexpected CONTINUATION frame"); + + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR); +} + + +static u_char * +ngx_http_v2_state_complete(ngx_http_v2_connection_t *h2c, u_char *pos, + u_char *end) +{ + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "http2 frame complete pos:%p end:%p", pos, end); + + if (pos > end) { + ngx_log_error(NGX_LOG_ALERT, h2c->connection->log, 0, + "receive buffer overrun"); + + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR); + } + + h2c->state.stream = NULL; + h2c->state.handler = ngx_http_v2_state_head; + + return pos; +} + + +static u_char * +ngx_http_v2_state_skip_padded(ngx_http_v2_connection_t *h2c, u_char *pos, + u_char *end) +{ + h2c->state.length += h2c->state.padding; + h2c->state.padding = 0; + + return ngx_http_v2_state_skip(h2c, pos, end); +} + + +static u_char * +ngx_http_v2_state_skip(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end) +{ + size_t size; + + size = end - pos; + + if (size < h2c->state.length) { + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "http2 frame skip %uz of %uz", size, h2c->state.length); + + h2c->state.length -= size; + return ngx_http_v2_state_save(h2c, end, end, ngx_http_v2_state_skip); + } + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "http2 frame skip %uz", h2c->state.length); + + return ngx_http_v2_state_complete(h2c, pos + h2c->state.length, end); +} + + +static u_char * +ngx_http_v2_state_skip_headers(ngx_http_v2_connection_t *h2c, u_char *pos, + u_char *end) +{ + h2c->state.pool = ngx_create_pool(1024, h2c->connection->log); + if (h2c->state.pool == NULL) { + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR); + } + + return ngx_http_v2_state_header_block(h2c, pos, end); +} + + +static u_char * +ngx_http_v2_state_save(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end, + ngx_http_v2_handler_pt handler) +{ + size_t size; + + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "http2 frame state save pos:%p end:%p handler:%p", + pos, end, handler); + + size = end - pos; + + if (size > NGX_HTTP_V2_STATE_BUFFER_SIZE) { + ngx_log_error(NGX_LOG_ALERT, h2c->connection->log, 0, + "state buffer overflow: %uz bytes required", size); + + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR); + } + + ngx_memcpy(h2c->state.buffer, pos, NGX_HTTP_V2_STATE_BUFFER_SIZE); + + h2c->state.buffer_used = size; + h2c->state.handler = handler; + h2c->state.incomplete = 1; + + return end; +} + + +static u_char * +ngx_http_v2_connection_error(ngx_http_v2_connection_t *h2c, + ngx_uint_t err) +{ + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "http2 state connection error"); + + if (err == NGX_HTTP_V2_INTERNAL_ERROR) { + ngx_debug_point(); + } + + if (h2c->state.stream) { + h2c->state.stream->out_closed = 1; + h2c->state.pool = NULL; + ngx_http_v2_close_stream(h2c->state.stream, NGX_HTTP_BAD_REQUEST); + } + + ngx_http_v2_finalize_connection(h2c, err); + + return NULL; +} + + +static ngx_int_t +ngx_http_v2_parse_int(ngx_http_v2_connection_t *h2c, u_char **pos, u_char *end, + ngx_uint_t prefix) +{ + u_char *start, *p; + ngx_uint_t value, octet, shift; + + start = *pos; + p = start; + + value = *p++ & prefix; + + if (value != prefix) { + if (h2c->state.length == 0) { + return NGX_ERROR; + } + + h2c->state.length--; + + *pos = p; + return value; + } + + if (end - p > NGX_HTTP_V2_INT_OCTETS - 1) { + end = p + NGX_HTTP_V2_INT_OCTETS - 1; + } + + for (shift = 0; p != end; shift += 7) { + octet = *p++; + + value += (octet & 0x7f) << shift; + + if (octet < 128) { + if ((size_t) (p - start) > h2c->state.length) { + return NGX_ERROR; + } + + h2c->state.length -= p - start; + + *pos = p; + return value; + } + } + + if ((size_t) (end - start) >= NGX_HTTP_V2_INT_OCTETS) { + return NGX_DECLINED; + } + + if ((size_t) (end - start) >= h2c->state.length) { + return NGX_ERROR; + } + + return NGX_AGAIN; +} + + +static ngx_int_t +ngx_http_v2_send_settings(ngx_http_v2_connection_t *h2c, ngx_uint_t ack) +{ + size_t len; + ngx_buf_t *buf; + ngx_chain_t *cl; + ngx_http_v2_srv_conf_t *h2scf; + ngx_http_v2_out_frame_t *frame; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "http2 send SETTINGS frame"); + + frame = ngx_palloc(h2c->pool, sizeof(ngx_http_v2_out_frame_t)); + if (frame == NULL) { + return NGX_ERROR; + } + + cl = ngx_alloc_chain_link(h2c->pool); + if (cl == NULL) { + return NGX_ERROR; + } + + len = ack ? 0 : (sizeof(uint16_t) + sizeof(uint32_t)) * 3; + + buf = ngx_create_temp_buf(h2c->pool, NGX_HTTP_V2_FRAME_HEADER_SIZE + len); + if (buf == NULL) { + return NGX_ERROR; + } + + buf->last_buf = 1; + + cl->buf = buf; + cl->next = NULL; + + frame->first = cl; + frame->last = cl; + frame->handler = ngx_http_v2_settings_frame_handler; + frame->stream = NULL; +#if (NGX_DEBUG) + frame->length = len; +#endif + frame->blocked = 0; + + buf->last = ngx_http_v2_write_len_and_type(buf->last, len, + NGX_HTTP_V2_SETTINGS_FRAME); + + *buf->last++ = ack ? NGX_HTTP_V2_ACK_FLAG : NGX_HTTP_V2_NO_FLAG; + + buf->last = ngx_http_v2_write_sid(buf->last, 0); + + if (!ack) { + h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, + ngx_http_v2_module); + + buf->last = ngx_http_v2_write_uint16(buf->last, + NGX_HTTP_V2_MAX_STREAMS_SETTING); + buf->last = ngx_http_v2_write_uint32(buf->last, + h2scf->concurrent_streams); + + buf->last = ngx_http_v2_write_uint16(buf->last, + NGX_HTTP_V2_INIT_WINDOW_SIZE_SETTING); + buf->last = ngx_http_v2_write_uint32(buf->last, + NGX_HTTP_V2_MAX_WINDOW); + + buf->last = ngx_http_v2_write_uint16(buf->last, + NGX_HTTP_V2_MAX_FRAME_SIZE_SETTING); + buf->last = ngx_http_v2_write_uint32(buf->last, + NGX_HTTP_V2_MAX_FRAME_SIZE); + } + + ngx_http_v2_queue_blocked_frame(h2c, frame); + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_v2_settings_frame_handler(ngx_http_v2_connection_t *h2c, + ngx_http_v2_out_frame_t *frame) +{ + ngx_buf_t *buf; + + buf = frame->first->buf; + + if (buf->pos != buf->last) { + return NGX_AGAIN; + } + + ngx_free_chain(h2c->pool, frame->first); + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_v2_send_window_update(ngx_http_v2_connection_t *h2c, ngx_uint_t sid, + size_t window) +{ + ngx_buf_t *buf; + ngx_http_v2_out_frame_t *frame; + + frame = ngx_http_v2_get_frame(h2c, NGX_HTTP_V2_WINDOW_UPDATE_SIZE, + NGX_HTTP_V2_WINDOW_UPDATE_FRAME, + NGX_HTTP_V2_NO_FLAG, sid); + if (frame == NULL) { + return NGX_ERROR; + } + + buf = frame->first->buf; + + buf->last = ngx_http_v2_write_uint32(buf->last, window); + + ngx_http_v2_queue_blocked_frame(h2c, frame); + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_v2_send_rst_stream(ngx_http_v2_connection_t *h2c, ngx_uint_t sid, + ngx_uint_t status) +{ + ngx_buf_t *buf; + ngx_http_v2_out_frame_t *frame; + + frame = ngx_http_v2_get_frame(h2c, NGX_HTTP_V2_RST_STREAM_SIZE, + NGX_HTTP_V2_RST_STREAM_FRAME, + NGX_HTTP_V2_NO_FLAG, sid); + if (frame == NULL) { + return NGX_ERROR; + } + + buf = frame->first->buf; + + buf->last = ngx_http_v2_write_uint32(buf->last, status); + + ngx_http_v2_queue_blocked_frame(h2c, frame); + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_v2_send_goaway(ngx_http_v2_connection_t *h2c, ngx_uint_t status) +{ + ngx_buf_t *buf; + ngx_http_v2_out_frame_t *frame; + + frame = ngx_http_v2_get_frame(h2c, NGX_HTTP_V2_GOAWAY_SIZE, + NGX_HTTP_V2_GOAWAY_FRAME, + NGX_HTTP_V2_NO_FLAG, 0); + if (frame == NULL) { + return NGX_ERROR; + } + + buf = frame->first->buf; + + buf->last = ngx_http_v2_write_sid(buf->last, h2c->last_sid); + buf->last = ngx_http_v2_write_uint32(buf->last, status); + + ngx_http_v2_queue_blocked_frame(h2c, frame); + + return NGX_OK; +} + + +static ngx_http_v2_out_frame_t * +ngx_http_v2_get_frame(ngx_http_v2_connection_t *h2c, size_t length, + ngx_uint_t type, u_char flags, ngx_uint_t sid) +{ + ngx_buf_t *buf; + ngx_pool_t *pool; + ngx_http_v2_out_frame_t *frame; + + frame = h2c->free_frames; + + if (frame) { + h2c->free_frames = frame->next; + + buf = frame->first->buf; + buf->pos = buf->start; + + frame->blocked = 0; + + } else { + pool = h2c->pool ? h2c->pool : h2c->connection->pool; + + frame = ngx_pcalloc(pool, sizeof(ngx_http_v2_out_frame_t)); + if (frame == NULL) { + return NULL; + } + + frame->first = ngx_alloc_chain_link(pool); + if (frame->first == NULL) { + return NULL; + } + + buf = ngx_create_temp_buf(pool, NGX_HTTP_V2_FRAME_BUFFER_SIZE); + if (buf == NULL) { + return NULL; + } + + buf->last_buf = 1; + + frame->first->buf = buf; + frame->last = frame->first; + + frame->handler = ngx_http_v2_frame_handler; + } + +#if (NGX_DEBUG) + if (length > NGX_HTTP_V2_FRAME_BUFFER_SIZE - NGX_HTTP_V2_FRAME_HEADER_SIZE) + { + ngx_log_error(NGX_LOG_ALERT, h2c->connection->log, 0, + "requested control frame is too large: %uz", length); + return NULL; + } + + frame->length = length; +#endif + + buf->last = ngx_http_v2_write_len_and_type(buf->pos, length, type); + + *buf->last++ = flags; + + buf->last = ngx_http_v2_write_sid(buf->last, sid); + + return frame; +} + + +static ngx_int_t +ngx_http_v2_frame_handler(ngx_http_v2_connection_t *h2c, + ngx_http_v2_out_frame_t *frame) +{ + ngx_buf_t *buf; + + buf = frame->first->buf; + + if (buf->pos != buf->last) { + return NGX_AGAIN; + } + + frame->next = h2c->free_frames; + h2c->free_frames = frame; + + return NGX_OK; +} + + +static ngx_http_v2_stream_t * +ngx_http_v2_create_stream(ngx_http_v2_connection_t *h2c) +{ + ngx_log_t *log; + ngx_event_t *rev, *wev; + ngx_connection_t *fc; + ngx_http_log_ctx_t *ctx; + ngx_http_request_t *r; + ngx_http_v2_stream_t *stream; + ngx_http_core_srv_conf_t *cscf; + + fc = h2c->free_fake_connections; + + if (fc) { + h2c->free_fake_connections = fc->data; + + rev = fc->read; + wev = fc->write; + log = fc->log; + ctx = log->data; + + } else { + fc = ngx_palloc(h2c->pool, sizeof(ngx_connection_t)); + if (fc == NULL) { + return NULL; + } + + rev = ngx_palloc(h2c->pool, sizeof(ngx_event_t)); + if (rev == NULL) { + return NULL; + } + + wev = ngx_palloc(h2c->pool, sizeof(ngx_event_t)); + if (wev == NULL) { + return NULL; + } + + log = ngx_palloc(h2c->pool, sizeof(ngx_log_t)); + if (log == NULL) { + return NULL; + } + + ctx = ngx_palloc(h2c->pool, sizeof(ngx_http_log_ctx_t)); + if (ctx == NULL) { + return NULL; + } + + ctx->connection = fc; + ctx->request = NULL; + ctx->current_request = NULL; + } + + ngx_memcpy(log, h2c->connection->log, sizeof(ngx_log_t)); + + log->data = ctx; + + ngx_memzero(rev, sizeof(ngx_event_t)); + + rev->data = fc; + rev->ready = 1; + rev->handler = ngx_http_v2_close_stream_handler; + rev->log = log; + + ngx_memcpy(wev, rev, sizeof(ngx_event_t)); + + wev->write = 1; + + ngx_memcpy(fc, h2c->connection, sizeof(ngx_connection_t)); + + fc->data = h2c->http_connection; + fc->read = rev; + fc->write = wev; + fc->sent = 0; + fc->log = log; + fc->buffered = 0; + fc->sndlowat = 1; + fc->tcp_nodelay = NGX_TCP_NODELAY_DISABLED; + + r = ngx_http_create_request(fc); + if (r == NULL) { + return NULL; + } + + r->http_version = NGX_HTTP_VERSION_20; + r->valid_location = 1; + + fc->data = r; + h2c->connection->requests++; + + cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); + + r->header_in = ngx_create_temp_buf(r->pool, + cscf->client_header_buffer_size); + if (r->header_in == NULL) { + ngx_http_free_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return NULL; + } + + if (ngx_list_init(&r->headers_in.headers, r->pool, 20, + sizeof(ngx_table_elt_t)) + != NGX_OK) + { + ngx_http_free_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return NULL; + } + + r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE; + + stream = ngx_pcalloc(r->pool, sizeof(ngx_http_v2_stream_t)); + if (stream == NULL) { + ngx_http_free_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return NULL; + } + + r->stream = stream; + + stream->request = r; + stream->connection = h2c; + + stream->send_window = h2c->init_window; + stream->recv_window = NGX_HTTP_V2_MAX_WINDOW; + + h2c->processing++; + + return stream; +} + + +static ngx_http_v2_node_t * +ngx_http_v2_get_node_by_id(ngx_http_v2_connection_t *h2c, ngx_uint_t sid, + ngx_uint_t alloc) +{ + ngx_uint_t index; + ngx_http_v2_node_t *node; + ngx_http_v2_srv_conf_t *h2scf; + + h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, + ngx_http_v2_module); + + index = ngx_http_v2_index(h2scf, sid); + + for (node = h2c->streams_index[index]; node; node = node->index) { + + if (node->id == sid) { + return node; + } + } + + if (!alloc) { + return NULL; + } + + if (h2c->closed_nodes < 32) { + node = ngx_pcalloc(h2c->connection->pool, sizeof(ngx_http_v2_node_t)); + if (node == NULL) { + return NULL; + } + + } else { + node = ngx_http_v2_get_closed_node(h2c); + } + + node->id = sid; + + ngx_queue_init(&node->children); + + node->index = h2c->streams_index[index]; + h2c->streams_index[index] = node; + + return node; +} + + +static ngx_http_v2_node_t * +ngx_http_v2_get_closed_node(ngx_http_v2_connection_t *h2c) +{ + ngx_uint_t weight; + ngx_queue_t *q, *children; + ngx_http_v2_node_t *node, **next, *n, *parent, *child; + ngx_http_v2_srv_conf_t *h2scf; + + h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, + ngx_http_v2_module); + + h2c->closed_nodes--; + + q = ngx_queue_head(&h2c->closed); + + ngx_queue_remove(q); + + node = ngx_queue_data(q, ngx_http_v2_node_t, reuse); + + next = &h2c->streams_index[ngx_http_v2_index(h2scf, node->id)]; + + for ( ;; ) { + n = *next; + + if (n == node) { + *next = n->index; + break; + } + + next = &n->index; + } + + ngx_queue_remove(&node->queue); + + weight = 0; + + for (q = ngx_queue_head(&node->children); + q != ngx_queue_sentinel(&node->children); + q = ngx_queue_next(q)) + { + child = ngx_queue_data(q, ngx_http_v2_node_t, queue); + weight += child->weight; + } + + for (q = ngx_queue_head(&node->children); + q != ngx_queue_sentinel(&node->children); + q = ngx_queue_next(q)) + { + child = ngx_queue_data(q, ngx_http_v2_node_t, queue); + child->weight = node->weight * child->weight / weight; + + if (child->weight == 0) { + child->weight = 1; + } + } + + parent = node->parent; + + if (parent == NGX_HTTP_V2_ROOT) { + node->rank = 0; + node->rel_weight = 1.0; + + children = &h2c->dependencies; + + } else { + node->rank = parent->rank; + node->rel_weight = parent->rel_weight; + + children = &parent->children; + } + + ngx_http_v2_node_children_update(node); + ngx_queue_add(children, &node->children); + + ngx_memzero(node, sizeof(ngx_http_v2_node_t)); + + return node; +} + + +static ngx_int_t +ngx_http_v2_validate_header(ngx_http_request_t *r, ngx_http_v2_header_t *header) +{ + u_char ch; + ngx_uint_t i; + ngx_http_core_srv_conf_t *cscf; + + if (header->name.len == 0) { + return NGX_ERROR; + } + + cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); + + for (i = (header->name.data[0] == ':'); i != header->name.len; i++) { + ch = header->name.data[i]; + + if ((ch >= 'a' && ch <= 'z') + || (ch == '-') + || (ch >= '0' && ch <= '9') + || (ch == '_' && cscf->underscores_in_headers)) + { + continue; + } + + switch (ch) { + case '\0': + case LF: + case CR: + case ':': + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent invalid header name: \"%V\"", + &header->name); + + return NGX_ERROR; + } + + if (ch >= 'A' && ch <= 'Z') { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent invalid header name: \"%V\"", + &header->name); + + return NGX_ERROR; + } + + r->invalid_header = 1; + } + + for (i = 0; i != header->value.len; i++) { + ch = header->value.data[i]; + + switch (ch) { + case '\0': + case LF: + case CR: + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent header \"%V\" with " + "invalid value: \"%V\"", + &header->name, &header->value); + + return NGX_ERROR; + } + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_v2_pseudo_header(ngx_http_request_t *r, ngx_http_v2_header_t *header) +{ + header->name.len--; + header->name.data++; + + switch (header->name.len) { + case 4: + if (ngx_memcmp(header->name.data, "path", sizeof("path") - 1) + == 0) + { + return ngx_http_v2_parse_path(r, header); + } + + break; + + case 6: + if (ngx_memcmp(header->name.data, "method", sizeof("method") - 1) + == 0) + { + return ngx_http_v2_parse_method(r, header); + } + + if (ngx_memcmp(header->name.data, "scheme", sizeof("scheme") - 1) + == 0) + { + return ngx_http_v2_parse_scheme(r, header); + } + + break; + + case 9: + if (ngx_memcmp(header->name.data, "authority", sizeof("authority") - 1) + == 0) + { + return ngx_http_v2_parse_authority(r, header); + } + + break; + } + + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent unknown pseudo header \"%V\"", + &header->name); + + return NGX_DECLINED; +} + + +static ngx_int_t +ngx_http_v2_parse_path(ngx_http_request_t *r, ngx_http_v2_header_t *header) +{ + if (r->unparsed_uri.len) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent duplicate :path header"); + + return NGX_DECLINED; + } + + if (header->value.len == 0) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent empty :path header"); + + return NGX_DECLINED; + } + + r->uri_start = header->value.data; + r->uri_end = header->value.data + header->value.len; + + if (ngx_http_parse_uri(r) != NGX_OK) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent invalid :path header: \"%V\"", + &header->value); + + return NGX_DECLINED; + } + + if (ngx_http_process_request_uri(r) != NGX_OK) { + /* + * request has been finalized already + * in ngx_http_process_request_uri() + */ + return NGX_ABORT; + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_v2_parse_method(ngx_http_request_t *r, ngx_http_v2_header_t *header) +{ + size_t k, len; + ngx_uint_t n; + const u_char *p, *m; + + /* + * This array takes less than 256 sequential bytes, + * and if typical CPU cache line size is 64 bytes, + * it is prefetched for 4 load operations. + */ + static const struct { + u_char len; + const u_char method[11]; + uint32_t value; + } tests[] = { + { 3, "GET", NGX_HTTP_GET }, + { 4, "POST", NGX_HTTP_POST }, + { 4, "HEAD", NGX_HTTP_HEAD }, + { 7, "OPTIONS", NGX_HTTP_OPTIONS }, + { 8, "PROPFIND", NGX_HTTP_PROPFIND }, + { 3, "PUT", NGX_HTTP_PUT }, + { 5, "MKCOL", NGX_HTTP_MKCOL }, + { 6, "DELETE", NGX_HTTP_DELETE }, + { 4, "COPY", NGX_HTTP_COPY }, + { 4, "MOVE", NGX_HTTP_MOVE }, + { 9, "PROPPATCH", NGX_HTTP_PROPPATCH }, + { 4, "LOCK", NGX_HTTP_LOCK }, + { 6, "UNLOCK", NGX_HTTP_UNLOCK }, + { 5, "PATCH", NGX_HTTP_PATCH }, + { 5, "TRACE", NGX_HTTP_TRACE } + }, *test; + + if (r->method_name.len) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent duplicate :method header"); + + return NGX_DECLINED; + } + + if (header->value.len == 0) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent empty :method header"); + + return NGX_DECLINED; + } + + r->method_name.len = header->value.len; + r->method_name.data = header->value.data; + + len = r->method_name.len; + n = sizeof(tests) / sizeof(tests[0]); + test = tests; + + do { + if (len == test->len) { + p = r->method_name.data; + m = test->method; + k = len; + + do { + if (*p++ != *m++) { + goto next; + } + } while (--k); + + r->method = test->value; + return NGX_OK; + } + + next: + test++; + + } while (--n); + + p = r->method_name.data; + + do { + if ((*p < 'A' || *p > 'Z') && *p != '_') { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent invalid method: \"%V\"", + &r->method_name); + + return NGX_DECLINED; + } + + p++; + + } while (--len); + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_v2_parse_scheme(ngx_http_request_t *r, ngx_http_v2_header_t *header) +{ + if (r->schema_start) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent duplicate :schema header"); + + return NGX_DECLINED; + } + + if (header->value.len == 0) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent empty :schema header"); + + return NGX_DECLINED; + } + + r->schema_start = header->value.data; + r->schema_end = header->value.data + header->value.len; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_v2_parse_authority(ngx_http_request_t *r, ngx_http_v2_header_t *header) +{ + ngx_table_elt_t *h; + ngx_http_header_t *hh; + ngx_http_core_main_conf_t *cmcf; + + static ngx_str_t host = ngx_string("host"); + + h = ngx_list_push(&r->headers_in.headers); + if (h == NULL) { + return NGX_ERROR; + } + + h->hash = ngx_hash_key(host.data, host.len); + + h->key.len = host.len; + h->key.data = host.data; + + h->value.len = header->value.len; + h->value.data = header->value.data; + + h->lowcase_key = host.data; + + cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); + + hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash, + h->lowcase_key, h->key.len); + + if (hh == NULL) { + return NGX_ERROR; + } + + if (hh->handler(r, h, hh->offset) != NGX_OK) { + /* + * request has been finalized already + * in ngx_http_process_host() + */ + return NGX_ABORT; + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_v2_construct_request_line(ngx_http_request_t *r) +{ + u_char *p; + + static const u_char ending[] = " HTTP/2.0"; + + if (r->method_name.len == 0 + || r->unparsed_uri.len == 0) + { + ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); + return NGX_ERROR; + } + + r->request_line.len = r->method_name.len + 1 + + r->unparsed_uri.len + + sizeof(ending) - 1; + + p = ngx_pnalloc(r->pool, r->request_line.len + 1); + if (p == NULL) { + ngx_http_v2_close_stream(r->stream, NGX_HTTP_INTERNAL_SERVER_ERROR); + return NGX_ERROR; + } + + r->request_line.data = p; + + p = ngx_cpymem(p, r->method_name.data, r->method_name.len); + + *p++ = ' '; + + p = ngx_cpymem(p, r->unparsed_uri.data, r->unparsed_uri.len); + + ngx_memcpy(p, ending, sizeof(ending)); + + /* some modules expect the space character after method name */ + r->method_name.data = r->request_line.data; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http2 http request line: \"%V\"", &r->request_line); + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_v2_cookie(ngx_http_request_t *r, ngx_http_v2_header_t *header) +{ + ngx_str_t *val; + ngx_array_t *cookies; + + cookies = r->stream->cookies; + + if (cookies == NULL) { + cookies = ngx_array_create(r->pool, 2, sizeof(ngx_str_t)); + if (cookies == NULL) { + return NGX_ERROR; + } + + r->stream->cookies = cookies; + } + + val = ngx_array_push(cookies); + if (val == NULL) { + return NGX_ERROR; + } + + val->len = header->value.len; + val->data = header->value.data; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_v2_construct_cookie_header(ngx_http_request_t *r) +{ + u_char *buf, *p, *end; + size_t len; + ngx_str_t *vals; + ngx_uint_t i; + ngx_array_t *cookies; + ngx_table_elt_t *h; + ngx_http_header_t *hh; + ngx_http_core_main_conf_t *cmcf; + + static ngx_str_t cookie = ngx_string("cookie"); + + cookies = r->stream->cookies; + + if (cookies == NULL) { + return NGX_OK; + } + + vals = cookies->elts; + + i = 0; + len = 0; + + do { + len += vals[i].len + 2; + } while (++i != cookies->nelts); + + len -= 2; + + buf = ngx_pnalloc(r->pool, len + 1); + if (buf == NULL) { + ngx_http_v2_close_stream(r->stream, NGX_HTTP_INTERNAL_SERVER_ERROR); + return NGX_ERROR; + } + + p = buf; + end = buf + len; + + for (i = 0; /* void */ ; i++) { + + p = ngx_cpymem(p, vals[i].data, vals[i].len); + + if (p == end) { + *p = '\0'; + break; + } + + *p++ = ';'; *p++ = ' '; + } + + h = ngx_list_push(&r->headers_in.headers); + if (h == NULL) { + ngx_http_v2_close_stream(r->stream, NGX_HTTP_INTERNAL_SERVER_ERROR); + return NGX_ERROR; + } + + h->hash = ngx_hash_key(cookie.data, cookie.len); + + h->key.len = cookie.len; + h->key.data = cookie.data; + + h->value.len = len; + h->value.data = buf; + + h->lowcase_key = cookie.data; + + cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); + + hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash, + h->lowcase_key, h->key.len); + + if (hh == NULL) { + ngx_http_v2_close_stream(r->stream, NGX_HTTP_INTERNAL_SERVER_ERROR); + return NGX_ERROR; + } + + if (hh->handler(r, h, hh->offset) != NGX_OK) { + /* + * request has been finalized already + * in ngx_http_process_multi_header_lines() + */ + return NGX_ERROR; + } + + return NGX_OK; +} + + +static void +ngx_http_v2_run_request(ngx_http_request_t *r) +{ + if (ngx_http_v2_construct_request_line(r) != NGX_OK) { + return; + } + + if (ngx_http_v2_construct_cookie_header(r) != NGX_OK) { + return; + } + + r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE; + + if (ngx_http_process_request_header(r) != NGX_OK) { + return; + } + + if (r->headers_in.content_length_n > 0 && r->stream->in_closed) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client prematurely closed stream"); + + r->stream->skip_data = NGX_HTTP_V2_DATA_ERROR; + + ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); + return; + } + + ngx_http_process_request(r); +} + + +static ngx_int_t +ngx_http_v2_init_request_body(ngx_http_request_t *r) +{ + ngx_buf_t *buf; + ngx_temp_file_t *tf; + ngx_http_request_body_t *rb; + ngx_http_core_loc_conf_t *clcf; + + rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t)); + if (rb == NULL) { + return NGX_ERROR; + } + + r->request_body = rb; + + if (r->stream->in_closed) { + return NGX_OK; + } + + rb->rest = r->headers_in.content_length_n; + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + if (r->request_body_in_file_only + || rb->rest > (off_t) clcf->client_body_buffer_size + || rb->rest < 0) + { + tf = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t)); + if (tf == NULL) { + return NGX_ERROR; + } + + tf->file.fd = NGX_INVALID_FILE; + tf->file.log = r->connection->log; + tf->path = clcf->client_body_temp_path; + tf->pool = r->pool; + tf->warn = "a client request body is buffered to a temporary file"; + tf->log_level = r->request_body_file_log_level; + tf->persistent = r->request_body_in_persistent_file; + tf->clean = r->request_body_in_clean_file; + + if (r->request_body_file_group_access) { + tf->access = 0660; + } + + rb->temp_file = tf; + + if (r->stream->in_closed + && ngx_create_temp_file(&tf->file, tf->path, tf->pool, + tf->persistent, tf->clean, tf->access) + != NGX_OK) + { + return NGX_ERROR; + } + + buf = ngx_calloc_buf(r->pool); + if (buf == NULL) { + return NGX_ERROR; + } + + } else { + + if (rb->rest == 0) { + return NGX_OK; + } + + buf = ngx_create_temp_buf(r->pool, (size_t) rb->rest); + if (buf == NULL) { + return NGX_ERROR; + } + } + + rb->buf = buf; + + rb->bufs = ngx_alloc_chain_link(r->pool); + if (rb->bufs == NULL) { + return NGX_ERROR; + } + + rb->bufs->buf = buf; + rb->bufs->next = NULL; + + rb->rest = 0; + + return NGX_OK; +} + + +ngx_int_t +ngx_http_v2_read_request_body(ngx_http_request_t *r, + ngx_http_client_body_handler_pt post_handler) +{ + ngx_http_v2_stream_t *stream; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http2 read request body"); + + stream = r->stream; + + switch (stream->skip_data) { + + case NGX_HTTP_V2_DATA_DISCARD: + post_handler(r); + return NGX_OK; + + case NGX_HTTP_V2_DATA_ERROR: + if (r->headers_in.content_length_n == -1) { + return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE; + } else { + return NGX_HTTP_BAD_REQUEST; + } + + case NGX_HTTP_V2_DATA_INTERNAL_ERROR: + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + if (!r->request_body && ngx_http_v2_init_request_body(r) != NGX_OK) { + stream->skip_data = NGX_HTTP_V2_DATA_INTERNAL_ERROR; + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + if (stream->in_closed) { + post_handler(r); + return NGX_OK; + } + + r->request_body->post_handler = post_handler; + + r->read_event_handler = ngx_http_test_reading; + r->write_event_handler = ngx_http_request_empty_handler; + + return NGX_AGAIN; +} + + +static ngx_int_t +ngx_http_v2_terminate_stream(ngx_http_v2_connection_t *h2c, + ngx_http_v2_stream_t *stream, ngx_uint_t status) +{ + ngx_event_t *rev; + ngx_connection_t *fc; + + if (ngx_http_v2_send_rst_stream(h2c, stream->node->id, status) + == NGX_ERROR) + { + return NGX_ERROR; + } + + stream->out_closed = 1; + + fc = stream->request->connection; + fc->error = 1; + + rev = fc->read; + rev->handler(rev); + + return NGX_OK; +} + + +void +ngx_http_v2_close_stream(ngx_http_v2_stream_t *stream, ngx_int_t rc) +{ + ngx_event_t *ev; + ngx_connection_t *fc; + ngx_http_v2_node_t *node; + ngx_http_v2_connection_t *h2c; + + h2c = stream->connection; + node = stream->node; + + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "http2 close stream %ui, queued %ui, processing %ui", + node->id, stream->queued, h2c->processing); + + fc = stream->request->connection; + + if (stream->queued) { + fc->write->handler = ngx_http_v2_close_stream_handler; + return; + } + + if (!stream->out_closed) { + if (ngx_http_v2_send_rst_stream(h2c, node->id, + NGX_HTTP_V2_INTERNAL_ERROR) + != NGX_OK) + { + h2c->connection->error = 1; + } + } + + node->stream = NULL; + + ngx_queue_insert_tail(&h2c->closed, &node->reuse); + h2c->closed_nodes++; + + ngx_http_free_request(stream->request, rc); + + ev = fc->read; + + if (ev->active || ev->disabled) { + ngx_log_error(NGX_LOG_ALERT, h2c->connection->log, 0, + "fake read event was activated"); + } + + if (ev->timer_set) { + ngx_del_timer(ev); + } + + if (ev->posted) { + ngx_delete_posted_event(ev); + } + + ev = fc->write; + + if (ev->active || ev->disabled) { + ngx_log_error(NGX_LOG_ALERT, h2c->connection->log, 0, + "fake write event was activated"); + } + + if (ev->timer_set) { + ngx_del_timer(ev); + } + + if (ev->posted) { + ngx_delete_posted_event(ev); + } + + fc->data = h2c->free_fake_connections; + h2c->free_fake_connections = fc; + + h2c->processing--; + + if (h2c->processing || h2c->blocked) { + return; + } + + ev = h2c->connection->read; + + ev->handler = ngx_http_v2_handle_connection_handler; + ngx_post_event(ev, &ngx_posted_events); +} + + +static void +ngx_http_v2_close_stream_handler(ngx_event_t *ev) +{ + ngx_connection_t *fc; + ngx_http_request_t *r; + + fc = ev->data; + r = fc->data; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http2 close stream handler"); + + ngx_http_v2_close_stream(r->stream, 0); +} + + +static void +ngx_http_v2_handle_connection_handler(ngx_event_t *rev) +{ + ngx_connection_t *c; + + rev->handler = ngx_http_v2_read_handler; + + if (rev->ready) { + ngx_http_v2_read_handler(rev); + return; + } + + c = rev->data; + + ngx_http_v2_handle_connection(c->data); +} + + +static void +ngx_http_v2_idle_handler(ngx_event_t *rev) +{ + ngx_connection_t *c; + ngx_http_v2_srv_conf_t *h2scf; + ngx_http_v2_connection_t *h2c; + + c = rev->data; + h2c = c->data; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http2 idle handler"); + + if (rev->timedout || c->close) { + ngx_http_v2_finalize_connection(h2c, NGX_HTTP_V2_NO_ERROR); + return; + } + +#if (NGX_HAVE_KQUEUE) + + if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { + if (rev->pending_eof) { + c->log->handler = NULL; + ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno, + "kevent() reported that client %V closed " + "idle connection", &c->addr_text); +#if (NGX_HTTP_SSL) + if (c->ssl) { + c->ssl->no_send_shutdown = 1; + } +#endif + ngx_http_close_connection(c); + return; + } + } + +#endif + + c->destroyed = 0; + c->idle = 0; + ngx_reusable_connection(c, 0); + + h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, + ngx_http_v2_module); + + h2c->pool = ngx_create_pool(h2scf->pool_size, h2c->connection->log); + if (h2c->pool == NULL) { + ngx_http_v2_finalize_connection(h2c, NGX_HTTP_V2_INTERNAL_ERROR); + return; + } + + c->write->handler = ngx_http_v2_write_handler; + + rev->handler = ngx_http_v2_read_handler; + ngx_http_v2_read_handler(rev); +} + + +static void +ngx_http_v2_finalize_connection(ngx_http_v2_connection_t *h2c, + ngx_uint_t status) +{ + ngx_uint_t i, size; + ngx_event_t *ev; + ngx_connection_t *c, *fc; + ngx_http_request_t *r; + ngx_http_v2_node_t *node; + ngx_http_v2_stream_t *stream; + ngx_http_v2_srv_conf_t *h2scf; + + c = h2c->connection; + + h2c->blocked = 1; + + if (!c->error && ngx_http_v2_send_goaway(h2c, status) != NGX_ERROR) { + (void) ngx_http_v2_send_output_queue(h2c); + } + + if (!h2c->processing) { + ngx_http_close_connection(c); + return; + } + + c->error = 1; + c->read->handler = ngx_http_empty_handler; + c->write->handler = ngx_http_empty_handler; + + h2c->last_out = NULL; + + h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, + ngx_http_v2_module); + + size = ngx_http_v2_index_size(h2scf); + + for (i = 0; i < size; i++) { + + for (node = h2c->streams_index[i]; node; node = node->index) { + stream = node->stream; + + if (stream == NULL) { + continue; + } + + stream->handled = 0; + + r = stream->request; + fc = r->connection; + + fc->error = 1; + + if (stream->queued) { + stream->queued = 0; + + ev = fc->write; + ev->delayed = 0; + + } else { + ev = fc->read; + } + + ev->eof = 1; + ev->handler(ev); + } + } + + h2c->blocked = 0; + + if (h2c->processing) { + return; + } + + ngx_http_close_connection(c); +} + + +static ngx_int_t +ngx_http_v2_adjust_windows(ngx_http_v2_connection_t *h2c, ssize_t delta) +{ + ngx_uint_t i, size; + ngx_event_t *wev; + ngx_http_v2_node_t *node; + ngx_http_v2_stream_t *stream; + ngx_http_v2_srv_conf_t *h2scf; + + h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, + ngx_http_v2_module); + + size = ngx_http_v2_index_size(h2scf); + + for (i = 0; i < size; i++) { + + for (node = h2c->streams_index[i]; node; node = node->index) { + stream = node->stream; + + if (stream == NULL) { + continue; + } + + if (delta > 0 + && stream->send_window + > (ssize_t) (NGX_HTTP_V2_MAX_WINDOW - delta)) + { + if (ngx_http_v2_terminate_stream(h2c, stream, + NGX_HTTP_V2_FLOW_CTRL_ERROR) + == NGX_ERROR) + { + return NGX_ERROR; + } + + continue; + } + + stream->send_window += delta; + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "http2:%ui adjusted window: %z", + node->id, stream->send_window); + + if (stream->send_window > 0 && stream->exhausted) { + stream->exhausted = 0; + + wev = stream->request->connection->write; + + if (!wev->timer_set) { + wev->delayed = 0; + wev->handler(wev); + } + } + } + } + + return NGX_OK; +} + + +static void +ngx_http_v2_set_dependency(ngx_http_v2_connection_t *h2c, + ngx_http_v2_node_t *node, ngx_uint_t depend, ngx_uint_t exclusive) +{ + ngx_queue_t *children; + ngx_http_v2_node_t *parent, *next; + + parent = depend ? ngx_http_v2_get_node_by_id(h2c, depend, 0) : NULL; + + if (parent == NULL) { + parent = NGX_HTTP_V2_ROOT; + + if (depend != 0) { + exclusive = 0; + } + + node->rank = 1; + node->rel_weight = (1.0 / 256) * node->weight; + + children = &h2c->dependencies; + + } else { + if (node->parent != NULL) { + + for (next = parent->parent; + next != NGX_HTTP_V2_ROOT && next->rank >= node->rank; + next = next->parent) + { + if (next != node) { + continue; + } + + ngx_queue_remove(&parent->queue); + ngx_queue_insert_after(&node->queue, &parent->queue); + + parent->parent = node->parent; + + if (node->parent == NGX_HTTP_V2_ROOT) { + parent->rank = 1; + parent->rel_weight = (1.0 / 256) * parent->weight; + + } else { + parent->rank = node->parent->rank + 1; + parent->rel_weight = (node->parent->rel_weight / 256) + * parent->weight; + } + + if (!exclusive) { + ngx_http_v2_node_children_update(parent); + } + + break; + } + } + + node->rank = parent->rank + 1; + node->rel_weight = (parent->rel_weight / 256) * node->weight; + + if (parent->stream == NULL) { + ngx_queue_remove(&parent->reuse); + ngx_queue_insert_tail(&h2c->closed, &parent->reuse); + } + + children = &parent->children; + } + + if (exclusive) { + ngx_queue_add(&node->children, children); + ngx_queue_init(children); + } + + if (node->parent != NULL) { + ngx_queue_remove(&node->queue); + } + + ngx_queue_insert_tail(children, &node->queue); + + node->parent = parent; + + ngx_http_v2_node_children_update(node); +} + + +static void +ngx_http_v2_node_children_update(ngx_http_v2_node_t *node) +{ + ngx_queue_t *q; + ngx_http_v2_node_t *child; + + for (q = ngx_queue_head(&node->children); + q != ngx_queue_sentinel(&node->children); + q = ngx_queue_next(q)) + { + child = ngx_queue_data(q, ngx_http_v2_node_t, queue); + + child->rank = node->rank + 1; + child->rel_weight = (node->rel_weight / 256) * child->weight; + + ngx_http_v2_node_children_update(child); + } +} + + +static void +ngx_http_v2_pool_cleanup(void *data) +{ + ngx_http_v2_connection_t *h2c = data; + + if (h2c->state.pool) { + ngx_destroy_pool(h2c->state.pool); + } + + if (h2c->pool) { + ngx_destroy_pool(h2c->pool); + } +} diff --git a/src/http/v2/ngx_http_v2.h b/src/http/v2/ngx_http_v2.h new file mode 100644 index 0000000..b7e73c9 --- /dev/null +++ b/src/http/v2/ngx_http_v2.h @@ -0,0 +1,333 @@ +/* + * Copyright (C) Nginx, Inc. + * Copyright (C) Valentin V. Bartenev + */ + + +#ifndef _NGX_HTTP_V2_H_INCLUDED_ +#define _NGX_HTTP_V2_H_INCLUDED_ + + +#include +#include +#include + + +#define NGX_HTTP_V2_ALPN_ADVERTISE "\x02h2" +#define NGX_HTTP_V2_NPN_ADVERTISE NGX_HTTP_V2_ALPN_ADVERTISE + +#define NGX_HTTP_V2_STATE_BUFFER_SIZE 16 + +#define NGX_HTTP_V2_MAX_FRAME_SIZE ((1 << 24) - 1) + +#define NGX_HTTP_V2_INT_OCTETS 4 +#define NGX_HTTP_V2_MAX_FIELD ((1 << NGX_HTTP_V2_INT_OCTETS * 7) - 1) + +#define NGX_HTTP_V2_DATA_DISCARD 1 +#define NGX_HTTP_V2_DATA_ERROR 2 +#define NGX_HTTP_V2_DATA_INTERNAL_ERROR 3 + +#define NGX_HTTP_V2_FRAME_HEADER_SIZE 9 + +/* frame types */ +#define NGX_HTTP_V2_DATA_FRAME 0x0 +#define NGX_HTTP_V2_HEADERS_FRAME 0x1 +#define NGX_HTTP_V2_PRIORITY_FRAME 0x2 +#define NGX_HTTP_V2_RST_STREAM_FRAME 0x3 +#define NGX_HTTP_V2_SETTINGS_FRAME 0x4 +#define NGX_HTTP_V2_PUSH_PROMISE_FRAME 0x5 +#define NGX_HTTP_V2_PING_FRAME 0x6 +#define NGX_HTTP_V2_GOAWAY_FRAME 0x7 +#define NGX_HTTP_V2_WINDOW_UPDATE_FRAME 0x8 +#define NGX_HTTP_V2_CONTINUATION_FRAME 0x9 + +/* frame flags */ +#define NGX_HTTP_V2_NO_FLAG 0x00 +#define NGX_HTTP_V2_ACK_FLAG 0x01 +#define NGX_HTTP_V2_END_STREAM_FLAG 0x01 +#define NGX_HTTP_V2_END_HEADERS_FLAG 0x04 +#define NGX_HTTP_V2_PADDED_FLAG 0x08 +#define NGX_HTTP_V2_PRIORITY_FLAG 0x20 + + +typedef struct ngx_http_v2_connection_s ngx_http_v2_connection_t; +typedef struct ngx_http_v2_node_s ngx_http_v2_node_t; +typedef struct ngx_http_v2_out_frame_s ngx_http_v2_out_frame_t; + + +typedef u_char *(*ngx_http_v2_handler_pt) (ngx_http_v2_connection_t *h2c, + u_char *pos, u_char *end); + + +typedef struct { + ngx_str_t name; + ngx_str_t value; +} ngx_http_v2_header_t; + + +typedef struct { + ngx_uint_t sid; + size_t length; + size_t padding; + unsigned flags:8; + + unsigned incomplete:1; + + /* HPACK */ + unsigned parse_name:1; + unsigned parse_value:1; + unsigned index:1; + ngx_http_v2_header_t header; + size_t header_limit; + size_t field_limit; + u_char field_state; + u_char *field_start; + u_char *field_end; + size_t field_rest; + ngx_pool_t *pool; + + ngx_http_v2_stream_t *stream; + + u_char buffer[NGX_HTTP_V2_STATE_BUFFER_SIZE]; + size_t buffer_used; + ngx_http_v2_handler_pt handler; +} ngx_http_v2_state_t; + + + +typedef struct { + ngx_http_v2_header_t **entries; + + ngx_uint_t added; + ngx_uint_t deleted; + ngx_uint_t reused; + ngx_uint_t allocated; + + size_t size; + size_t free; + u_char *storage; + u_char *pos; +} ngx_http_v2_hpack_t; + + +struct ngx_http_v2_connection_s { + ngx_connection_t *connection; + ngx_http_connection_t *http_connection; + + ngx_uint_t processing; + + size_t send_window; + size_t recv_window; + size_t init_window; + + size_t frame_size; + + ngx_queue_t waiting; + + ngx_http_v2_state_t state; + + ngx_http_v2_hpack_t hpack; + + ngx_pool_t *pool; + + ngx_http_v2_out_frame_t *free_frames; + ngx_connection_t *free_fake_connections; + + ngx_http_v2_node_t **streams_index; + + ngx_http_v2_out_frame_t *last_out; + + ngx_queue_t posted; + ngx_queue_t dependencies; + ngx_queue_t closed; + + ngx_uint_t last_sid; + + unsigned closed_nodes:8; + unsigned blocked:1; +}; + + +struct ngx_http_v2_node_s { + ngx_uint_t id; + ngx_http_v2_node_t *index; + ngx_http_v2_node_t *parent; + ngx_queue_t queue; + ngx_queue_t children; + ngx_queue_t reuse; + ngx_uint_t rank; + ngx_uint_t weight; + double rel_weight; + ngx_http_v2_stream_t *stream; +}; + + +struct ngx_http_v2_stream_s { + ngx_http_request_t *request; + ngx_http_v2_connection_t *connection; + ngx_http_v2_node_t *node; + + ngx_uint_t header_buffers; + ngx_uint_t queued; + + /* + * A change to SETTINGS_INITIAL_WINDOW_SIZE could cause the + * send_window to become negative, hence it's signed. + */ + ssize_t send_window; + size_t recv_window; + + ngx_http_v2_out_frame_t *free_frames; + ngx_chain_t *free_data_headers; + ngx_chain_t *free_bufs; + + ngx_queue_t queue; + + ngx_array_t *cookies; + + size_t header_limit; + + unsigned handled:1; + unsigned blocked:1; + unsigned exhausted:1; + unsigned in_closed:1; + unsigned out_closed:1; + unsigned skip_data:2; +}; + + +struct ngx_http_v2_out_frame_s { + ngx_http_v2_out_frame_t *next; + ngx_chain_t *first; + ngx_chain_t *last; + ngx_int_t (*handler)(ngx_http_v2_connection_t *h2c, + ngx_http_v2_out_frame_t *frame); + + ngx_http_v2_stream_t *stream; + size_t length; + + unsigned blocked:1; + unsigned fin:1; +}; + + +static ngx_inline void +ngx_http_v2_queue_frame(ngx_http_v2_connection_t *h2c, + ngx_http_v2_out_frame_t *frame) +{ + ngx_http_v2_out_frame_t **out; + + for (out = &h2c->last_out; *out; out = &(*out)->next) { + + if ((*out)->blocked || (*out)->stream == NULL) { + break; + } + + if ((*out)->stream->node->rank < frame->stream->node->rank + || ((*out)->stream->node->rank == frame->stream->node->rank + && (*out)->stream->node->rel_weight + >= frame->stream->node->rel_weight)) + { + break; + } + } + + frame->next = *out; + *out = frame; +} + + +static ngx_inline void +ngx_http_v2_queue_blocked_frame(ngx_http_v2_connection_t *h2c, + ngx_http_v2_out_frame_t *frame) +{ + ngx_http_v2_out_frame_t **out; + + for (out = &h2c->last_out; *out; out = &(*out)->next) + { + if ((*out)->blocked || (*out)->stream == NULL) { + break; + } + } + + frame->next = *out; + *out = frame; +} + + +void ngx_http_v2_init(ngx_event_t *rev); +void ngx_http_v2_request_headers_init(void); + +ngx_int_t ngx_http_v2_read_request_body(ngx_http_request_t *r, + ngx_http_client_body_handler_pt post_handler); + +void ngx_http_v2_close_stream(ngx_http_v2_stream_t *stream, ngx_int_t rc); + +ngx_int_t ngx_http_v2_send_output_queue(ngx_http_v2_connection_t *h2c); + + +ngx_int_t ngx_http_v2_get_indexed_header(ngx_http_v2_connection_t *h2c, + ngx_uint_t index, ngx_uint_t name_only); +ngx_int_t ngx_http_v2_add_header(ngx_http_v2_connection_t *h2c, + ngx_http_v2_header_t *header); +ngx_int_t ngx_http_v2_table_size(ngx_http_v2_connection_t *h2c, size_t size); + + +ngx_int_t ngx_http_v2_huff_decode(u_char *state, u_char *src, size_t len, + u_char **dst, ngx_uint_t last, ngx_log_t *log); + + +#define ngx_http_v2_prefix(bits) ((1 << (bits)) - 1) + + +#if (NGX_HAVE_NONALIGNED) + +#define ngx_http_v2_parse_uint16(p) ntohs(*(uint16_t *) (p)) +#define ngx_http_v2_parse_uint32(p) ntohl(*(uint32_t *) (p)) + +#else + +#define ngx_http_v2_parse_uint16(p) ((p)[0] << 8 | (p)[1]) +#define ngx_http_v2_parse_uint32(p) \ + ((p)[0] << 24 | (p)[1] << 16 | (p)[2] << 8 | (p)[3]) + +#endif + +#define ngx_http_v2_parse_length(p) ((p) >> 8) +#define ngx_http_v2_parse_type(p) ((p) & 0xff) +#define ngx_http_v2_parse_sid(p) (ngx_http_v2_parse_uint32(p) & 0x7fffffff) +#define ngx_http_v2_parse_window(p) (ngx_http_v2_parse_uint32(p) & 0x7fffffff) + + +#define ngx_http_v2_write_uint16_aligned(p, s) \ + (*(uint16_t *) (p) = htons((uint16_t) (s)), (p) + sizeof(uint16_t)) +#define ngx_http_v2_write_uint32_aligned(p, s) \ + (*(uint32_t *) (p) = htonl((uint32_t) (s)), (p) + sizeof(uint32_t)) + +#if (NGX_HAVE_NONALIGNED) + +#define ngx_http_v2_write_uint16 ngx_http_v2_write_uint16_aligned +#define ngx_http_v2_write_uint32 ngx_http_v2_write_uint32_aligned + +#else + +#define ngx_http_v2_write_uint16(p, s) \ + ((p)[0] = (u_char) ((s) >> 8), \ + (p)[1] = (u_char) (s), \ + (p) + sizeof(uint16_t)) + +#define ngx_http_v2_write_uint32(p, s) \ + ((p)[0] = (u_char) ((s) >> 24), \ + (p)[1] = (u_char) ((s) >> 16), \ + (p)[2] = (u_char) ((s) >> 8), \ + (p)[3] = (u_char) (s), \ + (p) + sizeof(uint32_t)) + +#endif + +#define ngx_http_v2_write_len_and_type(p, l, t) \ + ngx_http_v2_write_uint32_aligned(p, (l) << 8 | (t)) + +#define ngx_http_v2_write_sid ngx_http_v2_write_uint32 + +#endif /* _NGX_HTTP_V2_H_INCLUDED_ */ diff --git a/src/http/v2/ngx_http_v2_filter_module.c b/src/http/v2/ngx_http_v2_filter_module.c new file mode 100644 index 0000000..17cfcd8 --- /dev/null +++ b/src/http/v2/ngx_http_v2_filter_module.c @@ -0,0 +1,1291 @@ + +/* + * Copyright (C) Nginx, Inc. + * Copyright (C) Valentin V. Bartenev + */ + + +#include +#include +#include +#include +#include + + +#define ngx_http_v2_integer_octets(v) (((v) + 127) / 128) + +#define ngx_http_v2_literal_size(h) \ + (ngx_http_v2_integer_octets(sizeof(h) - 1) + sizeof(h) - 1) + +#define ngx_http_v2_indexed(i) (128 + (i)) +#define ngx_http_v2_inc_indexed(i) (64 + (i)) + + +#define NGX_HTTP_V2_STATUS_INDEX 8 +#define NGX_HTTP_V2_STATUS_200_INDEX 8 +#define NGX_HTTP_V2_STATUS_204_INDEX 9 +#define NGX_HTTP_V2_STATUS_206_INDEX 10 +#define NGX_HTTP_V2_STATUS_304_INDEX 11 +#define NGX_HTTP_V2_STATUS_400_INDEX 12 +#define NGX_HTTP_V2_STATUS_404_INDEX 13 +#define NGX_HTTP_V2_STATUS_500_INDEX 14 + +#define NGX_HTTP_V2_CONTENT_LENGTH_INDEX 28 +#define NGX_HTTP_V2_CONTENT_TYPE_INDEX 31 +#define NGX_HTTP_V2_DATE_INDEX 33 +#define NGX_HTTP_V2_LAST_MODIFIED_INDEX 44 +#define NGX_HTTP_V2_LOCATION_INDEX 46 +#define NGX_HTTP_V2_SERVER_INDEX 54 +#define NGX_HTTP_V2_VARY_INDEX 59 + + +static u_char *ngx_http_v2_write_int(u_char *pos, ngx_uint_t prefix, + ngx_uint_t value); +static void ngx_http_v2_write_headers_head(u_char *pos, size_t length, + ngx_uint_t sid, ngx_uint_t end_headers, ngx_uint_t end_stream); +static void ngx_http_v2_write_continuation_head(u_char *pos, size_t length, + ngx_uint_t sid, ngx_uint_t end_headers); + +static ngx_chain_t *ngx_http_v2_send_chain(ngx_connection_t *fc, + ngx_chain_t *in, off_t limit); + +static ngx_chain_t *ngx_http_v2_filter_get_shadow( + ngx_http_v2_stream_t *stream, ngx_buf_t *buf, off_t offset, off_t size); +static ngx_http_v2_out_frame_t *ngx_http_v2_filter_get_data_frame( + ngx_http_v2_stream_t *stream, size_t len, ngx_chain_t *first, + ngx_chain_t *last); + +static ngx_inline ngx_int_t ngx_http_v2_flow_control( + ngx_http_v2_connection_t *h2c, ngx_http_v2_stream_t *stream); +static void ngx_http_v2_waiting_queue(ngx_http_v2_connection_t *h2c, + ngx_http_v2_stream_t *stream); + +static ngx_inline ngx_int_t ngx_http_v2_filter_send( + ngx_connection_t *fc, ngx_http_v2_stream_t *stream); + +static ngx_int_t ngx_http_v2_headers_frame_handler( + ngx_http_v2_connection_t *h2c, ngx_http_v2_out_frame_t *frame); +static ngx_int_t ngx_http_v2_data_frame_handler( + ngx_http_v2_connection_t *h2c, ngx_http_v2_out_frame_t *frame); +static ngx_inline void ngx_http_v2_handle_frame( + ngx_http_v2_stream_t *stream, ngx_http_v2_out_frame_t *frame); +static ngx_inline void ngx_http_v2_handle_stream( + ngx_http_v2_connection_t *h2c, ngx_http_v2_stream_t *stream); + +static void ngx_http_v2_filter_cleanup(void *data); + +static ngx_int_t ngx_http_v2_filter_init(ngx_conf_t *cf); + + +static ngx_http_module_t ngx_http_v2_filter_module_ctx = { + NULL, /* preconfiguration */ + ngx_http_v2_filter_init, /* postconfiguration */ + + NULL, /* create main configuration */ + NULL, /* init main configuration */ + + NULL, /* create server configuration */ + NULL, /* merge server configuration */ + + NULL, /* create location configuration */ + NULL /* merge location configuration */ +}; + + +ngx_module_t ngx_http_v2_filter_module = { + NGX_MODULE_V1, + &ngx_http_v2_filter_module_ctx, /* module context */ + NULL, /* 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_http_output_header_filter_pt ngx_http_next_header_filter; + + +static ngx_int_t +ngx_http_v2_header_filter(ngx_http_request_t *r) +{ + u_char status, *p, *head; + size_t len, rest, frame_size; + ngx_buf_t *b; + ngx_str_t host, location; + ngx_uint_t i, port, continuation; + ngx_chain_t *cl; + ngx_list_part_t *part; + ngx_table_elt_t *header; + ngx_connection_t *fc; + ngx_http_cleanup_t *cln; + ngx_http_v2_stream_t *stream; + ngx_http_v2_out_frame_t *frame; + ngx_http_core_loc_conf_t *clcf; + ngx_http_core_srv_conf_t *cscf; + struct sockaddr_in *sin; +#if (NGX_HAVE_INET6) + struct sockaddr_in6 *sin6; +#endif + u_char addr[NGX_SOCKADDR_STRLEN]; + + + if (!r->stream) { + return ngx_http_next_header_filter(r); + } + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http2 header filter"); + + if (r->header_sent) { + return NGX_OK; + } + + r->header_sent = 1; + + if (r != r->main) { + return NGX_OK; + } + + if (r->method == NGX_HTTP_HEAD) { + r->header_only = 1; + } + + switch (r->headers_out.status) { + + case NGX_HTTP_OK: + status = ngx_http_v2_indexed(NGX_HTTP_V2_STATUS_200_INDEX); + break; + + case NGX_HTTP_NO_CONTENT: + r->header_only = 1; + + ngx_str_null(&r->headers_out.content_type); + + r->headers_out.content_length = NULL; + r->headers_out.content_length_n = -1; + + r->headers_out.last_modified_time = -1; + r->headers_out.last_modified = NULL; + + status = ngx_http_v2_indexed(NGX_HTTP_V2_STATUS_204_INDEX); + break; + + case NGX_HTTP_PARTIAL_CONTENT: + status = ngx_http_v2_indexed(NGX_HTTP_V2_STATUS_206_INDEX); + break; + + case NGX_HTTP_NOT_MODIFIED: + r->header_only = 1; + status = ngx_http_v2_indexed(NGX_HTTP_V2_STATUS_304_INDEX); + break; + + default: + r->headers_out.last_modified_time = -1; + r->headers_out.last_modified = NULL; + + switch (r->headers_out.status) { + + case NGX_HTTP_BAD_REQUEST: + status = ngx_http_v2_indexed(NGX_HTTP_V2_STATUS_400_INDEX); + break; + + case NGX_HTTP_NOT_FOUND: + status = ngx_http_v2_indexed(NGX_HTTP_V2_STATUS_404_INDEX); + break; + + case NGX_HTTP_INTERNAL_SERVER_ERROR: + status = ngx_http_v2_indexed(NGX_HTTP_V2_STATUS_500_INDEX); + break; + + default: + status = 0; + } + } + + len = status ? 1 : 1 + ngx_http_v2_literal_size("418"); + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + if (r->headers_out.server == NULL) { + len += 1 + clcf->server_tokens ? ngx_http_v2_literal_size(NGINX_VER) + : ngx_http_v2_literal_size("nginx"); + } + + if (r->headers_out.date == NULL) { + len += 1 + ngx_http_v2_literal_size("Wed, 31 Dec 1986 18:00:00 GMT"); + } + + if (r->headers_out.content_type.len) { + len += NGX_HTTP_V2_INT_OCTETS + r->headers_out.content_type.len; + + if (r->headers_out.content_type_len == r->headers_out.content_type.len + && r->headers_out.charset.len) + { + len += sizeof("; charset=") - 1 + r->headers_out.charset.len; + } + } + + if (r->headers_out.content_length == NULL + && r->headers_out.content_length_n >= 0) + { + len += 1 + ngx_http_v2_integer_octets(NGX_OFF_T_LEN) + NGX_OFF_T_LEN; + } + + if (r->headers_out.last_modified == NULL + && r->headers_out.last_modified_time != -1) + { + len += 1 + ngx_http_v2_literal_size("Wed, 31 Dec 1986 18:00:00 GMT"); + } + + fc = r->connection; + + if (r->headers_out.location && r->headers_out.location->value.len) { + + if (r->headers_out.location->value.data[0] == '/') { + if (clcf->server_name_in_redirect) { + cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); + host = cscf->server_name; + + } else if (r->headers_in.server.len) { + host = r->headers_in.server; + + } else { + host.len = NGX_SOCKADDR_STRLEN; + host.data = addr; + + if (ngx_connection_local_sockaddr(fc, &host, 0) != NGX_OK) { + return NGX_ERROR; + } + } + + switch (fc->local_sockaddr->sa_family) { + +#if (NGX_HAVE_INET6) + case AF_INET6: + sin6 = (struct sockaddr_in6 *) fc->local_sockaddr; + port = ntohs(sin6->sin6_port); + break; +#endif +#if (NGX_HAVE_UNIX_DOMAIN) + case AF_UNIX: + port = 0; + break; +#endif + default: /* AF_INET */ + sin = (struct sockaddr_in *) fc->local_sockaddr; + port = ntohs(sin->sin_port); + break; + } + + location.len = sizeof("https://") - 1 + host.len + + r->headers_out.location->value.len; + + if (clcf->port_in_redirect) { + +#if (NGX_HTTP_SSL) + if (fc->ssl) + port = (port == 443) ? 0 : port; + else +#endif + port = (port == 80) ? 0 : port; + + } else { + port = 0; + } + + if (port) { + location.len += sizeof(":65535") - 1; + } + + location.data = ngx_pnalloc(r->pool, location.len); + if (location.data == NULL) { + return NGX_ERROR; + } + + p = ngx_cpymem(location.data, "http", sizeof("http") - 1); + +#if (NGX_HTTP_SSL) + if (fc->ssl) { + *p++ = 's'; + } +#endif + + *p++ = ':'; *p++ = '/'; *p++ = '/'; + p = ngx_cpymem(p, host.data, host.len); + + if (port) { + p = ngx_sprintf(p, ":%ui", port); + } + + p = ngx_cpymem(p, r->headers_out.location->value.data, + r->headers_out.location->value.len); + + /* update r->headers_out.location->value for possible logging */ + + r->headers_out.location->value.len = p - location.data; + r->headers_out.location->value.data = location.data; + ngx_str_set(&r->headers_out.location->key, "Location"); + } + + r->headers_out.location->hash = 0; + + len += 1 + NGX_HTTP_V2_INT_OCTETS + r->headers_out.location->value.len; + } + +#if (NGX_HTTP_GZIP) + if (r->gzip_vary) { + if (clcf->gzip_vary) { + len += 1 + ngx_http_v2_literal_size("Accept-Encoding"); + + } else { + r->gzip_vary = 0; + } + } +#endif + + part = &r->headers_out.headers.part; + header = part->elts; + + for (i = 0; /* void */; i++) { + + if (i >= part->nelts) { + if (part->next == NULL) { + break; + } + + part = part->next; + header = part->elts; + i = 0; + } + + if (header[i].hash == 0) { + continue; + } + + if (header[i].key.len > NGX_HTTP_V2_MAX_FIELD) { + ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0, + "too long response header name: \"%V\"", + &header[i].key); + return NGX_ERROR; + } + + if (header[i].value.len > NGX_HTTP_V2_MAX_FIELD) { + ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0, + "too long response header value: \"%V: %V\"", + &header[i].key, &header[i].value); + return NGX_ERROR; + } + + len += 1 + NGX_HTTP_V2_INT_OCTETS + header[i].key.len + + NGX_HTTP_V2_INT_OCTETS + header[i].value.len; + } + + stream = r->stream; + frame_size = stream->connection->frame_size; + + len += NGX_HTTP_V2_FRAME_HEADER_SIZE + * ((len + frame_size - 1) / frame_size); + + b = ngx_create_temp_buf(r->pool, len); + if (b == NULL) { + return NGX_ERROR; + } + + b->last_buf = r->header_only; + + b->last += NGX_HTTP_V2_FRAME_HEADER_SIZE; + + if (status) { + *b->last++ = status; + + } else { + *b->last++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_STATUS_INDEX); + *b->last++ = 3; + b->last = ngx_sprintf(b->last, "%03ui", r->headers_out.status); + } + + if (r->headers_out.server == NULL) { + *b->last++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_SERVER_INDEX); + + if (clcf->server_tokens) { + *b->last++ = sizeof(NGINX_VER) - 1; + b->last = ngx_cpymem(b->last, NGINX_VER, sizeof(NGINX_VER) - 1); + + } else { + *b->last++ = sizeof("nginx") - 1; + b->last = ngx_cpymem(b->last, "nginx", sizeof("nginx") - 1); + } + } + + if (r->headers_out.date == NULL) { + *b->last++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_DATE_INDEX); + *b->last++ = (u_char) ngx_cached_http_time.len; + + b->last = ngx_cpymem(b->last, ngx_cached_http_time.data, + ngx_cached_http_time.len); + } + + if (r->headers_out.content_type.len) { + *b->last++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_CONTENT_TYPE_INDEX); + + if (r->headers_out.content_type_len == r->headers_out.content_type.len + && r->headers_out.charset.len) + { + *b->last = 0; + b->last = ngx_http_v2_write_int(b->last, ngx_http_v2_prefix(7), + r->headers_out.content_type.len + + sizeof("; charset=") - 1 + + r->headers_out.charset.len); + + p = b->last; + + b->last = ngx_cpymem(p, r->headers_out.content_type.data, + r->headers_out.content_type.len); + + b->last = ngx_cpymem(b->last, "; charset=", + sizeof("; charset=") - 1); + + b->last = ngx_cpymem(b->last, r->headers_out.charset.data, + r->headers_out.charset.len); + + /* update r->headers_out.content_type for possible logging */ + + r->headers_out.content_type.len = b->last - p; + r->headers_out.content_type.data = p; + + } else { + *b->last = 0; + b->last = ngx_http_v2_write_int(b->last, ngx_http_v2_prefix(7), + r->headers_out.content_type.len); + b->last = ngx_cpymem(b->last, r->headers_out.content_type.data, + r->headers_out.content_type.len); + } + } + + if (r->headers_out.content_length == NULL + && r->headers_out.content_length_n >= 0) + { + *b->last++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_CONTENT_LENGTH_INDEX); + + p = b->last; + b->last = ngx_sprintf(b->last + 1, "%O", + r->headers_out.content_length_n); + *p = (u_char) (b->last - p - 1); + } + + if (r->headers_out.last_modified == NULL + && r->headers_out.last_modified_time != -1) + { + *b->last++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_LAST_MODIFIED_INDEX); + + p = b->last; + b->last = ngx_http_time(b->last + 1, r->headers_out.last_modified_time); + *p = (u_char) (b->last - p - 1); + } + + if (r->headers_out.location && r->headers_out.location->value.len) { + *b->last++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_LOCATION_INDEX); + + *b->last = 0; + b->last = ngx_http_v2_write_int(b->last, ngx_http_v2_prefix(7), + r->headers_out.location->value.len); + b->last = ngx_cpymem(b->last, r->headers_out.location->value.data, + r->headers_out.location->value.len); + } + +#if (NGX_HTTP_GZIP) + if (r->gzip_vary) { + *b->last++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_VARY_INDEX); + *b->last++ = sizeof("Accept-Encoding") - 1; + b->last = ngx_cpymem(b->last, "Accept-Encoding", + sizeof("Accept-Encoding") - 1); + } +#endif + + continuation = 0; + head = b->pos; + + len = b->last - head - NGX_HTTP_V2_FRAME_HEADER_SIZE; + rest = frame_size - len; + + part = &r->headers_out.headers.part; + header = part->elts; + + for (i = 0; /* void */; i++) { + + if (i >= part->nelts) { + if (part->next == NULL) { + break; + } + + part = part->next; + header = part->elts; + i = 0; + } + + if (header[i].hash == 0) { + continue; + } + + len = 1 + NGX_HTTP_V2_INT_OCTETS * 2 + + header[i].key.len + + header[i].value.len; + + if (len > rest) { + len = b->last - head - NGX_HTTP_V2_FRAME_HEADER_SIZE; + + if (continuation) { + ngx_http_v2_write_continuation_head(head, len, + stream->node->id, 0); + } else { + continuation = 1; + ngx_http_v2_write_headers_head(head, len, stream->node->id, 0, + r->header_only); + } + + rest = frame_size; + head = b->last; + + b->last += NGX_HTTP_V2_FRAME_HEADER_SIZE; + } + + p = b->last; + + *p++ = 0; + + *p = 0; + p = ngx_http_v2_write_int(p, ngx_http_v2_prefix(7), header[i].key.len); + ngx_strlow(p, header[i].key.data, header[i].key.len); + p += header[i].key.len; + + *p = 0; + p = ngx_http_v2_write_int(p, ngx_http_v2_prefix(7), + header[i].value.len); + p = ngx_cpymem(p, header[i].value.data, header[i].value.len); + + rest -= p - b->last; + b->last = p; + } + + len = b->last - head - NGX_HTTP_V2_FRAME_HEADER_SIZE; + + if (continuation) { + ngx_http_v2_write_continuation_head(head, len, stream->node->id, 1); + + } else { + ngx_http_v2_write_headers_head(head, len, stream->node->id, 1, + r->header_only); + } + + cl = ngx_alloc_chain_link(r->pool); + if (cl == NULL) { + return NGX_ERROR; + } + + cl->buf = b; + cl->next = NULL; + + frame = ngx_palloc(r->pool, sizeof(ngx_http_v2_out_frame_t)); + if (frame == NULL) { + return NGX_ERROR; + } + + frame->first = cl; + frame->last = cl; + frame->handler = ngx_http_v2_headers_frame_handler; + frame->stream = stream; + frame->length = b->last - b->pos - NGX_HTTP_V2_FRAME_HEADER_SIZE; + frame->blocked = 1; + frame->fin = r->header_only; + + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, stream->request->connection->log, 0, + "http2:%ui create HEADERS frame %p: len:%uz", + stream->node->id, frame, frame->length); + + ngx_http_v2_queue_blocked_frame(stream->connection, frame); + + cln = ngx_http_cleanup_add(r, 0); + if (cln == NULL) { + return NGX_ERROR; + } + + cln->handler = ngx_http_v2_filter_cleanup; + cln->data = stream; + + stream->queued = 1; + + fc->send_chain = ngx_http_v2_send_chain; + fc->need_last_buf = 1; + + return ngx_http_v2_filter_send(fc, stream); +} + + +static u_char * +ngx_http_v2_write_int(u_char *pos, ngx_uint_t prefix, ngx_uint_t value) +{ + if (value < prefix) { + *pos++ |= value; + return pos; + } + + *pos++ |= prefix; + value -= prefix; + + while (value >= 128) { + *pos++ = value % 128 + 128; + value /= 128; + } + + *pos++ = (u_char) value; + + return pos; +} + + +static void +ngx_http_v2_write_headers_head(u_char *pos, size_t length, ngx_uint_t sid, + ngx_uint_t end_headers, ngx_uint_t end_stream) +{ + u_char flags; + + pos = ngx_http_v2_write_len_and_type(pos, length, + NGX_HTTP_V2_HEADERS_FRAME); + + flags = NGX_HTTP_V2_NO_FLAG; + + if (end_headers) { + flags |= NGX_HTTP_V2_END_HEADERS_FLAG; + } + + if (end_stream) { + flags |= NGX_HTTP_V2_END_STREAM_FLAG; + } + + *pos++ = flags; + + (void) ngx_http_v2_write_sid(pos, sid); +} + + +static void +ngx_http_v2_write_continuation_head(u_char *pos, size_t length, ngx_uint_t sid, + ngx_uint_t end_headers) +{ + pos = ngx_http_v2_write_len_and_type(pos, length, + NGX_HTTP_V2_CONTINUATION_FRAME); + + *pos++ = end_headers ? NGX_HTTP_V2_END_HEADERS_FLAG : NGX_HTTP_V2_NO_FLAG; + + (void) ngx_http_v2_write_sid(pos, sid); +} + + +static ngx_chain_t * +ngx_http_v2_send_chain(ngx_connection_t *fc, ngx_chain_t *in, off_t limit) +{ + off_t size, offset; + size_t rest, frame_size; + ngx_chain_t *cl, *out, **ln; + ngx_http_request_t *r; + ngx_http_v2_stream_t *stream; + ngx_http_v2_loc_conf_t *h2lcf; + ngx_http_v2_out_frame_t *frame; + ngx_http_v2_connection_t *h2c; + + r = fc->data; + stream = r->stream; + +#if (NGX_SUPPRESS_WARN) + size = 0; +#endif + + while (in) { + size = ngx_buf_size(in->buf); + + if (size || in->buf->last_buf) { + break; + } + + in = in->next; + } + + if (in == NULL) { + + if (stream->queued) { + fc->write->delayed = 1; + } else { + fc->buffered &= ~NGX_HTTP_V2_BUFFERED; + } + + return NULL; + } + + h2c = stream->connection; + + if (size && ngx_http_v2_flow_control(h2c, stream) == NGX_DECLINED) { + fc->write->delayed = 1; + return in; + } + + if (in->buf->tag == (ngx_buf_tag_t) &ngx_http_v2_filter_get_shadow) { + cl = ngx_alloc_chain_link(r->pool); + if (cl == NULL) { + return NGX_CHAIN_ERROR; + } + + cl->buf = in->buf; + in->buf = cl->buf->shadow; + + offset = ngx_buf_in_memory(in->buf) + ? (cl->buf->pos - in->buf->pos) + : (cl->buf->file_pos - in->buf->file_pos); + + cl->next = stream->free_bufs; + stream->free_bufs = cl; + + } else { + offset = 0; + } + + if (limit == 0 || limit > (off_t) h2c->send_window) { + limit = h2c->send_window; + } + + if (limit > stream->send_window) { + limit = (stream->send_window > 0) ? stream->send_window : 0; + } + + h2lcf = ngx_http_get_module_loc_conf(r, ngx_http_v2_module); + + frame_size = (h2lcf->chunk_size < h2c->frame_size) + ? h2lcf->chunk_size : h2c->frame_size; + +#if (NGX_SUPPRESS_WARN) + cl = NULL; +#endif + + for ( ;; ) { + if ((off_t) frame_size > limit) { + frame_size = (size_t) limit; + } + + ln = &out; + rest = frame_size; + + while ((off_t) rest >= size) { + + if (offset) { + cl = ngx_http_v2_filter_get_shadow(stream, in->buf, + offset, size); + if (cl == NULL) { + return NGX_CHAIN_ERROR; + } + + offset = 0; + + } else { + cl = ngx_alloc_chain_link(r->pool); + if (cl == NULL) { + return NGX_CHAIN_ERROR; + } + + cl->buf = in->buf; + } + + *ln = cl; + ln = &cl->next; + + rest -= (size_t) size; + in = in->next; + + if (in == NULL) { + frame_size -= rest; + rest = 0; + break; + } + + size = ngx_buf_size(in->buf); + } + + if (rest) { + cl = ngx_http_v2_filter_get_shadow(stream, in->buf, offset, rest); + if (cl == NULL) { + return NGX_CHAIN_ERROR; + } + + cl->buf->flush = 0; + cl->buf->last_buf = 0; + + *ln = cl; + + offset += rest; + size -= rest; + } + + frame = ngx_http_v2_filter_get_data_frame(stream, frame_size, out, cl); + if (frame == NULL) { + return NGX_CHAIN_ERROR; + } + + ngx_http_v2_queue_frame(h2c, frame); + + h2c->send_window -= frame_size; + + stream->send_window -= frame_size; + stream->queued++; + + if (in == NULL) { + break; + } + + limit -= frame_size; + + if (limit == 0) { + break; + } + } + + if (offset) { + cl = ngx_http_v2_filter_get_shadow(stream, in->buf, offset, size); + if (cl == NULL) { + return NGX_CHAIN_ERROR; + } + + in->buf = cl->buf; + ngx_free_chain(r->pool, cl); + } + + if (ngx_http_v2_filter_send(fc, stream) == NGX_ERROR) { + return NGX_CHAIN_ERROR; + } + + if (in && ngx_http_v2_flow_control(h2c, stream) == NGX_DECLINED) { + fc->write->delayed = 1; + } + + return in; +} + + +static ngx_chain_t * +ngx_http_v2_filter_get_shadow(ngx_http_v2_stream_t *stream, ngx_buf_t *buf, + off_t offset, off_t size) +{ + ngx_buf_t *chunk; + ngx_chain_t *cl; + + cl = ngx_chain_get_free_buf(stream->request->pool, &stream->free_bufs); + if (cl == NULL) { + return NULL; + } + + chunk = cl->buf; + + ngx_memcpy(chunk, buf, sizeof(ngx_buf_t)); + + chunk->tag = (ngx_buf_tag_t) &ngx_http_v2_filter_get_shadow; + chunk->shadow = buf; + + if (ngx_buf_in_memory(chunk)) { + chunk->pos += offset; + chunk->last = chunk->pos + size; + } + + if (chunk->in_file) { + chunk->file_pos += offset; + chunk->file_last = chunk->file_pos + size; + } + + return cl; +} + + +static ngx_http_v2_out_frame_t * +ngx_http_v2_filter_get_data_frame(ngx_http_v2_stream_t *stream, + size_t len, ngx_chain_t *first, ngx_chain_t *last) +{ + u_char flags; + ngx_buf_t *buf; + ngx_chain_t *cl; + ngx_http_v2_out_frame_t *frame; + + + frame = stream->free_frames; + + if (frame) { + stream->free_frames = frame->next; + + } else { + frame = ngx_palloc(stream->request->pool, + sizeof(ngx_http_v2_out_frame_t)); + if (frame == NULL) { + return NULL; + } + } + + flags = last->buf->last_buf ? NGX_HTTP_V2_END_STREAM_FLAG : 0; + + ngx_log_debug4(NGX_LOG_DEBUG_HTTP, stream->request->connection->log, 0, + "http2:%ui create DATA frame %p: len:%uz flags:%ui", + stream->node->id, frame, len, (ngx_uint_t) flags); + + cl = ngx_chain_get_free_buf(stream->request->pool, + &stream->free_data_headers); + if (cl == NULL) { + return NULL; + } + + buf = cl->buf; + + if (!buf->start) { + buf->start = ngx_palloc(stream->request->pool, + NGX_HTTP_V2_FRAME_HEADER_SIZE); + if (buf->start == NULL) { + return NULL; + } + + buf->end = buf->start + NGX_HTTP_V2_FRAME_HEADER_SIZE; + buf->last = buf->end; + + buf->tag = (ngx_buf_tag_t) &ngx_http_v2_filter_get_data_frame; + buf->memory = 1; + } + + buf->pos = buf->start; + buf->last = buf->pos; + + buf->last = ngx_http_v2_write_len_and_type(buf->last, len, + NGX_HTTP_V2_DATA_FRAME); + *buf->last++ = flags; + + buf->last = ngx_http_v2_write_sid(buf->last, stream->node->id); + + cl->next = first; + first = cl; + + last->buf->flush = 1; + + frame->first = first; + frame->last = last; + frame->handler = ngx_http_v2_data_frame_handler; + frame->stream = stream; + frame->length = len; + frame->blocked = 0; + frame->fin = last->buf->last_buf; + + return frame; +} + + +static ngx_inline ngx_int_t +ngx_http_v2_filter_send(ngx_connection_t *fc, ngx_http_v2_stream_t *stream) +{ + stream->blocked = 1; + + if (ngx_http_v2_send_output_queue(stream->connection) == NGX_ERROR) { + fc->error = 1; + return NGX_ERROR; + } + + stream->blocked = 0; + + if (stream->queued) { + fc->buffered |= NGX_HTTP_V2_BUFFERED; + fc->write->delayed = 1; + return NGX_AGAIN; + } + + fc->buffered &= ~NGX_HTTP_V2_BUFFERED; + + return NGX_OK; +} + + +static ngx_inline ngx_int_t +ngx_http_v2_flow_control(ngx_http_v2_connection_t *h2c, + ngx_http_v2_stream_t *stream) +{ + if (stream->send_window <= 0) { + stream->exhausted = 1; + return NGX_DECLINED; + } + + if (h2c->send_window == 0) { + ngx_http_v2_waiting_queue(h2c, stream); + return NGX_DECLINED; + } + + return NGX_OK; +} + + +static void +ngx_http_v2_waiting_queue(ngx_http_v2_connection_t *h2c, + ngx_http_v2_stream_t *stream) +{ + ngx_queue_t *q; + ngx_http_v2_stream_t *s; + + if (stream->handled) { + return; + } + + stream->handled = 1; + + for (q = ngx_queue_last(&h2c->waiting); + q != ngx_queue_sentinel(&h2c->waiting); + q = ngx_queue_prev(q)) + { + s = ngx_queue_data(q, ngx_http_v2_stream_t, queue); + + if (s->node->rank < stream->node->rank + || (s->node->rank == stream->node->rank + && s->node->rel_weight >= stream->node->rel_weight)) + { + break; + } + } + + ngx_queue_insert_after(q, &stream->queue); +} + + + +static ngx_int_t +ngx_http_v2_headers_frame_handler(ngx_http_v2_connection_t *h2c, + ngx_http_v2_out_frame_t *frame) +{ + ngx_buf_t *buf; + ngx_http_v2_stream_t *stream; + + buf = frame->first->buf; + + if (buf->pos != buf->last) { + return NGX_AGAIN; + } + + stream = frame->stream; + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "http2:%ui HEADERS frame %p was sent", + stream->node->id, frame); + + ngx_free_chain(stream->request->pool, frame->first); + + ngx_http_v2_handle_frame(stream, frame); + + ngx_http_v2_handle_stream(h2c, stream); + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_v2_data_frame_handler(ngx_http_v2_connection_t *h2c, + ngx_http_v2_out_frame_t *frame) +{ + ngx_buf_t *buf; + ngx_chain_t *cl, *ln; + ngx_http_v2_stream_t *stream; + + stream = frame->stream; + + cl = frame->first; + + if (cl->buf->tag == (ngx_buf_tag_t) &ngx_http_v2_filter_get_data_frame) { + + if (cl->buf->pos != cl->buf->last) { + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "http2:%ui DATA frame %p was sent partially", + stream->node->id, frame); + + return NGX_AGAIN; + } + + ln = cl->next; + + cl->next = stream->free_data_headers; + stream->free_data_headers = cl; + + if (cl == frame->last) { + goto done; + } + + cl = ln; + } + + for ( ;; ) { + if (cl->buf->tag == (ngx_buf_tag_t) &ngx_http_v2_filter_get_shadow) { + buf = cl->buf->shadow; + + if (ngx_buf_in_memory(buf)) { + buf->pos = cl->buf->pos; + } + + if (buf->in_file) { + buf->file_pos = cl->buf->file_pos; + } + } + + if (ngx_buf_size(cl->buf) != 0) { + + if (cl != frame->first) { + frame->first = cl; + ngx_http_v2_handle_stream(h2c, stream); + } + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "http2:%ui DATA frame %p was sent partially", + stream->node->id, frame); + + return NGX_AGAIN; + } + + ln = cl->next; + + if (cl->buf->tag == (ngx_buf_tag_t) &ngx_http_v2_filter_get_shadow) { + cl->next = stream->free_bufs; + stream->free_bufs = cl; + + } else { + ngx_free_chain(stream->request->pool, cl); + } + + if (cl == frame->last) { + goto done; + } + + cl = ln; + } + +done: + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "http2:%ui DATA frame %p was sent", + stream->node->id, frame); + + stream->request->header_size += NGX_HTTP_V2_FRAME_HEADER_SIZE; + + ngx_http_v2_handle_frame(stream, frame); + + ngx_http_v2_handle_stream(h2c, stream); + + return NGX_OK; +} + + +static ngx_inline void +ngx_http_v2_handle_frame(ngx_http_v2_stream_t *stream, + ngx_http_v2_out_frame_t *frame) +{ + ngx_http_request_t *r; + + r = stream->request; + + r->connection->sent += NGX_HTTP_V2_FRAME_HEADER_SIZE + frame->length; + + if (frame->fin) { + stream->out_closed = 1; + } + + frame->next = stream->free_frames; + stream->free_frames = frame; + + stream->queued--; +} + + +static ngx_inline void +ngx_http_v2_handle_stream(ngx_http_v2_connection_t *h2c, + ngx_http_v2_stream_t *stream) +{ + ngx_event_t *wev; + + if (stream->handled || stream->blocked || stream->exhausted) { + return; + } + + wev = stream->request->connection->write; + + /* + * This timer can only be set if the stream was delayed because of rate + * limit. In that case the event should be triggered by the timer. + */ + + if (!wev->timer_set) { + wev->delayed = 0; + + stream->handled = 1; + ngx_queue_insert_tail(&h2c->posted, &stream->queue); + } +} + + +static void +ngx_http_v2_filter_cleanup(void *data) +{ + ngx_http_v2_stream_t *stream = data; + + size_t window; + ngx_http_v2_out_frame_t *frame, **fn; + ngx_http_v2_connection_t *h2c; + + if (stream->handled) { + stream->handled = 0; + ngx_queue_remove(&stream->queue); + } + + if (stream->queued == 0) { + return; + } + + window = 0; + h2c = stream->connection; + fn = &h2c->last_out; + + for ( ;; ) { + frame = *fn; + + if (frame == NULL) { + break; + } + + if (frame->stream == stream && !frame->blocked) { + *fn = frame->next; + + window += frame->length; + + if (--stream->queued == 0) { + break; + } + + continue; + } + + 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); + } + + h2c->send_window += window; +} + + +static ngx_int_t +ngx_http_v2_filter_init(ngx_conf_t *cf) +{ + ngx_http_next_header_filter = ngx_http_top_header_filter; + ngx_http_top_header_filter = ngx_http_v2_header_filter; + + return NGX_OK; +} diff --git a/src/http/v2/ngx_http_v2_huff_decode.c b/src/http/v2/ngx_http_v2_huff_decode.c new file mode 100644 index 0000000..49ca576 --- /dev/null +++ b/src/http/v2/ngx_http_v2_huff_decode.c @@ -0,0 +1,2714 @@ + +/* + * Copyright (C) Nginx, Inc. + * Copyright (C) Valentin V. Bartenev + */ + + +#include +#include +#include + + +typedef struct { + u_char next; + u_char emit; + u_char sym; + u_char ending; +} ngx_http_v2_huff_decode_code_t; + + +static ngx_inline ngx_int_t ngx_http_v2_huff_decode_bits(u_char *state, + u_char *ending, ngx_uint_t bits, u_char **dst); + + +static ngx_http_v2_huff_decode_code_t ngx_http_v2_huff_decode_codes[256][16] = +{ + /* 0 */ + { + {0x04, 0x00, 0x00, 0x00}, {0x05, 0x00, 0x00, 0x00}, + {0x07, 0x00, 0x00, 0x00}, {0x08, 0x00, 0x00, 0x00}, + {0x0b, 0x00, 0x00, 0x00}, {0x0c, 0x00, 0x00, 0x00}, + {0x10, 0x00, 0x00, 0x00}, {0x13, 0x00, 0x00, 0x00}, + {0x19, 0x00, 0x00, 0x00}, {0x1c, 0x00, 0x00, 0x00}, + {0x20, 0x00, 0x00, 0x00}, {0x23, 0x00, 0x00, 0x00}, + {0x2a, 0x00, 0x00, 0x00}, {0x31, 0x00, 0x00, 0x00}, + {0x39, 0x00, 0x00, 0x00}, {0x40, 0x00, 0x00, 0x01} + }, + { + {0x00, 0x01, 0x30, 0x01}, {0x00, 0x01, 0x31, 0x01}, + {0x00, 0x01, 0x32, 0x01}, {0x00, 0x01, 0x61, 0x01}, + {0x00, 0x01, 0x63, 0x01}, {0x00, 0x01, 0x65, 0x01}, + {0x00, 0x01, 0x69, 0x01}, {0x00, 0x01, 0x6f, 0x01}, + {0x00, 0x01, 0x73, 0x01}, {0x00, 0x01, 0x74, 0x01}, + {0x0d, 0x00, 0x00, 0x00}, {0x0e, 0x00, 0x00, 0x00}, + {0x11, 0x00, 0x00, 0x00}, {0x12, 0x00, 0x00, 0x00}, + {0x14, 0x00, 0x00, 0x00}, {0x15, 0x00, 0x00, 0x00} + }, + { + {0x01, 0x01, 0x30, 0x00}, {0x16, 0x01, 0x30, 0x01}, + {0x01, 0x01, 0x31, 0x00}, {0x16, 0x01, 0x31, 0x01}, + {0x01, 0x01, 0x32, 0x00}, {0x16, 0x01, 0x32, 0x01}, + {0x01, 0x01, 0x61, 0x00}, {0x16, 0x01, 0x61, 0x01}, + {0x01, 0x01, 0x63, 0x00}, {0x16, 0x01, 0x63, 0x01}, + {0x01, 0x01, 0x65, 0x00}, {0x16, 0x01, 0x65, 0x01}, + {0x01, 0x01, 0x69, 0x00}, {0x16, 0x01, 0x69, 0x01}, + {0x01, 0x01, 0x6f, 0x00}, {0x16, 0x01, 0x6f, 0x01} + }, + { + {0x02, 0x01, 0x30, 0x00}, {0x09, 0x01, 0x30, 0x00}, + {0x17, 0x01, 0x30, 0x00}, {0x28, 0x01, 0x30, 0x01}, + {0x02, 0x01, 0x31, 0x00}, {0x09, 0x01, 0x31, 0x00}, + {0x17, 0x01, 0x31, 0x00}, {0x28, 0x01, 0x31, 0x01}, + {0x02, 0x01, 0x32, 0x00}, {0x09, 0x01, 0x32, 0x00}, + {0x17, 0x01, 0x32, 0x00}, {0x28, 0x01, 0x32, 0x01}, + {0x02, 0x01, 0x61, 0x00}, {0x09, 0x01, 0x61, 0x00}, + {0x17, 0x01, 0x61, 0x00}, {0x28, 0x01, 0x61, 0x01} + }, + { + {0x03, 0x01, 0x30, 0x00}, {0x06, 0x01, 0x30, 0x00}, + {0x0a, 0x01, 0x30, 0x00}, {0x0f, 0x01, 0x30, 0x00}, + {0x18, 0x01, 0x30, 0x00}, {0x1f, 0x01, 0x30, 0x00}, + {0x29, 0x01, 0x30, 0x00}, {0x38, 0x01, 0x30, 0x01}, + {0x03, 0x01, 0x31, 0x00}, {0x06, 0x01, 0x31, 0x00}, + {0x0a, 0x01, 0x31, 0x00}, {0x0f, 0x01, 0x31, 0x00}, + {0x18, 0x01, 0x31, 0x00}, {0x1f, 0x01, 0x31, 0x00}, + {0x29, 0x01, 0x31, 0x00}, {0x38, 0x01, 0x31, 0x01} + }, + /* 5 */ + { + {0x03, 0x01, 0x32, 0x00}, {0x06, 0x01, 0x32, 0x00}, + {0x0a, 0x01, 0x32, 0x00}, {0x0f, 0x01, 0x32, 0x00}, + {0x18, 0x01, 0x32, 0x00}, {0x1f, 0x01, 0x32, 0x00}, + {0x29, 0x01, 0x32, 0x00}, {0x38, 0x01, 0x32, 0x01}, + {0x03, 0x01, 0x61, 0x00}, {0x06, 0x01, 0x61, 0x00}, + {0x0a, 0x01, 0x61, 0x00}, {0x0f, 0x01, 0x61, 0x00}, + {0x18, 0x01, 0x61, 0x00}, {0x1f, 0x01, 0x61, 0x00}, + {0x29, 0x01, 0x61, 0x00}, {0x38, 0x01, 0x61, 0x01} + }, + { + {0x02, 0x01, 0x63, 0x00}, {0x09, 0x01, 0x63, 0x00}, + {0x17, 0x01, 0x63, 0x00}, {0x28, 0x01, 0x63, 0x01}, + {0x02, 0x01, 0x65, 0x00}, {0x09, 0x01, 0x65, 0x00}, + {0x17, 0x01, 0x65, 0x00}, {0x28, 0x01, 0x65, 0x01}, + {0x02, 0x01, 0x69, 0x00}, {0x09, 0x01, 0x69, 0x00}, + {0x17, 0x01, 0x69, 0x00}, {0x28, 0x01, 0x69, 0x01}, + {0x02, 0x01, 0x6f, 0x00}, {0x09, 0x01, 0x6f, 0x00}, + {0x17, 0x01, 0x6f, 0x00}, {0x28, 0x01, 0x6f, 0x01} + }, + { + {0x03, 0x01, 0x63, 0x00}, {0x06, 0x01, 0x63, 0x00}, + {0x0a, 0x01, 0x63, 0x00}, {0x0f, 0x01, 0x63, 0x00}, + {0x18, 0x01, 0x63, 0x00}, {0x1f, 0x01, 0x63, 0x00}, + {0x29, 0x01, 0x63, 0x00}, {0x38, 0x01, 0x63, 0x01}, + {0x03, 0x01, 0x65, 0x00}, {0x06, 0x01, 0x65, 0x00}, + {0x0a, 0x01, 0x65, 0x00}, {0x0f, 0x01, 0x65, 0x00}, + {0x18, 0x01, 0x65, 0x00}, {0x1f, 0x01, 0x65, 0x00}, + {0x29, 0x01, 0x65, 0x00}, {0x38, 0x01, 0x65, 0x01} + }, + { + {0x03, 0x01, 0x69, 0x00}, {0x06, 0x01, 0x69, 0x00}, + {0x0a, 0x01, 0x69, 0x00}, {0x0f, 0x01, 0x69, 0x00}, + {0x18, 0x01, 0x69, 0x00}, {0x1f, 0x01, 0x69, 0x00}, + {0x29, 0x01, 0x69, 0x00}, {0x38, 0x01, 0x69, 0x01}, + {0x03, 0x01, 0x6f, 0x00}, {0x06, 0x01, 0x6f, 0x00}, + {0x0a, 0x01, 0x6f, 0x00}, {0x0f, 0x01, 0x6f, 0x00}, + {0x18, 0x01, 0x6f, 0x00}, {0x1f, 0x01, 0x6f, 0x00}, + {0x29, 0x01, 0x6f, 0x00}, {0x38, 0x01, 0x6f, 0x01} + }, + { + {0x01, 0x01, 0x73, 0x00}, {0x16, 0x01, 0x73, 0x01}, + {0x01, 0x01, 0x74, 0x00}, {0x16, 0x01, 0x74, 0x01}, + {0x00, 0x01, 0x20, 0x01}, {0x00, 0x01, 0x25, 0x01}, + {0x00, 0x01, 0x2d, 0x01}, {0x00, 0x01, 0x2e, 0x01}, + {0x00, 0x01, 0x2f, 0x01}, {0x00, 0x01, 0x33, 0x01}, + {0x00, 0x01, 0x34, 0x01}, {0x00, 0x01, 0x35, 0x01}, + {0x00, 0x01, 0x36, 0x01}, {0x00, 0x01, 0x37, 0x01}, + {0x00, 0x01, 0x38, 0x01}, {0x00, 0x01, 0x39, 0x01} + }, + /* 10 */ + { + {0x02, 0x01, 0x73, 0x00}, {0x09, 0x01, 0x73, 0x00}, + {0x17, 0x01, 0x73, 0x00}, {0x28, 0x01, 0x73, 0x01}, + {0x02, 0x01, 0x74, 0x00}, {0x09, 0x01, 0x74, 0x00}, + {0x17, 0x01, 0x74, 0x00}, {0x28, 0x01, 0x74, 0x01}, + {0x01, 0x01, 0x20, 0x00}, {0x16, 0x01, 0x20, 0x01}, + {0x01, 0x01, 0x25, 0x00}, {0x16, 0x01, 0x25, 0x01}, + {0x01, 0x01, 0x2d, 0x00}, {0x16, 0x01, 0x2d, 0x01}, + {0x01, 0x01, 0x2e, 0x00}, {0x16, 0x01, 0x2e, 0x01} + }, + { + {0x03, 0x01, 0x73, 0x00}, {0x06, 0x01, 0x73, 0x00}, + {0x0a, 0x01, 0x73, 0x00}, {0x0f, 0x01, 0x73, 0x00}, + {0x18, 0x01, 0x73, 0x00}, {0x1f, 0x01, 0x73, 0x00}, + {0x29, 0x01, 0x73, 0x00}, {0x38, 0x01, 0x73, 0x01}, + {0x03, 0x01, 0x74, 0x00}, {0x06, 0x01, 0x74, 0x00}, + {0x0a, 0x01, 0x74, 0x00}, {0x0f, 0x01, 0x74, 0x00}, + {0x18, 0x01, 0x74, 0x00}, {0x1f, 0x01, 0x74, 0x00}, + {0x29, 0x01, 0x74, 0x00}, {0x38, 0x01, 0x74, 0x01} + }, + { + {0x02, 0x01, 0x20, 0x00}, {0x09, 0x01, 0x20, 0x00}, + {0x17, 0x01, 0x20, 0x00}, {0x28, 0x01, 0x20, 0x01}, + {0x02, 0x01, 0x25, 0x00}, {0x09, 0x01, 0x25, 0x00}, + {0x17, 0x01, 0x25, 0x00}, {0x28, 0x01, 0x25, 0x01}, + {0x02, 0x01, 0x2d, 0x00}, {0x09, 0x01, 0x2d, 0x00}, + {0x17, 0x01, 0x2d, 0x00}, {0x28, 0x01, 0x2d, 0x01}, + {0x02, 0x01, 0x2e, 0x00}, {0x09, 0x01, 0x2e, 0x00}, + {0x17, 0x01, 0x2e, 0x00}, {0x28, 0x01, 0x2e, 0x01} + }, + { + {0x03, 0x01, 0x20, 0x00}, {0x06, 0x01, 0x20, 0x00}, + {0x0a, 0x01, 0x20, 0x00}, {0x0f, 0x01, 0x20, 0x00}, + {0x18, 0x01, 0x20, 0x00}, {0x1f, 0x01, 0x20, 0x00}, + {0x29, 0x01, 0x20, 0x00}, {0x38, 0x01, 0x20, 0x01}, + {0x03, 0x01, 0x25, 0x00}, {0x06, 0x01, 0x25, 0x00}, + {0x0a, 0x01, 0x25, 0x00}, {0x0f, 0x01, 0x25, 0x00}, + {0x18, 0x01, 0x25, 0x00}, {0x1f, 0x01, 0x25, 0x00}, + {0x29, 0x01, 0x25, 0x00}, {0x38, 0x01, 0x25, 0x01} + }, + { + {0x03, 0x01, 0x2d, 0x00}, {0x06, 0x01, 0x2d, 0x00}, + {0x0a, 0x01, 0x2d, 0x00}, {0x0f, 0x01, 0x2d, 0x00}, + {0x18, 0x01, 0x2d, 0x00}, {0x1f, 0x01, 0x2d, 0x00}, + {0x29, 0x01, 0x2d, 0x00}, {0x38, 0x01, 0x2d, 0x01}, + {0x03, 0x01, 0x2e, 0x00}, {0x06, 0x01, 0x2e, 0x00}, + {0x0a, 0x01, 0x2e, 0x00}, {0x0f, 0x01, 0x2e, 0x00}, + {0x18, 0x01, 0x2e, 0x00}, {0x1f, 0x01, 0x2e, 0x00}, + {0x29, 0x01, 0x2e, 0x00}, {0x38, 0x01, 0x2e, 0x01} + }, + /* 15 */ + { + {0x01, 0x01, 0x2f, 0x00}, {0x16, 0x01, 0x2f, 0x01}, + {0x01, 0x01, 0x33, 0x00}, {0x16, 0x01, 0x33, 0x01}, + {0x01, 0x01, 0x34, 0x00}, {0x16, 0x01, 0x34, 0x01}, + {0x01, 0x01, 0x35, 0x00}, {0x16, 0x01, 0x35, 0x01}, + {0x01, 0x01, 0x36, 0x00}, {0x16, 0x01, 0x36, 0x01}, + {0x01, 0x01, 0x37, 0x00}, {0x16, 0x01, 0x37, 0x01}, + {0x01, 0x01, 0x38, 0x00}, {0x16, 0x01, 0x38, 0x01}, + {0x01, 0x01, 0x39, 0x00}, {0x16, 0x01, 0x39, 0x01} + }, + { + {0x02, 0x01, 0x2f, 0x00}, {0x09, 0x01, 0x2f, 0x00}, + {0x17, 0x01, 0x2f, 0x00}, {0x28, 0x01, 0x2f, 0x01}, + {0x02, 0x01, 0x33, 0x00}, {0x09, 0x01, 0x33, 0x00}, + {0x17, 0x01, 0x33, 0x00}, {0x28, 0x01, 0x33, 0x01}, + {0x02, 0x01, 0x34, 0x00}, {0x09, 0x01, 0x34, 0x00}, + {0x17, 0x01, 0x34, 0x00}, {0x28, 0x01, 0x34, 0x01}, + {0x02, 0x01, 0x35, 0x00}, {0x09, 0x01, 0x35, 0x00}, + {0x17, 0x01, 0x35, 0x00}, {0x28, 0x01, 0x35, 0x01} + }, + { + {0x03, 0x01, 0x2f, 0x00}, {0x06, 0x01, 0x2f, 0x00}, + {0x0a, 0x01, 0x2f, 0x00}, {0x0f, 0x01, 0x2f, 0x00}, + {0x18, 0x01, 0x2f, 0x00}, {0x1f, 0x01, 0x2f, 0x00}, + {0x29, 0x01, 0x2f, 0x00}, {0x38, 0x01, 0x2f, 0x01}, + {0x03, 0x01, 0x33, 0x00}, {0x06, 0x01, 0x33, 0x00}, + {0x0a, 0x01, 0x33, 0x00}, {0x0f, 0x01, 0x33, 0x00}, + {0x18, 0x01, 0x33, 0x00}, {0x1f, 0x01, 0x33, 0x00}, + {0x29, 0x01, 0x33, 0x00}, {0x38, 0x01, 0x33, 0x01} + }, + { + {0x03, 0x01, 0x34, 0x00}, {0x06, 0x01, 0x34, 0x00}, + {0x0a, 0x01, 0x34, 0x00}, {0x0f, 0x01, 0x34, 0x00}, + {0x18, 0x01, 0x34, 0x00}, {0x1f, 0x01, 0x34, 0x00}, + {0x29, 0x01, 0x34, 0x00}, {0x38, 0x01, 0x34, 0x01}, + {0x03, 0x01, 0x35, 0x00}, {0x06, 0x01, 0x35, 0x00}, + {0x0a, 0x01, 0x35, 0x00}, {0x0f, 0x01, 0x35, 0x00}, + {0x18, 0x01, 0x35, 0x00}, {0x1f, 0x01, 0x35, 0x00}, + {0x29, 0x01, 0x35, 0x00}, {0x38, 0x01, 0x35, 0x01} + }, + { + {0x02, 0x01, 0x36, 0x00}, {0x09, 0x01, 0x36, 0x00}, + {0x17, 0x01, 0x36, 0x00}, {0x28, 0x01, 0x36, 0x01}, + {0x02, 0x01, 0x37, 0x00}, {0x09, 0x01, 0x37, 0x00}, + {0x17, 0x01, 0x37, 0x00}, {0x28, 0x01, 0x37, 0x01}, + {0x02, 0x01, 0x38, 0x00}, {0x09, 0x01, 0x38, 0x00}, + {0x17, 0x01, 0x38, 0x00}, {0x28, 0x01, 0x38, 0x01}, + {0x02, 0x01, 0x39, 0x00}, {0x09, 0x01, 0x39, 0x00}, + {0x17, 0x01, 0x39, 0x00}, {0x28, 0x01, 0x39, 0x01} + }, + /* 20 */ + { + {0x03, 0x01, 0x36, 0x00}, {0x06, 0x01, 0x36, 0x00}, + {0x0a, 0x01, 0x36, 0x00}, {0x0f, 0x01, 0x36, 0x00}, + {0x18, 0x01, 0x36, 0x00}, {0x1f, 0x01, 0x36, 0x00}, + {0x29, 0x01, 0x36, 0x00}, {0x38, 0x01, 0x36, 0x01}, + {0x03, 0x01, 0x37, 0x00}, {0x06, 0x01, 0x37, 0x00}, + {0x0a, 0x01, 0x37, 0x00}, {0x0f, 0x01, 0x37, 0x00}, + {0x18, 0x01, 0x37, 0x00}, {0x1f, 0x01, 0x37, 0x00}, + {0x29, 0x01, 0x37, 0x00}, {0x38, 0x01, 0x37, 0x01} + }, + { + {0x03, 0x01, 0x38, 0x00}, {0x06, 0x01, 0x38, 0x00}, + {0x0a, 0x01, 0x38, 0x00}, {0x0f, 0x01, 0x38, 0x00}, + {0x18, 0x01, 0x38, 0x00}, {0x1f, 0x01, 0x38, 0x00}, + {0x29, 0x01, 0x38, 0x00}, {0x38, 0x01, 0x38, 0x01}, + {0x03, 0x01, 0x39, 0x00}, {0x06, 0x01, 0x39, 0x00}, + {0x0a, 0x01, 0x39, 0x00}, {0x0f, 0x01, 0x39, 0x00}, + {0x18, 0x01, 0x39, 0x00}, {0x1f, 0x01, 0x39, 0x00}, + {0x29, 0x01, 0x39, 0x00}, {0x38, 0x01, 0x39, 0x01} + }, + { + {0x1a, 0x00, 0x00, 0x00}, {0x1b, 0x00, 0x00, 0x00}, + {0x1d, 0x00, 0x00, 0x00}, {0x1e, 0x00, 0x00, 0x00}, + {0x21, 0x00, 0x00, 0x00}, {0x22, 0x00, 0x00, 0x00}, + {0x24, 0x00, 0x00, 0x00}, {0x25, 0x00, 0x00, 0x00}, + {0x2b, 0x00, 0x00, 0x00}, {0x2e, 0x00, 0x00, 0x00}, + {0x32, 0x00, 0x00, 0x00}, {0x35, 0x00, 0x00, 0x00}, + {0x3a, 0x00, 0x00, 0x00}, {0x3d, 0x00, 0x00, 0x00}, + {0x41, 0x00, 0x00, 0x00}, {0x44, 0x00, 0x00, 0x01} + }, + { + {0x00, 0x01, 0x3d, 0x01}, {0x00, 0x01, 0x41, 0x01}, + {0x00, 0x01, 0x5f, 0x01}, {0x00, 0x01, 0x62, 0x01}, + {0x00, 0x01, 0x64, 0x01}, {0x00, 0x01, 0x66, 0x01}, + {0x00, 0x01, 0x67, 0x01}, {0x00, 0x01, 0x68, 0x01}, + {0x00, 0x01, 0x6c, 0x01}, {0x00, 0x01, 0x6d, 0x01}, + {0x00, 0x01, 0x6e, 0x01}, {0x00, 0x01, 0x70, 0x01}, + {0x00, 0x01, 0x72, 0x01}, {0x00, 0x01, 0x75, 0x01}, + {0x26, 0x00, 0x00, 0x00}, {0x27, 0x00, 0x00, 0x00} + }, + { + {0x01, 0x01, 0x3d, 0x00}, {0x16, 0x01, 0x3d, 0x01}, + {0x01, 0x01, 0x41, 0x00}, {0x16, 0x01, 0x41, 0x01}, + {0x01, 0x01, 0x5f, 0x00}, {0x16, 0x01, 0x5f, 0x01}, + {0x01, 0x01, 0x62, 0x00}, {0x16, 0x01, 0x62, 0x01}, + {0x01, 0x01, 0x64, 0x00}, {0x16, 0x01, 0x64, 0x01}, + {0x01, 0x01, 0x66, 0x00}, {0x16, 0x01, 0x66, 0x01}, + {0x01, 0x01, 0x67, 0x00}, {0x16, 0x01, 0x67, 0x01}, + {0x01, 0x01, 0x68, 0x00}, {0x16, 0x01, 0x68, 0x01} + }, + /* 25 */ + { + {0x02, 0x01, 0x3d, 0x00}, {0x09, 0x01, 0x3d, 0x00}, + {0x17, 0x01, 0x3d, 0x00}, {0x28, 0x01, 0x3d, 0x01}, + {0x02, 0x01, 0x41, 0x00}, {0x09, 0x01, 0x41, 0x00}, + {0x17, 0x01, 0x41, 0x00}, {0x28, 0x01, 0x41, 0x01}, + {0x02, 0x01, 0x5f, 0x00}, {0x09, 0x01, 0x5f, 0x00}, + {0x17, 0x01, 0x5f, 0x00}, {0x28, 0x01, 0x5f, 0x01}, + {0x02, 0x01, 0x62, 0x00}, {0x09, 0x01, 0x62, 0x00}, + {0x17, 0x01, 0x62, 0x00}, {0x28, 0x01, 0x62, 0x01} + }, + { + {0x03, 0x01, 0x3d, 0x00}, {0x06, 0x01, 0x3d, 0x00}, + {0x0a, 0x01, 0x3d, 0x00}, {0x0f, 0x01, 0x3d, 0x00}, + {0x18, 0x01, 0x3d, 0x00}, {0x1f, 0x01, 0x3d, 0x00}, + {0x29, 0x01, 0x3d, 0x00}, {0x38, 0x01, 0x3d, 0x01}, + {0x03, 0x01, 0x41, 0x00}, {0x06, 0x01, 0x41, 0x00}, + {0x0a, 0x01, 0x41, 0x00}, {0x0f, 0x01, 0x41, 0x00}, + {0x18, 0x01, 0x41, 0x00}, {0x1f, 0x01, 0x41, 0x00}, + {0x29, 0x01, 0x41, 0x00}, {0x38, 0x01, 0x41, 0x01} + }, + { + {0x03, 0x01, 0x5f, 0x00}, {0x06, 0x01, 0x5f, 0x00}, + {0x0a, 0x01, 0x5f, 0x00}, {0x0f, 0x01, 0x5f, 0x00}, + {0x18, 0x01, 0x5f, 0x00}, {0x1f, 0x01, 0x5f, 0x00}, + {0x29, 0x01, 0x5f, 0x00}, {0x38, 0x01, 0x5f, 0x01}, + {0x03, 0x01, 0x62, 0x00}, {0x06, 0x01, 0x62, 0x00}, + {0x0a, 0x01, 0x62, 0x00}, {0x0f, 0x01, 0x62, 0x00}, + {0x18, 0x01, 0x62, 0x00}, {0x1f, 0x01, 0x62, 0x00}, + {0x29, 0x01, 0x62, 0x00}, {0x38, 0x01, 0x62, 0x01} + }, + { + {0x02, 0x01, 0x64, 0x00}, {0x09, 0x01, 0x64, 0x00}, + {0x17, 0x01, 0x64, 0x00}, {0x28, 0x01, 0x64, 0x01}, + {0x02, 0x01, 0x66, 0x00}, {0x09, 0x01, 0x66, 0x00}, + {0x17, 0x01, 0x66, 0x00}, {0x28, 0x01, 0x66, 0x01}, + {0x02, 0x01, 0x67, 0x00}, {0x09, 0x01, 0x67, 0x00}, + {0x17, 0x01, 0x67, 0x00}, {0x28, 0x01, 0x67, 0x01}, + {0x02, 0x01, 0x68, 0x00}, {0x09, 0x01, 0x68, 0x00}, + {0x17, 0x01, 0x68, 0x00}, {0x28, 0x01, 0x68, 0x01} + }, + { + {0x03, 0x01, 0x64, 0x00}, {0x06, 0x01, 0x64, 0x00}, + {0x0a, 0x01, 0x64, 0x00}, {0x0f, 0x01, 0x64, 0x00}, + {0x18, 0x01, 0x64, 0x00}, {0x1f, 0x01, 0x64, 0x00}, + {0x29, 0x01, 0x64, 0x00}, {0x38, 0x01, 0x64, 0x01}, + {0x03, 0x01, 0x66, 0x00}, {0x06, 0x01, 0x66, 0x00}, + {0x0a, 0x01, 0x66, 0x00}, {0x0f, 0x01, 0x66, 0x00}, + {0x18, 0x01, 0x66, 0x00}, {0x1f, 0x01, 0x66, 0x00}, + {0x29, 0x01, 0x66, 0x00}, {0x38, 0x01, 0x66, 0x01} + }, + /* 30 */ + { + {0x03, 0x01, 0x67, 0x00}, {0x06, 0x01, 0x67, 0x00}, + {0x0a, 0x01, 0x67, 0x00}, {0x0f, 0x01, 0x67, 0x00}, + {0x18, 0x01, 0x67, 0x00}, {0x1f, 0x01, 0x67, 0x00}, + {0x29, 0x01, 0x67, 0x00}, {0x38, 0x01, 0x67, 0x01}, + {0x03, 0x01, 0x68, 0x00}, {0x06, 0x01, 0x68, 0x00}, + {0x0a, 0x01, 0x68, 0x00}, {0x0f, 0x01, 0x68, 0x00}, + {0x18, 0x01, 0x68, 0x00}, {0x1f, 0x01, 0x68, 0x00}, + {0x29, 0x01, 0x68, 0x00}, {0x38, 0x01, 0x68, 0x01} + }, + { + {0x01, 0x01, 0x6c, 0x00}, {0x16, 0x01, 0x6c, 0x01}, + {0x01, 0x01, 0x6d, 0x00}, {0x16, 0x01, 0x6d, 0x01}, + {0x01, 0x01, 0x6e, 0x00}, {0x16, 0x01, 0x6e, 0x01}, + {0x01, 0x01, 0x70, 0x00}, {0x16, 0x01, 0x70, 0x01}, + {0x01, 0x01, 0x72, 0x00}, {0x16, 0x01, 0x72, 0x01}, + {0x01, 0x01, 0x75, 0x00}, {0x16, 0x01, 0x75, 0x01}, + {0x00, 0x01, 0x3a, 0x01}, {0x00, 0x01, 0x42, 0x01}, + {0x00, 0x01, 0x43, 0x01}, {0x00, 0x01, 0x44, 0x01} + }, + { + {0x02, 0x01, 0x6c, 0x00}, {0x09, 0x01, 0x6c, 0x00}, + {0x17, 0x01, 0x6c, 0x00}, {0x28, 0x01, 0x6c, 0x01}, + {0x02, 0x01, 0x6d, 0x00}, {0x09, 0x01, 0x6d, 0x00}, + {0x17, 0x01, 0x6d, 0x00}, {0x28, 0x01, 0x6d, 0x01}, + {0x02, 0x01, 0x6e, 0x00}, {0x09, 0x01, 0x6e, 0x00}, + {0x17, 0x01, 0x6e, 0x00}, {0x28, 0x01, 0x6e, 0x01}, + {0x02, 0x01, 0x70, 0x00}, {0x09, 0x01, 0x70, 0x00}, + {0x17, 0x01, 0x70, 0x00}, {0x28, 0x01, 0x70, 0x01} + }, + { + {0x03, 0x01, 0x6c, 0x00}, {0x06, 0x01, 0x6c, 0x00}, + {0x0a, 0x01, 0x6c, 0x00}, {0x0f, 0x01, 0x6c, 0x00}, + {0x18, 0x01, 0x6c, 0x00}, {0x1f, 0x01, 0x6c, 0x00}, + {0x29, 0x01, 0x6c, 0x00}, {0x38, 0x01, 0x6c, 0x01}, + {0x03, 0x01, 0x6d, 0x00}, {0x06, 0x01, 0x6d, 0x00}, + {0x0a, 0x01, 0x6d, 0x00}, {0x0f, 0x01, 0x6d, 0x00}, + {0x18, 0x01, 0x6d, 0x00}, {0x1f, 0x01, 0x6d, 0x00}, + {0x29, 0x01, 0x6d, 0x00}, {0x38, 0x01, 0x6d, 0x01} + }, + { + {0x03, 0x01, 0x6e, 0x00}, {0x06, 0x01, 0x6e, 0x00}, + {0x0a, 0x01, 0x6e, 0x00}, {0x0f, 0x01, 0x6e, 0x00}, + {0x18, 0x01, 0x6e, 0x00}, {0x1f, 0x01, 0x6e, 0x00}, + {0x29, 0x01, 0x6e, 0x00}, {0x38, 0x01, 0x6e, 0x01}, + {0x03, 0x01, 0x70, 0x00}, {0x06, 0x01, 0x70, 0x00}, + {0x0a, 0x01, 0x70, 0x00}, {0x0f, 0x01, 0x70, 0x00}, + {0x18, 0x01, 0x70, 0x00}, {0x1f, 0x01, 0x70, 0x00}, + {0x29, 0x01, 0x70, 0x00}, {0x38, 0x01, 0x70, 0x01} + }, + /* 35 */ + { + {0x02, 0x01, 0x72, 0x00}, {0x09, 0x01, 0x72, 0x00}, + {0x17, 0x01, 0x72, 0x00}, {0x28, 0x01, 0x72, 0x01}, + {0x02, 0x01, 0x75, 0x00}, {0x09, 0x01, 0x75, 0x00}, + {0x17, 0x01, 0x75, 0x00}, {0x28, 0x01, 0x75, 0x01}, + {0x01, 0x01, 0x3a, 0x00}, {0x16, 0x01, 0x3a, 0x01}, + {0x01, 0x01, 0x42, 0x00}, {0x16, 0x01, 0x42, 0x01}, + {0x01, 0x01, 0x43, 0x00}, {0x16, 0x01, 0x43, 0x01}, + {0x01, 0x01, 0x44, 0x00}, {0x16, 0x01, 0x44, 0x01} + }, + { + {0x03, 0x01, 0x72, 0x00}, {0x06, 0x01, 0x72, 0x00}, + {0x0a, 0x01, 0x72, 0x00}, {0x0f, 0x01, 0x72, 0x00}, + {0x18, 0x01, 0x72, 0x00}, {0x1f, 0x01, 0x72, 0x00}, + {0x29, 0x01, 0x72, 0x00}, {0x38, 0x01, 0x72, 0x01}, + {0x03, 0x01, 0x75, 0x00}, {0x06, 0x01, 0x75, 0x00}, + {0x0a, 0x01, 0x75, 0x00}, {0x0f, 0x01, 0x75, 0x00}, + {0x18, 0x01, 0x75, 0x00}, {0x1f, 0x01, 0x75, 0x00}, + {0x29, 0x01, 0x75, 0x00}, {0x38, 0x01, 0x75, 0x01} + }, + { + {0x02, 0x01, 0x3a, 0x00}, {0x09, 0x01, 0x3a, 0x00}, + {0x17, 0x01, 0x3a, 0x00}, {0x28, 0x01, 0x3a, 0x01}, + {0x02, 0x01, 0x42, 0x00}, {0x09, 0x01, 0x42, 0x00}, + {0x17, 0x01, 0x42, 0x00}, {0x28, 0x01, 0x42, 0x01}, + {0x02, 0x01, 0x43, 0x00}, {0x09, 0x01, 0x43, 0x00}, + {0x17, 0x01, 0x43, 0x00}, {0x28, 0x01, 0x43, 0x01}, + {0x02, 0x01, 0x44, 0x00}, {0x09, 0x01, 0x44, 0x00}, + {0x17, 0x01, 0x44, 0x00}, {0x28, 0x01, 0x44, 0x01} + }, + { + {0x03, 0x01, 0x3a, 0x00}, {0x06, 0x01, 0x3a, 0x00}, + {0x0a, 0x01, 0x3a, 0x00}, {0x0f, 0x01, 0x3a, 0x00}, + {0x18, 0x01, 0x3a, 0x00}, {0x1f, 0x01, 0x3a, 0x00}, + {0x29, 0x01, 0x3a, 0x00}, {0x38, 0x01, 0x3a, 0x01}, + {0x03, 0x01, 0x42, 0x00}, {0x06, 0x01, 0x42, 0x00}, + {0x0a, 0x01, 0x42, 0x00}, {0x0f, 0x01, 0x42, 0x00}, + {0x18, 0x01, 0x42, 0x00}, {0x1f, 0x01, 0x42, 0x00}, + {0x29, 0x01, 0x42, 0x00}, {0x38, 0x01, 0x42, 0x01} + }, + { + {0x03, 0x01, 0x43, 0x00}, {0x06, 0x01, 0x43, 0x00}, + {0x0a, 0x01, 0x43, 0x00}, {0x0f, 0x01, 0x43, 0x00}, + {0x18, 0x01, 0x43, 0x00}, {0x1f, 0x01, 0x43, 0x00}, + {0x29, 0x01, 0x43, 0x00}, {0x38, 0x01, 0x43, 0x01}, + {0x03, 0x01, 0x44, 0x00}, {0x06, 0x01, 0x44, 0x00}, + {0x0a, 0x01, 0x44, 0x00}, {0x0f, 0x01, 0x44, 0x00}, + {0x18, 0x01, 0x44, 0x00}, {0x1f, 0x01, 0x44, 0x00}, + {0x29, 0x01, 0x44, 0x00}, {0x38, 0x01, 0x44, 0x01} + }, + /* 40 */ + { + {0x2c, 0x00, 0x00, 0x00}, {0x2d, 0x00, 0x00, 0x00}, + {0x2f, 0x00, 0x00, 0x00}, {0x30, 0x00, 0x00, 0x00}, + {0x33, 0x00, 0x00, 0x00}, {0x34, 0x00, 0x00, 0x00}, + {0x36, 0x00, 0x00, 0x00}, {0x37, 0x00, 0x00, 0x00}, + {0x3b, 0x00, 0x00, 0x00}, {0x3c, 0x00, 0x00, 0x00}, + {0x3e, 0x00, 0x00, 0x00}, {0x3f, 0x00, 0x00, 0x00}, + {0x42, 0x00, 0x00, 0x00}, {0x43, 0x00, 0x00, 0x00}, + {0x45, 0x00, 0x00, 0x00}, {0x48, 0x00, 0x00, 0x01} + }, + { + {0x00, 0x01, 0x45, 0x01}, {0x00, 0x01, 0x46, 0x01}, + {0x00, 0x01, 0x47, 0x01}, {0x00, 0x01, 0x48, 0x01}, + {0x00, 0x01, 0x49, 0x01}, {0x00, 0x01, 0x4a, 0x01}, + {0x00, 0x01, 0x4b, 0x01}, {0x00, 0x01, 0x4c, 0x01}, + {0x00, 0x01, 0x4d, 0x01}, {0x00, 0x01, 0x4e, 0x01}, + {0x00, 0x01, 0x4f, 0x01}, {0x00, 0x01, 0x50, 0x01}, + {0x00, 0x01, 0x51, 0x01}, {0x00, 0x01, 0x52, 0x01}, + {0x00, 0x01, 0x53, 0x01}, {0x00, 0x01, 0x54, 0x01} + }, + { + {0x01, 0x01, 0x45, 0x00}, {0x16, 0x01, 0x45, 0x01}, + {0x01, 0x01, 0x46, 0x00}, {0x16, 0x01, 0x46, 0x01}, + {0x01, 0x01, 0x47, 0x00}, {0x16, 0x01, 0x47, 0x01}, + {0x01, 0x01, 0x48, 0x00}, {0x16, 0x01, 0x48, 0x01}, + {0x01, 0x01, 0x49, 0x00}, {0x16, 0x01, 0x49, 0x01}, + {0x01, 0x01, 0x4a, 0x00}, {0x16, 0x01, 0x4a, 0x01}, + {0x01, 0x01, 0x4b, 0x00}, {0x16, 0x01, 0x4b, 0x01}, + {0x01, 0x01, 0x4c, 0x00}, {0x16, 0x01, 0x4c, 0x01} + }, + { + {0x02, 0x01, 0x45, 0x00}, {0x09, 0x01, 0x45, 0x00}, + {0x17, 0x01, 0x45, 0x00}, {0x28, 0x01, 0x45, 0x01}, + {0x02, 0x01, 0x46, 0x00}, {0x09, 0x01, 0x46, 0x00}, + {0x17, 0x01, 0x46, 0x00}, {0x28, 0x01, 0x46, 0x01}, + {0x02, 0x01, 0x47, 0x00}, {0x09, 0x01, 0x47, 0x00}, + {0x17, 0x01, 0x47, 0x00}, {0x28, 0x01, 0x47, 0x01}, + {0x02, 0x01, 0x48, 0x00}, {0x09, 0x01, 0x48, 0x00}, + {0x17, 0x01, 0x48, 0x00}, {0x28, 0x01, 0x48, 0x01} + }, + { + {0x03, 0x01, 0x45, 0x00}, {0x06, 0x01, 0x45, 0x00}, + {0x0a, 0x01, 0x45, 0x00}, {0x0f, 0x01, 0x45, 0x00}, + {0x18, 0x01, 0x45, 0x00}, {0x1f, 0x01, 0x45, 0x00}, + {0x29, 0x01, 0x45, 0x00}, {0x38, 0x01, 0x45, 0x01}, + {0x03, 0x01, 0x46, 0x00}, {0x06, 0x01, 0x46, 0x00}, + {0x0a, 0x01, 0x46, 0x00}, {0x0f, 0x01, 0x46, 0x00}, + {0x18, 0x01, 0x46, 0x00}, {0x1f, 0x01, 0x46, 0x00}, + {0x29, 0x01, 0x46, 0x00}, {0x38, 0x01, 0x46, 0x01} + }, + /* 45 */ + { + {0x03, 0x01, 0x47, 0x00}, {0x06, 0x01, 0x47, 0x00}, + {0x0a, 0x01, 0x47, 0x00}, {0x0f, 0x01, 0x47, 0x00}, + {0x18, 0x01, 0x47, 0x00}, {0x1f, 0x01, 0x47, 0x00}, + {0x29, 0x01, 0x47, 0x00}, {0x38, 0x01, 0x47, 0x01}, + {0x03, 0x01, 0x48, 0x00}, {0x06, 0x01, 0x48, 0x00}, + {0x0a, 0x01, 0x48, 0x00}, {0x0f, 0x01, 0x48, 0x00}, + {0x18, 0x01, 0x48, 0x00}, {0x1f, 0x01, 0x48, 0x00}, + {0x29, 0x01, 0x48, 0x00}, {0x38, 0x01, 0x48, 0x01} + }, + { + {0x02, 0x01, 0x49, 0x00}, {0x09, 0x01, 0x49, 0x00}, + {0x17, 0x01, 0x49, 0x00}, {0x28, 0x01, 0x49, 0x01}, + {0x02, 0x01, 0x4a, 0x00}, {0x09, 0x01, 0x4a, 0x00}, + {0x17, 0x01, 0x4a, 0x00}, {0x28, 0x01, 0x4a, 0x01}, + {0x02, 0x01, 0x4b, 0x00}, {0x09, 0x01, 0x4b, 0x00}, + {0x17, 0x01, 0x4b, 0x00}, {0x28, 0x01, 0x4b, 0x01}, + {0x02, 0x01, 0x4c, 0x00}, {0x09, 0x01, 0x4c, 0x00}, + {0x17, 0x01, 0x4c, 0x00}, {0x28, 0x01, 0x4c, 0x01} + }, + { + {0x03, 0x01, 0x49, 0x00}, {0x06, 0x01, 0x49, 0x00}, + {0x0a, 0x01, 0x49, 0x00}, {0x0f, 0x01, 0x49, 0x00}, + {0x18, 0x01, 0x49, 0x00}, {0x1f, 0x01, 0x49, 0x00}, + {0x29, 0x01, 0x49, 0x00}, {0x38, 0x01, 0x49, 0x01}, + {0x03, 0x01, 0x4a, 0x00}, {0x06, 0x01, 0x4a, 0x00}, + {0x0a, 0x01, 0x4a, 0x00}, {0x0f, 0x01, 0x4a, 0x00}, + {0x18, 0x01, 0x4a, 0x00}, {0x1f, 0x01, 0x4a, 0x00}, + {0x29, 0x01, 0x4a, 0x00}, {0x38, 0x01, 0x4a, 0x01} + }, + { + {0x03, 0x01, 0x4b, 0x00}, {0x06, 0x01, 0x4b, 0x00}, + {0x0a, 0x01, 0x4b, 0x00}, {0x0f, 0x01, 0x4b, 0x00}, + {0x18, 0x01, 0x4b, 0x00}, {0x1f, 0x01, 0x4b, 0x00}, + {0x29, 0x01, 0x4b, 0x00}, {0x38, 0x01, 0x4b, 0x01}, + {0x03, 0x01, 0x4c, 0x00}, {0x06, 0x01, 0x4c, 0x00}, + {0x0a, 0x01, 0x4c, 0x00}, {0x0f, 0x01, 0x4c, 0x00}, + {0x18, 0x01, 0x4c, 0x00}, {0x1f, 0x01, 0x4c, 0x00}, + {0x29, 0x01, 0x4c, 0x00}, {0x38, 0x01, 0x4c, 0x01} + }, + { + {0x01, 0x01, 0x4d, 0x00}, {0x16, 0x01, 0x4d, 0x01}, + {0x01, 0x01, 0x4e, 0x00}, {0x16, 0x01, 0x4e, 0x01}, + {0x01, 0x01, 0x4f, 0x00}, {0x16, 0x01, 0x4f, 0x01}, + {0x01, 0x01, 0x50, 0x00}, {0x16, 0x01, 0x50, 0x01}, + {0x01, 0x01, 0x51, 0x00}, {0x16, 0x01, 0x51, 0x01}, + {0x01, 0x01, 0x52, 0x00}, {0x16, 0x01, 0x52, 0x01}, + {0x01, 0x01, 0x53, 0x00}, {0x16, 0x01, 0x53, 0x01}, + {0x01, 0x01, 0x54, 0x00}, {0x16, 0x01, 0x54, 0x01} + }, + /* 50 */ + { + {0x02, 0x01, 0x4d, 0x00}, {0x09, 0x01, 0x4d, 0x00}, + {0x17, 0x01, 0x4d, 0x00}, {0x28, 0x01, 0x4d, 0x01}, + {0x02, 0x01, 0x4e, 0x00}, {0x09, 0x01, 0x4e, 0x00}, + {0x17, 0x01, 0x4e, 0x00}, {0x28, 0x01, 0x4e, 0x01}, + {0x02, 0x01, 0x4f, 0x00}, {0x09, 0x01, 0x4f, 0x00}, + {0x17, 0x01, 0x4f, 0x00}, {0x28, 0x01, 0x4f, 0x01}, + {0x02, 0x01, 0x50, 0x00}, {0x09, 0x01, 0x50, 0x00}, + {0x17, 0x01, 0x50, 0x00}, {0x28, 0x01, 0x50, 0x01} + }, + { + {0x03, 0x01, 0x4d, 0x00}, {0x06, 0x01, 0x4d, 0x00}, + {0x0a, 0x01, 0x4d, 0x00}, {0x0f, 0x01, 0x4d, 0x00}, + {0x18, 0x01, 0x4d, 0x00}, {0x1f, 0x01, 0x4d, 0x00}, + {0x29, 0x01, 0x4d, 0x00}, {0x38, 0x01, 0x4d, 0x01}, + {0x03, 0x01, 0x4e, 0x00}, {0x06, 0x01, 0x4e, 0x00}, + {0x0a, 0x01, 0x4e, 0x00}, {0x0f, 0x01, 0x4e, 0x00}, + {0x18, 0x01, 0x4e, 0x00}, {0x1f, 0x01, 0x4e, 0x00}, + {0x29, 0x01, 0x4e, 0x00}, {0x38, 0x01, 0x4e, 0x01} + }, + { + {0x03, 0x01, 0x4f, 0x00}, {0x06, 0x01, 0x4f, 0x00}, + {0x0a, 0x01, 0x4f, 0x00}, {0x0f, 0x01, 0x4f, 0x00}, + {0x18, 0x01, 0x4f, 0x00}, {0x1f, 0x01, 0x4f, 0x00}, + {0x29, 0x01, 0x4f, 0x00}, {0x38, 0x01, 0x4f, 0x01}, + {0x03, 0x01, 0x50, 0x00}, {0x06, 0x01, 0x50, 0x00}, + {0x0a, 0x01, 0x50, 0x00}, {0x0f, 0x01, 0x50, 0x00}, + {0x18, 0x01, 0x50, 0x00}, {0x1f, 0x01, 0x50, 0x00}, + {0x29, 0x01, 0x50, 0x00}, {0x38, 0x01, 0x50, 0x01} + }, + { + {0x02, 0x01, 0x51, 0x00}, {0x09, 0x01, 0x51, 0x00}, + {0x17, 0x01, 0x51, 0x00}, {0x28, 0x01, 0x51, 0x01}, + {0x02, 0x01, 0x52, 0x00}, {0x09, 0x01, 0x52, 0x00}, + {0x17, 0x01, 0x52, 0x00}, {0x28, 0x01, 0x52, 0x01}, + {0x02, 0x01, 0x53, 0x00}, {0x09, 0x01, 0x53, 0x00}, + {0x17, 0x01, 0x53, 0x00}, {0x28, 0x01, 0x53, 0x01}, + {0x02, 0x01, 0x54, 0x00}, {0x09, 0x01, 0x54, 0x00}, + {0x17, 0x01, 0x54, 0x00}, {0x28, 0x01, 0x54, 0x01} + }, + { + {0x03, 0x01, 0x51, 0x00}, {0x06, 0x01, 0x51, 0x00}, + {0x0a, 0x01, 0x51, 0x00}, {0x0f, 0x01, 0x51, 0x00}, + {0x18, 0x01, 0x51, 0x00}, {0x1f, 0x01, 0x51, 0x00}, + {0x29, 0x01, 0x51, 0x00}, {0x38, 0x01, 0x51, 0x01}, + {0x03, 0x01, 0x52, 0x00}, {0x06, 0x01, 0x52, 0x00}, + {0x0a, 0x01, 0x52, 0x00}, {0x0f, 0x01, 0x52, 0x00}, + {0x18, 0x01, 0x52, 0x00}, {0x1f, 0x01, 0x52, 0x00}, + {0x29, 0x01, 0x52, 0x00}, {0x38, 0x01, 0x52, 0x01} + }, + /* 55 */ + { + {0x03, 0x01, 0x53, 0x00}, {0x06, 0x01, 0x53, 0x00}, + {0x0a, 0x01, 0x53, 0x00}, {0x0f, 0x01, 0x53, 0x00}, + {0x18, 0x01, 0x53, 0x00}, {0x1f, 0x01, 0x53, 0x00}, + {0x29, 0x01, 0x53, 0x00}, {0x38, 0x01, 0x53, 0x01}, + {0x03, 0x01, 0x54, 0x00}, {0x06, 0x01, 0x54, 0x00}, + {0x0a, 0x01, 0x54, 0x00}, {0x0f, 0x01, 0x54, 0x00}, + {0x18, 0x01, 0x54, 0x00}, {0x1f, 0x01, 0x54, 0x00}, + {0x29, 0x01, 0x54, 0x00}, {0x38, 0x01, 0x54, 0x01} + }, + { + {0x00, 0x01, 0x55, 0x01}, {0x00, 0x01, 0x56, 0x01}, + {0x00, 0x01, 0x57, 0x01}, {0x00, 0x01, 0x59, 0x01}, + {0x00, 0x01, 0x6a, 0x01}, {0x00, 0x01, 0x6b, 0x01}, + {0x00, 0x01, 0x71, 0x01}, {0x00, 0x01, 0x76, 0x01}, + {0x00, 0x01, 0x77, 0x01}, {0x00, 0x01, 0x78, 0x01}, + {0x00, 0x01, 0x79, 0x01}, {0x00, 0x01, 0x7a, 0x01}, + {0x46, 0x00, 0x00, 0x00}, {0x47, 0x00, 0x00, 0x00}, + {0x49, 0x00, 0x00, 0x00}, {0x4a, 0x00, 0x00, 0x01} + }, + { + {0x01, 0x01, 0x55, 0x00}, {0x16, 0x01, 0x55, 0x01}, + {0x01, 0x01, 0x56, 0x00}, {0x16, 0x01, 0x56, 0x01}, + {0x01, 0x01, 0x57, 0x00}, {0x16, 0x01, 0x57, 0x01}, + {0x01, 0x01, 0x59, 0x00}, {0x16, 0x01, 0x59, 0x01}, + {0x01, 0x01, 0x6a, 0x00}, {0x16, 0x01, 0x6a, 0x01}, + {0x01, 0x01, 0x6b, 0x00}, {0x16, 0x01, 0x6b, 0x01}, + {0x01, 0x01, 0x71, 0x00}, {0x16, 0x01, 0x71, 0x01}, + {0x01, 0x01, 0x76, 0x00}, {0x16, 0x01, 0x76, 0x01} + }, + { + {0x02, 0x01, 0x55, 0x00}, {0x09, 0x01, 0x55, 0x00}, + {0x17, 0x01, 0x55, 0x00}, {0x28, 0x01, 0x55, 0x01}, + {0x02, 0x01, 0x56, 0x00}, {0x09, 0x01, 0x56, 0x00}, + {0x17, 0x01, 0x56, 0x00}, {0x28, 0x01, 0x56, 0x01}, + {0x02, 0x01, 0x57, 0x00}, {0x09, 0x01, 0x57, 0x00}, + {0x17, 0x01, 0x57, 0x00}, {0x28, 0x01, 0x57, 0x01}, + {0x02, 0x01, 0x59, 0x00}, {0x09, 0x01, 0x59, 0x00}, + {0x17, 0x01, 0x59, 0x00}, {0x28, 0x01, 0x59, 0x01} + }, + { + {0x03, 0x01, 0x55, 0x00}, {0x06, 0x01, 0x55, 0x00}, + {0x0a, 0x01, 0x55, 0x00}, {0x0f, 0x01, 0x55, 0x00}, + {0x18, 0x01, 0x55, 0x00}, {0x1f, 0x01, 0x55, 0x00}, + {0x29, 0x01, 0x55, 0x00}, {0x38, 0x01, 0x55, 0x01}, + {0x03, 0x01, 0x56, 0x00}, {0x06, 0x01, 0x56, 0x00}, + {0x0a, 0x01, 0x56, 0x00}, {0x0f, 0x01, 0x56, 0x00}, + {0x18, 0x01, 0x56, 0x00}, {0x1f, 0x01, 0x56, 0x00}, + {0x29, 0x01, 0x56, 0x00}, {0x38, 0x01, 0x56, 0x01} + }, + /* 60 */ + { + {0x03, 0x01, 0x57, 0x00}, {0x06, 0x01, 0x57, 0x00}, + {0x0a, 0x01, 0x57, 0x00}, {0x0f, 0x01, 0x57, 0x00}, + {0x18, 0x01, 0x57, 0x00}, {0x1f, 0x01, 0x57, 0x00}, + {0x29, 0x01, 0x57, 0x00}, {0x38, 0x01, 0x57, 0x01}, + {0x03, 0x01, 0x59, 0x00}, {0x06, 0x01, 0x59, 0x00}, + {0x0a, 0x01, 0x59, 0x00}, {0x0f, 0x01, 0x59, 0x00}, + {0x18, 0x01, 0x59, 0x00}, {0x1f, 0x01, 0x59, 0x00}, + {0x29, 0x01, 0x59, 0x00}, {0x38, 0x01, 0x59, 0x01} + }, + { + {0x02, 0x01, 0x6a, 0x00}, {0x09, 0x01, 0x6a, 0x00}, + {0x17, 0x01, 0x6a, 0x00}, {0x28, 0x01, 0x6a, 0x01}, + {0x02, 0x01, 0x6b, 0x00}, {0x09, 0x01, 0x6b, 0x00}, + {0x17, 0x01, 0x6b, 0x00}, {0x28, 0x01, 0x6b, 0x01}, + {0x02, 0x01, 0x71, 0x00}, {0x09, 0x01, 0x71, 0x00}, + {0x17, 0x01, 0x71, 0x00}, {0x28, 0x01, 0x71, 0x01}, + {0x02, 0x01, 0x76, 0x00}, {0x09, 0x01, 0x76, 0x00}, + {0x17, 0x01, 0x76, 0x00}, {0x28, 0x01, 0x76, 0x01} + }, + { + {0x03, 0x01, 0x6a, 0x00}, {0x06, 0x01, 0x6a, 0x00}, + {0x0a, 0x01, 0x6a, 0x00}, {0x0f, 0x01, 0x6a, 0x00}, + {0x18, 0x01, 0x6a, 0x00}, {0x1f, 0x01, 0x6a, 0x00}, + {0x29, 0x01, 0x6a, 0x00}, {0x38, 0x01, 0x6a, 0x01}, + {0x03, 0x01, 0x6b, 0x00}, {0x06, 0x01, 0x6b, 0x00}, + {0x0a, 0x01, 0x6b, 0x00}, {0x0f, 0x01, 0x6b, 0x00}, + {0x18, 0x01, 0x6b, 0x00}, {0x1f, 0x01, 0x6b, 0x00}, + {0x29, 0x01, 0x6b, 0x00}, {0x38, 0x01, 0x6b, 0x01} + }, + { + {0x03, 0x01, 0x71, 0x00}, {0x06, 0x01, 0x71, 0x00}, + {0x0a, 0x01, 0x71, 0x00}, {0x0f, 0x01, 0x71, 0x00}, + {0x18, 0x01, 0x71, 0x00}, {0x1f, 0x01, 0x71, 0x00}, + {0x29, 0x01, 0x71, 0x00}, {0x38, 0x01, 0x71, 0x01}, + {0x03, 0x01, 0x76, 0x00}, {0x06, 0x01, 0x76, 0x00}, + {0x0a, 0x01, 0x76, 0x00}, {0x0f, 0x01, 0x76, 0x00}, + {0x18, 0x01, 0x76, 0x00}, {0x1f, 0x01, 0x76, 0x00}, + {0x29, 0x01, 0x76, 0x00}, {0x38, 0x01, 0x76, 0x01} + }, + { + {0x01, 0x01, 0x77, 0x00}, {0x16, 0x01, 0x77, 0x01}, + {0x01, 0x01, 0x78, 0x00}, {0x16, 0x01, 0x78, 0x01}, + {0x01, 0x01, 0x79, 0x00}, {0x16, 0x01, 0x79, 0x01}, + {0x01, 0x01, 0x7a, 0x00}, {0x16, 0x01, 0x7a, 0x01}, + {0x00, 0x01, 0x26, 0x01}, {0x00, 0x01, 0x2a, 0x01}, + {0x00, 0x01, 0x2c, 0x01}, {0x00, 0x01, 0x3b, 0x01}, + {0x00, 0x01, 0x58, 0x01}, {0x00, 0x01, 0x5a, 0x01}, + {0x4b, 0x00, 0x00, 0x00}, {0x4e, 0x00, 0x00, 0x01} + }, + /* 65 */ + { + {0x02, 0x01, 0x77, 0x00}, {0x09, 0x01, 0x77, 0x00}, + {0x17, 0x01, 0x77, 0x00}, {0x28, 0x01, 0x77, 0x01}, + {0x02, 0x01, 0x78, 0x00}, {0x09, 0x01, 0x78, 0x00}, + {0x17, 0x01, 0x78, 0x00}, {0x28, 0x01, 0x78, 0x01}, + {0x02, 0x01, 0x79, 0x00}, {0x09, 0x01, 0x79, 0x00}, + {0x17, 0x01, 0x79, 0x00}, {0x28, 0x01, 0x79, 0x01}, + {0x02, 0x01, 0x7a, 0x00}, {0x09, 0x01, 0x7a, 0x00}, + {0x17, 0x01, 0x7a, 0x00}, {0x28, 0x01, 0x7a, 0x01} + }, + { + {0x03, 0x01, 0x77, 0x00}, {0x06, 0x01, 0x77, 0x00}, + {0x0a, 0x01, 0x77, 0x00}, {0x0f, 0x01, 0x77, 0x00}, + {0x18, 0x01, 0x77, 0x00}, {0x1f, 0x01, 0x77, 0x00}, + {0x29, 0x01, 0x77, 0x00}, {0x38, 0x01, 0x77, 0x01}, + {0x03, 0x01, 0x78, 0x00}, {0x06, 0x01, 0x78, 0x00}, + {0x0a, 0x01, 0x78, 0x00}, {0x0f, 0x01, 0x78, 0x00}, + {0x18, 0x01, 0x78, 0x00}, {0x1f, 0x01, 0x78, 0x00}, + {0x29, 0x01, 0x78, 0x00}, {0x38, 0x01, 0x78, 0x01} + }, + { + {0x03, 0x01, 0x79, 0x00}, {0x06, 0x01, 0x79, 0x00}, + {0x0a, 0x01, 0x79, 0x00}, {0x0f, 0x01, 0x79, 0x00}, + {0x18, 0x01, 0x79, 0x00}, {0x1f, 0x01, 0x79, 0x00}, + {0x29, 0x01, 0x79, 0x00}, {0x38, 0x01, 0x79, 0x01}, + {0x03, 0x01, 0x7a, 0x00}, {0x06, 0x01, 0x7a, 0x00}, + {0x0a, 0x01, 0x7a, 0x00}, {0x0f, 0x01, 0x7a, 0x00}, + {0x18, 0x01, 0x7a, 0x00}, {0x1f, 0x01, 0x7a, 0x00}, + {0x29, 0x01, 0x7a, 0x00}, {0x38, 0x01, 0x7a, 0x01} + }, + { + {0x01, 0x01, 0x26, 0x00}, {0x16, 0x01, 0x26, 0x01}, + {0x01, 0x01, 0x2a, 0x00}, {0x16, 0x01, 0x2a, 0x01}, + {0x01, 0x01, 0x2c, 0x00}, {0x16, 0x01, 0x2c, 0x01}, + {0x01, 0x01, 0x3b, 0x00}, {0x16, 0x01, 0x3b, 0x01}, + {0x01, 0x01, 0x58, 0x00}, {0x16, 0x01, 0x58, 0x01}, + {0x01, 0x01, 0x5a, 0x00}, {0x16, 0x01, 0x5a, 0x01}, + {0x4c, 0x00, 0x00, 0x00}, {0x4d, 0x00, 0x00, 0x00}, + {0x4f, 0x00, 0x00, 0x00}, {0x51, 0x00, 0x00, 0x01} + }, + { + {0x02, 0x01, 0x26, 0x00}, {0x09, 0x01, 0x26, 0x00}, + {0x17, 0x01, 0x26, 0x00}, {0x28, 0x01, 0x26, 0x01}, + {0x02, 0x01, 0x2a, 0x00}, {0x09, 0x01, 0x2a, 0x00}, + {0x17, 0x01, 0x2a, 0x00}, {0x28, 0x01, 0x2a, 0x01}, + {0x02, 0x01, 0x2c, 0x00}, {0x09, 0x01, 0x2c, 0x00}, + {0x17, 0x01, 0x2c, 0x00}, {0x28, 0x01, 0x2c, 0x01}, + {0x02, 0x01, 0x3b, 0x00}, {0x09, 0x01, 0x3b, 0x00}, + {0x17, 0x01, 0x3b, 0x00}, {0x28, 0x01, 0x3b, 0x01} + }, + /* 70 */ + { + {0x03, 0x01, 0x26, 0x00}, {0x06, 0x01, 0x26, 0x00}, + {0x0a, 0x01, 0x26, 0x00}, {0x0f, 0x01, 0x26, 0x00}, + {0x18, 0x01, 0x26, 0x00}, {0x1f, 0x01, 0x26, 0x00}, + {0x29, 0x01, 0x26, 0x00}, {0x38, 0x01, 0x26, 0x01}, + {0x03, 0x01, 0x2a, 0x00}, {0x06, 0x01, 0x2a, 0x00}, + {0x0a, 0x01, 0x2a, 0x00}, {0x0f, 0x01, 0x2a, 0x00}, + {0x18, 0x01, 0x2a, 0x00}, {0x1f, 0x01, 0x2a, 0x00}, + {0x29, 0x01, 0x2a, 0x00}, {0x38, 0x01, 0x2a, 0x01} + }, + { + {0x03, 0x01, 0x2c, 0x00}, {0x06, 0x01, 0x2c, 0x00}, + {0x0a, 0x01, 0x2c, 0x00}, {0x0f, 0x01, 0x2c, 0x00}, + {0x18, 0x01, 0x2c, 0x00}, {0x1f, 0x01, 0x2c, 0x00}, + {0x29, 0x01, 0x2c, 0x00}, {0x38, 0x01, 0x2c, 0x01}, + {0x03, 0x01, 0x3b, 0x00}, {0x06, 0x01, 0x3b, 0x00}, + {0x0a, 0x01, 0x3b, 0x00}, {0x0f, 0x01, 0x3b, 0x00}, + {0x18, 0x01, 0x3b, 0x00}, {0x1f, 0x01, 0x3b, 0x00}, + {0x29, 0x01, 0x3b, 0x00}, {0x38, 0x01, 0x3b, 0x01} + }, + { + {0x02, 0x01, 0x58, 0x00}, {0x09, 0x01, 0x58, 0x00}, + {0x17, 0x01, 0x58, 0x00}, {0x28, 0x01, 0x58, 0x01}, + {0x02, 0x01, 0x5a, 0x00}, {0x09, 0x01, 0x5a, 0x00}, + {0x17, 0x01, 0x5a, 0x00}, {0x28, 0x01, 0x5a, 0x01}, + {0x00, 0x01, 0x21, 0x01}, {0x00, 0x01, 0x22, 0x01}, + {0x00, 0x01, 0x28, 0x01}, {0x00, 0x01, 0x29, 0x01}, + {0x00, 0x01, 0x3f, 0x01}, {0x50, 0x00, 0x00, 0x00}, + {0x52, 0x00, 0x00, 0x00}, {0x54, 0x00, 0x00, 0x01} + }, + { + {0x03, 0x01, 0x58, 0x00}, {0x06, 0x01, 0x58, 0x00}, + {0x0a, 0x01, 0x58, 0x00}, {0x0f, 0x01, 0x58, 0x00}, + {0x18, 0x01, 0x58, 0x00}, {0x1f, 0x01, 0x58, 0x00}, + {0x29, 0x01, 0x58, 0x00}, {0x38, 0x01, 0x58, 0x01}, + {0x03, 0x01, 0x5a, 0x00}, {0x06, 0x01, 0x5a, 0x00}, + {0x0a, 0x01, 0x5a, 0x00}, {0x0f, 0x01, 0x5a, 0x00}, + {0x18, 0x01, 0x5a, 0x00}, {0x1f, 0x01, 0x5a, 0x00}, + {0x29, 0x01, 0x5a, 0x00}, {0x38, 0x01, 0x5a, 0x01} + }, + { + {0x01, 0x01, 0x21, 0x00}, {0x16, 0x01, 0x21, 0x01}, + {0x01, 0x01, 0x22, 0x00}, {0x16, 0x01, 0x22, 0x01}, + {0x01, 0x01, 0x28, 0x00}, {0x16, 0x01, 0x28, 0x01}, + {0x01, 0x01, 0x29, 0x00}, {0x16, 0x01, 0x29, 0x01}, + {0x01, 0x01, 0x3f, 0x00}, {0x16, 0x01, 0x3f, 0x01}, + {0x00, 0x01, 0x27, 0x01}, {0x00, 0x01, 0x2b, 0x01}, + {0x00, 0x01, 0x7c, 0x01}, {0x53, 0x00, 0x00, 0x00}, + {0x55, 0x00, 0x00, 0x00}, {0x58, 0x00, 0x00, 0x01} + }, + /* 75 */ + { + {0x02, 0x01, 0x21, 0x00}, {0x09, 0x01, 0x21, 0x00}, + {0x17, 0x01, 0x21, 0x00}, {0x28, 0x01, 0x21, 0x01}, + {0x02, 0x01, 0x22, 0x00}, {0x09, 0x01, 0x22, 0x00}, + {0x17, 0x01, 0x22, 0x00}, {0x28, 0x01, 0x22, 0x01}, + {0x02, 0x01, 0x28, 0x00}, {0x09, 0x01, 0x28, 0x00}, + {0x17, 0x01, 0x28, 0x00}, {0x28, 0x01, 0x28, 0x01}, + {0x02, 0x01, 0x29, 0x00}, {0x09, 0x01, 0x29, 0x00}, + {0x17, 0x01, 0x29, 0x00}, {0x28, 0x01, 0x29, 0x01} + }, + { + {0x03, 0x01, 0x21, 0x00}, {0x06, 0x01, 0x21, 0x00}, + {0x0a, 0x01, 0x21, 0x00}, {0x0f, 0x01, 0x21, 0x00}, + {0x18, 0x01, 0x21, 0x00}, {0x1f, 0x01, 0x21, 0x00}, + {0x29, 0x01, 0x21, 0x00}, {0x38, 0x01, 0x21, 0x01}, + {0x03, 0x01, 0x22, 0x00}, {0x06, 0x01, 0x22, 0x00}, + {0x0a, 0x01, 0x22, 0x00}, {0x0f, 0x01, 0x22, 0x00}, + {0x18, 0x01, 0x22, 0x00}, {0x1f, 0x01, 0x22, 0x00}, + {0x29, 0x01, 0x22, 0x00}, {0x38, 0x01, 0x22, 0x01} + }, + { + {0x03, 0x01, 0x28, 0x00}, {0x06, 0x01, 0x28, 0x00}, + {0x0a, 0x01, 0x28, 0x00}, {0x0f, 0x01, 0x28, 0x00}, + {0x18, 0x01, 0x28, 0x00}, {0x1f, 0x01, 0x28, 0x00}, + {0x29, 0x01, 0x28, 0x00}, {0x38, 0x01, 0x28, 0x01}, + {0x03, 0x01, 0x29, 0x00}, {0x06, 0x01, 0x29, 0x00}, + {0x0a, 0x01, 0x29, 0x00}, {0x0f, 0x01, 0x29, 0x00}, + {0x18, 0x01, 0x29, 0x00}, {0x1f, 0x01, 0x29, 0x00}, + {0x29, 0x01, 0x29, 0x00}, {0x38, 0x01, 0x29, 0x01} + }, + { + {0x02, 0x01, 0x3f, 0x00}, {0x09, 0x01, 0x3f, 0x00}, + {0x17, 0x01, 0x3f, 0x00}, {0x28, 0x01, 0x3f, 0x01}, + {0x01, 0x01, 0x27, 0x00}, {0x16, 0x01, 0x27, 0x01}, + {0x01, 0x01, 0x2b, 0x00}, {0x16, 0x01, 0x2b, 0x01}, + {0x01, 0x01, 0x7c, 0x00}, {0x16, 0x01, 0x7c, 0x01}, + {0x00, 0x01, 0x23, 0x01}, {0x00, 0x01, 0x3e, 0x01}, + {0x56, 0x00, 0x00, 0x00}, {0x57, 0x00, 0x00, 0x00}, + {0x59, 0x00, 0x00, 0x00}, {0x5a, 0x00, 0x00, 0x01} + }, + { + {0x03, 0x01, 0x3f, 0x00}, {0x06, 0x01, 0x3f, 0x00}, + {0x0a, 0x01, 0x3f, 0x00}, {0x0f, 0x01, 0x3f, 0x00}, + {0x18, 0x01, 0x3f, 0x00}, {0x1f, 0x01, 0x3f, 0x00}, + {0x29, 0x01, 0x3f, 0x00}, {0x38, 0x01, 0x3f, 0x01}, + {0x02, 0x01, 0x27, 0x00}, {0x09, 0x01, 0x27, 0x00}, + {0x17, 0x01, 0x27, 0x00}, {0x28, 0x01, 0x27, 0x01}, + {0x02, 0x01, 0x2b, 0x00}, {0x09, 0x01, 0x2b, 0x00}, + {0x17, 0x01, 0x2b, 0x00}, {0x28, 0x01, 0x2b, 0x01} + }, + /* 80 */ + { + {0x03, 0x01, 0x27, 0x00}, {0x06, 0x01, 0x27, 0x00}, + {0x0a, 0x01, 0x27, 0x00}, {0x0f, 0x01, 0x27, 0x00}, + {0x18, 0x01, 0x27, 0x00}, {0x1f, 0x01, 0x27, 0x00}, + {0x29, 0x01, 0x27, 0x00}, {0x38, 0x01, 0x27, 0x01}, + {0x03, 0x01, 0x2b, 0x00}, {0x06, 0x01, 0x2b, 0x00}, + {0x0a, 0x01, 0x2b, 0x00}, {0x0f, 0x01, 0x2b, 0x00}, + {0x18, 0x01, 0x2b, 0x00}, {0x1f, 0x01, 0x2b, 0x00}, + {0x29, 0x01, 0x2b, 0x00}, {0x38, 0x01, 0x2b, 0x01} + }, + { + {0x02, 0x01, 0x7c, 0x00}, {0x09, 0x01, 0x7c, 0x00}, + {0x17, 0x01, 0x7c, 0x00}, {0x28, 0x01, 0x7c, 0x01}, + {0x01, 0x01, 0x23, 0x00}, {0x16, 0x01, 0x23, 0x01}, + {0x01, 0x01, 0x3e, 0x00}, {0x16, 0x01, 0x3e, 0x01}, + {0x00, 0x01, 0x00, 0x01}, {0x00, 0x01, 0x24, 0x01}, + {0x00, 0x01, 0x40, 0x01}, {0x00, 0x01, 0x5b, 0x01}, + {0x00, 0x01, 0x5d, 0x01}, {0x00, 0x01, 0x7e, 0x01}, + {0x5b, 0x00, 0x00, 0x00}, {0x5c, 0x00, 0x00, 0x01} + }, + { + {0x03, 0x01, 0x7c, 0x00}, {0x06, 0x01, 0x7c, 0x00}, + {0x0a, 0x01, 0x7c, 0x00}, {0x0f, 0x01, 0x7c, 0x00}, + {0x18, 0x01, 0x7c, 0x00}, {0x1f, 0x01, 0x7c, 0x00}, + {0x29, 0x01, 0x7c, 0x00}, {0x38, 0x01, 0x7c, 0x01}, + {0x02, 0x01, 0x23, 0x00}, {0x09, 0x01, 0x23, 0x00}, + {0x17, 0x01, 0x23, 0x00}, {0x28, 0x01, 0x23, 0x01}, + {0x02, 0x01, 0x3e, 0x00}, {0x09, 0x01, 0x3e, 0x00}, + {0x17, 0x01, 0x3e, 0x00}, {0x28, 0x01, 0x3e, 0x01} + }, + { + {0x03, 0x01, 0x23, 0x00}, {0x06, 0x01, 0x23, 0x00}, + {0x0a, 0x01, 0x23, 0x00}, {0x0f, 0x01, 0x23, 0x00}, + {0x18, 0x01, 0x23, 0x00}, {0x1f, 0x01, 0x23, 0x00}, + {0x29, 0x01, 0x23, 0x00}, {0x38, 0x01, 0x23, 0x01}, + {0x03, 0x01, 0x3e, 0x00}, {0x06, 0x01, 0x3e, 0x00}, + {0x0a, 0x01, 0x3e, 0x00}, {0x0f, 0x01, 0x3e, 0x00}, + {0x18, 0x01, 0x3e, 0x00}, {0x1f, 0x01, 0x3e, 0x00}, + {0x29, 0x01, 0x3e, 0x00}, {0x38, 0x01, 0x3e, 0x01} + }, + { + {0x01, 0x01, 0x00, 0x00}, {0x16, 0x01, 0x00, 0x01}, + {0x01, 0x01, 0x24, 0x00}, {0x16, 0x01, 0x24, 0x01}, + {0x01, 0x01, 0x40, 0x00}, {0x16, 0x01, 0x40, 0x01}, + {0x01, 0x01, 0x5b, 0x00}, {0x16, 0x01, 0x5b, 0x01}, + {0x01, 0x01, 0x5d, 0x00}, {0x16, 0x01, 0x5d, 0x01}, + {0x01, 0x01, 0x7e, 0x00}, {0x16, 0x01, 0x7e, 0x01}, + {0x00, 0x01, 0x5e, 0x01}, {0x00, 0x01, 0x7d, 0x01}, + {0x5d, 0x00, 0x00, 0x00}, {0x5e, 0x00, 0x00, 0x01} + }, + /* 85 */ + { + {0x02, 0x01, 0x00, 0x00}, {0x09, 0x01, 0x00, 0x00}, + {0x17, 0x01, 0x00, 0x00}, {0x28, 0x01, 0x00, 0x01}, + {0x02, 0x01, 0x24, 0x00}, {0x09, 0x01, 0x24, 0x00}, + {0x17, 0x01, 0x24, 0x00}, {0x28, 0x01, 0x24, 0x01}, + {0x02, 0x01, 0x40, 0x00}, {0x09, 0x01, 0x40, 0x00}, + {0x17, 0x01, 0x40, 0x00}, {0x28, 0x01, 0x40, 0x01}, + {0x02, 0x01, 0x5b, 0x00}, {0x09, 0x01, 0x5b, 0x00}, + {0x17, 0x01, 0x5b, 0x00}, {0x28, 0x01, 0x5b, 0x01} + }, + { + {0x03, 0x01, 0x00, 0x00}, {0x06, 0x01, 0x00, 0x00}, + {0x0a, 0x01, 0x00, 0x00}, {0x0f, 0x01, 0x00, 0x00}, + {0x18, 0x01, 0x00, 0x00}, {0x1f, 0x01, 0x00, 0x00}, + {0x29, 0x01, 0x00, 0x00}, {0x38, 0x01, 0x00, 0x01}, + {0x03, 0x01, 0x24, 0x00}, {0x06, 0x01, 0x24, 0x00}, + {0x0a, 0x01, 0x24, 0x00}, {0x0f, 0x01, 0x24, 0x00}, + {0x18, 0x01, 0x24, 0x00}, {0x1f, 0x01, 0x24, 0x00}, + {0x29, 0x01, 0x24, 0x00}, {0x38, 0x01, 0x24, 0x01} + }, + { + {0x03, 0x01, 0x40, 0x00}, {0x06, 0x01, 0x40, 0x00}, + {0x0a, 0x01, 0x40, 0x00}, {0x0f, 0x01, 0x40, 0x00}, + {0x18, 0x01, 0x40, 0x00}, {0x1f, 0x01, 0x40, 0x00}, + {0x29, 0x01, 0x40, 0x00}, {0x38, 0x01, 0x40, 0x01}, + {0x03, 0x01, 0x5b, 0x00}, {0x06, 0x01, 0x5b, 0x00}, + {0x0a, 0x01, 0x5b, 0x00}, {0x0f, 0x01, 0x5b, 0x00}, + {0x18, 0x01, 0x5b, 0x00}, {0x1f, 0x01, 0x5b, 0x00}, + {0x29, 0x01, 0x5b, 0x00}, {0x38, 0x01, 0x5b, 0x01} + }, + { + {0x02, 0x01, 0x5d, 0x00}, {0x09, 0x01, 0x5d, 0x00}, + {0x17, 0x01, 0x5d, 0x00}, {0x28, 0x01, 0x5d, 0x01}, + {0x02, 0x01, 0x7e, 0x00}, {0x09, 0x01, 0x7e, 0x00}, + {0x17, 0x01, 0x7e, 0x00}, {0x28, 0x01, 0x7e, 0x01}, + {0x01, 0x01, 0x5e, 0x00}, {0x16, 0x01, 0x5e, 0x01}, + {0x01, 0x01, 0x7d, 0x00}, {0x16, 0x01, 0x7d, 0x01}, + {0x00, 0x01, 0x3c, 0x01}, {0x00, 0x01, 0x60, 0x01}, + {0x00, 0x01, 0x7b, 0x01}, {0x5f, 0x00, 0x00, 0x01} + }, + { + {0x03, 0x01, 0x5d, 0x00}, {0x06, 0x01, 0x5d, 0x00}, + {0x0a, 0x01, 0x5d, 0x00}, {0x0f, 0x01, 0x5d, 0x00}, + {0x18, 0x01, 0x5d, 0x00}, {0x1f, 0x01, 0x5d, 0x00}, + {0x29, 0x01, 0x5d, 0x00}, {0x38, 0x01, 0x5d, 0x01}, + {0x03, 0x01, 0x7e, 0x00}, {0x06, 0x01, 0x7e, 0x00}, + {0x0a, 0x01, 0x7e, 0x00}, {0x0f, 0x01, 0x7e, 0x00}, + {0x18, 0x01, 0x7e, 0x00}, {0x1f, 0x01, 0x7e, 0x00}, + {0x29, 0x01, 0x7e, 0x00}, {0x38, 0x01, 0x7e, 0x01} + }, + /* 90 */ + { + {0x02, 0x01, 0x5e, 0x00}, {0x09, 0x01, 0x5e, 0x00}, + {0x17, 0x01, 0x5e, 0x00}, {0x28, 0x01, 0x5e, 0x01}, + {0x02, 0x01, 0x7d, 0x00}, {0x09, 0x01, 0x7d, 0x00}, + {0x17, 0x01, 0x7d, 0x00}, {0x28, 0x01, 0x7d, 0x01}, + {0x01, 0x01, 0x3c, 0x00}, {0x16, 0x01, 0x3c, 0x01}, + {0x01, 0x01, 0x60, 0x00}, {0x16, 0x01, 0x60, 0x01}, + {0x01, 0x01, 0x7b, 0x00}, {0x16, 0x01, 0x7b, 0x01}, + {0x60, 0x00, 0x00, 0x00}, {0x6e, 0x00, 0x00, 0x01} + }, + { + {0x03, 0x01, 0x5e, 0x00}, {0x06, 0x01, 0x5e, 0x00}, + {0x0a, 0x01, 0x5e, 0x00}, {0x0f, 0x01, 0x5e, 0x00}, + {0x18, 0x01, 0x5e, 0x00}, {0x1f, 0x01, 0x5e, 0x00}, + {0x29, 0x01, 0x5e, 0x00}, {0x38, 0x01, 0x5e, 0x01}, + {0x03, 0x01, 0x7d, 0x00}, {0x06, 0x01, 0x7d, 0x00}, + {0x0a, 0x01, 0x7d, 0x00}, {0x0f, 0x01, 0x7d, 0x00}, + {0x18, 0x01, 0x7d, 0x00}, {0x1f, 0x01, 0x7d, 0x00}, + {0x29, 0x01, 0x7d, 0x00}, {0x38, 0x01, 0x7d, 0x01} + }, + { + {0x02, 0x01, 0x3c, 0x00}, {0x09, 0x01, 0x3c, 0x00}, + {0x17, 0x01, 0x3c, 0x00}, {0x28, 0x01, 0x3c, 0x01}, + {0x02, 0x01, 0x60, 0x00}, {0x09, 0x01, 0x60, 0x00}, + {0x17, 0x01, 0x60, 0x00}, {0x28, 0x01, 0x60, 0x01}, + {0x02, 0x01, 0x7b, 0x00}, {0x09, 0x01, 0x7b, 0x00}, + {0x17, 0x01, 0x7b, 0x00}, {0x28, 0x01, 0x7b, 0x01}, + {0x61, 0x00, 0x00, 0x00}, {0x65, 0x00, 0x00, 0x00}, + {0x6f, 0x00, 0x00, 0x00}, {0x85, 0x00, 0x00, 0x01} + }, + { + {0x03, 0x01, 0x3c, 0x00}, {0x06, 0x01, 0x3c, 0x00}, + {0x0a, 0x01, 0x3c, 0x00}, {0x0f, 0x01, 0x3c, 0x00}, + {0x18, 0x01, 0x3c, 0x00}, {0x1f, 0x01, 0x3c, 0x00}, + {0x29, 0x01, 0x3c, 0x00}, {0x38, 0x01, 0x3c, 0x01}, + {0x03, 0x01, 0x60, 0x00}, {0x06, 0x01, 0x60, 0x00}, + {0x0a, 0x01, 0x60, 0x00}, {0x0f, 0x01, 0x60, 0x00}, + {0x18, 0x01, 0x60, 0x00}, {0x1f, 0x01, 0x60, 0x00}, + {0x29, 0x01, 0x60, 0x00}, {0x38, 0x01, 0x60, 0x01} + }, + { + {0x03, 0x01, 0x7b, 0x00}, {0x06, 0x01, 0x7b, 0x00}, + {0x0a, 0x01, 0x7b, 0x00}, {0x0f, 0x01, 0x7b, 0x00}, + {0x18, 0x01, 0x7b, 0x00}, {0x1f, 0x01, 0x7b, 0x00}, + {0x29, 0x01, 0x7b, 0x00}, {0x38, 0x01, 0x7b, 0x01}, + {0x62, 0x00, 0x00, 0x00}, {0x63, 0x00, 0x00, 0x00}, + {0x66, 0x00, 0x00, 0x00}, {0x69, 0x00, 0x00, 0x00}, + {0x70, 0x00, 0x00, 0x00}, {0x77, 0x00, 0x00, 0x00}, + {0x86, 0x00, 0x00, 0x00}, {0x99, 0x00, 0x00, 0x01} + }, + /* 95 */ + { + {0x00, 0x01, 0x5c, 0x01}, {0x00, 0x01, 0xc3, 0x01}, + {0x00, 0x01, 0xd0, 0x01}, {0x64, 0x00, 0x00, 0x00}, + {0x67, 0x00, 0x00, 0x00}, {0x68, 0x00, 0x00, 0x00}, + {0x6a, 0x00, 0x00, 0x00}, {0x6b, 0x00, 0x00, 0x00}, + {0x71, 0x00, 0x00, 0x00}, {0x74, 0x00, 0x00, 0x00}, + {0x78, 0x00, 0x00, 0x00}, {0x7e, 0x00, 0x00, 0x00}, + {0x87, 0x00, 0x00, 0x00}, {0x8e, 0x00, 0x00, 0x00}, + {0x9a, 0x00, 0x00, 0x00}, {0xa9, 0x00, 0x00, 0x01} + }, + { + {0x01, 0x01, 0x5c, 0x00}, {0x16, 0x01, 0x5c, 0x01}, + {0x01, 0x01, 0xc3, 0x00}, {0x16, 0x01, 0xc3, 0x01}, + {0x01, 0x01, 0xd0, 0x00}, {0x16, 0x01, 0xd0, 0x01}, + {0x00, 0x01, 0x80, 0x01}, {0x00, 0x01, 0x82, 0x01}, + {0x00, 0x01, 0x83, 0x01}, {0x00, 0x01, 0xa2, 0x01}, + {0x00, 0x01, 0xb8, 0x01}, {0x00, 0x01, 0xc2, 0x01}, + {0x00, 0x01, 0xe0, 0x01}, {0x00, 0x01, 0xe2, 0x01}, + {0x6c, 0x00, 0x00, 0x00}, {0x6d, 0x00, 0x00, 0x00} + }, + { + {0x02, 0x01, 0x5c, 0x00}, {0x09, 0x01, 0x5c, 0x00}, + {0x17, 0x01, 0x5c, 0x00}, {0x28, 0x01, 0x5c, 0x01}, + {0x02, 0x01, 0xc3, 0x00}, {0x09, 0x01, 0xc3, 0x00}, + {0x17, 0x01, 0xc3, 0x00}, {0x28, 0x01, 0xc3, 0x01}, + {0x02, 0x01, 0xd0, 0x00}, {0x09, 0x01, 0xd0, 0x00}, + {0x17, 0x01, 0xd0, 0x00}, {0x28, 0x01, 0xd0, 0x01}, + {0x01, 0x01, 0x80, 0x00}, {0x16, 0x01, 0x80, 0x01}, + {0x01, 0x01, 0x82, 0x00}, {0x16, 0x01, 0x82, 0x01} + }, + { + {0x03, 0x01, 0x5c, 0x00}, {0x06, 0x01, 0x5c, 0x00}, + {0x0a, 0x01, 0x5c, 0x00}, {0x0f, 0x01, 0x5c, 0x00}, + {0x18, 0x01, 0x5c, 0x00}, {0x1f, 0x01, 0x5c, 0x00}, + {0x29, 0x01, 0x5c, 0x00}, {0x38, 0x01, 0x5c, 0x01}, + {0x03, 0x01, 0xc3, 0x00}, {0x06, 0x01, 0xc3, 0x00}, + {0x0a, 0x01, 0xc3, 0x00}, {0x0f, 0x01, 0xc3, 0x00}, + {0x18, 0x01, 0xc3, 0x00}, {0x1f, 0x01, 0xc3, 0x00}, + {0x29, 0x01, 0xc3, 0x00}, {0x38, 0x01, 0xc3, 0x01} + }, + { + {0x03, 0x01, 0xd0, 0x00}, {0x06, 0x01, 0xd0, 0x00}, + {0x0a, 0x01, 0xd0, 0x00}, {0x0f, 0x01, 0xd0, 0x00}, + {0x18, 0x01, 0xd0, 0x00}, {0x1f, 0x01, 0xd0, 0x00}, + {0x29, 0x01, 0xd0, 0x00}, {0x38, 0x01, 0xd0, 0x01}, + {0x02, 0x01, 0x80, 0x00}, {0x09, 0x01, 0x80, 0x00}, + {0x17, 0x01, 0x80, 0x00}, {0x28, 0x01, 0x80, 0x01}, + {0x02, 0x01, 0x82, 0x00}, {0x09, 0x01, 0x82, 0x00}, + {0x17, 0x01, 0x82, 0x00}, {0x28, 0x01, 0x82, 0x01} + }, + /* 100 */ + { + {0x03, 0x01, 0x80, 0x00}, {0x06, 0x01, 0x80, 0x00}, + {0x0a, 0x01, 0x80, 0x00}, {0x0f, 0x01, 0x80, 0x00}, + {0x18, 0x01, 0x80, 0x00}, {0x1f, 0x01, 0x80, 0x00}, + {0x29, 0x01, 0x80, 0x00}, {0x38, 0x01, 0x80, 0x01}, + {0x03, 0x01, 0x82, 0x00}, {0x06, 0x01, 0x82, 0x00}, + {0x0a, 0x01, 0x82, 0x00}, {0x0f, 0x01, 0x82, 0x00}, + {0x18, 0x01, 0x82, 0x00}, {0x1f, 0x01, 0x82, 0x00}, + {0x29, 0x01, 0x82, 0x00}, {0x38, 0x01, 0x82, 0x01} + }, + { + {0x01, 0x01, 0x83, 0x00}, {0x16, 0x01, 0x83, 0x01}, + {0x01, 0x01, 0xa2, 0x00}, {0x16, 0x01, 0xa2, 0x01}, + {0x01, 0x01, 0xb8, 0x00}, {0x16, 0x01, 0xb8, 0x01}, + {0x01, 0x01, 0xc2, 0x00}, {0x16, 0x01, 0xc2, 0x01}, + {0x01, 0x01, 0xe0, 0x00}, {0x16, 0x01, 0xe0, 0x01}, + {0x01, 0x01, 0xe2, 0x00}, {0x16, 0x01, 0xe2, 0x01}, + {0x00, 0x01, 0x99, 0x01}, {0x00, 0x01, 0xa1, 0x01}, + {0x00, 0x01, 0xa7, 0x01}, {0x00, 0x01, 0xac, 0x01} + }, + { + {0x02, 0x01, 0x83, 0x00}, {0x09, 0x01, 0x83, 0x00}, + {0x17, 0x01, 0x83, 0x00}, {0x28, 0x01, 0x83, 0x01}, + {0x02, 0x01, 0xa2, 0x00}, {0x09, 0x01, 0xa2, 0x00}, + {0x17, 0x01, 0xa2, 0x00}, {0x28, 0x01, 0xa2, 0x01}, + {0x02, 0x01, 0xb8, 0x00}, {0x09, 0x01, 0xb8, 0x00}, + {0x17, 0x01, 0xb8, 0x00}, {0x28, 0x01, 0xb8, 0x01}, + {0x02, 0x01, 0xc2, 0x00}, {0x09, 0x01, 0xc2, 0x00}, + {0x17, 0x01, 0xc2, 0x00}, {0x28, 0x01, 0xc2, 0x01} + }, + { + {0x03, 0x01, 0x83, 0x00}, {0x06, 0x01, 0x83, 0x00}, + {0x0a, 0x01, 0x83, 0x00}, {0x0f, 0x01, 0x83, 0x00}, + {0x18, 0x01, 0x83, 0x00}, {0x1f, 0x01, 0x83, 0x00}, + {0x29, 0x01, 0x83, 0x00}, {0x38, 0x01, 0x83, 0x01}, + {0x03, 0x01, 0xa2, 0x00}, {0x06, 0x01, 0xa2, 0x00}, + {0x0a, 0x01, 0xa2, 0x00}, {0x0f, 0x01, 0xa2, 0x00}, + {0x18, 0x01, 0xa2, 0x00}, {0x1f, 0x01, 0xa2, 0x00}, + {0x29, 0x01, 0xa2, 0x00}, {0x38, 0x01, 0xa2, 0x01} + }, + { + {0x03, 0x01, 0xb8, 0x00}, {0x06, 0x01, 0xb8, 0x00}, + {0x0a, 0x01, 0xb8, 0x00}, {0x0f, 0x01, 0xb8, 0x00}, + {0x18, 0x01, 0xb8, 0x00}, {0x1f, 0x01, 0xb8, 0x00}, + {0x29, 0x01, 0xb8, 0x00}, {0x38, 0x01, 0xb8, 0x01}, + {0x03, 0x01, 0xc2, 0x00}, {0x06, 0x01, 0xc2, 0x00}, + {0x0a, 0x01, 0xc2, 0x00}, {0x0f, 0x01, 0xc2, 0x00}, + {0x18, 0x01, 0xc2, 0x00}, {0x1f, 0x01, 0xc2, 0x00}, + {0x29, 0x01, 0xc2, 0x00}, {0x38, 0x01, 0xc2, 0x01} + }, + /* 105 */ + { + {0x02, 0x01, 0xe0, 0x00}, {0x09, 0x01, 0xe0, 0x00}, + {0x17, 0x01, 0xe0, 0x00}, {0x28, 0x01, 0xe0, 0x01}, + {0x02, 0x01, 0xe2, 0x00}, {0x09, 0x01, 0xe2, 0x00}, + {0x17, 0x01, 0xe2, 0x00}, {0x28, 0x01, 0xe2, 0x01}, + {0x01, 0x01, 0x99, 0x00}, {0x16, 0x01, 0x99, 0x01}, + {0x01, 0x01, 0xa1, 0x00}, {0x16, 0x01, 0xa1, 0x01}, + {0x01, 0x01, 0xa7, 0x00}, {0x16, 0x01, 0xa7, 0x01}, + {0x01, 0x01, 0xac, 0x00}, {0x16, 0x01, 0xac, 0x01} + }, + { + {0x03, 0x01, 0xe0, 0x00}, {0x06, 0x01, 0xe0, 0x00}, + {0x0a, 0x01, 0xe0, 0x00}, {0x0f, 0x01, 0xe0, 0x00}, + {0x18, 0x01, 0xe0, 0x00}, {0x1f, 0x01, 0xe0, 0x00}, + {0x29, 0x01, 0xe0, 0x00}, {0x38, 0x01, 0xe0, 0x01}, + {0x03, 0x01, 0xe2, 0x00}, {0x06, 0x01, 0xe2, 0x00}, + {0x0a, 0x01, 0xe2, 0x00}, {0x0f, 0x01, 0xe2, 0x00}, + {0x18, 0x01, 0xe2, 0x00}, {0x1f, 0x01, 0xe2, 0x00}, + {0x29, 0x01, 0xe2, 0x00}, {0x38, 0x01, 0xe2, 0x01} + }, + { + {0x02, 0x01, 0x99, 0x00}, {0x09, 0x01, 0x99, 0x00}, + {0x17, 0x01, 0x99, 0x00}, {0x28, 0x01, 0x99, 0x01}, + {0x02, 0x01, 0xa1, 0x00}, {0x09, 0x01, 0xa1, 0x00}, + {0x17, 0x01, 0xa1, 0x00}, {0x28, 0x01, 0xa1, 0x01}, + {0x02, 0x01, 0xa7, 0x00}, {0x09, 0x01, 0xa7, 0x00}, + {0x17, 0x01, 0xa7, 0x00}, {0x28, 0x01, 0xa7, 0x01}, + {0x02, 0x01, 0xac, 0x00}, {0x09, 0x01, 0xac, 0x00}, + {0x17, 0x01, 0xac, 0x00}, {0x28, 0x01, 0xac, 0x01} + }, + { + {0x03, 0x01, 0x99, 0x00}, {0x06, 0x01, 0x99, 0x00}, + {0x0a, 0x01, 0x99, 0x00}, {0x0f, 0x01, 0x99, 0x00}, + {0x18, 0x01, 0x99, 0x00}, {0x1f, 0x01, 0x99, 0x00}, + {0x29, 0x01, 0x99, 0x00}, {0x38, 0x01, 0x99, 0x01}, + {0x03, 0x01, 0xa1, 0x00}, {0x06, 0x01, 0xa1, 0x00}, + {0x0a, 0x01, 0xa1, 0x00}, {0x0f, 0x01, 0xa1, 0x00}, + {0x18, 0x01, 0xa1, 0x00}, {0x1f, 0x01, 0xa1, 0x00}, + {0x29, 0x01, 0xa1, 0x00}, {0x38, 0x01, 0xa1, 0x01} + }, + { + {0x03, 0x01, 0xa7, 0x00}, {0x06, 0x01, 0xa7, 0x00}, + {0x0a, 0x01, 0xa7, 0x00}, {0x0f, 0x01, 0xa7, 0x00}, + {0x18, 0x01, 0xa7, 0x00}, {0x1f, 0x01, 0xa7, 0x00}, + {0x29, 0x01, 0xa7, 0x00}, {0x38, 0x01, 0xa7, 0x01}, + {0x03, 0x01, 0xac, 0x00}, {0x06, 0x01, 0xac, 0x00}, + {0x0a, 0x01, 0xac, 0x00}, {0x0f, 0x01, 0xac, 0x00}, + {0x18, 0x01, 0xac, 0x00}, {0x1f, 0x01, 0xac, 0x00}, + {0x29, 0x01, 0xac, 0x00}, {0x38, 0x01, 0xac, 0x01} + }, + /* 110 */ + { + {0x72, 0x00, 0x00, 0x00}, {0x73, 0x00, 0x00, 0x00}, + {0x75, 0x00, 0x00, 0x00}, {0x76, 0x00, 0x00, 0x00}, + {0x79, 0x00, 0x00, 0x00}, {0x7b, 0x00, 0x00, 0x00}, + {0x7f, 0x00, 0x00, 0x00}, {0x82, 0x00, 0x00, 0x00}, + {0x88, 0x00, 0x00, 0x00}, {0x8b, 0x00, 0x00, 0x00}, + {0x8f, 0x00, 0x00, 0x00}, {0x92, 0x00, 0x00, 0x00}, + {0x9b, 0x00, 0x00, 0x00}, {0xa2, 0x00, 0x00, 0x00}, + {0xaa, 0x00, 0x00, 0x00}, {0xb4, 0x00, 0x00, 0x01} + }, + { + {0x00, 0x01, 0xb0, 0x01}, {0x00, 0x01, 0xb1, 0x01}, + {0x00, 0x01, 0xb3, 0x01}, {0x00, 0x01, 0xd1, 0x01}, + {0x00, 0x01, 0xd8, 0x01}, {0x00, 0x01, 0xd9, 0x01}, + {0x00, 0x01, 0xe3, 0x01}, {0x00, 0x01, 0xe5, 0x01}, + {0x00, 0x01, 0xe6, 0x01}, {0x7a, 0x00, 0x00, 0x00}, + {0x7c, 0x00, 0x00, 0x00}, {0x7d, 0x00, 0x00, 0x00}, + {0x80, 0x00, 0x00, 0x00}, {0x81, 0x00, 0x00, 0x00}, + {0x83, 0x00, 0x00, 0x00}, {0x84, 0x00, 0x00, 0x00} + }, + { + {0x01, 0x01, 0xb0, 0x00}, {0x16, 0x01, 0xb0, 0x01}, + {0x01, 0x01, 0xb1, 0x00}, {0x16, 0x01, 0xb1, 0x01}, + {0x01, 0x01, 0xb3, 0x00}, {0x16, 0x01, 0xb3, 0x01}, + {0x01, 0x01, 0xd1, 0x00}, {0x16, 0x01, 0xd1, 0x01}, + {0x01, 0x01, 0xd8, 0x00}, {0x16, 0x01, 0xd8, 0x01}, + {0x01, 0x01, 0xd9, 0x00}, {0x16, 0x01, 0xd9, 0x01}, + {0x01, 0x01, 0xe3, 0x00}, {0x16, 0x01, 0xe3, 0x01}, + {0x01, 0x01, 0xe5, 0x00}, {0x16, 0x01, 0xe5, 0x01} + }, + { + {0x02, 0x01, 0xb0, 0x00}, {0x09, 0x01, 0xb0, 0x00}, + {0x17, 0x01, 0xb0, 0x00}, {0x28, 0x01, 0xb0, 0x01}, + {0x02, 0x01, 0xb1, 0x00}, {0x09, 0x01, 0xb1, 0x00}, + {0x17, 0x01, 0xb1, 0x00}, {0x28, 0x01, 0xb1, 0x01}, + {0x02, 0x01, 0xb3, 0x00}, {0x09, 0x01, 0xb3, 0x00}, + {0x17, 0x01, 0xb3, 0x00}, {0x28, 0x01, 0xb3, 0x01}, + {0x02, 0x01, 0xd1, 0x00}, {0x09, 0x01, 0xd1, 0x00}, + {0x17, 0x01, 0xd1, 0x00}, {0x28, 0x01, 0xd1, 0x01} + }, + { + {0x03, 0x01, 0xb0, 0x00}, {0x06, 0x01, 0xb0, 0x00}, + {0x0a, 0x01, 0xb0, 0x00}, {0x0f, 0x01, 0xb0, 0x00}, + {0x18, 0x01, 0xb0, 0x00}, {0x1f, 0x01, 0xb0, 0x00}, + {0x29, 0x01, 0xb0, 0x00}, {0x38, 0x01, 0xb0, 0x01}, + {0x03, 0x01, 0xb1, 0x00}, {0x06, 0x01, 0xb1, 0x00}, + {0x0a, 0x01, 0xb1, 0x00}, {0x0f, 0x01, 0xb1, 0x00}, + {0x18, 0x01, 0xb1, 0x00}, {0x1f, 0x01, 0xb1, 0x00}, + {0x29, 0x01, 0xb1, 0x00}, {0x38, 0x01, 0xb1, 0x01} + }, + /* 115 */ + { + {0x03, 0x01, 0xb3, 0x00}, {0x06, 0x01, 0xb3, 0x00}, + {0x0a, 0x01, 0xb3, 0x00}, {0x0f, 0x01, 0xb3, 0x00}, + {0x18, 0x01, 0xb3, 0x00}, {0x1f, 0x01, 0xb3, 0x00}, + {0x29, 0x01, 0xb3, 0x00}, {0x38, 0x01, 0xb3, 0x01}, + {0x03, 0x01, 0xd1, 0x00}, {0x06, 0x01, 0xd1, 0x00}, + {0x0a, 0x01, 0xd1, 0x00}, {0x0f, 0x01, 0xd1, 0x00}, + {0x18, 0x01, 0xd1, 0x00}, {0x1f, 0x01, 0xd1, 0x00}, + {0x29, 0x01, 0xd1, 0x00}, {0x38, 0x01, 0xd1, 0x01} + }, + { + {0x02, 0x01, 0xd8, 0x00}, {0x09, 0x01, 0xd8, 0x00}, + {0x17, 0x01, 0xd8, 0x00}, {0x28, 0x01, 0xd8, 0x01}, + {0x02, 0x01, 0xd9, 0x00}, {0x09, 0x01, 0xd9, 0x00}, + {0x17, 0x01, 0xd9, 0x00}, {0x28, 0x01, 0xd9, 0x01}, + {0x02, 0x01, 0xe3, 0x00}, {0x09, 0x01, 0xe3, 0x00}, + {0x17, 0x01, 0xe3, 0x00}, {0x28, 0x01, 0xe3, 0x01}, + {0x02, 0x01, 0xe5, 0x00}, {0x09, 0x01, 0xe5, 0x00}, + {0x17, 0x01, 0xe5, 0x00}, {0x28, 0x01, 0xe5, 0x01} + }, + { + {0x03, 0x01, 0xd8, 0x00}, {0x06, 0x01, 0xd8, 0x00}, + {0x0a, 0x01, 0xd8, 0x00}, {0x0f, 0x01, 0xd8, 0x00}, + {0x18, 0x01, 0xd8, 0x00}, {0x1f, 0x01, 0xd8, 0x00}, + {0x29, 0x01, 0xd8, 0x00}, {0x38, 0x01, 0xd8, 0x01}, + {0x03, 0x01, 0xd9, 0x00}, {0x06, 0x01, 0xd9, 0x00}, + {0x0a, 0x01, 0xd9, 0x00}, {0x0f, 0x01, 0xd9, 0x00}, + {0x18, 0x01, 0xd9, 0x00}, {0x1f, 0x01, 0xd9, 0x00}, + {0x29, 0x01, 0xd9, 0x00}, {0x38, 0x01, 0xd9, 0x01} + }, + { + {0x03, 0x01, 0xe3, 0x00}, {0x06, 0x01, 0xe3, 0x00}, + {0x0a, 0x01, 0xe3, 0x00}, {0x0f, 0x01, 0xe3, 0x00}, + {0x18, 0x01, 0xe3, 0x00}, {0x1f, 0x01, 0xe3, 0x00}, + {0x29, 0x01, 0xe3, 0x00}, {0x38, 0x01, 0xe3, 0x01}, + {0x03, 0x01, 0xe5, 0x00}, {0x06, 0x01, 0xe5, 0x00}, + {0x0a, 0x01, 0xe5, 0x00}, {0x0f, 0x01, 0xe5, 0x00}, + {0x18, 0x01, 0xe5, 0x00}, {0x1f, 0x01, 0xe5, 0x00}, + {0x29, 0x01, 0xe5, 0x00}, {0x38, 0x01, 0xe5, 0x01} + }, + { + {0x01, 0x01, 0xe6, 0x00}, {0x16, 0x01, 0xe6, 0x01}, + {0x00, 0x01, 0x81, 0x01}, {0x00, 0x01, 0x84, 0x01}, + {0x00, 0x01, 0x85, 0x01}, {0x00, 0x01, 0x86, 0x01}, + {0x00, 0x01, 0x88, 0x01}, {0x00, 0x01, 0x92, 0x01}, + {0x00, 0x01, 0x9a, 0x01}, {0x00, 0x01, 0x9c, 0x01}, + {0x00, 0x01, 0xa0, 0x01}, {0x00, 0x01, 0xa3, 0x01}, + {0x00, 0x01, 0xa4, 0x01}, {0x00, 0x01, 0xa9, 0x01}, + {0x00, 0x01, 0xaa, 0x01}, {0x00, 0x01, 0xad, 0x01} + }, + /* 120 */ + { + {0x02, 0x01, 0xe6, 0x00}, {0x09, 0x01, 0xe6, 0x00}, + {0x17, 0x01, 0xe6, 0x00}, {0x28, 0x01, 0xe6, 0x01}, + {0x01, 0x01, 0x81, 0x00}, {0x16, 0x01, 0x81, 0x01}, + {0x01, 0x01, 0x84, 0x00}, {0x16, 0x01, 0x84, 0x01}, + {0x01, 0x01, 0x85, 0x00}, {0x16, 0x01, 0x85, 0x01}, + {0x01, 0x01, 0x86, 0x00}, {0x16, 0x01, 0x86, 0x01}, + {0x01, 0x01, 0x88, 0x00}, {0x16, 0x01, 0x88, 0x01}, + {0x01, 0x01, 0x92, 0x00}, {0x16, 0x01, 0x92, 0x01} + }, + { + {0x03, 0x01, 0xe6, 0x00}, {0x06, 0x01, 0xe6, 0x00}, + {0x0a, 0x01, 0xe6, 0x00}, {0x0f, 0x01, 0xe6, 0x00}, + {0x18, 0x01, 0xe6, 0x00}, {0x1f, 0x01, 0xe6, 0x00}, + {0x29, 0x01, 0xe6, 0x00}, {0x38, 0x01, 0xe6, 0x01}, + {0x02, 0x01, 0x81, 0x00}, {0x09, 0x01, 0x81, 0x00}, + {0x17, 0x01, 0x81, 0x00}, {0x28, 0x01, 0x81, 0x01}, + {0x02, 0x01, 0x84, 0x00}, {0x09, 0x01, 0x84, 0x00}, + {0x17, 0x01, 0x84, 0x00}, {0x28, 0x01, 0x84, 0x01} + }, + { + {0x03, 0x01, 0x81, 0x00}, {0x06, 0x01, 0x81, 0x00}, + {0x0a, 0x01, 0x81, 0x00}, {0x0f, 0x01, 0x81, 0x00}, + {0x18, 0x01, 0x81, 0x00}, {0x1f, 0x01, 0x81, 0x00}, + {0x29, 0x01, 0x81, 0x00}, {0x38, 0x01, 0x81, 0x01}, + {0x03, 0x01, 0x84, 0x00}, {0x06, 0x01, 0x84, 0x00}, + {0x0a, 0x01, 0x84, 0x00}, {0x0f, 0x01, 0x84, 0x00}, + {0x18, 0x01, 0x84, 0x00}, {0x1f, 0x01, 0x84, 0x00}, + {0x29, 0x01, 0x84, 0x00}, {0x38, 0x01, 0x84, 0x01} + }, + { + {0x02, 0x01, 0x85, 0x00}, {0x09, 0x01, 0x85, 0x00}, + {0x17, 0x01, 0x85, 0x00}, {0x28, 0x01, 0x85, 0x01}, + {0x02, 0x01, 0x86, 0x00}, {0x09, 0x01, 0x86, 0x00}, + {0x17, 0x01, 0x86, 0x00}, {0x28, 0x01, 0x86, 0x01}, + {0x02, 0x01, 0x88, 0x00}, {0x09, 0x01, 0x88, 0x00}, + {0x17, 0x01, 0x88, 0x00}, {0x28, 0x01, 0x88, 0x01}, + {0x02, 0x01, 0x92, 0x00}, {0x09, 0x01, 0x92, 0x00}, + {0x17, 0x01, 0x92, 0x00}, {0x28, 0x01, 0x92, 0x01} + }, + { + {0x03, 0x01, 0x85, 0x00}, {0x06, 0x01, 0x85, 0x00}, + {0x0a, 0x01, 0x85, 0x00}, {0x0f, 0x01, 0x85, 0x00}, + {0x18, 0x01, 0x85, 0x00}, {0x1f, 0x01, 0x85, 0x00}, + {0x29, 0x01, 0x85, 0x00}, {0x38, 0x01, 0x85, 0x01}, + {0x03, 0x01, 0x86, 0x00}, {0x06, 0x01, 0x86, 0x00}, + {0x0a, 0x01, 0x86, 0x00}, {0x0f, 0x01, 0x86, 0x00}, + {0x18, 0x01, 0x86, 0x00}, {0x1f, 0x01, 0x86, 0x00}, + {0x29, 0x01, 0x86, 0x00}, {0x38, 0x01, 0x86, 0x01} + }, + /* 125 */ + { + {0x03, 0x01, 0x88, 0x00}, {0x06, 0x01, 0x88, 0x00}, + {0x0a, 0x01, 0x88, 0x00}, {0x0f, 0x01, 0x88, 0x00}, + {0x18, 0x01, 0x88, 0x00}, {0x1f, 0x01, 0x88, 0x00}, + {0x29, 0x01, 0x88, 0x00}, {0x38, 0x01, 0x88, 0x01}, + {0x03, 0x01, 0x92, 0x00}, {0x06, 0x01, 0x92, 0x00}, + {0x0a, 0x01, 0x92, 0x00}, {0x0f, 0x01, 0x92, 0x00}, + {0x18, 0x01, 0x92, 0x00}, {0x1f, 0x01, 0x92, 0x00}, + {0x29, 0x01, 0x92, 0x00}, {0x38, 0x01, 0x92, 0x01} + }, + { + {0x01, 0x01, 0x9a, 0x00}, {0x16, 0x01, 0x9a, 0x01}, + {0x01, 0x01, 0x9c, 0x00}, {0x16, 0x01, 0x9c, 0x01}, + {0x01, 0x01, 0xa0, 0x00}, {0x16, 0x01, 0xa0, 0x01}, + {0x01, 0x01, 0xa3, 0x00}, {0x16, 0x01, 0xa3, 0x01}, + {0x01, 0x01, 0xa4, 0x00}, {0x16, 0x01, 0xa4, 0x01}, + {0x01, 0x01, 0xa9, 0x00}, {0x16, 0x01, 0xa9, 0x01}, + {0x01, 0x01, 0xaa, 0x00}, {0x16, 0x01, 0xaa, 0x01}, + {0x01, 0x01, 0xad, 0x00}, {0x16, 0x01, 0xad, 0x01} + }, + { + {0x02, 0x01, 0x9a, 0x00}, {0x09, 0x01, 0x9a, 0x00}, + {0x17, 0x01, 0x9a, 0x00}, {0x28, 0x01, 0x9a, 0x01}, + {0x02, 0x01, 0x9c, 0x00}, {0x09, 0x01, 0x9c, 0x00}, + {0x17, 0x01, 0x9c, 0x00}, {0x28, 0x01, 0x9c, 0x01}, + {0x02, 0x01, 0xa0, 0x00}, {0x09, 0x01, 0xa0, 0x00}, + {0x17, 0x01, 0xa0, 0x00}, {0x28, 0x01, 0xa0, 0x01}, + {0x02, 0x01, 0xa3, 0x00}, {0x09, 0x01, 0xa3, 0x00}, + {0x17, 0x01, 0xa3, 0x00}, {0x28, 0x01, 0xa3, 0x01} + }, + { + {0x03, 0x01, 0x9a, 0x00}, {0x06, 0x01, 0x9a, 0x00}, + {0x0a, 0x01, 0x9a, 0x00}, {0x0f, 0x01, 0x9a, 0x00}, + {0x18, 0x01, 0x9a, 0x00}, {0x1f, 0x01, 0x9a, 0x00}, + {0x29, 0x01, 0x9a, 0x00}, {0x38, 0x01, 0x9a, 0x01}, + {0x03, 0x01, 0x9c, 0x00}, {0x06, 0x01, 0x9c, 0x00}, + {0x0a, 0x01, 0x9c, 0x00}, {0x0f, 0x01, 0x9c, 0x00}, + {0x18, 0x01, 0x9c, 0x00}, {0x1f, 0x01, 0x9c, 0x00}, + {0x29, 0x01, 0x9c, 0x00}, {0x38, 0x01, 0x9c, 0x01} + }, + { + {0x03, 0x01, 0xa0, 0x00}, {0x06, 0x01, 0xa0, 0x00}, + {0x0a, 0x01, 0xa0, 0x00}, {0x0f, 0x01, 0xa0, 0x00}, + {0x18, 0x01, 0xa0, 0x00}, {0x1f, 0x01, 0xa0, 0x00}, + {0x29, 0x01, 0xa0, 0x00}, {0x38, 0x01, 0xa0, 0x01}, + {0x03, 0x01, 0xa3, 0x00}, {0x06, 0x01, 0xa3, 0x00}, + {0x0a, 0x01, 0xa3, 0x00}, {0x0f, 0x01, 0xa3, 0x00}, + {0x18, 0x01, 0xa3, 0x00}, {0x1f, 0x01, 0xa3, 0x00}, + {0x29, 0x01, 0xa3, 0x00}, {0x38, 0x01, 0xa3, 0x01} + }, + /* 130 */ + { + {0x02, 0x01, 0xa4, 0x00}, {0x09, 0x01, 0xa4, 0x00}, + {0x17, 0x01, 0xa4, 0x00}, {0x28, 0x01, 0xa4, 0x01}, + {0x02, 0x01, 0xa9, 0x00}, {0x09, 0x01, 0xa9, 0x00}, + {0x17, 0x01, 0xa9, 0x00}, {0x28, 0x01, 0xa9, 0x01}, + {0x02, 0x01, 0xaa, 0x00}, {0x09, 0x01, 0xaa, 0x00}, + {0x17, 0x01, 0xaa, 0x00}, {0x28, 0x01, 0xaa, 0x01}, + {0x02, 0x01, 0xad, 0x00}, {0x09, 0x01, 0xad, 0x00}, + {0x17, 0x01, 0xad, 0x00}, {0x28, 0x01, 0xad, 0x01} + }, + { + {0x03, 0x01, 0xa4, 0x00}, {0x06, 0x01, 0xa4, 0x00}, + {0x0a, 0x01, 0xa4, 0x00}, {0x0f, 0x01, 0xa4, 0x00}, + {0x18, 0x01, 0xa4, 0x00}, {0x1f, 0x01, 0xa4, 0x00}, + {0x29, 0x01, 0xa4, 0x00}, {0x38, 0x01, 0xa4, 0x01}, + {0x03, 0x01, 0xa9, 0x00}, {0x06, 0x01, 0xa9, 0x00}, + {0x0a, 0x01, 0xa9, 0x00}, {0x0f, 0x01, 0xa9, 0x00}, + {0x18, 0x01, 0xa9, 0x00}, {0x1f, 0x01, 0xa9, 0x00}, + {0x29, 0x01, 0xa9, 0x00}, {0x38, 0x01, 0xa9, 0x01} + }, + { + {0x03, 0x01, 0xaa, 0x00}, {0x06, 0x01, 0xaa, 0x00}, + {0x0a, 0x01, 0xaa, 0x00}, {0x0f, 0x01, 0xaa, 0x00}, + {0x18, 0x01, 0xaa, 0x00}, {0x1f, 0x01, 0xaa, 0x00}, + {0x29, 0x01, 0xaa, 0x00}, {0x38, 0x01, 0xaa, 0x01}, + {0x03, 0x01, 0xad, 0x00}, {0x06, 0x01, 0xad, 0x00}, + {0x0a, 0x01, 0xad, 0x00}, {0x0f, 0x01, 0xad, 0x00}, + {0x18, 0x01, 0xad, 0x00}, {0x1f, 0x01, 0xad, 0x00}, + {0x29, 0x01, 0xad, 0x00}, {0x38, 0x01, 0xad, 0x01} + }, + { + {0x89, 0x00, 0x00, 0x00}, {0x8a, 0x00, 0x00, 0x00}, + {0x8c, 0x00, 0x00, 0x00}, {0x8d, 0x00, 0x00, 0x00}, + {0x90, 0x00, 0x00, 0x00}, {0x91, 0x00, 0x00, 0x00}, + {0x93, 0x00, 0x00, 0x00}, {0x96, 0x00, 0x00, 0x00}, + {0x9c, 0x00, 0x00, 0x00}, {0x9f, 0x00, 0x00, 0x00}, + {0xa3, 0x00, 0x00, 0x00}, {0xa6, 0x00, 0x00, 0x00}, + {0xab, 0x00, 0x00, 0x00}, {0xae, 0x00, 0x00, 0x00}, + {0xb5, 0x00, 0x00, 0x00}, {0xbe, 0x00, 0x00, 0x01} + }, + { + {0x00, 0x01, 0xb2, 0x01}, {0x00, 0x01, 0xb5, 0x01}, + {0x00, 0x01, 0xb9, 0x01}, {0x00, 0x01, 0xba, 0x01}, + {0x00, 0x01, 0xbb, 0x01}, {0x00, 0x01, 0xbd, 0x01}, + {0x00, 0x01, 0xbe, 0x01}, {0x00, 0x01, 0xc4, 0x01}, + {0x00, 0x01, 0xc6, 0x01}, {0x00, 0x01, 0xe4, 0x01}, + {0x00, 0x01, 0xe8, 0x01}, {0x00, 0x01, 0xe9, 0x01}, + {0x94, 0x00, 0x00, 0x00}, {0x95, 0x00, 0x00, 0x00}, + {0x97, 0x00, 0x00, 0x00}, {0x98, 0x00, 0x00, 0x00} + }, + /* 135 */ + { + {0x01, 0x01, 0xb2, 0x00}, {0x16, 0x01, 0xb2, 0x01}, + {0x01, 0x01, 0xb5, 0x00}, {0x16, 0x01, 0xb5, 0x01}, + {0x01, 0x01, 0xb9, 0x00}, {0x16, 0x01, 0xb9, 0x01}, + {0x01, 0x01, 0xba, 0x00}, {0x16, 0x01, 0xba, 0x01}, + {0x01, 0x01, 0xbb, 0x00}, {0x16, 0x01, 0xbb, 0x01}, + {0x01, 0x01, 0xbd, 0x00}, {0x16, 0x01, 0xbd, 0x01}, + {0x01, 0x01, 0xbe, 0x00}, {0x16, 0x01, 0xbe, 0x01}, + {0x01, 0x01, 0xc4, 0x00}, {0x16, 0x01, 0xc4, 0x01} + }, + { + {0x02, 0x01, 0xb2, 0x00}, {0x09, 0x01, 0xb2, 0x00}, + {0x17, 0x01, 0xb2, 0x00}, {0x28, 0x01, 0xb2, 0x01}, + {0x02, 0x01, 0xb5, 0x00}, {0x09, 0x01, 0xb5, 0x00}, + {0x17, 0x01, 0xb5, 0x00}, {0x28, 0x01, 0xb5, 0x01}, + {0x02, 0x01, 0xb9, 0x00}, {0x09, 0x01, 0xb9, 0x00}, + {0x17, 0x01, 0xb9, 0x00}, {0x28, 0x01, 0xb9, 0x01}, + {0x02, 0x01, 0xba, 0x00}, {0x09, 0x01, 0xba, 0x00}, + {0x17, 0x01, 0xba, 0x00}, {0x28, 0x01, 0xba, 0x01} + }, + { + {0x03, 0x01, 0xb2, 0x00}, {0x06, 0x01, 0xb2, 0x00}, + {0x0a, 0x01, 0xb2, 0x00}, {0x0f, 0x01, 0xb2, 0x00}, + {0x18, 0x01, 0xb2, 0x00}, {0x1f, 0x01, 0xb2, 0x00}, + {0x29, 0x01, 0xb2, 0x00}, {0x38, 0x01, 0xb2, 0x01}, + {0x03, 0x01, 0xb5, 0x00}, {0x06, 0x01, 0xb5, 0x00}, + {0x0a, 0x01, 0xb5, 0x00}, {0x0f, 0x01, 0xb5, 0x00}, + {0x18, 0x01, 0xb5, 0x00}, {0x1f, 0x01, 0xb5, 0x00}, + {0x29, 0x01, 0xb5, 0x00}, {0x38, 0x01, 0xb5, 0x01} + }, + { + {0x03, 0x01, 0xb9, 0x00}, {0x06, 0x01, 0xb9, 0x00}, + {0x0a, 0x01, 0xb9, 0x00}, {0x0f, 0x01, 0xb9, 0x00}, + {0x18, 0x01, 0xb9, 0x00}, {0x1f, 0x01, 0xb9, 0x00}, + {0x29, 0x01, 0xb9, 0x00}, {0x38, 0x01, 0xb9, 0x01}, + {0x03, 0x01, 0xba, 0x00}, {0x06, 0x01, 0xba, 0x00}, + {0x0a, 0x01, 0xba, 0x00}, {0x0f, 0x01, 0xba, 0x00}, + {0x18, 0x01, 0xba, 0x00}, {0x1f, 0x01, 0xba, 0x00}, + {0x29, 0x01, 0xba, 0x00}, {0x38, 0x01, 0xba, 0x01} + }, + { + {0x02, 0x01, 0xbb, 0x00}, {0x09, 0x01, 0xbb, 0x00}, + {0x17, 0x01, 0xbb, 0x00}, {0x28, 0x01, 0xbb, 0x01}, + {0x02, 0x01, 0xbd, 0x00}, {0x09, 0x01, 0xbd, 0x00}, + {0x17, 0x01, 0xbd, 0x00}, {0x28, 0x01, 0xbd, 0x01}, + {0x02, 0x01, 0xbe, 0x00}, {0x09, 0x01, 0xbe, 0x00}, + {0x17, 0x01, 0xbe, 0x00}, {0x28, 0x01, 0xbe, 0x01}, + {0x02, 0x01, 0xc4, 0x00}, {0x09, 0x01, 0xc4, 0x00}, + {0x17, 0x01, 0xc4, 0x00}, {0x28, 0x01, 0xc4, 0x01} + }, + /* 140 */ + { + {0x03, 0x01, 0xbb, 0x00}, {0x06, 0x01, 0xbb, 0x00}, + {0x0a, 0x01, 0xbb, 0x00}, {0x0f, 0x01, 0xbb, 0x00}, + {0x18, 0x01, 0xbb, 0x00}, {0x1f, 0x01, 0xbb, 0x00}, + {0x29, 0x01, 0xbb, 0x00}, {0x38, 0x01, 0xbb, 0x01}, + {0x03, 0x01, 0xbd, 0x00}, {0x06, 0x01, 0xbd, 0x00}, + {0x0a, 0x01, 0xbd, 0x00}, {0x0f, 0x01, 0xbd, 0x00}, + {0x18, 0x01, 0xbd, 0x00}, {0x1f, 0x01, 0xbd, 0x00}, + {0x29, 0x01, 0xbd, 0x00}, {0x38, 0x01, 0xbd, 0x01} + }, + { + {0x03, 0x01, 0xbe, 0x00}, {0x06, 0x01, 0xbe, 0x00}, + {0x0a, 0x01, 0xbe, 0x00}, {0x0f, 0x01, 0xbe, 0x00}, + {0x18, 0x01, 0xbe, 0x00}, {0x1f, 0x01, 0xbe, 0x00}, + {0x29, 0x01, 0xbe, 0x00}, {0x38, 0x01, 0xbe, 0x01}, + {0x03, 0x01, 0xc4, 0x00}, {0x06, 0x01, 0xc4, 0x00}, + {0x0a, 0x01, 0xc4, 0x00}, {0x0f, 0x01, 0xc4, 0x00}, + {0x18, 0x01, 0xc4, 0x00}, {0x1f, 0x01, 0xc4, 0x00}, + {0x29, 0x01, 0xc4, 0x00}, {0x38, 0x01, 0xc4, 0x01} + }, + { + {0x01, 0x01, 0xc6, 0x00}, {0x16, 0x01, 0xc6, 0x01}, + {0x01, 0x01, 0xe4, 0x00}, {0x16, 0x01, 0xe4, 0x01}, + {0x01, 0x01, 0xe8, 0x00}, {0x16, 0x01, 0xe8, 0x01}, + {0x01, 0x01, 0xe9, 0x00}, {0x16, 0x01, 0xe9, 0x01}, + {0x00, 0x01, 0x01, 0x01}, {0x00, 0x01, 0x87, 0x01}, + {0x00, 0x01, 0x89, 0x01}, {0x00, 0x01, 0x8a, 0x01}, + {0x00, 0x01, 0x8b, 0x01}, {0x00, 0x01, 0x8c, 0x01}, + {0x00, 0x01, 0x8d, 0x01}, {0x00, 0x01, 0x8f, 0x01} + }, + { + {0x02, 0x01, 0xc6, 0x00}, {0x09, 0x01, 0xc6, 0x00}, + {0x17, 0x01, 0xc6, 0x00}, {0x28, 0x01, 0xc6, 0x01}, + {0x02, 0x01, 0xe4, 0x00}, {0x09, 0x01, 0xe4, 0x00}, + {0x17, 0x01, 0xe4, 0x00}, {0x28, 0x01, 0xe4, 0x01}, + {0x02, 0x01, 0xe8, 0x00}, {0x09, 0x01, 0xe8, 0x00}, + {0x17, 0x01, 0xe8, 0x00}, {0x28, 0x01, 0xe8, 0x01}, + {0x02, 0x01, 0xe9, 0x00}, {0x09, 0x01, 0xe9, 0x00}, + {0x17, 0x01, 0xe9, 0x00}, {0x28, 0x01, 0xe9, 0x01} + }, + { + {0x03, 0x01, 0xc6, 0x00}, {0x06, 0x01, 0xc6, 0x00}, + {0x0a, 0x01, 0xc6, 0x00}, {0x0f, 0x01, 0xc6, 0x00}, + {0x18, 0x01, 0xc6, 0x00}, {0x1f, 0x01, 0xc6, 0x00}, + {0x29, 0x01, 0xc6, 0x00}, {0x38, 0x01, 0xc6, 0x01}, + {0x03, 0x01, 0xe4, 0x00}, {0x06, 0x01, 0xe4, 0x00}, + {0x0a, 0x01, 0xe4, 0x00}, {0x0f, 0x01, 0xe4, 0x00}, + {0x18, 0x01, 0xe4, 0x00}, {0x1f, 0x01, 0xe4, 0x00}, + {0x29, 0x01, 0xe4, 0x00}, {0x38, 0x01, 0xe4, 0x01} + }, + /* 145 */ + { + {0x03, 0x01, 0xe8, 0x00}, {0x06, 0x01, 0xe8, 0x00}, + {0x0a, 0x01, 0xe8, 0x00}, {0x0f, 0x01, 0xe8, 0x00}, + {0x18, 0x01, 0xe8, 0x00}, {0x1f, 0x01, 0xe8, 0x00}, + {0x29, 0x01, 0xe8, 0x00}, {0x38, 0x01, 0xe8, 0x01}, + {0x03, 0x01, 0xe9, 0x00}, {0x06, 0x01, 0xe9, 0x00}, + {0x0a, 0x01, 0xe9, 0x00}, {0x0f, 0x01, 0xe9, 0x00}, + {0x18, 0x01, 0xe9, 0x00}, {0x1f, 0x01, 0xe9, 0x00}, + {0x29, 0x01, 0xe9, 0x00}, {0x38, 0x01, 0xe9, 0x01} + }, + { + {0x01, 0x01, 0x01, 0x00}, {0x16, 0x01, 0x01, 0x01}, + {0x01, 0x01, 0x87, 0x00}, {0x16, 0x01, 0x87, 0x01}, + {0x01, 0x01, 0x89, 0x00}, {0x16, 0x01, 0x89, 0x01}, + {0x01, 0x01, 0x8a, 0x00}, {0x16, 0x01, 0x8a, 0x01}, + {0x01, 0x01, 0x8b, 0x00}, {0x16, 0x01, 0x8b, 0x01}, + {0x01, 0x01, 0x8c, 0x00}, {0x16, 0x01, 0x8c, 0x01}, + {0x01, 0x01, 0x8d, 0x00}, {0x16, 0x01, 0x8d, 0x01}, + {0x01, 0x01, 0x8f, 0x00}, {0x16, 0x01, 0x8f, 0x01} + }, + { + {0x02, 0x01, 0x01, 0x00}, {0x09, 0x01, 0x01, 0x00}, + {0x17, 0x01, 0x01, 0x00}, {0x28, 0x01, 0x01, 0x01}, + {0x02, 0x01, 0x87, 0x00}, {0x09, 0x01, 0x87, 0x00}, + {0x17, 0x01, 0x87, 0x00}, {0x28, 0x01, 0x87, 0x01}, + {0x02, 0x01, 0x89, 0x00}, {0x09, 0x01, 0x89, 0x00}, + {0x17, 0x01, 0x89, 0x00}, {0x28, 0x01, 0x89, 0x01}, + {0x02, 0x01, 0x8a, 0x00}, {0x09, 0x01, 0x8a, 0x00}, + {0x17, 0x01, 0x8a, 0x00}, {0x28, 0x01, 0x8a, 0x01} + }, + { + {0x03, 0x01, 0x01, 0x00}, {0x06, 0x01, 0x01, 0x00}, + {0x0a, 0x01, 0x01, 0x00}, {0x0f, 0x01, 0x01, 0x00}, + {0x18, 0x01, 0x01, 0x00}, {0x1f, 0x01, 0x01, 0x00}, + {0x29, 0x01, 0x01, 0x00}, {0x38, 0x01, 0x01, 0x01}, + {0x03, 0x01, 0x87, 0x00}, {0x06, 0x01, 0x87, 0x00}, + {0x0a, 0x01, 0x87, 0x00}, {0x0f, 0x01, 0x87, 0x00}, + {0x18, 0x01, 0x87, 0x00}, {0x1f, 0x01, 0x87, 0x00}, + {0x29, 0x01, 0x87, 0x00}, {0x38, 0x01, 0x87, 0x01} + }, + { + {0x03, 0x01, 0x89, 0x00}, {0x06, 0x01, 0x89, 0x00}, + {0x0a, 0x01, 0x89, 0x00}, {0x0f, 0x01, 0x89, 0x00}, + {0x18, 0x01, 0x89, 0x00}, {0x1f, 0x01, 0x89, 0x00}, + {0x29, 0x01, 0x89, 0x00}, {0x38, 0x01, 0x89, 0x01}, + {0x03, 0x01, 0x8a, 0x00}, {0x06, 0x01, 0x8a, 0x00}, + {0x0a, 0x01, 0x8a, 0x00}, {0x0f, 0x01, 0x8a, 0x00}, + {0x18, 0x01, 0x8a, 0x00}, {0x1f, 0x01, 0x8a, 0x00}, + {0x29, 0x01, 0x8a, 0x00}, {0x38, 0x01, 0x8a, 0x01} + }, + /* 150 */ + { + {0x02, 0x01, 0x8b, 0x00}, {0x09, 0x01, 0x8b, 0x00}, + {0x17, 0x01, 0x8b, 0x00}, {0x28, 0x01, 0x8b, 0x01}, + {0x02, 0x01, 0x8c, 0x00}, {0x09, 0x01, 0x8c, 0x00}, + {0x17, 0x01, 0x8c, 0x00}, {0x28, 0x01, 0x8c, 0x01}, + {0x02, 0x01, 0x8d, 0x00}, {0x09, 0x01, 0x8d, 0x00}, + {0x17, 0x01, 0x8d, 0x00}, {0x28, 0x01, 0x8d, 0x01}, + {0x02, 0x01, 0x8f, 0x00}, {0x09, 0x01, 0x8f, 0x00}, + {0x17, 0x01, 0x8f, 0x00}, {0x28, 0x01, 0x8f, 0x01} + }, + { + {0x03, 0x01, 0x8b, 0x00}, {0x06, 0x01, 0x8b, 0x00}, + {0x0a, 0x01, 0x8b, 0x00}, {0x0f, 0x01, 0x8b, 0x00}, + {0x18, 0x01, 0x8b, 0x00}, {0x1f, 0x01, 0x8b, 0x00}, + {0x29, 0x01, 0x8b, 0x00}, {0x38, 0x01, 0x8b, 0x01}, + {0x03, 0x01, 0x8c, 0x00}, {0x06, 0x01, 0x8c, 0x00}, + {0x0a, 0x01, 0x8c, 0x00}, {0x0f, 0x01, 0x8c, 0x00}, + {0x18, 0x01, 0x8c, 0x00}, {0x1f, 0x01, 0x8c, 0x00}, + {0x29, 0x01, 0x8c, 0x00}, {0x38, 0x01, 0x8c, 0x01} + }, + { + {0x03, 0x01, 0x8d, 0x00}, {0x06, 0x01, 0x8d, 0x00}, + {0x0a, 0x01, 0x8d, 0x00}, {0x0f, 0x01, 0x8d, 0x00}, + {0x18, 0x01, 0x8d, 0x00}, {0x1f, 0x01, 0x8d, 0x00}, + {0x29, 0x01, 0x8d, 0x00}, {0x38, 0x01, 0x8d, 0x01}, + {0x03, 0x01, 0x8f, 0x00}, {0x06, 0x01, 0x8f, 0x00}, + {0x0a, 0x01, 0x8f, 0x00}, {0x0f, 0x01, 0x8f, 0x00}, + {0x18, 0x01, 0x8f, 0x00}, {0x1f, 0x01, 0x8f, 0x00}, + {0x29, 0x01, 0x8f, 0x00}, {0x38, 0x01, 0x8f, 0x01} + }, + { + {0x9d, 0x00, 0x00, 0x00}, {0x9e, 0x00, 0x00, 0x00}, + {0xa0, 0x00, 0x00, 0x00}, {0xa1, 0x00, 0x00, 0x00}, + {0xa4, 0x00, 0x00, 0x00}, {0xa5, 0x00, 0x00, 0x00}, + {0xa7, 0x00, 0x00, 0x00}, {0xa8, 0x00, 0x00, 0x00}, + {0xac, 0x00, 0x00, 0x00}, {0xad, 0x00, 0x00, 0x00}, + {0xaf, 0x00, 0x00, 0x00}, {0xb1, 0x00, 0x00, 0x00}, + {0xb6, 0x00, 0x00, 0x00}, {0xb9, 0x00, 0x00, 0x00}, + {0xbf, 0x00, 0x00, 0x00}, {0xcf, 0x00, 0x00, 0x01} + }, + { + {0x00, 0x01, 0x93, 0x01}, {0x00, 0x01, 0x95, 0x01}, + {0x00, 0x01, 0x96, 0x01}, {0x00, 0x01, 0x97, 0x01}, + {0x00, 0x01, 0x98, 0x01}, {0x00, 0x01, 0x9b, 0x01}, + {0x00, 0x01, 0x9d, 0x01}, {0x00, 0x01, 0x9e, 0x01}, + {0x00, 0x01, 0xa5, 0x01}, {0x00, 0x01, 0xa6, 0x01}, + {0x00, 0x01, 0xa8, 0x01}, {0x00, 0x01, 0xae, 0x01}, + {0x00, 0x01, 0xaf, 0x01}, {0x00, 0x01, 0xb4, 0x01}, + {0x00, 0x01, 0xb6, 0x01}, {0x00, 0x01, 0xb7, 0x01} + }, + /* 155 */ + { + {0x01, 0x01, 0x93, 0x00}, {0x16, 0x01, 0x93, 0x01}, + {0x01, 0x01, 0x95, 0x00}, {0x16, 0x01, 0x95, 0x01}, + {0x01, 0x01, 0x96, 0x00}, {0x16, 0x01, 0x96, 0x01}, + {0x01, 0x01, 0x97, 0x00}, {0x16, 0x01, 0x97, 0x01}, + {0x01, 0x01, 0x98, 0x00}, {0x16, 0x01, 0x98, 0x01}, + {0x01, 0x01, 0x9b, 0x00}, {0x16, 0x01, 0x9b, 0x01}, + {0x01, 0x01, 0x9d, 0x00}, {0x16, 0x01, 0x9d, 0x01}, + {0x01, 0x01, 0x9e, 0x00}, {0x16, 0x01, 0x9e, 0x01} + }, + { + {0x02, 0x01, 0x93, 0x00}, {0x09, 0x01, 0x93, 0x00}, + {0x17, 0x01, 0x93, 0x00}, {0x28, 0x01, 0x93, 0x01}, + {0x02, 0x01, 0x95, 0x00}, {0x09, 0x01, 0x95, 0x00}, + {0x17, 0x01, 0x95, 0x00}, {0x28, 0x01, 0x95, 0x01}, + {0x02, 0x01, 0x96, 0x00}, {0x09, 0x01, 0x96, 0x00}, + {0x17, 0x01, 0x96, 0x00}, {0x28, 0x01, 0x96, 0x01}, + {0x02, 0x01, 0x97, 0x00}, {0x09, 0x01, 0x97, 0x00}, + {0x17, 0x01, 0x97, 0x00}, {0x28, 0x01, 0x97, 0x01} + }, + { + {0x03, 0x01, 0x93, 0x00}, {0x06, 0x01, 0x93, 0x00}, + {0x0a, 0x01, 0x93, 0x00}, {0x0f, 0x01, 0x93, 0x00}, + {0x18, 0x01, 0x93, 0x00}, {0x1f, 0x01, 0x93, 0x00}, + {0x29, 0x01, 0x93, 0x00}, {0x38, 0x01, 0x93, 0x01}, + {0x03, 0x01, 0x95, 0x00}, {0x06, 0x01, 0x95, 0x00}, + {0x0a, 0x01, 0x95, 0x00}, {0x0f, 0x01, 0x95, 0x00}, + {0x18, 0x01, 0x95, 0x00}, {0x1f, 0x01, 0x95, 0x00}, + {0x29, 0x01, 0x95, 0x00}, {0x38, 0x01, 0x95, 0x01} + }, + { + {0x03, 0x01, 0x96, 0x00}, {0x06, 0x01, 0x96, 0x00}, + {0x0a, 0x01, 0x96, 0x00}, {0x0f, 0x01, 0x96, 0x00}, + {0x18, 0x01, 0x96, 0x00}, {0x1f, 0x01, 0x96, 0x00}, + {0x29, 0x01, 0x96, 0x00}, {0x38, 0x01, 0x96, 0x01}, + {0x03, 0x01, 0x97, 0x00}, {0x06, 0x01, 0x97, 0x00}, + {0x0a, 0x01, 0x97, 0x00}, {0x0f, 0x01, 0x97, 0x00}, + {0x18, 0x01, 0x97, 0x00}, {0x1f, 0x01, 0x97, 0x00}, + {0x29, 0x01, 0x97, 0x00}, {0x38, 0x01, 0x97, 0x01} + }, + { + {0x02, 0x01, 0x98, 0x00}, {0x09, 0x01, 0x98, 0x00}, + {0x17, 0x01, 0x98, 0x00}, {0x28, 0x01, 0x98, 0x01}, + {0x02, 0x01, 0x9b, 0x00}, {0x09, 0x01, 0x9b, 0x00}, + {0x17, 0x01, 0x9b, 0x00}, {0x28, 0x01, 0x9b, 0x01}, + {0x02, 0x01, 0x9d, 0x00}, {0x09, 0x01, 0x9d, 0x00}, + {0x17, 0x01, 0x9d, 0x00}, {0x28, 0x01, 0x9d, 0x01}, + {0x02, 0x01, 0x9e, 0x00}, {0x09, 0x01, 0x9e, 0x00}, + {0x17, 0x01, 0x9e, 0x00}, {0x28, 0x01, 0x9e, 0x01} + }, + /* 160 */ + { + {0x03, 0x01, 0x98, 0x00}, {0x06, 0x01, 0x98, 0x00}, + {0x0a, 0x01, 0x98, 0x00}, {0x0f, 0x01, 0x98, 0x00}, + {0x18, 0x01, 0x98, 0x00}, {0x1f, 0x01, 0x98, 0x00}, + {0x29, 0x01, 0x98, 0x00}, {0x38, 0x01, 0x98, 0x01}, + {0x03, 0x01, 0x9b, 0x00}, {0x06, 0x01, 0x9b, 0x00}, + {0x0a, 0x01, 0x9b, 0x00}, {0x0f, 0x01, 0x9b, 0x00}, + {0x18, 0x01, 0x9b, 0x00}, {0x1f, 0x01, 0x9b, 0x00}, + {0x29, 0x01, 0x9b, 0x00}, {0x38, 0x01, 0x9b, 0x01} + }, + { + {0x03, 0x01, 0x9d, 0x00}, {0x06, 0x01, 0x9d, 0x00}, + {0x0a, 0x01, 0x9d, 0x00}, {0x0f, 0x01, 0x9d, 0x00}, + {0x18, 0x01, 0x9d, 0x00}, {0x1f, 0x01, 0x9d, 0x00}, + {0x29, 0x01, 0x9d, 0x00}, {0x38, 0x01, 0x9d, 0x01}, + {0x03, 0x01, 0x9e, 0x00}, {0x06, 0x01, 0x9e, 0x00}, + {0x0a, 0x01, 0x9e, 0x00}, {0x0f, 0x01, 0x9e, 0x00}, + {0x18, 0x01, 0x9e, 0x00}, {0x1f, 0x01, 0x9e, 0x00}, + {0x29, 0x01, 0x9e, 0x00}, {0x38, 0x01, 0x9e, 0x01} + }, + { + {0x01, 0x01, 0xa5, 0x00}, {0x16, 0x01, 0xa5, 0x01}, + {0x01, 0x01, 0xa6, 0x00}, {0x16, 0x01, 0xa6, 0x01}, + {0x01, 0x01, 0xa8, 0x00}, {0x16, 0x01, 0xa8, 0x01}, + {0x01, 0x01, 0xae, 0x00}, {0x16, 0x01, 0xae, 0x01}, + {0x01, 0x01, 0xaf, 0x00}, {0x16, 0x01, 0xaf, 0x01}, + {0x01, 0x01, 0xb4, 0x00}, {0x16, 0x01, 0xb4, 0x01}, + {0x01, 0x01, 0xb6, 0x00}, {0x16, 0x01, 0xb6, 0x01}, + {0x01, 0x01, 0xb7, 0x00}, {0x16, 0x01, 0xb7, 0x01} + }, + { + {0x02, 0x01, 0xa5, 0x00}, {0x09, 0x01, 0xa5, 0x00}, + {0x17, 0x01, 0xa5, 0x00}, {0x28, 0x01, 0xa5, 0x01}, + {0x02, 0x01, 0xa6, 0x00}, {0x09, 0x01, 0xa6, 0x00}, + {0x17, 0x01, 0xa6, 0x00}, {0x28, 0x01, 0xa6, 0x01}, + {0x02, 0x01, 0xa8, 0x00}, {0x09, 0x01, 0xa8, 0x00}, + {0x17, 0x01, 0xa8, 0x00}, {0x28, 0x01, 0xa8, 0x01}, + {0x02, 0x01, 0xae, 0x00}, {0x09, 0x01, 0xae, 0x00}, + {0x17, 0x01, 0xae, 0x00}, {0x28, 0x01, 0xae, 0x01} + }, + { + {0x03, 0x01, 0xa5, 0x00}, {0x06, 0x01, 0xa5, 0x00}, + {0x0a, 0x01, 0xa5, 0x00}, {0x0f, 0x01, 0xa5, 0x00}, + {0x18, 0x01, 0xa5, 0x00}, {0x1f, 0x01, 0xa5, 0x00}, + {0x29, 0x01, 0xa5, 0x00}, {0x38, 0x01, 0xa5, 0x01}, + {0x03, 0x01, 0xa6, 0x00}, {0x06, 0x01, 0xa6, 0x00}, + {0x0a, 0x01, 0xa6, 0x00}, {0x0f, 0x01, 0xa6, 0x00}, + {0x18, 0x01, 0xa6, 0x00}, {0x1f, 0x01, 0xa6, 0x00}, + {0x29, 0x01, 0xa6, 0x00}, {0x38, 0x01, 0xa6, 0x01} + }, + /* 165 */ + { + {0x03, 0x01, 0xa8, 0x00}, {0x06, 0x01, 0xa8, 0x00}, + {0x0a, 0x01, 0xa8, 0x00}, {0x0f, 0x01, 0xa8, 0x00}, + {0x18, 0x01, 0xa8, 0x00}, {0x1f, 0x01, 0xa8, 0x00}, + {0x29, 0x01, 0xa8, 0x00}, {0x38, 0x01, 0xa8, 0x01}, + {0x03, 0x01, 0xae, 0x00}, {0x06, 0x01, 0xae, 0x00}, + {0x0a, 0x01, 0xae, 0x00}, {0x0f, 0x01, 0xae, 0x00}, + {0x18, 0x01, 0xae, 0x00}, {0x1f, 0x01, 0xae, 0x00}, + {0x29, 0x01, 0xae, 0x00}, {0x38, 0x01, 0xae, 0x01} + }, + { + {0x02, 0x01, 0xaf, 0x00}, {0x09, 0x01, 0xaf, 0x00}, + {0x17, 0x01, 0xaf, 0x00}, {0x28, 0x01, 0xaf, 0x01}, + {0x02, 0x01, 0xb4, 0x00}, {0x09, 0x01, 0xb4, 0x00}, + {0x17, 0x01, 0xb4, 0x00}, {0x28, 0x01, 0xb4, 0x01}, + {0x02, 0x01, 0xb6, 0x00}, {0x09, 0x01, 0xb6, 0x00}, + {0x17, 0x01, 0xb6, 0x00}, {0x28, 0x01, 0xb6, 0x01}, + {0x02, 0x01, 0xb7, 0x00}, {0x09, 0x01, 0xb7, 0x00}, + {0x17, 0x01, 0xb7, 0x00}, {0x28, 0x01, 0xb7, 0x01} + }, + { + {0x03, 0x01, 0xaf, 0x00}, {0x06, 0x01, 0xaf, 0x00}, + {0x0a, 0x01, 0xaf, 0x00}, {0x0f, 0x01, 0xaf, 0x00}, + {0x18, 0x01, 0xaf, 0x00}, {0x1f, 0x01, 0xaf, 0x00}, + {0x29, 0x01, 0xaf, 0x00}, {0x38, 0x01, 0xaf, 0x01}, + {0x03, 0x01, 0xb4, 0x00}, {0x06, 0x01, 0xb4, 0x00}, + {0x0a, 0x01, 0xb4, 0x00}, {0x0f, 0x01, 0xb4, 0x00}, + {0x18, 0x01, 0xb4, 0x00}, {0x1f, 0x01, 0xb4, 0x00}, + {0x29, 0x01, 0xb4, 0x00}, {0x38, 0x01, 0xb4, 0x01} + }, + { + {0x03, 0x01, 0xb6, 0x00}, {0x06, 0x01, 0xb6, 0x00}, + {0x0a, 0x01, 0xb6, 0x00}, {0x0f, 0x01, 0xb6, 0x00}, + {0x18, 0x01, 0xb6, 0x00}, {0x1f, 0x01, 0xb6, 0x00}, + {0x29, 0x01, 0xb6, 0x00}, {0x38, 0x01, 0xb6, 0x01}, + {0x03, 0x01, 0xb7, 0x00}, {0x06, 0x01, 0xb7, 0x00}, + {0x0a, 0x01, 0xb7, 0x00}, {0x0f, 0x01, 0xb7, 0x00}, + {0x18, 0x01, 0xb7, 0x00}, {0x1f, 0x01, 0xb7, 0x00}, + {0x29, 0x01, 0xb7, 0x00}, {0x38, 0x01, 0xb7, 0x01} + }, + { + {0x00, 0x01, 0xbc, 0x01}, {0x00, 0x01, 0xbf, 0x01}, + {0x00, 0x01, 0xc5, 0x01}, {0x00, 0x01, 0xe7, 0x01}, + {0x00, 0x01, 0xef, 0x01}, {0xb0, 0x00, 0x00, 0x00}, + {0xb2, 0x00, 0x00, 0x00}, {0xb3, 0x00, 0x00, 0x00}, + {0xb7, 0x00, 0x00, 0x00}, {0xb8, 0x00, 0x00, 0x00}, + {0xba, 0x00, 0x00, 0x00}, {0xbb, 0x00, 0x00, 0x00}, + {0xc0, 0x00, 0x00, 0x00}, {0xc7, 0x00, 0x00, 0x00}, + {0xd0, 0x00, 0x00, 0x00}, {0xdf, 0x00, 0x00, 0x01} + }, + /* 170 */ + { + {0x01, 0x01, 0xbc, 0x00}, {0x16, 0x01, 0xbc, 0x01}, + {0x01, 0x01, 0xbf, 0x00}, {0x16, 0x01, 0xbf, 0x01}, + {0x01, 0x01, 0xc5, 0x00}, {0x16, 0x01, 0xc5, 0x01}, + {0x01, 0x01, 0xe7, 0x00}, {0x16, 0x01, 0xe7, 0x01}, + {0x01, 0x01, 0xef, 0x00}, {0x16, 0x01, 0xef, 0x01}, + {0x00, 0x01, 0x09, 0x01}, {0x00, 0x01, 0x8e, 0x01}, + {0x00, 0x01, 0x90, 0x01}, {0x00, 0x01, 0x91, 0x01}, + {0x00, 0x01, 0x94, 0x01}, {0x00, 0x01, 0x9f, 0x01} + }, + { + {0x02, 0x01, 0xbc, 0x00}, {0x09, 0x01, 0xbc, 0x00}, + {0x17, 0x01, 0xbc, 0x00}, {0x28, 0x01, 0xbc, 0x01}, + {0x02, 0x01, 0xbf, 0x00}, {0x09, 0x01, 0xbf, 0x00}, + {0x17, 0x01, 0xbf, 0x00}, {0x28, 0x01, 0xbf, 0x01}, + {0x02, 0x01, 0xc5, 0x00}, {0x09, 0x01, 0xc5, 0x00}, + {0x17, 0x01, 0xc5, 0x00}, {0x28, 0x01, 0xc5, 0x01}, + {0x02, 0x01, 0xe7, 0x00}, {0x09, 0x01, 0xe7, 0x00}, + {0x17, 0x01, 0xe7, 0x00}, {0x28, 0x01, 0xe7, 0x01} + }, + { + {0x03, 0x01, 0xbc, 0x00}, {0x06, 0x01, 0xbc, 0x00}, + {0x0a, 0x01, 0xbc, 0x00}, {0x0f, 0x01, 0xbc, 0x00}, + {0x18, 0x01, 0xbc, 0x00}, {0x1f, 0x01, 0xbc, 0x00}, + {0x29, 0x01, 0xbc, 0x00}, {0x38, 0x01, 0xbc, 0x01}, + {0x03, 0x01, 0xbf, 0x00}, {0x06, 0x01, 0xbf, 0x00}, + {0x0a, 0x01, 0xbf, 0x00}, {0x0f, 0x01, 0xbf, 0x00}, + {0x18, 0x01, 0xbf, 0x00}, {0x1f, 0x01, 0xbf, 0x00}, + {0x29, 0x01, 0xbf, 0x00}, {0x38, 0x01, 0xbf, 0x01} + }, + { + {0x03, 0x01, 0xc5, 0x00}, {0x06, 0x01, 0xc5, 0x00}, + {0x0a, 0x01, 0xc5, 0x00}, {0x0f, 0x01, 0xc5, 0x00}, + {0x18, 0x01, 0xc5, 0x00}, {0x1f, 0x01, 0xc5, 0x00}, + {0x29, 0x01, 0xc5, 0x00}, {0x38, 0x01, 0xc5, 0x01}, + {0x03, 0x01, 0xe7, 0x00}, {0x06, 0x01, 0xe7, 0x00}, + {0x0a, 0x01, 0xe7, 0x00}, {0x0f, 0x01, 0xe7, 0x00}, + {0x18, 0x01, 0xe7, 0x00}, {0x1f, 0x01, 0xe7, 0x00}, + {0x29, 0x01, 0xe7, 0x00}, {0x38, 0x01, 0xe7, 0x01} + }, + { + {0x02, 0x01, 0xef, 0x00}, {0x09, 0x01, 0xef, 0x00}, + {0x17, 0x01, 0xef, 0x00}, {0x28, 0x01, 0xef, 0x01}, + {0x01, 0x01, 0x09, 0x00}, {0x16, 0x01, 0x09, 0x01}, + {0x01, 0x01, 0x8e, 0x00}, {0x16, 0x01, 0x8e, 0x01}, + {0x01, 0x01, 0x90, 0x00}, {0x16, 0x01, 0x90, 0x01}, + {0x01, 0x01, 0x91, 0x00}, {0x16, 0x01, 0x91, 0x01}, + {0x01, 0x01, 0x94, 0x00}, {0x16, 0x01, 0x94, 0x01}, + {0x01, 0x01, 0x9f, 0x00}, {0x16, 0x01, 0x9f, 0x01} + }, + /* 175 */ + { + {0x03, 0x01, 0xef, 0x00}, {0x06, 0x01, 0xef, 0x00}, + {0x0a, 0x01, 0xef, 0x00}, {0x0f, 0x01, 0xef, 0x00}, + {0x18, 0x01, 0xef, 0x00}, {0x1f, 0x01, 0xef, 0x00}, + {0x29, 0x01, 0xef, 0x00}, {0x38, 0x01, 0xef, 0x01}, + {0x02, 0x01, 0x09, 0x00}, {0x09, 0x01, 0x09, 0x00}, + {0x17, 0x01, 0x09, 0x00}, {0x28, 0x01, 0x09, 0x01}, + {0x02, 0x01, 0x8e, 0x00}, {0x09, 0x01, 0x8e, 0x00}, + {0x17, 0x01, 0x8e, 0x00}, {0x28, 0x01, 0x8e, 0x01} + }, + { + {0x03, 0x01, 0x09, 0x00}, {0x06, 0x01, 0x09, 0x00}, + {0x0a, 0x01, 0x09, 0x00}, {0x0f, 0x01, 0x09, 0x00}, + {0x18, 0x01, 0x09, 0x00}, {0x1f, 0x01, 0x09, 0x00}, + {0x29, 0x01, 0x09, 0x00}, {0x38, 0x01, 0x09, 0x01}, + {0x03, 0x01, 0x8e, 0x00}, {0x06, 0x01, 0x8e, 0x00}, + {0x0a, 0x01, 0x8e, 0x00}, {0x0f, 0x01, 0x8e, 0x00}, + {0x18, 0x01, 0x8e, 0x00}, {0x1f, 0x01, 0x8e, 0x00}, + {0x29, 0x01, 0x8e, 0x00}, {0x38, 0x01, 0x8e, 0x01} + }, + { + {0x02, 0x01, 0x90, 0x00}, {0x09, 0x01, 0x90, 0x00}, + {0x17, 0x01, 0x90, 0x00}, {0x28, 0x01, 0x90, 0x01}, + {0x02, 0x01, 0x91, 0x00}, {0x09, 0x01, 0x91, 0x00}, + {0x17, 0x01, 0x91, 0x00}, {0x28, 0x01, 0x91, 0x01}, + {0x02, 0x01, 0x94, 0x00}, {0x09, 0x01, 0x94, 0x00}, + {0x17, 0x01, 0x94, 0x00}, {0x28, 0x01, 0x94, 0x01}, + {0x02, 0x01, 0x9f, 0x00}, {0x09, 0x01, 0x9f, 0x00}, + {0x17, 0x01, 0x9f, 0x00}, {0x28, 0x01, 0x9f, 0x01} + }, + { + {0x03, 0x01, 0x90, 0x00}, {0x06, 0x01, 0x90, 0x00}, + {0x0a, 0x01, 0x90, 0x00}, {0x0f, 0x01, 0x90, 0x00}, + {0x18, 0x01, 0x90, 0x00}, {0x1f, 0x01, 0x90, 0x00}, + {0x29, 0x01, 0x90, 0x00}, {0x38, 0x01, 0x90, 0x01}, + {0x03, 0x01, 0x91, 0x00}, {0x06, 0x01, 0x91, 0x00}, + {0x0a, 0x01, 0x91, 0x00}, {0x0f, 0x01, 0x91, 0x00}, + {0x18, 0x01, 0x91, 0x00}, {0x1f, 0x01, 0x91, 0x00}, + {0x29, 0x01, 0x91, 0x00}, {0x38, 0x01, 0x91, 0x01} + }, + { + {0x03, 0x01, 0x94, 0x00}, {0x06, 0x01, 0x94, 0x00}, + {0x0a, 0x01, 0x94, 0x00}, {0x0f, 0x01, 0x94, 0x00}, + {0x18, 0x01, 0x94, 0x00}, {0x1f, 0x01, 0x94, 0x00}, + {0x29, 0x01, 0x94, 0x00}, {0x38, 0x01, 0x94, 0x01}, + {0x03, 0x01, 0x9f, 0x00}, {0x06, 0x01, 0x9f, 0x00}, + {0x0a, 0x01, 0x9f, 0x00}, {0x0f, 0x01, 0x9f, 0x00}, + {0x18, 0x01, 0x9f, 0x00}, {0x1f, 0x01, 0x9f, 0x00}, + {0x29, 0x01, 0x9f, 0x00}, {0x38, 0x01, 0x9f, 0x01} + }, + /* 180 */ + { + {0x00, 0x01, 0xab, 0x01}, {0x00, 0x01, 0xce, 0x01}, + {0x00, 0x01, 0xd7, 0x01}, {0x00, 0x01, 0xe1, 0x01}, + {0x00, 0x01, 0xec, 0x01}, {0x00, 0x01, 0xed, 0x01}, + {0xbc, 0x00, 0x00, 0x00}, {0xbd, 0x00, 0x00, 0x00}, + {0xc1, 0x00, 0x00, 0x00}, {0xc4, 0x00, 0x00, 0x00}, + {0xc8, 0x00, 0x00, 0x00}, {0xcb, 0x00, 0x00, 0x00}, + {0xd1, 0x00, 0x00, 0x00}, {0xd8, 0x00, 0x00, 0x00}, + {0xe0, 0x00, 0x00, 0x00}, {0xee, 0x00, 0x00, 0x01} + }, + { + {0x01, 0x01, 0xab, 0x00}, {0x16, 0x01, 0xab, 0x01}, + {0x01, 0x01, 0xce, 0x00}, {0x16, 0x01, 0xce, 0x01}, + {0x01, 0x01, 0xd7, 0x00}, {0x16, 0x01, 0xd7, 0x01}, + {0x01, 0x01, 0xe1, 0x00}, {0x16, 0x01, 0xe1, 0x01}, + {0x01, 0x01, 0xec, 0x00}, {0x16, 0x01, 0xec, 0x01}, + {0x01, 0x01, 0xed, 0x00}, {0x16, 0x01, 0xed, 0x01}, + {0x00, 0x01, 0xc7, 0x01}, {0x00, 0x01, 0xcf, 0x01}, + {0x00, 0x01, 0xea, 0x01}, {0x00, 0x01, 0xeb, 0x01} + }, + { + {0x02, 0x01, 0xab, 0x00}, {0x09, 0x01, 0xab, 0x00}, + {0x17, 0x01, 0xab, 0x00}, {0x28, 0x01, 0xab, 0x01}, + {0x02, 0x01, 0xce, 0x00}, {0x09, 0x01, 0xce, 0x00}, + {0x17, 0x01, 0xce, 0x00}, {0x28, 0x01, 0xce, 0x01}, + {0x02, 0x01, 0xd7, 0x00}, {0x09, 0x01, 0xd7, 0x00}, + {0x17, 0x01, 0xd7, 0x00}, {0x28, 0x01, 0xd7, 0x01}, + {0x02, 0x01, 0xe1, 0x00}, {0x09, 0x01, 0xe1, 0x00}, + {0x17, 0x01, 0xe1, 0x00}, {0x28, 0x01, 0xe1, 0x01} + }, + { + {0x03, 0x01, 0xab, 0x00}, {0x06, 0x01, 0xab, 0x00}, + {0x0a, 0x01, 0xab, 0x00}, {0x0f, 0x01, 0xab, 0x00}, + {0x18, 0x01, 0xab, 0x00}, {0x1f, 0x01, 0xab, 0x00}, + {0x29, 0x01, 0xab, 0x00}, {0x38, 0x01, 0xab, 0x01}, + {0x03, 0x01, 0xce, 0x00}, {0x06, 0x01, 0xce, 0x00}, + {0x0a, 0x01, 0xce, 0x00}, {0x0f, 0x01, 0xce, 0x00}, + {0x18, 0x01, 0xce, 0x00}, {0x1f, 0x01, 0xce, 0x00}, + {0x29, 0x01, 0xce, 0x00}, {0x38, 0x01, 0xce, 0x01} + }, + { + {0x03, 0x01, 0xd7, 0x00}, {0x06, 0x01, 0xd7, 0x00}, + {0x0a, 0x01, 0xd7, 0x00}, {0x0f, 0x01, 0xd7, 0x00}, + {0x18, 0x01, 0xd7, 0x00}, {0x1f, 0x01, 0xd7, 0x00}, + {0x29, 0x01, 0xd7, 0x00}, {0x38, 0x01, 0xd7, 0x01}, + {0x03, 0x01, 0xe1, 0x00}, {0x06, 0x01, 0xe1, 0x00}, + {0x0a, 0x01, 0xe1, 0x00}, {0x0f, 0x01, 0xe1, 0x00}, + {0x18, 0x01, 0xe1, 0x00}, {0x1f, 0x01, 0xe1, 0x00}, + {0x29, 0x01, 0xe1, 0x00}, {0x38, 0x01, 0xe1, 0x01} + }, + /* 185 */ + { + {0x02, 0x01, 0xec, 0x00}, {0x09, 0x01, 0xec, 0x00}, + {0x17, 0x01, 0xec, 0x00}, {0x28, 0x01, 0xec, 0x01}, + {0x02, 0x01, 0xed, 0x00}, {0x09, 0x01, 0xed, 0x00}, + {0x17, 0x01, 0xed, 0x00}, {0x28, 0x01, 0xed, 0x01}, + {0x01, 0x01, 0xc7, 0x00}, {0x16, 0x01, 0xc7, 0x01}, + {0x01, 0x01, 0xcf, 0x00}, {0x16, 0x01, 0xcf, 0x01}, + {0x01, 0x01, 0xea, 0x00}, {0x16, 0x01, 0xea, 0x01}, + {0x01, 0x01, 0xeb, 0x00}, {0x16, 0x01, 0xeb, 0x01} + }, + { + {0x03, 0x01, 0xec, 0x00}, {0x06, 0x01, 0xec, 0x00}, + {0x0a, 0x01, 0xec, 0x00}, {0x0f, 0x01, 0xec, 0x00}, + {0x18, 0x01, 0xec, 0x00}, {0x1f, 0x01, 0xec, 0x00}, + {0x29, 0x01, 0xec, 0x00}, {0x38, 0x01, 0xec, 0x01}, + {0x03, 0x01, 0xed, 0x00}, {0x06, 0x01, 0xed, 0x00}, + {0x0a, 0x01, 0xed, 0x00}, {0x0f, 0x01, 0xed, 0x00}, + {0x18, 0x01, 0xed, 0x00}, {0x1f, 0x01, 0xed, 0x00}, + {0x29, 0x01, 0xed, 0x00}, {0x38, 0x01, 0xed, 0x01} + }, + { + {0x02, 0x01, 0xc7, 0x00}, {0x09, 0x01, 0xc7, 0x00}, + {0x17, 0x01, 0xc7, 0x00}, {0x28, 0x01, 0xc7, 0x01}, + {0x02, 0x01, 0xcf, 0x00}, {0x09, 0x01, 0xcf, 0x00}, + {0x17, 0x01, 0xcf, 0x00}, {0x28, 0x01, 0xcf, 0x01}, + {0x02, 0x01, 0xea, 0x00}, {0x09, 0x01, 0xea, 0x00}, + {0x17, 0x01, 0xea, 0x00}, {0x28, 0x01, 0xea, 0x01}, + {0x02, 0x01, 0xeb, 0x00}, {0x09, 0x01, 0xeb, 0x00}, + {0x17, 0x01, 0xeb, 0x00}, {0x28, 0x01, 0xeb, 0x01} + }, + { + {0x03, 0x01, 0xc7, 0x00}, {0x06, 0x01, 0xc7, 0x00}, + {0x0a, 0x01, 0xc7, 0x00}, {0x0f, 0x01, 0xc7, 0x00}, + {0x18, 0x01, 0xc7, 0x00}, {0x1f, 0x01, 0xc7, 0x00}, + {0x29, 0x01, 0xc7, 0x00}, {0x38, 0x01, 0xc7, 0x01}, + {0x03, 0x01, 0xcf, 0x00}, {0x06, 0x01, 0xcf, 0x00}, + {0x0a, 0x01, 0xcf, 0x00}, {0x0f, 0x01, 0xcf, 0x00}, + {0x18, 0x01, 0xcf, 0x00}, {0x1f, 0x01, 0xcf, 0x00}, + {0x29, 0x01, 0xcf, 0x00}, {0x38, 0x01, 0xcf, 0x01} + }, + { + {0x03, 0x01, 0xea, 0x00}, {0x06, 0x01, 0xea, 0x00}, + {0x0a, 0x01, 0xea, 0x00}, {0x0f, 0x01, 0xea, 0x00}, + {0x18, 0x01, 0xea, 0x00}, {0x1f, 0x01, 0xea, 0x00}, + {0x29, 0x01, 0xea, 0x00}, {0x38, 0x01, 0xea, 0x01}, + {0x03, 0x01, 0xeb, 0x00}, {0x06, 0x01, 0xeb, 0x00}, + {0x0a, 0x01, 0xeb, 0x00}, {0x0f, 0x01, 0xeb, 0x00}, + {0x18, 0x01, 0xeb, 0x00}, {0x1f, 0x01, 0xeb, 0x00}, + {0x29, 0x01, 0xeb, 0x00}, {0x38, 0x01, 0xeb, 0x01} + }, + /* 190 */ + { + {0xc2, 0x00, 0x00, 0x00}, {0xc3, 0x00, 0x00, 0x00}, + {0xc5, 0x00, 0x00, 0x00}, {0xc6, 0x00, 0x00, 0x00}, + {0xc9, 0x00, 0x00, 0x00}, {0xca, 0x00, 0x00, 0x00}, + {0xcc, 0x00, 0x00, 0x00}, {0xcd, 0x00, 0x00, 0x00}, + {0xd2, 0x00, 0x00, 0x00}, {0xd5, 0x00, 0x00, 0x00}, + {0xd9, 0x00, 0x00, 0x00}, {0xdc, 0x00, 0x00, 0x00}, + {0xe1, 0x00, 0x00, 0x00}, {0xe7, 0x00, 0x00, 0x00}, + {0xef, 0x00, 0x00, 0x00}, {0xf6, 0x00, 0x00, 0x01} + }, + { + {0x00, 0x01, 0xc0, 0x01}, {0x00, 0x01, 0xc1, 0x01}, + {0x00, 0x01, 0xc8, 0x01}, {0x00, 0x01, 0xc9, 0x01}, + {0x00, 0x01, 0xca, 0x01}, {0x00, 0x01, 0xcd, 0x01}, + {0x00, 0x01, 0xd2, 0x01}, {0x00, 0x01, 0xd5, 0x01}, + {0x00, 0x01, 0xda, 0x01}, {0x00, 0x01, 0xdb, 0x01}, + {0x00, 0x01, 0xee, 0x01}, {0x00, 0x01, 0xf0, 0x01}, + {0x00, 0x01, 0xf2, 0x01}, {0x00, 0x01, 0xf3, 0x01}, + {0x00, 0x01, 0xff, 0x01}, {0xce, 0x00, 0x00, 0x00} + }, + { + {0x01, 0x01, 0xc0, 0x00}, {0x16, 0x01, 0xc0, 0x01}, + {0x01, 0x01, 0xc1, 0x00}, {0x16, 0x01, 0xc1, 0x01}, + {0x01, 0x01, 0xc8, 0x00}, {0x16, 0x01, 0xc8, 0x01}, + {0x01, 0x01, 0xc9, 0x00}, {0x16, 0x01, 0xc9, 0x01}, + {0x01, 0x01, 0xca, 0x00}, {0x16, 0x01, 0xca, 0x01}, + {0x01, 0x01, 0xcd, 0x00}, {0x16, 0x01, 0xcd, 0x01}, + {0x01, 0x01, 0xd2, 0x00}, {0x16, 0x01, 0xd2, 0x01}, + {0x01, 0x01, 0xd5, 0x00}, {0x16, 0x01, 0xd5, 0x01} + }, + { + {0x02, 0x01, 0xc0, 0x00}, {0x09, 0x01, 0xc0, 0x00}, + {0x17, 0x01, 0xc0, 0x00}, {0x28, 0x01, 0xc0, 0x01}, + {0x02, 0x01, 0xc1, 0x00}, {0x09, 0x01, 0xc1, 0x00}, + {0x17, 0x01, 0xc1, 0x00}, {0x28, 0x01, 0xc1, 0x01}, + {0x02, 0x01, 0xc8, 0x00}, {0x09, 0x01, 0xc8, 0x00}, + {0x17, 0x01, 0xc8, 0x00}, {0x28, 0x01, 0xc8, 0x01}, + {0x02, 0x01, 0xc9, 0x00}, {0x09, 0x01, 0xc9, 0x00}, + {0x17, 0x01, 0xc9, 0x00}, {0x28, 0x01, 0xc9, 0x01} + }, + { + {0x03, 0x01, 0xc0, 0x00}, {0x06, 0x01, 0xc0, 0x00}, + {0x0a, 0x01, 0xc0, 0x00}, {0x0f, 0x01, 0xc0, 0x00}, + {0x18, 0x01, 0xc0, 0x00}, {0x1f, 0x01, 0xc0, 0x00}, + {0x29, 0x01, 0xc0, 0x00}, {0x38, 0x01, 0xc0, 0x01}, + {0x03, 0x01, 0xc1, 0x00}, {0x06, 0x01, 0xc1, 0x00}, + {0x0a, 0x01, 0xc1, 0x00}, {0x0f, 0x01, 0xc1, 0x00}, + {0x18, 0x01, 0xc1, 0x00}, {0x1f, 0x01, 0xc1, 0x00}, + {0x29, 0x01, 0xc1, 0x00}, {0x38, 0x01, 0xc1, 0x01} + }, + /* 195 */ + { + {0x03, 0x01, 0xc8, 0x00}, {0x06, 0x01, 0xc8, 0x00}, + {0x0a, 0x01, 0xc8, 0x00}, {0x0f, 0x01, 0xc8, 0x00}, + {0x18, 0x01, 0xc8, 0x00}, {0x1f, 0x01, 0xc8, 0x00}, + {0x29, 0x01, 0xc8, 0x00}, {0x38, 0x01, 0xc8, 0x01}, + {0x03, 0x01, 0xc9, 0x00}, {0x06, 0x01, 0xc9, 0x00}, + {0x0a, 0x01, 0xc9, 0x00}, {0x0f, 0x01, 0xc9, 0x00}, + {0x18, 0x01, 0xc9, 0x00}, {0x1f, 0x01, 0xc9, 0x00}, + {0x29, 0x01, 0xc9, 0x00}, {0x38, 0x01, 0xc9, 0x01} + }, + { + {0x02, 0x01, 0xca, 0x00}, {0x09, 0x01, 0xca, 0x00}, + {0x17, 0x01, 0xca, 0x00}, {0x28, 0x01, 0xca, 0x01}, + {0x02, 0x01, 0xcd, 0x00}, {0x09, 0x01, 0xcd, 0x00}, + {0x17, 0x01, 0xcd, 0x00}, {0x28, 0x01, 0xcd, 0x01}, + {0x02, 0x01, 0xd2, 0x00}, {0x09, 0x01, 0xd2, 0x00}, + {0x17, 0x01, 0xd2, 0x00}, {0x28, 0x01, 0xd2, 0x01}, + {0x02, 0x01, 0xd5, 0x00}, {0x09, 0x01, 0xd5, 0x00}, + {0x17, 0x01, 0xd5, 0x00}, {0x28, 0x01, 0xd5, 0x01} + }, + { + {0x03, 0x01, 0xca, 0x00}, {0x06, 0x01, 0xca, 0x00}, + {0x0a, 0x01, 0xca, 0x00}, {0x0f, 0x01, 0xca, 0x00}, + {0x18, 0x01, 0xca, 0x00}, {0x1f, 0x01, 0xca, 0x00}, + {0x29, 0x01, 0xca, 0x00}, {0x38, 0x01, 0xca, 0x01}, + {0x03, 0x01, 0xcd, 0x00}, {0x06, 0x01, 0xcd, 0x00}, + {0x0a, 0x01, 0xcd, 0x00}, {0x0f, 0x01, 0xcd, 0x00}, + {0x18, 0x01, 0xcd, 0x00}, {0x1f, 0x01, 0xcd, 0x00}, + {0x29, 0x01, 0xcd, 0x00}, {0x38, 0x01, 0xcd, 0x01} + }, + { + {0x03, 0x01, 0xd2, 0x00}, {0x06, 0x01, 0xd2, 0x00}, + {0x0a, 0x01, 0xd2, 0x00}, {0x0f, 0x01, 0xd2, 0x00}, + {0x18, 0x01, 0xd2, 0x00}, {0x1f, 0x01, 0xd2, 0x00}, + {0x29, 0x01, 0xd2, 0x00}, {0x38, 0x01, 0xd2, 0x01}, + {0x03, 0x01, 0xd5, 0x00}, {0x06, 0x01, 0xd5, 0x00}, + {0x0a, 0x01, 0xd5, 0x00}, {0x0f, 0x01, 0xd5, 0x00}, + {0x18, 0x01, 0xd5, 0x00}, {0x1f, 0x01, 0xd5, 0x00}, + {0x29, 0x01, 0xd5, 0x00}, {0x38, 0x01, 0xd5, 0x01} + }, + { + {0x01, 0x01, 0xda, 0x00}, {0x16, 0x01, 0xda, 0x01}, + {0x01, 0x01, 0xdb, 0x00}, {0x16, 0x01, 0xdb, 0x01}, + {0x01, 0x01, 0xee, 0x00}, {0x16, 0x01, 0xee, 0x01}, + {0x01, 0x01, 0xf0, 0x00}, {0x16, 0x01, 0xf0, 0x01}, + {0x01, 0x01, 0xf2, 0x00}, {0x16, 0x01, 0xf2, 0x01}, + {0x01, 0x01, 0xf3, 0x00}, {0x16, 0x01, 0xf3, 0x01}, + {0x01, 0x01, 0xff, 0x00}, {0x16, 0x01, 0xff, 0x01}, + {0x00, 0x01, 0xcb, 0x01}, {0x00, 0x01, 0xcc, 0x01} + }, + /* 200 */ + { + {0x02, 0x01, 0xda, 0x00}, {0x09, 0x01, 0xda, 0x00}, + {0x17, 0x01, 0xda, 0x00}, {0x28, 0x01, 0xda, 0x01}, + {0x02, 0x01, 0xdb, 0x00}, {0x09, 0x01, 0xdb, 0x00}, + {0x17, 0x01, 0xdb, 0x00}, {0x28, 0x01, 0xdb, 0x01}, + {0x02, 0x01, 0xee, 0x00}, {0x09, 0x01, 0xee, 0x00}, + {0x17, 0x01, 0xee, 0x00}, {0x28, 0x01, 0xee, 0x01}, + {0x02, 0x01, 0xf0, 0x00}, {0x09, 0x01, 0xf0, 0x00}, + {0x17, 0x01, 0xf0, 0x00}, {0x28, 0x01, 0xf0, 0x01} + }, + { + {0x03, 0x01, 0xda, 0x00}, {0x06, 0x01, 0xda, 0x00}, + {0x0a, 0x01, 0xda, 0x00}, {0x0f, 0x01, 0xda, 0x00}, + {0x18, 0x01, 0xda, 0x00}, {0x1f, 0x01, 0xda, 0x00}, + {0x29, 0x01, 0xda, 0x00}, {0x38, 0x01, 0xda, 0x01}, + {0x03, 0x01, 0xdb, 0x00}, {0x06, 0x01, 0xdb, 0x00}, + {0x0a, 0x01, 0xdb, 0x00}, {0x0f, 0x01, 0xdb, 0x00}, + {0x18, 0x01, 0xdb, 0x00}, {0x1f, 0x01, 0xdb, 0x00}, + {0x29, 0x01, 0xdb, 0x00}, {0x38, 0x01, 0xdb, 0x01} + }, + { + {0x03, 0x01, 0xee, 0x00}, {0x06, 0x01, 0xee, 0x00}, + {0x0a, 0x01, 0xee, 0x00}, {0x0f, 0x01, 0xee, 0x00}, + {0x18, 0x01, 0xee, 0x00}, {0x1f, 0x01, 0xee, 0x00}, + {0x29, 0x01, 0xee, 0x00}, {0x38, 0x01, 0xee, 0x01}, + {0x03, 0x01, 0xf0, 0x00}, {0x06, 0x01, 0xf0, 0x00}, + {0x0a, 0x01, 0xf0, 0x00}, {0x0f, 0x01, 0xf0, 0x00}, + {0x18, 0x01, 0xf0, 0x00}, {0x1f, 0x01, 0xf0, 0x00}, + {0x29, 0x01, 0xf0, 0x00}, {0x38, 0x01, 0xf0, 0x01} + }, + { + {0x02, 0x01, 0xf2, 0x00}, {0x09, 0x01, 0xf2, 0x00}, + {0x17, 0x01, 0xf2, 0x00}, {0x28, 0x01, 0xf2, 0x01}, + {0x02, 0x01, 0xf3, 0x00}, {0x09, 0x01, 0xf3, 0x00}, + {0x17, 0x01, 0xf3, 0x00}, {0x28, 0x01, 0xf3, 0x01}, + {0x02, 0x01, 0xff, 0x00}, {0x09, 0x01, 0xff, 0x00}, + {0x17, 0x01, 0xff, 0x00}, {0x28, 0x01, 0xff, 0x01}, + {0x01, 0x01, 0xcb, 0x00}, {0x16, 0x01, 0xcb, 0x01}, + {0x01, 0x01, 0xcc, 0x00}, {0x16, 0x01, 0xcc, 0x01} + }, + { + {0x03, 0x01, 0xf2, 0x00}, {0x06, 0x01, 0xf2, 0x00}, + {0x0a, 0x01, 0xf2, 0x00}, {0x0f, 0x01, 0xf2, 0x00}, + {0x18, 0x01, 0xf2, 0x00}, {0x1f, 0x01, 0xf2, 0x00}, + {0x29, 0x01, 0xf2, 0x00}, {0x38, 0x01, 0xf2, 0x01}, + {0x03, 0x01, 0xf3, 0x00}, {0x06, 0x01, 0xf3, 0x00}, + {0x0a, 0x01, 0xf3, 0x00}, {0x0f, 0x01, 0xf3, 0x00}, + {0x18, 0x01, 0xf3, 0x00}, {0x1f, 0x01, 0xf3, 0x00}, + {0x29, 0x01, 0xf3, 0x00}, {0x38, 0x01, 0xf3, 0x01} + }, + /* 205 */ + { + {0x03, 0x01, 0xff, 0x00}, {0x06, 0x01, 0xff, 0x00}, + {0x0a, 0x01, 0xff, 0x00}, {0x0f, 0x01, 0xff, 0x00}, + {0x18, 0x01, 0xff, 0x00}, {0x1f, 0x01, 0xff, 0x00}, + {0x29, 0x01, 0xff, 0x00}, {0x38, 0x01, 0xff, 0x01}, + {0x02, 0x01, 0xcb, 0x00}, {0x09, 0x01, 0xcb, 0x00}, + {0x17, 0x01, 0xcb, 0x00}, {0x28, 0x01, 0xcb, 0x01}, + {0x02, 0x01, 0xcc, 0x00}, {0x09, 0x01, 0xcc, 0x00}, + {0x17, 0x01, 0xcc, 0x00}, {0x28, 0x01, 0xcc, 0x01} + }, + { + {0x03, 0x01, 0xcb, 0x00}, {0x06, 0x01, 0xcb, 0x00}, + {0x0a, 0x01, 0xcb, 0x00}, {0x0f, 0x01, 0xcb, 0x00}, + {0x18, 0x01, 0xcb, 0x00}, {0x1f, 0x01, 0xcb, 0x00}, + {0x29, 0x01, 0xcb, 0x00}, {0x38, 0x01, 0xcb, 0x01}, + {0x03, 0x01, 0xcc, 0x00}, {0x06, 0x01, 0xcc, 0x00}, + {0x0a, 0x01, 0xcc, 0x00}, {0x0f, 0x01, 0xcc, 0x00}, + {0x18, 0x01, 0xcc, 0x00}, {0x1f, 0x01, 0xcc, 0x00}, + {0x29, 0x01, 0xcc, 0x00}, {0x38, 0x01, 0xcc, 0x01} + }, + { + {0xd3, 0x00, 0x00, 0x00}, {0xd4, 0x00, 0x00, 0x00}, + {0xd6, 0x00, 0x00, 0x00}, {0xd7, 0x00, 0x00, 0x00}, + {0xda, 0x00, 0x00, 0x00}, {0xdb, 0x00, 0x00, 0x00}, + {0xdd, 0x00, 0x00, 0x00}, {0xde, 0x00, 0x00, 0x00}, + {0xe2, 0x00, 0x00, 0x00}, {0xe4, 0x00, 0x00, 0x00}, + {0xe8, 0x00, 0x00, 0x00}, {0xeb, 0x00, 0x00, 0x00}, + {0xf0, 0x00, 0x00, 0x00}, {0xf3, 0x00, 0x00, 0x00}, + {0xf7, 0x00, 0x00, 0x00}, {0xfa, 0x00, 0x00, 0x01} + }, + { + {0x00, 0x01, 0xd3, 0x01}, {0x00, 0x01, 0xd4, 0x01}, + {0x00, 0x01, 0xd6, 0x01}, {0x00, 0x01, 0xdd, 0x01}, + {0x00, 0x01, 0xde, 0x01}, {0x00, 0x01, 0xdf, 0x01}, + {0x00, 0x01, 0xf1, 0x01}, {0x00, 0x01, 0xf4, 0x01}, + {0x00, 0x01, 0xf5, 0x01}, {0x00, 0x01, 0xf6, 0x01}, + {0x00, 0x01, 0xf7, 0x01}, {0x00, 0x01, 0xf8, 0x01}, + {0x00, 0x01, 0xfa, 0x01}, {0x00, 0x01, 0xfb, 0x01}, + {0x00, 0x01, 0xfc, 0x01}, {0x00, 0x01, 0xfd, 0x01} + }, + { + {0x01, 0x01, 0xd3, 0x00}, {0x16, 0x01, 0xd3, 0x01}, + {0x01, 0x01, 0xd4, 0x00}, {0x16, 0x01, 0xd4, 0x01}, + {0x01, 0x01, 0xd6, 0x00}, {0x16, 0x01, 0xd6, 0x01}, + {0x01, 0x01, 0xdd, 0x00}, {0x16, 0x01, 0xdd, 0x01}, + {0x01, 0x01, 0xde, 0x00}, {0x16, 0x01, 0xde, 0x01}, + {0x01, 0x01, 0xdf, 0x00}, {0x16, 0x01, 0xdf, 0x01}, + {0x01, 0x01, 0xf1, 0x00}, {0x16, 0x01, 0xf1, 0x01}, + {0x01, 0x01, 0xf4, 0x00}, {0x16, 0x01, 0xf4, 0x01} + }, + /* 210 */ + { + {0x02, 0x01, 0xd3, 0x00}, {0x09, 0x01, 0xd3, 0x00}, + {0x17, 0x01, 0xd3, 0x00}, {0x28, 0x01, 0xd3, 0x01}, + {0x02, 0x01, 0xd4, 0x00}, {0x09, 0x01, 0xd4, 0x00}, + {0x17, 0x01, 0xd4, 0x00}, {0x28, 0x01, 0xd4, 0x01}, + {0x02, 0x01, 0xd6, 0x00}, {0x09, 0x01, 0xd6, 0x00}, + {0x17, 0x01, 0xd6, 0x00}, {0x28, 0x01, 0xd6, 0x01}, + {0x02, 0x01, 0xdd, 0x00}, {0x09, 0x01, 0xdd, 0x00}, + {0x17, 0x01, 0xdd, 0x00}, {0x28, 0x01, 0xdd, 0x01} + }, + { + {0x03, 0x01, 0xd3, 0x00}, {0x06, 0x01, 0xd3, 0x00}, + {0x0a, 0x01, 0xd3, 0x00}, {0x0f, 0x01, 0xd3, 0x00}, + {0x18, 0x01, 0xd3, 0x00}, {0x1f, 0x01, 0xd3, 0x00}, + {0x29, 0x01, 0xd3, 0x00}, {0x38, 0x01, 0xd3, 0x01}, + {0x03, 0x01, 0xd4, 0x00}, {0x06, 0x01, 0xd4, 0x00}, + {0x0a, 0x01, 0xd4, 0x00}, {0x0f, 0x01, 0xd4, 0x00}, + {0x18, 0x01, 0xd4, 0x00}, {0x1f, 0x01, 0xd4, 0x00}, + {0x29, 0x01, 0xd4, 0x00}, {0x38, 0x01, 0xd4, 0x01} + }, + { + {0x03, 0x01, 0xd6, 0x00}, {0x06, 0x01, 0xd6, 0x00}, + {0x0a, 0x01, 0xd6, 0x00}, {0x0f, 0x01, 0xd6, 0x00}, + {0x18, 0x01, 0xd6, 0x00}, {0x1f, 0x01, 0xd6, 0x00}, + {0x29, 0x01, 0xd6, 0x00}, {0x38, 0x01, 0xd6, 0x01}, + {0x03, 0x01, 0xdd, 0x00}, {0x06, 0x01, 0xdd, 0x00}, + {0x0a, 0x01, 0xdd, 0x00}, {0x0f, 0x01, 0xdd, 0x00}, + {0x18, 0x01, 0xdd, 0x00}, {0x1f, 0x01, 0xdd, 0x00}, + {0x29, 0x01, 0xdd, 0x00}, {0x38, 0x01, 0xdd, 0x01} + }, + { + {0x02, 0x01, 0xde, 0x00}, {0x09, 0x01, 0xde, 0x00}, + {0x17, 0x01, 0xde, 0x00}, {0x28, 0x01, 0xde, 0x01}, + {0x02, 0x01, 0xdf, 0x00}, {0x09, 0x01, 0xdf, 0x00}, + {0x17, 0x01, 0xdf, 0x00}, {0x28, 0x01, 0xdf, 0x01}, + {0x02, 0x01, 0xf1, 0x00}, {0x09, 0x01, 0xf1, 0x00}, + {0x17, 0x01, 0xf1, 0x00}, {0x28, 0x01, 0xf1, 0x01}, + {0x02, 0x01, 0xf4, 0x00}, {0x09, 0x01, 0xf4, 0x00}, + {0x17, 0x01, 0xf4, 0x00}, {0x28, 0x01, 0xf4, 0x01} + }, + { + {0x03, 0x01, 0xde, 0x00}, {0x06, 0x01, 0xde, 0x00}, + {0x0a, 0x01, 0xde, 0x00}, {0x0f, 0x01, 0xde, 0x00}, + {0x18, 0x01, 0xde, 0x00}, {0x1f, 0x01, 0xde, 0x00}, + {0x29, 0x01, 0xde, 0x00}, {0x38, 0x01, 0xde, 0x01}, + {0x03, 0x01, 0xdf, 0x00}, {0x06, 0x01, 0xdf, 0x00}, + {0x0a, 0x01, 0xdf, 0x00}, {0x0f, 0x01, 0xdf, 0x00}, + {0x18, 0x01, 0xdf, 0x00}, {0x1f, 0x01, 0xdf, 0x00}, + {0x29, 0x01, 0xdf, 0x00}, {0x38, 0x01, 0xdf, 0x01} + }, + /* 215 */ + { + {0x03, 0x01, 0xf1, 0x00}, {0x06, 0x01, 0xf1, 0x00}, + {0x0a, 0x01, 0xf1, 0x00}, {0x0f, 0x01, 0xf1, 0x00}, + {0x18, 0x01, 0xf1, 0x00}, {0x1f, 0x01, 0xf1, 0x00}, + {0x29, 0x01, 0xf1, 0x00}, {0x38, 0x01, 0xf1, 0x01}, + {0x03, 0x01, 0xf4, 0x00}, {0x06, 0x01, 0xf4, 0x00}, + {0x0a, 0x01, 0xf4, 0x00}, {0x0f, 0x01, 0xf4, 0x00}, + {0x18, 0x01, 0xf4, 0x00}, {0x1f, 0x01, 0xf4, 0x00}, + {0x29, 0x01, 0xf4, 0x00}, {0x38, 0x01, 0xf4, 0x01} + }, + { + {0x01, 0x01, 0xf5, 0x00}, {0x16, 0x01, 0xf5, 0x01}, + {0x01, 0x01, 0xf6, 0x00}, {0x16, 0x01, 0xf6, 0x01}, + {0x01, 0x01, 0xf7, 0x00}, {0x16, 0x01, 0xf7, 0x01}, + {0x01, 0x01, 0xf8, 0x00}, {0x16, 0x01, 0xf8, 0x01}, + {0x01, 0x01, 0xfa, 0x00}, {0x16, 0x01, 0xfa, 0x01}, + {0x01, 0x01, 0xfb, 0x00}, {0x16, 0x01, 0xfb, 0x01}, + {0x01, 0x01, 0xfc, 0x00}, {0x16, 0x01, 0xfc, 0x01}, + {0x01, 0x01, 0xfd, 0x00}, {0x16, 0x01, 0xfd, 0x01} + }, + { + {0x02, 0x01, 0xf5, 0x00}, {0x09, 0x01, 0xf5, 0x00}, + {0x17, 0x01, 0xf5, 0x00}, {0x28, 0x01, 0xf5, 0x01}, + {0x02, 0x01, 0xf6, 0x00}, {0x09, 0x01, 0xf6, 0x00}, + {0x17, 0x01, 0xf6, 0x00}, {0x28, 0x01, 0xf6, 0x01}, + {0x02, 0x01, 0xf7, 0x00}, {0x09, 0x01, 0xf7, 0x00}, + {0x17, 0x01, 0xf7, 0x00}, {0x28, 0x01, 0xf7, 0x01}, + {0x02, 0x01, 0xf8, 0x00}, {0x09, 0x01, 0xf8, 0x00}, + {0x17, 0x01, 0xf8, 0x00}, {0x28, 0x01, 0xf8, 0x01} + }, + { + {0x03, 0x01, 0xf5, 0x00}, {0x06, 0x01, 0xf5, 0x00}, + {0x0a, 0x01, 0xf5, 0x00}, {0x0f, 0x01, 0xf5, 0x00}, + {0x18, 0x01, 0xf5, 0x00}, {0x1f, 0x01, 0xf5, 0x00}, + {0x29, 0x01, 0xf5, 0x00}, {0x38, 0x01, 0xf5, 0x01}, + {0x03, 0x01, 0xf6, 0x00}, {0x06, 0x01, 0xf6, 0x00}, + {0x0a, 0x01, 0xf6, 0x00}, {0x0f, 0x01, 0xf6, 0x00}, + {0x18, 0x01, 0xf6, 0x00}, {0x1f, 0x01, 0xf6, 0x00}, + {0x29, 0x01, 0xf6, 0x00}, {0x38, 0x01, 0xf6, 0x01} + }, + { + {0x03, 0x01, 0xf7, 0x00}, {0x06, 0x01, 0xf7, 0x00}, + {0x0a, 0x01, 0xf7, 0x00}, {0x0f, 0x01, 0xf7, 0x00}, + {0x18, 0x01, 0xf7, 0x00}, {0x1f, 0x01, 0xf7, 0x00}, + {0x29, 0x01, 0xf7, 0x00}, {0x38, 0x01, 0xf7, 0x01}, + {0x03, 0x01, 0xf8, 0x00}, {0x06, 0x01, 0xf8, 0x00}, + {0x0a, 0x01, 0xf8, 0x00}, {0x0f, 0x01, 0xf8, 0x00}, + {0x18, 0x01, 0xf8, 0x00}, {0x1f, 0x01, 0xf8, 0x00}, + {0x29, 0x01, 0xf8, 0x00}, {0x38, 0x01, 0xf8, 0x01} + }, + /* 220 */ + { + {0x02, 0x01, 0xfa, 0x00}, {0x09, 0x01, 0xfa, 0x00}, + {0x17, 0x01, 0xfa, 0x00}, {0x28, 0x01, 0xfa, 0x01}, + {0x02, 0x01, 0xfb, 0x00}, {0x09, 0x01, 0xfb, 0x00}, + {0x17, 0x01, 0xfb, 0x00}, {0x28, 0x01, 0xfb, 0x01}, + {0x02, 0x01, 0xfc, 0x00}, {0x09, 0x01, 0xfc, 0x00}, + {0x17, 0x01, 0xfc, 0x00}, {0x28, 0x01, 0xfc, 0x01}, + {0x02, 0x01, 0xfd, 0x00}, {0x09, 0x01, 0xfd, 0x00}, + {0x17, 0x01, 0xfd, 0x00}, {0x28, 0x01, 0xfd, 0x01} + }, + { + {0x03, 0x01, 0xfa, 0x00}, {0x06, 0x01, 0xfa, 0x00}, + {0x0a, 0x01, 0xfa, 0x00}, {0x0f, 0x01, 0xfa, 0x00}, + {0x18, 0x01, 0xfa, 0x00}, {0x1f, 0x01, 0xfa, 0x00}, + {0x29, 0x01, 0xfa, 0x00}, {0x38, 0x01, 0xfa, 0x01}, + {0x03, 0x01, 0xfb, 0x00}, {0x06, 0x01, 0xfb, 0x00}, + {0x0a, 0x01, 0xfb, 0x00}, {0x0f, 0x01, 0xfb, 0x00}, + {0x18, 0x01, 0xfb, 0x00}, {0x1f, 0x01, 0xfb, 0x00}, + {0x29, 0x01, 0xfb, 0x00}, {0x38, 0x01, 0xfb, 0x01} + }, + { + {0x03, 0x01, 0xfc, 0x00}, {0x06, 0x01, 0xfc, 0x00}, + {0x0a, 0x01, 0xfc, 0x00}, {0x0f, 0x01, 0xfc, 0x00}, + {0x18, 0x01, 0xfc, 0x00}, {0x1f, 0x01, 0xfc, 0x00}, + {0x29, 0x01, 0xfc, 0x00}, {0x38, 0x01, 0xfc, 0x01}, + {0x03, 0x01, 0xfd, 0x00}, {0x06, 0x01, 0xfd, 0x00}, + {0x0a, 0x01, 0xfd, 0x00}, {0x0f, 0x01, 0xfd, 0x00}, + {0x18, 0x01, 0xfd, 0x00}, {0x1f, 0x01, 0xfd, 0x00}, + {0x29, 0x01, 0xfd, 0x00}, {0x38, 0x01, 0xfd, 0x01} + }, + { + {0x00, 0x01, 0xfe, 0x01}, {0xe3, 0x00, 0x00, 0x00}, + {0xe5, 0x00, 0x00, 0x00}, {0xe6, 0x00, 0x00, 0x00}, + {0xe9, 0x00, 0x00, 0x00}, {0xea, 0x00, 0x00, 0x00}, + {0xec, 0x00, 0x00, 0x00}, {0xed, 0x00, 0x00, 0x00}, + {0xf1, 0x00, 0x00, 0x00}, {0xf2, 0x00, 0x00, 0x00}, + {0xf4, 0x00, 0x00, 0x00}, {0xf5, 0x00, 0x00, 0x00}, + {0xf8, 0x00, 0x00, 0x00}, {0xf9, 0x00, 0x00, 0x00}, + {0xfb, 0x00, 0x00, 0x00}, {0xfc, 0x00, 0x00, 0x01} + }, + { + {0x01, 0x01, 0xfe, 0x00}, {0x16, 0x01, 0xfe, 0x01}, + {0x00, 0x01, 0x02, 0x01}, {0x00, 0x01, 0x03, 0x01}, + {0x00, 0x01, 0x04, 0x01}, {0x00, 0x01, 0x05, 0x01}, + {0x00, 0x01, 0x06, 0x01}, {0x00, 0x01, 0x07, 0x01}, + {0x00, 0x01, 0x08, 0x01}, {0x00, 0x01, 0x0b, 0x01}, + {0x00, 0x01, 0x0c, 0x01}, {0x00, 0x01, 0x0e, 0x01}, + {0x00, 0x01, 0x0f, 0x01}, {0x00, 0x01, 0x10, 0x01}, + {0x00, 0x01, 0x11, 0x01}, {0x00, 0x01, 0x12, 0x01} + }, + /* 225 */ + { + {0x02, 0x01, 0xfe, 0x00}, {0x09, 0x01, 0xfe, 0x00}, + {0x17, 0x01, 0xfe, 0x00}, {0x28, 0x01, 0xfe, 0x01}, + {0x01, 0x01, 0x02, 0x00}, {0x16, 0x01, 0x02, 0x01}, + {0x01, 0x01, 0x03, 0x00}, {0x16, 0x01, 0x03, 0x01}, + {0x01, 0x01, 0x04, 0x00}, {0x16, 0x01, 0x04, 0x01}, + {0x01, 0x01, 0x05, 0x00}, {0x16, 0x01, 0x05, 0x01}, + {0x01, 0x01, 0x06, 0x00}, {0x16, 0x01, 0x06, 0x01}, + {0x01, 0x01, 0x07, 0x00}, {0x16, 0x01, 0x07, 0x01} + }, + { + {0x03, 0x01, 0xfe, 0x00}, {0x06, 0x01, 0xfe, 0x00}, + {0x0a, 0x01, 0xfe, 0x00}, {0x0f, 0x01, 0xfe, 0x00}, + {0x18, 0x01, 0xfe, 0x00}, {0x1f, 0x01, 0xfe, 0x00}, + {0x29, 0x01, 0xfe, 0x00}, {0x38, 0x01, 0xfe, 0x01}, + {0x02, 0x01, 0x02, 0x00}, {0x09, 0x01, 0x02, 0x00}, + {0x17, 0x01, 0x02, 0x00}, {0x28, 0x01, 0x02, 0x01}, + {0x02, 0x01, 0x03, 0x00}, {0x09, 0x01, 0x03, 0x00}, + {0x17, 0x01, 0x03, 0x00}, {0x28, 0x01, 0x03, 0x01} + }, + { + {0x03, 0x01, 0x02, 0x00}, {0x06, 0x01, 0x02, 0x00}, + {0x0a, 0x01, 0x02, 0x00}, {0x0f, 0x01, 0x02, 0x00}, + {0x18, 0x01, 0x02, 0x00}, {0x1f, 0x01, 0x02, 0x00}, + {0x29, 0x01, 0x02, 0x00}, {0x38, 0x01, 0x02, 0x01}, + {0x03, 0x01, 0x03, 0x00}, {0x06, 0x01, 0x03, 0x00}, + {0x0a, 0x01, 0x03, 0x00}, {0x0f, 0x01, 0x03, 0x00}, + {0x18, 0x01, 0x03, 0x00}, {0x1f, 0x01, 0x03, 0x00}, + {0x29, 0x01, 0x03, 0x00}, {0x38, 0x01, 0x03, 0x01} + }, + { + {0x02, 0x01, 0x04, 0x00}, {0x09, 0x01, 0x04, 0x00}, + {0x17, 0x01, 0x04, 0x00}, {0x28, 0x01, 0x04, 0x01}, + {0x02, 0x01, 0x05, 0x00}, {0x09, 0x01, 0x05, 0x00}, + {0x17, 0x01, 0x05, 0x00}, {0x28, 0x01, 0x05, 0x01}, + {0x02, 0x01, 0x06, 0x00}, {0x09, 0x01, 0x06, 0x00}, + {0x17, 0x01, 0x06, 0x00}, {0x28, 0x01, 0x06, 0x01}, + {0x02, 0x01, 0x07, 0x00}, {0x09, 0x01, 0x07, 0x00}, + {0x17, 0x01, 0x07, 0x00}, {0x28, 0x01, 0x07, 0x01} + }, + { + {0x03, 0x01, 0x04, 0x00}, {0x06, 0x01, 0x04, 0x00}, + {0x0a, 0x01, 0x04, 0x00}, {0x0f, 0x01, 0x04, 0x00}, + {0x18, 0x01, 0x04, 0x00}, {0x1f, 0x01, 0x04, 0x00}, + {0x29, 0x01, 0x04, 0x00}, {0x38, 0x01, 0x04, 0x01}, + {0x03, 0x01, 0x05, 0x00}, {0x06, 0x01, 0x05, 0x00}, + {0x0a, 0x01, 0x05, 0x00}, {0x0f, 0x01, 0x05, 0x00}, + {0x18, 0x01, 0x05, 0x00}, {0x1f, 0x01, 0x05, 0x00}, + {0x29, 0x01, 0x05, 0x00}, {0x38, 0x01, 0x05, 0x01} + }, + /* 230 */ + { + {0x03, 0x01, 0x06, 0x00}, {0x06, 0x01, 0x06, 0x00}, + {0x0a, 0x01, 0x06, 0x00}, {0x0f, 0x01, 0x06, 0x00}, + {0x18, 0x01, 0x06, 0x00}, {0x1f, 0x01, 0x06, 0x00}, + {0x29, 0x01, 0x06, 0x00}, {0x38, 0x01, 0x06, 0x01}, + {0x03, 0x01, 0x07, 0x00}, {0x06, 0x01, 0x07, 0x00}, + {0x0a, 0x01, 0x07, 0x00}, {0x0f, 0x01, 0x07, 0x00}, + {0x18, 0x01, 0x07, 0x00}, {0x1f, 0x01, 0x07, 0x00}, + {0x29, 0x01, 0x07, 0x00}, {0x38, 0x01, 0x07, 0x01} + }, + { + {0x01, 0x01, 0x08, 0x00}, {0x16, 0x01, 0x08, 0x01}, + {0x01, 0x01, 0x0b, 0x00}, {0x16, 0x01, 0x0b, 0x01}, + {0x01, 0x01, 0x0c, 0x00}, {0x16, 0x01, 0x0c, 0x01}, + {0x01, 0x01, 0x0e, 0x00}, {0x16, 0x01, 0x0e, 0x01}, + {0x01, 0x01, 0x0f, 0x00}, {0x16, 0x01, 0x0f, 0x01}, + {0x01, 0x01, 0x10, 0x00}, {0x16, 0x01, 0x10, 0x01}, + {0x01, 0x01, 0x11, 0x00}, {0x16, 0x01, 0x11, 0x01}, + {0x01, 0x01, 0x12, 0x00}, {0x16, 0x01, 0x12, 0x01} + }, + { + {0x02, 0x01, 0x08, 0x00}, {0x09, 0x01, 0x08, 0x00}, + {0x17, 0x01, 0x08, 0x00}, {0x28, 0x01, 0x08, 0x01}, + {0x02, 0x01, 0x0b, 0x00}, {0x09, 0x01, 0x0b, 0x00}, + {0x17, 0x01, 0x0b, 0x00}, {0x28, 0x01, 0x0b, 0x01}, + {0x02, 0x01, 0x0c, 0x00}, {0x09, 0x01, 0x0c, 0x00}, + {0x17, 0x01, 0x0c, 0x00}, {0x28, 0x01, 0x0c, 0x01}, + {0x02, 0x01, 0x0e, 0x00}, {0x09, 0x01, 0x0e, 0x00}, + {0x17, 0x01, 0x0e, 0x00}, {0x28, 0x01, 0x0e, 0x01} + }, + { + {0x03, 0x01, 0x08, 0x00}, {0x06, 0x01, 0x08, 0x00}, + {0x0a, 0x01, 0x08, 0x00}, {0x0f, 0x01, 0x08, 0x00}, + {0x18, 0x01, 0x08, 0x00}, {0x1f, 0x01, 0x08, 0x00}, + {0x29, 0x01, 0x08, 0x00}, {0x38, 0x01, 0x08, 0x01}, + {0x03, 0x01, 0x0b, 0x00}, {0x06, 0x01, 0x0b, 0x00}, + {0x0a, 0x01, 0x0b, 0x00}, {0x0f, 0x01, 0x0b, 0x00}, + {0x18, 0x01, 0x0b, 0x00}, {0x1f, 0x01, 0x0b, 0x00}, + {0x29, 0x01, 0x0b, 0x00}, {0x38, 0x01, 0x0b, 0x01} + }, + { + {0x03, 0x01, 0x0c, 0x00}, {0x06, 0x01, 0x0c, 0x00}, + {0x0a, 0x01, 0x0c, 0x00}, {0x0f, 0x01, 0x0c, 0x00}, + {0x18, 0x01, 0x0c, 0x00}, {0x1f, 0x01, 0x0c, 0x00}, + {0x29, 0x01, 0x0c, 0x00}, {0x38, 0x01, 0x0c, 0x01}, + {0x03, 0x01, 0x0e, 0x00}, {0x06, 0x01, 0x0e, 0x00}, + {0x0a, 0x01, 0x0e, 0x00}, {0x0f, 0x01, 0x0e, 0x00}, + {0x18, 0x01, 0x0e, 0x00}, {0x1f, 0x01, 0x0e, 0x00}, + {0x29, 0x01, 0x0e, 0x00}, {0x38, 0x01, 0x0e, 0x01} + }, + /* 235 */ + { + {0x02, 0x01, 0x0f, 0x00}, {0x09, 0x01, 0x0f, 0x00}, + {0x17, 0x01, 0x0f, 0x00}, {0x28, 0x01, 0x0f, 0x01}, + {0x02, 0x01, 0x10, 0x00}, {0x09, 0x01, 0x10, 0x00}, + {0x17, 0x01, 0x10, 0x00}, {0x28, 0x01, 0x10, 0x01}, + {0x02, 0x01, 0x11, 0x00}, {0x09, 0x01, 0x11, 0x00}, + {0x17, 0x01, 0x11, 0x00}, {0x28, 0x01, 0x11, 0x01}, + {0x02, 0x01, 0x12, 0x00}, {0x09, 0x01, 0x12, 0x00}, + {0x17, 0x01, 0x12, 0x00}, {0x28, 0x01, 0x12, 0x01} + }, + { + {0x03, 0x01, 0x0f, 0x00}, {0x06, 0x01, 0x0f, 0x00}, + {0x0a, 0x01, 0x0f, 0x00}, {0x0f, 0x01, 0x0f, 0x00}, + {0x18, 0x01, 0x0f, 0x00}, {0x1f, 0x01, 0x0f, 0x00}, + {0x29, 0x01, 0x0f, 0x00}, {0x38, 0x01, 0x0f, 0x01}, + {0x03, 0x01, 0x10, 0x00}, {0x06, 0x01, 0x10, 0x00}, + {0x0a, 0x01, 0x10, 0x00}, {0x0f, 0x01, 0x10, 0x00}, + {0x18, 0x01, 0x10, 0x00}, {0x1f, 0x01, 0x10, 0x00}, + {0x29, 0x01, 0x10, 0x00}, {0x38, 0x01, 0x10, 0x01} + }, + { + {0x03, 0x01, 0x11, 0x00}, {0x06, 0x01, 0x11, 0x00}, + {0x0a, 0x01, 0x11, 0x00}, {0x0f, 0x01, 0x11, 0x00}, + {0x18, 0x01, 0x11, 0x00}, {0x1f, 0x01, 0x11, 0x00}, + {0x29, 0x01, 0x11, 0x00}, {0x38, 0x01, 0x11, 0x01}, + {0x03, 0x01, 0x12, 0x00}, {0x06, 0x01, 0x12, 0x00}, + {0x0a, 0x01, 0x12, 0x00}, {0x0f, 0x01, 0x12, 0x00}, + {0x18, 0x01, 0x12, 0x00}, {0x1f, 0x01, 0x12, 0x00}, + {0x29, 0x01, 0x12, 0x00}, {0x38, 0x01, 0x12, 0x01} + }, + { + {0x00, 0x01, 0x13, 0x01}, {0x00, 0x01, 0x14, 0x01}, + {0x00, 0x01, 0x15, 0x01}, {0x00, 0x01, 0x17, 0x01}, + {0x00, 0x01, 0x18, 0x01}, {0x00, 0x01, 0x19, 0x01}, + {0x00, 0x01, 0x1a, 0x01}, {0x00, 0x01, 0x1b, 0x01}, + {0x00, 0x01, 0x1c, 0x01}, {0x00, 0x01, 0x1d, 0x01}, + {0x00, 0x01, 0x1e, 0x01}, {0x00, 0x01, 0x1f, 0x01}, + {0x00, 0x01, 0x7f, 0x01}, {0x00, 0x01, 0xdc, 0x01}, + {0x00, 0x01, 0xf9, 0x01}, {0xfd, 0x00, 0x00, 0x01} + }, + { + {0x01, 0x01, 0x13, 0x00}, {0x16, 0x01, 0x13, 0x01}, + {0x01, 0x01, 0x14, 0x00}, {0x16, 0x01, 0x14, 0x01}, + {0x01, 0x01, 0x15, 0x00}, {0x16, 0x01, 0x15, 0x01}, + {0x01, 0x01, 0x17, 0x00}, {0x16, 0x01, 0x17, 0x01}, + {0x01, 0x01, 0x18, 0x00}, {0x16, 0x01, 0x18, 0x01}, + {0x01, 0x01, 0x19, 0x00}, {0x16, 0x01, 0x19, 0x01}, + {0x01, 0x01, 0x1a, 0x00}, {0x16, 0x01, 0x1a, 0x01}, + {0x01, 0x01, 0x1b, 0x00}, {0x16, 0x01, 0x1b, 0x01} + }, + /* 240 */ + { + {0x02, 0x01, 0x13, 0x00}, {0x09, 0x01, 0x13, 0x00}, + {0x17, 0x01, 0x13, 0x00}, {0x28, 0x01, 0x13, 0x01}, + {0x02, 0x01, 0x14, 0x00}, {0x09, 0x01, 0x14, 0x00}, + {0x17, 0x01, 0x14, 0x00}, {0x28, 0x01, 0x14, 0x01}, + {0x02, 0x01, 0x15, 0x00}, {0x09, 0x01, 0x15, 0x00}, + {0x17, 0x01, 0x15, 0x00}, {0x28, 0x01, 0x15, 0x01}, + {0x02, 0x01, 0x17, 0x00}, {0x09, 0x01, 0x17, 0x00}, + {0x17, 0x01, 0x17, 0x00}, {0x28, 0x01, 0x17, 0x01} + }, + { + {0x03, 0x01, 0x13, 0x00}, {0x06, 0x01, 0x13, 0x00}, + {0x0a, 0x01, 0x13, 0x00}, {0x0f, 0x01, 0x13, 0x00}, + {0x18, 0x01, 0x13, 0x00}, {0x1f, 0x01, 0x13, 0x00}, + {0x29, 0x01, 0x13, 0x00}, {0x38, 0x01, 0x13, 0x01}, + {0x03, 0x01, 0x14, 0x00}, {0x06, 0x01, 0x14, 0x00}, + {0x0a, 0x01, 0x14, 0x00}, {0x0f, 0x01, 0x14, 0x00}, + {0x18, 0x01, 0x14, 0x00}, {0x1f, 0x01, 0x14, 0x00}, + {0x29, 0x01, 0x14, 0x00}, {0x38, 0x01, 0x14, 0x01} + }, + { + {0x03, 0x01, 0x15, 0x00}, {0x06, 0x01, 0x15, 0x00}, + {0x0a, 0x01, 0x15, 0x00}, {0x0f, 0x01, 0x15, 0x00}, + {0x18, 0x01, 0x15, 0x00}, {0x1f, 0x01, 0x15, 0x00}, + {0x29, 0x01, 0x15, 0x00}, {0x38, 0x01, 0x15, 0x01}, + {0x03, 0x01, 0x17, 0x00}, {0x06, 0x01, 0x17, 0x00}, + {0x0a, 0x01, 0x17, 0x00}, {0x0f, 0x01, 0x17, 0x00}, + {0x18, 0x01, 0x17, 0x00}, {0x1f, 0x01, 0x17, 0x00}, + {0x29, 0x01, 0x17, 0x00}, {0x38, 0x01, 0x17, 0x01} + }, + { + {0x02, 0x01, 0x18, 0x00}, {0x09, 0x01, 0x18, 0x00}, + {0x17, 0x01, 0x18, 0x00}, {0x28, 0x01, 0x18, 0x01}, + {0x02, 0x01, 0x19, 0x00}, {0x09, 0x01, 0x19, 0x00}, + {0x17, 0x01, 0x19, 0x00}, {0x28, 0x01, 0x19, 0x01}, + {0x02, 0x01, 0x1a, 0x00}, {0x09, 0x01, 0x1a, 0x00}, + {0x17, 0x01, 0x1a, 0x00}, {0x28, 0x01, 0x1a, 0x01}, + {0x02, 0x01, 0x1b, 0x00}, {0x09, 0x01, 0x1b, 0x00}, + {0x17, 0x01, 0x1b, 0x00}, {0x28, 0x01, 0x1b, 0x01} + }, + { + {0x03, 0x01, 0x18, 0x00}, {0x06, 0x01, 0x18, 0x00}, + {0x0a, 0x01, 0x18, 0x00}, {0x0f, 0x01, 0x18, 0x00}, + {0x18, 0x01, 0x18, 0x00}, {0x1f, 0x01, 0x18, 0x00}, + {0x29, 0x01, 0x18, 0x00}, {0x38, 0x01, 0x18, 0x01}, + {0x03, 0x01, 0x19, 0x00}, {0x06, 0x01, 0x19, 0x00}, + {0x0a, 0x01, 0x19, 0x00}, {0x0f, 0x01, 0x19, 0x00}, + {0x18, 0x01, 0x19, 0x00}, {0x1f, 0x01, 0x19, 0x00}, + {0x29, 0x01, 0x19, 0x00}, {0x38, 0x01, 0x19, 0x01} + }, + /* 245 */ + { + {0x03, 0x01, 0x1a, 0x00}, {0x06, 0x01, 0x1a, 0x00}, + {0x0a, 0x01, 0x1a, 0x00}, {0x0f, 0x01, 0x1a, 0x00}, + {0x18, 0x01, 0x1a, 0x00}, {0x1f, 0x01, 0x1a, 0x00}, + {0x29, 0x01, 0x1a, 0x00}, {0x38, 0x01, 0x1a, 0x01}, + {0x03, 0x01, 0x1b, 0x00}, {0x06, 0x01, 0x1b, 0x00}, + {0x0a, 0x01, 0x1b, 0x00}, {0x0f, 0x01, 0x1b, 0x00}, + {0x18, 0x01, 0x1b, 0x00}, {0x1f, 0x01, 0x1b, 0x00}, + {0x29, 0x01, 0x1b, 0x00}, {0x38, 0x01, 0x1b, 0x01} + }, + { + {0x01, 0x01, 0x1c, 0x00}, {0x16, 0x01, 0x1c, 0x01}, + {0x01, 0x01, 0x1d, 0x00}, {0x16, 0x01, 0x1d, 0x01}, + {0x01, 0x01, 0x1e, 0x00}, {0x16, 0x01, 0x1e, 0x01}, + {0x01, 0x01, 0x1f, 0x00}, {0x16, 0x01, 0x1f, 0x01}, + {0x01, 0x01, 0x7f, 0x00}, {0x16, 0x01, 0x7f, 0x01}, + {0x01, 0x01, 0xdc, 0x00}, {0x16, 0x01, 0xdc, 0x01}, + {0x01, 0x01, 0xf9, 0x00}, {0x16, 0x01, 0xf9, 0x01}, + {0xfe, 0x00, 0x00, 0x00}, {0xff, 0x00, 0x00, 0x01} + }, + { + {0x02, 0x01, 0x1c, 0x00}, {0x09, 0x01, 0x1c, 0x00}, + {0x17, 0x01, 0x1c, 0x00}, {0x28, 0x01, 0x1c, 0x01}, + {0x02, 0x01, 0x1d, 0x00}, {0x09, 0x01, 0x1d, 0x00}, + {0x17, 0x01, 0x1d, 0x00}, {0x28, 0x01, 0x1d, 0x01}, + {0x02, 0x01, 0x1e, 0x00}, {0x09, 0x01, 0x1e, 0x00}, + {0x17, 0x01, 0x1e, 0x00}, {0x28, 0x01, 0x1e, 0x01}, + {0x02, 0x01, 0x1f, 0x00}, {0x09, 0x01, 0x1f, 0x00}, + {0x17, 0x01, 0x1f, 0x00}, {0x28, 0x01, 0x1f, 0x01} + }, + { + {0x03, 0x01, 0x1c, 0x00}, {0x06, 0x01, 0x1c, 0x00}, + {0x0a, 0x01, 0x1c, 0x00}, {0x0f, 0x01, 0x1c, 0x00}, + {0x18, 0x01, 0x1c, 0x00}, {0x1f, 0x01, 0x1c, 0x00}, + {0x29, 0x01, 0x1c, 0x00}, {0x38, 0x01, 0x1c, 0x01}, + {0x03, 0x01, 0x1d, 0x00}, {0x06, 0x01, 0x1d, 0x00}, + {0x0a, 0x01, 0x1d, 0x00}, {0x0f, 0x01, 0x1d, 0x00}, + {0x18, 0x01, 0x1d, 0x00}, {0x1f, 0x01, 0x1d, 0x00}, + {0x29, 0x01, 0x1d, 0x00}, {0x38, 0x01, 0x1d, 0x01} + }, + { + {0x03, 0x01, 0x1e, 0x00}, {0x06, 0x01, 0x1e, 0x00}, + {0x0a, 0x01, 0x1e, 0x00}, {0x0f, 0x01, 0x1e, 0x00}, + {0x18, 0x01, 0x1e, 0x00}, {0x1f, 0x01, 0x1e, 0x00}, + {0x29, 0x01, 0x1e, 0x00}, {0x38, 0x01, 0x1e, 0x01}, + {0x03, 0x01, 0x1f, 0x00}, {0x06, 0x01, 0x1f, 0x00}, + {0x0a, 0x01, 0x1f, 0x00}, {0x0f, 0x01, 0x1f, 0x00}, + {0x18, 0x01, 0x1f, 0x00}, {0x1f, 0x01, 0x1f, 0x00}, + {0x29, 0x01, 0x1f, 0x00}, {0x38, 0x01, 0x1f, 0x01} + }, + /* 250 */ + { + {0x02, 0x01, 0x7f, 0x00}, {0x09, 0x01, 0x7f, 0x00}, + {0x17, 0x01, 0x7f, 0x00}, {0x28, 0x01, 0x7f, 0x01}, + {0x02, 0x01, 0xdc, 0x00}, {0x09, 0x01, 0xdc, 0x00}, + {0x17, 0x01, 0xdc, 0x00}, {0x28, 0x01, 0xdc, 0x01}, + {0x02, 0x01, 0xf9, 0x00}, {0x09, 0x01, 0xf9, 0x00}, + {0x17, 0x01, 0xf9, 0x00}, {0x28, 0x01, 0xf9, 0x01}, + {0x00, 0x01, 0x0a, 0x01}, {0x00, 0x01, 0x0d, 0x01}, + {0x00, 0x01, 0x16, 0x01}, {0xfa, 0x00, 0x00, 0x00} + }, + { + {0x03, 0x01, 0x7f, 0x00}, {0x06, 0x01, 0x7f, 0x00}, + {0x0a, 0x01, 0x7f, 0x00}, {0x0f, 0x01, 0x7f, 0x00}, + {0x18, 0x01, 0x7f, 0x00}, {0x1f, 0x01, 0x7f, 0x00}, + {0x29, 0x01, 0x7f, 0x00}, {0x38, 0x01, 0x7f, 0x01}, + {0x03, 0x01, 0xdc, 0x00}, {0x06, 0x01, 0xdc, 0x00}, + {0x0a, 0x01, 0xdc, 0x00}, {0x0f, 0x01, 0xdc, 0x00}, + {0x18, 0x01, 0xdc, 0x00}, {0x1f, 0x01, 0xdc, 0x00}, + {0x29, 0x01, 0xdc, 0x00}, {0x38, 0x01, 0xdc, 0x01} + }, + { + {0x03, 0x01, 0xf9, 0x00}, {0x06, 0x01, 0xf9, 0x00}, + {0x0a, 0x01, 0xf9, 0x00}, {0x0f, 0x01, 0xf9, 0x00}, + {0x18, 0x01, 0xf9, 0x00}, {0x1f, 0x01, 0xf9, 0x00}, + {0x29, 0x01, 0xf9, 0x00}, {0x38, 0x01, 0xf9, 0x01}, + {0x01, 0x01, 0x0a, 0x00}, {0x16, 0x01, 0x0a, 0x01}, + {0x01, 0x01, 0x0d, 0x00}, {0x16, 0x01, 0x0d, 0x01}, + {0x01, 0x01, 0x16, 0x00}, {0x16, 0x01, 0x16, 0x01}, + {0xfc, 0x00, 0x00, 0x00}, {0xfc, 0x00, 0x00, 0x00} + }, + { + {0x02, 0x01, 0x0a, 0x00}, {0x09, 0x01, 0x0a, 0x00}, + {0x17, 0x01, 0x0a, 0x00}, {0x28, 0x01, 0x0a, 0x01}, + {0x02, 0x01, 0x0d, 0x00}, {0x09, 0x01, 0x0d, 0x00}, + {0x17, 0x01, 0x0d, 0x00}, {0x28, 0x01, 0x0d, 0x01}, + {0x02, 0x01, 0x16, 0x00}, {0x09, 0x01, 0x16, 0x00}, + {0x17, 0x01, 0x16, 0x00}, {0x28, 0x01, 0x16, 0x01}, + {0xfd, 0x00, 0x00, 0x00}, {0xfd, 0x00, 0x00, 0x00}, + {0xfd, 0x00, 0x00, 0x00}, {0xfd, 0x00, 0x00, 0x00} + }, + { + {0x03, 0x01, 0x0a, 0x00}, {0x06, 0x01, 0x0a, 0x00}, + {0x0a, 0x01, 0x0a, 0x00}, {0x0f, 0x01, 0x0a, 0x00}, + {0x18, 0x01, 0x0a, 0x00}, {0x1f, 0x01, 0x0a, 0x00}, + {0x29, 0x01, 0x0a, 0x00}, {0x38, 0x01, 0x0a, 0x01}, + {0x03, 0x01, 0x0d, 0x00}, {0x06, 0x01, 0x0d, 0x00}, + {0x0a, 0x01, 0x0d, 0x00}, {0x0f, 0x01, 0x0d, 0x00}, + {0x18, 0x01, 0x0d, 0x00}, {0x1f, 0x01, 0x0d, 0x00}, + {0x29, 0x01, 0x0d, 0x00}, {0x38, 0x01, 0x0d, 0x01} + }, + /* 255 */ + { + {0x03, 0x01, 0x16, 0x00}, {0x06, 0x01, 0x16, 0x00}, + {0x0a, 0x01, 0x16, 0x00}, {0x0f, 0x01, 0x16, 0x00}, + {0x18, 0x01, 0x16, 0x00}, {0x1f, 0x01, 0x16, 0x00}, + {0x29, 0x01, 0x16, 0x00}, {0x38, 0x01, 0x16, 0x01}, + {0xff, 0x00, 0x00, 0x00}, {0xff, 0x00, 0x00, 0x00}, + {0xff, 0x00, 0x00, 0x00}, {0xff, 0x00, 0x00, 0x00}, + {0xff, 0x00, 0x00, 0x00}, {0xff, 0x00, 0x00, 0x00}, + {0xff, 0x00, 0x00, 0x00}, {0xff, 0x00, 0x00, 0x00} + } +}; + + +ngx_int_t +ngx_http_v2_huff_decode(u_char *state, u_char *src, size_t len, u_char **dst, + ngx_uint_t last, ngx_log_t *log) +{ + u_char *end, ch, ending; + + ch = 0; + ending = 1; + + end = src + len; + + while (src != end) { + ch = *src++; + + if (ngx_http_v2_huff_decode_bits(state, &ending, ch >> 4, dst) + != NGX_OK) + { + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, log, 0, + "http2 huffman decoding error at state %d: " + "bad code 0x%Xd", *state, ch >> 4); + + return NGX_ERROR; + } + + if (ngx_http_v2_huff_decode_bits(state, &ending, ch & 0xf, dst) + != NGX_OK) + { + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, log, 0, + "http2 huffman decoding error at state %d: " + "bad code 0x%Xd", *state, ch & 0xf); + + return NGX_ERROR; + } + } + + if (last) { + if (!ending) { + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, + "http2 huffman decoding error: " + "incomplete code 0x%Xd", ch); + + return NGX_ERROR; + } + + *state = 0; + } + + return NGX_OK; +} + + + +static ngx_inline ngx_int_t +ngx_http_v2_huff_decode_bits(u_char *state, u_char *ending, ngx_uint_t bits, + u_char **dst) +{ + ngx_http_v2_huff_decode_code_t code; + + code = ngx_http_v2_huff_decode_codes[*state][bits]; + + if (code.next == *state) { + return NGX_ERROR; + } + + if (code.emit) { + *(*dst)++ = code.sym; + } + + *ending = code.ending; + *state = code.next; + + return NGX_OK; +} diff --git a/src/http/v2/ngx_http_v2_huff_encode.c b/src/http/v2/ngx_http_v2_huff_encode.c new file mode 100644 index 0000000..6c412cf --- /dev/null +++ b/src/http/v2/ngx_http_v2_huff_encode.c @@ -0,0 +1,10 @@ + +/* + * Copyright (C) Nginx, Inc. + * Copyright (C) Valentin V. Bartenev + */ + + +#include +#include +#include diff --git a/src/http/v2/ngx_http_v2_module.c b/src/http/v2/ngx_http_v2_module.c new file mode 100644 index 0000000..d99ac30 --- /dev/null +++ b/src/http/v2/ngx_http_v2_module.c @@ -0,0 +1,469 @@ + +/* + * Copyright (C) Nginx, Inc. + * Copyright (C) Valentin V. Bartenev + */ + + +#include +#include +#include +#include + + +static ngx_int_t ngx_http_v2_add_variables(ngx_conf_t *cf); + +static ngx_int_t ngx_http_v2_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); + +static ngx_int_t ngx_http_v2_module_init(ngx_cycle_t *cycle); + +static void *ngx_http_v2_create_main_conf(ngx_conf_t *cf); +static char *ngx_http_v2_init_main_conf(ngx_conf_t *cf, void *conf); +static void *ngx_http_v2_create_srv_conf(ngx_conf_t *cf); +static char *ngx_http_v2_merge_srv_conf(ngx_conf_t *cf, void *parent, + void *child); +static void *ngx_http_v2_create_loc_conf(ngx_conf_t *cf); +static char *ngx_http_v2_merge_loc_conf(ngx_conf_t *cf, void *parent, + void *child); + +static char *ngx_http_v2_recv_buffer_size(ngx_conf_t *cf, void *post, + void *data); +static char *ngx_http_v2_pool_size(ngx_conf_t *cf, void *post, void *data); +static char *ngx_http_v2_streams_index_mask(ngx_conf_t *cf, void *post, + void *data); +static char *ngx_http_v2_chunk_size(ngx_conf_t *cf, void *post, void *data); +static char *ngx_http_v2_spdy_deprecated(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); + + +static ngx_conf_post_t ngx_http_v2_recv_buffer_size_post = + { ngx_http_v2_recv_buffer_size }; +static ngx_conf_post_t ngx_http_v2_pool_size_post = + { ngx_http_v2_pool_size }; +static ngx_conf_post_t ngx_http_v2_streams_index_mask_post = + { ngx_http_v2_streams_index_mask }; +static ngx_conf_post_t ngx_http_v2_chunk_size_post = + { ngx_http_v2_chunk_size }; + + +static ngx_command_t ngx_http_v2_commands[] = { + + { ngx_string("http2_recv_buffer_size"), + NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_HTTP_MAIN_CONF_OFFSET, + offsetof(ngx_http_v2_main_conf_t, recv_buffer_size), + &ngx_http_v2_recv_buffer_size_post }, + + { ngx_string("http2_pool_size"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_http_v2_srv_conf_t, pool_size), + &ngx_http_v2_pool_size_post }, + + { ngx_string("http2_max_concurrent_streams"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_http_v2_srv_conf_t, concurrent_streams), + NULL }, + + { ngx_string("http2_max_field_size"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_http_v2_srv_conf_t, max_field_size), + NULL }, + + { ngx_string("http2_max_header_size"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_http_v2_srv_conf_t, max_header_size), + NULL }, + + { ngx_string("http2_streams_index_size"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_http_v2_srv_conf_t, streams_index_mask), + &ngx_http_v2_streams_index_mask_post }, + + { ngx_string("http2_recv_timeout"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_http_v2_srv_conf_t, recv_timeout), + NULL }, + + { ngx_string("http2_idle_timeout"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_http_v2_srv_conf_t, idle_timeout), + NULL }, + + { ngx_string("http2_chunk_size"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_v2_loc_conf_t, chunk_size), + &ngx_http_v2_chunk_size_post }, + + { ngx_string("spdy_recv_buffer_size"), + NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, + ngx_http_v2_spdy_deprecated, + NGX_HTTP_MAIN_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("spdy_pool_size"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_http_v2_spdy_deprecated, + NGX_HTTP_SRV_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("spdy_max_concurrent_streams"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_http_v2_spdy_deprecated, + NGX_HTTP_SRV_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("spdy_streams_index_size"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_http_v2_spdy_deprecated, + NGX_HTTP_SRV_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("spdy_recv_timeout"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_http_v2_spdy_deprecated, + NGX_HTTP_SRV_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("spdy_keepalive_timeout"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_http_v2_spdy_deprecated, + NGX_HTTP_SRV_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("spdy_headers_comp"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_http_v2_spdy_deprecated, + NGX_HTTP_SRV_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("spdy_chunk_size"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_http_v2_spdy_deprecated, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + NULL }, + + ngx_null_command +}; + + +static ngx_http_module_t ngx_http_v2_module_ctx = { + ngx_http_v2_add_variables, /* preconfiguration */ + NULL, /* postconfiguration */ + + ngx_http_v2_create_main_conf, /* create main configuration */ + ngx_http_v2_init_main_conf, /* init main configuration */ + + ngx_http_v2_create_srv_conf, /* create server configuration */ + ngx_http_v2_merge_srv_conf, /* merge server configuration */ + + ngx_http_v2_create_loc_conf, /* create location configuration */ + ngx_http_v2_merge_loc_conf /* merge location configuration */ +}; + + +ngx_module_t ngx_http_v2_module = { + NGX_MODULE_V1, + &ngx_http_v2_module_ctx, /* module context */ + ngx_http_v2_commands, /* module directives */ + NGX_HTTP_MODULE, /* module type */ + NULL, /* init master */ + ngx_http_v2_module_init, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + + +static ngx_http_variable_t ngx_http_v2_vars[] = { + + { ngx_string("http2"), NULL, + ngx_http_v2_variable, 0, 0, 0 }, + + { ngx_null_string, NULL, NULL, 0, 0, 0 } +}; + + +static ngx_int_t +ngx_http_v2_add_variables(ngx_conf_t *cf) +{ + ngx_http_variable_t *var, *v; + + for (v = ngx_http_v2_vars; v->name.len; v++) { + var = ngx_http_add_variable(cf, &v->name, v->flags); + if (var == NULL) { + return NGX_ERROR; + } + + var->get_handler = v->get_handler; + var->data = v->data; + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_v2_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + + if (r->stream) { +#if (NGX_HTTP_SSL) + + if (r->connection->ssl) { + v->len = sizeof("h2") - 1; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = (u_char *) "h2"; + + return NGX_OK; + } + +#endif + v->len = sizeof("h2c") - 1; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = (u_char *) "h2c"; + + return NGX_OK; + } + + *v = ngx_http_variable_null_value; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_v2_module_init(ngx_cycle_t *cycle) +{ + return NGX_OK; +} + + +static void * +ngx_http_v2_create_main_conf(ngx_conf_t *cf) +{ + ngx_http_v2_main_conf_t *h2mcf; + + h2mcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_v2_main_conf_t)); + if (h2mcf == NULL) { + return NULL; + } + + h2mcf->recv_buffer_size = NGX_CONF_UNSET_SIZE; + + return h2mcf; +} + + +static char * +ngx_http_v2_init_main_conf(ngx_conf_t *cf, void *conf) +{ + ngx_http_v2_main_conf_t *h2mcf = conf; + + ngx_conf_init_size_value(h2mcf->recv_buffer_size, 256 * 1024); + + return NGX_CONF_OK; +} + + +static void * +ngx_http_v2_create_srv_conf(ngx_conf_t *cf) +{ + ngx_http_v2_srv_conf_t *h2scf; + + h2scf = ngx_pcalloc(cf->pool, sizeof(ngx_http_v2_srv_conf_t)); + if (h2scf == NULL) { + return NULL; + } + + h2scf->pool_size = NGX_CONF_UNSET_SIZE; + + h2scf->concurrent_streams = NGX_CONF_UNSET_UINT; + + h2scf->max_field_size = NGX_CONF_UNSET_SIZE; + h2scf->max_header_size = NGX_CONF_UNSET_SIZE; + + h2scf->streams_index_mask = NGX_CONF_UNSET_UINT; + + h2scf->recv_timeout = NGX_CONF_UNSET_MSEC; + h2scf->idle_timeout = NGX_CONF_UNSET_MSEC; + + return h2scf; +} + + +static char * +ngx_http_v2_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) +{ + ngx_http_v2_srv_conf_t *prev = parent; + ngx_http_v2_srv_conf_t *conf = child; + + ngx_conf_merge_size_value(conf->pool_size, prev->pool_size, 4096); + + ngx_conf_merge_uint_value(conf->concurrent_streams, + prev->concurrent_streams, 128); + + ngx_conf_merge_size_value(conf->max_field_size, prev->max_field_size, + 4096); + ngx_conf_merge_size_value(conf->max_header_size, prev->max_header_size, + 16384); + + ngx_conf_merge_uint_value(conf->streams_index_mask, + prev->streams_index_mask, 32 - 1); + + ngx_conf_merge_msec_value(conf->recv_timeout, + prev->recv_timeout, 30000); + ngx_conf_merge_msec_value(conf->idle_timeout, + prev->idle_timeout, 180000); + + return NGX_CONF_OK; +} + + +static void * +ngx_http_v2_create_loc_conf(ngx_conf_t *cf) +{ + ngx_http_v2_loc_conf_t *h2lcf; + + h2lcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_v2_loc_conf_t)); + if (h2lcf == NULL) { + return NULL; + } + + h2lcf->chunk_size = NGX_CONF_UNSET_SIZE; + + return h2lcf; +} + + +static char * +ngx_http_v2_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) +{ + ngx_http_v2_loc_conf_t *prev = parent; + ngx_http_v2_loc_conf_t *conf = child; + + ngx_conf_merge_size_value(conf->chunk_size, prev->chunk_size, 8 * 1024); + + return NGX_CONF_OK; +} + + +static char * +ngx_http_v2_recv_buffer_size(ngx_conf_t *cf, void *post, void *data) +{ + size_t *sp = data; + + if (*sp <= 2 * NGX_HTTP_V2_STATE_BUFFER_SIZE) { + return "value is too small"; + } + + return NGX_CONF_OK; +} + + +static char * +ngx_http_v2_pool_size(ngx_conf_t *cf, void *post, void *data) +{ + size_t *sp = data; + + if (*sp < NGX_MIN_POOL_SIZE) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "the pool size must be no less than %uz", + NGX_MIN_POOL_SIZE); + + return NGX_CONF_ERROR; + } + + if (*sp % NGX_POOL_ALIGNMENT) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "the pool size must be a multiple of %uz", + NGX_POOL_ALIGNMENT); + + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; +} + + +static char * +ngx_http_v2_streams_index_mask(ngx_conf_t *cf, void *post, void *data) +{ + ngx_uint_t *np = data; + + ngx_uint_t mask; + + mask = *np - 1; + + if (*np == 0 || (*np & mask)) { + return "must be a power of two"; + } + + *np = mask; + + return NGX_CONF_OK; +} + + +static char * +ngx_http_v2_chunk_size(ngx_conf_t *cf, void *post, void *data) +{ + size_t *sp = data; + + if (*sp == 0) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "the http2 chunk size cannot be zero"); + + return NGX_CONF_ERROR; + } + + if (*sp > NGX_HTTP_V2_MAX_FRAME_SIZE) { + *sp = NGX_HTTP_V2_MAX_FRAME_SIZE; + } + + return NGX_CONF_OK; +} + + +static char * +ngx_http_v2_spdy_deprecated(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, + "invalid directive \"%V\": ngx_http_spdy_module " + "was superseded by ngx_http_v2_module", &cmd->name); + + return NGX_CONF_OK; +} diff --git a/src/http/ngx_http_spdy_module.h b/src/http/v2/ngx_http_v2_module.h similarity index 58% rename from src/http/ngx_http_spdy_module.h rename to src/http/v2/ngx_http_v2_module.h index 5242322..95cc7d8 100644 --- a/src/http/ngx_http_spdy_module.h +++ b/src/http/v2/ngx_http_v2_module.h @@ -5,8 +5,8 @@ */ -#ifndef _NGX_HTTP_SPDY_MODULE_H_INCLUDED_ -#define _NGX_HTTP_SPDY_MODULE_H_INCLUDED_ +#ifndef _NGX_HTTP_V2_MODULE_H_INCLUDED_ +#define _NGX_HTTP_V2_MODULE_H_INCLUDED_ #include @@ -17,25 +17,26 @@ typedef struct { size_t recv_buffer_size; u_char *recv_buffer; -} ngx_http_spdy_main_conf_t; +} ngx_http_v2_main_conf_t; typedef struct { size_t pool_size; ngx_uint_t concurrent_streams; + size_t max_field_size; + size_t max_header_size; ngx_uint_t streams_index_mask; ngx_msec_t recv_timeout; - ngx_msec_t keepalive_timeout; - ngx_int_t headers_comp; -} ngx_http_spdy_srv_conf_t; + ngx_msec_t idle_timeout; +} ngx_http_v2_srv_conf_t; typedef struct { size_t chunk_size; -} ngx_http_spdy_loc_conf_t; +} ngx_http_v2_loc_conf_t; -extern ngx_module_t ngx_http_spdy_module; +extern ngx_module_t ngx_http_v2_module; -#endif /* _NGX_HTTP_SPDY_MODULE_H_INCLUDED_ */ +#endif /* _NGX_HTTP_V2_MODULE_H_INCLUDED_ */ diff --git a/src/http/v2/ngx_http_v2_table.c b/src/http/v2/ngx_http_v2_table.c new file mode 100644 index 0000000..a73748a --- /dev/null +++ b/src/http/v2/ngx_http_v2_table.c @@ -0,0 +1,349 @@ + +/* + * Copyright (C) Nginx, Inc. + * Copyright (C) Valentin V. Bartenev + */ + + +#include +#include +#include + + +#define NGX_HTTP_V2_TABLE_SIZE 4096 + + +static ngx_int_t ngx_http_v2_table_account(ngx_http_v2_connection_t *h2c, + size_t size); + + +static ngx_http_v2_header_t ngx_http_v2_static_table[] = { + { ngx_string(":authority"), ngx_string("") }, + { ngx_string(":method"), ngx_string("GET") }, + { ngx_string(":method"), ngx_string("POST") }, + { ngx_string(":path"), ngx_string("/") }, + { ngx_string(":path"), ngx_string("/index.html") }, + { ngx_string(":scheme"), ngx_string("http") }, + { ngx_string(":scheme"), ngx_string("https") }, + { ngx_string(":status"), ngx_string("200") }, + { ngx_string(":status"), ngx_string("204") }, + { ngx_string(":status"), ngx_string("206") }, + { ngx_string(":status"), ngx_string("304") }, + { ngx_string(":status"), ngx_string("400") }, + { ngx_string(":status"), ngx_string("404") }, + { ngx_string(":status"), ngx_string("500") }, + { ngx_string("accept-charset"), ngx_string("") }, + { ngx_string("accept-encoding"), ngx_string("gzip, deflate") }, + { ngx_string("accept-language"), ngx_string("") }, + { ngx_string("accept-ranges"), ngx_string("") }, + { ngx_string("accept"), ngx_string("") }, + { ngx_string("access-control-allow-origin"), ngx_string("") }, + { ngx_string("age"), ngx_string("") }, + { ngx_string("allow"), ngx_string("") }, + { ngx_string("authorization"), ngx_string("") }, + { ngx_string("cache-control"), ngx_string("") }, + { ngx_string("content-disposition"), ngx_string("") }, + { ngx_string("content-encoding"), ngx_string("") }, + { ngx_string("content-language"), ngx_string("") }, + { ngx_string("content-length"), ngx_string("") }, + { ngx_string("content-location"), ngx_string("") }, + { ngx_string("content-range"), ngx_string("") }, + { ngx_string("content-type"), ngx_string("") }, + { ngx_string("cookie"), ngx_string("") }, + { ngx_string("date"), ngx_string("") }, + { ngx_string("etag"), ngx_string("") }, + { ngx_string("expect"), ngx_string("") }, + { ngx_string("expires"), ngx_string("") }, + { ngx_string("from"), ngx_string("") }, + { ngx_string("host"), ngx_string("") }, + { ngx_string("if-match"), ngx_string("") }, + { ngx_string("if-modified-since"), ngx_string("") }, + { ngx_string("if-none-match"), ngx_string("") }, + { ngx_string("if-range"), ngx_string("") }, + { ngx_string("if-unmodified-since"), ngx_string("") }, + { ngx_string("last-modified"), ngx_string("") }, + { ngx_string("link"), ngx_string("") }, + { ngx_string("location"), ngx_string("") }, + { ngx_string("max-forwards"), ngx_string("") }, + { ngx_string("proxy-authenticate"), ngx_string("") }, + { ngx_string("proxy-authorization"), ngx_string("") }, + { ngx_string("range"), ngx_string("") }, + { ngx_string("referer"), ngx_string("") }, + { ngx_string("refresh"), ngx_string("") }, + { ngx_string("retry-after"), ngx_string("") }, + { ngx_string("server"), ngx_string("") }, + { ngx_string("set-cookie"), ngx_string("") }, + { ngx_string("strict-transport-security"), ngx_string("") }, + { ngx_string("transfer-encoding"), ngx_string("") }, + { ngx_string("user-agent"), ngx_string("") }, + { ngx_string("vary"), ngx_string("") }, + { ngx_string("via"), ngx_string("") }, + { ngx_string("www-authenticate"), ngx_string("") }, +}; + +#define NGX_HTTP_V2_STATIC_TABLE_ENTRIES \ + (sizeof(ngx_http_v2_static_table) \ + / sizeof(ngx_http_v2_header_t)) + + +ngx_int_t +ngx_http_v2_get_indexed_header(ngx_http_v2_connection_t *h2c, ngx_uint_t index, + ngx_uint_t name_only) +{ + u_char *p; + size_t rest; + ngx_http_v2_header_t *entry; + + if (index == 0) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent invalid hpack table index 0"); + return NGX_ERROR; + } + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "http2 get indexed %s: %ui", + name_only ? "header" : "header name", index); + + index--; + + if (index < NGX_HTTP_V2_STATIC_TABLE_ENTRIES) { + h2c->state.header = ngx_http_v2_static_table[index]; + return NGX_OK; + } + + index -= NGX_HTTP_V2_STATIC_TABLE_ENTRIES; + + if (index < h2c->hpack.added - h2c->hpack.deleted) { + index = (h2c->hpack.added - index - 1) % h2c->hpack.allocated; + entry = h2c->hpack.entries[index]; + + p = ngx_pnalloc(h2c->state.pool, entry->name.len + 1); + if (p == NULL) { + return NGX_ERROR; + } + + h2c->state.header.name.len = entry->name.len; + h2c->state.header.name.data = p; + + rest = h2c->hpack.storage + NGX_HTTP_V2_TABLE_SIZE - entry->name.data; + + if (entry->name.len > rest) { + p = ngx_cpymem(p, entry->name.data, rest); + p = ngx_cpymem(p, h2c->hpack.storage, entry->name.len - rest); + + } else { + p = ngx_cpymem(p, entry->name.data, entry->name.len); + } + + *p = '\0'; + + if (name_only) { + return NGX_OK; + } + + p = ngx_pnalloc(h2c->state.pool, entry->value.len + 1); + if (p == NULL) { + return NGX_ERROR; + } + + h2c->state.header.value.len = entry->value.len; + h2c->state.header.value.data = p; + + rest = h2c->hpack.storage + NGX_HTTP_V2_TABLE_SIZE - entry->value.data; + + if (entry->value.len > rest) { + p = ngx_cpymem(p, entry->value.data, rest); + p = ngx_cpymem(p, h2c->hpack.storage, entry->value.len - rest); + + } else { + p = ngx_cpymem(p, entry->value.data, entry->value.len); + } + + *p = '\0'; + + return NGX_OK; + } + + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent out of bound hpack table index: %ui", index); + + return NGX_ERROR; +} + + +ngx_int_t +ngx_http_v2_add_header(ngx_http_v2_connection_t *h2c, + ngx_http_v2_header_t *header) +{ + size_t avail; + ngx_uint_t index; + ngx_http_v2_header_t *entry, **entries; + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "http2 add header to hpack table: \"%V: %V\"", + &header->name, &header->value); + + if (h2c->hpack.entries == NULL) { + h2c->hpack.allocated = 64; + h2c->hpack.size = NGX_HTTP_V2_TABLE_SIZE; + h2c->hpack.free = NGX_HTTP_V2_TABLE_SIZE; + + h2c->hpack.entries = ngx_palloc(h2c->connection->pool, + sizeof(ngx_http_v2_header_t *) + * h2c->hpack.allocated); + if (h2c->hpack.entries == NULL) { + return NGX_ERROR; + } + + h2c->hpack.storage = ngx_palloc(h2c->connection->pool, + h2c->hpack.free); + if (h2c->hpack.storage == NULL) { + return NGX_ERROR; + } + + h2c->hpack.pos = h2c->hpack.storage; + } + + if (ngx_http_v2_table_account(h2c, header->name.len + header->value.len) + != NGX_OK) + { + return NGX_OK; + } + + if (h2c->hpack.reused == h2c->hpack.deleted) { + entry = ngx_palloc(h2c->connection->pool, sizeof(ngx_http_v2_header_t)); + if (entry == NULL) { + return NGX_ERROR; + } + + } else { + entry = h2c->hpack.entries[h2c->hpack.reused++ % h2c->hpack.allocated]; + } + + avail = h2c->hpack.storage + NGX_HTTP_V2_TABLE_SIZE - h2c->hpack.pos; + + entry->name.len = header->name.len; + entry->name.data = h2c->hpack.pos; + + if (avail >= header->name.len) { + h2c->hpack.pos = ngx_cpymem(h2c->hpack.pos, header->name.data, + header->name.len); + } else { + ngx_memcpy(h2c->hpack.pos, header->name.data, avail); + h2c->hpack.pos = ngx_cpymem(h2c->hpack.storage, + header->name.data + avail, + header->name.len - avail); + avail = NGX_HTTP_V2_TABLE_SIZE; + } + + avail -= header->name.len; + + entry->value.len = header->value.len; + entry->value.data = h2c->hpack.pos; + + if (avail >= header->value.len) { + h2c->hpack.pos = ngx_cpymem(h2c->hpack.pos, header->value.data, + header->value.len); + } else { + ngx_memcpy(h2c->hpack.pos, header->value.data, avail); + h2c->hpack.pos = ngx_cpymem(h2c->hpack.storage, + header->value.data + avail, + header->value.len - avail); + } + + if (h2c->hpack.allocated == h2c->hpack.added - h2c->hpack.deleted) { + + entries = ngx_palloc(h2c->connection->pool, + sizeof(ngx_http_v2_header_t *) + * (h2c->hpack.allocated + 64)); + if (entries == NULL) { + return NGX_ERROR; + } + + index = h2c->hpack.deleted % h2c->hpack.allocated; + + ngx_memcpy(entries, &h2c->hpack.entries[index], + (h2c->hpack.allocated - index) + * sizeof(ngx_http_v2_header_t *)); + + ngx_memcpy(&entries[h2c->hpack.allocated - index], h2c->hpack.entries, + index * sizeof(ngx_http_v2_header_t *)); + + (void) ngx_pfree(h2c->connection->pool, h2c->hpack.entries); + + h2c->hpack.entries = entries; + + h2c->hpack.added = h2c->hpack.allocated; + h2c->hpack.deleted = 0; + h2c->hpack.reused = 0; + h2c->hpack.allocated += 64; + } + + h2c->hpack.entries[h2c->hpack.added++ % h2c->hpack.allocated] = entry; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_v2_table_account(ngx_http_v2_connection_t *h2c, size_t size) +{ + ngx_http_v2_header_t *entry; + + size += 32; + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "http2 hpack table account: %uz free:%uz", + size, h2c->hpack.free); + + if (size <= h2c->hpack.free) { + h2c->hpack.free -= size; + return NGX_OK; + } + + if (size > h2c->hpack.size) { + h2c->hpack.deleted = h2c->hpack.added; + h2c->hpack.free = h2c->hpack.size; + return NGX_DECLINED; + } + + do { + entry = h2c->hpack.entries[h2c->hpack.deleted++ % h2c->hpack.allocated]; + h2c->hpack.free += 32 + entry->name.len + entry->value.len; + } while (size > h2c->hpack.free); + + h2c->hpack.free -= size; + + return NGX_OK; +} + + +ngx_int_t +ngx_http_v2_table_size(ngx_http_v2_connection_t *h2c, size_t size) +{ + ssize_t needed; + ngx_http_v2_header_t *entry; + + if (size > NGX_HTTP_V2_TABLE_SIZE) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent invalid table size update: %uz", size); + + return NGX_ERROR; + } + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "http2 new hpack table size: %uz was:%uz", + size, h2c->hpack.size); + + needed = h2c->hpack.size - size; + + while (needed > (ssize_t) h2c->hpack.free) { + entry = h2c->hpack.entries[h2c->hpack.deleted++ % h2c->hpack.allocated]; + h2c->hpack.free += 32 + entry->name.len + entry->value.len; + } + + h2c->hpack.size = size; + h2c->hpack.free -= needed; + + return NGX_OK; +} diff --git a/src/os/unix/ngx_files.c b/src/os/unix/ngx_files.c index 2a3ed2f..417b598 100644 --- a/src/os/unix/ngx_files.c +++ b/src/os/unix/ngx_files.c @@ -264,6 +264,7 @@ ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl, off_t offset, u_char *prev; size_t size; ssize_t total, n; + ngx_err_t err; ngx_array_t vec; struct iovec *iov, iovs[NGX_IOVS]; @@ -335,10 +336,20 @@ ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl, off_t offset, file->sys_offset = offset; } +eintr: + n = writev(file->fd, vec.elts, vec.nelts); if (n == -1) { - ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, + err = ngx_errno; + + if (err == NGX_EINTR) { + ngx_log_debug0(NGX_LOG_DEBUG_CORE, file->log, err, + "writev() was interrupted"); + goto eintr; + } + + ngx_log_error(NGX_LOG_CRIT, file->log, err, "writev() \"%s\" failed", file->name.data); return NGX_ERROR; } From 4e0f0048066088f11656d5764ebe8ca2f4b4d539 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Fri, 25 Sep 2015 14:03:48 +0300 Subject: [PATCH 009/600] New upstream release (1.9.5) --- debian/changelog | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/debian/changelog b/debian/changelog index 004eaa2..1fb0f6e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +nginx (1.9.5-1) UNRELEASED; urgency=medium + + [ Christos Trochalakis] + * New upstream release. + + -- Christos Trochalakis Fri, 25 Sep 2015 14:03:10 +0300 + nginx (1.9.4-1) unstable; urgency=medium [ Christos Trochalakis] From baf8feb207a5263be5260c2c5e2d70b958c9077a Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Wed, 30 Sep 2015 16:58:41 +0300 Subject: [PATCH 010/600] Enable http2 module --- debian/control | 6 +++--- debian/rules | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/debian/control b/debian/control index b3bfcc3..de705d4 100644 --- a/debian/control +++ b/debian/control @@ -98,7 +98,7 @@ Description: nginx web/proxy server (standard version) Referer, Rewrite, SCGI, Split Clients, UWSGI. . OPTIONAL HTTP MODULES: Addition, Auth Request, Charset, WebDAV, GeoIP, Gunzip, - Gzip, Gzip Precompression, Headers, Image Filter, Index, Log, Real IP, Spdy, + Gzip, Gzip Precompression, Headers, HTTP/2, Image Filter, Index, Log, Real IP, SSI, SSL, Stream, Stub Status, Substitution, Thread Pool, Upstream, User ID, XSLT. . @@ -185,8 +185,8 @@ Description: nginx web/proxy server (extended version) Referer, Rewrite, SCGI, Split Clients, UWSGI. . OPTIONAL HTTP MODULES: Addition, Auth Request, Charset, WebDAV, FLV, GeoIP, - Gunzip, Gzip, Gzip Precompression, Headers, Image Filter, Index, Log, MP4, - Embedded Perl, Random Index, Real IP, Secure Link, Spdy, SSI, SSL, Stream, + Gunzip, Gzip, Gzip Precompression, Headers, HTTP/2, Image Filter, Index, Log, + MP4, Embedded Perl, Random Index, Real IP, Secure Link, SSI, SSL, Stream, Stub Status, Substitution, Thread Pool, Upstream, User ID, XSLT. . MAIL MODULES: Mail Core, Auth HTTP, Proxy, SSL, IMAP, POP3, SMTP. diff --git a/debian/rules b/debian/rules index 34223d8..1cdef59 100755 --- a/debian/rules +++ b/debian/rules @@ -73,7 +73,7 @@ full_configure_flags := \ --with-http_gunzip_module \ --with-http_gzip_static_module \ --with-http_image_filter_module \ - --with-http_spdy_module \ + --with-http_v2_module \ --with-http_sub_module \ --with-http_xslt_module \ --with-stream \ @@ -100,7 +100,7 @@ extras_configure_flags := \ --with-http_perl_module \ --with-http_random_index_module \ --with-http_secure_link_module \ - --with-http_spdy_module \ + --with-http_v2_module \ --with-http_sub_module \ --with-http_xslt_module \ --with-mail \ From efe7d922f49e133d66031b58fedbf308690080f6 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Wed, 30 Sep 2015 16:50:59 +0300 Subject: [PATCH 011/600] Add a NEWS entry for http2 --- debian/nginx-common.NEWS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/debian/nginx-common.NEWS b/debian/nginx-common.NEWS index edd750f..161d061 100644 --- a/debian/nginx-common.NEWS +++ b/debian/nginx-common.NEWS @@ -1,3 +1,10 @@ +nginx-common (1.9.5-1) UNRELEASED; urgency=medium + + As of nginx 1.9.5 spdy has been replaced by the http2 module. Make sure to + replace "spdy" with "http2" in your config files. + + -- Christos Trochalakis Fri, 25 Sep 2015 14:06:28 +0300 + nginx-common (1.9.1-1) unstable; urgency=medium Starting with this release, we have enabled PIE build features which allows From 6a711b5bd6566b3723657c8e14e5de56079f7c94 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Tue, 3 Nov 2015 08:58:01 +0200 Subject: [PATCH 012/600] Imported Upstream version 1.9.6 --- CHANGES | 26 ++ CHANGES.ru | 27 ++ auto/endianness | 9 +- auto/types/uintptr_t | 9 +- src/core/nginx.c | 127 +++++---- src/core/nginx.h | 4 +- src/core/ngx_connection.c | 2 +- src/core/ngx_rwlock.c | 2 +- src/event/ngx_event.c | 9 + src/event/ngx_event_openssl.c | 25 +- src/event/ngx_event_openssl.h | 1 + src/http/ngx_http_core_module.c | 4 +- src/http/ngx_http_variables.c | 38 ++- src/http/v2/ngx_http_v2.c | 69 +++-- src/http/v2/ngx_http_v2.h | 3 +- src/http/v2/ngx_http_v2_filter_module.c | 352 ++++++++++++------------ src/stream/ngx_stream_proxy_module.c | 4 + 17 files changed, 413 insertions(+), 298 deletions(-) diff --git a/CHANGES b/CHANGES index 47d33a4..2b9809c 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,30 @@ +Changes with nginx 1.9.6 27 Oct 2015 + + *) Bugfix: a segmentation fault might occur in a worker process when + using HTTP/2. + Thanks to Piotr Sikora and Denis Andzakovic. + + *) Bugfix: the $server_protocol variable was empty when using HTTP/2. + + *) Bugfix: backend SSL connections in the stream module might be timed + out unexpectedly. + + *) Bugfix: a segmentation fault might occur in a worker process if + different ssl_session_cache settings were used in different virtual + servers. + + *) Bugfix: nginx/Windows could not be built with MinGW gcc; the bug had + appeared in 1.9.4. + Thanks to Kouhei Sutou. + + *) Bugfix: time was not updated when the timer_resolution directive was + used on Windows. + + *) Miscellaneous minor fixes and improvements. + Thanks to Markus Linnala, Kurtis Nusbaum and Piotr Sikora. + + Changes with nginx 1.9.5 22 Sep 2015 *) Feature: the ngx_http_v2_module (replaces ngx_http_spdy_module). diff --git a/CHANGES.ru b/CHANGES.ru index b95c33d..3e8c364 100644 --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,31 @@ +Изменения в nginx 1.9.6 27.10.2015 + + *) Исправление: при использовании HTTP/2 в рабочем процессе мог + произойти segmentation fault. + Спасибо Piotr Sikora и Denis Andzakovic. + + *) Исправление: при использовании HTTP/2 переменная $server_protocol + была пустой. + + *) Исправление: SSL-соединения к бэкендам в модуле stream могли + неожиданно завершаться по таймауту. + + *) Исправление: при использовании различных настроек ssl_session_cache в + разных виртуальных серверах в рабочем процессе мог произойти + segmentation fault. + + *) Исправление: nginx/Windows не собирался с MinGW gcc; ошибка появилась + в 1.9.4. + Спасибо Kouhei Sutou. + + *) Исправление: при использовании директивы timer_resolution на Windows + время не обновлялось. + + *) Незначительные исправления и улучшения. + Спасибо Markus Linnala, Kurtis Nusbaum и Piotr Sikora. + + Изменения в nginx 1.9.5 22.09.2015 *) Добавление: модуль ngx_http_v2_module (заменяет модуль diff --git a/auto/endianness b/auto/endianness index 93da2f8..70b0a10 100644 --- a/auto/endianness +++ b/auto/endianness @@ -4,8 +4,13 @@ echo $ngx_n "checking for system byte ordering ...$ngx_c" -echo >> $NGX_ERR -echo "checking for system byte ordering" >> $NGX_ERR + +cat << END >> $NGX_AUTOCONF_ERR + +---------------------------------------- +checking for system byte ordering + +END cat << END > $NGX_AUTOTEST.c diff --git a/auto/types/uintptr_t b/auto/types/uintptr_t index f3cdccb..2b7212e 100644 --- a/auto/types/uintptr_t +++ b/auto/types/uintptr_t @@ -4,8 +4,13 @@ echo $ngx_n "checking for uintptr_t ...$ngx_c" -echo >> $NGX_AUTOCONF_ERR -echo "checking for uintptr_t" >> $NGX_AUTOCONF_ERR + +cat << END >> $NGX_AUTOCONF_ERR + +---------------------------------------- +checking for uintptr_t + +END found=no diff --git a/src/core/nginx.c b/src/core/nginx.c index 3213527..3335587 100644 --- a/src/core/nginx.c +++ b/src/core/nginx.c @@ -10,6 +10,7 @@ #include +static void ngx_show_version_info(); static ngx_int_t ngx_add_inherited_sockets(ngx_cycle_t *cycle); static ngx_int_t ngx_get_options(int argc, char *const *argv); static ngx_int_t ngx_process_options(ngx_cycle_t *cycle); @@ -194,64 +195,7 @@ main(int argc, char *const *argv) } if (ngx_show_version) { - ngx_write_stderr("nginx version: " NGINX_VER_BUILD NGX_LINEFEED); - - if (ngx_show_help) { - ngx_write_stderr( - "Usage: nginx [-?hvVtTq] [-s signal] [-c filename] " - "[-p prefix] [-g directives]" NGX_LINEFEED - NGX_LINEFEED - "Options:" NGX_LINEFEED - " -?,-h : this help" NGX_LINEFEED - " -v : show version and exit" NGX_LINEFEED - " -V : show version and configure options then exit" - NGX_LINEFEED - " -t : test configuration and exit" NGX_LINEFEED - " -T : test configuration, dump it and exit" - NGX_LINEFEED - " -q : suppress non-error messages " - "during configuration testing" NGX_LINEFEED - " -s signal : send signal to a master process: " - "stop, quit, reopen, reload" NGX_LINEFEED -#ifdef NGX_PREFIX - " -p prefix : set prefix path (default: " - NGX_PREFIX ")" NGX_LINEFEED -#else - " -p prefix : set prefix path (default: NONE)" NGX_LINEFEED -#endif - " -c filename : set configuration file (default: " - NGX_CONF_PATH ")" NGX_LINEFEED - " -g directives : set global directives out of configuration " - "file" NGX_LINEFEED NGX_LINEFEED - ); - } - - if (ngx_show_configure) { - -#ifdef NGX_COMPILER - ngx_write_stderr("built by " NGX_COMPILER NGX_LINEFEED); -#endif - -#if (NGX_SSL) - if (SSLeay() == SSLEAY_VERSION_NUMBER) { - ngx_write_stderr("built with " OPENSSL_VERSION_TEXT - NGX_LINEFEED); - } else { - ngx_write_stderr("built with " OPENSSL_VERSION_TEXT - " (running with "); - ngx_write_stderr((char *) (uintptr_t) - SSLeay_version(SSLEAY_VERSION)); - ngx_write_stderr(")" NGX_LINEFEED); - } -#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME - ngx_write_stderr("TLS SNI support enabled" NGX_LINEFEED); -#else - ngx_write_stderr("TLS SNI support disabled" NGX_LINEFEED); -#endif -#endif - - ngx_write_stderr("configure arguments:" NGX_CONFIGURE NGX_LINEFEED); - } + ngx_show_version_info(); if (!ngx_test_config) { return 0; @@ -419,6 +363,69 @@ main(int argc, char *const *argv) } +static void +ngx_show_version_info() +{ + ngx_write_stderr("nginx version: " NGINX_VER_BUILD NGX_LINEFEED); + + if (ngx_show_help) { + ngx_write_stderr( + "Usage: nginx [-?hvVtTq] [-s signal] [-c filename] " + "[-p prefix] [-g directives]" NGX_LINEFEED + NGX_LINEFEED + "Options:" NGX_LINEFEED + " -?,-h : this help" NGX_LINEFEED + " -v : show version and exit" NGX_LINEFEED + " -V : show version and configure options then exit" + NGX_LINEFEED + " -t : test configuration and exit" NGX_LINEFEED + " -T : test configuration, dump it and exit" + NGX_LINEFEED + " -q : suppress non-error messages " + "during configuration testing" NGX_LINEFEED + " -s signal : send signal to a master process: " + "stop, quit, reopen, reload" NGX_LINEFEED +#ifdef NGX_PREFIX + " -p prefix : set prefix path (default: " NGX_PREFIX ")" + NGX_LINEFEED +#else + " -p prefix : set prefix path (default: NONE)" NGX_LINEFEED +#endif + " -c filename : set configuration file (default: " NGX_CONF_PATH + ")" NGX_LINEFEED + " -g directives : set global directives out of configuration " + "file" NGX_LINEFEED NGX_LINEFEED + ); + } + + if (ngx_show_configure) { + +#ifdef NGX_COMPILER + ngx_write_stderr("built by " NGX_COMPILER NGX_LINEFEED); +#endif + +#if (NGX_SSL) + if (SSLeay() == SSLEAY_VERSION_NUMBER) { + ngx_write_stderr("built with " OPENSSL_VERSION_TEXT NGX_LINEFEED); + } else { + ngx_write_stderr("built with " OPENSSL_VERSION_TEXT + " (running with "); + ngx_write_stderr((char *) (uintptr_t) + SSLeay_version(SSLEAY_VERSION)); + ngx_write_stderr(")" NGX_LINEFEED); + } +#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME + ngx_write_stderr("TLS SNI support enabled" NGX_LINEFEED); +#else + ngx_write_stderr("TLS SNI support disabled" NGX_LINEFEED); +#endif +#endif + + ngx_write_stderr("configure arguments:" NGX_CONFIGURE NGX_LINEFEED); + } +} + + static ngx_int_t ngx_add_inherited_sockets(ngx_cycle_t *cycle) { @@ -1139,7 +1146,7 @@ ngx_set_user(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_OK; } - value = (ngx_str_t *) cf->args->elts; + value = cf->args->elts; ccf->username = (char *) value[1].data; @@ -1345,7 +1352,7 @@ ngx_set_worker_processes(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return "is duplicate"; } - value = (ngx_str_t *) cf->args->elts; + value = cf->args->elts; if (ngx_strcmp(value[1].data, "auto") == 0) { ccf->worker_processes = ngx_ncpu; diff --git a/src/core/nginx.h b/src/core/nginx.h index 34a6a80..56e9587 100644 --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1009005 -#define NGINX_VERSION "1.9.5" +#define nginx_version 1009006 +#define NGINX_VERSION "1.9.6" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c index 9f2675b..0c19d5d 100644 --- a/src/core/ngx_connection.c +++ b/src/core/ngx_connection.c @@ -1175,7 +1175,7 @@ ngx_close_idle_connections(ngx_cycle_t *cycle) /* THREAD: lock */ - if (c[i].fd != -1 && c[i].idle) { + if (c[i].fd != (ngx_socket_t) -1 && c[i].idle) { c[i].close = 1; c[i].read->handler(c[i].read); } diff --git a/src/core/ngx_rwlock.c b/src/core/ngx_rwlock.c index 1404c6e..905de78 100644 --- a/src/core/ngx_rwlock.c +++ b/src/core/ngx_rwlock.c @@ -111,7 +111,7 @@ ngx_rwlock_unlock(ngx_atomic_t *lock) #else -#if (NGX_HTTP_UPSTREAM_ZONE) +#if (NGX_HTTP_UPSTREAM_ZONE || NGX_STREAM_UPSTREAM_ZONE) #error ngx_atomic_cmp_set() is not defined! diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c index b8e0607..15da213 100644 --- a/src/event/ngx_event.c +++ b/src/event/ngx_event.c @@ -670,6 +670,15 @@ ngx_event_process_init(ngx_cycle_t *cycle) } } +#else + + if (ngx_timer_resolution && !(ngx_event_flags & NGX_USE_TIMER_EVENT)) { + ngx_log_error(NGX_LOG_WARN, cycle->log, 0, + "the \"timer_resolution\" directive is not supported " + "with the configured event method, ignored"); + ngx_timer_resolution = 0; + } + #endif cycle->connections = diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c index 1b789e6..57dfc6c 100644 --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -1038,6 +1038,8 @@ ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c, ngx_uint_t flags) sc->buffer = ((flags & NGX_SSL_BUFFER) != 0); sc->buffer_size = ssl->buffer_size; + sc->session_ctx = ssl->ctx; + sc->connection = SSL_new(ssl->ctx); if (sc->connection == NULL) { @@ -1158,6 +1160,7 @@ ngx_ssl_handshake(ngx_connection_t *c) c->recv_chain = ngx_ssl_recv_chain; c->send_chain = ngx_ssl_send_chain; +#if OPENSSL_VERSION_NUMBER < 0x10100000L #ifdef SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS /* initial handshake done, disable renegotiation (CVE-2009-3555) */ @@ -1165,6 +1168,7 @@ ngx_ssl_handshake(ngx_connection_t *c) c->ssl->connection->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS; } +#endif #endif return NGX_OK; @@ -2043,7 +2047,7 @@ ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, char *fmt, ...) (void) ERR_get_error(); } - ngx_log_error(level, log, err, "%s)", errstr); + ngx_log_error(level, log, err, "%*s)", p - errstr, errstr); } @@ -2303,7 +2307,7 @@ ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess) c = ngx_ssl_get_connection(ssl_conn); - ssl_ctx = SSL_get_SSL_CTX(ssl_conn); + ssl_ctx = c->ssl->session_ctx; shm_zone = SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_session_cache_index); cache = shm_zone->data; @@ -2441,21 +2445,17 @@ ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn, u_char *id, int len, ngx_ssl_sess_id_t *sess_id; ngx_ssl_session_cache_t *cache; u_char buf[NGX_SSL_MAX_SESSION_SIZE]; -#if (NGX_DEBUG) ngx_connection_t *c; -#endif hash = ngx_crc32_short(id, (size_t) len); *copy = 0; -#if (NGX_DEBUG) c = ngx_ssl_get_connection(ssl_conn); ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, "ssl get session: %08XD:%d", hash, len); -#endif - shm_zone = SSL_CTX_get_ex_data(SSL_get_SSL_CTX(ssl_conn), + shm_zone = SSL_CTX_get_ex_data(c->ssl->session_ctx, ngx_ssl_session_cache_index); cache = shm_zone->data; @@ -2834,13 +2834,14 @@ ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn, SSL_CTX *ssl_ctx; ngx_uint_t i; ngx_array_t *keys; + ngx_connection_t *c; ngx_ssl_session_ticket_key_t *key; #if (NGX_DEBUG) u_char buf[32]; - ngx_connection_t *c; #endif - ssl_ctx = SSL_get_SSL_CTX(ssl_conn); + c = ngx_ssl_get_connection(ssl_conn); + ssl_ctx = c->ssl->session_ctx; keys = SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_session_ticket_keys_index); if (keys == NULL) { @@ -2849,10 +2850,6 @@ ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn, key = keys->elts; -#if (NGX_DEBUG) - c = ngx_ssl_get_connection(ssl_conn); -#endif - if (enc == 1) { /* encrypt session ticket */ @@ -2861,7 +2858,7 @@ ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn, ngx_hex_dump(buf, key[0].name, 16) - buf, buf, SSL_session_reused(ssl_conn) ? "reused" : "new"); - RAND_pseudo_bytes(iv, 16); + RAND_bytes(iv, 16); EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, key[0].aes_key, iv); HMAC_Init_ex(hctx, key[0].hmac_key, 16, ngx_ssl_session_ticket_md(), NULL); diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h index 08eff64..c86be2a 100644 --- a/src/event/ngx_event_openssl.h +++ b/src/event/ngx_event_openssl.h @@ -46,6 +46,7 @@ typedef struct { typedef struct { ngx_ssl_conn_t *connection; + SSL_CTX *session_ctx; ngx_int_t last; ngx_buf_t *buf; diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index 36f00f6..7a29608 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -4489,7 +4489,9 @@ ngx_http_core_root(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) clcf->alias = alias ? clcf->name.len : 0; clcf->root = value[1]; - if (!alias && clcf->root.data[clcf->root.len - 1] == '/') { + if (!alias && clcf->root.len > 0 + && clcf->root.data[clcf->root.len - 1] == '/') + { clcf->root.len--; } diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c index c65de35..eaf294a 100644 --- a/src/http/ngx_http_variables.c +++ b/src/http/ngx_http_variables.c @@ -575,7 +575,7 @@ ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key) return NULL; } - if (ngx_strncmp(name->data, "http_", 5) == 0) { + if (name->len >= 5 && ngx_strncmp(name->data, "http_", 5) == 0) { if (ngx_http_variable_unknown_header_in(r, vv, (uintptr_t) name) == NGX_OK) @@ -586,7 +586,7 @@ ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key) return NULL; } - if (ngx_strncmp(name->data, "sent_http_", 10) == 0) { + if (name->len >= 10 && ngx_strncmp(name->data, "sent_http_", 10) == 0) { if (ngx_http_variable_unknown_header_out(r, vv, (uintptr_t) name) == NGX_OK) @@ -597,7 +597,7 @@ ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key) return NULL; } - if (ngx_strncmp(name->data, "upstream_http_", 14) == 0) { + if (name->len >= 14 && ngx_strncmp(name->data, "upstream_http_", 14) == 0) { if (ngx_http_upstream_header_variable(r, vv, (uintptr_t) name) == NGX_OK) @@ -608,7 +608,7 @@ ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key) return NULL; } - if (ngx_strncmp(name->data, "cookie_", 7) == 0) { + if (name->len >= 7 && ngx_strncmp(name->data, "cookie_", 7) == 0) { if (ngx_http_variable_cookie(r, vv, (uintptr_t) name) == NGX_OK) { return vv; @@ -617,7 +617,9 @@ ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key) return NULL; } - if (ngx_strncmp(name->data, "upstream_cookie_", 16) == 0) { + if (name->len >= 16 + && ngx_strncmp(name->data, "upstream_cookie_", 16) == 0) + { if (ngx_http_upstream_cookie_variable(r, vv, (uintptr_t) name) == NGX_OK) @@ -628,7 +630,7 @@ ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key) return NULL; } - if (ngx_strncmp(name->data, "arg_", 4) == 0) { + if (name->len >= 4 && ngx_strncmp(name->data, "arg_", 4) == 0) { if (ngx_http_variable_argument(r, vv, (uintptr_t) name) == NGX_OK) { return vv; @@ -2535,21 +2537,27 @@ ngx_http_variables_init_vars(ngx_conf_t *cf) } } - if (ngx_strncmp(v[i].name.data, "http_", 5) == 0) { + if (v[i].name.len >= 5 + && ngx_strncmp(v[i].name.data, "http_", 5) == 0) + { v[i].get_handler = ngx_http_variable_unknown_header_in; v[i].data = (uintptr_t) &v[i].name; continue; } - if (ngx_strncmp(v[i].name.data, "sent_http_", 10) == 0) { + if (v[i].name.len >= 10 + && ngx_strncmp(v[i].name.data, "sent_http_", 10) == 0) + { v[i].get_handler = ngx_http_variable_unknown_header_out; v[i].data = (uintptr_t) &v[i].name; continue; } - if (ngx_strncmp(v[i].name.data, "upstream_http_", 14) == 0) { + if (v[i].name.len >= 14 + && ngx_strncmp(v[i].name.data, "upstream_http_", 14) == 0) + { v[i].get_handler = ngx_http_upstream_header_variable; v[i].data = (uintptr_t) &v[i].name; v[i].flags = NGX_HTTP_VAR_NOCACHEABLE; @@ -2557,14 +2565,18 @@ ngx_http_variables_init_vars(ngx_conf_t *cf) continue; } - if (ngx_strncmp(v[i].name.data, "cookie_", 7) == 0) { + if (v[i].name.len >= 7 + && ngx_strncmp(v[i].name.data, "cookie_", 7) == 0) + { v[i].get_handler = ngx_http_variable_cookie; v[i].data = (uintptr_t) &v[i].name; continue; } - if (ngx_strncmp(v[i].name.data, "upstream_cookie_", 16) == 0) { + if (v[i].name.len >= 16 + && ngx_strncmp(v[i].name.data, "upstream_cookie_", 16) == 0) + { v[i].get_handler = ngx_http_upstream_cookie_variable; v[i].data = (uintptr_t) &v[i].name; v[i].flags = NGX_HTTP_VAR_NOCACHEABLE; @@ -2572,7 +2584,9 @@ ngx_http_variables_init_vars(ngx_conf_t *cf) continue; } - if (ngx_strncmp(v[i].name.data, "arg_", 4) == 0) { + if (v[i].name.len >= 4 + && ngx_strncmp(v[i].name.data, "arg_", 4) == 0) + { v[i].get_handler = ngx_http_variable_argument; v[i].data = (uintptr_t) &v[i].name; v[i].flags = NGX_HTTP_VAR_NOCACHEABLE; diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c index bf07997..10cb727 100644 --- a/src/http/v2/ngx_http_v2.c +++ b/src/http/v2/ngx_http_v2.c @@ -870,6 +870,8 @@ ngx_http_v2_state_data(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end) return ngx_http_v2_state_skip_padded(h2c, pos, end); } + stream->in_closed = h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG; + h2c->state.stream = stream; return ngx_http_v2_state_read_data(h2c, pos, end); @@ -897,8 +899,6 @@ ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos, } if (stream->skip_data) { - stream->in_closed = h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG; - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, "skipping http2 DATA frame, reason: %d", stream->skip_data); @@ -988,9 +988,7 @@ ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos, ngx_http_v2_state_read_data); } - if (h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG) { - stream->in_closed = 1; - + if (stream->in_closed) { if (r->headers_in.content_length_n < 0) { r->headers_in.content_length_n = rb->rest; @@ -1133,6 +1131,22 @@ ngx_http_v2_state_headers(ngx_http_v2_connection_t *h2c, u_char *pos, h2c->last_sid = h2c->state.sid; + if (depend == h2c->state.sid) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent HEADERS frame for stream %ui " + "with incorrect dependency", h2c->state.sid); + + if (ngx_http_v2_send_rst_stream(h2c, h2c->state.sid, + NGX_HTTP_V2_PROTOCOL_ERROR) + != NGX_OK) + { + return ngx_http_v2_connection_error(h2c, + NGX_HTTP_V2_INTERNAL_ERROR); + } + + return ngx_http_v2_state_skip_headers(h2c, pos, end); + } + h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, ngx_http_v2_module); @@ -1233,7 +1247,7 @@ ngx_http_v2_state_header_block(ngx_http_v2_connection_t *h2c, u_char *pos, } else { /* literal header field without indexing */ - prefix = ngx_http_v2_prefix(3); + prefix = ngx_http_v2_prefix(4); } value = ngx_http_v2_parse_int(h2c, &pos, end, prefix); @@ -2361,12 +2375,6 @@ ngx_http_v2_connection_error(ngx_http_v2_connection_t *h2c, ngx_debug_point(); } - if (h2c->state.stream) { - h2c->state.stream->out_closed = 1; - h2c->state.pool = NULL; - ngx_http_v2_close_stream(h2c->state.stream, NGX_HTTP_BAD_REQUEST); - } - ngx_http_v2_finalize_connection(h2c, err); return NULL; @@ -2396,8 +2404,8 @@ ngx_http_v2_parse_int(ngx_http_v2_connection_t *h2c, u_char **pos, u_char *end, return value; } - if (end - p > NGX_HTTP_V2_INT_OCTETS - 1) { - end = p + NGX_HTTP_V2_INT_OCTETS - 1; + if (end - start > NGX_HTTP_V2_INT_OCTETS) { + end = start + NGX_HTTP_V2_INT_OCTETS; } for (shift = 0; p != end; shift += 7) { @@ -2417,14 +2425,14 @@ ngx_http_v2_parse_int(ngx_http_v2_connection_t *h2c, u_char **pos, u_char *end, } } - if ((size_t) (end - start) >= NGX_HTTP_V2_INT_OCTETS) { - return NGX_DECLINED; - } - if ((size_t) (end - start) >= h2c->state.length) { return NGX_ERROR; } + if (end == start + NGX_HTTP_V2_INT_OCTETS) { + return NGX_DECLINED; + } + return NGX_AGAIN; } @@ -2762,6 +2770,8 @@ ngx_http_v2_create_stream(ngx_http_v2_connection_t *h2c) return NULL; } + ngx_str_set(&r->http_protocol, "HTTP/2.0"); + r->http_version = NGX_HTTP_VERSION_20; r->valid_location = 1; @@ -2896,11 +2906,14 @@ ngx_http_v2_get_closed_node(ngx_http_v2_connection_t *h2c) weight += child->weight; } + parent = node->parent; + for (q = ngx_queue_head(&node->children); q != ngx_queue_sentinel(&node->children); q = ngx_queue_next(q)) { child = ngx_queue_data(q, ngx_http_v2_node_t, queue); + child->parent = parent; child->weight = node->weight * child->weight / weight; if (child->weight == 0) { @@ -2908,8 +2921,6 @@ ngx_http_v2_get_closed_node(ngx_http_v2_connection_t *h2c) } } - parent = node->parent; - if (parent == NGX_HTTP_V2_ROOT) { node->rank = 0; node->rel_weight = 1.0; @@ -3795,6 +3806,12 @@ ngx_http_v2_finalize_connection(ngx_http_v2_connection_t *h2c, c = h2c->connection; + if (h2c->state.stream) { + h2c->state.stream->out_closed = 1; + h2c->state.pool = NULL; + ngx_http_v2_close_stream(h2c->state.stream, NGX_HTTP_BAD_REQUEST); + } + h2c->blocked = 1; if (!c->error && ngx_http_v2_send_goaway(h2c, status) != NGX_ERROR) { @@ -3922,8 +3939,8 @@ static void ngx_http_v2_set_dependency(ngx_http_v2_connection_t *h2c, ngx_http_v2_node_t *node, ngx_uint_t depend, ngx_uint_t exclusive) { - ngx_queue_t *children; - ngx_http_v2_node_t *parent, *next; + ngx_queue_t *children, *q; + ngx_http_v2_node_t *parent, *child, *next; parent = depend ? ngx_http_v2_get_node_by_id(h2c, depend, 0) : NULL; @@ -3985,6 +4002,14 @@ ngx_http_v2_set_dependency(ngx_http_v2_connection_t *h2c, } if (exclusive) { + for (q = ngx_queue_head(children); + q != ngx_queue_sentinel(children); + q = ngx_queue_next(q)) + { + child = ngx_queue_data(q, ngx_http_v2_node_t, queue); + child->parent = node; + } + ngx_queue_add(&node->children, children); ngx_queue_init(children); } diff --git a/src/http/v2/ngx_http_v2.h b/src/http/v2/ngx_http_v2.h index b7e73c9..462d254 100644 --- a/src/http/v2/ngx_http_v2.h +++ b/src/http/v2/ngx_http_v2.h @@ -21,7 +21,8 @@ #define NGX_HTTP_V2_MAX_FRAME_SIZE ((1 << 24) - 1) #define NGX_HTTP_V2_INT_OCTETS 4 -#define NGX_HTTP_V2_MAX_FIELD ((1 << NGX_HTTP_V2_INT_OCTETS * 7) - 1) +#define NGX_HTTP_V2_MAX_FIELD \ + (127 + (1 << (NGX_HTTP_V2_INT_OCTETS - 1) * 7) - 1) #define NGX_HTTP_V2_DATA_DISCARD 1 #define NGX_HTTP_V2_DATA_ERROR 2 diff --git a/src/http/v2/ngx_http_v2_filter_module.c b/src/http/v2/ngx_http_v2_filter_module.c index 17cfcd8..a866cde 100644 --- a/src/http/v2/ngx_http_v2_filter_module.c +++ b/src/http/v2/ngx_http_v2_filter_module.c @@ -12,7 +12,12 @@ #include -#define ngx_http_v2_integer_octets(v) (((v) + 127) / 128) +/* + * This returns precise number of octets for values in range 0..253 + * and estimate number for the rest, but not smaller than required. + */ + +#define ngx_http_v2_integer_octets(v) (1 + (v) / 127) #define ngx_http_v2_literal_size(h) \ (ngx_http_v2_integer_octets(sizeof(h) - 1) + sizeof(h) - 1) @@ -20,6 +25,8 @@ #define ngx_http_v2_indexed(i) (128 + (i)) #define ngx_http_v2_inc_indexed(i) (64 + (i)) +#define NGX_HTTP_V2_ENCODE_RAW 0 +#define NGX_HTTP_V2_ENCODE_HUFF 0x80 #define NGX_HTTP_V2_STATUS_INDEX 8 #define NGX_HTTP_V2_STATUS_200_INDEX 8 @@ -41,10 +48,8 @@ static u_char *ngx_http_v2_write_int(u_char *pos, ngx_uint_t prefix, ngx_uint_t value); -static void ngx_http_v2_write_headers_head(u_char *pos, size_t length, - ngx_uint_t sid, ngx_uint_t end_headers, ngx_uint_t end_stream); -static void ngx_http_v2_write_continuation_head(u_char *pos, size_t length, - ngx_uint_t sid, ngx_uint_t end_headers); +static ngx_http_v2_out_frame_t *ngx_http_v2_create_headers_frame( + ngx_http_request_t *r, u_char *pos, u_char *end); static ngx_chain_t *ngx_http_v2_send_chain(ngx_connection_t *fc, ngx_chain_t *in, off_t limit); @@ -114,17 +119,14 @@ static ngx_http_output_header_filter_pt ngx_http_next_header_filter; static ngx_int_t ngx_http_v2_header_filter(ngx_http_request_t *r) { - u_char status, *p, *head; - size_t len, rest, frame_size; - ngx_buf_t *b; + u_char status, *pos, *start, *p; + size_t len; ngx_str_t host, location; - ngx_uint_t i, port, continuation; - ngx_chain_t *cl; + ngx_uint_t i, port; ngx_list_part_t *part; ngx_table_elt_t *header; ngx_connection_t *fc; ngx_http_cleanup_t *cln; - ngx_http_v2_stream_t *stream; ngx_http_v2_out_frame_t *frame; ngx_http_core_loc_conf_t *clcf; ngx_http_core_srv_conf_t *cscf; @@ -222,7 +224,7 @@ ngx_http_v2_header_filter(ngx_http_request_t *r) } if (r->headers_out.content_type.len) { - len += NGX_HTTP_V2_INT_OCTETS + r->headers_out.content_type.len; + len += 1 + NGX_HTTP_V2_INT_OCTETS + r->headers_out.content_type.len; if (r->headers_out.content_type_len == r->headers_out.content_type.len && r->headers_out.charset.len) @@ -386,134 +388,117 @@ ngx_http_v2_header_filter(ngx_http_request_t *r) + NGX_HTTP_V2_INT_OCTETS + header[i].value.len; } - stream = r->stream; - frame_size = stream->connection->frame_size; - - len += NGX_HTTP_V2_FRAME_HEADER_SIZE - * ((len + frame_size - 1) / frame_size); - - b = ngx_create_temp_buf(r->pool, len); - if (b == NULL) { + pos = ngx_palloc(r->pool, len); + if (pos == NULL) { return NGX_ERROR; } - b->last_buf = r->header_only; - - b->last += NGX_HTTP_V2_FRAME_HEADER_SIZE; + start = pos; if (status) { - *b->last++ = status; + *pos++ = status; } else { - *b->last++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_STATUS_INDEX); - *b->last++ = 3; - b->last = ngx_sprintf(b->last, "%03ui", r->headers_out.status); + *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_STATUS_INDEX); + *pos++ = NGX_HTTP_V2_ENCODE_RAW | 3; + pos = ngx_sprintf(pos, "%03ui", r->headers_out.status); } if (r->headers_out.server == NULL) { - *b->last++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_SERVER_INDEX); + *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_SERVER_INDEX); if (clcf->server_tokens) { - *b->last++ = sizeof(NGINX_VER) - 1; - b->last = ngx_cpymem(b->last, NGINX_VER, sizeof(NGINX_VER) - 1); + *pos++ = NGX_HTTP_V2_ENCODE_RAW | (sizeof(NGINX_VER) - 1); + pos = ngx_cpymem(pos, NGINX_VER, sizeof(NGINX_VER) - 1); } else { - *b->last++ = sizeof("nginx") - 1; - b->last = ngx_cpymem(b->last, "nginx", sizeof("nginx") - 1); + *pos++ = NGX_HTTP_V2_ENCODE_RAW | (sizeof("nginx") - 1); + pos = ngx_cpymem(pos, "nginx", sizeof("nginx") - 1); } } if (r->headers_out.date == NULL) { - *b->last++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_DATE_INDEX); - *b->last++ = (u_char) ngx_cached_http_time.len; + *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_DATE_INDEX); + *pos++ = (u_char) ngx_cached_http_time.len; - b->last = ngx_cpymem(b->last, ngx_cached_http_time.data, - ngx_cached_http_time.len); + pos = ngx_cpymem(pos, ngx_cached_http_time.data, + ngx_cached_http_time.len); } if (r->headers_out.content_type.len) { - *b->last++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_CONTENT_TYPE_INDEX); + *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_CONTENT_TYPE_INDEX); if (r->headers_out.content_type_len == r->headers_out.content_type.len && r->headers_out.charset.len) { - *b->last = 0; - b->last = ngx_http_v2_write_int(b->last, ngx_http_v2_prefix(7), - r->headers_out.content_type.len - + sizeof("; charset=") - 1 - + r->headers_out.charset.len); + *pos = NGX_HTTP_V2_ENCODE_RAW; + pos = ngx_http_v2_write_int(pos, ngx_http_v2_prefix(7), + r->headers_out.content_type.len + + sizeof("; charset=") - 1 + + r->headers_out.charset.len); - p = b->last; + p = pos; - b->last = ngx_cpymem(p, r->headers_out.content_type.data, - r->headers_out.content_type.len); + pos = ngx_cpymem(pos, r->headers_out.content_type.data, + r->headers_out.content_type.len); - b->last = ngx_cpymem(b->last, "; charset=", - sizeof("; charset=") - 1); + pos = ngx_cpymem(pos, "; charset=", sizeof("; charset=") - 1); - b->last = ngx_cpymem(b->last, r->headers_out.charset.data, - r->headers_out.charset.len); + pos = ngx_cpymem(pos, r->headers_out.charset.data, + r->headers_out.charset.len); /* update r->headers_out.content_type for possible logging */ - r->headers_out.content_type.len = b->last - p; + r->headers_out.content_type.len = pos - p; r->headers_out.content_type.data = p; } else { - *b->last = 0; - b->last = ngx_http_v2_write_int(b->last, ngx_http_v2_prefix(7), - r->headers_out.content_type.len); - b->last = ngx_cpymem(b->last, r->headers_out.content_type.data, - r->headers_out.content_type.len); + *pos = NGX_HTTP_V2_ENCODE_RAW; + pos = ngx_http_v2_write_int(pos, ngx_http_v2_prefix(7), + r->headers_out.content_type.len); + pos = ngx_cpymem(pos, r->headers_out.content_type.data, + r->headers_out.content_type.len); } } if (r->headers_out.content_length == NULL && r->headers_out.content_length_n >= 0) { - *b->last++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_CONTENT_LENGTH_INDEX); + *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_CONTENT_LENGTH_INDEX); - p = b->last; - b->last = ngx_sprintf(b->last + 1, "%O", - r->headers_out.content_length_n); - *p = (u_char) (b->last - p - 1); + p = pos; + pos = ngx_sprintf(pos + 1, "%O", r->headers_out.content_length_n); + *p = NGX_HTTP_V2_ENCODE_RAW | (u_char) (pos - p - 1); } if (r->headers_out.last_modified == NULL && r->headers_out.last_modified_time != -1) { - *b->last++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_LAST_MODIFIED_INDEX); + *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_LAST_MODIFIED_INDEX); - p = b->last; - b->last = ngx_http_time(b->last + 1, r->headers_out.last_modified_time); - *p = (u_char) (b->last - p - 1); + *pos++ = NGX_HTTP_V2_ENCODE_RAW + | (sizeof("Wed, 31 Dec 1986 18:00:00 GMT") - 1); + pos = ngx_http_time(pos, r->headers_out.last_modified_time); } if (r->headers_out.location && r->headers_out.location->value.len) { - *b->last++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_LOCATION_INDEX); + *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_LOCATION_INDEX); - *b->last = 0; - b->last = ngx_http_v2_write_int(b->last, ngx_http_v2_prefix(7), - r->headers_out.location->value.len); - b->last = ngx_cpymem(b->last, r->headers_out.location->value.data, - r->headers_out.location->value.len); + *pos = NGX_HTTP_V2_ENCODE_RAW; + pos = ngx_http_v2_write_int(pos, ngx_http_v2_prefix(7), + r->headers_out.location->value.len); + pos = ngx_cpymem(pos, r->headers_out.location->value.data, + r->headers_out.location->value.len); } #if (NGX_HTTP_GZIP) if (r->gzip_vary) { - *b->last++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_VARY_INDEX); - *b->last++ = sizeof("Accept-Encoding") - 1; - b->last = ngx_cpymem(b->last, "Accept-Encoding", - sizeof("Accept-Encoding") - 1); + *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_VARY_INDEX); + *pos++ = NGX_HTTP_V2_ENCODE_RAW | (sizeof("Accept-Encoding") - 1); + pos = ngx_cpymem(pos, "Accept-Encoding", sizeof("Accept-Encoding") - 1); } #endif - continuation = 0; - head = b->pos; - - len = b->last - head - NGX_HTTP_V2_FRAME_HEADER_SIZE; - rest = frame_size - len; - part = &r->headers_out.headers.part; header = part->elts; @@ -533,82 +518,26 @@ ngx_http_v2_header_filter(ngx_http_request_t *r) continue; } - len = 1 + NGX_HTTP_V2_INT_OCTETS * 2 - + header[i].key.len - + header[i].value.len; + *pos++ = 0; - if (len > rest) { - len = b->last - head - NGX_HTTP_V2_FRAME_HEADER_SIZE; + *pos = NGX_HTTP_V2_ENCODE_RAW; + pos = ngx_http_v2_write_int(pos, ngx_http_v2_prefix(7), + header[i].key.len); + ngx_strlow(pos, header[i].key.data, header[i].key.len); + pos += header[i].key.len; - if (continuation) { - ngx_http_v2_write_continuation_head(head, len, - stream->node->id, 0); - } else { - continuation = 1; - ngx_http_v2_write_headers_head(head, len, stream->node->id, 0, - r->header_only); - } - - rest = frame_size; - head = b->last; - - b->last += NGX_HTTP_V2_FRAME_HEADER_SIZE; - } - - p = b->last; - - *p++ = 0; - - *p = 0; - p = ngx_http_v2_write_int(p, ngx_http_v2_prefix(7), header[i].key.len); - ngx_strlow(p, header[i].key.data, header[i].key.len); - p += header[i].key.len; - - *p = 0; - p = ngx_http_v2_write_int(p, ngx_http_v2_prefix(7), - header[i].value.len); - p = ngx_cpymem(p, header[i].value.data, header[i].value.len); - - rest -= p - b->last; - b->last = p; + *pos = NGX_HTTP_V2_ENCODE_RAW; + pos = ngx_http_v2_write_int(pos, ngx_http_v2_prefix(7), + header[i].value.len); + pos = ngx_cpymem(pos, header[i].value.data, header[i].value.len); } - len = b->last - head - NGX_HTTP_V2_FRAME_HEADER_SIZE; - - if (continuation) { - ngx_http_v2_write_continuation_head(head, len, stream->node->id, 1); - - } else { - ngx_http_v2_write_headers_head(head, len, stream->node->id, 1, - r->header_only); - } - - cl = ngx_alloc_chain_link(r->pool); - if (cl == NULL) { - return NGX_ERROR; - } - - cl->buf = b; - cl->next = NULL; - - frame = ngx_palloc(r->pool, sizeof(ngx_http_v2_out_frame_t)); + frame = ngx_http_v2_create_headers_frame(r, start, pos); if (frame == NULL) { return NGX_ERROR; } - frame->first = cl; - frame->last = cl; - frame->handler = ngx_http_v2_headers_frame_handler; - frame->stream = stream; - frame->length = b->last - b->pos - NGX_HTTP_V2_FRAME_HEADER_SIZE; - frame->blocked = 1; - frame->fin = r->header_only; - - ngx_log_debug3(NGX_LOG_DEBUG_HTTP, stream->request->connection->log, 0, - "http2:%ui create HEADERS frame %p: len:%uz", - stream->node->id, frame, frame->length); - - ngx_http_v2_queue_blocked_frame(stream->connection, frame); + ngx_http_v2_queue_blocked_frame(r->stream->connection, frame); cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { @@ -616,14 +545,14 @@ ngx_http_v2_header_filter(ngx_http_request_t *r) } cln->handler = ngx_http_v2_filter_cleanup; - cln->data = stream; + cln->data = r->stream; - stream->queued = 1; + r->stream->queued = 1; fc->send_chain = ngx_http_v2_send_chain; fc->need_last_buf = 1; - return ngx_http_v2_filter_send(fc, stream); + return ngx_http_v2_filter_send(fc, r->stream); } @@ -649,41 +578,104 @@ ngx_http_v2_write_int(u_char *pos, ngx_uint_t prefix, ngx_uint_t value) } -static void -ngx_http_v2_write_headers_head(u_char *pos, size_t length, ngx_uint_t sid, - ngx_uint_t end_headers, ngx_uint_t end_stream) +static ngx_http_v2_out_frame_t * +ngx_http_v2_create_headers_frame(ngx_http_request_t *r, u_char *pos, + u_char *end) { - u_char flags; + u_char type, flags; + size_t rest, frame_size; + ngx_buf_t *b; + ngx_chain_t *cl, **ll; + ngx_http_v2_stream_t *stream; + ngx_http_v2_out_frame_t *frame; - pos = ngx_http_v2_write_len_and_type(pos, length, - NGX_HTTP_V2_HEADERS_FRAME); + stream = r->stream; + rest = end - pos; - flags = NGX_HTTP_V2_NO_FLAG; - - if (end_headers) { - flags |= NGX_HTTP_V2_END_HEADERS_FLAG; + frame = ngx_palloc(r->pool, sizeof(ngx_http_v2_out_frame_t)); + if (frame == NULL) { + return NULL; } - if (end_stream) { - flags |= NGX_HTTP_V2_END_STREAM_FLAG; + frame->handler = ngx_http_v2_headers_frame_handler; + frame->stream = stream; + frame->length = rest; + frame->blocked = 1; + frame->fin = r->header_only; + + ll = &frame->first; + + type = NGX_HTTP_V2_HEADERS_FRAME; + flags = r->header_only ? NGX_HTTP_V2_END_STREAM_FLAG : NGX_HTTP_V2_NO_FLAG; + frame_size = stream->connection->frame_size; + + for ( ;; ) { + if (rest <= frame_size) { + frame_size = rest; + flags |= NGX_HTTP_V2_END_HEADERS_FLAG; + } + + b = ngx_create_temp_buf(r->pool, NGX_HTTP_V2_FRAME_HEADER_SIZE); + if (b == NULL) { + return NULL; + } + + b->last = ngx_http_v2_write_len_and_type(b->last, frame_size, type); + *b->last++ = flags; + b->last = ngx_http_v2_write_sid(b->last, stream->node->id); + + cl = ngx_alloc_chain_link(r->pool); + if (cl == NULL) { + return NULL; + } + + cl->buf = b; + + *ll = cl; + ll = &cl->next; + + b = ngx_calloc_buf(r->pool); + if (b == NULL) { + return NULL; + } + + b->pos = pos; + + pos += frame_size; + + b->last = pos; + b->start = b->pos; + b->end = b->last; + b->temporary = 1; + + cl = ngx_alloc_chain_link(r->pool); + if (cl == NULL) { + return NULL; + } + + cl->buf = b; + + *ll = cl; + ll = &cl->next; + + rest -= frame_size; + + if (rest) { + type = NGX_HTTP_V2_CONTINUATION_FRAME; + flags = NGX_HTTP_V2_NO_FLAG; + continue; + } + + b->last_buf = r->header_only; + cl->next = NULL; + frame->last = cl; + + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http2:%ui create HEADERS frame %p: len:%uz", + stream->node->id, frame, frame->length); + + return frame; } - - *pos++ = flags; - - (void) ngx_http_v2_write_sid(pos, sid); -} - - -static void -ngx_http_v2_write_continuation_head(u_char *pos, size_t length, ngx_uint_t sid, - ngx_uint_t end_headers) -{ - pos = ngx_http_v2_write_len_and_type(pos, length, - NGX_HTTP_V2_CONTINUATION_FRAME); - - *pos++ = end_headers ? NGX_HTTP_V2_END_HEADERS_FLAG : NGX_HTTP_V2_NO_FLAG; - - (void) ngx_http_v2_write_sid(pos, sid); } diff --git a/src/stream/ngx_stream_proxy_module.c b/src/stream/ngx_stream_proxy_module.c index ea142e7..6800500 100644 --- a/src/stream/ngx_stream_proxy_module.c +++ b/src/stream/ngx_stream_proxy_module.c @@ -759,6 +759,10 @@ ngx_stream_proxy_ssl_handshake(ngx_connection_t *pc) u->peer.save_session(&u->peer, u->peer.data); } + if (pc->write->timer_set) { + ngx_del_timer(pc->write); + } + ngx_stream_proxy_init_upstream(s); return; From b37dfd906aaea875b38630ee2383cd5a2e17cad8 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Tue, 3 Nov 2015 08:59:14 +0200 Subject: [PATCH 013/600] New upsteam release (1.9.6) --- debian/changelog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index 1fb0f6e..10811de 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -nginx (1.9.5-1) UNRELEASED; urgency=medium +nginx (1.9.6-1) UNRELEASED; urgency=medium [ Christos Trochalakis] * New upstream release. From 6f5cefd11e961c884fcb0bea4cd9334c0f979007 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Tue, 3 Nov 2015 08:59:30 +0200 Subject: [PATCH 014/600] 1.9.6-1 --- debian/changelog | 5 +++-- debian/nginx-common.NEWS | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/debian/changelog b/debian/changelog index 10811de..d01c0c2 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,9 +1,10 @@ -nginx (1.9.6-1) UNRELEASED; urgency=medium +nginx (1.9.6-1) unstable; urgency=medium [ Christos Trochalakis] * New upstream release. + * Enable http2 module in nginx-full & nginx-extras - -- Christos Trochalakis Fri, 25 Sep 2015 14:03:10 +0300 + -- Christos Trochalakis Tue, 03 Nov 2015 08:59:21 +0200 nginx (1.9.4-1) unstable; urgency=medium diff --git a/debian/nginx-common.NEWS b/debian/nginx-common.NEWS index 161d061..46a6f14 100644 --- a/debian/nginx-common.NEWS +++ b/debian/nginx-common.NEWS @@ -1,4 +1,4 @@ -nginx-common (1.9.5-1) UNRELEASED; urgency=medium +nginx-common (1.9.6-1) unstable; urgency=medium As of nginx 1.9.5 spdy has been replaced by the http2 module. Make sure to replace "spdy" with "http2" in your config files. From 7a486795eb9b1e2a441a4035cb8854f7d2e2d9cf Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Fri, 13 Nov 2015 16:07:02 +0200 Subject: [PATCH 015/600] Update nginx-lua 0.9.19 Fixes http/2 issues o https://github.com/openresty/lua-nginx-module/issues/566 --- debian/changelog | 8 + debian/modules/README.Modules-versions | 2 +- debian/modules/nginx-lua/.gitignore | 164 - debian/modules/nginx-lua/README.markdown | 484 +- debian/modules/nginx-lua/config | 105 +- .../modules/nginx-lua/doc/HttpLuaModule.wiki | 437 +- .../nginx-lua/src/api/ngx_http_lua_api.h | 2 +- debian/modules/nginx-lua/src/ddebug.h | 6 +- .../nginx-lua/src/ngx_http_lua_directive.c | 612 ++ .../nginx-lua/src/ngx_http_lua_directive.h | 18 + .../nginx-lua/src/ngx_http_lua_headers_in.c | 76 +- .../nginx-lua/src/ngx_http_lua_headers_out.c | 12 + .../nginx-lua/src/ngx_http_lua_initworkerby.c | 8 +- .../modules/nginx-lua/src/ngx_http_lua_lex.c | 8251 +++++++++++++++++ .../modules/nginx-lua/src/ngx_http_lua_lex.h | 17 + .../nginx-lua/src/ngx_http_lua_module.c | 86 +- .../nginx-lua/src/ngx_http_lua_shdict.c | 59 +- .../nginx-lua/src/ngx_http_lua_socket_tcp.c | 10 +- .../nginx-lua/src/ngx_http_lua_socket_udp.c | 2 +- .../nginx-lua/src/ngx_http_lua_subrequest.c | 8 +- debian/modules/nginx-lua/t/000--init.t | 1 - debian/modules/nginx-lua/t/000-sanity.t | 1 - debian/modules/nginx-lua/t/001-set.t | 1 - debian/modules/nginx-lua/t/002-content.t | 2 +- debian/modules/nginx-lua/t/003-errors.t | 1 - debian/modules/nginx-lua/t/004-require.t | 2 +- debian/modules/nginx-lua/t/005-exit.t | 1 - debian/modules/nginx-lua/t/006-escape.t | 1 - debian/modules/nginx-lua/t/007-md5.t | 2 +- debian/modules/nginx-lua/t/008-today.t | 2 +- debian/modules/nginx-lua/t/009-log.t | 2 +- debian/modules/nginx-lua/t/010-request_body.t | 2 +- debian/modules/nginx-lua/t/011-md5_bin.t | 1 - debian/modules/nginx-lua/t/012-now.t | 2 +- debian/modules/nginx-lua/t/013-base64.t | 1 - debian/modules/nginx-lua/t/014-bugs.t | 1 - debian/modules/nginx-lua/t/015-status.t | 1 - debian/modules/nginx-lua/t/016-resp-header.t | 46 +- debian/modules/nginx-lua/t/017-exec.t | 1 - debian/modules/nginx-lua/t/018-ndk.t | 1 - debian/modules/nginx-lua/t/019-const.t | 1 - debian/modules/nginx-lua/t/020-subrequest.t | 76 +- debian/modules/nginx-lua/t/021-cookie-time.t | 2 +- debian/modules/nginx-lua/t/022-redirect.t | 1 - .../nginx-lua/t/023-rewrite/client-abort.t | 1 - debian/modules/nginx-lua/t/023-rewrite/exec.t | 1 - debian/modules/nginx-lua/t/023-rewrite/exit.t | 1 - .../modules/nginx-lua/t/023-rewrite/mixed.t | 1 - .../nginx-lua/t/023-rewrite/multi-capture.t | 1 - .../nginx-lua/t/023-rewrite/on-abort.t | 1 - .../nginx-lua/t/023-rewrite/redirect.t | 1 - .../nginx-lua/t/023-rewrite/req-body.t | 2 +- .../nginx-lua/t/023-rewrite/req-socket.t | 1 - .../nginx-lua/t/023-rewrite/request_body.t | 1 - .../modules/nginx-lua/t/023-rewrite/sanity.t | 1 - .../modules/nginx-lua/t/023-rewrite/sleep.t | 1 - .../t/023-rewrite/socket-keepalive.t | 1 - .../nginx-lua/t/023-rewrite/subrequest.t | 1 - .../t/023-rewrite/tcp-socket-timeout.t | 1 - .../nginx-lua/t/023-rewrite/tcp-socket.t | 1 - .../nginx-lua/t/023-rewrite/unix-socket.t | 1 - .../nginx-lua/t/023-rewrite/uthread-exec.t | 1 - .../nginx-lua/t/023-rewrite/uthread-exit.t | 1 - .../t/023-rewrite/uthread-redirect.t | 1 - .../nginx-lua/t/023-rewrite/uthread-spawn.t | 1 - debian/modules/nginx-lua/t/024-access/auth.t | 1 - .../nginx-lua/t/024-access/client-abort.t | 1 - debian/modules/nginx-lua/t/024-access/exec.t | 1 - debian/modules/nginx-lua/t/024-access/exit.t | 1 - debian/modules/nginx-lua/t/024-access/mixed.t | 1 - .../nginx-lua/t/024-access/multi-capture.t | 1 - .../modules/nginx-lua/t/024-access/on-abort.t | 1 - .../modules/nginx-lua/t/024-access/redirect.t | 1 - .../modules/nginx-lua/t/024-access/req-body.t | 2 +- .../nginx-lua/t/024-access/request_body.t | 1 - .../modules/nginx-lua/t/024-access/sanity.t | 1 - .../modules/nginx-lua/t/024-access/satisfy.t | 1 - debian/modules/nginx-lua/t/024-access/sleep.t | 1 - .../nginx-lua/t/024-access/subrequest.t | 1 - .../nginx-lua/t/024-access/uthread-exec.t | 1 - .../nginx-lua/t/024-access/uthread-exit.t | 1 - .../nginx-lua/t/024-access/uthread-redirect.t | 1 - .../nginx-lua/t/024-access/uthread-spawn.t | 1 - debian/modules/nginx-lua/t/025-codecache.t | 1 - debian/modules/nginx-lua/t/026-mysql.t | 1 - .../modules/nginx-lua/t/027-multi-capture.t | 1 - debian/modules/nginx-lua/t/028-req-header.t | 96 +- debian/modules/nginx-lua/t/029-http-time.t | 1 - debian/modules/nginx-lua/t/030-uri-args.t | 1 - debian/modules/nginx-lua/t/031-post-args.t | 1 - debian/modules/nginx-lua/t/032-iolist.t | 1 - debian/modules/nginx-lua/t/033-ctx.t | 1 - debian/modules/nginx-lua/t/035-gmatch.t | 1 - debian/modules/nginx-lua/t/036-sub.t | 1 - debian/modules/nginx-lua/t/037-gsub.t | 1 - debian/modules/nginx-lua/t/038-match-o.t | 1 - debian/modules/nginx-lua/t/039-sub-o.t | 1 - debian/modules/nginx-lua/t/040-gsub-o.t | 1 - .../modules/nginx-lua/t/041-header-filter.t | 1 - debian/modules/nginx-lua/t/042-crc32.t | 1 - debian/modules/nginx-lua/t/043-shdict.t | 135 +- debian/modules/nginx-lua/t/044-req-body.t | 1 - debian/modules/nginx-lua/t/045-ngx-var.t | 1 - debian/modules/nginx-lua/t/046-hmac.t | 1 - debian/modules/nginx-lua/t/047-match-jit.t | 1 - debian/modules/nginx-lua/t/048-match-dfa.t | 1 - debian/modules/nginx-lua/t/049-gmatch-jit.t | 1 - debian/modules/nginx-lua/t/050-gmatch-dfa.t | 1 - debian/modules/nginx-lua/t/051-sub-jit.t | 1 - debian/modules/nginx-lua/t/052-sub-dfa.t | 1 - debian/modules/nginx-lua/t/053-gsub-jit.t | 1 - debian/modules/nginx-lua/t/054-gsub-dfa.t | 1 - debian/modules/nginx-lua/t/055-subreq-vars.t | 1 - debian/modules/nginx-lua/t/056-flush.t | 1 - .../modules/nginx-lua/t/057-flush-timeout.t | 1 - debian/modules/nginx-lua/t/058-tcp-socket.t | 1 - debian/modules/nginx-lua/t/059-unix-socket.t | 1 - .../modules/nginx-lua/t/060-lua-memcached.t | 1 - debian/modules/nginx-lua/t/061-lua-redis.t | 1 - debian/modules/nginx-lua/t/062-count.t | 66 +- debian/modules/nginx-lua/t/063-abort.t | 1 - debian/modules/nginx-lua/t/064-pcall.t | 1 - .../nginx-lua/t/065-tcp-socket-timeout.t | 1 - .../nginx-lua/t/066-socket-receiveuntil.t | 1 - debian/modules/nginx-lua/t/067-req-socket.t | 1 - .../nginx-lua/t/068-socket-keepalive.t | 1 - debian/modules/nginx-lua/t/069-null.t | 1 - debian/modules/nginx-lua/t/070-sha1.t | 1 - debian/modules/nginx-lua/t/071-idle-socket.t | 1 - .../modules/nginx-lua/t/072-conditional-get.t | 1 - debian/modules/nginx-lua/t/073-backtrace.t | 1 - debian/modules/nginx-lua/t/074-prefix-var.t | 1 - debian/modules/nginx-lua/t/075-logby.t | 1 - debian/modules/nginx-lua/t/076-no-postpone.t | 1 - debian/modules/nginx-lua/t/077-sleep.t | 1 - debian/modules/nginx-lua/t/078-hup-vars.t | 1 - .../nginx-lua/t/079-unused-directives.t | 12 +- debian/modules/nginx-lua/t/080-hup-shdict.t | 1 - debian/modules/nginx-lua/t/081-bytecode.t | 1 - debian/modules/nginx-lua/t/082-body-filter.t | 1 - .../modules/nginx-lua/t/083-bad-sock-self.t | 1 - .../nginx-lua/t/084-inclusive-receiveuntil.t | 1 - debian/modules/nginx-lua/t/085-if.t | 1 - debian/modules/nginx-lua/t/086-init-by.t | 1 - debian/modules/nginx-lua/t/087-udp-socket.t | 1 - debian/modules/nginx-lua/t/088-req-method.t | 1 - .../nginx-lua/t/090-log-socket-errors.t | 1 - debian/modules/nginx-lua/t/091-coroutine.t | 1 - debian/modules/nginx-lua/t/092-eof.t | 1 - .../modules/nginx-lua/t/093-uthread-spawn.t | 1 - debian/modules/nginx-lua/t/094-uthread-exit.t | 1 - debian/modules/nginx-lua/t/095-uthread-exec.t | 1 - .../nginx-lua/t/096-uthread-redirect.t | 1 - .../modules/nginx-lua/t/097-uthread-rewrite.t | 1 - debian/modules/nginx-lua/t/098-uthread-wait.t | 1 - debian/modules/nginx-lua/t/099-c-api.t | 36 +- debian/modules/nginx-lua/t/100-client-abort.t | 1 - debian/modules/nginx-lua/t/101-on-abort.t | 1 - .../modules/nginx-lua/t/102-req-start-time.t | 1 - debian/modules/nginx-lua/t/103-req-http-ver.t | 1 - .../modules/nginx-lua/t/104-req-raw-header.t | 1 - debian/modules/nginx-lua/t/105-pressure.t | 1 - debian/modules/nginx-lua/t/106-timer.t | 1 - debian/modules/nginx-lua/t/107-timer-errors.t | 1 - debian/modules/nginx-lua/t/108-timer-safe.t | 1 - debian/modules/nginx-lua/t/109-timer-hup.t | 1 - debian/modules/nginx-lua/t/110-etag.t | 1 - .../modules/nginx-lua/t/111-req-header-ua.t | 1 - .../modules/nginx-lua/t/112-req-header-conn.t | 1 - .../nginx-lua/t/113-req-header-cookie.t | 1 - debian/modules/nginx-lua/t/114-config.t | 1 - .../modules/nginx-lua/t/115-quote-sql-str.t | 1 - .../modules/nginx-lua/t/116-raw-req-socket.t | 1 - .../nginx-lua/t/117-raw-req-socket-timeout.t | 1 - .../nginx-lua/t/118-use-default-type.t | 1 - .../modules/nginx-lua/t/119-config-prefix.t | 1 - debian/modules/nginx-lua/t/121-version.t | 1 - debian/modules/nginx-lua/t/123-lua-path.t | 1 - debian/modules/nginx-lua/t/124-init-worker.t | 18 +- .../modules/nginx-lua/t/125-configure-args.t | 1 - debian/modules/nginx-lua/t/126-shdict-frag.t | 2 +- debian/modules/nginx-lua/t/127-uthread-kill.t | 1 - .../nginx-lua/t/128-duplex-tcp-socket.t | 1 - debian/modules/nginx-lua/t/129-ssl-socket.t | 17 +- debian/modules/nginx-lua/t/130-internal-api.t | 2 +- debian/modules/nginx-lua/t/132-lua-blocks.t | 490 + .../nginx-lua/t/data/fake-module/config | 3 + .../t/data/fake-module/ngx_http_fake_module.c | 121 + debian/modules/nginx-lua/util/build.sh | 39 - debian/modules/nginx-lua/util/build2.sh | 8 +- debian/modules/nginx-lua/util/gen-lexer-c | 18 + debian/modules/nginx-lua/valgrind.suppress | 7 + 192 files changed, 11008 insertions(+), 715 deletions(-) delete mode 100644 debian/modules/nginx-lua/.gitignore create mode 100644 debian/modules/nginx-lua/src/ngx_http_lua_lex.c create mode 100644 debian/modules/nginx-lua/src/ngx_http_lua_lex.h create mode 100644 debian/modules/nginx-lua/t/132-lua-blocks.t create mode 100644 debian/modules/nginx-lua/t/data/fake-module/config create mode 100644 debian/modules/nginx-lua/t/data/fake-module/ngx_http_fake_module.c delete mode 100755 debian/modules/nginx-lua/util/build.sh create mode 100755 debian/modules/nginx-lua/util/gen-lexer-c diff --git a/debian/changelog b/debian/changelog index d01c0c2..08dd22b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,11 @@ +nginx (1.9.6-2) UNRELEASED; urgency=medium + + [ Christos Trochalakis] + * debian/modules/nginx-lua: + + Update nginx-lua to v0.9.19 fixing HTTP/2 compatibility. + + -- Christos Trochalakis Fri, 13 Nov 2015 16:04:32 +0200 + nginx (1.9.6-1) unstable; urgency=medium [ Christos Trochalakis] diff --git a/debian/modules/README.Modules-versions b/debian/modules/README.Modules-versions index 435eaab..3690858 100644 --- a/debian/modules/README.Modules-versions +++ b/debian/modules/README.Modules-versions @@ -22,7 +22,7 @@ README for Modules versions nginx-lua Homepage: https://github.com/openresty/lua-nginx-module - Version: v0.9.16 + Version: v0.9.19 nginx-upstream-fair Homepage: https://github.com/gnosek/nginx-upstream-fair diff --git a/debian/modules/nginx-lua/.gitignore b/debian/modules/nginx-lua/.gitignore deleted file mode 100644 index 61613b2..0000000 --- a/debian/modules/nginx-lua/.gitignore +++ /dev/null @@ -1,164 +0,0 @@ -build/ -work/ -tags -cscope.* -*.mobi -genmobi.sh -.libs -*.swp -*.slo -*.la -*.swo -*.lo -*~ -*.o -print.txt -.rsync -*.tar.gz -dist -build[789] -build -tags -update-readme -*.tmp -test/Makefile -test/blib -test.sh -t.sh -t/t.sh -test/t/servroot/ -releng -reset -*.t_ -src/handler.h -src/util.c -src/module.h -src/module.c -src/drizzle.c -src/processor.h -src/handler.c -src/util.h -src/drizzle.h -src/processor.c -src/output.c -src/output.h -libdrizzle -ctags -src/stream.h -nginx -keepalive -reindex -src/keepalive.c -src/keepalive.h -src/checker.h -src/checker.c -src/quoting.h -src/quoting.c -src/module.h -src/module.c -src/util.h -src/util.c -src/processor.h -src/processor.c -src/rds.h -src/utils.h -src/handler.c -src/handler.h -util/bench -*.html -trace.out* -try.sh -src/cache.c -src/cache.h -src/common.h -src/directive.c -src/directive.h -src/consts.[ch] -src/contentby.[ch] -src/pcrefix.[ch] -src/util.c -src/clfactory.c -src/directive.c -src/conf.h -src/setby.h -src/cache.h -src/hook.c -src/util.h -src/hook.h -src/common.h -src/directive.h -src/conf.c -src/setby.c -src/cache.c -src/module.c -src/clfactory.h -src/capturefilter.[ch] -src/contentby.c -pack -b.sh -src/in.[ch] -src/out.[ch] -go -all.sh -src/accessby.[ch] -src/rewriteby.[ch] -src/patch.[ch] -src/ndk.[ch] -src/control.[ch] -src/output.[ch] -src/variable.[ch] -src/string.[ch] -src/misc.[ch] -src/log.[ch] -src/exception.[ch] -src/subrequest.[ch] -src/time.[ch] -src/regex.[ch] -src/ctx.[ch] -src/args.[ch] -src/headers.[ch] -src/script.[ch] -src/filter.[ch] -src/shdict.[ch] -src/body.[ch] -src/uri.[ch] -src/api.[ch] -src/coroutine.[ch] -src/logby.[ch] -src/sleep.[ch] -a.patch -all -build1[0-9] -g -buildroot/ -src/headerfilterby.[ch] -*.patch -analyze -tsock -a.c -test.lua -build12 -ERRORS -src/bodyfilterby.[ch] -src/tcp.[ch] -src/initby.[ch] -src/initworkerby.[ch] -src/socket.[ch] -src/udp.[ch] -src/method.[ch] -tre -src/phase.[ch] -src/probe.h -src/uthread.[ch] -src/timer.[ch] -src/config.[ch] -src/worker.[ch] -*.plist -lua -ttimer -Makefile -tsubreq -tthread -addr2line -hup -theaders diff --git a/debian/modules/nginx-lua/README.markdown b/debian/modules/nginx-lua/README.markdown index 248c47f..da06da6 100644 --- a/debian/modules/nginx-lua/README.markdown +++ b/debian/modules/nginx-lua/README.markdown @@ -6,7 +6,7 @@ Don't edit this file manually! Instead you should generate it by using: Name ==== -ngx_lua - Embed the power of Lua into Nginx +ngx_http_lua_module - Embed the power of Lua into Nginx HTTP Servers. *This module is not distributed with the Nginx source.* See [the installation instructions](#installation). @@ -61,7 +61,7 @@ Production ready. Version ======= -This document describes ngx_lua [v0.9.16](https://github.com/openresty/lua-nginx-module/tags) released on 22 June 2015. +This document describes ngx_lua [v0.9.19](https://github.com/openresty/lua-nginx-module/tags) released on 11 November 2015. Synopsis ======== @@ -74,42 +74,13 @@ Synopsis lua_package_cpath '/bar/baz/?.so;/blah/blah/?.so;;'; server { - location /inline_concat { - # MIME type determined by default_type: - default_type 'text/plain'; - - set $a "hello"; - set $b "world"; - # inline Lua script - set_by_lua $res "return ngx.arg[1]..ngx.arg[2]" $a $b; - echo $res; - } - - location /rel_file_concat { - set $a "foo"; - set $b "bar"; - # script path relative to nginx prefix - # $ngx_prefix/conf/concat.lua contents: - # - # return ngx.arg[1]..ngx.arg[2] - # - set_by_lua_file $res conf/concat.lua $a $b; - echo $res; - } - - location /abs_file_concat { - set $a "fee"; - set $b "baz"; - # absolute script path not modified - set_by_lua_file $res /usr/nginx/conf/concat.lua $a $b; - echo $res; - } - location /lua_content { # MIME type determined by default_type: default_type 'text/plain'; - content_by_lua "ngx.say('Hello,world!')"; + content_by_lua_block { + ngx.say('Hello,world!') + } } location /nginx_var { @@ -117,84 +88,61 @@ Synopsis default_type 'text/plain'; # try access /nginx_var?a=hello,world - content_by_lua "ngx.print(ngx.var['arg_a'], '\\n')"; + content_by_lua_block { + ngx.say(ngx.var.arg_a) + } } - location /request_body { - # force reading request body (default off) - lua_need_request_body on; - client_max_body_size 50k; - client_body_buffer_size 50k; + location = /request_body { + client_max_body_size 50k; + client_body_buffer_size 50k; - content_by_lua 'ngx.print(ngx.var.request_body)'; + content_by_lua_block { + ngx.req.read_body() -- explicitly read the req body + local data = ngx.req.get_body_data() + if data then + ngx.say("body data:") + ngx.print(data) + return + end + + -- body may get buffered in a temp file: + local file = ngx.req.get_body_file() + if file then + ngx.say("body is in file ", file) + else + ngx.say("no body found") + end + } } # transparent non-blocking I/O in Lua via subrequests - location /lua { + # (well, a better way is to use cosockets) + location = /lua { # MIME type determined by default_type: default_type 'text/plain'; - content_by_lua ' + content_by_lua_block { local res = ngx.location.capture("/some_other_location") - if res.status == 200 then + if res then + ngx.say("status: ", res.status) + ngx.say("body:") ngx.print(res.body) end'; + } } - # GET /recur?num=5 - location /recur { - # MIME type determined by default_type: - default_type 'text/plain'; - - content_by_lua ' - local num = tonumber(ngx.var.arg_num) or 0 - - if num > 50 then - ngx.say("num too big") - return - end - - ngx.say("num is: ", num) - - if num > 0 then - res = ngx.location.capture("/recur?num=" .. tostring(num - 1)) - ngx.print("status=", res.status, " ") - ngx.print("body=", res.body) - else - ngx.say("end") - end - '; - } - - location /foo { - rewrite_by_lua ' + location = /foo { + rewrite_by_lua_block { res = ngx.location.capture("/memc", { args = { cmd = "incr", key = ngx.var.uri } } ) - '; + } proxy_pass http://blah.blah.com; } - location /blah { - access_by_lua ' - local res = ngx.location.capture("/auth") - - if res.status == ngx.HTTP_OK then - return - end - - if res.status == ngx.HTTP_FORBIDDEN then - ngx.exit(res.status) - end - - ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) - '; - - # proxy_pass/fastcgi_pass/postgres_pass/... - } - - location /mixed { + location = /mixed { rewrite_by_lua_file /path/to/rewrite.lua; access_by_lua_file /path/to/access.lua; content_by_lua_file /path/to/content.lua; @@ -209,26 +157,24 @@ Synopsis } location / { - lua_need_request_body on; - client_max_body_size 100k; client_body_buffer_size 100k; - access_by_lua ' + access_by_lua_block { -- check the client IP address is in our black list if ngx.var.remote_addr == "132.5.72.3" then ngx.exit(ngx.HTTP_FORBIDDEN) end - -- check if the request body contains bad words - if ngx.var.request_body and - string.match(ngx.var.request_body, "fsck") + -- check if the URI contains bad words + if ngx.var.uri and + string.match(ngx.var.request_body, "evil") then return ngx.redirect("/terms_of_use.html") end -- tests passed - '; + } # proxy_pass/fastcgi_pass/etc settings } @@ -254,6 +200,8 @@ At least the following Lua libraries and Nginx modules can be used with this ngx * [lua-resty-upload](https://github.com/openresty/lua-resty-upload) * [lua-resty-websocket](https://github.com/openresty/lua-resty-websocket) * [lua-resty-lock](https://github.com/openresty/lua-resty-lock) +* [lua-resty-logger-socket](https://github.com/cloudflare/lua-resty-logger-socket) +* [lua-resty-lrucache](https://github.com/openresty/lua-resty-lrucache) * [lua-resty-string](https://github.com/openresty/lua-resty-string) * [ngx_memc](http://github.com/openresty/memc-nginx-module) * [ngx_postgres](https://github.com/FRiCKLE/ngx_postgres) @@ -295,6 +243,7 @@ Nginx Compatibility =================== The latest module is compatible with the following versions of Nginx: +* 1.9.x (last tested: 1.9.3) * 1.7.x (last tested: 1.7.10) * 1.6.x * 1.5.x (last tested: 1.5.12) @@ -315,7 +264,7 @@ It is highly recommended to use the [ngx_openresty bundle](http://openresty.org) Alternatively, ngx_lua can be manually compiled into Nginx: -1. Install LuaJIT 2.0 or 2.1 (recommended) or Lua 5.1 (Lua 5.2 is *not* supported yet). LuaJIT can be downloaded from the [the LuaJIT project website](http://luajit.org/download.html) and Lua 5.1, from the [Lua project website](http://www.lua.org/). Some distribution package managers also distribute LuajIT and/or Lua. +1. Install LuaJIT 2.0 or 2.1 (recommended) or Lua 5.1 (Lua 5.2 is *not* supported yet). LuaJIT can be downloaded from the [the LuaJIT project website](http://luajit.org/download.html) and Lua 5.1, from the [Lua project website](http://www.lua.org/). Some distribution package managers also distribute LuaJIT and/or Lua. 1. Download the latest version of the ngx_devel_kit (NDK) module [HERE](https://github.com/simpl/ngx_devel_kit/tags). 1. Download the latest version of ngx_lua [HERE](https://github.com/openresty/lua-nginx-module/tags). 1. Download the latest version of Nginx [HERE](http://nginx.org/) (See [Nginx Compatibility](#nginx-compatibility)) @@ -324,9 +273,9 @@ Build the source with this module: ```bash - wget 'http://nginx.org/download/nginx-1.7.10.tar.gz' - tar -xzvf nginx-1.7.10.tar.gz - cd nginx-1.7.10/ + wget 'http://nginx.org/download/nginx-1.9.3.tar.gz' + tar -xzvf nginx-1.9.3.tar.gz + cd nginx-1.9.3/ # tell nginx's build system where to find LuaJIT 2.0: export LUAJIT_LIB=/path/to/luajit/lib @@ -342,7 +291,7 @@ Build the source with this module: # Here we assume Nginx is to be installed under /opt/nginx/. ./configure --prefix=/opt/nginx \ - --with-ld-opt='-Wl,-rpath,/path/to/luajit-or-lua/lib" \ + --with-ld-opt="-Wl,-rpath,/path/to/luajit-or-lua/lib" \ --add-module=/path/to/ngx_devel_kit \ --add-module=/path/to/lua-nginx-module @@ -753,6 +702,10 @@ There exists a work-around, however, when the original context does *not* need t Special Escaping Sequences -------------------------- + +**WARNING** We no longer suffer from this pitfall since the introduction of the +`*_by_lua_block {}` configuration directives. + PCRE sequences such as `\d`, `\s`, or `\w`, require special attention because in string literals, the backslash character, `\`, is stripped out by both the Lua language parser and by the Nginx config file parser before processing. So the following snippet will not work as expected: ```nginx @@ -881,21 +834,6 @@ phases. TODO ==== -* add `*_by_lua_block` directives for existing `*_by_lua` directives so that we put literal Lua code directly in curly braces instead of an nginx literal string. For example, -```nginx - - content_by_lua_block { - ngx.say("hello, world\r\n") - } -``` - which is equivalent to -```nginx - - content_by_lua ' - ngx.say("hello, world\\r\\n") - '; -``` - but the former is much cleaner and nicer. * cosocket: implement LuaSocket's unconnected UDP API. * add support for implementing general TCP servers instead of HTTP servers in Lua. For example, ```lua @@ -1064,22 +1002,31 @@ Directives * [lua_package_path](#lua_package_path) * [lua_package_cpath](#lua_package_cpath) * [init_by_lua](#init_by_lua) +* [init_by_lua_block](#init_by_lua_block) * [init_by_lua_file](#init_by_lua_file) * [init_worker_by_lua](#init_worker_by_lua) +* [init_worker_by_lua_block](#init_worker_by_lua_block) * [init_worker_by_lua_file](#init_worker_by_lua_file) * [set_by_lua](#set_by_lua) +* [set_by_lua_block](#set_by_lua_block) * [set_by_lua_file](#set_by_lua_file) * [content_by_lua](#content_by_lua) +* [content_by_lua_block](#content_by_lua_block) * [content_by_lua_file](#content_by_lua_file) * [rewrite_by_lua](#rewrite_by_lua) +* [rewrite_by_lua_block](#rewrite_by_lua_block) * [rewrite_by_lua_file](#rewrite_by_lua_file) * [access_by_lua](#access_by_lua) +* [access_by_lua_block](#access_by_lua_block) * [access_by_lua_file](#access_by_lua_file) * [header_filter_by_lua](#header_filter_by_lua) +* [header_filter_by_lua_block](#header_filter_by_lua_block) * [header_filter_by_lua_file](#header_filter_by_lua_file) * [body_filter_by_lua](#body_filter_by_lua) +* [body_filter_by_lua_block](#body_filter_by_lua_block) * [body_filter_by_lua_file](#body_filter_by_lua_file) * [log_by_lua](#log_by_lua) +* [log_by_lua_block](#log_by_lua_block) * [log_by_lua_file](#log_by_lua_file) * [lua_need_request_body](#lua_need_request_body) * [lua_shared_dict](#lua_shared_dict) @@ -1241,6 +1188,9 @@ init_by_lua **phase:** *loading-config* +**WARNING** Since the `v0.9.17` release, use of this directive is *discouraged*; +use the new [init_by_lua_block](#init_by_lua_block) directive instead. + Runs the Lua code specified by the argument `` on the global Lua VM level when the Nginx master process (if any) is loading the Nginx config file. When Nginx receives the `HUP` signal and starts reloading the config file, the Lua VM will also be re-created and `init_by_lua` will run again on the new Lua VM. In case that the [lua_code_cache](#lua_code_cache) directive is turned off (default on), the `init_by_lua` handler will run upon every request because in this special mode a standalone Lua VM is always created for each request. @@ -1302,6 +1252,33 @@ This directive was first introduced in the `v0.5.5` release. [Back to TOC](#directives) +init_by_lua_block +----------------- + +**syntax:** *init_by_lua_block { lua-script }* + +**context:** *http* + +**phase:** *loading-config* + +Similar to the [init_by_lua](#init_by_lua) directive except that this directive inlines +the Lua source directly +inside a pair of curly braces (`{}`) instead of in an NGINX string literal (which requires +special character escaping). + +For instance, + +```nginx + + init_by_lua_block { + print("I need no extra escaping here, for example: \r\nblah") + } +``` + +This directive was first introduced in the `v0.9.17` release. + +[Back to TOC](#directives) + init_by_lua_file ---------------- @@ -1328,9 +1305,11 @@ init_worker_by_lua **phase:** *starting-worker* +**WARNING** Since the `v0.9.17` release, use of this directive is *discouraged*; use the new [init_worker_by_lua_block](#init_worker_by_lua_block) directive instead. + Runs the specified Lua code upon every Nginx worker process's startup when the master process is enabled. When the master process is disabled, this hook will just run after [init_by_lua*](#init_by_lua). -This hook is often used to create per-worker reoccurring timers (via the [ngx.timer.at](#ngxtimerat) Lua API), either for backend healthcheck or other timed routine work. Below is an example, +This hook is often used to create per-worker reoccurring timers (via the [ngx.timer.at](#ngxtimerat) Lua API), either for backend health-check or other timed routine work. Below is an example, ```nginx @@ -1364,6 +1343,33 @@ This directive was first introduced in the `v0.9.5` release. [Back to TOC](#directives) +init_worker_by_lua_block +------------------------ + +**syntax:** *init_worker_by_lua_block { lua-script }* + +**context:** *http* + +**phase:** *starting-worker* + +Similar to the [init_worker_by_lua](#init_worker_by_lua) directive except that this directive inlines +the Lua source directly +inside a pair of curly braces (`{}`) instead of in an NGINX string literal (which requires +special character escaping). + +For instance, + +```nginx + + init_worker_by_lua_block { + print("I need no extra escaping here, for example: \r\nblah") + } +``` + +This directive was first introduced in the `v0.9.17` release. + +[Back to TOC](#directives) + init_worker_by_lua_file ----------------------- @@ -1388,7 +1394,9 @@ set_by_lua **phase:** *rewrite* -Executes code specified in `` with optional input arguments `$arg1 $arg2 ...`, and returns string output to `$res`. +**WARNING** Since the `v0.9.17` release, use of this directive is *discouraged*; use the new [set_by_lua_block](#set_by_lua_block) directive instead. + +Executes code specified in `` with optional input arguments `$arg1 $arg2 ...`, and returns string output to `$res`. The code in `` can make [API calls](#nginx-api-for-lua) and can retrieve input arguments from the `ngx.arg` table (index starts from `1` and increases sequentially). This directive is designed to execute short, fast running code blocks as the Nginx event loop is blocked during code execution. Time consuming code sequences should therefore be avoided. @@ -1398,7 +1406,7 @@ This directive is implemented by injecting custom commands into the standard [ng At least the following API functions are currently disabled within the context of `set_by_lua`: * Output API functions (e.g., [ngx.say](#ngxsay) and [ngx.send_headers](#ngxsend_headers)) -* Control API functions (e.g., [ngx.exit](#ngxexit)) +* Control API functions (e.g., [ngx.exit](#ngxexit)) * Subrequest API functions (e.g., [ngx.location.capture](#ngxlocationcapture) and [ngx.location.capture_multi](#ngxlocationcapture_multi)) * Cosocket API functions (e.g., [ngx.socket.tcp](#ngxsockettcp) and [ngx.req.socket](#ngxreqsocket)). * Sleeping API function [ngx.sleep](#ngxsleep). @@ -1428,7 +1436,7 @@ This directive can be freely mixed with all directives of the [ngx_http_rewrite_ ```nginx set $foo 32; - set_by_lua $bar 'tonumber(ngx.var.foo) + 1'; + set_by_lua $bar 'return tonumber(ngx.var.foo) + 1'; set $baz "bar: $bar"; # $baz == "bar: 33" ``` @@ -1438,6 +1446,36 @@ This directive requires the [ngx_devel_kit](https://github.com/simpl/ngx_devel_k [Back to TOC](#directives) +set_by_lua_block +---------------- + +**syntax:** *set_by_lua_block $res { lua-script }* + +**context:** *server, server if, location, location if* + +**phase:** *rewrite* + +Similar to the [set_by_lua](#set_by_lua) directive except that + +1. this directive inlines the Lua source directly +inside a pair of curly braces (`{}`) instead of in an NGINX string literal (which requires +special character escaping), and +1. this directive does not support extra arguments after the Lua script as in [set_by_lua](#set_by_lua). + +For example, + +```nginx + + set_by_lua_block $res { return 32 + math.cos(32) } + # $res now has the value "32.834223360507" or alike. +``` + +No special escaping is required in the Lua code block. + +This directive was first introduced in the `v0.9.17` release. + +[Back to TOC](#directives) + set_by_lua_file --------------- **syntax:** *set_by_lua_file $res <path-to-lua-script-file> [$arg1 $arg2 ...]* @@ -1470,6 +1508,9 @@ content_by_lua **phase:** *content* +**WARNING** Since the `v0.9.17` release, use of this directive is *discouraged*; +use the new [content_by_lua_block](#content_by_lua_block) directive instead. + Acts as a "content handler" and executes Lua code string specified in `` for every request. The Lua code may make [API calls](#nginx-api-for-lua) and is executed as a new spawned coroutine in an independent global environment (i.e. a sandbox). @@ -1477,6 +1518,33 @@ Do not use this directive and other content handler directives in the same locat [Back to TOC](#directives) +content_by_lua_block +-------------------- + +**syntax:** *content_by_lua_block { lua-script }* + +**context:** *location, location if* + +**phase:** *content* + +Similar to the [content_by_lua](#content_by_lua) directive except that this directive inlines +the Lua source directly +inside a pair of curly braces (`{}`) instead of in an NGINX string literal (which requires +special character escaping). + +For instance, + +```nginx + + content_by_lua_block { + ngx.say("I need no extra escaping here, for example: \r\nblah") + } +``` + +This directive was first introduced in the `v0.9.17` release. + +[Back to TOC](#directives) + content_by_lua_file ------------------- @@ -1522,6 +1590,9 @@ rewrite_by_lua **phase:** *rewrite tail* +**WARNING** Since the `v0.9.17` release, use of this directive is *discouraged*; +use the new [rewrite_by_lua_block](#rewrite_by_lua_block) directive instead. + Acts as a rewrite phase handler and executes Lua code string specified in `` for every request. The Lua code may make [API calls](#nginx-api-for-lua) and is executed as a new spawned coroutine in an independent global environment (i.e. a sandbox). @@ -1637,6 +1708,33 @@ The `rewrite_by_lua` code will always run at the end of the `rewrite` request-pr [Back to TOC](#directives) +rewrite_by_lua_block +-------------------- + +**syntax:** *rewrite_by_lua_block { lua-script }* + +**context:** *http, server, location, location if* + +**phase:** *rewrite tail* + +Similar to the [rewrite_by_lua](#rewrite_by_lua) directive except that this directive inlines +the Lua source directly +inside a pair of curly braces (`{}`) instead of in an NGINX string literal (which requires +special character escaping). + +For instance, + +```nginx + + rewrite_by_lua_block { + do_something("hello, world!\nhiya\n") + } +``` + +This directive was first introduced in the `v0.9.17` release. + +[Back to TOC](#directives) + rewrite_by_lua_file ------------------- @@ -1669,6 +1767,9 @@ access_by_lua **phase:** *access tail* +**WARNING** Since the `v0.9.17` release, use of this directive is *discouraged*; +use the new [access_by_lua_block](#access_by_lua_block) directive instead. + Acts as an access phase handler and executes Lua code string specified in `` for every request. The Lua code may make [API calls](#nginx-api-for-lua) and is executed as a new spawned coroutine in an independent global environment (i.e. a sandbox). @@ -1733,6 +1834,33 @@ Note that when calling `ngx.exit(ngx.OK)` within a [access_by_lua](#access_by_lu [Back to TOC](#directives) +access_by_lua_block +------------------- + +**syntax:** *access_by_lua_block { lua-script }* + +**context:** *http, server, location, location if* + +**phase:** *access tail* + +Similar to the [access_by_lua](#access_by_lua) directive except that this directive inlines +the Lua source directly +inside a pair of curly braces (`{}`) instead of in an NGINX string literal (which requires +special character escaping). + +For instance, + +```nginx + + access_by_lua_block { + do_something("hello, world!\nhiya\n") + } +``` + +This directive was first introduced in the `v0.9.17` release. + +[Back to TOC](#directives) + access_by_lua_file ------------------ @@ -1765,12 +1893,15 @@ header_filter_by_lua **phase:** *output-header-filter* +**WARNING** Since the `v0.9.17` release, use of this directive is *discouraged*; +use the new [header_filter_by_lua_block](#header_filter_by_lua_block) directive instead. + Uses Lua code specified in `` to define an output header filter. Note that the following API functions are currently disabled within this context: * Output API functions (e.g., [ngx.say](#ngxsay) and [ngx.send_headers](#ngxsend_headers)) -* Control API functions (e.g., [ngx.exit](#ngxexit) and [ngx.exec](#ngxexec)) +* Control API functions (e.g., [ngx.redirect](#ngxredirect) and [ngx.exec](#ngxexec)) * Subrequest API functions (e.g., [ngx.location.capture](#ngxlocationcapture) and [ngx.location.capture_multi](#ngxlocationcapture_multi)) * Cosocket API functions (e.g., [ngx.socket.tcp](#ngxsockettcp) and [ngx.req.socket](#ngxreqsocket)). @@ -1788,6 +1919,33 @@ This directive was first introduced in the `v0.2.1rc20` release. [Back to TOC](#directives) +header_filter_by_lua_block +-------------------------- + +**syntax:** *header_filter_by_lua_block { lua-script }* + +**context:** *http, server, location, location if* + +**phase:** *output-header-filter* + +Similar to the [header_filter_by_lua](#header_filter_by_lua) directive except that this directive inlines +the Lua source directly +inside a pair of curly braces (`{}`) instead of in an NGINX string literal (which requires +special character escaping). + +For instance, + +```nginx + + header_filter_by_lua_block { + ngx.header["content-length"] = nil + } +``` + +This directive was first introduced in the `v0.9.17` release. + +[Back to TOC](#directives) + header_filter_by_lua_file ------------------------- @@ -1814,6 +1972,9 @@ body_filter_by_lua **phase:** *output-body-filter* +**WARNING** Since the `v0.9.17` release, use of this directive is *discouraged*; +use the new [body_filter_by_lua_block](#body_filter_by_lua_block) directive instead. + Uses Lua code specified in `` to define an output body filter. The input data chunk is passed via [ngx.arg](#ngxarg)\[1\] (as a Lua string value) and the "eof" flag indicating the end of the response body data stream is passed via [ngx.arg](#ngxarg)\[2\] (as a Lua boolean value). @@ -1895,6 +2056,33 @@ This directive was first introduced in the `v0.5.0rc32` release. [Back to TOC](#directives) +body_filter_by_lua_block +------------------------ + +**syntax:** *body_filter_by_lua_block { lua-script-str }* + +**context:** *http, server, location, location if* + +**phase:** *output-body-filter* + +Similar to the [body_filter_by_lua](#body_filter_by_lua) directive except that this directive inlines +the Lua source directly +inside a pair of curly braces (`{}`) instead of in an NGINX string literal (which requires +special character escaping). + +For instance, + +```nginx + + body_filter_by_lua_block { + local data, eof = ngx.arg[1], ngx.arg[2] + } +``` + +This directive was first introduced in the `v0.9.17` release. + +[Back to TOC](#directives) + body_filter_by_lua_file ----------------------- @@ -1921,7 +2109,10 @@ log_by_lua **phase:** *log* -Run the Lua source code inlined as the `` at the `log` request processing phase. This does not replace the current access logs, but runs after. +**WARNING** Since the `v0.9.17` release, use of this directive is *discouraged*; +use the new [log_by_lua_block](#log_by_lua_block) directive instead. + +Runs the Lua source code inlined as the `` at the `log` request processing phase. This does not replace the current access logs, but runs after. Note that the following API functions are currently disabled within this context: @@ -1977,6 +2168,33 @@ This directive was first introduced in the `v0.5.0rc31` release. [Back to TOC](#directives) +log_by_lua_block +---------------- + +**syntax:** *log_by_lua_block { lua-script }* + +**context:** *http, server, location, location if* + +**phase:** *log* + +Similar to the [log_by_lua](#log_by_lua) directive except that this directive inlines +the Lua source directly +inside a pair of curly braces (`{}`) instead of in an NGINX string literal (which requires +special character escaping). + +For instance, + +```nginx + + log_by_lua_block { + print("I need no extra escaping here, for example: \r\nblah") + } +``` + +This directive was first introduced in the `v0.9.17` release. + +[Back to TOC](#directives) + log_by_lua_file --------------- @@ -2637,7 +2855,7 @@ many others are not, like `$query_string`, `$arg_PARAMETER`, and `$http_NAME`. Nginx regex group capturing variables `$1`, `$2`, `$3`, and etc, can be read by this interface as well, by writing `ngx.var[1]`, `ngx.var[2]`, `ngx.var[3]`, and etc. -Setting `ngx.var.Foo` to a `nil` value will unset the `$Foo` Nginx variable. +Setting `ngx.var.Foo` to a `nil` value will unset the `$Foo` Nginx variable. ```lua @@ -2654,6 +2872,8 @@ Setting `ngx.var.Foo` to a `nil` value will unset the `$Foo` Nginx variable. to prevent (temporary) memory leaking within the current request's lifetime. Another way of caching the result is to use the [ngx.ctx](#ngxctx) table. +Undefined NGINX variables are evaluated to `nil` while uninitialized (but defined) NGINX variables are evaluated to an empty Lua string. + This API requires a relatively expensive metamethod call and it is recommended to avoid using it on hot code paths. [Back to TOC](#nginx-api-for-lua) @@ -2912,7 +3132,7 @@ Here is a basic example: res = ngx.location.capture(uri) ``` -Returns a Lua table with three slots (`res.status`, `res.header`, `res.body`, and `res.truncated`). +Returns a Lua table with 4 slots: `res.status`, `res.header`, `res.body`, and `res.truncated`. `res.status` holds the response status code for the subrequest response. @@ -3502,7 +3722,7 @@ ngx.req.set_method **context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua** -Overrides the current request's request method with the `request_id` argument. Currently only numerical [method constants](#http-method-constants) are supported, like `ngx.HTTP_POST` and `ngx.HTTP_GET`. +Overrides the current request's request method with the `method_id` argument. Currently only numerical [method constants](#http-method-constants) are supported, like `ngx.HTTP_POST` and `ngx.HTTP_GET`. If the current request is an Nginx subrequest, then the subrequest's method will be overridden. @@ -3559,7 +3779,7 @@ or equivalently, ngx.req.set_uri("/foo") ``` -The `jump` can only be set to `true` in [rewrite_by_lua](#rewrite_by_lua) and [rewrite_by_lua_file](#rewrite_by_lua_file). Use of jump in other contexts is prohibited and will throw out a Lua exception. +The `jump` argument can only be set to `true` in [rewrite_by_lua](#rewrite_by_lua) and [rewrite_by_lua_file](#rewrite_by_lua_file). Use of jump in other contexts is prohibited and will throw out a Lua exception. A more sophisticated example involving regex substitutions is as follows @@ -3567,7 +3787,7 @@ A more sophisticated example involving regex substitutions is as follows location /test { rewrite_by_lua ' - local uri = ngx.re.sub(ngx.var.uri, "^/test/(.*)", "$1", "o") + local uri = ngx.re.sub(ngx.var.uri, "^/test/(.*)", "/$1", "o") ngx.req.set_uri(uri) '; proxy_pass http://my_backend; @@ -3808,7 +4028,7 @@ will yield: a b: 1a 2 ``` -Arguments without the `=` parts are treated as boolean arguments. `GET /test?foo&bar` will yield: +Arguments without the `=` parts are treated as boolean arguments. `POST /test` with the request body `foo&bar` will yield: ```bash @@ -3893,14 +4113,14 @@ However, the optional `max_headers` function argument can be used to override th ```lua - local args = ngx.req.get_headers(10) + local headers = ngx.req.get_headers(10) ``` This argument can be set to zero to remove the limit and to process all request headers received: ```lua - local args = ngx.req.get_headers(0) + local headers = ngx.req.get_headers(0) ``` Removing the `max_headers` cap is strongly discouraged. diff --git a/debian/modules/nginx-lua/config b/debian/modules/nginx-lua/config index 28b4078..4b770d7 100644 --- a/debian/modules/nginx-lua/config +++ b/debian/modules/nginx-lua/config @@ -14,32 +14,77 @@ ngx_lua_opt_L= if [ -n "$LUAJIT_INC" -o -n "$LUAJIT_LIB" ]; then # explicitly set LuaJIT paths - # attempt to link with -ldl, static linking on Linux requires it. - ngx_feature="LuaJIT library in $LUAJIT_LIB and $LUAJIT_INC (specified by the LUAJIT_LIB and LUAJIT_INC env, with -ldl)" - ngx_feature_path="$LUAJIT_INC" - ngx_lua_opt_I="-I$LUAJIT_INC" - ngx_lua_opt_L="-L$LUAJIT_LIB" - if [ $NGX_RPATH = YES ]; then - ngx_feature_libs="-R$LUAJIT_LIB $ngx_lua_opt_L -lluajit-5.1 -lm -ldl" - else - ngx_feature_libs="$ngx_lua_opt_L -lluajit-5.1 -lm -ldl" - fi - - . auto/feature - - if [ $ngx_found = no ]; then - # retry without -ldl - ngx_feature="LuaJIT library in $LUAJIT_LIB and $LUAJIT_INC (specified by the LUAJIT_LIB and LUAJIT_INC env)" + if [ "$NGX_PLATFORM" = win32 ]; then + ngx_feature="LuaJIT library in $LUAJIT_LIB and $LUAJIT_INC (win32)" ngx_feature_path="$LUAJIT_INC" ngx_lua_opt_I="-I$LUAJIT_INC" ngx_lua_opt_L="-L$LUAJIT_LIB" + + # ensure that our -I$LUAJIT_INC and -L$LUAJIT_LIB is at the first. + SAVED_CC_TEST_FLAGS="$CC_TEST_FLAGS" + CC_TEST_FLAGS="$ngx_lua_opt_I $CC_TEST_FLAGS" + SAVED_NGX_TEST_LD_OPT="$NGX_TEST_LD_OPT" + NGX_TEST_LD_OPT="$ngx_lua_opt_L $NGX_TEST_LD_OPT" + + # LuaJIT's win32 build uses the library file name lua51.dll. + ngx_feature_libs="$ngx_lua_opt_L -llua51" + + . auto/feature + + # clean up + CC_TEST_FLAGS="$SAVED_CC_TEST_FLAGS" + NGX_TEST_LD_OPT="$SAVED_NGX_TEST_LD_OPT" + else + + # attempt to link with -ldl, static linking on Linux requires it. + ngx_feature="LuaJIT library in $LUAJIT_LIB and $LUAJIT_INC (specified by the LUAJIT_LIB and LUAJIT_INC env, with -ldl)" + ngx_feature_path="$LUAJIT_INC" + ngx_lua_opt_I="-I$LUAJIT_INC" + ngx_lua_opt_L="-L$LUAJIT_LIB" + + # ensure that our -I$LUAJIT_INC and -L$LUAJIT_LIB is at the first. + SAVED_CC_TEST_FLAGS="$CC_TEST_FLAGS" + CC_TEST_FLAGS="$ngx_lua_opt_I $CC_TEST_FLAGS" + SAVED_NGX_TEST_LD_OPT="$NGX_TEST_LD_OPT" + NGX_TEST_LD_OPT="$ngx_lua_opt_L $NGX_TEST_LD_OPT" + if [ $NGX_RPATH = YES ]; then - ngx_feature_libs="-R$LUAJIT_LIB $ngx_lua_opt_L -lluajit-5.1 -lm" + ngx_feature_libs="-R$LUAJIT_LIB $ngx_lua_opt_L -lluajit-5.1 -lm -ldl" else - ngx_feature_libs="$ngx_lua_opt_L -lluajit-5.1 -lm" + ngx_feature_libs="$ngx_lua_opt_L -lluajit-5.1 -lm -ldl" fi . auto/feature + + # clean up + CC_TEST_FLAGS="$SAVED_CC_TEST_FLAGS" + NGX_TEST_LD_OPT="$SAVED_NGX_TEST_LD_OPT" + + if [ $ngx_found = no ]; then + # retry without -ldl + ngx_feature="LuaJIT library in $LUAJIT_LIB and $LUAJIT_INC (specified by the LUAJIT_LIB and LUAJIT_INC env)" + ngx_feature_path="$LUAJIT_INC" + ngx_lua_opt_I="-I$LUAJIT_INC" + ngx_lua_opt_L="-L$LUAJIT_LIB" + + # ensure that our -I$LUAJIT_INC and -L$LUAJIT_LIB is at the first. + SAVED_CC_TEST_FLAGS="$CC_TEST_FLAGS" + CC_TEST_FLAGS="$ngx_lua_opt_I $CC_TEST_FLAGS" + SAVED_NGX_TEST_LD_OPT="$NGX_TEST_LD_OPT" + NGX_TEST_LD_OPT="$ngx_lua_opt_L $NGX_TEST_LD_OPT" + + if [ $NGX_RPATH = YES ]; then + ngx_feature_libs="-R$LUAJIT_LIB $ngx_lua_opt_L -lluajit-5.1 -lm" + else + ngx_feature_libs="$ngx_lua_opt_L -lluajit-5.1 -lm" + fi + + . auto/feature + + # clean up + CC_TEST_FLAGS="$SAVED_CC_TEST_FLAGS" + NGX_TEST_LD_OPT="$SAVED_NGX_TEST_LD_OPT" + fi fi if [ $ngx_found = no ]; then @@ -72,6 +117,13 @@ else ngx_feature_path="$LUA_INC" ngx_lua_opt_I="-I$LUA_INC" ngx_lua_opt_L="-L$LUA_LIB" + + # ensure that our -I$LUA_INC and -L$LUA_LIB is at the first. + SAVED_CC_TEST_FLAGS="$CC_TEST_FLAGS" + CC_TEST_FLAGS="$ngx_lua_opt_I $CC_TEST_FLAGS" + SAVED_NGX_TEST_LD_OPT="$NGX_TEST_LD_OPT" + NGX_TEST_LD_OPT="$ngx_lua_opt_L $NGX_TEST_LD_OPT" + if [ $NGX_RPATH = YES ]; then ngx_feature_libs="-R$LUA_LIB $ngx_lua_opt_L -llua -lm -ldl" else @@ -80,12 +132,23 @@ else . auto/feature + # clean up + CC_TEST_FLAGS="$SAVED_CC_TEST_FLAGS" + NGX_TEST_LD_OPT="$SAVED_NGX_TEST_LD_OPT" + if [ $ngx_found = no ]; then # retry without -ldl ngx_feature_path="$LUA_INC" ngx_lua_opt_I="-I$LUA_INC" ngx_lua_opt_L="-L$LUA_LIB" + + # ensure that our -I$LUA_INC and -L$LUA_LIB is at the first. + SAVED_CC_TEST_FLAGS="$CC_TEST_FLAGS" + CC_TEST_FLAGS="$ngx_lua_opt_I $CC_TEST_FLAGS" + SAVED_NGX_TEST_LD_OPT="$NGX_TEST_LD_OPT" + NGX_TEST_LD_OPT="$ngx_lua_opt_L $NGX_TEST_LD_OPT" + if [ $NGX_RPATH = YES ]; then ngx_feature_libs="-R$LUA_LIB $ngx_lua_opt_L -llua -lm" else @@ -93,6 +156,10 @@ else fi . auto/feature + + # clean up + CC_TEST_FLAGS="$SAVED_CC_TEST_FLAGS" + NGX_TEST_LD_OPT="$SAVED_NGX_TEST_LD_OPT" fi if [ $ngx_found = no ]; then @@ -283,6 +350,7 @@ NGX_ADDON_SRCS="$NGX_ADDON_SRCS \ $ngx_addon_dir/src/ngx_http_lua_timer.c \ $ngx_addon_dir/src/ngx_http_lua_config.c \ $ngx_addon_dir/src/ngx_http_lua_worker.c \ + $ngx_addon_dir/src/ngx_http_lua_lex.c \ " NGX_ADDON_DEPS="$NGX_ADDON_DEPS \ @@ -336,6 +404,7 @@ NGX_ADDON_DEPS="$NGX_ADDON_DEPS \ $ngx_addon_dir/src/ngx_http_lua_timer.h \ $ngx_addon_dir/src/ngx_http_lua_config.h \ $ngx_addon_dir/src/ngx_http_lua_worker.h \ + $ngx_addon_dir/src/ngx_http_lua_lex.h \ " CFLAGS="$CFLAGS -DNDK_SET_VAR" diff --git a/debian/modules/nginx-lua/doc/HttpLuaModule.wiki b/debian/modules/nginx-lua/doc/HttpLuaModule.wiki index 7e72449..3726509 100644 --- a/debian/modules/nginx-lua/doc/HttpLuaModule.wiki +++ b/debian/modules/nginx-lua/doc/HttpLuaModule.wiki @@ -1,6 +1,6 @@ = Name = -ngx_lua - Embed the power of Lua into Nginx +ngx_http_lua_module - Embed the power of Lua into Nginx HTTP Servers. ''This module is not distributed with the Nginx source.'' See [[#Installation|the installation instructions]]. @@ -10,7 +10,7 @@ Production ready. = Version = -This document describes ngx_lua [https://github.com/openresty/lua-nginx-module/tags v0.9.16] released on 22 June 2015. +This document describes ngx_lua [https://github.com/openresty/lua-nginx-module/tags v0.9.19] released on 11 November 2015. = Synopsis = @@ -21,42 +21,13 @@ This document describes ngx_lua [https://github.com/openresty/lua-nginx-module/t lua_package_cpath '/bar/baz/?.so;/blah/blah/?.so;;'; server { - location /inline_concat { - # MIME type determined by default_type: - default_type 'text/plain'; - - set $a "hello"; - set $b "world"; - # inline Lua script - set_by_lua $res "return ngx.arg[1]..ngx.arg[2]" $a $b; - echo $res; - } - - location /rel_file_concat { - set $a "foo"; - set $b "bar"; - # script path relative to nginx prefix - # $ngx_prefix/conf/concat.lua contents: - # - # return ngx.arg[1]..ngx.arg[2] - # - set_by_lua_file $res conf/concat.lua $a $b; - echo $res; - } - - location /abs_file_concat { - set $a "fee"; - set $b "baz"; - # absolute script path not modified - set_by_lua_file $res /usr/nginx/conf/concat.lua $a $b; - echo $res; - } - location /lua_content { # MIME type determined by default_type: default_type 'text/plain'; - content_by_lua "ngx.say('Hello,world!')"; + content_by_lua_block { + ngx.say('Hello,world!') + } } location /nginx_var { @@ -64,84 +35,61 @@ This document describes ngx_lua [https://github.com/openresty/lua-nginx-module/t default_type 'text/plain'; # try access /nginx_var?a=hello,world - content_by_lua "ngx.print(ngx.var['arg_a'], '\\n')"; + content_by_lua_block { + ngx.say(ngx.var.arg_a) + } } - location /request_body { - # force reading request body (default off) - lua_need_request_body on; - client_max_body_size 50k; - client_body_buffer_size 50k; + location = /request_body { + client_max_body_size 50k; + client_body_buffer_size 50k; - content_by_lua 'ngx.print(ngx.var.request_body)'; + content_by_lua_block { + ngx.req.read_body() -- explicitly read the req body + local data = ngx.req.get_body_data() + if data then + ngx.say("body data:") + ngx.print(data) + return + end + + -- body may get buffered in a temp file: + local file = ngx.req.get_body_file() + if file then + ngx.say("body is in file ", file) + else + ngx.say("no body found") + end + } } # transparent non-blocking I/O in Lua via subrequests - location /lua { + # (well, a better way is to use cosockets) + location = /lua { # MIME type determined by default_type: default_type 'text/plain'; - content_by_lua ' + content_by_lua_block { local res = ngx.location.capture("/some_other_location") - if res.status == 200 then + if res then + ngx.say("status: ", res.status) + ngx.say("body:") ngx.print(res.body) end'; + } } - # GET /recur?num=5 - location /recur { - # MIME type determined by default_type: - default_type 'text/plain'; - - content_by_lua ' - local num = tonumber(ngx.var.arg_num) or 0 - - if num > 50 then - ngx.say("num too big") - return - end - - ngx.say("num is: ", num) - - if num > 0 then - res = ngx.location.capture("/recur?num=" .. tostring(num - 1)) - ngx.print("status=", res.status, " ") - ngx.print("body=", res.body) - else - ngx.say("end") - end - '; - } - - location /foo { - rewrite_by_lua ' + location = /foo { + rewrite_by_lua_block { res = ngx.location.capture("/memc", { args = { cmd = "incr", key = ngx.var.uri } } ) - '; + } proxy_pass http://blah.blah.com; } - location /blah { - access_by_lua ' - local res = ngx.location.capture("/auth") - - if res.status == ngx.HTTP_OK then - return - end - - if res.status == ngx.HTTP_FORBIDDEN then - ngx.exit(res.status) - end - - ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) - '; - - # proxy_pass/fastcgi_pass/postgres_pass/... - } - - location /mixed { + location = /mixed { rewrite_by_lua_file /path/to/rewrite.lua; access_by_lua_file /path/to/access.lua; content_by_lua_file /path/to/content.lua; @@ -156,26 +104,24 @@ This document describes ngx_lua [https://github.com/openresty/lua-nginx-module/t } location / { - lua_need_request_body on; - client_max_body_size 100k; client_body_buffer_size 100k; - access_by_lua ' + access_by_lua_block { -- check the client IP address is in our black list if ngx.var.remote_addr == "132.5.72.3" then ngx.exit(ngx.HTTP_FORBIDDEN) end - -- check if the request body contains bad words - if ngx.var.request_body and - string.match(ngx.var.request_body, "fsck") + -- check if the URI contains bad words + if ngx.var.uri and + string.match(ngx.var.request_body, "evil") then return ngx.redirect("/terms_of_use.html") end -- tests passed - '; + } # proxy_pass/fastcgi_pass/etc settings } @@ -198,6 +144,8 @@ At least the following Lua libraries and Nginx modules can be used with this ngx * [https://github.com/openresty/lua-resty-upload lua-resty-upload] * [https://github.com/openresty/lua-resty-websocket lua-resty-websocket] * [https://github.com/openresty/lua-resty-lock lua-resty-lock] +* [https://github.com/cloudflare/lua-resty-logger-socket lua-resty-logger-socket] +* [https://github.com/openresty/lua-resty-lrucache lua-resty-lrucache] * [https://github.com/openresty/lua-resty-string lua-resty-string] * [[HttpMemcModule|ngx_memc]] * [https://github.com/FRiCKLE/ngx_postgres ngx_postgres] @@ -233,6 +181,7 @@ The Lua state (Lua VM instance) is shared across all the requests handled by a s = Nginx Compatibility = The latest module is compatible with the following versions of Nginx: +* 1.9.x (last tested: 1.9.3) * 1.7.x (last tested: 1.7.10) * 1.6.x * 1.5.x (last tested: 1.5.12) @@ -250,7 +199,7 @@ It is highly recommended to use the [http://openresty.org ngx_openresty bundle] Alternatively, ngx_lua can be manually compiled into Nginx: -# Install LuaJIT 2.0 or 2.1 (recommended) or Lua 5.1 (Lua 5.2 is ''not'' supported yet). LuaJIT can be downloaded from the [http://luajit.org/download.html the LuaJIT project website] and Lua 5.1, from the [http://www.lua.org/ Lua project website]. Some distribution package managers also distribute LuajIT and/or Lua. +# Install LuaJIT 2.0 or 2.1 (recommended) or Lua 5.1 (Lua 5.2 is ''not'' supported yet). LuaJIT can be downloaded from the [http://luajit.org/download.html the LuaJIT project website] and Lua 5.1, from the [http://www.lua.org/ Lua project website]. Some distribution package managers also distribute LuaJIT and/or Lua. # Download the latest version of the ngx_devel_kit (NDK) module [https://github.com/simpl/ngx_devel_kit/tags HERE]. # Download the latest version of ngx_lua [https://github.com/openresty/lua-nginx-module/tags HERE]. # Download the latest version of Nginx [http://nginx.org/ HERE] (See [[#Nginx Compatibility|Nginx Compatibility]]) @@ -258,9 +207,9 @@ Alternatively, ngx_lua can be manually compiled into Nginx: Build the source with this module: - wget 'http://nginx.org/download/nginx-1.7.10.tar.gz' - tar -xzvf nginx-1.7.10.tar.gz - cd nginx-1.7.10/ + wget 'http://nginx.org/download/nginx-1.9.3.tar.gz' + tar -xzvf nginx-1.9.3.tar.gz + cd nginx-1.9.3/ # tell nginx's build system where to find LuaJIT 2.0: export LUAJIT_LIB=/path/to/luajit/lib @@ -276,7 +225,7 @@ Build the source with this module: # Here we assume Nginx is to be installed under /opt/nginx/. ./configure --prefix=/opt/nginx \ - --with-ld-opt='-Wl,-rpath,/path/to/luajit-or-lua/lib" \ + --with-ld-opt="-Wl,-rpath,/path/to/luajit-or-lua/lib" \ --add-module=/path/to/ngx_devel_kit \ --add-module=/path/to/lua-nginx-module @@ -610,6 +559,10 @@ The cosockets are currently also disabled in the [[#init_by_lua|init_by_lua*]] a There exists a work-around, however, when the original context does *not* need to wait for the cosocket results. That is, creating a 0-delay timer via the [[#ngx.timer.at|ngx.timer.at]] API and do the cosocket results in the timer handler, which runs asynchronously as to the original context creating the timer. == Special Escaping Sequences == + +'''WARNING''' We no longer suffer from this pitfall since the introduction of the +*_by_lua_block {} configuration directives. + PCRE sequences such as \d, \s, or \w, require special attention because in string literals, the backslash character, \, is stripped out by both the Lua language parser and by the Nginx config file parser before processing. So the following snippet will not work as expected: @@ -720,19 +673,6 @@ phases. = TODO = -* add *_by_lua_block directives for existing *_by_lua directives so that we put literal Lua code directly in curly braces instead of an nginx literal string. For example, - - content_by_lua_block { - ngx.say("hello, world\r\n") - } - -: which is equivalent to - - content_by_lua ' - ngx.say("hello, world\\r\\n") - '; - -: but the former is much cleaner and nicer. * cosocket: implement LuaSocket's unconnected UDP API. * add support for implementing general TCP servers instead of HTTP servers in Lua. For example, @@ -995,6 +935,9 @@ As from the v0.5.0rc29 release, the special notation $prefix< '''phase:''' ''loading-config'' +'''WARNING''' Since the v0.9.17 release, use of this directive is ''discouraged''; +use the new [[#init_by_lua_block|init_by_lua_block]] directive instead. + Runs the Lua code specified by the argument on the global Lua VM level when the Nginx master process (if any) is loading the Nginx config file. When Nginx receives the HUP signal and starts reloading the config file, the Lua VM will also be re-created and init_by_lua will run again on the new Lua VM. In case that the [[#lua_code_cache|lua_code_cache]] directive is turned off (default on), the init_by_lua handler will run upon every request because in this special mode a standalone Lua VM is always created for each request. @@ -1052,6 +995,29 @@ You should be very careful about potential security vulnerabilities in your Lua This directive was first introduced in the v0.5.5 release. +== init_by_lua_block == + +'''syntax:''' ''init_by_lua_block { lua-script }'' + +'''context:''' ''http'' + +'''phase:''' ''loading-config'' + +Similar to the [[#init_by_lua|init_by_lua]] directive except that this directive inlines +the Lua source directly +inside a pair of curly braces (`{}`) instead of in an NGINX string literal (which requires +special character escaping). + +For instance, + + + init_by_lua_block { + print("I need no extra escaping here, for example: \r\nblah") + } + + +This directive was first introduced in the v0.9.17 release. + == init_by_lua_file == '''syntax:''' ''init_by_lua_file '' @@ -1074,9 +1040,11 @@ This directive was first introduced in the v0.5.5 release. '''phase:''' ''starting-worker'' +'''WARNING''' Since the v0.9.17 release, use of this directive is ''discouraged''; use the new [[#init_worker_by_lua_block|init_worker_by_lua_block]] directive instead. + Runs the specified Lua code upon every Nginx worker process's startup when the master process is enabled. When the master process is disabled, this hook will just run after [[#init_by_lua|init_by_lua*]]. -This hook is often used to create per-worker reoccurring timers (via the [[#ngx.timer.at|ngx.timer.at]] Lua API), either for backend healthcheck or other timed routine work. Below is an example, +This hook is often used to create per-worker reoccurring timers (via the [[#ngx.timer.at|ngx.timer.at]] Lua API), either for backend health-check or other timed routine work. Below is an example, init_worker_by_lua ' @@ -1107,6 +1075,29 @@ This hook is often used to create per-worker reoccurring timers (via the [[#ngx. This directive was first introduced in the v0.9.5 release. +== init_worker_by_lua_block == + +'''syntax:''' ''init_worker_by_lua_block { lua-script }'' + +'''context:''' ''http'' + +'''phase:''' ''starting-worker'' + +Similar to the [[#init_worker_by_lua|init_worker_by_lua]] directive except that this directive inlines +the Lua source directly +inside a pair of curly braces (`{}`) instead of in an NGINX string literal (which requires +special character escaping). + +For instance, + + + init_worker_by_lua_block { + print("I need no extra escaping here, for example: \r\nblah") + } + + +This directive was first introduced in the v0.9.17 release. + == init_worker_by_lua_file == '''syntax:''' ''init_worker_by_lua_file '' @@ -1127,7 +1118,9 @@ This directive was first introduced in the v0.9.5 release. '''phase:''' ''rewrite'' -Executes code specified in with optional input arguments $arg1 $arg2 ..., and returns string output to $res. +'''WARNING''' Since the v0.9.17 release, use of this directive is ''discouraged''; use the new [[#set_by_lua_block|set_by_lua_block]] directive instead. + +Executes code specified in with optional input arguments $arg1 $arg2 ..., and returns string output to $res. The code in can make [[#Nginx API for Lua|API calls]] and can retrieve input arguments from the ngx.arg table (index starts from 1 and increases sequentially). This directive is designed to execute short, fast running code blocks as the Nginx event loop is blocked during code execution. Time consuming code sequences should therefore be avoided. @@ -1137,7 +1130,7 @@ This directive is implemented by injecting custom commands into the standard [[H At least the following API functions are currently disabled within the context of set_by_lua: * Output API functions (e.g., [[#ngx.say|ngx.say]] and [[#ngx.send_headers|ngx.send_headers]]) -* Control API functions (e.g., [[#ngx.exit|ngx.exit]]) +* Control API functions (e.g., [[#ngx.exit|ngx.exit]]) * Subrequest API functions (e.g., [[#ngx.location.capture|ngx.location.capture]] and [[#ngx.location.capture_multi|ngx.location.capture_multi]]) * Cosocket API functions (e.g., [[#ngx.socket.tcp|ngx.socket.tcp]] and [[#ngx.req.socket|ngx.req.socket]]). * Sleeping API function [[#ngx.sleep|ngx.sleep]]. @@ -1165,7 +1158,7 @@ This directive can be freely mixed with all directives of the [[HttpRewriteModul set $foo 32; - set_by_lua $bar 'tonumber(ngx.var.foo) + 1'; + set_by_lua $bar 'return tonumber(ngx.var.foo) + 1'; set $baz "bar: $bar"; # $baz == "bar: 33" @@ -1173,6 +1166,32 @@ As from the v0.5.0rc29 release, Nginx variable interpolation is dis This directive requires the [https://github.com/simpl/ngx_devel_kit ngx_devel_kit] module. +== set_by_lua_block == + +'''syntax:''' ''set_by_lua_block $res { lua-script }'' + +'''context:''' ''server, server if, location, location if'' + +'''phase:''' ''rewrite'' + +Similar to the [[#set_by_lua|set_by_lua]] directive except that + +# this directive inlines the Lua source directly +inside a pair of curly braces (`{}`) instead of in an NGINX string literal (which requires +special character escaping), and +# this directive does not support extra arguments after the Lua script as in [[#set_by_lua|set_by_lua]]. + +For example, + + + set_by_lua_block $res { return 32 + math.cos(32) } + # $res now has the value "32.834223360507" or alike. + + +No special escaping is required in the Lua code block. + +This directive was first introduced in the v0.9.17 release. + == set_by_lua_file == '''syntax:''' ''set_by_lua_file $res [$arg1 $arg2 ...]'' @@ -1201,11 +1220,37 @@ This directive requires the [https://github.com/simpl/ngx_devel_kit ngx_devel_ki '''phase:''' ''content'' +'''WARNING''' Since the v0.9.17 release, use of this directive is ''discouraged''; +use the new [[#content_by_lua_block|content_by_lua_block]] directive instead. + Acts as a "content handler" and executes Lua code string specified in for every request. The Lua code may make [[#Nginx API for Lua|API calls]] and is executed as a new spawned coroutine in an independent global environment (i.e. a sandbox). Do not use this directive and other content handler directives in the same location. For example, this directive and the [[HttpProxyModule#proxy_pass|proxy_pass]] directive should not be used in the same location. +== content_by_lua_block == + +'''syntax:''' ''content_by_lua_block { lua-script }'' + +'''context:''' ''location, location if'' + +'''phase:''' ''content'' + +Similar to the [[#content_by_lua|content_by_lua]] directive except that this directive inlines +the Lua source directly +inside a pair of curly braces (`{}`) instead of in an NGINX string literal (which requires +special character escaping). + +For instance, + + + content_by_lua_block { + ngx.say("I need no extra escaping here, for example: \r\nblah") + } + + +This directive was first introduced in the v0.9.17 release. + == content_by_lua_file == '''syntax:''' ''content_by_lua_file '' @@ -1246,6 +1291,9 @@ But be very careful about malicious user inputs and always carefully validate or '''phase:''' ''rewrite tail'' +'''WARNING''' Since the v0.9.17 release, use of this directive is ''discouraged''; +use the new [[#rewrite_by_lua_block|rewrite_by_lua_block]] directive instead. + Acts as a rewrite phase handler and executes Lua code string specified in for every request. The Lua code may make [[#Nginx API for Lua|API calls]] and is executed as a new spawned coroutine in an independent global environment (i.e. a sandbox). @@ -1353,6 +1401,29 @@ Here the Lua code ngx.exit(503) will never run. This will be the ca The rewrite_by_lua code will always run at the end of the rewrite request-processing phase unless [[#rewrite_by_lua_no_postpone|rewrite_by_lua_no_postpone]] is turned on. +== rewrite_by_lua_block == + +'''syntax:''' ''rewrite_by_lua_block { lua-script }'' + +'''context:''' ''http, server, location, location if'' + +'''phase:''' ''rewrite tail'' + +Similar to the [[#rewrite_by_lua|rewrite_by_lua]] directive except that this directive inlines +the Lua source directly +inside a pair of curly braces (`{}`) instead of in an NGINX string literal (which requires +special character escaping). + +For instance, + + + rewrite_by_lua_block { + do_something("hello, world!\nhiya\n") + } + + +This directive was first introduced in the v0.9.17 release. + == rewrite_by_lua_file == '''syntax:''' ''rewrite_by_lua_file '' @@ -1381,6 +1452,9 @@ Nginx variables are supported in the file path for dynamic dispatch just as in [ '''phase:''' ''access tail'' +'''WARNING''' Since the v0.9.17 release, use of this directive is ''discouraged''; +use the new [[#access_by_lua_block|access_by_lua_block]] directive instead. + Acts as an access phase handler and executes Lua code string specified in for every request. The Lua code may make [[#Nginx API for Lua|API calls]] and is executed as a new spawned coroutine in an independent global environment (i.e. a sandbox). @@ -1440,6 +1514,29 @@ As with other access phase handlers, [[#access_by_lua|access_by_lua]] will ''not Note that when calling ngx.exit(ngx.OK) within a [[#access_by_lua|access_by_lua]] handler, the nginx request processing control flow will still continue to the content handler. To terminate the current request from within a [[#access_by_lua|access_by_lua]] handler, calling [[#ngx.exit|ngx.exit]] with status >= 200 (ngx.HTTP_OK) and status < 300 (ngx.HTTP_SPECIAL_RESPONSE) for successful quits and ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) (or its friends) for failures. +== access_by_lua_block == + +'''syntax:''' ''access_by_lua_block { lua-script }'' + +'''context:''' ''http, server, location, location if'' + +'''phase:''' ''access tail'' + +Similar to the [[#access_by_lua|access_by_lua]] directive except that this directive inlines +the Lua source directly +inside a pair of curly braces (`{}`) instead of in an NGINX string literal (which requires +special character escaping). + +For instance, + + + access_by_lua_block { + do_something("hello, world!\nhiya\n") + } + + +This directive was first introduced in the v0.9.17 release. + == access_by_lua_file == '''syntax:''' ''access_by_lua_file '' @@ -1468,12 +1565,15 @@ Nginx variables are supported in the file path for dynamic dispatch just as in [ '''phase:''' ''output-header-filter'' +'''WARNING''' Since the v0.9.17 release, use of this directive is ''discouraged''; +use the new [[#header_filter_by_lua_block|header_filter_by_lua_block]] directive instead. + Uses Lua code specified in to define an output header filter. Note that the following API functions are currently disabled within this context: * Output API functions (e.g., [[#ngx.say|ngx.say]] and [[#ngx.send_headers|ngx.send_headers]]) -* Control API functions (e.g., [[#ngx.exit|ngx.exit]] and [[#ngx.exec|ngx.exec]]) +* Control API functions (e.g., [[#ngx.redirect|ngx.redirect]] and [[#ngx.exec|ngx.exec]]) * Subrequest API functions (e.g., [[#ngx.location.capture|ngx.location.capture]] and [[#ngx.location.capture_multi|ngx.location.capture_multi]]) * Cosocket API functions (e.g., [[#ngx.socket.tcp|ngx.socket.tcp]] and [[#ngx.req.socket|ngx.req.socket]]). @@ -1488,6 +1588,29 @@ Here is an example of overriding a response header (or adding one if absent) in This directive was first introduced in the v0.2.1rc20 release. +== header_filter_by_lua_block == + +'''syntax:''' ''header_filter_by_lua_block { lua-script }'' + +'''context:''' ''http, server, location, location if'' + +'''phase:''' ''output-header-filter'' + +Similar to the [[#header_filter_by_lua|header_filter_by_lua]] directive except that this directive inlines +the Lua source directly +inside a pair of curly braces (`{}`) instead of in an NGINX string literal (which requires +special character escaping). + +For instance, + + + header_filter_by_lua_block { + ngx.header["content-length"] = nil + } + + +This directive was first introduced in the v0.9.17 release. + == header_filter_by_lua_file == '''syntax:''' ''header_filter_by_lua_file '' @@ -1510,6 +1633,9 @@ This directive was first introduced in the v0.2.1rc20 release. '''phase:''' ''output-body-filter'' +'''WARNING''' Since the v0.9.17 release, use of this directive is ''discouraged''; +use the new [[#body_filter_by_lua_block|body_filter_by_lua_block]] directive instead. + Uses Lua code specified in to define an output body filter. The input data chunk is passed via [[#ngx.arg|ngx.arg]][1] (as a Lua string value) and the "eof" flag indicating the end of the response body data stream is passed via [[#ngx.arg|ngx.arg]][2] (as a Lua boolean value). @@ -1585,6 +1711,29 @@ Nginx output filters may be called multiple times for a single request because r This directive was first introduced in the v0.5.0rc32 release. +== body_filter_by_lua_block == + +'''syntax:''' ''body_filter_by_lua_block { lua-script-str }'' + +'''context:''' ''http, server, location, location if'' + +'''phase:''' ''output-body-filter'' + +Similar to the [[#body_filter_by_lua|body_filter_by_lua]] directive except that this directive inlines +the Lua source directly +inside a pair of curly braces (`{}`) instead of in an NGINX string literal (which requires +special character escaping). + +For instance, + + + body_filter_by_lua_block { + local data, eof = ngx.arg[1], ngx.arg[2] + } + + +This directive was first introduced in the v0.9.17 release. + == body_filter_by_lua_file == '''syntax:''' ''body_filter_by_lua_file '' @@ -1607,7 +1756,10 @@ This directive was first introduced in the v0.5.0rc32 release. '''phase:''' ''log'' -Run the Lua source code inlined as the at the log request processing phase. This does not replace the current access logs, but runs after. +'''WARNING''' Since the v0.9.17 release, use of this directive is ''discouraged''; +use the new [[#log_by_lua_block|log_by_lua_block]] directive instead. + +Runs the Lua source code inlined as the at the log request processing phase. This does not replace the current access logs, but runs after. Note that the following API functions are currently disabled within this context: @@ -1660,6 +1812,29 @@ Here is an example of gathering average data for [[HttpUpstreamModule#$upstream_ This directive was first introduced in the v0.5.0rc31 release. +== log_by_lua_block == + +'''syntax:''' ''log_by_lua_block { lua-script }'' + +'''context:''' ''http, server, location, location if'' + +'''phase:''' ''log'' + +Similar to the [[#log_by_lua|log_by_lua]] directive except that this directive inlines +the Lua source directly +inside a pair of curly braces (`{}`) instead of in an NGINX string literal (which requires +special character escaping). + +For instance, + + + log_by_lua_block { + print("I need no extra escaping here, for example: \r\nblah") + } + + +This directive was first introduced in the v0.9.17 release. + == log_by_lua_file == '''syntax:''' ''log_by_lua_file '' @@ -2110,7 +2285,7 @@ many others are not, like $query_string, $arg_PARAMETER$1, $2, $3, and etc, can be read by this interface as well, by writing ngx.var[1], ngx.var[2], ngx.var[3], and etc. -Setting ngx.var.Foo to a nil value will unset the $Foo Nginx variable. +Setting ngx.var.Foo to a nil value will unset the $Foo Nginx variable. ngx.var.args = nil @@ -2125,6 +2300,8 @@ Setting ngx.var.Foo to a nil value will unset the -Returns a Lua table with three slots (res.status, res.header, res.body, and res.truncated). +Returns a Lua table with 4 slots: res.status, res.header, res.body, and res.truncated. res.status holds the response status code for the subrequest response. @@ -2884,7 +3061,7 @@ See also [[#ngx.req.set_method|ngx.req.set_method]]. '''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*'' -Overrides the current request's request method with the request_id argument. Currently only numerical [[#HTTP method constants|method constants]] are supported, like ngx.HTTP_POST and ngx.HTTP_GET. +Overrides the current request's request method with the method_id argument. Currently only numerical [[#HTTP method constants|method constants]] are supported, like ngx.HTTP_POST and ngx.HTTP_GET. If the current request is an Nginx subrequest, then the subrequest's method will be overridden. @@ -2933,14 +3110,14 @@ or equivalently, ngx.req.set_uri("/foo") -The jump can only be set to true in [[#rewrite_by_lua|rewrite_by_lua]] and [[#rewrite_by_lua_file|rewrite_by_lua_file]]. Use of jump in other contexts is prohibited and will throw out a Lua exception. +The jump argument can only be set to true in [[#rewrite_by_lua|rewrite_by_lua]] and [[#rewrite_by_lua_file|rewrite_by_lua_file]]. Use of jump in other contexts is prohibited and will throw out a Lua exception. A more sophisticated example involving regex substitutions is as follows location /test { rewrite_by_lua ' - local uri = ngx.re.sub(ngx.var.uri, "^/test/(.*)", "$1", "o") + local uri = ngx.re.sub(ngx.var.uri, "^/test/(.*)", "/$1", "o") ngx.req.set_uri(uri) '; proxy_pass http://my_backend; @@ -3151,7 +3328,7 @@ will yield: a b: 1a 2 -Arguments without the = parts are treated as boolean arguments. GET /test?foo&bar will yield: +Arguments without the = parts are treated as boolean arguments. POST /test with the request body foo&bar will yield: foo: true @@ -3224,13 +3401,13 @@ Note that a maximum of 100 request headers are parsed by default (including thos However, the optional max_headers function argument can be used to override this limit: - local args = ngx.req.get_headers(10) + local headers = ngx.req.get_headers(10) This argument can be set to zero to remove the limit and to process all request headers received: - local args = ngx.req.get_headers(0) + local headers = ngx.req.get_headers(0) Removing the max_headers cap is strongly discouraged. diff --git a/debian/modules/nginx-lua/src/api/ngx_http_lua_api.h b/debian/modules/nginx-lua/src/api/ngx_http_lua_api.h index c9e3e66..962c651 100644 --- a/debian/modules/nginx-lua/src/api/ngx_http_lua_api.h +++ b/debian/modules/nginx-lua/src/api/ngx_http_lua_api.h @@ -19,7 +19,7 @@ /* Public API for other Nginx modules */ -#define ngx_http_lua_version 9016 +#define ngx_http_lua_version 9019 typedef struct { diff --git a/debian/modules/nginx-lua/src/ddebug.h b/debian/modules/nginx-lua/src/ddebug.h index d0f3d1b..f2d4b73 100644 --- a/debian/modules/nginx-lua/src/ddebug.h +++ b/debian/modules/nginx-lua/src/ddebug.h @@ -28,7 +28,8 @@ #include -static void dd(const char *fmt, ...) { +static ngx_inline void +dd(const char *fmt, ...) { } # endif @@ -43,7 +44,8 @@ static void dd(const char *fmt, ...) { #include -static void dd(const char *fmt, ...) { +static ngx_inline void +dd(const char *fmt, ...) { } # endif diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_directive.c b/debian/modules/nginx-lua/src/ngx_http_lua_directive.c index dc9a12c..ae8b09f 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_directive.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_directive.c @@ -24,6 +24,11 @@ #include "ngx_http_lua_initby.h" #include "ngx_http_lua_initworkerby.h" #include "ngx_http_lua_shdict.h" +#include "ngx_http_lua_lex.h" + + +typedef struct ngx_http_lua_block_parser_ctx_s + ngx_http_lua_block_parser_ctx_t; #if defined(NDK) && NDK @@ -35,6 +40,32 @@ static ngx_int_t ngx_http_lua_set_by_lua_init(ngx_http_request_t *r); static u_char *ngx_http_lua_gen_chunk_name(ngx_conf_t *cf, const char *tag, size_t tag_len); +static char *ngx_http_lua_conf_lua_block_parse(ngx_conf_t *cf, + ngx_command_t *cmd); +static ngx_int_t ngx_http_lua_conf_read_lua_token(ngx_conf_t *cf, + ngx_http_lua_block_parser_ctx_t *ctx); +static u_char *ngx_http_lua_strlstrn(u_char *s1, u_char *last, u_char *s2, + size_t n); + + +struct ngx_http_lua_block_parser_ctx_s { + ngx_uint_t start_line; + int token_len; +}; + + +enum { + FOUND_LEFT_CURLY = 0, + FOUND_RIGHT_CURLY, + FOUND_LEFT_LBRACKET_STR, + FOUND_LBRACKET_STR = FOUND_LEFT_LBRACKET_STR, + FOUND_LEFT_LBRACKET_CMT, + FOUND_LBRACKET_CMT = FOUND_LEFT_LBRACKET_CMT, + FOUND_RIGHT_LBRACKET, + FOUND_COMMENT_LINE, + FOUND_DOUBLE_QUOTED, + FOUND_SINGLE_QUOTED +}; char * @@ -189,6 +220,25 @@ ngx_http_lua_package_path(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) #if defined(NDK) && NDK +char * +ngx_http_lua_set_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) +{ + char *rv; + ngx_conf_t save; + + save = *cf; + cf->handler = ngx_http_lua_set_by_lua; + cf->handler_conf = conf; + + rv = ngx_http_lua_conf_lua_block_parse(cf, cmd); + + *cf = save; + + return rv; +} + + char * ngx_http_lua_set_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { @@ -372,6 +422,25 @@ ngx_http_lua_filter_set_by_lua_file(ngx_http_request_t *r, ngx_str_t *val, #endif /* defined(NDK) && NDK */ +char * +ngx_http_lua_rewrite_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) +{ + char *rv; + ngx_conf_t save; + + save = *cf; + cf->handler = ngx_http_lua_rewrite_by_lua; + cf->handler_conf = conf; + + rv = ngx_http_lua_conf_lua_block_parse(cf, cmd); + + *cf = save; + + return rv; +} + + char * ngx_http_lua_rewrite_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { @@ -467,6 +536,25 @@ ngx_http_lua_rewrite_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) } +char * +ngx_http_lua_access_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) +{ + char *rv; + ngx_conf_t save; + + save = *cf; + cf->handler = ngx_http_lua_access_by_lua; + cf->handler_conf = conf; + + rv = ngx_http_lua_conf_lua_block_parse(cf, cmd); + + *cf = save; + + return rv; +} + + char * ngx_http_lua_access_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { @@ -558,6 +646,25 @@ ngx_http_lua_access_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) } +char * +ngx_http_lua_content_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) +{ + char *rv; + ngx_conf_t save; + + save = *cf; + cf->handler = ngx_http_lua_content_by_lua; + cf->handler_conf = conf; + + rv = ngx_http_lua_conf_lua_block_parse(cf, cmd); + + *cf = save; + + return rv; +} + + char * ngx_http_lua_content_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { @@ -583,6 +690,9 @@ ngx_http_lua_content_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) value = cf->args->elts; + dd("value[0]: %.*s", (int) value[0].len, value[0].data); + dd("value[1]: %.*s", (int) value[1].len, value[1].data); + if (value[1].len == 0) { /* Oops...Invalid location conf */ ngx_conf_log_error(NGX_LOG_ERR, cf, 0, @@ -659,6 +769,25 @@ ngx_http_lua_content_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) } +char * +ngx_http_lua_log_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) +{ + char *rv; + ngx_conf_t save; + + save = *cf; + cf->handler = ngx_http_lua_log_by_lua; + cf->handler_conf = conf; + + rv = ngx_http_lua_conf_lua_block_parse(cf, cmd); + + *cf = save; + + return rv; +} + + char * ngx_http_lua_log_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { @@ -749,6 +878,25 @@ ngx_http_lua_log_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) } +char * +ngx_http_lua_header_filter_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) +{ + char *rv; + ngx_conf_t save; + + save = *cf; + cf->handler = ngx_http_lua_header_filter_by_lua; + cf->handler_conf = conf; + + rv = ngx_http_lua_conf_lua_block_parse(cf, cmd); + + *cf = save; + + return rv; +} + + char * ngx_http_lua_header_filter_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) @@ -830,6 +978,25 @@ ngx_http_lua_header_filter_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, } +char * +ngx_http_lua_body_filter_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) +{ + char *rv; + ngx_conf_t save; + + save = *cf; + cf->handler = ngx_http_lua_body_filter_by_lua; + cf->handler_conf = conf; + + rv = ngx_http_lua_conf_lua_block_parse(cf, cmd); + + *cf = save; + + return rv; +} + + char * ngx_http_lua_body_filter_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) @@ -912,6 +1079,25 @@ ngx_http_lua_body_filter_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, } +char * +ngx_http_lua_init_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) +{ + char *rv; + ngx_conf_t save; + + save = *cf; + cf->handler = ngx_http_lua_init_by_lua; + cf->handler_conf = conf; + + rv = ngx_http_lua_conf_lua_block_parse(cf, cmd); + + *cf = save; + + return rv; +} + + char * ngx_http_lua_init_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) @@ -960,6 +1146,25 @@ ngx_http_lua_init_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, } +char * +ngx_http_lua_init_worker_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) +{ + char *rv; + ngx_conf_t save; + + save = *cf; + cf->handler = ngx_http_lua_init_worker_by_lua; + cf->handler_conf = conf; + + rv = ngx_http_lua_conf_lua_block_parse(cf, cmd); + + *cf = save; + + return rv; +} + + char * ngx_http_lua_init_worker_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) @@ -1078,4 +1283,411 @@ found: } +/* a specialized version of the standard ngx_conf_parse() function */ +static char * +ngx_http_lua_conf_lua_block_parse(ngx_conf_t *cf, ngx_command_t *cmd) +{ + ngx_http_lua_block_parser_ctx_t ctx; + + int level = 1; + char *rv; + u_char *p; + size_t len; + ngx_str_t *src, *dst; + ngx_int_t rc; + ngx_uint_t i, start_line; + ngx_array_t *saved; + enum { + parse_block = 0, + parse_param + } type; + + if (cf->conf_file->file.fd != NGX_INVALID_FILE) { + + type = parse_block; + + } else { + type = parse_param; + } + + saved = cf->args; + + cf->args = ngx_array_create(cf->temp_pool, 4, sizeof(ngx_str_t)); + if (cf->args == NULL) { + return NGX_CONF_ERROR; + } + + ctx.token_len = 0; + start_line = cf->conf_file->line; + + dd("init start line: %d", (int) start_line); + + ctx.start_line = start_line; + + for ( ;; ) { + rc = ngx_http_lua_conf_read_lua_token(cf, &ctx); + + dd("parser start line: %d", (int) start_line); + + switch (rc) { + + case NGX_ERROR: + goto done; + + case FOUND_LEFT_CURLY: + + ctx.start_line = cf->conf_file->line; + + if (type == parse_param) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "block directives are not supported " + "in -g option"); + goto failed; + } + + level++; + dd("seen block start: level=%d", (int) level); + break; + + case FOUND_RIGHT_CURLY: + + level--; + dd("seen block done: level=%d", (int) level); + + if (type != parse_block || level < 0) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "unexpected \"}\": level %d, " + "starting at line %ui", level, + start_line); + goto failed; + } + + if (level == 0) { + ngx_http_lua_assert(cf->handler); + + src = cf->args->elts; + + for (len = 0, i = 0; i < cf->args->nelts; i++) { + len += src[i].len; + } + + dd("saved nelts: %d", (int) saved->nelts); + dd("temp nelts: %d", (int) cf->args->nelts); +#if 0 + ngx_http_lua_assert(saved->nelts == 1); +#endif + + dst = ngx_array_push(saved); + if (dst == NULL) { + return NGX_CONF_ERROR; + } + dst->len = len; + dst->len--; /* skip the trailing '}' block terminator */ + + p = ngx_palloc(cf->pool, len); + if (p == NULL) { + return NGX_CONF_ERROR; + } + dst->data = p; + + for (i = 0; i < cf->args->nelts; i++) { + p = ngx_copy(p, src[i].data, src[i].len); + } + + p[-1] = '\0'; /* override the last '}' char to null */ + + cf->args = saved; + + rv = (*cf->handler)(cf, cmd, cf->handler_conf); + if (rv == NGX_CONF_OK) { + goto done; + } + + if (rv == NGX_CONF_ERROR) { + goto failed; + } + + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, rv); + + goto failed; + } + + break; + + case FOUND_LBRACKET_STR: + + break; + + case FOUND_LBRACKET_CMT: + + break; + + case FOUND_RIGHT_LBRACKET: + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "unexpected lua closing long-bracket"); + goto failed; + + break; + + case FOUND_COMMENT_LINE: + case FOUND_DOUBLE_QUOTED: + case FOUND_SINGLE_QUOTED: + break; + + default: + + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "unknown return value from the lexer: %i", rc); + goto failed; + } + } + +failed: + + rc = NGX_ERROR; + +done: + + if (rc == NGX_ERROR) { + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; +} + + +static ngx_int_t +ngx_http_lua_conf_read_lua_token(ngx_conf_t *cf, + ngx_http_lua_block_parser_ctx_t *ctx) +{ + enum { + OVEC_SIZE = 2 + }; + int i, rc; + int ovec[OVEC_SIZE]; + u_char *start, *p, *q, ch; + off_t file_size; + size_t len, buf_size; + ssize_t n, size; + ngx_uint_t start_line; + ngx_str_t *word; + ngx_buf_t *b; +#if nginx_version >= 1009002 + ngx_buf_t *dump; +#endif + + b = cf->conf_file->buffer; +#if nginx_version >= 1009002 + dump = cf->conf_file->dump; +#endif + start = b->pos; + start_line = cf->conf_file->line; + buf_size = b->end - b->start; + + dd("lexer start line: %d", (int) start_line); + + file_size = ngx_file_size(&cf->conf_file->file.info); + + for ( ;; ) { + + if (b->pos >= b->last) { + + if (cf->conf_file->file.offset >= file_size) { + + cf->conf_file->line = ctx->start_line; + + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "unexpected end of file, expecting " + "terminating characters for lua code " + "block"); + return NGX_ERROR; + } + + len = b->pos - start; + + if (len == buf_size) { + + cf->conf_file->line = start_line; + + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "too long lua code block, probably " + "missing terminating characters"); + + return NGX_ERROR; + } + + if (len) { + ngx_memmove(b->start, start, len); + } + + size = (ssize_t) (file_size - cf->conf_file->file.offset); + + if (size > b->end - (b->start + len)) { + size = b->end - (b->start + len); + } + + n = ngx_read_file(&cf->conf_file->file, b->start + len, size, + cf->conf_file->file.offset); + + if (n == NGX_ERROR) { + return NGX_ERROR; + } + + if (n != size) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + ngx_read_file_n " returned " + "only %z bytes instead of %z", + n, size); + return NGX_ERROR; + } + + b->pos = b->start + len; + b->last = b->pos + n; + start = b->start; + +#if nginx_version >= 1009002 + if (dump) { + dump->last = ngx_cpymem(dump->last, b->pos, size); + } +#endif + } + + rc = ngx_http_lua_lex(b->pos, b->last - b->pos, ovec); + + if (rc < 0) { /* no match */ + cf->conf_file->line = start_line; + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "Lua code block missing the \"}\" " + "character"); + + return NGX_ERROR; + } + + if (rc == FOUND_LEFT_LBRACKET_STR || rc == FOUND_LEFT_LBRACKET_CMT) { + + /* we update the line numbers for best error messages when the + * closing long bracket is missing */ + + for (i = 0; i < ovec[0]; i++) { + ch = b->pos[i]; + if (ch == LF) { + cf->conf_file->line++; + } + } + + b->pos += ovec[0]; + ovec[1] -= ovec[0]; + ovec[0] = 0; + + if (rc == FOUND_LEFT_LBRACKET_CMT) { + p = &b->pos[2]; /* we skip the leading "--" prefix */ + rc = FOUND_LBRACKET_CMT; + + } else { + p = b->pos; + rc = FOUND_LBRACKET_STR; + } + + /* we temporarily rewrite [=*[ in the input buffer to ]=*] to + * construct the pattern for the corresponding closing long + * bracket without additional buffers. */ + + ngx_http_lua_assert(p[0] == '['); + p[0] = ']'; + + ngx_http_lua_assert(b->pos[ovec[1] - 1] == '['); + b->pos[ovec[1] - 1] = ']'; + + /* search for the corresponding closing bracket */ + + dd("search pattern for the closing long bracket: \"%.*s\" (len=%d)", + (int) (b->pos + ovec[1] - p), p, (int) (b->pos + ovec[1] - p)); + + q = ngx_http_lua_strlstrn(b->pos + ovec[1], b->last, p, + b->pos + ovec[1] - p - 1); + + if (q == NULL) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "Lua code block missing the closing " + "long bracket \"%*s\"", + b->pos + ovec[1] - p, p); + return NGX_ERROR; + } + + /* restore the original opening long bracket */ + + p[0] = '['; + b->pos[ovec[1] - 1] = '['; + + ovec[1] = q - b->pos + b->pos + ovec[1] - p; + + dd("found long bracket token: \"%.*s\"", + (int) (ovec[1] - ovec[0]), b->pos + ovec[0]); + } + + for (i = 0; i < ovec[1]; i++) { + ch = b->pos[i]; + if (ch == LF) { + cf->conf_file->line++; + } + } + + b->pos += ovec[1]; + ctx->token_len = ovec[1] - ovec[0]; + + break; + } + + word = ngx_array_push(cf->args); + if (word == NULL) { + return NGX_ERROR; + } + + word->data = ngx_pnalloc(cf->temp_pool, b->pos - start); + if (word->data == NULL) { + return NGX_ERROR; + } + + len = b->pos - start; + ngx_memcpy(word->data, start, len); + word->len = len; + + return rc; +} + + +/* + * ngx_http_lua_strlstrn() is intended to search for static substring + * with known length in string until the argument last. The argument n + * must be length of the second substring - 1. + */ + +static u_char * +ngx_http_lua_strlstrn(u_char *s1, u_char *last, u_char *s2, size_t n) +{ + ngx_uint_t c1, c2; + + c2 = (ngx_uint_t) *s2++; + last -= n; + + do { + do { + if (s1 >= last) { + return NULL; + } + + c1 = (ngx_uint_t) *s1++; + + dd("testing char '%c' vs '%c'", (int) c1, (int) c2); + + } while (c1 != c2); + + dd("testing against pattern \"%.*s\"", (int) n, s2); + + } while (ngx_strncmp(s1, s2, n) != 0); + + return --s1; +} + + /* vi:set ft=c ts=4 sw=4 et fdm=marker: */ diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_directive.h b/debian/modules/nginx-lua/src/ngx_http_lua_directive.h index 5d5540c..5a8d93b 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_directive.h +++ b/debian/modules/nginx-lua/src/ngx_http_lua_directive.h @@ -17,26 +17,44 @@ char *ngx_http_lua_package_cpath(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); char *ngx_http_lua_package_path(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +char *ngx_http_lua_content_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); char *ngx_http_lua_content_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +char *ngx_http_lua_rewrite_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); char *ngx_http_lua_rewrite_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +char *ngx_http_lua_access_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); char *ngx_http_lua_access_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +char *ngx_http_lua_log_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); char *ngx_http_lua_log_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +char *ngx_http_lua_header_filter_by_lua_block(ngx_conf_t *cf, + ngx_command_t *cmd, void *conf); char *ngx_http_lua_header_filter_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +char *ngx_http_lua_body_filter_by_lua_block(ngx_conf_t *cf, + ngx_command_t *cmd, void *conf); char *ngx_http_lua_body_filter_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +char *ngx_http_lua_init_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); char *ngx_http_lua_init_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +char *ngx_http_lua_init_worker_by_lua_block(ngx_conf_t *cf, + ngx_command_t *cmd, void *conf); char *ngx_http_lua_init_worker_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); char *ngx_http_lua_code_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); #if defined(NDK) && NDK +char *ngx_http_lua_set_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); char *ngx_http_lua_set_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); char *ngx_http_lua_set_by_lua_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_headers_in.c b/debian/modules/nginx-lua/src/ngx_http_lua_headers_in.c index f2f805c..abce458 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_headers_in.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_headers_in.c @@ -44,17 +44,6 @@ static ngx_int_t ngx_http_lua_rm_header_helper(ngx_list_t *l, static ngx_http_lua_set_header_t ngx_http_lua_set_handlers[] = { - -#if (NGX_HTTP_GZIP) - { ngx_string("Accept-Encoding"), - offsetof(ngx_http_headers_in_t, accept_encoding), - ngx_http_set_builtin_header }, - - { ngx_string("Via"), - offsetof(ngx_http_headers_in_t, via), - ngx_http_set_builtin_header }, -#endif - { ngx_string("Host"), offsetof(ngx_http_headers_in_t, host), ngx_http_set_host_header }, @@ -67,6 +56,22 @@ static ngx_http_lua_set_header_t ngx_http_lua_set_handlers[] = { offsetof(ngx_http_headers_in_t, if_modified_since), ngx_http_set_builtin_header }, +#if defined(nginx_version) && nginx_version >= 9002 + { ngx_string("If-Unmodified-Since"), + offsetof(ngx_http_headers_in_t, if_unmodified_since), + ngx_http_set_builtin_header }, +#endif + +#if defined(nginx_version) && nginx_version >= 1003003 + { ngx_string("If-Match"), + offsetof(ngx_http_headers_in_t, if_match), + ngx_http_set_builtin_header }, + + { ngx_string("If-None-Match"), + offsetof(ngx_http_headers_in_t, if_none_match), + ngx_http_set_builtin_header }, +#endif + { ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent), ngx_http_set_user_agent_header }, @@ -75,6 +80,10 @@ static ngx_http_lua_set_header_t ngx_http_lua_set_handlers[] = { offsetof(ngx_http_headers_in_t, referer), ngx_http_set_builtin_header }, + { ngx_string("Content-Length"), + offsetof(ngx_http_headers_in_t, content_length), + ngx_http_set_content_length_header }, + { ngx_string("Content-Type"), offsetof(ngx_http_headers_in_t, content_type), ngx_http_set_builtin_header }, @@ -95,6 +104,22 @@ static ngx_http_lua_set_header_t ngx_http_lua_set_handlers[] = { offsetof(ngx_http_headers_in_t, expect), ngx_http_set_builtin_header }, +#if defined(nginx_version) && nginx_version >= 1003013 + { ngx_string("Upgrade"), + offsetof(ngx_http_headers_in_t, upgrade), + ngx_http_set_builtin_header }, +#endif + +#if (NGX_HTTP_GZIP) + { ngx_string("Accept-Encoding"), + offsetof(ngx_http_headers_in_t, accept_encoding), + ngx_http_set_builtin_header }, + + { ngx_string("Via"), + offsetof(ngx_http_headers_in_t, via), + ngx_http_set_builtin_header }, +#endif + { ngx_string("Authorization"), offsetof(ngx_http_headers_in_t, authorization), ngx_http_set_builtin_header }, @@ -103,20 +128,33 @@ static ngx_http_lua_set_header_t ngx_http_lua_set_handlers[] = { offsetof(ngx_http_headers_in_t, keep_alive), ngx_http_set_builtin_header }, - { ngx_string("Content-Length"), - offsetof(ngx_http_headers_in_t, content_length), - ngx_http_set_content_length_header }, - - { ngx_string("Cookie"), - 0, - ngx_http_set_cookie_header }, - #if (NGX_HTTP_REALIP) { ngx_string("X-Real-IP"), offsetof(ngx_http_headers_in_t, x_real_ip), ngx_http_set_builtin_header }, #endif +#if (NGX_HTTP_DAV) + { ngx_string("Depth"), + offsetof(ngx_http_headers_in_t, depth), + ngx_http_set_builtin_header }, + + { ngx_string("Destination"), + offsetof(ngx_http_headers_in_t, destination), + ngx_http_set_builtin_header }, + + { ngx_string("Overwrite"), + offsetof(ngx_http_headers_in_t, overwrite), + ngx_http_set_builtin_header }, + + { ngx_string("Date"), offsetof(ngx_http_headers_in_t, date), + ngx_http_set_builtin_header }, +#endif + + { ngx_string("Cookie"), + 0, + ngx_http_set_cookie_header }, + { ngx_null_string, 0, ngx_http_set_header } }; diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_headers_out.c b/debian/modules/nginx-lua/src/ngx_http_lua_headers_out.c index 5039c27..5fd077f 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_headers_out.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_headers_out.c @@ -385,7 +385,19 @@ static ngx_int_t ngx_http_set_content_type_header(ngx_http_request_t *r, ngx_http_lua_header_val_t *hv, ngx_str_t *value) { + ngx_uint_t i; + r->headers_out.content_type_len = value->len; + +#if 1 + for (i = 0; i < value->len; i++) { + if (value->data[i] == ';') { + r->headers_out.content_type_len = i; + break; + } + } +#endif + r->headers_out.content_type = *value; r->headers_out.content_type_hash = hv->hash; r->headers_out.content_type_lowcase = NULL; diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_initworkerby.c b/debian/modules/nginx-lua/src/ngx_http_lua_initworkerby.c index 6aa1a33..0876f26 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_initworkerby.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_initworkerby.c @@ -167,6 +167,8 @@ ngx_http_lua_init_worker(ngx_cycle_t *cycle) return NGX_ERROR; } + http_ctx.srv_conf[ngx_modules[i]->ctx_index] = cur; + if (module->merge_srv_conf) { prev = module->create_srv_conf(&conf); if (prev == NULL) { @@ -178,8 +180,6 @@ ngx_http_lua_init_worker(ngx_cycle_t *cycle) goto failed; } } - - http_ctx.srv_conf[ngx_modules[i]->ctx_index] = cur; } if (module->create_loc_conf) { @@ -188,6 +188,8 @@ ngx_http_lua_init_worker(ngx_cycle_t *cycle) return NGX_ERROR; } + http_ctx.loc_conf[ngx_modules[i]->ctx_index] = cur; + if (module->merge_loc_conf) { prev = module->create_loc_conf(&conf); if (prev == NULL) { @@ -199,8 +201,6 @@ ngx_http_lua_init_worker(ngx_cycle_t *cycle) goto failed; } } - - http_ctx.loc_conf[ngx_modules[i]->ctx_index] = cur; } } diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_lex.c b/debian/modules/nginx-lua/src/ngx_http_lua_lex.c new file mode 100644 index 0000000..45cf754 --- /dev/null +++ b/debian/modules/nginx-lua/src/ngx_http_lua_lex.c @@ -0,0 +1,8251 @@ +/* + * Copyright (C) Yichun Zhang (agentzh) + * + * WARNING: DO NOT EVER EDIT THIS FILE!! + * + * This file was automatically generated by the re.pl script of sregex's + * "dfa-multi-re" git branch. + */ + + +#include "ngx_http_lua_lex.h" +#include +#include +#include +#include +#include +#include + + +#if __GNUC__ > 3 +# define likely(x) __builtin_expect((x),1) +# define unlikely(x) __builtin_expect((x),0) +#else +# define likely(x) (x) +# define unlikely(x) (x) +#endif + + +#ifndef u_char +#define u_char unsigned char +#endif + + +enum { + NO_MATCH = -1, +}; + + +/* + * ngx_http_lua_lex: the "ovec" array should be allocated by the caller with at + * least 2 elements. + */ +int +ngx_http_lua_lex(const u_char *const s, size_t len, int *const ovec) +{ + unsigned i = 0; + int matched_0 = -1; + int matched_1 = -1; + int matched_id = NO_MATCH; /* (pending) matched regex ID */ + int c; + int caps0_0 = -1; + int caps0_10 = -1; + int caps0_12 = -1; + int caps0_14 = -1; + int caps0_2 = -1; + int caps0_4 = -1; + int caps0_6 = -1; + int caps0_8 = -1; + int caps1_0 = -1; + int caps1_10 = -1; + int caps1_12 = -1; + int caps1_14 = -1; + int caps1_2 = -1; + int caps1_4 = -1; + int caps1_6 = -1; + int caps1_8 = -1; + int caps2_0 = -1; + int caps2_10 = -1; + int caps2_2 = -1; + int caps2_4 = -1; + int caps2_6 = -1; + int caps2_8 = -1; + int caps3_10 = -1; + + { /* DFA node {0} 0 */ + if (unlikely(i >= len)) { + i++; + goto st0_error; + } + + c = s[i]; + i++; + switch (c) { + case 34: { + /* transfer caps from row 0 to row 1 */ + /* capture stores */ + caps0_12 = i - 1; + goto st2; + break; + } + case 39: { + /* transfer caps from row 0 to row 1 */ + /* capture stores */ + caps0_14 = i - 1; + goto st3; + break; + } + case 45: { + /* transfer caps from row 0 to row 1 */ + /* transfer caps from row 0 to row 2 */ + /* capture stores */ + caps0_6 = i - 1; + caps1_10 = i - 1; + goto st4; + break; + } + case 91: { + /* transfer caps from row 0 to row 1 */ + /* capture stores */ + caps0_4 = i - 1; + goto st5; + break; + } + case 93: { + /* transfer caps from row 0 to row 1 */ + /* capture stores */ + caps0_8 = i - 1; + goto st6; + break; + } + case 123: { + /* transfer caps from row 0 to row 1 */ + /* capture stores */ + caps0_0 = i - 1; + goto st7; + break; + } + case 125: { + /* transfer caps from row 0 to row 1 */ + /* capture stores */ + caps0_2 = i - 1; + goto st8; + break; + } + default: + break; + } + /* (c >= 0 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 90) + * || (c == 92) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + goto st1; + } /* end state */ + + goto st0_error; + +st1: { /* DFA node {1} 1 */ + if (unlikely(i >= len)) { + i++; + goto st1_error; + } + + c = s[i]; + i++; + switch (c) { + case 34: { + /* transfer caps from row 0 to row 1 */ + /* capture stores */ + caps0_12 = i - 1; + goto st2; + break; + } + case 39: { + /* transfer caps from row 0 to row 1 */ + /* capture stores */ + caps0_14 = i - 1; + goto st3; + break; + } + case 45: { + /* transfer caps from row 0 to row 1 */ + /* transfer caps from row 0 to row 2 */ + /* capture stores */ + caps0_6 = i - 1; + caps1_10 = i - 1; + goto st4; + break; + } + case 91: { + /* transfer caps from row 0 to row 1 */ + /* capture stores */ + caps0_4 = i - 1; + goto st5; + break; + } + case 93: { + /* transfer caps from row 0 to row 1 */ + /* capture stores */ + caps0_8 = i - 1; + goto st6; + break; + } + case 123: { + /* transfer caps from row 0 to row 1 */ + /* capture stores */ + caps0_0 = i - 1; + goto st7; + break; + } + case 125: { + /* transfer caps from row 0 to row 1 */ + /* capture stores */ + caps0_2 = i - 1; + goto st8; + break; + } + default: + break; + } + /* (c >= 0 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 90) + * || (c == 92) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + goto st1; + } /* end state */ + + goto st1_error; + +st2: { /* DFA node {59,1} 2 */ + if (unlikely(i >= len)) { + i++; + goto st2_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 1 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_12 = i - 1; + goto st10; + break; + } + case 39: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_14 = i - 1; + goto st11; + break; + } + case 45: { + /* transfer caps from row 1 to row 2 */ + /* transfer caps from row 1 to row 3 */ + /* capture stores */ + caps1_6 = i - 1; + caps2_10 = i - 1; + goto st12; + break; + } + case 91: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_4 = i - 1; + goto st13; + break; + } + case 92: { + goto st14; + break; + } + case 93: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_8 = i - 1; + goto st15; + break; + } + case 123: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_0 = i - 1; + goto st16; + break; + } + case 125: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_2 = i - 1; + goto st17; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + goto st9; + } /* end state */ + + goto st2_error; + +st3: { /* DFA node {72,1} 3 */ + if (unlikely(i >= len)) { + i++; + goto st3_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 1 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_12 = i - 1; + goto st19; + break; + } + case 39: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_14 = i - 1; + goto st20; + break; + } + case 45: { + /* transfer caps from row 1 to row 2 */ + /* transfer caps from row 1 to row 3 */ + /* capture stores */ + caps1_6 = i - 1; + caps2_10 = i - 1; + goto st21; + break; + } + case 91: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_4 = i - 1; + goto st22; + break; + } + case 92: { + goto st23; + break; + } + case 93: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_8 = i - 1; + goto st24; + break; + } + case 123: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_0 = i - 1; + goto st25; + break; + } + case 125: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_2 = i - 1; + goto st26; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + goto st18; + } /* end state */ + + goto st3_error; + +st4: { /* DFA node {30,50,1} 4 */ + if (unlikely(i >= len)) { + i++; + goto st4_error; + } + + c = s[i]; + i++; + switch (c) { + case 34: { + /* transfer caps from row 2 to row 0 */ + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps0_12 = i - 1; + goto st2; + break; + } + case 39: { + /* transfer caps from row 2 to row 0 */ + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps0_14 = i - 1; + goto st3; + break; + } + case 45: { + /* transfer caps from row 2 to row 3 */ + /* transfer caps from row 2 to row 4 */ + /* capture stores */ + caps2_6 = i - 1; + caps3_10 = i - 1; + goto st27; + break; + } + case 91: { + /* transfer caps from row 2 to row 0 */ + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps0_4 = i - 1; + goto st5; + break; + } + case 93: { + /* transfer caps from row 2 to row 0 */ + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps0_8 = i - 1; + goto st6; + break; + } + case 123: { + /* transfer caps from row 2 to row 0 */ + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps0_0 = i - 1; + goto st7; + break; + } + case 125: { + /* transfer caps from row 2 to row 0 */ + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps0_2 = i - 1; + goto st8; + break; + } + default: + break; + } + /* (c >= 0 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 90) + * || (c == 92) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 2 to row 0 */ + goto st1; + } /* end state */ + + goto st4_error; + +st5: { /* DFA node {21,1} 5 */ + if (unlikely(i >= len)) { + i++; + goto st5_error; + } + + c = s[i]; + i++; + switch (c) { + case 34: { + /* transfer caps from row 1 to row 0 */ + /* capture stores */ + caps0_12 = i - 1; + goto st2; + break; + } + case 39: { + /* transfer caps from row 1 to row 0 */ + /* capture stores */ + caps0_14 = i - 1; + goto st3; + break; + } + case 45: { + /* transfer caps from row 1 to row 0 */ + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps0_6 = i - 1; + caps1_10 = i - 1; + goto st4; + break; + } + case 61: { + goto st28; + break; + } + case 91: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_4 = i - 1; + goto st29; + break; + } + case 93: { + /* transfer caps from row 1 to row 0 */ + /* capture stores */ + caps0_8 = i - 1; + goto st6; + break; + } + case 123: { + /* transfer caps from row 1 to row 0 */ + /* capture stores */ + caps0_0 = i - 1; + goto st7; + break; + } + case 125: { + /* transfer caps from row 1 to row 0 */ + /* capture stores */ + caps0_2 = i - 1; + goto st8; + break; + } + default: + break; + } + /* (c >= 0 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 60) + * || (c >= 62 && c <= 90) + * || (c == 92) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 1 to row 0 */ + goto st1; + } /* end state */ + + goto st5_error; + +st6: { /* DFA node {41,1} 6 */ + if (unlikely(i >= len)) { + i++; + goto st6_error; + } + + c = s[i]; + i++; + switch (c) { + case 34: { + /* transfer caps from row 1 to row 0 */ + /* capture stores */ + caps0_12 = i - 1; + goto st2; + break; + } + case 39: { + /* transfer caps from row 1 to row 0 */ + /* capture stores */ + caps0_14 = i - 1; + goto st3; + break; + } + case 45: { + /* transfer caps from row 1 to row 0 */ + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps0_6 = i - 1; + caps1_10 = i - 1; + goto st4; + break; + } + case 61: { + goto st30; + break; + } + case 91: { + /* transfer caps from row 1 to row 0 */ + /* capture stores */ + caps0_4 = i - 1; + goto st5; + break; + } + case 93: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_8 = i - 1; + goto st31; + break; + } + case 123: { + /* transfer caps from row 1 to row 0 */ + /* capture stores */ + caps0_0 = i - 1; + goto st7; + break; + } + case 125: { + /* transfer caps from row 1 to row 0 */ + /* capture stores */ + caps0_2 = i - 1; + goto st8; + break; + } + default: + break; + } + /* (c >= 0 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 60) + * || (c >= 62 && c <= 90) + * || (c == 92) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 1 to row 0 */ + goto st1; + } /* end state */ + + goto st6_error; + +st7: { /* DFA node {11,1} 7 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 0 to matched */ + matched_0 = caps0_0; + /* capture stores */ + matched_1 = i - 1; + matched_id = 0; + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st8: { /* DFA node {16,1} 8 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 0 to matched */ + matched_0 = caps0_2; + /* capture stores */ + matched_1 = i - 1; + matched_id = 1; + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st9: { /* DFA node {65,1} 9 */ + if (unlikely(i >= len)) { + i++; + goto st9_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 1 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_12 = i - 1; + goto st10; + break; + } + case 39: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_14 = i - 1; + goto st11; + break; + } + case 45: { + /* transfer caps from row 1 to row 2 */ + /* transfer caps from row 1 to row 3 */ + /* capture stores */ + caps1_6 = i - 1; + caps2_10 = i - 1; + goto st12; + break; + } + case 91: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_4 = i - 1; + goto st13; + break; + } + case 92: { + goto st14; + break; + } + case 93: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_8 = i - 1; + goto st15; + break; + } + case 123: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_0 = i - 1; + goto st16; + break; + } + case 125: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_2 = i - 1; + goto st17; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + goto st9; + } /* end state */ + + goto st9_error; + +st10: { /* DFA node {67,59,1} 10 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 0 to matched */ + matched_0 = caps0_12; + /* capture stores */ + matched_1 = i - 1; + matched_id = 6; + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st11: { /* DFA node {65,72,1} 11 */ + if (unlikely(i >= len)) { + i++; + goto st11_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 2 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + goto st36; + break; + } + case 39: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + goto st37; + break; + } + case 45: { + /* transfer caps from row 2 to row 3 */ + /* transfer caps from row 2 to row 4 */ + /* capture stores */ + caps2_6 = i - 1; + caps3_10 = i - 1; + goto st38; + break; + } + case 91: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_4 = i - 1; + goto st39; + break; + } + case 92: { + goto st40; + break; + } + case 93: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_8 = i - 1; + goto st41; + break; + } + case 123: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_0 = i - 1; + goto st42; + break; + } + case 125: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_2 = i - 1; + goto st43; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + goto st35; + } /* end state */ + + goto st11_error; + +st12: { /* DFA node {65,30,50,1} 12 */ + if (unlikely(i >= len)) { + i++; + goto st12_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 3 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 3 to row 1 */ + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps1_12 = i - 1; + goto st10; + break; + } + case 39: { + /* transfer caps from row 3 to row 1 */ + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps1_14 = i - 1; + goto st11; + break; + } + case 45: { + /* transfer caps from row 3 to row 4 */ + /* transfer caps from row 3 to row 5 */ + /* capture stores */ + goto st44; + break; + } + case 91: { + /* transfer caps from row 3 to row 1 */ + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps1_4 = i - 1; + goto st13; + break; + } + case 92: { + /* transfer caps from row 3 to row 1 */ + goto st14; + break; + } + case 93: { + /* transfer caps from row 3 to row 1 */ + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps1_8 = i - 1; + goto st15; + break; + } + case 123: { + /* transfer caps from row 3 to row 1 */ + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps1_0 = i - 1; + goto st16; + break; + } + case 125: { + /* transfer caps from row 3 to row 1 */ + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps1_2 = i - 1; + goto st17; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 3 to row 1 */ + goto st9; + } /* end state */ + + goto st12_error; + +st13: { /* DFA node {65,21,1} 13 */ + if (unlikely(i >= len)) { + i++; + goto st13_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 2 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_12 = i - 1; + goto st10; + break; + } + case 39: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_14 = i - 1; + goto st11; + break; + } + case 45: { + /* transfer caps from row 2 to row 1 */ + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps1_6 = i - 1; + caps2_10 = i - 1; + goto st12; + break; + } + case 61: { + goto st45; + break; + } + case 91: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_4 = i - 1; + goto st46; + break; + } + case 92: { + /* transfer caps from row 2 to row 1 */ + goto st14; + break; + } + case 93: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_8 = i - 1; + goto st15; + break; + } + case 123: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_0 = i - 1; + goto st16; + break; + } + case 125: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_2 = i - 1; + goto st17; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 60) + * || (c >= 62 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 2 to row 1 */ + goto st9; + } /* end state */ + + goto st13_error; + +st14: { /* DFA node {62,1} 14 */ + if (unlikely(i >= len)) { + i++; + goto st14_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 1 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_12 = i - 1; + goto st48; + break; + } + case 39: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_14 = i - 1; + goto st49; + break; + } + case 45: { + /* transfer caps from row 1 to row 2 */ + /* transfer caps from row 1 to row 3 */ + /* capture stores */ + caps1_6 = i - 1; + caps2_10 = i - 1; + goto st50; + break; + } + case 91: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_4 = i - 1; + goto st51; + break; + } + case 93: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_8 = i - 1; + goto st52; + break; + } + case 123: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_0 = i - 1; + goto st53; + break; + } + case 125: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_2 = i - 1; + goto st54; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 90) + * || (c == 92) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + goto st47; + } /* end state */ + + goto st14_error; + +st15: { /* DFA node {65,41,1} 15 */ + if (unlikely(i >= len)) { + i++; + goto st15_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 2 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_12 = i - 1; + goto st10; + break; + } + case 39: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_14 = i - 1; + goto st11; + break; + } + case 45: { + /* transfer caps from row 2 to row 1 */ + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps1_6 = i - 1; + caps2_10 = i - 1; + goto st12; + break; + } + case 61: { + goto st55; + break; + } + case 91: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_4 = i - 1; + goto st13; + break; + } + case 92: { + /* transfer caps from row 2 to row 1 */ + goto st14; + break; + } + case 93: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_8 = i - 1; + goto st56; + break; + } + case 123: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_0 = i - 1; + goto st16; + break; + } + case 125: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_2 = i - 1; + goto st17; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 60) + * || (c >= 62 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 2 to row 1 */ + goto st9; + } /* end state */ + + goto st15_error; + +st16: { /* DFA node {65,11,1} 16 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 1 to matched */ + matched_0 = caps1_0; + /* capture stores */ + matched_1 = i - 1; + matched_id = 0; + if (c != -1) { + if (c == 34) { + goto st58; + } + if (c == 92) { + goto st59; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st57; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st17: { /* DFA node {65,16,1} 17 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 1 to matched */ + matched_0 = caps1_2; + /* capture stores */ + matched_1 = i - 1; + matched_id = 1; + if (c != -1) { + if (c == 34) { + goto st58; + } + if (c == 92) { + goto st59; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st57; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st18: { /* DFA node {78,1} 18 */ + if (unlikely(i >= len)) { + i++; + goto st18_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 1 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_12 = i - 1; + goto st19; + break; + } + case 39: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_14 = i - 1; + goto st20; + break; + } + case 45: { + /* transfer caps from row 1 to row 2 */ + /* transfer caps from row 1 to row 3 */ + /* capture stores */ + caps1_6 = i - 1; + caps2_10 = i - 1; + goto st21; + break; + } + case 91: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_4 = i - 1; + goto st22; + break; + } + case 92: { + goto st23; + break; + } + case 93: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_8 = i - 1; + goto st24; + break; + } + case 123: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_0 = i - 1; + goto st25; + break; + } + case 125: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_2 = i - 1; + goto st26; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + goto st18; + } /* end state */ + + goto st18_error; + +st19: { /* DFA node {78,59,1} 19 */ + if (unlikely(i >= len)) { + i++; + goto st19_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 2 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + goto st61; + break; + } + case 39: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + goto st62; + break; + } + case 45: { + /* transfer caps from row 2 to row 3 */ + /* transfer caps from row 2 to row 4 */ + /* capture stores */ + caps2_6 = i - 1; + caps3_10 = i - 1; + goto st63; + break; + } + case 91: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_4 = i - 1; + goto st64; + break; + } + case 92: { + goto st65; + break; + } + case 93: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_8 = i - 1; + goto st66; + break; + } + case 123: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_0 = i - 1; + goto st67; + break; + } + case 125: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_2 = i - 1; + goto st68; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + goto st60; + } /* end state */ + + goto st19_error; + +st20: { /* DFA node {80,72,1} 20 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 0 to matched */ + matched_0 = caps0_14; + /* capture stores */ + matched_1 = i - 1; + matched_id = 7; + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st21: { /* DFA node {78,30,50,1} 21 */ + if (unlikely(i >= len)) { + i++; + goto st21_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 3 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 3 to row 1 */ + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps1_12 = i - 1; + goto st19; + break; + } + case 39: { + /* transfer caps from row 3 to row 1 */ + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps1_14 = i - 1; + goto st20; + break; + } + case 45: { + /* transfer caps from row 3 to row 4 */ + /* transfer caps from row 3 to row 5 */ + /* capture stores */ + goto st70; + break; + } + case 91: { + /* transfer caps from row 3 to row 1 */ + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps1_4 = i - 1; + goto st22; + break; + } + case 92: { + /* transfer caps from row 3 to row 1 */ + goto st23; + break; + } + case 93: { + /* transfer caps from row 3 to row 1 */ + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps1_8 = i - 1; + goto st24; + break; + } + case 123: { + /* transfer caps from row 3 to row 1 */ + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps1_0 = i - 1; + goto st25; + break; + } + case 125: { + /* transfer caps from row 3 to row 1 */ + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps1_2 = i - 1; + goto st26; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 3 to row 1 */ + goto st18; + } /* end state */ + + goto st21_error; + +st22: { /* DFA node {78,21,1} 22 */ + if (unlikely(i >= len)) { + i++; + goto st22_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 2 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_12 = i - 1; + goto st19; + break; + } + case 39: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_14 = i - 1; + goto st20; + break; + } + case 45: { + /* transfer caps from row 2 to row 1 */ + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps1_6 = i - 1; + caps2_10 = i - 1; + goto st21; + break; + } + case 61: { + goto st71; + break; + } + case 91: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_4 = i - 1; + goto st72; + break; + } + case 92: { + /* transfer caps from row 2 to row 1 */ + goto st23; + break; + } + case 93: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_8 = i - 1; + goto st24; + break; + } + case 123: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_0 = i - 1; + goto st25; + break; + } + case 125: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_2 = i - 1; + goto st26; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 60) + * || (c >= 62 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 2 to row 1 */ + goto st18; + } /* end state */ + + goto st22_error; + +st23: { /* DFA node {75,1} 23 */ + if (unlikely(i >= len)) { + i++; + goto st23_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 1 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_12 = i - 1; + goto st74; + break; + } + case 39: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_14 = i - 1; + goto st75; + break; + } + case 45: { + /* transfer caps from row 1 to row 2 */ + /* transfer caps from row 1 to row 3 */ + /* capture stores */ + caps1_6 = i - 1; + caps2_10 = i - 1; + goto st76; + break; + } + case 91: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_4 = i - 1; + goto st77; + break; + } + case 93: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_8 = i - 1; + goto st78; + break; + } + case 123: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_0 = i - 1; + goto st79; + break; + } + case 125: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_2 = i - 1; + goto st80; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 90) + * || (c == 92) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + goto st73; + } /* end state */ + + goto st23_error; + +st24: { /* DFA node {78,41,1} 24 */ + if (unlikely(i >= len)) { + i++; + goto st24_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 2 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_12 = i - 1; + goto st19; + break; + } + case 39: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_14 = i - 1; + goto st20; + break; + } + case 45: { + /* transfer caps from row 2 to row 1 */ + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps1_6 = i - 1; + caps2_10 = i - 1; + goto st21; + break; + } + case 61: { + goto st81; + break; + } + case 91: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_4 = i - 1; + goto st22; + break; + } + case 92: { + /* transfer caps from row 2 to row 1 */ + goto st23; + break; + } + case 93: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_8 = i - 1; + goto st82; + break; + } + case 123: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_0 = i - 1; + goto st25; + break; + } + case 125: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_2 = i - 1; + goto st26; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 60) + * || (c >= 62 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 2 to row 1 */ + goto st18; + } /* end state */ + + goto st24_error; + +st25: { /* DFA node {78,11,1} 25 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 1 to matched */ + matched_0 = caps1_0; + /* capture stores */ + matched_1 = i - 1; + matched_id = 0; + if (c != -1) { + if (c == 39) { + goto st84; + } + if (c == 92) { + goto st85; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 38) + || (c >= 40 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st83; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st26: { /* DFA node {78,16,1} 26 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 1 to matched */ + matched_0 = caps1_2; + /* capture stores */ + matched_1 = i - 1; + matched_id = 1; + if (c != -1) { + if (c == 39) { + goto st84; + } + if (c == 92) { + goto st85; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 38) + || (c >= 40 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st83; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st27: { /* DFA node {31,51,30,50,1} 27 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 1 to matched */ + matched_0 = caps1_10; + /* capture stores */ + matched_1 = i - 1; + matched_id = 5; + if (c != -1) { + if (c == 91) { + goto st88; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 90) + || (c >= 92 && c <= 255)) + { + /* transfer caps from row 1 to row 0 */ + caps0_10 = caps1_10; + goto st87; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st28: { /* DFA node {23,1} 28 */ + if (unlikely(i >= len)) { + i++; + goto st28_error; + } + + c = s[i]; + i++; + switch (c) { + case 34: { + /* transfer caps from row 1 to row 0 */ + /* capture stores */ + caps0_12 = i - 1; + goto st2; + break; + } + case 39: { + /* transfer caps from row 1 to row 0 */ + /* capture stores */ + caps0_14 = i - 1; + goto st3; + break; + } + case 45: { + /* transfer caps from row 1 to row 0 */ + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps0_6 = i - 1; + caps1_10 = i - 1; + goto st4; + break; + } + case 61: { + goto st28; + break; + } + case 91: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_4 = i - 1; + goto st29; + break; + } + case 93: { + /* transfer caps from row 1 to row 0 */ + /* capture stores */ + caps0_8 = i - 1; + goto st6; + break; + } + case 123: { + /* transfer caps from row 1 to row 0 */ + /* capture stores */ + caps0_0 = i - 1; + goto st7; + break; + } + case 125: { + /* transfer caps from row 1 to row 0 */ + /* capture stores */ + caps0_2 = i - 1; + goto st8; + break; + } + default: + break; + } + /* (c >= 0 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 60) + * || (c >= 62 && c <= 90) + * || (c == 92) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 1 to row 0 */ + goto st1; + } /* end state */ + + goto st28_error; + +st29: { /* DFA node {25,21,1} 29 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 0 to matched */ + matched_0 = caps0_4; + /* capture stores */ + matched_1 = i - 1; + matched_id = 2; + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st30: { /* DFA node {43,1} 30 */ + if (unlikely(i >= len)) { + i++; + goto st30_error; + } + + c = s[i]; + i++; + switch (c) { + case 34: { + /* transfer caps from row 1 to row 0 */ + /* capture stores */ + caps0_12 = i - 1; + goto st2; + break; + } + case 39: { + /* transfer caps from row 1 to row 0 */ + /* capture stores */ + caps0_14 = i - 1; + goto st3; + break; + } + case 45: { + /* transfer caps from row 1 to row 0 */ + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps0_6 = i - 1; + caps1_10 = i - 1; + goto st4; + break; + } + case 61: { + goto st30; + break; + } + case 91: { + /* transfer caps from row 1 to row 0 */ + /* capture stores */ + caps0_4 = i - 1; + goto st5; + break; + } + case 93: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_8 = i - 1; + goto st31; + break; + } + case 123: { + /* transfer caps from row 1 to row 0 */ + /* capture stores */ + caps0_0 = i - 1; + goto st7; + break; + } + case 125: { + /* transfer caps from row 1 to row 0 */ + /* capture stores */ + caps0_2 = i - 1; + goto st8; + break; + } + default: + break; + } + /* (c >= 0 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 60) + * || (c >= 62 && c <= 90) + * || (c == 92) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 1 to row 0 */ + goto st1; + } /* end state */ + + goto st30_error; + +st31: { /* DFA node {45,41,1} 31 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 0 to matched */ + matched_0 = caps0_8; + /* capture stores */ + matched_1 = i - 1; + matched_id = 4; + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st35: { /* DFA node {65,78,1} 35 */ + if (unlikely(i >= len)) { + i++; + goto st35_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 2 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + goto st36; + break; + } + case 39: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + goto st37; + break; + } + case 45: { + /* transfer caps from row 2 to row 3 */ + /* transfer caps from row 2 to row 4 */ + /* capture stores */ + caps2_6 = i - 1; + caps3_10 = i - 1; + goto st38; + break; + } + case 91: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_4 = i - 1; + goto st39; + break; + } + case 92: { + goto st40; + break; + } + case 93: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_8 = i - 1; + goto st41; + break; + } + case 123: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_0 = i - 1; + goto st42; + break; + } + case 125: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_2 = i - 1; + goto st43; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + goto st35; + } /* end state */ + + goto st35_error; + +st36: { /* DFA node {67,78,59,1} 36 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 0 to matched */ + matched_0 = caps0_12; + /* capture stores */ + matched_1 = i - 1; + matched_id = 6; + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st37: { /* DFA node {65,80,72,1} 37 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 1 to matched */ + matched_0 = caps1_14; + /* capture stores */ + matched_1 = i - 1; + matched_id = 7; + if (c != -1) { + if (c == 34) { + goto st58; + } + if (c == 92) { + goto st59; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st57; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st38: { /* DFA node {65,78,30,50,1} 38 */ + if (unlikely(i >= len)) { + i++; + goto st38_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 4 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 4 to row 2 */ + /* transfer caps from row 4 to row 3 */ + /* capture stores */ + goto st36; + break; + } + case 39: { + /* transfer caps from row 4 to row 2 */ + /* transfer caps from row 4 to row 3 */ + /* capture stores */ + goto st37; + break; + } + case 45: { + /* transfer caps from row 4 to row 5 */ + /* transfer caps from row 4 to row 6 */ + /* capture stores */ + goto st91; + break; + } + case 91: { + /* transfer caps from row 4 to row 2 */ + /* transfer caps from row 4 to row 3 */ + /* capture stores */ + caps2_4 = i - 1; + goto st39; + break; + } + case 92: { + /* transfer caps from row 4 to row 2 */ + goto st40; + break; + } + case 93: { + /* transfer caps from row 4 to row 2 */ + /* transfer caps from row 4 to row 3 */ + /* capture stores */ + caps2_8 = i - 1; + goto st41; + break; + } + case 123: { + /* transfer caps from row 4 to row 2 */ + /* transfer caps from row 4 to row 3 */ + /* capture stores */ + caps2_0 = i - 1; + goto st42; + break; + } + case 125: { + /* transfer caps from row 4 to row 2 */ + /* transfer caps from row 4 to row 3 */ + /* capture stores */ + caps2_2 = i - 1; + goto st43; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 4 to row 2 */ + goto st35; + } /* end state */ + + goto st38_error; + +st39: { /* DFA node {65,78,21,1} 39 */ + if (unlikely(i >= len)) { + i++; + goto st39_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 3 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + goto st36; + break; + } + case 39: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + goto st37; + break; + } + case 45: { + /* transfer caps from row 3 to row 2 */ + /* transfer caps from row 3 to row 4 */ + /* capture stores */ + caps2_6 = i - 1; + caps3_10 = i - 1; + goto st38; + break; + } + case 61: { + goto st92; + break; + } + case 91: { + /* transfer caps from row 3 to row 4 */ + /* capture stores */ + goto st93; + break; + } + case 92: { + /* transfer caps from row 3 to row 2 */ + goto st40; + break; + } + case 93: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_8 = i - 1; + goto st41; + break; + } + case 123: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_0 = i - 1; + goto st42; + break; + } + case 125: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_2 = i - 1; + goto st43; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 60) + * || (c >= 62 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 3 to row 2 */ + goto st35; + } /* end state */ + + goto st39_error; + +st40: { /* DFA node {62,75,1} 40 */ + if (unlikely(i >= len)) { + i++; + goto st40_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 2 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + goto st95; + break; + } + case 39: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + goto st96; + break; + } + case 45: { + /* transfer caps from row 2 to row 3 */ + /* transfer caps from row 2 to row 4 */ + /* capture stores */ + caps2_6 = i - 1; + caps3_10 = i - 1; + goto st97; + break; + } + case 91: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_4 = i - 1; + goto st98; + break; + } + case 93: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_8 = i - 1; + goto st99; + break; + } + case 123: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_0 = i - 1; + goto st100; + break; + } + case 125: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_2 = i - 1; + goto st101; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 90) + * || (c == 92) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + goto st94; + } /* end state */ + + goto st40_error; + +st41: { /* DFA node {65,78,41,1} 41 */ + if (unlikely(i >= len)) { + i++; + goto st41_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 3 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + goto st36; + break; + } + case 39: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + goto st37; + break; + } + case 45: { + /* transfer caps from row 3 to row 2 */ + /* transfer caps from row 3 to row 4 */ + /* capture stores */ + caps2_6 = i - 1; + caps3_10 = i - 1; + goto st38; + break; + } + case 61: { + goto st102; + break; + } + case 91: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_4 = i - 1; + goto st39; + break; + } + case 92: { + /* transfer caps from row 3 to row 2 */ + goto st40; + break; + } + case 93: { + /* transfer caps from row 3 to row 4 */ + /* capture stores */ + goto st103; + break; + } + case 123: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_0 = i - 1; + goto st42; + break; + } + case 125: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_2 = i - 1; + goto st43; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 60) + * || (c >= 62 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 3 to row 2 */ + goto st35; + } /* end state */ + + goto st41_error; + +st42: { /* DFA node {65,78,11,1} 42 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 2 to matched */ + matched_0 = caps2_0; + /* capture stores */ + matched_1 = i - 1; + matched_id = 0; + if (c != -1) { + if (c == 34) { + goto st105; + } + if (c == 39) { + goto st106; + } + if (c == 92) { + goto st107; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 38) + || (c >= 40 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st104; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st43: { /* DFA node {65,78,16,1} 43 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 2 to matched */ + matched_0 = caps2_2; + /* capture stores */ + matched_1 = i - 1; + matched_id = 1; + if (c != -1) { + if (c == 34) { + goto st105; + } + if (c == 39) { + goto st106; + } + if (c == 92) { + goto st107; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 38) + || (c >= 40 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st104; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st44: { /* DFA node {65,31,51,30,50,1} 44 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 2 to matched */ + matched_0 = caps2_10; + /* capture stores */ + matched_1 = i - 1; + matched_id = 5; + if (c != -1) { + if (c == 34) { + /* transfer caps from row 2 to row 1 */ + caps1_10 = caps2_10; + goto st109; + } + if (c == 91) { + goto st110; + } + if (c == 92) { + /* transfer caps from row 2 to row 1 */ + caps1_10 = caps2_10; + goto st111; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 90) + || (c >= 93 && c <= 255)) + { + /* transfer caps from row 2 to row 1 */ + caps1_10 = caps2_10; + goto st108; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st45: { /* DFA node {65,23,1} 45 */ + if (unlikely(i >= len)) { + i++; + goto st45_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 2 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_12 = i - 1; + goto st10; + break; + } + case 39: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_14 = i - 1; + goto st11; + break; + } + case 45: { + /* transfer caps from row 2 to row 1 */ + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps1_6 = i - 1; + caps2_10 = i - 1; + goto st12; + break; + } + case 61: { + goto st45; + break; + } + case 91: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_4 = i - 1; + goto st46; + break; + } + case 92: { + /* transfer caps from row 2 to row 1 */ + goto st14; + break; + } + case 93: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_8 = i - 1; + goto st15; + break; + } + case 123: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_0 = i - 1; + goto st16; + break; + } + case 125: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_2 = i - 1; + goto st17; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 60) + * || (c >= 62 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 2 to row 1 */ + goto st9; + } /* end state */ + + goto st45_error; + +st46: { /* DFA node {65,25,21,1} 46 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 1 to matched */ + matched_0 = caps1_4; + /* capture stores */ + matched_1 = i - 1; + matched_id = 2; + if (c != -1) { + if (c == 34) { + goto st58; + } + if (c == 92) { + goto st59; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st57; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st47: { /* DFA node {63,1} 47 */ + if (unlikely(i >= len)) { + i++; + goto st47_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 1 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_12 = i - 1; + goto st10; + break; + } + case 39: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_14 = i - 1; + goto st11; + break; + } + case 45: { + /* transfer caps from row 1 to row 2 */ + /* transfer caps from row 1 to row 3 */ + /* capture stores */ + caps1_6 = i - 1; + caps2_10 = i - 1; + goto st12; + break; + } + case 91: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_4 = i - 1; + goto st13; + break; + } + case 92: { + goto st14; + break; + } + case 93: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_8 = i - 1; + goto st15; + break; + } + case 123: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_0 = i - 1; + goto st16; + break; + } + case 125: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_2 = i - 1; + goto st17; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + goto st9; + } /* end state */ + + goto st47_error; + +st48: { /* DFA node {63,59,1} 48 */ + if (unlikely(i >= len)) { + i++; + goto st48_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 2 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_12 = i - 1; + goto st10; + break; + } + case 39: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_14 = i - 1; + goto st11; + break; + } + case 45: { + /* transfer caps from row 2 to row 1 */ + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps1_6 = i - 1; + caps2_10 = i - 1; + goto st12; + break; + } + case 91: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_4 = i - 1; + goto st13; + break; + } + case 92: { + /* transfer caps from row 2 to row 1 */ + goto st14; + break; + } + case 93: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_8 = i - 1; + goto st15; + break; + } + case 123: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_0 = i - 1; + goto st16; + break; + } + case 125: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_2 = i - 1; + goto st17; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 2 to row 1 */ + goto st9; + } /* end state */ + + goto st48_error; + +st49: { /* DFA node {63,72,1} 49 */ + if (unlikely(i >= len)) { + i++; + goto st49_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 2 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + goto st36; + break; + } + case 39: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + goto st37; + break; + } + case 45: { + /* transfer caps from row 2 to row 3 */ + /* transfer caps from row 2 to row 4 */ + /* capture stores */ + caps2_6 = i - 1; + caps3_10 = i - 1; + goto st38; + break; + } + case 91: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_4 = i - 1; + goto st39; + break; + } + case 92: { + goto st40; + break; + } + case 93: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_8 = i - 1; + goto st41; + break; + } + case 123: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_0 = i - 1; + goto st42; + break; + } + case 125: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_2 = i - 1; + goto st43; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + goto st35; + } /* end state */ + + goto st49_error; + +st50: { /* DFA node {63,30,50,1} 50 */ + if (unlikely(i >= len)) { + i++; + goto st50_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 3 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 3 to row 1 */ + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps1_12 = i - 1; + goto st10; + break; + } + case 39: { + /* transfer caps from row 3 to row 1 */ + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps1_14 = i - 1; + goto st11; + break; + } + case 45: { + /* transfer caps from row 3 to row 4 */ + /* transfer caps from row 3 to row 5 */ + /* capture stores */ + goto st44; + break; + } + case 91: { + /* transfer caps from row 3 to row 1 */ + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps1_4 = i - 1; + goto st13; + break; + } + case 92: { + /* transfer caps from row 3 to row 1 */ + goto st14; + break; + } + case 93: { + /* transfer caps from row 3 to row 1 */ + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps1_8 = i - 1; + goto st15; + break; + } + case 123: { + /* transfer caps from row 3 to row 1 */ + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps1_0 = i - 1; + goto st16; + break; + } + case 125: { + /* transfer caps from row 3 to row 1 */ + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps1_2 = i - 1; + goto st17; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 3 to row 1 */ + goto st9; + } /* end state */ + + goto st50_error; + +st51: { /* DFA node {63,21,1} 51 */ + if (unlikely(i >= len)) { + i++; + goto st51_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 2 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_12 = i - 1; + goto st10; + break; + } + case 39: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_14 = i - 1; + goto st11; + break; + } + case 45: { + /* transfer caps from row 2 to row 1 */ + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps1_6 = i - 1; + caps2_10 = i - 1; + goto st12; + break; + } + case 61: { + goto st45; + break; + } + case 91: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_4 = i - 1; + goto st46; + break; + } + case 92: { + /* transfer caps from row 2 to row 1 */ + goto st14; + break; + } + case 93: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_8 = i - 1; + goto st15; + break; + } + case 123: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_0 = i - 1; + goto st16; + break; + } + case 125: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_2 = i - 1; + goto st17; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 60) + * || (c >= 62 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 2 to row 1 */ + goto st9; + } /* end state */ + + goto st51_error; + +st52: { /* DFA node {63,41,1} 52 */ + if (unlikely(i >= len)) { + i++; + goto st52_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 2 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_12 = i - 1; + goto st10; + break; + } + case 39: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_14 = i - 1; + goto st11; + break; + } + case 45: { + /* transfer caps from row 2 to row 1 */ + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps1_6 = i - 1; + caps2_10 = i - 1; + goto st12; + break; + } + case 61: { + goto st55; + break; + } + case 91: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_4 = i - 1; + goto st13; + break; + } + case 92: { + /* transfer caps from row 2 to row 1 */ + goto st14; + break; + } + case 93: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_8 = i - 1; + goto st56; + break; + } + case 123: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_0 = i - 1; + goto st16; + break; + } + case 125: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_2 = i - 1; + goto st17; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 60) + * || (c >= 62 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 2 to row 1 */ + goto st9; + } /* end state */ + + goto st52_error; + +st53: { /* DFA node {63,11,1} 53 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 1 to matched */ + matched_0 = caps1_0; + /* capture stores */ + matched_1 = i - 1; + matched_id = 0; + if (c != -1) { + if (c == 34) { + goto st58; + } + if (c == 92) { + goto st59; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st57; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st54: { /* DFA node {63,16,1} 54 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 1 to matched */ + matched_0 = caps1_2; + /* capture stores */ + matched_1 = i - 1; + matched_id = 1; + if (c != -1) { + if (c == 34) { + goto st58; + } + if (c == 92) { + goto st59; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st57; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st55: { /* DFA node {65,43,1} 55 */ + if (unlikely(i >= len)) { + i++; + goto st55_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 2 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_12 = i - 1; + goto st10; + break; + } + case 39: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_14 = i - 1; + goto st11; + break; + } + case 45: { + /* transfer caps from row 2 to row 1 */ + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps1_6 = i - 1; + caps2_10 = i - 1; + goto st12; + break; + } + case 61: { + goto st55; + break; + } + case 91: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_4 = i - 1; + goto st13; + break; + } + case 92: { + /* transfer caps from row 2 to row 1 */ + goto st14; + break; + } + case 93: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_8 = i - 1; + goto st56; + break; + } + case 123: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_0 = i - 1; + goto st16; + break; + } + case 125: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_2 = i - 1; + goto st17; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 60) + * || (c >= 62 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 2 to row 1 */ + goto st9; + } /* end state */ + + goto st55_error; + +st56: { /* DFA node {65,45,41,1} 56 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 1 to matched */ + matched_0 = caps1_8; + /* capture stores */ + matched_1 = i - 1; + matched_id = 4; + if (c != -1) { + if (c == 34) { + goto st58; + } + if (c == 92) { + goto st59; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st57; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st57: { /* DFA node {65} 57 */ + if (unlikely(i >= len)) { + i++; + goto st57_error; + } + + c = s[i]; + i++; + switch (c) { + case 34: { + goto st58; + break; + } + case 92: { + goto st59; + break; + } + default: + break; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st57; + } + } /* end state */ + + goto st57_error; + +st58: { /* DFA node {67} 58 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 0 to matched */ + matched_0 = caps0_12; + /* capture stores */ + matched_1 = i - 1; + matched_id = 6; + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st59: { /* DFA node {62} 59 */ + if (unlikely(i >= len)) { + i++; + goto st59_error; + } + + c = s[i]; + i++; + if ((c >= 0 && c <= 9) || (c >= 11 && c <= 255)) { + goto st112; + } + } /* end state */ + + goto st59_error; + +st60: { /* DFA node {78,65,1} 60 */ + if (unlikely(i >= len)) { + i++; + goto st60_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 2 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + goto st61; + break; + } + case 39: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + goto st62; + break; + } + case 45: { + /* transfer caps from row 2 to row 3 */ + /* transfer caps from row 2 to row 4 */ + /* capture stores */ + caps2_6 = i - 1; + caps3_10 = i - 1; + goto st63; + break; + } + case 91: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_4 = i - 1; + goto st64; + break; + } + case 92: { + goto st65; + break; + } + case 93: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_8 = i - 1; + goto st66; + break; + } + case 123: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_0 = i - 1; + goto st67; + break; + } + case 125: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_2 = i - 1; + goto st68; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + goto st60; + } /* end state */ + + goto st60_error; + +st61: { /* DFA node {78,67,59,1} 61 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 1 to matched */ + matched_0 = caps1_12; + /* capture stores */ + matched_1 = i - 1; + matched_id = 6; + if (c != -1) { + if (c == 39) { + goto st84; + } + if (c == 92) { + goto st85; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 38) + || (c >= 40 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st83; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st62: { /* DFA node {80,65,72,1} 62 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 0 to matched */ + matched_0 = caps0_14; + /* capture stores */ + matched_1 = i - 1; + matched_id = 7; + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st63: { /* DFA node {78,65,30,50,1} 63 */ + if (unlikely(i >= len)) { + i++; + goto st63_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 4 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 4 to row 2 */ + /* transfer caps from row 4 to row 3 */ + /* capture stores */ + goto st61; + break; + } + case 39: { + /* transfer caps from row 4 to row 2 */ + /* transfer caps from row 4 to row 3 */ + /* capture stores */ + goto st62; + break; + } + case 45: { + /* transfer caps from row 4 to row 5 */ + /* transfer caps from row 4 to row 6 */ + /* capture stores */ + goto st113; + break; + } + case 91: { + /* transfer caps from row 4 to row 2 */ + /* transfer caps from row 4 to row 3 */ + /* capture stores */ + caps2_4 = i - 1; + goto st64; + break; + } + case 92: { + /* transfer caps from row 4 to row 2 */ + goto st65; + break; + } + case 93: { + /* transfer caps from row 4 to row 2 */ + /* transfer caps from row 4 to row 3 */ + /* capture stores */ + caps2_8 = i - 1; + goto st66; + break; + } + case 123: { + /* transfer caps from row 4 to row 2 */ + /* transfer caps from row 4 to row 3 */ + /* capture stores */ + caps2_0 = i - 1; + goto st67; + break; + } + case 125: { + /* transfer caps from row 4 to row 2 */ + /* transfer caps from row 4 to row 3 */ + /* capture stores */ + caps2_2 = i - 1; + goto st68; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 4 to row 2 */ + goto st60; + } /* end state */ + + goto st63_error; + +st64: { /* DFA node {78,65,21,1} 64 */ + if (unlikely(i >= len)) { + i++; + goto st64_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 3 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + goto st61; + break; + } + case 39: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + goto st62; + break; + } + case 45: { + /* transfer caps from row 3 to row 2 */ + /* transfer caps from row 3 to row 4 */ + /* capture stores */ + caps2_6 = i - 1; + caps3_10 = i - 1; + goto st63; + break; + } + case 61: { + goto st114; + break; + } + case 91: { + /* transfer caps from row 3 to row 4 */ + /* capture stores */ + goto st115; + break; + } + case 92: { + /* transfer caps from row 3 to row 2 */ + goto st65; + break; + } + case 93: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_8 = i - 1; + goto st66; + break; + } + case 123: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_0 = i - 1; + goto st67; + break; + } + case 125: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_2 = i - 1; + goto st68; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 60) + * || (c >= 62 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 3 to row 2 */ + goto st60; + } /* end state */ + + goto st64_error; + +st65: { /* DFA node {75,62,1} 65 */ + if (unlikely(i >= len)) { + i++; + goto st65_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 2 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + goto st117; + break; + } + case 39: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + goto st118; + break; + } + case 45: { + /* transfer caps from row 2 to row 3 */ + /* transfer caps from row 2 to row 4 */ + /* capture stores */ + caps2_6 = i - 1; + caps3_10 = i - 1; + goto st119; + break; + } + case 91: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_4 = i - 1; + goto st120; + break; + } + case 93: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_8 = i - 1; + goto st121; + break; + } + case 123: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_0 = i - 1; + goto st122; + break; + } + case 125: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_2 = i - 1; + goto st123; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 90) + * || (c == 92) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + goto st116; + } /* end state */ + + goto st65_error; + +st66: { /* DFA node {78,65,41,1} 66 */ + if (unlikely(i >= len)) { + i++; + goto st66_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 3 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + goto st61; + break; + } + case 39: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + goto st62; + break; + } + case 45: { + /* transfer caps from row 3 to row 2 */ + /* transfer caps from row 3 to row 4 */ + /* capture stores */ + caps2_6 = i - 1; + caps3_10 = i - 1; + goto st63; + break; + } + case 61: { + goto st124; + break; + } + case 91: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_4 = i - 1; + goto st64; + break; + } + case 92: { + /* transfer caps from row 3 to row 2 */ + goto st65; + break; + } + case 93: { + /* transfer caps from row 3 to row 4 */ + /* capture stores */ + goto st125; + break; + } + case 123: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_0 = i - 1; + goto st67; + break; + } + case 125: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_2 = i - 1; + goto st68; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 60) + * || (c >= 62 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 3 to row 2 */ + goto st60; + } /* end state */ + + goto st66_error; + +st67: { /* DFA node {78,65,11,1} 67 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 2 to matched */ + matched_0 = caps2_0; + /* capture stores */ + matched_1 = i - 1; + matched_id = 0; + if (c != -1) { + if (c == 34) { + goto st127; + } + if (c == 39) { + goto st128; + } + if (c == 92) { + goto st129; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 38) + || (c >= 40 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st126; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st68: { /* DFA node {78,65,16,1} 68 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 2 to matched */ + matched_0 = caps2_2; + /* capture stores */ + matched_1 = i - 1; + matched_id = 1; + if (c != -1) { + if (c == 34) { + goto st127; + } + if (c == 39) { + goto st128; + } + if (c == 92) { + goto st129; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 38) + || (c >= 40 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st126; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st70: { /* DFA node {78,31,51,30,50,1} 70 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 2 to matched */ + matched_0 = caps2_10; + /* capture stores */ + matched_1 = i - 1; + matched_id = 5; + if (c != -1) { + if (c == 39) { + /* transfer caps from row 2 to row 1 */ + caps1_10 = caps2_10; + goto st131; + } + if (c == 91) { + goto st132; + } + if (c == 92) { + /* transfer caps from row 2 to row 1 */ + caps1_10 = caps2_10; + goto st133; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 38) + || (c >= 40 && c <= 90) + || (c >= 93 && c <= 255)) + { + /* transfer caps from row 2 to row 1 */ + caps1_10 = caps2_10; + goto st130; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st71: { /* DFA node {78,23,1} 71 */ + if (unlikely(i >= len)) { + i++; + goto st71_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 2 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_12 = i - 1; + goto st19; + break; + } + case 39: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_14 = i - 1; + goto st20; + break; + } + case 45: { + /* transfer caps from row 2 to row 1 */ + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps1_6 = i - 1; + caps2_10 = i - 1; + goto st21; + break; + } + case 61: { + goto st71; + break; + } + case 91: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_4 = i - 1; + goto st72; + break; + } + case 92: { + /* transfer caps from row 2 to row 1 */ + goto st23; + break; + } + case 93: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_8 = i - 1; + goto st24; + break; + } + case 123: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_0 = i - 1; + goto st25; + break; + } + case 125: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_2 = i - 1; + goto st26; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 60) + * || (c >= 62 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 2 to row 1 */ + goto st18; + } /* end state */ + + goto st71_error; + +st72: { /* DFA node {78,25,21,1} 72 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 1 to matched */ + matched_0 = caps1_4; + /* capture stores */ + matched_1 = i - 1; + matched_id = 2; + if (c != -1) { + if (c == 39) { + goto st84; + } + if (c == 92) { + goto st85; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 38) + || (c >= 40 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st83; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st73: { /* DFA node {76,1} 73 */ + if (unlikely(i >= len)) { + i++; + goto st73_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 1 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_12 = i - 1; + goto st19; + break; + } + case 39: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_14 = i - 1; + goto st20; + break; + } + case 45: { + /* transfer caps from row 1 to row 2 */ + /* transfer caps from row 1 to row 3 */ + /* capture stores */ + caps1_6 = i - 1; + caps2_10 = i - 1; + goto st21; + break; + } + case 91: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_4 = i - 1; + goto st22; + break; + } + case 92: { + goto st23; + break; + } + case 93: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_8 = i - 1; + goto st24; + break; + } + case 123: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_0 = i - 1; + goto st25; + break; + } + case 125: { + /* transfer caps from row 1 to row 2 */ + /* capture stores */ + caps1_2 = i - 1; + goto st26; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + goto st18; + } /* end state */ + + goto st73_error; + +st74: { /* DFA node {76,59,1} 74 */ + if (unlikely(i >= len)) { + i++; + goto st74_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 2 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + goto st61; + break; + } + case 39: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + goto st62; + break; + } + case 45: { + /* transfer caps from row 2 to row 3 */ + /* transfer caps from row 2 to row 4 */ + /* capture stores */ + caps2_6 = i - 1; + caps3_10 = i - 1; + goto st63; + break; + } + case 91: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_4 = i - 1; + goto st64; + break; + } + case 92: { + goto st65; + break; + } + case 93: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_8 = i - 1; + goto st66; + break; + } + case 123: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_0 = i - 1; + goto st67; + break; + } + case 125: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_2 = i - 1; + goto st68; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + goto st60; + } /* end state */ + + goto st74_error; + +st75: { /* DFA node {76,72,1} 75 */ + if (unlikely(i >= len)) { + i++; + goto st75_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 2 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_12 = i - 1; + goto st19; + break; + } + case 39: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_14 = i - 1; + goto st20; + break; + } + case 45: { + /* transfer caps from row 2 to row 1 */ + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps1_6 = i - 1; + caps2_10 = i - 1; + goto st21; + break; + } + case 91: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_4 = i - 1; + goto st22; + break; + } + case 92: { + /* transfer caps from row 2 to row 1 */ + goto st23; + break; + } + case 93: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_8 = i - 1; + goto st24; + break; + } + case 123: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_0 = i - 1; + goto st25; + break; + } + case 125: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_2 = i - 1; + goto st26; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 2 to row 1 */ + goto st18; + } /* end state */ + + goto st75_error; + +st76: { /* DFA node {76,30,50,1} 76 */ + if (unlikely(i >= len)) { + i++; + goto st76_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 3 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 3 to row 1 */ + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps1_12 = i - 1; + goto st19; + break; + } + case 39: { + /* transfer caps from row 3 to row 1 */ + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps1_14 = i - 1; + goto st20; + break; + } + case 45: { + /* transfer caps from row 3 to row 4 */ + /* transfer caps from row 3 to row 5 */ + /* capture stores */ + goto st70; + break; + } + case 91: { + /* transfer caps from row 3 to row 1 */ + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps1_4 = i - 1; + goto st22; + break; + } + case 92: { + /* transfer caps from row 3 to row 1 */ + goto st23; + break; + } + case 93: { + /* transfer caps from row 3 to row 1 */ + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps1_8 = i - 1; + goto st24; + break; + } + case 123: { + /* transfer caps from row 3 to row 1 */ + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps1_0 = i - 1; + goto st25; + break; + } + case 125: { + /* transfer caps from row 3 to row 1 */ + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps1_2 = i - 1; + goto st26; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 3 to row 1 */ + goto st18; + } /* end state */ + + goto st76_error; + +st77: { /* DFA node {76,21,1} 77 */ + if (unlikely(i >= len)) { + i++; + goto st77_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 2 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_12 = i - 1; + goto st19; + break; + } + case 39: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_14 = i - 1; + goto st20; + break; + } + case 45: { + /* transfer caps from row 2 to row 1 */ + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps1_6 = i - 1; + caps2_10 = i - 1; + goto st21; + break; + } + case 61: { + goto st71; + break; + } + case 91: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_4 = i - 1; + goto st72; + break; + } + case 92: { + /* transfer caps from row 2 to row 1 */ + goto st23; + break; + } + case 93: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_8 = i - 1; + goto st24; + break; + } + case 123: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_0 = i - 1; + goto st25; + break; + } + case 125: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_2 = i - 1; + goto st26; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 60) + * || (c >= 62 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 2 to row 1 */ + goto st18; + } /* end state */ + + goto st77_error; + +st78: { /* DFA node {76,41,1} 78 */ + if (unlikely(i >= len)) { + i++; + goto st78_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 2 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_12 = i - 1; + goto st19; + break; + } + case 39: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_14 = i - 1; + goto st20; + break; + } + case 45: { + /* transfer caps from row 2 to row 1 */ + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps1_6 = i - 1; + caps2_10 = i - 1; + goto st21; + break; + } + case 61: { + goto st81; + break; + } + case 91: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_4 = i - 1; + goto st22; + break; + } + case 92: { + /* transfer caps from row 2 to row 1 */ + goto st23; + break; + } + case 93: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_8 = i - 1; + goto st82; + break; + } + case 123: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_0 = i - 1; + goto st25; + break; + } + case 125: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_2 = i - 1; + goto st26; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 60) + * || (c >= 62 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 2 to row 1 */ + goto st18; + } /* end state */ + + goto st78_error; + +st79: { /* DFA node {76,11,1} 79 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 1 to matched */ + matched_0 = caps1_0; + /* capture stores */ + matched_1 = i - 1; + matched_id = 0; + if (c != -1) { + if (c == 39) { + goto st84; + } + if (c == 92) { + goto st85; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 38) + || (c >= 40 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st83; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st80: { /* DFA node {76,16,1} 80 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 1 to matched */ + matched_0 = caps1_2; + /* capture stores */ + matched_1 = i - 1; + matched_id = 1; + if (c != -1) { + if (c == 39) { + goto st84; + } + if (c == 92) { + goto st85; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 38) + || (c >= 40 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st83; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st81: { /* DFA node {78,43,1} 81 */ + if (unlikely(i >= len)) { + i++; + goto st81_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 2 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_12 = i - 1; + goto st19; + break; + } + case 39: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_14 = i - 1; + goto st20; + break; + } + case 45: { + /* transfer caps from row 2 to row 1 */ + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps1_6 = i - 1; + caps2_10 = i - 1; + goto st21; + break; + } + case 61: { + goto st81; + break; + } + case 91: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_4 = i - 1; + goto st22; + break; + } + case 92: { + /* transfer caps from row 2 to row 1 */ + goto st23; + break; + } + case 93: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_8 = i - 1; + goto st82; + break; + } + case 123: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_0 = i - 1; + goto st25; + break; + } + case 125: { + /* transfer caps from row 2 to row 1 */ + /* capture stores */ + caps1_2 = i - 1; + goto st26; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 60) + * || (c >= 62 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 2 to row 1 */ + goto st18; + } /* end state */ + + goto st81_error; + +st82: { /* DFA node {78,45,41,1} 82 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 1 to matched */ + matched_0 = caps1_8; + /* capture stores */ + matched_1 = i - 1; + matched_id = 4; + if (c != -1) { + if (c == 39) { + goto st84; + } + if (c == 92) { + goto st85; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 38) + || (c >= 40 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st83; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st83: { /* DFA node {78} 83 */ + if (unlikely(i >= len)) { + i++; + goto st83_error; + } + + c = s[i]; + i++; + switch (c) { + case 39: { + goto st84; + break; + } + case 92: { + goto st85; + break; + } + default: + break; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 38) + || (c >= 40 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st83; + } + } /* end state */ + + goto st83_error; + +st84: { /* DFA node {80} 84 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 0 to matched */ + matched_0 = caps0_14; + /* capture stores */ + matched_1 = i - 1; + matched_id = 7; + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st85: { /* DFA node {75} 85 */ + if (unlikely(i >= len)) { + i++; + goto st85_error; + } + + c = s[i]; + i++; + if ((c >= 0 && c <= 9) || (c >= 11 && c <= 255)) { + goto st134; + } + } /* end state */ + + goto st85_error; + +st87: { /* DFA node {53} 87 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 0 to matched */ + matched_0 = caps0_10; + /* capture stores */ + matched_1 = i - 1; + matched_id = 5; + if (c != -1) { + if ((c >= 0 && c <= 9) || (c >= 11 && c <= 255)) { + goto st87; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st88: { /* DFA node {32,53} 88 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 1 to matched */ + matched_0 = caps1_10; + /* capture stores */ + matched_1 = i - 1; + matched_id = 5; + if (c != -1) { + if (c == 61) { + goto st135; + } + if (c == 91) { + goto st136; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 60) + || (c >= 62 && c <= 90) + || (c >= 92 && c <= 255)) + { + /* transfer caps from row 1 to row 0 */ + caps0_10 = caps1_10; + goto st87; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st91: { /* DFA node {65,78,31,51,30,50,1} 91 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 3 to matched */ + matched_0 = caps3_10; + /* capture stores */ + matched_1 = i - 1; + matched_id = 5; + if (c != -1) { + if (c == 34) { + /* transfer caps from row 3 to row 2 */ + caps2_10 = caps3_10; + goto st138; + } + if (c == 39) { + /* transfer caps from row 3 to row 2 */ + caps2_10 = caps3_10; + goto st139; + } + if (c == 91) { + goto st140; + } + if (c == 92) { + /* transfer caps from row 3 to row 2 */ + caps2_10 = caps3_10; + goto st141; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 38) + || (c >= 40 && c <= 90) + || (c >= 93 && c <= 255)) + { + /* transfer caps from row 3 to row 2 */ + caps2_10 = caps3_10; + goto st137; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st92: { /* DFA node {65,78,23,1} 92 */ + if (unlikely(i >= len)) { + i++; + goto st92_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 3 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + goto st36; + break; + } + case 39: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + goto st37; + break; + } + case 45: { + /* transfer caps from row 3 to row 2 */ + /* transfer caps from row 3 to row 4 */ + /* capture stores */ + caps2_6 = i - 1; + caps3_10 = i - 1; + goto st38; + break; + } + case 61: { + goto st92; + break; + } + case 91: { + /* transfer caps from row 3 to row 4 */ + /* capture stores */ + goto st93; + break; + } + case 92: { + /* transfer caps from row 3 to row 2 */ + goto st40; + break; + } + case 93: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_8 = i - 1; + goto st41; + break; + } + case 123: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_0 = i - 1; + goto st42; + break; + } + case 125: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_2 = i - 1; + goto st43; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 60) + * || (c >= 62 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 3 to row 2 */ + goto st35; + } /* end state */ + + goto st92_error; + +st93: { /* DFA node {65,78,25,21,1} 93 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 2 to matched */ + matched_0 = caps2_4; + /* capture stores */ + matched_1 = i - 1; + matched_id = 2; + if (c != -1) { + if (c == 34) { + goto st105; + } + if (c == 39) { + goto st106; + } + if (c == 92) { + goto st107; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 38) + || (c >= 40 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st104; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st94: { /* DFA node {63,76,1} 94 */ + if (unlikely(i >= len)) { + i++; + goto st94_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 2 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + goto st36; + break; + } + case 39: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + goto st37; + break; + } + case 45: { + /* transfer caps from row 2 to row 3 */ + /* transfer caps from row 2 to row 4 */ + /* capture stores */ + caps2_6 = i - 1; + caps3_10 = i - 1; + goto st38; + break; + } + case 91: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_4 = i - 1; + goto st39; + break; + } + case 92: { + goto st40; + break; + } + case 93: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_8 = i - 1; + goto st41; + break; + } + case 123: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_0 = i - 1; + goto st42; + break; + } + case 125: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_2 = i - 1; + goto st43; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + goto st35; + } /* end state */ + + goto st94_error; + +st95: { /* DFA node {63,76,59,1} 95 */ + if (unlikely(i >= len)) { + i++; + goto st95_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 3 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + goto st36; + break; + } + case 39: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + goto st37; + break; + } + case 45: { + /* transfer caps from row 3 to row 2 */ + /* transfer caps from row 3 to row 4 */ + /* capture stores */ + caps2_6 = i - 1; + caps3_10 = i - 1; + goto st38; + break; + } + case 91: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_4 = i - 1; + goto st39; + break; + } + case 92: { + /* transfer caps from row 3 to row 2 */ + goto st40; + break; + } + case 93: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_8 = i - 1; + goto st41; + break; + } + case 123: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_0 = i - 1; + goto st42; + break; + } + case 125: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_2 = i - 1; + goto st43; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 3 to row 2 */ + goto st35; + } /* end state */ + + goto st95_error; + +st96: { /* DFA node {63,76,72,1} 96 */ + if (unlikely(i >= len)) { + i++; + goto st96_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 3 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + goto st36; + break; + } + case 39: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + goto st37; + break; + } + case 45: { + /* transfer caps from row 3 to row 2 */ + /* transfer caps from row 3 to row 4 */ + /* capture stores */ + caps2_6 = i - 1; + caps3_10 = i - 1; + goto st38; + break; + } + case 91: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_4 = i - 1; + goto st39; + break; + } + case 92: { + /* transfer caps from row 3 to row 2 */ + goto st40; + break; + } + case 93: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_8 = i - 1; + goto st41; + break; + } + case 123: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_0 = i - 1; + goto st42; + break; + } + case 125: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_2 = i - 1; + goto st43; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 3 to row 2 */ + goto st35; + } /* end state */ + + goto st96_error; + +st97: { /* DFA node {63,76,30,50,1} 97 */ + if (unlikely(i >= len)) { + i++; + goto st97_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 4 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 4 to row 2 */ + /* transfer caps from row 4 to row 3 */ + /* capture stores */ + goto st36; + break; + } + case 39: { + /* transfer caps from row 4 to row 2 */ + /* transfer caps from row 4 to row 3 */ + /* capture stores */ + goto st37; + break; + } + case 45: { + /* transfer caps from row 4 to row 5 */ + /* transfer caps from row 4 to row 6 */ + /* capture stores */ + goto st91; + break; + } + case 91: { + /* transfer caps from row 4 to row 2 */ + /* transfer caps from row 4 to row 3 */ + /* capture stores */ + caps2_4 = i - 1; + goto st39; + break; + } + case 92: { + /* transfer caps from row 4 to row 2 */ + goto st40; + break; + } + case 93: { + /* transfer caps from row 4 to row 2 */ + /* transfer caps from row 4 to row 3 */ + /* capture stores */ + caps2_8 = i - 1; + goto st41; + break; + } + case 123: { + /* transfer caps from row 4 to row 2 */ + /* transfer caps from row 4 to row 3 */ + /* capture stores */ + caps2_0 = i - 1; + goto st42; + break; + } + case 125: { + /* transfer caps from row 4 to row 2 */ + /* transfer caps from row 4 to row 3 */ + /* capture stores */ + caps2_2 = i - 1; + goto st43; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 4 to row 2 */ + goto st35; + } /* end state */ + + goto st97_error; + +st98: { /* DFA node {63,76,21,1} 98 */ + if (unlikely(i >= len)) { + i++; + goto st98_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 3 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + goto st36; + break; + } + case 39: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + goto st37; + break; + } + case 45: { + /* transfer caps from row 3 to row 2 */ + /* transfer caps from row 3 to row 4 */ + /* capture stores */ + caps2_6 = i - 1; + caps3_10 = i - 1; + goto st38; + break; + } + case 61: { + goto st92; + break; + } + case 91: { + /* transfer caps from row 3 to row 4 */ + /* capture stores */ + goto st93; + break; + } + case 92: { + /* transfer caps from row 3 to row 2 */ + goto st40; + break; + } + case 93: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_8 = i - 1; + goto st41; + break; + } + case 123: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_0 = i - 1; + goto st42; + break; + } + case 125: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_2 = i - 1; + goto st43; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 60) + * || (c >= 62 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 3 to row 2 */ + goto st35; + } /* end state */ + + goto st98_error; + +st99: { /* DFA node {63,76,41,1} 99 */ + if (unlikely(i >= len)) { + i++; + goto st99_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 3 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + goto st36; + break; + } + case 39: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + goto st37; + break; + } + case 45: { + /* transfer caps from row 3 to row 2 */ + /* transfer caps from row 3 to row 4 */ + /* capture stores */ + caps2_6 = i - 1; + caps3_10 = i - 1; + goto st38; + break; + } + case 61: { + goto st102; + break; + } + case 91: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_4 = i - 1; + goto st39; + break; + } + case 92: { + /* transfer caps from row 3 to row 2 */ + goto st40; + break; + } + case 93: { + /* transfer caps from row 3 to row 4 */ + /* capture stores */ + goto st103; + break; + } + case 123: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_0 = i - 1; + goto st42; + break; + } + case 125: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_2 = i - 1; + goto st43; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 60) + * || (c >= 62 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 3 to row 2 */ + goto st35; + } /* end state */ + + goto st99_error; + +st100: { /* DFA node {63,76,11,1} 100 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 2 to matched */ + matched_0 = caps2_0; + /* capture stores */ + matched_1 = i - 1; + matched_id = 0; + if (c != -1) { + if (c == 34) { + goto st105; + } + if (c == 39) { + goto st106; + } + if (c == 92) { + goto st107; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 38) + || (c >= 40 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st104; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st101: { /* DFA node {63,76,16,1} 101 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 2 to matched */ + matched_0 = caps2_2; + /* capture stores */ + matched_1 = i - 1; + matched_id = 1; + if (c != -1) { + if (c == 34) { + goto st105; + } + if (c == 39) { + goto st106; + } + if (c == 92) { + goto st107; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 38) + || (c >= 40 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st104; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st102: { /* DFA node {65,78,43,1} 102 */ + if (unlikely(i >= len)) { + i++; + goto st102_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 3 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + goto st36; + break; + } + case 39: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + goto st37; + break; + } + case 45: { + /* transfer caps from row 3 to row 2 */ + /* transfer caps from row 3 to row 4 */ + /* capture stores */ + caps2_6 = i - 1; + caps3_10 = i - 1; + goto st38; + break; + } + case 61: { + goto st102; + break; + } + case 91: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_4 = i - 1; + goto st39; + break; + } + case 92: { + /* transfer caps from row 3 to row 2 */ + goto st40; + break; + } + case 93: { + /* transfer caps from row 3 to row 4 */ + /* capture stores */ + goto st103; + break; + } + case 123: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_0 = i - 1; + goto st42; + break; + } + case 125: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_2 = i - 1; + goto st43; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 60) + * || (c >= 62 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 3 to row 2 */ + goto st35; + } /* end state */ + + goto st102_error; + +st103: { /* DFA node {65,78,45,41,1} 103 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 2 to matched */ + matched_0 = caps2_8; + /* capture stores */ + matched_1 = i - 1; + matched_id = 4; + if (c != -1) { + if (c == 34) { + goto st105; + } + if (c == 39) { + goto st106; + } + if (c == 92) { + goto st107; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 38) + || (c >= 40 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st104; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st104: { /* DFA node {65,78} 104 */ + if (unlikely(i >= len)) { + i++; + goto st104_error; + } + + c = s[i]; + i++; + switch (c) { + case 34: { + goto st105; + break; + } + case 39: { + goto st106; + break; + } + case 92: { + goto st107; + break; + } + default: + break; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 38) + || (c >= 40 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st104; + } + } /* end state */ + + goto st104_error; + +st105: { /* DFA node {67,78} 105 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 0 to matched */ + matched_0 = caps0_12; + /* capture stores */ + matched_1 = i - 1; + matched_id = 6; + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st106: { /* DFA node {65,80} 106 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 1 to matched */ + matched_0 = caps1_14; + /* capture stores */ + matched_1 = i - 1; + matched_id = 7; + if (c != -1) { + if (c == 34) { + goto st58; + } + if (c == 92) { + goto st59; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st57; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st107: { /* DFA node {62,75} 107 */ + if (unlikely(i >= len)) { + i++; + goto st107_error; + } + + c = s[i]; + i++; + if ((c >= 0 && c <= 9) || (c >= 11 && c <= 255)) { + goto st142; + } + } /* end state */ + + goto st107_error; + +st108: { /* DFA node {65,53} 108 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 1 to matched */ + matched_0 = caps1_10; + /* capture stores */ + matched_1 = i - 1; + matched_id = 5; + if (c != -1) { + if (c == 34) { + goto st109; + } + if (c == 92) { + goto st111; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st108; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st109: { /* DFA node {67,53} 109 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 0 to matched */ + matched_0 = caps0_12; + /* capture stores */ + matched_1 = i - 1; + matched_id = 6; + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st110: { /* DFA node {65,32,53} 110 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 2 to matched */ + matched_0 = caps2_10; + /* capture stores */ + matched_1 = i - 1; + matched_id = 5; + if (c != -1) { + if (c == 34) { + /* transfer caps from row 2 to row 1 */ + caps1_10 = caps2_10; + goto st109; + } + if (c == 61) { + goto st143; + } + if (c == 91) { + goto st144; + } + if (c == 92) { + /* transfer caps from row 2 to row 1 */ + caps1_10 = caps2_10; + goto st111; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 60) + || (c >= 62 && c <= 90) + || (c >= 93 && c <= 255)) + { + /* transfer caps from row 2 to row 1 */ + caps1_10 = caps2_10; + goto st108; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st111: { /* DFA node {62,53} 111 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 1 to matched */ + matched_0 = caps1_10; + /* capture stores */ + matched_1 = i - 1; + matched_id = 5; + if (c != -1) { + if ((c >= 0 && c <= 9) || (c >= 11 && c <= 255)) { + goto st145; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st112: { /* DFA node {63} 112 */ + if (unlikely(i >= len)) { + i++; + goto st112_error; + } + + c = s[i]; + i++; + switch (c) { + case 34: { + goto st58; + break; + } + case 92: { + goto st59; + break; + } + default: + break; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st57; + } + } /* end state */ + + goto st112_error; + +st113: { /* DFA node {78,65,31,51,30,50,1} 113 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 3 to matched */ + matched_0 = caps3_10; + /* capture stores */ + matched_1 = i - 1; + matched_id = 5; + if (c != -1) { + if (c == 34) { + /* transfer caps from row 3 to row 2 */ + caps2_10 = caps3_10; + goto st147; + } + if (c == 39) { + /* transfer caps from row 3 to row 2 */ + caps2_10 = caps3_10; + goto st148; + } + if (c == 91) { + goto st149; + } + if (c == 92) { + /* transfer caps from row 3 to row 2 */ + caps2_10 = caps3_10; + goto st150; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 38) + || (c >= 40 && c <= 90) + || (c >= 93 && c <= 255)) + { + /* transfer caps from row 3 to row 2 */ + caps2_10 = caps3_10; + goto st146; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st114: { /* DFA node {78,65,23,1} 114 */ + if (unlikely(i >= len)) { + i++; + goto st114_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 3 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + goto st61; + break; + } + case 39: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + goto st62; + break; + } + case 45: { + /* transfer caps from row 3 to row 2 */ + /* transfer caps from row 3 to row 4 */ + /* capture stores */ + caps2_6 = i - 1; + caps3_10 = i - 1; + goto st63; + break; + } + case 61: { + goto st114; + break; + } + case 91: { + /* transfer caps from row 3 to row 4 */ + /* capture stores */ + goto st115; + break; + } + case 92: { + /* transfer caps from row 3 to row 2 */ + goto st65; + break; + } + case 93: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_8 = i - 1; + goto st66; + break; + } + case 123: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_0 = i - 1; + goto st67; + break; + } + case 125: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_2 = i - 1; + goto st68; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 60) + * || (c >= 62 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 3 to row 2 */ + goto st60; + } /* end state */ + + goto st114_error; + +st115: { /* DFA node {78,65,25,21,1} 115 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 2 to matched */ + matched_0 = caps2_4; + /* capture stores */ + matched_1 = i - 1; + matched_id = 2; + if (c != -1) { + if (c == 34) { + goto st127; + } + if (c == 39) { + goto st128; + } + if (c == 92) { + goto st129; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 38) + || (c >= 40 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st126; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st116: { /* DFA node {76,63,1} 116 */ + if (unlikely(i >= len)) { + i++; + goto st116_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 2 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + goto st61; + break; + } + case 39: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + goto st62; + break; + } + case 45: { + /* transfer caps from row 2 to row 3 */ + /* transfer caps from row 2 to row 4 */ + /* capture stores */ + caps2_6 = i - 1; + caps3_10 = i - 1; + goto st63; + break; + } + case 91: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_4 = i - 1; + goto st64; + break; + } + case 92: { + goto st65; + break; + } + case 93: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_8 = i - 1; + goto st66; + break; + } + case 123: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_0 = i - 1; + goto st67; + break; + } + case 125: { + /* transfer caps from row 2 to row 3 */ + /* capture stores */ + caps2_2 = i - 1; + goto st68; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + goto st60; + } /* end state */ + + goto st116_error; + +st117: { /* DFA node {76,63,59,1} 117 */ + if (unlikely(i >= len)) { + i++; + goto st117_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 3 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + goto st61; + break; + } + case 39: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + goto st62; + break; + } + case 45: { + /* transfer caps from row 3 to row 2 */ + /* transfer caps from row 3 to row 4 */ + /* capture stores */ + caps2_6 = i - 1; + caps3_10 = i - 1; + goto st63; + break; + } + case 91: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_4 = i - 1; + goto st64; + break; + } + case 92: { + /* transfer caps from row 3 to row 2 */ + goto st65; + break; + } + case 93: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_8 = i - 1; + goto st66; + break; + } + case 123: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_0 = i - 1; + goto st67; + break; + } + case 125: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_2 = i - 1; + goto st68; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 3 to row 2 */ + goto st60; + } /* end state */ + + goto st117_error; + +st118: { /* DFA node {76,63,72,1} 118 */ + if (unlikely(i >= len)) { + i++; + goto st118_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 3 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + goto st61; + break; + } + case 39: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + goto st62; + break; + } + case 45: { + /* transfer caps from row 3 to row 2 */ + /* transfer caps from row 3 to row 4 */ + /* capture stores */ + caps2_6 = i - 1; + caps3_10 = i - 1; + goto st63; + break; + } + case 91: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_4 = i - 1; + goto st64; + break; + } + case 92: { + /* transfer caps from row 3 to row 2 */ + goto st65; + break; + } + case 93: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_8 = i - 1; + goto st66; + break; + } + case 123: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_0 = i - 1; + goto st67; + break; + } + case 125: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_2 = i - 1; + goto st68; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 3 to row 2 */ + goto st60; + } /* end state */ + + goto st118_error; + +st119: { /* DFA node {76,63,30,50,1} 119 */ + if (unlikely(i >= len)) { + i++; + goto st119_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 4 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 4 to row 2 */ + /* transfer caps from row 4 to row 3 */ + /* capture stores */ + goto st61; + break; + } + case 39: { + /* transfer caps from row 4 to row 2 */ + /* transfer caps from row 4 to row 3 */ + /* capture stores */ + goto st62; + break; + } + case 45: { + /* transfer caps from row 4 to row 5 */ + /* transfer caps from row 4 to row 6 */ + /* capture stores */ + goto st113; + break; + } + case 91: { + /* transfer caps from row 4 to row 2 */ + /* transfer caps from row 4 to row 3 */ + /* capture stores */ + caps2_4 = i - 1; + goto st64; + break; + } + case 92: { + /* transfer caps from row 4 to row 2 */ + goto st65; + break; + } + case 93: { + /* transfer caps from row 4 to row 2 */ + /* transfer caps from row 4 to row 3 */ + /* capture stores */ + caps2_8 = i - 1; + goto st66; + break; + } + case 123: { + /* transfer caps from row 4 to row 2 */ + /* transfer caps from row 4 to row 3 */ + /* capture stores */ + caps2_0 = i - 1; + goto st67; + break; + } + case 125: { + /* transfer caps from row 4 to row 2 */ + /* transfer caps from row 4 to row 3 */ + /* capture stores */ + caps2_2 = i - 1; + goto st68; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 4 to row 2 */ + goto st60; + } /* end state */ + + goto st119_error; + +st120: { /* DFA node {76,63,21,1} 120 */ + if (unlikely(i >= len)) { + i++; + goto st120_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 3 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + goto st61; + break; + } + case 39: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + goto st62; + break; + } + case 45: { + /* transfer caps from row 3 to row 2 */ + /* transfer caps from row 3 to row 4 */ + /* capture stores */ + caps2_6 = i - 1; + caps3_10 = i - 1; + goto st63; + break; + } + case 61: { + goto st114; + break; + } + case 91: { + /* transfer caps from row 3 to row 4 */ + /* capture stores */ + goto st115; + break; + } + case 92: { + /* transfer caps from row 3 to row 2 */ + goto st65; + break; + } + case 93: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_8 = i - 1; + goto st66; + break; + } + case 123: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_0 = i - 1; + goto st67; + break; + } + case 125: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_2 = i - 1; + goto st68; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 60) + * || (c >= 62 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 3 to row 2 */ + goto st60; + } /* end state */ + + goto st120_error; + +st121: { /* DFA node {76,63,41,1} 121 */ + if (unlikely(i >= len)) { + i++; + goto st121_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 3 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + goto st61; + break; + } + case 39: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + goto st62; + break; + } + case 45: { + /* transfer caps from row 3 to row 2 */ + /* transfer caps from row 3 to row 4 */ + /* capture stores */ + caps2_6 = i - 1; + caps3_10 = i - 1; + goto st63; + break; + } + case 61: { + goto st124; + break; + } + case 91: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_4 = i - 1; + goto st64; + break; + } + case 92: { + /* transfer caps from row 3 to row 2 */ + goto st65; + break; + } + case 93: { + /* transfer caps from row 3 to row 4 */ + /* capture stores */ + goto st125; + break; + } + case 123: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_0 = i - 1; + goto st67; + break; + } + case 125: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_2 = i - 1; + goto st68; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 60) + * || (c >= 62 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 3 to row 2 */ + goto st60; + } /* end state */ + + goto st121_error; + +st122: { /* DFA node {76,63,11,1} 122 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 2 to matched */ + matched_0 = caps2_0; + /* capture stores */ + matched_1 = i - 1; + matched_id = 0; + if (c != -1) { + if (c == 34) { + goto st127; + } + if (c == 39) { + goto st128; + } + if (c == 92) { + goto st129; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 38) + || (c >= 40 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st126; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st123: { /* DFA node {76,63,16,1} 123 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 2 to matched */ + matched_0 = caps2_2; + /* capture stores */ + matched_1 = i - 1; + matched_id = 1; + if (c != -1) { + if (c == 34) { + goto st127; + } + if (c == 39) { + goto st128; + } + if (c == 92) { + goto st129; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 38) + || (c >= 40 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st126; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st124: { /* DFA node {78,65,43,1} 124 */ + if (unlikely(i >= len)) { + i++; + goto st124_error; + } + + c = s[i]; + i++; + switch (c) { + case 10: { + /* transfer caps from row 3 to row 0 */ + goto st1; + break; + } + case 34: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + goto st61; + break; + } + case 39: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + goto st62; + break; + } + case 45: { + /* transfer caps from row 3 to row 2 */ + /* transfer caps from row 3 to row 4 */ + /* capture stores */ + caps2_6 = i - 1; + caps3_10 = i - 1; + goto st63; + break; + } + case 61: { + goto st124; + break; + } + case 91: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_4 = i - 1; + goto st64; + break; + } + case 92: { + /* transfer caps from row 3 to row 2 */ + goto st65; + break; + } + case 93: { + /* transfer caps from row 3 to row 4 */ + /* capture stores */ + goto st125; + break; + } + case 123: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_0 = i - 1; + goto st67; + break; + } + case 125: { + /* transfer caps from row 3 to row 2 */ + /* capture stores */ + caps2_2 = i - 1; + goto st68; + break; + } + default: + break; + } + /* (c >= 0 && c <= 9) + * || (c >= 11 && c <= 33) + * || (c >= 35 && c <= 38) + * || (c >= 40 && c <= 44) + * || (c >= 46 && c <= 60) + * || (c >= 62 && c <= 90) + * || (c >= 94 && c <= 122) + * || (c == 124) + * || (c >= 126 && c <= 255) + */ + /* transfer caps from row 3 to row 2 */ + goto st60; + } /* end state */ + + goto st124_error; + +st125: { /* DFA node {78,65,45,41,1} 125 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 2 to matched */ + matched_0 = caps2_8; + /* capture stores */ + matched_1 = i - 1; + matched_id = 4; + if (c != -1) { + if (c == 34) { + goto st127; + } + if (c == 39) { + goto st128; + } + if (c == 92) { + goto st129; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 38) + || (c >= 40 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st126; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st126: { /* DFA node {78,65} 126 */ + if (unlikely(i >= len)) { + i++; + goto st126_error; + } + + c = s[i]; + i++; + switch (c) { + case 34: { + goto st127; + break; + } + case 39: { + goto st128; + break; + } + case 92: { + goto st129; + break; + } + default: + break; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 38) + || (c >= 40 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st126; + } + } /* end state */ + + goto st126_error; + +st127: { /* DFA node {78,67} 127 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 1 to matched */ + matched_0 = caps1_12; + /* capture stores */ + matched_1 = i - 1; + matched_id = 6; + if (c != -1) { + if (c == 39) { + goto st84; + } + if (c == 92) { + goto st85; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 38) + || (c >= 40 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st83; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st128: { /* DFA node {80,65} 128 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 0 to matched */ + matched_0 = caps0_14; + /* capture stores */ + matched_1 = i - 1; + matched_id = 7; + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st129: { /* DFA node {75,62} 129 */ + if (unlikely(i >= len)) { + i++; + goto st129_error; + } + + c = s[i]; + i++; + if ((c >= 0 && c <= 9) || (c >= 11 && c <= 255)) { + goto st151; + } + } /* end state */ + + goto st129_error; + +st130: { /* DFA node {78,53} 130 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 1 to matched */ + matched_0 = caps1_10; + /* capture stores */ + matched_1 = i - 1; + matched_id = 5; + if (c != -1) { + if (c == 39) { + goto st131; + } + if (c == 92) { + goto st133; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 38) + || (c >= 40 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st130; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st131: { /* DFA node {80,53} 131 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 0 to matched */ + matched_0 = caps0_14; + /* capture stores */ + matched_1 = i - 1; + matched_id = 7; + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st132: { /* DFA node {78,32,53} 132 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 2 to matched */ + matched_0 = caps2_10; + /* capture stores */ + matched_1 = i - 1; + matched_id = 5; + if (c != -1) { + if (c == 39) { + /* transfer caps from row 2 to row 1 */ + caps1_10 = caps2_10; + goto st131; + } + if (c == 61) { + goto st152; + } + if (c == 91) { + goto st153; + } + if (c == 92) { + /* transfer caps from row 2 to row 1 */ + caps1_10 = caps2_10; + goto st133; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 38) + || (c >= 40 && c <= 60) + || (c >= 62 && c <= 90) + || (c >= 93 && c <= 255)) + { + /* transfer caps from row 2 to row 1 */ + caps1_10 = caps2_10; + goto st130; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st133: { /* DFA node {75,53} 133 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 1 to matched */ + matched_0 = caps1_10; + /* capture stores */ + matched_1 = i - 1; + matched_id = 5; + if (c != -1) { + if ((c >= 0 && c <= 9) || (c >= 11 && c <= 255)) { + goto st154; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st134: { /* DFA node {76} 134 */ + if (unlikely(i >= len)) { + i++; + goto st134_error; + } + + c = s[i]; + i++; + switch (c) { + case 39: { + goto st84; + break; + } + case 92: { + goto st85; + break; + } + default: + break; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 38) + || (c >= 40 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st83; + } + } /* end state */ + + goto st134_error; + +st135: { /* DFA node {34,53} 135 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 1 to matched */ + matched_0 = caps1_10; + /* capture stores */ + matched_1 = i - 1; + matched_id = 5; + if (c != -1) { + if (c == 61) { + goto st135; + } + if (c == 91) { + goto st136; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 60) + || (c >= 62 && c <= 90) + || (c >= 92 && c <= 255)) + { + /* transfer caps from row 1 to row 0 */ + caps0_10 = caps1_10; + goto st87; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st136: { /* DFA node {36,53} 136 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 0 to matched */ + matched_0 = caps0_6; + /* capture stores */ + matched_1 = i - 1; + matched_id = 3; + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st137: { /* DFA node {65,78,53} 137 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 2 to matched */ + matched_0 = caps2_10; + /* capture stores */ + matched_1 = i - 1; + matched_id = 5; + if (c != -1) { + if (c == 34) { + goto st138; + } + if (c == 39) { + goto st139; + } + if (c == 92) { + goto st141; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 38) + || (c >= 40 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st137; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st138: { /* DFA node {67,78,53} 138 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 0 to matched */ + matched_0 = caps0_12; + /* capture stores */ + matched_1 = i - 1; + matched_id = 6; + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st139: { /* DFA node {65,80,53} 139 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 1 to matched */ + matched_0 = caps1_14; + /* capture stores */ + matched_1 = i - 1; + matched_id = 7; + if (c != -1) { + if (c == 34) { + goto st58; + } + if (c == 92) { + goto st59; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st57; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st140: { /* DFA node {65,78,32,53} 140 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 3 to matched */ + matched_0 = caps3_10; + /* capture stores */ + matched_1 = i - 1; + matched_id = 5; + if (c != -1) { + if (c == 34) { + /* transfer caps from row 3 to row 2 */ + caps2_10 = caps3_10; + goto st138; + } + if (c == 39) { + /* transfer caps from row 3 to row 2 */ + caps2_10 = caps3_10; + goto st139; + } + if (c == 61) { + goto st156; + } + if (c == 91) { + goto st157; + } + if (c == 92) { + /* transfer caps from row 3 to row 2 */ + caps2_10 = caps3_10; + goto st141; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 38) + || (c >= 40 && c <= 60) + || (c >= 62 && c <= 90) + || (c >= 93 && c <= 255)) + { + /* transfer caps from row 3 to row 2 */ + caps2_10 = caps3_10; + goto st137; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st141: { /* DFA node {62,75,53} 141 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 2 to matched */ + matched_0 = caps2_10; + /* capture stores */ + matched_1 = i - 1; + matched_id = 5; + if (c != -1) { + if ((c >= 0 && c <= 9) || (c >= 11 && c <= 255)) { + goto st158; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st142: { /* DFA node {63,76} 142 */ + if (unlikely(i >= len)) { + i++; + goto st142_error; + } + + c = s[i]; + i++; + switch (c) { + case 34: { + goto st105; + break; + } + case 39: { + goto st106; + break; + } + case 92: { + goto st107; + break; + } + default: + break; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 38) + || (c >= 40 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st104; + } + } /* end state */ + + goto st142_error; + +st143: { /* DFA node {65,34,53} 143 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 2 to matched */ + matched_0 = caps2_10; + /* capture stores */ + matched_1 = i - 1; + matched_id = 5; + if (c != -1) { + if (c == 34) { + /* transfer caps from row 2 to row 1 */ + caps1_10 = caps2_10; + goto st109; + } + if (c == 61) { + goto st143; + } + if (c == 91) { + goto st144; + } + if (c == 92) { + /* transfer caps from row 2 to row 1 */ + caps1_10 = caps2_10; + goto st111; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 60) + || (c >= 62 && c <= 90) + || (c >= 93 && c <= 255)) + { + /* transfer caps from row 2 to row 1 */ + caps1_10 = caps2_10; + goto st108; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st144: { /* DFA node {65,36,53} 144 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 1 to matched */ + matched_0 = caps1_6; + /* capture stores */ + matched_1 = i - 1; + matched_id = 3; + if (c != -1) { + if (c == 34) { + goto st58; + } + if (c == 92) { + goto st59; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st57; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st145: { /* DFA node {63,53} 145 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 1 to matched */ + matched_0 = caps1_10; + /* capture stores */ + matched_1 = i - 1; + matched_id = 5; + if (c != -1) { + if (c == 34) { + goto st109; + } + if (c == 92) { + goto st111; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st108; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st146: { /* DFA node {78,65,53} 146 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 2 to matched */ + matched_0 = caps2_10; + /* capture stores */ + matched_1 = i - 1; + matched_id = 5; + if (c != -1) { + if (c == 34) { + goto st147; + } + if (c == 39) { + goto st148; + } + if (c == 92) { + goto st150; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 38) + || (c >= 40 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st146; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st147: { /* DFA node {78,67,53} 147 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 1 to matched */ + matched_0 = caps1_12; + /* capture stores */ + matched_1 = i - 1; + matched_id = 6; + if (c != -1) { + if (c == 39) { + goto st84; + } + if (c == 92) { + goto st85; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 38) + || (c >= 40 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st83; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st148: { /* DFA node {80,65,53} 148 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 0 to matched */ + matched_0 = caps0_14; + /* capture stores */ + matched_1 = i - 1; + matched_id = 7; + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st149: { /* DFA node {78,65,32,53} 149 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 3 to matched */ + matched_0 = caps3_10; + /* capture stores */ + matched_1 = i - 1; + matched_id = 5; + if (c != -1) { + if (c == 34) { + /* transfer caps from row 3 to row 2 */ + caps2_10 = caps3_10; + goto st147; + } + if (c == 39) { + /* transfer caps from row 3 to row 2 */ + caps2_10 = caps3_10; + goto st148; + } + if (c == 61) { + goto st159; + } + if (c == 91) { + goto st160; + } + if (c == 92) { + /* transfer caps from row 3 to row 2 */ + caps2_10 = caps3_10; + goto st150; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 38) + || (c >= 40 && c <= 60) + || (c >= 62 && c <= 90) + || (c >= 93 && c <= 255)) + { + /* transfer caps from row 3 to row 2 */ + caps2_10 = caps3_10; + goto st146; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st150: { /* DFA node {75,62,53} 150 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 2 to matched */ + matched_0 = caps2_10; + /* capture stores */ + matched_1 = i - 1; + matched_id = 5; + if (c != -1) { + if ((c >= 0 && c <= 9) || (c >= 11 && c <= 255)) { + goto st161; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st151: { /* DFA node {76,63} 151 */ + if (unlikely(i >= len)) { + i++; + goto st151_error; + } + + c = s[i]; + i++; + switch (c) { + case 34: { + goto st127; + break; + } + case 39: { + goto st128; + break; + } + case 92: { + goto st129; + break; + } + default: + break; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 38) + || (c >= 40 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st126; + } + } /* end state */ + + goto st151_error; + +st152: { /* DFA node {78,34,53} 152 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 2 to matched */ + matched_0 = caps2_10; + /* capture stores */ + matched_1 = i - 1; + matched_id = 5; + if (c != -1) { + if (c == 39) { + /* transfer caps from row 2 to row 1 */ + caps1_10 = caps2_10; + goto st131; + } + if (c == 61) { + goto st152; + } + if (c == 91) { + goto st153; + } + if (c == 92) { + /* transfer caps from row 2 to row 1 */ + caps1_10 = caps2_10; + goto st133; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 38) + || (c >= 40 && c <= 60) + || (c >= 62 && c <= 90) + || (c >= 93 && c <= 255)) + { + /* transfer caps from row 2 to row 1 */ + caps1_10 = caps2_10; + goto st130; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st153: { /* DFA node {78,36,53} 153 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 1 to matched */ + matched_0 = caps1_6; + /* capture stores */ + matched_1 = i - 1; + matched_id = 3; + if (c != -1) { + if (c == 39) { + goto st84; + } + if (c == 92) { + goto st85; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 38) + || (c >= 40 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st83; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st154: { /* DFA node {76,53} 154 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 1 to matched */ + matched_0 = caps1_10; + /* capture stores */ + matched_1 = i - 1; + matched_id = 5; + if (c != -1) { + if (c == 39) { + goto st131; + } + if (c == 92) { + goto st133; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 38) + || (c >= 40 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st130; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st156: { /* DFA node {65,78,34,53} 156 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 3 to matched */ + matched_0 = caps3_10; + /* capture stores */ + matched_1 = i - 1; + matched_id = 5; + if (c != -1) { + if (c == 34) { + /* transfer caps from row 3 to row 2 */ + caps2_10 = caps3_10; + goto st138; + } + if (c == 39) { + /* transfer caps from row 3 to row 2 */ + caps2_10 = caps3_10; + goto st139; + } + if (c == 61) { + goto st156; + } + if (c == 91) { + goto st157; + } + if (c == 92) { + /* transfer caps from row 3 to row 2 */ + caps2_10 = caps3_10; + goto st141; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 38) + || (c >= 40 && c <= 60) + || (c >= 62 && c <= 90) + || (c >= 93 && c <= 255)) + { + /* transfer caps from row 3 to row 2 */ + caps2_10 = caps3_10; + goto st137; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st157: { /* DFA node {65,78,36,53} 157 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 2 to matched */ + matched_0 = caps2_6; + /* capture stores */ + matched_1 = i - 1; + matched_id = 3; + if (c != -1) { + if (c == 34) { + goto st105; + } + if (c == 39) { + goto st106; + } + if (c == 92) { + goto st107; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 38) + || (c >= 40 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st104; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st158: { /* DFA node {63,76,53} 158 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 2 to matched */ + matched_0 = caps2_10; + /* capture stores */ + matched_1 = i - 1; + matched_id = 5; + if (c != -1) { + if (c == 34) { + goto st138; + } + if (c == 39) { + goto st139; + } + if (c == 92) { + goto st141; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 38) + || (c >= 40 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st137; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st159: { /* DFA node {78,65,34,53} 159 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 3 to matched */ + matched_0 = caps3_10; + /* capture stores */ + matched_1 = i - 1; + matched_id = 5; + if (c != -1) { + if (c == 34) { + /* transfer caps from row 3 to row 2 */ + caps2_10 = caps3_10; + goto st147; + } + if (c == 39) { + /* transfer caps from row 3 to row 2 */ + caps2_10 = caps3_10; + goto st148; + } + if (c == 61) { + goto st159; + } + if (c == 91) { + goto st160; + } + if (c == 92) { + /* transfer caps from row 3 to row 2 */ + caps2_10 = caps3_10; + goto st150; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 38) + || (c >= 40 && c <= 60) + || (c >= 62 && c <= 90) + || (c >= 93 && c <= 255)) + { + /* transfer caps from row 3 to row 2 */ + caps2_10 = caps3_10; + goto st146; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st160: { /* DFA node {78,65,36,53} 160 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 2 to matched */ + matched_0 = caps2_6; + /* capture stores */ + matched_1 = i - 1; + matched_id = 3; + if (c != -1) { + if (c == 34) { + goto st127; + } + if (c == 39) { + goto st128; + } + if (c == 92) { + goto st129; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 38) + || (c >= 40 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st126; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st161: { /* DFA node {76,63,53} 161 */ + c = i < len ? s[i] : -1; + i++; + /* transfer caps from row 2 to matched */ + matched_0 = caps2_10; + /* capture stores */ + matched_1 = i - 1; + matched_id = 5; + if (c != -1) { + if (c == 34) { + goto st147; + } + if (c == 39) { + goto st148; + } + if (c == 92) { + goto st150; + } + if ((c >= 0 && c <= 9) + || (c >= 11 && c <= 33) + || (c >= 35 && c <= 38) + || (c >= 40 && c <= 91) + || (c >= 93 && c <= 255)) + { + goto st146; + } + } + } /* end state */ + + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + +st0_error: +st1_error: +st2_error: +st3_error: +st4_error: +st5_error: +st6_error: +st9_error: +st11_error: +st12_error: +st13_error: +st14_error: +st15_error: +st18_error: +st19_error: +st21_error: +st22_error: +st23_error: +st24_error: +st28_error: +st30_error: +st35_error: +st38_error: +st39_error: +st40_error: +st41_error: +st45_error: +st47_error: +st48_error: +st49_error: +st50_error: +st51_error: +st52_error: +st55_error: +st57_error: +st59_error: +st60_error: +st63_error: +st64_error: +st65_error: +st66_error: +st71_error: +st73_error: +st74_error: +st75_error: +st76_error: +st77_error: +st78_error: +st81_error: +st83_error: +st85_error: +st92_error: +st94_error: +st95_error: +st96_error: +st97_error: +st98_error: +st99_error: +st102_error: +st104_error: +st107_error: +st112_error: +st114_error: +st116_error: +st117_error: +st118_error: +st119_error: +st120_error: +st121_error: +st124_error: +st126_error: +st129_error: +st134_error: +st142_error: +st151_error: + + if (matched_0 != -1) { + ovec[0] = matched_0; + ovec[1] = matched_1; + return matched_id; /* fallback */ + } + return NO_MATCH; +} diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_lex.h b/debian/modules/nginx-lua/src/ngx_http_lua_lex.h new file mode 100644 index 0000000..11f102c --- /dev/null +++ b/debian/modules/nginx-lua/src/ngx_http_lua_lex.h @@ -0,0 +1,17 @@ + +/* + * Copyright (C) Yichun Zhang (agentzh) + */ + + +#ifndef _NGX_HTTP_LUA_LEX_H_INCLUDED_ +#define _NGX_HTTP_LUA_LEX_H_INCLUDED_ + + +#include "ngx_http_lua_common.h" + + +int ngx_http_lua_lex(const u_char *const s, size_t len, int *const ovec); + + +#endif diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_module.c b/debian/modules/nginx-lua/src/ngx_http_lua_module.c index 6f43b23..3bf50c2 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_module.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_module.c @@ -149,6 +149,13 @@ static ngx_command_t ngx_http_lua_cmds[] = { offsetof(ngx_http_lua_loc_conf_t, log_socket_errors), NULL }, + { ngx_string("init_by_lua_block"), + NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS, + ngx_http_lua_init_by_lua_block, + NGX_HTTP_MAIN_CONF_OFFSET, + 0, + (void *) ngx_http_lua_init_by_inline }, + { ngx_string("init_by_lua"), NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, ngx_http_lua_init_by_lua, @@ -163,6 +170,13 @@ static ngx_command_t ngx_http_lua_cmds[] = { 0, (void *) ngx_http_lua_init_by_file }, + { ngx_string("init_worker_by_lua_block"), + NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS, + ngx_http_lua_init_worker_by_lua_block, + NGX_HTTP_MAIN_CONF_OFFSET, + 0, + (void *) ngx_http_lua_init_worker_by_inline }, + { ngx_string("init_worker_by_lua"), NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, ngx_http_lua_init_worker_by_lua, @@ -178,6 +192,15 @@ static ngx_command_t ngx_http_lua_cmds[] = { (void *) ngx_http_lua_init_worker_by_file }, #if defined(NDK) && NDK + /* set_by_lua $res { inline Lua code } [$arg1 [$arg2 [...]]] */ + { ngx_string("set_by_lua_block"), + NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF + |NGX_CONF_1MORE|NGX_CONF_BLOCK, + ngx_http_lua_set_by_lua_block, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + (void *) ngx_http_lua_filter_set_by_lua_inline }, + /* set_by_lua $res [$arg1 [$arg2 [...]]] */ { ngx_string("set_by_lua"), NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF @@ -197,7 +220,7 @@ static ngx_command_t ngx_http_lua_cmds[] = { (void *) ngx_http_lua_filter_set_by_lua_file }, #endif - /* rewrite_by_lua */ + /* rewrite_by_lua "" */ { ngx_string("rewrite_by_lua"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF |NGX_CONF_TAKE1, @@ -206,7 +229,16 @@ static ngx_command_t ngx_http_lua_cmds[] = { 0, (void *) ngx_http_lua_rewrite_handler_inline }, - /* access_by_lua */ + /* rewrite_by_lua_block { } */ + { ngx_string("rewrite_by_lua_block"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF + |NGX_CONF_BLOCK|NGX_CONF_NOARGS, + ngx_http_lua_rewrite_by_lua_block, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + (void *) ngx_http_lua_rewrite_handler_inline }, + + /* access_by_lua "" */ { ngx_string("access_by_lua"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF |NGX_CONF_TAKE1, @@ -215,7 +247,16 @@ static ngx_command_t ngx_http_lua_cmds[] = { 0, (void *) ngx_http_lua_access_handler_inline }, - /* content_by_lua */ + /* access_by_lua_block { } */ + { ngx_string("access_by_lua_block"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF + |NGX_CONF_BLOCK|NGX_CONF_NOARGS, + ngx_http_lua_access_by_lua_block, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + (void *) ngx_http_lua_access_handler_inline }, + + /* content_by_lua "" */ { ngx_string("content_by_lua"), NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1, ngx_http_lua_content_by_lua, @@ -223,6 +264,14 @@ static ngx_command_t ngx_http_lua_cmds[] = { 0, (void *) ngx_http_lua_content_handler_inline }, + /* content_by_lua_block { } */ + { ngx_string("content_by_lua_block"), + NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS, + ngx_http_lua_content_by_lua_block, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + (void *) ngx_http_lua_content_handler_inline }, + /* log_by_lua */ { ngx_string("log_by_lua"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF @@ -232,6 +281,15 @@ static ngx_command_t ngx_http_lua_cmds[] = { 0, (void *) ngx_http_lua_log_handler_inline }, + /* log_by_lua_block { } */ + { ngx_string("log_by_lua_block"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF + |NGX_CONF_BLOCK|NGX_CONF_NOARGS, + ngx_http_lua_log_by_lua_block, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + (void *) ngx_http_lua_log_handler_inline }, + { ngx_string("rewrite_by_lua_file"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF |NGX_CONF_TAKE1, @@ -280,6 +338,15 @@ static ngx_command_t ngx_http_lua_cmds[] = { 0, (void *) ngx_http_lua_header_filter_inline }, + /* header_filter_by_lua_block { } */ + { ngx_string("header_filter_by_lua_block"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF + |NGX_CONF_BLOCK|NGX_CONF_NOARGS, + ngx_http_lua_header_filter_by_lua_block, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + (void *) ngx_http_lua_header_filter_inline }, + { ngx_string("header_filter_by_lua_file"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF |NGX_CONF_TAKE1, @@ -296,6 +363,15 @@ static ngx_command_t ngx_http_lua_cmds[] = { 0, (void *) ngx_http_lua_body_filter_inline }, + /* body_filter_by_lua_block { } */ + { ngx_string("body_filter_by_lua_block"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF + |NGX_CONF_BLOCK|NGX_CONF_NOARGS, + ngx_http_lua_body_filter_by_lua_block, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + (void *) ngx_http_lua_body_filter_inline }, + { ngx_string("body_filter_by_lua_file"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF |NGX_CONF_TAKE1, @@ -582,7 +658,7 @@ ngx_http_lua_lowat_check(ngx_conf_t *cf, void *post, void *data) if ((u_long) *np >= ngx_freebsd_net_inet_tcp_sendspace) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "\"fastcgi_send_lowat\" must be less than %d " + "\"lua_send_lowat\" must be less than %d " "(sysctl net.inet.tcp.sendspace)", ngx_freebsd_net_inet_tcp_sendspace); @@ -593,7 +669,7 @@ ngx_http_lua_lowat_check(ngx_conf_t *cf, void *post, void *data) ssize_t *np = data; ngx_conf_log_error(NGX_LOG_WARN, cf, 0, - "\"fastcgi_send_lowat\" is not supported, ignored"); + "\"lua_send_lowat\" is not supported, ignored"); *np = 0; diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_shdict.c b/debian/modules/nginx-lua/src/ngx_http_lua_shdict.c index 8c666f7..a72f9da 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_shdict.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_shdict.c @@ -36,11 +36,20 @@ static int ngx_http_lua_shdict_flush_expired(lua_State *L); static int ngx_http_lua_shdict_get_keys(lua_State *L); +static ngx_inline ngx_shm_zone_t *ngx_http_lua_shdict_get_zone(lua_State *L, + int index); + + #define NGX_HTTP_LUA_SHDICT_ADD 0x0001 #define NGX_HTTP_LUA_SHDICT_REPLACE 0x0002 #define NGX_HTTP_LUA_SHDICT_SAFE_STORE 0x0004 +enum { + SHDICT_USERDATA_INDEX = 1, +}; + + ngx_int_t ngx_http_lua_shdict_init_zone(ngx_shm_zone_t *shm_zone, void *data) { @@ -347,7 +356,10 @@ ngx_http_lua_inject_shdict_api(ngx_http_lua_main_conf_t *lmcf, lua_State *L) lua_pushlstring(L, (char *) ctx->name.data, ctx->name.len); /* shared mt key */ + lua_createtable(L, 1 /* narr */, 0 /* nrec */); + /* table of zone[i] */ lua_pushlightuserdata(L, zone[i]); /* shared mt key ud */ + lua_rawseti(L, -2, SHDICT_USERDATA_INDEX); /* {zone[i]} */ lua_pushvalue(L, -3); /* shared mt key ud mt */ lua_setmetatable(L, -2); /* shared mt key ud */ lua_rawset(L, -4); /* shared mt */ @@ -377,6 +389,19 @@ ngx_http_lua_shdict_get_stale(lua_State *L) } +static ngx_inline ngx_shm_zone_t * +ngx_http_lua_shdict_get_zone(lua_State *L, int index) +{ + ngx_shm_zone_t *zone; + + lua_rawgeti(L, index, SHDICT_USERDATA_INDEX); + zone = lua_touserdata(L, -1); + lua_pop(L, 1); + + return zone; +} + + static int ngx_http_lua_shdict_get_helper(lua_State *L, int get_stale) { @@ -401,7 +426,11 @@ ngx_http_lua_shdict_get_helper(lua_State *L, int get_stale) "but only seen %d", n); } - zone = lua_touserdata(L, 1); + if (lua_type(L, 1) != LUA_TTABLE) { + return luaL_error(L, "bad \"zone\" argument"); + } + + zone = ngx_http_lua_shdict_get_zone(L, 1); if (zone == NULL) { return luaL_error(L, "bad \"zone\" argument"); } @@ -572,9 +601,9 @@ ngx_http_lua_shdict_flush_all(lua_State *L) return luaL_error(L, "expecting 1 argument, but seen %d", n); } - luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); + luaL_checktype(L, 1, LUA_TTABLE); - zone = lua_touserdata(L, 1); + zone = ngx_http_lua_shdict_get_zone(L, 1); if (zone == NULL) { return luaL_error(L, "bad user data for the ngx_shm_zone_t pointer"); } @@ -619,9 +648,9 @@ ngx_http_lua_shdict_flush_expired(lua_State *L) return luaL_error(L, "expecting 1 or 2 argument(s), but saw %d", n); } - luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); + luaL_checktype(L, 1, LUA_TTABLE); - zone = lua_touserdata(L, 1); + zone = ngx_http_lua_shdict_get_zone(L, 1); if (zone == NULL) { return luaL_error(L, "bad user data for the ngx_shm_zone_t pointer"); } @@ -700,9 +729,9 @@ ngx_http_lua_shdict_get_keys(lua_State *L) "but saw %d", n); } - luaL_checktype(L, 1, LUA_TLIGHTUSERDATA); + luaL_checktype(L, 1, LUA_TTABLE); - zone = lua_touserdata(L, 1); + zone = ngx_http_lua_shdict_get_zone(L, 1); if (zone == NULL) { return luaL_error(L, "bad user data for the ngx_shm_zone_t pointer"); } @@ -840,7 +869,11 @@ ngx_http_lua_shdict_set_helper(lua_State *L, int flags) "but only seen %d", n); } - zone = lua_touserdata(L, 1); + if (lua_type(L, 1) != LUA_TTABLE) { + return luaL_error(L, "bad \"zone\" argument"); + } + + zone = ngx_http_lua_shdict_get_zone(L, 1); if (zone == NULL) { return luaL_error(L, "bad \"zone\" argument"); } @@ -1013,7 +1046,7 @@ replace: } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ctx->log, 0, - "lua shared dict set: found old entry bug value size " + "lua shared dict set: found old entry but value size " "NOT matched, removing it first"); remove: @@ -1147,11 +1180,11 @@ ngx_http_lua_shdict_incr(lua_State *L) return luaL_error(L, "expecting 3 arguments, but only seen %d", n); } - if (lua_type(L, 1) != LUA_TLIGHTUSERDATA) { + if (lua_type(L, 1) != LUA_TTABLE) { return luaL_error(L, "bad \"zone\" argument"); } - zone = lua_touserdata(L, 1); + zone = ngx_http_lua_shdict_get_zone(L, 1); if (zone == NULL) { return luaL_error(L, "bad user data for the ngx_shm_zone_t pointer"); } @@ -1366,7 +1399,7 @@ ngx_http_lua_find_zone(u_char *name_data, size_t name_len) if (name->len == name_len && ngx_strncmp(name->data, name_data, name_len) == 0) { - return zone; + return &zone[i]; } } @@ -1522,7 +1555,7 @@ replace: } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ctx->log, 0, - "lua shared dict set: found old entry bug value size " + "lua shared dict set: found old entry but value size " "NOT matched, removing it first"); remove: diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_socket_tcp.c b/debian/modules/nginx-lua/src/ngx_http_lua_socket_tcp.c index 804c854..4640f87 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_socket_tcp.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_socket_tcp.c @@ -223,7 +223,7 @@ ngx_http_lua_inject_socket_tcp_api(ngx_log_t *log, lua_State *L) /* {{{req socket object metatable */ lua_pushlightuserdata(L, &ngx_http_lua_req_socket_metatable_key); - lua_createtable(L, 0 /* narr */, 3 /* nrec */); + lua_createtable(L, 0 /* narr */, 4 /* nrec */); lua_pushcfunction(L, ngx_http_lua_socket_tcp_receive); lua_setfield(L, -2, "receive"); @@ -242,7 +242,7 @@ ngx_http_lua_inject_socket_tcp_api(ngx_log_t *log, lua_State *L) /* {{{raw req socket object metatable */ lua_pushlightuserdata(L, &ngx_http_lua_raw_req_socket_metatable_key); - lua_createtable(L, 0 /* narr */, 4 /* nrec */); + lua_createtable(L, 0 /* narr */, 5 /* nrec */); lua_pushcfunction(L, ngx_http_lua_socket_tcp_receive); lua_setfield(L, -2, "receive"); @@ -4084,6 +4084,12 @@ ngx_http_lua_req_socket(lua_State *L) } #endif +#if (NGX_HTTP_V2) + if (r->stream) { + return luaL_error(L, "http v2 not supported yet"); + } +#endif + #if nginx_version >= 1003009 if (!raw && r->headers_in.chunked) { lua_pushnil(L); diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_socket_udp.c b/debian/modules/nginx-lua/src/ngx_http_lua_socket_udp.c index 6c846f5..23cc69a 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_socket_udp.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_socket_udp.c @@ -82,7 +82,7 @@ ngx_http_lua_inject_socket_udp_api(ngx_log_t *log, lua_State *L) /* udp socket object metatable */ lua_pushlightuserdata(L, &ngx_http_lua_socket_udp_metatable_key); - lua_createtable(L, 0 /* narr */, 4 /* nrec */); + lua_createtable(L, 0 /* narr */, 6 /* nrec */); lua_pushcfunction(L, ngx_http_lua_socket_udp_setpeername); lua_setfield(L, -2, "setpeername"); /* ngx socket mt */ diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_subrequest.c b/debian/modules/nginx-lua/src/ngx_http_lua_subrequest.c index 87fc74c..4ac801b 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_subrequest.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_subrequest.c @@ -116,7 +116,7 @@ static int ngx_http_lua_ngx_location_capture_multi(lua_State *L) { ngx_http_request_t *r; - ngx_http_request_t *sr; /* subrequest object */ + ngx_http_request_t *sr = NULL; /* subrequest object */ ngx_http_post_subrequest_t *psr; ngx_http_lua_ctx_t *sr_ctx; ngx_http_lua_ctx_t *ctx; @@ -1004,7 +1004,7 @@ ngx_http_lua_post_subrequest(ngx_http_request_t *r, void *data, ngx_int_t rc) rc = NGX_HTTP_INTERNAL_SERVER_ERROR; } - if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { + if (rc >= 100) { pr_coctx->sr_statuses[ctx->index] = rc; } } @@ -1489,6 +1489,10 @@ ngx_http_lua_subrequest(ngx_http_request_t *r, sr->spdy_stream = r->spdy_stream; #endif +#if (NGX_HTTP_V2) + sr->stream = r->stream; +#endif + #ifdef HAVE_ALLOW_REQUEST_BODY_UPDATING_PATCH sr->content_length_n = -1; #endif diff --git a/debian/modules/nginx-lua/t/000--init.t b/debian/modules/nginx-lua/t/000--init.t index bb57e81..364334f 100644 --- a/debian/modules/nginx-lua/t/000--init.t +++ b/debian/modules/nginx-lua/t/000--init.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; repeat_each(1); diff --git a/debian/modules/nginx-lua/t/000-sanity.t b/debian/modules/nginx-lua/t/000-sanity.t index e390bf6..3f66752 100644 --- a/debian/modules/nginx-lua/t/000-sanity.t +++ b/debian/modules/nginx-lua/t/000-sanity.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; repeat_each(2); diff --git a/debian/modules/nginx-lua/t/001-set.t b/debian/modules/nginx-lua/t/001-set.t index 73bc3a7..2295a2d 100644 --- a/debian/modules/nginx-lua/t/001-set.t +++ b/debian/modules/nginx-lua/t/001-set.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; repeat_each(2); diff --git a/debian/modules/nginx-lua/t/002-content.t b/debian/modules/nginx-lua/t/002-content.t index 706083a..e6cb62d 100644 --- a/debian/modules/nginx-lua/t/002-content.t +++ b/debian/modules/nginx-lua/t/002-content.t @@ -1,5 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; + use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/003-errors.t b/debian/modules/nginx-lua/t/003-errors.t index 1b92266..764300a 100644 --- a/debian/modules/nginx-lua/t/003-errors.t +++ b/debian/modules/nginx-lua/t/003-errors.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; repeat_each(1); diff --git a/debian/modules/nginx-lua/t/004-require.t b/debian/modules/nginx-lua/t/004-require.t index 64b61be..3250b2f 100644 --- a/debian/modules/nginx-lua/t/004-require.t +++ b/debian/modules/nginx-lua/t/004-require.t @@ -1,5 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; + use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/005-exit.t b/debian/modules/nginx-lua/t/005-exit.t index 3ba5c58..781531f 100644 --- a/debian/modules/nginx-lua/t/005-exit.t +++ b/debian/modules/nginx-lua/t/005-exit.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #repeat_each(20000); diff --git a/debian/modules/nginx-lua/t/006-escape.t b/debian/modules/nginx-lua/t/006-escape.t index 5b801da..7b26bba 100644 --- a/debian/modules/nginx-lua/t/006-escape.t +++ b/debian/modules/nginx-lua/t/006-escape.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; repeat_each(2); diff --git a/debian/modules/nginx-lua/t/007-md5.t b/debian/modules/nginx-lua/t/007-md5.t index 6d851e7..501e3af 100644 --- a/debian/modules/nginx-lua/t/007-md5.t +++ b/debian/modules/nginx-lua/t/007-md5.t @@ -1,5 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; + use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/008-today.t b/debian/modules/nginx-lua/t/008-today.t index a8199df..02169c8 100644 --- a/debian/modules/nginx-lua/t/008-today.t +++ b/debian/modules/nginx-lua/t/008-today.t @@ -1,5 +1,5 @@ # vim:set ft=perl ts=4 sw=4 et fdm=marker: -use lib 'lib'; + use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/009-log.t b/debian/modules/nginx-lua/t/009-log.t index 70202ee..e06c799 100644 --- a/debian/modules/nginx-lua/t/009-log.t +++ b/debian/modules/nginx-lua/t/009-log.t @@ -1,5 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; + use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/010-request_body.t b/debian/modules/nginx-lua/t/010-request_body.t index 65f7ccb..d200495 100644 --- a/debian/modules/nginx-lua/t/010-request_body.t +++ b/debian/modules/nginx-lua/t/010-request_body.t @@ -1,5 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; + use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/011-md5_bin.t b/debian/modules/nginx-lua/t/011-md5_bin.t index 50e0762..48b8c61 100644 --- a/debian/modules/nginx-lua/t/011-md5_bin.t +++ b/debian/modules/nginx-lua/t/011-md5_bin.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/012-now.t b/debian/modules/nginx-lua/t/012-now.t index ae14a12..abcb735 100644 --- a/debian/modules/nginx-lua/t/012-now.t +++ b/debian/modules/nginx-lua/t/012-now.t @@ -1,5 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; + use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/013-base64.t b/debian/modules/nginx-lua/t/013-base64.t index 95db9a1..6903218 100644 --- a/debian/modules/nginx-lua/t/013-base64.t +++ b/debian/modules/nginx-lua/t/013-base64.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/014-bugs.t b/debian/modules/nginx-lua/t/014-bugs.t index 6461783..44337e3 100644 --- a/debian/modules/nginx-lua/t/014-bugs.t +++ b/debian/modules/nginx-lua/t/014-bugs.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/015-status.t b/debian/modules/nginx-lua/t/015-status.t index ba14e70..2e026f1 100644 --- a/debian/modules/nginx-lua/t/015-status.t +++ b/debian/modules/nginx-lua/t/015-status.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/016-resp-header.t b/debian/modules/nginx-lua/t/016-resp-header.t index 38765dc..e23b48f 100644 --- a/debian/modules/nginx-lua/t/016-resp-header.t +++ b/debian/modules/nginx-lua/t/016-resp-header.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); @@ -9,7 +8,7 @@ use Test::Nginx::Socket::Lua; repeat_each(2); -plan tests => repeat_each() * (blocks() * 3 + 34); +plan tests => repeat_each() * (blocks() * 3 + 38); #no_diff(); no_long_string(); @@ -1404,3 +1403,46 @@ Location: http://test.com/foo/bar --- no_error_log [error] + + +=== TEST 67: ngx.header["Content-Type"] with ngx_gzip +--- config + gzip on; + gzip_min_length 1; + location = /test2 { + content_by_lua ' + ngx.header["Content-Type"] = "text/html; charset=utf-8" + ngx.say("test") + '; + } +--- request +GET /test2 +--- more_headers +Accept-Encoding: gzip +--- response_headers +Content-Encoding: gzip +Content-Type: text/html; charset=utf-8 +--- response_body_like chomp +[^[:ascii:]]+ +--- no_error_log +[error] + + + +=== TEST 68: ngx.header["Content-Type"] with "; blah" +--- config + location = /test2 { + content_by_lua ' + ngx.header["Content-Type"] = "; blah" + ngx.say("test") + '; + } +--- request +GET /test2 +--- response_headers +!Content-Encoding +Content-Type: ; blah +--- response_body +test +--- no_error_log +[error] diff --git a/debian/modules/nginx-lua/t/017-exec.t b/debian/modules/nginx-lua/t/017-exec.t index 94defa2..4c7a918 100644 --- a/debian/modules/nginx-lua/t/017-exec.t +++ b/debian/modules/nginx-lua/t/017-exec.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; repeat_each(2); diff --git a/debian/modules/nginx-lua/t/018-ndk.t b/debian/modules/nginx-lua/t/018-ndk.t index 677e908..d68306b 100644 --- a/debian/modules/nginx-lua/t/018-ndk.t +++ b/debian/modules/nginx-lua/t/018-ndk.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; repeat_each(2); diff --git a/debian/modules/nginx-lua/t/019-const.t b/debian/modules/nginx-lua/t/019-const.t index 9ac0ce9..fe79bfb 100644 --- a/debian/modules/nginx-lua/t/019-const.t +++ b/debian/modules/nginx-lua/t/019-const.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; repeat_each(2); diff --git a/debian/modules/nginx-lua/t/020-subrequest.t b/debian/modules/nginx-lua/t/020-subrequest.t index e3357be..21e728d 100644 --- a/debian/modules/nginx-lua/t/020-subrequest.t +++ b/debian/modules/nginx-lua/t/020-subrequest.t @@ -1,5 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; + use Test::Nginx::Socket::Lua; #master_on(); @@ -8,6 +8,7 @@ use Test::Nginx::Socket::Lua; #log_level('warn'); #master_process_enabled(1); +no_root_location; repeat_each(2); plan tests => repeat_each() * (blocks() * 3 + 22); @@ -2797,3 +2798,76 @@ image header filter --- no_error_log [error] + + +=== TEST 75: WebDAV + MOVE +--- config + location = /t { + content_by_lua_block { + local file1 = "/file1.txt" + local file2 = "/file2.txt" + ngx.req.set_header( "Destination", file2 ) + local res = ngx.location.capture( + file1, { method = ngx.HTTP_MOVE } + ) + + ngx.say( + "MOVE ", file1, " -> ", file2, + ", response status: ", res.status + ) + } + } + + location / { + dav_methods MOVE; + } + +--- user_files +>>> file1.txt +hello, world! + +--- request +GET /t + +--- response_body +MOVE /file1.txt -> /file2.txt, response status: 204 + +--- no_error_log +[error] +--- error_code: 200 + + + +=== TEST 76: WebDAV + DELETE +--- config + location = /t { + content_by_lua_block { + local file = "/file.txt" + local res = ngx.location.capture( + file, { method = ngx.HTTP_DELETE } + ) + + ngx.say( + "DELETE ", file, + ", response status: ", res.status + ) + } + } + + location / { + dav_methods DELETE; + } + +--- user_files +>>> file.txt +hello, world! + +--- request +GET /t + +--- response_body +DELETE /file.txt, response status: 204 + +--- no_error_log +[error] +--- error_code: 200 diff --git a/debian/modules/nginx-lua/t/021-cookie-time.t b/debian/modules/nginx-lua/t/021-cookie-time.t index fb24d30..c00bbea 100644 --- a/debian/modules/nginx-lua/t/021-cookie-time.t +++ b/debian/modules/nginx-lua/t/021-cookie-time.t @@ -1,5 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; + use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/022-redirect.t b/debian/modules/nginx-lua/t/022-redirect.t index 1f874ec..0e2a107 100644 --- a/debian/modules/nginx-lua/t/022-redirect.t +++ b/debian/modules/nginx-lua/t/022-redirect.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/023-rewrite/client-abort.t b/debian/modules/nginx-lua/t/023-rewrite/client-abort.t index 3b3f242..e970802 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/client-abort.t +++ b/debian/modules/nginx-lua/t/023-rewrite/client-abort.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; use t::StapThread; diff --git a/debian/modules/nginx-lua/t/023-rewrite/exec.t b/debian/modules/nginx-lua/t/023-rewrite/exec.t index 1186c14..a063b5b 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/exec.t +++ b/debian/modules/nginx-lua/t/023-rewrite/exec.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; repeat_each(2); diff --git a/debian/modules/nginx-lua/t/023-rewrite/exit.t b/debian/modules/nginx-lua/t/023-rewrite/exit.t index 280602b..9d292f7 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/exit.t +++ b/debian/modules/nginx-lua/t/023-rewrite/exit.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #repeat_each(20000); diff --git a/debian/modules/nginx-lua/t/023-rewrite/mixed.t b/debian/modules/nginx-lua/t/023-rewrite/mixed.t index 17e38c7..1156567 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/mixed.t +++ b/debian/modules/nginx-lua/t/023-rewrite/mixed.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/023-rewrite/multi-capture.t b/debian/modules/nginx-lua/t/023-rewrite/multi-capture.t index 7f1a923..44629b0 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/multi-capture.t +++ b/debian/modules/nginx-lua/t/023-rewrite/multi-capture.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; repeat_each(10); diff --git a/debian/modules/nginx-lua/t/023-rewrite/on-abort.t b/debian/modules/nginx-lua/t/023-rewrite/on-abort.t index f5a5ef8..aca2ab6 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/on-abort.t +++ b/debian/modules/nginx-lua/t/023-rewrite/on-abort.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; use t::StapThread; diff --git a/debian/modules/nginx-lua/t/023-rewrite/redirect.t b/debian/modules/nginx-lua/t/023-rewrite/redirect.t index e4a46cc..8843f1a 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/redirect.t +++ b/debian/modules/nginx-lua/t/023-rewrite/redirect.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/023-rewrite/req-body.t b/debian/modules/nginx-lua/t/023-rewrite/req-body.t index c085c0f..2f42e0a 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/req-body.t +++ b/debian/modules/nginx-lua/t/023-rewrite/req-body.t @@ -1,5 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; + use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/023-rewrite/req-socket.t b/debian/modules/nginx-lua/t/023-rewrite/req-socket.t index 59dac5d..34aedaa 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/req-socket.t +++ b/debian/modules/nginx-lua/t/023-rewrite/req-socket.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; repeat_each(2); diff --git a/debian/modules/nginx-lua/t/023-rewrite/request_body.t b/debian/modules/nginx-lua/t/023-rewrite/request_body.t index db87e5f..665d6de 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/request_body.t +++ b/debian/modules/nginx-lua/t/023-rewrite/request_body.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/023-rewrite/sanity.t b/debian/modules/nginx-lua/t/023-rewrite/sanity.t index f213f53..20b00e2 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/sanity.t +++ b/debian/modules/nginx-lua/t/023-rewrite/sanity.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/023-rewrite/sleep.t b/debian/modules/nginx-lua/t/023-rewrite/sleep.t index e8d88f0..1719784 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/sleep.t +++ b/debian/modules/nginx-lua/t/023-rewrite/sleep.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/023-rewrite/socket-keepalive.t b/debian/modules/nginx-lua/t/023-rewrite/socket-keepalive.t index 85a9b53..50de0b3 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/socket-keepalive.t +++ b/debian/modules/nginx-lua/t/023-rewrite/socket-keepalive.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; repeat_each(2); diff --git a/debian/modules/nginx-lua/t/023-rewrite/subrequest.t b/debian/modules/nginx-lua/t/023-rewrite/subrequest.t index 12321e6..3c206a8 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/subrequest.t +++ b/debian/modules/nginx-lua/t/023-rewrite/subrequest.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/023-rewrite/tcp-socket-timeout.t b/debian/modules/nginx-lua/t/023-rewrite/tcp-socket-timeout.t index 129f711..79cd0b9 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/tcp-socket-timeout.t +++ b/debian/modules/nginx-lua/t/023-rewrite/tcp-socket-timeout.t @@ -20,7 +20,6 @@ BEGIN { $ENV{MOCKEAGAIN_WRITE_TIMEOUT_PATTERN} = 'get helloworld'; } -use lib 'lib'; use Test::Nginx::Socket::Lua; repeat_each(2); diff --git a/debian/modules/nginx-lua/t/023-rewrite/tcp-socket.t b/debian/modules/nginx-lua/t/023-rewrite/tcp-socket.t index fdac782..9b39ba1 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/tcp-socket.t +++ b/debian/modules/nginx-lua/t/023-rewrite/tcp-socket.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; repeat_each(2); diff --git a/debian/modules/nginx-lua/t/023-rewrite/unix-socket.t b/debian/modules/nginx-lua/t/023-rewrite/unix-socket.t index d19ba8c..098dd67 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/unix-socket.t +++ b/debian/modules/nginx-lua/t/023-rewrite/unix-socket.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; repeat_each(2); diff --git a/debian/modules/nginx-lua/t/023-rewrite/uthread-exec.t b/debian/modules/nginx-lua/t/023-rewrite/uthread-exec.t index d929670..2bea7e7 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/uthread-exec.t +++ b/debian/modules/nginx-lua/t/023-rewrite/uthread-exec.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; use t::StapThread; diff --git a/debian/modules/nginx-lua/t/023-rewrite/uthread-exit.t b/debian/modules/nginx-lua/t/023-rewrite/uthread-exit.t index f17c9c3..266d5ab 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/uthread-exit.t +++ b/debian/modules/nginx-lua/t/023-rewrite/uthread-exit.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; use t::StapThread; diff --git a/debian/modules/nginx-lua/t/023-rewrite/uthread-redirect.t b/debian/modules/nginx-lua/t/023-rewrite/uthread-redirect.t index 6d4f0a1..0f125e0 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/uthread-redirect.t +++ b/debian/modules/nginx-lua/t/023-rewrite/uthread-redirect.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; use t::StapThread; diff --git a/debian/modules/nginx-lua/t/023-rewrite/uthread-spawn.t b/debian/modules/nginx-lua/t/023-rewrite/uthread-spawn.t index b65e748..58af7d0 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/uthread-spawn.t +++ b/debian/modules/nginx-lua/t/023-rewrite/uthread-spawn.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; use t::StapThread; diff --git a/debian/modules/nginx-lua/t/024-access/auth.t b/debian/modules/nginx-lua/t/024-access/auth.t index 4b7927c..5da09cb 100644 --- a/debian/modules/nginx-lua/t/024-access/auth.t +++ b/debian/modules/nginx-lua/t/024-access/auth.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/024-access/client-abort.t b/debian/modules/nginx-lua/t/024-access/client-abort.t index 528838e..a94f822 100644 --- a/debian/modules/nginx-lua/t/024-access/client-abort.t +++ b/debian/modules/nginx-lua/t/024-access/client-abort.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; use t::StapThread; diff --git a/debian/modules/nginx-lua/t/024-access/exec.t b/debian/modules/nginx-lua/t/024-access/exec.t index f6e3e76..8bf638f 100644 --- a/debian/modules/nginx-lua/t/024-access/exec.t +++ b/debian/modules/nginx-lua/t/024-access/exec.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; repeat_each(2); diff --git a/debian/modules/nginx-lua/t/024-access/exit.t b/debian/modules/nginx-lua/t/024-access/exit.t index 39d39ea..8470ab9 100644 --- a/debian/modules/nginx-lua/t/024-access/exit.t +++ b/debian/modules/nginx-lua/t/024-access/exit.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #repeat_each(20000); diff --git a/debian/modules/nginx-lua/t/024-access/mixed.t b/debian/modules/nginx-lua/t/024-access/mixed.t index 1644c6c..d801216 100644 --- a/debian/modules/nginx-lua/t/024-access/mixed.t +++ b/debian/modules/nginx-lua/t/024-access/mixed.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/024-access/multi-capture.t b/debian/modules/nginx-lua/t/024-access/multi-capture.t index caa6755..368d401 100644 --- a/debian/modules/nginx-lua/t/024-access/multi-capture.t +++ b/debian/modules/nginx-lua/t/024-access/multi-capture.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; repeat_each(10); diff --git a/debian/modules/nginx-lua/t/024-access/on-abort.t b/debian/modules/nginx-lua/t/024-access/on-abort.t index 638c644..0c17b55 100644 --- a/debian/modules/nginx-lua/t/024-access/on-abort.t +++ b/debian/modules/nginx-lua/t/024-access/on-abort.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; use t::StapThread; diff --git a/debian/modules/nginx-lua/t/024-access/redirect.t b/debian/modules/nginx-lua/t/024-access/redirect.t index b8c3519..c7ce512 100644 --- a/debian/modules/nginx-lua/t/024-access/redirect.t +++ b/debian/modules/nginx-lua/t/024-access/redirect.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/024-access/req-body.t b/debian/modules/nginx-lua/t/024-access/req-body.t index 4d8eb78..fd33aff 100644 --- a/debian/modules/nginx-lua/t/024-access/req-body.t +++ b/debian/modules/nginx-lua/t/024-access/req-body.t @@ -1,5 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; + use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/024-access/request_body.t b/debian/modules/nginx-lua/t/024-access/request_body.t index 0e83801..e4ac161 100644 --- a/debian/modules/nginx-lua/t/024-access/request_body.t +++ b/debian/modules/nginx-lua/t/024-access/request_body.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/024-access/sanity.t b/debian/modules/nginx-lua/t/024-access/sanity.t index f5b9f70..de63a68 100644 --- a/debian/modules/nginx-lua/t/024-access/sanity.t +++ b/debian/modules/nginx-lua/t/024-access/sanity.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/024-access/satisfy.t b/debian/modules/nginx-lua/t/024-access/satisfy.t index 55724a6..10d3ece 100644 --- a/debian/modules/nginx-lua/t/024-access/satisfy.t +++ b/debian/modules/nginx-lua/t/024-access/satisfy.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/024-access/sleep.t b/debian/modules/nginx-lua/t/024-access/sleep.t index cbf2362..2eb0822 100644 --- a/debian/modules/nginx-lua/t/024-access/sleep.t +++ b/debian/modules/nginx-lua/t/024-access/sleep.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/024-access/subrequest.t b/debian/modules/nginx-lua/t/024-access/subrequest.t index 0347d51..00c56b8 100644 --- a/debian/modules/nginx-lua/t/024-access/subrequest.t +++ b/debian/modules/nginx-lua/t/024-access/subrequest.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/024-access/uthread-exec.t b/debian/modules/nginx-lua/t/024-access/uthread-exec.t index b8d01e0..d7c2321 100644 --- a/debian/modules/nginx-lua/t/024-access/uthread-exec.t +++ b/debian/modules/nginx-lua/t/024-access/uthread-exec.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; use t::StapThread; diff --git a/debian/modules/nginx-lua/t/024-access/uthread-exit.t b/debian/modules/nginx-lua/t/024-access/uthread-exit.t index a843d3b..c08fefc 100644 --- a/debian/modules/nginx-lua/t/024-access/uthread-exit.t +++ b/debian/modules/nginx-lua/t/024-access/uthread-exit.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; use t::StapThread; diff --git a/debian/modules/nginx-lua/t/024-access/uthread-redirect.t b/debian/modules/nginx-lua/t/024-access/uthread-redirect.t index 620fcc0..8b030ac 100644 --- a/debian/modules/nginx-lua/t/024-access/uthread-redirect.t +++ b/debian/modules/nginx-lua/t/024-access/uthread-redirect.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; use t::StapThread; diff --git a/debian/modules/nginx-lua/t/024-access/uthread-spawn.t b/debian/modules/nginx-lua/t/024-access/uthread-spawn.t index 4f52019..415e4c0 100644 --- a/debian/modules/nginx-lua/t/024-access/uthread-spawn.t +++ b/debian/modules/nginx-lua/t/024-access/uthread-spawn.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; use t::StapThread; diff --git a/debian/modules/nginx-lua/t/025-codecache.t b/debian/modules/nginx-lua/t/025-codecache.t index f708286..f33452a 100644 --- a/debian/modules/nginx-lua/t/025-codecache.t +++ b/debian/modules/nginx-lua/t/025-codecache.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; repeat_each(2); diff --git a/debian/modules/nginx-lua/t/026-mysql.t b/debian/modules/nginx-lua/t/026-mysql.t index 72622c9..e14ffb6 100644 --- a/debian/modules/nginx-lua/t/026-mysql.t +++ b/debian/modules/nginx-lua/t/026-mysql.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; repeat_each(2); diff --git a/debian/modules/nginx-lua/t/027-multi-capture.t b/debian/modules/nginx-lua/t/027-multi-capture.t index 06873c1..3588c69 100644 --- a/debian/modules/nginx-lua/t/027-multi-capture.t +++ b/debian/modules/nginx-lua/t/027-multi-capture.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; repeat_each(10); diff --git a/debian/modules/nginx-lua/t/028-req-header.t b/debian/modules/nginx-lua/t/028-req-header.t index 1d18c39..77c0b06 100644 --- a/debian/modules/nginx-lua/t/028-req-header.t +++ b/debian/modules/nginx-lua/t/028-req-header.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); @@ -9,7 +8,7 @@ use Test::Nginx::Socket::Lua; repeat_each(2); -plan tests => repeat_each() * (2 * blocks() + 21); +plan tests => repeat_each() * (2 * blocks() + 26); #no_diff(); #no_long_string(); @@ -1440,3 +1439,96 @@ AAA: 678 --- no_error_log [error] + + +=== TEST 46: clear If-Match req header +--- config + location /t { + content_by_lua ' + ngx.req.clear_header("if-match") + if not ngx.send_headers() then + return + end + ngx.say("test") + '; + } +--- request +GET /t +--- more_headers +If-Match: abc +--- response_body +test +--- no_error_log +[error] + + + +=== TEST 47: clear If-Unmodified-Since req header +--- config + location /t { + content_by_lua ' + ngx.req.clear_header("if-unmodified-since") + ngx.header["Last-Modified"] = "Tue, 30 Jun 2011 12:16:36 GMT" + if not ngx.send_headers() then + return + end + ngx.say("test") + '; + } +--- request +GET /t +--- more_headers +If-Unmodified-Since: Tue, 28 Jun 2011 12:16:36 GMT +--- response_body +test +--- no_error_log +[error] + + + +=== TEST 48: clear If-None-Match req header +--- config + location /t { + content_by_lua ' + ngx.req.clear_header("if-none-match") + -- ngx.header["etags"] = "abc" + if not ngx.send_headers() then + return + end + ngx.say("test") + '; + } +--- request +GET /t +--- more_headers +If-None-Match: * +--- response_body +test +--- no_error_log +[error] + + + +=== TEST 49: set the Destination request header for WebDav +--- config + location = /a.txt { + rewrite_by_lua_block { + ngx.req.set_header("Destination", "/b.txt") + } + dav_methods MOVE; + dav_access all:rw; + root html; + } + +--- user_files +>>> a.txt +hello, world! + +--- request +MOVE /a.txt + +--- response_body +--- no_error_log +client sent no "Destination" header +[error] +--- error_code: 204 diff --git a/debian/modules/nginx-lua/t/029-http-time.t b/debian/modules/nginx-lua/t/029-http-time.t index 8ac1725..71a7758 100644 --- a/debian/modules/nginx-lua/t/029-http-time.t +++ b/debian/modules/nginx-lua/t/029-http-time.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/030-uri-args.t b/debian/modules/nginx-lua/t/030-uri-args.t index 83b3842..2f18ba7 100644 --- a/debian/modules/nginx-lua/t/030-uri-args.t +++ b/debian/modules/nginx-lua/t/030-uri-args.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/031-post-args.t b/debian/modules/nginx-lua/t/031-post-args.t index 209af69..29d6057 100644 --- a/debian/modules/nginx-lua/t/031-post-args.t +++ b/debian/modules/nginx-lua/t/031-post-args.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/032-iolist.t b/debian/modules/nginx-lua/t/032-iolist.t index 12c9635..ddf3d7f 100644 --- a/debian/modules/nginx-lua/t/032-iolist.t +++ b/debian/modules/nginx-lua/t/032-iolist.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/033-ctx.t b/debian/modules/nginx-lua/t/033-ctx.t index 8301bac..eefb216 100644 --- a/debian/modules/nginx-lua/t/033-ctx.t +++ b/debian/modules/nginx-lua/t/033-ctx.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/035-gmatch.t b/debian/modules/nginx-lua/t/035-gmatch.t index b6e3110..04a06ed 100644 --- a/debian/modules/nginx-lua/t/035-gmatch.t +++ b/debian/modules/nginx-lua/t/035-gmatch.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/036-sub.t b/debian/modules/nginx-lua/t/036-sub.t index ad8638c..88dc8d6 100644 --- a/debian/modules/nginx-lua/t/036-sub.t +++ b/debian/modules/nginx-lua/t/036-sub.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/037-gsub.t b/debian/modules/nginx-lua/t/037-gsub.t index fb4a706..b3bb04e 100644 --- a/debian/modules/nginx-lua/t/037-gsub.t +++ b/debian/modules/nginx-lua/t/037-gsub.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/038-match-o.t b/debian/modules/nginx-lua/t/038-match-o.t index 7da2c72..4ccd73a 100644 --- a/debian/modules/nginx-lua/t/038-match-o.t +++ b/debian/modules/nginx-lua/t/038-match-o.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/039-sub-o.t b/debian/modules/nginx-lua/t/039-sub-o.t index 05fc0ba..a861b6c 100644 --- a/debian/modules/nginx-lua/t/039-sub-o.t +++ b/debian/modules/nginx-lua/t/039-sub-o.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/040-gsub-o.t b/debian/modules/nginx-lua/t/040-gsub-o.t index a371526..90619b0 100644 --- a/debian/modules/nginx-lua/t/040-gsub-o.t +++ b/debian/modules/nginx-lua/t/040-gsub-o.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/041-header-filter.t b/debian/modules/nginx-lua/t/041-header-filter.t index c3d495c..553ee43 100644 --- a/debian/modules/nginx-lua/t/041-header-filter.t +++ b/debian/modules/nginx-lua/t/041-header-filter.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/042-crc32.t b/debian/modules/nginx-lua/t/042-crc32.t index 1725435..86d9201 100644 --- a/debian/modules/nginx-lua/t/042-crc32.t +++ b/debian/modules/nginx-lua/t/042-crc32.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/043-shdict.t b/debian/modules/nginx-lua/t/043-shdict.t index 22ab0d8..4c4d121 100644 --- a/debian/modules/nginx-lua/t/043-shdict.t +++ b/debian/modules/nginx-lua/t/043-shdict.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); @@ -8,7 +7,7 @@ use Test::Nginx::Socket::Lua; #repeat_each(2); -plan tests => repeat_each() * (blocks() * 3 + 17); +plan tests => repeat_each() * (blocks() * 3 + 18); #no_diff(); no_long_string(); @@ -2298,3 +2297,135 @@ foo = nil --- no_error_log [error] + + +=== TEST 86: the lightuserdata ngx.null has no methods of shared dicts. +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua ' + local lightuserdata = ngx.null + lightuserdata:set("foo", 1) + '; + } +--- request +GET /test +--- response_body_like: 500 Internal Server Error +--- error_code: 500 +--- grep_error_log chop +attempt to index local 'lightuserdata' (a userdata value) +--- grep_error_log_out +attempt to index local 'lightuserdata' (a userdata value) +--- error_log +[error] +--- no_error_log +bad "zone" argument + + + +=== TEST 87: set bad zone table +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua ' + local dogs = ngx.shared.dogs + dogs.set({1}, "foo", 1) + '; + } +--- request +GET /test +--- response_body_like: 500 Internal Server Error +--- error_code: 500 +--- error_log +bad "zone" argument + + + +=== TEST 88: get bad zone table +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua ' + local dogs = ngx.shared.dogs + dogs.get({1}, "foo") + '; + } +--- request +GET /test +--- response_body_like: 500 Internal Server Error +--- error_code: 500 +--- error_log +bad "zone" argument + + + +=== TEST 89: incr bad zone table +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua ' + local dogs = ngx.shared.dogs + dogs.incr({1}, "foo", 32) + '; + } +--- request +GET /test +--- response_body_like: 500 Internal Server Error +--- error_code: 500 +--- error_log + + + +=== TEST 90: check the type of the shdict object +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua ' + ngx.say("type: ", type(ngx.shared.dogs)) + '; + } +--- request +GET /test +--- response_body +type: table +--- no_error_log +[error] + + + +=== TEST 91: dogs, cat mixing +--- http_config + lua_shared_dict dogs 1m; + lua_shared_dict cats 1m; +--- config + location = /test { + content_by_lua ' + local dogs = ngx.shared.dogs + dogs:set("foo", 32) + dogs:set("bah", 10502) + local val = dogs:get("foo") + ngx.say(val, " ", type(val)) + val = dogs:get("bah") + ngx.say(val, " ", type(val)) + + local cats = ngx.shared.cats + val = cats:get("foo") + ngx.say(val or "nil") + val = cats:get("bah") + ngx.say(val or "nil") + '; + } +--- request +GET /test +--- response_body +32 number +10502 number +nil +nil +--- no_error_log +[error] diff --git a/debian/modules/nginx-lua/t/044-req-body.t b/debian/modules/nginx-lua/t/044-req-body.t index 0246265..f0d0a4d 100644 --- a/debian/modules/nginx-lua/t/044-req-body.t +++ b/debian/modules/nginx-lua/t/044-req-body.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/045-ngx-var.t b/debian/modules/nginx-lua/t/045-ngx-var.t index a909040..8f2dcb3 100644 --- a/debian/modules/nginx-lua/t/045-ngx-var.t +++ b/debian/modules/nginx-lua/t/045-ngx-var.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/046-hmac.t b/debian/modules/nginx-lua/t/046-hmac.t index d8280e4..686b479 100644 --- a/debian/modules/nginx-lua/t/046-hmac.t +++ b/debian/modules/nginx-lua/t/046-hmac.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/047-match-jit.t b/debian/modules/nginx-lua/t/047-match-jit.t index ef5970b..077ebb6 100644 --- a/debian/modules/nginx-lua/t/047-match-jit.t +++ b/debian/modules/nginx-lua/t/047-match-jit.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/048-match-dfa.t b/debian/modules/nginx-lua/t/048-match-dfa.t index 6860532..8350a73 100644 --- a/debian/modules/nginx-lua/t/048-match-dfa.t +++ b/debian/modules/nginx-lua/t/048-match-dfa.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/049-gmatch-jit.t b/debian/modules/nginx-lua/t/049-gmatch-jit.t index 51e268a..614c440 100644 --- a/debian/modules/nginx-lua/t/049-gmatch-jit.t +++ b/debian/modules/nginx-lua/t/049-gmatch-jit.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/050-gmatch-dfa.t b/debian/modules/nginx-lua/t/050-gmatch-dfa.t index 15295ba..c6b87e1 100644 --- a/debian/modules/nginx-lua/t/050-gmatch-dfa.t +++ b/debian/modules/nginx-lua/t/050-gmatch-dfa.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/051-sub-jit.t b/debian/modules/nginx-lua/t/051-sub-jit.t index 038fa83..789e897 100644 --- a/debian/modules/nginx-lua/t/051-sub-jit.t +++ b/debian/modules/nginx-lua/t/051-sub-jit.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/052-sub-dfa.t b/debian/modules/nginx-lua/t/052-sub-dfa.t index 93c29b6..f4de4d2 100644 --- a/debian/modules/nginx-lua/t/052-sub-dfa.t +++ b/debian/modules/nginx-lua/t/052-sub-dfa.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/053-gsub-jit.t b/debian/modules/nginx-lua/t/053-gsub-jit.t index e2c2e22..3a2a1aa 100644 --- a/debian/modules/nginx-lua/t/053-gsub-jit.t +++ b/debian/modules/nginx-lua/t/053-gsub-jit.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/054-gsub-dfa.t b/debian/modules/nginx-lua/t/054-gsub-dfa.t index 912fe3a..9c471a9 100644 --- a/debian/modules/nginx-lua/t/054-gsub-dfa.t +++ b/debian/modules/nginx-lua/t/054-gsub-dfa.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/055-subreq-vars.t b/debian/modules/nginx-lua/t/055-subreq-vars.t index e2b0658..2fc6960 100644 --- a/debian/modules/nginx-lua/t/055-subreq-vars.t +++ b/debian/modules/nginx-lua/t/055-subreq-vars.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/056-flush.t b/debian/modules/nginx-lua/t/056-flush.t index 8b8ee0d..260e39a 100644 --- a/debian/modules/nginx-lua/t/056-flush.t +++ b/debian/modules/nginx-lua/t/056-flush.t @@ -4,7 +4,6 @@ BEGIN { $ENV{TEST_NGINX_POSTPONE_OUTPUT} = 1; } -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/057-flush-timeout.t b/debian/modules/nginx-lua/t/057-flush-timeout.t index 7420e8e..d6e0f86 100644 --- a/debian/modules/nginx-lua/t/057-flush-timeout.t +++ b/debian/modules/nginx-lua/t/057-flush-timeout.t @@ -21,7 +21,6 @@ BEGIN { $ENV{TEST_NGINX_POSTPONE_OUTPUT} = 1; } -use lib 'lib'; use Test::Nginx::Socket::Lua; use t::StapThread; diff --git a/debian/modules/nginx-lua/t/058-tcp-socket.t b/debian/modules/nginx-lua/t/058-tcp-socket.t index a4e6a56..145a07b 100644 --- a/debian/modules/nginx-lua/t/058-tcp-socket.t +++ b/debian/modules/nginx-lua/t/058-tcp-socket.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; repeat_each(2); diff --git a/debian/modules/nginx-lua/t/059-unix-socket.t b/debian/modules/nginx-lua/t/059-unix-socket.t index 3c5f93e..9e9e6df 100644 --- a/debian/modules/nginx-lua/t/059-unix-socket.t +++ b/debian/modules/nginx-lua/t/059-unix-socket.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; repeat_each(2); diff --git a/debian/modules/nginx-lua/t/060-lua-memcached.t b/debian/modules/nginx-lua/t/060-lua-memcached.t index d7fc68f..e1ebb92 100644 --- a/debian/modules/nginx-lua/t/060-lua-memcached.t +++ b/debian/modules/nginx-lua/t/060-lua-memcached.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; repeat_each(2); diff --git a/debian/modules/nginx-lua/t/061-lua-redis.t b/debian/modules/nginx-lua/t/061-lua-redis.t index abde988..d7b1876 100644 --- a/debian/modules/nginx-lua/t/061-lua-redis.t +++ b/debian/modules/nginx-lua/t/061-lua-redis.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; repeat_each(2); diff --git a/debian/modules/nginx-lua/t/062-count.t b/debian/modules/nginx-lua/t/062-count.t index 38c4faf..120d131 100644 --- a/debian/modules/nginx-lua/t/062-count.t +++ b/debian/modules/nginx-lua/t/062-count.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); @@ -240,20 +239,25 @@ n = 10 -=== TEST 11: entries under ngx._reqsock_meta ---- SKIP +=== TEST 11: entries under the metatable of req sockets --- config location = /test { content_by_lua ' local n = 0 - for k, v in pairs(ngx._reqsock_meta) do + local sock, err = ngx.req.socket() + if not sock then + ngx.say("failed to get the request socket: ", err) + end + + for k, v in pairs(getmetatable(sock)) do n = n + 1 end ngx.say("n = ", n) '; } --- request -GET /test +POST /test +hello world --- response_body n = 4 --- no_error_log @@ -438,3 +442,55 @@ worker: 2 --- no_error_log [error] + + +=== TEST 20: entries under the metatable of udp sockets +--- config + location = /test { + content_by_lua ' + local n = 0 + local sock = ngx.socket.udp() + for k, v in pairs(getmetatable(sock)) do + n = n + 1 + end + ngx.say("n = ", n) + '; + } +--- request +GET /test +--- response_body +n = 6 +--- no_error_log +[error] + + + +=== TEST 21: entries under the metatable of req raw sockets +--- config + location = /test { + content_by_lua ' + local n = 0 + ngx.req.read_body() + local sock, err = ngx.req.socket(true) + if not sock then + ngx.log(ngx.ERR, "server: failed to get raw req socket: ", err) + return + end + + for k, v in pairs(getmetatable(sock)) do + n = n + 1 + end + + local ok, err = sock:send("HTTP/1.1 200 OK\\r\\nContent-Length: 6\\r\\n\\r\\nn = "..n.."\\n") + if not ok then + ngx.log(ngx.ERR, "failed to send: ", err) + return + end + '; + } +--- request +GET /test +--- response_body +n = 5 +--- no_error_log +[error] diff --git a/debian/modules/nginx-lua/t/063-abort.t b/debian/modules/nginx-lua/t/063-abort.t index 2019639..c112ee1 100644 --- a/debian/modules/nginx-lua/t/063-abort.t +++ b/debian/modules/nginx-lua/t/063-abort.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/064-pcall.t b/debian/modules/nginx-lua/t/064-pcall.t index cfa344d..cf90a07 100644 --- a/debian/modules/nginx-lua/t/064-pcall.t +++ b/debian/modules/nginx-lua/t/064-pcall.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/065-tcp-socket-timeout.t b/debian/modules/nginx-lua/t/065-tcp-socket-timeout.t index b330019..ec79891 100644 --- a/debian/modules/nginx-lua/t/065-tcp-socket-timeout.t +++ b/debian/modules/nginx-lua/t/065-tcp-socket-timeout.t @@ -20,7 +20,6 @@ BEGIN { $ENV{MOCKEAGAIN_WRITE_TIMEOUT_PATTERN} = 'get helloworld'; } -use lib 'lib'; use Test::Nginx::Socket::Lua; use t::StapThread; diff --git a/debian/modules/nginx-lua/t/066-socket-receiveuntil.t b/debian/modules/nginx-lua/t/066-socket-receiveuntil.t index 23fe8a0..3bf5229 100644 --- a/debian/modules/nginx-lua/t/066-socket-receiveuntil.t +++ b/debian/modules/nginx-lua/t/066-socket-receiveuntil.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; repeat_each(2); diff --git a/debian/modules/nginx-lua/t/067-req-socket.t b/debian/modules/nginx-lua/t/067-req-socket.t index 7797521..30a653a 100644 --- a/debian/modules/nginx-lua/t/067-req-socket.t +++ b/debian/modules/nginx-lua/t/067-req-socket.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; repeat_each(2); diff --git a/debian/modules/nginx-lua/t/068-socket-keepalive.t b/debian/modules/nginx-lua/t/068-socket-keepalive.t index 21f9631..a005620 100644 --- a/debian/modules/nginx-lua/t/068-socket-keepalive.t +++ b/debian/modules/nginx-lua/t/068-socket-keepalive.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #repeat_each(2); diff --git a/debian/modules/nginx-lua/t/069-null.t b/debian/modules/nginx-lua/t/069-null.t index 6133545..7761c91 100644 --- a/debian/modules/nginx-lua/t/069-null.t +++ b/debian/modules/nginx-lua/t/069-null.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; repeat_each(2); diff --git a/debian/modules/nginx-lua/t/070-sha1.t b/debian/modules/nginx-lua/t/070-sha1.t index e6fe687..8648a8c 100644 --- a/debian/modules/nginx-lua/t/070-sha1.t +++ b/debian/modules/nginx-lua/t/070-sha1.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/071-idle-socket.t b/debian/modules/nginx-lua/t/071-idle-socket.t index 049e291..55d25c6 100644 --- a/debian/modules/nginx-lua/t/071-idle-socket.t +++ b/debian/modules/nginx-lua/t/071-idle-socket.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; repeat_each(2); diff --git a/debian/modules/nginx-lua/t/072-conditional-get.t b/debian/modules/nginx-lua/t/072-conditional-get.t index 10a5370..4bb567a 100644 --- a/debian/modules/nginx-lua/t/072-conditional-get.t +++ b/debian/modules/nginx-lua/t/072-conditional-get.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; use t::StapThread; diff --git a/debian/modules/nginx-lua/t/073-backtrace.t b/debian/modules/nginx-lua/t/073-backtrace.t index 914fa15..aae4bae 100644 --- a/debian/modules/nginx-lua/t/073-backtrace.t +++ b/debian/modules/nginx-lua/t/073-backtrace.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/074-prefix-var.t b/debian/modules/nginx-lua/t/074-prefix-var.t index c95517f..3cc4587 100644 --- a/debian/modules/nginx-lua/t/074-prefix-var.t +++ b/debian/modules/nginx-lua/t/074-prefix-var.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/075-logby.t b/debian/modules/nginx-lua/t/075-logby.t index 5dadb9f..f987c8e 100644 --- a/debian/modules/nginx-lua/t/075-logby.t +++ b/debian/modules/nginx-lua/t/075-logby.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/076-no-postpone.t b/debian/modules/nginx-lua/t/076-no-postpone.t index 655650e..d19bb77 100644 --- a/debian/modules/nginx-lua/t/076-no-postpone.t +++ b/debian/modules/nginx-lua/t/076-no-postpone.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/077-sleep.t b/debian/modules/nginx-lua/t/077-sleep.t index c4d7c0c..a7c251a 100644 --- a/debian/modules/nginx-lua/t/077-sleep.t +++ b/debian/modules/nginx-lua/t/077-sleep.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/078-hup-vars.t b/debian/modules/nginx-lua/t/078-hup-vars.t index d6667c7..8acc346 100644 --- a/debian/modules/nginx-lua/t/078-hup-vars.t +++ b/debian/modules/nginx-lua/t/078-hup-vars.t @@ -12,7 +12,6 @@ BEGIN { } } -use lib 'lib'; use Test::Nginx::Socket::Lua $SkipReason ? (skip_all => $SkipReason) : (); #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/079-unused-directives.t b/debian/modules/nginx-lua/t/079-unused-directives.t index c06d228..cba0e41 100644 --- a/debian/modules/nginx-lua/t/079-unused-directives.t +++ b/debian/modules/nginx-lua/t/079-unused-directives.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); @@ -10,7 +9,7 @@ log_level('debug'); repeat_each(2); -plan tests => repeat_each() * 120; +plan tests => repeat_each() * 110; #no_diff(); #no_long_string(); @@ -264,6 +263,9 @@ lua log handler, uri:"/t" === TEST 11: header_filter_by_lua with multiple http blocks (github issue #294) +This test case won't run with nginx 1.9.3+ since duplicate http {} blocks +have been prohibited since then. +--- SKIP --- config location = /t { echo ok; @@ -289,6 +291,9 @@ ok === TEST 12: body_filter_by_lua in multiple http blocks (github issue #294) +This test case won't run with nginx 1.9.3+ since duplicate http {} blocks +have been prohibited since then. +--- SKIP --- config location = /t { echo -n ok; @@ -312,6 +317,9 @@ okay === TEST 13: capture filter with multiple http blocks (github issue #294) +This test case won't run with nginx 1.9.3+ since duplicate http {} blocks +have been prohibited since then. +--- SKIP --- config location = /t { content_by_lua ' diff --git a/debian/modules/nginx-lua/t/080-hup-shdict.t b/debian/modules/nginx-lua/t/080-hup-shdict.t index ac3ee00..f9a0278 100644 --- a/debian/modules/nginx-lua/t/080-hup-shdict.t +++ b/debian/modules/nginx-lua/t/080-hup-shdict.t @@ -12,7 +12,6 @@ BEGIN { } } -use lib 'lib'; use Test::Nginx::Socket::Lua $SkipReason ? (skip_all => $SkipReason) : (); #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/081-bytecode.t b/debian/modules/nginx-lua/t/081-bytecode.t index 6612235..93139e2 100644 --- a/debian/modules/nginx-lua/t/081-bytecode.t +++ b/debian/modules/nginx-lua/t/081-bytecode.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/082-body-filter.t b/debian/modules/nginx-lua/t/082-body-filter.t index 3f7b6da..c0a7c23 100644 --- a/debian/modules/nginx-lua/t/082-body-filter.t +++ b/debian/modules/nginx-lua/t/082-body-filter.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/083-bad-sock-self.t b/debian/modules/nginx-lua/t/083-bad-sock-self.t index eb4f215..b93849f 100644 --- a/debian/modules/nginx-lua/t/083-bad-sock-self.t +++ b/debian/modules/nginx-lua/t/083-bad-sock-self.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; repeat_each(2); diff --git a/debian/modules/nginx-lua/t/084-inclusive-receiveuntil.t b/debian/modules/nginx-lua/t/084-inclusive-receiveuntil.t index a86afd5..c966015 100644 --- a/debian/modules/nginx-lua/t/084-inclusive-receiveuntil.t +++ b/debian/modules/nginx-lua/t/084-inclusive-receiveuntil.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; repeat_each(2); diff --git a/debian/modules/nginx-lua/t/085-if.t b/debian/modules/nginx-lua/t/085-if.t index c82085f..e08b43c 100644 --- a/debian/modules/nginx-lua/t/085-if.t +++ b/debian/modules/nginx-lua/t/085-if.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/086-init-by.t b/debian/modules/nginx-lua/t/086-init-by.t index f9ed12c..3a474fe 100644 --- a/debian/modules/nginx-lua/t/086-init-by.t +++ b/debian/modules/nginx-lua/t/086-init-by.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/087-udp-socket.t b/debian/modules/nginx-lua/t/087-udp-socket.t index fd07ff9..39ff54f 100644 --- a/debian/modules/nginx-lua/t/087-udp-socket.t +++ b/debian/modules/nginx-lua/t/087-udp-socket.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; repeat_each(2); diff --git a/debian/modules/nginx-lua/t/088-req-method.t b/debian/modules/nginx-lua/t/088-req-method.t index aceb877..9ced40c 100644 --- a/debian/modules/nginx-lua/t/088-req-method.t +++ b/debian/modules/nginx-lua/t/088-req-method.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/090-log-socket-errors.t b/debian/modules/nginx-lua/t/090-log-socket-errors.t index 1e41491..a5943c2 100644 --- a/debian/modules/nginx-lua/t/090-log-socket-errors.t +++ b/debian/modules/nginx-lua/t/090-log-socket-errors.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/091-coroutine.t b/debian/modules/nginx-lua/t/091-coroutine.t index c7c5922..b047ccb 100644 --- a/debian/modules/nginx-lua/t/091-coroutine.t +++ b/debian/modules/nginx-lua/t/091-coroutine.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; repeat_each(2); diff --git a/debian/modules/nginx-lua/t/092-eof.t b/debian/modules/nginx-lua/t/092-eof.t index 7b852b3..a75711f 100644 --- a/debian/modules/nginx-lua/t/092-eof.t +++ b/debian/modules/nginx-lua/t/092-eof.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/093-uthread-spawn.t b/debian/modules/nginx-lua/t/093-uthread-spawn.t index e6dba5f..772e866 100644 --- a/debian/modules/nginx-lua/t/093-uthread-spawn.t +++ b/debian/modules/nginx-lua/t/093-uthread-spawn.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; use t::StapThread; diff --git a/debian/modules/nginx-lua/t/094-uthread-exit.t b/debian/modules/nginx-lua/t/094-uthread-exit.t index 1bd970c..4d1d316 100644 --- a/debian/modules/nginx-lua/t/094-uthread-exit.t +++ b/debian/modules/nginx-lua/t/094-uthread-exit.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; use t::StapThread; diff --git a/debian/modules/nginx-lua/t/095-uthread-exec.t b/debian/modules/nginx-lua/t/095-uthread-exec.t index 2309fbe..4459360 100644 --- a/debian/modules/nginx-lua/t/095-uthread-exec.t +++ b/debian/modules/nginx-lua/t/095-uthread-exec.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; use t::StapThread; diff --git a/debian/modules/nginx-lua/t/096-uthread-redirect.t b/debian/modules/nginx-lua/t/096-uthread-redirect.t index 177e071..b0258fb 100644 --- a/debian/modules/nginx-lua/t/096-uthread-redirect.t +++ b/debian/modules/nginx-lua/t/096-uthread-redirect.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; use t::StapThread; diff --git a/debian/modules/nginx-lua/t/097-uthread-rewrite.t b/debian/modules/nginx-lua/t/097-uthread-rewrite.t index bf88864..178a374 100644 --- a/debian/modules/nginx-lua/t/097-uthread-rewrite.t +++ b/debian/modules/nginx-lua/t/097-uthread-rewrite.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; use t::StapThread; diff --git a/debian/modules/nginx-lua/t/098-uthread-wait.t b/debian/modules/nginx-lua/t/098-uthread-wait.t index 1f064f3..aaf020a 100644 --- a/debian/modules/nginx-lua/t/098-uthread-wait.t +++ b/debian/modules/nginx-lua/t/098-uthread-wait.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; use t::StapThread; diff --git a/debian/modules/nginx-lua/t/099-c-api.t b/debian/modules/nginx-lua/t/099-c-api.t index a61b8f4..a0b375c 100644 --- a/debian/modules/nginx-lua/t/099-c-api.t +++ b/debian/modules/nginx-lua/t/099-c-api.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); @@ -361,3 +360,38 @@ foo: rc=-5 --- no_error_log [error] + + +=== TEST 7: find zone (multiple zones) +--- http_config + lua_shared_dict dogs 1m; + lua_shared_dict cats 1m; +--- config + location = /test { + content_by_lua ' + local ffi = require "ffi" + + ffi.cdef[[ + void *ngx_http_lua_find_zone(char *data, size_t len); + ]] + + local buf = ffi.new("char[?]", 4) + ffi.copy(buf, "cats", 4) + local zone = ffi.C.ngx_http_lua_find_zone(buf, 4) + local cats = tostring(zone) + + ffi.copy(buf, "dogs", 4) + zone = ffi.C.ngx_http_lua_find_zone(buf, 4) + local dogs = tostring(zone) + + ngx.say("dogs == cats ? ", dogs == cats) + -- ngx.say("dogs: ", dogs) + -- ngx.say("cats ", cats) + '; + } +--- request +GET /test +--- response_body +dogs == cats ? false +--- no_error_log +[error] diff --git a/debian/modules/nginx-lua/t/100-client-abort.t b/debian/modules/nginx-lua/t/100-client-abort.t index 2428388..cd46859 100644 --- a/debian/modules/nginx-lua/t/100-client-abort.t +++ b/debian/modules/nginx-lua/t/100-client-abort.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; use t::StapThread; diff --git a/debian/modules/nginx-lua/t/101-on-abort.t b/debian/modules/nginx-lua/t/101-on-abort.t index 6eed29d..bb74204 100644 --- a/debian/modules/nginx-lua/t/101-on-abort.t +++ b/debian/modules/nginx-lua/t/101-on-abort.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; use t::StapThread; diff --git a/debian/modules/nginx-lua/t/102-req-start-time.t b/debian/modules/nginx-lua/t/102-req-start-time.t index 6ce6196..1d5fe28 100644 --- a/debian/modules/nginx-lua/t/102-req-start-time.t +++ b/debian/modules/nginx-lua/t/102-req-start-time.t @@ -1,7 +1,6 @@ # -*- mode: conf -*- # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/103-req-http-ver.t b/debian/modules/nginx-lua/t/103-req-http-ver.t index 89b491f..6ded75a 100644 --- a/debian/modules/nginx-lua/t/103-req-http-ver.t +++ b/debian/modules/nginx-lua/t/103-req-http-ver.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/104-req-raw-header.t b/debian/modules/nginx-lua/t/104-req-raw-header.t index 5fe326b..439b9de 100644 --- a/debian/modules/nginx-lua/t/104-req-raw-header.t +++ b/debian/modules/nginx-lua/t/104-req-raw-header.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/105-pressure.t b/debian/modules/nginx-lua/t/105-pressure.t index ce9d8b4..10f495e 100644 --- a/debian/modules/nginx-lua/t/105-pressure.t +++ b/debian/modules/nginx-lua/t/105-pressure.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/106-timer.t b/debian/modules/nginx-lua/t/106-timer.t index 497ffa2..5cfc01b 100644 --- a/debian/modules/nginx-lua/t/106-timer.t +++ b/debian/modules/nginx-lua/t/106-timer.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; use t::StapThread; diff --git a/debian/modules/nginx-lua/t/107-timer-errors.t b/debian/modules/nginx-lua/t/107-timer-errors.t index 5e9b664..9ed1334 100644 --- a/debian/modules/nginx-lua/t/107-timer-errors.t +++ b/debian/modules/nginx-lua/t/107-timer-errors.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/108-timer-safe.t b/debian/modules/nginx-lua/t/108-timer-safe.t index 94c322d..19c9f6d 100644 --- a/debian/modules/nginx-lua/t/108-timer-safe.t +++ b/debian/modules/nginx-lua/t/108-timer-safe.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; use t::StapThread; diff --git a/debian/modules/nginx-lua/t/109-timer-hup.t b/debian/modules/nginx-lua/t/109-timer-hup.t index 5cdf75b..15aaa0e 100644 --- a/debian/modules/nginx-lua/t/109-timer-hup.t +++ b/debian/modules/nginx-lua/t/109-timer-hup.t @@ -12,7 +12,6 @@ BEGIN { } } -use lib 'lib'; use Test::Nginx::Socket::Lua $SkipReason ? (skip_all => $SkipReason) : (); diff --git a/debian/modules/nginx-lua/t/110-etag.t b/debian/modules/nginx-lua/t/110-etag.t index d6f2864..351fec4 100644 --- a/debian/modules/nginx-lua/t/110-etag.t +++ b/debian/modules/nginx-lua/t/110-etag.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/111-req-header-ua.t b/debian/modules/nginx-lua/t/111-req-header-ua.t index 7d395c8..7c980d0 100644 --- a/debian/modules/nginx-lua/t/111-req-header-ua.t +++ b/debian/modules/nginx-lua/t/111-req-header-ua.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/112-req-header-conn.t b/debian/modules/nginx-lua/t/112-req-header-conn.t index 4926a01..51df730 100644 --- a/debian/modules/nginx-lua/t/112-req-header-conn.t +++ b/debian/modules/nginx-lua/t/112-req-header-conn.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/113-req-header-cookie.t b/debian/modules/nginx-lua/t/113-req-header-cookie.t index df08205..b26b709 100644 --- a/debian/modules/nginx-lua/t/113-req-header-cookie.t +++ b/debian/modules/nginx-lua/t/113-req-header-cookie.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/114-config.t b/debian/modules/nginx-lua/t/114-config.t index fa97eb1..e6d75fc 100644 --- a/debian/modules/nginx-lua/t/114-config.t +++ b/debian/modules/nginx-lua/t/114-config.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/115-quote-sql-str.t b/debian/modules/nginx-lua/t/115-quote-sql-str.t index e473b21..0c20dfb 100644 --- a/debian/modules/nginx-lua/t/115-quote-sql-str.t +++ b/debian/modules/nginx-lua/t/115-quote-sql-str.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; repeat_each(2); diff --git a/debian/modules/nginx-lua/t/116-raw-req-socket.t b/debian/modules/nginx-lua/t/116-raw-req-socket.t index 81b84bd..c2ff8f7 100644 --- a/debian/modules/nginx-lua/t/116-raw-req-socket.t +++ b/debian/modules/nginx-lua/t/116-raw-req-socket.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; repeat_each(2); diff --git a/debian/modules/nginx-lua/t/117-raw-req-socket-timeout.t b/debian/modules/nginx-lua/t/117-raw-req-socket-timeout.t index 46e7d71..4e3929b 100644 --- a/debian/modules/nginx-lua/t/117-raw-req-socket-timeout.t +++ b/debian/modules/nginx-lua/t/117-raw-req-socket-timeout.t @@ -21,7 +21,6 @@ BEGIN { $ENV{TEST_NGINX_POSTPONE_OUTPUT} = 1; } -use lib 'lib'; use Test::Nginx::Socket::Lua; use t::StapThread; diff --git a/debian/modules/nginx-lua/t/118-use-default-type.t b/debian/modules/nginx-lua/t/118-use-default-type.t index fd77cff..6008d65 100644 --- a/debian/modules/nginx-lua/t/118-use-default-type.t +++ b/debian/modules/nginx-lua/t/118-use-default-type.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; repeat_each(2); diff --git a/debian/modules/nginx-lua/t/119-config-prefix.t b/debian/modules/nginx-lua/t/119-config-prefix.t index 047c68e..4581aa1 100644 --- a/debian/modules/nginx-lua/t/119-config-prefix.t +++ b/debian/modules/nginx-lua/t/119-config-prefix.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/121-version.t b/debian/modules/nginx-lua/t/121-version.t index 4ddd263..2b7a306 100644 --- a/debian/modules/nginx-lua/t/121-version.t +++ b/debian/modules/nginx-lua/t/121-version.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/123-lua-path.t b/debian/modules/nginx-lua/t/123-lua-path.t index 964b48b..da97909 100644 --- a/debian/modules/nginx-lua/t/123-lua-path.t +++ b/debian/modules/nginx-lua/t/123-lua-path.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/124-init-worker.t b/debian/modules/nginx-lua/t/124-init-worker.t index ce86fee..d6ea675 100644 --- a/debian/modules/nginx-lua/t/124-init-worker.t +++ b/debian/modules/nginx-lua/t/124-init-worker.t @@ -9,7 +9,7 @@ use Test::Nginx::Socket::Lua; repeat_each(1); -plan tests => repeat_each() * (blocks() * 4 + 1); +plan tests => repeat_each() * (blocks() * 4); $ENV{TEST_NGINX_MEMCACHED_PORT} ||= 11211; $ENV{TEST_NGINX_RESOLVER} ||= '8.8.8.8'; @@ -740,3 +740,19 @@ ok Bad bad bad --- skip_nginx: 4: < 1.7.1 + + +=== TEST 19: fake module calls ngx_http_conf_get_module_srv_conf in its merge_srv_conf callback (GitHub issue #554) +This also affects merge_loc_conf +--- http_config + init_worker_by_lua return; +--- config + location = /t { + return 200 ok; + } +--- request +GET /t +--- response_body chomp +ok +--- no_error_log +[error] diff --git a/debian/modules/nginx-lua/t/125-configure-args.t b/debian/modules/nginx-lua/t/125-configure-args.t index d37a218..adec129 100644 --- a/debian/modules/nginx-lua/t/125-configure-args.t +++ b/debian/modules/nginx-lua/t/125-configure-args.t @@ -1,5 +1,4 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/126-shdict-frag.t b/debian/modules/nginx-lua/t/126-shdict-frag.t index 8c1ad75..94422fb 100644 --- a/debian/modules/nginx-lua/t/126-shdict-frag.t +++ b/debian/modules/nginx-lua/t/126-shdict-frag.t @@ -1,5 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; + use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/127-uthread-kill.t b/debian/modules/nginx-lua/t/127-uthread-kill.t index a5afc2b..2ab8abe 100644 --- a/debian/modules/nginx-lua/t/127-uthread-kill.t +++ b/debian/modules/nginx-lua/t/127-uthread-kill.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; use t::StapThread; diff --git a/debian/modules/nginx-lua/t/128-duplex-tcp-socket.t b/debian/modules/nginx-lua/t/128-duplex-tcp-socket.t index 571bdc8..0bf38d0 100644 --- a/debian/modules/nginx-lua/t/128-duplex-tcp-socket.t +++ b/debian/modules/nginx-lua/t/128-duplex-tcp-socket.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; repeat_each(2); diff --git a/debian/modules/nginx-lua/t/129-ssl-socket.t b/debian/modules/nginx-lua/t/129-ssl-socket.t index bb04110..45eaa82 100644 --- a/debian/modules/nginx-lua/t/129-ssl-socket.t +++ b/debian/modules/nginx-lua/t/129-ssl-socket.t @@ -1,6 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; use Test::Nginx::Socket::Lua; repeat_each(2); @@ -102,13 +101,13 @@ __DATA__ --- request GET /t ---- response_body -connected: 1 +--- response_body_like chop +\Aconnected: 1 ssl handshake: userdata sent http request: 59 bytes. -received: HTTP/1.1 200 OK +received: HTTP/1.1 (?:200 OK|302 Found) close: 1 nil - +\z --- grep_error_log eval: qr/lua ssl (?:set|save|free) session: [0-9A-F]+:\d+/ --- grep_error_log_out eval qr/^lua ssl save session: ([0-9A-F]+):2 @@ -920,13 +919,13 @@ $::EquifaxRootCertificate" --- request GET /t ---- response_body -connected: 1 +--- response_body_like chop +\Aconnected: 1 ssl handshake: userdata sent http request: 59 bytes. -received: HTTP/1.1 200 OK +received: HTTP/1.1 (?:200 OK|302 Found) close: 1 nil - +\z --- grep_error_log eval: qr/lua ssl (?:set|save|free) session: [0-9A-F]+:\d+/ --- grep_error_log_out eval qr/^lua ssl save session: ([0-9A-F]+):2 diff --git a/debian/modules/nginx-lua/t/130-internal-api.t b/debian/modules/nginx-lua/t/130-internal-api.t index c40bf13..d641ab5 100644 --- a/debian/modules/nginx-lua/t/130-internal-api.t +++ b/debian/modules/nginx-lua/t/130-internal-api.t @@ -1,5 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use lib 'lib'; + use Test::Nginx::Socket::Lua; #worker_connections(1014); diff --git a/debian/modules/nginx-lua/t/132-lua-blocks.t b/debian/modules/nginx-lua/t/132-lua-blocks.t new file mode 100644 index 0000000..874d017 --- /dev/null +++ b/debian/modules/nginx-lua/t/132-lua-blocks.t @@ -0,0 +1,490 @@ +# vim:set ft= ts=4 sw=4 et fdm=marker: + +use Test::Nginx::Socket::Lua; + +#worker_connections(1014); +#master_on(); +#workers(2); +#log_level('warn'); + +repeat_each(2); +#repeat_each(1); + +plan tests => repeat_each() * (blocks() * 3 + 4); + +#no_diff(); +no_long_string(); +run_tests(); + +__DATA__ + +=== TEST 1: content_by_lua_block (simplest) +--- config + location = /t { + content_by_lua_block { + ngx.say("hello, world") + } + } +--- request +GET /t +--- response_body +hello, world +--- no_error_log +[error] + + + +=== TEST 2: content_by_lua_block (nested curly braces) +--- config + location = /t { + content_by_lua_block { + local a = { + dogs = {32, 78, 96}, + cat = "kitty", + } + ngx.say("a.dogs[1] = ", a.dogs[1]) + ngx.say("a.dogs[2] = ", a.dogs[2]) + ngx.say("a.dogs[3] = ", a.dogs[3]) + ngx.say("a.cat = ", a.cat) + } + } +--- request +GET /t +--- response_body +a.dogs[1] = 32 +a.dogs[2] = 78 +a.dogs[3] = 96 +a.cat = kitty + +--- no_error_log +[error] + + + +=== TEST 3: content_by_lua_block (curly braces in strings) +--- config + location = /t { + content_by_lua_block { + ngx.say("}1, 2)") + ngx.say('{1, 2)') + } + } +--- request +GET /t +--- response_body +}1, 2) +{1, 2) + +--- no_error_log +[error] + + + +=== TEST 4: content_by_lua_block (curly braces in strings, with escaped terminators) +--- config + location = /t { + content_by_lua_block { + ngx.say("\"}1, 2)") + ngx.say('\'{1, 2)') + } + } +--- request +GET /t +--- response_body +"}1, 2) +'{1, 2) + +--- no_error_log +[error] + + + +=== TEST 5: content_by_lua_block (curly braces in long brackets) +--- config + location = /t { + content_by_lua_block { + --[[ + {{{ + + } + ]] + --[==[ + }}} + + { + ]==] + ngx.say("ok") + } + } +--- request +GET /t +--- response_body +ok +--- no_error_log +[error] + + + +=== TEST 6: content_by_lua_block ("nested" long brackets) +--- config + location = /t { + content_by_lua_block { + --[[ + ]=] + ' " + } + ]] + ngx.say("ok") + } + } +--- request +GET /t +--- response_body +ok +--- no_error_log +[error] + + + +=== TEST 7: content_by_lua_block (curly braces in line comments) +--- config + location = /t { + content_by_lua_block { + --}} {} + ngx.say("ok") + } + } +--- request +GET /t +--- response_body +ok +--- no_error_log +[error] + + + +=== TEST 8: content_by_lua_block (cosockets) +--- config + server_tokens off; + location = /t { + content_by_lua_block { + local sock = ngx.socket.tcp() + local port = ngx.var.port + local ok, err = sock:connect('127.0.0.1', tonumber(ngx.var.server_port)) + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say('connected: ', ok) + + local req = "GET /foo HTTP/1.0\r\nHost: localhost\r\nConnection: close\r\n\r\n" + -- req = "OK" + + local bytes, err = sock:send(req) + if not bytes then + ngx.say("failed to send request: ", err) + return + end + + ngx.say("request sent: ", bytes) + + while true do + local line, err, part = sock:receive() + if line then + ngx.say("received: ", line) + + else + ngx.say("failed to receive a line: ", err, " [", part, "]") + break + end + end + + ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + } + } + + location /foo { + content_by_lua_block { ngx.say("foo") } + more_clear_headers Date; + } + +--- request +GET /t +--- response_body +connected: 1 +request sent: 57 +received: HTTP/1.1 200 OK +received: Server: nginx +received: Content-Type: text/plain +received: Content-Length: 4 +received: Connection: close +received: +received: foo +failed to receive a line: closed [] +close: 1 nil +--- no_error_log +[error] + + + +=== TEST 9: all in one +--- http_config + init_by_lua_block { + glob = "init by lua }here{" + } + + init_worker_by_lua_block { + glob = glob .. ", init worker }here{" + } +--- config + location = /t { + set $a ''; + rewrite_by_lua_block { + local s = ngx.var.a + s = s .. "}rewrite{\n" + ngx.var.a = s + } + access_by_lua_block { + local s = ngx.var.a + s = s .. '}access{\n' + ngx.var.a = s + } + content_by_lua_block { + local s = ngx.var.a + s = s .. [[}content{]] + ngx.say(s) + ngx.say("glob: ", glob) + } + log_by_lua_block { + print("log by lua running \"}{!\"") + } + header_filter_by_lua_block { + ngx.header["Foo"] = "\"Hello, world\"" + ngx.header["Content-Length"] = nil + } + body_filter_by_lua_block { + local data, eof = ngx.arg[1], ngx.arg[2] + print("eof = ", eof) + if eof then + if not data then + data = "" + end + data = data .. "}body filter{\n" + print("data: ", data) + ngx.arg[1] = data + end + } + } +--- request +GET /t +--- response_body +}rewrite{ +}access{ +}content{ +glob: init by lua }here{, init worker }here{ +}body filter{ + +--- response_headers +Foo: "Hello, world" +--- error_log +log by lua running "}{!" +--- no_error_log +[error] + + + +=== TEST 10: missing ]] (string) +--- config + location = /t { + content_by_lua_block { + ngx.say([[hello, world") + } + } +--- request +GET /t +--- response_body +hello, world +--- no_error_log +[error] +--- must_die +--- error_log eval +qr/\[emerg\] .*? Lua code block missing the closing long bracket "]]" in .*?\bnginx\.conf:41/ + + + +=== TEST 11: missing ]==] (string) +--- config + location = /t { + content_by_lua_block { + ngx.say([==[hello, world") + } + } +--- request +GET /t +--- response_body +hello, world +--- no_error_log +[error] +--- must_die +--- error_log eval +qr/\[emerg\] .*? Lua code block missing the closing long bracket "]==]" in .*?\bnginx\.conf:41/ + + + +=== TEST 12: missing ]] (comment) +--- config + location = /t { + content_by_lua_block { + ngx.say(--[[hello, world") + } + } +--- request +GET /t +--- response_body +hello, world +--- no_error_log +[error] +--- must_die +--- error_log eval +qr/\[emerg\] .*? Lua code block missing the closing long bracket "]]" in .*?\bnginx\.conf:41/ + + + +=== TEST 13: missing ]=] (comment) +--- config + location = /t { + content_by_lua_block { + ngx.say(--[=[hello, world") + } + } +--- request +GET /t +--- response_body +hello, world +--- no_error_log +[error] +--- must_die +--- error_log eval +qr/\[emerg\] .*? Lua code block missing the closing long bracket "]=]" in .*?\bnginx\.conf:41/ + + + +=== TEST 14: missing } +FIXME: we need better diagnostics by actually loading the inlined Lua code while parsing +the *_by_lua_block directive. + +--- config + location = /t { + content_by_lua_block { + ngx.say("hello") +--- request +GET /t +--- response_body +hello, world +--- no_error_log +[error] +--- error_log +"events" directive is not allowed here +--- must_die + + + +=== TEST 15: content_by_lua_block (compact) +--- config + location = /t { + content_by_lua_block {ngx.say("hello, world", {"!"})} + } +--- request +GET /t +--- response_body +hello, world! +--- no_error_log +[error] + + + +=== TEST 16: content_by_lua_block (unexpected closing long brackets) +--- config + location = /t { + content_by_lua_block { + ]=] + } + } +--- request +GET /t +--- no_error_log +[error] +--- error_log eval +qr{\[emerg\] .*? unexpected lua closing long-bracket in .*?/nginx\.conf:41} +--- must_die + + + +=== TEST 17: simple set_by_lua_block (integer) +--- config + location /lua { + set_by_lua_block $res { return 1+1 } + echo $res; + } +--- request +GET /lua +--- response_body +2 +--- no_error_log +[error] + + + +=== TEST 18: ambiguous line comments inside a long bracket string (GitHub #596) +--- config + location = /t { + content_by_lua_block { + ngx.say([[ok--]]) + ngx.say([==[ok--]==]) + ngx.say([==[ok-- ]==]) + --[[ --]] ngx.say("done") + } + } +--- request +GET /t +--- response_body +ok-- +ok-- +ok-- +done +--- no_error_log +[error] + + + +=== TEST 19: double quotes in long brackets +--- config + location = /t { + rewrite_by_lua_block { print([[Hey, it is "!]]) } content_by_lua_block { ngx.say([["]]) } + } +--- request +GET /t +--- response_body +" +--- error_log +Hey, it is "! +--- no_error_log +[error] + + + +=== TEST 20: single quotes in long brackets +--- config + location = /t { + rewrite_by_lua_block { print([[Hey, it is '!]]) } content_by_lua_block { ngx.say([[']]) } + } +--- request +GET /t +--- response_body +' +--- error_log +Hey, it is '! +--- no_error_log +[error] diff --git a/debian/modules/nginx-lua/t/data/fake-module/config b/debian/modules/nginx-lua/t/data/fake-module/config new file mode 100644 index 0000000..00cc8e8 --- /dev/null +++ b/debian/modules/nginx-lua/t/data/fake-module/config @@ -0,0 +1,3 @@ +ngx_addon_name=ngx_http_fake_module +HTTP_MODULES="$HTTP_MODULES ngx_http_fake_module" +NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_fake_module.c" diff --git a/debian/modules/nginx-lua/t/data/fake-module/ngx_http_fake_module.c b/debian/modules/nginx-lua/t/data/fake-module/ngx_http_fake_module.c new file mode 100644 index 0000000..ec74aa4 --- /dev/null +++ b/debian/modules/nginx-lua/t/data/fake-module/ngx_http_fake_module.c @@ -0,0 +1,121 @@ +/* Copyright (C) ZHANG Heng (chiyouhen) + * + * This fake module was used to reproduce a bug in ngx_lua's + * init_worker_by_lua implementation. + */ + + +#include +#include +#include +#include + + +typedef struct { + ngx_int_t a; +} ngx_http_fake_srv_conf_t; + + +typedef struct { + ngx_int_t a; +} ngx_http_fake_loc_conf_t; + + +static void *ngx_http_fake_create_srv_conf(ngx_conf_t *cf); +static char *ngx_http_fake_merge_srv_conf(ngx_conf_t *cf, void *prev, void *conf); +static void *ngx_http_fake_create_loc_conf(ngx_conf_t *cf); +static char *ngx_http_fake_merge_loc_conf(ngx_conf_t *cf, void *prev, void *conf); + + +/* flow identify module configure struct */ +static ngx_http_module_t ngx_http_fake_module_ctx = { + NULL, /* preconfiguration */ + NULL, /* postconfiguration */ + + NULL, /* create main configuration */ + NULL, /* init main configuration */ + + ngx_http_fake_create_srv_conf, /* create server configuration */ + ngx_http_fake_merge_srv_conf, /* merge server configuration */ + + ngx_http_fake_create_loc_conf, /* create location configuration */ + ngx_http_fake_merge_loc_conf /* merge location configuration */ +}; + +/* flow identify module struct */ +ngx_module_t ngx_http_fake_module = { + NGX_MODULE_V1, + &ngx_http_fake_module_ctx, /* module context */ + NULL, /* 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 +}; + + +/* create server configure */ +static void *ngx_http_fake_create_srv_conf(ngx_conf_t *cf) +{ + ngx_http_fake_srv_conf_t *fscf; + + fscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_fake_srv_conf_t)); + if (fscf == NULL) { + return NULL; + } + + return fscf; +} + + +/* merge server configure */ +static char *ngx_http_fake_merge_srv_conf(ngx_conf_t *cf, void *prev, void *conf) +{ + ngx_http_fake_srv_conf_t *fscf; + + fscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_fake_module); + if (fscf == NULL) { + ngx_conf_log_error(NGX_LOG_ALERT, cf, 0, + "get module srv conf failed in merge srv conf"); + return NGX_CONF_ERROR; + } + + ngx_conf_log_error(NGX_LOG_NOTICE, cf, 0, "merge srv conf ok"); + return NGX_CONF_OK; +} + + +/* create location configure */ +static void *ngx_http_fake_create_loc_conf(ngx_conf_t *cf) +{ + ngx_http_fake_loc_conf_t *flcf; + + flcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_fake_loc_conf_t)); + if (flcf == NULL) { + return NULL; + } + + return flcf; +} + + +/* merge location configure */ +static char *ngx_http_fake_merge_loc_conf(ngx_conf_t *cf, void *prev, void *conf) +{ + ngx_http_fake_loc_conf_t *flcf; + + flcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_fake_module); + if (flcf == NULL) { + ngx_conf_log_error(NGX_LOG_ALERT, cf, 0, + "get module loc conf failed in merge loc conf"); + return NGX_CONF_ERROR; + } + + ngx_conf_log_error(NGX_LOG_NOTICE, cf, 0, "merge loc conf ok"); + return NGX_CONF_OK; +} diff --git a/debian/modules/nginx-lua/util/build.sh b/debian/modules/nginx-lua/util/build.sh deleted file mode 100755 index 6617817..0000000 --- a/debian/modules/nginx-lua/util/build.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/bash - -# this file is mostly meant to be used by the author himself. - -version=${1:-0.8.54} -opts=$2 - -root=$(cd ${0%/*}/.. && echo $PWD) -mkdir -p $root/{build,work} - -cd $root -git submodule update --init - -cd $root/build -if [ ! -s nginx-$version.tar.gz ]; then - wget "http://sysoev.ru/nginx/nginx-$version.tar.gz" -O nginx-$version.tar.gz -fi -tar -xzvf nginx-$version.tar.gz - -cd nginx-$version/ -if [[ "$BUILD_CLEAN" -eq 1 || ! -f Makefile || "$root/config" -nt Makefile || "$root/util/build.sh" -nt Makefile ]]; then - ./configure --prefix=$root/work \ - --add-module=$root \ - --add-module=$root/deps/ngx_devel_kit \ - $opts \ - --with-debug -fi - -if [ -f $root/work/sbin/nginx ]; then - rm -f $root/work/sbin/nginx -fi - -if [ -f $root/work/logs/nginx.pid ]; then - kill `cat $root/work/logs/nginx.pid` -fi - -make -j2 -make install - diff --git a/debian/modules/nginx-lua/util/build2.sh b/debian/modules/nginx-lua/util/build2.sh index 21caf1f..5a89c29 100755 --- a/debian/modules/nginx-lua/util/build2.sh +++ b/debian/modules/nginx-lua/util/build2.sh @@ -1,6 +1,9 @@ #!/usr/bin/env bash -# this file is mostly meant to be used by the author himself. +# this script is for developers only. +# dependent on the ngx-build script from the nginx-devel-utils repostory: +# https://github.com/openresty/nginx-devel-utils/blob/master/ngx-build +# the resulting nginx is located at ./work/nginx/sbin/nginx root=`pwd` version=${1:-1.4.1} @@ -17,6 +20,7 @@ force=$2 #--with-cc=gcc46 \ #--with-cc=clang \ #--without-http_referer_module \ + #--with-http_v2_module \ time ngx-build $force $version \ --with-ipv6 \ @@ -46,7 +50,9 @@ time ngx-build $force $version \ --add-module=$root/../rds-json-nginx-module \ --add-module=$root/../coolkit-nginx-module \ --add-module=$root/../redis2-nginx-module \ + --add-module=$root/t/data/fake-module \ --with-http_gunzip_module \ + --with-http_dav_module \ --with-select_module \ --with-poll_module \ $opts \ diff --git a/debian/modules/nginx-lua/util/gen-lexer-c b/debian/modules/nginx-lua/util/gen-lexer-c new file mode 100755 index 0000000..dfed3fc --- /dev/null +++ b/debian/modules/nginx-lua/util/gen-lexer-c @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +if [ -z "$1" ]; then + level=0 +else + level="$1" +fi + +#echo '{' '}' '\[=*\[' '--\[=*\[' '\]=*\]' '--[^\n]*' '"(?:\\[^\n]|[^"\n\\])*"' $'\'(?:\\\\[^\\n]|[^\'\\n\\\\])*\'' + +# we need the re.pl script here: +# https://github.com/openresty/sregex/blob/dfa-multi-re/re.pl +re.pl -W --no-main -c --cc="clang -O2" \ + --func-name ngx_http_lua_lex \ + --header ngx_http_lua_lex.h -o src/ngx_http_lua_lex.c \ + --debug=$level -n 8 \ + -- '{' '}' '\[=*\[' '--\[=*\[' '\]=*\]' '--[^\n]*' '"(?:\\[^\n]|[^"\n\\])*"' $'\'(?:\\\\[^\\n]|[^\'\\n\\\\])*\'' \ + || exit 1 diff --git a/debian/modules/nginx-lua/valgrind.suppress b/debian/modules/nginx-lua/valgrind.suppress index a69e606..fe161e8 100644 --- a/debian/modules/nginx-lua/valgrind.suppress +++ b/debian/modules/nginx-lua/valgrind.suppress @@ -103,6 +103,13 @@ fun:main fun:ngx_alloc fun:ngx_event_process_init } +{ + + Memcheck:Param + sendmsg(mmsg[0].msg_hdr) + fun:sendmmsg + fun:__libc_res_nsend +} { Memcheck:Param From b1928b468dcb842a0a989f108d89afa8d7b321d5 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Fri, 13 Nov 2015 16:08:16 +0200 Subject: [PATCH 016/600] Release 1.9.6-2 --- debian/changelog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index 08dd22b..0a868c8 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,10 +1,10 @@ -nginx (1.9.6-2) UNRELEASED; urgency=medium +nginx (1.9.6-2) unstable; urgency=medium [ Christos Trochalakis] * debian/modules/nginx-lua: + Update nginx-lua to v0.9.19 fixing HTTP/2 compatibility. - -- Christos Trochalakis Fri, 13 Nov 2015 16:04:32 +0200 + -- Christos Trochalakis Fri, 13 Nov 2015 16:08:01 +0200 nginx (1.9.6-1) unstable; urgency=medium From 255c62e0b5926e3d5517fe2331cd4f71400afff6 Mon Sep 17 00:00:00 2001 From: Michael Lustfield Date: Thu, 10 Dec 2015 04:09:20 -0600 Subject: [PATCH 017/600] Changing logrotate from 52 days to 14 because of a typo and similar bug. Bug #805322 --- debian/changelog | 7 +++++++ debian/nginx-common.nginx.logrotate | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index 0a868c8..3000163 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +nginx (1.9.6-3) UNRELEASED; urgency=medium + + * debian/nginx-common.nginx.logrotate: + + Switching logrotate to 14 days. (Closes: #805322) + + -- Michael Lustfield Thu, 10 Dec 2015 04:07:29 -0600 + nginx (1.9.6-2) unstable; urgency=medium [ Christos Trochalakis] diff --git a/debian/nginx-common.nginx.logrotate b/debian/nginx-common.nginx.logrotate index 489c31b..1b25aad 100644 --- a/debian/nginx-common.nginx.logrotate +++ b/debian/nginx-common.nginx.logrotate @@ -1,7 +1,7 @@ /var/log/nginx/*.log { weekly missingok - rotate 52 + rotate 14 compress delaycompress notifempty From 23c5f9380615637d6d33f1583d07487e1f138637 Mon Sep 17 00:00:00 2001 From: Michael Lustfield Date: Tue, 15 Dec 2015 01:51:24 -0600 Subject: [PATCH 018/600] Adding some missing files --- .../nginx-lua/misc/recv-until-pm/Makefile | 3 + debian/modules/nginx-lua/util/reindex | 64 +++++++++++++++++++ debian/modules/nginx-lua/util/releng | 8 +++ 3 files changed, 75 insertions(+) create mode 100644 debian/modules/nginx-lua/misc/recv-until-pm/Makefile create mode 100755 debian/modules/nginx-lua/util/reindex create mode 100755 debian/modules/nginx-lua/util/releng diff --git a/debian/modules/nginx-lua/misc/recv-until-pm/Makefile b/debian/modules/nginx-lua/misc/recv-until-pm/Makefile new file mode 100644 index 0000000..eb4d937 --- /dev/null +++ b/debian/modules/nginx-lua/misc/recv-until-pm/Makefile @@ -0,0 +1,3 @@ +test: + prove -Ilib -r t + diff --git a/debian/modules/nginx-lua/util/reindex b/debian/modules/nginx-lua/util/reindex new file mode 100755 index 0000000..bd54c9d --- /dev/null +++ b/debian/modules/nginx-lua/util/reindex @@ -0,0 +1,64 @@ +#!/usr/bin/perl +#: reindex.pl +#: reindex .t files for Test::Base based test files +#: Copyright (c) 2006 Agent Zhang +#: 2006-04-27 2006-05-09 + +use strict; +use warnings; + +#use File::Copy; +use Getopt::Std; + +my %opts; +getopts('hb:', \%opts); +if ($opts{h} or ! @ARGV) { + die "Usage: reindex [-b 0] t/*.t\n"; +} + +my $init = $opts{b}; +$init = 1 if not defined $init; + +my @files = map glob, @ARGV; +for my $file (@files) { + next if -d $file or $file !~ /\.t_?$/; + reindex($file); +} + +sub reindex { + my $file = $_[0]; + open my $in, $file or + die "Can't open $file for reading: $!"; + my @lines; + my $counter = $init; + my $changed; + while (<$in>) { + s/\r$//; + my $num; + s/ ^ === \s+ TEST \s+ (\d+)/$num=$1; "=== TEST " . $counter++/xie; + next if !defined $num; + if ($num != $counter-1) { + $changed++; + } + } continue { + push @lines, $_; + } + close $in; + my $text = join '', @lines; + $text =~ s/(?x) \n+ === \s+ TEST/\n\n\n\n=== TEST/ixsg; + $text =~ s/__(DATA|END)__\n+=== TEST/__${1}__\n\n=== TEST/; + #$text =~ s/\n+$/\n\n/s; + if (! $changed and $text eq join '', @lines) { + warn "reindex: $file:\tskipped.\n"; + return; + } + #File::Copy::copy( $file, "$file.bak" ); + open my $out, "> $file" or + die "Can't open $file for writing: $!"; + binmode $out; + print $out $text; + close $out; + + warn "reindex: $file:\tdone.\n"; +} + diff --git a/debian/modules/nginx-lua/util/releng b/debian/modules/nginx-lua/util/releng new file mode 100755 index 0000000..adc2f4d --- /dev/null +++ b/debian/modules/nginx-lua/util/releng @@ -0,0 +1,8 @@ +#!/bin/bash + +./update-readme +ack '(?<=\#define)\s*DDEBUG\s*1' src +echo ==================================================== +ack '(?<=_version_string) "\d+\.\d+\.\d+"' src +ack '(?<=This document describes rds-json-nginx-module v)\d+\.\d+' README + From 6771862784569cc570591459a9248cee2873dd89 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Thu, 14 Jan 2016 10:06:28 +0200 Subject: [PATCH 019/600] Imported Upstream version 1.9.9 --- CHANGES | 41 ++ CHANGES.ru | 42 ++ auto/lib/openssl/conf | 1 + auto/lib/perl/conf | 2 +- auto/modules | 15 +- auto/options | 3 + auto/sources | 7 +- auto/unix | 16 + src/core/nginx.h | 4 +- src/core/ngx_conf_file.h | 2 +- src/core/ngx_parse.c | 2 +- src/core/ngx_string.c | 2 +- src/core/ngx_syslog.c | 8 + src/core/ngx_syslog.h | 3 +- .../modules/ngx_http_chunked_filter_module.c | 2 +- src/http/modules/ngx_http_fastcgi_module.c | 5 +- src/http/modules/ngx_http_proxy_module.c | 33 +- .../modules/ngx_http_range_filter_module.c | 28 +- src/http/modules/ngx_http_realip_module.c | 72 ++- src/http/modules/ngx_http_scgi_module.c | 5 +- .../modules/ngx_http_slice_filter_module.c | 526 ++++++++++++++++++ src/http/modules/ngx_http_static_module.c | 2 +- .../modules/ngx_http_stub_status_module.c | 2 +- src/http/modules/ngx_http_uwsgi_module.c | 5 +- src/http/ngx_http_core_module.c | 4 +- src/http/ngx_http_request.c | 32 +- src/http/ngx_http_request.h | 2 + src/http/ngx_http_special_response.c | 5 +- src/http/ngx_http_upstream.c | 21 +- src/http/ngx_http_upstream.h | 1 + src/http/v2/ngx_http_v2.c | 50 +- src/http/v2/ngx_http_v2.h | 3 +- src/http/v2/ngx_http_v2_filter_module.c | 52 +- src/os/unix/ngx_files.c | 151 +++-- src/os/unix/ngx_posix_init.c | 2 +- 35 files changed, 1005 insertions(+), 146 deletions(-) create mode 100644 src/http/modules/ngx_http_slice_filter_module.c diff --git a/CHANGES b/CHANGES index 2b9809c..267669b 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,45 @@ +Changes with nginx 1.9.9 09 Dec 2015 + + *) Bugfix: proxying to unix domain sockets did not work when using + variables; the bug had appeared in 1.9.8. + + +Changes with nginx 1.9.8 08 Dec 2015 + + *) Feature: pwritev() support. + + *) Feature: the "include" directive inside the "upstream" block. + + *) Feature: the ngx_http_slice_module. + + *) Bugfix: a segmentation fault might occur in a worker process when + using LibreSSL; the bug had appeared in 1.9.6. + + *) Bugfix: nginx could not be built on OS X in some cases. + + +Changes with nginx 1.9.7 17 Nov 2015 + + *) Feature: the "nohostname" parameter of logging to syslog. + + *) Feature: the "proxy_cache_convert_head" directive. + + *) Feature: the $realip_remote_addr variable in the + ngx_http_realip_module. + + *) Bugfix: the "expires" directive might not work when using variables. + + *) Bugfix: a segmentation fault might occur in a worker process when + using HTTP/2; the bug had appeared in 1.9.6. + + *) Bugfix: if nginx was built with the ngx_http_v2_module it was + possible to use the HTTP/2 protocol even if the "http2" parameter of + the "listen" directive was not specified. + + *) Bugfix: in the ngx_http_v2_module. + + Changes with nginx 1.9.6 27 Oct 2015 *) Bugfix: a segmentation fault might occur in a worker process when diff --git a/CHANGES.ru b/CHANGES.ru index 3e8c364..315013b 100644 --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,46 @@ +Изменения в nginx 1.9.9 09.12.2015 + + *) Исправление: проксирование в unix domain сокеты не работало при + использовании переменных; ошибка появилась в 1.9.8. + + +Изменения в nginx 1.9.8 08.12.2015 + + *) Добавление: поддержка pwritev(). + + *) Добавление: директива include в блоке upstream. + + *) Добавление: модуль ngx_http_slice_module. + + *) Исправление: при использовании LibreSSL в рабочем процессе мог + произойти segmentation fault; ошибка появилась в 1.9.6. + + *) Исправление: nginx мог не собираться на OS X. + + +Изменения в nginx 1.9.7 17.11.2015 + + *) Добавление: параметр nohostname логгирования в syslog. + + *) Добавление: директива proxy_cache_convert_head. + + *) Добавление: переменная $realip_remote_addr в модуле + ngx_http_realip_module. + + *) Исправление: директива expires могла не срабатывать при использовании + переменных. + + *) Исправление: при использовании HTTP/2 в рабочем процессе мог + произойти segmentation fault; ошибка появилась в 1.9.6. + + *) Исправление: если nginx был собран с модулем ngx_http_v2_module, + протокол HTTP/2 мог быть использован клиентом, даже если не был + указан параметр http2 директивы listen. + + *) Исправление: в модуле ngx_http_v2_module. + + Изменения в nginx 1.9.6 27.10.2015 *) Исправление: при использовании HTTP/2 в рабочем процессе мог diff --git a/auto/lib/openssl/conf b/auto/lib/openssl/conf index bca2050..28a99b2 100644 --- a/auto/lib/openssl/conf +++ b/auto/lib/openssl/conf @@ -105,6 +105,7 @@ else if [ $ngx_found = yes ]; then have=NGX_SSL . auto/have + CORE_INCS="$CORE_INCS $ngx_feature_path" CORE_LIBS="$CORE_LIBS $ngx_feature_libs $NGX_LIBDL" OPENSSL=YES fi diff --git a/auto/lib/perl/conf b/auto/lib/perl/conf index 2a1a3fe..4d1bcf1 100644 --- a/auto/lib/perl/conf +++ b/auto/lib/perl/conf @@ -57,7 +57,7 @@ if test -n "$NGX_PERL_VER"; then if [ "$NGX_SYSTEM" = "Darwin" ]; then # OS X system perl wants to link universal binaries ngx_perl_ldopts=`echo $ngx_perl_ldopts \ - | sed -e 's/-arch x86_64 -arch i386//'` + | sed -e 's/-arch i386//' -e 's/-arch x86_64//'` fi CORE_LINK="$CORE_LINK $ngx_perl_ldopts" diff --git a/auto/modules b/auto/modules index 5c734e1..b2d2ee4 100644 --- a/auto/modules +++ b/auto/modules @@ -73,6 +73,11 @@ if [ $HTTP_SSI = YES ]; then fi +if [ $HTTP_SLICE = YES ]; then + HTTP_POSTPONE=YES +fi + + if [ $HTTP_ADDITION = YES ]; then HTTP_POSTPONE=YES fi @@ -110,6 +115,7 @@ fi # ngx_http_copy_filter # ngx_http_range_body_filter # ngx_http_not_modified_filter +# ngx_http_slice_filter HTTP_FILTER_MODULES="$HTTP_WRITE_FILTER_MODULE \ $HTTP_HEADER_FILTER_MODULE \ @@ -179,6 +185,12 @@ if [ $HTTP_USERID = YES ]; then HTTP_SRCS="$HTTP_SRCS $HTTP_USERID_SRCS" fi +if [ $HTTP_SLICE = YES ]; then + HTTP_SRCS="$HTTP_SRCS $HTTP_SLICE_SRCS" +else + HTTP_SLICE_FILTER_MODULE="" +fi + if [ $HTTP_V2 = YES ]; then have=NGX_HTTP_V2 . auto/have @@ -461,7 +473,8 @@ if [ $HTTP = YES ]; then $HTTP_AUX_FILTER_MODULES \ $HTTP_COPY_FILTER_MODULE \ $HTTP_RANGE_BODY_FILTER_MODULE \ - $HTTP_NOT_MODIFIED_FILTER_MODULE" + $HTTP_NOT_MODIFIED_FILTER_MODULE \ + $HTTP_SLICE_FILTER_MODULE" NGX_ADDON_DEPS="$NGX_ADDON_DEPS \$(HTTP_DEPS)" fi diff --git a/auto/options b/auto/options index efc8943..931dabb 100644 --- a/auto/options +++ b/auto/options @@ -71,6 +71,7 @@ HTTP_ACCESS=YES HTTP_AUTH_BASIC=YES HTTP_AUTH_REQUEST=NO HTTP_USERID=YES +HTTP_SLICE=NO HTTP_AUTOINDEX=YES HTTP_RANDOM_INDEX=NO HTTP_STATUS=NO @@ -226,6 +227,7 @@ do --with-http_random_index_module) HTTP_RANDOM_INDEX=YES ;; --with-http_secure_link_module) HTTP_SECURE_LINK=YES ;; --with-http_degradation_module) HTTP_DEGRADATION=YES ;; + --with-http_slice_module) HTTP_SLICE=YES ;; --without-http_charset_module) HTTP_CHARSET=NO ;; --without-http_gzip_module) HTTP_GZIP=NO ;; @@ -394,6 +396,7 @@ cat << END --with-http_random_index_module enable ngx_http_random_index_module --with-http_secure_link_module enable ngx_http_secure_link_module --with-http_degradation_module enable ngx_http_degradation_module + --with-http_slice_module enable ngx_http_slice_module --with-http_stub_status_module enable ngx_http_stub_status_module --without-http_charset_module disable ngx_http_charset_module diff --git a/auto/sources b/auto/sources index 2abbc60..2e44ce1 100644 --- a/auto/sources +++ b/auto/sources @@ -254,9 +254,6 @@ NGX_WIN32_ICONS="src/os/win32/nginx.ico" NGX_WIN32_RC="src/os/win32/nginx.rc" -# the http modules that have their logging formats -# must be after ngx_http_log_module - HTTP_MODULES="ngx_http_module \ ngx_http_core_module \ ngx_http_log_module \ @@ -363,6 +360,10 @@ HTTP_USERID_FILTER_MODULE=ngx_http_userid_filter_module HTTP_USERID_SRCS=src/http/modules/ngx_http_userid_filter_module.c +HTTP_SLICE_FILTER_MODULE=ngx_http_slice_filter_module +HTTP_SLICE_SRCS=src/http/modules/ngx_http_slice_filter_module.c + + HTTP_REALIP_MODULE=ngx_http_realip_module HTTP_REALIP_SRCS=src/http/modules/ngx_http_realip_module.c diff --git a/auto/unix b/auto/unix index b7b7a25..7bfca8f 100755 --- a/auto/unix +++ b/auto/unix @@ -589,6 +589,22 @@ ngx_feature_test="char buf[1]; ssize_t n; n = pwrite(1, buf, 1, 0); . auto/feature +# pwritev() was introduced in FreeBSD 6 and Linux 2.6.30, glibc 2.10 + +ngx_feature="pwritev()" +ngx_feature_name="NGX_HAVE_PWRITEV" +ngx_feature_run=no +ngx_feature_incs='#include ' +ngx_feature_path= +ngx_feature_libs= +ngx_feature_test="char buf[1]; struct iovec vec[1]; ssize_t n; + vec[0].iov_base = buf; + vec[0].iov_len = 1; + n = pwritev(1, vec, 1, 0); + if (n == -1) return 1" +. auto/feature + + ngx_feature="sys_nerr" ngx_feature_name="NGX_SYS_NERR" ngx_feature_run=value diff --git a/src/core/nginx.h b/src/core/nginx.h index 56e9587..87a984a 100644 --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1009006 -#define NGINX_VERSION "1.9.6" +#define nginx_version 1009009 +#define NGINX_VERSION "1.9.9" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD diff --git a/src/core/ngx_conf_file.h b/src/core/ngx_conf_file.h index ee44306..2d03f43 100644 --- a/src/core/ngx_conf_file.h +++ b/src/core/ngx_conf_file.h @@ -50,7 +50,7 @@ #define NGX_DIRECT_CONF 0x00010000 #define NGX_MAIN_CONF 0x01000000 -#define NGX_ANY_CONF 0x0F000000 +#define NGX_ANY_CONF 0x1F000000 diff --git a/src/core/ngx_parse.c b/src/core/ngx_parse.c index d7350d4..7b60c5f 100644 --- a/src/core/ngx_parse.c +++ b/src/core/ngx_parse.c @@ -188,7 +188,7 @@ ngx_parse_time(ngx_str_t *line, ngx_uint_t is_sec) break; case 'm': - if (*p == 's') { + if (p < last && *p == 's') { if (is_sec || step >= st_msec) { return NGX_ERROR; } diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c index d2a8d01..cf665a4 100644 --- a/src/core/ngx_string.c +++ b/src/core/ngx_string.c @@ -410,7 +410,7 @@ ngx_vslprintf(u_char *buf, u_char *last, const char *fmt, va_list args) hex = 2; sign = 0; zero = '0'; - width = NGX_PTR_SIZE * 2; + width = 2 * sizeof(void *); break; case 'c': diff --git a/src/core/ngx_syslog.c b/src/core/ngx_syslog.c index d4e79f6..08f4c04 100644 --- a/src/core/ngx_syslog.c +++ b/src/core/ngx_syslog.c @@ -194,6 +194,9 @@ ngx_syslog_parse_args(ngx_conf_t *cf, ngx_syslog_peer_t *peer) peer->tag.data = p + 4; peer->tag.len = len - 4; + } else if (len == 10 && ngx_strncmp(p, "nohostname", 10) == 0) { + peer->nohostname = 1; + } else { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unknown syslog parameter \"%s\"", p); @@ -220,6 +223,11 @@ ngx_syslog_add_header(ngx_syslog_peer_t *peer, u_char *buf) pri = peer->facility * 8 + peer->severity; + if (peer->nohostname) { + return ngx_sprintf(buf, "<%ui>%V %V: ", pri, &ngx_cached_syslog_time, + &peer->tag); + } + return ngx_sprintf(buf, "<%ui>%V %V %V: ", pri, &ngx_cached_syslog_time, &ngx_cycle->hostname, &peer->tag); } diff --git a/src/core/ngx_syslog.h b/src/core/ngx_syslog.h index a915051..cc4c842 100644 --- a/src/core/ngx_syslog.h +++ b/src/core/ngx_syslog.h @@ -16,7 +16,8 @@ typedef struct { ngx_addr_t server; ngx_connection_t conn; - ngx_uint_t busy; /* unsigned busy:1; */ + unsigned busy:1; + unsigned nohostname:1; } ngx_syslog_peer_t; diff --git a/src/http/modules/ngx_http_chunked_filter_module.c b/src/http/modules/ngx_http_chunked_filter_module.c index a7dc5bf..0059a98 100644 --- a/src/http/modules/ngx_http_chunked_filter_module.c +++ b/src/http/modules/ngx_http_chunked_filter_module.c @@ -64,7 +64,7 @@ ngx_http_chunked_header_filter(ngx_http_request_t *r) || r->headers_out.status == NGX_HTTP_NO_CONTENT || r->headers_out.status < NGX_HTTP_OK || r != r->main - || (r->method & NGX_HTTP_HEAD)) + || r->method == NGX_HTTP_HEAD) { return ngx_http_next_header_filter(r); } diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c index 668719f..dbd7767 100644 --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -773,10 +773,11 @@ ngx_http_fastcgi_eval(ngx_http_request_t *r, ngx_http_fastcgi_loc_conf_t *flcf) } else { u->resolved->host = url.host; - u->resolved->port = url.port; - u->resolved->no_port = url.no_port; } + u->resolved->port = url.port; + u->resolved->no_port = url.no_port; + return NGX_OK; } diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c index 514c23b..a869e74 100644 --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -533,6 +533,13 @@ static ngx_command_t ngx_http_proxy_commands[] = { offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_revalidate), NULL }, + { ngx_string("proxy_cache_convert_head"), + 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_proxy_loc_conf_t, upstream.cache_convert_head), + NULL }, + #endif { ngx_string("proxy_temp_path"), @@ -1008,10 +1015,11 @@ ngx_http_proxy_eval(ngx_http_request_t *r, ngx_http_proxy_ctx_t *ctx, } else { u->resolved->host = url.host; - u->resolved->port = (in_port_t) (url.no_port ? port : url.port); - u->resolved->no_port = url.no_port; } + u->resolved->port = (in_port_t) (url.no_port ? port : url.port); + u->resolved->no_port = url.no_port; + return NGX_OK; } @@ -1149,25 +1157,24 @@ ngx_http_proxy_create_request(ngx_http_request_t *r) if (u->method.len) { /* HEAD was changed to GET to cache response */ method = u->method; - method.len++; } else if (plcf->method.len) { method = plcf->method; } else { method = r->method_name; - method.len++; } ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module); - if (method.len == 5 - && ngx_strncasecmp(method.data, (u_char *) "HEAD ", 5) == 0) + if (method.len == 4 + && ngx_strncasecmp(method.data, (u_char *) "HEAD", 4) == 0) { ctx->head = 1; } - len = method.len + sizeof(ngx_http_proxy_version) - 1 + sizeof(CRLF) - 1; + len = method.len + 1 + sizeof(ngx_http_proxy_version) - 1 + + sizeof(CRLF) - 1; escape = 0; loc_len = 0; @@ -1286,6 +1293,7 @@ ngx_http_proxy_create_request(ngx_http_request_t *r) /* the request line */ b->last = ngx_copy(b->last, method.data, method.len); + *b->last++ = ' '; u->uri.data = b->last; @@ -2845,6 +2853,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf) conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC; conf->upstream.cache_lock_age = NGX_CONF_UNSET_MSEC; conf->upstream.cache_revalidate = NGX_CONF_UNSET; + conf->upstream.cache_convert_head = NGX_CONF_UNSET; #endif conf->upstream.hide_headers = NGX_CONF_UNSET_PTR; @@ -3143,17 +3152,13 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_value(conf->upstream.cache_revalidate, prev->upstream.cache_revalidate, 0); + ngx_conf_merge_value(conf->upstream.cache_convert_head, + prev->upstream.cache_convert_head, 1); + #endif ngx_conf_merge_str_value(conf->method, prev->method, ""); - if (conf->method.len - && conf->method.data[conf->method.len - 1] != ' ') - { - conf->method.data[conf->method.len] = ' '; - conf->method.len++; - } - ngx_conf_merge_value(conf->upstream.pass_request_headers, prev->upstream.pass_request_headers, 1); ngx_conf_merge_value(conf->upstream.pass_request_body, diff --git a/src/http/modules/ngx_http_range_filter_module.c b/src/http/modules/ngx_http_range_filter_module.c index 952da75..b07b2e2 100644 --- a/src/http/modules/ngx_http_range_filter_module.c +++ b/src/http/modules/ngx_http_range_filter_module.c @@ -154,7 +154,7 @@ ngx_http_range_header_filter(ngx_http_request_t *r) if (r->http_version < NGX_HTTP_VERSION_10 || r->headers_out.status != NGX_HTTP_OK - || r != r->main + || (r != r->main && !r->subrequest_ranges) || r->headers_out.content_length_n == -1 || !r->allow_ranges) { @@ -222,6 +222,8 @@ parse: return NGX_ERROR; } + ctx->offset = r->headers_out.content_offset; + if (ngx_array_init(&ctx->ranges, r->pool, 1, sizeof(ngx_http_range_t)) != NGX_OK) { @@ -273,10 +275,21 @@ static ngx_int_t ngx_http_range_parse(ngx_http_request_t *r, ngx_http_range_filter_ctx_t *ctx, ngx_uint_t ranges) { - u_char *p; - off_t start, end, size, content_length, cutoff, cutlim; - ngx_uint_t suffix; - ngx_http_range_t *range; + u_char *p; + off_t start, end, size, content_length, cutoff, + cutlim; + ngx_uint_t suffix; + ngx_http_range_t *range; + ngx_http_range_filter_ctx_t *mctx; + + if (r != r->main) { + mctx = ngx_http_get_module_ctx(r->main, + ngx_http_range_body_filter_module); + if (mctx) { + ctx->ranges = mctx->ranges; + return NGX_OK; + } + } p = r->headers_in.range->value.data + 6; size = 0; @@ -395,6 +408,10 @@ ngx_http_range_singlepart_header(ngx_http_request_t *r, ngx_table_elt_t *content_range; ngx_http_range_t *range; + if (r != r->main) { + return ngx_http_next_header_filter(r); + } + content_range = ngx_list_push(&r->headers_out.headers); if (content_range == NULL) { return NGX_ERROR; @@ -422,6 +439,7 @@ ngx_http_range_singlepart_header(ngx_http_request_t *r, - content_range->value.data; r->headers_out.content_length_n = range->end - range->start; + r->headers_out.content_offset = range->start; if (r->headers_out.content_length) { r->headers_out.content_length->hash = 0; diff --git a/src/http/modules/ngx_http_realip_module.c b/src/http/modules/ngx_http_realip_module.c index 7a62118..c3d7ebe 100644 --- a/src/http/modules/ngx_http_realip_module.c +++ b/src/http/modules/ngx_http_realip_module.c @@ -43,9 +43,14 @@ static char *ngx_http_realip(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static void *ngx_http_realip_create_loc_conf(ngx_conf_t *cf); static char *ngx_http_realip_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child); +static ngx_int_t ngx_http_realip_add_variables(ngx_conf_t *cf); static ngx_int_t ngx_http_realip_init(ngx_conf_t *cf); +static ngx_int_t ngx_http_realip_remote_addr_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); + + static ngx_command_t ngx_http_realip_commands[] = { { ngx_string("set_real_ip_from"), @@ -75,7 +80,7 @@ static ngx_command_t ngx_http_realip_commands[] = { static ngx_http_module_t ngx_http_realip_module_ctx = { - NULL, /* preconfiguration */ + ngx_http_realip_add_variables, /* preconfiguration */ ngx_http_realip_init, /* postconfiguration */ NULL, /* create main configuration */ @@ -105,6 +110,15 @@ ngx_module_t ngx_http_realip_module = { }; +static ngx_http_variable_t ngx_http_realip_vars[] = { + + { ngx_string("realip_remote_addr"), NULL, + ngx_http_realip_remote_addr_variable, 0, 0, 0 }, + + { ngx_null_string, NULL, NULL, 0, 0, 0 } +}; + + static ngx_int_t ngx_http_realip_handler(ngx_http_request_t *r) { @@ -416,6 +430,25 @@ ngx_http_realip_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) } +static ngx_int_t +ngx_http_realip_add_variables(ngx_conf_t *cf) +{ + ngx_http_variable_t *var, *v; + + for (v = ngx_http_realip_vars; v->name.len; v++) { + var = ngx_http_add_variable(cf, &v->name, v->flags); + if (var == NULL) { + return NGX_ERROR; + } + + var->get_handler = v->get_handler; + var->data = v->data; + } + + return NGX_OK; +} + + static ngx_int_t ngx_http_realip_init(ngx_conf_t *cf) { @@ -440,3 +473,40 @@ ngx_http_realip_init(ngx_conf_t *cf) return NGX_OK; } + + +static ngx_int_t +ngx_http_realip_remote_addr_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_str_t *addr_text; + ngx_pool_cleanup_t *cln; + ngx_http_realip_ctx_t *ctx; + + ctx = ngx_http_get_module_ctx(r, ngx_http_realip_module); + + if (ctx == NULL && (r->internal || r->filter_finalize)) { + + /* + * if module context was reset, the original address + * can still be found in the cleanup handler + */ + + for (cln = r->pool->cleanup; cln; cln = cln->next) { + if (cln->handler == ngx_http_realip_cleanup) { + ctx = cln->data; + break; + } + } + } + + addr_text = ctx ? &ctx->addr_text : &r->connection->addr_text; + + v->len = addr_text->len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = addr_text->data; + + return NGX_OK; +} diff --git a/src/http/modules/ngx_http_scgi_module.c b/src/http/modules/ngx_http_scgi_module.c index 6e5b077..76c7786 100644 --- a/src/http/modules/ngx_http_scgi_module.c +++ b/src/http/modules/ngx_http_scgi_module.c @@ -569,10 +569,11 @@ ngx_http_scgi_eval(ngx_http_request_t *r, ngx_http_scgi_loc_conf_t * scf) } else { u->resolved->host = url.host; - u->resolved->port = url.port; - u->resolved->no_port = url.no_port; } + u->resolved->port = url.port; + u->resolved->no_port = url.no_port; + return NGX_OK; } diff --git a/src/http/modules/ngx_http_slice_filter_module.c b/src/http/modules/ngx_http_slice_filter_module.c new file mode 100644 index 0000000..5e149b4 --- /dev/null +++ b/src/http/modules/ngx_http_slice_filter_module.c @@ -0,0 +1,526 @@ + +/* + * Copyright (C) Roman Arutyunyan + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + + +typedef struct { + size_t size; +} ngx_http_slice_loc_conf_t; + + +typedef struct { + off_t start; + off_t end; + ngx_str_t range; + ngx_str_t etag; + ngx_uint_t last; /* unsigned last:1; */ +} ngx_http_slice_ctx_t; + + +typedef struct { + off_t start; + off_t end; + off_t complete_length; +} ngx_http_slice_content_range_t; + + +static ngx_int_t ngx_http_slice_header_filter(ngx_http_request_t *r); +static ngx_int_t ngx_http_slice_body_filter(ngx_http_request_t *r, + ngx_chain_t *in); +static ngx_int_t ngx_http_slice_parse_content_range(ngx_http_request_t *r, + ngx_http_slice_content_range_t *cr); +static ngx_int_t ngx_http_slice_range_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static off_t ngx_http_slice_get_start(ngx_http_request_t *r); +static void *ngx_http_slice_create_loc_conf(ngx_conf_t *cf); +static char *ngx_http_slice_merge_loc_conf(ngx_conf_t *cf, void *parent, + void *child); +static ngx_int_t ngx_http_slice_add_variables(ngx_conf_t *cf); +static ngx_int_t ngx_http_slice_init(ngx_conf_t *cf); + + +static ngx_command_t ngx_http_slice_filter_commands[] = { + + { ngx_string("slice"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_slice_loc_conf_t, size), + NULL }, + + ngx_null_command +}; + + +static ngx_http_module_t ngx_http_slice_filter_module_ctx = { + ngx_http_slice_add_variables, /* preconfiguration */ + ngx_http_slice_init, /* postconfiguration */ + + NULL, /* create main configuration */ + NULL, /* init main configuration */ + + NULL, /* create server configuration */ + NULL, /* merge server configuration */ + + ngx_http_slice_create_loc_conf, /* create location configuration */ + ngx_http_slice_merge_loc_conf /* merge location configuration */ +}; + + +ngx_module_t ngx_http_slice_filter_module = { + NGX_MODULE_V1, + &ngx_http_slice_filter_module_ctx, /* module context */ + ngx_http_slice_filter_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_str_t ngx_http_slice_range_name = ngx_string("slice_range"); + +static ngx_http_output_header_filter_pt ngx_http_next_header_filter; +static ngx_http_output_body_filter_pt ngx_http_next_body_filter; + + +static ngx_int_t +ngx_http_slice_header_filter(ngx_http_request_t *r) +{ + off_t end; + ngx_int_t rc; + ngx_table_elt_t *h; + ngx_http_slice_ctx_t *ctx; + ngx_http_slice_loc_conf_t *slcf; + ngx_http_slice_content_range_t cr; + + ctx = ngx_http_get_module_ctx(r, ngx_http_slice_filter_module); + if (ctx == NULL) { + return ngx_http_next_header_filter(r); + } + + if (r->headers_out.status != NGX_HTTP_PARTIAL_CONTENT) { + if (r == r->main) { + ngx_http_set_ctx(r, NULL, ngx_http_slice_filter_module); + return ngx_http_next_header_filter(r); + } + + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "unexpected status code %ui in slice response", + r->headers_out.status); + return NGX_ERROR; + } + + h = r->headers_out.etag; + + if (ctx->etag.len) { + if (h == NULL + || h->value.len != ctx->etag.len + || ngx_strncmp(h->value.data, ctx->etag.data, ctx->etag.len) + != 0) + { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "etag mismatch in slice response"); + return NGX_ERROR; + } + } + + if (h) { + ctx->etag = h->value; + } + + if (ngx_http_slice_parse_content_range(r, &cr) != NGX_OK) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "invalid range in slice response"); + return NGX_ERROR; + } + + if (cr.complete_length == -1) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "no complete length in slice response"); + return NGX_ERROR; + } + + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http slice response range: %O-%O/%O", + cr.start, cr.end, cr.complete_length); + + slcf = ngx_http_get_module_loc_conf(r, ngx_http_slice_filter_module); + + end = ngx_min(cr.start + (off_t) slcf->size, cr.complete_length); + + if (cr.start != ctx->start || cr.end != end) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "unexpected range in slice response: %O-%O", + cr.start, cr.end); + return NGX_ERROR; + } + + ctx->start = end; + + r->headers_out.status = NGX_HTTP_OK; + r->headers_out.status_line.len = 0; + r->headers_out.content_length_n = cr.complete_length; + r->headers_out.content_offset = cr.start; + r->headers_out.content_range->hash = 0; + r->headers_out.content_range = NULL; + + r->allow_ranges = 1; + r->subrequest_ranges = 1; + r->single_range = 1; + + rc = ngx_http_next_header_filter(r); + + if (r != r->main) { + return rc; + } + + if (r->headers_out.status == NGX_HTTP_PARTIAL_CONTENT) { + if (ctx->start + (off_t) slcf->size <= r->headers_out.content_offset) { + ctx->start = slcf->size + * (r->headers_out.content_offset / slcf->size); + } + + ctx->end = r->headers_out.content_offset + + r->headers_out.content_length_n; + + } else { + ctx->end = cr.complete_length; + } + + return rc; +} + + +static ngx_int_t +ngx_http_slice_body_filter(ngx_http_request_t *r, ngx_chain_t *in) +{ + ngx_int_t rc; + ngx_chain_t *cl; + ngx_http_request_t *sr; + ngx_http_slice_ctx_t *ctx; + ngx_http_slice_loc_conf_t *slcf; + + ctx = ngx_http_get_module_ctx(r, ngx_http_slice_filter_module); + + if (ctx == NULL || r != r->main) { + return ngx_http_next_body_filter(r, in); + } + + for (cl = in; cl; cl = cl->next) { + if (cl->buf->last_buf) { + cl->buf->last_buf = 0; + cl->buf->last_in_chain = 1; + cl->buf->sync = 1; + ctx->last = 1; + } + } + + rc = ngx_http_next_body_filter(r, in); + + if (rc == NGX_ERROR || !ctx->last) { + return rc; + } + + if (ctx->start >= ctx->end) { + ngx_http_set_ctx(r, NULL, ngx_http_slice_filter_module); + ngx_http_send_special(r, NGX_HTTP_LAST); + return rc; + } + + if (r->buffered) { + return rc; + } + + if (ngx_http_subrequest(r, &r->uri, &r->args, &sr, NULL, 0) != NGX_OK) { + return NGX_ERROR; + } + + ngx_http_set_ctx(sr, ctx, ngx_http_slice_filter_module); + + slcf = ngx_http_get_module_loc_conf(r, ngx_http_slice_filter_module); + + ctx->range.len = ngx_sprintf(ctx->range.data, "bytes=%O-%O", ctx->start, + ctx->start + (off_t) slcf->size - 1) + - ctx->range.data; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http slice subrequest: \"%V\"", &ctx->range); + + return rc; +} + + +static ngx_int_t +ngx_http_slice_parse_content_range(ngx_http_request_t *r, + ngx_http_slice_content_range_t *cr) +{ + off_t start, end, complete_length, cutoff, cutlim; + u_char *p; + ngx_table_elt_t *h; + + h = r->headers_out.content_range; + + if (h == NULL + || h->value.len < 7 + || ngx_strncmp(h->value.data, "bytes ", 6) != 0) + { + return NGX_ERROR; + } + + p = h->value.data + 6; + + cutoff = NGX_MAX_OFF_T_VALUE / 10; + cutlim = NGX_MAX_OFF_T_VALUE % 10; + + start = 0; + end = 0; + complete_length = 0; + + while (*p == ' ') { p++; } + + if (*p < '0' || *p > '9') { + return NGX_ERROR; + } + + while (*p >= '0' && *p <= '9') { + if (start >= cutoff && (start > cutoff || *p - '0' > cutlim)) { + return NGX_ERROR; + } + + start = start * 10 + *p++ - '0'; + } + + while (*p == ' ') { p++; } + + if (*p++ != '-') { + return NGX_ERROR; + } + + while (*p == ' ') { p++; } + + if (*p < '0' || *p > '9') { + return NGX_ERROR; + } + + while (*p >= '0' && *p <= '9') { + if (end >= cutoff && (end > cutoff || *p - '0' > cutlim)) { + return NGX_ERROR; + } + + end = end * 10 + *p++ - '0'; + } + + end++; + + while (*p == ' ') { p++; } + + if (*p++ != '/') { + return NGX_ERROR; + } + + while (*p == ' ') { p++; } + + if (*p != '*') { + if (*p < '0' || *p > '9') { + return NGX_ERROR; + } + + while (*p >= '0' && *p <= '9') { + if (complete_length >= cutoff + && (complete_length > cutoff || *p - '0' > cutlim)) + { + return NGX_ERROR; + } + + complete_length = complete_length * 10 + *p++ - '0'; + } + + } else { + complete_length = -1; + p++; + } + + while (*p == ' ') { p++; } + + if (*p != '\0') { + return NGX_ERROR; + } + + cr->start = start; + cr->end = end; + cr->complete_length = complete_length; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_slice_range_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + u_char *p; + ngx_http_slice_ctx_t *ctx; + ngx_http_slice_loc_conf_t *slcf; + + ctx = ngx_http_get_module_ctx(r, ngx_http_slice_filter_module); + + if (ctx == NULL) { + if (r != r->main || r->headers_out.status) { + v->not_found = 1; + return NGX_OK; + } + + slcf = ngx_http_get_module_loc_conf(r, ngx_http_slice_filter_module); + + if (slcf->size == 0) { + v->not_found = 1; + return NGX_OK; + } + + ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_slice_ctx_t)); + if (ctx == NULL) { + return NGX_ERROR; + } + + ngx_http_set_ctx(r, ctx, ngx_http_slice_filter_module); + + p = ngx_pnalloc(r->pool, sizeof("bytes=-") - 1 + 2 * NGX_OFF_T_LEN); + if (p == NULL) { + return NGX_ERROR; + } + + ctx->start = slcf->size * (ngx_http_slice_get_start(r) / slcf->size); + + ctx->range.data = p; + ctx->range.len = ngx_sprintf(p, "bytes=%O-%O", ctx->start, + ctx->start + (off_t) slcf->size - 1) + - p; + } + + v->data = ctx->range.data; + v->valid = 1; + v->not_found = 0; + v->no_cacheable = 1; + v->len = ctx->range.len; + + return NGX_OK; +} + + +static off_t +ngx_http_slice_get_start(ngx_http_request_t *r) +{ + off_t start, cutoff, cutlim; + u_char *p; + ngx_table_elt_t *h; + + if (r->headers_in.if_range) { + return 0; + } + + h = r->headers_in.range; + + if (h == NULL + || h->value.len < 7 + || ngx_strncasecmp(h->value.data, (u_char *) "bytes=", 6) != 0) + { + return 0; + } + + p = h->value.data + 6; + + if (ngx_strchr(p, ',')) { + return 0; + } + + while (*p == ' ') { p++; } + + if (*p == '-') { + return 0; + } + + cutoff = NGX_MAX_OFF_T_VALUE / 10; + cutlim = NGX_MAX_OFF_T_VALUE % 10; + + start = 0; + + while (*p >= '0' && *p <= '9') { + if (start >= cutoff && (start > cutoff || *p - '0' > cutlim)) { + return 0; + } + + start = start * 10 + *p++ - '0'; + } + + return start; +} + + +static void * +ngx_http_slice_create_loc_conf(ngx_conf_t *cf) +{ + ngx_http_slice_loc_conf_t *slcf; + + slcf = ngx_palloc(cf->pool, sizeof(ngx_http_slice_loc_conf_t)); + if (slcf == NULL) { + return NULL; + } + + slcf->size = NGX_CONF_UNSET_SIZE; + + return slcf; +} + + +static char * +ngx_http_slice_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) +{ + ngx_http_slice_loc_conf_t *prev = parent; + ngx_http_slice_loc_conf_t *conf = child; + + ngx_conf_merge_size_value(conf->size, prev->size, 0); + + return NGX_CONF_OK; +} + + +static ngx_int_t +ngx_http_slice_add_variables(ngx_conf_t *cf) +{ + ngx_http_variable_t *var; + + var = ngx_http_add_variable(cf, &ngx_http_slice_range_name, 0); + if (var == NULL) { + return NGX_ERROR; + } + + var->get_handler = ngx_http_slice_range_variable; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_slice_init(ngx_conf_t *cf) +{ + ngx_http_next_header_filter = ngx_http_top_header_filter; + ngx_http_top_header_filter = ngx_http_slice_header_filter; + + ngx_http_next_body_filter = ngx_http_top_body_filter; + ngx_http_top_body_filter = ngx_http_slice_body_filter; + + return NGX_OK; +} diff --git a/src/http/modules/ngx_http_static_module.c b/src/http/modules/ngx_http_static_module.c index 631eb17..f79c4ae 100644 --- a/src/http/modules/ngx_http_static_module.c +++ b/src/http/modules/ngx_http_static_module.c @@ -204,7 +204,7 @@ ngx_http_static_handler(ngx_http_request_t *r) #endif - if (r->method & NGX_HTTP_POST) { + if (r->method == NGX_HTTP_POST) { return NGX_HTTP_NOT_ALLOWED; } diff --git a/src/http/modules/ngx_http_stub_status_module.c b/src/http/modules/ngx_http_stub_status_module.c index dd68358..61199f2 100644 --- a/src/http/modules/ngx_http_stub_status_module.c +++ b/src/http/modules/ngx_http_stub_status_module.c @@ -89,7 +89,7 @@ ngx_http_stub_status_handler(ngx_http_request_t *r) ngx_chain_t out; ngx_atomic_int_t ap, hn, ac, rq, rd, wr, wa; - if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) { + if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { return NGX_HTTP_NOT_ALLOWED; } diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c index a50c553..0313dfa 100644 --- a/src/http/modules/ngx_http_uwsgi_module.c +++ b/src/http/modules/ngx_http_uwsgi_module.c @@ -771,10 +771,11 @@ ngx_http_uwsgi_eval(ngx_http_request_t *r, ngx_http_uwsgi_loc_conf_t * uwcf) } else { u->resolved->host = url.host; - u->resolved->port = url.port; - u->resolved->no_port = url.no_port; } + u->resolved->port = url.port; + u->resolved->no_port = url.no_port; + return NGX_OK; } diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index 7a29608..4b8dd4c 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -776,7 +776,7 @@ ngx_module_t ngx_http_core_module = { }; -ngx_str_t ngx_http_core_get_method = { 3, (u_char *) "GET " }; +ngx_str_t ngx_http_core_get_method = { 3, (u_char *) "GET" }; void @@ -3503,7 +3503,7 @@ ngx_http_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) /* TODO: it does not merge, it inits only */ ngx_conf_merge_size_value(conf->connection_pool_size, - prev->connection_pool_size, 256); + prev->connection_pool_size, 64 * sizeof(void *)); ngx_conf_merge_size_value(conf->request_pool_size, prev->request_pool_size, 4096); ngx_conf_merge_msec_value(conf->client_header_timeout, diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c index 9da972e..99e9325 100644 --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -768,25 +768,31 @@ ngx_http_ssl_handshake_handler(ngx_connection_t *c) && (defined TLSEXT_TYPE_application_layer_protocol_negotiation \ || defined TLSEXT_TYPE_next_proto_neg)) { - unsigned int len; - const unsigned char *data; + unsigned int len; + const unsigned char *data; + ngx_http_connection_t *hc; + + hc = c->data; + + if (hc->addr_conf->http2) { #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation - SSL_get0_alpn_selected(c->ssl->connection, &data, &len); + SSL_get0_alpn_selected(c->ssl->connection, &data, &len); #ifdef TLSEXT_TYPE_next_proto_neg - if (len == 0) { - SSL_get0_next_proto_negotiated(c->ssl->connection, &data, &len); - } + if (len == 0) { + SSL_get0_next_proto_negotiated(c->ssl->connection, &data, &len); + } #endif #else /* TLSEXT_TYPE_next_proto_neg */ - SSL_get0_next_proto_negotiated(c->ssl->connection, &data, &len); + SSL_get0_next_proto_negotiated(c->ssl->connection, &data, &len); #endif - if (len == 2 && data[0] == 'h' && data[1] == '2') { - ngx_http_v2_init(c->read); - return; + if (len == 2 && data[0] == 'h' && data[1] == '2') { + ngx_http_v2_init(c->read); + return; + } } } #endif @@ -831,6 +837,10 @@ ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg) c = ngx_ssl_get_connection(ssl_conn); + if (c->ssl->renegotiation) { + return SSL_TLSEXT_ERR_NOACK; + } + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "SSL server name: \"%s\"", servername); @@ -1782,7 +1792,7 @@ ngx_http_process_request_header(ngx_http_request_t *r) } } - if (r->method & NGX_HTTP_TRACE) { + if (r->method == NGX_HTTP_TRACE) { ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "client sent TRACE method"); ngx_http_finalize_request(r, NGX_HTTP_NOT_ALLOWED); diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h index 967032a..8b88139 100644 --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -271,6 +271,7 @@ typedef struct { ngx_array_t cache_control; off_t content_length_n; + off_t content_offset; time_t date_time; time_t last_modified_time; } ngx_http_headers_out_t; @@ -530,6 +531,7 @@ struct ngx_http_request_s { unsigned filter_need_in_memory:1; unsigned filter_need_temporary:1; unsigned allow_ranges:1; + unsigned subrequest_ranges:1; unsigned single_range:1; unsigned disable_not_modified:1; diff --git a/src/http/ngx_http_special_response.c b/src/http/ngx_http_special_response.c index a97791e..2771e58 100644 --- a/src/http/ngx_http_special_response.c +++ b/src/http/ngx_http_special_response.c @@ -359,9 +359,6 @@ static ngx_str_t ngx_http_error_pages[] = { }; -static ngx_str_t ngx_http_get_name = { 3, (u_char *) "GET " }; - - ngx_int_t ngx_http_special_response_handler(ngx_http_request_t *r, ngx_int_t error) { @@ -564,7 +561,7 @@ ngx_http_send_error_page(ngx_http_request_t *r, ngx_http_err_page_t *err_page) if (r->method != NGX_HTTP_HEAD) { r->method = NGX_HTTP_GET; - r->method_name = ngx_http_get_name; + r->method_name = ngx_http_core_get_method; } return ngx_http_internal_redirect(r, &uri, &args); diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c index 1530596..6c6ee80 100644 --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -250,6 +250,11 @@ ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = { ngx_http_upstream_copy_allow_ranges, offsetof(ngx_http_headers_out_t, accept_ranges), 1 }, + { ngx_string("Content-Range"), + ngx_http_upstream_ignore_header_line, 0, + ngx_http_upstream_copy_header_line, + offsetof(ngx_http_headers_out_t, content_range), 0 }, + { ngx_string("Connection"), ngx_http_upstream_process_connection, 0, ngx_http_upstream_ignore_header_line, 0, 0 }, @@ -633,8 +638,20 @@ ngx_http_upstream_init_request(ngx_http_request_t *r) u->ssl_name = u->resolved->host; #endif + host = &u->resolved->host; + if (u->resolved->sockaddr) { + if (u->resolved->port == 0 + && u->resolved->sockaddr->sa_family != AF_UNIX) + { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "no port in upstream \"%V\"", host); + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + if (ngx_http_upstream_create_round_robin_peer(r, u->resolved) != NGX_OK) { @@ -648,8 +665,6 @@ ngx_http_upstream_init_request(ngx_http_request_t *r) return; } - host = &u->resolved->host; - umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module); uscfp = umcf->upstreams.elts; @@ -764,7 +779,7 @@ ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u) return rc; } - if (r->method & NGX_HTTP_HEAD) { + if (r->method == NGX_HTTP_HEAD && u->conf->cache_convert_head) { u->method = ngx_http_core_get_method; } diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h index 64157e6..8404265 100644 --- a/src/http/ngx_http_upstream.h +++ b/src/http/ngx_http_upstream.h @@ -193,6 +193,7 @@ typedef struct { ngx_msec_t cache_lock_age; ngx_flag_t cache_revalidate; + ngx_flag_t cache_convert_head; ngx_array_t *cache_valid; ngx_array_t *cache_bypass; diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c index 10cb727..869ce08 100644 --- a/src/http/v2/ngx_http_v2.c +++ b/src/http/v2/ngx_http_v2.c @@ -870,8 +870,6 @@ ngx_http_v2_state_data(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end) return ngx_http_v2_state_skip_padded(h2c, pos, end); } - stream->in_closed = h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG; - h2c->state.stream = stream; return ngx_http_v2_state_read_data(h2c, pos, end); @@ -899,6 +897,8 @@ ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos, } if (stream->skip_data) { + stream->in_closed = h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG; + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, "skipping http2 DATA frame, reason: %d", stream->skip_data); @@ -988,7 +988,9 @@ ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos, ngx_http_v2_state_read_data); } - if (stream->in_closed) { + if (h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG) { + stream->in_closed = 1; + if (r->headers_in.content_length_n < 0) { r->headers_in.content_length_n = rb->rest; @@ -1204,10 +1206,9 @@ static u_char * ngx_http_v2_state_header_block(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end) { - u_char ch; - ngx_int_t value; - ngx_uint_t indexed, size_update, prefix; - ngx_http_v2_srv_conf_t *h2scf; + u_char ch; + ngx_int_t value; + ngx_uint_t indexed, size_update, prefix; if (end - pos < 1) { return ngx_http_v2_state_save(h2c, pos, end, @@ -1288,20 +1289,11 @@ ngx_http_v2_state_header_block(ngx_http_v2_connection_t *h2c, u_char *pos, return ngx_http_v2_state_header_complete(h2c, pos, end); } - h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, - ngx_http_v2_module); - - h2c->state.field_limit = h2scf->max_field_size; - if (value == 0) { h2c->state.parse_name = 1; - } else { - if (ngx_http_v2_get_indexed_header(h2c, value, 1) != NGX_OK) { - return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_COMP_ERROR); - } - - h2c->state.field_limit -= h2c->state.header.name.len; + } else if (ngx_http_v2_get_indexed_header(h2c, value, 1) != NGX_OK) { + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_COMP_ERROR); } h2c->state.parse_value = 1; @@ -1314,9 +1306,10 @@ static u_char * ngx_http_v2_state_field_len(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end) { - size_t alloc; - ngx_int_t len; - ngx_uint_t huff; + size_t alloc; + ngx_int_t len; + ngx_uint_t huff; + ngx_http_v2_srv_conf_t *h2scf; if (!(h2c->state.flags & NGX_HTTP_V2_END_HEADERS_FLAG) && h2c->state.length < NGX_HTTP_V2_INT_OCTETS) @@ -1363,14 +1356,16 @@ ngx_http_v2_state_field_len(ngx_http_v2_connection_t *h2c, u_char *pos, "http2 hpack %s string length: %i", huff ? "encoded" : "raw", len); - if ((size_t) len > h2c->state.field_limit) { + h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, + ngx_http_v2_module); + + if ((size_t) len > h2scf->max_field_size) { ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, "client exceeded http2_max_field_size limit"); return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_ENHANCE_YOUR_CALM); } - h2c->state.field_limit -= len; h2c->state.field_rest = len; if (h2c->state.stream == NULL && !h2c->state.index) { @@ -1664,7 +1659,7 @@ ngx_http_v2_state_process_header(ngx_http_v2_connection_t *h2c, u_char *pos, h->key.len = header->name.len; h->key.data = header->name.data; - /* TODO Optimization: precalculate hash and hadnler for indexed headers. */ + /* TODO Optimization: precalculate hash and handler for indexed headers. */ h->hash = ngx_hash_key(h->key.data, h->key.len); h->value.len = header->value.len; @@ -1818,7 +1813,7 @@ ngx_http_v2_state_priority(ngx_http_v2_connection_t *h2c, u_char *pos, if (depend == h2c->state.sid) { ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, "client sent PRIORITY frame for stream %ui " - "with incorrect dependancy", h2c->state.sid); + "with incorrect dependency", h2c->state.sid); node = ngx_http_v2_get_node_by_id(h2c, h2c->state.sid, 0); @@ -2954,6 +2949,8 @@ ngx_http_v2_validate_header(ngx_http_request_t *r, ngx_http_v2_header_t *header) return NGX_ERROR; } + r->invalid_header = 0; + cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); for (i = (header->name.data[0] == ':'); i != header->name.len; i++) { @@ -3297,9 +3294,6 @@ ngx_http_v2_construct_request_line(ngx_http_request_t *r) ngx_memcpy(p, ending, sizeof(ending)); - /* some modules expect the space character after method name */ - r->method_name.data = r->request_line.data; - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http2 http request line: \"%V\"", &r->request_line); diff --git a/src/http/v2/ngx_http_v2.h b/src/http/v2/ngx_http_v2.h index 462d254..4c63b21 100644 --- a/src/http/v2/ngx_http_v2.h +++ b/src/http/v2/ngx_http_v2.h @@ -80,7 +80,6 @@ typedef struct { unsigned index:1; ngx_http_v2_header_t header; size_t header_limit; - size_t field_limit; u_char field_state; u_char *field_start; u_char *field_end; @@ -179,7 +178,7 @@ struct ngx_http_v2_stream_s { size_t recv_window; ngx_http_v2_out_frame_t *free_frames; - ngx_chain_t *free_data_headers; + ngx_chain_t *free_frame_headers; ngx_chain_t *free_bufs; ngx_queue_t queue; diff --git a/src/http/v2/ngx_http_v2_filter_module.c b/src/http/v2/ngx_http_v2_filter_module.c index a866cde..ed30fe5 100644 --- a/src/http/v2/ngx_http_v2_filter_module.c +++ b/src/http/v2/ngx_http_v2_filter_module.c @@ -624,6 +624,8 @@ ngx_http_v2_create_headers_frame(ngx_http_request_t *r, u_char *pos, *b->last++ = flags; b->last = ngx_http_v2_write_sid(b->last, stream->node->id); + b->tag = (ngx_buf_tag_t) &ngx_http_v2_module; + cl = ngx_alloc_chain_link(r->pool); if (cl == NULL) { return NULL; @@ -929,7 +931,7 @@ ngx_http_v2_filter_get_data_frame(ngx_http_v2_stream_t *stream, stream->node->id, frame, len, (ngx_uint_t) flags); cl = ngx_chain_get_free_buf(stream->request->pool, - &stream->free_data_headers); + &stream->free_frame_headers); if (cl == NULL) { return NULL; } @@ -946,7 +948,7 @@ ngx_http_v2_filter_get_data_frame(ngx_http_v2_stream_t *stream, buf->end = buf->start + NGX_HTTP_V2_FRAME_HEADER_SIZE; buf->last = buf->end; - buf->tag = (ngx_buf_tag_t) &ngx_http_v2_filter_get_data_frame; + buf->tag = (ngx_buf_tag_t) &ngx_http_v2_module; buf->memory = 1; } @@ -1054,23 +1056,45 @@ static ngx_int_t ngx_http_v2_headers_frame_handler(ngx_http_v2_connection_t *h2c, ngx_http_v2_out_frame_t *frame) { - ngx_buf_t *buf; + ngx_chain_t *cl, *ln; ngx_http_v2_stream_t *stream; - buf = frame->first->buf; - - if (buf->pos != buf->last) { - return NGX_AGAIN; - } - stream = frame->stream; + cl = frame->first; + + for ( ;; ) { + if (cl->buf->pos != cl->buf->last) { + frame->first = cl; + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "http2:%ui HEADERS frame %p was sent partially", + stream->node->id, frame); + + return NGX_AGAIN; + } + + ln = cl->next; + + if (cl->buf->tag == (ngx_buf_tag_t) &ngx_http_v2_module) { + cl->next = stream->free_frame_headers; + stream->free_frame_headers = cl; + + } else { + cl->next = stream->free_bufs; + stream->free_bufs = cl; + } + + if (cl == frame->last) { + break; + } + + cl = ln; + } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, "http2:%ui HEADERS frame %p was sent", stream->node->id, frame); - ngx_free_chain(stream->request->pool, frame->first); - ngx_http_v2_handle_frame(stream, frame); ngx_http_v2_handle_stream(h2c, stream); @@ -1091,7 +1115,7 @@ ngx_http_v2_data_frame_handler(ngx_http_v2_connection_t *h2c, cl = frame->first; - if (cl->buf->tag == (ngx_buf_tag_t) &ngx_http_v2_filter_get_data_frame) { + if (cl->buf->tag == (ngx_buf_tag_t) &ngx_http_v2_module) { if (cl->buf->pos != cl->buf->last) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, @@ -1103,8 +1127,8 @@ ngx_http_v2_data_frame_handler(ngx_http_v2_connection_t *h2c, ln = cl->next; - cl->next = stream->free_data_headers; - stream->free_data_headers = cl; + cl->next = stream->free_frame_headers; + stream->free_frame_headers = cl; if (cl == frame->last) { goto done; diff --git a/src/os/unix/ngx_files.c b/src/os/unix/ngx_files.c index 417b598..00a6a49 100644 --- a/src/os/unix/ngx_files.c +++ b/src/os/unix/ngx_files.c @@ -14,6 +14,9 @@ static void ngx_thread_read_handler(void *data, ngx_log_t *log); #endif +static ssize_t ngx_writev_file(ngx_file_t *file, ngx_array_t *vec, size_t size, + off_t offset); + #if (NGX_HAVE_FILE_AIO) @@ -176,7 +179,8 @@ ngx_thread_read_handler(void *data, ngx_log_t *log) ssize_t ngx_write_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset) { - ssize_t n, written; + ssize_t n, written; + ngx_err_t err; ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0, "write: %d, %p, %uz, %O", file->fd, buf, size, offset); @@ -189,7 +193,15 @@ ngx_write_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset) n = pwrite(file->fd, buf + written, size, offset); if (n == -1) { - ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, + err = ngx_errno; + + if (err == NGX_EINTR) { + ngx_log_debug0(NGX_LOG_DEBUG_CORE, file->log, err, + "pwrite() was interrupted"); + continue; + } + + ngx_log_error(NGX_LOG_CRIT, file->log, err, "pwrite() \"%s\" failed", file->name.data); return NGX_ERROR; } @@ -221,11 +233,20 @@ ngx_write_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset) n = write(file->fd, buf + written, size); if (n == -1) { - ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, + err = ngx_errno; + + if (err == NGX_EINTR) { + ngx_log_debug0(NGX_LOG_DEBUG_CORE, file->log, err, + "write() was interrupted"); + continue; + } + + ngx_log_error(NGX_LOG_CRIT, file->log, err, "write() \"%s\" failed", file->name.data); return NGX_ERROR; } + file->sys_offset += n; file->offset += n; written += n; @@ -264,7 +285,6 @@ ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl, off_t offset, u_char *prev; size_t size; ssize_t total, n; - ngx_err_t err; ngx_array_t vec; struct iovec *iov, iovs[NGX_IOVS]; @@ -326,46 +346,12 @@ ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl, off_t offset, return total + n; } - if (file->sys_offset != offset) { - if (lseek(file->fd, offset, SEEK_SET) == -1) { - ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, - "lseek() \"%s\" failed", file->name.data); - return NGX_ERROR; - } + n = ngx_writev_file(file, &vec, size, offset); - file->sys_offset = offset; + if (n == NGX_ERROR) { + return n; } -eintr: - - n = writev(file->fd, vec.elts, vec.nelts); - - if (n == -1) { - err = ngx_errno; - - if (err == NGX_EINTR) { - ngx_log_debug0(NGX_LOG_DEBUG_CORE, file->log, err, - "writev() was interrupted"); - goto eintr; - } - - ngx_log_error(NGX_LOG_CRIT, file->log, err, - "writev() \"%s\" failed", file->name.data); - return NGX_ERROR; - } - - if ((size_t) n != size) { - ngx_log_error(NGX_LOG_CRIT, file->log, 0, - "writev() \"%s\" has written only %z of %uz", - file->name.data, n, size); - return NGX_ERROR; - } - - ngx_log_debug2(NGX_LOG_DEBUG_CORE, file->log, 0, - "writev: %d, %z", file->fd, n); - - file->sys_offset += n; - file->offset += n; offset += n; total += n; @@ -375,6 +361,89 @@ eintr: } +static ssize_t +ngx_writev_file(ngx_file_t *file, ngx_array_t *vec, size_t size, off_t offset) +{ + ssize_t n; + ngx_err_t err; + + ngx_log_debug3(NGX_LOG_DEBUG_CORE, file->log, 0, + "writev: %d, %uz, %O", file->fd, size, offset); + +#if (NGX_HAVE_PWRITEV) + +eintr: + + n = pwritev(file->fd, vec->elts, vec->nelts, offset); + + if (n == -1) { + err = ngx_errno; + + if (err == NGX_EINTR) { + ngx_log_debug0(NGX_LOG_DEBUG_CORE, file->log, err, + "pwritev() was interrupted"); + goto eintr; + } + + ngx_log_error(NGX_LOG_CRIT, file->log, err, + "pwritev() \"%s\" failed", file->name.data); + return NGX_ERROR; + } + + if ((size_t) n != size) { + ngx_log_error(NGX_LOG_CRIT, file->log, 0, + "pwritev() \"%s\" has written only %z of %uz", + file->name.data, n, size); + return NGX_ERROR; + } + +#else + + if (file->sys_offset != offset) { + if (lseek(file->fd, offset, SEEK_SET) == -1) { + ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, + "lseek() \"%s\" failed", file->name.data); + return NGX_ERROR; + } + + file->sys_offset = offset; + } + +eintr: + + n = writev(file->fd, vec->elts, vec->nelts); + + if (n == -1) { + err = ngx_errno; + + if (err == NGX_EINTR) { + ngx_log_debug0(NGX_LOG_DEBUG_CORE, file->log, err, + "writev() was interrupted"); + goto eintr; + } + + ngx_log_error(NGX_LOG_CRIT, file->log, err, + "writev() \"%s\" failed", file->name.data); + return NGX_ERROR; + } + + if ((size_t) n != size) { + ngx_log_error(NGX_LOG_CRIT, file->log, 0, + "writev() \"%s\" has written only %z of %uz", + file->name.data, n, size); + return NGX_ERROR; + } + + file->sys_offset += n; + +#endif + + file->offset += n; + + return n; +} + + ngx_int_t ngx_set_file_time(u_char *name, ngx_fd_t fd, time_t s) { diff --git a/src/os/unix/ngx_posix_init.c b/src/os/unix/ngx_posix_init.c index bf3a310..61cc8ca 100644 --- a/src/os/unix/ngx_posix_init.c +++ b/src/os/unix/ngx_posix_init.c @@ -63,7 +63,7 @@ ngx_os_init(ngx_log_t *log) if (getrlimit(RLIMIT_NOFILE, &rlmt) == -1) { ngx_log_error(NGX_LOG_ALERT, log, errno, - "getrlimit(RLIMIT_NOFILE) failed)"); + "getrlimit(RLIMIT_NOFILE) failed"); return NGX_ERROR; } From 2de69eb4943511047b082b2b60699f5e8292a7f7 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Thu, 14 Jan 2016 10:12:18 +0200 Subject: [PATCH 020/600] New upstream release (1.9.9) --- debian/changelog | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index 3000163..897af34 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,9 +1,13 @@ -nginx (1.9.6-3) UNRELEASED; urgency=medium +nginx (1.9.9-1) UNRELEASED; urgency=medium + [ Michael Lustfield ] * debian/nginx-common.nginx.logrotate: + Switching logrotate to 14 days. (Closes: #805322) - -- Michael Lustfield Thu, 10 Dec 2015 04:07:29 -0600 + [ Christos Trochalakis ] + * New upstream release (1.9.9). + + -- Christos Trochalakis Thu, 14 Jan 2016 10:11:34 +0200 nginx (1.9.6-2) unstable; urgency=medium From 3ed34604605ae854620ec6b50acf942d7485190d Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Thu, 14 Jan 2016 10:11:18 +0200 Subject: [PATCH 021/600] Update nginx-lua to v0.10.0 --- debian/changelog | 2 + debian/modules/README.Modules-versions | 2 +- debian/modules/nginx-lua/README.markdown | 719 +++++++-- debian/modules/nginx-lua/config | 7 + .../modules/nginx-lua/doc/HttpLuaModule.wiki | 477 +++++- .../nginx-lua/src/api/ngx_http_lua_api.h | 2 +- .../nginx-lua/src/ngx_http_lua_accessby.c | 6 +- .../modules/nginx-lua/src/ngx_http_lua_args.c | 12 +- .../nginx-lua/src/ngx_http_lua_balancer.c | 607 ++++++++ .../nginx-lua/src/ngx_http_lua_balancer.h | 27 + .../nginx-lua/src/ngx_http_lua_bodyfilterby.c | 5 +- .../nginx-lua/src/ngx_http_lua_cache.c | 16 +- .../nginx-lua/src/ngx_http_lua_cache.h | 4 +- .../nginx-lua/src/ngx_http_lua_clfactory.c | 4 +- .../nginx-lua/src/ngx_http_lua_common.h | 70 +- .../nginx-lua/src/ngx_http_lua_consts.c | 51 + .../nginx-lua/src/ngx_http_lua_contentby.c | 7 +- .../nginx-lua/src/ngx_http_lua_contentby.h | 2 +- .../nginx-lua/src/ngx_http_lua_control.c | 71 +- .../nginx-lua/src/ngx_http_lua_coroutine.c | 14 +- .../nginx-lua/src/ngx_http_lua_directive.c | 77 +- .../nginx-lua/src/ngx_http_lua_directive.h | 3 + .../src/ngx_http_lua_headerfilterby.c | 4 +- .../nginx-lua/src/ngx_http_lua_headers.c | 10 +- .../nginx-lua/src/ngx_http_lua_headers_in.c | 42 +- .../nginx-lua/src/ngx_http_lua_headers_out.c | 2 +- .../nginx-lua/src/ngx_http_lua_logby.c | 6 +- .../modules/nginx-lua/src/ngx_http_lua_misc.c | 32 +- .../modules/nginx-lua/src/ngx_http_lua_misc.h | 2 + .../nginx-lua/src/ngx_http_lua_module.c | 169 +- .../nginx-lua/src/ngx_http_lua_output.c | 4 +- .../nginx-lua/src/ngx_http_lua_phase.c | 8 + .../nginx-lua/src/ngx_http_lua_regex.c | 20 +- .../nginx-lua/src/ngx_http_lua_req_body.c | 4 +- .../nginx-lua/src/ngx_http_lua_req_method.c | 6 +- .../nginx-lua/src/ngx_http_lua_rewriteby.c | 8 +- .../nginx-lua/src/ngx_http_lua_script.c | 2 +- .../nginx-lua/src/ngx_http_lua_semaphore.c | 546 +++++++ .../nginx-lua/src/ngx_http_lua_semaphore.h | 51 + .../nginx-lua/src/ngx_http_lua_shdict.c | 15 +- .../nginx-lua/src/ngx_http_lua_shdict.h | 1 + .../nginx-lua/src/ngx_http_lua_sleep.c | 5 +- .../nginx-lua/src/ngx_http_lua_socket_tcp.c | 184 +-- .../nginx-lua/src/ngx_http_lua_socket_tcp.h | 6 +- .../nginx-lua/src/ngx_http_lua_socket_udp.c | 10 +- .../nginx-lua/src/ngx_http_lua_socket_udp.h | 4 +- .../nginx-lua/src/ngx_http_lua_ssl_certby.c | 938 +++++++++++ .../nginx-lua/src/ngx_http_lua_ssl_certby.h | 47 + .../nginx-lua/src/ngx_http_lua_ssl_ocsp.c | 497 ++++++ .../nginx-lua/src/ngx_http_lua_string.c | 2 +- .../nginx-lua/src/ngx_http_lua_subrequest.c | 53 +- .../nginx-lua/src/ngx_http_lua_timer.c | 50 +- .../nginx-lua/src/ngx_http_lua_uthread.c | 6 +- .../modules/nginx-lua/src/ngx_http_lua_util.c | 166 +- .../modules/nginx-lua/src/ngx_http_lua_util.h | 22 +- .../nginx-lua/src/ngx_http_lua_variable.c | 8 +- .../nginx-lua/src/ngx_http_lua_worker.c | 58 +- debian/modules/nginx-lua/t/020-subrequest.t | 6 +- debian/modules/nginx-lua/t/022-redirect.t | 54 +- debian/modules/nginx-lua/t/028-req-header.t | 52 +- debian/modules/nginx-lua/t/056-flush.t | 2 +- debian/modules/nginx-lua/t/058-tcp-socket.t | 297 +++- debian/modules/nginx-lua/t/062-count.t | 18 +- debian/modules/nginx-lua/t/076-no-postpone.t | 64 +- debian/modules/nginx-lua/t/082-body-filter.t | 15 +- debian/modules/nginx-lua/t/129-ssl-socket.t | 18 +- debian/modules/nginx-lua/t/132-lua-blocks.t | 85 + debian/modules/nginx-lua/t/133-worker-count.t | 32 + .../modules/nginx-lua/t/134-worker-count-5.t | 32 + debian/modules/nginx-lua/t/135-worker-id.t | 33 + debian/modules/nginx-lua/t/136-timer-counts.t | 111 ++ debian/modules/nginx-lua/t/137-req-misc.t | 62 + debian/modules/nginx-lua/t/138-balancer.t | 304 ++++ debian/modules/nginx-lua/t/139-ssl-cert-by.t | 1382 +++++++++++++++++ debian/modules/nginx-lua/util/build2.sh | 8 +- 75 files changed, 7242 insertions(+), 506 deletions(-) create mode 100644 debian/modules/nginx-lua/src/ngx_http_lua_balancer.c create mode 100644 debian/modules/nginx-lua/src/ngx_http_lua_balancer.h create mode 100644 debian/modules/nginx-lua/src/ngx_http_lua_semaphore.c create mode 100644 debian/modules/nginx-lua/src/ngx_http_lua_semaphore.h create mode 100644 debian/modules/nginx-lua/src/ngx_http_lua_ssl_certby.c create mode 100644 debian/modules/nginx-lua/src/ngx_http_lua_ssl_certby.h create mode 100644 debian/modules/nginx-lua/src/ngx_http_lua_ssl_ocsp.c create mode 100644 debian/modules/nginx-lua/t/133-worker-count.t create mode 100644 debian/modules/nginx-lua/t/134-worker-count-5.t create mode 100644 debian/modules/nginx-lua/t/135-worker-id.t create mode 100644 debian/modules/nginx-lua/t/136-timer-counts.t create mode 100644 debian/modules/nginx-lua/t/137-req-misc.t create mode 100644 debian/modules/nginx-lua/t/138-balancer.t create mode 100644 debian/modules/nginx-lua/t/139-ssl-cert-by.t diff --git a/debian/changelog b/debian/changelog index 897af34..bf298f1 100644 --- a/debian/changelog +++ b/debian/changelog @@ -6,6 +6,8 @@ nginx (1.9.9-1) UNRELEASED; urgency=medium [ Christos Trochalakis ] * New upstream release (1.9.9). + * debian/modules/nginx-lua: + + Update nginx-lua to v0.10.0. -- Christos Trochalakis Thu, 14 Jan 2016 10:11:34 +0200 diff --git a/debian/modules/README.Modules-versions b/debian/modules/README.Modules-versions index 3690858..eb35054 100644 --- a/debian/modules/README.Modules-versions +++ b/debian/modules/README.Modules-versions @@ -22,7 +22,7 @@ README for Modules versions nginx-lua Homepage: https://github.com/openresty/lua-nginx-module - Version: v0.9.19 + Version: v0.10.0 nginx-upstream-fair Homepage: https://github.com/gnosek/nginx-upstream-fair diff --git a/debian/modules/nginx-lua/README.markdown b/debian/modules/nginx-lua/README.markdown index da06da6..64adc0e 100644 --- a/debian/modules/nginx-lua/README.markdown +++ b/debian/modules/nginx-lua/README.markdown @@ -61,7 +61,7 @@ Production ready. Version ======= -This document describes ngx_lua [v0.9.19](https://github.com/openresty/lua-nginx-module/tags) released on 11 November 2015. +This document describes ngx_lua [v0.10.0](https://github.com/openresty/lua-nginx-module/tags) released on 11 January 2015. Synopsis ======== @@ -241,19 +241,15 @@ The Lua state (Lua VM instance) is shared across all the requests handled by a s Nginx Compatibility =================== -The latest module is compatible with the following versions of Nginx: -* 1.9.x (last tested: 1.9.3) +The latest version of this module is compatible with the following versions of Nginx: + +* 1.9.x (last tested: 1.9.7) +* 1.8.x * 1.7.x (last tested: 1.7.10) * 1.6.x -* 1.5.x (last tested: 1.5.12) -* 1.4.x (last tested: 1.4.4) -* 1.3.x (last tested: 1.3.11) -* 1.2.x (last tested: 1.2.9) -* 1.1.x (last tested: 1.1.5) -* 1.0.x (last tested: 1.0.15) -* 0.9.x (last tested: 0.9.4) -* 0.8.x >= 0.8.54 (last tested: 0.8.54) + +Nginx cores older than 1.6.0 (exclusive) are *not* supported. [Back to TOC](#table-of-contents) @@ -273,9 +269,9 @@ Build the source with this module: ```bash - wget 'http://nginx.org/download/nginx-1.9.3.tar.gz' - tar -xzvf nginx-1.9.3.tar.gz - cd nginx-1.9.3/ + wget 'http://nginx.org/download/nginx-1.9.7.tar.gz' + tar -xzvf nginx-1.9.7.tar.gz + cd nginx-1.9.7/ # tell nginx's build system where to find LuaJIT 2.0: export LUAJIT_LIB=/path/to/luajit/lib @@ -859,7 +855,6 @@ TODO } } ``` -* ssl: implement directives `ssl_certificate_by_lua` and `ssl_certificate_by_lua_file` to allow using Lua to dynamically serve SSL certificates and keys for downstream SSL handshake. (already done in CloudFlare's private branch and powering CloudFlare's SSL gateway of its global network. expected to be opensourced in March 2015.) * shm: implement a "shared queue API" to complement the existing [shared dict](#lua_shared_dict) API. * cosocket: add support in the context of [init_by_lua*](#init_by_lua). * cosocket: implement the `bind()` method for stream-typed cosockets. @@ -1028,7 +1023,11 @@ Directives * [log_by_lua](#log_by_lua) * [log_by_lua_block](#log_by_lua_block) * [log_by_lua_file](#log_by_lua_file) +* [balancer_by_lua_block](#balancer_by_lua_block) +* [balancer_by_lua_file](#balancer_by_lua_file) * [lua_need_request_body](#lua_need_request_body) +* [ssl_certificate_by_lua_block](#ssl_certificate_by_lua_block) +* [ssl_certificate_by_lua_file](#ssl_certificate_by_lua_file) * [lua_shared_dict](#lua_shared_dict) * [lua_socket_connect_timeout](#lua_socket_connect_timeout) * [lua_socket_send_timeout](#lua_socket_send_timeout) @@ -1045,6 +1044,7 @@ Directives * [lua_ssl_verify_depth](#lua_ssl_verify_depth) * [lua_http10_buffering](#lua_http10_buffering) * [rewrite_by_lua_no_postpone](#rewrite_by_lua_no_postpone) +* [access_by_lua_no_postpone](#access_by_lua_no_postpone) * [lua_transform_underscores_in_response_headers](#lua_transform_underscores_in_response_headers) * [lua_check_client_abort](#lua_check_client_abort) * [lua_max_pending_timers](#lua_max_pending_timers) @@ -1832,6 +1832,10 @@ As with other access phase handlers, [access_by_lua](#access_by_lua) will *not* Note that when calling `ngx.exit(ngx.OK)` within a [access_by_lua](#access_by_lua) handler, the nginx request processing control flow will still continue to the content handler. To terminate the current request from within a [access_by_lua](#access_by_lua) handler, calling [ngx.exit](#ngxexit) with status >= 200 (`ngx.HTTP_OK`) and status < 300 (`ngx.HTTP_SPECIAL_RESPONSE`) for successful quits and `ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)` (or its friends) for failures. +Starting from the `v0.9.20` release, you can use the [access_by_lua_no_postpone](#access_by_lua_no_postpone) +directive to control when to run this handler inside the "access" request-processing phase +of NGINX. + [Back to TOC](#directives) access_by_lua_block @@ -2212,6 +2216,83 @@ This directive was first introduced in the `v0.5.0rc31` release. [Back to TOC](#directives) +balancer_by_lua_block +--------------------- + +**syntax:** *balancer_by_lua_block { lua-script }* + +**context:** *upstream* + +**phase:** *content* + +This directive runs Lua code as an upstream balancer for any upstream entities defined +by the `upstream {}` configuration block. + +For instance, + +```nginx + + upstream foo { + server 127.0.0.1; + balancer_by_lua_block { + -- use Lua to do something interesting here + -- as a dynamic balancer + } + } + + server { + location / { + proxy_pass http://foo; + } + } +``` + +The resulting Lua load balancer can work with any existing nginx upstream modules +like [ngx_proxy](http://nginx.org/en/docs/http/ngx_http_proxy_module.html) and +[ngx_fastcgi](http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html). + +Also, the Lua load balancer can work with the standard upstream connection pool mechanism, +i.e., the standard [keepalive](http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive) directive. +Just ensure that the [keepalive](http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive) directive +is used *after* this `balancer_by_lua_block` directive in a single `upstream {}` configuration block. + +The Lua load balancer can totally ignore the list of servers defined in the `upstream {}` block +and select peer from a completely dynamic server list (even changing per request) via the +[ngx.balancer](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/balancer.md) module +from the [lua-resty-core](https://github.com/openresty/lua-resty-core) library. + +The Lua code handler registered by this directive might get called more than once in a single +downstream request when the nginx upstream mechanism retries the request on conditions +specified by directives like the [proxy_next_upstream](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_next_upstream) +directive. + +This Lua code execution context does not support yielding, so Lua APIs that may yield +(like cosockets and "light threads") are disabled in this context. One can usually work +around this limitation by doing such operations in an earlier phase handler (like +[access_by_lua*](#access_by_lua)) and passing along the result into this context +via the [ngx.ctx](#ngxctx) table. + +This directive was first introduced in the `v0.10.0` release. + +[Back to TOC](#directives) + +balancer_by_lua_file +-------------------- + +**syntax:** *balancer_by_lua_file <path-to-lua-script-file>* + +**context:** *upstream* + +**phase:** *content* + +Equivalent to [balancer_by_lua_block](#balancer_by_lua_block), except that the file specified by `` contains the Lua code, or, as from the `v0.5.0rc32` release, the [Lua/LuaJIT bytecode](#lualuajit-bytecode-support) to be executed. + +When a relative path like `foo/bar.lua` is given, they will be turned into the absolute path relative to the `server prefix` path determined by the `-p PATH` command-line option while starting the Nginx server. + +This directive was first introduced in the `v0.10.0` release. + +[Back to TOC](#directives) + lua_need_request_body --------------------- @@ -2240,6 +2321,112 @@ This also applies to [access_by_lua](#access_by_lua) and [access_by_lua_file](#a [Back to TOC](#directives) +ssl_certificate_by_lua_block +---------------------------- + +**syntax:** *ssl_certificate_by_lua_block { lua-script }* + +**context:** *server* + +**phase:** *right-before-SSL-handshake* + +This directive runs user Lua code when NGINX is about to start the SSL handshake for the downstream +SSL (https) connections. + +It is particularly useful for setting the SSL certificate chain and the corresponding private key on a per-request +basis. It is also useful to load such handshake configurations nonblockingly from the remote (for example, +with the [cosocket](#ngxsockettcp) API). And one can also do per-request OCSP stapling handling in pure +Lua here as well. + +Another typical use case is to do SSL handshake traffic control nonblockingly in this context, +with the help of the [lua-resty-limit-traffic#readme](https://github.com/openresty/lua-resty-limit-traffic) +library, for example. + +One can also do interesting things with the SSL handshake requests from the client side, like +rejecting old SSL clients using the SSLv3 protocol or even below selectively. + +The [ngx.ssl](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ssl.md) +and [ngx.ocsp](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ocsp.md) Lua modules +provided by the [lua-resty-core](https://github.com/openresty/lua-resty-core/#readme) +library are particularly useful in this context. You can use the Lua API offered by these two Lua modules +to manipulate the SSL certificate chain and private key for the current SSL connection +being initiated. + +This Lua handler does not run at all, however, when NGINX/OpenSSL successfully resumes +the SSL session via SSL session IDs or TLS session tickets for the current SSL connection. In +other words, this Lua handler only runs when NGINX has to initiate a full SSL handshake. + +Below is a trivial example using the +[ngx.ssl](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ssl.md) module +at the same time: + +```nginx + + server { + listen 443 ssl; + server_name test.com; + + ssl_certificate_by_lua_block { + print("About to initiate a new SSL handshake!") + } + + location / { + root html; + } + } +``` + +See more complicated examples in the [ngx.ssl](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ssl.md) +and [ngx.ocsp](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ocsp.md) +Lua modules' official documentation. + +Uncaught Lua exceptions in the user Lua code immediately abort the current SSL session, so does the +[ngx.exit](#ngxexit) call with an error code like `ngx.ERROR`. + +This Lua code execution context *does* support yielding, so Lua APIs that may yield +(like cosockets, sleeping, and "light threads") +are enabled in this context. + +Note, however, you still need to configure the [ssl_certificate](http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_certificate) and +[ssl_certificate_key](http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_certificate_key) +directives even though you will not use this static certificate and private key at all. This is +because the NGINX core requires their appearance otherwise you are seeing the following error +while starting NGINX: + + + nginx: [emerg] no ssl configured for the server + + +This directive currently requires the following NGINX core patch to work correctly: + + + +The bundled version of the NGINX core in OpenResty 1.9.7.2 (or above) already has this +patch applied. + +Furthermore, one needs at least OpenSSL 1.0.2e for this directive to work. + +This directive was first introduced in the `v0.10.0` release. + +[Back to TOC](#directives) + +ssl_certificate_by_lua_file +--------------------------- + +**syntax:** *ssl_certificate_by_lua_file <path-to-lua-script-file>* + +**context:** *server* + +**phase:** *right-before-SSL-handshake* + +Equivalent to [ssl_certificate_by_lua_block](#ssl_certificate_by_lua_block), except that the file specified by `` contains the Lua code, or, as from the `v0.5.0rc32` release, the [Lua/LuaJIT bytecode](#lualuajit-bytecode-support) to be executed. + +When a relative path like `foo/bar.lua` is given, they will be turned into the absolute path relative to the `server prefix` path determined by the `-p PATH` command-line option while starting the Nginx server. + +This directive was first introduced in the `v0.10.0` release. + +[Back to TOC](#directives) + lua_shared_dict --------------- @@ -2265,6 +2452,9 @@ The `` argument accepts size units such as `k` and `m`: } ``` +The hard-coded minimum size is 8KB while the practical minimum size depends +on actual user data set (some people start with 12KB). + See [ngx.shared.DICT](#ngxshareddict) for details. This directive was first introduced in the `v0.3.1rc22` release. @@ -2518,12 +2708,27 @@ rewrite_by_lua_no_postpone **context:** *http* -Controls whether or not to disable postponing [rewrite_by_lua](#rewrite_by_lua) and [rewrite_by_lua_file](#rewrite_by_lua_file) directives to run at the end of the `rewrite` request-processing phase. By default, this directive is turned off and the Lua code is postponed to run at the end of the `rewrite` phase. +Controls whether or not to disable postponing [rewrite_by_lua](#rewrite_by_lua)* directives to run at the end of the `rewrite` request-processing phase. By default, this directive is turned off and the Lua code is postponed to run at the end of the `rewrite` phase. This directive was first introduced in the `v0.5.0rc29` release. [Back to TOC](#directives) +access_by_lua_no_postpone +------------------------- + +**syntax:** *access_by_lua_no_postpone on|off* + +**default:** *access_by_lua_no_postpone off* + +**context:** *http* + +Controls whether or not to disable postponing [access_by_lua](#access_by_lua)* directives to run at the end of the `access` request-processing phase. By default, this directive is turned off and the Lua code is postponed to run at the end of the `access` phase. + +This directive was first introduced in the `v0.9.20` release. + +[Back to TOC](#directives) + lua_transform_underscores_in_response_headers --------------------------------------------- @@ -2629,6 +2834,7 @@ Nginx API for Lua * [ngx.status](#ngxstatus) * [ngx.header.HEADER](#ngxheaderheader) * [ngx.resp.get_headers](#ngxrespget_headers) +* [ngx.req.is_internal](#ngxreqis_internal) * [ngx.req.start_time](#ngxreqstart_time) * [ngx.req.http_version](#ngxreqhttp_version) * [ngx.req.raw_header](#ngxreqraw_header) @@ -2727,6 +2933,8 @@ Nginx API for Lua * [ngx.thread.kill](#ngxthreadkill) * [ngx.on_abort](#ngxon_abort) * [ngx.timer.at](#ngxtimerat) +* [ngx.timer.running_count](#ngxtimerrunning_count) +* [ngx.timer.pending_count](#ngxtimerpending_count) * [ngx.config.debug](#ngxconfigdebug) * [ngx.config.prefix](#ngxconfigprefix) * [ngx.config.nginx_version](#ngxconfignginx_version) @@ -2734,6 +2942,12 @@ Nginx API for Lua * [ngx.config.ngx_lua_version](#ngxconfigngx_lua_version) * [ngx.worker.exiting](#ngxworkerexiting) * [ngx.worker.pid](#ngxworkerpid) +* [ngx.worker.count](#ngxworkercount) +* [ngx.worker.id](#ngxworkerid) +* [ngx.semaphore](#ngxsemaphore) +* [ngx.balancer](#ngxbalancer) +* [ngx.ssl](#ngxssl) +* [ngx.ocsp](#ngxocsp) * [ndk.set_var.DIRECTIVE](#ndkset_vardirective) * [coroutine.create](#coroutinecreate) * [coroutine.resume](#coroutineresume) @@ -2786,7 +3000,7 @@ ngx.arg ------- **syntax:** *val = ngx.arg\[index\]* -**context:** *set_by_lua*, body_filter_by_lua** +**context:** *set_by_lua*, body_filter_by_lua** When this is used in the context of the [set_by_lua](#set_by_lua) or [set_by_lua_file](#set_by_lua_file) directives, this table is read-only and holds the input arguments to the config directives: @@ -2823,7 +3037,7 @@ ngx.var.VARIABLE ---------------- **syntax:** *ngx.var.VAR_NAME* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua** Read and write Nginx variable values. @@ -2880,7 +3094,7 @@ This API requires a relatively expensive metamethod call and it is recommended t Core constants -------------- -**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, *log_by_lua*, ngx.timer.** +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, *log_by_lua*, ngx.timer.** ```lua @@ -2906,7 +3120,7 @@ The `ngx.DECLINED` constant was first introduced in the `v0.5.0rc19` release. HTTP method constants --------------------- -**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.** +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.** ngx.HTTP_GET @@ -2932,34 +3146,51 @@ These constants are usually used in [ngx.location.capture](#ngxlocationcapture) HTTP status constants --------------------- -**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.** +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.** ```nginx + value = ngx.HTTP_CONTINUE (100) (first added in the v0.9.20 release) + value = ngx.HTTP_SWITCHING_PROTOCOLS (101) (first added in the v0.9.20 release) value = ngx.HTTP_OK (200) value = ngx.HTTP_CREATED (201) + value = ngx.HTTP_ACCEPTED (202) (first added in the v0.9.20 release) + value = ngx.HTTP_NO_CONTENT (204) (first added in the v0.9.20 release) + value = ngx.HTTP_PARTIAL_CONTENT (206) (first added in the v0.9.20 release) value = ngx.HTTP_SPECIAL_RESPONSE (300) value = ngx.HTTP_MOVED_PERMANENTLY (301) value = ngx.HTTP_MOVED_TEMPORARILY (302) value = ngx.HTTP_SEE_OTHER (303) value = ngx.HTTP_NOT_MODIFIED (304) + value = ngx.HTTP_TEMPORARY_REDIRECT (307) (first added in the v0.9.20 release) value = ngx.HTTP_BAD_REQUEST (400) value = ngx.HTTP_UNAUTHORIZED (401) + value = ngx.HTTP_PAYMENT_REQUIRED (402) (first added in the v0.9.20 release) value = ngx.HTTP_FORBIDDEN (403) value = ngx.HTTP_NOT_FOUND (404) value = ngx.HTTP_NOT_ALLOWED (405) + value = ngx.HTTP_NOT_ACCEPTABLE (406) (first added in the v0.9.20 release) + value = ngx.HTTP_REQUEST_TIMEOUT (408) (first added in the v0.9.20 release) + value = ngx.HTTP_CONFLICT (409) (first added in the v0.9.20 release) value = ngx.HTTP_GONE (410) + value = ngx.HTTP_UPGRADE_REQUIRED (426) (first added in the v0.9.20 release) + value = ngx.HTTP_TOO_MANY_REQUESTS (429) (first added in the v0.9.20 release) + value = ngx.HTTP_CLOSE (444) (first added in the v0.9.20 release) + value = ngx.HTTP_ILLEGAL (451) (first added in the v0.9.20 release) value = ngx.HTTP_INTERNAL_SERVER_ERROR (500) value = ngx.HTTP_METHOD_NOT_IMPLEMENTED (501) + value = ngx.HTTP_BAD_GATEWAY (502) (first added in the v0.9.20 release) value = ngx.HTTP_SERVICE_UNAVAILABLE (503) value = ngx.HTTP_GATEWAY_TIMEOUT (504) (first added in the v0.3.1rc38 release) + value = ngx.HTTP_VERSION_NOT_SUPPORTED (505) (first added in the v0.9.20 release) + value = ngx.HTTP_INSUFFICIENT_STORAGE (507) (first added in the v0.9.20 release) ``` [Back to TOC](#nginx-api-for-lua) Nginx log level constants ------------------------- -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.** ```lua @@ -2982,7 +3213,7 @@ print ----- **syntax:** *print(...)* -**context:** *init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.** +**context:** *init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.*, balancer_by_lua*, certificate_by_lua** Writes argument values into the nginx `error.log` file with the `ngx.NOTICE` log level. @@ -3001,7 +3232,7 @@ There is a hard coded `2048` byte limitation on error message lengths in the Ngi ngx.ctx ------- -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.*, balancer_by_lua** This table can be used to store per-request Lua context data and has a life time identical to the current request (as with the Nginx variables). @@ -3104,7 +3335,42 @@ Overriding `ngx.ctx` with a new Lua table is also supported, for example, When being used in the context of [init_worker_by_lua*](#init_worker_by_lua), this table just has the same lifetime of the current Lua handler. -The `ngx.ctx` lookup requires relatively expensive metamethod calls and it is much slower than explicitly passing per-request data along by your own function arguments. So do not abuse this API for saving your own function arguments because it usually has quite some performance impact. And because of the metamethod magic, never "local" the `ngx.ctx` table outside your function scope. +The `ngx.ctx` lookup requires relatively expensive metamethod calls and it is much slower than explicitly passing per-request data along by your own function arguments. So do not abuse this API for saving your own function arguments because it usually has quite some performance impact. + +Because of the metamethod magic, never "local" the `ngx.ctx` table outside your Lua function scope on the Lua module level level due to [worker-level data sharing](#data-sharing-within-an-nginx-worker). For example, the following is bad: + +```lua + + -- mymodule.lua + local _M = {} + + -- the following line is bad since ngx.ctx is a per-request + -- data while this `ctx` variable is on the Lua module level + -- and thus is per-nginx-worker. + local ctx = ngx.ctx + + function _M.main() + ctx.foo = "bar" + end + + return _M +``` + +Use the following instead: + +```lua + + -- mymodule.lua + local _M = {} + + function _M.main(ctx) + ctx.foo = "bar" + end + + return _M +``` + +That is, let the caller pass the `ctx` table explicitly via a function argument. [Back to TOC](#nginx-api-for-lua) @@ -3112,9 +3378,9 @@ ngx.location.capture -------------------- **syntax:** *res = ngx.location.capture(uri, options?)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua** -Issue a synchronous but still non-blocking *Nginx Subrequest* using `uri`. +Issues a synchronous but still non-blocking *Nginx Subrequest* using `uri`. Nginx's subrequests provide a powerful way to make non-blocking internal requests to other locations configured with disk file directory or *any* other nginx C modules like `ngx_proxy`, `ngx_fastcgi`, `ngx_memc`, `ngx_postgres`, `ngx_drizzle`, and even ngx_lua itself and etc etc etc. @@ -3125,6 +3391,9 @@ Subrequests are completely different from HTTP 301/302 redirection (via [ngx.red You should always read the request body (by either calling [ngx.req.read_body](#ngxreqread_body) or configuring [lua_need_request_body](#lua_need_request_body) on) before initiating a subrequest. +This API function (as well as [ngx.location.capture_multi](#ngxlocationcapture_multi)) always buffers the whole response body of the subrequest in memory. Thus, you should use [cosockets](#ngxsockettcp) +and streaming processing instead if you have to handle large subrequest responses. + Here is a basic example: ```lua @@ -3401,7 +3670,7 @@ ngx.location.capture_multi -------------------------- **syntax:** *res1, res2, ... = ngx.location.capture_multi({ {uri, options?}, {uri, options?}, ... })* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua** Just like [ngx.location.capture](#ngxlocationcapture), but supports multiple subrequests running in parallel. @@ -3464,7 +3733,7 @@ Please also refer to restrictions on capturing locations configured by [subreque ngx.status ---------- -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua** Read and write the current request's response status. This should be called before sending out the response headers. @@ -3489,7 +3758,7 @@ ngx.header.HEADER **syntax:** *value = ngx.header.HEADER* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua** Set, add to, or clear the current request's `HEADER` response header that is to be sent. @@ -3601,7 +3870,7 @@ ngx.resp.get_headers -------------------- **syntax:** *headers = ngx.resp.get_headers(max_headers?, raw?)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, balancer_by_lua** Returns a Lua table holding all the current response headers for the current request. @@ -3619,11 +3888,26 @@ This API was first introduced in the `v0.9.5` release. [Back to TOC](#nginx-api-for-lua) +ngx.req.is_internal +------------------- +**syntax:** *is_internal = ngx.req.is_internal()* + +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua** + +Returns a boolean indicating whether the current request is an "internal request", i.e., +a request initiated from inside the current nginx server instead of from the client side. + +Subrequests are all internal requests and so are requests after internal redirects. + +This API was first introduced in the `v0.9.20` release. + +[Back to TOC](#nginx-api-for-lua) + ngx.req.start_time ------------------ **syntax:** *secs = ngx.req.start_time()* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua** Returns a floating-point number representing the timestamp (including milliseconds as the decimal part) when the current request was created. @@ -3644,7 +3928,7 @@ ngx.req.http_version -------------------- **syntax:** *num = ngx.req.http_version()* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua** Returns the HTTP version number for the current request as a Lua number. @@ -3658,7 +3942,7 @@ ngx.req.raw_header ------------------ **syntax:** *str = ngx.req.raw_header(no_request_line?)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua** Returns the original raw HTTP protocol header received by the Nginx server. @@ -3704,7 +3988,7 @@ ngx.req.get_method ------------------ **syntax:** *method_name = ngx.req.get_method()* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, balancer_by_lua** Retrieves the current request's request method name. Strings like `"GET"` and `"POST"` are returned instead of numerical [method constants](#http-method-constants). @@ -3720,7 +4004,7 @@ ngx.req.set_method ------------------ **syntax:** *ngx.req.set_method(method_id)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua** Overrides the current request's request method with the `method_id` argument. Currently only numerical [method constants](#http-method-constants) are supported, like `ngx.HTTP_POST` and `ngx.HTTP_GET`. @@ -3736,7 +4020,7 @@ ngx.req.set_uri --------------- **syntax:** *ngx.req.set_uri(uri, jump?)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua** Rewrite the current request's (parsed) URI by the `uri` argument. The `uri` argument must be a Lua string and cannot be of zero length, or a Lua exception will be thrown. @@ -3835,7 +4119,7 @@ ngx.req.set_uri_args -------------------- **syntax:** *ngx.req.set_uri_args(args)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua** Rewrite the current request's URI query arguments by the `args` argument. The `args` argument can be either a Lua string, as in @@ -3872,7 +4156,7 @@ ngx.req.get_uri_args -------------------- **syntax:** *args = ngx.req.get_uri_args(max_args?)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, balancer_by_lua** Returns a Lua table holding all the current request URL query arguments. @@ -3968,7 +4252,7 @@ ngx.req.get_post_args --------------------- **syntax:** *args, err = ngx.req.get_post_args(max_args?)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua** Returns a Lua table holding all the current request POST query arguments (of the MIME type `application/x-www-form-urlencoded`). Call [ngx.req.read_body](#ngxreqread_body) to read the request body first or turn on the [lua_need_request_body](#lua_need_request_body) directive to avoid errors. @@ -4070,7 +4354,7 @@ ngx.req.get_headers ------------------- **syntax:** *headers = ngx.req.get_headers(max_headers?, raw?)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua** Returns a Lua table holding all the current request headers. @@ -4144,7 +4428,7 @@ ngx.req.set_header ------------------ **syntax:** *ngx.req.set_header(header_name, header_value)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua* +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua* Set the current request's request header named `header_name` to value `header_value`, overriding any existing ones. @@ -4195,7 +4479,7 @@ ngx.req.clear_header -------------------- **syntax:** *ngx.req.clear_header(header_name)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua** Clears the current request's request header named `header_name`. None of the current request's existing subrequests will be affected but subsequently initiated subrequests will inherit the change by default. @@ -4205,7 +4489,7 @@ ngx.req.read_body ----------------- **syntax:** *ngx.req.read_body()* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua** Reads the client request body synchronously without blocking the Nginx event loop. @@ -4236,7 +4520,7 @@ ngx.req.discard_body -------------------- **syntax:** *ngx.req.discard_body()* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua** Explicitly discard the request body, i.e., read the data on the connection and throw it away immediately. Please note that ignoring request body is not the right way to discard it, and that this function must be called to avoid breaking things under HTTP 1.1 keepalive or HTTP 1.1 pipelining. @@ -4254,7 +4538,7 @@ ngx.req.get_body_data --------------------- **syntax:** *data = ngx.req.get_body_data()* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua** Retrieves in-memory request body data. It returns a Lua string rather than a Lua table holding all the parsed query arguments. Use the [ngx.req.get_post_args](#ngxreqget_post_args) function instead if a Lua table is required. @@ -4282,7 +4566,7 @@ ngx.req.get_body_file --------------------- **syntax:** *file_name = ngx.req.get_body_file()* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua** Retrieves the file name for the in-file request body data. Returns `nil` if the request body has not been read or has been read into memory. @@ -4304,7 +4588,7 @@ ngx.req.set_body_data --------------------- **syntax:** *ngx.req.set_body_data(data)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua** Set the current request's request body using the in-memory data specified by the `data` argument. @@ -4320,7 +4604,7 @@ ngx.req.set_body_file --------------------- **syntax:** *ngx.req.set_body_file(file_name, auto_clean?)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua** Set the current request's request body using the in-file data specified by the `file_name` argument. @@ -4340,7 +4624,7 @@ ngx.req.init_body ----------------- **syntax:** *ngx.req.init_body(buffer_size?)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua** Creates a new blank request body for the current request and inializes the buffer for later request body data writing via the [ngx.req.append_body](#ngxreqappend_body) and [ngx.req.finish_body](#ngxreqfinish_body) APIs. @@ -4371,7 +4655,7 @@ ngx.req.append_body ------------------- **syntax:** *ngx.req.append_body(data_chunk)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua** Append new data chunk specified by the `data_chunk` argument onto the existing request body created by the [ngx.req.init_body](#ngxreqinit_body) call. @@ -4391,7 +4675,7 @@ ngx.req.finish_body ------------------- **syntax:** *ngx.req.finish_body()* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua** Completes the construction process of the new request body created by the [ngx.req.init_body](#ngxreqinit_body) and [ngx.req.append_body](#ngxreqappend_body) calls. @@ -4409,7 +4693,7 @@ ngx.req.socket **syntax:** *tcpsock, err = ngx.req.socket(raw)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua** Returns a read-only cosocket object that wraps the downstream connection. Only [receive](#tcpsockreceive) and [receiveuntil](#tcpsockreceiveuntil) methods are supported on this object. @@ -4434,7 +4718,7 @@ ngx.exec -------- **syntax:** *ngx.exec(uri, args?)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua** Does an internal redirect to `uri` with `args` and is similar to the [echo_exec](http://github.com/openresty/echo-nginx-module#echo_exec) directive of the [echo-nginx-module](http://github.com/openresty/echo-nginx-module). @@ -4501,7 +4785,7 @@ ngx.redirect ------------ **syntax:** *ngx.redirect(uri, status?)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua** Issue an `HTTP 301` or `302` redirection to `uri`. @@ -4583,7 +4867,7 @@ ngx.send_headers ---------------- **syntax:** *ok, err = ngx.send_headers()* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua** Explicitly send out the response headers. @@ -4598,7 +4882,7 @@ ngx.headers_sent ---------------- **syntax:** *value = ngx.headers_sent* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua** Returns `true` if the response headers have been sent (by ngx_lua), and `false` otherwise. @@ -4610,7 +4894,7 @@ ngx.print --------- **syntax:** *ok, err = ngx.print(...)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua** Emits arguments concatenated to the HTTP client (as response body). If response headers have not been sent, this function will send headers out first and then output body data. @@ -4651,7 +4935,7 @@ ngx.say ------- **syntax:** *ok, err = ngx.say(...)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua** Just as [ngx.print](#ngxprint) but also emit a trailing newline. @@ -4661,7 +4945,7 @@ ngx.log ------- **syntax:** *ngx.log(log_level, ...)* -**context:** *init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Log arguments concatenated to error.log with the given logging level. @@ -4677,7 +4961,7 @@ ngx.flush --------- **syntax:** *ok, err = ngx.flush(wait?)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua** Flushes response output to the client. @@ -4697,7 +4981,7 @@ ngx.exit -------- **syntax:** *ngx.exit(status)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, ngx.timer.** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** When `status >= 200` (i.e., `ngx.HTTP_OK` and above), it will interrupt the execution of the current request and return status code to nginx. @@ -4750,7 +5034,7 @@ ngx.eof ------- **syntax:** *ok, err = ngx.eof()* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua** Explicitly specify the end of the response output stream. In the case of HTTP 1.1 chunked encoded output, it will just trigger the Nginx core to send out the "last chunk". @@ -4785,7 +5069,7 @@ ngx.sleep --------- **syntax:** *ngx.sleep(seconds)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** Sleeps for the specified seconds without blocking. One can specify time resolution up to 0.001 seconds (i.e., one milliseconds). @@ -4801,7 +5085,7 @@ ngx.escape_uri -------------- **syntax:** *newstr = ngx.escape_uri(str)* -**context:** *init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Escape `str` as a URI component. @@ -4811,7 +5095,7 @@ ngx.unescape_uri ---------------- **syntax:** *newstr = ngx.unescape_uri(str)* -**context:** *init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Unescape `str` as an escaped URI component. @@ -4834,7 +5118,7 @@ ngx.encode_args --------------- **syntax:** *str = ngx.encode_args(table)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Encode the Lua table to a query args string according to the URI encoded rules. @@ -4891,7 +5175,7 @@ ngx.decode_args --------------- **syntax:** *table = ngx.decode_args(str, max_args?)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Decodes a URI encoded query-string into a Lua table. This is the inverse function of [ngx.encode_args](#ngxencode_args). @@ -4914,7 +5198,7 @@ ngx.encode_base64 ----------------- **syntax:** *newstr = ngx.encode_base64(str, no_padding?)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Encodes `str` to a base64 digest. @@ -4926,7 +5210,7 @@ ngx.decode_base64 ----------------- **syntax:** *newstr = ngx.decode_base64(str)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Decodes the `str` argument as a base64 digest to the raw form. Returns `nil` if `str` is not well formed. @@ -4936,7 +5220,7 @@ ngx.crc32_short --------------- **syntax:** *intval = ngx.crc32_short(str)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Calculates the CRC-32 (Cyclic Redundancy Code) digest for the `str` argument. @@ -4952,7 +5236,7 @@ ngx.crc32_long -------------- **syntax:** *intval = ngx.crc32_long(str)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Calculates the CRC-32 (Cyclic Redundancy Code) digest for the `str` argument. @@ -4968,7 +5252,7 @@ ngx.hmac_sha1 ------------- **syntax:** *digest = ngx.hmac_sha1(secret_key, str)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Computes the [HMAC-SHA1](http://en.wikipedia.org/wiki/HMAC) digest of the argument `str` and turns the result using the secret key ``. @@ -5000,7 +5284,7 @@ ngx.md5 ------- **syntax:** *digest = ngx.md5(str)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Returns the hexadecimal representation of the MD5 digest of the `str` argument. @@ -5027,7 +5311,7 @@ ngx.md5_bin ----------- **syntax:** *digest = ngx.md5_bin(str)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Returns the binary form of the MD5 digest of the `str` argument. @@ -5039,7 +5323,7 @@ ngx.sha1_bin ------------ **syntax:** *digest = ngx.sha1_bin(str)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Returns the binary form of the SHA-1 digest of the `str` argument. @@ -5053,7 +5337,7 @@ ngx.quote_sql_str ----------------- **syntax:** *quoted_value = ngx.quote_sql_str(raw_value)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Returns a quoted SQL string literal according to the MySQL quoting rules. @@ -5063,7 +5347,7 @@ ngx.today --------- **syntax:** *str = ngx.today()* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Returns current date (in the format `yyyy-mm-dd`) from the nginx cached time (no syscall involved unlike Lua's date library). @@ -5075,7 +5359,7 @@ ngx.time -------- **syntax:** *secs = ngx.time()* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Returns the elapsed seconds from the epoch for the current time stamp from the nginx cached time (no syscall involved unlike Lua's date library). @@ -5087,7 +5371,7 @@ ngx.now ------- **syntax:** *secs = ngx.now()* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Returns a floating-point number for the elapsed time in seconds (including milliseconds as the decimal part) from the epoch for the current time stamp from the nginx cached time (no syscall involved unlike Lua's date library). @@ -5101,7 +5385,7 @@ ngx.update_time --------------- **syntax:** *ngx.update_time()* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Forcibly updates the Nginx current time cache. This call involves a syscall and thus has some overhead, so do not abuse it. @@ -5113,7 +5397,7 @@ ngx.localtime ------------- **syntax:** *str = ngx.localtime()* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Returns the current time stamp (in the format `yyyy-mm-dd hh:mm:ss`) of the nginx cached time (no syscall involved unlike Lua's [os.date](http://www.lua.org/manual/5.1/manual.html#pdf-os.date) function). @@ -5125,7 +5409,7 @@ ngx.utctime ----------- **syntax:** *str = ngx.utctime()* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Returns the current time stamp (in the format `yyyy-mm-dd hh:mm:ss`) of the nginx cached time (no syscall involved unlike Lua's [os.date](http://www.lua.org/manual/5.1/manual.html#pdf-os.date) function). @@ -5137,7 +5421,7 @@ ngx.cookie_time --------------- **syntax:** *str = ngx.cookie_time(sec)* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Returns a formatted string can be used as the cookie expiration time. The parameter `sec` is the time stamp in seconds (like those returned from [ngx.time](#ngxtime)). @@ -5153,7 +5437,7 @@ ngx.http_time ------------- **syntax:** *str = ngx.http_time(sec)* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Returns a formated string can be used as the http header time (for example, being used in `Last-Modified` header). The parameter `sec` is the time stamp in seconds (like those returned from [ngx.time](#ngxtime)). @@ -5169,7 +5453,7 @@ ngx.parse_http_time ------------------- **syntax:** *sec = ngx.parse_http_time(str)* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Parse the http time string (as returned by [ngx.http_time](#ngxhttp_time)) into seconds. Returns the seconds or `nil` if the input string is in bad forms. @@ -5187,7 +5471,7 @@ ngx.is_subrequest ----------------- **syntax:** *value = ngx.is_subrequest* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua** Returns `true` if the current request is an nginx subrequest, or `false` otherwise. @@ -5197,7 +5481,7 @@ ngx.re.match ------------ **syntax:** *captures, err = ngx.re.match(subject, regex, options?, ctx?, res_table?)* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Matches the `subject` string using the Perl compatible regular expression `regex` with the optional `options`. @@ -5355,7 +5639,7 @@ ngx.re.find ----------- **syntax:** *from, to, err = ngx.re.find(subject, regex, options?, ctx?, nth?)* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Similar to [ngx.re.match](#ngxrematch) but only returns the begining index (`from`) and end index (`to`) of the matched substring. The returned indexes are 1-based and can be fed directly into the [string.sub](http://www.lua.org/manual/5.1/manual.html#pdf-string.sub) API function to obtain the matched substring. @@ -5409,7 +5693,7 @@ ngx.re.gmatch ------------- **syntax:** *iterator, err = ngx.re.gmatch(subject, regex, options?)* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Similar to [ngx.re.match](#ngxrematch), but returns a Lua iterator instead, so as to let the user programmer iterate all the matches over the `` string argument with the PCRE `regex`. @@ -5487,7 +5771,7 @@ ngx.re.sub ---------- **syntax:** *newstr, n, err = ngx.re.sub(subject, regex, replace, options?)* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Substitutes the first match of the Perl compatible regular expression `regex` on the `subject` argument string with the string or function argument `replace`. The optional `options` argument has exactly the same meaning as in [ngx.re.match](#ngxrematch). @@ -5553,7 +5837,7 @@ ngx.re.gsub ----------- **syntax:** *newstr, n, err = ngx.re.gsub(subject, regex, replace, options?)* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Just like [ngx.re.sub](#ngxresub), but does global substitution. @@ -5593,7 +5877,7 @@ ngx.shared.DICT **syntax:** *dict = ngx.shared\[name_var\]* -**context:** *init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Fetching the shm-based Lua dictionary object for the shared memory zone named `DICT` defined by the [lua_shared_dict](#lua_shared_dict) directive. @@ -5666,7 +5950,7 @@ ngx.shared.DICT.get ------------------- **syntax:** *value, flags = ngx.shared.DICT:get(key)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Retrieving the value in the dictionary [ngx.shared.DICT](#ngxshareddict) for the key `key`. If the key does not exist or has been expired, then `nil` will be returned. @@ -5704,7 +5988,7 @@ ngx.shared.DICT.get_stale ------------------------- **syntax:** *value, flags, stale = ngx.shared.DICT:get_stale(key)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Similar to the [get](#ngxshareddictget) method but returns the value even if the key has already expired. @@ -5722,7 +6006,7 @@ ngx.shared.DICT.set ------------------- **syntax:** *success, err, forcible = ngx.shared.DICT:set(key, value, exptime?, flags?)* -**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Unconditionally sets a key-value pair into the shm-based dictionary [ngx.shared.DICT](#ngxshareddict). Returns three values: @@ -5732,7 +6016,7 @@ Unconditionally sets a key-value pair into the shm-based dictionary [ngx.shared. The `value` argument inserted can be Lua booleans, numbers, strings, or `nil`. Their value type will also be stored into the dictionary and the same data type can be retrieved later via the [get](#ngxshareddictget) method. -The optional `exptime` argument specifies expiration time (in seconds) for the inserted key-value pair. The time resolution is `0.001` seconds. If the `exptime` takes the value `0` (which is the default), then the item will never be expired. +The optional `exptime` argument specifies expiration time (in seconds) for the inserted key-value pair. The time resolution is `0.001` seconds. If the `exptime` takes the value `0` (which is the default), then the item will never expire. The optional `flags` argument specifies a user flags value associated with the entry to be stored. It can also be retrieved later with the value. The user flags is stored as an unsigned 32-bit integer internally. Defaults to `0`. The user flags argument was first introduced in the `v0.5.0rc2` release. @@ -5770,7 +6054,7 @@ ngx.shared.DICT.safe_set ------------------------ **syntax:** *ok, err = ngx.shared.DICT:safe_set(key, value, exptime?, flags?)* -**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Similar to the [set](#ngxshareddictset) method, but never overrides the (least recently used) unexpired items in the store when running out of storage in the shared memory zone. In this case, it will immediately return `nil` and the string "no memory". @@ -5784,7 +6068,7 @@ ngx.shared.DICT.add ------------------- **syntax:** *success, err, forcible = ngx.shared.DICT:add(key, value, exptime?, flags?)* -**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Just like the [set](#ngxshareddictset) method, but only stores the key-value pair into the dictionary [ngx.shared.DICT](#ngxshareddict) if the key does *not* exist. @@ -5800,7 +6084,7 @@ ngx.shared.DICT.safe_add ------------------------ **syntax:** *ok, err = ngx.shared.DICT:safe_add(key, value, exptime?, flags?)* -**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Similar to the [add](#ngxshareddictadd) method, but never overrides the (least recently used) unexpired items in the store when running out of storage in the shared memory zone. In this case, it will immediately return `nil` and the string "no memory". @@ -5814,7 +6098,7 @@ ngx.shared.DICT.replace ----------------------- **syntax:** *success, err, forcible = ngx.shared.DICT:replace(key, value, exptime?, flags?)* -**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Just like the [set](#ngxshareddictset) method, but only stores the key-value pair into the dictionary [ngx.shared.DICT](#ngxshareddict) if the key *does* exist. @@ -5830,7 +6114,7 @@ ngx.shared.DICT.delete ---------------------- **syntax:** *ngx.shared.DICT:delete(key)* -**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Unconditionally removes the key-value pair from the shm-based dictionary [ngx.shared.DICT](#ngxshareddict). @@ -5846,7 +6130,7 @@ ngx.shared.DICT.incr -------------------- **syntax:** *newval, err = ngx.shared.DICT:incr(key, value)* -**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Increments the (numerical) value for `key` in the shm-based dictionary [ngx.shared.DICT](#ngxshareddict) by the step value `value`. Returns the new resulting number if the operation is successfully completed or `nil` and an error message otherwise. @@ -5866,7 +6150,7 @@ ngx.shared.DICT.flush_all ------------------------- **syntax:** *ngx.shared.DICT:flush_all()* -**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Flushes out all the items in the dictionary. This method does not actuall free up all the memory blocks in the dictionary but just marks all the existing items as expired. @@ -5880,7 +6164,7 @@ ngx.shared.DICT.flush_expired ----------------------------- **syntax:** *flushed = ngx.shared.DICT:flush_expired(max_count?)* -**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Flushes out the expired items in the dictionary, up to the maximal number specified by the optional `max_count` argument. When the `max_count` argument is given `0` or not given at all, then it means unlimited. Returns the number of items that have actually been flushed. @@ -5896,7 +6180,7 @@ ngx.shared.DICT.get_keys ------------------------ **syntax:** *keys = ngx.shared.DICT:get_keys(max_count?)* -**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Fetch a list of the keys from the dictionary, up to ``. @@ -5912,7 +6196,7 @@ ngx.socket.udp -------------- **syntax:** *udpsock = ngx.socket.udp()* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** Creates and returns a UDP or datagram-oriented unix domain socket object (also known as one type of the "cosocket" objects). The following methods are supported on this object: @@ -5936,7 +6220,7 @@ udpsock:setpeername **syntax:** *ok, err = udpsock:setpeername("unix:/path/to/unix-domain.socket")* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** Attempts to connect a UDP socket object to a remote server or to a datagram unix domain socket file. Because the datagram protocol is actually connection-less, this method does not really establish a "connection", but only just set the name of the remote peer for subsequent read/write operations. @@ -5995,7 +6279,7 @@ udpsock:send ------------ **syntax:** *ok, err = udpsock:send(data)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** Sends data on the current UDP or datagram unix domain socket object. @@ -6011,7 +6295,7 @@ udpsock:receive --------------- **syntax:** *data, err = udpsock:receive(size?)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** Receives data from the UDP or datagram unix domain socket object with an optional receive buffer size argument, `size`. @@ -6046,7 +6330,7 @@ udpsock:close ------------- **syntax:** *ok, err = udpsock:close()* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** Closes the current UDP or datagram unix domain socket. It returns the `1` in case of success and returns `nil` with a string describing the error otherwise. @@ -6060,7 +6344,7 @@ udpsock:settimeout ------------------ **syntax:** *udpsock:settimeout(time)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** Set the timeout value in milliseconds for subsequent socket operations (like [receive](#udpsockreceive)). @@ -6074,7 +6358,7 @@ ngx.socket.tcp -------------- **syntax:** *tcpsock = ngx.socket.tcp()* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** Creates and returns a TCP or stream-oriented unix domain socket object (also known as one type of the "cosocket" objects). The following methods are supported on this object: @@ -6120,7 +6404,7 @@ tcpsock:connect **syntax:** *ok, err = tcpsock:connect("unix:/path/to/unix-domain.socket", options_table?)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** Attempts to connect a TCP socket object to a remote server or to a stream unix domain socket file without blocking. @@ -6197,9 +6481,9 @@ This method was first introduced in the `v0.5.0rc1` release. tcpsock:sslhandshake -------------------- -**syntax:** *session, err = tcpsock:sslhandshake(reused_session?, server_name?, ssl_verify?)* +**syntax:** *session, err = tcpsock:sslhandshake(reused_session?, server_name?, ssl_verify?, send_status_req?)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** Does SSL/TLS handshake on the currently established connection. @@ -6230,6 +6514,9 @@ Also, when the `ssl_verify` argument is true and the `server_name` argument is also specified, the latter will be used to validate the server name in the server certificate. +The optional `send_status_req` argument takes a boolean that controls whether to send +the OCSP status request in the SSL handshake request (which is for requesting OCSP stapling). + For connections that have already done SSL/TLS handshake, this method returns immediately. @@ -6241,7 +6528,7 @@ tcpsock:send ------------ **syntax:** *bytes, err = tcpsock:send(data)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** Sends data without blocking on the current TCP or Unix Domain Socket connection. @@ -6273,7 +6560,7 @@ tcpsock:receive **syntax:** *data, err, partial = tcpsock:receive(pattern?)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** Receives data from the connected socket according to the reading pattern or size. @@ -6315,7 +6602,7 @@ tcpsock:receiveuntil -------------------- **syntax:** *iterator = tcpsock:receiveuntil(pattern, options?)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** This method returns an iterator Lua function that can be called to read the data stream until it sees the specified pattern or an error occurs. @@ -6414,7 +6701,7 @@ tcpsock:close ------------- **syntax:** *ok, err = tcpsock:close()* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** Closes the current TCP or stream unix domain socket. It returns the `1` in case of success and returns `nil` with a string describing the error otherwise. @@ -6430,7 +6717,7 @@ tcpsock:settimeout ------------------ **syntax:** *tcpsock:settimeout(time)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** Set the timeout value in milliseconds for subsequent socket operations ([connect](#tcpsockconnect), [receive](#tcpsockreceive), and iterators returned from [receiveuntil](#tcpsockreceiveuntil)). @@ -6446,7 +6733,7 @@ tcpsock:setoption ----------------- **syntax:** *tcpsock:setoption(option, value?)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** This function is added for [LuaSocket](http://w3.impa.br/~diego/software/luasocket/tcp.html) API compatibility and does nothing for now. Its functionality will be implemented in future. @@ -6458,7 +6745,7 @@ tcpsock:setkeepalive -------------------- **syntax:** *ok, err = tcpsock:setkeepalive(timeout?, size?)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** Puts the current socket's connection immediately into the cosocket built-in connection pool and keep it alive until other [connect](#tcpsockconnect) method calls request it or the associated maximal idle timeout is expired. @@ -6486,7 +6773,7 @@ tcpsock:getreusedtimes ---------------------- **syntax:** *count, err = tcpsock:getreusedtimes()* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** This method returns the (successfully) reused times for the current connection. In case of error, it returns `nil` and a string describing the error. @@ -6502,7 +6789,7 @@ ngx.socket.connect **syntax:** *tcpsock, err = ngx.socket.connect("unix:/path/to/unix-domain.socket")* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.** This function is a shortcut for combining [ngx.socket.tcp()](#ngxsockettcp) and the [connect()](#tcpsockconnect) method call in a single operation. It is actually implemented like this: @@ -6526,7 +6813,7 @@ ngx.get_phase ------------- **syntax:** *str = ngx.get_phase()* -**context:** *init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Retrieves the current running phase name. Possible return values are @@ -6559,7 +6846,7 @@ ngx.thread.spawn ---------------- **syntax:** *co = ngx.thread.spawn(func, arg1, arg2, ...)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** Spawns a new user "light thread" with the Lua function `func` as well as those optional arguments `arg1`, `arg2`, and etc. Returns a Lua thread (or Lua coroutine) object represents this "light thread". @@ -6697,7 +6984,7 @@ ngx.thread.wait --------------- **syntax:** *ok, res1, res2, ... = ngx.thread.wait(thread1, thread2, ...)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** Waits on one or more child "light threads" and returns the results of the first "light thread" that terminates (either successfully or with an error). @@ -6800,7 +7087,7 @@ ngx.thread.kill --------------- **syntax:** *ok, err = ngx.thread.kill(thread)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.** Kills a running "light thread" created by [ngx.thread.spawn](#ngxthreadspawn). Returns a true value when successful or `nil` and a string describing the error otherwise. @@ -6814,7 +7101,7 @@ ngx.on_abort ------------ **syntax:** *ok, err = ngx.on_abort(callback)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua** Registers a user Lua function as the callback which gets called automatically when the client closes the (downstream) connection prematurely. @@ -6854,7 +7141,7 @@ ngx.timer.at ------------ **syntax:** *ok, err = ngx.timer.at(delay, callback, user_arg1, user_arg2, ...)* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** Creates an Nginx timer with a user callback function as well as optional user arguments. @@ -6976,11 +7263,35 @@ This API was first introduced in the `v0.8.0` release. [Back to TOC](#nginx-api-for-lua) +ngx.timer.running_count +----------------------- +**syntax:** *count = ngx.timer.running_count()* + +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** + +Returns the number of timers currently running. + +This directive was first introduced in the `v0.9.20` release. + +[Back to TOC](#nginx-api-for-lua) + +ngx.timer.pending_count +----------------------- +**syntax:** *count = ngx.timer.pending_count()* + +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** + +Returns the number of pending timers. + +This directive was first introduced in the `v0.9.20` release. + +[Back to TOC](#nginx-api-for-lua) + ngx.config.debug ---------------- **syntax:** *debug = ngx.config.debug* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, init_by_lua*, init_worker_by_lua** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, init_by_lua*, init_worker_by_lua** This boolean field indicates whether the current Nginx is a debug build, i.e., being built by the `./configure` option `--with-debug`. @@ -6993,7 +7304,7 @@ ngx.config.prefix **syntax:** *prefix = ngx.config.prefix()* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, init_by_lua*, init_worker_by_lua** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, init_by_lua*, init_worker_by_lua** Returns the Nginx server "prefix" path, as determined by the `-p` command-line option when running the nginx executable, or the path specified by the `--prefix` command-line option when building Nginx with the `./configure` script. @@ -7006,7 +7317,7 @@ ngx.config.nginx_version **syntax:** *ver = ngx.config.nginx_version* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, init_by_lua*, init_worker_by_lua** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, init_by_lua*, init_worker_by_lua** This field take an integral value indicating the version number of the current Nginx core being used. For example, the version number `1.4.3` results in the Lua number 1004003. @@ -7019,7 +7330,7 @@ ngx.config.nginx_configure **syntax:** *str = ngx.config.nginx_configure()* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, init_by_lua** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, init_by_lua** This function returns a string for the NGINX `./configure` command's arguments string. @@ -7032,7 +7343,7 @@ ngx.config.ngx_lua_version **syntax:** *ver = ngx.config.ngx_lua_version* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, init_by_lua** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, init_by_lua** This field take an integral value indicating the version number of the current `ngx_lua` module being used. For example, the version number `0.9.3` results in the Lua number 9003. @@ -7045,7 +7356,7 @@ ngx.worker.exiting **syntax:** *exiting = ngx.worker.exiting()* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, init_by_lua*, init_worker_by_lua** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, init_by_lua*, init_worker_by_lua** This function returns a boolean value indicating whether the current Nginx worker process already starts exiting. Nginx worker process exiting happens on Nginx server quit or configuration reload (aka HUP reload). @@ -7058,7 +7369,7 @@ ngx.worker.pid **syntax:** *pid = ngx.worker.pid()* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, init_by_lua*, init_worker_by_lua** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, init_by_lua*, init_worker_by_lua** This function returns a Lua number for the process ID (PID) of the current Nginx worker process. This API is more efficient than `ngx.var.pid` and can be used in contexts where the [ngx.var.VARIABLE](#ngxvarvariable) API cannot be used (like [init_worker_by_lua](#init_worker_by_lua)). @@ -7066,11 +7377,127 @@ This API was first introduced in the `0.9.5` release. [Back to TOC](#nginx-api-for-lua) +ngx.worker.count +---------------- + +**syntax:** *count = ngx.worker.count()* + +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, init_by_lua** + +Returns the total number of the Nginx worker processes (i.e., the value configured +by the [worker_processes](http://nginx.org/en/docs/ngx_core_module.html#worker_processes) +directive in `nginx.conf`). + +This API was first introduced in the `0.9.20` release. + +[Back to TOC](#nginx-api-for-lua) + +ngx.worker.id +------------- + +**syntax:** *count = ngx.worker.id()* + +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, init_worker_by_lua** + +Returns the ordinal number of the current Nginx worker processes (starting from number 0). + +So if the total number of workers is `N`, then this method may return a number between 0 +and `N - 1` (inclusive). + +This function returns meaningful values only for NGINX 1.9.1+. With earlier versions of NGINX, it +always returns `nil`. + +See also [ngx.worker.count](#ngxworkercount). + +This API was first introduced in the `0.9.20` release. + +[Back to TOC](#nginx-api-for-lua) + +ngx.semaphore +------------- +**syntax:** *local semaphore = require "ngx.semaphore"* + +This is a Lua module that implements a classic-style semaphore API for efficient synchronizations among +different "light threads". Sharing the same semaphore among different "light threads" created in different (request) +contexts are also supported as long as the "light threads" reside in the same NGINX worker process +and the [lua_code_cache](#lua_code_cache) directive is turned on (which is the default). + +This Lua module does not ship with this ngx_lua module itself rather it is shipped with +the +[lua-resty-core](https://github.com/openresty/lua-resty-core) library. + +Please refer to the [documentation](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/semaphore.md) +for this `ngx.semaphore` Lua module in [lua-resty-core](https://github.com/openresty/lua-resty-core) +for more details. + +This feature requires at least ngx_lua `v0.10.0`. + +[Back to TOC](#nginx-api-for-lua) + +ngx.balancer +------------ +**syntax:** *local balancer = require "ngx.balancer"* + +This is a Lua module that provides a Lua API to allow defining completely dynamic load balancers +in pure Lua. + +This Lua module does not ship with this ngx_lua module itself rather it is shipped with +the +[lua-resty-core](https://github.com/openresty/lua-resty-core) library. + +Please refer to the [documentation](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/balancer.md) +for this `ngx.balancer` Lua module in [lua-resty-core](https://github.com/openresty/lua-resty-core) +for more details. + +This feature requires at least ngx_lua `v0.10.0`. + +[Back to TOC](#nginx-api-for-lua) + +ngx.ssl +------- +**syntax:** *local ssl = require "ngx.ssl"* + +This Lua module provides API functions to control the SSL handshake process in contexts like +[ssl_certificate_by_lua*](#ssl_certificate_by_lua_block). + +This Lua module does not ship with this ngx_lua module itself rather it is shipped with +the +[lua-resty-core](https://github.com/openresty/lua-resty-core) library. + +Please refer to the [documentation](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ssl.md) +for this `ngx.ssl` Lua module for more details. + +This feature requires at least ngx_lua `v0.10.0`. + +[Back to TOC](#nginx-api-for-lua) + +ngx.ocsp +-------- +**syntax:** *local ocsp = require "ngx.ocsp"* + +This Lua module provides API to perform OCSP queries, OCSP response validations, and +OCSP stapling planting. + +Usually, this module is used together with the [ngx.ssl](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ssl.md) +module in the +context of [ssl_certificate_by_lua*](#ssl_certificate_by_lua_block). + +This Lua module does not ship with this ngx_lua module itself rather it is shipped with +the +[lua-resty-core](https://github.com/openresty/lua-resty-core) library. + +Please refer to the [documentation](https://github.com/openresty/lua-resty-core/blob/ocsp-cert-by-lua-2/lib/ngx/ocsp.md) +for this `ngx.ocsp` Lua module for more details. + +This feature requires at least ngx_lua `v0.10.0`. + +[Back to TOC](#nginx-api-for-lua) + ndk.set_var.DIRECTIVE --------------------- **syntax:** *res = ndk.set_var.DIRECTIVE_NAME* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** This mechanism allows calling other nginx C modules' directives that are implemented by [Nginx Devel Kit](https://github.com/simpl/ngx_devel_kit) (NDK)'s set_var submodule's `ndk_set_var_value`. @@ -7111,7 +7538,7 @@ coroutine.create ---------------- **syntax:** *co = coroutine.create(f)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua** Creates a user Lua coroutines with a Lua function, and returns a coroutine object. @@ -7127,7 +7554,7 @@ coroutine.resume ---------------- **syntax:** *ok, ... = coroutine.resume(co, ...)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua** Resumes the executation of a user Lua coroutine object previously yielded or just created. @@ -7143,9 +7570,9 @@ coroutine.yield --------------- **syntax:** *... = coroutine.yield(...)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua** -Yields the executation of the current user Lua coroutine. +Yields the execution of the current user Lua coroutine. Similar to the standard Lua [coroutine.yield](http://www.lua.org/manual/5.1/manual.html#pdf-coroutine.yield) API, but works in the context of the Lua coroutines created by ngx_lua. @@ -7159,7 +7586,7 @@ coroutine.wrap -------------- **syntax:** *co = coroutine.wrap(f)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua** Similar to the standard Lua [coroutine.wrap](http://www.lua.org/manual/5.1/manual.html#pdf-coroutine.wrap) API, but works in the context of the Lua coroutines created by ngx_lua. @@ -7173,7 +7600,7 @@ coroutine.running ----------------- **syntax:** *co = coroutine.running()* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua** Identical to the standard Lua [coroutine.running](http://www.lua.org/manual/5.1/manual.html#pdf-coroutine.running) API. @@ -7187,7 +7614,7 @@ coroutine.status ---------------- **syntax:** *status = coroutine.status(co)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua** Identical to the standard Lua [coroutine.status](http://www.lua.org/manual/5.1/manual.html#pdf-coroutine.status) API. diff --git a/debian/modules/nginx-lua/config b/debian/modules/nginx-lua/config index 4b770d7..030788c 100644 --- a/debian/modules/nginx-lua/config +++ b/debian/modules/nginx-lua/config @@ -339,6 +339,7 @@ NGX_ADDON_SRCS="$NGX_ADDON_SRCS \ $ngx_addon_dir/src/ngx_http_lua_api.c \ $ngx_addon_dir/src/ngx_http_lua_logby.c \ $ngx_addon_dir/src/ngx_http_lua_sleep.c \ + $ngx_addon_dir/src/ngx_http_lua_semaphore.c\ $ngx_addon_dir/src/ngx_http_lua_coroutine.c \ $ngx_addon_dir/src/ngx_http_lua_bodyfilterby.c \ $ngx_addon_dir/src/ngx_http_lua_initby.c \ @@ -350,7 +351,10 @@ NGX_ADDON_SRCS="$NGX_ADDON_SRCS \ $ngx_addon_dir/src/ngx_http_lua_timer.c \ $ngx_addon_dir/src/ngx_http_lua_config.c \ $ngx_addon_dir/src/ngx_http_lua_worker.c \ + $ngx_addon_dir/src/ngx_http_lua_ssl_certby.c \ + $ngx_addon_dir/src/ngx_http_lua_ssl_ocsp.c \ $ngx_addon_dir/src/ngx_http_lua_lex.c \ + $ngx_addon_dir/src/ngx_http_lua_balancer.c \ " NGX_ADDON_DEPS="$NGX_ADDON_DEPS \ @@ -392,6 +396,7 @@ NGX_ADDON_DEPS="$NGX_ADDON_DEPS \ $ngx_addon_dir/src/api/ngx_http_lua_api.h \ $ngx_addon_dir/src/ngx_http_lua_logby.h \ $ngx_addon_dir/src/ngx_http_lua_sleep.h \ + $ngx_addon_dir/src/ngx_http_lua_semaphore.h\ $ngx_addon_dir/src/ngx_http_lua_coroutine.h \ $ngx_addon_dir/src/ngx_http_lua_bodyfilterby.h \ $ngx_addon_dir/src/ngx_http_lua_initby.h \ @@ -404,7 +409,9 @@ NGX_ADDON_DEPS="$NGX_ADDON_DEPS \ $ngx_addon_dir/src/ngx_http_lua_timer.h \ $ngx_addon_dir/src/ngx_http_lua_config.h \ $ngx_addon_dir/src/ngx_http_lua_worker.h \ + $ngx_addon_dir/src/ngx_http_lua_ssl_certby.h \ $ngx_addon_dir/src/ngx_http_lua_lex.h \ + $ngx_addon_dir/src/ngx_http_lua_balancer.h \ " CFLAGS="$CFLAGS -DNDK_SET_VAR" diff --git a/debian/modules/nginx-lua/doc/HttpLuaModule.wiki b/debian/modules/nginx-lua/doc/HttpLuaModule.wiki index 3726509..f3bf06e 100644 --- a/debian/modules/nginx-lua/doc/HttpLuaModule.wiki +++ b/debian/modules/nginx-lua/doc/HttpLuaModule.wiki @@ -10,7 +10,7 @@ Production ready. = Version = -This document describes ngx_lua [https://github.com/openresty/lua-nginx-module/tags v0.9.19] released on 11 November 2015. +This document describes ngx_lua [https://github.com/openresty/lua-nginx-module/tags v0.10.0] released on 11 January 2015. = Synopsis = @@ -179,19 +179,15 @@ Other scripting language implementations typically struggle to match this perfor The Lua state (Lua VM instance) is shared across all the requests handled by a single nginx worker process to minimize memory use. = Nginx Compatibility = -The latest module is compatible with the following versions of Nginx: -* 1.9.x (last tested: 1.9.3) +The latest version of this module is compatible with the following versions of Nginx: + +* 1.9.x (last tested: 1.9.7) +* 1.8.x * 1.7.x (last tested: 1.7.10) * 1.6.x -* 1.5.x (last tested: 1.5.12) -* 1.4.x (last tested: 1.4.4) -* 1.3.x (last tested: 1.3.11) -* 1.2.x (last tested: 1.2.9) -* 1.1.x (last tested: 1.1.5) -* 1.0.x (last tested: 1.0.15) -* 0.9.x (last tested: 0.9.4) -* 0.8.x >= 0.8.54 (last tested: 0.8.54) + +Nginx cores older than 1.6.0 (exclusive) are *not* supported. = Installation = @@ -207,9 +203,9 @@ Alternatively, ngx_lua can be manually compiled into Nginx: Build the source with this module: - wget 'http://nginx.org/download/nginx-1.9.3.tar.gz' - tar -xzvf nginx-1.9.3.tar.gz - cd nginx-1.9.3/ + wget 'http://nginx.org/download/nginx-1.9.7.tar.gz' + tar -xzvf nginx-1.9.7.tar.gz + cd nginx-1.9.7/ # tell nginx's build system where to find LuaJIT 2.0: export LUAJIT_LIB=/path/to/luajit/lib @@ -696,7 +692,6 @@ phases. } } -* ssl: implement directives ssl_certificate_by_lua and ssl_certificate_by_lua_file to allow using Lua to dynamically serve SSL certificates and keys for downstream SSL handshake. (already done in CloudFlare's private branch and powering CloudFlare's SSL gateway of its global network. expected to be opensourced in March 2015.) * shm: implement a "shared queue API" to complement the existing [[#lua_shared_dict|shared dict]] API. * cosocket: add support in the context of [[#init_by_lua|init_by_lua*]]. * cosocket: implement the bind() method for stream-typed cosockets. @@ -1514,6 +1509,10 @@ As with other access phase handlers, [[#access_by_lua|access_by_lua]] will ''not Note that when calling ngx.exit(ngx.OK) within a [[#access_by_lua|access_by_lua]] handler, the nginx request processing control flow will still continue to the content handler. To terminate the current request from within a [[#access_by_lua|access_by_lua]] handler, calling [[#ngx.exit|ngx.exit]] with status >= 200 (ngx.HTTP_OK) and status < 300 (ngx.HTTP_SPECIAL_RESPONSE) for successful quits and ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) (or its friends) for failures. +Starting from the v0.9.20 release, you can use the [[#access_by_lua_no_postpone|access_by_lua_no_postpone]] +directive to control when to run this handler inside the "access" request-processing phase +of NGINX. + == access_by_lua_block == '''syntax:''' ''access_by_lua_block { lua-script }'' @@ -1849,6 +1848,76 @@ When a relative path like foo/bar.lua is given, they will be turned This directive was first introduced in the v0.5.0rc31 release. +== balancer_by_lua_block == + +'''syntax:''' ''balancer_by_lua_block { lua-script }'' + +'''context:''' ''upstream'' + +'''phase:''' ''content'' + +This directive runs Lua code as an upstream balancer for any upstream entities defined +by the upstream {} configuration block. + +For instance, + + + upstream foo { + server 127.0.0.1; + balancer_by_lua_block { + -- use Lua to do something interesting here + -- as a dynamic balancer + } + } + + server { + location / { + proxy_pass http://foo; + } + } + + +The resulting Lua load balancer can work with any existing nginx upstream modules +like [http://nginx.org/en/docs/http/ngx_http_proxy_module.html ngx_proxy] and +[http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html ngx_fastcgi]. + +Also, the Lua load balancer can work with the standard upstream connection pool mechanism, +i.e., the standard [http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive keepalive] directive. +Just ensure that the [http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive keepalive] directive +is used *after* this balancer_by_lua_block directive in a single upstream {} configuration block. + +The Lua load balancer can totally ignore the list of servers defined in the upstream {} block +and select peer from a completely dynamic server list (even changing per request) via the +[https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/balancer.md ngx.balancer] module +from the [https://github.com/openresty/lua-resty-core lua-resty-core] library. + +The Lua code handler registered by this directive might get called more than once in a single +downstream request when the nginx upstream mechanism retries the request on conditions +specified by directives like the [http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_next_upstream proxy_next_upstream] +directive. + +This Lua code execution context does not support yielding, so Lua APIs that may yield +(like cosockets and "light threads") are disabled in this context. One can usually work +around this limitation by doing such operations in an earlier phase handler (like +[[#access_by_lua|access_by_lua*]]) and passing along the result into this context +via the [[#ngx.ctx|ngx.ctx]] table. + +This directive was first introduced in the v0.10.0 release. + +== balancer_by_lua_file == + +'''syntax:''' ''balancer_by_lua_file '' + +'''context:''' ''upstream'' + +'''phase:''' ''content'' + +Equivalent to [[#balancer_by_lua_block|balancer_by_lua_block]], except that the file specified by contains the Lua code, or, as from the v0.5.0rc32 release, the [[#Lua/LuaJIT bytecode support|Lua/LuaJIT bytecode]] to be executed. + +When a relative path like foo/bar.lua is given, they will be turned into the absolute path relative to the server prefix path determined by the -p PATH command-line option while starting the Nginx server. + +This directive was first introduced in the v0.10.0 release. + == lua_need_request_body == '''syntax:''' ''lua_need_request_body '' @@ -1874,6 +1943,105 @@ It is recommended however, to use the [[#ngx.req.read_body|ngx.req.read_body]] a This also applies to [[#access_by_lua|access_by_lua]] and [[#access_by_lua_file|access_by_lua_file]]. +== ssl_certificate_by_lua_block == + +'''syntax:''' ''ssl_certificate_by_lua_block { lua-script }'' + +'''context:''' ''server'' + +'''phase:''' ''right-before-SSL-handshake'' + +This directive runs user Lua code when NGINX is about to start the SSL handshake for the downstream +SSL (https) connections. + +It is particularly useful for setting the SSL certificate chain and the corresponding private key on a per-request +basis. It is also useful to load such handshake configurations nonblockingly from the remote (for example, +with the [[#ngx.socket.tcp|cosocket]] API). And one can also do per-request OCSP stapling handling in pure +Lua here as well. + +Another typical use case is to do SSL handshake traffic control nonblockingly in this context, +with the help of the [https://github.com/openresty/lua-resty-limit-traffic lua-resty-limit-traffic#readme] +library, for example. + +One can also do interesting things with the SSL handshake requests from the client side, like +rejecting old SSL clients using the SSLv3 protocol or even below selectively. + +The [https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ssl.md ngx.ssl] +and [https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ocsp.md ngx.ocsp] Lua modules +provided by the [https://github.com/openresty/lua-resty-core/#readme lua-resty-core] +library are particularly useful in this context. You can use the Lua API offered by these two Lua modules +to manipulate the SSL certificate chain and private key for the current SSL connection +being initiated. + +This Lua handler does not run at all, however, when NGINX/OpenSSL successfully resumes +the SSL session via SSL session IDs or TLS session tickets for the current SSL connection. In +other words, this Lua handler only runs when NGINX has to initiate a full SSL handshake. + +Below is a trivial example using the +[https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ssl.md ngx.ssl] module +at the same time: + + + server { + listen 443 ssl; + server_name test.com; + + ssl_certificate_by_lua_block { + print("About to initiate a new SSL handshake!") + } + + location / { + root html; + } + } + + +See more complicated examples in the [https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ssl.md ngx.ssl] +and [https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ocsp.md ngx.ocsp] +Lua modules' official documentation. + +Uncaught Lua exceptions in the user Lua code immediately abort the current SSL session, so does the +[[#ngx.exit|ngx.exit]] call with an error code like ngx.ERROR. + +This Lua code execution context *does* support yielding, so Lua APIs that may yield +(like cosockets, sleeping, and "light threads") +are enabled in this context. + +Note, however, you still need to configure the [http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_certificate ssl_certificate] and +[http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_certificate_key ssl_certificate_key] +directives even though you will not use this static certificate and private key at all. This is +because the NGINX core requires their appearance otherwise you are seeing the following error +while starting NGINX: + + + nginx: [emerg] no ssl configured for the server + + +This directive currently requires the following NGINX core patch to work correctly: + +http://mailman.nginx.org/pipermail/nginx-devel/2016-January/007748.html + +The bundled version of the NGINX core in OpenResty 1.9.7.2 (or above) already has this +patch applied. + +Furthermore, one needs at least OpenSSL 1.0.2e for this directive to work. + +This directive was first introduced in the v0.10.0 release. + +== ssl_certificate_by_lua_file == + +'''syntax:''' ''ssl_certificate_by_lua_file '' + +'''context:''' ''server'' + +'''phase:''' ''right-before-SSL-handshake'' + +Equivalent to [[#ssl_certificate_by_lua_block|ssl_certificate_by_lua_block]], except that the file specified by contains the Lua code, or, as from the v0.5.0rc32 release, the [[#Lua/LuaJIT bytecode support|Lua/LuaJIT bytecode]] to be executed. + +When a relative path like foo/bar.lua is given, they will be turned into the absolute path relative to the server prefix path determined by the -p PATH command-line option while starting the Nginx server. + +This directive was first introduced in the v0.10.0 release. + == lua_shared_dict == '''syntax:''' ''lua_shared_dict '' @@ -1897,6 +2065,9 @@ The argument accepts size units such as k and < } +The hard-coded minimum size is 8KB while the practical minimum size depends +on actual user data set (some people start with 12KB). + See [[#ngx.shared.DICT|ngx.shared.DICT]] for details. This directive was first introduced in the v0.3.1rc22 release. @@ -2105,10 +2276,22 @@ This directive was first introduced in the v0.5.0rc19 release. '''context:''' ''http'' -Controls whether or not to disable postponing [[#rewrite_by_lua|rewrite_by_lua]] and [[#rewrite_by_lua_file|rewrite_by_lua_file]] directives to run at the end of the rewrite request-processing phase. By default, this directive is turned off and the Lua code is postponed to run at the end of the rewrite phase. +Controls whether or not to disable postponing [[#rewrite_by_lua|rewrite_by_lua]]* directives to run at the end of the rewrite request-processing phase. By default, this directive is turned off and the Lua code is postponed to run at the end of the rewrite phase. This directive was first introduced in the v0.5.0rc29 release. +== access_by_lua_no_postpone == + +'''syntax:''' ''access_by_lua_no_postpone on|off'' + +'''default:''' ''access_by_lua_no_postpone off'' + +'''context:''' ''http'' + +Controls whether or not to disable postponing [[#access_by_lua|access_by_lua]]* directives to run at the end of the access request-processing phase. By default, this directive is turned off and the Lua code is postponed to run at the end of the access phase. + +This directive was first introduced in the v0.9.20 release. + == lua_transform_underscores_in_response_headers == '''syntax:''' ''lua_transform_underscores_in_response_headers on|off'' @@ -2352,23 +2535,40 @@ These constants are usually used in [[#ngx.location.capture|ngx.location.capture '''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.*'' + value = ngx.HTTP_CONTINUE (100) (first added in the v0.9.20 release) + value = ngx.HTTP_SWITCHING_PROTOCOLS (101) (first added in the v0.9.20 release) value = ngx.HTTP_OK (200) value = ngx.HTTP_CREATED (201) + value = ngx.HTTP_ACCEPTED (202) (first added in the v0.9.20 release) + value = ngx.HTTP_NO_CONTENT (204) (first added in the v0.9.20 release) + value = ngx.HTTP_PARTIAL_CONTENT (206) (first added in the v0.9.20 release) value = ngx.HTTP_SPECIAL_RESPONSE (300) value = ngx.HTTP_MOVED_PERMANENTLY (301) value = ngx.HTTP_MOVED_TEMPORARILY (302) value = ngx.HTTP_SEE_OTHER (303) value = ngx.HTTP_NOT_MODIFIED (304) + value = ngx.HTTP_TEMPORARY_REDIRECT (307) (first added in the v0.9.20 release) value = ngx.HTTP_BAD_REQUEST (400) value = ngx.HTTP_UNAUTHORIZED (401) + value = ngx.HTTP_PAYMENT_REQUIRED (402) (first added in the v0.9.20 release) value = ngx.HTTP_FORBIDDEN (403) value = ngx.HTTP_NOT_FOUND (404) value = ngx.HTTP_NOT_ALLOWED (405) + value = ngx.HTTP_NOT_ACCEPTABLE (406) (first added in the v0.9.20 release) + value = ngx.HTTP_REQUEST_TIMEOUT (408) (first added in the v0.9.20 release) + value = ngx.HTTP_CONFLICT (409) (first added in the v0.9.20 release) value = ngx.HTTP_GONE (410) + value = ngx.HTTP_UPGRADE_REQUIRED (426) (first added in the v0.9.20 release) + value = ngx.HTTP_TOO_MANY_REQUESTS (429) (first added in the v0.9.20 release) + value = ngx.HTTP_CLOSE (444) (first added in the v0.9.20 release) + value = ngx.HTTP_ILLEGAL (451) (first added in the v0.9.20 release) value = ngx.HTTP_INTERNAL_SERVER_ERROR (500) value = ngx.HTTP_METHOD_NOT_IMPLEMENTED (501) + value = ngx.HTTP_BAD_GATEWAY (502) (first added in the v0.9.20 release) value = ngx.HTTP_SERVICE_UNAVAILABLE (503) value = ngx.HTTP_GATEWAY_TIMEOUT (504) (first added in the v0.3.1rc38 release) + value = ngx.HTTP_VERSION_NOT_SUPPORTED (505) (first added in the v0.9.20 release) + value = ngx.HTTP_INSUFFICIENT_STORAGE (507) (first added in the v0.9.20 release) == Nginx log level constants == @@ -2391,7 +2591,7 @@ These constants are usually used by the [[#ngx.log|ngx.log]] method. == print == '''syntax:''' ''print(...)'' -'''context:''' ''init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.*'' +'''context:''' ''init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.*, balancer_by_lua*, certificate_by_lua*'' Writes argument values into the nginx error.log file with the ngx.NOTICE log level. @@ -2406,7 +2606,7 @@ Lua nil arguments are accepted and result in literal "nil"2048 byte limitation on error message lengths in the Nginx core. This limit includes trailing newlines and leading time stamps. If the message size exceeds this limit, Nginx will truncate the message text accordingly. This limit can be manually modified by editing the NGX_MAX_ERROR_STR macro definition in the src/core/ngx_log.h file in the Nginx source tree. == ngx.ctx == -'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.*'' +'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.*, balancer_by_lua*'' This table can be used to store per-request Lua context data and has a life time identical to the current request (as with the Nginx variables). @@ -2502,14 +2702,47 @@ Overriding ngx.ctx with a new Lua table is also supported, for exam When being used in the context of [[#init_worker_by_lua|init_worker_by_lua*]], this table just has the same lifetime of the current Lua handler. -The ngx.ctx lookup requires relatively expensive metamethod calls and it is much slower than explicitly passing per-request data along by your own function arguments. So do not abuse this API for saving your own function arguments because it usually has quite some performance impact. And because of the metamethod magic, never "local" the ngx.ctx table outside your function scope. +The ngx.ctx lookup requires relatively expensive metamethod calls and it is much slower than explicitly passing per-request data along by your own function arguments. So do not abuse this API for saving your own function arguments because it usually has quite some performance impact. + +Because of the metamethod magic, never "local" the ngx.ctx table outside your Lua function scope on the Lua module level level due to [[#Data_Sharing_within_an_Nginx_Worker|worker-level data sharing]]. For example, the following is bad: + + +-- mymodule.lua +local _M = {} + +-- the following line is bad since ngx.ctx is a per-request +-- data while this `ctx` variable is on the Lua module level +-- and thus is per-nginx-worker. +local ctx = ngx.ctx + +function _M.main() + ctx.foo = "bar" +end + +return _M + + +Use the following instead: + + +-- mymodule.lua +local _M = {} + +function _M.main(ctx) + ctx.foo = "bar" +end + +return _M + + +That is, let the caller pass the `ctx` table explicitly via a function argument. == ngx.location.capture == '''syntax:''' ''res = ngx.location.capture(uri, options?)'' '''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*'' -Issue a synchronous but still non-blocking ''Nginx Subrequest'' using uri. +Issues a synchronous but still non-blocking ''Nginx Subrequest'' using uri. Nginx's subrequests provide a powerful way to make non-blocking internal requests to other locations configured with disk file directory or ''any'' other nginx C modules like ngx_proxy, ngx_fastcgi, ngx_memc, ngx_postgres, ngx_drizzle, and even ngx_lua itself and etc etc etc. @@ -2520,6 +2753,9 @@ Subrequests are completely different from HTTP 301/302 redirection (via [[#ngx.r You should always read the request body (by either calling [[#ngx.req.read_body|ngx.req.read_body]] or configuring [[#lua_need_request_body|lua_need_request_body]] on) before initiating a subrequest. +This API function (as well as [[#ngx.location.capture_multi|ngx.location.capture_multi]]) always buffers the whole response body of the subrequest in memory. Thus, you should use [[#ngx.socket.tcp|cosockets]] +and streaming processing instead if you have to handle large subrequest responses. + Here is a basic example: @@ -2959,7 +3195,7 @@ For reading ''request'' headers, use the [[#ngx.req.get_headers|ngx.req.get_head == ngx.resp.get_headers == '''syntax:''' ''headers = ngx.resp.get_headers(max_headers?, raw?)'' -'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*'' +'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, balancer_by_lua*'' Returns a Lua table holding all the current response headers for the current request. @@ -2974,6 +3210,18 @@ This function has the same signature as [[#ngx.req.get_headers|ngx.req.get_heade This API was first introduced in the v0.9.5 release. +== ngx.req.is_internal == +'''syntax:''' ''is_internal = ngx.req.is_internal()'' + +'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*'' + +Returns a boolean indicating whether the current request is an "internal request", i.e., +a request initiated from inside the current nginx server instead of from the client side. + +Subrequests are all internal requests and so are requests after internal redirects. + +This API was first introduced in the v0.9.20 release. + == ngx.req.start_time == '''syntax:''' ''secs = ngx.req.start_time()'' @@ -3046,7 +3294,7 @@ This method was first introduced in the v0.7.17 release. == ngx.req.get_method == '''syntax:''' ''method_name = ngx.req.get_method()'' -'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*'' +'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, balancer_by_lua*'' Retrieves the current request's request method name. Strings like "GET" and "POST" are returned instead of numerical [[#HTTP method constants|method constants]]. @@ -3189,7 +3437,7 @@ See also [[#ngx.req.set_uri|ngx.req.set_uri]]. == ngx.req.get_uri_args == '''syntax:''' ''args = ngx.req.get_uri_args(max_args?)'' -'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*'' +'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, balancer_by_lua*'' Returns a Lua table holding all the current request URL query arguments. @@ -3868,7 +4116,7 @@ Just as [[#ngx.print|ngx.print]] but also emit a trailing newline. == ngx.log == '''syntax:''' ''ngx.log(log_level, ...)'' -'''context:''' ''init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Log arguments concatenated to error.log with the given logging level. @@ -3898,7 +4146,7 @@ Since v0.8.3 this function returns 1 on success, or re == ngx.exit == '''syntax:''' ''ngx.exit(status)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, ngx.timer.*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' When status >= 200 (i.e., ngx.HTTP_OK and above), it will interrupt the execution of the current request and return status code to nginx. @@ -3975,7 +4223,7 @@ Since v0.8.3 this function returns 1 on success, or re == ngx.sleep == '''syntax:''' ''ngx.sleep(seconds)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' Sleeps for the specified seconds without blocking. One can specify time resolution up to 0.001 seconds (i.e., one milliseconds). @@ -4794,7 +5042,7 @@ Unconditionally sets a key-value pair into the shm-based dictionary [[#ngx.share The value argument inserted can be Lua booleans, numbers, strings, or nil. Their value type will also be stored into the dictionary and the same data type can be retrieved later via the [[#ngx.shared.DICT.get|get]] method. -The optional exptime argument specifies expiration time (in seconds) for the inserted key-value pair. The time resolution is 0.001 seconds. If the exptime takes the value 0 (which is the default), then the item will never be expired. +The optional exptime argument specifies expiration time (in seconds) for the inserted key-value pair. The time resolution is 0.001 seconds. If the exptime takes the value 0 (which is the default), then the item will never expire. The optional flags argument specifies a user flags value associated with the entry to be stored. It can also be retrieved later with the value. The user flags is stored as an unsigned 32-bit integer internally. Defaults to 0. The user flags argument was first introduced in the v0.5.0rc2 release. @@ -4942,7 +5190,7 @@ This feature was first introduced in the v0.7.3 release. == ngx.socket.udp == '''syntax:''' ''udpsock = ngx.socket.udp()'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' Creates and returns a UDP or datagram-oriented unix domain socket object (also known as one type of the "cosocket" objects). The following methods are supported on this object: @@ -4963,7 +5211,7 @@ See also [[#ngx.socket.tcp|ngx.socket.tcp]]. '''syntax:''' ''ok, err = udpsock:setpeername("unix:/path/to/unix-domain.socket")'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' Attempts to connect a UDP socket object to a remote server or to a datagram unix domain socket file. Because the datagram protocol is actually connection-less, this method does not really establish a "connection", but only just set the name of the remote peer for subsequent read/write operations. @@ -5016,7 +5264,7 @@ This method was first introduced in the v0.5.7 release. == udpsock:send == '''syntax:''' ''ok, err = udpsock:send(data)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' Sends data on the current UDP or datagram unix domain socket object. @@ -5029,7 +5277,7 @@ This feature was first introduced in the v0.5.7 release. == udpsock:receive == '''syntax:''' ''data, err = udpsock:receive(size?)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' Receives data from the UDP or datagram unix domain socket object with an optional receive buffer size argument, size. @@ -5060,7 +5308,7 @@ This feature was first introduced in the v0.5.7 release. == udpsock:close == '''syntax:''' ''ok, err = udpsock:close()'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' Closes the current UDP or datagram unix domain socket. It returns the 1 in case of success and returns nil with a string describing the error otherwise. @@ -5071,7 +5319,7 @@ This feature was first introduced in the v0.5.7 release. == udpsock:settimeout == '''syntax:''' ''udpsock:settimeout(time)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' Set the timeout value in milliseconds for subsequent socket operations (like [[#udpsock:receive|receive]]). @@ -5082,7 +5330,7 @@ This feature was first introduced in the v0.5.7 release. == ngx.socket.tcp == '''syntax:''' ''tcpsock = ngx.socket.tcp()'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' Creates and returns a TCP or stream-oriented unix domain socket object (also known as one type of the "cosocket" objects). The following methods are supported on this object: @@ -5125,7 +5373,7 @@ See also [[#ngx.socket.udp|ngx.socket.udp]]. '''syntax:''' ''ok, err = tcpsock:connect("unix:/path/to/unix-domain.socket", options_table?)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' Attempts to connect a TCP socket object to a remote server or to a stream unix domain socket file without blocking. @@ -5195,9 +5443,9 @@ The support for the options table argument was first introduced in the v0. This method was first introduced in the v0.5.0rc1 release. == tcpsock:sslhandshake == -'''syntax:''' ''session, err = tcpsock:sslhandshake(reused_session?, server_name?, ssl_verify?)'' +'''syntax:''' ''session, err = tcpsock:sslhandshake(reused_session?, server_name?, ssl_verify?, send_status_req?)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' Does SSL/TLS handshake on the currently established connection. @@ -5228,6 +5476,9 @@ Also, when the ssl_verify argument is true and the server_name argument is also specified, the latter will be used to validate the server name in the server certificate. +The optional send_status_req argument takes a boolean that controls whether to send +the OCSP status request in the SSL handshake request (which is for requesting OCSP stapling). + For connections that have already done SSL/TLS handshake, this method returns immediately. @@ -5236,7 +5487,7 @@ This method was first introduced in the v0.9.11 release. == tcpsock:send == '''syntax:''' ''bytes, err = tcpsock:send(data)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' Sends data without blocking on the current TCP or Unix Domain Socket connection. @@ -5264,7 +5515,7 @@ This feature was first introduced in the v0.5.0rc1 release. '''syntax:''' ''data, err, partial = tcpsock:receive(pattern?)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' Receives data from the connected socket according to the reading pattern or size. @@ -5302,7 +5553,7 @@ This feature was first introduced in the v0.5.0rc1 release. == tcpsock:receiveuntil == '''syntax:''' ''iterator = tcpsock:receiveuntil(pattern, options?)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' This method returns an iterator Lua function that can be called to read the data stream until it sees the specified pattern or an error occurs. @@ -5394,7 +5645,7 @@ This method was first introduced in the v0.5.0rc1 release. == tcpsock:close == '''syntax:''' ''ok, err = tcpsock:close()'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' Closes the current TCP or stream unix domain socket. It returns the 1 in case of success and returns nil with a string describing the error otherwise. @@ -5407,7 +5658,7 @@ This feature was first introduced in the v0.5.0rc1 release. == tcpsock:settimeout == '''syntax:''' ''tcpsock:settimeout(time)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' Set the timeout value in milliseconds for subsequent socket operations ([[#tcpsock:connect|connect]], [[#tcpsock:receive|receive]], and iterators returned from [[#tcpsock:receiveuntil|receiveuntil]]). @@ -5420,7 +5671,7 @@ This feature was first introduced in the v0.5.0rc1 release. == tcpsock:setoption == '''syntax:''' ''tcpsock:setoption(option, value?)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' This function is added for [http://w3.impa.br/~diego/software/luasocket/tcp.html LuaSocket] API compatibility and does nothing for now. Its functionality will be implemented in future. @@ -5429,7 +5680,7 @@ This feature was first introduced in the v0.5.0rc1 release. == tcpsock:setkeepalive == '''syntax:''' ''ok, err = tcpsock:setkeepalive(timeout?, size?)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' Puts the current socket's connection immediately into the cosocket built-in connection pool and keep it alive until other [[#tcpsock:connect|connect]] method calls request it or the associated maximal idle timeout is expired. @@ -5454,7 +5705,7 @@ This feature was first introduced in the v0.5.0rc1 release. == tcpsock:getreusedtimes == '''syntax:''' ''count, err = tcpsock:getreusedtimes()'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' This method returns the (successfully) reused times for the current connection. In case of error, it returns nil and a string describing the error. @@ -5487,7 +5738,7 @@ This feature was first introduced in the v0.5.0rc1 release. == ngx.get_phase == '''syntax:''' ''str = ngx.get_phase()'' -'''context:''' ''init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Retrieves the current running phase name. Possible return values are @@ -5517,7 +5768,7 @@ This API was first introduced in the v0.5.10 release. == ngx.thread.spawn == '''syntax:''' ''co = ngx.thread.spawn(func, arg1, arg2, ...)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' Spawns a new user "light thread" with the Lua function func as well as those optional arguments arg1, arg2, and etc. Returns a Lua thread (or Lua coroutine) object represents this "light thread". @@ -5650,7 +5901,7 @@ This API was first enabled in the v0.7.0 release. == ngx.thread.wait == '''syntax:''' ''ok, res1, res2, ... = ngx.thread.wait(thread1, thread2, ...)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' Waits on one or more child "light threads" and returns the results of the first "light thread" that terminates (either successfully or with an error). @@ -5913,6 +6164,24 @@ You can pass most of the standard Lua values (nils, booleans, numbers, strings, This API was first introduced in the v0.8.0 release. +== ngx.timer.running_count == +'''syntax:''' ''count = ngx.timer.running_count()'' + +'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' + +Returns the number of timers currently running. + +This directive was first introduced in the v0.9.20 release. + +== ngx.timer.pending_count == +'''syntax:''' ''count = ngx.timer.pending_count()'' + +'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' + +Returns the number of pending timers. + +This directive was first introduced in the v0.9.20 release. + == ngx.config.debug == '''syntax:''' ''debug = ngx.config.debug'' @@ -5982,6 +6251,104 @@ This function returns a Lua number for the process ID (PID) of the current Nginx This API was first introduced in the 0.9.5 release. +== ngx.worker.count == + +'''syntax:''' ''count = ngx.worker.count()'' + +'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, init_by_lua*'' + +Returns the total number of the Nginx worker processes (i.e., the value configured +by the [http://nginx.org/en/docs/ngx_core_module.html#worker_processes worker_processes] +directive in `nginx.conf`). + +This API was first introduced in the 0.9.20 release. + +== ngx.worker.id == + +'''syntax:''' ''count = ngx.worker.id()'' + +'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, init_worker_by_lua*'' + +Returns the ordinal number of the current Nginx worker processes (starting from number 0). + +So if the total number of workers is `N`, then this method may return a number between 0 +and `N - 1` (inclusive). + +This function returns meaningful values only for NGINX 1.9.1+. With earlier versions of NGINX, it +always returns `nil`. + +See also [[#ngx.worker.count|ngx.worker.count]]. + +This API was first introduced in the 0.9.20 release. + +== ngx.semaphore == +'''syntax:''' ''local semaphore = require "ngx.semaphore"'' + +This is a Lua module that implements a classic-style semaphore API for efficient synchronizations among +different "light threads". Sharing the same semaphore among different "light threads" created in different (request) +contexts are also supported as long as the "light threads" reside in the same NGINX worker process +and the [[#lua_code_cache|lua_code_cache]] directive is turned on (which is the default). + +This Lua module does not ship with this ngx_lua module itself rather it is shipped with +the +[https://github.com/openresty/lua-resty-core lua-resty-core] library. + +Please refer to the [https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/semaphore.md documentation] +for this ngx.semaphore Lua module in [https://github.com/openresty/lua-resty-core lua-resty-core] +for more details. + +This feature requires at least ngx_lua v0.10.0. + +== ngx.balancer == +'''syntax:''' ''local balancer = require "ngx.balancer"'' + +This is a Lua module that provides a Lua API to allow defining completely dynamic load balancers +in pure Lua. + +This Lua module does not ship with this ngx_lua module itself rather it is shipped with +the +[https://github.com/openresty/lua-resty-core lua-resty-core] library. + +Please refer to the [https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/balancer.md documentation] +for this ngx.balancer Lua module in [https://github.com/openresty/lua-resty-core lua-resty-core] +for more details. + +This feature requires at least ngx_lua v0.10.0. + +== ngx.ssl == +'''syntax:''' ''local ssl = require "ngx.ssl"'' + +This Lua module provides API functions to control the SSL handshake process in contexts like +[ssl_certificate_by_lua*](#ssl_certificate_by_lua_block). + +This Lua module does not ship with this ngx_lua module itself rather it is shipped with +the +[https://github.com/openresty/lua-resty-core lua-resty-core] library. + +Please refer to the [https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ssl.md documentation] +for this ngx.ssl Lua module for more details. + +This feature requires at least ngx_lua v0.10.0. + +== ngx.ocsp == +'''syntax:''' ''local ocsp = require "ngx.ocsp"'' + +This Lua module provides API to perform OCSP queries, OCSP response validations, and +OCSP stapling planting. + +Usually, this module is used together with the [ngx.ssl](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ssl.md) +module in the +context of [ssl_certificate_by_lua*](#ssl_certificate_by_lua_block). + +This Lua module does not ship with this ngx_lua module itself rather it is shipped with +the +[https://github.com/openresty/lua-resty-core lua-resty-core] library. + +Please refer to the [https://github.com/openresty/lua-resty-core/blob/ocsp-cert-by-lua-2/lib/ngx/ocsp.md documentation] +for this ngx.ocsp Lua module for more details. + +This feature requires at least ngx_lua v0.10.0. + == ndk.set_var.DIRECTIVE == '''syntax:''' ''res = ndk.set_var.DIRECTIVE_NAME'' @@ -6022,7 +6389,7 @@ This feature requires the [https://github.com/simpl/ngx_devel_kit ngx_devel_kit] == coroutine.create == '''syntax:''' ''co = coroutine.create(f)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua*'' Creates a user Lua coroutines with a Lua function, and returns a coroutine object. @@ -6035,7 +6402,7 @@ This API was first introduced in the v0.6.0 release. == coroutine.resume == '''syntax:''' ''ok, ... = coroutine.resume(co, ...)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua*'' Resumes the executation of a user Lua coroutine object previously yielded or just created. @@ -6048,9 +6415,9 @@ This API was first introduced in the v0.6.0 release. == coroutine.yield == '''syntax:''' ''... = coroutine.yield(...)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua*'' -Yields the executation of the current user Lua coroutine. +Yields the execution of the current user Lua coroutine. Similar to the standard Lua [http://www.lua.org/manual/5.1/manual.html#pdf-coroutine.yield coroutine.yield] API, but works in the context of the Lua coroutines created by ngx_lua. @@ -6061,7 +6428,7 @@ This API was first introduced in the v0.6.0 release. == coroutine.wrap == '''syntax:''' ''co = coroutine.wrap(f)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua*'' Similar to the standard Lua [http://www.lua.org/manual/5.1/manual.html#pdf-coroutine.wrap coroutine.wrap] API, but works in the context of the Lua coroutines created by ngx_lua. @@ -6072,7 +6439,7 @@ This API was first introduced in the v0.6.0 release. == coroutine.running == '''syntax:''' ''co = coroutine.running()'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua*'' Identical to the standard Lua [http://www.lua.org/manual/5.1/manual.html#pdf-coroutine.running coroutine.running] API. @@ -6083,7 +6450,7 @@ This API was first enabled in the v0.6.0 release. == coroutine.status == '''syntax:''' ''status = coroutine.status(co)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua*'' Identical to the standard Lua [http://www.lua.org/manual/5.1/manual.html#pdf-coroutine.status coroutine.status] API. diff --git a/debian/modules/nginx-lua/src/api/ngx_http_lua_api.h b/debian/modules/nginx-lua/src/api/ngx_http_lua_api.h index 962c651..84a0579 100644 --- a/debian/modules/nginx-lua/src/api/ngx_http_lua_api.h +++ b/debian/modules/nginx-lua/src/api/ngx_http_lua_api.h @@ -19,7 +19,7 @@ /* Public API for other Nginx modules */ -#define ngx_http_lua_version 9019 +#define ngx_http_lua_version 10000 typedef struct { diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_accessby.c b/debian/modules/nginx-lua/src/ngx_http_lua_accessby.c index 8a82e07..14cc342 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_accessby.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_accessby.c @@ -176,7 +176,8 @@ ngx_http_lua_access_handler_inline(ngx_http_request_t *r) L = ngx_http_lua_get_lua_vm(r, NULL); /* load Lua inline script (w/ cache) sp = 1 */ - rc = ngx_http_lua_cache_loadbuffer(r, L, llcf->access_src.value.data, + rc = ngx_http_lua_cache_loadbuffer(r->connection->log, L, + llcf->access_src.value.data, llcf->access_src.value.len, llcf->access_src_key, (const char *) llcf->access_chunkname); @@ -215,7 +216,8 @@ ngx_http_lua_access_handler_file(ngx_http_request_t *r) L = ngx_http_lua_get_lua_vm(r, NULL); /* load Lua script file (w/ cache) sp = 1 */ - rc = ngx_http_lua_cache_loadfile(r, L, script_path, llcf->access_src_key); + rc = ngx_http_lua_cache_loadfile(r->connection->log, L, script_path, + llcf->access_src_key); if (rc != NGX_OK) { if (rc < NGX_HTTP_SPECIAL_RESPONSE) { return NGX_HTTP_INTERNAL_SERVER_ERROR; diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_args.c b/debian/modules/nginx-lua/src/ngx_http_lua_args.c index d1376bd..dbc2ac6 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_args.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_args.c @@ -113,6 +113,11 @@ ngx_http_lua_ngx_req_get_uri_args(lua_State *L) lua_createtable(L, 0, 4); + if (r->args.len == 0) { + lua_createtable(L, 0, 0); + return 1; + } + /* we copy r->args over to buf to simplify * unescaping query arg keys and values */ @@ -197,6 +202,11 @@ ngx_http_lua_ngx_req_get_post_args(lua_State *L) dd("post body length: %d", (int) len); + if (len == 0) { + lua_createtable(L, 0, 0); + return 1; + } + buf = ngx_palloc(r->pool, len); if (buf == NULL) { return luaL_error(L, "no memory"); @@ -379,7 +389,7 @@ ngx_http_lua_ffi_req_get_uri_args_count(ngx_http_request_t *r, int max) int count; u_char *p, *last; - if (r->connection->fd == -1) { + if (r->connection->fd == (ngx_socket_t) -1) { return NGX_HTTP_LUA_FFI_BAD_CONTEXT; } diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_balancer.c b/debian/modules/nginx-lua/src/ngx_http_lua_balancer.c new file mode 100644 index 0000000..4fa91fc --- /dev/null +++ b/debian/modules/nginx-lua/src/ngx_http_lua_balancer.c @@ -0,0 +1,607 @@ + +/* + * Copyright (C) Yichun Zhang (agentzh) + */ + + +#ifndef DDEBUG +#define DDEBUG 0 +#endif +#include "ddebug.h" + + +#include "ngx_http_lua_cache.h" +#include "ngx_http_lua_balancer.h" +#include "ngx_http_lua_util.h" +#include "ngx_http_lua_directive.h" + + +struct ngx_http_lua_balancer_peer_data_s { + /* the round robin data must be first */ + ngx_http_upstream_rr_peer_data_t rrp; + + ngx_http_lua_srv_conf_t *conf; + ngx_http_request_t *request; + + ngx_event_get_peer_pt get_rr_peer; + + ngx_uint_t more_tries; + ngx_uint_t total_tries; + + struct sockaddr *sockaddr; + socklen_t socklen; + + ngx_str_t host; + in_port_t port; + + int last_peer_state; +}; + + +static ngx_int_t ngx_http_lua_balancer_init(ngx_conf_t *cf, + ngx_http_upstream_srv_conf_t *us); +static ngx_int_t ngx_http_lua_balancer_init_peer(ngx_http_request_t *r, + ngx_http_upstream_srv_conf_t *us); +static ngx_int_t ngx_http_lua_balancer_get_peer(ngx_peer_connection_t *pc, + void *data); +static ngx_int_t ngx_http_lua_balancer_by_chunk(lua_State *L, + ngx_http_request_t *r); +void ngx_http_lua_balancer_free_peer(ngx_peer_connection_t *pc, void *data, + ngx_uint_t state); + + +ngx_int_t +ngx_http_lua_balancer_handler_file(ngx_http_request_t *r, + ngx_http_lua_srv_conf_t *lscf, lua_State *L) +{ + ngx_int_t rc; + + rc = ngx_http_lua_cache_loadfile(r->connection->log, L, + lscf->balancer.src.data, + lscf->balancer.src_key); + if (rc != NGX_OK) { + return rc; + } + + /* make sure we have a valid code chunk */ + ngx_http_lua_assert(lua_isfunction(L, -1)); + + return ngx_http_lua_balancer_by_chunk(L, r); +} + + +ngx_int_t +ngx_http_lua_balancer_handler_inline(ngx_http_request_t *r, + ngx_http_lua_srv_conf_t *lscf, lua_State *L) +{ + ngx_int_t rc; + + rc = ngx_http_lua_cache_loadbuffer(r->connection->log, L, + lscf->balancer.src.data, + lscf->balancer.src.len, + lscf->balancer.src_key, + "=balancer_by_lua"); + if (rc != NGX_OK) { + return rc; + } + + /* make sure we have a valid code chunk */ + ngx_http_lua_assert(lua_isfunction(L, -1)); + + return ngx_http_lua_balancer_by_chunk(L, r); +} + + +char * +ngx_http_lua_balancer_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) +{ + char *rv; + ngx_conf_t save; + + save = *cf; + cf->handler = ngx_http_lua_balancer_by_lua; + cf->handler_conf = conf; + + rv = ngx_http_lua_conf_lua_block_parse(cf, cmd); + + *cf = save; + + return rv; +} + + +char * +ngx_http_lua_balancer_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) +{ + u_char *p; + u_char *name; + ngx_str_t *value; + ngx_http_lua_srv_conf_t *lscf = conf; + + ngx_http_upstream_srv_conf_t *uscf; + + dd("enter"); + + /* must specifiy a content handler */ + if (cmd->post == NULL) { + return NGX_CONF_ERROR; + } + + if (lscf->balancer.handler) { + return "is duplicate"; + } + + value = cf->args->elts; + + lscf->balancer.handler = (ngx_http_lua_srv_conf_handler_pt) cmd->post; + + if (cmd->post == ngx_http_lua_balancer_handler_file) { + /* Lua code in an external file */ + + name = ngx_http_lua_rebase_path(cf->pool, value[1].data, + value[1].len); + if (name == NULL) { + return NGX_CONF_ERROR; + } + + lscf->balancer.src.data = name; + lscf->balancer.src.len = ngx_strlen(name); + + p = ngx_palloc(cf->pool, NGX_HTTP_LUA_FILE_KEY_LEN + 1); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + lscf->balancer.src_key = p; + + p = ngx_copy(p, NGX_HTTP_LUA_FILE_TAG, NGX_HTTP_LUA_FILE_TAG_LEN); + p = ngx_http_lua_digest_hex(p, value[1].data, value[1].len); + *p = '\0'; + + } else { + /* inlined Lua code */ + + lscf->balancer.src = value[1]; + + p = ngx_palloc(cf->pool, NGX_HTTP_LUA_INLINE_KEY_LEN + 1); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + lscf->balancer.src_key = p; + + p = ngx_copy(p, NGX_HTTP_LUA_INLINE_TAG, NGX_HTTP_LUA_INLINE_TAG_LEN); + p = ngx_http_lua_digest_hex(p, value[1].data, value[1].len); + *p = '\0'; + } + + uscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module); + + if (uscf->peer.init_upstream) { + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, + "load balancing method redefined"); + } + + uscf->peer.init_upstream = ngx_http_lua_balancer_init; + + uscf->flags = NGX_HTTP_UPSTREAM_CREATE + |NGX_HTTP_UPSTREAM_WEIGHT + |NGX_HTTP_UPSTREAM_MAX_FAILS + |NGX_HTTP_UPSTREAM_FAIL_TIMEOUT + |NGX_HTTP_UPSTREAM_DOWN; + + return NGX_CONF_OK; +} + + +static ngx_int_t +ngx_http_lua_balancer_init(ngx_conf_t *cf, + ngx_http_upstream_srv_conf_t *us) +{ + if (ngx_http_upstream_init_round_robin(cf, us) != NGX_OK) { + return NGX_ERROR; + } + + /* this callback is called upon individual requests */ + us->peer.init = ngx_http_lua_balancer_init_peer; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_lua_balancer_init_peer(ngx_http_request_t *r, + ngx_http_upstream_srv_conf_t *us) +{ + ngx_http_lua_srv_conf_t *bcf; + ngx_http_lua_balancer_peer_data_t *bp; + + bp = ngx_pcalloc(r->pool, sizeof(ngx_http_lua_balancer_peer_data_t)); + if (bp == NULL) { + return NGX_ERROR; + } + + r->upstream->peer.data = &bp->rrp; + + if (ngx_http_upstream_init_round_robin_peer(r, us) != NGX_OK) { + return NGX_ERROR; + } + + r->upstream->peer.get = ngx_http_lua_balancer_get_peer; + r->upstream->peer.free = ngx_http_lua_balancer_free_peer; + + bcf = ngx_http_conf_upstream_srv_conf(us, ngx_http_lua_module); + + bp->conf = bcf; + bp->get_rr_peer = ngx_http_upstream_get_round_robin_peer; + bp->request = r; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_lua_balancer_get_peer(ngx_peer_connection_t *pc, void *data) +{ + lua_State *L; + ngx_int_t rc; + ngx_http_request_t *r; + ngx_http_lua_ctx_t *ctx; + ngx_http_lua_srv_conf_t *lscf; + ngx_http_lua_main_conf_t *lmcf; + ngx_http_lua_balancer_peer_data_t *bp = data; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, + "lua balancer peer, try: %ui", pc->tries); + + lscf = bp->conf; + + r = bp->request; + + ngx_http_lua_assert(lscf->balancer.handler && r); + + L = ngx_http_lua_get_lua_vm(r, NULL); + + bp->sockaddr = NULL; + bp->socklen = 0; + bp->more_tries = 0; + bp->total_tries++; + + lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); + + /* balancer_by_lua does not support yielding and + * there cannot be any conflicts among concurrent requests, + * thus it is safe to store the peer data in the main conf. + */ + lmcf->balancer_peer_data = bp; + + rc = lscf->balancer.handler(r, lscf, L); + + if (rc == NGX_ERROR) { + return NGX_ERROR; + } + + ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); + + if (ctx->exited && ctx->exit_code != NGX_OK) { + rc = ctx->exit_code; + if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) { + return rc; + } + + if (rc > NGX_OK) { + return NGX_ERROR; + } + } + + if (bp->sockaddr && bp->socklen) { + pc->sockaddr = bp->sockaddr; + pc->socklen = bp->socklen; + pc->name = &bp->host; + bp->rrp.peers->single = 0; + + if (bp->more_tries) { + r->upstream->peer.tries += bp->more_tries; + } + + dd("tries: %d", (int) r->upstream->peer.tries); + + return NGX_OK; + } + + return bp->get_rr_peer(pc, &bp->rrp); +} + + +static ngx_int_t +ngx_http_lua_balancer_by_chunk(lua_State *L, ngx_http_request_t *r) +{ + u_char *err_msg; + size_t len; + ngx_int_t rc; + ngx_http_lua_ctx_t *ctx; + + ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); + + if (ctx == NULL) { + ctx = ngx_http_lua_create_ctx(r); + if (ctx == NULL) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + } else { + dd("reset ctx"); + ngx_http_lua_reset_ctx(r, L, ctx); + } + + ctx->context = NGX_HTTP_LUA_CONTEXT_BALANCER; + + /* init nginx context in Lua VM */ + ngx_http_lua_set_req(L, r); + ngx_http_lua_create_new_globals_table(L, 0 /* narr */, 1 /* nrec */); + + /* {{{ make new env inheriting main thread's globals table */ + lua_createtable(L, 0, 1 /* nrec */); /* the metatable for the new env */ + ngx_http_lua_get_globals_table(L); + lua_setfield(L, -2, "__index"); + lua_setmetatable(L, -2); /* setmetatable({}, {__index = _G}) */ + /* }}} */ + + lua_setfenv(L, -2); /* set new running env for the code closure */ + + lua_pushcfunction(L, ngx_http_lua_traceback); + lua_insert(L, 1); /* put it under chunk and args */ + + /* protected call user code */ + rc = lua_pcall(L, 0, 1, 1); + + lua_remove(L, 1); /* remove traceback function */ + + dd("rc == %d", (int) rc); + + if (rc != 0) { + /* error occured when running loaded code */ + err_msg = (u_char *) lua_tolstring(L, -1, &len); + + if (err_msg == NULL) { + err_msg = (u_char *) "unknown reason"; + len = sizeof("unknown reason") - 1; + } + + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "failed to run balancer_by_lua*: %*s", len, err_msg); + + lua_settop(L, 0); /* clear remaining elems on stack */ + + return NGX_ERROR; + } + + lua_settop(L, 0); /* clear remaining elems on stack */ + return rc; +} + + +void +ngx_http_lua_balancer_free_peer(ngx_peer_connection_t *pc, void *data, + ngx_uint_t state) +{ + ngx_http_lua_balancer_peer_data_t *bp = data; + + if (bp->sockaddr && bp->socklen) { + bp->last_peer_state = (int) state; + + if (pc->tries) { + pc->tries--; + } + + return; + } + + /* fallback */ + + ngx_http_upstream_free_round_robin_peer(pc, data, state); +} + + +#ifndef NGX_LUA_NO_FFI_API + +int +ngx_http_lua_ffi_balancer_set_current_peer(ngx_http_request_t *r, + const u_char *addr, size_t addr_len, int port, char **err) +{ + ngx_url_t url; + ngx_http_lua_ctx_t *ctx; + ngx_http_upstream_t *u; + + ngx_http_lua_main_conf_t *lmcf; + ngx_http_lua_balancer_peer_data_t *bp; + + if (r == NULL) { + *err = "no request found"; + return NGX_ERROR; + } + + u = r->upstream; + + if (u == NULL) { + *err = "no upstream found"; + return NGX_ERROR; + } + + ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); + if (ctx == NULL) { + *err = "no ctx found"; + return NGX_ERROR; + } + + if ((ctx->context & NGX_HTTP_LUA_CONTEXT_BALANCER) == 0) { + *err = "API disabled in the current context"; + return NGX_ERROR; + } + + lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); + + /* we cannot read r->upstream->peer.data here directly because + * it could be overridden by other modules like + * ngx_http_upstream_keepalive_module. + */ + bp = lmcf->balancer_peer_data; + if (bp == NULL) { + *err = "no upstream peer data found"; + return NGX_ERROR; + } + + ngx_memzero(&url, sizeof(ngx_url_t)); + + url.url.data = ngx_palloc(r->pool, addr_len); + if (url.url.data == NULL) { + *err = "no memory"; + return NGX_ERROR; + } + + ngx_memcpy(url.url.data, addr, addr_len); + + url.url.len = addr_len; + url.default_port = (in_port_t) port; + url.uri_part = 0; + url.no_resolve = 1; + + if (ngx_parse_url(r->pool, &url) != NGX_OK) { + if (url.err) { + *err = url.err; + } + + return NGX_ERROR; + } + + if (url.addrs && url.addrs[0].sockaddr) { + bp->sockaddr = url.addrs[0].sockaddr; + bp->socklen = url.addrs[0].socklen; + bp->host = url.addrs[0].name; + + } else { + *err = "no host allowed"; + return NGX_ERROR; + } + + return NGX_OK; +} + + +int +ngx_http_lua_ffi_balancer_set_more_tries(ngx_http_request_t *r, + int count, char **err) +{ + ngx_uint_t max_tries; + ngx_http_lua_ctx_t *ctx; + ngx_http_upstream_t *u; + + ngx_http_lua_main_conf_t *lmcf; + ngx_http_lua_balancer_peer_data_t *bp; + + if (r == NULL) { + *err = "no request found"; + return NGX_ERROR; + } + + u = r->upstream; + + if (u == NULL) { + *err = "no upstream found"; + return NGX_ERROR; + } + + ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); + if (ctx == NULL) { + *err = "no ctx found"; + return NGX_ERROR; + } + + if ((ctx->context & NGX_HTTP_LUA_CONTEXT_BALANCER) == 0) { + *err = "API disabled in the current context"; + return NGX_ERROR; + } + + lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); + + bp = lmcf->balancer_peer_data; + if (bp == NULL) { + *err = "no upstream peer data found"; + return NGX_ERROR; + } + +#if (nginx_version >= 1007005) + max_tries = r->upstream->conf->next_upstream_tries; + + if (bp->total_tries + count > max_tries) { + count = max_tries - bp->total_tries; + *err = "reduced tries due to limit"; + + } else { + *err = NULL; + } +#else + *err = NULL; +#endif + + bp->more_tries = count; + return NGX_OK; +} + + +int +ngx_http_lua_ffi_balancer_get_last_failure(ngx_http_request_t *r, + int *status, char **err) +{ + ngx_http_lua_ctx_t *ctx; + ngx_http_upstream_t *u; + ngx_http_upstream_state_t *state; + + ngx_http_lua_balancer_peer_data_t *bp; + ngx_http_lua_main_conf_t *lmcf; + + if (r == NULL) { + *err = "no request found"; + return NGX_ERROR; + } + + u = r->upstream; + + if (u == NULL) { + *err = "no upstream found"; + return NGX_ERROR; + } + + ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); + if (ctx == NULL) { + *err = "no ctx found"; + return NGX_ERROR; + } + + if ((ctx->context & NGX_HTTP_LUA_CONTEXT_BALANCER) == 0) { + *err = "API disabled in the current context"; + return NGX_ERROR; + } + + lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); + + bp = lmcf->balancer_peer_data; + if (bp == NULL) { + *err = "no upstream peer data found"; + return NGX_ERROR; + } + + if (r->upstream_states && r->upstream_states->nelts > 1) { + state = r->upstream_states->elts; + *status = (int) state[r->upstream_states->nelts - 2].status; + + } else { + *status = 0; + } + + return bp->last_peer_state; +} + +#endif /* NGX_LUA_NO_FFI_API */ diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_balancer.h b/debian/modules/nginx-lua/src/ngx_http_lua_balancer.h new file mode 100644 index 0000000..bb49dc0 --- /dev/null +++ b/debian/modules/nginx-lua/src/ngx_http_lua_balancer.h @@ -0,0 +1,27 @@ + +/* + * Copyright (C) Yichun Zhang (agentzh) + */ + + +#ifndef _NGX_HTTP_LUA_BALANCER_H_INCLUDED_ +#define _NGX_HTTP_LUA_BALANCER_H_INCLUDED_ + + +#include "ngx_http_lua_common.h" + + +ngx_int_t ngx_http_lua_balancer_handler_inline(ngx_http_request_t *r, + ngx_http_lua_srv_conf_t *lscf, lua_State *L); + +ngx_int_t ngx_http_lua_balancer_handler_file(ngx_http_request_t *r, + ngx_http_lua_srv_conf_t *lscf, lua_State *L); + +char *ngx_http_lua_balancer_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); + +char *ngx_http_lua_balancer_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); + + +#endif /* _NGX_HTTP_LUA_BALANCER_H_INCLUDED_ */ diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_bodyfilterby.c b/debian/modules/nginx-lua/src/ngx_http_lua_bodyfilterby.c index a07a0d9..86e347e 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_bodyfilterby.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_bodyfilterby.c @@ -160,7 +160,8 @@ ngx_http_lua_body_filter_inline(ngx_http_request_t *r, ngx_chain_t *in) L = ngx_http_lua_get_lua_vm(r, NULL); /* load Lua inline script (w/ cache) sp = 1 */ - rc = ngx_http_lua_cache_loadbuffer(r, L, llcf->body_filter_src.value.data, + rc = ngx_http_lua_cache_loadbuffer(r->connection->log, L, + llcf->body_filter_src.value.data, llcf->body_filter_src.value.len, llcf->body_filter_src_key, "=body_filter_by_lua"); @@ -208,7 +209,7 @@ ngx_http_lua_body_filter_file(ngx_http_request_t *r, ngx_chain_t *in) L = ngx_http_lua_get_lua_vm(r, NULL); /* load Lua script file (w/ cache) sp = 1 */ - rc = ngx_http_lua_cache_loadfile(r, L, script_path, + rc = ngx_http_lua_cache_loadfile(r->connection->log, L, script_path, llcf->body_filter_src_key); if (rc != NGX_OK) { return NGX_ERROR; diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_cache.c b/debian/modules/nginx-lua/src/ngx_http_lua_cache.c index 6a1655f..e8a132e 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_cache.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_cache.c @@ -32,7 +32,7 @@ * * */ static ngx_int_t -ngx_http_lua_cache_load_code(ngx_http_request_t *r, lua_State *L, +ngx_http_lua_cache_load_code(ngx_log_t *log, lua_State *L, const char *key) { int rc; @@ -68,7 +68,7 @@ ngx_http_lua_cache_load_code(ngx_http_request_t *r, lua_State *L, err = (u_char *) "unknown error"; } - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + ngx_log_error(NGX_LOG_ERR, log, 0, "lua: failed to run factory at key \"%s\": %s", key, err); lua_pop(L, 2); @@ -133,7 +133,7 @@ ngx_http_lua_cache_store_code(lua_State *L, const char *key) ngx_int_t -ngx_http_lua_cache_loadbuffer(ngx_http_request_t *r, lua_State *L, +ngx_http_lua_cache_loadbuffer(ngx_log_t *log, lua_State *L, const u_char *src, size_t src_len, const u_char *cache_key, const char *name) { @@ -145,7 +145,7 @@ ngx_http_lua_cache_loadbuffer(ngx_http_request_t *r, lua_State *L, dd("XXX cache key: [%s]", cache_key); - rc = ngx_http_lua_cache_load_code(r, L, (char *) cache_key); + rc = ngx_http_lua_cache_load_code(log, L, (char *) cache_key); if (rc == NGX_OK) { /* code chunk loaded from cache, sp++ */ dd("Code cache hit! cache key='%s', stack top=%d, script='%.*s'", @@ -194,7 +194,7 @@ ngx_http_lua_cache_loadbuffer(ngx_http_request_t *r, lua_State *L, error: - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + ngx_log_error(NGX_LOG_ERR, log, 0, "failed to load inlined Lua code: %s", err); lua_settop(L, n); return NGX_ERROR; @@ -202,7 +202,7 @@ error: ngx_int_t -ngx_http_lua_cache_loadfile(ngx_http_request_t *r, lua_State *L, +ngx_http_lua_cache_loadfile(ngx_log_t *log, lua_State *L, const u_char *script, const u_char *cache_key) { int n; @@ -229,7 +229,7 @@ ngx_http_lua_cache_loadfile(ngx_http_request_t *r, lua_State *L, dd("XXX cache key for file: [%s]", cache_key); - rc = ngx_http_lua_cache_load_code(r, L, (char *) cache_key); + rc = ngx_http_lua_cache_load_code(log, L, (char *) cache_key); if (rc == NGX_OK) { /* code chunk loaded from cache, sp++ */ dd("Code cache hit! cache key='%s', stack top=%d, file path='%s'", @@ -286,7 +286,7 @@ ngx_http_lua_cache_loadfile(ngx_http_request_t *r, lua_State *L, error: - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + ngx_log_error(NGX_LOG_ERR, log, 0, "failed to load external Lua file \"%s\": %s", script, err); lua_settop(L, n); diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_cache.h b/debian/modules/nginx-lua/src/ngx_http_lua_cache.h index 64c4aa2..52e6d2c 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_cache.h +++ b/debian/modules/nginx-lua/src/ngx_http_lua_cache.h @@ -12,10 +12,10 @@ #include "ngx_http_lua_common.h" -ngx_int_t ngx_http_lua_cache_loadbuffer(ngx_http_request_t *r, lua_State *L, +ngx_int_t ngx_http_lua_cache_loadbuffer(ngx_log_t *log, lua_State *L, const u_char *src, size_t src_len, const u_char *cache_key, const char *name); -ngx_int_t ngx_http_lua_cache_loadfile(ngx_http_request_t *r, lua_State *L, +ngx_int_t ngx_http_lua_cache_loadfile(ngx_log_t *log, lua_State *L, const u_char *script, const u_char *cache_key); diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_clfactory.c b/debian/modules/nginx-lua/src/ngx_http_lua_clfactory.c index 221f952..86885bb 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_clfactory.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_clfactory.c @@ -368,7 +368,7 @@ ngx_http_lua_clfactory_bytecode_prepare(lua_State *L, dd("==LJ_BT_HEADER=="); size_t i; for (i = 0; i < LJ_HEADERSIZE; i++) { - dd("%ld: 0x%02X", i, (unsigned)(u_char)lf->begin_code.str[i]); + dd("%ld: 0x%02X", i, (unsigned)(u_char) lf->begin_code.str[i]); } dd("==LJ_BT_HEADER_END=="); } @@ -471,7 +471,7 @@ ngx_http_lua_clfactory_bytecode_prepare(lua_State *L, dd("==LUA_BT_HEADER=="); size_t i; for (i = 0; i < LUAC_HEADERSIZE; i++) { - dd("%ld, 0x%02X", i, (unsigned)(u_char)lf->begin_code.str[i]); + dd("%ld, 0x%02X", i, (unsigned)(u_char) lf->begin_code.str[i]); } dd("==LUA_BT_HEADER_END=="); } diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_common.h b/debian/modules/nginx-lua/src/ngx_http_lua_common.h index 582815c..e7b9969 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_common.h +++ b/debian/modules/nginx-lua/src/ngx_http_lua_common.h @@ -21,6 +21,12 @@ #include #include + +#if !defined(nginx_version) || (nginx_version < 1006000) +#error at least nginx 1.6.0 is required but found an older version +#endif + + #if defined(NDK) && NDK #include #endif @@ -31,6 +37,11 @@ #endif +#if (!defined OPENSSL_NO_OCSP && defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB) +# define NGX_HTTP_LUA_USE_OCSP 1 +#endif + + #ifndef MD5_DIGEST_LENGTH #define MD5_DIGEST_LENGTH 16 #endif @@ -94,6 +105,8 @@ typedef struct { #define NGX_HTTP_LUA_CONTEXT_BODY_FILTER 0x040 #define NGX_HTTP_LUA_CONTEXT_TIMER 0x080 #define NGX_HTTP_LUA_CONTEXT_INIT_WORKER 0x100 +#define NGX_HTTP_LUA_CONTEXT_BALANCER 0x200 +#define NGX_HTTP_LUA_CONTEXT_SSL_CERT 0x400 #ifndef NGX_LUA_NO_FFI_API @@ -102,11 +115,21 @@ typedef struct { #endif -typedef struct ngx_http_lua_main_conf_s ngx_http_lua_main_conf_t; +typedef struct ngx_http_lua_main_conf_s ngx_http_lua_main_conf_t; +typedef union ngx_http_lua_srv_conf_u ngx_http_lua_srv_conf_t; -typedef ngx_int_t (*ngx_http_lua_conf_handler_pt)(ngx_log_t *log, - ngx_http_lua_main_conf_t *lmcf, lua_State *L); +typedef struct ngx_http_lua_balancer_peer_data_s + ngx_http_lua_balancer_peer_data_t; + + +typedef struct ngx_http_lua_semaphore_mm_s ngx_http_lua_semaphore_mm_t; + + +typedef ngx_int_t (*ngx_http_lua_main_conf_handler_pt)(ngx_log_t *log, + ngx_http_lua_main_conf_t *lmcf, lua_State *L); +typedef ngx_int_t (*ngx_http_lua_srv_conf_handler_pt)(ngx_http_request_t *r, + ngx_http_lua_srv_conf_t *lmcf, lua_State *L); typedef struct { @@ -145,14 +168,22 @@ struct ngx_http_lua_main_conf_s { ngx_flag_t postponed_to_rewrite_phase_end; ngx_flag_t postponed_to_access_phase_end; - ngx_http_lua_conf_handler_pt init_handler; - ngx_str_t init_src; + ngx_http_lua_main_conf_handler_pt init_handler; + ngx_str_t init_src; - ngx_http_lua_conf_handler_pt init_worker_handler; - ngx_str_t init_worker_src; + ngx_http_lua_main_conf_handler_pt init_worker_handler; + ngx_str_t init_worker_src; + + ngx_http_lua_balancer_peer_data_t *balancer_peer_data; + /* balancer_by_lua does not support yielding and + * there cannot be any conflicts among concurrent requests, + * thus it is safe to store the peer data in the main conf. + */ ngx_uint_t shm_zones_inited; + ngx_http_lua_semaphore_mm_t *semaphore_mm; + unsigned requires_header_filter:1; unsigned requires_body_filter:1; unsigned requires_capture_filter:1; @@ -163,6 +194,24 @@ struct ngx_http_lua_main_conf_s { }; +union ngx_http_lua_srv_conf_u { +#if (NGX_HTTP_SSL) + struct { + ngx_http_lua_srv_conf_handler_pt cert_handler; + ngx_str_t cert_src; + u_char *cert_src_key; + } ssl; +#endif + + struct { + ngx_str_t src; + u_char *src_key; + + ngx_http_lua_srv_conf_handler_pt handler; + } balancer; +}; + + typedef struct { #if (NGX_HTTP_SSL) ngx_ssl_t *ssl; /* shared by SSL cosockets */ @@ -303,6 +352,8 @@ struct ngx_http_lua_co_ctx_s { ngx_event_t sleep; /* used for ngx.sleep */ + ngx_queue_t sem_wait_queue; + #ifdef NGX_LUA_USE_ASSERT int co_top; /* stack top after yielding/creation, only for sanity checks */ @@ -330,6 +381,7 @@ struct ngx_http_lua_co_ctx_s { unsigned thread_spawn_yielded:1; /* yielded from the ngx.thread.spawn() call */ + unsigned sem_resume_status:1; }; @@ -372,6 +424,8 @@ typedef struct ngx_http_lua_ctx_s { ngx_http_cleanup_pt *cleanup; + ngx_http_cleanup_t *free_cleanup; /* free list of cleanup records */ + ngx_chain_t *body; /* buffered subrequest response body chains */ @@ -451,7 +505,7 @@ typedef struct ngx_http_lua_ctx_s { } ngx_http_lua_ctx_t; -typedef struct ngx_http_lua_header_val_s ngx_http_lua_header_val_t; +typedef struct ngx_http_lua_header_val_s ngx_http_lua_header_val_t; typedef ngx_int_t (*ngx_http_lua_set_header_pt)(ngx_http_request_t *r, diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_consts.c b/debian/modules/nginx-lua/src/ngx_http_lua_consts.c index ebf8724..30a86f1 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_consts.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_consts.c @@ -89,12 +89,27 @@ ngx_http_lua_inject_http_consts(lua_State *L) lua_setfield(L, -2, "HTTP_TRACE"); /* }}} */ + lua_pushinteger(L, NGX_HTTP_CONTINUE); + lua_setfield(L, -2, "HTTP_CONTINUE"); + + lua_pushinteger(L, NGX_HTTP_SWITCHING_PROTOCOLS); + lua_setfield(L, -2, "HTTP_SWITCHING_PROTOCOLS"); + lua_pushinteger(L, NGX_HTTP_OK); lua_setfield(L, -2, "HTTP_OK"); lua_pushinteger(L, NGX_HTTP_CREATED); lua_setfield(L, -2, "HTTP_CREATED"); + lua_pushinteger(L, NGX_HTTP_ACCEPTED); + lua_setfield(L, -2, "HTTP_ACCEPTED"); + + lua_pushinteger(L, NGX_HTTP_NO_CONTENT); + lua_setfield(L, -2, "HTTP_NO_CONTENT"); + + lua_pushinteger(L, NGX_HTTP_PARTIAL_CONTENT); + lua_setfield(L, -2, "HTTP_PARTIAL_CONTENT"); + lua_pushinteger(L, NGX_HTTP_SPECIAL_RESPONSE); lua_setfield(L, -2, "HTTP_SPECIAL_RESPONSE"); @@ -112,12 +127,17 @@ ngx_http_lua_inject_http_consts(lua_State *L) lua_pushinteger(L, NGX_HTTP_NOT_MODIFIED); lua_setfield(L, -2, "HTTP_NOT_MODIFIED"); + lua_pushinteger(L, NGX_HTTP_TEMPORARY_REDIRECT); + lua_setfield(L, -2, "HTTP_TEMPORARY_REDIRECT"); + lua_pushinteger(L, NGX_HTTP_BAD_REQUEST); lua_setfield(L, -2, "HTTP_BAD_REQUEST"); lua_pushinteger(L, NGX_HTTP_UNAUTHORIZED); lua_setfield(L, -2, "HTTP_UNAUTHORIZED"); + lua_pushinteger(L, 402); + lua_setfield(L, -2, "HTTP_PAYMENT_REQUIRED"); lua_pushinteger(L, NGX_HTTP_FORBIDDEN); lua_setfield(L, -2, "HTTP_FORBIDDEN"); @@ -128,20 +148,51 @@ ngx_http_lua_inject_http_consts(lua_State *L) lua_pushinteger(L, NGX_HTTP_NOT_ALLOWED); lua_setfield(L, -2, "HTTP_NOT_ALLOWED"); + lua_pushinteger(L, 406); + lua_setfield(L, -2, "HTTP_NOT_ACCEPTABLE"); + + lua_pushinteger(L, NGX_HTTP_REQUEST_TIME_OUT); + lua_setfield(L, -2, "HTTP_REQUEST_TIMEOUT"); + + lua_pushinteger(L, NGX_HTTP_CONFLICT); + lua_setfield(L, -2, "HTTP_CONFLICT"); + lua_pushinteger(L, 410); lua_setfield(L, -2, "HTTP_GONE"); + lua_pushinteger(L, 426); + lua_setfield(L, -2, "HTTP_UPGRADE_REQUIRED"); + + lua_pushinteger(L, 429); + lua_setfield(L, -2, "HTTP_TOO_MANY_REQUESTS"); + + lua_pushinteger(L, 451); + lua_setfield(L, -2, "HTTP_ILLEGAL"); + + lua_pushinteger(L, NGX_HTTP_CLOSE); + lua_setfield(L, -2, "HTTP_CLOSE"); + lua_pushinteger(L, NGX_HTTP_INTERNAL_SERVER_ERROR); lua_setfield(L, -2, "HTTP_INTERNAL_SERVER_ERROR"); lua_pushinteger(L, NGX_HTTP_NOT_IMPLEMENTED); lua_setfield(L, -2, "HTTP_METHOD_NOT_IMPLEMENTED"); + lua_pushinteger(L, NGX_HTTP_BAD_GATEWAY); + lua_setfield(L, -2, "HTTP_BAD_GATEWAY"); + lua_pushinteger(L, NGX_HTTP_SERVICE_UNAVAILABLE); lua_setfield(L, -2, "HTTP_SERVICE_UNAVAILABLE"); lua_pushinteger(L, NGX_HTTP_GATEWAY_TIME_OUT); lua_setfield(L, -2, "HTTP_GATEWAY_TIMEOUT"); + + lua_pushinteger(L, 505); + lua_setfield(L, -2, "HTTP_VERSION_NOT_SUPPORTED"); + + lua_pushinteger(L, NGX_HTTP_INSUFFICIENT_STORAGE); + lua_setfield(L, -2, "HTTP_INSUFFICIENT_STORAGE"); + /* }}} */ } diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_contentby.c b/debian/modules/nginx-lua/src/ngx_http_lua_contentby.c index 9234dd9..666b549 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_contentby.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_contentby.c @@ -54,7 +54,7 @@ ngx_http_lua_content_by_chunk(lua_State *L, ngx_http_request_t *r) if (co == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "lua: failed to create new coroutine to handle request"); + "lua: failed to create new coroutine to handle request"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } @@ -251,7 +251,7 @@ ngx_http_lua_content_handler_file(ngx_http_request_t *r) L = ngx_http_lua_get_lua_vm(r, NULL); /* load Lua script file (w/ cache) sp = 1 */ - rc = ngx_http_lua_cache_loadfile(r, L, script_path, + rc = ngx_http_lua_cache_loadfile(r->connection->log, L, script_path, llcf->content_src_key); if (rc != NGX_OK) { if (rc < NGX_HTTP_SPECIAL_RESPONSE) { @@ -280,7 +280,8 @@ ngx_http_lua_content_handler_inline(ngx_http_request_t *r) L = ngx_http_lua_get_lua_vm(r, NULL); /* load Lua inline script (w/ cache) sp = 1 */ - rc = ngx_http_lua_cache_loadbuffer(r, L, llcf->content_src.value.data, + rc = ngx_http_lua_cache_loadbuffer(r->connection->log, L, + llcf->content_src.value.data, llcf->content_src.value.len, llcf->content_src_key, (const char *) diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_contentby.h b/debian/modules/nginx-lua/src/ngx_http_lua_contentby.h index 766baa6..58ba8e1 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_contentby.h +++ b/debian/modules/nginx-lua/src/ngx_http_lua_contentby.h @@ -12,7 +12,7 @@ #include "ngx_http_lua_common.h" -ngx_int_t ngx_http_lua_content_by_chunk(lua_State *l, ngx_http_request_t *r); +ngx_int_t ngx_http_lua_content_by_chunk(lua_State *L, ngx_http_request_t *r); void ngx_http_lua_content_wev_handler(ngx_http_request_t *r); ngx_int_t ngx_http_lua_content_handler_file(ngx_http_request_t *r); ngx_int_t ngx_http_lua_content_handler_inline(ngx_http_request_t *r); diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_control.c b/debian/modules/nginx-lua/src/ngx_http_lua_control.c index 6105edd..0e1dd47 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_control.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_control.c @@ -10,6 +10,7 @@ #endif #include "ddebug.h" + #include "ngx_http_lua_control.h" #include "ngx_http_lua_util.h" #include "ngx_http_lua_coroutine.h" @@ -209,12 +210,15 @@ ngx_http_lua_ngx_redirect(lua_State *L) if (n == 2) { rc = (ngx_int_t) luaL_checknumber(L, 2); - if (rc != NGX_HTTP_MOVED_TEMPORARILY && - rc != NGX_HTTP_MOVED_PERMANENTLY) + if (rc != NGX_HTTP_MOVED_TEMPORARILY + && rc != NGX_HTTP_MOVED_PERMANENTLY + && rc != NGX_HTTP_TEMPORARY_REDIRECT) { - return luaL_error(L, "only ngx.HTTP_MOVED_TEMPORARILY and " - "ngx.HTTP_MOVED_PERMANENTLY are allowed"); + return luaL_error(L, "only ngx.HTTP_MOVED_TEMPORARILY, " + "ngx.HTTP_MOVED_PERMANENTLY, and " + "ngx.HTTP_TEMPORARY_REDIRECT are allowed"); } + } else { rc = NGX_HTTP_MOVED_TEMPORARILY; } @@ -256,9 +260,9 @@ ngx_http_lua_ngx_redirect(lua_State *L) #if 0 dd("location hash: %lu == %lu", - (unsigned long) h->hash, - (unsigned long) ngx_hash_key_lc((u_char *) "Location", - sizeof("Location") - 1)); + (unsigned long) h->hash, + (unsigned long) ngx_hash_key_lc((u_char *) "Location", + sizeof("Location") - 1)); #endif h->value.len = len; @@ -290,9 +294,9 @@ ngx_http_lua_ngx_redirect(lua_State *L) static int ngx_http_lua_ngx_exit(lua_State *L) { + ngx_int_t rc; ngx_http_request_t *r; ngx_http_lua_ctx_t *ctx; - ngx_int_t rc; if (lua_gettop(L) != 1) { return luaL_error(L, "expecting one argument"); @@ -312,10 +316,31 @@ ngx_http_lua_ngx_exit(lua_State *L) | NGX_HTTP_LUA_CONTEXT_ACCESS | NGX_HTTP_LUA_CONTEXT_CONTENT | NGX_HTTP_LUA_CONTEXT_TIMER - | NGX_HTTP_LUA_CONTEXT_HEADER_FILTER); + | NGX_HTTP_LUA_CONTEXT_HEADER_FILTER + | NGX_HTTP_LUA_CONTEXT_BALANCER + | NGX_HTTP_LUA_CONTEXT_SSL_CERT); rc = (ngx_int_t) luaL_checkinteger(L, 1); + if (ctx->context == NGX_HTTP_LUA_CONTEXT_SSL_CERT) { + +#if (NGX_HTTP_SSL) + + ctx->exit_code = rc; + ctx->exited = 1; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "lua exit with code %i", rc); + + return lua_yield(L, 0); + +#else + + return luaL_error(L, "no SSL support"); + +#endif + } + if (ctx->no_abort && rc != NGX_ERROR && rc != NGX_HTTP_CLOSE @@ -348,7 +373,9 @@ ngx_http_lua_ngx_exit(lua_State *L) ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua exit with code %i", ctx->exit_code); - if (ctx->context & NGX_HTTP_LUA_CONTEXT_HEADER_FILTER) { + if (ctx->context & (NGX_HTTP_LUA_CONTEXT_HEADER_FILTER + | NGX_HTTP_LUA_CONTEXT_BALANCER)) + { return 0; } @@ -431,13 +458,33 @@ ngx_http_lua_ffi_exit(ngx_http_request_t *r, int status, u_char *err, | NGX_HTTP_LUA_CONTEXT_ACCESS | NGX_HTTP_LUA_CONTEXT_CONTENT | NGX_HTTP_LUA_CONTEXT_TIMER - | NGX_HTTP_LUA_CONTEXT_HEADER_FILTER, + | NGX_HTTP_LUA_CONTEXT_HEADER_FILTER + | NGX_HTTP_LUA_CONTEXT_SSL_CERT, err, errlen) != NGX_OK) { return NGX_ERROR; } + if (ctx->context == NGX_HTTP_LUA_CONTEXT_SSL_CERT) { + +#if (NGX_HTTP_SSL) + + ctx->exit_code = status; + ctx->exited = 1; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "lua exit with code %d", status); + + return NGX_OK; + +#else + + return NGX_ERROR; + +#endif + } + if (ctx->no_abort && status != NGX_ERROR && status != NGX_HTTP_CLOSE @@ -458,7 +505,7 @@ ngx_http_lua_ffi_exit(ngx_http_request_t *r, int status, u_char *err, { if (status != (ngx_int_t) r->headers_out.status) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "attempt to " - "set status %i via ngx.exit after sending out the " + "set status %d via ngx.exit after sending out the " "response status %ui", status, r->headers_out.status); } diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_coroutine.c b/debian/modules/nginx-lua/src/ngx_http_lua_coroutine.c index 2bd9cb7..cb819c6 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_coroutine.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_coroutine.c @@ -71,12 +71,13 @@ ngx_http_lua_coroutine_create_helper(lua_State *L, ngx_http_request_t *r, ngx_http_lua_co_ctx_t *coctx; /* co ctx for the new coroutine */ luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1, - "Lua function expected"); + "Lua function expected"); ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE | NGX_HTTP_LUA_CONTEXT_ACCESS | NGX_HTTP_LUA_CONTEXT_CONTENT - | NGX_HTTP_LUA_CONTEXT_TIMER); + | NGX_HTTP_LUA_CONTEXT_TIMER + | NGX_HTTP_LUA_CONTEXT_SSL_CERT); vm = ngx_http_lua_get_lua_vm(r, ctx); @@ -151,7 +152,8 @@ ngx_http_lua_coroutine_resume(lua_State *L) ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE | NGX_HTTP_LUA_CONTEXT_ACCESS | NGX_HTTP_LUA_CONTEXT_CONTENT - | NGX_HTTP_LUA_CONTEXT_TIMER); + | NGX_HTTP_LUA_CONTEXT_TIMER + | NGX_HTTP_LUA_CONTEXT_SSL_CERT); p_coctx = ctx->cur_co_ctx; if (p_coctx == NULL) { @@ -210,7 +212,8 @@ ngx_http_lua_coroutine_yield(lua_State *L) ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE | NGX_HTTP_LUA_CONTEXT_ACCESS | NGX_HTTP_LUA_CONTEXT_CONTENT - | NGX_HTTP_LUA_CONTEXT_TIMER); + | NGX_HTTP_LUA_CONTEXT_TIMER + | NGX_HTTP_LUA_CONTEXT_SSL_CERT); coctx = ctx->cur_co_ctx; @@ -358,7 +361,8 @@ ngx_http_lua_coroutine_status(lua_State *L) ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE | NGX_HTTP_LUA_CONTEXT_ACCESS | NGX_HTTP_LUA_CONTEXT_CONTENT - | NGX_HTTP_LUA_CONTEXT_TIMER); + | NGX_HTTP_LUA_CONTEXT_TIMER + | NGX_HTTP_LUA_CONTEXT_SSL_CERT); coctx = ngx_http_lua_get_co_ctx(co, ctx); if (coctx == NULL) { diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_directive.c b/debian/modules/nginx-lua/src/ngx_http_lua_directive.c index ae8b09f..7ac8c28 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_directive.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_directive.c @@ -24,6 +24,7 @@ #include "ngx_http_lua_initby.h" #include "ngx_http_lua_initworkerby.h" #include "ngx_http_lua_shdict.h" +#include "ngx_http_lua_ssl_certby.h" #include "ngx_http_lua_lex.h" @@ -40,8 +41,6 @@ static ngx_int_t ngx_http_lua_set_by_lua_init(ngx_http_request_t *r); static u_char *ngx_http_lua_gen_chunk_name(ngx_conf_t *cf, const char *tag, size_t tag_len); -static char *ngx_http_lua_conf_lua_block_parse(ngx_conf_t *cf, - ngx_command_t *cmd); static ngx_int_t ngx_http_lua_conf_read_lua_token(ngx_conf_t *cf, ngx_http_lua_block_parser_ctx_t *ctx); static u_char *ngx_http_lua_strlstrn(u_char *s1, u_char *last, u_char *s2, @@ -121,6 +120,7 @@ ngx_http_lua_shared_dict(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ctx->name = name; ctx->main_conf = lmcf; ctx->log = &cf->cycle->new_log; + ctx->cycle = cf->cycle; zone = ngx_shared_memory_add(cf, &name, (size_t) size, &ngx_http_lua_module); @@ -354,7 +354,8 @@ ngx_http_lua_filter_set_by_lua_inline(ngx_http_request_t *r, ngx_str_t *val, L = ngx_http_lua_get_lua_vm(r, NULL); /* load Lua inline script (w/ cache) sp = 1 */ - rc = ngx_http_lua_cache_loadbuffer(r, L, filter_data->script.data, + rc = ngx_http_lua_cache_loadbuffer(r->connection->log, L, + filter_data->script.data, filter_data->script.len, filter_data->key, "=set_by_lua"); if (rc != NGX_OK) { @@ -407,7 +408,8 @@ ngx_http_lua_filter_set_by_lua_file(ngx_http_request_t *r, ngx_str_t *val, L = ngx_http_lua_get_lua_vm(r, NULL); /* load Lua script file (w/ cache) sp = 1 */ - rc = ngx_http_lua_cache_loadfile(r, L, script_path, filter_data->key); + rc = ngx_http_lua_cache_loadfile(r->connection->log, L, script_path, + filter_data->key); if (rc != NGX_OK) { return NGX_ERROR; } @@ -1126,7 +1128,7 @@ ngx_http_lua_init_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, return NGX_CONF_ERROR; } - lmcf->init_handler = (ngx_http_lua_conf_handler_pt) cmd->post; + lmcf->init_handler = (ngx_http_lua_main_conf_handler_pt) cmd->post; if (cmd->post == ngx_http_lua_init_by_file) { name = ngx_http_lua_rebase_path(cf->pool, value[1].data, @@ -1186,7 +1188,7 @@ ngx_http_lua_init_worker_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, value = cf->args->elts; - lmcf->init_worker_handler = (ngx_http_lua_conf_handler_pt) cmd->post; + lmcf->init_worker_handler = (ngx_http_lua_main_conf_handler_pt) cmd->post; if (cmd->post == ngx_http_lua_init_worker_by_file) { name = ngx_http_lua_rebase_path(cf->pool, value[1].data, @@ -1284,7 +1286,7 @@ found: /* a specialized version of the standard ngx_conf_parse() function */ -static char * +char * ngx_http_lua_conf_lua_block_parse(ngx_conf_t *cf, ngx_command_t *cmd) { ngx_http_lua_block_parser_ctx_t ctx; @@ -1555,12 +1557,63 @@ ngx_http_lua_conf_read_lua_token(ngx_conf_t *cf, rc = ngx_http_lua_lex(b->pos, b->last - b->pos, ovec); if (rc < 0) { /* no match */ - cf->conf_file->line = start_line; - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "Lua code block missing the \"}\" " - "character"); + /* alas. the lexer does not yet support streaming processing. need + * more work below */ - return NGX_ERROR; + if (cf->conf_file->file.offset >= file_size) { + + cf->conf_file->line = ctx->start_line; + + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "unexpected end of file, expecting " + "terminating characters for lua code " + "block"); + return NGX_ERROR; + } + + len = b->last - b->pos; + + if (len == buf_size) { + + cf->conf_file->line = start_line; + + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "too long lua code block, probably " + "missing terminating characters"); + + return NGX_ERROR; + } + + if (len) { + ngx_memcpy(b->start, b->pos, len); + } + + size = (ssize_t) (file_size - cf->conf_file->file.offset); + + if (size > b->end - (b->start + len)) { + size = b->end - (b->start + len); + } + + n = ngx_read_file(&cf->conf_file->file, b->start + len, size, + cf->conf_file->file.offset); + + if (n == NGX_ERROR) { + return NGX_ERROR; + } + + if (n != size) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + ngx_read_file_n " returned " + "only %z bytes instead of %z", + n, size); + return NGX_ERROR; + } + + b->pos = b->start + len; + b->last = b->pos + n; + start = b->start; + + continue; } if (rc == FOUND_LEFT_LBRACKET_STR || rc == FOUND_LEFT_LBRACKET_CMT) { diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_directive.h b/debian/modules/nginx-lua/src/ngx_http_lua_directive.h index 5a8d93b..be591f3 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_directive.h +++ b/debian/modules/nginx-lua/src/ngx_http_lua_directive.h @@ -68,6 +68,9 @@ ngx_int_t ngx_http_lua_filter_set_by_lua_file(ngx_http_request_t *r, char *ngx_http_lua_rewrite_no_postpone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +char *ngx_http_lua_conf_lua_block_parse(ngx_conf_t *cf, + ngx_command_t *cmd); + #endif /* _NGX_HTTP_LUA_DIRECTIVE_H_INCLUDED_ */ diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_headerfilterby.c b/debian/modules/nginx-lua/src/ngx_http_lua_headerfilterby.c index 79bac65..75ce324 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_headerfilterby.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_headerfilterby.c @@ -168,7 +168,7 @@ ngx_http_lua_header_filter_inline(ngx_http_request_t *r) L = ngx_http_lua_get_lua_vm(r, NULL); /* load Lua inline script (w/ cache) sp = 1 */ - rc = ngx_http_lua_cache_loadbuffer(r, L, + rc = ngx_http_lua_cache_loadbuffer(r->connection->log, L, llcf->header_filter_src.value.data, llcf->header_filter_src.value.len, llcf->header_filter_src_key, @@ -211,7 +211,7 @@ ngx_http_lua_header_filter_file(ngx_http_request_t *r) L = ngx_http_lua_get_lua_vm(r, NULL); /* load Lua script file (w/ cache) sp = 1 */ - rc = ngx_http_lua_cache_loadfile(r, L, script_path, + rc = ngx_http_lua_cache_loadfile(r->connection->log, L, script_path, llcf->header_filter_src_key); if (rc != NGX_OK) { return NGX_ERROR; diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_headers.c b/debian/modules/nginx-lua/src/ngx_http_lua_headers.c index 5f8e59a..a9e45d3 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_headers.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_headers.c @@ -608,7 +608,7 @@ ngx_http_lua_ngx_header_get(lua_State *L) if (llcf->transform_underscores_in_resp_headers && memchr(p, '_', len) != NULL) { - key.data = (u_char*) lua_newuserdata(L, len); + key.data = (u_char *) lua_newuserdata(L, len); if (key.data == NULL) { return luaL_error(L, "no memory"); } @@ -989,7 +989,7 @@ ngx_http_lua_ffi_req_get_headers_count(ngx_http_request_t *r, int max) int count; ngx_list_part_t *part; - if (r->connection->fd == -1) { + if (r->connection->fd == (ngx_socket_t) -1) { return NGX_HTTP_LUA_FFI_BAD_CONTEXT; } @@ -1082,7 +1082,7 @@ ngx_http_lua_ffi_set_resp_header(ngx_http_request_t *r, const u_char *key_data, return NGX_HTTP_LUA_FFI_NO_REQ_CTX; } - if (r->connection->fd == -1) { + if (r->connection->fd == (ngx_socket_t) -1) { return NGX_HTTP_LUA_FFI_BAD_CONTEXT; } @@ -1198,7 +1198,7 @@ ngx_http_lua_ffi_req_header_set_single_value(ngx_http_request_t *r, ngx_str_t k; ngx_str_t v; - if (r->connection->fd == -1) { /* fake request */ + if (r->connection->fd == (ngx_socket_t) -1) { /* fake request */ return NGX_HTTP_LUA_FFI_BAD_CONTEXT; } @@ -1253,7 +1253,7 @@ ngx_http_lua_ffi_get_resp_header(ngx_http_request_t *r, ngx_http_lua_loc_conf_t *llcf; - if (r->connection->fd == -1) { + if (r->connection->fd == (ngx_socket_t) -1) { return NGX_HTTP_LUA_FFI_BAD_CONTEXT; } diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_headers_in.c b/debian/modules/nginx-lua/src/ngx_http_lua_headers_in.c index abce458..82b4331 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_headers_in.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_headers_in.c @@ -29,7 +29,7 @@ static ngx_int_t ngx_http_set_connection_header(ngx_http_request_t *r, ngx_http_lua_header_val_t *hv, ngx_str_t *value); static ngx_int_t ngx_http_set_content_length_header(ngx_http_request_t *r, ngx_http_lua_header_val_t *hv, ngx_str_t *value); -static ngx_int_t ngx_http_set_cookie_header(ngx_http_request_t *r, +static ngx_int_t ngx_http_set_builtin_multi_header(ngx_http_request_t *r, ngx_http_lua_header_val_t *hv, ngx_str_t *value); static ngx_int_t ngx_http_clear_builtin_header(ngx_http_request_t *r, ngx_http_lua_header_val_t *hv, ngx_str_t *value); @@ -128,6 +128,13 @@ static ngx_http_lua_set_header_t ngx_http_lua_set_handlers[] = { offsetof(ngx_http_headers_in_t, keep_alive), ngx_http_set_builtin_header }, +#if (NGX_HTTP_X_FORWARDED_FOR) + { ngx_string("X-Forwarded-For"), + offsetof(ngx_http_headers_in_t, x_forwarded_for), + ngx_http_set_builtin_multi_header }, + +#endif + #if (NGX_HTTP_REALIP) { ngx_string("X-Real-IP"), offsetof(ngx_http_headers_in_t, x_real_ip), @@ -152,8 +159,8 @@ static ngx_http_lua_set_header_t ngx_http_lua_set_handlers[] = { #endif { ngx_string("Cookie"), - 0, - ngx_http_set_cookie_header }, + offsetof(ngx_http_headers_in_t, cookies), + ngx_http_set_builtin_multi_header }, { ngx_null_string, 0, ngx_http_set_header } }; @@ -558,7 +565,7 @@ ngx_http_set_content_length_header(ngx_http_request_t *r, return NGX_ERROR; } - dd("reset headers_in.content_length_n to %d", (int)len); + dd("reset headers_in.content_length_n to %d", (int) len); r->headers_in.content_length_n = len; @@ -567,27 +574,30 @@ ngx_http_set_content_length_header(ngx_http_request_t *r, static ngx_int_t -ngx_http_set_cookie_header(ngx_http_request_t *r, +ngx_http_set_builtin_multi_header(ngx_http_request_t *r, ngx_http_lua_header_val_t *hv, ngx_str_t *value) { - ngx_table_elt_t **cookie, *h; + ngx_array_t *headers; + ngx_table_elt_t **v, *h; - if (!hv->no_override && r->headers_in.cookies.nelts > 0) { - ngx_array_destroy(&r->headers_in.cookies); + headers = (ngx_array_t *) ((char *) &r->headers_in + hv->offset); - if (ngx_array_init(&r->headers_in.cookies, r->pool, 2, + if (!hv->no_override && headers->nelts > 0) { + ngx_array_destroy(headers); + + if (ngx_array_init(headers, r->pool, 2, sizeof(ngx_table_elt_t *)) != NGX_OK) { return NGX_ERROR; } - dd("clear headers in cookies: %d", (int) r->headers_in.cookies.nelts); + dd("clear multi-value headers: %d", (int) headers->nelts); } #if 1 - if (r->headers_in.cookies.nalloc == 0) { - if (ngx_array_init(&r->headers_in.cookies, r->pool, 2, + if (headers->nalloc == 0) { + if (ngx_array_init(headers, r->pool, 2, sizeof(ngx_table_elt_t *)) != NGX_OK) { @@ -604,14 +614,14 @@ ngx_http_set_cookie_header(ngx_http_request_t *r, return NGX_OK; } - dd("new cookie header: %p", h); + dd("new multi-value header: %p", h); - cookie = ngx_array_push(&r->headers_in.cookies); - if (cookie == NULL) { + v = ngx_array_push(headers); + if (v == NULL) { return NGX_ERROR; } - *cookie = h; + *v = h; return NGX_OK; } diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_headers_out.c b/debian/modules/nginx-lua/src/ngx_http_lua_headers_out.c index 5fd077f..b908eae 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_headers_out.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_headers_out.c @@ -179,7 +179,7 @@ ngx_http_set_header_helper(ngx_http_request_t *r, ngx_http_lua_header_val_t *hv, } else { dd("setting header to value %.*s", (int) value->len, - value->data); + value->data); h[i].value = *value; h[i].hash = hv->hash; diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_logby.c b/debian/modules/nginx-lua/src/ngx_http_lua_logby.c index 9d06323..0a79acd 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_logby.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_logby.c @@ -113,7 +113,8 @@ ngx_http_lua_log_handler_inline(ngx_http_request_t *r) L = ngx_http_lua_get_lua_vm(r, NULL); /* load Lua inline script (w/ cache) sp = 1 */ - rc = ngx_http_lua_cache_loadbuffer(r, L, llcf->log_src.value.data, + rc = ngx_http_lua_cache_loadbuffer(r->connection->log, L, + llcf->log_src.value.data, llcf->log_src.value.len, llcf->log_src_key, (const char *) llcf->log_chunkname); @@ -150,7 +151,8 @@ ngx_http_lua_log_handler_file(ngx_http_request_t *r) L = ngx_http_lua_get_lua_vm(r, NULL); /* load Lua script file (w/ cache) sp = 1 */ - rc = ngx_http_lua_cache_loadfile(r, L, script_path, llcf->log_src_key); + rc = ngx_http_lua_cache_loadfile(r->connection->log, L, script_path, + llcf->log_src_key); if (rc != NGX_OK) { return NGX_ERROR; } diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_misc.c b/debian/modules/nginx-lua/src/ngx_http_lua_misc.c index 4990e26..e3c7ec7 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_misc.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_misc.c @@ -18,6 +18,7 @@ static int ngx_http_lua_ngx_get(lua_State *L); static int ngx_http_lua_ngx_set(lua_State *L); +static int ngx_http_lua_ngx_req_is_internal(lua_State *L); void @@ -33,6 +34,29 @@ ngx_http_lua_inject_misc_api(lua_State *L) } +void +ngx_http_lua_inject_req_misc_api(lua_State *L) +{ + lua_pushcfunction(L, ngx_http_lua_ngx_req_is_internal); + lua_setfield(L, -2, "is_internal"); +} + + +static int +ngx_http_lua_ngx_req_is_internal(lua_State *L) +{ + ngx_http_request_t *r; + + r = ngx_http_lua_get_req(L); + if (r == NULL) { + return luaL_error(L, "no request object found"); + } + + lua_pushboolean(L, r->internal == 1); + return 1; +} + + static int ngx_http_lua_ngx_get(lua_State *L) { @@ -176,7 +200,7 @@ ngx_http_lua_ngx_set(lua_State *L) int ngx_http_lua_ffi_get_resp_status(ngx_http_request_t *r) { - if (r->connection->fd == -1) { + if (r->connection->fd == (ngx_socket_t) -1) { return NGX_HTTP_LUA_FFI_BAD_CONTEXT; } @@ -198,7 +222,7 @@ ngx_http_lua_ffi_get_resp_status(ngx_http_request_t *r) int ngx_http_lua_ffi_set_resp_status(ngx_http_request_t *r, int status) { - if (r->connection->fd == -1) { + if (r->connection->fd == (ngx_socket_t) -1) { return NGX_HTTP_LUA_FFI_BAD_CONTEXT; } @@ -230,7 +254,7 @@ ngx_http_lua_ffi_set_resp_status(ngx_http_request_t *r, int status) int ngx_http_lua_ffi_is_subrequest(ngx_http_request_t *r) { - if (r->connection->fd == -1) { + if (r->connection->fd == (ngx_socket_t) -1) { return NGX_HTTP_LUA_FFI_BAD_CONTEXT; } @@ -248,7 +272,7 @@ ngx_http_lua_ffi_headers_sent(ngx_http_request_t *r) return NGX_HTTP_LUA_FFI_NO_REQ_CTX; } - if (r->connection->fd == -1) { + if (r->connection->fd == (ngx_socket_t) -1) { return NGX_HTTP_LUA_FFI_BAD_CONTEXT; } diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_misc.h b/debian/modules/nginx-lua/src/ngx_http_lua_misc.h index 8a79b92..c26d869 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_misc.h +++ b/debian/modules/nginx-lua/src/ngx_http_lua_misc.h @@ -14,6 +14,8 @@ void ngx_http_lua_inject_misc_api(lua_State *L); +void ngx_http_lua_inject_req_misc_api(lua_State *L); + #endif /* _NGX_HTTP_LUA_MISC_H_INCLUDED_ */ diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_module.c b/debian/modules/nginx-lua/src/ngx_http_lua_module.c index 3bf50c2..c72a705 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_module.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_module.c @@ -23,16 +23,18 @@ #include "ngx_http_lua_initby.h" #include "ngx_http_lua_initworkerby.h" #include "ngx_http_lua_probe.h" - - -#if !defined(nginx_version) || nginx_version < 8054 -#error "at least nginx 0.8.54 is required" -#endif +#include "ngx_http_lua_semaphore.h" +#include "ngx_http_lua_balancer.h" +#include "ngx_http_lua_ssl_certby.h" static void *ngx_http_lua_create_main_conf(ngx_conf_t *cf); static char *ngx_http_lua_init_main_conf(ngx_conf_t *cf, void *conf); +static void *ngx_http_lua_create_srv_conf(ngx_conf_t *cf); +static char *ngx_http_lua_merge_srv_conf(ngx_conf_t *cf, void *parent, + void *child); static void *ngx_http_lua_create_loc_conf(ngx_conf_t *cf); + static char *ngx_http_lua_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child); static ngx_int_t ngx_http_lua_init(ngx_conf_t *cf); @@ -313,6 +315,13 @@ static ngx_command_t ngx_http_lua_cmds[] = { 0, (void *) ngx_http_lua_access_handler_file }, + { ngx_string("access_by_lua_no_postpone"), + NGX_HTTP_MAIN_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_MAIN_CONF_OFFSET, + offsetof(ngx_http_lua_main_conf_t, postponed_to_access_phase_end), + NULL }, + /* content_by_lua_file rel/or/abs/path/to/script */ { ngx_string("content_by_lua_file"), NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1, @@ -380,6 +389,20 @@ static ngx_command_t ngx_http_lua_cmds[] = { 0, (void *) ngx_http_lua_body_filter_file }, + { ngx_string("balancer_by_lua_block"), + NGX_HTTP_UPS_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS, + ngx_http_lua_balancer_by_lua_block, + NGX_HTTP_SRV_CONF_OFFSET, + 0, + (void *) ngx_http_lua_balancer_handler_inline }, + + { ngx_string("balancer_by_lua_file"), + NGX_HTTP_UPS_CONF|NGX_CONF_TAKE1, + ngx_http_lua_balancer_by_lua, + NGX_HTTP_SRV_CONF_OFFSET, + 0, + (void *) ngx_http_lua_balancer_handler_file }, + { ngx_string("lua_socket_keepalive_timeout"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF |NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1, @@ -480,6 +503,24 @@ static ngx_command_t ngx_http_lua_cmds[] = { offsetof(ngx_http_lua_loc_conf_t, ssl_ciphers), NULL }, +#if (NGX_HTTP_SSL) + + { ngx_string("ssl_certificate_by_lua_block"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS, + ngx_http_lua_ssl_cert_by_lua_block, + NGX_HTTP_SRV_CONF_OFFSET, + 0, + (void *) ngx_http_lua_ssl_cert_handler_inline }, + + { ngx_string("ssl_certificate_by_lua_file"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_http_lua_ssl_cert_by_lua, + NGX_HTTP_SRV_CONF_OFFSET, + 0, + (void *) ngx_http_lua_ssl_cert_handler_file }, + +#endif /* NGX_HTTP_SSL */ + { ngx_string("lua_ssl_verify_depth"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_num_slot, @@ -514,8 +555,8 @@ ngx_http_module_t ngx_http_lua_module_ctx = { ngx_http_lua_create_main_conf, /* create main configuration */ ngx_http_lua_init_main_conf, /* init main configuration */ - NULL, /* create server configuration */ - NULL, /* merge server configuration */ + ngx_http_lua_create_srv_conf, /* create server configuration */ + ngx_http_lua_merge_srv_conf, /* merge server configuration */ ngx_http_lua_create_loc_conf, /* create location configuration */ ngx_http_lua_merge_loc_conf /* merge location configuration */ @@ -545,8 +586,12 @@ ngx_http_lua_init(ngx_conf_t *cf) ngx_int_t rc; ngx_array_t *arr; ngx_http_handler_pt *h; + volatile ngx_cycle_t *saved_cycle; ngx_http_core_main_conf_t *cmcf; ngx_http_lua_main_conf_t *lmcf; +#ifndef NGX_LUA_NO_FFI_API + ngx_pool_cleanup_t *cln; +#endif lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_lua_module); @@ -569,6 +614,10 @@ ngx_http_lua_init(ngx_conf_t *cf) lmcf->postponed_to_rewrite_phase_end = 0; } + if (lmcf->postponed_to_access_phase_end == NGX_CONF_UNSET) { + lmcf->postponed_to_access_phase_end = 0; + } + cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); if (lmcf->requires_rewrite) { @@ -621,6 +670,19 @@ ngx_http_lua_init(ngx_conf_t *cf) } } +#ifndef NGX_LUA_NO_FFI_API + + /* add the cleanup of semaphores after the lua_close */ + cln = ngx_pool_cleanup_add(cf->pool, 0); + if (cln == NULL) { + return NGX_ERROR; + } + + cln->data = lmcf; + cln->handler = ngx_http_lua_cleanup_semaphore_mm; + +#endif + if (lmcf->lua == NULL) { dd("initializing lua vm"); @@ -637,7 +699,14 @@ ngx_http_lua_init(ngx_conf_t *cf) } if (!lmcf->requires_shm && lmcf->init_handler) { - if (lmcf->init_handler(cf->log, lmcf, lmcf->lua) != NGX_OK) { + saved_cycle = ngx_cycle; + ngx_cycle = cf->cycle; + + rc = lmcf->init_handler(cf->log, lmcf, lmcf->lua); + + ngx_cycle = saved_cycle; + + if (rc != NGX_OK) { /* an error happened */ return NGX_ERROR; } @@ -683,6 +752,7 @@ static void * ngx_http_lua_create_main_conf(ngx_conf_t *cf) { ngx_http_lua_main_conf_t *lmcf; + ngx_http_lua_semaphore_mm_t *mm; lmcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_lua_main_conf_t)); if (lmcf == NULL) { @@ -719,6 +789,25 @@ ngx_http_lua_create_main_conf(ngx_conf_t *cf) lmcf->regex_match_limit = NGX_CONF_UNSET; #endif lmcf->postponed_to_rewrite_phase_end = NGX_CONF_UNSET; + lmcf->postponed_to_access_phase_end = NGX_CONF_UNSET; + + mm = ngx_palloc(cf->pool, sizeof(ngx_http_lua_semaphore_mm_t)); + if (mm == NULL) { + return NULL; + } + + lmcf->semaphore_mm = mm; + mm->lmcf = lmcf; + + ngx_queue_init(&mm->free_queue); + mm->cur_epoch = 0; + mm->total = 0; + mm->used = 0; + + /* it's better to be 4096, but it needs some space for + * ngx_http_lua_semaphore_mm_block_t, one is enough, so it is 4095 + */ + mm->num_per_block = 4095; dd("nginx Lua module main config structure initialized!"); @@ -755,6 +844,70 @@ ngx_http_lua_init_main_conf(ngx_conf_t *cf, void *conf) } +static void * +ngx_http_lua_create_srv_conf(ngx_conf_t *cf) +{ + ngx_http_lua_srv_conf_t *lscf; + + lscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_lua_srv_conf_t)); + if (lscf == NULL) { + return NULL; + } + + /* set by ngx_pcalloc: + * lscf->ssl.cert_handler = NULL; + * lscf->ssl.cert_src = { 0, NULL }; + * lscf->ssl.cert_src_key = NULL; + * lscf->balancer.handler = NULL; + * lscf->balancer.src = { 0, NULL }; + * lscf->balancer.src_key = NULL; + */ + + return lscf; +} + + +static char * +ngx_http_lua_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) +{ +#if (NGX_HTTP_SSL) + + ngx_http_lua_srv_conf_t *prev = parent; + ngx_http_lua_srv_conf_t *conf = child; + ngx_http_ssl_srv_conf_t *sscf; + + dd("merge srv conf"); + + if (conf->ssl.cert_src.len == 0) { + conf->ssl.cert_src = prev->ssl.cert_src; + conf->ssl.cert_handler = prev->ssl.cert_handler; + } + + if (conf->ssl.cert_src.len) { + sscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_ssl_module); + if (sscf == NULL || sscf->ssl.ctx == NULL) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "no ssl configured for the server"); + + return NGX_CONF_ERROR; + } + +#if OPENSSL_VERSION_NUMBER >= 0x1000205fL + + SSL_CTX_set_cert_cb(sscf->ssl.ctx, ngx_http_lua_ssl_cert_handler, NULL); + +#else + + return NGX_CONF_ERROR; + +#endif + } + +#endif /* NGX_HTTP_SSL */ + return NGX_CONF_OK; +} + + static void * ngx_http_lua_create_loc_conf(ngx_conf_t *cf) { diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_output.c b/debian/modules/nginx-lua/src/ngx_http_lua_output.c index 2062e5a..dca5fb9 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_output.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_output.c @@ -345,7 +345,7 @@ ngx_http_lua_calc_strlen_in_table(lua_State *L, int index, int arg_i, bad_type: msg = lua_pushfstring(L, "bad data type %s found", - lua_typename(L, type)); + lua_typename(L, type)); return luaL_argerror(L, arg_i, msg); } @@ -458,7 +458,7 @@ ngx_http_lua_ngx_flush(lua_State *L) n = lua_gettop(L); if (n > 1) { return luaL_error(L, "attempt to pass %d arguments, but accepted 0 " - "or 1", n); + "or 1", n); } r = ngx_http_lua_get_req(L); diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_phase.c b/debian/modules/nginx-lua/src/ngx_http_lua_phase.c index 6053a39..b8e936a 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_phase.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_phase.c @@ -76,6 +76,14 @@ ngx_http_lua_ngx_get_phase(lua_State *L) lua_pushliteral(L, "timer"); break; + case NGX_HTTP_LUA_CONTEXT_BALANCER: + lua_pushliteral(L, "balancer"); + break; + + case NGX_HTTP_LUA_CONTEXT_SSL_CERT: + lua_pushliteral(L, "ssl_cert"); + break; + default: return luaL_error(L, "unknown phase: %d", (int) ctx->context); } diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_regex.c b/debian/modules/nginx-lua/src/ngx_http_lua_regex.c index 1ecfd70..8b4a668 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_regex.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_regex.c @@ -449,7 +449,7 @@ ngx_http_lua_ngx_re_match_helper(lua_State *L, int wantcaps) } dd("saving regex %p, ncaptures %d, captures %p", re_comp.regex, - re_comp.captures, cap); + re_comp.captures, cap); re->regex = re_comp.regex; re->regex_sd = sd; @@ -681,7 +681,7 @@ ngx_http_lua_ngx_re_gmatch(lua_State *L) if (nargs != 2 && nargs != 3) { return luaL_error(L, "expecting two or three arguments, but got %d", - nargs); + nargs); } r = ngx_http_lua_get_req(L); @@ -1321,7 +1321,7 @@ ngx_http_lua_ngx_re_sub_helper(lua_State *L, unsigned global) if (nargs != 3 && nargs != 4) { return luaL_error(L, "expecting three or four arguments, but got %d", - nargs); + nargs); } r = ngx_http_lua_get_req(L); @@ -1820,7 +1820,7 @@ exec: } rc = ngx_http_lua_complex_value(r, &subj, cp_offset, rc, cap, ctpl, - &luabuf); + &luabuf); if (rc != NGX_OK) { msg = lua_pushfstring(L, "failed to eval the template for " @@ -1972,16 +1972,16 @@ ngx_http_lua_regex_compile(ngx_http_lua_regex_compile_t *rc) if (re == NULL) { if ((size_t) erroff == rc->pattern.len) { - rc->err.len = ngx_snprintf(rc->err.data, rc->err.len, - "pcre_compile() failed: %s in \"%V\"", + rc->err.len = ngx_snprintf(rc->err.data, rc->err.len, + "pcre_compile() failed: %s in \"%V\"", errstr, &rc->pattern) - rc->err.data; } else { - rc->err.len = ngx_snprintf(rc->err.data, rc->err.len, - "pcre_compile() failed: %s in \"%V\" " - "at \"%s\"", errstr, &rc->pattern, - rc->pattern.data + erroff) + rc->err.len = ngx_snprintf(rc->err.data, rc->err.len, + "pcre_compile() failed: %s in \"%V\" " + "at \"%s\"", errstr, &rc->pattern, + rc->pattern.data + erroff) - rc->err.data; } diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_req_body.c b/debian/modules/nginx-lua/src/ngx_http_lua_req_body.c index af90245..a916396 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_req_body.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_req_body.c @@ -110,7 +110,7 @@ ngx_http_lua_ngx_req_read_body(lua_State *L) } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "lua start to read buffered request body"); + "lua start to read buffered request body"); rc = ngx_http_read_client_request_body(r, ngx_http_lua_req_body_post_read); @@ -332,7 +332,7 @@ ngx_http_lua_ngx_req_get_body_file(lua_State *L) r->request_body->bufs->buf->memory, r->request_body->bufs->buf->temporary, (int) (r->request_body->bufs->buf->end - - r->request_body->bufs->buf->pos), + r->request_body->bufs->buf->pos), (int) ngx_buf_size(r->request_body->bufs->buf)); lua_pushlstring(L, (char *) r->request_body->temp_file->file.name.data, diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_req_method.c b/debian/modules/nginx-lua/src/ngx_http_lua_req_method.c index 41736c3..0a2a154 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_req_method.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_req_method.c @@ -149,7 +149,7 @@ ngx_http_lua_ngx_req_set_method(lua_State *L) int ngx_http_lua_ffi_req_get_method(ngx_http_request_t *r) { - if (r->connection->fd == -1) { + if (r->connection->fd == (ngx_socket_t) -1) { return NGX_HTTP_LUA_FFI_BAD_CONTEXT; } @@ -161,7 +161,7 @@ int ngx_http_lua_ffi_req_get_method_name(ngx_http_request_t *r, char *buf, size_t *len) { - if (r->connection->fd == -1) { + if (r->connection->fd == (ngx_socket_t) -1) { return NGX_HTTP_LUA_FFI_BAD_CONTEXT; } @@ -174,7 +174,7 @@ ngx_http_lua_ffi_req_get_method_name(ngx_http_request_t *r, char *buf, int ngx_http_lua_ffi_req_set_method(ngx_http_request_t *r, int method) { - if (r->connection->fd == -1) { + if (r->connection->fd == (ngx_socket_t) -1) { return NGX_HTTP_LUA_FFI_BAD_CONTEXT; } diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_rewriteby.c b/debian/modules/nginx-lua/src/ngx_http_lua_rewriteby.c index af3b499..da30b8b 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_rewriteby.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_rewriteby.c @@ -67,7 +67,7 @@ ngx_http_lua_rewrite_handler(ngx_http_request_t *r) tmp = *cur_ph; memmove(cur_ph, cur_ph + 1, - (last_ph - cur_ph) * sizeof (ngx_http_phase_handler_t)); + (last_ph - cur_ph) * sizeof (ngx_http_phase_handler_t)); *last_ph = tmp; @@ -176,7 +176,8 @@ ngx_http_lua_rewrite_handler_inline(ngx_http_request_t *r) L = ngx_http_lua_get_lua_vm(r, NULL); /* load Lua inline script (w/ cache) sp = 1 */ - rc = ngx_http_lua_cache_loadbuffer(r, L, llcf->rewrite_src.value.data, + rc = ngx_http_lua_cache_loadbuffer(r->connection->log, L, + llcf->rewrite_src.value.data, llcf->rewrite_src.value.len, llcf->rewrite_src_key, (const char *) @@ -214,7 +215,8 @@ ngx_http_lua_rewrite_handler_file(ngx_http_request_t *r) L = ngx_http_lua_get_lua_vm(r, NULL); /* load Lua script file (w/ cache) sp = 1 */ - rc = ngx_http_lua_cache_loadfile(r, L, script_path, llcf->rewrite_src_key); + rc = ngx_http_lua_cache_loadfile(r->connection->log, L, script_path, + llcf->rewrite_src_key); if (rc != NGX_OK) { if (rc < NGX_HTTP_SPECIAL_RESPONSE) { return NGX_HTTP_INTERNAL_SERVER_ERROR; diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_script.c b/debian/modules/nginx-lua/src/ngx_http_lua_script.c index 24be601..95ebadf 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_script.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_script.c @@ -59,7 +59,7 @@ ngx_http_lua_compile_complex_value(ngx_http_lua_compile_complex_value_t *ccv) } n = nv * (2 * sizeof(ngx_http_lua_script_copy_code_t) - + sizeof(ngx_http_lua_script_capture_code_t)) + + sizeof(ngx_http_lua_script_capture_code_t)) + sizeof(uintptr_t); if (ngx_array_init(&lengths, ccv->pool, n, 1) != NGX_OK) { diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_semaphore.c b/debian/modules/nginx-lua/src/ngx_http_lua_semaphore.c new file mode 100644 index 0000000..b022604 --- /dev/null +++ b/debian/modules/nginx-lua/src/ngx_http_lua_semaphore.c @@ -0,0 +1,546 @@ + +/* + * Copyright (C) Yichun Zhang (agentzh) + * Copyright (C) cuiweixie + * I hereby assign copyright in this code to the lua-nginx-module project, + * to be licensed under the same terms as the rest of the code. + */ + + +#ifndef NGX_LUA_NO_FFI_API + + +#ifndef DDEBUG +#define DDEBUG 0 +#endif +#include "ddebug.h" + + +#include "ngx_http_lua_util.h" +#include "ngx_http_lua_semaphore.h" +#include "ngx_http_lua_contentby.h" + + +ngx_int_t ngx_http_lua_semaphore_init_mm(ngx_http_lua_semaphore_mm_t *mm); +static ngx_http_lua_semaphore_t *ngx_http_lua_alloc_semaphore(void); +void ngx_http_lua_cleanup_semaphore_mm(void *data); +static void ngx_http_lua_free_semaphore(ngx_http_lua_semaphore_t *sem); +static ngx_int_t ngx_http_lua_semaphore_resume(ngx_http_request_t *r); +int ngx_http_lua_ffi_semaphore_new(ngx_http_lua_semaphore_t **psem, + int n, char **errmsg); +int ngx_http_lua_ffi_semaphore_post(ngx_http_lua_semaphore_t *sem, + int n); +int ngx_http_lua_ffi_semaphore_wait(ngx_http_request_t *r, + ngx_http_lua_semaphore_t *sem, int wait_ms, u_char *err, size_t *errlen); +static void ngx_http_lua_semaphore_cleanup(void *data); +static void ngx_http_lua_semaphore_handler(ngx_event_t *ev); +static void ngx_http_lua_semaphore_timeout_handler(ngx_event_t *ev); +void ngx_http_lua_ffi_semaphore_gc(ngx_http_lua_semaphore_t *sem); + + +enum { + SEMAPHORE_WAIT_SUCC = 0, + SEMAPHORE_WAIT_TIMEOUT = 1 +}; + + +static ngx_http_lua_semaphore_t * +ngx_http_lua_alloc_semaphore(void) +{ + ngx_http_lua_semaphore_t *sem, *iter; + ngx_http_lua_main_conf_t *lmcf; + ngx_queue_t *q; + ngx_uint_t i, n; + ngx_http_lua_semaphore_mm_block_t *block; + ngx_http_lua_semaphore_mm_t *mm; + + ngx_http_lua_assert(ngx_cycle && ngx_cycle->conf_ctx); + + lmcf = ngx_http_cycle_get_module_main_conf(ngx_cycle, + ngx_http_lua_module); + + mm = lmcf->semaphore_mm; + + if (!ngx_queue_empty(&mm->free_queue)) { + q = ngx_queue_head(&mm->free_queue); + ngx_queue_remove(q); + + sem = ngx_queue_data(q, ngx_http_lua_semaphore_t, chain); + + sem->block->used++; + + ngx_memzero(&sem->sem_event, sizeof(ngx_event_t)); + + sem->sem_event.handler = ngx_http_lua_semaphore_handler; + sem->sem_event.data = sem; + sem->sem_event.log = ngx_cycle->log; + + mm->used++; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, + "from head of free queue, alloc semaphore: %p", sem); + + return sem; + } + + /* free_queue is empty */ + + n = sizeof(ngx_http_lua_semaphore_mm_block_t) + + mm->num_per_block * sizeof(ngx_http_lua_semaphore_t); + + dd("block size: %d, item size: %d", + (int) sizeof(ngx_http_lua_semaphore_mm_block_t), + (int) sizeof(ngx_http_lua_semaphore_t)); + + block = ngx_alloc(n, ngx_cycle->log); + if (block == NULL) { + return NULL; + } + + mm->cur_epoch++; + mm->total += mm->num_per_block; + mm->used++; + + block->mm = mm; + block->epoch = mm->cur_epoch; + + sem = (ngx_http_lua_semaphore_t *) (block + 1); + sem->block = block; + sem->block->used = 1; + + ngx_memzero(&sem->sem_event, sizeof(ngx_event_t)); + + sem->sem_event.handler = ngx_http_lua_semaphore_handler; + sem->sem_event.data = sem; + sem->sem_event.log = ngx_cycle->log; + + for (iter = sem + 1, i = 1; i < mm->num_per_block; i++, iter++) { + iter->block = block; + ngx_queue_insert_tail(&mm->free_queue, &iter->chain); + } + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, + "new block, alloc semaphore: %p block: %p", sem, block); + + return sem; +} + + +void +ngx_http_lua_cleanup_semaphore_mm(void *data) +{ + ngx_http_lua_semaphore_t *sem, *iter; + ngx_uint_t i; + ngx_http_lua_main_conf_t *lmcf; + ngx_queue_t *q; + ngx_http_lua_semaphore_mm_block_t *block; + ngx_http_lua_semaphore_mm_t *mm; + + lmcf = (ngx_http_lua_main_conf_t *) data; + mm = lmcf->semaphore_mm; + + while (!ngx_queue_empty(&mm->free_queue)) { + q = ngx_queue_head(&mm->free_queue); + + sem = ngx_queue_data(q, ngx_http_lua_semaphore_t, chain); + block = sem->block; + + if (block->used == 0) { + iter = (ngx_http_lua_semaphore_t *) (block + 1); + + for (i = 0; i < block->mm->num_per_block; i++, iter++) { + ngx_queue_remove(&iter->chain); + } + + dd("free semaphore block: %p at final", block); + + ngx_free(block); + + } else { + /* just return directly when some thing goes wrong */ + + ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, + "ngx_http_lua_cleanup_semaphore_mm when cleanup" + " block %p is still used by someone", block); + + return; + } + } + + dd("ngx_http_lua_cleanup_semaphore_mm"); +} + + +static void +ngx_http_lua_free_semaphore(ngx_http_lua_semaphore_t *sem) +{ + ngx_http_lua_semaphore_t *iter; + ngx_uint_t i, mid_epoch; + ngx_http_lua_semaphore_mm_block_t *block; + ngx_http_lua_semaphore_mm_t *mm; + + block = sem->block; + block->used--; + + mm = block->mm; + mm->used--; + + mid_epoch = mm->cur_epoch - ((mm->total / mm->num_per_block) >> 1); + + if (block->epoch < mid_epoch) { + ngx_queue_insert_tail(&mm->free_queue, &sem->chain); + ngx_log_debug4(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, + "add to free queue tail semaphore: %p epoch: %d" + "mid_epoch: %d cur_epoch: %d", sem, (int) block->epoch, + (int) mid_epoch, (int) mm->cur_epoch); + + } else { + ngx_queue_insert_head(&mm->free_queue, &sem->chain); + ngx_log_debug4(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, + "add to free queue head semaphore: %p epoch: %d" + "mid_epoch: %d cur_epoch: %d", sem, (int) block->epoch, + (int) mid_epoch, (int) mm->cur_epoch); + } + + dd("used: %d", (int) block->used); + + if (block->used == 0 + && mm->used <= (mm->total >> 1) + && block->epoch < mid_epoch) + { + /* load <= 50% and it's on the older side */ + iter = (ngx_http_lua_semaphore_t *) (block + 1); + + for (i = 0; i < mm->num_per_block; i++, iter++) { + ngx_queue_remove(&iter->chain); + } + + mm->total -= mm->num_per_block; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, + "free semaphore block: %p", block); + + ngx_free(block); + } +} + + +static ngx_int_t +ngx_http_lua_semaphore_resume(ngx_http_request_t *r) +{ + lua_State *vm; + ngx_connection_t *c; + ngx_int_t rc; + ngx_http_lua_ctx_t *ctx; + + ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); + if (ctx == NULL) { + return NGX_ERROR; + } + + ctx->resume_handler = ngx_http_lua_wev_handler; + + c = r->connection; + vm = ngx_http_lua_get_lua_vm(r, ctx); + + if (ctx->cur_co_ctx->sem_resume_status == SEMAPHORE_WAIT_SUCC) { + lua_pushboolean(ctx->cur_co_ctx->co, 1); + lua_pushnil(ctx->cur_co_ctx->co); + + } else { + lua_pushboolean(ctx->cur_co_ctx->co, 0); + lua_pushstring(ctx->cur_co_ctx->co, "timeout"); + } + + rc = ngx_http_lua_run_thread(vm, r, ctx, 2); + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "lua run thread returned %d", rc); + + if (rc == NGX_AGAIN) { + return ngx_http_lua_run_posted_threads(c, vm, r, ctx); + } + + if (rc == NGX_DONE) { + ngx_http_lua_finalize_request(r, NGX_DONE); + return ngx_http_lua_run_posted_threads(c, vm, r, ctx); + } + + /* rc == NGX_ERROR || rc >= NGX_OK */ + + if (ctx->entered_content_phase) { + ngx_http_lua_finalize_request(r, rc); + return NGX_DONE; + } + + return rc; +} + + +int +ngx_http_lua_ffi_semaphore_new(ngx_http_lua_semaphore_t **psem, + int n, char **errmsg) +{ + ngx_http_lua_semaphore_t *sem; + + sem = ngx_http_lua_alloc_semaphore(); + if (sem == NULL) { + *errmsg = "no memory"; + return NGX_ERROR; + } + + ngx_queue_init(&sem->wait_queue); + + sem->resource_count = n; + sem->wait_count = 0; + *psem = sem; + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, + "http lua semaphore new: %p, resources: %d", + sem, sem->resource_count); + + return NGX_OK; +} + + +int +ngx_http_lua_ffi_semaphore_post(ngx_http_lua_semaphore_t *sem, int n) +{ + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, + "http lua semaphore post: %p, n: %d, resources: %d", + sem, n, sem->resource_count); + + sem->resource_count += n; + + if (!ngx_queue_empty(&sem->wait_queue)) { + /* we need the extra paranthese around the first argument of + * ngx_post_event() just to work around macro issues in nginx + * cores older than nginx 1.7.12 (exclusive). + */ + ngx_post_event((&sem->sem_event), &ngx_posted_events); + } + + return NGX_OK; +} + + +int +ngx_http_lua_ffi_semaphore_wait(ngx_http_request_t *r, + ngx_http_lua_semaphore_t *sem, int wait_ms, u_char *err, size_t *errlen) +{ + ngx_http_lua_ctx_t *ctx; + ngx_http_lua_co_ctx_t *wait_co_ctx; + ngx_int_t rc; + + ngx_log_debug4(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, + "http lua semaphore wait: %p, timeout: %d, " + "resources: %d, event posted: %d", + sem, wait_ms, sem->resource_count, +#if (nginx_version >= 1007005) + (int) sem->sem_event.posted +#else + sem->sem_event.prev ? 1 : 0 +#endif + ); + + ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); + if (ctx == NULL) { + *errlen = ngx_snprintf(err, *errlen, "no request ctx found") - err; + return NGX_ERROR; + } + + rc = ngx_http_lua_ffi_check_context(ctx, NGX_HTTP_LUA_CONTEXT_REWRITE + | NGX_HTTP_LUA_CONTEXT_ACCESS + | NGX_HTTP_LUA_CONTEXT_CONTENT + | NGX_HTTP_LUA_CONTEXT_TIMER + | NGX_HTTP_LUA_CONTEXT_SSL_CERT, + err, errlen); + + if (rc != NGX_OK) { + return NGX_ERROR; + } + + /* we keep the order, will resume the older waited firtly + * in ngx_http_lua_semaphore_handler + */ + + if (ngx_queue_empty(&sem->wait_queue) && sem->resource_count > 0) { + sem->resource_count--; + return NGX_OK; + } + + if (wait_ms == 0) { + return NGX_DECLINED; + } + + sem->wait_count++; + wait_co_ctx = ctx->cur_co_ctx; + + wait_co_ctx->sleep.handler = ngx_http_lua_semaphore_timeout_handler; + wait_co_ctx->sleep.data = ctx->cur_co_ctx; + wait_co_ctx->sleep.log = r->connection->log; + + ngx_add_timer(&wait_co_ctx->sleep, (ngx_msec_t) wait_ms); + + dd("ngx_http_lua_ffi_semaphore_wait add timer coctx:%p wait: %d(ms)", + wait_co_ctx, wait_ms); + + ngx_queue_insert_tail(&sem->wait_queue, &wait_co_ctx->sem_wait_queue); + + wait_co_ctx->data = sem; + wait_co_ctx->cleanup = ngx_http_lua_semaphore_cleanup; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, + "http lua semaphore wait yielding"); + + return NGX_AGAIN; +} + + +int +ngx_http_lua_ffi_semaphore_count(ngx_http_lua_semaphore_t *sem) +{ + return sem->resource_count - sem->wait_count; +} + + +static void +ngx_http_lua_semaphore_cleanup(void *data) +{ + ngx_http_lua_co_ctx_t *coctx = data; + ngx_queue_t *q; + ngx_http_lua_semaphore_t *sem; + + sem = coctx->data; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, + "http lua semaphore cleanup"); + + if (coctx->sleep.timer_set) { + ngx_del_timer(&coctx->sleep); + } + + q = &coctx->sem_wait_queue; + + ngx_queue_remove(q); + sem->wait_count--; + coctx->cleanup = NULL; +} + + +static void +ngx_http_lua_semaphore_handler(ngx_event_t *ev) +{ + ngx_http_lua_semaphore_t *sem; + ngx_http_request_t *r; + ngx_http_lua_ctx_t *ctx; + ngx_http_lua_co_ctx_t *wait_co_ctx; + ngx_connection_t *c; + ngx_queue_t *q; + + sem = ev->data; + + while (!ngx_queue_empty(&sem->wait_queue) && sem->resource_count > 0) { + + q = ngx_queue_head(&sem->wait_queue); + ngx_queue_remove(q); + + sem->wait_count--; + + wait_co_ctx = ngx_queue_data(q, ngx_http_lua_co_ctx_t, sem_wait_queue); + wait_co_ctx->cleanup = NULL; + + if (wait_co_ctx->sleep.timer_set) { + ngx_del_timer(&wait_co_ctx->sleep); + } + + r = ngx_http_lua_get_req(wait_co_ctx->co); + c = r->connection; + + ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); + ngx_http_lua_assert(ctx != NULL); + + sem->resource_count--; + + ctx->cur_co_ctx = wait_co_ctx; + + wait_co_ctx->sem_resume_status = SEMAPHORE_WAIT_SUCC; + + if (ctx->entered_content_phase) { + (void) ngx_http_lua_semaphore_resume(r); + + } else { + ctx->resume_handler = ngx_http_lua_semaphore_resume; + ngx_http_core_run_phases(r); + } + + ngx_http_run_posted_requests(c); + } +} + + +static void +ngx_http_lua_semaphore_timeout_handler(ngx_event_t *ev) +{ + ngx_http_lua_co_ctx_t *wait_co_ctx; + ngx_http_request_t *r; + ngx_http_lua_ctx_t *ctx; + ngx_connection_t *c; + ngx_http_lua_semaphore_t *sem; + + wait_co_ctx = ev->data; + wait_co_ctx->cleanup = NULL; + + dd("ngx_http_lua_semaphore_timeout_handler timeout coctx:%p", wait_co_ctx); + + sem = wait_co_ctx->data; + + ngx_queue_remove(&wait_co_ctx->sem_wait_queue); + sem->wait_count--; + + r = ngx_http_lua_get_req(wait_co_ctx->co); + c = r->connection; + + ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); + ngx_http_lua_assert(ctx != NULL); + + ctx->cur_co_ctx = wait_co_ctx; + + wait_co_ctx->sem_resume_status = SEMAPHORE_WAIT_TIMEOUT; + + if (ctx->entered_content_phase) { + (void) ngx_http_lua_semaphore_resume(r); + + } else { + ctx->resume_handler = ngx_http_lua_semaphore_resume; + ngx_http_core_run_phases(r); + } + + ngx_http_run_posted_requests(c); +} + + +void +ngx_http_lua_ffi_semaphore_gc(ngx_http_lua_semaphore_t *sem) +{ + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, + "in lua gc, semaphore %p", sem); + + if (sem == NULL) { + return; + } + + if (!ngx_queue_empty(&sem->wait_queue)) { + ngx_log_error(NGX_LOG_CRIT, ngx_cycle->log, 0, + "in lua semaphore gc wait queue is" + " not empty while the semaphore %p is being " + "destroyed", sem); + } + + ngx_http_lua_free_semaphore(sem); +} + + +#endif /* NGX_LUA_NO_FFI_API */ + +/* vi:set ft=c ts=4 sw=4 et fdm=marker: */ diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_semaphore.h b/debian/modules/nginx-lua/src/ngx_http_lua_semaphore.h new file mode 100644 index 0000000..a71cc23 --- /dev/null +++ b/debian/modules/nginx-lua/src/ngx_http_lua_semaphore.h @@ -0,0 +1,51 @@ + +/* + * Copyright (C) Yichun Zhang (agentzh) + * Copyright (C) cuiweixie + * I hereby assign copyright in this code to the lua-nginx-module project, + * to be licensed under the same terms as the rest of the code. + */ + + +#ifndef _NGX_HTTP_LUA_SEMAPHORE_H_INCLUDED_ +#define _NGX_HTTP_LUA_SEMAPHORE_H_INCLUDED_ + + +#include "ngx_http_lua_common.h" + + +typedef struct ngx_http_lua_semaphore_mm_block_s { + ngx_uint_t used; + ngx_http_lua_semaphore_mm_t *mm; + ngx_uint_t epoch; +} ngx_http_lua_semaphore_mm_block_t; + + +struct ngx_http_lua_semaphore_mm_s { + ngx_queue_t free_queue; + ngx_uint_t total; + ngx_uint_t used; + ngx_uint_t num_per_block; + ngx_uint_t cur_epoch; + ngx_http_lua_main_conf_t *lmcf; +}; + + +typedef struct ngx_http_lua_semaphore_s { + ngx_queue_t wait_queue; + ngx_queue_t chain; + ngx_event_t sem_event; + ngx_http_lua_semaphore_mm_block_t *block; + int resource_count; + unsigned wait_count; +} ngx_http_lua_semaphore_t; + + +#ifndef NGX_LUA_NO_FFI_API +void ngx_http_lua_cleanup_semaphore_mm(void *data); +#endif + + +#endif /* _NGX_HTTP_LUA_SEMAPHORE_H_INCLUDED_ */ + +/* vi:set ft=c ts=4 sw=4 et fdm=marker: */ diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_shdict.c b/debian/modules/nginx-lua/src/ngx_http_lua_shdict.c index a72f9da..d853382 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_shdict.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_shdict.c @@ -56,6 +56,8 @@ ngx_http_lua_shdict_init_zone(ngx_shm_zone_t *shm_zone, void *data) ngx_http_lua_shdict_ctx_t *octx = data; size_t len; + ngx_int_t rc; + volatile ngx_cycle_t *saved_cycle; ngx_http_lua_shdict_ctx_t *ctx; ngx_http_lua_main_conf_t *lmcf; @@ -117,7 +119,14 @@ done: if (lmcf->shm_zones_inited == lmcf->shm_zones->nelts && lmcf->init_handler) { - if (lmcf->init_handler(ctx->log, lmcf, lmcf->lua) != NGX_OK) { + saved_cycle = ngx_cycle; + ngx_cycle = ctx->cycle; + + rc = lmcf->init_handler(ctx->log, lmcf, lmcf->lua); + + ngx_cycle = saved_cycle; + + if (rc != NGX_OK) { /* an error happened */ return NGX_ERROR; } @@ -378,14 +387,14 @@ ngx_http_lua_inject_shdict_api(ngx_http_lua_main_conf_t *lmcf, lua_State *L) static int ngx_http_lua_shdict_get(lua_State *L) { - return ngx_http_lua_shdict_get_helper(L, 0 /* stale */); + return ngx_http_lua_shdict_get_helper(L, 0 /* stale */); } static int ngx_http_lua_shdict_get_stale(lua_State *L) { - return ngx_http_lua_shdict_get_helper(L, 1 /* stale */); + return ngx_http_lua_shdict_get_helper(L, 1 /* stale */); } diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_shdict.h b/debian/modules/nginx-lua/src/ngx_http_lua_shdict.h index 29ea28f..aa1bb58 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_shdict.h +++ b/debian/modules/nginx-lua/src/ngx_http_lua_shdict.h @@ -37,6 +37,7 @@ typedef struct { ngx_str_t name; ngx_http_lua_main_conf_t *main_conf; ngx_log_t *log; + ngx_cycle_t *cycle; } ngx_http_lua_shdict_ctx_t; diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_sleep.c b/debian/modules/nginx-lua/src/ngx_http_lua_sleep.c index b59b9e7..a887c3a 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_sleep.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_sleep.c @@ -55,7 +55,8 @@ ngx_http_lua_ngx_sleep(lua_State *L) ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE | NGX_HTTP_LUA_CONTEXT_ACCESS | NGX_HTTP_LUA_CONTEXT_CONTENT - | NGX_HTTP_LUA_CONTEXT_TIMER); + | NGX_HTTP_LUA_CONTEXT_TIMER + | NGX_HTTP_LUA_CONTEXT_SSL_CERT); coctx = ctx->cur_co_ctx; if (coctx == NULL) { @@ -102,7 +103,7 @@ ngx_http_lua_sleep_handler(ngx_event_t *ev) return; } - if (c->fd != -1) { /* not a fake connection */ + if (c->fd != (ngx_socket_t) -1) { /* not a fake connection */ log_ctx = c->log->data; log_ctx->current_request = r; } diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_socket_tcp.c b/debian/modules/nginx-lua/src/ngx_http_lua_socket_tcp.c index 4640f87..98801f5 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_socket_tcp.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_socket_tcp.c @@ -383,7 +383,8 @@ ngx_http_lua_socket_tcp(lua_State *L) ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE | NGX_HTTP_LUA_CONTEXT_ACCESS | NGX_HTTP_LUA_CONTEXT_CONTENT - | NGX_HTTP_LUA_CONTEXT_TIMER); + | NGX_HTTP_LUA_CONTEXT_TIMER + | NGX_HTTP_LUA_CONTEXT_SSL_CERT); lua_createtable(L, 3 /* narr */, 1 /* nrec */); lua_pushlightuserdata(L, &ngx_http_lua_tcp_socket_metatable_key); @@ -440,22 +441,13 @@ ngx_http_lua_socket_tcp_connect(lua_State *L) ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE | NGX_HTTP_LUA_CONTEXT_ACCESS | NGX_HTTP_LUA_CONTEXT_CONTENT - | NGX_HTTP_LUA_CONTEXT_TIMER); + | NGX_HTTP_LUA_CONTEXT_TIMER + | NGX_HTTP_LUA_CONTEXT_SSL_CERT); luaL_checktype(L, 1, LUA_TTABLE); p = (u_char *) luaL_checklstring(L, 2, &len); - host.data = ngx_palloc(r->pool, len + 1); - if (host.data == NULL) { - return luaL_error(L, "no memory"); - } - - host.len = len; - - ngx_memcpy(host.data, p, len); - host.data[len] = '\0'; - key_index = 2; custom_pool = 0; @@ -610,6 +602,18 @@ ngx_http_lua_socket_tcp_connect(lua_State *L) /* rc == NGX_DECLINED */ + /* TODO: we should avoid this in-pool allocation */ + + host.data = ngx_palloc(r->pool, len + 1); + if (host.data == NULL) { + return luaL_error(L, "no memory"); + } + + host.len = len; + + ngx_memcpy(host.data, p, len); + host.data[len] = '\0'; + ngx_memzero(&url, sizeof(ngx_url_t)); url.url.len = host.len; @@ -804,7 +808,7 @@ ngx_http_lua_socket_resolve_handler(ngx_resolver_ctx_t *ctx) u->write_prepare_retvals = ngx_http_lua_socket_conn_error_retval_handler; ngx_http_lua_socket_handle_conn_error(r, u, - NGX_HTTP_LUA_SOCKET_FT_RESOLVER); + NGX_HTTP_LUA_SOCKET_FT_RESOLVER); if (waiting) { ngx_http_run_posted_requests(c); @@ -1001,7 +1005,7 @@ ngx_http_lua_socket_resolve_retval_handler(ngx_http_request_t *r, } if (u->cleanup == NULL) { - cln = ngx_http_cleanup_add(r, 0); + cln = ngx_http_lua_cleanup_add(r, 0); if (cln == NULL) { u->ft_type |= NGX_HTTP_LUA_SOCKET_FT_ERROR; lua_pushnil(L); @@ -1089,7 +1093,7 @@ ngx_http_lua_socket_resolve_retval_handler(ngx_http_request_t *r, if (ngx_handle_write_event(c->write, 0) != NGX_OK) { ngx_http_lua_socket_handle_conn_error(r, u, - NGX_HTTP_LUA_SOCKET_FT_ERROR); + NGX_HTTP_LUA_SOCKET_FT_ERROR); lua_pushnil(L); lua_pushliteral(L, "failed to handle write event"); return 2; @@ -1097,7 +1101,7 @@ ngx_http_lua_socket_resolve_retval_handler(ngx_http_request_t *r, if (ngx_handle_read_event(c->read, 0) != NGX_OK) { ngx_http_lua_socket_handle_conn_error(r, u, - NGX_HTTP_LUA_SOCKET_FT_ERROR); + NGX_HTTP_LUA_SOCKET_FT_ERROR); lua_pushnil(L); lua_pushliteral(L, "failed to handle read event"); return 2; @@ -1310,6 +1314,17 @@ ngx_http_lua_socket_tcp_sslhandshake(lua_State *L) if (n >= 4) { u->ssl_verify = lua_toboolean(L, 4); + + if (n >= 5) { + if (lua_toboolean(L, 5)) { +#ifdef NGX_HTTP_LUA_USE_OCSP + SSL_set_tlsext_status_type(c->ssl->connection, + TLSEXT_STATUSTYPE_ocsp); +#else + return luaL_error(L, "no OCSP support"); +#endif + } + } } } } @@ -1353,6 +1368,12 @@ new_ssl_name: u->write_co_ctx = coctx; +#if 0 +#ifdef NGX_HTTP_LUA_USE_OCSP + SSL_set_tlsext_status_type(c->ssl->connection, TLSEXT_STATUSTYPE_ocsp); +#endif +#endif + rc = ngx_ssl_handshake(c); dd("ngx_ssl_handshake returned %d", (int) rc); @@ -1513,7 +1534,7 @@ ngx_http_lua_ssl_handshake_retval_handler(ngx_http_request_t *r, return 1; } - ud = lua_newuserdata(L, sizeof(ngx_ssl_session_t*)); + ud = lua_newuserdata(L, sizeof(ngx_ssl_session_t *)); c = u->peer.connection; @@ -1525,8 +1546,8 @@ ngx_http_lua_ssl_handshake_retval_handler(ngx_http_request_t *r, *ud = ssl_session; ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, - "lua ssl save session: %p:%d", ssl_session, - ssl_session->references); + "lua ssl save session: %p:%d", ssl_session, + ssl_session->references); /* set up the __gc metamethod */ lua_pushlightuserdata(L, &ngx_http_lua_ssl_session_metatable_key); @@ -1945,8 +1966,8 @@ ngx_http_lua_socket_read_line(void *data, ssize_t bytes) #endif dd("already read: %p: %.*s", u->buf_in, - (int) (u->buf_in->buf->last - u->buf_in->buf->pos), - u->buf_in->buf->pos); + (int) (u->buf_in->buf->last - u->buf_in->buf->pos), + u->buf_in->buf->pos); dd("data read: %.*s", (int) bytes, b->pos); @@ -1965,8 +1986,8 @@ ngx_http_lua_socket_read_line(void *data, ssize_t bytes) u->buf_in->buf->last = dst; dd("read a line: %p: %.*s", u->buf_in, - (int) (u->buf_in->buf->last - u->buf_in->buf->pos), - u->buf_in->buf->pos); + (int) (u->buf_in->buf->last - u->buf_in->buf->pos), + u->buf_in->buf->pos); return NGX_OK; @@ -2242,7 +2263,7 @@ success: if (n == NGX_ERROR) { u->socket_errno = ngx_socket_errno; ngx_http_lua_socket_handle_read_error(r, u, - NGX_HTTP_LUA_SOCKET_FT_ERROR); + NGX_HTTP_LUA_SOCKET_FT_ERROR); return NGX_ERROR; } @@ -2687,7 +2708,7 @@ ngx_http_lua_socket_tcp_handler(ngx_event_t *ev) r = u->request; c = r->connection; - if (c->fd != -1) { /* not a fake connection */ + if (c->fd != (ngx_socket_t) -1) { /* not a fake connection */ ctx = c->log->data; ctx->current_request = r; } @@ -2775,7 +2796,7 @@ ngx_http_lua_socket_send_handler(ngx_http_request_t *r, } ngx_http_lua_socket_handle_write_error(r, u, - NGX_HTTP_LUA_SOCKET_FT_TIMEOUT); + NGX_HTTP_LUA_SOCKET_FT_TIMEOUT); return; } @@ -2802,7 +2823,7 @@ ngx_http_lua_socket_send(ngx_http_request_t *r, ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); if (ctx == NULL) { ngx_http_lua_socket_handle_write_error(r, u, - NGX_HTTP_LUA_SOCKET_FT_ERROR); + NGX_HTTP_LUA_SOCKET_FT_ERROR); return NGX_ERROR; } @@ -3332,6 +3353,7 @@ ngx_http_lua_socket_tcp_finalize(ngx_http_request_t *r, if (u->cleanup) { *u->cleanup = NULL; + ngx_http_lua_cleanup_free(r, u->cleanup); u->cleanup = NULL; } @@ -3423,7 +3445,7 @@ ngx_http_lua_socket_test_connect(ngx_http_request_t *r, ngx_connection_t *c) if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { dd("pending eof: (%p)%d (%p)%d", c->write, c->write->pending_eof, - c->read, c->read->pending_eof); + c->read, c->read->pending_eof); if (c->write->pending_eof) { ev = c->write; @@ -4251,7 +4273,7 @@ ngx_http_lua_req_socket(lua_State *L) u->connect_timeout = u->conf->connect_timeout; u->send_timeout = u->conf->send_timeout; - cln = ngx_http_cleanup_add(r, 0); + cln = ngx_http_lua_cleanup_add(r, 0); if (cln == NULL) { u->ft_type |= NGX_HTTP_LUA_SOCKET_FT_ERROR; lua_pushnil(L); @@ -4347,7 +4369,7 @@ ngx_http_lua_socket_tcp_setkeepalive(lua_State *L) ngx_http_lua_socket_tcp_upstream_t *u; ngx_connection_t *c; ngx_http_lua_socket_pool_t *spool; - size_t size; + size_t size, key_len; ngx_str_t key; ngx_uint_t i; ngx_queue_t *q; @@ -4477,7 +4499,9 @@ ngx_http_lua_socket_tcp_setkeepalive(lua_State *L) ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua tcp socket connection pool size: %ui", pool_size); - size = sizeof(ngx_http_lua_socket_pool_t) + key.len + key_len = ngx_align(key.len + 1, sizeof(void *)); + + size = sizeof(ngx_http_lua_socket_pool_t) + key_len - 1 + sizeof(ngx_http_lua_socket_pool_item_t) * pool_size; @@ -4505,7 +4529,12 @@ ngx_http_lua_socket_tcp_setkeepalive(lua_State *L) p = ngx_copy(spool->key, key.data, key.len); *p++ = '\0'; - items = (ngx_http_lua_socket_pool_item_t *) p; + items = (ngx_http_lua_socket_pool_item_t *) (spool->key + key_len); + + dd("items: %p", items); + + ngx_http_lua_assert((void *) items == ngx_align_ptr(items, + sizeof(void *))); for (i = 0; i < pool_size; i++) { ngx_queue_insert_head(&spool->free, &items[i].queue); @@ -4688,7 +4717,7 @@ ngx_http_lua_get_keepalive_peer(ngx_http_request_t *r, lua_State *L, #endif if (u->cleanup == NULL) { - cln = ngx_http_cleanup_add(r, 0); + cln = ngx_http_lua_cleanup_add(r, 0); if (cln == NULL) { u->ft_type |= NGX_HTTP_LUA_SOCKET_FT_ERROR; lua_settop(L, top); @@ -4893,83 +4922,52 @@ ngx_http_lua_socket_push_input_data(ngx_http_request_t *r, { ngx_chain_t *cl; ngx_chain_t **ll; - size_t size; +#if (DDEBUG) || (NGX_DTRACE) + size_t size = 0; +#endif + size_t chunk_size; ngx_buf_t *b; size_t nbufs; - u_char *p; - u_char *last; - - if (!u->bufs_in) { - lua_pushliteral(L, ""); - ngx_http_lua_probe_socket_tcp_receive_done(r, u, (u_char *) "", 0); - return NGX_OK; - } + luaL_Buffer luabuf; dd("bufs_in: %p, buf_in: %p", u->bufs_in, u->buf_in); - size = 0; nbufs = 0; ll = NULL; + luaL_buffinit(L, &luabuf); + for (cl = u->bufs_in; cl; cl = cl->next) { b = cl->buf; - size += b->last - b->pos; + chunk_size = b->last - b->pos; + + dd("copying input data chunk from %p: \"%.*s\"", cl, + (int) chunk_size, b->pos); + + luaL_addlstring(&luabuf, (char *) b->pos, chunk_size); if (cl->next) { ll = &cl->next; } +#if (DDEBUG) || (NGX_DTRACE) + size += chunk_size; +#endif + nbufs++; } + luaL_pushresult(&luabuf); + +#if (DDEBUG) dd("size: %d, nbufs: %d", (int) size, (int) nbufs); +#endif - if (size == 0) { - lua_pushliteral(L, ""); - - ngx_http_lua_probe_socket_tcp_receive_done(r, u, (u_char *) "", 0); - - goto done; - } - - if (nbufs == 1) { - b = u->buf_in->buf; - - lua_pushlstring(L, (char *) b->pos, size); - - dd("copying input data chunk from %p: \"%.*s\"", u->buf_in, (int) size, - b->pos); - - ngx_http_lua_probe_socket_tcp_receive_done(r, u, b->pos, size); - - goto done; - } - - /* nbufs > 1 */ - - dd("WARN: allocate a big memory: %d", (int) size); - - p = ngx_palloc(r->pool, size); - if (p == NULL) { - return NGX_ERROR; - } - - last = p; - for (cl = u->bufs_in; cl; cl = cl->next) { - b = cl->buf; - last = ngx_copy(last, b->pos, b->last - b->pos); - - dd("copying input data chunk from %p: \"%.*s\"", cl, - (int) (b->last - b->pos), b->pos); - } - - lua_pushlstring(L, (char *) p, size); - - ngx_http_lua_probe_socket_tcp_receive_done(r, u, p, size); - - ngx_pfree(r->pool, p); - -done: +#if (NGX_DTRACE) + ngx_http_lua_probe_socket_tcp_receive_done(r, u, + (u_char *) lua_tostring(L, -1), + size); +#endif if (nbufs > 1 && ll) { dd("recycle buffers: %d", (int) (nbufs - 1)); @@ -4985,8 +4983,10 @@ done: u->buffer.last = u->buffer.start; } - u->buf_in->buf->last = u->buffer.pos; - u->buf_in->buf->pos = u->buffer.pos; + if (u->bufs_in) { + u->buf_in->buf->last = u->buffer.pos; + u->buf_in->buf->pos = u->buffer.pos; + } return NGX_OK; } diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_socket_tcp.h b/debian/modules/nginx-lua/src/ngx_http_lua_socket_tcp.h index 915d4f4..dbdee41 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_socket_tcp.h +++ b/debian/modules/nginx-lua/src/ngx_http_lua_socket_tcp.h @@ -31,8 +31,8 @@ typedef ngx_http_lua_socket_tcp_upstream_t *u, lua_State *L); -typedef void (*ngx_http_lua_socket_tcp_upstream_handler_pt)( - ngx_http_request_t *r, ngx_http_lua_socket_tcp_upstream_t *u); +typedef void (*ngx_http_lua_socket_tcp_upstream_handler_pt) + (ngx_http_request_t *r, ngx_http_lua_socket_tcp_upstream_t *u); typedef struct { @@ -111,7 +111,7 @@ struct ngx_http_lua_socket_tcp_upstream_s { }; -typedef struct ngx_http_lua_dfa_edge_s ngx_http_lua_dfa_edge_t; +typedef struct ngx_http_lua_dfa_edge_s ngx_http_lua_dfa_edge_t; struct ngx_http_lua_dfa_edge_s { diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_socket_udp.c b/debian/modules/nginx-lua/src/ngx_http_lua_socket_udp.c index 23cc69a..bfb122f 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_socket_udp.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_socket_udp.c @@ -140,7 +140,8 @@ ngx_http_lua_socket_udp(lua_State *L) ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE | NGX_HTTP_LUA_CONTEXT_ACCESS | NGX_HTTP_LUA_CONTEXT_CONTENT - | NGX_HTTP_LUA_CONTEXT_TIMER); + | NGX_HTTP_LUA_CONTEXT_TIMER + | NGX_HTTP_LUA_CONTEXT_SSL_CERT); lua_createtable(L, 3 /* narr */, 1 /* nrec */); lua_pushlightuserdata(L, &ngx_http_lua_socket_udp_metatable_key); @@ -200,7 +201,8 @@ ngx_http_lua_socket_udp_setpeername(lua_State *L) ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE | NGX_HTTP_LUA_CONTEXT_ACCESS | NGX_HTTP_LUA_CONTEXT_CONTENT - | NGX_HTTP_LUA_CONTEXT_TIMER); + | NGX_HTTP_LUA_CONTEXT_TIMER + | NGX_HTTP_LUA_CONTEXT_SSL_CERT); luaL_checktype(L, 1, LUA_TTABLE); @@ -1299,7 +1301,7 @@ ngx_http_lua_socket_udp_handler(ngx_event_t *ev) r = u->request; c = r->connection; - if (c->fd != -1) { /* not a fake connection */ + if (c->fd != (ngx_socket_t) -1) { /* not a fake connection */ ctx = c->log->data; ctx->current_request = r; } @@ -1358,7 +1360,7 @@ ngx_http_lua_udp_connect(ngx_udp_connection_t *uc) ngx_log_debug1(NGX_LOG_DEBUG_EVENT, &uc->log, 0, "UDP socket %d", s); - if (s == -1) { + if (s == (ngx_socket_t) -1) { ngx_log_error(NGX_LOG_ALERT, &uc->log, ngx_socket_errno, ngx_socket_n " failed"); diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_socket_udp.h b/debian/modules/nginx-lua/src/ngx_http_lua_socket_udp.h index 819e36b..dd75b2d 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_socket_udp.h +++ b/debian/modules/nginx-lua/src/ngx_http_lua_socket_udp.h @@ -20,8 +20,8 @@ typedef ngx_http_lua_socket_udp_upstream_t *u, lua_State *L); -typedef void (*ngx_http_lua_socket_udp_upstream_handler_pt)( - ngx_http_request_t *r, ngx_http_lua_socket_udp_upstream_t *u); +typedef void (*ngx_http_lua_socket_udp_upstream_handler_pt) + (ngx_http_request_t *r, ngx_http_lua_socket_udp_upstream_t *u); struct ngx_http_lua_socket_udp_upstream_s { diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_ssl_certby.c b/debian/modules/nginx-lua/src/ngx_http_lua_ssl_certby.c new file mode 100644 index 0000000..f8648a7 --- /dev/null +++ b/debian/modules/nginx-lua/src/ngx_http_lua_ssl_certby.c @@ -0,0 +1,938 @@ + +/* + * Copyright (C) Yichun Zhang (agentzh) + */ + + +#ifndef DDEBUG +#define DDEBUG 0 +#endif +#include "ddebug.h" + + +#if (NGX_HTTP_SSL) + + +#include "ngx_http_lua_cache.h" +#include "ngx_http_lua_initworkerby.h" +#include "ngx_http_lua_util.h" +#include "ngx_http_ssl_module.h" +#include "ngx_http_lua_contentby.h" +#include "ngx_http_lua_ssl_certby.h" +#include "ngx_http_lua_directive.h" + + +enum { + NGX_HTTP_LUA_ADDR_TYPE_UNIX = 0, + NGX_HTTP_LUA_ADDR_TYPE_INET = 1, + NGX_HTTP_LUA_ADDR_TYPE_INET6 = 2 +}; + + +static void ngx_http_lua_ssl_cert_done(void *data); +static void ngx_http_lua_ssl_cert_aborted(void *data); +static u_char *ngx_http_lua_log_ssl_cert_error(ngx_log_t *log, u_char *buf, + size_t len); +static ngx_int_t ngx_http_lua_ssl_cert_by_chunk(lua_State *L, + ngx_http_request_t *r); + + +int ngx_http_lua_ssl_ctx_index = -1; + + +ngx_int_t +ngx_http_lua_ssl_cert_handler_file(ngx_http_request_t *r, + ngx_http_lua_srv_conf_t *lscf, lua_State *L) +{ + ngx_int_t rc; + + rc = ngx_http_lua_cache_loadfile(r->connection->log, L, + lscf->ssl.cert_src.data, + lscf->ssl.cert_src_key); + if (rc != NGX_OK) { + return rc; + } + + /* make sure we have a valid code chunk */ + ngx_http_lua_assert(lua_isfunction(L, -1)); + + return ngx_http_lua_ssl_cert_by_chunk(L, r); +} + + +ngx_int_t +ngx_http_lua_ssl_cert_handler_inline(ngx_http_request_t *r, + ngx_http_lua_srv_conf_t *lscf, lua_State *L) +{ + ngx_int_t rc; + + rc = ngx_http_lua_cache_loadbuffer(r->connection->log, L, + lscf->ssl.cert_src.data, + lscf->ssl.cert_src.len, + lscf->ssl.cert_src_key, + "=ssl_certificate_by_lua"); + if (rc != NGX_OK) { + return rc; + } + + /* make sure we have a valid code chunk */ + ngx_http_lua_assert(lua_isfunction(L, -1)); + + return ngx_http_lua_ssl_cert_by_chunk(L, r); +} + + +char * +ngx_http_lua_ssl_cert_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) +{ + char *rv; + ngx_conf_t save; + + save = *cf; + cf->handler = ngx_http_lua_ssl_cert_by_lua; + cf->handler_conf = conf; + + rv = ngx_http_lua_conf_lua_block_parse(cf, cmd); + + *cf = save; + + return rv; +} + + +char * +ngx_http_lua_ssl_cert_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) +{ +#if OPENSSL_VERSION_NUMBER < 0x1000205fL + + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "at least OpenSSL 1.0.2e required but found " + OPENSSL_VERSION_TEXT); + + return NGX_CONF_ERROR; + +#else + + u_char *p; + u_char *name; + ngx_str_t *value; + ngx_http_lua_srv_conf_t *lscf = conf; + + /* must specifiy a concrete handler */ + if (cmd->post == NULL) { + return NGX_CONF_ERROR; + } + + if (lscf->ssl.cert_handler) { + return "is duplicate"; + } + + if (ngx_http_lua_ssl_ctx_index == -1) { + ngx_http_lua_ssl_ctx_index = SSL_get_ex_new_index(0, NULL, NULL, + NULL, NULL); + + if (ngx_ssl_connection_index == -1) { + ngx_ssl_error(NGX_LOG_ALERT, cf->log, 0, + "lua: SSL_get_ex_new_index() failed"); + return NGX_CONF_ERROR; + } + } + + value = cf->args->elts; + + lscf->ssl.cert_handler = (ngx_http_lua_srv_conf_handler_pt) cmd->post; + + if (cmd->post == ngx_http_lua_ssl_cert_handler_file) { + /* Lua code in an external file */ + + name = ngx_http_lua_rebase_path(cf->pool, value[1].data, + value[1].len); + if (name == NULL) { + return NGX_CONF_ERROR; + } + + lscf->ssl.cert_src.data = name; + lscf->ssl.cert_src.len = ngx_strlen(name); + + p = ngx_palloc(cf->pool, NGX_HTTP_LUA_FILE_KEY_LEN + 1); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + lscf->ssl.cert_src_key = p; + + p = ngx_copy(p, NGX_HTTP_LUA_FILE_TAG, NGX_HTTP_LUA_FILE_TAG_LEN); + p = ngx_http_lua_digest_hex(p, value[1].data, value[1].len); + *p = '\0'; + + } else { + /* inlined Lua code */ + + lscf->ssl.cert_src = value[1]; + + p = ngx_palloc(cf->pool, NGX_HTTP_LUA_INLINE_KEY_LEN + 1); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + lscf->ssl.cert_src_key = p; + + p = ngx_copy(p, NGX_HTTP_LUA_INLINE_TAG, NGX_HTTP_LUA_INLINE_TAG_LEN); + p = ngx_http_lua_digest_hex(p, value[1].data, value[1].len); + *p = '\0'; + } + + return NGX_CONF_OK; + +#endif /* OPENSSL_VERSION_NUMBER < 0x1000205fL */ +} + + +int +ngx_http_lua_ssl_cert_handler(ngx_ssl_conn_t *ssl_conn, void *data) +{ + lua_State *L; + ngx_int_t rc; + ngx_connection_t *c, *fc; + ngx_http_request_t *r = NULL; + ngx_pool_cleanup_t *cln; + ngx_http_connection_t *hc; + ngx_http_lua_srv_conf_t *lscf; + ngx_http_lua_ssl_cert_ctx_t *cctx; + + c = ngx_ssl_get_connection(ssl_conn); + + dd("c = %p", c); + + cctx = ngx_http_lua_ssl_get_ctx(c->ssl->connection); + + dd("ssl cert handler, cert-ctx=%p", cctx); + + if (cctx) { + /* not the first time */ + + if (cctx->done) { + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, + "lua_certificate_by_lua: cert cb exit code: %d", + cctx->exit_code); + + dd("lua ssl cert done, finally"); + return cctx->exit_code; + } + + return -1; + } + + /* cctx == NULL */ + + dd("first time"); + + hc = c->data; + + fc = ngx_http_lua_create_fake_connection(NULL); + if (fc == NULL) { + goto failed; + } + + fc->log->handler = ngx_http_lua_log_ssl_cert_error; + fc->log->data = fc; + + fc->addr_text = c->addr_text; + fc->listening = c->listening; + + r = ngx_http_lua_create_fake_request(fc); + if (r == NULL) { + goto failed; + } + + r->main_conf = hc->conf_ctx->main_conf; + r->srv_conf = hc->conf_ctx->srv_conf; + r->loc_conf = hc->conf_ctx->loc_conf; + + fc->log->file = c->log->file; + fc->log->log_level = c->log->log_level; + fc->ssl = c->ssl; + + cctx = ngx_pcalloc(c->pool, sizeof(ngx_http_lua_ssl_cert_ctx_t)); + if (cctx == NULL) { + goto failed; /* error */ + } + + cctx->exit_code = 1; /* successful by default */ + cctx->connection = c; + cctx->request = r; + + dd("setting cctx"); + + if (SSL_set_ex_data(c->ssl->connection, ngx_http_lua_ssl_ctx_index, cctx) + == 0) + { + ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_ex_data() failed"); + goto failed; + } + + lscf = ngx_http_get_module_srv_conf(r, ngx_http_lua_module); + + /* TODO honor lua_code_cache off */ + L = ngx_http_lua_get_lua_vm(r, NULL); + + c->log->action = "loading SSL certificate by lua"; + + rc = lscf->ssl.cert_handler(r, lscf, L); + + if (rc >= NGX_OK || rc == NGX_ERROR) { + cctx->done = 1; + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, + "lua_certificate_by_lua: handler return value: %i, " + "cert cb exit code: %d", rc, cctx->exit_code); + + c->log->action = "SSL handshaking"; + return cctx->exit_code; + } + + /* rc == NGX_DONE */ + + cln = ngx_pool_cleanup_add(fc->pool, 0); + if (cln == NULL) { + goto failed; + } + + cln->handler = ngx_http_lua_ssl_cert_done; + cln->data = cctx; + + cln = ngx_pool_cleanup_add(c->pool, 0); + if (cln == NULL) { + goto failed; + } + + cln->handler = ngx_http_lua_ssl_cert_aborted; + cln->data = cctx; + + return -1; + +#if 1 +failed: + + if (r && r->pool) { + ngx_http_lua_free_fake_request(r); + } + + if (fc) { + ngx_http_lua_close_fake_connection(fc); + } + + return 0; +#endif +} + + +static void +ngx_http_lua_ssl_cert_done(void *data) +{ + ngx_connection_t *c; + ngx_http_lua_ssl_cert_ctx_t *cctx = data; + + dd("lua ssl cert done"); + + if (cctx->aborted) { + return; + } + + ngx_http_lua_assert(cctx->done == 0); + + cctx->done = 1; + + c = cctx->connection; + + c->log->action = "SSL handshaking"; + + ngx_post_event(c->write, &ngx_posted_events); +} + + +static void +ngx_http_lua_ssl_cert_aborted(void *data) +{ + ngx_http_lua_ssl_cert_ctx_t *cctx = data; + + dd("lua ssl cert done"); + + if (cctx->done) { + /* completed successfully already */ + return; + } + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cctx->connection->log, 0, + "lua_certificate_by_lua: cert cb aborted"); + + cctx->aborted = 1; + cctx->request->connection->ssl = NULL; + + ngx_http_lua_finalize_fake_request(cctx->request, NGX_ERROR); +} + + +static u_char * +ngx_http_lua_log_ssl_cert_error(ngx_log_t *log, u_char *buf, size_t len) +{ + u_char *p; + ngx_connection_t *c; + + if (log->action) { + p = ngx_snprintf(buf, len, " while %s", log->action); + len -= p - buf; + buf = p; + } + + p = ngx_snprintf(buf, len, ", context: ssl_certificate_by_lua*"); + len -= p - buf; + buf = p; + + c = log->data; + + if (c->addr_text.len) { + p = ngx_snprintf(buf, len, ", client: %V", &c->addr_text); + len -= p - buf; + buf = p; + } + + if (c && c->listening && c->listening->addr_text.len) { + p = ngx_snprintf(buf, len, ", server: %V", &c->listening->addr_text); + /* len -= p - buf; */ + buf = p; + } + + return buf; +} + + +static ngx_int_t +ngx_http_lua_ssl_cert_by_chunk(lua_State *L, ngx_http_request_t *r) +{ + int co_ref; + ngx_int_t rc; + lua_State *co; + ngx_http_lua_ctx_t *ctx; + ngx_http_cleanup_t *cln; + + ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); + + if (ctx == NULL) { + ctx = ngx_http_lua_create_ctx(r); + if (ctx == NULL) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + } else { + dd("reset ctx"); + ngx_http_lua_reset_ctx(r, L, ctx); + } + + ctx->entered_content_phase = 1; + + /* {{{ new coroutine to handle request */ + co = ngx_http_lua_new_thread(r, L, &co_ref); + + if (co == NULL) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "lua: failed to create new coroutine to handle request"); + + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + /* move code closure to new coroutine */ + lua_xmove(L, co, 1); + + /* set closure's env table to new coroutine's globals table */ + ngx_http_lua_get_globals_table(co); + lua_setfenv(co, -2); + + /* save nginx request in coroutine globals table */ + ngx_http_lua_set_req(co, r); + + ctx->cur_co_ctx = &ctx->entry_co_ctx; + ctx->cur_co_ctx->co = co; + ctx->cur_co_ctx->co_ref = co_ref; +#ifdef NGX_LUA_USE_ASSERT + ctx->cur_co_ctx->co_top = 1; +#endif + + /* register request cleanup hooks */ + if (ctx->cleanup == NULL) { + cln = ngx_http_cleanup_add(r, 0); + if (cln == NULL) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + cln->handler = ngx_http_lua_request_cleanup_handler; + cln->data = ctx; + ctx->cleanup = &cln->handler; + } + + ctx->context = NGX_HTTP_LUA_CONTEXT_SSL_CERT; + + rc = ngx_http_lua_run_thread(L, r, ctx, 0); + + if (rc == NGX_ERROR || rc >= NGX_OK) { + /* do nothing */ + + } else if (rc == NGX_AGAIN) { + rc = ngx_http_lua_content_run_posted_threads(L, r, ctx, 0); + + } else if (rc == NGX_DONE) { + rc = ngx_http_lua_content_run_posted_threads(L, r, ctx, 1); + + } else { + rc = NGX_OK; + } + + ngx_http_lua_finalize_request(r, rc); + return rc; +} + + +#ifndef NGX_LUA_NO_FFI_API + +int +ngx_http_lua_ffi_ssl_get_tls1_version(ngx_http_request_t *r, char **err) +{ +#ifndef TLS1_get_version + + *err = "no TLS1 support"; + return NGX_ERROR; + +#else + + ngx_ssl_conn_t *ssl_conn; + + if (r->connection == NULL || r->connection->ssl == NULL) { + *err = "bad request"; + return NGX_ERROR; + } + + ssl_conn = r->connection->ssl->connection; + if (ssl_conn == NULL) { + *err = "bad ssl conn"; + return NGX_ERROR; + } + + dd("tls1 ver: %d", (int) TLS1_get_version(ssl_conn)); + + return (int) TLS1_get_version(ssl_conn); + +#endif +} + + +int +ngx_http_lua_ffi_ssl_clear_certs(ngx_http_request_t *r, char **err) +{ +#if OPENSSL_VERSION_NUMBER < 0x1000205fL + + *err = "at least OpenSSL 1.0.2e required but found " OPENSSL_VERSION_TEXT; + return NGX_ERROR; + +#else + + ngx_ssl_conn_t *ssl_conn; + + if (r->connection == NULL || r->connection->ssl == NULL) { + *err = "bad request"; + return NGX_ERROR; + } + + ssl_conn = r->connection->ssl->connection; + if (ssl_conn == NULL) { + *err = "bad ssl conn"; + return NGX_ERROR; + } + + SSL_certs_clear(ssl_conn); + return NGX_OK; + +#endif /* OPENSSL_VERSION_NUMBER < 0x1000205fL */ +} + + +int +ngx_http_lua_ffi_ssl_set_der_certificate(ngx_http_request_t *r, + const char *data, size_t len, char **err) +{ +#if OPENSSL_VERSION_NUMBER < 0x1000205fL + + *err = "at least OpenSSL 1.0.2e required but found " OPENSSL_VERSION_TEXT; + return NGX_ERROR; + +#else + + BIO *bio = NULL; + X509 *x509 = NULL; + ngx_ssl_conn_t *ssl_conn; + + if (r->connection == NULL || r->connection->ssl == NULL) { + *err = "bad request"; + return NGX_ERROR; + } + + ssl_conn = r->connection->ssl->connection; + if (ssl_conn == NULL) { + *err = "bad ssl conn"; + return NGX_ERROR; + } + + bio = BIO_new_mem_buf((char *) data, len); + if (bio == NULL) { + *err = " BIO_new_mem_buf() failed"; + goto failed; + } + + x509 = d2i_X509_bio(bio, NULL); + if (x509 == NULL) { + *err = " d2i_X509_bio() failed"; + goto failed; + } + + if (SSL_use_certificate(ssl_conn, x509) == 0) { + *err = " SSL_use_certificate() failed"; + goto failed; + } + +#if 0 + if (SSL_set_ex_data(ssl_conn, ngx_ssl_certificate_index, x509) == 0) { + *err = " SSL_set_ex_data() failed"; + goto failed; + } +#endif + + X509_free(x509); + x509 = NULL; + + /* read rest of the chain */ + + while (!BIO_eof(bio)) { + + x509 = d2i_X509_bio(bio, NULL); + if (x509 == NULL) { + *err = "d2i_X509_bio() failed"; + goto failed; + } + + if (SSL_add0_chain_cert(ssl_conn, x509) == 0) { + *err = "SSL_add0_chain_cert() failed"; + goto failed; + } + } + + BIO_free(bio); + + *err = NULL; + return NGX_OK; + +failed: + + if (bio) { + BIO_free(bio); + } + + if (x509) { + X509_free(x509); + } + + return NGX_ERROR; + +#endif /* OPENSSL_VERSION_NUMBER < 0x1000205fL */ +} + + +int +ngx_http_lua_ffi_ssl_set_der_private_key(ngx_http_request_t *r, + const char *data, size_t len, char **err) +{ + BIO *bio = NULL; + EVP_PKEY *pkey = NULL; + ngx_ssl_conn_t *ssl_conn; + + if (r->connection == NULL || r->connection->ssl == NULL) { + *err = "bad request"; + return NGX_ERROR; + } + + ssl_conn = r->connection->ssl->connection; + if (ssl_conn == NULL) { + *err = "bad ssl conn"; + return NGX_ERROR; + } + + bio = BIO_new_mem_buf((char *) data, len); + if (bio == NULL) { + *err = "BIO_new_mem_buf() failed"; + goto failed; + } + + pkey = d2i_PrivateKey_bio(bio, NULL); + if (pkey == NULL) { + *err = "d2i_PrivateKey_bio() failed"; + goto failed; + } + + if (SSL_use_PrivateKey(ssl_conn, pkey) == 0) { + *err = "SSL_CTX_use_PrivateKey() failed"; + goto failed; + } + + EVP_PKEY_free(pkey); + BIO_free(bio); + + return NGX_OK; + +failed: + + if (pkey) { + EVP_PKEY_free(pkey); + } + + if (bio) { + BIO_free(bio); + } + + return NGX_ERROR; +} + + +int +ngx_http_lua_ffi_ssl_raw_server_addr(ngx_http_request_t *r, char **addr, + size_t *addrlen, int *addrtype, char **err) +{ +#if (NGX_HAVE_UNIX_DOMAIN) + struct sockaddr_un *saun; +#endif + ngx_ssl_conn_t *ssl_conn; + ngx_connection_t *c; + struct sockaddr_in *sin; +#if (NGX_HAVE_INET6) + struct sockaddr_in6 *sin6; +#endif + + if (r->connection == NULL || r->connection->ssl == NULL) { + *err = "bad request"; + return NGX_ERROR; + } + + ssl_conn = r->connection->ssl->connection; + if (ssl_conn == NULL) { + *err = "bad ssl conn"; + return NGX_ERROR; + } + + c = ngx_ssl_get_connection(ssl_conn); + + if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) { + return 0; + } + + switch (c->local_sockaddr->sa_family) { + +#if (NGX_HAVE_INET6) + case AF_INET6: + sin6 = (struct sockaddr_in6 *) c->local_sockaddr; + *addrlen = 16; + *addr = (char *) &sin6->sin6_addr.s6_addr; + *addrtype = NGX_HTTP_LUA_ADDR_TYPE_INET6; + + break; +#endif + +#if (NGX_HAVE_UNIX_DOMAIN) + case AF_UNIX: + saun = (struct sockaddr_un *) c->local_sockaddr; + + /* on Linux sockaddr might not include sun_path at all */ + if (c->local_socklen <= (socklen_t) + offsetof(struct sockaddr_un, sun_path)) + { + *addr = ""; + *addrlen = 0; + + } else { + *addr = saun->sun_path; + *addrlen = ngx_strlen(saun->sun_path); + } + + *addrtype = NGX_HTTP_LUA_ADDR_TYPE_UNIX; + break; +#endif + + default: /* AF_INET */ + sin = (struct sockaddr_in *) c->local_sockaddr; + *addr = (char *) &sin->sin_addr.s_addr; + *addrlen = 4; + *addrtype = NGX_HTTP_LUA_ADDR_TYPE_INET; + break; + } + + return NGX_OK; +} + + +int +ngx_http_lua_ffi_ssl_server_name(ngx_http_request_t *r, char **name, + size_t *namelen, char **err) +{ + ngx_ssl_conn_t *ssl_conn; + + if (r->connection == NULL || r->connection->ssl == NULL) { + *err = "bad request"; + return NGX_ERROR; + } + + ssl_conn = r->connection->ssl->connection; + if (ssl_conn == NULL) { + *err = "bad ssl conn"; + return NGX_ERROR; + } + +#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME + + *name = (char *) SSL_get_servername(ssl_conn, TLSEXT_NAMETYPE_host_name); + + if (*name) { + *namelen = ngx_strlen(*name); + return NGX_OK; + } + + return NGX_DECLINED; + +#else + + *err = "no TLS extension support"; + return NGX_ERROR; + +#endif +} + + +int +ngx_http_lua_ffi_cert_pem_to_der(const u_char *pem, size_t pem_len, u_char *der, + char **err) +{ + int total, len; + BIO *bio; + X509 *x509; + u_long n; + + bio = BIO_new_mem_buf((char *) pem, (int) pem_len); + if (bio == NULL) { + *err = "BIO_new_mem_buf() failed"; + return NGX_ERROR; + } + + x509 = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL); + if (x509 == NULL) { + *err = "PEM_read_bio_X509_AUX() failed"; + return NGX_ERROR; + } + + total = i2d_X509(x509, &der); + if (total < 0) { + X509_free(x509); + BIO_free(bio); + return NGX_ERROR; + } + + X509_free(x509); + + /* read rest of the chain */ + + for ( ;; ) { + + x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL); + if (x509 == NULL) { + n = ERR_peek_last_error(); + + if (ERR_GET_LIB(n) == ERR_LIB_PEM + && ERR_GET_REASON(n) == PEM_R_NO_START_LINE) + { + /* end of file */ + ERR_clear_error(); + break; + } + + /* some real error */ + + *err = "PEM_read_bio_X509() failed"; + BIO_free(bio); + return NGX_ERROR; + } + + len = i2d_X509(x509, &der); + if (len < 0) { + *err = "i2d_X509() failed"; + X509_free(x509); + BIO_free(bio); + return NGX_ERROR; + } + + total += len; + + X509_free(x509); + } + + BIO_free(bio); + + return total; +} + + +int +ngx_http_lua_ffi_priv_key_pem_to_der(const u_char *pem, size_t pem_len, + u_char *der, char **err) +{ + int len; + BIO *in; + RSA *rsa; + EVP_PKEY *pkey; + + in = BIO_new_mem_buf((char *) pem, (int) pem_len); + if (in == NULL) { + *err = "BIO_new_mem_buf() failed"; + return NGX_ERROR; + } + + pkey = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL); + if (pkey == NULL) { + BIO_free(in); + *err = "PEM_read_bio_PrivateKey failed"; + return NGX_ERROR; + } + + BIO_free(in); + + rsa = EVP_PKEY_get1_RSA(pkey); + if (rsa == NULL) { + EVP_PKEY_free(pkey); + *err = "EVP_PKEY_get1_RSA failed"; + return NGX_ERROR; + } + + EVP_PKEY_free(pkey); + + len = i2d_RSAPrivateKey(rsa, &der); + if (len < 0) { + RSA_free(rsa); + *err = "i2d_RSAPrivateKey failed"; + return NGX_ERROR; + } + + RSA_free(rsa); + + return len; +} + + +#endif /* NGX_LUA_NO_FFI_API */ + + +#endif /* NGX_HTTP_SSL */ diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_ssl_certby.h b/debian/modules/nginx-lua/src/ngx_http_lua_ssl_certby.h new file mode 100644 index 0000000..11cb963 --- /dev/null +++ b/debian/modules/nginx-lua/src/ngx_http_lua_ssl_certby.h @@ -0,0 +1,47 @@ + +/* + * Copyright (C) Yichun Zhang (agentzh) + */ + + +#ifndef _NGX_HTTP_LUA_SSL_CERTBY_H_INCLUDED_ +#define _NGX_HTTP_LUA_SSL_CERTBY_H_INCLUDED_ + + +#include "ngx_http_lua_common.h" + + +#if (NGX_HTTP_SSL) + + +typedef struct { + ngx_connection_t *connection; /* original true connection */ + ngx_http_request_t *request; /* fake request */ + int exit_code; /* exit code for openssl's + set_cert_cb callback */ + unsigned done; /* :1 */ + unsigned aborted; /* :1 */ +} ngx_http_lua_ssl_cert_ctx_t; + + +ngx_int_t ngx_http_lua_ssl_cert_handler_inline(ngx_http_request_t *r, + ngx_http_lua_srv_conf_t *lscf, lua_State *L); + +ngx_int_t ngx_http_lua_ssl_cert_handler_file(ngx_http_request_t *r, + ngx_http_lua_srv_conf_t *lscf, lua_State *L); + +char *ngx_http_lua_ssl_cert_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); + +char *ngx_http_lua_ssl_cert_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); + +int ngx_http_lua_ssl_cert_handler(ngx_ssl_conn_t *ssl_conn, void *data); + + +#endif /* NGX_HTTP_SSL */ + + +#endif /* _NGX_HTTP_LUA_SSL_CERTBY_H_INCLUDED_ */ + +/* vi:set ft=c ts=4 sw=4 et fdm=marker: */ diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_ssl_ocsp.c b/debian/modules/nginx-lua/src/ngx_http_lua_ssl_ocsp.c new file mode 100644 index 0000000..9f9e276 --- /dev/null +++ b/debian/modules/nginx-lua/src/ngx_http_lua_ssl_ocsp.c @@ -0,0 +1,497 @@ + +/* + * Copyright (C) Yichun Zhang (agentzh) + */ + + +#ifndef DDEBUG +#define DDEBUG 0 +#endif +#include "ddebug.h" + + +#if (NGX_HTTP_SSL) + + +#include "ngx_http_lua_common.h" + + +#ifndef NGX_LUA_NO_FFI_API + +#ifdef NGX_HTTP_LUA_USE_OCSP +static int ngx_http_lua_ssl_empty_status_callback(ngx_ssl_conn_t *ssl_conn, + void *data); +#endif + + +int +ngx_http_lua_ffi_ssl_get_ocsp_responder_from_der_chain( + const char *chain_data, size_t chain_len, unsigned char *out, + size_t *out_size, char **err) +{ +#ifndef NGX_HTTP_LUA_USE_OCSP + + *err = "no OCSP support"; + return NGX_ERROR; + +#else + + int rc = NGX_OK; + BIO *bio = NULL; + char *s; + X509 *cert = NULL, *issuer = NULL; + size_t len; + STACK_OF(OPENSSL_STRING) *aia = NULL; + + /* certificate */ + + bio = BIO_new_mem_buf((char *) chain_data, chain_len); + if (bio == NULL) { + *err = "BIO_new_mem_buf() failed"; + rc = NGX_ERROR; + goto done; + } + + cert = d2i_X509_bio(bio, NULL); + if (cert == NULL) { + *err = "d2i_X509_bio() failed"; + rc = NGX_ERROR; + goto done; + } + + /* responder */ + + aia = X509_get1_ocsp(cert); + if (aia == NULL) { + rc = NGX_DECLINED; + goto done; + } + +#if OPENSSL_VERSION_NUMBER >= 0x10000000L + s = sk_OPENSSL_STRING_value(aia, 0); +#else + s = sk_value(aia, 0); +#endif + if (s == NULL) { + rc = NGX_DECLINED; + goto done; + } + + len = ngx_strlen(s); + if (len > *out_size) { + len = *out_size; + rc = NGX_BUSY; + + } else { + rc = NGX_OK; + *out_size = len; + } + + ngx_memcpy(out, s, len); + + X509_email_free(aia); + aia = NULL; + + /* issuer */ + + if (BIO_eof(bio)) { + *err = "no issuer certificate in chain"; + rc = NGX_ERROR; + goto done; + } + + issuer = d2i_X509_bio(bio, NULL); + if (issuer == NULL) { + *err = "d2i_X509_bio() failed"; + rc = NGX_ERROR; + goto done; + } + + if (X509_check_issued(issuer, cert) != X509_V_OK) { + *err = "issuer certificate not next to leaf"; + rc = NGX_ERROR; + goto done; + } + + X509_free(issuer); + X509_free(cert); + BIO_free(bio); + + return rc; + +done: + + if (aia) { + X509_email_free(aia); + } + + if (issuer) { + X509_free(issuer); + } + + if (cert) { + X509_free(cert); + } + + if (bio) { + BIO_free(bio); + } + + return rc; + +#endif /* NGX_HTTP_LUA_USE_OCSP */ +} + + +int +ngx_http_lua_ffi_ssl_create_ocsp_request(const char *chain_data, + size_t chain_len, unsigned char *out, size_t *out_size, char **err) +{ +#ifndef NGX_HTTP_LUA_USE_OCSP + + *err = "no OCSP support"; + return NGX_ERROR; + +#else + + int rc = NGX_ERROR; + BIO *bio = NULL; + X509 *cert = NULL, *issuer = NULL; + size_t len; + OCSP_CERTID *id; + OCSP_REQUEST *ocsp = NULL; + + /* certificate */ + + bio = BIO_new_mem_buf((char *) chain_data, chain_len); + if (bio == NULL) { + *err = "BIO_new_mem_buf() failed"; + goto failed; + } + + cert = d2i_X509_bio(bio, NULL); + if (cert == NULL) { + *err = "d2i_X509_bio() failed"; + goto failed; + } + + if (BIO_eof(bio)) { + *err = "no issuer certificate in chain"; + goto failed; + } + + issuer = d2i_X509_bio(bio, NULL); + if (issuer == NULL) { + *err = "d2i_X509_bio() failed"; + goto failed; + } + + ocsp = OCSP_REQUEST_new(); + if (ocsp == NULL) { + *err = "OCSP_REQUEST_new() failed"; + goto failed; + } + + id = OCSP_cert_to_id(NULL, cert, issuer); + if (id == NULL) { + *err = "OCSP_cert_to_id() failed"; + goto failed; + } + + if (OCSP_request_add0_id(ocsp, id) == NULL) { + *err = "OCSP_request_add0_id() failed"; + goto failed; + } + + len = i2d_OCSP_REQUEST(ocsp, NULL); + if (len <= 0) { + *err = "i2d_OCSP_REQUEST() failed"; + goto failed; + } + + if (len > *out_size) { + *err = "output buffer too small"; + *out_size = len; + rc = NGX_BUSY; + goto failed; + } + + len = i2d_OCSP_REQUEST(ocsp, &out); + if (len <= 0) { + *err = "i2d_OCSP_REQUEST() failed"; + goto failed; + } + + *out_size = len; + + OCSP_REQUEST_free(ocsp); + X509_free(issuer); + X509_free(cert); + BIO_free(bio); + + return NGX_OK; + +failed: + + if (ocsp) { + OCSP_REQUEST_free(ocsp); + } + + if (issuer) { + X509_free(issuer); + } + + if (cert) { + X509_free(cert); + } + + if (bio) { + BIO_free(bio); + } + + return rc; + +#endif /* NGX_HTTP_LUA_USE_OCSP */ +} + + +int +ngx_http_lua_ffi_ssl_validate_ocsp_response(const u_char *resp, + size_t resp_len, const char *chain_data, size_t chain_len, + u_char *errbuf, size_t *errbuf_size) +{ +#ifndef NGX_HTTP_LUA_USE_OCSP + + *errbuf_size = ngx_snprintf(errbuf, *errbuf_size, + "no OCSP support") - errbuf; + return NGX_ERROR; + +#else + + int n; + BIO *bio = NULL; + X509 *cert = NULL, *issuer = NULL; + OCSP_CERTID *id = NULL; + OCSP_RESPONSE *ocsp = NULL; + OCSP_BASICRESP *basic = NULL; + STACK_OF(X509) *chain = NULL; + ASN1_GENERALIZEDTIME *thisupdate, *nextupdate; + + ocsp = d2i_OCSP_RESPONSE(NULL, &resp, resp_len); + if (ocsp == NULL) { + *errbuf_size = ngx_snprintf(errbuf, *errbuf_size, + "d2i_OCSP_RESPONSE() failed") - errbuf; + goto error; + } + + n = OCSP_response_status(ocsp); + + if (n != OCSP_RESPONSE_STATUS_SUCCESSFUL) { + *errbuf_size = ngx_snprintf(errbuf, *errbuf_size, + "OCSP response not successful (%d: %s)", + n, OCSP_response_status_str(n)) - errbuf; + goto error; + } + + basic = OCSP_response_get1_basic(ocsp); + if (basic == NULL) { + *errbuf_size = ngx_snprintf(errbuf, *errbuf_size, + "OCSP_response_get1_basic() failed") + - errbuf; + goto error; + } + + /* get issuer certificate from chain */ + + bio = BIO_new_mem_buf((char *) chain_data, chain_len); + if (bio == NULL) { + *errbuf_size = ngx_snprintf(errbuf, *errbuf_size, + "BIO_new_mem_buf() failed") + - errbuf; + goto error; + } + + cert = d2i_X509_bio(bio, NULL); + if (cert == NULL) { + *errbuf_size = ngx_snprintf(errbuf, *errbuf_size, + "d2i_X509_bio() failed") + - errbuf; + goto error; + } + + if (BIO_eof(bio)) { + *errbuf_size = ngx_snprintf(errbuf, *errbuf_size, + "no issuer certificate in chain") + - errbuf; + goto error; + } + + issuer = d2i_X509_bio(bio, NULL); + if (issuer == NULL) { + *errbuf_size = ngx_snprintf(errbuf, *errbuf_size, + "d2i_X509_bio() failed") - errbuf; + goto error; + } + + chain = sk_X509_new_null(); + if (chain == NULL) { + *errbuf_size = ngx_snprintf(errbuf, *errbuf_size, + "sk_X509_new_null() failed") - errbuf; + goto error; + } + + (void) sk_X509_push(chain, issuer); + + if (OCSP_basic_verify(basic, chain, NULL, OCSP_NOVERIFY) != 1) { + *errbuf_size = ngx_snprintf(errbuf, *errbuf_size, + "OCSP_basic_verify() failed") - errbuf; + goto error; + } + + id = OCSP_cert_to_id(NULL, cert, issuer); + if (id == NULL) { + *errbuf_size = ngx_snprintf(errbuf, *errbuf_size, + "OCSP_cert_to_id() failed") - errbuf; + goto error; + } + + if (OCSP_resp_find_status(basic, id, &n, NULL, NULL, + &thisupdate, &nextupdate) + != 1) + { + *errbuf_size = ngx_snprintf(errbuf, *errbuf_size, + "certificate status not found in the " + "OCSP response") - errbuf; + goto error; + } + + if (n != V_OCSP_CERTSTATUS_GOOD) { + *errbuf_size = ngx_snprintf(errbuf, *errbuf_size, + "certificate status \"%s\" in the OCSP " + "response", OCSP_cert_status_str(n)) + - errbuf; + goto error; + } + + if (OCSP_check_validity(thisupdate, nextupdate, 300, -1) != 1) { + *errbuf_size = ngx_snprintf(errbuf, *errbuf_size, + "OCSP_check_validity() failed") - errbuf; + goto error; + } + + sk_X509_free(chain); + X509_free(cert); + X509_free(issuer); + BIO_free(bio); + OCSP_CERTID_free(id); + OCSP_BASICRESP_free(basic); + OCSP_RESPONSE_free(ocsp); + + return NGX_OK; + +error: + + if (chain) { + sk_X509_free(chain); + } + + if (id) { + OCSP_CERTID_free(id); + } + + if (basic) { + OCSP_BASICRESP_free(basic); + } + + if (ocsp) { + OCSP_RESPONSE_free(ocsp); + } + + if (cert) { + X509_free(cert); + } + + if (issuer) { + X509_free(issuer); + } + + if (bio) { + BIO_free(bio); + } + + ERR_clear_error(); + + return NGX_ERROR; + +#endif /* NGX_HTTP_LUA_USE_OCSP */ +} + + +#ifdef NGX_HTTP_LUA_USE_OCSP +static int +ngx_http_lua_ssl_empty_status_callback(ngx_ssl_conn_t *ssl_conn, void *data) +{ + return SSL_TLSEXT_ERR_OK; +} +#endif + + +int +ngx_http_lua_ffi_ssl_set_ocsp_status_resp(ngx_http_request_t *r, + const u_char *resp, size_t resp_len, char **err) +{ +#ifndef NGX_HTTP_LUA_USE_OCSP + + *err = "no OCSP support"; + return NGX_ERROR; + +#else + + u_char *p; + SSL_CTX *ctx; + ngx_ssl_conn_t *ssl_conn; + + if (r->connection == NULL || r->connection->ssl == NULL) { + *err = "bad request"; + return NGX_ERROR; + } + + ssl_conn = r->connection->ssl->connection; + if (ssl_conn == NULL) { + *err = "bad ssl conn"; + return NGX_ERROR; + } + + if (ssl_conn->tlsext_status_type == -1) { + dd("no ocsp status req from client"); + return NGX_DECLINED; + } + + /* we have to register an empty status callback here otherwise + * OpenSSL won't send the response staple. */ + + ctx = SSL_get_SSL_CTX(ssl_conn); + SSL_CTX_set_tlsext_status_cb(ctx, + ngx_http_lua_ssl_empty_status_callback); + + p = OPENSSL_malloc(resp_len); + if (p == NULL) { + *err = "OPENSSL_malloc() failed"; + return NGX_ERROR; + } + + ngx_memcpy(p, resp, resp_len); + + dd("set ocsp resp: resp_len=%d", (int) resp_len); + (void) SSL_set_tlsext_status_ocsp_resp(ssl_conn, p, resp_len); + ssl_conn->tlsext_status_expected = 1; + + return NGX_OK; + +#endif /* NGX_HTTP_LUA_USE_OCSP */ +} + +#endif /* NGX_LUA_NO_FFI_API */ + + +#endif /* NGX_HTTP_SSL */ diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_string.c b/debian/modules/nginx-lua/src/ngx_http_lua_string.c index 750d95e..241b969 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_string.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_string.c @@ -548,7 +548,7 @@ ngx_http_lua_ngx_crc32_short(lua_State *L) if (lua_gettop(L) != 1) { return luaL_error(L, "expecting one argument, but got %d", - lua_gettop(L)); + lua_gettop(L)); } p = (u_char *) luaL_checklstring(L, 1, &len); diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_subrequest.c b/debian/modules/nginx-lua/src/ngx_http_lua_subrequest.c index 4ac801b..4f8a753 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_subrequest.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_subrequest.c @@ -143,6 +143,7 @@ ngx_http_lua_ngx_location_capture_multi(lua_State *L) size_t sr_headers_len; size_t sr_bodies_len; size_t sr_flags_len; + size_t ofs1, ofs2; unsigned custom_ctx; ngx_http_lua_co_ctx_t *coctx; @@ -527,23 +528,31 @@ ngx_http_lua_ngx_location_capture_multi(lua_State *L) args.len = len; } - p = ngx_pnalloc(r->pool, sizeof(ngx_http_post_subrequest_t) - + sizeof(ngx_http_lua_ctx_t) - + sizeof(ngx_http_lua_post_subrequest_data_t)); + ofs1 = ngx_align(sizeof(ngx_http_post_subrequest_t), sizeof(void *)); + ofs2 = ngx_align(sizeof(ngx_http_lua_ctx_t), sizeof(void *)); + + p = ngx_palloc(r->pool, ofs1 + ofs2 + + sizeof(ngx_http_lua_post_subrequest_data_t)); if (p == NULL) { return luaL_error(L, "no memory"); } psr = (ngx_http_post_subrequest_t *) p; - p += sizeof(ngx_http_post_subrequest_t); + p += ofs1; sr_ctx = (ngx_http_lua_ctx_t *) p; - p += sizeof(ngx_http_lua_ctx_t); + ngx_http_lua_assert((void *) sr_ctx == ngx_align_ptr(sr_ctx, + sizeof(void *))); + + p += ofs2; psr_data = (ngx_http_lua_post_subrequest_data_t *) p; + ngx_http_lua_assert((void *) psr_data == ngx_align_ptr(psr_data, + sizeof(void *))); + ngx_memzero(sr_ctx, sizeof(ngx_http_lua_ctx_t)); /* set by ngx_memzero: @@ -766,7 +775,7 @@ ngx_http_lua_adjust_subrequest(ngx_http_request_t *sr, ngx_uint_t method, static ngx_int_t ngx_http_lua_subrequest_add_extra_vars(ngx_http_request_t *sr, - ngx_array_t *extra_vars) + ngx_array_t *extra_vars) { ngx_http_core_main_conf_t *cmcf; ngx_http_variable_t *v; @@ -1155,11 +1164,11 @@ ngx_http_lua_set_content_length_header(ngx_http_request_t *r, off_t len) #if 0 dd("content length hash: %lu == %lu", (unsigned long) h->hash, ngx_hash_key_lc((u_char *) "Content-Length", - sizeof("Content-Length") - 1)); + sizeof("Content-Length") - 1)); #endif dd("r content length: %.*s", - (int)r->headers_in.content_length->value.len, + (int) r->headers_in.content_length->value.len, r->headers_in.content_length->value.data); pr = r->parent; @@ -1293,7 +1302,7 @@ ngx_http_lua_handle_subreq_responses(ngx_http_request_t *r, } dd("checking sr header %.*s", (int) header[i].key.len, - header[i].key.data); + header[i].key.data); #if 1 if (header[i].hash == 0) { @@ -1304,7 +1313,7 @@ ngx_http_lua_handle_subreq_responses(ngx_http_request_t *r, header[i].hash = 0; dd("pushing sr header %.*s", (int) header[i].key.len, - header[i].key.data); + header[i].key.data); lua_pushlstring(co, (char *) header[i].key.data, header[i].key.len); /* header key */ @@ -1434,6 +1443,20 @@ ngx_http_lua_subrequest(ngx_http_request_t *r, ngx_http_request_t *sr; ngx_http_core_srv_conf_t *cscf; +#if nginx_version >= 1009005 + + if (r->subrequests == 0) { +#if defined(NGX_DTRACE) && NGX_DTRACE + ngx_http_probe_subrequest_cycle(r, uri, args); +#endif + + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "lua subrequests cycle while processing \"%V\"", uri); + return NGX_ERROR; + } + +#else /* nginx_version <= 1009004 */ + r->main->subrequests--; if (r->main->subrequests == 0) { @@ -1442,11 +1465,13 @@ ngx_http_lua_subrequest(ngx_http_request_t *r, #endif ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "subrequests cycle while processing \"%V\"", uri); + "lua subrequests cycle while processing \"%V\"", uri); r->main->subrequests = 1; return NGX_ERROR; } +#endif + sr = ngx_pcalloc(r->pool, sizeof(ngx_http_request_t)); if (sr == NULL) { return NGX_ERROR; @@ -1508,7 +1533,7 @@ ngx_http_lua_subrequest(ngx_http_request_t *r, } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, - "http subrequest \"%V?%V\"", uri, &sr->args); + "lua http subrequest \"%V?%V\"", uri, &sr->args); sr->subrequest_in_memory = (flags & NGX_HTTP_SUBREQUEST_IN_MEMORY) != 0; sr->waited = (flags & NGX_HTTP_SUBREQUEST_WAITED) != 0; @@ -1537,6 +1562,10 @@ ngx_http_lua_subrequest(ngx_http_request_t *r, sr->uri_changes = NGX_HTTP_MAX_URI_CHANGES + 1; +#if nginx_version >= 1009005 + sr->subrequests = r->subrequests - 1; +#endif + tp = ngx_timeofday(); sr->start_sec = tp->sec; sr->start_msec = tp->msec; diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_timer.c b/debian/modules/nginx-lua/src/ngx_http_lua_timer.c index 49230f4..393eac7 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_timer.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_timer.c @@ -40,6 +40,8 @@ typedef struct { static int ngx_http_lua_ngx_timer_at(lua_State *L); +static int ngx_http_lua_ngx_timer_running_count(lua_State *L); +static int ngx_http_lua_ngx_timer_pending_count(lua_State *L); static void ngx_http_lua_timer_handler(ngx_event_t *ev); static u_char *ngx_http_lua_log_timer_error(ngx_log_t *log, u_char *buf, size_t len); @@ -49,15 +51,59 @@ static void ngx_http_lua_abort_pending_timers(ngx_event_t *ev); void ngx_http_lua_inject_timer_api(lua_State *L) { - lua_createtable(L, 0 /* narr */, 1 /* nrec */); /* ngx.timer. */ + lua_createtable(L, 0 /* narr */, 3 /* nrec */); /* ngx.timer. */ lua_pushcfunction(L, ngx_http_lua_ngx_timer_at); lua_setfield(L, -2, "at"); + lua_pushcfunction(L, ngx_http_lua_ngx_timer_running_count); + lua_setfield(L, -2, "running_count"); + + lua_pushcfunction(L, ngx_http_lua_ngx_timer_pending_count); + lua_setfield(L, -2, "pending_count"); + lua_setfield(L, -2, "timer"); } +static int +ngx_http_lua_ngx_timer_running_count(lua_State *L) +{ + ngx_http_request_t *r; + ngx_http_lua_main_conf_t *lmcf; + + r = ngx_http_lua_get_req(L); + if (r == NULL) { + return luaL_error(L, "no request"); + } + + lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); + + lua_pushnumber(L, lmcf->running_timers); + + return 1; +} + + +static int +ngx_http_lua_ngx_timer_pending_count(lua_State *L) +{ + ngx_http_request_t *r; + ngx_http_lua_main_conf_t *lmcf; + + r = ngx_http_lua_get_req(L); + if (r == NULL) { + return luaL_error(L, "no request"); + } + + lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); + + lua_pushnumber(L, lmcf->pending_timers); + + return 1; +} + + static int ngx_http_lua_ngx_timer_at(lua_State *L) { @@ -89,7 +135,7 @@ ngx_http_lua_ngx_timer_at(lua_State *L) delay = (ngx_msec_t) (luaL_checknumber(L, 1) * 1000); luaL_argcheck(L, lua_isfunction(L, 2) && !lua_iscfunction(L, 2), 2, - "Lua function expected"); + "Lua function expected"); r = ngx_http_lua_get_req(L); if (r == NULL) { diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_uthread.c b/debian/modules/nginx-lua/src/ngx_http_lua_uthread.c index de7a72c..8195ec0 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_uthread.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_uthread.c @@ -126,7 +126,8 @@ ngx_http_lua_uthread_wait(lua_State *L) ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE | NGX_HTTP_LUA_CONTEXT_ACCESS | NGX_HTTP_LUA_CONTEXT_CONTENT - | NGX_HTTP_LUA_CONTEXT_TIMER); + | NGX_HTTP_LUA_CONTEXT_TIMER + | NGX_HTTP_LUA_CONTEXT_SSL_CERT); coctx = ctx->cur_co_ctx; @@ -223,7 +224,8 @@ ngx_http_lua_uthread_kill(lua_State *L) ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE | NGX_HTTP_LUA_CONTEXT_ACCESS | NGX_HTTP_LUA_CONTEXT_CONTENT - | NGX_HTTP_LUA_CONTEXT_TIMER); + | NGX_HTTP_LUA_CONTEXT_TIMER + | NGX_HTTP_LUA_CONTEXT_SSL_CERT); coctx = ctx->cur_co_ctx; diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_util.c b/debian/modules/nginx-lua/src/ngx_http_lua_util.c index 65916be..afb7655 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_util.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_util.c @@ -49,6 +49,7 @@ #include "ngx_http_lua_config.h" #include "ngx_http_lua_worker.h" #include "ngx_http_lua_socket_tcp.h" +#include "ngx_http_lua_ssl_certby.h" #if 1 @@ -111,7 +112,6 @@ static void ngx_http_lua_cleanup_zombie_child_uthreads(ngx_http_request_t *r, lua_State *L, ngx_http_lua_ctx_t *ctx, ngx_http_lua_co_ctx_t *coctx); static ngx_int_t ngx_http_lua_on_abort_resume(ngx_http_request_t *r); static void ngx_http_lua_close_fake_request(ngx_http_request_t *r); -static void ngx_http_lua_free_fake_request(ngx_http_request_t *r); static ngx_int_t ngx_http_lua_flush_pending_output(ngx_http_request_t *r, ngx_http_lua_ctx_t *ctx); static ngx_int_t @@ -139,7 +139,7 @@ ngx_http_lua_set_path(ngx_cycle_t *cycle, lua_State *L, int tab_idx, /* XXX here we use some hack to simplify string manipulation */ tmp_path = luaL_gsub(L, path, LUA_PATH_SEP LUA_PATH_SEP, - LUA_PATH_SEP AUX_MARK LUA_PATH_SEP); + LUA_PATH_SEP AUX_MARK LUA_PATH_SEP); lua_pushlstring(L, (char *) cycle->prefix.data, cycle->prefix.len); prefix = lua_tostring(L, -1); @@ -719,7 +719,7 @@ static void ngx_http_lua_inject_ngx_api(lua_State *L, ngx_http_lua_main_conf_t *lmcf, ngx_log_t *log) { - lua_createtable(L, 0 /* narr */, 99 /* nrec */); /* ngx.* */ + lua_createtable(L, 0 /* narr */, 116 /* nrec */); /* ngx.* */ lua_pushcfunction(L, ngx_http_lua_get_raw_phase_context); lua_setfield(L, -2, "_phase_ctx"); @@ -926,7 +926,7 @@ ngx_http_lua_request_cleanup(ngx_http_lua_ctx_t *ctx, int forcible) lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); #if 1 - if (r->connection->fd == -1) { + if (r->connection->fd == (ngx_socket_t) -1) { /* being a fake request */ lmcf->running_timers--; } @@ -1480,7 +1480,9 @@ no_parent: done: - if (ctx->entered_content_phase && r->connection->fd != -1) { + if (ctx->entered_content_phase + && r->connection->fd != (ngx_socket_t) -1) + { rc = ngx_http_lua_send_chain_link(r, ctx, NULL /* last_buf */); @@ -2090,7 +2092,7 @@ ngx_http_lua_inject_req_api(ngx_log_t *log, lua_State *L) { /* ngx.req table */ - lua_createtable(L, 0 /* narr */, 23 /* nrec */); /* .req */ + lua_createtable(L, 0 /* narr */, 24 /* nrec */); /* .req */ ngx_http_lua_inject_req_header_api(L); ngx_http_lua_inject_req_uri_api(log, L); @@ -2099,6 +2101,7 @@ ngx_http_lua_inject_req_api(ngx_log_t *log, lua_State *L) ngx_http_lua_inject_req_socket_api(L); ngx_http_lua_inject_req_method_api(L); ngx_http_lua_inject_req_time_api(L); + ngx_http_lua_inject_req_misc_api(L); lua_setfield(L, -2, "req"); } @@ -2169,7 +2172,7 @@ ngx_http_lua_handle_exec(lua_State *L, ngx_http_request_t *r, } dd("internal redirect to %.*s", (int) ctx->exec_uri.len, - ctx->exec_uri.data); + ctx->exec_uri.data); r->write_event_handler = ngx_http_request_empty_handler; @@ -2182,7 +2185,7 @@ ngx_http_lua_handle_exec(lua_State *L, ngx_http_request_t *r, rc = ngx_http_internal_redirect(r, &ctx->exec_uri, &ctx->exec_args); dd("internal redirect returned %d when in content phase? " - "%d", (int) rc, ctx->entered_content_phase); + "%d", (int) rc, ctx->entered_content_phase); if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) { return rc; @@ -2212,16 +2215,6 @@ ngx_http_lua_handle_exit(lua_State *L, ngx_http_request_t *r, "lua thread aborting request with status %d", ctx->exit_code); -#if 1 - if (!r->header_sent - && !ctx->header_sent - && r->headers_out.status == 0 - && ctx->exit_code >= NGX_HTTP_OK) - { - r->headers_out.status = ctx->exit_code; - } -#endif - ngx_http_lua_cleanup_pending_operation(ctx->cur_co_ctx); ngx_http_lua_probe_coroutine_done(r, ctx->cur_co_ctx->co, 1); @@ -2234,6 +2227,20 @@ ngx_http_lua_handle_exit(lua_State *L, ngx_http_request_t *r, ngx_http_lua_request_cleanup(ctx, 0); + if (r->connection->fd == (ngx_socket_t) -1) { /* fake request */ + return ctx->exit_code; + } + +#if 1 + if (!r->header_sent + && !ctx->header_sent + && r->headers_out.status == 0 + && ctx->exit_code >= NGX_HTTP_OK) + { + r->headers_out.status = ctx->exit_code; + } +#endif + if (ctx->buffering && r->headers_out.status && ctx->exit_code != NGX_ERROR @@ -2326,7 +2333,7 @@ ngx_http_lua_process_args_option(ngx_http_request_t *r, lua_State *L, value = (u_char *) lua_tolstring(L, -1, &value_len); total_escape += 2 * ngx_http_lua_escape_uri(NULL, value, value_len, - NGX_ESCAPE_URI); + NGX_ESCAPE_URI); len += key_len + value_len + (sizeof("=") - 1); n++; @@ -2548,7 +2555,7 @@ ngx_http_lua_process_args_option(ngx_http_request_t *r, lua_State *L, if (p - args->data != (ssize_t) len) { luaL_error(L, "buffer error: %d != %d", - (int) (p - args->data), (int) len); + (int) (p - args->data), (int) len); return; } } @@ -3523,7 +3530,7 @@ ngx_http_lua_finalize_request(ngx_http_request_t *r, ngx_int_t rc) ngx_http_lua_cleanup_pending_operation(ctx->cur_co_ctx); } - if (r->connection->fd != -1) { + if (r->connection->fd != (ngx_socket_t) -1) { ngx_http_finalize_request(r, rc); return; } @@ -3536,6 +3543,11 @@ void ngx_http_lua_finalize_fake_request(ngx_http_request_t *r, ngx_int_t rc) { ngx_connection_t *c; +#if (NGX_HTTP_SSL) + ngx_ssl_conn_t *ssl_conn; + + ngx_http_lua_ssl_cert_ctx_t *cctx; +#endif c = r->connection; @@ -3549,6 +3561,25 @@ ngx_http_lua_finalize_fake_request(ngx_http_request_t *r, ngx_int_t rc) } if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) { + +#if (NGX_HTTP_SSL) + + if (r->connection->ssl) { + ssl_conn = r->connection->ssl->connection; + if (ssl_conn) { + c = ngx_ssl_get_connection(ssl_conn); + + if (c && c->ssl) { + cctx = ngx_http_lua_ssl_get_ctx(c->ssl->connection); + if (cctx != NULL) { + cctx->exit_code = 0; + } + } + } + } + +#endif + ngx_http_lua_close_fake_request(r); return; } @@ -3593,7 +3624,7 @@ ngx_http_lua_close_fake_request(ngx_http_request_t *r) } -static void +void ngx_http_lua_free_fake_request(ngx_http_request_t *r) { ngx_log_t *log; @@ -3610,10 +3641,15 @@ ngx_http_lua_free_fake_request(ngx_http_request_t *r) return; } - for (cln = r->cleanup; cln; cln = cln->next) { + cln = r->cleanup; + r->cleanup = NULL; + + while (cln) { if (cln->handler) { cln->handler(cln->data); } + + cln = cln->next; } r->request_line.len = 0; @@ -3628,8 +3664,8 @@ ngx_http_lua_close_fake_connection(ngx_connection_t *c) ngx_pool_t *pool; ngx_connection_t *saved_c = NULL; - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, - "http lua close fake http connection"); + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http lua close fake http connection %p", c); c->destroyed = 1; @@ -3819,6 +3855,8 @@ ngx_http_lua_create_fake_connection(ngx_pool_t *pool) c->error = 1; + dd("created fake connection: %p", c); + return c; failed: @@ -3878,7 +3916,7 @@ ngx_http_lua_create_fake_request(ngx_connection_t *c) cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); r->variables = ngx_pcalloc(r->pool, cmcf->variables.nelts - * sizeof(ngx_http_variable_value_t)); + * sizeof(ngx_http_variable_value_t)); if (r->variables == NULL) { goto failed; } @@ -3905,6 +3943,8 @@ ngx_http_lua_create_fake_request(ngx_connection_t *c) r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE; r->discard_body = 1; + dd("created fake request %p", r); + return r; } @@ -3980,4 +4020,78 @@ ngx_http_lua_get_raw_phase_context(lua_State *L) return 1; } + +ngx_http_cleanup_t * +ngx_http_lua_cleanup_add(ngx_http_request_t *r, size_t size) +{ + ngx_http_cleanup_t *cln; + ngx_http_lua_ctx_t *ctx; + + if (size == 0) { + ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); + + r = r->main; + + if (ctx != NULL && ctx->free_cleanup) { + cln = ctx->free_cleanup; + ctx->free_cleanup = cln->next; + + dd("reuse cleanup: %p", cln); + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "lua http cleanup reuse: %p", cln); + + cln->handler = NULL; + cln->next = r->cleanup; + + r->cleanup = cln; + + return cln; + } + } + + return ngx_http_cleanup_add(r, size); +} + + +void +ngx_http_lua_cleanup_free(ngx_http_request_t *r, ngx_http_cleanup_pt *cleanup) +{ + ngx_http_cleanup_t **last; + ngx_http_cleanup_t *cln; + ngx_http_lua_ctx_t *ctx; + + ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); + if (ctx == NULL) { + return; + } + + r = r->main; + + cln = (ngx_http_cleanup_t *) + ((u_char *) cleanup - offsetof(ngx_http_cleanup_t, handler)); + + dd("cln: %p, cln->handler: %p, &cln->handler: %p", + cln, cln->handler, &cln->handler); + + last = &r->cleanup; + + while (*last) { + if (*last == cln) { + *last = cln->next; + + cln->next = ctx->free_cleanup; + ctx->free_cleanup = cln; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "lua http cleanup free: %p", cln); + + return; + } + + last = &(*last)->next; + } +} + + /* vi:set ft=c ts=4 sw=4 et fdm=marker: */ diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_util.h b/debian/modules/nginx-lua/src/ngx_http_lua_util.h index 42ba07e..f0e8923 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_util.h +++ b/debian/modules/nginx-lua/src/ngx_http_lua_util.h @@ -82,8 +82,11 @@ extern char ngx_http_lua_headers_metatable_key; : (c) == NGX_HTTP_LUA_CONTEXT_CONTENT ? "content_by_lua*" \ : (c) == NGX_HTTP_LUA_CONTEXT_LOG ? "log_by_lua*" \ : (c) == NGX_HTTP_LUA_CONTEXT_HEADER_FILTER ? "header_filter_by_lua*" \ + : (c) == NGX_HTTP_LUA_CONTEXT_BODY_FILTER ? "body_filter_by_lua*" \ : (c) == NGX_HTTP_LUA_CONTEXT_TIMER ? "ngx.timer" \ : (c) == NGX_HTTP_LUA_CONTEXT_INIT_WORKER ? "init_worker_by_lua*" \ + : (c) == NGX_HTTP_LUA_CONTEXT_BALANCER ? "balancer_by_lua*" \ + : (c) == NGX_HTTP_LUA_CONTEXT_SSL_CERT ? "ssl_certificate_by_lua*" \ : "(unknown)") @@ -114,18 +117,22 @@ ngx_http_lua_ffi_check_context(ngx_http_lua_ctx_t *ctx, unsigned flags, #define ngx_http_lua_check_fake_request(L, r) \ - if ((r)->connection->fd == -1) { \ + if ((r)->connection->fd == (ngx_socket_t) -1) { \ return luaL_error(L, "API disabled in the current context"); \ } #define ngx_http_lua_check_fake_request2(L, r, ctx) \ - if ((r)->connection->fd == -1) { \ + if ((r)->connection->fd == (ngx_socket_t) -1) { \ return luaL_error(L, "API disabled in the context of %s", \ ngx_http_lua_context_name((ctx)->context)); \ } +#define ngx_http_lua_ssl_get_ctx(ssl_conn) \ + SSL_get_ex_data(ssl_conn, ngx_http_lua_ssl_ctx_index) + + lua_State *ngx_http_lua_init_vm(lua_State *parent_vm, ngx_cycle_t *cycle, ngx_pool_t *pool, ngx_http_lua_main_conf_t *lmcf, ngx_log_t *log, ngx_pool_cleanup_t **pcln); @@ -216,6 +223,8 @@ void ngx_http_lua_finalize_fake_request(ngx_http_request_t *r, void ngx_http_lua_close_fake_connection(ngx_connection_t *c); +void ngx_http_lua_free_fake_request(ngx_http_request_t *r); + void ngx_http_lua_release_ngx_ctx_table(ngx_log_t *log, lua_State *L, ngx_http_lua_ctx_t *ctx); @@ -230,6 +239,12 @@ ngx_int_t ngx_http_lua_report(ngx_log_t *log, lua_State *L, int status, int ngx_http_lua_do_call(ngx_log_t *log, lua_State *L); +ngx_http_cleanup_t *ngx_http_lua_cleanup_add(ngx_http_request_t *r, + size_t size); + +void ngx_http_lua_cleanup_free(ngx_http_request_t *r, + ngx_http_cleanup_pt *cleanup); + #define ngx_http_lua_check_if_abortable(L, ctx) \ if ((ctx)->no_abort) { \ @@ -266,7 +281,7 @@ ngx_http_lua_create_ctx(ngx_http_request_t *r) ngx_http_set_ctx(r, ctx, ngx_http_lua_module); llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module); - if (!llcf->enable_code_cache && r->connection->fd != -1) { + if (!llcf->enable_code_cache && r->connection->fd != (ngx_socket_t) -1) { lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); dd("lmcf: %p", lmcf); @@ -418,6 +433,7 @@ ngx_http_lua_get_flush_chain(ngx_http_request_t *r, ngx_http_lua_ctx_t *ctx) extern ngx_uint_t ngx_http_lua_location_hash; extern ngx_uint_t ngx_http_lua_content_length_hash; +extern int ngx_http_lua_ssl_ctx_index; #endif /* _NGX_HTTP_LUA_UTIL_H_INCLUDED_ */ diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_variable.c b/debian/modules/nginx-lua/src/ngx_http_lua_variable.c index 67ba86d..0de9312 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_variable.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_variable.c @@ -307,7 +307,7 @@ ngx_http_lua_ffi_var_get(ngx_http_request_t *r, u_char *name_data, return NGX_ERROR; } - if ((r)->connection->fd == -1) { + if ((r)->connection->fd == (ngx_socket_t) -1) { *err = "API disabled in the current context"; return NGX_ERROR; } @@ -377,7 +377,7 @@ ngx_http_lua_ffi_var_set(ngx_http_request_t *r, u_char *name_data, return NGX_ERROR; } - if ((r)->connection->fd == -1) { + if ((r)->connection->fd == (ngx_socket_t) -1) { ngx_snprintf(errbuf, errlen, "API disabled in the current context"); return NGX_ERROR; } @@ -405,8 +405,8 @@ ngx_http_lua_ffi_var_set(ngx_http_request_t *r, u_char *name_data, dd("set variables with set_handler"); if (value != NULL && value_len) { - vv = ngx_pnalloc(r->pool, sizeof(ngx_http_variable_value_t) - + value_len); + vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t) + + value_len); if (vv == NULL) { goto nomem; } diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_worker.c b/debian/modules/nginx-lua/src/ngx_http_lua_worker.c index f9c4a44..44faf48 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_worker.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_worker.c @@ -15,12 +15,14 @@ static int ngx_http_lua_ngx_worker_exiting(lua_State *L); static int ngx_http_lua_ngx_worker_pid(lua_State *L); +static int ngx_http_lua_ngx_worker_id(lua_State *L); +static int ngx_http_lua_ngx_worker_count(lua_State *L); void ngx_http_lua_inject_worker_api(lua_State *L) { - lua_createtable(L, 0 /* narr */, 2 /* nrec */); /* ngx.worker. */ + lua_createtable(L, 0 /* narr */, 4 /* nrec */); /* ngx.worker. */ lua_pushcfunction(L, ngx_http_lua_ngx_worker_exiting); lua_setfield(L, -2, "exiting"); @@ -28,6 +30,12 @@ ngx_http_lua_inject_worker_api(lua_State *L) lua_pushcfunction(L, ngx_http_lua_ngx_worker_pid); lua_setfield(L, -2, "pid"); + lua_pushcfunction(L, ngx_http_lua_ngx_worker_id); + lua_setfield(L, -2, "id"); + + lua_pushcfunction(L, ngx_http_lua_ngx_worker_count); + lua_setfield(L, -2, "count"); + lua_setfield(L, -2, "worker"); } @@ -48,6 +56,31 @@ ngx_http_lua_ngx_worker_pid(lua_State *L) } +static int +ngx_http_lua_ngx_worker_id(lua_State *L) +{ +#if (nginx_version >= 1009001) + lua_pushinteger(L, (lua_Integer) ngx_worker); +#else + lua_pushnil(L); +#endif + return 1; +} + + +static int +ngx_http_lua_ngx_worker_count(lua_State *L) +{ + ngx_core_conf_t *ccf; + + ccf = (ngx_core_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, + ngx_core_module); + + lua_pushinteger(L, (lua_Integer) ccf->worker_processes); + return 1; +} + + #ifndef NGX_LUA_NO_FFI_API int ngx_http_lua_ffi_worker_pid(void) @@ -56,9 +89,32 @@ ngx_http_lua_ffi_worker_pid(void) } +int +ngx_http_lua_ffi_worker_id(void) +{ +#if (nginx_version >= 1009001) + return (int) ngx_worker; +#else + return -1; +#endif +} + + int ngx_http_lua_ffi_worker_exiting(void) { return (int) ngx_exiting; } + + +int +ngx_http_lua_ffi_worker_count(void) +{ + ngx_core_conf_t *ccf; + + ccf = (ngx_core_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, + ngx_core_module); + + return (int) ccf->worker_processes; +} #endif diff --git a/debian/modules/nginx-lua/t/020-subrequest.t b/debian/modules/nginx-lua/t/020-subrequest.t index 21e728d..88ac1b4 100644 --- a/debian/modules/nginx-lua/t/020-subrequest.t +++ b/debian/modules/nginx-lua/t/020-subrequest.t @@ -11,7 +11,7 @@ use Test::Nginx::Socket::Lua; no_root_location; repeat_each(2); -plan tests => repeat_each() * (blocks() * 3 + 22); +plan tests => repeat_each() * (blocks() * 3 + 23); $ENV{TEST_NGINX_MEMCACHED_PORT} ||= 11211; @@ -42,6 +42,8 @@ __DATA__ GET /lua --- response_body DELETE +--- error_log +lua http subrequest "/other?" --- no_error_log [error] @@ -1059,7 +1061,7 @@ hello, world GET /t --- ignore_response --- error_log -subrequests cycle while processing "/t" +lua subrequests cycle while processing "/t" diff --git a/debian/modules/nginx-lua/t/022-redirect.t b/debian/modules/nginx-lua/t/022-redirect.t index 0e2a107..57c7add 100644 --- a/debian/modules/nginx-lua/t/022-redirect.t +++ b/debian/modules/nginx-lua/t/022-redirect.t @@ -9,7 +9,7 @@ use Test::Nginx::Socket::Lua; repeat_each(2); #repeat_each(1); -plan tests => repeat_each() * (blocks() * 3 + 1); +plan tests => repeat_each() * (blocks() * 3 + 2); #no_diff(); #no_long_string(); @@ -83,6 +83,8 @@ GET /read !Location --- response_body_like: 500 Internal Server Error --- error_code: 500 +--- error_log +only ngx.HTTP_MOVED_TEMPORARILY, ngx.HTTP_MOVED_PERMANENTLY, and ngx.HTTP_TEMPORARY_REDIRECT are allowed @@ -166,3 +168,53 @@ Location: http://agentzh.org/foo?bar=3 --- response_body eval [qr/302 Found/, qr/302 Found/] + + +=== TEST 9: explicit 307 +--- config + location /read { + content_by_lua ' + ngx.redirect("http://agentzh.org/foo", ngx.HTTP_TEMPORARY_REDIRECT); + ngx.say("hi") + '; + } +--- request +GET /read +--- response_headers +Location: http://agentzh.org/foo +--- response_body_like: 307 Temporary Redirect +--- error_code: 307 + + + +=== TEST 10: explicit 307 with args +--- config + location /read { + content_by_lua ' + ngx.redirect("http://agentzh.org/foo?a=b&c=d", ngx.HTTP_TEMPORARY_REDIRECT); + ngx.say("hi") + '; + } +--- request +GET /read +--- response_headers +Location: http://agentzh.org/foo?a=b&c=d +--- response_body_like: 307 Temporary Redirect +--- error_code: 307 + + + +=== TEST 11: explicit 307 +--- config + location /read { + content_by_lua ' + ngx.redirect("http://agentzh.org/foo?a=b&c=d", 307); + ngx.say("hi") + '; + } +--- request +GET /read +--- response_headers +Location: http://agentzh.org/foo?a=b&c=d +--- response_body_like: 307 Temporary Redirect +--- error_code: 307 diff --git a/debian/modules/nginx-lua/t/028-req-header.t b/debian/modules/nginx-lua/t/028-req-header.t index 77c0b06..fd13cba 100644 --- a/debian/modules/nginx-lua/t/028-req-header.t +++ b/debian/modules/nginx-lua/t/028-req-header.t @@ -8,7 +8,7 @@ use Test::Nginx::Socket::Lua; repeat_each(2); -plan tests => repeat_each() * (2 * blocks() + 26); +plan tests => repeat_each() * (2 * blocks() + 28); #no_diff(); #no_long_string(); @@ -1532,3 +1532,53 @@ MOVE /a.txt client sent no "Destination" header [error] --- error_code: 204 + + + +=== TEST 50: X-Forwarded-For +--- config + location = /t { + access_by_lua_block { + ngx.req.set_header("X-Forwarded-For", "8.8.8.8") + } + proxy_pass http://127.0.0.1:$server_port/back; + proxy_set_header Foo $proxy_add_x_forwarded_for; + } + + location = /back { + echo "Foo: $http_foo"; + } + +--- request +GET /t + +--- response_body +Foo: 8.8.8.8, 127.0.0.1 +--- no_error_log +[error] + + + +=== TEST 51: X-Forwarded-For +--- config + location = /t { + access_by_lua_block { + ngx.req.clear_header("X-Forwarded-For") + } + proxy_pass http://127.0.0.1:$server_port/back; + proxy_set_header Foo $proxy_add_x_forwarded_for; + } + + location = /back { + echo "Foo: $http_foo"; + } + +--- request +GET /t + +--- more_headers +X-Forwarded-For: 8.8.8.8 +--- response_body +Foo: 127.0.0.1 +--- no_error_log +[error] diff --git a/debian/modules/nginx-lua/t/056-flush.t b/debian/modules/nginx-lua/t/056-flush.t index 260e39a..d189cd5 100644 --- a/debian/modules/nginx-lua/t/056-flush.t +++ b/debian/modules/nginx-lua/t/056-flush.t @@ -42,7 +42,7 @@ hiya --- no_error_log [error] --- error_log -lua reuse free buf memory 13 >= 5 +lua reuse free buf chain, but reallocate memory because 5 >= 0 diff --git a/debian/modules/nginx-lua/t/058-tcp-socket.t b/debian/modules/nginx-lua/t/058-tcp-socket.t index 145a07b..3368589 100644 --- a/debian/modules/nginx-lua/t/058-tcp-socket.t +++ b/debian/modules/nginx-lua/t/058-tcp-socket.t @@ -4,7 +4,7 @@ use Test::Nginx::Socket::Lua; repeat_each(2); -plan tests => repeat_each() * 175; +plan tests => repeat_each() * 187; our $HtmlDir = html_dir; @@ -3343,3 +3343,298 @@ failed to setkeepalive: closed lua tcp socket connect timeout: 100 --- timeout: 10 + + +=== TEST 56: reuse cleanup +--- config + server_tokens off; + location /t { + set $port $TEST_NGINX_SERVER_PORT; + + content_by_lua_block { + local sock = ngx.socket.tcp() + local port = ngx.var.port + + for i = 1, 2 do + local ok, err = sock:connect("127.0.0.1", port) + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local req = "GET /foo HTTP/1.0\r\nHost: localhost\r\nConnection: close\r\n\r\n" + + local bytes, err = sock:send(req) + if not bytes then + ngx.say("failed to send request: ", err) + return + end + + ngx.say("request sent: ", bytes) + + while true do + local line, err, part = sock:receive() + if not line then + ngx.say("failed to receive a line: ", err, " [", part, "]") + break + end + end + + ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end + } + } + + location /foo { + content_by_lua 'ngx.say("foo")'; + more_clear_headers Date; + } + +--- request +GET /t +--- response_body +connected: 1 +request sent: 57 +failed to receive a line: closed [] +close: 1 nil +connected: 1 +request sent: 57 +failed to receive a line: closed [] +close: 1 nil +--- error_log +lua http cleanup reuse + + + +=== TEST 57: reuse cleanup in ngx.timer (fake_request) +--- config + server_tokens off; + location /t { + #set $port 5000; + set $port $TEST_NGINX_SERVER_PORT; + + content_by_lua_block { + local total_send_bytes = 0 + local port = ngx.var.port + + local function network() + local sock = ngx.socket.tcp() + + local ok, err = sock:connect("127.0.0.1", port) + if not ok then + ngx.log(ngx.ERR, "failed to connect: ", err) + return + end + + local req = "GET /foo HTTP/1.0\r\nHost: localhost\r\nConnection: close\r\n\r\n" + + local bytes, err = sock:send(req) + if not bytes then + ngx.log(ngx.ERR, "failed to send request: ", err) + return + end + + total_send_bytes = total_send_bytes + bytes + + while true do + local line, err, part = sock:receive() + if not line then + break + end + end + + ok, err = sock:close() + end + + local done = false + + local function double_network() + network() + network() + done = true + end + + local ok, err = ngx.timer.at(0, double_network) + if not ok then + ngx.say("failed to create timer: ", err) + end + + i = 1 + while not done do + local time = 0.005 * i + if time > 0.1 then + time = 0.1 + end + ngx.sleep(time) + i = i + 1 + end + + collectgarbage("collect") + + ngx.say("total_send_bytes: ", total_send_bytes) + } + } + + location /foo { + content_by_lua 'ngx.say("foo")'; + more_clear_headers Date; + } + +--- request +GET /t +--- response_body +total_send_bytes: 114 +--- error_log +lua http cleanup reuse + + + +=== TEST 58: free cleanup in ngx.timer (without sock:close) +--- config + server_tokens off; + location /t { + #set $port 5000; + set $port $TEST_NGINX_SERVER_PORT; + + content_by_lua_block { + local total_send_bytes = 0 + local port = ngx.var.port + + local function network() + local sock = ngx.socket.tcp() + + local ok, err = sock:connect("127.0.0.1", port) + if not ok then + ngx.log(ngx.ERR, "failed to connect: ", err) + return + end + + local req = "GET /foo HTTP/1.0\r\nHost: localhost\r\nConnection: close\r\n\r\n" + + local bytes, err = sock:send(req) + if not bytes then + ngx.log(ngx.ERR, "failed to send request: ", err) + return + end + + total_send_bytes = total_send_bytes + bytes + + while true do + local line, err, part = sock:receive() + if not line then + break + end + end + end + + local done = false + + local function double_network() + network() + network() + done = true + end + + local ok, err = ngx.timer.at(0, double_network) + if not ok then + ngx.say("failed to create timer: ", err) + end + + i = 1 + while not done do + local time = 0.005 * i + if time > 0.1 then + time = 0.1 + end + ngx.sleep(time) + i = i + 1 + end + + collectgarbage("collect") + + ngx.say("total_send_bytes: ", total_send_bytes) + } + } + + location /foo { + content_by_lua 'ngx.say("foo")'; + more_clear_headers Date; + } + +--- request +GET /t +--- response_body +total_send_bytes: 114 +--- no_error_log +[error] + + + +=== TEST 59: reuse cleanup in subrequest +--- config + server_tokens off; + location /t { + echo_location /tt; + } + + location /tt { + set $port $TEST_NGINX_SERVER_PORT; + + content_by_lua ' + local sock = ngx.socket.tcp() + local port = ngx.var.port + + for i = 1, 2 do + local ok, err = sock:connect("127.0.0.1", port) + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local req = "GET /foo HTTP/1.0\\r\\nHost: localhost\\r\\nConnection: close\\r\\n\\r\\n" + + local bytes, err = sock:send(req) + if not bytes then + ngx.say("failed to send request: ", err) + return + end + + ngx.say("request sent: ", bytes) + + while true do + local line, err, part = sock:receive() + if not line then + ngx.say("failed to receive a line: ", err, " [", part, "]") + break + end + end + + ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end + '; + } + + location /foo { + content_by_lua 'ngx.say("foo")'; + more_clear_headers Date; + } + +--- request +GET /t +--- response_body +connected: 1 +request sent: 57 +failed to receive a line: closed [] +close: 1 nil +connected: 1 +request sent: 57 +failed to receive a line: closed [] +close: 1 nil +--- error_log +lua http cleanup reuse diff --git a/debian/modules/nginx-lua/t/062-count.t b/debian/modules/nginx-lua/t/062-count.t index 120d131..c94491c 100644 --- a/debian/modules/nginx-lua/t/062-count.t +++ b/debian/modules/nginx-lua/t/062-count.t @@ -34,7 +34,7 @@ __DATA__ --- request GET /test --- response_body -ngx: 99 +ngx: 116 --- no_error_log [error] @@ -55,7 +55,7 @@ ngx: 99 --- request GET /test --- response_body -99 +116 --- no_error_log [error] @@ -83,7 +83,7 @@ GET /test --- request GET /test --- response_body -n = 99 +n = 116 --- no_error_log [error] @@ -123,7 +123,7 @@ n = 1 --- request GET /test --- response_body -n = 23 +n = 24 --- no_error_log [error] @@ -145,7 +145,7 @@ n = 23 --- request GET /test --- response_body -n = 23 +n = 24 --- no_error_log [error] @@ -172,7 +172,7 @@ n = 23 --- request GET /test --- response_body -n = 23 +n = 24 --- no_error_log [error] @@ -305,7 +305,7 @@ GET /t --- response_body_like: 404 Not Found --- error_code: 404 --- error_log -ngx. entry count: 99 +ngx. entry count: 116 @@ -323,7 +323,7 @@ ngx. entry count: 99 --- request GET /test --- response_body -n = 1 +n = 3 --- no_error_log [error] @@ -438,7 +438,7 @@ thread: 3 --- request GET /test --- response_body -worker: 2 +worker: 4 --- no_error_log [error] diff --git a/debian/modules/nginx-lua/t/076-no-postpone.t b/debian/modules/nginx-lua/t/076-no-postpone.t index d19bb77..94da63a 100644 --- a/debian/modules/nginx-lua/t/076-no-postpone.t +++ b/debian/modules/nginx-lua/t/076-no-postpone.t @@ -9,7 +9,7 @@ use Test::Nginx::Socket::Lua; repeat_each(2); #repeat_each(1); -plan tests => repeat_each() * (blocks() * 3); +plan tests => repeat_each() * (blocks() * 3 + 1); #no_diff(); #no_long_string(); @@ -82,3 +82,65 @@ no foo: 1 --- no_error_log [error] + + +=== TEST 4: access no postpone on +--- http_config + access_by_lua_no_postpone on; +--- config + location /t { + access_by_lua ' + ngx.redirect("http://www.taobao.com/foo") + ngx.say("hi") + '; + content_by_lua 'return'; + deny all; + } +--- request +GET /t +--- response_headers +Location: http://www.taobao.com/foo +--- response_body_like: 302 Found +--- error_code: 302 +--- no_error_log +[error] + + + +=== TEST 5: access no postpone explicitly off +--- http_config + access_by_lua_no_postpone off; +--- config + location /t { + access_by_lua ' + ngx.redirect("http://www.taobao.com/foo") + ngx.say("hi") + '; + content_by_lua 'return'; + deny all; + } +--- request +GET /t +--- response_body_like: 403 Forbidden +--- error_code: 403 +--- error_log +access forbidden by rule + + + +=== TEST 6: access no postpone off by default +--- config + location /t { + access_by_lua ' + ngx.redirect("http://www.taobao.com/foo") + ngx.say("hi") + '; + content_by_lua 'return'; + deny all; + } +--- request +GET /t +--- response_body_like: 403 Forbidden +--- error_code: 403 +--- error_log +access forbidden by rule diff --git a/debian/modules/nginx-lua/t/082-body-filter.t b/debian/modules/nginx-lua/t/082-body-filter.t index c0a7c23..98efa84 100644 --- a/debian/modules/nginx-lua/t/082-body-filter.t +++ b/debian/modules/nginx-lua/t/082-body-filter.t @@ -10,7 +10,7 @@ log_level('debug'); repeat_each(2); -plan tests => repeat_each() * (blocks() * 3 + 13); +plan tests => repeat_each() * (blocks() * 3 + 11); #no_diff(); no_long_string(); @@ -824,3 +824,16 @@ eof 2: true [error] [alert] + + +=== TEST 26: no ngx.print +--- config + location /lua { + echo ok; + body_filter_by_lua "ngx.print(32) return 1"; + } +--- request +GET /lua +--- ignore_response +--- error_log +API disabled in the context of body_filter_by_lua* diff --git a/debian/modules/nginx-lua/t/129-ssl-socket.t b/debian/modules/nginx-lua/t/129-ssl-socket.t index 45eaa82..446cfeb 100644 --- a/debian/modules/nginx-lua/t/129-ssl-socket.t +++ b/debian/modules/nginx-lua/t/129-ssl-socket.t @@ -371,11 +371,12 @@ lua ssl free session === TEST 5: certificate does not match host name (verify) +The certificate for "blah.agentzh.org" does not contain the name "blah.agentzh.org". --- config server_tokens off; resolver $TEST_NGINX_RESOLVER; lua_ssl_trusted_certificate ../html/trusted.crt; - lua_ssl_verify_depth 2; + lua_ssl_verify_depth 5; location /t { #set $port 5000; set $port $TEST_NGINX_MEMCACHED_PORT; @@ -393,14 +394,14 @@ lua ssl free session ngx.say("connected: ", ok) - local session, err = sock:sslhandshake(nil, "agentzh.org", true) + local session, err = sock:sslhandshake(nil, "blah.agentzh.org", true) if not session then ngx.say("failed to do SSL handshake: ", err) else ngx.say("ssl handshake: ", type(session)) end - local req = "GET / HTTP/1.1\\r\\nHost: iscribblet.org\\r\\nConnection: close\\r\\n\\r\\n" + local req = "GET / HTTP/1.1\\r\\nHost: agentzh.org\\r\\nConnection: close\\r\\n\\r\\n" local bytes, err = sock:send(req) if not bytes then ngx.say("failed to send http request: ", err) @@ -439,8 +440,8 @@ failed to send http request: closed --- grep_error_log eval: qr/lua ssl (?:set|save|free) session: [0-9A-F]+:\d+/ --- grep_error_log_out --- error_log -lua ssl server name: "agentzh.org" -lua ssl certificate does not match host "agentzh.org" +lua ssl server name: "blah.agentzh.org" +lua ssl certificate does not match host "blah.agentzh.org" --- no_error_log SSL reused session [alert] @@ -449,6 +450,7 @@ SSL reused session === TEST 6: certificate does not match host name (verify, no log socket errors) +The certificate for "blah.agentzh.org" does not contain the name "blah.agentzh.org". --- config server_tokens off; resolver $TEST_NGINX_RESOLVER; @@ -472,14 +474,14 @@ SSL reused session ngx.say("connected: ", ok) - local session, err = sock:sslhandshake(nil, "agentzh.org", true) + local session, err = sock:sslhandshake(nil, "blah.agentzh.org", true) if not session then ngx.say("failed to do SSL handshake: ", err) else ngx.say("ssl handshake: ", type(session)) end - local req = "GET / HTTP/1.1\\r\\nHost: iscribblet.org\\r\\nConnection: close\\r\\n\\r\\n" + local req = "GET / HTTP/1.1\\r\\nHost: blah.agentzh.org\\r\\nConnection: close\\r\\n\\r\\n" local bytes, err = sock:send(req) if not bytes then ngx.say("failed to send http request: ", err) @@ -518,7 +520,7 @@ failed to send http request: closed --- grep_error_log eval: qr/lua ssl (?:set|save|free) session: [0-9A-F]+:\d+/ --- grep_error_log_out --- error_log -lua ssl server name: "agentzh.org" +lua ssl server name: "blah.agentzh.org" --- no_error_log lua ssl certificate does not match host SSL reused session diff --git a/debian/modules/nginx-lua/t/132-lua-blocks.t b/debian/modules/nginx-lua/t/132-lua-blocks.t index 874d017..d157d27 100644 --- a/debian/modules/nginx-lua/t/132-lua-blocks.t +++ b/debian/modules/nginx-lua/t/132-lua-blocks.t @@ -488,3 +488,88 @@ GET /t Hey, it is '! --- no_error_log [error] + + + +=== TEST 21: lexer no match due to incomplete data chunks in a fixed size buffer +--- config + location /test1 { + content_by_lua_block { + ngx.say("1: this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error") + } + } + location /test2 { + content_by_lua_block { + ngx.say("2: this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error") + } + } + + location /test3 { + content_by_lua_block { + ngx.say("3: this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error", + "this is just some random filler to cause an error") + } + } +--- request +GET /test3 +--- response_body eval +"3: " . ("this is just some random filler to cause an error" x 20) . "\n" +--- no_error_log +[error] diff --git a/debian/modules/nginx-lua/t/133-worker-count.t b/debian/modules/nginx-lua/t/133-worker-count.t new file mode 100644 index 0000000..a7bae65 --- /dev/null +++ b/debian/modules/nginx-lua/t/133-worker-count.t @@ -0,0 +1,32 @@ +# vim:set ft= ts=4 sw=4 et fdm=marker: + +use Test::Nginx::Socket::Lua; + +#worker_connections(1014); +#master_on(); +#workers(2); +#log_level('warn'); + +repeat_each(2); + +plan tests => repeat_each() * (blocks() * 3); + +#no_diff(); +#no_long_string(); +run_tests(); + +__DATA__ + +=== TEST 1: content_by_lua +--- config + location /lua { + content_by_lua_block { + ngx.say("workers: ", ngx.worker.count()) + } + } +--- request +GET /lua +--- response_body +workers: 1 +--- no_error_log +[error] diff --git a/debian/modules/nginx-lua/t/134-worker-count-5.t b/debian/modules/nginx-lua/t/134-worker-count-5.t new file mode 100644 index 0000000..d6f16c2 --- /dev/null +++ b/debian/modules/nginx-lua/t/134-worker-count-5.t @@ -0,0 +1,32 @@ +# vim:set ft= ts=4 sw=4 et fdm=marker: + +use Test::Nginx::Socket::Lua; + +#worker_connections(1014); +#master_on(); +workers(5); +#log_level('warn'); + +repeat_each(2); + +plan tests => repeat_each() * (blocks() * 3); + +#no_diff(); +#no_long_string(); +run_tests(); + +__DATA__ + +=== TEST 1: sanity +--- config + location /lua { + content_by_lua_block { + ngx.say("worker count: ", ngx.worker.count()) + } + } +--- request +GET /lua +--- response_body +worker count: 5 +--- no_error_log +[error] diff --git a/debian/modules/nginx-lua/t/135-worker-id.t b/debian/modules/nginx-lua/t/135-worker-id.t new file mode 100644 index 0000000..752b406 --- /dev/null +++ b/debian/modules/nginx-lua/t/135-worker-id.t @@ -0,0 +1,33 @@ +# vim:set ft= ts=4 sw=4 et fdm=marker: + +use Test::Nginx::Socket::Lua; + +#worker_connections(1014); +#master_on(); +workers(2); +#log_level('warn'); + +repeat_each(2); + +plan tests => repeat_each() * (blocks() * 3); + +#no_diff(); +#no_long_string(); +run_tests(); + +__DATA__ + +=== TEST 1: sanity +--- config + location /lua { + content_by_lua_block { + ngx.say("worker id: ", ngx.worker.id()) + } + } +--- request +GET /lua +--- response_body_like chop +^worker id: [0-1]$ +--- no_error_log +[error] +--- skip_nginx: 3: <=1.9.0 diff --git a/debian/modules/nginx-lua/t/136-timer-counts.t b/debian/modules/nginx-lua/t/136-timer-counts.t new file mode 100644 index 0000000..8f5329b --- /dev/null +++ b/debian/modules/nginx-lua/t/136-timer-counts.t @@ -0,0 +1,111 @@ +# vim:set ft= ts=4 sw=4 et fdm=marker: + +use Test::Nginx::Socket::Lua; + +repeat_each(1); + +plan tests => blocks() * (repeat_each() * 3); + +run_tests(); + +__DATA__ + +=== TEST 1: running count with no running timers +--- config + location /timers { + content_by_lua_block { ngx.say(ngx.timer.running_count()) } + } +--- request +GET /timers +--- response_body +0 +--- no_error_log +[error] + + + +=== TEST 2: running count with no pending timers +--- config + location /timers { + content_by_lua_block { ngx.say(ngx.timer.pending_count()) } + } +--- request +GET /timers +--- response_body +0 +--- no_error_log +[error] + + + +=== TEST 3: pending count with one pending timer +--- config + location /timers { + content_by_lua_block { + ngx.timer.at(3, function() end) + ngx.say(ngx.timer.pending_count()) + } + } +--- request +GET /timers +--- response_body +1 +--- no_error_log +[error] + + + +=== TEST 4: pending count with 3 pending timers +--- config + location /timers { + content_by_lua_block { + ngx.timer.at(4, function() end) + ngx.timer.at(2, function() end) + ngx.timer.at(1, function() end) + ngx.say(ngx.timer.pending_count()) + } + } +--- request +GET /timers +--- response_body +3 +--- no_error_log +[error] + + + +=== TEST 5: one running timer +--- config + location /timers { + content_by_lua_block { + ngx.timer.at(0.1, function() ngx.sleep(0.3) end) + ngx.sleep(0.2) + ngx.say(ngx.timer.running_count()) + } + } +--- request +GET /timers +--- response_body +1 +--- no_error_log +[error] + + + +=== TEST 6: 3 running timers +--- config + location /timers { + content_by_lua_block { + ngx.timer.at(0.1, function() ngx.sleep(0.3) end) + ngx.timer.at(0.11, function() ngx.sleep(0.3) end) + ngx.timer.at(0.09, function() ngx.sleep(0.3) end) + ngx.sleep(0.2) + ngx.say(ngx.timer.running_count()) + } + } +--- request +GET /timers +--- response_body +3 +--- no_error_log +[error] diff --git a/debian/modules/nginx-lua/t/137-req-misc.t b/debian/modules/nginx-lua/t/137-req-misc.t new file mode 100644 index 0000000..20ada3c --- /dev/null +++ b/debian/modules/nginx-lua/t/137-req-misc.t @@ -0,0 +1,62 @@ +use Test::Nginx::Socket::Lua; + +#master_on(); +#workers(1); +#worker_connections(1014); +#log_level('warn'); +#master_process_enabled(1); + +repeat_each(2); + +plan tests => repeat_each() * blocks() * 2; + +$ENV{TEST_NGINX_MEMCACHED_PORT} ||= 11211; + +#no_diff(); +no_long_string(); +#no_shuffle(); + +run_tests(); + +__DATA__ + +=== TEST 1: not internal request +--- config + location /test { + rewrite ^/test$ /lua last; + } + location /lua { + content_by_lua ' + if ngx.req.is_internal() then + ngx.say("internal") + else + ngx.say("not internal") + end + '; + } +--- request +GET /lua +--- response_body +not internal + + + +=== TEST 2: internal request +--- config + location /test { + rewrite ^/test$ /lua last; + } + location /lua { + content_by_lua ' + if ngx.req.is_internal() then + ngx.say("internal") + else + ngx.say("not internal") + end + '; + } +--- request +GET /test +--- response_body +internal + diff --git a/debian/modules/nginx-lua/t/138-balancer.t b/debian/modules/nginx-lua/t/138-balancer.t new file mode 100644 index 0000000..076465a --- /dev/null +++ b/debian/modules/nginx-lua/t/138-balancer.t @@ -0,0 +1,304 @@ +# vim:set ft= ts=4 sw=4 et fdm=marker: + +use Test::Nginx::Socket::Lua; + +#worker_connections(1014); +#master_on(); +#workers(2); +#log_level('warn'); + +repeat_each(2); + +plan tests => repeat_each() * (blocks() * 4 + 8); + +#no_diff(); +no_long_string(); +run_tests(); + +__DATA__ + +=== TEST 1: simple logging +--- http_config + upstream backend { + server 0.0.0.1; + balancer_by_lua_block { + print("hello from balancer by lua!") + } + } +--- config + location = /t { + proxy_pass http://backend; + } +--- request + GET /t +--- response_body_like: 502 Bad Gateway +--- error_code: 502 +--- error_log eval +[ +'[lua] balancer_by_lua:2: hello from balancer by lua! while connecting to upstream,', +qr{\[crit\] .*? connect\(\) to 0\.0\.0\.1:80 failed .*?, upstream: "http://0\.0\.0\.1:80/t"}, +] +--- no_error_log +[warn] + + + +=== TEST 2: exit 403 +--- http_config + upstream backend { + server 0.0.0.1; + balancer_by_lua_block { + print("hello from balancer by lua!") + ngx.exit(403) + } + } +--- config + location = /t { + proxy_pass http://backend; + } +--- request + GET /t +--- response_body_like: 500 Internal Server Error +--- error_code: 500 +--- error_log +[lua] balancer_by_lua:2: hello from balancer by lua! while connecting to upstream, +--- no_error_log eval +[ +'[warn]', +qr{\[crit\] .*? connect\(\) to 0\.0\.0\.1:80 failed .*?, upstream: "http://0\.0\.0\.1:80/t"}, +] + + + +=== TEST 3: exit OK +--- http_config + upstream backend { + server 0.0.0.1; + balancer_by_lua_block { + print("hello from balancer by lua!") + ngx.exit(ngx.OK) + } + } +--- config + location = /t { + proxy_pass http://backend; + } +--- request + GET /t +--- response_body_like: 502 Bad Gateway +--- error_code: 502 +--- error_log eval +[ +'[lua] balancer_by_lua:2: hello from balancer by lua! while connecting to upstream,', +qr{\[crit\] .*? connect\(\) to 0\.0\.0\.1:80 failed .*?, upstream: "http://0\.0\.0\.1:80/t"}, +] +--- no_error_log +[warn] + + + +=== TEST 4: ngx.var works +--- http_config + upstream backend { + server 0.0.0.1; + balancer_by_lua_block { + print("1: variable foo = ", ngx.var.foo) + ngx.var.foo = tonumber(ngx.var.foo) + 1 + print("2: variable foo = ", ngx.var.foo) + } + } +--- config + location = /t { + set $foo 32; + proxy_pass http://backend; + } +--- request + GET /t +--- response_body_like: 502 Bad Gateway +--- error_code: 502 +--- error_log eval +[ +"1: variable foo = 32", +"2: variable foo = 33", +qr/\[crit\] .* connect\(\) .*? failed/, +] +--- no_error_log +[warn] + + + +=== TEST 5: ngx.req.get_headers works +--- http_config + upstream backend { + server 0.0.0.1; + balancer_by_lua_block { + print("header foo: ", ngx.req.get_headers()["foo"]) + } + } +--- config + location = /t { + proxy_pass http://backend; + } +--- request + GET /t +--- more_headers +Foo: bar +--- response_body_like: 502 Bad Gateway +--- error_code: 502 +--- error_log eval +[ +"header foo: bar", +qr/\[crit\] .* connect\(\) .*? failed/, +] +--- no_error_log +[warn] + + + +=== TEST 6: ngx.req.get_uri_args() works +--- http_config + upstream backend { + server 0.0.0.1; + balancer_by_lua_block { + print("arg foo: ", ngx.req.get_uri_args()["foo"]) + } + } +--- config + location = /t { + proxy_pass http://backend; + } +--- request + GET /t?baz=blah&foo=bar +--- more_headers +Foo: bar +--- response_body_like: 502 Bad Gateway +--- error_code: 502 +--- error_log eval +["arg foo: bar", +qr/\[crit\] .* connect\(\) .*? failed/, +] +--- no_error_log +[warn] + + + +=== TEST 7: ngx.req.get_method() works +--- http_config + upstream backend { + server 0.0.0.1; + balancer_by_lua_block { + print("method: ", ngx.req.get_method()) + } + } +--- config + location = /t { + proxy_pass http://backend; + } +--- request + GET /t +--- more_headers +Foo: bar +--- response_body_like: 502 Bad Gateway +--- error_code: 502 +--- error_log eval +[ +"method: GET", +qr/\[crit\] .* connect\(\) .*? failed/, +] +--- no_error_log +[warn] + + + +=== TEST 8: simple logging (by_lua_file) +--- http_config + upstream backend { + server 0.0.0.1; + balancer_by_lua_file html/a.lua; + } +--- config + location = /t { + proxy_pass http://backend; + } +--- user_files +>>> a.lua +print("hello from balancer by lua!") +--- request + GET /t +--- response_body_like: 502 Bad Gateway +--- error_code: 502 +--- error_log eval +[ +'[lua] a.lua:1: hello from balancer by lua! while connecting to upstream,', +qr{\[crit\] .*? connect\(\) to 0\.0\.0\.1:80 failed .*?, upstream: "http://0\.0\.0\.1:80/t"}, +] +--- no_error_log +[warn] + + + +=== TEST 9: cosockets are disabled +--- http_config + upstream backend { + server 0.0.0.1; + balancer_by_lua_block { + local sock, err = ngx.socket.tcp() + } + } +--- config + location = /t { + proxy_pass http://backend; + } +--- request + GET /t +--- response_body_like: 500 Internal Server Error +--- error_code: 500 +--- error_log eval +qr/\[error\] .*? failed to run balancer_by_lua\*: balancer_by_lua:2: API disabled in the context of balancer_by_lua\*/ + + + +=== TEST 10: ngx.sleep is disabled +--- http_config + upstream backend { + server 0.0.0.1; + balancer_by_lua_block { + ngx.sleep(0.1) + } + } +--- config + location = /t { + proxy_pass http://backend; + } +--- request + GET /t +--- response_body_like: 500 Internal Server Error +--- error_code: 500 +--- error_log eval +qr/\[error\] .*? failed to run balancer_by_lua\*: balancer_by_lua:2: API disabled in the context of balancer_by_lua\*/ + + + +=== TEST 11: get_phase +--- http_config + upstream backend { + server 0.0.0.1; + balancer_by_lua_block { + print("I am in phase ", ngx.get_phase()) + } + } +--- config + location = /t { + proxy_pass http://backend; + } +--- request + GET /t +--- response_body_like: 502 Bad Gateway +--- error_code: 502 +--- grep_error_log eval: qr/I am in phase \w+/ +--- grep_error_log_out +I am in phase balancer +--- error_log eval +qr{\[crit\] .*? connect\(\) to 0\.0\.0\.1:80 failed .*?, upstream: "http://0\.0\.0\.1:80/t"} +--- no_error_log +[error] diff --git a/debian/modules/nginx-lua/t/139-ssl-cert-by.t b/debian/modules/nginx-lua/t/139-ssl-cert-by.t new file mode 100644 index 0000000..e40fe85 --- /dev/null +++ b/debian/modules/nginx-lua/t/139-ssl-cert-by.t @@ -0,0 +1,1382 @@ +# vim:set ft= ts=4 sw=4 et fdm=marker: + +use Test::Nginx::Socket::Lua; + +repeat_each(3); + +# All these tests need to have new openssl +my $NginxBinary = $ENV{'TEST_NGINX_BINARY'} || 'nginx'; +my $openssl_version = eval { `$NginxBinary -V 2>&1` }; + +if ($openssl_version =~ m/built with OpenSSL (0|1\.0\.(?:0|1[^\d]|2[a-d]).*)/) { + plan(skip_all => "too old OpenSSL, need 1.0.2e, was $1"); +} else { + plan tests => repeat_each() * (blocks() * 6 + 10); +} + +$ENV{TEST_NGINX_HTML_DIR} ||= html_dir(); +$ENV{TEST_NGINX_MEMCACHED_PORT} ||= 11211; + +#log_level 'warn'; +log_level 'debug'; + +no_long_string(); +#no_diff(); + +run_tests(); + +__DATA__ + +=== TEST 1: simple logging +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + ssl_certificate_by_lua_block { print("ssl cert by lua is running!") } + ssl_certificate ../../cert/test.crt; + ssl_certificate_key ../../cert/test.key; + + server_tokens off; + location /foo { + default_type 'text/plain'; + content_by_lua_block { ngx.status = 201 ngx.say("foo") ngx.exit(201) } + more_clear_headers Date; + } + } +--- config + server_tokens off; + lua_ssl_trusted_certificate ../../cert/test.crt; + + location /t { + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(2000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(nil, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + local req = "GET /foo HTTP/1.0\r\nHost: test.com\r\nConnection: close\r\n\r\n" + local bytes, err = sock:send(req) + if not bytes then + ngx.say("failed to send http request: ", err) + return + end + + ngx.say("sent http request: ", bytes, " bytes.") + + while true do + local line, err = sock:receive() + if not line then + -- ngx.say("failed to recieve response status line: ", err) + break + end + + ngx.say("received: ", line) + end + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: userdata +sent http request: 56 bytes. +received: HTTP/1.1 201 Created +received: Server: nginx +received: Content-Type: text/plain +received: Content-Length: 4 +received: Connection: close +received: +received: foo +close: 1 nil + +--- error_log +lua ssl server name: "test.com" +ssl_certificate_by_lua:1: ssl cert by lua is running! + +--- no_error_log +[error] +[alert] + + + +=== TEST 2: sleep +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + ssl_certificate_by_lua_block { + local begin = ngx.now() + ngx.sleep(0.1) + print("elapsed in ssl cert by lua: ", ngx.now() - begin) + } + ssl_certificate ../../cert/test.crt; + ssl_certificate_key ../../cert/test.key; + + server_tokens off; + location /foo { + default_type 'text/plain'; + content_by_lua_block {ngx.status = 201 ngx.say("foo") ngx.exit(201)} + more_clear_headers Date; + } + } +--- config + server_tokens off; + lua_ssl_trusted_certificate ../../cert/test.crt; + + location /t { + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(2000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(nil, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + local req = "GET /foo HTTP/1.0\r\nHost: test.com\r\nConnection: close\r\n\r\n" + local bytes, err = sock:send(req) + if not bytes then + ngx.say("failed to send http request: ", err) + return + end + + ngx.say("sent http request: ", bytes, " bytes.") + + while true do + local line, err = sock:receive() + if not line then + -- ngx.say("failed to recieve response status line: ", err) + break + end + + ngx.say("received: ", line) + end + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: userdata +sent http request: 56 bytes. +received: HTTP/1.1 201 Created +received: Server: nginx +received: Content-Type: text/plain +received: Content-Length: 4 +received: Connection: close +received: +received: foo +close: 1 nil + +--- error_log eval +[ +'lua ssl server name: "test.com"', +qr/elapsed in ssl cert by lua: 0.(?:09|1[01])\d+,/, +] + +--- no_error_log +[error] +[alert] + + + +=== TEST 3: timer +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + ssl_certificate_by_lua_block { + local function f() + print("my timer run!") + end + local ok, err = ngx.timer.at(0, f) + if not ok then + ngx.log(ngx.ERR, "failed to create timer: ", err) + return + end + } + ssl_certificate ../../cert/test.crt; + ssl_certificate_key ../../cert/test.key; + + server_tokens off; + location /foo { + default_type 'text/plain'; + content_by_lua_block {ngx.status = 201 ngx.say("foo") ngx.exit(201)} + more_clear_headers Date; + } + } +--- config + server_tokens off; + lua_ssl_trusted_certificate ../../cert/test.crt; + + location /t { + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(2000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(nil, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + local req = "GET /foo HTTP/1.0\r\nHost: test.com\r\nConnection: close\r\n\r\n" + local bytes, err = sock:send(req) + if not bytes then + ngx.say("failed to send http request: ", err) + return + end + + ngx.say("sent http request: ", bytes, " bytes.") + + while true do + local line, err = sock:receive() + if not line then + -- ngx.say("failed to recieve response status line: ", err) + break + end + + ngx.say("received: ", line) + end + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: userdata +sent http request: 56 bytes. +received: HTTP/1.1 201 Created +received: Server: nginx +received: Content-Type: text/plain +received: Content-Length: 4 +received: Connection: close +received: +received: foo +close: 1 nil + +--- error_log +lua ssl server name: "test.com" +my timer run! + +--- no_error_log +[error] +[alert] + + + +=== TEST 4: cosocket +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + ssl_certificate_by_lua_block { + local sock = ngx.socket.tcp() + + sock:settimeout(2000) + + local ok, err = sock:connect("127.0.0.1", $TEST_NGINX_MEMCACHED_PORT) + if not ok then + ngx.log(ngx.ERR, "failed to connect to memc: ", err) + return + end + + local bytes, err = sock:send("flush_all\r\n") + if not bytes then + ngx.log(ngx.ERR, "failed to send flush_all command: ", err) + return + end + + local res, err = sock:receive() + if not res then + ngx.log(ngx.ERR, "failed to receive memc reply: ", err) + return + end + + print("received memc reply: ", res) + } + ssl_certificate ../../cert/test.crt; + ssl_certificate_key ../../cert/test.key; + + server_tokens off; + location /foo { + default_type 'text/plain'; + content_by_lua_block {ngx.status = 201 ngx.say("foo") ngx.exit(201)} + more_clear_headers Date; + } + } +--- config + server_tokens off; + lua_ssl_trusted_certificate ../../cert/test.crt; + + location /t { + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(2000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(nil, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + local req = "GET /foo HTTP/1.0\r\nHost: test.com\r\nConnection: close\r\n\r\n" + local bytes, err = sock:send(req) + if not bytes then + ngx.say("failed to send http request: ", err) + return + end + + ngx.say("sent http request: ", bytes, " bytes.") + + while true do + local line, err = sock:receive() + if not line then + -- ngx.say("failed to recieve response status line: ", err) + break + end + + ngx.say("received: ", line) + end + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: userdata +sent http request: 56 bytes. +received: HTTP/1.1 201 Created +received: Server: nginx +received: Content-Type: text/plain +received: Content-Length: 4 +received: Connection: close +received: +received: foo +close: 1 nil + +--- error_log +lua ssl server name: "test.com" +received memc reply: OK + +--- no_error_log +[error] +[alert] + + + +=== TEST 5: ngx.exit(0) - no yield +--- http_config + server { + listen 127.0.0.2:8080 ssl; + server_name test.com; + ssl_certificate_by_lua_block { + ngx.exit(0) + ngx.log(ngx.ERR, "should never reached here...") + } + ssl_certificate ../../cert/test.crt; + ssl_certificate_key ../../cert/test.key; + + server_tokens off; + location /foo { + default_type 'text/plain'; + content_by_lua_block {ngx.status = 201 ngx.say("foo") ngx.exit(201)} + more_clear_headers Date; + } + } +--- config + server_tokens off; + lua_ssl_trusted_certificate ../../cert/test.crt; + lua_ssl_verify_depth 3; + + location /t { + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(2000) + + local ok, err = sock:connect("127.0.0.2", 8080) + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(false, nil, true, false) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + end -- do + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: boolean + +--- error_log +lua exit with code 0 + +--- no_error_log +should never reached here +[error] +[alert] +[emerg] + + + +=== TEST 6: ngx.exit(ngx.ERROR) - no yield +--- http_config + server { + listen 127.0.0.2:8080 ssl; + server_name test.com; + ssl_certificate_by_lua_block { + ngx.exit(ngx.ERROR) + ngx.log(ngx.ERR, "should never reached here...") + } + ssl_certificate ../../cert/test.crt; + ssl_certificate_key ../../cert/test.key; + + server_tokens off; + location /foo { + default_type 'text/plain'; + content_by_lua_block {ngx.status = 201 ngx.say("foo") ngx.exit(201)} + more_clear_headers Date; + } + } +--- config + server_tokens off; + lua_ssl_trusted_certificate ../../cert/test.crt; + lua_ssl_verify_depth 3; + + location /t { + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(2000) + + local ok, err = sock:connect("127.0.0.2", 8080) + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(false, nil, true, false) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + end -- do + } + } + +--- request +GET /t +--- response_body +connected: 1 +failed to do SSL handshake: handshake failed + +--- error_log eval +[ +'lua_certificate_by_lua: handler return value: -1, cert cb exit code: 0', +qr/\[crit\] .*? SSL_do_handshake\(\) failed .*?cert cb error/, +'lua exit with code -1', +] + +--- no_error_log +should never reached here +[alert] +[emerg] + + + +=== TEST 7: ngx.exit(0) - yield +--- http_config + server { + listen 127.0.0.2:8080 ssl; + server_name test.com; + ssl_certificate_by_lua_block { + ngx.sleep(0.001) + ngx.exit(0) + + ngx.log(ngx.ERR, "should never reached here...") + } + ssl_certificate ../../cert/test.crt; + ssl_certificate_key ../../cert/test.key; + + server_tokens off; + location /foo { + default_type 'text/plain'; + content_by_lua_block {ngx.status = 201 ngx.say("foo") ngx.exit(201)} + more_clear_headers Date; + } + } +--- config + server_tokens off; + lua_ssl_trusted_certificate ../../cert/test.crt; + lua_ssl_verify_depth 3; + + location /t { + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(2000) + + local ok, err = sock:connect("127.0.0.2", 8080) + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(false, nil, true, false) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + end -- do + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: boolean + +--- error_log +lua exit with code 0 + +--- no_error_log +should never reached here +[error] +[alert] +[emerg] + + + +=== TEST 8: ngx.exit(ngx.ERROR) - yield +--- http_config + server { + listen 127.0.0.2:8080 ssl; + server_name test.com; + ssl_certificate_by_lua_block { + ngx.sleep(0.001) + ngx.exit(ngx.ERROR) + + ngx.log(ngx.ERR, "should never reached here...") + } + ssl_certificate ../../cert/test.crt; + ssl_certificate_key ../../cert/test.key; + + server_tokens off; + location /foo { + default_type 'text/plain'; + content_by_lua_block {ngx.status = 201 ngx.say("foo") ngx.exit(201)} + more_clear_headers Date; + } + } +--- config + server_tokens off; + lua_ssl_trusted_certificate ../../cert/test.crt; + lua_ssl_verify_depth 3; + + location /t { + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(2000) + + local ok, err = sock:connect("127.0.0.2", 8080) + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(false, nil, true, false) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + end -- do + } + } + +--- request +GET /t +--- response_body +connected: 1 +failed to do SSL handshake: handshake failed + +--- error_log eval +[ +'lua_certificate_by_lua: cert cb exit code: 0', +qr/\[crit\] .*? SSL_do_handshake\(\) failed .*?cert cb error/, +'lua exit with code -1', +] + +--- no_error_log +should never reached here +[alert] +[emerg] + + + +=== TEST 9: lua exception - no yield +--- http_config + server { + listen 127.0.0.2:8080 ssl; + server_name test.com; + ssl_certificate_by_lua_block { + error("bad bad bad") + ngx.log(ngx.ERR, "should never reached here...") + } + ssl_certificate ../../cert/test.crt; + ssl_certificate_key ../../cert/test.key; + + server_tokens off; + location /foo { + default_type 'text/plain'; + content_by_lua_block {ngx.status = 201 ngx.say("foo") ngx.exit(201)} + more_clear_headers Date; + } + } +--- config + server_tokens off; + lua_ssl_trusted_certificate ../../cert/test.crt; + lua_ssl_verify_depth 3; + + location /t { + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(2000) + + local ok, err = sock:connect("127.0.0.2", 8080) + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(false, nil, true, false) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + end -- do + } + } + +--- request +GET /t +--- response_body +connected: 1 +failed to do SSL handshake: handshake failed + +--- error_log eval +[ +'runtime error: ssl_certificate_by_lua:2: bad bad bad', +'lua_certificate_by_lua: handler return value: 500, cert cb exit code: 0', +qr/\[crit\] .*? SSL_do_handshake\(\) failed .*?cert cb error/, +qr/context: ssl_certificate_by_lua\*, client: \d+\.\d+\.\d+\.\d+, server: \d+\.\d+\.\d+\.\d+:\d+/, +] + +--- no_error_log +should never reached here +[alert] +[emerg] + + + +=== TEST 10: lua exception - yield +--- http_config + server { + listen 127.0.0.2:8080 ssl; + server_name test.com; + ssl_certificate_by_lua_block { + ngx.sleep(0.001) + error("bad bad bad") + ngx.log(ngx.ERR, "should never reached here...") + } + ssl_certificate ../../cert/test.crt; + ssl_certificate_key ../../cert/test.key; + + server_tokens off; + location /foo { + default_type 'text/plain'; + content_by_lua_block {ngx.status = 201 ngx.say("foo") ngx.exit(201)} + more_clear_headers Date; + } + } +--- config + server_tokens off; + lua_ssl_trusted_certificate ../../cert/test.crt; + lua_ssl_verify_depth 3; + + location /t { + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(2000) + + local ok, err = sock:connect("127.0.0.2", 8080) + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(false, nil, true, false) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + end -- do + } + } + +--- request +GET /t +--- response_body +connected: 1 +failed to do SSL handshake: handshake failed + +--- error_log eval +[ +'runtime error: ssl_certificate_by_lua:3: bad bad bad', +'lua_certificate_by_lua: cert cb exit code: 0', +qr/\[crit\] .*? SSL_do_handshake\(\) failed .*?cert cb error/, +] + +--- no_error_log +should never reached here +[alert] +[emerg] + + + +=== TEST 11: get phase +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + ssl_certificate_by_lua_block {print("get_phase: ", ngx.get_phase())} + ssl_certificate ../../cert/test.crt; + ssl_certificate_key ../../cert/test.key; + + server_tokens off; + location /foo { + default_type 'text/plain'; + content_by_lua_block {ngx.status = 201 ngx.say("foo") ngx.exit(201)} + more_clear_headers Date; + } + } +--- config + server_tokens off; + lua_ssl_trusted_certificate ../../cert/test.crt; + + location /t { + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(2000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(nil, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + end + collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: userdata + +--- error_log +lua ssl server name: "test.com" +get_phase: ssl_cert + +--- no_error_log +[error] +[alert] + + + +=== TEST 12: connection aborted prematurely +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + ssl_certificate_by_lua_block { + ngx.sleep(0.3) + -- local ssl = require "ngx.ssl" + -- ssl.clear_certs() + print("ssl-cert-by-lua: after sleeping") + } + ssl_certificate ../../cert/test.crt; + ssl_certificate_key ../../cert/test.key; + + server_tokens off; + } +--- config + server_tokens off; + lua_ssl_trusted_certificate ../../cert/test.crt; + + location /t { + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(150) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(false, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t + +--- response_body +connected: 1 +failed to do SSL handshake: timeout + +--- error_log +lua ssl server name: "test.com" +ssl-cert-by-lua: after sleeping + +--- no_error_log +[error] +[alert] +--- wait: 0.6 + + + +=== TEST 13: subrequests disabled +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + ssl_certificate_by_lua_block {ngx.location.capture("/foo")} + ssl_certificate ../../cert/test.crt; + ssl_certificate_key ../../cert/test.key; + } +--- config + server_tokens off; + lua_ssl_trusted_certificate ../../cert/test.crt; + + location /t { + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(2000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(nil, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +failed to do SSL handshake: handshake failed + +--- error_log eval +[ +'lua ssl server name: "test.com"', +'ssl_certificate_by_lua:1: API disabled in the context of ssl_certificate_by_lua*', +qr/\[crit\] .*?cert cb error/, +] + +--- no_error_log +[alert] + + + +=== TEST 14: simple logging (by_lua_file) +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + ssl_certificate_by_lua_file html/a.lua; + ssl_certificate ../../cert/test.crt; + ssl_certificate_key ../../cert/test.key; + + server_tokens off; + location /foo { + default_type 'text/plain'; + content_by_lua_block {ngx.status = 201 ngx.say("foo") ngx.exit(201)} + more_clear_headers Date; + } + } + +--- user_files +>>> a.lua +print("ssl cert by lua is running!") + +--- config + server_tokens off; + lua_ssl_trusted_certificate ../../cert/test.crt; + + location /t { + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(2000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(nil, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + local req = "GET /foo HTTP/1.0\r\nHost: test.com\r\nConnection: close\r\n\r\n" + local bytes, err = sock:send(req) + if not bytes then + ngx.say("failed to send http request: ", err) + return + end + + ngx.say("sent http request: ", bytes, " bytes.") + + while true do + local line, err = sock:receive() + if not line then + -- ngx.say("failed to recieve response status line: ", err) + break + end + + ngx.say("received: ", line) + end + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: userdata +sent http request: 56 bytes. +received: HTTP/1.1 201 Created +received: Server: nginx +received: Content-Type: text/plain +received: Content-Length: 4 +received: Connection: close +received: +received: foo +close: 1 nil + +--- error_log +lua ssl server name: "test.com" +a.lua:1: ssl cert by lua is running! + +--- no_error_log +[error] +[alert] + + + +=== TEST 15: coroutine API +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + ssl_certificate_by_lua_block { + local cc, cr, cy = coroutine.create, coroutine.resume, coroutine.yield + + local function f() + local cnt = 0 + for i = 1, 20 do + print("co yield: ", cnt) + cy() + cnt = cnt + 1 + end + end + + local c = cc(f) + for i = 1, 3 do + print("co resume, status: ", coroutine.status(c)) + cr(c) + end + } + ssl_certificate ../../cert/test.crt; + ssl_certificate_key ../../cert/test.key; + + server_tokens off; + location /foo { + default_type 'text/plain'; + content_by_lua_block { ngx.status = 201 ngx.say("foo") ngx.exit(201) } + more_clear_headers Date; + } + } +--- config + server_tokens off; + lua_ssl_trusted_certificate ../../cert/test.crt; + + location /t { + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(2000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(nil, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + local req = "GET /foo HTTP/1.0\r\nHost: test.com\r\nConnection: close\r\n\r\n" + local bytes, err = sock:send(req) + if not bytes then + ngx.say("failed to send http request: ", err) + return + end + + ngx.say("sent http request: ", bytes, " bytes.") + + while true do + local line, err = sock:receive() + if not line then + -- ngx.say("failed to recieve response status line: ", err) + break + end + + ngx.say("received: ", line) + end + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: userdata +sent http request: 56 bytes. +received: HTTP/1.1 201 Created +received: Server: nginx +received: Content-Type: text/plain +received: Content-Length: 4 +received: Connection: close +received: +received: foo +close: 1 nil + +--- grep_error_log eval: qr/co (?:yield: \d+|resume, status: \w+)/ +--- grep_error_log_out +co resume, status: suspended +co yield: 0 +co resume, status: suspended +co yield: 1 +co resume, status: suspended +co yield: 2 + +--- error_log +lua ssl server name: "test.com" + +--- no_error_log +[error] +[alert] + + + +=== TEST 16: simple user thread wait with yielding +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + ssl_certificate_by_lua_block { + function f() + ngx.sleep(0.01) + print("uthread: hello in thread") + return "done" + end + + local t, err = ngx.thread.spawn(f) + if not t then + ngx.log(ngx.ERR, "uthread: failed to spawn thread: ", err) + return ngx.exit(ngx.ERROR) + end + + print("uthread: thread created: ", coroutine.status(t)) + + local ok, res = ngx.thread.wait(t) + if not ok then + print("uthread: failed to wait thread: ", res) + return + end + + print("uthread: ", res) + } + ssl_certificate ../../cert/test.crt; + ssl_certificate_key ../../cert/test.key; + + server_tokens off; + location /foo { + default_type 'text/plain'; + content_by_lua_block { ngx.status = 201 ngx.say("foo") ngx.exit(201) } + more_clear_headers Date; + } + } +--- config + server_tokens off; + lua_ssl_trusted_certificate ../../cert/test.crt; + + location /t { + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(2000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(nil, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + local req = "GET /foo HTTP/1.0\r\nHost: test.com\r\nConnection: close\r\n\r\n" + local bytes, err = sock:send(req) + if not bytes then + ngx.say("failed to send http request: ", err) + return + end + + ngx.say("sent http request: ", bytes, " bytes.") + + while true do + local line, err = sock:receive() + if not line then + -- ngx.say("failed to recieve response status line: ", err) + break + end + + ngx.say("received: ", line) + end + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: userdata +sent http request: 56 bytes. +received: HTTP/1.1 201 Created +received: Server: nginx +received: Content-Type: text/plain +received: Content-Length: 4 +received: Connection: close +received: +received: foo +close: 1 nil + +--- no_error_log +[error] +[alert] +--- grep_error_log eval: qr/uthread: [^.,]+/ +--- grep_error_log_out +uthread: thread created: running +uthread: hello in thread +uthread: done diff --git a/debian/modules/nginx-lua/util/build2.sh b/debian/modules/nginx-lua/util/build2.sh index 5a89c29..2aa79cc 100755 --- a/debian/modules/nginx-lua/util/build2.sh +++ b/debian/modules/nginx-lua/util/build2.sh @@ -21,16 +21,16 @@ force=$2 #--with-cc=clang \ #--without-http_referer_module \ #--with-http_v2_module \ + #--with-http_spdy_module \ time ngx-build $force $version \ --with-ipv6 \ - --with-cc-opt="-I$PCRE_INC" \ + --with-cc-opt="-I$PCRE_INC -I$OPENSSL_INC" \ --with-http_realip_module \ - --with-http_ssl_module \ + --with-http_ssl_module \ --add-module=$root/../ndk-nginx-module \ --add-module=$root/../set-misc-nginx-module \ - --with-ld-opt="-L$PCRE_LIB -Wl,-rpath,$PCRE_LIB:$LIBDRIZZLE_LIB:/usr/local/lib" \ - --with-http_spdy_module \ + --with-ld-opt="-L$PCRE_LIB -L$OPENSSL_LIB -Wl,-rpath,$PCRE_LIB:$LIBDRIZZLE_LIB:$OPENSSL_LIB" \ --without-mail_pop3_module \ --without-mail_imap_module \ --with-http_image_filter_module \ From 45aed60c9d102d2dd12030f05c318ed6e9ff0522 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Thu, 14 Jan 2016 10:31:38 +0200 Subject: [PATCH 022/600] Keep logs for 14 *days* Complements Mike's 255c62e0 (#805322) --- debian/nginx-common.nginx.logrotate | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/nginx-common.nginx.logrotate b/debian/nginx-common.nginx.logrotate index 1b25aad..423c6ad 100644 --- a/debian/nginx-common.nginx.logrotate +++ b/debian/nginx-common.nginx.logrotate @@ -1,5 +1,5 @@ /var/log/nginx/*.log { - weekly + daily missingok rotate 14 compress From 706a679a92e1bfa57e22f6f09eec02800b7d289a Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Thu, 14 Jan 2016 10:37:03 +0200 Subject: [PATCH 023/600] Add a NEWS entry for our logrotate policy change --- debian/nginx-common.NEWS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/debian/nginx-common.NEWS b/debian/nginx-common.NEWS index 46a6f14..a72049d 100644 --- a/debian/nginx-common.NEWS +++ b/debian/nginx-common.NEWS @@ -1,3 +1,10 @@ +nginx-common (1.9.9-1) UNRELEASED; urgency=medium + + Starting with this release we are changing the default logrotate rule to keep + daily logs for 14 days, this aligns our policy with apache2 (Bug #805322). + + -- Christos Trochalakis Thu, 14 Jan 2016 10:17:33 +0200 + nginx-common (1.9.6-1) unstable; urgency=medium As of nginx 1.9.5 spdy has been replaced by the http2 module. Make sure to From 4f41a6929370dd71500208b147bd9af0fc950858 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Thu, 14 Jan 2016 10:41:13 +0200 Subject: [PATCH 024/600] Release 1.9.9-1 --- debian/changelog | 4 ++-- debian/nginx-common.NEWS | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/debian/changelog b/debian/changelog index bf298f1..5e94be3 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -nginx (1.9.9-1) UNRELEASED; urgency=medium +nginx (1.9.9-1) unstable; urgency=medium [ Michael Lustfield ] * debian/nginx-common.nginx.logrotate: @@ -9,7 +9,7 @@ nginx (1.9.9-1) UNRELEASED; urgency=medium * debian/modules/nginx-lua: + Update nginx-lua to v0.10.0. - -- Christos Trochalakis Thu, 14 Jan 2016 10:11:34 +0200 + -- Christos Trochalakis Thu, 14 Jan 2016 10:40:35 +0200 nginx (1.9.6-2) unstable; urgency=medium diff --git a/debian/nginx-common.NEWS b/debian/nginx-common.NEWS index a72049d..3d06e67 100644 --- a/debian/nginx-common.NEWS +++ b/debian/nginx-common.NEWS @@ -1,4 +1,4 @@ -nginx-common (1.9.9-1) UNRELEASED; urgency=medium +nginx-common (1.9.9-1) unstable; urgency=medium Starting with this release we are changing the default logrotate rule to keep daily logs for 14 days, this aligns our policy with apache2 (Bug #805322). From 647d381b13d22aee80f29ee9dd88ca453f49735a Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Tue, 26 Jan 2016 19:42:15 +0200 Subject: [PATCH 025/600] Imported Upstream version 1.9.10 --- CHANGES | 30 +++ CHANGES.ru | 36 ++- LICENSE | 4 +- src/core/nginx.c | 43 +++- src/core/nginx.h | 4 +- src/core/ngx_cycle.h | 1 + src/core/ngx_resolver.c | 234 ++++++++++-------- src/core/ngx_resolver.h | 15 +- .../ngx_http_upstream_keepalive_module.c | 4 + src/http/ngx_http.c | 1 + src/http/ngx_http_request_body.c | 6 - src/http/ngx_http_upstream.c | 4 + src/http/ngx_http_upstream.h | 1 + 13 files changed, 263 insertions(+), 120 deletions(-) diff --git a/CHANGES b/CHANGES index 267669b..3827f90 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,34 @@ +Changes with nginx 1.9.10 26 Jan 2016 + + *) Security: invalid pointer dereference might occur during DNS server + response processing if the "resolver" directive was used, allowing an + attacker who is able to forge UDP packets from the DNS server to + cause segmentation fault in a worker process (CVE-2016-0742). + + *) Security: use-after-free condition might occur during CNAME response + processing if the "resolver" directive was used, allowing an attacker + who is able to trigger name resolution to cause segmentation fault in + a worker process, or might have potential other impact + (CVE-2016-0746). + + *) Security: CNAME resolution was insufficiently limited if the + "resolver" directive was used, allowing an attacker who is able to + trigger arbitrary name resolution to cause excessive resource + consumption in worker processes (CVE-2016-0747). + + *) Feature: the "auto" parameter of the "worker_cpu_affinity" directive. + + *) Bugfix: the "proxy_protocol" parameter of the "listen" directive did + not work with IPv6 listen sockets. + + *) Bugfix: connections to upstream servers might be cached incorrectly + when using the "keepalive" directive. + + *) Bugfix: proxying used the HTTP method of the original request after + an "X-Accel-Redirect" redirection. + + Changes with nginx 1.9.9 09 Dec 2015 *) Bugfix: proxying to unix domain sockets did not work when using diff --git a/CHANGES.ru b/CHANGES.ru index 315013b..563163a 100644 --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,38 @@ +Изменения в nginx 1.9.10 26.01.2016 + + *) Безопасность: при использовании директивы resolver во время обработки + ответов DNS-сервера могло происходить разыменование некорректного + адреса, что позволяло атакующему, имеющему возможность подделывать + UDP-пакеты от DNS-сервера, вызвать segmentation fault в рабочем + процессе (CVE-2016-0742). + + *) Безопасность: при использовании директивы resolver во время обработки + CNAME-записей могло произойти обращение к ранее освобождённой памяти, + что позволяло атакующему, имеющему возможность инициировать + преобразование произвольных имён в адреса, вызвать segmentation fault + в рабочем процессе, а также потенциально могло иметь другие + последствия (CVE-2016-0746). + + *) Безопасность: при использовании директивы resolver во время обработки + CNAME-записей не во всех случаях проверялось ограничение на + максимальное количество записей в цепочке, что позволяло атакующему, + имеющему возможность инициировать преобразование произвольных имён в + адреса, вызвать чрезмерное потребление ресурсов рабочими процессами + (CVE-2016-0747). + + *) Добавление: параметр auto директивы worker_cpu_affinity. + + *) Исправление: параметр proxy_protocol директивы listen не работал с + IPv6 listen-сокетами. + + *) Исправление: при использовании директивы keepalive соединения к + бэкендам могли кэшироваться некорректно. + + *) Исправление: после перенаправления запроса с помощью X-Accel-Redirect + при проксировании использовался HTTP-метод оригинального запроса. + + Изменения в nginx 1.9.9 09.12.2015 *) Исправление: проксирование в unix domain сокеты не работало при @@ -138,7 +172,7 @@ *) Добавление: ограничение количества соединений в модуле stream. - *) Добавление: органичение скорости в модуле stream. + *) Добавление: ограничение скорости в модуле stream. *) Исправление: директива zone в блоке upstream не работала на Windows. diff --git a/LICENSE b/LICENSE index f752308..1d3d15c 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ /* - * Copyright (C) 2002-2015 Igor Sysoev - * Copyright (C) 2011-2015 Nginx, Inc. + * Copyright (C) 2002-2016 Igor Sysoev + * Copyright (C) 2011-2016 Nginx, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/src/core/nginx.c b/src/core/nginx.c index 3335587..64db381 100644 --- a/src/core/nginx.c +++ b/src/core/nginx.c @@ -961,6 +961,7 @@ ngx_core_module_create_conf(ngx_cycle_t *cycle) * ccf->pid = NULL; * ccf->oldpid = NULL; * ccf->priority = 0; + * ccf->cpu_affinity_auto = 0; * ccf->cpu_affinity_n = 0; * ccf->cpu_affinity = NULL; */ @@ -1002,7 +1003,8 @@ ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf) #if (NGX_HAVE_CPU_AFFINITY) - if (ccf->cpu_affinity_n + if (!ccf->cpu_affinity_auto + && ccf->cpu_affinity_n && ccf->cpu_affinity_n != 1 && ccf->cpu_affinity_n != (ngx_uint_t) ccf->worker_processes) { @@ -1273,7 +1275,24 @@ ngx_set_cpu_affinity(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) value = cf->args->elts; - for (n = 1; n < cf->args->nelts; n++) { + if (ngx_strcmp(value[1].data, "auto") == 0) { + + if (cf->args->nelts > 3) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid number of arguments in " + "\"worker_cpu_affinity\" directive"); + return NGX_CONF_ERROR; + } + + ccf->cpu_affinity_auto = 1; + mask[0] = (uint64_t) -1 >> (64 - ngx_min(64, ngx_ncpu)); + n = 2; + + } else { + n = 1; + } + + for ( /* void */ ; n < cf->args->nelts; n++) { if (value[n].len > 64) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, @@ -1323,6 +1342,8 @@ ngx_set_cpu_affinity(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) uint64_t ngx_get_cpu_affinity(ngx_uint_t n) { + uint64_t mask; + ngx_uint_t i; ngx_core_conf_t *ccf; ccf = (ngx_core_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, @@ -1332,6 +1353,24 @@ ngx_get_cpu_affinity(ngx_uint_t n) return 0; } + if (ccf->cpu_affinity_auto) { + mask = ccf->cpu_affinity[ccf->cpu_affinity_n - 1]; + + if (mask == 0) { + return 0; + } + + for (i = 0; /* void */ ; i++) { + if ((mask & ((uint64_t) 1 << (i % 64))) && n-- == 0) { + break; + } + + /* void */ + } + + return (uint64_t) 1 << (i % 64); + } + if (ccf->cpu_affinity_n > n) { return ccf->cpu_affinity[n]; } diff --git a/src/core/nginx.h b/src/core/nginx.h index 87a984a..0960afb 100644 --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1009009 -#define NGINX_VERSION "1.9.9" +#define nginx_version 1009010 +#define NGINX_VERSION "1.9.10" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD diff --git a/src/core/ngx_cycle.h b/src/core/ngx_cycle.h index b77c109..a730efe 100644 --- a/src/core/ngx_cycle.h +++ b/src/core/ngx_cycle.h @@ -88,6 +88,7 @@ typedef struct { int priority; + ngx_uint_t cpu_affinity_auto; ngx_uint_t cpu_affinity_n; uint64_t *cpu_affinity; diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c index 7013885..7b60abd 100644 --- a/src/core/ngx_resolver.c +++ b/src/core/ngx_resolver.c @@ -59,15 +59,15 @@ ngx_int_t ngx_udp_connect(ngx_udp_connection_t *uc); static void ngx_resolver_cleanup(void *data); static void ngx_resolver_cleanup_tree(ngx_resolver_t *r, ngx_rbtree_t *tree); static ngx_int_t ngx_resolve_name_locked(ngx_resolver_t *r, - ngx_resolver_ctx_t *ctx); + ngx_resolver_ctx_t *ctx, ngx_str_t *name); static void ngx_resolver_expire(ngx_resolver_t *r, ngx_rbtree_t *tree, ngx_queue_t *queue); static ngx_int_t ngx_resolver_send_query(ngx_resolver_t *r, ngx_resolver_node_t *rn); -static ngx_int_t ngx_resolver_create_name_query(ngx_resolver_node_t *rn, - ngx_resolver_ctx_t *ctx); -static ngx_int_t ngx_resolver_create_addr_query(ngx_resolver_node_t *rn, - ngx_resolver_ctx_t *ctx); +static ngx_int_t ngx_resolver_create_name_query(ngx_resolver_t *r, + ngx_resolver_node_t *rn, ngx_str_t *name); +static ngx_int_t ngx_resolver_create_addr_query(ngx_resolver_t *r, + ngx_resolver_node_t *rn, ngx_addr_t *addr); static void ngx_resolver_resend_handler(ngx_event_t *ev); static time_t ngx_resolver_resend(ngx_resolver_t *r, ngx_rbtree_t *tree, ngx_queue_t *queue); @@ -376,7 +376,7 @@ ngx_resolve_name(ngx_resolver_ctx_t *ctx) /* lock name mutex */ - rc = ngx_resolve_name_locked(r, ctx); + rc = ngx_resolve_name_locked(r, ctx, &ctx->name); if (rc == NGX_OK) { return NGX_OK; @@ -403,7 +403,6 @@ ngx_resolve_name(ngx_resolver_ctx_t *ctx) void ngx_resolve_name_done(ngx_resolver_ctx_t *ctx) { - uint32_t hash; ngx_resolver_t *r; ngx_resolver_ctx_t *w, **p; ngx_resolver_node_t *rn; @@ -423,11 +422,9 @@ ngx_resolve_name_done(ngx_resolver_ctx_t *ctx) /* lock name mutex */ - if (ctx->state == NGX_AGAIN) { + if (ctx->state == NGX_AGAIN || ctx->state == NGX_RESOLVE_TIMEDOUT) { - hash = ngx_crc32_short(ctx->name.data, ctx->name.len); - - rn = ngx_resolver_lookup_name(r, &ctx->name, hash); + rn = ctx->node; if (rn) { p = &rn->waiting; @@ -472,23 +469,28 @@ done: static ngx_int_t -ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx) +ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx, + ngx_str_t *name) { uint32_t hash; ngx_int_t rc; + ngx_str_t cname; ngx_uint_t naddrs; ngx_addr_t *addrs; - ngx_resolver_ctx_t *next; + ngx_resolver_ctx_t *next, *last; ngx_resolver_node_t *rn; - ngx_strlow(ctx->name.data, ctx->name.data, ctx->name.len); + ngx_strlow(name->data, name->data, name->len); - hash = ngx_crc32_short(ctx->name.data, ctx->name.len); + hash = ngx_crc32_short(name->data, name->len); - rn = ngx_resolver_lookup_name(r, &ctx->name, hash); + rn = ngx_resolver_lookup_name(r, name, hash); if (rn) { + /* ctx can be a list after NGX_RESOLVE_CNAME */ + for (last = ctx; last->next; last = last->next); + if (rn->valid >= ngx_time()) { ngx_log_debug0(NGX_LOG_DEBUG_CORE, r->log, 0, "resolve cached"); @@ -516,7 +518,7 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx) } } - ctx->next = rn->waiting; + last->next = rn->waiting; rn->waiting = NULL; /* unlock name mutex */ @@ -556,13 +558,13 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx) if (ctx->recursion++ < NGX_RESOLVER_MAX_RECURSION) { - ctx->name.len = rn->cnlen; - ctx->name.data = rn->u.cname; + cname.len = rn->cnlen; + cname.data = rn->u.cname; - return ngx_resolve_name_locked(r, ctx); + return ngx_resolve_name_locked(r, ctx, &cname); } - ctx->next = rn->waiting; + last->next = rn->waiting; rn->waiting = NULL; /* unlock name mutex */ @@ -581,10 +583,29 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx) if (rn->waiting) { - ctx->next = rn->waiting; + if (ctx->event == NULL) { + ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t)); + if (ctx->event == NULL) { + return NGX_ERROR; + } + + ctx->event->handler = ngx_resolver_timeout_handler; + ctx->event->data = ctx; + ctx->event->log = r->log; + ctx->ident = -1; + + ngx_add_timer(ctx->event, ctx->timeout); + } + + last->next = rn->waiting; rn->waiting = ctx; ctx->state = NGX_AGAIN; + do { + ctx->node = rn; + ctx = ctx->next; + } while (ctx); + return NGX_AGAIN; } @@ -623,14 +644,14 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx) return NGX_ERROR; } - rn->name = ngx_resolver_dup(r, ctx->name.data, ctx->name.len); + rn->name = ngx_resolver_dup(r, name->data, name->len); if (rn->name == NULL) { ngx_resolver_free(r, rn); return NGX_ERROR; } rn->node.key = hash; - rn->nlen = (u_short) ctx->name.len; + rn->nlen = (u_short) name->len; rn->query = NULL; #if (NGX_HAVE_INET6) rn->query6 = NULL; @@ -639,7 +660,7 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx) ngx_rbtree_insert(&r->name_rbtree, &rn->node); } - rc = ngx_resolver_create_name_query(rn, ctx); + rc = ngx_resolver_create_name_query(r, rn, name); if (rc == NGX_ERROR) { goto failed; @@ -652,8 +673,14 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx) ngx_resolver_free(r, rn->name); ngx_resolver_free(r, rn); - ctx->state = NGX_RESOLVE_NXDOMAIN; - ctx->handler(ctx); + do { + ctx->state = NGX_RESOLVE_NXDOMAIN; + next = ctx->next; + + ctx->handler(ctx); + + ctx = next; + } while (ctx); return NGX_OK; } @@ -674,9 +701,9 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx) } ctx->event->handler = ngx_resolver_timeout_handler; - ctx->event->data = rn; + ctx->event->data = ctx; ctx->event->log = r->log; - rn->ident = -1; + ctx->ident = -1; ngx_add_timer(ctx->event, ctx->timeout); } @@ -697,6 +724,11 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx) ctx->state = NGX_AGAIN; + do { + ctx->node = rn; + ctx = ctx->next; + } while (ctx); + return NGX_AGAIN; failed: @@ -804,9 +836,22 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx) if (rn->waiting) { + ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t)); + if (ctx->event == NULL) { + return NGX_ERROR; + } + + ctx->event->handler = ngx_resolver_timeout_handler; + ctx->event->data = ctx; + ctx->event->log = r->log; + ctx->ident = -1; + + ngx_add_timer(ctx->event, ctx->timeout); + ctx->next = rn->waiting; rn->waiting = ctx; ctx->state = NGX_AGAIN; + ctx->node = rn; /* unlock addr mutex */ @@ -848,7 +893,7 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx) ngx_rbtree_insert(tree, &rn->node); } - if (ngx_resolver_create_addr_query(rn, ctx) != NGX_OK) { + if (ngx_resolver_create_addr_query(r, rn, &ctx->addr) != NGX_OK) { goto failed; } @@ -867,9 +912,9 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx) } ctx->event->handler = ngx_resolver_timeout_handler; - ctx->event->data = rn; + ctx->event->data = ctx; ctx->event->log = r->log; - rn->ident = -1; + ctx->ident = -1; ngx_add_timer(ctx->event, ctx->timeout); @@ -892,6 +937,7 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx) /* unlock addr mutex */ ctx->state = NGX_AGAIN; + ctx->node = rn; return NGX_OK; @@ -922,17 +968,11 @@ failed: void ngx_resolve_addr_done(ngx_resolver_ctx_t *ctx) { - in_addr_t addr; ngx_queue_t *expire_queue; ngx_rbtree_t *tree; ngx_resolver_t *r; ngx_resolver_ctx_t *w, **p; - struct sockaddr_in *sin; ngx_resolver_node_t *rn; -#if (NGX_HAVE_INET6) - uint32_t hash; - struct sockaddr_in6 *sin6; -#endif r = ctx->resolver; @@ -959,23 +999,9 @@ ngx_resolve_addr_done(ngx_resolver_ctx_t *ctx) /* lock addr mutex */ - if (ctx->state == NGX_AGAIN) { + if (ctx->state == NGX_AGAIN || ctx->state == NGX_RESOLVE_TIMEDOUT) { - switch (ctx->addr.sockaddr->sa_family) { - -#if (NGX_HAVE_INET6) - case AF_INET6: - sin6 = (struct sockaddr_in6 *) ctx->addr.sockaddr; - hash = ngx_crc32_short(sin6->sin6_addr.s6_addr, 16); - rn = ngx_resolver_lookup_addr6(r, &sin6->sin6_addr, hash); - break; -#endif - - default: /* AF_INET */ - sin = (struct sockaddr_in *) ctx->addr.sockaddr; - addr = ntohl(sin->sin_addr.s_addr); - rn = ngx_resolver_lookup_addr(r, addr); - } + rn = ctx->node; if (rn) { p = &rn->waiting; @@ -1312,7 +1338,7 @@ ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf, size_t n) times = 0; for (q = ngx_queue_head(&r->name_resend_queue); - q != ngx_queue_sentinel(&r->name_resend_queue) || times++ < 100; + q != ngx_queue_sentinel(&r->name_resend_queue) && times++ < 100; q = ngx_queue_next(q)) { rn = ngx_queue_data(q, ngx_resolver_node_t, queue); @@ -1975,21 +2001,40 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last, ngx_queue_insert_head(&r->name_expire_queue, &rn->queue); - ctx = rn->waiting; - rn->waiting = NULL; - - if (ctx) { - ctx->name = name; - - (void) ngx_resolve_name_locked(r, ctx); - } - ngx_resolver_free(r, rn->query); rn->query = NULL; #if (NGX_HAVE_INET6) rn->query6 = NULL; #endif + ctx = rn->waiting; + rn->waiting = NULL; + + if (ctx) { + + if (ctx->recursion++ >= NGX_RESOLVER_MAX_RECURSION) { + + /* unlock name mutex */ + + do { + ctx->state = NGX_RESOLVE_NXDOMAIN; + next = ctx->next; + + ctx->handler(ctx); + + ctx = next; + } while (ctx); + + return; + } + + for (next = ctx; next; next = next->next) { + next->node = NULL; + } + + (void) ngx_resolve_name_locked(r, ctx, &name); + } + /* unlock name mutex */ return; @@ -2496,27 +2541,23 @@ ngx_resolver_rbtree_insert_addr6_value(ngx_rbtree_node_t *temp, static ngx_int_t -ngx_resolver_create_name_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx) +ngx_resolver_create_name_query(ngx_resolver_t *r, ngx_resolver_node_t *rn, + ngx_str_t *name) { u_char *p, *s; size_t len, nlen; ngx_uint_t ident; -#if (NGX_HAVE_INET6) - ngx_resolver_t *r; -#endif ngx_resolver_qs_t *qs; ngx_resolver_hdr_t *query; - nlen = ctx->name.len ? (1 + ctx->name.len + 1) : 1; + nlen = name->len ? (1 + name->len + 1) : 1; len = sizeof(ngx_resolver_hdr_t) + nlen + sizeof(ngx_resolver_qs_t); #if (NGX_HAVE_INET6) - r = ctx->resolver; - - p = ngx_resolver_alloc(ctx->resolver, r->ipv6 ? len * 2 : len); + p = ngx_resolver_alloc(r, r->ipv6 ? len * 2 : len); #else - p = ngx_resolver_alloc(ctx->resolver, len); + p = ngx_resolver_alloc(r, len); #endif if (p == NULL) { return NGX_ERROR; @@ -2535,8 +2576,8 @@ ngx_resolver_create_name_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx) ident = ngx_random(); - ngx_log_debug2(NGX_LOG_DEBUG_CORE, ctx->resolver->log, 0, - "resolve: \"%V\" A %i", &ctx->name, ident & 0xffff); + ngx_log_debug2(NGX_LOG_DEBUG_CORE, r->log, 0, + "resolve: \"%V\" A %i", name, ident & 0xffff); query->ident_hi = (u_char) ((ident >> 8) & 0xff); query->ident_lo = (u_char) (ident & 0xff); @@ -2566,11 +2607,11 @@ ngx_resolver_create_name_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx) p--; *p-- = '\0'; - if (ctx->name.len == 0) { + if (name->len == 0) { return NGX_DECLINED; } - for (s = ctx->name.data + ctx->name.len - 1; s >= ctx->name.data; s--) { + for (s = name->data + name->len - 1; s >= name->data; s--) { if (*s != '.') { *p = *s; len++; @@ -2606,8 +2647,8 @@ ngx_resolver_create_name_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx) ident = ngx_random(); - ngx_log_debug2(NGX_LOG_DEBUG_CORE, ctx->resolver->log, 0, - "resolve: \"%V\" AAAA %i", &ctx->name, ident & 0xffff); + ngx_log_debug2(NGX_LOG_DEBUG_CORE, r->log, 0, + "resolve: \"%V\" AAAA %i", name, ident & 0xffff); query->ident_hi = (u_char) ((ident >> 8) & 0xff); query->ident_lo = (u_char) (ident & 0xff); @@ -2624,11 +2665,12 @@ ngx_resolver_create_name_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx) static ngx_int_t -ngx_resolver_create_addr_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx) +ngx_resolver_create_addr_query(ngx_resolver_t *r, ngx_resolver_node_t *rn, + ngx_addr_t *addr) { u_char *p, *d; size_t len; - in_addr_t addr; + in_addr_t inaddr; ngx_int_t n; ngx_uint_t ident; ngx_resolver_hdr_t *query; @@ -2637,7 +2679,7 @@ ngx_resolver_create_addr_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx) struct sockaddr_in6 *sin6; #endif - switch (ctx->addr.sockaddr->sa_family) { + switch (addr->sockaddr->sa_family) { #if (NGX_HAVE_INET6) case AF_INET6: @@ -2654,7 +2696,7 @@ ngx_resolver_create_addr_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx) + sizeof(ngx_resolver_qs_t); } - p = ngx_resolver_alloc(ctx->resolver, len); + p = ngx_resolver_alloc(r, len); if (p == NULL) { return NGX_ERROR; } @@ -2678,11 +2720,11 @@ ngx_resolver_create_addr_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx) p += sizeof(ngx_resolver_hdr_t); - switch (ctx->addr.sockaddr->sa_family) { + switch (addr->sockaddr->sa_family) { #if (NGX_HAVE_INET6) case AF_INET6: - sin6 = (struct sockaddr_in6 *) ctx->addr.sockaddr; + sin6 = (struct sockaddr_in6 *) addr->sockaddr; for (n = 15; n >= 0; n--) { p = ngx_sprintf(p, "\1%xd\1%xd", @@ -2697,11 +2739,11 @@ ngx_resolver_create_addr_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx) default: /* AF_INET */ - sin = (struct sockaddr_in *) ctx->addr.sockaddr; - addr = ntohl(sin->sin_addr.s_addr); + sin = (struct sockaddr_in *) addr->sockaddr; + inaddr = ntohl(sin->sin_addr.s_addr); for (n = 0; n < 32; n += 8) { - d = ngx_sprintf(&p[1], "%ud", (addr >> n) & 0xff); + d = ngx_sprintf(&p[1], "%ud", (inaddr >> n) & 0xff); *p = (u_char) (d - &p[1]); p = d; } @@ -2815,21 +2857,13 @@ done: static void ngx_resolver_timeout_handler(ngx_event_t *ev) { - ngx_resolver_ctx_t *ctx, *next; - ngx_resolver_node_t *rn; + ngx_resolver_ctx_t *ctx; - rn = ev->data; - ctx = rn->waiting; - rn->waiting = NULL; + ctx = ev->data; - do { - ctx->state = NGX_RESOLVE_TIMEDOUT; - next = ctx->next; + ctx->state = NGX_RESOLVE_TIMEDOUT; - ctx->handler(ctx); - - ctx = next; - } while (ctx); + ctx->handler(ctx); } diff --git a/src/core/ngx_resolver.h b/src/core/ngx_resolver.h index d3519fb..07fa257 100644 --- a/src/core/ngx_resolver.h +++ b/src/core/ngx_resolver.h @@ -51,15 +51,11 @@ typedef void (*ngx_resolver_handler_pt)(ngx_resolver_ctx_t *ctx); typedef struct { - /* PTR: resolved name, A: name to resolve */ - u_char *name; - + ngx_rbtree_node_t node; ngx_queue_t queue; - /* event ident must be after 3 pointers as in ngx_connection_t */ - ngx_int_t ident; - - ngx_rbtree_node_t node; + /* PTR: resolved name, A: name to resolve */ + u_char *name; #if (NGX_HAVE_INET6) /* PTR: IPv6 address to resolve (IPv4 address is in rbtree node key) */ @@ -147,6 +143,9 @@ struct ngx_resolver_ctx_s { ngx_resolver_t *resolver; ngx_udp_connection_t *udp_connection; + /* event ident must be after 3 pointers as in ngx_connection_t */ + ngx_int_t ident; + ngx_int_t state; ngx_str_t name; @@ -162,6 +161,8 @@ struct ngx_resolver_ctx_s { ngx_uint_t quick; /* unsigned quick:1; */ ngx_uint_t recursion; ngx_event_t *event; + + ngx_resolver_node_t *node; }; diff --git a/src/http/modules/ngx_http_upstream_keepalive_module.c b/src/http/modules/ngx_http_upstream_keepalive_module.c index 51887b4..85bfcdb 100644 --- a/src/http/modules/ngx_http_upstream_keepalive_module.c +++ b/src/http/modules/ngx_http_upstream_keepalive_module.c @@ -302,6 +302,10 @@ ngx_http_upstream_free_keepalive_peer(ngx_peer_connection_t *pc, void *data, goto invalid; } + if (!u->request_body_sent) { + goto invalid; + } + if (ngx_terminate || ngx_exiting) { goto invalid; } diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c index d09e3f0..64af447 100644 --- a/src/http/ngx_http.c +++ b/src/http/ngx_http.c @@ -1927,6 +1927,7 @@ ngx_http_add_addrs6(ngx_conf_t *cf, ngx_http_port_t *hport, #if (NGX_HTTP_V2) addrs6[i].conf.http2 = addr[i].opt.http2; #endif + addrs6[i].conf.proxy_protocol = addr[i].opt.proxy_protocol; if (addr[i].hash.buckets == NULL && (addr[i].wc_head == NULL diff --git a/src/http/ngx_http_request_body.c b/src/http/ngx_http_request_body.c index 77e92e3..e9562c0 100644 --- a/src/http/ngx_http_request_body.c +++ b/src/http/ngx_http_request_body.c @@ -172,9 +172,6 @@ ngx_http_read_client_request_body(ngx_http_request_t *r, b->file = &rb->temp_file->file; rb->bufs = cl; - - } else { - rb->bufs = NULL; } } @@ -466,9 +463,6 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r) b->file = &rb->temp_file->file; rb->bufs = cl; - - } else { - rb->bufs = NULL; } } diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c index 6c6ee80..7f377b6 100644 --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -1441,6 +1441,7 @@ ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u) } u->request_sent = 0; + u->request_body_sent = 0; if (rc == NGX_AGAIN) { ngx_add_timer(c->write, u->conf->connect_timeout); @@ -1825,6 +1826,8 @@ ngx_http_upstream_send_request(ngx_http_request_t *r, ngx_http_upstream_t *u, /* rc == NGX_OK */ + u->request_body_sent = 1; + if (c->write->timer_set) { ngx_del_timer(c->write); } @@ -2496,6 +2499,7 @@ ngx_http_upstream_process_headers(ngx_http_request_t *r, ngx_http_upstream_t *u) if (r->method != NGX_HTTP_HEAD) { r->method = NGX_HTTP_GET; + r->method_name = ngx_http_core_get_method; } ngx_http_internal_redirect(r, &uri, &args); diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h index 8404265..4246c8a 100644 --- a/src/http/ngx_http_upstream.h +++ b/src/http/ngx_http_upstream.h @@ -370,6 +370,7 @@ struct ngx_http_upstream_s { unsigned upgrade:1; unsigned request_sent:1; + unsigned request_body_sent:1; unsigned header_sent:1; }; From e752ea86a642040d3628dbfc496003403d1429bf Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Tue, 26 Jan 2016 19:43:53 +0200 Subject: [PATCH 026/600] New upstream release (1.9.10) --- debian/changelog | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/debian/changelog b/debian/changelog index 5e94be3..14d5de7 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +nginx (1.9.10-1) UNRELEASED; urgency=medium + + [ Christos Trochalakis ] + * New upstream release (1.9.10) (Closes: #812806) + + -- Christos Trochalakis Tue, 26 Jan 2016 19:43:29 +0200 + nginx (1.9.9-1) unstable; urgency=medium [ Michael Lustfield ] From 0bcc8e5f72587e2e3ce56376a9b1343894049753 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Tue, 26 Jan 2016 20:11:10 +0200 Subject: [PATCH 027/600] Remove python from nginx-common deps, closes ##808699 ngx-conf is going to be shipped as a separate package. --- debian/changelog | 2 ++ debian/control | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index 14d5de7..9a30425 100644 --- a/debian/changelog +++ b/debian/changelog @@ -2,6 +2,8 @@ nginx (1.9.10-1) UNRELEASED; urgency=medium [ Christos Trochalakis ] * New upstream release (1.9.10) (Closes: #812806) + * debian/control: + + Drop python dependency from nginx-common. (Closes: #808699) -- Christos Trochalakis Tue, 26 Jan 2016 19:43:29 +0200 diff --git a/debian/control b/debian/control index de705d4..7c60e5f 100644 --- a/debian/control +++ b/debian/control @@ -59,7 +59,7 @@ Description: small, powerful, scalable web/proxy server - documentation Package: nginx-common Architecture: all -Depends: lsb-base (>= 3.2-14), ${misc:Depends}, python +Depends: lsb-base (>= 3.2-14), ${misc:Depends} Replaces: nginx (<< 0.8.54-4), nginx-extras (<< 0.8.54-4), nginx-full (<< 0.8.54-4), From 19d658f41b1fa17c6ac343001606702a7690982f Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Tue, 26 Jan 2016 20:12:14 +0200 Subject: [PATCH 028/600] Release 1.9.10-1 --- debian/changelog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index 9a30425..5b341ce 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,11 +1,11 @@ -nginx (1.9.10-1) UNRELEASED; urgency=medium +nginx (1.9.10-1) unstable; urgency=medium [ Christos Trochalakis ] * New upstream release (1.9.10) (Closes: #812806) * debian/control: + Drop python dependency from nginx-common. (Closes: #808699) - -- Christos Trochalakis Tue, 26 Jan 2016 19:43:29 +0200 + -- Christos Trochalakis Tue, 26 Jan 2016 20:12:06 +0200 nginx (1.9.9-1) unstable; urgency=medium From 0e20bccf292c0206de80d792ed9dc8a082d7573c Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Thu, 11 Feb 2016 15:06:14 +0200 Subject: [PATCH 029/600] Imported Upstream version 1.9.11 --- CHANGES | 12 + CHANGES.ru | 12 + auto/cc/conf | 22 + auto/cc/msvc | 6 + auto/cc/sunc | 3 + auto/init | 1 + auto/install | 24 + auto/lib/conf | 6 +- auto/lib/geoip/conf | 7 +- auto/lib/libgd/conf | 7 +- auto/lib/libxslt/conf | 13 +- auto/lib/openssl/conf | 3 +- auto/make | 209 +++- auto/module | 122 +++ auto/modules | 1092 ++++++++++++++++---- auto/options | 26 +- auto/os/darwin | 3 + auto/os/win32 | 5 + auto/sources | 356 +------ auto/summary | 1 + auto/unix | 6 +- src/core/nginx.c | 116 ++- src/core/nginx.h | 4 +- src/core/ngx_conf_file.c | 14 +- src/core/ngx_conf_file.h | 51 - src/core/ngx_core.h | 2 + src/core/ngx_cycle.c | 33 +- src/core/ngx_cycle.h | 4 + src/core/ngx_module.c | 361 +++++++ src/core/ngx_module.h | 307 ++++++ src/core/ngx_resolver.c | 876 +++++++++++++--- src/core/ngx_resolver.h | 29 +- src/event/ngx_event.c | 53 +- src/http/modules/ngx_http_rewrite_module.c | 8 +- src/http/ngx_http.c | 37 +- src/http/ngx_http_core_module.c | 28 +- src/http/ngx_http_upstream.c | 10 +- src/http/v2/ngx_http_v2.c | 25 +- src/http/v2/ngx_http_v2.h | 1 - src/http/v2/ngx_http_v2_filter_module.c | 4 +- src/mail/ngx_mail.c | 25 +- src/mail/ngx_mail_core_module.c | 20 +- src/os/unix/ngx_darwin_config.h | 2 + src/os/unix/ngx_dlopen.c | 28 + src/os/unix/ngx_dlopen.h | 31 + src/os/unix/ngx_freebsd_config.h | 2 + src/os/unix/ngx_linux_config.h | 2 + src/os/unix/ngx_posix_config.h | 5 + src/os/unix/ngx_process_cycle.c | 30 +- src/os/unix/ngx_solaris_config.h | 2 + src/stream/ngx_stream.c | 31 +- src/stream/ngx_stream_core_module.c | 8 +- src/stream/ngx_stream_upstream.c | 8 +- 53 files changed, 3116 insertions(+), 977 deletions(-) create mode 100644 auto/module create mode 100644 src/core/ngx_module.c create mode 100644 src/core/ngx_module.h create mode 100644 src/os/unix/ngx_dlopen.c create mode 100644 src/os/unix/ngx_dlopen.h diff --git a/CHANGES b/CHANGES index 3827f90..da1fa00 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,16 @@ +Changes with nginx 1.9.11 09 Feb 2016 + + *) Feature: TCP support in resolver. + + *) Feature: dynamic modules. + + *) Bugfix: the $request_length variable did not include size of request + headers when using HTTP/2. + + *) Bugfix: in the ngx_http_v2_module. + + Changes with nginx 1.9.10 26 Jan 2016 *) Security: invalid pointer dereference might occur during DNS server diff --git a/CHANGES.ru b/CHANGES.ru index 563163a..33302e2 100644 --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,16 @@ +Изменения в nginx 1.9.11 09.02.2016 + + *) Добавление: теперь resolver поддерживает TCP. + + *) Добавление: динамические модули. + + *) Исправление: при использовании HTTP/2 переменная $request_length не + учитывала размер заголовков запроса. + + *) Исправление: в модуле ngx_http_v2_module. + + Изменения в nginx 1.9.10 26.01.2016 *) Безопасность: при использовании директивы resolver во время обработки diff --git a/auto/cc/conf b/auto/cc/conf index edc6d74..35fd39c 100644 --- a/auto/cc/conf +++ b/auto/cc/conf @@ -5,12 +5,17 @@ LINK="\$(CC)" +MAIN_LINK= +MODULE_LINK="-shared" + ngx_include_opt="-I " ngx_compile_opt="-c" +ngx_pic_opt="-fPIC" ngx_objout="-o " ngx_binout="-o " ngx_objext="o" ngx_binext= +ngx_modext=".so" ngx_long_start= ngx_long_end= @@ -45,6 +50,9 @@ if test -n "$CFLAGS"; then sunc) + MAIN_LINK= + MODULE_LINK="-G" + case "$NGX_MACHINE" in i86pc) @@ -156,6 +164,20 @@ if [ "$NGX_PLATFORM" != win32 ]; then fi + ngx_feature="-Wl,-E switch" + ngx_feature_name= + ngx_feature_run=no + ngx_feature_incs= + ngx_feature_path= + ngx_feature_libs=-Wl,-E + ngx_feature_test= + . auto/feature + + if [ $ngx_found = yes ]; then + MAIN_LINK="-Wl,-E" + fi + + ngx_feature="gcc builtin atomic operations" ngx_feature_name=NGX_HAVE_GCC_ATOMIC ngx_feature_run=yes diff --git a/auto/cc/msvc b/auto/cc/msvc index 393ba32..e588c48 100644 --- a/auto/cc/msvc +++ b/auto/cc/msvc @@ -118,6 +118,12 @@ NGX_RCC="rc -fo$NGX_RES \$(CORE_INCS) $NGX_WIN32_RC" CORE_LINK="$NGX_RES $CORE_LINK" +# dynamic modules +#MAIN_LINK="-link -def:$NGX_OBJS/nginx.def" +#MODULE_LINK="-LD $NGX_OBJS/nginx.lib" + + +ngx_pic_opt= ngx_objout="-Fo" ngx_binout="-Fe" ngx_objext="obj" diff --git a/auto/cc/sunc b/auto/cc/sunc index 8f12d7c..8360c49 100644 --- a/auto/cc/sunc +++ b/auto/cc/sunc @@ -57,6 +57,9 @@ case "$NGX_MACHINE" in esac +MAIN_LINK= +MODULE_LINK="-G" + # optimizations diff --git a/auto/init b/auto/init index 910f529..c593eda 100644 --- a/auto/init +++ b/auto/init @@ -5,6 +5,7 @@ NGX_MAKEFILE=$NGX_OBJS/Makefile NGX_MODULES_C=$NGX_OBJS/ngx_modules.c +NGX_MODULES= NGX_AUTO_HEADERS_H=$NGX_OBJS/ngx_auto_headers.h NGX_AUTO_CONFIG_H=$NGX_OBJS/ngx_auto_config.h diff --git a/auto/install b/auto/install index f7f686c..4dcc743 100644 --- a/auto/install +++ b/auto/install @@ -26,6 +26,18 @@ case ".$NGX_SBIN_PATH" in esac +case ".$NGX_MODULES_PATH" in + ./*) + ;; + + *) + NGX_MODULES_PATH=$NGX_PREFIX/$NGX_MODULES_PATH + ;; +esac + +NGX_MODULES_PATH=`dirname $NGX_MODULES_PATH/.` + + case ".$NGX_CONF_PATH" in ./*) ;; @@ -158,12 +170,24 @@ END fi +if test -n "$NGX_MODULES"; then + cat << END >> $NGX_MAKEFILE + + test -d '\$(DESTDIR)$NGX_MODULES_PATH' \ + || mkdir -p '\$(DESTDIR)$NGX_MODULES_PATH' + cp $NGX_MODULES '\$(DESTDIR)$NGX_MODULES_PATH' +END + +fi + + # create Makefile cat << END >> Makefile build: \$(MAKE) -f $NGX_MAKEFILE + \$(MAKE) -f $NGX_MAKEFILE modules \$(MAKE) -f $NGX_MAKEFILE manpage install: diff --git a/auto/lib/conf b/auto/lib/conf index e1e4475..6aaa43a 100644 --- a/auto/lib/conf +++ b/auto/lib/conf @@ -58,11 +58,11 @@ if [ $USE_ZLIB = YES ]; then . auto/lib/zlib/conf fi -if [ $USE_LIBXSLT = YES ]; then +if [ $USE_LIBXSLT != NO ]; then . auto/lib/libxslt/conf fi -if [ $USE_LIBGD = YES ]; then +if [ $USE_LIBGD != NO ]; then . auto/lib/libgd/conf fi @@ -70,7 +70,7 @@ if [ $USE_PERL = YES ]; then . auto/lib/perl/conf fi -if [ $HTTP_GEOIP = YES ]; then +if [ $USE_GEOIP != NO ]; then . auto/lib/geoip/conf fi diff --git a/auto/lib/geoip/conf b/auto/lib/geoip/conf index 53c274d..ebd2e15 100644 --- a/auto/lib/geoip/conf +++ b/auto/lib/geoip/conf @@ -67,7 +67,12 @@ fi if [ $ngx_found = yes ]; then CORE_INCS="$CORE_INCS $ngx_feature_path" - CORE_LIBS="$CORE_LIBS $ngx_feature_libs" + + if [ $USE_GEOIP = YES ]; then + CORE_LIBS="$CORE_LIBS $ngx_feature_libs" + fi + + NGX_LIB_GEOIP=$ngx_feature_libs if [ $NGX_IPV6 = YES ]; then ngx_feature="GeoIP IPv6 support" diff --git a/auto/lib/libgd/conf b/auto/lib/libgd/conf index ff99054..6e4e91c 100644 --- a/auto/lib/libgd/conf +++ b/auto/lib/libgd/conf @@ -67,7 +67,12 @@ fi if [ $ngx_found = yes ]; then CORE_INCS="$CORE_INCS $ngx_feature_path" - CORE_LIBS="$CORE_LIBS $ngx_feature_libs" + + if [ $USE_LIBGD = YES ]; then + CORE_LIBS="$CORE_LIBS $ngx_feature_libs" + fi + + NGX_LIB_LIBGD=$ngx_feature_libs else diff --git a/auto/lib/libxslt/conf b/auto/lib/libxslt/conf index bc19d83..3a0f37b 100644 --- a/auto/lib/libxslt/conf +++ b/auto/lib/libxslt/conf @@ -76,7 +76,12 @@ fi if [ $ngx_found = yes ]; then CORE_INCS="$CORE_INCS $ngx_feature_path" - CORE_LIBS="$CORE_LIBS $ngx_feature_libs" + + if [ $USE_LIBXSLT = YES ]; then + CORE_LIBS="$CORE_LIBS $ngx_feature_libs" + fi + + NGX_LIB_LIBXSLT=$ngx_feature_libs else @@ -152,5 +157,9 @@ fi if [ $ngx_found = yes ]; then - CORE_LIBS="$CORE_LIBS -lexslt" + if [ $USE_LIBXSLT = YES ]; then + CORE_LIBS="$CORE_LIBS -lexslt" + fi + + NGX_LIB_LIBXSLT="$NGX_LIB_LIBXSLT -lexslt" fi diff --git a/auto/lib/openssl/conf b/auto/lib/openssl/conf index 28a99b2..2187e5c 100644 --- a/auto/lib/openssl/conf +++ b/auto/lib/openssl/conf @@ -32,7 +32,6 @@ if [ $OPENSSL != NONE ]; then CORE_DEPS="$CORE_DEPS $OPENSSL/.openssl/include/openssl/ssl.h" CORE_LIBS="$CORE_LIBS $OPENSSL/.openssl/lib/libssl.a" CORE_LIBS="$CORE_LIBS $OPENSSL/.openssl/lib/libcrypto.a" - CORE_LIBS="$CORE_LIBS $NGX_LIBDL" if [ "$NGX_PLATFORM" = win32 ]; then CORE_LIBS="$CORE_LIBS -lgdi32 -lcrypt32 -lws2_32" @@ -106,7 +105,7 @@ else if [ $ngx_found = yes ]; then have=NGX_SSL . auto/have CORE_INCS="$CORE_INCS $ngx_feature_path" - CORE_LIBS="$CORE_LIBS $ngx_feature_libs $NGX_LIBDL" + CORE_LIBS="$CORE_LIBS $ngx_feature_libs" OPENSSL=YES fi fi diff --git a/auto/make b/auto/make index dca011c..039a70f 100644 --- a/auto/make +++ b/auto/make @@ -98,9 +98,11 @@ fi # the mail dependencies and include paths -if [ $MAIL = YES ]; then +if [ $MAIL != NO ]; then - ngx_all_srcs="$ngx_all_srcs $MAIL_SRCS" + if [ $MAIL = YES ]; then + ngx_all_srcs="$ngx_all_srcs $MAIL_SRCS" + fi ngx_deps=`echo $MAIL_DEPS \ | sed -e "s/ *\([^ ][^ ]*\)/$ngx_regex_cont\1/g" \ @@ -124,9 +126,11 @@ fi # the stream dependencies and include paths -if [ $STREAM = YES ]; then +if [ $STREAM != NO ]; then - ngx_all_srcs="$ngx_all_srcs $STREAM_SRCS" + if [ $STREAM = YES ]; then + ngx_all_srcs="$ngx_all_srcs $STREAM_SRCS" + fi ngx_deps=`echo $STREAM_DEPS \ | sed -e "s/ *\([^ ][^ ]*\)/$ngx_regex_cont\1/g" \ @@ -148,7 +152,7 @@ END fi -ngx_all_srcs="$ngx_all_srcs $NGX_MISC_SRCS" +ngx_all_srcs="$ngx_all_srcs $MISC_SRCS" if test -n "$NGX_ADDON_SRCS"; then @@ -204,6 +208,7 @@ ngx_objs=`echo $ngx_all_objs $ngx_modules_obj \ | sed -e "s/ *\([^ ][^ ]*\)/$ngx_long_regex_cont\1/g" \ -e "s/\//$ngx_regex_dirsep/g"` +ngx_libs= if test -n "$NGX_LD_OPT$CORE_LIBS"; then ngx_libs=`echo $NGX_LD_OPT $CORE_LIBS \ | sed -e "s/\//$ngx_regex_dirsep/g" -e "s/^/$ngx_long_regex_cont/"` @@ -212,13 +217,18 @@ fi ngx_link=${CORE_LINK:+`echo $CORE_LINK \ | sed -e "s/\//$ngx_regex_dirsep/g" -e "s/^/$ngx_long_regex_cont/"`} +ngx_main_link=${MAIN_LINK:+`echo $MAIN_LINK \ + | sed -e "s/\//$ngx_regex_dirsep/g" -e "s/^/$ngx_long_regex_cont/"`} + cat << END >> $NGX_MAKEFILE $NGX_OBJS${ngx_dirsep}nginx${ngx_binext}: $ngx_deps$ngx_spacer - \$(LINK) ${ngx_long_start}${ngx_binout}$NGX_OBJS${ngx_dirsep}nginx$ngx_long_cont$ngx_objs$ngx_libs$ngx_link + \$(LINK) ${ngx_long_start}${ngx_binout}$NGX_OBJS${ngx_dirsep}nginx$ngx_long_cont$ngx_objs$ngx_libs$ngx_link$ngx_main_link $ngx_rcc ${ngx_long_end} + +modules: END @@ -365,11 +375,11 @@ fi # the misc sources -if test -n "$NGX_MISC_SRCS"; then +if test -n "$MISC_SRCS"; then ngx_cc="\$(CC) $ngx_compile_opt \$(CFLAGS) $ngx_use_pch \$(ALL_INCS)" - for ngx_src in $NGX_MISC_SRCS + for ngx_src in $MISC_SRCS do ngx_src=`echo $ngx_src | sed -e "s/\//$ngx_regex_dirsep/g"` ngx_obj=`echo $ngx_src \ @@ -472,3 +482,186 @@ $ngx_pch END fi + + +# dynamic modules + +if test -n "$NGX_PCH"; then + ngx_cc="\$(CC) $ngx_compile_opt $ngx_pic_opt \$(CFLAGS) $ngx_use_pch \$(ALL_INCS)" +else + ngx_cc="\$(CC) $ngx_compile_opt $ngx_pic_opt \$(CFLAGS) \$(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" + eval eval ngx_module_libs="\\\"\$${ngx_module}_LIBS\\\"" + + eval ngx_module_modules="\$${ngx_module}_MODULES" + eval ngx_module_order="\$${ngx_module}_ORDER" + + ngx_modules_c=$NGX_OBJS/${ngx_module}_modules.c + + cat << END > $ngx_modules_c + +#include +#include + +END + + for mod in $ngx_module_modules + do + echo "extern ngx_module_t $mod;" >> $ngx_modules_c + done + + echo >> $ngx_modules_c + echo 'ngx_module_t *ngx_modules[] = {' >> $ngx_modules_c + + for mod in $ngx_module_modules + do + echo " &$mod," >> $ngx_modules_c + done + + cat << END >> $ngx_modules_c + NULL +}; + +END + + echo 'char *ngx_module_names[] = {' >> $ngx_modules_c + + for mod in $ngx_module_modules + do + echo " \"$mod\"," >> $ngx_modules_c + done + + cat << END >> $ngx_modules_c + NULL +}; + +END + + echo 'char *ngx_module_order[] = {' >> $ngx_modules_c + + for mod in $ngx_module_order + do + echo " \"$mod\"," >> $ngx_modules_c + done + + cat << END >> $ngx_modules_c + NULL +}; + +END + + ngx_modules_c=`echo $ngx_modules_c | sed -e "s/\//$ngx_regex_dirsep/g"` + + ngx_modules_obj=`echo $ngx_modules_c \ + | sed -e "s/\(.*\.\)c/\1$ngx_objext/"` + + ngx_module_objs= + for ngx_src in $ngx_module_srcs + do + case "$ngx_src" in + src/*) + ngx_obj=$ngx_src + ;; + *) + ngx_obj="addon/`basename \`dirname $ngx_src\``" + mkdir -p $NGX_OBJS/$ngx_obj + ngx_obj="$ngx_obj/`basename $ngx_src`" + ;; + esac + + ngx_module_objs="$ngx_module_objs $ngx_obj" + done + + ngx_module_objs=`echo $ngx_module_objs \ + | sed -e "s#\([^ ]*\.\)cpp#$NGX_OBJS\/\1$ngx_objext#g" \ + -e "s#\([^ ]*\.\)cc#$NGX_OBJS\/\1$ngx_objext#g" \ + -e "s#\([^ ]*\.\)c#$NGX_OBJS\/\1$ngx_objext#g" \ + -e "s#\([^ ]*\.\)S#$NGX_OBJS\/\1$ngx_objext#g"` + + ngx_deps=`echo $ngx_module_objs $ngx_modules_obj $LINK_DEPS \ + | sed -e "s/ *\([^ ][^ ]*\)/$ngx_regex_cont\1/g" \ + -e "s/\//$ngx_regex_dirsep/g"` + + ngx_objs=`echo $ngx_module_objs $ngx_modules_obj \ + | sed -e "s/ *\([^ ][^ ]*\)/$ngx_long_regex_cont\1/g" \ + -e "s/\//$ngx_regex_dirsep/g"` + + ngx_obj=$NGX_OBJS${ngx_dirsep}${ngx_module}${ngx_modext} + + NGX_MODULES="$NGX_MODULES $ngx_obj" + + if [ "$NGX_PLATFORM" = win32 ]; then + ngx_module_libs="$CORE_LIBS $ngx_module_libs" + fi + + ngx_libs= + if test -n "$NGX_LD_OPT$ngx_module_libs"; then + ngx_libs=`echo $NGX_LD_OPT $ngx_module_libs \ + | sed -e "s/\//$ngx_regex_dirsep/g" -e "s/^/$ngx_long_regex_cont/"` + fi + + ngx_link=${CORE_LINK:+`echo $CORE_LINK \ + | sed -e "s/\//$ngx_regex_dirsep/g" -e "s/^/$ngx_long_regex_cont/"`} + + ngx_module_link=${MODULE_LINK:+`echo $MODULE_LINK \ + | sed -e "s/\//$ngx_regex_dirsep/g" -e "s/^/$ngx_long_regex_cont/"`} + + + cat << END >> $NGX_MAKEFILE + +modules: $ngx_obj + +$ngx_obj: $ngx_deps$ngx_spacer + \$(LINK) $ngx_long_start$ngx_binout$ngx_obj$ngx_long_cont$ngx_objs$ngx_libs$ngx_link$ngx_module_link +$ngx_long_end + +$ngx_modules_obj: \$(CORE_DEPS)$ngx_cont$ngx_modules_c + $ngx_cc$ngx_tab$ngx_objout$ngx_modules_obj$ngx_tab$ngx_modules_c$NGX_AUX + +END + + for ngx_src in $ngx_module_srcs + do + case "$ngx_src" in + src/*) + ngx_obj=`echo $ngx_src | sed -e "s/\//$ngx_regex_dirsep/g"` + ;; + *) + ngx_obj="addon/`basename \`dirname $ngx_src\``" + ngx_obj=`echo $ngx_obj/\`basename $ngx_src\` \ + | sed -e "s/\//$ngx_regex_dirsep/g"` + ;; + esac + + ngx_obj=`echo $ngx_obj \ + | sed -e "s#^\(.*\.\)cpp\\$#$ngx_objs_dir\1$ngx_objext#g" \ + -e "s#^\(.*\.\)cc\\$#$ngx_objs_dir\1$ngx_objext#g" \ + -e "s#^\(.*\.\)c\\$#$ngx_objs_dir\1$ngx_objext#g" \ + -e "s#^\(.*\.\)S\\$#$ngx_objs_dir\1$ngx_objext#g"` + + ngx_src=`echo $ngx_src | sed -e "s/\//$ngx_regex_dirsep/g"` + + cat << END >> $NGX_MAKEFILE + +$ngx_obj: $ngx_obj_deps$ngx_cont$ngx_src + $ngx_cc$ngx_tab$ngx_objout$ngx_obj$ngx_tab$ngx_src$NGX_AUX + +END + + done +done diff --git a/auto/module b/auto/module new file mode 100644 index 0000000..908f0c6 --- /dev/null +++ b/auto/module @@ -0,0 +1,122 @@ + +# Copyright (C) Ruslan Ermilov +# Copyright (C) Nginx, Inc. + + +case $ngx_module_type in + HTTP_*) ngx_var=HTTP ;; + *) ngx_var=$ngx_module_type ;; +esac + + +if [ "$ngx_module_link" = DYNAMIC ]; then + + for ngx_module in $ngx_module_name; do + # extract the first name + break + done + + DYNAMIC_MODULES="$DYNAMIC_MODULES $ngx_module" + eval ${ngx_module}_SRCS=\"$ngx_module_srcs\" + + eval ${ngx_module}_MODULES=\"$ngx_module_name\" + + if [ -z "$ngx_module_order" -a \ + \( "$ngx_module_type" = "HTTP_FILTER" \ + -o "$ngx_module_type" = "HTTP_AUX_FILTER" \) ] + then + eval ${ngx_module}_ORDER=\"$ngx_module_name \ + ngx_http_copy_filter_module\" + else + eval ${ngx_module}_ORDER=\"$ngx_module_order\" + fi + + if test -n "$ngx_module_incs"; then + CORE_INCS="$CORE_INCS $ngx_module_incs" + fi + + libs= + for lib in $ngx_module_libs + do + case $lib in + + LIBXSLT | LIBGD | GEOIP) + libs="$libs \$NGX_LIB_$lib" + + if eval [ "\$USE_${lib}" = NO ] ; then + eval USE_${lib}=DYNAMIC + fi + ;; + + PCRE | OPENSSL | MD5 | SHA1 | ZLIB | PERL) + eval USE_${lib}=YES + ;; + + *) + libs="$libs $lib" + ;; + + esac + done + eval ${ngx_module}_LIBS=\'$libs\' + +elif [ "$ngx_module_link" = YES ]; then + + eval ${ngx_module_type}_MODULES=\"\$${ngx_module_type}_MODULES \ + $ngx_module_name\" + + eval ${ngx_var}_SRCS=\"\$${ngx_var}_SRCS $ngx_module_srcs\" + + if test -n "$ngx_module_incs"; then + eval ${ngx_var}_INCS=\"\$${ngx_var}_INCS $ngx_module_incs\" + fi + + if test -n "$ngx_module_deps"; then + eval ${ngx_var}_DEPS=\"\$${ngx_var}_DEPS $ngx_module_deps\" + fi + + for lib in $ngx_module_libs + do + case $lib in + + PCRE | OPENSSL | MD5 | SHA1 | ZLIB | LIBXSLT | LIBGD | PERL | GEOIP) + eval USE_${lib}=YES + ;; + + *) + CORE_LIBS="$CORE_LIBS $lib" + ;; + + esac + done + +elif [ "$ngx_module_link" = ADDON ]; then + + eval ${ngx_module_type}_MODULES=\"\$${ngx_module_type}_MODULES \ + $ngx_module_name\" + + NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_module_srcs" + + if test -n "$ngx_module_incs"; then + eval ${ngx_var}_INCS=\"\$${ngx_var}_INCS $ngx_module_incs\" + fi + + if test -n "$ngx_module_deps"; then + NGX_ADDON_DEPS="$NGX_ADDON_DEPS $ngx_module_deps" + fi + + for lib in $ngx_module_libs + do + case $lib in + + PCRE | OPENSSL | MD5 | SHA1 | ZLIB | LIBXSLT | LIBGD | PERL | GEOIP) + eval USE_${lib}=YES + ;; + + *) + CORE_LIBS="$CORE_LIBS $lib" + ;; + + esac + done +fi diff --git a/auto/modules b/auto/modules index b2d2ee4..2074778 100644 --- a/auto/modules +++ b/auto/modules @@ -55,6 +55,45 @@ if [ $NGX_TEST_BUILD_SOLARIS_SENDFILEV = YES ]; then fi +HTTP_MODULES= +HTTP_DEPS= +HTTP_INCS= + +ngx_module_type=HTTP + +if :; then + ngx_module_name="ngx_http_module \ + ngx_http_core_module \ + ngx_http_log_module \ + ngx_http_upstream_module" + ngx_module_incs="src/http src/http/modules" + ngx_module_deps="src/http/ngx_http.h \ + src/http/ngx_http_request.h \ + src/http/ngx_http_config.h \ + src/http/ngx_http_core_module.h \ + src/http/ngx_http_cache.h \ + src/http/ngx_http_variables.h \ + src/http/ngx_http_script.h \ + src/http/ngx_http_upstream.h \ + src/http/ngx_http_upstream_round_robin.h" + ngx_module_srcs="src/http/ngx_http.c \ + src/http/ngx_http_core_module.c \ + src/http/ngx_http_special_response.c \ + src/http/ngx_http_request.c \ + src/http/ngx_http_parse.c \ + src/http/modules/ngx_http_log_module.c \ + src/http/ngx_http_request_body.c \ + src/http/ngx_http_variables.c \ + src/http/ngx_http_script.c \ + src/http/ngx_http_upstream.c \ + src/http/ngx_http_upstream_round_robin.c" + ngx_module_libs= + ngx_module_link=YES + + . auto/module +fi + + if [ $HTTP != YES ]; then have=NGX_CRYPT . auto/nohave CRYPT_LIB= @@ -117,297 +156,903 @@ fi # ngx_http_not_modified_filter # ngx_http_slice_filter -HTTP_FILTER_MODULES="$HTTP_WRITE_FILTER_MODULE \ - $HTTP_HEADER_FILTER_MODULE \ - $HTTP_CHUNKED_FILTER_MODULE" +ngx_module_type=HTTP_FILTER +HTTP_FILTER_MODULES= -if [ $HTTP_V2 = YES ]; then - HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_V2_FILTER_MODULE" +ngx_module_order="ngx_http_static_module \ + ngx_http_gzip_static_module \ + ngx_http_dav_module \ + ngx_http_autoindex_module \ + ngx_http_index_module \ + ngx_http_random_index_module \ + ngx_http_access_module \ + ngx_http_realip_module \ + ngx_http_write_filter_module \ + ngx_http_header_filter_module \ + ngx_http_chunked_filter_module \ + ngx_http_v2_filter_module \ + ngx_http_range_header_filter_module \ + ngx_http_gzip_filter_module \ + ngx_http_postpone_filter_module \ + ngx_http_ssi_filter_module \ + ngx_http_charset_filter_module \ + ngx_http_xslt_filter_module \ + ngx_http_image_filter_module \ + ngx_http_sub_filter_module \ + ngx_http_addition_filter_module \ + ngx_http_gunzip_filter_module \ + ngx_http_userid_filter_module \ + ngx_http_headers_filter_module \ + ngx_http_copy_filter_module \ + ngx_http_range_body_filter_module \ + ngx_http_not_modified_filter_module \ + ngx_http_slice_filter_module" + +if :; then + ngx_module_name=ngx_http_write_filter_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/ngx_http_write_filter_module.c + ngx_module_libs= + ngx_module_link=YES + + . auto/module fi -HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_RANGE_HEADER_FILTER_MODULE" +if :; then + ngx_module_name=ngx_http_header_filter_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/ngx_http_header_filter_module.c + ngx_module_libs= + ngx_module_link=YES + + . auto/module +fi + +if :; then + ngx_module_name=ngx_http_chunked_filter_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_chunked_filter_module.c + ngx_module_libs= + ngx_module_link=YES + + . auto/module +fi + +if [ $HTTP_V2 = YES ]; then + ngx_module_name=ngx_http_v2_filter_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/v2/ngx_http_v2_filter_module.c + ngx_module_libs= + ngx_module_link=$HTTP_V2 + + . auto/module +fi + +if :; then + ngx_module_name=ngx_http_range_header_filter_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_range_filter_module.c + ngx_module_libs= + ngx_module_link=YES + + . auto/module +fi if [ $HTTP_GZIP = YES ]; then have=NGX_HTTP_GZIP . auto/have USE_ZLIB=YES - HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_GZIP_FILTER_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_GZIP_SRCS" + + ngx_module_name=ngx_http_gzip_filter_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_gzip_filter_module.c + ngx_module_libs= + ngx_module_link=$HTTP_GZIP + + . auto/module fi if [ $HTTP_POSTPONE = YES ]; then - HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_POSTPONE_FILTER_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_POSTPONE_FILTER_SRCS" + ngx_module_name=ngx_http_postpone_filter_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/ngx_http_postpone_filter_module.c + ngx_module_libs= + ngx_module_link=$HTTP_POSTPONE + + . auto/module fi if [ $HTTP_SSI = YES ]; then have=NGX_HTTP_SSI . auto/have - HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_SSI_FILTER_MODULE" - HTTP_DEPS="$HTTP_DEPS $HTTP_SSI_DEPS" - HTTP_SRCS="$HTTP_SRCS $HTTP_SSI_SRCS" + + ngx_module_name=ngx_http_ssi_filter_module + ngx_module_incs= + ngx_module_deps=src/http/modules/ngx_http_ssi_filter_module.h + ngx_module_srcs=src/http/modules/ngx_http_ssi_filter_module.c + ngx_module_libs= + ngx_module_link=$HTTP_SSI + + . auto/module fi if [ $HTTP_CHARSET = YES ]; then - HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_CHARSET_FILTER_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_CHARSET_SRCS" + ngx_module_name=ngx_http_charset_filter_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_charset_filter_module.c + ngx_module_libs= + ngx_module_link=$HTTP_CHARSET + + . auto/module fi -if [ $HTTP_XSLT = YES ]; then - USE_LIBXSLT=YES - HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_XSLT_FILTER_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_XSLT_SRCS" +if [ $HTTP_XSLT != NO ]; then + ngx_module_name=ngx_http_xslt_filter_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_xslt_filter_module.c + ngx_module_libs=LIBXSLT + ngx_module_link=$HTTP_XSLT + + . auto/module fi -if [ $HTTP_IMAGE_FILTER = YES ]; then - USE_LIBGD=YES - HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_IMAGE_FILTER_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_IMAGE_SRCS" +if [ $HTTP_IMAGE_FILTER != NO ]; then + ngx_module_name=ngx_http_image_filter_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_image_filter_module.c + ngx_module_libs=LIBGD + ngx_module_link=$HTTP_IMAGE_FILTER + + . auto/module fi if [ $HTTP_SUB = YES ]; then - HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_SUB_FILTER_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_SUB_SRCS" + ngx_module_name=ngx_http_sub_filter_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_sub_filter_module.c + ngx_module_libs= + ngx_module_link=$HTTP_SUB + + . auto/module fi if [ $HTTP_ADDITION = YES ]; then - HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_ADDITION_FILTER_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_ADDITION_SRCS" + ngx_module_name=ngx_http_addition_filter_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_addition_filter_module.c + ngx_module_libs= + ngx_module_link=$HTTP_ADDITION + + . auto/module fi if [ $HTTP_GUNZIP = YES ]; then have=NGX_HTTP_GZIP . auto/have USE_ZLIB=YES - HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_GUNZIP_FILTER_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_GUNZIP_SRCS" + + ngx_module_name=ngx_http_gunzip_filter_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_gunzip_filter_module.c + ngx_module_libs= + ngx_module_link=$HTTP_GUNZIP + + . auto/module fi if [ $HTTP_USERID = YES ]; then - HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_USERID_FILTER_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_USERID_SRCS" + ngx_module_name=ngx_http_userid_filter_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_userid_filter_module.c + ngx_module_libs= + ngx_module_link=$HTTP_USERID + + . auto/module +fi + +if :; then + ngx_module_name=ngx_http_headers_filter_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_headers_filter_module.c + ngx_module_libs= + ngx_module_link=YES + + . auto/module +fi + + +ngx_module_type=HTTP_INIT_FILTER +HTTP_INIT_FILTER_MODULES= + +if :; then + ngx_module_name=ngx_http_copy_filter_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/ngx_http_copy_filter_module.c + ngx_module_libs= + ngx_module_link=YES + + . auto/module +fi + +if :; then + ngx_module_name=ngx_http_range_body_filter_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs= + ngx_module_libs= + ngx_module_link=YES + + . auto/module +fi + +if :; then + ngx_module_name=ngx_http_not_modified_filter_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_not_modified_filter_module.c + ngx_module_libs= + ngx_module_link=YES + + . auto/module fi if [ $HTTP_SLICE = YES ]; then - HTTP_SRCS="$HTTP_SRCS $HTTP_SLICE_SRCS" -else - HTTP_SLICE_FILTER_MODULE="" + ngx_module_name=ngx_http_slice_filter_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_slice_filter_module.c + ngx_module_libs= + ngx_module_link=$HTTP_SLICE + + . auto/module fi +ngx_module_type=HTTP + if [ $HTTP_V2 = YES ]; then have=NGX_HTTP_V2 . auto/have - HTTP_MODULES="$HTTP_MODULES $HTTP_V2_MODULE" - HTTP_INCS="$HTTP_INCS $HTTP_V2_INCS" - HTTP_DEPS="$HTTP_DEPS $HTTP_V2_DEPS" - HTTP_SRCS="$HTTP_SRCS $HTTP_V2_SRCS" + + ngx_module_name=ngx_http_v2_module + ngx_module_incs=src/http/v2 + ngx_module_deps="src/http/v2/ngx_http_v2.h src/http/v2/ngx_http_v2_module.h" + ngx_module_srcs="src/http/v2/ngx_http_v2.c \ + src/http/v2/ngx_http_v2_table.c \ + src/http/v2/ngx_http_v2_huff_decode.c \ + src/http/v2/ngx_http_v2_huff_encode.c \ + src/http/v2/ngx_http_v2_module.c" + ngx_module_libs= + ngx_module_link=$HTTP_V2 + + . auto/module fi -HTTP_MODULES="$HTTP_MODULES $HTTP_STATIC_MODULE" +if :; then + ngx_module_name=ngx_http_static_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_static_module.c + ngx_module_libs= + ngx_module_link=YES + + . auto/module +fi if [ $HTTP_GZIP_STATIC = YES ]; then have=NGX_HTTP_GZIP . auto/have - HTTP_MODULES="$HTTP_MODULES $HTTP_GZIP_STATIC_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_GZIP_STATIC_SRCS" + + ngx_module_name=ngx_http_gzip_static_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_gzip_static_module.c + ngx_module_libs= + ngx_module_link=$HTTP_GZIP_STATIC + + . auto/module fi if [ $HTTP_DAV = YES ]; then have=NGX_HTTP_DAV . auto/have - HTTP_MODULES="$HTTP_MODULES $HTTP_DAV_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_DAV_SRCS" + + ngx_module_name=ngx_http_dav_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_dav_module.c + ngx_module_libs= + ngx_module_link=$HTTP_DAV + + . auto/module fi if [ $HTTP_AUTOINDEX = YES ]; then - HTTP_MODULES="$HTTP_MODULES $HTTP_AUTOINDEX_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_AUTOINDEX_SRCS" + ngx_module_name=ngx_http_autoindex_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_autoindex_module.c + ngx_module_libs= + ngx_module_link=$HTTP_AUTOINDEX + + . auto/module fi -HTTP_MODULES="$HTTP_MODULES $HTTP_INDEX_MODULE" +if :; then + ngx_module_name=ngx_http_index_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_index_module.c + ngx_module_libs= + ngx_module_link=YES + + . auto/module +fi if [ $HTTP_RANDOM_INDEX = YES ]; then - HTTP_MODULES="$HTTP_MODULES $HTTP_RANDOM_INDEX_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_RANDOM_INDEX_SRCS" + ngx_module_name=ngx_http_random_index_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_random_index_module.c + ngx_module_libs= + ngx_module_link=$HTTP_RANDOM_INDEX + + . auto/module fi if [ $HTTP_AUTH_REQUEST = YES ]; then - HTTP_MODULES="$HTTP_MODULES $HTTP_AUTH_REQUEST_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_AUTH_REQUEST_SRCS" + ngx_module_name=ngx_http_auth_request_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_auth_request_module.c + ngx_module_libs= + ngx_module_link=$HTTP_AUTH_REQUEST + + . auto/module fi if [ $HTTP_AUTH_BASIC = YES ]; then USE_MD5=YES USE_SHA1=YES have=NGX_CRYPT . auto/have - HTTP_MODULES="$HTTP_MODULES $HTTP_AUTH_BASIC_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_AUTH_BASIC_SRCS" + + ngx_module_name=ngx_http_auth_basic_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_auth_basic_module.c + ngx_module_libs= + ngx_module_link=$HTTP_AUTH_BASIC + + . auto/module CORE_LIBS="$CORE_LIBS $CRYPT_LIB" fi if [ $HTTP_ACCESS = YES ]; then - HTTP_MODULES="$HTTP_MODULES $HTTP_ACCESS_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_ACCESS_SRCS" + ngx_module_name=ngx_http_access_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_access_module.c + ngx_module_libs= + ngx_module_link=$HTTP_ACCESS + + . auto/module fi if [ $HTTP_LIMIT_CONN = YES ]; then - HTTP_MODULES="$HTTP_MODULES $HTTP_LIMIT_CONN_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_LIMIT_CONN_SRCS" + ngx_module_name=ngx_http_limit_conn_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_limit_conn_module.c + ngx_module_libs= + ngx_module_link=$HTTP_LIMIT_CONN + + . auto/module fi if [ $HTTP_LIMIT_REQ = YES ]; then - HTTP_MODULES="$HTTP_MODULES $HTTP_LIMIT_REQ_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_LIMIT_REQ_SRCS" + ngx_module_name=ngx_http_limit_req_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_limit_req_module.c + ngx_module_libs= + ngx_module_link=$HTTP_LIMIT_REQ + + . auto/module 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" + + ngx_module_name=ngx_http_realip_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_realip_module.c + ngx_module_libs= + ngx_module_link=$HTTP_REALIP + + . auto/module fi if [ $HTTP_STATUS = YES ]; then - HTTP_MODULES="$HTTP_MODULES $HTTP_STATUS_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_STATUS_SRCS" + ngx_module_name=ngx_http_status_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_status_module.c + ngx_module_libs= + ngx_module_link=$HTTP_STATUS + + . auto/module fi if [ $HTTP_GEO = YES ]; then have=NGX_HTTP_X_FORWARDED_FOR . auto/have - HTTP_MODULES="$HTTP_MODULES $HTTP_GEO_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_GEO_SRCS" + + ngx_module_name=ngx_http_geo_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_geo_module.c + ngx_module_libs= + ngx_module_link=$HTTP_GEO + + . auto/module fi -if [ $HTTP_GEOIP = YES ]; then +if [ $HTTP_GEOIP != NO ]; then have=NGX_HTTP_X_FORWARDED_FOR . auto/have - HTTP_MODULES="$HTTP_MODULES $HTTP_GEOIP_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_GEOIP_SRCS" + + ngx_module_name=ngx_http_geoip_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_geoip_module.c + ngx_module_libs=GEOIP + ngx_module_link=$HTTP_GEOIP + + . auto/module fi if [ $HTTP_MAP = YES ]; then - HTTP_MODULES="$HTTP_MODULES $HTTP_MAP_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_MAP_SRCS" + ngx_module_name=ngx_http_map_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_map_module.c + ngx_module_libs= + ngx_module_link=$HTTP_MAP + + . auto/module fi if [ $HTTP_SPLIT_CLIENTS = YES ]; then - HTTP_MODULES="$HTTP_MODULES $HTTP_SPLIT_CLIENTS_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_SPLIT_CLIENTS_SRCS" + ngx_module_name=ngx_http_split_clients_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_split_clients_module.c + ngx_module_libs= + ngx_module_link=$HTTP_SPLIT_CLIENTS + + . auto/module fi if [ $HTTP_REFERER = YES ]; then - HTTP_MODULES="$HTTP_MODULES $HTTP_REFERER_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_REFERER_SRCS" + ngx_module_name=ngx_http_referer_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_referer_module.c + ngx_module_libs= + ngx_module_link=$HTTP_REFERER + + . auto/module fi if [ $HTTP_REWRITE = YES -a $USE_PCRE != DISABLED ]; then USE_PCRE=YES - HTTP_MODULES="$HTTP_MODULES $HTTP_REWRITE_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_REWRITE_SRCS" + + ngx_module_name=ngx_http_rewrite_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_rewrite_module.c + ngx_module_libs= + ngx_module_link=$HTTP_REWRITE + + . auto/module fi if [ $HTTP_SSL = YES ]; then USE_OPENSSL=YES have=NGX_HTTP_SSL . auto/have - HTTP_MODULES="$HTTP_MODULES $HTTP_SSL_MODULE" - HTTP_DEPS="$HTTP_DEPS $HTTP_SSL_DEPS" - HTTP_SRCS="$HTTP_SRCS $HTTP_SSL_SRCS" + + ngx_module_name=ngx_http_ssl_module + ngx_module_incs= + ngx_module_deps=src/http/modules/ngx_http_ssl_module.h + ngx_module_srcs=src/http/modules/ngx_http_ssl_module.c + ngx_module_libs= + ngx_module_link=$HTTP_SSL + + . auto/module fi if [ $HTTP_PROXY = YES ]; then 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" - HTTP_SRCS="$HTTP_SRCS $HTTP_PROXY_SRCS" + + ngx_module_name=ngx_http_proxy_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_proxy_module.c + ngx_module_libs= + ngx_module_link=$HTTP_PROXY + + . auto/module fi if [ $HTTP_FASTCGI = YES ]; then - HTTP_MODULES="$HTTP_MODULES $HTTP_FASTCGI_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_FASTCGI_SRCS" + ngx_module_name=ngx_http_fastcgi_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_fastcgi_module.c + ngx_module_libs= + ngx_module_link=$HTTP_FASTCGI + + . auto/module fi if [ $HTTP_UWSGI = YES ]; then - HTTP_MODULES="$HTTP_MODULES $HTTP_UWSGI_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_UWSGI_SRCS" + ngx_module_name=ngx_http_uwsgi_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_uwsgi_module.c + ngx_module_libs= + ngx_module_link=$HTTP_UWSGI + + . auto/module fi if [ $HTTP_SCGI = YES ]; then - HTTP_MODULES="$HTTP_MODULES $HTTP_SCGI_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_SCGI_SRCS" + ngx_module_name=ngx_http_scgi_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_scgi_module.c + ngx_module_libs= + ngx_module_link=$HTTP_SCGI + + . auto/module fi if [ $HTTP_PERL = YES ]; then USE_PERL=YES - HTTP_MODULES="$HTTP_MODULES $HTTP_PERL_MODULE" - HTTP_INCS="$HTTP_INCS $HTTP_PERL_INCS" - HTTP_DEPS="$HTTP_DEPS $HTTP_PERL_DEPS" - HTTP_SRCS="$HTTP_SRCS $HTTP_PERL_SRCS" + + ngx_module_name=ngx_http_perl_module + ngx_module_incs=src/http/modules/perl + ngx_module_deps=src/http/modules/perl/ngx_http_perl_module.h + ngx_module_srcs=src/http/modules/perl/ngx_http_perl_module.c + ngx_module_libs= + ngx_module_link=$HTTP_PERL + + . auto/module fi if [ $HTTP_MEMCACHED = YES ]; then - HTTP_MODULES="$HTTP_MODULES $HTTP_MEMCACHED_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_MEMCACHED_SRCS" + ngx_module_name=ngx_http_memcached_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_memcached_module.c + ngx_module_libs= + ngx_module_link=$HTTP_MEMCACHED + + . auto/module fi if [ $HTTP_EMPTY_GIF = YES ]; then - HTTP_MODULES="$HTTP_MODULES $HTTP_EMPTY_GIF_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_EMPTY_GIF_SRCS" + ngx_module_name=ngx_http_empty_gif_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_empty_gif_module.c + ngx_module_libs= + ngx_module_link=$HTTP_EMPTY_GIF + + . auto/module fi if [ $HTTP_BROWSER = YES ]; then - HTTP_MODULES="$HTTP_MODULES $HTTP_BROWSER_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_BROWSER_SRCS" + ngx_module_name=ngx_http_browser_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_browser_module.c + ngx_module_libs= + ngx_module_link=$HTTP_BROWSER + + . auto/module fi if [ $HTTP_SECURE_LINK = YES ]; then USE_MD5=YES - HTTP_MODULES="$HTTP_MODULES $HTTP_SECURE_LINK_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_SECURE_LINK_SRCS" + + ngx_module_name=ngx_http_secure_link_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_secure_link_module.c + ngx_module_libs= + ngx_module_link=$HTTP_SECURE_LINK + + . auto/module fi if [ $HTTP_DEGRADATION = YES ]; then have=NGX_HTTP_DEGRADATION . auto/have - HTTP_MODULES="$HTTP_MODULES $HTTP_DEGRADATION_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_DEGRADATION_SRCS" + + ngx_module_name=ngx_http_degradation_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_degradation_module.c + ngx_module_libs= + ngx_module_link=$HTTP_DEGRADATION + + . auto/module fi if [ $HTTP_FLV = YES ]; then - HTTP_MODULES="$HTTP_MODULES $HTTP_FLV_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_FLV_SRCS" + ngx_module_name=ngx_http_flv_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_flv_module.c + ngx_module_libs= + ngx_module_link=$HTTP_FLV + + . auto/module fi if [ $HTTP_MP4 = YES ]; then - HTTP_MODULES="$HTTP_MODULES $HTTP_MP4_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_MP4_SRCS" + ngx_module_name=ngx_http_mp4_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_mp4_module.c + ngx_module_libs= + ngx_module_link=$HTTP_MP4 + + . auto/module fi if [ $HTTP_UPSTREAM_HASH = YES ]; then - HTTP_MODULES="$HTTP_MODULES $HTTP_UPSTREAM_HASH_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_UPSTREAM_HASH_SRCS" + ngx_module_name=ngx_http_upstream_hash_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_upstream_hash_module.c + ngx_module_libs= + ngx_module_link=$HTTP_UPSTREAM_HASH + + . auto/module fi if [ $HTTP_UPSTREAM_IP_HASH = YES ]; then - HTTP_MODULES="$HTTP_MODULES $HTTP_UPSTREAM_IP_HASH_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_UPSTREAM_IP_HASH_SRCS" + ngx_module_name=ngx_http_upstream_ip_hash_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_upstream_ip_hash_module.c + ngx_module_libs= + ngx_module_link=$HTTP_UPSTREAM_IP_HASH + + . auto/module 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" + ngx_module_name=ngx_http_upstream_least_conn_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_upstream_least_conn_module.c + ngx_module_libs= + ngx_module_link=$HTTP_UPSTREAM_LEAST_CONN + + . auto/module fi if [ $HTTP_UPSTREAM_KEEPALIVE = YES ]; then - HTTP_MODULES="$HTTP_MODULES $HTTP_UPSTREAM_KEEPALIVE_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_UPSTREAM_KEEPALIVE_SRCS" + ngx_module_name=ngx_http_upstream_keepalive_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_upstream_keepalive_module.c + ngx_module_libs= + ngx_module_link=$HTTP_UPSTREAM_KEEPALIVE + + . auto/module fi if [ $HTTP_UPSTREAM_ZONE = YES ]; then have=NGX_HTTP_UPSTREAM_ZONE . auto/have - HTTP_MODULES="$HTTP_MODULES $HTTP_UPSTREAM_ZONE_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_UPSTREAM_ZONE_SRCS" + + ngx_module_name=ngx_http_upstream_zone_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_upstream_zone_module.c + ngx_module_libs= + ngx_module_link=$HTTP_UPSTREAM_ZONE + + . auto/module fi if [ $HTTP_STUB_STATUS = YES ]; then have=NGX_STAT_STUB . auto/have - HTTP_MODULES="$HTTP_MODULES ngx_http_stub_status_module" - HTTP_SRCS="$HTTP_SRCS src/http/modules/ngx_http_stub_status_module.c" + + ngx_module_name=ngx_http_stub_status_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_stub_status_module.c + ngx_module_libs= + ngx_module_link=$HTTP_STUB_STATUS + + . auto/module fi + +if [ $MAIL != NO ]; then + MAIL_MODULES= + MAIL_DEPS= + MAIL_INCS= + + ngx_module_type=MAIL + ngx_module_libs= + ngx_module_link=YES + + ngx_module_order= + + ngx_module_name="ngx_mail_module ngx_mail_core_module" + ngx_module_incs="src/mail" + ngx_module_deps="src/mail/ngx_mail.h" + ngx_module_srcs="src/mail/ngx_mail.c \ + src/mail/ngx_mail_core_module.c \ + src/mail/ngx_mail_handler.c \ + src/mail/ngx_mail_parse.c" + + . auto/module + + ngx_module_incs= + + if [ $MAIL_SSL = YES ]; then + USE_OPENSSL=YES + have=NGX_MAIL_SSL . auto/have + + ngx_module_name=ngx_mail_ssl_module + ngx_module_deps=src/mail/ngx_mail_ssl_module.h + ngx_module_srcs=src/mail/ngx_mail_ssl_module.c + + . auto/module + fi + + if [ $MAIL_POP3 = YES ]; then + ngx_module_name=ngx_mail_pop3_module + ngx_module_deps=src/mail/ngx_mail_pop3_module.h + ngx_module_srcs="src/mail/ngx_mail_pop3_module.c \ + src/mail/ngx_mail_pop3_handler.c" + + . auto/module + fi + + if [ $MAIL_IMAP = YES ]; then + ngx_module_name=ngx_mail_imap_module + ngx_module_deps=src/mail/ngx_mail_imap_module.h + ngx_module_srcs="src/mail/ngx_mail_imap_module.c \ + src/mail/ngx_mail_imap_handler.c" + + . auto/module + fi + + if [ $MAIL_SMTP = YES ]; then + ngx_module_name=ngx_mail_smtp_module + ngx_module_deps=src/mail/ngx_mail_smtp_module.h + ngx_module_srcs="src/mail/ngx_mail_smtp_module.c \ + src/mail/ngx_mail_smtp_handler.c" + + . auto/module + fi + + ngx_module_name=ngx_mail_auth_http_module + ngx_module_deps= + ngx_module_srcs=src/mail/ngx_mail_auth_http_module.c + + . auto/module + + ngx_module_name=ngx_mail_proxy_module + ngx_module_deps= + ngx_module_srcs=src/mail/ngx_mail_proxy_module.c + + . auto/module +fi + + +if [ $STREAM != NO ]; then + STREAM_MODULES= + STREAM_DEPS= + STREAM_INCS= + + ngx_module_type=STREAM + ngx_module_libs= + ngx_module_link=YES + + ngx_module_order= + + ngx_module_name="ngx_stream_module \ + ngx_stream_core_module \ + ngx_stream_proxy_module \ + ngx_stream_upstream_module" + ngx_module_incs="src/stream" + ngx_module_deps="src/stream/ngx_stream.h \ + src/stream/ngx_stream_upstream.h \ + src/stream/ngx_stream_upstream_round_robin.h" + ngx_module_srcs="src/stream/ngx_stream.c \ + src/stream/ngx_stream_handler.c \ + src/stream/ngx_stream_core_module.c \ + src/stream/ngx_stream_proxy_module.c \ + src/stream/ngx_stream_upstream.c \ + src/stream/ngx_stream_upstream_round_robin.c" + + . auto/module + + ngx_module_incs= + + if [ $STREAM_SSL = YES ]; then + USE_OPENSSL=YES + have=NGX_STREAM_SSL . auto/have + + ngx_module_name=ngx_stream_ssl_module + ngx_module_deps=src/stream/ngx_stream_ssl_module.h + ngx_module_srcs=src/stream/ngx_stream_ssl_module.c + + . auto/module + fi + + if [ $STREAM_LIMIT_CONN = YES ]; then + ngx_module_name=ngx_stream_limit_conn_module + ngx_module_deps= + ngx_module_srcs=src/stream/ngx_stream_limit_conn_module.c + + . auto/module + fi + + if [ $STREAM_ACCESS = YES ]; then + ngx_module_name=ngx_stream_access_module + ngx_module_deps= + ngx_module_srcs=src/stream/ngx_stream_access_module.c + + . auto/module + fi + + if [ $STREAM_UPSTREAM_HASH = YES ]; then + ngx_module_name=ngx_stream_upstream_hash_module + ngx_module_deps= + ngx_module_srcs=src/stream/ngx_stream_upstream_hash_module.c + + . auto/module + fi + + if [ $STREAM_UPSTREAM_LEAST_CONN = YES ]; then + ngx_module_name=ngx_stream_upstream_least_conn_module + ngx_module_deps= + ngx_module_srcs=src/stream/ngx_stream_upstream_least_conn_module.c + + . auto/module + fi + + if [ $STREAM_UPSTREAM_ZONE = YES ]; then + have=NGX_STREAM_UPSTREAM_ZONE . auto/have + + ngx_module_name=ngx_stream_upstream_zone_module + ngx_module_deps= + ngx_module_srcs=src/stream/ngx_stream_upstream_zone_module.c + + . auto/module + fi +fi + + #if [ -r $NGX_OBJS/auto ]; then # . $NGX_OBJS/auto #fi @@ -421,6 +1066,15 @@ if test -n "$NGX_ADDONS"; then do echo "adding module in $ngx_addon_dir" + ngx_module_type= + ngx_module_name= + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs= + ngx_module_libs= + ngx_module_order= + ngx_module_link=ADDON + if test -f $ngx_addon_dir/config; then . $ngx_addon_dir/config @@ -434,15 +1088,62 @@ if test -n "$NGX_ADDONS"; then fi -if [ $MAIL_SSL = YES ]; then - have=NGX_MAIL_SSL . auto/have - USE_OPENSSL=YES +if test -n "$DYNAMIC_ADDONS"; then + + echo configuring additional dynamic modules + + for ngx_addon_dir in $DYNAMIC_ADDONS + do + echo "adding module in $ngx_addon_dir" + + ngx_module_type= + ngx_module_name= + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs= + ngx_module_libs= + ngx_module_order= + ngx_module_link=DYNAMIC + + if test -f $ngx_addon_dir/config; then + . $ngx_addon_dir/config + + echo " + $ngx_addon_name was configured" + + else + echo "$0: error: no $ngx_addon_dir/config was found" + exit 1 + fi + done fi -if [ $STREAM_SSL = YES ]; then - have=NGX_STREAM_SSL . auto/have - USE_OPENSSL=YES +if [ $USE_OPENSSL = YES ]; then + ngx_module_type=CORE + ngx_module_name=ngx_openssl_module + ngx_module_incs= + ngx_module_deps=src/event/ngx_event_openssl.h + ngx_module_srcs="src/event/ngx_event_openssl.c + src/event/ngx_event_openssl_stapling.c" + ngx_module_libs= + ngx_module_link=YES + ngx_module_order= + + . auto/module +fi + + +if [ $USE_PCRE = YES ]; then + ngx_module_type=CORE + ngx_module_name=ngx_regex_module + ngx_module_incs= + ngx_module_deps=src/core/ngx_regex.h + ngx_module_srcs=src/core/ngx_regex.c + ngx_module_libs= + ngx_module_link=YES + ngx_module_order= + + . auto/module fi @@ -455,119 +1156,81 @@ if [ $USE_THREADS = YES ]; then fi -if [ $USE_OPENSSL = YES ]; then - modules="$modules $OPENSSL_MODULE" - CORE_DEPS="$CORE_DEPS $OPENSSL_DEPS" - CORE_SRCS="$CORE_SRCS $OPENSSL_SRCS" -fi - -if [ $USE_PCRE = YES ]; then - modules="$modules $REGEX_MODULE" - CORE_DEPS="$CORE_DEPS $REGEX_DEPS" - CORE_SRCS="$CORE_SRCS $REGEX_SRCS" -fi - if [ $HTTP = YES ]; then modules="$modules $HTTP_MODULES $HTTP_FILTER_MODULES \ - $HTTP_HEADERS_FILTER_MODULE \ - $HTTP_AUX_FILTER_MODULES \ - $HTTP_COPY_FILTER_MODULE \ - $HTTP_RANGE_BODY_FILTER_MODULE \ - $HTTP_NOT_MODIFIED_FILTER_MODULE \ - $HTTP_SLICE_FILTER_MODULE" + $HTTP_AUX_FILTER_MODULES $HTTP_INIT_FILTER_MODULES" NGX_ADDON_DEPS="$NGX_ADDON_DEPS \$(HTTP_DEPS)" fi -if [ $MAIL = YES ]; then - modules="$modules $MAIL_MODULES" +if [ $MAIL != NO ]; then - if [ $MAIL_SSL = YES ]; then - modules="$modules $MAIL_SSL_MODULE" - MAIL_DEPS="$MAIL_DEPS $MAIL_SSL_DEPS" - MAIL_SRCS="$MAIL_SRCS $MAIL_SSL_SRCS" + if [ $MAIL = YES ]; then + modules="$modules $MAIL_MODULES" + + elif [ $MAIL = DYNAMIC ]; then + ngx_module_name=$MAIL_MODULES + ngx_module_incs= + ngx_module_deps=$MAIL_DEPS + ngx_module_srcs=$MAIL_SRCS + ngx_module_libs= + ngx_module_link=DYNAMIC + + . auto/module fi - if [ $MAIL_POP3 = YES ]; then - modules="$modules $MAIL_POP3_MODULE" - MAIL_DEPS="$MAIL_DEPS $MAIL_POP3_DEPS" - MAIL_SRCS="$MAIL_SRCS $MAIL_POP3_SRCS" - fi - - if [ $MAIL_IMAP = YES ]; then - modules="$modules $MAIL_IMAP_MODULE" - MAIL_DEPS="$MAIL_DEPS $MAIL_IMAP_DEPS" - MAIL_SRCS="$MAIL_SRCS $MAIL_IMAP_SRCS" - fi - - if [ $MAIL_SMTP = YES ]; then - modules="$modules $MAIL_SMTP_MODULE" - MAIL_DEPS="$MAIL_DEPS $MAIL_SMTP_DEPS" - MAIL_SRCS="$MAIL_SRCS $MAIL_SMTP_SRCS" - fi - - modules="$modules $MAIL_AUTH_HTTP_MODULE" - MAIL_SRCS="$MAIL_SRCS $MAIL_AUTH_HTTP_SRCS" - - modules="$modules $MAIL_PROXY_MODULE" - MAIL_SRCS="$MAIL_SRCS $MAIL_PROXY_SRCS" - NGX_ADDON_DEPS="$NGX_ADDON_DEPS \$(MAIL_DEPS)" fi -if [ $STREAM = YES ]; then - have=NGX_STREAM . auto/have - modules="$modules $STREAM_MODULES" +if [ $STREAM != NO ]; then - if [ $STREAM_SSL = YES ]; then - modules="$modules $STREAM_SSL_MODULE" - STREAM_DEPS="$STREAM_DEPS $STREAM_SSL_DEPS" - STREAM_SRCS="$STREAM_SRCS $STREAM_SSL_SRCS" - fi + if [ $STREAM = YES ]; then + modules="$modules $STREAM_MODULES" - if [ $STREAM_LIMIT_CONN = YES ]; then - modules="$modules $STREAM_LIMIT_CONN_MODULE" - STREAM_SRCS="$STREAM_SRCS $STREAM_LIMIT_CONN_SRCS" - fi + elif [ $STREAM = DYNAMIC ]; then + ngx_module_name=$STREAM_MODULES + ngx_module_incs= + ngx_module_deps=$STREAM_DEPS + ngx_module_srcs=$STREAM_SRCS + ngx_module_libs= + ngx_module_link=DYNAMIC - if [ $STREAM_ACCESS = YES ]; then - modules="$modules $STREAM_ACCESS_MODULE" - STREAM_SRCS="$STREAM_SRCS $STREAM_ACCESS_SRCS" - fi - - if [ $STREAM_UPSTREAM_HASH = YES ]; then - modules="$modules $STREAM_UPSTREAM_HASH_MODULE" - STREAM_SRCS="$STREAM_SRCS $STREAM_UPSTREAM_HASH_SRCS" - fi - - if [ $STREAM_UPSTREAM_LEAST_CONN = YES ]; then - modules="$modules $STREAM_UPSTREAM_LEAST_CONN_MODULE" - STREAM_SRCS="$STREAM_SRCS $STREAM_UPSTREAM_LEAST_CONN_SRCS" - fi - - if [ $STREAM_UPSTREAM_ZONE = YES ]; then - have=NGX_STREAM_UPSTREAM_ZONE . auto/have - modules="$modules $STREAM_UPSTREAM_ZONE_MODULE" - STREAM_SRCS="$STREAM_SRCS $STREAM_UPSTREAM_ZONE_SRCS" + . auto/module fi NGX_ADDON_DEPS="$NGX_ADDON_DEPS \$(STREAM_DEPS)" fi -if [ $NGX_GOOGLE_PERFTOOLS = YES ]; then - modules="$modules $NGX_GOOGLE_PERFTOOLS_MODULE" - NGX_MISC_SRCS="$NGX_MISC_SRCS $NGX_GOOGLE_PERFTOOLS_SRCS" -fi +ngx_module_type=MISC +MISC_MODULES= +if [ $NGX_GOOGLE_PERFTOOLS = YES ]; then + ngx_module_name=ngx_google_perftools_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/misc/ngx_google_perftools_module.c + ngx_module_libs= + ngx_module_link=$NGX_GOOGLE_PERFTOOLS + + . auto/module +fi if [ $NGX_CPP_TEST = YES ]; then - NGX_MISC_SRCS="$NGX_MISC_SRCS $NGX_CPP_TEST_SRCS" - CORE_LIBS="$CORE_LIBS -lstdc++" + ngx_module_name= + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/misc/ngx_cpp_test_module.cpp + ngx_module_libs=-lstdc++ + ngx_module_link=$NGX_CPP_TEST + + . auto/module fi +modules="$modules $MISC_MODULES" + cat << END > $NGX_MODULES_C @@ -596,3 +1259,16 @@ cat << END >> $NGX_MODULES_C }; END + +echo 'char *ngx_module_names[] = {' >> $NGX_MODULES_C + +for mod in $modules +do + echo " \"$mod\"," >> $NGX_MODULES_C +done + +cat << END >> $NGX_MODULES_C + NULL +}; + +END diff --git a/auto/options b/auto/options index 931dabb..36b34bc 100644 --- a/auto/options +++ b/auto/options @@ -7,6 +7,7 @@ help=no NGX_PREFIX= NGX_SBIN_PATH= +NGX_MODULES_PATH= NGX_CONF_PREFIX= NGX_CONF_PATH= NGX_ERROR_LOG_PATH= @@ -120,7 +121,11 @@ STREAM_UPSTREAM_HASH=YES STREAM_UPSTREAM_LEAST_CONN=YES STREAM_UPSTREAM_ZONE=YES +DYNAMIC_MODULES= + NGX_ADDONS= +NGX_ADDON_DEPS= +DYNAMIC_ADDONS= USE_PCRE=NO PCRE=NONE @@ -151,6 +156,7 @@ NGX_PERL=perl USE_LIBXSLT=NO USE_LIBGD=NO +USE_GEOIP=NO NGX_GOOGLE_PERFTOOLS=NO NGX_CPP_TEST=NO @@ -178,6 +184,7 @@ do --prefix=) NGX_PREFIX="!" ;; --prefix=*) NGX_PREFIX="$value" ;; --sbin-path=*) NGX_SBIN_PATH="$value" ;; + --modules-path=*) NGX_MODULES_PATH="$value" ;; --conf-path=*) NGX_CONF_PATH="$value" ;; --error-log-path=*) NGX_ERROR_LOG_PATH="$value";; --pid-path=*) NGX_PID_PATH="$value" ;; @@ -215,8 +222,13 @@ do --with-http_realip_module) HTTP_REALIP=YES ;; --with-http_addition_module) HTTP_ADDITION=YES ;; --with-http_xslt_module) HTTP_XSLT=YES ;; + --with-http_xslt_module=dynamic) HTTP_XSLT=DYNAMIC ;; --with-http_image_filter_module) HTTP_IMAGE_FILTER=YES ;; + --with-http_image_filter_module=dynamic) + HTTP_IMAGE_FILTER=DYNAMIC ;; --with-http_geoip_module) HTTP_GEOIP=YES ;; + --with-http_geoip_module=dynamic) + HTTP_GEOIP=DYNAMIC ;; --with-http_sub_module) HTTP_SUB=YES ;; --with-http_dav_module) HTTP_DAV=YES ;; --with-http_flv_module) HTTP_FLV=YES ;; @@ -266,6 +278,7 @@ do --with-http_stub_status_module) HTTP_STUB_STATUS=YES ;; --with-mail) MAIL=YES ;; + --with-mail=dynamic) MAIL=DYNAMIC ;; --with-mail_ssl_module) MAIL_SSL=YES ;; # STUB --with-imap) @@ -285,6 +298,7 @@ use the \"--with-mail_ssl_module\" option instead" --without-mail_smtp_module) MAIL_SMTP=NO ;; --with-stream) STREAM=YES ;; + --with-stream=dynamic) STREAM=DYNAMIC ;; --with-stream_ssl_module) STREAM_SSL=YES ;; --without-stream_limit_conn_module) STREAM_LIMIT_CONN=NO ;; @@ -300,6 +314,7 @@ use the \"--with-mail_ssl_module\" option instead" --with-cpp_test_module) NGX_CPP_TEST=YES ;; --add-module=*) NGX_ADDONS="$NGX_ADDONS $value" ;; + --add-dynamic-module=*) DYNAMIC_ADDONS="$DYNAMIC_ADDONS $value" ;; --with-cc=*) CC="$value" ;; --with-cpp=*) CPP="$value" ;; @@ -356,6 +371,7 @@ cat << END --prefix=PATH set installation prefix --sbin-path=PATH set nginx binary pathname + --modules-path=PATH set modules path --conf-path=PATH set nginx.conf pathname --error-log-path=PATH set error log pathname --pid-path=PATH set nginx.pid pathname @@ -384,8 +400,12 @@ cat << END --with-http_realip_module enable ngx_http_realip_module --with-http_addition_module enable ngx_http_addition_module --with-http_xslt_module enable ngx_http_xslt_module + --with-http_xslt_module=dynamic enable dynamic ngx_http_xslt_module --with-http_image_filter_module enable ngx_http_image_filter_module + --with-http_image_filter_module=dynamic + enable dynamic ngx_http_image_filter_module --with-http_geoip_module enable ngx_http_geoip_module + --with-http_geoip_module=dynamic enable dynamic ngx_http_geoip_module --with-http_sub_module enable ngx_http_sub_module --with-http_dav_module enable ngx_http_dav_module --with-http_flv_module enable ngx_http_flv_module @@ -451,12 +471,14 @@ cat << END --without-http-cache disable HTTP cache --with-mail enable POP3/IMAP4/SMTP proxy module + --with-mail=dynamic enable dynamic POP3/IMAP4/SMTP proxy module --with-mail_ssl_module enable ngx_mail_ssl_module --without-mail_pop3_module disable ngx_mail_pop3_module --without-mail_imap_module disable ngx_mail_imap_module --without-mail_smtp_module disable ngx_mail_smtp_module --with-stream enable TCP proxy module + --with-stream=dynamic enable dynamic TCP proxy module --with-stream_ssl_module enable ngx_stream_ssl_module --without-stream_limit_conn_module disable ngx_stream_limit_conn_module --without-stream_access_module disable ngx_stream_access_module @@ -470,7 +492,8 @@ cat << END --with-google_perftools_module enable ngx_google_perftools_module --with-cpp_test_module enable ngx_cpp_test_module - --add-module=PATH enable an external module + --add-module=PATH enable external module + --add-dynamic-module=PATH enable dynamic external module --with-cc=PATH set C compiler pathname --with-cpp=PATH set C preprocessor pathname @@ -533,6 +556,7 @@ fi NGX_SBIN_PATH=${NGX_SBIN_PATH:-sbin/nginx} +NGX_MODULES_PATH=${NGX_MODULES_PATH:-modules} NGX_CONF_PATH=${NGX_CONF_PATH:-conf/nginx.conf} NGX_CONF_PREFIX=`dirname $NGX_CONF_PATH` NGX_PID_PATH=${NGX_PID_PATH:-logs/nginx.pid} diff --git a/auto/os/darwin b/auto/os/darwin index 1d3e3d3..9b31b1f 100644 --- a/auto/os/darwin +++ b/auto/os/darwin @@ -14,6 +14,9 @@ CORE_SRCS="$UNIX_SRCS $DARWIN_SRCS" ngx_spacer=' ' +MAIN_LINK= +MODULE_LINK="-shared -Wl,-undefined,dynamic_lookup" + # kqueue echo " + kqueue found" diff --git a/auto/os/win32 b/auto/os/win32 index 82fc212..14ae3b8 100644 --- a/auto/os/win32 +++ b/auto/os/win32 @@ -12,10 +12,15 @@ OS_CONFIG="$WIN32_CONFIG" NGX_ICONS="$NGX_WIN32_ICONS" SELECT_SRCS=$WIN32_SELECT_SRCS +ngx_pic_opt= + case "$NGX_CC_NAME" in gcc) CORE_LIBS="$CORE_LIBS -ladvapi32 -lws2_32" + MAIN_LINK="$MAIN_LINK -Wl,--export-all-symbols" + MAIN_LINK="$MAIN_LINK -Wl,--out-implib=$NGX_OBJS/libnginx.a" + MODULE_LINK="-shared -L $NGX_OBJS -lnginx" ;; *) diff --git a/auto/sources b/auto/sources index 2e44ce1..e08e863 100644 --- a/auto/sources +++ b/auto/sources @@ -36,6 +36,7 @@ CORE_DEPS="src/core/nginx.h \ src/core/ngx_connection.h \ src/core/ngx_cycle.h \ src/core/ngx_conf_file.h \ + src/core/ngx_module.h \ src/core/ngx_resolver.h \ src/core/ngx_open_file_cache.h \ src/core/ngx_crypt.h \ @@ -71,6 +72,7 @@ CORE_SRCS="src/core/nginx.c \ src/core/ngx_rwlock.c \ src/core/ngx_cpuinfo.c \ src/core/ngx_conf_file.c \ + src/core/ngx_module.c \ src/core/ngx_resolver.c \ src/core/ngx_open_file_cache.c \ src/core/ngx_crypt.c \ @@ -78,17 +80,6 @@ CORE_SRCS="src/core/nginx.c \ src/core/ngx_syslog.c" -REGEX_MODULE=ngx_regex_module -REGEX_DEPS=src/core/ngx_regex.h -REGEX_SRCS=src/core/ngx_regex.c - - -OPENSSL_MODULE=ngx_openssl_module -OPENSSL_DEPS=src/event/ngx_event_openssl.h -OPENSSL_SRCS="src/event/ngx_event_openssl.c \ - src/event/ngx_event_openssl_stapling.c" - - EVENT_MODULES="ngx_events_module ngx_event_core_module" EVENT_INCS="src/event src/event/modules" @@ -150,6 +141,7 @@ UNIX_DEPS="$CORE_DEPS $EVENT_DEPS \ src/os/unix/ngx_socket.h \ src/os/unix/ngx_os.h \ src/os/unix/ngx_user.h \ + src/os/unix/ngx_dlopen.h \ src/os/unix/ngx_process_cycle.h" # add to UNIX_DEPS @@ -181,6 +173,7 @@ UNIX_SRCS="$CORE_SRCS $EVENT_SRCS \ src/os/unix/ngx_setproctitle.c \ src/os/unix/ngx_posix_init.c \ src/os/unix/ngx_user.c \ + src/os/unix/ngx_dlopen.c \ src/os/unix/ngx_process_cycle.c" POSIX_DEPS=src/os/unix/ngx_posix_config.h @@ -226,6 +219,7 @@ WIN32_DEPS="$CORE_DEPS $EVENT_DEPS \ src/os/win32/ngx_socket.h \ src/os/win32/ngx_os.h \ src/os/win32/ngx_user.h \ + src/os/win32/ngx_dlopen.h \ src/os/win32/ngx_process_cycle.h" WIN32_CONFIG=src/os/win32/ngx_win32_config.h @@ -246,6 +240,7 @@ WIN32_SRCS="$CORE_SRCS $EVENT_SRCS \ src/os/win32/ngx_wsasend_chain.c \ src/os/win32/ngx_win32_init.c \ src/os/win32/ngx_user.c \ + src/os/win32/ngx_dlopen.c \ src/os/win32/ngx_event_log.c \ src/os/win32/ngx_process_cycle.c \ src/event/ngx_event_acceptex.c" @@ -254,343 +249,4 @@ NGX_WIN32_ICONS="src/os/win32/nginx.ico" NGX_WIN32_RC="src/os/win32/nginx.rc" -HTTP_MODULES="ngx_http_module \ - ngx_http_core_module \ - ngx_http_log_module \ - ngx_http_upstream_module" - -HTTP_WRITE_FILTER_MODULE="ngx_http_write_filter_module" -HTTP_HEADER_FILTER_MODULE="ngx_http_header_filter_module" - -HTTP_POSTPONE_FILTER_MODULE=ngx_http_postpone_filter_module -HTTP_COPY_FILTER_MODULE=ngx_http_copy_filter_module - -HTTP_CHUNKED_FILTER_MODULE=ngx_http_chunked_filter_module -HTTP_HEADERS_FILTER_MODULE=ngx_http_headers_filter_module - -HTTP_RANGE_HEADER_FILTER_MODULE=ngx_http_range_header_filter_module -HTTP_RANGE_BODY_FILTER_MODULE=ngx_http_range_body_filter_module - -HTTP_NOT_MODIFIED_FILTER_MODULE=ngx_http_not_modified_filter_module - -HTTP_STATIC_MODULE=ngx_http_static_module -HTTP_INDEX_MODULE=ngx_http_index_module - -HTTP_INCS="src/http src/http/modules" - -HTTP_DEPS="src/http/ngx_http.h \ - src/http/ngx_http_request.h \ - src/http/ngx_http_config.h \ - src/http/ngx_http_core_module.h \ - src/http/ngx_http_cache.h \ - src/http/ngx_http_variables.h \ - src/http/ngx_http_script.h \ - src/http/ngx_http_upstream.h \ - src/http/ngx_http_upstream_round_robin.h" - -HTTP_SRCS="src/http/ngx_http.c \ - src/http/ngx_http_core_module.c \ - src/http/ngx_http_special_response.c \ - src/http/ngx_http_request.c \ - src/http/ngx_http_parse.c \ - src/http/ngx_http_header_filter_module.c \ - src/http/ngx_http_write_filter_module.c \ - src/http/ngx_http_copy_filter_module.c \ - src/http/modules/ngx_http_log_module.c \ - src/http/ngx_http_request_body.c \ - src/http/ngx_http_variables.c \ - src/http/ngx_http_script.c \ - src/http/ngx_http_upstream.c \ - src/http/ngx_http_upstream_round_robin.c \ - src/http/modules/ngx_http_static_module.c \ - src/http/modules/ngx_http_index_module.c \ - src/http/modules/ngx_http_chunked_filter_module.c \ - src/http/modules/ngx_http_range_filter_module.c \ - src/http/modules/ngx_http_headers_filter_module.c \ - src/http/modules/ngx_http_not_modified_filter_module.c" - -HTTP_POSTPONE_FILTER_SRCS=src/http/ngx_http_postpone_filter_module.c - HTTP_FILE_CACHE_SRCS=src/http/ngx_http_file_cache.c - - -HTTP_V2_MODULE=ngx_http_v2_module -HTTP_V2_FILTER_MODULE=ngx_http_v2_filter_module -HTTP_V2_INCS="src/http/v2" -HTTP_V2_DEPS="src/http/v2/ngx_http_v2.h \ - src/http/v2/ngx_http_v2_module.h" -HTTP_V2_SRCS="src/http/v2/ngx_http_v2.c \ - src/http/v2/ngx_http_v2_table.c \ - src/http/v2/ngx_http_v2_huff_decode.c \ - src/http/v2/ngx_http_v2_huff_encode.c \ - src/http/v2/ngx_http_v2_module.c \ - src/http/v2/ngx_http_v2_filter_module.c" - - -HTTP_CHARSET_FILTER_MODULE=ngx_http_charset_filter_module -HTTP_CHARSET_SRCS=src/http/modules/ngx_http_charset_filter_module.c - - -HTTP_GZIP_FILTER_MODULE=ngx_http_gzip_filter_module -HTTP_GZIP_SRCS=src/http/modules/ngx_http_gzip_filter_module.c - - -HTTP_GUNZIP_FILTER_MODULE=ngx_http_gunzip_filter_module -HTTP_GUNZIP_SRCS=src/http/modules/ngx_http_gunzip_filter_module.c - - -HTTP_SSI_FILTER_MODULE=ngx_http_ssi_filter_module -HTTP_SSI_DEPS=src/http/modules/ngx_http_ssi_filter_module.h -HTTP_SSI_SRCS=src/http/modules/ngx_http_ssi_filter_module.c - - -HTTP_XSLT_FILTER_MODULE=ngx_http_xslt_filter_module -HTTP_XSLT_SRCS=src/http/modules/ngx_http_xslt_filter_module.c - - -HTTP_IMAGE_FILTER_MODULE=ngx_http_image_filter_module -HTTP_IMAGE_SRCS=src/http/modules/ngx_http_image_filter_module.c - - -HTTP_SUB_FILTER_MODULE=ngx_http_sub_filter_module -HTTP_SUB_SRCS=src/http/modules/ngx_http_sub_filter_module.c - - -HTTP_USERID_FILTER_MODULE=ngx_http_userid_filter_module -HTTP_USERID_SRCS=src/http/modules/ngx_http_userid_filter_module.c - - -HTTP_SLICE_FILTER_MODULE=ngx_http_slice_filter_module -HTTP_SLICE_SRCS=src/http/modules/ngx_http_slice_filter_module.c - - -HTTP_REALIP_MODULE=ngx_http_realip_module -HTTP_REALIP_SRCS=src/http/modules/ngx_http_realip_module.c - - -HTTP_ADDITION_FILTER_MODULE=ngx_http_addition_filter_module -HTTP_ADDITION_SRCS=src/http/modules/ngx_http_addition_filter_module.c - - -HTTP_DAV_MODULE=ngx_http_dav_module -HTTP_DAV_SRCS=src/http/modules/ngx_http_dav_module.c - - -HTTP_ACCESS_MODULE=ngx_http_access_module -HTTP_ACCESS_SRCS=src/http/modules/ngx_http_access_module.c - - -HTTP_AUTH_BASIC_MODULE=ngx_http_auth_basic_module -HTTP_AUTH_BASIC_SRCS=src/http/modules/ngx_http_auth_basic_module.c - - -HTTP_AUTH_REQUEST_MODULE=ngx_http_auth_request_module -HTTP_AUTH_REQUEST_SRCS=src/http/modules/ngx_http_auth_request_module.c - - -HTTP_AUTOINDEX_MODULE=ngx_http_autoindex_module -HTTP_AUTOINDEX_SRCS=src/http/modules/ngx_http_autoindex_module.c - - -HTTP_RANDOM_INDEX_MODULE=ngx_http_random_index_module -HTTP_RANDOM_INDEX_SRCS=src/http/modules/ngx_http_random_index_module.c - - -HTTP_STATUS_MODULE=ngx_http_status_module -HTTP_STATUS_SRCS=src/http/modules/ngx_http_status_module.c - - -HTTP_GEO_MODULE=ngx_http_geo_module -HTTP_GEO_SRCS=src/http/modules/ngx_http_geo_module.c - - -HTTP_GEOIP_MODULE=ngx_http_geoip_module -HTTP_GEOIP_SRCS=src/http/modules/ngx_http_geoip_module.c - - -HTTP_MAP_MODULE=ngx_http_map_module -HTTP_MAP_SRCS=src/http/modules/ngx_http_map_module.c - - -HTTP_SPLIT_CLIENTS_MODULE=ngx_http_split_clients_module -HTTP_SPLIT_CLIENTS_SRCS=src/http/modules/ngx_http_split_clients_module.c - - -HTTP_REFERER_MODULE=ngx_http_referer_module -HTTP_REFERER_SRCS=src/http/modules/ngx_http_referer_module.c - - -HTTP_REWRITE_MODULE=ngx_http_rewrite_module -HTTP_REWRITE_SRCS=src/http/modules/ngx_http_rewrite_module.c - - -HTTP_SSL_MODULE=ngx_http_ssl_module -HTTP_SSL_DEPS=src/http/modules/ngx_http_ssl_module.h -HTTP_SSL_SRCS=src/http/modules/ngx_http_ssl_module.c - - -HTTP_PROXY_MODULE=ngx_http_proxy_module -HTTP_PROXY_SRCS=src/http/modules/ngx_http_proxy_module.c - - -HTTP_FASTCGI_MODULE=ngx_http_fastcgi_module -HTTP_FASTCGI_SRCS=src/http/modules/ngx_http_fastcgi_module.c - - -HTTP_UWSGI_MODULE=ngx_http_uwsgi_module -HTTP_UWSGI_SRCS=src/http/modules/ngx_http_uwsgi_module.c - - -HTTP_SCGI_MODULE=ngx_http_scgi_module -HTTP_SCGI_SRCS=src/http/modules/ngx_http_scgi_module.c - - -HTTP_PERL_MODULE=ngx_http_perl_module -HTTP_PERL_INCS=src/http/modules/perl -HTTP_PERL_DEPS=src/http/modules/perl/ngx_http_perl_module.h -HTTP_PERL_SRCS=src/http/modules/perl/ngx_http_perl_module.c - - -HTTP_MEMCACHED_MODULE=ngx_http_memcached_module -HTTP_MEMCACHED_SRCS=src/http/modules/ngx_http_memcached_module.c - - -HTTP_LIMIT_CONN_MODULE=ngx_http_limit_conn_module -HTTP_LIMIT_CONN_SRCS=src/http/modules/ngx_http_limit_conn_module.c - - -HTTP_LIMIT_REQ_MODULE=ngx_http_limit_req_module -HTTP_LIMIT_REQ_SRCS=src/http/modules/ngx_http_limit_req_module.c - - -HTTP_EMPTY_GIF_MODULE=ngx_http_empty_gif_module -HTTP_EMPTY_GIF_SRCS=src/http/modules/ngx_http_empty_gif_module.c - - -HTTP_BROWSER_MODULE=ngx_http_browser_module -HTTP_BROWSER_SRCS=src/http/modules/ngx_http_browser_module.c - - -HTTP_SECURE_LINK_MODULE=ngx_http_secure_link_module -HTTP_SECURE_LINK_SRCS=src/http/modules/ngx_http_secure_link_module.c - - -HTTP_DEGRADATION_MODULE=ngx_http_degradation_module -HTTP_DEGRADATION_SRCS=src/http/modules/ngx_http_degradation_module.c - - -HTTP_FLV_MODULE=ngx_http_flv_module -HTTP_FLV_SRCS=src/http/modules/ngx_http_flv_module.c - - -HTTP_MP4_MODULE=ngx_http_mp4_module -HTTP_MP4_SRCS=src/http/modules/ngx_http_mp4_module.c - - -HTTP_GZIP_STATIC_MODULE=ngx_http_gzip_static_module -HTTP_GZIP_STATIC_SRCS=src/http/modules/ngx_http_gzip_static_module.c - - -HTTP_UPSTREAM_HASH_MODULE=ngx_http_upstream_hash_module -HTTP_UPSTREAM_HASH_SRCS=src/http/modules/ngx_http_upstream_hash_module.c - - -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" - - -HTTP_UPSTREAM_ZONE_MODULE=ngx_http_upstream_zone_module -HTTP_UPSTREAM_ZONE_SRCS=" \ - src/http/modules/ngx_http_upstream_zone_module.c" - - -MAIL_INCS="src/mail" - -MAIL_DEPS="src/mail/ngx_mail.h" - -MAIL_MODULES="ngx_mail_module ngx_mail_core_module" - -MAIL_SRCS="src/mail/ngx_mail.c \ - src/mail/ngx_mail_core_module.c \ - src/mail/ngx_mail_handler.c \ - src/mail/ngx_mail_parse.c" - -MAIL_POP3_MODULE="ngx_mail_pop3_module" -MAIL_POP3_DEPS="src/mail/ngx_mail_pop3_module.h" -MAIL_POP3_SRCS="src/mail/ngx_mail_pop3_module.c \ - src/mail/ngx_mail_pop3_handler.c" - -MAIL_IMAP_MODULE="ngx_mail_imap_module" -MAIL_IMAP_DEPS="src/mail/ngx_mail_imap_module.h" -MAIL_IMAP_SRCS="src/mail/ngx_mail_imap_module.c \ - src/mail/ngx_mail_imap_handler.c" - -MAIL_SMTP_MODULE="ngx_mail_smtp_module" -MAIL_SMTP_DEPS="src/mail/ngx_mail_smtp_module.h" -MAIL_SMTP_SRCS="src/mail/ngx_mail_smtp_module.c \ - src/mail/ngx_mail_smtp_handler.c" - -MAIL_SSL_MODULE="ngx_mail_ssl_module" -MAIL_SSL_DEPS="src/mail/ngx_mail_ssl_module.h" -MAIL_SSL_SRCS="src/mail/ngx_mail_ssl_module.c" - -MAIL_AUTH_HTTP_MODULE="ngx_mail_auth_http_module" -MAIL_AUTH_HTTP_SRCS="src/mail/ngx_mail_auth_http_module.c" - -MAIL_PROXY_MODULE="ngx_mail_proxy_module" -MAIL_PROXY_SRCS="src/mail/ngx_mail_proxy_module.c" - - -STREAM_INCS="src/stream" - -STREAM_DEPS="src/stream/ngx_stream.h \ - src/stream/ngx_stream_upstream.h \ - src/stream/ngx_stream_upstream_round_robin.h" - -STREAM_MODULES="ngx_stream_module \ - ngx_stream_core_module \ - ngx_stream_proxy_module \ - ngx_stream_upstream_module" - -STREAM_SRCS="src/stream/ngx_stream.c \ - src/stream/ngx_stream_handler.c \ - src/stream/ngx_stream_core_module.c \ - src/stream/ngx_stream_proxy_module.c \ - src/stream/ngx_stream_upstream.c \ - src/stream/ngx_stream_upstream_round_robin.c" - -STREAM_SSL_MODULE="ngx_stream_ssl_module" -STREAM_SSL_DEPS="src/stream/ngx_stream_ssl_module.h" -STREAM_SSL_SRCS="src/stream/ngx_stream_ssl_module.c" - -STREAM_LIMIT_CONN_MODULE=ngx_stream_limit_conn_module -STREAM_LIMIT_CONN_SRCS=src/stream/ngx_stream_limit_conn_module.c - -STREAM_ACCESS_MODULE=ngx_stream_access_module -STREAM_ACCESS_SRCS=src/stream/ngx_stream_access_module.c - -STREAM_UPSTREAM_HASH_MODULE=ngx_stream_upstream_hash_module -STREAM_UPSTREAM_HASH_SRCS=src/stream/ngx_stream_upstream_hash_module.c - -STREAM_UPSTREAM_LEAST_CONN_MODULE=ngx_stream_upstream_least_conn_module -STREAM_UPSTREAM_LEAST_CONN_SRCS=" \ - src/stream/ngx_stream_upstream_least_conn_module.c" - -STREAM_UPSTREAM_ZONE_MODULE=ngx_stream_upstream_zone_module -STREAM_UPSTREAM_ZONE_SRCS=src/stream/ngx_stream_upstream_zone_module.c - - -NGX_GOOGLE_PERFTOOLS_MODULE=ngx_google_perftools_module -NGX_GOOGLE_PERFTOOLS_SRCS=src/misc/ngx_google_perftools_module.c - -NGX_CPP_TEST_SRCS=src/misc/ngx_cpp_test_module.cpp diff --git a/auto/summary b/auto/summary index 1be975d..dc8fe4f 100644 --- a/auto/summary +++ b/auto/summary @@ -60,6 +60,7 @@ echo cat << END nginx path prefix: "$NGX_PREFIX" nginx binary file: "$NGX_SBIN_PATH" + nginx modules path: "$NGX_MODULES_PATH" nginx configuration prefix: "$NGX_CONF_PREFIX" nginx configuration file: "$NGX_CONF_PATH" nginx pid file: "$NGX_PID_PATH" diff --git a/auto/unix b/auto/unix index 7bfca8f..e07df08 100755 --- a/auto/unix +++ b/auto/unix @@ -255,12 +255,12 @@ ngx_feature_test="struct statvfs fs; ngx_feature="dlopen()" -ngx_feature_name= +ngx_feature_name="NGX_HAVE_DLOPEN" ngx_feature_run=no ngx_feature_incs="#include " ngx_feature_path= ngx_feature_libs= -ngx_feature_test="dlopen(NULL, 0)" +ngx_feature_test="dlopen(NULL, 0); dlsym(NULL, NULL)" . auto/feature @@ -271,7 +271,7 @@ if [ $ngx_found != yes ]; then . auto/feature if [ $ngx_found = yes ]; then - NGX_LIBDL="-ldl" + CORE_LIBS="$CORE_LIBS -ldl" fi fi diff --git a/src/core/nginx.c b/src/core/nginx.c index 64db381..6ce030c 100644 --- a/src/core/nginx.c +++ b/src/core/nginx.c @@ -24,6 +24,10 @@ 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 char *ngx_load_module(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +#if (NGX_HAVE_DLOPEN) +static void ngx_unload_module(void *data); +#endif static ngx_conf_enum_t ngx_debug_points[] = { @@ -133,6 +137,13 @@ static ngx_command_t ngx_core_commands[] = { 0, NULL }, + { ngx_string("load_module"), + NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, + ngx_load_module, + 0, + 0, + NULL }, + ngx_null_command }; @@ -160,8 +171,6 @@ ngx_module_t ngx_core_module = { }; -ngx_uint_t ngx_max_module; - static ngx_uint_t ngx_show_help; static ngx_uint_t ngx_show_version; static ngx_uint_t ngx_show_configure; @@ -260,9 +269,8 @@ main(int argc, char *const *argv) return 1; } - ngx_max_module = 0; - for (i = 0; ngx_modules[i]; i++) { - ngx_modules[i]->index = ngx_max_module++; + if (ngx_preinit_modules() != NGX_OK) { + return 1; } cycle = ngx_init_cycle(&init_cycle); @@ -1406,3 +1414,101 @@ ngx_set_worker_processes(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_OK; } + + +static char * +ngx_load_module(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ +#if (NGX_HAVE_DLOPEN) + void *handle; + char **names, **order; + ngx_str_t *value, file; + ngx_uint_t i; + ngx_module_t *module, **modules; + ngx_pool_cleanup_t *cln; + + if (cf->cycle->modules_used) { + return "is specified too late"; + } + + value = cf->args->elts; + + file = value[1]; + + if (ngx_conf_full_name(cf->cycle, &file, 0) != NGX_OK) { + return NGX_CONF_ERROR; + } + + cln = ngx_pool_cleanup_add(cf->cycle->pool, 0); + if (cln == NULL) { + return NGX_CONF_ERROR; + } + + handle = ngx_dlopen(file.data); + if (handle == NULL) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + ngx_dlopen_n " \"%s\" failed (%s)", + file.data, ngx_dlerror()); + return NGX_CONF_ERROR; + } + + cln->handler = ngx_unload_module; + cln->data = handle; + + modules = ngx_dlsym(handle, "ngx_modules"); + if (modules == NULL) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + ngx_dlsym_n " \"%V\", \"%s\" failed (%s)", + &value[1], "ngx_modules", ngx_dlerror()); + return NGX_CONF_ERROR; + } + + names = ngx_dlsym(handle, "ngx_module_names"); + if (names == NULL) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + ngx_dlsym_n " \"%V\", \"%s\" failed (%s)", + &value[1], "ngx_module_names", ngx_dlerror()); + return NGX_CONF_ERROR; + } + + order = ngx_dlsym(handle, "ngx_module_order"); + + for (i = 0; modules[i]; i++) { + module = modules[i]; + module->name = names[i]; + + if (ngx_add_module(cf, &file, module, order) != NGX_OK) { + return NGX_CONF_ERROR; + } + + ngx_log_debug2(NGX_LOG_DEBUG_CORE, cf->log, 0, "module: %s i:%i", + module->name, module->index); + } + + return NGX_CONF_OK; + +#else + + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "\"load_module\" is not supported " + "on this platform"); + return NGX_CONF_ERROR; + +#endif +} + + +#if (NGX_HAVE_DLOPEN) + +static void +ngx_unload_module(void *data) +{ + void *handle = data; + + if (ngx_dlclose(handle) != 0) { + ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, + ngx_dlclose_n " failed (%s)", ngx_dlerror()); + } +} + +#endif diff --git a/src/core/nginx.h b/src/core/nginx.h index 0960afb..e416e90 100644 --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1009010 -#define NGINX_VERSION "1.9.10" +#define nginx_version 1009011 +#define NGINX_VERSION "1.9.11" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD diff --git a/src/core/ngx_conf_file.c b/src/core/ngx_conf_file.c index 1c3238c..fb72656 100644 --- a/src/core/ngx_conf_file.c +++ b/src/core/ngx_conf_file.c @@ -329,9 +329,9 @@ ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last) found = 0; - for (i = 0; ngx_modules[i]; i++) { + for (i = 0; cf->cycle->modules[i]; i++) { - cmd = ngx_modules[i]->commands; + cmd = cf->cycle->modules[i]->commands; if (cmd == NULL) { continue; } @@ -348,8 +348,8 @@ ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last) found = 1; - if (ngx_modules[i]->type != NGX_CONF_MODULE - && ngx_modules[i]->type != cf->module_type) + if (cf->cycle->modules[i]->type != NGX_CONF_MODULE + && cf->cycle->modules[i]->type != cf->module_type) { continue; } @@ -411,16 +411,16 @@ ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last) conf = NULL; if (cmd->type & NGX_DIRECT_CONF) { - conf = ((void **) cf->ctx)[ngx_modules[i]->index]; + conf = ((void **) cf->ctx)[cf->cycle->modules[i]->index]; } else if (cmd->type & NGX_MAIN_CONF) { - conf = &(((void **) cf->ctx)[ngx_modules[i]->index]); + conf = &(((void **) cf->ctx)[cf->cycle->modules[i]->index]); } else if (cf->ctx) { confp = *(void **) ((char *) cf->ctx + cmd->conf); if (confp) { - conf = confp[ngx_modules[i]->ctx_index]; + conf = confp[cf->cycle->modules[i]->ctx_index]; } } diff --git a/src/core/ngx_conf_file.h b/src/core/ngx_conf_file.h index 2d03f43..9ccee36 100644 --- a/src/core/ngx_conf_file.h +++ b/src/core/ngx_conf_file.h @@ -96,53 +96,6 @@ struct ngx_open_file_s { }; -#define NGX_MODULE_V1 0, 0, 0, 0, 0, 0, 1 -#define NGX_MODULE_V1_PADDING 0, 0, 0, 0, 0, 0, 0, 0 - -struct ngx_module_s { - ngx_uint_t ctx_index; - ngx_uint_t index; - - ngx_uint_t spare0; - ngx_uint_t spare1; - ngx_uint_t spare2; - ngx_uint_t spare3; - - ngx_uint_t version; - - void *ctx; - ngx_command_t *commands; - ngx_uint_t type; - - ngx_int_t (*init_master)(ngx_log_t *log); - - ngx_int_t (*init_module)(ngx_cycle_t *cycle); - - ngx_int_t (*init_process)(ngx_cycle_t *cycle); - ngx_int_t (*init_thread)(ngx_cycle_t *cycle); - void (*exit_thread)(ngx_cycle_t *cycle); - void (*exit_process)(ngx_cycle_t *cycle); - - void (*exit_master)(ngx_cycle_t *cycle); - - uintptr_t spare_hook0; - uintptr_t spare_hook1; - uintptr_t spare_hook2; - uintptr_t spare_hook3; - uintptr_t spare_hook4; - uintptr_t spare_hook5; - uintptr_t spare_hook6; - uintptr_t spare_hook7; -}; - - -typedef struct { - ngx_str_t name; - void *(*create_conf)(ngx_cycle_t *cycle); - char *(*init_conf)(ngx_cycle_t *cycle, void *conf); -} ngx_core_module_t; - - typedef struct { ngx_file_t file; ngx_buf_t *buffer; @@ -340,8 +293,4 @@ char *ngx_conf_set_enum_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); char *ngx_conf_set_bitmask_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); -extern ngx_uint_t ngx_max_module; -extern ngx_module_t *ngx_modules[]; - - #endif /* _NGX_CONF_FILE_H_INCLUDED_ */ diff --git a/src/core/ngx_core.h b/src/core/ngx_core.h index 6b31705..2819c1a 100644 --- a/src/core/ngx_core.h +++ b/src/core/ngx_core.h @@ -53,6 +53,7 @@ typedef void (*ngx_connection_handler_pt)(ngx_connection_t *c); #include #include #include +#include #include #include #include @@ -83,6 +84,7 @@ typedef void (*ngx_connection_handler_pt)(ngx_connection_t *c); #endif #include #include +#include #include #include #include diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c index ad4bf92..f103266 100644 --- a/src/core/ngx_cycle.c +++ b/src/core/ngx_cycle.c @@ -212,12 +212,18 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) ngx_strlow(cycle->hostname.data, (u_char *) hostname, cycle->hostname.len); - for (i = 0; ngx_modules[i]; i++) { - if (ngx_modules[i]->type != NGX_CORE_MODULE) { + if (ngx_cycle_modules(cycle) != NGX_OK) { + ngx_destroy_pool(pool); + return NULL; + } + + + for (i = 0; cycle->modules[i]; i++) { + if (cycle->modules[i]->type != NGX_CORE_MODULE) { continue; } - module = ngx_modules[i]->ctx; + module = cycle->modules[i]->ctx; if (module->create_conf) { rv = module->create_conf(cycle); @@ -225,7 +231,7 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) ngx_destroy_pool(pool); return NULL; } - cycle->conf_ctx[ngx_modules[i]->index] = rv; + cycle->conf_ctx[cycle->modules[i]->index] = rv; } } @@ -276,15 +282,16 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) cycle->conf_file.data); } - for (i = 0; ngx_modules[i]; i++) { - if (ngx_modules[i]->type != NGX_CORE_MODULE) { + for (i = 0; cycle->modules[i]; i++) { + if (cycle->modules[i]->type != NGX_CORE_MODULE) { continue; } - module = ngx_modules[i]->ctx; + module = cycle->modules[i]->ctx; if (module->init_conf) { - if (module->init_conf(cycle, cycle->conf_ctx[ngx_modules[i]->index]) + if (module->init_conf(cycle, + cycle->conf_ctx[cycle->modules[i]->index]) == NGX_CONF_ERROR) { environ = senv; @@ -612,13 +619,9 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) pool->log = cycle->log; - for (i = 0; ngx_modules[i]; i++) { - if (ngx_modules[i]->init_module) { - if (ngx_modules[i]->init_module(cycle) != NGX_OK) { - /* fatal */ - exit(1); - } - } + if (ngx_init_modules(cycle) != NGX_OK) { + /* fatal */ + exit(1); } diff --git a/src/core/ngx_cycle.h b/src/core/ngx_cycle.h index a730efe..27401d0 100644 --- a/src/core/ngx_cycle.h +++ b/src/core/ngx_cycle.h @@ -48,6 +48,10 @@ struct ngx_cycle_s { ngx_connection_t *free_connections; ngx_uint_t free_connection_n; + ngx_module_t **modules; + ngx_uint_t modules_n; + ngx_uint_t modules_used; /* unsigned modules_used:1; */ + ngx_queue_t reusable_connections_queue; ngx_array_t listening; diff --git a/src/core/ngx_module.c b/src/core/ngx_module.c new file mode 100644 index 0000000..1e947c9 --- /dev/null +++ b/src/core/ngx_module.c @@ -0,0 +1,361 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Maxim Dounin + * Copyright (C) Nginx, Inc. + */ + + +#include +#include + + +#define NGX_MAX_DYNAMIC_MODULES 128 + + +static ngx_uint_t ngx_module_index(ngx_cycle_t *cycle); +static ngx_uint_t ngx_module_ctx_index(ngx_cycle_t *cycle, ngx_uint_t type, + ngx_uint_t index); + + +ngx_uint_t ngx_max_module; +static ngx_uint_t ngx_modules_n; + + +ngx_int_t +ngx_preinit_modules() +{ + ngx_uint_t i; + + ngx_max_module = 0; + for (i = 0; ngx_modules[i]; i++) { + ngx_modules[i]->index = i; + ngx_modules[i]->name = ngx_module_names[i]; + } + + ngx_modules_n = i; + ngx_max_module = ngx_modules_n + NGX_MAX_DYNAMIC_MODULES; + + return NGX_OK; +} + + +ngx_int_t +ngx_cycle_modules(ngx_cycle_t *cycle) +{ + /* + * create a list of modules to be used for this cycle, + * copy static modules to it + */ + + cycle->modules = ngx_pcalloc(cycle->pool, (ngx_max_module + 1) + * sizeof(ngx_module_t *)); + if (cycle->modules == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(cycle->modules, ngx_modules, + ngx_modules_n * sizeof(ngx_module_t *)); + + cycle->modules_n = ngx_modules_n; + + return NGX_OK; +} + + +ngx_int_t +ngx_init_modules(ngx_cycle_t *cycle) +{ + ngx_uint_t i; + + for (i = 0; cycle->modules[i]; i++) { + if (cycle->modules[i]->init_module) { + if (cycle->modules[i]->init_module(cycle) != NGX_OK) { + return NGX_ERROR; + } + } + } + + return NGX_OK; +} + + +ngx_int_t +ngx_count_modules(ngx_cycle_t *cycle, ngx_uint_t type) +{ + ngx_uint_t i, next, max; + ngx_module_t *module; + + next = 0; + max = 0; + + /* count appropriate modules, set up their indices */ + + for (i = 0; cycle->modules[i]; i++) { + module = cycle->modules[i]; + + if (module->type != type) { + continue; + } + + if (module->ctx_index != NGX_MODULE_UNSET_INDEX) { + + /* if ctx_index was assigned, preserve it */ + + if (module->ctx_index > max) { + max = module->ctx_index; + } + + if (module->ctx_index == next) { + next++; + } + + continue; + } + + /* search for some free index */ + + module->ctx_index = ngx_module_ctx_index(cycle, type, next); + + if (module->ctx_index > max) { + max = module->ctx_index; + } + + next = module->ctx_index + 1; + } + + /* + * make sure the number returned is big enough for previous + * cycle as well, else there will be problems if the number + * will be stored in a global variable (as it's used to be) + * and we'll have to roll back to the previous cycle + */ + + if (cycle->old_cycle && cycle->old_cycle->modules) { + + for (i = 0; cycle->old_cycle->modules[i]; i++) { + module = cycle->old_cycle->modules[i]; + + if (module->type != type) { + continue; + } + + if (module->ctx_index > max) { + max = module->ctx_index; + } + } + } + + /* prevent loading of additional modules */ + + cycle->modules_used = 1; + + return max + 1; +} + + +ngx_int_t +ngx_add_module(ngx_conf_t *cf, ngx_str_t *file, ngx_module_t *module, + char **order) +{ + void *rv; + ngx_uint_t i, m, before; + ngx_core_module_t *core_module; + + if (cf->cycle->modules_n >= ngx_max_module) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "too many modules loaded"); + return NGX_ERROR; + } + + if (module->version != nginx_version) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "module \"%V\" version %ui instead of %ui", + file, module->version, nginx_version); + return NGX_ERROR; + } + + if (ngx_strcmp(module->signature, NGX_MODULE_SIGNATURE) != 0) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "module \"%V\" is not binary compatible", + file); + return NGX_ERROR; + } + + for (m = 0; cf->cycle->modules[m]; m++) { + if (ngx_strcmp(cf->cycle->modules[m]->name, module->name) == 0) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "module \"%s\" is already loaded", + module->name); + return NGX_ERROR; + } + } + + /* + * if the module wasn't previously loaded, assign an index + */ + + if (module->index == NGX_MODULE_UNSET_INDEX) { + module->index = ngx_module_index(cf->cycle); + + if (module->index >= ngx_max_module) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "too many modules loaded"); + return NGX_ERROR; + } + } + + /* + * put the module into the cycle->modules array + */ + + before = cf->cycle->modules_n; + + if (order) { + for (i = 0; order[i]; i++) { + if (ngx_strcmp(order[i], module->name) == 0) { + i++; + break; + } + } + + for ( /* void */ ; order[i]; i++) { + +#if 0 + ngx_log_debug2(NGX_LOG_DEBUG_CORE, cf->log, 0, + "module: %s before %s", + module->name, order[i]); +#endif + + for (m = 0; m < before; m++) { + if (ngx_strcmp(cf->cycle->modules[m]->name, order[i]) == 0) { + + ngx_log_debug3(NGX_LOG_DEBUG_CORE, cf->log, 0, + "module: %s before %s:%i", + module->name, order[i], m); + + before = m; + break; + } + } + } + } + + /* put the module before modules[before] */ + + if (before != cf->cycle->modules_n) { + ngx_memmove(&cf->cycle->modules[before + 1], + &cf->cycle->modules[before], + (cf->cycle->modules_n - before) * sizeof(ngx_module_t *)); + } + + cf->cycle->modules[before] = module; + cf->cycle->modules_n++; + + if (module->type == NGX_CORE_MODULE) { + + /* + * we are smart enough to initialize core modules; + * other modules are expected to be loaded before + * initialization - e.g., http modules must be loaded + * before http{} block + */ + + core_module = module->ctx; + + if (core_module->create_conf) { + rv = core_module->create_conf(cf->cycle); + if (rv == NULL) { + return NGX_ERROR; + } + + cf->cycle->conf_ctx[module->index] = rv; + } + } + + return NGX_OK; +} + + +static ngx_uint_t +ngx_module_index(ngx_cycle_t *cycle) +{ + ngx_uint_t i, index; + ngx_module_t *module; + + index = 0; + +again: + + /* find an unused index */ + + for (i = 0; cycle->modules[i]; i++) { + module = cycle->modules[i]; + + if (module->index == index) { + index++; + goto again; + } + } + + /* check previous cycle */ + + if (cycle->old_cycle && cycle->old_cycle->modules) { + + for (i = 0; cycle->old_cycle->modules[i]; i++) { + module = cycle->old_cycle->modules[i]; + + if (module->index == index) { + index++; + goto again; + } + } + } + + return index; +} + + +static ngx_uint_t +ngx_module_ctx_index(ngx_cycle_t *cycle, ngx_uint_t type, ngx_uint_t index) +{ + ngx_uint_t i; + ngx_module_t *module; + +again: + + /* find an unused ctx_index */ + + for (i = 0; cycle->modules[i]; i++) { + module = cycle->modules[i]; + + if (module->type != type) { + continue; + } + + if (module->ctx_index == index) { + index++; + goto again; + } + } + + /* check previous cycle */ + + if (cycle->old_cycle && cycle->old_cycle->modules) { + + for (i = 0; cycle->old_cycle->modules[i]; i++) { + module = cycle->old_cycle->modules[i]; + + if (module->type != type) { + continue; + } + + if (module->ctx_index == index) { + index++; + goto again; + } + } + } + + return index; +} diff --git a/src/core/ngx_module.h b/src/core/ngx_module.h new file mode 100644 index 0000000..cd28c49 --- /dev/null +++ b/src/core/ngx_module.h @@ -0,0 +1,307 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Maxim Dounin + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_MODULE_H_INCLUDED_ +#define _NGX_MODULE_H_INCLUDED_ + + +#include +#include +#include + + +#define NGX_MODULE_UNSET_INDEX (ngx_uint_t) -1 + + +#define NGX_MODULE_SIGNATURE_0 \ + ngx_value(NGX_PTR_SIZE) "," \ + ngx_value(NGX_SIG_ATOMIC_T_SIZE) "," \ + ngx_value(NGX_TIME_T_SIZE) "," + +#if (NGX_HAVE_KQUEUE) +#define NGX_MODULE_SIGNATURE_1 "1" +#else +#define NGX_MODULE_SIGNATURE_1 "0" +#endif + +#if (NGX_HAVE_IOCP) +#define NGX_MODULE_SIGNATURE_2 "1" +#else +#define NGX_MODULE_SIGNATURE_2 "0" +#endif + +#if (NGX_HAVE_FILE_AIO) +#define NGX_MODULE_SIGNATURE_3 "1" +#else +#define NGX_MODULE_SIGNATURE_3 "0" +#endif + +#if (NGX_HAVE_AIO_SENDFILE) +#define NGX_MODULE_SIGNATURE_4 "1" +#else +#define NGX_MODULE_SIGNATURE_4 "0" +#endif + +#if (NGX_HAVE_EVENTFD) +#define NGX_MODULE_SIGNATURE_5 "1" +#else +#define NGX_MODULE_SIGNATURE_5 "0" +#endif + +#if (NGX_HAVE_EPOLL) +#define NGX_MODULE_SIGNATURE_6 "1" +#else +#define NGX_MODULE_SIGNATURE_6 "0" +#endif + +#if (NGX_HAVE_KEEPALIVE_TUNABLE) +#define NGX_MODULE_SIGNATURE_7 "1" +#else +#define NGX_MODULE_SIGNATURE_7 "0" +#endif + +#if (NGX_HAVE_INET6) +#define NGX_MODULE_SIGNATURE_8 "1" +#else +#define NGX_MODULE_SIGNATURE_8 "0" +#endif + +#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) +#define NGX_MODULE_SIGNATURE_9 "1" +#else +#define NGX_MODULE_SIGNATURE_9 "0" +#endif + +#if (NGX_HAVE_REUSEPORT) +#define NGX_MODULE_SIGNATURE_10 "1" +#else +#define NGX_MODULE_SIGNATURE_10 "0" +#endif + +#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) +#define NGX_MODULE_SIGNATURE_11 "1" +#else +#define NGX_MODULE_SIGNATURE_11 "0" +#endif + +#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) +#define NGX_MODULE_SIGNATURE_12 "1" +#else +#define NGX_MODULE_SIGNATURE_12 "0" +#endif + +#if (NGX_HAVE_SETFIB) +#define NGX_MODULE_SIGNATURE_13 "1" +#else +#define NGX_MODULE_SIGNATURE_13 "0" +#endif + +#if (NGX_HAVE_TCP_FASTOPEN) +#define NGX_MODULE_SIGNATURE_14 "1" +#else +#define NGX_MODULE_SIGNATURE_14 "0" +#endif + +#if (NGX_HAVE_UNIX_DOMAIN) +#define NGX_MODULE_SIGNATURE_15 "1" +#else +#define NGX_MODULE_SIGNATURE_15 "0" +#endif + +#if (NGX_HAVE_VARIADIC_MACROS) +#define NGX_MODULE_SIGNATURE_16 "1" +#else +#define NGX_MODULE_SIGNATURE_16 "0" +#endif + +#if (NGX_HAVE_MD5) +#define NGX_MODULE_SIGNATURE_17 "1" +#else +#define NGX_MODULE_SIGNATURE_17 "0" +#endif + +#if (NGX_HAVE_SHA1) +#define NGX_MODULE_SIGNATURE_18 "1" +#else +#define NGX_MODULE_SIGNATURE_18 "0" +#endif + +#if (NGX_HAVE_OPENAT) +#define NGX_MODULE_SIGNATURE_19 "1" +#else +#define NGX_MODULE_SIGNATURE_19 "0" +#endif + +#if (NGX_HAVE_ATOMIC_OPS) +#define NGX_MODULE_SIGNATURE_20 "1" +#else +#define NGX_MODULE_SIGNATURE_20 "0" +#endif + +#if (NGX_HAVE_POSIX_SEM) +#define NGX_MODULE_SIGNATURE_21 "1" +#else +#define NGX_MODULE_SIGNATURE_21 "0" +#endif + +#if (NGX_THREADS) +#define NGX_MODULE_SIGNATURE_22 "1" +#else +#define NGX_MODULE_SIGNATURE_22 "0" +#endif + +#if (NGX_PCRE) +#define NGX_MODULE_SIGNATURE_23 "1" +#else +#define NGX_MODULE_SIGNATURE_23 "0" +#endif + +#if (NGX_HTTP_SSL) +#define NGX_MODULE_SIGNATURE_24 "1" +#else +#define NGX_MODULE_SIGNATURE_24 "0" +#endif + +#if (NGX_HTTP_V2) +#define NGX_MODULE_SIGNATURE_25 "1" +#else +#define NGX_MODULE_SIGNATURE_25 "0" +#endif + +#if (NGX_HTTP_GZIP) +#define NGX_MODULE_SIGNATURE_26 "1" +#else +#define NGX_MODULE_SIGNATURE_26 "0" +#endif + +#if (NGX_HTTP_DEGRADATION) +#define NGX_MODULE_SIGNATURE_27 "1" +#else +#define NGX_MODULE_SIGNATURE_27 "0" +#endif + +#if (NGX_HTTP_X_FORWARDED_FOR) +#define NGX_MODULE_SIGNATURE_28 "1" +#else +#define NGX_MODULE_SIGNATURE_28 "0" +#endif + +#if (NGX_HTTP_REALIP) +#define NGX_MODULE_SIGNATURE_29 "1" +#else +#define NGX_MODULE_SIGNATURE_29 "0" +#endif + +#if (NGX_HTTP_HEADERS) +#define NGX_MODULE_SIGNATURE_30 "1" +#else +#define NGX_MODULE_SIGNATURE_30 "0" +#endif + +#if (NGX_HTTP_DAV) +#define NGX_MODULE_SIGNATURE_31 "1" +#else +#define NGX_MODULE_SIGNATURE_31 "0" +#endif + +#if (NGX_HTTP_CACHE) +#define NGX_MODULE_SIGNATURE_32 "1" +#else +#define NGX_MODULE_SIGNATURE_32 "0" +#endif + +#if (NGX_HTTP_UPSTREAM_ZONE) +#define NGX_MODULE_SIGNATURE_33 "1" +#else +#define NGX_MODULE_SIGNATURE_33 "0" +#endif + +#define NGX_MODULE_SIGNATURE \ + NGX_MODULE_SIGNATURE_0 NGX_MODULE_SIGNATURE_1 NGX_MODULE_SIGNATURE_2 \ + NGX_MODULE_SIGNATURE_3 NGX_MODULE_SIGNATURE_4 NGX_MODULE_SIGNATURE_5 \ + NGX_MODULE_SIGNATURE_6 NGX_MODULE_SIGNATURE_7 NGX_MODULE_SIGNATURE_8 \ + NGX_MODULE_SIGNATURE_9 NGX_MODULE_SIGNATURE_10 NGX_MODULE_SIGNATURE_11 \ + NGX_MODULE_SIGNATURE_12 NGX_MODULE_SIGNATURE_13 NGX_MODULE_SIGNATURE_14 \ + NGX_MODULE_SIGNATURE_15 NGX_MODULE_SIGNATURE_16 NGX_MODULE_SIGNATURE_17 \ + NGX_MODULE_SIGNATURE_18 NGX_MODULE_SIGNATURE_19 NGX_MODULE_SIGNATURE_20 \ + NGX_MODULE_SIGNATURE_21 NGX_MODULE_SIGNATURE_22 NGX_MODULE_SIGNATURE_23 \ + NGX_MODULE_SIGNATURE_24 NGX_MODULE_SIGNATURE_25 NGX_MODULE_SIGNATURE_26 \ + NGX_MODULE_SIGNATURE_27 NGX_MODULE_SIGNATURE_28 NGX_MODULE_SIGNATURE_29 \ + NGX_MODULE_SIGNATURE_30 NGX_MODULE_SIGNATURE_31 NGX_MODULE_SIGNATURE_32 \ + NGX_MODULE_SIGNATURE_33 + + +#define NGX_MODULE_V1 \ + NGX_MODULE_UNSET_INDEX, NGX_MODULE_UNSET_INDEX, \ + NULL, 0, 0, nginx_version, NGX_MODULE_SIGNATURE + +#define NGX_MODULE_V1_PADDING 0, 0, 0, 0, 0, 0, 0, 0 + + +struct ngx_module_s { + ngx_uint_t ctx_index; + ngx_uint_t index; + + char *name; + + ngx_uint_t spare0; + ngx_uint_t spare1; + + ngx_uint_t version; + char *signature; + + void *ctx; + ngx_command_t *commands; + ngx_uint_t type; + + ngx_int_t (*init_master)(ngx_log_t *log); + + ngx_int_t (*init_module)(ngx_cycle_t *cycle); + + ngx_int_t (*init_process)(ngx_cycle_t *cycle); + ngx_int_t (*init_thread)(ngx_cycle_t *cycle); + void (*exit_thread)(ngx_cycle_t *cycle); + void (*exit_process)(ngx_cycle_t *cycle); + + void (*exit_master)(ngx_cycle_t *cycle); + + uintptr_t spare_hook0; + uintptr_t spare_hook1; + uintptr_t spare_hook2; + uintptr_t spare_hook3; + uintptr_t spare_hook4; + uintptr_t spare_hook5; + uintptr_t spare_hook6; + uintptr_t spare_hook7; +}; + + +typedef struct { + ngx_str_t name; + void *(*create_conf)(ngx_cycle_t *cycle); + char *(*init_conf)(ngx_cycle_t *cycle, void *conf); +} ngx_core_module_t; + + +ngx_int_t ngx_preinit_modules(); +ngx_int_t ngx_cycle_modules(ngx_cycle_t *cycle); +ngx_int_t ngx_init_modules(ngx_cycle_t *cycle); +ngx_int_t ngx_count_modules(ngx_cycle_t *cycle, ngx_uint_t type); + + +ngx_int_t ngx_add_module(ngx_conf_t *cf, ngx_str_t *file, + ngx_module_t *module, char **order); + + +extern ngx_module_t *ngx_modules[]; +extern ngx_uint_t ngx_max_module; + +extern char *ngx_module_names[]; + + +#endif /* _NGX_MODULE_H_INCLUDED_ */ diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c index 7b60abd..7f0d3ad 100644 --- a/src/core/ngx_resolver.c +++ b/src/core/ngx_resolver.c @@ -12,6 +12,9 @@ #define NGX_RESOLVER_UDP_SIZE 4096 +#define NGX_RESOLVER_TCP_RSIZE (2 + 65535) +#define NGX_RESOLVER_TCP_WSIZE 8192 + typedef struct { u_char ident_hi; @@ -53,7 +56,8 @@ typedef struct { ((u_char *) (n) - offsetof(ngx_resolver_node_t, node)) -ngx_int_t ngx_udp_connect(ngx_udp_connection_t *uc); +ngx_int_t ngx_udp_connect(ngx_resolver_connection_t *rec); +ngx_int_t ngx_tcp_connect(ngx_resolver_connection_t *rec); static void ngx_resolver_cleanup(void *data); @@ -64,6 +68,10 @@ static void ngx_resolver_expire(ngx_resolver_t *r, ngx_rbtree_t *tree, ngx_queue_t *queue); static ngx_int_t ngx_resolver_send_query(ngx_resolver_t *r, ngx_resolver_node_t *rn); +static ngx_int_t ngx_resolver_send_udp_query(ngx_resolver_t *r, + ngx_resolver_connection_t *rec, u_char *query, u_short qlen); +static ngx_int_t ngx_resolver_send_tcp_query(ngx_resolver_t *r, + ngx_resolver_connection_t *rec, u_char *query, u_short qlen); static ngx_int_t ngx_resolver_create_name_query(ngx_resolver_t *r, ngx_resolver_node_t *rn, ngx_str_t *name); static ngx_int_t ngx_resolver_create_addr_query(ngx_resolver_t *r, @@ -72,12 +80,14 @@ static void ngx_resolver_resend_handler(ngx_event_t *ev); static time_t ngx_resolver_resend(ngx_resolver_t *r, ngx_rbtree_t *tree, ngx_queue_t *queue); static ngx_uint_t ngx_resolver_resend_empty(ngx_resolver_t *r); -static void ngx_resolver_read_response(ngx_event_t *rev); +static void ngx_resolver_udp_read(ngx_event_t *rev); +static void ngx_resolver_tcp_write(ngx_event_t *wev); +static void ngx_resolver_tcp_read(ngx_event_t *rev); static void ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf, - size_t n); + size_t n, ngx_uint_t tcp); static void ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t n, ngx_uint_t ident, ngx_uint_t code, ngx_uint_t qtype, - ngx_uint_t nan, ngx_uint_t ans); + ngx_uint_t nan, ngx_uint_t trunc, ngx_uint_t ans); static void ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n, ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan); static ngx_resolver_node_t *ngx_resolver_lookup_name(ngx_resolver_t *r, @@ -110,12 +120,12 @@ static ngx_resolver_node_t *ngx_resolver_lookup_addr6(ngx_resolver_t *r, ngx_resolver_t * 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, j; - ngx_resolver_t *r; - ngx_pool_cleanup_t *cln; - ngx_udp_connection_t *uc; + ngx_str_t s; + ngx_url_t u; + ngx_uint_t i, j; + ngx_resolver_t *r; + ngx_pool_cleanup_t *cln; + ngx_resolver_connection_t *rec; cln = ngx_pool_cleanup_add(cf->pool, 0); if (cln == NULL) { @@ -165,6 +175,7 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n) r->ident = -1; r->resend_timeout = 5; + r->tcp_timeout = 5; r->expire = 30; r->valid = 0; @@ -172,8 +183,8 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n) r->log_level = NGX_LOG_ERR; if (n) { - if (ngx_array_init(&r->udp_connections, cf->pool, n, - sizeof(ngx_udp_connection_t)) + if (ngx_array_init(&r->connections, cf->pool, n, + sizeof(ngx_resolver_connection_t)) != NGX_OK) { return NULL; @@ -230,17 +241,18 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n) return NULL; } - uc = ngx_array_push_n(&r->udp_connections, u.naddrs); - if (uc == NULL) { + rec = ngx_array_push_n(&r->connections, u.naddrs); + if (rec == NULL) { return NULL; } - ngx_memzero(uc, u.naddrs * sizeof(ngx_udp_connection_t)); + ngx_memzero(rec, u.naddrs * sizeof(ngx_resolver_connection_t)); 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; + rec[j].sockaddr = u.addrs[j].sockaddr; + rec[j].socklen = u.addrs[j].socklen; + rec[j].server = u.addrs[j].name; + rec[j].resolver = r; } } @@ -253,8 +265,8 @@ ngx_resolver_cleanup(void *data) { ngx_resolver_t *r = data; - ngx_uint_t i; - ngx_udp_connection_t *uc; + ngx_uint_t i; + ngx_resolver_connection_t *rec; if (r) { ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, @@ -273,11 +285,25 @@ ngx_resolver_cleanup(void *data) } - uc = r->udp_connections.elts; + rec = r->connections.elts; - for (i = 0; i < r->udp_connections.nelts; i++) { - if (uc[i].connection) { - ngx_close_connection(uc[i].connection); + for (i = 0; i < r->connections.nelts; i++) { + if (rec[i].udp) { + ngx_close_connection(rec[i].udp); + } + + if (rec[i].tcp) { + ngx_close_connection(rec[i].tcp); + } + + if (rec[i].read_buf) { + ngx_resolver_free(r, rec[i].read_buf->start); + ngx_resolver_free(r, rec[i].read_buf); + } + + if (rec[i].write_buf) { + ngx_resolver_free(r, rec[i].write_buf->start); + ngx_resolver_free(r, rec[i].write_buf); } } @@ -340,7 +366,7 @@ ngx_resolve_start(ngx_resolver_t *r, ngx_resolver_ctx_t *temp) } } - if (r->udp_connections.nelts == 0) { + if (r->connections.nelts == 0) { return NGX_NO_RESOLVER; } @@ -685,9 +711,16 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx, return NGX_OK; } + rn->last_connection = r->last_connection++; + if (r->last_connection == r->connections.nelts) { + r->last_connection = 0; + } + rn->naddrs = (u_short) -1; + rn->tcp = 0; #if (NGX_HAVE_INET6) rn->naddrs6 = r->ipv6 ? (u_short) -1 : 0; + rn->tcp6 = 0; #endif if (ngx_resolver_send_query(r, rn) != NGX_OK) { @@ -897,9 +930,16 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx) goto failed; } + rn->last_connection = r->last_connection++; + if (r->last_connection == r->connections.nelts) { + r->last_connection = 0; + } + rn->naddrs = (u_short) -1; + rn->tcp = 0; #if (NGX_HAVE_INET6) rn->naddrs6 = (u_short) -1; + rn->tcp6 = 0; #endif if (ngx_resolver_send_query(r, rn) != NGX_OK) { @@ -1094,64 +1134,163 @@ ngx_resolver_expire(ngx_resolver_t *r, ngx_rbtree_t *tree, ngx_queue_t *queue) static ngx_int_t ngx_resolver_send_query(ngx_resolver_t *r, ngx_resolver_node_t *rn) { - ssize_t n; - ngx_udp_connection_t *uc; + ngx_int_t rc; + ngx_resolver_connection_t *rec; - uc = r->udp_connections.elts; + rec = r->connections.elts; + rec = &rec[rn->last_connection]; - uc = &uc[r->last_connection++]; - if (r->last_connection == r->udp_connections.nelts) { - r->last_connection = 0; - } - - if (uc->connection == NULL) { - - uc->log = *r->log; - uc->log.handler = ngx_resolver_log_error; - uc->log.data = uc; - uc->log.action = "resolving"; - - if (ngx_udp_connect(uc) != NGX_OK) { - return NGX_ERROR; - } - - uc->connection->data = r; - uc->connection->read->handler = ngx_resolver_read_response; - uc->connection->read->resolver = 1; + if (rec->log.handler == NULL) { + rec->log = *r->log; + rec->log.handler = ngx_resolver_log_error; + rec->log.data = rec; + rec->log.action = "resolving"; } if (rn->naddrs == (u_short) -1) { - n = ngx_send(uc->connection, rn->query, rn->qlen); + rc = rn->tcp ? ngx_resolver_send_tcp_query(r, rec, rn->query, rn->qlen) + : ngx_resolver_send_udp_query(r, rec, rn->query, rn->qlen); - if (n == -1) { - return NGX_ERROR; - } - - if ((size_t) n != (size_t) rn->qlen) { - ngx_log_error(NGX_LOG_CRIT, &uc->log, 0, "send() incomplete"); - return NGX_ERROR; + if (rc != NGX_OK) { + return rc; } } #if (NGX_HAVE_INET6) + if (rn->query6 && rn->naddrs6 == (u_short) -1) { - n = ngx_send(uc->connection, rn->query6, rn->qlen); + rc = rn->tcp6 + ? ngx_resolver_send_tcp_query(r, rec, rn->query6, rn->qlen) + : ngx_resolver_send_udp_query(r, rec, rn->query6, rn->qlen); - if (n == -1) { - return NGX_ERROR; - } - - if ((size_t) n != (size_t) rn->qlen) { - ngx_log_error(NGX_LOG_CRIT, &uc->log, 0, "send() incomplete"); - return NGX_ERROR; + if (rc != NGX_OK) { + return rc; } } + #endif return NGX_OK; } +static ngx_int_t +ngx_resolver_send_udp_query(ngx_resolver_t *r, ngx_resolver_connection_t *rec, + u_char *query, u_short qlen) +{ + ssize_t n; + + if (rec->udp == NULL) { + if (ngx_udp_connect(rec) != NGX_OK) { + return NGX_ERROR; + } + + rec->udp->data = rec; + rec->udp->read->handler = ngx_resolver_udp_read; + rec->udp->read->resolver = 1; + } + + n = ngx_send(rec->udp, query, qlen); + + if (n == -1) { + return NGX_ERROR; + } + + if ((size_t) n != (size_t) qlen) { + ngx_log_error(NGX_LOG_CRIT, &rec->log, 0, "send() incomplete"); + return NGX_ERROR; + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_resolver_send_tcp_query(ngx_resolver_t *r, ngx_resolver_connection_t *rec, + u_char *query, u_short qlen) +{ + ngx_buf_t *b; + ngx_int_t rc; + + rc = NGX_OK; + + if (rec->tcp == NULL) { + b = rec->read_buf; + + if (b == NULL) { + b = ngx_resolver_calloc(r, sizeof(ngx_buf_t)); + if (b == NULL) { + return NGX_ERROR; + } + + b->start = ngx_resolver_alloc(r, NGX_RESOLVER_TCP_RSIZE); + if (b->start == NULL) { + ngx_resolver_free(r, b); + return NGX_ERROR; + } + + b->end = b->start + NGX_RESOLVER_TCP_RSIZE; + + rec->read_buf = b; + } + + b->pos = b->start; + b->last = b->start; + + b = rec->write_buf; + + if (b == NULL) { + b = ngx_resolver_calloc(r, sizeof(ngx_buf_t)); + if (b == NULL) { + return NGX_ERROR; + } + + b->start = ngx_resolver_alloc(r, NGX_RESOLVER_TCP_WSIZE); + if (b->start == NULL) { + ngx_resolver_free(r, b); + return NGX_ERROR; + } + + b->end = b->start + NGX_RESOLVER_TCP_WSIZE; + + rec->write_buf = b; + } + + b->pos = b->start; + b->last = b->start; + + rc = ngx_tcp_connect(rec); + if (rc == NGX_ERROR) { + return NGX_ERROR; + } + + rec->tcp->data = rec; + rec->tcp->write->handler = ngx_resolver_tcp_write; + rec->tcp->read->handler = ngx_resolver_tcp_read; + rec->tcp->read->resolver = 1; + + ngx_add_timer(rec->tcp->write, (ngx_msec_t) (r->tcp_timeout * 1000)); + } + + b = rec->write_buf; + + if (b->end - b->last < 2 + qlen) { + ngx_log_error(NGX_LOG_CRIT, &rec->log, 0, "buffer overflow"); + return NGX_ERROR; + } + + *b->last++ = (u_char) (qlen >> 8); + *b->last++ = (u_char) qlen; + b->last = ngx_cpymem(b->last, query, qlen); + + if (rc == NGX_OK) { + ngx_resolver_tcp_write(rec->tcp->write); + } + + return NGX_OK; +} + + static void ngx_resolver_resend_handler(ngx_event_t *ev) { @@ -1244,6 +1383,10 @@ ngx_resolver_resend(ngx_resolver_t *r, ngx_rbtree_t *tree, ngx_queue_t *queue) if (rn->waiting) { + if (++rn->last_connection == r->connections.nelts) { + rn->last_connection = 0; + } + (void) ngx_resolver_send_query(r, rn); rn->expire = now + r->resend_timeout; @@ -1272,13 +1415,15 @@ ngx_resolver_resend_empty(ngx_resolver_t *r) static void -ngx_resolver_read_response(ngx_event_t *rev) +ngx_resolver_udp_read(ngx_event_t *rev) { - ssize_t n; - ngx_connection_t *c; - u_char buf[NGX_RESOLVER_UDP_SIZE]; + ssize_t n; + ngx_connection_t *c; + ngx_resolver_connection_t *rec; + u_char buf[NGX_RESOLVER_UDP_SIZE]; c = rev->data; + rec = c->data; do { n = ngx_udp_recv(c, buf, NGX_RESOLVER_UDP_SIZE); @@ -1287,17 +1432,144 @@ ngx_resolver_read_response(ngx_event_t *rev) return; } - ngx_resolver_process_response(c->data, buf, n); + ngx_resolver_process_response(rec->resolver, buf, n, 0); } while (rev->ready); } static void -ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf, size_t n) +ngx_resolver_tcp_write(ngx_event_t *wev) +{ + off_t sent; + ssize_t n; + ngx_buf_t *b; + ngx_resolver_t *r; + ngx_connection_t *c; + ngx_resolver_connection_t *rec; + + c = wev->data; + rec = c->data; + b = rec->write_buf; + r = rec->resolver; + + if (wev->timedout) { + goto failed; + } + + sent = c->sent; + + while (wev->ready && b->pos < b->last) { + n = ngx_send(c, b->pos, b->last - b->pos); + + if (n == NGX_AGAIN) { + break; + } + + if (n == NGX_ERROR) { + goto failed; + } + + b->pos += n; + } + + if (b->pos != b->start) { + b->last = ngx_movemem(b->start, b->pos, b->last - b->pos); + b->pos = b->start; + } + + if (c->sent != sent) { + ngx_add_timer(wev, (ngx_msec_t) (r->tcp_timeout * 1000)); + } + + if (ngx_handle_write_event(wev, 0) != NGX_OK) { + goto failed; + } + + return; + +failed: + + ngx_close_connection(c); + rec->tcp = NULL; +} + + +static void +ngx_resolver_tcp_read(ngx_event_t *rev) +{ + u_char *p; + size_t size; + ssize_t n; + u_short qlen; + ngx_buf_t *b; + ngx_resolver_t *r; + ngx_connection_t *c; + ngx_resolver_connection_t *rec; + + c = rev->data; + rec = c->data; + b = rec->read_buf; + r = rec->resolver; + + while (rev->ready) { + n = ngx_recv(c, b->last, b->end - b->last); + + if (n == NGX_AGAIN) { + break; + } + + if (n == NGX_ERROR || n == 0) { + goto failed; + } + + b->last += n; + + for ( ;; ) { + p = b->pos; + size = b->last - p; + + if (size < 2) { + break; + } + + qlen = (u_short) *p++ << 8; + qlen += *p++; + + if (size < (size_t) (2 + qlen)) { + break; + } + + ngx_resolver_process_response(r, p, qlen, 1); + + b->pos += 2 + qlen; + } + + if (b->pos != b->start) { + b->last = ngx_movemem(b->start, b->pos, b->last - b->pos); + b->pos = b->start; + } + } + + if (ngx_handle_read_event(rev, 0) != NGX_OK) { + goto failed; + } + + return; + +failed: + + ngx_close_connection(c); + rec->tcp = NULL; +} + + +static void +ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf, size_t n, + ngx_uint_t tcp) { char *err; - ngx_uint_t i, times, ident, qident, flags, code, nqs, nan, + ngx_uint_t i, times, ident, qident, flags, code, nqs, nan, trunc, qtype, qclass; #if (NGX_HAVE_INET6) ngx_uint_t qident6; @@ -1317,6 +1589,7 @@ ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf, size_t n) flags = (response->flags_hi << 8) + response->flags_lo; nqs = (response->nqs_hi << 8) + response->nqs_lo; nan = (response->nan_hi << 8) + response->nan_lo; + trunc = flags & 0x0200; ngx_log_debug6(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver DNS response %ui fl:%04Xui %ui/%ui/%ud/%ud", @@ -1325,9 +1598,10 @@ ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf, size_t n) (response->nar_hi << 8) + response->nar_lo); /* response to a standard query */ - if ((flags & 0xf870) != 0x8000) { + if ((flags & 0xf870) != 0x8000 || (trunc && tcp)) { ngx_log_error(r->log_level, r->log, 0, - "invalid DNS response %ui fl:%04Xui", ident, flags); + "invalid %s DNS response %ui fl:%04Xui", + tcp ? "TCP" : "UDP", ident, flags); return; } @@ -1417,7 +1691,7 @@ found: case NGX_RESOLVE_AAAA: #endif - ngx_resolver_process_a(r, buf, n, ident, code, qtype, nan, + ngx_resolver_process_a(r, buf, n, ident, code, qtype, nan, trunc, i + sizeof(ngx_resolver_qs_t)); break; @@ -1464,28 +1738,29 @@ dns_error: static void -ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last, +ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t n, ngx_uint_t ident, ngx_uint_t code, ngx_uint_t qtype, - ngx_uint_t nan, ngx_uint_t ans) + ngx_uint_t nan, ngx_uint_t trunc, ngx_uint_t ans) { - char *err; - u_char *cname; - size_t len; - int32_t ttl; - uint32_t hash; - in_addr_t *addr; - ngx_str_t name; - ngx_addr_t *addrs; - ngx_uint_t type, class, qident, naddrs, a, i, n, start; + char *err; + u_char *cname; + size_t len; + int32_t ttl; + uint32_t hash; + in_addr_t *addr; + ngx_str_t name; + ngx_addr_t *addrs; + ngx_uint_t type, class, qident, naddrs, a, i, j, start; #if (NGX_HAVE_INET6) - struct in6_addr *addr6; + struct in6_addr *addr6; #endif - ngx_resolver_an_t *an; - ngx_resolver_ctx_t *ctx, *next; - ngx_resolver_node_t *rn; + ngx_resolver_an_t *an; + ngx_resolver_ctx_t *ctx, *next; + ngx_resolver_node_t *rn; + ngx_resolver_connection_t *rec; if (ngx_resolver_copy(r, &name, buf, - buf + sizeof(ngx_resolver_hdr_t), buf + last) + buf + sizeof(ngx_resolver_hdr_t), buf + n) != NGX_OK) { return; @@ -1518,6 +1793,11 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last, goto failed; } + if (trunc && rn->tcp6) { + ngx_resolver_free(r, name.data); + goto failed; + } + qident = (rn->query6[0] << 8) + rn->query6[1]; break; @@ -1532,6 +1812,11 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last, goto failed; } + if (trunc && rn->tcp) { + ngx_resolver_free(r, name.data); + goto failed; + } + qident = (rn->query[0] << 8) + rn->query[1]; } @@ -1545,6 +1830,45 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last, ngx_resolver_free(r, name.data); + if (trunc) { + + ngx_queue_remove(&rn->queue); + + if (rn->waiting == NULL) { + ngx_rbtree_delete(&r->name_rbtree, &rn->node); + ngx_resolver_free_node(r, rn); + goto next; + } + + rec = r->connections.elts; + rec = &rec[rn->last_connection]; + + switch (qtype) { + +#if (NGX_HAVE_INET6) + case NGX_RESOLVE_AAAA: + + rn->tcp6 = 1; + + (void) ngx_resolver_send_tcp_query(r, rec, rn->query6, rn->qlen); + + break; +#endif + + default: /* NGX_RESOLVE_A */ + + rn->tcp = 1; + + (void) ngx_resolver_send_tcp_query(r, rec, rn->query, rn->qlen); + } + + rn->expire = ngx_time() + r->resend_timeout; + + ngx_queue_insert_head(&r->name_resend_queue, &rn->queue); + + goto next; + } + if (code == 0 && rn->code) { code = rn->code; } @@ -1642,7 +1966,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last, start = i; - while (i < last) { + while (i < n) { if (buf[i] & 0xc0) { i += 2; @@ -1668,7 +1992,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last, found: - if (i + sizeof(ngx_resolver_an_t) >= last) { + if (i + sizeof(ngx_resolver_an_t) >= n) { goto short_response; } @@ -1708,7 +2032,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last, goto invalid; } - if (i + 4 > last) { + if (i + 4 > n) { goto short_response; } @@ -1729,7 +2053,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last, goto invalid; } - if (i + 16 > last) { + if (i + 16 > n) { goto short_response; } @@ -1810,7 +2134,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last, #endif } - n = 0; + j = 0; i = ans; for (a = 0; a < nan; a++) { @@ -1839,10 +2163,10 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last, if (type == NGX_RESOLVE_A) { - addr[n] = htonl((buf[i] << 24) + (buf[i + 1] << 16) + addr[j] = htonl((buf[i] << 24) + (buf[i + 1] << 16) + (buf[i + 2] << 8) + (buf[i + 3])); - if (++n == naddrs) { + if (++j == naddrs) { #if (NGX_HAVE_INET6) if (rn->naddrs6 == (u_short) -1) { @@ -1857,9 +2181,9 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last, #if (NGX_HAVE_INET6) else if (type == NGX_RESOLVE_AAAA) { - ngx_memcpy(addr6[n].s6_addr, &buf[i], 16); + ngx_memcpy(addr6[j].s6_addr, &buf[i], 16); - if (++n == naddrs) { + if (++j == naddrs) { if (rn->naddrs == (u_short) -1) { goto next; @@ -1984,7 +2308,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last, goto next; } - if (ngx_resolver_copy(r, &name, buf, cname, buf + last) != NGX_OK) { + if (ngx_resolver_copy(r, &name, buf, cname, buf + n) != NGX_OK) { goto failed; } @@ -2072,12 +2396,11 @@ ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n, { char *err; size_t len; - u_char text[NGX_SOCKADDR_STRLEN]; in_addr_t addr; int32_t ttl; ngx_int_t octet; ngx_str_t name; - ngx_uint_t i, mask, qident, class; + ngx_uint_t mask, type, class, qident, a, i, start; ngx_queue_t *expire_queue; ngx_rbtree_t *tree; ngx_resolver_an_t *an; @@ -2089,13 +2412,15 @@ ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n, struct in6_addr addr6; #endif - if (ngx_resolver_copy(r, NULL, buf, + if (ngx_resolver_copy(r, &name, buf, buf + sizeof(ngx_resolver_hdr_t), buf + n) != NGX_OK) { return; } + ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver qs:%V", &name); + /* AF_INET */ addr = 0; @@ -2123,10 +2448,6 @@ ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n, tree = &r->addr_rbtree; expire_queue = &r->addr_expire_queue; - addr = htonl(addr); - name.len = ngx_inet_ntop(AF_INET, &addr, text, NGX_SOCKADDR_STRLEN); - name.data = text; - goto valid; } @@ -2171,9 +2492,6 @@ invalid_in_addr_arpa: tree = &r->addr6_rbtree; expire_queue = &r->addr6_expire_queue; - name.len = ngx_inet6_ntop(addr6.s6_addr, text, NGX_SOCKADDR_STRLEN); - name.data = text; - goto valid; } @@ -2182,6 +2500,7 @@ invalid_ip6_arpa: ngx_log_error(r->log_level, r->log, 0, "invalid in-addr.arpa or ip6.arpa name in DNS response"); + ngx_resolver_free(r, name.data); return; valid: @@ -2189,6 +2508,7 @@ valid: if (rn == NULL || rn->query == NULL) { ngx_log_error(r->log_level, r->log, 0, "unexpected response for %V", &name); + ngx_resolver_free(r, name.data); goto failed; } @@ -2198,9 +2518,12 @@ valid: ngx_log_error(r->log_level, r->log, 0, "wrong ident %ui response for %V, expect %ui", ident, &name, qident); + ngx_resolver_free(r, name.data); goto failed; } + ngx_resolver_free(r, name.data); + if (code == 0 && nan == 0) { code = NGX_RESOLVE_NXDOMAIN; } @@ -2230,44 +2553,90 @@ valid: i += sizeof(ngx_resolver_qs_t); - if (i + 2 + sizeof(ngx_resolver_an_t) >= n) { + for (a = 0; a < nan; a++) { + + start = i; + + while (i < n) { + + if (buf[i] & 0xc0) { + i += 2; + goto found; + } + + if (buf[i] == 0) { + i++; + goto test_length; + } + + i += 1 + buf[i]; + } + goto short_response; + + test_length: + + if (i - start < 2) { + err = "invalid name in DNS response"; + goto invalid; + } + + found: + + if (i + sizeof(ngx_resolver_an_t) >= n) { + goto short_response; + } + + an = (ngx_resolver_an_t *) &buf[i]; + + type = (an->type_hi << 8) + an->type_lo; + class = (an->class_hi << 8) + an->class_lo; + len = (an->len_hi << 8) + an->len_lo; + ttl = (an->ttl[0] << 24) + (an->ttl[1] << 16) + + (an->ttl[2] << 8) + (an->ttl[3]); + + if (class != 1) { + ngx_log_error(r->log_level, r->log, 0, + "unexpected RR class %ui", class); + goto failed; + } + + if (ttl < 0) { + ttl = 0; + } + + ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0, + "resolver qt:%ui cl:%ui len:%uz", + type, class, len); + + i += sizeof(ngx_resolver_an_t); + + switch (type) { + + case NGX_RESOLVE_PTR: + + goto ptr; + + case NGX_RESOLVE_CNAME: + + break; + + default: + + ngx_log_error(r->log_level, r->log, 0, + "unexpected RR type %ui", type); + } + + i += len; } - /* compression pointer to *.arpa */ + /* unlock addr mutex */ - if (buf[i] != 0xc0 || buf[i + 1] != sizeof(ngx_resolver_hdr_t)) { - err = "invalid in-addr.arpa or ip6.arpa name in DNS response"; - goto invalid; - } + ngx_log_error(r->log_level, r->log, 0, + "no PTR type in DNS response"); + return; - an = (ngx_resolver_an_t *) &buf[i + 2]; - - class = (an->class_hi << 8) + an->class_lo; - len = (an->len_hi << 8) + an->len_lo; - ttl = (an->ttl[0] << 24) + (an->ttl[1] << 16) - + (an->ttl[2] << 8) + (an->ttl[3]); - - if (class != 1) { - ngx_log_error(r->log_level, r->log, 0, - "unexpected RR class %ui", class); - goto failed; - } - - if (ttl < 0) { - ttl = 0; - } - - ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0, - "resolver qt:%ui cl:%ui len:%uz", - (an->type_hi << 8) + an->type_lo, - class, len); - - i += 2 + sizeof(ngx_resolver_an_t); - - if (i + len > n) { - goto short_response; - } +ptr: if (ngx_resolver_copy(r, &name, buf, buf + i, buf + n) != NGX_OK) { goto failed; @@ -3074,8 +3443,8 @@ ngx_resolver_strerror(ngx_int_t err) static u_char * ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t len) { - u_char *p; - ngx_udp_connection_t *uc; + u_char *p; + ngx_resolver_connection_t *rec; p = buf; @@ -3084,10 +3453,10 @@ ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t len) len -= p - buf; } - uc = log->data; + rec = log->data; - if (uc) { - p = ngx_snprintf(p, len, ", resolver: %V", &uc->server); + if (rec) { + p = ngx_snprintf(p, len, ", resolver: %V", &rec->server); } return p; @@ -3095,7 +3464,7 @@ ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t len) ngx_int_t -ngx_udp_connect(ngx_udp_connection_t *uc) +ngx_udp_connect(ngx_resolver_connection_t *rec) { int rc; ngx_int_t event; @@ -3103,21 +3472,21 @@ ngx_udp_connect(ngx_udp_connection_t *uc) ngx_socket_t s; ngx_connection_t *c; - s = ngx_socket(uc->sockaddr->sa_family, SOCK_DGRAM, 0); + s = ngx_socket(rec->sockaddr->sa_family, SOCK_DGRAM, 0); - ngx_log_debug1(NGX_LOG_DEBUG_EVENT, &uc->log, 0, "UDP socket %d", s); + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, &rec->log, 0, "UDP socket %d", s); if (s == (ngx_socket_t) -1) { - ngx_log_error(NGX_LOG_ALERT, &uc->log, ngx_socket_errno, + ngx_log_error(NGX_LOG_ALERT, &rec->log, ngx_socket_errno, ngx_socket_n " failed"); return NGX_ERROR; } - c = ngx_get_connection(s, &uc->log); + c = ngx_get_connection(s, &rec->log); if (c == NULL) { if (ngx_close_socket(s) == -1) { - ngx_log_error(NGX_LOG_ALERT, &uc->log, ngx_socket_errno, + ngx_log_error(NGX_LOG_ALERT, &rec->log, ngx_socket_errno, ngx_close_socket_n "failed"); } @@ -3125,7 +3494,7 @@ ngx_udp_connect(ngx_udp_connection_t *uc) } if (ngx_nonblocking(s) == -1) { - ngx_log_error(NGX_LOG_ALERT, &uc->log, ngx_socket_errno, + ngx_log_error(NGX_LOG_ALERT, &rec->log, ngx_socket_errno, ngx_nonblocking_n " failed"); goto failed; @@ -3134,22 +3503,22 @@ ngx_udp_connect(ngx_udp_connection_t *uc) rev = c->read; wev = c->write; - rev->log = &uc->log; - wev->log = &uc->log; + rev->log = &rec->log; + wev->log = &rec->log; - uc->connection = c; + rec->udp = c; c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1); - ngx_log_debug3(NGX_LOG_DEBUG_EVENT, &uc->log, 0, - "connect to %V, fd:%d #%uA", &uc->server, s, c->number); + ngx_log_debug3(NGX_LOG_DEBUG_EVENT, &rec->log, 0, + "connect to %V, fd:%d #%uA", &rec->server, s, c->number); - rc = connect(s, uc->sockaddr, uc->socklen); + rc = connect(s, rec->sockaddr, rec->socklen); /* TODO: iocp */ if (rc == -1) { - ngx_log_error(NGX_LOG_CRIT, &uc->log, ngx_socket_errno, + ngx_log_error(NGX_LOG_CRIT, &rec->log, ngx_socket_errno, "connect() failed"); goto failed; @@ -3172,7 +3541,190 @@ ngx_udp_connect(ngx_udp_connection_t *uc) failed: ngx_close_connection(c); - uc->connection = NULL; + rec->udp = NULL; + + return NGX_ERROR; +} + + +ngx_int_t +ngx_tcp_connect(ngx_resolver_connection_t *rec) +{ + int rc; + ngx_int_t event; + ngx_err_t err; + ngx_uint_t level; + ngx_socket_t s; + ngx_event_t *rev, *wev; + ngx_connection_t *c; + + s = ngx_socket(rec->sockaddr->sa_family, SOCK_STREAM, 0); + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, &rec->log, 0, "TCP socket %d", s); + + if (s == (ngx_socket_t) -1) { + ngx_log_error(NGX_LOG_ALERT, &rec->log, ngx_socket_errno, + ngx_socket_n " failed"); + return NGX_ERROR; + } + + c = ngx_get_connection(s, &rec->log); + + if (c == NULL) { + if (ngx_close_socket(s) == -1) { + ngx_log_error(NGX_LOG_ALERT, &rec->log, ngx_socket_errno, + ngx_close_socket_n "failed"); + } + + return NGX_ERROR; + } + + if (ngx_nonblocking(s) == -1) { + ngx_log_error(NGX_LOG_ALERT, &rec->log, ngx_socket_errno, + ngx_nonblocking_n " failed"); + + goto failed; + } + + rev = c->read; + wev = c->write; + + rev->log = &rec->log; + wev->log = &rec->log; + + rec->tcp = c; + + c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1); + + if (ngx_add_conn) { + if (ngx_add_conn(c) == NGX_ERROR) { + goto failed; + } + } + + ngx_log_debug3(NGX_LOG_DEBUG_EVENT, &rec->log, 0, + "connect to %V, fd:%d #%uA", &rec->server, s, c->number); + + rc = connect(s, rec->sockaddr, rec->socklen); + + if (rc == -1) { + err = ngx_socket_errno; + + + if (err != NGX_EINPROGRESS +#if (NGX_WIN32) + /* Winsock returns WSAEWOULDBLOCK (NGX_EAGAIN) */ + && err != NGX_EAGAIN +#endif + ) + { + if (err == NGX_ECONNREFUSED +#if (NGX_LINUX) + /* + * Linux returns EAGAIN instead of ECONNREFUSED + * for unix sockets if listen queue is full + */ + || err == NGX_EAGAIN +#endif + || err == NGX_ECONNRESET + || err == NGX_ENETDOWN + || err == NGX_ENETUNREACH + || err == NGX_EHOSTDOWN + || err == NGX_EHOSTUNREACH) + { + level = NGX_LOG_ERR; + + } else { + level = NGX_LOG_CRIT; + } + + ngx_log_error(level, c->log, err, "connect() to %V failed", + &rec->server); + + ngx_close_connection(c); + rec->tcp = NULL; + + return NGX_ERROR; + } + } + + if (ngx_add_conn) { + if (rc == -1) { + + /* NGX_EINPROGRESS */ + + return NGX_AGAIN; + } + + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, &rec->log, 0, "connected"); + + wev->ready = 1; + + return NGX_OK; + } + + if (ngx_event_flags & NGX_USE_IOCP_EVENT) { + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, &rec->log, ngx_socket_errno, + "connect(): %d", rc); + + if (ngx_blocking(s) == -1) { + ngx_log_error(NGX_LOG_ALERT, &rec->log, ngx_socket_errno, + ngx_blocking_n " failed"); + goto failed; + } + + /* + * FreeBSD's aio allows to post an operation on non-connected socket. + * NT does not support it. + * + * TODO: check in Win32, etc. As workaround we can use NGX_ONESHOT_EVENT + */ + + rev->ready = 1; + wev->ready = 1; + + return NGX_OK; + } + + if (ngx_event_flags & NGX_USE_CLEAR_EVENT) { + + /* kqueue */ + + event = NGX_CLEAR_EVENT; + + } else { + + /* select, poll, /dev/poll */ + + event = NGX_LEVEL_EVENT; + } + + if (ngx_add_event(rev, NGX_READ_EVENT, event) != NGX_OK) { + goto failed; + } + + if (rc == -1) { + + /* NGX_EINPROGRESS */ + + if (ngx_add_event(wev, NGX_WRITE_EVENT, event) != NGX_OK) { + goto failed; + } + + return NGX_AGAIN; + } + + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, &rec->log, 0, "connected"); + + wev->ready = 1; + + return NGX_OK; + +failed: + + ngx_close_connection(c); + rec->tcp = NULL; return NGX_ERROR; } diff --git a/src/core/ngx_resolver.h b/src/core/ngx_resolver.h index 07fa257..3165abd 100644 --- a/src/core/ngx_resolver.h +++ b/src/core/ngx_resolver.h @@ -36,13 +36,20 @@ #define NGX_RESOLVER_MAX_RECURSION 50 +typedef struct ngx_resolver_s ngx_resolver_t; + + typedef struct { - ngx_connection_t *connection; + ngx_connection_t *udp; + ngx_connection_t *tcp; struct sockaddr *sockaddr; socklen_t socklen; ngx_str_t server; ngx_log_t log; -} ngx_udp_connection_t; + ngx_buf_t *read_buf; + ngx_buf_t *write_buf; + ngx_resolver_t *resolver; +} ngx_resolver_connection_t; typedef struct ngx_resolver_ctx_s ngx_resolver_ctx_t; @@ -93,11 +100,18 @@ typedef struct { time_t valid; uint32_t ttl; + unsigned tcp:1; +#if (NGX_HAVE_INET6) + unsigned tcp6:1; +#endif + + ngx_uint_t last_connection; + ngx_resolver_ctx_t *waiting; } ngx_resolver_node_t; -typedef struct { +struct ngx_resolver_s { /* has to be pointer because of "incomplete type" */ ngx_event_t *event; void *dummy; @@ -107,7 +121,7 @@ typedef struct { ngx_int_t ident; /* simple round robin DNS peers balancer */ - ngx_array_t udp_connections; + ngx_array_t connections; ngx_uint_t last_connection; ngx_rbtree_t name_rbtree; @@ -131,17 +145,18 @@ typedef struct { #endif time_t resend_timeout; + time_t tcp_timeout; time_t expire; time_t valid; ngx_uint_t log_level; -} ngx_resolver_t; +}; struct ngx_resolver_ctx_s { ngx_resolver_ctx_t *next; ngx_resolver_t *resolver; - ngx_udp_connection_t *udp_connection; + ngx_resolver_node_t *node; /* event ident must be after 3 pointers as in ngx_connection_t */ ngx_int_t ident; @@ -161,8 +176,6 @@ struct ngx_resolver_ctx_s { ngx_uint_t quick; /* unsigned quick:1; */ ngx_uint_t recursion; ngx_event_t *event; - - ngx_resolver_node_t *node; }; diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c index 15da213..955622b 100644 --- a/src/event/ngx_event.c +++ b/src/event/ngx_event.c @@ -606,16 +606,16 @@ ngx_event_process_init(ngx_cycle_t *cycle) return NGX_ERROR; } - for (m = 0; ngx_modules[m]; m++) { - if (ngx_modules[m]->type != NGX_EVENT_MODULE) { + for (m = 0; cycle->modules[m]; m++) { + if (cycle->modules[m]->type != NGX_EVENT_MODULE) { continue; } - if (ngx_modules[m]->ctx_index != ecf->use) { + if (cycle->modules[m]->ctx_index != ecf->use) { continue; } - module = ngx_modules[m]->ctx; + module = cycle->modules[m]->ctx; if (module->actions.init(cycle, ngx_timer_resolution) != NGX_OK) { /* fatal */ @@ -891,14 +891,7 @@ ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) /* count the number of the event modules and set up their indices */ - ngx_event_max_module = 0; - for (i = 0; ngx_modules[i]; i++) { - if (ngx_modules[i]->type != NGX_EVENT_MODULE) { - continue; - } - - ngx_modules[i]->ctx_index = ngx_event_max_module++; - } + ngx_event_max_module = ngx_count_modules(cf->cycle, NGX_EVENT_MODULE); ctx = ngx_pcalloc(cf->pool, sizeof(void *)); if (ctx == NULL) { @@ -912,16 +905,17 @@ ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) *(void **) conf = ctx; - for (i = 0; ngx_modules[i]; i++) { - if (ngx_modules[i]->type != NGX_EVENT_MODULE) { + for (i = 0; cf->cycle->modules[i]; i++) { + if (cf->cycle->modules[i]->type != NGX_EVENT_MODULE) { continue; } - m = ngx_modules[i]->ctx; + m = cf->cycle->modules[i]->ctx; if (m->create_conf) { - (*ctx)[ngx_modules[i]->ctx_index] = m->create_conf(cf->cycle); - if ((*ctx)[ngx_modules[i]->ctx_index] == NULL) { + (*ctx)[cf->cycle->modules[i]->ctx_index] = + m->create_conf(cf->cycle); + if ((*ctx)[cf->cycle->modules[i]->ctx_index] == NULL) { return NGX_CONF_ERROR; } } @@ -940,15 +934,16 @@ ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return rv; } - for (i = 0; ngx_modules[i]; i++) { - if (ngx_modules[i]->type != NGX_EVENT_MODULE) { + for (i = 0; cf->cycle->modules[i]; i++) { + if (cf->cycle->modules[i]->type != NGX_EVENT_MODULE) { continue; } - m = ngx_modules[i]->ctx; + m = cf->cycle->modules[i]->ctx; if (m->init_conf) { - rv = m->init_conf(cf->cycle, (*ctx)[ngx_modules[i]->ctx_index]); + rv = m->init_conf(cf->cycle, + (*ctx)[cf->cycle->modules[i]->ctx_index]); if (rv != NGX_CONF_OK) { return rv; } @@ -1009,15 +1004,15 @@ ngx_event_use(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) } - for (m = 0; ngx_modules[m]; m++) { - if (ngx_modules[m]->type != NGX_EVENT_MODULE) { + for (m = 0; cf->cycle->modules[m]; m++) { + if (cf->cycle->modules[m]->type != NGX_EVENT_MODULE) { continue; } - module = ngx_modules[m]->ctx; + module = cf->cycle->modules[m]->ctx; if (module->name->len == value[1].len) { if (ngx_strcmp(module->name->data, value[1].data) == 0) { - ecf->use = ngx_modules[m]->ctx_index; + ecf->use = cf->cycle->modules[m]->ctx_index; ecf->name = module->name->data; if (ngx_process == NGX_PROCESS_SINGLE @@ -1232,20 +1227,20 @@ ngx_event_core_init_conf(ngx_cycle_t *cycle, void *conf) #endif if (module == NULL) { - for (i = 0; ngx_modules[i]; i++) { + for (i = 0; cycle->modules[i]; i++) { - if (ngx_modules[i]->type != NGX_EVENT_MODULE) { + if (cycle->modules[i]->type != NGX_EVENT_MODULE) { continue; } - event_module = ngx_modules[i]->ctx; + event_module = cycle->modules[i]->ctx; if (ngx_strcmp(event_module->name->data, event_core_name.data) == 0) { continue; } - module = ngx_modules[i]; + module = cycle->modules[i]; break; } } diff --git a/src/http/modules/ngx_http_rewrite_module.c b/src/http/modules/ngx_http_rewrite_module.c index 754512f..2ec7f5d 100644 --- a/src/http/modules/ngx_http_rewrite_module.c +++ b/src/http/modules/ngx_http_rewrite_module.c @@ -560,12 +560,12 @@ ngx_http_rewrite_if(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_ERROR; } - for (i = 0; ngx_modules[i]; i++) { - if (ngx_modules[i]->type != NGX_HTTP_MODULE) { + for (i = 0; cf->cycle->modules[i]; i++) { + if (cf->cycle->modules[i]->type != NGX_HTTP_MODULE) { continue; } - module = ngx_modules[i]->ctx; + module = cf->cycle->modules[i]->ctx; if (module->create_loc_conf) { @@ -574,7 +574,7 @@ ngx_http_rewrite_if(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_ERROR; } - ctx->loc_conf[ngx_modules[i]->ctx_index] = mconf; + ctx->loc_conf[cf->cycle->modules[i]->ctx_index] = mconf; } } diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c index 64af447..0ceb613 100644 --- a/src/http/ngx_http.c +++ b/src/http/ngx_http.c @@ -144,14 +144,7 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) /* count the number of the http modules and set up their indices */ - ngx_http_max_module = 0; - for (m = 0; ngx_modules[m]; m++) { - if (ngx_modules[m]->type != NGX_HTTP_MODULE) { - continue; - } - - ngx_modules[m]->ctx_index = ngx_http_max_module++; - } + ngx_http_max_module = ngx_count_modules(cf->cycle, NGX_HTTP_MODULE); /* the http main_conf context, it is the same in the all http contexts */ @@ -190,13 +183,13 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) * of the all http modules */ - for (m = 0; ngx_modules[m]; m++) { - if (ngx_modules[m]->type != NGX_HTTP_MODULE) { + for (m = 0; cf->cycle->modules[m]; m++) { + if (cf->cycle->modules[m]->type != NGX_HTTP_MODULE) { continue; } - module = ngx_modules[m]->ctx; - mi = ngx_modules[m]->ctx_index; + module = cf->cycle->modules[m]->ctx; + mi = cf->cycle->modules[m]->ctx_index; if (module->create_main_conf) { ctx->main_conf[mi] = module->create_main_conf(cf); @@ -223,12 +216,12 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) pcf = *cf; cf->ctx = ctx; - for (m = 0; ngx_modules[m]; m++) { - if (ngx_modules[m]->type != NGX_HTTP_MODULE) { + for (m = 0; cf->cycle->modules[m]; m++) { + if (cf->cycle->modules[m]->type != NGX_HTTP_MODULE) { continue; } - module = ngx_modules[m]->ctx; + module = cf->cycle->modules[m]->ctx; if (module->preconfiguration) { if (module->preconfiguration(cf) != NGX_OK) { @@ -255,13 +248,13 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) cmcf = ctx->main_conf[ngx_http_core_module.ctx_index]; cscfp = cmcf->servers.elts; - for (m = 0; ngx_modules[m]; m++) { - if (ngx_modules[m]->type != NGX_HTTP_MODULE) { + for (m = 0; cf->cycle->modules[m]; m++) { + if (cf->cycle->modules[m]->type != NGX_HTTP_MODULE) { continue; } - module = ngx_modules[m]->ctx; - mi = ngx_modules[m]->ctx_index; + module = cf->cycle->modules[m]->ctx; + mi = cf->cycle->modules[m]->ctx_index; /* init http{} main_conf's */ @@ -304,12 +297,12 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) } - for (m = 0; ngx_modules[m]; m++) { - if (ngx_modules[m]->type != NGX_HTTP_MODULE) { + for (m = 0; cf->cycle->modules[m]; m++) { + if (cf->cycle->modules[m]->type != NGX_HTTP_MODULE) { continue; } - module = ngx_modules[m]->ctx; + module = cf->cycle->modules[m]->ctx; if (module->postconfiguration) { if (module->postconfiguration(cf) != NGX_OK) { diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index 4b8dd4c..df7e8d4 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -2968,12 +2968,12 @@ ngx_http_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) return NGX_CONF_ERROR; } - for (i = 0; ngx_modules[i]; i++) { - if (ngx_modules[i]->type != NGX_HTTP_MODULE) { + for (i = 0; cf->cycle->modules[i]; i++) { + if (cf->cycle->modules[i]->type != NGX_HTTP_MODULE) { continue; } - module = ngx_modules[i]->ctx; + module = cf->cycle->modules[i]->ctx; if (module->create_srv_conf) { mconf = module->create_srv_conf(cf); @@ -2981,7 +2981,7 @@ ngx_http_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) return NGX_CONF_ERROR; } - ctx->srv_conf[ngx_modules[i]->ctx_index] = mconf; + ctx->srv_conf[cf->cycle->modules[i]->ctx_index] = mconf; } if (module->create_loc_conf) { @@ -2990,7 +2990,7 @@ ngx_http_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) return NGX_CONF_ERROR; } - ctx->loc_conf[ngx_modules[i]->ctx_index] = mconf; + ctx->loc_conf[cf->cycle->modules[i]->ctx_index] = mconf; } } @@ -3086,17 +3086,17 @@ ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) return NGX_CONF_ERROR; } - for (i = 0; ngx_modules[i]; i++) { - if (ngx_modules[i]->type != NGX_HTTP_MODULE) { + for (i = 0; cf->cycle->modules[i]; i++) { + if (cf->cycle->modules[i]->type != NGX_HTTP_MODULE) { continue; } - module = ngx_modules[i]->ctx; + module = cf->cycle->modules[i]->ctx; if (module->create_loc_conf) { - ctx->loc_conf[ngx_modules[i]->ctx_index] = + ctx->loc_conf[cf->cycle->modules[i]->ctx_index] = module->create_loc_conf(cf); - if (ctx->loc_conf[ngx_modules[i]->ctx_index] == NULL) { + if (ctx->loc_conf[cf->cycle->modules[i]->ctx_index] == NULL) { return NGX_CONF_ERROR; } } @@ -4607,12 +4607,12 @@ ngx_http_core_limit_except(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_ERROR; } - for (i = 0; ngx_modules[i]; i++) { - if (ngx_modules[i]->type != NGX_HTTP_MODULE) { + for (i = 0; cf->cycle->modules[i]; i++) { + if (cf->cycle->modules[i]->type != NGX_HTTP_MODULE) { continue; } - module = ngx_modules[i]->ctx; + module = cf->cycle->modules[i]->ctx; if (module->create_loc_conf) { @@ -4621,7 +4621,7 @@ ngx_http_core_limit_except(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_ERROR; } - ctx->loc_conf[ngx_modules[i]->ctx_index] = mconf; + ctx->loc_conf[cf->cycle->modules[i]->ctx_index] = mconf; } } diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c index 7f377b6..dbaa956 100644 --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -5331,12 +5331,12 @@ ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) return NGX_CONF_ERROR; } - for (m = 0; ngx_modules[m]; m++) { - if (ngx_modules[m]->type != NGX_HTTP_MODULE) { + for (m = 0; cf->cycle->modules[m]; m++) { + if (cf->cycle->modules[m]->type != NGX_HTTP_MODULE) { continue; } - module = ngx_modules[m]->ctx; + module = cf->cycle->modules[m]->ctx; if (module->create_srv_conf) { mconf = module->create_srv_conf(cf); @@ -5344,7 +5344,7 @@ ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) return NGX_CONF_ERROR; } - ctx->srv_conf[ngx_modules[m]->ctx_index] = mconf; + ctx->srv_conf[cf->cycle->modules[m]->ctx_index] = mconf; } if (module->create_loc_conf) { @@ -5353,7 +5353,7 @@ ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) return NGX_CONF_ERROR; } - ctx->loc_conf[ngx_modules[m]->ctx_index] = mconf; + ctx->loc_conf[cf->cycle->modules[m]->ctx_index] = mconf; } } diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c index 869ce08..4e378c9 100644 --- a/src/http/v2/ngx_http_v2.c +++ b/src/http/v2/ngx_http_v2.c @@ -251,7 +251,7 @@ ngx_http_v2_init(ngx_event_t *rev) return; } - cln = ngx_pool_cleanup_add(c->pool, sizeof(ngx_pool_cleanup_file_t)); + cln = ngx_pool_cleanup_add(c->pool, 0); if (cln == NULL) { ngx_http_close_connection(c); return; @@ -1185,6 +1185,8 @@ ngx_http_v2_state_headers(ngx_http_v2_connection_t *h2c, u_char *pos, return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR); } + stream->request->request_length = h2c->state.length; + stream->in_closed = h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG; stream->node = node; @@ -1731,11 +1733,21 @@ ngx_http_v2_handle_continuation(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end, ngx_http_v2_handler_pt handler) { u_char *p; - size_t len; + size_t len, skip; uint32_t head; len = h2c->state.length; + if (h2c->state.padding && (size_t) (end - pos) > len) { + skip = ngx_min(h2c->state.padding, (end - pos) - len); + + h2c->state.padding -= skip; + + p = pos; + pos += skip; + ngx_memmove(pos, p, len); + } + if ((size_t) (end - pos) < len + NGX_HTTP_V2_FRAME_HEADER_SIZE) { return ngx_http_v2_state_save(h2c, pos, end, handler); } @@ -1751,7 +1763,6 @@ ngx_http_v2_handle_continuation(ngx_http_v2_connection_t *h2c, u_char *pos, return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR); } - h2c->state.length += ngx_http_v2_parse_length(head); h2c->state.flags |= p[4]; if (h2c->state.sid != ngx_http_v2_parse_sid(&p[5])) { @@ -1766,6 +1777,14 @@ ngx_http_v2_handle_continuation(ngx_http_v2_connection_t *h2c, u_char *pos, ngx_memcpy(pos, p, len); + len = ngx_http_v2_parse_length(head); + + h2c->state.length += len; + + if (h2c->state.stream) { + h2c->state.stream->request->request_length += len; + } + h2c->state.handler = handler; return pos; } diff --git a/src/http/v2/ngx_http_v2.h b/src/http/v2/ngx_http_v2.h index 4c63b21..0f03922 100644 --- a/src/http/v2/ngx_http_v2.h +++ b/src/http/v2/ngx_http_v2.h @@ -167,7 +167,6 @@ struct ngx_http_v2_stream_s { ngx_http_v2_connection_t *connection; ngx_http_v2_node_t *node; - ngx_uint_t header_buffers; ngx_uint_t queued; /* diff --git a/src/http/v2/ngx_http_v2_filter_module.c b/src/http/v2/ngx_http_v2_filter_module.c index ed30fe5..ea58979 100644 --- a/src/http/v2/ngx_http_v2_filter_module.c +++ b/src/http/v2/ngx_http_v2_filter_module.c @@ -215,8 +215,8 @@ ngx_http_v2_header_filter(ngx_http_request_t *r) clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); if (r->headers_out.server == NULL) { - len += 1 + clcf->server_tokens ? ngx_http_v2_literal_size(NGINX_VER) - : ngx_http_v2_literal_size("nginx"); + len += 1 + (clcf->server_tokens ? ngx_http_v2_literal_size(NGINX_VER) + : ngx_http_v2_literal_size("nginx")); } if (r->headers_out.date == NULL) { diff --git a/src/mail/ngx_mail.c b/src/mail/ngx_mail.c index 962ae8b..6ad5a67 100644 --- a/src/mail/ngx_mail.c +++ b/src/mail/ngx_mail.c @@ -91,14 +91,7 @@ ngx_mail_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) /* count the number of the mail modules and set up their indices */ - ngx_mail_max_module = 0; - for (m = 0; ngx_modules[m]; m++) { - if (ngx_modules[m]->type != NGX_MAIL_MODULE) { - continue; - } - - ngx_modules[m]->ctx_index = ngx_mail_max_module++; - } + ngx_mail_max_module = ngx_count_modules(cf->cycle, NGX_MAIL_MODULE); /* the mail main_conf context, it is the same in the all mail contexts */ @@ -125,13 +118,13 @@ ngx_mail_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) * create the main_conf's and the null srv_conf's of the all mail modules */ - for (m = 0; ngx_modules[m]; m++) { - if (ngx_modules[m]->type != NGX_MAIL_MODULE) { + for (m = 0; cf->cycle->modules[m]; m++) { + if (cf->cycle->modules[m]->type != NGX_MAIL_MODULE) { continue; } - module = ngx_modules[m]->ctx; - mi = ngx_modules[m]->ctx_index; + module = cf->cycle->modules[m]->ctx; + mi = cf->cycle->modules[m]->ctx_index; if (module->create_main_conf) { ctx->main_conf[mi] = module->create_main_conf(cf); @@ -169,13 +162,13 @@ ngx_mail_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) cmcf = ctx->main_conf[ngx_mail_core_module.ctx_index]; cscfp = cmcf->servers.elts; - for (m = 0; ngx_modules[m]; m++) { - if (ngx_modules[m]->type != NGX_MAIL_MODULE) { + for (m = 0; cf->cycle->modules[m]; m++) { + if (cf->cycle->modules[m]->type != NGX_MAIL_MODULE) { continue; } - module = ngx_modules[m]->ctx; - mi = ngx_modules[m]->ctx_index; + module = cf->cycle->modules[m]->ctx; + mi = cf->cycle->modules[m]->ctx_index; /* init mail{} main_conf's */ diff --git a/src/mail/ngx_mail_core_module.c b/src/mail/ngx_mail_core_module.c index c219296..8ea8ea9 100644 --- a/src/mail/ngx_mail_core_module.c +++ b/src/mail/ngx_mail_core_module.c @@ -237,12 +237,12 @@ ngx_mail_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_ERROR; } - for (m = 0; ngx_modules[m]; m++) { - if (ngx_modules[m]->type != NGX_MAIL_MODULE) { + for (m = 0; cf->cycle->modules[m]; m++) { + if (cf->cycle->modules[m]->type != NGX_MAIL_MODULE) { continue; } - module = ngx_modules[m]->ctx; + module = cf->cycle->modules[m]->ctx; if (module->create_srv_conf) { mconf = module->create_srv_conf(cf); @@ -250,7 +250,7 @@ ngx_mail_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_ERROR; } - ctx->srv_conf[ngx_modules[m]->ctx_index] = mconf; + ctx->srv_conf[cf->cycle->modules[m]->ctx_index] = mconf; } } @@ -392,12 +392,12 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) #endif if (cscf->protocol == NULL) { - for (m = 0; ngx_modules[m]; m++) { - if (ngx_modules[m]->type != NGX_MAIL_MODULE) { + for (m = 0; cf->cycle->modules[m]; m++) { + if (cf->cycle->modules[m]->type != NGX_MAIL_MODULE) { continue; } - module = ngx_modules[m]->ctx; + module = cf->cycle->modules[m]->ctx; if (module->protocol == NULL) { continue; @@ -595,12 +595,12 @@ ngx_mail_core_protocol(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) value = cf->args->elts; - for (m = 0; ngx_modules[m]; m++) { - if (ngx_modules[m]->type != NGX_MAIL_MODULE) { + for (m = 0; cf->cycle->modules[m]; m++) { + if (cf->cycle->modules[m]->type != NGX_MAIL_MODULE) { continue; } - module = ngx_modules[m]->ctx; + module = cf->cycle->modules[m]->ctx; if (module->protocol && ngx_strcmp(module->protocol->name.data, value[1].data) == 0) diff --git a/src/os/unix/ngx_darwin_config.h b/src/os/unix/ngx_darwin_config.h index bbad977..cfe3ce2 100644 --- a/src/os/unix/ngx_darwin_config.h +++ b/src/os/unix/ngx_darwin_config.h @@ -48,6 +48,8 @@ #include #include +#include + #ifndef IOV_MAX #define IOV_MAX 64 diff --git a/src/os/unix/ngx_dlopen.c b/src/os/unix/ngx_dlopen.c new file mode 100644 index 0000000..a0efc69 --- /dev/null +++ b/src/os/unix/ngx_dlopen.c @@ -0,0 +1,28 @@ + +/* + * Copyright (C) Maxim Dounin + * Copyright (C) Nginx, Inc. + */ + + +#include +#include + + +#if (NGX_HAVE_DLOPEN) + +char * +ngx_dlerror(void) +{ + char *err; + + err = (char *) dlerror(); + + if (err == NULL) { + return ""; + } + + return err; +} + +#endif diff --git a/src/os/unix/ngx_dlopen.h b/src/os/unix/ngx_dlopen.h new file mode 100644 index 0000000..7a3159f --- /dev/null +++ b/src/os/unix/ngx_dlopen.h @@ -0,0 +1,31 @@ + +/* + * Copyright (C) Maxim Dounin + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_DLOPEN_H_INCLUDED_ +#define _NGX_DLOPEN_H_INCLUDED_ + + +#include +#include + + +#define ngx_dlopen(path) dlopen((char *) path, RTLD_NOW | RTLD_GLOBAL) +#define ngx_dlopen_n "dlopen()" + +#define ngx_dlsym(handle, symbol) dlsym(handle, symbol) +#define ngx_dlsym_n "dlsym()" + +#define ngx_dlclose(handle) dlclose(handle) +#define ngx_dlclose_n "dlclose()" + + +#if (NGX_HAVE_DLOPEN) +char *ngx_dlerror(void); +#endif + + +#endif /* _NGX_DLOPEN_H_INCLUDED_ */ diff --git a/src/os/unix/ngx_freebsd_config.h b/src/os/unix/ngx_freebsd_config.h index 9a25788..b7da48c 100644 --- a/src/os/unix/ngx_freebsd_config.h +++ b/src/os/unix/ngx_freebsd_config.h @@ -49,6 +49,8 @@ #include #include +#include + #if __FreeBSD_version < 400017 diff --git a/src/os/unix/ngx_linux_config.h b/src/os/unix/ngx_linux_config.h index 162a992..2f6129d 100644 --- a/src/os/unix/ngx_linux_config.h +++ b/src/os/unix/ngx_linux_config.h @@ -55,6 +55,8 @@ #include #include /* uname() */ +#include + #include diff --git a/src/os/unix/ngx_posix_config.h b/src/os/unix/ngx_posix_config.h index 443c4b0..bf75997 100644 --- a/src/os/unix/ngx_posix_config.h +++ b/src/os/unix/ngx_posix_config.h @@ -108,6 +108,11 @@ #include +#if (NGX_HAVE_DLOPEN) +#include +#endif + + #if (NGX_HAVE_POSIX_SEM) #include #endif diff --git a/src/os/unix/ngx_process_cycle.c b/src/os/unix/ngx_process_cycle.c index 5da0911..7c6bf7a 100644 --- a/src/os/unix/ngx_process_cycle.c +++ b/src/os/unix/ngx_process_cycle.c @@ -294,9 +294,9 @@ ngx_single_process_cycle(ngx_cycle_t *cycle) exit(2); } - for (i = 0; ngx_modules[i]; i++) { - if (ngx_modules[i]->init_process) { - if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) { + for (i = 0; cycle->modules[i]; i++) { + if (cycle->modules[i]->init_process) { + if (cycle->modules[i]->init_process(cycle) == NGX_ERROR) { /* fatal */ exit(2); } @@ -310,9 +310,9 @@ ngx_single_process_cycle(ngx_cycle_t *cycle) if (ngx_terminate || ngx_quit) { - for (i = 0; ngx_modules[i]; i++) { - if (ngx_modules[i]->exit_process) { - ngx_modules[i]->exit_process(cycle); + for (i = 0; cycle->modules[i]; i++) { + if (cycle->modules[i]->exit_process) { + cycle->modules[i]->exit_process(cycle); } } @@ -689,9 +689,9 @@ ngx_master_process_exit(ngx_cycle_t *cycle) ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exit"); - for (i = 0; ngx_modules[i]; i++) { - if (ngx_modules[i]->exit_master) { - ngx_modules[i]->exit_master(cycle); + for (i = 0; cycle->modules[i]; i++) { + if (cycle->modules[i]->exit_master) { + cycle->modules[i]->exit_master(cycle); } } @@ -895,9 +895,9 @@ ngx_worker_process_init(ngx_cycle_t *cycle, ngx_int_t worker) ls[i].previous = NULL; } - for (i = 0; ngx_modules[i]; i++) { - if (ngx_modules[i]->init_process) { - if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) { + for (i = 0; cycle->modules[i]; i++) { + if (cycle->modules[i]->init_process) { + if (cycle->modules[i]->init_process(cycle) == NGX_ERROR) { /* fatal */ exit(2); } @@ -949,9 +949,9 @@ ngx_worker_process_exit(ngx_cycle_t *cycle) ngx_uint_t i; ngx_connection_t *c; - for (i = 0; ngx_modules[i]; i++) { - if (ngx_modules[i]->exit_process) { - ngx_modules[i]->exit_process(cycle); + for (i = 0; cycle->modules[i]; i++) { + if (cycle->modules[i]->exit_process) { + cycle->modules[i]->exit_process(cycle); } } diff --git a/src/os/unix/ngx_solaris_config.h b/src/os/unix/ngx_solaris_config.h index ddfd984..ffa01c8 100644 --- a/src/os/unix/ngx_solaris_config.h +++ b/src/os/unix/ngx_solaris_config.h @@ -55,6 +55,8 @@ #include #include +#include + #define NGX_ALIGNMENT _MAX_ALIGNMENT #include diff --git a/src/stream/ngx_stream.c b/src/stream/ngx_stream.c index f0aa532..caaf38a 100644 --- a/src/stream/ngx_stream.c +++ b/src/stream/ngx_stream.c @@ -91,14 +91,7 @@ ngx_stream_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) /* count the number of the stream modules and set up their indices */ - ngx_stream_max_module = 0; - for (m = 0; ngx_modules[m]; m++) { - if (ngx_modules[m]->type != NGX_STREAM_MODULE) { - continue; - } - - ngx_modules[m]->ctx_index = ngx_stream_max_module++; - } + ngx_stream_max_module = ngx_count_modules(cf->cycle, NGX_STREAM_MODULE); /* the stream main_conf context, it's the same in the all stream contexts */ @@ -126,13 +119,13 @@ ngx_stream_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) * create the main_conf's and the null srv_conf's of the all stream modules */ - for (m = 0; ngx_modules[m]; m++) { - if (ngx_modules[m]->type != NGX_STREAM_MODULE) { + for (m = 0; cf->cycle->modules[m]; m++) { + if (cf->cycle->modules[m]->type != NGX_STREAM_MODULE) { continue; } - module = ngx_modules[m]->ctx; - mi = ngx_modules[m]->ctx_index; + module = cf->cycle->modules[m]->ctx; + mi = cf->cycle->modules[m]->ctx_index; if (module->create_main_conf) { ctx->main_conf[mi] = module->create_main_conf(cf); @@ -170,13 +163,13 @@ ngx_stream_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) cmcf = ctx->main_conf[ngx_stream_core_module.ctx_index]; cscfp = cmcf->servers.elts; - for (m = 0; ngx_modules[m]; m++) { - if (ngx_modules[m]->type != NGX_STREAM_MODULE) { + for (m = 0; cf->cycle->modules[m]; m++) { + if (cf->cycle->modules[m]->type != NGX_STREAM_MODULE) { continue; } - module = ngx_modules[m]->ctx; - mi = ngx_modules[m]->ctx_index; + module = cf->cycle->modules[m]->ctx; + mi = cf->cycle->modules[m]->ctx_index; /* init stream{} main_conf's */ @@ -208,12 +201,12 @@ ngx_stream_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) } } - for (m = 0; ngx_modules[m]; m++) { - if (ngx_modules[m]->type != NGX_STREAM_MODULE) { + for (m = 0; cf->cycle->modules[m]; m++) { + if (cf->cycle->modules[m]->type != NGX_STREAM_MODULE) { continue; } - module = ngx_modules[m]->ctx; + module = cf->cycle->modules[m]->ctx; if (module->postconfiguration) { if (module->postconfiguration(cf) != NGX_OK) { diff --git a/src/stream/ngx_stream_core_module.c b/src/stream/ngx_stream_core_module.c index 4fe6818..0ecc448 100644 --- a/src/stream/ngx_stream_core_module.c +++ b/src/stream/ngx_stream_core_module.c @@ -199,12 +199,12 @@ ngx_stream_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_ERROR; } - for (m = 0; ngx_modules[m]; m++) { - if (ngx_modules[m]->type != NGX_STREAM_MODULE) { + for (m = 0; cf->cycle->modules[m]; m++) { + if (cf->cycle->modules[m]->type != NGX_STREAM_MODULE) { continue; } - module = ngx_modules[m]->ctx; + module = cf->cycle->modules[m]->ctx; if (module->create_srv_conf) { mconf = module->create_srv_conf(cf); @@ -212,7 +212,7 @@ ngx_stream_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_ERROR; } - ctx->srv_conf[ngx_modules[m]->ctx_index] = mconf; + ctx->srv_conf[cf->cycle->modules[m]->ctx_index] = mconf; } } diff --git a/src/stream/ngx_stream_upstream.c b/src/stream/ngx_stream_upstream.c index f21e17d..805ee70 100644 --- a/src/stream/ngx_stream_upstream.c +++ b/src/stream/ngx_stream_upstream.c @@ -116,12 +116,12 @@ ngx_stream_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) uscf->srv_conf = ctx->srv_conf; - for (m = 0; ngx_modules[m]; m++) { - if (ngx_modules[m]->type != NGX_STREAM_MODULE) { + for (m = 0; cf->cycle->modules[m]; m++) { + if (cf->cycle->modules[m]->type != NGX_STREAM_MODULE) { continue; } - module = ngx_modules[m]->ctx; + module = cf->cycle->modules[m]->ctx; if (module->create_srv_conf) { mconf = module->create_srv_conf(cf); @@ -129,7 +129,7 @@ ngx_stream_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) return NGX_CONF_ERROR; } - ctx->srv_conf[ngx_modules[m]->ctx_index] = mconf; + ctx->srv_conf[cf->cycle->modules[m]->ctx_index] = mconf; } } From 586dea93587b32afc4e69a8ac53295f54c9c778d Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Thu, 11 Feb 2016 15:07:08 +0200 Subject: [PATCH 030/600] New upstream release (1.9.11) --- debian/changelog | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/debian/changelog b/debian/changelog index 5b341ce..b176a32 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +nginx (1.9.11-1) UNRELEASED; urgency=medium + + [ Christos Trochalakis ] + * New upstream release (1.9.11) (Closes: #812806) + + -- Christos Trochalakis Thu, 11 Feb 2016 15:06:38 +0200 + nginx (1.9.10-1) unstable; urgency=medium [ Christos Trochalakis ] From 3c7520faddbf9caa0320a68676110b0fb1122762 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Fri, 12 Feb 2016 12:37:52 +0200 Subject: [PATCH 031/600] Update nginx-lua module to v0.10.1rc0-5-g01727a3 Fixes building issues with nginx 1.9.11. --- debian/changelog | 3 + debian/modules/README.Modules-versions | 2 +- debian/modules/nginx-lua/README.markdown | 171 +++++---- debian/modules/nginx-lua/config | 247 ++++++------ .../modules/nginx-lua/doc/HttpLuaModule.wiki | 163 ++++---- .../nginx-lua/src/api/ngx_http_lua_api.h | 2 +- .../nginx-lua/src/ngx_http_lua_accessby.c | 9 + .../nginx-lua/src/ngx_http_lua_balancer.c | 37 +- .../nginx-lua/src/ngx_http_lua_config.c | 5 +- .../nginx-lua/src/ngx_http_lua_contentby.c | 9 + .../nginx-lua/src/ngx_http_lua_headers.c | 6 + .../nginx-lua/src/ngx_http_lua_initworkerby.c | 19 +- .../modules/nginx-lua/src/ngx_http_lua_log.c | 16 + .../nginx-lua/src/ngx_http_lua_module.c | 14 +- .../modules/nginx-lua/src/ngx_http_lua_ndk.c | 13 +- .../nginx-lua/src/ngx_http_lua_output.c | 1 + .../nginx-lua/src/ngx_http_lua_regex.c | 36 +- .../nginx-lua/src/ngx_http_lua_req_body.c | 14 +- .../nginx-lua/src/ngx_http_lua_rewriteby.c | 9 + .../nginx-lua/src/ngx_http_lua_script.h | 6 +- .../nginx-lua/src/ngx_http_lua_semaphore.c | 2 +- .../nginx-lua/src/ngx_http_lua_shdict.c | 4 +- .../nginx-lua/src/ngx_http_lua_socket_tcp.c | 7 +- .../nginx-lua/src/ngx_http_lua_socket_udp.c | 8 +- .../nginx-lua/src/ngx_http_lua_socket_udp.h | 11 +- .../nginx-lua/src/ngx_http_lua_ssl_certby.c | 25 +- .../modules/nginx-lua/src/ngx_http_lua_util.c | 11 +- debian/modules/nginx-lua/t/008-today.t | 4 +- debian/modules/nginx-lua/t/009-log.t | 107 +++++- debian/modules/nginx-lua/t/011-md5_bin.t | 4 +- debian/modules/nginx-lua/t/013-base64.t | 1 - debian/modules/nginx-lua/t/016-resp-header.t | 5 - debian/modules/nginx-lua/t/034-match.t | 31 +- debian/modules/nginx-lua/t/035-gmatch.t | 8 +- debian/modules/nginx-lua/t/036-sub.t | 25 +- debian/modules/nginx-lua/t/037-gsub.t | 27 +- debian/modules/nginx-lua/t/038-match-o.t | 10 +- debian/modules/nginx-lua/t/043-shdict.t | 19 + debian/modules/nginx-lua/t/044-req-body.t | 26 +- debian/modules/nginx-lua/t/048-match-dfa.t | 39 +- debian/modules/nginx-lua/t/050-gmatch-dfa.t | 50 +++ debian/modules/nginx-lua/t/052-sub-dfa.t | 37 +- debian/modules/nginx-lua/t/054-gsub-dfa.t | 37 +- debian/modules/nginx-lua/t/058-tcp-socket.t | 2 +- debian/modules/nginx-lua/t/059-unix-socket.t | 67 ++++ debian/modules/nginx-lua/t/062-count.t | 4 +- debian/modules/nginx-lua/t/081-bytecode.t | 57 +++ debian/modules/nginx-lua/t/101-on-abort.t | 1 + debian/modules/nginx-lua/t/106-timer.t | 1 - debian/modules/nginx-lua/t/114-config.t | 16 + .../modules/nginx-lua/t/116-raw-req-socket.t | 1 - debian/modules/nginx-lua/t/138-balancer.t | 103 +++++ debian/modules/nginx-lua/t/140-ssl-c-api.t | 363 ++++++++++++++++++ debian/modules/nginx-lua/t/cert/test2.crt | 16 + debian/modules/nginx-lua/t/cert/test2.key | 15 + .../modules/nginx-lua/t/cert/test_ecdsa.crt | 12 + .../modules/nginx-lua/t/cert/test_ecdsa.key | 5 + .../nginx-lua/util/{build2.sh => build.sh} | 0 58 files changed, 1551 insertions(+), 392 deletions(-) create mode 100644 debian/modules/nginx-lua/t/140-ssl-c-api.t create mode 100644 debian/modules/nginx-lua/t/cert/test2.crt create mode 100644 debian/modules/nginx-lua/t/cert/test2.key create mode 100644 debian/modules/nginx-lua/t/cert/test_ecdsa.crt create mode 100644 debian/modules/nginx-lua/t/cert/test_ecdsa.key rename debian/modules/nginx-lua/util/{build2.sh => build.sh} (100%) diff --git a/debian/changelog b/debian/changelog index b176a32..0f8009f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -2,6 +2,9 @@ nginx (1.9.11-1) UNRELEASED; urgency=medium [ Christos Trochalakis ] * New upstream release (1.9.11) (Closes: #812806) + * debian/modules/nginx-lua: + + Update nginx-lua to v0.10.1rc0-5-g01727a3. + Fixes buiding failures with nginx 1.9.11. -- Christos Trochalakis Thu, 11 Feb 2016 15:06:38 +0200 diff --git a/debian/modules/README.Modules-versions b/debian/modules/README.Modules-versions index eb35054..dbff74d 100644 --- a/debian/modules/README.Modules-versions +++ b/debian/modules/README.Modules-versions @@ -22,7 +22,7 @@ README for Modules versions nginx-lua Homepage: https://github.com/openresty/lua-nginx-module - Version: v0.10.0 + Version: v0.10.1rc0-5-g01727a3 nginx-upstream-fair Homepage: https://github.com/gnosek/nginx-upstream-fair diff --git a/debian/modules/nginx-lua/README.markdown b/debian/modules/nginx-lua/README.markdown index 64adc0e..94e67ad 100644 --- a/debian/modules/nginx-lua/README.markdown +++ b/debian/modules/nginx-lua/README.markdown @@ -61,7 +61,7 @@ Production ready. Version ======= -This document describes ngx_lua [v0.10.0](https://github.com/openresty/lua-nginx-module/tags) released on 11 January 2015. +This document describes ngx_lua [v0.10.0](https://github.com/openresty/lua-nginx-module/tags) released on 11 January 2016. Synopsis ======== @@ -216,6 +216,10 @@ The Lua interpreter or LuaJIT instance is shared across all the requests in a si Loaded Lua modules persist in the nginx worker process level resulting in a small memory footprint in Lua even when under heavy loads. +This module is plugged into NGINX's "http" subsystem so it can only speaks downstream communication protocols in the HTTP family (HTTP 0.9/1.0/1.1/2.0, WebSockets, and etc). +If you want to do generic TCP communications with the downstream clients, then you should use the [ngx_stream_lua](https://github.com/openresty/stream-lua-nginx-module#readme) module instead +which has a compatible Lua API. + [Back to TOC](#table-of-contents) Typical Uses @@ -256,7 +260,7 @@ Nginx cores older than 1.6.0 (exclusive) are *not* supported. Installation ============ -It is highly recommended to use the [ngx_openresty bundle](http://openresty.org) that bundles Nginx, ngx_lua, LuaJIT 2.0/2.1 (or the optional standard Lua 5.1 interpreter), as well as a package of powerful companion Nginx modules. The basic installation step is a simple command: `./configure --with-luajit && make && make install`. +It is highly recommended to use the [OpenResty bundle](http://openresty.org) that bundles Nginx, ngx_lua, LuaJIT 2.0/2.1 (or the optional standard Lua 5.1 interpreter), as well as a package of powerful companion Nginx modules. The basic installation step is a simple command: `./configure --with-luajit && make && make install`. Alternatively, ngx_lua can be manually compiled into Nginx: @@ -295,6 +299,14 @@ Build the source with this module: make install ``` +Starting from NGINX 1.9.11, you can also compile this module as a dynamic module, by using the `--add-dynamic-module=PATH` option instead of `--add-module=PATH` on the +`./configure` command line above. And then you can explicitly load the module in your `nginx.conf` via the [load_module](http://nginx.org/en/docs/ngx_core_module.html#load_module) +directive, for example, + +```nginx +load_module /path/to/modules/ngx_http_lua_module.so; +``` + [Back to TOC](#table-of-contents) C Macro Configurations @@ -591,7 +603,7 @@ If server-wide data sharing is required, then use one or more of the following a 1. Use the [ngx.shared.DICT](#ngxshareddict) API provided by this module. 1. Use only a single nginx worker and a single server (this is however not recommended when there is a multi core CPU or multiple CPUs in a single machine). -1. Use data storage mechanisms such as `memcached`, `redis`, `MySQL` or `PostgreSQL`. [The ngx_openresty bundle](http://openresty.org) associated with this module comes with a set of companion Nginx modules and Lua libraries that provide interfaces with these data storage mechanisms. +1. Use data storage mechanisms such as `memcached`, `redis`, `MySQL` or `PostgreSQL`. [The OpenResty bundle](http://openresty.org) associated with this module comes with a set of companion Nginx modules and Lua libraries that provide interfaces with these data storage mechanisms. [Back to TOC](#table-of-contents) @@ -861,7 +873,6 @@ TODO * cosocket: pool-based backend concurrency level control: implement automatic `connect` queueing when the backend concurrency exceeds its connection pool limit. * cosocket: review and merge aviramc's [patch](https://github.com/openresty/lua-nginx-module/pull/290) for adding the `bsdrecv` method. * add new API function `ngx.resp.add_header` to emulate the standard `add_header` config directive. -* [ngx.re](#ngxrematch) API: use `false` instead of `nil` in the resulting match table to indicate non-existent submatch captures, such that we can avoid "holes" in the array table. * review and apply Jader H. Silva's patch for `ngx.re.split()`. * review and apply vadim-pavlov's patch for [ngx.location.capture](#ngxlocationcapture)'s `extra_headers` option * use `ngx_hash_t` to optimize the built-in header look-up process for [ngx.req.set_header](#ngxreqset_header), [ngx.header.HEADER](#ngxheaderheader), and etc. @@ -876,7 +887,7 @@ TODO Changes ======= -The changes of every release of this module can be obtained from the ngx_openresty bundle's change logs: +The changes of every release of this module can be obtained from the OpenResty bundle's change logs: @@ -945,9 +956,9 @@ Copyright and License This module is licensed under the BSD license. -Copyright (C) 2009-2015, by Xiaozhe Wang (chaoslawful) . +Copyright (C) 2009-2016, by Xiaozhe Wang (chaoslawful) . -Copyright (C) 2009-2015, by Yichun "agentzh" Zhang (章亦春) , CloudFlare Inc. +Copyright (C) 2009-2016, by Yichun "agentzh" Zhang (章亦春) , CloudFlare Inc. All rights reserved. @@ -964,6 +975,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND See Also ======== +* [ngx_stream_lua_module](https://github.com/openresty/stream-lua-nginx-module#readme) for an official port of this module for the NGINX "stream" subsystem (doing generic downstream TCP communications). * [lua-resty-memcached](https://github.com/openresty/lua-resty-memcached) library based on ngx_lua cosocket. * [lua-resty-redis](https://github.com/openresty/lua-resty-redis) library based on ngx_lua cosocket. * [lua-resty-mysql](https://github.com/openresty/lua-resty-mysql) library based on ngx_lua cosocket. @@ -982,7 +994,7 @@ See Also * [drizzle-nginx-module](http://github.com/openresty/drizzle-nginx-module) * [postgres-nginx-module](https://github.com/FRiCKLE/ngx_postgres) * [memc-nginx-module](http://github.com/openresty/memc-nginx-module) -* [The ngx_openresty bundle](http://openresty.org) +* [The OpenResty bundle](http://openresty.org) * [Nginx Systemtap Toolkit](https://github.com/openresty/nginx-systemtap-toolkit) [Back to TOC](#table-of-contents) @@ -2116,7 +2128,7 @@ log_by_lua **WARNING** Since the `v0.9.17` release, use of this directive is *discouraged*; use the new [log_by_lua_block](#log_by_lua_block) directive instead. -Runs the Lua source code inlined as the `` at the `log` request processing phase. This does not replace the current access logs, but runs after. +Runs the Lua source code inlined as the `` at the `log` request processing phase. This does not replace the current access logs, but runs before. Note that the following API functions are currently disabled within this context: @@ -2915,6 +2927,7 @@ Nginx API for Lua * [udpsock:receive](#udpsockreceive) * [udpsock:close](#udpsockclose) * [udpsock:settimeout](#udpsocksettimeout) +* [ngx.socket.stream](#ngxsocketstream) * [ngx.socket.tcp](#ngxsockettcp) * [tcpsock:connect](#tcpsockconnect) * [tcpsock:sslhandshake](#tcpsocksslhandshake) @@ -2935,6 +2948,7 @@ Nginx API for Lua * [ngx.timer.at](#ngxtimerat) * [ngx.timer.running_count](#ngxtimerrunning_count) * [ngx.timer.pending_count](#ngxtimerpending_count) +* [ngx.config.subsystem](#ngxconfigsubsystem) * [ngx.config.debug](#ngxconfigdebug) * [ngx.config.prefix](#ngxconfigprefix) * [ngx.config.nginx_version](#ngxconfignginx_version) @@ -3094,7 +3108,7 @@ This API requires a relatively expensive metamethod call and it is recommended t Core constants -------------- -**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, *log_by_lua*, ngx.timer.** +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, *log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** ```lua @@ -3120,7 +3134,7 @@ The `ngx.DECLINED` constant was first introduced in the `v0.5.0rc19` release. HTTP method constants --------------------- -**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.** +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** ngx.HTTP_GET @@ -3146,7 +3160,7 @@ These constants are usually used in [ngx.location.capture](#ngxlocationcapture) HTTP status constants --------------------- -**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.** +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** ```nginx @@ -3190,7 +3204,7 @@ HTTP status constants Nginx log level constants ------------------------- -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** ```lua @@ -3932,7 +3946,7 @@ ngx.req.http_version Returns the HTTP version number for the current request as a Lua number. -Current possible values are 1.0, 1.1, and 0.9. Returns `nil` for unrecognized values. +Current possible values are 2.0, 1.0, 1.1, and 0.9. Returns `nil` for unrecognized values. This method was first introduced in the `v0.7.17` release. @@ -4522,7 +4536,7 @@ ngx.req.discard_body **context:** *rewrite_by_lua*, access_by_lua*, content_by_lua** -Explicitly discard the request body, i.e., read the data on the connection and throw it away immediately. Please note that ignoring request body is not the right way to discard it, and that this function must be called to avoid breaking things under HTTP 1.1 keepalive or HTTP 1.1 pipelining. +Explicitly discard the request body, i.e., read the data on the connection and throw it away immediately (without using the request body by any means). This function is an asynchronous call and returns immediately. @@ -4538,7 +4552,7 @@ ngx.req.get_body_data --------------------- **syntax:** *data = ngx.req.get_body_data()* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, log_by_lua** Retrieves in-memory request body data. It returns a Lua string rather than a Lua table holding all the parsed query arguments. Use the [ngx.req.get_post_args](#ngxreqget_post_args) function instead if a Lua table is required. @@ -5085,7 +5099,7 @@ ngx.escape_uri -------------- **syntax:** *newstr = ngx.escape_uri(str)* -**context:** *init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Escape `str` as a URI component. @@ -5095,7 +5109,7 @@ ngx.unescape_uri ---------------- **syntax:** *newstr = ngx.unescape_uri(str)* -**context:** *init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Unescape `str` as an escaped URI component. @@ -5118,7 +5132,7 @@ ngx.encode_args --------------- **syntax:** *str = ngx.encode_args(table)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Encode the Lua table to a query args string according to the URI encoded rules. @@ -5175,7 +5189,7 @@ ngx.decode_args --------------- **syntax:** *table = ngx.decode_args(str, max_args?)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Decodes a URI encoded query-string into a Lua table. This is the inverse function of [ngx.encode_args](#ngxencode_args). @@ -5198,11 +5212,11 @@ ngx.encode_base64 ----------------- **syntax:** *newstr = ngx.encode_base64(str, no_padding?)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Encodes `str` to a base64 digest. -Since the `0.9.16` release, an optional boolean-typed `no_padding` argument can be specified to control whether the base64 padding should be appended to the resulting digest (default to `false`, i.e., with padding enabled). This enables streaming base64 digest calculation by (data chunks) though it would be the caller's responsibility to append an appropriate padding at the end of data stream. +Since the `0.9.16` release, an optional boolean-typed `no_padding` argument can be specified to control whether the base64 padding should be appended to the resulting digest (default to `false`, i.e., with padding enabled). [Back to TOC](#nginx-api-for-lua) @@ -5210,7 +5224,7 @@ ngx.decode_base64 ----------------- **syntax:** *newstr = ngx.decode_base64(str)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Decodes the `str` argument as a base64 digest to the raw form. Returns `nil` if `str` is not well formed. @@ -5220,7 +5234,7 @@ ngx.crc32_short --------------- **syntax:** *intval = ngx.crc32_short(str)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Calculates the CRC-32 (Cyclic Redundancy Code) digest for the `str` argument. @@ -5236,7 +5250,7 @@ ngx.crc32_long -------------- **syntax:** *intval = ngx.crc32_long(str)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Calculates the CRC-32 (Cyclic Redundancy Code) digest for the `str` argument. @@ -5252,7 +5266,7 @@ ngx.hmac_sha1 ------------- **syntax:** *digest = ngx.hmac_sha1(secret_key, str)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Computes the [HMAC-SHA1](http://en.wikipedia.org/wiki/HMAC) digest of the argument `str` and turns the result using the secret key ``. @@ -5284,7 +5298,7 @@ ngx.md5 ------- **syntax:** *digest = ngx.md5(str)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Returns the hexadecimal representation of the MD5 digest of the `str` argument. @@ -5311,7 +5325,7 @@ ngx.md5_bin ----------- **syntax:** *digest = ngx.md5_bin(str)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Returns the binary form of the MD5 digest of the `str` argument. @@ -5323,7 +5337,7 @@ ngx.sha1_bin ------------ **syntax:** *digest = ngx.sha1_bin(str)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Returns the binary form of the SHA-1 digest of the `str` argument. @@ -5337,7 +5351,7 @@ ngx.quote_sql_str ----------------- **syntax:** *quoted_value = ngx.quote_sql_str(raw_value)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Returns a quoted SQL string literal according to the MySQL quoting rules. @@ -5347,7 +5361,7 @@ ngx.today --------- **syntax:** *str = ngx.today()* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Returns current date (in the format `yyyy-mm-dd`) from the nginx cached time (no syscall involved unlike Lua's date library). @@ -5359,7 +5373,7 @@ ngx.time -------- **syntax:** *secs = ngx.time()* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Returns the elapsed seconds from the epoch for the current time stamp from the nginx cached time (no syscall involved unlike Lua's date library). @@ -5371,7 +5385,7 @@ ngx.now ------- **syntax:** *secs = ngx.now()* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Returns a floating-point number for the elapsed time in seconds (including milliseconds as the decimal part) from the epoch for the current time stamp from the nginx cached time (no syscall involved unlike Lua's date library). @@ -5385,7 +5399,7 @@ ngx.update_time --------------- **syntax:** *ngx.update_time()* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Forcibly updates the Nginx current time cache. This call involves a syscall and thus has some overhead, so do not abuse it. @@ -5397,7 +5411,7 @@ ngx.localtime ------------- **syntax:** *str = ngx.localtime()* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Returns the current time stamp (in the format `yyyy-mm-dd hh:mm:ss`) of the nginx cached time (no syscall involved unlike Lua's [os.date](http://www.lua.org/manual/5.1/manual.html#pdf-os.date) function). @@ -5409,7 +5423,7 @@ ngx.utctime ----------- **syntax:** *str = ngx.utctime()* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Returns the current time stamp (in the format `yyyy-mm-dd hh:mm:ss`) of the nginx cached time (no syscall involved unlike Lua's [os.date](http://www.lua.org/manual/5.1/manual.html#pdf-os.date) function). @@ -5421,7 +5435,7 @@ ngx.cookie_time --------------- **syntax:** *str = ngx.cookie_time(sec)* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Returns a formatted string can be used as the cookie expiration time. The parameter `sec` is the time stamp in seconds (like those returned from [ngx.time](#ngxtime)). @@ -5437,7 +5451,7 @@ ngx.http_time ------------- **syntax:** *str = ngx.http_time(sec)* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Returns a formated string can be used as the http header time (for example, being used in `Last-Modified` header). The parameter `sec` is the time stamp in seconds (like those returned from [ngx.time](#ngxtime)). @@ -5453,7 +5467,7 @@ ngx.parse_http_time ------------------- **syntax:** *sec = ngx.parse_http_time(str)* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Parse the http time string (as returned by [ngx.http_time](#ngxhttp_time)) into seconds. Returns the seconds or `nil` if the input string is in bad forms. @@ -5481,7 +5495,7 @@ ngx.re.match ------------ **syntax:** *captures, err = ngx.re.match(subject, regex, options?, ctx?, res_table?)* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Matches the `subject` string using the Perl compatible regular expression `regex` with the optional `options`. @@ -5524,16 +5538,16 @@ and are returned in the same Lua table as key-value pairs as the numbered captur -- m["remaining"] == "234" ``` -Unmatched subpatterns will have `nil` values in their `captures` table fields. +Unmatched subpatterns will have `false` values in their `captures` table fields. ```lua local m, err = ngx.re.match("hello, world", "(world)|(hello)|(?howdy)") -- m[0] == "hello" - -- m[1] == nil + -- m[1] == false -- m[2] == "hello" - -- m[3] == nil - -- m["named"] == nil + -- m[3] == false + -- m["named"] == false ``` Specify `options` to control how the match operation will be performed. The following option characters are supported: @@ -5623,7 +5637,7 @@ Note that, the `options` argument is not optional when the `ctx` argument is spe This method requires the PCRE library enabled in Nginx. ([Known Issue With Special Escaping Sequences](#special-escaping-sequences)). -To confirm that PCRE JIT is enabled, activate the Nginx debug log by adding the `--with-debug` option to Nginx or ngx_openresty's `./configure` script. Then, enable the "debug" error log level in `error_log` directive. The following message will be generated if PCRE JIT is enabled: +To confirm that PCRE JIT is enabled, activate the Nginx debug log by adding the `--with-debug` option to Nginx or OpenResty's `./configure` script. Then, enable the "debug" error log level in `error_log` directive. The following message will be generated if PCRE JIT is enabled: pcre JIT compiling result: 1 @@ -5639,7 +5653,7 @@ ngx.re.find ----------- **syntax:** *from, to, err = ngx.re.find(subject, regex, options?, ctx?, nth?)* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Similar to [ngx.re.match](#ngxrematch) but only returns the begining index (`from`) and end index (`to`) of the matched substring. The returned indexes are 1-based and can be fed directly into the [string.sub](http://www.lua.org/manual/5.1/manual.html#pdf-string.sub) API function to obtain the matched substring. @@ -5693,7 +5707,7 @@ ngx.re.gmatch ------------- **syntax:** *iterator, err = ngx.re.gmatch(subject, regex, options?)* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Similar to [ngx.re.match](#ngxrematch), but returns a Lua iterator instead, so as to let the user programmer iterate all the matches over the `` string argument with the PCRE `regex`. @@ -5771,7 +5785,7 @@ ngx.re.sub ---------- **syntax:** *newstr, n, err = ngx.re.sub(subject, regex, replace, options?)* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Substitutes the first match of the Perl compatible regular expression `regex` on the `subject` argument string with the string or function argument `replace`. The optional `options` argument has exactly the same meaning as in [ngx.re.match](#ngxrematch). @@ -5837,7 +5851,7 @@ ngx.re.gsub ----------- **syntax:** *newstr, n, err = ngx.re.gsub(subject, regex, replace, options?)* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Just like [ngx.re.sub](#ngxresub), but does global substitution. @@ -5877,7 +5891,7 @@ ngx.shared.DICT **syntax:** *dict = ngx.shared\[name_var\]* -**context:** *init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Fetching the shm-based Lua dictionary object for the shared memory zone named `DICT` defined by the [lua_shared_dict](#lua_shared_dict) directive. @@ -5950,7 +5964,7 @@ ngx.shared.DICT.get ------------------- **syntax:** *value, flags = ngx.shared.DICT:get(key)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Retrieving the value in the dictionary [ngx.shared.DICT](#ngxshareddict) for the key `key`. If the key does not exist or has been expired, then `nil` will be returned. @@ -5988,7 +6002,7 @@ ngx.shared.DICT.get_stale ------------------------- **syntax:** *value, flags, stale = ngx.shared.DICT:get_stale(key)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Similar to the [get](#ngxshareddictget) method but returns the value even if the key has already expired. @@ -6006,7 +6020,7 @@ ngx.shared.DICT.set ------------------- **syntax:** *success, err, forcible = ngx.shared.DICT:set(key, value, exptime?, flags?)* -**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Unconditionally sets a key-value pair into the shm-based dictionary [ngx.shared.DICT](#ngxshareddict). Returns three values: @@ -6054,7 +6068,7 @@ ngx.shared.DICT.safe_set ------------------------ **syntax:** *ok, err = ngx.shared.DICT:safe_set(key, value, exptime?, flags?)* -**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Similar to the [set](#ngxshareddictset) method, but never overrides the (least recently used) unexpired items in the store when running out of storage in the shared memory zone. In this case, it will immediately return `nil` and the string "no memory". @@ -6068,7 +6082,7 @@ ngx.shared.DICT.add ------------------- **syntax:** *success, err, forcible = ngx.shared.DICT:add(key, value, exptime?, flags?)* -**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Just like the [set](#ngxshareddictset) method, but only stores the key-value pair into the dictionary [ngx.shared.DICT](#ngxshareddict) if the key does *not* exist. @@ -6084,7 +6098,7 @@ ngx.shared.DICT.safe_add ------------------------ **syntax:** *ok, err = ngx.shared.DICT:safe_add(key, value, exptime?, flags?)* -**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Similar to the [add](#ngxshareddictadd) method, but never overrides the (least recently used) unexpired items in the store when running out of storage in the shared memory zone. In this case, it will immediately return `nil` and the string "no memory". @@ -6098,7 +6112,7 @@ ngx.shared.DICT.replace ----------------------- **syntax:** *success, err, forcible = ngx.shared.DICT:replace(key, value, exptime?, flags?)* -**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Just like the [set](#ngxshareddictset) method, but only stores the key-value pair into the dictionary [ngx.shared.DICT](#ngxshareddict) if the key *does* exist. @@ -6114,7 +6128,7 @@ ngx.shared.DICT.delete ---------------------- **syntax:** *ngx.shared.DICT:delete(key)* -**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Unconditionally removes the key-value pair from the shm-based dictionary [ngx.shared.DICT](#ngxshareddict). @@ -6130,7 +6144,7 @@ ngx.shared.DICT.incr -------------------- **syntax:** *newval, err = ngx.shared.DICT:incr(key, value)* -**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Increments the (numerical) value for `key` in the shm-based dictionary [ngx.shared.DICT](#ngxshareddict) by the step value `value`. Returns the new resulting number if the operation is successfully completed or `nil` and an error message otherwise. @@ -6150,7 +6164,7 @@ ngx.shared.DICT.flush_all ------------------------- **syntax:** *ngx.shared.DICT:flush_all()* -**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Flushes out all the items in the dictionary. This method does not actuall free up all the memory blocks in the dictionary but just marks all the existing items as expired. @@ -6164,7 +6178,7 @@ ngx.shared.DICT.flush_expired ----------------------------- **syntax:** *flushed = ngx.shared.DICT:flush_expired(max_count?)* -**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Flushes out the expired items in the dictionary, up to the maximal number specified by the optional `max_count` argument. When the `max_count` argument is given `0` or not given at all, then it means unlimited. Returns the number of items that have actually been flushed. @@ -6180,7 +6194,7 @@ ngx.shared.DICT.get_keys ------------------------ **syntax:** *keys = ngx.shared.DICT:get_keys(max_count?)* -**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Fetch a list of the keys from the dictionary, up to ``. @@ -6314,7 +6328,7 @@ Timeout for the reading operation is controlled by the [lua_socket_read_timeout] sock:settimeout(1000) -- one second timeout local data, err = sock:receive() if not data then - ngx.say("failed to read a packet: ", data) + ngx.say("failed to read a packet: ", err) return end ngx.say("successfully read a packet: ", data) @@ -6354,6 +6368,16 @@ This feature was first introduced in the `v0.5.7` release. [Back to TOC](#nginx-api-for-lua) +ngx.socket.stream +----------------- + +Just an alias to [ngx.socket.tcp](#ngxsockettcp). If the stream-typed cosocket may also connect to a unix domain +socket, then this API name is preferred. + +This API function was first added to the `v0.10.1` release. + +[Back to TOC](#nginx-api-for-lua) + ngx.socket.tcp -------------- **syntax:** *tcpsock = ngx.socket.tcp()* @@ -7141,7 +7165,7 @@ ngx.timer.at ------------ **syntax:** *ok, err = ngx.timer.at(delay, callback, user_arg1, user_arg2, ...)* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Creates an Nginx timer with a user callback function as well as optional user arguments. @@ -7267,7 +7291,7 @@ ngx.timer.running_count ----------------------- **syntax:** *count = ngx.timer.running_count()* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Returns the number of timers currently running. @@ -7279,7 +7303,7 @@ ngx.timer.pending_count ----------------------- **syntax:** *count = ngx.timer.pending_count()* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** Returns the number of pending timers. @@ -7287,6 +7311,19 @@ This directive was first introduced in the `v0.9.20` release. [Back to TOC](#nginx-api-for-lua) +ngx.config.subsystem +-------------------- +**syntax:** *subsystem = ngx.config.subsystem* + +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, init_by_lua*, init_worker_by_lua** + +This string field indicates the current NGINX subsystem the current Lua environment is based on. For this module, this field always takes the string value `"http"`. For +[ngx_stream_lua_module](https://github.com/openresty/stream-lua-nginx-module#readme), however, this field takes the value `"stream"`. + +This field was first introduced in the `0.10.1`. + +[Back to TOC](#nginx-api-for-lua) + ngx.config.debug ---------------- **syntax:** *debug = ngx.config.debug* @@ -7497,7 +7534,7 @@ ndk.set_var.DIRECTIVE --------------------- **syntax:** *res = ndk.set_var.DIRECTIVE_NAME* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** This mechanism allows calling other nginx C modules' directives that are implemented by [Nginx Devel Kit](https://github.com/simpl/ngx_devel_kit) (NDK)'s set_var submodule's `ndk_set_var_value`. diff --git a/debian/modules/nginx-lua/config b/debian/modules/nginx-lua/config index 030788c..3c2548b 100644 --- a/debian/modules/nginx-lua/config +++ b/debian/modules/nginx-lua/config @@ -284,14 +284,17 @@ END fi fi +ngx_module_incs= +ngx_module_libs= + if [ $ngx_found = yes ]; then # this is a hack to persuade nginx's build system to favor # the paths set by our user environments: CFLAGS="$ngx_lua_opt_I $CFLAGS" NGX_LD_OPT="$ngx_lua_opt_L $NGX_LD_OPT" - CORE_INCS="$CORE_INCS $ngx_feature_path" - CORE_LIBS="$CORE_LIBS $ngx_feature_libs" + ngx_module_incs="$ngx_module_incs $ngx_feature_path" + ngx_module_libs="$ngx_module_libs $ngx_feature_libs" else cat << END $0: error: ngx_http_lua_module requires the Lua library. @@ -300,119 +303,118 @@ END fi ngx_addon_name=ngx_http_lua_module -HTTP_AUX_FILTER_MODULES="$HTTP_AUX_FILTER_MODULES ngx_http_lua_module" -NGX_ADDON_SRCS="$NGX_ADDON_SRCS \ - $ngx_addon_dir/src/ngx_http_lua_script.c \ - $ngx_addon_dir/src/ngx_http_lua_log.c \ - $ngx_addon_dir/src/ngx_http_lua_subrequest.c \ - $ngx_addon_dir/src/ngx_http_lua_ndk.c \ - $ngx_addon_dir/src/ngx_http_lua_control.c \ - $ngx_addon_dir/src/ngx_http_lua_time.c \ - $ngx_addon_dir/src/ngx_http_lua_misc.c \ - $ngx_addon_dir/src/ngx_http_lua_variable.c \ - $ngx_addon_dir/src/ngx_http_lua_string.c \ - $ngx_addon_dir/src/ngx_http_lua_output.c \ - $ngx_addon_dir/src/ngx_http_lua_headers.c \ - $ngx_addon_dir/src/ngx_http_lua_req_body.c \ - $ngx_addon_dir/src/ngx_http_lua_uri.c \ - $ngx_addon_dir/src/ngx_http_lua_args.c \ - $ngx_addon_dir/src/ngx_http_lua_ctx.c \ - $ngx_addon_dir/src/ngx_http_lua_regex.c \ - $ngx_addon_dir/src/ngx_http_lua_module.c \ - $ngx_addon_dir/src/ngx_http_lua_headers_out.c \ - $ngx_addon_dir/src/ngx_http_lua_headers_in.c \ - $ngx_addon_dir/src/ngx_http_lua_directive.c \ - $ngx_addon_dir/src/ngx_http_lua_consts.c \ - $ngx_addon_dir/src/ngx_http_lua_exception.c \ - $ngx_addon_dir/src/ngx_http_lua_util.c \ - $ngx_addon_dir/src/ngx_http_lua_cache.c \ - $ngx_addon_dir/src/ngx_http_lua_contentby.c \ - $ngx_addon_dir/src/ngx_http_lua_rewriteby.c \ - $ngx_addon_dir/src/ngx_http_lua_accessby.c \ - $ngx_addon_dir/src/ngx_http_lua_setby.c \ - $ngx_addon_dir/src/ngx_http_lua_capturefilter.c \ - $ngx_addon_dir/src/ngx_http_lua_clfactory.c \ - $ngx_addon_dir/src/ngx_http_lua_pcrefix.c \ - $ngx_addon_dir/src/ngx_http_lua_headerfilterby.c \ - $ngx_addon_dir/src/ngx_http_lua_shdict.c \ - $ngx_addon_dir/src/ngx_http_lua_socket_tcp.c \ - $ngx_addon_dir/src/ngx_http_lua_api.c \ - $ngx_addon_dir/src/ngx_http_lua_logby.c \ - $ngx_addon_dir/src/ngx_http_lua_sleep.c \ - $ngx_addon_dir/src/ngx_http_lua_semaphore.c\ - $ngx_addon_dir/src/ngx_http_lua_coroutine.c \ - $ngx_addon_dir/src/ngx_http_lua_bodyfilterby.c \ - $ngx_addon_dir/src/ngx_http_lua_initby.c \ - $ngx_addon_dir/src/ngx_http_lua_initworkerby.c \ - $ngx_addon_dir/src/ngx_http_lua_socket_udp.c \ - $ngx_addon_dir/src/ngx_http_lua_req_method.c \ - $ngx_addon_dir/src/ngx_http_lua_phase.c \ - $ngx_addon_dir/src/ngx_http_lua_uthread.c \ - $ngx_addon_dir/src/ngx_http_lua_timer.c \ - $ngx_addon_dir/src/ngx_http_lua_config.c \ - $ngx_addon_dir/src/ngx_http_lua_worker.c \ - $ngx_addon_dir/src/ngx_http_lua_ssl_certby.c \ - $ngx_addon_dir/src/ngx_http_lua_ssl_ocsp.c \ - $ngx_addon_dir/src/ngx_http_lua_lex.c \ - $ngx_addon_dir/src/ngx_http_lua_balancer.c \ - " +HTTP_LUA_SRCS=" \ + $ngx_addon_dir/src/ngx_http_lua_script.c \ + $ngx_addon_dir/src/ngx_http_lua_log.c \ + $ngx_addon_dir/src/ngx_http_lua_subrequest.c \ + $ngx_addon_dir/src/ngx_http_lua_ndk.c \ + $ngx_addon_dir/src/ngx_http_lua_control.c \ + $ngx_addon_dir/src/ngx_http_lua_time.c \ + $ngx_addon_dir/src/ngx_http_lua_misc.c \ + $ngx_addon_dir/src/ngx_http_lua_variable.c \ + $ngx_addon_dir/src/ngx_http_lua_string.c \ + $ngx_addon_dir/src/ngx_http_lua_output.c \ + $ngx_addon_dir/src/ngx_http_lua_headers.c \ + $ngx_addon_dir/src/ngx_http_lua_req_body.c \ + $ngx_addon_dir/src/ngx_http_lua_uri.c \ + $ngx_addon_dir/src/ngx_http_lua_args.c \ + $ngx_addon_dir/src/ngx_http_lua_ctx.c \ + $ngx_addon_dir/src/ngx_http_lua_regex.c \ + $ngx_addon_dir/src/ngx_http_lua_module.c \ + $ngx_addon_dir/src/ngx_http_lua_headers_out.c \ + $ngx_addon_dir/src/ngx_http_lua_headers_in.c \ + $ngx_addon_dir/src/ngx_http_lua_directive.c \ + $ngx_addon_dir/src/ngx_http_lua_consts.c \ + $ngx_addon_dir/src/ngx_http_lua_exception.c \ + $ngx_addon_dir/src/ngx_http_lua_util.c \ + $ngx_addon_dir/src/ngx_http_lua_cache.c \ + $ngx_addon_dir/src/ngx_http_lua_contentby.c \ + $ngx_addon_dir/src/ngx_http_lua_rewriteby.c \ + $ngx_addon_dir/src/ngx_http_lua_accessby.c \ + $ngx_addon_dir/src/ngx_http_lua_setby.c \ + $ngx_addon_dir/src/ngx_http_lua_capturefilter.c \ + $ngx_addon_dir/src/ngx_http_lua_clfactory.c \ + $ngx_addon_dir/src/ngx_http_lua_pcrefix.c \ + $ngx_addon_dir/src/ngx_http_lua_headerfilterby.c \ + $ngx_addon_dir/src/ngx_http_lua_shdict.c \ + $ngx_addon_dir/src/ngx_http_lua_socket_tcp.c \ + $ngx_addon_dir/src/ngx_http_lua_api.c \ + $ngx_addon_dir/src/ngx_http_lua_logby.c \ + $ngx_addon_dir/src/ngx_http_lua_sleep.c \ + $ngx_addon_dir/src/ngx_http_lua_semaphore.c\ + $ngx_addon_dir/src/ngx_http_lua_coroutine.c \ + $ngx_addon_dir/src/ngx_http_lua_bodyfilterby.c \ + $ngx_addon_dir/src/ngx_http_lua_initby.c \ + $ngx_addon_dir/src/ngx_http_lua_initworkerby.c \ + $ngx_addon_dir/src/ngx_http_lua_socket_udp.c \ + $ngx_addon_dir/src/ngx_http_lua_req_method.c \ + $ngx_addon_dir/src/ngx_http_lua_phase.c \ + $ngx_addon_dir/src/ngx_http_lua_uthread.c \ + $ngx_addon_dir/src/ngx_http_lua_timer.c \ + $ngx_addon_dir/src/ngx_http_lua_config.c \ + $ngx_addon_dir/src/ngx_http_lua_worker.c \ + $ngx_addon_dir/src/ngx_http_lua_ssl_certby.c \ + $ngx_addon_dir/src/ngx_http_lua_ssl_ocsp.c \ + $ngx_addon_dir/src/ngx_http_lua_lex.c \ + $ngx_addon_dir/src/ngx_http_lua_balancer.c \ + " -NGX_ADDON_DEPS="$NGX_ADDON_DEPS \ - $ngx_addon_dir/src/ddebug.h \ - $ngx_addon_dir/src/ngx_http_lua_script.h \ - $ngx_addon_dir/src/ngx_http_lua_log.h \ - $ngx_addon_dir/src/ngx_http_lua_subrequest.h \ - $ngx_addon_dir/src/ngx_http_lua_ndk.h \ - $ngx_addon_dir/src/ngx_http_lua_control.h \ - $ngx_addon_dir/src/ngx_http_lua_time.h \ - $ngx_addon_dir/src/ngx_http_lua_string.h \ - $ngx_addon_dir/src/ngx_http_lua_misc.h \ - $ngx_addon_dir/src/ngx_http_lua_variable.h \ - $ngx_addon_dir/src/ngx_http_lua_output.h \ - $ngx_addon_dir/src/ngx_http_lua_headers.h \ - $ngx_addon_dir/src/ngx_http_lua_uri.h \ - $ngx_addon_dir/src/ngx_http_lua_req_body.h \ - $ngx_addon_dir/src/ngx_http_lua_args.h \ - $ngx_addon_dir/src/ngx_http_lua_ctx.h \ - $ngx_addon_dir/src/ngx_http_lua_regex.h \ - $ngx_addon_dir/src/ngx_http_lua_common.h \ - $ngx_addon_dir/src/ngx_http_lua_directive.h \ - $ngx_addon_dir/src/ngx_http_lua_headers_out.h \ - $ngx_addon_dir/src/ngx_http_lua_headers_in.h \ - $ngx_addon_dir/src/ngx_http_lua_consts.h \ - $ngx_addon_dir/src/ngx_http_lua_exception.h \ - $ngx_addon_dir/src/ngx_http_lua_util.h \ - $ngx_addon_dir/src/ngx_http_lua_cache.h \ - $ngx_addon_dir/src/ngx_http_lua_contentby.h \ - $ngx_addon_dir/src/ngx_http_lua_rewriteby.h \ - $ngx_addon_dir/src/ngx_http_lua_accessby.h \ - $ngx_addon_dir/src/ngx_http_lua_setby.h \ - $ngx_addon_dir/src/ngx_http_lua_capturefilter.h \ - $ngx_addon_dir/src/ngx_http_lua_clfactory.h \ - $ngx_addon_dir/src/ngx_http_lua_pcrefix.h \ - $ngx_addon_dir/src/ngx_http_lua_headerfilterby.h \ - $ngx_addon_dir/src/ngx_http_lua_shdict.h \ - $ngx_addon_dir/src/ngx_http_lua_socket_tcp.h \ - $ngx_addon_dir/src/api/ngx_http_lua_api.h \ - $ngx_addon_dir/src/ngx_http_lua_logby.h \ - $ngx_addon_dir/src/ngx_http_lua_sleep.h \ - $ngx_addon_dir/src/ngx_http_lua_semaphore.h\ - $ngx_addon_dir/src/ngx_http_lua_coroutine.h \ - $ngx_addon_dir/src/ngx_http_lua_bodyfilterby.h \ - $ngx_addon_dir/src/ngx_http_lua_initby.h \ - $ngx_addon_dir/src/ngx_http_lua_initworkerby.h \ - $ngx_addon_dir/src/ngx_http_lua_socket_udp.h \ - $ngx_addon_dir/src/ngx_http_lua_req_method.h \ - $ngx_addon_dir/src/ngx_http_lua_phase.h \ - $ngx_addon_dir/src/ngx_http_lua_probe.h \ - $ngx_addon_dir/src/ngx_http_lua_uthread.h \ - $ngx_addon_dir/src/ngx_http_lua_timer.h \ - $ngx_addon_dir/src/ngx_http_lua_config.h \ - $ngx_addon_dir/src/ngx_http_lua_worker.h \ - $ngx_addon_dir/src/ngx_http_lua_ssl_certby.h \ - $ngx_addon_dir/src/ngx_http_lua_lex.h \ - $ngx_addon_dir/src/ngx_http_lua_balancer.h \ - " +HTTP_LUA_DEPS=" \ + $ngx_addon_dir/src/ddebug.h \ + $ngx_addon_dir/src/ngx_http_lua_script.h \ + $ngx_addon_dir/src/ngx_http_lua_log.h \ + $ngx_addon_dir/src/ngx_http_lua_subrequest.h \ + $ngx_addon_dir/src/ngx_http_lua_ndk.h \ + $ngx_addon_dir/src/ngx_http_lua_control.h \ + $ngx_addon_dir/src/ngx_http_lua_time.h \ + $ngx_addon_dir/src/ngx_http_lua_string.h \ + $ngx_addon_dir/src/ngx_http_lua_misc.h \ + $ngx_addon_dir/src/ngx_http_lua_variable.h \ + $ngx_addon_dir/src/ngx_http_lua_output.h \ + $ngx_addon_dir/src/ngx_http_lua_headers.h \ + $ngx_addon_dir/src/ngx_http_lua_uri.h \ + $ngx_addon_dir/src/ngx_http_lua_req_body.h \ + $ngx_addon_dir/src/ngx_http_lua_args.h \ + $ngx_addon_dir/src/ngx_http_lua_ctx.h \ + $ngx_addon_dir/src/ngx_http_lua_regex.h \ + $ngx_addon_dir/src/ngx_http_lua_common.h \ + $ngx_addon_dir/src/ngx_http_lua_directive.h \ + $ngx_addon_dir/src/ngx_http_lua_headers_out.h \ + $ngx_addon_dir/src/ngx_http_lua_headers_in.h \ + $ngx_addon_dir/src/ngx_http_lua_consts.h \ + $ngx_addon_dir/src/ngx_http_lua_exception.h \ + $ngx_addon_dir/src/ngx_http_lua_util.h \ + $ngx_addon_dir/src/ngx_http_lua_cache.h \ + $ngx_addon_dir/src/ngx_http_lua_contentby.h \ + $ngx_addon_dir/src/ngx_http_lua_rewriteby.h \ + $ngx_addon_dir/src/ngx_http_lua_accessby.h \ + $ngx_addon_dir/src/ngx_http_lua_setby.h \ + $ngx_addon_dir/src/ngx_http_lua_capturefilter.h \ + $ngx_addon_dir/src/ngx_http_lua_clfactory.h \ + $ngx_addon_dir/src/ngx_http_lua_pcrefix.h \ + $ngx_addon_dir/src/ngx_http_lua_headerfilterby.h \ + $ngx_addon_dir/src/ngx_http_lua_shdict.h \ + $ngx_addon_dir/src/ngx_http_lua_socket_tcp.h \ + $ngx_addon_dir/src/api/ngx_http_lua_api.h \ + $ngx_addon_dir/src/ngx_http_lua_logby.h \ + $ngx_addon_dir/src/ngx_http_lua_sleep.h \ + $ngx_addon_dir/src/ngx_http_lua_semaphore.h\ + $ngx_addon_dir/src/ngx_http_lua_coroutine.h \ + $ngx_addon_dir/src/ngx_http_lua_bodyfilterby.h \ + $ngx_addon_dir/src/ngx_http_lua_initby.h \ + $ngx_addon_dir/src/ngx_http_lua_initworkerby.h \ + $ngx_addon_dir/src/ngx_http_lua_socket_udp.h \ + $ngx_addon_dir/src/ngx_http_lua_req_method.h \ + $ngx_addon_dir/src/ngx_http_lua_phase.h \ + $ngx_addon_dir/src/ngx_http_lua_probe.h \ + $ngx_addon_dir/src/ngx_http_lua_uthread.h \ + $ngx_addon_dir/src/ngx_http_lua_timer.h \ + $ngx_addon_dir/src/ngx_http_lua_config.h \ + $ngx_addon_dir/src/ngx_http_lua_worker.h \ + $ngx_addon_dir/src/ngx_http_lua_ssl_certby.h \ + $ngx_addon_dir/src/ngx_http_lua_lex.h \ + $ngx_addon_dir/src/ngx_http_lua_balancer.h \ + " CFLAGS="$CFLAGS -DNDK_SET_VAR" @@ -464,6 +466,21 @@ ngx_feature_test='setsockopt(1, SOL_SOCKET, SO_PASSCRED, NULL, 0);' . auto/feature +if test -n "$ngx_module_link"; then + ngx_module_type=HTTP_AUX_FILTER + ngx_module_name=$ngx_addon_name + ngx_module_deps="$HTTP_LUA_DEPS" + ngx_module_srcs="$HTTP_LUA_SRCS" + + . auto/module +else + HTTP_AUX_FILTER_MODULES="$HTTP_AUX_FILTER_MODULES $ngx_addon_name" + NGX_ADDON_SRCS="$NGX_ADDON_SRCS $HTTP_LUA_SRCS" + NGX_ADDON_DEPS="$NGX_ADDON_DEPS $HTTP_LUA_DEPS" + + CORE_INCS="$CORE_INCS $ngx_module_incs" + CORE_LIBS="$CORE_LIBS $ngx_module_libs" +fi + #CFLAGS=$"$CFLAGS -DLUA_DEFAULT_PATH='\"/usr/local/openresty/lualib/?.lua\"'" #CFLAGS=$"$CFLAGS -DLUA_DEFAULT_CPATH='\"/usr/local/openresty/lualib/?.so\"'" - diff --git a/debian/modules/nginx-lua/doc/HttpLuaModule.wiki b/debian/modules/nginx-lua/doc/HttpLuaModule.wiki index f3bf06e..3a39ef8 100644 --- a/debian/modules/nginx-lua/doc/HttpLuaModule.wiki +++ b/debian/modules/nginx-lua/doc/HttpLuaModule.wiki @@ -10,7 +10,7 @@ Production ready. = Version = -This document describes ngx_lua [https://github.com/openresty/lua-nginx-module/tags v0.10.0] released on 11 January 2015. +This document describes ngx_lua [https://github.com/openresty/lua-nginx-module/tags v0.10.0] released on 11 January 2016. = Synopsis = @@ -160,6 +160,10 @@ The Lua interpreter or LuaJIT instance is shared across all the requests in a si Loaded Lua modules persist in the nginx worker process level resulting in a small memory footprint in Lua even when under heavy loads. +This module is plugged into NGINX's "http" subsystem so it can only speaks downstream communication protocols in the HTTP family (HTTP 0.9/1.0/1.1/2.0, WebSockets, and etc). +If you want to do generic TCP communications with the downstream clients, then you should use the [https://github.com/openresty/stream-lua-nginx-module#readme ngx_stream_lua] module instead +which has a compatible Lua API. + = Typical Uses = Just to name a few: @@ -191,7 +195,7 @@ Nginx cores older than 1.6.0 (exclusive) are *not* supported. = Installation = -It is highly recommended to use the [http://openresty.org ngx_openresty bundle] that bundles Nginx, ngx_lua, LuaJIT 2.0/2.1 (or the optional standard Lua 5.1 interpreter), as well as a package of powerful companion Nginx modules. The basic installation step is a simple command: ./configure --with-luajit && make && make install. +It is highly recommended to use the [http://openresty.org OpenResty bundle] that bundles Nginx, ngx_lua, LuaJIT 2.0/2.1 (or the optional standard Lua 5.1 interpreter), as well as a package of powerful companion Nginx modules. The basic installation step is a simple command: ./configure --with-luajit && make && make install. Alternatively, ngx_lua can be manually compiled into Nginx: @@ -229,6 +233,14 @@ Build the source with this module: make install +Starting from NGINX 1.9.11, you can also compile this module as a dynamic module, by using the `--add-dynamic-module=PATH` option instead of `--add-module=PATH` on the +`./configure` command line above. And then you can explicitly load the module in your `nginx.conf` via the [load_module](http://nginx.org/en/docs/ngx_core_module.html#load_module) +directive, for example, + +```nginx +load_module /path/to/modules/ngx_http_lua_module.so; +``` + == C Macro Configurations == While building this module either via OpenResty or with the NGINX core, you can define the following C macros via the C compiler options: @@ -473,7 +485,7 @@ If server-wide data sharing is required, then use one or more of the following a # Use the [[#ngx.shared.DICT|ngx.shared.DICT]] API provided by this module. # Use only a single nginx worker and a single server (this is however not recommended when there is a multi core CPU or multiple CPUs in a single machine). -# Use data storage mechanisms such as memcached, redis, MySQL or PostgreSQL. [http://openresty.org The ngx_openresty bundle] associated with this module comes with a set of companion Nginx modules and Lua libraries that provide interfaces with these data storage mechanisms. +# Use data storage mechanisms such as memcached, redis, MySQL or PostgreSQL. [http://openresty.org The OpenResty bundle] associated with this module comes with a set of companion Nginx modules and Lua libraries that provide interfaces with these data storage mechanisms. = Known Issues = @@ -698,7 +710,6 @@ phases. * cosocket: pool-based backend concurrency level control: implement automatic connect queueing when the backend concurrency exceeds its connection pool limit. * cosocket: review and merge aviramc's [https://github.com/openresty/lua-nginx-module/pull/290 patch] for adding the bsdrecv method. * add new API function ngx.resp.add_header to emulate the standard add_header config directive. -* [[#ngx.re.match|ngx.re]] API: use false instead of nil in the resulting match table to indicate non-existent submatch captures, such that we can avoid "holes" in the array table. * review and apply Jader H. Silva's patch for ngx.re.split(). * review and apply vadim-pavlov's patch for [[#ngx.location.capture|ngx.location.capture]]'s extra_headers option * use ngx_hash_t to optimize the built-in header look-up process for [[#ngx.req.set_header|ngx.req.set_header]], [[#ngx.header.HEADER|ngx.header.HEADER]], and etc. @@ -710,7 +721,7 @@ phases. = Changes = -The changes of every release of this module can be obtained from the ngx_openresty bundle's change logs: +The changes of every release of this module can be obtained from the OpenResty bundle's change logs: http://openresty.org/#Changes @@ -773,9 +784,9 @@ There are also various testing modes based on mockeagain, valgrind, and etc. Ref This module is licensed under the BSD license. -Copyright (C) 2009-2015, by Xiaozhe Wang (chaoslawful) . +Copyright (C) 2009-2016, by Xiaozhe Wang (chaoslawful) . -Copyright (C) 2009-2015, by Yichun "agentzh" Zhang (章亦春) , CloudFlare Inc. +Copyright (C) 2009-2016, by Yichun "agentzh" Zhang (章亦春) , CloudFlare Inc. All rights reserved. @@ -789,6 +800,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND = See Also = +* [https://github.com/openresty/stream-lua-nginx-module#readme ngx_stream_lua_module] for an official port of this module for the NGINX "stream" subsystem (doing generic downstream TCP communications). * [https://github.com/openresty/lua-resty-memcached lua-resty-memcached] library based on ngx_lua cosocket. * [https://github.com/openresty/lua-resty-redis lua-resty-redis] library based on ngx_lua cosocket. * [https://github.com/openresty/lua-resty-mysql lua-resty-mysql] library based on ngx_lua cosocket. @@ -807,7 +819,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * [[HttpDrizzleModule]] * [https://github.com/FRiCKLE/ngx_postgres postgres-nginx-module] * [[HttpMemcModule]] -* [http://openresty.org The ngx_openresty bundle] +* [http://openresty.org The OpenResty bundle] * [https://github.com/openresty/nginx-systemtap-toolkit Nginx Systemtap Toolkit] = Directives = @@ -1758,7 +1770,7 @@ This directive was first introduced in the v0.5.0rc32 release. '''WARNING''' Since the v0.9.17 release, use of this directive is ''discouraged''; use the new [[#log_by_lua_block|log_by_lua_block]] directive instead. -Runs the Lua source code inlined as the at the log request processing phase. This does not replace the current access logs, but runs after. +Runs the Lua source code inlined as the at the log request processing phase. This does not replace the current access logs, but runs before. Note that the following API functions are currently disabled within this context: @@ -2488,7 +2500,7 @@ Undefined NGINX variables are evaluated to `nil` while uninitialized (but define This API requires a relatively expensive metamethod call and it is recommended to avoid using it on hot code paths. == Core constants == -'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, *log_by_lua*, ngx.timer.*'' +'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, *log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' ngx.OK (0) @@ -2509,7 +2521,7 @@ The ngx.null constant is a NULL light userdata usually The ngx.DECLINED constant was first introduced in the v0.5.0rc19 release. == HTTP method constants == -'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.*'' +'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' ngx.HTTP_GET @@ -2532,7 +2544,7 @@ The ngx.DECLINED constant was first introduced in the v0.5.0r These constants are usually used in [[#ngx.location.capture|ngx.location.capture]] and [[#ngx.location.capture_multi|ngx.location.capture_multi]] method calls. == HTTP status constants == -'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.*'' +'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' value = ngx.HTTP_CONTINUE (100) (first added in the v0.9.20 release) @@ -2572,7 +2584,7 @@ These constants are usually used in [[#ngx.location.capture|ngx.location.capture == Nginx log level constants == -'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.*'' +'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' ngx.STDERR @@ -3246,7 +3258,7 @@ See also [[#ngx.now|ngx.now]] and [[#ngx.update_time|ngx.update_time]]. Returns the HTTP version number for the current request as a Lua number. -Current possible values are 1.0, 1.1, and 0.9. Returns nil for unrecognized values. +Current possible values are 2.0, 1.0, 1.1, and 0.9. Returns nil for unrecognized values. This method was first introduced in the v0.7.17 release. @@ -3754,7 +3766,7 @@ This function was first introduced in the v0.3.1rc17 release. '''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*'' -Explicitly discard the request body, i.e., read the data on the connection and throw it away immediately. Please note that ignoring request body is not the right way to discard it, and that this function must be called to avoid breaking things under HTTP 1.1 keepalive or HTTP 1.1 pipelining. +Explicitly discard the request body, i.e., read the data on the connection and throw it away immediately (without using the request body by any means). This function is an asynchronous call and returns immediately. @@ -3767,7 +3779,7 @@ See also [[#ngx.req.read_body|ngx.req.read_body]]. == ngx.req.get_body_data == '''syntax:''' ''data = ngx.req.get_body_data()'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, log_by_lua*'' Retrieves in-memory request body data. It returns a Lua string rather than a Lua table holding all the parsed query arguments. Use the [[#ngx.req.get_post_args|ngx.req.get_post_args]] function instead if a Lua table is required. @@ -4236,14 +4248,14 @@ This method was introduced in the 0.5.0rc30 release. == ngx.escape_uri == '''syntax:''' ''newstr = ngx.escape_uri(str)'' -'''context:''' ''init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Escape str as a URI component. == ngx.unescape_uri == '''syntax:''' ''newstr = ngx.unescape_uri(str)'' -'''context:''' ''init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Unescape str as an escaped URI component. @@ -4262,7 +4274,7 @@ gives the output == ngx.encode_args == '''syntax:''' ''str = ngx.encode_args(table)'' -'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Encode the Lua table to a query args string according to the URI encoded rules. @@ -4313,7 +4325,7 @@ This method was first introduced in the v0.3.1rc27 release. == ngx.decode_args == '''syntax:''' ''table = ngx.decode_args(str, max_args?)'' -'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Decodes a URI encoded query-string into a Lua table. This is the inverse function of [[#ngx.encode_args|ngx.encode_args]]. @@ -4332,23 +4344,23 @@ This method was introduced in the v0.5.0rc29. == ngx.encode_base64 == '''syntax:''' ''newstr = ngx.encode_base64(str, no_padding?)'' -'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Encodes str to a base64 digest. -Since the 0.9.16 release, an optional boolean-typed no_padding argument can be specified to control whether the base64 padding should be appended to the resulting digest (default to false, i.e., with padding enabled). This enables streaming base64 digest calculation by (data chunks) though it would be the caller's responsibility to append an appropriate padding at the end of data stream. +Since the 0.9.16 release, an optional boolean-typed no_padding argument can be specified to control whether the base64 padding should be appended to the resulting digest (default to false, i.e., with padding enabled). == ngx.decode_base64 == '''syntax:''' ''newstr = ngx.decode_base64(str)'' -'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Decodes the str argument as a base64 digest to the raw form. Returns nil if str is not well formed. == ngx.crc32_short == '''syntax:''' ''intval = ngx.crc32_short(str)'' -'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Calculates the CRC-32 (Cyclic Redundancy Code) digest for the str argument. @@ -4361,7 +4373,7 @@ This API was first introduced in the v0.3.1rc8 release. == ngx.crc32_long == '''syntax:''' ''intval = ngx.crc32_long(str)'' -'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Calculates the CRC-32 (Cyclic Redundancy Code) digest for the str argument. @@ -4374,7 +4386,7 @@ This API was first introduced in the v0.3.1rc8 release. == ngx.hmac_sha1 == '''syntax:''' ''digest = ngx.hmac_sha1(secret_key, str)'' -'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Computes the [http://en.wikipedia.org/wiki/HMAC HMAC-SHA1] digest of the argument str and turns the result using the secret key . @@ -4402,7 +4414,7 @@ This function was first introduced in the v0.3.1rc29 release. == ngx.md5 == '''syntax:''' ''digest = ngx.md5(str)'' -'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Returns the hexadecimal representation of the MD5 digest of the str argument. @@ -4425,7 +4437,7 @@ See [[#ngx.md5_bin|ngx.md5_bin]] if the raw binary MD5 digest is required. == ngx.md5_bin == '''syntax:''' ''digest = ngx.md5_bin(str)'' -'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Returns the binary form of the MD5 digest of the str argument. @@ -4434,7 +4446,7 @@ See [[#ngx.md5|ngx.md5]] if the hexadecimal form of the MD5 digest is required. == ngx.sha1_bin == '''syntax:''' ''digest = ngx.sha1_bin(str)'' -'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Returns the binary form of the SHA-1 digest of the str argument. @@ -4445,14 +4457,14 @@ This function was first introduced in the v0.5.0rc6. == ngx.quote_sql_str == '''syntax:''' ''quoted_value = ngx.quote_sql_str(raw_value)'' -'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Returns a quoted SQL string literal according to the MySQL quoting rules. == ngx.today == '''syntax:''' ''str = ngx.today()'' -'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Returns current date (in the format yyyy-mm-dd) from the nginx cached time (no syscall involved unlike Lua's date library). @@ -4461,7 +4473,7 @@ This is the local time. == ngx.time == '''syntax:''' ''secs = ngx.time()'' -'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Returns the elapsed seconds from the epoch for the current time stamp from the nginx cached time (no syscall involved unlike Lua's date library). @@ -4470,7 +4482,7 @@ Updates of the Nginx time cache an be forced by calling [[#ngx.update_time|ngx.u == ngx.now == '''syntax:''' ''secs = ngx.now()'' -'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Returns a floating-point number for the elapsed time in seconds (including milliseconds as the decimal part) from the epoch for the current time stamp from the nginx cached time (no syscall involved unlike Lua's date library). @@ -4481,7 +4493,7 @@ This API was first introduced in v0.3.1rc32. == ngx.update_time == '''syntax:''' ''ngx.update_time()'' -'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Forcibly updates the Nginx current time cache. This call involves a syscall and thus has some overhead, so do not abuse it. @@ -4490,7 +4502,7 @@ This API was first introduced in v0.3.1rc32. == ngx.localtime == '''syntax:''' ''str = ngx.localtime()'' -'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Returns the current time stamp (in the format yyyy-mm-dd hh:mm:ss) of the nginx cached time (no syscall involved unlike Lua's [http://www.lua.org/manual/5.1/manual.html#pdf-os.date os.date] function). @@ -4499,7 +4511,7 @@ This is the local time. == ngx.utctime == '''syntax:''' ''str = ngx.utctime()'' -'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Returns the current time stamp (in the format yyyy-mm-dd hh:mm:ss) of the nginx cached time (no syscall involved unlike Lua's [http://www.lua.org/manual/5.1/manual.html#pdf-os.date os.date] function). @@ -4508,7 +4520,7 @@ This is the UTC time. == ngx.cookie_time == '''syntax:''' ''str = ngx.cookie_time(sec)'' -'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Returns a formatted string can be used as the cookie expiration time. The parameter sec is the time stamp in seconds (like those returned from [[#ngx.time|ngx.time]]). @@ -4520,7 +4532,7 @@ Returns a formatted string can be used as the cookie expiration time. The parame == ngx.http_time == '''syntax:''' ''str = ngx.http_time(sec)'' -'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Returns a formated string can be used as the http header time (for example, being used in Last-Modified header). The parameter sec is the time stamp in seconds (like those returned from [[#ngx.time|ngx.time]]). @@ -4532,7 +4544,7 @@ Returns a formated string can be used as the http header time (for example, bein == ngx.parse_http_time == '''syntax:''' ''sec = ngx.parse_http_time(str)'' -'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Parse the http time string (as returned by [[#ngx.http_time|ngx.http_time]]) into seconds. Returns the seconds or nil if the input string is in bad forms. @@ -4553,7 +4565,7 @@ Returns true if the current request is an nginx subrequest, or subject string using the Perl compatible regular expression regex with the optional options. @@ -4593,15 +4605,15 @@ and are returned in the same Lua table as key-value pairs as the numbered captur -- m["remaining"] == "234" -Unmatched subpatterns will have nil values in their captures table fields. +Unmatched subpatterns will have false values in their captures table fields. local m, err = ngx.re.match("hello, world", "(world)|(hello)|(?howdy)") -- m[0] == "hello" - -- m[1] == nil + -- m[1] == false -- m[2] == "hello" - -- m[3] == nil - -- m["named"] == nil + -- m[3] == false + -- m["named"] == false Specify options to control how the match operation will be performed. The following option characters are supported: @@ -4687,7 +4699,7 @@ Note that, the options argument is not optional when the ctx< This method requires the PCRE library enabled in Nginx. ([[#Special Escaping Sequences|Known Issue With Special Escaping Sequences]]). -To confirm that PCRE JIT is enabled, activate the Nginx debug log by adding the --with-debug option to Nginx or ngx_openresty's ./configure script. Then, enable the "debug" error log level in error_log directive. The following message will be generated if PCRE JIT is enabled: +To confirm that PCRE JIT is enabled, activate the Nginx debug log by adding the --with-debug option to Nginx or OpenResty's ./configure script. Then, enable the "debug" error log level in error_log directive. The following message will be generated if PCRE JIT is enabled: pcre JIT compiling result: 1 @@ -4700,7 +4712,7 @@ This feature was introduced in the v0.2.1rc11 release. == ngx.re.find == '''syntax:''' ''from, to, err = ngx.re.find(subject, regex, options?, ctx?, nth?)'' -'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Similar to [[#ngx.re.match|ngx.re.match]] but only returns the begining index (from) and end index (to) of the matched substring. The returned indexes are 1-based and can be fed directly into the [http://www.lua.org/manual/5.1/manual.html#pdf-string.sub string.sub] API function to obtain the matched substring. @@ -4749,7 +4761,7 @@ This API function was first introduced in the v0.9.2 release. == ngx.re.gmatch == '''syntax:''' ''iterator, err = ngx.re.gmatch(subject, regex, options?)'' -'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Similar to [[#ngx.re.match|ngx.re.match]], but returns a Lua iterator instead, so as to let the user programmer iterate all the matches over the string argument with the PCRE regex. @@ -4822,7 +4834,7 @@ This feature was first introduced in the v0.2.1rc12 release. == ngx.re.sub == '''syntax:''' ''newstr, n, err = ngx.re.sub(subject, regex, replace, options?)'' -'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Substitutes the first match of the Perl compatible regular expression regex on the subject argument string with the string or function argument replace. The optional options argument has exactly the same meaning as in [[#ngx.re.match|ngx.re.match]]. @@ -4881,7 +4893,7 @@ This feature was first introduced in the v0.2.1rc13 release. == ngx.re.gsub == '''syntax:''' ''newstr, n, err = ngx.re.gsub(subject, regex, replace, options?)'' -'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Just like [[#ngx.re.sub|ngx.re.sub]], but does global substitution. @@ -4916,7 +4928,7 @@ This feature was first introduced in the v0.2.1rc15 release. '''syntax:''' ''dict = ngx.shared[name_var]'' -'''context:''' ''init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Fetching the shm-based Lua dictionary object for the shared memory zone named DICT defined by the [[#lua_shared_dict|lua_shared_dict]] directive. @@ -4984,7 +4996,7 @@ This feature was first introduced in the v0.3.1rc22 release. == ngx.shared.DICT.get == '''syntax:''' ''value, flags = ngx.shared.DICT:get(key)'' -'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Retrieving the value in the dictionary [[#ngx.shared.DICT|ngx.shared.DICT]] for the key key. If the key does not exist or has been expired, then nil will be returned. @@ -5017,7 +5029,7 @@ See also [[#ngx.shared.DICT|ngx.shared.DICT]]. == ngx.shared.DICT.get_stale == '''syntax:''' ''value, flags, stale = ngx.shared.DICT:get_stale(key)'' -'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Similar to the [[#ngx.shared.DICT.get|get]] method but returns the value even if the key has already expired. @@ -5032,7 +5044,7 @@ See also [[#ngx.shared.DICT|ngx.shared.DICT]]. == ngx.shared.DICT.set == '''syntax:''' ''success, err, forcible = ngx.shared.DICT:set(key, value, exptime?, flags?)'' -'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Unconditionally sets a key-value pair into the shm-based dictionary [[#ngx.shared.DICT|ngx.shared.DICT]]. Returns three values: @@ -5075,7 +5087,7 @@ See also [[#ngx.shared.DICT|ngx.shared.DICT]]. == ngx.shared.DICT.safe_set == '''syntax:''' ''ok, err = ngx.shared.DICT:safe_set(key, value, exptime?, flags?)'' -'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Similar to the [[#ngx.shared.DICT.set|set]] method, but never overrides the (least recently used) unexpired items in the store when running out of storage in the shared memory zone. In this case, it will immediately return nil and the string "no memory". @@ -5086,7 +5098,7 @@ See also [[#ngx.shared.DICT|ngx.shared.DICT]]. == ngx.shared.DICT.add == '''syntax:''' ''success, err, forcible = ngx.shared.DICT:add(key, value, exptime?, flags?)'' -'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Just like the [[#ngx.shared.DICT.set|set]] method, but only stores the key-value pair into the dictionary [[#ngx.shared.DICT|ngx.shared.DICT]] if the key does ''not'' exist. @@ -5099,7 +5111,7 @@ See also [[#ngx.shared.DICT|ngx.shared.DICT]]. == ngx.shared.DICT.safe_add == '''syntax:''' ''ok, err = ngx.shared.DICT:safe_add(key, value, exptime?, flags?)'' -'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Similar to the [[#ngx.shared.DICT.add|add]] method, but never overrides the (least recently used) unexpired items in the store when running out of storage in the shared memory zone. In this case, it will immediately return nil and the string "no memory". @@ -5110,7 +5122,7 @@ See also [[#ngx.shared.DICT|ngx.shared.DICT]]. == ngx.shared.DICT.replace == '''syntax:''' ''success, err, forcible = ngx.shared.DICT:replace(key, value, exptime?, flags?)'' -'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Just like the [[#ngx.shared.DICT.set|set]] method, but only stores the key-value pair into the dictionary [[#ngx.shared.DICT|ngx.shared.DICT]] if the key ''does'' exist. @@ -5123,7 +5135,7 @@ See also [[#ngx.shared.DICT|ngx.shared.DICT]]. == ngx.shared.DICT.delete == '''syntax:''' ''ngx.shared.DICT:delete(key)'' -'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Unconditionally removes the key-value pair from the shm-based dictionary [[#ngx.shared.DICT|ngx.shared.DICT]]. @@ -5136,7 +5148,7 @@ See also [[#ngx.shared.DICT|ngx.shared.DICT]]. == ngx.shared.DICT.incr == '''syntax:''' ''newval, err = ngx.shared.DICT:incr(key, value)'' -'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Increments the (numerical) value for key in the shm-based dictionary [[#ngx.shared.DICT|ngx.shared.DICT]] by the step value value. Returns the new resulting number if the operation is successfully completed or nil and an error message otherwise. @@ -5153,7 +5165,7 @@ See also [[#ngx.shared.DICT|ngx.shared.DICT]]. == ngx.shared.DICT.flush_all == '''syntax:''' ''ngx.shared.DICT:flush_all()'' -'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Flushes out all the items in the dictionary. This method does not actuall free up all the memory blocks in the dictionary but just marks all the existing items as expired. @@ -5164,7 +5176,7 @@ See also [[#ngx.shared.DICT.flush_expired|ngx.shared.DICT.flush_expired]] and [[ == ngx.shared.DICT.flush_expired == '''syntax:''' ''flushed = ngx.shared.DICT:flush_expired(max_count?)'' -'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Flushes out the expired items in the dictionary, up to the maximal number specified by the optional max_count argument. When the max_count argument is given 0 or not given at all, then it means unlimited. Returns the number of items that have actually been flushed. @@ -5177,7 +5189,7 @@ See also [[#ngx.shared.DICT.flush_all|ngx.shared.DICT.flush_all]] and [[#ngx.sha == ngx.shared.DICT.get_keys == '''syntax:''' ''keys = ngx.shared.DICT:get_keys(max_count?)'' -'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Fetch a list of the keys from the dictionary, up to . @@ -5295,7 +5307,7 @@ Timeout for the reading operation is controlled by the [[#lua_socket_read_timeou sock:settimeout(1000) -- one second timeout local data, err = sock:receive() if not data then - ngx.say("failed to read a packet: ", data) + ngx.say("failed to read a packet: ", err) return end ngx.say("successfully read a packet: ", data) @@ -5327,6 +5339,13 @@ Settings done by this method takes priority over those config directives, like [ This feature was first introduced in the v0.5.7 release. +== ngx.socket.stream == + +Just an alias to [[#ngx.socket.tcp|ngx.socket.tcp]]. If the stream-typed cosocket may also connect to a unix domain +socket, then this API name is preferred. + +This API function was first added to the v0.10.1 release. + == ngx.socket.tcp == '''syntax:''' ''tcpsock = ngx.socket.tcp()'' @@ -6046,7 +6065,7 @@ See also [[#lua_check_client_abort|lua_check_client_abort]]. == ngx.timer.at == '''syntax:''' ''ok, err = ngx.timer.at(delay, callback, user_arg1, user_arg2, ...)'' -'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Creates an Nginx timer with a user callback function as well as optional user arguments. @@ -6167,7 +6186,7 @@ This API was first introduced in the v0.8.0 release. == ngx.timer.running_count == '''syntax:''' ''count = ngx.timer.running_count()'' -'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Returns the number of timers currently running. @@ -6176,12 +6195,22 @@ This directive was first introduced in the v0.9.20 release. == ngx.timer.pending_count == '''syntax:''' ''count = ngx.timer.pending_count()'' -'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' Returns the number of pending timers. This directive was first introduced in the v0.9.20 release. +== ngx.config.subsystem == +'''syntax:''' ''subsystem = ngx.config.subsystem'' + +'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, init_by_lua*, init_worker_by_lua*'' + +This string field indicates the current NGINX subsystem the current Lua environment is based on. For this module, this field always takes the string value `"http"`. For +[https://github.com/openresty/stream-lua-nginx-module#readme ngx_stream_lua_module], however, this field takes the value `"stream"`. + +This field was first introduced in the 0.10.1. + == ngx.config.debug == '''syntax:''' ''debug = ngx.config.debug'' @@ -6352,7 +6381,7 @@ This feature requires at least ngx_lua v0.10.0. == ndk.set_var.DIRECTIVE == '''syntax:''' ''res = ndk.set_var.DIRECTIVE_NAME'' -'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*'' +'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' This mechanism allows calling other nginx C modules' directives that are implemented by [https://github.com/simpl/ngx_devel_kit Nginx Devel Kit] (NDK)'s set_var submodule's ndk_set_var_value. diff --git a/debian/modules/nginx-lua/src/api/ngx_http_lua_api.h b/debian/modules/nginx-lua/src/api/ngx_http_lua_api.h index 84a0579..a15d40e 100644 --- a/debian/modules/nginx-lua/src/api/ngx_http_lua_api.h +++ b/debian/modules/nginx-lua/src/api/ngx_http_lua_api.h @@ -19,7 +19,7 @@ /* Public API for other Nginx modules */ -#define ngx_http_lua_version 10000 +#define ngx_http_lua_version 10001 typedef struct { diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_accessby.c b/debian/modules/nginx-lua/src/ngx_http_lua_accessby.c index 14cc342..bd09def 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_accessby.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_accessby.c @@ -239,6 +239,7 @@ ngx_http_lua_access_by_chunk(lua_State *L, ngx_http_request_t *r) int co_ref; ngx_int_t rc; lua_State *co; + ngx_event_t *rev; ngx_connection_t *c; ngx_http_lua_ctx_t *ctx; ngx_http_cleanup_t *cln; @@ -308,6 +309,14 @@ ngx_http_lua_access_by_chunk(lua_State *L, ngx_http_request_t *r) if (llcf->check_client_abort) { r->read_event_handler = ngx_http_lua_rd_check_broken_connection; + rev = r->connection->read; + + if (!rev->active) { + if (ngx_add_event(rev, NGX_READ_EVENT, 0) != NGX_OK) { + return NGX_ERROR; + } + } + } else { r->read_event_handler = ngx_http_block_reading; } diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_balancer.c b/debian/modules/nginx-lua/src/ngx_http_lua_balancer.c index 4fa91fc..1201d26 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_balancer.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_balancer.c @@ -262,7 +262,24 @@ ngx_http_lua_balancer_get_peer(ngx_peer_connection_t *pc, void *data) ngx_http_lua_assert(lscf->balancer.handler && r); - L = ngx_http_lua_get_lua_vm(r, NULL); + ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); + + if (ctx == NULL) { + ctx = ngx_http_lua_create_ctx(r); + if (ctx == NULL) { + return NGX_ERROR; + } + + L = ngx_http_lua_get_lua_vm(r, ctx); + + } else { + L = ngx_http_lua_get_lua_vm(r, ctx); + + dd("reset ctx"); + ngx_http_lua_reset_ctx(r, L, ctx); + } + + ctx->context = NGX_HTTP_LUA_CONTEXT_BALANCER; bp->sockaddr = NULL; bp->socklen = 0; @@ -283,8 +300,6 @@ ngx_http_lua_balancer_get_peer(ngx_peer_connection_t *pc, void *data) return NGX_ERROR; } - ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); - if (ctx->exited && ctx->exit_code != NGX_OK) { rc = ctx->exit_code; if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) { @@ -321,22 +336,6 @@ ngx_http_lua_balancer_by_chunk(lua_State *L, ngx_http_request_t *r) u_char *err_msg; size_t len; ngx_int_t rc; - ngx_http_lua_ctx_t *ctx; - - ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); - - if (ctx == NULL) { - ctx = ngx_http_lua_create_ctx(r); - if (ctx == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - } else { - dd("reset ctx"); - ngx_http_lua_reset_ctx(r, L, ctx); - } - - ctx->context = NGX_HTTP_LUA_CONTEXT_BALANCER; /* init nginx context in Lua VM */ ngx_http_lua_set_req(L, r); diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_config.c b/debian/modules/nginx-lua/src/ngx_http_lua_config.c index 00594be..3323175 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_config.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_config.c @@ -23,7 +23,7 @@ ngx_http_lua_inject_config_api(lua_State *L) { /* ngx.config */ - lua_createtable(L, 0, 5 /* nrec */); /* .config */ + lua_createtable(L, 0, 6 /* nrec */); /* .config */ #if (NGX_DEBUG) lua_pushboolean(L, 1); @@ -44,6 +44,9 @@ ngx_http_lua_inject_config_api(lua_State *L) lua_pushcfunction(L, ngx_http_lua_config_configure); lua_setfield(L, -2, "nginx_configure"); + lua_pushliteral(L, "http"); + lua_setfield(L, -2, "subsystem"); + lua_setfield(L, -2, "config"); } diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_contentby.c b/debian/modules/nginx-lua/src/ngx_http_lua_contentby.c index 666b549..6718885 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_contentby.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_contentby.c @@ -27,6 +27,7 @@ ngx_http_lua_content_by_chunk(lua_State *L, ngx_http_request_t *r) int co_ref; ngx_int_t rc; lua_State *co; + ngx_event_t *rev; ngx_http_lua_ctx_t *ctx; ngx_http_cleanup_t *cln; @@ -96,6 +97,14 @@ ngx_http_lua_content_by_chunk(lua_State *L, ngx_http_request_t *r) if (llcf->check_client_abort) { r->read_event_handler = ngx_http_lua_rd_check_broken_connection; + rev = r->connection->read; + + if (!rev->active) { + if (ngx_add_event(rev, NGX_READ_EVENT, 0) != NGX_OK) { + return NGX_ERROR; + } + } + } else { r->read_event_handler = ngx_http_block_reading; } diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_headers.c b/debian/modules/nginx-lua/src/ngx_http_lua_headers.c index a9e45d3..45be168 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_headers.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_headers.c @@ -53,6 +53,12 @@ ngx_http_lua_ngx_req_http_version(lua_State *L) lua_pushnumber(L, 1.1); break; +#ifdef NGX_HTTP_VERSION_20 + case NGX_HTTP_VERSION_20: + lua_pushnumber(L, 2.0); + break; +#endif + default: lua_pushnil(L); break; diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_initworkerby.c b/debian/modules/nginx-lua/src/ngx_http_lua_initworkerby.c index 0876f26..8a374c2 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_initworkerby.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_initworkerby.c @@ -26,6 +26,7 @@ ngx_http_lua_init_worker(ngx_cycle_t *cycle) ngx_uint_t i; ngx_conf_t conf; ngx_cycle_t *fake_cycle; + ngx_module_t **modules; ngx_open_file_t *file, *ofile; ngx_list_part_t *part; ngx_connection_t *c = NULL; @@ -46,7 +47,7 @@ ngx_http_lua_init_worker(ngx_cycle_t *cycle) return NGX_OK; } - conf_ctx = ((ngx_http_conf_ctx_t *) cycle->conf_ctx[ngx_http_module.index]); + conf_ctx = (ngx_http_conf_ctx_t *) cycle->conf_ctx[ngx_http_module.index]; http_ctx.main_conf = conf_ctx->main_conf; top_clcf = conf_ctx->loc_conf[ngx_http_core_module.ctx_index]; @@ -154,12 +155,18 @@ ngx_http_lua_init_worker(ngx_cycle_t *cycle) return NGX_ERROR; } - for (i = 0; ngx_modules[i]; i++) { - if (ngx_modules[i]->type != NGX_HTTP_MODULE) { +#if defined(nginx_version) && nginx_version >= 1009011 + modules = cycle->modules; +#else + modules = ngx_modules; +#endif + + for (i = 0; modules[i]; i++) { + if (modules[i]->type != NGX_HTTP_MODULE) { continue; } - module = ngx_modules[i]->ctx; + module = modules[i]->ctx; if (module->create_srv_conf) { cur = module->create_srv_conf(&conf); @@ -167,7 +174,7 @@ ngx_http_lua_init_worker(ngx_cycle_t *cycle) return NGX_ERROR; } - http_ctx.srv_conf[ngx_modules[i]->ctx_index] = cur; + http_ctx.srv_conf[modules[i]->ctx_index] = cur; if (module->merge_srv_conf) { prev = module->create_srv_conf(&conf); @@ -188,7 +195,7 @@ ngx_http_lua_init_worker(ngx_cycle_t *cycle) return NGX_ERROR; } - http_ctx.loc_conf[ngx_modules[i]->ctx_index] = cur; + http_ctx.loc_conf[modules[i]->ctx_index] = cur; if (module->merge_loc_conf) { prev = module->create_loc_conf(&conf); diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_log.c b/debian/modules/nginx-lua/src/ngx_http_lua_log.c index daca3fd..c2b2269 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_log.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_log.c @@ -160,6 +160,16 @@ log_wrapper(ngx_log_t *log, const char *ident, ngx_uint_t level, break; + case LUA_TTABLE: + if (!luaL_callmeta(L, i, "__tostring")) { + return luaL_argerror(L, i, "expected table to have " + "__tostring metamethod"); + } + + lua_tolstring(L, -1, &len); + size += len; + break; + case LUA_TLIGHTUSERDATA: if (lua_touserdata(L, i) == NULL) { size += sizeof("null") - 1; @@ -227,6 +237,12 @@ log_wrapper(ngx_log_t *log, const char *ident, ngx_uint_t level, break; + case LUA_TTABLE: + luaL_callmeta(L, i, "__tostring"); + q = (u_char *) lua_tolstring(L, -1, &len); + p = ngx_copy(p, q, len); + break; + case LUA_TLIGHTUSERDATA: *p++ = 'n'; *p++ = 'u'; diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_module.c b/debian/modules/nginx-lua/src/ngx_http_lua_module.c index c72a705..4cfee82 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_module.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_module.c @@ -503,8 +503,6 @@ static ngx_command_t ngx_http_lua_cmds[] = { offsetof(ngx_http_lua_loc_conf_t, ssl_ciphers), NULL }, -#if (NGX_HTTP_SSL) - { ngx_string("ssl_certificate_by_lua_block"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS, ngx_http_lua_ssl_cert_by_lua_block, @@ -519,8 +517,6 @@ static ngx_command_t ngx_http_lua_cmds[] = { 0, (void *) ngx_http_lua_ssl_cert_handler_file }, -#endif /* NGX_HTTP_SSL */ - { ngx_string("lua_ssl_verify_depth"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_num_slot, @@ -941,11 +937,11 @@ ngx_http_lua_create_loc_conf(ngx_conf_t *cf) * conf->body_filter_src_key = NULL * conf->body_filter_handler = NULL; * - * conf->ssl = 0; - * conf->ssl_protocols = 0; - * conf->ssl_ciphers = { 0, NULL }; - * conf->ssl_trusted_certificate = { 0, NULL }; - * conf->ssl_crl = { 0, NULL }; + * conf->ssl = 0; + * conf->ssl_protocols = 0; + * conf->ssl_ciphers = { 0, NULL }; + * conf->ssl_trusted_certificate = { 0, NULL }; + * conf->ssl_crl = { 0, NULL }; */ conf->force_read_body = NGX_CONF_UNSET; diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_ndk.c b/debian/modules/nginx-lua/src/ngx_http_lua_ndk.c index d942296..24b80b4 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_ndk.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_ndk.c @@ -116,15 +116,22 @@ ngx_http_lookup_ndk_set_var_directive(u_char *name, ndk_set_var_t *filter; ngx_uint_t i; ngx_module_t *module; + ngx_module_t **modules; ngx_command_t *cmd; - for (i = 0; ngx_modules[i]; i++) { - module = ngx_modules[i]; +#if defined(nginx_version) && nginx_version >= 1009011 + modules = ngx_cycle->modules; +#else + modules = ngx_modules; +#endif + + for (i = 0; modules[i]; i++) { + module = modules[i]; if (module->type != NGX_HTTP_MODULE) { continue; } - cmd = ngx_modules[i]->commands; + cmd = modules[i]->commands; if (cmd == NULL) { continue; } diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_output.c b/debian/modules/nginx-lua/src/ngx_http_lua_output.c index dca5fb9..ef816d2 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_output.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_output.c @@ -3,6 +3,7 @@ #endif #include "ddebug.h" + #include "ngx_http_lua_output.h" #include "ngx_http_lua_util.h" #include "ngx_http_lua_contentby.h" diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_regex.c b/debian/modules/nginx-lua/src/ngx_http_lua_regex.c index 8b4a668..be110e3 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_regex.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_regex.c @@ -420,6 +420,7 @@ ngx_http_lua_ngx_re_match_helper(lua_State *L, int wantcaps) if (flags & NGX_LUA_RE_MODE_DFA) { ovecsize = 2; + re_comp.captures = 0; } else { ovecsize = (re_comp.captures + 1) * 3; @@ -592,14 +593,15 @@ exec: } if (res_tb_idx == 0) { - lua_createtable(L, rc /* narr */, 0 /* nrec */); + lua_createtable(L, re_comp.captures || 1 /* narr */, + name_count /* nrec */); res_tb_idx = lua_gettop(L); } - for (i = 0, n = 0; i < rc; i++, n += 2) { + for (i = 0, n = 0; i <= re_comp.captures; i++, n += 2) { dd("capture %d: %d %d", i, cap[n], cap[n + 1]); - if (cap[n] < 0) { - lua_pushnil(L); + if (i >= rc || cap[n] < 0) { + lua_pushboolean(L, 0); } else { lua_pushlstring(L, (char *) &subj.data[cap[n]], @@ -881,6 +883,7 @@ ngx_http_lua_ngx_re_gmatch(lua_State *L) if (flags & NGX_LUA_RE_MODE_DFA) { ovecsize = 2; + re_comp.captures = 0; } else { ovecsize = (re_comp.captures + 1) * 3; @@ -1116,12 +1119,12 @@ ngx_http_lua_ngx_re_gmatch_iterator(lua_State *L) dd("rc = %d", (int) rc); - lua_createtable(L, rc /* narr */, 0 /* nrec */); + lua_createtable(L, ctx->ncaptures || 1 /* narr */, name_count /* nrec */); - for (i = 0, n = 0; i < rc; i++, n += 2) { + for (i = 0, n = 0; i <= ctx->ncaptures; i++, n += 2) { dd("capture %d: %d %d", i, cap[n], cap[n + 1]); - if (cap[n] < 0) { - lua_pushnil(L); + if (i >= rc || cap[n] < 0) { + lua_pushboolean(L, 0); } else { lua_pushlstring(L, (char *) &subj.data[cap[n]], @@ -1564,6 +1567,7 @@ ngx_http_lua_ngx_re_sub_helper(lua_State *L, unsigned global) if (flags & NGX_LUA_RE_MODE_DFA) { ovecsize = 2; + re_comp.captures = 0; } else { ovecsize = (re_comp.captures + 1) * 3; @@ -1750,12 +1754,13 @@ exec: if (func) { lua_pushvalue(L, 3); - lua_createtable(L, rc - 1 /* narr */, 1 /* nrec */); + lua_createtable(L, re_comp.captures || 1 /* narr */, + name_count /* nrec */); - for (i = 0, n = 0; i < rc; i++, n += 2) { + for (i = 0, n = 0; i <= re_comp.captures; i++, n += 2) { dd("capture %d: %d %d", (int) i, cap[n], cap[n + 1]); - if (cap[n] < 0) { - lua_pushnil(L); + if (i >= rc || cap[n] < 0) { + lua_pushboolean(L, 0); } else { lua_pushlstring(L, (char *) &subj.data[cap[n]], @@ -2071,6 +2076,11 @@ ngx_http_lua_re_collect_named_captures(lua_State *L, int res_tb_idx, } if (flags & NGX_LUA_RE_MODE_DUPNAMES) { + /* unmatched groups are not stored in tables in DUPNAMES mode */ + if (!lua_toboolean(L, -1)) { + lua_pop(L, 1); + continue; + } lua_getfield(L, -2, name); /* big_tb cap small_tb */ @@ -2201,6 +2211,7 @@ ngx_http_lua_ffi_compile_regex(const unsigned char *pat, size_t pat_len, if (flags & NGX_LUA_RE_MODE_DFA) { ovecsize = 2; + re_comp.captures = 0; } else { ovecsize = (re_comp.captures + 1) * 3; @@ -2279,6 +2290,7 @@ ngx_http_lua_ffi_exec_regex(ngx_http_lua_regex_t *re, int flags, if (flags & NGX_LUA_RE_MODE_DFA) { ovecsize = 2; + re->ncaptures = 0; } else { ovecsize = (re->ncaptures + 1) * 3; diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_req_body.c b/debian/modules/nginx-lua/src/ngx_http_lua_req_body.c index a916396..591d2cd 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_req_body.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_req_body.c @@ -619,9 +619,9 @@ ngx_http_lua_ngx_req_append_body(lua_State *L) ngx_http_request_t *r; int n; ngx_http_request_body_t *rb; - ngx_str_t body; - size_t size, rest; - size_t offset = 0; + ngx_str_t body; + size_t size, rest; + size_t offset = 0; n = lua_gettop(L); @@ -683,10 +683,10 @@ ngx_http_lua_ngx_req_body_finish(lua_State *L) int n; ngx_http_request_body_t *rb; ngx_buf_t *b; - size_t size; - ngx_str_t value; - ngx_str_t key; - ngx_int_t rc; + size_t size; + ngx_str_t value; + ngx_str_t key; + ngx_int_t rc; n = lua_gettop(L); diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_rewriteby.c b/debian/modules/nginx-lua/src/ngx_http_lua_rewriteby.c index da30b8b..2ef59c5 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_rewriteby.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_rewriteby.c @@ -235,6 +235,7 @@ ngx_http_lua_rewrite_by_chunk(lua_State *L, ngx_http_request_t *r) int co_ref; lua_State *co; ngx_int_t rc; + ngx_event_t *rev; ngx_connection_t *c; ngx_http_lua_ctx_t *ctx; ngx_http_cleanup_t *cln; @@ -303,6 +304,14 @@ ngx_http_lua_rewrite_by_chunk(lua_State *L, ngx_http_request_t *r) if (llcf->check_client_abort) { r->read_event_handler = ngx_http_lua_rd_check_broken_connection; + rev = r->connection->read; + + if (!rev->active) { + if (ngx_add_event(rev, NGX_READ_EVENT, 0) != NGX_OK) { + return NGX_ERROR; + } + } + } else { r->read_event_handler = ngx_http_block_reading; } diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_script.h b/debian/modules/nginx-lua/src/ngx_http_lua_script.h index b6dbcd4..9fdca96 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_script.h +++ b/debian/modules/nginx-lua/src/ngx_http_lua_script.h @@ -75,10 +75,10 @@ typedef struct { ngx_int_t ngx_http_lua_compile_complex_value( - ngx_http_lua_compile_complex_value_t *ccv); + ngx_http_lua_compile_complex_value_t *ccv); ngx_int_t ngx_http_lua_complex_value(ngx_http_request_t *r, ngx_str_t *subj, - size_t offset, ngx_int_t count, int *cap, - ngx_http_lua_complex_value_t *val, luaL_Buffer *luabuf); + size_t offset, ngx_int_t count, int *cap, + ngx_http_lua_complex_value_t *val, luaL_Buffer *luabuf); #endif /* _NGX_HTTP_LUA_SCRIPT_H_INCLUDED_ */ diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_semaphore.c b/debian/modules/nginx-lua/src/ngx_http_lua_semaphore.c index b022604..8d4ac07 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_semaphore.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_semaphore.c @@ -249,7 +249,7 @@ ngx_http_lua_semaphore_resume(ngx_http_request_t *r) } else { lua_pushboolean(ctx->cur_co_ctx->co, 0); - lua_pushstring(ctx->cur_co_ctx->co, "timeout"); + lua_pushliteral(ctx->cur_co_ctx->co, "timeout"); } rc = ngx_http_lua_run_thread(vm, r, ctx, 2); diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_shdict.c b/debian/modules/nginx-lua/src/ngx_http_lua_shdict.c index d853382..43f5f9e 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_shdict.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_shdict.c @@ -140,7 +140,7 @@ void ngx_http_lua_shdict_rbtree_insert_value(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel) { - ngx_rbtree_node_t **p; + ngx_rbtree_node_t **p; ngx_http_lua_shdict_node_t *sdn, *sdnt; for ( ;; ) { @@ -949,7 +949,7 @@ ngx_http_lua_shdict_set_helper(lua_State *L, int flags) if (n >= 4) { exptime = luaL_checknumber(L, 4); if (exptime < 0) { - exptime = 0; + return luaL_error(L, "bad \"exptime\" argument"); } } diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_socket_tcp.c b/debian/modules/nginx-lua/src/ngx_http_lua_socket_tcp.c index 98801f5..1a6594d 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_socket_tcp.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_socket_tcp.c @@ -197,10 +197,12 @@ ngx_http_lua_inject_socket_tcp_api(ngx_log_t *log, lua_State *L) { ngx_int_t rc; - lua_createtable(L, 0, 3 /* nrec */); /* ngx.socket */ + lua_createtable(L, 0, 4 /* nrec */); /* ngx.socket */ lua_pushcfunction(L, ngx_http_lua_socket_tcp); - lua_setfield(L, -2, "tcp"); + lua_pushvalue(L, -1); + lua_setfield(L, -3, "tcp"); + lua_setfield(L, -2, "stream"); { const char buf[] = "local sock = ngx.socket.tcp()" @@ -2874,6 +2876,7 @@ ngx_http_lua_socket_send(ngx_http_request_t *r, } if (n == NGX_ERROR) { + c->error = 1; u->socket_errno = ngx_socket_errno; ngx_http_lua_socket_handle_write_error(r, u, NGX_HTTP_LUA_SOCKET_FT_ERROR); diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_socket_udp.c b/debian/modules/nginx-lua/src/ngx_http_lua_socket_udp.c index bfb122f..1ec0c00 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_socket_udp.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_socket_udp.c @@ -54,7 +54,7 @@ static void ngx_http_lua_socket_udp_read_handler(ngx_http_request_t *r, ngx_http_lua_socket_udp_upstream_t *u); static void ngx_http_lua_socket_udp_handle_success(ngx_http_request_t *r, ngx_http_lua_socket_udp_upstream_t *u); -static ngx_int_t ngx_http_lua_udp_connect(ngx_udp_connection_t *uc); +static ngx_int_t ngx_http_lua_udp_connect(ngx_http_lua_udp_connection_t *uc); static int ngx_http_lua_socket_udp_close(lua_State *L); static ngx_int_t ngx_http_lua_socket_udp_resume(ngx_http_request_t *r); static void ngx_http_lua_udp_resolve_cleanup(void *data); @@ -170,10 +170,10 @@ ngx_http_lua_socket_udp_setpeername(lua_State *L) ngx_url_t url; ngx_int_t rc; ngx_http_lua_loc_conf_t *llcf; - ngx_udp_connection_t *uc; int timeout; ngx_http_lua_co_ctx_t *coctx; + ngx_http_lua_udp_connection_t *uc; ngx_http_lua_socket_udp_upstream_t *u; /* @@ -642,11 +642,11 @@ ngx_http_lua_socket_resolve_retval_handler(ngx_http_request_t *r, { ngx_http_lua_ctx_t *ctx; ngx_http_lua_co_ctx_t *coctx; - ngx_udp_connection_t *uc; ngx_connection_t *c; ngx_http_cleanup_t *cln; ngx_http_upstream_resolved_t *ur; ngx_int_t rc; + ngx_http_lua_udp_connection_t *uc; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua udp socket resolve retval handler"); @@ -1348,7 +1348,7 @@ ngx_http_lua_socket_udp_handle_success(ngx_http_request_t *r, static ngx_int_t -ngx_http_lua_udp_connect(ngx_udp_connection_t *uc) +ngx_http_lua_udp_connect(ngx_http_lua_udp_connection_t *uc) { int rc; ngx_int_t event; diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_socket_udp.h b/debian/modules/nginx-lua/src/ngx_http_lua_socket_udp.h index dd75b2d..8333346 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_socket_udp.h +++ b/debian/modules/nginx-lua/src/ngx_http_lua_socket_udp.h @@ -24,6 +24,15 @@ typedef void (*ngx_http_lua_socket_udp_upstream_handler_pt) (ngx_http_request_t *r, ngx_http_lua_socket_udp_upstream_t *u); +typedef struct { + ngx_connection_t *connection; + struct sockaddr *sockaddr; + socklen_t socklen; + ngx_str_t server; + ngx_log_t log; +} ngx_http_lua_udp_connection_t; + + struct ngx_http_lua_socket_udp_upstream_s { ngx_http_lua_socket_udp_retval_handler prepare_retvals; ngx_http_lua_socket_udp_upstream_handler_pt read_event_handler; @@ -31,7 +40,7 @@ struct ngx_http_lua_socket_udp_upstream_s { ngx_http_lua_loc_conf_t *conf; ngx_http_cleanup_pt *cleanup; ngx_http_request_t *request; - ngx_udp_connection_t udp_connection; + ngx_http_lua_udp_connection_t udp_connection; ngx_msec_t read_timeout; diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_ssl_certby.c b/debian/modules/nginx-lua/src/ngx_http_lua_ssl_certby.c index f8648a7..32675b2 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_ssl_certby.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_ssl_certby.c @@ -585,24 +585,24 @@ ngx_http_lua_ffi_ssl_set_der_certificate(ngx_http_request_t *r, bio = BIO_new_mem_buf((char *) data, len); if (bio == NULL) { - *err = " BIO_new_mem_buf() failed"; + *err = "BIO_new_mem_buf() failed"; goto failed; } x509 = d2i_X509_bio(bio, NULL); if (x509 == NULL) { - *err = " d2i_X509_bio() failed"; + *err = "d2i_X509_bio() failed"; goto failed; } if (SSL_use_certificate(ssl_conn, x509) == 0) { - *err = " SSL_use_certificate() failed"; + *err = "SSL_use_certificate() failed"; goto failed; } #if 0 if (SSL_set_ex_data(ssl_conn, ngx_ssl_certificate_index, x509) == 0) { - *err = " SSL_set_ex_data() failed"; + *err = "SSL_set_ex_data() failed"; goto failed; } #endif @@ -837,6 +837,7 @@ ngx_http_lua_ffi_cert_pem_to_der(const u_char *pem, size_t pem_len, u_char *der, total = i2d_X509(x509, &der); if (total < 0) { + *err = "i2d_X509() failed"; X509_free(x509); BIO_free(bio); return NGX_ERROR; @@ -892,7 +893,6 @@ ngx_http_lua_ffi_priv_key_pem_to_der(const u_char *pem, size_t pem_len, { int len; BIO *in; - RSA *rsa; EVP_PKEY *pkey; in = BIO_new_mem_buf((char *) pem, (int) pem_len); @@ -910,24 +910,15 @@ ngx_http_lua_ffi_priv_key_pem_to_der(const u_char *pem, size_t pem_len, BIO_free(in); - rsa = EVP_PKEY_get1_RSA(pkey); - if (rsa == NULL) { + len = i2d_PrivateKey(pkey, &der); + if (len < 0) { EVP_PKEY_free(pkey); - *err = "EVP_PKEY_get1_RSA failed"; + *err = "i2d_PrivateKey failed"; return NGX_ERROR; } EVP_PKEY_free(pkey); - len = i2d_RSAPrivateKey(rsa, &der); - if (len < 0) { - RSA_free(rsa); - *err = "i2d_RSAPrivateKey failed"; - return NGX_ERROR; - } - - RSA_free(rsa); - return len; } diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_util.c b/debian/modules/nginx-lua/src/ngx_http_lua_util.c index afb7655..69eccae 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_util.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_util.c @@ -1649,6 +1649,8 @@ ngx_http_lua_process_flushing_coroutines(ngx_http_request_t *r, if (coctx[i].flushing) { coctx[i].flushing = 0; + ctx->flushing_coros--; + n--; ctx->cur_co_ctx = &coctx[i]; rc = ngx_http_lua_flush_resume_helper(r, ctx); @@ -1658,8 +1660,6 @@ ngx_http_lua_process_flushing_coroutines(ngx_http_request_t *r, /* rc == NGX_DONE */ - ctx->flushing_coros--; - n--; if (n == 0) { return NGX_DONE; } @@ -1694,6 +1694,8 @@ ngx_http_lua_flush_pending_output(ngx_http_request_t *r, c->buffered); if (ctx->busy_bufs) { + /* FIXME since cosockets also share this busy_bufs chain, this condition + * might not be strong enough. better use separate busy_bufs chains. */ rc = ngx_http_lua_output_filter(r, NULL); } else { @@ -3782,8 +3784,9 @@ ngx_http_lua_cleanup_vm(void *data) #endif if (state) { - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, "decrementing " - "the reference count for Lua VM: %i", state->count); + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, + "lua decrementing the reference count for Lua VM: %i", + state->count); if (--state->count == 0) { L = state->vm; diff --git a/debian/modules/nginx-lua/t/008-today.t b/debian/modules/nginx-lua/t/008-today.t index 02169c8..54bd949 100644 --- a/debian/modules/nginx-lua/t/008-today.t +++ b/debian/modules/nginx-lua/t/008-today.t @@ -1,4 +1,4 @@ -# vim:set ft=perl ts=4 sw=4 et fdm=marker: +# vim:set ft= ts=4 sw=4 et fdm=marker: use Test::Nginx::Socket::Lua; @@ -6,7 +6,7 @@ use Test::Nginx::Socket::Lua; #master_process_enabled(1); log_level('warn'); -repeat_each(1); +repeat_each(2); plan tests => repeat_each() * (blocks() * 2); diff --git a/debian/modules/nginx-lua/t/009-log.t b/debian/modules/nginx-lua/t/009-log.t index e06c799..053dd45 100644 --- a/debian/modules/nginx-lua/t/009-log.t +++ b/debian/modules/nginx-lua/t/009-log.t @@ -265,7 +265,96 @@ qr/\[error\] \S+: \S+ \[lua\] set_by_lua:2: truefalsenil,/ -=== TEST 14: print() in header filter +=== TEST 14: test table with metamethod +--- config + location /log { + content_by_lua_block { + ngx.say("before log") + local t = setmetatable({v = "value"}, { + __tostring = function(self) + return "tostring "..self.v + end + }) + ngx.log(ngx.ERR, t) + ngx.say("after log") + } + } +--- request +GET /log +--- response_body +before log +after log +--- error_log eval +qr/\[error\] \S+: \S+ \[lua\] content_by_lua\(nginx\.conf:\d+\):8: tostring value,/ + + + +=== TEST 15: test table without metamethod +--- config + location /log { + content_by_lua_block { + ngx.log(ngx.ERR, {}) + ngx.say("done") + } + } +--- request +GET /log +--- response_body_like: 500 Internal Server Error +--- error_code: 500 +--- error_log +bad argument #1 to 'log' (expected table to have __tostring metamethod) + + + +=== TEST 16: test tables mixed with other types +--- config + location /log { + content_by_lua_block { + ngx.say("before log") + local t = setmetatable({v = "value"}, { + __tostring = function(self) + return "tostring: "..self.v + end + }) + ngx.log(ngx.ERR, t, " hello ", t) + ngx.say("after log") + } + } +--- request +GET /log +--- response_body +before log +after log +--- error_log eval +qr/\[error\] \S+: \S+ \[lua\] content_by_lua\(nginx\.conf:\d+\):8: tostring: value hello tostring: value,/ + + + +=== TEST 17: test print with tables +--- config + location /log { + content_by_lua_block { + ngx.say("before log") + local t = setmetatable({v = "value"}, { + __tostring = function(self) + return "tostring: "..self.v + end + }) + print(t, " hello ", t) + ngx.say("after log") + } + } +--- request +GET /log +--- response_body +before log +after log +--- error_log eval +qr/\[notice\] \S+: \S+ \[lua\] content_by_lua\(nginx\.conf:\d+\):8: tostring: value hello tostring: value,/ + + + +=== TEST 18: print() in header filter --- config location /log { header_filter_by_lua ' @@ -285,7 +374,7 @@ hi -=== TEST 15: ngx.log() in header filter +=== TEST 19: ngx.log in header filter --- config location /log { header_filter_by_lua ' @@ -305,7 +394,7 @@ qr/\[error\] .*? \[lua\] header_filter_by_lua:2: howdy, lua!/ -=== TEST 16: ngx.log() big data +=== TEST 20: ngx.log big data --- config location /log { content_by_lua ' @@ -321,7 +410,7 @@ GET /log -=== TEST 17: ngx.log in Lua function calls & inlined lua +=== TEST 21: ngx.log in Lua function calls & inlined lua --- config location /log { content_by_lua ' @@ -346,7 +435,7 @@ qr/\[error\] \S+: \S+ \[lua\] content_by_lua\(nginx\.conf:\d+\):7: bar\(\): hell -=== TEST 18: ngx.log in Lua function tail-calls & inlined lua +=== TEST 22: ngx.log in Lua function tail-calls & inlined lua --- config location /log { content_by_lua ' @@ -376,7 +465,7 @@ qr/\[error\] \S+: \S+ \[lua\] content_by_lua\(nginx\.conf:\d+\):8:(?: foo\(\):)? -=== TEST 19: ngx.log in Lua files +=== TEST 23: ngx.log in Lua files --- config location /log { content_by_lua_file 'html/test.lua'; @@ -403,7 +492,7 @@ qr/\[error\] \S+: \S+ \[lua\] test.lua:6: bar\(\): hello, log12343.14159/ -=== TEST 20: ngx.log with bad levels (ngx.ERROR, -1) +=== TEST 24: ngx.log with bad levels (ngx.ERROR, -1) --- config location /log { content_by_lua ' @@ -420,7 +509,7 @@ bad log level: -1 -=== TEST 21: ngx.log with bad levels (9) +=== TEST 25: ngx.log with bad levels (9) --- config location /log { content_by_lua ' @@ -437,7 +526,7 @@ bad log level: 9 -=== TEST 22: \0 in the log message +=== TEST 26: \0 in the log message --- config location = /t { content_by_lua ' diff --git a/debian/modules/nginx-lua/t/011-md5_bin.t b/debian/modules/nginx-lua/t/011-md5_bin.t index 48b8c61..ae7c974 100644 --- a/debian/modules/nginx-lua/t/011-md5_bin.t +++ b/debian/modules/nginx-lua/t/011-md5_bin.t @@ -160,11 +160,11 @@ d41d8cd98f00b204e9800998ecf8427e s = string.gsub(s, ".", function (c) return string.format("%02x", string.byte(c)) end) - return s + ngx.say(s) '; } --- request GET /t --- response_body - +6c8349cc7260ae62e3b1396831a8398f diff --git a/debian/modules/nginx-lua/t/013-base64.t b/debian/modules/nginx-lua/t/013-base64.t index 6903218..1cc27de 100644 --- a/debian/modules/nginx-lua/t/013-base64.t +++ b/debian/modules/nginx-lua/t/013-base64.t @@ -14,7 +14,6 @@ plan tests => repeat_each() * (blocks() * 2 + 4); #no_long_string(); run_tests(); - __DATA__ === TEST 1: base64 encode hello diff --git a/debian/modules/nginx-lua/t/016-resp-header.t b/debian/modules/nginx-lua/t/016-resp-header.t index e23b48f..b1f5e2a 100644 --- a/debian/modules/nginx-lua/t/016-resp-header.t +++ b/debian/modules/nginx-lua/t/016-resp-header.t @@ -1226,7 +1226,6 @@ bar: baz === TEST 60: built-in Content-Type header ---- main_config --- config location = /t { content_by_lua ' @@ -1255,7 +1254,6 @@ my content_type: text/plain === TEST 61: built-in Content-Length header ---- main_config --- config location = /t { content_by_lua ' @@ -1284,7 +1282,6 @@ my content_length: 3 === TEST 62: built-in Connection header ---- main_config --- config location = /t { content_by_lua ' @@ -1311,7 +1308,6 @@ my connection: close === TEST 63: built-in Transfer-Encoding header (chunked) ---- main_config --- config location = /t { content_by_lua ' @@ -1339,7 +1335,6 @@ my transfer-encoding: chunked === TEST 64: built-in Transfer-Encoding header (none) ---- main_config --- config location = /t { content_by_lua ' diff --git a/debian/modules/nginx-lua/t/034-match.t b/debian/modules/nginx-lua/t/034-match.t index 172c1b3..4792ae6 100644 --- a/debian/modules/nginx-lua/t/034-match.t +++ b/debian/modules/nginx-lua/t/034-match.t @@ -409,7 +409,7 @@ error: .*?unknown flag "H" \(flags "Hm"\) GET /re --- response_body hello -nil +false hello @@ -814,7 +814,7 @@ hello-1234 -=== TEST 38: named captures are nil +=== TEST 38: named captures are false --- config location /re { content_by_lua ' @@ -834,10 +834,10 @@ hello-1234 GET /re --- response_body hello -nil +false hello -nil -nil +false +false @@ -1148,3 +1148,24 @@ failed to match 1234 --- SKIP + + +=== TEST 49: trailing captures are false +--- config + location /re { + content_by_lua ' + local m = ngx.re.match("hello", "(hello)(.+)?") + if m then + ngx.say(m[0]) + ngx.say(m[1]) + ngx.say(m[2]) + end + '; + } +--- request + GET /re +--- response_body +hello +hello +false + diff --git a/debian/modules/nginx-lua/t/035-gmatch.t b/debian/modules/nginx-lua/t/035-gmatch.t index 04a06ed..69b9512 100644 --- a/debian/modules/nginx-lua/t/035-gmatch.t +++ b/debian/modules/nginx-lua/t/035-gmatch.t @@ -582,13 +582,13 @@ matched: [] --- response_body 1234 1234 -nil +false 1234 -nil +false abcd -nil +false abcd -nil +false abcd diff --git a/debian/modules/nginx-lua/t/036-sub.t b/debian/modules/nginx-lua/t/036-sub.t index 88dc8d6..f08c50f 100644 --- a/debian/modules/nginx-lua/t/036-sub.t +++ b/debian/modules/nginx-lua/t/036-sub.t @@ -8,7 +8,7 @@ use Test::Nginx::Socket::Lua; repeat_each(2); -plan tests => repeat_each() * (blocks() * 2 + 18); +plan tests => repeat_each() * (blocks() * 2 + 19); #no_diff(); no_long_string(); @@ -732,3 +732,26 @@ GET /t bad argument type NYI + + +=== TEST 33: function replace (false for groups) +--- config + location /re { + content_by_lua ' + local repl = function (m) + print("group 1: ", m[2]) + return "[" .. m[0] .. "] [" .. m[1] .. "]" + end + + local s, n = ngx.re.sub("hello, 34", "([0-9])|(world)", repl) + ngx.say(s) + ngx.say(n) + '; + } +--- request + GET /re +--- response_body +hello, [3] [3]4 +1 +--- error_log +group 1: false diff --git a/debian/modules/nginx-lua/t/037-gsub.t b/debian/modules/nginx-lua/t/037-gsub.t index b3bb04e..2a1e00f 100644 --- a/debian/modules/nginx-lua/t/037-gsub.t +++ b/debian/modules/nginx-lua/t/037-gsub.t @@ -4,11 +4,11 @@ use Test::Nginx::Socket::Lua; #worker_connections(1014); #master_on(); #workers(2); -log_level('warn'); +#log_level('warn'); repeat_each(2); -plan tests => repeat_each() * (blocks() * 2 + 16); +plan tests => repeat_each() * (blocks() * 2 + 17); #no_diff(); no_long_string(); @@ -674,3 +674,26 @@ GET /t --- no_error_log [error] + + +=== TEST 29: function replace (false for groups) +--- config + location /re { + content_by_lua ' + local repl = function (m) + print("group 1: ", m[2]) + return "[" .. m[0] .. "] [" .. m[1] .. "]" + end + + local s, n = ngx.re.gsub("hello, 34", "([0-9])|(world)", repl) + ngx.say(s) + ngx.say(n) + '; + } +--- request + GET /re +--- response_body +hello, [3] [3][4] [4] +2 +--- error_log +group 1: false diff --git a/debian/modules/nginx-lua/t/038-match-o.t b/debian/modules/nginx-lua/t/038-match-o.t index 4ccd73a..628e27f 100644 --- a/debian/modules/nginx-lua/t/038-match-o.t +++ b/debian/modules/nginx-lua/t/038-match-o.t @@ -384,7 +384,7 @@ error: pcre_compile() failed: missing ) in "(abc" GET /re --- response_body hello -nil +false hello @@ -716,7 +716,7 @@ hello-1234 -=== TEST 33: named captures are nil +=== TEST 33: named captures are false --- config location /re { content_by_lua ' @@ -736,8 +736,8 @@ hello-1234 GET /re --- response_body hello -nil +false hello -nil -nil +false +false diff --git a/debian/modules/nginx-lua/t/043-shdict.t b/debian/modules/nginx-lua/t/043-shdict.t index 4c4d121..91a4196 100644 --- a/debian/modules/nginx-lua/t/043-shdict.t +++ b/debian/modules/nginx-lua/t/043-shdict.t @@ -2429,3 +2429,22 @@ nil nil --- no_error_log [error] + + + +=== TEST 92: invalid expire time +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua ' + local dogs = ngx.shared.dogs + dogs:set("foo", 32, -1) + '; + } +--- request +GET /test +--- response_body_like: 500 Internal Server Error +--- error_code: 500 +--- error_log +bad "exptime" argument diff --git a/debian/modules/nginx-lua/t/044-req-body.t b/debian/modules/nginx-lua/t/044-req-body.t index f0d0a4d..1c1be40 100644 --- a/debian/modules/nginx-lua/t/044-req-body.t +++ b/debian/modules/nginx-lua/t/044-req-body.t @@ -7,7 +7,7 @@ log_level('warn'); repeat_each(2); -plan tests => repeat_each() * (blocks() * 4 + 51); +plan tests => repeat_each() * (blocks() * 4 + 52 ); #no_diff(); no_long_string(); @@ -1606,3 +1606,27 @@ hiya, world"] --- no_error_log [error] [alert] + + + +=== TEST 49: get body data at log phase +--- config + location = /test { + content_by_lua_block { + ngx.req.read_body() + ngx.say(ngx.req.get_body_data()) + } + log_by_lua_block { + ngx.log(ngx.WARN, "request body:", ngx.req.get_body_data()) + } + } +--- request +POST /test +hello, world +--- response_body +hello, world +--- error_log +request body:hello, world +--- no_error_log +[error] +[alert] diff --git a/debian/modules/nginx-lua/t/048-match-dfa.t b/debian/modules/nginx-lua/t/048-match-dfa.t index 8350a73..8a0a328 100644 --- a/debian/modules/nginx-lua/t/048-match-dfa.t +++ b/debian/modules/nginx-lua/t/048-match-dfa.t @@ -23,6 +23,8 @@ __DATA__ m = ngx.re.match("hello", "(he|hell)", "d") if m then ngx.say(m[0]) + ngx.say(m[1]) + ngx.say(m[2]) else ngx.say("not matched!") end @@ -32,10 +34,35 @@ __DATA__ GET /re --- response_body hell +nil +nil -=== TEST 2: matched with d + j +=== TEST 2: matched with d + o +--- config + location /re { + content_by_lua ' + m = ngx.re.match("hello", "(he|hell)", "do") + if m then + ngx.say(m[0]) + ngx.say(m[1]) + ngx.say(m[2]) + else + ngx.say("not matched!") + end + '; + } +--- request + GET /re +--- response_body +hell +nil +nil + + + +=== TEST 3: matched with d + j --- config location /re { content_by_lua ' @@ -54,7 +81,7 @@ hell -=== TEST 3: not matched with j +=== TEST 4: not matched with j --- config location /re { content_by_lua ' @@ -73,7 +100,7 @@ not matched! -=== TEST 4: matched with do +=== TEST 5: matched with do --- config location /re { content_by_lua ' @@ -96,7 +123,7 @@ nil -=== TEST 5: not matched with do +=== TEST 6: not matched with do --- config location /re { content_by_lua ' @@ -115,7 +142,7 @@ not matched! -=== TEST 6: UTF-8 mode without UTF-8 sequence checks +=== TEST 7: UTF-8 mode without UTF-8 sequence checks --- config location /re { content_by_lua ' @@ -149,7 +176,7 @@ exec opts: 2000 -=== TEST 7: UTF-8 mode with UTF-8 sequence checks +=== TEST 8: UTF-8 mode with UTF-8 sequence checks --- config location /re { content_by_lua ' diff --git a/debian/modules/nginx-lua/t/050-gmatch-dfa.t b/debian/modules/nginx-lua/t/050-gmatch-dfa.t index c6b87e1..d2ac2bc 100644 --- a/debian/modules/nginx-lua/t/050-gmatch-dfa.t +++ b/debian/modules/nginx-lua/t/050-gmatch-dfa.t @@ -23,6 +23,7 @@ __DATA__ for m in ngx.re.gmatch("hello, halo", "h[a-z]|h[a-z][a-z]", "d") do if m then ngx.say(m[0]) + ngx.say(m[1]) else ngx.say("not matched: ", m) end @@ -33,7 +34,9 @@ __DATA__ GET /re --- response_body hel +nil hal +nil @@ -286,3 +289,50 @@ exec opts: 0 --- no_error_log [error] + + +=== TEST 13: gmatched with submatch captures +--- config + location /re { + content_by_lua ' + for m in ngx.re.gmatch("hello", "(he|hell)", "d") do + if m then + ngx.say(m[0]) + ngx.say(m[1]) + ngx.say(m[2]) + else + ngx.say("not matched!") + end + end + '; + } +--- request + GET /re +--- response_body +hell +nil +nil + + + +=== TEST 14: gmatched with submatch captures (compile once) +--- config + location /re { + content_by_lua ' + for m in ngx.re.gmatch("hello", "(he|hell)", "od") do + if m then + ngx.say(m[0]) + ngx.say(m[1]) + ngx.say(m[2]) + else + ngx.say("not matched!") + end + end + '; + } +--- request + GET /re +--- response_body +hell +nil +nil diff --git a/debian/modules/nginx-lua/t/052-sub-dfa.t b/debian/modules/nginx-lua/t/052-sub-dfa.t index f4de4d2..254913b 100644 --- a/debian/modules/nginx-lua/t/052-sub-dfa.t +++ b/debian/modules/nginx-lua/t/052-sub-dfa.t @@ -8,7 +8,7 @@ use Test::Nginx::Socket::Lua; repeat_each(2); -plan tests => repeat_each() * (blocks() * 2 + 6); +plan tests => repeat_each() * (blocks() * 2 + 8); #no_diff(); no_long_string(); @@ -198,3 +198,38 @@ s: a好 --- no_error_log [error] + + +=== TEST 9: sub with d +--- config + location /re { + content_by_lua ' + ngx.say(ngx.re.sub("hello", "(he|hell)", function (m) ngx.say(m[0]) ngx.say(m[1]) return "x" end, "d")) + '; + } +--- request + GET /re +--- response_body +hell +nil +xo1 +--- no_error_log +[error] + + + +=== TEST 10: sub with d + o +--- config + location /re { + content_by_lua ' + ngx.say(ngx.re.sub("hello", "(he|hell)", function (m) ngx.say(m[0]) ngx.say(m[1]) return "x" end, "do")) + '; + } +--- request + GET /re +--- response_body +hell +nil +xo1 +--- no_error_log +[error] diff --git a/debian/modules/nginx-lua/t/054-gsub-dfa.t b/debian/modules/nginx-lua/t/054-gsub-dfa.t index 9c471a9..937aa1c 100644 --- a/debian/modules/nginx-lua/t/054-gsub-dfa.t +++ b/debian/modules/nginx-lua/t/054-gsub-dfa.t @@ -8,7 +8,7 @@ use Test::Nginx::Socket::Lua; repeat_each(2); -plan tests => repeat_each() * (blocks() * 2 + 5); +plan tests => repeat_each() * (blocks() * 2 + 7); #no_diff(); no_long_string(); @@ -199,3 +199,38 @@ s: aa --- no_error_log [error] + + +=== TEST 9: gsub with d +--- config + location /re { + content_by_lua ' + ngx.say(ngx.re.gsub("hello", "(he|hell)", function (m) ngx.say(m[0]) ngx.say(m[1]) return "x" end, "d")) + '; + } +--- request + GET /re +--- response_body +hell +nil +xo1 +--- no_error_log +[error] + + + +=== TEST 10: gsub with d + o +--- config + location /re { + content_by_lua ' + ngx.say(ngx.re.gsub("hello", "(he|hell)", function (m) ngx.say(m[0]) ngx.say(m[1]) return "x" end, "do")) + '; + } +--- request + GET /re +--- response_body +hell +nil +xo1 +--- no_error_log +[error] diff --git a/debian/modules/nginx-lua/t/058-tcp-socket.t b/debian/modules/nginx-lua/t/058-tcp-socket.t index 3368589..b9e4175 100644 --- a/debian/modules/nginx-lua/t/058-tcp-socket.t +++ b/debian/modules/nginx-lua/t/058-tcp-socket.t @@ -432,7 +432,7 @@ attempt to send data on a closed socket --- request GET /t --- response_body_like -^failed to connect: blah-blah-not-found\.agentzh\.org could not be resolved(?: \(\d+: Operation timed out\))? +^failed to connect: blah-blah-not-found\.agentzh\.org could not be resolved(?: \(\d+: (?:Operation timed out|Host not found)\))? connected: nil failed to send request: closed$ --- error_log diff --git a/debian/modules/nginx-lua/t/059-unix-socket.t b/debian/modules/nginx-lua/t/059-unix-socket.t index 9e9e6df..b06ba6e 100644 --- a/debian/modules/nginx-lua/t/059-unix-socket.t +++ b/debian/modules/nginx-lua/t/059-unix-socket.t @@ -134,3 +134,70 @@ received: foo failed to receive a line: closed close: 1 nil + + +=== TEST 4: ngx.socket.stream +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock; + default_type 'text/plain'; + + server_tokens off; + location /foo { + content_by_lua_block { ngx.say("foo") } + more_clear_headers Date; + } + } +--- config + location /test { + content_by_lua_block { + local sock = ngx.socket.stream() + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local req = "GET /foo HTTP/1.0\r\nHost: localhost\r\nConnection: close\r\n\r\n" + -- req = "OK" + + local bytes, err = sock:send(req) + if not bytes then + ngx.say("failed to send request: ", err) + return + end + + ngx.say("request sent: ", bytes) + + while true do + print("calling receive") + local line, err = sock:receive() + if line then + ngx.say("received: ", line) + + else + ngx.say("failed to receive a line: ", err) + break + end + end + + ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + } + } +--- request + GET /test +--- response_body +connected: 1 +request sent: 57 +received: HTTP/1.1 200 OK +received: Server: nginx +received: Content-Type: text/plain +received: Content-Length: 4 +received: Connection: close +received: +received: foo +failed to receive a line: closed +close: 1 nil diff --git a/debian/modules/nginx-lua/t/062-count.t b/debian/modules/nginx-lua/t/062-count.t index c94491c..a24611c 100644 --- a/debian/modules/nginx-lua/t/062-count.t +++ b/debian/modules/nginx-lua/t/062-count.t @@ -212,7 +212,7 @@ n = 2 --- request GET /test --- response_body -n = 3 +n = 4 --- no_error_log [error] @@ -343,7 +343,7 @@ n = 3 --- request GET /test --- response_body -n = 5 +n = 6 --- no_error_log [error] diff --git a/debian/modules/nginx-lua/t/081-bytecode.t b/debian/modules/nginx-lua/t/081-bytecode.t index 93139e2..cb50e94 100644 --- a/debian/modules/nginx-lua/t/081-bytecode.t +++ b/debian/modules/nginx-lua/t/081-bytecode.t @@ -314,3 +314,60 @@ ngx.status = 201 ngx.say("hello from Lua!") [error] --- error_code: 201 + + +=== TEST 9: bytecode (not stripped) +--- config + location = /t { + content_by_lua_block { + local f = assert(loadstring("a = a and a + 1 or 1 ngx.say('a = ', a)", "=code")) + local bc = string.dump(f) + local f = assert(io.open("t/servroot/html/a.luac", "w")) + f:write(bc) + f:close() + } + } + + location = /t2 { + content_by_lua_file html/a.luac; + } + + location = /main { + echo_location /t; + echo_location /t2; + } +--- request +GET /main +--- response_body +a = 1 +--- no_error_log +[error] + + + +=== TEST 10: bytecode (stripped) +--- config + location = /t { + content_by_lua_block { + local f = assert(loadstring("a = a and a + 1 or 1 ngx.say('a = ', a)", "=code")) + local bc = string.dump(f, true) + local f = assert(io.open("t/servroot/html/a.luac", "w")) + f:write(bc) + f:close() + } + } + + location = /t2 { + content_by_lua_file html/a.luac; + } + + location = /main { + echo_location /t; + echo_location /t2; + } +--- request +GET /main +--- response_body +a = 1 +--- no_error_log +[error] diff --git a/debian/modules/nginx-lua/t/101-on-abort.t b/debian/modules/nginx-lua/t/101-on-abort.t index bb74204..81cec78 100644 --- a/debian/modules/nginx-lua/t/101-on-abort.t +++ b/debian/modules/nginx-lua/t/101-on-abort.t @@ -107,6 +107,7 @@ lua req cleanup delete thread 2 delete thread 1 +--- wait: 0.1 --- timeout: 0.2 --- abort --- ignore_response diff --git a/debian/modules/nginx-lua/t/106-timer.t b/debian/modules/nginx-lua/t/106-timer.t index 5cfc01b..d0f6f36 100644 --- a/debian/modules/nginx-lua/t/106-timer.t +++ b/debian/modules/nginx-lua/t/106-timer.t @@ -2141,7 +2141,6 @@ qr/\[lua\] content_by_lua\(nginx\.conf:\d+\):\d+: elapsed: 0\.0(?:4[4-9]|5[0-6]) end ngx.say("registered timer") '; - log_by_lua return; } --- request GET /t diff --git a/debian/modules/nginx-lua/t/114-config.t b/debian/modules/nginx-lua/t/114-config.t index e6d75fc..9d6680d 100644 --- a/debian/modules/nginx-lua/t/114-config.t +++ b/debian/modules/nginx-lua/t/114-config.t @@ -1,4 +1,5 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: + use Test::Nginx::Socket::Lua; #worker_connections(1014); @@ -30,3 +31,18 @@ GET /t --- no_error_log [error] + + +=== TEST 2: ngx.config.subystem +--- config + location /t { + content_by_lua ' + ngx.say("subsystem: ", ngx.config.subsystem) + '; + } +--- request +GET /t +--- response_body +subsystem: http +--- no_error_log +[error] diff --git a/debian/modules/nginx-lua/t/116-raw-req-socket.t b/debian/modules/nginx-lua/t/116-raw-req-socket.t index c2ff8f7..6518f0e 100644 --- a/debian/modules/nginx-lua/t/116-raw-req-socket.t +++ b/debian/modules/nginx-lua/t/116-raw-req-socket.t @@ -783,7 +783,6 @@ server: failed to get raw req socket: pending request body reading in some other === TEST 15: read chunked request body with raw req socket ---- main_config --- config location = /t { content_by_lua ' diff --git a/debian/modules/nginx-lua/t/138-balancer.t b/debian/modules/nginx-lua/t/138-balancer.t index 076465a..e44cf8e 100644 --- a/debian/modules/nginx-lua/t/138-balancer.t +++ b/debian/modules/nginx-lua/t/138-balancer.t @@ -302,3 +302,106 @@ I am in phase balancer qr{\[crit\] .*? connect\(\) to 0\.0\.0\.1:80 failed .*?, upstream: "http://0\.0\.0\.1:80/t"} --- no_error_log [error] + + + +=== TEST 12: code cache off +--- http_config + lua_package_path "t/servroot/html/?.lua;;"; + + lua_code_cache off; + + upstream backend { + server 127.0.0.1:$TEST_NGINX_SERVER_PORT; + balancer_by_lua_block { + require("test") + } + } +--- config + location = /t { + echo_location /main; + echo_location /update; + echo_location /main; + } + + location = /update { + content_by_lua_block { + -- os.execute("(echo HERE; pwd) > /dev/stderr") + local f = assert(io.open("t/servroot/html/test.lua", "w")) + f:write("print('me: ', 101)") + f:close() + ngx.say("updated") + } + } + + location = /main { + proxy_pass http://backend/back; + } + + location = /back { + echo ok; + } +--- request + GET /t +--- user_files +>>> test.lua +print("me: ", 32) +return {} +--- response_body +ok +updated +ok +--- grep_error_log eval: qr/\bme: \w+/ +--- grep_error_log_out +me: 32 +me: 101 +--- no_error_log +[error] + + + +=== TEST 13: lua subrequests +--- http_config + lua_package_path "t/servroot/html/?.lua;;"; + + lua_code_cache off; + + upstream backend { + server 127.0.0.1:$TEST_NGINX_SERVER_PORT; + balancer_by_lua_block { + print("ctx counter: ", ngx.ctx.count) + if not ngx.ctx.count then + ngx.ctx.count = 1 + else + ngx.ctx.count = ngx.ctx.count + 1 + end + } + } +--- config + location = /t { + content_by_lua_block { + local res = ngx.location.capture("/main") + ngx.print(res.body) + res = ngx.location.capture("/main") + ngx.print(res.body) + } + } + + location = /main { + proxy_pass http://backend/back; + } + + location = /back { + echo ok; + } +--- request + GET /t +--- response_body +ok +ok +--- grep_error_log eval: qr/\bctx counter: \w+/ +--- grep_error_log_out +ctx counter: nil +ctx counter: nil +--- no_error_log +[error] diff --git a/debian/modules/nginx-lua/t/140-ssl-c-api.t b/debian/modules/nginx-lua/t/140-ssl-c-api.t new file mode 100644 index 0000000..9812de2 --- /dev/null +++ b/debian/modules/nginx-lua/t/140-ssl-c-api.t @@ -0,0 +1,363 @@ +# vim:set ft= ts=4 sw=4 et fdm=marker: + +use Test::Nginx::Socket::Lua; + +repeat_each(3); + +# All these tests need to have new openssl +my $NginxBinary = $ENV{'TEST_NGINX_BINARY'} || 'nginx'; +my $openssl_version = eval { `$NginxBinary -V 2>&1` }; + +if ($openssl_version =~ m/built with OpenSSL (0|1\.0\.(?:0|1[^\d]|2[a-d]).*)/) { + plan(skip_all => "too old OpenSSL, need 1.0.2e, was $1"); +} else { + plan tests => repeat_each() * (blocks() * 5); +} + +$ENV{TEST_NGINX_HTML_DIR} ||= html_dir(); + +#log_level 'warn'; +log_level 'debug'; + +no_long_string(); +#no_diff(); + +run_tests(); + +__DATA__ + +=== TEST 1: simple cert + private key +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + + ssl_certificate_by_lua_block { + collectgarbage() + + local ffi = require "ffi" + + ffi.cdef[[ + int ngx_http_lua_ffi_cert_pem_to_der(const unsigned char *pem, + size_t pem_len, unsigned char *der, char **err); + + int ngx_http_lua_ffi_priv_key_pem_to_der(const unsigned char *pem, + size_t pem_len, unsigned char *der, char **err); + + int ngx_http_lua_ffi_ssl_set_der_certificate(void *r, + const char *data, size_t len, char **err); + + int ngx_http_lua_ffi_ssl_set_der_private_key(void *r, + const char *data, size_t len, char **err); + + int ngx_http_lua_ffi_ssl_clear_certs(void *r, char **err); + ]] + + local errmsg = ffi.new("char *[1]") + + local r = getfenv(0).__ngx_req + if not r then + ngx.log(ngx.ERR, "no request found") + return + end + + ffi.C.ngx_http_lua_ffi_ssl_clear_certs(r, errmsg) + + local f = assert(io.open("t/cert/test.crt", "rb")) + local cert = f:read("*all") + f:close() + + local out = ffi.new("char [?]", #cert) + + local rc = ffi.C.ngx_http_lua_ffi_cert_pem_to_der(cert, #cert, out, errmsg) + if rc < 1 then + ngx.log(ngx.ERR, "failed to parse PEM cert: ", + ffi.string(errmsg[0])) + return + end + + local cert_der = ffi.string(out, rc) + + local rc = ffi.C.ngx_http_lua_ffi_ssl_set_der_certificate(r, cert_der, #cert_der, errmsg) + if rc ~= 0 then + ngx.log(ngx.ERR, "failed to set DER cert: ", + ffi.string(errmsg[0])) + return + end + + f = assert(io.open("t/cert/test.key", "rb")) + local pkey = f:read("*all") + f:close() + + out = ffi.new("char [?]", #pkey) + + local rc = ffi.C.ngx_http_lua_ffi_priv_key_pem_to_der(pkey, #pkey, out, errmsg) + if rc < 1 then + ngx.log(ngx.ERR, "failed to parse PEM priv key: ", + ffi.string(errmsg[0])) + return + end + + local pkey_der = ffi.string(out, rc) + + local rc = ffi.C.ngx_http_lua_ffi_ssl_set_der_private_key(r, pkey_der, #pkey_der, errmsg) + if rc ~= 0 then + ngx.log(ngx.ERR, "failed to set DER priv key: ", + ffi.string(errmsg[0])) + return + end + } + + ssl_certificate ../../cert/test2.crt; + ssl_certificate_key ../../cert/test2.key; + + server_tokens off; + location /foo { + default_type 'text/plain'; + content_by_lua_block { ngx.status = 201 ngx.say("foo") ngx.exit(201) } + more_clear_headers Date; + } + } +--- config + server_tokens off; + lua_ssl_trusted_certificate ../../cert/test.crt; + + location /t { + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(2000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(nil, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + local req = "GET /foo HTTP/1.0\r\nHost: test.com\r\nConnection: close\r\n\r\n" + local bytes, err = sock:send(req) + if not bytes then + ngx.say("failed to send http request: ", err) + return + end + + ngx.say("sent http request: ", bytes, " bytes.") + + while true do + local line, err = sock:receive() + if not line then + -- ngx.say("failed to recieve response status line: ", err) + break + end + + ngx.say("received: ", line) + end + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: userdata +sent http request: 56 bytes. +received: HTTP/1.1 201 Created +received: Server: nginx +received: Content-Type: text/plain +received: Content-Length: 4 +received: Connection: close +received: +received: foo +close: 1 nil + +--- error_log +lua ssl server name: "test.com" + +--- no_error_log +[error] +[alert] + + + +=== TEST 2: ECDSA cert + private key +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + + ssl_certificate_by_lua_block { + collectgarbage() + + local ffi = require "ffi" + + ffi.cdef[[ + int ngx_http_lua_ffi_cert_pem_to_der(const unsigned char *pem, + size_t pem_len, unsigned char *der, char **err); + + int ngx_http_lua_ffi_priv_key_pem_to_der(const unsigned char *pem, + size_t pem_len, unsigned char *der, char **err); + + int ngx_http_lua_ffi_ssl_set_der_certificate(void *r, + const char *data, size_t len, char **err); + + int ngx_http_lua_ffi_ssl_set_der_private_key(void *r, + const char *data, size_t len, char **err); + + int ngx_http_lua_ffi_ssl_clear_certs(void *r, char **err); + ]] + + local errmsg = ffi.new("char *[1]") + + local r = getfenv(0).__ngx_req + if not r then + ngx.log(ngx.ERR, "no request found") + return + end + + ffi.C.ngx_http_lua_ffi_ssl_clear_certs(r, errmsg) + + local f = assert(io.open("t/cert/test_ecdsa.crt", "rb")) + local cert = f:read("*all") + f:close() + + local out = ffi.new("char [?]", #cert) + + local rc = ffi.C.ngx_http_lua_ffi_cert_pem_to_der(cert, #cert, out, errmsg) + if rc < 1 then + ngx.log(ngx.ERR, "failed to parse PEM cert: ", + ffi.string(errmsg[0])) + return + end + + local cert_der = ffi.string(out, rc) + + local rc = ffi.C.ngx_http_lua_ffi_ssl_set_der_certificate(r, cert_der, #cert_der, errmsg) + if rc ~= 0 then + ngx.log(ngx.ERR, "failed to set DER cert: ", + ffi.string(errmsg[0])) + return + end + + f = assert(io.open("t/cert/test_ecdsa.key", "rb")) + local pkey = f:read("*all") + f:close() + + out = ffi.new("char [?]", #pkey) + + local rc = ffi.C.ngx_http_lua_ffi_priv_key_pem_to_der(pkey, #pkey, out, errmsg) + if rc < 1 then + ngx.log(ngx.ERR, "failed to parse PEM priv key: ", + ffi.string(errmsg[0])) + return + end + + local pkey_der = ffi.string(out, rc) + + local rc = ffi.C.ngx_http_lua_ffi_ssl_set_der_private_key(r, pkey_der, #pkey_der, errmsg) + if rc ~= 0 then + ngx.log(ngx.ERR, "failed to set DER priv key: ", + ffi.string(errmsg[0])) + return + end + } + + ssl_certificate ../../cert/test2.crt; + ssl_certificate_key ../../cert/test2.key; + + server_tokens off; + location /foo { + default_type 'text/plain'; + content_by_lua_block { ngx.status = 201 ngx.say("foo") ngx.exit(201) } + more_clear_headers Date; + } + } +--- config + server_tokens off; + lua_ssl_trusted_certificate ../../cert/test_ecdsa.crt; + + location /t { + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(2000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(nil, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + local req = "GET /foo HTTP/1.0\r\nHost: test.com\r\nConnection: close\r\n\r\n" + local bytes, err = sock:send(req) + if not bytes then + ngx.say("failed to send http request: ", err) + return + end + + ngx.say("sent http request: ", bytes, " bytes.") + + while true do + local line, err = sock:receive() + if not line then + -- ngx.say("failed to recieve response status line: ", err) + break + end + + ngx.say("received: ", line) + end + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: userdata +sent http request: 56 bytes. +received: HTTP/1.1 201 Created +received: Server: nginx +received: Content-Type: text/plain +received: Content-Length: 4 +received: Connection: close +received: +received: foo +close: 1 nil + +--- error_log +lua ssl server name: "test.com" + +--- no_error_log +[error] +[alert] diff --git a/debian/modules/nginx-lua/t/cert/test2.crt b/debian/modules/nginx-lua/t/cert/test2.crt new file mode 100644 index 0000000..edc3b0d --- /dev/null +++ b/debian/modules/nginx-lua/t/cert/test2.crt @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIIChzCCAfACCQDjCkJpJUtZmjANBgkqhkiG9w0BAQUFADCBhjELMAkGA1UEBhMC +VVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28x +EjAQBgNVBAoMCU9wZW5SZXN0eTESMBAGA1UEAwwJdGVzdDIuY29tMSIwIAYJKoZI +hvcNAQkBFhNvcGVucmVzdHlAZ21haWwuY29tMCAXDTE0MDkxMzAwMTgxMFoYDzIx +MTQwODIwMDAxODEwWjCBhjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3Ju +aWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xEjAQBgNVBAoMCU9wZW5SZXN0eTES +MBAGA1UEAwwJdGVzdDIuY29tMSIwIAYJKoZIhvcNAQkBFhNvcGVucmVzdHlAZ21h +aWwuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDy+OVI2u5NBOeB2Cyz +Gnwy9b7Ao4CSi05XtUxh2IoVdzYZz6c4PFb9C1ad52LDdRStiQT5A7+RKLj6Kr7f +JrKFziJxMy4g4Kdn9G659vE7CWu/UAVjRUtc+mTBAEfjdbumizmHLG7DmnNhGl3R +NGiVNLsUInSMGfUlJRzZJXhI4QIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAEMmRvyN +N7uE24Tc6TR19JadNHK8g3YGktRoXWiqd/y0HY4NRPgvnK/nX7CY/wXa1j+uDO8K +e6/Ldm5RZrjtvfHJmTSAu8zkqTJz8bqRDH7kzL5Ni2Ky2x8r9dtB0ImpOiSlwvZN +snMvbrxEdwBiqlC9prV2f9aG+ACo1KnPL0j6 +-----END CERTIFICATE----- diff --git a/debian/modules/nginx-lua/t/cert/test2.key b/debian/modules/nginx-lua/t/cert/test2.key new file mode 100644 index 0000000..82ce6ce --- /dev/null +++ b/debian/modules/nginx-lua/t/cert/test2.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQDy+OVI2u5NBOeB2CyzGnwy9b7Ao4CSi05XtUxh2IoVdzYZz6c4 +PFb9C1ad52LDdRStiQT5A7+RKLj6Kr7fJrKFziJxMy4g4Kdn9G659vE7CWu/UAVj +RUtc+mTBAEfjdbumizmHLG7DmnNhGl3RNGiVNLsUInSMGfUlJRzZJXhI4QIDAQAB +AoGAEqBB83PVENJvbOTFiHVfUAjGtr3R/Wnwd4jOcjHHZB3fZ9sjVoxJntxfp3s1 +dwZir2rxlqVS6i3VAFiGiVTOGo2Vvzhw2J7f58twCECmnLb2f863AkGEYe4dAndD +GHGD0WI0CBMD1sT18YCj561o0Wol5deWH0gM9pr2N3HkeIECQQD6hUKFlFhrpaHP +WNJsl6BxgE6pB5kxLcMcpIQ7P+kHUvtyvCJl5QZJqPrpPGjRsAI5Ph92rpsp/zDp +/IZNWGVjAkEA+Ele31Rt+XbV32MrLKZgBDBk+Pzss5LTn9fZ5v1k/7hrMk2VVWvk +AD6n5QiGe/g59woANpPb1T9l956SBf0d6wJABTXOS17pc9uvANP1FGMW6CVl/Wf2 +DKrJ+weE5IKQwyE7r4gwIvRfbBrClSU3fNzvPueG2f4JphbzmnoxBNzIxwJAYivY +mGNwzHehXx99/byXMHDWK+EN0n8WsBgP75Z3rekEcbJdfpYXY8Via1vwmOnwOW65 +4NqbzHix37PSNw37GwJBALxaGNpREO2Tk+oWOvsD2QyviMVae3mXAJHc6nLVdKDM +q0YvDT6VdeNYYFTkAuzJacsVXOpn6AnUMFj0OBedMhc= +-----END RSA PRIVATE KEY----- diff --git a/debian/modules/nginx-lua/t/cert/test_ecdsa.crt b/debian/modules/nginx-lua/t/cert/test_ecdsa.crt new file mode 100644 index 0000000..b3e1e9f --- /dev/null +++ b/debian/modules/nginx-lua/t/cert/test_ecdsa.crt @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBtDCCAVoCCQD0QJnL8zpA0jAKBggqhkjOPQQDAjBhMQswCQYDVQQGEwJVUzET +MBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzESMBAG +A1UECgwJT3BlblJlc3R5MREwDwYDVQQDDAh0ZXN0LmNvbTAgFw0xNTA3MTcyMTUx +NDFaGA8yMTE1MDYyMzIxNTE0MVowYTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNh +bGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xEjAQBgNVBAoMCU9wZW5S +ZXN0eTERMA8GA1UEAwwIdGVzdC5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC +AAT/OtGmlIlbtvvJ3OP0dm5lyEMCrMnpDTDjwBPnUZ2f+16LCmNsdtEJ0r0Sd4GM +o4Lss2JpwzPy2SLGEj3KwGKSMAoGCCqGSM49BAMCA0gAMEUCIQDbNwDkq1FiqcRD +XdbP1MPAc33N2IK9EDIfMgJ0nTL82wIgNZiL4xvCQe9UA0zC+JqHLnVCQHYAM9kI +BbvzNrt0hEM= +-----END CERTIFICATE----- diff --git a/debian/modules/nginx-lua/t/cert/test_ecdsa.key b/debian/modules/nginx-lua/t/cert/test_ecdsa.key new file mode 100644 index 0000000..46eb72c --- /dev/null +++ b/debian/modules/nginx-lua/t/cert/test_ecdsa.key @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg0vwBPGgv1hE6RnQo +3imyoceR+5dLsKegodOlBwnWtbuhRANCAAT/OtGmlIlbtvvJ3OP0dm5lyEMCrMnp +DTDjwBPnUZ2f+16LCmNsdtEJ0r0Sd4GMo4Lss2JpwzPy2SLGEj3KwGKS +-----END PRIVATE KEY----- diff --git a/debian/modules/nginx-lua/util/build2.sh b/debian/modules/nginx-lua/util/build.sh similarity index 100% rename from debian/modules/nginx-lua/util/build2.sh rename to debian/modules/nginx-lua/util/build.sh From fd1a40a6f89e94a118ed1fe550d330c6ccce9606 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Fri, 12 Feb 2016 14:47:59 +0200 Subject: [PATCH 032/600] Update Vcs field with secure links Fixes vcs-field-uses-insecure-uri https://lintian.debian.org/tags/vcs-field-uses-insecure-uri.html --- debian/control | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/control b/debian/control index 7c60e5f..d96788e 100644 --- a/debian/control +++ b/debian/control @@ -26,8 +26,8 @@ Build-Depends: autotools-dev, zlib1g-dev Standards-Version: 3.9.6.0 Homepage: http://nginx.net -Vcs-Git: git://anonscm.debian.org/collab-maint/nginx.git -Vcs-Browser: http://anonscm.debian.org/gitweb/?p=collab-maint/nginx.git;a=summary +Vcs-Git: https://anonscm.debian.org/cgit/collab-maint/nginx.git +Vcs-Browser: https://anonscm.debian.org/cgit/collab-maint/nginx.git Package: nginx Architecture: all From 7b00376f31ef3b908921f594ef14fa4d61864012 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Tue, 29 Mar 2016 13:20:16 +0300 Subject: [PATCH 033/600] Bump Standards-Version to 3.9.7.0 (no changes needed) --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index d96788e..f43fe4f 100644 --- a/debian/control +++ b/debian/control @@ -24,7 +24,7 @@ Build-Depends: autotools-dev, libxslt1-dev, po-debconf, zlib1g-dev -Standards-Version: 3.9.6.0 +Standards-Version: 3.9.7.0 Homepage: http://nginx.net Vcs-Git: https://anonscm.debian.org/cgit/collab-maint/nginx.git Vcs-Browser: https://anonscm.debian.org/cgit/collab-maint/nginx.git From a50cd439eb4f8d5ad8c2519e0914d00b49a5ee23 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Mon, 28 Mar 2016 13:38:53 +0300 Subject: [PATCH 034/600] Add documentation option to systemd unit Fixes systemd-service-file-missing-documentation-key lintian check. --- debian/nginx-common.nginx.service | 1 + 1 file changed, 1 insertion(+) diff --git a/debian/nginx-common.nginx.service b/debian/nginx-common.nginx.service index 0da034d..a909641 100644 --- a/debian/nginx-common.nginx.service +++ b/debian/nginx-common.nginx.service @@ -12,6 +12,7 @@ # [Unit] Description=A high performance web server and a reverse proxy server +Documentation=man:nginx(8) After=network.target [Service] From 44b30c100a3bcf9b4b6a89910aa4d989a5e1c46b Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Fri, 12 Feb 2016 14:27:46 +0200 Subject: [PATCH 035/600] Disable PIE hardening flags for now, it breaks dynamic libraries --- debian/rules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/rules b/debian/rules index 1cdef59..c18af76 100755 --- a/debian/rules +++ b/debian/rules @@ -1,7 +1,7 @@ #!/usr/bin/make -f export DH_VERBOSE=1 -export DEB_BUILD_MAINT_OPTIONS=hardening=+all +export DEB_BUILD_MAINT_OPTIONS=hardening=+all,-pie debian_cflags:=$(shell dpkg-buildflags --get CFLAGS) $(shell dpkg-buildflags --get CPPFLAGS) debian_ldflags:=$(shell dpkg-buildflags --get LDFLAGS) From 7a5fa94b9d190bedabcdada1cdd6ca91fb5e0ef3 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Wed, 23 Mar 2016 16:36:44 +0200 Subject: [PATCH 036/600] Setup modules-{enabled,available} directories Modules have to be declared with top-level includes --- debian/conf/nginx.conf | 1 + debian/nginx-common.dirs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/debian/conf/nginx.conf b/debian/conf/nginx.conf index 01a4a21..6e57ea9 100644 --- a/debian/conf/nginx.conf +++ b/debian/conf/nginx.conf @@ -1,6 +1,7 @@ user www-data; worker_processes auto; pid /run/nginx.pid; +include /etc/nginx/modules-enabled/*.conf; events { worker_connections 768; diff --git a/debian/nginx-common.dirs b/debian/nginx-common.dirs index d75dabf..8ee01f5 100644 --- a/debian/nginx-common.dirs +++ b/debian/nginx-common.dirs @@ -1,6 +1,8 @@ etc/nginx etc/nginx/sites-available etc/nginx/sites-enabled +etc/nginx/modules-available +etc/nginx/modules-enabled etc/nginx/conf.d etc/ufw/applications.d usr/share/nginx From 916384bde3a24d93cf2434687520429ea6855d27 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Wed, 23 Mar 2016 16:43:07 +0200 Subject: [PATCH 037/600] Setup libnginx-mod packaging flow We introduce a dh_nginx helper script. For now dh_nginx will only be used in the nginx source but when are confident about it will ship it in a nginx-dev package. --- debian/autoscripts/postinst-nginx | 11 ++ debian/autoscripts/postrm-nginx | 11 ++ debian/autoscripts/prerm-nginx | 11 ++ debian/dh_nginx | 278 +++++++++++++++++++++++++++++ debian/libnginx-mod.nginx.skeleton | 13 ++ debian/nginx-common.links | 1 + debian/rules | 10 +- 7 files changed, 334 insertions(+), 1 deletion(-) create mode 100644 debian/autoscripts/postinst-nginx create mode 100644 debian/autoscripts/postrm-nginx create mode 100644 debian/autoscripts/prerm-nginx create mode 100755 debian/dh_nginx create mode 100755 debian/libnginx-mod.nginx.skeleton create mode 100644 debian/nginx-common.links diff --git a/debian/autoscripts/postinst-nginx b/debian/autoscripts/postinst-nginx new file mode 100644 index 0000000..565015b --- /dev/null +++ b/debian/autoscripts/postinst-nginx @@ -0,0 +1,11 @@ +for conf in #NAMES# ; do + # Symlink on fresh installations + if [ -z "$2" ]; then + ln -sf /usr/share/nginx/modules-available/$conf \ + /etc/nginx/modules-enabled/$conf + fi +done + +if [ -s /run/nginx.pid ]; then + nginx -s reload +fi diff --git a/debian/autoscripts/postrm-nginx b/debian/autoscripts/postrm-nginx new file mode 100644 index 0000000..60b0493 --- /dev/null +++ b/debian/autoscripts/postrm-nginx @@ -0,0 +1,11 @@ +if [ "$1" = "purge" ] ; then + for conf in #NAMES# ; do + if [ -e /etc/nginx/etc/nginx/modules-enabled/$conf ]; then + rm /etc/nginx/etc/nginx/modules-enabled/$conf + fi + done + + if [ -s /run/nginx.pid ]; then + nginx -s reload + fi +fi diff --git a/debian/autoscripts/prerm-nginx b/debian/autoscripts/prerm-nginx new file mode 100644 index 0000000..efeaae8 --- /dev/null +++ b/debian/autoscripts/prerm-nginx @@ -0,0 +1,11 @@ +if [ "$1" = "remove" ] || [ "$1" = "deconfigure" ] ; then + for conf in #NAMES# ; do + if [ -e /etc/nginx/etc/nginx/modules-enabled/$conf ]; then + rm /etc/nginx/etc/nginx/modules-enabled/$conf + fi + done + + if [ -s /run/nginx.pid ]; then + nginx -s reload + fi +fi diff --git a/debian/dh_nginx b/debian/dh_nginx new file mode 100755 index 0000000..26dedb2 --- /dev/null +++ b/debian/dh_nginx @@ -0,0 +1,278 @@ +#! /usr/bin/perl + +# dh_nginx - Nginx configuration helper +# Copyright (C) 2016 Christos Trochalakis +# +# This program is licensed under the terms of the GNU General +# Public License veserion 2+ +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +use strict; +use File::Find; +use Debian::Debhelper::Dh_Lib; + + +=head1 NAME + +dh_nginx - register configuration snippets to the nginx web server + +=cut + +sub nginx_depends +{ + return 'nginx-light (= ${binary:Version}) |nginx-full (= ${binary:Version}) | nginx-extras (= ${binary:Version})' +} + +sub nginx_api_installdir +{ + return "/usr/lib/nginx/modules/"; +} + +sub nginx_modules_conf_installdir +{ + return "usr/share/nginx/modules-available/" +} + +=head1 SYNOPSIS + +B [S>] [B<-n>|B<--noscripts>] + +=head1 DESCRIPTION + +B is a debhelper program that is responsible for correctly installing +Nginx configuration snippets and setting postinst, prerm and dependencies in +Nginx web server modules and web applications. + +It supports the following configuration types + +=over 4 + +=item * +Nginx modules + +=head1 INVOCATION + + %: + dh $@ --with nginx + +=head1 FILES + +=over 4 + +=item debian/I.nginx + +=item debian/nginx + +=back + +Lists files to be registered with the Nginx HTTP server. The file is +interpreted as line separated list of installation stanzas, where each entry +consists of whitespace separated values conforming to the file semantics below. + +=head2 FILE SEMANTICS + +Each line consists of a triple + +I I [I] + +where the values are interpreted as follows: + + +=head3 I + +Denotes the type of file to be installed. Recognized values are B for +Nginx modules. + +=head3 I + +Is interpreted as existing file name within the source package. No path +expansion is effectuated. Just like L, B can not +rename files. + +=head3 I + +Is inrerpreted as optional arguments if any, currently not used. + +=head2 MODULES + +Modules are handled specially and are determined by the B type. Modules must +have a I<.conf> suffix. In that case the file is interpreted as module load +file and is installed to I. If the file is ending +with a I<.so> suffix it is interpreted as actual module shared object and is +installed to the Nginx module directory. Moreover, if a I<.load> file is +installed the configuration is activated in the maintainer script at +installation time. + +=head1 OPTIONS + +=over 4 + +=item B<-e>, B<--noenable> + +Install maintainer scripts accordingly, but do not enable the scripts or +configuration by default. + +=item B<-n>, B<--noscripts> + +Do not modify F/F/F maintainer scripts. + + +=back + +=head1 NOTES + +Note that this command is not idempotent. L should be called +between invocations of this command. Otherwise, it may cause multiple +instances of the same text to be added to maintainer scripts. + +=head1 AUTHOR + +This manual and L was written by Christos Trochalakis. +dh_nginx is heavily influnced by dh_apache2 written by Arno Toell +. + +=cut + + +## +## main code starts here +## + +init(options => { + "e|noenable" => \$dh{NOENABLE}, +}); + +foreach my $package ((@{$dh{DOPACKAGES}})) +{ + my %PACKAGE_TYPE = ( + has_a_module => [], + ); + + my $file = pkgfile($package, "nginx"); + my $tmp = tmpdir($package); + + my @files_to_register = filedoublearray($file, ".") if $file; + foreach my $line (@files_to_register) + { + my $type = lc(shift @{$line}) if $line->[0]; + my $source = shift @{$line} if $line->[0]; + my @arguments = map {"$_ "} @{$line}; + + $type = "modules" if $type eq "mod"; + my $installdir = $tmp . "/" . nginx_modules_conf_installdir(); + + verbose_print("$type -- $source -- @arguments\n\n"); + + if ($type eq "modules") + { + my $basesource = basename($source); + + if ($type eq "modules") + { + if ($basesource =~ m/\.conf$/) + { + my $enablename = $basesource; + push @{$PACKAGE_TYPE{'has_a_module'}}, $enablename; + verbose_print("Installing module configuration $enablename into $installdir\n"); + } + elsif ($basesource =~ m/\.so$/) + { + my $modinstalldir = $tmp . "/" . nginx_api_installdir(); + verbose_print("Installing module binary $source into $modinstalldir\n"); + if (! -d $modinstalldir) + { + complex_doit("mkdir","-p", $modinstalldir); + complex_doit("chmod","755","$modinstalldir"); + } + complex_doit("cp", $source, $modinstalldir); + next; + } + + # TODO + error("module: \"$basesource\" needs .conf, .so or .load suffix") if $basesource !~ m/\.(conf|so)/; + } + + if (! -d $installdir) + { + complex_doit("mkdir","-p",$installdir); + complex_doit("chmod","755","$installdir"); + } + complex_doit("cp",$source,$installdir); + complex_doit("chmod","644","$installdir/$basesource"); + + } + else + { + error("Unknown parameter: $type\n"); + } + + } + + my @postinst_autoscripts; + + if ($#{$PACKAGE_TYPE{'has_a_module'}} >= 0) + { + if ($package !~ m/libnginx-mod-\w+?/) + { + warning("Package $package appears to be an Nginx module. It should comply to the package naming scheme libnginx-mod-\n"); + } + addsubstvar($package, "misc:Depends", nginx_depends()); + + my $modules = ""; + foreach my $module (@{$PACKAGE_TYPE{'has_a_module'}}) + { + $modules .= "$module "; + } + + push @postinst_autoscripts, ["module", $modules]; + } + + if (! $dh{NOSCRIPTS}) + { + foreach my $ref (@postinst_autoscripts) + { + for my $script_type (qw/postinst prerm postrm/) + { + if ($script_type eq "postinst" && $dh{NOENABLE}) + { + next + } + + my %replacements = ( + NAMES => $ref->[1], + ); + + my $sed_command = ""; + foreach my $key (sort keys %replacements) + { + my $val = $replacements{$key}; + # Use a control char as separator for sed, to + # reduce escaping issues. Everything else is + # passed verbatim, i.e. it must not contain any + # shell or sed special characters. + my $sep = "\x17"; + $sed_command .= "s" . $sep . "#$key#" . + $sep . $val . + $sep . "g; "; + } + + autoscript($package, "$script_type", "$script_type-nginx", $sed_command); + } + } + } +} + +# vim: syntax=perl sw=8 sts=8 sr noet diff --git a/debian/libnginx-mod.nginx.skeleton b/debian/libnginx-mod.nginx.skeleton new file mode 100755 index 0000000..bf7936c --- /dev/null +++ b/debian/libnginx-mod.nginx.skeleton @@ -0,0 +1,13 @@ +#!/usr/bin/perl -w + +use File::Basename; + +# Guess module name +$module = basename($0, '.nginx'); +$module =~ s/^libnginx-mod-//; + +$modulepath = $module; +$modulepath =~ s/-/_/; + +print "mod debian/build-full/objs/ngx_${modulepath}_module.so\n"; +print "mod debian/libnginx-mod.conf/mod-${module}.conf\n"; diff --git a/debian/nginx-common.links b/debian/nginx-common.links new file mode 100644 index 0000000..ca651a5 --- /dev/null +++ b/debian/nginx-common.links @@ -0,0 +1 @@ +usr/lib/nginx/modules usr/share/nginx/modules diff --git a/debian/rules b/debian/rules index c18af76..8dd6eca 100755 --- a/debian/rules +++ b/debian/rules @@ -36,6 +36,7 @@ common_configure_flags := \ --error-log-path=/var/log/nginx/error.log \ --lock-path=/var/lock/nginx.lock \ --pid-path=/run/nginx.pid \ + --modules-path=/usr/lib/nginx/modules \ --http-client-body-temp-path=/var/lib/nginx/body \ --http-fastcgi-temp-path=/var/lib/nginx/fastcgi \ --http-proxy-temp-path=/var/lib/nginx/proxy \ @@ -126,10 +127,14 @@ extras_configure_flags := \ override_dh_auto_configure: $(foreach flavour,$(FLAVOURS),config.arch.$(flavour)) override_dh_auto_build: $(foreach flavour,$(FLAVOURS),build.arch.$(flavour)) -override_dh_strip: $(foreach flavour,$(FLAVOURS),strip.arch.$(flavour)) +override_dh_strip: $(foreach flavour,$(FLAVOURS),strip.arch.$(flavour)) $(foreach mod,$(DYN_MODS),strip.mods.$(mod)) override_dh_clean: $(foreach flavour,$(FLAVOURS),clean.$(flavour)) dh_clean +override_dh_install: + dh_install + DH_AUTOSCRIPTDIR=$(CURDIR)/debian/autoscripts debian/dh_nginx + override_dh_installinit: dh_installinit --no-restart-on-upgrade --no-start --name=nginx @@ -145,6 +150,9 @@ build.arch.%: strip.arch.%: dh_strip --package=nginx-$(*) --dbg-package=nginx-$(*)-dbg +strip.mods.%: + dh_strip --package=libnginx-mod-$(*) --automatic-dbgsym + config.arch.%: dh_testdir mkdir -p $(BUILDDIR_$*) From b231ba8f39ea52a6277f029bf1c8a9f75eb61796 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Mon, 28 Mar 2016 16:22:08 +0300 Subject: [PATCH 038/600] dh_nginx: Modules depend on nginx-common for now We will change that to nginx-binary when it's available. --- debian/dh_nginx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/dh_nginx b/debian/dh_nginx index 26dedb2..2d7b942 100755 --- a/debian/dh_nginx +++ b/debian/dh_nginx @@ -33,7 +33,7 @@ dh_nginx - register configuration snippets to the nginx web server sub nginx_depends { - return 'nginx-light (= ${binary:Version}) |nginx-full (= ${binary:Version}) | nginx-extras (= ${binary:Version})' + return 'nginx-common (= ${source:Version})' } sub nginx_api_installdir From d19e7548ee639c07ee534164d1be02d88ceba8d0 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Wed, 23 Mar 2016 16:44:39 +0200 Subject: [PATCH 039/600] Build libnginx-mod-* packages --- debian/control | 63 ++++++++++++++++++- debian/libnginx-mod-http-geoip.nginx | 13 ++++ debian/libnginx-mod-http-image-filter.nginx | 13 ++++ debian/libnginx-mod-http-xslt-filter.nginx | 13 ++++ debian/libnginx-mod-mail.nginx | 13 ++++ debian/libnginx-mod-stream.nginx | 13 ++++ debian/libnginx-mod.conf/mod-http-geoip.conf | 1 + .../mod-http-image-filter.conf | 1 + .../mod-http-xslt-filter.conf | 1 + debian/libnginx-mod.conf/mod-mail.conf | 1 + debian/libnginx-mod.conf/mod-stream.conf | 1 + debian/libnginx-mod.nginx.skeleton | 2 +- debian/rules | 21 ++++--- 13 files changed, 144 insertions(+), 12 deletions(-) create mode 100755 debian/libnginx-mod-http-geoip.nginx create mode 100755 debian/libnginx-mod-http-image-filter.nginx create mode 100755 debian/libnginx-mod-http-xslt-filter.nginx create mode 100755 debian/libnginx-mod-mail.nginx create mode 100755 debian/libnginx-mod-stream.nginx create mode 100644 debian/libnginx-mod.conf/mod-http-geoip.conf create mode 100644 debian/libnginx-mod.conf/mod-http-image-filter.conf create mode 100644 debian/libnginx-mod.conf/mod-http-xslt-filter.conf create mode 100644 debian/libnginx-mod.conf/mod-mail.conf create mode 100644 debian/libnginx-mod.conf/mod-stream.conf diff --git a/debian/control b/debian/control index f43fe4f..49aacde 100644 --- a/debian/control +++ b/debian/control @@ -79,7 +79,14 @@ Description: small, powerful, scalable web/proxy server - common files Package: nginx-full Architecture: any -Depends: nginx-common (= ${source:Version}), ${misc:Depends}, ${shlibs:Depends} +Depends: nginx-common (= ${source:Version}), + libnginx-mod-http-geoip (= ${binary:Version}), + libnginx-mod-http-image-filter (= ${binary:Version}), + libnginx-mod-http-xslt-filter (= ${binary:Version}), + libnginx-mod-mail (= ${binary:Version}), + libnginx-mod-stream (= ${binary:Version}), + ${misc:Depends}, + ${shlibs:Depends} Breaks: nginx (<< 1.4.5-1) Provides: httpd, httpd-cgi, nginx Conflicts: nginx-extras, nginx-light @@ -164,6 +171,11 @@ Package: nginx-extras Architecture: any Priority: extra Depends: nginx-common (= ${source:Version}), + libnginx-mod-http-geoip (= ${binary:Version}), + libnginx-mod-http-image-filter (= ${binary:Version}), + libnginx-mod-http-xslt-filter (= ${binary:Version}), + libnginx-mod-mail (= ${binary:Version}), + libnginx-mod-stream (= ${binary:Version}), ${misc:Depends}, ${perl:Depends}, ${shlibs:Depends} @@ -209,3 +221,52 @@ Description: nginx web/proxy server (extended version) - debugging symbols This package provides debugging symbols for nginx-extras, to assist in debugging issues that you may find. It should not be required for normal operation. + +Package: libnginx-mod-http-geoip +Architecture: any +Depends: ${misc:Depends}, ${shlibs:Depends} +Description: GeoIP HTTP module for Nginx + The ngx_http_geoip module creates variables with values depending on the + client IP address, using the precompiled MaxMind databases. + . + Those variables include country, region, city, latitude, longitude, postal + code, etc. + +Package: libnginx-mod-http-image-filter +Architecture: any +Depends: ${misc:Depends}, ${shlibs:Depends} +Description: HTTP image filter module for Nginx + The ngx_http_image_filter module is a filter that transforms images in JPEG, + GIF, and PNG formats. + . + The module supports filters such as rotate, resize, crop, quality, sharpening, + interlacing and more. + +Package: libnginx-mod-http-xslt-filter +Architecture: any +Depends: ${misc:Depends}, ${shlibs:Depends} +Description: XSLT Transformation module for Nginx + The ngx_http_xslt_filter module is a filter that transforms XML responses + using one or more XSLT stylesheets. + . + The transformation can be adjusted by setting the relevant configuration + parameters. + +Package: libnginx-mod-mail +Architecture: any +Depends: ${misc:Depends}, ${shlibs:Depends} +Description: Mail module for Nginx + The nginx_mail module adds mail proxy support to nginx. + . + The module supports proxying all the standard mail protocols such as IMAP, + POP3 & SMTP. + +Package: libnginx-mod-stream +Architecture: any +Depends: ${misc:Depends}, ${shlibs:Depends} +Description: Stream module for Nginx + The nginx_stream module adds stream proxy support to nginx. + . + Stream module supports loadbalancing & proxying to TCP servers. The module + also supports ACLs/connection limiting and configuring multiple operational + parameters. diff --git a/debian/libnginx-mod-http-geoip.nginx b/debian/libnginx-mod-http-geoip.nginx new file mode 100755 index 0000000..02c5edc --- /dev/null +++ b/debian/libnginx-mod-http-geoip.nginx @@ -0,0 +1,13 @@ +#!/usr/bin/perl -w + +use File::Basename; + +# Guess module name +$module = basename($0, '.nginx'); +$module =~ s/^libnginx-mod-//; + +$modulepath = $module; +$modulepath =~ s/-/_/g; + +print "mod debian/build-full/objs/ngx_${modulepath}_module.so\n"; +print "mod debian/libnginx-mod.conf/mod-${module}.conf\n"; diff --git a/debian/libnginx-mod-http-image-filter.nginx b/debian/libnginx-mod-http-image-filter.nginx new file mode 100755 index 0000000..02c5edc --- /dev/null +++ b/debian/libnginx-mod-http-image-filter.nginx @@ -0,0 +1,13 @@ +#!/usr/bin/perl -w + +use File::Basename; + +# Guess module name +$module = basename($0, '.nginx'); +$module =~ s/^libnginx-mod-//; + +$modulepath = $module; +$modulepath =~ s/-/_/g; + +print "mod debian/build-full/objs/ngx_${modulepath}_module.so\n"; +print "mod debian/libnginx-mod.conf/mod-${module}.conf\n"; diff --git a/debian/libnginx-mod-http-xslt-filter.nginx b/debian/libnginx-mod-http-xslt-filter.nginx new file mode 100755 index 0000000..02c5edc --- /dev/null +++ b/debian/libnginx-mod-http-xslt-filter.nginx @@ -0,0 +1,13 @@ +#!/usr/bin/perl -w + +use File::Basename; + +# Guess module name +$module = basename($0, '.nginx'); +$module =~ s/^libnginx-mod-//; + +$modulepath = $module; +$modulepath =~ s/-/_/g; + +print "mod debian/build-full/objs/ngx_${modulepath}_module.so\n"; +print "mod debian/libnginx-mod.conf/mod-${module}.conf\n"; diff --git a/debian/libnginx-mod-mail.nginx b/debian/libnginx-mod-mail.nginx new file mode 100755 index 0000000..02c5edc --- /dev/null +++ b/debian/libnginx-mod-mail.nginx @@ -0,0 +1,13 @@ +#!/usr/bin/perl -w + +use File::Basename; + +# Guess module name +$module = basename($0, '.nginx'); +$module =~ s/^libnginx-mod-//; + +$modulepath = $module; +$modulepath =~ s/-/_/g; + +print "mod debian/build-full/objs/ngx_${modulepath}_module.so\n"; +print "mod debian/libnginx-mod.conf/mod-${module}.conf\n"; diff --git a/debian/libnginx-mod-stream.nginx b/debian/libnginx-mod-stream.nginx new file mode 100755 index 0000000..02c5edc --- /dev/null +++ b/debian/libnginx-mod-stream.nginx @@ -0,0 +1,13 @@ +#!/usr/bin/perl -w + +use File::Basename; + +# Guess module name +$module = basename($0, '.nginx'); +$module =~ s/^libnginx-mod-//; + +$modulepath = $module; +$modulepath =~ s/-/_/g; + +print "mod debian/build-full/objs/ngx_${modulepath}_module.so\n"; +print "mod debian/libnginx-mod.conf/mod-${module}.conf\n"; diff --git a/debian/libnginx-mod.conf/mod-http-geoip.conf b/debian/libnginx-mod.conf/mod-http-geoip.conf new file mode 100644 index 0000000..9721986 --- /dev/null +++ b/debian/libnginx-mod.conf/mod-http-geoip.conf @@ -0,0 +1 @@ +load_module modules/ngx_http_geoip_module.so; diff --git a/debian/libnginx-mod.conf/mod-http-image-filter.conf b/debian/libnginx-mod.conf/mod-http-image-filter.conf new file mode 100644 index 0000000..dfa2939 --- /dev/null +++ b/debian/libnginx-mod.conf/mod-http-image-filter.conf @@ -0,0 +1 @@ +load_module modules/ngx_http_image_filter_module.so; diff --git a/debian/libnginx-mod.conf/mod-http-xslt-filter.conf b/debian/libnginx-mod.conf/mod-http-xslt-filter.conf new file mode 100644 index 0000000..a4f87ac --- /dev/null +++ b/debian/libnginx-mod.conf/mod-http-xslt-filter.conf @@ -0,0 +1 @@ +load_module modules/ngx_http_xslt_filter_module.so; diff --git a/debian/libnginx-mod.conf/mod-mail.conf b/debian/libnginx-mod.conf/mod-mail.conf new file mode 100644 index 0000000..cfd4a4d --- /dev/null +++ b/debian/libnginx-mod.conf/mod-mail.conf @@ -0,0 +1 @@ +load_module modules/ngx_mail_module.so; diff --git a/debian/libnginx-mod.conf/mod-stream.conf b/debian/libnginx-mod.conf/mod-stream.conf new file mode 100644 index 0000000..f2b2657 --- /dev/null +++ b/debian/libnginx-mod.conf/mod-stream.conf @@ -0,0 +1 @@ +load_module modules/ngx_stream_module.so; diff --git a/debian/libnginx-mod.nginx.skeleton b/debian/libnginx-mod.nginx.skeleton index bf7936c..02c5edc 100755 --- a/debian/libnginx-mod.nginx.skeleton +++ b/debian/libnginx-mod.nginx.skeleton @@ -7,7 +7,7 @@ $module = basename($0, '.nginx'); $module =~ s/^libnginx-mod-//; $modulepath = $module; -$modulepath =~ s/-/_/; +$modulepath =~ s/-/_/g; print "mod debian/build-full/objs/ngx_${modulepath}_module.so\n"; print "mod debian/libnginx-mod.conf/mod-${module}.conf\n"; diff --git a/debian/rules b/debian/rules index 8dd6eca..6f88edc 100755 --- a/debian/rules +++ b/debian/rules @@ -11,6 +11,7 @@ DEBIAN_NGINX_PERL_LDFLAGS:= $(shell DEB_BUILD_MAINT_OPTIONS=hardening=+all,-pie export DEBIAN_NGINX_PERL_LDFLAGS FLAVOURS := full light extras +DYN_MODS := http-geoip http-image-filter http-xslt-filter mail stream MODULESDIR = $(CURDIR)/debian/modules BASEDIR = $(CURDIR) @@ -70,16 +71,16 @@ full_configure_flags := \ $(common_configure_flags) \ --with-http_addition_module \ --with-http_dav_module \ - --with-http_geoip_module \ + --with-http_geoip_module=dynamic \ --with-http_gunzip_module \ --with-http_gzip_static_module \ - --with-http_image_filter_module \ + --with-http_image_filter_module=dynamic \ --with-http_v2_module \ --with-http_sub_module \ - --with-http_xslt_module \ - --with-stream \ + --with-http_xslt_module=dynamic \ + --with-stream=dynamic \ --with-stream_ssl_module \ - --with-mail \ + --with-mail=dynamic \ --with-mail_ssl_module \ --with-threads \ --add-module=$(MODULESDIR)/nginx-auth-pam \ @@ -93,20 +94,20 @@ extras_configure_flags := \ --with-http_addition_module \ --with-http_dav_module \ --with-http_flv_module \ - --with-http_geoip_module \ + --with-http_geoip_module=dynamic \ --with-http_gunzip_module \ --with-http_gzip_static_module \ - --with-http_image_filter_module \ + --with-http_image_filter_module=dynamic \ --with-http_mp4_module \ --with-http_perl_module \ --with-http_random_index_module \ --with-http_secure_link_module \ --with-http_v2_module \ --with-http_sub_module \ - --with-http_xslt_module \ - --with-mail \ + --with-http_xslt_module=dynamic \ + --with-mail=dynamic \ --with-mail_ssl_module \ - --with-stream \ + --with-stream=dynamic \ --with-stream_ssl_module \ --with-threads \ --add-module=$(MODULESDIR)/headers-more-nginx-module \ From 24ba8b51ef2d27d90ec3b0739ef099fb9cef8212 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Wed, 30 Mar 2016 09:53:48 +0300 Subject: [PATCH 040/600] Make sure signature stays the same in all nginx builds When a dyn module is loaded the signature of the module is compared to the one of the nginx binary. dyn modules are build from nginx-full, so in order to make them loadable in other flavors we need to make sure all the binaries share the same signature. The signature is a vector computed from 33+3 parameters (src/core/ngx_module.h) With this commit we align all nginx flavors to same signature vector. --- debian/control | 3 +- ...ure-stays-the-same-in-all-nginx-buil.patch | 30 +++++++++++++++++++ debian/patches/series | 1 + debian/rules | 11 +++---- 4 files changed, 37 insertions(+), 8 deletions(-) create mode 100644 debian/patches/0002-Make-sure-signature-stays-the-same-in-all-nginx-buil.patch diff --git a/debian/control b/debian/control index 49aacde..2076f5c 100644 --- a/debian/control +++ b/debian/control @@ -148,7 +148,8 @@ Description: nginx web/proxy server (basic version) FastCGI, Map, Proxy, Rewrite. . OPTIONAL HTTP MODULES: Auth Request, Charset, Gzip, Gzip Precompression, - Headers, Index, Log, Real IP, SSL, Stub Status, Upstream. + Headers, HTTP/2, Index, Log, Real IP, SSL, Stub Status, Thread Pool, WebDAV, + Upstream. . THIRD PARTY MODULES: Echo. diff --git a/debian/patches/0002-Make-sure-signature-stays-the-same-in-all-nginx-buil.patch b/debian/patches/0002-Make-sure-signature-stays-the-same-in-all-nginx-buil.patch new file mode 100644 index 0000000..1bea8b2 --- /dev/null +++ b/debian/patches/0002-Make-sure-signature-stays-the-same-in-all-nginx-buil.patch @@ -0,0 +1,30 @@ +From: Christos Trochalakis +Date: Wed, 30 Mar 2016 09:47:11 +0300 +Subject: Make sure signature stays the same in all nginx builds + +NGX_HTTP_HEADERS is part of nginx signature. When a dyn +modules is loaded the signature of the module is compared +to the one of the nginx binary. + +dyn modules are build from nginx-full, so in order to make +them loadable in other flavors we need to make sure all the +binaries share the same signature. +--- + configure | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/configure b/configure +index ceff15e..3816fa1 100755 +--- a/configure ++++ b/configure +@@ -58,6 +58,10 @@ if [ "$NGX_PLATFORM" != win32 ]; then + . auto/unix + fi + ++# Debian ++# Make sure signature stays the same on all nginx flavors ++have=NGX_HTTP_HEADERS . auto/have ++ + . auto/threads + . auto/modules + . auto/lib/conf diff --git a/debian/patches/series b/debian/patches/series index 73f535e..04b971f 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -1 +1,2 @@ perl-use-dpkg-buildflags.patch +0002-Make-sure-signature-stays-the-same-in-all-nginx-buil.patch diff --git a/debian/rules b/debian/rules index 6f88edc..f9db327 100755 --- a/debian/rules +++ b/debian/rules @@ -49,7 +49,10 @@ common_configure_flags := \ --with-http_ssl_module \ --with-http_stub_status_module \ --with-http_realip_module \ - --with-http_auth_request_module + --with-http_auth_request_module \ + --with-http_v2_module \ + --with-http_dav_module \ + --with-threads light_configure_flags := \ $(common_configure_flags) \ @@ -70,19 +73,16 @@ light_configure_flags := \ full_configure_flags := \ $(common_configure_flags) \ --with-http_addition_module \ - --with-http_dav_module \ --with-http_geoip_module=dynamic \ --with-http_gunzip_module \ --with-http_gzip_static_module \ --with-http_image_filter_module=dynamic \ - --with-http_v2_module \ --with-http_sub_module \ --with-http_xslt_module=dynamic \ --with-stream=dynamic \ --with-stream_ssl_module \ --with-mail=dynamic \ --with-mail_ssl_module \ - --with-threads \ --add-module=$(MODULESDIR)/nginx-auth-pam \ --add-module=$(MODULESDIR)/nginx-dav-ext-module \ --add-module=$(MODULESDIR)/nginx-echo \ @@ -92,7 +92,6 @@ full_configure_flags := \ extras_configure_flags := \ $(common_configure_flags) \ --with-http_addition_module \ - --with-http_dav_module \ --with-http_flv_module \ --with-http_geoip_module=dynamic \ --with-http_gunzip_module \ @@ -102,14 +101,12 @@ extras_configure_flags := \ --with-http_perl_module \ --with-http_random_index_module \ --with-http_secure_link_module \ - --with-http_v2_module \ --with-http_sub_module \ --with-http_xslt_module=dynamic \ --with-mail=dynamic \ --with-mail_ssl_module \ --with-stream=dynamic \ --with-stream_ssl_module \ - --with-threads \ --add-module=$(MODULESDIR)/headers-more-nginx-module \ --add-module=$(MODULESDIR)/nginx-auth-pam \ --add-module=$(MODULESDIR)/nginx-cache-purge \ From bba86a8f896aeecb716dde79ef3f2ba9fc86a092 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Wed, 30 Mar 2016 10:00:33 +0300 Subject: [PATCH 041/600] tests: Test if nginx-light can successfully load dynamic modules --- debian/tests/control | 3 +++ 1 file changed, 3 insertions(+) diff --git a/debian/tests/control b/debian/tests/control index 8d0e384..881cc56 100644 --- a/debian/tests/control +++ b/debian/tests/control @@ -10,3 +10,6 @@ Test-Command: curl --silent --fail -o /dev/null -w "response_code: %{http_code}\ Restrictions: allow-stderr isolation-container Depends: nginx-extras, curl +Test-Command: curl --silent --fail -o /dev/null -w "response_code: %{http_code}\n" http://127.0.0.1/ +Restrictions: allow-stderr isolation-container +Depends: nginx-light, libnginx-mod-stream, curl From 830a8fbc342545e228baefbbb9f4f540d6fdd3f6 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Wed, 30 Mar 2016 11:17:18 +0300 Subject: [PATCH 042/600] Sum up changes --- debian/changelog | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/debian/changelog b/debian/changelog index 0f8009f..226b72b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -2,6 +2,23 @@ nginx (1.9.11-1) UNRELEASED; urgency=medium [ Christos Trochalakis ] * New upstream release (1.9.11) (Closes: #812806) + * debian: + + Setup dynamic module flow, and implement a simple dh_nginx helper for + internal use. + + Split modules in libnginx-mod-* packages. + Not all modules are ready for dynamic building. + * debian/control: + + Enable http/2, thread pool & WebDAV on nginx-light. + In order for dynamic modules to be loadable in all nginx flavors we need + to ensure the share the same build signature. + + Use secure VCS uri (lintian). + + Bump Standards to 3.9.7. + * debian/rules: + + Disable PIE for now so we can build dynamic modules. + * debian/tests/control: + + Test if modules are loadable in nginx-light. + * debian/nginx-common.nginx.service: + + Documentation points to nginx man page. * debian/modules/nginx-lua: + Update nginx-lua to v0.10.1rc0-5-g01727a3. Fixes buiding failures with nginx 1.9.11. From 95448c85f548c75efe77f4433c6bb1f5a30e36b2 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Wed, 30 Mar 2016 11:23:20 +0300 Subject: [PATCH 043/600] Imported Upstream version 1.9.12 --- CHANGES | 30 +++ CHANGES.ru | 29 +++ auto/cc/conf | 10 + auto/cc/msvc | 31 ++- auto/cc/name | 27 +- auto/install | 5 +- auto/lib/md5/conf | 4 +- auto/lib/md5/make | 4 +- auto/lib/openssl/conf | 15 +- auto/lib/openssl/make | 2 +- auto/lib/pcre/conf | 4 +- auto/lib/pcre/make | 4 +- auto/lib/sha1/conf | 4 +- auto/lib/sha1/make | 4 +- auto/lib/zlib/conf | 4 +- auto/lib/zlib/make | 4 +- auto/make | 4 + auto/modules | 3 +- auto/unix | 1 + src/core/nginx.c | 79 ++++-- src/core/nginx.h | 4 +- src/core/ngx_cycle.h | 4 +- src/core/ngx_module.c | 2 +- src/core/ngx_module.h | 2 +- src/event/ngx_event_openssl.c | 15 +- .../modules/ngx_http_headers_filter_module.c | 16 +- src/http/ngx_http_request.c | 19 +- src/http/v2/ngx_http_v2.c | 237 ++++++++++++----- src/http/v2/ngx_http_v2.h | 5 + src/http/v2/ngx_http_v2_filter_module.c | 224 +++++++++++----- src/http/v2/ngx_http_v2_huff_encode.c | 244 ++++++++++++++++++ src/os/unix/ngx_process_cycle.c | 2 +- src/os/unix/ngx_setaffinity.c | 44 +--- src/os/unix/ngx_setaffinity.h | 16 +- src/stream/ngx_stream_proxy_module.c | 7 +- 35 files changed, 820 insertions(+), 289 deletions(-) diff --git a/CHANGES b/CHANGES index da1fa00..e94e14f 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,34 @@ +Changes with nginx 1.9.12 24 Feb 2016 + + *) Feature: Huffman encoding of response headers in HTTP/2. + Thanks to Vlad Krasnov. + + *) Feature: the "worker_cpu_affinity" directive now supports more than + 64 CPUs. + + *) Bugfix: compatibility with 3rd party C++ modules; the bug had + appeared in 1.9.11. + Thanks to Piotr Sikora. + + *) Bugfix: nginx could not be built statically with OpenSSL on Linux; + the bug had appeared in 1.9.11. + + *) Bugfix: the "add_header ... always" directive with an empty value did + not delete "Last-Modified" and "ETag" header lines from error + responses. + + *) Workaround: "called a function you should not call" and "shutdown + while in init" messages might appear in logs when using OpenSSL + 1.0.2f. + + *) Bugfix: invalid headers might be logged incorrectly. + + *) Bugfix: socket leak when using HTTP/2. + + *) Bugfix: in the ngx_http_v2_module. + + Changes with nginx 1.9.11 09 Feb 2016 *) Feature: TCP support in resolver. diff --git a/CHANGES.ru b/CHANGES.ru index 33302e2..c11c477 100644 --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,33 @@ +Изменения в nginx 1.9.12 24.02.2016 + + *) Добавление: кодирование Хаффмана заголовков ответов в HTTP/2. + Спасибо Владу Краснову. + + *) Добавление: директива worker_cpu_affinity теперь поддерживает более + 64 процессоров. + + *) Исправление: совместимость со сторонними модулями на C++; ошибка + появилась в 1.9.11. + Спасибо Piotr Sikora. + + *) Исправление: nginx не собирался статически с OpenSSL на Linux; ошибка + появилась в 1.9.11. + + *) Исправление: директива "add_header ... always" с пустым значением не + удаляла из заголовков ошибочных ответов строки Last-Modified и ETag. + + *) Изменение: при использовании OpenSSL 1.0.2f в логах могли появляться + сообщения "called a function you should not call" и "shutdown while + in init". + + *) Исправление: ошибочные заголовки могли логгироваться некорректно. + + *) Исправление: утечки сокетов при использовании HTTP/2. + + *) Исправление: в модуле ngx_http_v2_module. + + Изменения в nginx 1.9.11 09.02.2016 *) Добавление: теперь resolver поддерживает TCP. diff --git a/auto/cc/conf b/auto/cc/conf index 35fd39c..f2c25ed 100644 --- a/auto/cc/conf +++ b/auto/cc/conf @@ -225,6 +225,16 @@ if [ "$NGX_PLATFORM" != win32 ]; then . auto/feature + ngx_feature="gcc builtin 64 bit byteswap" + ngx_feature_name="NGX_HAVE_GCC_BSWAP64" + ngx_feature_run=no + ngx_feature_incs= + ngx_feature_path= + ngx_feature_libs= + ngx_feature_test="__builtin_bswap64(0)" + . auto/feature + + # ngx_feature="inline" # ngx_feature_name= # ngx_feature_run=no diff --git a/auto/cc/msvc b/auto/cc/msvc index e588c48..4eef101 100644 --- a/auto/cc/msvc +++ b/auto/cc/msvc @@ -3,9 +3,24 @@ # Copyright (C) Nginx, Inc. -# MSVC 6.0 SP2 -# MSVC Toolkit 2003 (7.1) -# MSVC 2005 Express Edition SP1 (8.0) +# MSVC 6.0 SP2 cl 12.00 +# MSVC Toolkit 2003 (7.1) cl 13.10 +# MSVC 2005 Express Edition SP1 (8.0) cl 14.00 +# MSVC 2008 Express Edition (9.0) cl 15.00 +# MSVC 2010 (10.0) cl 16.00 +# MSVC 2015 (14.0) cl 19.00 + + +NGX_MSVC_VER=`$NGX_WINE $CC 2>&1 | grep 'Compiler Version' 2>&1 \ + | sed -e 's/^.* Version \(.*\)/\1/'` + +echo " + cl version: $NGX_MSVC_VER" + +have=NGX_COMPILER value="\"cl $NGX_MSVC_VER\"" . auto/define + + +ngx_msvc_ver=`echo $NGX_MSVC_VER | sed -e 's/^\([0-9]*\).*/\1/'` + # optimizations @@ -90,17 +105,17 @@ CORE_LIBS="$CORE_LIBS kernel32.lib user32.lib" #CORE_LINK="$CORE_LINK -subsystem:windows -entry:mainCRTStartup" # debug -# msvc8 under Wine issues -# Program database manager mismatch; please check your installation -if [ $NGX_CC_NAME != msvc8 ]; then +# msvc under Wine issues +# C1902: Program database manager mismatch; please check your installation +if [ -z "$NGX_WINE" ]; then CFLAGS="$CFLAGS -Zi" CORE_LINK="$CORE_LINK -debug" fi # MSVC 2005 supports C99 variadic macros -if [ $NGX_CC_NAME = msvc8 ]; then - have=NGX_HAVE_C99_VARIADIC_MACROS . auto/have +if [ "$ngx_msvc_ver" -ge 14 ]; then + have=NGX_HAVE_C99_VARIADIC_MACROS . auto/have fi diff --git a/auto/cc/name b/auto/cc/name index 51a7ed9..35d319e 100644 --- a/auto/cc/name +++ b/auto/cc/name @@ -25,31 +25,8 @@ fi if [ "$CC" = cl ]; then - if `$NGX_WINE $CC -v 2>&1 \ - | grep '^Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16' \ - >/dev/null 2>&1`; then - - NGX_CC_NAME=msvc10 - echo " + using Microsoft Visual C++ 10 compiler" - - 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" - - elif `$NGX_WINE $CC -v 2>&1 \ - | grep '^Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13' \ - >/dev/null 2>&1`; then - - NGX_CC_NAME=msvc7 - echo " + using Microsoft Visual C++ 7 compiler" - - else - NGX_CC_NAME=msvc - echo " + using Microsoft Visual C++ compiler" - fi + NGX_CC_NAME=msvc + echo " + using Microsoft Visual C++ compiler" elif [ "$CC" = wcl386 ]; then NGX_CC_NAME=owc diff --git a/auto/install b/auto/install index 4dcc743..9469a49 100644 --- a/auto/install +++ b/auto/install @@ -104,8 +104,7 @@ $NGX_OBJS/nginx.8: $NGX_MAN $NGX_AUTO_CONFIG_H -e "s|%%ERROR_LOG_PATH%%|${NGX_ERROR_LOG_PATH:-stderr}|" \\ < $NGX_MAN > \$@ -install: $NGX_OBJS${ngx_dirsep}nginx${ngx_binext} \ - $NGX_INSTALL_PERL_MODULES +install: build $NGX_INSTALL_PERL_MODULES test -d '\$(DESTDIR)$NGX_PREFIX' || mkdir -p '\$(DESTDIR)$NGX_PREFIX' test -d '\$(DESTDIR)`dirname "$NGX_SBIN_PATH"`' \ @@ -187,8 +186,6 @@ cat << END >> Makefile build: \$(MAKE) -f $NGX_MAKEFILE - \$(MAKE) -f $NGX_MAKEFILE modules - \$(MAKE) -f $NGX_MAKEFILE manpage install: \$(MAKE) -f $NGX_MAKEFILE install diff --git a/auto/lib/md5/conf b/auto/lib/md5/conf index eb5dfd1..49c0ddf 100644 --- a/auto/lib/md5/conf +++ b/auto/lib/md5/conf @@ -20,12 +20,12 @@ if [ $MD5 != NONE ]; then case "$NGX_CC_NAME" in - msvc* | owc* | bcc) + msvc | owc | bcc) LINK_DEPS="$LINK_DEPS $MD5/md5.lib" CORE_LIBS="$CORE_LIBS $MD5/md5.lib" ;; - icc*) + icc) LINK_DEPS="$LINK_DEPS $MD5/libmd5.a" # to allow -ipo optimization we link with the *.o but not library diff --git a/auto/lib/md5/make b/auto/lib/md5/make index 81f138a..7000b20 100644 --- a/auto/lib/md5/make +++ b/auto/lib/md5/make @@ -5,13 +5,13 @@ case "$NGX_CC_NAME" in - msvc*) + msvc) ngx_makefile=makefile.msvc ngx_opt="CPU_OPT=\"$CPU_OPT\" LIBC=$LIBC MD5_ASM=$MD5_ASM" ngx_md5="MD5=\"$MD5\"" ;; - owc*) + owc) ngx_makefile=makefile.owc ngx_opt="CPU_OPT=\"$CPU_OPT\"" ngx_md5=`echo MD5=\"$MD5\" | sed -e "s/\//$ngx_regex_dirsep/g"` diff --git a/auto/lib/openssl/conf b/auto/lib/openssl/conf index 2187e5c..e438050 100644 --- a/auto/lib/openssl/conf +++ b/auto/lib/openssl/conf @@ -32,6 +32,7 @@ if [ $OPENSSL != NONE ]; then CORE_DEPS="$CORE_DEPS $OPENSSL/.openssl/include/openssl/ssl.h" CORE_LIBS="$CORE_LIBS $OPENSSL/.openssl/lib/libssl.a" CORE_LIBS="$CORE_LIBS $OPENSSL/.openssl/lib/libcrypto.a" + CORE_LIBS="$CORE_LIBS $NGX_LIBDL" if [ "$NGX_PLATFORM" = win32 ]; then CORE_LIBS="$CORE_LIBS -lgdi32 -lcrypt32 -lws2_32" @@ -50,7 +51,7 @@ else ngx_feature_run=no ngx_feature_incs="#include " ngx_feature_path= - ngx_feature_libs="-lssl -lcrypto" + ngx_feature_libs="-lssl -lcrypto $NGX_LIBDL" ngx_feature_test="SSL_library_init()" . auto/feature @@ -62,9 +63,9 @@ else ngx_feature_path="/usr/local/include" if [ $NGX_RPATH = YES ]; then - ngx_feature_libs="-R/usr/local/lib -L/usr/local/lib -lssl -lcrypto" + ngx_feature_libs="-R/usr/local/lib -L/usr/local/lib -lssl -lcrypto $NGX_LIBDL" else - ngx_feature_libs="-L/usr/local/lib -lssl -lcrypto" + ngx_feature_libs="-L/usr/local/lib -lssl -lcrypto $NGX_LIBDL" fi . auto/feature @@ -78,9 +79,9 @@ else ngx_feature_path="/usr/pkg/include" if [ $NGX_RPATH = YES ]; then - ngx_feature_libs="-R/usr/pkg/lib -L/usr/pkg/lib -lssl -lcrypto" + ngx_feature_libs="-R/usr/pkg/lib -L/usr/pkg/lib -lssl -lcrypto $NGX_LIBDL" else - ngx_feature_libs="-L/usr/pkg/lib -lssl -lcrypto" + ngx_feature_libs="-L/usr/pkg/lib -lssl -lcrypto $NGX_LIBDL" fi . auto/feature @@ -94,9 +95,9 @@ else ngx_feature_path="/opt/local/include" if [ $NGX_RPATH = YES ]; then - ngx_feature_libs="-R/opt/local/lib -L/opt/local/lib -lssl -lcrypto" + ngx_feature_libs="-R/opt/local/lib -L/opt/local/lib -lssl -lcrypto $NGX_LIBDL" else - ngx_feature_libs="-L/opt/local/lib -lssl -lcrypto" + ngx_feature_libs="-L/opt/local/lib -lssl -lcrypto $NGX_LIBDL" fi . auto/feature diff --git a/auto/lib/openssl/make b/auto/lib/openssl/make index 765cd06..a6090c6 100644 --- a/auto/lib/openssl/make +++ b/auto/lib/openssl/make @@ -53,7 +53,7 @@ $OPENSSL/.openssl/include/openssl/ssl.h: $NGX_MAKEFILE && if [ -f Makefile ]; then \$(MAKE) clean; fi \\ && ./config --prefix=$ngx_prefix no-shared $OPENSSL_OPT \\ && \$(MAKE) \\ - && \$(MAKE) install LIBDIR=lib + && \$(MAKE) install_sw LIBDIR=lib END diff --git a/auto/lib/pcre/conf b/auto/lib/pcre/conf index 939f01b..5e3960f 100644 --- a/auto/lib/pcre/conf +++ b/auto/lib/pcre/conf @@ -8,7 +8,7 @@ if [ $PCRE != NONE ]; then case "$NGX_CC_NAME" in - msvc* | owc* | bcc) + msvc | owc | bcc) have=NGX_PCRE . auto/have have=PCRE_STATIC . auto/have CORE_DEPS="$CORE_DEPS $PCRE/pcre.h" @@ -16,7 +16,7 @@ if [ $PCRE != NONE ]; then CORE_LIBS="$CORE_LIBS $PCRE/pcre.lib" ;; - icc* ) + icc) have=NGX_PCRE . auto/have CORE_DEPS="$CORE_DEPS $PCRE/pcre.h" diff --git a/auto/lib/pcre/make b/auto/lib/pcre/make index 0a27a11..97c9f3b 100644 --- a/auto/lib/pcre/make +++ b/auto/lib/pcre/make @@ -5,13 +5,13 @@ case "$NGX_CC_NAME" in - msvc*) + msvc) ngx_makefile=makefile.msvc ngx_opt="CPU_OPT=\"$CPU_OPT\" LIBC=$LIBC" ngx_pcre="PCRE=\"$PCRE\"" ;; - owc*) + owc) ngx_makefile=makefile.owc ngx_opt="CPU_OPT=\"$CPU_OPT\"" ngx_pcre=`echo PCRE=\"$PCRE\" | sed -e "s/\//$ngx_regex_dirsep/g"` diff --git a/auto/lib/sha1/conf b/auto/lib/sha1/conf index fd69afd..78f9efd 100644 --- a/auto/lib/sha1/conf +++ b/auto/lib/sha1/conf @@ -10,12 +10,12 @@ if [ $SHA1 != NONE ]; then case "$NGX_CC_NAME" in - msvc* | owc* | bcc) + msvc | owc | bcc) LINK_DEPS="$LINK_DEPS $SHA1/sha1.lib" CORE_LIBS="$CORE_LIBS $SHA1/sha1.lib" ;; - icc*) + icc) LINK_DEPS="$LINK_DEPS $SHA1/libsha.a" # to allow -ipo optimization we link with the *.o but not library diff --git a/auto/lib/sha1/make b/auto/lib/sha1/make index fc10aae..fc3b340 100644 --- a/auto/lib/sha1/make +++ b/auto/lib/sha1/make @@ -5,13 +5,13 @@ case "$NGX_CC_NAME" in - msvc*) + msvc) ngx_makefile=makefile.msvc ngx_opt="CPU_OPT=\"$CPU_OPT\" LIBC=$LIBC SHA1_ASM=$SHA1_ASM" ngx_sha1="SHA1=\"$SHA1\"" ;; - owc*) + owc) ngx_makefile=makefile.owc ngx_opt="CPU_OPT=\"$CPU_OPT\"" ngx_sha1=`echo SHA1=\"$SHA1\" | sed -e "s/\//$ngx_regex_dirsep/g"` diff --git a/auto/lib/zlib/conf b/auto/lib/zlib/conf index 26db642..239592e 100644 --- a/auto/lib/zlib/conf +++ b/auto/lib/zlib/conf @@ -8,13 +8,13 @@ if [ $ZLIB != NONE ]; then case "$NGX_CC_NAME" in - msvc* | owc* | bcc) + msvc | owc | bcc) have=NGX_ZLIB . auto/have LINK_DEPS="$LINK_DEPS $ZLIB/zlib.lib" CORE_LIBS="$CORE_LIBS $ZLIB/zlib.lib" ;; - icc*) + icc) have=NGX_ZLIB . auto/have LINK_DEPS="$LINK_DEPS $ZLIB/libz.a" diff --git a/auto/lib/zlib/make b/auto/lib/zlib/make index 7875ef6..0082ad5 100644 --- a/auto/lib/zlib/make +++ b/auto/lib/zlib/make @@ -5,14 +5,14 @@ case "$NGX_CC_NAME" in - msvc*) + msvc) ngx_makefile=makefile.msvc ngx_opt="CPU_OPT=\"$CPU_OPT\" LIBC=$LIBC" ngx_zlib="ZLIB=\"$ZLIB\"" ;; - owc*) + owc) ngx_makefile=makefile.owc ngx_opt="CPU_OPT=\"$CPU_OPT\"" ngx_zlib=`echo ZLIB=\"$ZLIB\" | sed -e "s/\//$ngx_regex_dirsep/g"` diff --git a/auto/make b/auto/make index 039a70f..560924b 100644 --- a/auto/make +++ b/auto/make @@ -223,6 +223,10 @@ ngx_main_link=${MAIN_LINK:+`echo $MAIN_LINK \ cat << END >> $NGX_MAKEFILE +build: binary modules manpage + +binary: $NGX_OBJS${ngx_dirsep}nginx${ngx_binext} + $NGX_OBJS${ngx_dirsep}nginx${ngx_binext}: $ngx_deps$ngx_spacer \$(LINK) ${ngx_long_start}${ngx_binout}$NGX_OBJS${ngx_dirsep}nginx$ngx_long_cont$ngx_objs$ngx_libs$ngx_link$ngx_main_link $ngx_rcc diff --git a/auto/modules b/auto/modules index 2074778..ebfc91d 100644 --- a/auto/modules +++ b/auto/modules @@ -530,11 +530,10 @@ if [ $HTTP_AUTH_BASIC = YES ]; then ngx_module_incs= ngx_module_deps= ngx_module_srcs=src/http/modules/ngx_http_auth_basic_module.c - ngx_module_libs= + ngx_module_libs=$CRYPT_LIB ngx_module_link=$HTTP_AUTH_BASIC . auto/module - CORE_LIBS="$CORE_LIBS $CRYPT_LIB" fi if [ $HTTP_ACCESS = YES ]; then diff --git a/auto/unix b/auto/unix index e07df08..ce01791 100755 --- a/auto/unix +++ b/auto/unix @@ -272,6 +272,7 @@ if [ $ngx_found != yes ]; then if [ $ngx_found = yes ]; then CORE_LIBS="$CORE_LIBS -ldl" + NGX_LIBDL="-ldl" fi fi diff --git a/src/core/nginx.c b/src/core/nginx.c index 6ce030c..cdc067e 100644 --- a/src/core/nginx.c +++ b/src/core/nginx.c @@ -481,6 +481,12 @@ ngx_add_inherited_sockets(ngx_cycle_t *cycle) } } + if (v != p) { + ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, + "invalid socket number \"%s\" in " NGINX_VAR + " environment variable, ignoring", v); + } + ngx_inherited = 1; return ngx_set_inherited_sockets(cycle); @@ -1264,16 +1270,16 @@ ngx_set_cpu_affinity(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) #if (NGX_HAVE_CPU_AFFINITY) ngx_core_conf_t *ccf = conf; - u_char ch; - uint64_t *mask; + u_char ch, *p; ngx_str_t *value; ngx_uint_t i, n; + ngx_cpuset_t *mask; if (ccf->cpu_affinity) { return "is duplicate"; } - mask = ngx_palloc(cf->pool, (cf->args->nelts - 1) * sizeof(uint64_t)); + mask = ngx_palloc(cf->pool, (cf->args->nelts - 1) * sizeof(ngx_cpuset_t)); if (mask == NULL) { return NGX_CONF_ERROR; } @@ -1293,7 +1299,12 @@ ngx_set_cpu_affinity(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) } ccf->cpu_affinity_auto = 1; - mask[0] = (uint64_t) -1 >> (64 - ngx_min(64, ngx_ncpu)); + + CPU_ZERO(&mask[0]); + for (i = 0; i < (ngx_uint_t) ngx_min(ngx_ncpu, CPU_SETSIZE); i++) { + CPU_SET(i, &mask[0]); + } + n = 2; } else { @@ -1302,30 +1313,34 @@ ngx_set_cpu_affinity(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) for ( /* void */ ; n < cf->args->nelts; n++) { - if (value[n].len > 64) { + if (value[n].len > CPU_SETSIZE) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "\"worker_cpu_affinity\" supports up to 64 CPUs only"); + "\"worker_cpu_affinity\" supports up to %d CPUs only", + CPU_SETSIZE); return NGX_CONF_ERROR; } - mask[n - 1] = 0; + i = 0; + CPU_ZERO(&mask[n - 1]); - for (i = 0; i < value[n].len; i++) { - - ch = value[n].data[i]; + for (p = value[n].data + value[n].len - 1; + p >= value[n].data; + p--) + { + ch = *p; if (ch == ' ') { continue; } - mask[n - 1] <<= 1; + i++; if (ch == '0') { continue; } if (ch == '1') { - mask[n - 1] |= 1; + CPU_SET(i - 1, &mask[n - 1]); continue; } @@ -1347,43 +1362,57 @@ ngx_set_cpu_affinity(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) } -uint64_t +ngx_cpuset_t * ngx_get_cpu_affinity(ngx_uint_t n) { - uint64_t mask; - ngx_uint_t i; +#if (NGX_HAVE_CPU_AFFINITY) + ngx_uint_t i, j; + ngx_cpuset_t *mask; ngx_core_conf_t *ccf; + static ngx_cpuset_t result; + ccf = (ngx_core_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, ngx_core_module); if (ccf->cpu_affinity == NULL) { - return 0; + return NULL; } if (ccf->cpu_affinity_auto) { - mask = ccf->cpu_affinity[ccf->cpu_affinity_n - 1]; + mask = &ccf->cpu_affinity[ccf->cpu_affinity_n - 1]; - if (mask == 0) { - return 0; - } + for (i = 0, j = n; /* void */ ; i++) { - for (i = 0; /* void */ ; i++) { - if ((mask & ((uint64_t) 1 << (i % 64))) && n-- == 0) { + if (CPU_ISSET(i % CPU_SETSIZE, mask) && j-- == 0) { break; } + if (i == CPU_SETSIZE && j == n) { + /* empty mask */ + return NULL; + } + /* void */ } - return (uint64_t) 1 << (i % 64); + CPU_ZERO(&result); + CPU_SET(i % CPU_SETSIZE, &result); + + return &result; } if (ccf->cpu_affinity_n > n) { - return ccf->cpu_affinity[n]; + return &ccf->cpu_affinity[n]; } - return ccf->cpu_affinity[ccf->cpu_affinity_n - 1]; + return &ccf->cpu_affinity[ccf->cpu_affinity_n - 1]; + +#else + + return NULL; + +#endif } diff --git a/src/core/nginx.h b/src/core/nginx.h index e416e90..dec7b88 100644 --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1009011 -#define NGINX_VERSION "1.9.11" +#define nginx_version 1009012 +#define NGINX_VERSION "1.9.12" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD diff --git a/src/core/ngx_cycle.h b/src/core/ngx_cycle.h index 27401d0..cfdbb55 100644 --- a/src/core/ngx_cycle.h +++ b/src/core/ngx_cycle.h @@ -94,7 +94,7 @@ typedef struct { ngx_uint_t cpu_affinity_auto; ngx_uint_t cpu_affinity_n; - uint64_t *cpu_affinity; + ngx_cpuset_t *cpu_affinity; char *username; ngx_uid_t user; @@ -121,7 +121,7 @@ ngx_int_t ngx_signal_process(ngx_cycle_t *cycle, char *sig); void ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user); char **ngx_set_environment(ngx_cycle_t *cycle, ngx_uint_t *last); ngx_pid_t ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv); -uint64_t ngx_get_cpu_affinity(ngx_uint_t n); +ngx_cpuset_t *ngx_get_cpu_affinity(ngx_uint_t n); ngx_shm_zone_t *ngx_shared_memory_add(ngx_conf_t *cf, ngx_str_t *name, size_t size, void *tag); diff --git a/src/core/ngx_module.c b/src/core/ngx_module.c index 1e947c9..f5ec86a 100644 --- a/src/core/ngx_module.c +++ b/src/core/ngx_module.c @@ -171,7 +171,7 @@ ngx_add_module(ngx_conf_t *cf, ngx_str_t *file, ngx_module_t *module, if (module->version != nginx_version) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "module \"%V\" version %ui instead of %ui", - file, module->version, nginx_version); + file, module->version, (ngx_uint_t) nginx_version); return NGX_ERROR; } diff --git a/src/core/ngx_module.h b/src/core/ngx_module.h index cd28c49..3e74def 100644 --- a/src/core/ngx_module.h +++ b/src/core/ngx_module.h @@ -253,7 +253,7 @@ struct ngx_module_s { ngx_uint_t spare1; ngx_uint_t version; - char *signature; + const char *signature; void *ctx; ngx_command_t *commands; diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c index 57dfc6c..de10d48 100644 --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -1767,6 +1767,19 @@ ngx_ssl_shutdown(ngx_connection_t *c) int n, sslerr, mode; ngx_err_t err; + if (SSL_in_init(c->ssl->connection)) { + /* + * OpenSSL 1.0.2f complains if SSL_shutdown() is called during + * an SSL handshake, while previous versions always return 0. + * Avoid calling SSL_shutdown() if handshake wasn't completed. + */ + + SSL_free(c->ssl->connection); + c->ssl = NULL; + + return NGX_OK; + } + if (c->timedout) { mode = SSL_RECEIVED_SHUTDOWN|SSL_SENT_SHUTDOWN; SSL_set_quiet_shutdown(c->ssl->connection, 1); @@ -1797,7 +1810,7 @@ ngx_ssl_shutdown(ngx_connection_t *c) sslerr = 0; - /* SSL_shutdown() never returns -1, on error it returns 0 */ + /* before 0.9.8m SSL_shutdown() returned 0 instead of -1 on errors */ if (n != 1 && ERR_peek_error()) { sslerr = SSL_get_error(c->ssl->connection, n); diff --git a/src/http/modules/ngx_http_headers_filter_module.c b/src/http/modules/ngx_http_headers_filter_module.c index 985e5b3..6738afe 100644 --- a/src/http/modules/ngx_http_headers_filter_module.c +++ b/src/http/modules/ngx_http_headers_filter_module.c @@ -712,17 +712,17 @@ ngx_http_headers_add(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) if (value[2].len == 0) { ngx_memzero(&hv->value, sizeof(ngx_http_complex_value_t)); - return NGX_CONF_OK; - } - ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + } else { + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); - ccv.cf = cf; - ccv.value = &value[2]; - ccv.complex_value = &hv->value; + ccv.cf = cf; + ccv.value = &value[2]; + ccv.complex_value = &hv->value; - if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { - return NGX_CONF_ERROR; + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } } if (cf->args->nelts == 3) { diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c index 99e9325..fd790e1 100644 --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -1351,12 +1351,11 @@ ngx_http_process_request_headers(ngx_event_t *rev) continue; } - /* rc == NGX_HTTP_PARSE_INVALID_HEADER: "\r" is not followed by "\n" */ + /* rc == NGX_HTTP_PARSE_INVALID_HEADER */ ngx_log_error(NGX_LOG_INFO, c->log, 0, - "client sent invalid header line: \"%*s\\r...\"", - r->header_end - r->header_name_start, - r->header_name_start); + "client sent invalid header line"); + ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); return; } @@ -2574,12 +2573,6 @@ ngx_http_set_write_handler(ngx_http_request_t *r) ngx_http_test_reading; r->write_event_handler = ngx_http_writer; -#if (NGX_HTTP_V2) - if (r->stream) { - return NGX_OK; - } -#endif - wev = r->connection->write; if (wev->ready && wev->delayed) { @@ -2665,12 +2658,6 @@ ngx_http_writer(ngx_http_request_t *r) if (r->buffered || r->postponed || (r == r->main && c->buffered)) { -#if (NGX_HTTP_V2) - if (r->stream) { - return; - } -#endif - if (!wev->delayed) { ngx_add_timer(wev, clcf->send_timeout); } diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c index 4e378c9..4c4a4e7 100644 --- a/src/http/v2/ngx_http_v2.c +++ b/src/http/v2/ngx_http_v2.c @@ -112,10 +112,10 @@ static u_char *ngx_http_v2_state_skip_padded(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end); static u_char *ngx_http_v2_state_skip(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end); -static u_char *ngx_http_v2_state_skip_headers(ngx_http_v2_connection_t *h2c, - u_char *pos, u_char *end); static u_char *ngx_http_v2_state_save(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end, ngx_http_v2_handler_pt handler); +static u_char *ngx_http_v2_state_headers_save(ngx_http_v2_connection_t *h2c, + u_char *pos, u_char *end, ngx_http_v2_handler_pt handler); static u_char *ngx_http_v2_connection_error(ngx_http_v2_connection_t *h2c, ngx_uint_t err); @@ -164,6 +164,7 @@ static ngx_int_t ngx_http_v2_cookie(ngx_http_request_t *r, static ngx_int_t ngx_http_v2_construct_cookie_header(ngx_http_request_t *r); static void ngx_http_v2_run_request(ngx_http_request_t *r); static ngx_int_t ngx_http_v2_init_request_body(ngx_http_request_t *r); +static void ngx_http_v2_read_client_request_body_handler(ngx_http_request_t *r); static ngx_int_t ngx_http_v2_terminate_stream(ngx_http_v2_connection_t *h2c, ngx_http_v2_stream_t *stream, ngx_uint_t status); @@ -432,6 +433,10 @@ ngx_http_v2_write_handler(ngx_event_t *wev) "run http2 stream %ui", stream->node->id); wev = stream->request->connection->write; + + wev->active = 0; + wev->ready = 1; + wev->handler(wev); } @@ -885,6 +890,7 @@ ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos, ngx_buf_t *buf; ngx_int_t rc; ngx_temp_file_t *tf; + ngx_connection_t *fc; ngx_http_request_t *r; ngx_http_v2_stream_t *stream; ngx_http_request_body_t *rb; @@ -921,6 +927,7 @@ ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos, return ngx_http_v2_state_skip_padded(h2c, pos, end); } + fc = r->connection; rb = r->request_body; tf = rb->temp_file; buf = rb->buf; @@ -931,7 +938,7 @@ ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos, if (r->headers_in.content_length_n != -1 && r->headers_in.content_length_n < rb->rest) { - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + ngx_log_error(NGX_LOG_INFO, fc->log, 0, "client intended to send body data " "larger than declared"); @@ -944,7 +951,7 @@ ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos, if (clcf->client_max_body_size && clcf->client_max_body_size < rb->rest) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + ngx_log_error(NGX_LOG_ERR, fc->log, 0, "client intended to send " "too large chunked body: %O bytes", rb->rest); @@ -984,6 +991,11 @@ ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos, } if (h2c->state.length) { + if (rb->post_handler) { + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + ngx_add_timer(fc->read, clcf->client_body_timeout); + } + return ngx_http_v2_state_save(h2c, pos, end, ngx_http_v2_state_read_data); } @@ -995,7 +1007,7 @@ ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos, r->headers_in.content_length_n = rb->rest; } else if (r->headers_in.content_length_n != rb->rest) { - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + ngx_log_error(NGX_LOG_INFO, fc->log, 0, "client prematurely closed stream: " "only %O out of %O bytes of request body received", rb->rest, r->headers_in.content_length_n); @@ -1015,9 +1027,17 @@ ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos, } if (rb->post_handler) { + if (fc->read->timer_set) { + ngx_del_timer(fc->read); + } + r->read_event_handler = ngx_http_block_reading; rb->post_handler(r); } + + } else if (rb->post_handler) { + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + ngx_add_timer(fc->read, clcf->client_body_timeout); } if (h2c->state.padding) { @@ -1029,6 +1049,9 @@ ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos, error: if (rb->post_handler) { + if (fc->read->timer_set) { + ngx_del_timer(fc->read); + } if (stream->skip_data == NGX_HTTP_V2_DATA_ERROR) { rc = (r->headers_in.content_length_n == -1) @@ -1133,6 +1156,11 @@ ngx_http_v2_state_headers(ngx_http_v2_connection_t *h2c, u_char *pos, h2c->last_sid = h2c->state.sid; + h2c->state.pool = ngx_create_pool(1024, h2c->connection->log); + if (h2c->state.pool == NULL) { + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR); + } + if (depend == h2c->state.sid) { ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, "client sent HEADERS frame for stream %ui " @@ -1146,7 +1174,7 @@ ngx_http_v2_state_headers(ngx_http_v2_connection_t *h2c, u_char *pos, NGX_HTTP_V2_INTERNAL_ERROR); } - return ngx_http_v2_state_skip_headers(h2c, pos, end); + return ngx_http_v2_state_header_block(h2c, pos, end); } h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, @@ -1166,7 +1194,7 @@ ngx_http_v2_state_headers(ngx_http_v2_connection_t *h2c, u_char *pos, NGX_HTTP_V2_INTERNAL_ERROR); } - return ngx_http_v2_state_skip_headers(h2c, pos, end); + return ngx_http_v2_state_header_block(h2c, pos, end); } node = ngx_http_v2_get_node_by_id(h2c, h2c->state.sid, 1); @@ -1185,6 +1213,11 @@ ngx_http_v2_state_headers(ngx_http_v2_connection_t *h2c, u_char *pos, return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR); } + h2c->state.stream = stream; + + stream->pool = h2c->state.pool; + h2c->state.keep_pool = 1; + stream->request->request_length = h2c->state.length; stream->in_closed = h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG; @@ -1192,9 +1225,6 @@ ngx_http_v2_state_headers(ngx_http_v2_connection_t *h2c, u_char *pos, node->stream = stream; - h2c->state.stream = stream; - h2c->state.pool = stream->request->pool; - if (priority || node->parent == NULL) { node->weight = weight; ngx_http_v2_set_dependency(h2c, node, depend, excl); @@ -1213,8 +1243,8 @@ ngx_http_v2_state_header_block(ngx_http_v2_connection_t *h2c, u_char *pos, ngx_uint_t indexed, size_update, prefix; if (end - pos < 1) { - return ngx_http_v2_state_save(h2c, pos, end, - ngx_http_v2_state_header_block); + return ngx_http_v2_state_headers_save(h2c, pos, end, + ngx_http_v2_state_header_block); } if (!(h2c->state.flags & NGX_HTTP_V2_END_HEADERS_FLAG) @@ -1257,8 +1287,8 @@ ngx_http_v2_state_header_block(ngx_http_v2_connection_t *h2c, u_char *pos, if (value < 0) { if (value == NGX_AGAIN) { - return ngx_http_v2_state_save(h2c, pos, end, - ngx_http_v2_state_header_block); + return ngx_http_v2_state_headers_save(h2c, pos, end, + ngx_http_v2_state_header_block); } if (value == NGX_DECLINED) { @@ -1328,8 +1358,8 @@ ngx_http_v2_state_field_len(ngx_http_v2_connection_t *h2c, u_char *pos, } if (end - pos < 1) { - return ngx_http_v2_state_save(h2c, pos, end, - ngx_http_v2_state_field_len); + return ngx_http_v2_state_headers_save(h2c, pos, end, + ngx_http_v2_state_field_len); } huff = *pos >> 7; @@ -1337,8 +1367,8 @@ ngx_http_v2_state_field_len(ngx_http_v2_connection_t *h2c, u_char *pos, if (len < 0) { if (len == NGX_AGAIN) { - return ngx_http_v2_state_save(h2c, pos, end, - ngx_http_v2_state_field_len); + return ngx_http_v2_state_headers_save(h2c, pos, end, + ngx_http_v2_state_field_len); } if (len == NGX_DECLINED) { @@ -1430,8 +1460,8 @@ ngx_http_v2_state_field_huff(ngx_http_v2_connection_t *h2c, u_char *pos, } if (h2c->state.length) { - return ngx_http_v2_state_save(h2c, pos, end, - ngx_http_v2_state_field_huff); + return ngx_http_v2_state_headers_save(h2c, pos, end, + ngx_http_v2_state_field_huff); } if (h2c->state.flags & NGX_HTTP_V2_END_HEADERS_FLAG) { @@ -1475,8 +1505,8 @@ ngx_http_v2_state_field_raw(ngx_http_v2_connection_t *h2c, u_char *pos, } if (h2c->state.length) { - return ngx_http_v2_state_save(h2c, pos, end, - ngx_http_v2_state_field_raw); + return ngx_http_v2_state_headers_save(h2c, pos, end, + ngx_http_v2_state_field_raw); } if (h2c->state.flags & NGX_HTTP_V2_END_HEADERS_FLAG) { @@ -1686,7 +1716,6 @@ ngx_http_v2_state_process_header(ngx_http_v2_connection_t *h2c, u_char *pos, error: h2c->state.stream = NULL; - h2c->state.pool = NULL; return ngx_http_v2_state_header_complete(h2c, pos, end); } @@ -1699,8 +1728,7 @@ ngx_http_v2_state_header_complete(ngx_http_v2_connection_t *h2c, u_char *pos, ngx_http_v2_stream_t *stream; if (h2c->state.length) { - h2c->state.handler = h2c->state.pool ? ngx_http_v2_state_header_block - : ngx_http_v2_state_skip_headers; + h2c->state.handler = ngx_http_v2_state_header_block; return pos; } @@ -1713,12 +1741,14 @@ ngx_http_v2_state_header_complete(ngx_http_v2_connection_t *h2c, u_char *pos, if (stream) { ngx_http_v2_run_request(stream->request); + } - } else if (h2c->state.pool) { + if (!h2c->state.keep_pool) { ngx_destroy_pool(h2c->state.pool); } h2c->state.pool = NULL; + h2c->state.keep_pool = 0; if (h2c->state.padding) { return ngx_http_v2_state_skip_padded(h2c, pos, end); @@ -1749,7 +1779,7 @@ ngx_http_v2_handle_continuation(ngx_http_v2_connection_t *h2c, u_char *pos, } if ((size_t) (end - pos) < len + NGX_HTTP_V2_FRAME_HEADER_SIZE) { - return ngx_http_v2_state_save(h2c, pos, end, handler); + return ngx_http_v2_state_headers_save(h2c, pos, end, handler); } p = pos + len; @@ -2224,8 +2254,10 @@ ngx_http_v2_state_window_update(ngx_http_v2_connection_t *h2c, u_char *pos, wev = stream->request->connection->write; - if (!wev->timer_set) { - wev->delayed = 0; + wev->active = 0; + wev->ready = 1; + + if (!wev->delayed) { wev->handler(wev); } } @@ -2257,8 +2289,10 @@ ngx_http_v2_state_window_update(ngx_http_v2_connection_t *h2c, u_char *pos, wev = stream->request->connection->write; - if (!wev->timer_set) { - wev->delayed = 0; + wev->active = 0; + wev->ready = 1; + + if (!wev->delayed) { wev->handler(wev); if (h2c->send_window == 0) { @@ -2336,19 +2370,6 @@ ngx_http_v2_state_skip(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end) } -static u_char * -ngx_http_v2_state_skip_headers(ngx_http_v2_connection_t *h2c, u_char *pos, - u_char *end) -{ - h2c->state.pool = ngx_create_pool(1024, h2c->connection->log); - if (h2c->state.pool == NULL) { - return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR); - } - - return ngx_http_v2_state_header_block(h2c, pos, end); -} - - static u_char * ngx_http_v2_state_save(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end, ngx_http_v2_handler_pt handler) @@ -2378,6 +2399,28 @@ ngx_http_v2_state_save(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end, } +static u_char * +ngx_http_v2_state_headers_save(ngx_http_v2_connection_t *h2c, u_char *pos, + u_char *end, ngx_http_v2_handler_pt handler) +{ + ngx_event_t *rev; + ngx_http_request_t *r; + ngx_http_core_srv_conf_t *cscf; + + if (h2c->state.stream) { + r = h2c->state.stream->request; + rev = r->connection->read; + + if (!rev->timer_set) { + cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); + ngx_add_timer(rev, cscf->client_header_timeout); + } + } + + return ngx_http_v2_state_save(h2c, pos, end, handler); +} + + static u_char * ngx_http_v2_connection_error(ngx_http_v2_connection_t *h2c, ngx_uint_t err) @@ -2756,6 +2799,7 @@ ngx_http_v2_create_stream(ngx_http_v2_connection_t *h2c) ngx_memcpy(log, h2c->connection->log, sizeof(ngx_log_t)); log->data = ctx; + log->action = "reading client request headers"; ngx_memzero(rev, sizeof(ngx_event_t)); @@ -3562,7 +3606,8 @@ ngx_int_t ngx_http_v2_read_request_body(ngx_http_request_t *r, ngx_http_client_body_handler_pt post_handler) { - ngx_http_v2_stream_t *stream; + ngx_http_v2_stream_t *stream; + ngx_http_core_loc_conf_t *clcf; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http2 read request body"); @@ -3598,13 +3643,48 @@ ngx_http_v2_read_request_body(ngx_http_request_t *r, r->request_body->post_handler = post_handler; - r->read_event_handler = ngx_http_test_reading; + r->read_event_handler = ngx_http_v2_read_client_request_body_handler; r->write_event_handler = ngx_http_request_empty_handler; + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + ngx_add_timer(r->connection->read, clcf->client_body_timeout); + return NGX_AGAIN; } +static void +ngx_http_v2_read_client_request_body_handler(ngx_http_request_t *r) +{ + ngx_connection_t *fc; + + fc = r->connection; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0, + "http2 read client request body handler"); + + if (fc->read->timedout) { + ngx_log_error(NGX_LOG_INFO, fc->log, NGX_ETIMEDOUT, "client timed out"); + + fc->timedout = 1; + r->stream->skip_data = NGX_HTTP_V2_DATA_DISCARD; + + ngx_http_finalize_request(r, NGX_HTTP_REQUEST_TIME_OUT); + return; + } + + if (fc->error) { + ngx_log_error(NGX_LOG_INFO, fc->log, 0, + "client prematurely closed stream"); + + r->stream->skip_data = NGX_HTTP_V2_DATA_DISCARD; + + ngx_http_finalize_request(r, NGX_HTTP_CLIENT_CLOSED_REQUEST); + return; + } +} + + static ngx_int_t ngx_http_v2_terminate_stream(ngx_http_v2_connection_t *h2c, ngx_http_v2_stream_t *stream, ngx_uint_t status) @@ -3633,6 +3713,7 @@ ngx_http_v2_terminate_stream(ngx_http_v2_connection_t *h2c, void ngx_http_v2_close_stream(ngx_http_v2_stream_t *stream, ngx_int_t rc) { + ngx_pool_t *pool; ngx_event_t *ev; ngx_connection_t *fc; ngx_http_v2_node_t *node; @@ -3654,27 +3735,44 @@ ngx_http_v2_close_stream(ngx_http_v2_stream_t *stream, ngx_int_t rc) if (!stream->out_closed) { if (ngx_http_v2_send_rst_stream(h2c, node->id, - NGX_HTTP_V2_INTERNAL_ERROR) + fc->timedout ? NGX_HTTP_V2_PROTOCOL_ERROR + : NGX_HTTP_V2_INTERNAL_ERROR) != NGX_OK) { h2c->connection->error = 1; } } + if (h2c->state.stream == stream) { + h2c->state.stream = NULL; + } + node->stream = NULL; ngx_queue_insert_tail(&h2c->closed, &node->reuse); h2c->closed_nodes++; + /* + * This pool keeps decoded request headers which can be used by log phase + * handlers in ngx_http_free_request(). + * + * The pointer is stored into local variable because the stream object + * will be destroyed after a call to ngx_http_free_request(). + */ + pool = stream->pool; + ngx_http_free_request(stream->request, rc); - ev = fc->read; + if (pool != h2c->state.pool) { + ngx_destroy_pool(pool); - if (ev->active || ev->disabled) { - ngx_log_error(NGX_LOG_ALERT, h2c->connection->log, 0, - "fake read event was activated"); + } else { + /* pool will be destroyed when the complete header is parsed */ + h2c->state.keep_pool = 0; } + ev = fc->read; + if (ev->timer_set) { ngx_del_timer(ev); } @@ -3685,11 +3783,6 @@ ngx_http_v2_close_stream(ngx_http_v2_stream_t *stream, ngx_int_t rc) ev = fc->write; - if (ev->active || ev->disabled) { - ngx_log_error(NGX_LOG_ALERT, h2c->connection->log, 0, - "fake write event was activated"); - } - if (ev->timer_set) { ngx_del_timer(ev); } @@ -3723,9 +3816,18 @@ ngx_http_v2_close_stream_handler(ngx_event_t *ev) fc = ev->data; r = fc->data; - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0, "http2 close stream handler"); + if (ev->timedout) { + ngx_log_error(NGX_LOG_INFO, fc->log, NGX_ETIMEDOUT, "client timed out"); + + fc->timedout = 1; + + ngx_http_v2_close_stream(r->stream, NGX_HTTP_REQUEST_TIME_OUT); + return; + } + ngx_http_v2_close_stream(r->stream, 0); } @@ -3733,7 +3835,11 @@ ngx_http_v2_close_stream_handler(ngx_event_t *ev) static void ngx_http_v2_handle_connection_handler(ngx_event_t *rev) { - ngx_connection_t *c; + ngx_connection_t *c; + ngx_http_v2_connection_t *h2c; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, + "http2 handle connection handler"); rev->handler = ngx_http_v2_read_handler; @@ -3743,6 +3849,12 @@ ngx_http_v2_handle_connection_handler(ngx_event_t *rev) } c = rev->data; + h2c = c->data; + + if (h2c->last_out && ngx_http_v2_send_output_queue(h2c) == NGX_ERROR) { + ngx_http_v2_finalize_connection(h2c, 0); + return; + } ngx_http_v2_handle_connection(c->data); } @@ -3821,7 +3933,6 @@ ngx_http_v2_finalize_connection(ngx_http_v2_connection_t *h2c, if (h2c->state.stream) { h2c->state.stream->out_closed = 1; - h2c->state.pool = NULL; ngx_http_v2_close_stream(h2c->state.stream, NGX_HTTP_BAD_REQUEST); } @@ -3865,9 +3976,7 @@ ngx_http_v2_finalize_connection(ngx_http_v2_connection_t *h2c, if (stream->queued) { stream->queued = 0; - ev = fc->write; - ev->delayed = 0; } else { ev = fc->read; @@ -3936,8 +4045,10 @@ ngx_http_v2_adjust_windows(ngx_http_v2_connection_t *h2c, ssize_t delta) wev = stream->request->connection->write; - if (!wev->timer_set) { - wev->delayed = 0; + wev->active = 0; + wev->ready = 1; + + if (!wev->delayed) { wev->handler(wev); } } diff --git a/src/http/v2/ngx_http_v2.h b/src/http/v2/ngx_http_v2.h index 0f03922..5a791e6 100644 --- a/src/http/v2/ngx_http_v2.h +++ b/src/http/v2/ngx_http_v2.h @@ -73,6 +73,7 @@ typedef struct { unsigned flags:8; unsigned incomplete:1; + unsigned keep_pool:1; /* HPACK */ unsigned parse_name:1; @@ -186,6 +187,8 @@ struct ngx_http_v2_stream_s { size_t header_limit; + ngx_pool_t *pool; + unsigned handled:1; unsigned blocked:1; unsigned exhausted:1; @@ -274,6 +277,8 @@ ngx_int_t ngx_http_v2_table_size(ngx_http_v2_connection_t *h2c, size_t size); ngx_int_t ngx_http_v2_huff_decode(u_char *state, u_char *src, size_t len, u_char **dst, ngx_uint_t last, ngx_log_t *log); +size_t ngx_http_v2_huff_encode(u_char *src, size_t len, u_char *dst, + ngx_uint_t lower); #define ngx_http_v2_prefix(bits) ((1 << (bits)) - 1) diff --git a/src/http/v2/ngx_http_v2_filter_module.c b/src/http/v2/ngx_http_v2_filter_module.c index ea58979..caa835d 100644 --- a/src/http/v2/ngx_http_v2_filter_module.c +++ b/src/http/v2/ngx_http_v2_filter_module.c @@ -25,6 +25,11 @@ #define ngx_http_v2_indexed(i) (128 + (i)) #define ngx_http_v2_inc_indexed(i) (64 + (i)) +#define ngx_http_v2_write_name(dst, src, len, tmp) \ + ngx_http_v2_string_encode(dst, src, len, tmp, 1) +#define ngx_http_v2_write_value(dst, src, len, tmp) \ + ngx_http_v2_string_encode(dst, src, len, tmp, 0) + #define NGX_HTTP_V2_ENCODE_RAW 0 #define NGX_HTTP_V2_ENCODE_HUFF 0x80 @@ -46,6 +51,8 @@ #define NGX_HTTP_V2_VARY_INDEX 59 +static u_char *ngx_http_v2_string_encode(u_char *dst, u_char *src, size_t len, + u_char *tmp, ngx_uint_t lower); static u_char *ngx_http_v2_write_int(u_char *pos, ngx_uint_t prefix, ngx_uint_t value); static ngx_http_v2_out_frame_t *ngx_http_v2_create_headers_frame( @@ -119,8 +126,8 @@ static ngx_http_output_header_filter_pt ngx_http_next_header_filter; static ngx_int_t ngx_http_v2_header_filter(ngx_http_request_t *r) { - u_char status, *pos, *start, *p; - size_t len; + u_char status, *pos, *start, *p, *tmp; + size_t len, tmp_len; ngx_str_t host, location; ngx_uint_t i, port; ngx_list_part_t *part; @@ -136,6 +143,14 @@ ngx_http_v2_header_filter(ngx_http_request_t *r) #endif u_char addr[NGX_SOCKADDR_STRLEN]; + static const u_char nginx[5] = "\x84\xaa\x63\x55\xe7"; +#if (NGX_HTTP_GZIP) + static const u_char accept_encoding[12] = + "\x8b\x84\x84\x2d\x69\x5b\x05\x44\x3c\x86\xaa\x6f"; +#endif + + static size_t nginx_ver_len = ngx_http_v2_literal_size(NGINX_VER); + static u_char nginx_ver[ngx_http_v2_literal_size(NGINX_VER)]; if (!r->stream) { return ngx_http_next_header_filter(r); @@ -215,8 +230,7 @@ ngx_http_v2_header_filter(ngx_http_request_t *r) clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); if (r->headers_out.server == NULL) { - len += 1 + (clcf->server_tokens ? ngx_http_v2_literal_size(NGINX_VER) - : ngx_http_v2_literal_size("nginx")); + len += 1 + (clcf->server_tokens ? nginx_ver_len : sizeof(nginx)); } if (r->headers_out.date == NULL) { @@ -340,10 +354,12 @@ ngx_http_v2_header_filter(ngx_http_request_t *r) len += 1 + NGX_HTTP_V2_INT_OCTETS + r->headers_out.location->value.len; } + tmp_len = len; + #if (NGX_HTTP_GZIP) if (r->gzip_vary) { if (clcf->gzip_vary) { - len += 1 + ngx_http_v2_literal_size("Accept-Encoding"); + len += 1 + sizeof(accept_encoding); } else { r->gzip_vary = 0; @@ -371,14 +387,14 @@ ngx_http_v2_header_filter(ngx_http_request_t *r) } if (header[i].key.len > NGX_HTTP_V2_MAX_FIELD) { - ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0, + ngx_log_error(NGX_LOG_CRIT, fc->log, 0, "too long response header name: \"%V\"", &header[i].key); return NGX_ERROR; } if (header[i].value.len > NGX_HTTP_V2_MAX_FIELD) { - ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0, + ngx_log_error(NGX_LOG_CRIT, fc->log, 0, "too long response header value: \"%V: %V\"", &header[i].key, &header[i].value); return NGX_ERROR; @@ -386,15 +402,29 @@ ngx_http_v2_header_filter(ngx_http_request_t *r) len += 1 + NGX_HTTP_V2_INT_OCTETS + header[i].key.len + NGX_HTTP_V2_INT_OCTETS + header[i].value.len; + + if (header[i].key.len > tmp_len) { + tmp_len = header[i].key.len; + } + + if (header[i].value.len > tmp_len) { + tmp_len = header[i].value.len; + } } - pos = ngx_palloc(r->pool, len); - if (pos == NULL) { + tmp = ngx_palloc(r->pool, tmp_len); + pos = ngx_pnalloc(r->pool, len); + + if (pos == NULL || tmp == NULL) { return NGX_ERROR; } start = pos; + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0, + "http2 output header: \":status: %03ui\"", + r->headers_out.status); + if (status) { *pos++ = status; @@ -405,24 +435,34 @@ ngx_http_v2_header_filter(ngx_http_request_t *r) } if (r->headers_out.server == NULL) { + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0, + "http2 output header: \"server: %s\"", + clcf->server_tokens ? NGINX_VER : "nginx"); + *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_SERVER_INDEX); if (clcf->server_tokens) { - *pos++ = NGX_HTTP_V2_ENCODE_RAW | (sizeof(NGINX_VER) - 1); - pos = ngx_cpymem(pos, NGINX_VER, sizeof(NGINX_VER) - 1); + if (nginx_ver[0] == '\0') { + p = ngx_http_v2_write_value(nginx_ver, (u_char *) NGINX_VER, + sizeof(NGINX_VER) - 1, tmp); + nginx_ver_len = p - nginx_ver; + } + + pos = ngx_cpymem(pos, nginx_ver, nginx_ver_len); } else { - *pos++ = NGX_HTTP_V2_ENCODE_RAW | (sizeof("nginx") - 1); - pos = ngx_cpymem(pos, "nginx", sizeof("nginx") - 1); + pos = ngx_cpymem(pos, nginx, sizeof(nginx)); } } if (r->headers_out.date == NULL) { - *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_DATE_INDEX); - *pos++ = (u_char) ngx_cached_http_time.len; + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0, + "http2 output header: \"date: %V\"", + &ngx_cached_http_time); - pos = ngx_cpymem(pos, ngx_cached_http_time.data, - ngx_cached_http_time.len); + *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_DATE_INDEX); + pos = ngx_http_v2_write_value(pos, ngx_cached_http_time.data, + ngx_cached_http_time.len, tmp); } if (r->headers_out.content_type.len) { @@ -431,39 +471,43 @@ ngx_http_v2_header_filter(ngx_http_request_t *r) if (r->headers_out.content_type_len == r->headers_out.content_type.len && r->headers_out.charset.len) { - *pos = NGX_HTTP_V2_ENCODE_RAW; - pos = ngx_http_v2_write_int(pos, ngx_http_v2_prefix(7), - r->headers_out.content_type.len - + sizeof("; charset=") - 1 - + r->headers_out.charset.len); + len = r->headers_out.content_type.len + sizeof("; charset=") - 1 + + r->headers_out.charset.len; - p = pos; + p = ngx_pnalloc(r->pool, len); + if (p == NULL) { + return NGX_ERROR; + } - pos = ngx_cpymem(pos, r->headers_out.content_type.data, - r->headers_out.content_type.len); + p = ngx_cpymem(p, r->headers_out.content_type.data, + r->headers_out.content_type.len); - pos = ngx_cpymem(pos, "; charset=", sizeof("; charset=") - 1); + p = ngx_cpymem(p, "; charset=", sizeof("; charset=") - 1); - pos = ngx_cpymem(pos, r->headers_out.charset.data, - r->headers_out.charset.len); + p = ngx_cpymem(p, r->headers_out.charset.data, + r->headers_out.charset.len); - /* update r->headers_out.content_type for possible logging */ + /* updated r->headers_out.content_type is also needed for logging */ - r->headers_out.content_type.len = pos - p; - r->headers_out.content_type.data = p; - - } else { - *pos = NGX_HTTP_V2_ENCODE_RAW; - pos = ngx_http_v2_write_int(pos, ngx_http_v2_prefix(7), - r->headers_out.content_type.len); - pos = ngx_cpymem(pos, r->headers_out.content_type.data, - r->headers_out.content_type.len); + r->headers_out.content_type.len = len; + r->headers_out.content_type.data = p - len; } + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0, + "http2 output header: \"content-type: %V\"", + &r->headers_out.content_type); + + pos = ngx_http_v2_write_value(pos, r->headers_out.content_type.data, + r->headers_out.content_type.len, tmp); } if (r->headers_out.content_length == NULL && r->headers_out.content_length_n >= 0) { + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0, + "http2 output header: \"content-length: %O\"", + r->headers_out.content_length_n); + *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_CONTENT_LENGTH_INDEX); p = pos; @@ -476,26 +520,37 @@ ngx_http_v2_header_filter(ngx_http_request_t *r) { *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_LAST_MODIFIED_INDEX); - *pos++ = NGX_HTTP_V2_ENCODE_RAW - | (sizeof("Wed, 31 Dec 1986 18:00:00 GMT") - 1); - pos = ngx_http_time(pos, r->headers_out.last_modified_time); + ngx_http_time(pos, r->headers_out.last_modified_time); + len = sizeof("Wed, 31 Dec 1986 18:00:00 GMT") - 1; + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, fc->log, 0, + "http2 output header: \"last-modified: %*s\"", + len, pos); + + /* + * Date will always be encoded using huffman in the temporary buffer, + * so it's safe here to use src and dst pointing to the same address. + */ + pos = ngx_http_v2_write_value(pos, pos, len, tmp); } if (r->headers_out.location && r->headers_out.location->value.len) { - *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_LOCATION_INDEX); + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0, + "http2 output header: \"location: %V\"", + &r->headers_out.location->value); - *pos = NGX_HTTP_V2_ENCODE_RAW; - pos = ngx_http_v2_write_int(pos, ngx_http_v2_prefix(7), - r->headers_out.location->value.len); - pos = ngx_cpymem(pos, r->headers_out.location->value.data, - r->headers_out.location->value.len); + *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_LOCATION_INDEX); + pos = ngx_http_v2_write_value(pos, r->headers_out.location->value.data, + r->headers_out.location->value.len, tmp); } #if (NGX_HTTP_GZIP) if (r->gzip_vary) { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0, + "http2 output header: \"vary: Accept-Encoding\""); + *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_VARY_INDEX); - *pos++ = NGX_HTTP_V2_ENCODE_RAW | (sizeof("Accept-Encoding") - 1); - pos = ngx_cpymem(pos, "Accept-Encoding", sizeof("Accept-Encoding") - 1); + pos = ngx_cpymem(pos, accept_encoding, sizeof(accept_encoding)); } #endif @@ -518,18 +573,23 @@ ngx_http_v2_header_filter(ngx_http_request_t *r) continue; } +#if (NGX_DEBUG) + if (fc->log->log_level & NGX_LOG_DEBUG_HTTP) { + ngx_strlow(tmp, header[i].key.data, header[i].key.len); + + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, fc->log, 0, + "http2 output header: \"%*s: %V\"", + header[i].key.len, tmp, &header[i].value); + } +#endif + *pos++ = 0; - *pos = NGX_HTTP_V2_ENCODE_RAW; - pos = ngx_http_v2_write_int(pos, ngx_http_v2_prefix(7), - header[i].key.len); - ngx_strlow(pos, header[i].key.data, header[i].key.len); - pos += header[i].key.len; + pos = ngx_http_v2_write_name(pos, header[i].key.data, + header[i].key.len, tmp); - *pos = NGX_HTTP_V2_ENCODE_RAW; - pos = ngx_http_v2_write_int(pos, ngx_http_v2_prefix(7), - header[i].value.len); - pos = ngx_cpymem(pos, header[i].value.data, header[i].value.len); + pos = ngx_http_v2_write_value(pos, header[i].value.data, + header[i].value.len, tmp); } frame = ngx_http_v2_create_headers_frame(r, start, pos); @@ -556,6 +616,32 @@ ngx_http_v2_header_filter(ngx_http_request_t *r) } +static u_char * +ngx_http_v2_string_encode(u_char *dst, u_char *src, size_t len, u_char *tmp, + ngx_uint_t lower) +{ + size_t hlen; + + hlen = ngx_http_v2_huff_encode(src, len, tmp, lower); + + if (hlen > 0) { + *dst = NGX_HTTP_V2_ENCODE_HUFF; + dst = ngx_http_v2_write_int(dst, ngx_http_v2_prefix(7), hlen); + return ngx_cpymem(dst, tmp, hlen); + } + + *dst = NGX_HTTP_V2_ENCODE_RAW; + dst = ngx_http_v2_write_int(dst, ngx_http_v2_prefix(7), len); + + if (lower) { + ngx_strlow(dst, src, len); + return dst + len; + } + + return ngx_cpymem(dst, src, len); +} + + static u_char * ngx_http_v2_write_int(u_char *pos, ngx_uint_t prefix, ngx_uint_t value) { @@ -713,7 +799,9 @@ ngx_http_v2_send_chain(ngx_connection_t *fc, ngx_chain_t *in, off_t limit) if (in == NULL) { if (stream->queued) { - fc->write->delayed = 1; + fc->write->active = 1; + fc->write->ready = 0; + } else { fc->buffered &= ~NGX_HTTP_V2_BUFFERED; } @@ -724,7 +812,8 @@ ngx_http_v2_send_chain(ngx_connection_t *fc, ngx_chain_t *in, off_t limit) h2c = stream->connection; if (size && ngx_http_v2_flow_control(h2c, stream) == NGX_DECLINED) { - fc->write->delayed = 1; + fc->write->active = 1; + fc->write->ready = 0; return in; } @@ -861,7 +950,8 @@ ngx_http_v2_send_chain(ngx_connection_t *fc, ngx_chain_t *in, off_t limit) } if (in && ngx_http_v2_flow_control(h2c, stream) == NGX_DECLINED) { - fc->write->delayed = 1; + fc->write->active = 1; + fc->write->ready = 0; } return in; @@ -992,7 +1082,8 @@ ngx_http_v2_filter_send(ngx_connection_t *fc, ngx_http_v2_stream_t *stream) if (stream->queued) { fc->buffered |= NGX_HTTP_V2_BUFFERED; - fc->write->delayed = 1; + fc->write->active = 1; + fc->write->ready = 0; return NGX_AGAIN; } @@ -1230,14 +1321,7 @@ ngx_http_v2_handle_stream(ngx_http_v2_connection_t *h2c, wev = stream->request->connection->write; - /* - * This timer can only be set if the stream was delayed because of rate - * limit. In that case the event should be triggered by the timer. - */ - - if (!wev->timer_set) { - wev->delayed = 0; - + if (!wev->delayed) { stream->handled = 1; ngx_queue_insert_tail(&h2c->posted, &stream->queue); } diff --git a/src/http/v2/ngx_http_v2_huff_encode.c b/src/http/v2/ngx_http_v2_huff_encode.c index 6c412cf..3f822cd 100644 --- a/src/http/v2/ngx_http_v2_huff_encode.c +++ b/src/http/v2/ngx_http_v2_huff_encode.c @@ -2,9 +2,253 @@ /* * Copyright (C) Nginx, Inc. * Copyright (C) Valentin V. Bartenev + * Copyright (C) 2015 Vlad Krasnov */ #include #include #include + + +typedef struct { + uint32_t code; + uint32_t len; +} ngx_http_v2_huff_encode_code_t; + + +static ngx_http_v2_huff_encode_code_t ngx_http_v2_huff_encode_table[256] = +{ + {0x00001ff8, 13}, {0x007fffd8, 23}, {0x0fffffe2, 28}, {0x0fffffe3, 28}, + {0x0fffffe4, 28}, {0x0fffffe5, 28}, {0x0fffffe6, 28}, {0x0fffffe7, 28}, + {0x0fffffe8, 28}, {0x00ffffea, 24}, {0x3ffffffc, 30}, {0x0fffffe9, 28}, + {0x0fffffea, 28}, {0x3ffffffd, 30}, {0x0fffffeb, 28}, {0x0fffffec, 28}, + {0x0fffffed, 28}, {0x0fffffee, 28}, {0x0fffffef, 28}, {0x0ffffff0, 28}, + {0x0ffffff1, 28}, {0x0ffffff2, 28}, {0x3ffffffe, 30}, {0x0ffffff3, 28}, + {0x0ffffff4, 28}, {0x0ffffff5, 28}, {0x0ffffff6, 28}, {0x0ffffff7, 28}, + {0x0ffffff8, 28}, {0x0ffffff9, 28}, {0x0ffffffa, 28}, {0x0ffffffb, 28}, + {0x00000014, 6}, {0x000003f8, 10}, {0x000003f9, 10}, {0x00000ffa, 12}, + {0x00001ff9, 13}, {0x00000015, 6}, {0x000000f8, 8}, {0x000007fa, 11}, + {0x000003fa, 10}, {0x000003fb, 10}, {0x000000f9, 8}, {0x000007fb, 11}, + {0x000000fa, 8}, {0x00000016, 6}, {0x00000017, 6}, {0x00000018, 6}, + {0x00000000, 5}, {0x00000001, 5}, {0x00000002, 5}, {0x00000019, 6}, + {0x0000001a, 6}, {0x0000001b, 6}, {0x0000001c, 6}, {0x0000001d, 6}, + {0x0000001e, 6}, {0x0000001f, 6}, {0x0000005c, 7}, {0x000000fb, 8}, + {0x00007ffc, 15}, {0x00000020, 6}, {0x00000ffb, 12}, {0x000003fc, 10}, + {0x00001ffa, 13}, {0x00000021, 6}, {0x0000005d, 7}, {0x0000005e, 7}, + {0x0000005f, 7}, {0x00000060, 7}, {0x00000061, 7}, {0x00000062, 7}, + {0x00000063, 7}, {0x00000064, 7}, {0x00000065, 7}, {0x00000066, 7}, + {0x00000067, 7}, {0x00000068, 7}, {0x00000069, 7}, {0x0000006a, 7}, + {0x0000006b, 7}, {0x0000006c, 7}, {0x0000006d, 7}, {0x0000006e, 7}, + {0x0000006f, 7}, {0x00000070, 7}, {0x00000071, 7}, {0x00000072, 7}, + {0x000000fc, 8}, {0x00000073, 7}, {0x000000fd, 8}, {0x00001ffb, 13}, + {0x0007fff0, 19}, {0x00001ffc, 13}, {0x00003ffc, 14}, {0x00000022, 6}, + {0x00007ffd, 15}, {0x00000003, 5}, {0x00000023, 6}, {0x00000004, 5}, + {0x00000024, 6}, {0x00000005, 5}, {0x00000025, 6}, {0x00000026, 6}, + {0x00000027, 6}, {0x00000006, 5}, {0x00000074, 7}, {0x00000075, 7}, + {0x00000028, 6}, {0x00000029, 6}, {0x0000002a, 6}, {0x00000007, 5}, + {0x0000002b, 6}, {0x00000076, 7}, {0x0000002c, 6}, {0x00000008, 5}, + {0x00000009, 5}, {0x0000002d, 6}, {0x00000077, 7}, {0x00000078, 7}, + {0x00000079, 7}, {0x0000007a, 7}, {0x0000007b, 7}, {0x00007ffe, 15}, + {0x000007fc, 11}, {0x00003ffd, 14}, {0x00001ffd, 13}, {0x0ffffffc, 28}, + {0x000fffe6, 20}, {0x003fffd2, 22}, {0x000fffe7, 20}, {0x000fffe8, 20}, + {0x003fffd3, 22}, {0x003fffd4, 22}, {0x003fffd5, 22}, {0x007fffd9, 23}, + {0x003fffd6, 22}, {0x007fffda, 23}, {0x007fffdb, 23}, {0x007fffdc, 23}, + {0x007fffdd, 23}, {0x007fffde, 23}, {0x00ffffeb, 24}, {0x007fffdf, 23}, + {0x00ffffec, 24}, {0x00ffffed, 24}, {0x003fffd7, 22}, {0x007fffe0, 23}, + {0x00ffffee, 24}, {0x007fffe1, 23}, {0x007fffe2, 23}, {0x007fffe3, 23}, + {0x007fffe4, 23}, {0x001fffdc, 21}, {0x003fffd8, 22}, {0x007fffe5, 23}, + {0x003fffd9, 22}, {0x007fffe6, 23}, {0x007fffe7, 23}, {0x00ffffef, 24}, + {0x003fffda, 22}, {0x001fffdd, 21}, {0x000fffe9, 20}, {0x003fffdb, 22}, + {0x003fffdc, 22}, {0x007fffe8, 23}, {0x007fffe9, 23}, {0x001fffde, 21}, + {0x007fffea, 23}, {0x003fffdd, 22}, {0x003fffde, 22}, {0x00fffff0, 24}, + {0x001fffdf, 21}, {0x003fffdf, 22}, {0x007fffeb, 23}, {0x007fffec, 23}, + {0x001fffe0, 21}, {0x001fffe1, 21}, {0x003fffe0, 22}, {0x001fffe2, 21}, + {0x007fffed, 23}, {0x003fffe1, 22}, {0x007fffee, 23}, {0x007fffef, 23}, + {0x000fffea, 20}, {0x003fffe2, 22}, {0x003fffe3, 22}, {0x003fffe4, 22}, + {0x007ffff0, 23}, {0x003fffe5, 22}, {0x003fffe6, 22}, {0x007ffff1, 23}, + {0x03ffffe0, 26}, {0x03ffffe1, 26}, {0x000fffeb, 20}, {0x0007fff1, 19}, + {0x003fffe7, 22}, {0x007ffff2, 23}, {0x003fffe8, 22}, {0x01ffffec, 25}, + {0x03ffffe2, 26}, {0x03ffffe3, 26}, {0x03ffffe4, 26}, {0x07ffffde, 27}, + {0x07ffffdf, 27}, {0x03ffffe5, 26}, {0x00fffff1, 24}, {0x01ffffed, 25}, + {0x0007fff2, 19}, {0x001fffe3, 21}, {0x03ffffe6, 26}, {0x07ffffe0, 27}, + {0x07ffffe1, 27}, {0x03ffffe7, 26}, {0x07ffffe2, 27}, {0x00fffff2, 24}, + {0x001fffe4, 21}, {0x001fffe5, 21}, {0x03ffffe8, 26}, {0x03ffffe9, 26}, + {0x0ffffffd, 28}, {0x07ffffe3, 27}, {0x07ffffe4, 27}, {0x07ffffe5, 27}, + {0x000fffec, 20}, {0x00fffff3, 24}, {0x000fffed, 20}, {0x001fffe6, 21}, + {0x003fffe9, 22}, {0x001fffe7, 21}, {0x001fffe8, 21}, {0x007ffff3, 23}, + {0x003fffea, 22}, {0x003fffeb, 22}, {0x01ffffee, 25}, {0x01ffffef, 25}, + {0x00fffff4, 24}, {0x00fffff5, 24}, {0x03ffffea, 26}, {0x007ffff4, 23}, + {0x03ffffeb, 26}, {0x07ffffe6, 27}, {0x03ffffec, 26}, {0x03ffffed, 26}, + {0x07ffffe7, 27}, {0x07ffffe8, 27}, {0x07ffffe9, 27}, {0x07ffffea, 27}, + {0x07ffffeb, 27}, {0x0ffffffe, 28}, {0x07ffffec, 27}, {0x07ffffed, 27}, + {0x07ffffee, 27}, {0x07ffffef, 27}, {0x07fffff0, 27}, {0x03ffffee, 26} +}; + + +/* same as above, but embeds lowercase transformation */ +static ngx_http_v2_huff_encode_code_t ngx_http_v2_huff_encode_table_lc[256] = +{ + {0x00001ff8, 13}, {0x007fffd8, 23}, {0x0fffffe2, 28}, {0x0fffffe3, 28}, + {0x0fffffe4, 28}, {0x0fffffe5, 28}, {0x0fffffe6, 28}, {0x0fffffe7, 28}, + {0x0fffffe8, 28}, {0x00ffffea, 24}, {0x3ffffffc, 30}, {0x0fffffe9, 28}, + {0x0fffffea, 28}, {0x3ffffffd, 30}, {0x0fffffeb, 28}, {0x0fffffec, 28}, + {0x0fffffed, 28}, {0x0fffffee, 28}, {0x0fffffef, 28}, {0x0ffffff0, 28}, + {0x0ffffff1, 28}, {0x0ffffff2, 28}, {0x3ffffffe, 30}, {0x0ffffff3, 28}, + {0x0ffffff4, 28}, {0x0ffffff5, 28}, {0x0ffffff6, 28}, {0x0ffffff7, 28}, + {0x0ffffff8, 28}, {0x0ffffff9, 28}, {0x0ffffffa, 28}, {0x0ffffffb, 28}, + {0x00000014, 6}, {0x000003f8, 10}, {0x000003f9, 10}, {0x00000ffa, 12}, + {0x00001ff9, 13}, {0x00000015, 6}, {0x000000f8, 8}, {0x000007fa, 11}, + {0x000003fa, 10}, {0x000003fb, 10}, {0x000000f9, 8}, {0x000007fb, 11}, + {0x000000fa, 8}, {0x00000016, 6}, {0x00000017, 6}, {0x00000018, 6}, + {0x00000000, 5}, {0x00000001, 5}, {0x00000002, 5}, {0x00000019, 6}, + {0x0000001a, 6}, {0x0000001b, 6}, {0x0000001c, 6}, {0x0000001d, 6}, + {0x0000001e, 6}, {0x0000001f, 6}, {0x0000005c, 7}, {0x000000fb, 8}, + {0x00007ffc, 15}, {0x00000020, 6}, {0x00000ffb, 12}, {0x000003fc, 10}, + {0x00001ffa, 13}, {0x00000003, 5}, {0x00000023, 6}, {0x00000004, 5}, + {0x00000024, 6}, {0x00000005, 5}, {0x00000025, 6}, {0x00000026, 6}, + {0x00000027, 6}, {0x00000006, 5}, {0x00000074, 7}, {0x00000075, 7}, + {0x00000028, 6}, {0x00000029, 6}, {0x0000002a, 6}, {0x00000007, 5}, + {0x0000002b, 6}, {0x00000076, 7}, {0x0000002c, 6}, {0x00000008, 5}, + {0x00000009, 5}, {0x0000002d, 6}, {0x00000077, 7}, {0x00000078, 7}, + {0x00000079, 7}, {0x0000007a, 7}, {0x0000007b, 7}, {0x00001ffb, 13}, + {0x0007fff0, 19}, {0x00001ffc, 13}, {0x00003ffc, 14}, {0x00000022, 6}, + {0x00007ffd, 15}, {0x00000003, 5}, {0x00000023, 6}, {0x00000004, 5}, + {0x00000024, 6}, {0x00000005, 5}, {0x00000025, 6}, {0x00000026, 6}, + {0x00000027, 6}, {0x00000006, 5}, {0x00000074, 7}, {0x00000075, 7}, + {0x00000028, 6}, {0x00000029, 6}, {0x0000002a, 6}, {0x00000007, 5}, + {0x0000002b, 6}, {0x00000076, 7}, {0x0000002c, 6}, {0x00000008, 5}, + {0x00000009, 5}, {0x0000002d, 6}, {0x00000077, 7}, {0x00000078, 7}, + {0x00000079, 7}, {0x0000007a, 7}, {0x0000007b, 7}, {0x00007ffe, 15}, + {0x000007fc, 11}, {0x00003ffd, 14}, {0x00001ffd, 13}, {0x0ffffffc, 28}, + {0x000fffe6, 20}, {0x003fffd2, 22}, {0x000fffe7, 20}, {0x000fffe8, 20}, + {0x003fffd3, 22}, {0x003fffd4, 22}, {0x003fffd5, 22}, {0x007fffd9, 23}, + {0x003fffd6, 22}, {0x007fffda, 23}, {0x007fffdb, 23}, {0x007fffdc, 23}, + {0x007fffdd, 23}, {0x007fffde, 23}, {0x00ffffeb, 24}, {0x007fffdf, 23}, + {0x00ffffec, 24}, {0x00ffffed, 24}, {0x003fffd7, 22}, {0x007fffe0, 23}, + {0x00ffffee, 24}, {0x007fffe1, 23}, {0x007fffe2, 23}, {0x007fffe3, 23}, + {0x007fffe4, 23}, {0x001fffdc, 21}, {0x003fffd8, 22}, {0x007fffe5, 23}, + {0x003fffd9, 22}, {0x007fffe6, 23}, {0x007fffe7, 23}, {0x00ffffef, 24}, + {0x003fffda, 22}, {0x001fffdd, 21}, {0x000fffe9, 20}, {0x003fffdb, 22}, + {0x003fffdc, 22}, {0x007fffe8, 23}, {0x007fffe9, 23}, {0x001fffde, 21}, + {0x007fffea, 23}, {0x003fffdd, 22}, {0x003fffde, 22}, {0x00fffff0, 24}, + {0x001fffdf, 21}, {0x003fffdf, 22}, {0x007fffeb, 23}, {0x007fffec, 23}, + {0x001fffe0, 21}, {0x001fffe1, 21}, {0x003fffe0, 22}, {0x001fffe2, 21}, + {0x007fffed, 23}, {0x003fffe1, 22}, {0x007fffee, 23}, {0x007fffef, 23}, + {0x000fffea, 20}, {0x003fffe2, 22}, {0x003fffe3, 22}, {0x003fffe4, 22}, + {0x007ffff0, 23}, {0x003fffe5, 22}, {0x003fffe6, 22}, {0x007ffff1, 23}, + {0x03ffffe0, 26}, {0x03ffffe1, 26}, {0x000fffeb, 20}, {0x0007fff1, 19}, + {0x003fffe7, 22}, {0x007ffff2, 23}, {0x003fffe8, 22}, {0x01ffffec, 25}, + {0x03ffffe2, 26}, {0x03ffffe3, 26}, {0x03ffffe4, 26}, {0x07ffffde, 27}, + {0x07ffffdf, 27}, {0x03ffffe5, 26}, {0x00fffff1, 24}, {0x01ffffed, 25}, + {0x0007fff2, 19}, {0x001fffe3, 21}, {0x03ffffe6, 26}, {0x07ffffe0, 27}, + {0x07ffffe1, 27}, {0x03ffffe7, 26}, {0x07ffffe2, 27}, {0x00fffff2, 24}, + {0x001fffe4, 21}, {0x001fffe5, 21}, {0x03ffffe8, 26}, {0x03ffffe9, 26}, + {0x0ffffffd, 28}, {0x07ffffe3, 27}, {0x07ffffe4, 27}, {0x07ffffe5, 27}, + {0x000fffec, 20}, {0x00fffff3, 24}, {0x000fffed, 20}, {0x001fffe6, 21}, + {0x003fffe9, 22}, {0x001fffe7, 21}, {0x001fffe8, 21}, {0x007ffff3, 23}, + {0x003fffea, 22}, {0x003fffeb, 22}, {0x01ffffee, 25}, {0x01ffffef, 25}, + {0x00fffff4, 24}, {0x00fffff5, 24}, {0x03ffffea, 26}, {0x007ffff4, 23}, + {0x03ffffeb, 26}, {0x07ffffe6, 27}, {0x03ffffec, 26}, {0x03ffffed, 26}, + {0x07ffffe7, 27}, {0x07ffffe8, 27}, {0x07ffffe9, 27}, {0x07ffffea, 27}, + {0x07ffffeb, 27}, {0x0ffffffe, 28}, {0x07ffffec, 27}, {0x07ffffed, 27}, + {0x07ffffee, 27}, {0x07ffffef, 27}, {0x07fffff0, 27}, {0x03ffffee, 26} +}; + + +#if (NGX_PTR_SIZE == 8) + +#if (NGX_HAVE_LITTLE_ENDIAN) + +#if (NGX_HAVE_GCC_BSWAP64) +#define ngx_http_v2_huff_encode_buf(dst, buf) \ + (*(uint64_t *) (dst) = __builtin_bswap64(buf)) +#else +#define ngx_http_v2_huff_encode_buf(dst, buf) \ + ((dst)[0] = (u_char) ((buf) >> 56), \ + (dst)[1] = (u_char) ((buf) >> 48), \ + (dst)[2] = (u_char) ((buf) >> 40), \ + (dst)[3] = (u_char) ((buf) >> 32), \ + (dst)[4] = (u_char) ((buf) >> 24), \ + (dst)[5] = (u_char) ((buf) >> 16), \ + (dst)[6] = (u_char) ((buf) >> 8), \ + (dst)[7] = (u_char) (buf)) +#endif + +#else /* !NGX_HAVE_LITTLE_ENDIAN */ +#define ngx_http_v2_huff_encode_buf(dst, buf) \ + (*(uint64_t *) (dst) = (buf)) +#endif + +#else /* NGX_PTR_SIZE == 4 */ + +#define ngx_http_v2_huff_encode_buf(dst, buf) \ + (*(uint32_t *) (dst) = htonl(buf)) + +#endif + + +size_t +ngx_http_v2_huff_encode(u_char *src, size_t len, u_char *dst, ngx_uint_t lower) +{ + u_char *end; + size_t hlen; + ngx_uint_t buf, pending, code; + ngx_http_v2_huff_encode_code_t *table, *next; + + table = lower ? ngx_http_v2_huff_encode_table_lc + : ngx_http_v2_huff_encode_table; + hlen = 0; + buf = 0; + pending = 0; + + end = src + len; + + while (src != end) { + next = &table[*src++]; + + code = next->code; + pending += next->len; + + /* accumulate bits */ + if (pending < sizeof(buf) * 8) { + buf |= code << (sizeof(buf) * 8 - pending); + continue; + } + + if (hlen + sizeof(buf) >= len) { + return 0; + } + + pending -= sizeof(buf) * 8; + + buf |= code >> pending; + + ngx_http_v2_huff_encode_buf(&dst[hlen], buf); + + hlen += sizeof(buf); + + buf = pending ? code << (sizeof(buf) * 8 - pending) : 0; + } + + if (pending == 0) { + return hlen; + } + + buf |= (ngx_uint_t) -1 >> pending; + + pending = ngx_align(pending, 8); + + if (hlen + pending / 8 >= len) { + return 0; + } + + buf >>= sizeof(buf) * 8 - pending; + + do { + pending -= 8; + dst[hlen++] = (u_char) (buf >> pending); + } while (pending); + + return hlen; +} diff --git a/src/os/unix/ngx_process_cycle.c b/src/os/unix/ngx_process_cycle.c index 7c6bf7a..9be6376 100644 --- a/src/os/unix/ngx_process_cycle.c +++ b/src/os/unix/ngx_process_cycle.c @@ -784,9 +784,9 @@ static void ngx_worker_process_init(ngx_cycle_t *cycle, ngx_int_t worker) { sigset_t set; - uint64_t cpu_affinity; ngx_int_t n; ngx_uint_t i; + ngx_cpuset_t *cpu_affinity; struct rlimit rlmt; ngx_core_conf_t *ccf; ngx_listening_t *ls; diff --git a/src/os/unix/ngx_setaffinity.c b/src/os/unix/ngx_setaffinity.c index 8f6cf35..34ec390 100644 --- a/src/os/unix/ngx_setaffinity.c +++ b/src/os/unix/ngx_setaffinity.c @@ -10,29 +10,20 @@ #if (NGX_HAVE_CPUSET_SETAFFINITY) -#include - void -ngx_setaffinity(uint64_t cpu_affinity, ngx_log_t *log) +ngx_setaffinity(ngx_cpuset_t *cpu_affinity, ngx_log_t *log) { - cpuset_t mask; ngx_uint_t i; - ngx_log_error(NGX_LOG_NOTICE, log, 0, - "cpuset_setaffinity(0x%08Xl)", cpu_affinity); - - CPU_ZERO(&mask); - i = 0; - do { - if (cpu_affinity & 1) { - CPU_SET(i, &mask); + for (i = 0; i < CPU_SETSIZE; i++) { + if (CPU_ISSET(i, cpu_affinity)) { + ngx_log_error(NGX_LOG_NOTICE, log, 0, + "cpuset_setaffinity(): using cpu #%ui", i); } - i++; - cpu_affinity >>= 1; - } while (cpu_affinity); + } if (cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, - sizeof(cpuset_t), &mask) == -1) + sizeof(cpuset_t), cpu_affinity) == -1) { ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "cpuset_setaffinity() failed"); @@ -42,25 +33,18 @@ ngx_setaffinity(uint64_t cpu_affinity, ngx_log_t *log) #elif (NGX_HAVE_SCHED_SETAFFINITY) void -ngx_setaffinity(uint64_t cpu_affinity, ngx_log_t *log) +ngx_setaffinity(ngx_cpuset_t *cpu_affinity, ngx_log_t *log) { - cpu_set_t mask; ngx_uint_t i; - ngx_log_error(NGX_LOG_NOTICE, log, 0, - "sched_setaffinity(0x%08Xl)", cpu_affinity); - - CPU_ZERO(&mask); - i = 0; - do { - if (cpu_affinity & 1) { - CPU_SET(i, &mask); + for (i = 0; i < CPU_SETSIZE; i++) { + if (CPU_ISSET(i, cpu_affinity)) { + ngx_log_error(NGX_LOG_NOTICE, log, 0, + "sched_setaffinity(): using cpu #%ui", i); } - i++; - cpu_affinity >>= 1; - } while (cpu_affinity); + } - if (sched_setaffinity(0, sizeof(cpu_set_t), &mask) == -1) { + if (sched_setaffinity(0, sizeof(cpu_set_t), cpu_affinity) == -1) { ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "sched_setaffinity() failed"); } diff --git a/src/os/unix/ngx_setaffinity.h b/src/os/unix/ngx_setaffinity.h index 33f5835..a4139ed 100644 --- a/src/os/unix/ngx_setaffinity.h +++ b/src/os/unix/ngx_setaffinity.h @@ -11,12 +11,26 @@ #define NGX_HAVE_CPU_AFFINITY 1 -void ngx_setaffinity(uint64_t cpu_affinity, ngx_log_t *log); +#if (NGX_HAVE_SCHED_SETAFFINITY) + +typedef cpu_set_t ngx_cpuset_t; + +#elif (NGX_HAVE_CPUSET_SETAFFINITY) + +#include + +typedef cpuset_t ngx_cpuset_t; + +#endif + +void ngx_setaffinity(ngx_cpuset_t *cpu_affinity, ngx_log_t *log); #else #define ngx_setaffinity(cpu_affinity, log) +typedef uint64_t ngx_cpuset_t; + #endif diff --git a/src/stream/ngx_stream_proxy_module.c b/src/stream/ngx_stream_proxy_module.c index 6800500..b969fea 100644 --- a/src/stream/ngx_stream_proxy_module.c +++ b/src/stream/ngx_stream_proxy_module.c @@ -10,9 +10,6 @@ #include -typedef void (*ngx_stream_proxy_handler_pt)(ngx_stream_session_t *s); - - typedef struct { ngx_msec_t connect_timeout; ngx_msec_t timeout; @@ -435,8 +432,6 @@ ngx_stream_proxy_connect(ngx_stream_session_t *s) ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0, "proxy connect: %i", rc); - pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module); - if (rc == NGX_ERROR) { ngx_stream_proxy_finalize(s, NGX_ERROR); return; @@ -471,6 +466,8 @@ ngx_stream_proxy_connect(ngx_stream_session_t *s) pc->read->handler = ngx_stream_proxy_connect_handler; pc->write->handler = ngx_stream_proxy_connect_handler; + pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module); + ngx_add_timer(pc->write, pscf->connect_timeout); } From 3072f74f2dc5a1dc18dc5f7f288f9613800f3780 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Wed, 30 Mar 2016 11:27:04 +0300 Subject: [PATCH 044/600] Imported Upstream version 1.9.13 --- CHANGES | 47 + CHANGES.ru | 50 + auto/init | 1 - auto/install | 63 +- auto/lib/conf | 2 +- auto/lib/make | 2 +- auto/lib/perl/conf | 7 +- auto/lib/perl/make | 5 +- auto/make | 45 +- auto/module | 4 +- auto/modules | 6 +- auto/options | 6 +- auto/sources | 1 + auto/unix | 39 + src/core/nginx.c | 4 +- src/core/nginx.h | 4 +- src/core/ngx_connection.c | 108 +- src/core/ngx_connection.h | 4 + src/core/ngx_cycle.c | 4 + src/core/ngx_file.c | 13 +- src/core/ngx_file.h | 2 + src/core/ngx_inet.c | 6 +- src/core/ngx_module.c | 3 +- src/core/ngx_module.h | 2 +- src/core/ngx_output_chain.c | 12 +- src/core/ngx_palloc.c | 88 +- src/core/ngx_resolver.c | 1024 ++++++++++++++++- src/core/ngx_resolver.h | 48 +- src/event/modules/ngx_devpoll_module.c | 4 +- src/event/modules/ngx_epoll_module.c | 3 + src/event/modules/ngx_eventport_module.c | 2 +- src/event/ngx_event.c | 6 +- src/event/ngx_event.h | 9 +- src/event/ngx_event_accept.c | 443 ++++++- src/event/ngx_event_connect.c | 41 +- src/event/ngx_event_connect.h | 1 + src/event/ngx_event_pipe.c | 98 +- src/event/ngx_event_pipe.h | 10 + src/http/modules/ngx_http_fastcgi_module.c | 1 + src/http/modules/ngx_http_proxy_module.c | 1 + src/http/modules/ngx_http_scgi_module.c | 1 + src/http/modules/ngx_http_sub_filter_module.c | 8 +- src/http/modules/ngx_http_uwsgi_module.c | 1 + src/http/ngx_http_cache.h | 4 + src/http/ngx_http_copy_filter_module.c | 16 +- src/http/ngx_http_core_module.c | 9 + src/http/ngx_http_core_module.h | 1 + src/http/ngx_http_file_cache.c | 48 +- src/http/ngx_http_request_body.c | 109 +- src/http/ngx_http_upstream.c | 230 +++- src/http/ngx_http_upstream.h | 3 +- src/http/v2/ngx_http_v2.c | 15 +- src/os/unix/ngx_darwin_init.c | 1 + src/os/unix/ngx_errno.h | 1 + src/os/unix/ngx_files.c | 284 +++-- src/os/unix/ngx_files.h | 6 +- src/os/unix/ngx_freebsd_init.c | 1 + src/os/unix/ngx_freebsd_sendfile_chain.c | 13 + src/os/unix/ngx_linux_init.c | 1 + src/os/unix/ngx_linux_sendfile_chain.c | 65 +- src/os/unix/ngx_os.h | 2 + src/os/unix/ngx_posix_config.h | 2 +- src/os/unix/ngx_posix_init.c | 1 + src/os/unix/ngx_solaris_init.c | 1 + src/os/unix/ngx_solaris_sendfilev_chain.c | 23 + src/os/unix/ngx_udp_send.c | 56 + src/stream/ngx_stream.c | 9 +- src/stream/ngx_stream.h | 2 + src/stream/ngx_stream_core_module.c | 30 +- src/stream/ngx_stream_handler.c | 15 +- src/stream/ngx_stream_proxy_module.c | 167 ++- src/stream/ngx_stream_upstream.c | 2 +- src/stream/ngx_stream_upstream.h | 1 + 73 files changed, 2809 insertions(+), 538 deletions(-) create mode 100644 src/os/unix/ngx_udp_send.c diff --git a/CHANGES b/CHANGES index e94e14f..0ac9c61 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,51 @@ +Changes with nginx 1.9.13 29 Mar 2016 + + *) Change: non-idempotent requests (POST, LOCK, PATCH) are no longer + passed to the next server by default if a request has been sent to a + backend; the "non_idempotent" parameter of the "proxy_next_upstream" + directive explicitly allows retrying such requests. + + *) Feature: the ngx_http_perl_module can be built dynamically. + + *) Feature: UDP support in the stream module. + + *) Feature: the "aio_write" directive. + + *) Feature: now cache manager monitors number of elements in caches and + tries to avoid cache keys zone overflows. + + *) Bugfix: "task already active" and "second aio post" alerts might + appear in logs when using the "sendfile" and "aio" directives with + subrequests. + + *) Bugfix: "zero size buf in output" alerts might appear in logs if + caching was used and a client closed a connection prematurely. + + *) Bugfix: connections with clients might be closed needlessly if + caching was used. + Thanks to Justin Li. + + *) Bugfix: nginx might hog CPU if the "sendfile" directive was used on + Linux or Solaris and a file being sent was changed during sending. + + *) Bugfix: connections might hang when using the "sendfile" and "aio + threads" directives. + + *) Bugfix: in the "proxy_pass", "fastcgi_pass", "scgi_pass", and + "uwsgi_pass" directives when using variables. + Thanks to Piotr Sikora. + + *) Bugfix: in the ngx_http_sub_filter_module. + + *) Bugfix: if an error occurred in a cached backend connection, the + request was passed to the next server regardless of the + proxy_next_upstream directive. + + *) Bugfix: "CreateFile() failed" errors when creating temporary files on + Windows. + + Changes with nginx 1.9.12 24 Feb 2016 *) Feature: Huffman encoding of response headers in HTTP/2. diff --git a/CHANGES.ru b/CHANGES.ru index c11c477..7c92f7b 100644 --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,54 @@ +Изменения в nginx 1.9.13 29.03.2016 + + *) Изменение: неидемпотентные запросы (POST, LOCK, PATCH) теперь по + умолчанию не передаются на другой сервер, если запрос уже был + отправлен на бэкенд; параметр non_idempotent директивы + proxy_next_upstream явно разрешает повторять такие запросы. + + *) Добавление: модуль ngx_http_perl_module теперь можно собрать + динамически. + + *) Добавление: поддержка UDP в модуле stream. + + *) Добавление: директива aio_write. + + *) Добавление: теперь cache manager следит за количеством элементов в + кэше и старается не допускать переполнений зоны разделяемой памяти. + + *) Исправление: при использовании директив sendfile и aio с подзапросами + в логах могли появляться сообщения "task already active" и "second + aio post". + + *) Исправление: при использовании кэширования в логах могли появляться + сообщения "zero size buf in output", если клиент закрывал соединение + преждевременно. + + *) Исправление: при использовании кэширования соединения с клиентами + могли закрываться без необходимости. + Спасибо Justin Li. + + *) Исправление: nginx мог нагружать процессор при использовании + директивы sendfile на Linux и Solaris, если отправляемый файл был + изменён в процессе отправки. + + *) Исправление: при использовании директив sendfile и "aio threads" + соединения могли зависать. + + *) Исправление: в директивах proxy_pass, fastcgi_pass, scgi_pass и + uwsgi_pass при использовании переменных. + Спасибо Piotr Sikora. + + *) Исправление: в модуле ngx_http_sub_filter_module. + + *) Исправление: если в закэшированном соединении к бэкенду происходила + ошибка, запрос передавался на другой сервер без учёта директивы + proxy_next_upstream. + + *) Исправление: ошибки "CreateFile() failed" при создании временных + файлов на Windows. + + Изменения в nginx 1.9.12 24.02.2016 *) Добавление: кодирование Хаффмана заголовков ответов в HTTP/2. diff --git a/auto/init b/auto/init index c593eda..910f529 100644 --- a/auto/init +++ b/auto/init @@ -5,7 +5,6 @@ NGX_MAKEFILE=$NGX_OBJS/Makefile NGX_MODULES_C=$NGX_OBJS/ngx_modules.c -NGX_MODULES= NGX_AUTO_HEADERS_H=$NGX_OBJS/ngx_auto_headers.h NGX_AUTO_CONFIG_H=$NGX_OBJS/ngx_auto_config.h diff --git a/auto/install b/auto/install index 9469a49..d884487 100644 --- a/auto/install +++ b/auto/install @@ -3,7 +3,7 @@ # Copyright (C) Nginx, Inc. -if [ $USE_PERL = YES ]; then +if [ $USE_PERL != NO ]; then cat << END >> $NGX_MAKEFILE @@ -107,54 +107,54 @@ $NGX_OBJS/nginx.8: $NGX_MAN $NGX_AUTO_CONFIG_H install: build $NGX_INSTALL_PERL_MODULES test -d '\$(DESTDIR)$NGX_PREFIX' || mkdir -p '\$(DESTDIR)$NGX_PREFIX' - test -d '\$(DESTDIR)`dirname "$NGX_SBIN_PATH"`' \ + test -d '\$(DESTDIR)`dirname "$NGX_SBIN_PATH"`' \\ || mkdir -p '\$(DESTDIR)`dirname "$NGX_SBIN_PATH"`' - test ! -f '\$(DESTDIR)$NGX_SBIN_PATH' \ - || mv '\$(DESTDIR)$NGX_SBIN_PATH' \ + test ! -f '\$(DESTDIR)$NGX_SBIN_PATH' \\ + || mv '\$(DESTDIR)$NGX_SBIN_PATH' \\ '\$(DESTDIR)$NGX_SBIN_PATH.old' cp $NGX_OBJS/nginx '\$(DESTDIR)$NGX_SBIN_PATH' - test -d '\$(DESTDIR)$NGX_CONF_PREFIX' \ + test -d '\$(DESTDIR)$NGX_CONF_PREFIX' \\ || mkdir -p '\$(DESTDIR)$NGX_CONF_PREFIX' cp conf/koi-win '\$(DESTDIR)$NGX_CONF_PREFIX' cp conf/koi-utf '\$(DESTDIR)$NGX_CONF_PREFIX' cp conf/win-utf '\$(DESTDIR)$NGX_CONF_PREFIX' - test -f '\$(DESTDIR)$NGX_CONF_PREFIX/mime.types' \ + test -f '\$(DESTDIR)$NGX_CONF_PREFIX/mime.types' \\ || cp conf/mime.types '\$(DESTDIR)$NGX_CONF_PREFIX' cp conf/mime.types '\$(DESTDIR)$NGX_CONF_PREFIX/mime.types.default' - test -f '\$(DESTDIR)$NGX_CONF_PREFIX/fastcgi_params' \ + test -f '\$(DESTDIR)$NGX_CONF_PREFIX/fastcgi_params' \\ || cp conf/fastcgi_params '\$(DESTDIR)$NGX_CONF_PREFIX' - cp conf/fastcgi_params \ + cp conf/fastcgi_params \\ '\$(DESTDIR)$NGX_CONF_PREFIX/fastcgi_params.default' - test -f '\$(DESTDIR)$NGX_CONF_PREFIX/fastcgi.conf' \ + test -f '\$(DESTDIR)$NGX_CONF_PREFIX/fastcgi.conf' \\ || cp conf/fastcgi.conf '\$(DESTDIR)$NGX_CONF_PREFIX' cp conf/fastcgi.conf '\$(DESTDIR)$NGX_CONF_PREFIX/fastcgi.conf.default' - test -f '\$(DESTDIR)$NGX_CONF_PREFIX/uwsgi_params' \ + test -f '\$(DESTDIR)$NGX_CONF_PREFIX/uwsgi_params' \\ || cp conf/uwsgi_params '\$(DESTDIR)$NGX_CONF_PREFIX' - cp conf/uwsgi_params \ + cp conf/uwsgi_params \\ '\$(DESTDIR)$NGX_CONF_PREFIX/uwsgi_params.default' - test -f '\$(DESTDIR)$NGX_CONF_PREFIX/scgi_params' \ + test -f '\$(DESTDIR)$NGX_CONF_PREFIX/scgi_params' \\ || cp conf/scgi_params '\$(DESTDIR)$NGX_CONF_PREFIX' - cp conf/scgi_params \ + cp conf/scgi_params \\ '\$(DESTDIR)$NGX_CONF_PREFIX/scgi_params.default' - test -f '\$(DESTDIR)$NGX_CONF_PATH' \ + test -f '\$(DESTDIR)$NGX_CONF_PATH' \\ || cp conf/nginx.conf '\$(DESTDIR)$NGX_CONF_PATH' cp conf/nginx.conf '\$(DESTDIR)$NGX_CONF_PREFIX/nginx.conf.default' - test -d '\$(DESTDIR)`dirname "$NGX_PID_PATH"`' \ + test -d '\$(DESTDIR)`dirname "$NGX_PID_PATH"`' \\ || mkdir -p '\$(DESTDIR)`dirname "$NGX_PID_PATH"`' - test -d '\$(DESTDIR)`dirname "$NGX_HTTP_LOG_PATH"`' || \ - mkdir -p '\$(DESTDIR)`dirname "$NGX_HTTP_LOG_PATH"`' + test -d '\$(DESTDIR)`dirname "$NGX_HTTP_LOG_PATH"`' \\ + || mkdir -p '\$(DESTDIR)`dirname "$NGX_HTTP_LOG_PATH"`' - test -d '\$(DESTDIR)$NGX_PREFIX/html' \ + test -d '\$(DESTDIR)$NGX_PREFIX/html' \\ || cp -R $NGX_HTML '\$(DESTDIR)$NGX_PREFIX' END @@ -162,24 +162,38 @@ END if test -n "$NGX_ERROR_LOG_PATH"; then cat << END >> $NGX_MAKEFILE - test -d '\$(DESTDIR)`dirname "$NGX_ERROR_LOG_PATH"`' || \ - mkdir -p '\$(DESTDIR)`dirname "$NGX_ERROR_LOG_PATH"`' + test -d '\$(DESTDIR)`dirname "$NGX_ERROR_LOG_PATH"`' \\ + || mkdir -p '\$(DESTDIR)`dirname "$NGX_ERROR_LOG_PATH"`' END fi -if test -n "$NGX_MODULES"; then +if test -n "$DYNAMIC_MODULES"; then cat << END >> $NGX_MAKEFILE - test -d '\$(DESTDIR)$NGX_MODULES_PATH' \ + test -d '\$(DESTDIR)$NGX_MODULES_PATH' \\ || mkdir -p '\$(DESTDIR)$NGX_MODULES_PATH' - cp $NGX_MODULES '\$(DESTDIR)$NGX_MODULES_PATH' END fi +for ngx_module in $DYNAMIC_MODULES +do + ngx_module=$ngx_module$ngx_modext + + cat << END >> $NGX_MAKEFILE + + test ! -f '\$(DESTDIR)$NGX_MODULES_PATH/$ngx_module' \\ + || mv '\$(DESTDIR)$NGX_MODULES_PATH/$ngx_module' \\ + '\$(DESTDIR)$NGX_MODULES_PATH/$ngx_module.old' + cp $NGX_OBJS/$ngx_module '\$(DESTDIR)$NGX_MODULES_PATH/$ngx_module' +END + +done + + # create Makefile cat << END >> Makefile @@ -190,6 +204,9 @@ build: install: \$(MAKE) -f $NGX_MAKEFILE install +modules: + \$(MAKE) -f $NGX_MAKEFILE modules + upgrade: $NGX_SBIN_PATH -t diff --git a/auto/lib/conf b/auto/lib/conf index 6aaa43a..a6242e7 100644 --- a/auto/lib/conf +++ b/auto/lib/conf @@ -66,7 +66,7 @@ if [ $USE_LIBGD != NO ]; then . auto/lib/libgd/conf fi -if [ $USE_PERL = YES ]; then +if [ $USE_PERL != NO ]; then . auto/lib/perl/conf fi diff --git a/auto/lib/make b/auto/lib/make index 58a84a3..6298b94 100644 --- a/auto/lib/make +++ b/auto/lib/make @@ -27,6 +27,6 @@ if [ $NGX_LIBATOMIC != NO -a $NGX_LIBATOMIC != YES ]; then . auto/lib/libatomic/make fi -if [ $USE_PERL = YES ]; then +if [ $USE_PERL != NO ]; then . auto/lib/perl/make fi diff --git a/auto/lib/perl/conf b/auto/lib/perl/conf index 4d1bcf1..f5f5d3e 100644 --- a/auto/lib/perl/conf +++ b/auto/lib/perl/conf @@ -60,8 +60,11 @@ if test -n "$NGX_PERL_VER"; then | sed -e 's/-arch i386//' -e 's/-arch x86_64//'` fi - CORE_LINK="$CORE_LINK $ngx_perl_ldopts" - LINK_DEPS="$LINK_DEPS $NGX_OBJS/$ngx_perl_module" + if [ $USE_PERL = YES ]; then + CORE_LINK="$CORE_LINK $ngx_perl_ldopts" + fi + + NGX_LIB_PERL="$ngx_perl_ldopts" if test -n "$NGX_PERL_MODULES"; then have=NGX_PERL_MODULES value="(u_char *) \"$NGX_PERL_MODULES\"" diff --git a/auto/lib/perl/make b/auto/lib/perl/make index d1c1b9e..8af8902 100644 --- a/auto/lib/perl/make +++ b/auto/lib/perl/make @@ -8,7 +8,10 @@ v=`grep 'define NGINX_VERSION' src/core/nginx.h | sed -e 's/^.*"\(.*\)".*/\1/'` cat << END >> $NGX_MAKEFILE -$NGX_OBJS/src/http/modules/perl/blib/arch/auto/nginx/nginx.$ngx_perl_dlext: \\ +$NGX_OBJS/src/http/modules/perl/ngx_http_perl_module.o: \\ + $NGX_OBJS/$ngx_perl_module + +$NGX_OBJS/$ngx_perl_module: \\ \$(CORE_DEPS) \$(HTTP_DEPS) \\ src/http/modules/perl/ngx_http_perl_module.h \\ $NGX_OBJS/src/http/modules/perl/Makefile diff --git a/auto/make b/auto/make index 560924b..5589bee 100644 --- a/auto/make +++ b/auto/make @@ -225,12 +225,12 @@ cat << END >> $NGX_MAKEFILE build: binary modules manpage -binary: $NGX_OBJS${ngx_dirsep}nginx${ngx_binext} +binary: $NGX_OBJS${ngx_dirsep}nginx$ngx_binext -$NGX_OBJS${ngx_dirsep}nginx${ngx_binext}: $ngx_deps$ngx_spacer - \$(LINK) ${ngx_long_start}${ngx_binout}$NGX_OBJS${ngx_dirsep}nginx$ngx_long_cont$ngx_objs$ngx_libs$ngx_link$ngx_main_link +$NGX_OBJS${ngx_dirsep}nginx$ngx_binext: $ngx_deps$ngx_spacer + \$(LINK) $ngx_long_start$ngx_binout$NGX_OBJS${ngx_dirsep}nginx$ngx_long_cont$ngx_objs$ngx_libs$ngx_link$ngx_main_link $ngx_rcc -${ngx_long_end} +$ngx_long_end modules: END @@ -281,7 +281,7 @@ if [ $HTTP = YES ]; then ngx_cc="\$(CC) $ngx_compile_opt \$(CFLAGS) $ngx_use_pch \$(ALL_INCS)" else ngx_cc="\$(CC) $ngx_compile_opt \$(CFLAGS) \$(CORE_INCS) \$(HTTP_INCS)" - ngx_perl_cc="\$(CC) $ngx_compile_opt \$(NGX_PERL_CFLAGS) " + ngx_perl_cc="\$(CC) $ngx_compile_opt \$(NGX_PERL_CFLAGS)" ngx_perl_cc="$ngx_perl_cc \$(CORE_INCS) \$(HTTP_INCS)" fi @@ -437,9 +437,9 @@ fi # the addons config.make -if test -n "$NGX_ADDONS"; then +if test -n "$NGX_ADDONS$DYNAMIC_ADDONS"; then - for ngx_addon_dir in $NGX_ADDONS + for ngx_addon_dir in $NGX_ADDONS $DYNAMIC_ADDONS do if test -f $ngx_addon_dir/config.make; then . $ngx_addon_dir/config.make @@ -494,6 +494,8 @@ if test -n "$NGX_PCH"; then ngx_cc="\$(CC) $ngx_compile_opt $ngx_pic_opt \$(CFLAGS) $ngx_use_pch \$(ALL_INCS)" else ngx_cc="\$(CC) $ngx_compile_opt $ngx_pic_opt \$(CFLAGS) \$(ALL_INCS)" + ngx_perl_cc="\$(CC) $ngx_compile_opt $ngx_pic_opt \$(NGX_PERL_CFLAGS)" + ngx_perl_cc="$ngx_perl_cc \$(ALL_INCS)" fi ngx_obj_deps="\$(CORE_DEPS)" @@ -605,9 +607,7 @@ END | sed -e "s/ *\([^ ][^ ]*\)/$ngx_long_regex_cont\1/g" \ -e "s/\//$ngx_regex_dirsep/g"` - ngx_obj=$NGX_OBJS${ngx_dirsep}${ngx_module}${ngx_modext} - - NGX_MODULES="$NGX_MODULES $ngx_obj" + ngx_obj=$NGX_OBJS$ngx_dirsep$ngx_module$ngx_modext if [ "$NGX_PLATFORM" = win32 ]; then ngx_module_libs="$CORE_LIBS $ngx_module_libs" @@ -639,15 +639,15 @@ $ngx_modules_obj: \$(CORE_DEPS)$ngx_cont$ngx_modules_c END - for ngx_src in $ngx_module_srcs + for ngx_source in $ngx_module_srcs do - case "$ngx_src" in + case "$ngx_source" in src/*) - ngx_obj=`echo $ngx_src | sed -e "s/\//$ngx_regex_dirsep/g"` + ngx_obj=`echo $ngx_source | sed -e "s/\//$ngx_regex_dirsep/g"` ;; *) - ngx_obj="addon/`basename \`dirname $ngx_src\``" - ngx_obj=`echo $ngx_obj/\`basename $ngx_src\` \ + ngx_obj="addon/`basename \`dirname $ngx_source\``" + ngx_obj=`echo $ngx_obj/\`basename $ngx_source\` \ | sed -e "s/\//$ngx_regex_dirsep/g"` ;; esac @@ -658,14 +658,25 @@ END -e "s#^\(.*\.\)c\\$#$ngx_objs_dir\1$ngx_objext#g" \ -e "s#^\(.*\.\)S\\$#$ngx_objs_dir\1$ngx_objext#g"` - ngx_src=`echo $ngx_src | sed -e "s/\//$ngx_regex_dirsep/g"` + ngx_src=`echo $ngx_source | sed -e "s/\//$ngx_regex_dirsep/g"` - cat << END >> $NGX_MAKEFILE + if [ $ngx_source = src/http/modules/perl/ngx_http_perl_module.c ]; then + + cat << END >> $NGX_MAKEFILE + +$ngx_obj: $ngx_obj_deps$ngx_cont$ngx_src + $ngx_perl_cc$ngx_tab$ngx_objout$ngx_obj$ngx_tab$ngx_src$NGX_AUX + +END + else + + cat << END >> $NGX_MAKEFILE $ngx_obj: $ngx_obj_deps$ngx_cont$ngx_src $ngx_cc$ngx_tab$ngx_objout$ngx_obj$ngx_tab$ngx_src$NGX_AUX END + fi done done diff --git a/auto/module b/auto/module index 908f0c6..16a816f 100644 --- a/auto/module +++ b/auto/module @@ -40,7 +40,7 @@ if [ "$ngx_module_link" = DYNAMIC ]; then do case $lib in - LIBXSLT | LIBGD | GEOIP) + LIBXSLT | LIBGD | GEOIP | PERL) libs="$libs \$NGX_LIB_$lib" if eval [ "\$USE_${lib}" = NO ] ; then @@ -48,7 +48,7 @@ if [ "$ngx_module_link" = DYNAMIC ]; then fi ;; - PCRE | OPENSSL | MD5 | SHA1 | ZLIB | PERL) + PCRE | OPENSSL | MD5 | SHA1 | ZLIB) eval USE_${lib}=YES ;; diff --git a/auto/modules b/auto/modules index ebfc91d..22ff6d9 100644 --- a/auto/modules +++ b/auto/modules @@ -727,14 +727,12 @@ if [ $HTTP_SCGI = YES ]; then . auto/module fi -if [ $HTTP_PERL = YES ]; then - USE_PERL=YES - +if [ $HTTP_PERL != NO ]; then ngx_module_name=ngx_http_perl_module ngx_module_incs=src/http/modules/perl ngx_module_deps=src/http/modules/perl/ngx_http_perl_module.h ngx_module_srcs=src/http/modules/perl/ngx_http_perl_module.c - ngx_module_libs= + ngx_module_libs=PERL ngx_module_link=$HTTP_PERL . auto/module diff --git a/auto/options b/auto/options index 36b34bc..ac8beb1 100644 --- a/auto/options +++ b/auto/options @@ -271,6 +271,7 @@ do --without-http_upstream_zone_module) HTTP_UPSTREAM_ZONE=NO ;; --with-http_perl_module) HTTP_PERL=YES ;; + --with-http_perl_module=dynamic) HTTP_PERL=DYNAMIC ;; --with-perl_modules_path=*) NGX_PERL_MODULES="$value" ;; --with-perl=*) NGX_PERL="$value" ;; @@ -452,6 +453,7 @@ cat << END disable ngx_http_upstream_zone_module --with-http_perl_module enable ngx_http_perl_module + --with-http_perl_module=dynamic enable dynamic ngx_http_perl_module --with-perl_modules_path=PATH set Perl modules path --with-perl=PATH set perl binary pathname @@ -477,8 +479,8 @@ cat << END --without-mail_imap_module disable ngx_mail_imap_module --without-mail_smtp_module disable ngx_mail_smtp_module - --with-stream enable TCP proxy module - --with-stream=dynamic enable dynamic TCP proxy module + --with-stream enable TCP/UDP proxy module + --with-stream=dynamic enable dynamic TCP/UDP proxy module --with-stream_ssl_module enable ngx_stream_ssl_module --without-stream_limit_conn_module disable ngx_stream_limit_conn_module --without-stream_access_module disable ngx_stream_access_module diff --git a/auto/sources b/auto/sources index e08e863..27849e6 100644 --- a/auto/sources +++ b/auto/sources @@ -165,6 +165,7 @@ UNIX_SRCS="$CORE_SRCS $EVENT_SRCS \ src/os/unix/ngx_udp_recv.c \ src/os/unix/ngx_send.c \ src/os/unix/ngx_writev_chain.c \ + src/os/unix/ngx_udp_send.c \ src/os/unix/ngx_channel.c \ src/os/unix/ngx_shmem.c \ src/os/unix/ngx_process.c \ diff --git a/auto/unix b/auto/unix index ce01791..16d9523 100755 --- a/auto/unix +++ b/auto/unix @@ -329,6 +329,45 @@ ngx_feature_test="setsockopt(0, SOL_SOCKET, SO_ACCEPTFILTER, NULL, 0)" . auto/feature +# BSD way to get IPv4 datagram destination address + +ngx_feature="IP_RECVDSTADDR" +ngx_feature_name="NGX_HAVE_IP_RECVDSTADDR" +ngx_feature_run=no +ngx_feature_incs="#include + #include " +ngx_feature_path= +ngx_feature_libs= +ngx_feature_test="setsockopt(0, IPPROTO_IP, IP_RECVDSTADDR, NULL, 0)" +. auto/feature + + +# Linux way to get IPv4 datagram destination address + +ngx_feature="IP_PKTINFO" +ngx_feature_name="NGX_HAVE_IP_PKTINFO" +ngx_feature_run=no +ngx_feature_incs="#include + #include " +ngx_feature_path= +ngx_feature_libs= +ngx_feature_test="setsockopt(0, IPPROTO_IP, IP_PKTINFO, NULL, 0)" +. auto/feature + + +# RFC 3542 way to get IPv6 datagram destination address + +ngx_feature="IPV6_RECVPKTINFO" +ngx_feature_name="NGX_HAVE_IPV6_RECVPKTINFO" +ngx_feature_run=no +ngx_feature_incs="#include + #include " +ngx_feature_path= +ngx_feature_libs= +ngx_feature_test="setsockopt(0, IPPROTO_IPV6, IPV6_RECVPKTINFO, NULL, 0)" +. auto/feature + + ngx_feature="TCP_DEFER_ACCEPT" ngx_feature_name="NGX_HAVE_DEFERRED_ACCEPT" ngx_feature_run=no diff --git a/src/core/nginx.c b/src/core/nginx.c index cdc067e..2823169 100644 --- a/src/core/nginx.c +++ b/src/core/nginx.c @@ -10,7 +10,7 @@ #include -static void ngx_show_version_info(); +static void ngx_show_version_info(void); static ngx_int_t ngx_add_inherited_sockets(ngx_cycle_t *cycle); static ngx_int_t ngx_get_options(int argc, char *const *argv); static ngx_int_t ngx_process_options(ngx_cycle_t *cycle); @@ -372,7 +372,7 @@ main(int argc, char *const *argv) static void -ngx_show_version_info() +ngx_show_version_info(void) { ngx_write_stderr("nginx version: " NGINX_VER_BUILD NGX_LINEFEED); diff --git a/src/core/nginx.h b/src/core/nginx.h index dec7b88..238d8b8 100644 --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1009012 -#define NGINX_VERSION "1.9.12" +#define nginx_version 1009013 +#define NGINX_VERSION "1.9.13" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c index 0c19d5d..572def2 100644 --- a/src/core/ngx_connection.c +++ b/src/core/ngx_connection.c @@ -210,6 +210,18 @@ ngx_set_inherited_sockets(ngx_cycle_t *cycle) olen = sizeof(int); + if (getsockopt(ls[i].fd, SOL_SOCKET, SO_TYPE, (void *) &ls[i].type, + &olen) + == -1) + { + ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno, + "getsockopt(SO_TYPE) %V failed", &ls[i].addr_text); + ls[i].ignore = 1; + continue; + } + + olen = sizeof(int); + if (getsockopt(ls[i].fd, SOL_SOCKET, SO_RCVBUF, (void *) &ls[i].rcvbuf, &olen) == -1) @@ -274,6 +286,10 @@ ngx_set_inherited_sockets(ngx_cycle_t *cycle) #endif + if (ls[i].type != SOCK_STREAM) { + continue; + } + #if (NGX_HAVE_TCP_FASTOPEN) olen = sizeof(int); @@ -566,6 +582,11 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle) } #endif + if (ls[i].type != SOCK_STREAM) { + ls[i].fd = s; + continue; + } + if (listen(s, ls[i].backlog) == -1) { err = ngx_socket_errno; @@ -865,6 +886,67 @@ ngx_configure_listening_sockets(ngx_cycle_t *cycle) #endif #endif /* NGX_HAVE_DEFERRED_ACCEPT */ + +#if (NGX_HAVE_IP_RECVDSTADDR) + + if (ls[i].wildcard + && ls[i].type == SOCK_DGRAM + && ls[i].sockaddr->sa_family == AF_INET) + { + value = 1; + + if (setsockopt(ls[i].fd, IPPROTO_IP, IP_RECVDSTADDR, + (const void *) &value, sizeof(int)) + == -1) + { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno, + "setsockopt(IP_RECVDSTADDR) " + "for %V failed, ignored", + &ls[i].addr_text); + } + } + +#elif (NGX_HAVE_IP_PKTINFO) + + if (ls[i].wildcard + && ls[i].type == SOCK_DGRAM + && ls[i].sockaddr->sa_family == AF_INET) + { + value = 1; + + if (setsockopt(ls[i].fd, IPPROTO_IP, IP_PKTINFO, + (const void *) &value, sizeof(int)) + == -1) + { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno, + "setsockopt(IP_PKTINFO) " + "for %V failed, ignored", + &ls[i].addr_text); + } + } + +#endif + +#if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO) + + if (ls[i].wildcard + && ls[i].type == SOCK_DGRAM + && ls[i].sockaddr->sa_family == AF_INET6) + { + value = 1; + + if (setsockopt(ls[i].fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, + (const void *) &value, sizeof(int)) + == -1) + { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno, + "setsockopt(IPV6_RECVPKTINFO) " + "for %V failed, ignored", + &ls[i].addr_text); + } + } + +#endif } return; @@ -978,7 +1060,7 @@ ngx_get_connection(ngx_socket_t s, ngx_log_t *log) ngx_cycle->free_connections = c->data; ngx_cycle->free_connection_n--; - if (ngx_cycle->files) { + if (ngx_cycle->files && ngx_cycle->files[s] == NULL) { ngx_cycle->files[s] = c; } @@ -1019,7 +1101,7 @@ ngx_free_connection(ngx_connection_t *c) ngx_cycle->free_connections = c; ngx_cycle->free_connection_n++; - if (ngx_cycle->files) { + if (ngx_cycle->files && ngx_cycle->files[c->fd] == c) { ngx_cycle->files[c->fd] = NULL; } } @@ -1045,16 +1127,18 @@ ngx_close_connection(ngx_connection_t *c) ngx_del_timer(c->write); } - if (ngx_del_conn) { - ngx_del_conn(c, NGX_CLOSE_EVENT); + if (!c->shared) { + if (ngx_del_conn) { + ngx_del_conn(c, NGX_CLOSE_EVENT); - } else { - if (c->read->active || c->read->disabled) { - ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT); - } + } else { + if (c->read->active || c->read->disabled) { + ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT); + } - if (c->write->active || c->write->disabled) { - ngx_del_event(c->write, NGX_WRITE_EVENT, NGX_CLOSE_EVENT); + if (c->write->active || c->write->disabled) { + ngx_del_event(c->write, NGX_WRITE_EVENT, NGX_CLOSE_EVENT); + } } } @@ -1078,6 +1162,10 @@ ngx_close_connection(ngx_connection_t *c) fd = c->fd; c->fd = (ngx_socket_t) -1; + if (c->shared) { + return; + } + if (ngx_close_socket(fd) == -1) { err = ngx_socket_errno; diff --git a/src/core/ngx_connection.h b/src/core/ngx_connection.h index 977f028..19a2ab7 100644 --- a/src/core/ngx_connection.h +++ b/src/core/ngx_connection.h @@ -64,6 +64,7 @@ struct ngx_listening_s { unsigned nonblocking:1; unsigned shared:1; /* shared between threads or processes */ unsigned addr_ntop:1; + unsigned wildcard:1; #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) unsigned ipv6only:1; @@ -141,6 +142,8 @@ struct ngx_connection_s { ngx_pool_t *pool; + int type; + struct sockaddr *sockaddr; socklen_t socklen; ngx_str_t addr_text; @@ -174,6 +177,7 @@ struct ngx_connection_s { unsigned idle:1; unsigned reusable:1; unsigned close:1; + unsigned shared:1; unsigned sendfile:1; unsigned sndlowat:1; diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c index f103266..5785eb5 100644 --- a/src/core/ngx_cycle.c +++ b/src/core/ngx_cycle.c @@ -512,6 +512,10 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) continue; } + if (ls[i].type != nls[n].type) { + continue; + } + if (ngx_cmp_sockaddr(nls[n].sockaddr, nls[n].socklen, ls[i].sockaddr, ls[i].socklen, 1) == NGX_OK) diff --git a/src/core/ngx_file.c b/src/core/ngx_file.c index 3ebd73d..d3e2ece 100644 --- a/src/core/ngx_file.c +++ b/src/core/ngx_file.c @@ -124,6 +124,15 @@ ngx_write_chain_to_temp_file(ngx_temp_file_t *tf, ngx_chain_t *chain) } } +#if (NGX_THREADS && NGX_HAVE_PWRITEV) + + if (tf->thread_write) { + return ngx_thread_write_chain_to_file(&tf->file, chain, tf->offset, + tf->pool); + } + +#endif + return ngx_write_chain_to_file(&tf->file, chain, tf->offset, tf->pool); } @@ -187,7 +196,7 @@ ngx_create_temp_file(ngx_file_t *file, ngx_path_t *path, ngx_pool_t *pool, err = ngx_errno; - if (err == NGX_EEXIST) { + if (err == NGX_EEXIST_FILE) { n = (uint32_t) ngx_next_temp_number(1); continue; } @@ -683,7 +692,7 @@ ngx_ext_rename_file(ngx_str_t *src, ngx_str_t *to, ngx_ext_rename_file_t *ext) #if (NGX_WIN32) - if (err == NGX_EEXIST) { + if (err == NGX_EEXIST || err == NGX_EEXIST_FILE) { err = ngx_win32_rename_file(src, to, ext->log); if (err == 0) { diff --git a/src/core/ngx_file.h b/src/core/ngx_file.h index 301b191..5f8228b 100644 --- a/src/core/ngx_file.h +++ b/src/core/ngx_file.h @@ -27,6 +27,7 @@ struct ngx_file_s { ngx_int_t (*thread_handler)(ngx_thread_task_t *task, ngx_file_t *file); void *thread_ctx; + ngx_thread_task_t *thread_task; #endif #if (NGX_HAVE_FILE_AIO) @@ -77,6 +78,7 @@ typedef struct { unsigned log_level:8; unsigned persistent:1; unsigned clean:1; + unsigned thread_write:1; } ngx_temp_file_t; diff --git a/src/core/ngx_inet.c b/src/core/ngx_inet.c index 96a04fd..3bbadb8 100644 --- a/src/core/ngx_inet.c +++ b/src/core/ngx_inet.c @@ -529,14 +529,16 @@ ngx_int_t ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u) { u_char *p; + size_t len; p = u->url.data; + len = u->url.len; - if (ngx_strncasecmp(p, (u_char *) "unix:", 5) == 0) { + if (len >= 5 && ngx_strncasecmp(p, (u_char *) "unix:", 5) == 0) { return ngx_parse_unix_domain_url(pool, u); } - if (p[0] == '[') { + if (len && p[0] == '[') { return ngx_parse_inet6_url(pool, u); } diff --git a/src/core/ngx_module.c b/src/core/ngx_module.c index f5ec86a..3e3c506 100644 --- a/src/core/ngx_module.c +++ b/src/core/ngx_module.c @@ -23,11 +23,10 @@ static ngx_uint_t ngx_modules_n; ngx_int_t -ngx_preinit_modules() +ngx_preinit_modules(void) { ngx_uint_t i; - ngx_max_module = 0; for (i = 0; ngx_modules[i]; i++) { ngx_modules[i]->index = i; ngx_modules[i]->name = ngx_module_names[i]; diff --git a/src/core/ngx_module.h b/src/core/ngx_module.h index 3e74def..e911cb4 100644 --- a/src/core/ngx_module.h +++ b/src/core/ngx_module.h @@ -288,7 +288,7 @@ typedef struct { } ngx_core_module_t; -ngx_int_t ngx_preinit_modules(); +ngx_int_t ngx_preinit_modules(void); ngx_int_t ngx_cycle_modules(ngx_cycle_t *cycle); ngx_int_t ngx_init_modules(ngx_cycle_t *cycle); ngx_int_t ngx_count_modules(ngx_cycle_t *cycle, ngx_uint_t type); diff --git a/src/core/ngx_output_chain.c b/src/core/ngx_output_chain.c index 252359a..f784578 100644 --- a/src/core/ngx_output_chain.c +++ b/src/core/ngx_output_chain.c @@ -577,11 +577,15 @@ ngx_output_chain_copy_buf(ngx_output_chain_ctx_t *ctx) } else #endif #if (NGX_THREADS) - if (src->file->thread_handler) { - n = ngx_thread_read(&ctx->thread_task, src->file, dst->pos, - (size_t) size, src->file_pos, ctx->pool); + if (ctx->thread_handler) { + src->file->thread_task = ctx->thread_task; + src->file->thread_handler = ctx->thread_handler; + src->file->thread_ctx = ctx->filter_ctx; + + n = ngx_thread_read(src->file, dst->pos, (size_t) size, + src->file_pos, ctx->pool); if (n == NGX_AGAIN) { - ctx->aio = 1; + ctx->thread_task = src->file->thread_task; return NGX_AGAIN; } diff --git a/src/core/ngx_palloc.c b/src/core/ngx_palloc.c index ef4a647..d3044ac 100644 --- a/src/core/ngx_palloc.c +++ b/src/core/ngx_palloc.c @@ -9,6 +9,8 @@ #include +static ngx_inline void *ngx_palloc_small(ngx_pool_t *pool, size_t size, + ngx_uint_t align); static void *ngx_palloc_block(ngx_pool_t *pool, size_t size); static void *ngx_palloc_large(ngx_pool_t *pool, size_t size); @@ -56,15 +58,6 @@ ngx_destroy_pool(ngx_pool_t *pool) } } - for (l = pool->large; l; l = l->next) { - - ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0, "free: %p", l->alloc); - - if (l->alloc) { - ngx_free(l->alloc); - } - } - #if (NGX_DEBUG) /* @@ -72,6 +65,10 @@ ngx_destroy_pool(ngx_pool_t *pool) * so we cannot use this log while free()ing the pool */ + for (l = pool->large; l; l = l->next) { + ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0, "free: %p", l->alloc); + } + for (p = pool, n = pool->d.next; /* void */; p = n, n = n->d.next) { ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, pool->log, 0, "free: %p, unused: %uz", p, p->d.end - p->d.last); @@ -83,6 +80,12 @@ ngx_destroy_pool(ngx_pool_t *pool) #endif + for (l = pool->large; l; l = l->next) { + if (l->alloc) { + ngx_free(l->alloc); + } + } + for (p = pool, n = pool->d.next; /* void */; p = n, n = n->d.next) { ngx_free(p); @@ -119,28 +122,11 @@ ngx_reset_pool(ngx_pool_t *pool) void * ngx_palloc(ngx_pool_t *pool, size_t size) { - u_char *m; - ngx_pool_t *p; - +#if !(NGX_DEBUG_PALLOC) if (size <= pool->max) { - - p = pool->current; - - do { - m = ngx_align_ptr(p->d.last, NGX_ALIGNMENT); - - if ((size_t) (p->d.end - m) >= size) { - p->d.last = m + size; - - return m; - } - - p = p->d.next; - - } while (p); - - return ngx_palloc_block(pool, size); + return ngx_palloc_small(pool, size, 1); } +#endif return ngx_palloc_large(pool, size); } @@ -148,31 +134,43 @@ ngx_palloc(ngx_pool_t *pool, size_t size) void * ngx_pnalloc(ngx_pool_t *pool, size_t size) +{ +#if !(NGX_DEBUG_PALLOC) + if (size <= pool->max) { + return ngx_palloc_small(pool, size, 0); + } +#endif + + return ngx_palloc_large(pool, size); +} + + +static ngx_inline void * +ngx_palloc_small(ngx_pool_t *pool, size_t size, ngx_uint_t align) { u_char *m; ngx_pool_t *p; - if (size <= pool->max) { + p = pool->current; - p = pool->current; + do { + m = p->d.last; - do { - m = p->d.last; + if (align) { + m = ngx_align_ptr(m, NGX_ALIGNMENT); + } - if ((size_t) (p->d.end - m) >= size) { - p->d.last = m + size; + if ((size_t) (p->d.end - m) >= size) { + p->d.last = m + size; - return m; - } + return m; + } - p = p->d.next; + p = p->d.next; - } while (p); + } while (p); - return ngx_palloc_block(pool, size); - } - - return ngx_palloc_large(pool, size); + return ngx_palloc_block(pool, size); } @@ -237,7 +235,7 @@ ngx_palloc_large(ngx_pool_t *pool, size_t size) } } - large = ngx_palloc(pool, sizeof(ngx_pool_large_t)); + large = ngx_palloc_small(pool, sizeof(ngx_pool_large_t), 1); if (large == NULL) { ngx_free(p); return NULL; @@ -262,7 +260,7 @@ ngx_pmemalign(ngx_pool_t *pool, size_t size, size_t alignment) return NULL; } - large = ngx_palloc(pool, sizeof(ngx_pool_large_t)); + large = ngx_palloc_small(pool, sizeof(ngx_pool_large_t), 1); if (large == NULL) { ngx_free(p); return NULL; diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c index 7f0d3ad..38bf956 100644 --- a/src/core/ngx_resolver.c +++ b/src/core/ngx_resolver.c @@ -74,8 +74,10 @@ static ngx_int_t ngx_resolver_send_tcp_query(ngx_resolver_t *r, ngx_resolver_connection_t *rec, u_char *query, u_short qlen); static ngx_int_t ngx_resolver_create_name_query(ngx_resolver_t *r, ngx_resolver_node_t *rn, ngx_str_t *name); +static ngx_int_t ngx_resolver_create_srv_query(ngx_resolver_t *r, + ngx_resolver_node_t *rn, ngx_str_t *name); static ngx_int_t ngx_resolver_create_addr_query(ngx_resolver_t *r, - ngx_resolver_node_t *rn, ngx_addr_t *addr); + ngx_resolver_node_t *rn, ngx_resolver_addr_t *addr); static void ngx_resolver_resend_handler(ngx_event_t *ev); static time_t ngx_resolver_resend(ngx_resolver_t *r, ngx_rbtree_t *tree, ngx_queue_t *queue); @@ -88,10 +90,15 @@ static void ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf, static void ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t n, ngx_uint_t ident, ngx_uint_t code, ngx_uint_t qtype, ngx_uint_t nan, ngx_uint_t trunc, ngx_uint_t ans); +static void ngx_resolver_process_srv(ngx_resolver_t *r, u_char *buf, size_t n, + ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan, + ngx_uint_t trunc, ngx_uint_t ans); static void ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n, ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan); static ngx_resolver_node_t *ngx_resolver_lookup_name(ngx_resolver_t *r, ngx_str_t *name, uint32_t hash); +static ngx_resolver_node_t *ngx_resolver_lookup_srv(ngx_resolver_t *r, + ngx_str_t *name, uint32_t hash); static ngx_resolver_node_t *ngx_resolver_lookup_addr(ngx_resolver_t *r, in_addr_t addr); static void ngx_resolver_rbtree_insert_value(ngx_rbtree_node_t *temp, @@ -105,9 +112,14 @@ 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 ngx_addr_t *ngx_resolver_export(ngx_resolver_t *r, +static ngx_resolver_addr_t *ngx_resolver_export(ngx_resolver_t *r, ngx_resolver_node_t *rn, ngx_uint_t rotate); +static void ngx_resolver_report_srv(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx); static u_char *ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t len); +static void ngx_resolver_resolve_srv_names(ngx_resolver_ctx_t *ctx, + ngx_resolver_node_t *rn); +static void ngx_resolver_srv_names_handler(ngx_resolver_ctx_t *ctx); +static ngx_int_t ngx_resolver_cmp_srvs(const void *one, const void *two); #if (NGX_HAVE_INET6) static void ngx_resolver_rbtree_insert_addr6_value(ngx_rbtree_node_t *temp, @@ -149,13 +161,18 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n) ngx_rbtree_init(&r->name_rbtree, &r->name_sentinel, ngx_resolver_rbtree_insert_value); + ngx_rbtree_init(&r->srv_rbtree, &r->srv_sentinel, + ngx_resolver_rbtree_insert_value); + ngx_rbtree_init(&r->addr_rbtree, &r->addr_sentinel, ngx_rbtree_insert_value); ngx_queue_init(&r->name_resend_queue); + ngx_queue_init(&r->srv_resend_queue); ngx_queue_init(&r->addr_resend_queue); ngx_queue_init(&r->name_expire_queue); + ngx_queue_init(&r->srv_expire_queue); ngx_queue_init(&r->addr_expire_queue); #if (NGX_HAVE_INET6) @@ -274,6 +291,8 @@ ngx_resolver_cleanup(void *data) ngx_resolver_cleanup_tree(r, &r->name_rbtree); + ngx_resolver_cleanup_tree(r, &r->srv_rbtree); + ngx_resolver_cleanup_tree(r, &r->addr_rbtree); #if (NGX_HAVE_INET6) @@ -383,7 +402,9 @@ ngx_resolve_start(ngx_resolver_t *r, ngx_resolver_ctx_t *temp) ngx_int_t ngx_resolve_name(ngx_resolver_ctx_t *ctx) { + size_t slen; ngx_int_t rc; + ngx_str_t name; ngx_resolver_t *r; r = ctx->resolver; @@ -400,9 +421,41 @@ ngx_resolve_name(ngx_resolver_ctx_t *ctx) return NGX_OK; } - /* lock name mutex */ + if (ctx->service.len) { + slen = ctx->service.len; - rc = ngx_resolve_name_locked(r, ctx, &ctx->name); + if (ngx_strlchr(ctx->service.data, + ctx->service.data + ctx->service.len, '.') + == NULL) + { + slen += sizeof("_._tcp") - 1; + } + + name.len = slen + 1 + ctx->name.len; + + name.data = ngx_resolver_alloc(r, name.len); + if (name.data == NULL) { + return NGX_ERROR; + } + + if (slen == ctx->service.len) { + ngx_sprintf(name.data, "%V.%V", &ctx->service, &ctx->name); + + } else { + ngx_sprintf(name.data, "_%V._tcp.%V", &ctx->service, &ctx->name); + } + + /* lock name mutex */ + + rc = ngx_resolve_name_locked(r, ctx, &name); + + ngx_resolver_free(r, name.data); + + } else { + /* lock name mutex */ + + rc = ngx_resolve_name_locked(r, ctx, &ctx->name); + } if (rc == NGX_OK) { return NGX_OK; @@ -429,6 +482,7 @@ ngx_resolve_name(ngx_resolver_ctx_t *ctx) void ngx_resolve_name_done(ngx_resolver_ctx_t *ctx) { + ngx_uint_t i; ngx_resolver_t *r; ngx_resolver_ctx_t *w, **p; ngx_resolver_node_t *rn; @@ -448,6 +502,23 @@ ngx_resolve_name_done(ngx_resolver_ctx_t *ctx) /* lock name mutex */ + if (ctx->nsrvs) { + for (i = 0; i < ctx->nsrvs; i++) { + if (ctx->srvs[i].ctx) { + ngx_resolve_name_done(ctx->srvs[i].ctx); + } + + if (ctx->srvs[i].addrs) { + ngx_resolver_free(r, ctx->srvs[i].addrs->sockaddr); + ngx_resolver_free(r, ctx->srvs[i].addrs); + } + + ngx_resolver_free(r, ctx->srvs[i].name.data); + } + + ngx_resolver_free(r, ctx->srvs); + } + if (ctx->state == NGX_AGAIN || ctx->state == NGX_RESOLVE_TIMEDOUT) { rn = ctx->node; @@ -466,15 +537,20 @@ ngx_resolve_name_done(ngx_resolver_ctx_t *ctx) p = &w->next; w = w->next; } - } - ngx_log_error(NGX_LOG_ALERT, r->log, 0, - "could not cancel %V resolving", &ctx->name); + ngx_log_error(NGX_LOG_ALERT, r->log, 0, + "could not cancel %V resolving", &ctx->name); + } } done: - ngx_resolver_expire(r, &r->name_rbtree, &r->name_expire_queue); + if (ctx->service.len) { + ngx_resolver_expire(r, &r->srv_rbtree, &r->srv_expire_queue); + + } else { + ngx_resolver_expire(r, &r->name_rbtree, &r->name_expire_queue); + } /* unlock name mutex */ @@ -501,16 +577,31 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx, uint32_t hash; ngx_int_t rc; ngx_str_t cname; - ngx_uint_t naddrs; - ngx_addr_t *addrs; + ngx_uint_t i, naddrs; + ngx_queue_t *resend_queue, *expire_queue; + ngx_rbtree_t *tree; ngx_resolver_ctx_t *next, *last; + ngx_resolver_addr_t *addrs; ngx_resolver_node_t *rn; ngx_strlow(name->data, name->data, name->len); hash = ngx_crc32_short(name->data, name->len); - rn = ngx_resolver_lookup_name(r, name, hash); + if (ctx->service.len) { + rn = ngx_resolver_lookup_srv(r, name, hash); + + tree = &r->srv_rbtree; + resend_queue = &r->srv_resend_queue; + expire_queue = &r->srv_expire_queue; + + } else { + rn = ngx_resolver_lookup_name(r, name, hash); + + tree = &r->name_rbtree; + resend_queue = &r->name_resend_queue; + expire_queue = &r->name_expire_queue; + } if (rn) { @@ -525,7 +616,7 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx, rn->expire = ngx_time() + r->expire; - ngx_queue_insert_head(&r->name_expire_queue, &rn->queue); + ngx_queue_insert_head(expire_queue, &rn->queue); naddrs = (rn->naddrs == (u_short) -1) ? 0 : rn->naddrs; #if (NGX_HAVE_INET6) @@ -551,6 +642,7 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx, do { ctx->state = NGX_OK; + ctx->valid = rn->valid; ctx->naddrs = naddrs; if (addrs == NULL) { @@ -580,6 +672,23 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx, return NGX_OK; } + if (rn->nsrvs) { + last->next = rn->waiting; + rn->waiting = NULL; + + /* unlock name mutex */ + + do { + next = ctx->next; + + ngx_resolver_resolve_srv_names(ctx, rn); + + ctx = next; + } while (ctx); + + return NGX_OK; + } + /* NGX_RESOLVE_CNAME */ if (ctx->recursion++ < NGX_RESOLVER_MAX_RECURSION) { @@ -597,6 +706,7 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx, do { ctx->state = NGX_RESOLVE_NXDOMAIN; + ctx->valid = ngx_time() + (r->valid ? r->valid : 10); next = ctx->next; ctx->handler(ctx); @@ -609,7 +719,7 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx, if (rn->waiting) { - if (ctx->event == NULL) { + if (ctx->event == NULL && ctx->timeout) { ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t)); if (ctx->event == NULL) { return NGX_ERROR; @@ -661,6 +771,16 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx, } #endif + if (rn->nsrvs) { + for (i = 0; i < rn->nsrvs; i++) { + if (rn->u.srvs[i].name.data) { + ngx_resolver_free_locked(r, rn->u.srvs[i].name.data); + } + } + + ngx_resolver_free_locked(r, rn->u.srvs); + } + /* unlock alloc mutex */ } else { @@ -683,17 +803,22 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx, rn->query6 = NULL; #endif - ngx_rbtree_insert(&r->name_rbtree, &rn->node); + ngx_rbtree_insert(tree, &rn->node); } - rc = ngx_resolver_create_name_query(r, rn, name); + if (ctx->service.len) { + rc = ngx_resolver_create_srv_query(r, rn, name); + + } else { + rc = ngx_resolver_create_name_query(r, rn, name); + } if (rc == NGX_ERROR) { goto failed; } if (rc == NGX_DECLINED) { - ngx_rbtree_delete(&r->name_rbtree, &rn->node); + ngx_rbtree_delete(tree, &rn->node); ngx_resolver_free(r, rn->query); ngx_resolver_free(r, rn->name); @@ -722,12 +847,13 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx, rn->naddrs6 = r->ipv6 ? (u_short) -1 : 0; rn->tcp6 = 0; #endif + rn->nsrvs = 0; if (ngx_resolver_send_query(r, rn) != NGX_OK) { goto failed; } - if (ctx->event == NULL) { + if (ctx->event == NULL && ctx->timeout) { ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t)); if (ctx->event == NULL) { goto failed; @@ -741,13 +867,13 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx, ngx_add_timer(ctx->event, ctx->timeout); } - if (ngx_queue_empty(&r->name_resend_queue)) { + if (ngx_queue_empty(resend_queue)) { ngx_add_timer(r->event, (ngx_msec_t) (r->resend_timeout * 1000)); } rn->expire = ngx_time() + r->resend_timeout; - ngx_queue_insert_head(&r->name_resend_queue, &rn->queue); + ngx_queue_insert_head(resend_queue, &rn->queue); rn->code = 0; rn->cnlen = 0; @@ -766,7 +892,7 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx, failed: - ngx_rbtree_delete(&r->name_rbtree, &rn->node); + ngx_rbtree_delete(tree, &rn->node); if (rn->query) { ngx_resolver_free(r, rn->query); @@ -859,6 +985,7 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx) /* unlock addr mutex */ ctx->state = NGX_OK; + ctx->valid = rn->valid; ctx->handler(ctx); @@ -869,18 +996,20 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx) if (rn->waiting) { - ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t)); - if (ctx->event == NULL) { - return NGX_ERROR; + if (ctx->event == NULL && ctx->timeout) { + ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t)); + if (ctx->event == NULL) { + return NGX_ERROR; + } + + ctx->event->handler = ngx_resolver_timeout_handler; + ctx->event->data = ctx; + ctx->event->log = r->log; + ctx->ident = -1; + + ngx_add_timer(ctx->event, ctx->timeout); } - ctx->event->handler = ngx_resolver_timeout_handler; - ctx->event->data = ctx; - ctx->event->log = r->log; - ctx->ident = -1; - - ngx_add_timer(ctx->event, ctx->timeout); - ctx->next = rn->waiting; rn->waiting = ctx; ctx->state = NGX_AGAIN; @@ -941,23 +1070,26 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx) rn->naddrs6 = (u_short) -1; rn->tcp6 = 0; #endif + rn->nsrvs = 0; if (ngx_resolver_send_query(r, rn) != NGX_OK) { goto failed; } - ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t)); - if (ctx->event == NULL) { - goto failed; + if (ctx->event == NULL && ctx->timeout) { + ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t)); + if (ctx->event == NULL) { + goto failed; + } + + ctx->event->handler = ngx_resolver_timeout_handler; + ctx->event->data = ctx; + ctx->event->log = r->log; + ctx->ident = -1; + + ngx_add_timer(ctx->event, ctx->timeout); } - ctx->event->handler = ngx_resolver_timeout_handler; - ctx->event->data = ctx; - ctx->event->log = r->log; - ctx->ident = -1; - - ngx_add_timer(ctx->event, ctx->timeout); - if (ngx_queue_empty(resend_queue)) { ngx_add_timer(r->event, (ngx_msec_t) (r->resend_timeout * 1000)); } @@ -1294,7 +1426,7 @@ ngx_resolver_send_tcp_query(ngx_resolver_t *r, ngx_resolver_connection_t *rec, static void ngx_resolver_resend_handler(ngx_event_t *ev) { - time_t timer, atimer, ntimer; + time_t timer, atimer, stimer, ntimer; #if (NGX_HAVE_INET6) time_t a6timer; #endif @@ -1309,6 +1441,8 @@ ngx_resolver_resend_handler(ngx_event_t *ev) ntimer = ngx_resolver_resend(r, &r->name_rbtree, &r->name_resend_queue); + stimer = ngx_resolver_resend(r, &r->srv_rbtree, &r->srv_resend_queue); + /* unlock name mutex */ /* lock addr mutex */ @@ -1336,6 +1470,13 @@ ngx_resolver_resend_handler(ngx_event_t *ev) timer = ngx_min(timer, atimer); } + if (timer == 0) { + timer = stimer; + + } else if (stimer) { + timer = ngx_min(timer, stimer); + } + #if (NGX_HAVE_INET6) if (timer == 0) { @@ -1696,6 +1837,13 @@ found: break; + case NGX_RESOLVE_SRV: + + ngx_resolver_process_srv(r, buf, n, ident, code, nan, trunc, + i + sizeof(ngx_resolver_qs_t)); + + break; + case NGX_RESOLVE_PTR: ngx_resolver_process_ptr(r, buf, n, ident, code, nan); @@ -1749,7 +1897,6 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t n, uint32_t hash; in_addr_t *addr; ngx_str_t name; - ngx_addr_t *addrs; ngx_uint_t type, class, qident, naddrs, a, i, j, start; #if (NGX_HAVE_INET6) struct in6_addr *addr6; @@ -1757,6 +1904,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t n, ngx_resolver_an_t *an; ngx_resolver_ctx_t *ctx, *next; ngx_resolver_node_t *rn; + ngx_resolver_addr_t *addrs; ngx_resolver_connection_t *rec; if (ngx_resolver_copy(r, &name, buf, @@ -1948,6 +2096,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t n, while (next) { ctx = next; ctx->state = code; + ctx->valid = ngx_time() + (r->valid ? r->valid : 10); next = ctx->next; ctx->handler(ctx); @@ -2262,6 +2411,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t n, while (next) { ctx = next; ctx->state = NGX_OK; + ctx->valid = rn->valid; ctx->naddrs = naddrs; if (addrs == NULL) { @@ -2390,6 +2540,536 @@ next: } +static void +ngx_resolver_process_srv(ngx_resolver_t *r, u_char *buf, size_t n, + ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan, + ngx_uint_t trunc, ngx_uint_t ans) +{ + char *err; + u_char *cname; + size_t len; + int32_t ttl; + uint32_t hash; + ngx_str_t name; + ngx_uint_t type, qident, class, start, nsrvs, a, i, j; + ngx_resolver_an_t *an; + ngx_resolver_ctx_t *ctx, *next; + ngx_resolver_srv_t *srvs; + ngx_resolver_node_t *rn; + ngx_resolver_connection_t *rec; + + if (ngx_resolver_copy(r, &name, buf, + buf + sizeof(ngx_resolver_hdr_t), buf + n) + != NGX_OK) + { + return; + } + + ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver qs:%V", &name); + + hash = ngx_crc32_short(name.data, name.len); + + rn = ngx_resolver_lookup_srv(r, &name, hash); + + if (rn == NULL || rn->query == NULL) { + ngx_log_error(r->log_level, r->log, 0, + "unexpected response for %V", &name); + ngx_resolver_free(r, name.data); + goto failed; + } + + if (trunc && rn->tcp) { + ngx_resolver_free(r, name.data); + goto failed; + } + + qident = (rn->query[0] << 8) + rn->query[1]; + + if (ident != qident) { + ngx_log_error(r->log_level, r->log, 0, + "wrong ident %ui response for %V, expect %ui", + ident, &name, qident); + ngx_resolver_free(r, name.data); + goto failed; + } + + ngx_resolver_free(r, name.data); + + if (trunc) { + + ngx_queue_remove(&rn->queue); + + if (rn->waiting == NULL) { + ngx_rbtree_delete(&r->srv_rbtree, &rn->node); + ngx_resolver_free_node(r, rn); + return; + } + + rec = r->connections.elts; + rec = &rec[rn->last_connection]; + + rn->tcp = 1; + + (void) ngx_resolver_send_tcp_query(r, rec, rn->query, rn->qlen); + + rn->expire = ngx_time() + r->resend_timeout; + + ngx_queue_insert_head(&r->srv_resend_queue, &rn->queue); + + return; + } + + if (code == 0 && rn->code) { + code = rn->code; + } + + if (code == 0 && nan == 0) { + code = NGX_RESOLVE_NXDOMAIN; + } + + if (code) { + next = rn->waiting; + rn->waiting = NULL; + + ngx_queue_remove(&rn->queue); + + ngx_rbtree_delete(&r->srv_rbtree, &rn->node); + + while (next) { + ctx = next; + ctx->state = code; + ctx->valid = ngx_time() + (r->valid ? r->valid : 10); + next = ctx->next; + + ctx->handler(ctx); + } + + ngx_resolver_free_node(r, rn); + + return; + } + + i = ans; + nsrvs = 0; + cname = NULL; + + for (a = 0; a < nan; a++) { + + start = i; + + while (i < n) { + + if (buf[i] & 0xc0) { + i += 2; + goto found; + } + + if (buf[i] == 0) { + i++; + goto test_length; + } + + i += 1 + buf[i]; + } + + goto short_response; + + test_length: + + if (i - start < 2) { + err = "invalid name DNS response"; + goto invalid; + } + + found: + + if (i + sizeof(ngx_resolver_an_t) >= n) { + goto short_response; + } + + an = (ngx_resolver_an_t *) &buf[i]; + + type = (an->type_hi << 8) + an->type_lo; + class = (an->class_hi << 8) + an->class_lo; + len = (an->len_hi << 8) + an->len_lo; + ttl = (an->ttl[0] << 24) + (an->ttl[1] << 16) + + (an->ttl[2] << 8) + (an->ttl[3]); + + if (class != 1) { + ngx_log_error(r->log_level, r->log, 0, + "unexpected RR class %ui", class); + goto failed; + } + + if (ttl < 0) { + ttl = 0; + } + + rn->ttl = ngx_min(rn->ttl, (uint32_t) ttl); + + i += sizeof(ngx_resolver_an_t); + + switch (type) { + + case NGX_RESOLVE_SRV: + + if (i + 6 > n) { + goto short_response; + } + + if (ngx_resolver_copy(r, NULL, buf, &buf[i + 6], buf + n) + != NGX_OK) + { + goto failed; + } + + nsrvs++; + + break; + + case NGX_RESOLVE_CNAME: + + cname = &buf[i]; + + break; + + case NGX_RESOLVE_DNAME: + + break; + + default: + + ngx_log_error(r->log_level, r->log, 0, + "unexpected RR type %ui", type); + } + + i += len; + } + + ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0, + "resolver nsrvs:%ui cname:%p ttl:%uD", + nsrvs, cname, rn->ttl); + + if (nsrvs) { + + srvs = ngx_resolver_calloc(r, nsrvs * sizeof(ngx_resolver_srv_t)); + if (srvs == NULL) { + goto failed; + } + + rn->u.srvs = srvs; + rn->nsrvs = (u_short) nsrvs; + + j = 0; + i = ans; + + for (a = 0; a < nan; a++) { + + for ( ;; ) { + + if (buf[i] & 0xc0) { + i += 2; + break; + } + + if (buf[i] == 0) { + i++; + break; + } + + i += 1 + buf[i]; + } + + an = (ngx_resolver_an_t *) &buf[i]; + + type = (an->type_hi << 8) + an->type_lo; + len = (an->len_hi << 8) + an->len_lo; + + i += sizeof(ngx_resolver_an_t); + + if (type == NGX_RESOLVE_SRV) { + + srvs[j].priority = (buf[i] << 8) + buf[i + 1]; + srvs[j].weight = (buf[i + 2] << 8) + buf[i + 3]; + + if (srvs[j].weight == 0) { + srvs[j].weight = 1; + } + + srvs[j].port = (buf[i + 4] << 8) + buf[i + 5]; + + if (ngx_resolver_copy(r, &srvs[j].name, buf, &buf[i + 6], + buf + n) + != NGX_OK) + { + goto failed; + } + + j++; + } + + i += len; + } + + ngx_sort(srvs, nsrvs, sizeof(ngx_resolver_srv_t), + ngx_resolver_cmp_srvs); + + ngx_resolver_free(r, rn->query); + rn->query = NULL; + + ngx_queue_remove(&rn->queue); + + rn->valid = ngx_time() + (r->valid ? r->valid : (time_t) rn->ttl); + rn->expire = ngx_time() + r->expire; + + ngx_queue_insert_head(&r->srv_expire_queue, &rn->queue); + + next = rn->waiting; + rn->waiting = NULL; + + while (next) { + ctx = next; + next = ctx->next; + + ngx_resolver_resolve_srv_names(ctx, rn); + } + + return; + } + + rn->nsrvs = 0; + + if (cname) { + + /* CNAME only */ + + if (ngx_resolver_copy(r, &name, buf, cname, buf + n) != NGX_OK) { + goto failed; + } + + ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0, + "resolver cname:\"%V\"", &name); + + ngx_queue_remove(&rn->queue); + + rn->cnlen = (u_short) name.len; + rn->u.cname = name.data; + + rn->valid = ngx_time() + (r->valid ? r->valid : (time_t) rn->ttl); + rn->expire = ngx_time() + r->expire; + + ngx_queue_insert_head(&r->srv_expire_queue, &rn->queue); + + ngx_resolver_free(r, rn->query); + rn->query = NULL; +#if (NGX_HAVE_INET6) + rn->query6 = NULL; +#endif + + ctx = rn->waiting; + rn->waiting = NULL; + + if (ctx) { + + if (ctx->recursion++ >= NGX_RESOLVER_MAX_RECURSION) { + + /* unlock name mutex */ + + do { + ctx->state = NGX_RESOLVE_NXDOMAIN; + next = ctx->next; + + ctx->handler(ctx); + + ctx = next; + } while (ctx); + + return; + } + + for (next = ctx; next; next = next->next) { + next->node = NULL; + } + + (void) ngx_resolve_name_locked(r, ctx, &name); + } + + /* unlock name mutex */ + + return; + } + + ngx_log_error(r->log_level, r->log, 0, "no SRV type in DNS response"); + + return; + +short_response: + + err = "short DNS response"; + +invalid: + + /* unlock name mutex */ + + ngx_log_error(r->log_level, r->log, 0, err); + + return; + +failed: + + /* unlock name mutex */ + + return; +} + + +static void +ngx_resolver_resolve_srv_names(ngx_resolver_ctx_t *ctx, ngx_resolver_node_t *rn) +{ + ngx_uint_t i; + ngx_resolver_t *r; + ngx_resolver_ctx_t *cctx; + ngx_resolver_srv_name_t *srvs; + + r = ctx->resolver; + + ctx->node = NULL; + ctx->state = NGX_OK; + ctx->valid = rn->valid; + ctx->count = rn->nsrvs; + + srvs = ngx_resolver_calloc(r, rn->nsrvs * sizeof(ngx_resolver_srv_name_t)); + if (srvs == NULL) { + goto failed; + } + + ctx->srvs = srvs; + ctx->nsrvs = rn->nsrvs; + + for (i = 0; i < rn->nsrvs; i++) { + srvs[i].name.data = ngx_resolver_alloc(r, rn->u.srvs[i].name.len); + if (srvs[i].name.data == NULL) { + goto failed; + } + + srvs[i].name.len = rn->u.srvs[i].name.len; + ngx_memcpy(srvs[i].name.data, rn->u.srvs[i].name.data, + srvs[i].name.len); + + cctx = ngx_resolve_start(r, NULL); + if (cctx == NULL) { + goto failed; + } + + cctx->name = srvs[i].name; + cctx->handler = ngx_resolver_srv_names_handler; + cctx->data = ctx; + cctx->srvs = &srvs[i]; + cctx->timeout = 0; + + srvs[i].priority = rn->u.srvs[i].priority; + srvs[i].weight = rn->u.srvs[i].weight; + srvs[i].port = rn->u.srvs[i].port; + srvs[i].ctx = cctx; + + if (ngx_resolve_name(cctx) == NGX_ERROR) { + srvs[i].ctx = NULL; + goto failed; + } + } + + return; + +failed: + + ctx->state = NGX_ERROR; + ctx->valid = ngx_time() + (r->valid ? r->valid : 10); + + ctx->handler(ctx); +} + + +static void +ngx_resolver_srv_names_handler(ngx_resolver_ctx_t *cctx) +{ + ngx_uint_t i; + u_char (*sockaddr)[NGX_SOCKADDRLEN]; + ngx_addr_t *addrs; + ngx_resolver_t *r; + struct sockaddr_in *sin; + ngx_resolver_ctx_t *ctx; + ngx_resolver_srv_name_t *srv; +#if (NGX_HAVE_INET6) + struct sockaddr_in6 *sin6; +#endif + + r = cctx->resolver; + ctx = cctx->data; + srv = cctx->srvs; + + ctx->count--; + + srv->ctx = NULL; + + if (cctx->naddrs) { + + ctx->valid = ngx_min(ctx->valid, cctx->valid); + + addrs = ngx_resolver_calloc(r, cctx->naddrs * sizeof(ngx_addr_t)); + if (addrs == NULL) { + ngx_resolve_name_done(cctx); + + ctx->state = NGX_ERROR; + ctx->valid = ngx_time() + (r->valid ? r->valid : 10); + + ctx->handler(ctx); + return; + } + + sockaddr = ngx_resolver_alloc(r, cctx->naddrs * NGX_SOCKADDRLEN); + if (sockaddr == NULL) { + ngx_resolver_free(r, addrs); + ngx_resolve_name_done(cctx); + + ctx->state = NGX_ERROR; + ctx->valid = ngx_time() + (r->valid ? r->valid : 10); + + ctx->handler(ctx); + return; + } + + for (i = 0; i < cctx->naddrs; i++) { + addrs[i].sockaddr = (struct sockaddr *) sockaddr[i]; + addrs[i].socklen = cctx->addrs[i].socklen; + + ngx_memcpy(sockaddr[i], cctx->addrs[i].sockaddr, + addrs[i].socklen); + + switch (addrs[i].sockaddr->sa_family) { +#if (NGX_HAVE_INET6) + case AF_INET6: + sin6 = (struct sockaddr_in6 *) addrs[i].sockaddr; + sin6->sin6_port = htons(srv->port); + break; +#endif + default: /* AF_INET */ + sin = (struct sockaddr_in *) addrs[i].sockaddr; + sin->sin_port = htons(srv->port); + } + } + + srv->addrs = addrs; + srv->naddrs = cctx->naddrs; + } + + ngx_resolve_name_done(cctx); + + if (ctx->count == 0) { + ngx_resolver_report_srv(r, ctx); + } +} + + static void ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n, ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan) @@ -2541,6 +3221,7 @@ valid: while (next) { ctx = next; ctx->state = code; + ctx->valid = ngx_time() + (r->valid ? r->valid : 10); next = ctx->next; ctx->handler(ctx); @@ -2675,6 +3356,7 @@ ptr: while (next) { ctx = next; ctx->state = NGX_OK; + ctx->valid = rn->valid; ctx->name = name; next = ctx->next; @@ -2746,6 +3428,47 @@ ngx_resolver_lookup_name(ngx_resolver_t *r, ngx_str_t *name, uint32_t hash) } +static ngx_resolver_node_t * +ngx_resolver_lookup_srv(ngx_resolver_t *r, ngx_str_t *name, uint32_t hash) +{ + ngx_int_t rc; + ngx_rbtree_node_t *node, *sentinel; + ngx_resolver_node_t *rn; + + node = r->srv_rbtree.root; + sentinel = r->srv_rbtree.sentinel; + + while (node != sentinel) { + + if (hash < node->key) { + node = node->left; + continue; + } + + if (hash > node->key) { + node = node->right; + continue; + } + + /* hash == node->key */ + + rn = ngx_resolver_node(node); + + rc = ngx_memn2cmp(name->data, rn->name, name->len, rn->nlen); + + if (rc == 0) { + return rn; + } + + node = (rc < 0) ? node->left : node->right; + } + + /* not found */ + + return NULL; +} + + static ngx_resolver_node_t * ngx_resolver_lookup_addr(ngx_resolver_t *r, in_addr_t addr) { @@ -3033,9 +3756,97 @@ ngx_resolver_create_name_query(ngx_resolver_t *r, ngx_resolver_node_t *rn, } +static ngx_int_t +ngx_resolver_create_srv_query(ngx_resolver_t *r, ngx_resolver_node_t *rn, + ngx_str_t *name) +{ + u_char *p, *s; + size_t len, nlen; + ngx_uint_t ident; + ngx_resolver_qs_t *qs; + ngx_resolver_hdr_t *query; + + nlen = name->len ? (1 + name->len + 1) : 1; + + len = sizeof(ngx_resolver_hdr_t) + nlen + sizeof(ngx_resolver_qs_t); + + p = ngx_resolver_alloc(r, len); + if (p == NULL) { + return NGX_ERROR; + } + + rn->qlen = (u_short) len; + rn->query = p; + + query = (ngx_resolver_hdr_t *) p; + + ident = ngx_random(); + + ngx_log_debug2(NGX_LOG_DEBUG_CORE, r->log, 0, + "resolve: \"%V\" SRV %i", name, ident & 0xffff); + + query->ident_hi = (u_char) ((ident >> 8) & 0xff); + query->ident_lo = (u_char) (ident & 0xff); + + /* recursion query */ + query->flags_hi = 1; query->flags_lo = 0; + + /* one question */ + query->nqs_hi = 0; query->nqs_lo = 1; + query->nan_hi = 0; query->nan_lo = 0; + query->nns_hi = 0; query->nns_lo = 0; + query->nar_hi = 0; query->nar_lo = 0; + + p += sizeof(ngx_resolver_hdr_t) + nlen; + + qs = (ngx_resolver_qs_t *) p; + + /* query type */ + qs->type_hi = 0; qs->type_lo = NGX_RESOLVE_SRV; + + /* IN query class */ + qs->class_hi = 0; qs->class_lo = 1; + + /* converts "www.example.com" to "\3www\7example\3com\0" */ + + len = 0; + p--; + *p-- = '\0'; + + if (name->len == 0) { + return NGX_DECLINED; + } + + for (s = name->data + name->len - 1; s >= name->data; s--) { + if (*s != '.') { + *p = *s; + len++; + + } else { + if (len == 0 || len > 255) { + return NGX_DECLINED; + } + + *p = (u_char) len; + len = 0; + } + + p--; + } + + if (len == 0 || len > 255) { + return NGX_DECLINED; + } + + *p = (u_char) len; + + return NGX_OK; +} + + static ngx_int_t ngx_resolver_create_addr_query(ngx_resolver_t *r, ngx_resolver_node_t *rn, - ngx_addr_t *addr) + ngx_resolver_addr_t *addr) { u_char *p, *d; size_t len; @@ -3239,6 +4050,8 @@ ngx_resolver_timeout_handler(ngx_event_t *ev) static void ngx_resolver_free_node(ngx_resolver_t *r, ngx_resolver_node_t *rn) { + ngx_uint_t i; + /* lock alloc mutex */ if (rn->query) { @@ -3263,6 +4076,16 @@ ngx_resolver_free_node(ngx_resolver_t *r, ngx_resolver_node_t *rn) } #endif + if (rn->nsrvs) { + for (i = 0; i < rn->nsrvs; i++) { + if (rn->u.srvs[i].name.data) { + ngx_resolver_free_locked(r, rn->u.srvs[i].name.data); + } + } + + ngx_resolver_free_locked(r, rn->u.srvs); + } + ngx_resolver_free_locked(r, rn); /* unlock alloc mutex */ @@ -3334,15 +4157,15 @@ ngx_resolver_dup(ngx_resolver_t *r, void *src, size_t size) } -static ngx_addr_t * +static ngx_resolver_addr_t * ngx_resolver_export(ngx_resolver_t *r, ngx_resolver_node_t *rn, ngx_uint_t rotate) { - ngx_addr_t *dst; ngx_uint_t d, i, j, n; u_char (*sockaddr)[NGX_SOCKADDRLEN]; in_addr_t *addr; struct sockaddr_in *sin; + ngx_resolver_addr_t *dst; #if (NGX_HAVE_INET6) struct in6_addr *addr6; struct sockaddr_in6 *sin6; @@ -3353,7 +4176,7 @@ ngx_resolver_export(ngx_resolver_t *r, ngx_resolver_node_t *rn, n += rn->naddrs6; #endif - dst = ngx_resolver_calloc(r, n * sizeof(ngx_addr_t)); + dst = ngx_resolver_calloc(r, n * sizeof(ngx_resolver_addr_t)); if (dst == NULL) { return NULL; } @@ -3417,6 +4240,99 @@ ngx_resolver_export(ngx_resolver_t *r, ngx_resolver_node_t *rn, } +static void +ngx_resolver_report_srv(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx) +{ + ngx_uint_t naddrs, nsrvs, nw, i, j, k, l, m, n, w; + ngx_resolver_addr_t *addrs; + ngx_resolver_srv_name_t *srvs; + + naddrs = 0; + + for (i = 0; i < ctx->nsrvs; i++) { + naddrs += ctx->srvs[i].naddrs; + } + + if (naddrs == 0) { + ctx->state = NGX_RESOLVE_NXDOMAIN; + ctx->valid = ngx_time() + (r->valid ? r->valid : 10); + + ctx->handler(ctx); + return; + } + + addrs = ngx_resolver_calloc(r, naddrs * sizeof(ngx_resolver_addr_t)); + if (addrs == NULL) { + ctx->state = NGX_ERROR; + ctx->valid = ngx_time() + (r->valid ? r->valid : 10); + + ctx->handler(ctx); + return; + } + + srvs = ctx->srvs; + nsrvs = ctx->nsrvs; + + i = 0; + n = 0; + + do { + nw = 0; + + for (j = i; j < nsrvs; j++) { + if (srvs[j].priority != srvs[i].priority) { + break; + } + + nw += srvs[j].naddrs * srvs[j].weight; + } + + if (nw == 0) { + goto next_srv; + } + + w = ngx_random() % nw; + + for (k = i; k < j; k++) { + if (w < srvs[k].naddrs * srvs[k].weight) { + break; + } + + w -= srvs[k].naddrs * srvs[k].weight; + } + + for (l = i; l < j; l++) { + + for (m = 0; m < srvs[k].naddrs; m++) { + addrs[n].socklen = srvs[k].addrs[m].socklen; + addrs[n].sockaddr = srvs[k].addrs[m].sockaddr; + addrs[n].name = srvs[k].name; + addrs[n].priority = srvs[k].priority; + addrs[n].weight = srvs[k].weight; + n++; + } + + if (++k == j) { + k = i; + } + } + +next_srv: + + i = j; + + } while (i < ctx->nsrvs); + + ctx->state = NGX_OK; + ctx->addrs = addrs; + ctx->naddrs = naddrs; + + ctx->handler(ctx); + + ngx_resolver_free(r, addrs); +} + + char * ngx_resolver_strerror(ngx_int_t err) { @@ -3728,3 +4644,19 @@ failed: return NGX_ERROR; } + + +static ngx_int_t +ngx_resolver_cmp_srvs(const void *one, const void *two) +{ + ngx_int_t p1, p2; + ngx_resolver_srv_t *first, *second; + + first = (ngx_resolver_srv_t *) one; + second = (ngx_resolver_srv_t *) two; + + p1 = first->priority; + p2 = second->priority; + + return p1 - p2; +} diff --git a/src/core/ngx_resolver.h b/src/core/ngx_resolver.h index 3165abd..e36cfdc 100644 --- a/src/core/ngx_resolver.h +++ b/src/core/ngx_resolver.h @@ -21,6 +21,7 @@ #if (NGX_HAVE_INET6) #define NGX_RESOLVE_AAAA 28 #endif +#define NGX_RESOLVE_SRV 33 #define NGX_RESOLVE_DNAME 39 #define NGX_RESOLVE_FORMERR 1 @@ -57,6 +58,36 @@ typedef struct ngx_resolver_ctx_s ngx_resolver_ctx_t; typedef void (*ngx_resolver_handler_pt)(ngx_resolver_ctx_t *ctx); +typedef struct { + struct sockaddr *sockaddr; + socklen_t socklen; + ngx_str_t name; + u_short priority; + u_short weight; +} ngx_resolver_addr_t; + + +typedef struct { + ngx_str_t name; + u_short priority; + u_short weight; + u_short port; +} ngx_resolver_srv_t; + + +typedef struct { + ngx_str_t name; + u_short priority; + u_short weight; + u_short port; + + ngx_resolver_ctx_t *ctx; + + ngx_uint_t naddrs; + ngx_addr_t *addrs; +} ngx_resolver_srv_name_t; + + typedef struct { ngx_rbtree_node_t node; ngx_queue_t queue; @@ -81,10 +112,12 @@ typedef struct { in_addr_t addr; in_addr_t *addrs; u_char *cname; + ngx_resolver_srv_t *srvs; } u; u_char code; u_short naddrs; + u_short nsrvs; u_short cnlen; #if (NGX_HAVE_INET6) @@ -127,13 +160,18 @@ struct ngx_resolver_s { ngx_rbtree_t name_rbtree; ngx_rbtree_node_t name_sentinel; + ngx_rbtree_t srv_rbtree; + ngx_rbtree_node_t srv_sentinel; + ngx_rbtree_t addr_rbtree; ngx_rbtree_node_t addr_sentinel; ngx_queue_t name_resend_queue; + ngx_queue_t srv_resend_queue; ngx_queue_t addr_resend_queue; ngx_queue_t name_expire_queue; + ngx_queue_t srv_expire_queue; ngx_queue_t addr_expire_queue; #if (NGX_HAVE_INET6) @@ -163,12 +201,18 @@ struct ngx_resolver_ctx_s { ngx_int_t state; ngx_str_t name; + ngx_str_t service; + time_t valid; ngx_uint_t naddrs; - ngx_addr_t *addrs; - ngx_addr_t addr; + ngx_resolver_addr_t *addrs; + ngx_resolver_addr_t addr; struct sockaddr_in sin; + ngx_uint_t count; + ngx_uint_t nsrvs; + ngx_resolver_srv_name_t *srvs; + ngx_resolver_handler_pt handler; void *data; ngx_msec_t timeout; diff --git a/src/event/modules/ngx_devpoll_module.c b/src/event/modules/ngx_devpoll_module.c index fa8aebd..f985fbd 100644 --- a/src/event/modules/ngx_devpoll_module.c +++ b/src/event/modules/ngx_devpoll_module.c @@ -14,7 +14,9 @@ /* Solaris declarations */ +#ifndef POLLREMOVE #define POLLREMOVE 0x0800 +#endif #define DP_POLL 0xD001 #define DP_ISPOLLED 0xD002 @@ -436,7 +438,7 @@ ngx_devpoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, default: ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, - "unexpected event %04Xd for closed and removed socket %d, ", + "unexpected event %04Xd for closed and removed socket %d, " "ioctl(DP_ISPOLLED) returned rc:%d, fd:%d, event %04Xd", revents, fd, rc, pfd.fd, pfd.revents); diff --git a/src/event/modules/ngx_epoll_module.c b/src/event/modules/ngx_epoll_module.c index d7f915d..081b0e5 100644 --- a/src/event/modules/ngx_epoll_module.c +++ b/src/event/modules/ngx_epoll_module.c @@ -840,6 +840,9 @@ ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags) } wev->ready = 1; +#if (NGX_THREADS) + wev->complete = 1; +#endif if (flags & NGX_POST_EVENTS) { ngx_post_event(wev, &ngx_posted_events); diff --git a/src/event/modules/ngx_eventport_module.c b/src/event/modules/ngx_eventport_module.c index bacbb05..9184547 100644 --- a/src/event/modules/ngx_eventport_module.c +++ b/src/event/modules/ngx_eventport_module.c @@ -49,7 +49,7 @@ typedef struct port_notify { void *portnfy_user; /* user defined */ } port_notify_t; -#if (__FreeBSD_version < 700005) +#if (__FreeBSD__) && (__FreeBSD_version < 700005) typedef struct itimerspec { /* definition per POSIX.4 */ struct timespec it_interval;/* timer period */ diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c index 955622b..38f9b38 100644 --- a/src/event/ngx_event.c +++ b/src/event/ngx_event.c @@ -746,6 +746,7 @@ ngx_event_process_init(ngx_cycle_t *cycle) return NGX_ERROR; } + c->type = ls[i].type; c->log = &ls[i].log; c->listening = &ls[i]; @@ -818,7 +819,8 @@ ngx_event_process_init(ngx_cycle_t *cycle) #else - rev->handler = ngx_event_accept; + rev->handler = (c->type == SOCK_STREAM) ? ngx_event_accept + : ngx_event_recvmsg; if (ngx_use_accept_mutex #if (NGX_HAVE_REUSEPORT) @@ -1206,7 +1208,7 @@ ngx_event_core_init_conf(ngx_cycle_t *cycle, void *conf) #endif -#if (NGX_HAVE_DEVPOLL) +#if (NGX_HAVE_DEVPOLL) && !(NGX_TEST_BUILD_DEVPOLL) module = &ngx_devpoll_module; diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h index 855c58d..591005a 100644 --- a/src/event/ngx_event.h +++ b/src/event/ngx_event.h @@ -343,7 +343,8 @@ extern ngx_event_actions_t ngx_event_actions; #define NGX_DISABLE_EVENT EV_DISABLE -#elif (NGX_HAVE_DEVPOLL || NGX_HAVE_EVENTPORT) +#elif (NGX_HAVE_DEVPOLL && !(NGX_TEST_BUILD_DEVPOLL)) \ + || (NGX_HAVE_EVENTPORT && !(NGX_TEST_BUILD_EVENTPORT)) #define NGX_READ_EVENT POLLIN #define NGX_WRITE_EVENT POLLOUT @@ -352,7 +353,7 @@ extern ngx_event_actions_t ngx_event_actions; #define NGX_ONESHOT_EVENT 1 -#elif (NGX_HAVE_EPOLL) +#elif (NGX_HAVE_EPOLL) && !(NGX_TEST_BUILD_EPOLL) #define NGX_READ_EVENT (EPOLLIN|EPOLLRDHUP) #define NGX_WRITE_EVENT EPOLLOUT @@ -418,6 +419,7 @@ extern ngx_os_io_t ngx_io; #define ngx_udp_recv ngx_io.udp_recv #define ngx_send ngx_io.send #define ngx_send_chain ngx_io.send_chain +#define ngx_udp_send ngx_io.udp_send #define NGX_EVENT_MODULE 0x544E5645 /* "EVNT" */ @@ -491,6 +493,9 @@ extern ngx_module_t ngx_event_core_module; void ngx_event_accept(ngx_event_t *ev); +#if !(NGX_WIN32) +void ngx_event_recvmsg(ngx_event_t *ev); +#endif ngx_int_t ngx_trylock_accept_mutex(ngx_cycle_t *cycle); u_char *ngx_accept_log_error(ngx_log_t *log, u_char *buf, size_t len); diff --git a/src/event/ngx_event_accept.c b/src/event/ngx_event_accept.c index 8888f5a..1c87a34 100644 --- a/src/event/ngx_event_accept.c +++ b/src/event/ngx_event_accept.c @@ -13,6 +13,10 @@ static ngx_int_t ngx_enable_accept_events(ngx_cycle_t *cycle); static ngx_int_t ngx_disable_accept_events(ngx_cycle_t *cycle, ngx_uint_t all); static void ngx_close_accepted_connection(ngx_connection_t *c); +#if (NGX_DEBUG) +static void ngx_debug_accepted_connection(ngx_event_conf_t *ecf, + ngx_connection_t *c); +#endif void @@ -149,6 +153,8 @@ ngx_event_accept(ngx_event_t *ev) return; } + c->type = SOCK_STREAM; + #if (NGX_STAT_STUB) (void) ngx_atomic_fetch_add(ngx_stat_active, 1); #endif @@ -276,60 +282,10 @@ ngx_event_accept(ngx_event_t *ev) #if (NGX_DEBUG) { + ngx_str_t addr; + u_char text[NGX_SOCKADDR_STRLEN]; - ngx_str_t addr; - struct sockaddr_in *sin; - ngx_cidr_t *cidr; - ngx_uint_t i; - u_char text[NGX_SOCKADDR_STRLEN]; -#if (NGX_HAVE_INET6) - struct sockaddr_in6 *sin6; - ngx_uint_t n; -#endif - - cidr = ecf->debug_connection.elts; - for (i = 0; i < ecf->debug_connection.nelts; i++) { - if (cidr[i].family != (ngx_uint_t) 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; - } + ngx_debug_accepted_connection(ecf, c); if (log->log_level & NGX_LOG_DEBUG_EVENT) { addr.data = text; @@ -363,6 +319,324 @@ ngx_event_accept(ngx_event_t *ev) } +#if !(NGX_WIN32) + +void +ngx_event_recvmsg(ngx_event_t *ev) +{ + ssize_t n; + ngx_log_t *log; + ngx_err_t err; + ngx_event_t *rev, *wev; + struct iovec iov[1]; + struct msghdr msg; + ngx_listening_t *ls; + ngx_event_conf_t *ecf; + ngx_connection_t *c, *lc; + u_char sa[NGX_SOCKADDRLEN]; + static u_char buffer[65535]; + +#if (NGX_HAVE_MSGHDR_MSG_CONTROL) + +#if (NGX_HAVE_IP_RECVDSTADDR) + u_char msg_control[CMSG_SPACE(sizeof(struct in_addr))]; +#elif (NGX_HAVE_IP_PKTINFO) + u_char msg_control[CMSG_SPACE(sizeof(struct in_pktinfo))]; +#endif + +#if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO) + u_char msg_control6[CMSG_SPACE(sizeof(struct in6_pktinfo))]; +#endif + +#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_KQUEUE_EVENT)) { + ev->available = ecf->multi_accept; + } + + lc = ev->data; + ls = lc->listening; + ev->ready = 0; + + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0, + "recvmsg on %V, ready: %d", &ls->addr_text, ev->available); + + do { + ngx_memzero(&msg, sizeof(struct msghdr)); + + iov[0].iov_base = (void *) buffer; + iov[0].iov_len = sizeof(buffer); + + msg.msg_name = &sa; + msg.msg_namelen = sizeof(sa); + msg.msg_iov = iov; + msg.msg_iovlen = 1; + +#if (NGX_HAVE_MSGHDR_MSG_CONTROL) + + if (ls->wildcard) { + +#if (NGX_HAVE_IP_RECVDSTADDR || NGX_HAVE_IP_PKTINFO) + if (ls->sockaddr->sa_family == AF_INET) { + msg.msg_control = &msg_control; + msg.msg_controllen = sizeof(msg_control); + } +#endif + +#if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO) + if (ls->sockaddr->sa_family == AF_INET6) { + msg.msg_control = &msg_control6; + msg.msg_controllen = sizeof(msg_control6); + } +#endif + } + +#endif + + n = recvmsg(lc->fd, &msg, 0); + + if (n == -1) { + err = ngx_socket_errno; + + if (err == NGX_EAGAIN) { + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, err, + "recvmsg() not ready"); + return; + } + + ngx_log_error(NGX_LOG_ALERT, ev->log, err, "recvmsg() failed"); + + return; + } + +#if (NGX_STAT_STUB) + (void) ngx_atomic_fetch_add(ngx_stat_accepted, 1); +#endif + +#if (NGX_HAVE_MSGHDR_MSG_CONTROL) + if (msg.msg_flags & (MSG_TRUNC|MSG_CTRUNC)) { + ngx_log_error(NGX_LOG_ALERT, ev->log, 0, + "recvmsg() truncated data"); + continue; + } +#endif + + ngx_accept_disabled = ngx_cycle->connection_n / 8 + - ngx_cycle->free_connection_n; + + c = ngx_get_connection(lc->fd, ev->log); + if (c == NULL) { + return; + } + + c->shared = 1; + c->type = SOCK_DGRAM; + c->socklen = msg.msg_namelen; + +#if (NGX_STAT_STUB) + (void) ngx_atomic_fetch_add(ngx_stat_active, 1); +#endif + + c->pool = ngx_create_pool(ls->pool_size, ev->log); + if (c->pool == NULL) { + ngx_close_accepted_connection(c); + return; + } + + c->sockaddr = ngx_palloc(c->pool, c->socklen); + if (c->sockaddr == NULL) { + ngx_close_accepted_connection(c); + return; + } + + ngx_memcpy(c->sockaddr, msg.msg_name, c->socklen); + + log = ngx_palloc(c->pool, sizeof(ngx_log_t)); + if (log == NULL) { + ngx_close_accepted_connection(c); + return; + } + + *log = ls->log; + + c->send = ngx_udp_send; + + c->log = log; + c->pool->log = log; + + c->listening = ls; + c->local_sockaddr = ls->sockaddr; + c->local_socklen = ls->socklen; + +#if (NGX_HAVE_MSGHDR_MSG_CONTROL) + + if (ls->wildcard) { + struct cmsghdr *cmsg; + struct sockaddr *sockaddr; + + sockaddr = ngx_palloc(c->pool, c->local_socklen); + if (sockaddr == NULL) { + ngx_close_accepted_connection(c); + return; + } + + ngx_memcpy(sockaddr, c->local_sockaddr, c->local_socklen); + c->local_sockaddr = sockaddr; + + for (cmsg = CMSG_FIRSTHDR(&msg); + cmsg != NULL; + cmsg = CMSG_NXTHDR(&msg, cmsg)) + { + +#if (NGX_HAVE_IP_RECVDSTADDR) + + if (cmsg->cmsg_level == IPPROTO_IP + && cmsg->cmsg_type == IP_RECVDSTADDR + && sockaddr->sa_family == AF_INET) + { + struct in_addr *addr; + struct sockaddr_in *sin; + + addr = (struct in_addr *) CMSG_DATA(cmsg); + sin = (struct sockaddr_in *) sockaddr; + sin->sin_addr = *addr; + + break; + } + +#elif (NGX_HAVE_IP_PKTINFO) + + if (cmsg->cmsg_level == IPPROTO_IP + && cmsg->cmsg_type == IP_PKTINFO + && sockaddr->sa_family == AF_INET) + { + struct in_pktinfo *pkt; + struct sockaddr_in *sin; + + pkt = (struct in_pktinfo *) CMSG_DATA(cmsg); + sin = (struct sockaddr_in *) sockaddr; + sin->sin_addr = pkt->ipi_addr; + + break; + } + +#endif + +#if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO) + + if (cmsg->cmsg_level == IPPROTO_IPV6 + && cmsg->cmsg_type == IPV6_PKTINFO + && sockaddr->sa_family == AF_INET6) + { + struct in6_pktinfo *pkt6; + struct sockaddr_in6 *sin6; + + pkt6 = (struct in6_pktinfo *) CMSG_DATA(cmsg); + sin6 = (struct sockaddr_in6 *) sockaddr; + sin6->sin6_addr = pkt6->ipi6_addr; + + break; + } + +#endif + + } + } + +#endif + + c->buffer = ngx_create_temp_buf(c->pool, n); + if (c->buffer == NULL) { + ngx_close_accepted_connection(c); + return; + } + + c->buffer->last = ngx_cpymem(c->buffer->last, buffer, n); + + rev = c->read; + wev = c->write; + + wev->ready = 1; + + rev->log = log; + wev->log = log; + + /* + * TODO: MT: - ngx_atomic_fetch_add() + * or protection by critical section or light mutex + * + * TODO: MP: - allocated in a shared memory + * - ngx_atomic_fetch_add() + * or protection by critical section or light mutex + */ + + c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1); + +#if (NGX_STAT_STUB) + (void) ngx_atomic_fetch_add(ngx_stat_handled, 1); +#endif + + if (ls->addr_ntop) { + c->addr_text.data = ngx_pnalloc(c->pool, ls->addr_text_max_len); + if (c->addr_text.data == NULL) { + ngx_close_accepted_connection(c); + return; + } + + c->addr_text.len = ngx_sock_ntop(c->sockaddr, c->socklen, + c->addr_text.data, + ls->addr_text_max_len, 0); + if (c->addr_text.len == 0) { + ngx_close_accepted_connection(c); + return; + } + } + +#if (NGX_DEBUG) + { + ngx_str_t addr; + u_char text[NGX_SOCKADDR_STRLEN]; + + ngx_debug_accepted_connection(ecf, c); + + if (log->log_level & NGX_LOG_DEBUG_EVENT) { + addr.data = text; + addr.len = ngx_sock_ntop(c->sockaddr, c->socklen, text, + NGX_SOCKADDR_STRLEN, 1); + + ngx_log_debug4(NGX_LOG_DEBUG_EVENT, log, 0, + "*%uA recvmsg: %V fd:%d n:%z", + c->number, &addr, c->fd, n); + } + + } +#endif + + log->data = NULL; + log->handler = NULL; + + ls->handler(c); + + if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { + ev->available -= n; + } + + } while (ev->available); +} + +#endif + + ngx_int_t ngx_trylock_accept_mutex(ngx_cycle_t *cycle) { @@ -476,7 +750,7 @@ ngx_close_accepted_connection(ngx_connection_t *c) fd = c->fd; c->fd = (ngx_socket_t) -1; - if (ngx_close_socket(fd) == -1) { + if (!c->shared && ngx_close_socket(fd) == -1) { ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno, ngx_close_socket_n " failed"); } @@ -497,3 +771,64 @@ ngx_accept_log_error(ngx_log_t *log, u_char *buf, size_t len) return ngx_snprintf(buf, len, " while accepting new connection on %V", log->data); } + + +#if (NGX_DEBUG) + +static void +ngx_debug_accepted_connection(ngx_event_conf_t *ecf, ngx_connection_t *c) +{ + 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 + + cidr = ecf->debug_connection.elts; + for (i = 0; i < ecf->debug_connection.nelts; i++) { + if (cidr[i].family != (ngx_uint_t) 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; + } + + c->log->log_level = NGX_LOG_DEBUG_CONNECTION|NGX_LOG_DEBUG_ALL; + break; + + next: + continue; + } +} + +#endif diff --git a/src/event/ngx_event_connect.c b/src/event/ngx_event_connect.c index 1186958..8aca862 100644 --- a/src/event/ngx_event_connect.c +++ b/src/event/ngx_event_connect.c @@ -14,7 +14,7 @@ ngx_int_t ngx_event_connect_peer(ngx_peer_connection_t *pc) { - int rc; + int rc, type; ngx_int_t event; ngx_err_t err; ngx_uint_t level; @@ -27,9 +27,12 @@ ngx_event_connect_peer(ngx_peer_connection_t *pc) return rc; } - s = ngx_socket(pc->sockaddr->sa_family, SOCK_STREAM, 0); + type = (pc->type ? pc->type : SOCK_STREAM); - ngx_log_debug1(NGX_LOG_DEBUG_EVENT, pc->log, 0, "socket %d", s); + s = ngx_socket(pc->sockaddr->sa_family, type, 0); + + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, pc->log, 0, "%s socket %d", + (type == SOCK_STREAM) ? "stream" : "dgram", s); if (s == (ngx_socket_t) -1) { ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno, @@ -49,6 +52,8 @@ ngx_event_connect_peer(ngx_peer_connection_t *pc) return NGX_ERROR; } + c->type = type; + if (pc->rcvbuf) { if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, (const void *) &pc->rcvbuf, sizeof(int)) == -1) @@ -75,25 +80,31 @@ ngx_event_connect_peer(ngx_peer_connection_t *pc) } } - c->recv = ngx_recv; - c->send = ngx_send; - c->recv_chain = ngx_recv_chain; - c->send_chain = ngx_send_chain; + if (type == SOCK_STREAM) { + c->recv = ngx_recv; + c->send = ngx_send; + c->recv_chain = ngx_recv_chain; + c->send_chain = ngx_send_chain; - c->sendfile = 1; + c->sendfile = 1; - c->log_error = pc->log_error; - - if (pc->sockaddr->sa_family == AF_UNIX) { - c->tcp_nopush = NGX_TCP_NOPUSH_DISABLED; - c->tcp_nodelay = NGX_TCP_NODELAY_DISABLED; + if (pc->sockaddr->sa_family == AF_UNIX) { + c->tcp_nopush = NGX_TCP_NOPUSH_DISABLED; + c->tcp_nodelay = NGX_TCP_NODELAY_DISABLED; #if (NGX_SOLARIS) - /* Solaris's sendfilev() supports AF_NCA, AF_INET, and AF_INET6 */ - c->sendfile = 0; + /* Solaris's sendfilev() supports AF_NCA, AF_INET, and AF_INET6 */ + c->sendfile = 0; #endif + } + + } else { /* type == SOCK_DGRAM */ + c->recv = ngx_udp_recv; + c->send = ngx_send; } + c->log_error = pc->log_error; + rev = c->read; wev = c->write; diff --git a/src/event/ngx_event_connect.h b/src/event/ngx_event_connect.h index ed18db7..1bacf82 100644 --- a/src/event/ngx_event_connect.h +++ b/src/event/ngx_event_connect.h @@ -55,6 +55,7 @@ struct ngx_peer_connection_s { ngx_addr_t *local; + int type; int rcvbuf; ngx_log_t *log; diff --git a/src/event/ngx_event_pipe.c b/src/event/ngx_event_pipe.c index 2d0e7d3..ee86c7e 100644 --- a/src/event/ngx_event_pipe.c +++ b/src/event/ngx_event_pipe.c @@ -112,6 +112,14 @@ ngx_event_pipe_read_upstream(ngx_event_pipe_t *p) return NGX_OK; } +#if (NGX_THREADS) + if (p->aio) { + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, p->log, 0, + "pipe read upstream: aio"); + return NGX_AGAIN; + } +#endif + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, p->log, 0, "pipe read upstream: %d", p->upstream->read->ready); @@ -258,19 +266,6 @@ ngx_event_pipe_read_upstream(ngx_event_pipe_t *p) break; } - if (rc == NGX_AGAIN) { - if (ngx_event_flags & NGX_USE_LEVEL_EVENT - && p->upstream->read->active - && p->upstream->read->ready) - { - if (ngx_del_event(p->upstream->read, NGX_READ_EVENT, 0) - == NGX_ERROR) - { - return NGX_ABORT; - } - } - } - if (rc != NGX_OK) { return rc; } @@ -475,8 +470,10 @@ ngx_event_pipe_read_upstream(ngx_event_pipe_t *p) ngx_log_debug0(NGX_LOG_DEBUG_EVENT, p->log, 0, "pipe write chain"); - if (ngx_event_pipe_write_chain_to_temp_file(p) == NGX_ABORT) { - return NGX_ABORT; + rc = ngx_event_pipe_write_chain_to_temp_file(p); + + if (rc != NGX_OK) { + return rc; } } @@ -499,6 +496,18 @@ ngx_event_pipe_write_to_downstream(ngx_event_pipe_t *p) ngx_log_debug1(NGX_LOG_DEBUG_EVENT, p->log, 0, "pipe write downstream: %d", downstream->write->ready); +#if (NGX_THREADS) + + if (p->writing) { + rc = ngx_event_pipe_write_chain_to_temp_file(p); + + if (rc == NGX_ABORT) { + return NGX_ABORT; + } + } + +#endif + flushed = 0; for ( ;; ) { @@ -532,6 +541,10 @@ ngx_event_pipe_write_to_downstream(ngx_event_pipe_t *p) p->out = NULL; } + if (p->writing) { + break; + } + if (p->in) { ngx_log_debug0(NGX_LOG_DEBUG_EVENT, p->log, 0, "pipe write downstream flush in"); @@ -608,7 +621,7 @@ ngx_event_pipe_write_to_downstream(ngx_event_pipe_t *p) p->out = p->out->next; - } else if (!p->cacheable && p->in) { + } else if (!p->cacheable && !p->writing && p->in) { cl = p->in; ngx_log_debug3(NGX_LOG_DEBUG_EVENT, p->log, 0, @@ -710,12 +723,38 @@ ngx_event_pipe_write_chain_to_temp_file(ngx_event_pipe_t *p) ssize_t size, bsize, n; ngx_buf_t *b; ngx_uint_t prev_last_shadow; - ngx_chain_t *cl, *tl, *next, *out, **ll, **last_out, **last_free, fl; + ngx_chain_t *cl, *tl, *next, *out, **ll, **last_out, **last_free; + +#if (NGX_THREADS) + + if (p->writing) { + + if (p->aio) { + return NGX_AGAIN; + } + + out = p->writing; + p->writing = NULL; + + n = ngx_write_chain_to_temp_file(p->temp_file, NULL); + + if (n == NGX_ERROR) { + return NGX_ABORT; + } + + goto done; + } + +#endif if (p->buf_to_file) { - fl.buf = p->buf_to_file; - fl.next = p->in; - out = &fl; + out = ngx_alloc_chain_link(p->pool); + if (out == NULL) { + return NGX_ABORT; + } + + out->buf = p->buf_to_file; + out->next = p->in; } else { out = p->in; @@ -775,12 +814,31 @@ ngx_event_pipe_write_chain_to_temp_file(ngx_event_pipe_t *p) p->last_in = &p->in; } +#if (NGX_THREADS) + p->temp_file->thread_write = p->thread_handler ? 1 : 0; + p->temp_file->file.thread_task = p->thread_task; + p->temp_file->file.thread_handler = p->thread_handler; + p->temp_file->file.thread_ctx = p->thread_ctx; +#endif + n = ngx_write_chain_to_temp_file(p->temp_file, out); if (n == NGX_ERROR) { return NGX_ABORT; } +#if (NGX_THREADS) + + if (n == NGX_AGAIN) { + p->writing = out; + p->thread_task = p->temp_file->file.thread_task; + return NGX_AGAIN; + } + +done: + +#endif + if (p->buf_to_file) { p->temp_file->offset = p->buf_to_file->last - p->buf_to_file->pos; n -= p->buf_to_file->last - p->buf_to_file->pos; diff --git a/src/event/ngx_event_pipe.h b/src/event/ngx_event_pipe.h index 451fc4c..ef2e7a0 100644 --- a/src/event/ngx_event_pipe.h +++ b/src/event/ngx_event_pipe.h @@ -30,6 +30,8 @@ struct ngx_event_pipe_s { ngx_chain_t *in; ngx_chain_t **last_in; + ngx_chain_t *writing; + ngx_chain_t *out; ngx_chain_t *free; ngx_chain_t *busy; @@ -45,6 +47,13 @@ struct ngx_event_pipe_s { ngx_event_pipe_output_filter_pt output_filter; void *output_ctx; +#if (NGX_THREADS) + ngx_int_t (*thread_handler)(ngx_thread_task_t *task, + ngx_file_t *file); + void *thread_ctx; + ngx_thread_task_t *thread_task; +#endif + unsigned read:1; unsigned cacheable:1; unsigned single_buf:1; @@ -56,6 +65,7 @@ struct ngx_event_pipe_s { unsigned downstream_done:1; unsigned downstream_error:1; unsigned cyclic_temp_file:1; + unsigned aio:1; ngx_int_t allocated; ngx_bufs_t bufs; diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c index dbd7767..e3024b3 100644 --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -206,6 +206,7 @@ static ngx_conf_bitmask_t ngx_http_fastcgi_next_upstream_masks[] = { { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR }, { ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT }, { ngx_string("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER }, + { ngx_string("non_idempotent"), NGX_HTTP_UPSTREAM_FT_NON_IDEMPOTENT }, { ngx_string("http_500"), NGX_HTTP_UPSTREAM_FT_HTTP_500 }, { ngx_string("http_503"), NGX_HTTP_UPSTREAM_FT_HTTP_503 }, { ngx_string("http_403"), NGX_HTTP_UPSTREAM_FT_HTTP_403 }, diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c index a869e74..5005b6b 100644 --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -213,6 +213,7 @@ static ngx_conf_bitmask_t ngx_http_proxy_next_upstream_masks[] = { { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR }, { ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT }, { ngx_string("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER }, + { ngx_string("non_idempotent"), NGX_HTTP_UPSTREAM_FT_NON_IDEMPOTENT }, { ngx_string("http_500"), NGX_HTTP_UPSTREAM_FT_HTTP_500 }, { ngx_string("http_502"), NGX_HTTP_UPSTREAM_FT_HTTP_502 }, { ngx_string("http_503"), NGX_HTTP_UPSTREAM_FT_HTTP_503 }, diff --git a/src/http/modules/ngx_http_scgi_module.c b/src/http/modules/ngx_http_scgi_module.c index 76c7786..b468eb7 100644 --- a/src/http/modules/ngx_http_scgi_module.c +++ b/src/http/modules/ngx_http_scgi_module.c @@ -77,6 +77,7 @@ static ngx_conf_bitmask_t ngx_http_scgi_next_upstream_masks[] = { { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR }, { ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT }, { ngx_string("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER }, + { ngx_string("non_idempotent"), NGX_HTTP_UPSTREAM_FT_NON_IDEMPOTENT }, { ngx_string("http_500"), NGX_HTTP_UPSTREAM_FT_HTTP_500 }, { ngx_string("http_503"), NGX_HTTP_UPSTREAM_FT_HTTP_503 }, { ngx_string("http_403"), NGX_HTTP_UPSTREAM_FT_HTTP_403 }, diff --git a/src/http/modules/ngx_http_sub_filter_module.c b/src/http/modules/ngx_http_sub_filter_module.c index 8ba75ed..7bf6e19 100644 --- a/src/http/modules/ngx_http_sub_filter_module.c +++ b/src/http/modules/ngx_http_sub_filter_module.c @@ -229,7 +229,7 @@ ngx_http_sub_header_filter(ngx_http_request_t *r) return ngx_http_next_header_filter(r); } - ctx->matches = ngx_pnalloc(r->pool, sizeof(ngx_array_t)); + ctx->matches = ngx_palloc(r->pool, sizeof(ngx_array_t)); if (ctx->matches == NULL) { return NGX_ERROR; } @@ -237,7 +237,7 @@ ngx_http_sub_header_filter(ngx_http_request_t *r) ctx->matches->elts = matches; ctx->matches->nelts = j; - ctx->tables = ngx_pnalloc(r->pool, sizeof(ngx_http_sub_tables_t)); + ctx->tables = ngx_palloc(r->pool, sizeof(ngx_http_sub_tables_t)); if (ctx->tables == NULL) { return NGX_ERROR; } @@ -859,7 +859,7 @@ ngx_http_sub_merge_conf(ngx_conf_t *cf, void *parent, void *child) pairs = conf->pairs->elts; n = conf->pairs->nelts; - matches = ngx_pnalloc(cf->pool, sizeof(ngx_http_sub_match_t) * n); + matches = ngx_palloc(cf->pool, sizeof(ngx_http_sub_match_t) * n); if (matches == NULL) { return NGX_CONF_ERROR; } @@ -869,7 +869,7 @@ ngx_http_sub_merge_conf(ngx_conf_t *cf, void *parent, void *child) matches[i].value = &pairs[i].value; } - conf->matches = ngx_pnalloc(cf->pool, sizeof(ngx_array_t)); + conf->matches = ngx_palloc(cf->pool, sizeof(ngx_array_t)); if (conf->matches == NULL) { return NGX_CONF_ERROR; } diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c index 0313dfa..fef2c46 100644 --- a/src/http/modules/ngx_http_uwsgi_module.c +++ b/src/http/modules/ngx_http_uwsgi_module.c @@ -109,6 +109,7 @@ static ngx_conf_bitmask_t ngx_http_uwsgi_next_upstream_masks[] = { { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR }, { ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT }, { ngx_string("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER }, + { ngx_string("non_idempotent"), NGX_HTTP_UPSTREAM_FT_NON_IDEMPOTENT }, { ngx_string("http_500"), NGX_HTTP_UPSTREAM_FT_HTTP_500 }, { ngx_string("http_503"), NGX_HTTP_UPSTREAM_FT_HTTP_503 }, { ngx_string("http_403"), NGX_HTTP_UPSTREAM_FT_HTTP_403 }, diff --git a/src/http/ngx_http_cache.h b/src/http/ngx_http_cache.h index d36fa77..2667cbb 100644 --- a/src/http/ngx_http_cache.h +++ b/src/http/ngx_http_cache.h @@ -138,6 +138,8 @@ typedef struct { ngx_atomic_t cold; ngx_atomic_t loading; off_t size; + ngx_uint_t count; + ngx_uint_t watermark; } ngx_http_file_cache_sh_t; @@ -153,6 +155,8 @@ struct ngx_http_file_cache_s { time_t inactive; + time_t fail_time; + ngx_uint_t files; ngx_uint_t loader_files; ngx_msec_t last; diff --git a/src/http/ngx_http_copy_filter_module.c b/src/http/ngx_http_copy_filter_module.c index c6d03ee..c696fb6 100644 --- a/src/http/ngx_http_copy_filter_module.c +++ b/src/http/ngx_http_copy_filter_module.c @@ -204,10 +204,11 @@ ngx_http_copy_aio_event_handler(ngx_event_t *ev) static ssize_t ngx_http_copy_aio_sendfile_preload(ngx_buf_t *file) { - ssize_t n; - static u_char buf[1]; - ngx_event_aio_t *aio; - ngx_http_request_t *r; + ssize_t n; + static u_char buf[1]; + ngx_event_aio_t *aio; + ngx_http_request_t *r; + ngx_output_chain_ctx_t *ctx; n = ngx_file_aio_read(file->file, buf, 1, file->file_pos, NULL); @@ -218,6 +219,9 @@ ngx_http_copy_aio_sendfile_preload(ngx_buf_t *file) r = aio->data; r->main->blocked++; r->aio = 1; + + ctx = ngx_http_get_module_ctx(r, ngx_http_copy_filter_module); + ctx->aio = 1; } return n; @@ -252,6 +256,7 @@ ngx_http_copy_thread_handler(ngx_thread_task_t *task, ngx_file_t *file) ngx_str_t name; ngx_thread_pool_t *tp; ngx_http_request_t *r; + ngx_output_chain_ctx_t *ctx; ngx_http_core_loc_conf_t *clcf; r = file->thread_ctx; @@ -285,6 +290,9 @@ ngx_http_copy_thread_handler(ngx_thread_task_t *task, ngx_file_t *file) r->main->blocked++; r->aio = 1; + ctx = ngx_http_get_module_ctx(r, ngx_http_copy_filter_module); + ctx->aio = 1; + return NGX_OK; } diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index df7e8d4..b88e869 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -400,6 +400,13 @@ static ngx_command_t ngx_http_core_commands[] = { 0, NULL }, + { ngx_string("aio_write"), + 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_core_loc_conf_t, aio_write), + NULL }, + { ngx_string("read_ahead"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_size_slot, @@ -3606,6 +3613,7 @@ ngx_http_core_create_loc_conf(ngx_conf_t *cf) clcf->sendfile = NGX_CONF_UNSET; clcf->sendfile_max_chunk = NGX_CONF_UNSET_SIZE; clcf->aio = NGX_CONF_UNSET; + clcf->aio_write = NGX_CONF_UNSET; #if (NGX_THREADS) clcf->thread_pool = NGX_CONF_UNSET_PTR; clcf->thread_pool_value = NGX_CONF_UNSET_PTR; @@ -3827,6 +3835,7 @@ ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) prev->sendfile_max_chunk, 0); #if (NGX_HAVE_FILE_AIO || NGX_THREADS) ngx_conf_merge_value(conf->aio, prev->aio, NGX_HTTP_AIO_OFF); + ngx_conf_merge_value(conf->aio_write, prev->aio_write, 0); #endif #if (NGX_THREADS) ngx_conf_merge_ptr_value(conf->thread_pool, prev->thread_pool, NULL); diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h index 7dec9e1..231c507 100644 --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -404,6 +404,7 @@ struct ngx_http_core_loc_conf_s { ngx_flag_t internal; /* internal */ ngx_flag_t sendfile; /* sendfile */ ngx_flag_t aio; /* aio */ + ngx_flag_t aio_write; /* aio_write */ ngx_flag_t tcp_nopush; /* tcp_nopush */ ngx_flag_t tcp_nodelay; /* tcp_nodelay */ ngx_flag_t reset_timedout_connection; /* reset_timedout_connection */ diff --git a/src/http/ngx_http_file_cache.c b/src/http/ngx_http_file_cache.c index 6633918..3561028 100644 --- a/src/http/ngx_http_file_cache.c +++ b/src/http/ngx_http_file_cache.c @@ -62,6 +62,7 @@ static ngx_int_t ngx_http_file_cache_add(ngx_http_file_cache_t *cache, ngx_http_cache_t *c); static ngx_int_t ngx_http_file_cache_delete_file(ngx_tree_ctx_t *ctx, ngx_str_t *path); +static void ngx_http_file_cache_set_watermark(ngx_http_file_cache_t *cache); ngx_str_t ngx_http_cache_status[] = { @@ -147,6 +148,8 @@ ngx_http_file_cache_init(ngx_shm_zone_t *shm_zone, void *data) cache->sh->cold = 1; cache->sh->loading = 0; cache->sh->size = 0; + cache->sh->count = 0; + cache->sh->watermark = (ngx_uint_t) -1; cache->bsize = ngx_fs_bsize(cache->path->name.data); @@ -691,12 +694,13 @@ ngx_http_file_cache_aio_read(ngx_http_request_t *r, ngx_http_cache_t *c) #if (NGX_THREADS) if (clcf->aio == NGX_HTTP_AIO_THREADS) { + c->file.thread_task = c->thread_task; c->file.thread_handler = ngx_http_cache_thread_handler; c->file.thread_ctx = r; - n = ngx_thread_read(&c->thread_task, &c->file, c->buf->pos, - c->body_start, 0, r->pool); + n = ngx_thread_read(&c->file, c->buf->pos, c->body_start, 0, r->pool); + c->thread_task = c->file.thread_task; c->reading = (n == NGX_AGAIN); return n; @@ -860,6 +864,8 @@ ngx_http_file_cache_exists(ngx_http_file_cache_t *cache, ngx_http_cache_t *c) fcn = ngx_slab_calloc_locked(cache->shpool, sizeof(ngx_http_file_cache_node_t)); if (fcn == NULL) { + ngx_http_file_cache_set_watermark(cache); + ngx_shmtx_unlock(&cache->shpool->mutex); (void) ngx_http_file_cache_forced_expire(cache); @@ -876,6 +882,8 @@ ngx_http_file_cache_exists(ngx_http_file_cache_t *cache, ngx_http_cache_t *c) } } + cache->sh->count++; + ngx_memcpy((u_char *) &fcn->node.key, c->key, sizeof(ngx_rbtree_key_t)); ngx_memcpy(fcn->key, &c->key[sizeof(ngx_rbtree_key_t)], @@ -1630,6 +1638,7 @@ ngx_http_file_cache_free(ngx_http_cache_t *c, ngx_temp_file_t *tf) ngx_queue_remove(&fcn->queue); ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node); ngx_slab_free_locked(cache->shpool, fcn); + cache->sh->count--; c->node = NULL; } @@ -1882,6 +1891,7 @@ ngx_http_file_cache_delete(ngx_http_file_cache_t *cache, ngx_queue_t *q, ngx_queue_remove(q); ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node); ngx_slab_free_locked(cache->shpool, fcn); + cache->sh->count--; } } @@ -1891,8 +1901,9 @@ ngx_http_file_cache_manager(void *data) { ngx_http_file_cache_t *cache = data; - off_t size; - time_t next, wait; + off_t size; + time_t next, wait; + ngx_uint_t count, watermark; next = ngx_http_file_cache_expire(cache); @@ -1903,13 +1914,16 @@ ngx_http_file_cache_manager(void *data) ngx_shmtx_lock(&cache->shpool->mutex); size = cache->sh->size; + count = cache->sh->count; + watermark = cache->sh->watermark; ngx_shmtx_unlock(&cache->shpool->mutex); - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, - "http file cache size: %O", size); + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, + "http file cache size: %O c:%ui w:%i", + size, count, (ngx_int_t) watermark); - if (size < cache->max_size) { + if (size < cache->max_size && count < watermark) { return next; } @@ -2093,10 +2107,20 @@ ngx_http_file_cache_add(ngx_http_file_cache_t *cache, ngx_http_cache_t *c) fcn = ngx_slab_calloc_locked(cache->shpool, sizeof(ngx_http_file_cache_node_t)); if (fcn == NULL) { + ngx_http_file_cache_set_watermark(cache); + + if (cache->fail_time != ngx_time()) { + cache->fail_time = ngx_time(); + ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, + "could not allocate node%s", cache->shpool->log_ctx); + } + ngx_shmtx_unlock(&cache->shpool->mutex); return NGX_ERROR; } + cache->sh->count++; + ngx_memcpy((u_char *) &fcn->node.key, c->key, sizeof(ngx_rbtree_key_t)); ngx_memcpy(fcn->key, &c->key[sizeof(ngx_rbtree_key_t)], @@ -2139,6 +2163,16 @@ ngx_http_file_cache_delete_file(ngx_tree_ctx_t *ctx, ngx_str_t *path) } +static void +ngx_http_file_cache_set_watermark(ngx_http_file_cache_t *cache) +{ + cache->sh->watermark = cache->sh->count - cache->sh->count / 8; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, + "http file cache watermark: %ui", cache->sh->watermark); +} + + time_t ngx_http_file_cache_valid(ngx_array_t *cache_valid, ngx_uint_t status) { diff --git a/src/http/ngx_http_request_body.c b/src/http/ngx_http_request_body.c index e9562c0..b5803d5 100644 --- a/src/http/ngx_http_request_body.c +++ b/src/http/ngx_http_request_body.c @@ -34,7 +34,7 @@ ngx_http_read_client_request_body(ngx_http_request_t *r, ssize_t size; ngx_int_t rc; ngx_buf_t *b; - ngx_chain_t out, *cl; + ngx_chain_t out; ngx_http_request_body_t *rb; ngx_http_core_loc_conf_t *clcf; @@ -59,10 +59,6 @@ ngx_http_read_client_request_body(ngx_http_request_t *r, goto done; } - if (r->request_body_no_buffering) { - r->request_body_in_file_only = 0; - } - rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t)); if (rb == NULL) { rc = NGX_HTTP_INTERNAL_SERVER_ERROR; @@ -148,37 +144,8 @@ ngx_http_read_client_request_body(ngx_http_request_t *r, if (rb->rest == 0) { /* the whole request body was pre-read */ - - if (r->request_body_in_file_only) { - if (ngx_http_write_request_body(r) != NGX_OK) { - rc = NGX_HTTP_INTERNAL_SERVER_ERROR; - goto done; - } - - if (rb->temp_file->file.offset != 0) { - - cl = ngx_chain_get_free_buf(r->pool, &rb->free); - if (cl == NULL) { - rc = NGX_HTTP_INTERNAL_SERVER_ERROR; - goto done; - } - - b = cl->buf; - - ngx_memzero(b, sizeof(ngx_buf_t)); - - b->in_file = 1; - b->file_last = rb->temp_file->file.offset; - b->file = &rb->temp_file->file; - - rb->bufs = cl; - } - } - r->request_body_no_buffering = 0; - post_handler(r); - return NGX_OK; } @@ -289,8 +256,7 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r) size_t size; ssize_t n; ngx_int_t rc; - ngx_buf_t *b; - ngx_chain_t *cl, out; + ngx_chain_t out; ngx_connection_t *c; ngx_http_request_body_t *rb; ngx_http_core_loc_conf_t *clcf; @@ -439,33 +405,6 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r) ngx_del_timer(c->read); } - if (rb->temp_file || r->request_body_in_file_only) { - - /* save the last part */ - - if (ngx_http_write_request_body(r) != NGX_OK) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - if (rb->temp_file->file.offset != 0) { - - cl = ngx_chain_get_free_buf(r->pool, &rb->free); - if (cl == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - b = cl->buf; - - ngx_memzero(b, sizeof(ngx_buf_t)); - - b->in_file = 1; - b->file_last = rb->temp_file->file.offset; - b->file = &rb->temp_file->file; - - rb->bufs = cl; - } - } - if (!r->request_body_no_buffering) { r->read_event_handler = ngx_http_block_reading; rb->post_handler(r); @@ -1127,9 +1066,8 @@ ngx_http_request_body_chunked_filter(ngx_http_request_t *r, ngx_chain_t *in) ngx_int_t ngx_http_request_body_save_filter(ngx_http_request_t *r, ngx_chain_t *in) { -#if (NGX_DEBUG) + ngx_buf_t *b; ngx_chain_t *cl; -#endif ngx_http_request_body_t *rb; rb = r->request_body; @@ -1166,13 +1104,46 @@ ngx_http_request_body_save_filter(ngx_http_request_t *r, ngx_chain_t *in) return NGX_HTTP_INTERNAL_SERVER_ERROR; } - if (rb->rest > 0 - && rb->buf && rb->buf->last == rb->buf->end - && !r->request_body_no_buffering) - { + if (r->request_body_no_buffering) { + return NGX_OK; + } + + if (rb->rest > 0) { + + if (rb->buf && rb->buf->last == rb->buf->end + && ngx_http_write_request_body(r) != NGX_OK) + { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + return NGX_OK; + } + + /* rb->rest == 0 */ + + if (rb->temp_file || r->request_body_in_file_only) { + if (ngx_http_write_request_body(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } + + if (rb->temp_file->file.offset != 0) { + + cl = ngx_chain_get_free_buf(r->pool, &rb->free); + if (cl == NULL) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + b = cl->buf; + + ngx_memzero(b, sizeof(ngx_buf_t)); + + b->in_file = 1; + b->file_last = rb->temp_file->file.offset; + b->file = &rb->temp_file->file; + + rb->bufs = cl; + } } return NGX_OK; diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c index dbaa956..911049f 100644 --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -76,6 +76,13 @@ static void static ngx_int_t ngx_http_upstream_non_buffered_filter_init(void *data); static ngx_int_t ngx_http_upstream_non_buffered_filter(void *data, ssize_t bytes); +#if (NGX_THREADS) +static ngx_int_t ngx_http_upstream_thread_handler(ngx_thread_task_t *task, + ngx_file_t *file); +static void ngx_http_upstream_thread_event_handler(ngx_event_t *ev); +#endif +static ngx_int_t ngx_http_upstream_output_filter(void *data, + ngx_chain_t *chain); static void ngx_http_upstream_process_downstream(ngx_http_request_t *r); static void ngx_http_upstream_process_upstream(ngx_http_request_t *r, ngx_http_upstream_t *u); @@ -416,10 +423,10 @@ static ngx_http_upstream_next_t ngx_http_upstream_next_errors[] = { ngx_conf_bitmask_t ngx_http_upstream_cache_method_mask[] = { - { ngx_string("GET"), NGX_HTTP_GET}, - { ngx_string("HEAD"), NGX_HTTP_HEAD }, - { ngx_string("POST"), NGX_HTTP_POST }, - { ngx_null_string, 0 } + { ngx_string("GET"), NGX_HTTP_GET }, + { ngx_string("HEAD"), NGX_HTTP_HEAD }, + { ngx_string("POST"), NGX_HTTP_POST }, + { ngx_null_string, 0 } }; @@ -2861,11 +2868,16 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u) ngx_http_file_cache_free(r->cache, u->pipe->temp_file); } + if (r->header_only && !u->cacheable && !u->store) { + ngx_http_upstream_finalize_request(r, u, 0); + return; + } + #endif p = u->pipe; - p->output_filter = (ngx_event_pipe_output_filter_pt) ngx_http_output_filter; + p->output_filter = ngx_http_upstream_output_filter; p->output_ctx = r; p->tag = u->output.tag; p->bufs = u->conf->bufs; @@ -2908,6 +2920,13 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u) p->max_temp_file_size = u->conf->max_temp_file_size; p->temp_file_write_size = u->conf->temp_file_write_size; +#if (NGX_THREADS) + if (clcf->aio == NGX_HTTP_AIO_THREADS && clcf->aio_write) { + p->thread_handler = ngx_http_upstream_thread_handler; + p->thread_ctx = r; + } +#endif + p->preread_bufs = ngx_alloc_chain_link(r->pool); if (p->preread_bufs == NULL) { ngx_http_upstream_finalize_request(r, u, NGX_ERROR); @@ -3482,6 +3501,97 @@ ngx_http_upstream_non_buffered_filter(void *data, ssize_t bytes) } +#if (NGX_THREADS) + +static ngx_int_t +ngx_http_upstream_thread_handler(ngx_thread_task_t *task, ngx_file_t *file) +{ + ngx_str_t name; + ngx_event_pipe_t *p; + ngx_thread_pool_t *tp; + ngx_http_request_t *r; + ngx_http_core_loc_conf_t *clcf; + + r = file->thread_ctx; + p = r->upstream->pipe; + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + tp = clcf->thread_pool; + + if (tp == NULL) { + if (ngx_http_complex_value(r, clcf->thread_pool_value, &name) + != NGX_OK) + { + return NGX_ERROR; + } + + tp = ngx_thread_pool_get((ngx_cycle_t *) ngx_cycle, &name); + + if (tp == NULL) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "thread pool \"%V\" not found", &name); + return NGX_ERROR; + } + } + + task->event.data = r; + task->event.handler = ngx_http_upstream_thread_event_handler; + + if (ngx_thread_task_post(tp, task) != NGX_OK) { + return NGX_ERROR; + } + + r->main->blocked++; + r->aio = 1; + p->aio = 1; + + return NGX_OK; +} + + +static void +ngx_http_upstream_thread_event_handler(ngx_event_t *ev) +{ + ngx_connection_t *c; + ngx_http_request_t *r; + + r = ev->data; + c = r->connection; + + ngx_http_set_log_request(c->log, r); + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http upstream thread: \"%V?%V\"", &r->uri, &r->args); + + r->main->blocked--; + r->aio = 0; + + r->write_event_handler(r); + + ngx_http_run_posted_requests(c); +} + +#endif + + +static ngx_int_t +ngx_http_upstream_output_filter(void *data, ngx_chain_t *chain) +{ + ngx_int_t rc; + ngx_event_pipe_t *p; + ngx_http_request_t *r; + + r = data; + p = r->upstream->pipe; + + rc = ngx_http_output_filter(r, chain); + + p->aio = r->aio; + + return rc; +} + + static void ngx_http_upstream_process_downstream(ngx_http_request_t *r) { @@ -3500,6 +3610,10 @@ ngx_http_upstream_process_downstream(ngx_http_request_t *r) c->log->action = "sending to client"; +#if (NGX_THREADS) + p->aio = r->aio; +#endif + if (wev->timedout) { if (wev->delayed) { @@ -3629,6 +3743,12 @@ ngx_http_upstream_process_request(ngx_http_request_t *r, p = u->pipe; +#if (NGX_THREADS) + if (p->writing) { + return; + } +#endif + if (u->peer.connection) { if (u->store) { @@ -3827,42 +3947,36 @@ ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u, "upstream timed out"); } - if (u->peer.cached && ft_type == NGX_HTTP_UPSTREAM_FT_ERROR - && (!u->request_sent || !r->request_body_no_buffering)) - { - status = 0; - + if (u->peer.cached && ft_type == NGX_HTTP_UPSTREAM_FT_ERROR) { /* TODO: inform balancer instead */ - u->peer.tries++; + } - } else { - switch (ft_type) { + switch (ft_type) { - case NGX_HTTP_UPSTREAM_FT_TIMEOUT: - status = NGX_HTTP_GATEWAY_TIME_OUT; - break; + case NGX_HTTP_UPSTREAM_FT_TIMEOUT: + status = NGX_HTTP_GATEWAY_TIME_OUT; + break; - case NGX_HTTP_UPSTREAM_FT_HTTP_500: - status = NGX_HTTP_INTERNAL_SERVER_ERROR; - break; + case NGX_HTTP_UPSTREAM_FT_HTTP_500: + status = NGX_HTTP_INTERNAL_SERVER_ERROR; + break; - case NGX_HTTP_UPSTREAM_FT_HTTP_403: - status = NGX_HTTP_FORBIDDEN; - break; + case NGX_HTTP_UPSTREAM_FT_HTTP_403: + status = NGX_HTTP_FORBIDDEN; + break; - case NGX_HTTP_UPSTREAM_FT_HTTP_404: - status = NGX_HTTP_NOT_FOUND; - break; + case NGX_HTTP_UPSTREAM_FT_HTTP_404: + status = NGX_HTTP_NOT_FOUND; + break; - /* - * NGX_HTTP_UPSTREAM_FT_BUSY_LOCK and NGX_HTTP_UPSTREAM_FT_MAX_WAITING - * never reach here - */ + /* + * NGX_HTTP_UPSTREAM_FT_BUSY_LOCK and NGX_HTTP_UPSTREAM_FT_MAX_WAITING + * never reach here + */ - default: - status = NGX_HTTP_BAD_GATEWAY; - } + default: + status = NGX_HTTP_BAD_GATEWAY; } if (r->connection->error) { @@ -3871,37 +3985,42 @@ ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u, return; } - if (status) { - u->state->status = status; - timeout = u->conf->next_upstream_timeout; + u->state->status = status; - if (u->peer.tries == 0 - || !(u->conf->next_upstream & ft_type) - || (u->request_sent && r->request_body_no_buffering) - || (timeout && ngx_current_msec - u->peer.start_time >= timeout)) - { + timeout = u->conf->next_upstream_timeout; + + if (u->request_sent + && (r->method & (NGX_HTTP_POST|NGX_HTTP_LOCK|NGX_HTTP_PATCH))) + { + ft_type |= NGX_HTTP_UPSTREAM_FT_NON_IDEMPOTENT; + } + + if (u->peer.tries == 0 + || ((u->conf->next_upstream & ft_type) != ft_type) + || (u->request_sent && r->request_body_no_buffering) + || (timeout && ngx_current_msec - u->peer.start_time >= timeout)) + { #if (NGX_HTTP_CACHE) - if (u->cache_status == NGX_HTTP_CACHE_EXPIRED - && (u->conf->cache_use_stale & ft_type)) - { - ngx_int_t rc; + if (u->cache_status == NGX_HTTP_CACHE_EXPIRED + && (u->conf->cache_use_stale & ft_type)) + { + ngx_int_t rc; - rc = u->reinit_request(r); + rc = u->reinit_request(r); - if (rc == NGX_OK) { - u->cache_status = NGX_HTTP_CACHE_STALE; - rc = ngx_http_upstream_cache_send(r, u); - } - - ngx_http_upstream_finalize_request(r, u, rc); - return; + if (rc == NGX_OK) { + u->cache_status = NGX_HTTP_CACHE_STALE; + rc = ngx_http_upstream_cache_send(r, u); } -#endif - ngx_http_upstream_finalize_request(r, u, status); + ngx_http_upstream_finalize_request(r, u, rc); return; } +#endif + + ngx_http_upstream_finalize_request(r, u, status); + return; } if (u->peer.connection) { @@ -4068,7 +4187,8 @@ ngx_http_upstream_finalize_request(ngx_http_request_t *r, if (!u->header_sent || rc == NGX_HTTP_REQUEST_TIME_OUT - || rc == NGX_HTTP_CLIENT_CLOSED_REQUEST) + || rc == NGX_HTTP_CLIENT_CLOSED_REQUEST + || (u->pipe && u->pipe->downstream_error)) { ngx_http_finalize_request(r, rc); return; diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h index 4246c8a..7595dcf 100644 --- a/src/http/ngx_http_upstream.h +++ b/src/http/ngx_http_upstream.h @@ -29,6 +29,7 @@ #define NGX_HTTP_UPSTREAM_FT_UPDATING 0x00000400 #define NGX_HTTP_UPSTREAM_FT_BUSY_LOCK 0x00000800 #define NGX_HTTP_UPSTREAM_FT_MAX_WAITING 0x00001000 +#define NGX_HTTP_UPSTREAM_FT_NON_IDEMPOTENT 0x00002000 #define NGX_HTTP_UPSTREAM_FT_NOLIVE 0x40000000 #define NGX_HTTP_UPSTREAM_FT_OFF 0x80000000 @@ -281,7 +282,7 @@ typedef struct { ngx_uint_t no_port; /* unsigned no_port:1 */ ngx_uint_t naddrs; - ngx_addr_t *addrs; + ngx_resolver_addr_t *addrs; struct sockaddr *sockaddr; socklen_t socklen; diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c index 4c4a4e7..ababd4b 100644 --- a/src/http/v2/ngx_http_v2.c +++ b/src/http/v2/ngx_http_v2.c @@ -2503,8 +2503,8 @@ ngx_http_v2_send_settings(ngx_http_v2_connection_t *h2c, ngx_uint_t ack) ngx_http_v2_srv_conf_t *h2scf; ngx_http_v2_out_frame_t *frame; - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "http2 send SETTINGS frame"); + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "http2 send SETTINGS frame ack:%ui", ack); frame = ngx_palloc(h2c->pool, sizeof(ngx_http_v2_out_frame_t)); if (frame == NULL) { @@ -2595,6 +2595,10 @@ ngx_http_v2_send_window_update(ngx_http_v2_connection_t *h2c, ngx_uint_t sid, ngx_buf_t *buf; ngx_http_v2_out_frame_t *frame; + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "http2 send WINDOW_UPDATE frame sid:%ui, window:%uz", + sid, window); + frame = ngx_http_v2_get_frame(h2c, NGX_HTTP_V2_WINDOW_UPDATE_SIZE, NGX_HTTP_V2_WINDOW_UPDATE_FRAME, NGX_HTTP_V2_NO_FLAG, sid); @@ -2619,6 +2623,10 @@ ngx_http_v2_send_rst_stream(ngx_http_v2_connection_t *h2c, ngx_uint_t sid, ngx_buf_t *buf; ngx_http_v2_out_frame_t *frame; + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "http2 send RST_STREAM frame sid:%ui, status:%uz", + sid, status); + frame = ngx_http_v2_get_frame(h2c, NGX_HTTP_V2_RST_STREAM_SIZE, NGX_HTTP_V2_RST_STREAM_FRAME, NGX_HTTP_V2_NO_FLAG, sid); @@ -2642,6 +2650,9 @@ ngx_http_v2_send_goaway(ngx_http_v2_connection_t *h2c, ngx_uint_t status) ngx_buf_t *buf; ngx_http_v2_out_frame_t *frame; + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "http2 send GOAWAY frame, status:%uz", status); + frame = ngx_http_v2_get_frame(h2c, NGX_HTTP_V2_GOAWAY_SIZE, NGX_HTTP_V2_GOAWAY_FRAME, NGX_HTTP_V2_NO_FLAG, 0); diff --git a/src/os/unix/ngx_darwin_init.c b/src/os/unix/ngx_darwin_init.c index 1bc7520..a9d12a8 100644 --- a/src/os/unix/ngx_darwin_init.c +++ b/src/os/unix/ngx_darwin_init.c @@ -23,6 +23,7 @@ static ngx_os_io_t ngx_darwin_io = { ngx_readv_chain, ngx_udp_unix_recv, ngx_unix_send, + ngx_udp_unix_send, #if (NGX_HAVE_SENDFILE) ngx_darwin_sendfile_chain, NGX_IO_SENDFILE diff --git a/src/os/unix/ngx_errno.h b/src/os/unix/ngx_errno.h index 16cafda..7d6ca76 100644 --- a/src/os/unix/ngx_errno.h +++ b/src/os/unix/ngx_errno.h @@ -25,6 +25,7 @@ typedef int ngx_err_t; #define NGX_EACCES EACCES #define NGX_EBUSY EBUSY #define NGX_EEXIST EEXIST +#define NGX_EEXIST_FILE EEXIST #define NGX_EXDEV EXDEV #define NGX_ENOTDIR ENOTDIR #define NGX_EISDIR EISDIR diff --git a/src/os/unix/ngx_files.c b/src/os/unix/ngx_files.c index 00a6a49..bcef7ec 100644 --- a/src/os/unix/ngx_files.c +++ b/src/os/unix/ngx_files.c @@ -12,9 +12,11 @@ #if (NGX_THREADS) #include static void ngx_thread_read_handler(void *data, ngx_log_t *log); +static void ngx_thread_write_chain_to_file_handler(void *data, ngx_log_t *log); #endif -static ssize_t ngx_writev_file(ngx_file_t *file, ngx_array_t *vec, size_t size, +static ngx_chain_t *ngx_chain_to_iovec(ngx_iovec_t *vec, ngx_chain_t *cl); +static ssize_t ngx_writev_file(ngx_file_t *file, ngx_iovec_t *vec, off_t offset); @@ -76,38 +78,39 @@ ngx_read_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset) #if (NGX_THREADS) typedef struct { - ngx_fd_t fd; - u_char *buf; - size_t size; - off_t offset; + ngx_fd_t fd; + ngx_uint_t write; /* unsigned write:1; */ - size_t read; - ngx_err_t err; -} ngx_thread_read_ctx_t; + u_char *buf; + size_t size; + ngx_chain_t *chain; + off_t offset; + + size_t nbytes; + ngx_err_t err; +} ngx_thread_file_ctx_t; ssize_t -ngx_thread_read(ngx_thread_task_t **taskp, ngx_file_t *file, u_char *buf, - size_t size, off_t offset, ngx_pool_t *pool) +ngx_thread_read(ngx_file_t *file, u_char *buf, size_t size, off_t offset, + ngx_pool_t *pool) { ngx_thread_task_t *task; - ngx_thread_read_ctx_t *ctx; + ngx_thread_file_ctx_t *ctx; ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0, "thread read: %d, %p, %uz, %O", file->fd, buf, size, offset); - task = *taskp; + task = file->thread_task; if (task == NULL) { - task = ngx_thread_task_alloc(pool, sizeof(ngx_thread_read_ctx_t)); + task = ngx_thread_task_alloc(pool, sizeof(ngx_thread_file_ctx_t)); if (task == NULL) { return NGX_ERROR; } - task->handler = ngx_thread_read_handler; - - *taskp = task; + file->thread_task = task; } ctx = task->ctx; @@ -115,15 +118,25 @@ ngx_thread_read(ngx_thread_task_t **taskp, ngx_file_t *file, u_char *buf, if (task->event.complete) { task->event.complete = 0; + if (ctx->write) { + ngx_log_error(NGX_LOG_ALERT, file->log, 0, + "invalid thread call, read instead of write"); + return NGX_ERROR; + } + if (ctx->err) { ngx_log_error(NGX_LOG_CRIT, file->log, ctx->err, "pread() \"%s\" failed", file->name.data); return NGX_ERROR; } - return ctx->read; + return ctx->nbytes; } + task->handler = ngx_thread_read_handler; + + ctx->write = 0; + ctx->fd = file->fd; ctx->buf = buf; ctx->size = size; @@ -142,7 +155,7 @@ ngx_thread_read(ngx_thread_task_t **taskp, ngx_file_t *file, u_char *buf, static void ngx_thread_read_handler(void *data, ngx_log_t *log) { - ngx_thread_read_ctx_t *ctx = data; + ngx_thread_file_ctx_t *ctx = data; ssize_t n; @@ -154,7 +167,7 @@ ngx_thread_read_handler(void *data, ngx_log_t *log) ctx->err = ngx_errno; } else { - ctx->read = n; + ctx->nbytes = n; ctx->err = 0; } @@ -276,17 +289,13 @@ ngx_open_tempfile(u_char *name, ngx_uint_t persistent, ngx_uint_t access) } -#define NGX_IOVS 8 - ssize_t ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl, off_t offset, ngx_pool_t *pool) { - u_char *prev; - size_t size; ssize_t total, n; - ngx_array_t vec; - struct iovec *iov, iovs[NGX_IOVS]; + ngx_iovec_t vec; + struct iovec iovs[NGX_IOVS_PREALLOCATE]; /* use pwrite() if there is the only buf in a chain */ @@ -298,46 +307,18 @@ ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl, off_t offset, total = 0; - vec.elts = iovs; - vec.size = sizeof(struct iovec); - vec.nalloc = NGX_IOVS; - vec.pool = pool; + vec.iovs = iovs; + vec.nalloc = NGX_IOVS_PREALLOCATE; do { - prev = NULL; - iov = NULL; - size = 0; - - vec.nelts = 0; - /* create the iovec and coalesce the neighbouring bufs */ - - while (cl && vec.nelts < IOV_MAX) { - if (prev == cl->buf->pos) { - iov->iov_len += cl->buf->last - cl->buf->pos; - - } else { - iov = ngx_array_push(&vec); - if (iov == NULL) { - return NGX_ERROR; - } - - iov->iov_base = (void *) cl->buf->pos; - iov->iov_len = cl->buf->last - cl->buf->pos; - } - - size += cl->buf->last - cl->buf->pos; - prev = cl->buf->last; - cl = cl->next; - } + cl = ngx_chain_to_iovec(&vec, cl); /* use pwrite() if there is the only iovec buffer */ - if (vec.nelts == 1) { - iov = vec.elts; - - n = ngx_write_file(file, (u_char *) iov[0].iov_base, - iov[0].iov_len, offset); + if (vec.count == 1) { + n = ngx_write_file(file, (u_char *) iovs[0].iov_base, + iovs[0].iov_len, offset); if (n == NGX_ERROR) { return n; @@ -346,7 +327,7 @@ ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl, off_t offset, return total + n; } - n = ngx_writev_file(file, &vec, size, offset); + n = ngx_writev_file(file, &vec, offset); if (n == NGX_ERROR) { return n; @@ -361,20 +342,61 @@ ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl, off_t offset, } +static ngx_chain_t * +ngx_chain_to_iovec(ngx_iovec_t *vec, ngx_chain_t *cl) +{ + size_t total, size; + u_char *prev; + ngx_uint_t n; + struct iovec *iov; + + iov = NULL; + prev = NULL; + total = 0; + n = 0; + + for ( /* void */ ; cl; cl = cl->next) { + size = cl->buf->last - cl->buf->pos; + + if (prev == cl->buf->pos) { + iov->iov_len += size; + + } else { + if (n == vec->nalloc) { + break; + } + + iov = &vec->iovs[n++]; + + iov->iov_base = (void *) cl->buf->pos; + iov->iov_len = size; + } + + prev = cl->buf->pos + size; + total += size; + } + + vec->count = n; + vec->size = total; + + return cl; +} + + static ssize_t -ngx_writev_file(ngx_file_t *file, ngx_array_t *vec, size_t size, off_t offset) +ngx_writev_file(ngx_file_t *file, ngx_iovec_t *vec, off_t offset) { ssize_t n; ngx_err_t err; ngx_log_debug3(NGX_LOG_DEBUG_CORE, file->log, 0, - "writev: %d, %uz, %O", file->fd, size, offset); + "writev: %d, %uz, %O", file->fd, vec->size, offset); #if (NGX_HAVE_PWRITEV) eintr: - n = pwritev(file->fd, vec->elts, vec->nelts, offset); + n = pwritev(file->fd, vec->iovs, vec->count, offset); if (n == -1) { err = ngx_errno; @@ -390,10 +412,10 @@ eintr: return NGX_ERROR; } - if ((size_t) n != size) { + if ((size_t) n != vec->size) { ngx_log_error(NGX_LOG_CRIT, file->log, 0, "pwritev() \"%s\" has written only %z of %uz", - file->name.data, n, size); + file->name.data, n, vec->size); return NGX_ERROR; } @@ -411,7 +433,7 @@ eintr: eintr: - n = writev(file->fd, vec->elts, vec->nelts); + n = writev(file->fd, vec->iovs, vec->count); if (n == -1) { err = ngx_errno; @@ -427,10 +449,10 @@ eintr: return NGX_ERROR; } - if ((size_t) n != size) { + if ((size_t) n != vec->size) { ngx_log_error(NGX_LOG_CRIT, file->log, 0, "writev() \"%s\" has written only %z of %uz", - file->name.data, n, size); + file->name.data, n, vec->size); return NGX_ERROR; } @@ -444,6 +466,132 @@ eintr: } +#if (NGX_THREADS) + +ssize_t +ngx_thread_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl, off_t offset, + ngx_pool_t *pool) +{ + ngx_thread_task_t *task; + ngx_thread_file_ctx_t *ctx; + + ngx_log_debug3(NGX_LOG_DEBUG_CORE, file->log, 0, + "thread write chain: %d, %p, %O", + file->fd, cl, offset); + + task = file->thread_task; + + if (task == NULL) { + task = ngx_thread_task_alloc(pool, + sizeof(ngx_thread_file_ctx_t)); + if (task == NULL) { + return NGX_ERROR; + } + + file->thread_task = task; + } + + ctx = task->ctx; + + if (task->event.complete) { + task->event.complete = 0; + + if (!ctx->write) { + ngx_log_error(NGX_LOG_ALERT, file->log, 0, + "invalid thread call, write instead of read"); + return NGX_ERROR; + } + + if (ctx->err || ctx->nbytes == 0) { + ngx_log_error(NGX_LOG_CRIT, file->log, ctx->err, + "pwritev() \"%s\" failed", file->name.data); + return NGX_ERROR; + } + + file->offset += ctx->nbytes; + return ctx->nbytes; + } + + task->handler = ngx_thread_write_chain_to_file_handler; + + ctx->write = 1; + + ctx->fd = file->fd; + ctx->chain = cl; + ctx->offset = offset; + + if (file->thread_handler(task, file) != NGX_OK) { + return NGX_ERROR; + } + + return NGX_AGAIN; +} + + +static void +ngx_thread_write_chain_to_file_handler(void *data, ngx_log_t *log) +{ + ngx_thread_file_ctx_t *ctx = data; + +#if (NGX_HAVE_PWRITEV) + + off_t offset; + ssize_t n; + ngx_err_t err; + ngx_chain_t *cl; + ngx_iovec_t vec; + struct iovec iovs[NGX_IOVS_PREALLOCATE]; + + vec.iovs = iovs; + vec.nalloc = NGX_IOVS_PREALLOCATE; + + cl = ctx->chain; + offset = ctx->offset; + + ctx->nbytes = 0; + ctx->err = 0; + + do { + /* create the iovec and coalesce the neighbouring bufs */ + cl = ngx_chain_to_iovec(&vec, cl); + +eintr: + + n = pwritev(ctx->fd, iovs, vec.count, offset); + + if (n == -1) { + err = ngx_errno; + + if (err == NGX_EINTR) { + ngx_log_debug0(NGX_LOG_DEBUG_CORE, log, err, + "pwritev() was interrupted"); + goto eintr; + } + + ctx->err = err; + return; + } + + if ((size_t) n != vec.size) { + ctx->nbytes = 0; + return; + } + + ctx->nbytes += n; + offset += n; + } while (cl); + +#else + + ctx->err = NGX_ENOSYS; + return; + +#endif +} + +#endif /* NGX_THREADS */ + + ngx_int_t ngx_set_file_time(u_char *name, ngx_fd_t fd, time_t s) { diff --git a/src/os/unix/ngx_files.h b/src/os/unix/ngx_files.h index 6081b00..07872b1 100644 --- a/src/os/unix/ngx_files.h +++ b/src/os/unix/ngx_files.h @@ -385,8 +385,10 @@ extern ngx_uint_t ngx_file_aio; #endif #if (NGX_THREADS) -ssize_t ngx_thread_read(ngx_thread_task_t **taskp, ngx_file_t *file, - u_char *buf, size_t size, off_t offset, ngx_pool_t *pool); +ssize_t ngx_thread_read(ngx_file_t *file, u_char *buf, size_t size, + off_t offset, ngx_pool_t *pool); +ssize_t ngx_thread_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl, + off_t offset, ngx_pool_t *pool); #endif diff --git a/src/os/unix/ngx_freebsd_init.c b/src/os/unix/ngx_freebsd_init.c index c4c12dd..71672c7 100644 --- a/src/os/unix/ngx_freebsd_init.c +++ b/src/os/unix/ngx_freebsd_init.c @@ -32,6 +32,7 @@ static ngx_os_io_t ngx_freebsd_io = { ngx_readv_chain, ngx_udp_unix_recv, ngx_unix_send, + ngx_udp_unix_send, #if (NGX_HAVE_SENDFILE) ngx_freebsd_sendfile_chain, NGX_IO_SENDFILE diff --git a/src/os/unix/ngx_freebsd_sendfile_chain.c b/src/os/unix/ngx_freebsd_sendfile_chain.c index 3f17dc6..d0299f5 100644 --- a/src/os/unix/ngx_freebsd_sendfile_chain.c +++ b/src/os/unix/ngx_freebsd_sendfile_chain.c @@ -247,6 +247,19 @@ ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) #if (NGX_HAVE_AIO_SENDFILE) if (ebusy) { + if (aio->event.active) { + /* + * tolerate duplicate calls; they can happen due to subrequests + * or multiple calls of the next body filter from a filter + */ + + if (sent) { + c->busy_count = 0; + } + + return in; + } + if (sent == 0) { c->busy_count++; diff --git a/src/os/unix/ngx_linux_init.c b/src/os/unix/ngx_linux_init.c index b306cda..a1372e9 100644 --- a/src/os/unix/ngx_linux_init.c +++ b/src/os/unix/ngx_linux_init.c @@ -18,6 +18,7 @@ static ngx_os_io_t ngx_linux_io = { ngx_readv_chain, ngx_udp_unix_recv, ngx_unix_send, + ngx_udp_unix_send, #if (NGX_HAVE_SENDFILE) ngx_linux_sendfile_chain, NGX_IO_SENDFILE diff --git a/src/os/unix/ngx_linux_sendfile_chain.c b/src/os/unix/ngx_linux_sendfile_chain.c index 97f741d..50a9cea 100644 --- a/src/os/unix/ngx_linux_sendfile_chain.c +++ b/src/os/unix/ngx_linux_sendfile_chain.c @@ -292,6 +292,19 @@ eintr: } } + if (n == 0) { + /* + * if sendfile returns zero, then someone has truncated the file, + * so the offset became beyond the end of the file + */ + + ngx_log_error(NGX_LOG_ALERT, c->log, 0, + "sendfile() reported that \"%s\" was truncated at %O", + file->file->name.data, file->file_pos); + + return NGX_ERROR; + } + ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, "sendfile: %z of %uz @%O", n, size, file->file_pos); @@ -315,7 +328,6 @@ static ngx_int_t ngx_linux_sendfile_thread(ngx_connection_t *c, ngx_buf_t *file, size_t size, size_t *sent) { - ngx_uint_t flags; ngx_event_t *wev; ngx_thread_task_t *task; ngx_linux_sendfile_ctx_t *ctx; @@ -343,29 +355,60 @@ ngx_linux_sendfile_thread(ngx_connection_t *c, ngx_buf_t *file, size_t size, if (task->event.complete) { task->event.complete = 0; - if (ctx->err && ctx->err != NGX_EAGAIN) { + if (ctx->err == NGX_EAGAIN) { + *sent = 0; + + if (wev->complete) { + return NGX_DONE; + } + + return NGX_AGAIN; + } + + if (ctx->err) { wev->error = 1; ngx_connection_error(c, ctx->err, "sendfile() failed"); return NGX_ERROR; } + if (ctx->sent == 0) { + /* + * if sendfile returns zero, then someone has truncated the file, + * so the offset became beyond the end of the file + */ + + ngx_log_error(NGX_LOG_ALERT, c->log, 0, + "sendfile() reported that \"%s\" was truncated at %O", + file->file->name.data, file->file_pos); + + return NGX_ERROR; + } + *sent = ctx->sent; - return (ctx->sent == ctx->size) ? NGX_DONE : NGX_AGAIN; + if (ctx->sent == ctx->size || wev->complete) { + return NGX_DONE; + } + + return NGX_AGAIN; + } + + if (task->event.active && ctx->file == file) { + /* + * tolerate duplicate calls; they can happen due to subrequests + * or multiple calls of the next body filter from a filter + */ + + *sent = 0; + + return NGX_OK; } ctx->file = file; ctx->socket = c->fd; ctx->size = size; - if (wev->active) { - flags = (ngx_event_flags & NGX_USE_CLEAR_EVENT) ? NGX_CLEAR_EVENT - : NGX_LEVEL_EVENT; - - if (ngx_del_event(wev, NGX_WRITE_EVENT, flags) == NGX_ERROR) { - return NGX_ERROR; - } - } + wev->complete = 0; if (file->file->thread_handler(task, file->file) != NGX_OK) { return NGX_ERROR; diff --git a/src/os/unix/ngx_os.h b/src/os/unix/ngx_os.h index d8bcb01..c0d59ef 100644 --- a/src/os/unix/ngx_os.h +++ b/src/os/unix/ngx_os.h @@ -28,6 +28,7 @@ typedef struct { ngx_recv_chain_pt recv_chain; ngx_recv_pt udp_recv; ngx_send_pt send; + ngx_send_pt udp_send; ngx_send_chain_pt send_chain; ngx_uint_t flags; } ngx_os_io_t; @@ -47,6 +48,7 @@ ssize_t ngx_udp_unix_recv(ngx_connection_t *c, u_char *buf, size_t size); ssize_t ngx_unix_send(ngx_connection_t *c, u_char *buf, size_t size); ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit); +ssize_t ngx_udp_unix_send(ngx_connection_t *c, u_char *buf, size_t size); #if (IOV_MAX > 64) diff --git a/src/os/unix/ngx_posix_config.h b/src/os/unix/ngx_posix_config.h index bf75997..5d1358e 100644 --- a/src/os/unix/ngx_posix_config.h +++ b/src/os/unix/ngx_posix_config.h @@ -128,7 +128,7 @@ #endif -#if (NGX_HAVE_DEVPOLL) +#if (NGX_HAVE_DEVPOLL) && !(NGX_TEST_BUILD_DEVPOLL) #include #include #endif diff --git a/src/os/unix/ngx_posix_init.c b/src/os/unix/ngx_posix_init.c index 61cc8ca..76ed94e 100644 --- a/src/os/unix/ngx_posix_init.c +++ b/src/os/unix/ngx_posix_init.c @@ -24,6 +24,7 @@ ngx_os_io_t ngx_os_io = { ngx_readv_chain, ngx_udp_unix_recv, ngx_unix_send, + ngx_udp_unix_send, ngx_writev_chain, 0 }; diff --git a/src/os/unix/ngx_solaris_init.c b/src/os/unix/ngx_solaris_init.c index f2f3600..83acae1 100644 --- a/src/os/unix/ngx_solaris_init.c +++ b/src/os/unix/ngx_solaris_init.c @@ -19,6 +19,7 @@ static ngx_os_io_t ngx_solaris_io = { ngx_readv_chain, ngx_udp_unix_recv, ngx_unix_send, + ngx_udp_unix_send, #if (NGX_HAVE_SENDFILE) ngx_solaris_sendfilev_chain, NGX_IO_SENDFILE diff --git a/src/os/unix/ngx_solaris_sendfilev_chain.c b/src/os/unix/ngx_solaris_sendfilev_chain.c index 7504239..39bcafa 100644 --- a/src/os/unix/ngx_solaris_sendfilev_chain.c +++ b/src/os/unix/ngx_solaris_sendfilev_chain.c @@ -48,6 +48,7 @@ ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) ssize_t n; ngx_int_t eintr; ngx_err_t err; + ngx_buf_t *file; ngx_uint_t nsfv; sendfilevec_t *sfv, sfvs[NGX_SENDFILEVECS]; ngx_event_t *wev; @@ -77,6 +78,7 @@ ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) fd = SFV_FD_SELF; prev = NULL; fprev = 0; + file = NULL; sfv = NULL; eintr = 0; sent = 0; @@ -153,6 +155,7 @@ ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) sfv->sfv_len = (size_t) size; } + file = cl->buf; fprev = cl->buf->file_pos + size; send += size; } @@ -179,6 +182,26 @@ ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, err, "sendfilev() sent only %uz bytes", sent); + + } else if (n == 0 && sent == 0) { + + /* + * sendfilev() is documented to return -1 with errno + * set to EINVAL if svf_len is greater than the file size, + * but at least Solaris 11 returns 0 instead + */ + + if (file) { + ngx_log_error(NGX_LOG_ALERT, c->log, 0, + "sendfilev() reported that \"%s\" was truncated at %O", + file->file->name.data, file->file_pos); + + } else { + ngx_log_error(NGX_LOG_ALERT, c->log, 0, + "sendfilev() returned 0 with memory buffers"); + } + + return NGX_CHAIN_ERROR; } ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, diff --git a/src/os/unix/ngx_udp_send.c b/src/os/unix/ngx_udp_send.c new file mode 100644 index 0000000..aabbc8e --- /dev/null +++ b/src/os/unix/ngx_udp_send.c @@ -0,0 +1,56 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + + +ssize_t +ngx_udp_unix_send(ngx_connection_t *c, u_char *buf, size_t size) +{ + ssize_t n; + ngx_err_t err; + ngx_event_t *wev; + + wev = c->write; + + for ( ;; ) { + n = sendto(c->fd, buf, size, 0, c->sockaddr, c->socklen); + + ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0, + "sendto: fd:%d %z of %uz to \"%V\"", + c->fd, n, size, &c->addr_text); + + if (n >= 0) { + if ((size_t) n != size) { + wev->error = 1; + (void) ngx_connection_error(c, 0, "sendto() incomplete"); + return NGX_ERROR; + } + + c->sent += n; + + return n; + } + + err = ngx_socket_errno; + + if (err == NGX_EAGAIN) { + wev->ready = 0; + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, NGX_EAGAIN, + "sendto() not ready"); + return NGX_AGAIN; + } + + if (err != NGX_EINTR) { + wev->error = 1; + (void) ngx_connection_error(c, err, "sendto() failed"); + return NGX_ERROR; + } + } +} diff --git a/src/stream/ngx_stream.c b/src/stream/ngx_stream.c index caaf38a..3bd8f6d 100644 --- a/src/stream/ngx_stream.c +++ b/src/stream/ngx_stream.c @@ -275,8 +275,11 @@ ngx_stream_add_ports(ngx_conf_t *cf, ngx_array_t *ports, port = ports->elts; for (i = 0; i < ports->nelts; i++) { - if (p == port[i].port && sa->sa_family == port[i].family) { + if (p == port[i].port + && listen->type == port[i].type + && sa->sa_family == port[i].family) + { /* a port is already in the port list */ port = &port[i]; @@ -292,6 +295,7 @@ ngx_stream_add_ports(ngx_conf_t *cf, ngx_array_t *ports, } port->family = sa->sa_family; + port->type = listen->type; port->port = p; if (ngx_array_init(&port->addrs, cf->temp_pool, 2, @@ -364,6 +368,7 @@ ngx_stream_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports) ls->addr_ntop = 1; ls->handler = ngx_stream_init_connection; ls->pool_size = 256; + ls->type = addr[i].opt.type; cscf = addr->opt.ctx->srv_conf[ngx_stream_core_module.ctx_index]; @@ -373,6 +378,8 @@ ngx_stream_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports) ls->backlog = addr[i].opt.backlog; + ls->wildcard = addr[i].opt.wildcard; + ls->keepalive = addr[i].opt.so_keepalive; #if (NGX_HAVE_KEEPALIVE_TUNABLE) ls->keepidle = addr[i].opt.tcp_keepidle; diff --git a/src/stream/ngx_stream.h b/src/stream/ngx_stream.h index 21953e9..49efa45 100644 --- a/src/stream/ngx_stream.h +++ b/src/stream/ngx_stream.h @@ -66,6 +66,7 @@ typedef struct { int tcp_keepcnt; #endif int backlog; + int type; } ngx_stream_listen_t; @@ -102,6 +103,7 @@ typedef struct { typedef struct { int family; + int type; in_port_t port; ngx_array_t addrs; /* array of ngx_stream_conf_addr_t */ } ngx_stream_conf_port_t; diff --git a/src/stream/ngx_stream_core_module.c b/src/stream/ngx_stream_core_module.c index 0ecc448..ebc2b1c 100644 --- a/src/stream/ngx_stream_core_module.c +++ b/src/stream/ngx_stream_core_module.c @@ -252,7 +252,7 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) in_port_t port; ngx_str_t *value; ngx_url_t u; - ngx_uint_t i; + ngx_uint_t i, backlog; struct sockaddr *sa; struct sockaddr_in *sin; ngx_stream_listen_t *ls; @@ -343,6 +343,7 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ls->socklen = u.socklen; ls->backlog = NGX_LISTEN_BACKLOG; + ls->type = SOCK_STREAM; ls->wildcard = u.wildcard; ls->ctx = cf->ctx; @@ -350,8 +351,17 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ls->ipv6only = 1; #endif + backlog = 0; + for (i = 2; i < cf->args->nelts; i++) { +#if !(NGX_WIN32) + if (ngx_strcmp(value[i].data, "udp") == 0) { + ls->type = SOCK_DGRAM; + continue; + } +#endif + if (ngx_strcmp(value[i].data, "bind") == 0) { ls->bind = 1; continue; @@ -367,6 +377,8 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_ERROR; } + backlog = 1; + continue; } @@ -530,5 +542,21 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_ERROR; } + if (ls->type == SOCK_DGRAM) { + if (backlog) { + return "\"backlog\" parameter is incompatible with \"udp\""; + } + +#if (NGX_STREAM_SSL) + if (ls->ssl) { + return "\"ssl\" parameter is incompatible with \"udp\""; + } +#endif + + if (ls->so_keepalive) { + return "\"so_keepalive\" parameter is incompatible with \"udp\""; + } + } + return NGX_CONF_OK; } diff --git a/src/stream/ngx_stream_handler.c b/src/stream/ngx_stream_handler.c index b3edb68..aa69e44 100644 --- a/src/stream/ngx_stream_handler.c +++ b/src/stream/ngx_stream_handler.c @@ -52,7 +52,7 @@ ngx_stream_init_connection(ngx_connection_t *c) * is the "*:port" wildcard so getsockname() is needed to determine * the server address. * - * AcceptEx() already gave this address. + * AcceptEx() and recvmsg() already gave this address. */ if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) { @@ -137,8 +137,9 @@ ngx_stream_init_connection(ngx_connection_t *c) len = ngx_sock_ntop(c->sockaddr, c->socklen, text, NGX_SOCKADDR_STRLEN, 1); - ngx_log_error(NGX_LOG_INFO, c->log, 0, "*%uA client %*s connected to %V", - c->number, len, text, &addr_conf->addr_text); + ngx_log_error(NGX_LOG_INFO, c->log, 0, "*%uA %sclient %*s connected to %V", + c->number, c->type == SOCK_DGRAM ? "udp " : "", + len, text, &addr_conf->addr_text); c->log->connection = c->number; c->log->handler = ngx_stream_log_error; @@ -166,7 +167,10 @@ ngx_stream_init_connection(ngx_connection_t *c) } } - if (cscf->tcp_nodelay && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) { + if (c->type == SOCK_STREAM + && cscf->tcp_nodelay + && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) + { ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0, "tcp_nodelay"); tcp_nodelay = 1; @@ -325,7 +329,8 @@ ngx_stream_log_error(ngx_log_t *log, u_char *buf, size_t len) s = log->data; - p = ngx_snprintf(buf, len, ", client: %V, server: %V", + p = ngx_snprintf(buf, len, ", %sclient: %V, server: %V", + s->connection->type == SOCK_DGRAM ? "udp " : "", &s->connection->addr_text, &s->connection->listening->addr_text); len -= p - buf; diff --git a/src/stream/ngx_stream_proxy_module.c b/src/stream/ngx_stream_proxy_module.c index b969fea..6c535fd 100644 --- a/src/stream/ngx_stream_proxy_module.c +++ b/src/stream/ngx_stream_proxy_module.c @@ -17,6 +17,7 @@ typedef struct { size_t buffer_size; size_t upload_rate; size_t download_rate; + ngx_uint_t responses; ngx_uint_t next_upstream_tries; ngx_flag_t next_upstream; ngx_flag_t proxy_protocol; @@ -54,7 +55,7 @@ static void ngx_stream_proxy_process_connection(ngx_event_t *ev, ngx_uint_t from_upstream); static void ngx_stream_proxy_connect_handler(ngx_event_t *ev); static ngx_int_t ngx_stream_proxy_test_connect(ngx_connection_t *c); -static ngx_int_t ngx_stream_proxy_process(ngx_stream_session_t *s, +static void ngx_stream_proxy_process(ngx_stream_session_t *s, ngx_uint_t from_upstream, ngx_uint_t do_write); static void ngx_stream_proxy_next_upstream(ngx_stream_session_t *s); static void ngx_stream_proxy_finalize(ngx_stream_session_t *s, ngx_int_t rc); @@ -167,6 +168,13 @@ static ngx_command_t ngx_stream_proxy_commands[] = { offsetof(ngx_stream_proxy_srv_conf_t, download_rate), NULL }, + { ngx_string("proxy_responses"), + NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_STREAM_SRV_CONF_OFFSET, + offsetof(ngx_stream_proxy_srv_conf_t, responses), + NULL }, + { ngx_string("proxy_next_upstream"), NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG, ngx_conf_set_flag_slot, @@ -351,6 +359,7 @@ ngx_stream_proxy_handler(ngx_stream_session_t *s) u->peer.log_error = NGX_ERROR_ERR; u->peer.local = pscf->local; + u->peer.type = c->type; uscf = pscf->upstream; @@ -370,6 +379,14 @@ ngx_stream_proxy_handler(ngx_stream_session_t *s) u->proxy_protocol = pscf->proxy_protocol; u->start_sec = ngx_time(); + c->write->handler = ngx_stream_proxy_downstream_handler; + c->read->handler = ngx_stream_proxy_downstream_handler; + + if (c->type == SOCK_DGRAM) { + ngx_stream_proxy_connect(s); + return; + } + p = ngx_pnalloc(c->pool, pscf->buffer_size); if (p == NULL) { ngx_stream_proxy_finalize(s, NGX_ERROR); @@ -381,9 +398,6 @@ ngx_stream_proxy_handler(ngx_stream_session_t *s) u->downstream_buf.pos = p; u->downstream_buf.last = p; - c->write->handler = ngx_stream_proxy_downstream_handler; - c->read->handler = ngx_stream_proxy_downstream_handler; - if (u->proxy_protocol #if (NGX_STREAM_SSL) && pscf->ssl == NULL @@ -406,8 +420,8 @@ ngx_stream_proxy_handler(ngx_stream_session_t *s) u->proxy_protocol = 0; } - if (ngx_stream_proxy_process(s, 0, 0) != NGX_OK) { - return; + if (c->read->ready) { + ngx_post_event(c->read, &ngx_posted_events); } ngx_stream_proxy_connect(s); @@ -488,7 +502,10 @@ ngx_stream_proxy_init_upstream(ngx_stream_session_t *s) cscf = ngx_stream_get_module_srv_conf(s, ngx_stream_core_module); - if (cscf->tcp_nodelay && pc->tcp_nodelay == NGX_TCP_NODELAY_UNSET) { + if (pc->type == SOCK_STREAM + && cscf->tcp_nodelay + && pc->tcp_nodelay == NGX_TCP_NODELAY_UNSET) + { ngx_log_debug0(NGX_LOG_DEBUG_STREAM, pc->log, 0, "tcp_nodelay"); tcp_nodelay = 1; @@ -516,7 +533,7 @@ ngx_stream_proxy_init_upstream(ngx_stream_session_t *s) pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module); #if (NGX_STREAM_SSL) - if (pscf->ssl && pc->ssl == NULL) { + if (pc->type == SOCK_STREAM && pscf->ssl && pc->ssl == NULL) { ngx_stream_proxy_ssl_init_connection(s); return; } @@ -535,7 +552,9 @@ ngx_stream_proxy_init_upstream(ngx_stream_session_t *s) handler = c->log->handler; c->log->handler = NULL; - ngx_log_error(NGX_LOG_INFO, c->log, 0, "proxy %V connected to %V", + ngx_log_error(NGX_LOG_INFO, c->log, 0, + "%sproxy %V connected to %V", + pc->type == SOCK_DGRAM ? "udp " : "", &str, u->peer.name); c->log->handler = handler; @@ -544,24 +563,36 @@ ngx_stream_proxy_init_upstream(ngx_stream_session_t *s) c->log->action = "proxying connection"; - p = ngx_pnalloc(c->pool, pscf->buffer_size); - if (p == NULL) { - ngx_stream_proxy_finalize(s, NGX_ERROR); - return; + if (u->upstream_buf.start == NULL) { + p = ngx_pnalloc(c->pool, pscf->buffer_size); + if (p == NULL) { + ngx_stream_proxy_finalize(s, NGX_ERROR); + return; + } + + u->upstream_buf.start = p; + u->upstream_buf.end = p + pscf->buffer_size; + u->upstream_buf.pos = p; + u->upstream_buf.last = p; } - u->upstream_buf.start = p; - u->upstream_buf.end = p + pscf->buffer_size; - u->upstream_buf.pos = p; - u->upstream_buf.last = p; + if (c->type == SOCK_DGRAM) { + s->received = c->buffer->last - c->buffer->pos; + u->downstream_buf = *c->buffer; + + if (pscf->responses == 0) { + pc->read->ready = 0; + pc->read->eof = 1; + } + } u->connected = 1; pc->read->handler = ngx_stream_proxy_upstream_handler; pc->write->handler = ngx_stream_proxy_upstream_handler; - if (ngx_stream_proxy_process(s, 1, 0) != NGX_OK) { - return; + if (pc->read->ready || pc->read->eof) { + ngx_post_event(pc->read, &ngx_posted_events); } ngx_stream_proxy_process(s, 0, 1); @@ -894,11 +925,15 @@ ngx_stream_proxy_process_connection(ngx_event_t *ev, ngx_uint_t from_upstream) s = c->data; u = s->upstream; + c = s->connection; + pc = u->peer.connection; + + pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module); + if (ev->timedout) { + ev->timedout = 0; if (ev->delayed) { - - ev->timedout = 0; ev->delayed = 0; if (!ev->ready) { @@ -907,20 +942,35 @@ ngx_stream_proxy_process_connection(ngx_event_t *ev, ngx_uint_t from_upstream) return; } - if (u->connected) { - pc = u->peer.connection; - - if (!c->read->delayed && !pc->read->delayed) { - pscf = ngx_stream_get_module_srv_conf(s, - ngx_stream_proxy_module); - ngx_add_timer(c->write, pscf->timeout); - } + if (u->connected && !c->read->delayed && !pc->read->delayed) { + ngx_add_timer(c->write, pscf->timeout); } return; } } else { + if (s->connection->type == SOCK_DGRAM) { + if (pscf->responses == NGX_MAX_INT32_VALUE) { + + /* + * successfully terminate timed out UDP session + * with unspecified number of responses + */ + + pc->read->ready = 0; + pc->read->eof = 1; + + ngx_stream_proxy_process(s, 1, 0); + return; + } + + if (u->received == 0) { + ngx_stream_proxy_next_upstream(s); + return; + } + } + ngx_connection_error(c, NGX_ETIMEDOUT, "connection timed out"); ngx_stream_proxy_finalize(s, NGX_DECLINED); return; @@ -1019,7 +1069,7 @@ ngx_stream_proxy_test_connect(ngx_connection_t *c) } -static ngx_int_t +static void ngx_stream_proxy_process(ngx_stream_session_t *s, ngx_uint_t from_upstream, ngx_uint_t do_write) { @@ -1039,6 +1089,21 @@ ngx_stream_proxy_process(ngx_stream_session_t *s, ngx_uint_t from_upstream, c = s->connection; pc = u->connected ? u->peer.connection : NULL; + if (c->type == SOCK_DGRAM && (ngx_terminate || ngx_exiting)) { + + /* socket is already closed on worker shutdown */ + + handler = c->log->handler; + c->log->handler = NULL; + + ngx_log_error(NGX_LOG_INFO, c->log, 0, "disconnected on shutdown"); + + c->log->handler = handler; + + ngx_stream_proxy_finalize(s, NGX_OK); + return; + } + pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module); if (from_upstream) { @@ -1066,9 +1131,19 @@ ngx_stream_proxy_process(ngx_stream_session_t *s, ngx_uint_t from_upstream, n = dst->send(dst, b->pos, size); + if (n == NGX_AGAIN && dst->shared) { + /* cannot wait on a shared socket */ + n = NGX_ERROR; + } + if (n == NGX_ERROR) { + if (c->type == SOCK_DGRAM && !from_upstream) { + ngx_stream_proxy_next_upstream(s); + return; + } + ngx_stream_proxy_finalize(s, NGX_DECLINED); - return NGX_ERROR; + return; } if (n > 0) { @@ -1118,6 +1193,12 @@ ngx_stream_proxy_process(ngx_stream_session_t *s, ngx_uint_t from_upstream, } } + if (c->type == SOCK_DGRAM && ++u->responses == pscf->responses) + { + src->read->ready = 0; + src->read->eof = 1; + } + *received += n; b->last += n; do_write = 1; @@ -1126,6 +1207,11 @@ ngx_stream_proxy_process(ngx_stream_session_t *s, ngx_uint_t from_upstream, } if (n == NGX_ERROR) { + if (c->type == SOCK_DGRAM && u->received == 0) { + ngx_stream_proxy_next_upstream(s); + return; + } + src->read->eof = 1; } } @@ -1138,29 +1224,30 @@ ngx_stream_proxy_process(ngx_stream_session_t *s, ngx_uint_t from_upstream, c->log->handler = NULL; ngx_log_error(NGX_LOG_INFO, c->log, 0, - "%s disconnected" + "%s%s disconnected" ", bytes from/to client:%O/%O" ", bytes from/to upstream:%O/%O", + src->type == SOCK_DGRAM ? "udp " : "", from_upstream ? "upstream" : "client", s->received, c->sent, u->received, pc ? pc->sent : 0); c->log->handler = handler; ngx_stream_proxy_finalize(s, NGX_OK); - return NGX_DONE; + return; } flags = src->read->eof ? NGX_CLOSE_EVENT : 0; - if (ngx_handle_read_event(src->read, flags) != NGX_OK) { + if (!src->shared && ngx_handle_read_event(src->read, flags) != NGX_OK) { ngx_stream_proxy_finalize(s, NGX_ERROR); - return NGX_ERROR; + return; } if (dst) { - if (ngx_handle_write_event(dst->write, 0) != NGX_OK) { + if (!dst->shared && ngx_handle_write_event(dst->write, 0) != NGX_OK) { ngx_stream_proxy_finalize(s, NGX_ERROR); - return NGX_ERROR; + return; } if (!c->read->delayed && !pc->read->delayed) { @@ -1170,8 +1257,6 @@ ngx_stream_proxy_process(ngx_stream_session_t *s, ngx_uint_t from_upstream, ngx_del_timer(c->write); } } - - return NGX_OK; } @@ -1333,6 +1418,7 @@ ngx_stream_proxy_create_srv_conf(ngx_conf_t *cf) conf->buffer_size = NGX_CONF_UNSET_SIZE; conf->upload_rate = NGX_CONF_UNSET_SIZE; conf->download_rate = NGX_CONF_UNSET_SIZE; + conf->responses = NGX_CONF_UNSET_UINT; conf->next_upstream_tries = NGX_CONF_UNSET_UINT; conf->next_upstream = NGX_CONF_UNSET; conf->proxy_protocol = NGX_CONF_UNSET; @@ -1375,6 +1461,9 @@ ngx_stream_proxy_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_size_value(conf->download_rate, prev->download_rate, 0); + ngx_conf_merge_uint_value(conf->responses, + prev->responses, NGX_MAX_INT32_VALUE); + ngx_conf_merge_uint_value(conf->next_upstream_tries, prev->next_upstream_tries, 0); diff --git a/src/stream/ngx_stream_upstream.c b/src/stream/ngx_stream_upstream.c index 805ee70..69dddc5 100644 --- a/src/stream/ngx_stream_upstream.c +++ b/src/stream/ngx_stream_upstream.c @@ -388,7 +388,7 @@ ngx_stream_upstream_add(ngx_conf_t *cf, ngx_url_t *u, ngx_uint_t flags) uscf->port = u->port; uscf->no_port = u->no_port; - if (u->naddrs == 1) { + if (u->naddrs == 1 && (u->port || u->family == AF_UNIX)) { uscf->servers = ngx_array_create(cf->pool, 1, sizeof(ngx_stream_upstream_server_t)); if (uscf->servers == NULL) { diff --git a/src/stream/ngx_stream_upstream.h b/src/stream/ngx_stream_upstream.h index 80520c2..1f4810c 100644 --- a/src/stream/ngx_stream_upstream.h +++ b/src/stream/ngx_stream_upstream.h @@ -84,6 +84,7 @@ typedef struct { ngx_buf_t upstream_buf; off_t received; time_t start_sec; + ngx_uint_t responses; #if (NGX_STREAM_SSL) ngx_str_t ssl_name; #endif From dfa3b2f2df7c50a06253dd9e4ecb22abae3be065 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Wed, 30 Mar 2016 11:28:10 +0300 Subject: [PATCH 045/600] New upstream release (1.9.13) --- debian/changelog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index 226b72b..ab5e082 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,7 +1,7 @@ -nginx (1.9.11-1) UNRELEASED; urgency=medium +nginx (1.9.13-1) UNRELEASED; urgency=medium [ Christos Trochalakis ] - * New upstream release (1.9.11) (Closes: #812806) + * New upstream release (1.9.13) (Closes: #812806) * debian: + Setup dynamic module flow, and implement a simple dh_nginx helper for internal use. From 5d3e5e8fcb4d6746aa28bc1513ed544cba29c69d Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Wed, 30 Mar 2016 12:05:52 +0300 Subject: [PATCH 046/600] Update auth-pam module and introduce libnginx-mod-http-auth-pam --- debian/changelog | 3 ++ debian/control | 11 +++++ debian/libnginx-mod-http-auth-pam.nginx | 13 ++++++ .../libnginx-mod.conf/mod-http-auth-pam.conf | 1 + debian/modules/README.Modules-versions | 2 +- debian/modules/nginx-auth-pam/ChangeLog | 8 ++++ debian/modules/nginx-auth-pam/LICENSE | 2 +- debian/modules/nginx-auth-pam/README.md | 14 +++--- debian/modules/nginx-auth-pam/VERSION | 1 + debian/modules/nginx-auth-pam/config | 18 ++++++-- .../nginx-auth-pam/ngx_http_auth_pam_module.c | 45 ++++++++++++------- debian/rules | 6 +-- 12 files changed, 93 insertions(+), 31 deletions(-) create mode 100755 debian/libnginx-mod-http-auth-pam.nginx create mode 100644 debian/libnginx-mod.conf/mod-http-auth-pam.conf create mode 100644 debian/modules/nginx-auth-pam/VERSION diff --git a/debian/changelog b/debian/changelog index ab5e082..63ae632 100644 --- a/debian/changelog +++ b/debian/changelog @@ -22,6 +22,9 @@ nginx (1.9.13-1) UNRELEASED; urgency=medium * debian/modules/nginx-lua: + Update nginx-lua to v0.10.1rc0-5-g01727a3. Fixes buiding failures with nginx 1.9.11. + * debian/modules/nginx-auth-pam: + + Update http-auth-pam module to 1.5 and convert it to a dyn module. + (Closes: #819062) -- Christos Trochalakis Thu, 11 Feb 2016 15:06:38 +0200 diff --git a/debian/control b/debian/control index 2076f5c..96def42 100644 --- a/debian/control +++ b/debian/control @@ -85,6 +85,7 @@ Depends: nginx-common (= ${source:Version}), libnginx-mod-http-xslt-filter (= ${binary:Version}), libnginx-mod-mail (= ${binary:Version}), libnginx-mod-stream (= ${binary:Version}), + libnginx-mod-http-auth-pam (= ${binary:Version}), ${misc:Depends}, ${shlibs:Depends} Breaks: nginx (<< 1.4.5-1) @@ -177,6 +178,7 @@ Depends: nginx-common (= ${source:Version}), libnginx-mod-http-xslt-filter (= ${binary:Version}), libnginx-mod-mail (= ${binary:Version}), libnginx-mod-stream (= ${binary:Version}), + libnginx-mod-http-auth-pam (= ${binary:Version}), ${misc:Depends}, ${perl:Depends}, ${shlibs:Depends} @@ -271,3 +273,12 @@ Description: Stream module for Nginx Stream module supports loadbalancing & proxying to TCP servers. The module also supports ACLs/connection limiting and configuring multiple operational parameters. + +Package: libnginx-mod-http-auth-pam +Architecture: any +Depends: ${misc:Depends}, ${shlibs:Depends} +Description: PAM authentication module for Nginx + The nginx_http_auth_pam module enables authentication using PAM. + . + The module uses PAM as a backend for simple http authentication. It + also allows setting the pam service name to allow more fine grained control. diff --git a/debian/libnginx-mod-http-auth-pam.nginx b/debian/libnginx-mod-http-auth-pam.nginx new file mode 100755 index 0000000..02c5edc --- /dev/null +++ b/debian/libnginx-mod-http-auth-pam.nginx @@ -0,0 +1,13 @@ +#!/usr/bin/perl -w + +use File::Basename; + +# Guess module name +$module = basename($0, '.nginx'); +$module =~ s/^libnginx-mod-//; + +$modulepath = $module; +$modulepath =~ s/-/_/g; + +print "mod debian/build-full/objs/ngx_${modulepath}_module.so\n"; +print "mod debian/libnginx-mod.conf/mod-${module}.conf\n"; diff --git a/debian/libnginx-mod.conf/mod-http-auth-pam.conf b/debian/libnginx-mod.conf/mod-http-auth-pam.conf new file mode 100644 index 0000000..2eb6752 --- /dev/null +++ b/debian/libnginx-mod.conf/mod-http-auth-pam.conf @@ -0,0 +1 @@ +load_module modules/ngx_http_auth_pam_module.so; diff --git a/debian/modules/README.Modules-versions b/debian/modules/README.Modules-versions index dbff74d..3952163 100644 --- a/debian/modules/README.Modules-versions +++ b/debian/modules/README.Modules-versions @@ -14,7 +14,7 @@ README for Modules versions nginx-auth-pam Homepage: https://github.com/stogh/ngx_http_auth_pam_module - Version: 1.4 + Version: 1.5 nginx-echo Homepage: https://github.com/agentzh/echo-nginx-module diff --git a/debian/modules/nginx-auth-pam/ChangeLog b/debian/modules/nginx-auth-pam/ChangeLog index 466bd9c..8aaf031 100644 --- a/debian/modules/nginx-auth-pam/ChangeLog +++ b/debian/modules/nginx-auth-pam/ChangeLog @@ -1,3 +1,11 @@ +2016-03-23 sto@iti.es + + * Version 1.5. + * Added support to build module dynamically (patch provided by Sjir + Bagmeijer ). + * Log PAM error and info messages to nginx log files (patch provided by + André Caron ). + 2015-02-04 sto@iti.es * Version 1.4. diff --git a/debian/modules/nginx-auth-pam/LICENSE b/debian/modules/nginx-auth-pam/LICENSE index f5be528..b2d9324 100644 --- a/debian/modules/nginx-auth-pam/LICENSE +++ b/debian/modules/nginx-auth-pam/LICENSE @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2015 Sergio Talens Oliag + * Copyright (C) 2008-2016 Sergio Talens Oliag * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/debian/modules/nginx-auth-pam/README.md b/debian/modules/nginx-auth-pam/README.md index c6d58f0..a4eea45 100644 --- a/debian/modules/nginx-auth-pam/README.md +++ b/debian/modules/nginx-auth-pam/README.md @@ -4,15 +4,17 @@ ### Compilation -When compiling from source build as usual adding the -add-module option: +When compiling from source build as usual adding the ``--add-module`` option: ./configure --add-module=$PATH_TO_MODULE -If you are using a Debian GNU/Linux distribution install the nginx-full package; -the module has been included in the nginx debian package since version 1.1.6-1 -and there are newer packages on the stable distribution (wheezy) and the wheezy -version is also available from the oldstable backports repository -(squeeze-backports). +or if you want to build the module as dynamic use the ``--add-dynamic-module`` +option. + +If you are using a Debian GNU/Linux distribution install the ``nginx-full`` +package; the module has been included in the debian package since version +``1.1.6-1``, so it is available on all stable distributions since the *wheezy* +release. ### Configuration diff --git a/debian/modules/nginx-auth-pam/VERSION b/debian/modules/nginx-auth-pam/VERSION new file mode 100644 index 0000000..c239c60 --- /dev/null +++ b/debian/modules/nginx-auth-pam/VERSION @@ -0,0 +1 @@ +1.5 diff --git a/debian/modules/nginx-auth-pam/config b/debian/modules/nginx-auth-pam/config index ef0815e..9c30919 100644 --- a/debian/modules/nginx-auth-pam/config +++ b/debian/modules/nginx-auth-pam/config @@ -1,4 +1,16 @@ ngx_addon_name=ngx_http_auth_pam_module -HTTP_MODULES="$HTTP_MODULES ngx_http_auth_pam_module" -NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_auth_pam_module.c" -CORE_LIBS="$CORE_LIBS -lpam" + +if test -n "$ngx_module_link"; then + ngx_module_type=HTTP + ngx_module_name=ngx_http_auth_pam_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_auth_pam_module.c" + ngx_module_libs="$CORE_LIBS -lpam" + + . auto/module +else + HTTP_MODULES="$HTTP_MODULES ngx_http_auth_pam_module" + NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_auth_pam_module.c" + CORE_LIBS="$CORE_LIBS -lpam" +fi \ No newline at end of file diff --git a/debian/modules/nginx-auth-pam/ngx_http_auth_pam_module.c b/debian/modules/nginx-auth-pam/ngx_http_auth_pam_module.c index a49d7a6..167a37f 100644 --- a/debian/modules/nginx-auth-pam/ngx_http_auth_pam_module.c +++ b/debian/modules/nginx-auth-pam/ngx_http_auth_pam_module.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2015 Sergio Talens-Oliag + * Copyright (C) 2008-2016 Sergio Talens-Oliag * * Based on nginx's 'ngx_http_auth_basic_module.c' by Igor Sysoev and apache's * 'mod_auth_pam.c' by Ingo Luetkebolhe. @@ -19,11 +19,12 @@ typedef struct { ngx_str_t passwd; } ngx_http_auth_pam_ctx_t; -/* PAM userinfo */ +/* PAM authinfo */ typedef struct { ngx_str_t username; ngx_str_t password; -} ngx_pam_userinfo; + ngx_log_t *log; +} ngx_pam_authinfo; /* Module configuration struct */ typedef struct { @@ -151,14 +152,14 @@ ngx_auth_pam_talker(int num_msg, const struct pam_message ** msg, struct pam_response ** resp, void *appdata_ptr) { int i; - ngx_pam_userinfo *uinfo; + ngx_pam_authinfo *ainfo; struct pam_response *response; - uinfo = (ngx_pam_userinfo *) appdata_ptr; + ainfo = (ngx_pam_authinfo *) appdata_ptr; response = NULL; /* parameter sanity checking */ - if (!resp || !msg || !uinfo) + if (!resp || !msg || !ainfo) return PAM_CONV_ERR; /* allocate memory to store response */ @@ -176,10 +177,18 @@ ngx_auth_pam_talker(int num_msg, const struct pam_message ** msg, switch (msg[i]->msg_style) { case PAM_PROMPT_ECHO_ON: /* on memory allocation failure, auth fails */ - response[i].resp = strdup((const char *)uinfo->username.data); + response[i].resp = strdup((const char *)ainfo->username.data); break; case PAM_PROMPT_ECHO_OFF: - response[i].resp = strdup((const char *)uinfo->password.data); + response[i].resp = strdup((const char *)ainfo->password.data); + break; + case PAM_ERROR_MSG: + ngx_log_error(NGX_LOG_ERR, ainfo->log, 0, + "PAM: \'%s\'.", msg[i]->msg); + break; + case PAM_TEXT_INFO: + ngx_log_error(NGX_LOG_INFO, ainfo->log, 0, + "PAM: \'%s\'.", msg[i]->msg); break; default: free_resp(i, response); @@ -277,7 +286,7 @@ ngx_http_auth_pam_authenticate(ngx_http_request_t *r, ngx_int_t rc; ngx_http_auth_pam_loc_conf_t *alcf; - ngx_pam_userinfo uinfo; + ngx_pam_authinfo ainfo; struct pam_conv conv_info; /* PAM struct */ pam_handle_t *pamh; u_char *service_name; @@ -303,14 +312,16 @@ ngx_http_auth_pam_authenticate(ngx_http_request_t *r, p = ngx_cpymem(uname_buf, r->headers_in.user.data , len); *p ='\0'; - uinfo.username.data = uname_buf; - uinfo.username.len = len; + ainfo.username.data = uname_buf; + ainfo.username.len = len; - uinfo.password.data = r->headers_in.passwd.data; - uinfo.password.len = r->headers_in.passwd.len; + ainfo.password.data = r->headers_in.passwd.data; + ainfo.password.len = r->headers_in.passwd.len; + + ainfo.log = r->connection->log; conv_info.conv = &ngx_auth_pam_talker; - conv_info.appdata_ptr = (void *) &uinfo; + conv_info.appdata_ptr = (void *) &ainfo; pamh = NULL; @@ -321,7 +332,7 @@ ngx_http_auth_pam_authenticate(ngx_http_request_t *r, service_name = alcf->service_name.data; } if ((rc = pam_start((const char *) service_name, - (const char *) uinfo.username.data, + (const char *) ainfo.username.data, &conv_info, &pamh)) != PAM_SUCCESS) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, @@ -339,7 +350,7 @@ ngx_http_auth_pam_authenticate(ngx_http_request_t *r, PAM_DISALLOW_NULL_AUTHTOK)) != PAM_SUCCESS) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "PAM: user '%s' - not authenticated: %s", - uinfo.username.data, pam_strerror(pamh, rc)); + ainfo.username.data, pam_strerror(pamh, rc)); pam_end(pamh, PAM_SUCCESS); return ngx_http_auth_pam_set_realm(r, &alcf->realm); } /* endif authenticate */ @@ -348,7 +359,7 @@ ngx_http_auth_pam_authenticate(ngx_http_request_t *r, if ((rc = pam_acct_mgmt(pamh, PAM_DISALLOW_NULL_AUTHTOK)) != PAM_SUCCESS) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "PAM: user '%s' - invalid account: %s", - uinfo.username.data, pam_strerror(pamh, rc)); + ainfo.username.data, pam_strerror(pamh, rc)); pam_end(pamh, PAM_SUCCESS); return ngx_http_auth_pam_set_realm(r, &alcf->realm); } diff --git a/debian/rules b/debian/rules index f9db327..4c28a8b 100755 --- a/debian/rules +++ b/debian/rules @@ -11,7 +11,7 @@ DEBIAN_NGINX_PERL_LDFLAGS:= $(shell DEB_BUILD_MAINT_OPTIONS=hardening=+all,-pie export DEBIAN_NGINX_PERL_LDFLAGS FLAVOURS := full light extras -DYN_MODS := http-geoip http-image-filter http-xslt-filter mail stream +DYN_MODS := http-geoip http-image-filter http-xslt-filter mail stream http-auth-pam MODULESDIR = $(CURDIR)/debian/modules BASEDIR = $(CURDIR) @@ -83,7 +83,7 @@ full_configure_flags := \ --with-stream_ssl_module \ --with-mail=dynamic \ --with-mail_ssl_module \ - --add-module=$(MODULESDIR)/nginx-auth-pam \ + --add-dynamic-module=$(MODULESDIR)/nginx-auth-pam \ --add-module=$(MODULESDIR)/nginx-dav-ext-module \ --add-module=$(MODULESDIR)/nginx-echo \ --add-module=$(MODULESDIR)/nginx-upstream-fair \ @@ -108,7 +108,7 @@ extras_configure_flags := \ --with-stream=dynamic \ --with-stream_ssl_module \ --add-module=$(MODULESDIR)/headers-more-nginx-module \ - --add-module=$(MODULESDIR)/nginx-auth-pam \ + --add-dynamic-module=$(MODULESDIR)/nginx-auth-pam \ --add-module=$(MODULESDIR)/nginx-cache-purge \ --add-module=$(MODULESDIR)/nginx-dav-ext-module \ --add-module=$(MODULESDIR)/nginx-development-kit \ From e7ea50abbd00e4172ee7d28f94c94c71047a32f0 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Wed, 30 Mar 2016 12:27:13 +0300 Subject: [PATCH 047/600] Update LUA module and introduce libnginx-mod-http-lua --- debian/changelog | 2 +- debian/control | 12 ++++ debian/libnginx-mod-http-lua.nginx | 13 ++++ debian/libnginx-mod.conf/mod-http-lua.conf | 1 + debian/modules/README.Modules-versions | 2 +- debian/modules/nginx-lua/README.markdown | 35 +++++------ .../modules/nginx-lua/doc/HttpLuaModule.wiki | 30 +++++----- .../modules/nginx-lua/src/ngx_http_lua_args.c | 13 ++-- .../nginx-lua/src/ngx_http_lua_balancer.c | 59 +++++++++++++++++-- .../nginx-lua/src/ngx_http_lua_module.c | 16 ++++- .../nginx-lua/src/ngx_http_lua_ssl_certby.c | 28 +++++++-- debian/modules/nginx-lua/t/031-post-args.t | 35 ++++++++++- debian/modules/nginx-lua/t/129-ssl-socket.t | 2 +- debian/modules/nginx-lua/t/133-worker-count.t | 20 +++++++ .../modules/nginx-lua/t/134-worker-count-5.t | 46 +++++++++++++++ debian/rules | 4 +- 16 files changed, 260 insertions(+), 58 deletions(-) create mode 100755 debian/libnginx-mod-http-lua.nginx create mode 100644 debian/libnginx-mod.conf/mod-http-lua.conf diff --git a/debian/changelog b/debian/changelog index 63ae632..24f9b02 100644 --- a/debian/changelog +++ b/debian/changelog @@ -20,7 +20,7 @@ nginx (1.9.13-1) UNRELEASED; urgency=medium * debian/nginx-common.nginx.service: + Documentation points to nginx man page. * debian/modules/nginx-lua: - + Update nginx-lua to v0.10.1rc0-5-g01727a3. + + Update nginx-lua to v0.12 and convert it to a dyn module. Fixes buiding failures with nginx 1.9.11. * debian/modules/nginx-auth-pam: + Update http-auth-pam module to 1.5 and convert it to a dyn module. diff --git a/debian/control b/debian/control index 96def42..96fa475 100644 --- a/debian/control +++ b/debian/control @@ -179,6 +179,7 @@ Depends: nginx-common (= ${source:Version}), libnginx-mod-mail (= ${binary:Version}), libnginx-mod-stream (= ${binary:Version}), libnginx-mod-http-auth-pam (= ${binary:Version}), + libnginx-mod-http-lua (= ${binary:Version}), ${misc:Depends}, ${perl:Depends}, ${shlibs:Depends} @@ -282,3 +283,14 @@ Description: PAM authentication module for Nginx . The module uses PAM as a backend for simple http authentication. It also allows setting the pam service name to allow more fine grained control. + +Package: libnginx-mod-http-lua +Architecture: any +Depends: ${misc:Depends}, ${shlibs:Depends} +Description: LUA module for Nginx + Embed LUA runtime into nginx. + . + This module embeds Lua, via the standard Lua 5.1 interpreter or LuaJIT + 2.0/2.1, into Nginx and by leveraging Nginx's subrequests, allows the + integration of the powerful Lua threads (Lua coroutines) into the Nginx event + model. diff --git a/debian/libnginx-mod-http-lua.nginx b/debian/libnginx-mod-http-lua.nginx new file mode 100755 index 0000000..02c5edc --- /dev/null +++ b/debian/libnginx-mod-http-lua.nginx @@ -0,0 +1,13 @@ +#!/usr/bin/perl -w + +use File::Basename; + +# Guess module name +$module = basename($0, '.nginx'); +$module =~ s/^libnginx-mod-//; + +$modulepath = $module; +$modulepath =~ s/-/_/g; + +print "mod debian/build-full/objs/ngx_${modulepath}_module.so\n"; +print "mod debian/libnginx-mod.conf/mod-${module}.conf\n"; diff --git a/debian/libnginx-mod.conf/mod-http-lua.conf b/debian/libnginx-mod.conf/mod-http-lua.conf new file mode 100644 index 0000000..f6311f4 --- /dev/null +++ b/debian/libnginx-mod.conf/mod-http-lua.conf @@ -0,0 +1 @@ +load_module modules/ngx_http_lua_module.so; diff --git a/debian/modules/README.Modules-versions b/debian/modules/README.Modules-versions index 3952163..53cbc2c 100644 --- a/debian/modules/README.Modules-versions +++ b/debian/modules/README.Modules-versions @@ -22,7 +22,7 @@ README for Modules versions nginx-lua Homepage: https://github.com/openresty/lua-nginx-module - Version: v0.10.1rc0-5-g01727a3 + Version: v0.10.2 nginx-upstream-fair Homepage: https://github.com/gnosek/nginx-upstream-fair diff --git a/debian/modules/nginx-lua/README.markdown b/debian/modules/nginx-lua/README.markdown index 94e67ad..4e8f9bd 100644 --- a/debian/modules/nginx-lua/README.markdown +++ b/debian/modules/nginx-lua/README.markdown @@ -21,6 +21,7 @@ Table of Contents * [Typical Uses](#typical-uses) * [Nginx Compatibility](#nginx-compatibility) * [Installation](#installation) + * [Building as a dynamic module](#building-as-a-dynamic-module) * [C Macro Configurations](#c-macro-configurations) * [Installation on Ubuntu 11.10](#installation-on-ubuntu-1110) * [Community](#community) @@ -61,7 +62,7 @@ Production ready. Version ======= -This document describes ngx_lua [v0.10.0](https://github.com/openresty/lua-nginx-module/tags) released on 11 January 2016. +This document describes ngx_lua [v0.10.2](https://github.com/openresty/lua-nginx-module/tags) released on 8 March 2016. Synopsis ======== @@ -128,7 +129,7 @@ Synopsis ngx.say("status: ", res.status) ngx.say("body:") ngx.print(res.body) - end'; + end } } @@ -264,7 +265,7 @@ It is highly recommended to use the [OpenResty bundle](http://openresty.org) tha Alternatively, ngx_lua can be manually compiled into Nginx: -1. Install LuaJIT 2.0 or 2.1 (recommended) or Lua 5.1 (Lua 5.2 is *not* supported yet). LuaJIT can be downloaded from the [the LuaJIT project website](http://luajit.org/download.html) and Lua 5.1, from the [Lua project website](http://www.lua.org/). Some distribution package managers also distribute LuaJIT and/or Lua. +1. Install LuaJIT 2.0 or 2.1 (recommended) or Lua 5.1 (Lua 5.2 is *not* supported yet). LuaJIT can be downloaded from the [LuaJIT project website](http://luajit.org/download.html) and Lua 5.1, from the [Lua project website](http://www.lua.org/). Some distribution package managers also distribute LuaJIT and/or Lua. 1. Download the latest version of the ngx_devel_kit (NDK) module [HERE](https://github.com/simpl/ngx_devel_kit/tags). 1. Download the latest version of ngx_lua [HERE](https://github.com/openresty/lua-nginx-module/tags). 1. Download the latest version of Nginx [HERE](http://nginx.org/) (See [Nginx Compatibility](#nginx-compatibility)) @@ -299,11 +300,17 @@ Build the source with this module: make install ``` +[Back to TOC](#table-of-contents) + +Building as a dynamic module +---------------------------- + Starting from NGINX 1.9.11, you can also compile this module as a dynamic module, by using the `--add-dynamic-module=PATH` option instead of `--add-module=PATH` on the `./configure` command line above. And then you can explicitly load the module in your `nginx.conf` via the [load_module](http://nginx.org/en/docs/ngx_core_module.html#load_module) directive, for example, ```nginx +load_module /path/to/modules/ndk_http_module.so; # assuming NDK is built as a dynamic module too load_module /path/to/modules/ngx_http_lua_module.so; ``` @@ -843,22 +850,11 @@ TODO ==== * cosocket: implement LuaSocket's unconnected UDP API. -* add support for implementing general TCP servers instead of HTTP servers in Lua. For example, +* port this module to the "datagram" subsystem of NGINX for implementing general UDP servers instead of HTTP +servers in Lua. For example, ```lua - tcp { - server { - listen 11212; - handler_by_lua ' - -- custom Lua code implementing the special TCP server... - '; - } - } -``` -* add support for implementing general UDP servers instead of HTTP servers in Lua. For example, -```lua - - udp { + datagram { server { listen 1953; handler_by_lua ' @@ -881,6 +877,7 @@ TODO * add `ignore_resp_headers`, `ignore_resp_body`, and `ignore_resp` options to [ngx.location.capture](#ngxlocationcapture) and [ngx.location.capture_multi](#ngxlocationcapture_multi) methods, to allow micro performance tuning on the user side. * add automatic Lua code time slicing support by yielding and resuming the Lua VM actively via Lua's debug hooks. * add `stat` mode similar to [mod_lua](https://httpd.apache.org/docs/trunk/mod/mod_lua.html). +* cosocket: add client SSL certificiate support. [Back to TOC](#table-of-contents) @@ -6845,10 +6842,14 @@ Retrieves the current running phase name. Possible return values are for the context of [init_by_lua](#init_by_lua) or [init_by_lua_file](#init_by_lua_file). * `init_worker` for the context of [init_worker_by_lua](#init_worker_by_lua) or [init_worker_by_lua_file](#init_worker_by_lua_file). +* `ssl_cert` + for the context of [ssl_certificate_by_lua_block](#ssl_certificate_by_lua_block) or [ssl_certificate_by_lua_file](#ssl_certificate_by_lua_file). * `set` for the context of [set_by_lua](#set_by_lua) or [set_by_lua_file](#set_by_lua_file). * `rewrite` for the context of [rewrite_by_lua](#rewrite_by_lua) or [rewrite_by_lua_file](#rewrite_by_lua_file). +* `balancer` + for the context of [balancer_by_lua_block](#balancer_by_lua_block) or [balancer_by_lua_file](#balancer_by_lua_file). * `access` for the context of [access_by_lua](#access_by_lua) or [access_by_lua_file](#access_by_lua_file). * `content` diff --git a/debian/modules/nginx-lua/doc/HttpLuaModule.wiki b/debian/modules/nginx-lua/doc/HttpLuaModule.wiki index 3a39ef8..f6824ef 100644 --- a/debian/modules/nginx-lua/doc/HttpLuaModule.wiki +++ b/debian/modules/nginx-lua/doc/HttpLuaModule.wiki @@ -10,7 +10,7 @@ Production ready. = Version = -This document describes ngx_lua [https://github.com/openresty/lua-nginx-module/tags v0.10.0] released on 11 January 2016. +This document describes ngx_lua [https://github.com/openresty/lua-nginx-module/tags v0.10.2] released on 8 March 2016. = Synopsis = @@ -75,7 +75,7 @@ This document describes ngx_lua [https://github.com/openresty/lua-nginx-module/t ngx.say("status: ", res.status) ngx.say("body:") ngx.print(res.body) - end'; + end } } @@ -199,7 +199,7 @@ It is highly recommended to use the [http://openresty.org OpenResty bundle] that Alternatively, ngx_lua can be manually compiled into Nginx: -# Install LuaJIT 2.0 or 2.1 (recommended) or Lua 5.1 (Lua 5.2 is ''not'' supported yet). LuaJIT can be downloaded from the [http://luajit.org/download.html the LuaJIT project website] and Lua 5.1, from the [http://www.lua.org/ Lua project website]. Some distribution package managers also distribute LuaJIT and/or Lua. +# Install LuaJIT 2.0 or 2.1 (recommended) or Lua 5.1 (Lua 5.2 is ''not'' supported yet). LuaJIT can be downloaded from the [http://luajit.org/download.html LuaJIT project website] and Lua 5.1, from the [http://www.lua.org/ Lua project website]. Some distribution package managers also distribute LuaJIT and/or Lua. # Download the latest version of the ngx_devel_kit (NDK) module [https://github.com/simpl/ngx_devel_kit/tags HERE]. # Download the latest version of ngx_lua [https://github.com/openresty/lua-nginx-module/tags HERE]. # Download the latest version of Nginx [http://nginx.org/ HERE] (See [[#Nginx Compatibility|Nginx Compatibility]]) @@ -233,11 +233,14 @@ Build the source with this module: make install +== Building as a dynamic module == + Starting from NGINX 1.9.11, you can also compile this module as a dynamic module, by using the `--add-dynamic-module=PATH` option instead of `--add-module=PATH` on the `./configure` command line above. And then you can explicitly load the module in your `nginx.conf` via the [load_module](http://nginx.org/en/docs/ngx_core_module.html#load_module) directive, for example, ```nginx +load_module /path/to/modules/ndk_http_module.so; # assuming NDK is built as a dynamic module too load_module /path/to/modules/ngx_http_lua_module.so; ``` @@ -682,20 +685,10 @@ phases. = TODO = * cosocket: implement LuaSocket's unconnected UDP API. -* add support for implementing general TCP servers instead of HTTP servers in Lua. For example, +* port this module to the "datagram" subsystem of NGINX for implementing general UDP servers instead of HTTP +servers in Lua. For example, - tcp { - server { - listen 11212; - handler_by_lua ' - -- custom Lua code implementing the special TCP server... - '; - } - } - -* add support for implementing general UDP servers instead of HTTP servers in Lua. For example, - - udp { + datagram { server { listen 1953; handler_by_lua ' @@ -718,6 +711,7 @@ phases. * add ignore_resp_headers, ignore_resp_body, and ignore_resp options to [[#ngx.location.capture|ngx.location.capture]] and [[#ngx.location.capture_multi|ngx.location.capture_multi]] methods, to allow micro performance tuning on the user side. * add automatic Lua code time slicing support by yielding and resuming the Lua VM actively via Lua's debug hooks. * add stat mode similar to [https://httpd.apache.org/docs/trunk/mod/mod_lua.html mod_lua]. +* cosocket: add client SSL certificiate support. = Changes = @@ -5765,10 +5759,14 @@ Retrieves the current running phase name. Possible return values are : for the context of [[#init_by_lua|init_by_lua]] or [[#init_by_lua_file|init_by_lua_file]]. * init_worker : for the context of [[#init_worker_by_lua|init_worker_by_lua]] or [[#init_worker_by_lua_file|init_worker_by_lua_file]]. +* ssl_cert +: for the context of [[#ssl_certificate_by_lua_block|ssl_certificate_by_lua_block]] or [[#ssl_certificate_by_lua_file|ssl_certificate_by_lua_file]]. * set : for the context of [[#set_by_lua|set_by_lua]] or [[#set_by_lua_file|set_by_lua_file]]. * rewrite : for the context of [[#rewrite_by_lua|rewrite_by_lua]] or [[#rewrite_by_lua_file|rewrite_by_lua_file]]. +* balancer +: for the context of [[#balancer_by_lua_block|balancer_by_lua_block]] or [[#balancer_by_lua_file|balancer_by_lua_file]]. * access : for the context of [[#access_by_lua|access_by_lua]] or [[#access_by_lua_file|access_by_lua_file]]. * content diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_args.c b/debian/modules/nginx-lua/src/ngx_http_lua_args.c index dbc2ac6..0c307d6 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_args.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_args.c @@ -111,8 +111,6 @@ ngx_http_lua_ngx_req_get_uri_args(lua_State *L) ngx_http_lua_check_fake_request(L, r); - lua_createtable(L, 0, 4); - if (r->args.len == 0) { lua_createtable(L, 0, 0); return 1; @@ -126,6 +124,8 @@ ngx_http_lua_ngx_req_get_uri_args(lua_State *L) return luaL_error(L, "no memory"); } + lua_createtable(L, 0, 4); + ngx_memcpy(buf, r->args.data, r->args.len); last = buf + r->args.len; @@ -183,12 +183,13 @@ ngx_http_lua_ngx_req_get_post_args(lua_State *L) } if (r->request_body->temp_file) { - return luaL_error(L, "requesty body in temp file not supported"); + lua_pushnil(L); + lua_pushliteral(L, "requesty body in temp file not supported"); + return 2; } - lua_createtable(L, 0, 4); - if (r->request_body->bufs == NULL) { + lua_createtable(L, 0, 0); return 1; } @@ -212,6 +213,8 @@ ngx_http_lua_ngx_req_get_post_args(lua_State *L) return luaL_error(L, "no memory"); } + lua_createtable(L, 0, 4); + p = buf; for (cl = r->request_body->bufs; cl; cl = cl->next) { p = ngx_copy(p, cl->buf->pos, cl->buf->last - cl->buf->pos); diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_balancer.c b/debian/modules/nginx-lua/src/ngx_http_lua_balancer.c index 1201d26..a2c66be 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_balancer.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_balancer.c @@ -23,8 +23,6 @@ struct ngx_http_lua_balancer_peer_data_s { ngx_http_lua_srv_conf_t *conf; ngx_http_request_t *request; - ngx_event_get_peer_pt get_rr_peer; - ngx_uint_t more_tries; ngx_uint_t total_tries; @@ -38,6 +36,12 @@ struct ngx_http_lua_balancer_peer_data_s { }; +#if (NGX_HTTP_SSL) +static ngx_int_t ngx_http_lua_balancer_set_session(ngx_peer_connection_t *pc, + void *data); +static void ngx_http_lua_balancer_save_session(ngx_peer_connection_t *pc, + void *data); +#endif static ngx_int_t ngx_http_lua_balancer_init(ngx_conf_t *cf, ngx_http_upstream_srv_conf_t *us); static ngx_int_t ngx_http_lua_balancer_init_peer(ngx_http_request_t *r, @@ -232,10 +236,14 @@ ngx_http_lua_balancer_init_peer(ngx_http_request_t *r, r->upstream->peer.get = ngx_http_lua_balancer_get_peer; r->upstream->peer.free = ngx_http_lua_balancer_free_peer; +#if (NGX_HTTP_SSL) + r->upstream->peer.set_session = ngx_http_lua_balancer_set_session; + r->upstream->peer.save_session = ngx_http_lua_balancer_save_session; +#endif + bcf = ngx_http_conf_upstream_srv_conf(us, ngx_http_lua_module); bp->conf = bcf; - bp->get_rr_peer = ngx_http_upstream_get_round_robin_peer; bp->request = r; return NGX_OK; @@ -254,7 +262,7 @@ ngx_http_lua_balancer_get_peer(ngx_peer_connection_t *pc, void *data) ngx_http_lua_balancer_peer_data_t *bp = data; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, - "lua balancer peer, try: %ui", pc->tries); + "lua balancer peer, tries: %ui", pc->tries); lscf = bp->conf; @@ -315,6 +323,9 @@ ngx_http_lua_balancer_get_peer(ngx_peer_connection_t *pc, void *data) pc->sockaddr = bp->sockaddr; pc->socklen = bp->socklen; pc->name = &bp->host; + pc->cached = 0; + pc->connection = NULL; + bp->rrp.peers->single = 0; if (bp->more_tries) { @@ -326,7 +337,7 @@ ngx_http_lua_balancer_get_peer(ngx_peer_connection_t *pc, void *data) return NGX_OK; } - return bp->get_rr_peer(pc, &bp->rrp); + return ngx_http_upstream_get_round_robin_peer(pc, &bp->rrp); } @@ -388,6 +399,9 @@ ngx_http_lua_balancer_free_peer(ngx_peer_connection_t *pc, void *data, { ngx_http_lua_balancer_peer_data_t *bp = data; + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, + "lua balancer free peer, tries: %ui", pc->tries); + if (bp->sockaddr && bp->socklen) { bp->last_peer_state = (int) state; @@ -404,6 +418,39 @@ ngx_http_lua_balancer_free_peer(ngx_peer_connection_t *pc, void *data, } +#if (NGX_HTTP_SSL) + +static ngx_int_t +ngx_http_lua_balancer_set_session(ngx_peer_connection_t *pc, void *data) +{ + ngx_http_lua_balancer_peer_data_t *bp = data; + + if (bp->sockaddr && bp->socklen) { + /* TODO */ + return NGX_OK; + } + + return ngx_http_upstream_set_round_robin_peer_session(pc, &bp->rrp); +} + + +static void +ngx_http_lua_balancer_save_session(ngx_peer_connection_t *pc, void *data) +{ + ngx_http_lua_balancer_peer_data_t *bp = data; + + if (bp->sockaddr && bp->socklen) { + /* TODO */ + return; + } + + ngx_http_upstream_save_round_robin_peer_session(pc, &bp->rrp); + return; +} + +#endif + + #ifndef NGX_LUA_NO_FFI_API int @@ -493,7 +540,9 @@ int ngx_http_lua_ffi_balancer_set_more_tries(ngx_http_request_t *r, int count, char **err) { +#if (nginx_version >= 1007005) ngx_uint_t max_tries; +#endif ngx_http_lua_ctx_t *ctx; ngx_http_upstream_t *u; diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_module.c b/debian/modules/nginx-lua/src/ngx_http_lua_module.c index 4cfee82..11eb653 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_module.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_module.c @@ -888,14 +888,26 @@ ngx_http_lua_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) return NGX_CONF_ERROR; } -#if OPENSSL_VERSION_NUMBER >= 0x1000205fL +#ifdef LIBRESSL_VERSION_NUMBER - SSL_CTX_set_cert_cb(sscf->ssl.ctx, ngx_http_lua_ssl_cert_handler, NULL); + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "LibreSSL does not support ssl_ceritificate_by_lua*"); + return NGX_CONF_ERROR; #else +# if OPENSSL_VERSION_NUMBER >= 0x1000205fL + + SSL_CTX_set_cert_cb(sscf->ssl.ctx, ngx_http_lua_ssl_cert_handler, NULL); + +# else + + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "OpenSSL too old to support ssl_ceritificate_by_lua*"); return NGX_CONF_ERROR; +# endif + #endif } diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_ssl_certby.c b/debian/modules/nginx-lua/src/ngx_http_lua_ssl_certby.c index 32675b2..c4e6a83 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_ssl_certby.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_ssl_certby.c @@ -530,12 +530,19 @@ ngx_http_lua_ffi_ssl_get_tls1_version(ngx_http_request_t *r, char **err) int ngx_http_lua_ffi_ssl_clear_certs(ngx_http_request_t *r, char **err) { -#if OPENSSL_VERSION_NUMBER < 0x1000205fL +#ifdef LIBRESSL_VERSION_NUMBER + + *err = "LibreSSL not supported"; + return NGX_ERROR; + +#else + +# if OPENSSL_VERSION_NUMBER < 0x1000205fL *err = "at least OpenSSL 1.0.2e required but found " OPENSSL_VERSION_TEXT; return NGX_ERROR; -#else +# else ngx_ssl_conn_t *ssl_conn; @@ -553,7 +560,8 @@ ngx_http_lua_ffi_ssl_clear_certs(ngx_http_request_t *r, char **err) SSL_certs_clear(ssl_conn); return NGX_OK; -#endif /* OPENSSL_VERSION_NUMBER < 0x1000205fL */ +# endif /* OPENSSL_VERSION_NUMBER < 0x1000205fL */ +#endif } @@ -561,12 +569,19 @@ int ngx_http_lua_ffi_ssl_set_der_certificate(ngx_http_request_t *r, const char *data, size_t len, char **err) { -#if OPENSSL_VERSION_NUMBER < 0x1000205fL +#ifdef LIBRESSL_VERSION_NUMBER + + *err = "LibreSSL not supported"; + return NGX_ERROR; + +#else + +# if OPENSSL_VERSION_NUMBER < 0x1000205fL *err = "at least OpenSSL 1.0.2e required but found " OPENSSL_VERSION_TEXT; return NGX_ERROR; -#else +# else BIO *bio = NULL; X509 *x509 = NULL; @@ -643,7 +658,8 @@ failed: return NGX_ERROR; -#endif /* OPENSSL_VERSION_NUMBER < 0x1000205fL */ +# endif /* OPENSSL_VERSION_NUMBER < 0x1000205fL */ +#endif } diff --git a/debian/modules/nginx-lua/t/031-post-args.t b/debian/modules/nginx-lua/t/031-post-args.t index 29d6057..4f8b9d7 100644 --- a/debian/modules/nginx-lua/t/031-post-args.t +++ b/debian/modules/nginx-lua/t/031-post-args.t @@ -7,9 +7,8 @@ use Test::Nginx::Socket::Lua; #log_level('warn'); repeat_each(2); -#repeat_each(1); -plan tests => repeat_each() * (blocks() * 2 + 5); +plan tests => repeat_each() * (blocks() * 2 + 6); #no_diff(); #no_long_string(); @@ -323,3 +322,35 @@ for my $k (@k) { CORE::join("", @k); --- timeout: 4 + + +=== TEST 10: request body in temp file +--- config + location /lua { + lua_need_request_body on; + client_body_in_file_only clean; + content_by_lua_block { + local args, err = ngx.req.get_post_args() + + if not args then + ngx.say(err) + else + local keys = {} + for key, val in pairs(args) do + table.insert(keys, key) + end + + table.sort(keys) + for i, key in ipairs(keys) do + ngx.say(key, " = ", args[key]) + end + end + } + } +--- request +POST /lua +a=3&b=4&c +--- response_body +requesty body in temp file not supported +--- no_error_log +[error] diff --git a/debian/modules/nginx-lua/t/129-ssl-socket.t b/debian/modules/nginx-lua/t/129-ssl-socket.t index 446cfeb..4921099 100644 --- a/debian/modules/nginx-lua/t/129-ssl-socket.t +++ b/debian/modules/nginx-lua/t/129-ssl-socket.t @@ -846,7 +846,7 @@ lua ssl server name: "iscribblet.org" lua ssl certificate verify error SSL reused session [alert] ---- timeout: 5 +--- timeout: 7 diff --git a/debian/modules/nginx-lua/t/133-worker-count.t b/debian/modules/nginx-lua/t/133-worker-count.t index a7bae65..c97f6b4 100644 --- a/debian/modules/nginx-lua/t/133-worker-count.t +++ b/debian/modules/nginx-lua/t/133-worker-count.t @@ -30,3 +30,23 @@ GET /lua workers: 1 --- no_error_log [error] + + + +=== TEST 2: init_by_lua +--- http_config + init_by_lua_block { + package.loaded.count = ngx.worker.count() + } +--- config + location /lua { + content_by_lua_block { + ngx.say("workers: ", package.loaded.count) + } + } +--- request +GET /lua +--- response_body +workers: 1 +--- no_error_log +[error] diff --git a/debian/modules/nginx-lua/t/134-worker-count-5.t b/debian/modules/nginx-lua/t/134-worker-count-5.t index d6f16c2..b257c12 100644 --- a/debian/modules/nginx-lua/t/134-worker-count-5.t +++ b/debian/modules/nginx-lua/t/134-worker-count-5.t @@ -30,3 +30,49 @@ GET /lua worker count: 5 --- no_error_log [error] + + + +=== TEST 2: init_by_lua +--- http_config + init_by_lua_block { + package.loaded.count = ngx.worker.count() + } +--- config + location /lua { + content_by_lua_block { + ngx.say("workers: ", package.loaded.count) + } + } +--- request +GET /lua +--- response_body +workers: 5 +--- no_error_log +[error] + + + +=== TEST 3: init_by_lua + module (github #681) +--- http_config + lua_package_path "t/servroot/html/?.lua;;"; + + init_by_lua_block { + local blah = require "file" + } +--- config + location /lua { + content_by_lua_block { + ngx.say("ok") + } + } +--- user_files +>>> file.lua +local timer_interval = 1 +local time_factor = timer_interval / (ngx.worker.count() * 60) +--- request +GET /lua +--- response_body +ok +--- no_error_log +[error] diff --git a/debian/rules b/debian/rules index 4c28a8b..14d079f 100755 --- a/debian/rules +++ b/debian/rules @@ -11,7 +11,7 @@ DEBIAN_NGINX_PERL_LDFLAGS:= $(shell DEB_BUILD_MAINT_OPTIONS=hardening=+all,-pie export DEBIAN_NGINX_PERL_LDFLAGS FLAVOURS := full light extras -DYN_MODS := http-geoip http-image-filter http-xslt-filter mail stream http-auth-pam +DYN_MODS := http-geoip http-image-filter http-xslt-filter mail stream http-auth-pam http-lua MODULESDIR = $(CURDIR)/debian/modules BASEDIR = $(CURDIR) @@ -115,7 +115,7 @@ extras_configure_flags := \ --add-module=$(MODULESDIR)/nginx-echo \ --add-module=$(MODULESDIR)/ngx-fancyindex \ --add-module=$(MODULESDIR)/nginx-http-push \ - --add-module=$(MODULESDIR)/nginx-lua \ + --add-dynamic-module=$(MODULESDIR)/nginx-lua \ --add-module=$(MODULESDIR)/nginx-upload-progress \ --add-module=$(MODULESDIR)/nginx-upstream-fair \ --add-module=$(MODULESDIR)/ngx_http_substitutions_filter_module From a12faa39a5bce0dc61e596fd08d79fe2469d60f8 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Wed, 30 Mar 2016 12:46:10 +0300 Subject: [PATCH 048/600] build modules using nginx-extras --- debian/libnginx-mod-http-auth-pam.nginx | 2 +- debian/libnginx-mod-http-geoip.nginx | 2 +- debian/libnginx-mod-http-image-filter.nginx | 2 +- debian/libnginx-mod-http-lua.nginx | 2 +- debian/libnginx-mod-http-xslt-filter.nginx | 2 +- debian/libnginx-mod-mail.nginx | 2 +- debian/libnginx-mod-stream.nginx | 2 +- debian/libnginx-mod.nginx.skeleton | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/debian/libnginx-mod-http-auth-pam.nginx b/debian/libnginx-mod-http-auth-pam.nginx index 02c5edc..78c206f 100755 --- a/debian/libnginx-mod-http-auth-pam.nginx +++ b/debian/libnginx-mod-http-auth-pam.nginx @@ -9,5 +9,5 @@ $module =~ s/^libnginx-mod-//; $modulepath = $module; $modulepath =~ s/-/_/g; -print "mod debian/build-full/objs/ngx_${modulepath}_module.so\n"; +print "mod debian/build-extras/objs/ngx_${modulepath}_module.so\n"; print "mod debian/libnginx-mod.conf/mod-${module}.conf\n"; diff --git a/debian/libnginx-mod-http-geoip.nginx b/debian/libnginx-mod-http-geoip.nginx index 02c5edc..78c206f 100755 --- a/debian/libnginx-mod-http-geoip.nginx +++ b/debian/libnginx-mod-http-geoip.nginx @@ -9,5 +9,5 @@ $module =~ s/^libnginx-mod-//; $modulepath = $module; $modulepath =~ s/-/_/g; -print "mod debian/build-full/objs/ngx_${modulepath}_module.so\n"; +print "mod debian/build-extras/objs/ngx_${modulepath}_module.so\n"; print "mod debian/libnginx-mod.conf/mod-${module}.conf\n"; diff --git a/debian/libnginx-mod-http-image-filter.nginx b/debian/libnginx-mod-http-image-filter.nginx index 02c5edc..78c206f 100755 --- a/debian/libnginx-mod-http-image-filter.nginx +++ b/debian/libnginx-mod-http-image-filter.nginx @@ -9,5 +9,5 @@ $module =~ s/^libnginx-mod-//; $modulepath = $module; $modulepath =~ s/-/_/g; -print "mod debian/build-full/objs/ngx_${modulepath}_module.so\n"; +print "mod debian/build-extras/objs/ngx_${modulepath}_module.so\n"; print "mod debian/libnginx-mod.conf/mod-${module}.conf\n"; diff --git a/debian/libnginx-mod-http-lua.nginx b/debian/libnginx-mod-http-lua.nginx index 02c5edc..78c206f 100755 --- a/debian/libnginx-mod-http-lua.nginx +++ b/debian/libnginx-mod-http-lua.nginx @@ -9,5 +9,5 @@ $module =~ s/^libnginx-mod-//; $modulepath = $module; $modulepath =~ s/-/_/g; -print "mod debian/build-full/objs/ngx_${modulepath}_module.so\n"; +print "mod debian/build-extras/objs/ngx_${modulepath}_module.so\n"; print "mod debian/libnginx-mod.conf/mod-${module}.conf\n"; diff --git a/debian/libnginx-mod-http-xslt-filter.nginx b/debian/libnginx-mod-http-xslt-filter.nginx index 02c5edc..78c206f 100755 --- a/debian/libnginx-mod-http-xslt-filter.nginx +++ b/debian/libnginx-mod-http-xslt-filter.nginx @@ -9,5 +9,5 @@ $module =~ s/^libnginx-mod-//; $modulepath = $module; $modulepath =~ s/-/_/g; -print "mod debian/build-full/objs/ngx_${modulepath}_module.so\n"; +print "mod debian/build-extras/objs/ngx_${modulepath}_module.so\n"; print "mod debian/libnginx-mod.conf/mod-${module}.conf\n"; diff --git a/debian/libnginx-mod-mail.nginx b/debian/libnginx-mod-mail.nginx index 02c5edc..78c206f 100755 --- a/debian/libnginx-mod-mail.nginx +++ b/debian/libnginx-mod-mail.nginx @@ -9,5 +9,5 @@ $module =~ s/^libnginx-mod-//; $modulepath = $module; $modulepath =~ s/-/_/g; -print "mod debian/build-full/objs/ngx_${modulepath}_module.so\n"; +print "mod debian/build-extras/objs/ngx_${modulepath}_module.so\n"; print "mod debian/libnginx-mod.conf/mod-${module}.conf\n"; diff --git a/debian/libnginx-mod-stream.nginx b/debian/libnginx-mod-stream.nginx index 02c5edc..78c206f 100755 --- a/debian/libnginx-mod-stream.nginx +++ b/debian/libnginx-mod-stream.nginx @@ -9,5 +9,5 @@ $module =~ s/^libnginx-mod-//; $modulepath = $module; $modulepath =~ s/-/_/g; -print "mod debian/build-full/objs/ngx_${modulepath}_module.so\n"; +print "mod debian/build-extras/objs/ngx_${modulepath}_module.so\n"; print "mod debian/libnginx-mod.conf/mod-${module}.conf\n"; diff --git a/debian/libnginx-mod.nginx.skeleton b/debian/libnginx-mod.nginx.skeleton index 02c5edc..78c206f 100755 --- a/debian/libnginx-mod.nginx.skeleton +++ b/debian/libnginx-mod.nginx.skeleton @@ -9,5 +9,5 @@ $module =~ s/^libnginx-mod-//; $modulepath = $module; $modulepath =~ s/-/_/g; -print "mod debian/build-full/objs/ngx_${modulepath}_module.so\n"; +print "mod debian/build-extras/objs/ngx_${modulepath}_module.so\n"; print "mod debian/libnginx-mod.conf/mod-${module}.conf\n"; From 6d20e665d31c472845d8c3315b0592ef7df992ee Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Wed, 30 Mar 2016 15:07:19 +0300 Subject: [PATCH 049/600] Introduce libnginx-mod-http-perl --- debian/control | 13 ++++++++++++- debian/libnginx-mod-http-perl.install | 7 +++++++ debian/libnginx-mod-http-perl.nginx | 13 +++++++++++++ debian/libnginx-mod.conf/mod-http-perl.conf | 1 + debian/nginx-extras.install | 10 +--------- debian/rules | 4 ++-- 6 files changed, 36 insertions(+), 12 deletions(-) create mode 100755 debian/libnginx-mod-http-perl.install create mode 100755 debian/libnginx-mod-http-perl.nginx create mode 100644 debian/libnginx-mod.conf/mod-http-perl.conf mode change 100755 => 100644 debian/nginx-extras.install diff --git a/debian/control b/debian/control index 96fa475..3d0b6e9 100644 --- a/debian/control +++ b/debian/control @@ -180,8 +180,8 @@ Depends: nginx-common (= ${source:Version}), libnginx-mod-stream (= ${binary:Version}), libnginx-mod-http-auth-pam (= ${binary:Version}), libnginx-mod-http-lua (= ${binary:Version}), + libnginx-mod-http-perl (= ${binary:Version}), ${misc:Depends}, - ${perl:Depends}, ${shlibs:Depends} Breaks: nginx (<< 1.4.5-1) Provides: httpd, httpd-cgi, nginx @@ -275,6 +275,17 @@ Description: Stream module for Nginx also supports ACLs/connection limiting and configuring multiple operational parameters. +Package: libnginx-mod-http-perl +Architecture: any +Depends: ${perl:Depends}, ${misc:Depends}, ${shlibs:Depends} +Description: Perl module for Nginx + Embed Perl runtime into nginx. + . + The ngx_http_perl module is used to implement location and variable handlers + in Perl and insert Perl calls into SSI. + . + Note that this module is marked experimental. + Package: libnginx-mod-http-auth-pam Architecture: any Depends: ${misc:Depends}, ${shlibs:Depends} diff --git a/debian/libnginx-mod-http-perl.install b/debian/libnginx-mod-http-perl.install new file mode 100755 index 0000000..14ca692 --- /dev/null +++ b/debian/libnginx-mod-http-perl.install @@ -0,0 +1,7 @@ +#!/usr/bin/perl -w + +use Config; + +my $vendorarch = substr($Config{vendorarch}, 1); +print "debian/build-extras/objs/src/http/modules/perl/blib/arch/auto/nginx/* $vendorarch/auto/nginx\n"; +print "debian/build-extras/objs/src/http/modules/perl/blib/lib/nginx.pm $vendorarch\n"; diff --git a/debian/libnginx-mod-http-perl.nginx b/debian/libnginx-mod-http-perl.nginx new file mode 100755 index 0000000..78c206f --- /dev/null +++ b/debian/libnginx-mod-http-perl.nginx @@ -0,0 +1,13 @@ +#!/usr/bin/perl -w + +use File::Basename; + +# Guess module name +$module = basename($0, '.nginx'); +$module =~ s/^libnginx-mod-//; + +$modulepath = $module; +$modulepath =~ s/-/_/g; + +print "mod debian/build-extras/objs/ngx_${modulepath}_module.so\n"; +print "mod debian/libnginx-mod.conf/mod-${module}.conf\n"; diff --git a/debian/libnginx-mod.conf/mod-http-perl.conf b/debian/libnginx-mod.conf/mod-http-perl.conf new file mode 100644 index 0000000..ab3d02a --- /dev/null +++ b/debian/libnginx-mod.conf/mod-http-perl.conf @@ -0,0 +1 @@ +load_module modules/ngx_http_perl_module.so; diff --git a/debian/nginx-extras.install b/debian/nginx-extras.install old mode 100755 new mode 100644 index dbcf498..833c24b --- a/debian/nginx-extras.install +++ b/debian/nginx-extras.install @@ -1,9 +1 @@ -#!/usr/bin/perl -w - -use Config; - -my $vendorarch = substr($Config{vendorarch}, 1); -print "debian/build-extras/objs/src/http/modules/perl/blib/arch/auto/nginx/* $vendorarch/auto/nginx\n"; -print "debian/build-extras/objs/src/http/modules/perl/blib/lib/nginx.pm $vendorarch\n"; - -print "debian/build-extras/objs/nginx usr/sbin\n"; +debian/build-extras/objs/nginx usr/sbin diff --git a/debian/rules b/debian/rules index 14d079f..9f6aeaf 100755 --- a/debian/rules +++ b/debian/rules @@ -11,7 +11,7 @@ DEBIAN_NGINX_PERL_LDFLAGS:= $(shell DEB_BUILD_MAINT_OPTIONS=hardening=+all,-pie export DEBIAN_NGINX_PERL_LDFLAGS FLAVOURS := full light extras -DYN_MODS := http-geoip http-image-filter http-xslt-filter mail stream http-auth-pam http-lua +DYN_MODS := http-geoip http-image-filter http-xslt-filter mail stream http-auth-pam http-lua http-perl MODULESDIR = $(CURDIR)/debian/modules BASEDIR = $(CURDIR) @@ -98,7 +98,7 @@ extras_configure_flags := \ --with-http_gzip_static_module \ --with-http_image_filter_module=dynamic \ --with-http_mp4_module \ - --with-http_perl_module \ + --with-http_perl_module=dynamic \ --with-http_random_index_module \ --with-http_secure_link_module \ --with-http_sub_module \ From d5ba950907a7115d16a0e4cd84f6654580fdd57d Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Wed, 30 Mar 2016 15:30:59 +0300 Subject: [PATCH 050/600] Perl module ifdefs for SSI so it cannot be loaded across builds. nginx-light is the only flavor that doesn't include SSI so we are including it there. Also, we switch the nginx-light module test to use libnginx-mod-http-perl, that way it's more likely to fail. --- debian/control | 4 ++-- debian/rules | 1 - debian/tests/control | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/debian/control b/debian/control index 3d0b6e9..d83c6cb 100644 --- a/debian/control +++ b/debian/control @@ -149,8 +149,8 @@ Description: nginx web/proxy server (basic version) FastCGI, Map, Proxy, Rewrite. . OPTIONAL HTTP MODULES: Auth Request, Charset, Gzip, Gzip Precompression, - Headers, HTTP/2, Index, Log, Real IP, SSL, Stub Status, Thread Pool, WebDAV, - Upstream. + Headers, HTTP/2, Index, Log, Real IP, SSI, SSL, Stub Status, Thread Pool, + WebDAV, Upstream. . THIRD PARTY MODULES: Echo. diff --git a/debian/rules b/debian/rules index 9f6aeaf..8805781 100755 --- a/debian/rules +++ b/debian/rules @@ -65,7 +65,6 @@ light_configure_flags := \ --without-http_referer_module \ --without-http_scgi_module \ --without-http_split_clients_module \ - --without-http_ssi_module \ --without-http_userid_module \ --without-http_uwsgi_module \ --add-module=$(MODULESDIR)/nginx-echo diff --git a/debian/tests/control b/debian/tests/control index 881cc56..735ce14 100644 --- a/debian/tests/control +++ b/debian/tests/control @@ -12,4 +12,4 @@ Depends: nginx-extras, curl Test-Command: curl --silent --fail -o /dev/null -w "response_code: %{http_code}\n" http://127.0.0.1/ Restrictions: allow-stderr isolation-container -Depends: nginx-light, libnginx-mod-stream, curl +Depends: nginx-light, libnginx-mod-http-perl, curl From 166eb741134455e18eaa40f09c1a1d3739f6cc67 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Thu, 31 Mar 2016 13:57:49 +0300 Subject: [PATCH 051/600] We accidentally closed a wishlist bug with the nginx-light enhancements --- debian/changelog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index 24f9b02..a6d6712 100644 --- a/debian/changelog +++ b/debian/changelog @@ -10,7 +10,7 @@ nginx (1.9.13-1) UNRELEASED; urgency=medium * debian/control: + Enable http/2, thread pool & WebDAV on nginx-light. In order for dynamic modules to be loadable in all nginx flavors we need - to ensure the share the same build signature. + to ensure the share the same build signature. (Closes: #816095) + Use secure VCS uri (lintian). + Bump Standards to 3.9.7. * debian/rules: From 832524e25ef79005b55886bc8595e770771846ba Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Thu, 31 Mar 2016 13:57:54 +0300 Subject: [PATCH 052/600] Mark nginx-common & nginx-doc as 'Multi-Arch: foreign' (Closes: #812484) --- debian/changelog | 2 ++ debian/control | 2 ++ 2 files changed, 4 insertions(+) diff --git a/debian/changelog b/debian/changelog index a6d6712..7e366f3 100644 --- a/debian/changelog +++ b/debian/changelog @@ -11,6 +11,8 @@ nginx (1.9.13-1) UNRELEASED; urgency=medium + Enable http/2, thread pool & WebDAV on nginx-light. In order for dynamic modules to be loadable in all nginx flavors we need to ensure the share the same build signature. (Closes: #816095) + + nginx-common & nginx-doc are now 'Multi-Arch: foreign'. (Closes: #812484) + Thanks Elrond for the report and the initial patch. + Use secure VCS uri (lintian). + Bump Standards to 3.9.7. * debian/rules: diff --git a/debian/control b/debian/control index d83c6cb..7c0a636 100644 --- a/debian/control +++ b/debian/control @@ -48,6 +48,7 @@ Description: small, powerful, scalable web/proxy server Package: nginx-doc Architecture: all +Multi-Arch: foreign Section: doc Depends: lsb-base (>= 3.2-14), ${misc:Depends} Description: small, powerful, scalable web/proxy server - documentation @@ -59,6 +60,7 @@ Description: small, powerful, scalable web/proxy server - documentation Package: nginx-common Architecture: all +Multi-Arch: foreign Depends: lsb-base (>= 3.2-14), ${misc:Depends} Replaces: nginx (<< 0.8.54-4), nginx-extras (<< 0.8.54-4), From f6a3b87f152ac63963e729d984677dbcdd4296a4 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Thu, 7 Apr 2016 09:06:12 +0300 Subject: [PATCH 053/600] Test all modules in all flavors --- debian/tests/control | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/debian/tests/control b/debian/tests/control index 735ce14..b4f6582 100644 --- a/debian/tests/control +++ b/debian/tests/control @@ -12,4 +12,12 @@ Depends: nginx-extras, curl Test-Command: curl --silent --fail -o /dev/null -w "response_code: %{http_code}\n" http://127.0.0.1/ Restrictions: allow-stderr isolation-container -Depends: nginx-light, libnginx-mod-http-perl, curl +Depends: nginx-extras, curl, libnginx-mod-http-auth-pam, libnginx-mod-http-geoip, libnginx-mod-http-image-filter, libnginx-mod-http-lua, libnginx-mod-http-perl, libnginx-mod-http-xslt-filter, libnginx-mod-mail, libnginx-mod-stream + +Test-Command: curl --silent --fail -o /dev/null -w "response_code: %{http_code}\n" http://127.0.0.1/ +Restrictions: allow-stderr isolation-container +Depends: nginx-full, curl, libnginx-mod-http-auth-pam, libnginx-mod-http-geoip, libnginx-mod-http-image-filter, libnginx-mod-http-lua, libnginx-mod-http-perl, libnginx-mod-http-xslt-filter, libnginx-mod-mail, libnginx-mod-stream + +Test-Command: curl --silent --fail -o /dev/null -w "response_code: %{http_code}\n" http://127.0.0.1/ +Restrictions: allow-stderr isolation-container +Depends: nginx-light, curl, libnginx-mod-http-auth-pam, libnginx-mod-http-geoip, libnginx-mod-http-image-filter, libnginx-mod-http-lua, libnginx-mod-http-perl, libnginx-mod-http-xslt-filter, libnginx-mod-mail, libnginx-mod-stream From ddb802850295fc87b9e49d8a0fa0d7f30895f42c Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Thu, 7 Apr 2016 09:31:25 +0300 Subject: [PATCH 054/600] Convert tests to scripts --- debian/tests/control | 18 +++++++++--------- debian/tests/extras-module-deps | 3 +++ debian/tests/extras-simple | 3 +++ debian/tests/full-module-deps | 3 +++ debian/tests/full-simple | 3 +++ debian/tests/light-module-deps | 3 +++ debian/tests/light-simple | 3 +++ 7 files changed, 27 insertions(+), 9 deletions(-) create mode 100644 debian/tests/extras-module-deps create mode 100644 debian/tests/extras-simple create mode 100644 debian/tests/full-module-deps create mode 100644 debian/tests/full-simple create mode 100644 debian/tests/light-module-deps create mode 100644 debian/tests/light-simple diff --git a/debian/tests/control b/debian/tests/control index b4f6582..a222b7f 100644 --- a/debian/tests/control +++ b/debian/tests/control @@ -1,23 +1,23 @@ -Test-Command: curl --silent --fail -o /dev/null -w "response_code: %{http_code}\n" http://127.0.0.1/ +Tests: light-simple Restrictions: allow-stderr isolation-container Depends: nginx-light, curl -Test-Command: curl --silent --fail -o /dev/null -w "response_code: %{http_code}\n" http://127.0.0.1/ +Tests: full-simple Restrictions: allow-stderr isolation-container Depends: nginx-full, curl -Test-Command: curl --silent --fail -o /dev/null -w "response_code: %{http_code}\n" http://127.0.0.1/ +Tests: extras-simple Restrictions: allow-stderr isolation-container Depends: nginx-extras, curl -Test-Command: curl --silent --fail -o /dev/null -w "response_code: %{http_code}\n" http://127.0.0.1/ -Restrictions: allow-stderr isolation-container -Depends: nginx-extras, curl, libnginx-mod-http-auth-pam, libnginx-mod-http-geoip, libnginx-mod-http-image-filter, libnginx-mod-http-lua, libnginx-mod-http-perl, libnginx-mod-http-xslt-filter, libnginx-mod-mail, libnginx-mod-stream - -Test-Command: curl --silent --fail -o /dev/null -w "response_code: %{http_code}\n" http://127.0.0.1/ +Tests: full-module-deps Restrictions: allow-stderr isolation-container Depends: nginx-full, curl, libnginx-mod-http-auth-pam, libnginx-mod-http-geoip, libnginx-mod-http-image-filter, libnginx-mod-http-lua, libnginx-mod-http-perl, libnginx-mod-http-xslt-filter, libnginx-mod-mail, libnginx-mod-stream -Test-Command: curl --silent --fail -o /dev/null -w "response_code: %{http_code}\n" http://127.0.0.1/ +Tests: light-module-deps Restrictions: allow-stderr isolation-container Depends: nginx-light, curl, libnginx-mod-http-auth-pam, libnginx-mod-http-geoip, libnginx-mod-http-image-filter, libnginx-mod-http-lua, libnginx-mod-http-perl, libnginx-mod-http-xslt-filter, libnginx-mod-mail, libnginx-mod-stream + +Tests: extras-module-deps +Restrictions: allow-stderr isolation-container +Depends: nginx-extras, curl, libnginx-mod-http-auth-pam, libnginx-mod-http-geoip, libnginx-mod-http-image-filter, libnginx-mod-http-lua, libnginx-mod-http-perl, libnginx-mod-http-xslt-filter, libnginx-mod-mail, libnginx-mod-stream diff --git a/debian/tests/extras-module-deps b/debian/tests/extras-module-deps new file mode 100644 index 0000000..cefed50 --- /dev/null +++ b/debian/tests/extras-module-deps @@ -0,0 +1,3 @@ +#!/bin/bash + +curl --silent --fail -o /dev/null -w "response_code: %{http_code}\n" http://127.0.0.1/ diff --git a/debian/tests/extras-simple b/debian/tests/extras-simple new file mode 100644 index 0000000..cefed50 --- /dev/null +++ b/debian/tests/extras-simple @@ -0,0 +1,3 @@ +#!/bin/bash + +curl --silent --fail -o /dev/null -w "response_code: %{http_code}\n" http://127.0.0.1/ diff --git a/debian/tests/full-module-deps b/debian/tests/full-module-deps new file mode 100644 index 0000000..cefed50 --- /dev/null +++ b/debian/tests/full-module-deps @@ -0,0 +1,3 @@ +#!/bin/bash + +curl --silent --fail -o /dev/null -w "response_code: %{http_code}\n" http://127.0.0.1/ diff --git a/debian/tests/full-simple b/debian/tests/full-simple new file mode 100644 index 0000000..cefed50 --- /dev/null +++ b/debian/tests/full-simple @@ -0,0 +1,3 @@ +#!/bin/bash + +curl --silent --fail -o /dev/null -w "response_code: %{http_code}\n" http://127.0.0.1/ diff --git a/debian/tests/light-module-deps b/debian/tests/light-module-deps new file mode 100644 index 0000000..cefed50 --- /dev/null +++ b/debian/tests/light-module-deps @@ -0,0 +1,3 @@ +#!/bin/bash + +curl --silent --fail -o /dev/null -w "response_code: %{http_code}\n" http://127.0.0.1/ diff --git a/debian/tests/light-simple b/debian/tests/light-simple new file mode 100644 index 0000000..cefed50 --- /dev/null +++ b/debian/tests/light-simple @@ -0,0 +1,3 @@ +#!/bin/bash + +curl --silent --fail -o /dev/null -w "response_code: %{http_code}\n" http://127.0.0.1/ From 9551b6324b11f2147cea249184254bbbb387c4f1 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Thu, 7 Apr 2016 10:02:52 +0300 Subject: [PATCH 055/600] Update nginx-auth-pam module to 1.5.1 Fixes linking issue with the dynamic module. --- debian/modules/README.Modules-versions | 2 +- debian/modules/nginx-auth-pam/ChangeLog | 6 ++++++ debian/modules/nginx-auth-pam/config | 4 ++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/debian/modules/README.Modules-versions b/debian/modules/README.Modules-versions index 53cbc2c..f6bec49 100644 --- a/debian/modules/README.Modules-versions +++ b/debian/modules/README.Modules-versions @@ -14,7 +14,7 @@ README for Modules versions nginx-auth-pam Homepage: https://github.com/stogh/ngx_http_auth_pam_module - Version: 1.5 + Version: 1.5.1 nginx-echo Homepage: https://github.com/agentzh/echo-nginx-module diff --git a/debian/modules/nginx-auth-pam/ChangeLog b/debian/modules/nginx-auth-pam/ChangeLog index 8aaf031..d45eae4 100644 --- a/debian/modules/nginx-auth-pam/ChangeLog +++ b/debian/modules/nginx-auth-pam/ChangeLog @@ -1,3 +1,9 @@ +2016-04-06 sto@iti.es + + * Version 1.5.1. + * Fix building alongside other modules in nginx 1.9.11+ (patch provided by + Graham Edgecombe ) + 2016-03-23 sto@iti.es * Version 1.5. diff --git a/debian/modules/nginx-auth-pam/config b/debian/modules/nginx-auth-pam/config index 9c30919..2275262 100644 --- a/debian/modules/nginx-auth-pam/config +++ b/debian/modules/nginx-auth-pam/config @@ -5,8 +5,8 @@ if test -n "$ngx_module_link"; then ngx_module_name=ngx_http_auth_pam_module ngx_module_incs= ngx_module_deps= - ngx_module_srcs="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_auth_pam_module.c" - ngx_module_libs="$CORE_LIBS -lpam" + ngx_module_srcs="$ngx_addon_dir/ngx_http_auth_pam_module.c" + ngx_module_libs="-lpam" . auto/module else From 30eb818ca4b5f6cec04d6a455900ec99713f3c07 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Thu, 7 Apr 2016 10:23:21 +0300 Subject: [PATCH 056/600] Update nginx-development-kit module to 0.3.0rc1 (dynamic module) --- debian/modules/README.Modules-versions | 2 +- debian/modules/nginx-development-kit/LICENSE | 13 + debian/modules/nginx-development-kit/README | 139 ---------- .../modules/nginx-development-kit/README.md | 238 ++++++++++++++++++ debian/modules/nginx-development-kit/config | 26 +- 5 files changed, 273 insertions(+), 145 deletions(-) create mode 100644 debian/modules/nginx-development-kit/LICENSE delete mode 100644 debian/modules/nginx-development-kit/README create mode 100644 debian/modules/nginx-development-kit/README.md diff --git a/debian/modules/README.Modules-versions b/debian/modules/README.Modules-versions index f6bec49..d7f35a4 100644 --- a/debian/modules/README.Modules-versions +++ b/debian/modules/README.Modules-versions @@ -10,7 +10,7 @@ README for Modules versions nginx-development-kit Homepage: https://github.com/simpl/ngx_devel_kit/ - Version: v0.2.19 + Version: v0.3.0rc1 nginx-auth-pam Homepage: https://github.com/stogh/ngx_http_auth_pam_module diff --git a/debian/modules/nginx-development-kit/LICENSE b/debian/modules/nginx-development-kit/LICENSE new file mode 100644 index 0000000..ee54448 --- /dev/null +++ b/debian/modules/nginx-development-kit/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2010-2015, Marcus Clyne + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 THE COPYRIGHT HOLDER 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) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/debian/modules/nginx-development-kit/README b/debian/modules/nginx-development-kit/README deleted file mode 100644 index 50a2d95..0000000 --- a/debian/modules/nginx-development-kit/README +++ /dev/null @@ -1,139 +0,0 @@ - Nginx Development Kit (NDK) - =========================== - -Synopsis - - The NDK is an Nginx module that is designed to extend the core functionality of the - excellent Nginx webserver in a way that can be used as a basis of other Nginx modules. - - It has functions and macros to deal with generic tasks that don't currently have - generic code as part of the core distribution. The NDK itself adds few features - that are seen from a user's point of view - it's just designed to help reduce the - code that Nginx module developers need to write. - - Nginx module developers wishing to use any of the features in the NDK should specify - that the NDK is a dependency of their module, and that users will need to compile - it as well when they compile their own modules. They will also need to declare in - their own modules which features of the NDK they wish to use (explained below). - - If you are not an Nginx module developer, then the only useful part of this project - will be the 'usage for users' section below. - - -Status - - The NDK is now considered to be stable. It is already being used in quite a few third - party modules. - - -Features - - - additional conf_set functions for regexes, complex/script values, paths... - - macros to simplify tasks like checking for NULL values when doing ngx_array_push - - patches to the main source code - - ngx_auto_lib_core generic external library handler is included (see separate readme) - - - -Design - - modular : - - The kit itself is designed in a modular way, so that only the required code is compiled. - It's possible to add just a single NDK module, a few or all of them. - - auto-generated & easily extensible : - - Many of the macros available in the NDK are auto-generated from simple configuration - files. This makes creating similar macros for your own code very simple - it's usually - just the case of adding an extra line to a config file and re-running the build script. - - -Usage for users - - If another Nginx module you wish to use specifies that the NDK is a dependency, you - will need to do the following : - - 1 - download the source (http://github.com/simpl/ngx_devel_kit) - - 2 - unpack the source (tar -xzf $name) - - 3 - compile Nginx with the following extra option - - --add-module=/path/to/src - - e.g. - - ./configure --add-module=/path/to/ndk/base --add-module=/path/to/another/mod - - -Usage for developers - - To use the NDK in your own module, you need to add the following : - - 1 - add this line to your module - - #include - - note : since the NDK includes the following lines - - #include - #include - #include - - you can replace these with the single include above. - - 2 - add the following line in the config file for your module : - - have=NDK_[module_name] . auto/have - - for each NDK module that you wish to use (you need to include auto/have multiple - times if you wish to use multiple NDK modules. - - - Note : the old method of setting - - CFLAGS="$CFLAGS -DNDK_[module_name]" - - is now deprecated. It will still work, but results in unnecessary lines being - displayed when compiling Nginx. - - - Warning : using NDK_ALL - - You can also set NDK_ALL to include all the NDK modules. This is primarily as - a convenience in the early stages of development of another module. However, - - DO NOT LEAVE 'NDK_ALL' IN YOUR CONFIG FILE WHEN PUBLISHING - - Although the NDK is fairly small now, it could in time become a large repository - of code that would, if using NDK_ALL, result in considerably more code being compiled - than is necessary. - - -Todo - - - documentation for modules that don't already have it - - additional phase-handler functions - - generically testing for needing to add a handler - - remove dependency of set_var on OpenSSL being compiled in - - -License - - BSD - - -Contributing / Feedback - - If you are an Nginx module developer, and have developed some functions that are - generic in nature (or would be easily adapted to be so), then please send them to - me at the address below, and I'll add them to the kit. - - -Author - - Marcus Clyne (contact at simpl dot it) - - - diff --git a/debian/modules/nginx-development-kit/README.md b/debian/modules/nginx-development-kit/README.md new file mode 100644 index 0000000..e0ed4eb --- /dev/null +++ b/debian/modules/nginx-development-kit/README.md @@ -0,0 +1,238 @@ +Name +==== + +NDK - Nginx Development Kit + +Table of Contents +================= + +* [Name](#name) +* [Synopsis](#synopsis) +* [Status](#status) +* [Features](#features) +* [Design](#design) + * [modular](#modular) + * [auto-generated & easily extensible](#auto-generated--easily-extensible) +* [Usage for users](#usage-for-users) + * [Building as a dynamic module](#building-as-a-dynamic-module) +* [Usage for developers](#usage-for-developers) + * [Warning: using NDK_ALL](#warning-using-ndk_all) +* [Modules using NDK](#modules-using-ndk) +* [TODO](#todo) +* [License](#license) +* [Contributing / Feedback](#contributing--feedback) +* [Author](#author) + +Synopsis +======== + +The NDK is an Nginx module that is designed to extend the core functionality of the +excellent Nginx webserver in a way that can be used as a basis of other Nginx modules. + +It has functions and macros to deal with generic tasks that don't currently have +generic code as part of the core distribution. The NDK itself adds few features +that are seen from a user's point of view - it's just designed to help reduce the +code that Nginx module developers need to write. + +Nginx module developers wishing to use any of the features in the NDK should specify +that the NDK is a dependency of their module, and that users will need to compile +it as well when they compile their own modules. They will also need to declare in +their own modules which features of the NDK they wish to use (explained below). + +If you are not an Nginx module developer, then the only useful part of this project +will be the 'usage for users' section below. + +Status +====== + +The NDK is now considered to be stable. It is already being used in quite a few third +party modules. + +Features +======== + +* additional conf_set functions for regexes, complex/script values, paths... +* macros to simplify tasks like checking for NULL values when doing ngx_array_push +* patches to the main source code +* ngx_auto_lib_core generic external library handler is included (see separate readme) + +[Back to TOC](#table-of-contents) + +Design +====== + +modular +------- + +The kit itself is designed in a modular way, so that only the required code is compiled. +It's possible to add just a single NDK module, a few or all of them. + +[Back to TOC](#table-of-contents) + +auto-generated & easily extensible +---------------------------------- + +Many of the macros available in the NDK are auto-generated from simple configuration +files. This makes creating similar macros for your own code very simple - it's usually +just the case of adding an extra line to a config file and re-running the build script. + +[Back to TOC](#table-of-contents) + +Usage for users +=============== + +If another Nginx module you wish to use specifies that the NDK is a dependency, you +will need to do the following : + +1. download the source (https://github.com/simpl/ngx_devel_kit) +2. unpack the source (tar -xzf $name) +3. compile Nginx with the following extra option `--add-module=/path/to/ngx_devel_kit`. + +e.g. + +```bash +./configure --add-module=/path/to/ngx_devel_kit \ + --add-module=/path/to/another/module +``` + +[Back to TOC](#table-of-contents) + +Building as a dynamic module +---------------------------- + +Starting from NGINX 1.9.11, you can also compile this module as a dynamic module, by using the `--add-dynamic-module=PATH` option instead of `--add-module=PATH` on the +`./configure` command line above. And then you can explicitly load the module in your `nginx.conf` via the [load_module](http://nginx.org/en/docs/ngx_core_module.html#load_module) +directive, for example, + +```nginx +load_module /path/to/modules/ndk_http_module.so; +load_module /path/to/another/module.so; +``` + +[Back to TOC](#table-of-contents) + +Usage for developers +==================== + +To use the NDK in your own module, you need to add the following: + +1. add this line to your module + +```C +#include +``` + +Note: since the NDK includes the following lines + +```C +#include +#include +#include +``` + +you can replace these with the single include above. +2. add the following line in the config file for your module: + +```bash +have=NDK_[module_name] . auto/have +``` + +for each NDK module that you wish to use (you need to include auto/have multiple +times if you wish to use multiple NDK modules. + +Note: the old method of setting + +```config +CFLAGS="$CFLAGS -DNDK_[module_name]" +``` + +is now deprecated. It will still work, but results in unnecessary lines being +displayed when compiling Nginx. + +[Back to TOC](#table-of-contents) + +Warning: using NDK_ALL +---------------------- + +You can also set `NDK_ALL` to include all the NDK modules. This is primarily as +a convenience in the early stages of development of another module. However, + +DO NOT LEAVE `NDK_ALL` IN YOUR CONFIG FILE WHEN PUBLISHING + +Although the NDK is fairly small now, it could in time become a large repository +of code that would, if using NDK_ALL, result in considerably more code being compiled +than is necessary. + +[Back to TOC](#table-of-contents) + +Modules using NDK +================= + +The following 3rd-party modules make use of NDK. + +* [ngx_http_lua_module](https://github.com/openresty/lua-nginx-module#readme) +* [ngx_http_set_misc_module](https://github.com/openresty/set-misc-nginx-module#readme) +* [ngx_http_encrypted_session_module](https://github.com/openresty/encrypted-session-nginx-module#readme) +* [ngx_http_form_input_module](https://github.com/calio/form-input-nginx-module#readme) +* [ngx_http_iconv_module](https://github.com/calio/iconv-nginx-module#readme) +* [ngx_http_array_var_module](https://github.com/openresty/array-var-nginx-module#readme) + +[Back to TOC](#table-of-contents) + +TODO +==== + +* documentation for modules that don't already have it +* additional phase-handler functions +* generically testing for needing to add a handler +* remove dependency of set_var on OpenSSL being compiled in + +[Back to TOC](#table-of-contents) + +License +======= + +Copyright (c) 2010-2016, Marcus Clyne + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are +permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of +conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, this list of +conditions and the following disclaimer in the documentation and/or other materials +provided with the distribution. +3. Neither the name of the copyright holder nor the names of its contributors may be used +to endorse or promote products derived from this software without specific prior +written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 THE +COPYRIGHT HOLDER 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) HOWEVER CAUSED +AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +[Back to TOC](#table-of-contents) + +Contributing / Feedback +======================= + +If you are an Nginx module developer, and have developed some functions that are +generic in nature (or would be easily adapted to be so), then please send them to +me at the address below, and I'll add them to the kit. + +[Back to TOC](#table-of-contents) + +Author +====== + +Marcus Clyne (contact at simpl dot it) + +[Back to TOC](#table-of-contents) + diff --git a/debian/modules/nginx-development-kit/config b/debian/modules/nginx-development-kit/config index 65563d7..8cb7ad0 100644 --- a/debian/modules/nginx-development-kit/config +++ b/debian/modules/nginx-development-kit/config @@ -18,8 +18,8 @@ ndk_get_nginx_version() { # We get the Nginx version number from the string form rather than # nginx_version because it is available in more (every?) version - cat src/core/nginx.h | - grep '#define NGINX_VERSION' | + cat src/core/nginx.h | + grep '#define NGINX_VERSION' | sed -r \ -e 's/[^0-9.]*([0-9.]+).*/\1/' \ -e 's/([0-9]+\.[0-9]+\.)([0-9]{1})$/\100\2/' \ @@ -35,10 +35,26 @@ ndk_get_nginx_version() { ngx_addon_name=ngx_devel_kit ngx_objs_dirs="$ngx_addon_dir/objs $NGX_OBJS/addon/ndk" +NDK_SRCS="$ngx_addon_dir/src/ndk.c" +NDK_DEPS="$ngx_addon_dir/src/ndk.h" +NDK_INCS="$ngx_addon_dir/src $ngx_objs_dirs" + CORE_INCS="$CORE_INCS $ngx_objs_dirs" HTTP_INCS="$HTTP_INCS $ngx_addon_dir/src $ngx_objs_dir" -HTTP_MODULES="$HTTP_MODULES ndk_http_module" -NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/src/ndk.c" + +if test -n "$ngx_module_link"; then + ngx_module_type=HTTP + ngx_module_name="ndk_http_module" + ngx_module_srcs="$NDK_SRCS" + ngx_module_deps="$NDK_DEPS" + ngx_module_incs="$NDK_INCS" + + . auto/module +else + HTTP_MODULES="$HTTP_MODULES ndk_http_module" + NGX_ADDON_SRCS="$NGX_ADDON_SRCS $NDK_SRCS" + NGX_ADDON_DEPS="$NGX_ADDON_SRCS $NDK_DEPS" +fi have=NDK . auto/have @@ -46,4 +62,4 @@ have=NDK . auto/have ## INCLUDES ## ############## -. $ngx_addon_dir/ngx_auto_lib_core \ No newline at end of file +. $ngx_addon_dir/ngx_auto_lib_core From 481751859a332c2881d4df19d4e761be5386f64a Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Thu, 7 Apr 2016 10:51:41 +0300 Subject: [PATCH 057/600] Introduce libnginx-mod-http-ndk module --- debian/control | 16 +++++++++++++++- debian/libnginx-mod-http-ndk.nginx | 2 ++ debian/libnginx-mod.conf/mod-http-ndk.conf | 1 + debian/rules | 4 ++-- 4 files changed, 20 insertions(+), 3 deletions(-) create mode 100644 debian/libnginx-mod-http-ndk.nginx create mode 100644 debian/libnginx-mod.conf/mod-http-ndk.conf diff --git a/debian/control b/debian/control index 7c0a636..2398e29 100644 --- a/debian/control +++ b/debian/control @@ -299,7 +299,7 @@ Description: PAM authentication module for Nginx Package: libnginx-mod-http-lua Architecture: any -Depends: ${misc:Depends}, ${shlibs:Depends} +Depends: libnginx-mod-http-ndk (= ${binary:Version}), ${misc:Depends}, ${shlibs:Depends} Description: LUA module for Nginx Embed LUA runtime into nginx. . @@ -307,3 +307,17 @@ Description: LUA module for Nginx 2.0/2.1, into Nginx and by leveraging Nginx's subrequests, allows the integration of the powerful Lua threads (Lua coroutines) into the Nginx event model. + +Package: libnginx-mod-http-ndk +Architecture: any +Depends: ${misc:Depends}, ${shlibs:Depends} +Description: Nginx Development Kit module + The NDK is an Nginx module that is designed to extend the core functionality of + the excellent Nginx webserver in a way that can be used as a basis of other + Nginx modules. + . + It has functions and macros to deal with generic tasks that don't currently + have generic code as part of the core distribution. The NDK itself adds few + features that are seen from a user's point of view - it's just designed to help + reduce the code that Nginx module developers need to write. Embed LUA runtime + into nginx. diff --git a/debian/libnginx-mod-http-ndk.nginx b/debian/libnginx-mod-http-ndk.nginx new file mode 100644 index 0000000..1905145 --- /dev/null +++ b/debian/libnginx-mod-http-ndk.nginx @@ -0,0 +1,2 @@ +mod debian/build-extras/objs/ndk_http_module.so +mod debian/libnginx-mod.conf/mod-http-ndk.conf diff --git a/debian/libnginx-mod.conf/mod-http-ndk.conf b/debian/libnginx-mod.conf/mod-http-ndk.conf new file mode 100644 index 0000000..3908af6 --- /dev/null +++ b/debian/libnginx-mod.conf/mod-http-ndk.conf @@ -0,0 +1 @@ +load_module modules/ndk_http_module.so; diff --git a/debian/rules b/debian/rules index 8805781..63abd77 100755 --- a/debian/rules +++ b/debian/rules @@ -11,7 +11,7 @@ DEBIAN_NGINX_PERL_LDFLAGS:= $(shell DEB_BUILD_MAINT_OPTIONS=hardening=+all,-pie export DEBIAN_NGINX_PERL_LDFLAGS FLAVOURS := full light extras -DYN_MODS := http-geoip http-image-filter http-xslt-filter mail stream http-auth-pam http-lua http-perl +DYN_MODS := http-geoip http-image-filter http-xslt-filter mail stream http-auth-pam http-lua http-perl http-ndk MODULESDIR = $(CURDIR)/debian/modules BASEDIR = $(CURDIR) @@ -110,7 +110,7 @@ extras_configure_flags := \ --add-dynamic-module=$(MODULESDIR)/nginx-auth-pam \ --add-module=$(MODULESDIR)/nginx-cache-purge \ --add-module=$(MODULESDIR)/nginx-dav-ext-module \ - --add-module=$(MODULESDIR)/nginx-development-kit \ + --add-dynamic-module=$(MODULESDIR)/nginx-development-kit \ --add-module=$(MODULESDIR)/nginx-echo \ --add-module=$(MODULESDIR)/ngx-fancyindex \ --add-module=$(MODULESDIR)/nginx-http-push \ From 57e63bc6d8f61ca4c8ddeb23957b6f8de01fb46c Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Mon, 18 Apr 2016 11:47:04 +0300 Subject: [PATCH 058/600] dh_nginx: Support setting module priorities in .nginx files --- debian/autoscripts/postinst-nginx | 9 ++++++--- debian/autoscripts/postrm-nginx | 9 ++++++--- debian/autoscripts/prerm-nginx | 9 ++++++--- debian/dh_nginx | 9 ++++++--- 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/debian/autoscripts/postinst-nginx b/debian/autoscripts/postinst-nginx index 565015b..b2efc7b 100644 --- a/debian/autoscripts/postinst-nginx +++ b/debian/autoscripts/postinst-nginx @@ -1,8 +1,11 @@ -for conf in #NAMES# ; do +for confpair in #NAMES# ; do + from=$(echo $confpair | cut -d: -f1) + to=$(echo $confpair | cut -d: -f2) + # Symlink on fresh installations if [ -z "$2" ]; then - ln -sf /usr/share/nginx/modules-available/$conf \ - /etc/nginx/modules-enabled/$conf + ln -sf /usr/share/nginx/modules-available/$from \ + /etc/nginx/modules-enabled/$to fi done diff --git a/debian/autoscripts/postrm-nginx b/debian/autoscripts/postrm-nginx index 60b0493..bb16a45 100644 --- a/debian/autoscripts/postrm-nginx +++ b/debian/autoscripts/postrm-nginx @@ -1,7 +1,10 @@ if [ "$1" = "purge" ] ; then - for conf in #NAMES# ; do - if [ -e /etc/nginx/etc/nginx/modules-enabled/$conf ]; then - rm /etc/nginx/etc/nginx/modules-enabled/$conf + for confpair in #NAMES# ; do + from=$(echo $confpair | cut -d: -f1) + to=$(echo $confpair | cut -d: -f2) + + if [ -e /etc/nginx/modules-enabled/$to ]; then + rm /etc/nginx/modules-enabled/$to fi done diff --git a/debian/autoscripts/prerm-nginx b/debian/autoscripts/prerm-nginx index efeaae8..8bc2d25 100644 --- a/debian/autoscripts/prerm-nginx +++ b/debian/autoscripts/prerm-nginx @@ -1,7 +1,10 @@ if [ "$1" = "remove" ] || [ "$1" = "deconfigure" ] ; then - for conf in #NAMES# ; do - if [ -e /etc/nginx/etc/nginx/modules-enabled/$conf ]; then - rm /etc/nginx/etc/nginx/modules-enabled/$conf + for confpair in #NAMES# ; do + from=$(echo $confpair | cut -d: -f1) + to=$(echo $confpair | cut -d: -f2) + + if [ -e /etc/nginx/modules-enabled/$to ]; then + rm /etc/nginx/modules-enabled/$to fi done diff --git a/debian/dh_nginx b/debian/dh_nginx index 2d7b942..447ab79 100755 --- a/debian/dh_nginx +++ b/debian/dh_nginx @@ -169,7 +169,8 @@ foreach my $package ((@{$dh{DOPACKAGES}})) { my $type = lc(shift @{$line}) if $line->[0]; my $source = shift @{$line} if $line->[0]; - my @arguments = map {"$_ "} @{$line}; + my @arguments = @{$line}; + my $destination; $type = "modules" if $type eq "mod"; my $installdir = $tmp . "/" . nginx_modules_conf_installdir(); @@ -185,8 +186,10 @@ foreach my $package ((@{$dh{DOPACKAGES}})) if ($basesource =~ m/\.conf$/) { my $enablename = $basesource; - push @{$PACKAGE_TYPE{'has_a_module'}}, $enablename; - verbose_print("Installing module configuration $enablename into $installdir\n"); + my $prio = $#arguments >= 0 ? $arguments[0] : 50; + $destination = "$prio-$basesource"; + push @{$PACKAGE_TYPE{'has_a_module'}}, "$enablename:$destination"; + verbose_print("Installing module configuration $enablename into $installdir prio:$prio\n"); } elsif ($basesource =~ m/\.so$/) { From fef2251ae991b7133991b311268fa39040cdd750 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Thu, 7 Apr 2016 12:56:43 +0300 Subject: [PATCH 059/600] NDK is a dependency, load it before nginx-lua --- debian/libnginx-mod-http-ndk.nginx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/libnginx-mod-http-ndk.nginx b/debian/libnginx-mod-http-ndk.nginx index 1905145..562723b 100644 --- a/debian/libnginx-mod-http-ndk.nginx +++ b/debian/libnginx-mod-http-ndk.nginx @@ -1,2 +1,2 @@ mod debian/build-extras/objs/ndk_http_module.so -mod debian/libnginx-mod.conf/mod-http-ndk.conf +mod debian/libnginx-mod.conf/mod-http-ndk.conf 10 From 65f92dd626ecd8eaf809ace9b81406511ce5c7af Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Mon, 18 Apr 2016 11:54:13 +0300 Subject: [PATCH 060/600] merge into dh_nginx --- debian/dh_nginx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/debian/dh_nginx b/debian/dh_nginx index 447ab79..3be792d 100755 --- a/debian/dh_nginx +++ b/debian/dh_nginx @@ -112,9 +112,8 @@ Modules are handled specially and are determined by the B type. Modules mus have a I<.conf> suffix. In that case the file is interpreted as module load file and is installed to I. If the file is ending with a I<.so> suffix it is interpreted as actual module shared object and is -installed to the Nginx module directory. Moreover, if a I<.load> file is -installed the configuration is activated in the maintainer script at -installation time. +installed to the Nginx module directory, an optional numeric priority can be +set as the last argument to handle module dependencies. =head1 OPTIONS @@ -205,7 +204,7 @@ foreach my $package ((@{$dh{DOPACKAGES}})) } # TODO - error("module: \"$basesource\" needs .conf, .so or .load suffix") if $basesource !~ m/\.(conf|so)/; + error("module: \"$basesource\" needs .conf, .so or suffix") if $basesource !~ m/\.(conf|so)/; } if (! -d $installdir) From 578f222e929b84dd1cccfb8b7a606fa4d4d5511c Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Mon, 18 Apr 2016 12:43:59 +0300 Subject: [PATCH 061/600] README.packaging: Add a note about dynamic module support. --- debian/README.Packaging | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/debian/README.Packaging b/debian/README.Packaging index 66a88c1..61358da 100644 --- a/debian/README.Packaging +++ b/debian/README.Packaging @@ -9,6 +9,22 @@ Workflow for Unstable We use the standard git-buildpackage workflow. +Dynamic Modules +=============== + +Since v1.9.11 Nginx added dynamic module support. This will sanitize the +nginx packaging flow in the long term, but there is a lot work to be done +in order to get there. We will gradually convert all modules to dynamic +as they add support for it. + +Currently nginx modules need to be build together with nginx, but this +will be fixed upstream [0]. Since we already ship 3rd party modules under +debian/modules/ we will start shipping module packages (libnginx-mod) from +the same source. Once upstream implements separated building we will +split each module to a separate source. + +[0] https://www.nginx.com/blog/dynamic-modules-nginx-1-9-11/ + Workflow for Experimental (not-active) ====================================== From 0eb87154ce11613d2ad16e5ff7d0b889ca84fd54 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Mon, 18 Apr 2016 12:58:40 +0300 Subject: [PATCH 062/600] Imported Upstream version 1.9.14 --- CHANGES | 19 +- CHANGES.ru | 17 + auto/lib/openssl/conf | 2 +- auto/types/sizeof | 8 +- auto/types/typedef | 13 +- auto/unix | 5 +- contrib/vim/syntax/nginx.vim | 2 +- src/core/nginx.c | 7 +- src/core/nginx.h | 4 +- src/core/ngx_conf_file.c | 6 +- src/core/ngx_config.h | 5 - src/core/ngx_connection.c | 36 +- src/core/ngx_connection.h | 22 +- src/core/ngx_crypt.c | 4 +- src/core/ngx_cycle.c | 10 +- src/core/ngx_cycle.h | 40 +- src/core/ngx_file.c | 6 +- src/core/ngx_inet.c | 22 +- src/core/ngx_log.c | 20 +- src/core/ngx_log.h | 3 +- src/core/ngx_open_file_cache.c | 2 +- src/core/ngx_parse_time.c | 2 +- src/core/ngx_resolver.c | 2 +- src/core/ngx_slab.c | 11 +- src/core/ngx_syslog.c | 6 +- src/core/ngx_times.c | 4 +- src/event/modules/ngx_epoll_module.c | 2 +- src/event/modules/ngx_eventport_module.c | 10 +- src/event/modules/ngx_kqueue_module.c | 23 +- src/event/ngx_event.c | 2 +- src/event/ngx_event.h | 2 +- src/event/ngx_event_openssl.c | 69 +- src/event/ngx_event_openssl.h | 17 + src/event/ngx_event_openssl_stapling.c | 6 +- src/event/ngx_event_pipe.c | 12 +- src/http/modules/ngx_http_auth_basic_module.c | 2 +- .../modules/ngx_http_auth_request_module.c | 4 +- .../modules/ngx_http_chunked_filter_module.c | 2 +- src/http/modules/ngx_http_dav_module.c | 10 +- src/http/modules/ngx_http_fastcgi_module.c | 16 +- .../modules/ngx_http_gzip_filter_module.c | 4 +- .../modules/ngx_http_image_filter_module.c | 4 +- src/http/modules/ngx_http_limit_conn_module.c | 4 +- src/http/modules/ngx_http_map_module.c | 2 +- src/http/modules/ngx_http_memcached_module.c | 2 +- src/http/modules/ngx_http_mp4_module.c | 18 +- src/http/modules/ngx_http_proxy_module.c | 8 +- .../modules/ngx_http_random_index_module.c | 2 +- .../modules/ngx_http_range_filter_module.c | 4 +- src/http/modules/ngx_http_realip_module.c | 4 +- src/http/modules/ngx_http_referer_module.c | 2 +- src/http/modules/ngx_http_rewrite_module.c | 2 +- src/http/modules/ngx_http_scgi_module.c | 2 +- src/http/modules/ngx_http_ssi_filter_module.c | 8 +- src/http/modules/ngx_http_ssl_module.c | 9 +- src/http/modules/ngx_http_sub_filter_module.c | 2 +- .../ngx_http_upstream_ip_hash_module.c | 2 +- .../ngx_http_upstream_least_conn_module.c | 2 +- src/http/ngx_http_core_module.c | 39 +- src/http/ngx_http_core_module.h | 8 +- src/http/ngx_http_file_cache.c | 2 +- src/http/ngx_http_request.c | 12 +- src/http/ngx_http_request.h | 3 + src/http/ngx_http_request_body.c | 41 +- src/http/ngx_http_script.c | 6 +- src/http/ngx_http_upstream.c | 24 +- src/http/ngx_http_upstream_round_robin.c | 2 +- src/http/ngx_http_variables.c | 5 +- src/http/ngx_http_write_filter_module.c | 2 +- src/http/v2/ngx_http_v2.c | 681 ++++++++++-------- src/http/v2/ngx_http_v2.h | 9 +- src/http/v2/ngx_http_v2_module.c | 2 +- src/mail/ngx_mail.h | 2 +- src/mail/ngx_mail_auth_http_module.c | 2 +- src/mail/ngx_mail_proxy_module.c | 2 +- src/mail/ngx_mail_smtp_handler.c | 2 +- src/mail/ngx_mail_ssl_module.c | 8 +- src/os/unix/ngx_atomic.h | 20 +- src/os/unix/ngx_channel.h | 8 +- src/os/unix/ngx_file_aio_read.c | 2 +- src/os/unix/ngx_files.c | 2 +- src/os/unix/ngx_linux_aio_read.c | 2 +- src/os/unix/ngx_linux_sendfile_chain.c | 2 +- src/os/unix/ngx_os.h | 2 +- src/os/unix/ngx_process.c | 2 +- src/os/unix/ngx_process_cycle.c | 10 +- src/os/unix/ngx_readv_chain.c | 2 +- src/os/unix/ngx_recv.c | 4 +- src/os/unix/ngx_send.c | 2 +- src/os/unix/ngx_sunpro_amd64.il | 6 +- src/os/unix/ngx_sunpro_x86.il | 6 +- src/os/unix/ngx_udp_recv.c | 4 +- src/stream/ngx_stream_limit_conn_module.c | 4 +- src/stream/ngx_stream_ssl_module.c | 2 +- .../ngx_stream_upstream_least_conn_module.c | 2 +- src/stream/ngx_stream_upstream_round_robin.c | 2 +- 96 files changed, 844 insertions(+), 628 deletions(-) diff --git a/CHANGES b/CHANGES index 0ac9c61..e1e596e 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,21 @@ +Changes with nginx 1.9.14 05 Apr 2016 + + *) Feature: OpenSSL 1.1.0 compatibility. + + *) Feature: the "proxy_request_buffering", "fastcgi_request_buffering", + "scgi_request_buffering", and "uwsgi_request_buffering" directives + now work with HTTP/2. + + *) Bugfix: "zero size buf in output" alerts might appear in logs when + using HTTP/2. + + *) Bugfix: the "client_max_body_size" directive might work incorrectly + when using HTTP/2. + + *) Bugfix: of minor bugs in logging. + + Changes with nginx 1.9.13 29 Mar 2016 *) Change: non-idempotent requests (POST, LOCK, PATCH) are no longer @@ -1875,7 +1892,7 @@ Changes with nginx 1.1.6 17 Oct 2011 sent to it after fail_timeout; the server will be considered alive if it will successfully respond to the request. - *) Change: now the 0x7F-0x1F characters are escaped as \xXX in an + *) Change: now the 0x7F-0xFF characters are escaped as \xXX in an access_log. *) Feature: "proxy/fastcgi/scgi/uwsgi_ignore_headers" directives support diff --git a/CHANGES.ru b/CHANGES.ru index 7c92f7b..c6e6e84 100644 --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,21 @@ +Изменения в nginx 1.9.14 05.04.2016 + + *) Добавление: совместимость с OpenSSL 1.1.0. + + *) Добавление: директивы proxy_request_buffering, + fastcgi_request_buffering, scgi_request_buffering и + uwsgi_request_buffering теперь работают при использовании HTTP/2. + + *) Исправление: при использовании HTTP/2 в логах могли появляться + сообщения "zero size buf in output". + + *) Исправление: при использовании HTTP/2 директива client_max_body_size + могла работать неверно. + + *) Исправление: незначительных ошибок логгирования. + + Изменения в nginx 1.9.13 29.03.2016 *) Изменение: неидемпотентные запросы (POST, LOCK, PATCH) теперь по diff --git a/auto/lib/openssl/conf b/auto/lib/openssl/conf index e438050..39d9602 100644 --- a/auto/lib/openssl/conf +++ b/auto/lib/openssl/conf @@ -52,7 +52,7 @@ else ngx_feature_incs="#include " ngx_feature_path= ngx_feature_libs="-lssl -lcrypto $NGX_LIBDL" - ngx_feature_test="SSL_library_init()" + ngx_feature_test="SSL_CTX_set_options(NULL, 0)" . auto/feature if [ $ngx_found = no ]; then diff --git a/auto/types/sizeof b/auto/types/sizeof index a5f66bb..b5b71bb 100644 --- a/auto/types/sizeof +++ b/auto/types/sizeof @@ -45,9 +45,6 @@ if [ -x $NGX_AUTOTEST ]; then fi -rm -rf $NGX_AUTOTEST* - - case $ngx_size in 4) ngx_max_value=2147483647 @@ -69,6 +66,11 @@ case $ngx_size in echo $ngx_test >> $NGX_AUTOCONF_ERR echo "----------" >> $NGX_AUTOCONF_ERR + rm -rf $NGX_AUTOTEST* + exit 1 esac + +rm -rf $NGX_AUTOTEST* + diff --git a/auto/types/typedef b/auto/types/typedef index 8b5c368..b55237e 100644 --- a/auto/types/typedef +++ b/auto/types/typedef @@ -49,18 +49,23 @@ END fi fi - rm -rf $NGX_AUTOTEST* - if [ $ngx_found = no ]; then - echo $ngx_n " $ngx_try not found$ngx_c" + if [ $ngx_try = $ngx_type ]; then + echo $ngx_n " $ngx_try not found$ngx_c" + else + echo $ngx_n ", $ngx_try not found$ngx_c" + fi echo "----------" >> $NGX_AUTOCONF_ERR cat $NGX_AUTOTEST.c >> $NGX_AUTOCONF_ERR echo "----------" >> $NGX_AUTOCONF_ERR echo $ngx_test >> $NGX_AUTOCONF_ERR echo "----------" >> $NGX_AUTOCONF_ERR + fi - else + rm -rf $NGX_AUTOTEST* + + if [ $ngx_found != no ]; then break fi done diff --git a/auto/unix b/auto/unix index 16d9523..8c0e813 100755 --- a/auto/unix +++ b/auto/unix @@ -260,7 +260,7 @@ ngx_feature_run=no ngx_feature_incs="#include " ngx_feature_path= ngx_feature_libs= -ngx_feature_test="dlopen(NULL, 0); dlsym(NULL, NULL)" +ngx_feature_test="dlopen(NULL, RTLD_NOW | RTLD_GLOBAL); dlsym(NULL, NULL)" . auto/feature @@ -547,6 +547,7 @@ ngx_param=NGX_PTR_SIZE; ngx_value=$ngx_size; . auto/types/value NGX_INCLUDE_AUTO_CONFIG_H="#include \"ngx_auto_config.h\"" +ngx_type="uint32_t"; ngx_types="u_int32_t"; . auto/types/typedef ngx_type="uint64_t"; ngx_types="u_int64_t"; . auto/types/typedef ngx_type="sig_atomic_t"; ngx_types="int"; . auto/types/typedef @@ -555,7 +556,7 @@ ngx_param=NGX_SIG_ATOMIC_T_SIZE; ngx_value=$ngx_size; . auto/types/value ngx_type="socklen_t"; ngx_types="int"; . auto/types/typedef -ngx_type="in_addr_t"; ngx_types="uint32_t"; . auto/types/typedef +ngx_type="in_addr_t"; ngx_types="uint32_t u_int32_t"; . auto/types/typedef ngx_type="in_port_t"; ngx_types="u_short"; . auto/types/typedef diff --git a/contrib/vim/syntax/nginx.vim b/contrib/vim/syntax/nginx.vim index 444d96e..8f13017 100644 --- a/contrib/vim/syntax/nginx.vim +++ b/contrib/vim/syntax/nginx.vim @@ -57,6 +57,7 @@ syn keyword ngxDirectiveError post_action syn keyword ngxDirectiveDeprecated connections syn keyword ngxDirectiveDeprecated imap syn keyword ngxDirectiveDeprecated limit_zone +syn keyword ngxDirectiveDeprecated mysql_test syn keyword ngxDirectiveDeprecated open_file_cache_retest syn keyword ngxDirectiveDeprecated optimize_server_names syn keyword ngxDirectiveDeprecated satisfy_any @@ -246,7 +247,6 @@ syn keyword ngxDirective mp4_max_buffer_size syn keyword ngxDirective msie_padding syn keyword ngxDirective msie_refresh syn keyword ngxDirective multi_accept -syn keyword ngxDirective mysql_test syn keyword ngxDirective open_file_cache syn keyword ngxDirective open_file_cache_errors syn keyword ngxDirective open_file_cache_events diff --git a/src/core/nginx.c b/src/core/nginx.c index 2823169..60f8fe7 100644 --- a/src/core/nginx.c +++ b/src/core/nginx.c @@ -413,13 +413,12 @@ ngx_show_version_info(void) #endif #if (NGX_SSL) - if (SSLeay() == SSLEAY_VERSION_NUMBER) { + if (ngx_strcmp(ngx_ssl_version(), OPENSSL_VERSION_TEXT) == 0) { ngx_write_stderr("built with " OPENSSL_VERSION_TEXT NGX_LINEFEED); } else { ngx_write_stderr("built with " OPENSSL_VERSION_TEXT " (running with "); - ngx_write_stderr((char *) (uintptr_t) - SSLeay_version(SSLEAY_VERSION)); + ngx_write_stderr((char *) (uintptr_t) ngx_ssl_version()); ngx_write_stderr(")" NGX_LINEFEED); } #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME @@ -1510,7 +1509,7 @@ ngx_load_module(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_ERROR; } - ngx_log_debug2(NGX_LOG_DEBUG_CORE, cf->log, 0, "module: %s i:%i", + ngx_log_debug2(NGX_LOG_DEBUG_CORE, cf->log, 0, "module: %s i:%ui", module->name, module->index); } diff --git a/src/core/nginx.h b/src/core/nginx.h index 238d8b8..d0a6f65 100644 --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1009013 -#define NGINX_VERSION "1.9.13" +#define nginx_version 1009014 +#define NGINX_VERSION "1.9.14" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD diff --git a/src/core/ngx_conf_file.c b/src/core/ngx_conf_file.c index fb72656..c60d5fb 100644 --- a/src/core/ngx_conf_file.c +++ b/src/core/ngx_conf_file.c @@ -613,9 +613,9 @@ ngx_conf_read_token(ngx_conf_t *cf) need_space = 0; } else { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "unexpected \"%c\"", ch); - return NGX_ERROR; + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "unexpected \"%c\"", ch); + return NGX_ERROR; } } diff --git a/src/core/ngx_config.h b/src/core/ngx_config.h index 145e43a..a0bfa63 100644 --- a/src/core/ngx_config.h +++ b/src/core/ngx_config.h @@ -125,12 +125,7 @@ typedef intptr_t ngx_flag_t; #endif -#if ((__GNU__ == 2) && (__GNUC_MINOR__ < 8)) -#define NGX_MAX_UINT32_VALUE (uint32_t) 0xffffffffLL -#else #define NGX_MAX_UINT32_VALUE (uint32_t) 0xffffffff -#endif - #define NGX_MAX_INT32_VALUE (uint32_t) 0x7fffffff diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c index 572def2..5a53bac 100644 --- a/src/core/ngx_connection.c +++ b/src/core/ngx_connection.c @@ -47,21 +47,21 @@ ngx_create_listening(ngx_conf_t *cf, void *sockaddr, socklen_t socklen) switch (ls->sockaddr->sa_family) { #if (NGX_HAVE_INET6) case AF_INET6: - ls->addr_text_max_len = NGX_INET6_ADDRSTRLEN; - break; + ls->addr_text_max_len = NGX_INET6_ADDRSTRLEN; + break; #endif #if (NGX_HAVE_UNIX_DOMAIN) case AF_UNIX: - ls->addr_text_max_len = NGX_UNIX_ADDRSTRLEN; - len++; - break; + ls->addr_text_max_len = NGX_UNIX_ADDRSTRLEN; + len++; + break; #endif case AF_INET: - ls->addr_text_max_len = NGX_INET_ADDRSTRLEN; - break; + ls->addr_text_max_len = NGX_INET_ADDRSTRLEN; + break; default: - ls->addr_text_max_len = NGX_SOCKADDR_STRLEN; - break; + ls->addr_text_max_len = NGX_SOCKADDR_STRLEN; + break; } ls->addr_text.data = ngx_pnalloc(cf->pool, len); @@ -168,22 +168,22 @@ ngx_set_inherited_sockets(ngx_cycle_t *cycle) #if (NGX_HAVE_INET6) case AF_INET6: - ls[i].addr_text_max_len = NGX_INET6_ADDRSTRLEN; - len = NGX_INET6_ADDRSTRLEN + sizeof("[]:65535") - 1; - break; + ls[i].addr_text_max_len = NGX_INET6_ADDRSTRLEN; + len = NGX_INET6_ADDRSTRLEN + sizeof("[]:65535") - 1; + break; #endif #if (NGX_HAVE_UNIX_DOMAIN) case AF_UNIX: - ls[i].addr_text_max_len = NGX_UNIX_ADDRSTRLEN; - len = NGX_UNIX_ADDRSTRLEN; - break; + ls[i].addr_text_max_len = NGX_UNIX_ADDRSTRLEN; + len = NGX_UNIX_ADDRSTRLEN; + break; #endif case AF_INET: - ls[i].addr_text_max_len = NGX_INET_ADDRSTRLEN; - len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1; - break; + ls[i].addr_text_max_len = NGX_INET_ADDRSTRLEN; + len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1; + break; default: ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno, diff --git a/src/core/ngx_connection.h b/src/core/ngx_connection.h index 19a2ab7..b0d162a 100644 --- a/src/core/ngx_connection.h +++ b/src/core/ngx_connection.h @@ -95,25 +95,25 @@ struct ngx_listening_s { typedef enum { - NGX_ERROR_ALERT = 0, - NGX_ERROR_ERR, - NGX_ERROR_INFO, - NGX_ERROR_IGNORE_ECONNRESET, - NGX_ERROR_IGNORE_EINVAL + NGX_ERROR_ALERT = 0, + NGX_ERROR_ERR, + NGX_ERROR_INFO, + NGX_ERROR_IGNORE_ECONNRESET, + NGX_ERROR_IGNORE_EINVAL } ngx_connection_log_error_e; typedef enum { - NGX_TCP_NODELAY_UNSET = 0, - NGX_TCP_NODELAY_SET, - NGX_TCP_NODELAY_DISABLED + NGX_TCP_NODELAY_UNSET = 0, + NGX_TCP_NODELAY_SET, + NGX_TCP_NODELAY_DISABLED } ngx_connection_tcp_nodelay_e; typedef enum { - NGX_TCP_NOPUSH_UNSET = 0, - NGX_TCP_NOPUSH_SET, - NGX_TCP_NOPUSH_DISABLED + NGX_TCP_NOPUSH_UNSET = 0, + NGX_TCP_NOPUSH_SET, + NGX_TCP_NOPUSH_DISABLED } ngx_connection_tcp_nopush_e; diff --git a/src/core/ngx_crypt.c b/src/core/ngx_crypt.c index d7d068c..9db74f4 100644 --- a/src/core/ngx_crypt.c +++ b/src/core/ngx_crypt.c @@ -165,8 +165,8 @@ ngx_crypt_to64(u_char *p, uint32_t v, size_t n) "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; while (n--) { - *p++ = itoa64[v & 0x3f]; - v >>= 6; + *p++ = itoa64[v & 0x3f]; + v >>= 6; } return p; diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c index 5785eb5..98599f3 100644 --- a/src/core/ngx_cycle.c +++ b/src/core/ngx_cycle.c @@ -1006,7 +1006,7 @@ ngx_int_t ngx_signal_process(ngx_cycle_t *cycle, char *sig) { ssize_t n; - ngx_int_t pid; + ngx_pid_t pid; ngx_file_t file; ngx_core_conf_t *ccf; u_char buf[NGX_INT64_LEN + 2]; @@ -1044,7 +1044,7 @@ ngx_signal_process(ngx_cycle_t *cycle, char *sig) pid = ngx_atoi(buf, ++n); - if (pid == NGX_ERROR) { + if (pid == (ngx_pid_t) NGX_ERROR) { ngx_log_error(NGX_LOG_ERR, cycle->log, 0, "invalid PID number \"%*s\" in \"%s\"", n, buf, file.name.data); @@ -1313,7 +1313,7 @@ ngx_clean_old_cycles(ngx_event_t *ev) if (cycle[i]->connections[n].fd != (ngx_socket_t) -1) { found = 1; - ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, "live fd:%d", n); + ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, "live fd:%ui", n); break; } @@ -1324,13 +1324,13 @@ ngx_clean_old_cycles(ngx_event_t *ev) continue; } - ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, "clean old cycle: %d", i); + ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, "clean old cycle: %ui", i); ngx_destroy_pool(cycle[i]->pool); cycle[i] = NULL; } - ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, "old cycles status: %d", live); + ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, "old cycles status: %ui", live); if (live) { ngx_add_timer(ev, 30000); diff --git a/src/core/ngx_cycle.h b/src/core/ngx_cycle.h index cfdbb55..c51b7ff 100644 --- a/src/core/ngx_cycle.h +++ b/src/core/ngx_cycle.h @@ -79,35 +79,35 @@ struct ngx_cycle_s { typedef struct { - ngx_flag_t daemon; - ngx_flag_t master; + ngx_flag_t daemon; + ngx_flag_t master; - ngx_msec_t timer_resolution; + ngx_msec_t timer_resolution; - ngx_int_t worker_processes; - ngx_int_t debug_points; + ngx_int_t worker_processes; + ngx_int_t debug_points; - ngx_int_t rlimit_nofile; - off_t rlimit_core; + ngx_int_t rlimit_nofile; + off_t rlimit_core; - int priority; + int priority; - ngx_uint_t cpu_affinity_auto; - ngx_uint_t cpu_affinity_n; - ngx_cpuset_t *cpu_affinity; + ngx_uint_t cpu_affinity_auto; + ngx_uint_t cpu_affinity_n; + ngx_cpuset_t *cpu_affinity; - char *username; - ngx_uid_t user; - ngx_gid_t group; + char *username; + ngx_uid_t user; + ngx_gid_t group; - ngx_str_t working_directory; - ngx_str_t lock_file; + ngx_str_t working_directory; + ngx_str_t lock_file; - ngx_str_t pid; - ngx_str_t oldpid; + ngx_str_t pid; + ngx_str_t oldpid; - ngx_array_t env; - char **environment; + ngx_array_t env; + char **environment; } ngx_core_conf_t; diff --git a/src/core/ngx_file.c b/src/core/ngx_file.c index d3e2ece..fc2dfd3 100644 --- a/src/core/ngx_file.c +++ b/src/core/ngx_file.c @@ -155,7 +155,7 @@ ngx_create_temp_file(ngx_file_t *file, ngx_path_t *path, ngx_pool_t *pool, #if 0 for (i = 0; i < file->name.len; i++) { - file->name.data[i] = 'X'; + file->name.data[i] = 'X'; } #endif @@ -841,7 +841,7 @@ ngx_copy_file(u_char *from, u_char *to, ngx_copy_file_t *cf) if ((size_t) n != len) { ngx_log_error(NGX_LOG_ALERT, cf->log, 0, - ngx_read_fd_n " has read only %z of %uz from %s", + ngx_read_fd_n " has read only %z of %O from %s", n, size, from); goto failed; } @@ -856,7 +856,7 @@ ngx_copy_file(u_char *from, u_char *to, ngx_copy_file_t *cf) if ((size_t) n != len) { ngx_log_error(NGX_LOG_ALERT, cf->log, 0, - ngx_write_fd_n " has written only %z of %uz to %s", + ngx_write_fd_n " has written only %z of %O to %s", n, size, to); goto failed; } diff --git a/src/core/ngx_inet.c b/src/core/ngx_inet.c index 3bbadb8..a4e80ed 100644 --- a/src/core/ngx_inet.c +++ b/src/core/ngx_inet.c @@ -348,7 +348,7 @@ ngx_inet6_ntop(u_char *p, u_char *text, size_t len) continue; } - dst = ngx_sprintf(dst, "%uxi", p[i] * 256 + p[i + 1]); + dst = ngx_sprintf(dst, "%uxd", p[i] * 256 + p[i + 1]); if (i < 14) { *dst++ = ':'; @@ -1242,19 +1242,19 @@ ngx_cmp_sockaddr(struct sockaddr *sa1, socklen_t slen1, #if (NGX_HAVE_UNIX_DOMAIN) case AF_UNIX: - /* TODO length */ + /* TODO length */ - saun1 = (struct sockaddr_un *) sa1; - saun2 = (struct sockaddr_un *) sa2; + saun1 = (struct sockaddr_un *) sa1; + saun2 = (struct sockaddr_un *) sa2; - if (ngx_memcmp(&saun1->sun_path, &saun2->sun_path, - sizeof(saun1->sun_path)) - != 0) - { - return NGX_DECLINED; - } + if (ngx_memcmp(&saun1->sun_path, &saun2->sun_path, + sizeof(saun1->sun_path)) + != 0) + { + return NGX_DECLINED; + } - break; + break; #endif default: /* AF_INET */ diff --git a/src/core/ngx_log.c b/src/core/ngx_log.c index 0893871..8e9408d 100644 --- a/src/core/ngx_log.c +++ b/src/core/ngx_log.c @@ -33,14 +33,14 @@ typedef struct { static ngx_command_t ngx_errlog_commands[] = { - {ngx_string("error_log"), - NGX_MAIN_CONF|NGX_CONF_1MORE, - ngx_error_log, - 0, - 0, - NULL}, + { ngx_string("error_log"), + NGX_MAIN_CONF|NGX_CONF_1MORE, + ngx_error_log, + 0, + 0, + NULL }, - ngx_null_command + ngx_null_command }; @@ -86,7 +86,7 @@ static ngx_str_t err_levels[] = { static const char *debug_levels[] = { "debug_core", "debug_alloc", "debug_mutex", "debug_event", - "debug_http", "debug_mail", "debug_mysql", "debug_stream" + "debug_http", "debug_mail", "debug_stream" }; @@ -585,7 +585,7 @@ ngx_log_set_log(ngx_conf_t *cf, ngx_log_t **head) return NGX_CONF_ERROR; } - } else if (ngx_strncmp(value[1].data, "memory:", 7) == 0) { + } else if (ngx_strncmp(value[1].data, "memory:", 7) == 0) { #if (NGX_DEBUG) size_t size, needed; @@ -644,7 +644,7 @@ ngx_log_set_log(ngx_conf_t *cf, ngx_log_t **head) return NGX_CONF_ERROR; #endif - } else if (ngx_strncmp(value[1].data, "syslog:", 7) == 0) { + } else if (ngx_strncmp(value[1].data, "syslog:", 7) == 0) { peer = ngx_pcalloc(cf->pool, sizeof(ngx_syslog_peer_t)); if (peer == NULL) { return NGX_CONF_ERROR; diff --git a/src/core/ngx_log.h b/src/core/ngx_log.h index 618d3ad..afb73bf 100644 --- a/src/core/ngx_log.h +++ b/src/core/ngx_log.h @@ -29,8 +29,7 @@ #define NGX_LOG_DEBUG_EVENT 0x080 #define NGX_LOG_DEBUG_HTTP 0x100 #define NGX_LOG_DEBUG_MAIL 0x200 -#define NGX_LOG_DEBUG_MYSQL 0x400 -#define NGX_LOG_DEBUG_STREAM 0x800 +#define NGX_LOG_DEBUG_STREAM 0x400 /* * do not forget to update debug_levels[] in src/core/ngx_log.c diff --git a/src/core/ngx_open_file_cache.c b/src/core/ngx_open_file_cache.c index f8bb2e3..b23ee78 100644 --- a/src/core/ngx_open_file_cache.c +++ b/src/core/ngx_open_file_cache.c @@ -544,7 +544,7 @@ failed: if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, - ngx_close_file_n " \"%V\" failed", name); + ngx_close_file_n " \"%s\" failed", name); } ngx_set_errno(err); diff --git a/src/core/ngx_parse_time.c b/src/core/ngx_parse_time.c index 831cc71..13afde3 100644 --- a/src/core/ngx_parse_time.c +++ b/src/core/ngx_parse_time.c @@ -220,7 +220,7 @@ ngx_parse_http_time(u_char *value, size_t len) } if (hour > 23 || min > 59 || sec > 59) { - return NGX_ERROR; + return NGX_ERROR; } if (day == 29 && month == 1) { diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c index 38bf956..3c52de8 100644 --- a/src/core/ngx_resolver.c +++ b/src/core/ngx_resolver.c @@ -1873,7 +1873,7 @@ dns_error_name: ngx_log_error(r->log_level, r->log, 0, "DNS error (%ui: %s), query id:%ui, name:\"%*s\"", code, ngx_resolver_strerror(code), ident, - rn->nlen, rn->name); + (size_t) rn->nlen, rn->name); return; dns_error: diff --git a/src/core/ngx_slab.c b/src/core/ngx_slab.c index c112506..56e7765 100644 --- a/src/core/ngx_slab.c +++ b/src/core/ngx_slab.c @@ -222,11 +222,11 @@ ngx_slab_alloc_locked(ngx_slab_pool_t *pool, size_t size) if (bitmap[n] == NGX_SLAB_BUSY) { for (n = n + 1; n < map; n++) { - if (bitmap[n] != NGX_SLAB_BUSY) { - p = (uintptr_t) bitmap + i; + if (bitmap[n] != NGX_SLAB_BUSY) { + p = (uintptr_t) bitmap + i; - goto done; - } + goto done; + } } prev = (ngx_slab_page_t *) @@ -392,7 +392,8 @@ ngx_slab_alloc_locked(ngx_slab_pool_t *pool, size_t size) done: - ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, ngx_cycle->log, 0, "slab alloc: %p", p); + ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, ngx_cycle->log, 0, + "slab alloc: %p", (void *) p); return (void *) p; } diff --git a/src/core/ngx_syslog.c b/src/core/ngx_syslog.c index 08f4c04..0a67928 100644 --- a/src/core/ngx_syslog.c +++ b/src/core/ngx_syslog.c @@ -10,9 +10,9 @@ #define NGX_SYSLOG_MAX_STR \ - NGX_MAX_ERROR_STR + sizeof("<255>Jan 01 00:00:00 ") - 1 \ - + (NGX_MAXHOSTNAMELEN - 1) + 1 /* space */ \ - + 32 /* tag */ + 2 /* colon, space */ + NGX_MAX_ERROR_STR + sizeof("<255>Jan 01 00:00:00 ") - 1 \ + + (NGX_MAXHOSTNAMELEN - 1) + 1 /* space */ \ + + 32 /* tag */ + 2 /* colon, space */ static char *ngx_syslog_parse_args(ngx_conf_t *cf, ngx_syslog_peer_t *peer); diff --git a/src/core/ngx_times.c b/src/core/ngx_times.c index 595c122..843314a 100644 --- a/src/core/ngx_times.c +++ b/src/core/ngx_times.c @@ -154,7 +154,7 @@ ngx_time_update(void) p2 = &cached_http_log_time[slot][0]; - (void) ngx_sprintf(p2, "%02d/%s/%d:%02d:%02d:%02d %c%02d%02d", + (void) ngx_sprintf(p2, "%02d/%s/%d:%02d:%02d:%02d %c%02i%02i", tm.ngx_tm_mday, months[tm.ngx_tm_mon - 1], tm.ngx_tm_year, tm.ngx_tm_hour, tm.ngx_tm_min, tm.ngx_tm_sec, @@ -163,7 +163,7 @@ ngx_time_update(void) p3 = &cached_http_log_iso8601[slot][0]; - (void) ngx_sprintf(p3, "%4d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d", + (void) ngx_sprintf(p3, "%4d-%02d-%02dT%02d:%02d:%02d%c%02i:%02i", tm.ngx_tm_year, tm.ngx_tm_mon, tm.ngx_tm_mday, tm.ngx_tm_hour, tm.ngx_tm_min, tm.ngx_tm_sec, diff --git a/src/event/modules/ngx_epoll_module.c b/src/event/modules/ngx_epoll_module.c index 081b0e5..828e4d1 100644 --- a/src/event/modules/ngx_epoll_module.c +++ b/src/event/modules/ngx_epoll_module.c @@ -902,7 +902,7 @@ ngx_epoll_eventfd_handler(ngx_event_t *ev) events = io_getevents(ngx_aio_ctx, 1, 64, event, &ts); ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0, - "io_getevents: %l", events); + "io_getevents: %d", events); if (events > 0) { ready -= events; diff --git a/src/event/modules/ngx_eventport_module.c b/src/event/modules/ngx_eventport_module.c index 9184547..dafa27f 100644 --- a/src/event/modules/ngx_eventport_module.c +++ b/src/event/modules/ngx_eventport_module.c @@ -49,7 +49,7 @@ typedef struct port_notify { void *portnfy_user; /* user defined */ } port_notify_t; -#if (__FreeBSD__) && (__FreeBSD_version < 700005) +#if (__FreeBSD__ && __FreeBSD_version < 700005) || (NGX_DARWIN) typedef struct itimerspec { /* definition per POSIX.4 */ struct timespec it_interval;/* timer period */ @@ -526,18 +526,18 @@ ngx_eventport_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "eventport: fd:%d, ev:%04Xd", - event_list[i].portev_object, revents); + (int) event_list[i].portev_object, revents); if (revents & (POLLERR|POLLHUP|POLLNVAL)) { ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "port_getn() error fd:%d ev:%04Xd", - event_list[i].portev_object, revents); + (int) event_list[i].portev_object, revents); } if (revents & ~(POLLIN|POLLOUT|POLLERR|POLLHUP|POLLNVAL)) { ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "strange port_getn() events fd:%d ev:%04Xd", - event_list[i].portev_object, revents); + (int) event_list[i].portev_object, revents); } if ((revents & (POLLERR|POLLHUP|POLLNVAL)) @@ -615,7 +615,7 @@ ngx_eventport_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, default: ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "unexpected eventport object %d", - event_list[i].portev_object); + (int) event_list[i].portev_object); continue; } } diff --git a/src/event/modules/ngx_kqueue_module.c b/src/event/modules/ngx_kqueue_module.c index 5573cb2..ca3bfe4 100644 --- a/src/event/modules/ngx_kqueue_module.c +++ b/src/event/modules/ngx_kqueue_module.c @@ -579,7 +579,7 @@ ngx_kqueue_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, if (event_list[i].flags & EV_ERROR) { ngx_log_error(NGX_LOG_ALERT, cycle->log, event_list[i].data, "kevent() error on %d filter:%d flags:%04Xd", - event_list[i].ident, event_list[i].filter, + (int) event_list[i].ident, event_list[i].filter, event_list[i].flags); continue; } @@ -676,13 +676,20 @@ ngx_kqueue_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, static ngx_inline void ngx_kqueue_dump_event(ngx_log_t *log, struct kevent *kev) { - ngx_log_debug6(NGX_LOG_DEBUG_EVENT, log, 0, - (kev->ident > 0x8000000 && kev->ident != (unsigned) -1) ? - "kevent: %p: ft:%d fl:%04Xd ff:%08Xd d:%d ud:%p": - "kevent: %d: ft:%d fl:%04Xd ff:%08Xd d:%d ud:%p", - kev->ident, kev->filter, - kev->flags, kev->fflags, - kev->data, kev->udata); + if (kev->ident > 0x8000000 && kev->ident != (unsigned) -1) { + ngx_log_debug6(NGX_LOG_DEBUG_EVENT, log, 0, + "kevent: %p: ft:%d fl:%04Xd ff:%08Xd d:%d ud:%p", + (void *) kev->ident, kev->filter, + kev->flags, kev->fflags, + (int) kev->data, kev->udata); + + } else { + ngx_log_debug6(NGX_LOG_DEBUG_EVENT, log, 0, + "kevent: %d: ft:%d fl:%04Xd ff:%08Xd d:%d ud:%p", + (int) kev->ident, kev->filter, + kev->flags, kev->fflags, + (int) kev->data, kev->udata); + } } diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c index 38f9b38..c8ae5b2 100644 --- a/src/event/ngx_event.c +++ b/src/event/ngx_event.c @@ -525,7 +525,7 @@ ngx_event_module_init(ngx_cycle_t *cycle) (void) ngx_atomic_cmp_set(ngx_connection_counter, 0, 1); ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0, - "counter: %p, %d", + "counter: %p, %uA", ngx_connection_counter, *ngx_connection_counter); ngx_temp_number = (ngx_atomic_t *) (shared + 2 * cl); diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h index 591005a..ed0682c 100644 --- a/src/event/ngx_event.h +++ b/src/event/ngx_event.h @@ -188,7 +188,7 @@ typedef struct { ngx_int_t (*notify)(ngx_event_handler_pt handler); ngx_int_t (*process_events)(ngx_cycle_t *cycle, ngx_msec_t timer, - ngx_uint_t flags); + ngx_uint_t flags); ngx_int_t (*init)(ngx_cycle_t *cycle, ngx_msec_t timer); void (*done)(ngx_cycle_t *cycle); diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c index de10d48..de10296 100644 --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -39,6 +39,9 @@ ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data); static int ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess); static ngx_ssl_session_t *ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn, +#if OPENSSL_VERSION_NUMBER >= 0x10100003L + const +#endif u_char *id, int len, int *copy); static void ngx_ssl_remove_session(SSL_CTX *ssl, ngx_ssl_session_t *sess); static void ngx_ssl_expire_sessions(ngx_ssl_session_cache_t *cache, @@ -52,7 +55,7 @@ static int ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn, HMAC_CTX *hctx, int enc); #endif -#if (OPENSSL_VERSION_NUMBER < 0x10002002L || defined LIBRESSL_VERSION_NUMBER) +#if OPENSSL_VERSION_NUMBER < 0x10002002L static ngx_int_t ngx_ssl_check_name(ngx_str_t *name, ASN1_STRING *str); #endif @@ -108,6 +111,12 @@ int ngx_ssl_stapling_index; ngx_int_t ngx_ssl_init(ngx_log_t *log) { +#if OPENSSL_VERSION_NUMBER >= 0x10100003L + + OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL); + +#else + #ifndef OPENSSL_IS_BORINGSSL OPENSSL_config(NULL); #endif @@ -117,6 +126,8 @@ ngx_ssl_init(ngx_log_t *log) OpenSSL_add_all_algorithms(); +#endif + #if OPENSSL_VERSION_NUMBER >= 0x0090800fL #ifndef SSL_OP_NO_COMPRESSION { @@ -747,7 +758,7 @@ ngx_ssl_rsa512_key_callback(ngx_ssl_conn_t *ssl_conn, int is_export, return NULL; } -#ifndef OPENSSL_NO_DEPRECATED +#if (OPENSSL_VERSION_NUMBER < 0x10100003L && !defined OPENSSL_NO_DEPRECATED) if (key == NULL) { key = RSA_generate_key(512, RSA_F4, NULL, NULL); @@ -1596,7 +1607,7 @@ ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, - "SSL buf copy: %d", size); + "SSL buf copy: %z", size); ngx_memcpy(buf->last, in->buf->pos, size); @@ -1668,7 +1679,7 @@ ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size) ngx_ssl_clear_error(c->log); - ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL to write: %d", size); + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL to write: %uz", size); n = SSL_write(c->ssl->connection, data, size); @@ -1956,6 +1967,7 @@ ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err, || n == SSL_R_INAPPROPRIATE_FALLBACK /* 373 */ #endif || n == 1000 /* SSL_R_SSLV3_ALERT_CLOSE_NOTIFY */ +#ifdef SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE || n == SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE /* 1010 */ || n == SSL_R_SSLV3_ALERT_BAD_RECORD_MAC /* 1020 */ || n == SSL_R_TLSV1_ALERT_DECRYPTION_FAILED /* 1021 */ @@ -1978,7 +1990,9 @@ ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err, || n == SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY /* 1071 */ || n == SSL_R_TLSV1_ALERT_INTERNAL_ERROR /* 1080 */ || n == SSL_R_TLSV1_ALERT_USER_CANCELLED /* 1090 */ - || n == SSL_R_TLSV1_ALERT_NO_RENEGOTIATION) /* 1100 */ + || n == SSL_R_TLSV1_ALERT_NO_RENEGOTIATION /* 1100 */ +#endif + ) { switch (c->log_error) { @@ -2143,7 +2157,7 @@ ngx_ssl_session_id_context(ngx_ssl_t *ssl, ngx_str_t *sess_ctx) int n, i; X509 *cert; X509_NAME *name; - EVP_MD_CTX md; + EVP_MD_CTX *md; unsigned int len; STACK_OF(X509_NAME) *list; u_char buf[EVP_MAX_MD_SIZE]; @@ -2153,15 +2167,18 @@ ngx_ssl_session_id_context(ngx_ssl_t *ssl, ngx_str_t *sess_ctx) * the server certificate, and the client CA list. */ - EVP_MD_CTX_init(&md); + md = EVP_MD_CTX_create(); + if (md == NULL) { + return NGX_ERROR; + } - if (EVP_DigestInit_ex(&md, EVP_sha1(), NULL) == 0) { + if (EVP_DigestInit_ex(md, EVP_sha1(), NULL) == 0) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "EVP_DigestInit_ex() failed"); goto failed; } - if (EVP_DigestUpdate(&md, sess_ctx->data, sess_ctx->len) == 0) { + if (EVP_DigestUpdate(md, sess_ctx->data, sess_ctx->len) == 0) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "EVP_DigestUpdate() failed"); goto failed; @@ -2175,7 +2192,7 @@ ngx_ssl_session_id_context(ngx_ssl_t *ssl, ngx_str_t *sess_ctx) goto failed; } - if (EVP_DigestUpdate(&md, buf, len) == 0) { + if (EVP_DigestUpdate(md, buf, len) == 0) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "EVP_DigestUpdate() failed"); goto failed; @@ -2195,7 +2212,7 @@ ngx_ssl_session_id_context(ngx_ssl_t *ssl, ngx_str_t *sess_ctx) goto failed; } - if (EVP_DigestUpdate(&md, buf, len) == 0) { + if (EVP_DigestUpdate(md, buf, len) == 0) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "EVP_DigestUpdate() failed"); goto failed; @@ -2203,13 +2220,13 @@ ngx_ssl_session_id_context(ngx_ssl_t *ssl, ngx_str_t *sess_ctx) } } - if (EVP_DigestFinal_ex(&md, buf, &len) == 0) { + if (EVP_DigestFinal_ex(md, buf, &len) == 0) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "EVP_DigestUpdate() failed"); goto failed; } - EVP_MD_CTX_cleanup(&md); + EVP_MD_CTX_destroy(md); if (SSL_CTX_set_session_id_context(ssl->ctx, buf, len) == 0) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, @@ -2221,7 +2238,7 @@ ngx_ssl_session_id_context(ngx_ssl_t *ssl, ngx_str_t *sess_ctx) failed: - EVP_MD_CTX_cleanup(&md); + EVP_MD_CTX_destroy(md); return NGX_ERROR; } @@ -2442,8 +2459,11 @@ failed: static ngx_ssl_session_t * -ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn, u_char *id, int len, - int *copy) +ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn, +#if OPENSSL_VERSION_NUMBER >= 0x10100003L + const +#endif + u_char *id, int len, int *copy) { #if OPENSSL_VERSION_NUMBER >= 0x0090707fL const @@ -2460,7 +2480,7 @@ ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn, u_char *id, int len, u_char buf[NGX_SSL_MAX_SESSION_SIZE]; ngx_connection_t *c; - hash = ngx_crc32_short(id, (size_t) len); + hash = ngx_crc32_short((u_char *) (uintptr_t) id, (size_t) len); *copy = 0; c = ngx_ssl_get_connection(ssl_conn); @@ -2498,7 +2518,8 @@ ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn, u_char *id, int len, sess_id = (ngx_ssl_sess_id_t *) node; - rc = ngx_memn2cmp(id, sess_id->id, (size_t) len, (size_t) node->data); + rc = ngx_memn2cmp((u_char *) (uintptr_t) id, sess_id->id, + (size_t) len, (size_t) node->data); if (rc == 0) { @@ -2542,9 +2563,9 @@ done: void ngx_ssl_remove_cached_session(SSL_CTX *ssl, ngx_ssl_session_t *sess) { - SSL_CTX_remove_session(ssl, sess); + SSL_CTX_remove_session(ssl, sess); - ngx_ssl_remove_session(ssl, sess); + ngx_ssl_remove_session(ssl, sess); } @@ -2944,7 +2965,7 @@ ngx_ssl_check_host(ngx_connection_t *c, ngx_str_t *name) return NGX_ERROR; } -#if (OPENSSL_VERSION_NUMBER >= 0x10002002L && !defined LIBRESSL_VERSION_NUMBER) +#if OPENSSL_VERSION_NUMBER >= 0x10002002L /* X509_check_host() is only available in OpenSSL 1.0.2+ */ @@ -3061,7 +3082,7 @@ found: } -#if (OPENSSL_VERSION_NUMBER < 0x10002002L || defined LIBRESSL_VERSION_NUMBER) +#if OPENSSL_VERSION_NUMBER < 0x10002002L static ngx_int_t ngx_ssl_check_name(ngx_str_t *name, ASN1_STRING *pattern) @@ -3538,8 +3559,12 @@ ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) static void ngx_openssl_exit(ngx_cycle_t *cycle) { +#if OPENSSL_VERSION_NUMBER < 0x10100003L + EVP_cleanup(); #ifndef OPENSSL_NO_ENGINE ENGINE_cleanup(); #endif + +#endif } diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h index c86be2a..09654db 100644 --- a/src/event/ngx_event_openssl.h +++ b/src/event/ngx_event_openssl.h @@ -33,6 +33,23 @@ #define NGX_SSL_NAME "OpenSSL" +#if (defined LIBRESSL_VERSION_NUMBER && OPENSSL_VERSION_NUMBER == 0x20000000L) +#undef OPENSSL_VERSION_NUMBER +#define OPENSSL_VERSION_NUMBER 0x1000107fL +#endif + + +#if (OPENSSL_VERSION_NUMBER >= 0x10100001L) + +#define ngx_ssl_version() OpenSSL_version(OPENSSL_VERSION) + +#else + +#define ngx_ssl_version() SSLeay_version(SSLEAY_VERSION) + +#endif + + #define ngx_ssl_session_t SSL_SESSION #define ngx_ssl_conn_t SSL diff --git a/src/event/ngx_event_openssl_stapling.c b/src/event/ngx_event_openssl_stapling.c index fa77678..5322b1b 100644 --- a/src/event/ngx_event_openssl_stapling.c +++ b/src/event/ngx_event_openssl_stapling.c @@ -285,7 +285,11 @@ ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl) for (i = 0; i < n; i++) { issuer = sk_X509_value(chain, i); if (X509_check_issued(issuer, cert) == X509_V_OK) { +#if OPENSSL_VERSION_NUMBER >= 0x10100001L + X509_up_ref(issuer); +#else CRYPTO_add(&issuer->references, 1, CRYPTO_LOCK_X509); +#endif ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0, "SSL get issuer: found %p in extra certs", issuer); @@ -1219,7 +1223,7 @@ ngx_ssl_ocsp_create_request(ngx_ssl_ocsp_ctx_t *ctx) ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0, "ssl ocsp request length %z, escape %d", - base64.len, escape); + base64.len, (int) escape); len = sizeof("GET ") - 1 + ctx->uri.len + sizeof("/") - 1 + base64.len + 2 * escape + sizeof(" HTTP/1.0" CRLF) - 1 diff --git a/src/event/ngx_event_pipe.c b/src/event/ngx_event_pipe.c index ee86c7e..5ce59ae 100644 --- a/src/event/ngx_event_pipe.c +++ b/src/event/ngx_event_pipe.c @@ -434,7 +434,7 @@ ngx_event_pipe_read_upstream(ngx_event_pipe_t *p) /* STUB */ cl->buf->num = p->num++; if (p->input_filter(p, cl->buf) == NGX_ERROR) { - return NGX_ABORT; + return NGX_ABORT; } ngx_free_chain(p->pool, cl); @@ -660,7 +660,7 @@ ngx_event_pipe_write_to_downstream(ngx_event_pipe_t *p) flush: ngx_log_debug2(NGX_LOG_DEBUG_EVENT, p->log, 0, - "pipe write: out:%p, f:%d", out, flush); + "pipe write: out:%p, f:%ui", out, flush); if (out == NULL) { @@ -801,12 +801,12 @@ ngx_event_pipe_write_chain_to_temp_file(ngx_event_pipe_t *p) } if (cl) { - p->in = cl; - *ll = NULL; + p->in = cl; + *ll = NULL; } else { - p->in = NULL; - p->last_in = &p->in; + p->in = NULL; + p->last_in = &p->in; } } else { diff --git a/src/http/modules/ngx_http_auth_basic_module.c b/src/http/modules/ngx_http_auth_basic_module.c index 8ec5329..1e7a0c2 100644 --- a/src/http/modules/ngx_http_auth_basic_module.c +++ b/src/http/modules/ngx_http_auth_basic_module.c @@ -298,7 +298,7 @@ ngx_http_auth_basic_crypt_handler(ngx_http_request_t *r, &encrypted); ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "rc: %d user: \"%V\" salt: \"%s\"", + "rc: %i user: \"%V\" salt: \"%s\"", rc, &r->headers_in.user, passwd->data); if (rc == NGX_OK) { diff --git a/src/http/modules/ngx_http_auth_request_module.c b/src/http/modules/ngx_http_auth_request_module.c index b4307be..bab79e4 100644 --- a/src/http/modules/ngx_http_auth_request_module.c +++ b/src/http/modules/ngx_http_auth_request_module.c @@ -168,7 +168,7 @@ ngx_http_auth_request_handler(ngx_http_request_t *r) } ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "auth request unexpected status: %d", ctx->status); + "auth request unexpected status: %ui", ctx->status); return NGX_HTTP_INTERNAL_SERVER_ERROR; } @@ -219,7 +219,7 @@ ngx_http_auth_request_done(ngx_http_request_t *r, void *data, ngx_int_t rc) ngx_http_auth_request_ctx_t *ctx = data; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "auth request done s:%d", r->headers_out.status); + "auth request done s:%ui", r->headers_out.status); ctx->done = 1; ctx->status = r->headers_out.status; diff --git a/src/http/modules/ngx_http_chunked_filter_module.c b/src/http/modules/ngx_http_chunked_filter_module.c index 0059a98..ac2e3e8 100644 --- a/src/http/modules/ngx_http_chunked_filter_module.c +++ b/src/http/modules/ngx_http_chunked_filter_module.c @@ -121,7 +121,7 @@ ngx_http_chunked_body_filter(ngx_http_request_t *r, ngx_chain_t *in) for ( ;; ) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http chunk: %d", ngx_buf_size(cl->buf)); + "http chunk: %O", ngx_buf_size(cl->buf)); size += ngx_buf_size(cl->buf); diff --git a/src/http/modules/ngx_http_dav_module.c b/src/http/modules/ngx_http_dav_module.c index b9fadd0..3600265 100644 --- a/src/http/modules/ngx_http_dav_module.c +++ b/src/http/modules/ngx_http_dav_module.c @@ -621,11 +621,11 @@ destination_done: if ((r->uri.data[r->uri.len - 1] == '/' && *(last - 1) != '/') || (r->uri.data[r->uri.len - 1] != '/' && *(last - 1) == '/')) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "both URI \"%V\" and \"Destination\" URI \"%V\" " - "should be either collections or non-collections", - &r->uri, &dest->value); - return NGX_HTTP_CONFLICT; + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "both URI \"%V\" and \"Destination\" URI \"%V\" " + "should be either collections or non-collections", + &r->uri, &dest->value); + return NGX_HTTP_CONFLICT; } depth = ngx_http_dav_depth(r, NGX_HTTP_DAV_INFINITY_DEPTH); diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c index e3024b3..a861203 100644 --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -751,7 +751,7 @@ ngx_http_fastcgi_eval(ngx_http_request_t *r, ngx_http_fastcgi_loc_conf_t *flcf) url.no_resolve = 1; if (ngx_parse_url(r->pool, &url) != NGX_OK) { - if (url.err) { + if (url.err) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%s in upstream \"%V\"", url.err, &url.url); } @@ -1653,7 +1653,7 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r) && f->type != NGX_HTTP_FASTCGI_STDERR) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "upstream sent unexpected FastCGI record: %d", + "upstream sent unexpected FastCGI record: %ui", f->type); return NGX_HTTP_UPSTREAM_INVALID_HEADER; @@ -1800,7 +1800,7 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r) } else { r->cache->header_start += u->buffer.pos - start - - sizeof(ngx_http_fastcgi_header_t); + - sizeof(ngx_http_fastcgi_header_t); } f->large_stderr = 0; @@ -1834,7 +1834,7 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r) rc = ngx_http_parse_header_line(r, &u->buffer, 1); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http fastcgi parser: %d", rc); + "http fastcgi parser: %i", rc); if (rc == NGX_AGAIN) { break; @@ -2505,7 +2505,7 @@ ngx_http_fastcgi_non_buffered_filter(void *data, ssize_t bytes) for (cl = u->out_bufs; cl; cl = cl->next) { ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http fastcgi in memory %p-%p %uz", + "http fastcgi in memory %p-%p %O", cl->buf->pos, cl->buf->last, ngx_buf_size(cl->buf)); if (buf->last == cl->buf->pos) { @@ -2558,8 +2558,8 @@ ngx_http_fastcgi_process_record(ngx_http_request_t *r, case NGX_HTTP_FASTCGI_STDOUT: case NGX_HTTP_FASTCGI_STDERR: case NGX_HTTP_FASTCGI_END_REQUEST: - f->type = (ngx_uint_t) ch; - break; + f->type = (ngx_uint_t) ch; + break; default: ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "upstream sent invalid FastCGI " @@ -2654,7 +2654,7 @@ ngx_http_fastcgi_finalize_request(ngx_http_request_t *r, ngx_int_t rc) static ngx_int_t ngx_http_fastcgi_add_variables(ngx_conf_t *cf) { - ngx_http_variable_t *var, *v; + ngx_http_variable_t *var, *v; for (v = ngx_http_fastcgi_vars; v->name.len; v++) { var = ngx_http_add_variable(cf, &v->name, v->flags); diff --git a/src/http/modules/ngx_http_gzip_filter_module.c b/src/http/modules/ngx_http_gzip_filter_module.c index f941e63..536fdf8 100644 --- a/src/http/modules/ngx_http_gzip_filter_module.c +++ b/src/http/modules/ngx_http_gzip_filter_module.c @@ -1009,14 +1009,14 @@ ngx_http_gzip_filter_alloc(void *opaque, u_int items, u_int size) ctx->allocated -= alloc; ngx_log_debug4(NGX_LOG_DEBUG_HTTP, ctx->request->connection->log, 0, - "gzip alloc: n:%ud s:%ud a:%ud p:%p", + "gzip alloc: n:%ud s:%ud a:%ui p:%p", items, size, alloc, p); return p; } ngx_log_error(NGX_LOG_ALERT, ctx->request->connection->log, 0, - "gzip filter failed to use preallocated memory: %ud of %ud", + "gzip filter failed to use preallocated memory: %ud of %ui", items * size, ctx->allocated); p = ngx_palloc(ctx->request->pool, items * size); diff --git a/src/http/modules/ngx_http_image_filter_module.c b/src/http/modules/ngx_http_image_filter_module.c index bd7a309..b608de1 100644 --- a/src/http/modules/ngx_http_image_filter_module.c +++ b/src/http/modules/ngx_http_image_filter_module.c @@ -144,7 +144,7 @@ static ngx_command_t ngx_http_image_filter_commands[] = { offsetof(ngx_http_image_filter_conf_t, transparency), NULL }, - { ngx_string("image_filter_interlace"), + { ngx_string("image_filter_interlace"), 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, @@ -737,7 +737,7 @@ ngx_http_image_size(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx) } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "image size: %d x %d", width, height); + "image size: %d x %d", (int) width, (int) height); ctx->width = width; ctx->height = height; diff --git a/src/http/modules/ngx_http_limit_conn_module.c b/src/http/modules/ngx_http_limit_conn_module.c index 4379311..913d599 100644 --- a/src/http/modules/ngx_http_limit_conn_module.c +++ b/src/http/modules/ngx_http_limit_conn_module.c @@ -232,7 +232,7 @@ ngx_http_limit_conn_handler(ngx_http_request_t *r) } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "limit conn: %08XD %d", node->key, lc->conn); + "limit conn: %08Xi %d", node->key, lc->conn); ngx_shmtx_unlock(&shpool->mutex); @@ -351,7 +351,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 conn cleanup: %08XD %d", node->key, lc->conn); + "limit conn cleanup: %08Xi %d", node->key, lc->conn); lc->conn--; diff --git a/src/http/modules/ngx_http_map_module.c b/src/http/modules/ngx_http_map_module.c index 2b80d0f..091ff09 100644 --- a/src/http/modules/ngx_http_map_module.c +++ b/src/http/modules/ngx_http_map_module.c @@ -141,7 +141,7 @@ ngx_http_map_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, *v = *value; ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http map: \"%v\" \"%v\"", &val, v); + "http map: \"%V\" \"%v\"", &val, v); return NGX_OK; } diff --git a/src/http/modules/ngx_http_memcached_module.c b/src/http/modules/ngx_http_memcached_module.c index 8341b92..d31996a 100644 --- a/src/http/modules/ngx_http_memcached_module.c +++ b/src/http/modules/ngx_http_memcached_module.c @@ -523,7 +523,7 @@ ngx_http_memcached_filter(void *data, ssize_t bytes) cl->buf->tag = u->output.tag; ngx_log_debug4(NGX_LOG_DEBUG_HTTP, ctx->request->connection->log, 0, - "memcached filter bytes:%z size:%z length:%z rest:%z", + "memcached filter bytes:%z size:%z length:%O rest:%z", bytes, b->last - b->pos, u->length, ctx->rest); if (bytes <= (ssize_t) (u->length - NGX_HTTP_MEMCACHED_END)) { diff --git a/src/http/modules/ngx_http_mp4_module.c b/src/http/modules/ngx_http_mp4_module.c index 980bf57..6cb3ccf 100644 --- a/src/http/modules/ngx_http_mp4_module.c +++ b/src/http/modules/ngx_http_mp4_module.c @@ -913,7 +913,7 @@ ngx_http_mp4_read_atom(ngx_http_mp4_file_t *mp4, ngx_log_debug4(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 atom: %*s @%O:%uL", - 4, atom_name, mp4->offset, atom_size); + (size_t) 4, atom_name, mp4->offset, atom_size); if (atom_size > (uint64_t) (NGX_MAX_OFF_T_VALUE - mp4->offset) || mp4->offset + (off_t) atom_size > end) @@ -1958,7 +1958,7 @@ ngx_http_mp4_read_stsd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size) ngx_log_debug3(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "stsd entries:%uD, media:%*s", ngx_mp4_get_32value(stsd_atom->entries), - 4, stsd_atom->media_name); + (size_t) 4, stsd_atom->media_name); trak = ngx_mp4_last_trak(mp4); @@ -2555,14 +2555,14 @@ ngx_http_mp4_crop_ctts_data(ngx_http_mp4_file_t *mp4, "sample:%uD, count:%uD, offset:%uD", start_sample, count, ngx_mp4_get_32value(entry->offset)); - if (start_sample <= count) { - rest = start_sample - 1; - goto found; - } + if (start_sample <= count) { + rest = start_sample - 1; + goto found; + } - start_sample -= count; - entries--; - entry++; + start_sample -= count; + entries--; + entry++; } if (start) { diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c index 5005b6b..c24ef17 100644 --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -1559,7 +1559,7 @@ ngx_http_proxy_body_output_filter(void *data, ngx_chain_t *in) for ( ;; ) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "proxy output chunk: %d", ngx_buf_size(cl->buf)); + "proxy output chunk: %O", ngx_buf_size(cl->buf)); size += ngx_buf_size(cl->buf); @@ -1917,7 +1917,7 @@ ngx_http_proxy_input_filter_init(void *data) } ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http proxy filter init s:%d h:%d c:%d l:%O", + "http proxy filter init s:%ui h:%d c:%d l:%O", u->headers_in.status_n, ctx->head, u->headers_in.chunked, u->headers_in.content_length_n); @@ -2125,7 +2125,7 @@ ngx_http_proxy_chunked_filter(ngx_event_pipe_t *p, ngx_buf_t *buf) } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http proxy chunked state %d, length %d", + "http proxy chunked state %ui, length %O", ctx->chunked.state, p->length); if (b) { @@ -2299,7 +2299,7 @@ ngx_http_proxy_non_buffered_chunked_filter(void *data, ssize_t bytes) for (cl = u->out_bufs; cl; cl = cl->next) { ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http proxy in memory %p-%p %uz", + "http proxy in memory %p-%p %O", cl->buf->pos, cl->buf->last, ngx_buf_size(cl->buf)); if (buf->last == cl->buf->pos) { diff --git a/src/http/modules/ngx_http_random_index_module.c b/src/http/modules/ngx_http_random_index_module.c index b0f0e08..b47ee4f 100644 --- a/src/http/modules/ngx_http_random_index_module.c +++ b/src/http/modules/ngx_http_random_index_module.c @@ -230,7 +230,7 @@ ngx_http_random_index_handler(ngx_http_request_t *r) if (ngx_close_dir(&dir) == NGX_ERROR) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, - ngx_close_dir_n " \"%s\" failed", &path); + ngx_close_dir_n " \"%V\" failed", &path); } n = names.nelts; diff --git a/src/http/modules/ngx_http_range_filter_module.c b/src/http/modules/ngx_http_range_filter_module.c index b07b2e2..57065e1 100644 --- a/src/http/modules/ngx_http_range_filter_module.c +++ b/src/http/modules/ngx_http_range_filter_module.c @@ -207,7 +207,7 @@ ngx_http_range_header_filter(ngx_http_request_t *r) if_range_time = ngx_parse_http_time(if_range->data, if_range->len); ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http ir:%d lm:%d", + "http ir:%T lm:%T", if_range_time, r->headers_out.last_modified_time); if (if_range_time != r->headers_out.last_modified_time) { @@ -665,7 +665,7 @@ ngx_http_range_test_overlapped(ngx_http_request_t *r, range = ctx->ranges.elts; for (i = 0; i < ctx->ranges.nelts; i++) { if (start > range[i].start || last < range[i].end) { - goto overlapped; + goto overlapped; } } } diff --git a/src/http/modules/ngx_http_realip_module.c b/src/http/modules/ngx_http_realip_module.c index c3d7ebe..b7befe6 100644 --- a/src/http/modules/ngx_http_realip_module.c +++ b/src/http/modules/ngx_http_realip_module.c @@ -328,8 +328,8 @@ ngx_http_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) #if (NGX_HAVE_UNIX_DOMAIN) if (ngx_strcmp(value[1].data, "unix:") == 0) { - cidr->family = AF_UNIX; - return NGX_CONF_OK; + cidr->family = AF_UNIX; + return NGX_CONF_OK; } #endif diff --git a/src/http/modules/ngx_http_referer_module.c b/src/http/modules/ngx_http_referer_module.c index b417eb2..3f0f78e 100644 --- a/src/http/modules/ngx_http_referer_module.c +++ b/src/http/modules/ngx_http_referer_module.c @@ -109,7 +109,7 @@ ngx_module_t ngx_http_referer_module = { static ngx_int_t ngx_http_referer_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, - uintptr_t data) + uintptr_t data) { u_char *p, *ref, *last; size_t len; diff --git a/src/http/modules/ngx_http_rewrite_module.c b/src/http/modules/ngx_http_rewrite_module.c index 2ec7f5d..6b2444c 100644 --- a/src/http/modules/ngx_http_rewrite_module.c +++ b/src/http/modules/ngx_http_rewrite_module.c @@ -571,7 +571,7 @@ ngx_http_rewrite_if(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) mconf = module->create_loc_conf(cf); if (mconf == NULL) { - return NGX_CONF_ERROR; + return NGX_CONF_ERROR; } ctx->loc_conf[cf->cycle->modules[i]->ctx_index] = mconf; diff --git a/src/http/modules/ngx_http_scgi_module.c b/src/http/modules/ngx_http_scgi_module.c index b468eb7..f09617e 100644 --- a/src/http/modules/ngx_http_scgi_module.c +++ b/src/http/modules/ngx_http_scgi_module.c @@ -876,7 +876,7 @@ ngx_http_scgi_create_request(ngx_http_request_t *r) next: continue; - } + } } *b->last++ = (u_char) ','; diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c index 8236320..b997aaa 100644 --- a/src/http/modules/ngx_http_ssi_filter_module.c +++ b/src/http/modules/ngx_http_ssi_filter_module.c @@ -468,12 +468,12 @@ ngx_http_ssi_body_filter(ngx_http_request_t *r, ngx_chain_t *in) while (ctx->pos < ctx->buf->last) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "saved: %d state: %d", ctx->saved, ctx->state); + "saved: %uz state: %ui", ctx->saved, ctx->state); rc = ngx_http_ssi_parse(r, ctx); ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "parse: %d, looked: %d %p-%p", + "parse: %i, looked: %uz %p-%p", rc, ctx->looked, ctx->copy_start, ctx->copy_end); if (rc == NGX_ERROR) { @@ -485,7 +485,7 @@ ngx_http_ssi_body_filter(ngx_http_request_t *r, ngx_chain_t *in) if (ctx->output) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "saved: %d", ctx->saved); + "saved: %uz", ctx->saved); if (ctx->saved) { @@ -1911,7 +1911,7 @@ ngx_http_ssi_regex_match(ngx_http_request_t *r, ngx_str_t *pattern, if (rc < NGX_REGEX_NO_MATCHED) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, - ngx_regex_exec_n " failed: %i on \"%V\" using \"%V\"", + ngx_regex_exec_n " failed: %d on \"%V\" using \"%V\"", rc, str, pattern); return NGX_HTTP_SSI_ERROR; } diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c index 7b051ea..6a4108c 100644 --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -337,8 +337,9 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out, #if (NGX_DEBUG) for (i = 0; i < inlen; i += in[i] + 1) { - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, - "SSL ALPN supported by client: %*s", in[i], &in[i + 1]); + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, + "SSL ALPN supported by client: %*s", + (size_t) in[i], &in[i + 1]); } #endif @@ -365,7 +366,7 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out, } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, - "SSL ALPN selected: %*s", *outlen, *out); + "SSL ALPN selected: %*s", (size_t) *outlen, *out); return SSL_TLSEXT_ERR_OK; } @@ -717,7 +718,7 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); } -#ifndef LIBRESSL_VERSION_NUMBER +#if (OPENSSL_VERSION_NUMBER < 0x10100001L && !defined LIBRESSL_VERSION_NUMBER) /* a temporary 512-bit RSA key is required for export versions of MSIE */ SSL_CTX_set_tmp_rsa_callback(conf->ssl.ctx, ngx_ssl_rsa512_key_callback); #endif diff --git a/src/http/modules/ngx_http_sub_filter_module.c b/src/http/modules/ngx_http_sub_filter_module.c index 7bf6e19..bb1c50b 100644 --- a/src/http/modules/ngx_http_sub_filter_module.c +++ b/src/http/modules/ngx_http_sub_filter_module.c @@ -341,7 +341,7 @@ ngx_http_sub_body_filter(ngx_http_request_t *r, ngx_chain_t *in) rc = ngx_http_sub_parse(r, ctx); ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "parse: %d, looked: \"%V\" %p-%p", + "parse: %i, looked: \"%V\" %p-%p", rc, &ctx->looked, ctx->copy_start, ctx->copy_end); if (rc == NGX_ERROR) { diff --git a/src/http/modules/ngx_http_upstream_ip_hash_module.c b/src/http/modules/ngx_http_upstream_ip_hash_module.c index 401b58e..8a5f0fa 100644 --- a/src/http/modules/ngx_http_upstream_ip_hash_module.c +++ b/src/http/modules/ngx_http_upstream_ip_hash_module.c @@ -199,7 +199,7 @@ ngx_http_upstream_get_ip_hash_peer(ngx_peer_connection_t *pc, void *data) } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0, - "get ip hash peer, hash: %ui %04XA", p, m); + "get ip hash peer, hash: %ui %04XL", p, (uint64_t) m); if (peer->down) { goto next; diff --git a/src/http/modules/ngx_http_upstream_least_conn_module.c b/src/http/modules/ngx_http_upstream_least_conn_module.c index 92951bd..8a300c1 100644 --- a/src/http/modules/ngx_http_upstream_least_conn_module.c +++ b/src/http/modules/ngx_http_upstream_least_conn_module.c @@ -259,7 +259,7 @@ failed: / (8 * sizeof(uintptr_t)); for (i = 0; i < n; i++) { - rrp->tried[i] = 0; + rrp->tried[i] = 0; } ngx_http_upstream_rr_peers_unlock(peers); diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index b88e869..bd36aec 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -1222,7 +1222,7 @@ ngx_http_core_try_files_phase(ngx_http_request_t *r, } name = path.data + root; - } + } if (tf->values == NULL) { @@ -1597,7 +1597,8 @@ ngx_http_core_find_static_location(ngx_http_request_t *r, } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "test location: \"%*s\"", node->len, node->name); + "test location: \"%*s\"", + (size_t) node->len, node->name); n = (len <= (size_t) node->len) ? len : node->len; @@ -3104,7 +3105,7 @@ ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) ctx->loc_conf[cf->cycle->modules[i]->ctx_index] = module->create_loc_conf(cf); if (ctx->loc_conf[cf->cycle->modules[i]->ctx_index] == NULL) { - return NGX_CONF_ERROR; + return NGX_CONF_ERROR; } } } @@ -4540,21 +4541,21 @@ ngx_http_core_root(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) static ngx_http_method_name_t ngx_methods_names[] = { - { (u_char *) "GET", (uint32_t) ~NGX_HTTP_GET }, - { (u_char *) "HEAD", (uint32_t) ~NGX_HTTP_HEAD }, - { (u_char *) "POST", (uint32_t) ~NGX_HTTP_POST }, - { (u_char *) "PUT", (uint32_t) ~NGX_HTTP_PUT }, - { (u_char *) "DELETE", (uint32_t) ~NGX_HTTP_DELETE }, - { (u_char *) "MKCOL", (uint32_t) ~NGX_HTTP_MKCOL }, - { (u_char *) "COPY", (uint32_t) ~NGX_HTTP_COPY }, - { (u_char *) "MOVE", (uint32_t) ~NGX_HTTP_MOVE }, - { (u_char *) "OPTIONS", (uint32_t) ~NGX_HTTP_OPTIONS }, - { (u_char *) "PROPFIND", (uint32_t) ~NGX_HTTP_PROPFIND }, - { (u_char *) "PROPPATCH", (uint32_t) ~NGX_HTTP_PROPPATCH }, - { (u_char *) "LOCK", (uint32_t) ~NGX_HTTP_LOCK }, - { (u_char *) "UNLOCK", (uint32_t) ~NGX_HTTP_UNLOCK }, - { (u_char *) "PATCH", (uint32_t) ~NGX_HTTP_PATCH }, - { NULL, 0 } + { (u_char *) "GET", (uint32_t) ~NGX_HTTP_GET }, + { (u_char *) "HEAD", (uint32_t) ~NGX_HTTP_HEAD }, + { (u_char *) "POST", (uint32_t) ~NGX_HTTP_POST }, + { (u_char *) "PUT", (uint32_t) ~NGX_HTTP_PUT }, + { (u_char *) "DELETE", (uint32_t) ~NGX_HTTP_DELETE }, + { (u_char *) "MKCOL", (uint32_t) ~NGX_HTTP_MKCOL }, + { (u_char *) "COPY", (uint32_t) ~NGX_HTTP_COPY }, + { (u_char *) "MOVE", (uint32_t) ~NGX_HTTP_MOVE }, + { (u_char *) "OPTIONS", (uint32_t) ~NGX_HTTP_OPTIONS }, + { (u_char *) "PROPFIND", (uint32_t) ~NGX_HTTP_PROPFIND }, + { (u_char *) "PROPPATCH", (uint32_t) ~NGX_HTTP_PROPPATCH }, + { (u_char *) "LOCK", (uint32_t) ~NGX_HTTP_LOCK }, + { (u_char *) "UNLOCK", (uint32_t) ~NGX_HTTP_UNLOCK }, + { (u_char *) "PATCH", (uint32_t) ~NGX_HTTP_PATCH }, + { NULL, 0 } }; @@ -4627,7 +4628,7 @@ ngx_http_core_limit_except(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) mconf = module->create_loc_conf(cf); if (mconf == NULL) { - return NGX_CONF_ERROR; + return NGX_CONF_ERROR; } ctx->loc_conf[cf->cycle->modules[i]->ctx_index] = mconf; diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h index 231c507..6c446a0 100644 --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -232,10 +232,10 @@ typedef struct { typedef struct { - ngx_hash_combined_t names; + ngx_hash_combined_t names; - ngx_uint_t nregex; - ngx_http_server_name_t *regex; + ngx_uint_t nregex; + ngx_http_server_name_t *regex; } ngx_http_virtual_names_t; @@ -544,7 +544,7 @@ typedef ngx_int_t (*ngx_http_request_body_filter_pt) ngx_int_t ngx_http_output_filter(ngx_http_request_t *r, ngx_chain_t *chain); ngx_int_t ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *chain); ngx_int_t ngx_http_request_body_save_filter(ngx_http_request_t *r, - ngx_chain_t *chain); + ngx_chain_t *chain); ngx_int_t ngx_http_set_disable_symlinks(ngx_http_request_t *r, diff --git a/src/http/ngx_http_file_cache.c b/src/http/ngx_http_file_cache.c index 3561028..37cd377 100644 --- a/src/http/ngx_http_file_cache.c +++ b/src/http/ngx_http_file_cache.c @@ -1834,7 +1834,7 @@ ngx_http_file_cache_expire(ngx_http_file_cache_t *cache) ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, "ignore long locked inactive cache entry %*s, count:%d", - 2 * NGX_HTTP_CACHE_KEY_LEN, key, fcn->count); + (size_t) 2 * NGX_HTTP_CACHE_KEY_LEN, key, fcn->count); } ngx_shmtx_unlock(&cache->shpool->mutex); diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c index fd790e1..7d6cada 100644 --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -648,7 +648,7 @@ ngx_http_ssl_handshake(ngx_event_t *rev) err = ngx_socket_errno; - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0, "http recv(): %d", n); + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0, "http recv(): %z", n); if (n == -1) { if (err == NGX_EAGAIN) { @@ -1500,7 +1500,7 @@ ngx_http_alloc_large_header_buffer(ngx_http_request_t *r, } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http large header copy: %d", r->header_in->pos - old); + "http large header copy: %uz", r->header_in->pos - old); new = b->start; @@ -2264,7 +2264,7 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc) c = r->connection; ngx_log_debug5(NGX_LOG_DEBUG_HTTP, c->log, 0, - "http finalize request: %d, \"%V?%V\" a:%d, c:%d", + "http finalize request: %i, \"%V?%V\" a:%d, c:%d", rc, &r->uri, &r->args, r == c->data, r->main->count); if (rc == NGX_DONE) { @@ -2956,7 +2956,7 @@ ngx_http_set_keepalive(ngx_http_request_t *r) b->last = b->start; } - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc free: %p %d", + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc free: %p %i", hc->free, hc->nfree); if (hc->free) { @@ -2968,7 +2968,7 @@ ngx_http_set_keepalive(ngx_http_request_t *r) hc->nfree = 0; } - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc busy: %p %d", + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc busy: %p %i", hc->busy, hc->nbusy); if (hc->busy) { @@ -3259,7 +3259,7 @@ ngx_http_lingering_close_handler(ngx_event_t *rev) do { n = c->recv(c, buffer, NGX_HTTP_LINGERING_BUFFER_SIZE); - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "lingering read: %d", n); + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "lingering read: %z", n); if (n == NGX_ERROR || n == 0) { ngx_http_close_request(r, 0); diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h index 8b88139..cfde7dc 100644 --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -284,6 +284,9 @@ typedef struct { ngx_chain_t *bufs; ngx_buf_t *buf; off_t rest; +#if (NGX_HTTP_V2) + off_t received; +#endif ngx_chain_t *free; ngx_chain_t *busy; ngx_http_chunked_t *chunked; diff --git a/src/http/ngx_http_request_body.c b/src/http/ngx_http_request_body.c index b5803d5..0641329 100644 --- a/src/http/ngx_http_request_body.c +++ b/src/http/ngx_http_request_body.c @@ -40,20 +40,19 @@ ngx_http_read_client_request_body(ngx_http_request_t *r, r->main->count++; -#if (NGX_HTTP_V2) - if (r->stream && r == r->main) { - r->request_body_no_buffering = 0; - rc = ngx_http_v2_read_request_body(r, post_handler); - goto done; - } -#endif - if (r != r->main || r->request_body || r->discard_body) { r->request_body_no_buffering = 0; post_handler(r); return NGX_OK; } +#if (NGX_HTTP_V2) + if (r->stream) { + rc = ngx_http_v2_read_request_body(r, post_handler); + goto done; + } +#endif + if (ngx_http_test_expect(r) != NGX_OK) { rc = NGX_HTTP_INTERNAL_SERVER_ERROR; goto done; @@ -215,6 +214,18 @@ ngx_http_read_unbuffered_request_body(ngx_http_request_t *r) { ngx_int_t rc; +#if (NGX_HTTP_V2) + if (r->stream) { + rc = ngx_http_v2_read_unbuffered_request_body(r); + + if (rc == NGX_OK) { + r->reading_body = 0; + } + + return rc; + } +#endif + if (r->connection->read->timedout) { r->connection->timedout = 1; return NGX_HTTP_REQUEST_TIME_OUT; @@ -503,17 +514,17 @@ ngx_http_discard_request_body(ngx_http_request_t *r) ngx_int_t rc; ngx_event_t *rev; -#if (NGX_HTTP_V2) - if (r->stream && r == r->main) { - r->stream->skip_data = NGX_HTTP_V2_DATA_DISCARD; - return NGX_OK; - } -#endif - if (r != r->main || r->discard_body || r->request_body) { return NGX_OK; } +#if (NGX_HTTP_V2) + if (r->stream) { + r->stream->skip_data = 1; + return NGX_OK; + } +#endif + if (ngx_http_test_expect(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c index 02e2be3..bff9525 100644 --- a/src/http/ngx_http_script.c +++ b/src/http/ngx_http_script.c @@ -19,10 +19,10 @@ static ngx_int_t ngx_http_script_add_var_code(ngx_http_script_compile_t *sc, static ngx_int_t ngx_http_script_add_args_code(ngx_http_script_compile_t *sc); #if (NGX_PCRE) static ngx_int_t ngx_http_script_add_capture_code(ngx_http_script_compile_t *sc, - ngx_uint_t n); + ngx_uint_t n); #endif static ngx_int_t - ngx_http_script_add_full_name_code(ngx_http_script_compile_t *sc); + ngx_http_script_add_full_name_code(ngx_http_script_compile_t *sc); static size_t ngx_http_script_full_name_len_code(ngx_http_script_engine_t *e); static void ngx_http_script_full_name_code(ngx_http_script_engine_t *e); @@ -1488,7 +1488,7 @@ ngx_http_script_file_code(ngx_http_script_engine_t *e) r = e->request; ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http script file op %p \"%V\"", code->op, &path); + "http script file op %p \"%V\"", (void *) code->op, &path); clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c index 911049f..1386bdb 100644 --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -1883,17 +1883,17 @@ ngx_http_upstream_send_request_body(ngx_http_request_t *r, if (!r->request_body_no_buffering) { - /* buffered request body */ + /* buffered request body */ - if (!u->request_sent) { - u->request_sent = 1; - out = u->request_bufs; + if (!u->request_sent) { + u->request_sent = 1; + out = u->request_bufs; - } else { - out = NULL; - } + } else { + out = NULL; + } - return ngx_output_chain(&u->output, out); + return ngx_output_chain(&u->output, out); } if (!u->request_sent) { @@ -4327,10 +4327,10 @@ ngx_http_upstream_process_cache_control(ngx_http_request_t *r, pa = &u->headers_in.cache_control; if (pa->elts == NULL) { - if (ngx_array_init(pa, r->pool, 2, sizeof(ngx_table_elt_t *)) != NGX_OK) - { - return NGX_ERROR; - } + if (ngx_array_init(pa, r->pool, 2, sizeof(ngx_table_elt_t *)) != NGX_OK) + { + return NGX_ERROR; + } } ph = ngx_array_push(pa); diff --git a/src/http/ngx_http_upstream_round_robin.c b/src/http/ngx_http_upstream_round_robin.c index d6ae33b..8342dc8 100644 --- a/src/http/ngx_http_upstream_round_robin.c +++ b/src/http/ngx_http_upstream_round_robin.c @@ -480,7 +480,7 @@ failed: / (8 * sizeof(uintptr_t)); for (i = 0; i < n; i++) { - rrp->tried[i] = 0; + rrp->tried[i] = 0; } ngx_http_upstream_rr_peers_unlock(peers); diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c index eaf294a..f8271ab 100644 --- a/src/http/ngx_http_variables.c +++ b/src/http/ngx_http_variables.c @@ -2428,9 +2428,8 @@ ngx_http_regex_exec(ngx_http_request_t *r, ngx_http_regex_t *re, ngx_str_t *s) v = cmcf->variables.elts; - ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http regex set $%V to \"%*s\"", - &v[index].name, vv->len, vv->data); + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http regex set $%V to \"%v\"", &v[index].name, vv); } #endif } diff --git a/src/http/ngx_http_write_filter_module.c b/src/http/ngx_http_write_filter_module.c index c164440..0036231 100644 --- a/src/http/ngx_http_write_filter_module.c +++ b/src/http/ngx_http_write_filter_module.c @@ -174,7 +174,7 @@ ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in) *ll = NULL; ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0, - "http write filter: l:%d f:%d s:%O", last, flush, size); + "http write filter: l:%ui f:%ui s:%O", last, flush, size); clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c index ababd4b..4bd85b8 100644 --- a/src/http/v2/ngx_http_v2.c +++ b/src/http/v2/ngx_http_v2.c @@ -51,6 +51,8 @@ #define NGX_HTTP_V2_MAX_WINDOW ((1U << 31) - 1) #define NGX_HTTP_V2_DEFAULT_WINDOW 65535 +#define NGX_HTTP_V2_INITIAL_WINDOW 0 + #define NGX_HTTP_V2_ROOT (void *) -1 @@ -163,7 +165,9 @@ static ngx_int_t ngx_http_v2_cookie(ngx_http_request_t *r, ngx_http_v2_header_t *header); static ngx_int_t ngx_http_v2_construct_cookie_header(ngx_http_request_t *r); static void ngx_http_v2_run_request(ngx_http_request_t *r); -static ngx_int_t ngx_http_v2_init_request_body(ngx_http_request_t *r); +static ngx_int_t ngx_http_v2_process_request_body(ngx_http_request_t *r, + u_char *pos, size_t size, ngx_uint_t last); +static ngx_int_t ngx_http_v2_filter_request_body(ngx_http_request_t *r); static void ngx_http_v2_read_client_request_body_handler(ngx_http_request_t *r); static ngx_int_t ngx_http_v2_terminate_stream(ngx_http_v2_connection_t *h2c, @@ -762,8 +766,7 @@ ngx_http_v2_state_data(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end) if (h2c->state.length == 0) { ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, "client sent padded DATA frame " - "with incorrect length: %uz", - h2c->state.length); + "with incorrect length: 0"); return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR); } @@ -845,8 +848,9 @@ ngx_http_v2_state_data(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end) stream->recv_window -= h2c->state.length; - if (stream->recv_window < NGX_HTTP_V2_MAX_WINDOW / 4) { - + if (stream->no_flow_control + && stream->recv_window < NGX_HTTP_V2_MAX_WINDOW / 4) + { if (ngx_http_v2_send_window_update(h2c, node->id, NGX_HTTP_V2_MAX_WINDOW - stream->recv_window) @@ -875,6 +879,8 @@ ngx_http_v2_state_data(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end) return ngx_http_v2_state_skip_padded(h2c, pos, end); } + stream->in_closed = h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG; + h2c->state.stream = stream; return ngx_http_v2_state_read_data(h2c, pos, end); @@ -885,16 +891,10 @@ static u_char * ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end) { - size_t size; - ssize_t n; - ngx_buf_t *buf; - ngx_int_t rc; - ngx_temp_file_t *tf; - ngx_connection_t *fc; - ngx_http_request_t *r; - ngx_http_v2_stream_t *stream; - ngx_http_request_body_t *rb; - ngx_http_core_loc_conf_t *clcf; + size_t size; + ngx_int_t rc; + ngx_uint_t last; + ngx_http_v2_stream_t *stream; stream = h2c->state.stream; @@ -903,168 +903,42 @@ ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos, } if (stream->skip_data) { - stream->in_closed = h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG; - - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "skipping http2 DATA frame, reason: %d", - stream->skip_data); + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "skipping http2 DATA frame"); return ngx_http_v2_state_skip_padded(h2c, pos, end); } size = end - pos; - if (size > h2c->state.length) { + if (size >= h2c->state.length) { size = h2c->state.length; + last = stream->in_closed; + + } else { + last = 0; } - r = stream->request; + rc = ngx_http_v2_process_request_body(stream->request, pos, size, last); - if (r->request_body == NULL - && ngx_http_v2_init_request_body(r) != NGX_OK) - { - stream->skip_data = NGX_HTTP_V2_DATA_INTERNAL_ERROR; - return ngx_http_v2_state_skip_padded(h2c, pos, end); + if (rc != NGX_OK) { + stream->skip_data = 1; + ngx_http_finalize_request(stream->request, rc); } - fc = r->connection; - rb = r->request_body; - tf = rb->temp_file; - buf = rb->buf; - - if (size) { - rb->rest += size; - - if (r->headers_in.content_length_n != -1 - && r->headers_in.content_length_n < rb->rest) - { - ngx_log_error(NGX_LOG_INFO, fc->log, 0, - "client intended to send body data " - "larger than declared"); - - stream->skip_data = NGX_HTTP_V2_DATA_ERROR; - goto error; - - } else { - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - - if (clcf->client_max_body_size - && clcf->client_max_body_size < rb->rest) - { - ngx_log_error(NGX_LOG_ERR, fc->log, 0, - "client intended to send " - "too large chunked body: %O bytes", rb->rest); - - stream->skip_data = NGX_HTTP_V2_DATA_ERROR; - goto error; - } - } - - h2c->state.length -= size; - - if (tf) { - buf->start = pos; - buf->pos = pos; - - pos += size; - - buf->end = pos; - buf->last = pos; - - n = ngx_write_chain_to_temp_file(tf, rb->bufs); - - /* TODO: n == 0 or not complete and level event */ - - if (n == NGX_ERROR) { - stream->skip_data = NGX_HTTP_V2_DATA_INTERNAL_ERROR; - goto error; - } - - tf->offset += n; - - } else { - buf->last = ngx_cpymem(buf->last, pos, size); - pos += size; - } - - r->request_length += size; - } + pos += size; + h2c->state.length -= size; if (h2c->state.length) { - if (rb->post_handler) { - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - ngx_add_timer(fc->read, clcf->client_body_timeout); - } - return ngx_http_v2_state_save(h2c, pos, end, ngx_http_v2_state_read_data); } - if (h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG) { - stream->in_closed = 1; - - if (r->headers_in.content_length_n < 0) { - r->headers_in.content_length_n = rb->rest; - - } else if (r->headers_in.content_length_n != rb->rest) { - ngx_log_error(NGX_LOG_INFO, fc->log, 0, - "client prematurely closed stream: " - "only %O out of %O bytes of request body received", - rb->rest, r->headers_in.content_length_n); - - stream->skip_data = NGX_HTTP_V2_DATA_ERROR; - goto error; - } - - if (tf) { - ngx_memzero(buf, sizeof(ngx_buf_t)); - - buf->in_file = 1; - buf->file_last = tf->file.offset; - buf->file = &tf->file; - - rb->buf = NULL; - } - - if (rb->post_handler) { - if (fc->read->timer_set) { - ngx_del_timer(fc->read); - } - - r->read_event_handler = ngx_http_block_reading; - rb->post_handler(r); - } - - } else if (rb->post_handler) { - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - ngx_add_timer(fc->read, clcf->client_body_timeout); - } - if (h2c->state.padding) { return ngx_http_v2_state_skip_padded(h2c, pos, end); } return ngx_http_v2_state_complete(h2c, pos, end); - -error: - - if (rb->post_handler) { - if (fc->read->timer_set) { - ngx_del_timer(fc->read); - } - - if (stream->skip_data == NGX_HTTP_V2_DATA_ERROR) { - rc = (r->headers_in.content_length_n == -1) - ? NGX_HTTP_REQUEST_ENTITY_TOO_LARGE : NGX_HTTP_BAD_REQUEST; - - } else { - rc = NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - ngx_http_finalize_request(r, rc); - } - - return ngx_http_v2_state_skip_padded(h2c, pos, end); } @@ -2124,7 +1998,7 @@ ngx_http_v2_state_ping(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end) } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "http2 PING frame, flags: %ui", h2c->state.flags); + "http2 PING frame, flags: %ud", h2c->state.flags); if (h2c->state.flags & NGX_HTTP_V2_ACK_FLAG) { return ngx_http_v2_state_skip(h2c, pos, end); @@ -2556,7 +2430,7 @@ ngx_http_v2_send_settings(ngx_http_v2_connection_t *h2c, ngx_uint_t ack) buf->last = ngx_http_v2_write_uint16(buf->last, NGX_HTTP_V2_INIT_WINDOW_SIZE_SETTING); buf->last = ngx_http_v2_write_uint32(buf->last, - NGX_HTTP_V2_MAX_WINDOW); + NGX_HTTP_V2_INITIAL_WINDOW); buf->last = ngx_http_v2_write_uint16(buf->last, NGX_HTTP_V2_MAX_FRAME_SIZE_SETTING); @@ -2878,7 +2752,7 @@ ngx_http_v2_create_stream(ngx_http_v2_connection_t *h2c) stream->connection = h2c; stream->send_window = h2c->init_window; - stream->recv_window = NGX_HTTP_V2_MAX_WINDOW; + stream->recv_window = NGX_HTTP_V2_INITIAL_WINDOW; h2c->processing++; @@ -3515,155 +3389,299 @@ ngx_http_v2_run_request(ngx_http_request_t *r) ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "client prematurely closed stream"); - r->stream->skip_data = NGX_HTTP_V2_DATA_ERROR; + r->stream->skip_data = 1; ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); return; } + r->headers_in.chunked = (r->headers_in.content_length_n == -1); + ngx_http_process_request(r); } -static ngx_int_t -ngx_http_v2_init_request_body(ngx_http_request_t *r) -{ - ngx_buf_t *buf; - ngx_temp_file_t *tf; - ngx_http_request_body_t *rb; - ngx_http_core_loc_conf_t *clcf; - - rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t)); - if (rb == NULL) { - return NGX_ERROR; - } - - r->request_body = rb; - - if (r->stream->in_closed) { - return NGX_OK; - } - - rb->rest = r->headers_in.content_length_n; - - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - - if (r->request_body_in_file_only - || rb->rest > (off_t) clcf->client_body_buffer_size - || rb->rest < 0) - { - tf = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t)); - if (tf == NULL) { - return NGX_ERROR; - } - - tf->file.fd = NGX_INVALID_FILE; - tf->file.log = r->connection->log; - tf->path = clcf->client_body_temp_path; - tf->pool = r->pool; - tf->warn = "a client request body is buffered to a temporary file"; - tf->log_level = r->request_body_file_log_level; - tf->persistent = r->request_body_in_persistent_file; - tf->clean = r->request_body_in_clean_file; - - if (r->request_body_file_group_access) { - tf->access = 0660; - } - - rb->temp_file = tf; - - if (r->stream->in_closed - && ngx_create_temp_file(&tf->file, tf->path, tf->pool, - tf->persistent, tf->clean, tf->access) - != NGX_OK) - { - return NGX_ERROR; - } - - buf = ngx_calloc_buf(r->pool); - if (buf == NULL) { - return NGX_ERROR; - } - - } else { - - if (rb->rest == 0) { - return NGX_OK; - } - - buf = ngx_create_temp_buf(r->pool, (size_t) rb->rest); - if (buf == NULL) { - return NGX_ERROR; - } - } - - rb->buf = buf; - - rb->bufs = ngx_alloc_chain_link(r->pool); - if (rb->bufs == NULL) { - return NGX_ERROR; - } - - rb->bufs->buf = buf; - rb->bufs->next = NULL; - - rb->rest = 0; - - return NGX_OK; -} - - ngx_int_t ngx_http_v2_read_request_body(ngx_http_request_t *r, ngx_http_client_body_handler_pt post_handler) { + off_t len; ngx_http_v2_stream_t *stream; + ngx_http_request_body_t *rb; ngx_http_core_loc_conf_t *clcf; - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http2 read request body"); - stream = r->stream; - switch (stream->skip_data) { - - case NGX_HTTP_V2_DATA_DISCARD: + if (stream->skip_data) { + r->request_body_no_buffering = 0; post_handler(r); return NGX_OK; + } - case NGX_HTTP_V2_DATA_ERROR: - if (r->headers_in.content_length_n == -1) { - return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE; - } else { - return NGX_HTTP_BAD_REQUEST; - } - - case NGX_HTTP_V2_DATA_INTERNAL_ERROR: + rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t)); + if (rb == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } - if (!r->request_body && ngx_http_v2_init_request_body(r) != NGX_OK) { - stream->skip_data = NGX_HTTP_V2_DATA_INTERNAL_ERROR; + /* + * set by ngx_pcalloc(): + * + * rb->bufs = NULL; + * rb->buf = NULL; + * rb->received = 0; + * rb->free = NULL; + * rb->busy = NULL; + */ + + rb->rest = 1; + rb->post_handler = post_handler; + + r->request_body = rb; + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + len = r->headers_in.content_length_n; + + if (r->request_body_no_buffering && !stream->in_closed) { + r->request_body_in_file_only = 0; + + if (len < 0 || len > (off_t) clcf->client_body_buffer_size) { + len = clcf->client_body_buffer_size; + } + + if (len > NGX_HTTP_V2_MAX_WINDOW) { + len = NGX_HTTP_V2_MAX_WINDOW; + } + } + + if (len >= 0 && len <= (off_t) clcf->client_body_buffer_size + && !r->request_body_in_file_only) + { + rb->buf = ngx_create_temp_buf(r->pool, (size_t) len); + + } else { + rb->buf = ngx_calloc_buf(r->pool); + + if (rb->buf != NULL) { + rb->buf->sync = 1; + } + } + + if (rb->buf == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (stream->in_closed) { - post_handler(r); - return NGX_OK; + r->request_body_no_buffering = 0; + return ngx_http_v2_process_request_body(r, NULL, 0, 1); } - r->request_body->post_handler = post_handler; + if (r->request_body_no_buffering) { + stream->no_flow_control = 0; + stream->recv_window = (size_t) len; + + } else { + stream->no_flow_control = 1; + stream->recv_window = NGX_HTTP_V2_MAX_WINDOW; + } + + if (ngx_http_v2_send_window_update(stream->connection, stream->node->id, + stream->recv_window) + == NGX_ERROR) + { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + ngx_add_timer(r->connection->read, clcf->client_body_timeout); r->read_event_handler = ngx_http_v2_read_client_request_body_handler; r->write_event_handler = ngx_http_request_empty_handler; - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - ngx_add_timer(r->connection->read, clcf->client_body_timeout); - return NGX_AGAIN; } +static ngx_int_t +ngx_http_v2_process_request_body(ngx_http_request_t *r, u_char *pos, + size_t size, ngx_uint_t last) +{ + ngx_buf_t *buf; + ngx_int_t rc; + ngx_connection_t *fc; + ngx_http_request_body_t *rb; + ngx_http_core_loc_conf_t *clcf; + + rb = r->request_body; + + if (rb == NULL) { + return NGX_OK; + } + + fc = r->connection; + buf = rb->buf; + + if (size) { + if (buf->sync) { + buf->pos = buf->start = pos; + buf->last = buf->end = pos + size; + + } else { + if (size > (size_t) (buf->end - buf->last)) { + ngx_log_error(NGX_LOG_INFO, fc->log, 0, + "client intended to send body data " + "larger than declared"); + + return NGX_HTTP_BAD_REQUEST; + } + + buf->last = ngx_cpymem(buf->last, pos, size); + } + } + + if (last) { + rb->rest = 0; + + if (fc->read->timer_set) { + ngx_del_timer(fc->read); + } + + if (r->request_body_no_buffering) { + ngx_post_event(fc->read, &ngx_posted_events); + return NGX_OK; + } + + rc = ngx_http_v2_filter_request_body(r); + + if (rc != NGX_OK) { + return rc; + } + + if (buf->sync) { + /* prevent reusing this buffer in the upstream module */ + rb->buf = NULL; + } + + if (r->headers_in.content_length_n == -1) { + r->headers_in.content_length_n = rb->received; + } + + r->read_event_handler = ngx_http_block_reading; + rb->post_handler(r); + + return NGX_OK; + } + + if (size == 0) { + return NGX_OK; + } + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + ngx_add_timer(fc->read, clcf->client_body_timeout); + + if (r->request_body_no_buffering) { + ngx_post_event(fc->read, &ngx_posted_events); + return NGX_OK; + } + + if (buf->sync) { + return ngx_http_v2_filter_request_body(r); + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_v2_filter_request_body(ngx_http_request_t *r) +{ + ngx_buf_t *b, *buf; + ngx_int_t rc; + ngx_chain_t *cl; + ngx_http_request_body_t *rb; + ngx_http_core_loc_conf_t *clcf; + + rb = r->request_body; + buf = rb->buf; + + if (buf->pos == buf->last && rb->rest) { + cl = NULL; + goto update; + } + + cl = ngx_chain_get_free_buf(r->pool, &rb->free); + if (cl == NULL) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + b = cl->buf; + + ngx_memzero(b, sizeof(ngx_buf_t)); + + if (buf->pos != buf->last) { + r->request_length += buf->last - buf->pos; + rb->received += buf->last - buf->pos; + + if (r->headers_in.content_length_n != -1) { + if (rb->received > r->headers_in.content_length_n) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client intended to send body data " + "larger than declared"); + + return NGX_HTTP_BAD_REQUEST; + } + + } else { + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + if (clcf->client_max_body_size + && rb->received > clcf->client_max_body_size) + { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "client intended to send too large chunked body: " + "%O bytes", rb->received); + + return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE; + } + } + + b->temporary = 1; + b->pos = buf->pos; + b->last = buf->last; + b->start = b->pos; + b->end = b->last; + + buf->pos = buf->last; + } + + if (!rb->rest) { + if (r->headers_in.content_length_n != -1 + && r->headers_in.content_length_n != rb->received) + { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client prematurely closed stream: " + "only %O out of %O bytes of request body received", + rb->received, r->headers_in.content_length_n); + + return NGX_HTTP_BAD_REQUEST; + } + + b->last_buf = 1; + } + + b->tag = (ngx_buf_tag_t) &ngx_http_v2_filter_request_body; + b->flush = r->request_body_no_buffering; + +update: + + rc = ngx_http_top_request_body_filter(r, cl); + + ngx_chain_update_chains(r->pool, &rb->free, &rb->busy, &cl, + (ngx_buf_tag_t) &ngx_http_v2_filter_request_body); + + return rc; +} + + static void ngx_http_v2_read_client_request_body_handler(ngx_http_request_t *r) { @@ -3678,7 +3696,7 @@ ngx_http_v2_read_client_request_body_handler(ngx_http_request_t *r) ngx_log_error(NGX_LOG_INFO, fc->log, NGX_ETIMEDOUT, "client timed out"); fc->timedout = 1; - r->stream->skip_data = NGX_HTTP_V2_DATA_DISCARD; + r->stream->skip_data = 1; ngx_http_finalize_request(r, NGX_HTTP_REQUEST_TIME_OUT); return; @@ -3688,7 +3706,7 @@ ngx_http_v2_read_client_request_body_handler(ngx_http_request_t *r) ngx_log_error(NGX_LOG_INFO, fc->log, 0, "client prematurely closed stream"); - r->stream->skip_data = NGX_HTTP_V2_DATA_DISCARD; + r->stream->skip_data = 1; ngx_http_finalize_request(r, NGX_HTTP_CLIENT_CLOSED_REQUEST); return; @@ -3696,6 +3714,91 @@ ngx_http_v2_read_client_request_body_handler(ngx_http_request_t *r) } +ngx_int_t +ngx_http_v2_read_unbuffered_request_body(ngx_http_request_t *r) +{ + size_t window; + ngx_buf_t *buf; + ngx_int_t rc; + ngx_connection_t *fc; + ngx_http_v2_stream_t *stream; + ngx_http_v2_connection_t *h2c; + ngx_http_core_loc_conf_t *clcf; + + stream = r->stream; + fc = r->connection; + + if (fc->read->timedout) { + if (stream->recv_window) { + stream->skip_data = 1; + fc->timedout = 1; + + return NGX_HTTP_REQUEST_TIME_OUT; + } + + fc->read->timedout = 0; + } + + if (fc->error) { + stream->skip_data = 1; + return NGX_HTTP_BAD_REQUEST; + } + + rc = ngx_http_v2_filter_request_body(r); + + if (rc != NGX_OK) { + stream->skip_data = 1; + return rc; + } + + if (!r->request_body->rest) { + return NGX_OK; + } + + if (r->request_body->busy != NULL) { + return NGX_AGAIN; + } + + buf = r->request_body->buf; + + buf->pos = buf->start; + buf->last = buf->start; + + window = buf->end - buf->start; + h2c = stream->connection; + + if (h2c->state.stream == stream) { + window -= h2c->state.length; + } + + if (window == stream->recv_window) { + return NGX_AGAIN; + } + + if (ngx_http_v2_send_window_update(h2c, stream->node->id, + window - stream->recv_window) + == NGX_ERROR) + { + stream->skip_data = 1; + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + if (ngx_http_v2_send_output_queue(h2c) == NGX_ERROR) { + stream->skip_data = 1; + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + if (stream->recv_window == 0) { + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + ngx_add_timer(fc->read, clcf->client_body_timeout); + } + + stream->recv_window = window; + + return NGX_AGAIN; +} + + static ngx_int_t ngx_http_v2_terminate_stream(ngx_http_v2_connection_t *h2c, ngx_http_v2_stream_t *stream, ngx_uint_t status) @@ -3709,7 +3812,7 @@ ngx_http_v2_terminate_stream(ngx_http_v2_connection_t *h2c, return NGX_ERROR; } - stream->out_closed = 1; + stream->rst_sent = 1; fc = stream->request->connection; fc->error = 1; @@ -3744,13 +3847,23 @@ ngx_http_v2_close_stream(ngx_http_v2_stream_t *stream, ngx_int_t rc) return; } - if (!stream->out_closed) { - if (ngx_http_v2_send_rst_stream(h2c, node->id, - fc->timedout ? NGX_HTTP_V2_PROTOCOL_ERROR - : NGX_HTTP_V2_INTERNAL_ERROR) - != NGX_OK) - { - h2c->connection->error = 1; + if (!stream->rst_sent && !h2c->connection->error) { + + if (!stream->out_closed) { + if (ngx_http_v2_send_rst_stream(h2c, node->id, + fc->timedout ? NGX_HTTP_V2_PROTOCOL_ERROR + : NGX_HTTP_V2_INTERNAL_ERROR) + != NGX_OK) + { + h2c->connection->error = 1; + } + + } else if (!stream->in_closed) { + if (ngx_http_v2_send_rst_stream(h2c, node->id, NGX_HTTP_V2_NO_ERROR) + != NGX_OK) + { + h2c->connection->error = 1; + } } } @@ -3942,23 +4055,23 @@ ngx_http_v2_finalize_connection(ngx_http_v2_connection_t *h2c, c = h2c->connection; - if (h2c->state.stream) { - h2c->state.stream->out_closed = 1; - ngx_http_v2_close_stream(h2c->state.stream, NGX_HTTP_BAD_REQUEST); - } - h2c->blocked = 1; if (!c->error && ngx_http_v2_send_goaway(h2c, status) != NGX_ERROR) { (void) ngx_http_v2_send_output_queue(h2c); } + c->error = 1; + + if (h2c->state.stream) { + ngx_http_v2_close_stream(h2c->state.stream, NGX_HTTP_BAD_REQUEST); + } + if (!h2c->processing) { ngx_http_close_connection(c); return; } - c->error = 1; c->read->handler = ngx_http_empty_handler; c->write->handler = ngx_http_empty_handler; diff --git a/src/http/v2/ngx_http_v2.h b/src/http/v2/ngx_http_v2.h index 5a791e6..7a77c27 100644 --- a/src/http/v2/ngx_http_v2.h +++ b/src/http/v2/ngx_http_v2.h @@ -24,10 +24,6 @@ #define NGX_HTTP_V2_MAX_FIELD \ (127 + (1 << (NGX_HTTP_V2_INT_OCTETS - 1) * 7) - 1) -#define NGX_HTTP_V2_DATA_DISCARD 1 -#define NGX_HTTP_V2_DATA_ERROR 2 -#define NGX_HTTP_V2_DATA_INTERNAL_ERROR 3 - #define NGX_HTTP_V2_FRAME_HEADER_SIZE 9 /* frame types */ @@ -194,7 +190,9 @@ struct ngx_http_v2_stream_s { unsigned exhausted:1; unsigned in_closed:1; unsigned out_closed:1; - unsigned skip_data:2; + unsigned rst_sent:1; + unsigned no_flow_control:1; + unsigned skip_data:1; }; @@ -262,6 +260,7 @@ void ngx_http_v2_request_headers_init(void); ngx_int_t ngx_http_v2_read_request_body(ngx_http_request_t *r, ngx_http_client_body_handler_pt post_handler); +ngx_int_t ngx_http_v2_read_unbuffered_request_body(ngx_http_request_t *r); void ngx_http_v2_close_stream(ngx_http_v2_stream_t *stream, ngx_int_t rc); diff --git a/src/http/v2/ngx_http_v2_module.c b/src/http/v2/ngx_http_v2_module.c index d99ac30..5a4561c 100644 --- a/src/http/v2/ngx_http_v2_module.c +++ b/src/http/v2/ngx_http_v2_module.c @@ -215,7 +215,7 @@ static ngx_http_variable_t ngx_http_v2_vars[] = { static ngx_int_t ngx_http_v2_add_variables(ngx_conf_t *cf) { - ngx_http_variable_t *var, *v; + ngx_http_variable_t *var, *v; for (v = ngx_http_v2_vars; v->name.len; v++) { var = ngx_http_add_variable(cf, &v->name, v->flags); diff --git a/src/mail/ngx_mail.h b/src/mail/ngx_mail.h index 07d0cb6..bfbf768 100644 --- a/src/mail/ngx_mail.h +++ b/src/mail/ngx_mail.h @@ -342,7 +342,7 @@ typedef struct { void *(*create_srv_conf)(ngx_conf_t *cf); char *(*merge_srv_conf)(ngx_conf_t *cf, void *prev, - void *conf); + void *conf); } ngx_mail_module_t; diff --git a/src/mail/ngx_mail_auth_http_module.c b/src/mail/ngx_mail_auth_http_module.c index d93e946..39f9b17 100644 --- a/src/mail/ngx_mail_auth_http_module.c +++ b/src/mail/ngx_mail_auth_http_module.c @@ -431,7 +431,7 @@ ngx_mail_auth_http_ignore_status_line(ngx_mail_session_t *s, } ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, - "auth http server &V sent invalid response", + "auth http server %V sent invalid response", ctx->peer.name); ngx_close_connection(ctx->peer.connection); ngx_destroy_pool(ctx->pool); diff --git a/src/mail/ngx_mail_proxy_module.c b/src/mail/ngx_mail_proxy_module.c index 3802c3e..007284b 100644 --- a/src/mail/ngx_mail_proxy_module.c +++ b/src/mail/ngx_mail_proxy_module.c @@ -935,7 +935,7 @@ ngx_mail_proxy_handler(ngx_event_t *ev) do_write = ev->write ? 1 : 0; ngx_log_debug3(NGX_LOG_DEBUG_MAIL, ev->log, 0, - "mail proxy handler: %d, #%d > #%d", + "mail proxy handler: %ui, #%d > #%d", do_write, src->fd, dst->fd); for ( ;; ) { diff --git a/src/mail/ngx_mail_smtp_handler.c b/src/mail/ngx_mail_smtp_handler.c index 46d703e..81cc75f 100644 --- a/src/mail/ngx_mail_smtp_handler.c +++ b/src/mail/ngx_mail_smtp_handler.c @@ -42,7 +42,7 @@ static u_char smtp_username[] = "334 VXNlcm5hbWU6" CRLF; static u_char smtp_password[] = "334 UGFzc3dvcmQ6" CRLF; static u_char smtp_invalid_command[] = "500 5.5.1 Invalid command" CRLF; static u_char smtp_invalid_pipelining[] = - "503 5.5.0 Improper use of SMTP command pipelining" CRLF; + "503 5.5.0 Improper use of SMTP command pipelining" CRLF; static u_char smtp_invalid_argument[] = "501 5.5.4 Invalid argument" CRLF; static u_char smtp_auth_required[] = "530 5.7.1 Authentication required" CRLF; static u_char smtp_bad_sequence[] = "503 5.5.1 Bad sequence of commands" CRLF; diff --git a/src/mail/ngx_mail_ssl_module.c b/src/mail/ngx_mail_ssl_module.c index 1075410..ff5c141 100644 --- a/src/mail/ngx_mail_ssl_module.c +++ b/src/mail/ngx_mail_ssl_module.c @@ -312,13 +312,13 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) conf->ssl.log = cf->log; if (conf->enable) { - mode = "ssl"; + mode = "ssl"; } else if (conf->starttls != NGX_MAIL_STARTTLS_OFF) { - mode = "starttls"; + mode = "starttls"; } else { - mode = ""; + mode = ""; } if (conf->file == NULL) { @@ -421,7 +421,7 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); } -#ifndef LIBRESSL_VERSION_NUMBER +#if (OPENSSL_VERSION_NUMBER < 0x10100001L && !defined LIBRESSL_VERSION_NUMBER) SSL_CTX_set_tmp_rsa_callback(conf->ssl.ctx, ngx_ssl_rsa512_key_callback); #endif diff --git a/src/os/unix/ngx_atomic.h b/src/os/unix/ngx_atomic.h index 417cd86..74b8b7f 100644 --- a/src/os/unix/ngx_atomic.h +++ b/src/os/unix/ngx_atomic.h @@ -276,26 +276,26 @@ typedef volatile ngx_atomic_uint_t ngx_atomic_t; static ngx_inline ngx_atomic_uint_t ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old, - ngx_atomic_uint_t set) + ngx_atomic_uint_t set) { - if (*lock == old) { - *lock = set; - return 1; - } + if (*lock == old) { + *lock = set; + return 1; + } - return 0; + return 0; } static ngx_inline ngx_atomic_int_t ngx_atomic_fetch_add(ngx_atomic_t *value, ngx_atomic_int_t add) { - ngx_atomic_int_t old; + ngx_atomic_int_t old; - old = *value; - *value += add; + old = *value; + *value += add; - return old; + return old; } #define ngx_memory_barrier() diff --git a/src/os/unix/ngx_channel.h b/src/os/unix/ngx_channel.h index d7a9f6b..362cc64 100644 --- a/src/os/unix/ngx_channel.h +++ b/src/os/unix/ngx_channel.h @@ -15,10 +15,10 @@ typedef struct { - ngx_uint_t command; - ngx_pid_t pid; - ngx_int_t slot; - ngx_fd_t fd; + ngx_uint_t command; + ngx_pid_t pid; + ngx_int_t slot; + ngx_fd_t fd; } ngx_channel_t; diff --git a/src/os/unix/ngx_file_aio_read.c b/src/os/unix/ngx_file_aio_read.c index b11cf8a..aedc3c9 100644 --- a/src/os/unix/ngx_file_aio_read.c +++ b/src/os/unix/ngx_file_aio_read.c @@ -84,7 +84,7 @@ ngx_file_aio_read(ngx_file_t *file, u_char *buf, size_t size, off_t offset, } ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0, - "aio complete:%d @%O:%z %V", + "aio complete:%d @%O:%uz %V", ev->complete, offset, size, &file->name); if (ev->complete) { diff --git a/src/os/unix/ngx_files.c b/src/os/unix/ngx_files.c index bcef7ec..65c79a2 100644 --- a/src/os/unix/ngx_files.c +++ b/src/os/unix/ngx_files.c @@ -176,7 +176,7 @@ ngx_thread_read_handler(void *data, ngx_log_t *log) #endif ngx_log_debug4(NGX_LOG_DEBUG_CORE, log, 0, - "pread: %z (err: %i) of %uz @%O", + "pread: %z (err: %d) of %uz @%O", n, ctx->err, ctx->size, ctx->offset); } diff --git a/src/os/unix/ngx_linux_aio_read.c b/src/os/unix/ngx_linux_aio_read.c index b0a9236..9f0a6c1 100644 --- a/src/os/unix/ngx_linux_aio_read.c +++ b/src/os/unix/ngx_linux_aio_read.c @@ -73,7 +73,7 @@ ngx_file_aio_read(ngx_file_t *file, u_char *buf, size_t size, off_t offset, } ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0, - "aio complete:%d @%O:%z %V", + "aio complete:%d @%O:%uz %V", ev->complete, offset, size, &file->name); if (ev->complete) { diff --git a/src/os/unix/ngx_linux_sendfile_chain.c b/src/os/unix/ngx_linux_sendfile_chain.c index 50a9cea..3c0696a 100644 --- a/src/os/unix/ngx_linux_sendfile_chain.c +++ b/src/os/unix/ngx_linux_sendfile_chain.c @@ -451,7 +451,7 @@ again: #endif ngx_log_debug4(NGX_LOG_DEBUG_EVENT, log, 0, - "sendfile: %z (err: %i) of %uz @%O", + "sendfile: %z (err: %d) of %uz @%O", n, ctx->err, ctx->size, file->file_pos); if (ctx->err == NGX_EINTR) { diff --git a/src/os/unix/ngx_os.h b/src/os/unix/ngx_os.h index c0d59ef..e22f07c 100644 --- a/src/os/unix/ngx_os.h +++ b/src/os/unix/ngx_os.h @@ -39,7 +39,7 @@ void ngx_os_status(ngx_log_t *log); ngx_int_t ngx_os_specific_init(ngx_log_t *log); void ngx_os_specific_status(ngx_log_t *log); ngx_int_t ngx_daemon(ngx_log_t *log); -ngx_int_t ngx_os_signal_process(ngx_cycle_t *cycle, char *sig, ngx_int_t pid); +ngx_int_t ngx_os_signal_process(ngx_cycle_t *cycle, char *sig, ngx_pid_t pid); ssize_t ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size); diff --git a/src/os/unix/ngx_process.c b/src/os/unix/ngx_process.c index 6f3f385..24a63fb 100644 --- a/src/os/unix/ngx_process.c +++ b/src/os/unix/ngx_process.c @@ -611,7 +611,7 @@ ngx_debug_point(void) ngx_int_t -ngx_os_signal_process(ngx_cycle_t *cycle, char *name, ngx_int_t pid) +ngx_os_signal_process(ngx_cycle_t *cycle, char *name, ngx_pid_t pid) { ngx_signal_t *sig; diff --git a/src/os/unix/ngx_process_cycle.c b/src/os/unix/ngx_process_cycle.c index 9be6376..7cee1c5 100644 --- a/src/os/unix/ngx_process_cycle.c +++ b/src/os/unix/ngx_process_cycle.c @@ -145,7 +145,7 @@ ngx_master_process_cycle(ngx_cycle_t *cycle) } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, - "termination cycle: %d", delay); + "termination cycle: %M", delay); itv.it_interval.tv_sec = 0; itv.it_interval.tv_usec = 0; @@ -438,7 +438,7 @@ ngx_pass_open_channel(ngx_cycle_t *cycle, ngx_channel_t *ch) } ngx_log_debug6(NGX_LOG_DEBUG_CORE, cycle->log, 0, - "pass channel s:%d pid:%P fd:%d to s:%i pid:%P fd:%d", + "pass channel s:%i pid:%P fd:%d to s:%i pid:%P fd:%d", ch->slot, ch->pid, ch->fd, i, ngx_processes[i].pid, ngx_processes[i].channel[0]); @@ -492,7 +492,7 @@ ngx_signal_worker_processes(ngx_cycle_t *cycle, int signo) for (i = 0; i < ngx_last_process; i++) { ngx_log_debug7(NGX_LOG_DEBUG_EVENT, cycle->log, 0, - "child: %d %P e:%d t:%d d:%d r:%d j:%d", + "child: %i %P e:%d t:%d d:%d r:%d j:%d", i, ngx_processes[i].pid, ngx_processes[i].exiting, @@ -570,7 +570,7 @@ ngx_reap_children(ngx_cycle_t *cycle) for (i = 0; i < ngx_last_process; i++) { ngx_log_debug7(NGX_LOG_DEBUG_EVENT, cycle->log, 0, - "child: %d %P e:%d t:%d d:%d r:%d j:%d", + "child: %i %P e:%d t:%d d:%d r:%d j:%d", i, ngx_processes[i].pid, ngx_processes[i].exiting, @@ -1047,7 +1047,7 @@ ngx_channel_handler(ngx_event_t *ev) } ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0, - "channel command: %d", ch.command); + "channel command: %ui", ch.command); switch (ch.command) { diff --git a/src/os/unix/ngx_readv_chain.c b/src/os/unix/ngx_readv_chain.c index 3544b4b..9953782 100644 --- a/src/os/unix/ngx_readv_chain.c +++ b/src/os/unix/ngx_readv_chain.c @@ -101,7 +101,7 @@ ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain, off_t limit) } ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, - "readv: %d, last:%d", vec.nelts, iov->iov_len); + "readv: %ui, last:%uz", vec.nelts, iov->iov_len); do { n = readv(c->fd, (struct iovec *) vec.elts, vec.nelts); diff --git a/src/os/unix/ngx_recv.c b/src/os/unix/ngx_recv.c index 86675df..fc7f76c 100644 --- a/src/os/unix/ngx_recv.c +++ b/src/os/unix/ngx_recv.c @@ -52,7 +52,7 @@ ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size) n = recv(c->fd, buf, size, 0); ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, - "recv: fd:%d %d of %d", c->fd, n, size); + "recv: fd:%d %z of %uz", c->fd, n, size); if (n >= 0) { if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { @@ -139,7 +139,7 @@ ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size) n = recv(c->fd, buf, size, 0); ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, - "recv: fd:%d %d of %d", c->fd, n, size); + "recv: fd:%d %z of %uz", c->fd, n, size); if (n == 0) { rev->ready = 0; diff --git a/src/os/unix/ngx_send.c b/src/os/unix/ngx_send.c index 80995ab..61ea202 100644 --- a/src/os/unix/ngx_send.c +++ b/src/os/unix/ngx_send.c @@ -34,7 +34,7 @@ ngx_unix_send(ngx_connection_t *c, u_char *buf, size_t size) n = send(c->fd, buf, size, 0); ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, - "send: fd:%d %d of %d", c->fd, n, size); + "send: fd:%d %z of %uz", c->fd, n, size); if (n > 0) { if (n < (ssize_t) size) { diff --git a/src/os/unix/ngx_sunpro_amd64.il b/src/os/unix/ngx_sunpro_amd64.il index dc454b2..07f3210 100644 --- a/src/os/unix/ngx_sunpro_amd64.il +++ b/src/os/unix/ngx_sunpro_amd64.il @@ -38,6 +38,6 @@ / / ld.so.1: nginx: fatal: hardware capability unsupported: 0x2000 [ PAUSE ] - .inline ngx_cpu_pause,0 - rep; nop - .end + .inline ngx_cpu_pause,0 + rep; nop + .end diff --git a/src/os/unix/ngx_sunpro_x86.il b/src/os/unix/ngx_sunpro_x86.il index fd1cc00..d7e127c 100644 --- a/src/os/unix/ngx_sunpro_x86.il +++ b/src/os/unix/ngx_sunpro_x86.il @@ -39,6 +39,6 @@ / / ld.so.1: nginx: fatal: hardware capability unsupported: 0x2000 [ PAUSE ] - .inline ngx_cpu_pause,0 - rep; nop - .end + .inline ngx_cpu_pause,0 + rep; nop + .end diff --git a/src/os/unix/ngx_udp_recv.c b/src/os/unix/ngx_udp_recv.c index 1c807a0..e03bf6c 100644 --- a/src/os/unix/ngx_udp_recv.c +++ b/src/os/unix/ngx_udp_recv.c @@ -25,7 +25,7 @@ ngx_udp_unix_recv(ngx_connection_t *c, u_char *buf, size_t size) n = recv(c->fd, buf, size, 0); ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, - "recv: fd:%d %d of %d", c->fd, n, size); + "recv: fd:%d %z of %uz", c->fd, n, size); if (n >= 0) { if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { @@ -83,7 +83,7 @@ ngx_udp_unix_recv(ngx_connection_t *c, u_char *buf, size_t size) n = recv(c->fd, buf, size, 0); ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, - "recv: fd:%d %d of %d", c->fd, n, size); + "recv: fd:%d %z of %uz", c->fd, n, size); if (n >= 0) { return n; diff --git a/src/stream/ngx_stream_limit_conn_module.c b/src/stream/ngx_stream_limit_conn_module.c index 732b089..f1d8a37 100644 --- a/src/stream/ngx_stream_limit_conn_module.c +++ b/src/stream/ngx_stream_limit_conn_module.c @@ -220,7 +220,7 @@ ngx_stream_limit_conn_handler(ngx_stream_session_t *s) } ngx_log_debug2(NGX_LOG_DEBUG_STREAM, s->connection->log, 0, - "limit conn: %08XD %d", node->key, lc->conn); + "limit conn: %08Xi %d", node->key, lc->conn); ngx_shmtx_unlock(&shpool->mutex); @@ -340,7 +340,7 @@ ngx_stream_limit_conn_cleanup(void *data) ngx_shmtx_lock(&shpool->mutex); ngx_log_debug2(NGX_LOG_DEBUG_STREAM, lccln->shm_zone->shm.log, 0, - "limit conn cleanup: %08XD %d", node->key, lc->conn); + "limit conn cleanup: %08Xi %d", node->key, lc->conn); lc->conn--; diff --git a/src/stream/ngx_stream_ssl_module.c b/src/stream/ngx_stream_ssl_module.c index 7abd9e1..e12da1b 100644 --- a/src/stream/ngx_stream_ssl_module.c +++ b/src/stream/ngx_stream_ssl_module.c @@ -276,7 +276,7 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); } -#ifndef LIBRESSL_VERSION_NUMBER +#if (OPENSSL_VERSION_NUMBER < 0x10100001L && !defined LIBRESSL_VERSION_NUMBER) SSL_CTX_set_tmp_rsa_callback(conf->ssl.ctx, ngx_ssl_rsa512_key_callback); #endif diff --git a/src/stream/ngx_stream_upstream_least_conn_module.c b/src/stream/ngx_stream_upstream_least_conn_module.c index 677da45..c9719f9 100644 --- a/src/stream/ngx_stream_upstream_least_conn_module.c +++ b/src/stream/ngx_stream_upstream_least_conn_module.c @@ -254,7 +254,7 @@ failed: / (8 * sizeof(uintptr_t)); for (i = 0; i < n; i++) { - rrp->tried[i] = 0; + rrp->tried[i] = 0; } ngx_stream_upstream_rr_peers_unlock(peers); diff --git a/src/stream/ngx_stream_upstream_round_robin.c b/src/stream/ngx_stream_upstream_round_robin.c index efedb28..e1ab592 100644 --- a/src/stream/ngx_stream_upstream_round_robin.c +++ b/src/stream/ngx_stream_upstream_round_robin.c @@ -356,7 +356,7 @@ failed: / (8 * sizeof(uintptr_t)); for (i = 0; i < n; i++) { - rrp->tried[i] = 0; + rrp->tried[i] = 0; } ngx_stream_upstream_rr_peers_unlock(peers); From cfc16224c03487b79c12990251035aced699068b Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Tue, 19 Apr 2016 12:26:59 +0300 Subject: [PATCH 063/600] Fix changelog typo --- debian/changelog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index 7e366f3..6d5fd8a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -10,7 +10,7 @@ nginx (1.9.13-1) UNRELEASED; urgency=medium * debian/control: + Enable http/2, thread pool & WebDAV on nginx-light. In order for dynamic modules to be loadable in all nginx flavors we need - to ensure the share the same build signature. (Closes: #816095) + to ensure they share the same build signature. (Closes: #816095) + nginx-common & nginx-doc are now 'Multi-Arch: foreign'. (Closes: #812484) Thanks Elrond for the report and the initial patch. + Use secure VCS uri (lintian). From 8b10bd4f01381a69b57b9957c2eca7b258d8e7b8 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Mon, 18 Apr 2016 14:15:19 +0300 Subject: [PATCH 064/600] Release 1.9.14-1 --- debian/changelog | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/debian/changelog b/debian/changelog index 6d5fd8a..ae2f6fc 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,7 +1,7 @@ -nginx (1.9.13-1) UNRELEASED; urgency=medium +nginx (1.9.14-1) unstable; urgency=medium [ Christos Trochalakis ] - * New upstream release (1.9.13) (Closes: #812806) + * New upstream release (1.9.14) (Closes: #812806) * debian: + Setup dynamic module flow, and implement a simple dh_nginx helper for internal use. @@ -28,7 +28,7 @@ nginx (1.9.13-1) UNRELEASED; urgency=medium + Update http-auth-pam module to 1.5 and convert it to a dyn module. (Closes: #819062) - -- Christos Trochalakis Thu, 11 Feb 2016 15:06:38 +0200 + -- Christos Trochalakis Tue, 19 Apr 2016 11:05:35 +0300 nginx (1.9.10-1) unstable; urgency=medium From 58105135c4fde9f33b277f02ff07ba6189d57abf Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Wed, 27 Apr 2016 16:37:15 +0300 Subject: [PATCH 065/600] Fix upgrading nginx-extras from a non-dynamic version libnginx-mod-http-perl ships a common file with nginx-extras, adding a Replaces header fixes that. Note that the is no need to add a Breaks header since these packages are not co-installable (they explicitly depend on a different nginx-common version). --- debian/changelog | 8 ++++++++ debian/control | 1 + 2 files changed, 9 insertions(+) diff --git a/debian/changelog b/debian/changelog index ae2f6fc..42d09e1 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,11 @@ +nginx (1.9.14-2) UNRELEASED; urgency=medium + + [ Christos Trochalakis ] + * debian/control: + + Fix upgrading nginx-extras from testing. (Closes: #822553) + + -- Christos Trochalakis Wed, 27 Apr 2016 16:34:16 +0300 + nginx (1.9.14-1) unstable; urgency=medium [ Christos Trochalakis ] diff --git a/debian/control b/debian/control index 2398e29..5bda8fe 100644 --- a/debian/control +++ b/debian/control @@ -280,6 +280,7 @@ Description: Stream module for Nginx Package: libnginx-mod-http-perl Architecture: any Depends: ${perl:Depends}, ${misc:Depends}, ${shlibs:Depends} +Replaces: nginx-extras (<< 1.9.14-1) Description: Perl module for Nginx Embed Perl runtime into nginx. . From 664bdf48f483d5a0682566077a79f63131b9ba94 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Thu, 28 Apr 2016 10:00:35 +0300 Subject: [PATCH 066/600] Bump standards to 3.9.8 --- debian/changelog | 1 + debian/control | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index 42d09e1..84d382c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -3,6 +3,7 @@ nginx (1.9.14-2) UNRELEASED; urgency=medium [ Christos Trochalakis ] * debian/control: + Fix upgrading nginx-extras from testing. (Closes: #822553) + + Bump Standards to 3.9.8, no changes needed. -- Christos Trochalakis Wed, 27 Apr 2016 16:34:16 +0300 diff --git a/debian/control b/debian/control index 5bda8fe..52baf37 100644 --- a/debian/control +++ b/debian/control @@ -24,7 +24,7 @@ Build-Depends: autotools-dev, libxslt1-dev, po-debconf, zlib1g-dev -Standards-Version: 3.9.7.0 +Standards-Version: 3.9.8.0 Homepage: http://nginx.net Vcs-Git: https://anonscm.debian.org/cgit/collab-maint/nginx.git Vcs-Browser: https://anonscm.debian.org/cgit/collab-maint/nginx.git From c46cc7556bd04b652d74d2cdaf796487c3914a3c Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Thu, 28 Apr 2016 10:01:02 +0300 Subject: [PATCH 067/600] libnginx-mod-http-perl: Override wrong-section-according-to-package-name warning --- debian/changelog | 2 ++ debian/libnginx-mod-http-perl.lintian-overrides | 1 + 2 files changed, 3 insertions(+) create mode 100644 debian/libnginx-mod-http-perl.lintian-overrides diff --git a/debian/changelog b/debian/changelog index 84d382c..c3ba4d3 100644 --- a/debian/changelog +++ b/debian/changelog @@ -4,6 +4,8 @@ nginx (1.9.14-2) UNRELEASED; urgency=medium * debian/control: + Fix upgrading nginx-extras from testing. (Closes: #822553) + Bump Standards to 3.9.8, no changes needed. + * debian/libnginx-mod-http-perl.lintian-overrides: + + Override wrong-section-according-to-package-name warning. -- Christos Trochalakis Wed, 27 Apr 2016 16:34:16 +0300 diff --git a/debian/libnginx-mod-http-perl.lintian-overrides b/debian/libnginx-mod-http-perl.lintian-overrides new file mode 100644 index 0000000..cda1f30 --- /dev/null +++ b/debian/libnginx-mod-http-perl.lintian-overrides @@ -0,0 +1 @@ +libnginx-mod-http-perl: wrong-section-according-to-package-name libnginx-mod-http-perl => perl From a66bea579bb35c6335beee0a46ad1b1535113f97 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Wed, 27 Apr 2016 16:44:22 +0300 Subject: [PATCH 068/600] Release 1.9.14-2 --- debian/changelog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index c3ba4d3..4d4885f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -nginx (1.9.14-2) UNRELEASED; urgency=medium +nginx (1.9.14-2) unstable; urgency=medium [ Christos Trochalakis ] * debian/control: @@ -7,7 +7,7 @@ nginx (1.9.14-2) UNRELEASED; urgency=medium * debian/libnginx-mod-http-perl.lintian-overrides: + Override wrong-section-according-to-package-name warning. - -- Christos Trochalakis Wed, 27 Apr 2016 16:34:16 +0300 + -- Christos Trochalakis Wed, 27 Apr 2016 16:43:02 +0300 nginx (1.9.14-1) unstable; urgency=medium From 95a2b168be9b408dd778f23476a22f2c9c1d2784 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Fri, 29 Apr 2016 10:30:33 +0300 Subject: [PATCH 069/600] Imported Upstream version 1.10.0 --- CHANGES | 24 ++++ CHANGES.ru | 23 ++++ auto/cc/icc | 4 +- contrib/vim/syntax/nginx.vim | 2 +- src/core/nginx.h | 4 +- src/core/ngx_inet.c | 2 +- src/core/ngx_regex.c | 2 +- src/core/ngx_resolver.c | 4 +- src/core/ngx_thread_pool.c | 4 + src/event/modules/ngx_epoll_module.c | 2 +- src/http/modules/ngx_http_fastcgi_module.c | 5 + src/http/modules/ngx_http_mp4_module.c | 8 +- src/http/modules/ngx_http_ssi_filter_module.c | 6 +- src/http/v2/ngx_http_v2.c | 100 +++++++++++----- src/http/v2/ngx_http_v2.h | 1 + src/os/unix/ngx_readv_chain.c | 50 ++++---- src/os/unix/ngx_recv.c | 107 +++++------------- src/os/unix/ngx_udp_recv.c | 53 +-------- 18 files changed, 201 insertions(+), 200 deletions(-) diff --git a/CHANGES b/CHANGES index e1e596e..408f952 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,28 @@ +Changes with nginx 1.10.0 26 Apr 2016 + + *) 1.10.x stable branch. + + +Changes with nginx 1.9.15 19 Apr 2016 + + *) Bugfix: "recv() failed" errors might occur when using HHVM as a + FastCGI server. + + *) Bugfix: when using HTTP/2 and the "limit_req" or "auth_request" + directives a timeout or a "client violated flow control" error might + occur while reading client request body; the bug had appeared in + 1.9.14. + + *) Workaround: a response might not be shown by some browsers if HTTP/2 + was used and client request body was not fully read; the bug had + appeared in 1.9.14. + + *) Bugfix: connections might hang when using the "aio threads" + directive. + Thanks to Mindaugas Rasiukevicius. + + Changes with nginx 1.9.14 05 Apr 2016 *) Feature: OpenSSL 1.1.0 compatibility. diff --git a/CHANGES.ru b/CHANGES.ru index c6e6e84..4e6002e 100644 --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,27 @@ +Изменения в nginx 1.10.0 26.04.2016 + + *) Стабильная ветка 1.10.x. + + +Изменения в nginx 1.9.15 19.04.2016 + + *) Исправление: при использовании HHVM в качестве FastCGI-сервера могли + возникать ошибки "recv() failed". + + *) Исправление: при использовании HTTP/2 и директив limit_req или + auth_request при чтении тела запроса мог произойти таймаут или ошибка + "client violated flow control"; ошибка появилась в 1.9.14. + + *) Изменение: при использовании HTTP/2 ответ мог не показываться + некоторыми браузерами, если тело запроса было прочитано не целиком; + ошибка появилась в 1.9.14. + + *) Исправление: при использовании директивы "aio threads" соединения + могли зависать. + Спасибо Mindaugas Rasiukevicius. + + Изменения в nginx 1.9.14 05.04.2016 *) Добавление: совместимость с OpenSSL 1.1.0. diff --git a/auto/cc/icc b/auto/cc/icc index 1d83ed3..1c0df1a 100644 --- a/auto/cc/icc +++ b/auto/cc/icc @@ -89,7 +89,7 @@ CFLAGS="$CFLAGS -wd1419" case "$NGX_ICC_VER" in 9.*) - # "cc" clobber ignored, warnings for Liunx's htonl()/htons() + # "cc" clobber ignored, warnings for Linux's htonl()/htons() CFLAGS="$CFLAGS -wd1469" # explicit conversion of a 64-bit integral type to a smaller # integral type @@ -103,7 +103,7 @@ case "$NGX_ICC_VER" in ;; 8.*) - # "cc" clobber ignored, warnings for Liunx's htonl()/htons() + # "cc" clobber ignored, warnings for Linux's htonl()/htons() CFLAGS="$CFLAGS -wd1469" # floating-point equality and inequality comparisons are unreliable, # warning on SvTRUE() diff --git a/contrib/vim/syntax/nginx.vim b/contrib/vim/syntax/nginx.vim index 8f13017..f1fd48a 100644 --- a/contrib/vim/syntax/nginx.vim +++ b/contrib/vim/syntax/nginx.vim @@ -604,7 +604,7 @@ syn keyword ngxDirectiveThirdParty echo_subrequest syn keyword ngxDirectiveThirdParty echo_subrequest_async " Events Module -" Privides options for start/stop events. +" Provides options for start/stop events. syn keyword ngxDirectiveThirdParty on_start syn keyword ngxDirectiveThirdParty on_stop diff --git a/src/core/nginx.h b/src/core/nginx.h index d0a6f65..fe78745 100644 --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1009014 -#define NGINX_VERSION "1.9.14" +#define nginx_version 1010000 +#define NGINX_VERSION "1.10.0" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD diff --git a/src/core/ngx_inet.c b/src/core/ngx_inet.c index a4e80ed..33b303d 100644 --- a/src/core/ngx_inet.c +++ b/src/core/ngx_inet.c @@ -348,7 +348,7 @@ ngx_inet6_ntop(u_char *p, u_char *text, size_t len) continue; } - dst = ngx_sprintf(dst, "%uxd", p[i] * 256 + p[i + 1]); + dst = ngx_sprintf(dst, "%xd", p[i] * 256 + p[i + 1]); if (i < 14) { *dst++ = ':'; diff --git a/src/core/ngx_regex.c b/src/core/ngx_regex.c index 416622d..9939dce 100644 --- a/src/core/ngx_regex.c +++ b/src/core/ngx_regex.c @@ -32,7 +32,7 @@ static ngx_conf_post_t ngx_regex_pcre_jit_post = { ngx_regex_pcre_jit }; static ngx_command_t ngx_regex_commands[] = { { ngx_string("pcre_jit"), - NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, + NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG, ngx_conf_set_flag_slot, 0, offsetof(ngx_regex_conf_t, pcre_jit), diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c index 3c52de8..e00fe22 100644 --- a/src/core/ngx_resolver.c +++ b/src/core/ngx_resolver.c @@ -1733,7 +1733,7 @@ ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf, size_t n, trunc = flags & 0x0200; ngx_log_debug6(NGX_LOG_DEBUG_CORE, r->log, 0, - "resolver DNS response %ui fl:%04Xui %ui/%ui/%ud/%ud", + "resolver DNS response %ui fl:%04Xi %ui/%ui/%ud/%ud", ident, flags, nqs, nan, (response->nns_hi << 8) + response->nns_lo, (response->nar_hi << 8) + response->nar_lo); @@ -1741,7 +1741,7 @@ ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf, size_t n, /* response to a standard query */ if ((flags & 0xf870) != 0x8000 || (trunc && tcp)) { ngx_log_error(r->log_level, r->log, 0, - "invalid %s DNS response %ui fl:%04Xui", + "invalid %s DNS response %ui fl:%04Xi", tcp ? "TCP" : "UDP", ident, flags); return; } diff --git a/src/core/ngx_thread_pool.c b/src/core/ngx_thread_pool.c index 0353085..f3655aa 100644 --- a/src/core/ngx_thread_pool.c +++ b/src/core/ngx_thread_pool.c @@ -345,6 +345,8 @@ ngx_thread_pool_cycle(void *data) *ngx_thread_pool_done.last = task; ngx_thread_pool_done.last = &task->next; + ngx_memory_barrier(); + ngx_unlock(&ngx_thread_pool_done_lock); (void) ngx_notify(ngx_thread_pool_handler); @@ -366,6 +368,8 @@ ngx_thread_pool_handler(ngx_event_t *ev) ngx_thread_pool_done.first = NULL; ngx_thread_pool_done.last = &ngx_thread_pool_done.first; + ngx_memory_barrier(); + ngx_unlock(&ngx_thread_pool_done_lock); while (task) { diff --git a/src/event/modules/ngx_epoll_module.c b/src/event/modules/ngx_epoll_module.c index 828e4d1..166c461 100644 --- a/src/event/modules/ngx_epoll_module.c +++ b/src/event/modules/ngx_epoll_module.c @@ -910,7 +910,7 @@ ngx_epoll_eventfd_handler(ngx_event_t *ev) for (i = 0; i < events; i++) { ngx_log_debug4(NGX_LOG_DEBUG_EVENT, ev->log, 0, - "io_event: %uXL %uXL %L %L", + "io_event: %XL %XL %L %L", event[i].data, event[i].obj, event[i].res, event[i].res2); diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c index a861203..2d288ce 100644 --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -1177,6 +1177,11 @@ ngx_http_fastcgi_create_request(ngx_http_request_t *r) while (body) { + if (ngx_buf_special(body->buf)) { + body = body->next; + continue; + } + if (body->buf->in_file) { file_pos = body->buf->file_pos; diff --git a/src/http/modules/ngx_http_mp4_module.c b/src/http/modules/ngx_http_mp4_module.c index 6cb3ccf..16ef83c 100644 --- a/src/http/modules/ngx_http_mp4_module.c +++ b/src/http/modules/ngx_http_mp4_module.c @@ -1433,10 +1433,10 @@ typedef struct { u_char layer[2]; u_char group[2]; u_char volume[2]; - u_char reverved3[2]; + u_char reserved3[2]; u_char matrix[36]; u_char width[4]; - u_char heigth[4]; + u_char height[4]; } ngx_mp4_tkhd_atom_t; typedef struct { @@ -1453,10 +1453,10 @@ typedef struct { u_char layer[2]; u_char group[2]; u_char volume[2]; - u_char reverved3[2]; + u_char reserved3[2]; u_char matrix[36]; u_char width[4]; - u_char heigth[4]; + u_char height[4]; } ngx_mp4_tkhd64_atom_t; diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c index b997aaa..fc6e65b 100644 --- a/src/http/modules/ngx_http_ssi_filter_module.c +++ b/src/http/modules/ngx_http_ssi_filter_module.c @@ -2005,7 +2005,7 @@ ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, if (uri && file) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "inlcusion may be either virtual=\"%V\" or file=\"%V\"", + "inclusion may be either virtual=\"%V\" or file=\"%V\"", uri, file); return NGX_HTTP_SSI_ERROR; } @@ -2525,7 +2525,7 @@ ngx_http_ssi_if(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "evaluted left: \"%V\"", &left); + "evaluated left: \"%V\"", &left); if (p == last) { if (left.len) { @@ -2589,7 +2589,7 @@ ngx_http_ssi_if(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "evaluted right: \"%V\"", &right); + "evaluated right: \"%V\"", &right); if (noregex) { if (left.len != right.len) { diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c index 4bd85b8..278c9ab 100644 --- a/src/http/v2/ngx_http_v2.c +++ b/src/http/v2/ngx_http_v2.c @@ -948,6 +948,7 @@ ngx_http_v2_state_headers(ngx_http_v2_connection_t *h2c, u_char *pos, { size_t size; ngx_uint_t padded, priority, depend, dependency, excl, weight; + ngx_uint_t status; ngx_http_v2_node_t *node; ngx_http_v2_stream_t *stream; ngx_http_v2_srv_conf_t *h2scf; @@ -1040,15 +1041,8 @@ ngx_http_v2_state_headers(ngx_http_v2_connection_t *h2c, u_char *pos, "client sent HEADERS frame for stream %ui " "with incorrect dependency", h2c->state.sid); - if (ngx_http_v2_send_rst_stream(h2c, h2c->state.sid, - NGX_HTTP_V2_PROTOCOL_ERROR) - != NGX_OK) - { - return ngx_http_v2_connection_error(h2c, - NGX_HTTP_V2_INTERNAL_ERROR); - } - - return ngx_http_v2_state_header_block(h2c, pos, end); + status = NGX_HTTP_V2_PROTOCOL_ERROR; + goto rst_stream; } h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, @@ -1060,15 +1054,18 @@ ngx_http_v2_state_headers(ngx_http_v2_connection_t *h2c, u_char *pos, ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, "concurrent streams exceeded %ui", h2c->processing); - if (ngx_http_v2_send_rst_stream(h2c, h2c->state.sid, - NGX_HTTP_V2_REFUSED_STREAM) - != NGX_OK) - { - return ngx_http_v2_connection_error(h2c, - NGX_HTTP_V2_INTERNAL_ERROR); - } + status = NGX_HTTP_V2_REFUSED_STREAM; + goto rst_stream; + } - return ngx_http_v2_state_header_block(h2c, pos, end); + if (!h2c->settings_ack && !(h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG)) + { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent stream with data " + "before settings were acknowledged"); + + status = NGX_HTTP_V2_REFUSED_STREAM; + goto rst_stream; } node = ngx_http_v2_get_node_by_id(h2c, h2c->state.sid, 1); @@ -1104,6 +1101,14 @@ ngx_http_v2_state_headers(ngx_http_v2_connection_t *h2c, u_char *pos, ngx_http_v2_set_dependency(h2c, node, depend, excl); } + return ngx_http_v2_state_header_block(h2c, pos, end); + +rst_stream: + + if (ngx_http_v2_send_rst_stream(h2c, h2c->state.sid, status) != NGX_OK) { + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR); + } + return ngx_http_v2_state_header_block(h2c, pos, end); } @@ -1883,7 +1888,7 @@ ngx_http_v2_state_settings(ngx_http_v2_connection_t *h2c, u_char *pos, return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR); } - /* TODO settings acknowledged */ + h2c->settings_ack = 1; return ngx_http_v2_state_complete(h2c, pos, end); } @@ -3409,6 +3414,7 @@ ngx_http_v2_read_request_body(ngx_http_request_t *r, ngx_http_v2_stream_t *stream; ngx_http_request_body_t *rb; ngx_http_core_loc_conf_t *clcf; + ngx_http_v2_connection_t *h2c; stream = r->stream; @@ -3468,6 +3474,7 @@ ngx_http_v2_read_request_body(ngx_http_request_t *r, } if (rb->buf == NULL) { + stream->skip_data = 1; return NGX_HTTP_INTERNAL_SERVER_ERROR; } @@ -3476,20 +3483,31 @@ ngx_http_v2_read_request_body(ngx_http_request_t *r, return ngx_http_v2_process_request_body(r, NULL, 0, 1); } - if (r->request_body_no_buffering) { - stream->no_flow_control = 0; - stream->recv_window = (size_t) len; + if (len) { + if (r->request_body_no_buffering) { + stream->recv_window = (size_t) len; - } else { - stream->no_flow_control = 1; - stream->recv_window = NGX_HTTP_V2_MAX_WINDOW; - } + } else { + stream->no_flow_control = 1; + stream->recv_window = NGX_HTTP_V2_MAX_WINDOW; + } - if (ngx_http_v2_send_window_update(stream->connection, stream->node->id, - stream->recv_window) - == NGX_ERROR) - { - return NGX_HTTP_INTERNAL_SERVER_ERROR; + if (ngx_http_v2_send_window_update(stream->connection, stream->node->id, + stream->recv_window) + == NGX_ERROR) + { + stream->skip_data = 1; + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + h2c = stream->connection; + + if (!h2c->blocked) { + if (ngx_http_v2_send_output_queue(h2c) == NGX_ERROR) { + stream->skip_data = 1; + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + } } ngx_add_timer(r->connection->read, clcf->client_body_timeout); @@ -3859,11 +3877,33 @@ ngx_http_v2_close_stream(ngx_http_v2_stream_t *stream, ngx_int_t rc) } } else if (!stream->in_closed) { +#if 0 if (ngx_http_v2_send_rst_stream(h2c, node->id, NGX_HTTP_V2_NO_ERROR) != NGX_OK) { h2c->connection->error = 1; } +#else + /* + * At the time of writing at least the latest versions of Chrome + * do not properly handle RST_STREAM with NO_ERROR status. + * + * See: https://bugs.chromium.org/p/chromium/issues/detail?id=603182 + * + * As a workaround, the stream window is maximized before closing + * the stream. This allows a client to send up to 2 GB of data + * before getting blocked on flow control. + */ + + if (stream->recv_window < NGX_HTTP_V2_MAX_WINDOW + && ngx_http_v2_send_window_update(h2c, node->id, + NGX_HTTP_V2_MAX_WINDOW + - stream->recv_window) + != NGX_OK) + { + h2c->connection->error = 1; + } +#endif } } diff --git a/src/http/v2/ngx_http_v2.h b/src/http/v2/ngx_http_v2.h index 7a77c27..1adf8de 100644 --- a/src/http/v2/ngx_http_v2.h +++ b/src/http/v2/ngx_http_v2.h @@ -141,6 +141,7 @@ struct ngx_http_v2_connection_s { ngx_uint_t last_sid; unsigned closed_nodes:8; + unsigned settings_ack:1; unsigned blocked:1; }; diff --git a/src/os/unix/ngx_readv_chain.c b/src/os/unix/ngx_readv_chain.c index 9953782..d23508e 100644 --- a/src/os/unix/ngx_readv_chain.c +++ b/src/os/unix/ngx_readv_chain.c @@ -106,7 +106,27 @@ ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain, off_t limit) do { n = readv(c->fd, (struct iovec *) vec.elts, vec.nelts); - if (n >= 0) { + if (n == 0) { + rev->ready = 0; + rev->eof = 1; + +#if (NGX_HAVE_KQUEUE) + + /* + * on FreeBSD readv() may return 0 on closed socket + * even if kqueue reported about available data + */ + + if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { + rev->available = 0; + } + +#endif + + return 0; + } + + if (n > 0) { #if (NGX_HAVE_KQUEUE) @@ -115,7 +135,7 @@ ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain, off_t limit) /* * rev->available may be negative here because some additional - * bytes may be received between kevent() and recv() + * bytes may be received between kevent() and readv() */ if (rev->available <= 0) { @@ -123,42 +143,18 @@ ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain, off_t limit) rev->ready = 0; } - if (rev->available < 0) { - rev->available = 0; - } - } - - if (n == 0) { - - /* - * on FreeBSD recv() may return 0 on closed socket - * even if kqueue reported about available data - */ - -#if 0 - ngx_log_error(NGX_LOG_ALERT, c->log, 0, - "readv() returned 0 while kevent() reported " - "%d available bytes", rev->available); -#endif - - rev->ready = 0; - rev->eof = 1; rev->available = 0; } return n; } -#endif /* NGX_HAVE_KQUEUE */ +#endif if (n < size && !(ngx_event_flags & NGX_USE_GREEDY_EVENT)) { rev->ready = 0; } - if (n == 0) { - rev->eof = 1; - } - return n; } diff --git a/src/os/unix/ngx_recv.c b/src/os/unix/ngx_recv.c index fc7f76c..5013ae3 100644 --- a/src/os/unix/ngx_recv.c +++ b/src/os/unix/ngx_recv.c @@ -10,8 +10,6 @@ #include -#if (NGX_HAVE_KQUEUE) - ssize_t ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size) { @@ -21,6 +19,8 @@ ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size) rev = c->read; +#if (NGX_HAVE_KQUEUE) + if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, "recv: eof:%d, avail:%d, err:%d", @@ -48,13 +48,38 @@ ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size) } } +#endif + do { n = recv(c->fd, buf, size, 0); ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, "recv: fd:%d %z of %uz", c->fd, n, size); - if (n >= 0) { + if (n == 0) { + rev->ready = 0; + rev->eof = 1; + +#if (NGX_HAVE_KQUEUE) + + /* + * on FreeBSD recv() may return 0 on closed socket + * even if kqueue reported about available data + */ + + if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { + rev->available = 0; + } + +#endif + + return 0; + } + + if (n > 0) { + +#if (NGX_HAVE_KQUEUE) + if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { rev->available -= n; @@ -68,85 +93,13 @@ ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size) rev->ready = 0; } - if (rev->available < 0) { - rev->available = 0; - } - } - - if (n == 0) { - - /* - * on FreeBSD recv() may return 0 on closed socket - * even if kqueue reported about available data - */ - - rev->ready = 0; - rev->eof = 1; rev->available = 0; } return n; } - if ((size_t) n < size - && !(ngx_event_flags & NGX_USE_GREEDY_EVENT)) - { - rev->ready = 0; - } - - if (n == 0) { - rev->eof = 1; - } - - return n; - } - - err = ngx_socket_errno; - - if (err == NGX_EAGAIN || err == NGX_EINTR) { - ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, - "recv() not ready"); - n = NGX_AGAIN; - - } else { - n = ngx_connection_error(c, err, "recv() failed"); - break; - } - - } while (err == NGX_EINTR); - - rev->ready = 0; - - if (n == NGX_ERROR) { - rev->error = 1; - } - - return n; -} - -#else /* ! NGX_HAVE_KQUEUE */ - -ssize_t -ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size) -{ - ssize_t n; - ngx_err_t err; - ngx_event_t *rev; - - rev = c->read; - - do { - n = recv(c->fd, buf, size, 0); - - ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, - "recv: fd:%d %z of %uz", c->fd, n, size); - - if (n == 0) { - rev->ready = 0; - rev->eof = 1; - return n; - - } else if (n > 0) { +#endif if ((size_t) n < size && !(ngx_event_flags & NGX_USE_GREEDY_EVENT)) @@ -179,5 +132,3 @@ ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size) return n; } - -#endif /* NGX_HAVE_KQUEUE */ diff --git a/src/os/unix/ngx_udp_recv.c b/src/os/unix/ngx_udp_recv.c index e03bf6c..6d544c2 100644 --- a/src/os/unix/ngx_udp_recv.c +++ b/src/os/unix/ngx_udp_recv.c @@ -10,8 +10,6 @@ #include -#if (NGX_HAVE_KQUEUE) - ssize_t ngx_udp_unix_recv(ngx_connection_t *c, u_char *buf, size_t size) { @@ -28,6 +26,9 @@ ngx_udp_unix_recv(ngx_connection_t *c, u_char *buf, size_t size) "recv: fd:%d %z of %uz", c->fd, n, size); if (n >= 0) { + +#if (NGX_HAVE_KQUEUE) + if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { rev->available -= n; @@ -42,6 +43,8 @@ ngx_udp_unix_recv(ngx_connection_t *c, u_char *buf, size_t size) } } +#endif + return n; } @@ -67,49 +70,3 @@ ngx_udp_unix_recv(ngx_connection_t *c, u_char *buf, size_t size) return n; } - -#else /* ! NGX_HAVE_KQUEUE */ - -ssize_t -ngx_udp_unix_recv(ngx_connection_t *c, u_char *buf, size_t size) -{ - ssize_t n; - ngx_err_t err; - ngx_event_t *rev; - - rev = c->read; - - do { - n = recv(c->fd, buf, size, 0); - - ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, - "recv: fd:%d %z of %uz", c->fd, n, size); - - if (n >= 0) { - return n; - } - - err = ngx_socket_errno; - - if (err == NGX_EAGAIN || err == NGX_EINTR) { - ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, - "recv() not ready"); - n = NGX_AGAIN; - - } else { - n = ngx_connection_error(c, err, "recv() failed"); - break; - } - - } while (err == NGX_EINTR); - - rev->ready = 0; - - if (n == NGX_ERROR) { - rev->error = 1; - } - - return n; -} - -#endif /* NGX_HAVE_KQUEUE */ From 6706bbedf8ee04027fda78f8ab0e86b4947a4242 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Fri, 29 Apr 2016 10:31:44 +0300 Subject: [PATCH 070/600] New upstream release --- debian/changelog | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/debian/changelog b/debian/changelog index 4d4885f..411e3cd 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +nginx (1.10.0-1) UNRELEASED; urgency=medium + + [ Christos Trochalakis ] + * New upstream release (1.10.0) + + -- Christos Trochalakis Fri, 29 Apr 2016 10:31:21 +0300 + nginx (1.9.14-2) unstable; urgency=medium [ Christos Trochalakis ] From 00cd95bfc14c7ee8035623f85f6be4359f5d75b0 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Fri, 29 Apr 2016 10:31:53 +0300 Subject: [PATCH 071/600] Release 1.10.0-1 --- debian/changelog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index 411e3cd..8e4cdbe 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,9 +1,9 @@ -nginx (1.10.0-1) UNRELEASED; urgency=medium +nginx (1.10.0-1) unstable; urgency=medium [ Christos Trochalakis ] * New upstream release (1.10.0) - -- Christos Trochalakis Fri, 29 Apr 2016 10:31:21 +0300 + -- Christos Trochalakis Fri, 29 Apr 2016 10:31:46 +0300 nginx (1.9.14-2) unstable; urgency=medium From 7ffd2fc6a928e8f981a8d7375870d408817fe4ef Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Tue, 31 May 2016 15:54:45 +0300 Subject: [PATCH 072/600] Generate dbgsym packages only if dh_strip supports it Makes backporting easier. --- debian/changelog | 3 +++ debian/rules | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index 8e4cdbe..69fb1f9 100644 --- a/debian/changelog +++ b/debian/changelog @@ -2,6 +2,9 @@ nginx (1.10.0-1) unstable; urgency=medium [ Christos Trochalakis ] * New upstream release (1.10.0) + * debian/control: + + Generate dbgsym packages only if dh_strip supports it. + Thanks Faidon Liambotis for the hint. -- Christos Trochalakis Fri, 29 Apr 2016 10:31:46 +0300 diff --git a/debian/rules b/debian/rules index 63abd77..c21c307 100755 --- a/debian/rules +++ b/debian/rules @@ -148,7 +148,7 @@ strip.arch.%: dh_strip --package=nginx-$(*) --dbg-package=nginx-$(*)-dbg strip.mods.%: - dh_strip --package=libnginx-mod-$(*) --automatic-dbgsym + dh_strip --package=libnginx-mod-$(*) -O--automatic-dbgsym config.arch.%: dh_testdir From 1b192da67cc8ce82a2fcc1c9889030cedd4a0182 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Tue, 31 May 2016 21:55:00 +0300 Subject: [PATCH 073/600] Imported Upstream version 1.10.1 --- CHANGES | 7 +++++++ CHANGES.ru | 7 +++++++ src/core/nginx.h | 4 ++-- src/os/unix/ngx_files.c | 5 +++++ 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 408f952..4396472 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,11 @@ +Changes with nginx 1.10.1 31 May 2016 + + *) Security: a segmentation fault might occur in a worker process while + writing a specially crafted request body to a temporary file + (CVE-2016-4450); the bug had appeared in 1.3.9. + + Changes with nginx 1.10.0 26 Apr 2016 *) 1.10.x stable branch. diff --git a/CHANGES.ru b/CHANGES.ru index 4e6002e..c96cf93 100644 --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,11 @@ +Изменения в nginx 1.10.1 31.05.2016 + + *) Безопасность: при записи тела специально созданного запроса во + временный файл в рабочем процессе мог происходить segmentation fault + (CVE-2016-4450); ошибка появилась в 1.3.9. + + Изменения в nginx 1.10.0 26.04.2016 *) Стабильная ветка 1.10.x. diff --git a/src/core/nginx.h b/src/core/nginx.h index fe78745..e2b8005 100644 --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1010000 -#define NGINX_VERSION "1.10.0" +#define nginx_version 1010001 +#define NGINX_VERSION "1.10.1" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD diff --git a/src/os/unix/ngx_files.c b/src/os/unix/ngx_files.c index 65c79a2..7fbb7c9 100644 --- a/src/os/unix/ngx_files.c +++ b/src/os/unix/ngx_files.c @@ -356,6 +356,11 @@ ngx_chain_to_iovec(ngx_iovec_t *vec, ngx_chain_t *cl) n = 0; for ( /* void */ ; cl; cl = cl->next) { + + if (ngx_buf_special(cl->buf)) { + continue; + } + size = cl->buf->last - cl->buf->pos; if (prev == cl->buf->pos) { From a1e2085dd78be871f4e226de667480a8c6e4e661 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Tue, 31 May 2016 22:00:26 +0300 Subject: [PATCH 074/600] Correctly add changelog entry to 1.10.0-2 --- debian/changelog | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/debian/changelog b/debian/changelog index 69fb1f9..451f3d1 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,10 +1,16 @@ +nginx (1.10.0-2) UNRELEASED; urgency=medium + + [ Christos Trochalakis ] + * debian/control: + + Generate dbgsym packages only if dh_strip supports it. + Thanks Faidon Liambotis for the hint. + + -- Christos Trochalakis Tue, 31 May 2016 21:59:40 +0300 + nginx (1.10.0-1) unstable; urgency=medium [ Christos Trochalakis ] * New upstream release (1.10.0) - * debian/control: - + Generate dbgsym packages only if dh_strip supports it. - Thanks Faidon Liambotis for the hint. -- Christos Trochalakis Fri, 29 Apr 2016 10:31:46 +0300 From 52025f4a8e64ffe9485c0bf10f286c710a2af6d3 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Tue, 31 May 2016 22:01:40 +0300 Subject: [PATCH 075/600] Release 1.10.1-1 --- debian/changelog | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index 451f3d1..d2f3264 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,11 +1,16 @@ -nginx (1.10.0-2) UNRELEASED; urgency=medium +nginx (1.10.1-1) unstable; urgency=medium [ Christos Trochalakis ] + * New upstream release (1.10.1) + Fixes CVE-2016-4450 + NULL pointer dereference while writing client request body. + (Closes: #825960) + * debian/control: + Generate dbgsym packages only if dh_strip supports it. Thanks Faidon Liambotis for the hint. - -- Christos Trochalakis Tue, 31 May 2016 21:59:40 +0300 + -- Christos Trochalakis Tue, 31 May 2016 22:01:25 +0300 nginx (1.10.0-1) unstable; urgency=medium From 60cdfb206953b55792c1303420d664c072fcfff2 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Tue, 7 Jun 2016 10:46:33 +0300 Subject: [PATCH 076/600] Only build against liblua5.1-0-dev when libluajit is not available --- debian/changelog | 9 +++++++++ debian/control | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index d2f3264..bad7a82 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,12 @@ +nginx (1.10.1-2) UNRELEASED; urgency=medium + + [ Christos Trochalakis ] + * debian/control: + Don't allow building against liblua5.1-0-dev on architectures + that libluajit is available. + + -- Christos Trochalakis Tue, 07 Jun 2016 10:47:36 +0300 + nginx (1.10.1-1) unstable; urgency=medium [ Christos Trochalakis ] diff --git a/debian/control b/debian/control index 52baf37..0c7f2cb 100644 --- a/debian/control +++ b/debian/control @@ -15,7 +15,8 @@ Build-Depends: autotools-dev, libexpat-dev, libgd-dev, libgeoip-dev, - libluajit-5.1-dev [i386 amd64 kfreebsd-i386 armel armhf powerpc powerpcspe mips mipsel] | liblua5.1-0-dev, + libluajit-5.1-dev [i386 amd64 kfreebsd-i386 armel armhf powerpc powerpcspe mips mipsel], + liblua5.1-0-dev [!i386 !amd64 !kfreebsd-i386 !armel !armhf !powerpc !powerpcspe !mips !mipsel], libmhash-dev, libpam0g-dev, libpcre3-dev, From 15695dee6eafdc463f3b8d7844ec6241e2919864 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Thu, 7 Jul 2016 11:25:23 +0300 Subject: [PATCH 077/600] Re-enable experimental flow for 1.11.x --- debian/README.Packaging | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/debian/README.Packaging b/debian/README.Packaging index 61358da..bbb7875 100644 --- a/debian/README.Packaging +++ b/debian/README.Packaging @@ -25,15 +25,10 @@ split each module to a separate source. [0] https://www.nginx.com/blog/dynamic-modules-nginx-1-9-11/ -Workflow for Experimental (not-active) -====================================== +Workflow for Experimental +========================= -Now that nginx 1.6.0 is released there is no plan to package mainline 1.7 -releases to experimental. The following guide is been kept as a reference. - --------- - -Nginx mainline releases (1.5.x series) are been packaged for experimental, +Nginx mainline releases (1.11.x series) are been packaged for experimental, as they lack security support. The workflow we use is based on the assumption that packaging work happens on @@ -41,7 +36,7 @@ origin/master and experimental builds are a trivial patch away from that. The direct consequense of treating experimental as a patchset for origin/master is that the relevant branches are forced-pushed whenever we release a new -1.5.x version. In other words, **it is not safe to base your work on the +1.11.x version. In other words, **it is not safe to base your work on the experimental branch**. This is a brief description of our experimental branches and how we are using @@ -50,27 +45,27 @@ them. * experimental-base Force-pushed when origin/master changes. - experimental-base tracks the changes needed for building the 1.5.x branch, - such as new configure parameters, etc. On new 1.5.x releases, it is rebased + experimental-base tracks the changes needed for building the 1.11.x branch, + such as new configure parameters, etc. On new 1.11.x releases, it is rebased on origin/master so it is always up-to-date with our latest packaging work. * experimental - Force-pushed on every 1.5.x release. + Force-pushed on every 1.11.x release. - This branch points to the latest 1.5.x release. + This branch points to the latest 1.11.x release. Before release this branch is reset to experimental-base, and then merged - with the new upstream-1.5 branch. Finally all the release specific changes + with the new upstream-1.11 branch. Finally all the release specific changes are commited (changelog entry etc) and the build is made. -* upstream-1.5 - Force-pushed on every 1.5.x release. +* upstream-1.11 + Force-pushed on every 1.11.x release. - Before a new 1.5.x release the branch is reset to origin/upstream. - This is a technicallity so we can avoid resolving conflicts when a new 1.4.x + Before a new 1.11.x release the branch is reset to origin/upstream. + This is a technicallity so we can avoid resolving conflicts when a new 1.10.x release happens between two experimental releases. -Older 1.5.x releases are not referenced by any branch, but they can be found by -the relevant debian/* tag. +Older 1.11.x releases are not referenced by any branch, but they can be found +by the relevant debian/* tag. 3rd party experimental workflow =============================== From a4f9f837e7b2bf4fba78462df3e226e03e88b4ac Mon Sep 17 00:00:00 2001 From: Michael Lustfield Date: Sat, 16 Jul 2016 17:30:40 -0700 Subject: [PATCH 078/600] Implemented patch in bug 826061. --- debian/changelog | 7 +++++- ...ource-on-other-glibc-based-platforms.patch | 23 +++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 debian/patches/0003-define_gnu_source-on-other-glibc-based-platforms.patch diff --git a/debian/changelog b/debian/changelog index bad7a82..f2a7ab6 100644 --- a/debian/changelog +++ b/debian/changelog @@ -5,7 +5,12 @@ nginx (1.10.1-2) UNRELEASED; urgency=medium Don't allow building against liblua5.1-0-dev on architectures that libluajit is available. - -- Christos Trochalakis Tue, 07 Jun 2016 10:47:36 +0300 + [ Michael Lustfield ] + * debian/patches/0003-*.patch: + + Use _GNU_SOURCE on GNU/kFreeBSD (Closes: #826061) + Thanks Steven Chamberlain for the patch. + + -- Michael Lustfield Sat, 16 Jul 2016 17:24:40 -0700 nginx (1.10.1-1) unstable; urgency=medium diff --git a/debian/patches/0003-define_gnu_source-on-other-glibc-based-platforms.patch b/debian/patches/0003-define_gnu_source-on-other-glibc-based-platforms.patch new file mode 100644 index 0000000..bb9b089 --- /dev/null +++ b/debian/patches/0003-define_gnu_source-on-other-glibc-based-platforms.patch @@ -0,0 +1,23 @@ +Date: Sat, 16 Jul 2016 23:52:50 +0100 +From: Steven Chamberlain +Subject: Use _GNU_SOURCE on GNU/kFreeBSD + +Define _GNU_SOURCE not only on GNU/Hurd, but also other glibc-based +platforms including GNU/kFreeBSD. +--- a/src/os/unix/ngx_posix_config.h ++++ b/src/os/unix/ngx_posix_config.h +@@ -21,10 +21,13 @@ + #endif + + +-#if (NGX_GNU_HURD) ++#if defined(__GLIBC__) + #ifndef _GNU_SOURCE + #define _GNU_SOURCE /* accept4() */ + #endif ++#endif ++ ++#if (NGX_GNU_HURD) + #define _FILE_OFFSET_BITS 64 + #endif + diff --git a/debian/patches/series b/debian/patches/series index 04b971f..f3ccceb 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -1,2 +1,3 @@ perl-use-dpkg-buildflags.patch 0002-Make-sure-signature-stays-the-same-in-all-nginx-buil.patch +0003-define_gnu_source-on-other-glibc-based-platforms.patch From 1b3fa883bbc71ab8fe1ddf0199f60850726a3957 Mon Sep 17 00:00:00 2001 From: Michael Lustfield Date: Sat, 16 Jul 2016 19:14:08 -0700 Subject: [PATCH 079/600] Make nginx-*.postinst use invoke-rc.d. --- debian/changelog | 5 ++++- debian/nginx-extras.postinst | 15 +-------------- debian/nginx-full.postinst | 15 +-------------- debian/nginx-light.postinst | 15 +-------------- 4 files changed, 7 insertions(+), 43 deletions(-) diff --git a/debian/changelog b/debian/changelog index f2a7ab6..52c4dcf 100644 --- a/debian/changelog +++ b/debian/changelog @@ -7,8 +7,11 @@ nginx (1.10.1-2) UNRELEASED; urgency=medium [ Michael Lustfield ] * debian/patches/0003-*.patch: - + Use _GNU_SOURCE on GNU/kFreeBSD (Closes: #826061) + + Use _GNU_SOURCE on GNU/kFreeBSD. (Closes: #826061) Thanks Steven Chamberlain for the patch. + * debian/nginx-*.postinst: + + Make nginx-*.postinst use invoke-rc.d. (Closes: #823435) + Thanks Simon Deziel for the patch. -- Michael Lustfield Sat, 16 Jul 2016 17:24:40 -0700 diff --git a/debian/nginx-extras.postinst b/debian/nginx-extras.postinst index bd9c818..4ea6d9d 100644 --- a/debian/nginx-extras.postinst +++ b/debian/nginx-extras.postinst @@ -13,20 +13,7 @@ esac if [ -x /etc/init.d/nginx ]; then if [ -f /run/nginx.pid ] && pidof /usr/sbin/nginx >/dev/null; then - NGX_PID=`cat /run/nginx.pid` - if kill -s USR2 $NGX_PID 2>/dev/null; then - while [ ! -s /run/nginx.pid.oldbin ] || [ ! -s /run/nginx.pid ]; do - cnt=`expr $cnt + 1` - if [ $cnt -gt 10 ]; then - kill -s KILL $NGX_PID - invoke-rc.d nginx start - exit 0 - fi - sleep 1 - done - NGX_OLD_PID=`cat /run/nginx.pid.oldbin` - kill -s QUIT $NGX_OLD_PID - fi + invoke-rc.d nginx upgrade || exit $? else invoke-rc.d nginx start || exit $? fi diff --git a/debian/nginx-full.postinst b/debian/nginx-full.postinst index bd9c818..4ea6d9d 100644 --- a/debian/nginx-full.postinst +++ b/debian/nginx-full.postinst @@ -13,20 +13,7 @@ esac if [ -x /etc/init.d/nginx ]; then if [ -f /run/nginx.pid ] && pidof /usr/sbin/nginx >/dev/null; then - NGX_PID=`cat /run/nginx.pid` - if kill -s USR2 $NGX_PID 2>/dev/null; then - while [ ! -s /run/nginx.pid.oldbin ] || [ ! -s /run/nginx.pid ]; do - cnt=`expr $cnt + 1` - if [ $cnt -gt 10 ]; then - kill -s KILL $NGX_PID - invoke-rc.d nginx start - exit 0 - fi - sleep 1 - done - NGX_OLD_PID=`cat /run/nginx.pid.oldbin` - kill -s QUIT $NGX_OLD_PID - fi + invoke-rc.d nginx upgrade || exit $? else invoke-rc.d nginx start || exit $? fi diff --git a/debian/nginx-light.postinst b/debian/nginx-light.postinst index bd9c818..4ea6d9d 100644 --- a/debian/nginx-light.postinst +++ b/debian/nginx-light.postinst @@ -13,20 +13,7 @@ esac if [ -x /etc/init.d/nginx ]; then if [ -f /run/nginx.pid ] && pidof /usr/sbin/nginx >/dev/null; then - NGX_PID=`cat /run/nginx.pid` - if kill -s USR2 $NGX_PID 2>/dev/null; then - while [ ! -s /run/nginx.pid.oldbin ] || [ ! -s /run/nginx.pid ]; do - cnt=`expr $cnt + 1` - if [ $cnt -gt 10 ]; then - kill -s KILL $NGX_PID - invoke-rc.d nginx start - exit 0 - fi - sleep 1 - done - NGX_OLD_PID=`cat /run/nginx.pid.oldbin` - kill -s QUIT $NGX_OLD_PID - fi + invoke-rc.d nginx upgrade || exit $? else invoke-rc.d nginx start || exit $? fi From 1445c1403ca7cc0eb3030cb74525f2bbc4b8e9f8 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Fri, 29 Jul 2016 16:16:43 +0300 Subject: [PATCH 080/600] *.postinst: Make sure we restart nginx if on-the-fly upgrade fails Complements Mike's 1b3fa883. --- debian/nginx-extras.postinst | 3 ++- debian/nginx-full.postinst | 3 ++- debian/nginx-light.postinst | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/debian/nginx-extras.postinst b/debian/nginx-extras.postinst index 4ea6d9d..9c2605d 100644 --- a/debian/nginx-extras.postinst +++ b/debian/nginx-extras.postinst @@ -13,7 +13,8 @@ esac if [ -x /etc/init.d/nginx ]; then if [ -f /run/nginx.pid ] && pidof /usr/sbin/nginx >/dev/null; then - invoke-rc.d nginx upgrade || exit $? + invoke-rc.d nginx upgrade || invoke-rc.d nginx restart + exit $? else invoke-rc.d nginx start || exit $? fi diff --git a/debian/nginx-full.postinst b/debian/nginx-full.postinst index 4ea6d9d..9c2605d 100644 --- a/debian/nginx-full.postinst +++ b/debian/nginx-full.postinst @@ -13,7 +13,8 @@ esac if [ -x /etc/init.d/nginx ]; then if [ -f /run/nginx.pid ] && pidof /usr/sbin/nginx >/dev/null; then - invoke-rc.d nginx upgrade || exit $? + invoke-rc.d nginx upgrade || invoke-rc.d nginx restart + exit $? else invoke-rc.d nginx start || exit $? fi diff --git a/debian/nginx-light.postinst b/debian/nginx-light.postinst index 4ea6d9d..9c2605d 100644 --- a/debian/nginx-light.postinst +++ b/debian/nginx-light.postinst @@ -13,7 +13,8 @@ esac if [ -x /etc/init.d/nginx ]; then if [ -f /run/nginx.pid ] && pidof /usr/sbin/nginx >/dev/null; then - invoke-rc.d nginx upgrade || exit $? + invoke-rc.d nginx upgrade || invoke-rc.d nginx restart + exit $? else invoke-rc.d nginx start || exit $? fi From 0f2905a7e013b0604e77c5640d10203476012ef9 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Fri, 29 Jul 2016 16:31:20 +0300 Subject: [PATCH 081/600] mod: Upgrade nginx-lua to v0.10.5 --- debian/changelog | 2 + debian/modules/README.Modules-versions | 2 +- debian/modules/nginx-lua/README.markdown | 17 +- debian/modules/nginx-lua/config | 47 +++++ .../modules/nginx-lua/doc/HttpLuaModule.wiki | 17 +- .../nginx-lua/dtrace/ngx_lua_provider.d | 24 +-- .../nginx-lua/src/api/ngx_http_lua_api.h | 2 +- .../nginx-lua/src/ngx_http_lua_balancer.c | 6 +- .../nginx-lua/src/ngx_http_lua_common.h | 5 +- .../nginx-lua/src/ngx_http_lua_control.c | 5 +- .../nginx-lua/src/ngx_http_lua_directive.c | 23 +-- .../nginx-lua/src/ngx_http_lua_initworkerby.c | 25 ++- .../modules/nginx-lua/src/ngx_http_lua_misc.c | 8 + .../nginx-lua/src/ngx_http_lua_module.c | 69 +++++-- .../nginx-lua/src/ngx_http_lua_output.c | 14 +- .../nginx-lua/src/ngx_http_lua_regex.c | 42 +++-- .../nginx-lua/src/ngx_http_lua_req_body.c | 35 +++- .../nginx-lua/src/ngx_http_lua_semaphore.c | 173 ++++++++++-------- .../nginx-lua/src/ngx_http_lua_semaphore.h | 18 +- .../nginx-lua/src/ngx_http_lua_socket_tcp.c | 4 +- .../nginx-lua/src/ngx_http_lua_ssl_certby.c | 13 ++ .../nginx-lua/src/ngx_http_lua_ssl_ocsp.c | 6 + .../nginx-lua/src/ngx_http_lua_timer.c | 1 - .../modules/nginx-lua/src/ngx_http_lua_util.c | 10 +- .../nginx-lua/src/ngx_http_lua_variable.c | 3 +- .../nginx-lua/src/ngx_http_lua_worker.c | 13 ++ debian/modules/nginx-lua/t/015-status.t | 23 ++- debian/modules/nginx-lua/t/024-access/mixed.t | 14 ++ debian/modules/nginx-lua/t/034-match.t | 23 ++- debian/modules/nginx-lua/t/043-shdict.t | 2 +- debian/modules/nginx-lua/t/044-req-body.t | 108 +++++++++++ debian/modules/nginx-lua/t/058-tcp-socket.t | 4 +- debian/modules/nginx-lua/t/087-udp-socket.t | 4 +- debian/modules/nginx-lua/t/129-ssl-socket.t | 36 +++- debian/modules/nginx-lua/t/132-lua-blocks.t | 35 +++- debian/modules/nginx-lua/t/135-worker-id.t | 66 ++++++- debian/modules/nginx-lua/t/139-ssl-cert-by.t | 95 ++++++++++ debian/modules/nginx-lua/t/140-ssl-c-api.t | 138 +++++++++++++- debian/modules/nginx-lua/t/141-luajit.t | 47 +++++ .../t/data/fake-module/ngx_http_fake_module.c | 2 - debian/modules/nginx-lua/util/build.sh | 2 +- 41 files changed, 961 insertions(+), 222 deletions(-) create mode 100644 debian/modules/nginx-lua/t/141-luajit.t diff --git a/debian/changelog b/debian/changelog index 52c4dcf..a0528da 100644 --- a/debian/changelog +++ b/debian/changelog @@ -4,6 +4,8 @@ nginx (1.10.1-2) UNRELEASED; urgency=medium * debian/control: Don't allow building against liblua5.1-0-dev on architectures that libluajit is available. + * debian/modules/nginx-lua: + + Update nginx-lua to v0.10.5 [ Michael Lustfield ] * debian/patches/0003-*.patch: diff --git a/debian/modules/README.Modules-versions b/debian/modules/README.Modules-versions index d7f35a4..b71b1e0 100644 --- a/debian/modules/README.Modules-versions +++ b/debian/modules/README.Modules-versions @@ -22,7 +22,7 @@ README for Modules versions nginx-lua Homepage: https://github.com/openresty/lua-nginx-module - Version: v0.10.2 + Version: v0.10.5 nginx-upstream-fair Homepage: https://github.com/gnosek/nginx-upstream-fair diff --git a/debian/modules/nginx-lua/README.markdown b/debian/modules/nginx-lua/README.markdown index 4e8f9bd..14e9ecc 100644 --- a/debian/modules/nginx-lua/README.markdown +++ b/debian/modules/nginx-lua/README.markdown @@ -62,7 +62,7 @@ Production ready. Version ======= -This document describes ngx_lua [v0.10.2](https://github.com/openresty/lua-nginx-module/tags) released on 8 March 2016. +This document describes ngx_lua [v0.10.5](https://github.com/openresty/lua-nginx-module/tags) released on 25 May 2016. Synopsis ======== @@ -249,7 +249,7 @@ Nginx Compatibility The latest version of this module is compatible with the following versions of Nginx: -* 1.9.x (last tested: 1.9.7) +* 1.9.x (last tested: 1.9.15) * 1.8.x * 1.7.x (last tested: 1.7.10) * 1.6.x @@ -274,9 +274,9 @@ Build the source with this module: ```bash - wget 'http://nginx.org/download/nginx-1.9.7.tar.gz' - tar -xzvf nginx-1.9.7.tar.gz - cd nginx-1.9.7/ + wget 'http://nginx.org/download/nginx-1.9.15.tar.gz' + tar -xzvf nginx-1.9.15.tar.gz + cd nginx-1.9.15/ # tell nginx's build system where to find LuaJIT 2.0: export LUAJIT_LIB=/path/to/luajit/lib @@ -926,7 +926,7 @@ filtering chain determines the final output, for example. The correct adding ord * memcached: listening on the default port, 11211. * redis: listening on the default port, 6379. -See also the [developer build script](https://github.com/openresty/lua-nginx-module/blob/master/util/build2.sh) for more details on setting up the testing environment. +See also the [developer build script](https://github.com/openresty/lua-nginx-module/blob/master/util/build.sh) for more details on setting up the testing environment. To run the whole test suite in the default testing mode: @@ -1060,6 +1060,11 @@ Directives * [lua_max_running_timers](#lua_max_running_timers) +The basic building blocks of scripting Nginx with Lua are directives. Directives are used to specify when the user Lua code is run and +how the result will be used. Below is a diagram showing the order in which directives are executed. + +![Lua Nginx Modules Directives](https://cloud.githubusercontent.com/assets/2137369/15272097/77d1c09e-1a37-11e6-97ef-d9767035fc3e.png) + [Back to TOC](#table-of-contents) lua_use_default_type diff --git a/debian/modules/nginx-lua/config b/debian/modules/nginx-lua/config index 3c2548b..c91a07e 100644 --- a/debian/modules/nginx-lua/config +++ b/debian/modules/nginx-lua/config @@ -466,6 +466,53 @@ ngx_feature_test='setsockopt(1, SOL_SOCKET, SO_PASSCRED, NULL, 0);' . auto/feature +ngx_feature="mmap(sbrk(0))" +ngx_feature_libs= +ngx_feature_name="NGX_HTTP_LUA_HAVE_MMAP_SBRK" +ngx_feature_run=yes +ngx_feature_incs="#include +#include +#include +#include +#define align_ptr(p, a) \ + (u_char *) (((uintptr_t) (p) + ((uintptr_t) a - 1)) & ~((uintptr_t) a - 1)) +" +ngx_feature_test=" +#if defined(__x86_64__) +exit(mmap(align_ptr(sbrk(0), getpagesize()), 1, PROT_READ, + MAP_FIXED|MAP_PRIVATE|MAP_ANON, -1, 0) < (void *) 0x40000000LL + ? 0 : 1); +#else +exit(1); +#endif +" +SAVED_CC_TEST_FLAGS="$CC_TEST_FLAGS" +CC_TEST_FLAGS="-Werror -Wall $CC_TEST_FLAGS" + +. auto/feature + +CC_TEST_FLAGS="$SAVED_CC_TEST_FLAGS" + +ngx_feature="__attribute__(constructor)" +ngx_feature_libs= +ngx_feature_name="NGX_HTTP_LUA_HAVE_CONSTRUCTOR" +ngx_feature_run=yes +ngx_feature_incs="#include +int a = 2; +__attribute__((constructor)) +static void foo(void) +{ + a = 0; +} +" +ngx_feature_test="exit(a);" +SAVED_CC_TEST_FLAGS="$CC_TEST_FLAGS" +CC_TEST_FLAGS="-Werror -Wall $CC_TEST_FLAGS" + +. auto/feature + +CC_TEST_FLAGS="$SAVED_CC_TEST_FLAGS" + if test -n "$ngx_module_link"; then ngx_module_type=HTTP_AUX_FILTER ngx_module_name=$ngx_addon_name diff --git a/debian/modules/nginx-lua/doc/HttpLuaModule.wiki b/debian/modules/nginx-lua/doc/HttpLuaModule.wiki index f6824ef..78ce13c 100644 --- a/debian/modules/nginx-lua/doc/HttpLuaModule.wiki +++ b/debian/modules/nginx-lua/doc/HttpLuaModule.wiki @@ -10,7 +10,7 @@ Production ready. = Version = -This document describes ngx_lua [https://github.com/openresty/lua-nginx-module/tags v0.10.2] released on 8 March 2016. +This document describes ngx_lua [https://github.com/openresty/lua-nginx-module/tags v0.10.5] released on 25 May 2016. = Synopsis = @@ -186,7 +186,7 @@ The Lua state (Lua VM instance) is shared across all the requests handled by a s The latest version of this module is compatible with the following versions of Nginx: -* 1.9.x (last tested: 1.9.7) +* 1.9.x (last tested: 1.9.15) * 1.8.x * 1.7.x (last tested: 1.7.10) * 1.6.x @@ -207,9 +207,9 @@ Alternatively, ngx_lua can be manually compiled into Nginx: Build the source with this module: - wget 'http://nginx.org/download/nginx-1.9.7.tar.gz' - tar -xzvf nginx-1.9.7.tar.gz - cd nginx-1.9.7/ + wget 'http://nginx.org/download/nginx-1.9.15.tar.gz' + tar -xzvf nginx-1.9.15.tar.gz + cd nginx-1.9.15/ # tell nginx's build system where to find LuaJIT 2.0: export LUAJIT_LIB=/path/to/luajit/lib @@ -754,7 +754,7 @@ filtering chain determines the final output, for example. The correct adding ord ** memcached: listening on the default port, 11211. ** redis: listening on the default port, 6379. -See also the [https://github.com/openresty/lua-nginx-module/blob/master/util/build2.sh developer build script] for more details on setting up the testing environment. +See also the [https://github.com/openresty/lua-nginx-module/blob/master/util/build.sh developer build script] for more details on setting up the testing environment. To run the whole test suite in the default testing mode: @@ -820,6 +820,11 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +The basic building blocks of scripting Nginx with Lua are directives. Directives are used to specify when the user Lua code is run and +how the result will be used. Below is a diagram showing the order in which directives are executed. + +![Lua Nginx Modules Directives](https://cloud.githubusercontent.com/assets/2137369/15272097/77d1c09e-1a37-11e6-97ef-d9767035fc3e.png) + == lua_use_default_type == '''syntax:''' ''lua_use_default_type on | off'' diff --git a/debian/modules/nginx-lua/dtrace/ngx_lua_provider.d b/debian/modules/nginx-lua/dtrace/ngx_lua_provider.d index 3767f9b..394484c 100644 --- a/debian/modules/nginx-lua/dtrace/ngx_lua_provider.d +++ b/debian/modules/nginx-lua/dtrace/ngx_lua_provider.d @@ -4,48 +4,48 @@ provider nginx_lua { /* lua_State *L */ probe http__lua__register__preload__package(void *L, u_char *pkg); - probe http__lua__req__socket__consume__preread(ngx_http_request_t *r, + probe http__lua__req__socket__consume__preread(void *r, u_char *data, size_t len); /* lua_State *parent, lua_State *child */ - probe http__lua__user__coroutine__create(ngx_http_request_t *r, + probe http__lua__user__coroutine__create(void *r, void *parent, void *child); /* lua_State *parent, lua_State *child */ - probe http__lua__user__coroutine__resume(ngx_http_request_t *r, + probe http__lua__user__coroutine__resume(void *r, void *parent, void *child); /* lua_State *parent, lua_State *child */ - probe http__lua__user__coroutine__yield(ngx_http_request_t *r, + probe http__lua__user__coroutine__yield(void *r, void *parent, void *child); /* lua_State *L */ - probe http__lua__thread__yield(ngx_http_request_t *r, void *L); + probe http__lua__thread__yield(void *r, void *L); /* ngx_http_lua_socket_tcp_upstream_t *u */ - probe http__lua__socket__tcp__send__start(ngx_http_request_t *r, + probe http__lua__socket__tcp__send__start(void *r, void *u, u_char *data, size_t len); /* ngx_http_lua_socket_tcp_upstream_t *u */ - probe http__lua__socket__tcp__receive__done(ngx_http_request_t *r, + probe http__lua__socket__tcp__receive__done(void *r, void *u, u_char *data, size_t len); /* ngx_http_lua_socket_tcp_upstream_t *u */ probe http__lua__socket__tcp__setkeepalive__buf__unread( - ngx_http_request_t *r, void *u, u_char *data, size_t len); + void *r, void *u, u_char *data, size_t len); /* lua_State *creator, lua_State *newthread */ - probe http__lua__user__thread__spawn(ngx_http_request_t *r, + probe http__lua__user__thread__spawn(void *r, void *creator, void *newthread); /* lua_State *thread, ngx_http_lua_ctx_t *ctx */ - probe http__lua__thread__delete(ngx_http_request_t *r, void *thread, void *ctx); + probe http__lua__thread__delete(void *r, void *thread, void *ctx); /* lua_State *thread */ - probe http__lua__run__posted__thread(ngx_http_request_t *r, void *thread, + probe http__lua__run__posted__thread(void *r, void *thread, int status); - probe http__lua__coroutine__done(ngx_http_request_t *r, void *co, + probe http__lua__coroutine__done(void *r, void *co, int success); /* lua_State *parent, lua_State *child */ diff --git a/debian/modules/nginx-lua/src/api/ngx_http_lua_api.h b/debian/modules/nginx-lua/src/api/ngx_http_lua_api.h index a15d40e..4bac0f6 100644 --- a/debian/modules/nginx-lua/src/api/ngx_http_lua_api.h +++ b/debian/modules/nginx-lua/src/api/ngx_http_lua_api.h @@ -19,7 +19,7 @@ /* Public API for other Nginx modules */ -#define ngx_http_lua_version 10001 +#define ngx_http_lua_version 10005 typedef struct { diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_balancer.c b/debian/modules/nginx-lua/src/ngx_http_lua_balancer.c index a2c66be..5fa289b 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_balancer.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_balancer.c @@ -29,7 +29,7 @@ struct ngx_http_lua_balancer_peer_data_s { struct sockaddr *sockaddr; socklen_t socklen; - ngx_str_t host; + ngx_str_t *host; in_port_t port; int last_peer_state; @@ -322,9 +322,9 @@ ngx_http_lua_balancer_get_peer(ngx_peer_connection_t *pc, void *data) if (bp->sockaddr && bp->socklen) { pc->sockaddr = bp->sockaddr; pc->socklen = bp->socklen; - pc->name = &bp->host; pc->cached = 0; pc->connection = NULL; + pc->name = bp->host; bp->rrp.peers->single = 0; @@ -525,7 +525,7 @@ ngx_http_lua_ffi_balancer_set_current_peer(ngx_http_request_t *r, if (url.addrs && url.addrs[0].sockaddr) { bp->sockaddr = url.addrs[0].sockaddr; bp->socklen = url.addrs[0].socklen; - bp->host = url.addrs[0].name; + bp->host = &url.addrs[0].name; } else { *err = "no host allowed"; diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_common.h b/debian/modules/nginx-lua/src/ngx_http_lua_common.h index e7b9969..758c42a 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_common.h +++ b/debian/modules/nginx-lua/src/ngx_http_lua_common.h @@ -123,7 +123,7 @@ typedef struct ngx_http_lua_balancer_peer_data_s ngx_http_lua_balancer_peer_data_t; -typedef struct ngx_http_lua_semaphore_mm_s ngx_http_lua_semaphore_mm_t; +typedef struct ngx_http_lua_sema_mm_s ngx_http_lua_sema_mm_t; typedef ngx_int_t (*ngx_http_lua_main_conf_handler_pt)(ngx_log_t *log, @@ -182,7 +182,7 @@ struct ngx_http_lua_main_conf_s { ngx_uint_t shm_zones_inited; - ngx_http_lua_semaphore_mm_t *semaphore_mm; + ngx_http_lua_sema_mm_t *sema_mm; unsigned requires_header_filter:1; unsigned requires_body_filter:1; @@ -502,6 +502,7 @@ typedef struct ngx_http_lua_ctx_s { socket */ unsigned acquired_raw_req_socket:1; /* whether a raw req socket is acquired */ + unsigned seen_body_data:1; } ngx_http_lua_ctx_t; diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_control.c b/debian/modules/nginx-lua/src/ngx_http_lua_control.c index 0e1dd47..4c5f65e 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_control.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_control.c @@ -459,6 +459,7 @@ ngx_http_lua_ffi_exit(ngx_http_request_t *r, int status, u_char *err, | NGX_HTTP_LUA_CONTEXT_CONTENT | NGX_HTTP_LUA_CONTEXT_TIMER | NGX_HTTP_LUA_CONTEXT_HEADER_FILTER + | NGX_HTTP_LUA_CONTEXT_BALANCER | NGX_HTTP_LUA_CONTEXT_SSL_CERT, err, errlen) != NGX_OK) @@ -519,7 +520,9 @@ ngx_http_lua_ffi_exit(ngx_http_request_t *r, int status, u_char *err, ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua exit with code %i", ctx->exit_code); - if (ctx->context & NGX_HTTP_LUA_CONTEXT_HEADER_FILTER) { + if (ctx->context & (NGX_HTTP_LUA_CONTEXT_HEADER_FILTER + | NGX_HTTP_LUA_CONTEXT_BALANCER)) + { return NGX_DONE; } diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_directive.c b/debian/modules/nginx-lua/src/ngx_http_lua_directive.c index 7ac8c28..e6bc339 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_directive.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_directive.c @@ -1417,20 +1417,8 @@ ngx_http_lua_conf_lua_block_parse(ngx_conf_t *cf, ngx_command_t *cmd) break; case FOUND_LBRACKET_STR: - - break; - case FOUND_LBRACKET_CMT: - - break; - case FOUND_RIGHT_LBRACKET: - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "unexpected lua closing long-bracket"); - goto failed; - - break; - case FOUND_COMMENT_LINE: case FOUND_DOUBLE_QUOTED: case FOUND_SINGLE_QUOTED: @@ -1492,7 +1480,10 @@ ngx_http_lua_conf_read_lua_token(ngx_conf_t *cf, for ( ;; ) { - if (b->pos >= b->last) { + if (b->pos >= b->last + || (b->last - b->pos < (b->end - b->start) / 3 + && cf->conf_file->file.offset < file_size)) + { if (cf->conf_file->file.offset >= file_size) { @@ -1505,7 +1496,7 @@ ngx_http_lua_conf_read_lua_token(ngx_conf_t *cf, return NGX_ERROR; } - len = b->pos - start; + len = b->last - start; if (len == buf_size) { @@ -1543,8 +1534,8 @@ ngx_http_lua_conf_read_lua_token(ngx_conf_t *cf, return NGX_ERROR; } - b->pos = b->start + len; - b->last = b->pos + n; + b->pos = b->start + (b->pos - start); + b->last = b->start + len + n; start = b->start; #if nginx_version >= 1009002 diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_initworkerby.c b/debian/modules/nginx-lua/src/ngx_http_lua_initworkerby.c index 8a374c2..6754b4b 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_initworkerby.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_initworkerby.c @@ -34,7 +34,7 @@ ngx_http_lua_init_worker(ngx_cycle_t *cycle) ngx_http_request_t *r = NULL; ngx_http_lua_ctx_t *ctx; ngx_http_conf_ctx_t *conf_ctx, http_ctx; - ngx_http_lua_loc_conf_t *llcf, *top_llcf; + ngx_http_lua_loc_conf_t *top_llcf; ngx_http_lua_main_conf_t *lmcf; ngx_http_core_loc_conf_t *clcf, *top_clcf; @@ -198,9 +198,17 @@ ngx_http_lua_init_worker(ngx_cycle_t *cycle) http_ctx.loc_conf[modules[i]->ctx_index] = cur; if (module->merge_loc_conf) { - prev = module->create_loc_conf(&conf); - if (prev == NULL) { - return NGX_ERROR; + if (modules[i] == &ngx_http_lua_module) { + prev = top_llcf; + + } else if (modules[i] == &ngx_http_core_module) { + prev = top_clcf; + + } else { + prev = module->create_loc_conf(&conf); + if (prev == NULL) { + return NGX_ERROR; + } } rv = module->merge_loc_conf(&conf, prev, cur); @@ -254,10 +262,6 @@ ngx_http_lua_init_worker(ngx_cycle_t *cycle) #endif - if (top_clcf->resolver) { - clcf->resolver = top_clcf->resolver; - } - ctx = ngx_http_lua_create_ctx(r); if (ctx == NULL) { goto failed; @@ -267,11 +271,6 @@ ngx_http_lua_init_worker(ngx_cycle_t *cycle) ctx->cur_co_ctx = NULL; r->read_event_handler = ngx_http_block_reading; - llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module); - if (top_llcf->log_socket_errors != NGX_CONF_UNSET) { - llcf->log_socket_errors = top_llcf->log_socket_errors; - } - ngx_http_lua_set_req(lmcf->lua, r); (void) lmcf->init_worker_handler(cycle->log, lmcf, lmcf->lua); diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_misc.c b/debian/modules/nginx-lua/src/ngx_http_lua_misc.c index e3c7ec7..f96e2f2 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_misc.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_misc.c @@ -160,6 +160,10 @@ ngx_http_lua_ngx_set(lua_State *L) return 0; } + if (r->err_status) { + r->err_status = 0; + } + ngx_http_lua_check_fake_request(L, r); /* get the value */ @@ -235,6 +239,10 @@ ngx_http_lua_ffi_set_resp_status(ngx_http_request_t *r, int status) r->headers_out.status = status; + if (r->err_status) { + r->err_status = 0; + } + if (status == 101) { /* * XXX work-around a bug in the Nginx core older than 1.5.5 diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_module.c b/debian/modules/nginx-lua/src/ngx_http_lua_module.c index 11eb653..867661c 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_module.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_module.c @@ -43,6 +43,14 @@ static char *ngx_http_lua_lowat_check(ngx_conf_t *cf, void *post, void *data); static ngx_int_t ngx_http_lua_set_ssl(ngx_conf_t *cf, ngx_http_lua_loc_conf_t *llcf); #endif +#if (NGX_HTTP_LUA_HAVE_MMAP_SBRK) && (NGX_LINUX) +/* we cannot use "static" for this function since it may lead to compiler + * warnings */ +void ngx_http_lua_limit_data_segment(void); +# if !(NGX_HTTP_LUA_HAVE_CONSTRUCTOR) +static ngx_int_t ngx_http_lua_pre_config(ngx_conf_t *cf); +# endif +#endif static ngx_conf_post_t ngx_http_lua_lowat_post = @@ -545,7 +553,13 @@ static ngx_command_t ngx_http_lua_cmds[] = { ngx_http_module_t ngx_http_lua_module_ctx = { +#if (NGX_HTTP_LUA_HAVE_MMAP_SBRK) \ + && (NGX_LINUX) \ + && !(NGX_HTTP_LUA_HAVE_CONSTRUCTOR) + ngx_http_lua_pre_config, /* preconfiguration */ +#else NULL, /* preconfiguration */ +#endif ngx_http_lua_init, /* postconfiguration */ ngx_http_lua_create_main_conf, /* create main configuration */ @@ -675,7 +689,7 @@ ngx_http_lua_init(ngx_conf_t *cf) } cln->data = lmcf; - cln->handler = ngx_http_lua_cleanup_semaphore_mm; + cln->handler = ngx_http_lua_sema_mm_cleanup; #endif @@ -747,8 +761,9 @@ ngx_http_lua_lowat_check(ngx_conf_t *cf, void *post, void *data) static void * ngx_http_lua_create_main_conf(ngx_conf_t *cf) { + ngx_int_t rc; + ngx_http_lua_main_conf_t *lmcf; - ngx_http_lua_semaphore_mm_t *mm; lmcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_lua_main_conf_t)); if (lmcf == NULL) { @@ -787,24 +802,10 @@ ngx_http_lua_create_main_conf(ngx_conf_t *cf) lmcf->postponed_to_rewrite_phase_end = NGX_CONF_UNSET; lmcf->postponed_to_access_phase_end = NGX_CONF_UNSET; - mm = ngx_palloc(cf->pool, sizeof(ngx_http_lua_semaphore_mm_t)); - if (mm == NULL) { + rc = ngx_http_lua_sema_mm_init(cf, lmcf); + if (rc != NGX_OK) { return NULL; } - - lmcf->semaphore_mm = mm; - mm->lmcf = lmcf; - - ngx_queue_init(&mm->free_queue); - mm->cur_epoch = 0; - mm->total = 0; - mm->used = 0; - - /* it's better to be 4096, but it needs some space for - * ngx_http_lua_semaphore_mm_block_t, one is enough, so it is 4095 - */ - mm->num_per_block = 4095; - dd("nginx Lua module main config structure initialized!"); return lmcf; @@ -876,6 +877,7 @@ ngx_http_lua_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) if (conf->ssl.cert_src.len == 0) { conf->ssl.cert_src = prev->ssl.cert_src; + conf->ssl.cert_src_key = prev->ssl.cert_src_key; conf->ssl.cert_handler = prev->ssl.cert_handler; } @@ -1158,4 +1160,35 @@ ngx_http_lua_set_ssl(ngx_conf_t *cf, ngx_http_lua_loc_conf_t *llcf) #endif /* NGX_HTTP_SSL */ + +#if (NGX_HTTP_LUA_HAVE_MMAP_SBRK) \ + && (NGX_LINUX) \ + && !(NGX_HTTP_LUA_HAVE_CONSTRUCTOR) +static ngx_int_t +ngx_http_lua_pre_config(ngx_conf_t *cf) +{ + ngx_http_lua_limit_data_segment(); + return NGX_OK; +} +#endif + + +/* + * we simply assume that LuaJIT is used. it does little harm when the + * standard Lua 5.1 interpreter is used instead. + */ +#if (NGX_HTTP_LUA_HAVE_MMAP_SBRK) && (NGX_LINUX) +# if (NGX_HTTP_LUA_HAVE_CONSTRUCTOR) +__attribute__((constructor)) +# endif +void +ngx_http_lua_limit_data_segment(void) +{ + if (sbrk(0) < (void *) 0x40000000LL) { + mmap(ngx_align_ptr(sbrk(0), getpagesize()), 1, PROT_READ, + MAP_FIXED|MAP_PRIVATE|MAP_ANON, -1, 0); + } +} +#endif + /* vi:set ft=c ts=4 sw=4 et fdm=marker: */ diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_output.c b/debian/modules/nginx-lua/src/ngx_http_lua_output.c index ef816d2..b410ba4 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_output.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_output.c @@ -147,11 +147,19 @@ ngx_http_lua_ngx_echo(lua_State *L, unsigned newline) } if (size == 0) { - /* do nothing for empty strings */ + rc = ngx_http_lua_send_header_if_needed(r, ctx); + if (rc == NGX_ERROR || rc > NGX_OK) { + lua_pushnil(L); + lua_pushliteral(L, "nginx output filter error"); + return 2; + } + lua_pushinteger(L, 1); return 1; } + ctx->seen_body_data = 1; + cl = ngx_http_lua_chain_get_free_buf(r->connection->log, r->pool, &ctx->free_bufs, size); @@ -511,7 +519,9 @@ ngx_http_lua_ngx_flush(lua_State *L) } #if 1 - if (!r->header_sent && !ctx->header_sent) { + if ((!r->header_sent && !ctx->header_sent) + || (!ctx->seen_body_data && !wait)) + { lua_pushnil(L); lua_pushliteral(L, "nothing to flush"); return 2; diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_regex.c b/debian/modules/nginx-lua/src/ngx_http_lua_regex.c index be110e3..d882061 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_regex.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_regex.c @@ -152,6 +152,7 @@ ngx_http_lua_ngx_re_match_helper(lua_State *L, int wantcaps) int nargs; int *cap = NULL; int ovecsize; + int has_ctx = 0; ngx_uint_t flags; ngx_pool_t *pool, *old_pool; ngx_http_lua_main_conf_t *lmcf; @@ -184,29 +185,34 @@ ngx_http_lua_ngx_re_match_helper(lua_State *L, int wantcaps) if (nargs >= 3) { opts.data = (u_char *) luaL_checklstring(L, 3, &opts.len); - if (nargs == 4) { - luaL_checktype(L, 4, LUA_TTABLE); - lua_getfield(L, 4, "pos"); - if (lua_isnumber(L, -1)) { - pos = (ngx_int_t) lua_tointeger(L, -1); - if (pos <= 0) { + if (nargs >= 4) { + if (!lua_isnil(L, 4)) { + luaL_checktype(L, 4, LUA_TTABLE); + has_ctx = 1; + + lua_getfield(L, 4, "pos"); + if (lua_isnumber(L, -1)) { + pos = (ngx_int_t) lua_tointeger(L, -1); + if (pos <= 0) { + pos = 0; + + } else { + pos--; /* 1-based on the Lua land */ + } + + } else if (lua_isnil(L, -1)) { pos = 0; } else { - pos--; /* 1-based on the Lua land */ + msg = lua_pushfstring(L, "bad pos field type in the ctx " + "table argument: %s", + luaL_typename(L, -1)); + + return luaL_argerror(L, 4, msg); } - } else if (lua_isnil(L, -1)) { - pos = 0; - - } else { - msg = lua_pushfstring(L, "bad pos field type in the ctx table " - "argument: %s", luaL_typename(L, -1)); - - return luaL_argerror(L, 4, msg); + lua_pop(L, 1); } - - lua_pop(L, 1); } } else { @@ -555,7 +561,7 @@ exec: dd("rc = %d", (int) rc); - if (nargs == 4) { /* having ctx table */ + if (has_ctx) { /* having ctx table */ pos = cap[1]; lua_pushinteger(L, (lua_Integer) (pos + 1)); lua_setfield(L, 4, "pos"); diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_req_body.c b/debian/modules/nginx-lua/src/ngx_http_lua_req_body.c index 591d2cd..6f2ae38 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_req_body.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_req_body.c @@ -548,7 +548,7 @@ ngx_http_lua_ngx_req_init_body(lua_State *L) if (n == 1) { num = luaL_checkinteger(L, 1); - if (num <= 0) { + if (num < 0) { return luaL_error(L, "bad size argument: %d", (int) num); } @@ -558,13 +558,10 @@ ngx_http_lua_ngx_req_init_body(lua_State *L) clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); size = clcf->client_body_buffer_size; + } - size += size >> 2; - - /* avoid allocating an unnecessary large buffer */ - if (size > (size_t) r->headers_in.content_length_n) { - size = (size_t) r->headers_in.content_length_n; - } + if (size == 0) { + r->request_body_in_file_only = 1; } rb = r->request_body; @@ -622,6 +619,8 @@ ngx_http_lua_ngx_req_append_body(lua_State *L) ngx_str_t body; size_t size, rest; size_t offset = 0; + ngx_chain_t chain; + ngx_buf_t buf; n = lua_gettop(L); @@ -642,7 +641,25 @@ ngx_http_lua_ngx_req_append_body(lua_State *L) || r->request_body->buf == NULL || r->request_body->bufs == NULL) { - return luaL_error(L, "request_body not initalized"); + return luaL_error(L, "request_body not initialized"); + } + + if (r->request_body_in_file_only) { + buf.start = body.data; + buf.pos = buf.start; + buf.last = buf.start + body.len; + buf.end = buf.last; + buf.temporary = 1; + + chain.buf = &buf; + chain.next = NULL; + + if (ngx_http_lua_write_request_body(r, &chain) != NGX_OK) { + return luaL_error(L, "fail to write file"); + } + + r->headers_in.content_length_n += body.len; + return 0; } rb = r->request_body; @@ -705,7 +722,7 @@ ngx_http_lua_ngx_req_body_finish(lua_State *L) || r->request_body->buf == NULL || r->request_body->bufs == NULL) { - return luaL_error(L, "request_body not initalized"); + return luaL_error(L, "request_body not initialized"); } rb = r->request_body; diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_semaphore.c b/debian/modules/nginx-lua/src/ngx_http_lua_semaphore.c index 8d4ac07..8a3f832 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_semaphore.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_semaphore.c @@ -21,21 +21,21 @@ #include "ngx_http_lua_contentby.h" -ngx_int_t ngx_http_lua_semaphore_init_mm(ngx_http_lua_semaphore_mm_t *mm); -static ngx_http_lua_semaphore_t *ngx_http_lua_alloc_semaphore(void); -void ngx_http_lua_cleanup_semaphore_mm(void *data); -static void ngx_http_lua_free_semaphore(ngx_http_lua_semaphore_t *sem); -static ngx_int_t ngx_http_lua_semaphore_resume(ngx_http_request_t *r); -int ngx_http_lua_ffi_semaphore_new(ngx_http_lua_semaphore_t **psem, +ngx_int_t ngx_http_lua_sema_mm_init(ngx_conf_t *cf, + ngx_http_lua_main_conf_t *lmcf); +void ngx_http_lua_sema_mm_cleanup(void *data); +static ngx_http_lua_sema_t *ngx_http_lua_alloc_sema(void); +static void ngx_http_lua_free_sema(ngx_http_lua_sema_t *sem); +static ngx_int_t ngx_http_lua_sema_resume(ngx_http_request_t *r); +int ngx_http_lua_ffi_sema_new(ngx_http_lua_sema_t **psem, int n, char **errmsg); -int ngx_http_lua_ffi_semaphore_post(ngx_http_lua_semaphore_t *sem, - int n); -int ngx_http_lua_ffi_semaphore_wait(ngx_http_request_t *r, - ngx_http_lua_semaphore_t *sem, int wait_ms, u_char *err, size_t *errlen); -static void ngx_http_lua_semaphore_cleanup(void *data); -static void ngx_http_lua_semaphore_handler(ngx_event_t *ev); -static void ngx_http_lua_semaphore_timeout_handler(ngx_event_t *ev); -void ngx_http_lua_ffi_semaphore_gc(ngx_http_lua_semaphore_t *sem); +int ngx_http_lua_ffi_sema_post(ngx_http_lua_sema_t *sem, int n); +int ngx_http_lua_ffi_sema_wait(ngx_http_request_t *r, + ngx_http_lua_sema_t *sem, int wait_ms, u_char *err, size_t *errlen); +static void ngx_http_lua_sema_cleanup(void *data); +static void ngx_http_lua_sema_handler(ngx_event_t *ev); +static void ngx_http_lua_sema_timeout_handler(ngx_event_t *ev); +void ngx_http_lua_ffi_sema_gc(ngx_http_lua_sema_t *sem); enum { @@ -44,34 +44,61 @@ enum { }; -static ngx_http_lua_semaphore_t * -ngx_http_lua_alloc_semaphore(void) +ngx_int_t +ngx_http_lua_sema_mm_init(ngx_conf_t *cf, ngx_http_lua_main_conf_t *lmcf) +{ + ngx_http_lua_sema_mm_t *mm; + + mm = ngx_palloc(cf->pool, sizeof(ngx_http_lua_sema_mm_t)); + if (mm == NULL) { + return NGX_ERROR; + } + + lmcf->sema_mm = mm; + mm->lmcf = lmcf; + + ngx_queue_init(&mm->free_queue); + mm->cur_epoch = 0; + mm->total = 0; + mm->used = 0; + + /* it's better to be 4096, but it needs some space for + * ngx_http_lua_sema_mm_block_t, one is enough, so it is 4095 + */ + mm->num_per_block = 4095; + + return NGX_OK; +} + + +static ngx_http_lua_sema_t * +ngx_http_lua_alloc_sema(void) { - ngx_http_lua_semaphore_t *sem, *iter; - ngx_http_lua_main_conf_t *lmcf; - ngx_queue_t *q; ngx_uint_t i, n; - ngx_http_lua_semaphore_mm_block_t *block; - ngx_http_lua_semaphore_mm_t *mm; + ngx_queue_t *q; + ngx_http_lua_sema_t *sem, *iter; + ngx_http_lua_sema_mm_t *mm; + ngx_http_lua_main_conf_t *lmcf; + ngx_http_lua_sema_mm_block_t *block; ngx_http_lua_assert(ngx_cycle && ngx_cycle->conf_ctx); lmcf = ngx_http_cycle_get_module_main_conf(ngx_cycle, ngx_http_lua_module); - mm = lmcf->semaphore_mm; + mm = lmcf->sema_mm; if (!ngx_queue_empty(&mm->free_queue)) { q = ngx_queue_head(&mm->free_queue); ngx_queue_remove(q); - sem = ngx_queue_data(q, ngx_http_lua_semaphore_t, chain); + sem = ngx_queue_data(q, ngx_http_lua_sema_t, chain); sem->block->used++; ngx_memzero(&sem->sem_event, sizeof(ngx_event_t)); - sem->sem_event.handler = ngx_http_lua_semaphore_handler; + sem->sem_event.handler = ngx_http_lua_sema_handler; sem->sem_event.data = sem; sem->sem_event.log = ngx_cycle->log; @@ -85,12 +112,12 @@ ngx_http_lua_alloc_semaphore(void) /* free_queue is empty */ - n = sizeof(ngx_http_lua_semaphore_mm_block_t) - + mm->num_per_block * sizeof(ngx_http_lua_semaphore_t); + n = sizeof(ngx_http_lua_sema_mm_block_t) + + mm->num_per_block * sizeof(ngx_http_lua_sema_t); dd("block size: %d, item size: %d", - (int) sizeof(ngx_http_lua_semaphore_mm_block_t), - (int) sizeof(ngx_http_lua_semaphore_t)); + (int) sizeof(ngx_http_lua_sema_mm_block_t), + (int) sizeof(ngx_http_lua_sema_t)); block = ngx_alloc(n, ngx_cycle->log); if (block == NULL) { @@ -104,13 +131,13 @@ ngx_http_lua_alloc_semaphore(void) block->mm = mm; block->epoch = mm->cur_epoch; - sem = (ngx_http_lua_semaphore_t *) (block + 1); + sem = (ngx_http_lua_sema_t *) (block + 1); sem->block = block; sem->block->used = 1; ngx_memzero(&sem->sem_event, sizeof(ngx_event_t)); - sem->sem_event.handler = ngx_http_lua_semaphore_handler; + sem->sem_event.handler = ngx_http_lua_sema_handler; sem->sem_event.data = sem; sem->sem_event.log = ngx_cycle->log; @@ -127,32 +154,32 @@ ngx_http_lua_alloc_semaphore(void) void -ngx_http_lua_cleanup_semaphore_mm(void *data) +ngx_http_lua_sema_mm_cleanup(void *data) { - ngx_http_lua_semaphore_t *sem, *iter; ngx_uint_t i; - ngx_http_lua_main_conf_t *lmcf; ngx_queue_t *q; - ngx_http_lua_semaphore_mm_block_t *block; - ngx_http_lua_semaphore_mm_t *mm; + ngx_http_lua_sema_t *sem, *iter; + ngx_http_lua_sema_mm_t *mm; + ngx_http_lua_main_conf_t *lmcf; + ngx_http_lua_sema_mm_block_t *block; lmcf = (ngx_http_lua_main_conf_t *) data; - mm = lmcf->semaphore_mm; + mm = lmcf->sema_mm; while (!ngx_queue_empty(&mm->free_queue)) { q = ngx_queue_head(&mm->free_queue); - sem = ngx_queue_data(q, ngx_http_lua_semaphore_t, chain); + sem = ngx_queue_data(q, ngx_http_lua_sema_t, chain); block = sem->block; if (block->used == 0) { - iter = (ngx_http_lua_semaphore_t *) (block + 1); + iter = (ngx_http_lua_sema_t *) (block + 1); for (i = 0; i < block->mm->num_per_block; i++, iter++) { ngx_queue_remove(&iter->chain); } - dd("free semaphore block: %p at final", block); + dd("free sema block: %p at final", block); ngx_free(block); @@ -160,24 +187,24 @@ ngx_http_lua_cleanup_semaphore_mm(void *data) /* just return directly when some thing goes wrong */ ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, - "ngx_http_lua_cleanup_semaphore_mm when cleanup" - " block %p is still used by someone", block); + "lua sema mm: freeing a block %p that is still " + " used by someone", block); return; } } - dd("ngx_http_lua_cleanup_semaphore_mm"); + dd("lua sema mm cleanup done"); } static void -ngx_http_lua_free_semaphore(ngx_http_lua_semaphore_t *sem) +ngx_http_lua_free_sema(ngx_http_lua_sema_t *sem) { - ngx_http_lua_semaphore_t *iter; - ngx_uint_t i, mid_epoch; - ngx_http_lua_semaphore_mm_block_t *block; - ngx_http_lua_semaphore_mm_t *mm; + ngx_http_lua_sema_t *iter; + ngx_uint_t i, mid_epoch; + ngx_http_lua_sema_mm_block_t *block; + ngx_http_lua_sema_mm_t *mm; block = sem->block; block->used--; @@ -209,7 +236,7 @@ ngx_http_lua_free_semaphore(ngx_http_lua_semaphore_t *sem) && block->epoch < mid_epoch) { /* load <= 50% and it's on the older side */ - iter = (ngx_http_lua_semaphore_t *) (block + 1); + iter = (ngx_http_lua_sema_t *) (block + 1); for (i = 0; i < mm->num_per_block; i++, iter++) { ngx_queue_remove(&iter->chain); @@ -226,7 +253,7 @@ ngx_http_lua_free_semaphore(ngx_http_lua_semaphore_t *sem) static ngx_int_t -ngx_http_lua_semaphore_resume(ngx_http_request_t *r) +ngx_http_lua_sema_resume(ngx_http_request_t *r) { lua_State *vm; ngx_connection_t *c; @@ -278,12 +305,12 @@ ngx_http_lua_semaphore_resume(ngx_http_request_t *r) int -ngx_http_lua_ffi_semaphore_new(ngx_http_lua_semaphore_t **psem, +ngx_http_lua_ffi_sema_new(ngx_http_lua_sema_t **psem, int n, char **errmsg) { - ngx_http_lua_semaphore_t *sem; + ngx_http_lua_sema_t *sem; - sem = ngx_http_lua_alloc_semaphore(); + sem = ngx_http_lua_alloc_sema(); if (sem == NULL) { *errmsg = "no memory"; return NGX_ERROR; @@ -304,7 +331,7 @@ ngx_http_lua_ffi_semaphore_new(ngx_http_lua_semaphore_t **psem, int -ngx_http_lua_ffi_semaphore_post(ngx_http_lua_semaphore_t *sem, int n) +ngx_http_lua_ffi_sema_post(ngx_http_lua_sema_t *sem, int n) { ngx_log_debug3(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, "http lua semaphore post: %p, n: %d, resources: %d", @@ -325,8 +352,8 @@ ngx_http_lua_ffi_semaphore_post(ngx_http_lua_semaphore_t *sem, int n) int -ngx_http_lua_ffi_semaphore_wait(ngx_http_request_t *r, - ngx_http_lua_semaphore_t *sem, int wait_ms, u_char *err, size_t *errlen) +ngx_http_lua_ffi_sema_wait(ngx_http_request_t *r, + ngx_http_lua_sema_t *sem, int wait_ms, u_char *err, size_t *errlen) { ngx_http_lua_ctx_t *ctx; ngx_http_lua_co_ctx_t *wait_co_ctx; @@ -361,7 +388,7 @@ ngx_http_lua_ffi_semaphore_wait(ngx_http_request_t *r, } /* we keep the order, will resume the older waited firtly - * in ngx_http_lua_semaphore_handler + * in ngx_http_lua_sema_handler */ if (ngx_queue_empty(&sem->wait_queue) && sem->resource_count > 0) { @@ -376,19 +403,19 @@ ngx_http_lua_ffi_semaphore_wait(ngx_http_request_t *r, sem->wait_count++; wait_co_ctx = ctx->cur_co_ctx; - wait_co_ctx->sleep.handler = ngx_http_lua_semaphore_timeout_handler; + wait_co_ctx->sleep.handler = ngx_http_lua_sema_timeout_handler; wait_co_ctx->sleep.data = ctx->cur_co_ctx; wait_co_ctx->sleep.log = r->connection->log; ngx_add_timer(&wait_co_ctx->sleep, (ngx_msec_t) wait_ms); - dd("ngx_http_lua_ffi_semaphore_wait add timer coctx:%p wait: %d(ms)", + dd("ngx_http_lua_ffi_sema_wait add timer coctx:%p wait: %d(ms)", wait_co_ctx, wait_ms); ngx_queue_insert_tail(&sem->wait_queue, &wait_co_ctx->sem_wait_queue); wait_co_ctx->data = sem; - wait_co_ctx->cleanup = ngx_http_lua_semaphore_cleanup; + wait_co_ctx->cleanup = ngx_http_lua_sema_cleanup; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, "http lua semaphore wait yielding"); @@ -398,18 +425,18 @@ ngx_http_lua_ffi_semaphore_wait(ngx_http_request_t *r, int -ngx_http_lua_ffi_semaphore_count(ngx_http_lua_semaphore_t *sem) +ngx_http_lua_ffi_sema_count(ngx_http_lua_sema_t *sem) { return sem->resource_count - sem->wait_count; } static void -ngx_http_lua_semaphore_cleanup(void *data) +ngx_http_lua_sema_cleanup(void *data) { ngx_http_lua_co_ctx_t *coctx = data; ngx_queue_t *q; - ngx_http_lua_semaphore_t *sem; + ngx_http_lua_sema_t *sem; sem = coctx->data; @@ -429,9 +456,9 @@ ngx_http_lua_semaphore_cleanup(void *data) static void -ngx_http_lua_semaphore_handler(ngx_event_t *ev) +ngx_http_lua_sema_handler(ngx_event_t *ev) { - ngx_http_lua_semaphore_t *sem; + ngx_http_lua_sema_t *sem; ngx_http_request_t *r; ngx_http_lua_ctx_t *ctx; ngx_http_lua_co_ctx_t *wait_co_ctx; @@ -467,10 +494,10 @@ ngx_http_lua_semaphore_handler(ngx_event_t *ev) wait_co_ctx->sem_resume_status = SEMAPHORE_WAIT_SUCC; if (ctx->entered_content_phase) { - (void) ngx_http_lua_semaphore_resume(r); + (void) ngx_http_lua_sema_resume(r); } else { - ctx->resume_handler = ngx_http_lua_semaphore_resume; + ctx->resume_handler = ngx_http_lua_sema_resume; ngx_http_core_run_phases(r); } @@ -480,18 +507,18 @@ ngx_http_lua_semaphore_handler(ngx_event_t *ev) static void -ngx_http_lua_semaphore_timeout_handler(ngx_event_t *ev) +ngx_http_lua_sema_timeout_handler(ngx_event_t *ev) { ngx_http_lua_co_ctx_t *wait_co_ctx; ngx_http_request_t *r; ngx_http_lua_ctx_t *ctx; ngx_connection_t *c; - ngx_http_lua_semaphore_t *sem; + ngx_http_lua_sema_t *sem; wait_co_ctx = ev->data; wait_co_ctx->cleanup = NULL; - dd("ngx_http_lua_semaphore_timeout_handler timeout coctx:%p", wait_co_ctx); + dd("ngx_http_lua_sema_timeout_handler timeout coctx:%p", wait_co_ctx); sem = wait_co_ctx->data; @@ -509,10 +536,10 @@ ngx_http_lua_semaphore_timeout_handler(ngx_event_t *ev) wait_co_ctx->sem_resume_status = SEMAPHORE_WAIT_TIMEOUT; if (ctx->entered_content_phase) { - (void) ngx_http_lua_semaphore_resume(r); + (void) ngx_http_lua_sema_resume(r); } else { - ctx->resume_handler = ngx_http_lua_semaphore_resume; + ctx->resume_handler = ngx_http_lua_sema_resume; ngx_http_core_run_phases(r); } @@ -521,7 +548,7 @@ ngx_http_lua_semaphore_timeout_handler(ngx_event_t *ev) void -ngx_http_lua_ffi_semaphore_gc(ngx_http_lua_semaphore_t *sem) +ngx_http_lua_ffi_sema_gc(ngx_http_lua_sema_t *sem) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, "in lua gc, semaphore %p", sem); @@ -537,7 +564,7 @@ ngx_http_lua_ffi_semaphore_gc(ngx_http_lua_semaphore_t *sem) "destroyed", sem); } - ngx_http_lua_free_semaphore(sem); + ngx_http_lua_free_sema(sem); } diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_semaphore.h b/debian/modules/nginx-lua/src/ngx_http_lua_semaphore.h index a71cc23..65ba8ff 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_semaphore.h +++ b/debian/modules/nginx-lua/src/ngx_http_lua_semaphore.h @@ -14,14 +14,14 @@ #include "ngx_http_lua_common.h" -typedef struct ngx_http_lua_semaphore_mm_block_s { +typedef struct ngx_http_lua_sema_mm_block_s { ngx_uint_t used; - ngx_http_lua_semaphore_mm_t *mm; + ngx_http_lua_sema_mm_t *mm; ngx_uint_t epoch; -} ngx_http_lua_semaphore_mm_block_t; +} ngx_http_lua_sema_mm_block_t; -struct ngx_http_lua_semaphore_mm_s { +struct ngx_http_lua_sema_mm_s { ngx_queue_t free_queue; ngx_uint_t total; ngx_uint_t used; @@ -31,18 +31,20 @@ struct ngx_http_lua_semaphore_mm_s { }; -typedef struct ngx_http_lua_semaphore_s { +typedef struct ngx_http_lua_sema_s { ngx_queue_t wait_queue; ngx_queue_t chain; ngx_event_t sem_event; - ngx_http_lua_semaphore_mm_block_t *block; + ngx_http_lua_sema_mm_block_t *block; int resource_count; unsigned wait_count; -} ngx_http_lua_semaphore_t; +} ngx_http_lua_sema_t; #ifndef NGX_LUA_NO_FFI_API -void ngx_http_lua_cleanup_semaphore_mm(void *data); +void ngx_http_lua_sema_mm_cleanup(void *data); +ngx_int_t ngx_http_lua_sema_mm_init(ngx_conf_t *cf, + ngx_http_lua_main_conf_t *lmcf); #endif diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_socket_tcp.c b/debian/modules/nginx-lua/src/ngx_http_lua_socket_tcp.c index 1a6594d..2bfdbd3 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_socket_tcp.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_socket_tcp.c @@ -1181,8 +1181,8 @@ ngx_http_lua_socket_tcp_sslhandshake(lua_State *L) /* Lua function arguments: self [,session] [,host] [,verify] */ n = lua_gettop(L); - if (n < 1 && n > 4) { - return luaL_error(L, "ngx.socket connect: expecting 1 ~ 4 " + if (n < 1 || n > 5) { + return luaL_error(L, "ngx.socket connect: expecting 1 ~ 5 " "arguments (including the object), but seen %d", n); } diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_ssl_certby.c b/debian/modules/nginx-lua/src/ngx_http_lua_ssl_certby.c index c4e6a83..c06bc8e 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_ssl_certby.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_ssl_certby.c @@ -656,6 +656,8 @@ failed: X509_free(x509); } + ERR_clear_error(); + return NGX_ERROR; # endif /* OPENSSL_VERSION_NUMBER < 0x1000205fL */ @@ -714,6 +716,8 @@ failed: BIO_free(bio); } + ERR_clear_error(); + return NGX_ERROR; } @@ -842,12 +846,15 @@ ngx_http_lua_ffi_cert_pem_to_der(const u_char *pem, size_t pem_len, u_char *der, bio = BIO_new_mem_buf((char *) pem, (int) pem_len); if (bio == NULL) { *err = "BIO_new_mem_buf() failed"; + ERR_clear_error(); return NGX_ERROR; } x509 = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL); if (x509 == NULL) { *err = "PEM_read_bio_X509_AUX() failed"; + BIO_free(bio); + ERR_clear_error(); return NGX_ERROR; } @@ -856,6 +863,7 @@ ngx_http_lua_ffi_cert_pem_to_der(const u_char *pem, size_t pem_len, u_char *der, *err = "i2d_X509() failed"; X509_free(x509); BIO_free(bio); + ERR_clear_error(); return NGX_ERROR; } @@ -881,6 +889,7 @@ ngx_http_lua_ffi_cert_pem_to_der(const u_char *pem, size_t pem_len, u_char *der, *err = "PEM_read_bio_X509() failed"; BIO_free(bio); + ERR_clear_error(); return NGX_ERROR; } @@ -889,6 +898,7 @@ ngx_http_lua_ffi_cert_pem_to_der(const u_char *pem, size_t pem_len, u_char *der, *err = "i2d_X509() failed"; X509_free(x509); BIO_free(bio); + ERR_clear_error(); return NGX_ERROR; } @@ -914,6 +924,7 @@ ngx_http_lua_ffi_priv_key_pem_to_der(const u_char *pem, size_t pem_len, in = BIO_new_mem_buf((char *) pem, (int) pem_len); if (in == NULL) { *err = "BIO_new_mem_buf() failed"; + ERR_clear_error(); return NGX_ERROR; } @@ -921,6 +932,7 @@ ngx_http_lua_ffi_priv_key_pem_to_der(const u_char *pem, size_t pem_len, if (pkey == NULL) { BIO_free(in); *err = "PEM_read_bio_PrivateKey failed"; + ERR_clear_error(); return NGX_ERROR; } @@ -930,6 +942,7 @@ ngx_http_lua_ffi_priv_key_pem_to_der(const u_char *pem, size_t pem_len, if (len < 0) { EVP_PKEY_free(pkey); *err = "i2d_PrivateKey failed"; + ERR_clear_error(); return NGX_ERROR; } diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_ssl_ocsp.c b/debian/modules/nginx-lua/src/ngx_http_lua_ssl_ocsp.c index 9f9e276..1bf4335 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_ssl_ocsp.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_ssl_ocsp.c @@ -137,6 +137,10 @@ done: BIO_free(bio); } + if (rc == NGX_ERROR) { + ERR_clear_error(); + } + return rc; #endif /* NGX_HTTP_LUA_USE_OCSP */ @@ -229,6 +233,8 @@ ngx_http_lua_ffi_ssl_create_ocsp_request(const char *chain_data, X509_free(cert); BIO_free(bio); + ERR_clear_error(); + return NGX_OK; failed: diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_timer.c b/debian/modules/nginx-lua/src/ngx_http_lua_timer.c index 393eac7..96c0ace 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_timer.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_timer.c @@ -359,7 +359,6 @@ ngx_http_lua_timer_handler(ngx_event_t *ev) ngx_memcpy(&tctx, ev->data, sizeof(ngx_http_lua_timer_ctx_t)); ngx_free(ev); - ev = NULL; lmcf = tctx.lmcf; diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_util.c b/debian/modules/nginx-lua/src/ngx_http_lua_util.c index 69eccae..1bd1388 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_util.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_util.c @@ -907,17 +907,17 @@ ngx_http_lua_request_cleanup(ngx_http_lua_ctx_t *ctx, int forcible) ngx_http_request_t *r; ngx_http_lua_main_conf_t *lmcf; - r = ctx->request; - - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "lua request cleanup: forcible=%d", forcible); - /* force coroutine handling the request quit */ if (ctx == NULL) { dd("ctx is NULL"); return; } + r = ctx->request; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "lua request cleanup: forcible=%d", forcible); + if (ctx->cleanup) { *ctx->cleanup = NULL; ctx->cleanup = NULL; diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_variable.c b/debian/modules/nginx-lua/src/ngx_http_lua_variable.c index 0de9312..b26c862 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_variable.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_variable.c @@ -185,7 +185,7 @@ ngx_http_lua_var_set(lua_State *L) val = ngx_palloc(r->pool, len); if (val == NULL) { - return luaL_error(L, "memory allocation erorr"); + return luaL_error(L, "memory allocation error"); } ngx_memcpy(val, p, len); @@ -460,6 +460,7 @@ ngx_http_lua_ffi_var_set(ngx_http_request_t *r, u_char *name_data, if (p == NULL) { goto nomem; } + ngx_memcpy(p, value, value_len); value = p; diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_worker.c b/debian/modules/nginx-lua/src/ngx_http_lua_worker.c index 44faf48..ff09b5b 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_worker.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_worker.c @@ -60,6 +60,13 @@ static int ngx_http_lua_ngx_worker_id(lua_State *L) { #if (nginx_version >= 1009001) + if (ngx_process != NGX_PROCESS_WORKER + && ngx_process != NGX_PROCESS_SINGLE) + { + lua_pushnil(L); + return 1; + } + lua_pushinteger(L, (lua_Integer) ngx_worker); #else lua_pushnil(L); @@ -93,6 +100,12 @@ int ngx_http_lua_ffi_worker_id(void) { #if (nginx_version >= 1009001) + if (ngx_process != NGX_PROCESS_WORKER + && ngx_process != NGX_PROCESS_SINGLE) + { + return -1; + } + return (int) ngx_worker; #else return -1; diff --git a/debian/modules/nginx-lua/t/015-status.t b/debian/modules/nginx-lua/t/015-status.t index 2e026f1..666dae7 100644 --- a/debian/modules/nginx-lua/t/015-status.t +++ b/debian/modules/nginx-lua/t/015-status.t @@ -9,7 +9,7 @@ log_level('warn'); #repeat_each(120); repeat_each(2); -plan tests => repeat_each() * (blocks() * 2 + 7); +plan tests => repeat_each() * (blocks() * 2 + 9); #no_diff(); #no_long_string(); @@ -270,3 +270,24 @@ ngx.status = 502 --- no_error_log [error] + + +=== TEST 16: ngx.status assignmnt should clear r->err_status +--- config +location = /t { + return 502; + header_filter_by_lua_block { + if ngx.status == 502 then + ngx.status = 654 + ngx.log(ngx.WARN, "ngx.status: ", ngx.status) + end + } +} +--- request +GET /t +--- response_body_like: Bad Gateway +--- error_log +ngx.status: 654 +--- no_error_log +[error] +--- error_code: 654 diff --git a/debian/modules/nginx-lua/t/024-access/mixed.t b/debian/modules/nginx-lua/t/024-access/mixed.t index d801216..a9f8039 100644 --- a/debian/modules/nginx-lua/t/024-access/mixed.t +++ b/debian/modules/nginx-lua/t/024-access/mixed.t @@ -245,3 +245,17 @@ access cached: hello --- log_level: info + + +=== TEST 7: I/O in access shortcuts content automatically +--- config + location = /t { + access_by_lua_block { + ngx.print("") + } + + echo ok; + } +--- request + GET /t +--- response_body diff --git a/debian/modules/nginx-lua/t/034-match.t b/debian/modules/nginx-lua/t/034-match.t index 4792ae6..35149f1 100644 --- a/debian/modules/nginx-lua/t/034-match.t +++ b/debian/modules/nginx-lua/t/034-match.t @@ -9,7 +9,7 @@ use Test::Nginx::Socket::Lua; repeat_each(2); -plan tests => repeat_each() * (blocks() * 2 + 14); +plan tests => repeat_each() * (blocks() * 2 + 15); #no_diff(); no_long_string(); @@ -1124,6 +1124,8 @@ failed to match 1: res size: 2 2: m size: 2 2: res size: 2 +--- no_error_log +[error] @@ -1169,3 +1171,22 @@ hello hello false + + +=== TEST 50: the 5th argument hides the 4th (GitHub #719) +--- config + location /re { + content_by_lua ' + local ctx, m = { pos = 5 }, {}; + local _, err = ngx.re.match("20172016-11-3 03:07:09", [=[(\d\d\d\d)]=], "", ctx, m); + if m then + ngx.say(m[0], " ", _[0], " ", ctx.pos) + else + ngx.say("not matched!") + end + '; + } +--- request + GET /re +--- response_body +2016 2016 9 diff --git a/debian/modules/nginx-lua/t/043-shdict.t b/debian/modules/nginx-lua/t/043-shdict.t index 91a4196..cd160f7 100644 --- a/debian/modules/nginx-lua/t/043-shdict.t +++ b/debian/modules/nginx-lua/t/043-shdict.t @@ -1584,7 +1584,7 @@ cur value: hello hello hello hello hello hello hello hello hello hello1 content_by_lua ' local dogs = ngx.shared.dogs dogs:set("foo", 32, 0.01) - dogs:set("blah", 33, 0.1) + dogs:set("blah", 33, 0.3) ngx.sleep(0.02) local val, flags, stale = dogs:get_stale("foo") ngx.say(val, ", ", flags, ", ", stale) diff --git a/debian/modules/nginx-lua/t/044-req-body.t b/debian/modules/nginx-lua/t/044-req-body.t index 1c1be40..28fa818 100644 --- a/debian/modules/nginx-lua/t/044-req-body.t +++ b/debian/modules/nginx-lua/t/044-req-body.t @@ -1630,3 +1630,111 @@ request body:hello, world --- no_error_log [error] [alert] + + + +=== TEST 50: init & append & finish (content_length = 0) +--- config + location /t { + content_by_lua ' + local old_http_content_length = ngx.var.http_content_length + + ngx.req.read_body() + ngx.req.init_body() + ngx.req.append_body("he") + ngx.req.append_body("llo") + ngx.req.finish_body() + + ngx.say("old content length: ", old_http_content_length) + + local data = ngx.req.get_body_data() + local data_file = ngx.req.get_body_file() + + if not data and data_file then + ngx.say("no data in buf, go to data file") + end + + ngx.say("content length: ", ngx.var.http_content_length) + '; + } +--- request + GET /t +--- more_headers +Content-Length: 0 +--- response_body +old content length: 0 +content length: 5 +--- no_error_log +[error] +[alert] + + + +=== TEST 51: init & append & finish (init_body(0)) +--- config + location /t { + content_by_lua ' + local old_http_content_length = ngx.var.http_content_length + + ngx.req.read_body() + ngx.req.init_body(0) + ngx.req.append_body("he") + ngx.req.append_body("llo") + ngx.req.finish_body() + + ngx.say("old content length: ", old_http_content_length) + + local data = ngx.req.get_body_data() + local data_file = ngx.req.get_body_file() + + if not data and data_file then + ngx.say("no data in buf, go to data file") + end + + ngx.say("content length: ", ngx.var.http_content_length) + '; + } +--- request + GET /t +--- more_headers +Content-Length: 0 +--- response_body +old content length: 0 +no data in buf, go to data file +content length: 5 +--- no_error_log +[error] +[alert] + + + +=== TEST 52: init & append & finish (client_body_buffer_size = 0) +--- http_config + client_body_buffer_size 0; +--- config + location /t { + content_by_lua ' + ngx.req.read_body() + ngx.req.init_body() + ngx.req.append_body("he") + ngx.req.append_body("llo") + ngx.req.finish_body() + + local data = ngx.req.get_body_data() + local data_file = ngx.req.get_body_file() + + if not data and data_file then + ngx.say("no data in buf, go to data file") + end + + ngx.say("content length: ", ngx.var.http_content_length) + '; + } +--- request + GET /t +--- response_body +no data in buf, go to data file +content length: 5 +--- no_error_log +[error] +[alert] diff --git a/debian/modules/nginx-lua/t/058-tcp-socket.t b/debian/modules/nginx-lua/t/058-tcp-socket.t index b9e4175..acf69f0 100644 --- a/debian/modules/nginx-lua/t/058-tcp-socket.t +++ b/debian/modules/nginx-lua/t/058-tcp-socket.t @@ -2039,6 +2039,7 @@ resolve name done === TEST 34: github issue #215: Handle the posted requests in lua cosocket api (successfully resolved) --- config resolver $TEST_NGINX_RESOLVER; + resolver_timeout 5s; location = /sub { content_by_lua ' @@ -2053,7 +2054,7 @@ resolve name done local sock = ngx.socket.tcp() local ok, err = sock:connect(server, 80) if not ok then - ngx.say("failed to connect to agentzh.org: ", err) + ngx.say("failed to connect to ", server, ": ", err) return end ngx.say("successfully connected to xxx!") @@ -3298,6 +3299,7 @@ failed to receive a line: closed [] close: 1 nil --- no_error_log [error] +--- skip_eval: 3: system("ping6 -c 1 ::1 >/dev/null 2>&1") ne 0 diff --git a/debian/modules/nginx-lua/t/087-udp-socket.t b/debian/modules/nginx-lua/t/087-udp-socket.t index 39ff54f..79ba452 100644 --- a/debian/modules/nginx-lua/t/087-udp-socket.t +++ b/debian/modules/nginx-lua/t/087-udp-socket.t @@ -710,7 +710,7 @@ resolve name done === TEST 13: github issue #215: Handle the posted requests in lua cosocket api (successfully resolved) --- config resolver $TEST_NGINX_RESOLVER; - resolver_timeout 3s; + resolver_timeout 5s; location = /sub { content_by_lua ' @@ -725,7 +725,7 @@ resolve name done local sock = ngx.socket.udp() local ok, err = sock:setpeername(server, 80) if not ok then - ngx.say("failed to connect to agentzh.org: ", err) + ngx.say("failed to connect to ", server, ": ", err) return end ngx.say("successfully connected to xxx!") diff --git a/debian/modules/nginx-lua/t/129-ssl-socket.t b/debian/modules/nginx-lua/t/129-ssl-socket.t index 4921099..c19853d 100644 --- a/debian/modules/nginx-lua/t/129-ssl-socket.t +++ b/debian/modules/nginx-lua/t/129-ssl-socket.t @@ -4,7 +4,7 @@ use Test::Nginx::Socket::Lua; repeat_each(2); -plan tests => repeat_each() * (blocks() * 7); +plan tests => repeat_each() * 219; $ENV{TEST_NGINX_HTML_DIR} ||= html_dir(); @@ -2584,3 +2584,37 @@ SSL reused session [alert] --- timeout: 5 + + +=== TEST 32: handshake, too many arguments +--- config + server_tokens off; + resolver $TEST_NGINX_RESOLVER; + location /t { + #set $port 5000; + set $port $TEST_NGINX_MEMCACHED_PORT; + + content_by_lua_block { + local sock = ngx.socket.tcp() + sock:settimeout(2000) + + local ok, err = sock:connect("g.sregex.org", 443) + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local session, err = sock.sslhandshake() + } + } + +--- request +GET /t +--- ignore_response +--- error_log eval +qr/\[error\] .* ngx.socket connect: expecting 1 ~ 5 arguments \(including the object\), but seen 0/ +--- no_error_log +[alert] +--- timeout: 5 diff --git a/debian/modules/nginx-lua/t/132-lua-blocks.t b/debian/modules/nginx-lua/t/132-lua-blocks.t index d157d27..e2933e9 100644 --- a/debian/modules/nginx-lua/t/132-lua-blocks.t +++ b/debian/modules/nginx-lua/t/132-lua-blocks.t @@ -10,7 +10,7 @@ use Test::Nginx::Socket::Lua; repeat_each(2); #repeat_each(1); -plan tests => repeat_each() * (blocks() * 3 + 4); +plan tests => repeat_each() * (blocks() * 3 + 3); #no_diff(); no_long_string(); @@ -405,7 +405,7 @@ hello, world! -=== TEST 16: content_by_lua_block (unexpected closing long brackets) +=== TEST 16: content_by_lua_block unexpected closing long brackets must FAIL --- config location = /t { content_by_lua_block { @@ -414,15 +414,30 @@ hello, world! } --- request GET /t +--- error_code: 500 +--- error_log eval +qr{\[error\] .*? unexpected symbol near ']'} + + + +=== TEST 17: content_by_lua_block unexpected closing long brackets ignored (GitHub #748) +--- config + location = /t { + content_by_lua_block { + local t1, t2 = {"hello world"}, {1} + ngx.say(t1[t2[1]]) + } + } +--- request +GET /t +--- response_body +hello world --- no_error_log [error] ---- error_log eval -qr{\[emerg\] .*? unexpected lua closing long-bracket in .*?/nginx\.conf:41} ---- must_die -=== TEST 17: simple set_by_lua_block (integer) +=== TEST 18: simple set_by_lua_block (integer) --- config location /lua { set_by_lua_block $res { return 1+1 } @@ -437,7 +452,7 @@ GET /lua -=== TEST 18: ambiguous line comments inside a long bracket string (GitHub #596) +=== TEST 19: ambiguous line comments inside a long bracket string (GitHub #596) --- config location = /t { content_by_lua_block { @@ -459,7 +474,7 @@ done -=== TEST 19: double quotes in long brackets +=== TEST 20: double quotes in long brackets --- config location = /t { rewrite_by_lua_block { print([[Hey, it is "!]]) } content_by_lua_block { ngx.say([["]]) } @@ -475,7 +490,7 @@ Hey, it is "! -=== TEST 20: single quotes in long brackets +=== TEST 21: single quotes in long brackets --- config location = /t { rewrite_by_lua_block { print([[Hey, it is '!]]) } content_by_lua_block { ngx.say([[']]) } @@ -491,7 +506,7 @@ Hey, it is '! -=== TEST 21: lexer no match due to incomplete data chunks in a fixed size buffer +=== TEST 22: lexer no match due to incomplete data chunks in a fixed size buffer --- config location /test1 { content_by_lua_block { diff --git a/debian/modules/nginx-lua/t/135-worker-id.t b/debian/modules/nginx-lua/t/135-worker-id.t index 752b406..3c1f24d 100644 --- a/debian/modules/nginx-lua/t/135-worker-id.t +++ b/debian/modules/nginx-lua/t/135-worker-id.t @@ -3,13 +3,13 @@ use Test::Nginx::Socket::Lua; #worker_connections(1014); -#master_on(); +master_on(); workers(2); #log_level('warn'); -repeat_each(2); +#repeat_each(2); -plan tests => repeat_each() * (blocks() * 3); +plan tests => repeat_each() * (blocks() * 3 + 1); #no_diff(); #no_long_string(); @@ -31,3 +31,63 @@ GET /lua --- no_error_log [error] --- skip_nginx: 3: <=1.9.0 + + + +=== TEST 2: worker id should be nil for non-worker processes +--- http_config + proxy_cache_path conf/cache levels=1:2 keys_zone=my-cache:8m max_size=10m inactive=60m; + proxy_temp_path conf/temp; + + lua_shared_dict counters 1m; + + init_by_lua_block { + ngx.shared.counters:set("c", 0) + } + + init_worker_by_lua_block { + ngx.shared.counters:incr("c", 1) + ngx.log(ngx.INFO, ngx.worker.pid(), ": worker id ", ngx.worker.id()); + } +--- config + location = /t { + content_by_lua_block { + local counters = ngx.shared.counters + local ok, c + for i = 1, 45 do + c = counters:get("c") + if c >= 4 then + ok = true + break + end + local delay = 0.001 * i + if delay > 0.1 then + delay = 0.1 + end + ngx.sleep(delay) + end + if ok then + ngx.say("ok") + else + ngx.say("not ok: c=", c) + end + } + } + location /cache { + proxy_pass http://127.0.0.1:$server_port; + proxy_cache my-cache; + } +--- request +GET /t +--- response_body +ok +--- grep_error_log eval: qr/worker id nil/ +--- grep_error_log_out +worker id nil +worker id nil +--- no_error_log +[error] +--- wait: 0.1 +--- skip_nginx: 3: <=1.9.0 +--- log_level: info +--- timeout: 6 diff --git a/debian/modules/nginx-lua/t/139-ssl-cert-by.t b/debian/modules/nginx-lua/t/139-ssl-cert-by.t index e40fe85..9297a0d 100644 --- a/debian/modules/nginx-lua/t/139-ssl-cert-by.t +++ b/debian/modules/nginx-lua/t/139-ssl-cert-by.t @@ -1380,3 +1380,98 @@ close: 1 nil uthread: thread created: running uthread: hello in thread uthread: done + + + +=== TEST 17: simple logging - use ssl_certificiate_by_lua* on the http {} level +GitHub openresty/lua-resty-core#42 +--- http_config + ssl_certificate_by_lua_block { print("ssl cert by lua is running!") } + ssl_certificate ../../cert/test.crt; + ssl_certificate_key ../../cert/test.key; + + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + server_tokens off; + location /foo { + default_type 'text/plain'; + content_by_lua_block { ngx.status = 201 ngx.say("foo") ngx.exit(201) } + more_clear_headers Date; + } + } +--- config + server_tokens off; + lua_ssl_trusted_certificate ../../cert/test.crt; + + location /t { + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(2000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(nil, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + local req = "GET /foo HTTP/1.0\r\nHost: test.com\r\nConnection: close\r\n\r\n" + local bytes, err = sock:send(req) + if not bytes then + ngx.say("failed to send http request: ", err) + return + end + + ngx.say("sent http request: ", bytes, " bytes.") + + while true do + local line, err = sock:receive() + if not line then + -- ngx.say("failed to recieve response status line: ", err) + break + end + + ngx.say("received: ", line) + end + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: userdata +sent http request: 56 bytes. +received: HTTP/1.1 201 Created +received: Server: nginx +received: Content-Type: text/plain +received: Content-Length: 4 +received: Connection: close +received: +received: foo +close: 1 nil + +--- error_log +lua ssl server name: "test.com" +ssl_certificate_by_lua:1: ssl cert by lua is running! + +--- no_error_log +[error] +[alert] diff --git a/debian/modules/nginx-lua/t/140-ssl-c-api.t b/debian/modules/nginx-lua/t/140-ssl-c-api.t index 9812de2..4ecc2cd 100644 --- a/debian/modules/nginx-lua/t/140-ssl-c-api.t +++ b/debian/modules/nginx-lua/t/140-ssl-c-api.t @@ -11,7 +11,7 @@ my $openssl_version = eval { `$NginxBinary -V 2>&1` }; if ($openssl_version =~ m/built with OpenSSL (0|1\.0\.(?:0|1[^\d]|2[a-d]).*)/) { plan(skip_all => "too old OpenSSL, need 1.0.2e, was $1"); } else { - plan tests => repeat_each() * (blocks() * 5); + plan tests => repeat_each() * (blocks() * 5 + 1); } $ENV{TEST_NGINX_HTML_DIR} ||= html_dir(); @@ -361,3 +361,139 @@ lua ssl server name: "test.com" --- no_error_log [error] [alert] + + + +=== TEST 3: Handshake continue when cert_pem_to_der errors +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + + ssl_certificate_by_lua_block { + collectgarbage() + + local ffi = require "ffi" + + ffi.cdef[[ + int ngx_http_lua_ffi_cert_pem_to_der(const unsigned char *pem, + size_t pem_len, unsigned char *der, char **err); + + int ngx_http_lua_ffi_priv_key_pem_to_der(const unsigned char *pem, + size_t pem_len, unsigned char *der, char **err); + ]] + + local errmsg = ffi.new("char *[1]") + + local r = getfenv(0).__ngx_req + if not r then + ngx.log(ngx.ERR, "no request found") + return + end + + local cert = "garbage data" + + local out = ffi.new("char [?]", #cert) + + local rc = ffi.C.ngx_http_lua_ffi_cert_pem_to_der(cert, #cert, out, errmsg) + if rc < 1 then + ngx.log(ngx.ERR, "failed to parse PEM cert: ", + ffi.string(errmsg[0])) + end + + local pkey = "garbage key data" + + out = ffi.new("char [?]", #pkey) + + local rc = ffi.C.ngx_http_lua_ffi_priv_key_pem_to_der(pkey, #pkey, out, errmsg) + if rc < 1 then + ngx.log(ngx.ERR, "failed to parse PEM priv key: ", + ffi.string(errmsg[0])) + end + } + + ssl_certificate ../../cert/test.crt; + ssl_certificate_key ../../cert/test.key; + + server_tokens off; + location /foo { + default_type 'text/plain'; + content_by_lua_block { ngx.status = 201 ngx.say("foo") ngx.exit(201) } + more_clear_headers Date; + } + } +--- config + server_tokens off; + lua_ssl_trusted_certificate ../../cert/test.crt; + + location /t { + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(2000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(nil, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + local req = "GET /foo HTTP/1.0\r\nHost: test.com\r\nConnection: close\r\n\r\n" + local bytes, err = sock:send(req) + if not bytes then + ngx.say("failed to send http request: ", err) + return + end + + ngx.say("sent http request: ", bytes, " bytes.") + + while true do + local line, err = sock:receive() + if not line then + -- ngx.say("failed to recieve response status line: ", err) + break + end + + ngx.say("received: ", line) + end + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: userdata +sent http request: 56 bytes. +received: HTTP/1.1 201 Created +received: Server: nginx +received: Content-Type: text/plain +received: Content-Length: 4 +received: Connection: close +received: +received: foo +close: 1 nil + +--- error_log +lua ssl server name: "test.com" +failed to parse PEM cert: PEM_read_bio_X509_AUX() +failed to parse PEM priv key: PEM_read_bio_PrivateKey failed + +--- no_error_log +[alert] diff --git a/debian/modules/nginx-lua/t/141-luajit.t b/debian/modules/nginx-lua/t/141-luajit.t new file mode 100644 index 0000000..be03fe3 --- /dev/null +++ b/debian/modules/nginx-lua/t/141-luajit.t @@ -0,0 +1,47 @@ +# vim:set ft= ts=4 sw=4 et fdm=marker: + +use Test::Nginx::Socket::Lua; + +#worker_connections(1014); +#master_on(); +#workers(2); +#log_level('warn'); + +repeat_each(2); + +plan tests => repeat_each() * (blocks() * 3); + +#no_diff(); +#no_long_string(); +run_tests(); + +__DATA__ + +=== TEST 1: avoid the data segment from growing on Linux +This is to maximize the address space that can be used by LuaJIT. +--- config + location = /t { + content_by_lua_block { + local ffi = require "ffi" + ffi.cdef[[ + void *malloc(size_t size); + void free(void *p); + ]] + local p = ffi.C.malloc(1); + local num = tonumber(ffi.cast("uintptr_t", p)) + ffi.C.free(p) + if ffi.abi("64bit") then + if num < 2^31 then + ngx.say("fail: ", string.format("p = %#x", num)) + return + end + end + ngx.say("pass") + } + } +--- request +GET /t +--- response_body +pass +--- no_error_log +[error] diff --git a/debian/modules/nginx-lua/t/data/fake-module/ngx_http_fake_module.c b/debian/modules/nginx-lua/t/data/fake-module/ngx_http_fake_module.c index ec74aa4..42cde55 100644 --- a/debian/modules/nginx-lua/t/data/fake-module/ngx_http_fake_module.c +++ b/debian/modules/nginx-lua/t/data/fake-module/ngx_http_fake_module.c @@ -85,7 +85,6 @@ static char *ngx_http_fake_merge_srv_conf(ngx_conf_t *cf, void *prev, void *conf return NGX_CONF_ERROR; } - ngx_conf_log_error(NGX_LOG_NOTICE, cf, 0, "merge srv conf ok"); return NGX_CONF_OK; } @@ -116,6 +115,5 @@ static char *ngx_http_fake_merge_loc_conf(ngx_conf_t *cf, void *prev, void *conf return NGX_CONF_ERROR; } - ngx_conf_log_error(NGX_LOG_NOTICE, cf, 0, "merge loc conf ok"); return NGX_CONF_OK; } diff --git a/debian/modules/nginx-lua/util/build.sh b/debian/modules/nginx-lua/util/build.sh index 2aa79cc..17841ed 100755 --- a/debian/modules/nginx-lua/util/build.sh +++ b/debian/modules/nginx-lua/util/build.sh @@ -39,7 +39,7 @@ time ngx-build $force $version \ --without-http_memcached_module \ --without-http_auth_basic_module \ --without-http_userid_module \ - --add-module=$home/work/nginx/ngx_http_auth_request_module-0.2 \ + --with-http_auth_request_module \ --add-module=$root/../echo-nginx-module \ --add-module=$root/../memc-nginx-module \ --add-module=$root/../srcache-nginx-module \ From 8e280162c688d6b00fc47690a1c7e015e8ddbb35 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Fri, 29 Jul 2016 16:46:55 +0300 Subject: [PATCH 082/600] Imported Upstream version 1.11.3 --- CHANGES | 100 +- CHANGES.ru | 101 +- auto/cc/acc | 1 - auto/cc/clang | 6 - auto/cc/conf | 2 +- auto/cc/gcc | 19 +- auto/cc/icc | 4 - auto/cc/sunc | 9 +- auto/endianness | 2 +- auto/feature | 2 +- auto/include | 5 +- auto/lib/conf | 29 - auto/lib/make | 8 - auto/lib/md5/conf | 103 -- auto/lib/md5/make | 96 - auto/lib/md5/makefile.bcc | 22 - auto/lib/md5/makefile.msvc | 22 - auto/lib/md5/makefile.owc | 11 - auto/lib/sha1/conf | 79 - auto/lib/sha1/make | 96 - auto/lib/sha1/makefile.bcc | 22 - auto/lib/sha1/makefile.msvc | 22 - auto/lib/sha1/makefile.owc | 11 - auto/lib/test | 40 - auto/module | 18 +- auto/modules | 75 +- auto/options | 68 +- auto/os/darwin | 4 +- auto/os/linux | 17 + auto/os/solaris | 2 +- auto/sources | 1 + auto/summary | 14 - auto/types/sizeof | 2 +- auto/types/typedef | 2 +- auto/types/uintptr_t | 4 +- auto/unix | 79 +- src/core/nginx.h | 4 +- src/core/ngx_conf_file.h | 1 - src/core/ngx_connection.c | 13 +- src/core/ngx_connection.h | 8 +- src/core/ngx_crypt.c | 13 - src/core/ngx_file.c | 19 +- src/core/ngx_file.h | 4 +- src/core/ngx_inet.c | 196 +- src/core/ngx_inet.h | 36 +- src/core/ngx_md5.c | 6 - src/core/ngx_md5.h | 32 - src/core/ngx_module.h | 9 - src/core/ngx_proxy_protocol.c | 52 +- src/core/ngx_resolver.c | 54 +- src/core/ngx_sha1.c | 294 +++ src/core/ngx_sha1.h | 19 +- src/core/ngx_string.c | 4 +- src/event/modules/ngx_epoll_module.c | 93 +- src/event/ngx_event.c | 35 +- src/event/ngx_event.h | 20 +- src/event/ngx_event_accept.c | 19 +- src/event/ngx_event_connect.c | 153 ++ src/event/ngx_event_connect.h | 3 + src/event/ngx_event_openssl.c | 240 ++- src/event/ngx_event_openssl.h | 5 + src/event/ngx_event_openssl_stapling.c | 150 +- src/http/modules/ngx_http_dav_module.c | 6 + src/http/modules/ngx_http_fastcgi_module.c | 2 +- src/http/modules/ngx_http_log_module.c | 4 +- src/http/modules/ngx_http_map_module.c | 126 +- src/http/modules/ngx_http_memcached_module.c | 2 +- src/http/modules/ngx_http_proxy_module.c | 10 +- src/http/modules/ngx_http_realip_module.c | 66 +- src/http/modules/ngx_http_scgi_module.c | 2 +- src/http/modules/ngx_http_ssl_module.c | 66 +- src/http/modules/ngx_http_ssl_module.h | 5 +- src/http/modules/ngx_http_sub_filter_module.c | 124 +- .../ngx_http_upstream_keepalive_module.c | 2 +- .../modules/ngx_http_userid_filter_module.c | 2 +- src/http/modules/ngx_http_uwsgi_module.c | 10 +- src/http/ngx_http.c | 73 +- src/http/ngx_http_core_module.c | 18 +- src/http/ngx_http_core_module.h | 13 +- src/http/ngx_http_file_cache.c | 11 +- src/http/ngx_http_header_filter_module.c | 37 +- src/http/ngx_http_parse.c | 38 +- src/http/ngx_http_request.c | 14 +- src/http/ngx_http_request.h | 2 + src/http/ngx_http_script.c | 14 +- src/http/ngx_http_special_response.c | 15 +- src/http/ngx_http_upstream.c | 115 +- src/http/ngx_http_upstream.h | 3 + src/http/ngx_http_upstream_round_robin.c | 11 +- src/http/ngx_http_variables.c | 132 +- src/http/v2/ngx_http_v2.c | 220 ++- src/http/v2/ngx_http_v2.h | 7 +- src/http/v2/ngx_http_v2_filter_module.c | 55 +- src/http/v2/ngx_http_v2_module.c | 31 + src/http/v2/ngx_http_v2_module.h | 1 + src/mail/ngx_mail.c | 42 +- src/mail/ngx_mail.h | 13 +- src/mail/ngx_mail_auth_http_module.c | 29 +- src/mail/ngx_mail_core_module.c | 58 +- src/mail/ngx_mail_ssl_module.c | 64 +- src/mail/ngx_mail_ssl_module.h | 5 +- src/os/unix/ngx_readv_chain.c | 32 + src/os/unix/ngx_recv.c | 33 + src/os/unix/ngx_thread_mutex.c | 2 +- src/stream/ngx_stream.c | 65 +- src/stream/ngx_stream.h | 148 +- src/stream/ngx_stream_access_module.c | 1 + src/stream/ngx_stream_core_module.c | 197 ++- src/stream/ngx_stream_geo_module.c | 1572 +++++++++++++++++ src/stream/ngx_stream_geoip_module.c | 814 +++++++++ src/stream/ngx_stream_handler.c | 9 + src/stream/ngx_stream_limit_conn_module.c | 142 +- src/stream/ngx_stream_map_module.c | 574 ++++++ src/stream/ngx_stream_proxy_module.c | 546 +++++- src/stream/ngx_stream_return_module.c | 207 +++ src/stream/ngx_stream_script.c | 854 +++++++++ src/stream/ngx_stream_script.h | 123 ++ src/stream/ngx_stream_split_clients_module.c | 244 +++ src/stream/ngx_stream_ssl_module.c | 163 +- src/stream/ngx_stream_ssl_module.h | 5 +- src/stream/ngx_stream_upstream.c | 3 +- src/stream/ngx_stream_upstream.h | 16 + src/stream/ngx_stream_upstream_hash_module.c | 26 +- .../ngx_stream_upstream_least_conn_module.c | 3 +- src/stream/ngx_stream_upstream_round_robin.c | 135 ++ src/stream/ngx_stream_upstream_round_robin.h | 2 + src/stream/ngx_stream_upstream_zone_module.c | 3 +- src/stream/ngx_stream_variables.c | 971 ++++++++++ src/stream/ngx_stream_variables.h | 109 ++ 129 files changed, 8999 insertions(+), 2028 deletions(-) delete mode 100644 auto/lib/md5/conf delete mode 100644 auto/lib/md5/make delete mode 100644 auto/lib/md5/makefile.bcc delete mode 100644 auto/lib/md5/makefile.msvc delete mode 100644 auto/lib/md5/makefile.owc delete mode 100644 auto/lib/sha1/conf delete mode 100644 auto/lib/sha1/make delete mode 100644 auto/lib/sha1/makefile.bcc delete mode 100644 auto/lib/sha1/makefile.msvc delete mode 100644 auto/lib/sha1/makefile.owc delete mode 100644 auto/lib/test create mode 100644 src/core/ngx_sha1.c create mode 100644 src/stream/ngx_stream_geo_module.c create mode 100644 src/stream/ngx_stream_geoip_module.c create mode 100644 src/stream/ngx_stream_map_module.c create mode 100644 src/stream/ngx_stream_return_module.c create mode 100644 src/stream/ngx_stream_script.c create mode 100644 src/stream/ngx_stream_script.h create mode 100644 src/stream/ngx_stream_split_clients_module.c create mode 100644 src/stream/ngx_stream_variables.c create mode 100644 src/stream/ngx_stream_variables.h diff --git a/CHANGES b/CHANGES index 4396472..a795ef2 100644 --- a/CHANGES +++ b/CHANGES @@ -1,14 +1,108 @@ -Changes with nginx 1.10.1 31 May 2016 +Changes with nginx 1.11.3 26 Jul 2016 + + *) Change: now the "accept_mutex" directive is turned off by default. + + *) Feature: now nginx uses EPOLLEXCLUSIVE on Linux. + + *) Feature: the ngx_stream_geo_module. + + *) Feature: the ngx_stream_geoip_module. + + *) Feature: the ngx_stream_split_clients_module. + + *) Feature: variables support in the "proxy_pass" and "proxy_ssl_name" + directives in the stream module. + + *) Bugfix: socket leak when using HTTP/2. + + *) Bugfix: in configure tests. + Thanks to Piotr Sikora. + + +Changes with nginx 1.11.2 05 Jul 2016 + + *) Change: now nginx always uses internal MD5 and SHA1 implementations; + the --with-md5 and --with-sha1 configure options were canceled. + + *) Feature: variables support in the stream module. + + *) Feature: the ngx_stream_map_module. + + *) Feature: the ngx_stream_return_module. + + *) Feature: a port can be specified in the "proxy_bind", "fastcgi_bind", + "memcached_bind", "scgi_bind", and "uwsgi_bind" directives. + + *) Feature: now nginx uses the IP_BIND_ADDRESS_NO_PORT socket option + when available. + + *) Bugfix: a segmentation fault might occur in a worker process when + using HTTP/2 and the "proxy_request_buffering" directive. + + *) Bugfix: the "Content-Length" request header line was always added to + requests passed to backends, including requests without body, when + using HTTP/2. + + *) Bugfix: "http request count is zero" alerts might appear in logs when + using HTTP/2. + + *) Bugfix: unnecessary buffering might occur when using the "sub_filter" + directive; the issue had appeared in 1.9.4. + + +Changes with nginx 1.11.1 31 May 2016 *) Security: a segmentation fault might occur in a worker process while writing a specially crafted request body to a temporary file (CVE-2016-4450); the bug had appeared in 1.3.9. -Changes with nginx 1.10.0 26 Apr 2016 +Changes with nginx 1.11.0 24 May 2016 - *) 1.10.x stable branch. + *) Feature: the "transparent" parameter of the "proxy_bind", + "fastcgi_bind", "memcached_bind", "scgi_bind", and "uwsgi_bind" + directives. + + *) Feature: the $request_id variable. + + *) Feature: the "map" directive supports combinations of multiple + variables as resulting values. + + *) Feature: now nginx checks if EPOLLRDHUP events are supported by + kernel, and optimizes connection handling accordingly if the "epoll" + method is used. + + *) Feature: the "ssl_certificate" and "ssl_certificate_key" directives + can be specified multiple times to load certificates of different + types (for example, RSA and ECDSA). + + *) Feature: the "ssl_ecdh_curve" directive now allows specifying a list + of curves when using OpenSSL 1.0.2 or newer; by default a list built + into OpenSSL is used. + + *) Change: to use DHE ciphers it is now required to specify parameters + using the "ssl_dhparam" directive. + + *) Feature: the $proxy_protocol_port variable. + + *) Feature: the $realip_remote_port variable in the + ngx_http_realip_module. + + *) Feature: the ngx_http_realip_module is now able to set the client + port in addition to the address. + + *) Change: the "421 Misdirected Request" response now used when + rejecting requests to a virtual server different from one negotiated + during an SSL handshake; this improves interoperability with some + HTTP/2 clients when using client certificates. + + *) Change: HTTP/2 clients can now start sending request body + immediately; the "http2_body_preread_size" directive controls size of + the buffer used before nginx will start reading client request body. + + *) Bugfix: cached error responses were not updated when using the + "proxy_cache_bypass" directive. Changes with nginx 1.9.15 19 Apr 2016 diff --git a/CHANGES.ru b/CHANGES.ru index c96cf93..cd424e9 100644 --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,14 +1,109 @@ -Изменения в nginx 1.10.1 31.05.2016 +Изменения в nginx 1.11.3 26.07.2016 + + *) Изменение: теперь accept_mutex по умолчанию выключен. + + *) Добавление: теперь nginx использует EPOLLEXCLUSIVE на Linux. + + *) Добавление: модуль ngx_stream_geo_module. + + *) Добавление: модуль ngx_stream_geoip_module. + + *) Добавление: модуль ngx_stream_split_clients_module. + + *) Добавление: директивы proxy_pass и proxy_ssl_name в модуле stream + поддерживают переменные. + + *) Исправление: утечки сокетов при использовании HTTP/2. + + *) Исправление: в configure. + Спасибо Piotr Sikora. + + +Изменения в nginx 1.11.2 05.07.2016 + + *) Изменение: теперь nginx всегда использует внутренние реализации MD5 и + SHA1; параметры configure --with-md5 и --with-sha1 упразднены. + + *) Добавление: поддержка переменных в модуле stream. + + *) Добавление: модуль ngx_stream_map_module. + + *) Добавление: модуль ngx_stream_return_module. + + *) Добавление: в директивах proxy_bind, fastcgi_bind, memcached_bind, + scgi_bind и uwsgi_bind теперь можно указывать порт. + + *) Добавление: теперь nginx использует опцию сокета + IP_BIND_ADDRESS_NO_PORT, если она доступна. + + *) Исправление: при использовании HTTP/2 и директивы + proxy_request_buffering в рабочем процессе мог произойти segmentation + fault. + + *) Исправление: при использовании HTTP/2 к запросам, передаваемым на + бэкенд, всегда добавлялась строка заголовка "Content-Length", даже + если у запроса не было тела. + + *) Исправление: при использовании HTTP/2 в логах могли появляться + сообщения "http request count is zero". + + *) Исправление: при использовании директивы sub_filter могло + буферизироваться больше данных, чем это необходимо; проблема + появилась в 1.9.4. + + +Изменения в nginx 1.11.1 31.05.2016 *) Безопасность: при записи тела специально созданного запроса во временный файл в рабочем процессе мог происходить segmentation fault (CVE-2016-4450); ошибка появилась в 1.3.9. -Изменения в nginx 1.10.0 26.04.2016 +Изменения в nginx 1.11.0 24.05.2016 - *) Стабильная ветка 1.10.x. + *) Добавление: параметр transparent директив proxy_bind, fastcgi_bind, + memcached_bind, scgi_bind и uwsgi_bind. + + *) Добавление: переменная $request_id. + + *) Добавление: директива map поддерживает комбинации нескольких + переменных в качестве результирующих значений. + + *) Добавление: теперь при использовании метода epoll nginx проверяет, + поддерживает ли ядро события EPOLLRDHUP, и соответственно + оптимизирует обработку соединений. + + *) Добавление: директивы ssl_certificate и ssl_certificate_key теперь + можно указывать несколько раз для загрузки сертификатов разных типов + (например, RSA и ECDSA). + + *) Добавление: при использовании OpenSSL 1.0.2 и новее с помощью + директивы ssl_ecdh_curve теперь можно задать список кривых; по + умолчанию используется встроенный в OpenSSL список кривых. + + *) Изменение: для использования DHE-шифров теперь надо явно задавать + файл параметров с помощью директивы ssl_dhparam. + + *) Добавление: переменная $proxy_protocol_port. + + *) Добавление: переменная $realip_remote_port в модуле + ngx_http_realip_module. + + *) Добавление: модуль ngx_http_realip_module теперь позволяет + устанавливать не только адрес, но и порт клиента. + + *) Изменение: при попытке запросить виртуальный сервер, отличающийся от + согласованного в процессе SSL handshake, теперь возвращается ответ + "421 Misdirected Request"; это улучшает совместимость с некоторыми + HTTP/2-клиентами в случае использования клиентских сертификатов. + + *) Изменение: HTTP/2-клиенты теперь могут сразу присылать тело запроса; + директива http2_body_preread_size позволяет указать размер буфера, + который будет использоваться до того, как nginx начнёт читать тело. + + *) Исправление: при использовании директивы proxy_cache_bypass не + обновлялись закэшированные ошибочные ответы. Изменения в nginx 1.9.15 19.04.2016 diff --git a/auto/cc/acc b/auto/cc/acc index 6baee67..64fa671 100644 --- a/auto/cc/acc +++ b/auto/cc/acc @@ -12,4 +12,3 @@ CC_TEST_FLAGS="-Ae" PCRE_OPT="$PCRE_OPT -Ae" ZLIB_OPT="$ZLIB_OPT -Ae" -MD5_OPT="$MD5_OPT -Ae" diff --git a/auto/cc/clang b/auto/cc/clang index 25707b4..19bdaaa 100644 --- a/auto/cc/clang +++ b/auto/cc/clang @@ -66,12 +66,6 @@ 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 diff --git a/auto/cc/conf b/auto/cc/conf index f2c25ed..b3b9f92 100644 --- a/auto/cc/conf +++ b/auto/cc/conf @@ -231,7 +231,7 @@ if [ "$NGX_PLATFORM" != win32 ]; then ngx_feature_incs= ngx_feature_path= ngx_feature_libs= - ngx_feature_test="__builtin_bswap64(0)" + ngx_feature_test="if (__builtin_bswap64(0)) return 1" . auto/feature diff --git a/auto/cc/gcc b/auto/cc/gcc index c9101fe..a5c5c18 100644 --- a/auto/cc/gcc +++ b/auto/cc/gcc @@ -128,12 +128,6 @@ else PCRE_OPT="$PCRE_OPT $PIPE" fi -if [ ".$MD5_OPT" = "." ]; then - MD5_OPT="-O2 -fomit-frame-pointer $PIPE $CPU_OPT" -else - MD5_OPT="$MD5_OPT $PIPE" -fi - if [ ".$ZLIB_OPT" = "." ]; then ZLIB_OPT="-O2 -fomit-frame-pointer $PIPE $CPU_OPT" else @@ -151,9 +145,13 @@ CFLAGS="$CFLAGS -Wall -Wpointer-arith" #CFLAGS="$CFLAGS -Winline" #CFLAGS="$CFLAGS -Wmissing-prototypes" - case "$NGX_GCC_VER" in - [3-5].*) + 2.*) + # we have a lot of the unused function arguments + CFLAGS="$CFLAGS -Wno-unused" + ;; + + *) # we have a lot of the unused function arguments CFLAGS="$CFLAGS -Wno-unused-parameter" # 4.2.1 shows the warning in wrong places @@ -164,11 +162,6 @@ case "$NGX_GCC_VER" in CFLAGS="$CFLAGS -Wno-deprecated-declarations" fi ;; - - *) - # we have a lot of the unused function arguments - CFLAGS="$CFLAGS -Wno-unused" - ;; esac diff --git a/auto/cc/icc b/auto/cc/icc index 1c0df1a..c47f6e4 100644 --- a/auto/cc/icc +++ b/auto/cc/icc @@ -43,10 +43,6 @@ if [ ".$PCRE_OPT" = "." ]; then PCRE_OPT="-O $CPU_OPT" fi -if [ ".$MD5_OPT" = "." ]; then - MD5_OPT="-O $CPU_OPT" -fi - if [ ".$ZLIB_OPT" = "." ]; then ZLIB_OPT="-O $CPU_OPT" fi diff --git a/auto/cc/sunc b/auto/cc/sunc index 8360c49..806ccc4 100644 --- a/auto/cc/sunc +++ b/auto/cc/sunc @@ -20,7 +20,10 @@ have=NGX_COMPILER value="\"Sun C $NGX_SUNC_VER\"" . auto/define cat << END > $NGX_AUTOTEST.c -int main() { printf("%d", __SUNPRO_C); } +int main(void) { + printf("%d", __SUNPRO_C); + return 0; +} END @@ -145,10 +148,6 @@ if [ ".$PCRE_OPT" = "." ]; then PCRE_OPT="$ngx_fast $IPO $CPU_OPT" fi -if [ ".$MD5_OPT" = "." ]; then - MD5_OPT="$ngx_fast $IPO $CPU_OPT" -fi - if [ ".$ZLIB_OPT" = "." ]; then ZLIB_OPT="$ngx_fast $IPO $CPU_OPT" fi diff --git a/auto/endianness b/auto/endianness index 70b0a10..1b552b6 100644 --- a/auto/endianness +++ b/auto/endianness @@ -15,7 +15,7 @@ END cat << END > $NGX_AUTOTEST.c -int main() { +int main(void) { int i = 0x11223344; char *p; diff --git a/auto/feature b/auto/feature index 1145f28..3561f59 100644 --- a/auto/feature +++ b/auto/feature @@ -31,7 +31,7 @@ cat << END > $NGX_AUTOTEST.c $NGX_INCLUDE_UNISTD_H $ngx_feature_incs -int main() { +int main(void) { $ngx_feature_test; return 0; } diff --git a/auto/include b/auto/include index e34dabd..c1bd364 100644 --- a/auto/include +++ b/auto/include @@ -20,7 +20,7 @@ cat << END > $NGX_AUTOTEST.c $NGX_INCLUDE_SYS_PARAM_H #include <$ngx_include> -int main() { +int main(void) { return 0; } @@ -45,9 +45,6 @@ if [ -x $NGX_AUTOTEST ]; then eval "NGX_INCLUDE_$ngx_name='#include <$ngx_include>'" - #STUB - eval "NGX_$ngx_name='#include <$ngx_include>'" - else echo " not found" diff --git a/auto/lib/conf b/auto/lib/conf index a6242e7..0b8545a 100644 --- a/auto/lib/conf +++ b/auto/lib/conf @@ -25,35 +25,6 @@ if [ $USE_OPENSSL = YES ]; then . auto/lib/openssl/conf fi -if [ $USE_MD5 = YES ]; then - - if [ $USE_OPENSSL = YES ]; then - have=NGX_HAVE_OPENSSL_MD5_H . auto/have - have=NGX_OPENSSL_MD5 . auto/have - have=NGX_HAVE_MD5 . auto/have - MD5=YES - MD5_LIB=OpenSSL - - else - . auto/lib/md5/conf - fi - -fi - -if [ $USE_SHA1 = YES ]; then - - if [ $USE_OPENSSL = YES ]; then - have=NGX_HAVE_OPENSSL_SHA1_H . auto/have - have=NGX_HAVE_SHA1 . auto/have - SHA1=YES - SHA1_LIB=OpenSSL - - else - . auto/lib/sha1/conf - fi - -fi - if [ $USE_ZLIB = YES ]; then . auto/lib/zlib/conf fi diff --git a/auto/lib/make b/auto/lib/make index 6298b94..b64e329 100644 --- a/auto/lib/make +++ b/auto/lib/make @@ -7,14 +7,6 @@ if [ $PCRE != NONE -a $PCRE != NO -a $PCRE != YES ]; then . auto/lib/pcre/make fi -if [ $MD5 != NONE -a $MD5 != NO -a $MD5 != YES ]; then - . auto/lib/md5/make -fi - -if [ $SHA1 != NONE -a $SHA1 != NO -a $SHA1 != YES ]; then - . auto/lib/sha1/make -fi - if [ $OPENSSL != NONE -a $OPENSSL != NO -a $OPENSSL != YES ]; then . auto/lib/openssl/make fi diff --git a/auto/lib/md5/conf b/auto/lib/md5/conf deleted file mode 100644 index 49c0ddf..0000000 --- a/auto/lib/md5/conf +++ /dev/null @@ -1,103 +0,0 @@ - -# Copyright (C) Igor Sysoev -# Copyright (C) Nginx, Inc. - - -if [ $MD5 != NONE ]; then - - if grep MD5_Init $MD5/md5.h 2>&1 >/dev/null; then - # OpenSSL md5 - OPENSSL_MD5=YES - have=NGX_HAVE_OPENSSL_MD5 . auto/have - have=NGX_OPENSSL_MD5 . auto/have - else - # rsaref md5 - OPENSSL_MD5=NO - fi - - have=NGX_HAVE_MD5 . auto/have - CORE_INCS="$CORE_INCS $MD5" - - case "$NGX_CC_NAME" in - - msvc | owc | bcc) - LINK_DEPS="$LINK_DEPS $MD5/md5.lib" - CORE_LIBS="$CORE_LIBS $MD5/md5.lib" - ;; - - icc) - LINK_DEPS="$LINK_DEPS $MD5/libmd5.a" - - # to allow -ipo optimization we link with the *.o but not library - CORE_LIBS="$CORE_LIBS $MD5/md5_dgst.o" - - if [ $MD5_ASM = YES ]; then - CORE_LIBS="$CORE_LIBS $MD5/asm/mx86-elf.o" - fi - ;; - - *) - LINK_DEPS="$LINK_DEPS $MD5/libmd5.a" - CORE_LIBS="$CORE_LIBS $MD5/libmd5.a" - #CORE_LIBS="$CORE_LIBS -L $MD5 -lmd5" - ;; - - esac - -else - - if [ "$NGX_PLATFORM" != win32 ]; then - - MD5=NO - - # FreeBSD, Solaris 10 - - ngx_feature="md5 in system md library" - ngx_feature_name=NGX_HAVE_MD5 - ngx_feature_run=no - ngx_feature_incs="#include " - ngx_feature_path= - ngx_feature_libs="-lmd" - ngx_feature_test="MD5_CTX md5; MD5Init(&md5)" - . auto/feature - - ngx_md5_lib="system md" - - if [ $ngx_found = no ]; then - - # Solaris 8/9 - - ngx_feature="md5 in system md5 library" - ngx_feature_libs="-lmd5" - . auto/feature - - ngx_md5_lib="system md5" - fi - - if [ $ngx_found = no ]; then - - # OpenSSL crypto library - - ngx_feature="md5 in system OpenSSL crypto library" - ngx_feature_name="NGX_OPENSSL_MD5" - ngx_feature_incs="#include " - ngx_feature_libs="-lcrypto" - ngx_feature_test="MD5_CTX md5; MD5_Init(&md5)" - . auto/feature - - ngx_md5_lib="system crypto" - - if [ $ngx_found = yes ]; then - have=NGX_HAVE_OPENSSL_MD5_H . auto/have - have=NGX_HAVE_MD5 . auto/have - fi - fi - - if [ $ngx_found = yes ]; then - CORE_LIBS="$CORE_LIBS $ngx_feature_libs" - MD5=YES - MD5_LIB=$ngx_md5_lib - fi - fi - -fi diff --git a/auto/lib/md5/make b/auto/lib/md5/make deleted file mode 100644 index 7000b20..0000000 --- a/auto/lib/md5/make +++ /dev/null @@ -1,96 +0,0 @@ - -# Copyright (C) Igor Sysoev -# Copyright (C) Nginx, Inc. - - -case "$NGX_CC_NAME" in - - msvc) - ngx_makefile=makefile.msvc - ngx_opt="CPU_OPT=\"$CPU_OPT\" LIBC=$LIBC MD5_ASM=$MD5_ASM" - ngx_md5="MD5=\"$MD5\"" - ;; - - owc) - ngx_makefile=makefile.owc - ngx_opt="CPU_OPT=\"$CPU_OPT\"" - ngx_md5=`echo MD5=\"$MD5\" | sed -e "s/\//$ngx_regex_dirsep/g"` - ;; - - bcc) - ngx_makefile=makefile.bcc - ngx_opt="-DCPU_OPT=\"$CPU_OPT\" -DMD5_ASM=$MD5_ASM" - ngx_md5=`echo \-DMD5=\"$MD5\" | sed -e "s/\//$ngx_regex_dirsep/g"` - ;; - -esac - - -done=NO - - -case "$NGX_PLATFORM" in - - win32) - cat << END >> $NGX_MAKEFILE - -`echo "$MD5/md5.lib: $NGX_MAKEFILE" | sed -e "s/\//$ngx_regex_dirsep/g"` - \$(MAKE) -f auto/lib/md5/$ngx_makefile $ngx_opt $ngx_md5 - -END - - done=YES - ;; - - SunOS:*:i86pc) - if [ $MD5_ASM = YES ]; then - - cat << END >> $NGX_MAKEFILE - -$MD5/libmd5.a: $NGX_MAKEFILE - cd $MD5 \\ - && \$(MAKE) CFLAGS="$MD5_OPT -DSOL -DMD5_ASM -DL_ENDIAN" \\ - CC="\$(CC)" CPP="\$(CPP)" \\ - MD5_ASM_OBJ=asm/mx86-sol.o clean libmd5.a - -END - - done=YES - fi - ;; - - # FreeBSD: i386 - # Linux: i686 - - *:i386 | *:i686) - if [ $MD5_ASM = YES ]; then - - cat << END >> $NGX_MAKEFILE - -$MD5/libmd5.a: $NGX_MAKEFILE - cd $MD5 \\ - && \$(MAKE) CFLAGS="$MD5_OPT -DELF -DMD5_ASM -DL_ENDIAN" \\ - CC="\$(CC)" CPP="\$(CPP)" \\ - MD5_ASM_OBJ=asm/mx86-elf.o clean libmd5.a - -END - - done=YES - fi - ;; - -esac - - -if [ $done = NO ]; then - - cat << END >> $NGX_MAKEFILE - -$MD5/libmd5.a: $NGX_MAKEFILE - cd $MD5 \\ - && \$(MAKE) CFLAGS="$MD5_OPT" \\ - CC="\$(CC)" MD5_ASM_OBJ= clean libmd5.a - -END - -fi diff --git a/auto/lib/md5/makefile.bcc b/auto/lib/md5/makefile.bcc deleted file mode 100644 index eb6fb62..0000000 --- a/auto/lib/md5/makefile.bcc +++ /dev/null @@ -1,22 +0,0 @@ - -# Copyright (C) Igor Sysoev -# Copyright (C) Nginx, Inc. - - -CFLAGS = -q -O2 -tWM $(CPU_OPT) -DL_ENDIAN - -!if "$(MD5_ASM)" == "YES" - -md5.lib: - cd $(MD5) - bcc32 -c $(CFLAGS) -DMD5_ASM md5_dgst.c - tlib md5.lib +md5_dgst.obj +"asm\m-win32.obj" - -!else - -md5.lib: - cd $(MD5) - bcc32 -c $(CFLAGS) md5_dgst.c - tlib md5.lib +md5_dgst.obj - -!endif diff --git a/auto/lib/md5/makefile.msvc b/auto/lib/md5/makefile.msvc deleted file mode 100644 index 90d62fa..0000000 --- a/auto/lib/md5/makefile.msvc +++ /dev/null @@ -1,22 +0,0 @@ - -# Copyright (C) Igor Sysoev -# Copyright (C) Nginx, Inc. - - -CFLAGS = -nologo -O2 -Ob1 -Oi -Gs $(LIBC) $(CPU_OPT) -D L_ENDIAN - -!IF "$(MD5_ASM)" == "YES" - -md5.lib: - cd $(MD5) - cl -c $(CFLAGS) -D MD5_ASM md5_dgst.c - link -lib -out:md5.lib md5_dgst.obj asm/m-win32.obj - -!ELSE - -md5.lib: - cd $(MD5) - cl -c $(CFLAGS) md5_dgst.c - link -lib -out:md5.lib md5_dgst.obj - -!ENDIF diff --git a/auto/lib/md5/makefile.owc b/auto/lib/md5/makefile.owc deleted file mode 100644 index 78c1e61..0000000 --- a/auto/lib/md5/makefile.owc +++ /dev/null @@ -1,11 +0,0 @@ - -# Copyright (C) Igor Sysoev -# Copyright (C) Nginx, Inc. - - -CFLAGS = -zq -bt=nt -bm -ot -op -oi -oe -s $(CPU_OPT) - -md5.lib: - cd $(MD5) - wcl386 -c $(CFLAGS) -dL_ENDIAN md5_dgst.c - wlib -n md5.lib md5_dgst.obj diff --git a/auto/lib/sha1/conf b/auto/lib/sha1/conf deleted file mode 100644 index 78f9efd..0000000 --- a/auto/lib/sha1/conf +++ /dev/null @@ -1,79 +0,0 @@ - -# Copyright (C) Igor Sysoev -# Copyright (C) Nginx, Inc. - - -if [ $SHA1 != NONE ]; then - - have=NGX_HAVE_SHA1 . auto/have - CORE_INCS="$CORE_INCS $SHA1" - - case "$NGX_CC_NAME" in - - msvc | owc | bcc) - LINK_DEPS="$LINK_DEPS $SHA1/sha1.lib" - CORE_LIBS="$CORE_LIBS $SHA1/sha1.lib" - ;; - - icc) - LINK_DEPS="$LINK_DEPS $SHA1/libsha.a" - - # to allow -ipo optimization we link with the *.o but not library - CORE_LIBS="$CORE_LIBS $SHA1/sha1_dgst.o" - - if [ $SHA1_ASM = YES ]; then - CORE_LIBS="$CORE_LIBS $SHA1/asm/sx86-elf.o" - fi - ;; - - *) - LINK_DEPS="$LINK_DEPS $SHA1/libsha.a" - CORE_LIBS="$CORE_LIBS $SHA1/libsha.a" - #CORE_LIBS="$CORE_LIBS -L $SHA1 -lsha" - ;; - - esac - -else - - if [ "$NGX_PLATFORM" != win32 ]; then - - SHA1=NO - - # FreeBSD - - ngx_feature="sha1 in system md library" - ngx_feature_name=NGX_HAVE_SHA1 - ngx_feature_run=no - ngx_feature_incs="#include " - ngx_feature_path= - ngx_feature_libs="-lmd" - ngx_feature_test="SHA_CTX sha1; SHA1_Init(&sha1)" - . auto/feature - - ngx_sha1_lib="system md" - - if [ $ngx_found = no ]; then - - # OpenSSL crypto library - - ngx_feature="sha1 in system OpenSSL crypto library" - ngx_feature_incs="#include " - ngx_feature_libs="-lcrypto" - . auto/feature - - ngx_sha1_lib="system crypto" - - if [ $ngx_found = yes ]; then - have=NGX_HAVE_OPENSSL_SHA1_H . auto/have - fi - fi - - if [ $ngx_found = yes ]; then - CORE_LIBS="$CORE_LIBS $ngx_feature_libs" - SHA1=YES - SHA1_LIB=$ngx_sha1_lib - fi - fi - -fi diff --git a/auto/lib/sha1/make b/auto/lib/sha1/make deleted file mode 100644 index fc3b340..0000000 --- a/auto/lib/sha1/make +++ /dev/null @@ -1,96 +0,0 @@ - -# Copyright (C) Igor Sysoev -# Copyright (C) Nginx, Inc. - - -case "$NGX_CC_NAME" in - - msvc) - ngx_makefile=makefile.msvc - ngx_opt="CPU_OPT=\"$CPU_OPT\" LIBC=$LIBC SHA1_ASM=$SHA1_ASM" - ngx_sha1="SHA1=\"$SHA1\"" - ;; - - owc) - ngx_makefile=makefile.owc - ngx_opt="CPU_OPT=\"$CPU_OPT\"" - ngx_sha1=`echo SHA1=\"$SHA1\" | sed -e "s/\//$ngx_regex_dirsep/g"` - ;; - - bcc) - ngx_makefile=makefile.bcc - ngx_opt="-DCPU_OPT=\"$CPU_OPT\" -DSHA1_ASM=$SHA1_ASM" - ngx_sha1=`echo \-DSHA1=\"$SHA1\" | sed -e "s/\//$ngx_regex_dirsep/g"` - ;; - -esac - - -done=NO - - -case "$NGX_PLATFORM" in - - win32) - cat << END >> $NGX_MAKEFILE - -`echo "$SHA1/sha1.lib: $NGX_MAKEFILE" | sed -e "s/\//$ngx_regex_dirsep/g"` - \$(MAKE) -f auto/lib/sha1/$ngx_makefile $ngx_opt $ngx_sha1 - -END - - done=YES - ;; - - SunOS:*:i86pc) - if [ $SHA1_ASM = YES ]; then - - cat << END >> $NGX_MAKEFILE - -$SHA1/libsha.a: $NGX_MAKEFILE - cd $SHA1 \\ - && \$(MAKE) CFLAGS="$SHA1_OPT -DSOL -DSHA1_ASM -DL_ENDIAN" \\ - CC="\$(CC)" CPP="\$(CPP)" \\ - SHA_ASM_OBJ=asm/sx86-sol.o clean libsha.a - -END - - done=YES - fi - ;; - - # FreeBSD: i386 - # Linux: i686 - - *:i386 | *:i686) - if [ $SHA1_ASM = YES ]; then - - cat << END >> $NGX_MAKEFILE - -$SHA1/libsha.a: $NGX_MAKEFILE - cd $SHA1 \\ - && \$(MAKE) CFLAGS="$SHA1_OPT -DELF -DSHA1_ASM -DL_ENDIAN" \\ - CC="\$(CC)" CPP="\$(CPP)" \\ - SHA_ASM_OBJ=asm/sx86-elf.o clean libsha.a - -END - - done=YES - fi - ;; - -esac - - -if [ $done = NO ]; then - - cat << END >> $NGX_MAKEFILE - -$SHA1/libsha.a: $NGX_MAKEFILE - cd $SHA1 \\ - && \$(MAKE) CFLAGS="$SHA1_OPT" \\ - CC="\$(CC)" SHA_ASM_OBJ= clean libsha.a - -END - -fi diff --git a/auto/lib/sha1/makefile.bcc b/auto/lib/sha1/makefile.bcc deleted file mode 100644 index b0685fa..0000000 --- a/auto/lib/sha1/makefile.bcc +++ /dev/null @@ -1,22 +0,0 @@ - -# Copyright (C) Igor Sysoev -# Copyright (C) Nginx, Inc. - - -CFLAGS = -q -O2 -tWM $(CPU_OPT) -DL_ENDIAN - -!if "$(SHA1_ASM)" == "YES" - -sha1.lib: - cd $(SHA1) - bcc32 -c $(CFLAGS) -DSHA1_ASM sha1dgst.c - tlib sha1.lib +sha1dgst.obj +"asm\s-win32.obj" - -!else - -sha1.lib: - cd $(SHA1) - bcc32 -c $(CFLAGS) sha1dgst.c - tlib sha1.lib +sha1dgst.obj - -!endif diff --git a/auto/lib/sha1/makefile.msvc b/auto/lib/sha1/makefile.msvc deleted file mode 100644 index 3cbd21b..0000000 --- a/auto/lib/sha1/makefile.msvc +++ /dev/null @@ -1,22 +0,0 @@ - -# Copyright (C) Igor Sysoev -# Copyright (C) Nginx, Inc. - - -CFLAGS = -nologo -O2 -Ob1 -Oi -Gs $(LIBC) $(CPU_OPT) -D L_ENDIAN - -!IF "$(SHA1_ASM)" == "YES" - -sha1.lib: - cd $(SHA1) - cl -c $(CFLAGS) -D SHA1_ASM sha1dgst.c - link -lib -out:sha1.lib sha1dgst.obj asm/s-win32.obj - -!ELSE - -sha1.lib: - cd $(SHA1) - cl -c $(CFLAGS) sha1dgst.c - link -lib -out:sha1.lib sha1dgst.obj - -!ENDIF diff --git a/auto/lib/sha1/makefile.owc b/auto/lib/sha1/makefile.owc deleted file mode 100644 index fc095cc..0000000 --- a/auto/lib/sha1/makefile.owc +++ /dev/null @@ -1,11 +0,0 @@ - -# Copyright (C) Igor Sysoev -# Copyright (C) Nginx, Inc. - - -CFLAGS = -zq -bt=nt -bm -ot -op -oi -oe -s $(CPU_OPT) - -sha1.lib: - cd $(SHA1) - wcl386 -c $(CFLAGS) -dL_ENDIAN sha1dgst.c - wlib -n sha1.lib sha1dgst.obj diff --git a/auto/lib/test b/auto/lib/test deleted file mode 100644 index ba943a2..0000000 --- a/auto/lib/test +++ /dev/null @@ -1,40 +0,0 @@ - -# Copyright (C) Igor Sysoev -# Copyright (C) Nginx, Inc. - - -echo $ngx_n "checking for $ngx_lib ...$ngx_c" - -cat << END >> $NGX_AUTOCONF_ERR - ----------------------------------------- -checking for $ngx_lib - -END - -ngx_found=no - -cat << END > $NGX_AUTOTEST.c - -$ngx_lib_incs - -int main() { - $ngx_lib_test; - return 0; -} - - -eval "$CC $cc_test_flags $ngx_lib_cflags \ - -o $NGX_AUTOTEST $NGX_AUTOTEST.c $ngx_libs \ - >> $NGX_ERR 2>&1" - -if [ -x $NGX_AUTOTEST ]; then - echo " found" - - ngx_found=yes - -else - echo " not found" -fi - -rm -rf $NGX_AUTOTEST* diff --git a/auto/module b/auto/module index 16a816f..3b00a07 100644 --- a/auto/module +++ b/auto/module @@ -48,10 +48,14 @@ if [ "$ngx_module_link" = DYNAMIC ]; then fi ;; - PCRE | OPENSSL | MD5 | SHA1 | ZLIB) + PCRE | OPENSSL | ZLIB) eval USE_${lib}=YES ;; + MD5 | SHA1) + # obsolete + ;; + *) libs="$libs $lib" ;; @@ -79,10 +83,14 @@ elif [ "$ngx_module_link" = YES ]; then do case $lib in - PCRE | OPENSSL | MD5 | SHA1 | ZLIB | LIBXSLT | LIBGD | PERL | GEOIP) + PCRE | OPENSSL | ZLIB | LIBXSLT | LIBGD | PERL | GEOIP) eval USE_${lib}=YES ;; + MD5 | SHA1) + # obsolete + ;; + *) CORE_LIBS="$CORE_LIBS $lib" ;; @@ -109,10 +117,14 @@ elif [ "$ngx_module_link" = ADDON ]; then do case $lib in - PCRE | OPENSSL | MD5 | SHA1 | ZLIB | LIBXSLT | LIBGD | PERL | GEOIP) + PCRE | OPENSSL | ZLIB | LIBXSLT | LIBGD | PERL | GEOIP) eval USE_${lib}=YES ;; + MD5 | SHA1) + # obsolete + ;; + *) CORE_LIBS="$CORE_LIBS $lib" ;; diff --git a/auto/modules b/auto/modules index 22ff6d9..614037c 100644 --- a/auto/modules +++ b/auto/modules @@ -43,6 +43,7 @@ fi if [ $NGX_TEST_BUILD_EPOLL = YES ]; then have=NGX_HAVE_EPOLL . auto/have have=NGX_HAVE_EPOLLRDHUP . auto/have + have=NGX_HAVE_EPOLLEXCLUSIVE . auto/have have=NGX_HAVE_EVENTFD . auto/have have=NGX_TEST_BUILD_EPOLL . auto/have EVENT_MODULES="$EVENT_MODULES $EPOLL_MODULE" @@ -101,7 +102,6 @@ fi if [ $HTTP_CACHE = YES ]; then - USE_MD5=YES have=NGX_HTTP_CACHE . auto/have HTTP_SRCS="$HTTP_SRCS $HTTP_FILE_CACHE_SRCS" fi @@ -522,8 +522,6 @@ if [ $HTTP_AUTH_REQUEST = YES ]; then fi if [ $HTTP_AUTH_BASIC = YES ]; then - USE_MD5=YES - USE_SHA1=YES have=NGX_CRYPT . auto/have ngx_module_name=ngx_http_auth_basic_module @@ -682,7 +680,6 @@ fi if [ $HTTP_PROXY = YES ]; then have=NGX_HTTP_X_FORWARDED_FOR . auto/have - #USE_MD5=YES ngx_module_name=ngx_http_proxy_module ngx_module_incs= @@ -772,8 +769,6 @@ if [ $HTTP_BROWSER = YES ]; then fi if [ $HTTP_SECURE_LINK = YES ]; then - USE_MD5=YES - ngx_module_name=ngx_http_secure_link_module ngx_module_incs= ngx_module_deps= @@ -971,8 +966,6 @@ if [ $STREAM != NO ]; then STREAM_INCS= ngx_module_type=STREAM - ngx_module_libs= - ngx_module_link=YES ngx_module_order= @@ -982,9 +975,13 @@ if [ $STREAM != NO ]; then ngx_stream_upstream_module" ngx_module_incs="src/stream" ngx_module_deps="src/stream/ngx_stream.h \ + src/stream/ngx_stream_variables.h \ + src/stream/ngx_stream_script.h \ src/stream/ngx_stream_upstream.h \ src/stream/ngx_stream_upstream_round_robin.h" ngx_module_srcs="src/stream/ngx_stream.c \ + src/stream/ngx_stream_variables.c \ + src/stream/ngx_stream_script.c \ src/stream/ngx_stream_handler.c \ src/stream/ngx_stream_core_module.c \ src/stream/ngx_stream_proxy_module.c \ @@ -1002,6 +999,8 @@ if [ $STREAM != NO ]; then ngx_module_name=ngx_stream_ssl_module ngx_module_deps=src/stream/ngx_stream_ssl_module.h ngx_module_srcs=src/stream/ngx_stream_ssl_module.c + ngx_module_libs= + ngx_module_link=$STREAM_SSL . auto/module fi @@ -1010,6 +1009,8 @@ if [ $STREAM != NO ]; then ngx_module_name=ngx_stream_limit_conn_module ngx_module_deps= ngx_module_srcs=src/stream/ngx_stream_limit_conn_module.c + ngx_module_libs= + ngx_module_link=$STREAM_LIMIT_CONN . auto/module fi @@ -1018,6 +1019,58 @@ if [ $STREAM != NO ]; then ngx_module_name=ngx_stream_access_module ngx_module_deps= ngx_module_srcs=src/stream/ngx_stream_access_module.c + ngx_module_libs= + ngx_module_link=$STREAM_ACCESS + + . auto/module + fi + + if [ $STREAM_GEO = YES ]; then + ngx_module_name=ngx_stream_geo_module + ngx_module_deps= + ngx_module_srcs=src/stream/ngx_stream_geo_module.c + ngx_module_libs= + ngx_module_link=$STREAM_GEO + + . auto/module + fi + + if [ $STREAM_GEOIP != NO ]; then + ngx_module_name=ngx_stream_geoip_module + ngx_module_deps= + ngx_module_srcs=src/stream/ngx_stream_geoip_module.c + ngx_module_libs=GEOIP + ngx_module_link=$STREAM_GEOIP + + . auto/module + fi + + if [ $STREAM_MAP = YES ]; then + ngx_module_name=ngx_stream_map_module + ngx_module_deps= + ngx_module_srcs=src/stream/ngx_stream_map_module.c + ngx_module_libs= + ngx_module_link=$STREAM_MAP + + . auto/module + fi + + if [ $STREAM_SPLIT_CLIENTS = YES ]; then + ngx_module_name=ngx_stream_split_clients_module + ngx_module_deps= + ngx_module_srcs=src/stream/ngx_stream_split_clients_module.c + ngx_module_libs= + ngx_module_link=$STREAM_SPLIT_CLIENTS + + . auto/module + fi + + if [ $STREAM_RETURN = YES ]; then + ngx_module_name=ngx_stream_return_module + ngx_module_deps= + ngx_module_srcs=src/stream/ngx_stream_return_module.c + ngx_module_libs= + ngx_module_link=$STREAM_RETURN . auto/module fi @@ -1026,6 +1079,8 @@ if [ $STREAM != NO ]; then ngx_module_name=ngx_stream_upstream_hash_module ngx_module_deps= ngx_module_srcs=src/stream/ngx_stream_upstream_hash_module.c + ngx_module_libs= + ngx_module_link=$STREAM_UPSTREAM_HASH . auto/module fi @@ -1034,6 +1089,8 @@ if [ $STREAM != NO ]; then ngx_module_name=ngx_stream_upstream_least_conn_module ngx_module_deps= ngx_module_srcs=src/stream/ngx_stream_upstream_least_conn_module.c + ngx_module_libs= + ngx_module_link=$STREAM_UPSTREAM_LEAST_CONN . auto/module fi @@ -1044,6 +1101,8 @@ if [ $STREAM != NO ]; then ngx_module_name=ngx_stream_upstream_zone_module ngx_module_deps= ngx_module_srcs=src/stream/ngx_stream_upstream_zone_module.c + ngx_module_libs= + ngx_module_link=$STREAM_UPSTREAM_ZONE . auto/module fi diff --git a/auto/options b/auto/options index ac8beb1..a8fce30 100644 --- a/auto/options +++ b/auto/options @@ -117,6 +117,11 @@ STREAM=NO STREAM_SSL=NO STREAM_LIMIT_CONN=YES STREAM_ACCESS=YES +STREAM_GEO=YES +STREAM_GEOIP=NO +STREAM_MAP=YES +STREAM_SPLIT_CLIENTS=YES +STREAM_RETURN=YES STREAM_UPSTREAM_HASH=YES STREAM_UPSTREAM_LEAST_CONN=YES STREAM_UPSTREAM_ZONE=YES @@ -136,16 +141,6 @@ PCRE_JIT=NO USE_OPENSSL=NO OPENSSL=NONE -USE_MD5=NO -MD5=NONE -MD5_OPT= -MD5_ASM=NO - -USE_SHA1=NO -SHA1=NONE -SHA1_OPT= -SHA1_ASM=NO - USE_ZLIB=NO ZLIB=NONE ZLIB_OPT= @@ -301,9 +296,17 @@ use the \"--with-mail_ssl_module\" option instead" --with-stream) STREAM=YES ;; --with-stream=dynamic) STREAM=DYNAMIC ;; --with-stream_ssl_module) STREAM_SSL=YES ;; + --with-stream_geoip_module) STREAM_GEOIP=YES ;; + --with-stream_geoip_module=dynamic) + STREAM_GEOIP=DYNAMIC ;; --without-stream_limit_conn_module) STREAM_LIMIT_CONN=NO ;; --without-stream_access_module) STREAM_ACCESS=NO ;; + --without-stream_geo_module) STREAM_GEO=NO ;; + --without-stream_map_module) STREAM_MAP=NO ;; + --without-stream_split_clients_module) + STREAM_SPLIT_CLIENTS=NO ;; + --without-stream_return_module) STREAM_RETURN=NO ;; --without-stream_upstream_hash_module) STREAM_UPSTREAM_HASH=NO ;; --without-stream_upstream_least_conn_module) @@ -333,13 +336,31 @@ use the \"--with-mail_ssl_module\" option instead" --with-openssl=*) OPENSSL="$value" ;; --with-openssl-opt=*) OPENSSL_OPT="$value" ;; - --with-md5=*) MD5="$value" ;; - --with-md5-opt=*) MD5_OPT="$value" ;; - --with-md5-asm) MD5_ASM=YES ;; + --with-md5=*) + NGX_POST_CONF_MSG="$NGX_POST_CONF_MSG +$0: warning: the \"--with-md5\" option is deprecated" + ;; + --with-md5-opt=*) + NGX_POST_CONF_MSG="$NGX_POST_CONF_MSG +$0: warning: the \"--with-md5-opt\" option is deprecated" + ;; + --with-md5-asm) + NGX_POST_CONF_MSG="$NGX_POST_CONF_MSG +$0: warning: the \"--with-md5-asm\" option is deprecated" + ;; - --with-sha1=*) SHA1="$value" ;; - --with-sha1-opt=*) SHA1_OPT="$value" ;; - --with-sha1-asm) SHA1_ASM=YES ;; + --with-sha1=*) + NGX_POST_CONF_MSG="$NGX_POST_CONF_MSG +$0: warning: the \"--with-sha1\" option is deprecated" + ;; + --with-sha1-opt=*) + NGX_POST_CONF_MSG="$NGX_POST_CONF_MSG +$0: warning: the \"--with-sha1-opt\" option is deprecated" + ;; + --with-sha1-asm) + NGX_POST_CONF_MSG="$NGX_POST_CONF_MSG +$0: warning: the \"--with-sha1-asm\" option is deprecated" + ;; --with-zlib=*) ZLIB="$value" ;; --with-zlib-opt=*) ZLIB_OPT="$value" ;; @@ -482,8 +503,15 @@ cat << END --with-stream enable TCP/UDP proxy module --with-stream=dynamic enable dynamic TCP/UDP proxy module --with-stream_ssl_module enable ngx_stream_ssl_module + --with-stream_geoip_module enable ngx_stream_geoip_module + --with-stream_geoip_module=dynamic enable dynamic ngx_stream_geoip_module --without-stream_limit_conn_module disable ngx_stream_limit_conn_module --without-stream_access_module disable ngx_stream_access_module + --without-stream_geo_module disable ngx_stream_geo_module + --without-stream_map_module disable ngx_stream_map_module + --without-stream_split_clients_module + disable ngx_stream_split_clients_module + --without-stream_return_module disable ngx_stream_return_module --without-stream_upstream_hash_module disable ngx_stream_upstream_hash_module --without-stream_upstream_least_conn_module @@ -511,14 +539,6 @@ cat << END --with-pcre-opt=OPTIONS set additional build options for PCRE --with-pcre-jit build PCRE with JIT compilation support - --with-md5=DIR set path to md5 library sources - --with-md5-opt=OPTIONS set additional build options for md5 - --with-md5-asm use md5 assembler sources - - --with-sha1=DIR set path to sha1 library sources - --with-sha1-opt=OPTIONS set additional build options for sha1 - --with-sha1-asm use sha1 assembler sources - --with-zlib=DIR set path to zlib library sources --with-zlib-opt=OPTIONS set additional build options for zlib --with-zlib-asm=CPU use zlib assembler sources optimized diff --git a/auto/os/darwin b/auto/os/darwin index 9b31b1f..b4b3ad3 100644 --- a/auto/os/darwin +++ b/auto/os/darwin @@ -113,6 +113,6 @@ ngx_feature_run=no ngx_feature_incs="#include " ngx_feature_path= ngx_feature_libs= -ngx_feature_test="int32_t lock, n; - n = OSAtomicCompareAndSwap32Barrier(0, 1, &lock)" +ngx_feature_test="int32_t lock = 0; + if (!OSAtomicCompareAndSwap32Barrier(0, 1, &lock)) return 1" . auto/feature diff --git a/auto/os/linux b/auto/os/linux index c932267..fae8842 100644 --- a/auto/os/linux +++ b/auto/os/linux @@ -44,6 +44,7 @@ ngx_feature_test="int efd = 0; struct epoll_event ee; ee.events = EPOLLIN|EPOLLOUT|EPOLLET; ee.data.ptr = NULL; + (void) ee; efd = epoll_create(100); if (efd == -1) return 1;" . auto/feature @@ -69,6 +70,22 @@ if [ $ngx_found = yes ]; then ee.data.ptr = NULL; epoll_ctl(efd, EPOLL_CTL_ADD, fd, &ee)" . auto/feature + + + # EPOLLEXCLUSIVE appeared in Linux 4.5, glibc 2.24 + + ngx_feature="EPOLLEXCLUSIVE" + ngx_feature_name="NGX_HAVE_EPOLLEXCLUSIVE" + ngx_feature_run=no + ngx_feature_incs="#include " + ngx_feature_path= + ngx_feature_libs= + ngx_feature_test="int efd = 0, fd = 0; + struct epoll_event ee; + ee.events = EPOLLIN|EPOLLEXCLUSIVE; + ee.data.ptr = NULL; + epoll_ctl(efd, EPOLL_CTL_ADD, fd, &ee)" + . auto/feature fi diff --git a/auto/os/solaris b/auto/os/solaris index d39df0b..1dcfe84 100644 --- a/auto/os/solaris +++ b/auto/os/solaris @@ -52,7 +52,7 @@ ngx_feature_run=no ngx_feature_incs="#include " ngx_feature_path= ngx_feature_libs= -ngx_feature_test="int n = port_create()" +ngx_feature_test="(void) port_create()" . auto/feature if [ $ngx_found = yes ]; then diff --git a/auto/sources b/auto/sources index 27849e6..216e900 100644 --- a/auto/sources +++ b/auto/sources @@ -61,6 +61,7 @@ CORE_SRCS="src/core/nginx.c \ src/core/ngx_crc32.c \ src/core/ngx_murmurhash.c \ src/core/ngx_md5.c \ + src/core/ngx_sha1.c \ src/core/ngx_rbtree.c \ src/core/ngx_radix_tree.c \ src/core/ngx_slab.c \ diff --git a/auto/summary b/auto/summary index dc8fe4f..9aa776e 100644 --- a/auto/summary +++ b/auto/summary @@ -28,20 +28,6 @@ case $OPENSSL in *) echo " + using OpenSSL library: $OPENSSL" ;; esac -case $MD5 in - YES) echo " + md5: using $MD5_LIB library" ;; - NONE) echo " + md5 library is not used" ;; - NO) echo " + using builtin md5 code" ;; - *) echo " + using md5 library: $MD5" ;; -esac - -case $SHA1 in - YES) echo " + sha1: using $SHA1_LIB library" ;; - NONE) echo " + sha1 library is not used" ;; - NO) echo " + sha1 library is not found" ;; - *) echo " + using sha1 library: $SHA1" ;; -esac - case $ZLIB in YES) echo " + using system zlib library" ;; NONE) echo " + zlib library is not used" ;; diff --git a/auto/types/sizeof b/auto/types/sizeof index b5b71bb..480d8cf 100644 --- a/auto/types/sizeof +++ b/auto/types/sizeof @@ -25,7 +25,7 @@ $NGX_INCLUDE_UNISTD_H $NGX_INCLUDE_INTTYPES_H $NGX_INCLUDE_AUTO_CONFIG_H -int main() { +int main(void) { printf("%d", (int) sizeof($ngx_type)); return 0; } diff --git a/auto/types/typedef b/auto/types/typedef index b55237e..d54c289 100644 --- a/auto/types/typedef +++ b/auto/types/typedef @@ -27,7 +27,7 @@ do #include $NGX_INCLUDE_INTTYPES_H -int main() { +int main(void) { $ngx_try i = 0; return (int) i; } diff --git a/auto/types/uintptr_t b/auto/types/uintptr_t index 2b7212e..a33d6d0 100644 --- a/auto/types/uintptr_t +++ b/auto/types/uintptr_t @@ -17,9 +17,9 @@ found=no cat << END > $NGX_AUTOTEST.c #include -$NGX_INTTYPES_H +$NGX_INCLUDE_INTTYPES_H -int main() { +int main(void) { uintptr_t i = 0; return (int) i; } diff --git a/auto/unix b/auto/unix index 8c0e813..dbc0f0e 100755 --- a/auto/unix +++ b/auto/unix @@ -75,7 +75,7 @@ if test -z "$NGX_KQUEUE_CHECKED"; then ngx_feature_incs="#include " ngx_feature_path= ngx_feature_libs= - ngx_feature_test="int kq; kq = kqueue()" + ngx_feature_test="(void) kqueue()" . auto/feature if [ $ngx_found = yes ]; then @@ -92,7 +92,8 @@ if test -z "$NGX_KQUEUE_CHECKED"; then ngx_feature_path= ngx_feature_libs= ngx_feature_test="struct kevent kev; - kev.fflags = NOTE_LOWAT;" + kev.fflags = NOTE_LOWAT; + (void) kev" . auto/feature @@ -260,11 +261,11 @@ ngx_feature_run=no ngx_feature_incs="#include " ngx_feature_path= ngx_feature_libs= -ngx_feature_test="dlopen(NULL, RTLD_NOW | RTLD_GLOBAL); dlsym(NULL, NULL)" +ngx_feature_test="dlopen(NULL, RTLD_NOW | RTLD_GLOBAL); dlsym(NULL, \"\")" . auto/feature -if [ $ngx_found != yes ]; then +if [ $ngx_found = no ]; then ngx_feature="dlopen() in libdl" ngx_feature_libs="-ldl" @@ -287,7 +288,7 @@ ngx_feature_test="sched_yield()" . auto/feature -if [ $ngx_found != yes ]; then +if [ $ngx_found = no ]; then ngx_feature="sched_yield() in librt" ngx_feature_libs="-lrt" @@ -329,6 +330,57 @@ ngx_feature_test="setsockopt(0, SOL_SOCKET, SO_ACCEPTFILTER, NULL, 0)" . auto/feature +# NetBSD bind to any address for transparent proxying + +ngx_feature="SO_BINDANY" +ngx_feature_name="NGX_HAVE_TRANSPARENT_PROXY" +ngx_feature_run=no +ngx_feature_incs="#include " +ngx_feature_path= +ngx_feature_libs= +ngx_feature_test="setsockopt(0, SOL_SOCKET, SO_BINDANY, NULL, 0)" +. auto/feature + + +# Linux IP_BIND_ADDRESS_NO_PORT + +ngx_feature="IP_BIND_ADDRESS_NO_PORT" +ngx_feature_name="NGX_HAVE_IP_BIND_ADDRESS_NO_PORT" +ngx_feature_run=no +ngx_feature_incs="#include + #include " +ngx_feature_path= +ngx_feature_libs= +ngx_feature_test="setsockopt(0, IPPROTO_IP, IP_BIND_ADDRESS_NO_PORT, NULL, 0)" +. auto/feature + + +# Linux transparent proxying + +ngx_feature="IP_TRANSPARENT" +ngx_feature_name="NGX_HAVE_TRANSPARENT_PROXY" +ngx_feature_run=no +ngx_feature_incs="#include + #include " +ngx_feature_path= +ngx_feature_libs= +ngx_feature_test="setsockopt(0, IPPROTO_IP, IP_TRANSPARENT, NULL, 0)" +. auto/feature + + +# FreeBSD bind to any address for transparent proxying + +ngx_feature="IP_BINDANY" +ngx_feature_name="NGX_HAVE_TRANSPARENT_PROXY" +ngx_feature_run=no +ngx_feature_incs="#include + #include " +ngx_feature_path= +ngx_feature_libs= +ngx_feature_test="setsockopt(0, IPPROTO_IP, IP_BINDANY, NULL, 0)" +. auto/feature + + # BSD way to get IPv4 datagram destination address ngx_feature="IP_RECVDSTADDR" @@ -441,9 +493,9 @@ if [ $NGX_FILE_AIO = YES ]; then ngx_feature_incs="#include " ngx_feature_path= ngx_feature_libs= - ngx_feature_test="int n; struct aiocb iocb; + ngx_feature_test="struct aiocb iocb; iocb.aio_sigevent.sigev_notify = SIGEV_KEVENT; - n = aio_read(&iocb)" + (void) aio_read(&iocb)" . auto/feature if [ $ngx_found = yes ]; then @@ -463,6 +515,7 @@ if [ $NGX_FILE_AIO = YES ]; then iocb.aio_lio_opcode = IOCB_CMD_PREAD; iocb.aio_flags = IOCB_FLAG_RESFD; iocb.aio_resfd = -1; + (void) iocb; (void) eventfd(0, 0)" . auto/feature @@ -478,11 +531,12 @@ if [ $NGX_FILE_AIO = YES ]; then ngx_feature="Linux AIO support (SYS_eventfd)" ngx_feature_incs="#include #include " - ngx_feature_test="int n = SYS_eventfd; - struct iocb iocb; + ngx_feature_test="struct iocb iocb; iocb.aio_lio_opcode = IOCB_CMD_PREAD; iocb.aio_flags = IOCB_FLAG_RESFD; - iocb.aio_resfd = -1;" + iocb.aio_resfd = -1; + (void) iocb; + (void) SYS_eventfd" . auto/feature if [ $ngx_found = yes ]; then @@ -520,7 +574,7 @@ else ngx_feature="eventfd() (SYS_eventfd)" ngx_feature_incs="#include " - ngx_feature_test="int n = SYS_eventfd" + ngx_feature_test="(void) SYS_eventfd" . auto/feature fi fi @@ -593,7 +647,8 @@ if [ $NGX_IPV6 = YES ]; then ngx_feature_path= ngx_feature_libs= ngx_feature_test="struct sockaddr_in6 sin6; - sin6.sin6_family = AF_INET6;" + sin6.sin6_family = AF_INET6; + (void) sin6" . auto/feature fi diff --git a/src/core/nginx.h b/src/core/nginx.h index e2b8005..e303e66 100644 --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1010001 -#define NGINX_VERSION "1.10.1" +#define nginx_version 1011003 +#define NGINX_VERSION "1.11.3" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD diff --git a/src/core/ngx_conf_file.h b/src/core/ngx_conf_file.h index 9ccee36..213611f 100644 --- a/src/core/ngx_conf_file.h +++ b/src/core/ngx_conf_file.h @@ -45,7 +45,6 @@ #define NGX_CONF_ANY 0x00000400 #define NGX_CONF_1MORE 0x00000800 #define NGX_CONF_2MORE 0x00001000 -#define NGX_CONF_MULTI 0x00000000 /* compatibility */ #define NGX_DIRECT_CONF 0x00010000 diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c index 5a53bac..16ba630 100644 --- a/src/core/ngx_connection.c +++ b/src/core/ngx_connection.c @@ -17,7 +17,8 @@ static void ngx_drain_connections(void); ngx_listening_t * -ngx_create_listening(ngx_conf_t *cf, void *sockaddr, socklen_t socklen) +ngx_create_listening(ngx_conf_t *cf, struct sockaddr *sockaddr, + socklen_t socklen) { size_t len; ngx_listening_t *ls; @@ -150,12 +151,12 @@ ngx_set_inherited_sockets(ngx_cycle_t *cycle) ls = cycle->listening.elts; for (i = 0; i < cycle->listening.nelts; i++) { - ls[i].sockaddr = ngx_palloc(cycle->pool, NGX_SOCKADDRLEN); + ls[i].sockaddr = ngx_palloc(cycle->pool, sizeof(ngx_sockaddr_t)); if (ls[i].sockaddr == NULL) { return NGX_ERROR; } - ls[i].socklen = NGX_SOCKADDRLEN; + ls[i].socklen = sizeof(ngx_sockaddr_t); if (getsockname(ls[i].fd, ls[i].sockaddr, &ls[i].socklen) == -1) { ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno, "getsockname() of the inherited " @@ -1277,7 +1278,7 @@ ngx_connection_local_sockaddr(ngx_connection_t *c, ngx_str_t *s, { socklen_t len; ngx_uint_t addr; - u_char sa[NGX_SOCKADDRLEN]; + ngx_sockaddr_t sa; struct sockaddr_in *sin; #if (NGX_HAVE_INET6) ngx_uint_t i; @@ -1315,9 +1316,9 @@ ngx_connection_local_sockaddr(ngx_connection_t *c, ngx_str_t *s, if (addr == 0) { - len = NGX_SOCKADDRLEN; + len = sizeof(ngx_sockaddr_t); - if (getsockname(c->fd, (struct sockaddr *) &sa, &len) == -1) { + if (getsockname(c->fd, &sa.sockaddr, &len) == -1) { ngx_connection_error(c, ngx_socket_errno, "getsockname() failed"); return NGX_ERROR; } diff --git a/src/core/ngx_connection.h b/src/core/ngx_connection.h index b0d162a..e484c81 100644 --- a/src/core/ngx_connection.h +++ b/src/core/ngx_connection.h @@ -149,6 +149,7 @@ struct ngx_connection_s { ngx_str_t addr_text; ngx_str_t proxy_protocol_addr; + in_port_t proxy_protocol_port; #if (NGX_SSL) ngx_ssl_connection_t *ssl; @@ -169,7 +170,6 @@ struct ngx_connection_s { unsigned log_error:3; /* ngx_connection_log_error_e */ - unsigned unexpected_eof:1; unsigned timedout:1; unsigned error:1; unsigned destroyed:1; @@ -186,10 +186,6 @@ struct ngx_connection_s { unsigned need_last_buf:1; -#if (NGX_HAVE_IOCP) - unsigned accept_context_updated:1; -#endif - #if (NGX_HAVE_AIO_SENDFILE) unsigned busy_count:2; #endif @@ -211,7 +207,7 @@ struct ngx_connection_s { } -ngx_listening_t *ngx_create_listening(ngx_conf_t *cf, void *sockaddr, +ngx_listening_t *ngx_create_listening(ngx_conf_t *cf, struct sockaddr *sockaddr, socklen_t socklen); ngx_int_t ngx_clone_listening(ngx_conf_t *cf, ngx_listening_t *ls); ngx_int_t ngx_set_inherited_sockets(ngx_cycle_t *cycle); diff --git a/src/core/ngx_crypt.c b/src/core/ngx_crypt.c index 9db74f4..868dc5d 100644 --- a/src/core/ngx_crypt.c +++ b/src/core/ngx_crypt.c @@ -8,9 +8,7 @@ #include #include #include -#if (NGX_HAVE_SHA1) #include -#endif #if (NGX_CRYPT) @@ -19,16 +17,11 @@ static ngx_int_t ngx_crypt_apr1(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted); static ngx_int_t ngx_crypt_plain(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted); - -#if (NGX_HAVE_SHA1) - static ngx_int_t ngx_crypt_ssha(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted); static ngx_int_t ngx_crypt_sha(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted); -#endif - static u_char *ngx_crypt_to64(u_char *p, uint32_t v, size_t n); @@ -42,13 +35,11 @@ ngx_crypt(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted) } else if (ngx_strncmp(salt, "{PLAIN}", sizeof("{PLAIN}") - 1) == 0) { return ngx_crypt_plain(pool, key, salt, encrypted); -#if (NGX_HAVE_SHA1) } else if (ngx_strncmp(salt, "{SSHA}", sizeof("{SSHA}") - 1) == 0) { return ngx_crypt_ssha(pool, key, salt, encrypted); } else if (ngx_strncmp(salt, "{SHA}", sizeof("{SHA}") - 1) == 0) { return ngx_crypt_sha(pool, key, salt, encrypted); -#endif } /* fallback to libc crypt() */ @@ -193,8 +184,6 @@ ngx_crypt_plain(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted) } -#if (NGX_HAVE_SHA1) - static ngx_int_t ngx_crypt_ssha(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted) { @@ -278,6 +267,4 @@ ngx_crypt_sha(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted) return NGX_OK; } -#endif /* NGX_HAVE_SHA1 */ - #endif /* NGX_CRYPT */ diff --git a/src/core/ngx_file.c b/src/core/ngx_file.c index fc2dfd3..c1137cc 100644 --- a/src/core/ngx_file.c +++ b/src/core/ngx_file.c @@ -225,7 +225,7 @@ ngx_create_hashed_filename(ngx_path_t *path, u_char *file, size_t len) file[path->name.len + path->len] = '/'; - for (n = 0; n < 3; n++) { + for (n = 0; n < NGX_MAX_PATH_LEVEL; n++) { level = path->level[n]; if (level == 0) { @@ -249,7 +249,7 @@ ngx_create_path(ngx_file_t *file, ngx_path_t *path) pos = path->name.len; - for (i = 0; i < 3; i++) { + for (i = 0; i < NGX_MAX_PATH_LEVEL; i++) { if (path->level[i] == 0) { break; } @@ -399,6 +399,8 @@ char * ngx_conf_merge_path_value(ngx_conf_t *cf, ngx_path_t **path, ngx_path_t *prev, ngx_path_init_t *init) { + ngx_uint_t i; + if (*path) { return NGX_CONF_OK; } @@ -419,13 +421,10 @@ ngx_conf_merge_path_value(ngx_conf_t *cf, ngx_path_t **path, ngx_path_t *prev, return NGX_CONF_ERROR; } - (*path)->level[0] = init->level[0]; - (*path)->level[1] = init->level[1]; - (*path)->level[2] = init->level[2]; - - (*path)->len = init->level[0] + (init->level[0] ? 1 : 0) - + init->level[1] + (init->level[1] ? 1 : 0) - + init->level[2] + (init->level[2] ? 1 : 0); + for (i = 0; i < NGX_MAX_PATH_LEVEL; i++) { + (*path)->level[i] = init->level[i]; + (*path)->len += init->level[i] + (init->level[i] ? 1 : 0); + } if (ngx_add_path(cf, path) != NGX_OK) { return NGX_CONF_ERROR; @@ -518,7 +517,7 @@ ngx_add_path(ngx_conf_t *cf, ngx_path_t **slot) return NGX_ERROR; } - for (n = 0; n < 3; n++) { + for (n = 0; n < NGX_MAX_PATH_LEVEL; n++) { if (p[i]->level[n] != path->level[n]) { if (path->conf_file == NULL) { if (p[i]->conf_file == NULL) { diff --git a/src/core/ngx_file.h b/src/core/ngx_file.h index 5f8228b..a723c3d 100644 --- a/src/core/ngx_file.h +++ b/src/core/ngx_file.h @@ -49,7 +49,7 @@ typedef void (*ngx_path_loader_pt) (void *data); typedef struct { ngx_str_t name; size_t len; - size_t level[3]; + size_t level[NGX_MAX_PATH_LEVEL]; ngx_path_manager_pt manager; ngx_path_loader_pt loader; @@ -62,7 +62,7 @@ typedef struct { typedef struct { ngx_str_t name; - size_t level[3]; + size_t level[NGX_MAX_PATH_LEVEL]; } ngx_path_init_t; diff --git a/src/core/ngx_inet.c b/src/core/ngx_inet.c index 33b303d..c4aaf3a 100644 --- a/src/core/ngx_inet.c +++ b/src/core/ngx_inet.c @@ -525,6 +525,68 @@ ngx_parse_addr(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text, size_t len) } +ngx_int_t +ngx_parse_addr_port(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text, + size_t len) +{ + u_char *p, *last; + size_t plen; + ngx_int_t rc, port; + + rc = ngx_parse_addr(pool, addr, text, len); + + if (rc != NGX_DECLINED) { + return rc; + } + + last = text + len; + +#if (NGX_HAVE_INET6) + if (len && text[0] == '[') { + + p = ngx_strlchr(text, last, ']'); + + if (p == NULL || p == last - 1 || *++p != ':') { + return NGX_DECLINED; + } + + text++; + len -= 2; + + } else +#endif + + { + p = ngx_strlchr(text, last, ':'); + + if (p == NULL) { + return NGX_DECLINED; + } + } + + p++; + plen = last - p; + + port = ngx_atoi(p, plen); + + if (port < 1 || port > 65535) { + return NGX_DECLINED; + } + + len -= plen + 1; + + rc = ngx_parse_addr(pool, addr, text, len); + + if (rc != NGX_OK) { + return rc; + } + + ngx_inet_set_port(addr->sockaddr, (in_port_t) port); + + return NGX_OK; +} + + ngx_int_t ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u) { @@ -763,7 +825,7 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u) return NGX_ERROR; } - ngx_memcpy(sin, u->sockaddr, sizeof(struct sockaddr_in)); + ngx_memcpy(sin, &u->sockaddr, sizeof(struct sockaddr_in)); u->addrs[0].sockaddr = (struct sockaddr *) sin; u->addrs[0].socklen = sizeof(struct sockaddr_in); @@ -790,7 +852,7 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u) u->family = u->addrs[0].sockaddr->sa_family; u->socklen = u->addrs[0].socklen; - ngx_memcpy(u->sockaddr, u->addrs[0].sockaddr, u->addrs[0].socklen); + ngx_memcpy(&u->sockaddr, u->addrs[0].sockaddr, u->addrs[0].socklen); switch (u->family) { @@ -843,47 +905,49 @@ ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u) return NGX_ERROR; } - if (last - p) { + port = p + 1; - port = p + 1; + uri = ngx_strlchr(port, last, '/'); - uri = ngx_strlchr(port, last, '/'); - - if (uri) { - if (u->listen || !u->uri_part) { - u->err = "invalid host"; - return NGX_ERROR; - } - - u->uri.len = last - uri; - u->uri.data = uri; - - last = uri; + if (uri) { + if (u->listen || !u->uri_part) { + u->err = "invalid host"; + return NGX_ERROR; } - if (*port == ':') { - port++; + u->uri.len = last - uri; + u->uri.data = uri; - len = last - port; + last = uri; + } - n = ngx_atoi(port, len); - - if (n < 1 || n > 65535) { - u->err = "invalid port"; - return NGX_ERROR; - } - - u->port = (in_port_t) n; - sin6->sin6_port = htons((in_port_t) n); - - u->port_text.len = len; - u->port_text.data = port; - - } else { - u->no_port = 1; - u->port = u->default_port; - sin6->sin6_port = htons(u->default_port); + if (port < last) { + if (*port != ':') { + u->err = "invalid host"; + return NGX_ERROR; } + + port++; + + len = last - port; + + n = ngx_atoi(port, len); + + if (n < 1 || n > 65535) { + u->err = "invalid port"; + return NGX_ERROR; + } + + u->port = (in_port_t) n; + sin6->sin6_port = htons((in_port_t) n); + + u->port_text.len = len; + u->port_text.data = port; + + } else { + u->no_port = 1; + u->port = u->default_port; + sin6->sin6_port = htons(u->default_port); } len = p - host; @@ -918,7 +982,7 @@ ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u) return NGX_ERROR; } - ngx_memcpy(sin6, u->sockaddr, sizeof(struct sockaddr_in6)); + ngx_memcpy(sin6, &u->sockaddr, sizeof(struct sockaddr_in6)); u->addrs[0].sockaddr = (struct sockaddr *) sin6; u->addrs[0].socklen = sizeof(struct sockaddr_in6); @@ -1275,3 +1339,61 @@ ngx_cmp_sockaddr(struct sockaddr *sa1, socklen_t slen1, return NGX_OK; } + + +in_port_t +ngx_inet_get_port(struct sockaddr *sa) +{ + struct sockaddr_in *sin; +#if (NGX_HAVE_INET6) + struct sockaddr_in6 *sin6; +#endif + + switch (sa->sa_family) { + +#if (NGX_HAVE_INET6) + case AF_INET6: + sin6 = (struct sockaddr_in6 *) sa; + return ntohs(sin6->sin6_port); +#endif + +#if (NGX_HAVE_UNIX_DOMAIN) + case AF_UNIX: + return 0; +#endif + + default: /* AF_INET */ + sin = (struct sockaddr_in *) sa; + return ntohs(sin->sin_port); + } +} + + +void +ngx_inet_set_port(struct sockaddr *sa, in_port_t port) +{ + struct sockaddr_in *sin; +#if (NGX_HAVE_INET6) + struct sockaddr_in6 *sin6; +#endif + + switch (sa->sa_family) { + +#if (NGX_HAVE_INET6) + case AF_INET6: + sin6 = (struct sockaddr_in6 *) sa; + sin6->sin6_port = htons(port); + break; +#endif + +#if (NGX_HAVE_UNIX_DOMAIN) + case AF_UNIX: + break; +#endif + + default: /* AF_INET */ + sin = (struct sockaddr_in *) sa; + sin->sin_port = htons(port); + break; + } +} diff --git a/src/core/ngx_inet.h b/src/core/ngx_inet.h index 0555750..97dc354 100644 --- a/src/core/ngx_inet.h +++ b/src/core/ngx_inet.h @@ -13,14 +13,6 @@ #include -/* - * TODO: autoconfigure NGX_SOCKADDRLEN and NGX_SOCKADDR_STRLEN as - * sizeof(struct sockaddr_storage) - * sizeof(struct sockaddr_un) - * sizeof(struct sockaddr_in6) - * sizeof(struct sockaddr_in) - */ - #define NGX_INET_ADDRSTRLEN (sizeof("255.255.255.255") - 1) #define NGX_INET6_ADDRSTRLEN \ (sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") - 1) @@ -29,15 +21,26 @@ #if (NGX_HAVE_UNIX_DOMAIN) #define NGX_SOCKADDR_STRLEN (sizeof("unix:") - 1 + NGX_UNIX_ADDRSTRLEN) -#else +#elif (NGX_HAVE_INET6) #define NGX_SOCKADDR_STRLEN (NGX_INET6_ADDRSTRLEN + sizeof("[]:65535") - 1) +#else +#define NGX_SOCKADDR_STRLEN (NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1) #endif -#if (NGX_HAVE_UNIX_DOMAIN) -#define NGX_SOCKADDRLEN sizeof(struct sockaddr_un) -#else -#define NGX_SOCKADDRLEN 512 +/* compatibility */ +#define NGX_SOCKADDRLEN sizeof(ngx_sockaddr_t) + + +typedef union { + struct sockaddr sockaddr; + struct sockaddr_in sockaddr_in; +#if (NGX_HAVE_INET6) + struct sockaddr_in6 sockaddr_in6; #endif +#if (NGX_HAVE_UNIX_DOMAIN) + struct sockaddr_un sockaddr_un; +#endif +} ngx_sockaddr_t; typedef struct { @@ -87,13 +90,12 @@ typedef struct { unsigned listen:1; unsigned uri_part:1; unsigned no_resolve:1; - unsigned one_addr:1; /* compatibility */ unsigned no_port:1; unsigned wildcard:1; socklen_t socklen; - u_char sockaddr[NGX_SOCKADDRLEN]; + ngx_sockaddr_t sockaddr; ngx_addr_t *addrs; ngx_uint_t naddrs; @@ -113,10 +115,14 @@ size_t ngx_inet_ntop(int family, void *addr, u_char *text, size_t len); ngx_int_t ngx_ptocidr(ngx_str_t *text, ngx_cidr_t *cidr); ngx_int_t ngx_parse_addr(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text, size_t len); +ngx_int_t ngx_parse_addr_port(ngx_pool_t *pool, ngx_addr_t *addr, + u_char *text, size_t len); ngx_int_t ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u); ngx_int_t ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u); ngx_int_t ngx_cmp_sockaddr(struct sockaddr *sa1, socklen_t slen1, struct sockaddr *sa2, socklen_t slen2, ngx_uint_t cmp_port); +in_port_t ngx_inet_get_port(struct sockaddr *sa); +void ngx_inet_set_port(struct sockaddr *sa, in_port_t port); #endif /* _NGX_INET_H_INCLUDED_ */ diff --git a/src/core/ngx_md5.c b/src/core/ngx_md5.c index 440c75b..c25d002 100644 --- a/src/core/ngx_md5.c +++ b/src/core/ngx_md5.c @@ -3,8 +3,6 @@ * An internal implementation, based on Alexander Peslyak's * public domain implementation: * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 - * It is not expected to be optimal and is used only - * if no MD5 implementation was found in system. */ @@ -13,8 +11,6 @@ #include -#if !(NGX_HAVE_MD5) - static const u_char *ngx_md5_body(ngx_md5_t *ctx, const u_char *data, size_t size); @@ -285,5 +281,3 @@ ngx_md5_body(ngx_md5_t *ctx, const u_char *data, size_t size) return p; } - -#endif diff --git a/src/core/ngx_md5.h b/src/core/ngx_md5.h index 18d09d6..713b614 100644 --- a/src/core/ngx_md5.h +++ b/src/core/ngx_md5.h @@ -13,36 +13,6 @@ #include -#if (NGX_HAVE_MD5) - -#if (NGX_HAVE_OPENSSL_MD5_H) -#include -#else -#include -#endif - - -typedef MD5_CTX ngx_md5_t; - - -#if (NGX_OPENSSL_MD5) - -#define ngx_md5_init MD5_Init -#define ngx_md5_update MD5_Update -#define ngx_md5_final MD5_Final - -#else - -#define ngx_md5_init MD5Init -#define ngx_md5_update MD5Update -#define ngx_md5_final MD5Final - -#endif - - -#else /* !NGX_HAVE_MD5 */ - - typedef struct { uint64_t bytes; uint32_t a, b, c, d; @@ -55,6 +25,4 @@ void ngx_md5_update(ngx_md5_t *ctx, const void *data, size_t size); void ngx_md5_final(u_char result[16], ngx_md5_t *ctx); -#endif - #endif /* _NGX_MD5_H_INCLUDED_ */ diff --git a/src/core/ngx_module.h b/src/core/ngx_module.h index e911cb4..a1a0d6c 100644 --- a/src/core/ngx_module.h +++ b/src/core/ngx_module.h @@ -119,17 +119,8 @@ #define NGX_MODULE_SIGNATURE_16 "0" #endif -#if (NGX_HAVE_MD5) -#define NGX_MODULE_SIGNATURE_17 "1" -#else #define NGX_MODULE_SIGNATURE_17 "0" -#endif - -#if (NGX_HAVE_SHA1) -#define NGX_MODULE_SIGNATURE_18 "1" -#else #define NGX_MODULE_SIGNATURE_18 "0" -#endif #if (NGX_HAVE_OPENAT) #define NGX_MODULE_SIGNATURE_19 "1" diff --git a/src/core/ngx_proxy_protocol.c b/src/core/ngx_proxy_protocol.c index f347e7f..523ec35 100644 --- a/src/core/ngx_proxy_protocol.c +++ b/src/core/ngx_proxy_protocol.c @@ -12,8 +12,9 @@ u_char * ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last) { - size_t len; - u_char ch, *p, *addr; + size_t len; + u_char ch, *p, *addr, *port; + ngx_int_t n; p = buf; len = last - buf; @@ -71,8 +72,40 @@ ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last) ngx_memcpy(c->proxy_protocol_addr.data, addr, len); c->proxy_protocol_addr.len = len; - ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0, - "PROXY protocol address: \"%V\"", &c->proxy_protocol_addr); + for ( ;; ) { + if (p == last) { + goto invalid; + } + + if (*p++ == ' ') { + break; + } + } + + port = p; + + for ( ;; ) { + if (p == last) { + goto invalid; + } + + if (*p++ == ' ') { + break; + } + } + + len = p - port - 1; + + n = ngx_atoi(port, len); + + if (n < 0 || n > 65535) { + goto invalid; + } + + c->proxy_protocol_port = (in_port_t) n; + + ngx_log_debug2(NGX_LOG_DEBUG_CORE, c->log, 0, + "PROXY protocol address: %V %i", &c->proxy_protocol_addr, n); skip: @@ -108,19 +141,11 @@ ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf, u_char *last) case AF_INET: buf = ngx_cpymem(buf, "PROXY TCP4 ", sizeof("PROXY TCP4 ") - 1); - - port = ntohs(((struct sockaddr_in *) c->sockaddr)->sin_port); - lport = ntohs(((struct sockaddr_in *) c->local_sockaddr)->sin_port); - break; #if (NGX_HAVE_INET6) case AF_INET6: buf = ngx_cpymem(buf, "PROXY TCP6 ", sizeof("PROXY TCP6 ") - 1); - - port = ntohs(((struct sockaddr_in6 *) c->sockaddr)->sin6_port); - lport = ntohs(((struct sockaddr_in6 *) c->local_sockaddr)->sin6_port); - break; #endif @@ -136,5 +161,8 @@ ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf, u_char *last) buf += ngx_sock_ntop(c->local_sockaddr, c->local_socklen, buf, last - buf, 0); + port = ngx_inet_get_port(c->sockaddr); + lport = ngx_inet_get_port(c->local_sockaddr); + return ngx_slprintf(buf, last, " %ui %ui" CRLF, port, lport); } diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c index e00fe22..53dae6b 100644 --- a/src/core/ngx_resolver.c +++ b/src/core/ngx_resolver.c @@ -2992,16 +2992,12 @@ failed: static void ngx_resolver_srv_names_handler(ngx_resolver_ctx_t *cctx) { - ngx_uint_t i; - u_char (*sockaddr)[NGX_SOCKADDRLEN]; - ngx_addr_t *addrs; - ngx_resolver_t *r; - struct sockaddr_in *sin; - ngx_resolver_ctx_t *ctx; - ngx_resolver_srv_name_t *srv; -#if (NGX_HAVE_INET6) - struct sockaddr_in6 *sin6; -#endif + ngx_uint_t i; + ngx_addr_t *addrs; + ngx_resolver_t *r; + ngx_sockaddr_t *sockaddr; + ngx_resolver_ctx_t *ctx; + ngx_resolver_srv_name_t *srv; r = cctx->resolver; ctx = cctx->data; @@ -3026,7 +3022,7 @@ ngx_resolver_srv_names_handler(ngx_resolver_ctx_t *cctx) return; } - sockaddr = ngx_resolver_alloc(r, cctx->naddrs * NGX_SOCKADDRLEN); + sockaddr = ngx_resolver_alloc(r, cctx->naddrs * sizeof(ngx_sockaddr_t)); if (sockaddr == NULL) { ngx_resolver_free(r, addrs); ngx_resolve_name_done(cctx); @@ -3039,23 +3035,13 @@ ngx_resolver_srv_names_handler(ngx_resolver_ctx_t *cctx) } for (i = 0; i < cctx->naddrs; i++) { - addrs[i].sockaddr = (struct sockaddr *) sockaddr[i]; + addrs[i].sockaddr = &sockaddr[i].sockaddr; addrs[i].socklen = cctx->addrs[i].socklen; - ngx_memcpy(sockaddr[i], cctx->addrs[i].sockaddr, + ngx_memcpy(&sockaddr[i], cctx->addrs[i].sockaddr, addrs[i].socklen); - switch (addrs[i].sockaddr->sa_family) { -#if (NGX_HAVE_INET6) - case AF_INET6: - sin6 = (struct sockaddr_in6 *) addrs[i].sockaddr; - sin6->sin6_port = htons(srv->port); - break; -#endif - default: /* AF_INET */ - sin = (struct sockaddr_in *) addrs[i].sockaddr; - sin->sin_port = htons(srv->port); - } + ngx_inet_set_port(addrs[i].sockaddr, srv->port); } srv->addrs = addrs; @@ -4161,14 +4147,14 @@ static ngx_resolver_addr_t * ngx_resolver_export(ngx_resolver_t *r, ngx_resolver_node_t *rn, ngx_uint_t rotate) { - ngx_uint_t d, i, j, n; - u_char (*sockaddr)[NGX_SOCKADDRLEN]; - in_addr_t *addr; - struct sockaddr_in *sin; - ngx_resolver_addr_t *dst; + ngx_uint_t d, i, j, n; + in_addr_t *addr; + ngx_sockaddr_t *sockaddr; + struct sockaddr_in *sin; + ngx_resolver_addr_t *dst; #if (NGX_HAVE_INET6) - struct in6_addr *addr6; - struct sockaddr_in6 *sin6; + struct in6_addr *addr6; + struct sockaddr_in6 *sin6; #endif n = rn->naddrs; @@ -4181,7 +4167,7 @@ ngx_resolver_export(ngx_resolver_t *r, ngx_resolver_node_t *rn, return NULL; } - sockaddr = ngx_resolver_calloc(r, n * NGX_SOCKADDRLEN); + sockaddr = ngx_resolver_calloc(r, n * sizeof(ngx_sockaddr_t)); if (sockaddr == NULL) { ngx_resolver_free(r, dst); return NULL; @@ -4196,7 +4182,7 @@ ngx_resolver_export(ngx_resolver_t *r, ngx_resolver_node_t *rn, addr = (rn->naddrs == 1) ? &rn->u.addr : rn->u.addrs; do { - sin = (struct sockaddr_in *) sockaddr[d]; + sin = &sockaddr[d].sockaddr_in; sin->sin_family = AF_INET; sin->sin_addr.s_addr = addr[j++]; dst[d].sockaddr = (struct sockaddr *) sin; @@ -4219,7 +4205,7 @@ ngx_resolver_export(ngx_resolver_t *r, ngx_resolver_node_t *rn, addr6 = (rn->naddrs6 == 1) ? &rn->u6.addr6 : rn->u6.addrs6; do { - sin6 = (struct sockaddr_in6 *) sockaddr[d]; + sin6 = &sockaddr[d].sockaddr_in6; sin6->sin6_family = AF_INET6; ngx_memcpy(sin6->sin6_addr.s6_addr, addr6[j++].s6_addr, 16); dst[d].sockaddr = (struct sockaddr *) sin6; diff --git a/src/core/ngx_sha1.c b/src/core/ngx_sha1.c new file mode 100644 index 0000000..f00dc52 --- /dev/null +++ b/src/core/ngx_sha1.c @@ -0,0 +1,294 @@ + +/* + * Copyright (C) Maxim Dounin + * Copyright (C) Nginx, Inc. + * + * An internal SHA1 implementation. + */ + + +#include +#include +#include + + +static const u_char *ngx_sha1_body(ngx_sha1_t *ctx, const u_char *data, + size_t size); + + +void +ngx_sha1_init(ngx_sha1_t *ctx) +{ + ctx->a = 0x67452301; + ctx->b = 0xefcdab89; + ctx->c = 0x98badcfe; + ctx->d = 0x10325476; + ctx->e = 0xc3d2e1f0; + + ctx->bytes = 0; +} + + +void +ngx_sha1_update(ngx_sha1_t *ctx, const void *data, size_t size) +{ + size_t used, free; + + used = (size_t) (ctx->bytes & 0x3f); + ctx->bytes += size; + + if (used) { + free = 64 - used; + + if (size < free) { + ngx_memcpy(&ctx->buffer[used], data, size); + return; + } + + ngx_memcpy(&ctx->buffer[used], data, free); + data = (u_char *) data + free; + size -= free; + (void) ngx_sha1_body(ctx, ctx->buffer, 64); + } + + if (size >= 64) { + data = ngx_sha1_body(ctx, data, size & ~(size_t) 0x3f); + size &= 0x3f; + } + + ngx_memcpy(ctx->buffer, data, size); +} + + +void +ngx_sha1_final(u_char result[20], ngx_sha1_t *ctx) +{ + size_t used, free; + + used = (size_t) (ctx->bytes & 0x3f); + + ctx->buffer[used++] = 0x80; + + free = 64 - used; + + if (free < 8) { + ngx_memzero(&ctx->buffer[used], free); + (void) ngx_sha1_body(ctx, ctx->buffer, 64); + used = 0; + free = 64; + } + + ngx_memzero(&ctx->buffer[used], free - 8); + + ctx->bytes <<= 3; + ctx->buffer[56] = (u_char) (ctx->bytes >> 56); + ctx->buffer[57] = (u_char) (ctx->bytes >> 48); + ctx->buffer[58] = (u_char) (ctx->bytes >> 40); + ctx->buffer[59] = (u_char) (ctx->bytes >> 32); + ctx->buffer[60] = (u_char) (ctx->bytes >> 24); + ctx->buffer[61] = (u_char) (ctx->bytes >> 16); + ctx->buffer[62] = (u_char) (ctx->bytes >> 8); + ctx->buffer[63] = (u_char) ctx->bytes; + + (void) ngx_sha1_body(ctx, ctx->buffer, 64); + + result[0] = (u_char) (ctx->a >> 24); + result[1] = (u_char) (ctx->a >> 16); + result[2] = (u_char) (ctx->a >> 8); + result[3] = (u_char) ctx->a; + result[4] = (u_char) (ctx->b >> 24); + result[5] = (u_char) (ctx->b >> 16); + result[6] = (u_char) (ctx->b >> 8); + result[7] = (u_char) ctx->b; + result[8] = (u_char) (ctx->c >> 24); + result[9] = (u_char) (ctx->c >> 16); + result[10] = (u_char) (ctx->c >> 8); + result[11] = (u_char) ctx->c; + result[12] = (u_char) (ctx->d >> 24); + result[13] = (u_char) (ctx->d >> 16); + result[14] = (u_char) (ctx->d >> 8); + result[15] = (u_char) ctx->d; + result[16] = (u_char) (ctx->e >> 24); + result[17] = (u_char) (ctx->e >> 16); + result[18] = (u_char) (ctx->e >> 8); + result[19] = (u_char) ctx->e; + + ngx_memzero(ctx, sizeof(*ctx)); +} + + +/* + * Helper functions. + */ + +#define ROTATE(bits, word) (((word) << (bits)) | ((word) >> (32 - (bits)))) + +#define F1(b, c, d) (((b) & (c)) | ((~(b)) & (d))) +#define F2(b, c, d) ((b) ^ (c) ^ (d)) +#define F3(b, c, d) (((b) & (c)) | ((b) & (d)) | ((c) & (d))) + +#define STEP(f, a, b, c, d, e, w, t) \ + temp = ROTATE(5, (a)) + f((b), (c), (d)) + (e) + (w) + (t); \ + (e) = (d); \ + (d) = (c); \ + (c) = ROTATE(30, (b)); \ + (b) = (a); \ + (a) = temp; + + +/* + * GET() reads 4 input bytes in big-endian byte order and returns + * them as uint32_t. + */ + +#define GET(n) \ + ((uint32_t) p[n * 4 + 3] | \ + ((uint32_t) p[n * 4 + 2] << 8) | \ + ((uint32_t) p[n * 4 + 1] << 16) | \ + ((uint32_t) p[n * 4] << 24)) + + +/* + * This processes one or more 64-byte data blocks, but does not update + * the bit counters. There are no alignment requirements. + */ + +static const u_char * +ngx_sha1_body(ngx_sha1_t *ctx, const u_char *data, size_t size) +{ + uint32_t a, b, c, d, e, temp; + uint32_t saved_a, saved_b, saved_c, saved_d, saved_e; + uint32_t words[80]; + ngx_uint_t i; + const u_char *p; + + p = data; + + a = ctx->a; + b = ctx->b; + c = ctx->c; + d = ctx->d; + e = ctx->e; + + do { + saved_a = a; + saved_b = b; + saved_c = c; + saved_d = d; + saved_e = e; + + /* Load data block into the words array */ + + for (i = 0; i < 16; i++) { + words[i] = GET(i); + } + + for (i = 16; i < 80; i++) { + words[i] = ROTATE(1, words[i - 3] ^ words[i - 8] ^ words[i - 14] + ^ words[i - 16]); + } + + /* Transformations */ + + STEP(F1, a, b, c, d, e, words[0], 0x5a827999); + STEP(F1, a, b, c, d, e, words[1], 0x5a827999); + STEP(F1, a, b, c, d, e, words[2], 0x5a827999); + STEP(F1, a, b, c, d, e, words[3], 0x5a827999); + STEP(F1, a, b, c, d, e, words[4], 0x5a827999); + STEP(F1, a, b, c, d, e, words[5], 0x5a827999); + STEP(F1, a, b, c, d, e, words[6], 0x5a827999); + STEP(F1, a, b, c, d, e, words[7], 0x5a827999); + STEP(F1, a, b, c, d, e, words[8], 0x5a827999); + STEP(F1, a, b, c, d, e, words[9], 0x5a827999); + STEP(F1, a, b, c, d, e, words[10], 0x5a827999); + STEP(F1, a, b, c, d, e, words[11], 0x5a827999); + STEP(F1, a, b, c, d, e, words[12], 0x5a827999); + STEP(F1, a, b, c, d, e, words[13], 0x5a827999); + STEP(F1, a, b, c, d, e, words[14], 0x5a827999); + STEP(F1, a, b, c, d, e, words[15], 0x5a827999); + STEP(F1, a, b, c, d, e, words[16], 0x5a827999); + STEP(F1, a, b, c, d, e, words[17], 0x5a827999); + STEP(F1, a, b, c, d, e, words[18], 0x5a827999); + STEP(F1, a, b, c, d, e, words[19], 0x5a827999); + + STEP(F2, a, b, c, d, e, words[20], 0x6ed9eba1); + STEP(F2, a, b, c, d, e, words[21], 0x6ed9eba1); + STEP(F2, a, b, c, d, e, words[22], 0x6ed9eba1); + STEP(F2, a, b, c, d, e, words[23], 0x6ed9eba1); + STEP(F2, a, b, c, d, e, words[24], 0x6ed9eba1); + STEP(F2, a, b, c, d, e, words[25], 0x6ed9eba1); + STEP(F2, a, b, c, d, e, words[26], 0x6ed9eba1); + STEP(F2, a, b, c, d, e, words[27], 0x6ed9eba1); + STEP(F2, a, b, c, d, e, words[28], 0x6ed9eba1); + STEP(F2, a, b, c, d, e, words[29], 0x6ed9eba1); + STEP(F2, a, b, c, d, e, words[30], 0x6ed9eba1); + STEP(F2, a, b, c, d, e, words[31], 0x6ed9eba1); + STEP(F2, a, b, c, d, e, words[32], 0x6ed9eba1); + STEP(F2, a, b, c, d, e, words[33], 0x6ed9eba1); + STEP(F2, a, b, c, d, e, words[34], 0x6ed9eba1); + STEP(F2, a, b, c, d, e, words[35], 0x6ed9eba1); + STEP(F2, a, b, c, d, e, words[36], 0x6ed9eba1); + STEP(F2, a, b, c, d, e, words[37], 0x6ed9eba1); + STEP(F2, a, b, c, d, e, words[38], 0x6ed9eba1); + STEP(F2, a, b, c, d, e, words[39], 0x6ed9eba1); + + STEP(F3, a, b, c, d, e, words[40], 0x8f1bbcdc); + STEP(F3, a, b, c, d, e, words[41], 0x8f1bbcdc); + STEP(F3, a, b, c, d, e, words[42], 0x8f1bbcdc); + STEP(F3, a, b, c, d, e, words[43], 0x8f1bbcdc); + STEP(F3, a, b, c, d, e, words[44], 0x8f1bbcdc); + STEP(F3, a, b, c, d, e, words[45], 0x8f1bbcdc); + STEP(F3, a, b, c, d, e, words[46], 0x8f1bbcdc); + STEP(F3, a, b, c, d, e, words[47], 0x8f1bbcdc); + STEP(F3, a, b, c, d, e, words[48], 0x8f1bbcdc); + STEP(F3, a, b, c, d, e, words[49], 0x8f1bbcdc); + STEP(F3, a, b, c, d, e, words[50], 0x8f1bbcdc); + STEP(F3, a, b, c, d, e, words[51], 0x8f1bbcdc); + STEP(F3, a, b, c, d, e, words[52], 0x8f1bbcdc); + STEP(F3, a, b, c, d, e, words[53], 0x8f1bbcdc); + STEP(F3, a, b, c, d, e, words[54], 0x8f1bbcdc); + STEP(F3, a, b, c, d, e, words[55], 0x8f1bbcdc); + STEP(F3, a, b, c, d, e, words[56], 0x8f1bbcdc); + STEP(F3, a, b, c, d, e, words[57], 0x8f1bbcdc); + STEP(F3, a, b, c, d, e, words[58], 0x8f1bbcdc); + STEP(F3, a, b, c, d, e, words[59], 0x8f1bbcdc); + + STEP(F2, a, b, c, d, e, words[60], 0xca62c1d6); + STEP(F2, a, b, c, d, e, words[61], 0xca62c1d6); + STEP(F2, a, b, c, d, e, words[62], 0xca62c1d6); + STEP(F2, a, b, c, d, e, words[63], 0xca62c1d6); + STEP(F2, a, b, c, d, e, words[64], 0xca62c1d6); + STEP(F2, a, b, c, d, e, words[65], 0xca62c1d6); + STEP(F2, a, b, c, d, e, words[66], 0xca62c1d6); + STEP(F2, a, b, c, d, e, words[67], 0xca62c1d6); + STEP(F2, a, b, c, d, e, words[68], 0xca62c1d6); + STEP(F2, a, b, c, d, e, words[69], 0xca62c1d6); + STEP(F2, a, b, c, d, e, words[70], 0xca62c1d6); + STEP(F2, a, b, c, d, e, words[71], 0xca62c1d6); + STEP(F2, a, b, c, d, e, words[72], 0xca62c1d6); + STEP(F2, a, b, c, d, e, words[73], 0xca62c1d6); + STEP(F2, a, b, c, d, e, words[74], 0xca62c1d6); + STEP(F2, a, b, c, d, e, words[75], 0xca62c1d6); + STEP(F2, a, b, c, d, e, words[76], 0xca62c1d6); + STEP(F2, a, b, c, d, e, words[77], 0xca62c1d6); + STEP(F2, a, b, c, d, e, words[78], 0xca62c1d6); + STEP(F2, a, b, c, d, e, words[79], 0xca62c1d6); + + a += saved_a; + b += saved_b; + c += saved_c; + d += saved_d; + e += saved_e; + + p += 64; + + } while (size -= 64); + + ctx->a = a; + ctx->b = b; + ctx->c = c; + ctx->d = d; + ctx->e = e; + + return p; +} diff --git a/src/core/ngx_sha1.h b/src/core/ngx_sha1.h index 81c909e..4a98f71 100644 --- a/src/core/ngx_sha1.h +++ b/src/core/ngx_sha1.h @@ -13,19 +13,16 @@ #include -#if (NGX_HAVE_OPENSSL_SHA1_H) -#include -#else -#include -#endif +typedef struct { + uint64_t bytes; + uint32_t a, b, c, d, e, f; + u_char buffer[64]; +} ngx_sha1_t; -typedef SHA_CTX ngx_sha1_t; - - -#define ngx_sha1_init SHA1_Init -#define ngx_sha1_update SHA1_Update -#define ngx_sha1_final SHA1_Final +void ngx_sha1_init(ngx_sha1_t *ctx); +void ngx_sha1_update(ngx_sha1_t *ctx, const void *data, size_t size); +void ngx_sha1_final(u_char result[20], ngx_sha1_t *ctx); #endif /* _NGX_SHA1_H_INCLUDED_ */ diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c index cf665a4..7a73ef5 100644 --- a/src/core/ngx_string.c +++ b/src/core/ngx_string.c @@ -1563,7 +1563,7 @@ ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type) n = 0; while (size) { - if (escape[*src >> 5] & (1 << (*src & 0x1f))) { + if (escape[*src >> 5] & (1U << (*src & 0x1f))) { n++; } src++; @@ -1574,7 +1574,7 @@ ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type) } while (size) { - if (escape[*src >> 5] & (1 << (*src & 0x1f))) { + if (escape[*src >> 5] & (1U << (*src & 0x1f))) { *dst++ = '%'; *dst++ = hex[*src >> 4]; *dst++ = hex[*src & 0xf]; diff --git a/src/event/modules/ngx_epoll_module.c b/src/event/modules/ngx_epoll_module.c index 166c461..c267fd6 100644 --- a/src/event/modules/ngx_epoll_module.c +++ b/src/event/modules/ngx_epoll_module.c @@ -17,18 +17,19 @@ #define EPOLLIN 0x001 #define EPOLLPRI 0x002 #define EPOLLOUT 0x004 +#define EPOLLERR 0x008 +#define EPOLLHUP 0x010 #define EPOLLRDNORM 0x040 #define EPOLLRDBAND 0x080 #define EPOLLWRNORM 0x100 #define EPOLLWRBAND 0x200 #define EPOLLMSG 0x400 -#define EPOLLERR 0x008 -#define EPOLLHUP 0x010 #define EPOLLRDHUP 0x2000 -#define EPOLLET 0x80000000 +#define EPOLLEXCLUSIVE 0x10000000 #define EPOLLONESHOT 0x40000000 +#define EPOLLET 0x80000000 #define EPOLL_CTL_ADD 1 #define EPOLL_CTL_DEL 2 @@ -105,6 +106,9 @@ static ngx_int_t ngx_epoll_init(ngx_cycle_t *cycle, ngx_msec_t timer); static ngx_int_t ngx_epoll_notify_init(ngx_log_t *log); static void ngx_epoll_notify_handler(ngx_event_t *ev); #endif +#if (NGX_HAVE_EPOLLRDHUP) +static void ngx_epoll_test_rdhup(ngx_cycle_t *cycle); +#endif static void ngx_epoll_done(ngx_cycle_t *cycle); static ngx_int_t ngx_epoll_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags); @@ -146,6 +150,10 @@ static ngx_connection_t ngx_eventfd_conn; #endif +#if (NGX_HAVE_EPOLLRDHUP) +ngx_uint_t ngx_use_epoll_rdhup; +#endif + static ngx_str_t epoll_name = ngx_string("epoll"); static ngx_command_t ngx_epoll_commands[] = { @@ -334,9 +342,11 @@ ngx_epoll_init(ngx_cycle_t *cycle, ngx_msec_t timer) #endif #if (NGX_HAVE_FILE_AIO) - ngx_epoll_aio_init(cycle, epcf); +#endif +#if (NGX_HAVE_EPOLLRDHUP) + ngx_epoll_test_rdhup(cycle); #endif } @@ -449,6 +459,73 @@ ngx_epoll_notify_handler(ngx_event_t *ev) #endif +#if (NGX_HAVE_EPOLLRDHUP) + +static void +ngx_epoll_test_rdhup(ngx_cycle_t *cycle) +{ + int s[2], events; + struct epoll_event ee; + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, s) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "socketpair() failed"); + return; + } + + ee.events = EPOLLET|EPOLLIN|EPOLLRDHUP; + + if (epoll_ctl(ep, EPOLL_CTL_ADD, s[0], &ee) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "epoll_ctl() failed"); + goto failed; + } + + if (close(s[1]) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "close() failed"); + s[1] = -1; + goto failed; + } + + s[1] = -1; + + events = epoll_wait(ep, &ee, 1, 5000); + + if (events == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "epoll_wait() failed"); + goto failed; + } + + if (events) { + ngx_use_epoll_rdhup = ee.events & EPOLLRDHUP; + + } else { + ngx_log_error(NGX_LOG_ALERT, cycle->log, NGX_ETIMEDOUT, + "epoll_wait() timed out"); + } + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, + "testing the EPOLLRDHUP flag: %s", + ngx_use_epoll_rdhup ? "success" : "fail"); + +failed: + + if (s[1] != -1 && close(s[1]) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "close() failed"); + } + + if (close(s[0]) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "close() failed"); + } +} + +#endif + + static void ngx_epoll_done(ngx_cycle_t *cycle) { @@ -534,6 +611,12 @@ ngx_epoll_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags) op = EPOLL_CTL_ADD; } +#if (NGX_HAVE_EPOLLEXCLUSIVE && NGX_HAVE_EPOLLRDHUP) + if (flags & NGX_EXCLUSIVE_EVENT) { + events &= ~EPOLLRDHUP; + } +#endif + ee.events = events | (uint32_t) flags; ee.data.ptr = (void *) ((uintptr_t) c | ev->instance); @@ -808,6 +891,8 @@ ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags) if (revents & EPOLLRDHUP) { rev->pending_eof = 1; } + + rev->available = 1; #endif rev->ready = 1; diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c index c8ae5b2..9d6c4c9 100644 --- a/src/event/ngx_event.c +++ b/src/event/ngx_event.c @@ -822,15 +822,38 @@ ngx_event_process_init(ngx_cycle_t *cycle) rev->handler = (c->type == SOCK_STREAM) ? ngx_event_accept : ngx_event_recvmsg; - if (ngx_use_accept_mutex #if (NGX_HAVE_REUSEPORT) - && !ls[i].reuseport -#endif - ) - { + + if (ls[i].reuseport) { + if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) { + return NGX_ERROR; + } + continue; } +#endif + + if (ngx_use_accept_mutex) { + continue; + } + +#if (NGX_HAVE_EPOLLEXCLUSIVE) + + if ((ngx_event_flags & NGX_USE_EPOLL_EVENT) + && ccf->worker_processes > 1) + { + if (ngx_add_event(rev, NGX_READ_EVENT, NGX_EXCLUSIVE_EVENT) + == NGX_ERROR) + { + return NGX_ERROR; + } + + continue; + } + +#endif + if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) { return NGX_ERROR; } @@ -1261,7 +1284,7 @@ ngx_event_core_init_conf(ngx_cycle_t *cycle, void *conf) ngx_conf_init_ptr_value(ecf->name, event_module->name->data); ngx_conf_init_value(ecf->multi_accept, 0); - ngx_conf_init_value(ecf->accept_mutex, 1); + ngx_conf_init_value(ecf->accept_mutex, 0); ngx_conf_init_msec_value(ecf->accept_mutex_delay, 500); return NGX_CONF_OK; diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h index ed0682c..27139ee 100644 --- a/src/event/ngx_event.h +++ b/src/event/ngx_event.h @@ -76,11 +76,6 @@ struct ngx_event_s { unsigned cancelable:1; -#if (NGX_WIN32) - /* setsockopt(SO_UPDATE_ACCEPT_CONTEXT) was successful */ - unsigned accept_context_updated:1; -#endif - #if (NGX_HAVE_KQUEUE) unsigned kq_vnode:1; @@ -96,6 +91,10 @@ struct ngx_event_s { * write: available space in buffer when event is ready * or lowat when event is set with NGX_LOWAT_EVENT flag * + * epoll with EPOLLRDHUP: + * accept: 1 if accept many, 0 otherwise + * read: 1 if there can be data to read, 0 otherwise + * * iocp: TODO * * otherwise: @@ -196,6 +195,9 @@ typedef struct { extern ngx_event_actions_t ngx_event_actions; +#if (NGX_HAVE_EPOLLRDHUP) +extern ngx_uint_t ngx_use_epoll_rdhup; +#endif /* @@ -365,6 +367,9 @@ extern ngx_event_actions_t ngx_event_actions; #define NGX_ONESHOT_EVENT EPOLLONESHOT #endif +#if (NGX_HAVE_EPOLLEXCLUSIVE) +#define NGX_EXCLUSIVE_EVENT EPOLLEXCLUSIVE +#endif #elif (NGX_HAVE_POLL) @@ -393,6 +398,11 @@ extern ngx_event_actions_t ngx_event_actions; #endif +#if (NGX_TEST_BUILD_EPOLL) +#define NGX_EXCLUSIVE_EVENT 0 +#endif + + #ifndef NGX_CLEAR_EVENT #define NGX_CLEAR_EVENT 0 /* dummy declaration */ #endif diff --git a/src/event/ngx_event_accept.c b/src/event/ngx_event_accept.c index 1c87a34..4445adc 100644 --- a/src/event/ngx_event_accept.c +++ b/src/event/ngx_event_accept.c @@ -28,10 +28,10 @@ ngx_event_accept(ngx_event_t *ev) ngx_uint_t level; ngx_socket_t s; ngx_event_t *rev, *wev; + ngx_sockaddr_t sa; ngx_listening_t *ls; ngx_connection_t *c, *lc; ngx_event_conf_t *ecf; - u_char sa[NGX_SOCKADDRLEN]; #if (NGX_HAVE_ACCEPT4) static ngx_uint_t use_accept4 = 1; #endif @@ -58,17 +58,16 @@ ngx_event_accept(ngx_event_t *ev) "accept on %V, ready: %d", &ls->addr_text, ev->available); do { - socklen = NGX_SOCKADDRLEN; + socklen = sizeof(ngx_sockaddr_t); #if (NGX_HAVE_ACCEPT4) if (use_accept4) { - s = accept4(lc->fd, (struct sockaddr *) sa, &socklen, - SOCK_NONBLOCK); + s = accept4(lc->fd, &sa.sockaddr, &socklen, SOCK_NONBLOCK); } else { - s = accept(lc->fd, (struct sockaddr *) sa, &socklen); + s = accept(lc->fd, &sa.sockaddr, &socklen); } #else - s = accept(lc->fd, (struct sockaddr *) sa, &socklen); + s = accept(lc->fd, &sa.sockaddr, &socklen); #endif if (s == (ngx_socket_t) -1) { @@ -171,7 +170,7 @@ ngx_event_accept(ngx_event_t *ev) return; } - ngx_memcpy(c->sockaddr, sa, socklen); + ngx_memcpy(c->sockaddr, &sa, socklen); log = ngx_palloc(c->pool, sizeof(ngx_log_t)); if (log == NULL) { @@ -217,8 +216,6 @@ ngx_event_accept(ngx_event_t *ev) c->local_sockaddr = ls->sockaddr; c->local_socklen = ls->socklen; - c->unexpected_eof = 1; - #if (NGX_HAVE_UNIX_DOMAIN) if (c->sockaddr->sa_family == AF_UNIX) { c->tcp_nopush = NGX_TCP_NOPUSH_DISABLED; @@ -330,10 +327,10 @@ ngx_event_recvmsg(ngx_event_t *ev) ngx_event_t *rev, *wev; struct iovec iov[1]; struct msghdr msg; + ngx_sockaddr_t sa; ngx_listening_t *ls; ngx_event_conf_t *ecf; ngx_connection_t *c, *lc; - u_char sa[NGX_SOCKADDRLEN]; static u_char buffer[65535]; #if (NGX_HAVE_MSGHDR_MSG_CONTROL) @@ -378,7 +375,7 @@ ngx_event_recvmsg(ngx_event_t *ev) iov[0].iov_len = sizeof(buffer); msg.msg_name = &sa; - msg.msg_namelen = sizeof(sa); + msg.msg_namelen = sizeof(ngx_sockaddr_t); msg.msg_iov = iov; msg.msg_iovlen = 1; diff --git a/src/event/ngx_event_connect.c b/src/event/ngx_event_connect.c index 8aca862..30cb59a 100644 --- a/src/event/ngx_event_connect.c +++ b/src/event/ngx_event_connect.c @@ -11,10 +11,19 @@ #include +#if (NGX_HAVE_TRANSPARENT_PROXY) +static ngx_int_t ngx_event_connect_set_transparent(ngx_peer_connection_t *pc, + ngx_socket_t s); +#endif + + ngx_int_t ngx_event_connect_peer(ngx_peer_connection_t *pc) { int rc, type; +#if (NGX_HAVE_IP_BIND_ADDRESS_NO_PORT || NGX_LINUX) + in_port_t port; +#endif ngx_int_t event; ngx_err_t err; ngx_uint_t level; @@ -72,6 +81,62 @@ ngx_event_connect_peer(ngx_peer_connection_t *pc) } if (pc->local) { + +#if (NGX_HAVE_TRANSPARENT_PROXY) + if (pc->transparent) { + if (ngx_event_connect_set_transparent(pc, s) != NGX_OK) { + goto failed; + } + } +#endif + +#if (NGX_HAVE_IP_BIND_ADDRESS_NO_PORT || NGX_LINUX) + port = ngx_inet_get_port(pc->sockaddr); +#endif + +#if (NGX_HAVE_IP_BIND_ADDRESS_NO_PORT) + + if (pc->sockaddr->sa_family != AF_UNIX && port == 0) { + static int bind_address_no_port = 1; + + if (bind_address_no_port) { + if (setsockopt(s, IPPROTO_IP, IP_BIND_ADDRESS_NO_PORT, + (const void *) &bind_address_no_port, + sizeof(int)) == -1) + { + err = ngx_socket_errno; + + if (err != NGX_EOPNOTSUPP && err != NGX_ENOPROTOOPT) { + ngx_log_error(NGX_LOG_ALERT, pc->log, err, + "setsockopt(IP_BIND_ADDRESS_NO_PORT) " + "failed, ignored"); + + } else { + bind_address_no_port = 0; + } + } + } + } + +#endif + +#if (NGX_LINUX) + + if (pc->type == SOCK_DGRAM && port != 0) { + int reuse_addr = 1; + + if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, + (const void *) &reuse_addr, sizeof(int)) + == -1) + { + ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno, + "setsockopt(SO_REUSEADDR) failed"); + goto failed; + } + } + +#endif + if (bind(s, pc->local->sockaddr, pc->local->socklen) == -1) { ngx_log_error(NGX_LOG_CRIT, pc->log, ngx_socket_errno, "bind(%V) failed", &pc->local->name); @@ -249,6 +314,94 @@ failed: } +#if (NGX_HAVE_TRANSPARENT_PROXY) + +static ngx_int_t +ngx_event_connect_set_transparent(ngx_peer_connection_t *pc, ngx_socket_t s) +{ + int value; + + value = 1; + +#if defined(SO_BINDANY) + + if (setsockopt(s, SOL_SOCKET, SO_BINDANY, + (const void *) &value, sizeof(int)) == -1) + { + ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno, + "setsockopt(SO_BINDANY) failed"); + return NGX_ERROR; + } + +#else + + switch (pc->local->sockaddr->sa_family) { + + case AF_INET: + +#if defined(IP_TRANSPARENT) + + if (setsockopt(s, IPPROTO_IP, IP_TRANSPARENT, + (const void *) &value, sizeof(int)) == -1) + { + ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno, + "setsockopt(IP_TRANSPARENT) failed"); + return NGX_ERROR; + } + +#elif defined(IP_BINDANY) + + if (setsockopt(s, IPPROTO_IP, IP_BINDANY, + (const void *) &value, sizeof(int)) == -1) + { + ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno, + "setsockopt(IP_BINDANY) failed"); + return NGX_ERROR; + } + +#endif + + break; + +#if (NGX_HAVE_INET6) + + case AF_INET6: + +#if defined(IPV6_TRANSPARENT) + + if (setsockopt(s, IPPROTO_IPV6, IPV6_TRANSPARENT, + (const void *) &value, sizeof(int)) == -1) + { + ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno, + "setsockopt(IPV6_TRANSPARENT) failed"); + return NGX_ERROR; + } + +#elif defined(IPV6_BINDANY) + + if (setsockopt(s, IPPROTO_IPV6, IPV6_BINDANY, + (const void *) &value, sizeof(int)) == -1) + { + ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno, + "setsockopt(IPV6_BINDANY) failed"); + return NGX_ERROR; + } + +#endif + break; + +#endif /* NGX_HAVE_INET6 */ + + } + +#endif /* SO_BINDANY */ + + return NGX_OK; +} + +#endif + + ngx_int_t ngx_event_get_peer(ngx_peer_connection_t *pc, void *data) { diff --git a/src/event/ngx_event_connect.h b/src/event/ngx_event_connect.h index 1bacf82..10b72a1 100644 --- a/src/event/ngx_event_connect.h +++ b/src/event/ngx_event_connect.h @@ -61,6 +61,9 @@ struct ngx_peer_connection_s { ngx_log_t *log; unsigned cached:1; +#if (NGX_HAVE_TRANSPARENT_PROXY) + unsigned transparent:1; +#endif /* ngx_connection_log_error_e */ unsigned log_error:2; diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c index de10296..bb9a900 100644 --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -105,6 +105,7 @@ int ngx_ssl_server_conf_index; int ngx_ssl_session_cache_index; int ngx_ssl_session_ticket_keys_index; int ngx_ssl_certificate_index; +int ngx_ssl_next_certificate_index; int ngx_ssl_stapling_index; @@ -187,11 +188,17 @@ ngx_ssl_init(ngx_log_t *log) return NGX_ERROR; } - ngx_ssl_stapling_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, - NULL); + ngx_ssl_next_certificate_index = X509_get_ex_new_index(0, NULL, NULL, NULL, + NULL); + if (ngx_ssl_next_certificate_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) { - ngx_ssl_error(NGX_LOG_ALERT, log, 0, - "SSL_CTX_get_ex_new_index() failed"); + ngx_ssl_error(NGX_LOG_ALERT, log, 0, "X509_get_ex_new_index() failed"); return NGX_ERROR; } @@ -215,6 +222,12 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data) return NGX_ERROR; } + if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_certificate_index, NULL) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "SSL_CTX_set_ex_data() failed"); + return NGX_ERROR; + } + ssl->buffer_size = NGX_SSL_BUFSIZE; /* client side options */ @@ -308,6 +321,29 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data) } +ngx_int_t +ngx_ssl_certificates(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *certs, + ngx_array_t *keys, ngx_array_t *passwords) +{ + ngx_str_t *cert, *key; + ngx_uint_t i; + + cert = certs->elts; + key = keys->elts; + + for (i = 0; i < certs->nelts; i++) { + + if (ngx_ssl_certificate(cf, ssl, &cert[i], &key[i], passwords) + != NGX_OK) + { + return NGX_ERROR; + } + } + + return NGX_OK; +} + + ngx_int_t ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert, ngx_str_t *key, ngx_array_t *passwords) @@ -351,6 +387,16 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert, 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) + { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_set_ex_data() failed"); + X509_free(x509); + BIO_free(bio); + return NGX_ERROR; + } + if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_certificate_index, x509) == 0) { @@ -361,8 +407,6 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert, return NGX_ERROR; } - X509_free(x509); - /* read rest of the chain */ for ( ;; ) { @@ -387,6 +431,24 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert, return NGX_ERROR; } +#ifdef SSL_CTRL_CHAIN_CERT + + /* + * SSL_CTX_add0_chain_cert() is needed to add chain to + * a particular certificate when multiple certificates are used; + * only available in OpenSSL 1.0.2+ + */ + + if (SSL_CTX_add0_chain_cert(ssl->ctx, x509) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "SSL_CTX_add0_chain_cert(\"%s\") failed", + cert->data); + X509_free(x509); + BIO_free(bio); + return NGX_ERROR; + } + +#else if (SSL_CTX_add_extra_chain_cert(ssl->ctx, x509) == 0) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "SSL_CTX_add_extra_chain_cert(\"%s\") failed", @@ -395,6 +457,7 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert, BIO_free(bio); return NGX_ERROR; } +#endif } BIO_free(bio); @@ -528,6 +591,30 @@ ngx_ssl_password_callback(char *buf, int size, int rwflag, void *userdata) } +ngx_int_t +ngx_ssl_ciphers(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *ciphers, + ngx_uint_t prefer_server_ciphers) +{ + if (SSL_CTX_set_cipher_list(ssl->ctx, (char *) ciphers->data) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "SSL_CTX_set_cipher_list(\"%V\") failed", + ciphers); + return NGX_ERROR; + } + + if (prefer_server_ciphers) { + SSL_CTX_set_options(ssl->ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); + } + +#if (OPENSSL_VERSION_NUMBER < 0x10100001L && !defined LIBRESSL_VERSION_NUMBER) + /* a temporary 512-bit RSA key is required for export versions of MSIE */ + SSL_CTX_set_tmp_rsa_callback(ssl->ctx, ngx_ssl_rsa512_key_callback); +#endif + + return NGX_OK; +} + + ngx_int_t ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert, ngx_int_t depth) @@ -918,52 +1005,7 @@ ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file) DH *dh; BIO *bio; - /* - * -----BEGIN DH PARAMETERS----- - * MIGHAoGBALu8LcrYRnSQfEP89YDpz9vZWKP1aLQtSwju1OsPs1BMbAMCducQgAxc - * y7qokiYUxb7spWWl/fHSh6K8BJvmd4Bg6RqSp1fjBI9osHb302zI8pul34HcLKcl - * 7OZicMyaUDXYzs7vnqAnSmOrHlj6/UmI0PZdFGdX2gcd8EXP4WubAgEC - * -----END DH PARAMETERS----- - */ - - static unsigned char dh1024_p[] = { - 0xBB, 0xBC, 0x2D, 0xCA, 0xD8, 0x46, 0x74, 0x90, 0x7C, 0x43, 0xFC, 0xF5, - 0x80, 0xE9, 0xCF, 0xDB, 0xD9, 0x58, 0xA3, 0xF5, 0x68, 0xB4, 0x2D, 0x4B, - 0x08, 0xEE, 0xD4, 0xEB, 0x0F, 0xB3, 0x50, 0x4C, 0x6C, 0x03, 0x02, 0x76, - 0xE7, 0x10, 0x80, 0x0C, 0x5C, 0xCB, 0xBA, 0xA8, 0x92, 0x26, 0x14, 0xC5, - 0xBE, 0xEC, 0xA5, 0x65, 0xA5, 0xFD, 0xF1, 0xD2, 0x87, 0xA2, 0xBC, 0x04, - 0x9B, 0xE6, 0x77, 0x80, 0x60, 0xE9, 0x1A, 0x92, 0xA7, 0x57, 0xE3, 0x04, - 0x8F, 0x68, 0xB0, 0x76, 0xF7, 0xD3, 0x6C, 0xC8, 0xF2, 0x9B, 0xA5, 0xDF, - 0x81, 0xDC, 0x2C, 0xA7, 0x25, 0xEC, 0xE6, 0x62, 0x70, 0xCC, 0x9A, 0x50, - 0x35, 0xD8, 0xCE, 0xCE, 0xEF, 0x9E, 0xA0, 0x27, 0x4A, 0x63, 0xAB, 0x1E, - 0x58, 0xFA, 0xFD, 0x49, 0x88, 0xD0, 0xF6, 0x5D, 0x14, 0x67, 0x57, 0xDA, - 0x07, 0x1D, 0xF0, 0x45, 0xCF, 0xE1, 0x6B, 0x9B - }; - - static unsigned char dh1024_g[] = { 0x02 }; - - if (file->len == 0) { - - dh = DH_new(); - if (dh == NULL) { - ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "DH_new() failed"); - return NGX_ERROR; - } - - dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL); - dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL); - - if (dh->p == NULL || dh->g == NULL) { - ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "BN_bin2bn() failed"); - DH_free(dh); - return NGX_ERROR; - } - - SSL_CTX_set_tmp_dh(ssl->ctx, dh); - - DH_free(dh); - return NGX_OK; } @@ -1000,27 +1042,69 @@ ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name) { #if OPENSSL_VERSION_NUMBER >= 0x0090800fL #ifndef OPENSSL_NO_ECDH - int nid; - EC_KEY *ecdh; /* * Elliptic-Curve Diffie-Hellman parameters are either "named curves" * from RFC 4492 section 5.1.1, or explicitly described curves over - * binary fields. OpenSSL only supports the "named curves", which provide + * binary fields. OpenSSL only supports the "named curves", which provide * maximum interoperability. */ - nid = OBJ_sn2nid((const char *) name->data); +#ifdef SSL_CTRL_SET_CURVES_LIST + + /* + * OpenSSL 1.0.2+ allows configuring a curve list instead of a single + * curve previously supported. By default an internal list is used, + * with prime256v1 being preferred by server in OpenSSL 1.0.2b+ + * and X25519 in OpenSSL 1.1.0+. + * + * By default a curve preferred by the client will be used for + * key exchange. The SSL_OP_CIPHER_SERVER_PREFERENCE option can + * be used to prefer server curves instead, similar to what it + * does for ciphers. + */ + + SSL_CTX_set_options(ssl->ctx, SSL_OP_SINGLE_ECDH_USE); + +#if SSL_CTRL_SET_ECDH_AUTO + /* not needed in OpenSSL 1.1.0+ */ + SSL_CTX_set_ecdh_auto(ssl->ctx, 1); +#endif + + if (ngx_strcmp(name->data, "auto") == 0) { + return NGX_OK; + } + + if (SSL_CTX_set1_curves_list(ssl->ctx, (char *) name->data) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "SSL_CTX_set1_curves_list(\"%s\") failed", name->data); + return NGX_ERROR; + } + +#else + + int nid; + char *curve; + EC_KEY *ecdh; + + if (ngx_strcmp(name->data, "auto") == 0) { + curve = "prime256v1"; + + } else { + curve = (char *) name->data; + } + + nid = OBJ_sn2nid(curve); if (nid == 0) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, - "Unknown curve name \"%s\"", name->data); + "OBJ_sn2nid(\"%s\") failed: unknown curve", curve); return NGX_ERROR; } ecdh = EC_KEY_new_by_curve_name(nid); if (ecdh == NULL) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, - "Unable to create curve \"%s\"", name->data); + "EC_KEY_new_by_curve_name(\"%s\") failed", curve); return NGX_ERROR; } @@ -1030,6 +1114,7 @@ ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name) EC_KEY_free(ecdh); #endif +#endif #endif return NGX_OK; @@ -2102,7 +2187,7 @@ ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx, * session reuse (see SSL_SESS_CACHE_OFF above), then * Outlook Express fails to upload a sent email to * the Sent Items folder on the IMAP server via a separate IMAP - * connection in the background. Therefore we have a special + * connection in the background. Therefore we have a special * mode (SSL_SESS_CACHE_SERVER|SSL_SESS_CACHE_NO_INTERNAL_STORE) * where the server pretends that it supports session reuse, * but it does not actually store any session. @@ -2164,7 +2249,7 @@ ngx_ssl_session_id_context(ngx_ssl_t *ssl, ngx_str_t *sess_ctx) /* * Session ID context is set based on the string provided, - * the server certificate, and the client CA list. + * the server certificates, and the client CA list. */ md = EVP_MD_CTX_create(); @@ -2184,18 +2269,21 @@ ngx_ssl_session_id_context(ngx_ssl_t *ssl, ngx_str_t *sess_ctx) goto failed; } - cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); + for (cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); + cert; + cert = X509_get_ex_data(cert, ngx_ssl_next_certificate_index)) + { + if (X509_digest(cert, EVP_sha1(), buf, &len) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "X509_digest() failed"); + goto failed; + } - if (X509_digest(cert, EVP_sha1(), buf, &len) == 0) { - ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, - "X509_digest() failed"); - goto failed; - } - - if (EVP_DigestUpdate(md, buf, len) == 0) { - ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, - "EVP_DigestUpdate() failed"); - goto failed; + if (EVP_DigestUpdate(md, buf, len) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "EVP_DigestUpdate() failed"); + goto failed; + } } list = SSL_CTX_get_client_CA_list(ssl->ctx); @@ -2951,6 +3039,16 @@ ngx_ssl_cleanup_ctx(void *data) { ngx_ssl_t *ssl = data; + X509 *cert, *next; + + cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); + + while (cert) { + next = X509_get_ex_data(cert, ngx_ssl_next_certificate_index); + X509_free(cert); + cert = next; + } + SSL_CTX_free(ssl->ctx); } @@ -3526,7 +3624,7 @@ ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) value = cf->args->elts; - engine = ENGINE_by_id((const char *) value[1].data); + engine = ENGINE_by_id((char *) value[1].data); if (engine == NULL) { ngx_ssl_error(NGX_LOG_WARN, cf->log, 0, diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h index 09654db..3367d10 100644 --- a/src/event/ngx_event_openssl.h +++ b/src/event/ngx_event_openssl.h @@ -140,8 +140,12 @@ typedef struct { ngx_int_t ngx_ssl_init(ngx_log_t *log); ngx_int_t ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data); +ngx_int_t ngx_ssl_certificates(ngx_conf_t *cf, ngx_ssl_t *ssl, + ngx_array_t *certs, ngx_array_t *keys, ngx_array_t *passwords); ngx_int_t ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert, ngx_str_t *key, ngx_array_t *passwords); +ngx_int_t ngx_ssl_ciphers(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *ciphers, + ngx_uint_t prefer_server_ciphers); ngx_int_t ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert, ngx_int_t depth); ngx_int_t ngx_ssl_trusted_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, @@ -227,6 +231,7 @@ extern int ngx_ssl_server_conf_index; extern int ngx_ssl_session_cache_index; 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_stapling_index; diff --git a/src/event/ngx_event_openssl_stapling.c b/src/event/ngx_event_openssl_stapling.c index 5322b1b..cce8e9e 100644 --- a/src/event/ngx_event_openssl_stapling.c +++ b/src/event/ngx_event_openssl_stapling.c @@ -83,11 +83,14 @@ struct ngx_ssl_ocsp_ctx_s { }; +static ngx_int_t ngx_ssl_stapling_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, + X509 *cert, ngx_str_t *file, ngx_str_t *responder, ngx_uint_t verify); static ngx_int_t ngx_ssl_stapling_file(ngx_conf_t *cf, ngx_ssl_t *ssl, - ngx_str_t *file); -static ngx_int_t ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl); + ngx_ssl_stapling_t *staple, ngx_str_t *file); +static ngx_int_t ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl, + ngx_ssl_stapling_t *staple); static ngx_int_t ngx_ssl_stapling_responder(ngx_conf_t *cf, ngx_ssl_t *ssl, - ngx_str_t *responder); + ngx_ssl_stapling_t *staple, ngx_str_t *responder); static int ngx_ssl_certificate_status_callback(ngx_ssl_conn_t *ssl_conn, void *data); @@ -121,9 +124,32 @@ ngx_int_t ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file, ngx_str_t *responder, ngx_uint_t verify) { - ngx_int_t rc; - ngx_pool_cleanup_t *cln; - ngx_ssl_stapling_t *staple; + X509 *cert; + + for (cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); + cert; + cert = X509_get_ex_data(cert, ngx_ssl_next_certificate_index)) + { + if (ngx_ssl_stapling_certificate(cf, ssl, cert, file, responder, verify) + != NGX_OK) + { + return NGX_ERROR; + } + } + + SSL_CTX_set_tlsext_status_cb(ssl->ctx, ngx_ssl_certificate_status_callback); + + return NGX_OK; +} + + +static ngx_int_t +ngx_ssl_stapling_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, X509 *cert, + ngx_str_t *file, ngx_str_t *responder, ngx_uint_t verify) +{ + ngx_int_t rc; + ngx_pool_cleanup_t *cln; + ngx_ssl_stapling_t *staple; staple = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_stapling_t)); if (staple == NULL) { @@ -138,29 +164,27 @@ ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file, cln->handler = ngx_ssl_stapling_cleanup; cln->data = staple; - if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_stapling_index, staple) - == 0) - { - ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, - "SSL_CTX_set_ex_data() failed"); + if (X509_set_ex_data(cert, ngx_ssl_stapling_index, staple) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_set_ex_data() failed"); return NGX_ERROR; } staple->ssl_ctx = ssl->ctx; staple->timeout = 60000; staple->verify = verify; + staple->cert = cert; if (file->len) { /* use OCSP response from the file */ - if (ngx_ssl_stapling_file(cf, ssl, file) != NGX_OK) { + if (ngx_ssl_stapling_file(cf, ssl, staple, file) != NGX_OK) { return NGX_ERROR; } - goto done; + return NGX_OK; } - rc = ngx_ssl_stapling_issuer(cf, ssl); + rc = ngx_ssl_stapling_issuer(cf, ssl, staple); if (rc == NGX_DECLINED) { return NGX_OK; @@ -170,7 +194,7 @@ ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file, return NGX_ERROR; } - rc = ngx_ssl_stapling_responder(cf, ssl, responder); + rc = ngx_ssl_stapling_responder(cf, ssl, staple, responder); if (rc == NGX_DECLINED) { return NGX_OK; @@ -180,25 +204,18 @@ ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file, return NGX_ERROR; } -done: - - SSL_CTX_set_tlsext_status_cb(ssl->ctx, ngx_ssl_certificate_status_callback); - SSL_CTX_set_tlsext_status_arg(ssl->ctx, staple); - return NGX_OK; } static ngx_int_t -ngx_ssl_stapling_file(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file) +ngx_ssl_stapling_file(ngx_conf_t *cf, ngx_ssl_t *ssl, + ngx_ssl_stapling_t *staple, ngx_str_t *file) { - BIO *bio; - int len; - u_char *p, *buf; - OCSP_RESPONSE *response; - ngx_ssl_stapling_t *staple; - - staple = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_stapling_index); + BIO *bio; + int len; + u_char *p, *buf; + OCSP_RESPONSE *response; if (ngx_conf_full_name(cf->cycle, file, 1) != NGX_OK) { return NGX_ERROR; @@ -259,19 +276,24 @@ failed: static ngx_int_t -ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl) +ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl, + ngx_ssl_stapling_t *staple) { - int i, n, rc; - X509 *cert, *issuer; - X509_STORE *store; - X509_STORE_CTX *store_ctx; - STACK_OF(X509) *chain; - ngx_ssl_stapling_t *staple; + int i, n, rc; + X509 *cert, *issuer; + X509_STORE *store; + X509_STORE_CTX *store_ctx; + STACK_OF(X509) *chain; - staple = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_stapling_index); - cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); + cert = staple->cert; -#if OPENSSL_VERSION_NUMBER >= 0x10001000L +#ifdef SSL_CTRL_SELECT_CURRENT_CERT + /* OpenSSL 1.0.2+ */ + SSL_CTX_select_current_cert(ssl->ctx, cert); +#endif + +#ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS + /* OpenSSL 1.0.1+ */ SSL_CTX_get_extra_chain_certs(ssl->ctx, &chain); #else chain = ssl->ctx->extra_certs; @@ -294,7 +316,6 @@ ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl) ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0, "SSL get issuer: found %p in extra certs", issuer); - staple->cert = cert; staple->issuer = issuer; return NGX_OK; @@ -343,7 +364,6 @@ ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl) ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0, "SSL get issuer: found %p in cert store", issuer); - staple->cert = cert; staple->issuer = issuer; return NGX_OK; @@ -351,15 +371,13 @@ ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl) static ngx_int_t -ngx_ssl_stapling_responder(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *responder) +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_ssl_stapling_t *staple; STACK_OF(OPENSSL_STRING) *aia; - staple = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_stapling_index); - if (responder->len == 0) { /* extract OCSP responder URL from certificate */ @@ -443,12 +461,17 @@ ngx_int_t ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_resolver_t *resolver, ngx_msec_t resolver_timeout) { + X509 *cert; ngx_ssl_stapling_t *staple; - staple = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_stapling_index); - - staple->resolver = resolver; - staple->resolver_timeout = resolver_timeout; + for (cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); + cert; + cert = X509_get_ex_data(cert, ngx_ssl_next_certificate_index)) + { + staple = X509_get_ex_data(cert, ngx_ssl_stapling_index); + staple->resolver = resolver; + staple->resolver_timeout = resolver_timeout; + } return NGX_OK; } @@ -458,6 +481,7 @@ static int ngx_ssl_certificate_status_callback(ngx_ssl_conn_t *ssl_conn, void *data) { int rc; + X509 *cert; u_char *p; ngx_connection_t *c; ngx_ssl_stapling_t *staple; @@ -467,9 +491,15 @@ ngx_ssl_certificate_status_callback(ngx_ssl_conn_t *ssl_conn, void *data) ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL certificate status callback"); - staple = data; rc = SSL_TLSEXT_ERR_NOACK; + cert = SSL_get_certificate(ssl_conn); + staple = X509_get_ex_data(cert, ngx_ssl_stapling_index); + + if (staple == NULL) { + return rc; + } + if (staple->staple.len && staple->valid >= ngx_time()) { @@ -597,7 +627,13 @@ ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx) goto error; } -#if OPENSSL_VERSION_NUMBER >= 0x10001000L +#ifdef SSL_CTRL_SELECT_CURRENT_CERT + /* OpenSSL 1.0.2+ */ + SSL_CTX_select_current_cert(staple->ssl_ctx, ctx->cert); +#endif + +#ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS + /* OpenSSL 1.0.1+ */ SSL_CTX_get_extra_chain_certs(staple->ssl_ctx, &chain); #else chain = staple->ssl_ctx->extra_certs; @@ -884,7 +920,6 @@ ngx_ssl_ocsp_resolve_handler(ngx_resolver_ctx_t *resolve) u_char *p; size_t len; - in_port_t port; socklen_t socklen; ngx_uint_t i; struct sockaddr *sockaddr; @@ -926,8 +961,6 @@ ngx_ssl_ocsp_resolve_handler(ngx_resolver_ctx_t *resolve) goto failed; } - port = htons(ctx->port); - for (i = 0; i < resolve->naddrs; i++) { socklen = resolve->addrs[i].socklen; @@ -938,16 +971,7 @@ ngx_ssl_ocsp_resolve_handler(ngx_resolver_ctx_t *resolve) } ngx_memcpy(sockaddr, resolve->addrs[i].sockaddr, socklen); - - switch (sockaddr->sa_family) { -#if (NGX_HAVE_INET6) - case AF_INET6: - ((struct sockaddr_in6 *) sockaddr)->sin6_port = port; - break; -#endif - default: /* AF_INET */ - ((struct sockaddr_in *) sockaddr)->sin_port = port; - } + ngx_inet_set_port(sockaddr, ctx->port); ctx->addrs[i].sockaddr = sockaddr; ctx->addrs[i].socklen = socklen; diff --git a/src/http/modules/ngx_http_dav_module.c b/src/http/modules/ngx_http_dav_module.c index 3600265..012a0fb 100644 --- a/src/http/modules/ngx_http_dav_module.c +++ b/src/http/modules/ngx_http_dav_module.c @@ -161,6 +161,12 @@ ngx_http_dav_handler(ngx_http_request_t *r) return NGX_HTTP_CONFLICT; } + if (r->headers_in.content_range) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "PUT with range is unsupported"); + return NGX_HTTP_NOT_IMPLEMENTED; + } + r->request_body_in_file_only = 1; r->request_body_in_persistent_file = 1; r->request_body_in_clean_file = 1; diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c index 2d288ce..62502b0 100644 --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -279,7 +279,7 @@ static ngx_command_t ngx_http_fastcgi_commands[] = { NULL }, { ngx_string("fastcgi_bind"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12, ngx_http_upstream_bind_set_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_fastcgi_loc_conf_t, upstream.local), diff --git a/src/http/modules/ngx_http_log_module.c b/src/http/modules/ngx_http_log_module.c index df9424f..c42fb08 100644 --- a/src/http/modules/ngx_http_log_module.c +++ b/src/http/modules/ngx_http_log_module.c @@ -1000,7 +1000,7 @@ ngx_http_log_escape(u_char *dst, u_char *src, size_t size) n = 0; while (size) { - if (escape[*src >> 5] & (1 << (*src & 0x1f))) { + if (escape[*src >> 5] & (1U << (*src & 0x1f))) { n++; } src++; @@ -1011,7 +1011,7 @@ ngx_http_log_escape(u_char *dst, u_char *src, size_t size) } while (size) { - if (escape[*src >> 5] & (1 << (*src & 0x1f))) { + if (escape[*src >> 5] & (1U << (*src & 0x1f))) { *dst++ = '\\'; *dst++ = 'x'; *dst++ = hex[*src >> 4]; diff --git a/src/http/modules/ngx_http_map_module.c b/src/http/modules/ngx_http_map_module.c index 091ff09..732aa5d 100644 --- a/src/http/modules/ngx_http_map_module.c +++ b/src/http/modules/ngx_http_map_module.c @@ -20,7 +20,6 @@ typedef struct { ngx_hash_keys_arrays_t keys; ngx_array_t *values_hash; - ngx_array_t var_values; #if (NGX_PCRE) ngx_array_t regexes; #endif @@ -110,7 +109,8 @@ 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; - ngx_str_t val; + ngx_str_t val, str; + ngx_http_complex_value_t *cv; ngx_http_variable_value_t *value; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, @@ -131,14 +131,21 @@ ngx_http_map_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, } if (!value->valid) { - value = ngx_http_get_flushed_variable(r, (uintptr_t) value->data); + cv = (ngx_http_complex_value_t *) value->data; - if (value == NULL || value->not_found) { - value = &ngx_http_variable_null_value; + if (ngx_http_complex_value(r, cv, &str) != NGX_OK) { + return NGX_ERROR; } - } - *v = *value; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->len = str.len; + v->data = str.data; + + } else { + *v = *value; + } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http map: \"%V\" \"%v\"", &val, v); @@ -246,14 +253,6 @@ ngx_http_map_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_ERROR; } - if (ngx_array_init(&ctx.var_values, cf->pool, 2, - sizeof(ngx_http_variable_value_t)) - != NGX_OK) - { - ngx_destroy_pool(pool); - return NGX_CONF_ERROR; - } - #if (NGX_PCRE) if (ngx_array_init(&ctx.regexes, cf->pool, 2, sizeof(ngx_http_map_regex_t)) != NGX_OK) @@ -375,11 +374,15 @@ ngx_http_map_cmp_dns_wildcards(const void *one, const void *two) static char * ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) { - ngx_int_t rv, index; - ngx_str_t *value, name; - ngx_uint_t i, key; - ngx_http_map_conf_ctx_t *ctx; - ngx_http_variable_value_t *var, **vp; + u_char *data; + size_t len; + ngx_int_t rv; + ngx_str_t *value, v; + ngx_uint_t i, key; + ngx_http_map_conf_ctx_t *ctx; + ngx_http_complex_value_t cv, *cvp; + ngx_http_variable_value_t *var, **vp; + ngx_http_compile_complex_value_t ccv; ctx = cf->ctx; @@ -401,39 +404,6 @@ ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) return ngx_conf_include(cf, dummy, conf); } - if (value[1].data[0] == '$') { - name = value[1]; - name.len--; - name.data++; - - index = ngx_http_get_variable_index(ctx->cf, &name); - if (index == NGX_ERROR) { - return NGX_CONF_ERROR; - } - - var = ctx->var_values.elts; - - for (i = 0; i < ctx->var_values.nelts; i++) { - if (index == (intptr_t) var[i].data) { - var = &var[i]; - goto found; - } - } - - var = ngx_array_push(&ctx->var_values); - if (var == NULL) { - return NGX_CONF_ERROR; - } - - var->valid = 0; - var->no_cacheable = 0; - var->not_found = 0; - var->len = 0; - var->data = (u_char *) (intptr_t) index; - - goto found; - } - key = 0; for (i = 0; i < value[1].len; i++) { @@ -446,11 +416,22 @@ ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) if (vp) { for (i = 0; i < ctx->values_hash[key].nelts; i++) { - if (value[1].len != (size_t) vp[i]->len) { + + if (vp[i]->valid) { + data = vp[i]->data; + len = vp[i]->len; + + } else { + cvp = (ngx_http_complex_value_t *) vp[i]->data; + data = cvp->value.data; + len = cvp->value.len; + } + + if (value[1].len != len) { continue; } - if (ngx_strncmp(value[1].data, vp[i]->data, value[1].len) == 0) { + if (ngx_strncmp(value[1].data, data, len) == 0) { var = vp[i]; goto found; } @@ -470,13 +451,40 @@ ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) return NGX_CONF_ERROR; } - var->len = value[1].len; - var->data = ngx_pstrdup(ctx->keys.pool, &value[1]); - if (var->data == NULL) { + v.len = value[1].len; + v.data = ngx_pstrdup(ctx->keys.pool, &value[1]); + if (v.data == NULL) { return NGX_CONF_ERROR; } - var->valid = 1; + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + + ccv.cf = ctx->cf; + ccv.value = &v; + ccv.complex_value = &cv; + + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + + if (cv.lengths != NULL) { + cvp = ngx_palloc(ctx->keys.pool, sizeof(ngx_http_complex_value_t)); + if (cvp == NULL) { + return NGX_CONF_ERROR; + } + + *cvp = cv; + + var->len = 0; + var->data = (u_char *) cvp; + var->valid = 0; + + } else { + var->len = v.len; + var->data = v.data; + var->valid = 1; + } + var->no_cacheable = 0; var->not_found = 0; diff --git a/src/http/modules/ngx_http_memcached_module.c b/src/http/modules/ngx_http_memcached_module.c index d31996a..69f28fa 100644 --- a/src/http/modules/ngx_http_memcached_module.c +++ b/src/http/modules/ngx_http_memcached_module.c @@ -61,7 +61,7 @@ static ngx_command_t ngx_http_memcached_commands[] = { NULL }, { ngx_string("memcached_bind"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12, ngx_http_upstream_bind_set_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_memcached_loc_conf_t, upstream.local), diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c index c24ef17..4f49a52 100644 --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -316,7 +316,7 @@ static ngx_command_t ngx_http_proxy_commands[] = { NULL }, { ngx_string("proxy_bind"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12, ngx_http_upstream_bind_set_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_proxy_loc_conf_t, upstream.local), @@ -4323,13 +4323,9 @@ ngx_http_proxy_set_ssl(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *plcf) } } - if (SSL_CTX_set_cipher_list(plcf->upstream.ssl->ctx, - (const char *) plcf->ssl_ciphers.data) - == 0) + if (ngx_ssl_ciphers(cf, plcf->upstream.ssl, &plcf->ssl_ciphers, 0) + != NGX_OK) { - ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, - "SSL_CTX_set_cipher_list(\"%V\") failed", - &plcf->ssl_ciphers); return NGX_ERROR; } diff --git a/src/http/modules/ngx_http_realip_module.c b/src/http/modules/ngx_http_realip_module.c index b7befe6..490a53d 100644 --- a/src/http/modules/ngx_http_realip_module.c +++ b/src/http/modules/ngx_http_realip_module.c @@ -45,10 +45,14 @@ static char *ngx_http_realip_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child); static ngx_int_t ngx_http_realip_add_variables(ngx_conf_t *cf); static ngx_int_t ngx_http_realip_init(ngx_conf_t *cf); +static ngx_http_realip_ctx_t *ngx_http_realip_get_module_ctx( + ngx_http_request_t *r); static ngx_int_t ngx_http_realip_remote_addr_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_realip_remote_port_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); static ngx_command_t ngx_http_realip_commands[] = { @@ -115,6 +119,9 @@ static ngx_http_variable_t ngx_http_realip_vars[] = { { ngx_string("realip_remote_addr"), NULL, ngx_http_realip_remote_addr_variable, 0, 0, 0 }, + { ngx_string("realip_remote_port"), NULL, + ngx_http_realip_remote_port_variable, 0, 0, 0 }, + { ngx_null_string, NULL, NULL, 0, 0, 0 } }; @@ -230,6 +237,10 @@ found: rlcf->recursive) != NGX_DECLINED) { + if (rlcf->type == NGX_HTTP_REALIP_PROXY) { + ngx_inet_set_port(addr.sockaddr, c->proxy_protocol_port); + } + return ngx_http_realip_set_addr(r, &addr); } @@ -358,6 +369,10 @@ ngx_http_realip(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ngx_str_t *value; + if (rlcf->type != NGX_CONF_UNSET_UINT) { + return "is duplicate"; + } + value = cf->args->elts; if (ngx_strcmp(value[1].data, "X-Real-IP") == 0) { @@ -475,11 +490,9 @@ ngx_http_realip_init(ngx_conf_t *cf) } -static ngx_int_t -ngx_http_realip_remote_addr_variable(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data) +static ngx_http_realip_ctx_t * +ngx_http_realip_get_module_ctx(ngx_http_request_t *r) { - ngx_str_t *addr_text; ngx_pool_cleanup_t *cln; ngx_http_realip_ctx_t *ctx; @@ -500,6 +513,19 @@ ngx_http_realip_remote_addr_variable(ngx_http_request_t *r, } } + return ctx; +} + + +static ngx_int_t +ngx_http_realip_remote_addr_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_str_t *addr_text; + ngx_http_realip_ctx_t *ctx; + + ctx = ngx_http_realip_get_module_ctx(r); + addr_text = ctx ? &ctx->addr_text : &r->connection->addr_text; v->len = addr_text->len; @@ -510,3 +536,35 @@ ngx_http_realip_remote_addr_variable(ngx_http_request_t *r, return NGX_OK; } + + +static ngx_int_t +ngx_http_realip_remote_port_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_uint_t port; + struct sockaddr *sa; + ngx_http_realip_ctx_t *ctx; + + ctx = ngx_http_realip_get_module_ctx(r); + + sa = ctx ? ctx->sockaddr : r->connection->sockaddr; + + v->len = 0; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + v->data = ngx_pnalloc(r->pool, sizeof("65535") - 1); + if (v->data == NULL) { + return NGX_ERROR; + } + + port = ngx_inet_get_port(sa); + + if (port > 0 && port < 65536) { + v->len = ngx_sprintf(v->data, "%ui", port) - v->data; + } + + return NGX_OK; +} diff --git a/src/http/modules/ngx_http_scgi_module.c b/src/http/modules/ngx_http_scgi_module.c index f09617e..36656ec 100644 --- a/src/http/modules/ngx_http_scgi_module.c +++ b/src/http/modules/ngx_http_scgi_module.c @@ -136,7 +136,7 @@ static ngx_command_t ngx_http_scgi_commands[] = { NULL }, { ngx_string("scgi_bind"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12, ngx_http_upstream_bind_set_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_scgi_loc_conf_t, upstream.local), diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c index 6a4108c..d685ae9 100644 --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -15,7 +15,7 @@ typedef ngx_int_t (*ngx_ssl_variable_handler_pt)(ngx_connection_t *c, #define NGX_DEFAULT_CIPHERS "HIGH:!aNULL:!MD5" -#define NGX_DEFAULT_ECDH_CURVE "prime256v1" +#define NGX_DEFAULT_ECDH_CURVE "auto" #define NGX_HTTP_NPN_ADVERTISE "\x08http/1.1" @@ -81,16 +81,16 @@ static ngx_command_t ngx_http_ssl_commands[] = { { ngx_string("ssl_certificate"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_conf_set_str_array_slot, NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_http_ssl_srv_conf_t, certificate), + offsetof(ngx_http_ssl_srv_conf_t, certificates), NULL }, { ngx_string("ssl_certificate_key"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_conf_set_str_array_slot, NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_http_ssl_srv_conf_t, certificate_key), + offsetof(ngx_http_ssl_srv_conf_t, certificate_keys), NULL }, { ngx_string("ssl_password_file"), @@ -508,8 +508,6 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t *cf) * set by ngx_pcalloc(): * * sscf->protocols = 0; - * sscf->certificate = { 0, NULL }; - * sscf->certificate_key = { 0, NULL }; * sscf->dhparam = { 0, NULL }; * sscf->ecdh_curve = { 0, NULL }; * sscf->client_certificate = { 0, NULL }; @@ -526,6 +524,8 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t *cf) sscf->buffer_size = NGX_CONF_UNSET_SIZE; sscf->verify = NGX_CONF_UNSET_UINT; sscf->verify_depth = NGX_CONF_UNSET_UINT; + sscf->certificates = NGX_CONF_UNSET_PTR; + sscf->certificate_keys = NGX_CONF_UNSET_PTR; sscf->passwords = NGX_CONF_UNSET_PTR; sscf->builtin_session_cache = NGX_CONF_UNSET; sscf->session_timeout = NGX_CONF_UNSET; @@ -573,8 +573,9 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_uint_value(conf->verify, prev->verify, 0); ngx_conf_merge_uint_value(conf->verify_depth, prev->verify_depth, 1); - ngx_conf_merge_str_value(conf->certificate, prev->certificate, ""); - ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key, ""); + ngx_conf_merge_ptr_value(conf->certificates, prev->certificates, NULL); + ngx_conf_merge_ptr_value(conf->certificate_keys, prev->certificate_keys, + NULL); ngx_conf_merge_ptr_value(conf->passwords, prev->passwords, NULL); @@ -601,7 +602,7 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) if (conf->enable) { - if (conf->certificate.len == 0) { + if (conf->certificates == NULL) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate\" is defined for " "the \"ssl\" directive in %s:%ui", @@ -609,7 +610,7 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) return NGX_CONF_ERROR; } - if (conf->certificate_key.len == 0) { + if (conf->certificate_keys == NULL) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate_key\" is defined for " "the \"ssl\" directive in %s:%ui", @@ -617,16 +618,31 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) return NGX_CONF_ERROR; } + if (conf->certificate_keys->nelts < conf->certificates->nelts) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "no \"ssl_certificate_key\" is defined " + "for certificate \"%V\" and " + "the \"ssl\" directive in %s:%ui", + ((ngx_str_t *) conf->certificates->elts) + + conf->certificates->nelts - 1, + conf->file, conf->line); + return NGX_CONF_ERROR; + } + } else { - if (conf->certificate.len == 0) { + if (conf->certificates == NULL) { return NGX_CONF_OK; } - if (conf->certificate_key.len == 0) { + if (conf->certificate_keys == NULL + || conf->certificate_keys->nelts < conf->certificates->nelts) + { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate_key\" is defined " - "for certificate \"%V\"", &conf->certificate); + "for certificate \"%V\"", + ((ngx_str_t *) conf->certificates->elts) + + conf->certificates->nelts - 1); return NGX_CONF_ERROR; } } @@ -666,20 +682,17 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) cln->handler = ngx_ssl_cleanup_ctx; cln->data = &conf->ssl; - if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate, - &conf->certificate_key, conf->passwords) + if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates, + conf->certificate_keys, conf->passwords) != NGX_OK) { return NGX_CONF_ERROR; } - if (SSL_CTX_set_cipher_list(conf->ssl.ctx, - (const char *) conf->ciphers.data) - == 0) + if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers, + conf->prefer_server_ciphers) + != NGX_OK) { - ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, - "SSL_CTX_set_cipher_list(\"%V\") failed", - &conf->ciphers); return NGX_CONF_ERROR; } @@ -714,15 +727,6 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) return NGX_CONF_ERROR; } - if (conf->prefer_server_ciphers) { - SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); - } - -#if (OPENSSL_VERSION_NUMBER < 0x10100001L && !defined LIBRESSL_VERSION_NUMBER) - /* a temporary 512-bit RSA key is required for export versions of MSIE */ - SSL_CTX_set_tmp_rsa_callback(conf->ssl.ctx, ngx_ssl_rsa512_key_callback); -#endif - if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) { return NGX_CONF_ERROR; } diff --git a/src/http/modules/ngx_http_ssl_module.h b/src/http/modules/ngx_http_ssl_module.h index 8e69e9e..57f5941 100644 --- a/src/http/modules/ngx_http_ssl_module.h +++ b/src/http/modules/ngx_http_ssl_module.h @@ -32,8 +32,9 @@ typedef struct { time_t session_timeout; - ngx_str_t certificate; - ngx_str_t certificate_key; + ngx_array_t *certificates; + ngx_array_t *certificate_keys; + ngx_str_t dhparam; ngx_str_t ecdh_curve; ngx_str_t client_certificate; diff --git a/src/http/modules/ngx_http_sub_filter_module.c b/src/http/modules/ngx_http_sub_filter_module.c index bb1c50b..e8d1d80 100644 --- a/src/http/modules/ngx_http_sub_filter_module.c +++ b/src/http/modules/ngx_http_sub_filter_module.c @@ -83,7 +83,9 @@ static ngx_uint_t ngx_http_sub_cmp_index; static ngx_int_t ngx_http_sub_output(ngx_http_request_t *r, ngx_http_sub_ctx_t *ctx); static ngx_int_t ngx_http_sub_parse(ngx_http_request_t *r, - ngx_http_sub_ctx_t *ctx); + ngx_http_sub_ctx_t *ctx, ngx_uint_t flush); +static ngx_int_t ngx_http_sub_match(ngx_http_sub_ctx_t *ctx, ngx_int_t start, + ngx_str_t *m); static char * ngx_http_sub_filter(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); @@ -285,6 +287,7 @@ ngx_http_sub_body_filter(ngx_http_request_t *r, ngx_chain_t *in) ngx_int_t rc; ngx_buf_t *b; ngx_str_t *sub; + ngx_uint_t flush, last; ngx_chain_t *cl; ngx_http_sub_ctx_t *ctx; ngx_http_sub_match_t *match; @@ -326,6 +329,9 @@ ngx_http_sub_body_filter(ngx_http_request_t *r, ngx_chain_t *in) ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http sub filter \"%V\"", &r->uri); + flush = 0; + last = 0; + while (ctx->in || ctx->buf) { if (ctx->buf == NULL) { @@ -334,11 +340,19 @@ ngx_http_sub_body_filter(ngx_http_request_t *r, ngx_chain_t *in) ctx->pos = ctx->buf->pos; } + if (ctx->buf->flush || ctx->buf->recycled) { + flush = 1; + } + + if (ctx->in == NULL) { + last = flush; + } + b = NULL; while (ctx->pos < ctx->buf->last) { - rc = ngx_http_sub_parse(r, ctx); + rc = ngx_http_sub_parse(r, ctx, last); ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "parse: %i, looked: \"%V\" %p-%p", @@ -590,9 +604,10 @@ ngx_http_sub_output(ngx_http_request_t *r, ngx_http_sub_ctx_t *ctx) static ngx_int_t -ngx_http_sub_parse(ngx_http_request_t *r, ngx_http_sub_ctx_t *ctx) +ngx_http_sub_parse(ngx_http_request_t *r, ngx_http_sub_ctx_t *ctx, + ngx_uint_t flush) { - u_char *p, *last, *pat, *pat_end, c; + u_char *p, c; ngx_str_t *m; ngx_int_t offset, start, next, end, len, rc; ngx_uint_t shift, i, j; @@ -602,6 +617,7 @@ ngx_http_sub_parse(ngx_http_request_t *r, ngx_http_sub_ctx_t *ctx) slcf = ngx_http_get_module_loc_conf(r, ngx_http_sub_filter_module); tables = ctx->tables; + match = ctx->matches->elts; offset = ctx->offset; end = ctx->buf->last - ctx->pos; @@ -628,7 +644,6 @@ ngx_http_sub_parse(ngx_http_request_t *r, ngx_http_sub_ctx_t *ctx) /* a potential match */ start = offset - (ngx_int_t) tables->min_match_len + 1; - match = ctx->matches->elts; i = ngx_max(tables->index[c], ctx->index); j = tables->index[c + 1]; @@ -641,41 +656,15 @@ ngx_http_sub_parse(ngx_http_request_t *r, ngx_http_sub_ctx_t *ctx) m = &match[i].match; - pat = m->data; - pat_end = m->data + m->len; + rc = ngx_http_sub_match(ctx, start, m); - if (start >= 0) { - p = ctx->pos + start; - - } else { - last = ctx->looked.data + ctx->looked.len; - p = last + start; - - while (p < last && pat < pat_end) { - if (ngx_tolower(*p) != *pat) { - goto next; - } - - p++; - pat++; - } - - p = ctx->pos; - } - - while (p < ctx->buf->last && pat < pat_end) { - if (ngx_tolower(*p) != *pat) { - goto next; - } - - p++; - pat++; + if (rc == NGX_DECLINED) { + goto next; } ctx->index = i; - if (pat != pat_end) { - /* partial match */ + if (rc == NGX_AGAIN) { goto again; } @@ -695,6 +684,26 @@ ngx_http_sub_parse(ngx_http_request_t *r, ngx_http_sub_ctx_t *ctx) ctx->index = 0; } + if (flush) { + for ( ;; ) { + start = offset - (ngx_int_t) tables->min_match_len + 1; + + if (start >= end) { + break; + } + + for (i = 0; i < ctx->matches->nelts; i++) { + m = &match[i].match; + + if (ngx_http_sub_match(ctx, start, m) == NGX_AGAIN) { + goto again; + } + } + + offset++; + } + } + again: ctx->offset = offset; @@ -731,6 +740,51 @@ done: } +static ngx_int_t +ngx_http_sub_match(ngx_http_sub_ctx_t *ctx, ngx_int_t start, ngx_str_t *m) +{ + u_char *p, *last, *pat, *pat_end; + + pat = m->data; + pat_end = m->data + m->len; + + if (start >= 0) { + p = ctx->pos + start; + + } else { + last = ctx->looked.data + ctx->looked.len; + p = last + start; + + while (p < last && pat < pat_end) { + if (ngx_tolower(*p) != *pat) { + return NGX_DECLINED; + } + + p++; + pat++; + } + + p = ctx->pos; + } + + while (p < ctx->buf->last && pat < pat_end) { + if (ngx_tolower(*p) != *pat) { + return NGX_DECLINED; + } + + p++; + pat++; + } + + if (pat != pat_end) { + /* partial match */ + return NGX_AGAIN; + } + + return NGX_OK; +} + + static char * ngx_http_sub_filter(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { diff --git a/src/http/modules/ngx_http_upstream_keepalive_module.c b/src/http/modules/ngx_http_upstream_keepalive_module.c index 85bfcdb..0048e6b 100644 --- a/src/http/modules/ngx_http_upstream_keepalive_module.c +++ b/src/http/modules/ngx_http_upstream_keepalive_module.c @@ -29,7 +29,7 @@ typedef struct { ngx_connection_t *connection; socklen_t socklen; - u_char sockaddr[NGX_SOCKADDRLEN]; + ngx_sockaddr_t sockaddr; } ngx_http_upstream_keepalive_cache_t; diff --git a/src/http/modules/ngx_http_userid_filter_module.c b/src/http/modules/ngx_http_userid_filter_module.c index 1487c09..0dbacba 100644 --- a/src/http/modules/ngx_http_userid_filter_module.c +++ b/src/http/modules/ngx_http_userid_filter_module.c @@ -836,7 +836,7 @@ ngx_http_userid_init_worker(ngx_cycle_t *cycle) ngx_gettimeofday(&tp); /* use the most significant usec part that fits to 16 bits */ - start_value = ((tp.tv_usec / 20) << 16) | ngx_pid; + start_value = (((uint32_t) tp.tv_usec / 20) << 16) | ngx_pid; return NGX_OK; } diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c index fef2c46..7f916e8 100644 --- a/src/http/modules/ngx_http_uwsgi_module.c +++ b/src/http/modules/ngx_http_uwsgi_module.c @@ -196,7 +196,7 @@ static ngx_command_t ngx_http_uwsgi_commands[] = { NULL }, { ngx_string("uwsgi_bind"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12, ngx_http_upstream_bind_set_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_uwsgi_loc_conf_t, upstream.local), @@ -2325,13 +2325,9 @@ ngx_http_uwsgi_set_ssl(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *uwcf) } } - if (SSL_CTX_set_cipher_list(uwcf->upstream.ssl->ctx, - (const char *) uwcf->ssl_ciphers.data) - == 0) + if (ngx_ssl_ciphers(cf, uwcf->upstream.ssl, &uwcf->ssl_ciphers, 0) + != NGX_OK) { - ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, - "SSL_CTX_set_cipher_list(\"%V\") failed", - &uwcf->ssl_ciphers); return NGX_ERROR; } diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c index 0ceb613..7a46b3e 100644 --- a/src/http/ngx_http.c +++ b/src/http/ngx_http.c @@ -1144,12 +1144,8 @@ ngx_http_add_listen(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, in_port_t p; ngx_uint_t i; struct sockaddr *sa; - struct sockaddr_in *sin; ngx_http_conf_port_t *port; ngx_http_core_main_conf_t *cmcf; -#if (NGX_HAVE_INET6) - struct sockaddr_in6 *sin6; -#endif cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); @@ -1161,28 +1157,8 @@ ngx_http_add_listen(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, } } - sa = &lsopt->u.sockaddr; - - switch (sa->sa_family) { - -#if (NGX_HAVE_INET6) - case AF_INET6: - sin6 = &lsopt->u.sockaddr_in6; - p = sin6->sin6_port; - break; -#endif - -#if (NGX_HAVE_UNIX_DOMAIN) - case AF_UNIX: - p = 0; - break; -#endif - - default: /* AF_INET */ - sin = &lsopt->u.sockaddr_in; - p = sin->sin_port; - break; - } + sa = &lsopt->sockaddr.sockaddr; + p = ngx_inet_get_port(sa); port = cmcf->ports->elts; for (i = 0; i < cmcf->ports->nelts; i++) { @@ -1215,14 +1191,8 @@ static ngx_int_t ngx_http_add_addresses(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, ngx_http_conf_port_t *port, ngx_http_listen_opt_t *lsopt) { - u_char *p; - size_t len, off; ngx_uint_t i, default_server, proxy_protocol; - struct sockaddr *sa; ngx_http_conf_addr_t *addr; -#if (NGX_HAVE_UNIX_DOMAIN) - struct sockaddr_un *saun; -#endif #if (NGX_HTTP_SSL) ngx_uint_t ssl; #endif @@ -1235,37 +1205,15 @@ ngx_http_add_addresses(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, * may fill some fields in inherited sockaddr struct's */ - sa = &lsopt->u.sockaddr; - - switch (sa->sa_family) { - -#if (NGX_HAVE_INET6) - case AF_INET6: - off = offsetof(struct sockaddr_in6, sin6_addr); - len = 16; - break; -#endif - -#if (NGX_HAVE_UNIX_DOMAIN) - case AF_UNIX: - off = offsetof(struct sockaddr_un, sun_path); - len = sizeof(saun->sun_path); - break; -#endif - - default: /* AF_INET */ - off = offsetof(struct sockaddr_in, sin_addr); - len = 4; - break; - } - - p = lsopt->u.sockaddr_data + off; - addr = port->addrs.elts; for (i = 0; i < port->addrs.nelts; i++) { - if (ngx_memcmp(p, addr[i].opt.u.sockaddr_data + off, len) != 0) { + if (ngx_cmp_sockaddr(&lsopt->sockaddr.sockaddr, lsopt->socklen, + &addr[i].opt.sockaddr.sockaddr, + addr[i].opt.socklen, 0) + != NGX_OK) + { continue; } @@ -1756,7 +1704,8 @@ ngx_http_add_listening(ngx_conf_t *cf, ngx_http_conf_addr_t *addr) ngx_http_core_loc_conf_t *clcf; ngx_http_core_srv_conf_t *cscf; - ls = ngx_create_listening(cf, &addr->opt.u.sockaddr, addr->opt.socklen); + ls = ngx_create_listening(cf, &addr->opt.sockaddr.sockaddr, + addr->opt.socklen); if (ls == NULL) { return NULL; } @@ -1846,7 +1795,7 @@ ngx_http_add_addrs(ngx_conf_t *cf, ngx_http_port_t *hport, for (i = 0; i < hport->naddrs; i++) { - sin = &addr[i].opt.u.sockaddr_in; + sin = &addr[i].opt.sockaddr.sockaddr_in; addrs[i].addr = sin->sin_addr.s_addr; addrs[i].conf.default_server = addr[i].default_server; #if (NGX_HTTP_SSL) @@ -1911,7 +1860,7 @@ ngx_http_add_addrs6(ngx_conf_t *cf, ngx_http_port_t *hport, for (i = 0; i < hport->naddrs; i++) { - sin6 = &addr[i].opt.u.sockaddr_in6; + sin6 = &addr[i].opt.sockaddr.sockaddr_in6; addrs6[i].addr6 = sin6->sin6_addr; addrs6[i].conf.default_server = addr[i].default_server; #if (NGX_HTTP_SSL) diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index bd36aec..76917bb 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -793,8 +793,6 @@ ngx_http_handler(ngx_http_request_t *r) r->connection->log->action = NULL; - r->connection->unexpected_eof = 0; - if (!r->internal) { switch (r->headers_in.connection_type) { case 0: @@ -2912,7 +2910,9 @@ ngx_http_get_forwarded_addr_internal(ngx_http_request_t *r, ngx_addr_t *addr, } } - if (ngx_parse_addr(r->pool, &paddr, p, xfflen - (p - xff)) != NGX_OK) { + if (ngx_parse_addr_port(r->pool, &paddr, p, xfflen - (p - xff)) + != NGX_OK) + { return NGX_DECLINED; } @@ -3032,7 +3032,7 @@ ngx_http_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) if (rv == NGX_CONF_OK && !cscf->listen) { ngx_memzero(&lsopt, sizeof(ngx_http_listen_opt_t)); - sin = &lsopt.u.sockaddr_in; + sin = &lsopt.sockaddr.sockaddr_in; sin->sin_family = AF_INET; #if (NGX_WIN32) @@ -3055,8 +3055,8 @@ ngx_http_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) #endif lsopt.wildcard = 1; - (void) ngx_sock_ntop(&lsopt.u.sockaddr, lsopt.socklen, lsopt.addr, - NGX_SOCKADDR_STRLEN, 1); + (void) ngx_sock_ntop(&lsopt.sockaddr.sockaddr, lsopt.socklen, + lsopt.addr, NGX_SOCKADDR_STRLEN, 1); if (ngx_http_add_listen(cf, cscf, &lsopt) != NGX_OK) { return NGX_CONF_ERROR; @@ -4000,7 +4000,7 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ngx_memzero(&lsopt, sizeof(ngx_http_listen_opt_t)); - ngx_memcpy(&lsopt.u.sockaddr, u.sockaddr, u.socklen); + ngx_memcpy(&lsopt.sockaddr.sockaddr, &u.sockaddr, u.socklen); lsopt.socklen = u.socklen; lsopt.backlog = NGX_LISTEN_BACKLOG; @@ -4017,7 +4017,7 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) lsopt.ipv6only = 1; #endif - (void) ngx_sock_ntop(&lsopt.u.sockaddr, lsopt.socklen, lsopt.addr, + (void) ngx_sock_ntop(&lsopt.sockaddr.sockaddr, lsopt.socklen, lsopt.addr, NGX_SOCKADDR_STRLEN, 1); for (n = 2; n < cf->args->nelts; n++) { @@ -4146,7 +4146,7 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) struct sockaddr *sa; - sa = &lsopt.u.sockaddr; + sa = &lsopt.sockaddr.sockaddr; if (sa->sa_family == AF_INET6) { diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h index 6c446a0..773c215 100644 --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -58,18 +58,7 @@ typedef struct ngx_http_core_loc_conf_s ngx_http_core_loc_conf_t; typedef struct { - union { - struct sockaddr sockaddr; - struct sockaddr_in sockaddr_in; -#if (NGX_HAVE_INET6) - struct sockaddr_in6 sockaddr_in6; -#endif -#if (NGX_HAVE_UNIX_DOMAIN) - struct sockaddr_un sockaddr_un; -#endif - u_char sockaddr_data[NGX_SOCKADDRLEN]; - } u; - + ngx_sockaddr_t sockaddr; socklen_t socklen; unsigned set:1; diff --git a/src/http/ngx_http_file_cache.c b/src/http/ngx_http_file_cache.c index 37cd377..4bf0f7f 100644 --- a/src/http/ngx_http_file_cache.c +++ b/src/http/ngx_http_file_cache.c @@ -101,7 +101,7 @@ ngx_http_file_cache_init(ngx_shm_zone_t *shm_zone, void *data) return NGX_ERROR; } - for (n = 0; n < 3; n++) { + for (n = 0; n < NGX_MAX_PATH_LEVEL; n++) { if (cache->path->level[n] != ocache->path->level[n]) { ngx_log_error(NGX_LOG_EMERG, shm_zone->shm.log, 0, "cache \"%V\" had previously different levels", @@ -1403,6 +1403,7 @@ ngx_http_file_cache_update(ngx_http_request_t *r, ngx_temp_file_t *tf) ngx_shmtx_lock(&cache->shpool->mutex); c->node->count--; + c->node->error = 0; c->node->uniq = uniq; c->node->body_start = c->body_start; @@ -2256,7 +2257,7 @@ ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) p = value[i].data + 7; last = value[i].data + value[i].len; - for (n = 0; n < 3 && p < last; n++) { + for (n = 0; n < NGX_MAX_PATH_LEVEL && p < last; n++) { if (*p > '0' && *p < '3') { @@ -2267,7 +2268,7 @@ ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) break; } - if (*p++ == ':' && n < 2 && p != last) { + if (*p++ == ':' && n < NGX_MAX_PATH_LEVEL - 1 && p < last) { continue; } @@ -2277,7 +2278,7 @@ ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) goto invalid_levels; } - if (cache->path->len < 10 + 3) { + if (cache->path->len < 10 + NGX_MAX_PATH_LEVEL) { continue; } @@ -2449,7 +2450,7 @@ ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ngx_memcpy(p, "/temp", sizeof("/temp")); ngx_memcpy(&cache->temp_path->level, &cache->path->level, - 3 * sizeof(size_t)); + NGX_MAX_PATH_LEVEL * sizeof(size_t)); cache->temp_path->len = cache->path->len; cache->temp_path->conf_file = cf->conf_file->file.name.data; diff --git a/src/http/ngx_http_header_filter_module.c b/src/http/ngx_http_header_filter_module.c index 507dc93..f000b2e 100644 --- a/src/http/ngx_http_header_filter_module.c +++ b/src/http/ngx_http_header_filter_module.c @@ -95,17 +95,17 @@ static ngx_str_t ngx_http_status_lines[] = { ngx_string("414 Request-URI Too Large"), ngx_string("415 Unsupported Media Type"), ngx_string("416 Requested Range Not Satisfiable"), + ngx_null_string, /* "417 Expectation Failed" */ + ngx_null_string, /* "418 unused" */ + ngx_null_string, /* "419 unused" */ + ngx_null_string, /* "420 unused" */ + ngx_string("421 Misdirected Request"), - /* ngx_null_string, */ /* "417 Expectation Failed" */ - /* ngx_null_string, */ /* "418 unused" */ - /* ngx_null_string, */ /* "419 unused" */ - /* ngx_null_string, */ /* "420 unused" */ - /* ngx_null_string, */ /* "421 unused" */ /* ngx_null_string, */ /* "422 Unprocessable Entity" */ /* ngx_null_string, */ /* "423 Locked" */ /* ngx_null_string, */ /* "424 Failed Dependency" */ -#define NGX_HTTP_LAST_4XX 417 +#define NGX_HTTP_LAST_4XX 422 #define NGX_HTTP_OFF_5XX (NGX_HTTP_LAST_4XX - 400 + NGX_HTTP_OFF_4XX) ngx_string("500 Internal Server Error"), @@ -113,10 +113,10 @@ static ngx_str_t ngx_http_status_lines[] = { ngx_string("502 Bad Gateway"), ngx_string("503 Service Temporarily Unavailable"), ngx_string("504 Gateway Time-out"), - ngx_null_string, /* "505 HTTP Version Not Supported" */ ngx_null_string, /* "506 Variant Also Negotiates" */ ngx_string("507 Insufficient Storage"), + /* ngx_null_string, */ /* "508 unused" */ /* ngx_null_string, */ /* "509 unused" */ /* ngx_null_string, */ /* "510 Not Extended" */ @@ -161,10 +161,6 @@ ngx_http_header_filter(ngx_http_request_t *r) ngx_connection_t *c; ngx_http_core_loc_conf_t *clcf; ngx_http_core_srv_conf_t *cscf; - struct sockaddr_in *sin; -#if (NGX_HAVE_INET6) - struct sockaddr_in6 *sin6; -#endif u_char addr[NGX_SOCKADDR_STRLEN]; if (r->header_sent) { @@ -333,24 +329,7 @@ ngx_http_header_filter(ngx_http_request_t *r) } } - switch (c->local_sockaddr->sa_family) { - -#if (NGX_HAVE_INET6) - case AF_INET6: - sin6 = (struct sockaddr_in6 *) c->local_sockaddr; - port = ntohs(sin6->sin6_port); - break; -#endif -#if (NGX_HAVE_UNIX_DOMAIN) - case AF_UNIX: - port = 0; - break; -#endif - default: /* AF_INET */ - sin = (struct sockaddr_in *) c->local_sockaddr; - port = ntohs(sin->sin_port); - break; - } + port = ngx_inet_get_port(c->local_sockaddr); len += sizeof("Location: https://") - 1 + host.len diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c index 0e0b3a2..bd6c9c9 100644 --- a/src/http/ngx_http_parse.c +++ b/src/http/ngx_http_parse.c @@ -481,7 +481,7 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b) /* check "/.", "//", "%", and "\" (Win32) in URI */ case sw_after_slash_in_uri: - if (usual[ch >> 5] & (1 << (ch & 0x1f))) { + if (usual[ch >> 5] & (1U << (ch & 0x1f))) { state = sw_check_uri; break; } @@ -540,7 +540,7 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b) /* check "/", "%" and "\" (Win32) in URI */ case sw_check_uri: - if (usual[ch >> 5] & (1 << (ch & 0x1f))) { + if (usual[ch >> 5] & (1U << (ch & 0x1f))) { break; } @@ -626,7 +626,7 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b) /* URI */ case sw_uri: - if (usual[ch >> 5] & (1 << (ch & 0x1f))) { + if (usual[ch >> 5] & (1U << (ch & 0x1f))) { break; } @@ -737,6 +737,10 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b) return NGX_HTTP_PARSE_INVALID_REQUEST; } + if (r->http_major > 99) { + return NGX_HTTP_PARSE_INVALID_REQUEST; + } + r->http_major = r->http_major * 10 + ch - '0'; break; @@ -770,6 +774,10 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b) return NGX_HTTP_PARSE_INVALID_REQUEST; } + if (r->http_minor > 99) { + return NGX_HTTP_PARSE_INVALID_REQUEST; + } + r->http_minor = r->http_minor * 10 + ch - '0'; break; @@ -1123,7 +1131,7 @@ ngx_http_parse_uri(ngx_http_request_t *r) /* check "/.", "//", "%", and "\" (Win32) in URI */ case sw_after_slash_in_uri: - if (usual[ch >> 5] & (1 << (ch & 0x1f))) { + if (usual[ch >> 5] & (1U << (ch & 0x1f))) { state = sw_check_uri; break; } @@ -1171,7 +1179,7 @@ ngx_http_parse_uri(ngx_http_request_t *r) /* check "/", "%" and "\" (Win32) in URI */ case sw_check_uri: - if (usual[ch >> 5] & (1 << (ch & 0x1f))) { + if (usual[ch >> 5] & (1U << (ch & 0x1f))) { break; } @@ -1220,7 +1228,7 @@ ngx_http_parse_uri(ngx_http_request_t *r) /* URI */ case sw_uri: - if (usual[ch >> 5] & (1 << (ch & 0x1f))) { + if (usual[ch >> 5] & (1U << (ch & 0x1f))) { break; } @@ -1281,7 +1289,7 @@ ngx_http_parse_complex_uri(ngx_http_request_t *r, ngx_uint_t merge_slashes) case sw_usual: - if (usual[ch >> 5] & (1 << (ch & 0x1f))) { + if (usual[ch >> 5] & (1U << (ch & 0x1f))) { *u++ = ch; ch = *p++; break; @@ -1350,7 +1358,7 @@ ngx_http_parse_complex_uri(ngx_http_request_t *r, ngx_uint_t merge_slashes) case sw_slash: - if (usual[ch >> 5] & (1 << (ch & 0x1f))) { + if (usual[ch >> 5] & (1U << (ch & 0x1f))) { state = sw_usual; *u++ = ch; ch = *p++; @@ -1393,7 +1401,7 @@ ngx_http_parse_complex_uri(ngx_http_request_t *r, ngx_uint_t merge_slashes) case sw_dot: - if (usual[ch >> 5] & (1 << (ch & 0x1f))) { + if (usual[ch >> 5] & (1U << (ch & 0x1f))) { state = sw_usual; *u++ = ch; ch = *p++; @@ -1434,7 +1442,7 @@ ngx_http_parse_complex_uri(ngx_http_request_t *r, ngx_uint_t merge_slashes) case sw_dot_dot: - if (usual[ch >> 5] & (1 << (ch & 0x1f))) { + if (usual[ch >> 5] & (1U << (ch & 0x1f))) { state = sw_usual; *u++ = ch; ch = *p++; @@ -1680,6 +1688,10 @@ ngx_http_parse_status_line(ngx_http_request_t *r, ngx_buf_t *b, return NGX_ERROR; } + if (r->http_major > 99) { + return NGX_ERROR; + } + r->http_major = r->http_major * 10 + ch - '0'; break; @@ -1704,6 +1716,10 @@ ngx_http_parse_status_line(ngx_http_request_t *r, ngx_buf_t *b, return NGX_ERROR; } + if (r->http_minor > 99) { + return NGX_ERROR; + } + r->http_minor = r->http_minor * 10 + ch - '0'; break; @@ -1820,7 +1836,7 @@ ngx_http_parse_unsafe_uri(ngx_http_request_t *r, ngx_str_t *uri, continue; } - if (usual[ch >> 5] & (1 << (ch & 0x1f))) { + if (usual[ch >> 5] & (1U << (ch & 0x1f))) { continue; } diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c index 7d6cada..6ff7903 100644 --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -110,6 +110,10 @@ ngx_http_header_t ngx_http_headers_in[] = { offsetof(ngx_http_headers_in_t, content_length), ngx_http_process_unique_header_line }, + { ngx_string("Content-Range"), + offsetof(ngx_http_headers_in_t, content_range), + ngx_http_process_unique_header_line }, + { ngx_string("Content-Type"), offsetof(ngx_http_headers_in_t, content_type), ngx_http_process_header_line }, @@ -2064,8 +2068,8 @@ ngx_http_set_virtual_server(ngx_http_request_t *r, ngx_str_t *host) if (sscf->verify) { ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "client attempted to request the server name " - "different from that one was negotiated"); - ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); + "different from the one that was negotiated"); + ngx_http_finalize_request(r, NGX_HTTP_MISDIRECTED_REQUEST); return NGX_ERROR; } } @@ -2752,9 +2756,13 @@ ngx_http_test_reading(ngx_http_request_t *r) #if (NGX_HAVE_EPOLLRDHUP) - if ((ngx_event_flags & NGX_USE_EPOLL_EVENT) && rev->pending_eof) { + if ((ngx_event_flags & NGX_USE_EPOLL_EVENT) && ngx_use_epoll_rdhup) { socklen_t len; + if (!rev->pending_eof) { + return; + } + rev->eof = 1; c->error = 1; diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h index cfde7dc..499c1ef 100644 --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -95,6 +95,7 @@ #define NGX_HTTP_REQUEST_URI_TOO_LARGE 414 #define NGX_HTTP_UNSUPPORTED_MEDIA_TYPE 415 #define NGX_HTTP_RANGE_NOT_SATISFIABLE 416 +#define NGX_HTTP_MISDIRECTED_REQUEST 421 /* Our own HTTP codes */ @@ -182,6 +183,7 @@ typedef struct { ngx_table_elt_t *user_agent; ngx_table_elt_t *referer; ngx_table_elt_t *content_length; + ngx_table_elt_t *content_range; ngx_table_elt_t *content_type; ngx_table_elt_t *range; diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c index bff9525..c2b1658 100644 --- a/src/http/ngx_http_script.c +++ b/src/http/ngx_http_script.c @@ -350,11 +350,9 @@ ngx_http_script_compile(ngx_http_script_compile_t *sc) goto invalid_variable; } -#if (NGX_PCRE) - { - ngx_uint_t n; - if (sc->source->data[i] >= '1' && sc->source->data[i] <= '9') { +#if (NGX_PCRE) + ngx_uint_t n; n = sc->source->data[i] - '0'; @@ -371,9 +369,13 @@ ngx_http_script_compile(ngx_http_script_compile_t *sc) i++; continue; - } - } +#else + ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0, + "using variable \"$%c\" requires " + "PCRE library", sc->source->data[i]); + return NGX_ERROR; #endif + } if (sc->source->data[i] == '{') { bracket = 1; diff --git a/src/http/ngx_http_special_response.c b/src/http/ngx_http_special_response.c index 2771e58..64e5acd 100644 --- a/src/http/ngx_http_special_response.c +++ b/src/http/ngx_http_special_response.c @@ -210,6 +210,14 @@ static char ngx_http_error_416_page[] = ; +static char ngx_http_error_421_page[] = +"" CRLF +"421 Misdirected Request" CRLF +"" CRLF +"

421 Misdirected Request

" CRLF +; + + static char ngx_http_error_494_page[] = "" CRLF "400 Request Header Or Cookie Too Large" @@ -334,8 +342,13 @@ static ngx_str_t ngx_http_error_pages[] = { ngx_string(ngx_http_error_414_page), ngx_string(ngx_http_error_415_page), ngx_string(ngx_http_error_416_page), + ngx_null_string, /* 417 */ + ngx_null_string, /* 418 */ + ngx_null_string, /* 419 */ + ngx_null_string, /* 420 */ + ngx_string(ngx_http_error_421_page), -#define NGX_HTTP_LAST_4XX 417 +#define NGX_HTTP_LAST_4XX 422 #define NGX_HTTP_OFF_5XX (NGX_HTTP_LAST_4XX - 400 + NGX_HTTP_OFF_4XX) ngx_string(ngx_http_error_494_page), /* 494, request header too large */ diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c index 1386bdb..0f6b3ae 100644 --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -165,8 +165,8 @@ static char *ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy); static char *ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); -static ngx_addr_t *ngx_http_upstream_get_local(ngx_http_request_t *r, - ngx_http_upstream_local_t *local); +static ngx_int_t ngx_http_upstream_set_local(ngx_http_request_t *r, + ngx_http_upstream_t *u, ngx_http_upstream_local_t *local); static void *ngx_http_upstream_create_main_conf(ngx_conf_t *cf); static char *ngx_http_upstream_init_main_conf(ngx_conf_t *cf, void *conf); @@ -588,7 +588,10 @@ ngx_http_upstream_init_request(ngx_http_request_t *r) return; } - u->peer.local = ngx_http_upstream_get_local(r, u->conf->local); + if (ngx_http_upstream_set_local(r, u, u->conf->local) != NGX_OK) { + ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); @@ -1219,9 +1222,13 @@ ngx_http_upstream_check_broken_connection(ngx_http_request_t *r, #if (NGX_HAVE_EPOLLRDHUP) - if ((ngx_event_flags & NGX_USE_EPOLL_EVENT) && ev->pending_eof) { + if ((ngx_event_flags & NGX_USE_EPOLL_EVENT) && ngx_use_epoll_rdhup) { socklen_t len; + if (!ev->pending_eof) { + return; + } + ev->eof = 1; c->error = 1; @@ -5785,7 +5792,7 @@ ngx_http_upstream_bind_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, value = cf->args->elts; - if (ngx_strcmp(value[1].data, "off") == 0) { + if (cf->args->nelts == 2 && ngx_strcmp(value[1].data, "off") == 0) { *plocal = NULL; return NGX_CONF_OK; } @@ -5815,34 +5822,52 @@ ngx_http_upstream_bind_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, *local->value = cv; - return NGX_CONF_OK; + } else { + local->addr = ngx_palloc(cf->pool, sizeof(ngx_addr_t)); + if (local->addr == NULL) { + return NGX_CONF_ERROR; + } + + rc = ngx_parse_addr_port(cf->pool, local->addr, value[1].data, + value[1].len); + + switch (rc) { + case NGX_OK: + local->addr->name = value[1]; + break; + + case NGX_DECLINED: + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid address \"%V\"", &value[1]); + /* fall through */ + + default: + return NGX_CONF_ERROR; + } } - local->addr = ngx_palloc(cf->pool, sizeof(ngx_addr_t)); - if (local->addr == NULL) { - return NGX_CONF_ERROR; + if (cf->args->nelts > 2) { + if (ngx_strcmp(value[2].data, "transparent") == 0) { +#if (NGX_HAVE_TRANSPARENT_PROXY) + local->transparent = 1; +#else + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "transparent proxying is not supported " + "on this platform, ignored"); +#endif + } else { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid parameter \"%V\"", &value[2]); + return NGX_CONF_ERROR; + } } - rc = ngx_parse_addr(cf->pool, local->addr, value[1].data, value[1].len); - - switch (rc) { - case NGX_OK: - local->addr->name = value[1]; - return NGX_CONF_OK; - - case NGX_DECLINED: - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid address \"%V\"", &value[1]); - /* fall through */ - - default: - return NGX_CONF_ERROR; - } + return NGX_CONF_OK; } -static ngx_addr_t * -ngx_http_upstream_get_local(ngx_http_request_t *r, +static ngx_int_t +ngx_http_upstream_set_local(ngx_http_request_t *r, ngx_http_upstream_t *u, ngx_http_upstream_local_t *local) { ngx_int_t rc; @@ -5850,41 +5875,47 @@ ngx_http_upstream_get_local(ngx_http_request_t *r, ngx_addr_t *addr; if (local == NULL) { - return NULL; + u->peer.local = NULL; + return NGX_OK; } +#if (NGX_HAVE_TRANSPARENT_PROXY) + u->peer.transparent = local->transparent; +#endif + if (local->value == NULL) { - return local->addr; + u->peer.local = local->addr; + return NGX_OK; } if (ngx_http_complex_value(r, local->value, &val) != NGX_OK) { - return NULL; + return NGX_ERROR; } if (val.len == 0) { - return NULL; + return NGX_OK; } addr = ngx_palloc(r->pool, sizeof(ngx_addr_t)); if (addr == NULL) { - return NULL; + return NGX_ERROR; } - rc = ngx_parse_addr(r->pool, addr, val.data, val.len); + rc = ngx_parse_addr_port(r->pool, addr, val.data, val.len); + if (rc == NGX_ERROR) { + return NGX_ERROR; + } - switch (rc) { - case NGX_OK: - addr->name = val; - return addr; - - case NGX_DECLINED: + if (rc != NGX_OK) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "invalid local address \"%V\"", &val); - /* fall through */ - - default: - return NULL; + return NGX_OK; } + + addr->name = val; + u->peer.local = addr; + + return NGX_OK; } diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h index 7595dcf..b288f28 100644 --- a/src/http/ngx_http_upstream.h +++ b/src/http/ngx_http_upstream.h @@ -133,6 +133,9 @@ struct ngx_http_upstream_srv_conf_s { typedef struct { ngx_addr_t *addr; ngx_http_complex_value_t *value; +#if (NGX_HAVE_TRANSPARENT_PROXY) + ngx_uint_t transparent; /* unsigned transparent:1; */ +#endif } ngx_http_upstream_local_t; diff --git a/src/http/ngx_http_upstream_round_robin.c b/src/http/ngx_http_upstream_round_robin.c index 8342dc8..8479c42 100644 --- a/src/http/ngx_http_upstream_round_robin.c +++ b/src/http/ngx_http_upstream_round_robin.c @@ -354,16 +354,7 @@ ngx_http_upstream_create_round_robin_peer(ngx_http_request_t *r, } ngx_memcpy(sockaddr, ur->addrs[i].sockaddr, socklen); - - switch (sockaddr->sa_family) { -#if (NGX_HAVE_INET6) - case AF_INET6: - ((struct sockaddr_in6 *) sockaddr)->sin6_port = htons(ur->port); - break; -#endif - default: /* AF_INET */ - ((struct sockaddr_in *) sockaddr)->sin_port = htons(ur->port); - } + ngx_inet_set_port(sockaddr, ur->port); p = ngx_pnalloc(r->pool, NGX_SOCKADDR_STRLEN); if (p == NULL) { diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c index f8271ab..7e65b2e 100644 --- a/src/http/ngx_http_variables.c +++ b/src/http/ngx_http_variables.c @@ -58,6 +58,8 @@ static ngx_int_t ngx_http_variable_remote_port(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_proxy_protocol_addr(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_proxy_protocol_port(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_server_addr(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_server_port(ngx_http_request_t *r, @@ -98,6 +100,8 @@ static ngx_int_t ngx_http_variable_request_length(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_request_time(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_request_id(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_status(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); @@ -192,6 +196,9 @@ static ngx_http_variable_t ngx_http_core_variables[] = { { ngx_string("proxy_protocol_addr"), NULL, ngx_http_variable_proxy_protocol_addr, 0, 0, 0 }, + { ngx_string("proxy_protocol_port"), NULL, + ngx_http_variable_proxy_protocol_port, 0, 0, 0 }, + { ngx_string("server_addr"), NULL, ngx_http_variable_server_addr, 0, 0, 0 }, { ngx_string("server_port"), NULL, ngx_http_variable_server_port, 0, 0, 0 }, @@ -274,6 +281,10 @@ static ngx_http_variable_t ngx_http_core_variables[] = { { ngx_string("request_time"), NULL, ngx_http_variable_request_time, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, + { ngx_string("request_id"), NULL, + ngx_http_variable_request_id, + 0, 0, 0 }, + { ngx_string("status"), NULL, ngx_http_variable_status, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, @@ -1190,11 +1201,7 @@ static ngx_int_t ngx_http_variable_remote_port(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { - ngx_uint_t port; - struct sockaddr_in *sin; -#if (NGX_HAVE_INET6) - struct sockaddr_in6 *sin6; -#endif + ngx_uint_t port; v->len = 0; v->valid = 1; @@ -1206,26 +1213,7 @@ ngx_http_variable_remote_port(ngx_http_request_t *r, return NGX_ERROR; } - switch (r->connection->sockaddr->sa_family) { - -#if (NGX_HAVE_INET6) - case AF_INET6: - sin6 = (struct sockaddr_in6 *) r->connection->sockaddr; - port = ntohs(sin6->sin6_port); - break; -#endif - -#if (NGX_HAVE_UNIX_DOMAIN) - case AF_UNIX: - port = 0; - break; -#endif - - default: /* AF_INET */ - sin = (struct sockaddr_in *) r->connection->sockaddr; - port = ntohs(sin->sin_port); - break; - } + port = ngx_inet_get_port(r->connection->sockaddr); if (port > 0 && port < 65536) { v->len = ngx_sprintf(v->data, "%ui", port) - v->data; @@ -1249,6 +1237,32 @@ ngx_http_variable_proxy_protocol_addr(ngx_http_request_t *r, } +static ngx_int_t +ngx_http_variable_proxy_protocol_port(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_uint_t port; + + v->len = 0; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + v->data = ngx_pnalloc(r->pool, sizeof("65535") - 1); + if (v->data == NULL) { + return NGX_ERROR; + } + + port = r->connection->proxy_protocol_port; + + if (port > 0 && port < 65536) { + v->len = ngx_sprintf(v->data, "%ui", port) - v->data; + } + + return NGX_OK; +} + + static ngx_int_t ngx_http_variable_server_addr(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) @@ -1284,11 +1298,7 @@ static ngx_int_t ngx_http_variable_server_port(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { - ngx_uint_t port; - struct sockaddr_in *sin; -#if (NGX_HAVE_INET6) - struct sockaddr_in6 *sin6; -#endif + ngx_uint_t port; v->len = 0; v->valid = 1; @@ -1304,26 +1314,7 @@ ngx_http_variable_server_port(ngx_http_request_t *r, return NGX_ERROR; } - switch (r->connection->local_sockaddr->sa_family) { - -#if (NGX_HAVE_INET6) - case AF_INET6: - sin6 = (struct sockaddr_in6 *) r->connection->local_sockaddr; - port = ntohs(sin6->sin6_port); - break; -#endif - -#if (NGX_HAVE_UNIX_DOMAIN) - case AF_UNIX: - port = 0; - break; -#endif - - default: /* AF_INET */ - sin = (struct sockaddr_in *) r->connection->local_sockaddr; - port = ntohs(sin->sin_port); - break; - } + port = ngx_inet_get_port(r->connection->local_sockaddr); if (port > 0 && port < 65536) { v->len = ngx_sprintf(v->data, "%ui", port) - v->data; @@ -2067,6 +2058,47 @@ ngx_http_variable_request_time(ngx_http_request_t *r, } +static ngx_int_t +ngx_http_variable_request_id(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + u_char *id; + +#if (NGX_OPENSSL) + u_char random_bytes[16]; +#endif + + id = ngx_pnalloc(r->pool, 32); + if (id == NULL) { + return NGX_ERROR; + } + + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + v->len = 32; + v->data = id; + +#if (NGX_OPENSSL) + + if (RAND_bytes(random_bytes, 16) == 1) { + ngx_hex_dump(id, random_bytes, 16); + return NGX_OK; + } + + ngx_ssl_error(NGX_LOG_ERR, r->connection->log, 0, "RAND_bytes() failed"); + +#endif + + ngx_sprintf(id, "%08xD%08xD%08xD%08xD", + (uint32_t) ngx_random(), (uint32_t) ngx_random(), + (uint32_t) ngx_random(), (uint32_t) ngx_random()); + + return NGX_OK; +} + + static ngx_int_t ngx_http_variable_connection(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c index 278c9ab..d0cd2ab 100644 --- a/src/http/v2/ngx_http_v2.c +++ b/src/http/v2/ngx_http_v2.c @@ -48,11 +48,6 @@ #define NGX_HTTP_V2_DEFAULT_FRAME_SIZE (1 << 14) -#define NGX_HTTP_V2_MAX_WINDOW ((1U << 31) - 1) -#define NGX_HTTP_V2_DEFAULT_WINDOW 65535 - -#define NGX_HTTP_V2_INITIAL_WINDOW 0 - #define NGX_HTTP_V2_ROOT (void *) -1 @@ -415,6 +410,16 @@ ngx_http_v2_write_handler(ngx_event_t *wev) ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http2 write handler"); + if (h2c->last_out == NULL && !c->buffered) { + + if (wev->timer_set) { + ngx_del_timer(wev); + } + + ngx_http_v2_handle_connection(h2c); + return; + } + h2c->blocked = 1; rc = ngx_http_v2_send_output_queue(h2c); @@ -473,7 +478,7 @@ ngx_http_v2_send_output_queue(ngx_http_v2_connection_t *h2c) wev = c->write; if (!wev->ready) { - return NGX_OK; + return NGX_AGAIN; } cl = NULL; @@ -544,15 +549,6 @@ ngx_http_v2_send_output_queue(ngx_http_v2_connection_t *h2c) c->tcp_nodelay = NGX_TCP_NODELAY_SET; } - if (cl) { - ngx_add_timer(wev, clcf->send_timeout); - - } else { - if (wev->timer_set) { - ngx_del_timer(wev); - } - } - for ( /* void */ ; out; out = fn) { fn = out->next; @@ -577,6 +573,15 @@ ngx_http_v2_send_output_queue(ngx_http_v2_connection_t *h2c) h2c->last_out = frame; + if (!wev->ready) { + ngx_add_timer(wev, clcf->send_timeout); + return NGX_AGAIN; + } + + if (wev->timer_set) { + ngx_del_timer(wev); + } + return NGX_OK; error: @@ -594,7 +599,8 @@ error: static void ngx_http_v2_handle_connection(ngx_http_v2_connection_t *h2c) { - ngx_connection_t *c; + ngx_int_t rc; + ngx_connection_t *c; ngx_http_v2_srv_conf_t *h2scf; if (h2c->last_out || h2c->processing) { @@ -609,7 +615,22 @@ ngx_http_v2_handle_connection(ngx_http_v2_connection_t *h2c) } if (c->buffered) { - return; + h2c->blocked = 1; + + rc = ngx_http_v2_send_output_queue(h2c); + + h2c->blocked = 0; + + if (rc == NGX_ERROR) { + ngx_http_close_connection(c); + return; + } + + if (rc == NGX_AGAIN) { + return; + } + + /* rc == NGX_OK */ } h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, @@ -620,7 +641,7 @@ ngx_http_v2_handle_connection(ngx_http_v2_connection_t *h2c) } if (ngx_terminate || ngx_exiting) { - ngx_http_close_connection(c); + ngx_http_v2_finalize_connection(h2c, NGX_HTTP_V2_NO_ERROR); return; } @@ -879,8 +900,6 @@ ngx_http_v2_state_data(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end) return ngx_http_v2_state_skip_padded(h2c, pos, end); } - stream->in_closed = h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG; - h2c->state.stream = stream; return ngx_http_v2_state_read_data(h2c, pos, end); @@ -891,10 +910,12 @@ static u_char * ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end) { - size_t size; - ngx_int_t rc; - ngx_uint_t last; - ngx_http_v2_stream_t *stream; + size_t size; + ngx_buf_t *buf; + ngx_int_t rc; + ngx_http_request_t *r; + ngx_http_v2_stream_t *stream; + ngx_http_v2_srv_conf_t *h2scf; stream = h2c->state.stream; @@ -913,17 +934,42 @@ ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos, if (size >= h2c->state.length) { size = h2c->state.length; - last = stream->in_closed; - - } else { - last = 0; + stream->in_closed = h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG; } - rc = ngx_http_v2_process_request_body(stream->request, pos, size, last); + r = stream->request; - if (rc != NGX_OK) { - stream->skip_data = 1; - ngx_http_finalize_request(stream->request, rc); + if (r->request_body) { + rc = ngx_http_v2_process_request_body(r, pos, size, stream->in_closed); + + if (rc != NGX_OK) { + stream->skip_data = 1; + ngx_http_finalize_request(r, rc); + } + + } else if (size) { + buf = stream->preread; + + if (buf == NULL) { + h2scf = ngx_http_get_module_srv_conf(r, ngx_http_v2_module); + + buf = ngx_create_temp_buf(r->pool, h2scf->preread_size); + if (buf == NULL) { + return ngx_http_v2_connection_error(h2c, + NGX_HTTP_V2_INTERNAL_ERROR); + } + + stream->preread = buf; + } + + if (size > (size_t) (buf->end - buf->last)) { + ngx_log_error(NGX_LOG_ALERT, h2c->connection->log, 0, + "http2 preread buffer overflow"); + return ngx_http_v2_connection_error(h2c, + NGX_HTTP_V2_INTERNAL_ERROR); + } + + buf->last = ngx_cpymem(buf->last, pos, size); } pos += size; @@ -1058,7 +1104,9 @@ ngx_http_v2_state_headers(ngx_http_v2_connection_t *h2c, u_char *pos, goto rst_stream; } - if (!h2c->settings_ack && !(h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG)) + if (!h2c->settings_ack + && !(h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG) + && h2scf->preread_size < NGX_HTTP_V2_DEFAULT_WINDOW) { ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, "client sent stream with data " @@ -2434,8 +2482,7 @@ ngx_http_v2_send_settings(ngx_http_v2_connection_t *h2c, ngx_uint_t ack) buf->last = ngx_http_v2_write_uint16(buf->last, NGX_HTTP_V2_INIT_WINDOW_SIZE_SETTING); - buf->last = ngx_http_v2_write_uint32(buf->last, - NGX_HTTP_V2_INITIAL_WINDOW); + buf->last = ngx_http_v2_write_uint32(buf->last, h2scf->preread_size); buf->last = ngx_http_v2_write_uint16(buf->last, NGX_HTTP_V2_MAX_FRAME_SIZE_SETTING); @@ -2643,6 +2690,7 @@ ngx_http_v2_create_stream(ngx_http_v2_connection_t *h2c) ngx_http_log_ctx_t *ctx; ngx_http_request_t *r; ngx_http_v2_stream_t *stream; + ngx_http_v2_srv_conf_t *h2scf; ngx_http_core_srv_conf_t *cscf; fc = h2c->free_fake_connections; @@ -2756,8 +2804,10 @@ ngx_http_v2_create_stream(ngx_http_v2_connection_t *h2c) stream->request = r; stream->connection = h2c; + h2scf = ngx_http_get_module_srv_conf(r, ngx_http_v2_module); + stream->send_window = h2c->init_window; - stream->recv_window = NGX_HTTP_V2_INITIAL_WINDOW; + stream->recv_window = h2scf->preread_size; h2c->processing++; @@ -3400,7 +3450,9 @@ ngx_http_v2_run_request(ngx_http_request_t *r) return; } - r->headers_in.chunked = (r->headers_in.content_length_n == -1); + if (r->headers_in.content_length_n == -1 && !r->stream->in_closed) { + r->headers_in.chunked = 1; + } ngx_http_process_request(r); } @@ -3411,7 +3463,11 @@ ngx_http_v2_read_request_body(ngx_http_request_t *r, ngx_http_client_body_handler_pt post_handler) { off_t len; + size_t size; + ngx_buf_t *buf; + ngx_int_t rc; ngx_http_v2_stream_t *stream; + ngx_http_v2_srv_conf_t *h2scf; ngx_http_request_body_t *rb; ngx_http_core_loc_conf_t *clcf; ngx_http_v2_connection_t *h2c; @@ -3444,24 +3500,34 @@ ngx_http_v2_read_request_body(ngx_http_request_t *r, r->request_body = rb; + h2scf = ngx_http_get_module_srv_conf(r, ngx_http_v2_module); clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); len = r->headers_in.content_length_n; if (r->request_body_no_buffering && !stream->in_closed) { - r->request_body_in_file_only = 0; if (len < 0 || len > (off_t) clcf->client_body_buffer_size) { len = clcf->client_body_buffer_size; } + /* + * We need a room to store data up to the stream's initial window size, + * at least until this window will be exhausted. + */ + + if (len < (off_t) h2scf->preread_size) { + len = h2scf->preread_size; + } + if (len > NGX_HTTP_V2_MAX_WINDOW) { len = NGX_HTTP_V2_MAX_WINDOW; } - } - if (len >= 0 && len <= (off_t) clcf->client_body_buffer_size - && !r->request_body_in_file_only) + rb->buf = ngx_create_temp_buf(r->pool, (size_t) len); + + } else if (len >= 0 && len <= (off_t) clcf->client_body_buffer_size + && !r->request_body_in_file_only) { rb->buf = ngx_create_temp_buf(r->pool, (size_t) len); @@ -3478,22 +3544,44 @@ ngx_http_v2_read_request_body(ngx_http_request_t *r, return NGX_HTTP_INTERNAL_SERVER_ERROR; } + buf = stream->preread; + if (stream->in_closed) { r->request_body_no_buffering = 0; + + if (buf) { + rc = ngx_http_v2_process_request_body(r, buf->pos, + buf->last - buf->pos, 1); + ngx_pfree(r->pool, buf->start); + return rc; + } + return ngx_http_v2_process_request_body(r, NULL, 0, 1); } - if (len) { - if (r->request_body_no_buffering) { - stream->recv_window = (size_t) len; + if (buf) { + rc = ngx_http_v2_process_request_body(r, buf->pos, + buf->last - buf->pos, 0); - } else { - stream->no_flow_control = 1; - stream->recv_window = NGX_HTTP_V2_MAX_WINDOW; + ngx_pfree(r->pool, buf->start); + + if (rc != NGX_OK) { + stream->skip_data = 1; + return rc; } + } - if (ngx_http_v2_send_window_update(stream->connection, stream->node->id, - stream->recv_window) + if (r->request_body_no_buffering) { + size = (size_t) len - h2scf->preread_size; + + } else { + stream->no_flow_control = 1; + size = NGX_HTTP_V2_MAX_WINDOW - stream->recv_window; + } + + if (size) { + if (ngx_http_v2_send_window_update(stream->connection, + stream->node->id, size) == NGX_ERROR) { stream->skip_data = 1; @@ -3508,9 +3596,13 @@ ngx_http_v2_read_request_body(ngx_http_request_t *r, return NGX_HTTP_INTERNAL_SERVER_ERROR; } } + + stream->recv_window += size; } - ngx_add_timer(r->connection->read, clcf->client_body_timeout); + if (!buf) { + ngx_add_timer(r->connection->read, clcf->client_body_timeout); + } r->read_event_handler = ngx_http_v2_read_client_request_body_handler; r->write_event_handler = ngx_http_request_empty_handler; @@ -3529,13 +3621,8 @@ ngx_http_v2_process_request_body(ngx_http_request_t *r, u_char *pos, ngx_http_request_body_t *rb; ngx_http_core_loc_conf_t *clcf; - rb = r->request_body; - - if (rb == NULL) { - return NGX_OK; - } - fc = r->connection; + rb = r->request_body; buf = rb->buf; if (size) { @@ -3579,7 +3666,7 @@ ngx_http_v2_process_request_body(ngx_http_request_t *r, u_char *pos, rb->buf = NULL; } - if (r->headers_in.content_length_n == -1) { + if (r->headers_in.chunked) { r->headers_in.content_length_n = rb->received; } @@ -3789,7 +3876,14 @@ ngx_http_v2_read_unbuffered_request_body(ngx_http_request_t *r) window -= h2c->state.length; } - if (window == stream->recv_window) { + if (window <= stream->recv_window) { + if (window < stream->recv_window) { + ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, + "http2 negative window update"); + stream->skip_data = 1; + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + return NGX_AGAIN; } @@ -3824,6 +3918,10 @@ ngx_http_v2_terminate_stream(ngx_http_v2_connection_t *h2c, ngx_event_t *rev; ngx_connection_t *fc; + if (stream->rst_sent) { + return NGX_OK; + } + if (ngx_http_v2_send_rst_stream(h2c, stream->node->id, status) == NGX_ERROR) { @@ -3831,6 +3929,7 @@ ngx_http_v2_terminate_stream(ngx_http_v2_connection_t *h2c, } stream->rst_sent = 1; + stream->skip_data = 1; fc = stream->request->connection; fc->error = 1; @@ -3862,6 +3961,7 @@ ngx_http_v2_close_stream(ngx_http_v2_stream_t *stream, ngx_int_t rc) if (stream->queued) { fc->write->handler = ngx_http_v2_close_stream_handler; + fc->read->handler = ngx_http_empty_handler; return; } @@ -4103,10 +4203,6 @@ ngx_http_v2_finalize_connection(ngx_http_v2_connection_t *h2c, c->error = 1; - if (h2c->state.stream) { - ngx_http_v2_close_stream(h2c->state.stream, NGX_HTTP_BAD_REQUEST); - } - if (!h2c->processing) { ngx_http_close_connection(c); return; diff --git a/src/http/v2/ngx_http_v2.h b/src/http/v2/ngx_http_v2.h index 1adf8de..d712d38 100644 --- a/src/http/v2/ngx_http_v2.h +++ b/src/http/v2/ngx_http_v2.h @@ -46,6 +46,9 @@ #define NGX_HTTP_V2_PADDED_FLAG 0x08 #define NGX_HTTP_V2_PRIORITY_FLAG 0x20 +#define NGX_HTTP_V2_MAX_WINDOW ((1U << 31) - 1) +#define NGX_HTTP_V2_DEFAULT_WINDOW 65535 + typedef struct ngx_http_v2_connection_s ngx_http_v2_connection_t; typedef struct ngx_http_v2_node_s ngx_http_v2_node_t; @@ -174,6 +177,8 @@ struct ngx_http_v2_stream_s { ssize_t send_window; size_t recv_window; + ngx_buf_t *preread; + ngx_http_v2_out_frame_t *free_frames; ngx_chain_t *free_frame_headers; ngx_chain_t *free_bufs; @@ -293,7 +298,7 @@ size_t ngx_http_v2_huff_encode(u_char *src, size_t len, u_char *dst, #define ngx_http_v2_parse_uint16(p) ((p)[0] << 8 | (p)[1]) #define ngx_http_v2_parse_uint32(p) \ - ((p)[0] << 24 | (p)[1] << 16 | (p)[2] << 8 | (p)[3]) + ((uint32_t) (p)[0] << 24 | (p)[1] << 16 | (p)[2] << 8 | (p)[3]) #endif diff --git a/src/http/v2/ngx_http_v2_filter_module.c b/src/http/v2/ngx_http_v2_filter_module.c index caa835d..4ab7791 100644 --- a/src/http/v2/ngx_http_v2_filter_module.c +++ b/src/http/v2/ngx_http_v2_filter_module.c @@ -137,10 +137,6 @@ ngx_http_v2_header_filter(ngx_http_request_t *r) ngx_http_v2_out_frame_t *frame; ngx_http_core_loc_conf_t *clcf; ngx_http_core_srv_conf_t *cscf; - struct sockaddr_in *sin; -#if (NGX_HAVE_INET6) - struct sockaddr_in6 *sin6; -#endif u_char addr[NGX_SOCKADDR_STRLEN]; static const u_char nginx[5] = "\x84\xaa\x63\x55\xe7"; @@ -169,6 +165,12 @@ ngx_http_v2_header_filter(ngx_http_request_t *r) return NGX_OK; } + fc = r->connection; + + if (fc->error) { + return NGX_ERROR; + } + if (r->method == NGX_HTTP_HEAD) { r->header_only = 1; } @@ -259,8 +261,6 @@ ngx_http_v2_header_filter(ngx_http_request_t *r) len += 1 + ngx_http_v2_literal_size("Wed, 31 Dec 1986 18:00:00 GMT"); } - fc = r->connection; - if (r->headers_out.location && r->headers_out.location->value.len) { if (r->headers_out.location->value.data[0] == '/') { @@ -280,24 +280,7 @@ ngx_http_v2_header_filter(ngx_http_request_t *r) } } - switch (fc->local_sockaddr->sa_family) { - -#if (NGX_HAVE_INET6) - case AF_INET6: - sin6 = (struct sockaddr_in6 *) fc->local_sockaddr; - port = ntohs(sin6->sin6_port); - break; -#endif -#if (NGX_HAVE_UNIX_DOMAIN) - case AF_UNIX: - port = 0; - break; -#endif - default: /* AF_INET */ - sin = (struct sockaddr_in *) fc->local_sockaddr; - port = ntohs(sin->sin_port); - break; - } + port = ngx_inet_get_port(fc->local_sockaddr); location.len = sizeof("https://") - 1 + host.len + r->headers_out.location->value.len; @@ -995,12 +978,11 @@ static ngx_http_v2_out_frame_t * ngx_http_v2_filter_get_data_frame(ngx_http_v2_stream_t *stream, size_t len, ngx_chain_t *first, ngx_chain_t *last) { - u_char flags; - ngx_buf_t *buf; - ngx_chain_t *cl; + u_char flags; + ngx_buf_t *buf; + ngx_chain_t *cl; ngx_http_v2_out_frame_t *frame; - frame = stream->free_frames; if (frame) { @@ -1028,7 +1010,7 @@ ngx_http_v2_filter_get_data_frame(ngx_http_v2_stream_t *stream, buf = cl->buf; - if (!buf->start) { + if (buf->start == NULL) { buf->start = ngx_palloc(stream->request->pool, NGX_HTTP_V2_FRAME_HEADER_SIZE); if (buf->start == NULL) { @@ -1203,7 +1185,6 @@ ngx_http_v2_data_frame_handler(ngx_http_v2_connection_t *h2c, ngx_http_v2_stream_t *stream; stream = frame->stream; - cl = frame->first; if (cl->buf->tag == (ngx_buf_tag_t) &ngx_http_v2_module) { @@ -1313,18 +1294,20 @@ static ngx_inline void 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 || stream->exhausted) { + if (stream->handled || stream->blocked) { return; } - wev = stream->request->connection->write; + fc = stream->request->connection; - if (!wev->delayed) { - stream->handled = 1; - ngx_queue_insert_tail(&h2c->posted, &stream->queue); + if (!fc->error && (stream->exhausted || fc->write->delayed)) { + return; } + + stream->handled = 1; + ngx_queue_insert_tail(&h2c->posted, &stream->queue); } diff --git a/src/http/v2/ngx_http_v2_module.c b/src/http/v2/ngx_http_v2_module.c index 5a4561c..b7d99e0 100644 --- a/src/http/v2/ngx_http_v2_module.c +++ b/src/http/v2/ngx_http_v2_module.c @@ -30,6 +30,7 @@ static char *ngx_http_v2_merge_loc_conf(ngx_conf_t *cf, void *parent, static char *ngx_http_v2_recv_buffer_size(ngx_conf_t *cf, void *post, void *data); static char *ngx_http_v2_pool_size(ngx_conf_t *cf, void *post, void *data); +static char *ngx_http_v2_preread_size(ngx_conf_t *cf, void *post, void *data); static char *ngx_http_v2_streams_index_mask(ngx_conf_t *cf, void *post, void *data); static char *ngx_http_v2_chunk_size(ngx_conf_t *cf, void *post, void *data); @@ -41,6 +42,8 @@ static ngx_conf_post_t ngx_http_v2_recv_buffer_size_post = { ngx_http_v2_recv_buffer_size }; static ngx_conf_post_t ngx_http_v2_pool_size_post = { ngx_http_v2_pool_size }; +static ngx_conf_post_t ngx_http_v2_preread_size_post = + { ngx_http_v2_preread_size }; static ngx_conf_post_t ngx_http_v2_streams_index_mask_post = { ngx_http_v2_streams_index_mask }; static ngx_conf_post_t ngx_http_v2_chunk_size_post = @@ -84,6 +87,13 @@ static ngx_command_t ngx_http_v2_commands[] = { offsetof(ngx_http_v2_srv_conf_t, max_header_size), NULL }, + { ngx_string("http2_body_preread_size"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_http_v2_srv_conf_t, preread_size), + &ngx_http_v2_preread_size_post }, + { ngx_string("http2_streams_index_size"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, ngx_conf_set_num_slot, @@ -316,6 +326,8 @@ ngx_http_v2_create_srv_conf(ngx_conf_t *cf) h2scf->max_field_size = NGX_CONF_UNSET_SIZE; h2scf->max_header_size = NGX_CONF_UNSET_SIZE; + h2scf->preread_size = NGX_CONF_UNSET_SIZE; + h2scf->streams_index_mask = NGX_CONF_UNSET_UINT; h2scf->recv_timeout = NGX_CONF_UNSET_MSEC; @@ -341,6 +353,8 @@ ngx_http_v2_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_size_value(conf->max_header_size, prev->max_header_size, 16384); + ngx_conf_merge_size_value(conf->preread_size, prev->preread_size, 65536); + ngx_conf_merge_uint_value(conf->streams_index_mask, prev->streams_index_mask, 32 - 1); @@ -419,6 +433,23 @@ ngx_http_v2_pool_size(ngx_conf_t *cf, void *post, void *data) } +static char * +ngx_http_v2_preread_size(ngx_conf_t *cf, void *post, void *data) +{ + size_t *sp = data; + + if (*sp > NGX_HTTP_V2_MAX_WINDOW) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "the maximum body preread buffer size is %uz", + NGX_HTTP_V2_MAX_WINDOW); + + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; +} + + static char * ngx_http_v2_streams_index_mask(ngx_conf_t *cf, void *post, void *data) { diff --git a/src/http/v2/ngx_http_v2_module.h b/src/http/v2/ngx_http_v2_module.h index 95cc7d8..91f97c2 100644 --- a/src/http/v2/ngx_http_v2_module.h +++ b/src/http/v2/ngx_http_v2_module.h @@ -25,6 +25,7 @@ typedef struct { ngx_uint_t concurrent_streams; size_t max_field_size; size_t max_header_size; + size_t preread_size; ngx_uint_t streams_index_mask; ngx_msec_t recv_timeout; ngx_msec_t idle_timeout; diff --git a/src/mail/ngx_mail.c b/src/mail/ngx_mail.c index 6ad5a67..e5a77b0 100644 --- a/src/mail/ngx_mail.c +++ b/src/mail/ngx_mail.c @@ -228,35 +228,11 @@ ngx_mail_add_ports(ngx_conf_t *cf, ngx_array_t *ports, in_port_t p; ngx_uint_t i; struct sockaddr *sa; - struct sockaddr_in *sin; ngx_mail_conf_port_t *port; ngx_mail_conf_addr_t *addr; -#if (NGX_HAVE_INET6) - struct sockaddr_in6 *sin6; -#endif - sa = &listen->u.sockaddr; - - switch (sa->sa_family) { - -#if (NGX_HAVE_INET6) - case AF_INET6: - sin6 = &listen->u.sockaddr_in6; - p = sin6->sin6_port; - break; -#endif - -#if (NGX_HAVE_UNIX_DOMAIN) - case AF_UNIX: - p = 0; - break; -#endif - - default: /* AF_INET */ - sin = &listen->u.sockaddr_in; - p = sin->sin_port; - break; - } + sa = &listen->sockaddr.sockaddr; + p = ngx_inet_get_port(sa); port = ports->elts; for (i = 0; i < ports->nelts; i++) { @@ -340,7 +316,7 @@ ngx_mail_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports) continue; } - ls = ngx_create_listening(cf, &addr[i].opt.u.sockaddr, + ls = ngx_create_listening(cf, &addr[i].opt.sockaddr.sockaddr, addr[i].opt.socklen); if (ls == NULL) { return NGX_CONF_ERROR; @@ -423,7 +399,7 @@ ngx_mail_add_addrs(ngx_conf_t *cf, ngx_mail_port_t *mport, for (i = 0; i < mport->naddrs; i++) { - sin = &addr[i].opt.u.sockaddr_in; + sin = &addr[i].opt.sockaddr.sockaddr_in; addrs[i].addr = sin->sin_addr.s_addr; addrs[i].conf.ctx = addr[i].opt.ctx; @@ -431,8 +407,8 @@ ngx_mail_add_addrs(ngx_conf_t *cf, ngx_mail_port_t *mport, addrs[i].conf.ssl = addr[i].opt.ssl; #endif - len = ngx_sock_ntop(&addr[i].opt.u.sockaddr, addr[i].opt.socklen, buf, - NGX_SOCKADDR_STRLEN, 1); + len = ngx_sock_ntop(&addr[i].opt.sockaddr.sockaddr, addr[i].opt.socklen, + buf, NGX_SOCKADDR_STRLEN, 1); p = ngx_pnalloc(cf->pool, len); if (p == NULL) { @@ -472,7 +448,7 @@ ngx_mail_add_addrs6(ngx_conf_t *cf, ngx_mail_port_t *mport, for (i = 0; i < mport->naddrs; i++) { - sin6 = &addr[i].opt.u.sockaddr_in6; + sin6 = &addr[i].opt.sockaddr.sockaddr_in6; addrs6[i].addr6 = sin6->sin6_addr; addrs6[i].conf.ctx = addr[i].opt.ctx; @@ -480,8 +456,8 @@ ngx_mail_add_addrs6(ngx_conf_t *cf, ngx_mail_port_t *mport, addrs6[i].conf.ssl = addr[i].opt.ssl; #endif - len = ngx_sock_ntop(&addr[i].opt.u.sockaddr, addr[i].opt.socklen, buf, - NGX_SOCKADDR_STRLEN, 1); + len = ngx_sock_ntop(&addr[i].opt.sockaddr.sockaddr, addr[i].opt.socklen, + buf, NGX_SOCKADDR_STRLEN, 1); p = ngx_pnalloc(cf->pool, len); if (p == NULL) { diff --git a/src/mail/ngx_mail.h b/src/mail/ngx_mail.h index bfbf768..ae1aa41 100644 --- a/src/mail/ngx_mail.h +++ b/src/mail/ngx_mail.h @@ -27,18 +27,7 @@ typedef struct { typedef struct { - union { - struct sockaddr sockaddr; - struct sockaddr_in sockaddr_in; -#if (NGX_HAVE_INET6) - struct sockaddr_in6 sockaddr_in6; -#endif -#if (NGX_HAVE_UNIX_DOMAIN) - struct sockaddr_un sockaddr_un; -#endif - u_char sockaddr_data[NGX_SOCKADDRLEN]; - } u; - + ngx_sockaddr_t sockaddr; socklen_t socklen; /* server ctx */ diff --git a/src/mail/ngx_mail_auth_http_module.c b/src/mail/ngx_mail_auth_http_module.c index 39f9b17..a94434a 100644 --- a/src/mail/ngx_mail_auth_http_module.c +++ b/src/mail/ngx_mail_auth_http_module.c @@ -462,15 +462,11 @@ static void ngx_mail_auth_http_process_headers(ngx_mail_session_t *s, ngx_mail_auth_http_ctx_t *ctx) { - u_char *p; - time_t timer; - size_t len, size; - ngx_int_t rc, port, n; - ngx_addr_t *peer; - struct sockaddr_in *sin; -#if (NGX_HAVE_INET6) - struct sockaddr_in6 *sin6; -#endif + u_char *p; + time_t timer; + size_t len, size; + ngx_int_t rc, port, n; + ngx_addr_t *peer; ngx_log_debug0(NGX_LOG_DEBUG_MAIL, s->connection->log, 0, "mail auth http process headers"); @@ -813,20 +809,7 @@ ngx_mail_auth_http_process_headers(ngx_mail_session_t *s, return; } - switch (peer->sockaddr->sa_family) { - -#if (NGX_HAVE_INET6) - case AF_INET6: - sin6 = (struct sockaddr_in6 *) peer->sockaddr; - sin6->sin6_port = htons((in_port_t) port); - break; -#endif - - default: /* AF_INET */ - sin = (struct sockaddr_in *) peer->sockaddr; - sin->sin_port = htons((in_port_t) port); - break; - } + ngx_inet_set_port(peer->sockaddr, (in_port_t) port); len = ctx->addr.len + 1 + ctx->port.len; diff --git a/src/mail/ngx_mail_core_module.c b/src/mail/ngx_mail_core_module.c index 8ea8ea9..d992402 100644 --- a/src/mail/ngx_mail_core_module.c +++ b/src/mail/ngx_mail_core_module.c @@ -288,19 +288,12 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_mail_core_srv_conf_t *cscf = conf; - size_t len, off; - in_port_t port; ngx_str_t *value; ngx_url_t u; ngx_uint_t i, m; - struct sockaddr *sa; ngx_mail_listen_t *ls; ngx_mail_module_t *module; - struct sockaddr_in *sin; ngx_mail_core_main_conf_t *cmcf; -#if (NGX_HAVE_INET6) - struct sockaddr_in6 *sin6; -#endif value = cf->args->elts; @@ -325,49 +318,13 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) for (i = 0; i < cmcf->listen.nelts; i++) { - sa = &ls[i].u.sockaddr; - - if (sa->sa_family != u.family) { - continue; - } - - switch (sa->sa_family) { - -#if (NGX_HAVE_INET6) - case AF_INET6: - off = offsetof(struct sockaddr_in6, sin6_addr); - len = 16; - sin6 = &ls[i].u.sockaddr_in6; - port = ntohs(sin6->sin6_port); - break; -#endif - -#if (NGX_HAVE_UNIX_DOMAIN) - case AF_UNIX: - off = offsetof(struct sockaddr_un, sun_path); - len = sizeof(((struct sockaddr_un *) sa)->sun_path); - port = 0; - break; -#endif - - default: /* AF_INET */ - off = offsetof(struct sockaddr_in, sin_addr); - len = 4; - sin = &ls[i].u.sockaddr_in; - port = ntohs(sin->sin_port); - break; - } - - if (ngx_memcmp(ls[i].u.sockaddr_data + off, u.sockaddr + off, len) - != 0) + if (ngx_cmp_sockaddr(&ls[i].sockaddr.sockaddr, ls[i].socklen, + (struct sockaddr *) &u.sockaddr, u.socklen, 1) + != NGX_OK) { continue; } - if (port != u.port) { - continue; - } - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "duplicate \"%V\" address and port pair", &u.url); return NGX_CONF_ERROR; @@ -380,7 +337,7 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ngx_memzero(ls, sizeof(ngx_mail_listen_t)); - ngx_memcpy(&ls->u.sockaddr, u.sockaddr, u.socklen); + ngx_memcpy(&ls->sockaddr.sockaddr, &u.sockaddr, u.socklen); ls->socklen = u.socklen; ls->backlog = NGX_LISTEN_BACKLOG; @@ -434,11 +391,10 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) { #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) + size_t len; u_char buf[NGX_SOCKADDR_STRLEN]; - sa = &ls->u.sockaddr; - - if (sa->sa_family == AF_INET6) { + if (ls->sockaddr.sockaddr.sa_family == AF_INET6) { if (ngx_strcmp(&value[i].data[10], "n") == 0) { ls->ipv6only = 1; @@ -456,7 +412,7 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ls->bind = 1; } else { - len = ngx_sock_ntop(sa, ls->socklen, buf, + len = ngx_sock_ntop(&ls->sockaddr.sockaddr, ls->socklen, buf, NGX_SOCKADDR_STRLEN, 1); ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, diff --git a/src/mail/ngx_mail_ssl_module.c b/src/mail/ngx_mail_ssl_module.c index ff5c141..11e428c 100644 --- a/src/mail/ngx_mail_ssl_module.c +++ b/src/mail/ngx_mail_ssl_module.c @@ -11,7 +11,7 @@ #define NGX_DEFAULT_CIPHERS "HIGH:!aNULL:!MD5" -#define NGX_DEFAULT_ECDH_CURVE "prime256v1" +#define NGX_DEFAULT_ECDH_CURVE "auto" static void *ngx_mail_ssl_create_conf(ngx_conf_t *cf); @@ -73,16 +73,16 @@ static ngx_command_t ngx_mail_ssl_commands[] = { { ngx_string("ssl_certificate"), NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_conf_set_str_array_slot, NGX_MAIL_SRV_CONF_OFFSET, - offsetof(ngx_mail_ssl_conf_t, certificate), + offsetof(ngx_mail_ssl_conf_t, certificates), NULL }, { ngx_string("ssl_certificate_key"), NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_conf_set_str_array_slot, NGX_MAIL_SRV_CONF_OFFSET, - offsetof(ngx_mail_ssl_conf_t, certificate_key), + offsetof(ngx_mail_ssl_conf_t, certificate_keys), NULL }, { ngx_string("ssl_password_file"), @@ -238,8 +238,6 @@ ngx_mail_ssl_create_conf(ngx_conf_t *cf) * set by ngx_pcalloc(): * * scf->protocols = 0; - * scf->certificate = { 0, NULL }; - * scf->certificate_key = { 0, NULL }; * scf->dhparam = { 0, NULL }; * scf->ecdh_curve = { 0, NULL }; * scf->client_certificate = { 0, NULL }; @@ -251,6 +249,8 @@ ngx_mail_ssl_create_conf(ngx_conf_t *cf) scf->enable = NGX_CONF_UNSET; scf->starttls = NGX_CONF_UNSET_UINT; + scf->certificates = NGX_CONF_UNSET_PTR; + scf->certificate_keys = NGX_CONF_UNSET_PTR; scf->passwords = NGX_CONF_UNSET_PTR; scf->prefer_server_ciphers = NGX_CONF_UNSET; scf->verify = NGX_CONF_UNSET_UINT; @@ -290,8 +290,9 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_uint_value(conf->verify, prev->verify, 0); ngx_conf_merge_uint_value(conf->verify_depth, prev->verify_depth, 1); - ngx_conf_merge_str_value(conf->certificate, prev->certificate, ""); - ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key, ""); + ngx_conf_merge_ptr_value(conf->certificates, prev->certificates, NULL); + ngx_conf_merge_ptr_value(conf->certificate_keys, prev->certificate_keys, + NULL); ngx_conf_merge_ptr_value(conf->passwords, prev->passwords, NULL); @@ -328,7 +329,7 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) if (*mode) { - if (conf->certificate.len == 0) { + if (conf->certificates == NULL) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate\" is defined for " "the \"%s\" directive in %s:%ui", @@ -336,7 +337,7 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) return NGX_CONF_ERROR; } - if (conf->certificate_key.len == 0) { + if (conf->certificate_keys == NULL) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate_key\" is defined for " "the \"%s\" directive in %s:%ui", @@ -344,17 +345,31 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) return NGX_CONF_ERROR; } + if (conf->certificate_keys->nelts < conf->certificates->nelts) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "no \"ssl_certificate_key\" is defined " + "for certificate \"%V\" and " + "the \"ssl\" directive in %s:%ui", + ((ngx_str_t *) conf->certificates->elts) + + conf->certificates->nelts - 1, + conf->file, conf->line); + return NGX_CONF_ERROR; + } + } else { - if (conf->certificate.len == 0) { + if (conf->certificates == NULL) { return NGX_CONF_OK; } - if (conf->certificate_key.len == 0) { + if (conf->certificate_keys == NULL + || conf->certificate_keys->nelts < conf->certificates->nelts) + { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate_key\" is defined " "for certificate \"%V\"", - &conf->certificate); + ((ngx_str_t *) conf->certificates->elts) + + conf->certificates->nelts - 1); return NGX_CONF_ERROR; } } @@ -371,8 +386,8 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) cln->handler = ngx_ssl_cleanup_ctx; cln->data = &conf->ssl; - if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate, - &conf->certificate_key, conf->passwords) + if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates, + conf->certificate_keys, conf->passwords) != NGX_OK) { return NGX_CONF_ERROR; @@ -407,24 +422,13 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) } } - if (SSL_CTX_set_cipher_list(conf->ssl.ctx, - (const char *) conf->ciphers.data) - == 0) + if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers, + conf->prefer_server_ciphers) + != NGX_OK) { - ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, - "SSL_CTX_set_cipher_list(\"%V\") failed", - &conf->ciphers); return NGX_CONF_ERROR; } - if (conf->prefer_server_ciphers) { - SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); - } - -#if (OPENSSL_VERSION_NUMBER < 0x10100001L && !defined LIBRESSL_VERSION_NUMBER) - SSL_CTX_set_tmp_rsa_callback(conf->ssl.ctx, ngx_ssl_rsa512_key_callback); -#endif - if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) { return NGX_CONF_ERROR; } diff --git a/src/mail/ngx_mail_ssl_module.h b/src/mail/ngx_mail_ssl_module.h index 296a6a2..26628d5 100644 --- a/src/mail/ngx_mail_ssl_module.h +++ b/src/mail/ngx_mail_ssl_module.h @@ -35,8 +35,9 @@ typedef struct { time_t session_timeout; - ngx_str_t certificate; - ngx_str_t certificate_key; + ngx_array_t *certificates; + ngx_array_t *certificate_keys; + ngx_str_t dhparam; ngx_str_t ecdh_curve; ngx_str_t client_certificate; diff --git a/src/os/unix/ngx_readv_chain.c b/src/os/unix/ngx_readv_chain.c index d23508e..454cfdc 100644 --- a/src/os/unix/ngx_readv_chain.c +++ b/src/os/unix/ngx_readv_chain.c @@ -51,6 +51,20 @@ ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain, off_t limit) } } +#endif + +#if (NGX_HAVE_EPOLLRDHUP) + + if (ngx_event_flags & NGX_USE_EPOLL_EVENT) { + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, + "readv: eof:%d, avail:%d", + rev->pending_eof, rev->available); + + if (!rev->available && !rev->pending_eof) { + return NGX_AGAIN; + } + } + #endif prev = NULL; @@ -149,6 +163,24 @@ ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain, off_t limit) return n; } +#endif + +#if (NGX_HAVE_EPOLLRDHUP) + + if ((ngx_event_flags & NGX_USE_EPOLL_EVENT) + && ngx_use_epoll_rdhup) + { + if (n < size) { + if (!rev->pending_eof) { + rev->ready = 0; + } + + rev->available = 0; + } + + return n; + } + #endif if (n < size && !(ngx_event_flags & NGX_USE_GREEDY_EVENT)) { diff --git a/src/os/unix/ngx_recv.c b/src/os/unix/ngx_recv.c index 5013ae3..c85fd45 100644 --- a/src/os/unix/ngx_recv.c +++ b/src/os/unix/ngx_recv.c @@ -48,6 +48,21 @@ ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size) } } +#endif + +#if (NGX_HAVE_EPOLLRDHUP) + + if (ngx_event_flags & NGX_USE_EPOLL_EVENT) { + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, + "recv: eof:%d, avail:%d", + rev->pending_eof, rev->available); + + if (!rev->available && !rev->pending_eof) { + rev->ready = 0; + return NGX_AGAIN; + } + } + #endif do { @@ -99,6 +114,24 @@ ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size) return n; } +#endif + +#if (NGX_HAVE_EPOLLRDHUP) + + if ((ngx_event_flags & NGX_USE_EPOLL_EVENT) + && ngx_use_epoll_rdhup) + { + if ((size_t) n < size) { + if (!rev->pending_eof) { + rev->ready = 0; + } + + rev->available = 0; + } + + return n; + } + #endif if ((size_t) n < size diff --git a/src/os/unix/ngx_thread_mutex.c b/src/os/unix/ngx_thread_mutex.c index 6e8385e..a0ef693 100644 --- a/src/os/unix/ngx_thread_mutex.c +++ b/src/os/unix/ngx_thread_mutex.c @@ -49,7 +49,7 @@ * for each mutex from 10 to 100 based on spin count taken * previously. * FreeBSD: Deadlock detection. The default spin count is 2000. - * It can be overriden using LIBPTHREAD_SPINLOOPS environment + * It can be overridden using LIBPTHREAD_SPINLOOPS environment * variable or by pthread_mutex_setspinloops_np(). If a lock * is still busy, sched_yield() can be called on both UP and * SMP systems. The default yield loop count is zero, but diff --git a/src/stream/ngx_stream.c b/src/stream/ngx_stream.c index 3bd8f6d..c195171 100644 --- a/src/stream/ngx_stream.c +++ b/src/stream/ngx_stream.c @@ -143,11 +143,26 @@ ngx_stream_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) } - /* parse inside the stream{} block */ - pcf = *cf; cf->ctx = ctx; + for (m = 0; cf->cycle->modules[m]; m++) { + if (cf->cycle->modules[m]->type != NGX_STREAM_MODULE) { + continue; + } + + module = cf->cycle->modules[m]->ctx; + + if (module->preconfiguration) { + if (module->preconfiguration(cf) != NGX_OK) { + return NGX_CONF_ERROR; + } + } + } + + + /* parse inside the stream{} block */ + cf->module_type = NGX_STREAM_MODULE; cf->cmd_type = NGX_STREAM_MAIN_CONF; rv = ngx_conf_parse(cf, NULL); @@ -215,6 +230,10 @@ ngx_stream_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) } } + if (ngx_stream_variables_init_vars(cf) != NGX_OK) { + return NGX_CONF_ERROR; + } + *cf = pcf; @@ -243,35 +262,11 @@ ngx_stream_add_ports(ngx_conf_t *cf, ngx_array_t *ports, in_port_t p; ngx_uint_t i; struct sockaddr *sa; - struct sockaddr_in *sin; ngx_stream_conf_port_t *port; ngx_stream_conf_addr_t *addr; -#if (NGX_HAVE_INET6) - struct sockaddr_in6 *sin6; -#endif - sa = &listen->u.sockaddr; - - switch (sa->sa_family) { - -#if (NGX_HAVE_INET6) - case AF_INET6: - sin6 = &listen->u.sockaddr_in6; - p = sin6->sin6_port; - break; -#endif - -#if (NGX_HAVE_UNIX_DOMAIN) - case AF_UNIX: - p = 0; - break; -#endif - - default: /* AF_INET */ - sin = &listen->u.sockaddr_in; - p = sin->sin_port; - break; - } + sa = &listen->sockaddr.sockaddr; + p = ngx_inet_get_port(sa); port = ports->elts; for (i = 0; i < ports->nelts; i++) { @@ -359,7 +354,7 @@ ngx_stream_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports) continue; } - ls = ngx_create_listening(cf, &addr[i].opt.u.sockaddr, + ls = ngx_create_listening(cf, &addr[i].opt.sockaddr.sockaddr, addr[i].opt.socklen); if (ls == NULL) { return NGX_CONF_ERROR; @@ -453,7 +448,7 @@ ngx_stream_add_addrs(ngx_conf_t *cf, ngx_stream_port_t *stport, for (i = 0; i < stport->naddrs; i++) { - sin = &addr[i].opt.u.sockaddr_in; + sin = &addr[i].opt.sockaddr.sockaddr_in; addrs[i].addr = sin->sin_addr.s_addr; addrs[i].conf.ctx = addr[i].opt.ctx; @@ -461,8 +456,8 @@ ngx_stream_add_addrs(ngx_conf_t *cf, ngx_stream_port_t *stport, addrs[i].conf.ssl = addr[i].opt.ssl; #endif - len = ngx_sock_ntop(&addr[i].opt.u.sockaddr, addr[i].opt.socklen, buf, - NGX_SOCKADDR_STRLEN, 1); + len = ngx_sock_ntop(&addr[i].opt.sockaddr.sockaddr, addr[i].opt.socklen, + buf, NGX_SOCKADDR_STRLEN, 1); p = ngx_pnalloc(cf->pool, len); if (p == NULL) { @@ -502,7 +497,7 @@ ngx_stream_add_addrs6(ngx_conf_t *cf, ngx_stream_port_t *stport, for (i = 0; i < stport->naddrs; i++) { - sin6 = &addr[i].opt.u.sockaddr_in6; + sin6 = &addr[i].opt.sockaddr.sockaddr_in6; addrs6[i].addr6 = sin6->sin6_addr; addrs6[i].conf.ctx = addr[i].opt.ctx; @@ -510,8 +505,8 @@ ngx_stream_add_addrs6(ngx_conf_t *cf, ngx_stream_port_t *stport, addrs6[i].conf.ssl = addr[i].opt.ssl; #endif - len = ngx_sock_ntop(&addr[i].opt.u.sockaddr, addr[i].opt.socklen, buf, - NGX_SOCKADDR_STRLEN, 1); + len = ngx_sock_ntop(&addr[i].opt.sockaddr.sockaddr, addr[i].opt.socklen, + buf, NGX_SOCKADDR_STRLEN, 1); p = ngx_pnalloc(cf->pool, len); if (p == NULL) { diff --git a/src/stream/ngx_stream.h b/src/stream/ngx_stream.h index 49efa45..807ab5b 100644 --- a/src/stream/ngx_stream.h +++ b/src/stream/ngx_stream.h @@ -20,75 +20,66 @@ typedef struct ngx_stream_session_s ngx_stream_session_t; +#include +#include #include #include typedef struct { - void **main_conf; - void **srv_conf; + void **main_conf; + void **srv_conf; } ngx_stream_conf_ctx_t; typedef struct { - union { - struct sockaddr sockaddr; - struct sockaddr_in sockaddr_in; -#if (NGX_HAVE_INET6) - struct sockaddr_in6 sockaddr_in6; -#endif -#if (NGX_HAVE_UNIX_DOMAIN) - struct sockaddr_un sockaddr_un; -#endif - u_char sockaddr_data[NGX_SOCKADDRLEN]; - } u; - - socklen_t socklen; + ngx_sockaddr_t sockaddr; + socklen_t socklen; /* server ctx */ - ngx_stream_conf_ctx_t *ctx; + ngx_stream_conf_ctx_t *ctx; - unsigned bind:1; - unsigned wildcard:1; + unsigned bind:1; + unsigned wildcard:1; #if (NGX_STREAM_SSL) - unsigned ssl:1; + unsigned ssl:1; #endif #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) - unsigned ipv6only:1; + unsigned ipv6only:1; #endif #if (NGX_HAVE_REUSEPORT) - unsigned reuseport:1; + unsigned reuseport:1; #endif - unsigned so_keepalive:2; + unsigned so_keepalive:2; #if (NGX_HAVE_KEEPALIVE_TUNABLE) - int tcp_keepidle; - int tcp_keepintvl; - int tcp_keepcnt; + int tcp_keepidle; + int tcp_keepintvl; + int tcp_keepcnt; #endif - int backlog; - int type; + int backlog; + int type; } ngx_stream_listen_t; typedef struct { - ngx_stream_conf_ctx_t *ctx; - ngx_str_t addr_text; + ngx_stream_conf_ctx_t *ctx; + ngx_str_t addr_text; #if (NGX_STREAM_SSL) - ngx_uint_t ssl; /* unsigned ssl:1; */ + ngx_uint_t ssl; /* unsigned ssl:1; */ #endif } ngx_stream_addr_conf_t; typedef struct { - in_addr_t addr; - ngx_stream_addr_conf_t conf; + in_addr_t addr; + ngx_stream_addr_conf_t conf; } ngx_stream_in_addr_t; #if (NGX_HAVE_INET6) typedef struct { - struct in6_addr addr6; - ngx_stream_addr_conf_t conf; + struct in6_addr addr6; + ngx_stream_addr_conf_t conf; } ngx_stream_in6_addr_t; #endif @@ -96,21 +87,21 @@ typedef struct { typedef struct { /* ngx_stream_in_addr_t or ngx_stream_in6_addr_t */ - void *addrs; - ngx_uint_t naddrs; + void *addrs; + ngx_uint_t naddrs; } ngx_stream_port_t; typedef struct { - int family; - int type; - in_port_t port; - ngx_array_t addrs; /* array of ngx_stream_conf_addr_t */ + int family; + int type; + in_port_t port; + ngx_array_t addrs; /* array of ngx_stream_conf_addr_t */ } ngx_stream_conf_port_t; typedef struct { - ngx_stream_listen_t opt; + ngx_stream_listen_t opt; } ngx_stream_conf_addr_t; @@ -118,10 +109,21 @@ typedef ngx_int_t (*ngx_stream_access_pt)(ngx_stream_session_t *s); typedef struct { - ngx_array_t servers; /* ngx_stream_core_srv_conf_t */ - ngx_array_t listen; /* ngx_stream_listen_t */ - ngx_stream_access_pt limit_conn_handler; - ngx_stream_access_pt access_handler; + ngx_array_t servers; /* ngx_stream_core_srv_conf_t */ + ngx_array_t listen; /* ngx_stream_listen_t */ + + ngx_stream_access_pt limit_conn_handler; + ngx_stream_access_pt access_handler; + + ngx_hash_t variables_hash; + + ngx_array_t variables; /* ngx_stream_variable_t */ + ngx_uint_t ncaptures; + + ngx_uint_t variables_hash_max_size; + ngx_uint_t variables_hash_bucket_size; + + ngx_hash_keys_arrays_t *variables_keys; } ngx_stream_core_main_conf_t; @@ -129,41 +131,57 @@ typedef void (*ngx_stream_handler_pt)(ngx_stream_session_t *s); typedef struct { - ngx_stream_handler_pt handler; - ngx_stream_conf_ctx_t *ctx; - u_char *file_name; - ngx_int_t line; - ngx_log_t *error_log; - ngx_flag_t tcp_nodelay; + ngx_stream_handler_pt handler; + + ngx_stream_conf_ctx_t *ctx; + + u_char *file_name; + ngx_int_t line; + + ngx_flag_t tcp_nodelay; + + ngx_log_t *error_log; + + ngx_msec_t resolver_timeout; + ngx_resolver_t *resolver; } ngx_stream_core_srv_conf_t; struct ngx_stream_session_s { - uint32_t signature; /* "STRM" */ + uint32_t signature; /* "STRM" */ - ngx_connection_t *connection; + ngx_connection_t *connection; - off_t received; + off_t received; - ngx_log_handler_pt log_handler; + ngx_log_handler_pt log_handler; - void **ctx; - void **main_conf; - void **srv_conf; + void **ctx; + void **main_conf; + void **srv_conf; - ngx_stream_upstream_t *upstream; + ngx_stream_upstream_t *upstream; + + ngx_stream_variable_value_t *variables; + +#if (NGX_PCRE) + ngx_uint_t ncaptures; + int *captures; + u_char *captures_data; +#endif }; typedef struct { - ngx_int_t (*postconfiguration)(ngx_conf_t *cf); + ngx_int_t (*preconfiguration)(ngx_conf_t *cf); + ngx_int_t (*postconfiguration)(ngx_conf_t *cf); - void *(*create_main_conf)(ngx_conf_t *cf); - char *(*init_main_conf)(ngx_conf_t *cf, void *conf); + void *(*create_main_conf)(ngx_conf_t *cf); + char *(*init_main_conf)(ngx_conf_t *cf, void *conf); - void *(*create_srv_conf)(ngx_conf_t *cf); - char *(*merge_srv_conf)(ngx_conf_t *cf, void *prev, - void *conf); + void *(*create_srv_conf)(ngx_conf_t *cf); + char *(*merge_srv_conf)(ngx_conf_t *cf, void *prev, + void *conf); } ngx_stream_module_t; diff --git a/src/stream/ngx_stream_access_module.c b/src/stream/ngx_stream_access_module.c index 64869d2..6985d36 100644 --- a/src/stream/ngx_stream_access_module.c +++ b/src/stream/ngx_stream_access_module.c @@ -88,6 +88,7 @@ static ngx_command_t ngx_stream_access_commands[] = { static ngx_stream_module_t ngx_stream_access_module_ctx = { + NULL, /* preconfiguration */ ngx_stream_access_init, /* postconfiguration */ NULL, /* create main configuration */ diff --git a/src/stream/ngx_stream_core_module.c b/src/stream/ngx_stream_core_module.c index ebc2b1c..70b9e2d 100644 --- a/src/stream/ngx_stream_core_module.c +++ b/src/stream/ngx_stream_core_module.c @@ -10,7 +10,9 @@ #include +static ngx_int_t ngx_stream_core_preconfiguration(ngx_conf_t *cf); static void *ngx_stream_core_create_main_conf(ngx_conf_t *cf); +static char *ngx_stream_core_init_main_conf(ngx_conf_t *cf, void *conf); static void *ngx_stream_core_create_srv_conf(ngx_conf_t *cf); static char *ngx_stream_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child); @@ -20,10 +22,26 @@ static char *ngx_stream_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +static char *ngx_stream_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); static ngx_command_t ngx_stream_core_commands[] = { + { ngx_string("variables_hash_max_size"), + NGX_STREAM_MAIN_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_STREAM_MAIN_CONF_OFFSET, + offsetof(ngx_stream_core_main_conf_t, variables_hash_max_size), + NULL }, + + { ngx_string("variables_hash_bucket_size"), + NGX_STREAM_MAIN_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_STREAM_MAIN_CONF_OFFSET, + offsetof(ngx_stream_core_main_conf_t, variables_hash_bucket_size), + NULL }, + { ngx_string("server"), NGX_STREAM_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS, ngx_stream_core_server, @@ -45,6 +63,20 @@ static ngx_command_t ngx_stream_core_commands[] = { 0, NULL }, + { ngx_string("resolver"), + NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_1MORE, + ngx_stream_core_resolver, + NGX_STREAM_SRV_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("resolver_timeout"), + NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + NGX_STREAM_SRV_CONF_OFFSET, + offsetof(ngx_stream_core_srv_conf_t, resolver_timeout), + NULL }, + { ngx_string("tcp_nodelay"), NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG, ngx_conf_set_flag_slot, @@ -57,10 +89,11 @@ static ngx_command_t ngx_stream_core_commands[] = { static ngx_stream_module_t ngx_stream_core_module_ctx = { + ngx_stream_core_preconfiguration, /* preconfiguration */ NULL, /* postconfiguration */ ngx_stream_core_create_main_conf, /* create main configuration */ - NULL, /* init main configuration */ + ngx_stream_core_init_main_conf, /* init main configuration */ ngx_stream_core_create_srv_conf, /* create server configuration */ ngx_stream_core_merge_srv_conf /* merge server configuration */ @@ -83,6 +116,13 @@ ngx_module_t ngx_stream_core_module = { }; +static ngx_int_t +ngx_stream_core_preconfiguration(ngx_conf_t *cf) +{ + return ngx_stream_variables_add_core_vars(cf); +} + + static void * ngx_stream_core_create_main_conf(ngx_conf_t *cf) { @@ -106,10 +146,32 @@ ngx_stream_core_create_main_conf(ngx_conf_t *cf) return NULL; } + cmcf->variables_hash_max_size = NGX_CONF_UNSET_UINT; + cmcf->variables_hash_bucket_size = NGX_CONF_UNSET_UINT; + return cmcf; } +static char * +ngx_stream_core_init_main_conf(ngx_conf_t *cf, void *conf) +{ + ngx_stream_core_main_conf_t *cmcf = conf; + + ngx_conf_init_uint_value(cmcf->variables_hash_max_size, 1024); + ngx_conf_init_uint_value(cmcf->variables_hash_bucket_size, 64); + + cmcf->variables_hash_bucket_size = + ngx_align(cmcf->variables_hash_bucket_size, ngx_cacheline_size); + + if (cmcf->ncaptures) { + cmcf->ncaptures = (cmcf->ncaptures + 1) * 3; + } + + return NGX_CONF_OK; +} + + static void * ngx_stream_core_create_srv_conf(ngx_conf_t *cf) { @@ -129,6 +191,7 @@ ngx_stream_core_create_srv_conf(ngx_conf_t *cf) cscf->file_name = cf->conf_file->file.name.data; cscf->line = cf->conf_file->line; + cscf->resolver_timeout = NGX_CONF_UNSET_MSEC; cscf->tcp_nodelay = NGX_CONF_UNSET; return cscf; @@ -141,6 +204,27 @@ ngx_stream_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) ngx_stream_core_srv_conf_t *prev = parent; ngx_stream_core_srv_conf_t *conf = child; + ngx_conf_merge_msec_value(conf->resolver_timeout, + prev->resolver_timeout, 30000); + + if (conf->resolver == NULL) { + + if (prev->resolver == NULL) { + + /* + * create dummy resolver in stream {} context + * to inherit it in all servers + */ + + prev->resolver = ngx_resolver_create(cf, NULL, 0); + if (prev->resolver == NULL) { + return NGX_CONF_ERROR; + } + } + + conf->resolver = prev->resolver; + } + if (conf->handler == NULL) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no handler for server in %s:%ui", @@ -248,18 +332,11 @@ ngx_stream_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) static char * ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { - size_t len, off; - in_port_t port; ngx_str_t *value; ngx_url_t u; ngx_uint_t i, backlog; - struct sockaddr *sa; - struct sockaddr_in *sin; - ngx_stream_listen_t *ls; + ngx_stream_listen_t *ls, *als; ngx_stream_core_main_conf_t *cmcf; -#if (NGX_HAVE_INET6) - struct sockaddr_in6 *sin6; -#endif value = cf->args->elts; @@ -280,58 +357,6 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module); - ls = cmcf->listen.elts; - - for (i = 0; i < cmcf->listen.nelts; i++) { - - sa = &ls[i].u.sockaddr; - - if (sa->sa_family != u.family) { - continue; - } - - switch (sa->sa_family) { - -#if (NGX_HAVE_INET6) - case AF_INET6: - off = offsetof(struct sockaddr_in6, sin6_addr); - len = 16; - sin6 = &ls[i].u.sockaddr_in6; - port = sin6->sin6_port; - break; -#endif - -#if (NGX_HAVE_UNIX_DOMAIN) - case AF_UNIX: - off = offsetof(struct sockaddr_un, sun_path); - len = sizeof(((struct sockaddr_un *) sa)->sun_path); - port = 0; - break; -#endif - - default: /* AF_INET */ - off = offsetof(struct sockaddr_in, sin_addr); - len = 4; - sin = &ls[i].u.sockaddr_in; - port = sin->sin_port; - break; - } - - if (ngx_memcmp(ls[i].u.sockaddr_data + off, u.sockaddr + off, len) - != 0) - { - continue; - } - - if (port != u.port) { - continue; - } - - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "duplicate \"%V\" address and port pair", &u.url); - return NGX_CONF_ERROR; - } - ls = ngx_array_push(&cmcf->listen); if (ls == NULL) { return NGX_CONF_ERROR; @@ -339,7 +364,7 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ngx_memzero(ls, sizeof(ngx_stream_listen_t)); - ngx_memcpy(&ls->u.sockaddr, u.sockaddr, u.socklen); + ngx_memcpy(&ls->sockaddr.sockaddr, &u.sockaddr, u.socklen); ls->socklen = u.socklen; ls->backlog = NGX_LISTEN_BACKLOG; @@ -384,11 +409,10 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) { #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) + size_t len; u_char buf[NGX_SOCKADDR_STRLEN]; - sa = &ls->u.sockaddr; - - if (sa->sa_family == AF_INET6) { + if (ls->sockaddr.sockaddr.sa_family == AF_INET6) { if (ngx_strcmp(&value[i].data[10], "n") == 0) { ls->ipv6only = 1; @@ -406,7 +430,7 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ls->bind = 1; } else { - len = ngx_sock_ntop(sa, ls->socklen, buf, + len = ngx_sock_ntop(&ls->sockaddr.sockaddr, ls->socklen, buf, NGX_SOCKADDR_STRLEN, 1); ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, @@ -558,5 +582,46 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) } } + als = cmcf->listen.elts; + + for (i = 0; i < cmcf->listen.nelts - 1; i++) { + if (ls->type != als[i].type) { + continue; + } + + if (ngx_cmp_sockaddr(&als[i].sockaddr.sockaddr, als[i].socklen, + &ls->sockaddr.sockaddr, ls->socklen, 1) + != NGX_OK) + { + continue; + } + + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "duplicate \"%V\" address and port pair", &u.url); + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; +} + + +static char * +ngx_stream_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_stream_core_srv_conf_t *cscf = conf; + + ngx_str_t *value; + + if (cscf->resolver) { + return "is duplicate"; + } + + value = cf->args->elts; + + cscf->resolver = ngx_resolver_create(cf, &value[1], cf->args->nelts - 1); + if (cscf->resolver == NULL) { + return NGX_CONF_ERROR; + } + return NGX_CONF_OK; } diff --git a/src/stream/ngx_stream_geo_module.c b/src/stream/ngx_stream_geo_module.c new file mode 100644 index 0000000..ed1a488 --- /dev/null +++ b/src/stream/ngx_stream_geo_module.c @@ -0,0 +1,1572 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + + +typedef struct { + ngx_stream_variable_value_t *value; + u_short start; + u_short end; +} ngx_stream_geo_range_t; + + +typedef struct { + ngx_radix_tree_t *tree; +#if (NGX_HAVE_INET6) + ngx_radix_tree_t *tree6; +#endif +} ngx_stream_geo_trees_t; + + +typedef struct { + ngx_stream_geo_range_t **low; + ngx_stream_variable_value_t *default_value; +} ngx_stream_geo_high_ranges_t; + + +typedef struct { + ngx_str_node_t sn; + ngx_stream_variable_value_t *value; + size_t offset; +} ngx_stream_geo_variable_value_node_t; + + +typedef struct { + ngx_stream_variable_value_t *value; + ngx_str_t *net; + ngx_stream_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_pool_t *pool; + ngx_pool_t *temp_pool; + + size_t data_size; + + ngx_str_t include_name; + ngx_uint_t includes; + ngx_uint_t entries; + + unsigned ranges:1; + unsigned outside_entries:1; + unsigned allow_binary_include:1; + unsigned binary_include:1; +} ngx_stream_geo_conf_ctx_t; + + +typedef struct { + union { + ngx_stream_geo_trees_t trees; + ngx_stream_geo_high_ranges_t high; + } u; + + ngx_int_t index; +} ngx_stream_geo_ctx_t; + + +static ngx_int_t ngx_stream_geo_addr(ngx_stream_session_t *s, + ngx_stream_geo_ctx_t *ctx, ngx_addr_t *addr); + +static char *ngx_stream_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); +static char *ngx_stream_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf); +static char *ngx_stream_geo_range(ngx_conf_t *cf, + ngx_stream_geo_conf_ctx_t *ctx, ngx_str_t *value); +static char *ngx_stream_geo_add_range(ngx_conf_t *cf, + ngx_stream_geo_conf_ctx_t *ctx, in_addr_t start, in_addr_t end); +static ngx_uint_t ngx_stream_geo_delete_range(ngx_conf_t *cf, + ngx_stream_geo_conf_ctx_t *ctx, in_addr_t start, in_addr_t end); +static char *ngx_stream_geo_cidr(ngx_conf_t *cf, + ngx_stream_geo_conf_ctx_t *ctx, ngx_str_t *value); +static char *ngx_stream_geo_cidr_add(ngx_conf_t *cf, + ngx_stream_geo_conf_ctx_t *ctx, ngx_cidr_t *cidr, ngx_str_t *value, + ngx_str_t *net); +static ngx_stream_variable_value_t *ngx_stream_geo_value(ngx_conf_t *cf, + ngx_stream_geo_conf_ctx_t *ctx, ngx_str_t *value); +static ngx_int_t ngx_stream_geo_cidr_value(ngx_conf_t *cf, ngx_str_t *net, + ngx_cidr_t *cidr); +static char *ngx_stream_geo_include(ngx_conf_t *cf, + ngx_stream_geo_conf_ctx_t *ctx, ngx_str_t *name); +static ngx_int_t ngx_stream_geo_include_binary_base(ngx_conf_t *cf, + ngx_stream_geo_conf_ctx_t *ctx, ngx_str_t *name); +static void ngx_stream_geo_create_binary_base(ngx_stream_geo_conf_ctx_t *ctx); +static u_char *ngx_stream_geo_copy_values(u_char *base, u_char *p, + ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); + + +static ngx_command_t ngx_stream_geo_commands[] = { + + { ngx_string("geo"), + NGX_STREAM_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE12, + ngx_stream_geo_block, + 0, + 0, + NULL }, + + ngx_null_command +}; + + +static ngx_stream_module_t ngx_stream_geo_module_ctx = { + NULL, /* preconfiguration */ + NULL, /* postconfiguration */ + + NULL, /* create main configuration */ + NULL, /* init main configuration */ + + NULL, /* create server configuration */ + NULL /* merge server configuration */ +}; + + +ngx_module_t ngx_stream_geo_module = { + NGX_MODULE_V1, + &ngx_stream_geo_module_ctx, /* module context */ + ngx_stream_geo_commands, /* module directives */ + NGX_STREAM_MODULE, /* module type */ + NULL, /* init master */ + NULL, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + + +typedef struct { + u_char GEORNG[6]; + u_char version; + u_char ptr_size; + uint32_t endianness; + uint32_t crc32; +} ngx_stream_geo_header_t; + + +static ngx_stream_geo_header_t ngx_stream_geo_header = { + { 'G', 'E', 'O', 'R', 'N', 'G' }, 0, sizeof(void *), 0x12345678, 0 +}; + + +/* geo range is AF_INET only */ + +static ngx_int_t +ngx_stream_geo_cidr_variable(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data) +{ + ngx_stream_geo_ctx_t *ctx = (ngx_stream_geo_ctx_t *) data; + + in_addr_t inaddr; + ngx_addr_t addr; + struct sockaddr_in *sin; + ngx_stream_variable_value_t *vv; +#if (NGX_HAVE_INET6) + u_char *p; + struct in6_addr *inaddr6; +#endif + + if (ngx_stream_geo_addr(s, ctx, &addr) != NGX_OK) { + vv = (ngx_stream_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_stream_variable_value_t *) + ngx_radix32tree_find(ctx->u.trees.tree, inaddr); + + } else { + vv = (ngx_stream_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_stream_variable_value_t *) + ngx_radix32tree_find(ctx->u.trees.tree, inaddr); + + break; + } + +done: + + *v = *vv; + + ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0, + "stream geo: %v", v); + + return NGX_OK; +} + + +static ngx_int_t +ngx_stream_geo_range_variable(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data) +{ + ngx_stream_geo_ctx_t *ctx = (ngx_stream_geo_ctx_t *) data; + + in_addr_t inaddr; + ngx_addr_t addr; + ngx_uint_t n; + struct sockaddr_in *sin; + ngx_stream_geo_range_t *range; +#if (NGX_HAVE_INET6) + u_char *p; + struct in6_addr *inaddr6; +#endif + + *v = *ctx->u.high.default_value; + + if (ngx_stream_geo_addr(s, ctx, &addr) == NGX_OK) { + + switch (addr.sockaddr->sa_family) { + +#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; + } + + 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_STREAM, s->connection->log, 0, + "stream geo: %v", v); + + return NGX_OK; +} + + +static ngx_int_t +ngx_stream_geo_addr(ngx_stream_session_t *s, ngx_stream_geo_ctx_t *ctx, + ngx_addr_t *addr) +{ + ngx_stream_variable_value_t *v; + + if (ctx->index == -1) { + ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0, + "stream geo started: %V", &s->connection->addr_text); + + addr->sockaddr = s->connection->sockaddr; + addr->socklen = s->connection->socklen; + /* addr->name = s->connection->addr_text; */ + + return NGX_OK; + } + + v = ngx_stream_get_flushed_variable(s, ctx->index); + + if (v == NULL || v->not_found) { + ngx_log_debug0(NGX_LOG_DEBUG_STREAM, s->connection->log, 0, + "stream geo not found"); + + return NGX_ERROR; + } + + ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0, + "stream geo started: %v", v); + + if (ngx_parse_addr(s->connection->pool, addr, v->data, v->len) == NGX_OK) { + return NGX_OK; + } + + return NGX_ERROR; +} + + +static char * +ngx_stream_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + char *rv; + size_t len; + ngx_str_t *value, name; + ngx_uint_t i; + ngx_conf_t save; + ngx_pool_t *pool; + ngx_array_t *a; + ngx_stream_variable_t *var; + ngx_stream_geo_ctx_t *geo; + ngx_stream_geo_conf_ctx_t ctx; +#if (NGX_HAVE_INET6) + static struct in6_addr zero; +#endif + + value = cf->args->elts; + + geo = ngx_palloc(cf->pool, sizeof(ngx_stream_geo_ctx_t)); + if (geo == NULL) { + return NGX_CONF_ERROR; + } + + 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++; + + if (cf->args->nelts == 3) { + + geo->index = ngx_stream_get_variable_index(cf, &name); + if (geo->index == NGX_ERROR) { + return NGX_CONF_ERROR; + } + + 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++; + + } else { + geo->index = -1; + } + + var = ngx_stream_add_variable(cf, &name, NGX_STREAM_VAR_CHANGEABLE); + if (var == NULL) { + return NGX_CONF_ERROR; + } + + pool = ngx_create_pool(NGX_DEFAULT_POOL_SIZE, cf->log); + if (pool == NULL) { + return NGX_CONF_ERROR; + } + + ngx_memzero(&ctx, sizeof(ngx_stream_geo_conf_ctx_t)); + + ctx.temp_pool = ngx_create_pool(NGX_DEFAULT_POOL_SIZE, cf->log); + if (ctx.temp_pool == NULL) { + return NGX_CONF_ERROR; + } + + ngx_rbtree_init(&ctx.rbtree, &ctx.sentinel, ngx_str_rbtree_insert_value); + + ctx.pool = cf->pool; + ctx.data_size = sizeof(ngx_stream_geo_header_t) + + sizeof(ngx_stream_variable_value_t) + + 0x10000 * sizeof(ngx_stream_geo_range_t *); + ctx.allow_binary_include = 1; + + save = *cf; + cf->pool = pool; + cf->ctx = &ctx; + cf->handler = ngx_stream_geo; + cf->handler_conf = conf; + + rv = ngx_conf_parse(cf, NULL); + + *cf = save; + + if (ctx.ranges) { + + if (ctx.high.low && !ctx.binary_include) { + for (i = 0; i < 0x10000; i++) { + a = (ngx_array_t *) ctx.high.low[i]; + + if (a == NULL || a->nelts == 0) { + continue; + } + + len = a->nelts * sizeof(ngx_stream_geo_range_t); + + ctx.high.low[i] = ngx_palloc(cf->pool, len + sizeof(void *)); + if (ctx.high.low[i] == NULL) { + return NGX_CONF_ERROR; + } + + ngx_memcpy(ctx.high.low[i], a->elts, len); + ctx.high.low[i][a->nelts].value = NULL; + ctx.data_size += len + sizeof(void *); + } + + if (ctx.allow_binary_include + && !ctx.outside_entries + && ctx.entries > 100000 + && ctx.includes == 1) + { + ngx_stream_geo_create_binary_base(&ctx); + } + } + + if (ctx.high.default_value == NULL) { + ctx.high.default_value = &ngx_stream_variable_null_value; + } + + geo->u.high = ctx.high; + + var->get_handler = ngx_stream_geo_range_variable; + var->data = (uintptr_t) geo; + + ngx_destroy_pool(ctx.temp_pool); + ngx_destroy_pool(pool); + + } else { + if (ctx.tree == NULL) { + ctx.tree = ngx_radix_tree_create(cf->pool, -1); + if (ctx.tree == NULL) { + return NGX_CONF_ERROR; + } + } + + 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_stream_geo_cidr_variable; + var->data = (uintptr_t) geo; + + ngx_destroy_pool(ctx.temp_pool); + ngx_destroy_pool(pool); + + if (ngx_radix32tree_insert(ctx.tree, 0, 0, + (uintptr_t) &ngx_stream_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_stream_variable_null_value) + == NGX_ERROR) + { + return NGX_CONF_ERROR; + } +#endif + } + + return rv; +} + + +static char * +ngx_stream_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) +{ + char *rv; + ngx_str_t *value; + ngx_stream_geo_conf_ctx_t *ctx; + + ctx = cf->ctx; + + value = cf->args->elts; + + if (cf->args->nelts == 1) { + + if (ngx_strcmp(value[0].data, "ranges") == 0) { + + 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"); + goto failed; + } + + ctx->ranges = 1; + + rv = NGX_CONF_OK; + + goto done; + } + } + + if (cf->args->nelts != 2) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid number of the geo parameters"); + goto failed; + } + + if (ngx_strcmp(value[0].data, "include") == 0) { + + rv = ngx_stream_geo_include(cf, ctx, &value[1]); + + goto done; + } + + if (ctx->ranges) { + rv = ngx_stream_geo_range(cf, ctx, value); + + } else { + rv = ngx_stream_geo_cidr(cf, ctx, value); + } + +done: + + ngx_reset_pool(cf->pool); + + return rv; + +failed: + + ngx_reset_pool(cf->pool); + + return NGX_CONF_ERROR; +} + + +static char * +ngx_stream_geo_range(ngx_conf_t *cf, ngx_stream_geo_conf_ctx_t *ctx, + ngx_str_t *value) +{ + u_char *p, *last; + in_addr_t start, end; + ngx_str_t *net; + ngx_uint_t del; + + if (ngx_strcmp(value[0].data, "default") == 0) { + + if (ctx->high.default_value) { + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, + "duplicate default geo range value: \"%V\", old value: \"%v\"", + &value[1], ctx->high.default_value); + } + + ctx->high.default_value = ngx_stream_geo_value(cf, ctx, &value[1]); + if (ctx->high.default_value == NULL) { + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; + } + + if (ctx->binary_include) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "binary geo range base \"%s\" cannot be mixed with usual entries", + ctx->include_name.data); + return NGX_CONF_ERROR; + } + + if (ctx->high.low == NULL) { + ctx->high.low = ngx_pcalloc(ctx->pool, + 0x10000 * sizeof(ngx_stream_geo_range_t *)); + if (ctx->high.low == NULL) { + return NGX_CONF_ERROR; + } + } + + ctx->entries++; + ctx->outside_entries = 1; + + if (ngx_strcmp(value[0].data, "delete") == 0) { + net = &value[1]; + del = 1; + + } else { + net = &value[0]; + del = 0; + } + + last = net->data + net->len; + + p = ngx_strlchr(net->data, last, '-'); + + if (p == NULL) { + goto invalid; + } + + start = ngx_inet_addr(net->data, p - net->data); + + if (start == INADDR_NONE) { + goto invalid; + } + + start = ntohl(start); + + p++; + + end = ngx_inet_addr(p, last - p); + + if (end == INADDR_NONE) { + goto invalid; + } + + end = ntohl(end); + + if (start > end) { + goto invalid; + } + + if (del) { + if (ngx_stream_geo_delete_range(cf, ctx, start, end)) { + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, + "no address range \"%V\" to delete", net); + } + + return NGX_CONF_OK; + } + + ctx->value = ngx_stream_geo_value(cf, ctx, &value[1]); + + if (ctx->value == NULL) { + return NGX_CONF_ERROR; + } + + ctx->net = net; + + return ngx_stream_geo_add_range(cf, ctx, start, end); + +invalid: + + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid range \"%V\"", net); + + return NGX_CONF_ERROR; +} + + +/* the add procedure is optimized to add a growing up sequence */ + +static char * +ngx_stream_geo_add_range(ngx_conf_t *cf, ngx_stream_geo_conf_ctx_t *ctx, + in_addr_t start, in_addr_t end) +{ + in_addr_t n; + ngx_uint_t h, i, s, e; + ngx_array_t *a; + ngx_stream_geo_range_t *range; + + for (n = start; n <= end; n = (n + 0x10000) & 0xffff0000) { + + h = n >> 16; + + if (n == start) { + s = n & 0xffff; + } else { + s = 0; + } + + if ((n | 0xffff) > end) { + e = end & 0xffff; + + } else { + e = 0xffff; + } + + a = (ngx_array_t *) ctx->high.low[h]; + + if (a == NULL) { + a = ngx_array_create(ctx->temp_pool, 64, + sizeof(ngx_stream_geo_range_t)); + if (a == NULL) { + return NGX_CONF_ERROR; + } + + ctx->high.low[h] = (ngx_stream_geo_range_t *) a; + } + + i = a->nelts; + range = a->elts; + + while (i) { + + i--; + + if (e < (ngx_uint_t) range[i].start) { + continue; + } + + if (s > (ngx_uint_t) range[i].end) { + + /* add after the range */ + + range = ngx_array_push(a); + if (range == NULL) { + return NGX_CONF_ERROR; + } + + range = a->elts; + + ngx_memmove(&range[i + 2], &range[i + 1], + (a->nelts - 2 - i) * sizeof(ngx_stream_geo_range_t)); + + range[i + 1].start = (u_short) s; + range[i + 1].end = (u_short) e; + range[i + 1].value = ctx->value; + + goto next; + } + + if (s == (ngx_uint_t) range[i].start + && e == (ngx_uint_t) range[i].end) + { + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, + "duplicate range \"%V\", value: \"%v\", old value: \"%v\"", + ctx->net, ctx->value, range[i].value); + + range[i].value = ctx->value; + + goto next; + } + + if (s > (ngx_uint_t) range[i].start + && e < (ngx_uint_t) range[i].end) + { + /* split the range and insert the new one */ + + range = ngx_array_push(a); + if (range == NULL) { + return NGX_CONF_ERROR; + } + + range = ngx_array_push(a); + if (range == NULL) { + return NGX_CONF_ERROR; + } + + range = a->elts; + + ngx_memmove(&range[i + 3], &range[i + 1], + (a->nelts - 3 - i) * sizeof(ngx_stream_geo_range_t)); + + range[i + 2].start = (u_short) (e + 1); + range[i + 2].end = range[i].end; + range[i + 2].value = range[i].value; + + range[i + 1].start = (u_short) s; + range[i + 1].end = (u_short) e; + range[i + 1].value = ctx->value; + + range[i].end = (u_short) (s - 1); + + goto next; + } + + if (s == (ngx_uint_t) range[i].start + && e < (ngx_uint_t) range[i].end) + { + /* shift the range start and insert the new range */ + + range = ngx_array_push(a); + if (range == NULL) { + return NGX_CONF_ERROR; + } + + range = a->elts; + + ngx_memmove(&range[i + 1], &range[i], + (a->nelts - 1 - i) * sizeof(ngx_stream_geo_range_t)); + + range[i + 1].start = (u_short) (e + 1); + + range[i].start = (u_short) s; + range[i].end = (u_short) e; + range[i].value = ctx->value; + + goto next; + } + + if (s > (ngx_uint_t) range[i].start + && e == (ngx_uint_t) range[i].end) + { + /* shift the range end and insert the new range */ + + range = ngx_array_push(a); + if (range == NULL) { + return NGX_CONF_ERROR; + } + + range = a->elts; + + ngx_memmove(&range[i + 2], &range[i + 1], + (a->nelts - 2 - i) * sizeof(ngx_stream_geo_range_t)); + + range[i + 1].start = (u_short) s; + range[i + 1].end = (u_short) e; + range[i + 1].value = ctx->value; + + range[i].end = (u_short) (s - 1); + + goto next; + } + + s = (ngx_uint_t) range[i].start; + e = (ngx_uint_t) range[i].end; + + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "range \"%V\" overlaps \"%d.%d.%d.%d-%d.%d.%d.%d\"", + ctx->net, + h >> 8, h & 0xff, s >> 8, s & 0xff, + h >> 8, h & 0xff, e >> 8, e & 0xff); + + return NGX_CONF_ERROR; + } + + /* add the first range */ + + range = ngx_array_push(a); + if (range == NULL) { + return NGX_CONF_ERROR; + } + + range->start = (u_short) s; + range->end = (u_short) e; + range->value = ctx->value; + + next: + + continue; + } + + return NGX_CONF_OK; +} + + +static ngx_uint_t +ngx_stream_geo_delete_range(ngx_conf_t *cf, ngx_stream_geo_conf_ctx_t *ctx, + in_addr_t start, in_addr_t end) +{ + in_addr_t n; + ngx_uint_t h, i, s, e, warn; + ngx_array_t *a; + ngx_stream_geo_range_t *range; + + warn = 0; + + for (n = start; n <= end; n += 0x10000) { + + h = n >> 16; + + if (n == start) { + s = n & 0xffff; + } else { + s = 0; + } + + if ((n | 0xffff) > end) { + e = end & 0xffff; + + } else { + e = 0xffff; + } + + a = (ngx_array_t *) ctx->high.low[h]; + + if (a == NULL) { + warn = 1; + continue; + } + + range = a->elts; + for (i = 0; i < a->nelts; i++) { + + if (s == (ngx_uint_t) range[i].start + && e == (ngx_uint_t) range[i].end) + { + ngx_memmove(&range[i], &range[i + 1], + (a->nelts - 1 - i) * sizeof(ngx_stream_geo_range_t)); + + a->nelts--; + + break; + } + + if (s != (ngx_uint_t) range[i].start + && e != (ngx_uint_t) range[i].end) + { + continue; + } + + warn = 1; + } + } + + return warn; +} + + +static char * +ngx_stream_geo_cidr(ngx_conf_t *cf, ngx_stream_geo_conf_ctx_t *ctx, + ngx_str_t *value) +{ + 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); + if (ctx->tree == NULL) { + return NGX_CONF_ERROR; + } + } + +#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 (ngx_strcmp(value[0].data, "default") == 0) { + cidr.family = AF_INET; + cidr.u.in.addr = 0; + cidr.u.in.mask = 0; + + rv = ngx_stream_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_stream_geo_cidr_add(cf, ctx, &cidr, &value[1], &value[0]); + + if (rv != NGX_CONF_OK) { + return rv; + } +#endif + + return NGX_CONF_OK; + } + + if (ngx_strcmp(value[0].data, "delete") == 0) { + net = &value[1]; + del = 1; + + } else { + net = &value[0]; + del = 0; + } + + if (ngx_stream_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_stream_geo_cidr_add(cf, ctx, &cidr, &value[1], net); +} + + +static char * +ngx_stream_geo_cidr_add(ngx_conf_t *cf, ngx_stream_geo_conf_ctx_t *ctx, + ngx_cidr_t *cidr, ngx_str_t *value, ngx_str_t *net) +{ + ngx_int_t rc; + ngx_stream_variable_value_t *val, *old; + + val = ngx_stream_geo_value(cf, ctx, value); + + if (val == NULL) { + return NGX_CONF_ERROR; + } + + 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; + } + + if (rc == NGX_ERROR) { + return NGX_CONF_ERROR; + } + + /* rc == NGX_BUSY */ + + old = (ngx_stream_variable_value_t *) + 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); + + 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_stream_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; +} + + +static ngx_stream_variable_value_t * +ngx_stream_geo_value(ngx_conf_t *cf, ngx_stream_geo_conf_ctx_t *ctx, + ngx_str_t *value) +{ + uint32_t hash; + ngx_stream_variable_value_t *val; + ngx_stream_geo_variable_value_node_t *gvvn; + + hash = ngx_crc32_long(value->data, value->len); + + gvvn = (ngx_stream_geo_variable_value_node_t *) + ngx_str_rbtree_lookup(&ctx->rbtree, value, hash); + + if (gvvn) { + return gvvn->value; + } + + val = ngx_palloc(ctx->pool, sizeof(ngx_stream_variable_value_t)); + if (val == NULL) { + return NULL; + } + + val->len = value->len; + val->data = ngx_pstrdup(ctx->pool, value); + if (val->data == NULL) { + return NULL; + } + + val->valid = 1; + val->no_cacheable = 0; + val->not_found = 0; + + gvvn = ngx_palloc(ctx->temp_pool, + sizeof(ngx_stream_geo_variable_value_node_t)); + if (gvvn == NULL) { + return NULL; + } + + gvvn->sn.node.key = hash; + gvvn->sn.str.len = val->len; + gvvn->sn.str.data = val->data; + gvvn->value = val; + gvvn->offset = 0; + + ngx_rbtree_insert(&ctx->rbtree, &gvvn->sn.node); + + ctx->data_size += ngx_align(sizeof(ngx_stream_variable_value_t) + + value->len, sizeof(void *)); + + return val; +} + + +static ngx_int_t +ngx_stream_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; + + 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 char * +ngx_stream_geo_include(ngx_conf_t *cf, ngx_stream_geo_conf_ctx_t *ctx, + ngx_str_t *name) +{ + char *rv; + ngx_str_t file; + + file.len = name->len + 4; + file.data = ngx_pnalloc(ctx->temp_pool, name->len + 5); + if (file.data == NULL) { + return NGX_CONF_ERROR; + } + + ngx_sprintf(file.data, "%V.bin%Z", name); + + if (ngx_conf_full_name(cf->cycle, &file, 1) != NGX_OK) { + return NGX_CONF_ERROR; + } + + if (ctx->ranges) { + ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data); + + switch (ngx_stream_geo_include_binary_base(cf, ctx, &file)) { + case NGX_OK: + return NGX_CONF_OK; + case NGX_ERROR: + return NGX_CONF_ERROR; + default: + break; + } + } + + file.len -= 4; + file.data[file.len] = '\0'; + + ctx->include_name = file; + + if (ctx->outside_entries) { + ctx->allow_binary_include = 0; + } + + ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data); + + rv = ngx_conf_parse(cf, &file); + + ctx->includes++; + ctx->outside_entries = 0; + + return rv; +} + + +static ngx_int_t +ngx_stream_geo_include_binary_base(ngx_conf_t *cf, + ngx_stream_geo_conf_ctx_t *ctx, ngx_str_t *name) +{ + u_char *base, ch; + time_t mtime; + size_t size, len; + ssize_t n; + uint32_t crc32; + ngx_err_t err; + ngx_int_t rc; + ngx_uint_t i; + ngx_file_t file; + ngx_file_info_t fi; + ngx_stream_geo_range_t *range, **ranges; + ngx_stream_geo_header_t *header; + ngx_stream_variable_value_t *vv; + + ngx_memzero(&file, sizeof(ngx_file_t)); + file.name = *name; + file.log = cf->log; + + file.fd = ngx_open_file(name->data, NGX_FILE_RDONLY, 0, 0); + if (file.fd == NGX_INVALID_FILE) { + err = ngx_errno; + if (err != NGX_ENOENT) { + ngx_conf_log_error(NGX_LOG_CRIT, cf, err, + ngx_open_file_n " \"%s\" failed", name->data); + } + return NGX_DECLINED; + } + + if (ctx->outside_entries) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "binary geo range base \"%s\" cannot be mixed with usual entries", + name->data); + rc = NGX_ERROR; + goto done; + } + + if (ctx->binary_include) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "second binary geo range base \"%s\" cannot be mixed with \"%s\"", + name->data, ctx->include_name.data); + rc = NGX_ERROR; + goto done; + } + + if (ngx_fd_info(file.fd, &fi) == NGX_FILE_ERROR) { + ngx_conf_log_error(NGX_LOG_CRIT, cf, ngx_errno, + ngx_fd_info_n " \"%s\" failed", name->data); + goto failed; + } + + size = (size_t) ngx_file_size(&fi); + mtime = ngx_file_mtime(&fi); + + ch = name->data[name->len - 4]; + name->data[name->len - 4] = '\0'; + + if (ngx_file_info(name->data, &fi) == NGX_FILE_ERROR) { + ngx_conf_log_error(NGX_LOG_CRIT, cf, ngx_errno, + ngx_file_info_n " \"%s\" failed", name->data); + goto failed; + } + + name->data[name->len - 4] = ch; + + if (mtime < ngx_file_mtime(&fi)) { + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, + "stale binary geo range base \"%s\"", name->data); + goto failed; + } + + base = ngx_palloc(ctx->pool, size); + if (base == NULL) { + goto failed; + } + + n = ngx_read_file(&file, base, size, 0); + + if (n == NGX_ERROR) { + ngx_conf_log_error(NGX_LOG_CRIT, cf, ngx_errno, + ngx_read_file_n " \"%s\" failed", name->data); + goto failed; + } + + if ((size_t) n != size) { + ngx_conf_log_error(NGX_LOG_CRIT, cf, 0, + ngx_read_file_n " \"%s\" returned only %z bytes instead of %z", + name->data, n, size); + goto failed; + } + + header = (ngx_stream_geo_header_t *) base; + + if (size < 16 || ngx_memcmp(&ngx_stream_geo_header, header, 12) != 0) { + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, + "incompatible binary geo range base \"%s\"", name->data); + goto failed; + } + + ngx_crc32_init(crc32); + + vv = (ngx_stream_variable_value_t *) + (base + sizeof(ngx_stream_geo_header_t)); + + while (vv->data) { + len = ngx_align(sizeof(ngx_stream_variable_value_t) + vv->len, + sizeof(void *)); + ngx_crc32_update(&crc32, (u_char *) vv, len); + vv->data += (size_t) base; + vv = (ngx_stream_variable_value_t *) ((u_char *) vv + len); + } + ngx_crc32_update(&crc32, (u_char *) vv, + sizeof(ngx_stream_variable_value_t)); + vv++; + + ranges = (ngx_stream_geo_range_t **) vv; + + for (i = 0; i < 0x10000; i++) { + ngx_crc32_update(&crc32, (u_char *) &ranges[i], sizeof(void *)); + if (ranges[i]) { + ranges[i] = (ngx_stream_geo_range_t *) + ((u_char *) ranges[i] + (size_t) base); + } + } + + range = (ngx_stream_geo_range_t *) &ranges[0x10000]; + + while ((u_char *) range < base + size) { + while (range->value) { + ngx_crc32_update(&crc32, (u_char *) range, + sizeof(ngx_stream_geo_range_t)); + range->value = (ngx_stream_variable_value_t *) + ((u_char *) range->value + (size_t) base); + range++; + } + ngx_crc32_update(&crc32, (u_char *) range, sizeof(void *)); + range = (ngx_stream_geo_range_t *) ((u_char *) range + sizeof(void *)); + } + + ngx_crc32_final(crc32); + + if (crc32 != header->crc32) { + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, + "CRC32 mismatch in binary geo range base \"%s\"", name->data); + goto failed; + } + + ngx_conf_log_error(NGX_LOG_NOTICE, cf, 0, + "using binary geo range base \"%s\"", name->data); + + ctx->include_name = *name; + ctx->binary_include = 1; + ctx->high.low = ranges; + rc = NGX_OK; + + goto done; + +failed: + + rc = NGX_DECLINED; + +done: + + if (ngx_close_file(file.fd) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, + ngx_close_file_n " \"%s\" failed", name->data); + } + + return rc; +} + + +static void +ngx_stream_geo_create_binary_base(ngx_stream_geo_conf_ctx_t *ctx) +{ + u_char *p; + uint32_t hash; + ngx_str_t s; + ngx_uint_t i; + ngx_file_mapping_t fm; + ngx_stream_geo_range_t *r, *range, **ranges; + ngx_stream_geo_header_t *header; + ngx_stream_geo_variable_value_node_t *gvvn; + + fm.name = ngx_pnalloc(ctx->temp_pool, ctx->include_name.len + 5); + if (fm.name == NULL) { + return; + } + + ngx_sprintf(fm.name, "%V.bin%Z", &ctx->include_name); + + fm.size = ctx->data_size; + fm.log = ctx->pool->log; + + ngx_log_error(NGX_LOG_NOTICE, fm.log, 0, + "creating binary geo range base \"%s\"", fm.name); + + if (ngx_create_file_mapping(&fm) != NGX_OK) { + return; + } + + p = ngx_cpymem(fm.addr, &ngx_stream_geo_header, + sizeof(ngx_stream_geo_header_t)); + + p = ngx_stream_geo_copy_values(fm.addr, p, ctx->rbtree.root, + ctx->rbtree.sentinel); + + p += sizeof(ngx_stream_variable_value_t); + + ranges = (ngx_stream_geo_range_t **) p; + + p += 0x10000 * sizeof(ngx_stream_geo_range_t *); + + for (i = 0; i < 0x10000; i++) { + r = ctx->high.low[i]; + if (r == NULL) { + continue; + } + + range = (ngx_stream_geo_range_t *) p; + ranges[i] = (ngx_stream_geo_range_t *) (p - (u_char *) fm.addr); + + do { + s.len = r->value->len; + s.data = r->value->data; + hash = ngx_crc32_long(s.data, s.len); + gvvn = (ngx_stream_geo_variable_value_node_t *) + ngx_str_rbtree_lookup(&ctx->rbtree, &s, hash); + + range->value = (ngx_stream_variable_value_t *) gvvn->offset; + range->start = r->start; + range->end = r->end; + range++; + + } while ((++r)->value); + + range->value = NULL; + + p = (u_char *) range + sizeof(void *); + } + + header = fm.addr; + header->crc32 = ngx_crc32_long((u_char *) fm.addr + + sizeof(ngx_stream_geo_header_t), + fm.size - sizeof(ngx_stream_geo_header_t)); + + ngx_close_file_mapping(&fm); +} + + +static u_char * +ngx_stream_geo_copy_values(u_char *base, u_char *p, ngx_rbtree_node_t *node, + ngx_rbtree_node_t *sentinel) +{ + ngx_stream_variable_value_t *vv; + ngx_stream_geo_variable_value_node_t *gvvn; + + if (node == sentinel) { + return p; + } + + gvvn = (ngx_stream_geo_variable_value_node_t *) node; + gvvn->offset = p - base; + + vv = (ngx_stream_variable_value_t *) p; + *vv = *gvvn->value; + p += sizeof(ngx_stream_variable_value_t); + vv->data = (u_char *) (p - base); + + p = ngx_cpymem(p, gvvn->sn.str.data, gvvn->sn.str.len); + + p = ngx_align_ptr(p, sizeof(void *)); + + p = ngx_stream_geo_copy_values(base, p, node->left, sentinel); + + return ngx_stream_geo_copy_values(base, p, node->right, sentinel); +} diff --git a/src/stream/ngx_stream_geoip_module.c b/src/stream/ngx_stream_geoip_module.c new file mode 100644 index 0000000..f694033 --- /dev/null +++ b/src/stream/ngx_stream_geoip_module.c @@ -0,0 +1,814 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + +#include +#include + + +#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; +#if (NGX_HAVE_GEOIP_V6) + unsigned country_v6:1; + unsigned org_v6:1; + unsigned city_v6:1; +#endif +} ngx_stream_geoip_conf_t; + + +typedef struct { + ngx_str_t *name; + uintptr_t data; +} ngx_stream_geoip_var_t; + + +typedef const char *(*ngx_stream_geoip_variable_handler_pt)(GeoIP *, + u_long addr); + + +ngx_stream_geoip_variable_handler_pt ngx_stream_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_stream_geoip_variable_handler_v6_pt)(GeoIP *, + geoipv6_t addr); + + +ngx_stream_geoip_variable_handler_v6_pt + ngx_stream_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_stream_geoip_country_variable(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_stream_geoip_org_variable(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_stream_geoip_city_variable(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_stream_geoip_region_name_variable(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_stream_geoip_city_float_variable(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_stream_geoip_city_int_variable(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data); +static GeoIPRecord *ngx_stream_geoip_get_city_record(ngx_stream_session_t *s); + +static ngx_int_t ngx_stream_geoip_add_variables(ngx_conf_t *cf); +static void *ngx_stream_geoip_create_conf(ngx_conf_t *cf); +static char *ngx_stream_geoip_country(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); +static char *ngx_stream_geoip_org(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); +static char *ngx_stream_geoip_city(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); +static void ngx_stream_geoip_cleanup(void *data); + + +static ngx_command_t ngx_stream_geoip_commands[] = { + + { ngx_string("geoip_country"), + NGX_STREAM_MAIN_CONF|NGX_CONF_TAKE12, + ngx_stream_geoip_country, + NGX_STREAM_MAIN_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("geoip_org"), + NGX_STREAM_MAIN_CONF|NGX_CONF_TAKE12, + ngx_stream_geoip_org, + NGX_STREAM_MAIN_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("geoip_city"), + NGX_STREAM_MAIN_CONF|NGX_CONF_TAKE12, + ngx_stream_geoip_city, + NGX_STREAM_MAIN_CONF_OFFSET, + 0, + NULL }, + + ngx_null_command +}; + + +static ngx_stream_module_t ngx_stream_geoip_module_ctx = { + ngx_stream_geoip_add_variables, /* preconfiguration */ + NULL, /* postconfiguration */ + + ngx_stream_geoip_create_conf, /* create main configuration */ + NULL, /* init main configuration */ + + NULL, /* create server configuration */ + NULL /* merge server configuration */ +}; + + +ngx_module_t ngx_stream_geoip_module = { + NGX_MODULE_V1, + &ngx_stream_geoip_module_ctx, /* module context */ + ngx_stream_geoip_commands, /* module directives */ + NGX_STREAM_MODULE, /* module type */ + NULL, /* init master */ + NULL, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + + +static ngx_stream_variable_t ngx_stream_geoip_vars[] = { + + { ngx_string("geoip_country_code"), NULL, + ngx_stream_geoip_country_variable, + NGX_GEOIP_COUNTRY_CODE, 0, 0 }, + + { ngx_string("geoip_country_code3"), NULL, + ngx_stream_geoip_country_variable, + NGX_GEOIP_COUNTRY_CODE3, 0, 0 }, + + { ngx_string("geoip_country_name"), NULL, + ngx_stream_geoip_country_variable, + NGX_GEOIP_COUNTRY_NAME, 0, 0 }, + + { ngx_string("geoip_org"), NULL, + ngx_stream_geoip_org_variable, + 0, 0, 0 }, + + { ngx_string("geoip_city_continent_code"), NULL, + ngx_stream_geoip_city_variable, + offsetof(GeoIPRecord, continent_code), 0, 0 }, + + { ngx_string("geoip_city_country_code"), NULL, + ngx_stream_geoip_city_variable, + offsetof(GeoIPRecord, country_code), 0, 0 }, + + { ngx_string("geoip_city_country_code3"), NULL, + ngx_stream_geoip_city_variable, + offsetof(GeoIPRecord, country_code3), 0, 0 }, + + { ngx_string("geoip_city_country_name"), NULL, + ngx_stream_geoip_city_variable, + offsetof(GeoIPRecord, country_name), 0, 0 }, + + { ngx_string("geoip_region"), NULL, + ngx_stream_geoip_city_variable, + offsetof(GeoIPRecord, region), 0, 0 }, + + { ngx_string("geoip_region_name"), NULL, + ngx_stream_geoip_region_name_variable, + 0, 0, 0 }, + + { ngx_string("geoip_city"), NULL, + ngx_stream_geoip_city_variable, + offsetof(GeoIPRecord, city), 0, 0 }, + + { ngx_string("geoip_postal_code"), NULL, + ngx_stream_geoip_city_variable, + offsetof(GeoIPRecord, postal_code), 0, 0 }, + + { ngx_string("geoip_latitude"), NULL, + ngx_stream_geoip_city_float_variable, + offsetof(GeoIPRecord, latitude), 0, 0 }, + + { ngx_string("geoip_longitude"), NULL, + ngx_stream_geoip_city_float_variable, + offsetof(GeoIPRecord, longitude), 0, 0 }, + + { ngx_string("geoip_dma_code"), NULL, + ngx_stream_geoip_city_int_variable, + offsetof(GeoIPRecord, dma_code), 0, 0 }, + + { ngx_string("geoip_area_code"), NULL, + ngx_stream_geoip_city_int_variable, + offsetof(GeoIPRecord, area_code), 0, 0 }, + + { ngx_null_string, NULL, NULL, 0, 0, 0 } +}; + + +static u_long +ngx_stream_geoip_addr(ngx_stream_session_t *s, ngx_stream_geoip_conf_t *gcf) +{ + ngx_addr_t addr; + struct sockaddr_in *sin; + + addr.sockaddr = s->connection->sockaddr; + addr.socklen = s->connection->socklen; + /* addr.name = s->connection->addr_text; */ + +#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_stream_geoip_addr_v6(ngx_stream_session_t *s, ngx_stream_geoip_conf_t *gcf) +{ + ngx_addr_t addr; + in_addr_t addr4; + struct in6_addr addr6; + struct sockaddr_in *sin; + struct sockaddr_in6 *sin6; + + addr.sockaddr = s->connection->sockaddr; + addr.socklen = s->connection->socklen; + /* addr.name = s->connection->addr_text; */ + + 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_stream_geoip_country_variable(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data) +{ + ngx_stream_geoip_variable_handler_pt handler = + ngx_stream_geoip_country_functions[data]; +#if (NGX_HAVE_GEOIP_V6) + ngx_stream_geoip_variable_handler_v6_pt handler_v6 = + ngx_stream_geoip_country_v6_functions[data]; +#endif + + const char *val; + ngx_stream_geoip_conf_t *gcf; + + gcf = ngx_stream_get_module_main_conf(s, ngx_stream_geoip_module); + + if (gcf->country == NULL) { + goto not_found; + } + +#if (NGX_HAVE_GEOIP_V6) + val = gcf->country_v6 + ? handler_v6(gcf->country, ngx_stream_geoip_addr_v6(s, gcf)) + : handler(gcf->country, ngx_stream_geoip_addr(s, gcf)); +#else + val = handler(gcf->country, ngx_stream_geoip_addr(s, gcf)); +#endif + + if (val == NULL) { + goto not_found; + } + + v->len = ngx_strlen(val); + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = (u_char *) val; + + return NGX_OK; + +not_found: + + v->not_found = 1; + + return NGX_OK; +} + + +static ngx_int_t +ngx_stream_geoip_org_variable(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data) +{ + size_t len; + char *val; + ngx_stream_geoip_conf_t *gcf; + + gcf = ngx_stream_get_module_main_conf(s, ngx_stream_geoip_module); + + if (gcf->org == NULL) { + goto not_found; + } + +#if (NGX_HAVE_GEOIP_V6) + val = gcf->org_v6 + ? GeoIP_name_by_ipnum_v6(gcf->org, + ngx_stream_geoip_addr_v6(s, gcf)) + : GeoIP_name_by_ipnum(gcf->org, + ngx_stream_geoip_addr(s, gcf)); +#else + val = GeoIP_name_by_ipnum(gcf->org, ngx_stream_geoip_addr(s, gcf)); +#endif + + if (val == NULL) { + goto not_found; + } + + len = ngx_strlen(val); + v->data = ngx_pnalloc(s->connection->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; + + ngx_free(val); + + return NGX_OK; + +not_found: + + v->not_found = 1; + + return NGX_OK; +} + + +static ngx_int_t +ngx_stream_geoip_city_variable(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data) +{ + char *val; + size_t len; + GeoIPRecord *gr; + + gr = ngx_stream_geoip_get_city_record(s); + if (gr == NULL) { + goto not_found; + } + + val = *(char **) ((char *) gr + data); + if (val == NULL) { + goto no_value; + } + + len = ngx_strlen(val); + v->data = ngx_pnalloc(s->connection->pool, len); + if (v->data == NULL) { + GeoIPRecord_delete(gr); + return NGX_ERROR; + } + + ngx_memcpy(v->data, val, len); + + v->len = len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + GeoIPRecord_delete(gr); + + return NGX_OK; + +no_value: + + GeoIPRecord_delete(gr); + +not_found: + + v->not_found = 1; + + return NGX_OK; +} + + +static ngx_int_t +ngx_stream_geoip_region_name_variable(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data) +{ + size_t len; + const char *val; + GeoIPRecord *gr; + + gr = ngx_stream_geoip_get_city_record(s); + if (gr == NULL) { + goto not_found; + } + + val = GeoIP_region_name_by_code(gr->country_code, gr->region); + + GeoIPRecord_delete(gr); + + if (val == NULL) { + goto not_found; + } + + len = ngx_strlen(val); + v->data = ngx_pnalloc(s->connection->pool, len); + if (v->data == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(v->data, val, len); + + v->len = len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + return NGX_OK; + +not_found: + + v->not_found = 1; + + return NGX_OK; +} + + +static ngx_int_t +ngx_stream_geoip_city_float_variable(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data) +{ + float val; + GeoIPRecord *gr; + + gr = ngx_stream_geoip_get_city_record(s); + if (gr == NULL) { + v->not_found = 1; + return NGX_OK; + } + + v->data = ngx_pnalloc(s->connection->pool, NGX_INT64_LEN + 5); + if (v->data == NULL) { + GeoIPRecord_delete(gr); + return NGX_ERROR; + } + + val = *(float *) ((char *) gr + data); + + v->len = ngx_sprintf(v->data, "%.4f", val) - v->data; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + GeoIPRecord_delete(gr); + + return NGX_OK; +} + + +static ngx_int_t +ngx_stream_geoip_city_int_variable(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data) +{ + int val; + GeoIPRecord *gr; + + gr = ngx_stream_geoip_get_city_record(s); + if (gr == NULL) { + v->not_found = 1; + return NGX_OK; + } + + v->data = ngx_pnalloc(s->connection->pool, NGX_INT64_LEN); + if (v->data == NULL) { + GeoIPRecord_delete(gr); + return NGX_ERROR; + } + + val = *(int *) ((char *) gr + data); + + v->len = ngx_sprintf(v->data, "%d", val) - v->data; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + GeoIPRecord_delete(gr); + + return NGX_OK; +} + + +static GeoIPRecord * +ngx_stream_geoip_get_city_record(ngx_stream_session_t *s) +{ + ngx_stream_geoip_conf_t *gcf; + + gcf = ngx_stream_get_module_main_conf(s, ngx_stream_geoip_module); + + if (gcf->city) { +#if (NGX_HAVE_GEOIP_V6) + return gcf->city_v6 + ? GeoIP_record_by_ipnum_v6(gcf->city, + ngx_stream_geoip_addr_v6(s, gcf)) + : GeoIP_record_by_ipnum(gcf->city, + ngx_stream_geoip_addr(s, gcf)); +#else + return GeoIP_record_by_ipnum(gcf->city, ngx_stream_geoip_addr(s, gcf)); +#endif + } + + return NULL; +} + + +static ngx_int_t +ngx_stream_geoip_add_variables(ngx_conf_t *cf) +{ + ngx_stream_variable_t *var, *v; + + for (v = ngx_stream_geoip_vars; v->name.len; v++) { + var = ngx_stream_add_variable(cf, &v->name, v->flags); + if (var == NULL) { + return NGX_ERROR; + } + + var->get_handler = v->get_handler; + var->data = v->data; + } + + return NGX_OK; +} + + +static void * +ngx_stream_geoip_create_conf(ngx_conf_t *cf) +{ + ngx_pool_cleanup_t *cln; + ngx_stream_geoip_conf_t *conf; + + conf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_geoip_conf_t)); + if (conf == NULL) { + return NULL; + } + + cln = ngx_pool_cleanup_add(cf->pool, 0); + if (cln == NULL) { + return NULL; + } + + cln->handler = ngx_stream_geoip_cleanup; + cln->data = conf; + + return conf; +} + + +static char * +ngx_stream_geoip_country(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_stream_geoip_conf_t *gcf = conf; + + ngx_str_t *value; + + if (gcf->country) { + return "is duplicate"; + } + + value = cf->args->elts; + + gcf->country = GeoIP_open((char *) value[1].data, GEOIP_MEMORY_CACHE); + + if (gcf->country == NULL) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "GeoIP_open(\"%V\") failed", &value[1]); + + return NGX_CONF_ERROR; + } + + if (cf->args->nelts == 3) { + if (ngx_strcmp(value[2].data, "utf8") == 0) { + GeoIP_set_charset(gcf->country, GEOIP_CHARSET_UTF8); + + } else { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid parameter \"%V\"", &value[2]); + return NGX_CONF_ERROR; + } + } + + switch (gcf->country->databaseType) { + + case GEOIP_COUNTRY_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", + &value[1], gcf->country->databaseType); + return NGX_CONF_ERROR; + } +} + + +static char * +ngx_stream_geoip_org(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_stream_geoip_conf_t *gcf = conf; + + ngx_str_t *value; + + if (gcf->org) { + return "is duplicate"; + } + + value = cf->args->elts; + + gcf->org = GeoIP_open((char *) value[1].data, GEOIP_MEMORY_CACHE); + + if (gcf->org == NULL) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "GeoIP_open(\"%V\") failed", &value[1]); + + return NGX_CONF_ERROR; + } + + if (cf->args->nelts == 3) { + if (ngx_strcmp(value[2].data, "utf8") == 0) { + GeoIP_set_charset(gcf->org, GEOIP_CHARSET_UTF8); + + } else { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid parameter \"%V\"", &value[2]); + return NGX_CONF_ERROR; + } + } + + switch (gcf->org->databaseType) { + + case GEOIP_ISP_EDITION: + case GEOIP_ORG_EDITION: + case GEOIP_DOMAIN_EDITION: + case GEOIP_ASNUM_EDITION: + + 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", + &value[1], gcf->org->databaseType); + return NGX_CONF_ERROR; + } +} + + +static char * +ngx_stream_geoip_city(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_stream_geoip_conf_t *gcf = conf; + + ngx_str_t *value; + + if (gcf->city) { + return "is duplicate"; + } + + value = cf->args->elts; + + gcf->city = GeoIP_open((char *) value[1].data, GEOIP_MEMORY_CACHE); + + if (gcf->city == NULL) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "GeoIP_open(\"%V\") failed", &value[1]); + + return NGX_CONF_ERROR; + } + + if (cf->args->nelts == 3) { + if (ngx_strcmp(value[2].data, "utf8") == 0) { + GeoIP_set_charset(gcf->city, GEOIP_CHARSET_UTF8); + + } else { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid parameter \"%V\"", &value[2]); + return NGX_CONF_ERROR; + } + } + + switch (gcf->city->databaseType) { + + case GEOIP_CITY_EDITION_REV0: + case GEOIP_CITY_EDITION_REV1: + + 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", + &value[1], gcf->city->databaseType); + return NGX_CONF_ERROR; + } +} + + +static void +ngx_stream_geoip_cleanup(void *data) +{ + ngx_stream_geoip_conf_t *gcf = data; + + if (gcf->country) { + GeoIP_delete(gcf->country); + } + + if (gcf->org) { + GeoIP_delete(gcf->org); + } + + if (gcf->city) { + GeoIP_delete(gcf->city); + } +} diff --git a/src/stream/ngx_stream_handler.c b/src/stream/ngx_stream_handler.c index aa69e44..61169e1 100644 --- a/src/stream/ngx_stream_handler.c +++ b/src/stream/ngx_stream_handler.c @@ -149,6 +149,15 @@ ngx_stream_init_connection(ngx_connection_t *c) cmcf = ngx_stream_get_module_main_conf(s, ngx_stream_core_module); + s->variables = ngx_pcalloc(s->connection->pool, + cmcf->variables.nelts + * sizeof(ngx_stream_variable_value_t)); + + if (s->variables == NULL) { + ngx_stream_close_connection(c); + return; + } + if (cmcf->limit_conn_handler) { rc = cmcf->limit_conn_handler(s); diff --git a/src/stream/ngx_stream_limit_conn_module.c b/src/stream/ngx_stream_limit_conn_module.c index f1d8a37..40eca94 100644 --- a/src/stream/ngx_stream_limit_conn_module.c +++ b/src/stream/ngx_stream_limit_conn_module.c @@ -11,33 +11,34 @@ typedef struct { - u_char color; - u_char len; - u_short conn; - u_char data[1]; + u_char color; + u_char len; + u_short conn; + u_char data[1]; } ngx_stream_limit_conn_node_t; typedef struct { - ngx_shm_zone_t *shm_zone; - ngx_rbtree_node_t *node; + ngx_shm_zone_t *shm_zone; + ngx_rbtree_node_t *node; } ngx_stream_limit_conn_cleanup_t; typedef struct { - ngx_rbtree_t *rbtree; + ngx_rbtree_t *rbtree; + ngx_stream_complex_value_t key; } ngx_stream_limit_conn_ctx_t; typedef struct { - ngx_shm_zone_t *shm_zone; - ngx_uint_t conn; + ngx_shm_zone_t *shm_zone; + ngx_uint_t conn; } ngx_stream_limit_conn_limit_t; typedef struct { - ngx_array_t limits; - ngx_uint_t log_level; + ngx_array_t limits; + ngx_uint_t log_level; } ngx_stream_limit_conn_conf_t; @@ -93,28 +94,29 @@ static ngx_command_t ngx_stream_limit_conn_commands[] = { static ngx_stream_module_t ngx_stream_limit_conn_module_ctx = { + NULL, /* preconfiguration */ ngx_stream_limit_conn_init, /* postconfiguration */ NULL, /* create main configuration */ NULL, /* init main configuration */ ngx_stream_limit_conn_create_conf, /* create server configuration */ - ngx_stream_limit_conn_merge_conf, /* merge server configuration */ + ngx_stream_limit_conn_merge_conf /* merge server configuration */ }; ngx_module_t ngx_stream_limit_conn_module = { NGX_MODULE_V1, - &ngx_stream_limit_conn_module_ctx, /* module context */ - ngx_stream_limit_conn_commands, /* module directives */ - NGX_STREAM_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ + &ngx_stream_limit_conn_module_ctx, /* module context */ + ngx_stream_limit_conn_commands, /* module directives */ + NGX_STREAM_MODULE, /* module type */ + NULL, /* init master */ + NULL, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ NGX_MODULE_V1_PADDING }; @@ -129,48 +131,36 @@ ngx_stream_limit_conn_handler(ngx_stream_session_t *s) ngx_slab_pool_t *shpool; ngx_rbtree_node_t *node; ngx_pool_cleanup_t *cln; - struct sockaddr_in *sin; -#if (NGX_HAVE_INET6) - struct sockaddr_in6 *sin6; -#endif ngx_stream_limit_conn_ctx_t *ctx; ngx_stream_limit_conn_node_t *lc; ngx_stream_limit_conn_conf_t *lccf; ngx_stream_limit_conn_limit_t *limits; ngx_stream_limit_conn_cleanup_t *lccln; - switch (s->connection->sockaddr->sa_family) { - - case AF_INET: - sin = (struct sockaddr_in *) s->connection->sockaddr; - - key.len = sizeof(in_addr_t); - key.data = (u_char *) &sin->sin_addr; - - break; - -#if (NGX_HAVE_INET6) - case AF_INET6: - sin6 = (struct sockaddr_in6 *) s->connection->sockaddr; - - key.len = sizeof(struct in6_addr); - key.data = sin6->sin6_addr.s6_addr; - - break; -#endif - - default: - return NGX_DECLINED; - } - - hash = ngx_crc32_short(key.data, key.len); - lccf = ngx_stream_get_module_srv_conf(s, ngx_stream_limit_conn_module); limits = lccf->limits.elts; for (i = 0; i < lccf->limits.nelts; i++) { ctx = limits[i].shm_zone->data; + if (ngx_stream_complex_value(s, &ctx->key, &key) != NGX_OK) { + return NGX_ERROR; + } + + if (key.len == 0) { + continue; + } + + if (key.len > 255) { + ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, + "the value of the \"%V\" key " + "is more than 255 bytes: \"%V\"", + &ctx->key.value, &key); + continue; + } + + hash = ngx_crc32_short(key.data, key.len); + shpool = (ngx_slab_pool_t *) limits[i].shm_zone->shm.addr; ngx_shmtx_lock(&shpool->mutex); @@ -382,6 +372,19 @@ ngx_stream_limit_conn_init_zone(ngx_shm_zone_t *shm_zone, void *data) ctx = shm_zone->data; if (octx) { + if (ctx->key.value.len != octx->key.value.len + || ngx_strncmp(ctx->key.value.data, octx->key.value.data, + ctx->key.value.len) + != 0) + { + ngx_log_error(NGX_LOG_EMERG, shm_zone->shm.log, 0, + "limit_conn_zone \"%V\" uses the \"%V\" key " + "while previously it used the \"%V\" key", + &shm_zone->shm.name, &ctx->key.value, + &octx->key.value); + return NGX_ERROR; + } + ctx->rbtree = octx->rbtree; return NGX_OK; @@ -465,12 +468,13 @@ ngx_stream_limit_conn_merge_conf(ngx_conf_t *cf, void *parent, void *child) static char * ngx_stream_limit_conn_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { - u_char *p; - ssize_t size; - ngx_str_t *value, name, s; - ngx_uint_t i; - ngx_shm_zone_t *shm_zone; - ngx_stream_limit_conn_ctx_t *ctx; + u_char *p; + ssize_t size; + ngx_str_t *value, name, s; + ngx_uint_t i; + ngx_shm_zone_t *shm_zone; + ngx_stream_limit_conn_ctx_t *ctx; + ngx_stream_compile_complex_value_t ccv; value = cf->args->elts; @@ -479,6 +483,16 @@ ngx_stream_limit_conn_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_ERROR; } + ngx_memzero(&ccv, sizeof(ngx_stream_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[1]; + ccv.complex_value = &ctx->key; + + if (ngx_stream_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + size = 0; name.len = 0; @@ -537,17 +551,11 @@ ngx_stream_limit_conn_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) } if (shm_zone->data) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "%V \"%V\" is already bound to key " - "\"$binary_remote_addr\"", - &cmd->name, &name); - return NGX_CONF_ERROR; - } + ctx = shm_zone->data; - if (ngx_strcmp(value[1].data, "$binary_remote_addr") != 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "unsupported key \"%V\", use " - "$binary_remote_addr", &value[1]); + "%V \"%V\" is already bound to key \"%V\"", + &cmd->name, &name, &ctx->key.value); return NGX_CONF_ERROR; } diff --git a/src/stream/ngx_stream_map_module.c b/src/stream/ngx_stream_map_module.c new file mode 100644 index 0000000..47a15be --- /dev/null +++ b/src/stream/ngx_stream_map_module.c @@ -0,0 +1,574 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + + +typedef struct { + ngx_uint_t hash_max_size; + ngx_uint_t hash_bucket_size; +} ngx_stream_map_conf_t; + + +typedef struct { + ngx_hash_keys_arrays_t keys; + + ngx_array_t *values_hash; +#if (NGX_PCRE) + ngx_array_t regexes; +#endif + + ngx_stream_variable_value_t *default_value; + ngx_conf_t *cf; + ngx_uint_t hostnames; /* unsigned hostnames:1 */ +} ngx_stream_map_conf_ctx_t; + + +typedef struct { + ngx_stream_map_t map; + ngx_stream_complex_value_t value; + ngx_stream_variable_value_t *default_value; + ngx_uint_t hostnames; /* unsigned hostnames:1 */ +} ngx_stream_map_ctx_t; + + +static int ngx_libc_cdecl ngx_stream_map_cmp_dns_wildcards(const void *one, + const void *two); +static void *ngx_stream_map_create_conf(ngx_conf_t *cf); +static char *ngx_stream_map_block(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); +static char *ngx_stream_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf); + + +static ngx_command_t ngx_stream_map_commands[] = { + + { ngx_string("map"), + NGX_STREAM_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE2, + ngx_stream_map_block, + NGX_STREAM_MAIN_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("map_hash_max_size"), + NGX_STREAM_MAIN_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_STREAM_MAIN_CONF_OFFSET, + offsetof(ngx_stream_map_conf_t, hash_max_size), + NULL }, + + { ngx_string("map_hash_bucket_size"), + NGX_STREAM_MAIN_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_STREAM_MAIN_CONF_OFFSET, + offsetof(ngx_stream_map_conf_t, hash_bucket_size), + NULL }, + + ngx_null_command +}; + + +static ngx_stream_module_t ngx_stream_map_module_ctx = { + NULL, /* preconfiguration */ + NULL, /* postconfiguration */ + + ngx_stream_map_create_conf, /* create main configuration */ + NULL, /* init main configuration */ + + NULL, /* create server configuration */ + NULL /* merge server configuration */ +}; + + +ngx_module_t ngx_stream_map_module = { + NGX_MODULE_V1, + &ngx_stream_map_module_ctx, /* module context */ + ngx_stream_map_commands, /* module directives */ + NGX_STREAM_MODULE, /* module type */ + NULL, /* init master */ + NULL, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + + +static ngx_int_t +ngx_stream_map_variable(ngx_stream_session_t *s, ngx_stream_variable_value_t *v, + uintptr_t data) +{ + ngx_stream_map_ctx_t *map = (ngx_stream_map_ctx_t *) data; + + ngx_str_t val, str; + ngx_stream_complex_value_t *cv; + ngx_stream_variable_value_t *value; + + ngx_log_debug0(NGX_LOG_DEBUG_STREAM, s->connection->log, 0, + "stream map started"); + + if (ngx_stream_complex_value(s, &map->value, &val) != NGX_OK) { + return NGX_ERROR; + } + + if (map->hostnames && val.len > 0 && val.data[val.len - 1] == '.') { + val.len--; + } + + value = ngx_stream_map_find(s, &map->map, &val); + + if (value == NULL) { + value = map->default_value; + } + + if (!value->valid) { + cv = (ngx_stream_complex_value_t *) value->data; + + if (ngx_stream_complex_value(s, cv, &str) != NGX_OK) { + return NGX_ERROR; + } + + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->len = str.len; + v->data = str.data; + + } else { + *v = *value; + } + + ngx_log_debug2(NGX_LOG_DEBUG_STREAM, s->connection->log, 0, + "stream map: \"%V\" \"%v\"", &val, v); + + return NGX_OK; +} + + +static void * +ngx_stream_map_create_conf(ngx_conf_t *cf) +{ + ngx_stream_map_conf_t *mcf; + + mcf = ngx_palloc(cf->pool, sizeof(ngx_stream_map_conf_t)); + if (mcf == NULL) { + return NULL; + } + + mcf->hash_max_size = NGX_CONF_UNSET_UINT; + mcf->hash_bucket_size = NGX_CONF_UNSET_UINT; + + return mcf; +} + + +static char * +ngx_stream_map_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_stream_map_conf_t *mcf = conf; + + char *rv; + ngx_str_t *value, name; + ngx_conf_t save; + ngx_pool_t *pool; + ngx_hash_init_t hash; + ngx_stream_map_ctx_t *map; + ngx_stream_variable_t *var; + ngx_stream_map_conf_ctx_t ctx; + ngx_stream_compile_complex_value_t ccv; + + if (mcf->hash_max_size == NGX_CONF_UNSET_UINT) { + mcf->hash_max_size = 2048; + } + + if (mcf->hash_bucket_size == NGX_CONF_UNSET_UINT) { + mcf->hash_bucket_size = ngx_cacheline_size; + + } else { + mcf->hash_bucket_size = ngx_align(mcf->hash_bucket_size, + ngx_cacheline_size); + } + + map = ngx_pcalloc(cf->pool, sizeof(ngx_stream_map_ctx_t)); + if (map == NULL) { + return NGX_CONF_ERROR; + } + + value = cf->args->elts; + + ngx_memzero(&ccv, sizeof(ngx_stream_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[1]; + ccv.complex_value = &map->value; + + if (ngx_stream_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + + 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++; + + var = ngx_stream_add_variable(cf, &name, NGX_STREAM_VAR_CHANGEABLE); + if (var == NULL) { + return NGX_CONF_ERROR; + } + + var->get_handler = ngx_stream_map_variable; + var->data = (uintptr_t) map; + + pool = ngx_create_pool(NGX_DEFAULT_POOL_SIZE, cf->log); + if (pool == NULL) { + return NGX_CONF_ERROR; + } + + ctx.keys.pool = cf->pool; + ctx.keys.temp_pool = pool; + + if (ngx_hash_keys_array_init(&ctx.keys, NGX_HASH_LARGE) != NGX_OK) { + ngx_destroy_pool(pool); + return NGX_CONF_ERROR; + } + + ctx.values_hash = ngx_pcalloc(pool, sizeof(ngx_array_t) * ctx.keys.hsize); + if (ctx.values_hash == NULL) { + ngx_destroy_pool(pool); + return NGX_CONF_ERROR; + } + +#if (NGX_PCRE) + if (ngx_array_init(&ctx.regexes, cf->pool, 2, + sizeof(ngx_stream_map_regex_t)) + != NGX_OK) + { + ngx_destroy_pool(pool); + return NGX_CONF_ERROR; + } +#endif + + ctx.default_value = NULL; + ctx.cf = &save; + ctx.hostnames = 0; + + save = *cf; + cf->pool = pool; + cf->ctx = &ctx; + cf->handler = ngx_stream_map; + cf->handler_conf = conf; + + rv = ngx_conf_parse(cf, NULL); + + *cf = save; + + if (rv != NGX_CONF_OK) { + ngx_destroy_pool(pool); + return rv; + } + + map->default_value = ctx.default_value ? ctx.default_value: + &ngx_stream_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; + hash.name = "map_hash"; + hash.pool = cf->pool; + + if (ctx.keys.keys.nelts) { + hash.hash = &map->map.hash.hash; + hash.temp_pool = NULL; + + if (ngx_hash_init(&hash, ctx.keys.keys.elts, ctx.keys.keys.nelts) + != NGX_OK) + { + ngx_destroy_pool(pool); + return NGX_CONF_ERROR; + } + } + + if (ctx.keys.dns_wc_head.nelts) { + + ngx_qsort(ctx.keys.dns_wc_head.elts, + (size_t) ctx.keys.dns_wc_head.nelts, + sizeof(ngx_hash_key_t), ngx_stream_map_cmp_dns_wildcards); + + hash.hash = NULL; + hash.temp_pool = pool; + + if (ngx_hash_wildcard_init(&hash, ctx.keys.dns_wc_head.elts, + ctx.keys.dns_wc_head.nelts) + != NGX_OK) + { + ngx_destroy_pool(pool); + return NGX_CONF_ERROR; + } + + map->map.hash.wc_head = (ngx_hash_wildcard_t *) hash.hash; + } + + if (ctx.keys.dns_wc_tail.nelts) { + + ngx_qsort(ctx.keys.dns_wc_tail.elts, + (size_t) ctx.keys.dns_wc_tail.nelts, + sizeof(ngx_hash_key_t), ngx_stream_map_cmp_dns_wildcards); + + hash.hash = NULL; + hash.temp_pool = pool; + + if (ngx_hash_wildcard_init(&hash, ctx.keys.dns_wc_tail.elts, + ctx.keys.dns_wc_tail.nelts) + != NGX_OK) + { + ngx_destroy_pool(pool); + return NGX_CONF_ERROR; + } + + map->map.hash.wc_tail = (ngx_hash_wildcard_t *) hash.hash; + } + +#if (NGX_PCRE) + + if (ctx.regexes.nelts) { + map->map.regex = ctx.regexes.elts; + map->map.nregex = ctx.regexes.nelts; + } + +#endif + + ngx_destroy_pool(pool); + + return rv; +} + + +static int ngx_libc_cdecl +ngx_stream_map_cmp_dns_wildcards(const void *one, const void *two) +{ + ngx_hash_key_t *first, *second; + + first = (ngx_hash_key_t *) one; + second = (ngx_hash_key_t *) two; + + return ngx_dns_strcmp(first->key.data, second->key.data); +} + + +static char * +ngx_stream_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) +{ + u_char *data; + size_t len; + ngx_int_t rv; + ngx_str_t *value, v; + ngx_uint_t i, key; + ngx_stream_map_conf_ctx_t *ctx; + ngx_stream_complex_value_t cv, *cvp; + ngx_stream_variable_value_t *var, **vp; + ngx_stream_compile_complex_value_t ccv; + + ctx = cf->ctx; + + value = cf->args->elts; + + if (cf->args->nelts == 1 + && ngx_strcmp(value[0].data, "hostnames") == 0) + { + ctx->hostnames = 1; + return NGX_CONF_OK; + + } else if (cf->args->nelts != 2) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid number of the map parameters"); + return NGX_CONF_ERROR; + } + + if (ngx_strcmp(value[0].data, "include") == 0) { + return ngx_conf_include(cf, dummy, conf); + } + + key = 0; + + for (i = 0; i < value[1].len; i++) { + key = ngx_hash(key, value[1].data[i]); + } + + key %= ctx->keys.hsize; + + vp = ctx->values_hash[key].elts; + + if (vp) { + for (i = 0; i < ctx->values_hash[key].nelts; i++) { + + if (vp[i]->valid) { + data = vp[i]->data; + len = vp[i]->len; + + } else { + cvp = (ngx_stream_complex_value_t *) vp[i]->data; + data = cvp->value.data; + len = cvp->value.len; + } + + if (value[1].len != len) { + continue; + } + + if (ngx_strncmp(value[1].data, data, len) == 0) { + var = vp[i]; + goto found; + } + } + + } else { + if (ngx_array_init(&ctx->values_hash[key], cf->pool, 4, + sizeof(ngx_stream_variable_value_t *)) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + } + + var = ngx_palloc(ctx->keys.pool, sizeof(ngx_stream_variable_value_t)); + if (var == NULL) { + return NGX_CONF_ERROR; + } + + v.len = value[1].len; + v.data = ngx_pstrdup(ctx->keys.pool, &value[1]); + if (v.data == NULL) { + return NGX_CONF_ERROR; + } + + ngx_memzero(&ccv, sizeof(ngx_stream_compile_complex_value_t)); + + ccv.cf = ctx->cf; + ccv.value = &v; + ccv.complex_value = &cv; + + if (ngx_stream_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + + if (cv.lengths != NULL) { + cvp = ngx_palloc(ctx->keys.pool, sizeof(ngx_stream_complex_value_t)); + if (cvp == NULL) { + return NGX_CONF_ERROR; + } + + *cvp = cv; + + var->len = 0; + var->data = (u_char *) cvp; + var->valid = 0; + + } else { + var->len = v.len; + var->data = v.data; + var->valid = 1; + } + + var->no_cacheable = 0; + var->not_found = 0; + + vp = ngx_array_push(&ctx->values_hash[key]); + if (vp == NULL) { + return NGX_CONF_ERROR; + } + + *vp = var; + +found: + + if (ngx_strcmp(value[0].data, "default") == 0) { + + if (ctx->default_value) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "duplicate default map parameter"); + return NGX_CONF_ERROR; + } + + ctx->default_value = var; + + return NGX_CONF_OK; + } + +#if (NGX_PCRE) + + if (value[0].len && value[0].data[0] == '~') { + ngx_regex_compile_t rc; + ngx_stream_map_regex_t *regex; + u_char errstr[NGX_MAX_CONF_ERRSTR]; + + regex = ngx_array_push(&ctx->regexes); + if (regex == NULL) { + return NGX_CONF_ERROR; + } + + value[0].len--; + value[0].data++; + + ngx_memzero(&rc, sizeof(ngx_regex_compile_t)); + + if (value[0].data[0] == '*') { + value[0].len--; + value[0].data++; + rc.options = NGX_REGEX_CASELESS; + } + + rc.pattern = value[0]; + rc.err.len = NGX_MAX_CONF_ERRSTR; + rc.err.data = errstr; + + regex->regex = ngx_stream_regex_compile(ctx->cf, &rc); + if (regex->regex == NULL) { + return NGX_CONF_ERROR; + } + + regex->value = var; + + return NGX_CONF_OK; + } + +#endif + + if (value[0].len && value[0].data[0] == '\\') { + value[0].len--; + value[0].data++; + } + + rv = ngx_hash_add_key(&ctx->keys, &value[0], var, + (ctx->hostnames) ? NGX_HASH_WILDCARD_KEY : 0); + + if (rv == NGX_OK) { + return NGX_CONF_OK; + } + + if (rv == NGX_DECLINED) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid hostname or wildcard \"%V\"", &value[0]); + } + + if (rv == NGX_BUSY) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "conflicting parameter \"%V\"", &value[0]); + } + + return NGX_CONF_ERROR; +} diff --git a/src/stream/ngx_stream_proxy_module.c b/src/stream/ngx_stream_proxy_module.c index 6c535fd..9d43109 100644 --- a/src/stream/ngx_stream_proxy_module.c +++ b/src/stream/ngx_stream_proxy_module.c @@ -10,6 +10,15 @@ #include +typedef struct { + ngx_addr_t *addr; + ngx_stream_complex_value_t *value; +#if (NGX_HAVE_TRANSPARENT_PROXY) + ngx_uint_t transparent; /* unsigned transparent:1; */ +#endif +} ngx_stream_upstream_local_t; + + typedef struct { ngx_msec_t connect_timeout; ngx_msec_t timeout; @@ -21,14 +30,14 @@ typedef struct { ngx_uint_t next_upstream_tries; ngx_flag_t next_upstream; ngx_flag_t proxy_protocol; - ngx_addr_t *local; + ngx_stream_upstream_local_t *local; #if (NGX_STREAM_SSL) ngx_flag_t ssl_enable; ngx_flag_t ssl_session_reuse; ngx_uint_t ssl_protocols; ngx_str_t ssl_ciphers; - ngx_str_t ssl_name; + ngx_stream_complex_value_t *ssl_name; ngx_flag_t ssl_server_name; ngx_flag_t ssl_verify; @@ -43,12 +52,18 @@ typedef struct { #endif ngx_stream_upstream_srv_conf_t *upstream; + ngx_stream_complex_value_t *upstream_value; } ngx_stream_proxy_srv_conf_t; static void ngx_stream_proxy_handler(ngx_stream_session_t *s); +static ngx_int_t ngx_stream_proxy_eval(ngx_stream_session_t *s, + ngx_stream_proxy_srv_conf_t *pscf); +static ngx_int_t ngx_stream_proxy_set_local(ngx_stream_session_t *s, + ngx_stream_upstream_t *u, ngx_stream_upstream_local_t *local); static void ngx_stream_proxy_connect(ngx_stream_session_t *s); static void ngx_stream_proxy_init_upstream(ngx_stream_session_t *s); +static void ngx_stream_proxy_resolve_handler(ngx_resolver_ctx_t *ctx); static void ngx_stream_proxy_upstream_handler(ngx_event_t *ev); static void ngx_stream_proxy_downstream_handler(ngx_event_t *ev); static void ngx_stream_proxy_process_connection(ngx_event_t *ev, @@ -113,7 +128,7 @@ static ngx_command_t ngx_stream_proxy_commands[] = { NULL }, { ngx_string("proxy_bind"), - NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, + NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE12, ngx_stream_proxy_bind, NGX_STREAM_SRV_CONF_OFFSET, 0, @@ -235,7 +250,7 @@ static ngx_command_t ngx_stream_proxy_commands[] = { { ngx_string("proxy_ssl_name"), NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_stream_set_complex_value_slot, NGX_STREAM_SRV_CONF_OFFSET, offsetof(ngx_stream_proxy_srv_conf_t, ssl_name), NULL }, @@ -303,6 +318,7 @@ static ngx_command_t ngx_stream_proxy_commands[] = { static ngx_stream_module_t ngx_stream_proxy_module_ctx = { + NULL, /* preconfiguration */ NULL, /* postconfiguration */ NULL, /* create main configuration */ @@ -332,11 +348,16 @@ ngx_module_t ngx_stream_proxy_module = { static void ngx_stream_proxy_handler(ngx_stream_session_t *s) { - u_char *p; - ngx_connection_t *c; - ngx_stream_upstream_t *u; - ngx_stream_proxy_srv_conf_t *pscf; - ngx_stream_upstream_srv_conf_t *uscf; + u_char *p; + ngx_str_t *host; + ngx_uint_t i; + ngx_connection_t *c; + ngx_resolver_ctx_t *ctx, temp; + ngx_stream_upstream_t *u; + ngx_stream_core_srv_conf_t *cscf; + ngx_stream_proxy_srv_conf_t *pscf; + ngx_stream_upstream_srv_conf_t *uscf, **uscfp; + ngx_stream_upstream_main_conf_t *umcf; c = s->connection; @@ -358,10 +379,168 @@ ngx_stream_proxy_handler(ngx_stream_session_t *s) u->peer.log = c->log; u->peer.log_error = NGX_ERROR_ERR; - u->peer.local = pscf->local; + if (ngx_stream_proxy_set_local(s, u, pscf->local) != NGX_OK) { + ngx_stream_proxy_finalize(s, NGX_ERROR); + return; + } + u->peer.type = c->type; - uscf = pscf->upstream; + u->proxy_protocol = pscf->proxy_protocol; + u->start_sec = ngx_time(); + + c->write->handler = ngx_stream_proxy_downstream_handler; + c->read->handler = ngx_stream_proxy_downstream_handler; + + if (c->type == SOCK_STREAM) { + p = ngx_pnalloc(c->pool, pscf->buffer_size); + if (p == NULL) { + ngx_stream_proxy_finalize(s, NGX_ERROR); + return; + } + + u->downstream_buf.start = p; + u->downstream_buf.end = p + pscf->buffer_size; + u->downstream_buf.pos = p; + u->downstream_buf.last = p; + + if (u->proxy_protocol +#if (NGX_STREAM_SSL) + && pscf->ssl == NULL +#endif + && pscf->buffer_size >= NGX_PROXY_PROTOCOL_MAX_HEADER) + { + /* optimization for a typical case */ + + ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0, + "stream proxy send PROXY protocol header"); + + p = ngx_proxy_protocol_write(c, u->downstream_buf.last, + u->downstream_buf.end); + if (p == NULL) { + ngx_stream_proxy_finalize(s, NGX_ERROR); + return; + } + + u->downstream_buf.last = p; + u->proxy_protocol = 0; + } + + if (c->read->ready) { + ngx_post_event(c->read, &ngx_posted_events); + } + } + + if (pscf->upstream_value) { + if (ngx_stream_proxy_eval(s, pscf) != NGX_OK) { + ngx_stream_proxy_finalize(s, NGX_ERROR); + return; + } + } + + if (u->resolved == NULL) { + + uscf = pscf->upstream; + + } else { + +#if (NGX_STREAM_SSL) + u->ssl_name = u->resolved->host; +#endif + + host = &u->resolved->host; + + if (u->resolved->sockaddr) { + + if (u->resolved->port == 0 + && u->resolved->sockaddr->sa_family != AF_UNIX) + { + ngx_log_error(NGX_LOG_ERR, c->log, 0, + "no port in upstream \"%V\"", host); + ngx_stream_proxy_finalize(s, NGX_ERROR); + return; + } + + if (ngx_stream_upstream_create_round_robin_peer(s, u->resolved) + != NGX_OK) + { + ngx_stream_proxy_finalize(s, NGX_ERROR); + return; + } + + ngx_stream_proxy_connect(s); + + return; + } + + umcf = ngx_stream_get_module_main_conf(s, ngx_stream_upstream_module); + + uscfp = umcf->upstreams.elts; + + for (i = 0; i < umcf->upstreams.nelts; i++) { + + uscf = uscfp[i]; + + if (uscf->host.len == host->len + && ((uscf->port == 0 && u->resolved->no_port) + || uscf->port == u->resolved->port) + && ngx_strncasecmp(uscf->host.data, host->data, host->len) == 0) + { + goto found; + } + } + + if (u->resolved->port == 0) { + ngx_log_error(NGX_LOG_ERR, c->log, 0, + "no port in upstream \"%V\"", host); + ngx_stream_proxy_finalize(s, NGX_ERROR); + return; + } + + temp.name = *host; + + cscf = ngx_stream_get_module_srv_conf(s, ngx_stream_core_module); + + ctx = ngx_resolve_start(cscf->resolver, &temp); + if (ctx == NULL) { + ngx_stream_proxy_finalize(s, NGX_ERROR); + return; + } + + if (ctx == NGX_NO_RESOLVER) { + ngx_log_error(NGX_LOG_ERR, c->log, 0, + "no resolver defined to resolve %V", host); + ngx_stream_proxy_finalize(s, NGX_ERROR); + return; + } + + ctx->name = *host; + ctx->handler = ngx_stream_proxy_resolve_handler; + ctx->data = s; + ctx->timeout = cscf->resolver_timeout; + + u->resolved->ctx = ctx; + + if (ngx_resolve_name(ctx) != NGX_OK) { + u->resolved->ctx = NULL; + ngx_stream_proxy_finalize(s, NGX_ERROR); + return; + } + + return; + } + +found: + + if (uscf == NULL) { + ngx_log_error(NGX_LOG_ALERT, c->log, 0, "no upstream configuration"); + ngx_stream_proxy_finalize(s, NGX_ERROR); + return; + } + +#if (NGX_HTTP_SSL) + u->ssl_name = uscf->host; +#endif if (uscf->peer.init(s, uscf) != NGX_OK) { ngx_stream_proxy_finalize(s, NGX_ERROR); @@ -376,55 +555,111 @@ ngx_stream_proxy_handler(ngx_stream_session_t *s) u->peer.tries = pscf->next_upstream_tries; } - u->proxy_protocol = pscf->proxy_protocol; - u->start_sec = ngx_time(); + ngx_stream_proxy_connect(s); +} - c->write->handler = ngx_stream_proxy_downstream_handler; - c->read->handler = ngx_stream_proxy_downstream_handler; - if (c->type == SOCK_DGRAM) { - ngx_stream_proxy_connect(s); - return; +static ngx_int_t +ngx_stream_proxy_eval(ngx_stream_session_t *s, + ngx_stream_proxy_srv_conf_t *pscf) +{ + ngx_str_t host; + ngx_url_t url; + ngx_stream_upstream_t *u; + + if (ngx_stream_complex_value(s, pscf->upstream_value, &host) != NGX_OK) { + return NGX_ERROR; } - p = ngx_pnalloc(c->pool, pscf->buffer_size); - if (p == NULL) { - ngx_stream_proxy_finalize(s, NGX_ERROR); - return; - } + ngx_memzero(&url, sizeof(ngx_url_t)); - u->downstream_buf.start = p; - u->downstream_buf.end = p + pscf->buffer_size; - u->downstream_buf.pos = p; - u->downstream_buf.last = p; + url.url = host; + url.no_resolve = 1; - if (u->proxy_protocol -#if (NGX_STREAM_SSL) - && pscf->ssl == NULL -#endif - && pscf->buffer_size >= NGX_PROXY_PROTOCOL_MAX_HEADER) - { - /* optimization for a typical case */ - - ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0, - "stream proxy send PROXY protocol header"); - - p = ngx_proxy_protocol_write(c, u->downstream_buf.last, - u->downstream_buf.end); - if (p == NULL) { - ngx_stream_proxy_finalize(s, NGX_ERROR); - return; + if (ngx_parse_url(s->connection->pool, &url) != NGX_OK) { + if (url.err) { + ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, + "%s in upstream \"%V\"", url.err, &url.url); } - u->downstream_buf.last = p; - u->proxy_protocol = 0; + return NGX_ERROR; } - if (c->read->ready) { - ngx_post_event(c->read, &ngx_posted_events); + u = s->upstream; + + u->resolved = ngx_pcalloc(s->connection->pool, + sizeof(ngx_stream_upstream_resolved_t)); + if (u->resolved == NULL) { + return NGX_ERROR; } - ngx_stream_proxy_connect(s); + if (url.addrs && url.addrs[0].sockaddr) { + u->resolved->sockaddr = url.addrs[0].sockaddr; + u->resolved->socklen = url.addrs[0].socklen; + u->resolved->naddrs = 1; + u->resolved->host = url.addrs[0].name; + + } else { + u->resolved->host = url.host; + } + + u->resolved->port = url.port; + u->resolved->no_port = url.no_port; + + return NGX_OK; +} + + +static ngx_int_t +ngx_stream_proxy_set_local(ngx_stream_session_t *s, ngx_stream_upstream_t *u, + ngx_stream_upstream_local_t *local) +{ + ngx_int_t rc; + ngx_str_t val; + ngx_addr_t *addr; + + if (local == NULL) { + u->peer.local = NULL; + return NGX_OK; + } + +#if (NGX_HAVE_TRANSPARENT_PROXY) + u->peer.transparent = local->transparent; +#endif + + if (local->value == NULL) { + u->peer.local = local->addr; + return NGX_OK; + } + + if (ngx_stream_complex_value(s, local->value, &val) != NGX_OK) { + return NGX_ERROR; + } + + if (val.len == 0) { + return NGX_OK; + } + + addr = ngx_palloc(s->connection->pool, sizeof(ngx_addr_t)); + if (addr == NULL) { + return NGX_ERROR; + } + + rc = ngx_parse_addr_port(s->connection->pool, addr, val.data, val.len); + if (rc == NGX_ERROR) { + return NGX_ERROR; + } + + if (rc != NGX_OK) { + ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, + "invalid local address \"%V\"", &val); + return NGX_OK; + } + + addr->name = val; + u->peer.local = addr; + + return NGX_OK; } @@ -814,10 +1049,13 @@ ngx_stream_proxy_ssl_name(ngx_stream_session_t *s) u = s->upstream; - name = pscf->ssl_name; + if (pscf->ssl_name) { + if (ngx_stream_complex_value(s, pscf->ssl_name, &name) != NGX_OK) { + return NGX_ERROR; + } - if (name.len == 0) { - name = pscf->upstream->host; + } else { + name = u->ssl_name; } if (name.len == 0) { @@ -906,6 +1144,75 @@ ngx_stream_proxy_downstream_handler(ngx_event_t *ev) } +static void +ngx_stream_proxy_resolve_handler(ngx_resolver_ctx_t *ctx) +{ + ngx_stream_session_t *s; + ngx_stream_upstream_t *u; + ngx_stream_proxy_srv_conf_t *pscf; + ngx_stream_upstream_resolved_t *ur; + + s = ctx->data; + + u = s->upstream; + ur = u->resolved; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, + "stream upstream resolve"); + + if (ctx->state) { + ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, + "%V could not be resolved (%i: %s)", + &ctx->name, ctx->state, + ngx_resolver_strerror(ctx->state)); + + ngx_stream_proxy_finalize(s, NGX_ERROR); + return; + } + + ur->naddrs = ctx->naddrs; + ur->addrs = ctx->addrs; + +#if (NGX_DEBUG) + { + u_char text[NGX_SOCKADDR_STRLEN]; + ngx_str_t addr; + ngx_uint_t i; + + addr.data = text; + + for (i = 0; i < ctx->naddrs; i++) { + addr.len = ngx_sock_ntop(ur->addrs[i].sockaddr, ur->addrs[i].socklen, + text, NGX_SOCKADDR_STRLEN, 0); + + ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0, + "name was resolved to %V", &addr); + } + } +#endif + + if (ngx_stream_upstream_create_round_robin_peer(s, ur) != NGX_OK) { + ngx_stream_proxy_finalize(s, NGX_ERROR); + return; + } + + ngx_resolve_name_done(ctx); + ur->ctx = NULL; + + u->peer.start_time = ngx_current_msec; + + pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module); + + if (pscf->next_upstream_tries + && u->peer.tries > pscf->next_upstream_tries) + { + u->peer.tries = pscf->next_upstream_tries; + } + + ngx_stream_proxy_connect(s); +} + + static void ngx_stream_proxy_upstream_handler(ngx_event_t *ev) { @@ -1328,6 +1635,11 @@ ngx_stream_proxy_finalize(ngx_stream_session_t *s, ngx_int_t rc) goto noupstream; } + if (u->resolved && u->resolved->ctx) { + ngx_resolve_name_done(u->resolved->ctx); + u->resolved->ctx = NULL; + } + if (u->peer.free && u->peer.sockaddr) { u->peer.free(&u->peer, u->peer.data, 0); u->peer.sockaddr = NULL; @@ -1402,7 +1714,7 @@ ngx_stream_proxy_create_srv_conf(ngx_conf_t *cf) * * conf->ssl_protocols = 0; * conf->ssl_ciphers = { 0, NULL }; - * conf->ssl_name = { 0, NULL }; + * conf->ssl_name = NULL; * conf->ssl_trusted_certificate = { 0, NULL }; * conf->ssl_crl = { 0, NULL }; * conf->ssl_certificate = { 0, NULL }; @@ -1410,6 +1722,7 @@ ngx_stream_proxy_create_srv_conf(ngx_conf_t *cf) * * conf->ssl = NULL; * conf->upstream = NULL; + * conf->upstream_value = NULL; */ conf->connect_timeout = NGX_CONF_UNSET_MSEC; @@ -1486,7 +1799,9 @@ ngx_stream_proxy_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers, "DEFAULT"); - ngx_conf_merge_str_value(conf->ssl_name, prev->ssl_name, ""); + if (conf->ssl_name == NULL) { + conf->ssl_name = prev->ssl_name; + } ngx_conf_merge_value(conf->ssl_server_name, prev->ssl_server_name, 0); @@ -1561,13 +1876,7 @@ ngx_stream_proxy_set_ssl(ngx_conf_t *cf, ngx_stream_proxy_srv_conf_t *pscf) } } - if (SSL_CTX_set_cipher_list(pscf->ssl->ctx, - (const char *) pscf->ssl_ciphers.data) - == 0) - { - ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, - "SSL_CTX_set_cipher_list(\"%V\") failed", - &pscf->ssl_ciphers); + if (ngx_ssl_ciphers(cf, pscf->ssl, &pscf->ssl_ciphers, 0) != NGX_OK) { return NGX_ERROR; } @@ -1602,11 +1911,13 @@ ngx_stream_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_stream_proxy_srv_conf_t *pscf = conf; - ngx_url_t u; - ngx_str_t *value, *url; - ngx_stream_core_srv_conf_t *cscf; + ngx_url_t u; + ngx_str_t *value, *url; + ngx_stream_complex_value_t cv; + ngx_stream_core_srv_conf_t *cscf; + ngx_stream_compile_complex_value_t ccv; - if (pscf->upstream) { + if (pscf->upstream || pscf->upstream_value) { return "is duplicate"; } @@ -1618,6 +1929,28 @@ ngx_stream_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) url = &value[1]; + ngx_memzero(&ccv, sizeof(ngx_stream_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = url; + ccv.complex_value = &cv; + + if (ngx_stream_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + + if (cv.lengths) { + pscf->upstream_value = ngx_palloc(cf->pool, + sizeof(ngx_stream_complex_value_t)); + if (pscf->upstream_value == NULL) { + return NGX_CONF_ERROR; + } + + *pscf->upstream_value = cv; + + return NGX_CONF_OK; + } + ngx_memzero(&u, sizeof(ngx_url_t)); u.url = *url; @@ -1637,8 +1970,11 @@ ngx_stream_proxy_bind(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_stream_proxy_srv_conf_t *pscf = conf; - ngx_int_t rc; - ngx_str_t *value; + ngx_int_t rc; + ngx_str_t *value; + ngx_stream_complex_value_t cv; + ngx_stream_upstream_local_t *local; + ngx_stream_compile_complex_value_t ccv; if (pscf->local != NGX_CONF_UNSET_PTR) { return "is duplicate"; @@ -1646,29 +1982,75 @@ ngx_stream_proxy_bind(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) value = cf->args->elts; - if (ngx_strcmp(value[1].data, "off") == 0) { + if (cf->args->nelts == 2 && ngx_strcmp(value[1].data, "off") == 0) { pscf->local = NULL; return NGX_CONF_OK; } - pscf->local = ngx_palloc(cf->pool, sizeof(ngx_addr_t)); - if (pscf->local == NULL) { + ngx_memzero(&ccv, sizeof(ngx_stream_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[1]; + ccv.complex_value = &cv; + + if (ngx_stream_compile_complex_value(&ccv) != NGX_OK) { return NGX_CONF_ERROR; } - rc = ngx_parse_addr(cf->pool, pscf->local, value[1].data, value[1].len); - - switch (rc) { - case NGX_OK: - pscf->local->name = value[1]; - return NGX_CONF_OK; - - case NGX_DECLINED: - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid address \"%V\"", &value[1]); - /* fall through */ - - default: + local = ngx_pcalloc(cf->pool, sizeof(ngx_stream_upstream_local_t)); + if (local == NULL) { return NGX_CONF_ERROR; } + + pscf->local = local; + + if (cv.lengths) { + local->value = ngx_palloc(cf->pool, sizeof(ngx_stream_complex_value_t)); + if (local->value == NULL) { + return NGX_CONF_ERROR; + } + + *local->value = cv; + + } else { + local->addr = ngx_palloc(cf->pool, sizeof(ngx_addr_t)); + if (local->addr == NULL) { + return NGX_CONF_ERROR; + } + + rc = ngx_parse_addr_port(cf->pool, local->addr, value[1].data, + value[1].len); + + switch (rc) { + case NGX_OK: + local->addr->name = value[1]; + break; + + case NGX_DECLINED: + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid address \"%V\"", &value[1]); + /* fall through */ + + default: + return NGX_CONF_ERROR; + } + } + + if (cf->args->nelts > 2) { + if (ngx_strcmp(value[2].data, "transparent") == 0) { +#if (NGX_HAVE_TRANSPARENT_PROXY) + local->transparent = 1; +#else + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "transparent proxying is not supported " + "on this platform, ignored"); +#endif + } else { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid parameter \"%V\"", &value[2]); + return NGX_CONF_ERROR; + } + } + + return NGX_CONF_OK; } diff --git a/src/stream/ngx_stream_return_module.c b/src/stream/ngx_stream_return_module.c new file mode 100644 index 0000000..3ab9bdf --- /dev/null +++ b/src/stream/ngx_stream_return_module.c @@ -0,0 +1,207 @@ + +/* + * Copyright (C) Roman Arutyunyan + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + + +typedef struct { + ngx_stream_complex_value_t text; +} ngx_stream_return_srv_conf_t; + + +typedef struct { + ngx_buf_t buf; +} ngx_stream_return_ctx_t; + + +static void ngx_stream_return_handler(ngx_stream_session_t *s); +static void ngx_stream_return_write_handler(ngx_event_t *ev); + +static void *ngx_stream_return_create_srv_conf(ngx_conf_t *cf); +static char *ngx_stream_return(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); + + +static ngx_command_t ngx_stream_return_commands[] = { + + { ngx_string("return"), + NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, + ngx_stream_return, + NGX_STREAM_SRV_CONF_OFFSET, + 0, + NULL }, + + ngx_null_command +}; + + +static ngx_stream_module_t ngx_stream_return_module_ctx = { + NULL, /* preconfiguration */ + NULL, /* postconfiguration */ + + NULL, /* create main configuration */ + NULL, /* init main configuration */ + + ngx_stream_return_create_srv_conf, /* create server configuration */ + NULL /* merge server configuration */ +}; + + +ngx_module_t ngx_stream_return_module = { + NGX_MODULE_V1, + &ngx_stream_return_module_ctx, /* module context */ + ngx_stream_return_commands, /* module directives */ + NGX_STREAM_MODULE, /* module type */ + NULL, /* init master */ + NULL, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + + +static void +ngx_stream_return_handler(ngx_stream_session_t *s) +{ + ngx_str_t text; + ngx_connection_t *c; + ngx_stream_return_ctx_t *ctx; + ngx_stream_return_srv_conf_t *rscf; + + c = s->connection; + + c->log->action = "returning text"; + + rscf = ngx_stream_get_module_srv_conf(s, ngx_stream_return_module); + + if (ngx_stream_complex_value(s, &rscf->text, &text) != NGX_OK) { + ngx_stream_close_connection(c); + return; + } + + ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0, + "stream return text: \"%V\"", &text); + + if (text.len == 0) { + ngx_stream_close_connection(c); + return; + } + + ctx = ngx_pcalloc(c->pool, sizeof(ngx_stream_return_ctx_t)); + if (ctx == NULL) { + ngx_stream_close_connection(c); + return; + } + + ngx_stream_set_ctx(s, ctx, ngx_stream_return_module); + + ctx->buf.pos = text.data; + ctx->buf.last = text.data + text.len; + + c->write->handler = ngx_stream_return_write_handler; + + ngx_stream_return_write_handler(c->write); +} + + +static void +ngx_stream_return_write_handler(ngx_event_t *ev) +{ + ssize_t n; + ngx_buf_t *b; + ngx_connection_t *c; + ngx_stream_session_t *s; + ngx_stream_return_ctx_t *ctx; + + c = ev->data; + s = c->data; + + if (ev->timedout) { + ngx_connection_error(c, NGX_ETIMEDOUT, "connection timed out"); + ngx_stream_close_connection(c); + return; + } + + if (ev->ready) { + ctx = ngx_stream_get_module_ctx(s, ngx_stream_return_module); + + b = &ctx->buf; + + n = c->send(c, b->pos, b->last - b->pos); + if (n == NGX_ERROR) { + ngx_stream_close_connection(c); + return; + } + + if (n > 0) { + b->pos += n; + + if (b->pos == b->last) { + ngx_stream_close_connection(c); + return; + } + } + } + + if (ngx_handle_write_event(ev, 0) != NGX_OK) { + ngx_stream_close_connection(c); + return; + } + + ngx_add_timer(ev, 5000); +} + + +static void * +ngx_stream_return_create_srv_conf(ngx_conf_t *cf) +{ + ngx_stream_return_srv_conf_t *conf; + + conf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_return_srv_conf_t)); + if (conf == NULL) { + return NULL; + } + + return conf; +} + + +static char * +ngx_stream_return(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_stream_return_srv_conf_t *rscf = conf; + + ngx_str_t *value; + ngx_stream_core_srv_conf_t *cscf; + ngx_stream_compile_complex_value_t ccv; + + if (rscf->text.value.data) { + return "is duplicate"; + } + + value = cf->args->elts; + + ngx_memzero(&ccv, sizeof(ngx_stream_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[1]; + ccv.complex_value = &rscf->text; + + if (ngx_stream_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + + cscf = ngx_stream_conf_get_module_srv_conf(cf, ngx_stream_core_module); + + cscf->handler = ngx_stream_return_handler; + + return NGX_CONF_OK; +} diff --git a/src/stream/ngx_stream_script.c b/src/stream/ngx_stream_script.c new file mode 100644 index 0000000..8130f92 --- /dev/null +++ b/src/stream/ngx_stream_script.c @@ -0,0 +1,854 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + + +static ngx_int_t ngx_stream_script_init_arrays( + ngx_stream_script_compile_t *sc); +static ngx_int_t ngx_stream_script_done(ngx_stream_script_compile_t *sc); +static ngx_int_t ngx_stream_script_add_copy_code( + ngx_stream_script_compile_t *sc, ngx_str_t *value, ngx_uint_t last); +static ngx_int_t ngx_stream_script_add_var_code( + ngx_stream_script_compile_t *sc, ngx_str_t *name); +#if (NGX_PCRE) +static ngx_int_t ngx_stream_script_add_capture_code( + ngx_stream_script_compile_t *sc, ngx_uint_t n); +#endif +static ngx_int_t ngx_stream_script_add_full_name_code( + ngx_stream_script_compile_t *sc); +static size_t ngx_stream_script_full_name_len_code( + ngx_stream_script_engine_t *e); +static void ngx_stream_script_full_name_code(ngx_stream_script_engine_t *e); + + +#define ngx_stream_script_exit (u_char *) &ngx_stream_script_exit_code + +static uintptr_t ngx_stream_script_exit_code = (uintptr_t) NULL; + + +void +ngx_stream_script_flush_complex_value(ngx_stream_session_t *s, + ngx_stream_complex_value_t *val) +{ + ngx_uint_t *index; + + index = val->flushes; + + if (index) { + while (*index != (ngx_uint_t) -1) { + + if (s->variables[*index].no_cacheable) { + s->variables[*index].valid = 0; + s->variables[*index].not_found = 0; + } + + index++; + } + } +} + + +ngx_int_t +ngx_stream_complex_value(ngx_stream_session_t *s, + ngx_stream_complex_value_t *val, ngx_str_t *value) +{ + size_t len; + ngx_stream_script_code_pt code; + ngx_stream_script_engine_t e; + ngx_stream_script_len_code_pt lcode; + + if (val->lengths == NULL) { + *value = val->value; + return NGX_OK; + } + + ngx_stream_script_flush_complex_value(s, val); + + ngx_memzero(&e, sizeof(ngx_stream_script_engine_t)); + + e.ip = val->lengths; + e.session = s; + e.flushed = 1; + + len = 0; + + while (*(uintptr_t *) e.ip) { + lcode = *(ngx_stream_script_len_code_pt *) e.ip; + len += lcode(&e); + } + + value->len = len; + value->data = ngx_pnalloc(s->connection->pool, len); + if (value->data == NULL) { + return NGX_ERROR; + } + + e.ip = val->values; + e.pos = value->data; + e.buf = *value; + + while (*(uintptr_t *) e.ip) { + code = *(ngx_stream_script_code_pt *) e.ip; + code((ngx_stream_script_engine_t *) &e); + } + + *value = e.buf; + + return NGX_OK; +} + + +ngx_int_t +ngx_stream_compile_complex_value(ngx_stream_compile_complex_value_t *ccv) +{ + ngx_str_t *v; + ngx_uint_t i, n, nv, nc; + ngx_array_t flushes, lengths, values, *pf, *pl, *pv; + ngx_stream_script_compile_t sc; + + v = ccv->value; + + nv = 0; + nc = 0; + + for (i = 0; i < v->len; i++) { + if (v->data[i] == '$') { + if (v->data[i + 1] >= '1' && v->data[i + 1] <= '9') { + nc++; + + } else { + nv++; + } + } + } + + if ((v->len == 0 || v->data[0] != '$') + && (ccv->conf_prefix || ccv->root_prefix)) + { + if (ngx_conf_full_name(ccv->cf->cycle, v, ccv->conf_prefix) != NGX_OK) { + return NGX_ERROR; + } + + ccv->conf_prefix = 0; + ccv->root_prefix = 0; + } + + ccv->complex_value->value = *v; + ccv->complex_value->flushes = NULL; + ccv->complex_value->lengths = NULL; + ccv->complex_value->values = NULL; + + if (nv == 0 && nc == 0) { + return NGX_OK; + } + + n = nv + 1; + + if (ngx_array_init(&flushes, ccv->cf->pool, n, sizeof(ngx_uint_t)) + != NGX_OK) + { + return NGX_ERROR; + } + + n = nv * (2 * sizeof(ngx_stream_script_copy_code_t) + + sizeof(ngx_stream_script_var_code_t)) + + sizeof(uintptr_t); + + if (ngx_array_init(&lengths, ccv->cf->pool, n, 1) != NGX_OK) { + return NGX_ERROR; + } + + n = (nv * (2 * sizeof(ngx_stream_script_copy_code_t) + + sizeof(ngx_stream_script_var_code_t)) + + sizeof(uintptr_t) + + v->len + + sizeof(uintptr_t) - 1) + & ~(sizeof(uintptr_t) - 1); + + if (ngx_array_init(&values, ccv->cf->pool, n, 1) != NGX_OK) { + return NGX_ERROR; + } + + pf = &flushes; + pl = &lengths; + pv = &values; + + ngx_memzero(&sc, sizeof(ngx_stream_script_compile_t)); + + sc.cf = ccv->cf; + sc.source = v; + sc.flushes = &pf; + sc.lengths = &pl; + sc.values = &pv; + sc.complete_lengths = 1; + sc.complete_values = 1; + sc.zero = ccv->zero; + sc.conf_prefix = ccv->conf_prefix; + sc.root_prefix = ccv->root_prefix; + + if (ngx_stream_script_compile(&sc) != NGX_OK) { + return NGX_ERROR; + } + + if (flushes.nelts) { + ccv->complex_value->flushes = flushes.elts; + ccv->complex_value->flushes[flushes.nelts] = (ngx_uint_t) -1; + } + + ccv->complex_value->lengths = lengths.elts; + ccv->complex_value->values = values.elts; + + return NGX_OK; +} + + +char * +ngx_stream_set_complex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) +{ + char *p = conf; + + ngx_str_t *value; + ngx_stream_complex_value_t **cv; + ngx_stream_compile_complex_value_t ccv; + + cv = (ngx_stream_complex_value_t **) (p + cmd->offset); + + if (*cv != NULL) { + return "duplicate"; + } + + *cv = ngx_palloc(cf->pool, sizeof(ngx_stream_complex_value_t)); + if (*cv == NULL) { + return NGX_CONF_ERROR; + } + + value = cf->args->elts; + + ngx_memzero(&ccv, sizeof(ngx_stream_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[1]; + ccv.complex_value = *cv; + + if (ngx_stream_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; +} + + +ngx_uint_t +ngx_stream_script_variables_count(ngx_str_t *value) +{ + ngx_uint_t i, n; + + for (n = 0, i = 0; i < value->len; i++) { + if (value->data[i] == '$') { + n++; + } + } + + return n; +} + + +ngx_int_t +ngx_stream_script_compile(ngx_stream_script_compile_t *sc) +{ + u_char ch; + ngx_str_t name; + ngx_uint_t i, bracket; + + if (ngx_stream_script_init_arrays(sc) != NGX_OK) { + return NGX_ERROR; + } + + for (i = 0; i < sc->source->len; /* void */ ) { + + name.len = 0; + + if (sc->source->data[i] == '$') { + + if (++i == sc->source->len) { + goto invalid_variable; + } + + if (sc->source->data[i] >= '1' && sc->source->data[i] <= '9') { +#if (NGX_PCRE) + ngx_uint_t n; + + n = sc->source->data[i] - '0'; + + if (ngx_stream_script_add_capture_code(sc, n) != NGX_OK) { + return NGX_ERROR; + } + + i++; + + continue; +#else + ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0, + "using variable \"$%c\" requires " + "PCRE library", sc->source->data[i]); + return NGX_ERROR; +#endif + } + + if (sc->source->data[i] == '{') { + bracket = 1; + + if (++i == sc->source->len) { + goto invalid_variable; + } + + name.data = &sc->source->data[i]; + + } else { + bracket = 0; + name.data = &sc->source->data[i]; + } + + for ( /* void */ ; i < sc->source->len; i++, name.len++) { + ch = sc->source->data[i]; + + if (ch == '}' && bracket) { + i++; + bracket = 0; + break; + } + + if ((ch >= 'A' && ch <= 'Z') + || (ch >= 'a' && ch <= 'z') + || (ch >= '0' && ch <= '9') + || ch == '_') + { + continue; + } + + break; + } + + if (bracket) { + ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0, + "the closing bracket in \"%V\" " + "variable is missing", &name); + return NGX_ERROR; + } + + if (name.len == 0) { + goto invalid_variable; + } + + sc->variables++; + + if (ngx_stream_script_add_var_code(sc, &name) != NGX_OK) { + return NGX_ERROR; + } + + continue; + } + + name.data = &sc->source->data[i]; + + while (i < sc->source->len) { + + if (sc->source->data[i] == '$') { + break; + } + + i++; + name.len++; + } + + sc->size += name.len; + + if (ngx_stream_script_add_copy_code(sc, &name, (i == sc->source->len)) + != NGX_OK) + { + return NGX_ERROR; + } + } + + return ngx_stream_script_done(sc); + +invalid_variable: + + ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0, "invalid variable name"); + + return NGX_ERROR; +} + + +static ngx_int_t +ngx_stream_script_init_arrays(ngx_stream_script_compile_t *sc) +{ + ngx_uint_t n; + + if (sc->flushes && *sc->flushes == NULL) { + n = sc->variables ? sc->variables : 1; + *sc->flushes = ngx_array_create(sc->cf->pool, n, sizeof(ngx_uint_t)); + if (*sc->flushes == NULL) { + return NGX_ERROR; + } + } + + if (*sc->lengths == NULL) { + n = sc->variables * (2 * sizeof(ngx_stream_script_copy_code_t) + + sizeof(ngx_stream_script_var_code_t)) + + sizeof(uintptr_t); + + *sc->lengths = ngx_array_create(sc->cf->pool, n, 1); + if (*sc->lengths == NULL) { + return NGX_ERROR; + } + } + + if (*sc->values == NULL) { + n = (sc->variables * (2 * sizeof(ngx_stream_script_copy_code_t) + + sizeof(ngx_stream_script_var_code_t)) + + sizeof(uintptr_t) + + sc->source->len + + sizeof(uintptr_t) - 1) + & ~(sizeof(uintptr_t) - 1); + + *sc->values = ngx_array_create(sc->cf->pool, n, 1); + if (*sc->values == NULL) { + return NGX_ERROR; + } + } + + sc->variables = 0; + + return NGX_OK; +} + + +static ngx_int_t +ngx_stream_script_done(ngx_stream_script_compile_t *sc) +{ + ngx_str_t zero; + uintptr_t *code; + + if (sc->zero) { + + zero.len = 1; + zero.data = (u_char *) "\0"; + + if (ngx_stream_script_add_copy_code(sc, &zero, 0) != NGX_OK) { + return NGX_ERROR; + } + } + + if (sc->conf_prefix || sc->root_prefix) { + if (ngx_stream_script_add_full_name_code(sc) != NGX_OK) { + return NGX_ERROR; + } + } + + if (sc->complete_lengths) { + code = ngx_stream_script_add_code(*sc->lengths, sizeof(uintptr_t), + NULL); + if (code == NULL) { + return NGX_ERROR; + } + + *code = (uintptr_t) NULL; + } + + if (sc->complete_values) { + code = ngx_stream_script_add_code(*sc->values, sizeof(uintptr_t), + &sc->main); + if (code == NULL) { + return NGX_ERROR; + } + + *code = (uintptr_t) NULL; + } + + return NGX_OK; +} + + +void * +ngx_stream_script_add_code(ngx_array_t *codes, size_t size, void *code) +{ + u_char *elts, **p; + void *new; + + elts = codes->elts; + + new = ngx_array_push_n(codes, size); + if (new == NULL) { + return NULL; + } + + if (code) { + if (elts != codes->elts) { + p = code; + *p += (u_char *) codes->elts - elts; + } + } + + return new; +} + + +static ngx_int_t +ngx_stream_script_add_copy_code(ngx_stream_script_compile_t *sc, + ngx_str_t *value, ngx_uint_t last) +{ + u_char *p; + size_t size, len, zero; + ngx_stream_script_copy_code_t *code; + + zero = (sc->zero && last); + len = value->len + zero; + + code = ngx_stream_script_add_code(*sc->lengths, + sizeof(ngx_stream_script_copy_code_t), + NULL); + if (code == NULL) { + return NGX_ERROR; + } + + code->code = (ngx_stream_script_code_pt) ngx_stream_script_copy_len_code; + code->len = len; + + size = (sizeof(ngx_stream_script_copy_code_t) + len + sizeof(uintptr_t) - 1) + & ~(sizeof(uintptr_t) - 1); + + code = ngx_stream_script_add_code(*sc->values, size, &sc->main); + if (code == NULL) { + return NGX_ERROR; + } + + code->code = ngx_stream_script_copy_code; + code->len = len; + + p = ngx_cpymem((u_char *) code + sizeof(ngx_stream_script_copy_code_t), + value->data, value->len); + + if (zero) { + *p = '\0'; + sc->zero = 0; + } + + return NGX_OK; +} + + +size_t +ngx_stream_script_copy_len_code(ngx_stream_script_engine_t *e) +{ + ngx_stream_script_copy_code_t *code; + + code = (ngx_stream_script_copy_code_t *) e->ip; + + e->ip += sizeof(ngx_stream_script_copy_code_t); + + return code->len; +} + + +void +ngx_stream_script_copy_code(ngx_stream_script_engine_t *e) +{ + u_char *p; + ngx_stream_script_copy_code_t *code; + + code = (ngx_stream_script_copy_code_t *) e->ip; + + p = e->pos; + + if (!e->skip) { + e->pos = ngx_copy(p, e->ip + sizeof(ngx_stream_script_copy_code_t), + code->len); + } + + e->ip += sizeof(ngx_stream_script_copy_code_t) + + ((code->len + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1)); + + ngx_log_debug2(NGX_LOG_DEBUG_STREAM, e->session->connection->log, 0, + "stream script copy: \"%*s\"", e->pos - p, p); +} + + +static ngx_int_t +ngx_stream_script_add_var_code(ngx_stream_script_compile_t *sc, ngx_str_t *name) +{ + ngx_int_t index, *p; + ngx_stream_script_var_code_t *code; + + index = ngx_stream_get_variable_index(sc->cf, name); + + if (index == NGX_ERROR) { + return NGX_ERROR; + } + + if (sc->flushes) { + p = ngx_array_push(*sc->flushes); + if (p == NULL) { + return NGX_ERROR; + } + + *p = index; + } + + code = ngx_stream_script_add_code(*sc->lengths, + sizeof(ngx_stream_script_var_code_t), + NULL); + if (code == NULL) { + return NGX_ERROR; + } + + code->code = (ngx_stream_script_code_pt) + ngx_stream_script_copy_var_len_code; + code->index = (uintptr_t) index; + + code = ngx_stream_script_add_code(*sc->values, + sizeof(ngx_stream_script_var_code_t), + &sc->main); + if (code == NULL) { + return NGX_ERROR; + } + + code->code = ngx_stream_script_copy_var_code; + code->index = (uintptr_t) index; + + return NGX_OK; +} + + +size_t +ngx_stream_script_copy_var_len_code(ngx_stream_script_engine_t *e) +{ + ngx_stream_variable_value_t *value; + ngx_stream_script_var_code_t *code; + + code = (ngx_stream_script_var_code_t *) e->ip; + + e->ip += sizeof(ngx_stream_script_var_code_t); + + if (e->flushed) { + value = ngx_stream_get_indexed_variable(e->session, code->index); + + } else { + value = ngx_stream_get_flushed_variable(e->session, code->index); + } + + if (value && !value->not_found) { + return value->len; + } + + return 0; +} + + +void +ngx_stream_script_copy_var_code(ngx_stream_script_engine_t *e) +{ + u_char *p; + ngx_stream_variable_value_t *value; + ngx_stream_script_var_code_t *code; + + code = (ngx_stream_script_var_code_t *) e->ip; + + e->ip += sizeof(ngx_stream_script_var_code_t); + + if (!e->skip) { + + if (e->flushed) { + value = ngx_stream_get_indexed_variable(e->session, code->index); + + } else { + value = ngx_stream_get_flushed_variable(e->session, code->index); + } + + if (value && !value->not_found) { + p = e->pos; + e->pos = ngx_copy(p, value->data, value->len); + + ngx_log_debug2(NGX_LOG_DEBUG_STREAM, + e->session->connection->log, 0, + "stream script var: \"%*s\"", e->pos - p, p); + } + } +} + + +#if (NGX_PCRE) + +static ngx_int_t +ngx_stream_script_add_capture_code(ngx_stream_script_compile_t *sc, + ngx_uint_t n) +{ + ngx_stream_script_copy_capture_code_t *code; + + code = ngx_stream_script_add_code(*sc->lengths, + sizeof(ngx_stream_script_copy_capture_code_t), + NULL); + if (code == NULL) { + return NGX_ERROR; + } + + code->code = (ngx_stream_script_code_pt) + ngx_stream_script_copy_capture_len_code; + code->n = 2 * n; + + + code = ngx_stream_script_add_code(*sc->values, + sizeof(ngx_stream_script_copy_capture_code_t), + &sc->main); + if (code == NULL) { + return NGX_ERROR; + } + + code->code = ngx_stream_script_copy_capture_code; + code->n = 2 * n; + + if (sc->ncaptures < n) { + sc->ncaptures = n; + } + + return NGX_OK; +} + + +size_t +ngx_stream_script_copy_capture_len_code(ngx_stream_script_engine_t *e) +{ + int *cap; + ngx_uint_t n; + ngx_stream_session_t *s; + ngx_stream_script_copy_capture_code_t *code; + + s = e->session; + + code = (ngx_stream_script_copy_capture_code_t *) e->ip; + + e->ip += sizeof(ngx_stream_script_copy_capture_code_t); + + n = code->n; + + if (n < s->ncaptures) { + cap = s->captures; + return cap[n + 1] - cap[n]; + } + + return 0; +} + + +void +ngx_stream_script_copy_capture_code(ngx_stream_script_engine_t *e) +{ + int *cap; + u_char *p, *pos; + ngx_uint_t n; + ngx_stream_session_t *s; + ngx_stream_script_copy_capture_code_t *code; + + s = e->session; + + code = (ngx_stream_script_copy_capture_code_t *) e->ip; + + e->ip += sizeof(ngx_stream_script_copy_capture_code_t); + + n = code->n; + + pos = e->pos; + + if (n < s->ncaptures) { + cap = s->captures; + p = s->captures_data; + e->pos = ngx_copy(pos, &p[cap[n]], cap[n + 1] - cap[n]); + } + + ngx_log_debug2(NGX_LOG_DEBUG_STREAM, e->session->connection->log, 0, + "stream script capture: \"%*s\"", e->pos - pos, pos); +} + +#endif + + +static ngx_int_t +ngx_stream_script_add_full_name_code(ngx_stream_script_compile_t *sc) +{ + ngx_stream_script_full_name_code_t *code; + + code = ngx_stream_script_add_code(*sc->lengths, + sizeof(ngx_stream_script_full_name_code_t), + NULL); + if (code == NULL) { + return NGX_ERROR; + } + + code->code = (ngx_stream_script_code_pt) + ngx_stream_script_full_name_len_code; + code->conf_prefix = sc->conf_prefix; + + code = ngx_stream_script_add_code(*sc->values, + sizeof(ngx_stream_script_full_name_code_t), &sc->main); + if (code == NULL) { + return NGX_ERROR; + } + + code->code = ngx_stream_script_full_name_code; + code->conf_prefix = sc->conf_prefix; + + return NGX_OK; +} + + +static size_t +ngx_stream_script_full_name_len_code(ngx_stream_script_engine_t *e) +{ + ngx_stream_script_full_name_code_t *code; + + code = (ngx_stream_script_full_name_code_t *) e->ip; + + e->ip += sizeof(ngx_stream_script_full_name_code_t); + + return code->conf_prefix ? ngx_cycle->conf_prefix.len: + ngx_cycle->prefix.len; +} + + +static void +ngx_stream_script_full_name_code(ngx_stream_script_engine_t *e) +{ + ngx_stream_script_full_name_code_t *code; + + ngx_str_t value, *prefix; + + code = (ngx_stream_script_full_name_code_t *) e->ip; + + value.data = e->buf.data; + value.len = e->pos - e->buf.data; + + prefix = code->conf_prefix ? (ngx_str_t *) &ngx_cycle->conf_prefix: + (ngx_str_t *) &ngx_cycle->prefix; + + if (ngx_get_full_name(e->session->connection->pool, prefix, &value) + != NGX_OK) + { + e->ip = ngx_stream_script_exit; + return; + } + + e->buf = value; + + ngx_log_debug1(NGX_LOG_DEBUG_STREAM, e->session->connection->log, 0, + "stream script fullname: \"%V\"", &value); + + e->ip += sizeof(ngx_stream_script_full_name_code_t); +} diff --git a/src/stream/ngx_stream_script.h b/src/stream/ngx_stream_script.h new file mode 100644 index 0000000..0abe50e --- /dev/null +++ b/src/stream/ngx_stream_script.h @@ -0,0 +1,123 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_STREAM_SCRIPT_H_INCLUDED_ +#define _NGX_STREAM_SCRIPT_H_INCLUDED_ + + +#include +#include +#include + + +typedef struct { + u_char *ip; + u_char *pos; + ngx_stream_variable_value_t *sp; + + ngx_str_t buf; + ngx_str_t line; + + unsigned flushed:1; + unsigned skip:1; + + ngx_stream_session_t *session; +} ngx_stream_script_engine_t; + + +typedef struct { + ngx_conf_t *cf; + ngx_str_t *source; + + ngx_array_t **flushes; + ngx_array_t **lengths; + ngx_array_t **values; + + ngx_uint_t variables; + ngx_uint_t ncaptures; + ngx_uint_t size; + + void *main; + + unsigned complete_lengths:1; + unsigned complete_values:1; + unsigned zero:1; + unsigned conf_prefix:1; + unsigned root_prefix:1; +} ngx_stream_script_compile_t; + + +typedef struct { + ngx_str_t value; + ngx_uint_t *flushes; + void *lengths; + void *values; +} ngx_stream_complex_value_t; + + +typedef struct { + ngx_conf_t *cf; + ngx_str_t *value; + ngx_stream_complex_value_t *complex_value; + + unsigned zero:1; + unsigned conf_prefix:1; + unsigned root_prefix:1; +} ngx_stream_compile_complex_value_t; + + +typedef void (*ngx_stream_script_code_pt) (ngx_stream_script_engine_t *e); +typedef size_t (*ngx_stream_script_len_code_pt) (ngx_stream_script_engine_t *e); + + +typedef struct { + ngx_stream_script_code_pt code; + uintptr_t len; +} ngx_stream_script_copy_code_t; + + +typedef struct { + ngx_stream_script_code_pt code; + uintptr_t index; +} ngx_stream_script_var_code_t; + + +typedef struct { + ngx_stream_script_code_pt code; + uintptr_t n; +} ngx_stream_script_copy_capture_code_t; + + +typedef struct { + ngx_stream_script_code_pt code; + uintptr_t conf_prefix; +} ngx_stream_script_full_name_code_t; + + +void ngx_stream_script_flush_complex_value(ngx_stream_session_t *s, + ngx_stream_complex_value_t *val); +ngx_int_t ngx_stream_complex_value(ngx_stream_session_t *s, + ngx_stream_complex_value_t *val, ngx_str_t *value); +ngx_int_t ngx_stream_compile_complex_value( + ngx_stream_compile_complex_value_t *ccv); +char *ngx_stream_set_complex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); + + +ngx_uint_t ngx_stream_script_variables_count(ngx_str_t *value); +ngx_int_t ngx_stream_script_compile(ngx_stream_script_compile_t *sc); + +void *ngx_stream_script_add_code(ngx_array_t *codes, size_t size, void *code); + +size_t ngx_stream_script_copy_len_code(ngx_stream_script_engine_t *e); +void ngx_stream_script_copy_code(ngx_stream_script_engine_t *e); +size_t ngx_stream_script_copy_var_len_code(ngx_stream_script_engine_t *e); +void ngx_stream_script_copy_var_code(ngx_stream_script_engine_t *e); +size_t ngx_stream_script_copy_capture_len_code(ngx_stream_script_engine_t *e); +void ngx_stream_script_copy_capture_code(ngx_stream_script_engine_t *e); + +#endif /* _NGX_STREAM_SCRIPT_H_INCLUDED_ */ diff --git a/src/stream/ngx_stream_split_clients_module.c b/src/stream/ngx_stream_split_clients_module.c new file mode 100644 index 0000000..af6c8a1 --- /dev/null +++ b/src/stream/ngx_stream_split_clients_module.c @@ -0,0 +1,244 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + + +typedef struct { + uint32_t percent; + ngx_stream_variable_value_t value; +} ngx_stream_split_clients_part_t; + + +typedef struct { + ngx_stream_complex_value_t value; + ngx_array_t parts; +} ngx_stream_split_clients_ctx_t; + + +static char *ngx_conf_split_clients_block(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); +static char *ngx_stream_split_clients(ngx_conf_t *cf, ngx_command_t *dummy, + void *conf); + +static ngx_command_t ngx_stream_split_clients_commands[] = { + + { ngx_string("split_clients"), + NGX_STREAM_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE2, + ngx_conf_split_clients_block, + NGX_STREAM_MAIN_CONF_OFFSET, + 0, + NULL }, + + ngx_null_command +}; + + +static ngx_stream_module_t ngx_stream_split_clients_module_ctx = { + NULL, /* preconfiguration */ + NULL, /* postconfiguration */ + + NULL, /* create main configuration */ + NULL, /* init main configuration */ + + NULL, /* create server configuration */ + NULL /* merge server configuration */ +}; + + +ngx_module_t ngx_stream_split_clients_module = { + NGX_MODULE_V1, + &ngx_stream_split_clients_module_ctx, /* module context */ + ngx_stream_split_clients_commands, /* module directives */ + NGX_STREAM_MODULE, /* module type */ + NULL, /* init master */ + NULL, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + + +static ngx_int_t +ngx_stream_split_clients_variable(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data) +{ + ngx_stream_split_clients_ctx_t *ctx = + (ngx_stream_split_clients_ctx_t *) data; + + uint32_t hash; + ngx_str_t val; + ngx_uint_t i; + ngx_stream_split_clients_part_t *part; + + *v = ngx_stream_variable_null_value; + + if (ngx_stream_complex_value(s, &ctx->value, &val) != NGX_OK) { + return NGX_OK; + } + + hash = ngx_murmur_hash2(val.data, val.len); + + part = ctx->parts.elts; + + for (i = 0; i < ctx->parts.nelts; i++) { + + ngx_log_debug2(NGX_LOG_DEBUG_STREAM, s->connection->log, 0, + "stream split: %uD %uD", hash, part[i].percent); + + if (hash < part[i].percent || part[i].percent == 0) { + *v = part[i].value; + return NGX_OK; + } + } + + return NGX_OK; +} + + +static char * +ngx_conf_split_clients_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + char *rv; + uint32_t sum, last; + ngx_str_t *value, name; + ngx_uint_t i; + ngx_conf_t save; + ngx_stream_variable_t *var; + ngx_stream_split_clients_ctx_t *ctx; + ngx_stream_split_clients_part_t *part; + ngx_stream_compile_complex_value_t ccv; + + ctx = ngx_pcalloc(cf->pool, sizeof(ngx_stream_split_clients_ctx_t)); + if (ctx == NULL) { + return NGX_CONF_ERROR; + } + + value = cf->args->elts; + + ngx_memzero(&ccv, sizeof(ngx_stream_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[1]; + ccv.complex_value = &ctx->value; + + if (ngx_stream_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + + 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++; + + var = ngx_stream_add_variable(cf, &name, NGX_STREAM_VAR_CHANGEABLE); + if (var == NULL) { + return NGX_CONF_ERROR; + } + + var->get_handler = ngx_stream_split_clients_variable; + var->data = (uintptr_t) ctx; + + if (ngx_array_init(&ctx->parts, cf->pool, 2, + sizeof(ngx_stream_split_clients_part_t)) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + + save = *cf; + cf->ctx = ctx; + cf->handler = ngx_stream_split_clients; + cf->handler_conf = conf; + + rv = ngx_conf_parse(cf, NULL); + + *cf = save; + + if (rv != NGX_CONF_OK) { + return rv; + } + + sum = 0; + last = 0; + part = ctx->parts.elts; + + for (i = 0; i < ctx->parts.nelts; i++) { + sum = part[i].percent ? sum + part[i].percent : 10000; + if (sum > 10000) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "percent total is greater than 100%%"); + return NGX_CONF_ERROR; + } + + if (part[i].percent) { + last += part[i].percent * (uint64_t) 0xffffffff / 10000; + part[i].percent = last; + } + } + + return rv; +} + + +static char * +ngx_stream_split_clients(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) +{ + ngx_int_t n; + ngx_str_t *value; + ngx_stream_split_clients_ctx_t *ctx; + ngx_stream_split_clients_part_t *part; + + ctx = cf->ctx; + value = cf->args->elts; + + part = ngx_array_push(&ctx->parts); + if (part == NULL) { + return NGX_CONF_ERROR; + } + + if (value[0].len == 1 && value[0].data[0] == '*') { + part->percent = 0; + + } else { + if (value[0].len == 0 || value[0].data[value[0].len - 1] != '%') { + goto invalid; + } + + n = ngx_atofp(value[0].data, value[0].len - 1, 2); + if (n == NGX_ERROR || n == 0) { + goto invalid; + } + + part->percent = (uint32_t) n; + } + + part->value.len = value[1].len; + part->value.valid = 1; + part->value.no_cacheable = 0; + part->value.not_found = 0; + part->value.data = value[1].data; + + return NGX_CONF_OK; + +invalid: + + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid percent value \"%V\"", &value[0]); + return NGX_CONF_ERROR; +} diff --git a/src/stream/ngx_stream_ssl_module.c b/src/stream/ngx_stream_ssl_module.c index e12da1b..2661220 100644 --- a/src/stream/ngx_stream_ssl_module.c +++ b/src/stream/ngx_stream_ssl_module.c @@ -10,10 +10,20 @@ #include +typedef ngx_int_t (*ngx_ssl_variable_handler_pt)(ngx_connection_t *c, + ngx_pool_t *pool, ngx_str_t *s); + + #define NGX_DEFAULT_CIPHERS "HIGH:!aNULL:!MD5" -#define NGX_DEFAULT_ECDH_CURVE "prime256v1" +#define NGX_DEFAULT_ECDH_CURVE "auto" +static ngx_int_t ngx_stream_ssl_static_variable(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_stream_ssl_variable(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data); + +static ngx_int_t ngx_stream_ssl_add_variables(ngx_conf_t *cf); static void *ngx_stream_ssl_create_conf(ngx_conf_t *cf); static char *ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child); @@ -45,16 +55,16 @@ static ngx_command_t ngx_stream_ssl_commands[] = { { ngx_string("ssl_certificate"), NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_conf_set_str_array_slot, NGX_STREAM_SRV_CONF_OFFSET, - offsetof(ngx_stream_ssl_conf_t, certificate), + offsetof(ngx_stream_ssl_conf_t, certificates), NULL }, { ngx_string("ssl_certificate_key"), NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_conf_set_str_array_slot, NGX_STREAM_SRV_CONF_OFFSET, - offsetof(ngx_stream_ssl_conf_t, certificate_key), + offsetof(ngx_stream_ssl_conf_t, certificate_keys), NULL }, { ngx_string("ssl_password_file"), @@ -132,6 +142,7 @@ static ngx_command_t ngx_stream_ssl_commands[] = { static ngx_stream_module_t ngx_stream_ssl_module_ctx = { + ngx_stream_ssl_add_variables, /* preconfiguration */ NULL, /* postconfiguration */ NULL, /* create main configuration */ @@ -158,9 +169,112 @@ ngx_module_t ngx_stream_ssl_module = { }; +static ngx_stream_variable_t ngx_stream_ssl_vars[] = { + + { ngx_string("ssl_protocol"), NULL, ngx_stream_ssl_static_variable, + (uintptr_t) ngx_ssl_get_protocol, NGX_STREAM_VAR_CHANGEABLE, 0 }, + + { 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_session_id"), NULL, ngx_stream_ssl_variable, + (uintptr_t) ngx_ssl_get_session_id, NGX_STREAM_VAR_CHANGEABLE, 0 }, + + { ngx_string("ssl_session_reused"), NULL, ngx_stream_ssl_variable, + (uintptr_t) ngx_ssl_get_session_reused, NGX_STREAM_VAR_CHANGEABLE, 0 }, + + { ngx_string("ssl_server_name"), NULL, ngx_stream_ssl_variable, + (uintptr_t) ngx_ssl_get_server_name, NGX_STREAM_VAR_CHANGEABLE, 0 }, + + { ngx_null_string, NULL, NULL, 0, 0, 0 } +}; + + static ngx_str_t ngx_stream_ssl_sess_id_ctx = ngx_string("STREAM"); +static ngx_int_t +ngx_stream_ssl_static_variable(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data) +{ + ngx_ssl_variable_handler_pt handler = (ngx_ssl_variable_handler_pt) data; + + size_t len; + ngx_str_t str; + + if (s->connection->ssl) { + + (void) handler(s->connection, NULL, &str); + + v->data = str.data; + + for (len = 0; v->data[len]; len++) { /* void */ } + + v->len = len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + return NGX_OK; + } + + v->not_found = 1; + + return NGX_OK; +} + + +static ngx_int_t +ngx_stream_ssl_variable(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data) +{ + ngx_ssl_variable_handler_pt handler = (ngx_ssl_variable_handler_pt) data; + + ngx_str_t str; + + if (s->connection->ssl) { + + if (handler(s->connection, s->connection->pool, &str) != NGX_OK) { + return NGX_ERROR; + } + + v->len = str.len; + v->data = str.data; + + if (v->len) { + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + return NGX_OK; + } + } + + v->not_found = 1; + + return NGX_OK; +} + + +static ngx_int_t +ngx_stream_ssl_add_variables(ngx_conf_t *cf) +{ + ngx_stream_variable_t *var, *v; + + for (v = ngx_stream_ssl_vars; v->name.len; v++) { + var = ngx_stream_add_variable(cf, &v->name, v->flags); + if (var == NULL) { + return NGX_ERROR; + } + + var->get_handler = v->get_handler; + var->data = v->data; + } + + return NGX_OK; +} + + static void * ngx_stream_ssl_create_conf(ngx_conf_t *cf) { @@ -175,8 +289,6 @@ ngx_stream_ssl_create_conf(ngx_conf_t *cf) * set by ngx_pcalloc(): * * scf->protocols = 0; - * scf->certificate = { 0, NULL }; - * scf->certificate_key = { 0, NULL }; * scf->dhparam = { 0, NULL }; * scf->ecdh_curve = { 0, NULL }; * scf->ciphers = { 0, NULL }; @@ -184,6 +296,8 @@ ngx_stream_ssl_create_conf(ngx_conf_t *cf) */ scf->handshake_timeout = NGX_CONF_UNSET_MSEC; + scf->certificates = NGX_CONF_UNSET_PTR; + scf->certificate_keys = NGX_CONF_UNSET_PTR; scf->passwords = NGX_CONF_UNSET_PTR; scf->prefer_server_ciphers = NGX_CONF_UNSET; scf->builtin_session_cache = NGX_CONF_UNSET; @@ -216,8 +330,9 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) (NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1 |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2)); - ngx_conf_merge_str_value(conf->certificate, prev->certificate, ""); - ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key, ""); + ngx_conf_merge_ptr_value(conf->certificates, prev->certificates, NULL); + ngx_conf_merge_ptr_value(conf->certificate_keys, prev->certificate_keys, + NULL); ngx_conf_merge_ptr_value(conf->passwords, prev->passwords, NULL); @@ -231,15 +346,18 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) conf->ssl.log = cf->log; - if (conf->certificate.len == 0) { + if (conf->certificates == NULL) { return NGX_CONF_OK; } - if (conf->certificate_key.len == 0) { + if (conf->certificate_keys == NULL + || conf->certificate_keys->nelts < conf->certificates->nelts) + { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate_key\" is defined " "for certificate \"%V\"", - &conf->certificate); + ((ngx_str_t *) conf->certificates->elts) + + conf->certificates->nelts - 1); return NGX_CONF_ERROR; } @@ -255,31 +373,20 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) cln->handler = ngx_ssl_cleanup_ctx; cln->data = &conf->ssl; - if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate, - &conf->certificate_key, conf->passwords) + if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates, + conf->certificate_keys, conf->passwords) != NGX_OK) { return NGX_CONF_ERROR; } - if (SSL_CTX_set_cipher_list(conf->ssl.ctx, - (const char *) conf->ciphers.data) - == 0) + if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers, + conf->prefer_server_ciphers) + != NGX_OK) { - ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, - "SSL_CTX_set_cipher_list(\"%V\") failed", - &conf->ciphers); return NGX_CONF_ERROR; } - if (conf->prefer_server_ciphers) { - SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); - } - -#if (OPENSSL_VERSION_NUMBER < 0x10100001L && !defined LIBRESSL_VERSION_NUMBER) - SSL_CTX_set_tmp_rsa_callback(conf->ssl.ctx, ngx_ssl_rsa512_key_callback); -#endif - if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) { return NGX_CONF_ERROR; } diff --git a/src/stream/ngx_stream_ssl_module.h b/src/stream/ngx_stream_ssl_module.h index 85e8b6e..9b1c41a 100644 --- a/src/stream/ngx_stream_ssl_module.h +++ b/src/stream/ngx_stream_ssl_module.h @@ -27,8 +27,9 @@ typedef struct { time_t session_timeout; - ngx_str_t certificate; - ngx_str_t certificate_key; + ngx_array_t *certificates; + ngx_array_t *certificate_keys; + ngx_str_t dhparam; ngx_str_t ecdh_curve; diff --git a/src/stream/ngx_stream_upstream.c b/src/stream/ngx_stream_upstream.c index 69dddc5..2ea5eeb 100644 --- a/src/stream/ngx_stream_upstream.c +++ b/src/stream/ngx_stream_upstream.c @@ -39,13 +39,14 @@ static ngx_command_t ngx_stream_upstream_commands[] = { static ngx_stream_module_t ngx_stream_upstream_module_ctx = { + NULL, /* preconfiguration */ NULL, /* postconfiguration */ ngx_stream_upstream_create_main_conf, /* create main configuration */ ngx_stream_upstream_init_main_conf, /* init main configuration */ NULL, /* create server configuration */ - NULL, /* merge server configuration */ + NULL /* merge server configuration */ }; diff --git a/src/stream/ngx_stream_upstream.h b/src/stream/ngx_stream_upstream.h index 1f4810c..5f067c0 100644 --- a/src/stream/ngx_stream_upstream.h +++ b/src/stream/ngx_stream_upstream.h @@ -78,6 +78,21 @@ struct ngx_stream_upstream_srv_conf_s { }; +typedef struct { + ngx_str_t host; + in_port_t port; + ngx_uint_t no_port; /* unsigned no_port:1 */ + + ngx_uint_t naddrs; + ngx_resolver_addr_t *addrs; + + struct sockaddr *sockaddr; + socklen_t socklen; + + ngx_resolver_ctx_t *ctx; +} ngx_stream_upstream_resolved_t; + + typedef struct { ngx_peer_connection_t peer; ngx_buf_t downstream_buf; @@ -88,6 +103,7 @@ typedef struct { #if (NGX_STREAM_SSL) ngx_str_t ssl_name; #endif + ngx_stream_upstream_resolved_t *resolved; unsigned connected:1; unsigned proxy_protocol:1; } ngx_stream_upstream_t; diff --git a/src/stream/ngx_stream_upstream_hash_module.c b/src/stream/ngx_stream_upstream_hash_module.c index 56ff7d6..88185eb 100644 --- a/src/stream/ngx_stream_upstream_hash_module.c +++ b/src/stream/ngx_stream_upstream_hash_module.c @@ -23,6 +23,7 @@ typedef struct { typedef struct { + ngx_stream_complex_value_t key; ngx_stream_upstream_chash_points_t *points; } ngx_stream_upstream_hash_srv_conf_t; @@ -76,13 +77,14 @@ static ngx_command_t ngx_stream_upstream_hash_commands[] = { static ngx_stream_module_t ngx_stream_upstream_hash_module_ctx = { + NULL, /* preconfiguration */ NULL, /* postconfiguration */ NULL, /* create main configuration */ NULL, /* init main configuration */ ngx_stream_upstream_hash_create_conf, /* create server configuration */ - NULL, /* merge server configuration */ + NULL /* merge server configuration */ }; @@ -140,7 +142,9 @@ ngx_stream_upstream_init_hash_peer(ngx_stream_session_t *s, hcf = ngx_stream_conf_upstream_srv_conf(us, ngx_stream_upstream_hash_module); - hp->key = s->connection->addr_text; + if (ngx_stream_complex_value(s, &hcf->key, &hp->key) != NGX_OK) { + return NGX_ERROR; + } ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0, "upstream hash key:\"%V\"", &hp->key); @@ -615,15 +619,21 @@ ngx_stream_upstream_hash_create_conf(ngx_conf_t *cf) static char * ngx_stream_upstream_hash(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { - ngx_str_t *value; - ngx_stream_upstream_srv_conf_t *uscf; + ngx_stream_upstream_hash_srv_conf_t *hcf = conf; + + ngx_str_t *value; + ngx_stream_upstream_srv_conf_t *uscf; + ngx_stream_compile_complex_value_t ccv; value = cf->args->elts; - if (ngx_strcmp(value[1].data, "$remote_addr")) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "unsupported hash key \"%V\", use $remote_addr", - &value[1]); + ngx_memzero(&ccv, sizeof(ngx_stream_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[1]; + ccv.complex_value = &hcf->key; + + if (ngx_stream_compile_complex_value(&ccv) != NGX_OK) { return NGX_CONF_ERROR; } diff --git a/src/stream/ngx_stream_upstream_least_conn_module.c b/src/stream/ngx_stream_upstream_least_conn_module.c index c9719f9..e884975 100644 --- a/src/stream/ngx_stream_upstream_least_conn_module.c +++ b/src/stream/ngx_stream_upstream_least_conn_module.c @@ -32,13 +32,14 @@ static ngx_command_t ngx_stream_upstream_least_conn_commands[] = { static ngx_stream_module_t ngx_stream_upstream_least_conn_module_ctx = { + NULL, /* preconfiguration */ NULL, /* postconfiguration */ NULL, /* create main configuration */ NULL, /* init main configuration */ NULL, /* create server configuration */ - NULL, /* merge server configuration */ + NULL /* merge server configuration */ }; diff --git a/src/stream/ngx_stream_upstream_round_robin.c b/src/stream/ngx_stream_upstream_round_robin.c index e1ab592..7aced0f 100644 --- a/src/stream/ngx_stream_upstream_round_robin.c +++ b/src/stream/ngx_stream_upstream_round_robin.c @@ -23,6 +23,10 @@ static ngx_int_t ngx_stream_upstream_set_round_robin_peer_session( ngx_peer_connection_t *pc, void *data); static void ngx_stream_upstream_save_round_robin_peer_session( ngx_peer_connection_t *pc, void *data); +static ngx_int_t ngx_stream_upstream_empty_set_session( + ngx_peer_connection_t *pc, void *data); +static void ngx_stream_upstream_empty_save_session(ngx_peer_connection_t *pc, + void *data); #endif @@ -292,6 +296,123 @@ ngx_stream_upstream_init_round_robin_peer(ngx_stream_session_t *s, } +ngx_int_t +ngx_stream_upstream_create_round_robin_peer(ngx_stream_session_t *s, + ngx_stream_upstream_resolved_t *ur) +{ + u_char *p; + size_t len; + socklen_t socklen; + ngx_uint_t i, n; + struct sockaddr *sockaddr; + ngx_stream_upstream_rr_peer_t *peer, **peerp; + ngx_stream_upstream_rr_peers_t *peers; + ngx_stream_upstream_rr_peer_data_t *rrp; + + rrp = s->upstream->peer.data; + + if (rrp == NULL) { + rrp = ngx_palloc(s->connection->pool, + sizeof(ngx_stream_upstream_rr_peer_data_t)); + if (rrp == NULL) { + return NGX_ERROR; + } + + s->upstream->peer.data = rrp; + } + + peers = ngx_pcalloc(s->connection->pool, + sizeof(ngx_stream_upstream_rr_peers_t)); + if (peers == NULL) { + return NGX_ERROR; + } + + peer = ngx_pcalloc(s->connection->pool, + sizeof(ngx_stream_upstream_rr_peer_t) * ur->naddrs); + if (peer == NULL) { + return NGX_ERROR; + } + + peers->single = (ur->naddrs == 1); + peers->number = ur->naddrs; + peers->name = &ur->host; + + if (ur->sockaddr) { + peer[0].sockaddr = ur->sockaddr; + peer[0].socklen = ur->socklen; + peer[0].name = ur->host; + peer[0].weight = 1; + peer[0].effective_weight = 1; + peer[0].current_weight = 0; + peer[0].max_fails = 1; + peer[0].fail_timeout = 10; + peers->peer = peer; + + } else { + peerp = &peers->peer; + + for (i = 0; i < ur->naddrs; i++) { + + socklen = ur->addrs[i].socklen; + + sockaddr = ngx_palloc(s->connection->pool, socklen); + if (sockaddr == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(sockaddr, ur->addrs[i].sockaddr, socklen); + ngx_inet_set_port(sockaddr, ur->port); + + p = ngx_pnalloc(s->connection->pool, NGX_SOCKADDR_STRLEN); + if (p == NULL) { + return NGX_ERROR; + } + + len = ngx_sock_ntop(sockaddr, socklen, p, NGX_SOCKADDR_STRLEN, 1); + + peer[i].sockaddr = sockaddr; + peer[i].socklen = socklen; + peer[i].name.len = len; + peer[i].name.data = p; + peer[i].weight = 1; + peer[i].effective_weight = 1; + peer[i].current_weight = 0; + peer[i].max_fails = 1; + peer[i].fail_timeout = 10; + *peerp = &peer[i]; + peerp = &peer[i].next; + } + } + + rrp->peers = peers; + rrp->current = NULL; + + if (rrp->peers->number <= 8 * sizeof(uintptr_t)) { + rrp->tried = &rrp->data; + rrp->data = 0; + + } else { + n = (rrp->peers->number + (8 * sizeof(uintptr_t) - 1)) + / (8 * sizeof(uintptr_t)); + + rrp->tried = ngx_pcalloc(s->connection->pool, n * sizeof(uintptr_t)); + if (rrp->tried == NULL) { + return NGX_ERROR; + } + } + + s->upstream->peer.get = ngx_stream_upstream_get_round_robin_peer; + s->upstream->peer.free = ngx_stream_upstream_free_round_robin_peer; + s->upstream->peer.tries = ngx_stream_upstream_tries(rrp->peers); +#if (NGX_STREAM_SSL) + s->upstream->peer.set_session = ngx_stream_upstream_empty_set_session; + s->upstream->peer.save_session = ngx_stream_upstream_empty_save_session; +#endif + + return NGX_OK; +} + + ngx_int_t ngx_stream_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data) { @@ -699,4 +820,18 @@ ngx_stream_upstream_save_round_robin_peer_session(ngx_peer_connection_t *pc, } } + +static ngx_int_t +ngx_stream_upstream_empty_set_session(ngx_peer_connection_t *pc, void *data) +{ + return NGX_OK; +} + + +static void +ngx_stream_upstream_empty_save_session(ngx_peer_connection_t *pc, void *data) +{ + return; +} + #endif diff --git a/src/stream/ngx_stream_upstream_round_robin.h b/src/stream/ngx_stream_upstream_round_robin.h index 77ee0ab..452c2e9 100644 --- a/src/stream/ngx_stream_upstream_round_robin.h +++ b/src/stream/ngx_stream_upstream_round_robin.h @@ -130,6 +130,8 @@ ngx_int_t ngx_stream_upstream_init_round_robin(ngx_conf_t *cf, ngx_stream_upstream_srv_conf_t *us); ngx_int_t ngx_stream_upstream_init_round_robin_peer(ngx_stream_session_t *s, ngx_stream_upstream_srv_conf_t *us); +ngx_int_t ngx_stream_upstream_create_round_robin_peer(ngx_stream_session_t *s, + ngx_stream_upstream_resolved_t *ur); ngx_int_t ngx_stream_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data); void ngx_stream_upstream_free_round_robin_peer(ngx_peer_connection_t *pc, diff --git a/src/stream/ngx_stream_upstream_zone_module.c b/src/stream/ngx_stream_upstream_zone_module.c index ffc9e8a..07ab88d 100644 --- a/src/stream/ngx_stream_upstream_zone_module.c +++ b/src/stream/ngx_stream_upstream_zone_module.c @@ -32,13 +32,14 @@ static ngx_command_t ngx_stream_upstream_zone_commands[] = { static ngx_stream_module_t ngx_stream_upstream_zone_module_ctx = { + NULL, /* preconfiguration */ NULL, /* postconfiguration */ NULL, /* create main configuration */ NULL, /* init main configuration */ NULL, /* create server configuration */ - NULL, /* merge server configuration */ + NULL /* merge server configuration */ }; diff --git a/src/stream/ngx_stream_variables.c b/src/stream/ngx_stream_variables.c new file mode 100644 index 0000000..10f9c7e --- /dev/null +++ b/src/stream/ngx_stream_variables.c @@ -0,0 +1,971 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include +#include + + +static ngx_int_t ngx_stream_variable_binary_remote_addr( + ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_stream_variable_remote_addr(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_stream_variable_remote_port(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_stream_variable_server_addr(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_stream_variable_server_port(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_stream_variable_bytes_sent(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_stream_variable_connection(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data); + +static ngx_int_t ngx_stream_variable_nginx_version(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_stream_variable_hostname(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_stream_variable_pid(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_stream_variable_msec(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_stream_variable_time_iso8601(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_stream_variable_time_local(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data); + + +static ngx_stream_variable_t ngx_stream_core_variables[] = { + + { ngx_string("binary_remote_addr"), NULL, + ngx_stream_variable_binary_remote_addr, 0, 0, 0 }, + + { ngx_string("remote_addr"), NULL, + ngx_stream_variable_remote_addr, 0, 0, 0 }, + + { ngx_string("remote_port"), NULL, + ngx_stream_variable_remote_port, 0, 0, 0 }, + + { ngx_string("server_addr"), NULL, + ngx_stream_variable_server_addr, 0, 0, 0 }, + + { ngx_string("server_port"), NULL, + ngx_stream_variable_server_port, 0, 0, 0 }, + + { ngx_string("bytes_sent"), NULL, ngx_stream_variable_bytes_sent, + 0, 0, 0 }, + + { ngx_string("connection"), NULL, + ngx_stream_variable_connection, 0, 0, 0 }, + + { ngx_string("nginx_version"), NULL, ngx_stream_variable_nginx_version, + 0, 0, 0 }, + + { ngx_string("hostname"), NULL, ngx_stream_variable_hostname, + 0, 0, 0 }, + + { ngx_string("pid"), NULL, ngx_stream_variable_pid, + 0, 0, 0 }, + + { ngx_string("msec"), NULL, ngx_stream_variable_msec, + 0, NGX_STREAM_VAR_NOCACHEABLE, 0 }, + + { ngx_string("time_iso8601"), NULL, ngx_stream_variable_time_iso8601, + 0, NGX_STREAM_VAR_NOCACHEABLE, 0 }, + + { ngx_string("time_local"), NULL, ngx_stream_variable_time_local, + 0, NGX_STREAM_VAR_NOCACHEABLE, 0 }, + + { ngx_null_string, NULL, NULL, 0, 0, 0 } +}; + + +ngx_stream_variable_value_t ngx_stream_variable_null_value = + ngx_stream_variable(""); +ngx_stream_variable_value_t ngx_stream_variable_true_value = + ngx_stream_variable("1"); + + +ngx_stream_variable_t * +ngx_stream_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags) +{ + ngx_int_t rc; + ngx_uint_t i; + ngx_hash_key_t *key; + ngx_stream_variable_t *v; + ngx_stream_core_main_conf_t *cmcf; + + if (name->len == 0) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid variable name \"$\""); + return NULL; + } + + cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module); + + key = cmcf->variables_keys->keys.elts; + for (i = 0; i < cmcf->variables_keys->keys.nelts; i++) { + if (name->len != key[i].key.len + || ngx_strncasecmp(name->data, key[i].key.data, name->len) != 0) + { + continue; + } + + v = key[i].value; + + if (!(v->flags & NGX_STREAM_VAR_CHANGEABLE)) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "the duplicate \"%V\" variable", name); + return NULL; + } + + return v; + } + + v = ngx_palloc(cf->pool, sizeof(ngx_stream_variable_t)); + if (v == NULL) { + return NULL; + } + + v->name.len = name->len; + v->name.data = ngx_pnalloc(cf->pool, name->len); + if (v->name.data == NULL) { + return NULL; + } + + ngx_strlow(v->name.data, name->data, name->len); + + v->set_handler = NULL; + v->get_handler = NULL; + v->data = 0; + v->flags = flags; + v->index = 0; + + rc = ngx_hash_add_key(cmcf->variables_keys, &v->name, v, 0); + + if (rc == NGX_ERROR) { + return NULL; + } + + if (rc == NGX_BUSY) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "conflicting variable name \"%V\"", name); + return NULL; + } + + return v; +} + + +ngx_int_t +ngx_stream_get_variable_index(ngx_conf_t *cf, ngx_str_t *name) +{ + ngx_uint_t i; + ngx_stream_variable_t *v; + ngx_stream_core_main_conf_t *cmcf; + + if (name->len == 0) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid variable name \"$\""); + return NGX_ERROR; + } + + cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module); + + v = cmcf->variables.elts; + + if (v == NULL) { + if (ngx_array_init(&cmcf->variables, cf->pool, 4, + sizeof(ngx_stream_variable_t)) + != NGX_OK) + { + return NGX_ERROR; + } + + } else { + for (i = 0; i < cmcf->variables.nelts; i++) { + if (name->len != v[i].name.len + || ngx_strncasecmp(name->data, v[i].name.data, name->len) != 0) + { + continue; + } + + return i; + } + } + + v = ngx_array_push(&cmcf->variables); + if (v == NULL) { + return NGX_ERROR; + } + + v->name.len = name->len; + v->name.data = ngx_pnalloc(cf->pool, name->len); + if (v->name.data == NULL) { + return NGX_ERROR; + } + + ngx_strlow(v->name.data, name->data, name->len); + + v->set_handler = NULL; + v->get_handler = NULL; + v->data = 0; + v->flags = 0; + v->index = cmcf->variables.nelts - 1; + + return v->index; +} + + +ngx_stream_variable_value_t * +ngx_stream_get_indexed_variable(ngx_stream_session_t *s, ngx_uint_t index) +{ + ngx_stream_variable_t *v; + ngx_stream_core_main_conf_t *cmcf; + + cmcf = ngx_stream_get_module_main_conf(s, ngx_stream_core_module); + + if (cmcf->variables.nelts <= index) { + ngx_log_error(NGX_LOG_ALERT, s->connection->log, 0, + "unknown variable index: %ui", index); + return NULL; + } + + if (s->variables[index].not_found || s->variables[index].valid) { + return &s->variables[index]; + } + + v = cmcf->variables.elts; + + if (v[index].get_handler(s, &s->variables[index], v[index].data) + == NGX_OK) + { + if (v[index].flags & NGX_STREAM_VAR_NOCACHEABLE) { + s->variables[index].no_cacheable = 1; + } + + return &s->variables[index]; + } + + s->variables[index].valid = 0; + s->variables[index].not_found = 1; + + return NULL; +} + + +ngx_stream_variable_value_t * +ngx_stream_get_flushed_variable(ngx_stream_session_t *s, ngx_uint_t index) +{ + ngx_stream_variable_value_t *v; + + v = &s->variables[index]; + + if (v->valid || v->not_found) { + if (!v->no_cacheable) { + return v; + } + + v->valid = 0; + v->not_found = 0; + } + + return ngx_stream_get_indexed_variable(s, index); +} + + +ngx_stream_variable_value_t * +ngx_stream_get_variable(ngx_stream_session_t *s, ngx_str_t *name, + ngx_uint_t key) +{ + ngx_stream_variable_t *v; + ngx_stream_variable_value_t *vv; + ngx_stream_core_main_conf_t *cmcf; + + cmcf = ngx_stream_get_module_main_conf(s, ngx_stream_core_module); + + v = ngx_hash_find(&cmcf->variables_hash, key, name->data, name->len); + + if (v) { + if (v->flags & NGX_STREAM_VAR_INDEXED) { + return ngx_stream_get_flushed_variable(s, v->index); + + } else { + + vv = ngx_palloc(s->connection->pool, + sizeof(ngx_stream_variable_value_t)); + + if (vv && v->get_handler(s, vv, v->data) == NGX_OK) { + return vv; + } + + return NULL; + } + } + + vv = ngx_palloc(s->connection->pool, sizeof(ngx_stream_variable_value_t)); + if (vv == NULL) { + return NULL; + } + + vv->not_found = 1; + + return vv; +} + + +static ngx_int_t +ngx_stream_variable_binary_remote_addr(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data) + { + struct sockaddr_in *sin; +#if (NGX_HAVE_INET6) + struct sockaddr_in6 *sin6; +#endif + + switch (s->connection->sockaddr->sa_family) { + +#if (NGX_HAVE_INET6) + case AF_INET6: + sin6 = (struct sockaddr_in6 *) s->connection->sockaddr; + + v->len = sizeof(struct in6_addr); + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = sin6->sin6_addr.s6_addr; + + break; +#endif + + default: /* AF_INET */ + sin = (struct sockaddr_in *) s->connection->sockaddr; + + v->len = sizeof(in_addr_t); + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = (u_char *) &sin->sin_addr; + + break; + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_stream_variable_remote_addr(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data) +{ + v->len = s->connection->addr_text.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = s->connection->addr_text.data; + + return NGX_OK; +} + + +static ngx_int_t +ngx_stream_variable_remote_port(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data) +{ + ngx_uint_t port; + + v->len = 0; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + v->data = ngx_pnalloc(s->connection->pool, sizeof("65535") - 1); + if (v->data == NULL) { + return NGX_ERROR; + } + + port = ngx_inet_get_port(s->connection->sockaddr); + + if (port > 0 && port < 65536) { + v->len = ngx_sprintf(v->data, "%ui", port) - v->data; + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_stream_variable_server_addr(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data) +{ + ngx_str_t str; + u_char addr[NGX_SOCKADDR_STRLEN]; + + str.len = NGX_SOCKADDR_STRLEN; + str.data = addr; + + if (ngx_connection_local_sockaddr(s->connection, &str, 0) != NGX_OK) { + return NGX_ERROR; + } + + str.data = ngx_pnalloc(s->connection->pool, str.len); + if (str.data == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(str.data, addr, str.len); + + v->len = str.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = str.data; + + return NGX_OK; +} + + +static ngx_int_t +ngx_stream_variable_server_port(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data) +{ + ngx_uint_t port; + + v->len = 0; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + if (ngx_connection_local_sockaddr(s->connection, NULL, 0) != NGX_OK) { + return NGX_ERROR; + } + + v->data = ngx_pnalloc(s->connection->pool, sizeof("65535") - 1); + if (v->data == NULL) { + return NGX_ERROR; + } + + port = ngx_inet_get_port(s->connection->local_sockaddr); + + if (port > 0 && port < 65536) { + v->len = ngx_sprintf(v->data, "%ui", port) - v->data; + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_stream_variable_bytes_sent(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data) +{ + u_char *p; + + p = ngx_pnalloc(s->connection->pool, NGX_OFF_T_LEN); + if (p == NULL) { + return NGX_ERROR; + } + + v->len = ngx_sprintf(p, "%O", s->connection->sent) - p; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = p; + + return NGX_OK; +} + + +static ngx_int_t +ngx_stream_variable_connection(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data) +{ + u_char *p; + + p = ngx_pnalloc(s->connection->pool, NGX_ATOMIC_T_LEN); + if (p == NULL) { + return NGX_ERROR; + } + + v->len = ngx_sprintf(p, "%uA", s->connection->number) - p; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = p; + + return NGX_OK; +} + + +static ngx_int_t +ngx_stream_variable_nginx_version(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data) +{ + v->len = sizeof(NGINX_VERSION) - 1; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = (u_char *) NGINX_VERSION; + + return NGX_OK; +} + + +static ngx_int_t +ngx_stream_variable_hostname(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data) +{ + v->len = ngx_cycle->hostname.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = ngx_cycle->hostname.data; + + return NGX_OK; +} + + +static ngx_int_t +ngx_stream_variable_pid(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data) +{ + u_char *p; + + p = ngx_pnalloc(s->connection->pool, NGX_INT64_LEN); + if (p == NULL) { + return NGX_ERROR; + } + + v->len = ngx_sprintf(p, "%P", ngx_pid) - p; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = p; + + return NGX_OK; +} + + +static ngx_int_t +ngx_stream_variable_msec(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data) +{ + u_char *p; + ngx_time_t *tp; + + p = ngx_pnalloc(s->connection->pool, NGX_TIME_T_LEN + 4); + if (p == NULL) { + return NGX_ERROR; + } + + tp = ngx_timeofday(); + + v->len = ngx_sprintf(p, "%T.%03M", tp->sec, tp->msec) - p; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = p; + + return NGX_OK; +} + + +static ngx_int_t +ngx_stream_variable_time_iso8601(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data) +{ + u_char *p; + + p = ngx_pnalloc(s->connection->pool, ngx_cached_http_log_iso8601.len); + if (p == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(p, ngx_cached_http_log_iso8601.data, + ngx_cached_http_log_iso8601.len); + + v->len = ngx_cached_http_log_iso8601.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = p; + + return NGX_OK; +} + + +static ngx_int_t +ngx_stream_variable_time_local(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data) +{ + u_char *p; + + p = ngx_pnalloc(s->connection->pool, ngx_cached_http_log_time.len); + if (p == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(p, ngx_cached_http_log_time.data, ngx_cached_http_log_time.len); + + v->len = ngx_cached_http_log_time.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = p; + + return NGX_OK; +} + + +void * +ngx_stream_map_find(ngx_stream_session_t *s, ngx_stream_map_t *map, + ngx_str_t *match) +{ + void *value; + u_char *low; + size_t len; + ngx_uint_t key; + + len = match->len; + + if (len) { + low = ngx_pnalloc(s->connection->pool, len); + if (low == NULL) { + return NULL; + } + + } else { + low = NULL; + } + + key = ngx_hash_strlow(low, match->data, len); + + value = ngx_hash_find_combined(&map->hash, key, low, len); + if (value) { + return value; + } + +#if (NGX_PCRE) + + if (len && map->nregex) { + ngx_int_t n; + ngx_uint_t i; + ngx_stream_map_regex_t *reg; + + reg = map->regex; + + for (i = 0; i < map->nregex; i++) { + + n = ngx_stream_regex_exec(s, reg[i].regex, match); + + if (n == NGX_OK) { + return reg[i].value; + } + + if (n == NGX_DECLINED) { + continue; + } + + /* NGX_ERROR */ + + return NULL; + } + } + +#endif + + return NULL; +} + + +#if (NGX_PCRE) + +static ngx_int_t +ngx_stream_variable_not_found(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data) +{ + v->not_found = 1; + return NGX_OK; +} + + +ngx_stream_regex_t * +ngx_stream_regex_compile(ngx_conf_t *cf, ngx_regex_compile_t *rc) +{ + u_char *p; + size_t size; + ngx_str_t name; + ngx_uint_t i, n; + ngx_stream_variable_t *v; + ngx_stream_regex_t *re; + ngx_stream_regex_variable_t *rv; + ngx_stream_core_main_conf_t *cmcf; + + rc->pool = cf->pool; + + if (ngx_regex_compile(rc) != NGX_OK) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc->err); + return NULL; + } + + re = ngx_pcalloc(cf->pool, sizeof(ngx_stream_regex_t)); + if (re == NULL) { + return NULL; + } + + re->regex = rc->regex; + re->ncaptures = rc->captures; + re->name = rc->pattern; + + cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module); + cmcf->ncaptures = ngx_max(cmcf->ncaptures, re->ncaptures); + + n = (ngx_uint_t) rc->named_captures; + + if (n == 0) { + return re; + } + + rv = ngx_palloc(rc->pool, n * sizeof(ngx_stream_regex_variable_t)); + if (rv == NULL) { + return NULL; + } + + re->variables = rv; + re->nvariables = n; + + size = rc->name_size; + p = rc->names; + + for (i = 0; i < n; i++) { + rv[i].capture = 2 * ((p[0] << 8) + p[1]); + + name.data = &p[2]; + name.len = ngx_strlen(name.data); + + v = ngx_stream_add_variable(cf, &name, NGX_STREAM_VAR_CHANGEABLE); + if (v == NULL) { + return NULL; + } + + rv[i].index = ngx_stream_get_variable_index(cf, &name); + if (rv[i].index == NGX_ERROR) { + return NULL; + } + + v->get_handler = ngx_stream_variable_not_found; + + p += size; + } + + return re; +} + + +ngx_int_t +ngx_stream_regex_exec(ngx_stream_session_t *s, ngx_stream_regex_t *re, + ngx_str_t *str) +{ + ngx_int_t rc, index; + ngx_uint_t i, n, len; + ngx_stream_variable_value_t *vv; + ngx_stream_core_main_conf_t *cmcf; + + cmcf = ngx_stream_get_module_main_conf(s, ngx_stream_core_module); + + if (re->ncaptures) { + len = cmcf->ncaptures; + + if (s->captures == NULL) { + s->captures = ngx_palloc(s->connection->pool, len * sizeof(int)); + if (s->captures == NULL) { + return NGX_ERROR; + } + } + + } else { + len = 0; + } + + rc = ngx_regex_exec(re->regex, str, s->captures, len); + + if (rc == NGX_REGEX_NO_MATCHED) { + return NGX_DECLINED; + } + + if (rc < 0) { + ngx_log_error(NGX_LOG_ALERT, s->connection->log, 0, + ngx_regex_exec_n " failed: %i on \"%V\" using \"%V\"", + rc, str, &re->name); + return NGX_ERROR; + } + + for (i = 0; i < re->nvariables; i++) { + + n = re->variables[i].capture; + index = re->variables[i].index; + vv = &s->variables[index]; + + vv->len = s->captures[n + 1] - s->captures[n]; + vv->valid = 1; + vv->no_cacheable = 0; + vv->not_found = 0; + vv->data = &str->data[s->captures[n]]; + +#if (NGX_DEBUG) + { + ngx_stream_variable_t *v; + + v = cmcf->variables.elts; + + ngx_log_debug2(NGX_LOG_DEBUG_STREAM, s->connection->log, 0, + "stream regex set $%V to \"%v\"", &v[index].name, vv); + } +#endif + } + + s->ncaptures = rc * 2; + s->captures_data = str->data; + + return NGX_OK; +} + +#endif + + +ngx_int_t +ngx_stream_variables_add_core_vars(ngx_conf_t *cf) +{ + ngx_int_t rc; + ngx_stream_variable_t *cv, *v; + ngx_stream_core_main_conf_t *cmcf; + + cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module); + + cmcf->variables_keys = ngx_pcalloc(cf->temp_pool, + sizeof(ngx_hash_keys_arrays_t)); + if (cmcf->variables_keys == NULL) { + return NGX_ERROR; + } + + cmcf->variables_keys->pool = cf->pool; + cmcf->variables_keys->temp_pool = cf->pool; + + if (ngx_hash_keys_array_init(cmcf->variables_keys, NGX_HASH_SMALL) + != NGX_OK) + { + return NGX_ERROR; + } + + for (cv = ngx_stream_core_variables; cv->name.len; cv++) { + v = ngx_palloc(cf->pool, sizeof(ngx_stream_variable_t)); + if (v == NULL) { + return NGX_ERROR; + } + + *v = *cv; + + rc = ngx_hash_add_key(cmcf->variables_keys, &v->name, v, + NGX_HASH_READONLY_KEY); + + if (rc == NGX_OK) { + continue; + } + + if (rc == NGX_BUSY) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "conflicting variable name \"%V\"", &v->name); + } + + return NGX_ERROR; + } + + return NGX_OK; +} + + +ngx_int_t +ngx_stream_variables_init_vars(ngx_conf_t *cf) +{ + ngx_uint_t i, n; + ngx_hash_key_t *key; + ngx_hash_init_t hash; + ngx_stream_variable_t *v, *av; + ngx_stream_core_main_conf_t *cmcf; + + /* set the handlers for the indexed stream variables */ + + cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module); + + v = cmcf->variables.elts; + key = cmcf->variables_keys->keys.elts; + + for (i = 0; i < cmcf->variables.nelts; i++) { + + for (n = 0; n < cmcf->variables_keys->keys.nelts; n++) { + + av = key[n].value; + + if (v[i].name.len == key[n].key.len + && ngx_strncmp(v[i].name.data, key[n].key.data, v[i].name.len) + == 0) + { + v[i].get_handler = av->get_handler; + v[i].data = av->data; + + av->flags |= NGX_STREAM_VAR_INDEXED; + v[i].flags = av->flags; + + av->index = i; + + if (av->get_handler == NULL) { + break; + } + + goto next; + } + } + + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "unknown \"%V\" variable", &v[i].name); + + return NGX_ERROR; + + next: + continue; + } + + + for (n = 0; n < cmcf->variables_keys->keys.nelts; n++) { + av = key[n].value; + + if (av->flags & NGX_STREAM_VAR_NOHASH) { + key[n].key.data = NULL; + } + } + + + hash.hash = &cmcf->variables_hash; + hash.key = ngx_hash_key; + hash.max_size = cmcf->variables_hash_max_size; + hash.bucket_size = cmcf->variables_hash_bucket_size; + hash.name = "variables_hash"; + hash.pool = cf->pool; + hash.temp_pool = NULL; + + if (ngx_hash_init(&hash, cmcf->variables_keys->keys.elts, + cmcf->variables_keys->keys.nelts) + != NGX_OK) + { + return NGX_ERROR; + } + + cmcf->variables_keys = NULL; + + return NGX_OK; +} diff --git a/src/stream/ngx_stream_variables.h b/src/stream/ngx_stream_variables.h new file mode 100644 index 0000000..e4151e2 --- /dev/null +++ b/src/stream/ngx_stream_variables.h @@ -0,0 +1,109 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_STREAM_VARIABLES_H_INCLUDED_ +#define _NGX_STREAM_VARIABLES_H_INCLUDED_ + + +#include +#include +#include + + +typedef ngx_variable_value_t ngx_stream_variable_value_t; + +#define ngx_stream_variable(v) { sizeof(v) - 1, 1, 0, 0, 0, (u_char *) v } + +typedef struct ngx_stream_variable_s ngx_stream_variable_t; + +typedef void (*ngx_stream_set_variable_pt) (ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data); +typedef ngx_int_t (*ngx_stream_get_variable_pt) (ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data); + + +#define NGX_STREAM_VAR_CHANGEABLE 1 +#define NGX_STREAM_VAR_NOCACHEABLE 2 +#define NGX_STREAM_VAR_INDEXED 4 +#define NGX_STREAM_VAR_NOHASH 8 + + +struct ngx_stream_variable_s { + ngx_str_t name; /* must be first to build the hash */ + ngx_stream_set_variable_pt set_handler; + ngx_stream_get_variable_pt get_handler; + uintptr_t data; + ngx_uint_t flags; + ngx_uint_t index; +}; + + +ngx_stream_variable_t *ngx_stream_add_variable(ngx_conf_t *cf, ngx_str_t *name, + ngx_uint_t flags); +ngx_int_t ngx_stream_get_variable_index(ngx_conf_t *cf, ngx_str_t *name); +ngx_stream_variable_value_t *ngx_stream_get_indexed_variable( + ngx_stream_session_t *s, ngx_uint_t index); +ngx_stream_variable_value_t *ngx_stream_get_flushed_variable( + ngx_stream_session_t *s, ngx_uint_t index); + +ngx_stream_variable_value_t *ngx_stream_get_variable(ngx_stream_session_t *s, + ngx_str_t *name, ngx_uint_t key); + + +#if (NGX_PCRE) + +typedef struct { + ngx_uint_t capture; + ngx_int_t index; +} ngx_stream_regex_variable_t; + + +typedef struct { + ngx_regex_t *regex; + ngx_uint_t ncaptures; + ngx_stream_regex_variable_t *variables; + ngx_uint_t nvariables; + ngx_str_t name; +} ngx_stream_regex_t; + + +typedef struct { + ngx_stream_regex_t *regex; + void *value; +} ngx_stream_map_regex_t; + + +ngx_stream_regex_t *ngx_stream_regex_compile(ngx_conf_t *cf, + ngx_regex_compile_t *rc); +ngx_int_t ngx_stream_regex_exec(ngx_stream_session_t *s, ngx_stream_regex_t *re, + ngx_str_t *str); + +#endif + + +typedef struct { + ngx_hash_combined_t hash; +#if (NGX_PCRE) + ngx_stream_map_regex_t *regex; + ngx_uint_t nregex; +#endif +} ngx_stream_map_t; + + +void *ngx_stream_map_find(ngx_stream_session_t *s, ngx_stream_map_t *map, + ngx_str_t *match); + + +ngx_int_t ngx_stream_variables_add_core_vars(ngx_conf_t *cf); +ngx_int_t ngx_stream_variables_init_vars(ngx_conf_t *cf); + + +extern ngx_stream_variable_value_t ngx_stream_variable_null_value; +extern ngx_stream_variable_value_t ngx_stream_variable_true_value; + + +#endif /* _NGX_STREAM_VARIABLES_H_INCLUDED_ */ From 561cc605190ba0f0d851af4073320c0607372ad2 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Mon, 1 Aug 2016 10:38:39 +0300 Subject: [PATCH 083/600] Add pointers to track modules not yet ready for migration --- debian/modules/README.Modules-versions | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/debian/modules/README.Modules-versions b/debian/modules/README.Modules-versions index b71b1e0..02e38b8 100644 --- a/debian/modules/README.Modules-versions +++ b/debian/modules/README.Modules-versions @@ -27,6 +27,7 @@ README for Modules versions nginx-upstream-fair Homepage: https://github.com/gnosek/nginx-upstream-fair Version: a18b409 + Dynamic: No, https://github.com/gnosek/nginx-upstream-fair/pull/21 nginx-push Homepage: https://github.com/slact/nginx_http_push_module @@ -36,14 +37,17 @@ README for Modules versions Homepage: https://github.com/masterzen/nginx-upload-progress-module rm -r debian/nginx-upload-progress/test Version: v0.9.1 + Dynamic: No, https://github.com/masterzen/nginx-upload-progress-module/issues/46 nginx-cache-purge Homepage: https://github.com/FRiCKLE/ngx_cache_purge/ Version: 2.3 + Dynamic: No, https://github.com/FRiCKLE/ngx_cache_purge/pull/45 nginx-dav-ext-module Homepage: https://github.com/arut/nginx-dav-ext-module Version: v0.0.3 + Dynamic: No, https://github.com/arut/nginx-dav-ext-module/issues/21 ngx-fancyindex Homepage: https://github.com/aperezdc/ngx-fancyindex @@ -52,3 +56,4 @@ README for Modules versions ngx_http_substitutions_filter_module Homepage: https://github.com/yaoweibin/ngx_http_substitutions_filter_module Version: v0.6.4 + Dynamic: No, https://github.com/yaoweibin/ngx_http_substitutions_filter_module/pull/19 From c06d35b10321f5906788672f9516a0e5afe01997 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Fri, 26 Aug 2016 12:40:48 +0300 Subject: [PATCH 084/600] Enable slice module on all flavors --- debian/changelog | 1 + debian/control | 12 ++++++------ debian/rules | 1 + 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/debian/changelog b/debian/changelog index a0528da..b505145 100644 --- a/debian/changelog +++ b/debian/changelog @@ -4,6 +4,7 @@ nginx (1.10.1-2) UNRELEASED; urgency=medium * debian/control: Don't allow building against liblua5.1-0-dev on architectures that libluajit is available. + + Enable slice module on all flavors. (Closes: #815080) * debian/modules/nginx-lua: + Update nginx-lua to v0.10.5 diff --git a/debian/control b/debian/control index 0c7f2cb..5badc14 100644 --- a/debian/control +++ b/debian/control @@ -110,8 +110,8 @@ Description: nginx web/proxy server (standard version) . OPTIONAL HTTP MODULES: Addition, Auth Request, Charset, WebDAV, GeoIP, Gunzip, Gzip, Gzip Precompression, Headers, HTTP/2, Image Filter, Index, Log, Real IP, - SSI, SSL, Stream, Stub Status, Substitution, Thread Pool, Upstream, User ID, - XSLT. + Slice, SSI, SSL, Stream, Stub Status, Substitution, Thread Pool, Upstream, + User ID, XSLT. . MAIL MODULES: Mail Core, Auth HTTP, Proxy, SSL, IMAP, POP3, SMTP. . @@ -152,8 +152,8 @@ Description: nginx web/proxy server (basic version) FastCGI, Map, Proxy, Rewrite. . OPTIONAL HTTP MODULES: Auth Request, Charset, Gzip, Gzip Precompression, - Headers, HTTP/2, Index, Log, Real IP, SSI, SSL, Stub Status, Thread Pool, - WebDAV, Upstream. + Headers, HTTP/2, Index, Log, Real IP, Slice, SSI, SSL, Stub Status, Thread + Pool, WebDAV, Upstream. . THIRD PARTY MODULES: Echo. @@ -205,8 +205,8 @@ Description: nginx web/proxy server (extended version) . OPTIONAL HTTP MODULES: Addition, Auth Request, Charset, WebDAV, FLV, GeoIP, Gunzip, Gzip, Gzip Precompression, Headers, HTTP/2, Image Filter, Index, Log, - MP4, Embedded Perl, Random Index, Real IP, Secure Link, SSI, SSL, Stream, - Stub Status, Substitution, Thread Pool, Upstream, User ID, XSLT. + MP4, Embedded Perl, Random Index, Real IP, Slice, Secure Link, SSI, SSL, + Stream, Stub Status, Substitution, Thread Pool, Upstream, User ID, XSLT. . MAIL MODULES: Mail Core, Auth HTTP, Proxy, SSL, IMAP, POP3, SMTP. . diff --git a/debian/rules b/debian/rules index c21c307..39eb71a 100755 --- a/debian/rules +++ b/debian/rules @@ -52,6 +52,7 @@ common_configure_flags := \ --with-http_auth_request_module \ --with-http_v2_module \ --with-http_dav_module \ + --with-http_slice_module \ --with-threads light_configure_flags := \ From 6cdcbed1f9080da5d03af903822db5d6ade7c92d Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Fri, 26 Aug 2016 13:15:12 +0300 Subject: [PATCH 085/600] mod: Upgrade nginx-lua to v0.10.6 --- debian/changelog | 2 +- debian/modules/README.Modules-versions | 2 +- debian/modules/nginx-lua/Changes | 51 - debian/modules/nginx-lua/README.markdown | 416 ++++-- debian/modules/nginx-lua/config | 6 + .../modules/nginx-lua/doc/HttpLuaModule.wiki | 380 ++++-- .../nginx-lua/src/api/ngx_http_lua_api.h | 2 +- .../nginx-lua/src/ngx_http_lua_accessby.c | 8 + .../nginx-lua/src/ngx_http_lua_balancer.c | 103 +- .../nginx-lua/src/ngx_http_lua_bodyfilterby.c | 2 +- .../nginx-lua/src/ngx_http_lua_cache.c | 4 +- .../nginx-lua/src/ngx_http_lua_clfactory.c | 8 +- .../nginx-lua/src/ngx_http_lua_common.h | 47 +- .../nginx-lua/src/ngx_http_lua_contentby.c | 8 + .../nginx-lua/src/ngx_http_lua_control.c | 26 +- .../nginx-lua/src/ngx_http_lua_coroutine.c | 12 +- .../nginx-lua/src/ngx_http_lua_directive.c | 16 +- .../src/ngx_http_lua_headerfilterby.c | 2 +- .../nginx-lua/src/ngx_http_lua_headers.c | 6 + .../nginx-lua/src/ngx_http_lua_headers_in.c | 5 + .../nginx-lua/src/ngx_http_lua_logby.c | 2 +- .../nginx-lua/src/ngx_http_lua_module.c | 112 +- .../nginx-lua/src/ngx_http_lua_phase.c | 10 +- .../nginx-lua/src/ngx_http_lua_rewriteby.c | 8 + .../nginx-lua/src/ngx_http_lua_setby.c | 2 +- .../nginx-lua/src/ngx_http_lua_shdict.c | 1133 +++++++++++++++-- .../nginx-lua/src/ngx_http_lua_shdict.h | 10 +- .../nginx-lua/src/ngx_http_lua_sleep.c | 3 +- .../nginx-lua/src/ngx_http_lua_socket_tcp.c | 12 +- .../modules/nginx-lua/src/ngx_http_lua_ssl.c | 37 + .../modules/nginx-lua/src/ngx_http_lua_ssl.h | 43 + .../nginx-lua/src/ngx_http_lua_ssl_certby.c | 362 +++++- .../nginx-lua/src/ngx_http_lua_ssl_certby.h | 10 - .../nginx-lua/src/ngx_http_lua_ssl_ocsp.c | 4 +- .../src/ngx_http_lua_ssl_session_fetchby.c | 592 +++++++++ .../src/ngx_http_lua_ssl_session_fetchby.h | 34 + .../src/ngx_http_lua_ssl_session_storeby.c | 602 +++++++++ .../src/ngx_http_lua_ssl_session_storeby.h | 34 + .../nginx-lua/src/ngx_http_lua_string.c | 4 +- .../nginx-lua/src/ngx_http_lua_subrequest.c | 2 +- .../nginx-lua/src/ngx_http_lua_timer.c | 2 +- .../modules/nginx-lua/src/ngx_http_lua_util.c | 48 +- .../modules/nginx-lua/src/ngx_http_lua_util.h | 5 +- debian/modules/nginx-lua/t/009-log.t | 2 +- debian/modules/nginx-lua/t/010-request_body.t | 2 +- debian/modules/nginx-lua/t/016-resp-header.t | 4 +- debian/modules/nginx-lua/t/020-subrequest.t | 2 +- .../nginx-lua/t/023-rewrite/request_body.t | 2 +- .../nginx-lua/t/023-rewrite/subrequest.t | 2 +- .../nginx-lua/t/024-access/request_body.t | 2 +- .../nginx-lua/t/024-access/subrequest.t | 2 +- debian/modules/nginx-lua/t/028-req-header.t | 42 +- debian/modules/nginx-lua/t/030-uri-args.t | 4 +- debian/modules/nginx-lua/t/031-post-args.t | 2 +- debian/modules/nginx-lua/t/043-shdict.t | 6 +- debian/modules/nginx-lua/t/062-count.t | 2 +- .../nginx-lua/t/068-socket-keepalive.t | 77 +- debian/modules/nginx-lua/t/070-sha1.t | 9 +- debian/modules/nginx-lua/t/129-ssl-socket.t | 48 +- debian/modules/nginx-lua/t/132-lua-blocks.t | 16 + debian/modules/nginx-lua/t/133-worker-count.t | 20 + debian/modules/nginx-lua/t/138-balancer.t | 28 +- debian/modules/nginx-lua/t/139-ssl-cert-by.t | 115 +- debian/modules/nginx-lua/t/140-ssl-c-api.t | 402 +++++- .../nginx-lua/t/142-ssl-session-store.t | 750 +++++++++++ .../nginx-lua/t/143-ssl-session-fetch.t | 1027 +++++++++++++++ .../nginx-lua/t/144-shdict-incr-init.t | 226 ++++ debian/modules/nginx-lua/t/145-shdict-list.t | 745 +++++++++++ debian/modules/nginx-lua/t/lib/CRC32.lua | 2 +- debian/modules/nginx-lua/util/build.sh | 2 +- debian/modules/nginx-lua/util/ngx-links | 2 +- 71 files changed, 7164 insertions(+), 556 deletions(-) delete mode 100644 debian/modules/nginx-lua/Changes create mode 100644 debian/modules/nginx-lua/src/ngx_http_lua_ssl.c create mode 100644 debian/modules/nginx-lua/src/ngx_http_lua_ssl.h create mode 100644 debian/modules/nginx-lua/src/ngx_http_lua_ssl_session_fetchby.c create mode 100644 debian/modules/nginx-lua/src/ngx_http_lua_ssl_session_fetchby.h create mode 100644 debian/modules/nginx-lua/src/ngx_http_lua_ssl_session_storeby.c create mode 100644 debian/modules/nginx-lua/src/ngx_http_lua_ssl_session_storeby.h create mode 100644 debian/modules/nginx-lua/t/142-ssl-session-store.t create mode 100644 debian/modules/nginx-lua/t/143-ssl-session-fetch.t create mode 100644 debian/modules/nginx-lua/t/144-shdict-incr-init.t create mode 100644 debian/modules/nginx-lua/t/145-shdict-list.t diff --git a/debian/changelog b/debian/changelog index b505145..1c253a7 100644 --- a/debian/changelog +++ b/debian/changelog @@ -6,7 +6,7 @@ nginx (1.10.1-2) UNRELEASED; urgency=medium that libluajit is available. + Enable slice module on all flavors. (Closes: #815080) * debian/modules/nginx-lua: - + Update nginx-lua to v0.10.5 + + Update nginx-lua to v0.10.6 [ Michael Lustfield ] * debian/patches/0003-*.patch: diff --git a/debian/modules/README.Modules-versions b/debian/modules/README.Modules-versions index 02e38b8..1ad980c 100644 --- a/debian/modules/README.Modules-versions +++ b/debian/modules/README.Modules-versions @@ -22,7 +22,7 @@ README for Modules versions nginx-lua Homepage: https://github.com/openresty/lua-nginx-module - Version: v0.10.5 + Version: v0.10.6 nginx-upstream-fair Homepage: https://github.com/gnosek/nginx-upstream-fair diff --git a/debian/modules/nginx-lua/Changes b/debian/modules/nginx-lua/Changes deleted file mode 100644 index 703f73d..0000000 --- a/debian/modules/nginx-lua/Changes +++ /dev/null @@ -1,51 +0,0 @@ -0.2.0 - 5 July 2011 -* now we support ngx.var[1], ngx.var[2], and etc to refer to the nginx regex capturing variables \$1, \$2, and etc in Lua. this resolved github issue #43. thanks Tobia Conforto for reporting it. - -* now we use the same value overriding mechanism as ngx_rewrite's set command for ngx.var.VAR = new_value. Assigning values to special variables like $limit_rate and $args should now work; also writing to built-in variables that are not changeable (like $arg_PARAMETER) will result in a 500 error page, as expected, now. thanks Richard Kearsley for reporting it. - -* fixed the lua_code_cache off warning when the lua_code_cache is explicitly on. thanks Feng Xingguo. - -* applied the patch from cyberty to add ngx.http_time() function to expose the nginx core function ngx_http_time to the Lua land. - -* fixed an issue on i386: we now use off_t consistently. mixing it with size_t on 32-bit systems can cause Bad Things. this fixed github issue #42. thanks moodydeath. - -* fixed an issue on i386: fixed a formatter mismatch issue in ngx_http_echo_adjust_subrequest. thanks Wang Bin. This caused incorrect subrequest Content-Length header when a body is specified. - -* now in the subrequest capturing processor, we worked around an issue in ngx_http_static_module that when it issues 301 redirect for directory access w/o a trailing slash, it does not inject r->headers_out.location into the r->headers_out.headers list. thanks moodydeath for reporting it in the discussion of github issue #41. - -* fixed a bug in ngx.location.capture() and ngx.location.capture_multi() that we could not capture locations with internal redirections in them. thanks moodydeath for reporting it in github issue #41. - -* fixed redundant last chunk issue for ngx.exec() invocation at rewrite and access phases: we should quit the current core_run_phases cycle; this also fixed github issue #40: 2 Subrequest calls when using access_by_lua, ngx.exec and echo_location. - -* fixed ngx.exit(status) where status >= 200 and status < 300 for access_by_lua* and rewrite_by_lua*: it should quit the whole request altegother and skip all those subsequent phase handlers (if any). thanks moodydeath for reporting it. - -* fixed github issue #39: setting differnt response headers in Lua with common prefix might interfere with each other. thanks moodydeath. - -* fixed GitHub issue #38: request headers did not forward to subrequests when the "method" or "body" option is explicitly specified by a non-nil value for ngx.location.capture(). thanks Richard Kearsley. - -* fixed a bug in output header set; we should always set the header->hash to 1. thanks moodydeath for reporting it. - -* fixed spots that trigger the "variable set but not used" warning issued by gcc 4.6.0. - -* now we turn the ngx.req.header table into an ngx.req.get_headers() function; we also added ngx.req.set_header(name, value) and ngx.req.clear_header(name). thanks moodydeath. - -* now we make ngx_devel_kit (NDK) optional. thanks Kirill A. Korinskiy. - -* removed a duplicate definition of the ngx_str_set macro caught by ctags; also fixed a warning thrown by gcc -O3 on Mac OS X 10.6. - -* added patch to use PCRE related Lua extensions in ngx_lua (chaoslawful) - -* now we change the way we process HTTP 1.0 requests by automatically buffering all the user outputs generated by ngx.print()/ngx.say() calls, which is much more natural than the old broken way. - -* fixed the "ngx.exec() after ngx.location.capture() hanging" bug for rewrite_by_lua* and access_by_lua* as well. thanks Wendal Chen. - -* applied a patch from moodydeath to introduce the "ngx.is_subrequest" attribute. - -* now we encourage use of the client_body_in_single_buffer directive instead of big client_body_buffer_size when lua_need_request_body is turned on. - -* fixed the config script and added extra linking options needed by LuaJIT in 64-bit Mac OS X. - -* fixed the zero size alert caused by ngx.print("") in Lua. - -* now we always allocate r->request_body for subrequests when the method option is specified for ngx.location.capture*. this prevents accidental inheritance of parent request's request body when client_body_buffer_size < client_max_body_size. - diff --git a/debian/modules/nginx-lua/README.markdown b/debian/modules/nginx-lua/README.markdown index 14e9ecc..8065060 100644 --- a/debian/modules/nginx-lua/README.markdown +++ b/debian/modules/nginx-lua/README.markdown @@ -62,7 +62,7 @@ Production ready. Version ======= -This document describes ngx_lua [v0.10.5](https://github.com/openresty/lua-nginx-module/tags) released on 25 May 2016. +This document describes ngx_lua [v0.10.6](https://github.com/openresty/lua-nginx-module/tags) released on 15 August 2016. Synopsis ======== @@ -249,6 +249,8 @@ Nginx Compatibility The latest version of this module is compatible with the following versions of Nginx: +* 1.11.x (last tested: 1.11.2) +* 1.10.x * 1.9.x (last tested: 1.9.15) * 1.8.x * 1.7.x (last tested: 1.7.10) @@ -274,9 +276,9 @@ Build the source with this module: ```bash - wget 'http://nginx.org/download/nginx-1.9.15.tar.gz' - tar -xzvf nginx-1.9.15.tar.gz - cd nginx-1.9.15/ + wget 'http://nginx.org/download/nginx-1.11.2.tar.gz' + tar -xzvf nginx-1.11.2.tar.gz + cd nginx-1.11.2/ # tell nginx's build system where to find LuaJIT 2.0: export LUAJIT_LIB=/path/to/luajit/lib @@ -1037,6 +1039,10 @@ Directives * [lua_need_request_body](#lua_need_request_body) * [ssl_certificate_by_lua_block](#ssl_certificate_by_lua_block) * [ssl_certificate_by_lua_file](#ssl_certificate_by_lua_file) +* [ssl_session_fetch_by_lua_block](#ssl_session_fetch_by_lua_block) +* [ssl_session_fetch_by_lua_file](#ssl_session_fetch_by_lua_file) +* [ssl_session_store_by_lua_block](#ssl_session_store_by_lua_block) +* [ssl_session_store_by_lua_file](#ssl_session_store_by_lua_file) * [lua_shared_dict](#lua_shared_dict) * [lua_socket_connect_timeout](#lua_socket_connect_timeout) * [lua_socket_send_timeout](#lua_socket_send_timeout) @@ -2320,7 +2326,7 @@ lua_need_request_body Determines whether to force the request body data to be read before running rewrite/access/access_by_lua* or not. The Nginx core does not read the client request body by default and if request body data is required, then this directive should be turned `on` or the [ngx.req.read_body](#ngxreqread_body) function should be called within the Lua code. -To read the request body data within the [$request_body](http://nginx.org/en/docs/http/ngx_http_core_module.html#var_request_body) variable, +To read the request body data within the [$request_body](http://nginx.org/en/docs/http/ngx_http_core_module.html#var_request_body) variable, [client_body_buffer_size](http://nginx.org/en/docs/http/ngx_http_core_module.html#client_body_buffer_size) must have the same value as [client_max_body_size](http://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size). Because when the content length exceeds [client_body_buffer_size](http://nginx.org/en/docs/http/ngx_http_core_module.html#client_body_buffer_size) but less than [client_max_body_size](http://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size), Nginx will buffer the data into a temporary file on the disk, which will lead to empty value in the [$request_body](http://nginx.org/en/docs/http/ngx_http_core_module.html#var_request_body) variable. If the current location includes [rewrite_by_lua](#rewrite_by_lua) or [rewrite_by_lua_file](#rewrite_by_lua_file) directives, @@ -2441,6 +2447,123 @@ This directive was first introduced in the `v0.10.0` release. [Back to TOC](#directives) +ssl_session_fetch_by_lua_block +------------------------------ + +**syntax:** *ssl_session_fetch_by_lua_block { lua-script }* + +**context:** *server* + +**phase:** *right-before-SSL-handshake* + +This directive runs Lua code to look up and load the SSL session (if any) according to the session ID +provided by the current SSL handshake request for the downstream. + +The Lua API for obtaining the current session ID and loading a cached SSL session data +is provided in the [ngx.ssl.session](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ssl/session.md) +Lua module shipped with the [lua-resty-core](https://github.com/openresty/lua-resty-core#readme) +library. + +Lua APIs that may yield, like [ngx.sleep](#ngxsleep) and [cosockets](#ngxsockettcp), +are enabled in this context. + +This hook, together with the [ssl_session_store_by_lua*](#ssl_session_store_by_lua_block) hook, +can be used to implement distributed caching mechanisms in pure Lua (based +on the [cosocket](#ngxsockettcp) API, for example). If a cached SSL session is found +and loaded into the current SSL connection context, +SSL session resumption can then get immediately initiated and bypass the full SSL handshake process which is very expensive in terms of CPU time. + +Please note that TLS session tickets are very different and it is the clients' responsibility +to cache the SSL session state when session tickets are used. SSL session resumptions based on +TLS session tickets would happen automatically without going through this hook (nor the +[ssl_session_store_by_lua_block](#ssl_session_store_by_lua) hook). This hook is mainly +for older or less capable SSL clients that can only do SSL sessions by session IDs. + +When [ssl_certificate_by_lua*](#ssl_certificate_by_lua_block) is specified at the same time, +this hook usually runs before [ssl_certificate_by_lua*](#ssl_certificate_by_lua_block). +When the SSL session is found and successfully loaded for the current SSL connection, +SSL session resumption will happen and thus bypass the [ssl_certificate_by_lua*](#ssl_certificate_by_lua_block) +hook completely. In this case, NGINX also bypasses the [ssl_session_store_by_lua_block](#ssl_session_store_by_lua) +hook, for obvious reasons. + +If you are using the [official pre-built packages](http://openresty.org/en/linux-packages.html) for [OpenResty](https://openresty.org/) +1.11.2.1 or later, then everything should work out of the box. + +If you are using OpenSSL libraries not provided by [OpenResty](https://openresty.org), +then you need to apply the following patch for OpenSSL 1.0.2h or later: + + + +If you are not using the NGINX core shipped with [OpenResty](https://openresty.org) 1.11.2.1 or later, then you need to +apply the following patch to the standard NGINX core 1.11.2 or later: + + + +This directive was first introduced in the `v0.10.6` release. + +[Back to TOC](#directives) + +ssl_session_fetch_by_lua_file +----------------------------- + +**syntax:** *ssl_session_fetch_by_lua_file <path-to-lua-script-file>* + +**context:** *server* + +**phase:** *right-before-SSL-handshake* + +Equivalent to [ssl_session_fetch_by_lua_block](#ssl_session_fetch_by_lua_block), except that the file specified by `` contains the Lua code, or rather, the [Lua/LuaJIT bytecode](#lualuajit-bytecode-support) to be executed. + +When a relative path like `foo/bar.lua` is given, they will be turned into the absolute path relative to the `server prefix` path determined by the `-p PATH` command-line option while starting the Nginx server. + +This directive was first introduced in the `v0.10.6` release. + +[Back to TOC](#directives) + +ssl_session_store_by_lua_block +------------------------------ + +**syntax:** *ssl_session_store_by_lua_block { lua-script }* + +**context:** *server* + +**phase:** *right-after-SSL-handshake* + +This directive runs Lua code to fetch and save the SSL session (if any) according to the session ID +provided by the current SSL handshake request for the downstream. The saved or cached SSL +session data can be used for future SSL connections to resume SSL sessions without going +through the full SSL handshake process (which is very expensive in terms of CPU time). + +Lua APIs that may yield, like [ngx.sleep](#ngxsleep) and [cosockets](#ngxsockettcp), +are *disabled* in this context. You can still, however, use the [ngx.timer.at](#ngxtimerat) API +to create 0-delay timers to save the SSL session data asynchronously to external services (like `redis` or `memcached`). + +The Lua API for obtaining the current session ID and the associated session state data +is provided in the [ngx.ssl.session](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ssl/session.md#readme) +Lua module shipped with the [lua-resty-core](https://github.com/openresty/lua-resty-core#readme) +library. + +This directive was first introduced in the `v0.10.6` release. + +[Back to TOC](#directives) + +ssl_session_store_by_lua_file +----------------------------- + +**syntax:** *ssl_session_store_by_lua_file <path-to-lua-script-file>* + +**context:** *server* + +**phase:** *right-before-SSL-handshake* + +Equivalent to [ssl_session_store_by_lua_block](#ssl_session_store_by_lua_block), except that the file specified by `` contains the Lua code, or rather, the [Lua/LuaJIT bytecode](#lualuajit-bytecode-support) to be executed. + +When a relative path like `foo/bar.lua` is given, they will be turned into the absolute path relative to the `server prefix` path determined by the `-p PATH` command-line option while starting the Nginx server. + +This directive was first introduced in the `v0.10.6` release. + +[Back to TOC](#directives) + lua_shared_dict --------------- @@ -2920,6 +3043,11 @@ Nginx API for Lua * [ngx.shared.DICT.replace](#ngxshareddictreplace) * [ngx.shared.DICT.delete](#ngxshareddictdelete) * [ngx.shared.DICT.incr](#ngxshareddictincr) +* [ngx.shared.DICT.lpush](#ngxshareddictlpush) +* [ngx.shared.DICT.rpush](#ngxshareddictrpush) +* [ngx.shared.DICT.lpop](#ngxshareddictlpop) +* [ngx.shared.DICT.rpop](#ngxshareddictrpop) +* [ngx.shared.DICT.llen](#ngxshareddictllen) * [ngx.shared.DICT.flush_all](#ngxshareddictflush_all) * [ngx.shared.DICT.flush_expired](#ngxshareddictflush_expired) * [ngx.shared.DICT.get_keys](#ngxshareddictget_keys) @@ -3110,7 +3238,7 @@ This API requires a relatively expensive metamethod call and it is recommended t Core constants -------------- -**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, *log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, *log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** ```lua @@ -3136,7 +3264,7 @@ The `ngx.DECLINED` constant was first introduced in the `v0.5.0rc19` release. HTTP method constants --------------------- -**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** ngx.HTTP_GET @@ -3162,7 +3290,7 @@ These constants are usually used in [ngx.location.capture](#ngxlocationcapture) HTTP status constants --------------------- -**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** ```nginx @@ -3206,7 +3334,7 @@ HTTP status constants Nginx log level constants ------------------------- -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** ```lua @@ -3229,7 +3357,7 @@ print ----- **syntax:** *print(...)* -**context:** *init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.*, balancer_by_lua*, certificate_by_lua** +**context:** *init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Writes argument values into the nginx `error.log` file with the `ngx.NOTICE` log level. @@ -3998,6 +4126,8 @@ outputs something like this: This method was first introduced in the `v0.7.17` release. +This method does not work in HTTP/2 requests yet. + [Back to TOC](#nginx-api-for-lua) ngx.req.get_method @@ -4961,7 +5091,7 @@ ngx.log ------- **syntax:** *ngx.log(log_level, ...)* -**context:** *init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Log arguments concatenated to error.log with the given logging level. @@ -4979,9 +5109,9 @@ ngx.flush **context:** *rewrite_by_lua*, access_by_lua*, content_by_lua** -Flushes response output to the client. +Flushes response output to the client. -`ngx.flush` accepts an optional boolean `wait` argument (Default: `false`) first introduced in the `v0.3.1rc34` release. When called with the default argument, it issues an asynchronous call (Returns immediately without waiting for output data to be written into the system send buffer). Calling the function with the `wait` argument set to `true` switches to synchronous mode. +`ngx.flush` accepts an optional boolean `wait` argument (Default: `false`) first introduced in the `v0.3.1rc34` release. When called with the default argument, it issues an asynchronous call (Returns immediately without waiting for output data to be written into the system send buffer). Calling the function with the `wait` argument set to `true` switches to synchronous mode. In synchronous mode, the function will not return until all output data has been written into the system send buffer or until the [send_timeout](http://nginx.org/en/docs/http/ngx_http_core_module.html#send_timeout) setting has expired. Note that using the Lua coroutine mechanism means that this function does not block the Nginx event loop even in the synchronous mode. @@ -4997,7 +5127,7 @@ ngx.exit -------- **syntax:** *ngx.exit(status)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** When `status >= 200` (i.e., `ngx.HTTP_OK` and above), it will interrupt the execution of the current request and return status code to nginx. @@ -5042,7 +5172,9 @@ Note that while this method accepts all [HTTP status constants](#http-status-con Also note that this method call terminates the processing of the current request and that it is recommended that a coding style that combines this method call with the `return` statement, i.e., `return ngx.exit(...)` be used to reinforce the fact that the request processing is being terminated. -When being used in the context of [header_filter_by_lua](#header_filter_by_lua), `ngx.exit()` is an asynchronous operation and will return immediately. This behavior may change in future and it is recommended that users always use `return` in combination as suggested above. +When being used in the contexts of [header_filter_by_lua](#header_filter_by_lua) and +[ssl_session_store_by_lua*](#ssl_session_store_by_lua_block), `ngx.exit()` is +an asynchronous operation and will return immediately. This behavior may change in future and it is recommended that users always use `return` in combination as suggested above. [Back to TOC](#nginx-api-for-lua) @@ -5085,7 +5217,7 @@ ngx.sleep --------- **syntax:** *ngx.sleep(seconds)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua** Sleeps for the specified seconds without blocking. One can specify time resolution up to 0.001 seconds (i.e., one milliseconds). @@ -5101,7 +5233,7 @@ ngx.escape_uri -------------- **syntax:** *newstr = ngx.escape_uri(str)* -**context:** *init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Escape `str` as a URI component. @@ -5191,7 +5323,7 @@ ngx.decode_args --------------- **syntax:** *table = ngx.decode_args(str, max_args?)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Decodes a URI encoded query-string into a Lua table. This is the inverse function of [ngx.encode_args](#ngxencode_args). @@ -5214,7 +5346,7 @@ ngx.encode_base64 ----------------- **syntax:** *newstr = ngx.encode_base64(str, no_padding?)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Encodes `str` to a base64 digest. @@ -5226,7 +5358,7 @@ ngx.decode_base64 ----------------- **syntax:** *newstr = ngx.decode_base64(str)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Decodes the `str` argument as a base64 digest to the raw form. Returns `nil` if `str` is not well formed. @@ -5236,7 +5368,7 @@ ngx.crc32_short --------------- **syntax:** *intval = ngx.crc32_short(str)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Calculates the CRC-32 (Cyclic Redundancy Code) digest for the `str` argument. @@ -5252,7 +5384,7 @@ ngx.crc32_long -------------- **syntax:** *intval = ngx.crc32_long(str)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Calculates the CRC-32 (Cyclic Redundancy Code) digest for the `str` argument. @@ -5268,7 +5400,7 @@ ngx.hmac_sha1 ------------- **syntax:** *digest = ngx.hmac_sha1(secret_key, str)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Computes the [HMAC-SHA1](http://en.wikipedia.org/wiki/HMAC) digest of the argument `str` and turns the result using the secret key ``. @@ -5300,7 +5432,7 @@ ngx.md5 ------- **syntax:** *digest = ngx.md5(str)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Returns the hexadecimal representation of the MD5 digest of the `str` argument. @@ -5327,7 +5459,7 @@ ngx.md5_bin ----------- **syntax:** *digest = ngx.md5_bin(str)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Returns the binary form of the MD5 digest of the `str` argument. @@ -5339,7 +5471,7 @@ ngx.sha1_bin ------------ **syntax:** *digest = ngx.sha1_bin(str)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Returns the binary form of the SHA-1 digest of the `str` argument. @@ -5353,7 +5485,7 @@ ngx.quote_sql_str ----------------- **syntax:** *quoted_value = ngx.quote_sql_str(raw_value)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Returns a quoted SQL string literal according to the MySQL quoting rules. @@ -5363,7 +5495,7 @@ ngx.today --------- **syntax:** *str = ngx.today()* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Returns current date (in the format `yyyy-mm-dd`) from the nginx cached time (no syscall involved unlike Lua's date library). @@ -5375,7 +5507,7 @@ ngx.time -------- **syntax:** *secs = ngx.time()* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Returns the elapsed seconds from the epoch for the current time stamp from the nginx cached time (no syscall involved unlike Lua's date library). @@ -5387,7 +5519,7 @@ ngx.now ------- **syntax:** *secs = ngx.now()* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Returns a floating-point number for the elapsed time in seconds (including milliseconds as the decimal part) from the epoch for the current time stamp from the nginx cached time (no syscall involved unlike Lua's date library). @@ -5401,7 +5533,7 @@ ngx.update_time --------------- **syntax:** *ngx.update_time()* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Forcibly updates the Nginx current time cache. This call involves a syscall and thus has some overhead, so do not abuse it. @@ -5413,7 +5545,7 @@ ngx.localtime ------------- **syntax:** *str = ngx.localtime()* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Returns the current time stamp (in the format `yyyy-mm-dd hh:mm:ss`) of the nginx cached time (no syscall involved unlike Lua's [os.date](http://www.lua.org/manual/5.1/manual.html#pdf-os.date) function). @@ -5425,7 +5557,7 @@ ngx.utctime ----------- **syntax:** *str = ngx.utctime()* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Returns the current time stamp (in the format `yyyy-mm-dd hh:mm:ss`) of the nginx cached time (no syscall involved unlike Lua's [os.date](http://www.lua.org/manual/5.1/manual.html#pdf-os.date) function). @@ -5437,7 +5569,7 @@ ngx.cookie_time --------------- **syntax:** *str = ngx.cookie_time(sec)* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Returns a formatted string can be used as the cookie expiration time. The parameter `sec` is the time stamp in seconds (like those returned from [ngx.time](#ngxtime)). @@ -5453,7 +5585,7 @@ ngx.http_time ------------- **syntax:** *str = ngx.http_time(sec)* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Returns a formated string can be used as the http header time (for example, being used in `Last-Modified` header). The parameter `sec` is the time stamp in seconds (like those returned from [ngx.time](#ngxtime)). @@ -5469,7 +5601,7 @@ ngx.parse_http_time ------------------- **syntax:** *sec = ngx.parse_http_time(str)* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Parse the http time string (as returned by [ngx.http_time](#ngxhttp_time)) into seconds. Returns the seconds or `nil` if the input string is in bad forms. @@ -5497,7 +5629,7 @@ ngx.re.match ------------ **syntax:** *captures, err = ngx.re.match(subject, regex, options?, ctx?, res_table?)* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Matches the `subject` string using the Perl compatible regular expression `regex` with the optional `options`. @@ -5655,9 +5787,9 @@ ngx.re.find ----------- **syntax:** *from, to, err = ngx.re.find(subject, regex, options?, ctx?, nth?)* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** -Similar to [ngx.re.match](#ngxrematch) but only returns the begining index (`from`) and end index (`to`) of the matched substring. The returned indexes are 1-based and can be fed directly into the [string.sub](http://www.lua.org/manual/5.1/manual.html#pdf-string.sub) API function to obtain the matched substring. +Similar to [ngx.re.match](#ngxrematch) but only returns the beginning index (`from`) and end index (`to`) of the matched substring. The returned indexes are 1-based and can be fed directly into the [string.sub](http://www.lua.org/manual/5.1/manual.html#pdf-string.sub) API function to obtain the matched substring. In case of errors (like bad regexes or any PCRE runtime errors), this API function returns two `nil` values followed by a string describing the error. @@ -5709,7 +5841,7 @@ ngx.re.gmatch ------------- **syntax:** *iterator, err = ngx.re.gmatch(subject, regex, options?)* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Similar to [ngx.re.match](#ngxrematch), but returns a Lua iterator instead, so as to let the user programmer iterate all the matches over the `` string argument with the PCRE `regex`. @@ -5787,7 +5919,7 @@ ngx.re.sub ---------- **syntax:** *newstr, n, err = ngx.re.sub(subject, regex, replace, options?)* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Substitutes the first match of the Perl compatible regular expression `regex` on the `subject` argument string with the string or function argument `replace`. The optional `options` argument has exactly the same meaning as in [ngx.re.match](#ngxrematch). @@ -5853,7 +5985,7 @@ ngx.re.gsub ----------- **syntax:** *newstr, n, err = ngx.re.gsub(subject, regex, replace, options?)* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Just like [ngx.re.sub](#ngxresub), but does global substitution. @@ -5893,7 +6025,7 @@ ngx.shared.DICT **syntax:** *dict = ngx.shared\[name_var\]* -**context:** *init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Fetching the shm-based Lua dictionary object for the shared memory zone named `DICT` defined by the [lua_shared_dict](#lua_shared_dict) directive. @@ -5910,6 +6042,11 @@ The resulting object `dict` has the following methods: * [replace](#ngxshareddictreplace) * [delete](#ngxshareddictdelete) * [incr](#ngxshareddictincr) +* [lpush](#ngxshareddictlpush) +* [rpush](#ngxshareddictrpush) +* [lpop](#ngxshareddictlpop) +* [rpop](#ngxshareddictrpop) +* [llen](#ngxshareddictllen) * [flush_all](#ngxshareddictflush_all) * [flush_expired](#ngxshareddictflush_expired) * [get_keys](#ngxshareddictget_keys) @@ -5966,9 +6103,9 @@ ngx.shared.DICT.get ------------------- **syntax:** *value, flags = ngx.shared.DICT:get(key)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** -Retrieving the value in the dictionary [ngx.shared.DICT](#ngxshareddict) for the key `key`. If the key does not exist or has been expired, then `nil` will be returned. +Retrieving the value in the dictionary [ngx.shared.DICT](#ngxshareddict) for the key `key`. If the key does not exist or has expired, then `nil` will be returned. In case of errors, `nil` and a string describing the error will be returned. @@ -6004,7 +6141,7 @@ ngx.shared.DICT.get_stale ------------------------- **syntax:** *value, flags, stale = ngx.shared.DICT:get_stale(key)* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Similar to the [get](#ngxshareddictget) method but returns the value even if the key has already expired. @@ -6022,7 +6159,7 @@ ngx.shared.DICT.set ------------------- **syntax:** *success, err, forcible = ngx.shared.DICT:set(key, value, exptime?, flags?)* -**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Unconditionally sets a key-value pair into the shm-based dictionary [ngx.shared.DICT](#ngxshareddict). Returns three values: @@ -6070,7 +6207,7 @@ ngx.shared.DICT.safe_set ------------------------ **syntax:** *ok, err = ngx.shared.DICT:safe_set(key, value, exptime?, flags?)* -**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Similar to the [set](#ngxshareddictset) method, but never overrides the (least recently used) unexpired items in the store when running out of storage in the shared memory zone. In this case, it will immediately return `nil` and the string "no memory". @@ -6084,7 +6221,7 @@ ngx.shared.DICT.add ------------------- **syntax:** *success, err, forcible = ngx.shared.DICT:add(key, value, exptime?, flags?)* -**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Just like the [set](#ngxshareddictset) method, but only stores the key-value pair into the dictionary [ngx.shared.DICT](#ngxshareddict) if the key does *not* exist. @@ -6100,7 +6237,7 @@ ngx.shared.DICT.safe_add ------------------------ **syntax:** *ok, err = ngx.shared.DICT:safe_add(key, value, exptime?, flags?)* -**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Similar to the [add](#ngxshareddictadd) method, but never overrides the (least recently used) unexpired items in the store when running out of storage in the shared memory zone. In this case, it will immediately return `nil` and the string "no memory". @@ -6114,7 +6251,7 @@ ngx.shared.DICT.replace ----------------------- **syntax:** *success, err, forcible = ngx.shared.DICT:replace(key, value, exptime?, flags?)* -**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Just like the [set](#ngxshareddictset) method, but only stores the key-value pair into the dictionary [ngx.shared.DICT](#ngxshareddict) if the key *does* exist. @@ -6130,7 +6267,7 @@ ngx.shared.DICT.delete ---------------------- **syntax:** *ngx.shared.DICT:delete(key)* -**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Unconditionally removes the key-value pair from the shm-based dictionary [ngx.shared.DICT](#ngxshareddict). @@ -6144,19 +6281,110 @@ See also [ngx.shared.DICT](#ngxshareddict). ngx.shared.DICT.incr -------------------- -**syntax:** *newval, err = ngx.shared.DICT:incr(key, value)* +**syntax:** *newval, err, forcible? = ngx.shared.DICT:incr(key, value, init?)* -**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Increments the (numerical) value for `key` in the shm-based dictionary [ngx.shared.DICT](#ngxshareddict) by the step value `value`. Returns the new resulting number if the operation is successfully completed or `nil` and an error message otherwise. -The key must already exist in the dictionary, otherwise it will return `nil` and `"not found"`. +When the key does not exist or has already expired in the shared dictionary, + +1. if the `init` argument is not specified or takes the value `nil`, this method will return `nil` and the error string `"not found"`, or +1. if the `init` argument takes a number value, this method will create a new `key` with the value `init + value`. + +Like the [add](#ngxshareddictadd) method, it also overrides the (least recently used) unexpired items in the store when running out of storage in the shared memory zone. + +The `forcible` return value will always be `nil` when the `init` argument is not specified. + +If this method succeeds in storing the current item by forcibly removing other not-yet-expired items in the dictionary via LRU, the `forcible` return value will be `true`. If it stores the item without forcibly removing other valid items, then the return value `forcible` will be `false`. If the original value is not a valid Lua number in the dictionary, it will return `nil` and `"not a number"`. -The `value` argument can be any valid Lua numbers, like negative numbers or floating-point numbers. +The `value` argument and `init` argument can be any valid Lua numbers, like negative numbers or floating-point numbers. -This feature was first introduced in the `v0.3.1rc22` release. +This method was first introduced in the `v0.3.1rc22` release. + +The optional `init` parameter was first added in the `v0.10.6` release. + +See also [ngx.shared.DICT](#ngxshareddict). + +[Back to TOC](#nginx-api-for-lua) + +ngx.shared.DICT.lpush +--------------------- +**syntax:** *length, err = ngx.shared.DICT:lpush(key, value)* + +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** + +Inserts the specified (numerical or string) `value` at the head of the list named `key` in the shm-based dictionary [ngx.shared.DICT](#ngxshareddict). Returns the number of elements in the list after the push operation. + +If `key` does not exist, it is created as an empty list before performing the push operation. When the `key` already takes a value that is not a list, it will return `nil` and `"value not a list"`. + +It never overrides the (least recently used) unexpired items in the store when running out of storage in the shared memory zone. In this case, it will immediately return `nil` and the string "no memory". + +This feature was first introduced in the `v0.10.6` release. + +See also [ngx.shared.DICT](#ngxshareddict). + +[Back to TOC](#nginx-api-for-lua) + +ngx.shared.DICT.rpush +--------------------- +**syntax:** *length, err = ngx.shared.DICT:rpush(key, value)* + +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** + +Similar to the [lpush](#ngxshareddictlpush) method, but inserts the specified (numerical or string) `value` at the tail of the list named `key`. + +This feature was first introduced in the `v0.10.6` release. + +See also [ngx.shared.DICT](#ngxshareddict). + +[Back to TOC](#nginx-api-for-lua) + +ngx.shared.DICT.lpop +-------------------- +**syntax:** *val, err = ngx.shared.DICT:lpop(key)* + +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** + +Removes and returns the first element of the list named `key` in the shm-based dictionary [ngx.shared.DICT](#ngxshareddict). + +If `key` does not exist, it will return `nil`. When the `key` already takes a value that is not a list, it will return `nil` and `"value not a list"`. + +This feature was first introduced in the `v0.10.6` release. + +See also [ngx.shared.DICT](#ngxshareddict). + +[Back to TOC](#nginx-api-for-lua) + +ngx.shared.DICT.rpop +-------------------- +**syntax:** *val, err = ngx.shared.DICT:rpop(key)* + +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** + +Removes and returns the last element of the list named `key` in the shm-based dictionary [ngx.shared.DICT](#ngxshareddict). + +If `key` does not exist, it will return `nil`. When the `key` already takes a value that is not a list, it will return `nil` and `"value not a list"`. + +This feature was first introduced in the `v0.10.6` release. + +See also [ngx.shared.DICT](#ngxshareddict). + +[Back to TOC](#nginx-api-for-lua) + +ngx.shared.DICT.llen +-------------------- +**syntax:** *len, err = ngx.shared.DICT:llen(key)* + +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** + +Returns the number of elements in the list named `key` in the shm-based dictionary [ngx.shared.DICT](#ngxshareddict). + +If key does not exist, it is interpreted as an empty list and 0 is returned. When the `key` already takes a value that is not a list, it will return `nil` and `"value not a list"`. + +This feature was first introduced in the `v0.10.6` release. See also [ngx.shared.DICT](#ngxshareddict). @@ -6166,7 +6394,7 @@ ngx.shared.DICT.flush_all ------------------------- **syntax:** *ngx.shared.DICT:flush_all()* -**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Flushes out all the items in the dictionary. This method does not actuall free up all the memory blocks in the dictionary but just marks all the existing items as expired. @@ -6180,7 +6408,7 @@ ngx.shared.DICT.flush_expired ----------------------------- **syntax:** *flushed = ngx.shared.DICT:flush_expired(max_count?)* -**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Flushes out the expired items in the dictionary, up to the maximal number specified by the optional `max_count` argument. When the `max_count` argument is given `0` or not given at all, then it means unlimited. Returns the number of items that have actually been flushed. @@ -6196,7 +6424,7 @@ ngx.shared.DICT.get_keys ------------------------ **syntax:** *keys = ngx.shared.DICT:get_keys(max_count?)* -**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Fetch a list of the keys from the dictionary, up to ``. @@ -6212,7 +6440,7 @@ ngx.socket.udp -------------- **syntax:** *udpsock = ngx.socket.udp()* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua** Creates and returns a UDP or datagram-oriented unix domain socket object (also known as one type of the "cosocket" objects). The following methods are supported on this object: @@ -6236,7 +6464,7 @@ udpsock:setpeername **syntax:** *ok, err = udpsock:setpeername("unix:/path/to/unix-domain.socket")* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua** Attempts to connect a UDP socket object to a remote server or to a datagram unix domain socket file. Because the datagram protocol is actually connection-less, this method does not really establish a "connection", but only just set the name of the remote peer for subsequent read/write operations. @@ -6295,7 +6523,7 @@ udpsock:send ------------ **syntax:** *ok, err = udpsock:send(data)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua** Sends data on the current UDP or datagram unix domain socket object. @@ -6311,7 +6539,7 @@ udpsock:receive --------------- **syntax:** *data, err = udpsock:receive(size?)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua** Receives data from the UDP or datagram unix domain socket object with an optional receive buffer size argument, `size`. @@ -6346,7 +6574,7 @@ udpsock:close ------------- **syntax:** *ok, err = udpsock:close()* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua** Closes the current UDP or datagram unix domain socket. It returns the `1` in case of success and returns `nil` with a string describing the error otherwise. @@ -6360,7 +6588,7 @@ udpsock:settimeout ------------------ **syntax:** *udpsock:settimeout(time)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua** Set the timeout value in milliseconds for subsequent socket operations (like [receive](#udpsockreceive)). @@ -6384,7 +6612,7 @@ ngx.socket.tcp -------------- **syntax:** *tcpsock = ngx.socket.tcp()* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua** Creates and returns a TCP or stream-oriented unix domain socket object (also known as one type of the "cosocket" objects). The following methods are supported on this object: @@ -6430,7 +6658,7 @@ tcpsock:connect **syntax:** *ok, err = tcpsock:connect("unix:/path/to/unix-domain.socket", options_table?)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua** Attempts to connect a TCP socket object to a remote server or to a stream unix domain socket file without blocking. @@ -6509,7 +6737,7 @@ tcpsock:sslhandshake -------------------- **syntax:** *session, err = tcpsock:sslhandshake(reused_session?, server_name?, ssl_verify?, send_status_req?)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua** Does SSL/TLS handshake on the currently established connection. @@ -6554,7 +6782,7 @@ tcpsock:send ------------ **syntax:** *bytes, err = tcpsock:send(data)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua** Sends data without blocking on the current TCP or Unix Domain Socket connection. @@ -6586,7 +6814,7 @@ tcpsock:receive **syntax:** *data, err, partial = tcpsock:receive(pattern?)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua** Receives data from the connected socket according to the reading pattern or size. @@ -6628,7 +6856,7 @@ tcpsock:receiveuntil -------------------- **syntax:** *iterator = tcpsock:receiveuntil(pattern, options?)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua** This method returns an iterator Lua function that can be called to read the data stream until it sees the specified pattern or an error occurs. @@ -6727,7 +6955,7 @@ tcpsock:close ------------- **syntax:** *ok, err = tcpsock:close()* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua** Closes the current TCP or stream unix domain socket. It returns the `1` in case of success and returns `nil` with a string describing the error otherwise. @@ -6743,7 +6971,7 @@ tcpsock:settimeout ------------------ **syntax:** *tcpsock:settimeout(time)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua** Set the timeout value in milliseconds for subsequent socket operations ([connect](#tcpsockconnect), [receive](#tcpsockreceive), and iterators returned from [receiveuntil](#tcpsockreceiveuntil)). @@ -6759,7 +6987,7 @@ tcpsock:setoption ----------------- **syntax:** *tcpsock:setoption(option, value?)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua** This function is added for [LuaSocket](http://w3.impa.br/~diego/software/luasocket/tcp.html) API compatibility and does nothing for now. Its functionality will be implemented in future. @@ -6771,7 +6999,7 @@ tcpsock:setkeepalive -------------------- **syntax:** *ok, err = tcpsock:setkeepalive(timeout?, size?)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua** Puts the current socket's connection immediately into the cosocket built-in connection pool and keep it alive until other [connect](#tcpsockconnect) method calls request it or the associated maximal idle timeout is expired. @@ -6799,7 +7027,7 @@ tcpsock:getreusedtimes ---------------------- **syntax:** *count, err = tcpsock:getreusedtimes()* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua** This method returns the (successfully) reused times for the current connection. In case of error, it returns `nil` and a string describing the error. @@ -6839,7 +7067,7 @@ ngx.get_phase ------------- **syntax:** *str = ngx.get_phase()* -**context:** *init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Retrieves the current running phase name. Possible return values are @@ -6849,6 +7077,10 @@ Retrieves the current running phase name. Possible return values are for the context of [init_worker_by_lua](#init_worker_by_lua) or [init_worker_by_lua_file](#init_worker_by_lua_file). * `ssl_cert` for the context of [ssl_certificate_by_lua_block](#ssl_certificate_by_lua_block) or [ssl_certificate_by_lua_file](#ssl_certificate_by_lua_file). +* `ssl_session_fetch` + for the context of [ssl_session_fetch_by_lua*](#ssl_session_fetch_by_lua_block). +* `ssl_session_store` + for the context of [ssl_session_store_by_lua*](#ssl_session_store_by_lua_block). * `set` for the context of [set_by_lua](#set_by_lua) or [set_by_lua_file](#set_by_lua_file). * `rewrite` @@ -6876,7 +7108,7 @@ ngx.thread.spawn ---------------- **syntax:** *co = ngx.thread.spawn(func, arg1, arg2, ...)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua** Spawns a new user "light thread" with the Lua function `func` as well as those optional arguments `arg1`, `arg2`, and etc. Returns a Lua thread (or Lua coroutine) object represents this "light thread". @@ -7014,7 +7246,7 @@ ngx.thread.wait --------------- **syntax:** *ok, res1, res2, ... = ngx.thread.wait(thread1, thread2, ...)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua** Waits on one or more child "light threads" and returns the results of the first "light thread" that terminates (either successfully or with an error). @@ -7171,7 +7403,7 @@ ngx.timer.at ------------ **syntax:** *ok, err = ngx.timer.at(delay, callback, user_arg1, user_arg2, ...)* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Creates an Nginx timer with a user callback function as well as optional user arguments. @@ -7229,7 +7461,7 @@ Here is a simple example: } ``` -One can also create infinite re-occuring timers, for instance, a timer getting triggered every `5` seconds, by calling `ngx.timer.at` recursively in the timer callback function. Here is such an example, +One can also create infinite re-occurring timers, for instance, a timer getting triggered every `5` seconds, by calling `ngx.timer.at` recursively in the timer callback function. Here is such an example, ```lua @@ -7297,7 +7529,7 @@ ngx.timer.running_count ----------------------- **syntax:** *count = ngx.timer.running_count()* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Returns the number of timers currently running. @@ -7309,7 +7541,7 @@ ngx.timer.pending_count ----------------------- **syntax:** *count = ngx.timer.pending_count()* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Returns the number of pending timers. @@ -7425,7 +7657,7 @@ ngx.worker.count **syntax:** *count = ngx.worker.count()* -**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, init_by_lua** +**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, init_by_lua*, init_worker_by_lua** Returns the total number of the Nginx worker processes (i.e., the value configured by the [worker_processes](http://nginx.org/en/docs/ngx_core_module.html#worker_processes) @@ -7540,7 +7772,7 @@ ndk.set_var.DIRECTIVE --------------------- **syntax:** *res = ndk.set_var.DIRECTIVE_NAME* -**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua** +**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** This mechanism allows calling other nginx C modules' directives that are implemented by [Nginx Devel Kit](https://github.com/simpl/ngx_devel_kit) (NDK)'s set_var submodule's `ndk_set_var_value`. @@ -7581,7 +7813,7 @@ coroutine.create ---------------- **syntax:** *co = coroutine.create(f)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Creates a user Lua coroutines with a Lua function, and returns a coroutine object. @@ -7597,7 +7829,7 @@ coroutine.resume ---------------- **syntax:** *ok, ... = coroutine.resume(co, ...)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Resumes the executation of a user Lua coroutine object previously yielded or just created. @@ -7613,7 +7845,7 @@ coroutine.yield --------------- **syntax:** *... = coroutine.yield(...)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Yields the execution of the current user Lua coroutine. @@ -7629,7 +7861,7 @@ coroutine.wrap -------------- **syntax:** *co = coroutine.wrap(f)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Similar to the standard Lua [coroutine.wrap](http://www.lua.org/manual/5.1/manual.html#pdf-coroutine.wrap) API, but works in the context of the Lua coroutines created by ngx_lua. @@ -7643,7 +7875,7 @@ coroutine.running ----------------- **syntax:** *co = coroutine.running()* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Identical to the standard Lua [coroutine.running](http://www.lua.org/manual/5.1/manual.html#pdf-coroutine.running) API. @@ -7657,7 +7889,7 @@ coroutine.status ---------------- **syntax:** *status = coroutine.status(co)* -**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua** +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** Identical to the standard Lua [coroutine.status](http://www.lua.org/manual/5.1/manual.html#pdf-coroutine.status) API. diff --git a/debian/modules/nginx-lua/config b/debian/modules/nginx-lua/config index c91a07e..0f2749d 100644 --- a/debian/modules/nginx-lua/config +++ b/debian/modules/nginx-lua/config @@ -357,6 +357,9 @@ HTTP_LUA_SRCS=" \ $ngx_addon_dir/src/ngx_http_lua_ssl_ocsp.c \ $ngx_addon_dir/src/ngx_http_lua_lex.c \ $ngx_addon_dir/src/ngx_http_lua_balancer.c \ + $ngx_addon_dir/src/ngx_http_lua_ssl_session_storeby.c \ + $ngx_addon_dir/src/ngx_http_lua_ssl_session_fetchby.c \ + $ngx_addon_dir/src/ngx_http_lua_ssl.c \ " HTTP_LUA_DEPS=" \ @@ -414,6 +417,9 @@ HTTP_LUA_DEPS=" \ $ngx_addon_dir/src/ngx_http_lua_ssl_certby.h \ $ngx_addon_dir/src/ngx_http_lua_lex.h \ $ngx_addon_dir/src/ngx_http_lua_balancer.h \ + $ngx_addon_dir/src/ngx_http_lua_ssl_session_storeby.h \ + $ngx_addon_dir/src/ngx_http_lua_ssl_session_fetchby.h \ + $ngx_addon_dir/src/ngx_http_lua_ssl.h \ " CFLAGS="$CFLAGS -DNDK_SET_VAR" diff --git a/debian/modules/nginx-lua/doc/HttpLuaModule.wiki b/debian/modules/nginx-lua/doc/HttpLuaModule.wiki index 78ce13c..2a5b0d2 100644 --- a/debian/modules/nginx-lua/doc/HttpLuaModule.wiki +++ b/debian/modules/nginx-lua/doc/HttpLuaModule.wiki @@ -10,7 +10,7 @@ Production ready. = Version = -This document describes ngx_lua [https://github.com/openresty/lua-nginx-module/tags v0.10.5] released on 25 May 2016. +This document describes ngx_lua [https://github.com/openresty/lua-nginx-module/tags v0.10.6] released on 15 August 2016. = Synopsis = @@ -186,6 +186,8 @@ The Lua state (Lua VM instance) is shared across all the requests handled by a s The latest version of this module is compatible with the following versions of Nginx: +* 1.11.x (last tested: 1.11.2) +* 1.10.x * 1.9.x (last tested: 1.9.15) * 1.8.x * 1.7.x (last tested: 1.7.10) @@ -207,9 +209,9 @@ Alternatively, ngx_lua can be manually compiled into Nginx: Build the source with this module: - wget 'http://nginx.org/download/nginx-1.9.15.tar.gz' - tar -xzvf nginx-1.9.15.tar.gz - cd nginx-1.9.15/ + wget 'http://nginx.org/download/nginx-1.11.2.tar.gz' + tar -xzvf nginx-1.11.2.tar.gz + cd nginx-1.11.2/ # tell nginx's build system where to find LuaJIT 2.0: export LUAJIT_LIB=/path/to/luajit/lib @@ -1941,7 +1943,7 @@ This directive was first introduced in the v0.10.0 release. Determines whether to force the request body data to be read before running rewrite/access/access_by_lua* or not. The Nginx core does not read the client request body by default and if request body data is required, then this directive should be turned on or the [[#ngx.req.read_body|ngx.req.read_body]] function should be called within the Lua code. -To read the request body data within the [[HttpCoreModule#$request_body|$request_body]] variable, +To read the request body data within the [[HttpCoreModule#$request_body|$request_body]] variable, [[HttpCoreModule#client_body_buffer_size|client_body_buffer_size]] must have the same value as [[HttpCoreModule#client_max_body_size|client_max_body_size]]. Because when the content length exceeds [[HttpCoreModule#client_body_buffer_size|client_body_buffer_size]] but less than [[HttpCoreModule#client_max_body_size|client_max_body_size]], Nginx will buffer the data into a temporary file on the disk, which will lead to empty value in the [[HttpCoreModule#$request_body|$request_body]] variable. If the current location includes [[#rewrite_by_lua|rewrite_by_lua]] or [[#rewrite_by_lua_file|rewrite_by_lua_file]] directives, @@ -2053,6 +2055,111 @@ When a relative path like foo/bar.lua is given, they will be turned This directive was first introduced in the v0.10.0 release. +== ssl_session_fetch_by_lua_block == + +'''syntax:''' ''ssl_session_fetch_by_lua_block { lua-script }'' + +'''context:''' ''server'' + +'''phase:''' ''right-before-SSL-handshake'' + +This directive runs Lua code to look up and load the SSL session (if any) according to the session ID +provided by the current SSL handshake request for the downstream. + +The Lua API for obtaining the current session ID and loading a cached SSL session data +is provided in the [ngx.ssl.session](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ssl/session.md) +Lua module shipped with the [lua-resty-core](https://github.com/openresty/lua-resty-core#readme) +library. + +Lua APIs that may yield, like [[#ngx.sleep|ngx.sleep]] and [[#ngx.socket.tcp|cosockets]], +are enabled in this context. + +This hook, together with the [[#ssl_session_store_by_lua_block|ssl_session_store_by_lua*]] hook, +can be used to implement distributed caching mechanisms in pure Lua (based +on the [[#ngx.socket.tcp|cosocket]] API, for example). If a cached SSL session is found +and loaded into the current SSL connection context, +SSL session resumption can then get immediately initiated and bypass the full SSL handshake process which is very expensive in terms of CPU time. + +Please note that TLS session tickets are very different and it is the clients' responsibility +to cache the SSL session state when session tickets are used. SSL session resumptions based on +TLS session tickets would happen automatically without going through this hook (nor the +[[#ssl_session_store_by_lua*|ssl_session_store_by_lua_block]] hook). This hook is mainly +for older or less capable SSL clients that can only do SSL sessions by session IDs. + +When [[#ssl_certificate_by_lua_block|ssl_certificate_by_lua*]] is specified at the same time, +this hook usually runs before [[#ssl_certificate_by_lua_block|ssl_certificate_by_lua*]]. +When the SSL session is found and successfully loaded for the current SSL connection, +SSL session resumption will happen and thus bypass the [[#ssl_certificate_by_lua_block|ssl_certificate_by_lua*]] +hook completely. In this case, NGINX also bypasses the [[#ssl_session_store_by_lua*|ssl_session_store_by_lua_block]] +hook, for obvious reasons. + +If you are using the [official pre-built packages](http://openresty.org/en/linux-packages.html) for [OpenResty](https://openresty.org/) +1.11.2.1 or later, then everything should work out of the box. + +If you are using OpenSSL libraries not provided by [OpenResty](https://openresty.org), +then you need to apply the following patch for OpenSSL 1.0.2h or later: + +https://github.com/openresty/openresty/blob/master/patches/openssl-1.0.2h-sess_set_get_cb_yield.patch + +If you are not using the NGINX core shipped with [OpenResty](https://openresty.org) 1.11.2.1 or later, then you need to +apply the following patch to the standard NGINX core 1.11.2 or later: + +http://openresty.org/download/nginx-1.11.2-nonblocking_ssl_handshake_hooks.patch + +This directive was first introduced in the v0.10.6 release. + +== ssl_session_fetch_by_lua_file == + +'''syntax:''' ''ssl_session_fetch_by_lua_file '' + +'''context:''' ''server'' + +'''phase:''' ''right-before-SSL-handshake'' + +Equivalent to [[#ssl_session_fetch_by_lua_block|ssl_session_fetch_by_lua_block]], except that the file specified by contains the Lua code, or rather, the [[#Lua/LuaJIT bytecode support|Lua/LuaJIT bytecode]] to be executed. + +When a relative path like foo/bar.lua is given, they will be turned into the absolute path relative to the server prefix path determined by the -p PATH command-line option while starting the Nginx server. + +This directive was first introduced in the v0.10.6 release. + +== ssl_session_store_by_lua_block == + +'''syntax:''' ''ssl_session_store_by_lua_block { lua-script }'' + +'''context:''' ''server'' + +'''phase:''' ''right-after-SSL-handshake'' + +This directive runs Lua code to fetch and save the SSL session (if any) according to the session ID +provided by the current SSL handshake request for the downstream. The saved or cached SSL +session data can be used for future SSL connections to resume SSL sessions without going +through the full SSL handshake process (which is very expensive in terms of CPU time). + +Lua APIs that may yield, like [[#ngx.sleep|ngx.sleep]] and [[#ngx.socket.tcp|cosockets]], +are *disabled* in this context. You can still, however, use the [[#ngx.timer.at|ngx.timer.at]] API +to create 0-delay timers to save the SSL session data asynchronously to external services (like redis or memcached). + +The Lua API for obtaining the current session ID and the associated session state data +is provided in the [ngx.ssl.session](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ssl/session.md#readme) +Lua module shipped with the [lua-resty-core](https://github.com/openresty/lua-resty-core#readme) +library. + +This directive was first introduced in the v0.10.6 release. + +== ssl_session_store_by_lua_file == + +'''syntax:''' ''ssl_session_store_by_lua_file '' + +'''context:''' ''server'' + +'''phase:''' ''right-before-SSL-handshake'' + +Equivalent to [[#ssl_session_store_by_lua_block|ssl_session_store_by_lua_block]], except that the file specified by contains the Lua code, or rather, the [[#Lua/LuaJIT bytecode support|Lua/LuaJIT bytecode]] to be executed. + +When a relative path like foo/bar.lua is given, they will be turned into the absolute path relative to the server prefix path determined by the -p PATH command-line option while starting the Nginx server. + +This directive was first introduced in the v0.10.6 release. + == lua_shared_dict == '''syntax:''' ''lua_shared_dict '' @@ -2499,7 +2606,7 @@ Undefined NGINX variables are evaluated to `nil` while uninitialized (but define This API requires a relatively expensive metamethod call and it is recommended to avoid using it on hot code paths. == Core constants == -'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, *log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, *log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' ngx.OK (0) @@ -2520,7 +2627,7 @@ The ngx.null constant is a NULL light userdata usually The ngx.DECLINED constant was first introduced in the v0.5.0rc19 release. == HTTP method constants == -'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' ngx.HTTP_GET @@ -2543,7 +2650,7 @@ The ngx.DECLINED constant was first introduced in the v0.5.0r These constants are usually used in [[#ngx.location.capture|ngx.location.capture]] and [[#ngx.location.capture_multi|ngx.location.capture_multi]] method calls. == HTTP status constants == -'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' value = ngx.HTTP_CONTINUE (100) (first added in the v0.9.20 release) @@ -2583,7 +2690,7 @@ These constants are usually used in [[#ngx.location.capture|ngx.location.capture == Nginx log level constants == -'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' ngx.STDERR @@ -2602,7 +2709,7 @@ These constants are usually used by the [[#ngx.log|ngx.log]] method. == print == '''syntax:''' ''print(...)'' -'''context:''' ''init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.*, balancer_by_lua*, certificate_by_lua*'' +'''context:''' ''init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Writes argument values into the nginx error.log file with the ngx.NOTICE log level. @@ -3302,6 +3409,8 @@ outputs something like this: This method was first introduced in the v0.7.17 release. +This method does not work in HTTP/2 requests yet. + == ngx.req.get_method == '''syntax:''' ''method_name = ngx.req.get_method()'' @@ -4127,7 +4236,7 @@ Just as [[#ngx.print|ngx.print]] but also emit a trailing newline. == ngx.log == '''syntax:''' ''ngx.log(log_level, ...)'' -'''context:''' ''init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Log arguments concatenated to error.log with the given logging level. @@ -4142,9 +4251,9 @@ There is a hard coded 2048 byte limitation on error message lengths '''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*'' -Flushes response output to the client. +Flushes response output to the client. -ngx.flush accepts an optional boolean wait argument (Default: false) first introduced in the v0.3.1rc34 release. When called with the default argument, it issues an asynchronous call (Returns immediately without waiting for output data to be written into the system send buffer). Calling the function with the wait argument set to true switches to synchronous mode. +ngx.flush accepts an optional boolean wait argument (Default: false) first introduced in the v0.3.1rc34 release. When called with the default argument, it issues an asynchronous call (Returns immediately without waiting for output data to be written into the system send buffer). Calling the function with the wait argument set to true switches to synchronous mode. In synchronous mode, the function will not return until all output data has been written into the system send buffer or until the [[HttpCoreModule#send_timeout|send_timeout]] setting has expired. Note that using the Lua coroutine mechanism means that this function does not block the Nginx event loop even in the synchronous mode. @@ -4157,7 +4266,7 @@ Since v0.8.3 this function returns 1 on success, or re == ngx.exit == '''syntax:''' ''ngx.exit(status)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' When status >= 200 (i.e., ngx.HTTP_OK and above), it will interrupt the execution of the current request and return status code to nginx. @@ -4199,7 +4308,9 @@ Note that while this method accepts all [[#HTTP status constants|HTTP status con Also note that this method call terminates the processing of the current request and that it is recommended that a coding style that combines this method call with the return statement, i.e., return ngx.exit(...) be used to reinforce the fact that the request processing is being terminated. -When being used in the context of [[#header_filter_by_lua|header_filter_by_lua]], ngx.exit() is an asynchronous operation and will return immediately. This behavior may change in future and it is recommended that users always use return in combination as suggested above. +When being used in the contexts of [[#header_filter_by_lua|header_filter_by_lua]] and +[[#ssl_session_store_by_lua_block|ssl_session_store_by_lua*]], ngx.exit() is +an asynchronous operation and will return immediately. This behavior may change in future and it is recommended that users always use return in combination as suggested above. == ngx.eof == '''syntax:''' ''ok, err = ngx.eof()'' @@ -4234,7 +4345,7 @@ Since v0.8.3 this function returns 1 on success, or re == ngx.sleep == '''syntax:''' ''ngx.sleep(seconds)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*'' Sleeps for the specified seconds without blocking. One can specify time resolution up to 0.001 seconds (i.e., one milliseconds). @@ -4247,7 +4358,7 @@ This method was introduced in the 0.5.0rc30 release. == ngx.escape_uri == '''syntax:''' ''newstr = ngx.escape_uri(str)'' -'''context:''' ''init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Escape str as a URI component. @@ -4324,7 +4435,7 @@ This method was first introduced in the v0.3.1rc27 release. == ngx.decode_args == '''syntax:''' ''table = ngx.decode_args(str, max_args?)'' -'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Decodes a URI encoded query-string into a Lua table. This is the inverse function of [[#ngx.encode_args|ngx.encode_args]]. @@ -4343,7 +4454,7 @@ This method was introduced in the v0.5.0rc29. == ngx.encode_base64 == '''syntax:''' ''newstr = ngx.encode_base64(str, no_padding?)'' -'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Encodes str to a base64 digest. @@ -4352,14 +4463,14 @@ Since the 0.9.16 release, an optional boolean-typed no_paddin == ngx.decode_base64 == '''syntax:''' ''newstr = ngx.decode_base64(str)'' -'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Decodes the str argument as a base64 digest to the raw form. Returns nil if str is not well formed. == ngx.crc32_short == '''syntax:''' ''intval = ngx.crc32_short(str)'' -'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Calculates the CRC-32 (Cyclic Redundancy Code) digest for the str argument. @@ -4372,7 +4483,7 @@ This API was first introduced in the v0.3.1rc8 release. == ngx.crc32_long == '''syntax:''' ''intval = ngx.crc32_long(str)'' -'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Calculates the CRC-32 (Cyclic Redundancy Code) digest for the str argument. @@ -4385,7 +4496,7 @@ This API was first introduced in the v0.3.1rc8 release. == ngx.hmac_sha1 == '''syntax:''' ''digest = ngx.hmac_sha1(secret_key, str)'' -'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Computes the [http://en.wikipedia.org/wiki/HMAC HMAC-SHA1] digest of the argument str and turns the result using the secret key . @@ -4413,7 +4524,7 @@ This function was first introduced in the v0.3.1rc29 release. == ngx.md5 == '''syntax:''' ''digest = ngx.md5(str)'' -'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Returns the hexadecimal representation of the MD5 digest of the str argument. @@ -4436,7 +4547,7 @@ See [[#ngx.md5_bin|ngx.md5_bin]] if the raw binary MD5 digest is required. == ngx.md5_bin == '''syntax:''' ''digest = ngx.md5_bin(str)'' -'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Returns the binary form of the MD5 digest of the str argument. @@ -4445,7 +4556,7 @@ See [[#ngx.md5|ngx.md5]] if the hexadecimal form of the MD5 digest is required. == ngx.sha1_bin == '''syntax:''' ''digest = ngx.sha1_bin(str)'' -'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Returns the binary form of the SHA-1 digest of the str argument. @@ -4456,14 +4567,14 @@ This function was first introduced in the v0.5.0rc6. == ngx.quote_sql_str == '''syntax:''' ''quoted_value = ngx.quote_sql_str(raw_value)'' -'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Returns a quoted SQL string literal according to the MySQL quoting rules. == ngx.today == '''syntax:''' ''str = ngx.today()'' -'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Returns current date (in the format yyyy-mm-dd) from the nginx cached time (no syscall involved unlike Lua's date library). @@ -4472,7 +4583,7 @@ This is the local time. == ngx.time == '''syntax:''' ''secs = ngx.time()'' -'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Returns the elapsed seconds from the epoch for the current time stamp from the nginx cached time (no syscall involved unlike Lua's date library). @@ -4481,7 +4592,7 @@ Updates of the Nginx time cache an be forced by calling [[#ngx.update_time|ngx.u == ngx.now == '''syntax:''' ''secs = ngx.now()'' -'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Returns a floating-point number for the elapsed time in seconds (including milliseconds as the decimal part) from the epoch for the current time stamp from the nginx cached time (no syscall involved unlike Lua's date library). @@ -4492,7 +4603,7 @@ This API was first introduced in v0.3.1rc32. == ngx.update_time == '''syntax:''' ''ngx.update_time()'' -'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Forcibly updates the Nginx current time cache. This call involves a syscall and thus has some overhead, so do not abuse it. @@ -4501,7 +4612,7 @@ This API was first introduced in v0.3.1rc32. == ngx.localtime == '''syntax:''' ''str = ngx.localtime()'' -'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Returns the current time stamp (in the format yyyy-mm-dd hh:mm:ss) of the nginx cached time (no syscall involved unlike Lua's [http://www.lua.org/manual/5.1/manual.html#pdf-os.date os.date] function). @@ -4510,7 +4621,7 @@ This is the local time. == ngx.utctime == '''syntax:''' ''str = ngx.utctime()'' -'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Returns the current time stamp (in the format yyyy-mm-dd hh:mm:ss) of the nginx cached time (no syscall involved unlike Lua's [http://www.lua.org/manual/5.1/manual.html#pdf-os.date os.date] function). @@ -4519,7 +4630,7 @@ This is the UTC time. == ngx.cookie_time == '''syntax:''' ''str = ngx.cookie_time(sec)'' -'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Returns a formatted string can be used as the cookie expiration time. The parameter sec is the time stamp in seconds (like those returned from [[#ngx.time|ngx.time]]). @@ -4531,7 +4642,7 @@ Returns a formatted string can be used as the cookie expiration time. The parame == ngx.http_time == '''syntax:''' ''str = ngx.http_time(sec)'' -'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Returns a formated string can be used as the http header time (for example, being used in Last-Modified header). The parameter sec is the time stamp in seconds (like those returned from [[#ngx.time|ngx.time]]). @@ -4543,7 +4654,7 @@ Returns a formated string can be used as the http header time (for example, bein == ngx.parse_http_time == '''syntax:''' ''sec = ngx.parse_http_time(str)'' -'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Parse the http time string (as returned by [[#ngx.http_time|ngx.http_time]]) into seconds. Returns the seconds or nil if the input string is in bad forms. @@ -4564,7 +4675,7 @@ Returns true if the current request is an nginx subrequest, or subject string using the Perl compatible regular expression regex with the optional options. @@ -4711,9 +4822,9 @@ This feature was introduced in the v0.2.1rc11 release. == ngx.re.find == '''syntax:''' ''from, to, err = ngx.re.find(subject, regex, options?, ctx?, nth?)'' -'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' -Similar to [[#ngx.re.match|ngx.re.match]] but only returns the begining index (from) and end index (to) of the matched substring. The returned indexes are 1-based and can be fed directly into the [http://www.lua.org/manual/5.1/manual.html#pdf-string.sub string.sub] API function to obtain the matched substring. +Similar to [[#ngx.re.match|ngx.re.match]] but only returns the beginning index (from) and end index (to) of the matched substring. The returned indexes are 1-based and can be fed directly into the [http://www.lua.org/manual/5.1/manual.html#pdf-string.sub string.sub] API function to obtain the matched substring. In case of errors (like bad regexes or any PCRE runtime errors), this API function returns two nil values followed by a string describing the error. @@ -4760,7 +4871,7 @@ This API function was first introduced in the v0.9.2 release. == ngx.re.gmatch == '''syntax:''' ''iterator, err = ngx.re.gmatch(subject, regex, options?)'' -'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Similar to [[#ngx.re.match|ngx.re.match]], but returns a Lua iterator instead, so as to let the user programmer iterate all the matches over the string argument with the PCRE regex. @@ -4833,7 +4944,7 @@ This feature was first introduced in the v0.2.1rc12 release. == ngx.re.sub == '''syntax:''' ''newstr, n, err = ngx.re.sub(subject, regex, replace, options?)'' -'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Substitutes the first match of the Perl compatible regular expression regex on the subject argument string with the string or function argument replace. The optional options argument has exactly the same meaning as in [[#ngx.re.match|ngx.re.match]]. @@ -4892,7 +5003,7 @@ This feature was first introduced in the v0.2.1rc13 release. == ngx.re.gsub == '''syntax:''' ''newstr, n, err = ngx.re.gsub(subject, regex, replace, options?)'' -'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Just like [[#ngx.re.sub|ngx.re.sub]], but does global substitution. @@ -4927,7 +5038,7 @@ This feature was first introduced in the v0.2.1rc15 release. '''syntax:''' ''dict = ngx.shared[name_var]'' -'''context:''' ''init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Fetching the shm-based Lua dictionary object for the shared memory zone named DICT defined by the [[#lua_shared_dict|lua_shared_dict]] directive. @@ -4944,6 +5055,11 @@ The resulting object dict has the following methods: * [[#ngx.shared.DICT.replace|replace]] * [[#ngx.shared.DICT.delete|delete]] * [[#ngx.shared.DICT.incr|incr]] +* [[#ngx.shared.DICT.lpush|lpush]] +* [[#ngx.shared.DICT.rpush|rpush]] +* [[#ngx.shared.DICT.lpop|lpop]] +* [[#ngx.shared.DICT.rpop|rpop]] +* [[#ngx.shared.DICT.llen|llen]] * [[#ngx.shared.DICT.flush_all|flush_all]] * [[#ngx.shared.DICT.flush_expired|flush_expired]] * [[#ngx.shared.DICT.get_keys|get_keys]] @@ -4995,9 +5111,9 @@ This feature was first introduced in the v0.3.1rc22 release. == ngx.shared.DICT.get == '''syntax:''' ''value, flags = ngx.shared.DICT:get(key)'' -'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' -Retrieving the value in the dictionary [[#ngx.shared.DICT|ngx.shared.DICT]] for the key key. If the key does not exist or has been expired, then nil will be returned. +Retrieving the value in the dictionary [[#ngx.shared.DICT|ngx.shared.DICT]] for the key key. If the key does not exist or has expired, then nil will be returned. In case of errors, nil and a string describing the error will be returned. @@ -5028,7 +5144,7 @@ See also [[#ngx.shared.DICT|ngx.shared.DICT]]. == ngx.shared.DICT.get_stale == '''syntax:''' ''value, flags, stale = ngx.shared.DICT:get_stale(key)'' -'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Similar to the [[#ngx.shared.DICT.get|get]] method but returns the value even if the key has already expired. @@ -5043,7 +5159,7 @@ See also [[#ngx.shared.DICT|ngx.shared.DICT]]. == ngx.shared.DICT.set == '''syntax:''' ''success, err, forcible = ngx.shared.DICT:set(key, value, exptime?, flags?)'' -'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Unconditionally sets a key-value pair into the shm-based dictionary [[#ngx.shared.DICT|ngx.shared.DICT]]. Returns three values: @@ -5086,7 +5202,7 @@ See also [[#ngx.shared.DICT|ngx.shared.DICT]]. == ngx.shared.DICT.safe_set == '''syntax:''' ''ok, err = ngx.shared.DICT:safe_set(key, value, exptime?, flags?)'' -'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Similar to the [[#ngx.shared.DICT.set|set]] method, but never overrides the (least recently used) unexpired items in the store when running out of storage in the shared memory zone. In this case, it will immediately return nil and the string "no memory". @@ -5097,7 +5213,7 @@ See also [[#ngx.shared.DICT|ngx.shared.DICT]]. == ngx.shared.DICT.add == '''syntax:''' ''success, err, forcible = ngx.shared.DICT:add(key, value, exptime?, flags?)'' -'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Just like the [[#ngx.shared.DICT.set|set]] method, but only stores the key-value pair into the dictionary [[#ngx.shared.DICT|ngx.shared.DICT]] if the key does ''not'' exist. @@ -5110,7 +5226,7 @@ See also [[#ngx.shared.DICT|ngx.shared.DICT]]. == ngx.shared.DICT.safe_add == '''syntax:''' ''ok, err = ngx.shared.DICT:safe_add(key, value, exptime?, flags?)'' -'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Similar to the [[#ngx.shared.DICT.add|add]] method, but never overrides the (least recently used) unexpired items in the store when running out of storage in the shared memory zone. In this case, it will immediately return nil and the string "no memory". @@ -5121,7 +5237,7 @@ See also [[#ngx.shared.DICT|ngx.shared.DICT]]. == ngx.shared.DICT.replace == '''syntax:''' ''success, err, forcible = ngx.shared.DICT:replace(key, value, exptime?, flags?)'' -'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Just like the [[#ngx.shared.DICT.set|set]] method, but only stores the key-value pair into the dictionary [[#ngx.shared.DICT|ngx.shared.DICT]] if the key ''does'' exist. @@ -5134,7 +5250,7 @@ See also [[#ngx.shared.DICT|ngx.shared.DICT]]. == ngx.shared.DICT.delete == '''syntax:''' ''ngx.shared.DICT:delete(key)'' -'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Unconditionally removes the key-value pair from the shm-based dictionary [[#ngx.shared.DICT|ngx.shared.DICT]]. @@ -5145,26 +5261,102 @@ This feature was first introduced in the v0.3.1rc22 release. See also [[#ngx.shared.DICT|ngx.shared.DICT]]. == ngx.shared.DICT.incr == -'''syntax:''' ''newval, err = ngx.shared.DICT:incr(key, value)'' +'''syntax:''' ''newval, err, forcible? = ngx.shared.DICT:incr(key, value, init?)'' -'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Increments the (numerical) value for key in the shm-based dictionary [[#ngx.shared.DICT|ngx.shared.DICT]] by the step value value. Returns the new resulting number if the operation is successfully completed or nil and an error message otherwise. -The key must already exist in the dictionary, otherwise it will return nil and "not found". +When the key does not exist or has already expired in the shared dictionary, + +# if the init argument is not specified or takes the value nil, this method will return nil and the error string "not found", or +# if the init argument takes a number value, this method will create a new key with the value init + value. + +Like the [[#ngx.shared.DICT.add|add]] method, it also overrides the (least recently used) unexpired items in the store when running out of storage in the shared memory zone. + +The forcible return value will always be nil when the init argument is not specified. + +If this method succeeds in storing the current item by forcibly removing other not-yet-expired items in the dictionary via LRU, the forcible return value will be true. If it stores the item without forcibly removing other valid items, then the return value forcible will be false. If the original value is not a valid Lua number in the dictionary, it will return nil and "not a number". -The value argument can be any valid Lua numbers, like negative numbers or floating-point numbers. +The value argument and init argument can be any valid Lua numbers, like negative numbers or floating-point numbers. -This feature was first introduced in the v0.3.1rc22 release. +This method was first introduced in the v0.3.1rc22 release. + +The optional `init` parameter was first added in the v0.10.6 release. + +See also [[#ngx.shared.DICT|ngx.shared.DICT]]. + +== ngx.shared.DICT.lpush == +'''syntax:''' ''length, err = ngx.shared.DICT:lpush(key, value)'' + +'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' + +Inserts the specified (numerical or string) value at the head of the list named key in the shm-based dictionary [[#ngx.shared.DICT|ngx.shared.DICT]]. Returns the number of elements in the list after the push operation. + +If key does not exist, it is created as an empty list before performing the push operation. When the key already takes a value that is not a list, it will return nil and "value not a list". + +It never overrides the (least recently used) unexpired items in the store when running out of storage in the shared memory zone. In this case, it will immediately return nil and the string "no memory". + +This feature was first introduced in the v0.10.6 release. + +See also [[#ngx.shared.DICT|ngx.shared.DICT]]. + +== ngx.shared.DICT.rpush == +'''syntax:''' ''length, err = ngx.shared.DICT:rpush(key, value)'' + +'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' + +Similar to the [[#ngx.shared.DICT.lpush|lpush]] method, but inserts the specified (numerical or string) value at the tail of the list named key. + +This feature was first introduced in the v0.10.6 release. + +See also [[#ngx.shared.DICT|ngx.shared.DICT]]. + +== ngx.shared.DICT.lpop == +'''syntax:''' ''val, err = ngx.shared.DICT:lpop(key)'' + +'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' + +Removes and returns the first element of the list named key in the shm-based dictionary [[#ngx.shared.DICT|ngx.shared.DICT]]. + +If key does not exist, it will return nil. When the key already takes a value that is not a list, it will return nil and "value not a list". + +This feature was first introduced in the v0.10.6 release. + +See also [[#ngx.shared.DICT|ngx.shared.DICT]]. + +== ngx.shared.DICT.rpop == +'''syntax:''' ''val, err = ngx.shared.DICT:rpop(key)'' + +'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' + +Removes and returns the last element of the list named key in the shm-based dictionary [[#ngx.shared.DICT|ngx.shared.DICT]]. + +If key does not exist, it will return nil. When the key already takes a value that is not a list, it will return nil and "value not a list". + +This feature was first introduced in the v0.10.6 release. + +See also [[#ngx.shared.DICT|ngx.shared.DICT]]. + +== ngx.shared.DICT.llen == +'''syntax:''' ''len, err = ngx.shared.DICT:llen(key)'' + +'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' + +Returns the number of elements in the list named key in the shm-based dictionary [[#ngx.shared.DICT|ngx.shared.DICT]]. + +If key does not exist, it is interpreted as an empty list and 0 is returned. When the key already takes a value that is not a list, it will return nil and "value not a list". + +This feature was first introduced in the v0.10.6 release. See also [[#ngx.shared.DICT|ngx.shared.DICT]]. == ngx.shared.DICT.flush_all == '''syntax:''' ''ngx.shared.DICT:flush_all()'' -'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Flushes out all the items in the dictionary. This method does not actuall free up all the memory blocks in the dictionary but just marks all the existing items as expired. @@ -5175,7 +5367,7 @@ See also [[#ngx.shared.DICT.flush_expired|ngx.shared.DICT.flush_expired]] and [[ == ngx.shared.DICT.flush_expired == '''syntax:''' ''flushed = ngx.shared.DICT:flush_expired(max_count?)'' -'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Flushes out the expired items in the dictionary, up to the maximal number specified by the optional max_count argument. When the max_count argument is given 0 or not given at all, then it means unlimited. Returns the number of items that have actually been flushed. @@ -5188,7 +5380,7 @@ See also [[#ngx.shared.DICT.flush_all|ngx.shared.DICT.flush_all]] and [[#ngx.sha == ngx.shared.DICT.get_keys == '''syntax:''' ''keys = ngx.shared.DICT:get_keys(max_count?)'' -'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Fetch a list of the keys from the dictionary, up to . @@ -5201,7 +5393,7 @@ This feature was first introduced in the v0.7.3 release. == ngx.socket.udp == '''syntax:''' ''udpsock = ngx.socket.udp()'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*'' Creates and returns a UDP or datagram-oriented unix domain socket object (also known as one type of the "cosocket" objects). The following methods are supported on this object: @@ -5222,7 +5414,7 @@ See also [[#ngx.socket.tcp|ngx.socket.tcp]]. '''syntax:''' ''ok, err = udpsock:setpeername("unix:/path/to/unix-domain.socket")'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*'' Attempts to connect a UDP socket object to a remote server or to a datagram unix domain socket file. Because the datagram protocol is actually connection-less, this method does not really establish a "connection", but only just set the name of the remote peer for subsequent read/write operations. @@ -5275,7 +5467,7 @@ This method was first introduced in the v0.5.7 release. == udpsock:send == '''syntax:''' ''ok, err = udpsock:send(data)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*'' Sends data on the current UDP or datagram unix domain socket object. @@ -5288,7 +5480,7 @@ This feature was first introduced in the v0.5.7 release. == udpsock:receive == '''syntax:''' ''data, err = udpsock:receive(size?)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*'' Receives data from the UDP or datagram unix domain socket object with an optional receive buffer size argument, size. @@ -5319,7 +5511,7 @@ This feature was first introduced in the v0.5.7 release. == udpsock:close == '''syntax:''' ''ok, err = udpsock:close()'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*'' Closes the current UDP or datagram unix domain socket. It returns the 1 in case of success and returns nil with a string describing the error otherwise. @@ -5330,7 +5522,7 @@ This feature was first introduced in the v0.5.7 release. == udpsock:settimeout == '''syntax:''' ''udpsock:settimeout(time)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*'' Set the timeout value in milliseconds for subsequent socket operations (like [[#udpsock:receive|receive]]). @@ -5348,7 +5540,7 @@ This API function was first added to the v0.10.1 release. == ngx.socket.tcp == '''syntax:''' ''tcpsock = ngx.socket.tcp()'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*'' Creates and returns a TCP or stream-oriented unix domain socket object (also known as one type of the "cosocket" objects). The following methods are supported on this object: @@ -5391,7 +5583,7 @@ See also [[#ngx.socket.udp|ngx.socket.udp]]. '''syntax:''' ''ok, err = tcpsock:connect("unix:/path/to/unix-domain.socket", options_table?)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*'' Attempts to connect a TCP socket object to a remote server or to a stream unix domain socket file without blocking. @@ -5463,7 +5655,7 @@ This method was first introduced in the v0.5.0rc1 release. == tcpsock:sslhandshake == '''syntax:''' ''session, err = tcpsock:sslhandshake(reused_session?, server_name?, ssl_verify?, send_status_req?)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*'' Does SSL/TLS handshake on the currently established connection. @@ -5505,7 +5697,7 @@ This method was first introduced in the v0.9.11 release. == tcpsock:send == '''syntax:''' ''bytes, err = tcpsock:send(data)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*'' Sends data without blocking on the current TCP or Unix Domain Socket connection. @@ -5533,7 +5725,7 @@ This feature was first introduced in the v0.5.0rc1 release. '''syntax:''' ''data, err, partial = tcpsock:receive(pattern?)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*'' Receives data from the connected socket according to the reading pattern or size. @@ -5571,7 +5763,7 @@ This feature was first introduced in the v0.5.0rc1 release. == tcpsock:receiveuntil == '''syntax:''' ''iterator = tcpsock:receiveuntil(pattern, options?)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*'' This method returns an iterator Lua function that can be called to read the data stream until it sees the specified pattern or an error occurs. @@ -5663,7 +5855,7 @@ This method was first introduced in the v0.5.0rc1 release. == tcpsock:close == '''syntax:''' ''ok, err = tcpsock:close()'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*'' Closes the current TCP or stream unix domain socket. It returns the 1 in case of success and returns nil with a string describing the error otherwise. @@ -5676,7 +5868,7 @@ This feature was first introduced in the v0.5.0rc1 release. == tcpsock:settimeout == '''syntax:''' ''tcpsock:settimeout(time)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*'' Set the timeout value in milliseconds for subsequent socket operations ([[#tcpsock:connect|connect]], [[#tcpsock:receive|receive]], and iterators returned from [[#tcpsock:receiveuntil|receiveuntil]]). @@ -5689,7 +5881,7 @@ This feature was first introduced in the v0.5.0rc1 release. == tcpsock:setoption == '''syntax:''' ''tcpsock:setoption(option, value?)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*'' This function is added for [http://w3.impa.br/~diego/software/luasocket/tcp.html LuaSocket] API compatibility and does nothing for now. Its functionality will be implemented in future. @@ -5698,7 +5890,7 @@ This feature was first introduced in the v0.5.0rc1 release. == tcpsock:setkeepalive == '''syntax:''' ''ok, err = tcpsock:setkeepalive(timeout?, size?)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*'' Puts the current socket's connection immediately into the cosocket built-in connection pool and keep it alive until other [[#tcpsock:connect|connect]] method calls request it or the associated maximal idle timeout is expired. @@ -5723,7 +5915,7 @@ This feature was first introduced in the v0.5.0rc1 release. == tcpsock:getreusedtimes == '''syntax:''' ''count, err = tcpsock:getreusedtimes()'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*'' This method returns the (successfully) reused times for the current connection. In case of error, it returns nil and a string describing the error. @@ -5756,7 +5948,7 @@ This feature was first introduced in the v0.5.0rc1 release. == ngx.get_phase == '''syntax:''' ''str = ngx.get_phase()'' -'''context:''' ''init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Retrieves the current running phase name. Possible return values are @@ -5766,6 +5958,10 @@ Retrieves the current running phase name. Possible return values are : for the context of [[#init_worker_by_lua|init_worker_by_lua]] or [[#init_worker_by_lua_file|init_worker_by_lua_file]]. * ssl_cert : for the context of [[#ssl_certificate_by_lua_block|ssl_certificate_by_lua_block]] or [[#ssl_certificate_by_lua_file|ssl_certificate_by_lua_file]]. +* ssl_session_fetch +: for the context of [[#ssl_session_fetch_by_lua_block|ssl_session_fetch_by_lua*]]. +* ssl_session_store +: for the context of [[#ssl_session_store_by_lua_block|ssl_session_store_by_lua*]]. * set : for the context of [[#set_by_lua|set_by_lua]] or [[#set_by_lua_file|set_by_lua_file]]. * rewrite @@ -5790,7 +5986,7 @@ This API was first introduced in the v0.5.10 release. == ngx.thread.spawn == '''syntax:''' ''co = ngx.thread.spawn(func, arg1, arg2, ...)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*'' Spawns a new user "light thread" with the Lua function func as well as those optional arguments arg1, arg2, and etc. Returns a Lua thread (or Lua coroutine) object represents this "light thread". @@ -5923,7 +6119,7 @@ This API was first enabled in the v0.7.0 release. == ngx.thread.wait == '''syntax:''' ''ok, res1, res2, ... = ngx.thread.wait(thread1, thread2, ...)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*'' Waits on one or more child "light threads" and returns the results of the first "light thread" that terminates (either successfully or with an error). @@ -6068,7 +6264,7 @@ See also [[#lua_check_client_abort|lua_check_client_abort]]. == ngx.timer.at == '''syntax:''' ''ok, err = ngx.timer.at(delay, callback, user_arg1, user_arg2, ...)'' -'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Creates an Nginx timer with a user callback function as well as optional user arguments. @@ -6125,7 +6321,7 @@ Here is a simple example: } -One can also create infinite re-occuring timers, for instance, a timer getting triggered every 5 seconds, by calling ngx.timer.at recursively in the timer callback function. Here is such an example, +One can also create infinite re-occurring timers, for instance, a timer getting triggered every 5 seconds, by calling ngx.timer.at recursively in the timer callback function. Here is such an example, local delay = 5 @@ -6189,7 +6385,7 @@ This API was first introduced in the v0.8.0 release. == ngx.timer.running_count == '''syntax:''' ''count = ngx.timer.running_count()'' -'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Returns the number of timers currently running. @@ -6198,7 +6394,7 @@ This directive was first introduced in the v0.9.20 release. == ngx.timer.pending_count == '''syntax:''' ''count = ngx.timer.pending_count()'' -'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Returns the number of pending timers. @@ -6287,7 +6483,7 @@ This API was first introduced in the 0.9.5 release. '''syntax:''' ''count = ngx.worker.count()'' -'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, init_by_lua*'' +'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, init_by_lua*, init_worker_by_lua*'' Returns the total number of the Nginx worker processes (i.e., the value configured by the [http://nginx.org/en/docs/ngx_core_module.html#worker_processes worker_processes] @@ -6384,7 +6580,7 @@ This feature requires at least ngx_lua v0.10.0. == ndk.set_var.DIRECTIVE == '''syntax:''' ''res = ndk.set_var.DIRECTIVE_NAME'' -'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' This mechanism allows calling other nginx C modules' directives that are implemented by [https://github.com/simpl/ngx_devel_kit Nginx Devel Kit] (NDK)'s set_var submodule's ndk_set_var_value. @@ -6421,7 +6617,7 @@ This feature requires the [https://github.com/simpl/ngx_devel_kit ngx_devel_kit] == coroutine.create == '''syntax:''' ''co = coroutine.create(f)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Creates a user Lua coroutines with a Lua function, and returns a coroutine object. @@ -6434,7 +6630,7 @@ This API was first introduced in the v0.6.0 release. == coroutine.resume == '''syntax:''' ''ok, ... = coroutine.resume(co, ...)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Resumes the executation of a user Lua coroutine object previously yielded or just created. @@ -6447,7 +6643,7 @@ This API was first introduced in the v0.6.0 release. == coroutine.yield == '''syntax:''' ''... = coroutine.yield(...)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Yields the execution of the current user Lua coroutine. @@ -6460,7 +6656,7 @@ This API was first introduced in the v0.6.0 release. == coroutine.wrap == '''syntax:''' ''co = coroutine.wrap(f)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Similar to the standard Lua [http://www.lua.org/manual/5.1/manual.html#pdf-coroutine.wrap coroutine.wrap] API, but works in the context of the Lua coroutines created by ngx_lua. @@ -6471,7 +6667,7 @@ This API was first introduced in the v0.6.0 release. == coroutine.running == '''syntax:''' ''co = coroutine.running()'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Identical to the standard Lua [http://www.lua.org/manual/5.1/manual.html#pdf-coroutine.running coroutine.running] API. @@ -6482,7 +6678,7 @@ This API was first enabled in the v0.6.0 release. == coroutine.status == '''syntax:''' ''status = coroutine.status(co)'' -'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua*'' +'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' Identical to the standard Lua [http://www.lua.org/manual/5.1/manual.html#pdf-coroutine.status coroutine.status] API. diff --git a/debian/modules/nginx-lua/src/api/ngx_http_lua_api.h b/debian/modules/nginx-lua/src/api/ngx_http_lua_api.h index 4bac0f6..88b41ad 100644 --- a/debian/modules/nginx-lua/src/api/ngx_http_lua_api.h +++ b/debian/modules/nginx-lua/src/api/ngx_http_lua_api.h @@ -19,7 +19,7 @@ /* Public API for other Nginx modules */ -#define ngx_http_lua_version 10005 +#define ngx_http_lua_version 10006 typedef struct { diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_accessby.c b/debian/modules/nginx-lua/src/ngx_http_lua_accessby.c index bd09def..1a4ba6d 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_accessby.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_accessby.c @@ -309,6 +309,10 @@ ngx_http_lua_access_by_chunk(lua_State *L, ngx_http_request_t *r) if (llcf->check_client_abort) { r->read_event_handler = ngx_http_lua_rd_check_broken_connection; +#if (NGX_HTTP_V2) + if (!r->stream) { +#endif + rev = r->connection->read; if (!rev->active) { @@ -317,6 +321,10 @@ ngx_http_lua_access_by_chunk(lua_State *L, ngx_http_request_t *r) } } +#if (NGX_HTTP_V2) + } +#endif + } else { r->read_event_handler = ngx_http_block_reading; } diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_balancer.c b/debian/modules/nginx-lua/src/ngx_http_lua_balancer.c index 5fa289b..0adf787 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_balancer.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_balancer.c @@ -33,6 +33,10 @@ struct ngx_http_lua_balancer_peer_data_s { in_port_t port; int last_peer_state; + +#if !(HAVE_NGX_UPSTREAM_TIMEOUT_FIELDS) + unsigned cloned_upstream_conf; /* :1 */ +#endif }; @@ -128,7 +132,7 @@ ngx_http_lua_balancer_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, dd("enter"); - /* must specifiy a content handler */ + /* must specify a content handler */ if (cmd->post == NULL) { return NGX_CONF_ERROR; } @@ -372,7 +376,7 @@ ngx_http_lua_balancer_by_chunk(lua_State *L, ngx_http_request_t *r) dd("rc == %d", (int) rc); if (rc != 0) { - /* error occured when running loaded code */ + /* error occurred when running loaded code */ err_msg = (u_char *) lua_tolstring(L, -1, &len); if (err_msg == NULL) { @@ -536,6 +540,101 @@ ngx_http_lua_ffi_balancer_set_current_peer(ngx_http_request_t *r, } +int +ngx_http_lua_ffi_balancer_set_timeouts(ngx_http_request_t *r, + long connect_timeout, long send_timeout, long read_timeout, + char **err) +{ + ngx_http_lua_ctx_t *ctx; + ngx_http_upstream_t *u; + +#if !(HAVE_NGX_UPSTREAM_TIMEOUT_FIELDS) + ngx_http_upstream_conf_t *ucf; +#endif + ngx_http_lua_main_conf_t *lmcf; + ngx_http_lua_balancer_peer_data_t *bp; + + if (r == NULL) { + *err = "no request found"; + return NGX_ERROR; + } + + u = r->upstream; + + if (u == NULL) { + *err = "no upstream found"; + return NGX_ERROR; + } + + ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); + if (ctx == NULL) { + *err = "no ctx found"; + return NGX_ERROR; + } + + if ((ctx->context & NGX_HTTP_LUA_CONTEXT_BALANCER) == 0) { + *err = "API disabled in the current context"; + return NGX_ERROR; + } + + lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); + + bp = lmcf->balancer_peer_data; + if (bp == NULL) { + *err = "no upstream peer data found"; + return NGX_ERROR; + } + +#if !(HAVE_NGX_UPSTREAM_TIMEOUT_FIELDS) + if (!bp->cloned_upstream_conf) { + /* we clone the upstream conf for the current request so that + * we do not affect other requests at all. */ + + ucf = ngx_palloc(r->pool, sizeof(ngx_http_upstream_conf_t)); + + if (ucf == NULL) { + *err = "no memory"; + return NGX_ERROR; + } + + ngx_memcpy(ucf, u->conf, sizeof(ngx_http_upstream_conf_t)); + + u->conf = ucf; + bp->cloned_upstream_conf = 1; + + } else { + ucf = u->conf; + } +#endif + + if (connect_timeout > 0) { +#if (HAVE_NGX_UPSTREAM_TIMEOUT_FIELDS) + u->connect_timeout = (ngx_msec_t) connect_timeout; +#else + ucf->connect_timeout = (ngx_msec_t) connect_timeout; +#endif + } + + if (send_timeout > 0) { +#if (HAVE_NGX_UPSTREAM_TIMEOUT_FIELDS) + u->send_timeout = (ngx_msec_t) send_timeout; +#else + ucf->send_timeout = (ngx_msec_t) send_timeout; +#endif + } + + if (read_timeout > 0) { +#if (HAVE_NGX_UPSTREAM_TIMEOUT_FIELDS) + u->read_timeout = (ngx_msec_t) read_timeout; +#else + ucf->read_timeout = (ngx_msec_t) read_timeout; +#endif + } + + return NGX_OK; +} + + int ngx_http_lua_ffi_balancer_set_more_tries(ngx_http_request_t *r, int count, char **err) diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_bodyfilterby.c b/debian/modules/nginx-lua/src/ngx_http_lua_bodyfilterby.c index 86e347e..2b3c38f 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_bodyfilterby.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_bodyfilterby.c @@ -116,7 +116,7 @@ ngx_http_lua_body_filter_by_chunk(lua_State *L, ngx_http_request_t *r, if (rc != 0) { - /* error occured */ + /* error occurred */ err_msg = (u_char *) lua_tolstring(L, -1, &len); if (err_msg == NULL) { diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_cache.c b/debian/modules/nginx-lua/src/ngx_http_lua_cache.c index e8a132e..5ea3069 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_cache.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_cache.c @@ -166,7 +166,7 @@ ngx_http_lua_cache_loadbuffer(ngx_log_t *log, lua_State *L, rc = ngx_http_lua_clfactory_loadbuffer(L, (char *) src, src_len, name); if (rc != 0) { - /* Oops! error occured when loading Lua script */ + /* Oops! error occurred when loading Lua script */ if (rc == LUA_ERRMEM) { err = "memory allocation error"; @@ -252,7 +252,7 @@ ngx_http_lua_cache_loadfile(ngx_log_t *log, lua_State *L, dd("loadfile returns %d (%d)", (int) rc, LUA_ERRFILE); if (rc != 0) { - /* Oops! error occured when loading Lua script */ + /* Oops! error occurred when loading Lua script */ switch (rc) { case LUA_ERRMEM: err = "memory allocation error"; diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_clfactory.c b/debian/modules/nginx-lua/src/ngx_http_lua_clfactory.c index 86885bb..89698c7 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_clfactory.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_clfactory.c @@ -93,14 +93,14 @@ * | Char | Number of upvalues referenced by this function * | [nups] | * --------------------- - * | Char | Number of paramters of this function + * | Char | Number of parameters of this function * | [numparams] | * --------------------- * | Char | Does this function has variable number of arguments? * | [is_var_arg] | main function always set to VARARG_ISVARARG (2) * --------------------- * | Char | Maximum stack size this function used - * | [maxstacksize] | Intially set to 2 + * | [maxstacksize] | Initially set to 2 * --------------------- * | Vector(instr) | Code instructions of this function * | [code] | @@ -177,7 +177,7 @@ * | Char | F(ffi) | V(vararg)| C(has internal funcs) * | [func flag] | * --------------------- - * | Char | Number of paramters of this function + * | Char | Number of parameters of this function * | [numparams] | * --------------------- * | Char | @@ -498,7 +498,7 @@ ngx_http_lua_clfactory_bytecode_prepare(lua_State *L, sizeof(size_t) + sizeof(int) * 2); /* number of upvalues */ *(lf->begin_code.str + POS_NUM_OF_UPVS) = 0; - /* number of paramters */ + /* number of parameters */ *(lf->begin_code.str + POS_NUM_OF_PARA) = 0; /* is var-argument function? */ *(lf->begin_code.str + POS_IS_VAR_ARG) = 2; diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_common.h b/debian/modules/nginx-lua/src/ngx_http_lua_common.h index 758c42a..d5e0dc8 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_common.h +++ b/debian/modules/nginx-lua/src/ngx_http_lua_common.h @@ -42,6 +42,13 @@ #endif +#ifndef NGX_HAVE_SHA1 +# if (nginx_version >= 1011002) +# define NGX_HAVE_SHA1 1 +# endif +#endif + + #ifndef MD5_DIGEST_LENGTH #define MD5_DIGEST_LENGTH 16 #endif @@ -96,17 +103,19 @@ typedef struct { /* must be within 16 bit */ -#define NGX_HTTP_LUA_CONTEXT_SET 0x001 -#define NGX_HTTP_LUA_CONTEXT_REWRITE 0x002 -#define NGX_HTTP_LUA_CONTEXT_ACCESS 0x004 -#define NGX_HTTP_LUA_CONTEXT_CONTENT 0x008 -#define NGX_HTTP_LUA_CONTEXT_LOG 0x010 -#define NGX_HTTP_LUA_CONTEXT_HEADER_FILTER 0x020 -#define NGX_HTTP_LUA_CONTEXT_BODY_FILTER 0x040 -#define NGX_HTTP_LUA_CONTEXT_TIMER 0x080 -#define NGX_HTTP_LUA_CONTEXT_INIT_WORKER 0x100 -#define NGX_HTTP_LUA_CONTEXT_BALANCER 0x200 -#define NGX_HTTP_LUA_CONTEXT_SSL_CERT 0x400 +#define NGX_HTTP_LUA_CONTEXT_SET 0x0001 +#define NGX_HTTP_LUA_CONTEXT_REWRITE 0x0002 +#define NGX_HTTP_LUA_CONTEXT_ACCESS 0x0004 +#define NGX_HTTP_LUA_CONTEXT_CONTENT 0x0008 +#define NGX_HTTP_LUA_CONTEXT_LOG 0x0010 +#define NGX_HTTP_LUA_CONTEXT_HEADER_FILTER 0x0020 +#define NGX_HTTP_LUA_CONTEXT_BODY_FILTER 0x0040 +#define NGX_HTTP_LUA_CONTEXT_TIMER 0x0080 +#define NGX_HTTP_LUA_CONTEXT_INIT_WORKER 0x0100 +#define NGX_HTTP_LUA_CONTEXT_BALANCER 0x0200 +#define NGX_HTTP_LUA_CONTEXT_SSL_CERT 0x0400 +#define NGX_HTTP_LUA_CONTEXT_SSL_SESS_STORE 0x0800 +#define NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH 0x1000 #ifndef NGX_LUA_NO_FFI_API @@ -197,10 +206,18 @@ struct ngx_http_lua_main_conf_s { union ngx_http_lua_srv_conf_u { #if (NGX_HTTP_SSL) struct { - ngx_http_lua_srv_conf_handler_pt cert_handler; - ngx_str_t cert_src; - u_char *cert_src_key; - } ssl; + ngx_http_lua_srv_conf_handler_pt ssl_cert_handler; + ngx_str_t ssl_cert_src; + u_char *ssl_cert_src_key; + + ngx_http_lua_srv_conf_handler_pt ssl_sess_store_handler; + ngx_str_t ssl_sess_store_src; + u_char *ssl_sess_store_src_key; + + ngx_http_lua_srv_conf_handler_pt ssl_sess_fetch_handler; + ngx_str_t ssl_sess_fetch_src; + u_char *ssl_sess_fetch_src_key; + } srv; #endif struct { diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_contentby.c b/debian/modules/nginx-lua/src/ngx_http_lua_contentby.c index 6718885..ecd6c0e 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_contentby.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_contentby.c @@ -97,6 +97,10 @@ ngx_http_lua_content_by_chunk(lua_State *L, ngx_http_request_t *r) if (llcf->check_client_abort) { r->read_event_handler = ngx_http_lua_rd_check_broken_connection; +#if (NGX_HTTP_V2) + if (!r->stream) { +#endif + rev = r->connection->read; if (!rev->active) { @@ -105,6 +109,10 @@ ngx_http_lua_content_by_chunk(lua_State *L, ngx_http_request_t *r) } } +#if (NGX_HTTP_V2) + } +#endif + } else { r->read_event_handler = ngx_http_block_reading; } diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_control.c b/debian/modules/nginx-lua/src/ngx_http_lua_control.c index 4c5f65e..9e78bec 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_control.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_control.c @@ -318,11 +318,16 @@ ngx_http_lua_ngx_exit(lua_State *L) | NGX_HTTP_LUA_CONTEXT_TIMER | NGX_HTTP_LUA_CONTEXT_HEADER_FILTER | NGX_HTTP_LUA_CONTEXT_BALANCER - | NGX_HTTP_LUA_CONTEXT_SSL_CERT); + | NGX_HTTP_LUA_CONTEXT_SSL_CERT + | NGX_HTTP_LUA_CONTEXT_SSL_SESS_STORE + | NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH); rc = (ngx_int_t) luaL_checkinteger(L, 1); - if (ctx->context == NGX_HTTP_LUA_CONTEXT_SSL_CERT) { + if (ctx->context & (NGX_HTTP_LUA_CONTEXT_SSL_CERT + | NGX_HTTP_LUA_CONTEXT_SSL_SESS_STORE + | NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH)) + { #if (NGX_HTTP_SSL) @@ -332,6 +337,10 @@ ngx_http_lua_ngx_exit(lua_State *L) ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua exit with code %i", rc); + if (ctx->context == NGX_HTTP_LUA_CONTEXT_SSL_SESS_STORE) { + return 0; + } + return lua_yield(L, 0); #else @@ -460,14 +469,19 @@ ngx_http_lua_ffi_exit(ngx_http_request_t *r, int status, u_char *err, | NGX_HTTP_LUA_CONTEXT_TIMER | NGX_HTTP_LUA_CONTEXT_HEADER_FILTER | NGX_HTTP_LUA_CONTEXT_BALANCER - | NGX_HTTP_LUA_CONTEXT_SSL_CERT, + | NGX_HTTP_LUA_CONTEXT_SSL_CERT + | NGX_HTTP_LUA_CONTEXT_SSL_SESS_STORE + | NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH, err, errlen) != NGX_OK) { return NGX_ERROR; } - if (ctx->context == NGX_HTTP_LUA_CONTEXT_SSL_CERT) { + if (ctx->context & (NGX_HTTP_LUA_CONTEXT_SSL_CERT + | NGX_HTTP_LUA_CONTEXT_SSL_SESS_STORE + | NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH)) + { #if (NGX_HTTP_SSL) @@ -477,6 +491,10 @@ ngx_http_lua_ffi_exit(ngx_http_request_t *r, int status, u_char *err, ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua exit with code %d", status); + if (ctx->context == NGX_HTTP_LUA_CONTEXT_SSL_SESS_STORE) { + return NGX_DONE; + } + return NGX_OK; #else diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_coroutine.c b/debian/modules/nginx-lua/src/ngx_http_lua_coroutine.c index cb819c6..b790814 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_coroutine.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_coroutine.c @@ -77,7 +77,8 @@ ngx_http_lua_coroutine_create_helper(lua_State *L, ngx_http_request_t *r, | NGX_HTTP_LUA_CONTEXT_ACCESS | NGX_HTTP_LUA_CONTEXT_CONTENT | NGX_HTTP_LUA_CONTEXT_TIMER - | NGX_HTTP_LUA_CONTEXT_SSL_CERT); + | NGX_HTTP_LUA_CONTEXT_SSL_CERT + | NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH); vm = ngx_http_lua_get_lua_vm(r, ctx); @@ -153,7 +154,8 @@ ngx_http_lua_coroutine_resume(lua_State *L) | NGX_HTTP_LUA_CONTEXT_ACCESS | NGX_HTTP_LUA_CONTEXT_CONTENT | NGX_HTTP_LUA_CONTEXT_TIMER - | NGX_HTTP_LUA_CONTEXT_SSL_CERT); + | NGX_HTTP_LUA_CONTEXT_SSL_CERT + | NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH); p_coctx = ctx->cur_co_ctx; if (p_coctx == NULL) { @@ -213,7 +215,8 @@ ngx_http_lua_coroutine_yield(lua_State *L) | NGX_HTTP_LUA_CONTEXT_ACCESS | NGX_HTTP_LUA_CONTEXT_CONTENT | NGX_HTTP_LUA_CONTEXT_TIMER - | NGX_HTTP_LUA_CONTEXT_SSL_CERT); + | NGX_HTTP_LUA_CONTEXT_SSL_CERT + | NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH); coctx = ctx->cur_co_ctx; @@ -362,7 +365,8 @@ ngx_http_lua_coroutine_status(lua_State *L) | NGX_HTTP_LUA_CONTEXT_ACCESS | NGX_HTTP_LUA_CONTEXT_CONTENT | NGX_HTTP_LUA_CONTEXT_TIMER - | NGX_HTTP_LUA_CONTEXT_SSL_CERT); + | NGX_HTTP_LUA_CONTEXT_SSL_CERT + | NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH); coctx = ngx_http_lua_get_co_ctx(co, ctx); if (coctx == NULL) { diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_directive.c b/debian/modules/nginx-lua/src/ngx_http_lua_directive.c index e6bc339..e9313db 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_directive.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_directive.c @@ -459,7 +459,7 @@ ngx_http_lua_rewrite_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return "does not work with " NGINX_VER; #endif - /* must specifiy a content handler */ + /* must specify a content handler */ if (cmd->post == NULL) { return NGX_CONF_ERROR; } @@ -569,7 +569,7 @@ ngx_http_lua_access_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) dd("enter"); - /* must specifiy a content handler */ + /* must specify a content handler */ if (cmd->post == NULL) { return NGX_CONF_ERROR; } @@ -681,7 +681,7 @@ ngx_http_lua_content_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) dd("enter"); - /* must specifiy a content handler */ + /* must specify a content handler */ if (cmd->post == NULL) { return NGX_CONF_ERROR; } @@ -802,7 +802,7 @@ ngx_http_lua_log_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) dd("enter"); - /* must specifiy a content handler */ + /* must specify a content handler */ if (cmd->post == NULL) { return NGX_CONF_ERROR; } @@ -912,7 +912,7 @@ ngx_http_lua_header_filter_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, dd("enter"); - /* must specifiy a content handler */ + /* must specify a content handler */ if (cmd->post == NULL) { return NGX_CONF_ERROR; } @@ -1012,7 +1012,7 @@ ngx_http_lua_body_filter_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, dd("enter"); - /* must specifiy a content handler */ + /* must specify a content handler */ if (cmd->post == NULL) { return NGX_CONF_ERROR; } @@ -1110,7 +1110,7 @@ ngx_http_lua_init_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, dd("enter"); - /* must specifiy a content handler */ + /* must specify a content handler */ if (cmd->post == NULL) { return NGX_CONF_ERROR; } @@ -1177,7 +1177,7 @@ ngx_http_lua_init_worker_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, dd("enter"); - /* must specifiy a content handler */ + /* must specify a content handler */ if (cmd->post == NULL) { return NGX_CONF_ERROR; } diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_headerfilterby.c b/debian/modules/nginx-lua/src/ngx_http_lua_headerfilterby.c index 75ce324..b504530 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_headerfilterby.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_headerfilterby.c @@ -112,7 +112,7 @@ ngx_http_lua_header_filter_by_chunk(lua_State *L, ngx_http_request_t *r) dd("rc == %d", (int) rc); if (rc != 0) { - /* error occured when running loaded code */ + /* error occurred when running loaded code */ err_msg = (u_char *) lua_tolstring(L, -1, &len); if (err_msg == NULL) { diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_headers.c b/debian/modules/nginx-lua/src/ngx_http_lua_headers.c index 45be168..0af56f6 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_headers.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_headers.c @@ -99,6 +99,12 @@ ngx_http_lua_ngx_req_raw_header(lua_State *L) hc = mr->http_connection; c = mr->connection; +#if (NGX_HTTP_V2) + if (mr->stream) { + return luaL_error(L, "http v2 not supported yet"); + } +#endif + #if 1 dd("hc->nbusy: %d", (int) hc->nbusy); diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_headers_in.c b/debian/modules/nginx-lua/src/ngx_http_lua_headers_in.c index 82b4331..b0c28d5 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_headers_in.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_headers_in.c @@ -263,6 +263,11 @@ retry: new_header: + if (r->headers_in.headers.last == NULL) { + /* must be 400 bad request */ + return NGX_OK; + } + h = ngx_list_push(&r->headers_in.headers); if (h == NULL) { diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_logby.c b/debian/modules/nginx-lua/src/ngx_http_lua_logby.c index 0a79acd..49fcd08 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_logby.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_logby.c @@ -198,7 +198,7 @@ ngx_http_lua_log_by_chunk(lua_State *L, ngx_http_request_t *r) #endif if (rc != 0) { - /* error occured when running loaded code */ + /* error occurred when running loaded code */ err_msg = (u_char *) lua_tolstring(L, -1, &len); if (err_msg == NULL) { diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_module.c b/debian/modules/nginx-lua/src/ngx_http_lua_module.c index 867661c..c5e10f9 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_module.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_module.c @@ -26,6 +26,8 @@ #include "ngx_http_lua_semaphore.h" #include "ngx_http_lua_balancer.h" #include "ngx_http_lua_ssl_certby.h" +#include "ngx_http_lua_ssl_session_storeby.h" +#include "ngx_http_lua_ssl_session_fetchby.h" static void *ngx_http_lua_create_main_conf(ngx_conf_t *cf); @@ -525,6 +527,34 @@ static ngx_command_t ngx_http_lua_cmds[] = { 0, (void *) ngx_http_lua_ssl_cert_handler_file }, + { ngx_string("ssl_session_store_by_lua_block"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS, + ngx_http_lua_ssl_sess_store_by_lua_block, + NGX_HTTP_SRV_CONF_OFFSET, + 0, + (void *) ngx_http_lua_ssl_sess_store_handler_inline }, + + { ngx_string("ssl_session_store_by_lua_file"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_http_lua_ssl_sess_store_by_lua, + NGX_HTTP_SRV_CONF_OFFSET, + 0, + (void *) ngx_http_lua_ssl_sess_store_handler_file }, + + { ngx_string("ssl_session_fetch_by_lua_block"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS, + ngx_http_lua_ssl_sess_fetch_by_lua_block, + NGX_HTTP_SRV_CONF_OFFSET, + 0, + (void *) ngx_http_lua_ssl_sess_fetch_handler_inline }, + + { ngx_string("ssl_session_fetch_by_lua_file"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_http_lua_ssl_sess_fetch_by_lua, + NGX_HTTP_SRV_CONF_OFFSET, + 0, + (void *) ngx_http_lua_ssl_sess_fetch_handler_file }, + { ngx_string("lua_ssl_verify_depth"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_num_slot, @@ -681,7 +711,6 @@ ngx_http_lua_init(ngx_conf_t *cf) } #ifndef NGX_LUA_NO_FFI_API - /* add the cleanup of semaphores after the lua_close */ cln = ngx_pool_cleanup_add(cf->pool, 0); if (cln == NULL) { @@ -690,7 +719,6 @@ ngx_http_lua_init(ngx_conf_t *cf) cln->data = lmcf; cln->handler = ngx_http_lua_sema_mm_cleanup; - #endif if (lmcf->lua == NULL) { @@ -761,7 +789,9 @@ ngx_http_lua_lowat_check(ngx_conf_t *cf, void *post, void *data) static void * ngx_http_lua_create_main_conf(ngx_conf_t *cf) { +#ifndef NGX_LUA_NO_FFI_API ngx_int_t rc; +#endif ngx_http_lua_main_conf_t *lmcf; @@ -802,11 +832,14 @@ ngx_http_lua_create_main_conf(ngx_conf_t *cf) lmcf->postponed_to_rewrite_phase_end = NGX_CONF_UNSET; lmcf->postponed_to_access_phase_end = NGX_CONF_UNSET; +#ifndef NGX_LUA_NO_FFI_API rc = ngx_http_lua_sema_mm_init(cf, lmcf); if (rc != NGX_OK) { return NULL; } + dd("nginx Lua module main config structure initialized!"); +#endif return lmcf; } @@ -852,9 +885,18 @@ ngx_http_lua_create_srv_conf(ngx_conf_t *cf) } /* set by ngx_pcalloc: - * lscf->ssl.cert_handler = NULL; - * lscf->ssl.cert_src = { 0, NULL }; - * lscf->ssl.cert_src_key = NULL; + * lscf->srv.ssl_cert_handler = NULL; + * lscf->srv.ssl_cert_src = { 0, NULL }; + * lscf->srv.ssl_cert_src_key = NULL; + * + * lscf->srv.ssl_session_store_handler = NULL; + * lscf->srv.ssl_session_store_src = { 0, NULL }; + * lscf->srv.ssl_session_store_src_key = NULL; + * + * lscf->srv.ssl_session_fetch_handler = NULL; + * lscf->srv.ssl_session_fetch_src = { 0, NULL }; + * lscf->srv.ssl_session_fetch_src_key = NULL; + * * lscf->balancer.handler = NULL; * lscf->balancer.src = { 0, NULL }; * lscf->balancer.src_key = NULL; @@ -875,13 +917,13 @@ ngx_http_lua_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) dd("merge srv conf"); - if (conf->ssl.cert_src.len == 0) { - conf->ssl.cert_src = prev->ssl.cert_src; - conf->ssl.cert_src_key = prev->ssl.cert_src_key; - conf->ssl.cert_handler = prev->ssl.cert_handler; + if (conf->srv.ssl_cert_src.len == 0) { + conf->srv.ssl_cert_src = prev->srv.ssl_cert_src; + conf->srv.ssl_cert_src_key = prev->srv.ssl_cert_src_key; + conf->srv.ssl_cert_handler = prev->srv.ssl_cert_handler; } - if (conf->ssl.cert_src.len) { + if (conf->srv.ssl_cert_src.len) { sscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_ssl_module); if (sscf == NULL || sscf->ssl.ctx == NULL) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, @@ -910,6 +952,56 @@ ngx_http_lua_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) # endif +#endif + } + + if (conf->srv.ssl_sess_store_src.len == 0) { + conf->srv.ssl_sess_store_src = prev->srv.ssl_sess_store_src; + conf->srv.ssl_sess_store_src_key = prev->srv.ssl_sess_store_src_key; + conf->srv.ssl_sess_store_handler = prev->srv.ssl_sess_store_handler; + } + + if (conf->srv.ssl_sess_store_src.len) { + sscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_ssl_module); + if (sscf == NULL || sscf->ssl.ctx == NULL) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "no ssl configured for the server"); + + return NGX_CONF_ERROR; + } + +#ifdef LIBRESSL_VERSION_NUMBER + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "LibreSSL does not support ssl_session_store_by_lua*"); + return NGX_CONF_ERROR; +#else + SSL_CTX_sess_set_new_cb(sscf->ssl.ctx, + ngx_http_lua_ssl_sess_store_handler); +#endif + } + + if (conf->srv.ssl_sess_fetch_src.len == 0) { + conf->srv.ssl_sess_fetch_src = prev->srv.ssl_sess_fetch_src; + conf->srv.ssl_sess_fetch_src_key = prev->srv.ssl_sess_fetch_src_key; + conf->srv.ssl_sess_fetch_handler = prev->srv.ssl_sess_fetch_handler; + } + + if (conf->srv.ssl_sess_fetch_src.len) { + sscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_ssl_module); + if (sscf == NULL || sscf->ssl.ctx == NULL) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "no ssl configured for the server"); + + return NGX_CONF_ERROR; + } + +#ifdef LIBRESSL_VERSION_NUMBER + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "LibreSSL does not support ssl_session_fetch_by_lua*"); + return NGX_CONF_ERROR; +#else + SSL_CTX_sess_set_get_cb(sscf->ssl.ctx, + ngx_http_lua_ssl_sess_fetch_handler); #endif } diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_phase.c b/debian/modules/nginx-lua/src/ngx_http_lua_phase.c index b8e936a..50c5311 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_phase.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_phase.c @@ -84,8 +84,16 @@ ngx_http_lua_ngx_get_phase(lua_State *L) lua_pushliteral(L, "ssl_cert"); break; + case NGX_HTTP_LUA_CONTEXT_SSL_SESS_STORE: + lua_pushliteral(L, "ssl_session_store"); + break; + + case NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH: + lua_pushliteral(L, "ssl_session_fetch"); + break; + default: - return luaL_error(L, "unknown phase: %d", (int) ctx->context); + return luaL_error(L, "unknown phase: %#x", (int) ctx->context); } return 1; diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_rewriteby.c b/debian/modules/nginx-lua/src/ngx_http_lua_rewriteby.c index 2ef59c5..44d8941 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_rewriteby.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_rewriteby.c @@ -304,6 +304,10 @@ ngx_http_lua_rewrite_by_chunk(lua_State *L, ngx_http_request_t *r) if (llcf->check_client_abort) { r->read_event_handler = ngx_http_lua_rd_check_broken_connection; +#if (NGX_HTTP_V2) + if (!r->stream) { +#endif + rev = r->connection->read; if (!rev->active) { @@ -312,6 +316,10 @@ ngx_http_lua_rewrite_by_chunk(lua_State *L, ngx_http_request_t *r) } } +#if (NGX_HTTP_V2) + } +#endif + } else { r->read_event_handler = ngx_http_block_reading; } diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_setby.c b/debian/modules/nginx-lua/src/ngx_http_lua_setby.c index ed9ccc4..2e8762a 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_setby.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_setby.c @@ -88,7 +88,7 @@ ngx_http_lua_set_by_chunk(lua_State *L, ngx_http_request_t *r, ngx_str_t *val, #endif if (rc != 0) { - /* error occured when running loaded code */ + /* error occurred when running loaded code */ err_msg = (u_char *) lua_tolstring(L, -1, &len); if (err_msg == NULL) { diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_shdict.c b/debian/modules/nginx-lua/src/ngx_http_lua_shdict.c index 43f5f9e..ac7f6f1 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_shdict.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_shdict.c @@ -34,6 +34,13 @@ static int ngx_http_lua_shdict_delete(lua_State *L); static int ngx_http_lua_shdict_flush_all(lua_State *L); static int ngx_http_lua_shdict_flush_expired(lua_State *L); static int ngx_http_lua_shdict_get_keys(lua_State *L); +static int ngx_http_lua_shdict_lpush(lua_State *L); +static int ngx_http_lua_shdict_rpush(lua_State *L); +static int ngx_http_lua_shdict_push_helper(lua_State *L, int flags); +static int ngx_http_lua_shdict_lpop(lua_State *L); +static int ngx_http_lua_shdict_rpop(lua_State *L); +static int ngx_http_lua_shdict_pop_helper(lua_State *L, int flags); +static int ngx_http_lua_shdict_llen(lua_State *L); static ngx_inline ngx_shm_zone_t *ngx_http_lua_shdict_get_zone(lua_State *L, @@ -45,11 +52,32 @@ static ngx_inline ngx_shm_zone_t *ngx_http_lua_shdict_get_zone(lua_State *L, #define NGX_HTTP_LUA_SHDICT_SAFE_STORE 0x0004 +#define NGX_HTTP_LUA_SHDICT_LEFT 0x0001 +#define NGX_HTTP_LUA_SHDICT_RIGHT 0x0002 + + enum { SHDICT_USERDATA_INDEX = 1, }; +enum { + SHDICT_TNIL = 0, /* same as LUA_TNIL */ + SHDICT_TBOOLEAN = 1, /* same as LUA_TBOOLEAN */ + SHDICT_TNUMBER = 3, /* same as LUA_TNUMBER */ + SHDICT_TSTRING = 4, /* same as LUA_TSTRING */ + SHDICT_TLIST = 5, +}; + + +static ngx_inline ngx_queue_t * +ngx_http_lua_shdict_get_list_head(ngx_http_lua_shdict_node_t *sd, size_t len) +{ + return (ngx_queue_t *) ngx_align_ptr(((u_char *) &sd->data + len), + NGX_ALIGNMENT); +} + + ngx_int_t ngx_http_lua_shdict_init_zone(ngx_shm_zone_t *shm_zone, void *data) { @@ -90,7 +118,7 @@ ngx_http_lua_shdict_init_zone(ngx_shm_zone_t *shm_zone, void *data) ngx_rbtree_init(&ctx->sh->rbtree, &ctx->sh->sentinel, ngx_http_lua_shdict_rbtree_insert_value); - ngx_queue_init(&ctx->sh->queue); + ngx_queue_init(&ctx->sh->lru_queue); len = sizeof(" in lua_shared_dict zone \"\"") + shm_zone->shm.name.len; @@ -214,7 +242,7 @@ ngx_http_lua_shdict_lookup(ngx_shm_zone_t *shm_zone, ngx_uint_t hash, if (rc == 0) { ngx_queue_remove(&sd->queue); - ngx_queue_insert_head(&ctx->sh->queue, &sd->queue); + ngx_queue_insert_head(&ctx->sh->lru_queue, &sd->queue); *sdp = sd; @@ -249,13 +277,14 @@ ngx_http_lua_shdict_lookup(ngx_shm_zone_t *shm_zone, ngx_uint_t hash, static int ngx_http_lua_shdict_expire(ngx_http_lua_shdict_ctx_t *ctx, ngx_uint_t n) { - ngx_time_t *tp; - uint64_t now; - ngx_queue_t *q; - int64_t ms; - ngx_rbtree_node_t *node; - ngx_http_lua_shdict_node_t *sd; - int freed = 0; + ngx_time_t *tp; + uint64_t now; + ngx_queue_t *q, *list_queue, *lq; + int64_t ms; + ngx_rbtree_node_t *node; + ngx_http_lua_shdict_node_t *sd; + int freed = 0; + ngx_http_lua_shdict_list_node_t *lnode; tp = ngx_timeofday(); @@ -269,11 +298,11 @@ ngx_http_lua_shdict_expire(ngx_http_lua_shdict_ctx_t *ctx, ngx_uint_t n) while (n < 3) { - if (ngx_queue_empty(&ctx->sh->queue)) { + if (ngx_queue_empty(&ctx->sh->lru_queue)) { return freed; } - q = ngx_queue_last(&ctx->sh->queue); + q = ngx_queue_last(&ctx->sh->lru_queue); sd = ngx_queue_data(q, ngx_http_lua_shdict_node_t, queue); @@ -289,6 +318,20 @@ ngx_http_lua_shdict_expire(ngx_http_lua_shdict_ctx_t *ctx, ngx_uint_t n) } } + if (sd->value_type == SHDICT_TLIST) { + list_queue = ngx_http_lua_shdict_get_list_head(sd, sd->key_len); + + for (lq = ngx_queue_head(list_queue); + lq != ngx_queue_sentinel(list_queue); + lq = ngx_queue_next(lq)) + { + lnode = ngx_queue_data(lq, ngx_http_lua_shdict_list_node_t, + queue); + + ngx_slab_free_locked(ctx->shpool, lnode); + } + } + ngx_queue_remove(q); node = (ngx_rbtree_node_t *) @@ -316,7 +359,7 @@ ngx_http_lua_inject_shdict_api(ngx_http_lua_main_conf_t *lmcf, lua_State *L) lua_createtable(L, 0, lmcf->shm_zones->nelts /* nrec */); /* ngx.shared */ - lua_createtable(L, 0 /* narr */, 13 /* nrec */); /* shared mt */ + lua_createtable(L, 0 /* narr */, 18 /* nrec */); /* shared mt */ lua_pushcfunction(L, ngx_http_lua_shdict_get); lua_setfield(L, -2, "get"); @@ -345,6 +388,21 @@ ngx_http_lua_inject_shdict_api(ngx_http_lua_main_conf_t *lmcf, lua_State *L) lua_pushcfunction(L, ngx_http_lua_shdict_delete); lua_setfield(L, -2, "delete"); + lua_pushcfunction(L, ngx_http_lua_shdict_lpush); + lua_setfield(L, -2, "lpush"); + + lua_pushcfunction(L, ngx_http_lua_shdict_rpush); + lua_setfield(L, -2, "rpush"); + + lua_pushcfunction(L, ngx_http_lua_shdict_lpop); + lua_setfield(L, -2, "lpop"); + + lua_pushcfunction(L, ngx_http_lua_shdict_rpop); + lua_setfield(L, -2, "rpop"); + + lua_pushcfunction(L, ngx_http_lua_shdict_llen); + lua_setfield(L, -2, "llen"); + lua_pushcfunction(L, ngx_http_lua_shdict_flush_all); lua_setfield(L, -2, "flush_all"); @@ -503,12 +561,13 @@ ngx_http_lua_shdict_get_helper(lua_State *L, int get_stale) value.len = (size_t) sd->value_len; switch (value_type) { - case LUA_TSTRING: + + case SHDICT_TSTRING: lua_pushlstring(L, (char *) value.data, value.len); break; - case LUA_TNUMBER: + case SHDICT_TNUMBER: if (value.len != sizeof(double)) { @@ -524,7 +583,7 @@ ngx_http_lua_shdict_get_helper(lua_State *L, int get_stale) lua_pushnumber(L, num); break; - case LUA_TBOOLEAN: + case SHDICT_TBOOLEAN: if (value.len != sizeof(u_char)) { @@ -540,6 +599,14 @@ ngx_http_lua_shdict_get_helper(lua_State *L, int get_stale) lua_pushboolean(L, c ? 1 : 0); break; + case SHDICT_TLIST: + + ngx_shmtx_unlock(&ctx->shpool->mutex); + + lua_pushnil(L); + lua_pushliteral(L, "value is a list"); + return 2; + default: ngx_shmtx_unlock(&ctx->shpool->mutex); @@ -621,8 +688,8 @@ ngx_http_lua_shdict_flush_all(lua_State *L) ngx_shmtx_lock(&ctx->shpool->mutex); - for (q = ngx_queue_head(&ctx->sh->queue); - q != ngx_queue_sentinel(&ctx->sh->queue); + for (q = ngx_queue_head(&ctx->sh->lru_queue); + q != ngx_queue_sentinel(&ctx->sh->lru_queue); q = ngx_queue_next(q)) { sd = ngx_queue_data(q, ngx_http_lua_shdict_node_t, queue); @@ -640,16 +707,17 @@ ngx_http_lua_shdict_flush_all(lua_State *L) static int ngx_http_lua_shdict_flush_expired(lua_State *L) { - ngx_queue_t *q, *prev; - ngx_http_lua_shdict_node_t *sd; - ngx_http_lua_shdict_ctx_t *ctx; - ngx_shm_zone_t *zone; - ngx_time_t *tp; - int freed = 0; - int attempts = 0; - ngx_rbtree_node_t *node; - uint64_t now; - int n; + ngx_queue_t *q, *prev, *list_queue, *lq; + ngx_http_lua_shdict_node_t *sd; + ngx_http_lua_shdict_ctx_t *ctx; + ngx_shm_zone_t *zone; + ngx_time_t *tp; + int freed = 0; + int attempts = 0; + ngx_rbtree_node_t *node; + uint64_t now; + int n; + ngx_http_lua_shdict_list_node_t *lnode; n = lua_gettop(L); @@ -672,7 +740,7 @@ ngx_http_lua_shdict_flush_expired(lua_State *L) ngx_shmtx_lock(&ctx->shpool->mutex); - if (ngx_queue_empty(&ctx->sh->queue)) { + if (ngx_queue_empty(&ctx->sh->lru_queue)) { ngx_shmtx_unlock(&ctx->shpool->mutex); lua_pushnumber(L, 0); return 1; @@ -682,14 +750,29 @@ ngx_http_lua_shdict_flush_expired(lua_State *L) now = (uint64_t) tp->sec * 1000 + tp->msec; - q = ngx_queue_last(&ctx->sh->queue); + q = ngx_queue_last(&ctx->sh->lru_queue); - while (q != ngx_queue_sentinel(&ctx->sh->queue)) { + while (q != ngx_queue_sentinel(&ctx->sh->lru_queue)) { prev = ngx_queue_prev(q); sd = ngx_queue_data(q, ngx_http_lua_shdict_node_t, queue); if (sd->expires != 0 && sd->expires <= now) { + + if (sd->value_type == SHDICT_TLIST) { + list_queue = ngx_http_lua_shdict_get_list_head(sd, sd->key_len); + + for (lq = ngx_queue_head(list_queue); + lq != ngx_queue_sentinel(list_queue); + lq = ngx_queue_next(lq)) + { + lnode = ngx_queue_data(lq, ngx_http_lua_shdict_list_node_t, + queue); + + ngx_slab_free_locked(ctx->shpool, lnode); + } + } + ngx_queue_remove(q); node = (ngx_rbtree_node_t *) @@ -753,7 +836,7 @@ ngx_http_lua_shdict_get_keys(lua_State *L) ngx_shmtx_lock(&ctx->shpool->mutex); - if (ngx_queue_empty(&ctx->sh->queue)) { + if (ngx_queue_empty(&ctx->sh->lru_queue)) { ngx_shmtx_unlock(&ctx->shpool->mutex); lua_createtable(L, 0, 0); return 1; @@ -765,9 +848,9 @@ ngx_http_lua_shdict_get_keys(lua_State *L) /* first run through: get total number of elements we need to allocate */ - q = ngx_queue_last(&ctx->sh->queue); + q = ngx_queue_last(&ctx->sh->lru_queue); - while (q != ngx_queue_sentinel(&ctx->sh->queue)) { + while (q != ngx_queue_sentinel(&ctx->sh->lru_queue)) { prev = ngx_queue_prev(q); sd = ngx_queue_data(q, ngx_http_lua_shdict_node_t, queue); @@ -787,9 +870,9 @@ ngx_http_lua_shdict_get_keys(lua_State *L) /* second run through: add keys to table */ total = 0; - q = ngx_queue_last(&ctx->sh->queue); + q = ngx_queue_last(&ctx->sh->lru_queue); - while (q != ngx_queue_sentinel(&ctx->sh->queue)) { + while (q != ngx_queue_sentinel(&ctx->sh->lru_queue)) { prev = ngx_queue_prev(q); sd = ngx_queue_data(q, ngx_http_lua_shdict_node_t, queue); @@ -870,6 +953,7 @@ ngx_http_lua_shdict_set_helper(lua_State *L, int flags) /* indicates whether to foricibly override other * valid entries */ int32_t user_flags = 0; + ngx_queue_t *queue, *q; n = lua_gettop(L); @@ -914,17 +998,18 @@ ngx_http_lua_shdict_set_helper(lua_State *L, int flags) value_type = lua_type(L, 3); switch (value_type) { - case LUA_TSTRING: + + case SHDICT_TSTRING: value.data = (u_char *) lua_tolstring(L, 3, &value.len); break; - case LUA_TNUMBER: + case SHDICT_TNUMBER: value.len = sizeof(double); num = lua_tonumber(L, 3); value.data = (u_char *) # break; - case LUA_TBOOLEAN: + case SHDICT_TBOOLEAN: value.len = sizeof(u_char); c = lua_toboolean(L, 3) ? 1 : 0; value.data = &c; @@ -1015,14 +1100,17 @@ ngx_http_lua_shdict_set_helper(lua_State *L, int flags) replace: - if (value.data && value.len == (size_t) sd->value_len) { + if (value.data + && value.len == (size_t) sd->value_len + && sd->value_type != SHDICT_TLIST) + { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ctx->log, 0, "lua shared dict set: found old entry and value " "size matched, reusing it"); ngx_queue_remove(&sd->queue); - ngx_queue_insert_head(&ctx->sh->queue, &sd->queue); + ngx_queue_insert_head(&ctx->sh->lru_queue, &sd->queue); sd->key_len = (u_short) key.len; @@ -1060,6 +1148,21 @@ replace: remove: + if (sd->value_type == SHDICT_TLIST) { + queue = ngx_http_lua_shdict_get_list_head(sd, key.len); + + for (q = ngx_queue_head(queue); + q != ngx_queue_sentinel(queue); + q = ngx_queue_next(q)) + { + p = (u_char *) ngx_queue_data(q, + ngx_http_lua_shdict_list_node_t, + queue); + + ngx_slab_free_locked(ctx->shpool, p); + } + } + ngx_queue_remove(&sd->queue); node = (ngx_rbtree_node_t *) @@ -1158,7 +1261,7 @@ allocated: ngx_rbtree_insert(&ctx->sh->rbtree, node); - ngx_queue_insert_head(&ctx->sh->queue, &sd->queue); + ngx_queue_insert_head(&ctx->sh->lru_queue, &sd->queue); ngx_shmtx_unlock(&ctx->shpool->mutex); @@ -1172,21 +1275,27 @@ allocated: static int ngx_http_lua_shdict_incr(lua_State *L) { - int n; + int i, n; ngx_str_t key; uint32_t hash; ngx_int_t rc; ngx_http_lua_shdict_ctx_t *ctx; ngx_http_lua_shdict_node_t *sd; double num; + double init = 0; u_char *p; ngx_shm_zone_t *zone; double value; + ngx_rbtree_node_t *node; + /* indicates whether to foricibly override other + * valid entries */ + int forcible = 0; + ngx_queue_t *queue, *q; n = lua_gettop(L); - if (n != 3) { - return luaL_error(L, "expecting 3 arguments, but only seen %d", n); + if (n != 3 && n != 4) { + return luaL_error(L, "expecting 3 or 4 arguments, but only seen %d", n); } if (lua_type(L, 1) != LUA_TTABLE) { @@ -1224,6 +1333,10 @@ ngx_http_lua_shdict_incr(lua_State *L) value = luaL_checknumber(L, 3); + if (n == 4) { + init = luaL_checknumber(L, 4); + } + dd("looking up key %.*s in shared dict %.*s", (int) key.len, key.data, (int) ctx->name.len, ctx->name.data); @@ -1238,16 +1351,47 @@ ngx_http_lua_shdict_incr(lua_State *L) dd("shdict lookup returned %d", (int) rc); if (rc == NGX_DECLINED || rc == NGX_DONE) { - ngx_shmtx_unlock(&ctx->shpool->mutex); - lua_pushnil(L); - lua_pushliteral(L, "not found"); - return 2; + if (n == 3) { + ngx_shmtx_unlock(&ctx->shpool->mutex); + + lua_pushnil(L); + lua_pushliteral(L, "not found"); + return 2; + } + + /* add value */ + num = value + init; + + if (rc == NGX_DONE) { + + /* found an expired item */ + + if ((size_t) sd->value_len == sizeof(double) + && sd->value_type != SHDICT_TLIST) + { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ctx->log, 0, + "lua shared dict incr: found old entry and " + "value size matched, reusing it"); + + ngx_queue_remove(&sd->queue); + ngx_queue_insert_head(&ctx->sh->lru_queue, &sd->queue); + + dd("go to setvalue"); + goto setvalue; + } + + dd("go to remove"); + goto remove; + } + + dd("go to insert"); + goto insert; } /* rc == NGX_OK */ - if (sd->value_type != LUA_TNUMBER || sd->value_len != sizeof(double)) { + if (sd->value_type != SHDICT_TNUMBER || sd->value_len != sizeof(double)) { ngx_shmtx_unlock(&ctx->shpool->mutex); lua_pushnil(L); @@ -1256,7 +1400,7 @@ ngx_http_lua_shdict_incr(lua_State *L) } ngx_queue_remove(&sd->queue); - ngx_queue_insert_head(&ctx->sh->queue, &sd->queue); + ngx_queue_insert_head(&ctx->sh->lru_queue, &sd->queue); dd("setting value type to %d", (int) sd->value_type); @@ -1272,6 +1416,109 @@ ngx_http_lua_shdict_incr(lua_State *L) lua_pushnumber(L, num); lua_pushnil(L); return 2; + +remove: + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ctx->log, 0, + "lua shared dict incr: found old entry but value size " + "NOT matched, removing it first"); + + if (sd->value_type == SHDICT_TLIST) { + queue = ngx_http_lua_shdict_get_list_head(sd, key.len); + + for (q = ngx_queue_head(queue); + q != ngx_queue_sentinel(queue); + q = ngx_queue_next(q)) + { + p = (u_char *) ngx_queue_data(q, + ngx_http_lua_shdict_list_node_t, + queue); + + ngx_slab_free_locked(ctx->shpool, p); + } + } + + ngx_queue_remove(&sd->queue); + + node = (ngx_rbtree_node_t *) + ((u_char *) sd - offsetof(ngx_rbtree_node_t, color)); + + ngx_rbtree_delete(&ctx->sh->rbtree, node); + + ngx_slab_free_locked(ctx->shpool, node); + +insert: + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ctx->log, 0, + "lua shared dict incr: creating a new entry"); + + n = offsetof(ngx_rbtree_node_t, color) + + offsetof(ngx_http_lua_shdict_node_t, data) + + key.len + + sizeof(double); + + node = ngx_slab_alloc_locked(ctx->shpool, n); + + if (node == NULL) { + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0, + "lua shared dict incr: overriding non-expired items " + "due to memory shortage for entry \"%V\"", &key); + + for (i = 0; i < 30; i++) { + if (ngx_http_lua_shdict_expire(ctx, 0) == 0) { + break; + } + + forcible = 1; + + node = ngx_slab_alloc_locked(ctx->shpool, n); + if (node != NULL) { + goto allocated; + } + } + + ngx_shmtx_unlock(&ctx->shpool->mutex); + + lua_pushboolean(L, 0); + lua_pushliteral(L, "no memory"); + lua_pushboolean(L, forcible); + return 3; + } + +allocated: + + sd = (ngx_http_lua_shdict_node_t *) &node->color; + + node->key = hash; + + sd->key_len = (u_short) key.len; + + sd->value_len = (uint32_t) sizeof(double); + + ngx_rbtree_insert(&ctx->sh->rbtree, node); + + ngx_queue_insert_head(&ctx->sh->lru_queue, &sd->queue); + +setvalue: + + sd->user_flags = 0; + + sd->expires = 0; + + dd("setting value type to %d", LUA_TNUMBER); + + sd->value_type = (uint8_t) LUA_TNUMBER; + + p = ngx_copy(sd->data, key.data, key.len); + ngx_memcpy(p, (double *) &num, sizeof(double)); + + ngx_shmtx_unlock(&ctx->shpool->mutex); + + lua_pushnumber(L, num); + lua_pushnil(L); + lua_pushboolean(L, forcible); + return 3; } @@ -1316,7 +1563,8 @@ ngx_http_lua_shared_dict_get(ngx_shm_zone_t *zone, u_char *key_data, len = (size_t) sd->value_len; switch (value->type) { - case LUA_TSTRING: + + case SHDICT_TSTRING: if (value->value.s.data == NULL || value->value.s.len == 0) { ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "no string buffer " @@ -1335,7 +1583,7 @@ ngx_http_lua_shared_dict_get(ngx_shm_zone_t *zone, u_char *key_data, ngx_memcpy(value->value.s.data, data, len); break; - case LUA_TNUMBER: + case SHDICT_TNUMBER: if (len != sizeof(double)) { ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "bad lua number " @@ -1349,7 +1597,7 @@ ngx_http_lua_shared_dict_get(ngx_shm_zone_t *zone, u_char *key_data, ngx_memcpy(&value->value.b, data, len); break; - case LUA_TBOOLEAN: + case SHDICT_TBOOLEAN: if (len != sizeof(u_char)) { ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "bad lua boolean " @@ -1377,6 +1625,574 @@ ngx_http_lua_shared_dict_get(ngx_shm_zone_t *zone, u_char *key_data, } +static int +ngx_http_lua_shdict_lpush(lua_State *L) +{ + return ngx_http_lua_shdict_push_helper(L, NGX_HTTP_LUA_SHDICT_LEFT); +} + + +static int +ngx_http_lua_shdict_rpush(lua_State *L) +{ + return ngx_http_lua_shdict_push_helper(L, NGX_HTTP_LUA_SHDICT_RIGHT); +} + + +static int +ngx_http_lua_shdict_push_helper(lua_State *L, int flags) +{ + int n; + ngx_str_t key; + uint32_t hash; + ngx_int_t rc; + ngx_http_lua_shdict_ctx_t *ctx; + ngx_http_lua_shdict_node_t *sd; + ngx_str_t value; + int value_type; + double num; + ngx_rbtree_node_t *node; + ngx_shm_zone_t *zone; + ngx_queue_t *queue, *q; + ngx_http_lua_shdict_list_node_t *lnode; + + n = lua_gettop(L); + + if (n != 3) { + return luaL_error(L, "expecting 3 arguments, " + "but only seen %d", n); + } + + if (lua_type(L, 1) != LUA_TTABLE) { + return luaL_error(L, "bad \"zone\" argument"); + } + + zone = ngx_http_lua_shdict_get_zone(L, 1); + if (zone == NULL) { + return luaL_error(L, "bad \"zone\" argument"); + } + + ctx = zone->data; + + if (lua_isnil(L, 2)) { + lua_pushnil(L); + lua_pushliteral(L, "nil key"); + return 2; + } + + key.data = (u_char *) luaL_checklstring(L, 2, &key.len); + + if (key.len == 0) { + lua_pushnil(L); + lua_pushliteral(L, "empty key"); + return 2; + } + + if (key.len > 65535) { + lua_pushnil(L); + lua_pushliteral(L, "key too long"); + return 2; + } + + hash = ngx_crc32_short(key.data, key.len); + + value_type = lua_type(L, 3); + + switch (value_type) { + + case SHDICT_TSTRING: + value.data = (u_char *) lua_tolstring(L, 3, &value.len); + break; + + case SHDICT_TNUMBER: + value.len = sizeof(double); + num = lua_tonumber(L, 3); + value.data = (u_char *) # + break; + + default: + lua_pushnil(L); + lua_pushliteral(L, "bad value type"); + return 2; + } + + ngx_shmtx_lock(&ctx->shpool->mutex); + +#if 1 + ngx_http_lua_shdict_expire(ctx, 1); +#endif + + rc = ngx_http_lua_shdict_lookup(zone, hash, key.data, key.len, &sd); + + dd("shdict lookup returned %d", (int) rc); + + /* exists but expired */ + + if (rc == NGX_DONE) { + + if (sd->value_type != SHDICT_TLIST) { + /* TODO: reuse when length matched */ + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ctx->log, 0, + "lua shared dict push: found old entry and value " + "type not matched, remove it first"); + + ngx_queue_remove(&sd->queue); + + node = (ngx_rbtree_node_t *) + ((u_char *) sd - offsetof(ngx_rbtree_node_t, color)); + + ngx_rbtree_delete(&ctx->sh->rbtree, node); + + ngx_slab_free_locked(ctx->shpool, node); + + dd("go to init_list"); + goto init_list; + } + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ctx->log, 0, + "lua shared dict push: found old entry and value " + "type matched, reusing it"); + + sd->expires = 0; + + /* free list nodes */ + + queue = ngx_http_lua_shdict_get_list_head(sd, key.len); + + for (q = ngx_queue_head(queue); + q != ngx_queue_sentinel(queue); + q = ngx_queue_next(q)) + { + /* TODO: reuse matched size list node */ + lnode = ngx_queue_data(q, ngx_http_lua_shdict_list_node_t, queue); + ngx_slab_free_locked(ctx->shpool, lnode); + } + + ngx_queue_init(queue); + + ngx_queue_remove(&sd->queue); + ngx_queue_insert_head(&ctx->sh->lru_queue, &sd->queue); + + dd("go to push_node"); + goto push_node; + } + + /* exists and not expired */ + + if (rc == NGX_OK) { + + if (sd->value_type != SHDICT_TLIST) { + ngx_shmtx_unlock(&ctx->shpool->mutex); + + lua_pushnil(L); + lua_pushliteral(L, "value not a list"); + return 2; + } + + queue = ngx_http_lua_shdict_get_list_head(sd, key.len); + + ngx_queue_remove(&sd->queue); + ngx_queue_insert_head(&ctx->sh->lru_queue, &sd->queue); + + dd("go to push_node"); + goto push_node; + } + + /* rc == NGX_DECLINED, not found */ + +init_list: + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ctx->log, 0, + "lua shared dict list: creating a new entry"); + + /* NOTICE: we assume the begin point aligned in slab, be careful */ + n = offsetof(ngx_rbtree_node_t, color) + + offsetof(ngx_http_lua_shdict_node_t, data) + + key.len + + sizeof(ngx_queue_t); + + dd("length before aligned: %d", n); + + n = (int) (uintptr_t) ngx_align_ptr(n, NGX_ALIGNMENT); + + dd("length after aligned: %d", n); + + node = ngx_slab_alloc_locked(ctx->shpool, n); + + if (node == NULL) { + ngx_shmtx_unlock(&ctx->shpool->mutex); + + lua_pushboolean(L, 0); + lua_pushliteral(L, "no memory"); + return 2; + } + + sd = (ngx_http_lua_shdict_node_t *) &node->color; + + queue = ngx_http_lua_shdict_get_list_head(sd, key.len); + + node->key = hash; + sd->key_len = (u_short) key.len; + + sd->expires = 0; + + sd->value_len = 0; + + dd("setting value type to %d", (int) SHDICT_TLIST); + + sd->value_type = (uint8_t) SHDICT_TLIST; + + ngx_memcpy(sd->data, key.data, key.len); + + ngx_queue_init(queue); + + ngx_rbtree_insert(&ctx->sh->rbtree, node); + + ngx_queue_insert_head(&ctx->sh->lru_queue, &sd->queue); + +push_node: + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ctx->log, 0, + "lua shared dict list: creating a new list node"); + + n = offsetof(ngx_http_lua_shdict_list_node_t, data) + + value.len; + + dd("list node length: %d", n); + + lnode = ngx_slab_alloc_locked(ctx->shpool, n); + + if (lnode == NULL) { + + if (sd->value_len == 0) { + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ctx->log, 0, + "lua shared dict list: no memory for create" + " list node and list empty, remove it"); + + ngx_queue_remove(&sd->queue); + + node = (ngx_rbtree_node_t *) + ((u_char *) sd - offsetof(ngx_rbtree_node_t, color)); + + ngx_rbtree_delete(&ctx->sh->rbtree, node); + + ngx_slab_free_locked(ctx->shpool, node); + } + + ngx_shmtx_unlock(&ctx->shpool->mutex); + + lua_pushboolean(L, 0); + lua_pushliteral(L, "no memory"); + return 2; + } + + dd("setting list length to %d", sd->value_len + 1); + + sd->value_len = sd->value_len + 1; + + dd("setting list node value length to %d", (int) value.len); + + lnode->value_len = (uint32_t) value.len; + + dd("setting list node value type to %d", value_type); + + lnode->value_type = (uint8_t) value_type; + + ngx_memcpy(lnode->data, value.data, value.len); + + if (flags == NGX_HTTP_LUA_SHDICT_LEFT) { + ngx_queue_insert_head(queue, &lnode->queue); + + } else { + ngx_queue_insert_tail(queue, &lnode->queue); + } + + ngx_shmtx_unlock(&ctx->shpool->mutex); + + lua_pushnumber(L, sd->value_len); + return 1; +} + + +static int +ngx_http_lua_shdict_lpop(lua_State *L) +{ + return ngx_http_lua_shdict_pop_helper(L, NGX_HTTP_LUA_SHDICT_LEFT); +} + + +static int +ngx_http_lua_shdict_rpop(lua_State *L) +{ + return ngx_http_lua_shdict_pop_helper(L, NGX_HTTP_LUA_SHDICT_RIGHT); +} + + +static int +ngx_http_lua_shdict_pop_helper(lua_State *L, int flags) +{ + int n; + ngx_str_t name; + ngx_str_t key; + uint32_t hash; + ngx_int_t rc; + ngx_http_lua_shdict_ctx_t *ctx; + ngx_http_lua_shdict_node_t *sd; + ngx_str_t value; + int value_type; + double num; + ngx_rbtree_node_t *node; + ngx_shm_zone_t *zone; + ngx_queue_t *queue; + ngx_http_lua_shdict_list_node_t *lnode; + + n = lua_gettop(L); + + if (n != 2) { + return luaL_error(L, "expecting 2 arguments, " + "but only seen %d", n); + } + + if (lua_type(L, 1) != LUA_TTABLE) { + return luaL_error(L, "bad \"zone\" argument"); + } + + zone = ngx_http_lua_shdict_get_zone(L, 1); + if (zone == NULL) { + return luaL_error(L, "bad \"zone\" argument"); + } + + ctx = zone->data; + name = ctx->name; + + if (lua_isnil(L, 2)) { + lua_pushnil(L); + lua_pushliteral(L, "nil key"); + return 2; + } + + key.data = (u_char *) luaL_checklstring(L, 2, &key.len); + + if (key.len == 0) { + lua_pushnil(L); + lua_pushliteral(L, "empty key"); + return 2; + } + + if (key.len > 65535) { + lua_pushnil(L); + lua_pushliteral(L, "key too long"); + return 2; + } + + hash = ngx_crc32_short(key.data, key.len); + + ngx_shmtx_lock(&ctx->shpool->mutex); + +#if 1 + ngx_http_lua_shdict_expire(ctx, 1); +#endif + + rc = ngx_http_lua_shdict_lookup(zone, hash, key.data, key.len, &sd); + + dd("shdict lookup returned %d", (int) rc); + + if (rc == NGX_DECLINED || rc == NGX_DONE) { + ngx_shmtx_unlock(&ctx->shpool->mutex); + lua_pushnil(L); + return 1; + } + + /* rc == NGX_OK */ + + if (sd->value_type != SHDICT_TLIST) { + ngx_shmtx_unlock(&ctx->shpool->mutex); + + lua_pushnil(L); + lua_pushliteral(L, "value not a list"); + return 2; + } + + if (sd->value_len <= 0) { + ngx_shmtx_unlock(&ctx->shpool->mutex); + + return luaL_error(L, "bad lua list length found for key %s " + "in shared_dict %s: %lu", key.data, name.data, + (unsigned long) sd->value_len); + } + + queue = ngx_http_lua_shdict_get_list_head(sd, key.len); + + if (flags == NGX_HTTP_LUA_SHDICT_LEFT) { + queue = ngx_queue_head(queue); + + } else { + queue = ngx_queue_last(queue); + } + + lnode = ngx_queue_data(queue, ngx_http_lua_shdict_list_node_t, queue); + + value_type = lnode->value_type; + + dd("data: %p", lnode->data); + dd("value len: %d", (int) sd->value_len); + + value.data = lnode->data; + value.len = (size_t) lnode->value_len; + + switch (value_type) { + + case SHDICT_TSTRING: + + lua_pushlstring(L, (char *) value.data, value.len); + break; + + case SHDICT_TNUMBER: + + if (value.len != sizeof(double)) { + + ngx_shmtx_unlock(&ctx->shpool->mutex); + + return luaL_error(L, "bad lua list node number value size found " + "for key %s in shared_dict %s: %lu", key.data, + name.data, (unsigned long) value.len); + } + + ngx_memcpy(&num, value.data, sizeof(double)); + + lua_pushnumber(L, num); + break; + + default: + + ngx_shmtx_unlock(&ctx->shpool->mutex); + + return luaL_error(L, "bad list node value type found for key %s in " + "shared_dict %s: %d", key.data, name.data, + value_type); + } + + ngx_queue_remove(queue); + + ngx_slab_free_locked(ctx->shpool, lnode); + + if (sd->value_len == 1) { + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ctx->log, 0, + "lua shared dict list: empty node after pop, " + "remove it"); + + ngx_queue_remove(&sd->queue); + + node = (ngx_rbtree_node_t *) + ((u_char *) sd - offsetof(ngx_rbtree_node_t, color)); + + ngx_rbtree_delete(&ctx->sh->rbtree, node); + + ngx_slab_free_locked(ctx->shpool, node); + + } else { + sd->value_len = sd->value_len - 1; + + ngx_queue_remove(&sd->queue); + ngx_queue_insert_head(&ctx->sh->lru_queue, &sd->queue); + } + + ngx_shmtx_unlock(&ctx->shpool->mutex); + + return 1; +} + + +static int +ngx_http_lua_shdict_llen(lua_State *L) +{ + int n; + ngx_str_t key; + uint32_t hash; + ngx_int_t rc; + ngx_http_lua_shdict_ctx_t *ctx; + ngx_http_lua_shdict_node_t *sd; + ngx_shm_zone_t *zone; + + n = lua_gettop(L); + + if (n != 2) { + return luaL_error(L, "expecting 2 arguments, " + "but only seen %d", n); + } + + if (lua_type(L, 1) != LUA_TTABLE) { + return luaL_error(L, "bad \"zone\" argument"); + } + + zone = ngx_http_lua_shdict_get_zone(L, 1); + if (zone == NULL) { + return luaL_error(L, "bad \"zone\" argument"); + } + + ctx = zone->data; + + if (lua_isnil(L, 2)) { + lua_pushnil(L); + lua_pushliteral(L, "nil key"); + return 2; + } + + key.data = (u_char *) luaL_checklstring(L, 2, &key.len); + + if (key.len == 0) { + lua_pushnil(L); + lua_pushliteral(L, "empty key"); + return 2; + } + + if (key.len > 65535) { + lua_pushnil(L); + lua_pushliteral(L, "key too long"); + return 2; + } + + hash = ngx_crc32_short(key.data, key.len); + + ngx_shmtx_lock(&ctx->shpool->mutex); + +#if 1 + ngx_http_lua_shdict_expire(ctx, 1); +#endif + + rc = ngx_http_lua_shdict_lookup(zone, hash, key.data, key.len, &sd); + + dd("shdict lookup returned %d", (int) rc); + + if (rc == NGX_OK) { + + if (sd->value_type != SHDICT_TLIST) { + ngx_shmtx_unlock(&ctx->shpool->mutex); + + lua_pushnil(L); + lua_pushliteral(L, "value not a list"); + return 2; + } + + ngx_queue_remove(&sd->queue); + ngx_queue_insert_head(&ctx->sh->lru_queue, &sd->queue); + + ngx_shmtx_unlock(&ctx->shpool->mutex); + + lua_pushnumber(L, (lua_Number) sd->value_len); + return 1; + } + + ngx_shmtx_unlock(&ctx->shpool->mutex); + + lua_pushnumber(L, 0); + return 1; +} + + ngx_shm_zone_t * ngx_http_lua_find_zone(u_char *name_data, size_t name_len) { @@ -1428,6 +2244,7 @@ ngx_http_lua_ffi_shdict_store(ngx_shm_zone_t *zone, int op, u_char *key, uint32_t hash; ngx_int_t rc; ngx_time_t *tp; + ngx_queue_t *queue, *q; ngx_rbtree_node_t *node; ngx_http_lua_shdict_ctx_t *ctx; ngx_http_lua_shdict_node_t *sd; @@ -1445,17 +2262,18 @@ ngx_http_lua_ffi_shdict_store(ngx_shm_zone_t *zone, int op, u_char *key, hash = ngx_crc32_short(key, key_len); switch (value_type) { - case LUA_TSTRING: + + case SHDICT_TSTRING: /* do nothing */ break; - case LUA_TNUMBER: + case SHDICT_TNUMBER: dd("num value: %lf", num_value); str_value_buf = (u_char *) &num_value; str_value_len = sizeof(double); break; - case LUA_TBOOLEAN: + case SHDICT_TBOOLEAN: c = num_value ? 1 : 0; str_value_buf = &c; str_value_len = sizeof(u_char); @@ -1493,6 +2311,7 @@ ngx_http_lua_ffi_shdict_store(ngx_shm_zone_t *zone, int op, u_char *key, *errmsg = "not found"; return NGX_DECLINED; } + /* rc == NGX_OK */ goto replace; @@ -1527,14 +2346,17 @@ ngx_http_lua_ffi_shdict_store(ngx_shm_zone_t *zone, int op, u_char *key, replace: - if (str_value_buf && str_value_len == (size_t) sd->value_len) { + if (str_value_buf + && str_value_len == (size_t) sd->value_len + && sd->value_type != SHDICT_TLIST) + { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ctx->log, 0, "lua shared dict set: found old entry and value " "size matched, reusing it"); ngx_queue_remove(&sd->queue); - ngx_queue_insert_head(&ctx->sh->queue, &sd->queue); + ngx_queue_insert_head(&ctx->sh->lru_queue, &sd->queue); sd->key_len = (u_short) key_len; @@ -1569,6 +2391,21 @@ replace: remove: + if (sd->value_type == SHDICT_TLIST) { + queue = ngx_http_lua_shdict_get_list_head(sd, key_len); + + for (q = ngx_queue_head(queue); + q != ngx_queue_sentinel(queue); + q = ngx_queue_next(q)) + { + p = (u_char *) ngx_queue_data(q, + ngx_http_lua_shdict_list_node_t, + queue); + + ngx_slab_free_locked(ctx->shpool, p); + } + } + ngx_queue_remove(&sd->queue); node = (ngx_rbtree_node_t *) @@ -1657,7 +2494,7 @@ allocated: ngx_memcpy(p, str_value_buf, str_value_len); ngx_rbtree_insert(&ctx->sh->rbtree, node); - ngx_queue_insert_head(&ctx->sh->queue, &sd->queue); + ngx_queue_insert_head(&ctx->sh->lru_queue, &sd->queue); ngx_shmtx_unlock(&ctx->shpool->mutex); return NGX_OK; @@ -1668,7 +2505,7 @@ int ngx_http_lua_ffi_shdict_get(ngx_shm_zone_t *zone, u_char *key, size_t key_len, int *value_type, u_char **str_value_buf, size_t *str_value_len, double *num_value, int *user_flags, - int get_stale, int *is_stale) + int get_stale, int *is_stale, char **err) { ngx_str_t name; uint32_t hash; @@ -1681,6 +2518,8 @@ ngx_http_lua_ffi_shdict_get(ngx_shm_zone_t *zone, u_char *key, return NGX_ERROR; } + *err = NULL; + ctx = zone->data; name = ctx->name; @@ -1721,12 +2560,12 @@ ngx_http_lua_ffi_shdict_get(ngx_shm_zone_t *zone, u_char *key, value.len = (size_t) sd->value_len; if (*str_value_len < (size_t) value.len) { - if (*value_type == LUA_TBOOLEAN) { + if (*value_type == SHDICT_TBOOLEAN) { ngx_shmtx_unlock(&ctx->shpool->mutex); return NGX_ERROR; } - if (*value_type == LUA_TSTRING) { + if (*value_type == SHDICT_TSTRING) { *str_value_buf = malloc(value.len); if (*str_value_buf == NULL) { ngx_shmtx_unlock(&ctx->shpool->mutex); @@ -1736,12 +2575,13 @@ ngx_http_lua_ffi_shdict_get(ngx_shm_zone_t *zone, u_char *key, } switch (*value_type) { - case LUA_TSTRING: + + case SHDICT_TSTRING: *str_value_len = value.len; ngx_memcpy(*str_value_buf, value.data, value.len); break; - case LUA_TNUMBER: + case SHDICT_TNUMBER: if (value.len != sizeof(double)) { ngx_shmtx_unlock(&ctx->shpool->mutex); @@ -1756,7 +2596,7 @@ ngx_http_lua_ffi_shdict_get(ngx_shm_zone_t *zone, u_char *key, ngx_memcpy(num_value, value.data, sizeof(double)); break; - case LUA_TBOOLEAN: + case SHDICT_TBOOLEAN: if (value.len != sizeof(u_char)) { ngx_shmtx_unlock(&ctx->shpool->mutex); @@ -1770,6 +2610,13 @@ ngx_http_lua_ffi_shdict_get(ngx_shm_zone_t *zone, u_char *key, ngx_memcpy(*str_value_buf, value.data, value.len); break; + case SHDICT_TLIST: + + ngx_shmtx_unlock(&ctx->shpool->mutex); + + *err = "value is a list"; + return NGX_ERROR; + default: ngx_shmtx_unlock(&ctx->shpool->mutex); @@ -1799,16 +2646,27 @@ ngx_http_lua_ffi_shdict_get(ngx_shm_zone_t *zone, u_char *key, int ngx_http_lua_ffi_shdict_incr(ngx_shm_zone_t *zone, u_char *key, - size_t key_len, double *value, char **err) + size_t key_len, double *value, char **err, int has_init, double init, + int *forcible) { + int i, n; uint32_t hash; ngx_int_t rc; ngx_http_lua_shdict_ctx_t *ctx; ngx_http_lua_shdict_node_t *sd; double num; + ngx_rbtree_node_t *node; u_char *p; + ngx_queue_t *queue, *q; + + if (zone == NULL) { + return NGX_ERROR; + } ctx = zone->data; + + *forcible = 0; + hash = ngx_crc32_short(key, key_len); dd("looking up key %.*s in shared dict %.*s", (int) key_len, key, @@ -1823,21 +2681,51 @@ ngx_http_lua_ffi_shdict_incr(ngx_shm_zone_t *zone, u_char *key, dd("shdict lookup returned %d", (int) rc); if (rc == NGX_DECLINED || rc == NGX_DONE) { - ngx_shmtx_unlock(&ctx->shpool->mutex); - *err = "not found"; - return NGX_ERROR; + if (!has_init) { + ngx_shmtx_unlock(&ctx->shpool->mutex); + *err = "not found"; + return NGX_ERROR; + } + + /* add value */ + num = *value + init; + + if (rc == NGX_DONE) { + + /* found an expired item */ + + if ((size_t) sd->value_len == sizeof(double) + && sd->value_type != SHDICT_TLIST) + { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ctx->log, 0, + "lua shared dict incr: found old entry and " + "value size matched, reusing it"); + + ngx_queue_remove(&sd->queue); + ngx_queue_insert_head(&ctx->sh->lru_queue, &sd->queue); + + dd("go to setvalue"); + goto setvalue; + } + + dd("go to remove"); + goto remove; + } + + dd("go to insert"); + goto insert; } /* rc == NGX_OK */ - if (sd->value_type != LUA_TNUMBER || sd->value_len != sizeof(double)) { + if (sd->value_type != SHDICT_TNUMBER || sd->value_len != sizeof(double)) { ngx_shmtx_unlock(&ctx->shpool->mutex); *err = "not a number"; return NGX_ERROR; } ngx_queue_remove(&sd->queue); - ngx_queue_insert_head(&ctx->sh->queue, &sd->queue); + ngx_queue_insert_head(&ctx->sh->lru_queue, &sd->queue); dd("setting value type to %d", (int) sd->value_type); @@ -1850,6 +2738,105 @@ ngx_http_lua_ffi_shdict_incr(ngx_shm_zone_t *zone, u_char *key, ngx_shmtx_unlock(&ctx->shpool->mutex); + *value = num; + return NGX_OK; + +remove: + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ctx->log, 0, + "lua shared dict incr: found old entry but value size " + "NOT matched, removing it first"); + + if (sd->value_type == SHDICT_TLIST) { + queue = ngx_http_lua_shdict_get_list_head(sd, key_len); + + for (q = ngx_queue_head(queue); + q != ngx_queue_sentinel(queue); + q = ngx_queue_next(q)) + { + p = (u_char *) ngx_queue_data(q, ngx_http_lua_shdict_list_node_t, + queue); + + ngx_slab_free_locked(ctx->shpool, p); + } + } + + ngx_queue_remove(&sd->queue); + + node = (ngx_rbtree_node_t *) + ((u_char *) sd - offsetof(ngx_rbtree_node_t, color)); + + ngx_rbtree_delete(&ctx->sh->rbtree, node); + + ngx_slab_free_locked(ctx->shpool, node); + +insert: + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ctx->log, 0, + "lua shared dict incr: creating a new entry"); + + n = offsetof(ngx_rbtree_node_t, color) + + offsetof(ngx_http_lua_shdict_node_t, data) + + key_len + + sizeof(double); + + node = ngx_slab_alloc_locked(ctx->shpool, n); + + if (node == NULL) { + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, ctx->log, 0, + "lua shared dict incr: overriding non-expired items " + "due to memory shortage for entry \"%*s\"", key_len, + key); + + for (i = 0; i < 30; i++) { + if (ngx_http_lua_shdict_expire(ctx, 0) == 0) { + break; + } + + *forcible = 1; + + node = ngx_slab_alloc_locked(ctx->shpool, n); + if (node != NULL) { + goto allocated; + } + } + + ngx_shmtx_unlock(&ctx->shpool->mutex); + + *err = "no memory"; + return NGX_ERROR; + } + +allocated: + + sd = (ngx_http_lua_shdict_node_t *) &node->color; + + node->key = hash; + + sd->key_len = (u_short) key_len; + + sd->value_len = (uint32_t) sizeof(double); + + ngx_rbtree_insert(&ctx->sh->rbtree, node); + + ngx_queue_insert_head(&ctx->sh->lru_queue, &sd->queue); + +setvalue: + + sd->user_flags = 0; + + sd->expires = 0; + + dd("setting value type to %d", LUA_TNUMBER); + + sd->value_type = (uint8_t) LUA_TNUMBER; + + p = ngx_copy(sd->data, key, key_len); + ngx_memcpy(p, (double *) &num, sizeof(double)); + + ngx_shmtx_unlock(&ctx->shpool->mutex); + *value = num; return NGX_OK; } @@ -1866,8 +2853,8 @@ ngx_http_lua_ffi_shdict_flush_all(ngx_shm_zone_t *zone) ngx_shmtx_lock(&ctx->shpool->mutex); - for (q = ngx_queue_head(&ctx->sh->queue); - q != ngx_queue_sentinel(&ctx->sh->queue); + for (q = ngx_queue_head(&ctx->sh->lru_queue); + q != ngx_queue_sentinel(&ctx->sh->lru_queue); q = ngx_queue_next(q)) { sd = ngx_queue_data(q, ngx_http_lua_shdict_node_t, queue); diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_shdict.h b/debian/modules/nginx-lua/src/ngx_http_lua_shdict.h index aa1bb58..5c4ff36 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_shdict.h +++ b/debian/modules/nginx-lua/src/ngx_http_lua_shdict.h @@ -24,10 +24,18 @@ typedef struct { } ngx_http_lua_shdict_node_t; +typedef struct { + ngx_queue_t queue; + uint32_t value_len; + uint8_t value_type; + u_char data[1]; +} ngx_http_lua_shdict_list_node_t; + + typedef struct { ngx_rbtree_t rbtree; ngx_rbtree_node_t sentinel; - ngx_queue_t queue; + ngx_queue_t lru_queue; } ngx_http_lua_shdict_shctx_t; diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_sleep.c b/debian/modules/nginx-lua/src/ngx_http_lua_sleep.c index a887c3a..4c0d016 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_sleep.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_sleep.c @@ -56,7 +56,8 @@ ngx_http_lua_ngx_sleep(lua_State *L) | NGX_HTTP_LUA_CONTEXT_ACCESS | NGX_HTTP_LUA_CONTEXT_CONTENT | NGX_HTTP_LUA_CONTEXT_TIMER - | NGX_HTTP_LUA_CONTEXT_SSL_CERT); + | NGX_HTTP_LUA_CONTEXT_SSL_CERT + | NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH); coctx = ctx->cur_co_ctx; if (coctx == NULL) { diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_socket_tcp.c b/debian/modules/nginx-lua/src/ngx_http_lua_socket_tcp.c index 2bfdbd3..fe6001f 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_socket_tcp.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_socket_tcp.c @@ -386,7 +386,8 @@ ngx_http_lua_socket_tcp(lua_State *L) | NGX_HTTP_LUA_CONTEXT_ACCESS | NGX_HTTP_LUA_CONTEXT_CONTENT | NGX_HTTP_LUA_CONTEXT_TIMER - | NGX_HTTP_LUA_CONTEXT_SSL_CERT); + | NGX_HTTP_LUA_CONTEXT_SSL_CERT + | NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH); lua_createtable(L, 3 /* narr */, 1 /* nrec */); lua_pushlightuserdata(L, &ngx_http_lua_tcp_socket_metatable_key); @@ -444,7 +445,8 @@ ngx_http_lua_socket_tcp_connect(lua_State *L) | NGX_HTTP_LUA_CONTEXT_ACCESS | NGX_HTTP_LUA_CONTEXT_CONTENT | NGX_HTTP_LUA_CONTEXT_TIMER - | NGX_HTTP_LUA_CONTEXT_SSL_CERT); + | NGX_HTTP_LUA_CONTEXT_SSL_CERT + | NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH); luaL_checktype(L, 1, LUA_TTABLE); @@ -4486,7 +4488,7 @@ ngx_http_lua_socket_tcp_setkeepalive(lua_State *L) if (spool == NULL) { /* create a new socket pool for the current peer key */ - if (n == 3) { + if (n >= 3 && !lua_isnil(L, 3)) { pool_size = luaL_checkinteger(L, 3); } else { @@ -4589,7 +4591,7 @@ ngx_http_lua_socket_tcp_setkeepalive(lua_State *L) ngx_del_timer(c->write); } - if (n >= 2) { + if (n >= 2 && !lua_isnil(L, 2)) { timeout = (ngx_msec_t) luaL_checkinteger(L, 2); } else { @@ -4902,7 +4904,7 @@ ngx_http_lua_socket_downstream_destroy(lua_State *L) { ngx_http_lua_socket_tcp_upstream_t *u; - dd("downstream destory"); + dd("downstream destroy"); u = lua_touserdata(L, 1); if (u == NULL) { diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_ssl.c b/debian/modules/nginx-lua/src/ngx_http_lua_ssl.c new file mode 100644 index 0000000..8ed7b95 --- /dev/null +++ b/debian/modules/nginx-lua/src/ngx_http_lua_ssl.c @@ -0,0 +1,37 @@ + +/* + * Copyright (C) Yichun Zhang (agentzh) + */ + + +#ifndef DDEBUG +#define DDEBUG 0 +#endif +#include "ddebug.h" + + +#if (NGX_HTTP_SSL) + + +int ngx_http_lua_ssl_ctx_index = -1; + + +ngx_int_t +ngx_http_lua_ssl_init(ngx_log_t *log) +{ + if (ngx_http_lua_ssl_ctx_index == -1) { + ngx_http_lua_ssl_ctx_index = SSL_get_ex_new_index(0, NULL, NULL, + NULL, NULL); + + if (ngx_http_lua_ssl_ctx_index == -1) { + ngx_ssl_error(NGX_LOG_ALERT, log, 0, + "lua: SSL_get_ex_new_index() for ctx failed"); + return NGX_ERROR; + } + } + + return NGX_OK; +} + + +#endif /* NGX_HTTP_SSL */ diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_ssl.h b/debian/modules/nginx-lua/src/ngx_http_lua_ssl.h new file mode 100644 index 0000000..7a245ff --- /dev/null +++ b/debian/modules/nginx-lua/src/ngx_http_lua_ssl.h @@ -0,0 +1,43 @@ + +/* + * Copyright (C) Yichun Zhang (agentzh) + */ + + +#ifndef _NGX_HTTP_LUA_SSL_H_INCLUDED_ +#define _NGX_HTTP_LUA_SSL_H_INCLUDED_ + + +#include "ngx_http_lua_common.h" + + +#if (NGX_HTTP_SSL) +typedef struct { + ngx_connection_t *connection; /* original true connection */ + ngx_http_request_t *request; /* fake request */ + ngx_pool_cleanup_pt *cleanup; + + ngx_ssl_session_t *session; /* retrurn value for openssl's + * session_get_cb */ + + ngx_str_t session_id; + + int exit_code; /* exit code for openssl's + set_cert_cb callback */ + + unsigned done:1; + unsigned aborted:1; + + unsigned entered_cert_handler:1; + unsigned entered_sess_fetch_handler:1; +} ngx_http_lua_ssl_ctx_t; +#endif + + +ngx_int_t ngx_http_lua_ssl_init(ngx_log_t *log); + + +extern int ngx_http_lua_ssl_ctx_index; + + +#endif /* _NGX_HTTP_LUA_SSL_H_INCLUDED_ */ diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_ssl_certby.c b/debian/modules/nginx-lua/src/ngx_http_lua_ssl_certby.c index c06bc8e..aca4735 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_ssl_certby.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_ssl_certby.c @@ -20,6 +20,7 @@ #include "ngx_http_lua_contentby.h" #include "ngx_http_lua_ssl_certby.h" #include "ngx_http_lua_directive.h" +#include "ngx_http_lua_ssl.h" enum { @@ -37,9 +38,6 @@ static ngx_int_t ngx_http_lua_ssl_cert_by_chunk(lua_State *L, ngx_http_request_t *r); -int ngx_http_lua_ssl_ctx_index = -1; - - ngx_int_t ngx_http_lua_ssl_cert_handler_file(ngx_http_request_t *r, ngx_http_lua_srv_conf_t *lscf, lua_State *L) @@ -47,8 +45,8 @@ ngx_http_lua_ssl_cert_handler_file(ngx_http_request_t *r, ngx_int_t rc; rc = ngx_http_lua_cache_loadfile(r->connection->log, L, - lscf->ssl.cert_src.data, - lscf->ssl.cert_src_key); + lscf->srv.ssl_cert_src.data, + lscf->srv.ssl_cert_src_key); if (rc != NGX_OK) { return rc; } @@ -67,9 +65,9 @@ ngx_http_lua_ssl_cert_handler_inline(ngx_http_request_t *r, ngx_int_t rc; rc = ngx_http_lua_cache_loadbuffer(r->connection->log, L, - lscf->ssl.cert_src.data, - lscf->ssl.cert_src.len, - lscf->ssl.cert_src_key, + lscf->srv.ssl_cert_src.data, + lscf->srv.ssl_cert_src.len, + lscf->srv.ssl_cert_src_key, "=ssl_certificate_by_lua"); if (rc != NGX_OK) { return rc; @@ -120,29 +118,22 @@ ngx_http_lua_ssl_cert_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, ngx_str_t *value; ngx_http_lua_srv_conf_t *lscf = conf; - /* must specifiy a concrete handler */ + /* must specify a concrete handler */ if (cmd->post == NULL) { return NGX_CONF_ERROR; } - if (lscf->ssl.cert_handler) { + if (lscf->srv.ssl_cert_handler) { return "is duplicate"; } - if (ngx_http_lua_ssl_ctx_index == -1) { - ngx_http_lua_ssl_ctx_index = SSL_get_ex_new_index(0, NULL, NULL, - NULL, NULL); - - if (ngx_ssl_connection_index == -1) { - ngx_ssl_error(NGX_LOG_ALERT, cf->log, 0, - "lua: SSL_get_ex_new_index() failed"); - return NGX_CONF_ERROR; - } + if (ngx_http_lua_ssl_init(cf->log) != NGX_OK) { + return NGX_CONF_ERROR; } value = cf->args->elts; - lscf->ssl.cert_handler = (ngx_http_lua_srv_conf_handler_pt) cmd->post; + lscf->srv.ssl_cert_handler = (ngx_http_lua_srv_conf_handler_pt) cmd->post; if (cmd->post == ngx_http_lua_ssl_cert_handler_file) { /* Lua code in an external file */ @@ -153,15 +144,15 @@ ngx_http_lua_ssl_cert_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, return NGX_CONF_ERROR; } - lscf->ssl.cert_src.data = name; - lscf->ssl.cert_src.len = ngx_strlen(name); + lscf->srv.ssl_cert_src.data = name; + lscf->srv.ssl_cert_src.len = ngx_strlen(name); p = ngx_palloc(cf->pool, NGX_HTTP_LUA_FILE_KEY_LEN + 1); if (p == NULL) { return NGX_CONF_ERROR; } - lscf->ssl.cert_src_key = p; + lscf->srv.ssl_cert_src_key = p; p = ngx_copy(p, NGX_HTTP_LUA_FILE_TAG, NGX_HTTP_LUA_FILE_TAG_LEN); p = ngx_http_lua_digest_hex(p, value[1].data, value[1].len); @@ -170,14 +161,14 @@ ngx_http_lua_ssl_cert_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, } else { /* inlined Lua code */ - lscf->ssl.cert_src = value[1]; + lscf->srv.ssl_cert_src = value[1]; p = ngx_palloc(cf->pool, NGX_HTTP_LUA_INLINE_KEY_LEN + 1); if (p == NULL) { return NGX_CONF_ERROR; } - lscf->ssl.cert_src_key = p; + lscf->srv.ssl_cert_src_key = p; p = ngx_copy(p, NGX_HTTP_LUA_INLINE_TAG, NGX_HTTP_LUA_INLINE_TAG_LEN); p = ngx_http_lua_digest_hex(p, value[1].data, value[1].len); @@ -200,7 +191,8 @@ ngx_http_lua_ssl_cert_handler(ngx_ssl_conn_t *ssl_conn, void *data) ngx_pool_cleanup_t *cln; ngx_http_connection_t *hc; ngx_http_lua_srv_conf_t *lscf; - ngx_http_lua_ssl_cert_ctx_t *cctx; + ngx_http_core_loc_conf_t *clcf; + ngx_http_lua_ssl_ctx_t *cctx; c = ngx_ssl_get_connection(ssl_conn); @@ -210,7 +202,7 @@ ngx_http_lua_ssl_cert_handler(ngx_ssl_conn_t *ssl_conn, void *data) dd("ssl cert handler, cert-ctx=%p", cctx); - if (cctx) { + if (cctx && cctx->entered_cert_handler) { /* not the first time */ if (cctx->done) { @@ -225,8 +217,6 @@ ngx_http_lua_ssl_cert_handler(ngx_ssl_conn_t *ssl_conn, void *data) return -1; } - /* cctx == NULL */ - dd("first time"); hc = c->data; @@ -255,14 +245,42 @@ ngx_http_lua_ssl_cert_handler(ngx_ssl_conn_t *ssl_conn, void *data) fc->log->log_level = c->log->log_level; fc->ssl = c->ssl; - cctx = ngx_pcalloc(c->pool, sizeof(ngx_http_lua_ssl_cert_ctx_t)); + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + +#if defined(nginx_version) && nginx_version >= 1003014 + +# if nginx_version >= 1009000 + + ngx_set_connection_log(fc, clcf->error_log); + +# else + + ngx_http_set_connection_log(fc, clcf->error_log); + +# endif + +#else + + fc->log->file = clcf->error_log->file; + + if (!(fc->log->log_level & NGX_LOG_DEBUG_CONNECTION)) { + fc->log->log_level = clcf->error_log->log_level; + } + +#endif + if (cctx == NULL) { - goto failed; /* error */ + cctx = ngx_pcalloc(c->pool, sizeof(ngx_http_lua_ssl_ctx_t)); + if (cctx == NULL) { + goto failed; /* error */ + } } cctx->exit_code = 1; /* successful by default */ cctx->connection = c; cctx->request = r; + cctx->entered_cert_handler = 1; + cctx->done = 0; dd("setting cctx"); @@ -280,11 +298,15 @@ ngx_http_lua_ssl_cert_handler(ngx_ssl_conn_t *ssl_conn, void *data) c->log->action = "loading SSL certificate by lua"; - rc = lscf->ssl.cert_handler(r, lscf, L); + rc = lscf->srv.ssl_cert_handler(r, lscf, L); if (rc >= NGX_OK || rc == NGX_ERROR) { cctx->done = 1; + if (cctx->cleanup) { + *cctx->cleanup = NULL; + } + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "lua_certificate_by_lua: handler return value: %i, " "cert cb exit code: %d", rc, cctx->exit_code); @@ -303,13 +325,17 @@ ngx_http_lua_ssl_cert_handler(ngx_ssl_conn_t *ssl_conn, void *data) cln->handler = ngx_http_lua_ssl_cert_done; cln->data = cctx; - cln = ngx_pool_cleanup_add(c->pool, 0); - if (cln == NULL) { - goto failed; + if (cctx->cleanup == NULL) { + cln = ngx_pool_cleanup_add(c->pool, 0); + if (cln == NULL) { + goto failed; + } + + cln->data = cctx; + cctx->cleanup = &cln->handler; } - cln->handler = ngx_http_lua_ssl_cert_aborted; - cln->data = cctx; + *cctx->cleanup = ngx_http_lua_ssl_cert_aborted; return -1; @@ -333,7 +359,7 @@ static void ngx_http_lua_ssl_cert_done(void *data) { ngx_connection_t *c; - ngx_http_lua_ssl_cert_ctx_t *cctx = data; + ngx_http_lua_ssl_ctx_t *cctx = data; dd("lua ssl cert done"); @@ -345,6 +371,10 @@ ngx_http_lua_ssl_cert_done(void *data) cctx->done = 1; + if (cctx->cleanup) { + *cctx->cleanup = NULL; + } + c = cctx->connection; c->log->action = "SSL handshaking"; @@ -356,7 +386,7 @@ ngx_http_lua_ssl_cert_done(void *data) static void ngx_http_lua_ssl_cert_aborted(void *data) { - ngx_http_lua_ssl_cert_ctx_t *cctx = data; + ngx_http_lua_ssl_ctx_t *cctx = data; dd("lua ssl cert done"); @@ -931,7 +961,7 @@ ngx_http_lua_ffi_priv_key_pem_to_der(const u_char *pem, size_t pem_len, pkey = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL); if (pkey == NULL) { BIO_free(in); - *err = "PEM_read_bio_PrivateKey failed"; + *err = "PEM_read_bio_PrivateKey() failed"; ERR_clear_error(); return NGX_ERROR; } @@ -941,7 +971,7 @@ ngx_http_lua_ffi_priv_key_pem_to_der(const u_char *pem, size_t pem_len, len = i2d_PrivateKey(pkey, &der); if (len < 0) { EVP_PKEY_free(pkey); - *err = "i2d_PrivateKey failed"; + *err = "i2d_PrivateKey() failed"; ERR_clear_error(); return NGX_ERROR; } @@ -952,6 +982,256 @@ ngx_http_lua_ffi_priv_key_pem_to_der(const u_char *pem, size_t pem_len, } +void * +ngx_http_lua_ffi_parse_pem_cert(const u_char *pem, size_t pem_len, + char **err) +{ + BIO *bio; + X509 *x509; + u_long n; + STACK_OF(X509) *chain; + + bio = BIO_new_mem_buf((char *) pem, (int) pem_len); + if (bio == NULL) { + *err = "BIO_new_mem_buf() failed"; + ERR_clear_error(); + return NULL; + } + + x509 = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL); + if (x509 == NULL) { + *err = "PEM_read_bio_X509_AUX() failed"; + BIO_free(bio); + ERR_clear_error(); + return NULL; + } + + chain = sk_X509_new_null(); + if (chain == NULL) { + *err = "sk_X509_new_null() failed"; + X509_free(x509); + BIO_free(bio); + ERR_clear_error(); + return NULL; + } + + if (sk_X509_push(chain, x509) == 0) { + *err = "sk_X509_push() failed"; + sk_X509_free(chain); + X509_free(x509); + BIO_free(bio); + ERR_clear_error(); + return NULL; + } + + /* read rest of the chain */ + + for ( ;; ) { + + x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL); + if (x509 == NULL) { + n = ERR_peek_last_error(); + + if (ERR_GET_LIB(n) == ERR_LIB_PEM + && ERR_GET_REASON(n) == PEM_R_NO_START_LINE) + { + /* end of file */ + ERR_clear_error(); + break; + } + + /* some real error */ + + *err = "PEM_read_bio_X509() failed"; + sk_X509_pop_free(chain, X509_free); + BIO_free(bio); + ERR_clear_error(); + return NULL; + } + + if (sk_X509_push(chain, x509) == 0) { + *err = "sk_X509_push() failed"; + sk_X509_pop_free(chain, X509_free); + X509_free(x509); + BIO_free(bio); + ERR_clear_error(); + return NULL; + } + } + + BIO_free(bio); + + return chain; +} + + +void +ngx_http_lua_ffi_free_cert(void *cdata) +{ + STACK_OF(X509) *chain = cdata; + + sk_X509_pop_free(chain, X509_free); +} + + +void * +ngx_http_lua_ffi_parse_pem_priv_key(const u_char *pem, size_t pem_len, + char **err) +{ + BIO *in; + EVP_PKEY *pkey; + + in = BIO_new_mem_buf((char *) pem, (int) pem_len); + if (in == NULL) { + *err = "BIO_new_mem_buf() failed"; + ERR_clear_error(); + return NULL; + } + + pkey = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL); + if (pkey == NULL) { + *err = "PEM_read_bio_PrivateKey() failed"; + BIO_free(in); + ERR_clear_error(); + return NULL; + } + + BIO_free(in); + + return pkey; +} + + +void +ngx_http_lua_ffi_free_priv_key(void *cdata) +{ + EVP_PKEY *pkey = cdata; + + EVP_PKEY_free(pkey); +} + + +int +ngx_http_lua_ffi_set_cert(ngx_http_request_t *r, + void *cdata, char **err) +{ +#ifdef LIBRESSL_VERSION_NUMBER + + *err = "LibreSSL not supported"; + return NGX_ERROR; + +#else + +# if OPENSSL_VERSION_NUMBER < 0x1000205fL + + *err = "at least OpenSSL 1.0.2e required but found " OPENSSL_VERSION_TEXT; + return NGX_ERROR; + +# else + + int i; + X509 *x509 = NULL; + ngx_ssl_conn_t *ssl_conn; + STACK_OF(X509) *chain = cdata; + + if (r->connection == NULL || r->connection->ssl == NULL) { + *err = "bad request"; + return NGX_ERROR; + } + + ssl_conn = r->connection->ssl->connection; + if (ssl_conn == NULL) { + *err = "bad ssl conn"; + return NGX_ERROR; + } + + if (sk_X509_num(chain) < 1) { + *err = "invalid certificate chain"; + goto failed; + } + + x509 = sk_X509_value(chain, 0); + if (x509 == NULL) { + *err = "sk_X509_value() failed"; + goto failed; + } + + if (SSL_use_certificate(ssl_conn, x509) == 0) { + *err = "SSL_use_certificate() failed"; + goto failed; + } + + x509 = NULL; + + /* read rest of the chain */ + + for (i = 1; i < sk_X509_num(chain); i++) { + + x509 = sk_X509_value(chain, i); + if (x509 == NULL) { + *err = "sk_X509_value() failed"; + goto failed; + } + + if (SSL_add1_chain_cert(ssl_conn, x509) == 0) { + *err = "SSL_add1_chain_cert() failed"; + goto failed; + } + } + + *err = NULL; + return NGX_OK; + +failed: + + ERR_clear_error(); + + return NGX_ERROR; + +# endif /* OPENSSL_VERSION_NUMBER < 0x1000205fL */ +#endif +} + + +int +ngx_http_lua_ffi_set_priv_key(ngx_http_request_t *r, + void *cdata, char **err) +{ + EVP_PKEY *pkey = NULL; + ngx_ssl_conn_t *ssl_conn; + + if (r->connection == NULL || r->connection->ssl == NULL) { + *err = "bad request"; + return NGX_ERROR; + } + + ssl_conn = r->connection->ssl->connection; + if (ssl_conn == NULL) { + *err = "bad ssl conn"; + return NGX_ERROR; + } + + pkey = cdata; + if (pkey == NULL) { + *err = "invalid private key failed"; + goto failed; + } + + if (SSL_use_PrivateKey(ssl_conn, pkey) == 0) { + *err = "SSL_use_PrivateKey() failed"; + goto failed; + } + + return NGX_OK; + +failed: + + ERR_clear_error(); + + return NGX_ERROR; +} + + #endif /* NGX_LUA_NO_FFI_API */ diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_ssl_certby.h b/debian/modules/nginx-lua/src/ngx_http_lua_ssl_certby.h index 11cb963..fb07e01 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_ssl_certby.h +++ b/debian/modules/nginx-lua/src/ngx_http_lua_ssl_certby.h @@ -14,16 +14,6 @@ #if (NGX_HTTP_SSL) -typedef struct { - ngx_connection_t *connection; /* original true connection */ - ngx_http_request_t *request; /* fake request */ - int exit_code; /* exit code for openssl's - set_cert_cb callback */ - unsigned done; /* :1 */ - unsigned aborted; /* :1 */ -} ngx_http_lua_ssl_cert_ctx_t; - - ngx_int_t ngx_http_lua_ssl_cert_handler_inline(ngx_http_request_t *r, ngx_http_lua_srv_conf_t *lscf, lua_State *L); diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_ssl_ocsp.c b/debian/modules/nginx-lua/src/ngx_http_lua_ssl_ocsp.c index 1bf4335..3904aa8 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_ssl_ocsp.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_ssl_ocsp.c @@ -233,8 +233,6 @@ ngx_http_lua_ffi_ssl_create_ocsp_request(const char *chain_data, X509_free(cert); BIO_free(bio); - ERR_clear_error(); - return NGX_OK; failed: @@ -255,6 +253,8 @@ failed: BIO_free(bio); } + ERR_clear_error(); + return rc; #endif /* NGX_HTTP_LUA_USE_OCSP */ diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_ssl_session_fetchby.c b/debian/modules/nginx-lua/src/ngx_http_lua_ssl_session_fetchby.c new file mode 100644 index 0000000..4c450b5 --- /dev/null +++ b/debian/modules/nginx-lua/src/ngx_http_lua_ssl_session_fetchby.c @@ -0,0 +1,592 @@ + +/* + * Copyright (C) Yichun Zhang (agentzh) + */ + + +#ifndef DDEBUG +#define DDEBUG 0 +#endif +#include "ddebug.h" + + +#if (NGX_HTTP_SSL) + + +#include "ngx_http_lua_cache.h" +#include "ngx_http_lua_initworkerby.h" +#include "ngx_http_lua_util.h" +#include "ngx_http_ssl_module.h" +#include "ngx_http_lua_contentby.h" +#include "ngx_http_lua_ssl_session_fetchby.h" +#include "ngx_http_lua_ssl.h" +#include "ngx_http_lua_directive.h" + + +/* Lua SSL cached session loading routines */ +static void ngx_http_lua_ssl_sess_fetch_done(void *data); +static void ngx_http_lua_ssl_sess_fetch_aborted(void *data); +static u_char *ngx_http_lua_log_ssl_sess_fetch_error(ngx_log_t *log, + u_char *buf, size_t len); +static ngx_int_t ngx_http_lua_ssl_sess_fetch_by_chunk(lua_State *L, + ngx_http_request_t *r); + + +/* load Lua code from a file for fetching cached SSL session */ +ngx_int_t +ngx_http_lua_ssl_sess_fetch_handler_file(ngx_http_request_t *r, + ngx_http_lua_srv_conf_t *lscf, lua_State *L) +{ + ngx_int_t rc; + + rc = ngx_http_lua_cache_loadfile(r->connection->log, L, + lscf->srv.ssl_sess_fetch_src.data, + lscf->srv.ssl_sess_fetch_src_key); + if (rc != NGX_OK) { + return rc; + } + + /* make sure we have a valid code chunk */ + ngx_http_lua_assert(lua_isfunction(L, -1)); + + return ngx_http_lua_ssl_sess_fetch_by_chunk(L, r); +} + + +/* load lua code from an inline snippet for fetching cached SSL session */ +ngx_int_t +ngx_http_lua_ssl_sess_fetch_handler_inline(ngx_http_request_t *r, + ngx_http_lua_srv_conf_t *lscf, lua_State *L) +{ + ngx_int_t rc; + + rc = ngx_http_lua_cache_loadbuffer(r->connection->log, L, + lscf->srv.ssl_sess_fetch_src.data, + lscf->srv.ssl_sess_fetch_src.len, + lscf->srv.ssl_sess_fetch_src_key, + "=ssl_session_fetch_by_lua_block"); + if (rc != NGX_OK) { + return rc; + } + + /* make sure we have a valid code chunk */ + ngx_http_lua_assert(lua_isfunction(L, -1)); + + return ngx_http_lua_ssl_sess_fetch_by_chunk(L, r); +} + + +char * +ngx_http_lua_ssl_sess_fetch_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) +{ + char *rv; + ngx_conf_t save; + + save = *cf; + cf->handler = ngx_http_lua_ssl_sess_fetch_by_lua; + cf->handler_conf = conf; + + rv = ngx_http_lua_conf_lua_block_parse(cf, cmd); + + *cf = save; + + return rv; +} + + +/* conf parser for directive ssl_session_fetch_by_lua */ +char * +ngx_http_lua_ssl_sess_fetch_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) +{ + u_char *p; + u_char *name; + ngx_str_t *value; + ngx_http_lua_srv_conf_t *lscf = conf; + + dd("enter"); + + /* must specifiy a content handler */ + if (cmd->post == NULL) { + return NGX_CONF_ERROR; + } + + if (lscf->srv.ssl_sess_fetch_handler) { + return "is duplicate"; + } + + if (ngx_http_lua_ssl_init(cf->log) != NGX_OK) { + return NGX_CONF_ERROR; + } + + value = cf->args->elts; + + lscf->srv.ssl_sess_fetch_handler = + (ngx_http_lua_srv_conf_handler_pt) cmd->post; + + if (cmd->post == ngx_http_lua_ssl_sess_fetch_handler_file) { + /* Lua code in an external file */ + + name = ngx_http_lua_rebase_path(cf->pool, value[1].data, + value[1].len); + if (name == NULL) { + return NGX_CONF_ERROR; + } + + lscf->srv.ssl_sess_fetch_src.data = name; + lscf->srv.ssl_sess_fetch_src.len = ngx_strlen(name); + + p = ngx_palloc(cf->pool, NGX_HTTP_LUA_FILE_KEY_LEN + 1); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + lscf->srv.ssl_sess_fetch_src_key = p; + + p = ngx_copy(p, NGX_HTTP_LUA_FILE_TAG, NGX_HTTP_LUA_FILE_TAG_LEN); + p = ngx_http_lua_digest_hex(p, value[1].data, value[1].len); + *p = '\0'; + + } else { + /* inlined Lua code */ + + lscf->srv.ssl_sess_fetch_src = value[1]; + + p = ngx_palloc(cf->pool, NGX_HTTP_LUA_INLINE_KEY_LEN + 1); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + lscf->srv.ssl_sess_fetch_src_key = p; + + p = ngx_copy(p, NGX_HTTP_LUA_INLINE_TAG, NGX_HTTP_LUA_INLINE_TAG_LEN); + p = ngx_http_lua_digest_hex(p, value[1].data, value[1].len); + *p = '\0'; + } + + return NGX_CONF_OK; +} + + +/* cached session fetching callback to be set with SSL_CTX_sess_set_get_cb */ +ngx_ssl_session_t * +ngx_http_lua_ssl_sess_fetch_handler(ngx_ssl_conn_t *ssl_conn, u_char *id, + int len, int *copy) +{ + lua_State *L; + ngx_int_t rc; + ngx_connection_t *c, *fc = NULL; + ngx_http_request_t *r = NULL; + ngx_pool_cleanup_t *cln; + ngx_http_connection_t *hc; + ngx_http_lua_ssl_ctx_t *cctx; + ngx_http_lua_srv_conf_t *lscf; + ngx_http_core_loc_conf_t *clcf; + + /* set copy to 0 as we expect OpenSSL to handle + * the memory of returned session */ + + *copy = 0; + + c = ngx_ssl_get_connection(ssl_conn); + + dd("c = %p", c); + + cctx = ngx_http_lua_ssl_get_ctx(c->ssl->connection); + + dd("ssl sess_fetch handler, sess_fetch-ctx=%p", cctx); + + if (cctx && cctx->entered_sess_fetch_handler) { + /* not the first time */ + + dd("here: %d", (int) cctx->entered_sess_fetch_handler); + + if (cctx->done) { + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, + "ssl_session_fetch_by_lua*: " + "sess get cb exit code: %d", + cctx->exit_code); + + dd("lua ssl sess_fetch done, finally"); + return cctx->session; + } + +#ifdef SSL_ERROR_PENDING_SESSION + return SSL_magic_pending_session_ptr(); +#else + ngx_log_error(NGX_LOG_CRIT, c->log, 0, + "lua: cannot yield in sess get cb: " + "missing async sess get cb support in OpenSSL"); + return NULL; +#endif + } + + dd("first time"); + + hc = c->data; + + fc = ngx_http_lua_create_fake_connection(NULL); + if (fc == NULL) { + goto failed; + } + + fc->log->handler = ngx_http_lua_log_ssl_sess_fetch_error; + fc->log->data = fc; + + fc->addr_text = c->addr_text; + fc->listening = c->listening; + + r = ngx_http_lua_create_fake_request(fc); + if (r == NULL) { + goto failed; + } + + r->main_conf = hc->conf_ctx->main_conf; + r->srv_conf = hc->conf_ctx->srv_conf; + r->loc_conf = hc->conf_ctx->loc_conf; + + fc->log->file = c->log->file; + fc->log->log_level = c->log->log_level; + fc->ssl = c->ssl; + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + +#if defined(nginx_version) && nginx_version >= 1003014 + +# if nginx_version >= 1009000 + + ngx_set_connection_log(fc, clcf->error_log); + +# else + + ngx_http_set_connection_log(fc, clcf->error_log); + +# endif + +#else + + fc->log->file = clcf->error_log->file; + + if (!(fc->log->log_level & NGX_LOG_DEBUG_CONNECTION)) { + fc->log->log_level = clcf->error_log->log_level; + } + +#endif + + if (cctx == NULL) { + cctx = ngx_pcalloc(c->pool, sizeof(ngx_http_lua_ssl_ctx_t)); + if (cctx == NULL) { + goto failed; /* error */ + } + } + + cctx->exit_code = 1; /* successful by default */ + cctx->connection = c; + cctx->request = r; + cctx->session_id.data = id; + cctx->session_id.len = len; + cctx->entered_sess_fetch_handler = 1; + cctx->done = 0; + + dd("setting cctx = %p", cctx); + + if (SSL_set_ex_data(c->ssl->connection, ngx_http_lua_ssl_ctx_index, cctx) + == 0) + { + ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_ex_data() failed"); + goto failed; + } + + lscf = ngx_http_get_module_srv_conf(r, ngx_http_lua_module); + + /* TODO honor lua_code_cache off */ + L = ngx_http_lua_get_lua_vm(r, NULL); + + c->log->action = "fetching SSL session by lua"; + + rc = lscf->srv.ssl_sess_fetch_handler(r, lscf, L); + + if (rc >= NGX_OK || rc == NGX_ERROR) { + cctx->done = 1; + + if (cctx->cleanup) { + *cctx->cleanup = NULL; + } + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, + "ssl_session_fetch_by_lua*: handler return value: %i, " + "sess get cb exit code: %d", rc, cctx->exit_code); + + c->log->action = "SSL handshaking"; + return cctx->session; + } + + /* rc == NGX_DONE */ + + cln = ngx_pool_cleanup_add(fc->pool, 0); + if (cln == NULL) { + goto failed; + } + + cln->handler = ngx_http_lua_ssl_sess_fetch_done; + cln->data = cctx; + + if (cctx->cleanup == NULL) { + /* we only want exactly one cleanup handler to be registered with the + * connection to clean up cctx when connection is aborted */ + cln = ngx_pool_cleanup_add(c->pool, 0); + if (cln == NULL) { + goto failed; + } + + cln->data = cctx; + cctx->cleanup = &cln->handler; + } + + *cctx->cleanup = ngx_http_lua_ssl_sess_fetch_aborted; + +#ifdef SSL_ERROR_PENDING_SESSION + return SSL_magic_pending_session_ptr(); +#else + ngx_log_error(NGX_LOG_CRIT, c->log, 0, + "lua: cannot yield in sess get cb: " + "missing async sess get cb support in OpenSSL"); + + /* fall through to the "failed" label below */ +#endif + +failed: + + if (r && r->pool) { + ngx_http_lua_free_fake_request(r); + } + + if (fc) { + ngx_http_lua_close_fake_connection(fc); + } + + return NULL; +} + + +static void +ngx_http_lua_ssl_sess_fetch_done(void *data) +{ + ngx_connection_t *c; + ngx_http_lua_ssl_ctx_t *cctx = data; + + dd("lua ssl sess_fetch done"); + + if (cctx->aborted) { + return; + } + + ngx_http_lua_assert(cctx->done == 0); + + cctx->done = 1; + + if (cctx->cleanup) { + *cctx->cleanup = NULL; + } + + c = cctx->connection; + + c->log->action = "SSL handshaking"; + + ngx_post_event(c->write, &ngx_posted_events); +} + + +static void +ngx_http_lua_ssl_sess_fetch_aborted(void *data) +{ + ngx_http_lua_ssl_ctx_t *cctx = data; + + dd("lua ssl sess_fetch done"); + + if (cctx->done) { + /* completed successfully already */ + return; + } + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cctx->connection->log, 0, + "ssl_session_fetch_by_lua*: sess_fetch cb aborted"); + + cctx->aborted = 1; + cctx->request->connection->ssl = NULL; + + ngx_http_lua_finalize_fake_request(cctx->request, NGX_ERROR); +} + + +static u_char * +ngx_http_lua_log_ssl_sess_fetch_error(ngx_log_t *log, u_char *buf, size_t len) +{ + u_char *p; + ngx_connection_t *c; + + if (log->action) { + p = ngx_snprintf(buf, len, " while %s", log->action); + len -= p - buf; + buf = p; + } + + p = ngx_snprintf(buf, len, ", context: ssl_session_fetch_by_lua*"); + len -= p - buf; + buf = p; + + c = log->data; + + if (c->addr_text.len) { + p = ngx_snprintf(buf, len, ", client: %V", &c->addr_text); + len -= p - buf; + buf = p; + } + + if (c && c->listening && c->listening->addr_text.len) { + p = ngx_snprintf(buf, len, ", server: %V", &c->listening->addr_text); + buf = p; + } + + return buf; +} + + +/* initialize lua coroutine for fetching cached session */ +static ngx_int_t +ngx_http_lua_ssl_sess_fetch_by_chunk(lua_State *L, ngx_http_request_t *r) +{ + int co_ref; + ngx_int_t rc; + lua_State *co; + ngx_http_lua_ctx_t *ctx; + ngx_http_cleanup_t *cln; + + ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); + + if (ctx == NULL) { + ctx = ngx_http_lua_create_ctx(r); + if (ctx == NULL) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + } else { + dd("reset ctx"); + ngx_http_lua_reset_ctx(r, L, ctx); + } + + ctx->entered_content_phase = 1; + + /* {{{ new coroutine to handle request */ + co = ngx_http_lua_new_thread(r, L, &co_ref); + + if (co == NULL) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "lua: failed to create new coroutine to handle request"); + + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + /* move code closure to new coroutine */ + lua_xmove(L, co, 1); + + /* set closure's env table to new coroutine's globals table */ + ngx_http_lua_get_globals_table(co); + lua_setfenv(co, -2); + + /* save nginx request in coroutine globals table */ + ngx_http_lua_set_req(co, r); + + ctx->cur_co_ctx = &ctx->entry_co_ctx; + ctx->cur_co_ctx->co = co; + ctx->cur_co_ctx->co_ref = co_ref; +#ifdef NGX_LUA_USE_ASSERT + ctx->cur_co_ctx->co_top = 1; +#endif + + /* register request cleanup hooks */ + if (ctx->cleanup == NULL) { + cln = ngx_http_cleanup_add(r, 0); + if (cln == NULL) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + cln->handler = ngx_http_lua_request_cleanup_handler; + cln->data = ctx; + ctx->cleanup = &cln->handler; + } + + ctx->context = NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH; + + rc = ngx_http_lua_run_thread(L, r, ctx, 0); + + if (rc == NGX_ERROR || rc >= NGX_OK) { + /* do nothing */ + + } else if (rc == NGX_AGAIN) { + rc = ngx_http_lua_content_run_posted_threads(L, r, ctx, 0); + + } else if (rc == NGX_DONE) { + rc = ngx_http_lua_content_run_posted_threads(L, r, ctx, 1); + + } else { + rc = NGX_OK; + } + + ngx_http_lua_finalize_request(r, rc); + return rc; +} + + +#ifndef NGX_LUA_NO_FFI_API + +/* de-serialized a SSL session and set it back to the request at lua context */ +int +ngx_http_lua_ffi_ssl_set_serialized_session(ngx_http_request_t *r, + const unsigned char *data, int len, char **err) +{ + u_char *p; + u_char buf[NGX_SSL_MAX_SESSION_SIZE]; + ngx_ssl_conn_t *ssl_conn; + ngx_connection_t *c; + ngx_ssl_session_t *session = NULL; + ngx_http_lua_ssl_ctx_t *cctx; + + c = r->connection; + + if (c == NULL || c->ssl == NULL) { + *err = "bad request"; + return NGX_ERROR; + } + + ssl_conn = c->ssl->connection; + if (ssl_conn == NULL) { + *err = "bad ssl conn"; + return NGX_ERROR; + } + + ngx_memcpy(buf, data, len); + p = buf; + session = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, len); + if (session == NULL) { + ERR_clear_error(); + *err = "failed to de-serialize session"; + return NGX_ERROR; + } + + cctx = ngx_http_lua_ssl_get_ctx(c->ssl->connection); + if (cctx == NULL) { + *err = "bad lua context"; + return NGX_ERROR; + } + + cctx->session = session; + + return NGX_OK; +} + +#endif /* NGX_LUA_NO_FFI_API */ + + +#endif /* NGX_HTTP_SSL */ diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_ssl_session_fetchby.h b/debian/modules/nginx-lua/src/ngx_http_lua_ssl_session_fetchby.h new file mode 100644 index 0000000..5a6f96f --- /dev/null +++ b/debian/modules/nginx-lua/src/ngx_http_lua_ssl_session_fetchby.h @@ -0,0 +1,34 @@ + +/* + * Copyright (C) Yichun Zhang (agentzh) + */ + + +#ifndef _NGX_HTTP_LUA_SSL_SESSION_FETCHBY_H_INCLUDED_ +#define _NGX_HTTP_LUA_SSL_SESSION_FETCHBY_H_INCLUDED_ + + +#include "ngx_http_lua_common.h" + + +#if (NGX_HTTP_SSL) +ngx_int_t ngx_http_lua_ssl_sess_fetch_handler_inline(ngx_http_request_t *r, + ngx_http_lua_srv_conf_t *lscf, lua_State *L); + +ngx_int_t ngx_http_lua_ssl_sess_fetch_handler_file(ngx_http_request_t *r, + ngx_http_lua_srv_conf_t *lscf, lua_State *L); + +char *ngx_http_lua_ssl_sess_fetch_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); + +char *ngx_http_lua_ssl_sess_fetch_by_lua_block(ngx_conf_t *cf, + ngx_command_t *cmd, void *conf); + +ngx_ssl_session_t *ngx_http_lua_ssl_sess_fetch_handler( + ngx_ssl_conn_t *ssl_conn, u_char *id, int len, int *copy); +#endif + + +#endif /* _NGX_HTTP_LUA_SSL_SESSION_FETCHBY_H_INCLUDED_ */ + +/* vi:set ft=c ts=4 sw=4 et fdm=marker: */ diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_ssl_session_storeby.c b/debian/modules/nginx-lua/src/ngx_http_lua_ssl_session_storeby.c new file mode 100644 index 0000000..b5596bc --- /dev/null +++ b/debian/modules/nginx-lua/src/ngx_http_lua_ssl_session_storeby.c @@ -0,0 +1,602 @@ + +/* + * Copyright (C) Yichun Zhang (agentzh) + */ + + +#ifndef DDEBUG +#define DDEBUG 0 +#endif +#include "ddebug.h" + + +#if (NGX_HTTP_SSL) + + +#include "ngx_http_lua_cache.h" +#include "ngx_http_lua_initworkerby.h" +#include "ngx_http_lua_util.h" +#include "ngx_http_ssl_module.h" +#include "ngx_http_lua_contentby.h" +#include "ngx_http_lua_ssl_session_storeby.h" +#include "ngx_http_lua_ssl.h" +#include "ngx_http_lua_directive.h" + + +/* Lua SSL new session store routines */ +static u_char *ngx_http_lua_log_ssl_sess_store_error(ngx_log_t *log, + u_char *buf, size_t len); +static ngx_int_t ngx_http_lua_ssl_sess_store_by_chunk(lua_State *L, + ngx_http_request_t *r); + + +/* load Lua code from a file for caching new SSL session. */ +ngx_int_t +ngx_http_lua_ssl_sess_store_handler_file(ngx_http_request_t *r, + ngx_http_lua_srv_conf_t *lscf, lua_State *L) +{ + ngx_int_t rc; + + rc = ngx_http_lua_cache_loadfile(r->connection->log, L, + lscf->srv.ssl_sess_store_src.data, + lscf->srv.ssl_sess_store_src_key); + if (rc != NGX_OK) { + return rc; + } + + /* make sure we have a valid code chunk */ + ngx_http_lua_assert(lua_isfunction(L, -1)); + + return ngx_http_lua_ssl_sess_store_by_chunk(L, r); +} + + +/* load lua code from an inline snippet for caching new SSL session */ +ngx_int_t +ngx_http_lua_ssl_sess_store_handler_inline(ngx_http_request_t *r, + ngx_http_lua_srv_conf_t *lscf, lua_State *L) +{ + ngx_int_t rc; + + rc = ngx_http_lua_cache_loadbuffer(r->connection->log, L, + lscf->srv.ssl_sess_store_src.data, + lscf->srv.ssl_sess_store_src.len, + lscf->srv.ssl_sess_store_src_key, + "=ssl_session_store_by_lua_block"); + if (rc != NGX_OK) { + return rc; + } + + /* make sure we have a valid code chunk */ + ngx_http_lua_assert(lua_isfunction(L, -1)); + + return ngx_http_lua_ssl_sess_store_by_chunk(L, r); +} + + +char * +ngx_http_lua_ssl_sess_store_by_lua_block(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) +{ + char *rv; + ngx_conf_t save; + + save = *cf; + cf->handler = ngx_http_lua_ssl_sess_store_by_lua; + cf->handler_conf = conf; + + rv = ngx_http_lua_conf_lua_block_parse(cf, cmd); + + *cf = save; + + return rv; +} + + +/* conf parser for directive ssl_session_store_by_lua */ +char * +ngx_http_lua_ssl_sess_store_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) +{ + u_char *p; + u_char *name; + ngx_str_t *value; + ngx_http_lua_srv_conf_t *lscf = conf; + + dd("enter"); + + /* must specifiy a content handler */ + if (cmd->post == NULL) { + return NGX_CONF_ERROR; + } + + if (lscf->srv.ssl_sess_store_handler) { + return "is duplicate"; + } + + if (ngx_http_lua_ssl_init(cf->log) != NGX_OK) { + return NGX_CONF_ERROR; + } + + value = cf->args->elts; + + lscf->srv.ssl_sess_store_handler = + (ngx_http_lua_srv_conf_handler_pt) cmd->post; + + if (cmd->post == ngx_http_lua_ssl_sess_store_handler_file) { + /* Lua code in an external file */ + + name = ngx_http_lua_rebase_path(cf->pool, value[1].data, + value[1].len); + if (name == NULL) { + return NGX_CONF_ERROR; + } + + lscf->srv.ssl_sess_store_src.data = name; + lscf->srv.ssl_sess_store_src.len = ngx_strlen(name); + + p = ngx_palloc(cf->pool, NGX_HTTP_LUA_FILE_KEY_LEN + 1); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + lscf->srv.ssl_sess_store_src_key = p; + + p = ngx_copy(p, NGX_HTTP_LUA_FILE_TAG, NGX_HTTP_LUA_FILE_TAG_LEN); + p = ngx_http_lua_digest_hex(p, value[1].data, value[1].len); + *p = '\0'; + + } else { + /* inlined Lua code */ + + lscf->srv.ssl_sess_store_src = value[1]; + + p = ngx_palloc(cf->pool, NGX_HTTP_LUA_INLINE_KEY_LEN + 1); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + lscf->srv.ssl_sess_store_src_key = p; + + p = ngx_copy(p, NGX_HTTP_LUA_INLINE_TAG, NGX_HTTP_LUA_INLINE_TAG_LEN); + p = ngx_http_lua_digest_hex(p, value[1].data, value[1].len); + *p = '\0'; + } + + return NGX_CONF_OK; +} + + +/* callback for new session caching, to be set with SSL_CTX_sess_set_new_cb */ +int +ngx_http_lua_ssl_sess_store_handler(ngx_ssl_conn_t *ssl_conn, + ngx_ssl_session_t *sess) +{ + lua_State *L; + ngx_int_t rc; + ngx_connection_t *c, *fc = NULL; + ngx_http_request_t *r = NULL; + ngx_http_connection_t *hc; + ngx_http_lua_ssl_ctx_t *cctx; + ngx_http_lua_srv_conf_t *lscf; + ngx_http_core_loc_conf_t *clcf; + + c = ngx_ssl_get_connection(ssl_conn); + + dd("c = %p", c); + + cctx = ngx_http_lua_ssl_get_ctx(c->ssl->connection); + + dd("ssl sess_store handler, sess_store-ctx=%p", cctx); + + hc = c->data; + + fc = ngx_http_lua_create_fake_connection(NULL); + if (fc == NULL) { + goto failed; + } + + fc->log->handler = ngx_http_lua_log_ssl_sess_store_error; + fc->log->data = fc; + + fc->addr_text = c->addr_text; + fc->listening = c->listening; + + r = ngx_http_lua_create_fake_request(fc); + if (r == NULL) { + goto failed; + } + + r->main_conf = hc->conf_ctx->main_conf; + r->srv_conf = hc->conf_ctx->srv_conf; + r->loc_conf = hc->conf_ctx->loc_conf; + + fc->log->file = c->log->file; + fc->log->log_level = c->log->log_level; + fc->ssl = c->ssl; + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + +#if defined(nginx_version) && nginx_version >= 1003014 + +# if nginx_version >= 1009000 + + ngx_set_connection_log(fc, clcf->error_log); + +# else + + ngx_http_set_connection_log(fc, clcf->error_log); + +# endif + +#else + + fc->log->file = clcf->error_log->file; + + if (!(fc->log->log_level & NGX_LOG_DEBUG_CONNECTION)) { + fc->log->log_level = clcf->error_log->log_level; + } + +#endif + + if (cctx == NULL) { + cctx = ngx_pcalloc(c->pool, sizeof(ngx_http_lua_ssl_ctx_t)); + if (cctx == NULL) { + goto failed; /* error */ + } + } + + cctx->connection = c; + cctx->request = r; + cctx->session = sess; + cctx->session_id.data = sess->session_id; + cctx->session_id.len = sess->session_id_length; + cctx->done = 0; + + dd("setting cctx"); + + if (SSL_set_ex_data(c->ssl->connection, ngx_http_lua_ssl_ctx_index, cctx) + == 0) + { + ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_ex_data() failed"); + goto failed; + } + + lscf = ngx_http_get_module_srv_conf(r, ngx_http_lua_module); + + /* TODO honor lua_code_cache off */ + L = ngx_http_lua_get_lua_vm(r, NULL); + + c->log->action = "storing SSL session by lua"; + + rc = lscf->srv.ssl_sess_store_handler(r, lscf, L); + + if (rc >= NGX_OK || rc == NGX_ERROR) { + cctx->done = 1; + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, + "ssl_session_store_by_lua*: handler return value: %i, " + "sess new cb exit code: %d", rc, cctx->exit_code); + + c->log->action = "SSL handshaking"; + + /* Return value is a flag indicating whether the passed-in session + * has been freed by this callback; always return 0 so OpenSSL will + * free the session. Nginx's own session caching logic has the same + * practice. */ + return 0; + } + + /* impossible to reach here */ + ngx_http_lua_assert(0); + +failed: + + if (r && r->pool) { + ngx_http_lua_free_fake_request(r); + } + + if (fc) { + ngx_http_lua_close_fake_connection(fc); + } + + return 0; +} + + +static u_char * +ngx_http_lua_log_ssl_sess_store_error(ngx_log_t *log, u_char *buf, size_t len) +{ + u_char *p; + ngx_connection_t *c; + + if (log->action) { + p = ngx_snprintf(buf, len, " while %s", log->action); + len -= p - buf; + buf = p; + } + + p = ngx_snprintf(buf, len, ", context: ssl_session_store_by_lua*"); + len -= p - buf; + buf = p; + + c = log->data; + + if (c->addr_text.len) { + p = ngx_snprintf(buf, len, ", client: %V", &c->addr_text); + len -= p - buf; + buf = p; + } + + if (c && c->listening && c->listening->addr_text.len) { + p = ngx_snprintf(buf, len, ", server: %V", &c->listening->addr_text); + buf = p; + } + + return buf; +} + + +/* initialize lua coroutine for caching new SSL session */ +static ngx_int_t +ngx_http_lua_ssl_sess_store_by_chunk(lua_State *L, ngx_http_request_t *r) +{ + size_t len; + u_char *err_msg; + ngx_int_t rc; + ngx_http_lua_ctx_t *ctx; + + ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); + + if (ctx == NULL) { + ctx = ngx_http_lua_create_ctx(r); + if (ctx == NULL) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + } else { + dd("reset ctx"); + ngx_http_lua_reset_ctx(r, L, ctx); + } + + ctx->entered_content_phase = 1; + ctx->context = NGX_HTTP_LUA_CONTEXT_SSL_SESS_STORE; + + /* init nginx context in Lua VM */ + ngx_http_lua_set_req(L, r); + ngx_http_lua_create_new_globals_table(L, 0 /* narr */, 1 /* nrec */); + + /* {{{ make new env inheriting main thread's globals table */ + lua_createtable(L, 0, 1 /* nrec */); /* the metatable for the new env */ + ngx_http_lua_get_globals_table(L); + lua_setfield(L, -2, "__index"); + lua_setmetatable(L, -2); /* setmetatable({}, {__index = _G}) */ + /* }}} */ + + lua_setfenv(L, -2); /* set new running env for the code closure */ + + lua_pushcfunction(L, ngx_http_lua_traceback); + lua_insert(L, 1); /* put it under chunk and args */ + + /* protected call user code */ + rc = lua_pcall(L, 0, 1, 1); + + lua_remove(L, 1); /* remove traceback function */ + + dd("rc == %d", (int) rc); + + if (rc != 0) { + /* error occured when running loaded code */ + err_msg = (u_char *) lua_tolstring(L, -1, &len); + + if (err_msg == NULL) { + err_msg = (u_char *) "unknown reason"; + len = sizeof("unknown reason") - 1; + } + + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "failed to run session_store_by_lua*: %*s", len, err_msg); + + lua_settop(L, 0); /* clear remaining elems on stack */ + ngx_http_lua_finalize_request(r, rc); + + return NGX_ERROR; + } + + lua_settop(L, 0); /* clear remaining elems on stack */ + ngx_http_lua_finalize_request(r, rc); + return rc; +} + + +#ifndef NGX_LUA_NO_FFI_API + +/* serialize a session from lua context into buf. + * the memory allocation of buf should be handled externally. */ +int +ngx_http_lua_ffi_ssl_get_serialized_session(ngx_http_request_t *r, + u_char *buf, char **err) +{ + ngx_ssl_conn_t *ssl_conn; + ngx_connection_t *c; + ngx_ssl_session_t *session; + ngx_http_lua_ssl_ctx_t *cctx; + + c = r->connection; + + if (c == NULL || c->ssl == NULL) { + *err = "bad request"; + return NGX_ERROR; + } + + ssl_conn = c->ssl->connection; + if (ssl_conn == NULL) { + *err = "bad ssl conn"; + return NGX_ERROR; + } + + dd("get cctx session"); + + cctx = ngx_http_lua_ssl_get_ctx(c->ssl->connection); + if (cctx == NULL) { + *err = "bad lua context"; + return NGX_ERROR; + } + + session = cctx->session; + if (session == NULL) { + *err = "bad session in lua context"; + return NGX_ERROR; + } + + if (i2d_SSL_SESSION(session, &buf) == 0) { + *err = "i2d_SSL_SESSION() failed"; + return NGX_ERROR; + } + + return NGX_OK; +} + + +/* return the size of serialized session. */ +int +ngx_http_lua_ffi_ssl_get_serialized_session_size(ngx_http_request_t *r, + char **err) +{ + int len; + ngx_ssl_conn_t *ssl_conn; + ngx_connection_t *c; + ngx_ssl_session_t *session; + ngx_http_lua_ssl_ctx_t *cctx; + + c = r->connection; + + if (c == NULL || c->ssl == NULL) { + *err = "bad request"; + return NGX_ERROR; + } + + ssl_conn = c->ssl->connection; + if (ssl_conn == NULL) { + *err = "bad ssl conn"; + return NGX_ERROR; + } + + dd("get cctx session size"); + cctx = ngx_http_lua_ssl_get_ctx(c->ssl->connection); + if (cctx == NULL) { + *err = "bad lua context"; + return NGX_ERROR; + } + + session = cctx->session; + if (session == NULL) { + *err = "bad session in lua context"; + return NGX_ERROR; + } + + len = i2d_SSL_SESSION(session, NULL); + if (len == 0) { + *err = "i2d_SSL_SESSION() failed"; + return NGX_ERROR; + } + + return len; +} + + +/* serialize the session id from lua context into buf. + * the memory allocation of buf should be handled externally. */ +int +ngx_http_lua_ffi_ssl_get_session_id(ngx_http_request_t *r, + u_char *buf, char **err) +{ + int id_len; + u_char *id; + ngx_ssl_conn_t *ssl_conn; + ngx_connection_t *c; + ngx_http_lua_ssl_ctx_t *cctx; + + c = r->connection; + + if (c == NULL || c->ssl == NULL) { + *err = "bad request"; + return NGX_ERROR; + } + + ssl_conn = c->ssl->connection; + if (ssl_conn == NULL) { + *err = "bad ssl conn"; + return NGX_ERROR; + } + + dd("get cctx session"); + cctx = ngx_http_lua_ssl_get_ctx(c->ssl->connection); + if (cctx == NULL) { + *err = "bad lua context"; + return NGX_ERROR; + } + + id = cctx->session_id.data; + if (id == NULL) { + *err = "uninitialized session id in lua context"; + return NGX_ERROR; + } + + id_len = cctx->session_id.len; + if (id_len == 0) { + *err = "uninitialized session id len in lua context"; + return NGX_ERROR; + } + + ngx_hex_dump(buf, id, id_len); + + return NGX_OK; +} + + +/* return the size of serialized session id. */ +int +ngx_http_lua_ffi_ssl_get_session_id_size(ngx_http_request_t *r, + char **err) +{ + ngx_ssl_conn_t *ssl_conn; + ngx_connection_t *c; + ngx_http_lua_ssl_ctx_t *cctx; + + c = r->connection; + + if (c == NULL || c->ssl == NULL) { + *err = "bad request"; + return NGX_ERROR; + } + + ssl_conn = c->ssl->connection; + if (ssl_conn == NULL) { + *err = "bad ssl conn"; + return NGX_ERROR; + } + + dd("get cctx session"); + cctx = ngx_http_lua_ssl_get_ctx(c->ssl->connection); + if (cctx == NULL) { + *err = "bad lua context"; + return NGX_ERROR; + } + + if (cctx->session_id.len == 0) { + *err = "uninitialized session id len in lua context"; + return NGX_ERROR; + } + + /* since the session id will be hex dumped to serialize, the serialized + * session will be twice the size of the session id: each byte will be a + * 2-digit hex value. */ + + return 2 * cctx->session_id.len; +} + +#endif /* NGX_LUA_NO_FFI_API */ + + +#endif /* NGX_HTTP_SSL */ diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_ssl_session_storeby.h b/debian/modules/nginx-lua/src/ngx_http_lua_ssl_session_storeby.h new file mode 100644 index 0000000..9bf25ad --- /dev/null +++ b/debian/modules/nginx-lua/src/ngx_http_lua_ssl_session_storeby.h @@ -0,0 +1,34 @@ + +/* + * Copyright (C) Yichun Zhang (agentzh) + */ + + +#ifndef _NGX_HTTP_LUA_SSL_SESSION_STOREBY_H_INCLUDED_ +#define _NGX_HTTP_LUA_SSL_SESSION_STOREBY_H_INCLUDED_ + + +#include "ngx_http_lua_common.h" + + +#if (NGX_HTTP_SSL) +ngx_int_t ngx_http_lua_ssl_sess_store_handler_inline(ngx_http_request_t *r, + ngx_http_lua_srv_conf_t *lscf, lua_State *L); + +ngx_int_t ngx_http_lua_ssl_sess_store_handler_file(ngx_http_request_t *r, + ngx_http_lua_srv_conf_t *lscf, lua_State *L); + +char *ngx_http_lua_ssl_sess_store_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); + +char *ngx_http_lua_ssl_sess_store_by_lua_block(ngx_conf_t *cf, + ngx_command_t *cmd, void *conf); + +int ngx_http_lua_ssl_sess_store_handler(ngx_ssl_conn_t *ssl_conn, + ngx_ssl_session_t *sess); +#endif + + +#endif /* _NGX_HTTP_LUA_SSL_SESSION_STOREBY_H_INCLUDED_ */ + +/* vi:set ft=c ts=4 sw=4 et fdm=marker: */ diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_string.c b/debian/modules/nginx-lua/src/ngx_http_lua_string.c index 241b969..22b4c00 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_string.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_string.c @@ -15,7 +15,7 @@ #include "ngx_http_lua_args.h" #include "ngx_crc32.h" -#if NGX_HAVE_SHA1 +#if (NGX_HAVE_SHA1) #include "ngx_sha1.h" #endif @@ -685,7 +685,7 @@ ngx_http_lua_ffi_md5(const u_char *src, size_t len, u_char *dst) int ngx_http_lua_ffi_sha1_bin(const u_char *src, size_t len, u_char *dst) { -#if NGX_HAVE_SHA1 +#if (NGX_HAVE_SHA1) ngx_sha1_t sha; ngx_sha1_init(&sha); diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_subrequest.c b/debian/modules/nginx-lua/src/ngx_http_lua_subrequest.c index 4f8a753..6f7aa97 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_subrequest.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_subrequest.c @@ -375,7 +375,7 @@ ngx_http_lua_ngx_location_capture_multi(lua_State *L) always_forward_body = lua_toboolean(L, -1); lua_pop(L, 1); - dd("always foward body: %d", always_forward_body); + dd("always forward body: %d", always_forward_body); /* check the "method" option */ diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_timer.c b/debian/modules/nginx-lua/src/ngx_http_lua_timer.c index 96c0ace..04dc9d0 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_timer.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_timer.c @@ -603,7 +603,7 @@ ngx_http_lua_abort_pending_timers(ngx_event_t *ev) cur = ngx_event_timer_rbtree.root; - /* XXX nginx does not guarentee the parent of root is meaningful, + /* XXX nginx does not guarantee the parent of root is meaningful, * so we temporarily override it to simplify tree traversal. */ temp = cur->parent; cur->parent = NULL; diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_util.c b/debian/modules/nginx-lua/src/ngx_http_lua_util.c index 1bd1388..7f59833 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_util.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_util.c @@ -50,6 +50,7 @@ #include "ngx_http_lua_worker.h" #include "ngx_http_lua_socket_tcp.h" #include "ngx_http_lua_ssl_certby.h" +#include "ngx_http_lua_ssl.h" #if 1 @@ -370,37 +371,26 @@ ngx_http_lua_del_thread(ngx_http_request_t *r, lua_State *L, u_char * ngx_http_lua_rebase_path(ngx_pool_t *pool, u_char *src, size_t len) { - u_char *p, *dst; + u_char *p; + ngx_str_t dst; - if (len == 0) { + dst.data = ngx_palloc(pool, len + 1); + if (dst.data == NULL) { return NULL; } - if (src[0] == '/') { - /* being an absolute path already */ - dst = ngx_palloc(pool, len + 1); - if (dst == NULL) { - return NULL; - } - - p = ngx_copy(dst, src, len); - - *p = '\0'; - - return dst; - } - - dst = ngx_palloc(pool, ngx_cycle->prefix.len + len + 1); - if (dst == NULL) { - return NULL; - } - - p = ngx_copy(dst, ngx_cycle->prefix.data, ngx_cycle->prefix.len); - p = ngx_copy(p, src, len); + dst.len = len; + p = ngx_copy(dst.data, src, len); *p = '\0'; - return dst; + if (ngx_get_full_name(pool, (ngx_str_t *) &ngx_cycle->prefix, &dst) + != NGX_OK) + { + return NULL; + } + + return dst.data; } @@ -3291,6 +3281,12 @@ ngx_http_lua_check_broken_connection(ngx_http_request_t *r, ngx_event_t *ev) return NGX_HTTP_CLIENT_CLOSED_REQUEST; } +#if (NGX_HTTP_V2) + if (r->stream) { + return NGX_OK; + } +#endif + #if (NGX_HAVE_KQUEUE) if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { @@ -3547,8 +3543,7 @@ ngx_http_lua_finalize_fake_request(ngx_http_request_t *r, ngx_int_t rc) ngx_connection_t *c; #if (NGX_HTTP_SSL) ngx_ssl_conn_t *ssl_conn; - - ngx_http_lua_ssl_cert_ctx_t *cctx; + ngx_http_lua_ssl_ctx_t *cctx; #endif c = r->connection; @@ -3823,6 +3818,7 @@ ngx_http_lua_create_fake_connection(ngx_pool_t *pool) } c->fd = (ngx_socket_t) -1; + c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1); if (pool) { c->pool = pool; diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_util.h b/debian/modules/nginx-lua/src/ngx_http_lua_util.h index f0e8923..a37852f 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_util.h +++ b/debian/modules/nginx-lua/src/ngx_http_lua_util.h @@ -87,6 +87,10 @@ extern char ngx_http_lua_headers_metatable_key; : (c) == NGX_HTTP_LUA_CONTEXT_INIT_WORKER ? "init_worker_by_lua*" \ : (c) == NGX_HTTP_LUA_CONTEXT_BALANCER ? "balancer_by_lua*" \ : (c) == NGX_HTTP_LUA_CONTEXT_SSL_CERT ? "ssl_certificate_by_lua*" \ + : (c) == NGX_HTTP_LUA_CONTEXT_SSL_SESS_STORE ? \ + "ssl_session_store_by_lua*" \ + : (c) == NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH ? \ + "ssl_session_fetch_by_lua*" \ : "(unknown)") @@ -433,7 +437,6 @@ ngx_http_lua_get_flush_chain(ngx_http_request_t *r, ngx_http_lua_ctx_t *ctx) extern ngx_uint_t ngx_http_lua_location_hash; extern ngx_uint_t ngx_http_lua_content_length_hash; -extern int ngx_http_lua_ssl_ctx_index; #endif /* _NGX_HTTP_LUA_UTIL_H_INCLUDED_ */ diff --git a/debian/modules/nginx-lua/t/009-log.t b/debian/modules/nginx-lua/t/009-log.t index 053dd45..0c6a9a5 100644 --- a/debian/modules/nginx-lua/t/009-log.t +++ b/debian/modules/nginx-lua/t/009-log.t @@ -4,7 +4,7 @@ use Test::Nginx::Socket::Lua; #worker_connections(1014); #master_process_enabled(1); -log_level('debug'); # to ensure any log-level can be outputed +log_level('debug'); # to ensure any log-level can be outputted repeat_each(2); diff --git a/debian/modules/nginx-lua/t/010-request_body.t b/debian/modules/nginx-lua/t/010-request_body.t index d200495..2640a54 100644 --- a/debian/modules/nginx-lua/t/010-request_body.t +++ b/debian/modules/nginx-lua/t/010-request_body.t @@ -4,7 +4,7 @@ use Test::Nginx::Socket::Lua; #worker_connections(1014); #master_process_enabled(1); -log_level('debug'); # to ensure any log-level can be outputed +log_level('debug'); # to ensure any log-level can be outputted repeat_each(2); diff --git a/debian/modules/nginx-lua/t/016-resp-header.t b/debian/modules/nginx-lua/t/016-resp-header.t index b1f5e2a..179b411 100644 --- a/debian/modules/nginx-lua/t/016-resp-header.t +++ b/debian/modules/nginx-lua/t/016-resp-header.t @@ -530,7 +530,7 @@ Hellofoo, baz -=== TEST 27: get non-existant header +=== TEST 27: get non-existent header --- config location /lua { content_by_lua ' @@ -546,7 +546,7 @@ nil -=== TEST 28: get non-existant header +=== TEST 28: get non-existent header --- config location /lua { content_by_lua ' diff --git a/debian/modules/nginx-lua/t/020-subrequest.t b/debian/modules/nginx-lua/t/020-subrequest.t index 88ac1b4..3390d64 100644 --- a/debian/modules/nginx-lua/t/020-subrequest.t +++ b/debian/modules/nginx-lua/t/020-subrequest.t @@ -427,7 +427,7 @@ cached: hello -=== TEST 14: emtpy args option table +=== TEST 14: empty args option table --- config location /foo { echo $query_string; diff --git a/debian/modules/nginx-lua/t/023-rewrite/request_body.t b/debian/modules/nginx-lua/t/023-rewrite/request_body.t index 665d6de..0594001 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/request_body.t +++ b/debian/modules/nginx-lua/t/023-rewrite/request_body.t @@ -3,7 +3,7 @@ use Test::Nginx::Socket::Lua; #worker_connections(1014); #master_process_enabled(1); -log_level('debug'); # to ensure any log-level can be outputed +log_level('debug'); # to ensure any log-level can be outputted repeat_each(2); diff --git a/debian/modules/nginx-lua/t/023-rewrite/subrequest.t b/debian/modules/nginx-lua/t/023-rewrite/subrequest.t index 3c206a8..a307388 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/subrequest.t +++ b/debian/modules/nginx-lua/t/023-rewrite/subrequest.t @@ -409,7 +409,7 @@ cached: hello -=== TEST 14: emtpy args option table +=== TEST 14: empty args option table --- config location /foo { echo $query_string; diff --git a/debian/modules/nginx-lua/t/024-access/request_body.t b/debian/modules/nginx-lua/t/024-access/request_body.t index e4ac161..a6fead2 100644 --- a/debian/modules/nginx-lua/t/024-access/request_body.t +++ b/debian/modules/nginx-lua/t/024-access/request_body.t @@ -3,7 +3,7 @@ use Test::Nginx::Socket::Lua; #worker_connections(1014); #master_process_enabled(1); -log_level('debug'); # to ensure any log-level can be outputed +log_level('debug'); # to ensure any log-level can be outputted repeat_each(2); diff --git a/debian/modules/nginx-lua/t/024-access/subrequest.t b/debian/modules/nginx-lua/t/024-access/subrequest.t index 00c56b8..bfe96d6 100644 --- a/debian/modules/nginx-lua/t/024-access/subrequest.t +++ b/debian/modules/nginx-lua/t/024-access/subrequest.t @@ -409,7 +409,7 @@ cached: hello -=== TEST 14: emtpy args option table +=== TEST 14: empty args option table --- config location /foo { echo $query_string; diff --git a/debian/modules/nginx-lua/t/028-req-header.t b/debian/modules/nginx-lua/t/028-req-header.t index fd13cba..498f777 100644 --- a/debian/modules/nginx-lua/t/028-req-header.t +++ b/debian/modules/nginx-lua/t/028-req-header.t @@ -8,7 +8,7 @@ use Test::Nginx::Socket::Lua; repeat_each(2); -plan tests => repeat_each() * (2 * blocks() + 28); +plan tests => repeat_each() * (2 * blocks() + 30); #no_diff(); #no_long_string(); @@ -1582,3 +1582,43 @@ X-Forwarded-For: 8.8.8.8 Foo: 127.0.0.1 --- no_error_log [error] + + + +=== TEST 52: for bad requests (bad request method letter case) +--- config + error_page 400 = /err; + + location = /err { + content_by_lua_block { + ngx.req.set_header("Foo", "bar") + ngx.say("ok") + } + } +--- raw_request +GeT / HTTP/1.1 +--- response_body +ok +--- no_error_log +[error] +--- no_check_leak + + + +=== TEST 53: for bad requests (bad request method names) +--- config + error_page 400 = /err; + + location = /err { + content_by_lua_block { + ngx.req.set_header("Foo", "bar") + ngx.say("ok") + } + } +--- raw_request +GET x HTTP/1.1 +--- response_body +ok +--- no_error_log +[error] +--- no_check_leak diff --git a/debian/modules/nginx-lua/t/030-uri-args.t b/debian/modules/nginx-lua/t/030-uri-args.t index 2f18ba7..8ee8401 100644 --- a/debian/modules/nginx-lua/t/030-uri-args.t +++ b/debian/modules/nginx-lua/t/030-uri-args.t @@ -276,7 +276,7 @@ done -=== TEST 10: empty key, but non-emtpy values +=== TEST 10: empty key, but non-empty values --- config location /lua { content_by_lua ' @@ -818,7 +818,7 @@ lua hit query args limit 2 -=== TEST 36: max args (limited after an empty key, but non-emtpy values) +=== TEST 36: max args (limited after an empty key, but non-empty values) --- config location /lua { content_by_lua ' diff --git a/debian/modules/nginx-lua/t/031-post-args.t b/debian/modules/nginx-lua/t/031-post-args.t index 4f8b9d7..c2b6b8f 100644 --- a/debian/modules/nginx-lua/t/031-post-args.t +++ b/debian/modules/nginx-lua/t/031-post-args.t @@ -152,7 +152,7 @@ lua hit query args limit 2 -=== TEST 6: max args (limited after an empty key, but non-emtpy values) +=== TEST 6: max args (limited after an empty key, but non-empty values) --- config location /lua { content_by_lua ' diff --git a/debian/modules/nginx-lua/t/043-shdict.t b/debian/modules/nginx-lua/t/043-shdict.t index cd160f7..a21a34a 100644 --- a/debian/modules/nginx-lua/t/043-shdict.t +++ b/debian/modules/nginx-lua/t/043-shdict.t @@ -816,7 +816,7 @@ foo = hello -=== TEST 31: incr key (key exists) +=== TEST 31: replace key (key exists) --- http_config lua_shared_dict dogs 1m; --- config @@ -950,7 +950,7 @@ foo = 10534 -=== TEST 36: replace key (key not exists) +=== TEST 36: incr key (key not exists) --- http_config lua_shared_dict dogs 1m; --- config @@ -973,7 +973,7 @@ foo = nil -=== TEST 37: replace key (key expired) +=== TEST 37: incr key (key expired) --- http_config lua_shared_dict dogs 1m; --- config diff --git a/debian/modules/nginx-lua/t/062-count.t b/debian/modules/nginx-lua/t/062-count.t index a24611c..e16291b 100644 --- a/debian/modules/nginx-lua/t/062-count.t +++ b/debian/modules/nginx-lua/t/062-count.t @@ -283,7 +283,7 @@ n = 4 --- request GET /test --- response_body -n = 13 +n = 18 --- no_error_log [error] diff --git a/debian/modules/nginx-lua/t/068-socket-keepalive.t b/debian/modules/nginx-lua/t/068-socket-keepalive.t index a005620..f052e9a 100644 --- a/debian/modules/nginx-lua/t/068-socket-keepalive.t +++ b/debian/modules/nginx-lua/t/068-socket-keepalive.t @@ -4,7 +4,7 @@ use Test::Nginx::Socket::Lua; #repeat_each(2); -plan tests => repeat_each() * (blocks() * 5 + 7); +plan tests => repeat_each() * (blocks() * 5 + 9); our $HtmlDir = html_dir; @@ -1476,3 +1476,78 @@ done --- no_error_log [error] + + +=== TEST 24: setkeepalive() with explicit nil args +--- config + server_tokens off; + location /t { + lua_socket_keepalive_timeout 100ms; + + set $port $TEST_NGINX_SERVER_PORT; + content_by_lua_block { + local port = ngx.var.port + + local sock = ngx.socket.tcp() + + local ok, err = sock:connect("127.0.0.1", port) + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local req = "GET /foo HTTP/1.1\r\nHost: localhost\r\nConnection: keepalive\r\n\r\n" + + local bytes, err = sock:send(req) + if not bytes then + ngx.say("failed to send request: ", err) + return + end + + ngx.say("request sent: ", bytes) + + local reader = sock:receiveuntil("\r\n0\r\n\r\n") + local data, res = reader() + + if not data then + ngx.say("failed to receive response body: ", err) + return + end + + ngx.say("received response of ", #data, " bytes") + + local ok, err = sock:setkeepalive(nil, nil) + if not ok then + ngx.say("failed to set reusable: ", err) + end + + ngx.location.capture("/sleep") + + ngx.say("done") + } + } + + location /foo { + echo foo; + } + + location /sleep { + echo_sleep 1; + } +--- request +GET /t +--- response_body +connected: 1 +request sent: 61 +received response of 156 bytes +done +--- no_error_log +[error] +--- error_log eval +["lua tcp socket keepalive close handler", +"lua tcp socket keepalive: free connection pool for ", +"lua tcp socket keepalive timeout: 100 ms", +qr/lua tcp socket connection pool size: 30\b/] +--- timeout: 4 diff --git a/debian/modules/nginx-lua/t/070-sha1.t b/debian/modules/nginx-lua/t/070-sha1.t index 8648a8c..62823a9 100644 --- a/debian/modules/nginx-lua/t/070-sha1.t +++ b/debian/modules/nginx-lua/t/070-sha1.t @@ -7,7 +7,7 @@ log_level('warn'); repeat_each(2); -plan tests => repeat_each() * (blocks() * 2 + 1); +plan tests => repeat_each() * (blocks() * 3); #no_diff(); #no_long_string(); @@ -24,6 +24,8 @@ __DATA__ GET /sha1 --- response_body qvTGHdzF6KLavt4PO0gs2a6pQ00= +--- no_error_log +[error] @@ -36,6 +38,8 @@ qvTGHdzF6KLavt4PO0gs2a6pQ00= GET /sha1 --- response_body 2jmj7l5rSw0yVb/vlWAYkK/YBwk= +--- no_error_log +[error] @@ -48,6 +52,8 @@ GET /sha1 GET /sha1 --- response_body 2jmj7l5rSw0yVb/vlWAYkK/YBwk= +--- no_error_log +[error] @@ -62,4 +68,3 @@ GET /sha1 zgmxJ9SPg4aKRWReJG07UvS97L4= --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/129-ssl-socket.t b/debian/modules/nginx-lua/t/129-ssl-socket.t index c19853d..9da9a5c 100644 --- a/debian/modules/nginx-lua/t/129-ssl-socket.t +++ b/debian/modules/nginx-lua/t/129-ssl-socket.t @@ -86,7 +86,7 @@ __DATA__ local line, err = sock:receive() if not line then - ngx.say("failed to recieve response status line: ", err) + ngx.say("failed to receive response status line: ", err) return end @@ -162,7 +162,7 @@ SSL reused session local line, err = sock:receive() if not line then - ngx.say("failed to recieve response status line: ", err) + ngx.say("failed to receive response status line: ", err) return end @@ -239,7 +239,7 @@ SSL reused session local line, err = sock:receive() if not line then - ngx.say("failed to recieve response status line: ", err) + ngx.say("failed to receive response status line: ", err) return end @@ -320,7 +320,7 @@ SSL reused session local line, err = sock:receive() if not line then - ngx.say("failed to recieve response status line: ", err) + ngx.say("failed to receive response status line: ", err) return end @@ -412,7 +412,7 @@ The certificate for "blah.agentzh.org" does not contain the name "blah.agentzh.o local line, err = sock:receive() if not line then - ngx.say("failed to recieve response status line: ", err) + ngx.say("failed to receive response status line: ", err) return end @@ -492,7 +492,7 @@ The certificate for "blah.agentzh.org" does not contain the name "blah.agentzh.o local line, err = sock:receive() if not line then - ngx.say("failed to recieve response status line: ", err) + ngx.say("failed to receive response status line: ", err) return end @@ -569,7 +569,7 @@ SSL reused session local line, err = sock:receive() if not line then - ngx.say("failed to recieve response status line: ", err) + ngx.say("failed to receive response status line: ", err) return end @@ -650,7 +650,7 @@ SSL reused session local line, err = sock:receive() if not line then - ngx.say("failed to recieve response status line: ", err) + ngx.say("failed to receive response status line: ", err) return end @@ -734,7 +734,7 @@ SSL reused session local line, err = sock:receive() if not line then - ngx.say("failed to recieve response status line: ", err) + ngx.say("failed to receive response status line: ", err) return end @@ -813,7 +813,7 @@ SSL reused session local line, err = sock:receive() if not line then - ngx.say("failed to recieve response status line: ", err) + ngx.say("failed to receive response status line: ", err) return end @@ -902,7 +902,7 @@ SSL reused session local line, err = sock:receive() if not line then - ngx.say("failed to recieve response status line: ", err) + ngx.say("failed to receive response status line: ", err) return end @@ -995,7 +995,7 @@ SSL reused session local line, err = sock:receive() if not line then - ngx.say("failed to recieve response status line: ", err) + ngx.say("failed to receive response status line: ", err) return end @@ -1072,7 +1072,7 @@ SSL reused session local line, err = sock:receive() if not line then - ngx.say("failed to recieve response status line: ", err) + ngx.say("failed to receive response status line: ", err) return end @@ -1156,7 +1156,7 @@ SSL reused session local line, err = sock:receive() if not line then - ngx.say("failed to recieve response status line: ", err) + ngx.say("failed to receive response status line: ", err) return end @@ -1236,7 +1236,7 @@ SSL reused session local line, err = sock:receive() if not line then - ngx.say("failed to recieve response status line: ", err) + ngx.say("failed to receive response status line: ", err) return end @@ -1316,7 +1316,7 @@ SSL reused session local line, err = sock:receive() if not line then - ngx.say("failed to recieve response status line: ", err) + ngx.say("failed to receive response status line: ", err) return end @@ -1396,7 +1396,7 @@ SSL reused session local line, err = sock:receive() if not line then - ngx.say("failed to recieve response status line: ", err) + ngx.say("failed to receive response status line: ", err) return end @@ -1684,7 +1684,7 @@ attempt to call method 'sslhandshake' (a nil value) while true do local line, err = sock:receive() if not line then - -- ngx.say("failed to recieve response status line: ", err) + -- ngx.say("failed to receive response status line: ", err) break end @@ -1789,7 +1789,7 @@ SSL reused session while true do local line, err = sock:receive() if not line then - -- ngx.say("failed to recieve response status line: ", err) + -- ngx.say("failed to receive response status line: ", err) break end @@ -1893,7 +1893,7 @@ SSL reused session while true do local line, err = sock:receive() if not line then - -- ngx.say("failed to recieve response status line: ", err) + -- ngx.say("failed to receive response status line: ", err) break end @@ -1987,7 +1987,7 @@ SSL reused session while true do local line, err = sock:receive() if not line then - -- ngx.say("failed to recieve response status line: ", err) + -- ngx.say("failed to receive response status line: ", err) break end @@ -2071,7 +2071,7 @@ SSL reused session local line, err = sock:receive() if not line then - ngx.say("failed to recieve response status line: ", err) + ngx.say("failed to receive response status line: ", err) return end @@ -2444,7 +2444,7 @@ SSL reused session while true do local line, err = sock:receive() if not line then - -- ngx.say("failed to recieve response status line: ", err) + -- ngx.say("failed to receive response status line: ", err) break end @@ -2549,7 +2549,7 @@ SSL reused session while true do local line, err = sock:receive() if not line then - -- ngx.say("failed to recieve response status line: ", err) + -- ngx.say("failed to receive response status line: ", err) break end diff --git a/debian/modules/nginx-lua/t/132-lua-blocks.t b/debian/modules/nginx-lua/t/132-lua-blocks.t index e2933e9..a57d701 100644 --- a/debian/modules/nginx-lua/t/132-lua-blocks.t +++ b/debian/modules/nginx-lua/t/132-lua-blocks.t @@ -588,3 +588,19 @@ GET /test3 "3: " . ("this is just some random filler to cause an error" x 20) . "\n" --- no_error_log [error] + + + +=== TEST 23: lexer should not stop lexing in the middle of a value +--- config + location /t { + content_by_lua_block { + ngx.say("} }") + ngx.say("} }") + } + } +--- request +GET /t +--- response_body_like: } +--- no_error_log +[error] diff --git a/debian/modules/nginx-lua/t/133-worker-count.t b/debian/modules/nginx-lua/t/133-worker-count.t index c97f6b4..3e03ecc 100644 --- a/debian/modules/nginx-lua/t/133-worker-count.t +++ b/debian/modules/nginx-lua/t/133-worker-count.t @@ -50,3 +50,23 @@ GET /lua workers: 1 --- no_error_log [error] + + + +=== TEST 3: init_worker_by_lua +--- http_config + init_worker_by_lua_block { + init_worker_count = ngx.worker.count() + } +--- config + location /lua { + content_by_lua_block { + ngx.say("workers: ", init_worker_count) + } + } +--- request +GET /lua +--- response_body +workers: 1 +--- no_error_log +[error] diff --git a/debian/modules/nginx-lua/t/138-balancer.t b/debian/modules/nginx-lua/t/138-balancer.t index e44cf8e..8d45c24 100644 --- a/debian/modules/nginx-lua/t/138-balancer.t +++ b/debian/modules/nginx-lua/t/138-balancer.t @@ -9,7 +9,7 @@ use Test::Nginx::Socket::Lua; repeat_each(2); -plan tests => repeat_each() * (blocks() * 4 + 8); +plan tests => repeat_each() * (blocks() * 4 + 9); #no_diff(); no_long_string(); @@ -405,3 +405,29 @@ ctx counter: nil ctx counter: nil --- no_error_log [error] + + + +=== TEST 14: ngx.log(ngx.ERR, ...) github #816 +--- http_config + upstream backend { + server 0.0.0.1; + balancer_by_lua_block { + ngx.log(ngx.ERR, "hello from balancer by lua!") + } + } +--- config + location = /t { + proxy_pass http://backend; + } +--- request + GET /t +--- response_body_like: 502 Bad Gateway +--- error_code: 502 +--- error_log eval +[ +'[lua] balancer_by_lua:2: hello from balancer by lua! while connecting to upstream,', +qr{\[crit\] .*? connect\(\) to 0\.0\.0\.1:80 failed .*?, upstream: "http://0\.0\.0\.1:80/t"}, +] +--- no_error_log +[warn] diff --git a/debian/modules/nginx-lua/t/139-ssl-cert-by.t b/debian/modules/nginx-lua/t/139-ssl-cert-by.t index 9297a0d..b9fd60d 100644 --- a/debian/modules/nginx-lua/t/139-ssl-cert-by.t +++ b/debian/modules/nginx-lua/t/139-ssl-cert-by.t @@ -82,7 +82,7 @@ __DATA__ while true do local line, err = sock:receive() if not line then - -- ngx.say("failed to recieve response status line: ", err) + -- ngx.say("failed to receive response status line: ", err) break end @@ -180,7 +180,7 @@ ssl_certificate_by_lua:1: ssl cert by lua is running! while true do local line, err = sock:receive() if not line then - -- ngx.say("failed to recieve response status line: ", err) + -- ngx.say("failed to receive response status line: ", err) break end @@ -285,7 +285,7 @@ qr/elapsed in ssl cert by lua: 0.(?:09|1[01])\d+,/, while true do local line, err = sock:receive() if not line then - -- ngx.say("failed to recieve response status line: ", err) + -- ngx.say("failed to receive response status line: ", err) break end @@ -403,7 +403,7 @@ my timer run! while true do local line, err = sock:receive() if not line then - -- ngx.say("failed to recieve response status line: ", err) + -- ngx.say("failed to receive response status line: ", err) break end @@ -1108,7 +1108,7 @@ print("ssl cert by lua is running!") while true do local line, err = sock:receive() if not line then - -- ngx.say("failed to recieve response status line: ", err) + -- ngx.say("failed to receive response status line: ", err) break end @@ -1219,7 +1219,7 @@ a.lua:1: ssl cert by lua is running! while true do local line, err = sock:receive() if not line then - -- ngx.say("failed to recieve response status line: ", err) + -- ngx.say("failed to receive response status line: ", err) break end @@ -1343,7 +1343,7 @@ lua ssl server name: "test.com" while true do local line, err = sock:receive() if not line then - -- ngx.say("failed to recieve response status line: ", err) + -- ngx.say("failed to receive response status line: ", err) break end @@ -1439,7 +1439,7 @@ GitHub openresty/lua-resty-core#42 while true do local line, err = sock:receive() if not line then - -- ngx.say("failed to recieve response status line: ", err) + -- ngx.say("failed to receive response status line: ", err) break end @@ -1475,3 +1475,102 @@ ssl_certificate_by_lua:1: ssl cert by lua is running! --- no_error_log [error] [alert] + + + +=== TEST 18: simple logging (syslog) +github issue #723 +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + + error_log syslog:server=127.0.0.1:12345 debug; + + ssl_certificate_by_lua_block { print("ssl cert by lua is running!") } + ssl_certificate ../../cert/test.crt; + ssl_certificate_key ../../cert/test.key; + + server_tokens off; + location /foo { + default_type 'text/plain'; + content_by_lua_block { ngx.status = 201 ngx.say("foo") ngx.exit(201) } + more_clear_headers Date; + } + } +--- config + server_tokens off; + lua_ssl_trusted_certificate ../../cert/test.crt; + + location /t { + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(2000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(nil, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + local req = "GET /foo HTTP/1.0\r\nHost: test.com\r\nConnection: close\r\n\r\n" + local bytes, err = sock:send(req) + if not bytes then + ngx.say("failed to send http request: ", err) + return + end + + ngx.say("sent http request: ", bytes, " bytes.") + + while true do + local line, err = sock:receive() + if not line then + -- ngx.say("failed to receive response status line: ", err) + break + end + + ngx.say("received: ", line) + end + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: userdata +sent http request: 56 bytes. +received: HTTP/1.1 201 Created +received: Server: nginx +received: Content-Type: text/plain +received: Content-Length: 4 +received: Connection: close +received: +received: foo +close: 1 nil + +--- error_log eval +[ +qr/\[error\] .*? send\(\) failed/, +'lua ssl server name: "test.com"', +] +--- no_error_log +[alert] +ssl_certificate_by_lua:1: ssl cert by lua is running! diff --git a/debian/modules/nginx-lua/t/140-ssl-c-api.t b/debian/modules/nginx-lua/t/140-ssl-c-api.t index 4ecc2cd..44ad93d 100644 --- a/debian/modules/nginx-lua/t/140-ssl-c-api.t +++ b/debian/modules/nginx-lua/t/140-ssl-c-api.t @@ -22,6 +22,57 @@ log_level 'debug'; no_long_string(); #no_diff(); +add_block_preprocessor(sub { + my $block = shift; + + if (!defined $block->user_files) { + $block->set_value("user_files", <<'_EOC_'); +>>> defines.lua +local ffi = require "ffi" + +ffi.cdef[[ + int ngx_http_lua_ffi_cert_pem_to_der(const unsigned char *pem, + size_t pem_len, unsigned char *der, char **err); + + int ngx_http_lua_ffi_priv_key_pem_to_der(const unsigned char *pem, + size_t pem_len, unsigned char *der, char **err); + + int ngx_http_lua_ffi_ssl_set_der_certificate(void *r, + const char *data, size_t len, char **err); + + int ngx_http_lua_ffi_ssl_set_der_private_key(void *r, + const char *data, size_t len, char **err); + + int ngx_http_lua_ffi_ssl_clear_certs(void *r, char **err); + + void *ngx_http_lua_ffi_parse_pem_cert(const unsigned char *pem, + size_t pem_len, char **err); + + void *ngx_http_lua_ffi_parse_pem_priv_key(const unsigned char *pem, + size_t pem_len, char **err); + + int ngx_http_lua_ffi_set_cert(void *r, + void *cdata, char **err); + + int ngx_http_lua_ffi_set_priv_key(void *r, + void *cdata, char **err); + + void ngx_http_lua_ffi_free_cert(void *cdata); + + void ngx_http_lua_ffi_free_priv_key(void *cdata); + + int ngx_http_lua_ffi_ssl_clear_certs(void *r, char **err); +]] +_EOC_ + } + + my $http_config = $block->http_config || ''; + $http_config .= <<'_EOC_'; +lua_package_path "$prefix/html/?.lua;;"; +_EOC_ + $block->set_value("http_config", $http_config); +}); + run_tests(); __DATA__ @@ -35,24 +86,9 @@ __DATA__ ssl_certificate_by_lua_block { collectgarbage() + require "defines" local ffi = require "ffi" - ffi.cdef[[ - int ngx_http_lua_ffi_cert_pem_to_der(const unsigned char *pem, - size_t pem_len, unsigned char *der, char **err); - - int ngx_http_lua_ffi_priv_key_pem_to_der(const unsigned char *pem, - size_t pem_len, unsigned char *der, char **err); - - int ngx_http_lua_ffi_ssl_set_der_certificate(void *r, - const char *data, size_t len, char **err); - - int ngx_http_lua_ffi_ssl_set_der_private_key(void *r, - const char *data, size_t len, char **err); - - int ngx_http_lua_ffi_ssl_clear_certs(void *r, char **err); - ]] - local errmsg = ffi.new("char *[1]") local r = getfenv(0).__ngx_req @@ -157,7 +193,7 @@ __DATA__ while true do local line, err = sock:receive() if not line then - -- ngx.say("failed to recieve response status line: ", err) + -- ngx.say("failed to receive response status line: ", err) break end @@ -205,22 +241,7 @@ lua ssl server name: "test.com" collectgarbage() local ffi = require "ffi" - - ffi.cdef[[ - int ngx_http_lua_ffi_cert_pem_to_der(const unsigned char *pem, - size_t pem_len, unsigned char *der, char **err); - - int ngx_http_lua_ffi_priv_key_pem_to_der(const unsigned char *pem, - size_t pem_len, unsigned char *der, char **err); - - int ngx_http_lua_ffi_ssl_set_der_certificate(void *r, - const char *data, size_t len, char **err); - - int ngx_http_lua_ffi_ssl_set_der_private_key(void *r, - const char *data, size_t len, char **err); - - int ngx_http_lua_ffi_ssl_clear_certs(void *r, char **err); - ]] + require "defines" local errmsg = ffi.new("char *[1]") @@ -326,7 +347,7 @@ lua ssl server name: "test.com" while true do local line, err = sock:receive() if not line then - -- ngx.say("failed to recieve response status line: ", err) + -- ngx.say("failed to receive response status line: ", err) break end @@ -374,14 +395,7 @@ lua ssl server name: "test.com" collectgarbage() local ffi = require "ffi" - - ffi.cdef[[ - int ngx_http_lua_ffi_cert_pem_to_der(const unsigned char *pem, - size_t pem_len, unsigned char *der, char **err); - - int ngx_http_lua_ffi_priv_key_pem_to_der(const unsigned char *pem, - size_t pem_len, unsigned char *der, char **err); - ]] + require "defines" local errmsg = ffi.new("char *[1]") @@ -461,7 +475,7 @@ lua ssl server name: "test.com" while true do local line, err = sock:receive() if not line then - -- ngx.say("failed to recieve response status line: ", err) + -- ngx.say("failed to receive response status line: ", err) break end @@ -493,7 +507,307 @@ close: 1 nil --- error_log lua ssl server name: "test.com" failed to parse PEM cert: PEM_read_bio_X509_AUX() -failed to parse PEM priv key: PEM_read_bio_PrivateKey failed +failed to parse PEM priv key: PEM_read_bio_PrivateKey() failed --- no_error_log [alert] + + + +=== TEST 4: simple cert + private key cdata +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + + ssl_certificate_by_lua_block { + collectgarbage() + + local ffi = require "ffi" + require "defines" + + local errmsg = ffi.new("char *[1]") + + local r = getfenv(0).__ngx_req + if not r then + ngx.log(ngx.ERR, "no request found") + return + end + + ffi.C.ngx_http_lua_ffi_ssl_clear_certs(r, errmsg) + + local f = assert(io.open("t/cert/test.crt", "rb")) + local cert_data = f:read("*all") + f:close() + + local cert = ffi.C.ngx_http_lua_ffi_parse_pem_cert(cert_data, #cert_data, errmsg) + if not cert then + ngx.log(ngx.ERR, "failed to parse PEM cert: ", + ffi.string(errmsg[0])) + return + end + + local rc = ffi.C.ngx_http_lua_ffi_set_cert(r, cert, errmsg) + if rc ~= 0 then + ngx.log(ngx.ERR, "failed to set cdata cert: ", + ffi.string(errmsg[0])) + return + end + + ffi.C.ngx_http_lua_ffi_free_cert(cert) + + f = assert(io.open("t/cert/test.key", "rb")) + local pkey_data = f:read("*all") + f:close() + + local pkey = ffi.C.ngx_http_lua_ffi_parse_pem_priv_key(pkey_data, #pkey_data, errmsg) + if not pkey then + ngx.log(ngx.ERR, "failed to parse PEM priv key: ", + ffi.string(errmsg[0])) + return + end + + local rc = ffi.C.ngx_http_lua_ffi_set_priv_key(r, pkey, errmsg) + if rc ~= 0 then + ngx.log(ngx.ERR, "failed to set cdata priv key: ", + ffi.string(errmsg[0])) + return + end + + ffi.C.ngx_http_lua_ffi_free_priv_key(pkey) + } + + ssl_certificate ../../cert/test2.crt; + ssl_certificate_key ../../cert/test2.key; + + server_tokens off; + location /foo { + default_type 'text/plain'; + content_by_lua_block { ngx.status = 201 ngx.say("foo") ngx.exit(201) } + more_clear_headers Date; + } + } +--- config + server_tokens off; + lua_ssl_trusted_certificate ../../cert/test.crt; + + location /t { + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(2000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(nil, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + local req = "GET /foo HTTP/1.0\r\nHost: test.com\r\nConnection: close\r\n\r\n" + local bytes, err = sock:send(req) + if not bytes then + ngx.say("failed to send http request: ", err) + return + end + + ngx.say("sent http request: ", bytes, " bytes.") + + while true do + local line, err = sock:receive() + if not line then + -- ngx.say("failed to recieve response status line: ", err) + break + end + + ngx.say("received: ", line) + end + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: userdata +sent http request: 56 bytes. +received: HTTP/1.1 201 Created +received: Server: nginx +received: Content-Type: text/plain +received: Content-Length: 4 +received: Connection: close +received: +received: foo +close: 1 nil + +--- error_log +lua ssl server name: "test.com" + +--- no_error_log +[error] +[alert] + + + +=== TEST 5: ECDSA cert + private key cdata +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + + ssl_certificate_by_lua_block { + collectgarbage() + + local ffi = require "ffi" + require "defines" + + local errmsg = ffi.new("char *[1]") + + local r = getfenv(0).__ngx_req + if not r then + ngx.log(ngx.ERR, "no request found") + return + end + + ffi.C.ngx_http_lua_ffi_ssl_clear_certs(r, errmsg) + + local f = assert(io.open("t/cert/test_ecdsa.crt", "rb")) + local cert_data = f:read("*all") + f:close() + + local cert = ffi.C.ngx_http_lua_ffi_parse_pem_cert(cert_data, #cert_data, errmsg) + if not cert then + ngx.log(ngx.ERR, "failed to parse PEM cert: ", + ffi.string(errmsg[0])) + return + end + + local rc = ffi.C.ngx_http_lua_ffi_set_cert(r, cert, errmsg) + if rc ~= 0 then + ngx.log(ngx.ERR, "failed to set cdata cert: ", + ffi.string(errmsg[0])) + return + end + + ffi.C.ngx_http_lua_ffi_free_cert(cert) + + f = assert(io.open("t/cert/test_ecdsa.key", "rb")) + local pkey_data = f:read("*all") + f:close() + + local pkey = ffi.C.ngx_http_lua_ffi_parse_pem_priv_key(pkey_data, #pkey_data, errmsg) + if not pkey then + ngx.log(ngx.ERR, "failed to parse PEM priv key: ", + ffi.string(errmsg[0])) + return + end + + local rc = ffi.C.ngx_http_lua_ffi_set_priv_key(r, pkey, errmsg) + if rc ~= 0 then + ngx.log(ngx.ERR, "failed to set cdata priv key: ", + ffi.string(errmsg[0])) + return + end + + ffi.C.ngx_http_lua_ffi_free_priv_key(pkey) + } + + ssl_certificate ../../cert/test2.crt; + ssl_certificate_key ../../cert/test2.key; + + server_tokens off; + location /foo { + default_type 'text/plain'; + content_by_lua_block { ngx.status = 201 ngx.say("foo") ngx.exit(201) } + more_clear_headers Date; + } + } +--- config + server_tokens off; + lua_ssl_trusted_certificate ../../cert/test_ecdsa.crt; + + location /t { + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(2000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(nil, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + local req = "GET /foo HTTP/1.0\r\nHost: test.com\r\nConnection: close\r\n\r\n" + local bytes, err = sock:send(req) + if not bytes then + ngx.say("failed to send http request: ", err) + return + end + + ngx.say("sent http request: ", bytes, " bytes.") + + while true do + local line, err = sock:receive() + if not line then + -- ngx.say("failed to recieve response status line: ", err) + break + end + + ngx.say("received: ", line) + end + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: userdata +sent http request: 56 bytes. +received: HTTP/1.1 201 Created +received: Server: nginx +received: Content-Type: text/plain +received: Content-Length: 4 +received: Connection: close +received: +received: foo +close: 1 nil + +--- error_log +lua ssl server name: "test.com" + +--- no_error_log +[error] +[alert] diff --git a/debian/modules/nginx-lua/t/142-ssl-session-store.t b/debian/modules/nginx-lua/t/142-ssl-session-store.t new file mode 100644 index 0000000..da84a8d --- /dev/null +++ b/debian/modules/nginx-lua/t/142-ssl-session-store.t @@ -0,0 +1,750 @@ +# vim:set ft= ts=4 sw=4 et fdm=marker: + +use Test::Nginx::Socket::Lua; +use Cwd qw(abs_path realpath); +use File::Basename; + +repeat_each(3); + +plan tests => repeat_each() * (blocks() * 6 + 2); + +$ENV{TEST_NGINX_HTML_DIR} ||= html_dir(); + +$ENV{TEST_NGINX_MEMCACHED_PORT} ||= 11211; +$ENV{TEST_NGINX_RESOLVER} ||= '8.8.8.8'; +$ENV{TEST_NGINX_CERT_DIR} ||= dirname(realpath(abs_path(__FILE__))); + +#log_level 'warn'; +log_level 'debug'; + +no_long_string(); +#no_diff(); + +run_tests(); + +__DATA__ + +=== TEST 1: simple logging +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + ssl_session_store_by_lua_block { print("ssl session store by lua is running!") } + ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; + ssl_protocols SSLv3; + + server_tokens off; + } +--- config + server_tokens off; + resolver $TEST_NGINX_RESOLVER; + lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + + location /t { + set $port $TEST_NGINX_MEMCACHED_PORT; + + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(5000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(nil, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: userdata +close: 1 nil + +--- error_log +lua ssl server name: "test.com" +ssl_session_store_by_lua_block:1: ssl session store by lua is running! + +--- no_error_log +[error] +[alert] + + + +=== TEST 2: sleep is not allowed +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + ssl_session_store_by_lua_block { + local begin = ngx.now() + ngx.sleep(0.1) + print("elapsed in ssl store session by lua: ", ngx.now() - begin) + } + ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; + ssl_protocols SSLv3; + + server_tokens off; + } +--- config + server_tokens off; + resolver $TEST_NGINX_RESOLVER; + lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + + location /t { + set $port $TEST_NGINX_MEMCACHED_PORT; + + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(5000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(nil, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: userdata +close: 1 nil + +--- error_log +lua ssl server name: "test.com" +API disabled in the context of ssl_session_store_by_lua* + +--- no_error_log +[alert] +[emerg] + + + +=== TEST 3: timer +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; + ssl_session_store_by_lua_block { + local function f() + print("my timer run!") + end + local ok, err = ngx.timer.at(0, f) + if not ok then + ngx.log(ngx.ERR, "failed to create timer: ", err) + return + end + } + ssl_protocols SSLv3; + + server_tokens off; + } +--- config + server_tokens off; + resolver $TEST_NGINX_RESOLVER; + lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + + location /t { + set $port $TEST_NGINX_MEMCACHED_PORT; + + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(5000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(nil, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: userdata +close: 1 nil + +--- error_log +lua ssl server name: "test.com" +my timer run! + +--- no_error_log +[error] +[alert] + + + +=== TEST 4: cosocket is not allowed +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + ssl_session_store_by_lua_block { + local sock = ngx.socket.tcp() + + sock:settimeout(5000) + + local ok, err = sock:connect("127.0.0.1", $TEST_NGINX_MEMCACHED_PORT) + if not ok then + ngx.log(ngx.ERR, "failed to connect to memc: ", err) + return + end + + local bytes, err = sock:send("flush_all\\r\\n") + if not bytes then + ngx.log(ngx.ERR, "failed to send flush_all command: ", err) + return + end + + local res, err = sock:receive() + if not res then + ngx.log(ngx.ERR, "failed to receive memc reply: ", err) + return + end + + print("received memc reply: ", res) + } + + ssl_protocols SSLv3; + ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; + + server_tokens off; + } +--- config + server_tokens off; + resolver $TEST_NGINX_RESOLVER; + lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + + location /t { + set $port $TEST_NGINX_MEMCACHED_PORT; + + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(5000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(nil, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: userdata +close: 1 nil + +--- error_log +lua ssl server name: "test.com" +API disabled in the context of ssl_session_store_by_lua* + +--- no_error_log +[alert] +[emerg] + + + +=== TEST 5: ngx.exit(0) - no yield +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + ssl_session_store_by_lua_block { + ngx.exit(0) + } + ssl_protocols SSLv3; + ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; + + server_tokens off; + } +--- config + server_tokens off; + resolver $TEST_NGINX_RESOLVER; + lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + lua_ssl_verify_depth 3; + + location /t { + set $port $TEST_NGINX_MEMCACHED_PORT; + + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(5000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(package.loaded.session, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + package.loaded.session = sess + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: userdata +close: 1 nil + +--- error_log +lua exit with code 0 + +--- no_error_log +[error] +[alert] +[emerg] + + + +=== TEST 6: ngx.exit(ngx.ERROR) - no yield +ngx.exit does not yield and the error code is eaten. +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + ssl_session_store_by_lua_block { + ngx.exit(ngx.ERROR) + } + ssl_protocols SSLv3; + ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; + + server_tokens off; + } +--- config + server_tokens off; + resolver $TEST_NGINX_RESOLVER; + lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + lua_ssl_verify_depth 3; + + location /t { + set $port $TEST_NGINX_MEMCACHED_PORT; + + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(5000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(package.loaded.session, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + package.loaded.session = sess + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: userdata +close: 1 nil + +--- error_log +lua exit with code -1 +ssl_session_store_by_lua*: handler return value: 0, sess new cb exit code: 0 + +--- no_error_log +[error] +[alert] +[emerg] + + + +=== TEST 7: lua exception - no yield +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + ssl_session_store_by_lua_block { + error("bad bad bad") + ngx.log(ngx.ERR, "should never reached here...") + } + ssl_protocols SSLv3; + ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; + + server_tokens off; + } +--- config + server_tokens off; + resolver $TEST_NGINX_RESOLVER; + lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + lua_ssl_verify_depth 3; + + location /t { + set $port $TEST_NGINX_MEMCACHED_PORT; + + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(5000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(nil, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: userdata +close: 1 nil + +--- error_log +failed to run session_store_by_lua*: ssl_session_store_by_lua_block:2: bad bad bad + +--- no_error_log +should never reached here +[alert] +[emerg] + + + +=== TEST 8: get phase +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + ssl_session_store_by_lua_block { + print("get_phase: ", ngx.get_phase()) + } + ssl_protocols SSLv3; + ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; + + server_tokens off; + } +--- config + server_tokens off; + resolver $TEST_NGINX_RESOLVER; + lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + lua_ssl_verify_depth 3; + + location /t { + set $port $TEST_NGINX_MEMCACHED_PORT; + + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(5000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(nil, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: userdata +close: 1 nil + +--- error_log +get_phase: ssl_session_store + +--- no_error_log +[alert] +[emerg] +[error] + + + +=== TEST 9: inter-operation with ssl_certificate_by_lua +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + ssl_certificate_by_lua_block { + local begin = ngx.now() + ngx.sleep(0.1) + print("elapsed in ssl cert by lua: ", ngx.now() - begin) + } + ssl_session_store_by_lua_block { print("ssl store session by lua is running!") } + ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; + ssl_protocols SSLv3; + + server_tokens off; + } +--- config + server_tokens off; + resolver $TEST_NGINX_RESOLVER; + lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + + location /t { + set $port $TEST_NGINX_MEMCACHED_PORT; + + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(5000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(nil, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: userdata +close: 1 nil + +--- error_log eval +[ +'lua ssl server name: "test.com"', +qr/elapsed in ssl cert by lua: 0.(?:09|1[01])\d+,/, +'ssl_session_store_by_lua_block:1: ssl store session by lua is running!', +] + +--- no_error_log +[error] +[alert] + + + +=== TEST 10: simple logging (by file) +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + ssl_session_store_by_lua_file html/a.lua; + ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; + ssl_protocols SSLv3; + + server_tokens off; + } +--- config + server_tokens off; + resolver $TEST_NGINX_RESOLVER; + lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + + location /t { + set $port $TEST_NGINX_MEMCACHED_PORT; + + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(5000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(nil, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- user_files +>>> a.lua +print("ssl store session by lua is running!") + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: userdata +close: 1 nil + +--- error_log +lua ssl server name: "test.com" +a.lua:1: ssl store session by lua is running! + +--- no_error_log +[error] +[alert] diff --git a/debian/modules/nginx-lua/t/143-ssl-session-fetch.t b/debian/modules/nginx-lua/t/143-ssl-session-fetch.t new file mode 100644 index 0000000..686f671 --- /dev/null +++ b/debian/modules/nginx-lua/t/143-ssl-session-fetch.t @@ -0,0 +1,1027 @@ +# vim:set ft= ts=4 sw=4 et fdm=marker: + +use lib 'lib'; +use Test::Nginx::Socket::Lua; +use Cwd qw(abs_path realpath); +use File::Basename; + +repeat_each(3); + +plan tests => repeat_each() * (blocks() * 6); + +$ENV{TEST_NGINX_HTML_DIR} ||= html_dir(); + +$ENV{TEST_NGINX_MEMCACHED_PORT} ||= 11211; +$ENV{TEST_NGINX_RESOLVER} ||= '8.8.8.8'; +$ENV{TEST_NGINX_CERT_DIR} ||= dirname(realpath(abs_path(__FILE__))); + +#log_level 'warn'; +log_level 'debug'; + +no_long_string(); +#no_diff(); + +run_tests(); + +__DATA__ + +=== TEST 1: simple logging +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + ssl_session_fetch_by_lua_block { print("ssl fetch sess by lua is running!") } + ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; + ssl_protocols SSLv3; + + server_tokens off; + } +--- config + server_tokens off; + resolver $TEST_NGINX_RESOLVER; + lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + + location /t { + set $port $TEST_NGINX_MEMCACHED_PORT; + + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(5000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(package.loaded.session, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + package.loaded.session = sess + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: userdata +close: 1 nil + +--- grep_error_log eval +qr/ssl_session_fetch_by_lua_block:1: ssl fetch sess by lua is running!/s + +--- grep_error_log_out eval +[ +'', +'ssl_session_fetch_by_lua_block:1: ssl fetch sess by lua is running! +', +'ssl_session_fetch_by_lua_block:1: ssl fetch sess by lua is running! +', +] + +--- no_error_log +[error] +[alert] +[emerg] + + + +=== TEST 2: sleep +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + ssl_session_fetch_by_lua_block { + local begin = ngx.now() + ngx.sleep(0.1) + print("elapsed in ssl fetch session by lua: ", ngx.now() - begin) + } + ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; + ssl_protocols SSLv3; + + server_tokens off; + } +--- config + server_tokens off; + resolver $TEST_NGINX_RESOLVER; + lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + + location /t { + set $port $TEST_NGINX_MEMCACHED_PORT; + + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(5000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(package.loaded.session, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + package.loaded.session = sess + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: userdata +close: 1 nil + +--- grep_error_log eval +qr/elapsed in ssl fetch session by lua: 0.(?:09|1[01])\d+,/, + +--- grep_error_log_out eval +[ +'', +qr/elapsed in ssl fetch session by lua: 0.(?:09|1[01])\d+,/, +qr/elapsed in ssl fetch session by lua: 0.(?:09|1[01])\d+,/, +] + +--- no_error_log +[error] +[alert] +[emerg] + + + +=== TEST 3: timer +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; + ssl_session_fetch_by_lua_block { + local function f() + print("my timer run!") + end + local ok, err = ngx.timer.at(0, f) + if not ok then + ngx.log(ngx.ERR, "failed to create timer: ", err) + return + end + } + ssl_protocols SSLv3; + + server_tokens off; + } +--- config + server_tokens off; + resolver $TEST_NGINX_RESOLVER; + lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + + location /t { + set $port $TEST_NGINX_MEMCACHED_PORT; + + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(5000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(package.loaded.session, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + package.loaded.session = sess + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: userdata +close: 1 nil + +--- grep_error_log eval +qr/my timer run!/s + +--- grep_error_log_out eval +[ +'', +'my timer run! +', +'my timer run! +', +] + +--- no_error_log +[error] +[alert] +[emerg] + + + +=== TEST 4: cosocket +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + ssl_session_fetch_by_lua_block { + local sock = ngx.socket.tcp() + + sock:settimeout(5000) + + local ok, err = sock:connect("127.0.0.1", $TEST_NGINX_MEMCACHED_PORT) + if not ok then + ngx.log(ngx.ERR, "failed to connect to memc: ", err) + return + end + + local bytes, err = sock:send("flush_all\r\n") + if not bytes then + ngx.log(ngx.ERR, "failed to send flush_all command: ", err) + return + end + + local res, err = sock:receive() + if not res then + ngx.log(ngx.ERR, "failed to receive memc reply: ", err) + return + end + + print("received memc reply: ", res) + } + ssl_protocols SSLv3; + ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; + + server_tokens off; + } +--- config + server_tokens off; + resolver $TEST_NGINX_RESOLVER; + lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + + location /t { + set $port $TEST_NGINX_MEMCACHED_PORT; + + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(5000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(package.loaded.session, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + package.loaded.session = sess + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: userdata +close: 1 nil + +--- grep_error_log eval +qr/received memc reply: OK/s + +--- grep_error_log_out eval +[ +'', +'received memc reply: OK +', +'received memc reply: OK +', +] + +--- no_error_log +[alert] +[error] +[emerg] + + + +=== TEST 5: ngx.exit(0) - yield +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + ssl_session_fetch_by_lua_block { + ngx.exit(0) + ngx.log(ngx.ERR, "should never reached here...") + } + ssl_protocols SSLv3; + ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; + + server_tokens off; + } +--- config + server_tokens off; + resolver $TEST_NGINX_RESOLVER; + lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + lua_ssl_verify_depth 3; + + location /t { + set $port $TEST_NGINX_MEMCACHED_PORT; + + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(5000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(package.loaded.session, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + package.loaded.session = sess + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: userdata +close: 1 nil + +--- grep_error_log eval +qr/lua exit with code 0/s + +--- grep_error_log_out eval +[ +'', +'lua exit with code 0 +', +'lua exit with code 0 +', +] + +--- no_error_log +should never reached here +[alert] +[emerg] + + + +=== TEST 6: ngx.exit(ngx.ERROR) - yield +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + ssl_session_fetch_by_lua_block { + ngx.exit(ngx.ERROR) + ngx.log(ngx.ERR, "should never reached here...") + } + ssl_protocols SSLv3; + ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; + + server_tokens off; + } +--- config + server_tokens off; + resolver $TEST_NGINX_RESOLVER; + lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + lua_ssl_verify_depth 3; + + location /t { + set $port $TEST_NGINX_MEMCACHED_PORT; + + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(5000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(package.loaded.session, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + package.loaded.session = sess + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: userdata +close: 1 nil + +--- grep_error_log eval +qr/ssl_session_fetch_by_lua\*: handler return value: -1, sess get cb exit code: 0/s + +--- grep_error_log_out eval +[ +'', +'ssl_session_fetch_by_lua*: handler return value: -1, sess get cb exit code: 0 +', +'ssl_session_fetch_by_lua*: handler return value: -1, sess get cb exit code: 0 +', +] + +--- no_error_log +should never reached here +[alert] +[emerg] + + + +=== TEST 7: ngx.exit(ngx.ERROR) - yield +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + ssl_session_fetch_by_lua_block { + ngx.sleep(0.001) + ngx.exit(ngx.ERROR) + ngx.log(ngx.ERR, "should never reached here...") + } + ssl_protocols SSLv3; + ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; + + server_tokens off; + } +--- config + server_tokens off; + resolver $TEST_NGINX_RESOLVER; + lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + lua_ssl_verify_depth 3; + + location /t { + set $port $TEST_NGINX_MEMCACHED_PORT; + + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(5000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(package.loaded.session, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + package.loaded.session = sess + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: userdata +close: 1 nil + +--- grep_error_log eval +qr/ssl_session_fetch_by_lua\*: sess get cb exit code: 0/s + +--- grep_error_log_out eval +[ +'', +'ssl_session_fetch_by_lua*: sess get cb exit code: 0 +', +'ssl_session_fetch_by_lua*: sess get cb exit code: 0 +', +] + +--- no_error_log +should never reached here +[alert] +[emerg] + + + +=== TEST 8: lua exception - no yield +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + ssl_session_fetch_by_lua_block { + error("bad bad bad") + ngx.log(ngx.ERR, "should never reached here...") + } + ssl_protocols SSLv3; + ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; + + server_tokens off; + } +--- config + server_tokens off; + resolver $TEST_NGINX_RESOLVER; + lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + lua_ssl_verify_depth 3; + + location /t { + set $port $TEST_NGINX_MEMCACHED_PORT; + + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(5000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(package.loaded.session, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + package.loaded.session = sess + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: userdata +close: 1 nil + +--- grep_error_log eval +qr/ssl_session_fetch_by_lua_block:2: bad bad bad/s + +--- grep_error_log_out eval +[ +'', +'ssl_session_fetch_by_lua_block:2: bad bad bad +', +'ssl_session_fetch_by_lua_block:2: bad bad bad +', + +] + +--- no_error_log +should never reached here +[alert] +[emerg] + + + +=== TEST 9: lua exception - yield +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + ssl_session_fetch_by_lua_block { + ngx.sleep(0.001) + error("bad bad bad") + ngx.log(ngx.ERR, "should never reached here...") + } + ssl_protocols SSLv3; + ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; + + server_tokens off; + } +--- config + server_tokens off; + resolver $TEST_NGINX_RESOLVER; + lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + lua_ssl_verify_depth 3; + + location /t { + set $port $TEST_NGINX_MEMCACHED_PORT; + + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(5000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(package.loaded.session, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + package.loaded.session = sess + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: userdata +close: 1 nil + +--- grep_error_log eval +qr/ssl_session_fetch_by_lua_block:3: bad bad bad|ssl_session_fetch_by_lua\*: sess get cb exit code: 0/s + +--- grep_error_log_out eval +[ +'', +'ssl_session_fetch_by_lua_block:3: bad bad bad +ssl_session_fetch_by_lua*: sess get cb exit code: 0 +', +'ssl_session_fetch_by_lua_block:3: bad bad bad +ssl_session_fetch_by_lua*: sess get cb exit code: 0 +', + +] + +--- no_error_log +should never reached here +[alert] +[emerg] + + + +=== TEST 10: get phase +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + ssl_session_fetch_by_lua_block { print("get_phase: ", ngx.get_phase()) } + ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; + ssl_protocols SSLv3; + + server_tokens off; + } +--- config + server_tokens off; + resolver $TEST_NGINX_RESOLVER; + lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + + location /t { + set $port $TEST_NGINX_MEMCACHED_PORT; + + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(5000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(package.loaded.session, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + package.loaded.session = sess + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: userdata +close: 1 nil + +--- grep_error_log eval +qr/get_phase: ssl_session_fetch/s + +--- grep_error_log_out eval +[ +'', +'get_phase: ssl_session_fetch +', +'get_phase: ssl_session_fetch +', +] + +--- no_error_log +[error] +[alert] +[emerg] + + + +=== TEST 11: inter-operation with ssl_certificate_by_lua +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + ssl_certificate_by_lua_block { + ngx.sleep(0.1) + print("ssl cert by lua is running!") + } + ssl_session_store_by_lua_block { print("ssl store session by lua is running!") } + ssl_session_fetch_by_lua_block { + ngx.sleep(0.1) + print("ssl fetch session by lua is running!") + } + ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; + ssl_protocols SSLv3; + + server_tokens off; + } + +--- config + server_tokens off; + resolver $TEST_NGINX_RESOLVER; + lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + + location /t { + set $port $TEST_NGINX_MEMCACHED_PORT; + + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(5000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(package.loaded.session, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + package.loaded.session = sess + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: userdata +close: 1 nil + +--- grep_error_log eval +qr/ssl ((fetch|store) session|cert) by lua is running!/s + +--- grep_error_log_out eval +[ +'ssl cert by lua is running! +ssl store session by lua is running! +', +'ssl fetch session by lua is running! +ssl cert by lua is running! +ssl store session by lua is running! +', +'ssl fetch session by lua is running! +ssl cert by lua is running! +ssl store session by lua is running! +', +] + +--- no_error_log +[error] +[alert] +[emerg] + + + +=== TEST 12: simple logging (by file) +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + ssl_session_fetch_by_lua_file html/a.lua; + ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; + ssl_protocols SSLv3; + + server_tokens off; + } +--- config + server_tokens off; + lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; + + location /t { + set $port $TEST_NGINX_MEMCACHED_PORT; + + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(5000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(package.loaded.session, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + package.loaded.session = sess + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- user_files +>>> a.lua +print("ssl fetch sess by lua is running!") + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: userdata +close: 1 nil + +--- grep_error_log eval +qr/\S+:\d+: ssl fetch sess by lua is running!/s + +--- grep_error_log_out eval +[ +'', +'a.lua:1: ssl fetch sess by lua is running! +', +'a.lua:1: ssl fetch sess by lua is running! +', +] + +--- no_error_log +[error] +[alert] +[emerg] diff --git a/debian/modules/nginx-lua/t/144-shdict-incr-init.t b/debian/modules/nginx-lua/t/144-shdict-incr-init.t new file mode 100644 index 0000000..71bb566 --- /dev/null +++ b/debian/modules/nginx-lua/t/144-shdict-incr-init.t @@ -0,0 +1,226 @@ +# vim:set ft= ts=4 sw=4 et fdm=marker: +use lib 'lib'; +use Test::Nginx::Socket::Lua; + +#worker_connections(1014); +#master_process_enabled(1); +#log_level('warn'); + +repeat_each(2); + +plan tests => repeat_each() * (blocks() * 3 + 0); + +#no_diff(); +no_long_string(); +#master_on(); +#workers(2); + +run_tests(); + +__DATA__ + +=== TEST 1: incr key with init (key exists) +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + dogs:set("foo", 32) + local res, err = dogs:incr("foo", 10502, 1) + ngx.say("incr: ", res, " ", err) + ngx.say("foo = ", dogs:get("foo")) + } + } +--- request +GET /test +--- response_body +incr: 10534 nil +foo = 10534 +--- no_error_log +[error] + + + +=== TEST 2: incr key with init (key not exists) +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + dogs:flush_all() + dogs:set("bah", 32) + local res, err = dogs:incr("foo", 10502, 1) + ngx.say("incr: ", res, " ", err) + ngx.say("foo = ", dogs:get("foo")) + } + } +--- request +GET /test +--- response_body +incr: 10503 nil +foo = 10503 +--- no_error_log +[error] + + + +=== TEST 3: incr key with init (key expired and size not matched) +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + for i = 1, 20 do + dogs:set("bar" .. i, i, 0.001) + end + dogs:set("foo", "32", 0.001) + ngx.location.capture("/sleep/0.002") + local res, err = dogs:incr("foo", 10502, 0) + ngx.say("incr: ", res, " ", err) + ngx.say("foo = ", dogs:get("foo")) + } + } + location ~ ^/sleep/(.+) { + echo_sleep $1; + } +--- request +GET /test +--- response_body +incr: 10502 nil +foo = 10502 +--- no_error_log +[error] + + + +=== TEST 4: incr key with init (key expired and size matched) +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + for i = 1, 20 do + dogs:set("bar" .. i, i, 0.001) + end + dogs:set("foo", 32, 0.001) + ngx.location.capture("/sleep/0.002") + local res, err = dogs:incr("foo", 10502, 0) + ngx.say("incr: ", res, " ", err) + ngx.say("foo = ", dogs:get("foo")) + } + } + location ~ ^/sleep/(.+) { + echo_sleep $1; + } +--- request +GET /test +--- response_body +incr: 10502 nil +foo = 10502 +--- no_error_log +[error] + + + +=== TEST 5: incr key with init (forcibly override other valid entries) +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + dogs:flush_all() + local long_prefix = string.rep("1234567890", 100) + for i = 1, 1000 do + local success, err, forcible = dogs:set(long_prefix .. i, i) + if forcible then + dogs:delete(long_prefix .. i) + break + end + end + local res, err, forcible = dogs:incr(long_prefix .. "bar", 10502, 0) + ngx.say("incr: ", res, " ", err, " ", forcible) + local res, err, forcible = dogs:incr(long_prefix .. "foo", 10502, 0) + ngx.say("incr: ", res, " ", err, " ", forcible) + ngx.say("foo = ", dogs:get(long_prefix .. "foo")) + } + } +--- request +GET /test +--- response_body +incr: 10502 nil false +incr: 10502 nil true +foo = 10502 +--- no_error_log +[error] + + + +=== TEST 6: incr key without init (no forcible returned) +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + dogs:set("foo", 1) + local res, err, forcible = dogs:incr("foo", 1) + ngx.say("incr: ", res, " ", err, " ", forcible) + ngx.say("foo = ", dogs:get("foo")) + } + } +--- request +GET /test +--- response_body +incr: 2 nil nil +foo = 2 +--- no_error_log +[error] + + + +=== TEST 7: incr key (original value is not number) +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + dogs:set("foo", true) + local res, err = dogs:incr("foo", 1, 0) + ngx.say("incr: ", res, " ", err) + ngx.say("foo = ", dogs:get("foo")) + } + } +--- request +GET /test +--- response_body +incr: nil not a number +foo = true +--- no_error_log +[error] + + + +=== TEST 8: init is not number +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + local res, err, forcible = dogs:incr("foo", 1, "bar") + ngx.say("incr: ", res, " ", err, " ", forcible) + ngx.say("foo = ", dogs:get("foo")) + } + } +--- request +GET /test +--- error_code: 500 +--- response_body_like: 500 Internal Server Error +--- error_log +number expected, got string diff --git a/debian/modules/nginx-lua/t/145-shdict-list.t b/debian/modules/nginx-lua/t/145-shdict-list.t new file mode 100644 index 0000000..9bb1592 --- /dev/null +++ b/debian/modules/nginx-lua/t/145-shdict-list.t @@ -0,0 +1,745 @@ +# vim:set ft= ts=4 sw=4 et fdm=marker: +use Test::Nginx::Socket::Lua; + +#worker_connections(1014); +#master_process_enabled(1); +#log_level('warn'); + +#repeat_each(2); + +plan tests => repeat_each() * (blocks() * 3 + 0); + +#no_diff(); +no_long_string(); +#master_on(); +#workers(2); + +run_tests(); + +__DATA__ + +=== TEST 1: lpush & lpop +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + + local len, err = dogs:lpush("foo", "bar") + if len then + ngx.say("push success") + else + ngx.say("push err: ", err) + end + + local val, err = dogs:llen("foo") + ngx.say(val, " ", err) + + local val, err = dogs:lpop("foo") + ngx.say(val, " ", err) + + local val, err = dogs:llen("foo") + ngx.say(val, " ", err) + + local val, err = dogs:lpop("foo") + ngx.say(val, " ", err) + } + } +--- request +GET /test +--- response_body +push success +1 nil +bar nil +0 nil +nil nil +--- no_error_log +[error] + + + +=== TEST 2: get operation on list type +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + + local len, err = dogs:lpush("foo", "bar") + if len then + ngx.say("push success") + else + ngx.say("push err: ", err) + end + + local val, err = dogs:get("foo") + ngx.say(val, " ", err) + } + } +--- request +GET /test +--- response_body +push success +nil value is a list +--- no_error_log +[error] + + + +=== TEST 3: set operation on list type +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + + local len, err = dogs:lpush("foo", "bar") + if len then + ngx.say("push success") + else + ngx.say("push err: ", err) + end + + local ok, err = dogs:set("foo", "bar") + ngx.say(ok, " ", err) + + local val, err = dogs:get("foo") + ngx.say(val, " ", err) + } + } +--- request +GET /test +--- response_body +push success +true nil +bar nil +--- no_error_log +[error] + + + +=== TEST 4: replace operation on list type +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + + local len, err = dogs:lpush("foo", "bar") + if len then + ngx.say("push success") + else + ngx.say("push err: ", err) + end + + local ok, err = dogs:replace("foo", "bar") + ngx.say(ok, " ", err) + + local val, err = dogs:get("foo") + ngx.say(val, " ", err) + } + } +--- request +GET /test +--- response_body +push success +true nil +bar nil +--- no_error_log +[error] + + + +=== TEST 5: add operation on list type +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + + local len, err = dogs:lpush("foo", "bar") + if len then + ngx.say("push success") + else + ngx.say("push err: ", err) + end + + local ok, err = dogs:add("foo", "bar") + ngx.say(ok, " ", err) + + local val, err = dogs:get("foo") + ngx.say(val, " ", err) + } + } +--- request +GET /test +--- response_body +push success +false exists +nil value is a list +--- no_error_log +[error] + + + +=== TEST 6: delete operation on list type +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + + local len, err = dogs:lpush("foo", "bar") + if len then + ngx.say("push success") + else + ngx.say("push err: ", err) + end + + local ok, err = dogs:delete("foo") + ngx.say(ok, " ", err) + + local val, err = dogs:get("foo") + ngx.say(val, " ", err) + } + } +--- request +GET /test +--- response_body +push success +true nil +nil nil +--- no_error_log +[error] + + + +=== TEST 7: incr operation on list type +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + + local len, err = dogs:lpush("foo", "bar") + if len then + ngx.say("push success") + else + ngx.say("push err: ", err) + end + + local ok, err = dogs:incr("foo", 1) + ngx.say(ok, " ", err) + + local val, err = dogs:get("foo") + ngx.say(val, " ", err) + } + } +--- request +GET /test +--- response_body +push success +nil not a number +nil value is a list +--- no_error_log +[error] + + + +=== TEST 8: get_keys operation on list type +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + + local len, err = dogs:lpush("foo", "bar") + if len then + ngx.say("push success") + else + ngx.say("push err: ", err) + end + + local keys, err = dogs:get_keys() + ngx.say("key: ", keys[1]) + } + } +--- request +GET /test +--- response_body +push success +key: foo +--- no_error_log +[error] + + + +=== TEST 9: push operation on key-value type +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + + local ok, err = dogs:set("foo", "bar") + if ok then + ngx.say("set success") + else + ngx.say("set err: ", err) + end + + local len, err = dogs:lpush("foo", "bar") + ngx.say(len, " ", err) + + local val, err = dogs:get("foo") + ngx.say(val, " ", err) + } + } +--- request +GET /test +--- response_body +set success +nil value not a list +bar nil +--- no_error_log +[error] + + + +=== TEST 10: pop operation on key-value type +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + + local ok, err = dogs:set("foo", "bar") + if ok then + ngx.say("set success") + else + ngx.say("set err: ", err) + end + + local val, err = dogs:lpop("foo") + ngx.say(val, " ", err) + + local val, err = dogs:get("foo") + ngx.say(val, " ", err) + } + } +--- request +GET /test +--- response_body +set success +nil value not a list +bar nil +--- no_error_log +[error] + + + +=== TEST 11: llen operation on key-value type +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + + local ok, err = dogs:set("foo", "bar") + if ok then + ngx.say("set success") + else + ngx.say("set err: ", err) + end + + local val, err = dogs:llen("foo") + ngx.say(val, " ", err) + + local val, err = dogs:get("foo") + ngx.say(val, " ", err) + } + } +--- request +GET /test +--- response_body +set success +nil value not a list +bar nil +--- no_error_log +[error] + + + +=== TEST 12: lpush and lpop +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + + for i = 1, 3 do + local len, err = dogs:lpush("foo", i) + if len ~= i then + ngx.say("push err: ", err) + break + end + end + + for i = 1, 3 do + local val, err = dogs:lpop("foo") + if not val then + ngx.say("pop err: ", err) + break + else + ngx.say(val) + end + end + } + } +--- request +GET /test +--- response_body +3 +2 +1 +--- no_error_log +[error] + + + +=== TEST 13: lpush and rpop +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + + for i = 1, 3 do + local len, err = dogs:lpush("foo", i) + if len ~= i then + ngx.say("push err: ", err) + break + end + end + + for i = 1, 3 do + local val, err = dogs:rpop("foo") + if not val then + ngx.say("pop err: ", err) + break + else + ngx.say(val) + end + end + } + } +--- request +GET /test +--- response_body +1 +2 +3 +--- no_error_log +[error] + + + +=== TEST 14: rpush and lpop +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + + for i = 1, 3 do + local len, err = dogs:rpush("foo", i) + if len ~= i then + ngx.say("push err: ", err) + break + end + end + + for i = 1, 3 do + local val, err = dogs:lpop("foo") + if not val then + ngx.say("pop err: ", err) + break + else + ngx.say(val) + end + end + } + } +--- request +GET /test +--- response_body +1 +2 +3 +--- no_error_log +[error] + + + +=== TEST 15: list removed: expired +--- http_config + lua_shared_dict dogs 900k; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + + local N = 100000 + local max = 0 + + for i = 1, N do + local key = string.format("%05d", i) + + local len , err = dogs:lpush(key, i) + if not len then + max = i + break + end + end + + local keys = dogs:get_keys(0) + + ngx.say("max - 1 matched keys length: ", max - 1 == #keys) + + dogs:flush_all() + + local keys = dogs:get_keys(0) + + ngx.say("keys all expired, left number: ", #keys) + + for i = 100000, 1, -1 do + local key = string.format("%05d", i) + + local len, err = dogs:lpush(key, i) + if not len then + ngx.say("loop again, max matched: ", N + 1 - i == max) + break + end + end + + dogs:flush_all() + + dogs:flush_expired() + + for i = 1, N do + local key = string.format("%05d", i) + + local len, err = dogs:lpush(key, i) + if not len then + ngx.say("loop again, max matched: ", i == max) + break + end + end + } + } +--- request +GET /test +--- response_body +max - 1 matched keys length: true +keys all expired, left number: 0 +loop again, max matched: true +loop again, max matched: true +--- no_error_log +[error] +--- timeout: 9 + + + +=== TEST 16: list removed: forcibly +--- http_config + lua_shared_dict dogs 900k; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + + local N = 200000 + local max = 0 + for i = 1, N do + local ok, err, forcible = dogs:set(i, i) + if not ok or forcible then + max = i + break + end + end + + local two = dogs:get(2) + + ngx.say("two == number 2: ", two == 2) + + dogs:flush_all() + dogs:flush_expired() + + local keys = dogs:get_keys(0) + + ngx.say("no one left: ", #keys) + + for i = 1, N do + local key = string.format("%05d", i) + + local len, err = dogs:lpush(key, i) + if not len then + break + end + end + + for i = 1, max do + local ok, err = dogs:set(i, i) + if not ok then + ngx.say("set err: ", err) + break + end + end + + local two = dogs:get(2) + + ngx.say("two == number 2: ", two == 2) + } + } +--- request +GET /test +--- response_body +two == number 2: true +no one left: 0 +two == number 2: true +--- no_error_log +[error] +--- timeout: 9 + + + +=== TEST 17: expire on all types +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + + local len, err = dogs:lpush("list", "foo") + if not len then + ngx.say("push err: ", err) + end + + local ok, err = dogs:set("key", "bar") + if not ok then + ngx.say("set err: ", err) + end + + local keys = dogs:get_keys(0) + + ngx.say("keys number: ", #keys) + + dogs:flush_all() + + local keys = dogs:get_keys(0) + + ngx.say("keys number: ", #keys) + } + } +--- request +GET /test +--- response_body +keys number: 2 +keys number: 0 +--- no_error_log +[error] + + + +=== TEST 18: long list node +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + + local long_str = string.rep("foo", 10) + + for i = 1, 3 do + local len, err = dogs:lpush("list", long_str) + if not len then + ngx.say("push err: ", err) + end + end + + for i = 1, 3 do + local val, err = dogs:lpop("list") + if val then + ngx.say(val) + end + end + } + } +--- request +GET /test +--- response_body +foofoofoofoofoofoofoofoofoofoo +foofoofoofoofoofoofoofoofoofoo +foofoofoofoofoofoofoofoofoofoo +--- no_error_log +[error] + + + +=== TEST 19: incr on expired list +--- http_config + lua_shared_dict dogs 1m; +--- config + location = /test { + content_by_lua_block { + local dogs = ngx.shared.dogs + + local long_str = string.rep("foo", 10 * 1024) -- 30k + + for i = 1, 100 do + for j = 1, 10 do + local key = "list" .. j + local len, err = dogs:lpush(key, long_str) + if not len then + ngx.say("push err: ", err) + end + end + + dogs:flush_all() + + for j = 10, 1, -1 do + local key = "list" .. j + local newval, err = dogs:incr(key, 1, 0) + if not newval then + ngx.say("incr err: ", err) + end + end + + dogs:flush_all() + end + + ngx.say("done") + } + } +--- request +GET /test +--- response_body +done +--- no_error_log +[error] diff --git a/debian/modules/nginx-lua/t/lib/CRC32.lua b/debian/modules/nginx-lua/t/lib/CRC32.lua index 70f4215..fcf260c 100755 --- a/debian/modules/nginx-lua/t/lib/CRC32.lua +++ b/debian/modules/nginx-lua/t/lib/CRC32.lua @@ -157,7 +157,7 @@ end -- CRC32.lua -- -- A pure Lua implementation of a CRC32 hashing algorithm. Slower than using a C implemtation, --- but useful having no other dependancies. +-- but useful having no other dependencies. -- -- -- Synopsis diff --git a/debian/modules/nginx-lua/util/build.sh b/debian/modules/nginx-lua/util/build.sh index 17841ed..1185e72 100755 --- a/debian/modules/nginx-lua/util/build.sh +++ b/debian/modules/nginx-lua/util/build.sh @@ -20,12 +20,12 @@ force=$2 #--with-cc=gcc46 \ #--with-cc=clang \ #--without-http_referer_module \ - #--with-http_v2_module \ #--with-http_spdy_module \ time ngx-build $force $version \ --with-ipv6 \ --with-cc-opt="-I$PCRE_INC -I$OPENSSL_INC" \ + --with-http_v2_module \ --with-http_realip_module \ --with-http_ssl_module \ --add-module=$root/../ndk-nginx-module \ diff --git a/debian/modules/nginx-lua/util/ngx-links b/debian/modules/nginx-lua/util/ngx-links index bf54f46..8afe91e 100755 --- a/debian/modules/nginx-lua/util/ngx-links +++ b/debian/modules/nginx-lua/util/ngx-links @@ -10,7 +10,7 @@ my %opts; getopts('f', \%opts) or die "Usage: $0 [-f] Options: - -f Override exising symbolic links with force + -f Override existing symbolic links with force "; my $root = shift || 'src'; From b04fb6c678504686d3eb5c3066f87082d6105a59 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Fri, 26 Aug 2016 16:09:41 +0300 Subject: [PATCH 086/600] Replace http-push module with nchan v1.0.2 by the same author --- debian/control | 5 +- debian/copyright | 19 +- debian/modules/README.Modules-versions | 6 +- .../{nginx-http-push => nchan}/LICENCE | 4 +- debian/modules/nchan/README.md | 597 + debian/modules/nchan/changelog.txt | 265 + debian/modules/nchan/cloc-exclude.txt | 17 + debian/modules/nchan/config | 104 + .../tests => nchan/dev}/.gitignore | 1 + debian/modules/nchan/dev/Gemfile | 28 + debian/modules/nchan/dev/authserver.rb | 62 + debian/modules/nchan/dev/bench-parallel.sh | 27 + debian/modules/nchan/dev/bench.rb | 178 + debian/modules/nchan/dev/cert-key.pem | 28 + debian/modules/nchan/dev/cert.pem | 22 + .../tests => nchan/dev}/chattertest.rb | 0 .../tests => nchan/dev}/debug.sh | 0 debian/modules/nchan/dev/dev.conf | 63 + .../tests => nchan/dev}/examine_coredump.sh | 2 +- .../modules/nchan/dev/gen_config_commands.rb | 129 + debian/modules/nchan/dev/longtest.rb | 184 + .../tests => nchan/dev}/memparse.lua | 76 +- debian/modules/nchan/dev/nginx | 1 + .../dev}/nginx-cachemanager.conf | 0 .../modules/nchan/dev/nginx-nchan/.gitignore | 6 + .../dev/nginx-nchan}/PKGBUILD | 136 +- debian/modules/nchan/dev/nginx-nchan/bl.txt | 6 + .../dev/nginx-nchan}/install | 0 .../dev/nginx-nchan/nchan} | 0 .../dev/nginx-nchan}/nginx.conf | 0 .../dev/nginx-nchan}/nginx.logrotate | 0 .../dev/nginx-nchan}/nginx.service | 0 .../dev/nginx-nchan}/ngx_slab.patch | 0 .../tests => nchan/dev}/nginx-proxy.conf | 0 debian/modules/nchan/dev/nginx.conf | 444 + debian/modules/nchan/dev/nginx.sh | 277 + debian/modules/nchan/dev/package/.gitignore | 1 + .../dev/package/nginx-nchan-static/.gitignore | 5 + .../dev/package/nginx-nchan-static/PKGBUILD | 165 + .../dev/package/nginx-nchan-static/nginx.conf | 1 + .../nginx-nchan-static/nginx.logrotate | 11 + .../package/nginx-nchan-static/nginx.service | 18 + debian/modules/nchan/dev/package/repackage.sh | 28 + debian/modules/nchan/dev/pub-multi.rb | 39 + debian/modules/nchan/dev/pub.rb | 90 + debian/modules/nchan/dev/pubsub.rb | 1483 + debian/modules/nchan/dev/rebuild.sh | 170 + debian/modules/nchan/dev/redis-trib.rb | 1696 + debian/modules/nchan/dev/redis.conf | 1018 + .../nchan/dev/redis_clusterconf/.gitignore | 1 + .../nchan/dev/redis_clusterconf/cluster.sh | 10 + .../nchan/dev/redis_clusterconf/failover.sh | 62 + .../dev/redis_clusterconf/redis-7000.conf | 1018 + .../dev/redis_clusterconf/redis-7001.conf | 1018 + .../dev/redis_clusterconf/redis-7002.conf | 1018 + .../dev/redis_clusterconf/redis-7003.conf | 1018 + .../dev/redis_clusterconf/redis-7004.conf | 1018 + .../dev/redis_clusterconf/redis-7005.conf | 1018 + .../dev/redis_clusterconf/redis-7006.conf | 1018 + .../redis-cluster-node-7000.conf | 7 + .../redis-cluster-node-7001.conf | 7 + .../redis-cluster-node-7002.conf | 7 + .../redis-cluster-node-7003.conf | 7 + .../redis-cluster-node-7004.conf | 7 + .../redis-cluster-node-7005.conf | 7 + .../redis-cluster-node-7006.conf | 2 + debian/modules/nchan/dev/redocument.rb | 295 + debian/modules/nchan/dev/rsck.sh | 67 + debian/modules/nchan/dev/sub.rb | 125 + .../tests => nchan/dev}/test-parallel.sh | 4 +- debian/modules/nchan/dev/test.rb | 875 + debian/modules/nchan/dev/vg.supp | 26977 ++++++++++++++++ debian/modules/nchan/src/.gitignore | 2 + debian/modules/nchan/src/hiredis/.gitignore | 7 + debian/modules/nchan/src/hiredis/.travis.yml | 24 + debian/modules/nchan/src/hiredis/CHANGELOG.md | 110 + debian/modules/nchan/src/hiredis/COPYING | 29 + debian/modules/nchan/src/hiredis/Makefile | 217 + debian/modules/nchan/src/hiredis/README.md | 392 + .../modules/nchan/src/hiredis/adapters/ae.h | 127 + .../nchan/src/hiredis/adapters/libev.h | 147 + .../nchan/src/hiredis/adapters/libevent.h | 108 + .../nchan/src/hiredis/adapters/libuv.h | 121 + debian/modules/nchan/src/hiredis/async.c | 687 + debian/modules/nchan/src/hiredis/async.h | 129 + debian/modules/nchan/src/hiredis/dict.c | 338 + debian/modules/nchan/src/hiredis/dict.h | 126 + .../nchan/src/hiredis/examples/example-ae.c | 62 + .../src/hiredis/examples/example-libev.c | 52 + .../src/hiredis/examples/example-libevent.c | 53 + .../src/hiredis/examples/example-libuv.c | 53 + .../nchan/src/hiredis/examples/example.c | 78 + debian/modules/nchan/src/hiredis/fmacros.h | 21 + debian/modules/nchan/src/hiredis/hiredis.c | 1021 + debian/modules/nchan/src/hiredis/hiredis.h | 223 + debian/modules/nchan/src/hiredis/net.c | 458 + debian/modules/nchan/src/hiredis/net.h | 53 + debian/modules/nchan/src/hiredis/read.c | 525 + debian/modules/nchan/src/hiredis/read.h | 116 + debian/modules/nchan/src/hiredis/sds.c | 1095 + debian/modules/nchan/src/hiredis/sds.h | 105 + debian/modules/nchan/src/hiredis/test.c | 807 + debian/modules/nchan/src/hiredis/win32.h | 42 + debian/modules/nchan/src/nchan_commands.rb | 412 + .../modules/nchan/src/nchan_config_commands.c | 408 + debian/modules/nchan/src/nchan_defs.c | 91 + debian/modules/nchan/src/nchan_defs.h | 107 + debian/modules/nchan/src/nchan_module.c | 817 + debian/modules/nchan/src/nchan_module.h | 74 + debian/modules/nchan/src/nchan_setup.c | 729 + debian/modules/nchan/src/nchan_types.h | 332 + debian/modules/nchan/src/nchan_variables.c | 231 + debian/modules/nchan/src/nchan_variables.h | 1 + .../nchan/src/nchan_websocket_publisher.c | 81 + .../nchan/src/nchan_websocket_publisher.h | 2 + .../nchan/src/store/memory/ipc-handlers.c | 804 + .../nchan/src/store/memory/ipc-handlers.h | 16 + debian/modules/nchan/src/store/memory/ipc.c | 529 + debian/modules/nchan/src/store/memory/ipc.h | 55 + .../modules/nchan/src/store/memory/memstore.c | 2861 ++ .../modules/nchan/src/store/memory/recycloc.c | 47 + .../nchan/src/store/memory/store-private.h | 148 + debian/modules/nchan/src/store/memory/store.h | 11 + .../src/store/ngx_rwlock.c | 6 +- .../src/store/ngx_rwlock.h | 0 .../modules/nchan/src/store/redis/cluster.c | 1257 + .../modules/nchan/src/store/redis/cluster.h | 30 + debian/modules/nchan/src/store/redis/cmp.c | 2835 ++ debian/modules/nchan/src/store/redis/cmp.h | 474 + .../modules/nchan/src/store/redis/rdsstore.c | 2799 ++ .../src/store/redis/redis_lua_commands.h | 1025 + .../src/store/redis/redis_nginx_adapter.c | 271 + .../src/store/redis/redis_nginx_adapter.h | 15 + .../nchan/src/store/redis/scripts/.gitignore | 1 + .../src/store/redis/scripts}/Gemfile | 10 +- .../src/store/redis/scripts/add_fakesub.lua | 29 + .../store/redis/scripts/channel_keepalive.lua | 34 + .../nchan/src/store/redis/scripts/delete.lua | 58 + .../src/store/redis/scripts/find_channel.lua | 45 + .../src/store/redis/scripts/get_message.lua | 156 + .../redis/scripts/get_message_from_key.lua | 9 + .../nchan/src/store/redis/scripts/publish.lua | 278 + .../store/redis/scripts/publish_status.lua | 26 + .../nchan/src/store/redis/scripts/rsck.lua | 199 + .../redis/scripts/subscriber_register.lua | 50 + .../redis/scripts/subscriber_unregister.lua | 49 + .../src/store/redis/scripts/testscripts.rb | 268 + .../nchan/src/store/redis/store-private.h | 195 + debian/modules/nchan/src/store/redis/store.h | 16 + debian/modules/nchan/src/store/spool.c | 1219 + debian/modules/nchan/src/store/spool.h | 113 + debian/modules/nchan/src/store/store_common.c | 7 + debian/modules/nchan/src/store/store_common.h | 12 + debian/modules/nchan/src/subscribers/common.c | 317 + debian/modules/nchan/src/subscribers/common.h | 22 + .../nchan/src/subscribers/eventsource.c | 337 + .../nchan/src/subscribers/eventsource.h | 4 + .../nchan/src/subscribers/http-chunked.c | 256 + .../nchan/src/subscribers/http-chunked.h | 4 + .../src/subscribers/http-multipart-mixed.c | 291 + .../src/subscribers/http-multipart-mixed.h | 3 + .../nchan/src/subscribers/http-raw-stream.c | 150 + .../nchan/src/subscribers/http-raw-stream.h | 1 + .../modules/nchan/src/subscribers/internal.c | 275 + .../modules/nchan/src/subscribers/internal.h | 30 + .../nchan/src/subscribers/intervalpoll.c | 32 + .../nchan/src/subscribers/intervalpoll.h | 1 + .../nchan/src/subscribers/longpoll-private.h | 34 + .../modules/nchan/src/subscribers/longpoll.c | 540 + .../modules/nchan/src/subscribers/longpoll.h | 2 + .../nchan/src/subscribers/memstore_ipc.c | 167 + .../nchan/src/subscribers/memstore_ipc.h | 2 + .../nchan/src/subscribers/memstore_multi.c | 179 + .../nchan/src/subscribers/memstore_multi.h | 2 + .../nchan/src/subscribers/memstore_redis.c | 251 + .../nchan/src/subscribers/memstore_redis.h | 4 + .../modules/nchan/src/subscribers/websocket.c | 1509 + .../modules/nchan/src/subscribers/websocket.h | 4 + debian/modules/nchan/src/uthash.h | 950 + .../nchan/src/util/nchan_bufchainpool.c | 141 + .../nchan/src/util/nchan_bufchainpool.h | 39 + .../modules/nchan/src/util/nchan_channel_id.c | 214 + .../modules/nchan/src/util/nchan_channel_id.h | 1 + .../nchan/src/util/nchan_channel_info.c | 133 + .../nchan/src/util/nchan_channel_info.h | 7 + debian/modules/nchan/src/util/nchan_list.c | 146 + debian/modules/nchan/src/util/nchan_list.h | 47 + debian/modules/nchan/src/util/nchan_msgid.c | 515 + debian/modules/nchan/src/util/nchan_msgid.h | 16 + debian/modules/nchan/src/util/nchan_output.c | 701 + debian/modules/nchan/src/util/nchan_output.h | 26 + debian/modules/nchan/src/util/nchan_rbtree.c | 379 + debian/modules/nchan/src/util/nchan_rbtree.h | 64 + debian/modules/nchan/src/util/nchan_reaper.c | 320 + debian/modules/nchan/src/util/nchan_reaper.h | 33 + .../nchan/src/util/nchan_reuse_queue.c | 151 + .../nchan/src/util/nchan_reuse_queue.h | 24 + .../modules/nchan/src/util/nchan_subrequest.c | 250 + .../modules/nchan/src/util/nchan_subrequest.h | 2 + .../modules/nchan/src/util/nchan_thingcache.c | 208 + .../modules/nchan/src/util/nchan_thingcache.h | 4 + debian/modules/nchan/src/util/nchan_util.c | 383 + debian/modules/nchan/src/util/nchan_util.h | 32 + .../nchan/src/util/ngx_nchan_hacked_slab.c | 761 + .../nchan/src/util/ngx_nchan_hacked_slab.h | 26 + debian/modules/nchan/src/util/shmem.c | 184 + debian/modules/nchan/src/util/shmem.h | 28 + debian/modules/nginx-http-push/README | 206 - debian/modules/nginx-http-push/changelog.txt | 53 - debian/modules/nginx-http-push/config | 26 - debian/modules/nginx-http-push/protocol.txt | 191 - .../nginx-http-push/src/ngx_http_push_defs.c | 59 - .../nginx-http-push/src/ngx_http_push_defs.h | 73 - .../src/ngx_http_push_module.c | 783 - .../src/ngx_http_push_module.h | 31 - .../src/ngx_http_push_module_setup.c | 361 - .../nginx-http-push/src/ngx_http_push_types.h | 120 - .../nginx-http-push/src/store/memory/store.c | 1180 - .../nginx-http-push/src/store/memory/store.h | 1 - .../src/store/ngx_http_push_module_ipc.c | 146 - .../src/store/ngx_http_push_module_ipc.h | 5 - .../src/store/ngx_http_push_store.h | 51 - .../nginx-http-push/src/store/rbtree_util.c | 246 - .../nginx-http-push/src/store/rbtree_util.h | 9 - .../tests/nginx-pushmodule/.gitignore | 5 - .../modules/nginx-http-push/tests/nginx.conf | 121 - debian/modules/nginx-http-push/tests/nginx.sh | 117 - debian/modules/nginx-http-push/tests/pub.rb | 54 - .../modules/nginx-http-push/tests/pubsub.rb | 375 - .../modules/nginx-http-push/tests/rebuild.sh | 55 - debian/modules/nginx-http-push/tests/sub.rb | 52 - debian/modules/nginx-http-push/tests/test.rb | 396 - debian/nginx-extras.NEWS | 6 + debian/rules | 2 +- 234 files changed, 79692 insertions(+), 4802 deletions(-) rename debian/modules/{nginx-http-push => nchan}/LICENCE (90%) create mode 100644 debian/modules/nchan/README.md create mode 100644 debian/modules/nchan/changelog.txt create mode 100644 debian/modules/nchan/cloc-exclude.txt create mode 100644 debian/modules/nchan/config rename debian/modules/{nginx-http-push/tests => nchan/dev}/.gitignore (90%) create mode 100644 debian/modules/nchan/dev/Gemfile create mode 100755 debian/modules/nchan/dev/authserver.rb create mode 100755 debian/modules/nchan/dev/bench-parallel.sh create mode 100755 debian/modules/nchan/dev/bench.rb create mode 100644 debian/modules/nchan/dev/cert-key.pem create mode 100644 debian/modules/nchan/dev/cert.pem rename debian/modules/{nginx-http-push/tests => nchan/dev}/chattertest.rb (100%) rename debian/modules/{nginx-http-push/tests => nchan/dev}/debug.sh (100%) create mode 100644 debian/modules/nchan/dev/dev.conf rename debian/modules/{nginx-http-push/tests => nchan/dev}/examine_coredump.sh (86%) create mode 100755 debian/modules/nchan/dev/gen_config_commands.rb create mode 100755 debian/modules/nchan/dev/longtest.rb rename debian/modules/{nginx-http-push/tests => nchan/dev}/memparse.lua (82%) create mode 120000 debian/modules/nchan/dev/nginx rename debian/modules/{nginx-http-push/tests => nchan/dev}/nginx-cachemanager.conf (100%) create mode 100644 debian/modules/nchan/dev/nginx-nchan/.gitignore rename debian/modules/{nginx-http-push/tests/nginx-pushmodule => nchan/dev/nginx-nchan}/PKGBUILD (53%) create mode 100644 debian/modules/nchan/dev/nginx-nchan/bl.txt rename debian/modules/{nginx-http-push/tests/nginx-pushmodule => nchan/dev/nginx-nchan}/install (100%) rename debian/modules/{nginx-http-push/tests/nginx-pushmodule/pushmodule => nchan/dev/nginx-nchan/nchan} (100%) rename debian/modules/{nginx-http-push/tests/nginx-pushmodule => nchan/dev/nginx-nchan}/nginx.conf (100%) rename debian/modules/{nginx-http-push/tests/nginx-pushmodule => nchan/dev/nginx-nchan}/nginx.logrotate (100%) rename debian/modules/{nginx-http-push/tests/nginx-pushmodule => nchan/dev/nginx-nchan}/nginx.service (100%) rename debian/modules/{nginx-http-push/tests/nginx-pushmodule => nchan/dev/nginx-nchan}/ngx_slab.patch (100%) rename debian/modules/{nginx-http-push/tests => nchan/dev}/nginx-proxy.conf (100%) create mode 100644 debian/modules/nchan/dev/nginx.conf create mode 100755 debian/modules/nchan/dev/nginx.sh create mode 100644 debian/modules/nchan/dev/package/.gitignore create mode 100644 debian/modules/nchan/dev/package/nginx-nchan-static/.gitignore create mode 100644 debian/modules/nchan/dev/package/nginx-nchan-static/PKGBUILD create mode 100644 debian/modules/nchan/dev/package/nginx-nchan-static/nginx.conf create mode 100644 debian/modules/nchan/dev/package/nginx-nchan-static/nginx.logrotate create mode 100644 debian/modules/nchan/dev/package/nginx-nchan-static/nginx.service create mode 100755 debian/modules/nchan/dev/package/repackage.sh create mode 100755 debian/modules/nchan/dev/pub-multi.rb create mode 100755 debian/modules/nchan/dev/pub.rb create mode 100644 debian/modules/nchan/dev/pubsub.rb create mode 100755 debian/modules/nchan/dev/rebuild.sh create mode 100755 debian/modules/nchan/dev/redis-trib.rb create mode 100644 debian/modules/nchan/dev/redis.conf create mode 100644 debian/modules/nchan/dev/redis_clusterconf/.gitignore create mode 100755 debian/modules/nchan/dev/redis_clusterconf/cluster.sh create mode 100755 debian/modules/nchan/dev/redis_clusterconf/failover.sh create mode 100644 debian/modules/nchan/dev/redis_clusterconf/redis-7000.conf create mode 100644 debian/modules/nchan/dev/redis_clusterconf/redis-7001.conf create mode 100644 debian/modules/nchan/dev/redis_clusterconf/redis-7002.conf create mode 100644 debian/modules/nchan/dev/redis_clusterconf/redis-7003.conf create mode 100644 debian/modules/nchan/dev/redis_clusterconf/redis-7004.conf create mode 100644 debian/modules/nchan/dev/redis_clusterconf/redis-7005.conf create mode 100644 debian/modules/nchan/dev/redis_clusterconf/redis-7006.conf create mode 100644 debian/modules/nchan/dev/redis_clusterconf/redis-cluster-node-7000.conf create mode 100644 debian/modules/nchan/dev/redis_clusterconf/redis-cluster-node-7001.conf create mode 100644 debian/modules/nchan/dev/redis_clusterconf/redis-cluster-node-7002.conf create mode 100644 debian/modules/nchan/dev/redis_clusterconf/redis-cluster-node-7003.conf create mode 100644 debian/modules/nchan/dev/redis_clusterconf/redis-cluster-node-7004.conf create mode 100644 debian/modules/nchan/dev/redis_clusterconf/redis-cluster-node-7005.conf create mode 100644 debian/modules/nchan/dev/redis_clusterconf/redis-cluster-node-7006.conf create mode 100755 debian/modules/nchan/dev/redocument.rb create mode 100755 debian/modules/nchan/dev/rsck.sh create mode 100755 debian/modules/nchan/dev/sub.rb rename debian/modules/{nginx-http-push/tests => nchan/dev}/test-parallel.sh (83%) create mode 100755 debian/modules/nchan/dev/test.rb create mode 100644 debian/modules/nchan/dev/vg.supp create mode 100644 debian/modules/nchan/src/.gitignore create mode 100644 debian/modules/nchan/src/hiredis/.gitignore create mode 100644 debian/modules/nchan/src/hiredis/.travis.yml create mode 100644 debian/modules/nchan/src/hiredis/CHANGELOG.md create mode 100644 debian/modules/nchan/src/hiredis/COPYING create mode 100644 debian/modules/nchan/src/hiredis/Makefile create mode 100644 debian/modules/nchan/src/hiredis/README.md create mode 100644 debian/modules/nchan/src/hiredis/adapters/ae.h create mode 100644 debian/modules/nchan/src/hiredis/adapters/libev.h create mode 100644 debian/modules/nchan/src/hiredis/adapters/libevent.h create mode 100644 debian/modules/nchan/src/hiredis/adapters/libuv.h create mode 100644 debian/modules/nchan/src/hiredis/async.c create mode 100644 debian/modules/nchan/src/hiredis/async.h create mode 100644 debian/modules/nchan/src/hiredis/dict.c create mode 100644 debian/modules/nchan/src/hiredis/dict.h create mode 100644 debian/modules/nchan/src/hiredis/examples/example-ae.c create mode 100644 debian/modules/nchan/src/hiredis/examples/example-libev.c create mode 100644 debian/modules/nchan/src/hiredis/examples/example-libevent.c create mode 100644 debian/modules/nchan/src/hiredis/examples/example-libuv.c create mode 100644 debian/modules/nchan/src/hiredis/examples/example.c create mode 100644 debian/modules/nchan/src/hiredis/fmacros.h create mode 100644 debian/modules/nchan/src/hiredis/hiredis.c create mode 100644 debian/modules/nchan/src/hiredis/hiredis.h create mode 100644 debian/modules/nchan/src/hiredis/net.c create mode 100644 debian/modules/nchan/src/hiredis/net.h create mode 100644 debian/modules/nchan/src/hiredis/read.c create mode 100644 debian/modules/nchan/src/hiredis/read.h create mode 100644 debian/modules/nchan/src/hiredis/sds.c create mode 100644 debian/modules/nchan/src/hiredis/sds.h create mode 100644 debian/modules/nchan/src/hiredis/test.c create mode 100644 debian/modules/nchan/src/hiredis/win32.h create mode 100644 debian/modules/nchan/src/nchan_commands.rb create mode 100644 debian/modules/nchan/src/nchan_config_commands.c create mode 100644 debian/modules/nchan/src/nchan_defs.c create mode 100644 debian/modules/nchan/src/nchan_defs.h create mode 100755 debian/modules/nchan/src/nchan_module.c create mode 100644 debian/modules/nchan/src/nchan_module.h create mode 100644 debian/modules/nchan/src/nchan_setup.c create mode 100644 debian/modules/nchan/src/nchan_types.h create mode 100644 debian/modules/nchan/src/nchan_variables.c create mode 100644 debian/modules/nchan/src/nchan_variables.h create mode 100644 debian/modules/nchan/src/nchan_websocket_publisher.c create mode 100644 debian/modules/nchan/src/nchan_websocket_publisher.h create mode 100644 debian/modules/nchan/src/store/memory/ipc-handlers.c create mode 100644 debian/modules/nchan/src/store/memory/ipc-handlers.h create mode 100755 debian/modules/nchan/src/store/memory/ipc.c create mode 100755 debian/modules/nchan/src/store/memory/ipc.h create mode 100755 debian/modules/nchan/src/store/memory/memstore.c create mode 100644 debian/modules/nchan/src/store/memory/recycloc.c create mode 100644 debian/modules/nchan/src/store/memory/store-private.h create mode 100644 debian/modules/nchan/src/store/memory/store.h rename debian/modules/{nginx-http-push => nchan}/src/store/ngx_rwlock.c (97%) rename debian/modules/{nginx-http-push => nchan}/src/store/ngx_rwlock.h (100%) create mode 100644 debian/modules/nchan/src/store/redis/cluster.c create mode 100644 debian/modules/nchan/src/store/redis/cluster.h create mode 100644 debian/modules/nchan/src/store/redis/cmp.c create mode 100644 debian/modules/nchan/src/store/redis/cmp.h create mode 100755 debian/modules/nchan/src/store/redis/rdsstore.c create mode 100644 debian/modules/nchan/src/store/redis/redis_lua_commands.h create mode 100644 debian/modules/nchan/src/store/redis/redis_nginx_adapter.c create mode 100644 debian/modules/nchan/src/store/redis/redis_nginx_adapter.h create mode 100644 debian/modules/nchan/src/store/redis/scripts/.gitignore rename debian/modules/{nginx-http-push/tests => nchan/src/store/redis/scripts}/Gemfile (61%) create mode 100644 debian/modules/nchan/src/store/redis/scripts/add_fakesub.lua create mode 100644 debian/modules/nchan/src/store/redis/scripts/channel_keepalive.lua create mode 100644 debian/modules/nchan/src/store/redis/scripts/delete.lua create mode 100644 debian/modules/nchan/src/store/redis/scripts/find_channel.lua create mode 100644 debian/modules/nchan/src/store/redis/scripts/get_message.lua create mode 100644 debian/modules/nchan/src/store/redis/scripts/get_message_from_key.lua create mode 100644 debian/modules/nchan/src/store/redis/scripts/publish.lua create mode 100644 debian/modules/nchan/src/store/redis/scripts/publish_status.lua create mode 100644 debian/modules/nchan/src/store/redis/scripts/rsck.lua create mode 100644 debian/modules/nchan/src/store/redis/scripts/subscriber_register.lua create mode 100644 debian/modules/nchan/src/store/redis/scripts/subscriber_unregister.lua create mode 100755 debian/modules/nchan/src/store/redis/scripts/testscripts.rb create mode 100644 debian/modules/nchan/src/store/redis/store-private.h create mode 100755 debian/modules/nchan/src/store/redis/store.h create mode 100755 debian/modules/nchan/src/store/spool.c create mode 100644 debian/modules/nchan/src/store/spool.h create mode 100644 debian/modules/nchan/src/store/store_common.c create mode 100644 debian/modules/nchan/src/store/store_common.h create mode 100644 debian/modules/nchan/src/subscribers/common.c create mode 100644 debian/modules/nchan/src/subscribers/common.h create mode 100644 debian/modules/nchan/src/subscribers/eventsource.c create mode 100644 debian/modules/nchan/src/subscribers/eventsource.h create mode 100644 debian/modules/nchan/src/subscribers/http-chunked.c create mode 100644 debian/modules/nchan/src/subscribers/http-chunked.h create mode 100644 debian/modules/nchan/src/subscribers/http-multipart-mixed.c create mode 100644 debian/modules/nchan/src/subscribers/http-multipart-mixed.h create mode 100644 debian/modules/nchan/src/subscribers/http-raw-stream.c create mode 100644 debian/modules/nchan/src/subscribers/http-raw-stream.h create mode 100644 debian/modules/nchan/src/subscribers/internal.c create mode 100644 debian/modules/nchan/src/subscribers/internal.h create mode 100644 debian/modules/nchan/src/subscribers/intervalpoll.c create mode 100644 debian/modules/nchan/src/subscribers/intervalpoll.h create mode 100644 debian/modules/nchan/src/subscribers/longpoll-private.h create mode 100644 debian/modules/nchan/src/subscribers/longpoll.c create mode 100644 debian/modules/nchan/src/subscribers/longpoll.h create mode 100644 debian/modules/nchan/src/subscribers/memstore_ipc.c create mode 100644 debian/modules/nchan/src/subscribers/memstore_ipc.h create mode 100644 debian/modules/nchan/src/subscribers/memstore_multi.c create mode 100644 debian/modules/nchan/src/subscribers/memstore_multi.h create mode 100644 debian/modules/nchan/src/subscribers/memstore_redis.c create mode 100644 debian/modules/nchan/src/subscribers/memstore_redis.h create mode 100644 debian/modules/nchan/src/subscribers/websocket.c create mode 100644 debian/modules/nchan/src/subscribers/websocket.h create mode 100644 debian/modules/nchan/src/uthash.h create mode 100644 debian/modules/nchan/src/util/nchan_bufchainpool.c create mode 100644 debian/modules/nchan/src/util/nchan_bufchainpool.h create mode 100644 debian/modules/nchan/src/util/nchan_channel_id.c create mode 100644 debian/modules/nchan/src/util/nchan_channel_id.h create mode 100644 debian/modules/nchan/src/util/nchan_channel_info.c create mode 100644 debian/modules/nchan/src/util/nchan_channel_info.h create mode 100644 debian/modules/nchan/src/util/nchan_list.c create mode 100644 debian/modules/nchan/src/util/nchan_list.h create mode 100644 debian/modules/nchan/src/util/nchan_msgid.c create mode 100644 debian/modules/nchan/src/util/nchan_msgid.h create mode 100644 debian/modules/nchan/src/util/nchan_output.c create mode 100644 debian/modules/nchan/src/util/nchan_output.h create mode 100644 debian/modules/nchan/src/util/nchan_rbtree.c create mode 100644 debian/modules/nchan/src/util/nchan_rbtree.h create mode 100644 debian/modules/nchan/src/util/nchan_reaper.c create mode 100644 debian/modules/nchan/src/util/nchan_reaper.h create mode 100644 debian/modules/nchan/src/util/nchan_reuse_queue.c create mode 100644 debian/modules/nchan/src/util/nchan_reuse_queue.h create mode 100644 debian/modules/nchan/src/util/nchan_subrequest.c create mode 100644 debian/modules/nchan/src/util/nchan_subrequest.h create mode 100644 debian/modules/nchan/src/util/nchan_thingcache.c create mode 100644 debian/modules/nchan/src/util/nchan_thingcache.h create mode 100644 debian/modules/nchan/src/util/nchan_util.c create mode 100644 debian/modules/nchan/src/util/nchan_util.h create mode 100644 debian/modules/nchan/src/util/ngx_nchan_hacked_slab.c create mode 100644 debian/modules/nchan/src/util/ngx_nchan_hacked_slab.h create mode 100644 debian/modules/nchan/src/util/shmem.c create mode 100644 debian/modules/nchan/src/util/shmem.h delete mode 100644 debian/modules/nginx-http-push/README delete mode 100644 debian/modules/nginx-http-push/changelog.txt delete mode 100644 debian/modules/nginx-http-push/config delete mode 100644 debian/modules/nginx-http-push/protocol.txt delete mode 100644 debian/modules/nginx-http-push/src/ngx_http_push_defs.c delete mode 100644 debian/modules/nginx-http-push/src/ngx_http_push_defs.h delete mode 100755 debian/modules/nginx-http-push/src/ngx_http_push_module.c delete mode 100644 debian/modules/nginx-http-push/src/ngx_http_push_module.h delete mode 100644 debian/modules/nginx-http-push/src/ngx_http_push_module_setup.c delete mode 100644 debian/modules/nginx-http-push/src/ngx_http_push_types.h delete mode 100755 debian/modules/nginx-http-push/src/store/memory/store.c delete mode 100644 debian/modules/nginx-http-push/src/store/memory/store.h delete mode 100644 debian/modules/nginx-http-push/src/store/ngx_http_push_module_ipc.c delete mode 100644 debian/modules/nginx-http-push/src/store/ngx_http_push_module_ipc.h delete mode 100755 debian/modules/nginx-http-push/src/store/ngx_http_push_store.h delete mode 100644 debian/modules/nginx-http-push/src/store/rbtree_util.c delete mode 100644 debian/modules/nginx-http-push/src/store/rbtree_util.h delete mode 100644 debian/modules/nginx-http-push/tests/nginx-pushmodule/.gitignore delete mode 100644 debian/modules/nginx-http-push/tests/nginx.conf delete mode 100755 debian/modules/nginx-http-push/tests/nginx.sh delete mode 100755 debian/modules/nginx-http-push/tests/pub.rb delete mode 100644 debian/modules/nginx-http-push/tests/pubsub.rb delete mode 100755 debian/modules/nginx-http-push/tests/rebuild.sh delete mode 100755 debian/modules/nginx-http-push/tests/sub.rb delete mode 100755 debian/modules/nginx-http-push/tests/test.rb create mode 100644 debian/nginx-extras.NEWS diff --git a/debian/control b/debian/control index 5badc14..912e6c4 100644 --- a/debian/control +++ b/debian/control @@ -24,7 +24,8 @@ Build-Depends: autotools-dev, libssl-dev, libxslt1-dev, po-debconf, - zlib1g-dev + zlib1g-dev, + libhiredis-dev Standards-Version: 3.9.8.0 Homepage: http://nginx.net Vcs-Git: https://anonscm.debian.org/cgit/collab-maint/nginx.git @@ -211,7 +212,7 @@ Description: nginx web/proxy server (extended version) MAIL MODULES: Mail Core, Auth HTTP, Proxy, SSL, IMAP, POP3, SMTP. . THIRD PARTY MODULES: Auth PAM, Cache Purge, DAV Ext, Echo, Fancy Index, - Headers More, Embedded Lua, HTTP Push, HTTP Substitutions, Upload Progress, + Headers More, Embedded Lua, HTTP Substitutions, Nchan, Upload Progress, Upstream Fair Queue. Package: nginx-extras-dbg diff --git a/debian/copyright b/debian/copyright index 0edb73b..019dc9d 100644 --- a/debian/copyright +++ b/debian/copyright @@ -70,9 +70,20 @@ Copyright: Copyright (c) 2007 Grzegorz Nosek Igor Sysoev License: BSD-2-clause -Files: debian/modules/nginx-http-push/* -Copyright: Copyright (c) 2009 Leo Ponomarev -License: Expat +Files: debian/modules/nchan/* +Copyright: 2009-2016 Leo Ponomarev +License: MIT + +Files: debian/modules/nchan/src/store/redis/cmp.* +Copyright: 2015 Charles Gunyon +License: MIT + +Files: debian/modules/nchan/src/hiredis/* +Copyright: 2009-2011, Salvatore Sanfilippo + 2010-2011, Pieter Noordhuis + Matt Stancliff + Jan-Erik Rediger +License: BSD-3-clause Files: debian/modules/nginx-upload-progress/* Copyright: Brice Figureau @@ -173,7 +184,7 @@ License: BSD-4-clause OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -License: Expat +License: MIT Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the diff --git a/debian/modules/README.Modules-versions b/debian/modules/README.Modules-versions index 1ad980c..6f32994 100644 --- a/debian/modules/README.Modules-versions +++ b/debian/modules/README.Modules-versions @@ -29,9 +29,9 @@ README for Modules versions Version: a18b409 Dynamic: No, https://github.com/gnosek/nginx-upstream-fair/pull/21 - nginx-push - Homepage: https://github.com/slact/nginx_http_push_module - Version: 0.73 + nchan + Homepage: https://github.com/slact/nchan + Version: 1.0.2 nginx-upload-progress Homepage: https://github.com/masterzen/nginx-upload-progress-module diff --git a/debian/modules/nginx-http-push/LICENCE b/debian/modules/nchan/LICENCE similarity index 90% rename from debian/modules/nginx-http-push/LICENCE rename to debian/modules/nchan/LICENCE index ad9c957..aed1f30 100644 --- a/debian/modules/nginx-http-push/LICENCE +++ b/debian/modules/nchan/LICENCE @@ -1,6 +1,6 @@ This work is distributed under the MIT Licence. -Copyright (c) 2009 Leo Ponomarev +Written by Leo Ponomarev (slact) 2009-2015. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation @@ -11,7 +11,7 @@ copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be +The above authorship notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, diff --git a/debian/modules/nchan/README.md b/debian/modules/nchan/README.md new file mode 100644 index 0000000..fecd417 --- /dev/null +++ b/debian/modules/nchan/README.md @@ -0,0 +1,597 @@ + + +https://nchan.slact.net + +Nchan is a scalable, flexible pub/sub server for the modern web, built as a module for the [Nginx](http://nginx.org) web server. It can be configured as a standalone server, or as a shim between your application and tens, thousands, or millions of live subscribers. It can buffer messages in memory, on-disk, or via [Redis](http://redis.io). All connections are handled asynchronously and distributed among any number of worker processes. It can also scale to many nginx server instances with [Redis](http://redis.io). + +Messages are [published](#publisher-endpoints) to channels with HTTP `POST` requests or websockets, and [subscribed](#subscriber-endpoint) also through websockets, [long-polling](#long-polling), [EventSource](#eventsource) (SSE), old-fashioned [interval polling](#interval-polling), [and](#http-chunked-transfer) [more](#http-multipart-mixed). Each subscriber can listen to [up to 255 channels](#channel-multiplexing) per connection, and can be optionally [authenticated](https://nchan.slact.net/details#authenticate-with-nchan_authorize_request) via a custom application url. An [events](#nchan_channel_event_string) [meta channel](#nchan_channel_events_channel_id) is also available for debugging. + +For use in a web browser, you can try the [NchanSubscriber.js](https://github.com/slact/nchan/blob/master/NchanSubscriber.js) wrapper library. It supports Long-Polling, EventSource, and resumable Websockets -- or you can build your own. + +## Status and History + +The latest Nchan release is v1.0.2 (August 29, 2016) ([changelog](https://nchan.slact.net/changelog)). + +The first iteration of Nchan was written in 2009-2010 as the [Nginx HTTP Push Module](https://pushmodule.slact.net), and was vastly refactored into its present state in 2014-2016. The present release is in the **testing** phase. The core features and old functionality are thoroughly tested and stable. Some of the new functionality, especially Redis Cluster may be a bit buggy. + +Please help make the entire codebase ready for production use! Report any quirks, bugs, leaks, crashes, or larvae you find. + +#### Upgrade from Nginx HTTP Push Module + +Although Nchan is backwards-compatible with all Push Module configuration directives, some of the more unusual and rarely used settings have been disabled and will be ignored (with a warning). See the [upgrade page](https://nchan.slact.net/upgrade) for a detailed list of changes and improvements, as well as a full list of incompatibilities. + + +## Does it scale? + +benchmarking internal subscriber response times + +Yes it does. Like Nginx, Nchan can easily handle as much traffic as you can throw at it. I've tried to benchmark it, but my benchmarking tools are much slower than Nchan. The data I've gathered is on how long Nchan itself takes to respond to every subscriber after publishing a message -- this excludes TCP handshake times and internal HTTP request parsing. Basically, it measures how Nchan scales assuming all other components are already tuned for scalability. The graphed data are averages of 5 runs with 50-byte messages. + +With a well-tuned OS and network stack on commodity server hardware, expect to handle upwards of 300K concurrent subscribers per second at minimal CPU load. Nchan can also be scaled out to multiple Nginx instances using the [Redis storage engine](#nchan_use_redis), and that too can be scaled up beyond a single-point-of-failure by using Redis Cluster. + +Currently, Nchan's performance is limited by available memory bandwidth. This can be improved significantly in future versions with fewer allocations and the use of contiguous memory pools. Please consider supporting Nchan to speed up the work of memory cache optimization. + +## Install + +#### Download Packages + - [Arch Linux](https://archlinux.org): [nginx-nchan](https://aur.archlinux.org/packages/nginx-nchan/) and [nginx-nchan-git](https://aur.archlinux.org/packages/nginx-nchan-git/) are available in the Arch User Repository. + - Mac OS X: a [homebrew](http://brew.sh) package is available. `brew tap homebrew/nginx; brew install nginx-full --with-nchan-module` + - [Debian](https://www.debian.org/): [nginx-common.deb](https://nchan.slact.net/download/nginx-common.deb) and [nginx-extras.deb](https://nchan.slact.net/download/nginx-extras.deb). Download both and install them with `dpkg -i`, followed by `sudo apt-get -f install`. These packages should soon be available directly from the Debian repository. + - [Ubuntu](http://www.ubuntu.com/): [nginx-common.ubuntu.deb](https://nchan.slact.net/download/nginx-common.ubuntu.deb) and [nginx-extras.ubuntu.deb](https://nchan.slact.net/download/nginx-extras.ubuntu.deb). Download both and install them with `dpkg -i`, followed by `sudo apt-get -f install`. Who knows when Ubuntu will add them to their repository?... + - [Fedora](https://fedoraproject.org): A 64-bit binary rpm and a source rpm are available: [nginx-nchan.x86_64.rpm](https://nchan.slact.net/download/nginx-nchan.x86-64.rpm), [ngx-nchan.src.rpm](https://nchan.slact.net/download/nginx-nchan.src.rpm). + - A statically compiled binary and associated linux nginx installation files are also [available as a tarball](https://nchan.slact.net/download/nginx-nchan-latest.tar.gz). + + +#### Build From Source +Grab the latest copy of Nginx from [nginx.org](http://nginx.org). Grab the latest Nchan source from [github](https://github.com/slact/nchan/releases). Follow the instructions for [building Nginx](https://www.nginx.com/resources/wiki/start/topics/tutorials/install/#source-releases), except during the `configure` stage, add +``` +./configure --add-module=path/to/nchan ... +``` + +If you're using Nginx > 1.9.11, you can build Nchan as a [dynamic module](https://www.nginx.com/blog/dynamic-modules-nginx-1-9-11/) with `--add-dynamic-module=path/to/nchan` + +Run `make`, `make install`, and enjoy. (Caution, contents may be hot.) + +## Conceptual Overview + +The basic unit of most pub/sub solutions is the messaging *channel*. Nchan is no different. Publishers send messages to channels with a certain *channel id*, and subscribers subscribed to those channels receive them. Some number of messages may be buffered for a time in a channel's message buffer before they are deleted. Pretty simple, right? + +Well... the trouble is that nginx configuration does not deal with channels, publishers, and subscribers. Rather, it has several sections for incoming requests to match against *server* and *location* sections. **Nchan configuration directives map servers and locations onto channel publishing and subscribing endpoints**: + +```nginx +#very basic nchan config +worker_processes 5; + +http { + server { + listen 80; + + location = /sub { + nchan_subscriber; + nchan_channel_id foobar; + } + + location = /pub { + nchan_publisher; + nchan_channel_id foobar; + } + } +} +``` + +The above maps requests to the URI `/sub` onto the channel `foobar`'s *subscriber endpoint* , and similarly `/pub` onto channel `foobar`'s *publisher endpoint*. + + +#### Publisher Endpoints + +Publisher endpoints are Nginx config *locations* with the [*`nchan_publisher`*](#nchan_publisher) directive. + +Messages can be published to a channel by sending HTTP **POST** requests with the message contents to the *publisher endpoint* locations. You can also publish messages through a **Websocket** connection to the same location. + +##### Publishing Messages + +Requests and websocket messages are responded to with information about the channel at time of message publication. Here's an example from publishing with `curl`: + +```console +> curl --request POST --data "test message" http://127.0.0.1:80/pub + + queued messages: 5 + last requested: 18 sec. ago + active subscribers: 0 + last message id: 1450755280:0 +``` + +The response can be in plaintext (as above), JSON, or XML, based on the request's *`Accept`* header: + +```console +> curl --request POST --data "test message" -H "Accept: text/json" http://127.0.0.2:80/pub + + {"messages": 6, "requested": 55, "subscribers": 0, "last_message_id": "1450755317:0" } +``` + +Websocket publishers also receive the same responses when publishing, with the encoding determined by the *`Accept`* header present during the handshake. + +The response code for an HTTP request is *`202` Accepted* if no subscribers are present at time of publication, or *`201` Created* if at least 1 subscriber was present. + +Metadata can be added to a message when using an HTTP POST request for publishing. A `Content-Type` header will be associated as the message's content type (and output to Long-Poll, Interval-Poll, and multipart/mixed subscribers). A `X-EventSource-Event` header can also be used to associate an EventSource `event:` line value with a message. + +##### Other Publisher Endpoint Actions + +**HTTP `GET`** requests return channel information without publishing a message. The response code is `200` if the channel exists, and `404` otherwise: +```console +> curl --request POST --data "test message" http://127.0.0.2:80/pub + ... + +> curl -v --request GET -H "Accept: text/json" http://127.0.0.2:80/pub + + {"messages": 1, "requested": 7, "subscribers": 0, "last_message_id": "1450755421:0" } +``` + + +**HTTP `DELETE`** requests delete a channel and end all subscriber connections. Like the `GET` requests, this returns a `200` status response with channel info if the channel existed, and a `404` otherwise. + +#### Subscriber Endpoint + +Subscriber endpoints are Nginx config *locations* with the [*`nchan_subscriber`*](#nchan_subscriber) directive. + +Nchan supports several different kinds of subscribers for receiving messages: [*Websocket*](#websocket), [*EventSource*](#eventsource) (Server Sent Events), [*Long-Poll*](#long-polling), [*Interval-Poll*](#interval-polling). [*HTTP chunked transfer*](#http-chunked-transfer), and [*HTTP multipart/mixed*](#http-multipart-mixed). + +- ##### Long-Polling + The tried-and-true server-push method supported by every browser out there. + Initiated by sending an HTTP `GET` request to a channel subscriber endpoint. + The long-polling subscriber walks through a channel's message queue via the built-in cache mechanism of HTTP clients, namely with the "`Last-Modified`" and "`Etag`" headers. Explicitly, to receive the next message for given a long-poll subscriber response, send a request with the "`If-Modified-Since`" header set to the previous response's "`Last-Modified`" header, and "`If-None-Match`" likewise set to the previous response's "`Etag`" header. + Sending a request without a "`If-Modified-Since`" or "`If-None-Match`" headers returns the oldest message in a channel's message queue, or waits until the next published message, depending on the value of the `nchan_subscriber_first_message` config directive. + A message's associated content type, if present, will be sent to this subscriber with the `Content-Type` header. + +- ##### Interval-Polling + Works just like long-polling, except if the requested message is not yet available, immediately responds with a `304 Not Modified`. + There is no way to differentiate between long-poll and interval-poll subscriber requests, so long-polling must be disabled for a subscriber location if you wish to use interval-polling. + +- ##### Websocket + Bidirectional communication for web browsers. Part of the [HTML5 spec](http://www.w3.org/TR/2014/REC-html5-20141028/single-page.html). Nchan supports the latest protocol version 13 ([RFC 6455](https://tools.ietf.org/html/rfc6455)). + Initiated by sending a websocket handshake to the desired subscriber endpoint location. + If the websocket connection is closed by the server, the `close` frame will contain the HTTP response code and status line describing the reason for closing the connection. Server-initiated keep-alive pings can be configured with the [`nchan_websocket_ping_interval`](#nchan_websocket_ping_interval) config directive. Websocket extensions are not yet supported. + Messages published through a websocket connection can be forwarded to an upstream application with the [`nchan_publisher_upstream_request`](nchan_publisher_upstream_request) config directive. + Websocket subscribers can use the custom `ws+meta.nchan` subprotocol to receive message metadata with messages, making websocket connections resumable. Messages received with this subprotocol are of the form +
+  id: message_id
+  content-type: message_content_type
+  \n
+  message_data
+  
+ The `content-type:` line may be omitted. +- ##### EventSource + Also known as [Server-Sent Events](https://en.wikipedia.org/wiki/Server-sent_events) or SSE, it predates Websockets in the [HTML5 spec](http://www.w3.org/TR/2014/REC-html5-20141028/single-page.html), and is a [very simple protocol](http://www.w3.org/TR/eventsource/#event-stream-interpretation). + Initiated by sending an HTTP `GET` request to a channel subscriber endpoint with the "`Accept: text/event-stream`" header. + Each message `data: ` segment will be prefaced by the message `id: `. + To resume a closed EventSource connection from the last-received message, one *should* start the connection with the "`Last-Event-ID`" header set to the last message's `id`. + Unfortunately, browsers [don't support setting](http://www.w3.org/TR/2011/WD-eventsource-20111020/#concept-event-stream-last-event-id) this header for an `EventSource` object, so by default the last message id is set either from the "`Last-Event-Id`" header or the `last_event_id` url query string argument. + This behavior can be configured via the [`nchan_subscriber_last_message_id`](#nchan_subscriber_last_message_id) config. + A message's associated `event` type, if present, will be sent to this subscriber with the `event:` line. + +- ##### HTTP [multipart/mixed](http://www.w3.org/Protocols/rfc1341/7_2_Multipart.html#z0) + The `multipart/mixed` MIMEtype was conceived for emails, but hey, why not use it for HTTP? It's easy to parse and includes metadata with each message. + Initiated by including an `Accept: multipart/mixed` header. + The response headers and the unused "preamble" portion of the response body are sent right away, with the boundary string generated randomly for each subscriber. Each subsequent message will be sent as one part of the multipart message, and will include the message time and tag (`Last-Modified` and `Etag`) as well as the optional `Content-Type` headers. + Each message is terminated with the next multipart message's boundary **without a trailing newline**. While this conforms to the multipart spec, it is unusual as multipart messages are defined as *starting*, rather than ending with a boundary. + A message's associated content type, if present, will be sent to this subscriber with the `Content-Type` header. + +- ##### HTTP Raw Stream + A simple subscription method similar to the [streaming subscriber](https://github.com/wandenberg/nginx-push-stream-module/blob/master/docs/directives/subscribers.textile#push_stream_subscriber) of the [Nginx HTTP Push Stream Module](https://github.com/wandenberg/nginx-push-stream-module). Messages are appended to the response body, separated by a newline or configurable by `nchan_subscriber_http_raw_stream_separator`. + +- ##### HTTP [Chunked Transfer](http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6.1) + This subscription method uses the `chunked` `Transfer-Encoding` to receive messages. + Initiated by explicitly including `chunked` in the [`TE` header](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.39): + `TE: chunked` (or `TE: chunked;q=??` where the qval > 0) + The response headers are sent right away, and each message will be sent as an individual chunk. Note that because a zero-length chunk terminates the transfer, **zero-length messages will not be sent** to the subscriber. + Unlike the other subscriber types, the `chunked` subscriber cannot be used with http/2 because it dissallows chunked encoding. + +#### PubSub Endpoint + +PubSub endpoints are Nginx config *locations* with the [*`nchan_pubsub`*](#nchan_pubsub) directive. + +A combination of *publisher* and *subscriber* endpoints, this location treats all HTTP `GET` +requests as subscribers, and all HTTP `POST` as publishers. One simple use case is an echo server: + +```nginx + location = /pubsub { + nchan_pubsub; + nchan_channel_id foobar; + } +``` + +A more applicable setup may set different publisher and subscriber channel ids: + +```nginx + location = /pubsub { + nchan_pubsub; + nchan_publisher_channel_id foo; + nchan_subscriber_channel_id bar; + } +``` + +Here, subscribers will listen for messages on channel `foo`, and publishers will publish messages to channel `bar`. This can be useful when setting up websocket proxying between web clients and your application. + +### The Channel ID + +So far the examples have used static channel ids, which is not very useful in practice. It can be set to any nginx *variable*, such as a querystring argument, a header value, or a part of the location url: + +```nginx + location = /sub_by_ip { + #channel id is the subscriber's IP address + nchan_subscriber; + nchan_channel_id $remote_addr; + } + + location /sub_by_querystring { + #channel id is the query string parameter chanid + # GET /sub/sub_by_querystring?foo=bar&chanid=baz will have the channel id set to 'baz' + nchan_subscriber; + nchan_channel_id $arg_chanid; + } + + location ~ /sub/(\w+)$ { + #channel id is the word after /sub/ + # GET /sub/foobar_baz will have the channel id set to 'foobar_baz' + # I hope you know your regular expressions... + nchan_subscriber; + nchan_channel_id $1; #first capture of the location match + } +``` + +#### Channel Multiplexing + +Any subscriber location can be an endpoint for up to 255 channels. Messages published to all the specified channels will be delivered in-order to the subscriber. There are two ways to enable multiplexing: + +Up to 7 channel ids can be specified for the `nchan_channel_id` or `nchan_channel_subscriber_id` config directive: + +```nginx + location ~ /multisub/(\w+)/(\w+)$ { + nchan_subscriber; + nchan_channel_id "$1" "$2" "common_channel"; + #GET /multisub/foo/bar will be subscribed to: + # channels 'foo', 'bar', and 'common_channel', + #and will receive messages from all of the above. + } +``` + +For more than 7 channels, `nchan_channel_id_split_delimiter` can be used to split the `nchan_channel_id` or `nchan_channel_subscriber_id` into up to 255 individual channel ids: + +```nginx + location ~ /multisub-split/(.*)$ { + nchan_subscriber; + nchan_channel_id "$1"; + nchan_channel_id_split_delimiter ","; + #GET /multisub-split/foo,bar,baz,a will be subscribed to: + # channels 'foo', 'bar', 'baz', and 'a' + #and will receive messages from all of the above. + } +``` + +`DELETE` requests on any channel are forwarded to relevant multi-channel subscribers, and their connections are terminated. + +Publishing to multiple channels with a single request is also possible, with similar configuration: + +```nginx + location ~ /multipub/(\w+)/(\w+)$ { + nchan_publisher; + nchan_channel_id "$1" "$2" "another_channel"; + } +``` +## Storage + +Nchan can stores messages in memory, on disk, or via Redis. Memory storage is much faster, whereas Redis has additional overhead as is considerably slower for publishing messages, but offers near unlimited scalability for broadcast use cases with far more subscribers than publishers. + +### Memory Storage + +This storage method uses a segment of shared memory to store messages and channel data. Large messages as determined by Nginx's caching layer are stored on-disk. The size of the memory segment is configured with `nchan_max_reserved_memory`. Data stored here is not persistent, and is lost if Nginx is restarted or reloaded. + +### Redis + +Nchan can also store messages and channels on a Redis server, or in a Redis cluster. To use a Redis server, set `nchan_use_redis on;` and set the server url with `nchan_redis_url`. These two settings are inheritable by nested locations, so it is enough to set them within an `http { }` block to enable Redis for all Nchan locations in that block. Different locations can also use different Redis servers. + +To use a Redis Cluster, the Redis servers acting as cluster nodes need to be configured in an `upstream { }` block: + +```nginx + upstream redis_cluster { + nchan_redis_server redis://127.0.0.1:7000; + nchan_redis_server redis://127.0.0.1:7001; + nchan_redis_server redis://127.0.0.1:7002; + } +``` + +It is best to specify all master cluster nodes, but this is not required -- as long as Nchan can connect to at least 1 node, it will discover and connect to the whole cluster. + +To use Redis Cluster in an Nchan location, use the `nchan_redis_pass` setting: + +```nginx + location ~ /pubsub/(\w+)$ { + nchan_channel_id $1; + nchan_pubsub; + nchan_redis_pass redis_cluster; + } + +``` + +Note that `nchan_redis_pass` implies `nchan_use_redis on;`, and that this setting is *not* inherited by nested locations. + +When connecting several Nchan servers to the same Redis server (or cluster), the servers **must have their times synced up**. Failure to do so may result in missing and duplicated messages. + +## Variables + +Nchan makes several variables usabled in the config file: + +- `$nchan_channel_id` + The channel id extracted from a publisher or subscriber location request. For multiplexed locations, this is the first channel id in the list. + +- `$nchan_channel_id1`, `$nchan_channel_id2`, `$nchan_channel_id3`, `$nchan_channel_id4` + As above, but for the nth channel id in multiplexed channels. + +- `$nchan_subscriber_type` + For subscriber locations, this variable is set to the subscriber type (websocket, longpoll, etc.). + +- `$nchan_publisher_type` + For subscriber locations, this variable is set to the subscriber type (http or websocket). + +- `$nchan_prev_message_id`, `$nchan_message_id` + The current and previous (if applicable) message id for publisher request or subscriber response. + +- `$nchan_channel_event` + For channel events, this is the event name. Useful when configuring `nchan_channel_event_string`. + +Additionally, `nchan_stub_status` data is also exposed as variables. These are available only when `nchan_stub_status` is enabled on at least one location: + +- `$nchan_stub_status_total_published_messages` +- `$nchan_stub_status_stored_messages` +- `$nchan_stub_status_shared_memory_used` +- `$nchan_stub_status_channels` +- `$nchan_stub_status_subscribers` +- `$nchan_stub_status_redis_pending_commands` +- `$nchan_stub_status_redis_connected_servers` +- `$nchan_stub_status_total_ipc_alerts_received` +- `$nchan_stub_status_ipc_queued_alerts` +- `$nchan_stub_status_total_ipc_send_delay` +- `$nchan_stub_status_total_ipc_receive_delay` + + +## Configuration Directives + +- **nchan_channel_id** + arguments: 1 - 7 + default: `(none)` + context: server, location, if + > Channel id for a publisher or subscriber location. Can have up to 4 values to subscribe to up to 4 channels. + +- **nchan_channel_id_split_delimiter** + arguments: 1 + default: `(none)` + context: server, location, if + > Split the channel id into several ids for multiplexing using the delimiter string provided. + +- **nchan_eventsource_event** + arguments: 1 + default: `(none)` + context: server, location, if + > Set the EventSource `event:` line to this value. When used in a publisher location, overrides the published message's `X-EventSource-Event` header and associates the message with the given value. When used in a subscriber location, overrides all messages' associated `event:` string with the given value. + +- **nchan_longpoll_multipart_response** `[ off | on | raw ]` + arguments: 1 + default: `off` + context: server, location, if + > when set to 'on', enable sending multiple messages in a single longpoll response, separated using the multipart/mixed content-type scheme. If there is only one available message in response to a long-poll request, it is sent unmodified. This is useful for high-latency long-polling connections as a way to minimize round-trips to the server. When set to 'raw', sends multiple messages using the http-raw-stream message separator. + +- **nchan_publisher** `[ http | websocket ]` + arguments: 0 - 2 + default: `http websocket` + context: server, location, if + legacy name: push_publisher + > Defines a server or location as a publisher endpoint. Requests to a publisher location are treated as messages to be sent to subscribers. See the protocol documentation for a detailed description. + +- **nchan_publisher_channel_id** + arguments: 1 - 7 + default: `(none)` + context: server, location, if + > Channel id for publisher location. + +- **nchan_publisher_upstream_request** `` + arguments: 1 + context: server, location, if + > Send POST request to internal location (which may proxy to an upstream server) with published message in the request body. Useful for bridging websocket publishers with HTTP applications, or for transforming message via upstream application before publishing to a channel. + > The upstream response code determine how publishing will proceed. A `200 OK` will publish the message from the upstream response's body. A `304 Not Modified` will publish the message as it was received from the publisher. A `204 No Content` will result in the message not being published. + +- **nchan_pubsub** `[ http | websocket | eventsource | longpoll | intervalpoll | chunked | multipart-mixed | http-raw-stream ]` + arguments: 0 - 6 + default: `http websocket eventsource longpoll chunked multipart-mixed` + context: server, location, if + > Defines a server or location as a pubsub endpoint. For long-polling, GETs subscribe. and POSTs publish. For Websockets, publishing data on a connection does not yield a channel metadata response. Without additional configuration, this turns a location into an echo server. + +- **nchan_subscriber** `[ websocket | eventsource | longpoll | intervalpoll | chunked | multipart-mixed | http-raw-stream ]` + arguments: 0 - 5 + default: `websocket eventsource longpoll chunked multipart-mixed` + context: server, location, if + legacy name: push_subscriber + > Defines a server or location as a channel subscriber endpoint. This location represents a subscriber's interface to a channel's message queue. The queue is traversed automatically, starting at the position defined by the `nchan_subscriber_first_message` setting. + > The value is a list of permitted subscriber types. + +- **nchan_subscriber_channel_id** + arguments: 1 - 7 + default: `(none)` + context: server, location, if + > Channel id for subscriber location. Can have up to 4 values to subscribe to up to 4 channels. + +- **nchan_subscriber_compound_etag_message_id** + arguments: 1 + default: `off` + context: server, location, if + > Override the default behavior of using both `Last-Modified` and `Etag` headers for the message id. + > Enabling this option packs the entire message id into the `Etag` header, and discards + > `Last-Modified` and `If-Modified-Since` headers. + +- **nchan_subscriber_first_message** `[ oldest | newest | ]` + arguments: 1 + default: `oldest` + context: server, location, if + > Controls the first message received by a new subscriber. 'oldest' starts at the oldest available message in a channel's message queue, 'newest' waits until a message arrives. If a number `n` is specified, starts at `n`th message from the oldest. (`-n` start at `n`th from now). 0 is equivalent to 'newest'. + +- **nchan_subscriber_http_raw_stream_separator** `` + arguments: 1 + default: `\n` + context: server, location, if + > Message separator string for the http-raw-stream subscriber. Automatically terminated with a newline character. + +- **nchan_subscriber_last_message_id** + arguments: 1 - 5 + default: `$http_last_event_id $arg_last_event_id` + context: server, location, if + > If `If-Modified-Since` and `If-None-Match` headers are absent, set the message id to the first non-empty of these values. Used primarily as a workaround for the inability to set the first `Last-Message-Id` of a web browser's EventSource object. + +- **nchan_subscriber_message_id_custom_etag_header** + arguments: 1 + default: `(none)` + context: server, location, if + > Use a custom header instead of the Etag header for message ID in subscriber responses. This setting is a hack, useful when behind a caching proxy such as Cloudflare that under some conditions (like using gzip encoding) swallow the Etag header. + +- **nchan_subscriber_timeout** ` (seconds)` + arguments: 1 + default: `0 (none)` + context: http, server, location, if + legacy name: push_subscriber_timeout + > Maximum time a subscriber may wait for a message before being disconnected. If you don't want a subscriber's connection to timeout, set this to 0. When possible, the subscriber will get a response with a `408 Request Timeout` status; otherwise the subscriber will simply be disconnected. + +- **nchan_websocket_ping_interval** ` (seconds)` + arguments: 1 + default: `0 (none)` + context: server, location, if + > Interval for sending websocket ping frames. Disabled by default. + +- **nchan_authorize_request** `` + arguments: 1 + context: server, location, if + > Send GET request to internal location (which may proxy to an upstream server) for authorization of a publisher or subscriber request. A 200 response authorizes the request, a 403 response forbids it. + +- **nchan_max_reserved_memory** `` + arguments: 1 + default: `32M` + context: http + legacy name: push_max_reserved_memory + > The size of the shared memory chunk this module will use for message queuing and buffering. + +- **nchan_message_buffer_length** `` + arguments: 1 + default: `10` + context: http, server, location + legacy names: push_max_message_buffer_length, push_message_buffer_length + > Publisher configuration setting the maximum number of messages to store per channel. A channel's message buffer will retain a maximum of this many most recent messages. + +- **nchan_message_timeout** `
@@ -1447,7 +1524,7 @@ The rewrite_by_lua code will always run at the end of the rew Similar to the [[#rewrite_by_lua|rewrite_by_lua]] directive except that this directive inlines the Lua source directly -inside a pair of curly braces (`{}`) instead of in an NGINX string literal (which requires +inside a pair of curly braces ({}) instead of in an NGINX string literal (which requires special character escaping). For instance, @@ -1488,8 +1565,7 @@ Nginx variables are supported in the file path for dynamic dispatch just as in [ '''phase:''' ''access tail'' -'''WARNING''' Since the v0.9.17 release, use of this directive is ''discouraged''; -use the new [[#access_by_lua_block|access_by_lua_block]] directive instead. +'''NOTE''' Use of this directive is ''discouraged'' following the v0.9.17 release. Use the [[#access_by_lua_block|access_by_lua_block]] directive instead. Acts as an access phase handler and executes Lua code string specified in for every request. The Lua code may make [[#Nginx API for Lua|API calls]] and is executed as a new spawned coroutine in an independent global environment (i.e. a sandbox). @@ -1502,12 +1578,12 @@ Note that this handler always runs ''after'' the standard [[HttpAccessModule]]. allow 192.168.1.0/24; allow 10.1.1.0/16; deny all; - + access_by_lua ' local res = ngx.location.capture("/mysql", { ... }) ... '; - + # proxy_pass/fastcgi_pass/... }
@@ -1519,7 +1595,7 @@ Note that the [http://mdounin.ru/hg/ngx_http_auth_request_module/ ngx_auth_reque location / { auth_request /auth; - + # proxy_pass/fastcgi_pass/postgres_pass/... } @@ -1530,18 +1606,18 @@ can be implemented in ngx_lua as: location / { access_by_lua ' local res = ngx.location.capture("/auth") - + if res.status == ngx.HTTP_OK then return end - + if res.status == ngx.HTTP_FORBIDDEN then ngx.exit(res.status) end - + ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) '; - + # proxy_pass/fastcgi_pass/postgres_pass/... }
@@ -1564,7 +1640,7 @@ of NGINX. Similar to the [[#access_by_lua|access_by_lua]] directive except that this directive inlines the Lua source directly -inside a pair of curly braces (`{}`) instead of in an NGINX string literal (which requires +inside a pair of curly braces ({}) instead of in an NGINX string literal (which requires special character escaping). For instance, @@ -1591,7 +1667,7 @@ Nginx variables can be used in the string When a relative path like foo/bar.lua is given, they will be turned into the absolute path relative to the server prefix path determined by the -p PATH command-line option while starting the Nginx server. -When the Lua code cache is turned on (by default), the user code is loaded once at the first request and cached +When the Lua code cache is turned on (by default), the user code is loaded once at the first request and cached and the Nginx config must be reloaded each time the Lua source file is modified. The Lua code cache can be temporarily disabled during development by switching [[#lua_code_cache|lua_code_cache]] off in nginx.conf to avoid repeatedly reloading Nginx. @@ -1605,8 +1681,7 @@ Nginx variables are supported in the file path for dynamic dispatch just as in [ '''phase:''' ''output-header-filter'' -'''WARNING''' Since the v0.9.17 release, use of this directive is ''discouraged''; -use the new [[#header_filter_by_lua_block|header_filter_by_lua_block]] directive instead. +'''NOTE''' Use of this directive is ''discouraged'' following the v0.9.17 release. Use the [[#header_filter_by_lua_block|header_filter_by_lua_block]] directive instead. Uses Lua code specified in to define an output header filter. @@ -1638,7 +1713,7 @@ This directive was first introduced in the v0.2.1rc20 release. Similar to the [[#header_filter_by_lua|header_filter_by_lua]] directive except that this directive inlines the Lua source directly -inside a pair of curly braces (`{}`) instead of in an NGINX string literal (which requires +inside a pair of curly braces ({}) instead of in an NGINX string literal (which requires special character escaping). For instance, @@ -1673,8 +1748,7 @@ This directive was first introduced in the v0.2.1rc20 release. '''phase:''' ''output-body-filter'' -'''WARNING''' Since the v0.9.17 release, use of this directive is ''discouraged''; -use the new [[#body_filter_by_lua_block|body_filter_by_lua_block]] directive instead. +'''NOTE''' Use of this directive is ''discouraged'' following the v0.9.17 release. Use the [[#body_filter_by_lua_block|body_filter_by_lua_block]] directive instead. Uses Lua code specified in to define an output body filter. @@ -1761,7 +1835,7 @@ This directive was first introduced in the v0.5.0rc32 release. Similar to the [[#body_filter_by_lua|body_filter_by_lua]] directive except that this directive inlines the Lua source directly -inside a pair of curly braces (`{}`) instead of in an NGINX string literal (which requires +inside a pair of curly braces ({}) instead of in an NGINX string literal (which requires special character escaping). For instance, @@ -1796,15 +1870,14 @@ This directive was first introduced in the v0.5.0rc32 release. '''phase:''' ''log'' -'''WARNING''' Since the v0.9.17 release, use of this directive is ''discouraged''; -use the new [[#log_by_lua_block|log_by_lua_block]] directive instead. +'''NOTE''' Use of this directive is ''discouraged'' following the v0.9.17 release. Use the [[#log_by_lua_block|log_by_lua_block]] directive instead. Runs the Lua source code inlined as the at the log request processing phase. This does not replace the current access logs, but runs before. Note that the following API functions are currently disabled within this context: * Output API functions (e.g., [[#ngx.say|ngx.say]] and [[#ngx.send_headers|ngx.send_headers]]) -* Control API functions (e.g., [[#ngx.exit|ngx.exit]]) +* Control API functions (e.g., [[#ngx.exit|ngx.exit]]) * Subrequest API functions (e.g., [[#ngx.location.capture|ngx.location.capture]] and [[#ngx.location.capture_multi|ngx.location.capture_multi]]) * Cosocket API functions (e.g., [[#ngx.socket.tcp|ngx.socket.tcp]] and [[#ngx.req.socket|ngx.req.socket]]). @@ -1838,7 +1911,7 @@ Here is an example of gathering average data for [[HttpUpstreamModule#$upstream_ local log_dict = ngx.shared.log_dict local sum = log_dict:get("upstream_time-sum") local nb = log_dict:get("upstream_time-nb") - + if nb and sum then ngx.say("average upstream response time: ", sum / nb, " (", nb, " reqs)") @@ -1862,7 +1935,7 @@ This directive was first introduced in the v0.5.0rc31 release. Similar to the [[#log_by_lua|log_by_lua]] directive except that this directive inlines the Lua source directly -inside a pair of curly braces (`{}`) instead of in an NGINX string literal (which requires +inside a pair of curly braces ({}) instead of in an NGINX string literal (which requires special character escaping). For instance, @@ -2430,7 +2503,7 @@ See also [[#lua_ssl_trusted_certificate|lua_ssl_trusted_certificate]]. '''context:''' ''http, server, location, location-if'' -Enables or disables automatic response buffering for HTTP 1.0 (or older) requests. This buffering mechanism is mainly used for HTTP 1.0 keep-alive which replies on a proper Content-Length response header. +Enables or disables automatic response buffering for HTTP 1.0 (or older) requests. This buffering mechanism is mainly used for HTTP 1.0 keep-alive which relies on a proper Content-Length response header. If the Lua code explicitly sets a Content-Length response header before sending the headers (either explicitly via [[#ngx.send_headers|ngx.send_headers]] or implicitly via the first [[#ngx.say|ngx.say]] or [[#ngx.print|ngx.print]] call), then the HTTP 1.0 response buffering will be disabled even when this directive is turned on. @@ -2486,7 +2559,7 @@ This directive was first introduced in the v0.5.0rc32 release. This directive controls whether to check for premature client connection abortion. -When this directive is turned on, the ngx_lua module will monitor the premature connection close event on the downstream connections. And when there is such an event, it will call the user Lua function callback (registered by [[#ngx.on_abort|ngx.on_abort]]) or just stop and clean up all the Lua "light threads" running in the current request's request handler when there is no user callback function registered. +When this directive is on, the ngx_lua module will monitor the premature connection close event on the downstream connections and when there is such an event, it will call the user Lua function callback (registered by [[#ngx.on_abort|ngx.on_abort]]) or just stop and clean up all the Lua "light threads" running in the current request's request handler when there is no user callback function registered. According to the current implementation, however, if the client closes the connection before the Lua code finishes reading the request body data via [[#ngx.req.socket|ngx.req.socket]], then ngx_lua will neither stop all the running "light threads" nor call the user callback (if [[#ngx.on_abort|ngx.on_abort]] has been called). Instead, the reading operation on [[#ngx.req.socket|ngx.req.socket]] will just return the error message "client aborted" as the second return value (the first return value is surely nil). @@ -2592,11 +2665,11 @@ Here is an example location /foo { set $a 32; set $b 56; - + set_by_lua $sum 'return tonumber(ngx.arg[1]) + tonumber(ngx.arg[2])' $a $b; - + echo $sum; }
@@ -2646,7 +2719,7 @@ Setting ngx.var.Foo to a nil value will unset the -'''WARNING''' When reading from an Nginx variable, Nginx will allocate memory in the per-request memory pool which is freed only at request termination. So when you need to read from an Nginx variable repeatedly in your Lua code, cache the Nginx variable value to your own Lua variable, for example, +'''CAUTION''' When reading from an Nginx variable, Nginx will allocate memory in the per-request memory pool which is freed only at request termination. So when you need to read from an Nginx variable repeatedly in your Lua code, cache the Nginx variable value to your own Lua variable, for example, local val = ngx.var.some_var @@ -2655,7 +2728,7 @@ Setting ngx.var.Foo to a nil value will unset the nil while uninitialized (but defined) NGINX variables are evaluated to an empty Lua string. This API requires a relatively expensive metamethod call and it is recommended to avoid using it on hot code paths. @@ -2780,7 +2853,7 @@ There is a hard coded 2048 byte limitation on error message lengths == ngx.ctx == '''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*'' -This table can be used to store per-request Lua context data and has a life time identical to the current request (as with the Nginx variables). +This table can be used to store per-request Lua context data and has a life time identical to the current request (as with the Nginx variables). Consider the following example, @@ -2816,7 +2889,7 @@ Every request, including subrequests, has its own copy of the table. For example ngx.say("sub post: ", ngx.ctx.blah) } } - + location /main { content_by_lua_block { ngx.ctx.blah = 73 @@ -2847,7 +2920,7 @@ Internal redirection will destroy the original request ngx.ctx data ngx.say(ngx.ctx.foo) } } - + location /orig { content_by_lua_block { ngx.ctx.foo = "hello" @@ -2876,14 +2949,14 @@ When being used in the context of [[#init_worker_by_lua|init_worker_by_lua*]], t The ngx.ctx lookup requires relatively expensive metamethod calls and it is much slower than explicitly passing per-request data along by your own function arguments. So do not abuse this API for saving your own function arguments because it usually has quite some performance impact. -Because of the metamethod magic, never "local" the ngx.ctx table outside your Lua function scope on the Lua module level level due to [[#Data_Sharing_within_an_Nginx_Worker|worker-level data sharing]]. For example, the following is bad: +Because of the metamethod magic, never "local" the ngx.ctx table outside your Lua function scope on the Lua module level due to [[#Data_Sharing_within_an_Nginx_Worker|worker-level data sharing]]. For example, the following is bad: -- mymodule.lua local _M = {} -- the following line is bad since ngx.ctx is a per-request --- data while this `ctx` variable is on the Lua module level +-- data while this ctx variable is on the Lua module level -- and thus is per-nginx-worker. local ctx = ngx.ctx @@ -2907,7 +2980,7 @@ end return _M -That is, let the caller pass the `ctx` table explicitly via a function argument. +That is, let the caller pass the ctx table explicitly via a function argument. == ngx.location.capture == '''syntax:''' ''res = ngx.location.capture(uri, options?)'' @@ -3024,7 +3097,7 @@ The args option can also take plain query strings: This is functionally identical to the previous examples. -The share_all_vars option controls whether to share nginx variables among the current request and its subrequests. +The share_all_vars option controls whether to share nginx variables among the current request and its subrequests. If this option is set to true, then the current request and associated subrequests will share the same Nginx variable scope. Hence, changes to Nginx variables made by a subrequest will affect the current request. Care should be taken in using this option as variable scope sharing can have unexpected side effects. The args, vars, or copy_all_vars options are generally preferable instead. @@ -3089,7 +3162,7 @@ In addition to the two settings above, it is possible to specify values for variables in the subrequest using the vars option. These variables are set after the sharing or copying of variables has been evaluated, and provides a more efficient method of passing specific -values to a subrequest over encoding them as URL arguments and +values to a subrequest over encoding them as URL arguments and unescaping them in the Nginx config file. @@ -3171,7 +3244,7 @@ Note that subrequests issued by [[#ngx.location.capture|ngx.location.capture]] i request headers of the current request by default and that this may have unexpected side effects on the subrequest responses. For example, when using the standard ngx_proxy module to serve subrequests, an "Accept-Encoding: gzip" header in the main request may result -in gzipped responses that cannot be handled properly in Lua code. Original request headers should be ignored by setting +in gzipped responses that cannot be handled properly in Lua code. Original request headers should be ignored by setting [[HttpProxyModule#proxy_pass_request_headers|proxy_pass_request_headers]] to off in subrequest locations. When the body option is not specified and the always_forward_body option is false (the default value), the POST and PUT subrequests will inherit the request bodies of the parent request (if any). @@ -3201,11 +3274,11 @@ This function issues several parallel subrequests specified by the input table a { "/bar" }, { "/baz", { method = ngx.HTTP_POST, body = "hello" } }, } - + if res1.status == ngx.HTTP_OK then ... end - + if res2.body == "BLAH" then ... end @@ -3223,10 +3296,10 @@ Lua tables can be used for both requests and responses when the number of subreq table.insert(reqs, { "/postgres" }) table.insert(reqs, { "/redis" }) table.insert(reqs, { "/memcached" }) - + -- issue all the requests at once and wait until they all return local resps = { ngx.location.capture_multi(reqs) } - + -- loop over the responses table for i, resp in ipairs(resps) do -- process the response table "resp" @@ -3278,7 +3351,7 @@ The header names are matched case-insensitively. -- equivalent to ngx.header["Content-Type"] = 'text/plain' ngx.header.content_type = 'text/plain'; - + ngx.header["X-My-Header"] = 'blah blah'; @@ -3295,7 +3368,7 @@ will yield Set-Cookie: b=4; path=/ -in the response headers. +in the response headers. Only Lua tables are accepted (Only the last element in the table will take effect for standard headers such as Content-Type that only accept a single value). @@ -3323,7 +3396,7 @@ The same applies to assigning an empty table: Setting ngx.header.HEADER after sending out response headers (either explicitly with [[#ngx.send_headers|ngx.send_headers]] or implicitly with [[#ngx.print|ngx.print]] and similar) will throw out a Lua exception. -Reading ngx.header.HEADER will return the value of the response header named HEADER. +Reading ngx.header.HEADER will return the value of the response header named HEADER. Underscores (_) in the header names will also be replaced by dashes (-) and the header names will be matched case-insensitively. If the response header is not present at all, nil will be returned. @@ -3655,8 +3728,8 @@ Arguments without the = parts are treated as boolean argumen That is, they will take Lua boolean values true. However, they are different from arguments taking empty string values. GET /test?foo=&bar= will give something like - foo: - bar: + foo: + bar: Empty key arguments are discarded. GET /test?=hello&=world will yield an empty output for instance. @@ -3760,13 +3833,13 @@ Arguments without the = parts are treated as boolean argumen That is, they will take Lua boolean values true. However, they are different from arguments taking empty string values. POST /test with request body foo=&bar= will return something like - foo: - bar: + foo: + bar: Empty key arguments are discarded. POST /test with body =hello&=world will yield empty outputs for instance. -Note that a maximum of 100 request arguments are parsed by default (including those with the same name) and that additional request arguments are silently discarded to guard against potential denial of service attacks. +Note that a maximum of 100 request arguments are parsed by default (including those with the same name) and that additional request arguments are silently discarded to guard against potential denial of service attacks. However, the optional max_args function argument can be used to override this limit: @@ -3818,7 +3891,7 @@ the value of ngx.req.get_headers()["Foo"] will be a Lua (array) tab {"foo", "bar", "baz"}
-Note that a maximum of 100 request headers are parsed by default (including those with the same name) and that additional request headers are silently discarded to guard against potential denial of service attacks. +Note that a maximum of 100 request headers are parsed by default (including those with the same name) and that additional request headers are silently discarded to guard against potential denial of service attacks. However, the optional max_headers function argument can be used to override this limit: @@ -4164,6 +4237,7 @@ The optional status parameter specifies the HTTP status code to be * 301 * 302 (default) +* 303 * 307 It is 302 (ngx.HTTP_MOVED_TEMPORARILY) by default. @@ -4367,7 +4441,7 @@ Note that while this method accepts all [[#HTTP status constants|HTTP status con Also note that this method call terminates the processing of the current request and that it is recommended that a coding style that combines this method call with the return statement, i.e., return ngx.exit(...) be used to reinforce the fact that the request processing is being terminated. -When being used in the contexts of [[#header_filter_by_lua|header_filter_by_lua]] and +When being used in the contexts of [[#header_filter_by_lua|header_filter_by_lua*]], [[#balancer_by_lua_block|balancer_by_lua*]], and [[#ssl_session_store_by_lua_block|ssl_session_store_by_lua*]], ngx.exit() is an asynchronous operation and will return immediately. This behavior may change in future and it is recommended that users always use return in combination as suggested above. @@ -4378,14 +4452,14 @@ an asynchronous operation and will return immediately. This behavior may change Explicitly specify the end of the response output stream. In the case of HTTP 1.1 chunked encoded output, it will just trigger the Nginx core to send out the "last chunk". -When you disable the HTTP 1.1 keep-alive feature for your downstream connections, you can rely on descent HTTP clients to close the connection actively for you when you call this method. This trick can be used do back-ground jobs without letting the HTTP clients to wait on the connection, as in the following example: +When you disable the HTTP 1.1 keep-alive feature for your downstream connections, you can rely on well written HTTP clients to close the connection actively for you when you call this method. This trick can be used do back-ground jobs without letting the HTTP clients to wait on the connection, as in the following example: location = /async { keepalive_timeout 0; content_by_lua_block { ngx.say("got the task!") - ngx.eof() -- a descent HTTP client will close the connection at this point + ngx.eof() -- well written HTTP clients will close the connection at this point -- access MySQL, PostgreSQL, Redis, Memcached, and etc here... } } @@ -4646,7 +4720,7 @@ This is the local time. Returns the elapsed seconds from the epoch for the current time stamp from the nginx cached time (no syscall involved unlike Lua's date library). -Updates of the Nginx time cache an be forced by calling [[#ngx.update_time|ngx.update_time]] first. +Updates of the Nginx time cache can be forced by calling [[#ngx.update_time|ngx.update_time]] first. == ngx.now == '''syntax:''' ''secs = ngx.now()'' @@ -4858,7 +4932,7 @@ The optional fourth argument, ctx, can be a Lua table holding an op local ctx = { pos = 2 } local m, err = ngx.re.match("1234, hello", "[0-9]+", "", ctx) - -- m[0] = "34" + -- m[0] = "234" -- ctx.pos == 5 @@ -5024,7 +5098,7 @@ When the replace is a string, then it is treated as a special templ where $0 referring to the whole substring matched by the pattern and $1 referring to the first parenthesized capturing substring. -Curly braces can also be used to disambiguate variable names from the background string literals: +Curly braces can also be used to disambiguate variable names from the background string literals: local newstr, n, err = ngx.re.sub("hello, 1234", "[0-9]", "${0}00") @@ -5123,6 +5197,8 @@ The resulting object dict has the following methods: * [[#ngx.shared.DICT.flush_expired|flush_expired]] * [[#ngx.shared.DICT.get_keys|get_keys]] +All these methods are ''atomic'' operations, that is, safe from concurrent accesses from multiple nginx worker processes for the same lua_shared_dict zone. + Here is an example: @@ -5343,7 +5419,7 @@ The value argument and init argument can be any valid This method was first introduced in the v0.3.1rc22 release. -The optional `init` parameter was first added in the v0.10.6 release. +The optional init parameter was first added in the v0.10.6 release. See also [[#ngx.shared.DICT|ngx.shared.DICT]]. @@ -5445,7 +5521,7 @@ Fetch a list of the keys from the dictionary, up to . By default, only the first 1024 keys (if any) are returned. When the argument is given the value 0, then all the keys will be returned even there is more than 1024 keys in the dictionary. -'''WARNING''' Be careful when calling this method on dictionaries with a really huge number of keys. This method may lock the dictionary for quite a while and block all the nginx worker processes that are trying to access the dictionary. +'''CAUTION''' Avoid calling this method on dictionaries with a very large number of keys as it may lock the dictionary for significant amount of time and block Nginx worker processes trying to access the dictionary. This feature was first introduced in the v0.7.3 release. @@ -5724,7 +5800,7 @@ session userdata returned by a previous sslhandshake call for exactly the same target. For short-lived connections, reusing SSL sessions can usually speed up the handshake by one order by magnitude but it is not so useful if the connection pool is enabled. This argument defaults to -`nil`. If this argument takes the boolean `false` value, no SSL session +nil. If this argument takes the boolean false value, no SSL session userdata would return by this call and only a Lua boolean will be returned as the first return value; otherwise the current SSL session will always be returned as the first argument in case of successes. @@ -5737,7 +5813,7 @@ also used to validate the server name specified in the server certificate sent f the remote. The optional ssl_verify argument takes a Lua boolean value to -control whether to perform SSL verification. When set to `true`, the server +control whether to perform SSL verification. When set to true, the server certificate will be verified according to the CA certificates specified by the [[#lua_ssl_trusted_certificate|lua_ssl_trusted_certificate]] directive. You may also need to adjust the [[#lua_ssl_verify_depth|lua_ssl_verify_depth]] @@ -6148,7 +6224,7 @@ Then it will generate the output 4 -"Light threads" are mostly useful for doing concurrent upstream requests in a single Nginx request handler, kinda like a generalized version of [[#ngx.location.capture_multi|ngx.location.capture_multi]] that can work with all the [[#Nginx API for Lua|Nginx API for Lua]]. The following example demonstrates parallel requests to MySQL, Memcached, and upstream HTTP services in a single Lua handler, and outputting the results in the order that they actually return (very much like the Facebook BigPipe model): +"Light threads" are mostly useful for making concurrent upstream requests in a single Nginx request handler, much like a generalized version of [[#ngx.location.capture_multi|ngx.location.capture_multi]] that can work with all the [[#Nginx API for Lua|Nginx API for Lua]]. The following example demonstrates parallel requests to MySQL, Memcached, and upstream HTTP services in a single Lua handler, and outputting the results in the order that they actually return (similar to Facebook's BigPipe model): -- query mysql, memcached, and a remote http service at the same time, @@ -6187,7 +6263,7 @@ Then it will generate the output ngx.thread.spawn(query_mysql) -- create thread 1 ngx.thread.spawn(query_memcached) -- create thread 2 - ngx.thread.spawn(query_http) -- create thread 3 + ngx.thread.spawn(query_http) -- create thread 3 This API was first enabled in the v0.7.0 release. @@ -6338,7 +6414,7 @@ This API was first introduced in the v0.7.4 release. See also [[#lua_check_client_abort|lua_check_client_abort]]. == ngx.timer.at == -'''syntax:''' ''ok, err = ngx.timer.at(delay, callback, user_arg1, user_arg2, ...)'' +'''syntax:''' ''hdl, err = ngx.timer.at(delay, callback, user_arg1, user_arg2, ...)'' '''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' @@ -6364,7 +6440,7 @@ Premature timer expiration happens when the Nginx worker process is trying to shut down, as in an Nginx configuration reload triggered by the HUP signal or in an Nginx server shutdown. When the Nginx worker is trying to shut down, one can no longer call ngx.timer.at to -create new timers with nonzero delays and in that case ngx.timer.at will return nil and +create new timers with nonzero delays and in that case ngx.timer.at will return a "conditional false" value and a string describing the error, that is, "process exiting". Starting from the v0.9.3 release, it is allowed to create zero-delay timers even when the Nginx worker process starts shutting down. @@ -6413,7 +6489,7 @@ One can also create infinite re-occurring timers, for instance, a timer getting return end end - + local ok, err = ngx.timer.at(delay, handler) if not ok then ngx.log(ngx.ERR, "failed to create the timer: ", err) @@ -6421,6 +6497,9 @@ One can also create infinite re-occurring timers, for instance, a timer getting end +It is recommended, however, to use the [[#ngx.timer.every|ngx.timer.every]] API function +instead for creating recurring timers since it is more robust. + Because timer callbacks run in the background and their running time will not add to any client request's response time, they can easily accumulate in the server and exhaust system resources due to either @@ -6458,6 +6537,22 @@ You can pass most of the standard Lua values (nils, booleans, numbers, strings, This API was first introduced in the v0.8.0 release. +== ngx.timer.every == +'''syntax:''' ''hdl, err = ngx.timer.every(delay, callback, user_arg1, user_arg2, ...)'' + +'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' + +Similar to the [[#ngx.timer.at|ngx.timer.at]] API function, but + +# delay ''cannot'' be zero, +# timer will be created every delay seconds until the current Nginx worker process starts exiting. + +When success, returns a "conditional true" value (but not a true). Otherwise, returns a "conditional false" value and a string describing the error. + +This API also respect the [[#lua_max_pending_timers|lua_max_pending_timers]] and [[#lua_max_running_timers|lua_max_running_timers]]. + +This API was first introduced in the v0.10.9 release. + == ngx.timer.running_count == '''syntax:''' ''count = ngx.timer.running_count()'' @@ -6481,8 +6576,8 @@ This directive was first introduced in the v0.9.20 release. '''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, init_by_lua*, init_worker_by_lua*'' -This string field indicates the current NGINX subsystem the current Lua environment is based on. For this module, this field always takes the string value `"http"`. For -[https://github.com/openresty/stream-lua-nginx-module#readme ngx_stream_lua_module], however, this field takes the value `"stream"`. +This string field indicates the current NGINX subsystem the current Lua environment is based on. For this module, this field always takes the string value "http". For +[https://github.com/openresty/stream-lua-nginx-module#readme ngx_stream_lua_module], however, this field takes the value "stream". This field was first introduced in the 0.10.1. @@ -6563,7 +6658,7 @@ This API was first introduced in the 0.9.5 release. Returns the total number of the Nginx worker processes (i.e., the value configured by the [http://nginx.org/en/docs/ngx_core_module.html#worker_processes worker_processes] -directive in `nginx.conf`). +directive in nginx.conf). This API was first introduced in the 0.9.20 release. @@ -6575,11 +6670,11 @@ This API was first introduced in the 0.9.20 release. Returns the ordinal number of the current Nginx worker processes (starting from number 0). -So if the total number of workers is `N`, then this method may return a number between 0 -and `N - 1` (inclusive). +So if the total number of workers is N, then this method may return a number between 0 +and N - 1 (inclusive). This function returns meaningful values only for NGINX 1.9.1+. With earlier versions of NGINX, it -always returns `nil`. +always returns nil. See also [[#ngx.worker.count|ngx.worker.count]]. diff --git a/debian/modules/nginx-lua/src/api/ngx_http_lua_api.h b/debian/modules/nginx-lua/src/api/ngx_http_lua_api.h index 3737149..cd64fc8 100644 --- a/debian/modules/nginx-lua/src/api/ngx_http_lua_api.h +++ b/debian/modules/nginx-lua/src/api/ngx_http_lua_api.h @@ -19,7 +19,7 @@ /* Public API for other Nginx modules */ -#define ngx_http_lua_version 10007 +#define ngx_http_lua_version 10010 typedef struct { diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_api.c b/debian/modules/nginx-lua/src/ngx_http_lua_api.c index b72c707..7b590e7 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_api.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_api.c @@ -56,11 +56,10 @@ ngx_http_lua_add_package_preload(ngx_conf_t *cf, const char *package, lua_pushcfunction(L, func); lua_setfield(L, -2, package); lua_pop(L, 2); - - return NGX_OK; } - /* L == NULL */ + /* we always register preload_hooks since we always create new Lua VMs + * when lua code cache is off. */ if (lmcf->preload_hooks == NULL) { lmcf->preload_hooks = @@ -176,7 +175,9 @@ ngx_http_lua_shared_memory_init(ngx_shm_zone_t *shm_zone, void *data) } zone->shm = shm_zone->shm; +#if defined(nginx_version) && nginx_version >= 1009000 zone->noreuse = shm_zone->noreuse; +#endif if (zone->init(zone, odata) != NGX_OK) { return NGX_ERROR; diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_args.c b/debian/modules/nginx-lua/src/ngx_http_lua_args.c index 0c307d6..b43697c 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_args.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_args.c @@ -184,7 +184,7 @@ ngx_http_lua_ngx_req_get_post_args(lua_State *L) if (r->request_body->temp_file) { lua_pushnil(L); - lua_pushliteral(L, "requesty body in temp file not supported"); + lua_pushliteral(L, "request body in temp file not supported"); return 2; } diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_balancer.c b/debian/modules/nginx-lua/src/ngx_http_lua_balancer.c index 0adf787..2fa634e 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_balancer.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_balancer.c @@ -314,7 +314,13 @@ ngx_http_lua_balancer_get_peer(ngx_peer_connection_t *pc, void *data) if (ctx->exited && ctx->exit_code != NGX_OK) { rc = ctx->exit_code; - if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) { + if (rc == NGX_ERROR + || rc == NGX_BUSY + || rc == NGX_DECLINED +#ifdef HAVE_BALANCER_STATUS_CODE_PATCH + || rc >= NGX_HTTP_SPECIAL_RESPONSE +#endif + ) { return rc; } @@ -640,7 +646,7 @@ ngx_http_lua_ffi_balancer_set_more_tries(ngx_http_request_t *r, int count, char **err) { #if (nginx_version >= 1007005) - ngx_uint_t max_tries; + ngx_uint_t max_tries, total; #endif ngx_http_lua_ctx_t *ctx; ngx_http_upstream_t *u; @@ -681,9 +687,10 @@ ngx_http_lua_ffi_balancer_set_more_tries(ngx_http_request_t *r, #if (nginx_version >= 1007005) max_tries = r->upstream->conf->next_upstream_tries; + total = bp->total_tries + r->upstream->peer.tries - 1; - if (bp->total_tries + count > max_tries) { - count = max_tries - bp->total_tries; + if (max_tries && total + count > max_tries) { + count = max_tries - total; *err = "reduced tries due to limit"; } else { diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_common.h b/debian/modules/nginx-lua/src/ngx_http_lua_common.h index 267952b..e389783 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_common.h +++ b/debian/modules/nginx-lua/src/ngx_http_lua_common.h @@ -22,6 +22,19 @@ #include +#if (NGX_PCRE) + +#include + +#if (PCRE_MAJOR > 8) || (PCRE_MAJOR == 8 && PCRE_MINOR >= 21) +# define LUA_HAVE_PCRE_JIT 1 +#else +# define LUA_HAVE_PCRE_JIT 0 +#endif + +#endif + + #if !defined(nginx_version) || (nginx_version < 1006000) #error at least nginx 1.6.0 is required but found an older version #endif @@ -138,7 +151,7 @@ typedef struct ngx_http_lua_sema_mm_s ngx_http_lua_sema_mm_t; typedef ngx_int_t (*ngx_http_lua_main_conf_handler_pt)(ngx_log_t *log, ngx_http_lua_main_conf_t *lmcf, lua_State *L); typedef ngx_int_t (*ngx_http_lua_srv_conf_handler_pt)(ngx_http_request_t *r, - ngx_http_lua_srv_conf_t *lmcf, lua_State *L); + ngx_http_lua_srv_conf_t *lscf, lua_State *L); typedef struct { @@ -168,6 +181,11 @@ struct ngx_http_lua_main_conf_s { ngx_int_t regex_cache_entries; ngx_int_t regex_cache_max_entries; ngx_int_t regex_match_limit; + +#if (LUA_HAVE_PCRE_JIT) + pcre_jit_stack *jit_stack; +#endif + #endif ngx_array_t *shm_zones; /* of ngx_shm_zone_t* */ @@ -199,6 +217,12 @@ struct ngx_http_lua_main_conf_s { of reqeusts */ ngx_uint_t malloc_trim_req_count; +#if nginx_version >= 1011011 + /* the following 2 fields are only used by ngx.req.raw_headers() for now */ + ngx_buf_t **busy_buf_ptrs; + ngx_int_t busy_buf_ptr_count; +#endif + unsigned requires_header_filter:1; unsigned requires_body_filter:1; unsigned requires_capture_filter:1; @@ -206,6 +230,7 @@ struct ngx_http_lua_main_conf_s { unsigned requires_access:1; unsigned requires_log:1; unsigned requires_shm:1; + unsigned requires_capture_log:1; }; diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_control.c b/debian/modules/nginx-lua/src/ngx_http_lua_control.c index 249d763..ae36505 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_control.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_control.c @@ -212,10 +212,12 @@ ngx_http_lua_ngx_redirect(lua_State *L) if (rc != NGX_HTTP_MOVED_TEMPORARILY && rc != NGX_HTTP_MOVED_PERMANENTLY + && rc != NGX_HTTP_SEE_OTHER && rc != NGX_HTTP_TEMPORARY_REDIRECT) { return luaL_error(L, "only ngx.HTTP_MOVED_TEMPORARILY, " - "ngx.HTTP_MOVED_PERMANENTLY, and " + "ngx.HTTP_MOVED_PERMANENTLY, " + "ngx.HTTP_SEE_OTHER, and " "ngx.HTTP_TEMPORARY_REDIRECT are allowed"); } diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_directive.c b/debian/modules/nginx-lua/src/ngx_http_lua_directive.c index 862edda..6a562f4 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_directive.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_directive.c @@ -27,6 +27,8 @@ #include "ngx_http_lua_ssl_certby.h" #include "ngx_http_lua_lex.h" #include "api/ngx_http_lua_api.h" +#include "ngx_http_lua_log_ringbuf.h" +#include "ngx_http_lua_log.h" typedef struct ngx_http_lua_block_parser_ctx_s @@ -1700,6 +1702,71 @@ ngx_http_lua_conf_read_lua_token(ngx_conf_t *cf, } +char * +ngx_http_lua_capture_error_log(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) +{ +#ifndef HAVE_INTERCEPT_ERROR_LOG_PATCH + return "not found: missing the capture error log patch for nginx"; +#else + ngx_str_t *value; + ssize_t size; + u_char *data; + ngx_cycle_t *cycle; + ngx_http_lua_main_conf_t *lmcf = conf; + ngx_http_lua_log_ringbuf_t *ringbuf; + + value = cf->args->elts; + cycle = cf->cycle; + + if (lmcf->requires_capture_log) { + return "is duplicate"; + } + + if (value[1].len == 0) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid capture error log size \"%V\"", + &value[1]); + return NGX_CONF_ERROR; + } + + size = ngx_parse_size(&value[1]); + + if (size < NGX_MAX_ERROR_STR) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid capture error log size \"%V\", " + "minimum size is %d", &value[1], + NGX_MAX_ERROR_STR); + return NGX_CONF_ERROR; + } + + if (cycle->intercept_error_log_handler) { + return "capture error log handler has been hooked"; + } + + ringbuf = (ngx_http_lua_log_ringbuf_t *) + ngx_palloc(cf->pool, sizeof(ngx_http_lua_log_ringbuf_t)); + if (ringbuf == NULL) { + return NGX_CONF_ERROR; + } + + data = ngx_palloc(cf->pool, size); + if (data == NULL) { + return NGX_CONF_ERROR; + } + + ngx_http_lua_log_ringbuf_init(ringbuf, data, size); + + lmcf->requires_capture_log = 1; + cycle->intercept_error_log_handler = (ngx_log_intercept_pt) + ngx_http_lua_capture_log_handler; + cycle->intercept_error_log_data = ringbuf; + + return NGX_CONF_OK; +#endif +} + + /* * ngx_http_lua_strlstrn() is intended to search for static substring * with known length in string until the argument last. The argument n diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_directive.h b/debian/modules/nginx-lua/src/ngx_http_lua_directive.h index be591f3..5abfe4d 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_directive.h +++ b/debian/modules/nginx-lua/src/ngx_http_lua_directive.h @@ -67,9 +67,10 @@ ngx_int_t ngx_http_lua_filter_set_by_lua_file(ngx_http_request_t *r, char *ngx_http_lua_rewrite_no_postpone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); - char *ngx_http_lua_conf_lua_block_parse(ngx_conf_t *cf, ngx_command_t *cmd); +char *ngx_http_lua_capture_error_log(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); #endif /* _NGX_HTTP_LUA_DIRECTIVE_H_INCLUDED_ */ diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_headers.c b/debian/modules/nginx-lua/src/ngx_http_lua_headers.c index 0af56f6..6700ce8 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_headers.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_headers.c @@ -26,6 +26,9 @@ static int ngx_http_lua_ngx_req_get_headers(lua_State *L); static int ngx_http_lua_ngx_req_header_clear(lua_State *L); static int ngx_http_lua_ngx_req_header_set(lua_State *L); static int ngx_http_lua_ngx_resp_get_headers(lua_State *L); +#if nginx_version >= 1011011 +void ngx_http_lua_ngx_raw_header_cleanup(void *data); +#endif static int @@ -77,6 +80,11 @@ ngx_http_lua_ngx_req_raw_header(lua_State *L) size_t size; ngx_buf_t *b, *first = NULL; ngx_int_t i, j; +#if nginx_version >= 1011011 + ngx_buf_t **bb; + ngx_chain_t *cl; + ngx_http_lua_main_conf_t *lmcf; +#endif ngx_connection_t *c; ngx_http_request_t *r, *mr; ngx_http_connection_t *hc; @@ -93,6 +101,10 @@ ngx_http_lua_ngx_req_raw_header(lua_State *L) return luaL_error(L, "no request object found"); } +#if nginx_version >= 1011011 + lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); +#endif + ngx_http_lua_check_fake_request(L, r); mr = r->main; @@ -109,8 +121,13 @@ ngx_http_lua_ngx_req_raw_header(lua_State *L) dd("hc->nbusy: %d", (int) hc->nbusy); if (hc->nbusy) { +#if nginx_version >= 1011011 + dd("hc->busy: %p %p %p %p", hc->busy->buf->start, hc->busy->buf->pos, + hc->busy->buf->last, hc->busy->buf->end); +#else dd("hc->busy: %p %p %p %p", hc->busy[0]->start, hc->busy[0]->pos, hc->busy[0]->last, hc->busy[0]->end); +#endif } dd("request line: %p %p", mr->request_line.data, @@ -146,9 +163,37 @@ ngx_http_lua_ngx_req_raw_header(lua_State *L) dd("size: %d", (int) size); if (hc->nbusy) { +#if nginx_version >= 1011011 + if (hc->nbusy > lmcf->busy_buf_ptr_count) { + if (lmcf->busy_buf_ptrs) { + ngx_free(lmcf->busy_buf_ptrs); + } + + lmcf->busy_buf_ptrs = ngx_alloc(hc->nbusy * sizeof(ngx_buf_t *), + r->connection->log); + + if (lmcf->busy_buf_ptrs == NULL) { + return luaL_error(L, "no memory"); + } + + lmcf->busy_buf_ptr_count = hc->nbusy; + } + + bb = lmcf->busy_buf_ptrs; + for (cl = hc->busy; cl; cl = cl->next) { + *bb++ = cl->buf; + } +#endif b = NULL; + +#if nginx_version >= 1011011 + bb = lmcf->busy_buf_ptrs; + for (i = hc->nbusy; i > 0; i--) { + b = bb[i - 1]; +#else for (i = 0; i < hc->nbusy; i++) { b = hc->busy[i]; +#endif dd("busy buf: %d: [%.*s]", (int) i, (int) (b->pos - b->start), b->start); @@ -223,8 +268,15 @@ ngx_http_lua_ngx_req_raw_header(lua_State *L) } if (hc->nbusy) { + +#if nginx_version >= 1011011 + bb = lmcf->busy_buf_ptrs; + for (i = hc->nbusy - 1; i >= 0; i--) { + b = bb[i]; +#else for (i = 0; i < hc->nbusy; i++) { b = hc->busy[i]; +#endif if (!found) { if (b != first) { @@ -444,6 +496,8 @@ ngx_http_lua_ngx_resp_get_headers(lua_State *L) ngx_list_part_t *part; ngx_table_elt_t *header; ngx_http_request_t *r; + ngx_http_lua_ctx_t *ctx; + ngx_int_t rc; u_char *lowcase_key = NULL; size_t lowcase_key_sz = 0; ngx_uint_t i; @@ -475,6 +529,22 @@ ngx_http_lua_ngx_resp_get_headers(lua_State *L) return luaL_error(L, "no request object found"); } + ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); + if (ctx == NULL) { + return luaL_error(L, "no ctx found"); + } + + if (!ctx->headers_set) { + rc = ngx_http_lua_set_content_type(r); + if (rc != NGX_OK) { + return luaL_error(L, + "failed to set default content type: %d", + (int) rc); + } + + ctx->headers_set = 1; + } + ngx_http_lua_check_fake_request(L, r); part = &r->headers_out.headers.part; @@ -603,12 +673,19 @@ ngx_http_lua_ngx_header_get(lua_State *L) ngx_uint_t i; size_t len; ngx_http_lua_loc_conf_t *llcf; + ngx_http_lua_ctx_t *ctx; + ngx_int_t rc; r = ngx_http_lua_get_req(L); if (r == NULL) { return luaL_error(L, "no request object found"); } + ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); + if (ctx == NULL) { + return luaL_error(L, "no ctx found"); + } + ngx_http_lua_check_fake_request(L, r); /* we skip the first argument that is the table */ @@ -640,6 +717,17 @@ ngx_http_lua_ngx_header_get(lua_State *L) key.len = len; + if (!ctx->headers_set) { + rc = ngx_http_lua_set_content_type(r); + if (rc != NGX_OK) { + return luaL_error(L, + "failed to set default content type: %d", + (int) rc); + } + + ctx->headers_set = 1; + } + return ngx_http_lua_get_output_header(L, r, &key); } @@ -718,7 +806,7 @@ ngx_http_lua_ngx_header_set(lua_State *L) ngx_str_null(&value); } else if (lua_type(L, 3) == LUA_TTABLE) { - n = luaL_getn(L, 3); + n = lua_objlen(L, 3); if (n == 0) { ngx_str_null(&value); @@ -852,7 +940,7 @@ ngx_http_lua_ngx_req_header_set_helper(lua_State *L) ngx_str_null(&value); } else if (lua_type(L, 2) == LUA_TTABLE) { - n = luaL_getn(L, 2); + n = lua_objlen(L, 2); if (n == 0) { ngx_str_null(&value); @@ -1262,6 +1350,7 @@ ngx_http_lua_ffi_get_resp_header(ngx_http_request_t *r, ngx_uint_t i; ngx_table_elt_t *h; ngx_list_part_t *part; + ngx_http_lua_ctx_t *ctx; ngx_http_lua_loc_conf_t *llcf; @@ -1269,6 +1358,21 @@ ngx_http_lua_ffi_get_resp_header(ngx_http_request_t *r, return NGX_HTTP_LUA_FFI_BAD_CONTEXT; } + ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); + if (ctx == NULL) { + /* *errmsg = "no ctx found"; */ + return NGX_ERROR; + } + + if (!ctx->headers_set) { + if (ngx_http_lua_set_content_type(r) != NGX_OK) { + /* *errmsg = "failed to set default content type"; */ + return NGX_ERROR; + } + + ctx->headers_set = 1; + } + llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module); if (llcf->transform_underscores_in_resp_headers && memchr(key, '_', key_len) != NULL) @@ -1379,4 +1483,20 @@ ngx_http_lua_ffi_get_resp_header(ngx_http_request_t *r, #endif /* NGX_LUA_NO_FFI_API */ +#if nginx_version >= 1011011 +void +ngx_http_lua_ngx_raw_header_cleanup(void *data) +{ + ngx_http_lua_main_conf_t *lmcf; + + lmcf = (ngx_http_lua_main_conf_t *) data; + + if (lmcf->busy_buf_ptrs) { + ngx_free(lmcf->busy_buf_ptrs); + lmcf->busy_buf_ptrs = NULL; + } +} +#endif + + /* vi:set ft=c ts=4 sw=4 et fdm=marker: */ diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_headers.h b/debian/modules/nginx-lua/src/ngx_http_lua_headers.h index 39f1114..ee4d21c 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_headers.h +++ b/debian/modules/nginx-lua/src/ngx_http_lua_headers.h @@ -15,6 +15,9 @@ void ngx_http_lua_inject_resp_header_api(lua_State *L); void ngx_http_lua_inject_req_header_api(lua_State *L); void ngx_http_lua_create_headers_metatable(ngx_log_t *log, lua_State *L); +#if nginx_version >= 1011011 +void ngx_http_lua_ngx_raw_header_cleanup(void *data); +#endif #endif /* _NGX_HTTP_LUA_HEADERS_H_INCLUDED_ */ diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_log.c b/debian/modules/nginx-lua/src/ngx_http_lua_log.c index c2b2269..c18e6b0 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_log.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_log.c @@ -13,6 +13,7 @@ #include "ngx_http_lua_log.h" #include "ngx_http_lua_util.h" +#include "ngx_http_lua_log_ringbuf.h" static int ngx_http_lua_print(lua_State *L); @@ -313,4 +314,120 @@ ngx_http_lua_inject_log_consts(lua_State *L) /* }}} */ } + +#ifdef HAVE_INTERCEPT_ERROR_LOG_PATCH +ngx_int_t +ngx_http_lua_capture_log_handler(ngx_log_t *log, + ngx_uint_t level, u_char *buf, size_t n) +{ + ngx_http_lua_log_ringbuf_t *ringbuf; + + dd("enter"); + + ringbuf = (ngx_http_lua_log_ringbuf_t *) + ngx_cycle->intercept_error_log_data; + + if (level > ringbuf->filter_level) { + return NGX_OK; + } + + ngx_http_lua_log_ringbuf_write(ringbuf, level, buf, n); + + dd("capture log: %s\n", buf); + + return NGX_OK; +} +#endif + + +#ifndef NGX_LUA_NO_FFI_API +int +ngx_http_lua_ffi_errlog_set_filter_level(int level, u_char *err, size_t *errlen) +{ +#ifdef HAVE_INTERCEPT_ERROR_LOG_PATCH + ngx_http_lua_log_ringbuf_t *ringbuf; + + ringbuf = ngx_cycle->intercept_error_log_data; + + if (ringbuf == NULL) { + *errlen = ngx_snprintf(err, *errlen, + "directive \"lua_capture_error_log\" is not set") + - err; + return NGX_ERROR; + } + + if (level > NGX_LOG_DEBUG || level < NGX_LOG_STDERR) { + *errlen = ngx_snprintf(err, *errlen, "bad log level: %d", level) + - err; + return NGX_ERROR; + } + + ringbuf->filter_level = level; + return NGX_OK; +#else + *errlen = ngx_snprintf(err, *errlen, + "missing the capture error log patch for nginx") + - err; + return NGX_ERROR; +#endif +} + + +int +ngx_http_lua_ffi_errlog_get_msg(char **log, int *loglevel, u_char *err, + size_t *errlen, double *log_time) +{ +#ifdef HAVE_INTERCEPT_ERROR_LOG_PATCH + ngx_uint_t loglen; + + ngx_http_lua_log_ringbuf_t *ringbuf; + + ringbuf = ngx_cycle->intercept_error_log_data; + + if (ringbuf == NULL) { + *errlen = ngx_snprintf(err, *errlen, + "directive \"lua_capture_error_log\" is not set") + - err; + return NGX_ERROR; + } + + if (ringbuf->count == 0) { + return NGX_DONE; + } + + ngx_http_lua_log_ringbuf_read(ringbuf, loglevel, (void **) log, &loglen, + log_time); + return loglen; +#else + *errlen = ngx_snprintf(err, *errlen, + "missing the capture error log patch for nginx") + - err; + return NGX_ERROR; +#endif +} + + +int +ngx_http_lua_ffi_errlog_get_sys_filter_level(ngx_http_request_t *r) +{ + ngx_log_t *log; + int log_level; + + if (r && r->connection && r->connection->log) { + log = r->connection->log; + + } else { + log = ngx_cycle->log; + } + + log_level = log->log_level; + if (log_level == NGX_LOG_DEBUG_ALL) { + log_level = NGX_LOG_DEBUG; + } + + return log_level; +} + +#endif + /* vi:set ft=c ts=4 sw=4 et fdm=marker: */ diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_log.h b/debian/modules/nginx-lua/src/ngx_http_lua_log.h index 42f1839..56cd771 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_log.h +++ b/debian/modules/nginx-lua/src/ngx_http_lua_log.h @@ -13,6 +13,10 @@ void ngx_http_lua_inject_log_api(lua_State *L); +#ifdef HAVE_INTERCEPT_ERROR_LOG_PATCH +ngx_int_t ngx_http_lua_capture_log_handler(ngx_log_t *log, + ngx_uint_t level, u_char *buf, size_t n); +#endif #endif /* _NGX_HTTP_LUA_LOG_H_INCLUDED_ */ diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_log_ringbuf.c b/debian/modules/nginx-lua/src/ngx_http_lua_log_ringbuf.c new file mode 100644 index 0000000..0464069 --- /dev/null +++ b/debian/modules/nginx-lua/src/ngx_http_lua_log_ringbuf.c @@ -0,0 +1,225 @@ + +#ifndef DDEBUG +#define DDEBUG 0 +#endif +#include "ddebug.h" + + +#include "ngx_http_lua_common.h" +#include "ngx_http_lua_log_ringbuf.h" + + +typedef struct { + double time; + unsigned len; + unsigned log_level; +} ngx_http_lua_log_ringbuf_header_t; + + +enum { + HEADER_LEN = sizeof(ngx_http_lua_log_ringbuf_header_t) +}; + + +static void *ngx_http_lua_log_ringbuf_next_header( + ngx_http_lua_log_ringbuf_t *rb); +static void ngx_http_lua_log_ringbuf_append( + ngx_http_lua_log_ringbuf_t *rb, int log_level, void *buf, int n); +static size_t ngx_http_lua_log_ringbuf_free_spaces( + ngx_http_lua_log_ringbuf_t *rb); + + +void +ngx_http_lua_log_ringbuf_init(ngx_http_lua_log_ringbuf_t *rb, void *buf, + size_t len) +{ + rb->data = buf; + rb->size = len; + + rb->tail = rb->data; + rb->head = rb->data; + rb->sentinel = rb->data + rb->size; + rb->count = 0; + rb->filter_level = NGX_LOG_DEBUG; + + return; +} + + +void +ngx_http_lua_log_ringbuf_reset(ngx_http_lua_log_ringbuf_t *rb) +{ + rb->tail = rb->data; + rb->head = rb->data; + rb->sentinel = rb->data + rb->size; + rb->count = 0; + + return; +} + + +/* + * get the next data header, it'll skip the useless data space or + * placehold data + */ +static void * +ngx_http_lua_log_ringbuf_next_header(ngx_http_lua_log_ringbuf_t *rb) +{ + /* useless data */ + if (rb->size - (rb->head - rb->data) < HEADER_LEN) + { + return rb->data; + } + + /* placehold data */ + if (rb->head >= rb->sentinel) { + return rb->data; + } + + return rb->head; +} + + +/* append data to ring buffer directly */ +static void +ngx_http_lua_log_ringbuf_append(ngx_http_lua_log_ringbuf_t *rb, + int log_level, void *buf, int n) +{ + ngx_http_lua_log_ringbuf_header_t *head; + ngx_time_t *tp; + + head = (ngx_http_lua_log_ringbuf_header_t *) rb->tail; + head->len = n; + head->log_level = log_level; + + tp = ngx_timeofday(); + head->time = tp->sec + tp->msec / 1000.0L; + + rb->tail += HEADER_LEN; + ngx_memcpy(rb->tail, buf, n); + rb->tail += n; + rb->count++; + + if (rb->tail > rb->sentinel) { + rb->sentinel = rb->tail; + } + + return; +} + + +/* throw away data at head */ +static void +ngx_http_lua_log_ringbuf_throw_away(ngx_http_lua_log_ringbuf_t *rb) +{ + ngx_http_lua_log_ringbuf_header_t *head; + + if (rb->count == 0) { + return; + } + + head = (ngx_http_lua_log_ringbuf_header_t *) rb->head; + + rb->head += HEADER_LEN + head->len; + rb->count--; + + if (rb->count == 0) { + ngx_http_lua_log_ringbuf_reset(rb); + } + + rb->head = ngx_http_lua_log_ringbuf_next_header(rb); + + return; +} + + +/* size of free spaces */ +static size_t +ngx_http_lua_log_ringbuf_free_spaces(ngx_http_lua_log_ringbuf_t *rb) +{ + if (rb->count == 0) { + return rb->size; + } + + if (rb->tail > rb->head) { + return rb->data + rb->size - rb->tail; + } + + return rb->head - rb->tail; +} + + +/* + * try to write log data to ring buffer, throw away old data + * if there was not enough free spaces. + */ +ngx_int_t +ngx_http_lua_log_ringbuf_write(ngx_http_lua_log_ringbuf_t *rb, int log_level, + void *buf, size_t n) +{ + if (n + HEADER_LEN > rb->size) { + return NGX_ERROR; + } + + if (ngx_http_lua_log_ringbuf_free_spaces(rb) < n + HEADER_LEN) { + /* if the right space is not enough, mark it as placehold data */ + if ((size_t)(rb->data + rb->size - rb->tail) < n + HEADER_LEN) { + + while (rb->head >= rb->tail && rb->count) { + /* head is after tail, so we will throw away all data between + * head and sentinel */ + ngx_http_lua_log_ringbuf_throw_away(rb); + } + + rb->sentinel = rb->tail; + rb->tail = rb->data; + } + + while (ngx_http_lua_log_ringbuf_free_spaces(rb) < n + HEADER_LEN) { + ngx_http_lua_log_ringbuf_throw_away(rb); + } + } + + ngx_http_lua_log_ringbuf_append(rb, log_level, buf, n); + + return NGX_OK; +} + + +/* read log from ring buffer, do reset if all of the logs were readed. */ +ngx_int_t +ngx_http_lua_log_ringbuf_read(ngx_http_lua_log_ringbuf_t *rb, int *log_level, + void **buf, size_t *n, double *log_time) +{ + ngx_http_lua_log_ringbuf_header_t *head; + + if (rb->count == 0) { + return NGX_ERROR; + } + + head = (ngx_http_lua_log_ringbuf_header_t *) rb->head; + + if (rb->head >= rb->sentinel) { + return NGX_ERROR; + } + + *log_level = head->log_level; + *n = head->len; + rb->head += HEADER_LEN; + *buf = rb->head; + rb->head += head->len; + + if (log_time) { + *log_time = head->time; + } + + rb->count--; + + if (rb->count == 0) { + ngx_http_lua_log_ringbuf_reset(rb); + } + + rb->head = ngx_http_lua_log_ringbuf_next_header(rb); + + return NGX_OK; +} diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_log_ringbuf.h b/debian/modules/nginx-lua/src/ngx_http_lua_log_ringbuf.h new file mode 100644 index 0000000..c9c2c2d --- /dev/null +++ b/debian/modules/nginx-lua/src/ngx_http_lua_log_ringbuf.h @@ -0,0 +1,31 @@ + +#ifndef _NGX_HTTP_LUA_RINGBUF_H_INCLUDED_ +#define _NGX_HTTP_LUA_RINGBUF_H_INCLUDED_ + + +#include "ngx_http_lua_common.h" + + +typedef struct { + ngx_uint_t filter_level; + char *tail; /* writed point */ + char *head; /* readed point */ + char *data; /* buffer */ + char *sentinel; + size_t size; /* buffer total size */ + size_t count; /* count of logs */ +} ngx_http_lua_log_ringbuf_t; + + +void ngx_http_lua_log_ringbuf_init(ngx_http_lua_log_ringbuf_t *rb, + void *buf, size_t len); +void ngx_http_lua_log_ringbuf_reset(ngx_http_lua_log_ringbuf_t *rb); +ngx_int_t ngx_http_lua_log_ringbuf_read(ngx_http_lua_log_ringbuf_t *rb, + int *log_level, void **buf, size_t *n, double *log_time); +ngx_int_t ngx_http_lua_log_ringbuf_write(ngx_http_lua_log_ringbuf_t *rb, + int log_level, void *buf, size_t n); + + +#endif /* _NGX_HTTP_LUA_RINGBUF_H_INCLUDED_ */ + +/* vi:set ft=c ts=4 sw=4 et fdm=marker: */ diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_module.c b/debian/modules/nginx-lua/src/ngx_http_lua_module.c index 6e93c8e..9d914e8 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_module.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_module.c @@ -28,6 +28,7 @@ #include "ngx_http_lua_ssl_certby.h" #include "ngx_http_lua_ssl_session_storeby.h" #include "ngx_http_lua_ssl_session_fetchby.h" +#include "ngx_http_lua_headers.h" static void *ngx_http_lua_create_main_conf(ngx_conf_t *cf); @@ -45,14 +46,6 @@ static char *ngx_http_lua_lowat_check(ngx_conf_t *cf, void *post, void *data); static ngx_int_t ngx_http_lua_set_ssl(ngx_conf_t *cf, ngx_http_lua_loc_conf_t *llcf); #endif -#if (NGX_HTTP_LUA_HAVE_MMAP_SBRK) && (NGX_LINUX) -/* we cannot use "static" for this function since it may lead to compiler - * warnings */ -void ngx_http_lua_limit_data_segment(void); -# if !(NGX_HTTP_LUA_HAVE_CONSTRUCTOR) -static ngx_int_t ngx_http_lua_pre_config(ngx_conf_t *cf); -# endif -#endif static char *ngx_http_lua_malloc_trim(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); @@ -101,6 +94,13 @@ static ngx_command_t ngx_http_lua_cmds[] = { 0, NULL }, + { ngx_string("lua_capture_error_log"), + NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, + ngx_http_lua_capture_error_log, + 0, + 0, + NULL }, + #if (NGX_PCRE) { ngx_string("lua_regex_cache_max_entries"), NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, @@ -592,13 +592,7 @@ static ngx_command_t ngx_http_lua_cmds[] = { ngx_http_module_t ngx_http_lua_module_ctx = { -#if (NGX_HTTP_LUA_HAVE_MMAP_SBRK) \ - && (NGX_LINUX) \ - && !(NGX_HTTP_LUA_HAVE_CONSTRUCTOR) - ngx_http_lua_pre_config, /* preconfiguration */ -#else NULL, /* preconfiguration */ -#endif ngx_http_lua_init, /* postconfiguration */ ngx_http_lua_create_main_conf, /* create main configuration */ @@ -638,7 +632,7 @@ ngx_http_lua_init(ngx_conf_t *cf) volatile ngx_cycle_t *saved_cycle; ngx_http_core_main_conf_t *cmcf; ngx_http_lua_main_conf_t *lmcf; -#ifndef NGX_LUA_NO_FFI_API +#if !defined(NGX_LUA_NO_FFI_API) || nginx_version >= 1011011 ngx_pool_cleanup_t *cln; #endif @@ -730,6 +724,16 @@ ngx_http_lua_init(ngx_conf_t *cf) cln->handler = ngx_http_lua_sema_mm_cleanup; #endif +#if nginx_version >= 1011011 + cln = ngx_pool_cleanup_add(cf->pool, 0); + if (cln == NULL) { + return NGX_ERROR; + } + + cln->data = lmcf; + cln->handler = ngx_http_lua_ngx_raw_header_cleanup; +#endif + if (lmcf->lua == NULL) { dd("initializing lua vm"); @@ -817,6 +821,7 @@ ngx_http_lua_create_main_conf(ngx_conf_t *cf) * lmcf->running_timers = 0; * lmcf->watcher = NULL; * lmcf->regex_cache_entries = 0; + * lmcf->jit_stack = NULL; * lmcf->shm_zones = NULL; * lmcf->init_handler = NULL; * lmcf->init_src = { 0, NULL }; @@ -955,7 +960,7 @@ ngx_http_lua_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) #ifdef LIBRESSL_VERSION_NUMBER ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "LibreSSL does not support ssl_ceritificate_by_lua*"); + "LibreSSL does not support ssl_certificate_by_lua*"); return NGX_CONF_ERROR; #else @@ -967,7 +972,7 @@ ngx_http_lua_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) # else ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "OpenSSL too old to support ssl_ceritificate_by_lua*"); + "OpenSSL too old to support ssl_certificate_by_lua*"); return NGX_CONF_ERROR; # endif @@ -1267,37 +1272,6 @@ ngx_http_lua_set_ssl(ngx_conf_t *cf, ngx_http_lua_loc_conf_t *llcf) #endif /* NGX_HTTP_SSL */ -#if (NGX_HTTP_LUA_HAVE_MMAP_SBRK) \ - && (NGX_LINUX) \ - && !(NGX_HTTP_LUA_HAVE_CONSTRUCTOR) -static ngx_int_t -ngx_http_lua_pre_config(ngx_conf_t *cf) -{ - ngx_http_lua_limit_data_segment(); - return NGX_OK; -} -#endif - - -/* - * we simply assume that LuaJIT is used. it does little harm when the - * standard Lua 5.1 interpreter is used instead. - */ -#if (NGX_HTTP_LUA_HAVE_MMAP_SBRK) && (NGX_LINUX) -# if (NGX_HTTP_LUA_HAVE_CONSTRUCTOR) -__attribute__((constructor)) -# endif -void -ngx_http_lua_limit_data_segment(void) -{ - if (sbrk(0) < (void *) 0x40000000LL) { - mmap(ngx_align_ptr(sbrk(0), getpagesize()), 1, PROT_READ, - MAP_FIXED|MAP_PRIVATE|MAP_ANON, -1, 0); - } -} -#endif - - static char * ngx_http_lua_malloc_trim(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_regex.c b/debian/modules/nginx-lua/src/ngx_http_lua_regex.c index d882061..80519ec 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_regex.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_regex.c @@ -17,14 +17,6 @@ #include "ngx_http_lua_script.h" #include "ngx_http_lua_pcrefix.h" #include "ngx_http_lua_util.h" -#include - - -#if (PCRE_MAJOR > 8) || (PCRE_MAJOR == 8 && PCRE_MINOR >= 21) -# define LUA_HAVE_PCRE_JIT 1 -#else -# define LUA_HAVE_PCRE_JIT 0 -#endif #if (PCRE_MAJOR >= 6) @@ -42,6 +34,8 @@ #define NGX_LUA_RE_DFA_MODE_WORKSPACE_COUNT (100) +#define NGX_LUA_RE_MIN_JIT_STACK_SIZE 32 * 1024 + typedef struct { #ifndef NGX_LUA_NO_FFI_API @@ -364,6 +358,10 @@ ngx_http_lua_ngx_re_match_helper(lua_State *L, int wantcaps) sd = pcre_study(re_comp.regex, PCRE_STUDY_JIT_COMPILE, &msg); + if (sd && lmcf->jit_stack) { + pcre_assign_jit_stack(sd, NULL, lmcf->jit_stack); + } + ngx_http_lua_pcre_malloc_done(old_pool); # if (NGX_DEBUG) @@ -826,6 +824,10 @@ ngx_http_lua_ngx_re_gmatch(lua_State *L) sd = pcre_study(re_comp.regex, PCRE_STUDY_JIT_COMPILE, &msg); + if (sd && lmcf->jit_stack) { + pcre_assign_jit_stack(sd, NULL, lmcf->jit_stack); + } + ngx_http_lua_pcre_malloc_done(old_pool); # if (NGX_DEBUG) @@ -1922,6 +1924,60 @@ error: } +ngx_int_t +ngx_http_lua_ffi_set_jit_stack_size(int size, u_char *errstr, + size_t *errstr_size) +{ +#if LUA_HAVE_PCRE_JIT + + ngx_http_lua_main_conf_t *lmcf; + ngx_pool_t *pool, *old_pool; + + lmcf = ngx_http_cycle_get_module_main_conf(ngx_cycle, + ngx_http_lua_module); + + if (size < NGX_LUA_RE_MIN_JIT_STACK_SIZE) { + size = NGX_LUA_RE_MIN_JIT_STACK_SIZE; + } + + pool = lmcf->pool; + + dd("server pool %p", lmcf->pool); + + if (lmcf->jit_stack) { + old_pool = ngx_http_lua_pcre_malloc_init(pool); + + pcre_jit_stack_free(lmcf->jit_stack); + + ngx_http_lua_pcre_malloc_done(old_pool); + } + + old_pool = ngx_http_lua_pcre_malloc_init(pool); + + lmcf->jit_stack = pcre_jit_stack_alloc(NGX_LUA_RE_MIN_JIT_STACK_SIZE, + size); + + ngx_http_lua_pcre_malloc_done(old_pool); + + if (lmcf->jit_stack == NULL) { + *errstr_size = ngx_snprintf(errstr, *errstr_size, + "pcre jit stack allocation failed") + - errstr; + return NGX_ERROR; + } + + return NGX_OK; + +#else /* LUA_HAVE_PCRE_JIT */ + + *errstr_size = ngx_snprintf(errstr, *errstr_size, + "no pcre jit support found") - errstr; + return NGX_ERROR; + +#endif /* LUA_HAVE_PCRE_JIT */ +} + + void ngx_http_lua_inject_regex_api(lua_State *L) { @@ -2170,6 +2226,9 @@ ngx_http_lua_ffi_compile_regex(const unsigned char *pat, size_t pat_len, goto error; } + lmcf = ngx_http_cycle_get_module_main_conf(ngx_cycle, + ngx_http_lua_module); + #if (LUA_HAVE_PCRE_JIT) if (flags & NGX_LUA_RE_MODE_JIT) { @@ -2205,10 +2264,11 @@ ngx_http_lua_ffi_compile_regex(const unsigned char *pat, size_t pat_len, ngx_http_lua_pcre_malloc_done(old_pool); } -#endif /* LUA_HAVE_PCRE_JIT */ + if (sd && lmcf->jit_stack) { + pcre_assign_jit_stack(sd, NULL, lmcf->jit_stack); + } - lmcf = ngx_http_cycle_get_module_main_conf(ngx_cycle, - ngx_http_lua_module); +#endif /* LUA_HAVE_PCRE_JIT */ if (sd && lmcf && lmcf->regex_match_limit > 0) { sd->flags |= PCRE_EXTRA_MATCH_LIMIT; diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_regex.h b/debian/modules/nginx-lua/src/ngx_http_lua_regex.h index f5f8e2f..03dffb8 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_regex.h +++ b/debian/modules/nginx-lua/src/ngx_http_lua_regex.h @@ -14,6 +14,8 @@ #if (NGX_PCRE) void ngx_http_lua_inject_regex_api(lua_State *L); +ngx_int_t ngx_http_lua_ffi_set_jit_stack_size(int size, u_char *errstr, + size_t *errstr_size); #endif diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_semaphore.c b/debian/modules/nginx-lua/src/ngx_http_lua_semaphore.c index 8a3f832..eda0141 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_semaphore.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_semaphore.c @@ -387,8 +387,8 @@ ngx_http_lua_ffi_sema_wait(ngx_http_request_t *r, return NGX_ERROR; } - /* we keep the order, will resume the older waited firtly - * in ngx_http_lua_sema_handler + /* we keep the order, will first resume the thread waiting for the + * longest time in ngx_http_lua_sema_handler */ if (ngx_queue_empty(&sem->wait_queue) && sem->resource_count > 0) { @@ -557,8 +557,11 @@ ngx_http_lua_ffi_sema_gc(ngx_http_lua_sema_t *sem) return; } - if (!ngx_queue_empty(&sem->wait_queue)) { - ngx_log_error(NGX_LOG_CRIT, ngx_cycle->log, 0, + if (!ngx_terminate + && !ngx_quit + && !ngx_queue_empty(&sem->wait_queue)) + { + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "in lua semaphore gc wait queue is" " not empty while the semaphore %p is being " "destroyed", sem); diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_sleep.c b/debian/modules/nginx-lua/src/ngx_http_lua_sleep.c index 4c0d016..ffee97f 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_sleep.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_sleep.c @@ -72,10 +72,25 @@ ngx_http_lua_ngx_sleep(lua_State *L) coctx->sleep.data = coctx; coctx->sleep.log = r->connection->log; - dd("adding timer with delay %lu ms, r:%.*s", (unsigned long) delay, - (int) r->uri.len, r->uri.data); + if (delay == 0) { +#ifdef HAVE_POSTED_DELAYED_EVENTS_PATCH + dd("posting 0 sec sleep event to head of delayed queue"); - ngx_add_timer(&coctx->sleep, (ngx_msec_t) delay); + coctx->sleep.delayed = 1; + ngx_post_event(&coctx->sleep, &ngx_posted_delayed_events); +#else + ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, "ngx.sleep(0)" + " called without delayed events patch, this will" + " hurt performance"); + ngx_add_timer(&coctx->sleep, (ngx_msec_t) delay); +#endif + + } else { + dd("adding timer with delay %lu ms, r:%.*s", (unsigned long) delay, + (int) r->uri.len, r->uri.data); + + ngx_add_timer(&coctx->sleep, (ngx_msec_t) delay); + } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua ready to sleep for %d ms", delay); @@ -147,6 +162,15 @@ ngx_http_lua_sleep_cleanup(void *data) ngx_del_timer(&coctx->sleep); } + +#ifdef HAVE_POSTED_DELAYED_EVENTS_PATCH + if (coctx->sleep.posted) { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, + "lua clean up the posted event for pending ngx.sleep"); + + ngx_delete_posted_event(&coctx->sleep); + } +#endif } diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_socket_tcp.c b/debian/modules/nginx-lua/src/ngx_http_lua_socket_tcp.c index 6db6e2d..382a94d 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_socket_tcp.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_socket_tcp.c @@ -69,8 +69,6 @@ static void ngx_http_lua_socket_dummy_handler(ngx_http_request_t *r, ngx_http_lua_socket_tcp_upstream_t *u); static ngx_int_t ngx_http_lua_socket_tcp_read(ngx_http_request_t *r, ngx_http_lua_socket_tcp_upstream_t *u); -static void ngx_http_lua_socket_read_handler(ngx_http_request_t *r, - ngx_http_lua_socket_tcp_upstream_t *u); static int ngx_http_lua_socket_tcp_receive_retval_handler(ngx_http_request_t *r, ngx_http_lua_socket_tcp_upstream_t *u, lua_State *L); static ngx_int_t ngx_http_lua_socket_read_line(void *data, ssize_t bytes); @@ -501,6 +499,12 @@ ngx_http_lua_socket_tcp_connect(lua_State *L) n--; } + /* the fourth argument is not a table */ + if (n == 4) { + lua_pop(L, 1); + n--; + } + if (n == 3) { port = luaL_checkinteger(L, 3); @@ -1208,11 +1212,12 @@ ngx_http_lua_socket_tcp_sslhandshake(lua_State *L) ngx_http_lua_socket_tcp_upstream_t *u; - /* Lua function arguments: self [,session] [,host] [,verify] */ + /* Lua function arguments: self [,session] [,host] [,verify] + [,send_status_req] */ n = lua_gettop(L); if (n < 1 || n > 5) { - return luaL_error(L, "ngx.socket connect: expecting 1 ~ 5 " + return luaL_error(L, "ngx.socket sslhandshake: expecting 1 ~ 5 " "arguments (including the object), but seen %d", n); } @@ -1327,7 +1332,8 @@ ngx_http_lua_socket_tcp_sslhandshake(lua_State *L) #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME - if (SSL_set_tlsext_host_name(c->ssl->connection, name.data) + if (SSL_set_tlsext_host_name(c->ssl->connection, + (char *) name.data) == 0) { lua_pushnil(L); @@ -4412,15 +4418,18 @@ ngx_http_lua_req_socket_rev_handler(ngx_http_request_t *r) ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); if (ctx == NULL) { + r->read_event_handler = ngx_http_block_reading; return; } u = ctx->downstream; - if (u) { - u->read_event_handler(r, u); + if (u == NULL || u->peer.connection == NULL) { + r->read_event_handler = ngx_http_block_reading; + return; } -} + u->read_event_handler(r, u); +} static int ngx_http_lua_socket_tcp_getreusedtimes(lua_State *L) diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_ssl.h b/debian/modules/nginx-lua/src/ngx_http_lua_ssl.h index 7a245ff..acb8c4b 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_ssl.h +++ b/debian/modules/nginx-lua/src/ngx_http_lua_ssl.h @@ -12,6 +12,8 @@ #if (NGX_HTTP_SSL) + + typedef struct { ngx_connection_t *connection; /* original true connection */ ngx_http_request_t *request; /* fake request */ @@ -31,7 +33,6 @@ typedef struct { unsigned entered_cert_handler:1; unsigned entered_sess_fetch_handler:1; } ngx_http_lua_ssl_ctx_t; -#endif ngx_int_t ngx_http_lua_ssl_init(ngx_log_t *log); @@ -40,4 +41,7 @@ ngx_int_t ngx_http_lua_ssl_init(ngx_log_t *log); extern int ngx_http_lua_ssl_ctx_index; +#endif + + #endif /* _NGX_HTTP_LUA_SSL_H_INCLUDED_ */ diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_ssl_certby.c b/debian/modules/nginx-lua/src/ngx_http_lua_ssl_certby.c index aca4735..c3591d1 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_ssl_certby.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_ssl_certby.c @@ -193,6 +193,7 @@ ngx_http_lua_ssl_cert_handler(ngx_ssl_conn_t *ssl_conn, void *data) ngx_http_lua_srv_conf_t *lscf; ngx_http_core_loc_conf_t *clcf; ngx_http_lua_ssl_ctx_t *cctx; + ngx_http_core_srv_conf_t *cscf; c = ngx_ssl_get_connection(ssl_conn); @@ -298,6 +299,16 @@ ngx_http_lua_ssl_cert_handler(ngx_ssl_conn_t *ssl_conn, void *data) c->log->action = "loading SSL certificate by lua"; + if (lscf->srv.ssl_cert_handler == NULL) { + cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); + + ngx_log_error(NGX_LOG_ALERT, c->log, 0, + "no ssl_certificate_by_lua* defined in " + "server %V", &cscf->server_name); + + goto failed; + } + rc = lscf->srv.ssl_cert_handler(r, lscf, L); if (rc >= NGX_OK || rc == NGX_ERROR) { @@ -453,7 +464,9 @@ ngx_http_lua_ssl_cert_by_chunk(lua_State *L, ngx_http_request_t *r) if (ctx == NULL) { ctx = ngx_http_lua_create_ctx(r); if (ctx == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; + rc = NGX_ERROR; + ngx_http_lua_finalize_request(r, rc); + return rc; } } else { @@ -470,7 +483,9 @@ ngx_http_lua_ssl_cert_by_chunk(lua_State *L, ngx_http_request_t *r) ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "lua: failed to create new coroutine to handle request"); - return NGX_HTTP_INTERNAL_SERVER_ERROR; + rc = NGX_ERROR; + ngx_http_lua_finalize_request(r, rc); + return rc; } /* move code closure to new coroutine */ @@ -494,7 +509,9 @@ ngx_http_lua_ssl_cert_by_chunk(lua_State *L, ngx_http_request_t *r) if (ctx->cleanup == NULL) { cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; + rc = NGX_ERROR; + ngx_http_lua_finalize_request(r, rc); + return rc; } cln->handler = ngx_http_lua_request_cleanup_handler; @@ -1129,7 +1146,11 @@ ngx_http_lua_ffi_set_cert(ngx_http_request_t *r, # else +#ifdef OPENSSL_IS_BORINGSSL + size_t i; +#else int i; +#endif X509 *x509 = NULL; ngx_ssl_conn_t *ssl_conn; STACK_OF(X509) *chain = cdata; diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_ssl_ocsp.c b/debian/modules/nginx-lua/src/ngx_http_lua_ssl_ocsp.c index 3904aa8..31b4f24 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_ssl_ocsp.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_ssl_ocsp.c @@ -490,7 +490,6 @@ ngx_http_lua_ffi_ssl_set_ocsp_status_resp(ngx_http_request_t *r, dd("set ocsp resp: resp_len=%d", (int) resp_len); (void) SSL_set_tlsext_status_ocsp_resp(ssl_conn, p, resp_len); - ssl_conn->tlsext_status_expected = 1; return NGX_OK; diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_ssl_session_fetchby.c b/debian/modules/nginx-lua/src/ngx_http_lua_ssl_session_fetchby.c index 4c450b5..556b732 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_ssl_session_fetchby.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_ssl_session_fetchby.c @@ -107,7 +107,7 @@ ngx_http_lua_ssl_sess_fetch_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, dd("enter"); - /* must specifiy a content handler */ + /* must specify a content handler */ if (cmd->post == NULL) { return NGX_CONF_ERROR; } @@ -468,7 +468,9 @@ ngx_http_lua_ssl_sess_fetch_by_chunk(lua_State *L, ngx_http_request_t *r) if (ctx == NULL) { ctx = ngx_http_lua_create_ctx(r); if (ctx == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; + rc = NGX_ERROR; + ngx_http_lua_finalize_request(r, rc); + return rc; } } else { @@ -485,7 +487,9 @@ ngx_http_lua_ssl_sess_fetch_by_chunk(lua_State *L, ngx_http_request_t *r) ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "lua: failed to create new coroutine to handle request"); - return NGX_HTTP_INTERNAL_SERVER_ERROR; + rc = NGX_ERROR; + ngx_http_lua_finalize_request(r, rc); + return rc; } /* move code closure to new coroutine */ @@ -509,7 +513,9 @@ ngx_http_lua_ssl_sess_fetch_by_chunk(lua_State *L, ngx_http_request_t *r) if (ctx->cleanup == NULL) { cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; + rc = NGX_ERROR; + ngx_http_lua_finalize_request(r, rc); + return rc; } cln->handler = ngx_http_lua_request_cleanup_handler; diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_ssl_session_storeby.c b/debian/modules/nginx-lua/src/ngx_http_lua_ssl_session_storeby.c index b5596bc..bae8273 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_ssl_session_storeby.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_ssl_session_storeby.c @@ -105,7 +105,7 @@ ngx_http_lua_ssl_sess_store_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, dd("enter"); - /* must specifiy a content handler */ + /* must specify a content handler */ if (cmd->post == NULL) { return NGX_CONF_ERROR; } @@ -351,7 +351,9 @@ ngx_http_lua_ssl_sess_store_by_chunk(lua_State *L, ngx_http_request_t *r) if (ctx == NULL) { ctx = ngx_http_lua_create_ctx(r); if (ctx == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; + rc = NGX_ERROR; + ngx_http_lua_finalize_request(r, rc); + return rc; } } else { @@ -386,7 +388,7 @@ ngx_http_lua_ssl_sess_store_by_chunk(lua_State *L, ngx_http_request_t *r) dd("rc == %d", (int) rc); if (rc != 0) { - /* error occured when running loaded code */ + /* error occurred when running loaded code */ err_msg = (u_char *) lua_tolstring(L, -1, &len); if (err_msg == NULL) { diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_string.c b/debian/modules/nginx-lua/src/ngx_http_lua_string.c index 22b4c00..239b232 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_string.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_string.c @@ -125,12 +125,13 @@ ngx_http_lua_ngx_escape_uri(lua_State *L) return 1; } - escape = 2 * ngx_http_lua_escape_uri(NULL, src, len, NGX_ESCAPE_URI); + escape = 2 * ngx_http_lua_escape_uri(NULL, src, len, + NGX_ESCAPE_URI_COMPONENT); if (escape) { dlen = escape + len; dst = lua_newuserdata(L, dlen); - ngx_http_lua_escape_uri(dst, src, len, NGX_ESCAPE_URI); + ngx_http_lua_escape_uri(dst, src, len, NGX_ESCAPE_URI_COMPONENT); lua_pushlstring(L, (char *) dst, dlen); } @@ -751,14 +752,14 @@ size_t ngx_http_lua_ffi_uri_escaped_length(const u_char *src, size_t len) { return len + 2 * ngx_http_lua_escape_uri(NULL, (u_char *) src, len, - NGX_ESCAPE_URI); + NGX_ESCAPE_URI_COMPONENT); } void ngx_http_lua_ffi_escape_uri(const u_char *src, size_t len, u_char *dst) { - ngx_http_lua_escape_uri(dst, (u_char *) src, len, NGX_ESCAPE_URI); + ngx_http_lua_escape_uri(dst, (u_char *) src, len, NGX_ESCAPE_URI_COMPONENT); } #endif diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_timer.c b/debian/modules/nginx-lua/src/ngx_http_lua_timer.c index 01b4777..596b2f7 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_timer.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_timer.c @@ -21,11 +21,6 @@ typedef struct { void **srv_conf; void **loc_conf; - /* event ident must be after 3 words (i.e. 3 pointers' size) as in - * ngx_connection_t. and we use the Lua coroutine reference number as - * the event ident */ - int co_ref; - unsigned premature; /* :1 */ lua_State *co; ngx_pool_t *pool; @@ -36,12 +31,18 @@ typedef struct { ngx_http_lua_main_conf_t *lmcf; ngx_http_lua_vm_state_t *vm_state; + int co_ref; + unsigned delay:31; + unsigned premature:1; } ngx_http_lua_timer_ctx_t; static int ngx_http_lua_ngx_timer_at(lua_State *L); +static int ngx_http_lua_ngx_timer_every(lua_State *L); +static int ngx_http_lua_ngx_timer_helper(lua_State *L, int every); static int ngx_http_lua_ngx_timer_running_count(lua_State *L); static int ngx_http_lua_ngx_timer_pending_count(lua_State *L); +static ngx_int_t ngx_http_lua_timer_copy(ngx_http_lua_timer_ctx_t *old_tctx); static void ngx_http_lua_timer_handler(ngx_event_t *ev); static u_char *ngx_http_lua_log_timer_error(ngx_log_t *log, u_char *buf, size_t len); @@ -51,11 +52,14 @@ static void ngx_http_lua_abort_pending_timers(ngx_event_t *ev); void ngx_http_lua_inject_timer_api(lua_State *L) { - lua_createtable(L, 0 /* narr */, 3 /* nrec */); /* ngx.timer. */ + lua_createtable(L, 0 /* narr */, 4 /* nrec */); /* ngx.timer. */ lua_pushcfunction(L, ngx_http_lua_ngx_timer_at); lua_setfield(L, -2, "at"); + lua_pushcfunction(L, ngx_http_lua_ngx_timer_every); + lua_setfield(L, -2, "every"); + lua_pushcfunction(L, ngx_http_lua_ngx_timer_running_count); lua_setfield(L, -2, "running_count"); @@ -106,6 +110,24 @@ ngx_http_lua_ngx_timer_pending_count(lua_State *L) static int ngx_http_lua_ngx_timer_at(lua_State *L) +{ + return ngx_http_lua_ngx_timer_helper(L, 0); +} + + +/* + * TODO: return a timer handler instead which can be passed to + * the ngx.timer.cancel method to cancel the timer. + */ +static int +ngx_http_lua_ngx_timer_every(lua_State *L) +{ + return ngx_http_lua_ngx_timer_helper(L, 1); +} + + +static int +ngx_http_lua_ngx_timer_helper(lua_State *L, int every) { int nargs, co_ref; u_char *p; @@ -134,6 +156,10 @@ ngx_http_lua_ngx_timer_at(lua_State *L) delay = (ngx_msec_t) (luaL_checknumber(L, 1) * 1000); + if (every && delay == 0) { + return luaL_error(L, "delay cannot be zero"); + } + luaL_argcheck(L, lua_isfunction(L, 2) && !lua_iscfunction(L, 2), 2, "Lua function expected"); @@ -233,7 +259,7 @@ ngx_http_lua_ngx_timer_at(lua_State *L) lua_pushlightuserdata(L, &ngx_http_lua_coroutines_key); lua_rawget(L, LUA_REGISTRYINDEX); - /* L stack: time func [args] thread corountines */ + /* L stack: time func [args] thread coroutines */ lua_pushvalue(L, -2); @@ -265,6 +291,8 @@ ngx_http_lua_ngx_timer_at(lua_State *L) tctx = (ngx_http_lua_timer_ctx_t *) p; + tctx->delay = every ? delay : 0; + tctx->premature = 0; tctx->co_ref = co_ref; tctx->co = co; @@ -338,6 +366,164 @@ nomem: } +static ngx_int_t +ngx_http_lua_timer_copy(ngx_http_lua_timer_ctx_t *old_tctx) +{ + int nargs, co_ref, i; + u_char *p; + lua_State *vm; /* the main thread */ + lua_State *co; + lua_State *L; + ngx_event_t *ev = NULL; + ngx_http_lua_timer_ctx_t *tctx = NULL; + ngx_http_lua_main_conf_t *lmcf; + + /* L stack: func [args] */ + L = old_tctx->co; + + lmcf = old_tctx->lmcf; + + vm = old_tctx->vm_state ? old_tctx->vm_state->vm : lmcf->lua; + + co = lua_newthread(vm); + + lua_createtable(co, 0, 0); /* the new globals table */ + + /* co stack: global_tb */ + + lua_createtable(co, 0, 1); /* the metatable */ + ngx_http_lua_get_globals_table(co); + lua_setfield(co, -2, "__index"); + lua_setmetatable(co, -2); + + /* co stack: global_tb */ + + ngx_http_lua_set_globals_table(co); + + /* co stack: */ + + dd("stack top: %d", lua_gettop(L)); + + lua_xmove(vm, L, 1); /* move coroutine from main thread to L */ + + /* L stack: func [args] thread */ + /* vm stack: empty */ + + lua_pushvalue(L, 1); /* copy entry function to top of L*/ + + /* L stack: func [args] thread func */ + + lua_xmove(L, co, 1); /* move entry function from L to co */ + + /* L stack: func [args] thread */ + /* co stack: func */ + + ngx_http_lua_get_globals_table(co); + lua_setfenv(co, -2); + + /* co stack: func */ + + lua_pushlightuserdata(L, &ngx_http_lua_coroutines_key); + lua_rawget(L, LUA_REGISTRYINDEX); + + /* L stack: func [args] thread coroutines */ + + lua_pushvalue(L, -2); + + /* L stack: func [args] thread coroutines thread */ + + co_ref = luaL_ref(L, -2); + lua_pop(L, 2); + + /* L stack: func [args] */ + + nargs = lua_gettop(L); + if (nargs > 1) { + for (i = 2; i <= nargs; i++) { + lua_pushvalue(L, i); + } + + /* L stack: func [args] [args] */ + + lua_xmove(L, co, nargs - 1); + + /* L stack: func [args] */ + /* co stack: func [args] */ + } + + p = ngx_alloc(sizeof(ngx_event_t) + sizeof(ngx_http_lua_timer_ctx_t), + ngx_cycle->log); + if (p == NULL) { + goto nomem; + } + + ev = (ngx_event_t *) p; + + ngx_memzero(ev, sizeof(ngx_event_t)); + + p += sizeof(ngx_event_t); + + tctx = (ngx_http_lua_timer_ctx_t *) p; + + ngx_memcpy(tctx, old_tctx, sizeof(ngx_http_lua_timer_ctx_t)); + + tctx->co_ref = co_ref; + tctx->co = co; + + tctx->pool = ngx_create_pool(128, ngx_cycle->log); + if (tctx->pool == NULL) { + goto nomem; + } + + if (tctx->client_addr_text.len) { + tctx->client_addr_text.data = ngx_palloc(tctx->pool, + tctx->client_addr_text.len); + if (tctx->client_addr_text.data == NULL) { + goto nomem; + } + + ngx_memcpy(tctx->client_addr_text.data, old_tctx->client_addr_text.data, + tctx->client_addr_text.len); + } + + if (tctx->vm_state) { + tctx->vm_state->count++; + } + + ev->handler = ngx_http_lua_timer_handler; + ev->data = tctx; + ev->log = ngx_cycle->log; + + lmcf->pending_timers++; + + ngx_add_timer(ev, tctx->delay); + + return NGX_OK; + +nomem: + + if (tctx && tctx->pool) { + ngx_destroy_pool(tctx->pool); + } + + if (ev) { + ngx_free(ev); + } + + /* L stack: func [args] */ + + lua_pushlightuserdata(L, &ngx_http_lua_coroutines_key); + lua_rawget(L, LUA_REGISTRYINDEX); + luaL_unref(L, -1, co_ref); + + /* L stack: func [args] coroutines */ + + lua_pop(L, 1); + + return NGX_ERROR; +} + + static void ngx_http_lua_timer_handler(ngx_event_t *ev) { @@ -364,6 +550,15 @@ ngx_http_lua_timer_handler(ngx_event_t *ev) lmcf->pending_timers--; + if (!ngx_exiting && tctx.delay > 0) { + rc = ngx_http_lua_timer_copy(&tctx); + if (rc != NGX_OK) { + ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, + "failed to create the next timer of delay %ud ms", + (unsigned) tctx.delay); + } + } + if (lmcf->running_timers >= lmcf->max_running_timers) { ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, "%i lua_max_running_timers are not enough", diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_util.c b/debian/modules/nginx-lua/src/ngx_http_lua_util.c index 7f59833..c7bee3e 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_util.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_util.c @@ -51,6 +51,7 @@ #include "ngx_http_lua_socket_tcp.h" #include "ngx_http_lua_ssl_certby.h" #include "ngx_http_lua_ssl.h" +#include "ngx_http_lua_log_ringbuf.h" #if 1 @@ -918,7 +919,11 @@ ngx_http_lua_request_cleanup(ngx_http_lua_ctx_t *ctx, int forcible) #if 1 if (r->connection->fd == (ngx_socket_t) -1) { /* being a fake request */ - lmcf->running_timers--; + + if (ctx->context == NGX_HTTP_LUA_CONTEXT_TIMER) { + /* being a timer handler */ + lmcf->running_timers--; + } } #endif @@ -1835,6 +1840,26 @@ ngx_http_lua_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type) /* ~}| {zyx wvut srqp onml kjih gfed cba` */ 0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + }; + + /* not ALPHA, DIGIT, "-", ".", "_", "~" */ + + static uint32_t uri_component[] = { + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + + /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ + 0xfc00987d, /* 1111 1100 0000 0000 1001 1000 0111 1101 */ + + /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */ + 0x78000001, /* 0111 1000 0000 0000 0000 0000 0000 0001 */ + + /* ~}| {zyx wvut srqp onml kjih gfed cba` */ + 0xb8000001, /* 1011 1000 0000 0000 0000 0000 0000 0001 */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ @@ -1904,8 +1929,7 @@ ngx_http_lua_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type) /* mail_auth is the same as memcached */ static uint32_t *map[] = - { uri, args, html, refresh, memcached, memcached }; - + { uri, args, uri_component, html, refresh, memcached, memcached }; escape = map[type]; @@ -2316,7 +2340,7 @@ ngx_http_lua_process_args_option(ngx_http_request_t *r, lua_State *L, key = (u_char *) lua_tolstring(L, -2, &key_len); key_escape = 2 * ngx_http_lua_escape_uri(NULL, key, key_len, - NGX_ESCAPE_URI); + NGX_ESCAPE_URI_COMPONENT); total_escape += key_escape; switch (lua_type(L, -1)) { @@ -2325,7 +2349,7 @@ ngx_http_lua_process_args_option(ngx_http_request_t *r, lua_State *L, value = (u_char *) lua_tolstring(L, -1, &value_len); total_escape += 2 * ngx_http_lua_escape_uri(NULL, value, value_len, - NGX_ESCAPE_URI); + NGX_ESCAPE_URI_COMPONENT); len += key_len + value_len + (sizeof("=") - 1); n++; @@ -2366,7 +2390,7 @@ ngx_http_lua_process_args_option(ngx_http_request_t *r, lua_State *L, total_escape += 2 * ngx_http_lua_escape_uri(NULL, value, value_len, - NGX_ESCAPE_URI); + NGX_ESCAPE_URI_COMPONENT); len += key_len + value_len + (sizeof("=") - 1); } @@ -2423,7 +2447,8 @@ ngx_http_lua_process_args_option(ngx_http_request_t *r, lua_State *L, if (total_escape) { p = (u_char *) ngx_http_lua_escape_uri(p, key, key_len, - NGX_ESCAPE_URI); + NGX_ESCAPE_URI_COMPONENT + ); } else { dd("shortcut: no escape required"); @@ -2437,7 +2462,8 @@ ngx_http_lua_process_args_option(ngx_http_request_t *r, lua_State *L, if (total_escape) { p = (u_char *) ngx_http_lua_escape_uri(p, value, value_len, - NGX_ESCAPE_URI); + NGX_ESCAPE_URI_COMPONENT + ); } else { p = ngx_copy(p, value, value_len); @@ -2456,7 +2482,7 @@ ngx_http_lua_process_args_option(ngx_http_request_t *r, lua_State *L, if (lua_toboolean(L, -1)) { if (total_escape) { p = (u_char *) ngx_http_lua_escape_uri(p, key, key_len, - NGX_ESCAPE_URI); + NGX_ESCAPE_URI_COMPONENT); } else { dd("shortcut: no escape required"); @@ -2484,7 +2510,7 @@ ngx_http_lua_process_args_option(ngx_http_request_t *r, lua_State *L, if (total_escape) { p = (u_char *) ngx_http_lua_escape_uri(p, key, key_len, - NGX_ESCAPE_URI); + NGX_ESCAPE_URI_COMPONENT); } else { dd("shortcut: no escape required"); @@ -2503,7 +2529,8 @@ ngx_http_lua_process_args_option(ngx_http_request_t *r, lua_State *L, p = (u_char *) ngx_http_lua_escape_uri(p, key, key_len, - NGX_ESCAPE_URI); + NGX_ESCAPE_URI_COMPONENT + ); } else { dd("shortcut: no escape required"); @@ -2519,7 +2546,8 @@ ngx_http_lua_process_args_option(ngx_http_request_t *r, lua_State *L, p = (u_char *) ngx_http_lua_escape_uri(p, value, value_len, - NGX_ESCAPE_URI); + NGX_ESCAPE_URI_COMPONENT + ); } else { p = ngx_copy(p, value, value_len); diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_worker.c b/debian/modules/nginx-lua/src/ngx_http_lua_worker.c index ff09b5b..e1cfec4 100644 --- a/debian/modules/nginx-lua/src/ngx_http_lua_worker.c +++ b/debian/modules/nginx-lua/src/ngx_http_lua_worker.c @@ -13,6 +13,9 @@ #include "ngx_http_lua_worker.h" +#define NGX_PROCESS_PRIVILEGED_AGENT 99 + + static int ngx_http_lua_ngx_worker_exiting(lua_State *L); static int ngx_http_lua_ngx_worker_pid(lua_State *L); static int ngx_http_lua_ngx_worker_id(lua_State *L); @@ -130,4 +133,46 @@ ngx_http_lua_ffi_worker_count(void) return (int) ccf->worker_processes; } + + +int +ngx_http_lua_ffi_get_process_type(void) +{ +#if defined(HAVE_PRIVILEGED_PROCESS_PATCH) && !NGX_WIN32 + if (ngx_process == NGX_PROCESS_HELPER) { + if (ngx_is_privileged_agent) { + return NGX_PROCESS_PRIVILEGED_AGENT; + } + } +#endif + + return ngx_process; +} + + +int +ngx_http_lua_ffi_enable_privileged_agent(char **err) +{ +#ifdef HAVE_PRIVILEGED_PROCESS_PATCH + ngx_core_conf_t *ccf; + + ccf = (ngx_core_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, + ngx_core_module); + + ccf->privileged_agent = 1; + + return NGX_OK; + +#else + *err = "missing privileged agent process patch in the nginx core"; + return NGX_ERROR; +#endif +} + + +void +ngx_http_lua_ffi_process_signal_graceful_exit(void) +{ + ngx_quit = 1; +} #endif diff --git a/debian/modules/nginx-lua/t/000--init.t b/debian/modules/nginx-lua/t/000--init.t index 364334f..ad2d70e 100644 --- a/debian/modules/nginx-lua/t/000--init.t +++ b/debian/modules/nginx-lua/t/000--init.t @@ -84,4 +84,3 @@ GET /flush --- timeout: 10 --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/000-sanity.t b/debian/modules/nginx-lua/t/000-sanity.t index 3f66752..87854ef 100644 --- a/debian/modules/nginx-lua/t/000-sanity.t +++ b/debian/modules/nginx-lua/t/000-sanity.t @@ -31,4 +31,3 @@ GET /lua GET /lua --- response_body helloworld - diff --git a/debian/modules/nginx-lua/t/001-set.t b/debian/modules/nginx-lua/t/001-set.t index 2295a2d..ba8f22c 100644 --- a/debian/modules/nginx-lua/t/001-set.t +++ b/debian/modules/nginx-lua/t/001-set.t @@ -795,4 +795,3 @@ GET /lua?a=1&b=2 --- error_code: 500 --- error_log eval qr/failed to load external Lua file ".*?test2\.lua": cannot open .*? No such file or directory/ - diff --git a/debian/modules/nginx-lua/t/002-content.t b/debian/modules/nginx-lua/t/002-content.t index e6cb62d..3f2460e 100644 --- a/debian/modules/nginx-lua/t/002-content.t +++ b/debian/modules/nginx-lua/t/002-content.t @@ -836,4 +836,3 @@ GET /lua --- error_code: 500 --- error_log eval qr/failed to load inlined Lua code: / - diff --git a/debian/modules/nginx-lua/t/003-errors.t b/debian/modules/nginx-lua/t/003-errors.t index 764300a..ad3a506 100644 --- a/debian/modules/nginx-lua/t/003-errors.t +++ b/debian/modules/nginx-lua/t/003-errors.t @@ -126,4 +126,3 @@ GET /main GET /main --- response_body 500 - diff --git a/debian/modules/nginx-lua/t/004-require.t b/debian/modules/nginx-lua/t/004-require.t index 3250b2f..ec74116 100644 --- a/debian/modules/nginx-lua/t/004-require.t +++ b/debian/modules/nginx-lua/t/004-require.t @@ -208,4 +208,3 @@ GET /ndk GET /ndk --- response_body %20 - diff --git a/debian/modules/nginx-lua/t/005-exit.t b/debian/modules/nginx-lua/t/005-exit.t index 781531f..a5a28b3 100644 --- a/debian/modules/nginx-lua/t/005-exit.t +++ b/debian/modules/nginx-lua/t/005-exit.t @@ -723,4 +723,3 @@ GET /t --- response_body --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/006-escape.t b/debian/modules/nginx-lua/t/006-escape.t index 7b26bba..a21d3cb 100644 --- a/debian/modules/nginx-lua/t/006-escape.t +++ b/debian/modules/nginx-lua/t/006-escape.t @@ -3,9 +3,8 @@ use Test::Nginx::Socket::Lua; repeat_each(2); -#repeat_each(1); -plan tests => repeat_each() * (blocks() * 2 + 1); +plan tests => repeat_each() * (blocks() * 2 + 2); no_long_string(); @@ -181,3 +180,20 @@ GET /t --- response_body [32] + + +=== TEST 14: reserved chars +--- config + location /lua { + content_by_lua_block { + ngx.say(ngx.escape_uri("-_.!~*'()")) + ngx.say(ngx.escape_uri(",$@|`")) + } + } +--- request +GET /lua +--- response_body +-_.!~*'() +%2C%24%40%7C%60 +--- no_error_log +[error] diff --git a/debian/modules/nginx-lua/t/007-md5.t b/debian/modules/nginx-lua/t/007-md5.t index 501e3af..2ae9efb 100644 --- a/debian/modules/nginx-lua/t/007-md5.t +++ b/debian/modules/nginx-lua/t/007-md5.t @@ -100,4 +100,3 @@ d41d8cd98f00b204e9800998ecf8427e GET /md5 --- response_body 6c8349cc7260ae62e3b1396831a8398f - diff --git a/debian/modules/nginx-lua/t/008-today.t b/debian/modules/nginx-lua/t/008-today.t index 54bd949..ec2f433 100644 --- a/debian/modules/nginx-lua/t/008-today.t +++ b/debian/modules/nginx-lua/t/008-today.t @@ -36,4 +36,3 @@ GET /today --- request GET /today --- response_body_like: ^\d{4}-\d{2}-\d{2}$ - diff --git a/debian/modules/nginx-lua/t/009-log.t b/debian/modules/nginx-lua/t/009-log.t index 0c6a9a5..68c057f 100644 --- a/debian/modules/nginx-lua/t/009-log.t +++ b/debian/modules/nginx-lua/t/009-log.t @@ -542,4 +542,3 @@ ok [error] --- error_log eval "2: hello\0world, client: " - diff --git a/debian/modules/nginx-lua/t/010-request_body.t b/debian/modules/nginx-lua/t/010-request_body.t index 2640a54..e669d94 100644 --- a/debian/modules/nginx-lua/t/010-request_body.t +++ b/debian/modules/nginx-lua/t/010-request_body.t @@ -270,4 +270,3 @@ Expect: 100-Continue http finalize request: 500, "/echo_body?" a:1, c:2 http finalize request: 500, "/echo_body?" a:1, c:0 --- log_level: debug - diff --git a/debian/modules/nginx-lua/t/012-now.t b/debian/modules/nginx-lua/t/012-now.t index abcb735..5885187 100644 --- a/debian/modules/nginx-lua/t/012-now.t +++ b/debian/modules/nginx-lua/t/012-now.t @@ -116,4 +116,3 @@ GET /time --- request GET /time --- response_body_like: ^\d{10,}(\.\d{1,3})?$ - diff --git a/debian/modules/nginx-lua/t/014-bugs.t b/debian/modules/nginx-lua/t/014-bugs.t index 44337e3..9aadff0 100644 --- a/debian/modules/nginx-lua/t/014-bugs.t +++ b/debian/modules/nginx-lua/t/014-bugs.t @@ -849,7 +849,7 @@ ok "lua_package_path '$::HtmlDir/?.lua;./?.lua';" --- config location /t { - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; set $myhost 'agentzh.org.'; proxy_pass http://$myhost/misc/.vimrc; } @@ -1018,4 +1018,3 @@ write timer set: 1 --- no_error_log [error] [alert] - diff --git a/debian/modules/nginx-lua/t/016-resp-header.t b/debian/modules/nginx-lua/t/016-resp-header.t index 179b411..1fae292 100644 --- a/debian/modules/nginx-lua/t/016-resp-header.t +++ b/debian/modules/nginx-lua/t/016-resp-header.t @@ -8,7 +8,7 @@ use Test::Nginx::Socket::Lua; repeat_each(2); -plan tests => repeat_each() * (blocks() * 3 + 38); +plan tests => repeat_each() * (blocks() * 3 + 41); #no_diff(); no_long_string(); @@ -1441,3 +1441,71 @@ Content-Type: ; blah test --- no_error_log [error] + + + +=== TEST 69: return the matched content-type instead of default_type +--- http_config +types { + image/png png; +} +--- config +location /set/ { + default_type text/html; + content_by_lua_block { + ngx.say(ngx.header["content-type"]) + } +} +--- request +GET /set/hello.png +--- response_headers +Content-Type: image/png +--- response_body +image/png +--- no_error_log +[error] + + + +=== TEST 70: always return the matched content-type +--- config + location /set/ { + default_type "image/png"; + content_by_lua_block { + ngx.say(ngx.header["content-type"]) + ngx.say(ngx.header["content-type"]) + } + } +--- request +GET /set/hello.png +--- response_headers +Content-Type: image/png +--- response_body +image/png +image/png +--- no_error_log +[error] + + + +=== TEST 71: return the matched content-type after ngx.resp.get_headers() +--- http_config +types { + image/png png; +} +--- config + location /set/ { + default_type text/html; + content_by_lua_block { + local h = ngx.resp.get_headers() + ngx.say(h["content-type"]) + } + } +--- request +GET /set/hello.png +--- response_headers +Content-Type: image/png +--- response_body +image/png +--- no_error_log +[error] diff --git a/debian/modules/nginx-lua/t/017-exec.t b/debian/modules/nginx-lua/t/017-exec.t index 4c7a918..535c4ab 100644 --- a/debian/modules/nginx-lua/t/017-exec.t +++ b/debian/modules/nginx-lua/t/017-exec.t @@ -572,4 +572,3 @@ hello, bah ["dummy", "dummy"] --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/018-ndk.t b/debian/modules/nginx-lua/t/018-ndk.t index d68306b..1429377 100644 --- a/debian/modules/nginx-lua/t/018-ndk.t +++ b/debian/modules/nginx-lua/t/018-ndk.t @@ -171,4 +171,3 @@ ok foo = a b --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/019-const.t b/debian/modules/nginx-lua/t/019-const.t index fe79bfb..4f9c764 100644 --- a/debian/modules/nginx-lua/t/019-const.t +++ b/debian/modules/nginx-lua/t/019-const.t @@ -44,4 +44,3 @@ GET /read GET /read --- response_body 504 - diff --git a/debian/modules/nginx-lua/t/021-cookie-time.t b/debian/modules/nginx-lua/t/021-cookie-time.t index c00bbea..b05e401 100644 --- a/debian/modules/nginx-lua/t/021-cookie-time.t +++ b/debian/modules/nginx-lua/t/021-cookie-time.t @@ -43,4 +43,3 @@ Thu, 18-Nov-10 11:27:35 GMT GET /lua --- response_body Thu, 18-Nov-10 11:27:35 GMT - diff --git a/debian/modules/nginx-lua/t/022-redirect.t b/debian/modules/nginx-lua/t/022-redirect.t index 57c7add..fae39e3 100644 --- a/debian/modules/nginx-lua/t/022-redirect.t +++ b/debian/modules/nginx-lua/t/022-redirect.t @@ -84,7 +84,7 @@ GET /read --- response_body_like: 500 Internal Server Error --- error_code: 500 --- error_log -only ngx.HTTP_MOVED_TEMPORARILY, ngx.HTTP_MOVED_PERMANENTLY, and ngx.HTTP_TEMPORARY_REDIRECT are allowed +only ngx.HTTP_MOVED_TEMPORARILY, ngx.HTTP_MOVED_PERMANENTLY, ngx.HTTP_SEE_OTHER, and ngx.HTTP_TEMPORARY_REDIRECT are allowed @@ -218,3 +218,54 @@ GET /read Location: http://agentzh.org/foo?a=b&c=d --- response_body_like: 307 Temporary Redirect --- error_code: 307 + + + +=== TEST 12: explicit 303 +--- config + location /read { + content_by_lua_block { + ngx.redirect("http://agentzh.org/foo", ngx.HTTP_SEE_OTHER); + ngx.say("hi") + } + } +--- request +GET /read +--- response_headers +Location: http://agentzh.org/foo +--- response_body_like: 303 See Other +--- error_code: 303 + + + +=== TEST 13: explicit 303 with args +--- config + location /read { + content_by_lua_block { + ngx.redirect("http://agentzh.org/foo?a=b&c=d", ngx.HTTP_SEE_OTHER); + ngx.say("hi") + } + } +--- request +GET /read +--- response_headers +Location: http://agentzh.org/foo?a=b&c=d +--- response_body_like: 303 See Other +--- error_code: 303 + + + +=== TEST 14: explicit 303 +--- config + location /read { + content_by_lua_block { + ngx.redirect("http://agentzh.org/foo?a=b&c=d", 303); + ngx.say("hi") + } + } +--- request +GET /read +--- response_headers +Location: http://agentzh.org/foo?a=b&c=d +--- response_body_like: 303 See Other +--- error_code: 303 diff --git a/debian/modules/nginx-lua/t/023-rewrite/client-abort.t b/debian/modules/nginx-lua/t/023-rewrite/client-abort.t index e970802..117d17e 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/client-abort.t +++ b/debian/modules/nginx-lua/t/023-rewrite/client-abort.t @@ -848,4 +848,3 @@ delete thread 1 --- no_error_log [error] [alert] - diff --git a/debian/modules/nginx-lua/t/023-rewrite/exec.t b/debian/modules/nginx-lua/t/023-rewrite/exec.t index a063b5b..bd97968 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/exec.t +++ b/debian/modules/nginx-lua/t/023-rewrite/exec.t @@ -376,4 +376,3 @@ ngx.exec("@proxy") GET /main --- response_body hello, bah - diff --git a/debian/modules/nginx-lua/t/023-rewrite/exit.t b/debian/modules/nginx-lua/t/023-rewrite/exit.t index 9d292f7..39ea5cb 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/exit.t +++ b/debian/modules/nginx-lua/t/023-rewrite/exit.t @@ -595,4 +595,3 @@ F(ngx_http_send_header) { --- error_code: 204 --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/023-rewrite/mixed.t b/debian/modules/nginx-lua/t/023-rewrite/mixed.t index 1156567..0f742b2 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/mixed.t +++ b/debian/modules/nginx-lua/t/023-rewrite/mixed.t @@ -167,4 +167,3 @@ world\x03\x04\xff hello\x00\x01\x02 world\x03\x04\xff " - diff --git a/debian/modules/nginx-lua/t/023-rewrite/multi-capture.t b/debian/modules/nginx-lua/t/023-rewrite/multi-capture.t index 44629b0..083ec78 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/multi-capture.t +++ b/debian/modules/nginx-lua/t/023-rewrite/multi-capture.t @@ -392,4 +392,3 @@ res4.status = 201 res4.body = STORED\r " - diff --git a/debian/modules/nginx-lua/t/023-rewrite/on-abort.t b/debian/modules/nginx-lua/t/023-rewrite/on-abort.t index aca2ab6..336b7ce 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/on-abort.t +++ b/debian/modules/nginx-lua/t/023-rewrite/on-abort.t @@ -654,4 +654,3 @@ delete thread 2 --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/023-rewrite/redirect.t b/debian/modules/nginx-lua/t/023-rewrite/redirect.t index 8843f1a..99f3fd4 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/redirect.t +++ b/debian/modules/nginx-lua/t/023-rewrite/redirect.t @@ -122,4 +122,3 @@ GET /read --- raw_response_headers_like: Location: /foo\r\n --- response_body_like: 302 Found --- error_code: 302 - diff --git a/debian/modules/nginx-lua/t/023-rewrite/req-body.t b/debian/modules/nginx-lua/t/023-rewrite/req-body.t index 2f42e0a..13bdcb2 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/req-body.t +++ b/debian/modules/nginx-lua/t/023-rewrite/req-body.t @@ -221,4 +221,3 @@ hiya, world"] --- no_error_log [error] [alert] - diff --git a/debian/modules/nginx-lua/t/023-rewrite/req-socket.t b/debian/modules/nginx-lua/t/023-rewrite/req-socket.t index 34aedaa..87cbbbe 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/req-socket.t +++ b/debian/modules/nginx-lua/t/023-rewrite/req-socket.t @@ -532,4 +532,3 @@ Expect: 100-Continue \breceived: hello\b.*?\breceived: worl\b --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/023-rewrite/request_body.t b/debian/modules/nginx-lua/t/023-rewrite/request_body.t index 0594001..b867d3a 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/request_body.t +++ b/debian/modules/nginx-lua/t/023-rewrite/request_body.t @@ -170,4 +170,3 @@ Expect: 100-Continue http finalize request: 500, "/echo_body?" a:1, c:2 http finalize request: 500, "/echo_body?" a:1, c:0 --- log_level: debug - diff --git a/debian/modules/nginx-lua/t/023-rewrite/sanity.t b/debian/modules/nginx-lua/t/023-rewrite/sanity.t index 20b00e2..b90aa0e 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/sanity.t +++ b/debian/modules/nginx-lua/t/023-rewrite/sanity.t @@ -799,4 +799,3 @@ test test --- no_error_log [alert] - diff --git a/debian/modules/nginx-lua/t/023-rewrite/sleep.t b/debian/modules/nginx-lua/t/023-rewrite/sleep.t index 1719784..8d4c2da 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/sleep.t +++ b/debian/modules/nginx-lua/t/023-rewrite/sleep.t @@ -219,4 +219,3 @@ hello world hello world --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/023-rewrite/socket-keepalive.t b/debian/modules/nginx-lua/t/023-rewrite/socket-keepalive.t index 50de0b3..489a70f 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/socket-keepalive.t +++ b/debian/modules/nginx-lua/t/023-rewrite/socket-keepalive.t @@ -1007,4 +1007,3 @@ Not found, dear... --- error_code: 404 --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/023-rewrite/subrequest.t b/debian/modules/nginx-lua/t/023-rewrite/subrequest.t index a307388..5d1e8f0 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/subrequest.t +++ b/debian/modules/nginx-lua/t/023-rewrite/subrequest.t @@ -639,4 +639,3 @@ the nginx core requires the patch https://github.com/agentzh/ngx_openresty/blob/ GET /t --- response_body done - diff --git a/debian/modules/nginx-lua/t/023-rewrite/tcp-socket-timeout.t b/debian/modules/nginx-lua/t/023-rewrite/tcp-socket-timeout.t index 79cd0b9..15bec7f 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/tcp-socket-timeout.t +++ b/debian/modules/nginx-lua/t/023-rewrite/tcp-socket-timeout.t @@ -41,7 +41,7 @@ __DATA__ --- config server_tokens off; lua_socket_connect_timeout 100ms; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; resolver_timeout 3s; location /t1 { rewrite_by_lua ' @@ -73,7 +73,7 @@ lua tcp socket connect timed out server_tokens off; lua_socket_connect_timeout 60s; lua_socket_log_errors off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; resolver_timeout 3s; location /t2 { rewrite_by_lua ' @@ -108,7 +108,7 @@ lua tcp socket connect timeout: 150 server_tokens off; lua_socket_log_errors off; lua_socket_connect_timeout 102ms; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; #resolver_timeout 3s; location /t3 { rewrite_by_lua ' @@ -143,7 +143,7 @@ lua tcp socket connect timeout: 102 server_tokens off; lua_socket_connect_timeout 102ms; lua_socket_log_errors off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; resolver_timeout 3s; location /t4 { rewrite_by_lua ' @@ -179,7 +179,7 @@ lua tcp socket connect timeout: 102 server_tokens off; lua_socket_connect_timeout 102ms; lua_socket_log_errors off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; resolver_timeout 3s; location /t5 { rewrite_by_lua ' @@ -251,7 +251,7 @@ lua tcp socket read timed out --- config server_tokens off; lua_socket_read_timeout 60s; - #resolver $TEST_NGINX_RESOLVER; + #resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { rewrite_by_lua ' local sock = ngx.socket.tcp() @@ -292,7 +292,7 @@ lua tcp socket read timed out --- config server_tokens off; lua_socket_read_timeout 102ms; - #resolver $TEST_NGINX_RESOLVER; + #resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { rewrite_by_lua ' local sock = ngx.socket.tcp() @@ -333,7 +333,7 @@ lua tcp socket read timed out --- config server_tokens off; lua_socket_read_timeout 102ms; - #resolver $TEST_NGINX_RESOLVER; + #resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { rewrite_by_lua ' local sock = ngx.socket.tcp() @@ -375,7 +375,7 @@ lua tcp socket read timed out --- config server_tokens off; lua_socket_read_timeout 102ms; - #resolver $TEST_NGINX_RESOLVER; + #resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { rewrite_by_lua ' local sock = ngx.socket.tcp() @@ -416,7 +416,7 @@ lua tcp socket read timed out --- config server_tokens off; lua_socket_send_timeout 100ms; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { rewrite_by_lua ' local sock = ngx.socket.tcp() @@ -455,7 +455,7 @@ lua tcp socket write timed out --- config server_tokens off; lua_socket_send_timeout 60s; - #resolver $TEST_NGINX_RESOLVER; + #resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { rewrite_by_lua ' local sock = ngx.socket.tcp() @@ -496,7 +496,7 @@ lua tcp socket write timed out --- config server_tokens off; lua_socket_send_timeout 102ms; - #resolver $TEST_NGINX_RESOLVER; + #resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { rewrite_by_lua ' local sock = ngx.socket.tcp() @@ -537,7 +537,7 @@ lua tcp socket write timed out --- config server_tokens off; lua_socket_send_timeout 102ms; - #resolver $TEST_NGINX_RESOLVER; + #resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { rewrite_by_lua ' local sock = ngx.socket.tcp() @@ -578,7 +578,7 @@ lua tcp socket write timed out --- config server_tokens off; lua_socket_send_timeout 102ms; - #resolver $TEST_NGINX_RESOLVER; + #resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { rewrite_by_lua ' local sock = ngx.socket.tcp() @@ -612,4 +612,3 @@ failed to send: timeout lua tcp socket send timeout: 102 lua tcp socket connect timeout: 60000 lua tcp socket write timed out - diff --git a/debian/modules/nginx-lua/t/023-rewrite/tcp-socket.t b/debian/modules/nginx-lua/t/023-rewrite/tcp-socket.t index cf9d80a..bff69a5 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/tcp-socket.t +++ b/debian/modules/nginx-lua/t/023-rewrite/tcp-socket.t @@ -204,7 +204,7 @@ attempt to send data on a closed socket: --- timeout: 10 --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; resolver_timeout 3s; location /t { rewrite_by_lua ' @@ -296,7 +296,7 @@ qr/connect\(\) failed \(\d+: Connection refused\)/ === TEST 6: connection timeout (tcp) --- config - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; lua_socket_connect_timeout 100ms; lua_socket_send_timeout 100ms; lua_socket_read_timeout 100ms; @@ -372,7 +372,7 @@ connected: 1 === TEST 8: resolver error (host not found) --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; resolver_timeout 3s; location /t { rewrite_by_lua ' @@ -415,7 +415,7 @@ attempt to send data on a closed socket === TEST 9: resolver error (timeout) --- config server_tokens off; - resolver 8.8.8.8; + resolver $TEST_NGINX_RESOLVER ipv6=off; resolver_timeout 1ms; location /t { rewrite_by_lua ' @@ -2390,4 +2390,3 @@ qr/runtime error: rewrite_by_lua\(nginx\.conf:\d+\):16: bad request/ --- no_error_log [alert] - diff --git a/debian/modules/nginx-lua/t/023-rewrite/unix-socket.t b/debian/modules/nginx-lua/t/023-rewrite/unix-socket.t index 098dd67..8a5f000 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/unix-socket.t +++ b/debian/modules/nginx-lua/t/023-rewrite/unix-socket.t @@ -150,4 +150,3 @@ received: received: foo failed to receive a line: closed close: 1 nil - diff --git a/debian/modules/nginx-lua/t/023-rewrite/uthread-redirect.t b/debian/modules/nginx-lua/t/023-rewrite/uthread-redirect.t index 0f125e0..83de1a3 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/uthread-redirect.t +++ b/debian/modules/nginx-lua/t/023-rewrite/uthread-redirect.t @@ -186,4 +186,3 @@ free request --- error_code: 302 --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/023-rewrite/uthread-spawn.t b/debian/modules/nginx-lua/t/023-rewrite/uthread-spawn.t index 58af7d0..5552107 100644 --- a/debian/modules/nginx-lua/t/023-rewrite/uthread-spawn.t +++ b/debian/modules/nginx-lua/t/023-rewrite/uthread-spawn.t @@ -1449,4 +1449,3 @@ status: 204 --- no_error_log [error] --- timeout: 3 - diff --git a/debian/modules/nginx-lua/t/024-access/auth.t b/debian/modules/nginx-lua/t/024-access/auth.t index 5da09cb..56e9862 100644 --- a/debian/modules/nginx-lua/t/024-access/auth.t +++ b/debian/modules/nginx-lua/t/024-access/auth.t @@ -107,4 +107,3 @@ Location: /terms_of_use\.html GET /lua --- response_body_like: 403 Forbidden --- error_code: 403 - diff --git a/debian/modules/nginx-lua/t/024-access/client-abort.t b/debian/modules/nginx-lua/t/024-access/client-abort.t index a94f822..c16f4ea 100644 --- a/debian/modules/nginx-lua/t/024-access/client-abort.t +++ b/debian/modules/nginx-lua/t/024-access/client-abort.t @@ -850,4 +850,3 @@ delete thread 1 --- no_error_log [error] [alert] - diff --git a/debian/modules/nginx-lua/t/024-access/exit.t b/debian/modules/nginx-lua/t/024-access/exit.t index 8470ab9..d6d66b8 100644 --- a/debian/modules/nginx-lua/t/024-access/exit.t +++ b/debian/modules/nginx-lua/t/024-access/exit.t @@ -545,4 +545,3 @@ Not found, dear... --- response_body Not found, dear... --- error_code: 404 - diff --git a/debian/modules/nginx-lua/t/024-access/multi-capture.t b/debian/modules/nginx-lua/t/024-access/multi-capture.t index 368d401..930b74d 100644 --- a/debian/modules/nginx-lua/t/024-access/multi-capture.t +++ b/debian/modules/nginx-lua/t/024-access/multi-capture.t @@ -392,4 +392,3 @@ res4.status = 201 res4.body = STORED\r " - diff --git a/debian/modules/nginx-lua/t/024-access/on-abort.t b/debian/modules/nginx-lua/t/024-access/on-abort.t index 0c17b55..5bb948b 100644 --- a/debian/modules/nginx-lua/t/024-access/on-abort.t +++ b/debian/modules/nginx-lua/t/024-access/on-abort.t @@ -649,4 +649,3 @@ delete thread 2 --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/024-access/redirect.t b/debian/modules/nginx-lua/t/024-access/redirect.t index c7ce512..b45fac7 100644 --- a/debian/modules/nginx-lua/t/024-access/redirect.t +++ b/debian/modules/nginx-lua/t/024-access/redirect.t @@ -122,4 +122,3 @@ GET /read --- raw_response_headers_like: Location: /foo\r\n --- response_body_like: 302 Found --- error_code: 302 - diff --git a/debian/modules/nginx-lua/t/024-access/req-body.t b/debian/modules/nginx-lua/t/024-access/req-body.t index fd33aff..70db85c 100644 --- a/debian/modules/nginx-lua/t/024-access/req-body.t +++ b/debian/modules/nginx-lua/t/024-access/req-body.t @@ -218,4 +218,3 @@ hiya, world"] --- no_error_log [error] [alert] - diff --git a/debian/modules/nginx-lua/t/024-access/request_body.t b/debian/modules/nginx-lua/t/024-access/request_body.t index a6fead2..fa03195 100644 --- a/debian/modules/nginx-lua/t/024-access/request_body.t +++ b/debian/modules/nginx-lua/t/024-access/request_body.t @@ -170,4 +170,3 @@ Expect: 100-Continue http finalize request: 500, "/echo_body?" a:1, c:2 http finalize request: 500, "/echo_body?" a:1, c:0 --- log_level: debug - diff --git a/debian/modules/nginx-lua/t/024-access/sanity.t b/debian/modules/nginx-lua/t/024-access/sanity.t index de63a68..7ff177f 100644 --- a/debian/modules/nginx-lua/t/024-access/sanity.t +++ b/debian/modules/nginx-lua/t/024-access/sanity.t @@ -741,4 +741,3 @@ test test --- no_error_log [alert] - diff --git a/debian/modules/nginx-lua/t/024-access/satisfy.t b/debian/modules/nginx-lua/t/024-access/satisfy.t index 10d3ece..7902f49 100644 --- a/debian/modules/nginx-lua/t/024-access/satisfy.t +++ b/debian/modules/nginx-lua/t/024-access/satisfy.t @@ -209,4 +209,3 @@ something important --- error_code: 200 --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/024-access/sleep.t b/debian/modules/nginx-lua/t/024-access/sleep.t index 2eb0822..fc1fc02 100644 --- a/debian/modules/nginx-lua/t/024-access/sleep.t +++ b/debian/modules/nginx-lua/t/024-access/sleep.t @@ -219,4 +219,3 @@ hello world hello world --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/024-access/subrequest.t b/debian/modules/nginx-lua/t/024-access/subrequest.t index bfe96d6..b6ccf11 100644 --- a/debian/modules/nginx-lua/t/024-access/subrequest.t +++ b/debian/modules/nginx-lua/t/024-access/subrequest.t @@ -599,4 +599,3 @@ the nginx core requires the patch https://github.com/agentzh/ngx_openresty/blob/ GET /t --- response_body done - diff --git a/debian/modules/nginx-lua/t/024-access/uthread-exec.t b/debian/modules/nginx-lua/t/024-access/uthread-exec.t index d7c2321..7add3d4 100644 --- a/debian/modules/nginx-lua/t/024-access/uthread-exec.t +++ b/debian/modules/nginx-lua/t/024-access/uthread-exec.t @@ -344,4 +344,3 @@ free request end --- error_log attempt to abort with pending subrequests - diff --git a/debian/modules/nginx-lua/t/024-access/uthread-exit.t b/debian/modules/nginx-lua/t/024-access/uthread-exit.t index da4a9db..7c146ae 100644 --- a/debian/modules/nginx-lua/t/024-access/uthread-exit.t +++ b/debian/modules/nginx-lua/t/024-access/uthread-exit.t @@ -1311,4 +1311,3 @@ free request end --- error_log attempt to abort with pending subrequests - diff --git a/debian/modules/nginx-lua/t/024-access/uthread-redirect.t b/debian/modules/nginx-lua/t/024-access/uthread-redirect.t index 8b030ac..4eb4759 100644 --- a/debian/modules/nginx-lua/t/024-access/uthread-redirect.t +++ b/debian/modules/nginx-lua/t/024-access/uthread-redirect.t @@ -187,4 +187,3 @@ free request --- error_code: 302 --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/024-access/uthread-spawn.t b/debian/modules/nginx-lua/t/024-access/uthread-spawn.t index 415e4c0..7c7ba3b 100644 --- a/debian/modules/nginx-lua/t/024-access/uthread-spawn.t +++ b/debian/modules/nginx-lua/t/024-access/uthread-spawn.t @@ -1116,4 +1116,3 @@ body: hello world)$ --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/025-codecache.t b/debian/modules/nginx-lua/t/025-codecache.t index f33452a..0b02a27 100644 --- a/debian/modules/nginx-lua/t/025-codecache.t +++ b/debian/modules/nginx-lua/t/025-codecache.t @@ -1244,4 +1244,3 @@ qr/\[alert\] \S+ lua_code_cache is off; this will hurt performance/, "decrementing the reference count for Lua VM: 1", "lua close the global Lua VM", ] - diff --git a/debian/modules/nginx-lua/t/026-mysql.t b/debian/modules/nginx-lua/t/026-mysql.t index e14ffb6..569f96f 100644 --- a/debian/modules/nginx-lua/t/026-mysql.t +++ b/debian/modules/nginx-lua/t/026-mysql.t @@ -66,7 +66,7 @@ __DATA__ ^status = 504 thread id = \d+ kill status = 200 -kill body = {"errcode":0}$ +kill body = \{"errcode":0\}$ --- error_log eval qr{upstream timed out \(\d+: Connection timed out\) while sending query to drizzle upstream} @@ -126,6 +126,5 @@ qr{upstream timed out \(\d+: Connection timed out\) while sending query to drizz ^status = 504 thread id = \d+ kill status = 200 -kill body = {"errcode":0}$ +kill body = \{"errcode":0\}$ --- SKIP - diff --git a/debian/modules/nginx-lua/t/027-multi-capture.t b/debian/modules/nginx-lua/t/027-multi-capture.t index 3588c69..9227fe5 100644 --- a/debian/modules/nginx-lua/t/027-multi-capture.t +++ b/debian/modules/nginx-lua/t/027-multi-capture.t @@ -752,4 +752,3 @@ proxy_cache_path conf/cache levels=1:2 keys_zone=STATIC:10m inactive=10m max_siz GET /foo --- response_body ok - diff --git a/debian/modules/nginx-lua/t/029-http-time.t b/debian/modules/nginx-lua/t/029-http-time.t index 71a7758..ecef492 100644 --- a/debian/modules/nginx-lua/t/029-http-time.t +++ b/debian/modules/nginx-lua/t/029-http-time.t @@ -85,4 +85,3 @@ GET /lua GET /lua --- response_body nil - diff --git a/debian/modules/nginx-lua/t/030-uri-args.t b/debian/modules/nginx-lua/t/030-uri-args.t index 8ee8401..96e216c 100644 --- a/debian/modules/nginx-lua/t/030-uri-args.t +++ b/debian/modules/nginx-lua/t/030-uri-args.t @@ -9,7 +9,7 @@ log_level('warn'); repeat_each(2); #repeat_each(1); -plan tests => repeat_each() * (blocks() * 2 + 17); +plan tests => repeat_each() * (blocks() * 2 + 18); no_root_location(); @@ -1390,3 +1390,19 @@ GET /lua --- response_body_like ^HTTP/1.0 (a=3&b|b&a=3)$ + + +=== TEST 57: ngx.encode_args (escaping) +--- config + location /lua { + content_by_lua_block { + local t = {bar = "-_.!~*'()", foo = ",$@|`"} + ngx.say("args: ", ngx.encode_args(t)) + } + } +--- request +GET /lua +--- response_body +args: foo=%2C%24%40%7C%60&bar=-_.!~*'() +--- no_error_log +[error] diff --git a/debian/modules/nginx-lua/t/031-post-args.t b/debian/modules/nginx-lua/t/031-post-args.t index c2b6b8f..62c88c1 100644 --- a/debian/modules/nginx-lua/t/031-post-args.t +++ b/debian/modules/nginx-lua/t/031-post-args.t @@ -351,6 +351,6 @@ CORE::join("", @k); POST /lua a=3&b=4&c --- response_body -requesty body in temp file not supported +request body in temp file not supported --- no_error_log [error] diff --git a/debian/modules/nginx-lua/t/032-iolist.t b/debian/modules/nginx-lua/t/032-iolist.t index ddf3d7f..3c56032 100644 --- a/debian/modules/nginx-lua/t/032-iolist.t +++ b/debian/modules/nginx-lua/t/032-iolist.t @@ -76,4 +76,3 @@ GET /lua GET /lua --- response_body_like: 500 Internal Server Error --- error_code: 500 - diff --git a/debian/modules/nginx-lua/t/033-ctx.t b/debian/modules/nginx-lua/t/033-ctx.t index eefb216..8fc50aa 100644 --- a/debian/modules/nginx-lua/t/033-ctx.t +++ b/debian/modules/nginx-lua/t/033-ctx.t @@ -440,4 +440,3 @@ lua release ngx.ctx at ref --- response_body --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/034-match.t b/debian/modules/nginx-lua/t/034-match.t index 35149f1..ebe5762 100644 --- a/debian/modules/nginx-lua/t/034-match.t +++ b/debian/modules/nginx-lua/t/034-match.t @@ -1017,7 +1017,7 @@ exec opts: 0 === TEST 45: just hit match limit --- http_config - lua_regex_match_limit 5600; + lua_regex_match_limit 5000; --- config location /re { content_by_lua_file html/a.lua; @@ -1057,7 +1057,7 @@ error: pcre_exec() failed: -8 === TEST 46: just not hit match limit --- http_config - lua_regex_match_limit 5700; + lua_regex_match_limit 5100; --- config location /re { content_by_lua_file html/a.lua; diff --git a/debian/modules/nginx-lua/t/035-gmatch.t b/debian/modules/nginx-lua/t/035-gmatch.t index 69b9512..5b63ae4 100644 --- a/debian/modules/nginx-lua/t/035-gmatch.t +++ b/debian/modules/nginx-lua/t/035-gmatch.t @@ -814,7 +814,7 @@ exec opts: 0 === TEST 30: just hit match limit --- http_config - lua_regex_match_limit 5600; + lua_regex_match_limit 5000; --- config location /re { content_by_lua_file html/a.lua; @@ -860,7 +860,7 @@ error: pcre_exec() failed: -8 === TEST 31: just not hit match limit --- http_config - lua_regex_match_limit 5700; + lua_regex_match_limit 5100; --- config location /re { content_by_lua_file html/a.lua; @@ -901,4 +901,3 @@ end GET /re --- response_body failed to match - diff --git a/debian/modules/nginx-lua/t/036-sub.t b/debian/modules/nginx-lua/t/036-sub.t index f08c50f..2b4b075 100644 --- a/debian/modules/nginx-lua/t/036-sub.t +++ b/debian/modules/nginx-lua/t/036-sub.t @@ -580,7 +580,7 @@ s: a好 === TEST 28: just hit match limit --- http_config - lua_regex_match_limit 5600; + lua_regex_match_limit 5000; --- config location /re { content_by_lua_file html/a.lua; @@ -617,7 +617,7 @@ error: pcre_exec() failed: -8 === TEST 29: just not hit match limit --- http_config - lua_regex_match_limit 5700; + lua_regex_match_limit 5100; --- config location /re { content_by_lua_file html/a.lua; diff --git a/debian/modules/nginx-lua/t/037-gsub.t b/debian/modules/nginx-lua/t/037-gsub.t index 2a1e00f..4c5810d 100644 --- a/debian/modules/nginx-lua/t/037-gsub.t +++ b/debian/modules/nginx-lua/t/037-gsub.t @@ -501,7 +501,7 @@ s: aa === TEST 23: just hit match limit --- http_config - lua_regex_match_limit 5600; + lua_regex_match_limit 5000; --- config location /re { content_by_lua_file html/a.lua; @@ -538,7 +538,7 @@ error: pcre_exec() failed: -8 === TEST 24: just not hit match limit --- http_config - lua_regex_match_limit 5700; + lua_regex_match_limit 5100; --- config location /re { content_by_lua_file html/a.lua; diff --git a/debian/modules/nginx-lua/t/038-match-o.t b/debian/modules/nginx-lua/t/038-match-o.t index 628e27f..d61ff1f 100644 --- a/debian/modules/nginx-lua/t/038-match-o.t +++ b/debian/modules/nginx-lua/t/038-match-o.t @@ -740,4 +740,3 @@ false hello false false - diff --git a/debian/modules/nginx-lua/t/039-sub-o.t b/debian/modules/nginx-lua/t/039-sub-o.t index a861b6c..580a671 100644 --- a/debian/modules/nginx-lua/t/039-sub-o.t +++ b/debian/modules/nginx-lua/t/039-sub-o.t @@ -578,4 +578,3 @@ a [b c] [b] [c] [] [] d --- response_body a [b c] [b] [c] d 1 - diff --git a/debian/modules/nginx-lua/t/040-gsub-o.t b/debian/modules/nginx-lua/t/040-gsub-o.t index 90619b0..5347266 100644 --- a/debian/modules/nginx-lua/t/040-gsub-o.t +++ b/debian/modules/nginx-lua/t/040-gsub-o.t @@ -198,4 +198,3 @@ hello, world --- response_body [hello,h], [world,w] 2 - diff --git a/debian/modules/nginx-lua/t/041-header-filter.t b/debian/modules/nginx-lua/t/041-header-filter.t index 553ee43..9cca3b7 100644 --- a/debian/modules/nginx-lua/t/041-header-filter.t +++ b/debian/modules/nginx-lua/t/041-header-filter.t @@ -790,4 +790,3 @@ GET /t --- error_code: 302 --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/042-crc32.t b/debian/modules/nginx-lua/t/042-crc32.t index 86d9201..73aa1f4 100644 --- a/debian/modules/nginx-lua/t/042-crc32.t +++ b/debian/modules/nginx-lua/t/042-crc32.t @@ -54,4 +54,3 @@ GET /test GET /test --- response_body 0 - diff --git a/debian/modules/nginx-lua/t/045-ngx-var.t b/debian/modules/nginx-lua/t/045-ngx-var.t index 8f2dcb3..6475f1e 100644 --- a/debian/modules/nginx-lua/t/045-ngx-var.t +++ b/debian/modules/nginx-lua/t/045-ngx-var.t @@ -154,14 +154,15 @@ invalid referer: 1 -=== TEST 8: $proxy_host & $proxy_port +=== TEST 8: $proxy_host & $proxy_port & $proxy_add_x_forwarded_for --- config location = /t { proxy_pass http://127.0.0.1:$server_port/back; - header_filter_by_lua ' + header_filter_by_lua_block { ngx.header["Proxy-Host"] = ngx.var.proxy_host ngx.header["Proxy-Port"] = ngx.var.proxy_port - '; + ngx.header["Proxy-Add-X-Forwarded-For"] = ngx.var.proxy_add_x_forwarded_for + } } location = /back { @@ -172,6 +173,7 @@ GET /t --- raw_response_headers_like Proxy-Host: 127.0.0.1\:\d+\r Proxy-Port: \d+\r +Proxy-Add-X-Forwarded-For: 127.0.0.1\r --- response_body hello --- no_error_log @@ -226,4 +228,3 @@ GET /test?hello --- error_log variable "query_string" not changeable --- error_code: 500 - diff --git a/debian/modules/nginx-lua/t/046-hmac.t b/debian/modules/nginx-lua/t/046-hmac.t index 686b479..32e222b 100644 --- a/debian/modules/nginx-lua/t/046-hmac.t +++ b/debian/modules/nginx-lua/t/046-hmac.t @@ -29,4 +29,3 @@ __DATA__ GET /lua --- response_body R/pvxzHC4NLtj7S+kXFg/NePTmk= - diff --git a/debian/modules/nginx-lua/t/047-match-jit.t b/debian/modules/nginx-lua/t/047-match-jit.t index 077ebb6..2417a63 100644 --- a/debian/modules/nginx-lua/t/047-match-jit.t +++ b/debian/modules/nginx-lua/t/047-match-jit.t @@ -212,4 +212,3 @@ end GET /re --- response_body failed to match - diff --git a/debian/modules/nginx-lua/t/048-match-dfa.t b/debian/modules/nginx-lua/t/048-match-dfa.t index 8a0a328..28b5a60 100644 --- a/debian/modules/nginx-lua/t/048-match-dfa.t +++ b/debian/modules/nginx-lua/t/048-match-dfa.t @@ -207,4 +207,3 @@ exec opts: 0 你 --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/049-gmatch-jit.t b/debian/modules/nginx-lua/t/049-gmatch-jit.t index 614c440..5134d52 100644 --- a/debian/modules/nginx-lua/t/049-gmatch-jit.t +++ b/debian/modules/nginx-lua/t/049-gmatch-jit.t @@ -226,4 +226,3 @@ qr/pcre JIT compiling result: \d+/ error: pcre_compile() failed: missing ) in "(abc" --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/051-sub-jit.t b/debian/modules/nginx-lua/t/051-sub-jit.t index 789e897..c8a49c0 100644 --- a/debian/modules/nginx-lua/t/051-sub-jit.t +++ b/debian/modules/nginx-lua/t/051-sub-jit.t @@ -147,4 +147,3 @@ error: pcre_compile() failed: missing ) in "(abc" error: pcre_compile() failed: missing ) in "(abc" --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/053-gsub-jit.t b/debian/modules/nginx-lua/t/053-gsub-jit.t index 3a2a1aa..3efc0a2 100644 --- a/debian/modules/nginx-lua/t/053-gsub-jit.t +++ b/debian/modules/nginx-lua/t/053-gsub-jit.t @@ -147,4 +147,3 @@ error: pcre_compile() failed: missing ) in "(abc" error: pcre_compile() failed: missing ) in "(abc" --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/055-subreq-vars.t b/debian/modules/nginx-lua/t/055-subreq-vars.t index 2fc6960..eb5e24d 100644 --- a/debian/modules/nginx-lua/t/055-subreq-vars.t +++ b/debian/modules/nginx-lua/t/055-subreq-vars.t @@ -336,4 +336,3 @@ dog = hiya cat = 56 parent dog: blah parent cat: foo - diff --git a/debian/modules/nginx-lua/t/056-flush.t b/debian/modules/nginx-lua/t/056-flush.t index d189cd5..6b697a4 100644 --- a/debian/modules/nginx-lua/t/056-flush.t +++ b/debian/modules/nginx-lua/t/056-flush.t @@ -520,4 +520,3 @@ qr/lua flush requires waiting: buffered 0x[0-9a-f]+, delayed:1/, --- no_error_log [error] --- timeout: 4 - diff --git a/debian/modules/nginx-lua/t/057-flush-timeout.t b/debian/modules/nginx-lua/t/057-flush-timeout.t index d6e0f86..a046539 100644 --- a/debian/modules/nginx-lua/t/057-flush-timeout.t +++ b/debian/modules/nginx-lua/t/057-flush-timeout.t @@ -318,4 +318,3 @@ qr/failed to flush: client aborted/, --- timeout: 0.2 --- abort --- wait: 1 - diff --git a/debian/modules/nginx-lua/t/058-tcp-socket.t b/debian/modules/nginx-lua/t/058-tcp-socket.t index acf69f0..1ee113b 100644 --- a/debian/modules/nginx-lua/t/058-tcp-socket.t +++ b/debian/modules/nginx-lua/t/058-tcp-socket.t @@ -4,7 +4,7 @@ use Test::Nginx::Socket::Lua; repeat_each(2); -plan tests => repeat_each() * 187; +plan tests => repeat_each() * 190; our $HtmlDir = html_dir; @@ -200,7 +200,7 @@ attempt to send data on a closed socket: --- timeout: 10 --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; resolver_timeout 3s; location /t { content_by_lua ' @@ -290,7 +290,7 @@ qr/connect\(\) failed \(\d+: Connection refused\)/ === TEST 6: connection timeout (tcp) --- config - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; lua_socket_connect_timeout 100ms; lua_socket_send_timeout 100ms; lua_socket_read_timeout 100ms; @@ -362,7 +362,7 @@ connected: 1 === TEST 8: resolver error (host not found) --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; resolver_timeout 3s; location /t { content_by_lua ' @@ -403,7 +403,7 @@ attempt to send data on a closed socket === TEST 9: resolver error (timeout) --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; resolver_timeout 1ms; location /t { content_by_lua ' @@ -1995,7 +1995,7 @@ close: 1 nil === TEST 33: github issue #215: Handle the posted requests in lua cosocket api (failed to resolve) --- config - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; location = /sub { content_by_lua ' @@ -2038,7 +2038,7 @@ resolve name done === TEST 34: github issue #215: Handle the posted requests in lua cosocket api (successfully resolved) --- config - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; resolver_timeout 5s; location = /sub { @@ -2136,7 +2136,7 @@ close: nil closed --- config server_tokens off; lua_socket_read_timeout 100ms; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { content_by_lua ' local sock = ngx.socket.tcp() @@ -2178,7 +2178,7 @@ lua tcp socket read timed out === TEST 37: successful reread after a read time out happen (receive -> receive) --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { content_by_lua ' local sock = ngx.socket.tcp() @@ -2255,7 +2255,7 @@ lua tcp socket read timed out === TEST 38: successful reread after a read time out happen (receive -> receiveuntil) --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { content_by_lua ' local sock = ngx.socket.tcp() @@ -2335,7 +2335,7 @@ lua tcp socket read timed out === TEST 39: successful reread after a read time out happen (receiveuntil -> receiveuntil) --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { content_by_lua ' local sock = ngx.socket.tcp() @@ -2417,7 +2417,7 @@ lua tcp socket read timed out === TEST 40: successful reread after a read time out happen (receiveuntil -> receive) --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { content_by_lua ' local sock = ngx.socket.tcp() @@ -3015,7 +3015,7 @@ qr/runtime error: content_by_lua\(nginx\.conf:\d+\):16: bad request/ === TEST 50: cosocket resolving aborted by coroutine yielding failures (require) --- http_config lua_package_path "$prefix/html/?.lua;;"; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; --- config location = /t { @@ -3049,7 +3049,7 @@ runtime error: attempt to yield across C-call boundary === TEST 51: cosocket resolving aborted by coroutine yielding failures (xpcall err) --- http_config lua_package_path "$prefix/html/?.lua;;"; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; --- config location = /t { @@ -3307,7 +3307,7 @@ close: 1 nil --- config server_tokens off; lua_socket_connect_timeout 1s; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; resolver_timeout 3s; location /t { content_by_lua ' @@ -3640,3 +3640,53 @@ failed to receive a line: closed [] close: 1 nil --- error_log lua http cleanup reuse + + + +=== TEST 60: options_table is nil +--- config + location /t { + set $port $TEST_NGINX_MEMCACHED_PORT; + + content_by_lua_block { + local sock = ngx.socket.tcp() + local port = ngx.var.port + + local ok, err = sock:connect("127.0.0.1", port, nil) + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local req = "flush_all\r\n" + + local bytes, err = sock:send(req) + if not bytes then + ngx.say("failed to send request: ", err) + return + end + ngx.say("request sent: ", bytes) + + local line, err, part = sock:receive() + if line then + ngx.say("received: ", line) + + else + ngx.say("failed to receive a line: ", err, " [", part, "]") + end + + ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + } + } +--- request +GET /t +--- response_body +connected: 1 +request sent: 11 +received: OK +close: 1 nil +--- no_error_log +[error] diff --git a/debian/modules/nginx-lua/t/060-lua-memcached.t b/debian/modules/nginx-lua/t/060-lua-memcached.t index e1ebb92..0751238 100644 --- a/debian/modules/nginx-lua/t/060-lua-memcached.t +++ b/debian/modules/nginx-lua/t/060-lua-memcached.t @@ -166,4 +166,3 @@ some_key: hello 1234 [error] --- error_log lua reuse free buf memory - diff --git a/debian/modules/nginx-lua/t/061-lua-redis.t b/debian/modules/nginx-lua/t/061-lua-redis.t index d7b1876..ebfa6d1 100644 --- a/debian/modules/nginx-lua/t/061-lua-redis.t +++ b/debian/modules/nginx-lua/t/061-lua-redis.t @@ -182,4 +182,3 @@ abort: function msg type: nil --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/062-count.t b/debian/modules/nginx-lua/t/062-count.t index c3973ad..a69c33e 100644 --- a/debian/modules/nginx-lua/t/062-count.t +++ b/debian/modules/nginx-lua/t/062-count.t @@ -323,7 +323,7 @@ ngx. entry count: 116 --- request GET /test --- response_body -n = 3 +n = 4 --- no_error_log [error] diff --git a/debian/modules/nginx-lua/t/063-abort.t b/debian/modules/nginx-lua/t/063-abort.t index c112ee1..411a07e 100644 --- a/debian/modules/nginx-lua/t/063-abort.t +++ b/debian/modules/nginx-lua/t/063-abort.t @@ -1017,4 +1017,3 @@ foo --- no_error_log [error] --- timeout: 2 - diff --git a/debian/modules/nginx-lua/t/064-pcall.t b/debian/modules/nginx-lua/t/064-pcall.t index cf90a07..3011f3e 100644 --- a/debian/modules/nginx-lua/t/064-pcall.t +++ b/debian/modules/nginx-lua/t/064-pcall.t @@ -104,4 +104,3 @@ $/ --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/065-tcp-socket-timeout.t b/debian/modules/nginx-lua/t/065-tcp-socket-timeout.t index ec79891..212766e 100644 --- a/debian/modules/nginx-lua/t/065-tcp-socket-timeout.t +++ b/debian/modules/nginx-lua/t/065-tcp-socket-timeout.t @@ -46,7 +46,7 @@ __DATA__ --- config server_tokens off; lua_socket_connect_timeout 100ms; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; resolver_timeout 3s; location /t { content_by_lua ' @@ -75,7 +75,7 @@ lua tcp socket connect timed out --- config server_tokens off; lua_socket_connect_timeout 60s; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; resolver_timeout 3s; location /t { content_by_lua ' @@ -105,7 +105,7 @@ lua tcp socket connect timed out --- config server_tokens off; lua_socket_connect_timeout 102ms; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { content_by_lua ' local sock = ngx.socket.tcp() @@ -133,7 +133,7 @@ lua tcp socket connect timed out --- config server_tokens off; lua_socket_connect_timeout 102ms; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; resolver_timeout 3s; location /t { content_by_lua ' @@ -163,7 +163,7 @@ lua tcp socket connect timed out --- config server_tokens off; lua_socket_connect_timeout 102ms; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { content_by_lua ' local sock = ngx.socket.tcp() @@ -191,7 +191,7 @@ lua tcp socket connect timed out --- config server_tokens off; lua_socket_read_timeout 100ms; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { content_by_lua ' local sock = ngx.socket.tcp() @@ -228,7 +228,7 @@ lua tcp socket read timed out --- config server_tokens off; lua_socket_read_timeout 60s; - #resolver $TEST_NGINX_RESOLVER; + #resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { content_by_lua ' local sock = ngx.socket.tcp() @@ -267,7 +267,7 @@ lua tcp socket read timed out --- config server_tokens off; lua_socket_read_timeout 102ms; - #resolver $TEST_NGINX_RESOLVER; + #resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { content_by_lua ' local sock = ngx.socket.tcp() @@ -306,7 +306,7 @@ lua tcp socket read timed out --- config server_tokens off; lua_socket_read_timeout 102ms; - #resolver $TEST_NGINX_RESOLVER; + #resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { content_by_lua ' local sock = ngx.socket.tcp() @@ -346,7 +346,7 @@ lua tcp socket read timed out --- config server_tokens off; lua_socket_read_timeout 102ms; - #resolver $TEST_NGINX_RESOLVER; + #resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { content_by_lua ' local sock = ngx.socket.tcp() @@ -385,7 +385,7 @@ lua tcp socket read timed out --- config server_tokens off; lua_socket_send_timeout 100ms; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { content_by_lua ' local sock = ngx.socket.tcp() @@ -436,7 +436,7 @@ lua tcp socket write timed out --- config server_tokens off; lua_socket_send_timeout 60s; - #resolver $TEST_NGINX_RESOLVER; + #resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { content_by_lua ' local sock = ngx.socket.tcp() @@ -475,7 +475,7 @@ lua tcp socket write timed out --- config server_tokens off; lua_socket_send_timeout 102ms; - #resolver $TEST_NGINX_RESOLVER; + #resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { content_by_lua ' local sock = ngx.socket.tcp() @@ -514,7 +514,7 @@ lua tcp socket write timed out --- config server_tokens off; lua_socket_send_timeout 102ms; - #resolver $TEST_NGINX_RESOLVER; + #resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { content_by_lua ' local sock = ngx.socket.tcp() @@ -553,7 +553,7 @@ lua tcp socket write timed out --- config server_tokens off; lua_socket_send_timeout 102ms; - #resolver $TEST_NGINX_RESOLVER; + #resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { content_by_lua ' local sock = ngx.socket.tcp() @@ -686,7 +686,7 @@ after --- config server_tokens off; lua_socket_connect_timeout 100ms; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; resolver_timeout 3s; location /t { content_by_lua ' @@ -724,7 +724,7 @@ lua tcp socket connect timed out --- config server_tokens off; lua_socket_send_timeout 100ms; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { content_by_lua ' local sock = ngx.socket.tcp() @@ -779,7 +779,7 @@ lua tcp socket write timed out === TEST 19: abort when upstream sockets pending on writes --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { content_by_lua ' local sock = ngx.socket.tcp() @@ -832,7 +832,7 @@ lua tcp socket write timed out === TEST 20: abort when downstream socket pending on writes --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { content_by_lua ' ngx.send_headers() @@ -888,7 +888,7 @@ lua tcp socket write timed out --- config server_tokens off; lua_socket_read_timeout 100ms; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { content_by_lua ' local sock = ngx.socket.tcp() @@ -994,4 +994,3 @@ close: 1 nil --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/066-socket-receiveuntil.t b/debian/modules/nginx-lua/t/066-socket-receiveuntil.t index 3bf5229..ffe74aa 100644 --- a/debian/modules/nginx-lua/t/066-socket-receiveuntil.t +++ b/debian/modules/nginx-lua/t/066-socket-receiveuntil.t @@ -1329,4 +1329,3 @@ this exposed a memory leak in receiveuntil ok --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/067-req-socket.t b/debian/modules/nginx-lua/t/067-req-socket.t index 30a653a..229d5cc 100644 --- a/debian/modules/nginx-lua/t/067-req-socket.t +++ b/debian/modules/nginx-lua/t/067-req-socket.t @@ -1096,4 +1096,3 @@ done --- grep_error_log_out lua finalize socket GC cycle done - diff --git a/debian/modules/nginx-lua/t/069-null.t b/debian/modules/nginx-lua/t/069-null.t index 7761c91..e4c26af 100644 --- a/debian/modules/nginx-lua/t/069-null.t +++ b/debian/modules/nginx-lua/t/069-null.t @@ -93,4 +93,3 @@ done ngx.null: null --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/071-idle-socket.t b/debian/modules/nginx-lua/t/071-idle-socket.t index 55d25c6..c9002be 100644 --- a/debian/modules/nginx-lua/t/071-idle-socket.t +++ b/debian/modules/nginx-lua/t/071-idle-socket.t @@ -431,4 +431,3 @@ failed to set keepalive: unread data in buffer } --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/072-conditional-get.t b/debian/modules/nginx-lua/t/072-conditional-get.t index 4bb567a..7cf2dcd 100644 --- a/debian/modules/nginx-lua/t/072-conditional-get.t +++ b/debian/modules/nginx-lua/t/072-conditional-get.t @@ -88,4 +88,3 @@ delete thread 1 say failed: nginx output filter error --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/073-backtrace.t b/debian/modules/nginx-lua/t/073-backtrace.t index aae4bae..6c54692 100644 --- a/debian/modules/nginx-lua/t/073-backtrace.t +++ b/debian/modules/nginx-lua/t/073-backtrace.t @@ -187,4 +187,3 @@ probe process("$LIBLUA_PATH").function("lua_concat") { :79: in function 'func20' :83: in function 'func21' ... - diff --git a/debian/modules/nginx-lua/t/074-prefix-var.t b/debian/modules/nginx-lua/t/074-prefix-var.t index 3cc4587..c116d84 100644 --- a/debian/modules/nginx-lua/t/074-prefix-var.t +++ b/debian/modules/nginx-lua/t/074-prefix-var.t @@ -64,4 +64,3 @@ GET /t Greetings from module foo. --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/075-logby.t b/debian/modules/nginx-lua/t/075-logby.t index f987c8e..520c62e 100644 --- a/debian/modules/nginx-lua/t/075-logby.t +++ b/debian/modules/nginx-lua/t/075-logby.t @@ -581,4 +581,3 @@ qr{log_by_lua\(nginx\.conf:\d+\):1: content-type: text/plain} --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/077-sleep.t b/debian/modules/nginx-lua/t/077-sleep.t index a7c251a..96f04bd 100644 --- a/debian/modules/nginx-lua/t/077-sleep.t +++ b/debian/modules/nginx-lua/t/077-sleep.t @@ -9,10 +9,10 @@ log_level('debug'); repeat_each(2); -plan tests => repeat_each() * 63; +plan tests => repeat_each() * 71; #no_diff(); -#no_long_string(); +no_long_string(); run_tests(); __DATA__ @@ -405,3 +405,98 @@ ok [error] [alert] + + +=== TEST 16: sleep 0 +--- config + location /t { + content_by_lua_block { + local function f (n) + print("f begin ", n) + ngx.sleep(0) + print("f middle ", n) + ngx.sleep(0) + print("f end ", n) + ngx.sleep(0) + end + + for i = 1, 3 do + assert(ngx.thread.spawn(f, i)) + end + + ngx.say("ok") + } + } +--- request +GET /t +--- response_body +ok +--- no_error_log +[error] +--- grep_error_log eval: qr/\bf (?:begin|middle|end)\b|\bworker cycle$|\be?poll timer: \d+$/ +--- grep_error_log_out eval +qr/f begin +f begin +f begin +worker cycle +e?poll timer: 0 +f middle +f middle +f middle +worker cycle +e?poll timer: 0 +f end +f end +f end +worker cycle +e?poll timer: 0 +/ + + + +=== TEST 17: sleep short times less than 1ms +--- config + location /t { + content_by_lua_block { + local delay = 0.0005 + + local function f (n) + print("f begin ", n) + ngx.sleep(delay) + print("f middle ", n) + ngx.sleep(delay) + print("f end ", n) + ngx.sleep(delay) + end + + for i = 1, 3 do + assert(ngx.thread.spawn(f, i)) + end + + ngx.say("ok") + } + } +--- request +GET /t +--- response_body +ok +--- no_error_log +[error] +--- grep_error_log eval: qr/\bf (?:begin|middle|end)\b|\bworker cycle$|\be?poll timer: \d+$/ +--- grep_error_log_out eval +qr/f begin +f begin +f begin +worker cycle +e?poll timer: 0 +f middle +f middle +f middle +worker cycle +e?poll timer: 0 +f end +f end +f end +worker cycle +e?poll timer: 0 +/ diff --git a/debian/modules/nginx-lua/t/078-hup-vars.t b/debian/modules/nginx-lua/t/078-hup-vars.t index 8acc346..5072c4d 100644 --- a/debian/modules/nginx-lua/t/078-hup-vars.t +++ b/debian/modules/nginx-lua/t/078-hup-vars.t @@ -62,4 +62,3 @@ GET /t localhost --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/079-unused-directives.t b/debian/modules/nginx-lua/t/079-unused-directives.t index cba0e41..aacd0d3 100644 --- a/debian/modules/nginx-lua/t/079-unused-directives.t +++ b/debian/modules/nginx-lua/t/079-unused-directives.t @@ -340,4 +340,3 @@ GET /t sub: sub --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/080-hup-shdict.t b/debian/modules/nginx-lua/t/080-hup-shdict.t index f9a0278..c762556 100644 --- a/debian/modules/nginx-lua/t/080-hup-shdict.t +++ b/debian/modules/nginx-lua/t/080-hup-shdict.t @@ -82,4 +82,3 @@ GET /test 10502 number --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/083-bad-sock-self.t b/debian/modules/nginx-lua/t/083-bad-sock-self.t index b93849f..7a76752 100644 --- a/debian/modules/nginx-lua/t/083-bad-sock-self.t +++ b/debian/modules/nginx-lua/t/083-bad-sock-self.t @@ -136,4 +136,3 @@ bad argument #1 to 'close' (table expected, got number) --- error_code: 500 --- error_log bad argument #1 to 'setkeepalive' (table expected, got number) - diff --git a/debian/modules/nginx-lua/t/084-inclusive-receiveuntil.t b/debian/modules/nginx-lua/t/084-inclusive-receiveuntil.t index c966015..f7d5d3d 100644 --- a/debian/modules/nginx-lua/t/084-inclusive-receiveuntil.t +++ b/debian/modules/nginx-lua/t/084-inclusive-receiveuntil.t @@ -743,4 +743,3 @@ close: 1 nil } --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/085-if.t b/debian/modules/nginx-lua/t/085-if.t index e08b43c..33f57ca 100644 --- a/debian/modules/nginx-lua/t/085-if.t +++ b/debian/modules/nginx-lua/t/085-if.t @@ -198,4 +198,3 @@ GET /proxy-pass-uri --- response_body_like: It works! --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/086-init-by.t b/debian/modules/nginx-lua/t/086-init-by.t index 3a474fe..bea34a4 100644 --- a/debian/modules/nginx-lua/t/086-init-by.t +++ b/debian/modules/nginx-lua/t/086-init-by.t @@ -8,7 +8,7 @@ use Test::Nginx::Socket::Lua; repeat_each(2); -plan tests => repeat_each() * (blocks() * 3 + 3); +plan tests => repeat_each() * (blocks() * 3 + 2); #no_diff(); #no_long_string(); @@ -304,3 +304,20 @@ INIT 2: foo = 3 ", "", ] + + + +=== TEST 12: error in init +--- http_config + init_by_lua_block { + error("failed to init") + } +--- config + location /t { + echo ok; + } +--- must_die +--- error_log +failed to init +--- error_log +[error] diff --git a/debian/modules/nginx-lua/t/087-udp-socket.t b/debian/modules/nginx-lua/t/087-udp-socket.t index 79ba452..a847031 100644 --- a/debian/modules/nginx-lua/t/087-udp-socket.t +++ b/debian/modules/nginx-lua/t/087-udp-socket.t @@ -596,6 +596,7 @@ received a good response. --- log_level: debug --- error_log lua udp socket receive buffer size: 8192 +--- no_check_leak @@ -662,12 +663,14 @@ received a good response. --- log_level: debug --- error_log lua udp socket receive buffer size: 8192 +--- no_check_leak === TEST 12: github issue #215: Handle the posted requests in lua cosocket api (failed to resolve) --- config - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; + resolver_timeout 5s; location = /sub { content_by_lua ' @@ -704,12 +707,13 @@ resolve name done --- no_error_log [error] +--- timeout: 10 === TEST 13: github issue #215: Handle the posted requests in lua cosocket api (successfully resolved) --- config - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; resolver_timeout 5s; location = /sub { @@ -1100,4 +1104,3 @@ qr/runtime error: content_by_lua\(nginx\.conf:\d+\):14: bad request/ --- no_error_log [alert] - diff --git a/debian/modules/nginx-lua/t/088-req-method.t b/debian/modules/nginx-lua/t/088-req-method.t index 9ced40c..198b3b3 100644 --- a/debian/modules/nginx-lua/t/088-req-method.t +++ b/debian/modules/nginx-lua/t/088-req-method.t @@ -262,4 +262,3 @@ method: PATCH method: TRACE --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/089-phase.t b/debian/modules/nginx-lua/t/089-phase.t index 57921fc..94b7619 100644 --- a/debian/modules/nginx-lua/t/089-phase.t +++ b/debian/modules/nginx-lua/t/089-phase.t @@ -176,4 +176,3 @@ GET /lua init_worker --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/090-log-socket-errors.t b/debian/modules/nginx-lua/t/090-log-socket-errors.t index a5943c2..8e498cd 100644 --- a/debian/modules/nginx-lua/t/090-log-socket-errors.t +++ b/debian/modules/nginx-lua/t/090-log-socket-errors.t @@ -11,6 +11,8 @@ repeat_each(2); plan tests => repeat_each() * (blocks() * 3); +$ENV{TEST_NGINX_RESOLVER} ||= '8.8.8.8'; + #no_diff(); #no_long_string(); run_tests(); @@ -19,12 +21,14 @@ __DATA__ === TEST 1: log socket errors off (tcp) --- config + resolver $TEST_NGINX_RESOLVER ipv6=off; + location /t { lua_socket_connect_timeout 1ms; lua_socket_log_errors off; content_by_lua ' local sock = ngx.socket.tcp() - local ok, err = sock:connect("8.8.8.8", 80) + local ok, err = sock:connect("agentzh.org", 12345) ngx.say(err) '; } @@ -39,12 +43,14 @@ timeout === TEST 2: log socket errors on (tcp) --- config + resolver $TEST_NGINX_RESOLVER ipv6=off; + location /t { lua_socket_connect_timeout 1ms; lua_socket_log_errors on; content_by_lua ' local sock = ngx.socket.tcp() - local ok, err = sock:connect("8.8.8.8", 80) + local ok, err = sock:connect("agentzh.org", 12345) ngx.say(err) '; } @@ -59,12 +65,14 @@ lua tcp socket connect timed out === TEST 3: log socket errors on (udp) --- config + resolver $TEST_NGINX_RESOLVER ipv6=off; + location /t { lua_socket_log_errors on; lua_socket_read_timeout 1ms; content_by_lua ' local sock = ngx.socket.udp() - local ok, err = sock:setpeername("8.8.8.8", 80) + local ok, err = sock:setpeername("agentzh.org", 12345) ok, err = sock:receive() ngx.say(err) '; @@ -80,12 +88,14 @@ lua udp socket read timed out === TEST 4: log socket errors off (udp) --- config + resolver $TEST_NGINX_RESOLVER ipv6=off; + location /t { lua_socket_log_errors off; lua_socket_read_timeout 1ms; content_by_lua ' local sock = ngx.socket.udp() - local ok, err = sock:setpeername("8.8.8.8", 80) + local ok, err = sock:setpeername("agentzh.org", 12345) ok, err = sock:receive() ngx.say(err) '; @@ -96,4 +106,3 @@ GET /t timeout --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/091-coroutine.t b/debian/modules/nginx-lua/t/091-coroutine.t index b047ccb..bceb512 100644 --- a/debian/modules/nginx-lua/t/091-coroutine.t +++ b/debian/modules/nginx-lua/t/091-coroutine.t @@ -160,7 +160,7 @@ cc3: 2 === TEST 3: basic coroutine and cosocket --- config - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; location /lua { content_by_lua ' function worker(url) @@ -359,7 +359,7 @@ GET /lua === TEST 7: coroutine wrap and cosocket --- config - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; location /lua { content_by_lua ' function worker(url) @@ -987,7 +987,7 @@ test10 --- http_config init_by_lua 'return'; --- config - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; location /lua { content_by_lua ' function worker(url) @@ -1041,7 +1041,7 @@ successfully connected to: agentzh.org init_by_lua_file html/init.lua; --- config - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; location /lua { content_by_lua ' function worker(url) @@ -1315,4 +1315,3 @@ co yield: 2 --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/092-eof.t b/debian/modules/nginx-lua/t/092-eof.t index a75711f..86778de 100644 --- a/debian/modules/nginx-lua/t/092-eof.t +++ b/debian/modules/nginx-lua/t/092-eof.t @@ -80,4 +80,3 @@ GET /t --- error_log hello, tom hello, jim - diff --git a/debian/modules/nginx-lua/t/093-uthread-spawn.t b/debian/modules/nginx-lua/t/093-uthread-spawn.t index 772e866..b622d30 100644 --- a/debian/modules/nginx-lua/t/093-uthread-spawn.t +++ b/debian/modules/nginx-lua/t/093-uthread-spawn.t @@ -1672,4 +1672,3 @@ delete thread 2 f --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/094-uthread-exit.t b/debian/modules/nginx-lua/t/094-uthread-exit.t index cd678c0..a623773 100644 --- a/debian/modules/nginx-lua/t/094-uthread-exit.t +++ b/debian/modules/nginx-lua/t/094-uthread-exit.t @@ -1648,4 +1648,3 @@ free request [alert] [error] [warn] - diff --git a/debian/modules/nginx-lua/t/095-uthread-exec.t b/debian/modules/nginx-lua/t/095-uthread-exec.t index 4459360..56156c4 100644 --- a/debian/modules/nginx-lua/t/095-uthread-exec.t +++ b/debian/modules/nginx-lua/t/095-uthread-exec.t @@ -423,4 +423,3 @@ attempt to abort with pending subrequests --- no_error_log [alert] [warn] - diff --git a/debian/modules/nginx-lua/t/096-uthread-redirect.t b/debian/modules/nginx-lua/t/096-uthread-redirect.t index b0258fb..003c642 100644 --- a/debian/modules/nginx-lua/t/096-uthread-redirect.t +++ b/debian/modules/nginx-lua/t/096-uthread-redirect.t @@ -277,4 +277,3 @@ attempt to abort with pending subrequests --- no_error_log [alert] [warn] - diff --git a/debian/modules/nginx-lua/t/097-uthread-rewrite.t b/debian/modules/nginx-lua/t/097-uthread-rewrite.t index 178a374..a93adc8 100644 --- a/debian/modules/nginx-lua/t/097-uthread-rewrite.t +++ b/debian/modules/nginx-lua/t/097-uthread-rewrite.t @@ -344,4 +344,3 @@ free request end --- error_log attempt to abort with pending subrequests - diff --git a/debian/modules/nginx-lua/t/098-uthread-wait.t b/debian/modules/nginx-lua/t/098-uthread-wait.t index aaf020a..4948596 100644 --- a/debian/modules/nginx-lua/t/098-uthread-wait.t +++ b/debian/modules/nginx-lua/t/098-uthread-wait.t @@ -1321,4 +1321,3 @@ $s; --- no_error_log [error] [alert] - diff --git a/debian/modules/nginx-lua/t/100-client-abort.t b/debian/modules/nginx-lua/t/100-client-abort.t index cd46859..89c1f6a 100644 --- a/debian/modules/nginx-lua/t/100-client-abort.t +++ b/debian/modules/nginx-lua/t/100-client-abort.t @@ -1064,4 +1064,3 @@ GET /t eof succeeded --- error_log eof failed: nginx output filter error - diff --git a/debian/modules/nginx-lua/t/101-on-abort.t b/debian/modules/nginx-lua/t/101-on-abort.t index 81cec78..182d12c 100644 --- a/debian/modules/nginx-lua/t/101-on-abort.t +++ b/debian/modules/nginx-lua/t/101-on-abort.t @@ -846,4 +846,3 @@ done client prematurely closed connection on abort called main handler done - diff --git a/debian/modules/nginx-lua/t/102-req-start-time.t b/debian/modules/nginx-lua/t/102-req-start-time.t index 1d5fe28..3b041af 100644 --- a/debian/modules/nginx-lua/t/102-req-start-time.t +++ b/debian/modules/nginx-lua/t/102-req-start-time.t @@ -113,4 +113,3 @@ true$ --- no_error_log [error] --- SKIP - diff --git a/debian/modules/nginx-lua/t/103-req-http-ver.t b/debian/modules/nginx-lua/t/103-req-http-ver.t index 6ded75a..e6de238 100644 --- a/debian/modules/nginx-lua/t/103-req-http-ver.t +++ b/debian/modules/nginx-lua/t/103-req-http-ver.t @@ -46,4 +46,3 @@ GET /t HTTP/1.0 1 --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/104-req-raw-header.t b/debian/modules/nginx-lua/t/104-req-raw-header.t index 439b9de..efea03c 100644 --- a/debian/modules/nginx-lua/t/104-req-raw-header.t +++ b/debian/modules/nginx-lua/t/104-req-raw-header.t @@ -876,4 +876,3 @@ Foo: bar\r --- no_error_log [error] --- timeout: 5 - diff --git a/debian/modules/nginx-lua/t/105-pressure.t b/debian/modules/nginx-lua/t/105-pressure.t index 10f495e..9d1ba1f 100644 --- a/debian/modules/nginx-lua/t/105-pressure.t +++ b/debian/modules/nginx-lua/t/105-pressure.t @@ -51,4 +51,3 @@ $::Id = int rand 10000; --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/106-timer.t b/debian/modules/nginx-lua/t/106-timer.t index d0f6f36..04a532e 100644 --- a/debian/modules/nginx-lua/t/106-timer.t +++ b/debian/modules/nginx-lua/t/106-timer.t @@ -2193,4 +2193,3 @@ ok --- error_log Bad bad bad --- skip_nginx: 4: < 1.7.1 - diff --git a/debian/modules/nginx-lua/t/107-timer-errors.t b/debian/modules/nginx-lua/t/107-timer-errors.t index 9ed1334..3201612 100644 --- a/debian/modules/nginx-lua/t/107-timer-errors.t +++ b/debian/modules/nginx-lua/t/107-timer-errors.t @@ -1420,4 +1420,3 @@ qr/\[error\] .*? runtime error: content_by_lua\(nginx\.conf:\d+\):3: API disable "lua ngx.timer expired", "http lua close fake http connection" ] - diff --git a/debian/modules/nginx-lua/t/108-timer-safe.t b/debian/modules/nginx-lua/t/108-timer-safe.t index 19c9f6d..2795998 100644 --- a/debian/modules/nginx-lua/t/108-timer-safe.t +++ b/debian/modules/nginx-lua/t/108-timer-safe.t @@ -1395,4 +1395,3 @@ registered timer lua ngx.timer expired http lua close fake http connection trace: [m][f][g] - diff --git a/debian/modules/nginx-lua/t/109-timer-hup.t b/debian/modules/nginx-lua/t/109-timer-hup.t index 15aaa0e..0864046 100644 --- a/debian/modules/nginx-lua/t/109-timer-hup.t +++ b/debian/modules/nginx-lua/t/109-timer-hup.t @@ -500,4 +500,3 @@ ok --- grep_error_log_out lua found 8191 pending timers --- timeout: 20 - diff --git a/debian/modules/nginx-lua/t/110-etag.t b/debian/modules/nginx-lua/t/110-etag.t index 351fec4..0a94d3d 100644 --- a/debian/modules/nginx-lua/t/110-etag.t +++ b/debian/modules/nginx-lua/t/110-etag.t @@ -81,4 +81,3 @@ If-Modified-Since: Thu, 10 May 2012 07:50:59 GMT --- no_error_log [error] --- skip_nginx: 3: < 1.3.3 - diff --git a/debian/modules/nginx-lua/t/111-req-header-ua.t b/debian/modules/nginx-lua/t/111-req-header-ua.t index 7c980d0..9e501e3 100644 --- a/debian/modules/nginx-lua/t/111-req-header-ua.t +++ b/debian/modules/nginx-lua/t/111-req-header-ua.t @@ -673,4 +673,3 @@ content: konqueror: 1 User-Agent: Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.10 (like Gecko) (Kubuntu) --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/112-req-header-conn.t b/debian/modules/nginx-lua/t/112-req-header-conn.t index 51df730..51bc8a4 100644 --- a/debian/modules/nginx-lua/t/112-req-header-conn.t +++ b/debian/modules/nginx-lua/t/112-req-header-conn.t @@ -146,4 +146,3 @@ content: conn type: 0 connection: bad --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/113-req-header-cookie.t b/debian/modules/nginx-lua/t/113-req-header-cookie.t index b26b709..4a93053 100644 --- a/debian/modules/nginx-lua/t/113-req-header-cookie.t +++ b/debian/modules/nginx-lua/t/113-req-header-cookie.t @@ -247,4 +247,3 @@ Cookie: boo=123; foo=bar --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/115-quote-sql-str.t b/debian/modules/nginx-lua/t/115-quote-sql-str.t index 0c20dfb..66553b1 100644 --- a/debian/modules/nginx-lua/t/115-quote-sql-str.t +++ b/debian/modules/nginx-lua/t/115-quote-sql-str.t @@ -74,4 +74,3 @@ GET /set 'a\Zb\Z' --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/116-raw-req-socket.t b/debian/modules/nginx-lua/t/116-raw-req-socket.t index 6518f0e..ab06ee4 100644 --- a/debian/modules/nginx-lua/t/116-raw-req-socket.t +++ b/debian/modules/nginx-lua/t/116-raw-req-socket.t @@ -876,4 +876,3 @@ request body: hey, hello world --- no_error_log [error] [alert] - diff --git a/debian/modules/nginx-lua/t/117-raw-req-socket-timeout.t b/debian/modules/nginx-lua/t/117-raw-req-socket-timeout.t index 4e3929b..07abadc 100644 --- a/debian/modules/nginx-lua/t/117-raw-req-socket-timeout.t +++ b/debian/modules/nginx-lua/t/117-raw-req-socket-timeout.t @@ -114,4 +114,3 @@ lua tcp socket write timed out server: failed to send: timeout --- no_error_log [alert] - diff --git a/debian/modules/nginx-lua/t/119-config-prefix.t b/debian/modules/nginx-lua/t/119-config-prefix.t index 4581aa1..3f79320 100644 --- a/debian/modules/nginx-lua/t/119-config-prefix.t +++ b/debian/modules/nginx-lua/t/119-config-prefix.t @@ -30,4 +30,3 @@ GET /lua ^prefix: \/\S+$ --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/120-re-find.t b/debian/modules/nginx-lua/t/120-re-find.t index 34c0207..73e6134 100644 --- a/debian/modules/nginx-lua/t/120-re-find.t +++ b/debian/modules/nginx-lua/t/120-re-find.t @@ -612,7 +612,7 @@ matched: 你 === TEST 22: just hit match limit --- http_config - lua_regex_match_limit 5600; + lua_regex_match_limit 5000; --- config location /re { content_by_lua_file html/a.lua; @@ -654,7 +654,7 @@ error: pcre_exec() failed: -8 === TEST 23: just not hit match limit --- http_config - lua_regex_match_limit 5700; + lua_regex_match_limit 5100; --- config location /re { content_by_lua_file html/a.lua; @@ -891,3 +891,29 @@ not matched! --- no_error_log [error] + + +=== TEST 31: match with ctx and a pos (anchored by \G) +--- config + location /re { + content_by_lua ' + local ctx = { pos = 3 } + local from, to, err = ngx.re.find("1234, hello", [[(\G[0-9]+)]], "", ctx) + if from then + ngx.say("from: ", from) + ngx.say("to: ", to) + ngx.say("pos: ", ctx.pos) + else + ngx.say("not matched!") + ngx.say("pos: ", ctx.pos) + end + '; + } +--- request + GET /re +--- response_body +from: 3 +to: 4 +pos: 5 +--- no_error_log +[error] diff --git a/debian/modules/nginx-lua/t/121-version.t b/debian/modules/nginx-lua/t/121-version.t index 2b7a306..9000eb3 100644 --- a/debian/modules/nginx-lua/t/121-version.t +++ b/debian/modules/nginx-lua/t/121-version.t @@ -46,4 +46,3 @@ GET /lua ^version: \d+$ --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/122-worker.t b/debian/modules/nginx-lua/t/122-worker.t index fa42b1d..b74c81f 100644 --- a/debian/modules/nginx-lua/t/122-worker.t +++ b/debian/modules/nginx-lua/t/122-worker.t @@ -79,4 +79,3 @@ worker pid: \d+ worker pid is correct\. --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/123-lua-path.t b/debian/modules/nginx-lua/t/123-lua-path.t index da97909..23681a9 100644 --- a/debian/modules/nginx-lua/t/123-lua-path.t +++ b/debian/modules/nginx-lua/t/123-lua-path.t @@ -68,4 +68,3 @@ GET /lua [error] --- error_log eval qr/\[alert\] .*? lua_code_cache is off/ - diff --git a/debian/modules/nginx-lua/t/124-init-worker.t b/debian/modules/nginx-lua/t/124-init-worker.t index d6ea675..22a943e 100644 --- a/debian/modules/nginx-lua/t/124-init-worker.t +++ b/debian/modules/nginx-lua/t/124-init-worker.t @@ -447,7 +447,7 @@ warn(): Thu, 01 Jan 1970 01:34:38 GMT --- timeout: 10 --- http_config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; resolver_timeout 3s; init_worker_by_lua ' -- global diff --git a/debian/modules/nginx-lua/t/125-configure-args.t b/debian/modules/nginx-lua/t/125-configure-args.t index adec129..4160d4e 100644 --- a/debian/modules/nginx-lua/t/125-configure-args.t +++ b/debian/modules/nginx-lua/t/125-configure-args.t @@ -29,4 +29,3 @@ GET /configure_args ^\s*\-\-[^-]+ --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/126-shdict-frag.t b/debian/modules/nginx-lua/t/126-shdict-frag.t index 94422fb..5a2aff8 100644 --- a/debian/modules/nginx-lua/t/126-shdict-frag.t +++ b/debian/modules/nginx-lua/t/126-shdict-frag.t @@ -1264,4 +1264,3 @@ ok --- no_error_log [error] --- timeout: 60 - diff --git a/debian/modules/nginx-lua/t/127-uthread-kill.t b/debian/modules/nginx-lua/t/127-uthread-kill.t index 2ab8abe..cc43c62 100644 --- a/debian/modules/nginx-lua/t/127-uthread-kill.t +++ b/debian/modules/nginx-lua/t/127-uthread-kill.t @@ -190,7 +190,7 @@ resolve name done: -2 === TEST 4: kill pending connect --- config - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; location /lua { content_by_lua ' local ready = false @@ -505,4 +505,3 @@ thread created: zombie [alert] lua tcp socket abort resolver --- error_log - diff --git a/debian/modules/nginx-lua/t/128-duplex-tcp-socket.t b/debian/modules/nginx-lua/t/128-duplex-tcp-socket.t index d3ef3f5..e8434a3 100644 --- a/debian/modules/nginx-lua/t/128-duplex-tcp-socket.t +++ b/debian/modules/nginx-lua/t/128-duplex-tcp-socket.t @@ -315,19 +315,24 @@ failed to send request: closed)$ local data = "" local ntm = 0 - local done = false + local aborted = false for i = 1, 3 do - local res, err, part = sock:receive(1) - if not res then - ngx.say("failed to receive: ", err) - return - else - data = data .. res + if not aborted then + local res, err, part = sock:receive(1) + if not res then + ngx.say("failed to receive: ", err) + aborted = true + else + data = data .. res + end end + ngx.sleep(0.001) end - ngx.say("received: ", data) + if not aborted then + ngx.say("received: ", data) + end '; } @@ -350,6 +355,7 @@ F(ngx_http_lua_socket_tcp_finalize_write_part) { --- tcp_query_len: 11 --- no_error_log [error] +--- wait: 0.05 @@ -623,4 +629,3 @@ close: 1 nil --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/129-ssl-socket.t b/debian/modules/nginx-lua/t/129-ssl-socket.t index 9da9a5c..1c3f7cd 100644 --- a/debian/modules/nginx-lua/t/129-ssl-socket.t +++ b/debian/modules/nginx-lua/t/129-ssl-socket.t @@ -4,7 +4,7 @@ use Test::Nginx::Socket::Lua; repeat_each(2); -plan tests => repeat_each() * 219; +plan tests => repeat_each() * 217; $ENV{TEST_NGINX_HTML_DIR} ||= html_dir(); @@ -26,7 +26,7 @@ sub read_file { $cert; } -our $StartComRootCertificate = read_file("t/cert/startcom.crt"); +our $ComodoRootCertificate = read_file("t/cert/comodo-ca.crt"); our $EquifaxRootCertificate = read_file("t/cert/equifax.crt"); our $TestCertificate = read_file("t/cert/test.crt"); our $TestCertificateKey = read_file("t/cert/test.key"); @@ -125,7 +125,7 @@ SSL reused session === TEST 2: no SNI, no verify --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { #set $port 5000; set $port $TEST_NGINX_MEMCACHED_PORT; @@ -135,7 +135,7 @@ SSL reused session sock:settimeout(2000) do - local ok, err = sock:connect("g.sregex.org", 443) + local ok, err = sock:connect("openresty.org", 443) if not ok then ngx.say("failed to connect: ", err) return @@ -151,7 +151,7 @@ SSL reused session ngx.say("ssl handshake: ", type(session)) - local req = "GET / HTTP/1.1\\r\\nHost: g.sregex.org\\r\\nConnection: close\\r\\n\\r\\n" + local req = "GET / HTTP/1.1\\r\\nHost: openresty.org\\r\\nConnection: close\\r\\n\\r\\n" local bytes, err = sock:send(req) if not bytes then ngx.say("failed to send http request: ", err) @@ -179,21 +179,14 @@ SSL reused session GET /t --- response_body connected: 1 -ssl handshake: userdata -sent http request: 57 bytes. -received: HTTP/1.1 401 Unauthorized -close: 1 nil +failed to do SSL handshake: handshake failed --- log_level: debug --- grep_error_log eval: qr/lua ssl (?:set|save|free) session: [0-9A-F]+:\d+/ ---- grep_error_log_out eval -qr/^lua ssl save session: ([0-9A-F]+):2 -lua ssl free session: ([0-9A-F]+):1 -$/ +--- grep_error_log_out --- no_error_log lua ssl server name: SSL reused session -[error] [alert] --- timeout: 5 @@ -202,17 +195,17 @@ SSL reused session === TEST 3: SNI, no verify --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { #set $port 5000; set $port $TEST_NGINX_MEMCACHED_PORT; - content_by_lua ' + content_by_lua_block { local sock = ngx.socket.tcp() sock:settimeout(2000) do - local ok, err = sock:connect("iscribblet.org", 443) + local ok, err = sock:connect("openresty.org", 443) if not ok then ngx.say("failed to connect: ", err) return @@ -220,7 +213,7 @@ SSL reused session ngx.say("connected: ", ok) - local session, err = sock:sslhandshake(nil, "iscribblet.org") + local session, err = sock:sslhandshake(nil, "openresty.org") if not session then ngx.say("failed to do SSL handshake: ", err) return @@ -228,7 +221,7 @@ SSL reused session ngx.say("ssl handshake: ", type(session)) - local req = "GET / HTTP/1.1\\r\\nHost: iscribblet.org\\r\\nConnection: close\\r\\n\\r\\n" + local req = "GET / HTTP/1.1\r\nHost: openresty.org\r\nConnection: close\r\n\r\n" local bytes, err = sock:send(req) if not bytes then ngx.say("failed to send http request: ", err) @@ -249,7 +242,7 @@ SSL reused session ngx.say("close: ", ok, " ", err) end -- do collectgarbage() - '; + } } --- request @@ -257,8 +250,8 @@ GET /t --- response_body connected: 1 ssl handshake: userdata -sent http request: 59 bytes. -received: HTTP/1.1 200 OK +sent http request: 58 bytes. +received: HTTP/1.1 302 Moved Temporarily close: 1 nil --- log_level: debug @@ -268,7 +261,7 @@ qr/^lua ssl save session: ([0-9A-F]+):2 lua ssl free session: ([0-9A-F]+):1 $/ --- error_log -lua ssl server name: "iscribblet.org" +lua ssl server name: "openresty.org" --- no_error_log SSL reused session [error] @@ -280,7 +273,8 @@ SSL reused session === TEST 4: ssl session reuse --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; + lua_ssl_protocols TLSv1.2; location /t { #set $port 5000; set $port $TEST_NGINX_MEMCACHED_PORT; @@ -293,7 +287,7 @@ SSL reused session local session for i = 1, 2 do - local ok, err = sock:connect("iscribblet.org", 443) + local ok, err = sock:connect("agentzh.org", 443) if not ok then ngx.say("failed to connect: ", err) return @@ -301,7 +295,7 @@ SSL reused session ngx.say("connected: ", ok) - session, err = sock:sslhandshake(session, "iscribblet.org") + session, err = sock:sslhandshake(session, "agentzh.org") if not session then ngx.say("failed to do SSL handshake: ", err) return @@ -309,7 +303,7 @@ SSL reused session ngx.say("ssl handshake: ", type(session)) - local req = "GET / HTTP/1.1\\r\\nHost: iscribblet.org\\r\\nConnection: close\\r\\n\\r\\n" + local req = "GET / HTTP/1.1\\r\\nHost: agentzh.org\\r\\nConnection: close\\r\\n\\r\\n" local bytes, err = sock:send(req) if not bytes then ngx.say("failed to send http request: ", err) @@ -340,12 +334,12 @@ GET /t --- response_body connected: 1 ssl handshake: userdata -sent http request: 59 bytes. +sent http request: 56 bytes. received: HTTP/1.1 200 OK close: 1 nil connected: 1 ssl handshake: userdata -sent http request: 59 bytes. +sent http request: 56 bytes. received: HTTP/1.1 200 OK close: 1 nil @@ -371,10 +365,10 @@ lua ssl free session === TEST 5: certificate does not match host name (verify) -The certificate for "blah.agentzh.org" does not contain the name "blah.agentzh.org". +The certificate of "openresty.org" does not contain the name "blah.openresty.org". --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; lua_ssl_trusted_certificate ../html/trusted.crt; lua_ssl_verify_depth 5; location /t { @@ -386,7 +380,7 @@ The certificate for "blah.agentzh.org" does not contain the name "blah.agentzh.o sock:settimeout(2000) do - local ok, err = sock:connect("agentzh.org", 443) + local ok, err = sock:connect("openresty.org", 443) if not ok then ngx.say("failed to connect: ", err) return @@ -394,13 +388,171 @@ The certificate for "blah.agentzh.org" does not contain the name "blah.agentzh.o ngx.say("connected: ", ok) - local session, err = sock:sslhandshake(nil, "blah.agentzh.org", true) + local session, err = sock:sslhandshake(nil, "blah.openresty.org", true) if not session then ngx.say("failed to do SSL handshake: ", err) else ngx.say("ssl handshake: ", type(session)) end + local req = "GET / HTTP/1.1\\r\\nHost: openresty.org\\r\\nConnection: close\\r\\n\\r\\n" + local bytes, err = sock:send(req) + if not bytes then + ngx.say("failed to send http request: ", err) + return + end + + ngx.say("sent http request: ", bytes, " bytes.") + + local line, err = sock:receive() + if not line then + ngx.say("failed to receive response status line: ", err) + return + end + + ngx.say("received: ", line) + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + collectgarbage() + '; + } + +--- user_files eval +">>> trusted.crt +$::ComodoRootCertificate" + +--- request +GET /t +--- response_body_like chomp +\Aconnected: 1 +failed to do SSL handshake: (?:handshake failed|certificate host mismatch) +failed to send http request: closed +\z + +--- log_level: debug +--- grep_error_log eval: qr/lua ssl (?:set|save|free) session: [0-9A-F]+:\d+/ +--- grep_error_log_out +--- error_log +lua ssl server name: "blah.openresty.org" +--- no_error_log +SSL reused session +[alert] +--- timeout: 5 + + + +=== TEST 6: certificate does not match host name (verify, no log socket errors) +The certificate for "openresty.org" does not contain the name "blah.openresty.org". +--- config + server_tokens off; + resolver $TEST_NGINX_RESOLVER ipv6=off; + lua_ssl_trusted_certificate ../html/trusted.crt; + lua_socket_log_errors off; + lua_ssl_verify_depth 2; + location /t { + #set $port 5000; + set $port $TEST_NGINX_MEMCACHED_PORT; + + content_by_lua ' + local sock = ngx.socket.tcp() + sock:settimeout(2000) + + do + local ok, err = sock:connect("openresty.org", 443) + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local session, err = sock:sslhandshake(nil, "blah.openresty.org", true) + if not session then + ngx.say("failed to do SSL handshake: ", err) + else + ngx.say("ssl handshake: ", type(session)) + end + + local req = "GET / HTTP/1.1\\r\\nHost: blah.openresty.org\\r\\nConnection: close\\r\\n\\r\\n" + local bytes, err = sock:send(req) + if not bytes then + ngx.say("failed to send http request: ", err) + return + end + + ngx.say("sent http request: ", bytes, " bytes.") + + local line, err = sock:receive() + if not line then + ngx.say("failed to receive response status line: ", err) + return + end + + ngx.say("received: ", line) + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + collectgarbage() + '; + } + +--- user_files eval +">>> trusted.crt +$::ComodoRootCertificate" + +--- request +GET /t +--- response_body_like chomp +\Aconnected: 1 +failed to do SSL handshake: (?:handshake failed|certificate host mismatch) +failed to send http request: closed +\z + +--- log_level: debug +--- grep_error_log eval: qr/lua ssl (?:set|save|free) session: [0-9A-F]+:\d+/ +--- grep_error_log_out +--- error_log +lua ssl server name: "blah.openresty.org" +--- no_error_log +lua ssl certificate does not match host +SSL reused session +[alert] +--- timeout: 5 + + + +=== TEST 7: certificate does not match host name (no verify) +--- config + server_tokens off; + resolver $TEST_NGINX_RESOLVER ipv6=off; + location /t { + #set $port 5000; + set $port $TEST_NGINX_MEMCACHED_PORT; + + content_by_lua ' + local sock = ngx.socket.tcp() + sock:settimeout(2000) + + do + local ok, err = sock:connect("openresty.org", 443) + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local session, err = sock:sslhandshake(nil, "openresty.org", false) + if not session then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(session)) + local req = "GET / HTTP/1.1\\r\\nHost: agentzh.org\\r\\nConnection: close\\r\\n\\r\\n" local bytes, err = sock:send(req) if not bytes then @@ -425,170 +577,13 @@ The certificate for "blah.agentzh.org" does not contain the name "blah.agentzh.o '; } ---- user_files eval -">>> trusted.crt -$::StartComRootCertificate" - ---- request -GET /t ---- response_body -connected: 1 -failed to do SSL handshake: certificate host mismatch -failed to send http request: closed - ---- log_level: debug ---- grep_error_log eval: qr/lua ssl (?:set|save|free) session: [0-9A-F]+:\d+/ ---- grep_error_log_out ---- error_log -lua ssl server name: "blah.agentzh.org" -lua ssl certificate does not match host "blah.agentzh.org" ---- no_error_log -SSL reused session -[alert] ---- timeout: 5 - - - -=== TEST 6: certificate does not match host name (verify, no log socket errors) -The certificate for "blah.agentzh.org" does not contain the name "blah.agentzh.org". ---- config - server_tokens off; - resolver $TEST_NGINX_RESOLVER; - lua_ssl_trusted_certificate ../html/trusted.crt; - lua_socket_log_errors off; - lua_ssl_verify_depth 2; - location /t { - #set $port 5000; - set $port $TEST_NGINX_MEMCACHED_PORT; - - content_by_lua ' - local sock = ngx.socket.tcp() - sock:settimeout(2000) - - do - local ok, err = sock:connect("agentzh.org", 443) - if not ok then - ngx.say("failed to connect: ", err) - return - end - - ngx.say("connected: ", ok) - - local session, err = sock:sslhandshake(nil, "blah.agentzh.org", true) - if not session then - ngx.say("failed to do SSL handshake: ", err) - else - ngx.say("ssl handshake: ", type(session)) - end - - local req = "GET / HTTP/1.1\\r\\nHost: blah.agentzh.org\\r\\nConnection: close\\r\\n\\r\\n" - local bytes, err = sock:send(req) - if not bytes then - ngx.say("failed to send http request: ", err) - return - end - - ngx.say("sent http request: ", bytes, " bytes.") - - local line, err = sock:receive() - if not line then - ngx.say("failed to receive response status line: ", err) - return - end - - ngx.say("received: ", line) - - local ok, err = sock:close() - ngx.say("close: ", ok, " ", err) - end -- do - collectgarbage() - '; - } - ---- user_files eval -">>> trusted.crt -$::StartComRootCertificate" - ---- request -GET /t ---- response_body -connected: 1 -failed to do SSL handshake: certificate host mismatch -failed to send http request: closed - ---- log_level: debug ---- grep_error_log eval: qr/lua ssl (?:set|save|free) session: [0-9A-F]+:\d+/ ---- grep_error_log_out ---- error_log -lua ssl server name: "blah.agentzh.org" ---- no_error_log -lua ssl certificate does not match host -SSL reused session -[alert] ---- timeout: 5 - - - -=== TEST 7: certificate does not match host name (no verify) ---- config - server_tokens off; - resolver $TEST_NGINX_RESOLVER; - location /t { - #set $port 5000; - set $port $TEST_NGINX_MEMCACHED_PORT; - - content_by_lua ' - local sock = ngx.socket.tcp() - sock:settimeout(2000) - - do - local ok, err = sock:connect("agentzh.org", 443) - if not ok then - ngx.say("failed to connect: ", err) - return - end - - ngx.say("connected: ", ok) - - local session, err = sock:sslhandshake(nil, "agentzh.org", false) - if not session then - ngx.say("failed to do SSL handshake: ", err) - return - end - - ngx.say("ssl handshake: ", type(session)) - - local req = "GET / HTTP/1.1\\r\\nHost: iscribblet.org\\r\\nConnection: close\\r\\n\\r\\n" - local bytes, err = sock:send(req) - if not bytes then - ngx.say("failed to send http request: ", err) - return - end - - ngx.say("sent http request: ", bytes, " bytes.") - - local line, err = sock:receive() - if not line then - ngx.say("failed to receive response status line: ", err) - return - end - - ngx.say("received: ", line) - - local ok, err = sock:close() - ngx.say("close: ", ok, " ", err) - end -- do - collectgarbage() - '; - } - --- request GET /t --- response_body connected: 1 ssl handshake: userdata -sent http request: 59 bytes. -received: HTTP/1.1 200 OK +sent http request: 56 bytes. +received: HTTP/1.1 404 Not Found close: 1 nil --- log_level: debug @@ -599,7 +594,7 @@ lua ssl free session: ([0-9A-F]+):1 $/ --- error_log -lua ssl server name: "agentzh.org" +lua ssl server name: "openresty.org" --- no_error_log SSL reused session [error] @@ -608,10 +603,10 @@ SSL reused session -=== TEST 8: iscribblet.org: passing SSL verify +=== TEST 8: openresty.org: passing SSL verify --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; lua_ssl_trusted_certificate ../html/trusted.crt; lua_ssl_verify_depth 2; location /t { @@ -623,7 +618,7 @@ SSL reused session sock:settimeout(2000) do - local ok, err = sock:connect("iscribblet.org", 443) + local ok, err = sock:connect("openresty.org", 443) if not ok then ngx.say("failed to connect: ", err) return @@ -631,7 +626,7 @@ SSL reused session ngx.say("connected: ", ok) - local session, err = sock:sslhandshake(nil, "iscribblet.org", true) + local session, err = sock:sslhandshake(nil, "openresty.org", true) if not session then ngx.say("failed to do SSL handshake: ", err) return @@ -639,7 +634,7 @@ SSL reused session ngx.say("ssl handshake: ", type(session)) - local req = "GET / HTTP/1.1\\r\\nHost: iscribblet.org\\r\\nConnection: close\\r\\n\\r\\n" + local req = "GET / HTTP/1.1\\r\\nHost: openresty.org\\r\\nConnection: close\\r\\n\\r\\n" local bytes, err = sock:send(req) if not bytes then ngx.say("failed to send http request: ", err) @@ -665,15 +660,15 @@ SSL reused session --- user_files eval ">>> trusted.crt -$::StartComRootCertificate" +$::ComodoRootCertificate" --- request GET /t --- response_body connected: 1 ssl handshake: userdata -sent http request: 59 bytes. -received: HTTP/1.1 200 OK +sent http request: 58 bytes. +received: HTTP/1.1 302 Moved Temporarily close: 1 nil --- log_level: debug @@ -684,7 +679,7 @@ lua ssl free session: ([0-9A-F]+):1 $/ --- error_log -lua ssl server name: "iscribblet.org" +lua ssl server name: "openresty.org" --- no_error_log SSL reused session [error] @@ -696,7 +691,7 @@ SSL reused session === TEST 9: ssl verify depth not enough (with automatic error logging) --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; lua_ssl_trusted_certificate ../html/trusted.crt; lua_ssl_verify_depth 1; location /t { @@ -708,7 +703,7 @@ SSL reused session sock:settimeout(2000) do - local ok, err = sock:connect("iscribblet.org", 443) + local ok, err = sock:connect("openresty.org", 443) if not ok then ngx.say("failed to connect: ", err) return @@ -716,14 +711,14 @@ SSL reused session ngx.say("connected: ", ok) - local session, err = sock:sslhandshake(nil, "iscribblet.org", true) + local session, err = sock:sslhandshake(nil, "openresty.org", true) if not session then ngx.say("failed to do SSL handshake: ", err) else ngx.say("ssl handshake: ", type(session)) end - local req = "GET / HTTP/1.1\\r\\nHost: iscribblet.org\\r\\nConnection: close\\r\\n\\r\\n" + local req = "GET / HTTP/1.1\\r\\nHost: openresty.org\\r\\nConnection: close\\r\\n\\r\\n" local bytes, err = sock:send(req) if not bytes then ngx.say("failed to send http request: ", err) @@ -749,7 +744,7 @@ SSL reused session --- user_files eval ">>> trusted.crt -$::StartComRootCertificate" +$::ComodoRootCertificate" --- request GET /t @@ -762,7 +757,7 @@ failed to send http request: closed --- grep_error_log eval: qr/lua ssl (?:set|save|free) session: [0-9A-F]+:\d+/ --- grep_error_log_out --- error_log -lua ssl server name: "iscribblet.org" +lua ssl server name: "openresty.org" lua ssl certificate verify error: (20: unable to get local issuer certificate) --- no_error_log SSL reused session @@ -774,7 +769,7 @@ SSL reused session === TEST 10: ssl verify depth not enough (without automatic error logging) --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; lua_ssl_trusted_certificate ../html/trusted.crt; lua_ssl_verify_depth 1; lua_socket_log_errors off; @@ -787,7 +782,7 @@ SSL reused session sock:settimeout(2000) do - local ok, err = sock:connect("iscribblet.org", 443) + local ok, err = sock:connect("openresty.org", 443) if not ok then ngx.say("failed to connect: ", err) return @@ -795,14 +790,14 @@ SSL reused session ngx.say("connected: ", ok) - local session, err = sock:sslhandshake(nil, "iscribblet.org", true) + local session, err = sock:sslhandshake(nil, "openresty.org", true) if not session then ngx.say("failed to do SSL handshake: ", err) else ngx.say("ssl handshake: ", type(session)) end - local req = "GET / HTTP/1.1\\r\\nHost: iscribblet.org\\r\\nConnection: close\\r\\n\\r\\n" + local req = "GET / HTTP/1.1\\r\\nHost: openresty.org\\r\\nConnection: close\\r\\n\\r\\n" local bytes, err = sock:send(req) if not bytes then ngx.say("failed to send http request: ", err) @@ -828,7 +823,7 @@ SSL reused session --- user_files eval ">>> trusted.crt -$::StartComRootCertificate" +$::ComodoRootCertificate" --- request GET /t @@ -841,7 +836,7 @@ failed to send http request: closed --- grep_error_log eval: qr/lua ssl (?:set|save|free) session: [0-9A-F]+:\d+/ --- grep_error_log_out --- error_log -lua ssl server name: "iscribblet.org" +lua ssl server name: "openresty.org" --- no_error_log lua ssl certificate verify error SSL reused session @@ -1010,7 +1005,7 @@ SSL reused session --- user_files eval ">>> trusted.crt -$::StartComRootCertificate" +$::ComodoRootCertificate" --- request GET /t @@ -1030,10 +1025,10 @@ SSL reused session -=== TEST 13: iscribblet.org: passing SSL verify with multiple certificates +=== TEST 13: openresty.org: passing SSL verify with multiple certificates --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; lua_ssl_trusted_certificate ../html/trusted.crt; lua_ssl_verify_depth 2; location /t { @@ -1045,7 +1040,7 @@ SSL reused session sock:settimeout(2000) do - local ok, err = sock:connect("iscribblet.org", 443) + local ok, err = sock:connect("openresty.org", 443) if not ok then ngx.say("failed to connect: ", err) return @@ -1053,7 +1048,7 @@ SSL reused session ngx.say("connected: ", ok) - local session, err = sock:sslhandshake(nil, "iscribblet.org", true) + local session, err = sock:sslhandshake(nil, "openresty.org", true) if not session then ngx.say("failed to do SSL handshake: ", err) return @@ -1061,7 +1056,7 @@ SSL reused session ngx.say("ssl handshake: ", type(session)) - local req = "GET / HTTP/1.1\\r\\nHost: iscribblet.org\\r\\nConnection: close\\r\\n\\r\\n" + local req = "GET / HTTP/1.1\\r\\nHost: openresty.org\\r\\nConnection: close\\r\\n\\r\\n" local bytes, err = sock:send(req) if not bytes then ngx.say("failed to send http request: ", err) @@ -1088,15 +1083,15 @@ SSL reused session --- user_files eval ">>> trusted.crt $::EquifaxRootCertificate -$::StartComRootCertificate" +$::ComodoRootCertificate" --- request GET /t --- response_body connected: 1 ssl handshake: userdata -sent http request: 59 bytes. -received: HTTP/1.1 200 OK +sent http request: 58 bytes. +received: HTTP/1.1 302 Moved Temporarily close: 1 nil --- log_level: debug @@ -1107,7 +1102,7 @@ lua ssl free session: ([0-9A-F]+):1 $/ --- error_log -lua ssl server name: "iscribblet.org" +lua ssl server name: "openresty.org" --- no_error_log SSL reused session [error] @@ -1119,7 +1114,7 @@ SSL reused session === TEST 14: default cipher --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { #set $port 5000; set $port $TEST_NGINX_MEMCACHED_PORT; @@ -1129,7 +1124,7 @@ SSL reused session sock:settimeout(2000) do - local ok, err = sock:connect("iscribblet.org", 443) + local ok, err = sock:connect("openresty.org", 443) if not ok then ngx.say("failed to connect: ", err) return @@ -1137,7 +1132,7 @@ SSL reused session ngx.say("connected: ", ok) - local session, err = sock:sslhandshake(nil, "iscribblet.org") + local session, err = sock:sslhandshake(nil, "openresty.org") if not session then ngx.say("failed to do SSL handshake: ", err) return @@ -1145,7 +1140,7 @@ SSL reused session ngx.say("ssl handshake: ", type(session)) - local req = "GET / HTTP/1.1\\r\\nHost: iscribblet.org\\r\\nConnection: close\\r\\n\\r\\n" + local req = "GET / HTTP/1.1\\r\\nHost: openresty.org\\r\\nConnection: close\\r\\n\\r\\n" local bytes, err = sock:send(req) if not bytes then ngx.say("failed to send http request: ", err) @@ -1174,8 +1169,8 @@ GET /t --- response_body connected: 1 ssl handshake: userdata -sent http request: 59 bytes. -received: HTTP/1.1 200 OK +sent http request: 58 bytes. +received: HTTP/1.1 302 Moved Temporarily close: 1 nil --- log_level: debug @@ -1185,8 +1180,8 @@ qr/^lua ssl save session: ([0-9A-F]+):2 lua ssl free session: ([0-9A-F]+):1 $/ --- error_log -lua ssl server name: "iscribblet.org" -SSL: TLSv1.2, cipher: "ECDHE-RSA-RC4-SHA SSLv3 +lua ssl server name: "openresty.org" +SSL: TLSv1.2, cipher: "ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 --- no_error_log SSL reused session [error] @@ -1198,8 +1193,8 @@ SSL reused session === TEST 15: explicit cipher configuration --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; - lua_ssl_ciphers RC4-SHA; + resolver $TEST_NGINX_RESOLVER ipv6=off; + lua_ssl_ciphers ECDHE-RSA-AES256-SHA; location /t { #set $port 5000; set $port $TEST_NGINX_MEMCACHED_PORT; @@ -1209,7 +1204,7 @@ SSL reused session sock:settimeout(2000) do - local ok, err = sock:connect("iscribblet.org", 443) + local ok, err = sock:connect("openresty.org", 443) if not ok then ngx.say("failed to connect: ", err) return @@ -1217,7 +1212,7 @@ SSL reused session ngx.say("connected: ", ok) - local session, err = sock:sslhandshake(nil, "iscribblet.org") + local session, err = sock:sslhandshake(nil, "openresty.org") if not session then ngx.say("failed to do SSL handshake: ", err) return @@ -1225,7 +1220,7 @@ SSL reused session ngx.say("ssl handshake: ", type(session)) - local req = "GET / HTTP/1.1\\r\\nHost: iscribblet.org\\r\\nConnection: close\\r\\n\\r\\n" + local req = "GET / HTTP/1.1\\r\\nHost: openresty.org\\r\\nConnection: close\\r\\n\\r\\n" local bytes, err = sock:send(req) if not bytes then ngx.say("failed to send http request: ", err) @@ -1254,8 +1249,8 @@ GET /t --- response_body connected: 1 ssl handshake: userdata -sent http request: 59 bytes. -received: HTTP/1.1 200 OK +sent http request: 58 bytes. +received: HTTP/1.1 302 Moved Temporarily close: 1 nil --- log_level: debug @@ -1265,8 +1260,8 @@ qr/^lua ssl save session: ([0-9A-F]+):2 lua ssl free session: ([0-9A-F]+):1 $/ --- error_log -lua ssl server name: "iscribblet.org" -SSL: TLSv1.2, cipher: "RC4-SHA SSLv3 +lua ssl server name: "openresty.org" +SSL: TLSv1.2, cipher: "ECDHE-RSA-AES256-SHA --- no_error_log SSL reused session [error] @@ -1278,7 +1273,7 @@ SSL reused session === TEST 16: explicit ssl protocol configuration --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; lua_ssl_protocols TLSv1; location /t { #set $port 5000; @@ -1289,7 +1284,7 @@ SSL reused session sock:settimeout(2000) do - local ok, err = sock:connect("iscribblet.org", 443) + local ok, err = sock:connect("openresty.org", 443) if not ok then ngx.say("failed to connect: ", err) return @@ -1297,7 +1292,7 @@ SSL reused session ngx.say("connected: ", ok) - local session, err = sock:sslhandshake(nil, "iscribblet.org") + local session, err = sock:sslhandshake(nil, "openresty.org") if not session then ngx.say("failed to do SSL handshake: ", err) return @@ -1305,7 +1300,7 @@ SSL reused session ngx.say("ssl handshake: ", type(session)) - local req = "GET / HTTP/1.1\\r\\nHost: iscribblet.org\\r\\nConnection: close\\r\\n\\r\\n" + local req = "GET / HTTP/1.1\\r\\nHost: openresty.org\\r\\nConnection: close\\r\\n\\r\\n" local bytes, err = sock:send(req) if not bytes then ngx.say("failed to send http request: ", err) @@ -1334,8 +1329,8 @@ GET /t --- response_body connected: 1 ssl handshake: userdata -sent http request: 59 bytes. -received: HTTP/1.1 200 OK +sent http request: 58 bytes. +received: HTTP/1.1 302 Moved Temporarily close: 1 nil --- log_level: debug @@ -1345,8 +1340,8 @@ qr/^lua ssl save session: ([0-9A-F]+):2 lua ssl free session: ([0-9A-F]+):1 $/ --- error_log -lua ssl server name: "iscribblet.org" -SSL: TLSv1, cipher: "ECDHE-RSA-RC4-SHA SSLv3 +lua ssl server name: "openresty.org" +SSL: TLSv1, cipher: "ECDHE-RSA-AES256-SHA --- no_error_log SSL reused session [error] @@ -1358,7 +1353,7 @@ SSL reused session === TEST 17: unsupported ssl protocol --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; lua_ssl_protocols SSLv2; lua_socket_log_errors off; location /t { @@ -1370,7 +1365,7 @@ SSL reused session sock:settimeout(2000) do - local ok, err = sock:connect("iscribblet.org", 443) + local ok, err = sock:connect("openresty.org", 443) if not ok then ngx.say("failed to connect: ", err) return @@ -1378,14 +1373,14 @@ SSL reused session ngx.say("connected: ", ok) - local session, err = sock:sslhandshake(nil, "iscribblet.org") + local session, err = sock:sslhandshake(nil, "openresty.org") if not session then ngx.say("failed to do SSL handshake: ", err) else ngx.say("ssl handshake: ", type(session)) end - local req = "GET / HTTP/1.1\\r\\nHost: iscribblet.org\\r\\nConnection: close\\r\\n\\r\\n" + local req = "GET / HTTP/1.1\\r\\nHost: openresty.org\\r\\nConnection: close\\r\\n\\r\\n" local bytes, err = sock:send(req) if not bytes then ngx.say("failed to send http request: ", err) @@ -1422,7 +1417,7 @@ failed to send http request: closed --- error_log eval [ qr/\[crit\] .*?SSL_do_handshake\(\) failed .*?unsupported protocol/, -'lua ssl server name: "iscribblet.org"', +'lua ssl server name: "openresty.org"', ] --- no_error_log SSL reused session @@ -1432,10 +1427,10 @@ SSL reused session -=== TEST 18: iscribblet.org: passing SSL verify: keepalive (reuse the ssl session) +=== TEST 18: openresty.org: passing SSL verify: keepalive (reuse the ssl session) --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; lua_ssl_trusted_certificate ../html/trusted.crt; lua_ssl_verify_depth 2; location /t { @@ -1450,7 +1445,7 @@ SSL reused session local session for i = 1, 3 do - local ok, err = sock:connect("iscribblet.org", 443) + local ok, err = sock:connect("openresty.org", 443) if not ok then ngx.say("failed to connect: ", err) return @@ -1458,7 +1453,7 @@ SSL reused session ngx.say("connected: ", ok) - session, err = sock:sslhandshake(session, "iscribblet.org", true) + session, err = sock:sslhandshake(session, "openresty.org", true) if not session then ngx.say("failed to do SSL handshake: ", err) return @@ -1477,7 +1472,7 @@ SSL reused session --- user_files eval ">>> trusted.crt -$::StartComRootCertificate" +$::ComodoRootCertificate" --- request GET /t @@ -1509,10 +1504,10 @@ SSL reused session -=== TEST 19: iscribblet.org: passing SSL verify: keepalive (no reusing the ssl session) +=== TEST 19: openresty.org: passing SSL verify: keepalive (no reusing the ssl session) --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; lua_ssl_trusted_certificate ../html/trusted.crt; lua_ssl_verify_depth 2; location /t { @@ -1526,7 +1521,7 @@ SSL reused session do for i = 1, 3 do - local ok, err = sock:connect("iscribblet.org", 443) + local ok, err = sock:connect("openresty.org", 443) if not ok then ngx.say("failed to connect: ", err) return @@ -1534,7 +1529,7 @@ SSL reused session ngx.say("connected: ", ok) - local session, err = sock:sslhandshake(nil, "iscribblet.org", true) + local session, err = sock:sslhandshake(nil, "openresty.org", true) if not session then ngx.say("failed to do SSL handshake: ", err) return @@ -1553,7 +1548,7 @@ SSL reused session --- user_files eval ">>> trusted.crt -$::StartComRootCertificate" +$::ComodoRootCertificate" --- request GET /t @@ -1592,7 +1587,7 @@ SSL reused session === TEST 20: downstream cosockets do not support ssl handshake --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; lua_ssl_trusted_certificate ../html/trusted.crt; lua_ssl_verify_depth 2; location /t { @@ -1612,7 +1607,7 @@ SSL reused session --- user_files eval ">>> trusted.crt -$::StartComRootCertificate" +$::ComodoRootCertificate" --- request POST /t @@ -1647,7 +1642,7 @@ attempt to call method 'sslhandshake' (a nil value) } --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { #set $port 5000; set $port $TEST_NGINX_MEMCACHED_PORT; @@ -1750,7 +1745,7 @@ SSL reused session } --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; lua_ssl_trusted_certificate ../html/test.crt; location /t { @@ -1854,7 +1849,7 @@ SSL reused session } --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { #set $port 5000; set $port $TEST_NGINX_MEMCACHED_PORT; @@ -1946,7 +1941,7 @@ SSL reused session } --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; lua_ssl_crl ../html/test.crl; lua_ssl_trusted_certificate ../html/test.crt; lua_socket_log_errors off; @@ -2031,7 +2026,7 @@ SSL reused session === TEST 25: multiple handshake calls --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { #set $port 5000; set $port $TEST_NGINX_MEMCACHED_PORT; @@ -2042,7 +2037,7 @@ SSL reused session sock:settimeout(2000) do - local ok, err = sock:connect("iscribblet.org", 443) + local ok, err = sock:connect("openresty.org", 443) if not ok then ngx.say("failed to connect: ", err) return @@ -2051,7 +2046,7 @@ SSL reused session ngx.say("connected: ", ok) for i = 1, 2 do - local session, err = sock:sslhandshake(nil, "iscribblet.org") + local session, err = sock:sslhandshake(nil, "openresty.org") if not session then ngx.say("failed to do SSL handshake: ", err) return @@ -2060,7 +2055,7 @@ SSL reused session ngx.say("ssl handshake: ", type(session)) end - local req = "GET / HTTP/1.1\\r\\nHost: iscribblet.org\\r\\nConnection: close\\r\\n\\r\\n" + local req = "GET / HTTP/1.1\\r\\nHost: openresty.org\\r\\nConnection: close\\r\\n\\r\\n" local bytes, err = sock:send(req) if not bytes then ngx.say("failed to send http request: ", err) @@ -2090,8 +2085,8 @@ GET /t connected: 1 ssl handshake: userdata ssl handshake: userdata -sent http request: 59 bytes. -received: HTTP/1.1 200 OK +sent http request: 58 bytes. +received: HTTP/1.1 302 Moved Temporarily close: 1 nil --- log_level: debug @@ -2103,7 +2098,7 @@ lua ssl free session: ([0-9A-F]+):2 lua ssl free session: ([0-9A-F]+):1 $/ --- error_log -lua ssl server name: "iscribblet.org" +lua ssl server name: "openresty.org" --- no_error_log SSL reused session [error] @@ -2115,7 +2110,7 @@ SSL reused session === TEST 26: handshake timed out --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { #set $port 5000; set $port $TEST_NGINX_MEMCACHED_PORT; @@ -2126,7 +2121,7 @@ SSL reused session sock:settimeout(2000) do - local ok, err = sock:connect("iscribblet.org", 443) + local ok, err = sock:connect("openresty.org", 443) if not ok then ngx.say("failed to connect: ", err) return @@ -2135,7 +2130,7 @@ SSL reused session ngx.say("connected: ", ok) sock:settimeout(1); -- should timeout immediately - local session, err = sock:sslhandshake(nil, "iscribblet.org") + local session, err = sock:sslhandshake(nil, "openresty.org") if not session then ngx.say("failed to do SSL handshake: ", err) return @@ -2157,7 +2152,7 @@ failed to do SSL handshake: timeout --- grep_error_log eval: qr/lua ssl (?:set|save|free) session: [0-9A-F]+:\d+/ --- grep_error_log_out --- error_log -lua ssl server name: "iscribblet.org" +lua ssl server name: "openresty.org" --- no_error_log SSL reused session [error] @@ -2183,7 +2178,7 @@ SSL reused session } --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { #set $port 5000; set $port $TEST_NGINX_MEMCACHED_PORT; @@ -2254,7 +2249,7 @@ SSL reused session } --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { #set $port 5000; set $port $TEST_NGINX_MEMCACHED_PORT; @@ -2328,7 +2323,7 @@ SSL reused session } --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { #set $port 5000; set $port $TEST_NGINX_MEMCACHED_PORT; @@ -2405,7 +2400,7 @@ SSL reused session } --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; lua_ssl_trusted_certificate ../html/test.crt; location /t { @@ -2510,7 +2505,7 @@ SSL reused session } --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; #lua_ssl_trusted_certificate ../html/test.crt; location /t { @@ -2589,7 +2584,7 @@ SSL reused session === TEST 32: handshake, too many arguments --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; location /t { #set $port 5000; set $port $TEST_NGINX_MEMCACHED_PORT; @@ -2598,7 +2593,7 @@ SSL reused session local sock = ngx.socket.tcp() sock:settimeout(2000) - local ok, err = sock:connect("g.sregex.org", 443) + local ok, err = sock:connect("openresty.org", 443) if not ok then ngx.say("failed to connect: ", err) return @@ -2614,7 +2609,7 @@ SSL reused session GET /t --- ignore_response --- error_log eval -qr/\[error\] .* ngx.socket connect: expecting 1 ~ 5 arguments \(including the object\), but seen 0/ +qr/\[error\] .* ngx.socket sslhandshake: expecting 1 ~ 5 arguments \(including the object\), but seen 0/ --- no_error_log [alert] --- timeout: 5 diff --git a/debian/modules/nginx-lua/t/130-internal-api.t b/debian/modules/nginx-lua/t/130-internal-api.t index d641ab5..eba0980 100644 --- a/debian/modules/nginx-lua/t/130-internal-api.t +++ b/debian/modules/nginx-lua/t/130-internal-api.t @@ -47,4 +47,3 @@ content req=0x[a-f0-9]{4,} $ --- no_error_log [error] - diff --git a/debian/modules/nginx-lua/t/135-worker-id.t b/debian/modules/nginx-lua/t/135-worker-id.t index 3c1f24d..984f446 100644 --- a/debian/modules/nginx-lua/t/135-worker-id.t +++ b/debian/modules/nginx-lua/t/135-worker-id.t @@ -54,7 +54,7 @@ GET /lua content_by_lua_block { local counters = ngx.shared.counters local ok, c - for i = 1, 45 do + for i = 1, 100 do c = counters:get("c") if c >= 4 then ok = true diff --git a/debian/modules/nginx-lua/t/137-req-misc.t b/debian/modules/nginx-lua/t/137-req-misc.t index 20ada3c..d56f80e 100644 --- a/debian/modules/nginx-lua/t/137-req-misc.t +++ b/debian/modules/nginx-lua/t/137-req-misc.t @@ -59,4 +59,3 @@ not internal GET /test --- response_body internal - diff --git a/debian/modules/nginx-lua/t/138-balancer.t b/debian/modules/nginx-lua/t/138-balancer.t index 8d45c24..ddd0da5 100644 --- a/debian/modules/nginx-lua/t/138-balancer.t +++ b/debian/modules/nginx-lua/t/138-balancer.t @@ -58,8 +58,8 @@ qr{\[crit\] .*? connect\(\) to 0\.0\.0\.1:80 failed .*?, upstream: "http://0\.0\ } --- request GET /t ---- response_body_like: 500 Internal Server Error ---- error_code: 500 +--- response_body_like: 403 Forbidden +--- error_code: 403 --- error_log [lua] balancer_by_lua:2: hello from balancer by lua! while connecting to upstream, --- no_error_log eval @@ -431,3 +431,98 @@ qr{\[crit\] .*? connect\(\) to 0\.0\.0\.1:80 failed .*?, upstream: "http://0\.0\ ] --- no_error_log [warn] + + + +=== TEST 15: test if execeed proxy_next_upstream_limit +--- http_config + lua_package_path "../lua-resty-core/lib/?.lua;;"; + + proxy_next_upstream_tries 5; + upstream backend { + server 0.0.0.1; + balancer_by_lua_block { + local b = require "ngx.balancer" + + if not ngx.ctx.tries then + ngx.ctx.tries = 0 + end + + if ngx.ctx.tries >= 6 then + ngx.log(ngx.ERR, "retry count exceed limit") + ngx.exit(500) + end + + ngx.ctx.tries = ngx.ctx.tries + 1 + print("retry counter: ", ngx.ctx.tries) + + local ok, err = b.set_more_tries(2) + if not ok then + return error("failed to set more tries: ", err) + elseif err then + ngx.log(ngx.WARN, "set more tries: ", err) + end + + assert(b.set_current_peer("127.0.0.1", 81)) + } + } +--- config + location = /t { + proxy_pass http://backend/back; + } + + location = /back { + return 404; + } +--- request + GET /t +--- response_body_like: 502 Bad Gateway +--- error_code: 502 +--- grep_error_log eval: qr/\bretry counter: \w+/ +--- grep_error_log_out +retry counter: 1 +retry counter: 2 +retry counter: 3 +retry counter: 4 +retry counter: 5 + +--- error_log +set more tries: reduced tries due to limit + + + +=== TEST 16: set_more_tries bugfix +--- http_config + lua_package_path "../lua-resty-core/lib/?.lua;;"; + proxy_next_upstream_tries 0; + upstream backend { + server 0.0.0.1; + balancer_by_lua_block { + local balancer = require "ngx.balancer" + local ctx = ngx.ctx + if not ctx.has_run then + ctx.has_run = true + local _, err = balancer.set_more_tries(3) + if err then + ngx.log(ngx.ERR, "failed to set more tries: ", err) + end + end + balancer.set_current_peer("127.0.0.1", 81) + } + } +--- config + location = /t { + proxy_pass http://backend; + } +--- request + GET /t +--- error_code: 502 +--- grep_error_log eval: qr/http next upstream, \d+/ +--- grep_error_log_out +http next upstream, 2 +http next upstream, 2 +http next upstream, 2 +http next upstream, 2 +--- no_error_log +failed to set more tries: reduced tries due to limit +[alert] diff --git a/debian/modules/nginx-lua/t/139-ssl-cert-by.t b/debian/modules/nginx-lua/t/139-ssl-cert-by.t index b9fd60d..c13044f 100644 --- a/debian/modules/nginx-lua/t/139-ssl-cert-by.t +++ b/debian/modules/nginx-lua/t/139-ssl-cert-by.t @@ -11,7 +11,7 @@ my $openssl_version = eval { `$NginxBinary -V 2>&1` }; if ($openssl_version =~ m/built with OpenSSL (0|1\.0\.(?:0|1[^\d]|2[a-d]).*)/) { plan(skip_all => "too old OpenSSL, need 1.0.2e, was $1"); } else { - plan tests => repeat_each() * (blocks() * 6 + 10); + plan tests => repeat_each() * (blocks() * 6 + 6); } $ENV{TEST_NGINX_HTML_DIR} ||= html_dir(); @@ -1383,7 +1383,7 @@ uthread: done -=== TEST 17: simple logging - use ssl_certificiate_by_lua* on the http {} level +=== TEST 17: simple logging - use ssl_certificate_by_lua* on the http {} level GitHub openresty/lua-resty-core#42 --- http_config ssl_certificate_by_lua_block { print("ssl cert by lua is running!") } @@ -1574,3 +1574,295 @@ qr/\[error\] .*? send\(\) failed/, --- no_error_log [alert] ssl_certificate_by_lua:1: ssl cert by lua is running! + + + +=== TEST 19: check the count of running timers +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + + ssl_certificate_by_lua_block { print("ssl cert by lua is running!") } + ssl_certificate ../../cert/test.crt; + ssl_certificate_key ../../cert/test.key; + + server_tokens off; + location /timers { + default_type 'text/plain'; + content_by_lua_block { + ngx.timer.at(0.1, function() ngx.sleep(0.3) end) + ngx.timer.at(0.11, function() ngx.sleep(0.3) end) + ngx.timer.at(0.09, function() ngx.sleep(0.3) end) + ngx.sleep(0.2) + ngx.say(ngx.timer.running_count()) + } + more_clear_headers Date; + } + } +--- config + server_tokens off; + lua_ssl_trusted_certificate ../../cert/test.crt; + + location /t { + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(2000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(nil, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + local req = "GET /timers HTTP/1.0\r\nHost: test.com\r\nConnection: close\r\n\r\n" + local bytes, err = sock:send(req) + if not bytes then + ngx.say("failed to send http request: ", err) + return + end + + ngx.say("sent http request: ", bytes, " bytes.") + + while true do + local line, err = sock:receive() + if not line then + -- ngx.say("failed to receive response status line: ", err) + break + end + + ngx.say("received: ", line) + end + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: userdata +sent http request: 59 bytes. +received: HTTP/1.1 200 OK +received: Server: nginx +received: Content-Type: text/plain +received: Content-Length: 2 +received: Connection: close +received: +received: 3 +close: 1 nil + +--- error_log eval +[ +'ssl_certificate_by_lua:1: ssl cert by lua is running!', +'lua ssl server name: "test.com"', +] +--- no_error_log +[error] +[alert] + + + +=== TEST 20: some server {} block missing ssl_certificate_by_lua* handlers (literal server name) +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + + ssl_certificate_by_lua_block { print("ssl cert by lua is running!") } + ssl_certificate ../../cert/test.crt; + ssl_certificate_key ../../cert/test.key; + + server_tokens off; + location /timers { + default_type 'text/plain'; + content_by_lua_block { + ngx.timer.at(0.1, function() ngx.sleep(0.3) end) + ngx.timer.at(0.11, function() ngx.sleep(0.3) end) + ngx.timer.at(0.09, function() ngx.sleep(0.3) end) + ngx.sleep(0.2) + ngx.say(ngx.timer.running_count()) + } + more_clear_headers Date; + } + } + + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test2.com; + } +--- config + server_tokens off; + lua_ssl_trusted_certificate ../../cert/test.crt; + + location /t { + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(2000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(nil, "test2.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + local req = "GET /timers HTTP/1.0\r\nHost: test.com\r\nConnection: close\r\n\r\n" + local bytes, err = sock:send(req) + if not bytes then + ngx.say("failed to send http request: ", err) + return + end + + ngx.say("sent http request: ", bytes, " bytes.") + + while true do + local line, err = sock:receive() + if not line then + -- ngx.say("failed to receive response status line: ", err) + break + end + + ngx.say("received: ", line) + end + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +failed to do SSL handshake: handshake failed + +--- error_log eval +[ +qr/\[alert\] .*? no ssl_certificate_by_lua\* defined in server test2\.com\b/, +qr/\[crit\] .*? SSL_do_handshake\(\) failed\b/, +] + + + +=== TEST 21: some server {} block missing ssl_certificate_by_lua* handlers (regex server name) +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + + ssl_certificate_by_lua_block { print("ssl cert by lua is running!") } + ssl_certificate ../../cert/test.crt; + ssl_certificate_key ../../cert/test.key; + + server_tokens off; + location /timers { + default_type 'text/plain'; + content_by_lua_block { + ngx.timer.at(0.1, function() ngx.sleep(0.3) end) + ngx.timer.at(0.11, function() ngx.sleep(0.3) end) + ngx.timer.at(0.09, function() ngx.sleep(0.3) end) + ngx.sleep(0.2) + ngx.say(ngx.timer.running_count()) + } + more_clear_headers Date; + } + } + + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name ~test2\.com; + } +--- config + server_tokens off; + lua_ssl_trusted_certificate ../../cert/test.crt; + + location /t { + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(2000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(nil, "test2.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + + local req = "GET /timers HTTP/1.0\r\nHost: test.com\r\nConnection: close\r\n\r\n" + local bytes, err = sock:send(req) + if not bytes then + ngx.say("failed to send http request: ", err) + return + end + + ngx.say("sent http request: ", bytes, " bytes.") + + while true do + local line, err = sock:receive() + if not line then + -- ngx.say("failed to receive response status line: ", err) + break + end + + ngx.say("received: ", line) + end + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +failed to do SSL handshake: handshake failed + +--- error_log eval +[ +qr/\[alert\] .*? no ssl_certificate_by_lua\* defined in server ~test2\\\.com\b/, +qr/\[crit\] .*? SSL_do_handshake\(\) failed\b/, +] diff --git a/debian/modules/nginx-lua/t/140-ssl-c-api.t b/debian/modules/nginx-lua/t/140-ssl-c-api.t index 44ad93d..8734d14 100644 --- a/debian/modules/nginx-lua/t/140-ssl-c-api.t +++ b/debian/modules/nginx-lua/t/140-ssl-c-api.t @@ -561,7 +561,7 @@ failed to parse PEM priv key: PEM_read_bio_PrivateKey() failed f:close() local pkey = ffi.C.ngx_http_lua_ffi_parse_pem_priv_key(pkey_data, #pkey_data, errmsg) - if not pkey then + if pkey == nil then ngx.log(ngx.ERR, "failed to parse PEM priv key: ", ffi.string(errmsg[0])) return @@ -626,7 +626,7 @@ failed to parse PEM priv key: PEM_read_bio_PrivateKey() failed while true do local line, err = sock:receive() if not line then - -- ngx.say("failed to recieve response status line: ", err) + -- ngx.say("failed to receive response status line: ", err) break end @@ -711,7 +711,7 @@ lua ssl server name: "test.com" f:close() local pkey = ffi.C.ngx_http_lua_ffi_parse_pem_priv_key(pkey_data, #pkey_data, errmsg) - if not pkey then + if pkey == nil then ngx.log(ngx.ERR, "failed to parse PEM priv key: ", ffi.string(errmsg[0])) return @@ -776,7 +776,7 @@ lua ssl server name: "test.com" while true do local line, err = sock:receive() if not line then - -- ngx.say("failed to recieve response status line: ", err) + -- ngx.say("failed to receive response status line: ", err) break end diff --git a/debian/modules/nginx-lua/t/141-luajit.t b/debian/modules/nginx-lua/t/141-luajit.t index be03fe3..36418d1 100644 --- a/debian/modules/nginx-lua/t/141-luajit.t +++ b/debian/modules/nginx-lua/t/141-luajit.t @@ -1,6 +1,7 @@ # vim:set ft= ts=4 sw=4 et fdm=marker: -use Test::Nginx::Socket::Lua; +use Test::Nginx::Socket::Lua + skip_all => 'no mmap(sbrk(0)) trick since glibc leaks memory in this case'; #worker_connections(1014); #master_on(); diff --git a/debian/modules/nginx-lua/t/142-ssl-session-store.t b/debian/modules/nginx-lua/t/142-ssl-session-store.t index 5c9fad3..73b6e19 100644 --- a/debian/modules/nginx-lua/t/142-ssl-session-store.t +++ b/debian/modules/nginx-lua/t/142-ssl-session-store.t @@ -38,7 +38,7 @@ __DATA__ } --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; location /t { @@ -108,7 +108,7 @@ ssl_session_store_by_lua_block:1: ssl session store by lua is running! } --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; location /t { @@ -183,7 +183,7 @@ API disabled in the context of ssl_session_store_by_lua* } --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; location /t { @@ -275,7 +275,7 @@ my timer run! } --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; location /t { @@ -343,7 +343,7 @@ API disabled in the context of ssl_session_store_by_lua* } --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; lua_ssl_verify_depth 3; @@ -415,7 +415,7 @@ ngx.exit does not yield and the error code is eaten. } --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; lua_ssl_verify_depth 3; @@ -488,7 +488,7 @@ ssl_session_store_by_lua*: handler return value: 0, sess new cb exit code: 0 } --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; lua_ssl_verify_depth 3; @@ -556,7 +556,7 @@ should never reached here } --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; lua_ssl_verify_depth 3; @@ -627,7 +627,7 @@ get_phase: ssl_session_store } --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; location /t { @@ -696,7 +696,7 @@ qr/elapsed in ssl cert by lua: 0.(?:09|1[01])\d+,/, } --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; location /t { @@ -778,7 +778,7 @@ a.lua:1: ssl store session by lua is running! } --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; lua_ssl_verify_depth 3; @@ -849,7 +849,7 @@ qr/\[emerg\] .*? "ssl_session_store_by_lua_block" directive is not allowed here } --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; location /t { diff --git a/debian/modules/nginx-lua/t/143-ssl-session-fetch.t b/debian/modules/nginx-lua/t/143-ssl-session-fetch.t index bd800ff..701ead7 100644 --- a/debian/modules/nginx-lua/t/143-ssl-session-fetch.t +++ b/debian/modules/nginx-lua/t/143-ssl-session-fetch.t @@ -39,7 +39,7 @@ __DATA__ } --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; location /t { @@ -120,7 +120,7 @@ qr/ssl_session_fetch_by_lua_block:1: ssl fetch sess by lua is running!/s } --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; location /t { @@ -204,7 +204,7 @@ qr/elapsed in ssl fetch session by lua: 0.(?:09|1[01])\d+,/, } --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; location /t { @@ -305,7 +305,7 @@ qr/my timer run!/s } --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; location /t { @@ -385,7 +385,7 @@ qr/received memc reply: OK/s } --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; lua_ssl_verify_depth 3; @@ -466,7 +466,7 @@ should never reached here } --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; lua_ssl_verify_depth 3; @@ -548,7 +548,7 @@ should never reached here } --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; lua_ssl_verify_depth 3; @@ -629,7 +629,7 @@ should never reached here } --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; lua_ssl_verify_depth 3; @@ -712,7 +712,7 @@ should never reached here } --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; lua_ssl_verify_depth 3; @@ -793,7 +793,7 @@ should never reached here } --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; location /t { @@ -879,7 +879,7 @@ qr/get_phase: ssl_session_fetch/s --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; location /t { @@ -1049,7 +1049,7 @@ qr/\S+:\d+: ssl fetch sess by lua is running!/s } --- config server_tokens off; - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; lua_ssl_trusted_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; location /t { diff --git a/debian/modules/nginx-lua/t/146-malloc-trim.t b/debian/modules/nginx-lua/t/146-malloc-trim.t index 45fb9f2..fc425ce 100644 --- a/debian/modules/nginx-lua/t/146-malloc-trim.t +++ b/debian/modules/nginx-lua/t/146-malloc-trim.t @@ -43,8 +43,9 @@ ok ok ok --- grep_error_log eval: qr/malloc_trim\(\d+\) returned \d+/ ---- grep_error_log_out -malloc_trim(1) returned 0 +--- grep_error_log_out eval +qr/\Amalloc_trim\(1\) returned [01] +\z/ --- wait: 0.2 --- no_error_log [error] @@ -76,13 +77,14 @@ ok ok ok --- grep_error_log eval: qr/malloc_trim\(\d+\) returned \d+/ ---- grep_error_log_out -malloc_trim(1) returned 0 -malloc_trim(1) returned 0 -malloc_trim(1) returned 0 -malloc_trim(1) returned 0 -malloc_trim(1) returned 0 -malloc_trim(1) returned 0 +--- grep_error_log_out eval +qr/\Amalloc_trim\(1\) returned [01] +malloc_trim\(1\) returned [01] +malloc_trim\(1\) returned [01] +malloc_trim\(1\) returned [01] +malloc_trim\(1\) returned [01] +malloc_trim\(1\) returned [01] +\z/ --- wait: 0.2 --- no_error_log [error] @@ -114,10 +116,11 @@ ok ok ok --- grep_error_log eval: qr/malloc_trim\(\d+\) returned \d+/ ---- grep_error_log_out -malloc_trim(1) returned 0 -malloc_trim(1) returned 0 -malloc_trim(1) returned 0 +--- grep_error_log_out eval +qr/\Amalloc_trim\(1\) returned [01] +malloc_trim\(1\) returned [01] +malloc_trim\(1\) returned [01] +\z/ --- wait: 0.2 --- no_error_log [error] @@ -149,9 +152,10 @@ ok ok ok --- grep_error_log eval: qr/malloc_trim\(\d+\) returned \d+/ ---- grep_error_log_out -malloc_trim(1) returned 0 -malloc_trim(1) returned 0 +--- grep_error_log_out eval +qr/\Amalloc_trim\(1\) returned [01] +malloc_trim\(1\) returned [01] +\z/ --- wait: 0.2 --- no_error_log [error] @@ -330,8 +334,9 @@ ok ok ok --- grep_error_log eval: qr/malloc_trim\(\d+\) returned \d+/ ---- grep_error_log_out -malloc_trim(1) returned 0 +--- grep_error_log_out eval +qr/\Amalloc_trim\(1\) returned [01] +\z/ --- wait: 0.2 --- no_error_log [error] diff --git a/debian/modules/nginx-lua/t/147-tcp-socket-timeouts.t b/debian/modules/nginx-lua/t/147-tcp-socket-timeouts.t index 52f015a..0689a9b 100644 --- a/debian/modules/nginx-lua/t/147-tcp-socket-timeouts.t +++ b/debian/modules/nginx-lua/t/147-tcp-socket-timeouts.t @@ -315,7 +315,7 @@ lua tcp socket write timed out === TEST 5: connection timeout (tcp) --- config - resolver $TEST_NGINX_RESOLVER; + resolver $TEST_NGINX_RESOLVER ipv6=off; resolver_timeout 3s; location /test { content_by_lua_block { diff --git a/debian/modules/nginx-lua/t/150-fake-delayed-load.t b/debian/modules/nginx-lua/t/150-fake-delayed-load.t new file mode 100644 index 0000000..232bbf3 --- /dev/null +++ b/debian/modules/nginx-lua/t/150-fake-delayed-load.t @@ -0,0 +1,56 @@ +# vim:set ft= ts=4 sw=4 et fdm=marker: +use lib 'lib'; +use Test::Nginx::Socket::Lua; + +#worker_connections(1014); +#master_process_enabled(1); +#log_level('warn'); + +#repeat_each(2); + +plan tests => repeat_each() * (blocks() * 3); + +#no_diff(); +no_long_string(); +#master_on(); +#workers(2); + +run_tests(); + +__DATA__ + +=== TEST 1: lua code cache on +--- http_config + lua_code_cache on; +--- config + location = /cache_on { + content_by_lua_block { + local delayed_load = require("ngx.delayed_load") + ngx.say(type(delayed_load.get_function)) + } + } +--- request +GET /cache_on +--- response_body +function +--- no_error_log +[error] + + + +=== TEST 2: lua code cache off +--- http_config + lua_code_cache off; +--- config + location = /cache_off { + content_by_lua_block { + local delayed_load = require("ngx.delayed_load") + ngx.say(type(delayed_load.get_function)) + } + } +--- request +GET /cache_off +--- response_body +function +--- no_error_log +[error] diff --git a/debian/modules/nginx-lua/t/151-initby-hup.t b/debian/modules/nginx-lua/t/151-initby-hup.t new file mode 100644 index 0000000..f278867 --- /dev/null +++ b/debian/modules/nginx-lua/t/151-initby-hup.t @@ -0,0 +1,168 @@ +# vim:set ft= ts=4 sw=4 et fdm=marker: + +our $SkipReason; + +BEGIN { + if ($ENV{TEST_NGINX_CHECK_LEAK}) { + $SkipReason = "unavailable for the hup tests"; + + } else { + $ENV{TEST_NGINX_USE_HUP} = 1; + undef $ENV{TEST_NGINX_USE_STAP}; + } +} + +use Test::Nginx::Socket::Lua 'no_plan'; + +#worker_connections(1014); +#master_on(); +#workers(2); +#log_level('warn'); + +repeat_each(1); + +#plan tests => repeat_each() * (blocks() * 3 + 3); + +#no_diff(); +#no_long_string(); +no_shuffle(); + +run_tests(); + +__DATA__ + +=== TEST 1: no error in init before HUP +--- http_config + init_by_lua_block { + foo = "hello, FOO" + } +--- config + location /lua { + content_by_lua_block { + ngx.say(foo) + } + } +--- request +GET /lua +--- response_body +hello, FOO +--- no_error_log +[error] + + + +=== TEST 2: error in init after HUP (master still alive, worker process still the same as before) +--- http_config + init_by_lua_block { + error("failed to init") + } +--- config + location /lua { + content_by_lua_block { + ngx.say(foo) + } + } +--- request +GET /lua +--- response_body +hello, FOO +--- error_log +failed to init +--- reload_fails + + + +=== TEST 3: no error in init again +--- http_config + init_by_lua_block { + foo = "hello, foo" + } +--- config + location /lua { + content_by_lua_block { + ngx.say(foo) + } + } +--- request +GET /lua +--- response_body +hello, foo +--- no_error_log +[error] + + + +=== TEST 4: no error in init before HUP, used ngx.shared.DICT +--- http_config + lua_shared_dict dogs 1m; + + init_by_lua_block { + local dogs = ngx.shared.dogs + dogs:set("foo", "hello, FOO") + } +--- config + location /lua { + content_by_lua_block { + local dogs = ngx.shared.dogs + local foo = dogs:get("foo") + ngx.say(foo) + } + } +--- request +GET /lua +--- response_body +hello, FOO +--- no_error_log +[error] + + + +=== TEST 5: error in init after HUP, not reloaded but foo have changed. +--- http_config + lua_shared_dict dogs 1m; + + init_by_lua_block { + local dogs = ngx.shared.dogs + dogs:set("foo", "foo have changed") + + error("failed to init") + } +--- config + location /lua { + content_by_lua_block { + ngx.say("HUP reload failed") + } + } +--- request +GET /lua +--- response_body +foo have changed +--- error_log +failed to init +--- reload_fails + + + +=== TEST 6: no error in init again, reload success and foo still have changed. +--- http_config + lua_shared_dict dogs 1m; + + init_by_lua_block { + -- do nothing + } +--- config + location /lua { + content_by_lua_block { + local dogs = ngx.shared.dogs + local foo = dogs:get("foo") + ngx.say(foo) + ngx.say("reload success") + } + } +--- request +GET /lua +--- response_body +foo have changed +reload success +--- no_error_log +[error] diff --git a/debian/modules/nginx-lua/t/152-timer-every.t b/debian/modules/nginx-lua/t/152-timer-every.t new file mode 100644 index 0000000..c8d62e7 --- /dev/null +++ b/debian/modules/nginx-lua/t/152-timer-every.t @@ -0,0 +1,385 @@ +# vim:set ft= ts=4 sw=4 et fdm=marker: +use Test::Nginx::Socket::Lua; + +#worker_connections(1014); +#master_on(); +#workers(2); +#log_level('warn'); + +repeat_each(2); + +plan tests => repeat_each() * (blocks() * 7 + 2); + +#no_diff(); +no_long_string(); + +our $HtmlDir = html_dir; + +$ENV{TEST_NGINX_MEMCACHED_PORT} ||= 11211; +$ENV{TEST_NGINX_HTML_DIR} = $HtmlDir; + +worker_connections(1024); +run_tests(); + +__DATA__ + +=== TEST 1: simple very +--- config + location /t { + content_by_lua_block { + local begin = ngx.now() + local function f(premature) + print("elapsed: ", ngx.now() - begin) + print("timer prematurely expired: ", premature) + end + + local ok, err = ngx.timer.every(0.05, f) + if not ok then + ngx.say("failed to set timer: ", err) + return + end + + ngx.say("registered timer") + } + } +--- request +GET /t +--- response_body +registered timer +--- wait: 0.11 +--- no_error_log +[error] +[alert] +[crit] +timer prematurely expired: true +--- error_log eval +[ +qr/\[lua\] content_by_lua\(nginx\.conf:\d+\):\d+: elapsed: 0\.0(?:4[4-9]|5[0-6])\d*, context: ngx\.timer, client: \d+\.\d+\.\d+\.\d+, server: 0\.0\.0\.0:\d+/, +qr/\[lua\] content_by_lua\(nginx\.conf:\d+\):\d+: elapsed: 0\.(?:09|10)\d*, context: ngx\.timer, client: \d+\.\d+\.\d+\.\d+, server: 0\.0\.0\.0:\d+/, +"lua ngx.timer expired", +"http lua close fake http connection", +"timer prematurely expired: false", +] + + + +=== TEST 2: separated global env +--- config + location /t { + content_by_lua_block { + local begin = ngx.now() + local function f() + foo = 3 + print("foo in timer: ", foo) + end + local ok, err = ngx.timer.every(0.05, f) + if not ok then + ngx.say("failed to set timer: ", err) + return + end + ngx.sleep(0.11) + ngx.say("foo = ", foo) + } + } +--- request +GET /t +--- response_body +foo = nil +--- wait: 0.12 +--- no_error_log +[error] +[alert] +[crit] +--- error_log eval +[ +qr/\[lua\] content_by_lua\(nginx\.conf:\d+\):\d+: foo in timer: 3/, +"lua ngx.timer expired", +"http lua close fake http connection" +] + + + +=== TEST 3: lua variable sharing via upvalue +--- config + location /t { + content_by_lua_block { + local begin = ngx.now() + local foo = 0 + local function f() + foo = foo + 3 + print("foo in timer: ", foo) + end + local ok, err = ngx.timer.every(0.05, f) + if not ok then + ngx.say("failed to set timer: ", err) + return + end + ngx.say("registered timer") + ngx.sleep(0.11) + ngx.say("foo = ", foo) + } + } +--- request +GET /t +--- response_body +registered timer +foo = 6 +--- wait: 0.12 +--- no_error_log +[error] +[alert] +[crit] +--- error_log eval +[ +qr/\[lua\] content_by_lua\(nginx\.conf:\d+\):\d+: foo in timer: 3/, +qr/\[lua\] content_by_lua\(nginx\.conf:\d+\):\d+: foo in timer: 6/, +"lua ngx.timer expired", +"http lua close fake http connection" +] + + + +=== TEST 4: create the next timer immediately when timer start running +--- config + location /t { + content_by_lua_block { + local begin = ngx.now() + local foo = 0 + local function f() + foo = foo + 3 + print("foo in timer: ", foo) + + ngx.sleep(0.1) + end + local ok, err = ngx.timer.every(0.05, f) + if not ok then + ngx.say("failed to set timer: ", err) + return + end + ngx.say("registered timer") + ngx.sleep(0.11) + ngx.say("foo = ", foo) + } + } +--- request +GET /t +--- response_body +registered timer +foo = 6 +--- wait: 0.12 +--- no_error_log +[error] +[alert] +[crit] +--- error_log eval +[ +qr/\[lua\] content_by_lua\(nginx\.conf:\d+\):\d+: foo in timer: 3/, +qr/\[lua\] content_by_lua\(nginx\.conf:\d+\):\d+: foo in timer: 6/, +"lua ngx.timer expired", +"http lua close fake http connection" +] + + + +=== TEST 5: callback args +--- config + location /t { + content_by_lua_block { + local n = 0 + + local function f(premature, a, b, c) + n = n + 1 + print("the ", n, " time, args: ", a, ", ", b, ", ", c) + + a, b, c = 0, 0, 0 + end + + local ok, err = ngx.timer.every(0.05, f, 1, 2) + if not ok then + ngx.say("failed to set timer: ", err) + return + end + + ngx.say("registered timer") + ngx.sleep(0.11) + } + } +--- request +GET /t +--- response_body +registered timer +--- wait: 0.12 +--- no_error_log +[error] +[alert] +[crit] +--- error_log eval +[ +"the 1 time, args: 1, 2, nil", +"the 2 time, args: 1, 2, nil", +"lua ngx.timer expired", +"http lua close fake http connection" +] + + + +=== TEST 6: memory leak check +--- config + location /t { + content_by_lua_block { + local function f() + local a = 1 + -- do nothing + end + + for i = 1, 100 do + local ok, err = ngx.timer.every(0.1, f) + if not ok then + ngx.say("failed to set timer: ", err) + return + end + end + + ngx.say("registered timer") + + collectgarbage("collect") + local start = collectgarbage("count") + + ngx.sleep(0.21) + + collectgarbage("collect") + local growth1 = collectgarbage("count") - start + + ngx.sleep(0.51) + + collectgarbage("collect") + local growth2 = collectgarbage("count") - start + + ngx.say("growth1 == growth2: ", growth1 == growth2) + } + } +--- request +GET /t +--- response_body +registered timer +growth1 == growth2: true +--- no_error_log +[error] +[alert] +[crit] +--- timeout: 8 + + + +=== TEST 7: respect lua_max_pending_timers +--- http_config + lua_max_pending_timers 10; +--- config + location /t { + content_by_lua_block { + local function f() + local a = 1 + -- do nothing + end + + for i = 1, 11 do + local ok, err = ngx.timer.every(0.1, f) + if not ok then + ngx.say("failed to set timer: ", err) + return + end + end + + ngx.say("registered 10 timers") + } + } +--- request +GET /t +--- response_body +failed to set timer: too many pending timers +--- no_error_log +[error] +[alert] +[crit] + + + +=== TEST 8: respect lua_max_running_timers +--- http_config + lua_max_pending_timers 100; + lua_max_running_timers 9; +--- config + location /t { + content_by_lua_block { + local function f() + local a = 1 + ngx.sleep(0.02) + -- do nothing + end + + for i = 1, 10 do + local ok, err = ngx.timer.every(0.01, f) + if not ok then + ngx.say("failed to set timer: ", err) + return + end + end + + ngx.say("registered 10 timers") + + ngx.sleep(0.03) + } + } +--- request +GET /t +--- response_body +registered 10 timers +--- no_error_log +[error] +[crit] +--- error_log +lua_max_running_timers are not enough + + + +=== TEST 9: lua_code_cache off +FIXME: it is know that this test case leaks memory. +so we skip it in the "check leak" testing mode. +--- http_config + lua_code_cache off; +--- config + location /t { + content_by_lua_block { + local function f() + local a = 1 + -- do nothing + end + + local ok, err = ngx.timer.every(0.01, f) + if not ok then + ngx.say("failed to set timer: ", err) + return + end + + collectgarbage("collect") + ngx.say("registered timer") + + ngx.sleep(0.03) + + collectgarbage("collect") + + ngx.sleep(0.03) + + collectgarbage("collect") + ngx.say("ok") + } + } +--- request +GET /t +--- response_body +registered timer +ok +--- no_error_log +[error] +[crit] +--- no_check_leak diff --git a/debian/modules/nginx-lua/t/153-semaphore-hup.t b/debian/modules/nginx-lua/t/153-semaphore-hup.t new file mode 100644 index 0000000..c85a21d --- /dev/null +++ b/debian/modules/nginx-lua/t/153-semaphore-hup.t @@ -0,0 +1,154 @@ +# vim:set ft= ts=4 sw=4 et fdm=marker: +use lib 'lib'; +use Test::Nginx::Socket::Lua; + +#worker_connections(10140); +#workers(1); +log_level('warn'); +master_process_enabled(1); +repeat_each(1); + +plan tests => repeat_each() * (blocks() * 3); + +no_long_string(); +#no_diff(); + +add_block_preprocessor(sub { + my $block = shift; + + my $http_config = $block->http_config || ''; + $http_config .= <<'_EOC_'; + lua_package_path "../lua-resty-core/lib/?.lua;../lua-resty-lrucache/lib/?.lua;;"; + lua_shared_dict shdict 4m; + + init_by_lua_block { + require "resty.core" + local process = require "ngx.process" + local ok, err = process.enable_privileged_agent() + if not ok then + ngx.log(ngx.ERR, "failed to enable_privileged_agent: ", err) + end + } + + init_worker_by_lua_block { + local function test(pre) + if pre then + return + end + + local semaphore = require "ngx.semaphore" + local sem = semaphore.new() + + ngx.log(ngx.ERR, "created semaphore object") + + local function sem_wait() + + local ok, err = sem:wait(100) + if not ok then + ngx.log(ngx.ERR, "err: ", err) + else + ngx.log(ngx.ERR, "wait success") + end + end + + while not ngx.worker.exiting() do + local co = ngx.thread.spawn(sem_wait) + ngx.thread.wait(co) + end + end + + local ok, err = ngx.timer.at(0, test) + if not ok then + ngx.log(ngx.ERR, "failed to create semaphore timer err: ", err) + end + + local function reload(pre) + if pre then + return + end + + shdict = ngx.shared.shdict + local success = shdict:add("reloaded", 1) + if not success then + return + end + + ngx.log(ngx.ERR, "try to reload nginx") + + local f, err = io.open(ngx.config.prefix() .. "/logs/nginx.pid", "r") + if not f then + ngx.say("failed to open nginx.pid: ", err) + return + end + + local pid = f:read() + + f:close() + os.execute("kill -HUP " .. pid) + end + + local typ = require "ngx.process".type + if typ() == "privileged agent" then + local ok, err = ngx.timer.at(0.1, reload) + if not ok then + ngx.log(ngx.ERR, "failed to create semaphore timer err: ", err) + end + end + } +_EOC_ + $block->set_value("http_config", $http_config); +}); + +run_tests(); + +__DATA__ + +=== TEST 1: timer + reload +--- config + location /test { + content_by_lua_block { + ngx.sleep(1) + ngx.say("hello") + } + } +--- request +GET /test +--- response_body +hello +--- grep_error_log eval: qr/created semaphore object|try to reload nginx|semaphore gc wait queue is not empty/ +--- grep_error_log_out +created semaphore object +created semaphore object +try to reload nginx +created semaphore object +created semaphore object +--- skip_nginx: 3: < 1.11.2 +--- no_check_leak +--- wait: 0.2 + + + +=== TEST 2: timer + reload (lua code cache off) +--- http_config + lua_code_cache off; +--- config + location /test { + content_by_lua_block { + ngx.sleep(1) + ngx.say("hello") + } + } +--- request +GET /test +--- response_body +hello +--- grep_error_log eval: qr/created semaphore object|try to reload nginx|semaphore gc wait queue is not empty/ +--- grep_error_log_out +created semaphore object +created semaphore object +try to reload nginx +created semaphore object +created semaphore object +--- skip_nginx: 3: < 1.11.2 +--- no_check_leak +--- wait: 0.2 diff --git a/debian/modules/nginx-lua/t/154-semaphore.t b/debian/modules/nginx-lua/t/154-semaphore.t new file mode 100644 index 0000000..3c1f004 --- /dev/null +++ b/debian/modules/nginx-lua/t/154-semaphore.t @@ -0,0 +1,118 @@ +# vim:set ft= ts=4 sw=4 et fdm=marker: +use lib 'lib'; +use Test::Nginx::Socket::Lua; + +#worker_connections(10140); +#workers(1); +#log_level('warn'); + +repeat_each(2); + +plan tests => repeat_each() * (blocks() * 3) + blocks(); + +no_long_string(); +#no_diff(); + +add_block_preprocessor(sub { + my $block = shift; + + my $http_config = $block->http_config || ''; + $http_config .= <<'_EOC_'; + lua_package_path "../lua-resty-core/lib/?.lua;../lua-resty-lrucache/lib/?.lua;;"; + + init_by_lua_block { + require "resty.core" + } +_EOC_ + $block->set_value("http_config", $http_config); +}); + +run_tests(); + +__DATA__ + +=== TEST 1: timer + shutdown error log +--- config + location /test { + content_by_lua_block { + local function test(pre) + + local semaphore = require "ngx.semaphore" + local sem = semaphore.new() + + local function sem_wait() + + local ok, err = sem:wait(10) + if not ok then + ngx.log(ngx.ERR, "err: ", err) + else + ngx.log(ngx.ERR, "wait success") + end + end + + while not ngx.worker.exiting() do + local co = ngx.thread.spawn(sem_wait) + ngx.thread.wait(co) + end + end + + local ok, err = ngx.timer.at(0, test) + ngx.log(ngx.ERR, "hello, world") + ngx.say("time: ", ok) + } + } +--- request +GET /test +--- response_body +time: 1 +--- grep_error_log eval: qr/hello, world|semaphore gc wait queue is not empty/ +--- grep_error_log_out +hello, world +--- shutdown_error_log +--- no_shutdown_error_log +semaphore gc wait queue is not empty + + + +=== TEST 2: timer + shutdown error log (lua code cache off) +--- http_config + lua_code_cache off; +--- config + location /test { + content_by_lua_block { + local function test(pre) + + local semaphore = require "ngx.semaphore" + local sem = semaphore.new() + + local function sem_wait() + + local ok, err = sem:wait(10) + if not ok then + ngx.log(ngx.ERR, "err: ", err) + else + ngx.log(ngx.ERR, "wait success") + end + end + + while not ngx.worker.exiting() do + local co = ngx.thread.spawn(sem_wait) + ngx.thread.wait(co) + end + end + + local ok, err = ngx.timer.at(0, test) + ngx.log(ngx.ERR, "hello, world") + ngx.say("time: ", ok) + } + } +--- request +GET /test +--- response_body +time: 1 +--- grep_error_log eval: qr/hello, world|semaphore gc wait queue is not empty/ +--- grep_error_log_out +hello, world +--- shutdown_error_log +--- no_shutdown_error_log +semaphore gc wait queue is not empty diff --git a/debian/modules/nginx-lua/t/cert/comodo-ca.crt b/debian/modules/nginx-lua/t/cert/comodo-ca.crt new file mode 100644 index 0000000..444461b --- /dev/null +++ b/debian/modules/nginx-lua/t/cert/comodo-ca.crt @@ -0,0 +1,29 @@ +-----BEGIN CERTIFICATE----- +MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCBhTELMAkGA1UE +BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG +A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkwHhcNMTAwMTE5MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMC +R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE +ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR6FSS0gpWsawNJN3Fz0Rn +dJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8Xpz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZ +FGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+ +5eNu/Nio5JIk2kNrYrhV/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pG +x8cgoLEfZd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z+pUX +2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7wqP/0uK3pN/u6uPQL +OvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZahSL0896+1DSJMwBGB7FY79tOi4lu3 +sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVICu9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+C +GCe01a60y1Dma/RMhnEw6abfFobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5 +WdYgGq/yapiqcrxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E +FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w +DQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvlwFTPoCWOAvn9sKIN9SCYPBMt +rFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+ +nq6PK7o9mfjYcwlYRm6mnPTXJ9OV2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSg +tZx8jb8uk2IntznaFxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwW +sRqZCuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiKboHGhfKp +pC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmckejkk9u+UJueBPSZI9FoJA +zMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yLS0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHq +ZJx64SIDqZxubw5lT2yHh17zbqD5daWbQOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk52 +7RH89elWsn2/x20Kk4yl0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7I +LaZRfyHBNVOFBkpdn627G190 +-----END CERTIFICATE----- diff --git a/debian/modules/nginx-lua/t/cert/startcom.crt b/debian/modules/nginx-lua/t/cert/startcom.crt deleted file mode 100644 index a5185ca..0000000 --- a/debian/modules/nginx-lua/t/cert/startcom.crt +++ /dev/null @@ -1,87 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEW -MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg -Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM3WhcNMzYwOTE3MTk0NjM2WjB9 -MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi -U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh -cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA -A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk -pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf -OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C -Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT -Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi -HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM -Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w -+2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+ -Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3 -Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B -26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID -AQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD -VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFul -F2mHMMo0aEPQQa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCC -ATgwLgYIKwYBBQUHAgEWImh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5w -ZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL2ludGVybWVk -aWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENvbW1lcmNpYWwgKFN0 -YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0aGUg -c2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0 -aWZpY2F0aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93 -d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgG -CWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1 -dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5fPGFf59Jb2vKXfuM/gTF -wWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWmN3PH/UvS -Ta0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst -0OcNOrg+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNc -pRJvkrKTlMeIFw6Ttn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKl -CcWw0bdT82AUuoVpaiF8H3VhFyAXe2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVF -P0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA2MFrLH9ZXF2RsXAiV+uKa0hK -1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBsHvUwyKMQ5bLm -KhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE -JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ -8dCAWZvLMdibD4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnm -fyWl8kgAwKQB2j8= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW -MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg -Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM2WhcNMzYwOTE3MTk0NjM2WjB9 -MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi -U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh -cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA -A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk -pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf -OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C -Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT -Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi -HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM -Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w -+2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+ -Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3 -Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B -26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID -AQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE -FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9j -ZXJ0LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3Js -LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFM -BgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUHAgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0 -Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRwOi8vY2VydC5zdGFy -dGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYgU3Rh -cnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlh -YmlsaXR5LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2Yg -dGhlIFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFp -bGFibGUgYXQgaHR0cDovL2NlcnQuc3RhcnRjb20ub3JnL3BvbGljeS5wZGYwEQYJ -YIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNT -TCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOCAgEAFmyZ -9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8 -jhvh3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUW -FjgKXlf2Ysd6AgXmvB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJz -ewT4F+irsfMuXGRuczE6Eri8sxHkfY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1 -ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3fsNrarnDy0RLrHiQi+fHLB5L -EUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZEoalHmdkrQYu -L6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq -yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuC -O3NJo2pXh5Tl1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6V -um0ABj6y6koQOdjQK/W/7HW/lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkySh -NOsF/5oirpt9P/FlUQqmMGqz9IgcgA38corog14= ------END CERTIFICATE----- diff --git a/debian/modules/nginx-lua/t/data/fake-delayed-load-module/config b/debian/modules/nginx-lua/t/data/fake-delayed-load-module/config new file mode 100644 index 0000000..a5fa6fb --- /dev/null +++ b/debian/modules/nginx-lua/t/data/fake-delayed-load-module/config @@ -0,0 +1,3 @@ +ngx_addon_name="ngx_http_lua_fake_delayed_load_module" +HTTP_AUX_FILTER_MODULES="$HTTP_AUX_FILTER_MODULES ngx_http_lua_fake_delayed_load_module" +NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_lua_fake_delayed_load_module.c" diff --git a/debian/modules/nginx-lua/t/data/fake-delayed-load-module/ngx_http_lua_fake_delayed_load_module.c b/debian/modules/nginx-lua/t/data/fake-delayed-load-module/ngx_http_lua_fake_delayed_load_module.c new file mode 100644 index 0000000..2898255 --- /dev/null +++ b/debian/modules/nginx-lua/t/data/fake-delayed-load-module/ngx_http_lua_fake_delayed_load_module.c @@ -0,0 +1,77 @@ +/* + * This fake_delayed_load delayed load module was used to reproduce + * a bug in ngx_lua's function ngx_http_lua_add_package_preload. + */ + + +#include +#include +#include +#include + + +#include "ngx_http_lua_api.h" + + +static ngx_int_t ngx_http_lua_fake_delayed_load_init(ngx_conf_t *cf); +static int ngx_http_lua_fake_delayed_load_preload(lua_State *L); +static int ngx_http_lua_fake_delayed_load_function(lua_State * L); + + +static ngx_http_module_t ngx_http_lua_fake_delayed_load_module_ctx = { + NULL, /* preconfiguration */ + ngx_http_lua_fake_delayed_load_init, /* postconfiguration */ + + NULL, /* create main configuration */ + NULL, /* init main configuration */ + + NULL, /* create server configuration */ + NULL, /* merge server configuration */ + + NULL, /* create location configuration */ + NULL, /* merge location configuration */ +}; + +/* flow identify module struct */ +ngx_module_t ngx_http_lua_fake_delayed_load_module = { + NGX_MODULE_V1, + &ngx_http_lua_fake_delayed_load_module_ctx, /* module context */ + NULL, /* 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_lua_fake_delayed_load_init(ngx_conf_t *cf) +{ + ngx_http_lua_add_package_preload(cf, "ngx.delayed_load", + ngx_http_lua_fake_delayed_load_preload); + return NGX_OK; +} + + +static int +ngx_http_lua_fake_delayed_load_preload(lua_State *L) +{ + lua_createtable(L, 0, 1); + + lua_pushcfunction(L, ngx_http_lua_fake_delayed_load_function); + lua_setfield(L, -2, "get_function"); + + return 1; +} + + +static int +ngx_http_lua_fake_delayed_load_function(lua_State * L) +{ + return 0; +} diff --git a/debian/modules/nginx-lua/t/data/fake-module/ngx_http_fake_module.c b/debian/modules/nginx-lua/t/data/fake-module/ngx_http_fake_module.c index 42cde55..650f4f7 100644 --- a/debian/modules/nginx-lua/t/data/fake-module/ngx_http_fake_module.c +++ b/debian/modules/nginx-lua/t/data/fake-module/ngx_http_fake_module.c @@ -1,5 +1,4 @@ -/* Copyright (C) ZHANG Heng (chiyouhen) - * +/* * This fake module was used to reproduce a bug in ngx_lua's * init_worker_by_lua implementation. */ diff --git a/debian/modules/nginx-lua/util/build.sh b/debian/modules/nginx-lua/util/build.sh index 7887fe9..e45c00a 100755 --- a/debian/modules/nginx-lua/util/build.sh +++ b/debian/modules/nginx-lua/util/build.sh @@ -52,6 +52,7 @@ time ngx-build $force $version \ --add-module=$root/../redis2-nginx-module \ --add-module=$root/t/data/fake-module \ --add-module=$root/t/data/fake-shm-module \ + --add-module=$root/t/data/fake-delayed-load-module \ --with-http_gunzip_module \ --with-http_dav_module \ --with-select_module \ diff --git a/debian/modules/nginx-lua/util/gdbinit b/debian/modules/nginx-lua/util/gdbinit deleted file mode 100644 index 1508c64..0000000 --- a/debian/modules/nginx-lua/util/gdbinit +++ /dev/null @@ -1,415 +0,0 @@ -# This gdb script provides several useful routines for debugging ngx_lua or -# standalone Lua/LuaJIT. -# -# You need gdb >= v7.3 to make this script working correctly. -# -# Installation: place it at $HOME/.gdbinit -# -# -- chaoslawful gmail com - -#### Lua type defines #### - -set $__LUA_TNONE = -1 -set $__LUA_TNIL = 0 -set $__LUA_TBOOLEAN = 1 -set $__LUA_TLIGHTUSERDATA = 2 -set $__LUA_TNUMBER = 3 -set $__LUA_TSTRING = 4 -set $__LUA_TTABLE = 5 -set $__LUA_TFUNCTION = 6 -set $__LUA_TUSERDATA = 7 -set $__LUA_TTHREAD = 8 - -#### Lua constants #### - -set $__LUA_GLOBALSINDEX = -10002 -set $__LUA_ENVIRONINDEX = -10001 -set $__LUA_REGISTRYINDEX = -10000 - -#### Auxiliary methods #### - -define __lua_debug_instance - if !$__lua_debug_instance - set $__lua_debug_instance = (lua_Debug*)malloc(sizeof(lua_Debug)) - end -end - -define __free_lua_debug_instance - if $__lua_debug_instance - set $rc = free($__lua_debug_instance) - set $__lua_debug_instance = 0 - end -end - -set $__BUCKET_SIZE = 16 -define __set_instance - if !$__set_instance - set $__set_instance = (void*(*(*))[2])malloc($__BUCKET_SIZE*sizeof(void*(*)[2])) - set $rc = memset($__set_instance, 0, $__BUCKET_SIZE*sizeof(void*(*)[2])) - end -end - -define __free_set_instance - if $__set_instance - __set_clean - set $rc = free($__set_instance) - set $__set_instance = 0 - end -end - -define __set_add - set $p = (void*)$arg0 - set $__bkt_idx = (int)$p%$__BUCKET_SIZE - - __set_instance - set $__elem = (void*(*)[2])$__set_instance[$__bkt_idx] - set $__found = 0 - while $__elem - if (*$__elem)[0] == $p - set $__found = 1 - loop_break - end - set $__elem = (void*(*)[2])(*$__elem)[1] - end - if $__found - set $existed_in_set = 1 - else - set $existed_in_set = 0 - - set $rc = (void*(*)[2])calloc(1, sizeof(void*)*2) - set (*$rc)[0] = $p - set (*$rc)[1] = $__set_instance[$__bkt_idx] - set $__set_instance[$__bkt_idx] = $rc - end -end - -define __set_is_exist - set $p = (void*)$arg0 - set $__bkt_idx = (int)$p%$__BUCKET_SIZE - - __set_instance - set $__elem = (void*(*)[2])$__set_instance[$__bkt_idx] - set $__found = 0 - while $__elem - if (*$__elem)[0] == $p - set $__found = 1 - loop_break - end - set $__elem = (void*(*)[2])(*$__elem)[1] - end - if $__found - set $existed_in_set = 1 - else - set $existed_in_set = 0 - end -end - -define __set_clean - __set_instance - - set $__bkt_idx = 0 - while $__bkt_idx < $__BUCKET_SIZE - set $__elem = (void*(*)[2])$__set_instance[$__bkt_idx] - while $__elem - set $__next = (void*(*)[2])(*$__elem)[1] - set $rc = free($__elem) - set $__elem = $__next - end - set $__set_instance[$__bkt_idx] = 0 - set $__bkt_idx = $__bkt_idx+1 - end -end - -define hook-quit - __free_lua_debug_instance - __free_set_instance -end - -define hook-detach - __free_lua_debug_instance - __free_set_instance -end - -define hook-disconnect - __free_lua_debug_instance - __free_set_instance -end - -define _lua_pop - set $l = (lua_State*)$arg0 - set $_n = (int)$arg1 - set $_rc = lua_settop($l, -$_n-1) -end - -define _lua_dump_locals - set $l = (lua_State*)$arg0 - set $dbg = (lua_Debug*)$arg1 - set $idx = 1 - - set $rc = lua_getlocal($l, $dbg, $idx) - if $rc - printf "\t----[[ Locals ]]----\n" - while $rc - printf "\t%d:\t'%s' = ", $idx, $rc - __lua_dump_stack $l -1 - printf "\n" - - _lua_pop $l 1 - set $idx = $idx + 1 - set $rc = lua_getlocal($l, $dbg, $idx) - end - else - printf "\tNo locals!\n" - end - printf "\n" -end - -define _lua_dump_upvalues - set $l = (lua_State*)$arg0 - set $dbg = (lua_Debug*)$arg1 - set $idx = 1 - - set $rc = lua_getinfo($l, "f", $dbg) - if $rc - set $rc = lua_getupvalue($l, -1, $idx) - if $rc - printf "\t----[[ Upvalues ]]----\n" - while $rc - printf "\t%d:\t'%s' = ", $idx, $rc - __lua_dump_stack $l -1 - printf "\n" - - _lua_pop $l 1 - set $idx = $idx + 1 - set $rc = lua_getupvalue($l, -1, $idx) - end - else - printf "\tNo upvalues!\n" - end - _lua_pop $l 1 - else - printf "\tFailed to get function closure!\n" - end - printf "\n" -end - -define __lua_dump_stack - __set_clean - __lua_dump_stack_aux $arg0 $arg1 0 -end - -define __lua_dump_stack_aux - set $l = (lua_State*)$arg0 - set $nidx_$arg2 = (int)$arg1 - set $cidx_$arg2 = (int)$arg2+1 - - # relative stack index to absolute index - if $nidx_$arg2 < 0 && $nidx_$arg2 > $__LUA_REGISTRYINDEX - set $nidx_$arg2 = $nidx_$arg2 + (int)lua_gettop($l) + 1 - end - - set $vt_$arg2 = (int)lua_type($l, $nidx_$arg2) - - if $vt_$arg2 == $__LUA_TNONE - echo - end - if $vt_$arg2 == $__LUA_TNIL - echo (nil) - end - if $vt_$arg2 == $__LUA_TBOOLEAN - printf "(bool) %d", lua_toboolean($l, $nidx_$arg2) - end - if $vt_$arg2 == $__LUA_TLIGHTUSERDATA - printf "(ludata) %p", lua_touserdata($l, $nidx_$arg2) - end - if $vt_$arg2 == $__LUA_TNUMBER - printf "%g", lua_tonumber($l, $nidx_$arg2) - end - if $vt_$arg2 == $__LUA_TSTRING - set $tmplen = (size_t*)malloc(sizeof(size_t)) - set $tmp = lua_pushvalue($l, $nidx_$arg2) - set $tmp = lua_tolstring($l, -1, $tmplen) -#printf "(string:%d) ", *$tmplen - eval "output/r *(const char (*)[%d])$tmp", *$tmplen - _lua_pop $l 1 - set $tmp = free($tmplen) - end - if $vt_$arg2 == $__LUA_TTABLE - set $rc = lua_topointer($l, $nidx_$arg2) -#printf "(table) %p { ", $rc - printf "{ " - __set_add $rc - if $existed_in_set - printf "... " - else - set $rc = lua_pushnil($l) - set $rc = lua_next($l, $nidx_$arg2) - while $rc != 0 - printf "[" - __lua_dump_stack_aux $l -2 $cidx_$arg2 - printf "]" - printf " = " - __lua_dump_stack_aux $l -1 $cidx_$arg2 - printf ", " - _lua_pop $l 1 - set $rc = lua_next($l, $nidx_$arg2) - end - end - printf "}" - end - if $vt_$arg2 == $__LUA_TFUNCTION - printf "(func) %p", lua_topointer($l, $nidx_$arg2) - end - if $vt_$arg2 == $__LUA_TUSERDATA - printf "(udata) %p", lua_topointer($l, $nidx_$arg2) - end - if $vt_$arg2 == $__LUA_TTHREAD - printf "(thread) %p", lua_topointer($l, $nidx_$arg2) - else - if $vt_$arg2 > $__LUA_TTHREAD || $vt_$arg2 < 0 - echo - end - end -end - -#### Command methods #### - -define lbt - if $argc < 1 - echo Please specify Lua state and/or dump flag!\n - else - set $l = (lua_State*)$arg0 - if $argc > 1 - set $dump_local = ($arg1&1)==1 - set $dump_upvalue = ($arg1&2)==2 - else - set $dump_local = 0 - set $dump_upvalue = 0 - end - - __lua_debug_instance - set $dbg = $__lua_debug_instance - - set $level = 0 - set $rc = lua_getstack($l, $level, $dbg) - while $rc > 0 - set $rc = lua_getinfo($l, "Sln", $dbg) - set $name = $dbg->name - if !$name - set $name = "???" - end - - printf "#%d\t%s\t[%s]\tat %s:%d\n", $level, $name, $dbg->what, $dbg->source, $dbg->currentline - - if $dump_local - _lua_dump_locals $l $dbg - end - if $dump_upvalue - _lua_dump_upvalues $l $dbg - end - - set $level = $level+1 - set $rc = lua_getstack($l, $level, $dbg) - end - end -end - -document lbt -lbt []: Dump the backtrace of the specified Lua state. is a mask value, whose bit 1/2 controls the dump of locals/upvalues at each stack frame correspondingly. So set to 1 dumps only locals; set to 2 dumps only upvalues; and set to 3 dumps both locals and upvalues. -end - -define ll - if $argc != 2 - echo Please specify Lua state and stack frame number (0-based)!\n - else - set $l = (lua_State*)$arg0 - set $level = (int)$arg1 - - __lua_debug_instance - set $dbg = $__lua_debug_instance - - set $rc = lua_getstack($l, $level, $dbg) - if $rc > 0 - _lua_dump_locals $l $dbg - else - echo Failed to get Lua stack frame!\n - end - end -end - -document ll -ll : Dump all local vars in the specified Lua stack frame (0-based). -end - -define lu - if $argc != 2 - echo Please specify Lua state and stack frame number (0-based)!\n - else - set $l = (lua_State*)$arg0 - set $level = (int)$arg1 - - __lua_debug_instance - set $dbg = $__lua_debug_instance - - set $rc = lua_getstack($l, $level, $dbg) - if $rc > 0 - _lua_dump_upvalues $l $dbg - else - echo Failed to get Lua stack frame!\n - end - end -end - -document lu -lu : Dump all upvalues in the specified Lua stack frame (0-based). -end - -define lg - if $argc != 1 - echo Please specify Lua state!\n - else - set $l = (lua_State*)$arg0 - __lua_dump_stack $l $__LUA_GLOBALSINDEX - printf "\n" - end -end - -document lg -lg : Dump all entries in Lua global table. -end - -define lr - if $argc != 1 - echo Please specify Lua state!\n - else - set $l = (lua_State*)$arg0 - __lua_dump_stack $l $__LUA_REGISTRYINDEX - printf "\n" - end -end - -document lr -lr : Dump all entries in Lua registry table. -end - -define ls - if $argc != 1 - echo Please specify Lua state!\n - else - set $l = (lua_State*)$arg0 - set $idx = lua_gettop($l) - while $idx >= 1 - printf "#%d ", $idx - __lua_dump_stack $l $idx - printf "\n" - set $idx = $idx - 1 - end - end -end - -document ls -ls : Dump all entries in call stack. -end - -# vi:ft=gdb ts=4 sw=4 - diff --git a/debian/modules/nginx-lua/util/reindex b/debian/modules/nginx-lua/util/reindex deleted file mode 100755 index bd54c9d..0000000 --- a/debian/modules/nginx-lua/util/reindex +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/perl -#: reindex.pl -#: reindex .t files for Test::Base based test files -#: Copyright (c) 2006 Agent Zhang -#: 2006-04-27 2006-05-09 - -use strict; -use warnings; - -#use File::Copy; -use Getopt::Std; - -my %opts; -getopts('hb:', \%opts); -if ($opts{h} or ! @ARGV) { - die "Usage: reindex [-b 0] t/*.t\n"; -} - -my $init = $opts{b}; -$init = 1 if not defined $init; - -my @files = map glob, @ARGV; -for my $file (@files) { - next if -d $file or $file !~ /\.t_?$/; - reindex($file); -} - -sub reindex { - my $file = $_[0]; - open my $in, $file or - die "Can't open $file for reading: $!"; - my @lines; - my $counter = $init; - my $changed; - while (<$in>) { - s/\r$//; - my $num; - s/ ^ === \s+ TEST \s+ (\d+)/$num=$1; "=== TEST " . $counter++/xie; - next if !defined $num; - if ($num != $counter-1) { - $changed++; - } - } continue { - push @lines, $_; - } - close $in; - my $text = join '', @lines; - $text =~ s/(?x) \n+ === \s+ TEST/\n\n\n\n=== TEST/ixsg; - $text =~ s/__(DATA|END)__\n+=== TEST/__${1}__\n\n=== TEST/; - #$text =~ s/\n+$/\n\n/s; - if (! $changed and $text eq join '', @lines) { - warn "reindex: $file:\tskipped.\n"; - return; - } - #File::Copy::copy( $file, "$file.bak" ); - open my $out, "> $file" or - die "Can't open $file for writing: $!"; - binmode $out; - print $out $text; - close $out; - - warn "reindex: $file:\tdone.\n"; -} - diff --git a/debian/modules/nginx-lua/valgrind.suppress b/debian/modules/nginx-lua/valgrind.suppress index fe161e8..d0bcc56 100644 --- a/debian/modules/nginx-lua/valgrind.suppress +++ b/debian/modules/nginx-lua/valgrind.suppress @@ -149,3 +149,18 @@ fun:main fun:__libc_res_nquerydomain fun:__libc_res_nsearch } +{ + + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + fun:ngx_alloc + fun:ngx_set_environment + fun:ngx_single_process_cycle + fun:main +} +{ + + Memcheck:Cond + obj:* +} From 70cb0befe7496ee84ef10792d03e9f8adc07679b Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Mon, 28 Aug 2017 15:16:06 +0300 Subject: [PATCH 207/600] Update OpenSSL 1.1 patch for v0.10.10 --- .../patches/nginx-lua/openssl-1.1.0.patch | 264 +++++------------- 1 file changed, 69 insertions(+), 195 deletions(-) diff --git a/debian/modules/patches/nginx-lua/openssl-1.1.0.patch b/debian/modules/patches/nginx-lua/openssl-1.1.0.patch index a4e42e5..431031b 100644 --- a/debian/modules/patches/nginx-lua/openssl-1.1.0.patch +++ b/debian/modules/patches/nginx-lua/openssl-1.1.0.patch @@ -1,7 +1,7 @@ -From 2f281b9def161d195da4d795fa916b686ac9fd87 Mon Sep 17 00:00:00 2001 +From 525d5a550f5f256af01de1264358086a4cd1ac4a Mon Sep 17 00:00:00 2001 From: Alessandro Ghedini Date: Tue, 13 Sep 2016 22:31:32 +0100 -Subject: [PATCH 1/6] bugfix: ssl: don't use SSLv3 in tests +Subject: [PATCH 1/4] bugfix: ssl: don't use SSLv3 in tests. OpenSSL 1.1.0 disables SSLv3 by default. In order to disable SSL session tickets set ssl_session_tickets to off instead. @@ -11,7 +11,7 @@ tickets set ssl_session_tickets to off instead. 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/t/142-ssl-session-store.t b/t/142-ssl-session-store.t -index 5c9fad35..b5955199 100644 +index 73b6e197..260fe490 100644 --- a/t/142-ssl-session-store.t +++ b/t/142-ssl-session-store.t @@ -32,7 +32,7 @@ __DATA__ @@ -140,7 +140,7 @@ index 5c9fad35..b5955199 100644 server_tokens off; } diff --git a/t/143-ssl-session-fetch.t b/t/143-ssl-session-fetch.t -index bd800ff8..54f7a4a3 100644 +index 701ead72..3626f0fb 100644 --- a/t/143-ssl-session-fetch.t +++ b/t/143-ssl-session-fetch.t @@ -33,7 +33,7 @@ __DATA__ @@ -273,25 +273,25 @@ index bd800ff8..54f7a4a3 100644 server_tokens off; } -- -2.11.0 +2.14.1 -From ad8df79bccef37a0bbfd8e40283f3b81cd867760 Mon Sep 17 00:00:00 2001 +From d308b44b3daf7702d9218e2a5620a89a5eca8389 Mon Sep 17 00:00:00 2001 From: Alessandro Ghedini Date: Thu, 12 May 2016 13:12:23 +0100 -Subject: [PATCH 2/6] bugfix: ssl: do not access SSL_SESSION struct directly +Subject: [PATCH 2/4] bugfix: ssl: do not access SSL_SESSION struct directly. In OpenSSL 1.1.0 it was made opaque. --- src/ngx_http_lua_socket_tcp.c | 15 ++--- - t/129-ssl-socket.t | 152 +++++++++++++++++++++--------------------- - 2 files changed, 82 insertions(+), 85 deletions(-) + t/129-ssl-socket.t | 148 +++++++++++++++++++++--------------------- + 2 files changed, 80 insertions(+), 83 deletions(-) diff --git a/src/ngx_http_lua_socket_tcp.c b/src/ngx_http_lua_socket_tcp.c -index 6db6e2da..18352bfe 100644 +index 382a94de..07164746 100644 --- a/src/ngx_http_lua_socket_tcp.c +++ b/src/ngx_http_lua_socket_tcp.c -@@ -1311,9 +1311,8 @@ ngx_http_lua_socket_tcp_sslhandshake(lua_State *L) +@@ -1316,9 +1316,8 @@ ngx_http_lua_socket_tcp_sslhandshake(lua_State *L) return 2; } @@ -303,7 +303,7 @@ index 6db6e2da..18352bfe 100644 } } -@@ -1577,9 +1576,8 @@ ngx_http_lua_ssl_handshake_retval_handler(ngx_http_request_t *r, +@@ -1583,9 +1582,8 @@ ngx_http_lua_ssl_handshake_retval_handler(ngx_http_request_t *r, } else { *ud = ssl_session; @@ -315,7 +315,7 @@ index 6db6e2da..18352bfe 100644 /* set up the __gc metamethod */ lua_pushlightuserdata(L, &ngx_http_lua_ssl_session_metatable_key); -@@ -5356,9 +5354,8 @@ ngx_http_lua_ssl_free_session(lua_State *L) +@@ -5365,9 +5363,8 @@ ngx_http_lua_ssl_free_session(lua_State *L) psession = lua_touserdata(L, 1); if (psession && *psession != NULL) { @@ -328,7 +328,7 @@ index 6db6e2da..18352bfe 100644 ngx_ssl_free_session(*psession); } diff --git a/t/129-ssl-socket.t b/t/129-ssl-socket.t -index 9da9a5c2..98fb5a2b 100644 +index 1c3f7cd0..0cd1f52f 100644 --- a/t/129-ssl-socket.t +++ b/t/129-ssl-socket.t @@ -108,10 +108,10 @@ sent http request: 59 bytes. @@ -345,21 +345,16 @@ index 9da9a5c2..98fb5a2b 100644 $/ --- no_error_log lua ssl server name: -@@ -185,10 +185,10 @@ received: HTTP/1.1 401 Unauthorized - close: 1 nil +@@ -182,7 +182,7 @@ connected: 1 + failed to do SSL handshake: handshake failed --- log_level: debug ---- grep_error_log eval: qr/lua ssl (?:set|save|free) session: [0-9A-F]+:\d+/ +--- grep_error_log eval: qr/lua ssl (?:set|save|free) session: [0-9A-F]+/ - --- grep_error_log_out eval --qr/^lua ssl save session: ([0-9A-F]+):2 --lua ssl free session: ([0-9A-F]+):1 -+qr/^lua ssl save session: ([0-9A-F]+) -+lua ssl free session: ([0-9A-F]+) - $/ + --- grep_error_log_out --- no_error_log lua ssl server name: -@@ -262,10 +262,10 @@ received: HTTP/1.1 200 OK +@@ -255,10 +255,10 @@ received: HTTP/1.1 302 Moved Temporarily close: 1 nil --- log_level: debug @@ -372,8 +367,8 @@ index 9da9a5c2..98fb5a2b 100644 +lua ssl free session: ([0-9A-F]+) $/ --- error_log - lua ssl server name: "iscribblet.org" -@@ -349,13 +349,13 @@ sent http request: 59 bytes. + lua ssl server name: "openresty.org" +@@ -343,13 +343,13 @@ sent http request: 56 bytes. received: HTTP/1.1 200 OK close: 1 nil @@ -393,25 +388,25 @@ index 9da9a5c2..98fb5a2b 100644 $/ --- error_log -@@ -437,7 +437,7 @@ failed to do SSL handshake: certificate host mismatch - failed to send http request: closed +@@ -432,7 +432,7 @@ failed to send http request: closed + \z --- log_level: debug ---- grep_error_log eval: qr/lua ssl (?:set|save|free) session: [0-9A-F]+:\d+/ +--- grep_error_log eval: qr/lua ssl (?:set|save|free) session: [0-9A-F]+/ --- grep_error_log_out --- error_log - lua ssl server name: "blah.agentzh.org" -@@ -517,7 +517,7 @@ failed to do SSL handshake: certificate host mismatch - failed to send http request: closed + lua ssl server name: "blah.openresty.org" +@@ -512,7 +512,7 @@ failed to send http request: closed + \z --- log_level: debug ---- grep_error_log eval: qr/lua ssl (?:set|save|free) session: [0-9A-F]+:\d+/ +--- grep_error_log eval: qr/lua ssl (?:set|save|free) session: [0-9A-F]+/ --- grep_error_log_out --- error_log - lua ssl server name: "blah.agentzh.org" -@@ -592,10 +592,10 @@ received: HTTP/1.1 200 OK + lua ssl server name: "blah.openresty.org" +@@ -587,10 +587,10 @@ received: HTTP/1.1 404 Not Found close: 1 nil --- log_level: debug @@ -425,7 +420,7 @@ index 9da9a5c2..98fb5a2b 100644 $/ --- error_log -@@ -677,10 +677,10 @@ received: HTTP/1.1 200 OK +@@ -672,10 +672,10 @@ received: HTTP/1.1 302 Moved Temporarily close: 1 nil --- log_level: debug @@ -439,7 +434,7 @@ index 9da9a5c2..98fb5a2b 100644 $/ --- error_log -@@ -759,7 +759,7 @@ failed to do SSL handshake: 20: unable to get local issuer certificate +@@ -754,7 +754,7 @@ failed to do SSL handshake: 20: unable to get local issuer certificate failed to send http request: closed --- log_level: debug @@ -447,8 +442,8 @@ index 9da9a5c2..98fb5a2b 100644 +--- grep_error_log eval: qr/lua ssl (?:set|save|free) session: [0-9A-F]+/ --- grep_error_log_out --- error_log - lua ssl server name: "iscribblet.org" -@@ -838,7 +838,7 @@ failed to do SSL handshake: 20: unable to get local issuer certificate + lua ssl server name: "openresty.org" +@@ -833,7 +833,7 @@ failed to do SSL handshake: 20: unable to get local issuer certificate failed to send http request: closed --- log_level: debug @@ -456,8 +451,8 @@ index 9da9a5c2..98fb5a2b 100644 +--- grep_error_log eval: qr/lua ssl (?:set|save|free) session: [0-9A-F]+/ --- grep_error_log_out --- error_log - lua ssl server name: "iscribblet.org" -@@ -928,10 +928,10 @@ sent http request: 59 bytes. + lua ssl server name: "openresty.org" +@@ -923,10 +923,10 @@ sent http request: 59 bytes. received: HTTP/1.1 (?:200 OK|302 Found) close: 1 nil \z @@ -471,7 +466,7 @@ index 9da9a5c2..98fb5a2b 100644 $/ --- error_log lua ssl server name: "www.google.com" -@@ -1018,7 +1018,7 @@ GET /t +@@ -1013,7 +1013,7 @@ GET /t connected: 1 failed to do SSL handshake: 20: unable to get local issuer certificate @@ -480,7 +475,7 @@ index 9da9a5c2..98fb5a2b 100644 --- grep_error_log_out --- error_log lua ssl server name: "www.google.com" -@@ -1100,10 +1100,10 @@ received: HTTP/1.1 200 OK +@@ -1095,10 +1095,10 @@ received: HTTP/1.1 302 Moved Temporarily close: 1 nil --- log_level: debug @@ -494,7 +489,7 @@ index 9da9a5c2..98fb5a2b 100644 $/ --- error_log -@@ -1179,10 +1179,10 @@ received: HTTP/1.1 200 OK +@@ -1174,10 +1174,10 @@ received: HTTP/1.1 302 Moved Temporarily close: 1 nil --- log_level: debug @@ -507,8 +502,8 @@ index 9da9a5c2..98fb5a2b 100644 +lua ssl free session: ([0-9A-F]+) $/ --- error_log - lua ssl server name: "iscribblet.org" -@@ -1259,10 +1259,10 @@ received: HTTP/1.1 200 OK + lua ssl server name: "openresty.org" +@@ -1254,10 +1254,10 @@ received: HTTP/1.1 302 Moved Temporarily close: 1 nil --- log_level: debug @@ -521,8 +516,8 @@ index 9da9a5c2..98fb5a2b 100644 +lua ssl free session: ([0-9A-F]+) $/ --- error_log - lua ssl server name: "iscribblet.org" -@@ -1339,10 +1339,10 @@ received: HTTP/1.1 200 OK + lua ssl server name: "openresty.org" +@@ -1334,10 +1334,10 @@ received: HTTP/1.1 302 Moved Temporarily close: 1 nil --- log_level: debug @@ -535,8 +530,8 @@ index 9da9a5c2..98fb5a2b 100644 +lua ssl free session: ([0-9A-F]+) $/ --- error_log - lua ssl server name: "iscribblet.org" -@@ -1417,7 +1417,7 @@ failed to do SSL handshake: handshake failed + lua ssl server name: "openresty.org" +@@ -1412,7 +1412,7 @@ failed to do SSL handshake: handshake failed failed to send http request: closed --- log_level: debug @@ -545,7 +540,7 @@ index 9da9a5c2..98fb5a2b 100644 --- grep_error_log_out --- error_log eval [ -@@ -1493,10 +1493,10 @@ ssl handshake: userdata +@@ -1488,10 +1488,10 @@ ssl handshake: userdata set keepalive: 1 nil --- log_level: debug @@ -559,7 +554,7 @@ index 9da9a5c2..98fb5a2b 100644 $/ --- error_log -@@ -1569,14 +1569,14 @@ ssl handshake: userdata +@@ -1564,14 +1564,14 @@ ssl handshake: userdata set keepalive: 1 nil --- log_level: debug @@ -581,7 +576,7 @@ index 9da9a5c2..98fb5a2b 100644 $/ --- error_log -@@ -1620,7 +1620,7 @@ hello world +@@ -1615,7 +1615,7 @@ hello world --- response_body_like: 500 Internal Server Error --- error_code: 500 --- log_level: debug @@ -590,7 +585,7 @@ index 9da9a5c2..98fb5a2b 100644 --- grep_error_log_out --- error_log attempt to call method 'sslhandshake' (a nil value) -@@ -1719,10 +1719,10 @@ $::TestCertificateKey +@@ -1714,10 +1714,10 @@ $::TestCertificateKey >>> test.crt $::TestCertificate" @@ -604,7 +599,7 @@ index 9da9a5c2..98fb5a2b 100644 $/ --- no_error_log lua ssl server name: -@@ -1824,10 +1824,10 @@ $::TestCertificateKey +@@ -1819,10 +1819,10 @@ $::TestCertificateKey >>> test.crt $::TestCertificate" @@ -618,7 +613,7 @@ index 9da9a5c2..98fb5a2b 100644 $/ --- error_log lua ssl server name: "test.com" -@@ -1917,7 +1917,7 @@ failed to do SSL handshake: handshake failed +@@ -1912,7 +1912,7 @@ failed to do SSL handshake: handshake failed ">>> test.crt $::TestCertificate" @@ -627,7 +622,7 @@ index 9da9a5c2..98fb5a2b 100644 --- grep_error_log_out --- error_log eval qr/SSL_do_handshake\(\) failed .*?unknown protocol/ -@@ -2016,7 +2016,7 @@ $::TestCertificate +@@ -2011,7 +2011,7 @@ $::TestCertificate >>> test.crl $::TestCRL" @@ -636,7 +631,7 @@ index 9da9a5c2..98fb5a2b 100644 --- grep_error_log_out --- error_log lua ssl server name: "test.com" -@@ -2095,12 +2095,12 @@ received: HTTP/1.1 200 OK +@@ -2090,12 +2090,12 @@ received: HTTP/1.1 302 Moved Temporarily close: 1 nil --- log_level: debug @@ -653,8 +648,8 @@ index 9da9a5c2..98fb5a2b 100644 +lua ssl free session: ([0-9A-F]+) $/ --- error_log - lua ssl server name: "iscribblet.org" -@@ -2154,7 +2154,7 @@ connected: 1 + lua ssl server name: "openresty.org" +@@ -2149,7 +2149,7 @@ connected: 1 failed to do SSL handshake: timeout --- log_level: debug @@ -662,8 +657,8 @@ index 9da9a5c2..98fb5a2b 100644 +--- grep_error_log eval: qr/lua ssl (?:set|save|free) session: [0-9A-F]+/ --- grep_error_log_out --- error_log - lua ssl server name: "iscribblet.org" -@@ -2226,7 +2226,7 @@ $::TestCertificateKey + lua ssl server name: "openresty.org" +@@ -2221,7 +2221,7 @@ $::TestCertificateKey >>> test.crt $::TestCertificate" @@ -672,7 +667,7 @@ index 9da9a5c2..98fb5a2b 100644 --- grep_error_log_out --- no_error_log lua ssl server name: -@@ -2297,10 +2297,10 @@ $::TestCertificateKey +@@ -2292,10 +2292,10 @@ $::TestCertificateKey >>> test.crt $::TestCertificate" @@ -686,7 +681,7 @@ index 9da9a5c2..98fb5a2b 100644 $/ --- no_error_log lua ssl server name: -@@ -2377,7 +2377,7 @@ $::TestCertificateKey +@@ -2372,7 +2372,7 @@ $::TestCertificateKey >>> test.crt $::TestCertificate" @@ -695,7 +690,7 @@ index 9da9a5c2..98fb5a2b 100644 --- grep_error_log_out --- no_error_log lua ssl server name: -@@ -2479,10 +2479,10 @@ $::TestCertificateKey +@@ -2474,10 +2474,10 @@ $::TestCertificateKey >>> test.crt $::TestCertificate" @@ -709,7 +704,7 @@ index 9da9a5c2..98fb5a2b 100644 $/ --- error_log --- no_error_log -@@ -2575,7 +2575,7 @@ $::TestCertificateKey +@@ -2570,7 +2570,7 @@ $::TestCertificateKey >>> test.crt $::TestCertificate" @@ -719,43 +714,14 @@ index 9da9a5c2..98fb5a2b 100644 --- error_log lua ssl certificate verify error: (18: self signed certificate) -- -2.11.0 +2.14.1 -From ee94698edd219607adbd4807f4e5173f6e51ad51 Mon Sep 17 00:00:00 2001 -From: Alessandro Ghedini -Date: Thu, 12 May 2016 13:17:52 +0100 -Subject: [PATCH 3/6] bugfix: ssl: do not set tlsext_status_expected flag - -In OpenSSL 1.1.0 the SSL struct was made opaque, and setting this -flag manually is not required anyway since OpenSSL already does that -automatically when ngx_http_lua_ssl_empty_status_callback() returns -"OK" (which is always), and an OCSP response has been set. ---- - src/ngx_http_lua_ssl_ocsp.c | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/src/ngx_http_lua_ssl_ocsp.c b/src/ngx_http_lua_ssl_ocsp.c -index 3904aa8e..31b4f243 100644 ---- a/src/ngx_http_lua_ssl_ocsp.c -+++ b/src/ngx_http_lua_ssl_ocsp.c -@@ -490,7 +490,6 @@ ngx_http_lua_ffi_ssl_set_ocsp_status_resp(ngx_http_request_t *r, - - dd("set ocsp resp: resp_len=%d", (int) resp_len); - (void) SSL_set_tlsext_status_ocsp_resp(ssl_conn, p, resp_len); -- ssl_conn->tlsext_status_expected = 1; - - return NGX_OK; - --- -2.11.0 - - -From 9794d2d1ba577fe4dd8771d69d1ca4a688efe36c Mon Sep 17 00:00:00 2001 +From 473c121668c658140dffdbeb70aa7df1fc48d2a7 Mon Sep 17 00:00:00 2001 From: Alessandro Ghedini Date: Fri, 10 Jun 2016 13:23:21 +0100 -Subject: [PATCH 4/6] bugfix: ssl: do not access SSL struct directly for - tlsext_status_type +Subject: [PATCH 3/4] bugfix: ssl: do not access SSL struct directly for + tlsext_status_type. In OpenSSL 1.1.0 it was made opaque, and a getter function was added. --- @@ -779,14 +745,14 @@ index 31b4f243..9ec8b509 100644 return NGX_DECLINED; } -- -2.11.0 +2.14.1 -From 4d1f5bdcdade5e3c6ac0c09446ac1dcd8b4006b0 Mon Sep 17 00:00:00 2001 +From 44988918835b8b41e51e75c1618250a560bc11ca Mon Sep 17 00:00:00 2001 From: Alessandro Ghedini Date: Tue, 13 Sep 2016 22:19:10 +0100 -Subject: [PATCH 5/6] bugfix: ssl: make SSL session callback build with OpenSSL - 1.1.0 +Subject: [PATCH 4/4] bugfix: ssl: make SSL session callback build with OpenSSL + 1.1.0. --- src/ngx_http_lua_ssl_session_fetchby.c | 9 ++++++--- @@ -795,7 +761,7 @@ Subject: [PATCH 5/6] bugfix: ssl: make SSL session callback build with OpenSSL 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/ngx_http_lua_ssl_session_fetchby.c b/src/ngx_http_lua_ssl_session_fetchby.c -index 4c450b56..6212c60d 100644 +index 556b7320..5289cb92 100644 --- a/src/ngx_http_lua_ssl_session_fetchby.c +++ b/src/ngx_http_lua_ssl_session_fetchby.c @@ -171,8 +171,11 @@ ngx_http_lua_ssl_sess_fetch_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, @@ -839,7 +805,7 @@ index 5a6f96f5..50c6616d 100644 diff --git a/src/ngx_http_lua_ssl_session_storeby.c b/src/ngx_http_lua_ssl_session_storeby.c -index b5596bc7..85dbece1 100644 +index bae8273d..dc1fad9b 100644 --- a/src/ngx_http_lua_ssl_session_storeby.c +++ b/src/ngx_http_lua_ssl_session_storeby.c @@ -172,6 +172,8 @@ int @@ -868,97 +834,5 @@ index b5596bc7..85dbece1 100644 dd("setting cctx"); -- -2.11.0 - - -From 97ca52b469fcf4881c06ab26fbc46cbd37d8cf9f Mon Sep 17 00:00:00 2001 -From: Alessandro Ghedini -Date: Mon, 28 Nov 2016 21:01:00 +0000 -Subject: [PATCH 6/6] bugfix: ssl: don't use RC4 in tests - -RC4 ciphers are deprecated and disabled by default in OpenSSL 1.1.0. ---- - t/129-ssl-socket.t | 18 +++++++++--------- - 1 file changed, 9 insertions(+), 9 deletions(-) - -diff --git a/t/129-ssl-socket.t b/t/129-ssl-socket.t -index 98fb5a2b..1d9c5710 100644 ---- a/t/129-ssl-socket.t -+++ b/t/129-ssl-socket.t -@@ -1129,7 +1129,7 @@ SSL reused session - sock:settimeout(2000) - - do -- local ok, err = sock:connect("iscribblet.org", 443) -+ local ok, err = sock:connect("openresty.org", 443) - if not ok then - ngx.say("failed to connect: ", err) - return -@@ -1137,7 +1137,7 @@ SSL reused session - - ngx.say("connected: ", ok) - -- local session, err = sock:sslhandshake(nil, "iscribblet.org") -+ local session, err = sock:sslhandshake(nil, "openresty.org") - if not session then - ngx.say("failed to do SSL handshake: ", err) - return -@@ -1145,7 +1145,7 @@ SSL reused session - - ngx.say("ssl handshake: ", type(session)) - -- local req = "GET / HTTP/1.1\\r\\nHost: iscribblet.org\\r\\nConnection: close\\r\\n\\r\\n" -+ local req = "GET /en/ HTTP/1.1\\r\\nHost: openresty.org\\r\\nConnection: close\\r\\n\\r\\n" - local bytes, err = sock:send(req) - if not bytes then - ngx.say("failed to send http request: ", err) -@@ -1174,7 +1174,7 @@ GET /t - --- response_body - connected: 1 - ssl handshake: userdata --sent http request: 59 bytes. -+sent http request: 61 bytes. - received: HTTP/1.1 200 OK - close: 1 nil - -@@ -1185,8 +1185,8 @@ qr/^lua ssl save session: ([0-9A-F]+) - lua ssl free session: ([0-9A-F]+) - $/ - --- error_log --lua ssl server name: "iscribblet.org" --SSL: TLSv1.2, cipher: "ECDHE-RSA-RC4-SHA SSLv3 -+lua ssl server name: "openresty.org" -+SSL: TLSv1.2, cipher: "ECDHE-RSA-AES128-GCM-SHA256 - --- no_error_log - SSL reused session - [error] -@@ -1199,7 +1199,7 @@ SSL reused session - --- config - server_tokens off; - resolver $TEST_NGINX_RESOLVER; -- lua_ssl_ciphers RC4-SHA; -+ lua_ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256; - location /t { - #set $port 5000; - set $port $TEST_NGINX_MEMCACHED_PORT; -@@ -1266,7 +1266,7 @@ lua ssl free session: ([0-9A-F]+) - $/ - --- error_log - lua ssl server name: "iscribblet.org" --SSL: TLSv1.2, cipher: "RC4-SHA SSLv3 -+SSL: TLSv1.2, cipher: "ECDHE-RSA-AES128-GCM-SHA256 - --- no_error_log - SSL reused session - [error] -@@ -1346,7 +1346,7 @@ lua ssl free session: ([0-9A-F]+) - $/ - --- error_log - lua ssl server name: "iscribblet.org" --SSL: TLSv1, cipher: "ECDHE-RSA-RC4-SHA SSLv3 -+SSL: TLSv1 - --- no_error_log - SSL reused session - [error] --- -2.11.0 +2.14.1 From 7614ff61a9d2985f19dea05d21bfd207bbd7d6e1 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Mon, 28 Aug 2017 16:05:03 +0300 Subject: [PATCH 208/600] lua: Drop patch to build against nginx 1.11.11, now included upstream --- debian/modules/README.Modules-versions | 1 - .../nginx-lua/build-nginx-1.1.11.patch | 217 ------------------ debian/modules/patches/nginx-lua/series | 1 - 3 files changed, 219 deletions(-) delete mode 100644 debian/modules/patches/nginx-lua/build-nginx-1.1.11.patch diff --git a/debian/modules/README.Modules-versions b/debian/modules/README.Modules-versions index 6b581cd..ff5f63b 100644 --- a/debian/modules/README.Modules-versions +++ b/debian/modules/README.Modules-versions @@ -25,7 +25,6 @@ README for Modules versions Homepage: https://github.com/openresty/lua-nginx-module Version: v0.10.10 Patch: openssl-1.1.0.patch - Patch: build-nginx-1.11.11.patch Patch: discover-luajit-2.1.patch nginx-upstream-fair diff --git a/debian/modules/patches/nginx-lua/build-nginx-1.1.11.patch b/debian/modules/patches/nginx-lua/build-nginx-1.1.11.patch deleted file mode 100644 index 597cbf8..0000000 --- a/debian/modules/patches/nginx-lua/build-nginx-1.1.11.patch +++ /dev/null @@ -1,217 +0,0 @@ -From 0459a285ca0159d45e73da8bd1164edb5c57cde3 Mon Sep 17 00:00:00 2001 -From: Andrei Belov -Date: Wed, 22 Mar 2017 07:50:57 +0300 -Subject: [PATCH] feature: nginx 1.11.11+ can now build with this module. - -Note: nginx 1.11.11+ are still not an officially supported target yet. -More work needed. - -Closes openresty/lua-nginx-module#1016 - -See also: -http://hg.nginx.org/nginx/rev/e662cbf1b932 ---- - src/ngx_http_lua_common.h | 6 ++++ - src/ngx_http_lua_headers.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++ - src/ngx_http_lua_headers.h | 3 ++ - src/ngx_http_lua_module.c | 13 ++++++++- - 4 files changed, 89 insertions(+), 1 deletion(-) - -diff --git a/src/ngx_http_lua_common.h b/src/ngx_http_lua_common.h -index 079a4dc3..f37d776a 100644 ---- a/src/ngx_http_lua_common.h -+++ b/src/ngx_http_lua_common.h -@@ -199,6 +199,12 @@ struct ngx_http_lua_main_conf_s { - of reqeusts */ - ngx_uint_t malloc_trim_req_count; - -+#if nginx_version >= 1011011 -+ /* the following 2 fields are only used by ngx.req.raw_headers() for now */ -+ ngx_buf_t **busy_buf_ptrs; -+ ngx_int_t busy_buf_ptr_count; -+#endif -+ - unsigned requires_header_filter:1; - unsigned requires_body_filter:1; - unsigned requires_capture_filter:1; -diff --git a/src/ngx_http_lua_headers.c b/src/ngx_http_lua_headers.c -index 23925984..6700ce80 100644 ---- a/src/ngx_http_lua_headers.c -+++ b/src/ngx_http_lua_headers.c -@@ -26,6 +26,9 @@ static int ngx_http_lua_ngx_req_get_headers(lua_State *L); - static int ngx_http_lua_ngx_req_header_clear(lua_State *L); - static int ngx_http_lua_ngx_req_header_set(lua_State *L); - static int ngx_http_lua_ngx_resp_get_headers(lua_State *L); -+#if nginx_version >= 1011011 -+void ngx_http_lua_ngx_raw_header_cleanup(void *data); -+#endif - - - static int -@@ -77,6 +80,11 @@ ngx_http_lua_ngx_req_raw_header(lua_State *L) - size_t size; - ngx_buf_t *b, *first = NULL; - ngx_int_t i, j; -+#if nginx_version >= 1011011 -+ ngx_buf_t **bb; -+ ngx_chain_t *cl; -+ ngx_http_lua_main_conf_t *lmcf; -+#endif - ngx_connection_t *c; - ngx_http_request_t *r, *mr; - ngx_http_connection_t *hc; -@@ -93,6 +101,10 @@ ngx_http_lua_ngx_req_raw_header(lua_State *L) - return luaL_error(L, "no request object found"); - } - -+#if nginx_version >= 1011011 -+ lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); -+#endif -+ - ngx_http_lua_check_fake_request(L, r); - - mr = r->main; -@@ -109,8 +121,13 @@ ngx_http_lua_ngx_req_raw_header(lua_State *L) - dd("hc->nbusy: %d", (int) hc->nbusy); - - if (hc->nbusy) { -+#if nginx_version >= 1011011 -+ dd("hc->busy: %p %p %p %p", hc->busy->buf->start, hc->busy->buf->pos, -+ hc->busy->buf->last, hc->busy->buf->end); -+#else - dd("hc->busy: %p %p %p %p", hc->busy[0]->start, hc->busy[0]->pos, - hc->busy[0]->last, hc->busy[0]->end); -+#endif - } - - dd("request line: %p %p", mr->request_line.data, -@@ -146,9 +163,37 @@ ngx_http_lua_ngx_req_raw_header(lua_State *L) - dd("size: %d", (int) size); - - if (hc->nbusy) { -+#if nginx_version >= 1011011 -+ if (hc->nbusy > lmcf->busy_buf_ptr_count) { -+ if (lmcf->busy_buf_ptrs) { -+ ngx_free(lmcf->busy_buf_ptrs); -+ } -+ -+ lmcf->busy_buf_ptrs = ngx_alloc(hc->nbusy * sizeof(ngx_buf_t *), -+ r->connection->log); -+ -+ if (lmcf->busy_buf_ptrs == NULL) { -+ return luaL_error(L, "no memory"); -+ } -+ -+ lmcf->busy_buf_ptr_count = hc->nbusy; -+ } -+ -+ bb = lmcf->busy_buf_ptrs; -+ for (cl = hc->busy; cl; cl = cl->next) { -+ *bb++ = cl->buf; -+ } -+#endif - b = NULL; -+ -+#if nginx_version >= 1011011 -+ bb = lmcf->busy_buf_ptrs; -+ for (i = hc->nbusy; i > 0; i--) { -+ b = bb[i - 1]; -+#else - for (i = 0; i < hc->nbusy; i++) { - b = hc->busy[i]; -+#endif - - dd("busy buf: %d: [%.*s]", (int) i, (int) (b->pos - b->start), - b->start); -@@ -223,8 +268,15 @@ ngx_http_lua_ngx_req_raw_header(lua_State *L) - } - - if (hc->nbusy) { -+ -+#if nginx_version >= 1011011 -+ bb = lmcf->busy_buf_ptrs; -+ for (i = hc->nbusy - 1; i >= 0; i--) { -+ b = bb[i]; -+#else - for (i = 0; i < hc->nbusy; i++) { - b = hc->busy[i]; -+#endif - - if (!found) { - if (b != first) { -@@ -1431,4 +1483,20 @@ ngx_http_lua_ffi_get_resp_header(ngx_http_request_t *r, - #endif /* NGX_LUA_NO_FFI_API */ - - -+#if nginx_version >= 1011011 -+void -+ngx_http_lua_ngx_raw_header_cleanup(void *data) -+{ -+ ngx_http_lua_main_conf_t *lmcf; -+ -+ lmcf = (ngx_http_lua_main_conf_t *) data; -+ -+ if (lmcf->busy_buf_ptrs) { -+ ngx_free(lmcf->busy_buf_ptrs); -+ lmcf->busy_buf_ptrs = NULL; -+ } -+} -+#endif -+ -+ - /* vi:set ft=c ts=4 sw=4 et fdm=marker: */ -diff --git a/src/ngx_http_lua_headers.h b/src/ngx_http_lua_headers.h -index 39f1114c..ee4d21c1 100644 ---- a/src/ngx_http_lua_headers.h -+++ b/src/ngx_http_lua_headers.h -@@ -15,6 +15,9 @@ - void ngx_http_lua_inject_resp_header_api(lua_State *L); - void ngx_http_lua_inject_req_header_api(lua_State *L); - void ngx_http_lua_create_headers_metatable(ngx_log_t *log, lua_State *L); -+#if nginx_version >= 1011011 -+void ngx_http_lua_ngx_raw_header_cleanup(void *data); -+#endif - - - #endif /* _NGX_HTTP_LUA_HEADERS_H_INCLUDED_ */ -diff --git a/src/ngx_http_lua_module.c b/src/ngx_http_lua_module.c -index 3dc2817b..875f9334 100644 ---- a/src/ngx_http_lua_module.c -+++ b/src/ngx_http_lua_module.c -@@ -28,6 +28,7 @@ - #include "ngx_http_lua_ssl_certby.h" - #include "ngx_http_lua_ssl_session_storeby.h" - #include "ngx_http_lua_ssl_session_fetchby.h" -+#include "ngx_http_lua_headers.h" - - - static void *ngx_http_lua_create_main_conf(ngx_conf_t *cf); -@@ -624,7 +625,7 @@ ngx_http_lua_init(ngx_conf_t *cf) - volatile ngx_cycle_t *saved_cycle; - ngx_http_core_main_conf_t *cmcf; - ngx_http_lua_main_conf_t *lmcf; --#ifndef NGX_LUA_NO_FFI_API -+#if !defined(NGX_LUA_NO_FFI_API) || nginx_version >= 1011011 - ngx_pool_cleanup_t *cln; - #endif - -@@ -716,6 +717,16 @@ ngx_http_lua_init(ngx_conf_t *cf) - cln->handler = ngx_http_lua_sema_mm_cleanup; - #endif - -+#if nginx_version >= 1011011 -+ cln = ngx_pool_cleanup_add(cf->pool, 0); -+ if (cln == NULL) { -+ return NGX_ERROR; -+ } -+ -+ cln->data = lmcf; -+ cln->handler = ngx_http_lua_ngx_raw_header_cleanup; -+#endif -+ - if (lmcf->lua == NULL) { - dd("initializing lua vm"); - --- -2.11.0 - diff --git a/debian/modules/patches/nginx-lua/series b/debian/modules/patches/nginx-lua/series index 8edeaf5..7d0f424 100644 --- a/debian/modules/patches/nginx-lua/series +++ b/debian/modules/patches/nginx-lua/series @@ -1,3 +1,2 @@ openssl-1.1.0.patch -build-nginx-1.1.11.patch discover-luajit-2.1.patch From e60711fcc72e83d560fa250fba484f3d541cb5b4 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Mon, 28 Aug 2017 16:35:53 +0300 Subject: [PATCH 209/600] tests: Fix race between reload and curl's http request Restart nginx to make sure it uses the new configuration. --- debian/tests/ec-x25519 | 2 +- debian/tests/lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/tests/ec-x25519 b/debian/tests/ec-x25519 index a01bc0d..edd4e2f 100644 --- a/debian/tests/ec-x25519 +++ b/debian/tests/ec-x25519 @@ -17,5 +17,5 @@ server { EOF nginx -t -nginx -s reload +invoke-rc.d nginx restart curl --insecure --silent --fail -o /dev/null -w "response_code: %{http_code}\n" https://127.0.0.1/ diff --git a/debian/tests/lua b/debian/tests/lua index 396d8a9..82c1820 100644 --- a/debian/tests/lua +++ b/debian/tests/lua @@ -14,5 +14,5 @@ server { EOF nginx -t -nginx -s reload +invoke-rc.d nginx restart curl --silent --fail -o /dev/null -w "response_code: %{http_code}\n" http://127.0.0.1/ping From 2005e7e35d4c99863c55019cca2a4675f57d8ee0 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Mon, 28 Aug 2017 16:53:56 +0300 Subject: [PATCH 210/600] Explicitly disable autoreconf (debhelper 10) Since debhelper 10 systemd & autoreconf are enabled by default, we need systemd and not autoconf so we reverse the logic. While at it, drop not needed autotools dependency. --- debian/control | 3 +-- debian/rules | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/debian/control b/debian/control index ccb769d..9d46418 100644 --- a/debian/control +++ b/debian/control @@ -5,8 +5,7 @@ Maintainer: Debian Nginx Maintainers , Michael Lustfield , Christos Trochalakis -Build-Depends: autotools-dev, - debhelper (>= 10), +Build-Depends: debhelper (>= 10), po-debconf, dh-systemd (>= 1.5), dpkg-dev (>= 1.15.5), diff --git a/debian/rules b/debian/rules index 3951529..a852d02 100755 --- a/debian/rules +++ b/debian/rules @@ -138,7 +138,7 @@ extras_configure_flags := \ --add-dynamic-module=$(MODULESDIR)/ngx_http_substitutions_filter_module %: - dh $@ --with systemd + dh $@ --without autoreconf override_dh_auto_configure: config_patch_modules $(foreach flavour,$(FLAVOURS),config.arch.$(flavour)) override_dh_auto_build: $(foreach flavour,$(FLAVOURS),build.arch.$(flavour)) From 22aae236484ddf9ace687ee7a846e8420e9927a6 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Mon, 28 Aug 2017 17:03:49 +0300 Subject: [PATCH 211/600] Drop Upstart configuration Upstart was removed in Debian stretch --- debian/nginx-common.nginx.upstart | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 debian/nginx-common.nginx.upstart diff --git a/debian/nginx-common.nginx.upstart b/debian/nginx-common.nginx.upstart deleted file mode 100644 index 317bcb0..0000000 --- a/debian/nginx-common.nginx.upstart +++ /dev/null @@ -1,16 +0,0 @@ -description "nginx - small, powerful, scalable web/proxy server" - -start on filesystem and static-network-up -stop on runlevel [016] - -expect fork -respawn - -pre-start script - [ -x /usr/sbin/nginx ] || { stop; exit 0; } - /usr/sbin/nginx -q -t -g 'daemon on; master_process on;' || { stop; exit 0; } -end script - -exec /usr/sbin/nginx -g 'daemon on; master_process on;' - -pre-stop exec /usr/sbin/nginx -s quit From 9ad7cddbce6fae45691b58421e362c579a4e4370 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Mon, 28 Aug 2017 17:11:10 +0300 Subject: [PATCH 212/600] Bump Standards to 4.1.0 o Switch all packages to Priority optional, extra is considered deprecated and should be treated as equivalent to optional. nginx-light & extras now inherit optional from the source package. --- debian/control | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/debian/control b/debian/control index 9d46418..e7a598a 100644 --- a/debian/control +++ b/debian/control @@ -24,7 +24,7 @@ Build-Depends: debhelper (>= 10), po-debconf, quilt, zlib1g-dev -Standards-Version: 4.0.0 +Standards-Version: 4.1.0 Homepage: http://nginx.net Vcs-Git: https://anonscm.debian.org/cgit/pkg-nginx/nginx.git Vcs-Browser: https://anonscm.debian.org/cgit/pkg-nginx/nginx.git @@ -111,7 +111,6 @@ Description: nginx web/proxy server (standard version) Package: nginx-light Architecture: any -Priority: extra Depends: libnginx-mod-http-echo (= ${binary:Version}), nginx-common (= ${source:Version}), ${misc:Depends}, @@ -139,7 +138,6 @@ Description: nginx web/proxy server (basic version) Package: nginx-extras Architecture: any -Priority: extra Depends: libnginx-mod-http-auth-pam (= ${binary:Version}), libnginx-mod-http-cache-purge (= ${binary:Version}), libnginx-mod-http-dav-ext (= ${binary:Version}), From ee4f08f8b48651eb584373af0bb71afd5a4d3c1d Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Tue, 29 Aug 2017 10:50:48 +0300 Subject: [PATCH 213/600] Release 1.13.4-1 --- debian/changelog | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/debian/changelog b/debian/changelog index 7d350cf..3e671b0 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,20 @@ +nginx (1.13.4-1) unstable; urgency=medium + + * New upstream version 1.13.4 + * nginx-lua: + + Add a simple lua autopkgtest + + Discover LuaJIT 2.1 (FTBFS) (Closes: #873319) + + Update to v0.10.10 + + Update OpenSSL 1.1 patch + + Drop patch to build against Nginx 1.11.11, now included upstream + * tests: Fix race between reload and curl's http request + * Explicitly disable autoreconf (debhelper 10) + * Drop Upstart configuration + * Bump Standards to 4.1.0 + + Switch all packages to Priority optional, extra is considered deprecated + + -- Christos Trochalakis Tue, 29 Aug 2017 10:49:03 +0300 + nginx (1.13.3-1) unstable; urgency=high * New upstream version 1.13.3. From 3ebf96c773e9685d526ebe77daaf0baa91e73e04 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Tue, 29 Aug 2017 13:04:11 +0300 Subject: [PATCH 214/600] doc: Improve example WordPress configuration Closes: #863343 Thanks: Larry Holish --- debian/help/examples/wordpress | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/debian/help/examples/wordpress b/debian/help/examples/wordpress index 6faf918..2d4c0ab 100644 --- a/debian/help/examples/wordpress +++ b/debian/help/examples/wordpress @@ -34,8 +34,8 @@ server { } # This location block protects against a known attack. It happens if - # the attacker uploads a non-php file and attempts to run it as a - # php file on the server. + # the attacker uploads a non-PHP file and attempts to run it as a + # PHP file on the server. location ~ \..*/.*\.php$ { return 403; } @@ -43,7 +43,7 @@ server { # This is our primary location block. The try_files directive will # attempt to serve the data in the order listed. First try the exact # request (such as an image or text file). If it doesn't exist, see if - # the directory exists. If not, then we move to the last options which + # the directory exists. If not, then we move to the last option which # passes the request to /index.php with the requested query. location / { try_files $uri $uri/ /index.php?q=$uri&$args; @@ -51,7 +51,7 @@ server { # If a PHP file is served, this block will handle the request. This block # works on the assumption you are using php-cgi listening on /tmp/phpcgi.socket. - # Please see the php example (usr/share/doc/nginx/exmaples/php) for more + # Please see the PHP example (/usr/share/doc/nginx-doc/php) for more # information about setting up PHP. # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini location ~ \.php$ { @@ -61,12 +61,11 @@ server { fastcgi_intercept_errors on; fastcgi_pass unix:/tmp/phpcgi.socket; } - - # As mentioned above, Nignx is king of static. If we're serving a static - # file that ends with one of the following extensions, it is best to set - # a very high expires time. This will generate fewer requests for the - # file. These requests will be logged if found, but not if they don't - # exist. + + # If we're serving a static file that ends with one of the following + # extensions, it is best to set a very high expires time. This will + # generate fewer requests for the file. These requests will be logged if + # found, but not if they don't exist. location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ { expires max; log_not_found off; From 3582062c0e7359e6fe9bd08f6b0cea332491554c Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Tue, 5 Sep 2017 10:29:14 +0300 Subject: [PATCH 215/600] Remove upstart configuration file Close: #874319 --- debian/nginx-common.postinst | 4 ++++ debian/nginx-common.postrm | 4 ++++ debian/nginx-common.preinst | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/debian/nginx-common.postinst b/debian/nginx-common.postinst index 2b176f8..f996cec 100644 --- a/debian/nginx-common.postinst +++ b/debian/nginx-common.postinst @@ -13,6 +13,10 @@ dpkg-maintscript-helper rm_conffile \ dpkg-maintscript-helper rm_conffile \ /etc/nginx/naxsi-ui.conf 1.6.2-2~ -- "$@" +# Handle upstart removal +dpkg-maintscript-helper rm_conffile \ + /etc/init/nginx.conf 1.13.4-2~ -- "$@" + case "$1" in configure) logdir="/var/log/nginx" diff --git a/debian/nginx-common.postrm b/debian/nginx-common.postrm index b0f2e30..9aa06d0 100644 --- a/debian/nginx-common.postrm +++ b/debian/nginx-common.postrm @@ -11,6 +11,10 @@ dpkg-maintscript-helper rm_conffile \ dpkg-maintscript-helper rm_conffile \ /etc/nginx/naxsi-ui.conf 1.6.2-2~ -- "$@" +# Handle upstart removal +dpkg-maintscript-helper rm_conffile \ + /etc/init/nginx.conf 1.13.4-2~ -- "$@" + case "$1" in purge) rm -rf /var/lib/nginx /var/log/nginx /etc/nginx diff --git a/debian/nginx-common.preinst b/debian/nginx-common.preinst index 037c80f..0d2737f 100644 --- a/debian/nginx-common.preinst +++ b/debian/nginx-common.preinst @@ -11,6 +11,10 @@ dpkg-maintscript-helper rm_conffile \ dpkg-maintscript-helper rm_conffile \ /etc/nginx/naxsi-ui.conf 1.6.2-2~ -- "$@" +# Handle upstart removal +dpkg-maintscript-helper rm_conffile \ + /etc/init/nginx.conf 1.13.4-2~ -- "$@" + case "$1" in install) # If we are doing a fresh install, then these files are no longer needed. From 2a7340c231ffc083156ad1af0691c3f25309ecc4 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Wed, 6 Sep 2017 10:06:33 +0300 Subject: [PATCH 216/600] New upstream version 1.13.5 --- CHANGES | 15 +++++ CHANGES.ru | 15 +++++ src/core/nginx.h | 4 +- src/core/ngx_conf_file.c | 1 + src/core/ngx_regex.c | 4 +- src/event/ngx_event.h | 4 +- src/event/ngx_event_openssl.c | 56 ++++++++++++++++--- src/event/ngx_event_openssl.h | 2 + src/http/modules/ngx_http_geo_module.c | 3 +- .../modules/ngx_http_range_filter_module.c | 17 +++--- src/http/modules/ngx_http_scgi_module.c | 2 +- .../modules/ngx_http_secure_link_module.c | 3 +- src/http/modules/ngx_http_ssl_module.c | 4 ++ src/http/modules/ngx_http_uwsgi_module.c | 8 +-- src/http/ngx_http_upstream.c | 20 +------ src/os/unix/ngx_files.c | 1 + src/stream/ngx_stream_geo_module.c | 3 +- src/stream/ngx_stream_ssl_module.c | 4 ++ 18 files changed, 119 insertions(+), 47 deletions(-) diff --git a/CHANGES b/CHANGES index cc22571..e46199b 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,19 @@ +Changes with nginx 1.13.5 05 Sep 2017 + + *) Feature: the $ssl_client_escaped_cert variable. + + *) Bugfix: the "ssl_session_ticket_key" directive and the "include" + parameter of the "geo" directive did not work on Windows. + + *) Bugfix: incorrect response length was returned on 32-bit platforms + when requesting more than 4 gigabytes with multiple ranges. + + *) Bugfix: the "expires modified" directive and processing of the + "If-Range" request header line did not use the response last + modification time if proxying without caching was used. + + Changes with nginx 1.13.4 08 Aug 2017 *) Feature: the ngx_http_mirror_module. diff --git a/CHANGES.ru b/CHANGES.ru index f466c4d..73c4164 100644 --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,19 @@ +Изменения в nginx 1.13.5 05.09.2017 + + *) Добавление: переменная $ssl_client_escaped_cert. + + *) Исправление: директива ssl_session_ticket_key и параметр include + директивы geo не работали на Windows. + + *) Исправление: на 32-битных платформах при запросе более 4 гигабайт с + помощью нескольких диапазонов возвращалась некорректная длина ответа. + + *) Исправление: директива "expires modified" и обработка строки If-Range + заголовка запроса не учитывали время последнего изменения ответа, + если использовалось проксирование без кэширования. + + Изменения в nginx 1.13.4 08.08.2017 *) Добавление: модуль ngx_http_mirror_module. diff --git a/src/core/nginx.h b/src/core/nginx.h index 3649945..a3c0ef8 100644 --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1013004 -#define NGINX_VERSION "1.13.4" +#define nginx_version 1013005 +#define NGINX_VERSION "1.13.5" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD diff --git a/src/core/ngx_conf_file.c b/src/core/ngx_conf_file.c index ce8c602..fb28a5a 100644 --- a/src/core/ngx_conf_file.c +++ b/src/core/ngx_conf_file.c @@ -178,6 +178,7 @@ ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename) /* open configuration file */ fd = ngx_open_file(filename->data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); + if (fd == NGX_INVALID_FILE) { ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno, ngx_open_file_n " \"%s\" failed", diff --git a/src/core/ngx_regex.c b/src/core/ngx_regex.c index 9939dce..52169f6 100644 --- a/src/core/ngx_regex.c +++ b/src/core/ngx_regex.c @@ -262,7 +262,7 @@ ngx_pcre_free_studies(void *data) part = &studies->part; elts = part->elts; - for (i = 0 ; /* void */ ; i++) { + for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { @@ -326,7 +326,7 @@ ngx_regex_module_init(ngx_cycle_t *cycle) part = &ngx_pcre_studies->part; elts = part->elts; - for (i = 0 ; /* void */ ; i++) { + for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h index 053bd16..19fec68 100644 --- a/src/event/ngx_event.h +++ b/src/event/ngx_event.h @@ -152,12 +152,12 @@ struct ngx_event_aio_s { ngx_event_handler_pt handler; ngx_file_t *file; + ngx_fd_t fd; + #if (NGX_HAVE_AIO_SENDFILE || NGX_COMPAT) ssize_t (*preload_handler)(ngx_buf_t *file); #endif - ngx_fd_t fd; - #if (NGX_HAVE_EVENTFD) int64_t res; #endif diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c index 07646b6..88a6dbe 100644 --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -924,6 +924,7 @@ ngx_ssl_read_password_file(ngx_conf_t *cf, ngx_str_t *file) cln->data = passwords; fd = ngx_open_file(file->data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); + if (fd == NGX_INVALID_FILE) { ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno, ngx_open_file_n " \"%s\" failed", file->data); @@ -2905,7 +2906,9 @@ ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths) file.name = path[i]; file.log = cf->log; - file.fd = ngx_open_file(file.name.data, NGX_FILE_RDONLY, 0, 0); + file.fd = ngx_open_file(file.name.data, NGX_FILE_RDONLY, + NGX_FILE_OPEN, 0); + if (file.fd == NGX_INVALID_FILE) { ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno, ngx_open_file_n " \"%V\" failed", &file.name); @@ -3548,13 +3551,22 @@ ngx_ssl_get_server_name(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) { #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME - const char *servername; + size_t len; + const char *name; + + name = SSL_get_servername(c->ssl->connection, TLSEXT_NAMETYPE_host_name); + + if (name) { + len = ngx_strlen(name); + + s->len = len; + s->data = ngx_pnalloc(pool, len); + if (s->data == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(s->data, name, len); - servername = SSL_get_servername(c->ssl->connection, - TLSEXT_NAMETYPE_host_name); - if (servername) { - s->data = (u_char *) servername; - s->len = ngx_strlen(servername); return NGX_OK; } @@ -3659,6 +3671,36 @@ ngx_ssl_get_certificate(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) } +ngx_int_t +ngx_ssl_get_escaped_certificate(ngx_connection_t *c, ngx_pool_t *pool, + ngx_str_t *s) +{ + ngx_str_t cert; + uintptr_t n; + + if (ngx_ssl_get_raw_certificate(c, pool, &cert) != NGX_OK) { + return NGX_ERROR; + } + + if (cert.len == 0) { + s->len = 0; + return NGX_OK; + } + + n = ngx_escape_uri(NULL, cert.data, cert.len, NGX_ESCAPE_URI_COMPONENT); + + s->len = cert.len + n * 2; + s->data = ngx_pnalloc(pool, s->len); + if (s->data == NULL) { + return NGX_ERROR; + } + + ngx_escape_uri(s->data, cert.data, cert.len, NGX_ESCAPE_URI_COMPONENT); + + return NGX_OK; +} + + ngx_int_t ngx_ssl_get_subject_dn(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) { diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h index 2a14980..b9a3a96 100644 --- a/src/event/ngx_event_openssl.h +++ b/src/event/ngx_event_openssl.h @@ -212,6 +212,8 @@ ngx_int_t ngx_ssl_get_raw_certificate(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s); ngx_int_t ngx_ssl_get_certificate(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s); +ngx_int_t ngx_ssl_get_escaped_certificate(ngx_connection_t *c, ngx_pool_t *pool, + ngx_str_t *s); ngx_int_t ngx_ssl_get_subject_dn(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s); ngx_int_t ngx_ssl_get_issuer_dn(ngx_connection_t *c, ngx_pool_t *pool, diff --git a/src/http/modules/ngx_http_geo_module.c b/src/http/modules/ngx_http_geo_module.c index 46a8d7c..8262c9d 100644 --- a/src/http/modules/ngx_http_geo_module.c +++ b/src/http/modules/ngx_http_geo_module.c @@ -1400,7 +1400,8 @@ ngx_http_geo_include_binary_base(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx, file.name = *name; file.log = cf->log; - file.fd = ngx_open_file(name->data, NGX_FILE_RDONLY, 0, 0); + file.fd = ngx_open_file(name->data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); + if (file.fd == NGX_INVALID_FILE) { err = ngx_errno; if (err != NGX_ENOENT) { diff --git a/src/http/modules/ngx_http_range_filter_module.c b/src/http/modules/ngx_http_range_filter_module.c index 6256b13..819c5c9 100644 --- a/src/http/modules/ngx_http_range_filter_module.c +++ b/src/http/modules/ngx_http_range_filter_module.c @@ -463,23 +463,24 @@ static ngx_int_t ngx_http_range_multipart_header(ngx_http_request_t *r, ngx_http_range_filter_ctx_t *ctx) { - size_t len; + off_t len; + size_t size; ngx_uint_t i; ngx_http_range_t *range; ngx_atomic_uint_t boundary; - len = sizeof(CRLF "--") - 1 + NGX_ATOMIC_T_LEN - + sizeof(CRLF "Content-Type: ") - 1 - + r->headers_out.content_type.len - + sizeof(CRLF "Content-Range: bytes ") - 1; + size = sizeof(CRLF "--") - 1 + NGX_ATOMIC_T_LEN + + sizeof(CRLF "Content-Type: ") - 1 + + r->headers_out.content_type.len + + sizeof(CRLF "Content-Range: bytes ") - 1; if (r->headers_out.content_type_len == r->headers_out.content_type.len && r->headers_out.charset.len) { - len += sizeof("; charset=") - 1 + r->headers_out.charset.len; + size += sizeof("; charset=") - 1 + r->headers_out.charset.len; } - ctx->boundary_header.data = ngx_pnalloc(r->pool, len); + ctx->boundary_header.data = ngx_pnalloc(r->pool, size); if (ctx->boundary_header.data == NULL) { return NGX_ERROR; } @@ -569,7 +570,7 @@ ngx_http_range_multipart_header(ngx_http_request_t *r, - range[i].content_range.data; len += ctx->boundary_header.len + range[i].content_range.len - + (size_t) (range[i].end - range[i].start); + + (range[i].end - range[i].start); } r->headers_out.content_length_n = len; diff --git a/src/http/modules/ngx_http_scgi_module.c b/src/http/modules/ngx_http_scgi_module.c index 9204af4..3fb227b 100644 --- a/src/http/modules/ngx_http_scgi_module.c +++ b/src/http/modules/ngx_http_scgi_module.c @@ -819,7 +819,7 @@ ngx_http_scgi_create_request(ngx_http_request_t *r) key = e.pos; #endif code = *(ngx_http_script_code_pt *) e.ip; - code((ngx_http_script_engine_t *) & e); + code((ngx_http_script_engine_t *) &e); #if (NGX_DEBUG) val = e.pos; diff --git a/src/http/modules/ngx_http_secure_link_module.c b/src/http/modules/ngx_http_secure_link_module.c index 907ba6e..536e09a 100644 --- a/src/http/modules/ngx_http_secure_link_module.c +++ b/src/http/modules/ngx_http_secure_link_module.c @@ -107,7 +107,7 @@ ngx_http_secure_link_variable(ngx_http_request_t *r, ngx_md5_t md5; ngx_http_secure_link_ctx_t *ctx; ngx_http_secure_link_conf_t *conf; - u_char hash_buf[16], md5_buf[16]; + u_char hash_buf[18], md5_buf[16]; conf = ngx_http_get_module_loc_conf(r, ngx_http_secure_link_module); @@ -154,7 +154,6 @@ ngx_http_secure_link_variable(ngx_http_request_t *r, goto not_found; } - hash.len = 16; hash.data = hash_buf; if (ngx_decode_base64url(&hash, &val) != NGX_OK) { diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c index 4370275..7d62176 100644 --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -299,6 +299,10 @@ static ngx_http_variable_t ngx_http_ssl_vars[] = { (uintptr_t) ngx_ssl_get_raw_certificate, NGX_HTTP_VAR_CHANGEABLE, 0 }, + { ngx_string("ssl_client_escaped_cert"), NULL, ngx_http_ssl_variable, + (uintptr_t) ngx_ssl_get_escaped_certificate, + NGX_HTTP_VAR_CHANGEABLE, 0 }, + { ngx_string("ssl_client_s_dn"), NULL, ngx_http_ssl_variable, (uintptr_t) ngx_ssl_get_subject_dn, NGX_HTTP_VAR_CHANGEABLE, 0 }, diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c index a2bec4c..124da4d 100644 --- a/src/http/modules/ngx_http_uwsgi_module.c +++ b/src/http/modules/ngx_http_uwsgi_module.c @@ -865,7 +865,7 @@ ngx_http_uwsgi_create_request(ngx_http_request_t *r) lcode = *(ngx_http_script_len_code_pt *) le.ip; skip_empty = lcode(&le); - for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode (&le)) { + for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) { lcode = *(ngx_http_script_len_code_pt *) le.ip; } le.ip += sizeof(uintptr_t); @@ -990,7 +990,7 @@ ngx_http_uwsgi_create_request(ngx_http_request_t *r) while (*(uintptr_t *) le.ip) { lcode = *(ngx_http_script_len_code_pt *) le.ip; - key_len = (u_char) lcode (&le); + key_len = (u_char) lcode(&le); lcode = *(ngx_http_script_len_code_pt *) le.ip; skip_empty = lcode(&le); @@ -1018,14 +1018,14 @@ ngx_http_uwsgi_create_request(ngx_http_request_t *r) *e.pos++ = (u_char) ((key_len >> 8) & 0xff); code = *(ngx_http_script_code_pt *) e.ip; - code((ngx_http_script_engine_t *) & e); + code((ngx_http_script_engine_t *) &e); *e.pos++ = (u_char) (val_len & 0xff); *e.pos++ = (u_char) ((val_len >> 8) & 0xff); while (*(uintptr_t *) e.ip) { code = *(ngx_http_script_code_pt *) e.ip; - code((ngx_http_script_engine_t *) & e); + code((ngx_http_script_engine_t *) &e); } e.ip += sizeof(uintptr_t); diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c index 6a2b322..73a5882 100644 --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -4390,15 +4390,8 @@ ngx_http_upstream_process_last_modified(ngx_http_request_t *r, u = r->upstream; u->headers_in.last_modified = h; - -#if (NGX_HTTP_CACHE) - - if (u->cacheable) { - u->headers_in.last_modified_time = ngx_parse_http_time(h->value.data, - h->value.len); - } - -#endif + u->headers_in.last_modified_time = ngx_parse_http_time(h->value.data, + h->value.len); return NGX_OK; } @@ -4940,15 +4933,8 @@ ngx_http_upstream_copy_last_modified(ngx_http_request_t *r, ngx_table_elt_t *h, *ho = *h; r->headers_out.last_modified = ho; - -#if (NGX_HTTP_CACHE) - - if (r->upstream->cacheable) { - r->headers_out.last_modified_time = + r->headers_out.last_modified_time = r->upstream->headers_in.last_modified_time; - } - -#endif return NGX_OK; } diff --git a/src/os/unix/ngx_files.c b/src/os/unix/ngx_files.c index 7fbb7c9..482d327 100644 --- a/src/os/unix/ngx_files.c +++ b/src/os/unix/ngx_files.c @@ -620,6 +620,7 @@ ngx_create_file_mapping(ngx_file_mapping_t *fm) { fm->fd = ngx_open_file(fm->name, NGX_FILE_RDWR, NGX_FILE_TRUNCATE, NGX_FILE_DEFAULT_ACCESS); + if (fm->fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_CRIT, fm->log, ngx_errno, ngx_open_file_n " \"%s\" failed", fm->name); diff --git a/src/stream/ngx_stream_geo_module.c b/src/stream/ngx_stream_geo_module.c index 2204546..632fa5a 100644 --- a/src/stream/ngx_stream_geo_module.c +++ b/src/stream/ngx_stream_geo_module.c @@ -1326,7 +1326,8 @@ ngx_stream_geo_include_binary_base(ngx_conf_t *cf, file.name = *name; file.log = cf->log; - file.fd = ngx_open_file(name->data, NGX_FILE_RDONLY, 0, 0); + file.fd = ngx_open_file(name->data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); + if (file.fd == NGX_INVALID_FILE) { err = ngx_errno; if (err != NGX_ENOENT) { diff --git a/src/stream/ngx_stream_ssl_module.c b/src/stream/ngx_stream_ssl_module.c index 010b98b..1e9973f 100644 --- a/src/stream/ngx_stream_ssl_module.c +++ b/src/stream/ngx_stream_ssl_module.c @@ -249,6 +249,10 @@ static ngx_stream_variable_t ngx_stream_ssl_vars[] = { (uintptr_t) ngx_ssl_get_raw_certificate, NGX_STREAM_VAR_CHANGEABLE, 0 }, + { ngx_string("ssl_client_escaped_cert"), NULL, ngx_stream_ssl_variable, + (uintptr_t) ngx_ssl_get_escaped_certificate, + NGX_STREAM_VAR_CHANGEABLE, 0 }, + { ngx_string("ssl_client_s_dn"), NULL, ngx_stream_ssl_variable, (uintptr_t) ngx_ssl_get_subject_dn, NGX_STREAM_VAR_CHANGEABLE, 0 }, From 1c5a8493cae9ec2fd6f1e258d077bea1a7c01475 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Wed, 6 Sep 2017 10:09:50 +0300 Subject: [PATCH 217/600] Adjust rm_conffile to the new version Gbp-Dch: Ignore --- debian/nginx-common.postinst | 2 +- debian/nginx-common.postrm | 2 +- debian/nginx-common.preinst | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/debian/nginx-common.postinst b/debian/nginx-common.postinst index f996cec..f83032d 100644 --- a/debian/nginx-common.postinst +++ b/debian/nginx-common.postinst @@ -15,7 +15,7 @@ dpkg-maintscript-helper rm_conffile \ # Handle upstart removal dpkg-maintscript-helper rm_conffile \ - /etc/init/nginx.conf 1.13.4-2~ -- "$@" + /etc/init/nginx.conf 1.13.5-1~ -- "$@" case "$1" in configure) diff --git a/debian/nginx-common.postrm b/debian/nginx-common.postrm index 9aa06d0..d6f313a 100644 --- a/debian/nginx-common.postrm +++ b/debian/nginx-common.postrm @@ -13,7 +13,7 @@ dpkg-maintscript-helper rm_conffile \ # Handle upstart removal dpkg-maintscript-helper rm_conffile \ - /etc/init/nginx.conf 1.13.4-2~ -- "$@" + /etc/init/nginx.conf 1.13.5-1~ -- "$@" case "$1" in purge) diff --git a/debian/nginx-common.preinst b/debian/nginx-common.preinst index 0d2737f..27f21da 100644 --- a/debian/nginx-common.preinst +++ b/debian/nginx-common.preinst @@ -13,7 +13,7 @@ dpkg-maintscript-helper rm_conffile \ # Handle upstart removal dpkg-maintscript-helper rm_conffile \ - /etc/init/nginx.conf 1.13.4-2~ -- "$@" + /etc/init/nginx.conf 1.13.5-1~ -- "$@" case "$1" in install) From cacbf319dba8b15bd02710ad5065516892148a5a Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Wed, 6 Sep 2017 10:10:41 +0300 Subject: [PATCH 218/600] Release 1.13.5-1 --- debian/changelog | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/debian/changelog b/debian/changelog index 3e671b0..396226e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,12 @@ +nginx (1.13.5-1) unstable; urgency=medium + + * New upstream version 1.13.5 + * doc: Improve example WordPress configuration + Thanks to Larry Holish (Closes: #863343) + * Remove upstart conffile (Closes: #874319) + + -- Christos Trochalakis Wed, 06 Sep 2017 10:10:24 +0300 + nginx (1.13.4-1) unstable; urgency=medium * New upstream version 1.13.4 From a5c72db78304846c75c7da22a26e539d4fb07874 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Wed, 11 Oct 2017 10:33:46 +0300 Subject: [PATCH 219/600] New upstream version 1.13.6 --- CHANGES | 36 ++++ CHANGES.ru | 36 ++++ conf/mime.types | 166 +++++++++--------- src/core/nginx.h | 4 +- src/core/ngx_connection.c | 4 + src/core/ngx_inet.c | 8 +- src/core/ngx_inet.h | 5 +- src/core/ngx_parse_time.c | 5 +- src/core/ngx_string.c | 16 ++ src/core/ngx_string.h | 2 + src/core/ngx_times.c | 30 +++- src/event/ngx_event_accept.c | 8 + src/http/modules/ngx_http_auth_basic_module.c | 70 ++------ .../modules/ngx_http_upstream_hash_module.c | 24 +-- .../modules/ngx_http_upstream_zone_module.c | 2 +- src/http/ngx_http_upstream.c | 73 ++++++-- src/http/ngx_http_upstream.h | 2 +- src/http/ngx_http_variables.c | 12 ++ src/http/v2/ngx_http_v2.c | 32 ++-- src/http/v2/ngx_http_v2.h | 1 + src/http/v2/ngx_http_v2_filter_module.c | 16 +- src/http/v2/ngx_http_v2_table.c | 6 +- src/os/unix/ngx_user.c | 10 -- src/stream/ngx_stream_proxy_module.c | 14 +- src/stream/ngx_stream_upstream.h | 2 +- src/stream/ngx_stream_upstream_hash_module.c | 24 +-- src/stream/ngx_stream_upstream_zone_module.c | 2 +- src/stream/ngx_stream_variables.c | 14 +- 28 files changed, 408 insertions(+), 216 deletions(-) diff --git a/CHANGES b/CHANGES index e46199b..6a9fdcc 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,40 @@ +Changes with nginx 1.13.6 10 Oct 2017 + + *) Bugfix: switching to the next upstream server in the stream module + did not work when using the "ssl_preread" directive. + + *) Bugfix: in the ngx_http_v2_module. + Thanks to Piotr Sikora. + + *) Bugfix: nginx did not support dates after the year 2038 on 32-bit + platforms with 64-bit time_t. + + *) Bugfix: in handling of dates prior to the year 1970 and after the + year 10000. + + *) Bugfix: in the stream module timeouts waiting for UDP datagrams from + upstream servers were not logged or logged at the "info" level + instead of "error". + + *) Bugfix: when using HTTP/2 nginx might return the 400 response without + logging the reason. + + *) Bugfix: in processing of corrupted cache files. + + *) Bugfix: cache control headers were ignored when caching errors + intercepted by error_page. + + *) Bugfix: when using HTTP/2 client request body might be corrupted. + + *) Bugfix: in handling of client addresses when using unix domain + sockets. + + *) Bugfix: nginx hogged CPU when using the "hash ... consistent" + directive in the upstream block if large weights were used and all or + most of the servers were unavailable. + + Changes with nginx 1.13.5 05 Sep 2017 *) Feature: the $ssl_client_escaped_cert variable. diff --git a/CHANGES.ru b/CHANGES.ru index 73c4164..6ea87c9 100644 --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,40 @@ +Изменения в nginx 1.13.6 10.10.2017 + + *) Исправление: при использовании директивы ssl_preread в модуле stream + не работало переключение на следующий бэкенд. + + *) Исправление: в модуле ngx_http_v2_module. + Спасибо Piotr Sikora. + + *) Исправление: nginx не поддерживал даты после 2038 года на 32-битных + платформах с 64-битным time_t. + + *) Исправление: в обработке дат до 1970 года и после 10000 года. + + *) Исправление: в модуле stream таймауты ожидания UDP-пакетов от + бэкендов не логгировались или логгировались на уровне info вместо + error. + + *) Исправление: при использовании HTTP/2 nginx мог вернуть ошибку 400, + не указав в логе причину. + + *) Исправление: в обработке повреждённых файлов кэша. + + *) Исправление: при кэшировании ошибок, перехваченных error_page, не + учитывались заголовки управления кэшированием. + + *) Исправление: при использовании HTTP/2 тело запроса могло быть + повреждено. + + *) Исправление: в обработке адресов клиентов при использовании unix + domain сокетов. + + *) Исправление: при использовании директивы "hash ... consistent" в + блоке upstream nginx нагружал процессор, если использовались большие + веса и все или почти все бэкенды были недоступны. + + Изменения в nginx 1.13.5 05.09.2017 *) Добавление: переменная $ssl_client_escaped_cert. diff --git a/conf/mime.types b/conf/mime.types index 89be9a4..8a2348a 100644 --- a/conf/mime.types +++ b/conf/mime.types @@ -1,89 +1,95 @@ types { - text/html html htm shtml; - text/css css; - text/xml xml; - image/gif gif; - image/jpeg jpeg jpg; - application/javascript js; - application/atom+xml atom; - application/rss+xml rss; + text/html html htm shtml; + text/css css; + text/xml xml; + image/gif gif; + image/jpeg jpeg jpg; + application/javascript js; + application/atom+xml atom; + application/rss+xml rss; - text/mathml mml; - text/plain txt; - text/vnd.sun.j2me.app-descriptor jad; - text/vnd.wap.wml wml; - text/x-component htc; + text/mathml mml; + text/plain txt; + text/vnd.sun.j2me.app-descriptor jad; + text/vnd.wap.wml wml; + text/x-component htc; - image/png png; - image/tiff tif tiff; - image/vnd.wap.wbmp wbmp; - image/x-icon ico; - image/x-jng jng; - image/x-ms-bmp bmp; - image/svg+xml svg svgz; - image/webp webp; + image/png png; + image/svg+xml svg svgz; + image/tiff tif tiff; + image/vnd.wap.wbmp wbmp; + image/webp webp; + image/x-icon ico; + image/x-jng jng; + image/x-ms-bmp bmp; - application/font-woff woff; - application/java-archive jar war ear; - application/json json; - application/mac-binhex40 hqx; - application/msword doc; - application/pdf pdf; - application/postscript ps eps ai; - application/rtf rtf; - application/vnd.apple.mpegurl m3u8; - application/vnd.ms-excel xls; - application/vnd.ms-fontobject eot; - application/vnd.ms-powerpoint ppt; - application/vnd.wap.wmlc wmlc; - application/vnd.google-earth.kml+xml kml; - application/vnd.google-earth.kmz kmz; - application/x-7z-compressed 7z; - application/x-cocoa cco; - application/x-java-archive-diff jardiff; - application/x-java-jnlp-file jnlp; - application/x-makeself run; - application/x-perl pl pm; - application/x-pilot prc pdb; - application/x-rar-compressed rar; - application/x-redhat-package-manager rpm; - application/x-sea sea; - application/x-shockwave-flash swf; - application/x-stuffit sit; - application/x-tcl tcl tk; - application/x-x509-ca-cert der pem crt; - application/x-xpinstall xpi; - application/xhtml+xml xhtml; - application/xspf+xml xspf; - application/zip zip; + application/font-woff woff; + application/java-archive jar war ear; + application/json json; + application/mac-binhex40 hqx; + application/msword doc; + application/pdf pdf; + application/postscript ps eps ai; + application/rtf rtf; + application/vnd.apple.mpegurl m3u8; + application/vnd.google-earth.kml+xml kml; + application/vnd.google-earth.kmz kmz; + application/vnd.ms-excel xls; + application/vnd.ms-fontobject eot; + application/vnd.ms-powerpoint ppt; + application/vnd.oasis.opendocument.graphics odg; + application/vnd.oasis.opendocument.presentation odp; + application/vnd.oasis.opendocument.spreadsheet ods; + application/vnd.oasis.opendocument.text odt; + application/vnd.openxmlformats-officedocument.presentationml.presentation + pptx; + application/vnd.openxmlformats-officedocument.spreadsheetml.sheet + xlsx; + application/vnd.openxmlformats-officedocument.wordprocessingml.document + docx; + application/vnd.wap.wmlc wmlc; + application/x-7z-compressed 7z; + application/x-cocoa cco; + application/x-java-archive-diff jardiff; + application/x-java-jnlp-file jnlp; + application/x-makeself run; + application/x-perl pl pm; + application/x-pilot prc pdb; + application/x-rar-compressed rar; + application/x-redhat-package-manager rpm; + application/x-sea sea; + application/x-shockwave-flash swf; + application/x-stuffit sit; + application/x-tcl tcl tk; + application/x-x509-ca-cert der pem crt; + application/x-xpinstall xpi; + application/xhtml+xml xhtml; + application/xspf+xml xspf; + application/zip zip; - application/octet-stream bin exe dll; - application/octet-stream deb; - application/octet-stream dmg; - application/octet-stream iso img; - application/octet-stream msi msp msm; + application/octet-stream bin exe dll; + application/octet-stream deb; + application/octet-stream dmg; + application/octet-stream iso img; + application/octet-stream msi msp msm; - application/vnd.openxmlformats-officedocument.wordprocessingml.document docx; - application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx; - application/vnd.openxmlformats-officedocument.presentationml.presentation pptx; + audio/midi mid midi kar; + audio/mpeg mp3; + audio/ogg ogg; + audio/x-m4a m4a; + audio/x-realaudio ra; - audio/midi mid midi kar; - audio/mpeg mp3; - audio/ogg ogg; - audio/x-m4a m4a; - audio/x-realaudio ra; - - video/3gpp 3gpp 3gp; - video/mp2t ts; - video/mp4 mp4; - video/mpeg mpeg mpg; - video/quicktime mov; - video/webm webm; - video/x-flv flv; - video/x-m4v m4v; - video/x-mng mng; - video/x-ms-asf asx asf; - video/x-ms-wmv wmv; - video/x-msvideo avi; + video/3gpp 3gpp 3gp; + video/mp2t ts; + video/mp4 mp4; + video/mpeg mpeg mpg; + video/quicktime mov; + video/webm webm; + video/x-flv flv; + video/x-m4v m4v; + video/x-mng mng; + video/x-ms-asf asx asf; + video/x-ms-wmv wmv; + video/x-msvideo avi; } diff --git a/src/core/nginx.h b/src/core/nginx.h index a3c0ef8..5806837 100644 --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1013005 -#define NGINX_VERSION "1.13.5" +#define nginx_version 1013006 +#define NGINX_VERSION "1.13.6" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c index 392fc35..9a74758 100644 --- a/src/core/ngx_connection.c +++ b/src/core/ngx_connection.c @@ -165,6 +165,10 @@ ngx_set_inherited_sockets(ngx_cycle_t *cycle) continue; } + if (ls[i].socklen > (socklen_t) sizeof(ngx_sockaddr_t)) { + ls[i].socklen = sizeof(ngx_sockaddr_t); + } + switch (ls[i].sockaddr->sa_family) { #if (NGX_HAVE_INET6) diff --git a/src/core/ngx_inet.c b/src/core/ngx_inet.c index 3bcd3e7..db48b93 100644 --- a/src/core/ngx_inet.c +++ b/src/core/ngx_inet.c @@ -182,9 +182,11 @@ ngx_sock_ntop(struct sockaddr *sa, socklen_t socklen, u_char *text, size_t len, ngx_uint_t port) { u_char *p; +#if (NGX_HAVE_INET6 || NGX_HAVE_UNIX_DOMAIN) + size_t n; +#endif struct sockaddr_in *sin; #if (NGX_HAVE_INET6) - size_t n; struct sockaddr_in6 *sin6; #endif #if (NGX_HAVE_UNIX_DOMAIN) @@ -241,7 +243,9 @@ ngx_sock_ntop(struct sockaddr *sa, socklen_t socklen, u_char *text, size_t len, p = ngx_snprintf(text, len, "unix:%Z"); } else { - p = ngx_snprintf(text, len, "unix:%s%Z", saun->sun_path); + n = ngx_strnlen((u_char *) saun->sun_path, + socklen - offsetof(struct sockaddr_un, sun_path)); + p = ngx_snprintf(text, len, "unix:%*s%Z", n, saun->sun_path); } /* we do not include trailing zero in address length */ diff --git a/src/core/ngx_inet.h b/src/core/ngx_inet.h index 538771e..a3b392e 100644 --- a/src/core/ngx_inet.h +++ b/src/core/ngx_inet.h @@ -17,10 +17,11 @@ #define NGX_INET6_ADDRSTRLEN \ (sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") - 1) #define NGX_UNIX_ADDRSTRLEN \ - (sizeof(struct sockaddr_un) - offsetof(struct sockaddr_un, sun_path)) + (sizeof("unix:") - 1 + \ + sizeof(struct sockaddr_un) - offsetof(struct sockaddr_un, sun_path)) #if (NGX_HAVE_UNIX_DOMAIN) -#define NGX_SOCKADDR_STRLEN (sizeof("unix:") - 1 + NGX_UNIX_ADDRSTRLEN) +#define NGX_SOCKADDR_STRLEN NGX_UNIX_ADDRSTRLEN #elif (NGX_HAVE_INET6) #define NGX_SOCKADDR_STRLEN (NGX_INET6_ADDRSTRLEN + sizeof("[]:65535") - 1) #else diff --git a/src/core/ngx_parse_time.c b/src/core/ngx_parse_time.c index a5c5034..232ac91 100644 --- a/src/core/ngx_parse_time.c +++ b/src/core/ngx_parse_time.c @@ -44,14 +44,15 @@ ngx_parse_http_time(u_char *value, size_t len) } } - for (p++; p < end; p++) + for (p++; p < end; p++) { if (*p != ' ') { break; } + } if (end - p < 18) { return NGX_ERROR; - } + } if (fmt != isoc) { if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9') { diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c index de10a06..2ee07bf 100644 --- a/src/core/ngx_string.c +++ b/src/core/ngx_string.c @@ -29,6 +29,22 @@ ngx_strlow(u_char *dst, u_char *src, size_t n) } +size_t +ngx_strnlen(u_char *p, size_t n) +{ + size_t i; + + for (i = 0; i < n; i++) { + + if (p[i] == '\0') { + return i; + } + } + + return n; +} + + u_char * ngx_cpystrn(u_char *dst, u_char *src, size_t n) { diff --git a/src/core/ngx_string.h b/src/core/ngx_string.h index 7363bd2..882ae7c 100644 --- a/src/core/ngx_string.h +++ b/src/core/ngx_string.h @@ -60,6 +60,8 @@ void ngx_strlow(u_char *dst, u_char *src, size_t n); #define ngx_strstr(s1, s2) strstr((const char *) s1, (const char *) s2) #define ngx_strlen(s) strlen((const char *) s) +size_t ngx_strnlen(u_char *p, size_t n); + #define ngx_strchr(s1, c) strchr((const char *) s1, (int) c) static ngx_inline u_char * diff --git a/src/core/ngx_times.c b/src/core/ngx_times.c index 843314a..b2edf1a 100644 --- a/src/core/ngx_times.c +++ b/src/core/ngx_times.c @@ -300,27 +300,39 @@ void ngx_gmtime(time_t t, ngx_tm_t *tp) { ngx_int_t yday; - ngx_uint_t n, sec, min, hour, mday, mon, year, wday, days, leap; + ngx_uint_t sec, min, hour, mday, mon, year, wday, days, leap; /* the calculation is valid for positive time_t only */ - n = (ngx_uint_t) t; + if (t < 0) { + t = 0; + } - days = n / 86400; + days = t / 86400; + sec = t % 86400; + + /* + * no more than 4 year digits supported, + * truncate to December 31, 9999, 23:59:59 + */ + + if (days > 2932896) { + days = 2932896; + sec = 86399; + } /* January 1, 1970 was Thursday */ wday = (4 + days) % 7; - n %= 86400; - hour = n / 3600; - n %= 3600; - min = n / 60; - sec = n % 60; + hour = sec / 3600; + sec %= 3600; + min = sec / 60; + sec %= 60; /* * the algorithm based on Gauss' formula, - * see src/http/ngx_http_parse_time.c + * see src/core/ngx_parse_time.c */ /* days since March 1, 1 BC */ diff --git a/src/event/ngx_event_accept.c b/src/event/ngx_event_accept.c index 87447d0..7756370 100644 --- a/src/event/ngx_event_accept.c +++ b/src/event/ngx_event_accept.c @@ -164,6 +164,10 @@ ngx_event_accept(ngx_event_t *ev) return; } + if (socklen > (socklen_t) sizeof(ngx_sockaddr_t)) { + socklen = sizeof(ngx_sockaddr_t); + } + c->sockaddr = ngx_palloc(c->pool, socklen); if (c->sockaddr == NULL) { ngx_close_accepted_connection(c); @@ -440,6 +444,10 @@ ngx_event_recvmsg(ngx_event_t *ev) c->type = SOCK_DGRAM; c->socklen = msg.msg_namelen; + if (c->socklen > (socklen_t) sizeof(ngx_sockaddr_t)) { + c->socklen = sizeof(ngx_sockaddr_t); + } + #if (NGX_STAT_STUB) (void) ngx_atomic_fetch_add(ngx_stat_active, 1); #endif diff --git a/src/http/modules/ngx_http_auth_basic_module.c b/src/http/modules/ngx_http_auth_basic_module.c index 4aa684f..2f345b6 100644 --- a/src/http/modules/ngx_http_auth_basic_module.c +++ b/src/http/modules/ngx_http_auth_basic_module.c @@ -14,11 +14,6 @@ #define NGX_HTTP_AUTH_BUF_SIZE 2048 -typedef struct { - ngx_str_t passwd; -} ngx_http_auth_basic_ctx_t; - - typedef struct { ngx_http_complex_value_t *realm; ngx_http_complex_value_t user_file; @@ -27,7 +22,7 @@ typedef struct { static ngx_int_t ngx_http_auth_basic_handler(ngx_http_request_t *r); static ngx_int_t ngx_http_auth_basic_crypt_handler(ngx_http_request_t *r, - ngx_http_auth_basic_ctx_t *ctx, ngx_str_t *passwd, ngx_str_t *realm); + ngx_str_t *passwd, ngx_str_t *realm); static ngx_int_t ngx_http_auth_basic_set_realm(ngx_http_request_t *r, ngx_str_t *realm); static void ngx_http_auth_basic_close(ngx_file_t *file); @@ -103,7 +98,6 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r) 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; ngx_http_auth_basic_loc_conf_t *alcf; u_char buf[NGX_HTTP_AUTH_BUF_SIZE]; enum { @@ -126,13 +120,6 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r) return NGX_DECLINED; } - ctx = ngx_http_get_module_ctx(r, ngx_http_auth_basic_module); - - if (ctx) { - return ngx_http_auth_basic_crypt_handler(r, ctx, &ctx->passwd, - &realm); - } - rc = ngx_http_auth_basic_user(r); if (rc == NGX_DECLINED) { @@ -237,8 +224,7 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r) pwd.len = i - passwd; pwd.data = &buf[passwd]; - return ngx_http_auth_basic_crypt_handler(r, NULL, &pwd, - &realm); + return ngx_http_auth_basic_crypt_handler(r, &pwd, &realm); } break; @@ -276,7 +262,7 @@ 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, &realm); + return ngx_http_auth_basic_crypt_handler(r, &pwd, &realm); } ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, @@ -288,8 +274,8 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r) static ngx_int_t -ngx_http_auth_basic_crypt_handler(ngx_http_request_t *r, - ngx_http_auth_basic_ctx_t *ctx, ngx_str_t *passwd, ngx_str_t *realm) +ngx_http_auth_basic_crypt_handler(ngx_http_request_t *r, ngx_str_t *passwd, + ngx_str_t *realm) { ngx_int_t rc; u_char *encrypted; @@ -301,48 +287,22 @@ ngx_http_auth_basic_crypt_handler(ngx_http_request_t *r, "rc: %i user: \"%V\" salt: \"%s\"", rc, &r->headers_in.user, passwd->data); - if (rc == NGX_OK) { - if (ngx_strcmp(encrypted, passwd->data) == 0) { - return NGX_OK; - } - - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "encrypted: \"%s\"", encrypted); - - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "user \"%V\": password mismatch", - &r->headers_in.user); - - return ngx_http_auth_basic_set_realm(r, realm); - } - - if (rc == NGX_ERROR) { + if (rc != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } - /* rc == NGX_AGAIN */ - - if (ctx == NULL) { - ctx = ngx_palloc(r->pool, sizeof(ngx_http_auth_basic_ctx_t)); - if (ctx == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - ngx_http_set_ctx(r, ctx, ngx_http_auth_basic_module); - - ctx->passwd.len = passwd->len; - passwd->len++; - - ctx->passwd.data = ngx_pstrdup(r->pool, passwd); - if (ctx->passwd.data == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - + if (ngx_strcmp(encrypted, passwd->data) == 0) { + return NGX_OK; } - /* TODO: add mutex event */ + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "encrypted: \"%s\"", encrypted); - return rc; + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "user \"%V\": password mismatch", + &r->headers_in.user); + + return ngx_http_auth_basic_set_realm(r, realm); } diff --git a/src/http/modules/ngx_http_upstream_hash_module.c b/src/http/modules/ngx_http_upstream_hash_module.c index 6c28c64..d67f34d 100644 --- a/src/http/modules/ngx_http_upstream_hash_module.c +++ b/src/http/modules/ngx_http_upstream_hash_module.c @@ -503,6 +503,11 @@ ngx_http_upstream_get_chash_peer(ngx_peer_connection_t *pc, void *data) ngx_http_upstream_rr_peers_wlock(hp->rrp.peers); + if (hp->tries > 20 || hp->rrp.peers->single) { + ngx_http_upstream_rr_peers_unlock(hp->rrp.peers); + return hp->get_rr_peer(pc, &hp->rrp); + } + pc->cached = 0; pc->connection = NULL; @@ -538,13 +543,6 @@ ngx_http_upstream_get_chash_peer(ngx_peer_connection_t *pc, void *data) continue; } - if (peer->server.len != server->len - || ngx_strncmp(peer->server.data, server->data, server->len) - != 0) - { - continue; - } - if (peer->max_fails && peer->fails >= peer->max_fails && now - peer->checked <= peer->fail_timeout) @@ -556,6 +554,13 @@ ngx_http_upstream_get_chash_peer(ngx_peer_connection_t *pc, void *data) continue; } + if (peer->server.len != server->len + || ngx_strncmp(peer->server.data, server->data, server->len) + != 0) + { + continue; + } + peer->current_weight += peer->effective_weight; total += peer->effective_weight; @@ -577,10 +582,9 @@ ngx_http_upstream_get_chash_peer(ngx_peer_connection_t *pc, void *data) hp->hash++; hp->tries++; - if (hp->tries >= points->number) { - pc->name = hp->rrp.peers->name; + if (hp->tries > 20) { ngx_http_upstream_rr_peers_unlock(hp->rrp.peers); - return NGX_BUSY; + return hp->get_rr_peer(pc, &hp->rrp); } } diff --git a/src/http/modules/ngx_http_upstream_zone_module.c b/src/http/modules/ngx_http_upstream_zone_module.c index d340b48..3229cfe 100644 --- a/src/http/modules/ngx_http_upstream_zone_module.c +++ b/src/http/modules/ngx_http_upstream_zone_module.c @@ -281,7 +281,7 @@ ngx_http_upstream_zone_copy_peer(ngx_http_upstream_rr_peers_t *peers, dst->server.data = NULL; } - dst->sockaddr = ngx_slab_calloc_locked(pool, NGX_SOCKADDRLEN); + dst->sockaddr = ngx_slab_calloc_locked(pool, sizeof(ngx_sockaddr_t)); if (dst->sockaddr == NULL) { goto failed; } diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c index 73a5882..2ea521b 100644 --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -582,6 +582,9 @@ ngx_http_upstream_init_request(ngx_http_request_t *r) if (rc == NGX_HTTP_UPSTREAM_INVALID_HEADER) { rc = NGX_DECLINED; r->cached = 0; + u->buffer.start = NULL; + u->cache_status = NGX_HTTP_CACHE_MISS; + u->request_sent = 1; } if (ngx_http_upstream_cache_background_update(r, u) != NGX_OK) { @@ -1059,8 +1062,16 @@ ngx_http_upstream_cache_send(ngx_http_request_t *r, ngx_http_upstream_t *u) return NGX_ERROR; } + if (rc == NGX_AGAIN) { + rc = NGX_HTTP_UPSTREAM_INVALID_HEADER; + } + /* rc == NGX_HTTP_UPSTREAM_INVALID_HEADER */ + ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0, + "cache file \"%s\" contains invalid header", + c->file.name.data); + /* TODO: delete file */ return rc; @@ -2393,9 +2404,20 @@ ngx_http_upstream_test_next(ngx_http_request_t *r, ngx_http_upstream_t *u) rc = u->reinit_request(r); - if (rc == NGX_OK) { - u->cache_status = NGX_HTTP_CACHE_STALE; - rc = ngx_http_upstream_cache_send(r, u); + if (rc != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, rc); + return NGX_OK; + } + + u->cache_status = NGX_HTTP_CACHE_STALE; + rc = ngx_http_upstream_cache_send(r, u); + + if (rc == NGX_DONE) { + return NGX_OK; + } + + if (rc == NGX_HTTP_UPSTREAM_INVALID_HEADER) { + rc = NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_http_upstream_finalize_request(r, u, rc); @@ -2433,6 +2455,14 @@ ngx_http_upstream_test_next(ngx_http_request_t *r, ngx_http_upstream_t *u) u->cache_status = NGX_HTTP_CACHE_REVALIDATED; rc = ngx_http_upstream_cache_send(r, u); + if (rc == NGX_DONE) { + return NGX_OK; + } + + if (rc == NGX_HTTP_UPSTREAM_INVALID_HEADER) { + rc = NGX_HTTP_INTERNAL_SERVER_ERROR; + } + if (valid == 0) { valid = r->cache->valid_sec; updating = r->cache->updating_sec; @@ -2518,13 +2548,23 @@ ngx_http_upstream_intercept_errors(ngx_http_request_t *r, #if (NGX_HTTP_CACHE) if (r->cache) { - time_t valid; - valid = ngx_http_file_cache_valid(u->conf->cache_valid, status); + if (u->cacheable) { + time_t valid; - if (valid) { - r->cache->valid_sec = ngx_time() + valid; - r->cache->error = status; + valid = r->cache->valid_sec; + + if (valid == 0) { + valid = ngx_http_file_cache_valid(u->conf->cache_valid, + status); + if (valid) { + r->cache->valid_sec = ngx_time() + valid; + } + } + + if (valid) { + r->cache->error = status; + } } ngx_http_file_cache_free(r->cache, u->pipe->temp_file); @@ -4129,9 +4169,20 @@ ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u, rc = u->reinit_request(r); - if (rc == NGX_OK) { - u->cache_status = NGX_HTTP_CACHE_STALE; - rc = ngx_http_upstream_cache_send(r, u); + if (rc != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, rc); + return; + } + + u->cache_status = NGX_HTTP_CACHE_STALE; + rc = ngx_http_upstream_cache_send(r, u); + + if (rc == NGX_DONE) { + return; + } + + if (rc == NGX_HTTP_UPSTREAM_INVALID_HEADER) { + rc = NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_http_upstream_finalize_request(r, u, rc); diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h index c552ac0..3e714e5 100644 --- a/src/http/ngx_http_upstream.h +++ b/src/http/ngx_http_upstream.h @@ -98,8 +98,8 @@ typedef struct { ngx_uint_t max_fails; time_t fail_timeout; ngx_msec_t slow_start; + ngx_uint_t down; - unsigned down:1; unsigned backup:1; NGX_COMPAT_BEGIN(6) diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c index afeb4ce..ab82177 100644 --- a/src/http/ngx_http_variables.c +++ b/src/http/ngx_http_variables.c @@ -1240,6 +1240,18 @@ ngx_http_variable_binary_remote_addr(ngx_http_request_t *r, break; #endif +#if (NGX_HAVE_UNIX_DOMAIN) + case AF_UNIX: + + v->len = r->connection->addr_text.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = r->connection->addr_text.data; + + break; +#endif + default: /* AF_INET */ sin = (struct sockaddr_in *) r->connection->sockaddr; diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c index 7725616..2c62190 100644 --- a/src/http/v2/ngx_http_v2.c +++ b/src/http/v2/ngx_http_v2.c @@ -245,6 +245,8 @@ ngx_http_v2_init(ngx_event_t *rev) h2c->frame_size = NGX_HTTP_V2_DEFAULT_FRAME_SIZE; + h2c->table_update = 1; + h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); h2c->pool = ngx_create_pool(h2scf->pool_size, h2c->connection->log); @@ -746,7 +748,7 @@ ngx_http_v2_state_head(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end) type = ngx_http_v2_parse_type(head); ngx_log_debug4(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "process http2 frame type:%ui f:%Xd l:%uz sid:%ui", + "http2 frame type:%ui f:%Xd l:%uz sid:%ui", type, h2c->state.flags, h2c->state.length, h2c->state.sid); if (type >= NGX_HTTP_V2_FRAME_STATES) { @@ -1314,7 +1316,7 @@ ngx_http_v2_state_field_len(ngx_http_v2_connection_t *h2c, u_char *pos, } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "http2 hpack %s string length: %i", + "http2 %s string, len:%i", huff ? "encoded" : "raw", len); h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, @@ -1569,7 +1571,7 @@ ngx_http_v2_state_process_header(ngx_http_v2_connection_t *h2c, u_char *pos, if (rc == NGX_OK) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http2 pseudo-header: \":%V: %V\"", + "http2 header: \":%V: %V\"", &header->name, &header->value); return ngx_http_v2_state_header_complete(h2c, pos, end); @@ -1645,7 +1647,7 @@ ngx_http_v2_state_process_header(ngx_http_v2_connection_t *h2c, u_char *pos, } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http2 http header: \"%V: %V\"", + "http2 header: \"%V: %V\"", &header->name, &header->value); return ngx_http_v2_state_header_complete(h2c, pos, end); @@ -3335,6 +3337,19 @@ ngx_http_v2_construct_request_line(ngx_http_request_t *r) || r->schema_start == NULL || r->unparsed_uri.len == 0) { + if (r->method_name.len == 0) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent no :method header"); + + } else if (r->schema_start == NULL) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent no :schema header"); + + } else { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent no :path header"); + } + ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); return NGX_ERROR; } @@ -3360,7 +3375,7 @@ ngx_http_v2_construct_request_line(ngx_http_request_t *r) ngx_memcpy(p, ending, sizeof(ending)); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http2 http request line: \"%V\"", &r->request_line); + "http2 request line: \"%V\"", &r->request_line); return NGX_OK; } @@ -3574,11 +3589,6 @@ ngx_http_v2_read_request_body(ngx_http_request_t *r) 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) { @@ -3679,6 +3689,8 @@ ngx_http_v2_process_request_body(ngx_http_request_t *r, u_char *pos, buf->pos = buf->start = pos; buf->last = buf->end = pos + size; + r->request_body_in_file_only = 1; + } else { if (size > (size_t) (buf->end - buf->last)) { ngx_log_error(NGX_LOG_INFO, fc->log, 0, diff --git a/src/http/v2/ngx_http_v2.h b/src/http/v2/ngx_http_v2.h index 4804658..42e0eb1 100644 --- a/src/http/v2/ngx_http_v2.h +++ b/src/http/v2/ngx_http_v2.h @@ -144,6 +144,7 @@ struct ngx_http_v2_connection_s { unsigned closed_nodes:8; unsigned settings_ack:1; + unsigned table_update:1; unsigned blocked:1; unsigned goaway:1; }; diff --git a/src/http/v2/ngx_http_v2_filter_module.c b/src/http/v2/ngx_http_v2_filter_module.c index 8621e7a..9070785 100644 --- a/src/http/v2/ngx_http_v2_filter_module.c +++ b/src/http/v2/ngx_http_v2_filter_module.c @@ -139,6 +139,7 @@ ngx_http_v2_header_filter(ngx_http_request_t *r) ngx_connection_t *fc; ngx_http_cleanup_t *cln; ngx_http_v2_out_frame_t *frame; + ngx_http_v2_connection_t *h2c; ngx_http_core_loc_conf_t *clcf; ngx_http_core_srv_conf_t *cscf; u_char addr[NGX_SOCKADDR_STRLEN]; @@ -235,7 +236,11 @@ ngx_http_v2_header_filter(ngx_http_request_t *r) } } - len = status ? 1 : 1 + ngx_http_v2_literal_size("418"); + h2c = r->stream->connection; + + len = h2c->table_update ? 1 : 0; + + len += status ? 1 : 1 + ngx_http_v2_literal_size("418"); clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); @@ -423,6 +428,13 @@ ngx_http_v2_header_filter(ngx_http_request_t *r) start = pos; + if (h2c->table_update) { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0, + "http2 table size update: 0"); + *pos++ = (1 << 5) | 0; + h2c->table_update = 0; + } + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0, "http2 output header: \":status: %03ui\"", r->headers_out.status); @@ -1257,7 +1269,7 @@ ngx_http_v2_flow_control(ngx_http_v2_connection_t *h2c, ngx_http_v2_stream_t *stream) { ngx_log_debug3(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "http2:%ui available windows: conn:%uz stream:%z", + "http2:%ui windows: conn:%uz stream:%z", stream->node->id, h2c->send_window, stream->send_window); if (stream->send_window <= 0) { diff --git a/src/http/v2/ngx_http_v2_table.c b/src/http/v2/ngx_http_v2_table.c index a73748a..62025c4 100644 --- a/src/http/v2/ngx_http_v2_table.c +++ b/src/http/v2/ngx_http_v2_table.c @@ -102,7 +102,7 @@ ngx_http_v2_get_indexed_header(ngx_http_v2_connection_t *h2c, ngx_uint_t index, ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, "http2 get indexed %s: %ui", - name_only ? "header" : "header name", index); + name_only ? "name" : "header", index); index--; @@ -180,7 +180,7 @@ ngx_http_v2_add_header(ngx_http_v2_connection_t *h2c, ngx_http_v2_header_t *entry, **entries; ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "http2 add header to hpack table: \"%V: %V\"", + "http2 table add: \"%V: %V\"", &header->name, &header->value); if (h2c->hpack.entries == NULL) { @@ -293,7 +293,7 @@ ngx_http_v2_table_account(ngx_http_v2_connection_t *h2c, size_t size) size += 32; ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "http2 hpack table account: %uz free:%uz", + "http2 table account: %uz free:%uz", size, h2c->hpack.free); if (size <= h2c->hpack.free) { diff --git a/src/os/unix/ngx_user.c b/src/os/unix/ngx_user.c index 27c76ef..7ebe2b5 100644 --- a/src/os/unix/ngx_user.c +++ b/src/os/unix/ngx_user.c @@ -9,16 +9,6 @@ #include -/* - * Solaris has thread-safe crypt() - * Linux has crypt_r(); "struct crypt_data" is more than 128K - * FreeBSD needs the mutex to protect crypt() - * - * TODO: - * ngx_crypt_init() to init mutex - */ - - #if (NGX_CRYPT) #if (NGX_HAVE_GNU_CRYPT_R) diff --git a/src/stream/ngx_stream_proxy_module.c b/src/stream/ngx_stream_proxy_module.c index 0afde1c..9d4b075 100644 --- a/src/stream/ngx_stream_proxy_module.c +++ b/src/stream/ngx_stream_proxy_module.c @@ -1331,13 +1331,17 @@ ngx_stream_proxy_process_connection(ngx_event_t *ev, ngx_uint_t from_upstream) return; } + ngx_connection_error(pc, NGX_ETIMEDOUT, "upstream timed out"); + if (u->received == 0) { ngx_stream_proxy_next_upstream(s); return; } + + } else { + ngx_connection_error(c, NGX_ETIMEDOUT, "connection timed out"); } - ngx_connection_error(c, NGX_ETIMEDOUT, "connection timed out"); ngx_stream_proxy_finalize(s, NGX_STREAM_OK); return; } @@ -1665,13 +1669,17 @@ ngx_stream_proxy_next_upstream(ngx_stream_session_t *s) u = s->upstream; pc = u->peer.connection; - if (u->upstream_out || u->upstream_busy || (pc && pc->buffered)) { + if (pc && pc->buffered) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, - "pending buffers on next upstream"); + "buffered data on next upstream"); ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return; } + if (s->connection->type == SOCK_DGRAM) { + u->upstream_out = NULL; + } + if (u->peer.sockaddr) { u->peer.free(&u->peer, u->peer.data, NGX_PEER_FAILED); u->peer.sockaddr = NULL; diff --git a/src/stream/ngx_stream_upstream.h b/src/stream/ngx_stream_upstream.h index 90076e0..73947f4 100644 --- a/src/stream/ngx_stream_upstream.h +++ b/src/stream/ngx_stream_upstream.h @@ -58,8 +58,8 @@ typedef struct { ngx_uint_t max_fails; time_t fail_timeout; ngx_msec_t slow_start; + ngx_uint_t down; - unsigned down:1; unsigned backup:1; NGX_COMPAT_BEGIN(4) diff --git a/src/stream/ngx_stream_upstream_hash_module.c b/src/stream/ngx_stream_upstream_hash_module.c index cb44fcd..79ad742 100644 --- a/src/stream/ngx_stream_upstream_hash_module.c +++ b/src/stream/ngx_stream_upstream_hash_module.c @@ -505,6 +505,11 @@ ngx_stream_upstream_get_chash_peer(ngx_peer_connection_t *pc, void *data) ngx_stream_upstream_rr_peers_wlock(hp->rrp.peers); + if (hp->tries > 20 || hp->rrp.peers->single) { + ngx_stream_upstream_rr_peers_unlock(hp->rrp.peers); + return hp->get_rr_peer(pc, &hp->rrp); + } + pc->connection = NULL; now = ngx_time(); @@ -539,13 +544,6 @@ ngx_stream_upstream_get_chash_peer(ngx_peer_connection_t *pc, void *data) continue; } - if (peer->server.len != server->len - || ngx_strncmp(peer->server.data, server->data, server->len) - != 0) - { - continue; - } - if (peer->max_fails && peer->fails >= peer->max_fails && now - peer->checked <= peer->fail_timeout) @@ -557,6 +555,13 @@ ngx_stream_upstream_get_chash_peer(ngx_peer_connection_t *pc, void *data) continue; } + if (peer->server.len != server->len + || ngx_strncmp(peer->server.data, server->data, server->len) + != 0) + { + continue; + } + peer->current_weight += peer->effective_weight; total += peer->effective_weight; @@ -578,10 +583,9 @@ ngx_stream_upstream_get_chash_peer(ngx_peer_connection_t *pc, void *data) hp->hash++; hp->tries++; - if (hp->tries >= points->number) { - pc->name = hp->rrp.peers->name; + if (hp->tries > 20) { ngx_stream_upstream_rr_peers_unlock(hp->rrp.peers); - return NGX_BUSY; + return hp->get_rr_peer(pc, &hp->rrp); } } diff --git a/src/stream/ngx_stream_upstream_zone_module.c b/src/stream/ngx_stream_upstream_zone_module.c index 4f72188..80d42fa 100644 --- a/src/stream/ngx_stream_upstream_zone_module.c +++ b/src/stream/ngx_stream_upstream_zone_module.c @@ -278,7 +278,7 @@ ngx_stream_upstream_zone_copy_peer(ngx_stream_upstream_rr_peers_t *peers, dst->server.data = NULL; } - dst->sockaddr = ngx_slab_calloc_locked(pool, NGX_SOCKADDRLEN); + dst->sockaddr = ngx_slab_calloc_locked(pool, sizeof(ngx_sockaddr_t)); if (dst->sockaddr == NULL) { goto failed; } diff --git a/src/stream/ngx_stream_variables.c b/src/stream/ngx_stream_variables.c index 45d6e60..95ae12b 100644 --- a/src/stream/ngx_stream_variables.c +++ b/src/stream/ngx_stream_variables.c @@ -460,7 +460,7 @@ ngx_stream_get_variable(ngx_stream_session_t *s, ngx_str_t *name, static ngx_int_t ngx_stream_variable_binary_remote_addr(ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data) - { +{ struct sockaddr_in *sin; #if (NGX_HAVE_INET6) struct sockaddr_in6 *sin6; @@ -481,6 +481,18 @@ ngx_stream_variable_binary_remote_addr(ngx_stream_session_t *s, break; #endif +#if (NGX_HAVE_UNIX_DOMAIN) + case AF_UNIX: + + v->len = s->connection->addr_text.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = s->connection->addr_text.data; + + break; +#endif + default: /* AF_INET */ sin = (struct sockaddr_in *) s->connection->sockaddr; From 515a80bc0a2ead9c5b7b8c5db9172869c0a0eab9 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Mon, 11 Sep 2017 17:55:23 +0300 Subject: [PATCH 220/600] mod: Normalize module locations Use the package name to infer module location. This will make it easier to script our maintaining tasks. --- debian/copyright | 28 +++++++-------- .../ChangeLog | 0 .../{nginx-auth-pam => http-auth-pam}/LICENSE | 0 .../README.md | 0 .../{nginx-auth-pam => http-auth-pam}/VERSION | 0 .../{nginx-auth-pam => http-auth-pam}/config | 0 .../ngx_http_auth_pam_module.c | 0 .../CHANGES | 0 .../LICENSE | 0 .../README.md | 0 .../TODO.md | 0 .../config | 0 .../ngx_cache_purge_module.c | 0 .../t/proxy1.t | 0 .../t/proxy1_vars.t | 0 .../t/proxy2.t | 0 .../t/proxy2_vars.t | 0 .../README | 0 .../config | 0 .../ngx_http_dav_ext_module.c | 0 .../modules/{nginx-echo => http-echo}/LICENSE | 0 .../{nginx-echo => http-echo}/README.markdown | 0 .../modules/{nginx-echo => http-echo}/config | 0 .../{nginx-echo => http-echo}/src/ddebug.h | 0 .../src/ngx_http_echo_echo.c | 0 .../src/ngx_http_echo_echo.h | 0 .../src/ngx_http_echo_filter.c | 0 .../src/ngx_http_echo_filter.h | 0 .../src/ngx_http_echo_foreach.c | 0 .../src/ngx_http_echo_foreach.h | 0 .../src/ngx_http_echo_handler.c | 0 .../src/ngx_http_echo_handler.h | 0 .../src/ngx_http_echo_location.c | 0 .../src/ngx_http_echo_location.h | 0 .../src/ngx_http_echo_module.c | 0 .../src/ngx_http_echo_module.h | 0 .../src/ngx_http_echo_request_info.c | 0 .../src/ngx_http_echo_request_info.h | 0 .../src/ngx_http_echo_sleep.c | 0 .../src/ngx_http_echo_sleep.h | 0 .../src/ngx_http_echo_subrequest.c | 0 .../src/ngx_http_echo_subrequest.h | 0 .../src/ngx_http_echo_timer.c | 0 .../src/ngx_http_echo_timer.h | 0 .../src/ngx_http_echo_util.c | 0 .../src/ngx_http_echo_util.h | 0 .../src/ngx_http_echo_var.c | 0 .../src/ngx_http_echo_var.h | 0 .../t/abort-parent.t | 0 .../t/blocking-sleep.t | 0 .../t/echo-after-body.t | 0 .../t/echo-before-body.t | 0 .../t/echo-duplicate.t | 0 .../{nginx-echo => http-echo}/t/echo-timer.t | 0 .../{nginx-echo => http-echo}/t/echo.t | 0 .../{nginx-echo => http-echo}/t/exec.t | 0 .../{nginx-echo => http-echo}/t/filter-used.t | 0 .../t/foreach-split.t | 0 .../{nginx-echo => http-echo}/t/gzip.t | 0 .../modules/{nginx-echo => http-echo}/t/if.t | 0 .../{nginx-echo => http-echo}/t/incr.t | 0 .../t/location-async.t | 0 .../{nginx-echo => http-echo}/t/location.t | 0 .../{nginx-echo => http-echo}/t/mixed.t | 0 .../t/request-body.t | 0 .../t/request-info.t | 0 .../{nginx-echo => http-echo}/t/sleep.t | 0 .../{nginx-echo => http-echo}/t/status.t | 0 .../t/subrequest-async.t | 0 .../{nginx-echo => http-echo}/t/subrequest.t | 0 .../{nginx-echo => http-echo}/t/unused.t | 0 .../{nginx-echo => http-echo}/util/build.sh | 0 .../{nginx-echo => http-echo}/util/releng | 0 .../util/wiki2pod.pl | 0 .../valgrind.suppress | 0 .../CHANGELOG.md | 0 .../HACKING.md | 0 .../LICENSE | 0 .../README.rst | 0 .../config | 0 .../nginx-0.6-support.patch | 0 .../ngx_http_fancyindex_module.c | 0 .../t/00-build-artifacts.test | 0 .../t/01-smoke-hasindex.test | 0 .../t/02-smoke-indexisfancy.test | 0 .../t/build-and-run | 0 .../t/has-index.test | 0 .../t/has-index/index.html | 0 .../t/nginx.conf | 0 .../t/preamble | 0 .../{ngx-fancyindex => http-fancyindex}/t/run | 0 .../template.awk | 0 .../template.h | 0 .../template.html | 0 .../README.markdown | 0 .../config | 0 .../src/ddebug.h | 0 .../src/ngx_http_headers_more_filter_module.c | 0 .../src/ngx_http_headers_more_filter_module.h | 0 .../src/ngx_http_headers_more_headers_in.c | 0 .../src/ngx_http_headers_more_headers_in.h | 0 .../src/ngx_http_headers_more_headers_out.c | 0 .../src/ngx_http_headers_more_headers_out.h | 0 .../src/ngx_http_headers_more_util.c | 0 .../src/ngx_http_headers_more_util.h | 0 .../t/bug.t | 0 .../t/builtin.t | 0 .../t/eval.t | 0 .../t/input-conn.t | 0 .../t/input-cookie.t | 0 .../t/input-ua.t | 0 .../t/input.t | 0 .../t/phase.t | 0 .../t/sanity.t | 0 .../t/subrequest.t | 0 .../t/unused.t | 0 .../t/vars.t | 0 .../util/build.sh | 0 .../valgrind.suppress | 0 .../{nginx-lua => http-lua}/README.markdown | 0 debian/modules/{nginx-lua => http-lua}/config | 0 .../doc/HttpLuaModule.wiki | 0 .../dtrace/ngx_lua_provider.d | 0 .../misc/recv-until-pm/Makefile | 0 .../misc/recv-until-pm/lib/RecvUntil.pm | 0 .../misc/recv-until-pm/t/sanity.t | 0 .../src/api/ngx_http_lua_api.h | 0 .../{nginx-lua => http-lua}/src/ddebug.h | 0 .../src/ngx_http_lua_accessby.c | 0 .../src/ngx_http_lua_accessby.h | 0 .../src/ngx_http_lua_api.c | 0 .../src/ngx_http_lua_args.c | 0 .../src/ngx_http_lua_args.h | 0 .../src/ngx_http_lua_balancer.c | 0 .../src/ngx_http_lua_balancer.h | 0 .../src/ngx_http_lua_bodyfilterby.c | 0 .../src/ngx_http_lua_bodyfilterby.h | 0 .../src/ngx_http_lua_cache.c | 0 .../src/ngx_http_lua_cache.h | 0 .../src/ngx_http_lua_capturefilter.c | 0 .../src/ngx_http_lua_capturefilter.h | 0 .../src/ngx_http_lua_clfactory.c | 0 .../src/ngx_http_lua_clfactory.h | 0 .../src/ngx_http_lua_common.h | 0 .../src/ngx_http_lua_config.c | 0 .../src/ngx_http_lua_config.h | 0 .../src/ngx_http_lua_consts.c | 0 .../src/ngx_http_lua_consts.h | 0 .../src/ngx_http_lua_contentby.c | 0 .../src/ngx_http_lua_contentby.h | 0 .../src/ngx_http_lua_control.c | 0 .../src/ngx_http_lua_control.h | 0 .../src/ngx_http_lua_coroutine.c | 0 .../src/ngx_http_lua_coroutine.h | 0 .../src/ngx_http_lua_ctx.c | 0 .../src/ngx_http_lua_ctx.h | 0 .../src/ngx_http_lua_directive.c | 0 .../src/ngx_http_lua_directive.h | 0 .../src/ngx_http_lua_exception.c | 0 .../src/ngx_http_lua_exception.h | 0 .../src/ngx_http_lua_headerfilterby.c | 0 .../src/ngx_http_lua_headerfilterby.h | 0 .../src/ngx_http_lua_headers.c | 0 .../src/ngx_http_lua_headers.h | 0 .../src/ngx_http_lua_headers_in.c | 0 .../src/ngx_http_lua_headers_in.h | 0 .../src/ngx_http_lua_headers_out.c | 0 .../src/ngx_http_lua_headers_out.h | 0 .../src/ngx_http_lua_initby.c | 0 .../src/ngx_http_lua_initby.h | 0 .../src/ngx_http_lua_initworkerby.c | 0 .../src/ngx_http_lua_initworkerby.h | 0 .../src/ngx_http_lua_lex.c | 0 .../src/ngx_http_lua_lex.h | 0 .../src/ngx_http_lua_log.c | 0 .../src/ngx_http_lua_log.h | 0 .../src/ngx_http_lua_log_ringbuf.c | 0 .../src/ngx_http_lua_log_ringbuf.h | 0 .../src/ngx_http_lua_logby.c | 0 .../src/ngx_http_lua_logby.h | 0 .../src/ngx_http_lua_misc.c | 0 .../src/ngx_http_lua_misc.h | 0 .../src/ngx_http_lua_module.c | 0 .../src/ngx_http_lua_ndk.c | 0 .../src/ngx_http_lua_ndk.h | 0 .../src/ngx_http_lua_output.c | 0 .../src/ngx_http_lua_output.h | 0 .../src/ngx_http_lua_pcrefix.c | 0 .../src/ngx_http_lua_pcrefix.h | 0 .../src/ngx_http_lua_phase.c | 0 .../src/ngx_http_lua_phase.h | 0 .../src/ngx_http_lua_probe.h | 0 .../src/ngx_http_lua_regex.c | 0 .../src/ngx_http_lua_regex.h | 0 .../src/ngx_http_lua_req_body.c | 0 .../src/ngx_http_lua_req_body.h | 0 .../src/ngx_http_lua_req_method.c | 0 .../src/ngx_http_lua_req_method.h | 0 .../src/ngx_http_lua_rewriteby.c | 0 .../src/ngx_http_lua_rewriteby.h | 0 .../src/ngx_http_lua_script.c | 0 .../src/ngx_http_lua_script.h | 0 .../src/ngx_http_lua_semaphore.c | 0 .../src/ngx_http_lua_semaphore.h | 0 .../src/ngx_http_lua_setby.c | 0 .../src/ngx_http_lua_setby.h | 0 .../src/ngx_http_lua_shdict.c | 0 .../src/ngx_http_lua_shdict.h | 0 .../src/ngx_http_lua_sleep.c | 0 .../src/ngx_http_lua_sleep.h | 0 .../src/ngx_http_lua_socket_tcp.c | 0 .../src/ngx_http_lua_socket_tcp.h | 0 .../src/ngx_http_lua_socket_udp.c | 0 .../src/ngx_http_lua_socket_udp.h | 0 .../src/ngx_http_lua_ssl.c | 0 .../src/ngx_http_lua_ssl.h | 0 .../src/ngx_http_lua_ssl_certby.c | 0 .../src/ngx_http_lua_ssl_certby.h | 0 .../src/ngx_http_lua_ssl_ocsp.c | 0 .../src/ngx_http_lua_ssl_session_fetchby.c | 0 .../src/ngx_http_lua_ssl_session_fetchby.h | 0 .../src/ngx_http_lua_ssl_session_storeby.c | 0 .../src/ngx_http_lua_ssl_session_storeby.h | 0 .../src/ngx_http_lua_string.c | 0 .../src/ngx_http_lua_string.h | 0 .../src/ngx_http_lua_subrequest.c | 0 .../src/ngx_http_lua_subrequest.h | 0 .../src/ngx_http_lua_time.c | 0 .../src/ngx_http_lua_time.h | 0 .../src/ngx_http_lua_timer.c | 0 .../src/ngx_http_lua_timer.h | 0 .../src/ngx_http_lua_uri.c | 0 .../src/ngx_http_lua_uri.h | 0 .../src/ngx_http_lua_uthread.c | 0 .../src/ngx_http_lua_uthread.h | 0 .../src/ngx_http_lua_util.c | 0 .../src/ngx_http_lua_util.h | 0 .../src/ngx_http_lua_variable.c | 0 .../src/ngx_http_lua_variable.h | 0 .../src/ngx_http_lua_worker.c | 0 .../src/ngx_http_lua_worker.h | 0 .../{nginx-lua => http-lua}/t/.gitignore | 0 .../{nginx-lua => http-lua}/t/000--init.t | 0 .../{nginx-lua => http-lua}/t/000-sanity.t | 0 .../{nginx-lua => http-lua}/t/001-set.t | 0 .../{nginx-lua => http-lua}/t/002-content.t | 0 .../{nginx-lua => http-lua}/t/003-errors.t | 0 .../{nginx-lua => http-lua}/t/004-require.t | 0 .../{nginx-lua => http-lua}/t/005-exit.t | 0 .../{nginx-lua => http-lua}/t/006-escape.t | 0 .../{nginx-lua => http-lua}/t/007-md5.t | 0 .../{nginx-lua => http-lua}/t/008-today.t | 0 .../{nginx-lua => http-lua}/t/009-log.t | 0 .../t/010-request_body.t | 0 .../{nginx-lua => http-lua}/t/011-md5_bin.t | 0 .../{nginx-lua => http-lua}/t/012-now.t | 0 .../{nginx-lua => http-lua}/t/013-base64.t | 0 .../{nginx-lua => http-lua}/t/014-bugs.t | 0 .../{nginx-lua => http-lua}/t/015-status.t | 0 .../t/016-resp-header.t | 0 .../{nginx-lua => http-lua}/t/017-exec.t | 0 .../{nginx-lua => http-lua}/t/018-ndk.t | 0 .../{nginx-lua => http-lua}/t/019-const.t | 0 .../t/020-subrequest.t | 0 .../t/021-cookie-time.t | 0 .../{nginx-lua => http-lua}/t/022-redirect.t | 0 .../t/023-rewrite/client-abort.t | 0 .../t/023-rewrite/exec.t | 0 .../t/023-rewrite/exit.t | 0 .../t/023-rewrite/mixed.t | 0 .../t/023-rewrite/multi-capture.t | 0 .../t/023-rewrite/on-abort.t | 0 .../t/023-rewrite/redirect.t | 0 .../t/023-rewrite/req-body.t | 0 .../t/023-rewrite/req-socket.t | 0 .../t/023-rewrite/request_body.t | 0 .../t/023-rewrite/sanity.t | 0 .../t/023-rewrite/sleep.t | 0 .../t/023-rewrite/socket-keepalive.t | 0 .../t/023-rewrite/subrequest.t | 0 .../t/023-rewrite/tcp-socket-timeout.t | 0 .../t/023-rewrite/tcp-socket.t | 0 .../t/023-rewrite/unix-socket.t | 0 .../t/023-rewrite/uthread-exec.t | 0 .../t/023-rewrite/uthread-exit.t | 0 .../t/023-rewrite/uthread-redirect.t | 0 .../t/023-rewrite/uthread-spawn.t | 0 .../t/024-access/auth.t | 0 .../t/024-access/client-abort.t | 0 .../t/024-access/exec.t | 0 .../t/024-access/exit.t | 0 .../t/024-access/mixed.t | 0 .../t/024-access/multi-capture.t | 0 .../t/024-access/on-abort.t | 0 .../t/024-access/redirect.t | 0 .../t/024-access/req-body.t | 0 .../t/024-access/request_body.t | 0 .../t/024-access/sanity.t | 0 .../t/024-access/satisfy.t | 0 .../t/024-access/sleep.t | 0 .../t/024-access/subrequest.t | 0 .../t/024-access/uthread-exec.t | 0 .../t/024-access/uthread-exit.t | 0 .../t/024-access/uthread-redirect.t | 0 .../t/024-access/uthread-spawn.t | 0 .../{nginx-lua => http-lua}/t/025-codecache.t | 0 .../{nginx-lua => http-lua}/t/026-mysql.t | 0 .../t/027-multi-capture.t | 0 .../t/028-req-header.t | 0 .../{nginx-lua => http-lua}/t/029-http-time.t | 0 .../{nginx-lua => http-lua}/t/030-uri-args.t | 0 .../{nginx-lua => http-lua}/t/031-post-args.t | 0 .../{nginx-lua => http-lua}/t/032-iolist.t | 0 .../{nginx-lua => http-lua}/t/033-ctx.t | 0 .../{nginx-lua => http-lua}/t/034-match.t | 0 .../{nginx-lua => http-lua}/t/035-gmatch.t | 0 .../{nginx-lua => http-lua}/t/036-sub.t | 0 .../{nginx-lua => http-lua}/t/037-gsub.t | 0 .../{nginx-lua => http-lua}/t/038-match-o.t | 0 .../{nginx-lua => http-lua}/t/039-sub-o.t | 0 .../{nginx-lua => http-lua}/t/040-gsub-o.t | 0 .../t/041-header-filter.t | 0 .../{nginx-lua => http-lua}/t/042-crc32.t | 0 .../{nginx-lua => http-lua}/t/043-shdict.t | 0 .../{nginx-lua => http-lua}/t/044-req-body.t | 0 .../{nginx-lua => http-lua}/t/045-ngx-var.t | 0 .../{nginx-lua => http-lua}/t/046-hmac.t | 0 .../{nginx-lua => http-lua}/t/047-match-jit.t | 0 .../{nginx-lua => http-lua}/t/048-match-dfa.t | 0 .../t/049-gmatch-jit.t | 0 .../t/050-gmatch-dfa.t | 0 .../{nginx-lua => http-lua}/t/051-sub-jit.t | 0 .../{nginx-lua => http-lua}/t/052-sub-dfa.t | 0 .../{nginx-lua => http-lua}/t/053-gsub-jit.t | 0 .../{nginx-lua => http-lua}/t/054-gsub-dfa.t | 0 .../t/055-subreq-vars.t | 0 .../{nginx-lua => http-lua}/t/056-flush.t | 0 .../t/057-flush-timeout.t | 0 .../t/058-tcp-socket.t | 0 .../t/059-unix-socket.t | 0 .../t/060-lua-memcached.t | 0 .../{nginx-lua => http-lua}/t/061-lua-redis.t | 0 .../{nginx-lua => http-lua}/t/062-count.t | 0 .../{nginx-lua => http-lua}/t/063-abort.t | 0 .../{nginx-lua => http-lua}/t/064-pcall.t | 0 .../t/065-tcp-socket-timeout.t | 0 .../t/066-socket-receiveuntil.t | 0 .../t/067-req-socket.t | 0 .../t/068-socket-keepalive.t | 0 .../{nginx-lua => http-lua}/t/069-null.t | 0 .../{nginx-lua => http-lua}/t/070-sha1.t | 0 .../t/071-idle-socket.t | 0 .../t/072-conditional-get.t | 0 .../{nginx-lua => http-lua}/t/073-backtrace.t | 0 .../t/074-prefix-var.t | 0 .../{nginx-lua => http-lua}/t/075-logby.t | 0 .../t/076-no-postpone.t | 0 .../{nginx-lua => http-lua}/t/077-sleep.t | 0 .../{nginx-lua => http-lua}/t/078-hup-vars.t | 0 .../t/079-unused-directives.t | 0 .../t/080-hup-shdict.t | 0 .../{nginx-lua => http-lua}/t/081-bytecode.t | 0 .../t/082-body-filter.t | 0 .../t/083-bad-sock-self.t | 0 .../t/084-inclusive-receiveuntil.t | 0 .../{nginx-lua => http-lua}/t/085-if.t | 0 .../{nginx-lua => http-lua}/t/086-init-by.t | 0 .../t/087-udp-socket.t | 0 .../t/088-req-method.t | 0 .../{nginx-lua => http-lua}/t/089-phase.t | 0 .../t/090-log-socket-errors.t | 0 .../{nginx-lua => http-lua}/t/091-coroutine.t | 0 .../{nginx-lua => http-lua}/t/092-eof.t | 0 .../t/093-uthread-spawn.t | 0 .../t/094-uthread-exit.t | 0 .../t/095-uthread-exec.t | 0 .../t/096-uthread-redirect.t | 0 .../t/097-uthread-rewrite.t | 0 .../t/098-uthread-wait.t | 0 .../{nginx-lua => http-lua}/t/099-c-api.t | 0 .../t/100-client-abort.t | 0 .../{nginx-lua => http-lua}/t/101-on-abort.t | 0 .../t/102-req-start-time.t | 0 .../t/103-req-http-ver.t | 0 .../t/104-req-raw-header.t | 0 .../{nginx-lua => http-lua}/t/105-pressure.t | 0 .../{nginx-lua => http-lua}/t/106-timer.t | 0 .../t/107-timer-errors.t | 0 .../t/108-timer-safe.t | 0 .../{nginx-lua => http-lua}/t/109-timer-hup.t | 0 .../{nginx-lua => http-lua}/t/110-etag.t | 0 .../t/111-req-header-ua.t | 0 .../t/112-req-header-conn.t | 0 .../t/113-req-header-cookie.t | 0 .../{nginx-lua => http-lua}/t/114-config.t | 0 .../t/115-quote-sql-str.t | 0 .../t/116-raw-req-socket.t | 0 .../t/117-raw-req-socket-timeout.t | 0 .../t/118-use-default-type.t | 0 .../t/119-config-prefix.t | 0 .../{nginx-lua => http-lua}/t/120-re-find.t | 0 .../{nginx-lua => http-lua}/t/121-version.t | 0 .../{nginx-lua => http-lua}/t/122-worker.t | 0 .../{nginx-lua => http-lua}/t/123-lua-path.t | 0 .../t/124-init-worker.t | 0 .../t/125-configure-args.t | 0 .../t/126-shdict-frag.t | 0 .../t/127-uthread-kill.t | 0 .../t/128-duplex-tcp-socket.t | 0 .../t/129-ssl-socket.t | 0 .../t/130-internal-api.t | 0 .../t/131-duplex-req-socket.t | 0 .../t/132-lua-blocks.t | 0 .../t/133-worker-count.t | 0 .../t/134-worker-count-5.t | 0 .../{nginx-lua => http-lua}/t/135-worker-id.t | 0 .../t/136-timer-counts.t | 0 .../{nginx-lua => http-lua}/t/137-req-misc.t | 0 .../{nginx-lua => http-lua}/t/138-balancer.t | 0 .../t/139-ssl-cert-by.t | 0 .../{nginx-lua => http-lua}/t/140-ssl-c-api.t | 0 .../{nginx-lua => http-lua}/t/141-luajit.t | 0 .../t/142-ssl-session-store.t | 0 .../t/143-ssl-session-fetch.t | 0 .../t/144-shdict-incr-init.t | 0 .../t/145-shdict-list.t | 0 .../t/146-malloc-trim.t | 0 .../t/147-tcp-socket-timeouts.t | 0 .../t/148-fake-shm-zone.t | 0 .../t/149-hup-fake-shm-zone.t | 0 .../t/150-fake-delayed-load.t | 0 .../t/151-initby-hup.t | 0 .../t/152-timer-every.t | 0 .../t/153-semaphore-hup.t | 0 .../{nginx-lua => http-lua}/t/154-semaphore.t | 0 .../{nginx-lua => http-lua}/t/StapThread.pm | 0 .../t/cert/comodo-ca.crt | 0 .../t/cert/equifax.crt | 0 .../{nginx-lua => http-lua}/t/cert/test.crl | 0 .../{nginx-lua => http-lua}/t/cert/test.crt | 0 .../{nginx-lua => http-lua}/t/cert/test.key | 0 .../{nginx-lua => http-lua}/t/cert/test2.crt | 0 .../{nginx-lua => http-lua}/t/cert/test2.key | 0 .../t/cert/test_ecdsa.crt | 0 .../t/cert/test_ecdsa.key | 0 .../t/data/fake-delayed-load-module/config | 0 .../ngx_http_lua_fake_delayed_load_module.c | 0 .../t/data/fake-module/config | 0 .../t/data/fake-module/ngx_http_fake_module.c | 0 .../t/data/fake-shm-module/config | 0 .../ngx_http_lua_fake_shm_module.c | 0 .../{nginx-lua => http-lua}/t/lib/CRC32.lua | 0 .../t/lib/Memcached.lua | 0 .../{nginx-lua => http-lua}/t/lib/Redis.lua | 0 .../{nginx-lua => http-lua}/t/lib/ljson.lua | 0 .../tapset/ngx_lua.stp | 0 .../{nginx-lua => http-lua}/util/build.sh | 0 .../{nginx-lua => http-lua}/util/fix-comments | 0 .../{nginx-lua => http-lua}/util/gen-lexer-c | 0 .../{nginx-lua => http-lua}/util/ngx-links | 0 .../{nginx-lua => http-lua}/util/releng | 0 .../{nginx-lua => http-lua}/util/retab | 0 .../{nginx-lua => http-lua}/util/revim | 0 .../{nginx-lua => http-lua}/util/run_test.sh | 0 .../util/update-readme.sh | 0 .../{nginx-lua => http-lua}/valgrind.suppress | 0 .../LICENSE | 0 .../README.md | 0 .../README_AUTO_LIB | 0 .../{nginx-development-kit => http-ndk}/TODO | 0 .../auto/actions/array | 0 .../auto/actions/palloc | 0 .../auto/build | 0 .../auto/data/action_replacements | 0 .../auto/data/action_types | 0 .../auto/data/conf_args | 0 .../auto/data/conf_locs | 0 .../auto/data/conf_macros | 0 .../auto/data/contexts | 0 .../auto/data/header_files | 0 .../auto/data/headers | 0 .../auto/data/module_dependencies | 0 .../auto/data/modules_optional | 0 .../auto/data/prefixes | 0 .../auto/src/array.h | 0 .../auto/src/conf_cmd_basic.h | 0 .../auto/src/conf_merge.h | 0 .../auto/src/palloc.h | 0 .../auto/text/autogen | 0 .../config | 0 .../docs/core/action_macros | 0 .../docs/core/conf_cmds | 0 .../docs/modules/set_var | 0 .../docs/patches/more_logging_info | 0 .../docs/upstream/list | 0 .../examples/README | 0 .../examples/http/set_var/config | 0 .../ngx_http_set_var_examples_module.c | 0 .../ngx_auto_lib_core | 0 .../notes/CHANGES | 0 .../notes/LICENSE | 0 .../objs/ndk_array.h | 0 .../objs/ndk_conf_cmd_basic.h | 0 .../objs/ndk_conf_cmd_extra.h | 0 .../objs/ndk_conf_merge.h | 0 .../objs/ndk_config.c | 0 .../objs/ndk_config.h | 0 .../objs/ndk_includes.h | 0 .../objs/ndk_palloc.h | 0 .../patches/auto_config | 0 .../patches/expose_rewrite_functions | 0 .../patches/rewrite_phase_handler | 0 .../src/hash/md5.h | 0 .../src/hash/murmurhash2.c | 0 .../src/hash/sha.h | 0 .../src/ndk.c | 0 .../src/ndk.h | 0 .../src/ndk_buf.c | 0 .../src/ndk_buf.h | 0 .../src/ndk_complex_path.c | 0 .../src/ndk_complex_path.h | 0 .../src/ndk_complex_value.c | 0 .../src/ndk_complex_value.h | 0 .../src/ndk_conf_file.c | 0 .../src/ndk_conf_file.h | 0 .../src/ndk_debug.c | 0 .../src/ndk_debug.h | 0 .../src/ndk_encoding.c | 0 .../src/ndk_encoding.h | 0 .../src/ndk_hash.c | 0 .../src/ndk_hash.h | 0 .../src/ndk_http.c | 0 .../src/ndk_http.h | 0 .../src/ndk_http_headers.h | 0 .../src/ndk_log.c | 0 .../src/ndk_log.h | 0 .../src/ndk_parse.h | 0 .../src/ndk_path.c | 0 .../src/ndk_path.h | 0 .../src/ndk_process.c | 0 .../src/ndk_process.h | 0 .../src/ndk_regex.c | 0 .../src/ndk_regex.h | 0 .../src/ndk_rewrite.c | 0 .../src/ndk_rewrite.h | 0 .../src/ndk_set_var.c | 0 .../src/ndk_set_var.h | 0 .../src/ndk_string.c | 0 .../src/ndk_string.h | 0 .../src/ndk_string_util.h | 0 .../src/ndk_upstream_list.c | 0 .../src/ndk_upstream_list.h | 0 .../src/ndk_uri.c | 0 .../src/ndk_uri.h | 0 .../CHANGES | 0 .../README | 0 .../config | 0 .../doc/README.google_code_home_page.wiki | 0 .../doc/README.html | 0 .../doc/README.wiki | 0 .../ngx_http_subs_filter_module.c | 0 .../test/README | 0 .../test/inc/Module/AutoInstall.pm | 0 .../test/inc/Module/Install.pm | 0 .../test/inc/Module/Install/AutoInstall.pm | 0 .../test/inc/Module/Install/Base.pm | 0 .../test/inc/Module/Install/Can.pm | 0 .../test/inc/Module/Install/Fetch.pm | 0 .../test/inc/Module/Install/Include.pm | 0 .../test/inc/Module/Install/Makefile.pm | 0 .../test/inc/Module/Install/Metadata.pm | 0 .../test/inc/Module/Install/TestBase.pm | 0 .../test/inc/Module/Install/Win32.pm | 0 .../test/inc/Module/Install/WriteAll.pm | 0 .../test/inc/Spiffy.pm | 0 .../test/inc/Test/Base.pm | 0 .../test/inc/Test/Base/Filter.pm | 0 .../test/inc/Test/Builder.pm | 0 .../test/inc/Test/Builder/Module.pm | 0 .../test/inc/Test/More.pm | 0 .../test/lib/Test/Nginx.pm | 0 .../test/lib/Test/Nginx/LWP.pm | 0 .../test/lib/Test/Nginx/Socket.pm | 0 .../test/lib/Test/Nginx/Util.pm | 0 .../test/t/subs.t | 0 .../test/t/subs_capture.t | 0 .../test/t/subs_fix_string.t | 0 .../test/t/subs_regex.t | 0 .../test/t/subs_types.t | 0 .../test/test.sh | 0 .../util/update-readme.sh | 0 .../util/wiki2google_code_homepage.pl | 0 .../util/wiki2pod.pl | 0 .../CHANGES | 0 .../LICENSE | 0 .../Makefile | 0 .../README | 0 .../config | 0 .../ngx_http_uploadprogress_module.c | 0 .../test/client.sh | 0 .../test/stress.sh | 0 .../.gdbinit | 0 .../README | 0 .../config | 0 .../ngx_http_upstream_fair_module.c | 0 .../dynamic-module.patch | 0 .../segfault-1.11.6.patch | 0 .../series | 0 .../dynamic-module.patch | 0 .../series | 0 .../build-nginx-1.11.11.patch | 0 .../patches/{nginx-echo => http-echo}/series | 0 .../discover-luajit-2.1.patch | 0 .../openssl-1.1.0.patch | 0 .../patches/{nginx-lua => http-lua}/series | 0 .../dynamic-module.patch | 0 .../series | 0 .../drop-default-port.patch | 0 .../dynamic-module.patch | 0 .../openssl-1.1.0.patch | 0 .../series | 0 debian/modules/{nginx-rtmp => rtmp}/AUTHORS | 0 debian/modules/{nginx-rtmp => rtmp}/LICENSE | 0 debian/modules/{nginx-rtmp => rtmp}/README.md | 0 debian/modules/{nginx-rtmp => rtmp}/config | 0 .../dash/ngx_rtmp_dash_module.c | 0 .../{nginx-rtmp => rtmp}/dash/ngx_rtmp_mp4.c | 0 .../{nginx-rtmp => rtmp}/dash/ngx_rtmp_mp4.h | 0 .../{nginx-rtmp => rtmp}/doc/README.md | 0 .../hls/ngx_rtmp_hls_module.c | 0 .../hls/ngx_rtmp_mpegts.c | 0 .../hls/ngx_rtmp_mpegts.h | 0 .../modules/{nginx-rtmp => rtmp}/ngx_rtmp.c | 0 .../modules/{nginx-rtmp => rtmp}/ngx_rtmp.h | 0 .../ngx_rtmp_access_module.c | 0 .../{nginx-rtmp => rtmp}/ngx_rtmp_amf.c | 0 .../{nginx-rtmp => rtmp}/ngx_rtmp_amf.h | 0 .../ngx_rtmp_auto_push_module.c | 0 .../{nginx-rtmp => rtmp}/ngx_rtmp_bandwidth.c | 0 .../{nginx-rtmp => rtmp}/ngx_rtmp_bandwidth.h | 0 .../{nginx-rtmp => rtmp}/ngx_rtmp_bitop.c | 0 .../{nginx-rtmp => rtmp}/ngx_rtmp_bitop.h | 0 .../ngx_rtmp_cmd_module.c | 0 .../ngx_rtmp_cmd_module.h | 0 .../ngx_rtmp_codec_module.c | 0 .../ngx_rtmp_codec_module.h | 0 .../ngx_rtmp_control_module.c | 0 .../ngx_rtmp_core_module.c | 0 .../{nginx-rtmp => rtmp}/ngx_rtmp_eval.c | 0 .../{nginx-rtmp => rtmp}/ngx_rtmp_eval.h | 0 .../ngx_rtmp_exec_module.c | 0 .../ngx_rtmp_flv_module.c | 0 .../{nginx-rtmp => rtmp}/ngx_rtmp_handler.c | 0 .../{nginx-rtmp => rtmp}/ngx_rtmp_handshake.c | 0 .../{nginx-rtmp => rtmp}/ngx_rtmp_init.c | 0 .../ngx_rtmp_limit_module.c | 0 .../ngx_rtmp_live_module.c | 0 .../ngx_rtmp_live_module.h | 0 .../ngx_rtmp_log_module.c | 0 .../ngx_rtmp_mp4_module.c | 0 .../ngx_rtmp_netcall_module.c | 0 .../ngx_rtmp_netcall_module.h | 0 .../ngx_rtmp_notify_module.c | 0 .../ngx_rtmp_play_module.c | 0 .../ngx_rtmp_play_module.h | 0 .../ngx_rtmp_proxy_protocol.c | 0 .../ngx_rtmp_proxy_protocol.h | 0 .../{nginx-rtmp => rtmp}/ngx_rtmp_receive.c | 0 .../ngx_rtmp_record_module.c | 0 .../ngx_rtmp_record_module.h | 0 .../ngx_rtmp_relay_module.c | 0 .../ngx_rtmp_relay_module.h | 0 .../{nginx-rtmp => rtmp}/ngx_rtmp_send.c | 0 .../{nginx-rtmp => rtmp}/ngx_rtmp_shared.c | 0 .../ngx_rtmp_stat_module.c | 0 .../{nginx-rtmp => rtmp}/ngx_rtmp_streams.h | 0 .../{nginx-rtmp => rtmp}/ngx_rtmp_version.h | 0 debian/modules/{nginx-rtmp => rtmp}/stat.xsl | 0 debian/rules | 36 +++++++++---------- 679 files changed, 32 insertions(+), 32 deletions(-) rename debian/modules/{nginx-auth-pam => http-auth-pam}/ChangeLog (100%) rename debian/modules/{nginx-auth-pam => http-auth-pam}/LICENSE (100%) rename debian/modules/{nginx-auth-pam => http-auth-pam}/README.md (100%) rename debian/modules/{nginx-auth-pam => http-auth-pam}/VERSION (100%) rename debian/modules/{nginx-auth-pam => http-auth-pam}/config (100%) rename debian/modules/{nginx-auth-pam => http-auth-pam}/ngx_http_auth_pam_module.c (100%) rename debian/modules/{nginx-cache-purge => http-cache-purge}/CHANGES (100%) rename debian/modules/{nginx-cache-purge => http-cache-purge}/LICENSE (100%) rename debian/modules/{nginx-cache-purge => http-cache-purge}/README.md (100%) rename debian/modules/{nginx-cache-purge => http-cache-purge}/TODO.md (100%) rename debian/modules/{nginx-cache-purge => http-cache-purge}/config (100%) rename debian/modules/{nginx-cache-purge => http-cache-purge}/ngx_cache_purge_module.c (100%) rename debian/modules/{nginx-cache-purge => http-cache-purge}/t/proxy1.t (100%) rename debian/modules/{nginx-cache-purge => http-cache-purge}/t/proxy1_vars.t (100%) rename debian/modules/{nginx-cache-purge => http-cache-purge}/t/proxy2.t (100%) rename debian/modules/{nginx-cache-purge => http-cache-purge}/t/proxy2_vars.t (100%) rename debian/modules/{nginx-dav-ext-module => http-dav-ext}/README (100%) rename debian/modules/{nginx-dav-ext-module => http-dav-ext}/config (100%) rename debian/modules/{nginx-dav-ext-module => http-dav-ext}/ngx_http_dav_ext_module.c (100%) rename debian/modules/{nginx-echo => http-echo}/LICENSE (100%) rename debian/modules/{nginx-echo => http-echo}/README.markdown (100%) rename debian/modules/{nginx-echo => http-echo}/config (100%) rename debian/modules/{nginx-echo => http-echo}/src/ddebug.h (100%) rename debian/modules/{nginx-echo => http-echo}/src/ngx_http_echo_echo.c (100%) rename debian/modules/{nginx-echo => http-echo}/src/ngx_http_echo_echo.h (100%) rename debian/modules/{nginx-echo => http-echo}/src/ngx_http_echo_filter.c (100%) rename debian/modules/{nginx-echo => http-echo}/src/ngx_http_echo_filter.h (100%) rename debian/modules/{nginx-echo => http-echo}/src/ngx_http_echo_foreach.c (100%) rename debian/modules/{nginx-echo => http-echo}/src/ngx_http_echo_foreach.h (100%) rename debian/modules/{nginx-echo => http-echo}/src/ngx_http_echo_handler.c (100%) rename debian/modules/{nginx-echo => http-echo}/src/ngx_http_echo_handler.h (100%) rename debian/modules/{nginx-echo => http-echo}/src/ngx_http_echo_location.c (100%) rename debian/modules/{nginx-echo => http-echo}/src/ngx_http_echo_location.h (100%) rename debian/modules/{nginx-echo => http-echo}/src/ngx_http_echo_module.c (100%) rename debian/modules/{nginx-echo => http-echo}/src/ngx_http_echo_module.h (100%) rename debian/modules/{nginx-echo => http-echo}/src/ngx_http_echo_request_info.c (100%) rename debian/modules/{nginx-echo => http-echo}/src/ngx_http_echo_request_info.h (100%) rename debian/modules/{nginx-echo => http-echo}/src/ngx_http_echo_sleep.c (100%) rename debian/modules/{nginx-echo => http-echo}/src/ngx_http_echo_sleep.h (100%) rename debian/modules/{nginx-echo => http-echo}/src/ngx_http_echo_subrequest.c (100%) rename debian/modules/{nginx-echo => http-echo}/src/ngx_http_echo_subrequest.h (100%) rename debian/modules/{nginx-echo => http-echo}/src/ngx_http_echo_timer.c (100%) rename debian/modules/{nginx-echo => http-echo}/src/ngx_http_echo_timer.h (100%) rename debian/modules/{nginx-echo => http-echo}/src/ngx_http_echo_util.c (100%) rename debian/modules/{nginx-echo => http-echo}/src/ngx_http_echo_util.h (100%) rename debian/modules/{nginx-echo => http-echo}/src/ngx_http_echo_var.c (100%) rename debian/modules/{nginx-echo => http-echo}/src/ngx_http_echo_var.h (100%) rename debian/modules/{nginx-echo => http-echo}/t/abort-parent.t (100%) rename debian/modules/{nginx-echo => http-echo}/t/blocking-sleep.t (100%) rename debian/modules/{nginx-echo => http-echo}/t/echo-after-body.t (100%) rename debian/modules/{nginx-echo => http-echo}/t/echo-before-body.t (100%) rename debian/modules/{nginx-echo => http-echo}/t/echo-duplicate.t (100%) rename debian/modules/{nginx-echo => http-echo}/t/echo-timer.t (100%) rename debian/modules/{nginx-echo => http-echo}/t/echo.t (100%) rename debian/modules/{nginx-echo => http-echo}/t/exec.t (100%) rename debian/modules/{nginx-echo => http-echo}/t/filter-used.t (100%) rename debian/modules/{nginx-echo => http-echo}/t/foreach-split.t (100%) rename debian/modules/{nginx-echo => http-echo}/t/gzip.t (100%) rename debian/modules/{nginx-echo => http-echo}/t/if.t (100%) rename debian/modules/{nginx-echo => http-echo}/t/incr.t (100%) rename debian/modules/{nginx-echo => http-echo}/t/location-async.t (100%) rename debian/modules/{nginx-echo => http-echo}/t/location.t (100%) rename debian/modules/{nginx-echo => http-echo}/t/mixed.t (100%) rename debian/modules/{nginx-echo => http-echo}/t/request-body.t (100%) rename debian/modules/{nginx-echo => http-echo}/t/request-info.t (100%) rename debian/modules/{nginx-echo => http-echo}/t/sleep.t (100%) rename debian/modules/{nginx-echo => http-echo}/t/status.t (100%) rename debian/modules/{nginx-echo => http-echo}/t/subrequest-async.t (100%) rename debian/modules/{nginx-echo => http-echo}/t/subrequest.t (100%) rename debian/modules/{nginx-echo => http-echo}/t/unused.t (100%) rename debian/modules/{nginx-echo => http-echo}/util/build.sh (100%) rename debian/modules/{nginx-echo => http-echo}/util/releng (100%) rename debian/modules/{nginx-echo => http-echo}/util/wiki2pod.pl (100%) rename debian/modules/{nginx-echo => http-echo}/valgrind.suppress (100%) rename debian/modules/{ngx-fancyindex => http-fancyindex}/CHANGELOG.md (100%) rename debian/modules/{ngx-fancyindex => http-fancyindex}/HACKING.md (100%) rename debian/modules/{ngx-fancyindex => http-fancyindex}/LICENSE (100%) rename debian/modules/{ngx-fancyindex => http-fancyindex}/README.rst (100%) rename debian/modules/{ngx-fancyindex => http-fancyindex}/config (100%) rename debian/modules/{ngx-fancyindex => http-fancyindex}/nginx-0.6-support.patch (100%) rename debian/modules/{ngx-fancyindex => http-fancyindex}/ngx_http_fancyindex_module.c (100%) rename debian/modules/{ngx-fancyindex => http-fancyindex}/t/00-build-artifacts.test (100%) rename debian/modules/{ngx-fancyindex => http-fancyindex}/t/01-smoke-hasindex.test (100%) rename debian/modules/{ngx-fancyindex => http-fancyindex}/t/02-smoke-indexisfancy.test (100%) rename debian/modules/{ngx-fancyindex => http-fancyindex}/t/build-and-run (100%) rename debian/modules/{ngx-fancyindex => http-fancyindex}/t/has-index.test (100%) rename debian/modules/{ngx-fancyindex => http-fancyindex}/t/has-index/index.html (100%) rename debian/modules/{ngx-fancyindex => http-fancyindex}/t/nginx.conf (100%) rename debian/modules/{ngx-fancyindex => http-fancyindex}/t/preamble (100%) rename debian/modules/{ngx-fancyindex => http-fancyindex}/t/run (100%) rename debian/modules/{ngx-fancyindex => http-fancyindex}/template.awk (100%) rename debian/modules/{ngx-fancyindex => http-fancyindex}/template.h (100%) rename debian/modules/{ngx-fancyindex => http-fancyindex}/template.html (100%) rename debian/modules/{headers-more-nginx-module => http-headers-more-filter}/README.markdown (100%) rename debian/modules/{headers-more-nginx-module => http-headers-more-filter}/config (100%) rename debian/modules/{headers-more-nginx-module => http-headers-more-filter}/src/ddebug.h (100%) rename debian/modules/{headers-more-nginx-module => http-headers-more-filter}/src/ngx_http_headers_more_filter_module.c (100%) rename debian/modules/{headers-more-nginx-module => http-headers-more-filter}/src/ngx_http_headers_more_filter_module.h (100%) rename debian/modules/{headers-more-nginx-module => http-headers-more-filter}/src/ngx_http_headers_more_headers_in.c (100%) rename debian/modules/{headers-more-nginx-module => http-headers-more-filter}/src/ngx_http_headers_more_headers_in.h (100%) rename debian/modules/{headers-more-nginx-module => http-headers-more-filter}/src/ngx_http_headers_more_headers_out.c (100%) rename debian/modules/{headers-more-nginx-module => http-headers-more-filter}/src/ngx_http_headers_more_headers_out.h (100%) rename debian/modules/{headers-more-nginx-module => http-headers-more-filter}/src/ngx_http_headers_more_util.c (100%) rename debian/modules/{headers-more-nginx-module => http-headers-more-filter}/src/ngx_http_headers_more_util.h (100%) rename debian/modules/{headers-more-nginx-module => http-headers-more-filter}/t/bug.t (100%) rename debian/modules/{headers-more-nginx-module => http-headers-more-filter}/t/builtin.t (100%) rename debian/modules/{headers-more-nginx-module => http-headers-more-filter}/t/eval.t (100%) rename debian/modules/{headers-more-nginx-module => http-headers-more-filter}/t/input-conn.t (100%) rename debian/modules/{headers-more-nginx-module => http-headers-more-filter}/t/input-cookie.t (100%) rename debian/modules/{headers-more-nginx-module => http-headers-more-filter}/t/input-ua.t (100%) rename debian/modules/{headers-more-nginx-module => http-headers-more-filter}/t/input.t (100%) rename debian/modules/{headers-more-nginx-module => http-headers-more-filter}/t/phase.t (100%) rename debian/modules/{headers-more-nginx-module => http-headers-more-filter}/t/sanity.t (100%) rename debian/modules/{headers-more-nginx-module => http-headers-more-filter}/t/subrequest.t (100%) rename debian/modules/{headers-more-nginx-module => http-headers-more-filter}/t/unused.t (100%) rename debian/modules/{headers-more-nginx-module => http-headers-more-filter}/t/vars.t (100%) rename debian/modules/{headers-more-nginx-module => http-headers-more-filter}/util/build.sh (100%) rename debian/modules/{headers-more-nginx-module => http-headers-more-filter}/valgrind.suppress (100%) rename debian/modules/{nginx-lua => http-lua}/README.markdown (100%) rename debian/modules/{nginx-lua => http-lua}/config (100%) rename debian/modules/{nginx-lua => http-lua}/doc/HttpLuaModule.wiki (100%) rename debian/modules/{nginx-lua => http-lua}/dtrace/ngx_lua_provider.d (100%) rename debian/modules/{nginx-lua => http-lua}/misc/recv-until-pm/Makefile (100%) rename debian/modules/{nginx-lua => http-lua}/misc/recv-until-pm/lib/RecvUntil.pm (100%) rename debian/modules/{nginx-lua => http-lua}/misc/recv-until-pm/t/sanity.t (100%) rename debian/modules/{nginx-lua => http-lua}/src/api/ngx_http_lua_api.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ddebug.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_accessby.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_accessby.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_api.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_args.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_args.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_balancer.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_balancer.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_bodyfilterby.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_bodyfilterby.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_cache.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_cache.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_capturefilter.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_capturefilter.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_clfactory.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_clfactory.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_common.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_config.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_config.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_consts.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_consts.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_contentby.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_contentby.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_control.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_control.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_coroutine.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_coroutine.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_ctx.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_ctx.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_directive.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_directive.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_exception.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_exception.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_headerfilterby.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_headerfilterby.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_headers.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_headers.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_headers_in.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_headers_in.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_headers_out.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_headers_out.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_initby.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_initby.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_initworkerby.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_initworkerby.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_lex.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_lex.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_log.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_log.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_log_ringbuf.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_log_ringbuf.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_logby.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_logby.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_misc.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_misc.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_module.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_ndk.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_ndk.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_output.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_output.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_pcrefix.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_pcrefix.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_phase.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_phase.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_probe.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_regex.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_regex.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_req_body.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_req_body.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_req_method.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_req_method.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_rewriteby.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_rewriteby.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_script.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_script.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_semaphore.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_semaphore.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_setby.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_setby.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_shdict.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_shdict.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_sleep.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_sleep.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_socket_tcp.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_socket_tcp.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_socket_udp.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_socket_udp.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_ssl.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_ssl.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_ssl_certby.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_ssl_certby.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_ssl_ocsp.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_ssl_session_fetchby.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_ssl_session_fetchby.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_ssl_session_storeby.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_ssl_session_storeby.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_string.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_string.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_subrequest.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_subrequest.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_time.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_time.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_timer.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_timer.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_uri.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_uri.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_uthread.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_uthread.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_util.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_util.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_variable.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_variable.h (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_worker.c (100%) rename debian/modules/{nginx-lua => http-lua}/src/ngx_http_lua_worker.h (100%) rename debian/modules/{nginx-lua => http-lua}/t/.gitignore (100%) rename debian/modules/{nginx-lua => http-lua}/t/000--init.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/000-sanity.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/001-set.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/002-content.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/003-errors.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/004-require.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/005-exit.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/006-escape.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/007-md5.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/008-today.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/009-log.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/010-request_body.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/011-md5_bin.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/012-now.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/013-base64.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/014-bugs.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/015-status.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/016-resp-header.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/017-exec.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/018-ndk.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/019-const.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/020-subrequest.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/021-cookie-time.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/022-redirect.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/023-rewrite/client-abort.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/023-rewrite/exec.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/023-rewrite/exit.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/023-rewrite/mixed.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/023-rewrite/multi-capture.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/023-rewrite/on-abort.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/023-rewrite/redirect.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/023-rewrite/req-body.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/023-rewrite/req-socket.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/023-rewrite/request_body.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/023-rewrite/sanity.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/023-rewrite/sleep.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/023-rewrite/socket-keepalive.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/023-rewrite/subrequest.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/023-rewrite/tcp-socket-timeout.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/023-rewrite/tcp-socket.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/023-rewrite/unix-socket.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/023-rewrite/uthread-exec.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/023-rewrite/uthread-exit.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/023-rewrite/uthread-redirect.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/023-rewrite/uthread-spawn.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/024-access/auth.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/024-access/client-abort.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/024-access/exec.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/024-access/exit.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/024-access/mixed.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/024-access/multi-capture.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/024-access/on-abort.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/024-access/redirect.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/024-access/req-body.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/024-access/request_body.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/024-access/sanity.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/024-access/satisfy.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/024-access/sleep.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/024-access/subrequest.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/024-access/uthread-exec.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/024-access/uthread-exit.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/024-access/uthread-redirect.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/024-access/uthread-spawn.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/025-codecache.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/026-mysql.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/027-multi-capture.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/028-req-header.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/029-http-time.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/030-uri-args.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/031-post-args.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/032-iolist.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/033-ctx.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/034-match.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/035-gmatch.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/036-sub.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/037-gsub.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/038-match-o.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/039-sub-o.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/040-gsub-o.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/041-header-filter.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/042-crc32.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/043-shdict.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/044-req-body.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/045-ngx-var.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/046-hmac.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/047-match-jit.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/048-match-dfa.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/049-gmatch-jit.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/050-gmatch-dfa.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/051-sub-jit.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/052-sub-dfa.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/053-gsub-jit.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/054-gsub-dfa.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/055-subreq-vars.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/056-flush.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/057-flush-timeout.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/058-tcp-socket.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/059-unix-socket.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/060-lua-memcached.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/061-lua-redis.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/062-count.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/063-abort.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/064-pcall.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/065-tcp-socket-timeout.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/066-socket-receiveuntil.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/067-req-socket.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/068-socket-keepalive.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/069-null.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/070-sha1.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/071-idle-socket.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/072-conditional-get.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/073-backtrace.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/074-prefix-var.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/075-logby.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/076-no-postpone.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/077-sleep.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/078-hup-vars.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/079-unused-directives.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/080-hup-shdict.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/081-bytecode.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/082-body-filter.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/083-bad-sock-self.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/084-inclusive-receiveuntil.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/085-if.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/086-init-by.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/087-udp-socket.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/088-req-method.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/089-phase.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/090-log-socket-errors.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/091-coroutine.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/092-eof.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/093-uthread-spawn.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/094-uthread-exit.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/095-uthread-exec.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/096-uthread-redirect.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/097-uthread-rewrite.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/098-uthread-wait.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/099-c-api.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/100-client-abort.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/101-on-abort.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/102-req-start-time.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/103-req-http-ver.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/104-req-raw-header.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/105-pressure.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/106-timer.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/107-timer-errors.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/108-timer-safe.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/109-timer-hup.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/110-etag.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/111-req-header-ua.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/112-req-header-conn.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/113-req-header-cookie.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/114-config.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/115-quote-sql-str.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/116-raw-req-socket.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/117-raw-req-socket-timeout.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/118-use-default-type.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/119-config-prefix.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/120-re-find.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/121-version.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/122-worker.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/123-lua-path.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/124-init-worker.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/125-configure-args.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/126-shdict-frag.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/127-uthread-kill.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/128-duplex-tcp-socket.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/129-ssl-socket.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/130-internal-api.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/131-duplex-req-socket.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/132-lua-blocks.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/133-worker-count.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/134-worker-count-5.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/135-worker-id.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/136-timer-counts.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/137-req-misc.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/138-balancer.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/139-ssl-cert-by.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/140-ssl-c-api.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/141-luajit.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/142-ssl-session-store.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/143-ssl-session-fetch.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/144-shdict-incr-init.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/145-shdict-list.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/146-malloc-trim.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/147-tcp-socket-timeouts.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/148-fake-shm-zone.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/149-hup-fake-shm-zone.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/150-fake-delayed-load.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/151-initby-hup.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/152-timer-every.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/153-semaphore-hup.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/154-semaphore.t (100%) rename debian/modules/{nginx-lua => http-lua}/t/StapThread.pm (100%) rename debian/modules/{nginx-lua => http-lua}/t/cert/comodo-ca.crt (100%) rename debian/modules/{nginx-lua => http-lua}/t/cert/equifax.crt (100%) rename debian/modules/{nginx-lua => http-lua}/t/cert/test.crl (100%) rename debian/modules/{nginx-lua => http-lua}/t/cert/test.crt (100%) rename debian/modules/{nginx-lua => http-lua}/t/cert/test.key (100%) rename debian/modules/{nginx-lua => http-lua}/t/cert/test2.crt (100%) rename debian/modules/{nginx-lua => http-lua}/t/cert/test2.key (100%) rename debian/modules/{nginx-lua => http-lua}/t/cert/test_ecdsa.crt (100%) rename debian/modules/{nginx-lua => http-lua}/t/cert/test_ecdsa.key (100%) rename debian/modules/{nginx-lua => http-lua}/t/data/fake-delayed-load-module/config (100%) rename debian/modules/{nginx-lua => http-lua}/t/data/fake-delayed-load-module/ngx_http_lua_fake_delayed_load_module.c (100%) rename debian/modules/{nginx-lua => http-lua}/t/data/fake-module/config (100%) rename debian/modules/{nginx-lua => http-lua}/t/data/fake-module/ngx_http_fake_module.c (100%) rename debian/modules/{nginx-lua => http-lua}/t/data/fake-shm-module/config (100%) rename debian/modules/{nginx-lua => http-lua}/t/data/fake-shm-module/ngx_http_lua_fake_shm_module.c (100%) rename debian/modules/{nginx-lua => http-lua}/t/lib/CRC32.lua (100%) rename debian/modules/{nginx-lua => http-lua}/t/lib/Memcached.lua (100%) rename debian/modules/{nginx-lua => http-lua}/t/lib/Redis.lua (100%) rename debian/modules/{nginx-lua => http-lua}/t/lib/ljson.lua (100%) rename debian/modules/{nginx-lua => http-lua}/tapset/ngx_lua.stp (100%) rename debian/modules/{nginx-lua => http-lua}/util/build.sh (100%) rename debian/modules/{nginx-lua => http-lua}/util/fix-comments (100%) rename debian/modules/{nginx-lua => http-lua}/util/gen-lexer-c (100%) rename debian/modules/{nginx-lua => http-lua}/util/ngx-links (100%) rename debian/modules/{nginx-lua => http-lua}/util/releng (100%) rename debian/modules/{nginx-lua => http-lua}/util/retab (100%) rename debian/modules/{nginx-lua => http-lua}/util/revim (100%) rename debian/modules/{nginx-lua => http-lua}/util/run_test.sh (100%) rename debian/modules/{nginx-lua => http-lua}/util/update-readme.sh (100%) rename debian/modules/{nginx-lua => http-lua}/valgrind.suppress (100%) rename debian/modules/{nginx-development-kit => http-ndk}/LICENSE (100%) rename debian/modules/{nginx-development-kit => http-ndk}/README.md (100%) rename debian/modules/{nginx-development-kit => http-ndk}/README_AUTO_LIB (100%) rename debian/modules/{nginx-development-kit => http-ndk}/TODO (100%) rename debian/modules/{nginx-development-kit => http-ndk}/auto/actions/array (100%) rename debian/modules/{nginx-development-kit => http-ndk}/auto/actions/palloc (100%) rename debian/modules/{nginx-development-kit => http-ndk}/auto/build (100%) rename debian/modules/{nginx-development-kit => http-ndk}/auto/data/action_replacements (100%) rename debian/modules/{nginx-development-kit => http-ndk}/auto/data/action_types (100%) rename debian/modules/{nginx-development-kit => http-ndk}/auto/data/conf_args (100%) rename debian/modules/{nginx-development-kit => http-ndk}/auto/data/conf_locs (100%) rename debian/modules/{nginx-development-kit => http-ndk}/auto/data/conf_macros (100%) rename debian/modules/{nginx-development-kit => http-ndk}/auto/data/contexts (100%) rename debian/modules/{nginx-development-kit => http-ndk}/auto/data/header_files (100%) rename debian/modules/{nginx-development-kit => http-ndk}/auto/data/headers (100%) rename debian/modules/{nginx-development-kit => http-ndk}/auto/data/module_dependencies (100%) rename debian/modules/{nginx-development-kit => http-ndk}/auto/data/modules_optional (100%) rename debian/modules/{nginx-development-kit => http-ndk}/auto/data/prefixes (100%) rename debian/modules/{nginx-development-kit => http-ndk}/auto/src/array.h (100%) rename debian/modules/{nginx-development-kit => http-ndk}/auto/src/conf_cmd_basic.h (100%) rename debian/modules/{nginx-development-kit => http-ndk}/auto/src/conf_merge.h (100%) rename debian/modules/{nginx-development-kit => http-ndk}/auto/src/palloc.h (100%) rename debian/modules/{nginx-development-kit => http-ndk}/auto/text/autogen (100%) rename debian/modules/{nginx-development-kit => http-ndk}/config (100%) rename debian/modules/{nginx-development-kit => http-ndk}/docs/core/action_macros (100%) rename debian/modules/{nginx-development-kit => http-ndk}/docs/core/conf_cmds (100%) rename debian/modules/{nginx-development-kit => http-ndk}/docs/modules/set_var (100%) rename debian/modules/{nginx-development-kit => http-ndk}/docs/patches/more_logging_info (100%) rename debian/modules/{nginx-development-kit => http-ndk}/docs/upstream/list (100%) rename debian/modules/{nginx-development-kit => http-ndk}/examples/README (100%) rename debian/modules/{nginx-development-kit => http-ndk}/examples/http/set_var/config (100%) rename debian/modules/{nginx-development-kit => http-ndk}/examples/http/set_var/ngx_http_set_var_examples_module.c (100%) rename debian/modules/{nginx-development-kit => http-ndk}/ngx_auto_lib_core (100%) rename debian/modules/{nginx-development-kit => http-ndk}/notes/CHANGES (100%) rename debian/modules/{nginx-development-kit => http-ndk}/notes/LICENSE (100%) rename debian/modules/{nginx-development-kit => http-ndk}/objs/ndk_array.h (100%) rename debian/modules/{nginx-development-kit => http-ndk}/objs/ndk_conf_cmd_basic.h (100%) rename debian/modules/{nginx-development-kit => http-ndk}/objs/ndk_conf_cmd_extra.h (100%) rename debian/modules/{nginx-development-kit => http-ndk}/objs/ndk_conf_merge.h (100%) rename debian/modules/{nginx-development-kit => http-ndk}/objs/ndk_config.c (100%) rename debian/modules/{nginx-development-kit => http-ndk}/objs/ndk_config.h (100%) rename debian/modules/{nginx-development-kit => http-ndk}/objs/ndk_includes.h (100%) rename debian/modules/{nginx-development-kit => http-ndk}/objs/ndk_palloc.h (100%) rename debian/modules/{nginx-development-kit => http-ndk}/patches/auto_config (100%) rename debian/modules/{nginx-development-kit => http-ndk}/patches/expose_rewrite_functions (100%) rename debian/modules/{nginx-development-kit => http-ndk}/patches/rewrite_phase_handler (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/hash/md5.h (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/hash/murmurhash2.c (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/hash/sha.h (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/ndk.c (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/ndk.h (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/ndk_buf.c (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/ndk_buf.h (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/ndk_complex_path.c (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/ndk_complex_path.h (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/ndk_complex_value.c (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/ndk_complex_value.h (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/ndk_conf_file.c (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/ndk_conf_file.h (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/ndk_debug.c (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/ndk_debug.h (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/ndk_encoding.c (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/ndk_encoding.h (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/ndk_hash.c (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/ndk_hash.h (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/ndk_http.c (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/ndk_http.h (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/ndk_http_headers.h (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/ndk_log.c (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/ndk_log.h (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/ndk_parse.h (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/ndk_path.c (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/ndk_path.h (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/ndk_process.c (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/ndk_process.h (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/ndk_regex.c (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/ndk_regex.h (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/ndk_rewrite.c (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/ndk_rewrite.h (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/ndk_set_var.c (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/ndk_set_var.h (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/ndk_string.c (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/ndk_string.h (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/ndk_string_util.h (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/ndk_upstream_list.c (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/ndk_upstream_list.h (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/ndk_uri.c (100%) rename debian/modules/{nginx-development-kit => http-ndk}/src/ndk_uri.h (100%) rename debian/modules/{ngx_http_substitutions_filter_module => http-subs-filter}/CHANGES (100%) rename debian/modules/{ngx_http_substitutions_filter_module => http-subs-filter}/README (100%) rename debian/modules/{ngx_http_substitutions_filter_module => http-subs-filter}/config (100%) rename debian/modules/{ngx_http_substitutions_filter_module => http-subs-filter}/doc/README.google_code_home_page.wiki (100%) rename debian/modules/{ngx_http_substitutions_filter_module => http-subs-filter}/doc/README.html (100%) rename debian/modules/{ngx_http_substitutions_filter_module => http-subs-filter}/doc/README.wiki (100%) rename debian/modules/{ngx_http_substitutions_filter_module => http-subs-filter}/ngx_http_subs_filter_module.c (100%) rename debian/modules/{ngx_http_substitutions_filter_module => http-subs-filter}/test/README (100%) rename debian/modules/{ngx_http_substitutions_filter_module => http-subs-filter}/test/inc/Module/AutoInstall.pm (100%) rename debian/modules/{ngx_http_substitutions_filter_module => http-subs-filter}/test/inc/Module/Install.pm (100%) rename debian/modules/{ngx_http_substitutions_filter_module => http-subs-filter}/test/inc/Module/Install/AutoInstall.pm (100%) rename debian/modules/{ngx_http_substitutions_filter_module => http-subs-filter}/test/inc/Module/Install/Base.pm (100%) rename debian/modules/{ngx_http_substitutions_filter_module => http-subs-filter}/test/inc/Module/Install/Can.pm (100%) rename debian/modules/{ngx_http_substitutions_filter_module => http-subs-filter}/test/inc/Module/Install/Fetch.pm (100%) rename debian/modules/{ngx_http_substitutions_filter_module => http-subs-filter}/test/inc/Module/Install/Include.pm (100%) rename debian/modules/{ngx_http_substitutions_filter_module => http-subs-filter}/test/inc/Module/Install/Makefile.pm (100%) rename debian/modules/{ngx_http_substitutions_filter_module => http-subs-filter}/test/inc/Module/Install/Metadata.pm (100%) rename debian/modules/{ngx_http_substitutions_filter_module => http-subs-filter}/test/inc/Module/Install/TestBase.pm (100%) rename debian/modules/{ngx_http_substitutions_filter_module => http-subs-filter}/test/inc/Module/Install/Win32.pm (100%) rename debian/modules/{ngx_http_substitutions_filter_module => http-subs-filter}/test/inc/Module/Install/WriteAll.pm (100%) rename debian/modules/{ngx_http_substitutions_filter_module => http-subs-filter}/test/inc/Spiffy.pm (100%) rename debian/modules/{ngx_http_substitutions_filter_module => http-subs-filter}/test/inc/Test/Base.pm (100%) rename debian/modules/{ngx_http_substitutions_filter_module => http-subs-filter}/test/inc/Test/Base/Filter.pm (100%) rename debian/modules/{ngx_http_substitutions_filter_module => http-subs-filter}/test/inc/Test/Builder.pm (100%) rename debian/modules/{ngx_http_substitutions_filter_module => http-subs-filter}/test/inc/Test/Builder/Module.pm (100%) rename debian/modules/{ngx_http_substitutions_filter_module => http-subs-filter}/test/inc/Test/More.pm (100%) rename debian/modules/{ngx_http_substitutions_filter_module => http-subs-filter}/test/lib/Test/Nginx.pm (100%) rename debian/modules/{ngx_http_substitutions_filter_module => http-subs-filter}/test/lib/Test/Nginx/LWP.pm (100%) rename debian/modules/{ngx_http_substitutions_filter_module => http-subs-filter}/test/lib/Test/Nginx/Socket.pm (100%) rename debian/modules/{ngx_http_substitutions_filter_module => http-subs-filter}/test/lib/Test/Nginx/Util.pm (100%) rename debian/modules/{ngx_http_substitutions_filter_module => http-subs-filter}/test/t/subs.t (100%) rename debian/modules/{ngx_http_substitutions_filter_module => http-subs-filter}/test/t/subs_capture.t (100%) rename debian/modules/{ngx_http_substitutions_filter_module => http-subs-filter}/test/t/subs_fix_string.t (100%) rename debian/modules/{ngx_http_substitutions_filter_module => http-subs-filter}/test/t/subs_regex.t (100%) rename debian/modules/{ngx_http_substitutions_filter_module => http-subs-filter}/test/t/subs_types.t (100%) rename debian/modules/{ngx_http_substitutions_filter_module => http-subs-filter}/test/test.sh (100%) rename debian/modules/{ngx_http_substitutions_filter_module => http-subs-filter}/util/update-readme.sh (100%) rename debian/modules/{ngx_http_substitutions_filter_module => http-subs-filter}/util/wiki2google_code_homepage.pl (100%) rename debian/modules/{ngx_http_substitutions_filter_module => http-subs-filter}/util/wiki2pod.pl (100%) rename debian/modules/{nginx-upload-progress => http-uploadprogress}/CHANGES (100%) rename debian/modules/{nginx-upload-progress => http-uploadprogress}/LICENSE (100%) rename debian/modules/{nginx-upload-progress => http-uploadprogress}/Makefile (100%) rename debian/modules/{nginx-upload-progress => http-uploadprogress}/README (100%) rename debian/modules/{nginx-upload-progress => http-uploadprogress}/config (100%) rename debian/modules/{nginx-upload-progress => http-uploadprogress}/ngx_http_uploadprogress_module.c (100%) rename debian/modules/{nginx-upload-progress => http-uploadprogress}/test/client.sh (100%) rename debian/modules/{nginx-upload-progress => http-uploadprogress}/test/stress.sh (100%) rename debian/modules/{nginx-upstream-fair => http-upstream-fair}/.gdbinit (100%) rename debian/modules/{nginx-upstream-fair => http-upstream-fair}/README (100%) rename debian/modules/{nginx-upstream-fair => http-upstream-fair}/config (100%) rename debian/modules/{nginx-upstream-fair => http-upstream-fair}/ngx_http_upstream_fair_module.c (100%) rename debian/modules/patches/{nginx-cache-purge => http-cache-purge}/dynamic-module.patch (100%) rename debian/modules/patches/{nginx-cache-purge => http-cache-purge}/segfault-1.11.6.patch (100%) rename debian/modules/patches/{nginx-cache-purge => http-cache-purge}/series (100%) rename debian/modules/patches/{nginx-dav-ext-module => http-dav-ext}/dynamic-module.patch (100%) rename debian/modules/patches/{nginx-dav-ext-module => http-dav-ext}/series (100%) rename debian/modules/patches/{nginx-echo => http-echo}/build-nginx-1.11.11.patch (100%) rename debian/modules/patches/{nginx-echo => http-echo}/series (100%) rename debian/modules/patches/{nginx-lua => http-lua}/discover-luajit-2.1.patch (100%) rename debian/modules/patches/{nginx-lua => http-lua}/openssl-1.1.0.patch (100%) rename debian/modules/patches/{nginx-lua => http-lua}/series (100%) rename debian/modules/patches/{ngx_http_substitutions_filter_module => http-subs-filter}/dynamic-module.patch (100%) rename debian/modules/patches/{ngx_http_substitutions_filter_module => http-subs-filter}/series (100%) rename debian/modules/patches/{nginx-upstream-fair => http-upstream-fair}/drop-default-port.patch (100%) rename debian/modules/patches/{nginx-upstream-fair => http-upstream-fair}/dynamic-module.patch (100%) rename debian/modules/patches/{nginx-upstream-fair => http-upstream-fair}/openssl-1.1.0.patch (100%) rename debian/modules/patches/{nginx-upstream-fair => http-upstream-fair}/series (100%) rename debian/modules/{nginx-rtmp => rtmp}/AUTHORS (100%) rename debian/modules/{nginx-rtmp => rtmp}/LICENSE (100%) rename debian/modules/{nginx-rtmp => rtmp}/README.md (100%) rename debian/modules/{nginx-rtmp => rtmp}/config (100%) rename debian/modules/{nginx-rtmp => rtmp}/dash/ngx_rtmp_dash_module.c (100%) rename debian/modules/{nginx-rtmp => rtmp}/dash/ngx_rtmp_mp4.c (100%) rename debian/modules/{nginx-rtmp => rtmp}/dash/ngx_rtmp_mp4.h (100%) rename debian/modules/{nginx-rtmp => rtmp}/doc/README.md (100%) rename debian/modules/{nginx-rtmp => rtmp}/hls/ngx_rtmp_hls_module.c (100%) rename debian/modules/{nginx-rtmp => rtmp}/hls/ngx_rtmp_mpegts.c (100%) rename debian/modules/{nginx-rtmp => rtmp}/hls/ngx_rtmp_mpegts.h (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp.c (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp.h (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_access_module.c (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_amf.c (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_amf.h (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_auto_push_module.c (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_bandwidth.c (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_bandwidth.h (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_bitop.c (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_bitop.h (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_cmd_module.c (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_cmd_module.h (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_codec_module.c (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_codec_module.h (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_control_module.c (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_core_module.c (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_eval.c (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_eval.h (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_exec_module.c (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_flv_module.c (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_handler.c (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_handshake.c (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_init.c (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_limit_module.c (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_live_module.c (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_live_module.h (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_log_module.c (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_mp4_module.c (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_netcall_module.c (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_netcall_module.h (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_notify_module.c (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_play_module.c (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_play_module.h (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_proxy_protocol.c (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_proxy_protocol.h (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_receive.c (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_record_module.c (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_record_module.h (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_relay_module.c (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_relay_module.h (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_send.c (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_shared.c (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_stat_module.c (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_streams.h (100%) rename debian/modules/{nginx-rtmp => rtmp}/ngx_rtmp_version.h (100%) rename debian/modules/{nginx-rtmp => rtmp}/stat.xsl (100%) diff --git a/debian/copyright b/debian/copyright index 3d1b4c5..7bba41c 100644 --- a/debian/copyright +++ b/debian/copyright @@ -37,35 +37,35 @@ Copyright: 2007-2009, Fabio Tranchitella 2013-2016, Christos Trochalakis License: BSD-2-clause -Files: debian/modules/headers-more-nginx-module/* +Files: debian/modules/http-headers-more-filter/* Copyright: Copyright (c) 2009-2014, Yichun "agentzh" Zhang (章亦春) , CloudFlare Inc. Copyright (c) 2010-2013, Bernd Dorn Copyright (c) Igor Sysoev License: BSD-2-clause -Files: debian/modules/nginx-development-kit/* +Files: debian/modules/http-ndk/* Copyright: Marcus Clyne License: BSD-3-clause -Files: debian/modules/nginx-development-kit/src/hash/md5.h - debian/modules/nginx-development-kit/src/hash/sha.h +Files: debian/modules/http-ndk/src/hash/md5.h + debian/modules/http-ndk/src/hash/sha.h Copyright: Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) License: BSD-4-clause -Files: debian/modules/nginx-auth-pam/* +Files: debian/modules/http-auth-pam/* Copyright: 2008-2013, Sergio Talens Oliag License: BSD-2-clause -Files: debian/modules/nginx-echo/* +Files: debian/modules/http-echo/* Copyright: Copyright (c) 2009-2014, Yichun "agentzh" Zhang License: BSD-2-clause -Files: debian/modules/nginx-lua/* +Files: debian/modules/http-lua/* Copyright: Copyright (C) 2009-2014, by Xiaozhe Wang (chaoslawful) . Copyright (C) 2009-2014, by Yichun "agentzh" Zhang (章亦春) , CloudFlare Inc. License: BSD-2-clause -Files: debian/modules/nginx-upstream-fair/* +Files: debian/modules/http-upstream-fair/* Copyright: Copyright (c) 2007 Grzegorz Nosek Igor Sysoev License: BSD-2-clause @@ -85,29 +85,29 @@ Copyright: 2009-2011, Salvatore Sanfilippo Jan-Erik Rediger License: BSD-3-clause -Files: debian/modules/nginx-upload-progress/* +Files: debian/modules/http-uploadprogress/* Copyright: Brice Figureau 2002-2007, Igor Sysoev License: BSD-2-clause -Files: debian/modules/nginx-cache-purge/* +Files: debian/modules/http-cache-purge/* Copyright: 2009-2012, FRiCKLE , 2009-2012, Piotr Sikora License: BSD-2-clause -Files: debian/modules/nginx-dav-ext-module/* +Files: debian/modules/http-dav-ext/* Copyright: Arutyunyan Roman License: BSD-2-clause -Files: debian/modules/ngx-fancyindex/* +Files: debian/modules/http-fancyindex/* Copyright: Copyright (c) Adrian Perez License: BSD-2-clause -Files: debian/modules/ngx_http_substitutions_filter_module/* +Files: debian/modules/http-subs-filter/* Copyright: Copyright (C) 2014 by Weibin Yao License: BSD-2-clause -Files: debian/modules/nginx-rtmp/* +Files: debian/modules/rtmp/* Copyright: Copyright (C) 2012-2014, Roman Arutyunyan License: BSD-2-clause diff --git a/debian/modules/nginx-auth-pam/ChangeLog b/debian/modules/http-auth-pam/ChangeLog similarity index 100% rename from debian/modules/nginx-auth-pam/ChangeLog rename to debian/modules/http-auth-pam/ChangeLog diff --git a/debian/modules/nginx-auth-pam/LICENSE b/debian/modules/http-auth-pam/LICENSE similarity index 100% rename from debian/modules/nginx-auth-pam/LICENSE rename to debian/modules/http-auth-pam/LICENSE diff --git a/debian/modules/nginx-auth-pam/README.md b/debian/modules/http-auth-pam/README.md similarity index 100% rename from debian/modules/nginx-auth-pam/README.md rename to debian/modules/http-auth-pam/README.md diff --git a/debian/modules/nginx-auth-pam/VERSION b/debian/modules/http-auth-pam/VERSION similarity index 100% rename from debian/modules/nginx-auth-pam/VERSION rename to debian/modules/http-auth-pam/VERSION diff --git a/debian/modules/nginx-auth-pam/config b/debian/modules/http-auth-pam/config similarity index 100% rename from debian/modules/nginx-auth-pam/config rename to debian/modules/http-auth-pam/config diff --git a/debian/modules/nginx-auth-pam/ngx_http_auth_pam_module.c b/debian/modules/http-auth-pam/ngx_http_auth_pam_module.c similarity index 100% rename from debian/modules/nginx-auth-pam/ngx_http_auth_pam_module.c rename to debian/modules/http-auth-pam/ngx_http_auth_pam_module.c diff --git a/debian/modules/nginx-cache-purge/CHANGES b/debian/modules/http-cache-purge/CHANGES similarity index 100% rename from debian/modules/nginx-cache-purge/CHANGES rename to debian/modules/http-cache-purge/CHANGES diff --git a/debian/modules/nginx-cache-purge/LICENSE b/debian/modules/http-cache-purge/LICENSE similarity index 100% rename from debian/modules/nginx-cache-purge/LICENSE rename to debian/modules/http-cache-purge/LICENSE diff --git a/debian/modules/nginx-cache-purge/README.md b/debian/modules/http-cache-purge/README.md similarity index 100% rename from debian/modules/nginx-cache-purge/README.md rename to debian/modules/http-cache-purge/README.md diff --git a/debian/modules/nginx-cache-purge/TODO.md b/debian/modules/http-cache-purge/TODO.md similarity index 100% rename from debian/modules/nginx-cache-purge/TODO.md rename to debian/modules/http-cache-purge/TODO.md diff --git a/debian/modules/nginx-cache-purge/config b/debian/modules/http-cache-purge/config similarity index 100% rename from debian/modules/nginx-cache-purge/config rename to debian/modules/http-cache-purge/config diff --git a/debian/modules/nginx-cache-purge/ngx_cache_purge_module.c b/debian/modules/http-cache-purge/ngx_cache_purge_module.c similarity index 100% rename from debian/modules/nginx-cache-purge/ngx_cache_purge_module.c rename to debian/modules/http-cache-purge/ngx_cache_purge_module.c diff --git a/debian/modules/nginx-cache-purge/t/proxy1.t b/debian/modules/http-cache-purge/t/proxy1.t similarity index 100% rename from debian/modules/nginx-cache-purge/t/proxy1.t rename to debian/modules/http-cache-purge/t/proxy1.t diff --git a/debian/modules/nginx-cache-purge/t/proxy1_vars.t b/debian/modules/http-cache-purge/t/proxy1_vars.t similarity index 100% rename from debian/modules/nginx-cache-purge/t/proxy1_vars.t rename to debian/modules/http-cache-purge/t/proxy1_vars.t diff --git a/debian/modules/nginx-cache-purge/t/proxy2.t b/debian/modules/http-cache-purge/t/proxy2.t similarity index 100% rename from debian/modules/nginx-cache-purge/t/proxy2.t rename to debian/modules/http-cache-purge/t/proxy2.t diff --git a/debian/modules/nginx-cache-purge/t/proxy2_vars.t b/debian/modules/http-cache-purge/t/proxy2_vars.t similarity index 100% rename from debian/modules/nginx-cache-purge/t/proxy2_vars.t rename to debian/modules/http-cache-purge/t/proxy2_vars.t diff --git a/debian/modules/nginx-dav-ext-module/README b/debian/modules/http-dav-ext/README similarity index 100% rename from debian/modules/nginx-dav-ext-module/README rename to debian/modules/http-dav-ext/README diff --git a/debian/modules/nginx-dav-ext-module/config b/debian/modules/http-dav-ext/config similarity index 100% rename from debian/modules/nginx-dav-ext-module/config rename to debian/modules/http-dav-ext/config diff --git a/debian/modules/nginx-dav-ext-module/ngx_http_dav_ext_module.c b/debian/modules/http-dav-ext/ngx_http_dav_ext_module.c similarity index 100% rename from debian/modules/nginx-dav-ext-module/ngx_http_dav_ext_module.c rename to debian/modules/http-dav-ext/ngx_http_dav_ext_module.c diff --git a/debian/modules/nginx-echo/LICENSE b/debian/modules/http-echo/LICENSE similarity index 100% rename from debian/modules/nginx-echo/LICENSE rename to debian/modules/http-echo/LICENSE diff --git a/debian/modules/nginx-echo/README.markdown b/debian/modules/http-echo/README.markdown similarity index 100% rename from debian/modules/nginx-echo/README.markdown rename to debian/modules/http-echo/README.markdown diff --git a/debian/modules/nginx-echo/config b/debian/modules/http-echo/config similarity index 100% rename from debian/modules/nginx-echo/config rename to debian/modules/http-echo/config diff --git a/debian/modules/nginx-echo/src/ddebug.h b/debian/modules/http-echo/src/ddebug.h similarity index 100% rename from debian/modules/nginx-echo/src/ddebug.h rename to debian/modules/http-echo/src/ddebug.h diff --git a/debian/modules/nginx-echo/src/ngx_http_echo_echo.c b/debian/modules/http-echo/src/ngx_http_echo_echo.c similarity index 100% rename from debian/modules/nginx-echo/src/ngx_http_echo_echo.c rename to debian/modules/http-echo/src/ngx_http_echo_echo.c diff --git a/debian/modules/nginx-echo/src/ngx_http_echo_echo.h b/debian/modules/http-echo/src/ngx_http_echo_echo.h similarity index 100% rename from debian/modules/nginx-echo/src/ngx_http_echo_echo.h rename to debian/modules/http-echo/src/ngx_http_echo_echo.h diff --git a/debian/modules/nginx-echo/src/ngx_http_echo_filter.c b/debian/modules/http-echo/src/ngx_http_echo_filter.c similarity index 100% rename from debian/modules/nginx-echo/src/ngx_http_echo_filter.c rename to debian/modules/http-echo/src/ngx_http_echo_filter.c diff --git a/debian/modules/nginx-echo/src/ngx_http_echo_filter.h b/debian/modules/http-echo/src/ngx_http_echo_filter.h similarity index 100% rename from debian/modules/nginx-echo/src/ngx_http_echo_filter.h rename to debian/modules/http-echo/src/ngx_http_echo_filter.h diff --git a/debian/modules/nginx-echo/src/ngx_http_echo_foreach.c b/debian/modules/http-echo/src/ngx_http_echo_foreach.c similarity index 100% rename from debian/modules/nginx-echo/src/ngx_http_echo_foreach.c rename to debian/modules/http-echo/src/ngx_http_echo_foreach.c diff --git a/debian/modules/nginx-echo/src/ngx_http_echo_foreach.h b/debian/modules/http-echo/src/ngx_http_echo_foreach.h similarity index 100% rename from debian/modules/nginx-echo/src/ngx_http_echo_foreach.h rename to debian/modules/http-echo/src/ngx_http_echo_foreach.h diff --git a/debian/modules/nginx-echo/src/ngx_http_echo_handler.c b/debian/modules/http-echo/src/ngx_http_echo_handler.c similarity index 100% rename from debian/modules/nginx-echo/src/ngx_http_echo_handler.c rename to debian/modules/http-echo/src/ngx_http_echo_handler.c diff --git a/debian/modules/nginx-echo/src/ngx_http_echo_handler.h b/debian/modules/http-echo/src/ngx_http_echo_handler.h similarity index 100% rename from debian/modules/nginx-echo/src/ngx_http_echo_handler.h rename to debian/modules/http-echo/src/ngx_http_echo_handler.h diff --git a/debian/modules/nginx-echo/src/ngx_http_echo_location.c b/debian/modules/http-echo/src/ngx_http_echo_location.c similarity index 100% rename from debian/modules/nginx-echo/src/ngx_http_echo_location.c rename to debian/modules/http-echo/src/ngx_http_echo_location.c diff --git a/debian/modules/nginx-echo/src/ngx_http_echo_location.h b/debian/modules/http-echo/src/ngx_http_echo_location.h similarity index 100% rename from debian/modules/nginx-echo/src/ngx_http_echo_location.h rename to debian/modules/http-echo/src/ngx_http_echo_location.h diff --git a/debian/modules/nginx-echo/src/ngx_http_echo_module.c b/debian/modules/http-echo/src/ngx_http_echo_module.c similarity index 100% rename from debian/modules/nginx-echo/src/ngx_http_echo_module.c rename to debian/modules/http-echo/src/ngx_http_echo_module.c diff --git a/debian/modules/nginx-echo/src/ngx_http_echo_module.h b/debian/modules/http-echo/src/ngx_http_echo_module.h similarity index 100% rename from debian/modules/nginx-echo/src/ngx_http_echo_module.h rename to debian/modules/http-echo/src/ngx_http_echo_module.h diff --git a/debian/modules/nginx-echo/src/ngx_http_echo_request_info.c b/debian/modules/http-echo/src/ngx_http_echo_request_info.c similarity index 100% rename from debian/modules/nginx-echo/src/ngx_http_echo_request_info.c rename to debian/modules/http-echo/src/ngx_http_echo_request_info.c diff --git a/debian/modules/nginx-echo/src/ngx_http_echo_request_info.h b/debian/modules/http-echo/src/ngx_http_echo_request_info.h similarity index 100% rename from debian/modules/nginx-echo/src/ngx_http_echo_request_info.h rename to debian/modules/http-echo/src/ngx_http_echo_request_info.h diff --git a/debian/modules/nginx-echo/src/ngx_http_echo_sleep.c b/debian/modules/http-echo/src/ngx_http_echo_sleep.c similarity index 100% rename from debian/modules/nginx-echo/src/ngx_http_echo_sleep.c rename to debian/modules/http-echo/src/ngx_http_echo_sleep.c diff --git a/debian/modules/nginx-echo/src/ngx_http_echo_sleep.h b/debian/modules/http-echo/src/ngx_http_echo_sleep.h similarity index 100% rename from debian/modules/nginx-echo/src/ngx_http_echo_sleep.h rename to debian/modules/http-echo/src/ngx_http_echo_sleep.h diff --git a/debian/modules/nginx-echo/src/ngx_http_echo_subrequest.c b/debian/modules/http-echo/src/ngx_http_echo_subrequest.c similarity index 100% rename from debian/modules/nginx-echo/src/ngx_http_echo_subrequest.c rename to debian/modules/http-echo/src/ngx_http_echo_subrequest.c diff --git a/debian/modules/nginx-echo/src/ngx_http_echo_subrequest.h b/debian/modules/http-echo/src/ngx_http_echo_subrequest.h similarity index 100% rename from debian/modules/nginx-echo/src/ngx_http_echo_subrequest.h rename to debian/modules/http-echo/src/ngx_http_echo_subrequest.h diff --git a/debian/modules/nginx-echo/src/ngx_http_echo_timer.c b/debian/modules/http-echo/src/ngx_http_echo_timer.c similarity index 100% rename from debian/modules/nginx-echo/src/ngx_http_echo_timer.c rename to debian/modules/http-echo/src/ngx_http_echo_timer.c diff --git a/debian/modules/nginx-echo/src/ngx_http_echo_timer.h b/debian/modules/http-echo/src/ngx_http_echo_timer.h similarity index 100% rename from debian/modules/nginx-echo/src/ngx_http_echo_timer.h rename to debian/modules/http-echo/src/ngx_http_echo_timer.h diff --git a/debian/modules/nginx-echo/src/ngx_http_echo_util.c b/debian/modules/http-echo/src/ngx_http_echo_util.c similarity index 100% rename from debian/modules/nginx-echo/src/ngx_http_echo_util.c rename to debian/modules/http-echo/src/ngx_http_echo_util.c diff --git a/debian/modules/nginx-echo/src/ngx_http_echo_util.h b/debian/modules/http-echo/src/ngx_http_echo_util.h similarity index 100% rename from debian/modules/nginx-echo/src/ngx_http_echo_util.h rename to debian/modules/http-echo/src/ngx_http_echo_util.h diff --git a/debian/modules/nginx-echo/src/ngx_http_echo_var.c b/debian/modules/http-echo/src/ngx_http_echo_var.c similarity index 100% rename from debian/modules/nginx-echo/src/ngx_http_echo_var.c rename to debian/modules/http-echo/src/ngx_http_echo_var.c diff --git a/debian/modules/nginx-echo/src/ngx_http_echo_var.h b/debian/modules/http-echo/src/ngx_http_echo_var.h similarity index 100% rename from debian/modules/nginx-echo/src/ngx_http_echo_var.h rename to debian/modules/http-echo/src/ngx_http_echo_var.h diff --git a/debian/modules/nginx-echo/t/abort-parent.t b/debian/modules/http-echo/t/abort-parent.t similarity index 100% rename from debian/modules/nginx-echo/t/abort-parent.t rename to debian/modules/http-echo/t/abort-parent.t diff --git a/debian/modules/nginx-echo/t/blocking-sleep.t b/debian/modules/http-echo/t/blocking-sleep.t similarity index 100% rename from debian/modules/nginx-echo/t/blocking-sleep.t rename to debian/modules/http-echo/t/blocking-sleep.t diff --git a/debian/modules/nginx-echo/t/echo-after-body.t b/debian/modules/http-echo/t/echo-after-body.t similarity index 100% rename from debian/modules/nginx-echo/t/echo-after-body.t rename to debian/modules/http-echo/t/echo-after-body.t diff --git a/debian/modules/nginx-echo/t/echo-before-body.t b/debian/modules/http-echo/t/echo-before-body.t similarity index 100% rename from debian/modules/nginx-echo/t/echo-before-body.t rename to debian/modules/http-echo/t/echo-before-body.t diff --git a/debian/modules/nginx-echo/t/echo-duplicate.t b/debian/modules/http-echo/t/echo-duplicate.t similarity index 100% rename from debian/modules/nginx-echo/t/echo-duplicate.t rename to debian/modules/http-echo/t/echo-duplicate.t diff --git a/debian/modules/nginx-echo/t/echo-timer.t b/debian/modules/http-echo/t/echo-timer.t similarity index 100% rename from debian/modules/nginx-echo/t/echo-timer.t rename to debian/modules/http-echo/t/echo-timer.t diff --git a/debian/modules/nginx-echo/t/echo.t b/debian/modules/http-echo/t/echo.t similarity index 100% rename from debian/modules/nginx-echo/t/echo.t rename to debian/modules/http-echo/t/echo.t diff --git a/debian/modules/nginx-echo/t/exec.t b/debian/modules/http-echo/t/exec.t similarity index 100% rename from debian/modules/nginx-echo/t/exec.t rename to debian/modules/http-echo/t/exec.t diff --git a/debian/modules/nginx-echo/t/filter-used.t b/debian/modules/http-echo/t/filter-used.t similarity index 100% rename from debian/modules/nginx-echo/t/filter-used.t rename to debian/modules/http-echo/t/filter-used.t diff --git a/debian/modules/nginx-echo/t/foreach-split.t b/debian/modules/http-echo/t/foreach-split.t similarity index 100% rename from debian/modules/nginx-echo/t/foreach-split.t rename to debian/modules/http-echo/t/foreach-split.t diff --git a/debian/modules/nginx-echo/t/gzip.t b/debian/modules/http-echo/t/gzip.t similarity index 100% rename from debian/modules/nginx-echo/t/gzip.t rename to debian/modules/http-echo/t/gzip.t diff --git a/debian/modules/nginx-echo/t/if.t b/debian/modules/http-echo/t/if.t similarity index 100% rename from debian/modules/nginx-echo/t/if.t rename to debian/modules/http-echo/t/if.t diff --git a/debian/modules/nginx-echo/t/incr.t b/debian/modules/http-echo/t/incr.t similarity index 100% rename from debian/modules/nginx-echo/t/incr.t rename to debian/modules/http-echo/t/incr.t diff --git a/debian/modules/nginx-echo/t/location-async.t b/debian/modules/http-echo/t/location-async.t similarity index 100% rename from debian/modules/nginx-echo/t/location-async.t rename to debian/modules/http-echo/t/location-async.t diff --git a/debian/modules/nginx-echo/t/location.t b/debian/modules/http-echo/t/location.t similarity index 100% rename from debian/modules/nginx-echo/t/location.t rename to debian/modules/http-echo/t/location.t diff --git a/debian/modules/nginx-echo/t/mixed.t b/debian/modules/http-echo/t/mixed.t similarity index 100% rename from debian/modules/nginx-echo/t/mixed.t rename to debian/modules/http-echo/t/mixed.t diff --git a/debian/modules/nginx-echo/t/request-body.t b/debian/modules/http-echo/t/request-body.t similarity index 100% rename from debian/modules/nginx-echo/t/request-body.t rename to debian/modules/http-echo/t/request-body.t diff --git a/debian/modules/nginx-echo/t/request-info.t b/debian/modules/http-echo/t/request-info.t similarity index 100% rename from debian/modules/nginx-echo/t/request-info.t rename to debian/modules/http-echo/t/request-info.t diff --git a/debian/modules/nginx-echo/t/sleep.t b/debian/modules/http-echo/t/sleep.t similarity index 100% rename from debian/modules/nginx-echo/t/sleep.t rename to debian/modules/http-echo/t/sleep.t diff --git a/debian/modules/nginx-echo/t/status.t b/debian/modules/http-echo/t/status.t similarity index 100% rename from debian/modules/nginx-echo/t/status.t rename to debian/modules/http-echo/t/status.t diff --git a/debian/modules/nginx-echo/t/subrequest-async.t b/debian/modules/http-echo/t/subrequest-async.t similarity index 100% rename from debian/modules/nginx-echo/t/subrequest-async.t rename to debian/modules/http-echo/t/subrequest-async.t diff --git a/debian/modules/nginx-echo/t/subrequest.t b/debian/modules/http-echo/t/subrequest.t similarity index 100% rename from debian/modules/nginx-echo/t/subrequest.t rename to debian/modules/http-echo/t/subrequest.t diff --git a/debian/modules/nginx-echo/t/unused.t b/debian/modules/http-echo/t/unused.t similarity index 100% rename from debian/modules/nginx-echo/t/unused.t rename to debian/modules/http-echo/t/unused.t diff --git a/debian/modules/nginx-echo/util/build.sh b/debian/modules/http-echo/util/build.sh similarity index 100% rename from debian/modules/nginx-echo/util/build.sh rename to debian/modules/http-echo/util/build.sh diff --git a/debian/modules/nginx-echo/util/releng b/debian/modules/http-echo/util/releng similarity index 100% rename from debian/modules/nginx-echo/util/releng rename to debian/modules/http-echo/util/releng diff --git a/debian/modules/nginx-echo/util/wiki2pod.pl b/debian/modules/http-echo/util/wiki2pod.pl similarity index 100% rename from debian/modules/nginx-echo/util/wiki2pod.pl rename to debian/modules/http-echo/util/wiki2pod.pl diff --git a/debian/modules/nginx-echo/valgrind.suppress b/debian/modules/http-echo/valgrind.suppress similarity index 100% rename from debian/modules/nginx-echo/valgrind.suppress rename to debian/modules/http-echo/valgrind.suppress diff --git a/debian/modules/ngx-fancyindex/CHANGELOG.md b/debian/modules/http-fancyindex/CHANGELOG.md similarity index 100% rename from debian/modules/ngx-fancyindex/CHANGELOG.md rename to debian/modules/http-fancyindex/CHANGELOG.md diff --git a/debian/modules/ngx-fancyindex/HACKING.md b/debian/modules/http-fancyindex/HACKING.md similarity index 100% rename from debian/modules/ngx-fancyindex/HACKING.md rename to debian/modules/http-fancyindex/HACKING.md diff --git a/debian/modules/ngx-fancyindex/LICENSE b/debian/modules/http-fancyindex/LICENSE similarity index 100% rename from debian/modules/ngx-fancyindex/LICENSE rename to debian/modules/http-fancyindex/LICENSE diff --git a/debian/modules/ngx-fancyindex/README.rst b/debian/modules/http-fancyindex/README.rst similarity index 100% rename from debian/modules/ngx-fancyindex/README.rst rename to debian/modules/http-fancyindex/README.rst diff --git a/debian/modules/ngx-fancyindex/config b/debian/modules/http-fancyindex/config similarity index 100% rename from debian/modules/ngx-fancyindex/config rename to debian/modules/http-fancyindex/config diff --git a/debian/modules/ngx-fancyindex/nginx-0.6-support.patch b/debian/modules/http-fancyindex/nginx-0.6-support.patch similarity index 100% rename from debian/modules/ngx-fancyindex/nginx-0.6-support.patch rename to debian/modules/http-fancyindex/nginx-0.6-support.patch diff --git a/debian/modules/ngx-fancyindex/ngx_http_fancyindex_module.c b/debian/modules/http-fancyindex/ngx_http_fancyindex_module.c similarity index 100% rename from debian/modules/ngx-fancyindex/ngx_http_fancyindex_module.c rename to debian/modules/http-fancyindex/ngx_http_fancyindex_module.c diff --git a/debian/modules/ngx-fancyindex/t/00-build-artifacts.test b/debian/modules/http-fancyindex/t/00-build-artifacts.test similarity index 100% rename from debian/modules/ngx-fancyindex/t/00-build-artifacts.test rename to debian/modules/http-fancyindex/t/00-build-artifacts.test diff --git a/debian/modules/ngx-fancyindex/t/01-smoke-hasindex.test b/debian/modules/http-fancyindex/t/01-smoke-hasindex.test similarity index 100% rename from debian/modules/ngx-fancyindex/t/01-smoke-hasindex.test rename to debian/modules/http-fancyindex/t/01-smoke-hasindex.test diff --git a/debian/modules/ngx-fancyindex/t/02-smoke-indexisfancy.test b/debian/modules/http-fancyindex/t/02-smoke-indexisfancy.test similarity index 100% rename from debian/modules/ngx-fancyindex/t/02-smoke-indexisfancy.test rename to debian/modules/http-fancyindex/t/02-smoke-indexisfancy.test diff --git a/debian/modules/ngx-fancyindex/t/build-and-run b/debian/modules/http-fancyindex/t/build-and-run similarity index 100% rename from debian/modules/ngx-fancyindex/t/build-and-run rename to debian/modules/http-fancyindex/t/build-and-run diff --git a/debian/modules/ngx-fancyindex/t/has-index.test b/debian/modules/http-fancyindex/t/has-index.test similarity index 100% rename from debian/modules/ngx-fancyindex/t/has-index.test rename to debian/modules/http-fancyindex/t/has-index.test diff --git a/debian/modules/ngx-fancyindex/t/has-index/index.html b/debian/modules/http-fancyindex/t/has-index/index.html similarity index 100% rename from debian/modules/ngx-fancyindex/t/has-index/index.html rename to debian/modules/http-fancyindex/t/has-index/index.html diff --git a/debian/modules/ngx-fancyindex/t/nginx.conf b/debian/modules/http-fancyindex/t/nginx.conf similarity index 100% rename from debian/modules/ngx-fancyindex/t/nginx.conf rename to debian/modules/http-fancyindex/t/nginx.conf diff --git a/debian/modules/ngx-fancyindex/t/preamble b/debian/modules/http-fancyindex/t/preamble similarity index 100% rename from debian/modules/ngx-fancyindex/t/preamble rename to debian/modules/http-fancyindex/t/preamble diff --git a/debian/modules/ngx-fancyindex/t/run b/debian/modules/http-fancyindex/t/run similarity index 100% rename from debian/modules/ngx-fancyindex/t/run rename to debian/modules/http-fancyindex/t/run diff --git a/debian/modules/ngx-fancyindex/template.awk b/debian/modules/http-fancyindex/template.awk similarity index 100% rename from debian/modules/ngx-fancyindex/template.awk rename to debian/modules/http-fancyindex/template.awk diff --git a/debian/modules/ngx-fancyindex/template.h b/debian/modules/http-fancyindex/template.h similarity index 100% rename from debian/modules/ngx-fancyindex/template.h rename to debian/modules/http-fancyindex/template.h diff --git a/debian/modules/ngx-fancyindex/template.html b/debian/modules/http-fancyindex/template.html similarity index 100% rename from debian/modules/ngx-fancyindex/template.html rename to debian/modules/http-fancyindex/template.html diff --git a/debian/modules/headers-more-nginx-module/README.markdown b/debian/modules/http-headers-more-filter/README.markdown similarity index 100% rename from debian/modules/headers-more-nginx-module/README.markdown rename to debian/modules/http-headers-more-filter/README.markdown diff --git a/debian/modules/headers-more-nginx-module/config b/debian/modules/http-headers-more-filter/config similarity index 100% rename from debian/modules/headers-more-nginx-module/config rename to debian/modules/http-headers-more-filter/config diff --git a/debian/modules/headers-more-nginx-module/src/ddebug.h b/debian/modules/http-headers-more-filter/src/ddebug.h similarity index 100% rename from debian/modules/headers-more-nginx-module/src/ddebug.h rename to debian/modules/http-headers-more-filter/src/ddebug.h diff --git a/debian/modules/headers-more-nginx-module/src/ngx_http_headers_more_filter_module.c b/debian/modules/http-headers-more-filter/src/ngx_http_headers_more_filter_module.c similarity index 100% rename from debian/modules/headers-more-nginx-module/src/ngx_http_headers_more_filter_module.c rename to debian/modules/http-headers-more-filter/src/ngx_http_headers_more_filter_module.c diff --git a/debian/modules/headers-more-nginx-module/src/ngx_http_headers_more_filter_module.h b/debian/modules/http-headers-more-filter/src/ngx_http_headers_more_filter_module.h similarity index 100% rename from debian/modules/headers-more-nginx-module/src/ngx_http_headers_more_filter_module.h rename to debian/modules/http-headers-more-filter/src/ngx_http_headers_more_filter_module.h diff --git a/debian/modules/headers-more-nginx-module/src/ngx_http_headers_more_headers_in.c b/debian/modules/http-headers-more-filter/src/ngx_http_headers_more_headers_in.c similarity index 100% rename from debian/modules/headers-more-nginx-module/src/ngx_http_headers_more_headers_in.c rename to debian/modules/http-headers-more-filter/src/ngx_http_headers_more_headers_in.c diff --git a/debian/modules/headers-more-nginx-module/src/ngx_http_headers_more_headers_in.h b/debian/modules/http-headers-more-filter/src/ngx_http_headers_more_headers_in.h similarity index 100% rename from debian/modules/headers-more-nginx-module/src/ngx_http_headers_more_headers_in.h rename to debian/modules/http-headers-more-filter/src/ngx_http_headers_more_headers_in.h diff --git a/debian/modules/headers-more-nginx-module/src/ngx_http_headers_more_headers_out.c b/debian/modules/http-headers-more-filter/src/ngx_http_headers_more_headers_out.c similarity index 100% rename from debian/modules/headers-more-nginx-module/src/ngx_http_headers_more_headers_out.c rename to debian/modules/http-headers-more-filter/src/ngx_http_headers_more_headers_out.c diff --git a/debian/modules/headers-more-nginx-module/src/ngx_http_headers_more_headers_out.h b/debian/modules/http-headers-more-filter/src/ngx_http_headers_more_headers_out.h similarity index 100% rename from debian/modules/headers-more-nginx-module/src/ngx_http_headers_more_headers_out.h rename to debian/modules/http-headers-more-filter/src/ngx_http_headers_more_headers_out.h diff --git a/debian/modules/headers-more-nginx-module/src/ngx_http_headers_more_util.c b/debian/modules/http-headers-more-filter/src/ngx_http_headers_more_util.c similarity index 100% rename from debian/modules/headers-more-nginx-module/src/ngx_http_headers_more_util.c rename to debian/modules/http-headers-more-filter/src/ngx_http_headers_more_util.c diff --git a/debian/modules/headers-more-nginx-module/src/ngx_http_headers_more_util.h b/debian/modules/http-headers-more-filter/src/ngx_http_headers_more_util.h similarity index 100% rename from debian/modules/headers-more-nginx-module/src/ngx_http_headers_more_util.h rename to debian/modules/http-headers-more-filter/src/ngx_http_headers_more_util.h diff --git a/debian/modules/headers-more-nginx-module/t/bug.t b/debian/modules/http-headers-more-filter/t/bug.t similarity index 100% rename from debian/modules/headers-more-nginx-module/t/bug.t rename to debian/modules/http-headers-more-filter/t/bug.t diff --git a/debian/modules/headers-more-nginx-module/t/builtin.t b/debian/modules/http-headers-more-filter/t/builtin.t similarity index 100% rename from debian/modules/headers-more-nginx-module/t/builtin.t rename to debian/modules/http-headers-more-filter/t/builtin.t diff --git a/debian/modules/headers-more-nginx-module/t/eval.t b/debian/modules/http-headers-more-filter/t/eval.t similarity index 100% rename from debian/modules/headers-more-nginx-module/t/eval.t rename to debian/modules/http-headers-more-filter/t/eval.t diff --git a/debian/modules/headers-more-nginx-module/t/input-conn.t b/debian/modules/http-headers-more-filter/t/input-conn.t similarity index 100% rename from debian/modules/headers-more-nginx-module/t/input-conn.t rename to debian/modules/http-headers-more-filter/t/input-conn.t diff --git a/debian/modules/headers-more-nginx-module/t/input-cookie.t b/debian/modules/http-headers-more-filter/t/input-cookie.t similarity index 100% rename from debian/modules/headers-more-nginx-module/t/input-cookie.t rename to debian/modules/http-headers-more-filter/t/input-cookie.t diff --git a/debian/modules/headers-more-nginx-module/t/input-ua.t b/debian/modules/http-headers-more-filter/t/input-ua.t similarity index 100% rename from debian/modules/headers-more-nginx-module/t/input-ua.t rename to debian/modules/http-headers-more-filter/t/input-ua.t diff --git a/debian/modules/headers-more-nginx-module/t/input.t b/debian/modules/http-headers-more-filter/t/input.t similarity index 100% rename from debian/modules/headers-more-nginx-module/t/input.t rename to debian/modules/http-headers-more-filter/t/input.t diff --git a/debian/modules/headers-more-nginx-module/t/phase.t b/debian/modules/http-headers-more-filter/t/phase.t similarity index 100% rename from debian/modules/headers-more-nginx-module/t/phase.t rename to debian/modules/http-headers-more-filter/t/phase.t diff --git a/debian/modules/headers-more-nginx-module/t/sanity.t b/debian/modules/http-headers-more-filter/t/sanity.t similarity index 100% rename from debian/modules/headers-more-nginx-module/t/sanity.t rename to debian/modules/http-headers-more-filter/t/sanity.t diff --git a/debian/modules/headers-more-nginx-module/t/subrequest.t b/debian/modules/http-headers-more-filter/t/subrequest.t similarity index 100% rename from debian/modules/headers-more-nginx-module/t/subrequest.t rename to debian/modules/http-headers-more-filter/t/subrequest.t diff --git a/debian/modules/headers-more-nginx-module/t/unused.t b/debian/modules/http-headers-more-filter/t/unused.t similarity index 100% rename from debian/modules/headers-more-nginx-module/t/unused.t rename to debian/modules/http-headers-more-filter/t/unused.t diff --git a/debian/modules/headers-more-nginx-module/t/vars.t b/debian/modules/http-headers-more-filter/t/vars.t similarity index 100% rename from debian/modules/headers-more-nginx-module/t/vars.t rename to debian/modules/http-headers-more-filter/t/vars.t diff --git a/debian/modules/headers-more-nginx-module/util/build.sh b/debian/modules/http-headers-more-filter/util/build.sh similarity index 100% rename from debian/modules/headers-more-nginx-module/util/build.sh rename to debian/modules/http-headers-more-filter/util/build.sh diff --git a/debian/modules/headers-more-nginx-module/valgrind.suppress b/debian/modules/http-headers-more-filter/valgrind.suppress similarity index 100% rename from debian/modules/headers-more-nginx-module/valgrind.suppress rename to debian/modules/http-headers-more-filter/valgrind.suppress diff --git a/debian/modules/nginx-lua/README.markdown b/debian/modules/http-lua/README.markdown similarity index 100% rename from debian/modules/nginx-lua/README.markdown rename to debian/modules/http-lua/README.markdown diff --git a/debian/modules/nginx-lua/config b/debian/modules/http-lua/config similarity index 100% rename from debian/modules/nginx-lua/config rename to debian/modules/http-lua/config diff --git a/debian/modules/nginx-lua/doc/HttpLuaModule.wiki b/debian/modules/http-lua/doc/HttpLuaModule.wiki similarity index 100% rename from debian/modules/nginx-lua/doc/HttpLuaModule.wiki rename to debian/modules/http-lua/doc/HttpLuaModule.wiki diff --git a/debian/modules/nginx-lua/dtrace/ngx_lua_provider.d b/debian/modules/http-lua/dtrace/ngx_lua_provider.d similarity index 100% rename from debian/modules/nginx-lua/dtrace/ngx_lua_provider.d rename to debian/modules/http-lua/dtrace/ngx_lua_provider.d diff --git a/debian/modules/nginx-lua/misc/recv-until-pm/Makefile b/debian/modules/http-lua/misc/recv-until-pm/Makefile similarity index 100% rename from debian/modules/nginx-lua/misc/recv-until-pm/Makefile rename to debian/modules/http-lua/misc/recv-until-pm/Makefile diff --git a/debian/modules/nginx-lua/misc/recv-until-pm/lib/RecvUntil.pm b/debian/modules/http-lua/misc/recv-until-pm/lib/RecvUntil.pm similarity index 100% rename from debian/modules/nginx-lua/misc/recv-until-pm/lib/RecvUntil.pm rename to debian/modules/http-lua/misc/recv-until-pm/lib/RecvUntil.pm diff --git a/debian/modules/nginx-lua/misc/recv-until-pm/t/sanity.t b/debian/modules/http-lua/misc/recv-until-pm/t/sanity.t similarity index 100% rename from debian/modules/nginx-lua/misc/recv-until-pm/t/sanity.t rename to debian/modules/http-lua/misc/recv-until-pm/t/sanity.t diff --git a/debian/modules/nginx-lua/src/api/ngx_http_lua_api.h b/debian/modules/http-lua/src/api/ngx_http_lua_api.h similarity index 100% rename from debian/modules/nginx-lua/src/api/ngx_http_lua_api.h rename to debian/modules/http-lua/src/api/ngx_http_lua_api.h diff --git a/debian/modules/nginx-lua/src/ddebug.h b/debian/modules/http-lua/src/ddebug.h similarity index 100% rename from debian/modules/nginx-lua/src/ddebug.h rename to debian/modules/http-lua/src/ddebug.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_accessby.c b/debian/modules/http-lua/src/ngx_http_lua_accessby.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_accessby.c rename to debian/modules/http-lua/src/ngx_http_lua_accessby.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_accessby.h b/debian/modules/http-lua/src/ngx_http_lua_accessby.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_accessby.h rename to debian/modules/http-lua/src/ngx_http_lua_accessby.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_api.c b/debian/modules/http-lua/src/ngx_http_lua_api.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_api.c rename to debian/modules/http-lua/src/ngx_http_lua_api.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_args.c b/debian/modules/http-lua/src/ngx_http_lua_args.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_args.c rename to debian/modules/http-lua/src/ngx_http_lua_args.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_args.h b/debian/modules/http-lua/src/ngx_http_lua_args.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_args.h rename to debian/modules/http-lua/src/ngx_http_lua_args.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_balancer.c b/debian/modules/http-lua/src/ngx_http_lua_balancer.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_balancer.c rename to debian/modules/http-lua/src/ngx_http_lua_balancer.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_balancer.h b/debian/modules/http-lua/src/ngx_http_lua_balancer.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_balancer.h rename to debian/modules/http-lua/src/ngx_http_lua_balancer.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_bodyfilterby.c b/debian/modules/http-lua/src/ngx_http_lua_bodyfilterby.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_bodyfilterby.c rename to debian/modules/http-lua/src/ngx_http_lua_bodyfilterby.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_bodyfilterby.h b/debian/modules/http-lua/src/ngx_http_lua_bodyfilterby.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_bodyfilterby.h rename to debian/modules/http-lua/src/ngx_http_lua_bodyfilterby.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_cache.c b/debian/modules/http-lua/src/ngx_http_lua_cache.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_cache.c rename to debian/modules/http-lua/src/ngx_http_lua_cache.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_cache.h b/debian/modules/http-lua/src/ngx_http_lua_cache.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_cache.h rename to debian/modules/http-lua/src/ngx_http_lua_cache.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_capturefilter.c b/debian/modules/http-lua/src/ngx_http_lua_capturefilter.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_capturefilter.c rename to debian/modules/http-lua/src/ngx_http_lua_capturefilter.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_capturefilter.h b/debian/modules/http-lua/src/ngx_http_lua_capturefilter.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_capturefilter.h rename to debian/modules/http-lua/src/ngx_http_lua_capturefilter.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_clfactory.c b/debian/modules/http-lua/src/ngx_http_lua_clfactory.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_clfactory.c rename to debian/modules/http-lua/src/ngx_http_lua_clfactory.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_clfactory.h b/debian/modules/http-lua/src/ngx_http_lua_clfactory.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_clfactory.h rename to debian/modules/http-lua/src/ngx_http_lua_clfactory.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_common.h b/debian/modules/http-lua/src/ngx_http_lua_common.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_common.h rename to debian/modules/http-lua/src/ngx_http_lua_common.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_config.c b/debian/modules/http-lua/src/ngx_http_lua_config.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_config.c rename to debian/modules/http-lua/src/ngx_http_lua_config.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_config.h b/debian/modules/http-lua/src/ngx_http_lua_config.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_config.h rename to debian/modules/http-lua/src/ngx_http_lua_config.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_consts.c b/debian/modules/http-lua/src/ngx_http_lua_consts.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_consts.c rename to debian/modules/http-lua/src/ngx_http_lua_consts.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_consts.h b/debian/modules/http-lua/src/ngx_http_lua_consts.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_consts.h rename to debian/modules/http-lua/src/ngx_http_lua_consts.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_contentby.c b/debian/modules/http-lua/src/ngx_http_lua_contentby.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_contentby.c rename to debian/modules/http-lua/src/ngx_http_lua_contentby.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_contentby.h b/debian/modules/http-lua/src/ngx_http_lua_contentby.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_contentby.h rename to debian/modules/http-lua/src/ngx_http_lua_contentby.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_control.c b/debian/modules/http-lua/src/ngx_http_lua_control.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_control.c rename to debian/modules/http-lua/src/ngx_http_lua_control.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_control.h b/debian/modules/http-lua/src/ngx_http_lua_control.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_control.h rename to debian/modules/http-lua/src/ngx_http_lua_control.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_coroutine.c b/debian/modules/http-lua/src/ngx_http_lua_coroutine.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_coroutine.c rename to debian/modules/http-lua/src/ngx_http_lua_coroutine.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_coroutine.h b/debian/modules/http-lua/src/ngx_http_lua_coroutine.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_coroutine.h rename to debian/modules/http-lua/src/ngx_http_lua_coroutine.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_ctx.c b/debian/modules/http-lua/src/ngx_http_lua_ctx.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_ctx.c rename to debian/modules/http-lua/src/ngx_http_lua_ctx.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_ctx.h b/debian/modules/http-lua/src/ngx_http_lua_ctx.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_ctx.h rename to debian/modules/http-lua/src/ngx_http_lua_ctx.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_directive.c b/debian/modules/http-lua/src/ngx_http_lua_directive.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_directive.c rename to debian/modules/http-lua/src/ngx_http_lua_directive.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_directive.h b/debian/modules/http-lua/src/ngx_http_lua_directive.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_directive.h rename to debian/modules/http-lua/src/ngx_http_lua_directive.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_exception.c b/debian/modules/http-lua/src/ngx_http_lua_exception.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_exception.c rename to debian/modules/http-lua/src/ngx_http_lua_exception.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_exception.h b/debian/modules/http-lua/src/ngx_http_lua_exception.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_exception.h rename to debian/modules/http-lua/src/ngx_http_lua_exception.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_headerfilterby.c b/debian/modules/http-lua/src/ngx_http_lua_headerfilterby.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_headerfilterby.c rename to debian/modules/http-lua/src/ngx_http_lua_headerfilterby.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_headerfilterby.h b/debian/modules/http-lua/src/ngx_http_lua_headerfilterby.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_headerfilterby.h rename to debian/modules/http-lua/src/ngx_http_lua_headerfilterby.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_headers.c b/debian/modules/http-lua/src/ngx_http_lua_headers.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_headers.c rename to debian/modules/http-lua/src/ngx_http_lua_headers.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_headers.h b/debian/modules/http-lua/src/ngx_http_lua_headers.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_headers.h rename to debian/modules/http-lua/src/ngx_http_lua_headers.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_headers_in.c b/debian/modules/http-lua/src/ngx_http_lua_headers_in.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_headers_in.c rename to debian/modules/http-lua/src/ngx_http_lua_headers_in.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_headers_in.h b/debian/modules/http-lua/src/ngx_http_lua_headers_in.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_headers_in.h rename to debian/modules/http-lua/src/ngx_http_lua_headers_in.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_headers_out.c b/debian/modules/http-lua/src/ngx_http_lua_headers_out.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_headers_out.c rename to debian/modules/http-lua/src/ngx_http_lua_headers_out.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_headers_out.h b/debian/modules/http-lua/src/ngx_http_lua_headers_out.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_headers_out.h rename to debian/modules/http-lua/src/ngx_http_lua_headers_out.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_initby.c b/debian/modules/http-lua/src/ngx_http_lua_initby.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_initby.c rename to debian/modules/http-lua/src/ngx_http_lua_initby.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_initby.h b/debian/modules/http-lua/src/ngx_http_lua_initby.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_initby.h rename to debian/modules/http-lua/src/ngx_http_lua_initby.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_initworkerby.c b/debian/modules/http-lua/src/ngx_http_lua_initworkerby.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_initworkerby.c rename to debian/modules/http-lua/src/ngx_http_lua_initworkerby.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_initworkerby.h b/debian/modules/http-lua/src/ngx_http_lua_initworkerby.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_initworkerby.h rename to debian/modules/http-lua/src/ngx_http_lua_initworkerby.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_lex.c b/debian/modules/http-lua/src/ngx_http_lua_lex.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_lex.c rename to debian/modules/http-lua/src/ngx_http_lua_lex.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_lex.h b/debian/modules/http-lua/src/ngx_http_lua_lex.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_lex.h rename to debian/modules/http-lua/src/ngx_http_lua_lex.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_log.c b/debian/modules/http-lua/src/ngx_http_lua_log.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_log.c rename to debian/modules/http-lua/src/ngx_http_lua_log.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_log.h b/debian/modules/http-lua/src/ngx_http_lua_log.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_log.h rename to debian/modules/http-lua/src/ngx_http_lua_log.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_log_ringbuf.c b/debian/modules/http-lua/src/ngx_http_lua_log_ringbuf.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_log_ringbuf.c rename to debian/modules/http-lua/src/ngx_http_lua_log_ringbuf.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_log_ringbuf.h b/debian/modules/http-lua/src/ngx_http_lua_log_ringbuf.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_log_ringbuf.h rename to debian/modules/http-lua/src/ngx_http_lua_log_ringbuf.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_logby.c b/debian/modules/http-lua/src/ngx_http_lua_logby.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_logby.c rename to debian/modules/http-lua/src/ngx_http_lua_logby.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_logby.h b/debian/modules/http-lua/src/ngx_http_lua_logby.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_logby.h rename to debian/modules/http-lua/src/ngx_http_lua_logby.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_misc.c b/debian/modules/http-lua/src/ngx_http_lua_misc.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_misc.c rename to debian/modules/http-lua/src/ngx_http_lua_misc.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_misc.h b/debian/modules/http-lua/src/ngx_http_lua_misc.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_misc.h rename to debian/modules/http-lua/src/ngx_http_lua_misc.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_module.c b/debian/modules/http-lua/src/ngx_http_lua_module.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_module.c rename to debian/modules/http-lua/src/ngx_http_lua_module.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_ndk.c b/debian/modules/http-lua/src/ngx_http_lua_ndk.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_ndk.c rename to debian/modules/http-lua/src/ngx_http_lua_ndk.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_ndk.h b/debian/modules/http-lua/src/ngx_http_lua_ndk.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_ndk.h rename to debian/modules/http-lua/src/ngx_http_lua_ndk.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_output.c b/debian/modules/http-lua/src/ngx_http_lua_output.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_output.c rename to debian/modules/http-lua/src/ngx_http_lua_output.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_output.h b/debian/modules/http-lua/src/ngx_http_lua_output.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_output.h rename to debian/modules/http-lua/src/ngx_http_lua_output.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_pcrefix.c b/debian/modules/http-lua/src/ngx_http_lua_pcrefix.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_pcrefix.c rename to debian/modules/http-lua/src/ngx_http_lua_pcrefix.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_pcrefix.h b/debian/modules/http-lua/src/ngx_http_lua_pcrefix.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_pcrefix.h rename to debian/modules/http-lua/src/ngx_http_lua_pcrefix.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_phase.c b/debian/modules/http-lua/src/ngx_http_lua_phase.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_phase.c rename to debian/modules/http-lua/src/ngx_http_lua_phase.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_phase.h b/debian/modules/http-lua/src/ngx_http_lua_phase.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_phase.h rename to debian/modules/http-lua/src/ngx_http_lua_phase.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_probe.h b/debian/modules/http-lua/src/ngx_http_lua_probe.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_probe.h rename to debian/modules/http-lua/src/ngx_http_lua_probe.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_regex.c b/debian/modules/http-lua/src/ngx_http_lua_regex.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_regex.c rename to debian/modules/http-lua/src/ngx_http_lua_regex.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_regex.h b/debian/modules/http-lua/src/ngx_http_lua_regex.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_regex.h rename to debian/modules/http-lua/src/ngx_http_lua_regex.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_req_body.c b/debian/modules/http-lua/src/ngx_http_lua_req_body.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_req_body.c rename to debian/modules/http-lua/src/ngx_http_lua_req_body.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_req_body.h b/debian/modules/http-lua/src/ngx_http_lua_req_body.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_req_body.h rename to debian/modules/http-lua/src/ngx_http_lua_req_body.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_req_method.c b/debian/modules/http-lua/src/ngx_http_lua_req_method.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_req_method.c rename to debian/modules/http-lua/src/ngx_http_lua_req_method.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_req_method.h b/debian/modules/http-lua/src/ngx_http_lua_req_method.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_req_method.h rename to debian/modules/http-lua/src/ngx_http_lua_req_method.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_rewriteby.c b/debian/modules/http-lua/src/ngx_http_lua_rewriteby.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_rewriteby.c rename to debian/modules/http-lua/src/ngx_http_lua_rewriteby.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_rewriteby.h b/debian/modules/http-lua/src/ngx_http_lua_rewriteby.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_rewriteby.h rename to debian/modules/http-lua/src/ngx_http_lua_rewriteby.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_script.c b/debian/modules/http-lua/src/ngx_http_lua_script.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_script.c rename to debian/modules/http-lua/src/ngx_http_lua_script.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_script.h b/debian/modules/http-lua/src/ngx_http_lua_script.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_script.h rename to debian/modules/http-lua/src/ngx_http_lua_script.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_semaphore.c b/debian/modules/http-lua/src/ngx_http_lua_semaphore.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_semaphore.c rename to debian/modules/http-lua/src/ngx_http_lua_semaphore.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_semaphore.h b/debian/modules/http-lua/src/ngx_http_lua_semaphore.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_semaphore.h rename to debian/modules/http-lua/src/ngx_http_lua_semaphore.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_setby.c b/debian/modules/http-lua/src/ngx_http_lua_setby.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_setby.c rename to debian/modules/http-lua/src/ngx_http_lua_setby.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_setby.h b/debian/modules/http-lua/src/ngx_http_lua_setby.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_setby.h rename to debian/modules/http-lua/src/ngx_http_lua_setby.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_shdict.c b/debian/modules/http-lua/src/ngx_http_lua_shdict.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_shdict.c rename to debian/modules/http-lua/src/ngx_http_lua_shdict.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_shdict.h b/debian/modules/http-lua/src/ngx_http_lua_shdict.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_shdict.h rename to debian/modules/http-lua/src/ngx_http_lua_shdict.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_sleep.c b/debian/modules/http-lua/src/ngx_http_lua_sleep.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_sleep.c rename to debian/modules/http-lua/src/ngx_http_lua_sleep.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_sleep.h b/debian/modules/http-lua/src/ngx_http_lua_sleep.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_sleep.h rename to debian/modules/http-lua/src/ngx_http_lua_sleep.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_socket_tcp.c b/debian/modules/http-lua/src/ngx_http_lua_socket_tcp.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_socket_tcp.c rename to debian/modules/http-lua/src/ngx_http_lua_socket_tcp.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_socket_tcp.h b/debian/modules/http-lua/src/ngx_http_lua_socket_tcp.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_socket_tcp.h rename to debian/modules/http-lua/src/ngx_http_lua_socket_tcp.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_socket_udp.c b/debian/modules/http-lua/src/ngx_http_lua_socket_udp.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_socket_udp.c rename to debian/modules/http-lua/src/ngx_http_lua_socket_udp.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_socket_udp.h b/debian/modules/http-lua/src/ngx_http_lua_socket_udp.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_socket_udp.h rename to debian/modules/http-lua/src/ngx_http_lua_socket_udp.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_ssl.c b/debian/modules/http-lua/src/ngx_http_lua_ssl.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_ssl.c rename to debian/modules/http-lua/src/ngx_http_lua_ssl.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_ssl.h b/debian/modules/http-lua/src/ngx_http_lua_ssl.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_ssl.h rename to debian/modules/http-lua/src/ngx_http_lua_ssl.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_ssl_certby.c b/debian/modules/http-lua/src/ngx_http_lua_ssl_certby.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_ssl_certby.c rename to debian/modules/http-lua/src/ngx_http_lua_ssl_certby.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_ssl_certby.h b/debian/modules/http-lua/src/ngx_http_lua_ssl_certby.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_ssl_certby.h rename to debian/modules/http-lua/src/ngx_http_lua_ssl_certby.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_ssl_ocsp.c b/debian/modules/http-lua/src/ngx_http_lua_ssl_ocsp.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_ssl_ocsp.c rename to debian/modules/http-lua/src/ngx_http_lua_ssl_ocsp.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_ssl_session_fetchby.c b/debian/modules/http-lua/src/ngx_http_lua_ssl_session_fetchby.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_ssl_session_fetchby.c rename to debian/modules/http-lua/src/ngx_http_lua_ssl_session_fetchby.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_ssl_session_fetchby.h b/debian/modules/http-lua/src/ngx_http_lua_ssl_session_fetchby.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_ssl_session_fetchby.h rename to debian/modules/http-lua/src/ngx_http_lua_ssl_session_fetchby.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_ssl_session_storeby.c b/debian/modules/http-lua/src/ngx_http_lua_ssl_session_storeby.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_ssl_session_storeby.c rename to debian/modules/http-lua/src/ngx_http_lua_ssl_session_storeby.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_ssl_session_storeby.h b/debian/modules/http-lua/src/ngx_http_lua_ssl_session_storeby.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_ssl_session_storeby.h rename to debian/modules/http-lua/src/ngx_http_lua_ssl_session_storeby.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_string.c b/debian/modules/http-lua/src/ngx_http_lua_string.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_string.c rename to debian/modules/http-lua/src/ngx_http_lua_string.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_string.h b/debian/modules/http-lua/src/ngx_http_lua_string.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_string.h rename to debian/modules/http-lua/src/ngx_http_lua_string.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_subrequest.c b/debian/modules/http-lua/src/ngx_http_lua_subrequest.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_subrequest.c rename to debian/modules/http-lua/src/ngx_http_lua_subrequest.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_subrequest.h b/debian/modules/http-lua/src/ngx_http_lua_subrequest.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_subrequest.h rename to debian/modules/http-lua/src/ngx_http_lua_subrequest.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_time.c b/debian/modules/http-lua/src/ngx_http_lua_time.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_time.c rename to debian/modules/http-lua/src/ngx_http_lua_time.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_time.h b/debian/modules/http-lua/src/ngx_http_lua_time.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_time.h rename to debian/modules/http-lua/src/ngx_http_lua_time.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_timer.c b/debian/modules/http-lua/src/ngx_http_lua_timer.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_timer.c rename to debian/modules/http-lua/src/ngx_http_lua_timer.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_timer.h b/debian/modules/http-lua/src/ngx_http_lua_timer.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_timer.h rename to debian/modules/http-lua/src/ngx_http_lua_timer.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_uri.c b/debian/modules/http-lua/src/ngx_http_lua_uri.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_uri.c rename to debian/modules/http-lua/src/ngx_http_lua_uri.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_uri.h b/debian/modules/http-lua/src/ngx_http_lua_uri.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_uri.h rename to debian/modules/http-lua/src/ngx_http_lua_uri.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_uthread.c b/debian/modules/http-lua/src/ngx_http_lua_uthread.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_uthread.c rename to debian/modules/http-lua/src/ngx_http_lua_uthread.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_uthread.h b/debian/modules/http-lua/src/ngx_http_lua_uthread.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_uthread.h rename to debian/modules/http-lua/src/ngx_http_lua_uthread.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_util.c b/debian/modules/http-lua/src/ngx_http_lua_util.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_util.c rename to debian/modules/http-lua/src/ngx_http_lua_util.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_util.h b/debian/modules/http-lua/src/ngx_http_lua_util.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_util.h rename to debian/modules/http-lua/src/ngx_http_lua_util.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_variable.c b/debian/modules/http-lua/src/ngx_http_lua_variable.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_variable.c rename to debian/modules/http-lua/src/ngx_http_lua_variable.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_variable.h b/debian/modules/http-lua/src/ngx_http_lua_variable.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_variable.h rename to debian/modules/http-lua/src/ngx_http_lua_variable.h diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_worker.c b/debian/modules/http-lua/src/ngx_http_lua_worker.c similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_worker.c rename to debian/modules/http-lua/src/ngx_http_lua_worker.c diff --git a/debian/modules/nginx-lua/src/ngx_http_lua_worker.h b/debian/modules/http-lua/src/ngx_http_lua_worker.h similarity index 100% rename from debian/modules/nginx-lua/src/ngx_http_lua_worker.h rename to debian/modules/http-lua/src/ngx_http_lua_worker.h diff --git a/debian/modules/nginx-lua/t/.gitignore b/debian/modules/http-lua/t/.gitignore similarity index 100% rename from debian/modules/nginx-lua/t/.gitignore rename to debian/modules/http-lua/t/.gitignore diff --git a/debian/modules/nginx-lua/t/000--init.t b/debian/modules/http-lua/t/000--init.t similarity index 100% rename from debian/modules/nginx-lua/t/000--init.t rename to debian/modules/http-lua/t/000--init.t diff --git a/debian/modules/nginx-lua/t/000-sanity.t b/debian/modules/http-lua/t/000-sanity.t similarity index 100% rename from debian/modules/nginx-lua/t/000-sanity.t rename to debian/modules/http-lua/t/000-sanity.t diff --git a/debian/modules/nginx-lua/t/001-set.t b/debian/modules/http-lua/t/001-set.t similarity index 100% rename from debian/modules/nginx-lua/t/001-set.t rename to debian/modules/http-lua/t/001-set.t diff --git a/debian/modules/nginx-lua/t/002-content.t b/debian/modules/http-lua/t/002-content.t similarity index 100% rename from debian/modules/nginx-lua/t/002-content.t rename to debian/modules/http-lua/t/002-content.t diff --git a/debian/modules/nginx-lua/t/003-errors.t b/debian/modules/http-lua/t/003-errors.t similarity index 100% rename from debian/modules/nginx-lua/t/003-errors.t rename to debian/modules/http-lua/t/003-errors.t diff --git a/debian/modules/nginx-lua/t/004-require.t b/debian/modules/http-lua/t/004-require.t similarity index 100% rename from debian/modules/nginx-lua/t/004-require.t rename to debian/modules/http-lua/t/004-require.t diff --git a/debian/modules/nginx-lua/t/005-exit.t b/debian/modules/http-lua/t/005-exit.t similarity index 100% rename from debian/modules/nginx-lua/t/005-exit.t rename to debian/modules/http-lua/t/005-exit.t diff --git a/debian/modules/nginx-lua/t/006-escape.t b/debian/modules/http-lua/t/006-escape.t similarity index 100% rename from debian/modules/nginx-lua/t/006-escape.t rename to debian/modules/http-lua/t/006-escape.t diff --git a/debian/modules/nginx-lua/t/007-md5.t b/debian/modules/http-lua/t/007-md5.t similarity index 100% rename from debian/modules/nginx-lua/t/007-md5.t rename to debian/modules/http-lua/t/007-md5.t diff --git a/debian/modules/nginx-lua/t/008-today.t b/debian/modules/http-lua/t/008-today.t similarity index 100% rename from debian/modules/nginx-lua/t/008-today.t rename to debian/modules/http-lua/t/008-today.t diff --git a/debian/modules/nginx-lua/t/009-log.t b/debian/modules/http-lua/t/009-log.t similarity index 100% rename from debian/modules/nginx-lua/t/009-log.t rename to debian/modules/http-lua/t/009-log.t diff --git a/debian/modules/nginx-lua/t/010-request_body.t b/debian/modules/http-lua/t/010-request_body.t similarity index 100% rename from debian/modules/nginx-lua/t/010-request_body.t rename to debian/modules/http-lua/t/010-request_body.t diff --git a/debian/modules/nginx-lua/t/011-md5_bin.t b/debian/modules/http-lua/t/011-md5_bin.t similarity index 100% rename from debian/modules/nginx-lua/t/011-md5_bin.t rename to debian/modules/http-lua/t/011-md5_bin.t diff --git a/debian/modules/nginx-lua/t/012-now.t b/debian/modules/http-lua/t/012-now.t similarity index 100% rename from debian/modules/nginx-lua/t/012-now.t rename to debian/modules/http-lua/t/012-now.t diff --git a/debian/modules/nginx-lua/t/013-base64.t b/debian/modules/http-lua/t/013-base64.t similarity index 100% rename from debian/modules/nginx-lua/t/013-base64.t rename to debian/modules/http-lua/t/013-base64.t diff --git a/debian/modules/nginx-lua/t/014-bugs.t b/debian/modules/http-lua/t/014-bugs.t similarity index 100% rename from debian/modules/nginx-lua/t/014-bugs.t rename to debian/modules/http-lua/t/014-bugs.t diff --git a/debian/modules/nginx-lua/t/015-status.t b/debian/modules/http-lua/t/015-status.t similarity index 100% rename from debian/modules/nginx-lua/t/015-status.t rename to debian/modules/http-lua/t/015-status.t diff --git a/debian/modules/nginx-lua/t/016-resp-header.t b/debian/modules/http-lua/t/016-resp-header.t similarity index 100% rename from debian/modules/nginx-lua/t/016-resp-header.t rename to debian/modules/http-lua/t/016-resp-header.t diff --git a/debian/modules/nginx-lua/t/017-exec.t b/debian/modules/http-lua/t/017-exec.t similarity index 100% rename from debian/modules/nginx-lua/t/017-exec.t rename to debian/modules/http-lua/t/017-exec.t diff --git a/debian/modules/nginx-lua/t/018-ndk.t b/debian/modules/http-lua/t/018-ndk.t similarity index 100% rename from debian/modules/nginx-lua/t/018-ndk.t rename to debian/modules/http-lua/t/018-ndk.t diff --git a/debian/modules/nginx-lua/t/019-const.t b/debian/modules/http-lua/t/019-const.t similarity index 100% rename from debian/modules/nginx-lua/t/019-const.t rename to debian/modules/http-lua/t/019-const.t diff --git a/debian/modules/nginx-lua/t/020-subrequest.t b/debian/modules/http-lua/t/020-subrequest.t similarity index 100% rename from debian/modules/nginx-lua/t/020-subrequest.t rename to debian/modules/http-lua/t/020-subrequest.t diff --git a/debian/modules/nginx-lua/t/021-cookie-time.t b/debian/modules/http-lua/t/021-cookie-time.t similarity index 100% rename from debian/modules/nginx-lua/t/021-cookie-time.t rename to debian/modules/http-lua/t/021-cookie-time.t diff --git a/debian/modules/nginx-lua/t/022-redirect.t b/debian/modules/http-lua/t/022-redirect.t similarity index 100% rename from debian/modules/nginx-lua/t/022-redirect.t rename to debian/modules/http-lua/t/022-redirect.t diff --git a/debian/modules/nginx-lua/t/023-rewrite/client-abort.t b/debian/modules/http-lua/t/023-rewrite/client-abort.t similarity index 100% rename from debian/modules/nginx-lua/t/023-rewrite/client-abort.t rename to debian/modules/http-lua/t/023-rewrite/client-abort.t diff --git a/debian/modules/nginx-lua/t/023-rewrite/exec.t b/debian/modules/http-lua/t/023-rewrite/exec.t similarity index 100% rename from debian/modules/nginx-lua/t/023-rewrite/exec.t rename to debian/modules/http-lua/t/023-rewrite/exec.t diff --git a/debian/modules/nginx-lua/t/023-rewrite/exit.t b/debian/modules/http-lua/t/023-rewrite/exit.t similarity index 100% rename from debian/modules/nginx-lua/t/023-rewrite/exit.t rename to debian/modules/http-lua/t/023-rewrite/exit.t diff --git a/debian/modules/nginx-lua/t/023-rewrite/mixed.t b/debian/modules/http-lua/t/023-rewrite/mixed.t similarity index 100% rename from debian/modules/nginx-lua/t/023-rewrite/mixed.t rename to debian/modules/http-lua/t/023-rewrite/mixed.t diff --git a/debian/modules/nginx-lua/t/023-rewrite/multi-capture.t b/debian/modules/http-lua/t/023-rewrite/multi-capture.t similarity index 100% rename from debian/modules/nginx-lua/t/023-rewrite/multi-capture.t rename to debian/modules/http-lua/t/023-rewrite/multi-capture.t diff --git a/debian/modules/nginx-lua/t/023-rewrite/on-abort.t b/debian/modules/http-lua/t/023-rewrite/on-abort.t similarity index 100% rename from debian/modules/nginx-lua/t/023-rewrite/on-abort.t rename to debian/modules/http-lua/t/023-rewrite/on-abort.t diff --git a/debian/modules/nginx-lua/t/023-rewrite/redirect.t b/debian/modules/http-lua/t/023-rewrite/redirect.t similarity index 100% rename from debian/modules/nginx-lua/t/023-rewrite/redirect.t rename to debian/modules/http-lua/t/023-rewrite/redirect.t diff --git a/debian/modules/nginx-lua/t/023-rewrite/req-body.t b/debian/modules/http-lua/t/023-rewrite/req-body.t similarity index 100% rename from debian/modules/nginx-lua/t/023-rewrite/req-body.t rename to debian/modules/http-lua/t/023-rewrite/req-body.t diff --git a/debian/modules/nginx-lua/t/023-rewrite/req-socket.t b/debian/modules/http-lua/t/023-rewrite/req-socket.t similarity index 100% rename from debian/modules/nginx-lua/t/023-rewrite/req-socket.t rename to debian/modules/http-lua/t/023-rewrite/req-socket.t diff --git a/debian/modules/nginx-lua/t/023-rewrite/request_body.t b/debian/modules/http-lua/t/023-rewrite/request_body.t similarity index 100% rename from debian/modules/nginx-lua/t/023-rewrite/request_body.t rename to debian/modules/http-lua/t/023-rewrite/request_body.t diff --git a/debian/modules/nginx-lua/t/023-rewrite/sanity.t b/debian/modules/http-lua/t/023-rewrite/sanity.t similarity index 100% rename from debian/modules/nginx-lua/t/023-rewrite/sanity.t rename to debian/modules/http-lua/t/023-rewrite/sanity.t diff --git a/debian/modules/nginx-lua/t/023-rewrite/sleep.t b/debian/modules/http-lua/t/023-rewrite/sleep.t similarity index 100% rename from debian/modules/nginx-lua/t/023-rewrite/sleep.t rename to debian/modules/http-lua/t/023-rewrite/sleep.t diff --git a/debian/modules/nginx-lua/t/023-rewrite/socket-keepalive.t b/debian/modules/http-lua/t/023-rewrite/socket-keepalive.t similarity index 100% rename from debian/modules/nginx-lua/t/023-rewrite/socket-keepalive.t rename to debian/modules/http-lua/t/023-rewrite/socket-keepalive.t diff --git a/debian/modules/nginx-lua/t/023-rewrite/subrequest.t b/debian/modules/http-lua/t/023-rewrite/subrequest.t similarity index 100% rename from debian/modules/nginx-lua/t/023-rewrite/subrequest.t rename to debian/modules/http-lua/t/023-rewrite/subrequest.t diff --git a/debian/modules/nginx-lua/t/023-rewrite/tcp-socket-timeout.t b/debian/modules/http-lua/t/023-rewrite/tcp-socket-timeout.t similarity index 100% rename from debian/modules/nginx-lua/t/023-rewrite/tcp-socket-timeout.t rename to debian/modules/http-lua/t/023-rewrite/tcp-socket-timeout.t diff --git a/debian/modules/nginx-lua/t/023-rewrite/tcp-socket.t b/debian/modules/http-lua/t/023-rewrite/tcp-socket.t similarity index 100% rename from debian/modules/nginx-lua/t/023-rewrite/tcp-socket.t rename to debian/modules/http-lua/t/023-rewrite/tcp-socket.t diff --git a/debian/modules/nginx-lua/t/023-rewrite/unix-socket.t b/debian/modules/http-lua/t/023-rewrite/unix-socket.t similarity index 100% rename from debian/modules/nginx-lua/t/023-rewrite/unix-socket.t rename to debian/modules/http-lua/t/023-rewrite/unix-socket.t diff --git a/debian/modules/nginx-lua/t/023-rewrite/uthread-exec.t b/debian/modules/http-lua/t/023-rewrite/uthread-exec.t similarity index 100% rename from debian/modules/nginx-lua/t/023-rewrite/uthread-exec.t rename to debian/modules/http-lua/t/023-rewrite/uthread-exec.t diff --git a/debian/modules/nginx-lua/t/023-rewrite/uthread-exit.t b/debian/modules/http-lua/t/023-rewrite/uthread-exit.t similarity index 100% rename from debian/modules/nginx-lua/t/023-rewrite/uthread-exit.t rename to debian/modules/http-lua/t/023-rewrite/uthread-exit.t diff --git a/debian/modules/nginx-lua/t/023-rewrite/uthread-redirect.t b/debian/modules/http-lua/t/023-rewrite/uthread-redirect.t similarity index 100% rename from debian/modules/nginx-lua/t/023-rewrite/uthread-redirect.t rename to debian/modules/http-lua/t/023-rewrite/uthread-redirect.t diff --git a/debian/modules/nginx-lua/t/023-rewrite/uthread-spawn.t b/debian/modules/http-lua/t/023-rewrite/uthread-spawn.t similarity index 100% rename from debian/modules/nginx-lua/t/023-rewrite/uthread-spawn.t rename to debian/modules/http-lua/t/023-rewrite/uthread-spawn.t diff --git a/debian/modules/nginx-lua/t/024-access/auth.t b/debian/modules/http-lua/t/024-access/auth.t similarity index 100% rename from debian/modules/nginx-lua/t/024-access/auth.t rename to debian/modules/http-lua/t/024-access/auth.t diff --git a/debian/modules/nginx-lua/t/024-access/client-abort.t b/debian/modules/http-lua/t/024-access/client-abort.t similarity index 100% rename from debian/modules/nginx-lua/t/024-access/client-abort.t rename to debian/modules/http-lua/t/024-access/client-abort.t diff --git a/debian/modules/nginx-lua/t/024-access/exec.t b/debian/modules/http-lua/t/024-access/exec.t similarity index 100% rename from debian/modules/nginx-lua/t/024-access/exec.t rename to debian/modules/http-lua/t/024-access/exec.t diff --git a/debian/modules/nginx-lua/t/024-access/exit.t b/debian/modules/http-lua/t/024-access/exit.t similarity index 100% rename from debian/modules/nginx-lua/t/024-access/exit.t rename to debian/modules/http-lua/t/024-access/exit.t diff --git a/debian/modules/nginx-lua/t/024-access/mixed.t b/debian/modules/http-lua/t/024-access/mixed.t similarity index 100% rename from debian/modules/nginx-lua/t/024-access/mixed.t rename to debian/modules/http-lua/t/024-access/mixed.t diff --git a/debian/modules/nginx-lua/t/024-access/multi-capture.t b/debian/modules/http-lua/t/024-access/multi-capture.t similarity index 100% rename from debian/modules/nginx-lua/t/024-access/multi-capture.t rename to debian/modules/http-lua/t/024-access/multi-capture.t diff --git a/debian/modules/nginx-lua/t/024-access/on-abort.t b/debian/modules/http-lua/t/024-access/on-abort.t similarity index 100% rename from debian/modules/nginx-lua/t/024-access/on-abort.t rename to debian/modules/http-lua/t/024-access/on-abort.t diff --git a/debian/modules/nginx-lua/t/024-access/redirect.t b/debian/modules/http-lua/t/024-access/redirect.t similarity index 100% rename from debian/modules/nginx-lua/t/024-access/redirect.t rename to debian/modules/http-lua/t/024-access/redirect.t diff --git a/debian/modules/nginx-lua/t/024-access/req-body.t b/debian/modules/http-lua/t/024-access/req-body.t similarity index 100% rename from debian/modules/nginx-lua/t/024-access/req-body.t rename to debian/modules/http-lua/t/024-access/req-body.t diff --git a/debian/modules/nginx-lua/t/024-access/request_body.t b/debian/modules/http-lua/t/024-access/request_body.t similarity index 100% rename from debian/modules/nginx-lua/t/024-access/request_body.t rename to debian/modules/http-lua/t/024-access/request_body.t diff --git a/debian/modules/nginx-lua/t/024-access/sanity.t b/debian/modules/http-lua/t/024-access/sanity.t similarity index 100% rename from debian/modules/nginx-lua/t/024-access/sanity.t rename to debian/modules/http-lua/t/024-access/sanity.t diff --git a/debian/modules/nginx-lua/t/024-access/satisfy.t b/debian/modules/http-lua/t/024-access/satisfy.t similarity index 100% rename from debian/modules/nginx-lua/t/024-access/satisfy.t rename to debian/modules/http-lua/t/024-access/satisfy.t diff --git a/debian/modules/nginx-lua/t/024-access/sleep.t b/debian/modules/http-lua/t/024-access/sleep.t similarity index 100% rename from debian/modules/nginx-lua/t/024-access/sleep.t rename to debian/modules/http-lua/t/024-access/sleep.t diff --git a/debian/modules/nginx-lua/t/024-access/subrequest.t b/debian/modules/http-lua/t/024-access/subrequest.t similarity index 100% rename from debian/modules/nginx-lua/t/024-access/subrequest.t rename to debian/modules/http-lua/t/024-access/subrequest.t diff --git a/debian/modules/nginx-lua/t/024-access/uthread-exec.t b/debian/modules/http-lua/t/024-access/uthread-exec.t similarity index 100% rename from debian/modules/nginx-lua/t/024-access/uthread-exec.t rename to debian/modules/http-lua/t/024-access/uthread-exec.t diff --git a/debian/modules/nginx-lua/t/024-access/uthread-exit.t b/debian/modules/http-lua/t/024-access/uthread-exit.t similarity index 100% rename from debian/modules/nginx-lua/t/024-access/uthread-exit.t rename to debian/modules/http-lua/t/024-access/uthread-exit.t diff --git a/debian/modules/nginx-lua/t/024-access/uthread-redirect.t b/debian/modules/http-lua/t/024-access/uthread-redirect.t similarity index 100% rename from debian/modules/nginx-lua/t/024-access/uthread-redirect.t rename to debian/modules/http-lua/t/024-access/uthread-redirect.t diff --git a/debian/modules/nginx-lua/t/024-access/uthread-spawn.t b/debian/modules/http-lua/t/024-access/uthread-spawn.t similarity index 100% rename from debian/modules/nginx-lua/t/024-access/uthread-spawn.t rename to debian/modules/http-lua/t/024-access/uthread-spawn.t diff --git a/debian/modules/nginx-lua/t/025-codecache.t b/debian/modules/http-lua/t/025-codecache.t similarity index 100% rename from debian/modules/nginx-lua/t/025-codecache.t rename to debian/modules/http-lua/t/025-codecache.t diff --git a/debian/modules/nginx-lua/t/026-mysql.t b/debian/modules/http-lua/t/026-mysql.t similarity index 100% rename from debian/modules/nginx-lua/t/026-mysql.t rename to debian/modules/http-lua/t/026-mysql.t diff --git a/debian/modules/nginx-lua/t/027-multi-capture.t b/debian/modules/http-lua/t/027-multi-capture.t similarity index 100% rename from debian/modules/nginx-lua/t/027-multi-capture.t rename to debian/modules/http-lua/t/027-multi-capture.t diff --git a/debian/modules/nginx-lua/t/028-req-header.t b/debian/modules/http-lua/t/028-req-header.t similarity index 100% rename from debian/modules/nginx-lua/t/028-req-header.t rename to debian/modules/http-lua/t/028-req-header.t diff --git a/debian/modules/nginx-lua/t/029-http-time.t b/debian/modules/http-lua/t/029-http-time.t similarity index 100% rename from debian/modules/nginx-lua/t/029-http-time.t rename to debian/modules/http-lua/t/029-http-time.t diff --git a/debian/modules/nginx-lua/t/030-uri-args.t b/debian/modules/http-lua/t/030-uri-args.t similarity index 100% rename from debian/modules/nginx-lua/t/030-uri-args.t rename to debian/modules/http-lua/t/030-uri-args.t diff --git a/debian/modules/nginx-lua/t/031-post-args.t b/debian/modules/http-lua/t/031-post-args.t similarity index 100% rename from debian/modules/nginx-lua/t/031-post-args.t rename to debian/modules/http-lua/t/031-post-args.t diff --git a/debian/modules/nginx-lua/t/032-iolist.t b/debian/modules/http-lua/t/032-iolist.t similarity index 100% rename from debian/modules/nginx-lua/t/032-iolist.t rename to debian/modules/http-lua/t/032-iolist.t diff --git a/debian/modules/nginx-lua/t/033-ctx.t b/debian/modules/http-lua/t/033-ctx.t similarity index 100% rename from debian/modules/nginx-lua/t/033-ctx.t rename to debian/modules/http-lua/t/033-ctx.t diff --git a/debian/modules/nginx-lua/t/034-match.t b/debian/modules/http-lua/t/034-match.t similarity index 100% rename from debian/modules/nginx-lua/t/034-match.t rename to debian/modules/http-lua/t/034-match.t diff --git a/debian/modules/nginx-lua/t/035-gmatch.t b/debian/modules/http-lua/t/035-gmatch.t similarity index 100% rename from debian/modules/nginx-lua/t/035-gmatch.t rename to debian/modules/http-lua/t/035-gmatch.t diff --git a/debian/modules/nginx-lua/t/036-sub.t b/debian/modules/http-lua/t/036-sub.t similarity index 100% rename from debian/modules/nginx-lua/t/036-sub.t rename to debian/modules/http-lua/t/036-sub.t diff --git a/debian/modules/nginx-lua/t/037-gsub.t b/debian/modules/http-lua/t/037-gsub.t similarity index 100% rename from debian/modules/nginx-lua/t/037-gsub.t rename to debian/modules/http-lua/t/037-gsub.t diff --git a/debian/modules/nginx-lua/t/038-match-o.t b/debian/modules/http-lua/t/038-match-o.t similarity index 100% rename from debian/modules/nginx-lua/t/038-match-o.t rename to debian/modules/http-lua/t/038-match-o.t diff --git a/debian/modules/nginx-lua/t/039-sub-o.t b/debian/modules/http-lua/t/039-sub-o.t similarity index 100% rename from debian/modules/nginx-lua/t/039-sub-o.t rename to debian/modules/http-lua/t/039-sub-o.t diff --git a/debian/modules/nginx-lua/t/040-gsub-o.t b/debian/modules/http-lua/t/040-gsub-o.t similarity index 100% rename from debian/modules/nginx-lua/t/040-gsub-o.t rename to debian/modules/http-lua/t/040-gsub-o.t diff --git a/debian/modules/nginx-lua/t/041-header-filter.t b/debian/modules/http-lua/t/041-header-filter.t similarity index 100% rename from debian/modules/nginx-lua/t/041-header-filter.t rename to debian/modules/http-lua/t/041-header-filter.t diff --git a/debian/modules/nginx-lua/t/042-crc32.t b/debian/modules/http-lua/t/042-crc32.t similarity index 100% rename from debian/modules/nginx-lua/t/042-crc32.t rename to debian/modules/http-lua/t/042-crc32.t diff --git a/debian/modules/nginx-lua/t/043-shdict.t b/debian/modules/http-lua/t/043-shdict.t similarity index 100% rename from debian/modules/nginx-lua/t/043-shdict.t rename to debian/modules/http-lua/t/043-shdict.t diff --git a/debian/modules/nginx-lua/t/044-req-body.t b/debian/modules/http-lua/t/044-req-body.t similarity index 100% rename from debian/modules/nginx-lua/t/044-req-body.t rename to debian/modules/http-lua/t/044-req-body.t diff --git a/debian/modules/nginx-lua/t/045-ngx-var.t b/debian/modules/http-lua/t/045-ngx-var.t similarity index 100% rename from debian/modules/nginx-lua/t/045-ngx-var.t rename to debian/modules/http-lua/t/045-ngx-var.t diff --git a/debian/modules/nginx-lua/t/046-hmac.t b/debian/modules/http-lua/t/046-hmac.t similarity index 100% rename from debian/modules/nginx-lua/t/046-hmac.t rename to debian/modules/http-lua/t/046-hmac.t diff --git a/debian/modules/nginx-lua/t/047-match-jit.t b/debian/modules/http-lua/t/047-match-jit.t similarity index 100% rename from debian/modules/nginx-lua/t/047-match-jit.t rename to debian/modules/http-lua/t/047-match-jit.t diff --git a/debian/modules/nginx-lua/t/048-match-dfa.t b/debian/modules/http-lua/t/048-match-dfa.t similarity index 100% rename from debian/modules/nginx-lua/t/048-match-dfa.t rename to debian/modules/http-lua/t/048-match-dfa.t diff --git a/debian/modules/nginx-lua/t/049-gmatch-jit.t b/debian/modules/http-lua/t/049-gmatch-jit.t similarity index 100% rename from debian/modules/nginx-lua/t/049-gmatch-jit.t rename to debian/modules/http-lua/t/049-gmatch-jit.t diff --git a/debian/modules/nginx-lua/t/050-gmatch-dfa.t b/debian/modules/http-lua/t/050-gmatch-dfa.t similarity index 100% rename from debian/modules/nginx-lua/t/050-gmatch-dfa.t rename to debian/modules/http-lua/t/050-gmatch-dfa.t diff --git a/debian/modules/nginx-lua/t/051-sub-jit.t b/debian/modules/http-lua/t/051-sub-jit.t similarity index 100% rename from debian/modules/nginx-lua/t/051-sub-jit.t rename to debian/modules/http-lua/t/051-sub-jit.t diff --git a/debian/modules/nginx-lua/t/052-sub-dfa.t b/debian/modules/http-lua/t/052-sub-dfa.t similarity index 100% rename from debian/modules/nginx-lua/t/052-sub-dfa.t rename to debian/modules/http-lua/t/052-sub-dfa.t diff --git a/debian/modules/nginx-lua/t/053-gsub-jit.t b/debian/modules/http-lua/t/053-gsub-jit.t similarity index 100% rename from debian/modules/nginx-lua/t/053-gsub-jit.t rename to debian/modules/http-lua/t/053-gsub-jit.t diff --git a/debian/modules/nginx-lua/t/054-gsub-dfa.t b/debian/modules/http-lua/t/054-gsub-dfa.t similarity index 100% rename from debian/modules/nginx-lua/t/054-gsub-dfa.t rename to debian/modules/http-lua/t/054-gsub-dfa.t diff --git a/debian/modules/nginx-lua/t/055-subreq-vars.t b/debian/modules/http-lua/t/055-subreq-vars.t similarity index 100% rename from debian/modules/nginx-lua/t/055-subreq-vars.t rename to debian/modules/http-lua/t/055-subreq-vars.t diff --git a/debian/modules/nginx-lua/t/056-flush.t b/debian/modules/http-lua/t/056-flush.t similarity index 100% rename from debian/modules/nginx-lua/t/056-flush.t rename to debian/modules/http-lua/t/056-flush.t diff --git a/debian/modules/nginx-lua/t/057-flush-timeout.t b/debian/modules/http-lua/t/057-flush-timeout.t similarity index 100% rename from debian/modules/nginx-lua/t/057-flush-timeout.t rename to debian/modules/http-lua/t/057-flush-timeout.t diff --git a/debian/modules/nginx-lua/t/058-tcp-socket.t b/debian/modules/http-lua/t/058-tcp-socket.t similarity index 100% rename from debian/modules/nginx-lua/t/058-tcp-socket.t rename to debian/modules/http-lua/t/058-tcp-socket.t diff --git a/debian/modules/nginx-lua/t/059-unix-socket.t b/debian/modules/http-lua/t/059-unix-socket.t similarity index 100% rename from debian/modules/nginx-lua/t/059-unix-socket.t rename to debian/modules/http-lua/t/059-unix-socket.t diff --git a/debian/modules/nginx-lua/t/060-lua-memcached.t b/debian/modules/http-lua/t/060-lua-memcached.t similarity index 100% rename from debian/modules/nginx-lua/t/060-lua-memcached.t rename to debian/modules/http-lua/t/060-lua-memcached.t diff --git a/debian/modules/nginx-lua/t/061-lua-redis.t b/debian/modules/http-lua/t/061-lua-redis.t similarity index 100% rename from debian/modules/nginx-lua/t/061-lua-redis.t rename to debian/modules/http-lua/t/061-lua-redis.t diff --git a/debian/modules/nginx-lua/t/062-count.t b/debian/modules/http-lua/t/062-count.t similarity index 100% rename from debian/modules/nginx-lua/t/062-count.t rename to debian/modules/http-lua/t/062-count.t diff --git a/debian/modules/nginx-lua/t/063-abort.t b/debian/modules/http-lua/t/063-abort.t similarity index 100% rename from debian/modules/nginx-lua/t/063-abort.t rename to debian/modules/http-lua/t/063-abort.t diff --git a/debian/modules/nginx-lua/t/064-pcall.t b/debian/modules/http-lua/t/064-pcall.t similarity index 100% rename from debian/modules/nginx-lua/t/064-pcall.t rename to debian/modules/http-lua/t/064-pcall.t diff --git a/debian/modules/nginx-lua/t/065-tcp-socket-timeout.t b/debian/modules/http-lua/t/065-tcp-socket-timeout.t similarity index 100% rename from debian/modules/nginx-lua/t/065-tcp-socket-timeout.t rename to debian/modules/http-lua/t/065-tcp-socket-timeout.t diff --git a/debian/modules/nginx-lua/t/066-socket-receiveuntil.t b/debian/modules/http-lua/t/066-socket-receiveuntil.t similarity index 100% rename from debian/modules/nginx-lua/t/066-socket-receiveuntil.t rename to debian/modules/http-lua/t/066-socket-receiveuntil.t diff --git a/debian/modules/nginx-lua/t/067-req-socket.t b/debian/modules/http-lua/t/067-req-socket.t similarity index 100% rename from debian/modules/nginx-lua/t/067-req-socket.t rename to debian/modules/http-lua/t/067-req-socket.t diff --git a/debian/modules/nginx-lua/t/068-socket-keepalive.t b/debian/modules/http-lua/t/068-socket-keepalive.t similarity index 100% rename from debian/modules/nginx-lua/t/068-socket-keepalive.t rename to debian/modules/http-lua/t/068-socket-keepalive.t diff --git a/debian/modules/nginx-lua/t/069-null.t b/debian/modules/http-lua/t/069-null.t similarity index 100% rename from debian/modules/nginx-lua/t/069-null.t rename to debian/modules/http-lua/t/069-null.t diff --git a/debian/modules/nginx-lua/t/070-sha1.t b/debian/modules/http-lua/t/070-sha1.t similarity index 100% rename from debian/modules/nginx-lua/t/070-sha1.t rename to debian/modules/http-lua/t/070-sha1.t diff --git a/debian/modules/nginx-lua/t/071-idle-socket.t b/debian/modules/http-lua/t/071-idle-socket.t similarity index 100% rename from debian/modules/nginx-lua/t/071-idle-socket.t rename to debian/modules/http-lua/t/071-idle-socket.t diff --git a/debian/modules/nginx-lua/t/072-conditional-get.t b/debian/modules/http-lua/t/072-conditional-get.t similarity index 100% rename from debian/modules/nginx-lua/t/072-conditional-get.t rename to debian/modules/http-lua/t/072-conditional-get.t diff --git a/debian/modules/nginx-lua/t/073-backtrace.t b/debian/modules/http-lua/t/073-backtrace.t similarity index 100% rename from debian/modules/nginx-lua/t/073-backtrace.t rename to debian/modules/http-lua/t/073-backtrace.t diff --git a/debian/modules/nginx-lua/t/074-prefix-var.t b/debian/modules/http-lua/t/074-prefix-var.t similarity index 100% rename from debian/modules/nginx-lua/t/074-prefix-var.t rename to debian/modules/http-lua/t/074-prefix-var.t diff --git a/debian/modules/nginx-lua/t/075-logby.t b/debian/modules/http-lua/t/075-logby.t similarity index 100% rename from debian/modules/nginx-lua/t/075-logby.t rename to debian/modules/http-lua/t/075-logby.t diff --git a/debian/modules/nginx-lua/t/076-no-postpone.t b/debian/modules/http-lua/t/076-no-postpone.t similarity index 100% rename from debian/modules/nginx-lua/t/076-no-postpone.t rename to debian/modules/http-lua/t/076-no-postpone.t diff --git a/debian/modules/nginx-lua/t/077-sleep.t b/debian/modules/http-lua/t/077-sleep.t similarity index 100% rename from debian/modules/nginx-lua/t/077-sleep.t rename to debian/modules/http-lua/t/077-sleep.t diff --git a/debian/modules/nginx-lua/t/078-hup-vars.t b/debian/modules/http-lua/t/078-hup-vars.t similarity index 100% rename from debian/modules/nginx-lua/t/078-hup-vars.t rename to debian/modules/http-lua/t/078-hup-vars.t diff --git a/debian/modules/nginx-lua/t/079-unused-directives.t b/debian/modules/http-lua/t/079-unused-directives.t similarity index 100% rename from debian/modules/nginx-lua/t/079-unused-directives.t rename to debian/modules/http-lua/t/079-unused-directives.t diff --git a/debian/modules/nginx-lua/t/080-hup-shdict.t b/debian/modules/http-lua/t/080-hup-shdict.t similarity index 100% rename from debian/modules/nginx-lua/t/080-hup-shdict.t rename to debian/modules/http-lua/t/080-hup-shdict.t diff --git a/debian/modules/nginx-lua/t/081-bytecode.t b/debian/modules/http-lua/t/081-bytecode.t similarity index 100% rename from debian/modules/nginx-lua/t/081-bytecode.t rename to debian/modules/http-lua/t/081-bytecode.t diff --git a/debian/modules/nginx-lua/t/082-body-filter.t b/debian/modules/http-lua/t/082-body-filter.t similarity index 100% rename from debian/modules/nginx-lua/t/082-body-filter.t rename to debian/modules/http-lua/t/082-body-filter.t diff --git a/debian/modules/nginx-lua/t/083-bad-sock-self.t b/debian/modules/http-lua/t/083-bad-sock-self.t similarity index 100% rename from debian/modules/nginx-lua/t/083-bad-sock-self.t rename to debian/modules/http-lua/t/083-bad-sock-self.t diff --git a/debian/modules/nginx-lua/t/084-inclusive-receiveuntil.t b/debian/modules/http-lua/t/084-inclusive-receiveuntil.t similarity index 100% rename from debian/modules/nginx-lua/t/084-inclusive-receiveuntil.t rename to debian/modules/http-lua/t/084-inclusive-receiveuntil.t diff --git a/debian/modules/nginx-lua/t/085-if.t b/debian/modules/http-lua/t/085-if.t similarity index 100% rename from debian/modules/nginx-lua/t/085-if.t rename to debian/modules/http-lua/t/085-if.t diff --git a/debian/modules/nginx-lua/t/086-init-by.t b/debian/modules/http-lua/t/086-init-by.t similarity index 100% rename from debian/modules/nginx-lua/t/086-init-by.t rename to debian/modules/http-lua/t/086-init-by.t diff --git a/debian/modules/nginx-lua/t/087-udp-socket.t b/debian/modules/http-lua/t/087-udp-socket.t similarity index 100% rename from debian/modules/nginx-lua/t/087-udp-socket.t rename to debian/modules/http-lua/t/087-udp-socket.t diff --git a/debian/modules/nginx-lua/t/088-req-method.t b/debian/modules/http-lua/t/088-req-method.t similarity index 100% rename from debian/modules/nginx-lua/t/088-req-method.t rename to debian/modules/http-lua/t/088-req-method.t diff --git a/debian/modules/nginx-lua/t/089-phase.t b/debian/modules/http-lua/t/089-phase.t similarity index 100% rename from debian/modules/nginx-lua/t/089-phase.t rename to debian/modules/http-lua/t/089-phase.t diff --git a/debian/modules/nginx-lua/t/090-log-socket-errors.t b/debian/modules/http-lua/t/090-log-socket-errors.t similarity index 100% rename from debian/modules/nginx-lua/t/090-log-socket-errors.t rename to debian/modules/http-lua/t/090-log-socket-errors.t diff --git a/debian/modules/nginx-lua/t/091-coroutine.t b/debian/modules/http-lua/t/091-coroutine.t similarity index 100% rename from debian/modules/nginx-lua/t/091-coroutine.t rename to debian/modules/http-lua/t/091-coroutine.t diff --git a/debian/modules/nginx-lua/t/092-eof.t b/debian/modules/http-lua/t/092-eof.t similarity index 100% rename from debian/modules/nginx-lua/t/092-eof.t rename to debian/modules/http-lua/t/092-eof.t diff --git a/debian/modules/nginx-lua/t/093-uthread-spawn.t b/debian/modules/http-lua/t/093-uthread-spawn.t similarity index 100% rename from debian/modules/nginx-lua/t/093-uthread-spawn.t rename to debian/modules/http-lua/t/093-uthread-spawn.t diff --git a/debian/modules/nginx-lua/t/094-uthread-exit.t b/debian/modules/http-lua/t/094-uthread-exit.t similarity index 100% rename from debian/modules/nginx-lua/t/094-uthread-exit.t rename to debian/modules/http-lua/t/094-uthread-exit.t diff --git a/debian/modules/nginx-lua/t/095-uthread-exec.t b/debian/modules/http-lua/t/095-uthread-exec.t similarity index 100% rename from debian/modules/nginx-lua/t/095-uthread-exec.t rename to debian/modules/http-lua/t/095-uthread-exec.t diff --git a/debian/modules/nginx-lua/t/096-uthread-redirect.t b/debian/modules/http-lua/t/096-uthread-redirect.t similarity index 100% rename from debian/modules/nginx-lua/t/096-uthread-redirect.t rename to debian/modules/http-lua/t/096-uthread-redirect.t diff --git a/debian/modules/nginx-lua/t/097-uthread-rewrite.t b/debian/modules/http-lua/t/097-uthread-rewrite.t similarity index 100% rename from debian/modules/nginx-lua/t/097-uthread-rewrite.t rename to debian/modules/http-lua/t/097-uthread-rewrite.t diff --git a/debian/modules/nginx-lua/t/098-uthread-wait.t b/debian/modules/http-lua/t/098-uthread-wait.t similarity index 100% rename from debian/modules/nginx-lua/t/098-uthread-wait.t rename to debian/modules/http-lua/t/098-uthread-wait.t diff --git a/debian/modules/nginx-lua/t/099-c-api.t b/debian/modules/http-lua/t/099-c-api.t similarity index 100% rename from debian/modules/nginx-lua/t/099-c-api.t rename to debian/modules/http-lua/t/099-c-api.t diff --git a/debian/modules/nginx-lua/t/100-client-abort.t b/debian/modules/http-lua/t/100-client-abort.t similarity index 100% rename from debian/modules/nginx-lua/t/100-client-abort.t rename to debian/modules/http-lua/t/100-client-abort.t diff --git a/debian/modules/nginx-lua/t/101-on-abort.t b/debian/modules/http-lua/t/101-on-abort.t similarity index 100% rename from debian/modules/nginx-lua/t/101-on-abort.t rename to debian/modules/http-lua/t/101-on-abort.t diff --git a/debian/modules/nginx-lua/t/102-req-start-time.t b/debian/modules/http-lua/t/102-req-start-time.t similarity index 100% rename from debian/modules/nginx-lua/t/102-req-start-time.t rename to debian/modules/http-lua/t/102-req-start-time.t diff --git a/debian/modules/nginx-lua/t/103-req-http-ver.t b/debian/modules/http-lua/t/103-req-http-ver.t similarity index 100% rename from debian/modules/nginx-lua/t/103-req-http-ver.t rename to debian/modules/http-lua/t/103-req-http-ver.t diff --git a/debian/modules/nginx-lua/t/104-req-raw-header.t b/debian/modules/http-lua/t/104-req-raw-header.t similarity index 100% rename from debian/modules/nginx-lua/t/104-req-raw-header.t rename to debian/modules/http-lua/t/104-req-raw-header.t diff --git a/debian/modules/nginx-lua/t/105-pressure.t b/debian/modules/http-lua/t/105-pressure.t similarity index 100% rename from debian/modules/nginx-lua/t/105-pressure.t rename to debian/modules/http-lua/t/105-pressure.t diff --git a/debian/modules/nginx-lua/t/106-timer.t b/debian/modules/http-lua/t/106-timer.t similarity index 100% rename from debian/modules/nginx-lua/t/106-timer.t rename to debian/modules/http-lua/t/106-timer.t diff --git a/debian/modules/nginx-lua/t/107-timer-errors.t b/debian/modules/http-lua/t/107-timer-errors.t similarity index 100% rename from debian/modules/nginx-lua/t/107-timer-errors.t rename to debian/modules/http-lua/t/107-timer-errors.t diff --git a/debian/modules/nginx-lua/t/108-timer-safe.t b/debian/modules/http-lua/t/108-timer-safe.t similarity index 100% rename from debian/modules/nginx-lua/t/108-timer-safe.t rename to debian/modules/http-lua/t/108-timer-safe.t diff --git a/debian/modules/nginx-lua/t/109-timer-hup.t b/debian/modules/http-lua/t/109-timer-hup.t similarity index 100% rename from debian/modules/nginx-lua/t/109-timer-hup.t rename to debian/modules/http-lua/t/109-timer-hup.t diff --git a/debian/modules/nginx-lua/t/110-etag.t b/debian/modules/http-lua/t/110-etag.t similarity index 100% rename from debian/modules/nginx-lua/t/110-etag.t rename to debian/modules/http-lua/t/110-etag.t diff --git a/debian/modules/nginx-lua/t/111-req-header-ua.t b/debian/modules/http-lua/t/111-req-header-ua.t similarity index 100% rename from debian/modules/nginx-lua/t/111-req-header-ua.t rename to debian/modules/http-lua/t/111-req-header-ua.t diff --git a/debian/modules/nginx-lua/t/112-req-header-conn.t b/debian/modules/http-lua/t/112-req-header-conn.t similarity index 100% rename from debian/modules/nginx-lua/t/112-req-header-conn.t rename to debian/modules/http-lua/t/112-req-header-conn.t diff --git a/debian/modules/nginx-lua/t/113-req-header-cookie.t b/debian/modules/http-lua/t/113-req-header-cookie.t similarity index 100% rename from debian/modules/nginx-lua/t/113-req-header-cookie.t rename to debian/modules/http-lua/t/113-req-header-cookie.t diff --git a/debian/modules/nginx-lua/t/114-config.t b/debian/modules/http-lua/t/114-config.t similarity index 100% rename from debian/modules/nginx-lua/t/114-config.t rename to debian/modules/http-lua/t/114-config.t diff --git a/debian/modules/nginx-lua/t/115-quote-sql-str.t b/debian/modules/http-lua/t/115-quote-sql-str.t similarity index 100% rename from debian/modules/nginx-lua/t/115-quote-sql-str.t rename to debian/modules/http-lua/t/115-quote-sql-str.t diff --git a/debian/modules/nginx-lua/t/116-raw-req-socket.t b/debian/modules/http-lua/t/116-raw-req-socket.t similarity index 100% rename from debian/modules/nginx-lua/t/116-raw-req-socket.t rename to debian/modules/http-lua/t/116-raw-req-socket.t diff --git a/debian/modules/nginx-lua/t/117-raw-req-socket-timeout.t b/debian/modules/http-lua/t/117-raw-req-socket-timeout.t similarity index 100% rename from debian/modules/nginx-lua/t/117-raw-req-socket-timeout.t rename to debian/modules/http-lua/t/117-raw-req-socket-timeout.t diff --git a/debian/modules/nginx-lua/t/118-use-default-type.t b/debian/modules/http-lua/t/118-use-default-type.t similarity index 100% rename from debian/modules/nginx-lua/t/118-use-default-type.t rename to debian/modules/http-lua/t/118-use-default-type.t diff --git a/debian/modules/nginx-lua/t/119-config-prefix.t b/debian/modules/http-lua/t/119-config-prefix.t similarity index 100% rename from debian/modules/nginx-lua/t/119-config-prefix.t rename to debian/modules/http-lua/t/119-config-prefix.t diff --git a/debian/modules/nginx-lua/t/120-re-find.t b/debian/modules/http-lua/t/120-re-find.t similarity index 100% rename from debian/modules/nginx-lua/t/120-re-find.t rename to debian/modules/http-lua/t/120-re-find.t diff --git a/debian/modules/nginx-lua/t/121-version.t b/debian/modules/http-lua/t/121-version.t similarity index 100% rename from debian/modules/nginx-lua/t/121-version.t rename to debian/modules/http-lua/t/121-version.t diff --git a/debian/modules/nginx-lua/t/122-worker.t b/debian/modules/http-lua/t/122-worker.t similarity index 100% rename from debian/modules/nginx-lua/t/122-worker.t rename to debian/modules/http-lua/t/122-worker.t diff --git a/debian/modules/nginx-lua/t/123-lua-path.t b/debian/modules/http-lua/t/123-lua-path.t similarity index 100% rename from debian/modules/nginx-lua/t/123-lua-path.t rename to debian/modules/http-lua/t/123-lua-path.t diff --git a/debian/modules/nginx-lua/t/124-init-worker.t b/debian/modules/http-lua/t/124-init-worker.t similarity index 100% rename from debian/modules/nginx-lua/t/124-init-worker.t rename to debian/modules/http-lua/t/124-init-worker.t diff --git a/debian/modules/nginx-lua/t/125-configure-args.t b/debian/modules/http-lua/t/125-configure-args.t similarity index 100% rename from debian/modules/nginx-lua/t/125-configure-args.t rename to debian/modules/http-lua/t/125-configure-args.t diff --git a/debian/modules/nginx-lua/t/126-shdict-frag.t b/debian/modules/http-lua/t/126-shdict-frag.t similarity index 100% rename from debian/modules/nginx-lua/t/126-shdict-frag.t rename to debian/modules/http-lua/t/126-shdict-frag.t diff --git a/debian/modules/nginx-lua/t/127-uthread-kill.t b/debian/modules/http-lua/t/127-uthread-kill.t similarity index 100% rename from debian/modules/nginx-lua/t/127-uthread-kill.t rename to debian/modules/http-lua/t/127-uthread-kill.t diff --git a/debian/modules/nginx-lua/t/128-duplex-tcp-socket.t b/debian/modules/http-lua/t/128-duplex-tcp-socket.t similarity index 100% rename from debian/modules/nginx-lua/t/128-duplex-tcp-socket.t rename to debian/modules/http-lua/t/128-duplex-tcp-socket.t diff --git a/debian/modules/nginx-lua/t/129-ssl-socket.t b/debian/modules/http-lua/t/129-ssl-socket.t similarity index 100% rename from debian/modules/nginx-lua/t/129-ssl-socket.t rename to debian/modules/http-lua/t/129-ssl-socket.t diff --git a/debian/modules/nginx-lua/t/130-internal-api.t b/debian/modules/http-lua/t/130-internal-api.t similarity index 100% rename from debian/modules/nginx-lua/t/130-internal-api.t rename to debian/modules/http-lua/t/130-internal-api.t diff --git a/debian/modules/nginx-lua/t/131-duplex-req-socket.t b/debian/modules/http-lua/t/131-duplex-req-socket.t similarity index 100% rename from debian/modules/nginx-lua/t/131-duplex-req-socket.t rename to debian/modules/http-lua/t/131-duplex-req-socket.t diff --git a/debian/modules/nginx-lua/t/132-lua-blocks.t b/debian/modules/http-lua/t/132-lua-blocks.t similarity index 100% rename from debian/modules/nginx-lua/t/132-lua-blocks.t rename to debian/modules/http-lua/t/132-lua-blocks.t diff --git a/debian/modules/nginx-lua/t/133-worker-count.t b/debian/modules/http-lua/t/133-worker-count.t similarity index 100% rename from debian/modules/nginx-lua/t/133-worker-count.t rename to debian/modules/http-lua/t/133-worker-count.t diff --git a/debian/modules/nginx-lua/t/134-worker-count-5.t b/debian/modules/http-lua/t/134-worker-count-5.t similarity index 100% rename from debian/modules/nginx-lua/t/134-worker-count-5.t rename to debian/modules/http-lua/t/134-worker-count-5.t diff --git a/debian/modules/nginx-lua/t/135-worker-id.t b/debian/modules/http-lua/t/135-worker-id.t similarity index 100% rename from debian/modules/nginx-lua/t/135-worker-id.t rename to debian/modules/http-lua/t/135-worker-id.t diff --git a/debian/modules/nginx-lua/t/136-timer-counts.t b/debian/modules/http-lua/t/136-timer-counts.t similarity index 100% rename from debian/modules/nginx-lua/t/136-timer-counts.t rename to debian/modules/http-lua/t/136-timer-counts.t diff --git a/debian/modules/nginx-lua/t/137-req-misc.t b/debian/modules/http-lua/t/137-req-misc.t similarity index 100% rename from debian/modules/nginx-lua/t/137-req-misc.t rename to debian/modules/http-lua/t/137-req-misc.t diff --git a/debian/modules/nginx-lua/t/138-balancer.t b/debian/modules/http-lua/t/138-balancer.t similarity index 100% rename from debian/modules/nginx-lua/t/138-balancer.t rename to debian/modules/http-lua/t/138-balancer.t diff --git a/debian/modules/nginx-lua/t/139-ssl-cert-by.t b/debian/modules/http-lua/t/139-ssl-cert-by.t similarity index 100% rename from debian/modules/nginx-lua/t/139-ssl-cert-by.t rename to debian/modules/http-lua/t/139-ssl-cert-by.t diff --git a/debian/modules/nginx-lua/t/140-ssl-c-api.t b/debian/modules/http-lua/t/140-ssl-c-api.t similarity index 100% rename from debian/modules/nginx-lua/t/140-ssl-c-api.t rename to debian/modules/http-lua/t/140-ssl-c-api.t diff --git a/debian/modules/nginx-lua/t/141-luajit.t b/debian/modules/http-lua/t/141-luajit.t similarity index 100% rename from debian/modules/nginx-lua/t/141-luajit.t rename to debian/modules/http-lua/t/141-luajit.t diff --git a/debian/modules/nginx-lua/t/142-ssl-session-store.t b/debian/modules/http-lua/t/142-ssl-session-store.t similarity index 100% rename from debian/modules/nginx-lua/t/142-ssl-session-store.t rename to debian/modules/http-lua/t/142-ssl-session-store.t diff --git a/debian/modules/nginx-lua/t/143-ssl-session-fetch.t b/debian/modules/http-lua/t/143-ssl-session-fetch.t similarity index 100% rename from debian/modules/nginx-lua/t/143-ssl-session-fetch.t rename to debian/modules/http-lua/t/143-ssl-session-fetch.t diff --git a/debian/modules/nginx-lua/t/144-shdict-incr-init.t b/debian/modules/http-lua/t/144-shdict-incr-init.t similarity index 100% rename from debian/modules/nginx-lua/t/144-shdict-incr-init.t rename to debian/modules/http-lua/t/144-shdict-incr-init.t diff --git a/debian/modules/nginx-lua/t/145-shdict-list.t b/debian/modules/http-lua/t/145-shdict-list.t similarity index 100% rename from debian/modules/nginx-lua/t/145-shdict-list.t rename to debian/modules/http-lua/t/145-shdict-list.t diff --git a/debian/modules/nginx-lua/t/146-malloc-trim.t b/debian/modules/http-lua/t/146-malloc-trim.t similarity index 100% rename from debian/modules/nginx-lua/t/146-malloc-trim.t rename to debian/modules/http-lua/t/146-malloc-trim.t diff --git a/debian/modules/nginx-lua/t/147-tcp-socket-timeouts.t b/debian/modules/http-lua/t/147-tcp-socket-timeouts.t similarity index 100% rename from debian/modules/nginx-lua/t/147-tcp-socket-timeouts.t rename to debian/modules/http-lua/t/147-tcp-socket-timeouts.t diff --git a/debian/modules/nginx-lua/t/148-fake-shm-zone.t b/debian/modules/http-lua/t/148-fake-shm-zone.t similarity index 100% rename from debian/modules/nginx-lua/t/148-fake-shm-zone.t rename to debian/modules/http-lua/t/148-fake-shm-zone.t diff --git a/debian/modules/nginx-lua/t/149-hup-fake-shm-zone.t b/debian/modules/http-lua/t/149-hup-fake-shm-zone.t similarity index 100% rename from debian/modules/nginx-lua/t/149-hup-fake-shm-zone.t rename to debian/modules/http-lua/t/149-hup-fake-shm-zone.t diff --git a/debian/modules/nginx-lua/t/150-fake-delayed-load.t b/debian/modules/http-lua/t/150-fake-delayed-load.t similarity index 100% rename from debian/modules/nginx-lua/t/150-fake-delayed-load.t rename to debian/modules/http-lua/t/150-fake-delayed-load.t diff --git a/debian/modules/nginx-lua/t/151-initby-hup.t b/debian/modules/http-lua/t/151-initby-hup.t similarity index 100% rename from debian/modules/nginx-lua/t/151-initby-hup.t rename to debian/modules/http-lua/t/151-initby-hup.t diff --git a/debian/modules/nginx-lua/t/152-timer-every.t b/debian/modules/http-lua/t/152-timer-every.t similarity index 100% rename from debian/modules/nginx-lua/t/152-timer-every.t rename to debian/modules/http-lua/t/152-timer-every.t diff --git a/debian/modules/nginx-lua/t/153-semaphore-hup.t b/debian/modules/http-lua/t/153-semaphore-hup.t similarity index 100% rename from debian/modules/nginx-lua/t/153-semaphore-hup.t rename to debian/modules/http-lua/t/153-semaphore-hup.t diff --git a/debian/modules/nginx-lua/t/154-semaphore.t b/debian/modules/http-lua/t/154-semaphore.t similarity index 100% rename from debian/modules/nginx-lua/t/154-semaphore.t rename to debian/modules/http-lua/t/154-semaphore.t diff --git a/debian/modules/nginx-lua/t/StapThread.pm b/debian/modules/http-lua/t/StapThread.pm similarity index 100% rename from debian/modules/nginx-lua/t/StapThread.pm rename to debian/modules/http-lua/t/StapThread.pm diff --git a/debian/modules/nginx-lua/t/cert/comodo-ca.crt b/debian/modules/http-lua/t/cert/comodo-ca.crt similarity index 100% rename from debian/modules/nginx-lua/t/cert/comodo-ca.crt rename to debian/modules/http-lua/t/cert/comodo-ca.crt diff --git a/debian/modules/nginx-lua/t/cert/equifax.crt b/debian/modules/http-lua/t/cert/equifax.crt similarity index 100% rename from debian/modules/nginx-lua/t/cert/equifax.crt rename to debian/modules/http-lua/t/cert/equifax.crt diff --git a/debian/modules/nginx-lua/t/cert/test.crl b/debian/modules/http-lua/t/cert/test.crl similarity index 100% rename from debian/modules/nginx-lua/t/cert/test.crl rename to debian/modules/http-lua/t/cert/test.crl diff --git a/debian/modules/nginx-lua/t/cert/test.crt b/debian/modules/http-lua/t/cert/test.crt similarity index 100% rename from debian/modules/nginx-lua/t/cert/test.crt rename to debian/modules/http-lua/t/cert/test.crt diff --git a/debian/modules/nginx-lua/t/cert/test.key b/debian/modules/http-lua/t/cert/test.key similarity index 100% rename from debian/modules/nginx-lua/t/cert/test.key rename to debian/modules/http-lua/t/cert/test.key diff --git a/debian/modules/nginx-lua/t/cert/test2.crt b/debian/modules/http-lua/t/cert/test2.crt similarity index 100% rename from debian/modules/nginx-lua/t/cert/test2.crt rename to debian/modules/http-lua/t/cert/test2.crt diff --git a/debian/modules/nginx-lua/t/cert/test2.key b/debian/modules/http-lua/t/cert/test2.key similarity index 100% rename from debian/modules/nginx-lua/t/cert/test2.key rename to debian/modules/http-lua/t/cert/test2.key diff --git a/debian/modules/nginx-lua/t/cert/test_ecdsa.crt b/debian/modules/http-lua/t/cert/test_ecdsa.crt similarity index 100% rename from debian/modules/nginx-lua/t/cert/test_ecdsa.crt rename to debian/modules/http-lua/t/cert/test_ecdsa.crt diff --git a/debian/modules/nginx-lua/t/cert/test_ecdsa.key b/debian/modules/http-lua/t/cert/test_ecdsa.key similarity index 100% rename from debian/modules/nginx-lua/t/cert/test_ecdsa.key rename to debian/modules/http-lua/t/cert/test_ecdsa.key diff --git a/debian/modules/nginx-lua/t/data/fake-delayed-load-module/config b/debian/modules/http-lua/t/data/fake-delayed-load-module/config similarity index 100% rename from debian/modules/nginx-lua/t/data/fake-delayed-load-module/config rename to debian/modules/http-lua/t/data/fake-delayed-load-module/config diff --git a/debian/modules/nginx-lua/t/data/fake-delayed-load-module/ngx_http_lua_fake_delayed_load_module.c b/debian/modules/http-lua/t/data/fake-delayed-load-module/ngx_http_lua_fake_delayed_load_module.c similarity index 100% rename from debian/modules/nginx-lua/t/data/fake-delayed-load-module/ngx_http_lua_fake_delayed_load_module.c rename to debian/modules/http-lua/t/data/fake-delayed-load-module/ngx_http_lua_fake_delayed_load_module.c diff --git a/debian/modules/nginx-lua/t/data/fake-module/config b/debian/modules/http-lua/t/data/fake-module/config similarity index 100% rename from debian/modules/nginx-lua/t/data/fake-module/config rename to debian/modules/http-lua/t/data/fake-module/config diff --git a/debian/modules/nginx-lua/t/data/fake-module/ngx_http_fake_module.c b/debian/modules/http-lua/t/data/fake-module/ngx_http_fake_module.c similarity index 100% rename from debian/modules/nginx-lua/t/data/fake-module/ngx_http_fake_module.c rename to debian/modules/http-lua/t/data/fake-module/ngx_http_fake_module.c diff --git a/debian/modules/nginx-lua/t/data/fake-shm-module/config b/debian/modules/http-lua/t/data/fake-shm-module/config similarity index 100% rename from debian/modules/nginx-lua/t/data/fake-shm-module/config rename to debian/modules/http-lua/t/data/fake-shm-module/config diff --git a/debian/modules/nginx-lua/t/data/fake-shm-module/ngx_http_lua_fake_shm_module.c b/debian/modules/http-lua/t/data/fake-shm-module/ngx_http_lua_fake_shm_module.c similarity index 100% rename from debian/modules/nginx-lua/t/data/fake-shm-module/ngx_http_lua_fake_shm_module.c rename to debian/modules/http-lua/t/data/fake-shm-module/ngx_http_lua_fake_shm_module.c diff --git a/debian/modules/nginx-lua/t/lib/CRC32.lua b/debian/modules/http-lua/t/lib/CRC32.lua similarity index 100% rename from debian/modules/nginx-lua/t/lib/CRC32.lua rename to debian/modules/http-lua/t/lib/CRC32.lua diff --git a/debian/modules/nginx-lua/t/lib/Memcached.lua b/debian/modules/http-lua/t/lib/Memcached.lua similarity index 100% rename from debian/modules/nginx-lua/t/lib/Memcached.lua rename to debian/modules/http-lua/t/lib/Memcached.lua diff --git a/debian/modules/nginx-lua/t/lib/Redis.lua b/debian/modules/http-lua/t/lib/Redis.lua similarity index 100% rename from debian/modules/nginx-lua/t/lib/Redis.lua rename to debian/modules/http-lua/t/lib/Redis.lua diff --git a/debian/modules/nginx-lua/t/lib/ljson.lua b/debian/modules/http-lua/t/lib/ljson.lua similarity index 100% rename from debian/modules/nginx-lua/t/lib/ljson.lua rename to debian/modules/http-lua/t/lib/ljson.lua diff --git a/debian/modules/nginx-lua/tapset/ngx_lua.stp b/debian/modules/http-lua/tapset/ngx_lua.stp similarity index 100% rename from debian/modules/nginx-lua/tapset/ngx_lua.stp rename to debian/modules/http-lua/tapset/ngx_lua.stp diff --git a/debian/modules/nginx-lua/util/build.sh b/debian/modules/http-lua/util/build.sh similarity index 100% rename from debian/modules/nginx-lua/util/build.sh rename to debian/modules/http-lua/util/build.sh diff --git a/debian/modules/nginx-lua/util/fix-comments b/debian/modules/http-lua/util/fix-comments similarity index 100% rename from debian/modules/nginx-lua/util/fix-comments rename to debian/modules/http-lua/util/fix-comments diff --git a/debian/modules/nginx-lua/util/gen-lexer-c b/debian/modules/http-lua/util/gen-lexer-c similarity index 100% rename from debian/modules/nginx-lua/util/gen-lexer-c rename to debian/modules/http-lua/util/gen-lexer-c diff --git a/debian/modules/nginx-lua/util/ngx-links b/debian/modules/http-lua/util/ngx-links similarity index 100% rename from debian/modules/nginx-lua/util/ngx-links rename to debian/modules/http-lua/util/ngx-links diff --git a/debian/modules/nginx-lua/util/releng b/debian/modules/http-lua/util/releng similarity index 100% rename from debian/modules/nginx-lua/util/releng rename to debian/modules/http-lua/util/releng diff --git a/debian/modules/nginx-lua/util/retab b/debian/modules/http-lua/util/retab similarity index 100% rename from debian/modules/nginx-lua/util/retab rename to debian/modules/http-lua/util/retab diff --git a/debian/modules/nginx-lua/util/revim b/debian/modules/http-lua/util/revim similarity index 100% rename from debian/modules/nginx-lua/util/revim rename to debian/modules/http-lua/util/revim diff --git a/debian/modules/nginx-lua/util/run_test.sh b/debian/modules/http-lua/util/run_test.sh similarity index 100% rename from debian/modules/nginx-lua/util/run_test.sh rename to debian/modules/http-lua/util/run_test.sh diff --git a/debian/modules/nginx-lua/util/update-readme.sh b/debian/modules/http-lua/util/update-readme.sh similarity index 100% rename from debian/modules/nginx-lua/util/update-readme.sh rename to debian/modules/http-lua/util/update-readme.sh diff --git a/debian/modules/nginx-lua/valgrind.suppress b/debian/modules/http-lua/valgrind.suppress similarity index 100% rename from debian/modules/nginx-lua/valgrind.suppress rename to debian/modules/http-lua/valgrind.suppress diff --git a/debian/modules/nginx-development-kit/LICENSE b/debian/modules/http-ndk/LICENSE similarity index 100% rename from debian/modules/nginx-development-kit/LICENSE rename to debian/modules/http-ndk/LICENSE diff --git a/debian/modules/nginx-development-kit/README.md b/debian/modules/http-ndk/README.md similarity index 100% rename from debian/modules/nginx-development-kit/README.md rename to debian/modules/http-ndk/README.md diff --git a/debian/modules/nginx-development-kit/README_AUTO_LIB b/debian/modules/http-ndk/README_AUTO_LIB similarity index 100% rename from debian/modules/nginx-development-kit/README_AUTO_LIB rename to debian/modules/http-ndk/README_AUTO_LIB diff --git a/debian/modules/nginx-development-kit/TODO b/debian/modules/http-ndk/TODO similarity index 100% rename from debian/modules/nginx-development-kit/TODO rename to debian/modules/http-ndk/TODO diff --git a/debian/modules/nginx-development-kit/auto/actions/array b/debian/modules/http-ndk/auto/actions/array similarity index 100% rename from debian/modules/nginx-development-kit/auto/actions/array rename to debian/modules/http-ndk/auto/actions/array diff --git a/debian/modules/nginx-development-kit/auto/actions/palloc b/debian/modules/http-ndk/auto/actions/palloc similarity index 100% rename from debian/modules/nginx-development-kit/auto/actions/palloc rename to debian/modules/http-ndk/auto/actions/palloc diff --git a/debian/modules/nginx-development-kit/auto/build b/debian/modules/http-ndk/auto/build similarity index 100% rename from debian/modules/nginx-development-kit/auto/build rename to debian/modules/http-ndk/auto/build diff --git a/debian/modules/nginx-development-kit/auto/data/action_replacements b/debian/modules/http-ndk/auto/data/action_replacements similarity index 100% rename from debian/modules/nginx-development-kit/auto/data/action_replacements rename to debian/modules/http-ndk/auto/data/action_replacements diff --git a/debian/modules/nginx-development-kit/auto/data/action_types b/debian/modules/http-ndk/auto/data/action_types similarity index 100% rename from debian/modules/nginx-development-kit/auto/data/action_types rename to debian/modules/http-ndk/auto/data/action_types diff --git a/debian/modules/nginx-development-kit/auto/data/conf_args b/debian/modules/http-ndk/auto/data/conf_args similarity index 100% rename from debian/modules/nginx-development-kit/auto/data/conf_args rename to debian/modules/http-ndk/auto/data/conf_args diff --git a/debian/modules/nginx-development-kit/auto/data/conf_locs b/debian/modules/http-ndk/auto/data/conf_locs similarity index 100% rename from debian/modules/nginx-development-kit/auto/data/conf_locs rename to debian/modules/http-ndk/auto/data/conf_locs diff --git a/debian/modules/nginx-development-kit/auto/data/conf_macros b/debian/modules/http-ndk/auto/data/conf_macros similarity index 100% rename from debian/modules/nginx-development-kit/auto/data/conf_macros rename to debian/modules/http-ndk/auto/data/conf_macros diff --git a/debian/modules/nginx-development-kit/auto/data/contexts b/debian/modules/http-ndk/auto/data/contexts similarity index 100% rename from debian/modules/nginx-development-kit/auto/data/contexts rename to debian/modules/http-ndk/auto/data/contexts diff --git a/debian/modules/nginx-development-kit/auto/data/header_files b/debian/modules/http-ndk/auto/data/header_files similarity index 100% rename from debian/modules/nginx-development-kit/auto/data/header_files rename to debian/modules/http-ndk/auto/data/header_files diff --git a/debian/modules/nginx-development-kit/auto/data/headers b/debian/modules/http-ndk/auto/data/headers similarity index 100% rename from debian/modules/nginx-development-kit/auto/data/headers rename to debian/modules/http-ndk/auto/data/headers diff --git a/debian/modules/nginx-development-kit/auto/data/module_dependencies b/debian/modules/http-ndk/auto/data/module_dependencies similarity index 100% rename from debian/modules/nginx-development-kit/auto/data/module_dependencies rename to debian/modules/http-ndk/auto/data/module_dependencies diff --git a/debian/modules/nginx-development-kit/auto/data/modules_optional b/debian/modules/http-ndk/auto/data/modules_optional similarity index 100% rename from debian/modules/nginx-development-kit/auto/data/modules_optional rename to debian/modules/http-ndk/auto/data/modules_optional diff --git a/debian/modules/nginx-development-kit/auto/data/prefixes b/debian/modules/http-ndk/auto/data/prefixes similarity index 100% rename from debian/modules/nginx-development-kit/auto/data/prefixes rename to debian/modules/http-ndk/auto/data/prefixes diff --git a/debian/modules/nginx-development-kit/auto/src/array.h b/debian/modules/http-ndk/auto/src/array.h similarity index 100% rename from debian/modules/nginx-development-kit/auto/src/array.h rename to debian/modules/http-ndk/auto/src/array.h diff --git a/debian/modules/nginx-development-kit/auto/src/conf_cmd_basic.h b/debian/modules/http-ndk/auto/src/conf_cmd_basic.h similarity index 100% rename from debian/modules/nginx-development-kit/auto/src/conf_cmd_basic.h rename to debian/modules/http-ndk/auto/src/conf_cmd_basic.h diff --git a/debian/modules/nginx-development-kit/auto/src/conf_merge.h b/debian/modules/http-ndk/auto/src/conf_merge.h similarity index 100% rename from debian/modules/nginx-development-kit/auto/src/conf_merge.h rename to debian/modules/http-ndk/auto/src/conf_merge.h diff --git a/debian/modules/nginx-development-kit/auto/src/palloc.h b/debian/modules/http-ndk/auto/src/palloc.h similarity index 100% rename from debian/modules/nginx-development-kit/auto/src/palloc.h rename to debian/modules/http-ndk/auto/src/palloc.h diff --git a/debian/modules/nginx-development-kit/auto/text/autogen b/debian/modules/http-ndk/auto/text/autogen similarity index 100% rename from debian/modules/nginx-development-kit/auto/text/autogen rename to debian/modules/http-ndk/auto/text/autogen diff --git a/debian/modules/nginx-development-kit/config b/debian/modules/http-ndk/config similarity index 100% rename from debian/modules/nginx-development-kit/config rename to debian/modules/http-ndk/config diff --git a/debian/modules/nginx-development-kit/docs/core/action_macros b/debian/modules/http-ndk/docs/core/action_macros similarity index 100% rename from debian/modules/nginx-development-kit/docs/core/action_macros rename to debian/modules/http-ndk/docs/core/action_macros diff --git a/debian/modules/nginx-development-kit/docs/core/conf_cmds b/debian/modules/http-ndk/docs/core/conf_cmds similarity index 100% rename from debian/modules/nginx-development-kit/docs/core/conf_cmds rename to debian/modules/http-ndk/docs/core/conf_cmds diff --git a/debian/modules/nginx-development-kit/docs/modules/set_var b/debian/modules/http-ndk/docs/modules/set_var similarity index 100% rename from debian/modules/nginx-development-kit/docs/modules/set_var rename to debian/modules/http-ndk/docs/modules/set_var diff --git a/debian/modules/nginx-development-kit/docs/patches/more_logging_info b/debian/modules/http-ndk/docs/patches/more_logging_info similarity index 100% rename from debian/modules/nginx-development-kit/docs/patches/more_logging_info rename to debian/modules/http-ndk/docs/patches/more_logging_info diff --git a/debian/modules/nginx-development-kit/docs/upstream/list b/debian/modules/http-ndk/docs/upstream/list similarity index 100% rename from debian/modules/nginx-development-kit/docs/upstream/list rename to debian/modules/http-ndk/docs/upstream/list diff --git a/debian/modules/nginx-development-kit/examples/README b/debian/modules/http-ndk/examples/README similarity index 100% rename from debian/modules/nginx-development-kit/examples/README rename to debian/modules/http-ndk/examples/README diff --git a/debian/modules/nginx-development-kit/examples/http/set_var/config b/debian/modules/http-ndk/examples/http/set_var/config similarity index 100% rename from debian/modules/nginx-development-kit/examples/http/set_var/config rename to debian/modules/http-ndk/examples/http/set_var/config diff --git a/debian/modules/nginx-development-kit/examples/http/set_var/ngx_http_set_var_examples_module.c b/debian/modules/http-ndk/examples/http/set_var/ngx_http_set_var_examples_module.c similarity index 100% rename from debian/modules/nginx-development-kit/examples/http/set_var/ngx_http_set_var_examples_module.c rename to debian/modules/http-ndk/examples/http/set_var/ngx_http_set_var_examples_module.c diff --git a/debian/modules/nginx-development-kit/ngx_auto_lib_core b/debian/modules/http-ndk/ngx_auto_lib_core similarity index 100% rename from debian/modules/nginx-development-kit/ngx_auto_lib_core rename to debian/modules/http-ndk/ngx_auto_lib_core diff --git a/debian/modules/nginx-development-kit/notes/CHANGES b/debian/modules/http-ndk/notes/CHANGES similarity index 100% rename from debian/modules/nginx-development-kit/notes/CHANGES rename to debian/modules/http-ndk/notes/CHANGES diff --git a/debian/modules/nginx-development-kit/notes/LICENSE b/debian/modules/http-ndk/notes/LICENSE similarity index 100% rename from debian/modules/nginx-development-kit/notes/LICENSE rename to debian/modules/http-ndk/notes/LICENSE diff --git a/debian/modules/nginx-development-kit/objs/ndk_array.h b/debian/modules/http-ndk/objs/ndk_array.h similarity index 100% rename from debian/modules/nginx-development-kit/objs/ndk_array.h rename to debian/modules/http-ndk/objs/ndk_array.h diff --git a/debian/modules/nginx-development-kit/objs/ndk_conf_cmd_basic.h b/debian/modules/http-ndk/objs/ndk_conf_cmd_basic.h similarity index 100% rename from debian/modules/nginx-development-kit/objs/ndk_conf_cmd_basic.h rename to debian/modules/http-ndk/objs/ndk_conf_cmd_basic.h diff --git a/debian/modules/nginx-development-kit/objs/ndk_conf_cmd_extra.h b/debian/modules/http-ndk/objs/ndk_conf_cmd_extra.h similarity index 100% rename from debian/modules/nginx-development-kit/objs/ndk_conf_cmd_extra.h rename to debian/modules/http-ndk/objs/ndk_conf_cmd_extra.h diff --git a/debian/modules/nginx-development-kit/objs/ndk_conf_merge.h b/debian/modules/http-ndk/objs/ndk_conf_merge.h similarity index 100% rename from debian/modules/nginx-development-kit/objs/ndk_conf_merge.h rename to debian/modules/http-ndk/objs/ndk_conf_merge.h diff --git a/debian/modules/nginx-development-kit/objs/ndk_config.c b/debian/modules/http-ndk/objs/ndk_config.c similarity index 100% rename from debian/modules/nginx-development-kit/objs/ndk_config.c rename to debian/modules/http-ndk/objs/ndk_config.c diff --git a/debian/modules/nginx-development-kit/objs/ndk_config.h b/debian/modules/http-ndk/objs/ndk_config.h similarity index 100% rename from debian/modules/nginx-development-kit/objs/ndk_config.h rename to debian/modules/http-ndk/objs/ndk_config.h diff --git a/debian/modules/nginx-development-kit/objs/ndk_includes.h b/debian/modules/http-ndk/objs/ndk_includes.h similarity index 100% rename from debian/modules/nginx-development-kit/objs/ndk_includes.h rename to debian/modules/http-ndk/objs/ndk_includes.h diff --git a/debian/modules/nginx-development-kit/objs/ndk_palloc.h b/debian/modules/http-ndk/objs/ndk_palloc.h similarity index 100% rename from debian/modules/nginx-development-kit/objs/ndk_palloc.h rename to debian/modules/http-ndk/objs/ndk_palloc.h diff --git a/debian/modules/nginx-development-kit/patches/auto_config b/debian/modules/http-ndk/patches/auto_config similarity index 100% rename from debian/modules/nginx-development-kit/patches/auto_config rename to debian/modules/http-ndk/patches/auto_config diff --git a/debian/modules/nginx-development-kit/patches/expose_rewrite_functions b/debian/modules/http-ndk/patches/expose_rewrite_functions similarity index 100% rename from debian/modules/nginx-development-kit/patches/expose_rewrite_functions rename to debian/modules/http-ndk/patches/expose_rewrite_functions diff --git a/debian/modules/nginx-development-kit/patches/rewrite_phase_handler b/debian/modules/http-ndk/patches/rewrite_phase_handler similarity index 100% rename from debian/modules/nginx-development-kit/patches/rewrite_phase_handler rename to debian/modules/http-ndk/patches/rewrite_phase_handler diff --git a/debian/modules/nginx-development-kit/src/hash/md5.h b/debian/modules/http-ndk/src/hash/md5.h similarity index 100% rename from debian/modules/nginx-development-kit/src/hash/md5.h rename to debian/modules/http-ndk/src/hash/md5.h diff --git a/debian/modules/nginx-development-kit/src/hash/murmurhash2.c b/debian/modules/http-ndk/src/hash/murmurhash2.c similarity index 100% rename from debian/modules/nginx-development-kit/src/hash/murmurhash2.c rename to debian/modules/http-ndk/src/hash/murmurhash2.c diff --git a/debian/modules/nginx-development-kit/src/hash/sha.h b/debian/modules/http-ndk/src/hash/sha.h similarity index 100% rename from debian/modules/nginx-development-kit/src/hash/sha.h rename to debian/modules/http-ndk/src/hash/sha.h diff --git a/debian/modules/nginx-development-kit/src/ndk.c b/debian/modules/http-ndk/src/ndk.c similarity index 100% rename from debian/modules/nginx-development-kit/src/ndk.c rename to debian/modules/http-ndk/src/ndk.c diff --git a/debian/modules/nginx-development-kit/src/ndk.h b/debian/modules/http-ndk/src/ndk.h similarity index 100% rename from debian/modules/nginx-development-kit/src/ndk.h rename to debian/modules/http-ndk/src/ndk.h diff --git a/debian/modules/nginx-development-kit/src/ndk_buf.c b/debian/modules/http-ndk/src/ndk_buf.c similarity index 100% rename from debian/modules/nginx-development-kit/src/ndk_buf.c rename to debian/modules/http-ndk/src/ndk_buf.c diff --git a/debian/modules/nginx-development-kit/src/ndk_buf.h b/debian/modules/http-ndk/src/ndk_buf.h similarity index 100% rename from debian/modules/nginx-development-kit/src/ndk_buf.h rename to debian/modules/http-ndk/src/ndk_buf.h diff --git a/debian/modules/nginx-development-kit/src/ndk_complex_path.c b/debian/modules/http-ndk/src/ndk_complex_path.c similarity index 100% rename from debian/modules/nginx-development-kit/src/ndk_complex_path.c rename to debian/modules/http-ndk/src/ndk_complex_path.c diff --git a/debian/modules/nginx-development-kit/src/ndk_complex_path.h b/debian/modules/http-ndk/src/ndk_complex_path.h similarity index 100% rename from debian/modules/nginx-development-kit/src/ndk_complex_path.h rename to debian/modules/http-ndk/src/ndk_complex_path.h diff --git a/debian/modules/nginx-development-kit/src/ndk_complex_value.c b/debian/modules/http-ndk/src/ndk_complex_value.c similarity index 100% rename from debian/modules/nginx-development-kit/src/ndk_complex_value.c rename to debian/modules/http-ndk/src/ndk_complex_value.c diff --git a/debian/modules/nginx-development-kit/src/ndk_complex_value.h b/debian/modules/http-ndk/src/ndk_complex_value.h similarity index 100% rename from debian/modules/nginx-development-kit/src/ndk_complex_value.h rename to debian/modules/http-ndk/src/ndk_complex_value.h diff --git a/debian/modules/nginx-development-kit/src/ndk_conf_file.c b/debian/modules/http-ndk/src/ndk_conf_file.c similarity index 100% rename from debian/modules/nginx-development-kit/src/ndk_conf_file.c rename to debian/modules/http-ndk/src/ndk_conf_file.c diff --git a/debian/modules/nginx-development-kit/src/ndk_conf_file.h b/debian/modules/http-ndk/src/ndk_conf_file.h similarity index 100% rename from debian/modules/nginx-development-kit/src/ndk_conf_file.h rename to debian/modules/http-ndk/src/ndk_conf_file.h diff --git a/debian/modules/nginx-development-kit/src/ndk_debug.c b/debian/modules/http-ndk/src/ndk_debug.c similarity index 100% rename from debian/modules/nginx-development-kit/src/ndk_debug.c rename to debian/modules/http-ndk/src/ndk_debug.c diff --git a/debian/modules/nginx-development-kit/src/ndk_debug.h b/debian/modules/http-ndk/src/ndk_debug.h similarity index 100% rename from debian/modules/nginx-development-kit/src/ndk_debug.h rename to debian/modules/http-ndk/src/ndk_debug.h diff --git a/debian/modules/nginx-development-kit/src/ndk_encoding.c b/debian/modules/http-ndk/src/ndk_encoding.c similarity index 100% rename from debian/modules/nginx-development-kit/src/ndk_encoding.c rename to debian/modules/http-ndk/src/ndk_encoding.c diff --git a/debian/modules/nginx-development-kit/src/ndk_encoding.h b/debian/modules/http-ndk/src/ndk_encoding.h similarity index 100% rename from debian/modules/nginx-development-kit/src/ndk_encoding.h rename to debian/modules/http-ndk/src/ndk_encoding.h diff --git a/debian/modules/nginx-development-kit/src/ndk_hash.c b/debian/modules/http-ndk/src/ndk_hash.c similarity index 100% rename from debian/modules/nginx-development-kit/src/ndk_hash.c rename to debian/modules/http-ndk/src/ndk_hash.c diff --git a/debian/modules/nginx-development-kit/src/ndk_hash.h b/debian/modules/http-ndk/src/ndk_hash.h similarity index 100% rename from debian/modules/nginx-development-kit/src/ndk_hash.h rename to debian/modules/http-ndk/src/ndk_hash.h diff --git a/debian/modules/nginx-development-kit/src/ndk_http.c b/debian/modules/http-ndk/src/ndk_http.c similarity index 100% rename from debian/modules/nginx-development-kit/src/ndk_http.c rename to debian/modules/http-ndk/src/ndk_http.c diff --git a/debian/modules/nginx-development-kit/src/ndk_http.h b/debian/modules/http-ndk/src/ndk_http.h similarity index 100% rename from debian/modules/nginx-development-kit/src/ndk_http.h rename to debian/modules/http-ndk/src/ndk_http.h diff --git a/debian/modules/nginx-development-kit/src/ndk_http_headers.h b/debian/modules/http-ndk/src/ndk_http_headers.h similarity index 100% rename from debian/modules/nginx-development-kit/src/ndk_http_headers.h rename to debian/modules/http-ndk/src/ndk_http_headers.h diff --git a/debian/modules/nginx-development-kit/src/ndk_log.c b/debian/modules/http-ndk/src/ndk_log.c similarity index 100% rename from debian/modules/nginx-development-kit/src/ndk_log.c rename to debian/modules/http-ndk/src/ndk_log.c diff --git a/debian/modules/nginx-development-kit/src/ndk_log.h b/debian/modules/http-ndk/src/ndk_log.h similarity index 100% rename from debian/modules/nginx-development-kit/src/ndk_log.h rename to debian/modules/http-ndk/src/ndk_log.h diff --git a/debian/modules/nginx-development-kit/src/ndk_parse.h b/debian/modules/http-ndk/src/ndk_parse.h similarity index 100% rename from debian/modules/nginx-development-kit/src/ndk_parse.h rename to debian/modules/http-ndk/src/ndk_parse.h diff --git a/debian/modules/nginx-development-kit/src/ndk_path.c b/debian/modules/http-ndk/src/ndk_path.c similarity index 100% rename from debian/modules/nginx-development-kit/src/ndk_path.c rename to debian/modules/http-ndk/src/ndk_path.c diff --git a/debian/modules/nginx-development-kit/src/ndk_path.h b/debian/modules/http-ndk/src/ndk_path.h similarity index 100% rename from debian/modules/nginx-development-kit/src/ndk_path.h rename to debian/modules/http-ndk/src/ndk_path.h diff --git a/debian/modules/nginx-development-kit/src/ndk_process.c b/debian/modules/http-ndk/src/ndk_process.c similarity index 100% rename from debian/modules/nginx-development-kit/src/ndk_process.c rename to debian/modules/http-ndk/src/ndk_process.c diff --git a/debian/modules/nginx-development-kit/src/ndk_process.h b/debian/modules/http-ndk/src/ndk_process.h similarity index 100% rename from debian/modules/nginx-development-kit/src/ndk_process.h rename to debian/modules/http-ndk/src/ndk_process.h diff --git a/debian/modules/nginx-development-kit/src/ndk_regex.c b/debian/modules/http-ndk/src/ndk_regex.c similarity index 100% rename from debian/modules/nginx-development-kit/src/ndk_regex.c rename to debian/modules/http-ndk/src/ndk_regex.c diff --git a/debian/modules/nginx-development-kit/src/ndk_regex.h b/debian/modules/http-ndk/src/ndk_regex.h similarity index 100% rename from debian/modules/nginx-development-kit/src/ndk_regex.h rename to debian/modules/http-ndk/src/ndk_regex.h diff --git a/debian/modules/nginx-development-kit/src/ndk_rewrite.c b/debian/modules/http-ndk/src/ndk_rewrite.c similarity index 100% rename from debian/modules/nginx-development-kit/src/ndk_rewrite.c rename to debian/modules/http-ndk/src/ndk_rewrite.c diff --git a/debian/modules/nginx-development-kit/src/ndk_rewrite.h b/debian/modules/http-ndk/src/ndk_rewrite.h similarity index 100% rename from debian/modules/nginx-development-kit/src/ndk_rewrite.h rename to debian/modules/http-ndk/src/ndk_rewrite.h diff --git a/debian/modules/nginx-development-kit/src/ndk_set_var.c b/debian/modules/http-ndk/src/ndk_set_var.c similarity index 100% rename from debian/modules/nginx-development-kit/src/ndk_set_var.c rename to debian/modules/http-ndk/src/ndk_set_var.c diff --git a/debian/modules/nginx-development-kit/src/ndk_set_var.h b/debian/modules/http-ndk/src/ndk_set_var.h similarity index 100% rename from debian/modules/nginx-development-kit/src/ndk_set_var.h rename to debian/modules/http-ndk/src/ndk_set_var.h diff --git a/debian/modules/nginx-development-kit/src/ndk_string.c b/debian/modules/http-ndk/src/ndk_string.c similarity index 100% rename from debian/modules/nginx-development-kit/src/ndk_string.c rename to debian/modules/http-ndk/src/ndk_string.c diff --git a/debian/modules/nginx-development-kit/src/ndk_string.h b/debian/modules/http-ndk/src/ndk_string.h similarity index 100% rename from debian/modules/nginx-development-kit/src/ndk_string.h rename to debian/modules/http-ndk/src/ndk_string.h diff --git a/debian/modules/nginx-development-kit/src/ndk_string_util.h b/debian/modules/http-ndk/src/ndk_string_util.h similarity index 100% rename from debian/modules/nginx-development-kit/src/ndk_string_util.h rename to debian/modules/http-ndk/src/ndk_string_util.h diff --git a/debian/modules/nginx-development-kit/src/ndk_upstream_list.c b/debian/modules/http-ndk/src/ndk_upstream_list.c similarity index 100% rename from debian/modules/nginx-development-kit/src/ndk_upstream_list.c rename to debian/modules/http-ndk/src/ndk_upstream_list.c diff --git a/debian/modules/nginx-development-kit/src/ndk_upstream_list.h b/debian/modules/http-ndk/src/ndk_upstream_list.h similarity index 100% rename from debian/modules/nginx-development-kit/src/ndk_upstream_list.h rename to debian/modules/http-ndk/src/ndk_upstream_list.h diff --git a/debian/modules/nginx-development-kit/src/ndk_uri.c b/debian/modules/http-ndk/src/ndk_uri.c similarity index 100% rename from debian/modules/nginx-development-kit/src/ndk_uri.c rename to debian/modules/http-ndk/src/ndk_uri.c diff --git a/debian/modules/nginx-development-kit/src/ndk_uri.h b/debian/modules/http-ndk/src/ndk_uri.h similarity index 100% rename from debian/modules/nginx-development-kit/src/ndk_uri.h rename to debian/modules/http-ndk/src/ndk_uri.h diff --git a/debian/modules/ngx_http_substitutions_filter_module/CHANGES b/debian/modules/http-subs-filter/CHANGES similarity index 100% rename from debian/modules/ngx_http_substitutions_filter_module/CHANGES rename to debian/modules/http-subs-filter/CHANGES diff --git a/debian/modules/ngx_http_substitutions_filter_module/README b/debian/modules/http-subs-filter/README similarity index 100% rename from debian/modules/ngx_http_substitutions_filter_module/README rename to debian/modules/http-subs-filter/README diff --git a/debian/modules/ngx_http_substitutions_filter_module/config b/debian/modules/http-subs-filter/config similarity index 100% rename from debian/modules/ngx_http_substitutions_filter_module/config rename to debian/modules/http-subs-filter/config diff --git a/debian/modules/ngx_http_substitutions_filter_module/doc/README.google_code_home_page.wiki b/debian/modules/http-subs-filter/doc/README.google_code_home_page.wiki similarity index 100% rename from debian/modules/ngx_http_substitutions_filter_module/doc/README.google_code_home_page.wiki rename to debian/modules/http-subs-filter/doc/README.google_code_home_page.wiki diff --git a/debian/modules/ngx_http_substitutions_filter_module/doc/README.html b/debian/modules/http-subs-filter/doc/README.html similarity index 100% rename from debian/modules/ngx_http_substitutions_filter_module/doc/README.html rename to debian/modules/http-subs-filter/doc/README.html diff --git a/debian/modules/ngx_http_substitutions_filter_module/doc/README.wiki b/debian/modules/http-subs-filter/doc/README.wiki similarity index 100% rename from debian/modules/ngx_http_substitutions_filter_module/doc/README.wiki rename to debian/modules/http-subs-filter/doc/README.wiki diff --git a/debian/modules/ngx_http_substitutions_filter_module/ngx_http_subs_filter_module.c b/debian/modules/http-subs-filter/ngx_http_subs_filter_module.c similarity index 100% rename from debian/modules/ngx_http_substitutions_filter_module/ngx_http_subs_filter_module.c rename to debian/modules/http-subs-filter/ngx_http_subs_filter_module.c diff --git a/debian/modules/ngx_http_substitutions_filter_module/test/README b/debian/modules/http-subs-filter/test/README similarity index 100% rename from debian/modules/ngx_http_substitutions_filter_module/test/README rename to debian/modules/http-subs-filter/test/README diff --git a/debian/modules/ngx_http_substitutions_filter_module/test/inc/Module/AutoInstall.pm b/debian/modules/http-subs-filter/test/inc/Module/AutoInstall.pm similarity index 100% rename from debian/modules/ngx_http_substitutions_filter_module/test/inc/Module/AutoInstall.pm rename to debian/modules/http-subs-filter/test/inc/Module/AutoInstall.pm diff --git a/debian/modules/ngx_http_substitutions_filter_module/test/inc/Module/Install.pm b/debian/modules/http-subs-filter/test/inc/Module/Install.pm similarity index 100% rename from debian/modules/ngx_http_substitutions_filter_module/test/inc/Module/Install.pm rename to debian/modules/http-subs-filter/test/inc/Module/Install.pm diff --git a/debian/modules/ngx_http_substitutions_filter_module/test/inc/Module/Install/AutoInstall.pm b/debian/modules/http-subs-filter/test/inc/Module/Install/AutoInstall.pm similarity index 100% rename from debian/modules/ngx_http_substitutions_filter_module/test/inc/Module/Install/AutoInstall.pm rename to debian/modules/http-subs-filter/test/inc/Module/Install/AutoInstall.pm diff --git a/debian/modules/ngx_http_substitutions_filter_module/test/inc/Module/Install/Base.pm b/debian/modules/http-subs-filter/test/inc/Module/Install/Base.pm similarity index 100% rename from debian/modules/ngx_http_substitutions_filter_module/test/inc/Module/Install/Base.pm rename to debian/modules/http-subs-filter/test/inc/Module/Install/Base.pm diff --git a/debian/modules/ngx_http_substitutions_filter_module/test/inc/Module/Install/Can.pm b/debian/modules/http-subs-filter/test/inc/Module/Install/Can.pm similarity index 100% rename from debian/modules/ngx_http_substitutions_filter_module/test/inc/Module/Install/Can.pm rename to debian/modules/http-subs-filter/test/inc/Module/Install/Can.pm diff --git a/debian/modules/ngx_http_substitutions_filter_module/test/inc/Module/Install/Fetch.pm b/debian/modules/http-subs-filter/test/inc/Module/Install/Fetch.pm similarity index 100% rename from debian/modules/ngx_http_substitutions_filter_module/test/inc/Module/Install/Fetch.pm rename to debian/modules/http-subs-filter/test/inc/Module/Install/Fetch.pm diff --git a/debian/modules/ngx_http_substitutions_filter_module/test/inc/Module/Install/Include.pm b/debian/modules/http-subs-filter/test/inc/Module/Install/Include.pm similarity index 100% rename from debian/modules/ngx_http_substitutions_filter_module/test/inc/Module/Install/Include.pm rename to debian/modules/http-subs-filter/test/inc/Module/Install/Include.pm diff --git a/debian/modules/ngx_http_substitutions_filter_module/test/inc/Module/Install/Makefile.pm b/debian/modules/http-subs-filter/test/inc/Module/Install/Makefile.pm similarity index 100% rename from debian/modules/ngx_http_substitutions_filter_module/test/inc/Module/Install/Makefile.pm rename to debian/modules/http-subs-filter/test/inc/Module/Install/Makefile.pm diff --git a/debian/modules/ngx_http_substitutions_filter_module/test/inc/Module/Install/Metadata.pm b/debian/modules/http-subs-filter/test/inc/Module/Install/Metadata.pm similarity index 100% rename from debian/modules/ngx_http_substitutions_filter_module/test/inc/Module/Install/Metadata.pm rename to debian/modules/http-subs-filter/test/inc/Module/Install/Metadata.pm diff --git a/debian/modules/ngx_http_substitutions_filter_module/test/inc/Module/Install/TestBase.pm b/debian/modules/http-subs-filter/test/inc/Module/Install/TestBase.pm similarity index 100% rename from debian/modules/ngx_http_substitutions_filter_module/test/inc/Module/Install/TestBase.pm rename to debian/modules/http-subs-filter/test/inc/Module/Install/TestBase.pm diff --git a/debian/modules/ngx_http_substitutions_filter_module/test/inc/Module/Install/Win32.pm b/debian/modules/http-subs-filter/test/inc/Module/Install/Win32.pm similarity index 100% rename from debian/modules/ngx_http_substitutions_filter_module/test/inc/Module/Install/Win32.pm rename to debian/modules/http-subs-filter/test/inc/Module/Install/Win32.pm diff --git a/debian/modules/ngx_http_substitutions_filter_module/test/inc/Module/Install/WriteAll.pm b/debian/modules/http-subs-filter/test/inc/Module/Install/WriteAll.pm similarity index 100% rename from debian/modules/ngx_http_substitutions_filter_module/test/inc/Module/Install/WriteAll.pm rename to debian/modules/http-subs-filter/test/inc/Module/Install/WriteAll.pm diff --git a/debian/modules/ngx_http_substitutions_filter_module/test/inc/Spiffy.pm b/debian/modules/http-subs-filter/test/inc/Spiffy.pm similarity index 100% rename from debian/modules/ngx_http_substitutions_filter_module/test/inc/Spiffy.pm rename to debian/modules/http-subs-filter/test/inc/Spiffy.pm diff --git a/debian/modules/ngx_http_substitutions_filter_module/test/inc/Test/Base.pm b/debian/modules/http-subs-filter/test/inc/Test/Base.pm similarity index 100% rename from debian/modules/ngx_http_substitutions_filter_module/test/inc/Test/Base.pm rename to debian/modules/http-subs-filter/test/inc/Test/Base.pm diff --git a/debian/modules/ngx_http_substitutions_filter_module/test/inc/Test/Base/Filter.pm b/debian/modules/http-subs-filter/test/inc/Test/Base/Filter.pm similarity index 100% rename from debian/modules/ngx_http_substitutions_filter_module/test/inc/Test/Base/Filter.pm rename to debian/modules/http-subs-filter/test/inc/Test/Base/Filter.pm diff --git a/debian/modules/ngx_http_substitutions_filter_module/test/inc/Test/Builder.pm b/debian/modules/http-subs-filter/test/inc/Test/Builder.pm similarity index 100% rename from debian/modules/ngx_http_substitutions_filter_module/test/inc/Test/Builder.pm rename to debian/modules/http-subs-filter/test/inc/Test/Builder.pm diff --git a/debian/modules/ngx_http_substitutions_filter_module/test/inc/Test/Builder/Module.pm b/debian/modules/http-subs-filter/test/inc/Test/Builder/Module.pm similarity index 100% rename from debian/modules/ngx_http_substitutions_filter_module/test/inc/Test/Builder/Module.pm rename to debian/modules/http-subs-filter/test/inc/Test/Builder/Module.pm diff --git a/debian/modules/ngx_http_substitutions_filter_module/test/inc/Test/More.pm b/debian/modules/http-subs-filter/test/inc/Test/More.pm similarity index 100% rename from debian/modules/ngx_http_substitutions_filter_module/test/inc/Test/More.pm rename to debian/modules/http-subs-filter/test/inc/Test/More.pm diff --git a/debian/modules/ngx_http_substitutions_filter_module/test/lib/Test/Nginx.pm b/debian/modules/http-subs-filter/test/lib/Test/Nginx.pm similarity index 100% rename from debian/modules/ngx_http_substitutions_filter_module/test/lib/Test/Nginx.pm rename to debian/modules/http-subs-filter/test/lib/Test/Nginx.pm diff --git a/debian/modules/ngx_http_substitutions_filter_module/test/lib/Test/Nginx/LWP.pm b/debian/modules/http-subs-filter/test/lib/Test/Nginx/LWP.pm similarity index 100% rename from debian/modules/ngx_http_substitutions_filter_module/test/lib/Test/Nginx/LWP.pm rename to debian/modules/http-subs-filter/test/lib/Test/Nginx/LWP.pm diff --git a/debian/modules/ngx_http_substitutions_filter_module/test/lib/Test/Nginx/Socket.pm b/debian/modules/http-subs-filter/test/lib/Test/Nginx/Socket.pm similarity index 100% rename from debian/modules/ngx_http_substitutions_filter_module/test/lib/Test/Nginx/Socket.pm rename to debian/modules/http-subs-filter/test/lib/Test/Nginx/Socket.pm diff --git a/debian/modules/ngx_http_substitutions_filter_module/test/lib/Test/Nginx/Util.pm b/debian/modules/http-subs-filter/test/lib/Test/Nginx/Util.pm similarity index 100% rename from debian/modules/ngx_http_substitutions_filter_module/test/lib/Test/Nginx/Util.pm rename to debian/modules/http-subs-filter/test/lib/Test/Nginx/Util.pm diff --git a/debian/modules/ngx_http_substitutions_filter_module/test/t/subs.t b/debian/modules/http-subs-filter/test/t/subs.t similarity index 100% rename from debian/modules/ngx_http_substitutions_filter_module/test/t/subs.t rename to debian/modules/http-subs-filter/test/t/subs.t diff --git a/debian/modules/ngx_http_substitutions_filter_module/test/t/subs_capture.t b/debian/modules/http-subs-filter/test/t/subs_capture.t similarity index 100% rename from debian/modules/ngx_http_substitutions_filter_module/test/t/subs_capture.t rename to debian/modules/http-subs-filter/test/t/subs_capture.t diff --git a/debian/modules/ngx_http_substitutions_filter_module/test/t/subs_fix_string.t b/debian/modules/http-subs-filter/test/t/subs_fix_string.t similarity index 100% rename from debian/modules/ngx_http_substitutions_filter_module/test/t/subs_fix_string.t rename to debian/modules/http-subs-filter/test/t/subs_fix_string.t diff --git a/debian/modules/ngx_http_substitutions_filter_module/test/t/subs_regex.t b/debian/modules/http-subs-filter/test/t/subs_regex.t similarity index 100% rename from debian/modules/ngx_http_substitutions_filter_module/test/t/subs_regex.t rename to debian/modules/http-subs-filter/test/t/subs_regex.t diff --git a/debian/modules/ngx_http_substitutions_filter_module/test/t/subs_types.t b/debian/modules/http-subs-filter/test/t/subs_types.t similarity index 100% rename from debian/modules/ngx_http_substitutions_filter_module/test/t/subs_types.t rename to debian/modules/http-subs-filter/test/t/subs_types.t diff --git a/debian/modules/ngx_http_substitutions_filter_module/test/test.sh b/debian/modules/http-subs-filter/test/test.sh similarity index 100% rename from debian/modules/ngx_http_substitutions_filter_module/test/test.sh rename to debian/modules/http-subs-filter/test/test.sh diff --git a/debian/modules/ngx_http_substitutions_filter_module/util/update-readme.sh b/debian/modules/http-subs-filter/util/update-readme.sh similarity index 100% rename from debian/modules/ngx_http_substitutions_filter_module/util/update-readme.sh rename to debian/modules/http-subs-filter/util/update-readme.sh diff --git a/debian/modules/ngx_http_substitutions_filter_module/util/wiki2google_code_homepage.pl b/debian/modules/http-subs-filter/util/wiki2google_code_homepage.pl similarity index 100% rename from debian/modules/ngx_http_substitutions_filter_module/util/wiki2google_code_homepage.pl rename to debian/modules/http-subs-filter/util/wiki2google_code_homepage.pl diff --git a/debian/modules/ngx_http_substitutions_filter_module/util/wiki2pod.pl b/debian/modules/http-subs-filter/util/wiki2pod.pl similarity index 100% rename from debian/modules/ngx_http_substitutions_filter_module/util/wiki2pod.pl rename to debian/modules/http-subs-filter/util/wiki2pod.pl diff --git a/debian/modules/nginx-upload-progress/CHANGES b/debian/modules/http-uploadprogress/CHANGES similarity index 100% rename from debian/modules/nginx-upload-progress/CHANGES rename to debian/modules/http-uploadprogress/CHANGES diff --git a/debian/modules/nginx-upload-progress/LICENSE b/debian/modules/http-uploadprogress/LICENSE similarity index 100% rename from debian/modules/nginx-upload-progress/LICENSE rename to debian/modules/http-uploadprogress/LICENSE diff --git a/debian/modules/nginx-upload-progress/Makefile b/debian/modules/http-uploadprogress/Makefile similarity index 100% rename from debian/modules/nginx-upload-progress/Makefile rename to debian/modules/http-uploadprogress/Makefile diff --git a/debian/modules/nginx-upload-progress/README b/debian/modules/http-uploadprogress/README similarity index 100% rename from debian/modules/nginx-upload-progress/README rename to debian/modules/http-uploadprogress/README diff --git a/debian/modules/nginx-upload-progress/config b/debian/modules/http-uploadprogress/config similarity index 100% rename from debian/modules/nginx-upload-progress/config rename to debian/modules/http-uploadprogress/config diff --git a/debian/modules/nginx-upload-progress/ngx_http_uploadprogress_module.c b/debian/modules/http-uploadprogress/ngx_http_uploadprogress_module.c similarity index 100% rename from debian/modules/nginx-upload-progress/ngx_http_uploadprogress_module.c rename to debian/modules/http-uploadprogress/ngx_http_uploadprogress_module.c diff --git a/debian/modules/nginx-upload-progress/test/client.sh b/debian/modules/http-uploadprogress/test/client.sh similarity index 100% rename from debian/modules/nginx-upload-progress/test/client.sh rename to debian/modules/http-uploadprogress/test/client.sh diff --git a/debian/modules/nginx-upload-progress/test/stress.sh b/debian/modules/http-uploadprogress/test/stress.sh similarity index 100% rename from debian/modules/nginx-upload-progress/test/stress.sh rename to debian/modules/http-uploadprogress/test/stress.sh diff --git a/debian/modules/nginx-upstream-fair/.gdbinit b/debian/modules/http-upstream-fair/.gdbinit similarity index 100% rename from debian/modules/nginx-upstream-fair/.gdbinit rename to debian/modules/http-upstream-fair/.gdbinit diff --git a/debian/modules/nginx-upstream-fair/README b/debian/modules/http-upstream-fair/README similarity index 100% rename from debian/modules/nginx-upstream-fair/README rename to debian/modules/http-upstream-fair/README diff --git a/debian/modules/nginx-upstream-fair/config b/debian/modules/http-upstream-fair/config similarity index 100% rename from debian/modules/nginx-upstream-fair/config rename to debian/modules/http-upstream-fair/config diff --git a/debian/modules/nginx-upstream-fair/ngx_http_upstream_fair_module.c b/debian/modules/http-upstream-fair/ngx_http_upstream_fair_module.c similarity index 100% rename from debian/modules/nginx-upstream-fair/ngx_http_upstream_fair_module.c rename to debian/modules/http-upstream-fair/ngx_http_upstream_fair_module.c diff --git a/debian/modules/patches/nginx-cache-purge/dynamic-module.patch b/debian/modules/patches/http-cache-purge/dynamic-module.patch similarity index 100% rename from debian/modules/patches/nginx-cache-purge/dynamic-module.patch rename to debian/modules/patches/http-cache-purge/dynamic-module.patch diff --git a/debian/modules/patches/nginx-cache-purge/segfault-1.11.6.patch b/debian/modules/patches/http-cache-purge/segfault-1.11.6.patch similarity index 100% rename from debian/modules/patches/nginx-cache-purge/segfault-1.11.6.patch rename to debian/modules/patches/http-cache-purge/segfault-1.11.6.patch diff --git a/debian/modules/patches/nginx-cache-purge/series b/debian/modules/patches/http-cache-purge/series similarity index 100% rename from debian/modules/patches/nginx-cache-purge/series rename to debian/modules/patches/http-cache-purge/series diff --git a/debian/modules/patches/nginx-dav-ext-module/dynamic-module.patch b/debian/modules/patches/http-dav-ext/dynamic-module.patch similarity index 100% rename from debian/modules/patches/nginx-dav-ext-module/dynamic-module.patch rename to debian/modules/patches/http-dav-ext/dynamic-module.patch diff --git a/debian/modules/patches/nginx-dav-ext-module/series b/debian/modules/patches/http-dav-ext/series similarity index 100% rename from debian/modules/patches/nginx-dav-ext-module/series rename to debian/modules/patches/http-dav-ext/series diff --git a/debian/modules/patches/nginx-echo/build-nginx-1.11.11.patch b/debian/modules/patches/http-echo/build-nginx-1.11.11.patch similarity index 100% rename from debian/modules/patches/nginx-echo/build-nginx-1.11.11.patch rename to debian/modules/patches/http-echo/build-nginx-1.11.11.patch diff --git a/debian/modules/patches/nginx-echo/series b/debian/modules/patches/http-echo/series similarity index 100% rename from debian/modules/patches/nginx-echo/series rename to debian/modules/patches/http-echo/series diff --git a/debian/modules/patches/nginx-lua/discover-luajit-2.1.patch b/debian/modules/patches/http-lua/discover-luajit-2.1.patch similarity index 100% rename from debian/modules/patches/nginx-lua/discover-luajit-2.1.patch rename to debian/modules/patches/http-lua/discover-luajit-2.1.patch diff --git a/debian/modules/patches/nginx-lua/openssl-1.1.0.patch b/debian/modules/patches/http-lua/openssl-1.1.0.patch similarity index 100% rename from debian/modules/patches/nginx-lua/openssl-1.1.0.patch rename to debian/modules/patches/http-lua/openssl-1.1.0.patch diff --git a/debian/modules/patches/nginx-lua/series b/debian/modules/patches/http-lua/series similarity index 100% rename from debian/modules/patches/nginx-lua/series rename to debian/modules/patches/http-lua/series diff --git a/debian/modules/patches/ngx_http_substitutions_filter_module/dynamic-module.patch b/debian/modules/patches/http-subs-filter/dynamic-module.patch similarity index 100% rename from debian/modules/patches/ngx_http_substitutions_filter_module/dynamic-module.patch rename to debian/modules/patches/http-subs-filter/dynamic-module.patch diff --git a/debian/modules/patches/ngx_http_substitutions_filter_module/series b/debian/modules/patches/http-subs-filter/series similarity index 100% rename from debian/modules/patches/ngx_http_substitutions_filter_module/series rename to debian/modules/patches/http-subs-filter/series diff --git a/debian/modules/patches/nginx-upstream-fair/drop-default-port.patch b/debian/modules/patches/http-upstream-fair/drop-default-port.patch similarity index 100% rename from debian/modules/patches/nginx-upstream-fair/drop-default-port.patch rename to debian/modules/patches/http-upstream-fair/drop-default-port.patch diff --git a/debian/modules/patches/nginx-upstream-fair/dynamic-module.patch b/debian/modules/patches/http-upstream-fair/dynamic-module.patch similarity index 100% rename from debian/modules/patches/nginx-upstream-fair/dynamic-module.patch rename to debian/modules/patches/http-upstream-fair/dynamic-module.patch diff --git a/debian/modules/patches/nginx-upstream-fair/openssl-1.1.0.patch b/debian/modules/patches/http-upstream-fair/openssl-1.1.0.patch similarity index 100% rename from debian/modules/patches/nginx-upstream-fair/openssl-1.1.0.patch rename to debian/modules/patches/http-upstream-fair/openssl-1.1.0.patch diff --git a/debian/modules/patches/nginx-upstream-fair/series b/debian/modules/patches/http-upstream-fair/series similarity index 100% rename from debian/modules/patches/nginx-upstream-fair/series rename to debian/modules/patches/http-upstream-fair/series diff --git a/debian/modules/nginx-rtmp/AUTHORS b/debian/modules/rtmp/AUTHORS similarity index 100% rename from debian/modules/nginx-rtmp/AUTHORS rename to debian/modules/rtmp/AUTHORS diff --git a/debian/modules/nginx-rtmp/LICENSE b/debian/modules/rtmp/LICENSE similarity index 100% rename from debian/modules/nginx-rtmp/LICENSE rename to debian/modules/rtmp/LICENSE diff --git a/debian/modules/nginx-rtmp/README.md b/debian/modules/rtmp/README.md similarity index 100% rename from debian/modules/nginx-rtmp/README.md rename to debian/modules/rtmp/README.md diff --git a/debian/modules/nginx-rtmp/config b/debian/modules/rtmp/config similarity index 100% rename from debian/modules/nginx-rtmp/config rename to debian/modules/rtmp/config diff --git a/debian/modules/nginx-rtmp/dash/ngx_rtmp_dash_module.c b/debian/modules/rtmp/dash/ngx_rtmp_dash_module.c similarity index 100% rename from debian/modules/nginx-rtmp/dash/ngx_rtmp_dash_module.c rename to debian/modules/rtmp/dash/ngx_rtmp_dash_module.c diff --git a/debian/modules/nginx-rtmp/dash/ngx_rtmp_mp4.c b/debian/modules/rtmp/dash/ngx_rtmp_mp4.c similarity index 100% rename from debian/modules/nginx-rtmp/dash/ngx_rtmp_mp4.c rename to debian/modules/rtmp/dash/ngx_rtmp_mp4.c diff --git a/debian/modules/nginx-rtmp/dash/ngx_rtmp_mp4.h b/debian/modules/rtmp/dash/ngx_rtmp_mp4.h similarity index 100% rename from debian/modules/nginx-rtmp/dash/ngx_rtmp_mp4.h rename to debian/modules/rtmp/dash/ngx_rtmp_mp4.h diff --git a/debian/modules/nginx-rtmp/doc/README.md b/debian/modules/rtmp/doc/README.md similarity index 100% rename from debian/modules/nginx-rtmp/doc/README.md rename to debian/modules/rtmp/doc/README.md diff --git a/debian/modules/nginx-rtmp/hls/ngx_rtmp_hls_module.c b/debian/modules/rtmp/hls/ngx_rtmp_hls_module.c similarity index 100% rename from debian/modules/nginx-rtmp/hls/ngx_rtmp_hls_module.c rename to debian/modules/rtmp/hls/ngx_rtmp_hls_module.c diff --git a/debian/modules/nginx-rtmp/hls/ngx_rtmp_mpegts.c b/debian/modules/rtmp/hls/ngx_rtmp_mpegts.c similarity index 100% rename from debian/modules/nginx-rtmp/hls/ngx_rtmp_mpegts.c rename to debian/modules/rtmp/hls/ngx_rtmp_mpegts.c diff --git a/debian/modules/nginx-rtmp/hls/ngx_rtmp_mpegts.h b/debian/modules/rtmp/hls/ngx_rtmp_mpegts.h similarity index 100% rename from debian/modules/nginx-rtmp/hls/ngx_rtmp_mpegts.h rename to debian/modules/rtmp/hls/ngx_rtmp_mpegts.h diff --git a/debian/modules/nginx-rtmp/ngx_rtmp.c b/debian/modules/rtmp/ngx_rtmp.c similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp.c rename to debian/modules/rtmp/ngx_rtmp.c diff --git a/debian/modules/nginx-rtmp/ngx_rtmp.h b/debian/modules/rtmp/ngx_rtmp.h similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp.h rename to debian/modules/rtmp/ngx_rtmp.h diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_access_module.c b/debian/modules/rtmp/ngx_rtmp_access_module.c similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_access_module.c rename to debian/modules/rtmp/ngx_rtmp_access_module.c diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_amf.c b/debian/modules/rtmp/ngx_rtmp_amf.c similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_amf.c rename to debian/modules/rtmp/ngx_rtmp_amf.c diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_amf.h b/debian/modules/rtmp/ngx_rtmp_amf.h similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_amf.h rename to debian/modules/rtmp/ngx_rtmp_amf.h diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_auto_push_module.c b/debian/modules/rtmp/ngx_rtmp_auto_push_module.c similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_auto_push_module.c rename to debian/modules/rtmp/ngx_rtmp_auto_push_module.c diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_bandwidth.c b/debian/modules/rtmp/ngx_rtmp_bandwidth.c similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_bandwidth.c rename to debian/modules/rtmp/ngx_rtmp_bandwidth.c diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_bandwidth.h b/debian/modules/rtmp/ngx_rtmp_bandwidth.h similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_bandwidth.h rename to debian/modules/rtmp/ngx_rtmp_bandwidth.h diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_bitop.c b/debian/modules/rtmp/ngx_rtmp_bitop.c similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_bitop.c rename to debian/modules/rtmp/ngx_rtmp_bitop.c diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_bitop.h b/debian/modules/rtmp/ngx_rtmp_bitop.h similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_bitop.h rename to debian/modules/rtmp/ngx_rtmp_bitop.h diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_cmd_module.c b/debian/modules/rtmp/ngx_rtmp_cmd_module.c similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_cmd_module.c rename to debian/modules/rtmp/ngx_rtmp_cmd_module.c diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_cmd_module.h b/debian/modules/rtmp/ngx_rtmp_cmd_module.h similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_cmd_module.h rename to debian/modules/rtmp/ngx_rtmp_cmd_module.h diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_codec_module.c b/debian/modules/rtmp/ngx_rtmp_codec_module.c similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_codec_module.c rename to debian/modules/rtmp/ngx_rtmp_codec_module.c diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_codec_module.h b/debian/modules/rtmp/ngx_rtmp_codec_module.h similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_codec_module.h rename to debian/modules/rtmp/ngx_rtmp_codec_module.h diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_control_module.c b/debian/modules/rtmp/ngx_rtmp_control_module.c similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_control_module.c rename to debian/modules/rtmp/ngx_rtmp_control_module.c diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_core_module.c b/debian/modules/rtmp/ngx_rtmp_core_module.c similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_core_module.c rename to debian/modules/rtmp/ngx_rtmp_core_module.c diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_eval.c b/debian/modules/rtmp/ngx_rtmp_eval.c similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_eval.c rename to debian/modules/rtmp/ngx_rtmp_eval.c diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_eval.h b/debian/modules/rtmp/ngx_rtmp_eval.h similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_eval.h rename to debian/modules/rtmp/ngx_rtmp_eval.h diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_exec_module.c b/debian/modules/rtmp/ngx_rtmp_exec_module.c similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_exec_module.c rename to debian/modules/rtmp/ngx_rtmp_exec_module.c diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_flv_module.c b/debian/modules/rtmp/ngx_rtmp_flv_module.c similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_flv_module.c rename to debian/modules/rtmp/ngx_rtmp_flv_module.c diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_handler.c b/debian/modules/rtmp/ngx_rtmp_handler.c similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_handler.c rename to debian/modules/rtmp/ngx_rtmp_handler.c diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_handshake.c b/debian/modules/rtmp/ngx_rtmp_handshake.c similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_handshake.c rename to debian/modules/rtmp/ngx_rtmp_handshake.c diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_init.c b/debian/modules/rtmp/ngx_rtmp_init.c similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_init.c rename to debian/modules/rtmp/ngx_rtmp_init.c diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_limit_module.c b/debian/modules/rtmp/ngx_rtmp_limit_module.c similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_limit_module.c rename to debian/modules/rtmp/ngx_rtmp_limit_module.c diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_live_module.c b/debian/modules/rtmp/ngx_rtmp_live_module.c similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_live_module.c rename to debian/modules/rtmp/ngx_rtmp_live_module.c diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_live_module.h b/debian/modules/rtmp/ngx_rtmp_live_module.h similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_live_module.h rename to debian/modules/rtmp/ngx_rtmp_live_module.h diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_log_module.c b/debian/modules/rtmp/ngx_rtmp_log_module.c similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_log_module.c rename to debian/modules/rtmp/ngx_rtmp_log_module.c diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_mp4_module.c b/debian/modules/rtmp/ngx_rtmp_mp4_module.c similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_mp4_module.c rename to debian/modules/rtmp/ngx_rtmp_mp4_module.c diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_netcall_module.c b/debian/modules/rtmp/ngx_rtmp_netcall_module.c similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_netcall_module.c rename to debian/modules/rtmp/ngx_rtmp_netcall_module.c diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_netcall_module.h b/debian/modules/rtmp/ngx_rtmp_netcall_module.h similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_netcall_module.h rename to debian/modules/rtmp/ngx_rtmp_netcall_module.h diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_notify_module.c b/debian/modules/rtmp/ngx_rtmp_notify_module.c similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_notify_module.c rename to debian/modules/rtmp/ngx_rtmp_notify_module.c diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_play_module.c b/debian/modules/rtmp/ngx_rtmp_play_module.c similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_play_module.c rename to debian/modules/rtmp/ngx_rtmp_play_module.c diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_play_module.h b/debian/modules/rtmp/ngx_rtmp_play_module.h similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_play_module.h rename to debian/modules/rtmp/ngx_rtmp_play_module.h diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_proxy_protocol.c b/debian/modules/rtmp/ngx_rtmp_proxy_protocol.c similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_proxy_protocol.c rename to debian/modules/rtmp/ngx_rtmp_proxy_protocol.c diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_proxy_protocol.h b/debian/modules/rtmp/ngx_rtmp_proxy_protocol.h similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_proxy_protocol.h rename to debian/modules/rtmp/ngx_rtmp_proxy_protocol.h diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_receive.c b/debian/modules/rtmp/ngx_rtmp_receive.c similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_receive.c rename to debian/modules/rtmp/ngx_rtmp_receive.c diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_record_module.c b/debian/modules/rtmp/ngx_rtmp_record_module.c similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_record_module.c rename to debian/modules/rtmp/ngx_rtmp_record_module.c diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_record_module.h b/debian/modules/rtmp/ngx_rtmp_record_module.h similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_record_module.h rename to debian/modules/rtmp/ngx_rtmp_record_module.h diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_relay_module.c b/debian/modules/rtmp/ngx_rtmp_relay_module.c similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_relay_module.c rename to debian/modules/rtmp/ngx_rtmp_relay_module.c diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_relay_module.h b/debian/modules/rtmp/ngx_rtmp_relay_module.h similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_relay_module.h rename to debian/modules/rtmp/ngx_rtmp_relay_module.h diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_send.c b/debian/modules/rtmp/ngx_rtmp_send.c similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_send.c rename to debian/modules/rtmp/ngx_rtmp_send.c diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_shared.c b/debian/modules/rtmp/ngx_rtmp_shared.c similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_shared.c rename to debian/modules/rtmp/ngx_rtmp_shared.c diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_stat_module.c b/debian/modules/rtmp/ngx_rtmp_stat_module.c similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_stat_module.c rename to debian/modules/rtmp/ngx_rtmp_stat_module.c diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_streams.h b/debian/modules/rtmp/ngx_rtmp_streams.h similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_streams.h rename to debian/modules/rtmp/ngx_rtmp_streams.h diff --git a/debian/modules/nginx-rtmp/ngx_rtmp_version.h b/debian/modules/rtmp/ngx_rtmp_version.h similarity index 100% rename from debian/modules/nginx-rtmp/ngx_rtmp_version.h rename to debian/modules/rtmp/ngx_rtmp_version.h diff --git a/debian/modules/nginx-rtmp/stat.xsl b/debian/modules/rtmp/stat.xsl similarity index 100% rename from debian/modules/nginx-rtmp/stat.xsl rename to debian/modules/rtmp/stat.xsl diff --git a/debian/rules b/debian/rules index a852d02..981a57e 100755 --- a/debian/rules +++ b/debian/rules @@ -82,7 +82,7 @@ light_configure_flags := \ --without-http_referer_module \ --without-http_split_clients_module \ --without-http_userid_module \ - --add-dynamic-module=$(MODULESDIR)/nginx-echo + --add-dynamic-module=$(MODULESDIR)/http-echo full_configure_flags := \ $(common_configure_flags) \ @@ -98,11 +98,11 @@ full_configure_flags := \ --with-stream_ssl_preread_module \ --with-mail=dynamic \ --with-mail_ssl_module \ - --add-dynamic-module=$(MODULESDIR)/nginx-auth-pam \ - --add-dynamic-module=$(MODULESDIR)/nginx-dav-ext-module \ - --add-dynamic-module=$(MODULESDIR)/nginx-echo \ - --add-dynamic-module=$(MODULESDIR)/nginx-upstream-fair \ - --add-dynamic-module=$(MODULESDIR)/ngx_http_substitutions_filter_module + --add-dynamic-module=$(MODULESDIR)/http-auth-pam \ + --add-dynamic-module=$(MODULESDIR)/http-dav-ext \ + --add-dynamic-module=$(MODULESDIR)/http-echo \ + --add-dynamic-module=$(MODULESDIR)/http-upstream-fair \ + --add-dynamic-module=$(MODULESDIR)/http-subs-filter extras_configure_flags := \ $(common_configure_flags) \ @@ -123,19 +123,19 @@ extras_configure_flags := \ --with-stream=dynamic \ --with-stream_ssl_module \ --with-stream_ssl_preread_module \ - --add-dynamic-module=$(MODULESDIR)/headers-more-nginx-module \ - --add-dynamic-module=$(MODULESDIR)/nginx-auth-pam \ - --add-dynamic-module=$(MODULESDIR)/nginx-cache-purge \ - --add-dynamic-module=$(MODULESDIR)/nginx-dav-ext-module \ - --add-dynamic-module=$(MODULESDIR)/nginx-development-kit \ - --add-dynamic-module=$(MODULESDIR)/nginx-echo \ - --add-dynamic-module=$(MODULESDIR)/ngx-fancyindex \ + --add-dynamic-module=$(MODULESDIR)/http-headers-more-filter \ + --add-dynamic-module=$(MODULESDIR)/http-auth-pam \ + --add-dynamic-module=$(MODULESDIR)/http-cache-purge \ + --add-dynamic-module=$(MODULESDIR)/http-dav-ext \ + --add-dynamic-module=$(MODULESDIR)/http-ndk \ + --add-dynamic-module=$(MODULESDIR)/http-echo \ + --add-dynamic-module=$(MODULESDIR)/http-fancyindex \ --add-dynamic-module=$(MODULESDIR)/nchan \ - --add-dynamic-module=$(MODULESDIR)/nginx-lua \ - --add-dynamic-module=$(MODULESDIR)/nginx-rtmp \ - --add-dynamic-module=$(MODULESDIR)/nginx-upload-progress \ - --add-dynamic-module=$(MODULESDIR)/nginx-upstream-fair \ - --add-dynamic-module=$(MODULESDIR)/ngx_http_substitutions_filter_module + --add-dynamic-module=$(MODULESDIR)/http-lua \ + --add-dynamic-module=$(MODULESDIR)/rtmp \ + --add-dynamic-module=$(MODULESDIR)/http-uploadprogress \ + --add-dynamic-module=$(MODULESDIR)/http-upstream-fair \ + --add-dynamic-module=$(MODULESDIR)/http-subs-filter %: dh $@ --without autoreconf From 0305fe8ea3e438b80a815f2ef18e6ecc77cca6b7 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Thu, 12 Oct 2017 10:37:08 +0300 Subject: [PATCH 221/600] Bump Standards-Version, no changes needed --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index e7a598a..17cfaab 100644 --- a/debian/control +++ b/debian/control @@ -24,7 +24,7 @@ Build-Depends: debhelper (>= 10), po-debconf, quilt, zlib1g-dev -Standards-Version: 4.1.0 +Standards-Version: 4.1.1 Homepage: http://nginx.net Vcs-Git: https://anonscm.debian.org/cgit/pkg-nginx/nginx.git Vcs-Browser: https://anonscm.debian.org/cgit/pkg-nginx/nginx.git From bf0c6fce6e6887b65e129f7974c3e8df69c8c627 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Thu, 12 Oct 2017 10:35:21 +0300 Subject: [PATCH 222/600] Drop dh-systemd dependency since we depend on debhelper >= 10 Fixes build-depends-on-obsolete-package in lintian. --- debian/control | 1 - 1 file changed, 1 deletion(-) diff --git a/debian/control b/debian/control index 17cfaab..b8ae948 100644 --- a/debian/control +++ b/debian/control @@ -7,7 +7,6 @@ Uploaders: Kartik Mistry , Christos Trochalakis Build-Depends: debhelper (>= 10), po-debconf, - dh-systemd (>= 1.5), dpkg-dev (>= 1.15.5), libexpat-dev, libgd-dev, From f056335a382b9ef80a0e7ea390c547ddeb61061e Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Thu, 12 Oct 2017 10:44:13 +0300 Subject: [PATCH 223/600] Release 1.13.6-1 --- debian/changelog | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/debian/changelog b/debian/changelog index 396226e..8aa3e0a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,12 @@ +nginx (1.13.6-1) unstable; urgency=medium + + * New upstream version + * Normalize module paths in packaging repository + * Bump Standards-Version, no changes needed + * Drop dh-systemd dependency since we depend on debhelper >= 10 + + -- Christos Trochalakis Thu, 12 Oct 2017 10:37:29 +0300 + nginx (1.13.5-1) unstable; urgency=medium * New upstream version 1.13.5 From 10af9c3beff85db4b194106586a899169e734be8 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Fri, 13 Oct 2017 12:40:11 +0300 Subject: [PATCH 224/600] rtmp: Ship docs & examples Closes: #878368 --- debian/libnginx-mod-rtmp.docs | 2 +- debian/libnginx-mod-rtmp.examples | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/libnginx-mod-rtmp.docs b/debian/libnginx-mod-rtmp.docs index 8bb7d17..e5c5c00 100644 --- a/debian/libnginx-mod-rtmp.docs +++ b/debian/libnginx-mod-rtmp.docs @@ -1 +1 @@ -debian/modules/nginx-rtmp/README.md +debian/modules/rtmp/README.md diff --git a/debian/libnginx-mod-rtmp.examples b/debian/libnginx-mod-rtmp.examples index 6748d60..563f038 100644 --- a/debian/libnginx-mod-rtmp.examples +++ b/debian/libnginx-mod-rtmp.examples @@ -1 +1 @@ -debian/modules/nginx-rtmp/stat.xsl +debian/modules/rtmp/stat.xsl From 08248c9d96a3a6d83444f268219a8f8812c79f48 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Fri, 13 Oct 2017 12:59:41 +0300 Subject: [PATCH 225/600] Release 1.13.6-2 --- debian/changelog | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/debian/changelog b/debian/changelog index 8aa3e0a..5be779e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +nginx (1.13.6-2) unstable; urgency=medium + + * rtmp: Ship docs & examples (Closes: #878368) + + -- Christos Trochalakis Fri, 13 Oct 2017 12:59:28 +0300 + nginx (1.13.6-1) unstable; urgency=medium * New upstream version From dfa79bec5c13485c7be06718a713fe2793568160 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Wed, 22 Nov 2017 16:31:37 +0200 Subject: [PATCH 226/600] New upstream version 1.13.7 --- CHANGES | 24 ++++++++++++ CHANGES.ru | 24 ++++++++++++ src/core/nginx.h | 4 +- src/core/ngx_conf_file.h | 2 +- src/core/ngx_cycle.c | 24 ++++++++---- src/event/ngx_event_openssl.h | 1 + src/http/modules/ngx_http_fastcgi_module.c | 1 + .../modules/ngx_http_gzip_filter_module.c | 38 ++++++++++++++++--- src/http/modules/ngx_http_ssi_filter_module.c | 15 ++++---- .../modules/ngx_http_xslt_filter_module.c | 15 +++++++- src/http/ngx_http_postpone_filter_module.c | 9 ++++- src/http/ngx_http_request.c | 7 ++++ src/http/ngx_http_upstream.c | 12 ++++++ src/mail/ngx_mail_proxy_module.c | 7 +++- src/stream/ngx_stream_proxy_module.c | 6 +++ 15 files changed, 160 insertions(+), 29 deletions(-) diff --git a/CHANGES b/CHANGES index 6a9fdcc..d93a938 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,28 @@ +Changes with nginx 1.13.7 21 Nov 2017 + + *) Bugfix: in the $upstream_status variable. + + *) Bugfix: a segmentation fault might occur in a worker process if a + backend returned a "101 Switching Protocols" response to a + subrequest. + + *) Bugfix: a segmentation fault occurred in a master process if a shared + memory zone size was changed during a reconfiguration and the + reconfiguration failed. + + *) Bugfix: in the ngx_http_fastcgi_module. + + *) Bugfix: nginx returned the 500 error if parameters without variables + were specified in the "xslt_stylesheet" directive. + + *) Workaround: "gzip filter failed to use preallocated memory" alerts + appeared in logs when using a zlib library variant from Intel. + + *) Bugfix: the "worker_shutdown_timeout" directive did not work when + using mail proxy and when proxying WebSocket connections. + + Changes with nginx 1.13.6 10 Oct 2017 *) Bugfix: switching to the next upstream server in the stream module diff --git a/CHANGES.ru b/CHANGES.ru index 6ea87c9..e688a5c 100644 --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,28 @@ +Изменения в nginx 1.13.7 21.11.2017 + + *) Исправление: в переменной $upstream_status. + + *) Исправление: в рабочем процессе мог произойти segmentation fault, + если бэкенд возвращал ответ "101 Switching Protocols" на подзапрос. + + *) Исправление: если при переконфигурации изменялся размер зоны + разделяемой памяти и переконфигурация завершалась неудачно, то в + главном процессе происходил segmentation fault. + + *) Исправление: в модуле ngx_http_fastcgi_module. + + *) Исправление: nginx возвращал ошибку 500, если в директиве + xslt_stylesheet были заданы параметры без использования переменных. + + *) Изменение: при использовании варианта библиотеки zlib от Intel в лог + писались сообщения "gzip filter failed to use preallocated memory". + + *) Исправление: директива worker_shutdown_timeout не работала при + использовании почтового прокси-сервера и при проксировании + WebSocket-соединений. + + Изменения в nginx 1.13.6 10.10.2017 *) Исправление: при использовании директивы ssl_preread в модуле stream diff --git a/src/core/nginx.h b/src/core/nginx.h index 5806837..02b51ab 100644 --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1013006 -#define NGINX_VERSION "1.13.6" +#define nginx_version 1013007 +#define NGINX_VERSION "1.13.7" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD diff --git a/src/core/ngx_conf_file.h b/src/core/ngx_conf_file.h index 213611f..9cd5806 100644 --- a/src/core/ngx_conf_file.h +++ b/src/core/ngx_conf_file.h @@ -128,7 +128,7 @@ struct ngx_conf_s { ngx_uint_t cmd_type; ngx_conf_handler_pt handler; - char *handler_conf; + void *handler_conf; }; diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c index 675a506..f3ac24d 100644 --- a/src/core/ngx_cycle.c +++ b/src/core/ngx_cycle.c @@ -470,8 +470,6 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) goto shm_zone_found; } - ngx_shm_free(&oshm_zone[n].shm); - break; } @@ -662,14 +660,26 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) n = 0; } - if (oshm_zone[i].shm.name.len == shm_zone[n].shm.name.len - && ngx_strncmp(oshm_zone[i].shm.name.data, - shm_zone[n].shm.name.data, - oshm_zone[i].shm.name.len) - == 0) + if (oshm_zone[i].shm.name.len != shm_zone[n].shm.name.len) { + continue; + } + + if (ngx_strncmp(oshm_zone[i].shm.name.data, + shm_zone[n].shm.name.data, + oshm_zone[i].shm.name.len) + != 0) + { + continue; + } + + if (oshm_zone[i].tag == shm_zone[n].tag + && oshm_zone[i].shm.size == shm_zone[n].shm.size + && !oshm_zone[i].noreuse) { goto live_shm_zone; } + + break; } ngx_shm_free(&oshm_zone[i].shm); diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h index b9a3a96..623d851 100644 --- a/src/event/ngx_event_openssl.h +++ b/src/event/ngx_event_openssl.h @@ -22,6 +22,7 @@ #include #endif #include +#include #ifndef OPENSSL_NO_OCSP #include #endif diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c index ea16eca..b4bb1d0 100644 --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -2646,6 +2646,7 @@ ngx_http_fastcgi_process_record(ngx_http_request_t *r, } } + f->pos = p; f->state = state; return NGX_AGAIN; diff --git a/src/http/modules/ngx_http_gzip_filter_module.c b/src/http/modules/ngx_http_gzip_filter_module.c index 73b6d89..e4c343c 100644 --- a/src/http/modules/ngx_http_gzip_filter_module.c +++ b/src/http/modules/ngx_http_gzip_filter_module.c @@ -57,6 +57,7 @@ typedef struct { unsigned nomem:1; unsigned gzheader:1; unsigned buffering:1; + unsigned intel:1; size_t zin; size_t zout; @@ -233,6 +234,8 @@ static ngx_str_t ngx_http_gzip_ratio = ngx_string("gzip_ratio"); static ngx_http_output_header_filter_pt ngx_http_next_header_filter; static ngx_http_output_body_filter_pt ngx_http_next_body_filter; +static ngx_uint_t ngx_http_gzip_assume_intel; + static ngx_int_t ngx_http_gzip_header_filter(ngx_http_request_t *r) @@ -527,7 +530,27 @@ ngx_http_gzip_filter_memory(ngx_http_request_t *r, ngx_http_gzip_ctx_t *ctx) * *) 5920 bytes on amd64 and sparc64 */ - ctx->allocated = 8192 + (1 << (wbits + 2)) + (1 << (memlevel + 9)); + if (!ngx_http_gzip_assume_intel) { + ctx->allocated = 8192 + (1 << (wbits + 2)) + (1 << (memlevel + 9)); + + } else { + /* + * A zlib variant from Intel, https://github.com/jtkukunas/zlib. + * It can force window bits to 13 for fast compression level, + * on processors with SSE 4.2 it uses 64K hash instead of scaling + * it from the specified memory level, and also introduces + * 16-byte padding in one out of the two window-sized buffers. + */ + + if (conf->level == 1) { + wbits = ngx_max(wbits, 13); + } + + ctx->allocated = 8192 + 16 + (1 << (wbits + 2)) + + (1 << (ngx_max(memlevel, 8) + 8)) + + (1 << (memlevel + 8)); + ctx->intel = 1; + } } @@ -1003,7 +1026,7 @@ ngx_http_gzip_filter_alloc(void *opaque, u_int items, u_int size) alloc = items * size; - if (alloc % 512 != 0 && alloc < 8192) { + if (items == 1 && alloc % 512 != 0 && alloc < 8192) { /* * The zlib deflate_state allocation, it takes about 6K, @@ -1025,9 +1048,14 @@ ngx_http_gzip_filter_alloc(void *opaque, u_int items, u_int size) return p; } - ngx_log_error(NGX_LOG_ALERT, ctx->request->connection->log, 0, - "gzip filter failed to use preallocated memory: %ud of %ui", - items * size, ctx->allocated); + if (ctx->intel) { + ngx_log_error(NGX_LOG_ALERT, ctx->request->connection->log, 0, + "gzip filter failed to use preallocated memory: " + "%ud of %ui", items * size, ctx->allocated); + + } else { + ngx_http_gzip_assume_intel = 1; + } p = ngx_palloc(ctx->request->pool, items * size); diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c index e29e173..c799b2f 100644 --- a/src/http/modules/ngx_http_ssi_filter_module.c +++ b/src/http/modules/ngx_http_ssi_filter_module.c @@ -1630,8 +1630,7 @@ ngx_http_ssi_evaluate_string(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, u_char ch, *p, **value, *data, *part_data; size_t *size, len, prefix, part_len; ngx_str_t var, *val; - ngx_int_t key; - ngx_uint_t i, n, bracket, quoted; + ngx_uint_t i, n, bracket, quoted, key; ngx_array_t lengths, values; ngx_http_variable_value_t *vv; @@ -1883,9 +1882,8 @@ ngx_http_ssi_regex_match(ngx_http_request_t *r, ngx_str_t *pattern, int rc, *captures; u_char *p, errstr[NGX_MAX_CONF_ERRSTR]; size_t size; - ngx_int_t key; ngx_str_t *vv, name, value; - ngx_uint_t i, n; + ngx_uint_t i, n, key; ngx_http_ssi_ctx_t *ctx; ngx_http_ssi_var_t *var; ngx_regex_compile_t rgc; @@ -1988,10 +1986,10 @@ static ngx_int_t ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, ngx_str_t **params) { - ngx_int_t rc, key; + ngx_int_t rc; ngx_str_t *uri, *file, *wait, *set, *stub, args; ngx_buf_t *b; - ngx_uint_t flags, i; + ngx_uint_t flags, i, key; ngx_chain_t *cl, *tl, **ll, *out; ngx_http_request_t *sr; ngx_http_ssi_var_t *var; @@ -2248,9 +2246,9 @@ ngx_http_ssi_echo(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, { u_char *p; uintptr_t len; - ngx_int_t key; ngx_buf_t *b; ngx_str_t *var, *value, *enc, text; + ngx_uint_t key; ngx_chain_t *cl; ngx_http_variable_value_t *vv; @@ -2410,8 +2408,9 @@ static ngx_int_t ngx_http_ssi_set(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, ngx_str_t **params) { - ngx_int_t key, rc; + ngx_int_t rc; ngx_str_t *name, *value, *vv; + ngx_uint_t key; ngx_http_ssi_var_t *var; ngx_http_ssi_ctx_t *mctx; diff --git a/src/http/modules/ngx_http_xslt_filter_module.c b/src/http/modules/ngx_http_xslt_filter_module.c index fae5895..ea7ce2a 100644 --- a/src/http/modules/ngx_http_xslt_filter_module.c +++ b/src/http/modules/ngx_http_xslt_filter_module.c @@ -686,8 +686,19 @@ ngx_http_xslt_params(ngx_http_request_t *r, ngx_http_xslt_filter_ctx_t *ctx, * specified in xslt_stylesheet directives */ - p = string.data; - last = string.data + string.len; + if (param[i].value.lengths) { + p = string.data; + + } else { + p = ngx_pnalloc(r->pool, string.len + 1); + if (p == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(p, string.data, string.len + 1); + } + + last = p + string.len; while (p && *p) { diff --git a/src/http/ngx_http_postpone_filter_module.c b/src/http/ngx_http_postpone_filter_module.c index e893b83..55f2698 100644 --- a/src/http/ngx_http_postpone_filter_module.c +++ b/src/http/ngx_http_postpone_filter_module.c @@ -63,7 +63,10 @@ ngx_http_postpone_filter(ngx_http_request_t *r, ngx_chain_t *in) if (r != c->data) { if (in) { - ngx_http_postpone_filter_add(r, in); + if (ngx_http_postpone_filter_add(r, in) != NGX_OK) { + return NGX_ERROR; + } + return NGX_OK; } @@ -86,7 +89,9 @@ ngx_http_postpone_filter(ngx_http_request_t *r, ngx_chain_t *in) } if (in) { - ngx_http_postpone_filter_add(r, in); + if (ngx_http_postpone_filter_add(r, in) != NGX_OK) { + return NGX_ERROR; + } } do { diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c index de1b202..5668bf4 100644 --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -2225,6 +2225,13 @@ ngx_http_request_handler(ngx_event_t *ev) ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "http run request: \"%V?%V\"", &r->uri, &r->args); + if (c->close) { + r->main->count++; + ngx_http_terminate_request(r, 0); + ngx_http_run_posted_requests(c); + return; + } + if (ev->delayed && ev->timedout) { ev->delayed = 0; ev->timedout = 0; diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c index 2ea521b..75f463b 100644 --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -3206,6 +3206,13 @@ ngx_http_upstream_upgrade(ngx_http_request_t *r, ngx_http_upstream_t *u) /* TODO: prevent upgrade if not requested or not possible */ + if (r != r->main) { + ngx_log_error(NGX_LOG_ERR, c->log, 0, + "connection upgrade in subrequest"); + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } + r->keepalive = 0; c->log->action = "proxying upgraded connection"; @@ -4111,6 +4118,7 @@ ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u, switch (ft_type) { case NGX_HTTP_UPSTREAM_FT_TIMEOUT: + case NGX_HTTP_UPSTREAM_FT_HTTP_504: status = NGX_HTTP_GATEWAY_TIME_OUT; break; @@ -4118,6 +4126,10 @@ ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u, status = NGX_HTTP_INTERNAL_SERVER_ERROR; break; + case NGX_HTTP_UPSTREAM_FT_HTTP_503: + status = NGX_HTTP_SERVICE_UNAVAILABLE; + break; + case NGX_HTTP_UPSTREAM_FT_HTTP_403: status = NGX_HTTP_FORBIDDEN; break; diff --git a/src/mail/ngx_mail_proxy_module.c b/src/mail/ngx_mail_proxy_module.c index 007284b..1c86e54 100644 --- a/src/mail/ngx_mail_proxy_module.c +++ b/src/mail/ngx_mail_proxy_module.c @@ -882,10 +882,13 @@ ngx_mail_proxy_handler(ngx_event_t *ev) c = ev->data; s = c->data; - if (ev->timedout) { + if (ev->timedout || c->close) { c->log->action = "proxying"; - if (c == s->connection) { + if (c->close) { + ngx_log_error(NGX_LOG_INFO, c->log, 0, "shutdown timeout"); + + } else if (c == s->connection) { ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); c->timedout = 1; diff --git a/src/stream/ngx_stream_proxy_module.c b/src/stream/ngx_stream_proxy_module.c index 9d4b075..ad81cc8 100644 --- a/src/stream/ngx_stream_proxy_module.c +++ b/src/stream/ngx_stream_proxy_module.c @@ -1290,6 +1290,12 @@ ngx_stream_proxy_process_connection(ngx_event_t *ev, ngx_uint_t from_upstream) s = c->data; u = s->upstream; + if (c->close) { + ngx_log_error(NGX_LOG_INFO, c->log, 0, "shutdown timeout"); + ngx_stream_proxy_finalize(s, NGX_STREAM_OK); + return; + } + c = s->connection; pc = u->peer.connection; From 9f10b314887ff633e1ef28419538980904938425 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Wed, 13 Dec 2017 10:51:58 +0200 Subject: [PATCH 227/600] Bump Standards-Version, no changes needed --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index b8ae948..38cd027 100644 --- a/debian/control +++ b/debian/control @@ -23,7 +23,7 @@ Build-Depends: debhelper (>= 10), po-debconf, quilt, zlib1g-dev -Standards-Version: 4.1.1 +Standards-Version: 4.1.2 Homepage: http://nginx.net Vcs-Git: https://anonscm.debian.org/cgit/pkg-nginx/nginx.git Vcs-Browser: https://anonscm.debian.org/cgit/pkg-nginx/nginx.git From 08d6a8fe7a78a1d008a1e566d7bd96b317c51a93 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Thu, 14 Dec 2017 10:53:44 +0200 Subject: [PATCH 228/600] debian/watch: switch to HTTPS for the upstream check Fixes lintian `source: debian-watch-uses-insecure-uri` info. --- debian/watch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/watch b/debian/watch index 6fa2f3e..0a39b11 100644 --- a/debian/watch +++ b/debian/watch @@ -1,3 +1,3 @@ version=3 opts=pgpsigurlmangle=s/$/.asc/ \ -http://nginx.org/download/nginx-(1\.13\.\d+)\.tar\.gz +https://nginx.org/download/nginx-(1\.13\.\d+)\.tar\.gz From 794cca0ebffcebe24c4d52eac33a961da1b79acd Mon Sep 17 00:00:00 2001 From: Mpampis Kostas Date: Sat, 22 Jul 2017 16:26:21 +0300 Subject: [PATCH 229/600] Automate modules watch & upgrade process This patch introduces the debian/ngxmod script and some helper files which can be used to automate the modules watch & upgrade process. The only subcommand for now is `uscan` and can be called as: $ debian/ngxmod uscan The uscan subcommand runs uscan for each nginx module listed in the newly deb822 formatted debian/modules/control using the watchfiles in debian/modules/watch. If a new version is available, it will ask you if you want to upgrade. If you agree, it will download the tarball, place it in the nginx source's parent directory and upgrade the module's source. After the upgrade, it will remove the files listed in the Files-Excluded module field and finally it will commit the changes. Closes: #869499 --- debian/modules/README.Modules-versions | 69 -------- debian/modules/control | 71 ++++++++ debian/modules/uupdate | 10 ++ debian/modules/watch/http-auth-pam | 4 + debian/modules/watch/http-cache-purge | 4 + debian/modules/watch/http-dav-ext | 4 + debian/modules/watch/http-echo | 4 + debian/modules/watch/http-fancyindex | 4 + debian/modules/watch/http-headers-more-filter | 4 + debian/modules/watch/http-lua | 4 + debian/modules/watch/http-ndk | 4 + debian/modules/watch/http-subs-filter | 4 + debian/modules/watch/http-uploadprogress | 4 + debian/modules/watch/nchan | 4 + debian/modules/watch/rtmp | 4 + debian/ngxmod | 156 ++++++++++++++++++ 16 files changed, 285 insertions(+), 69 deletions(-) delete mode 100644 debian/modules/README.Modules-versions create mode 100644 debian/modules/control create mode 100755 debian/modules/uupdate create mode 100644 debian/modules/watch/http-auth-pam create mode 100644 debian/modules/watch/http-cache-purge create mode 100644 debian/modules/watch/http-dav-ext create mode 100644 debian/modules/watch/http-echo create mode 100644 debian/modules/watch/http-fancyindex create mode 100644 debian/modules/watch/http-headers-more-filter create mode 100644 debian/modules/watch/http-lua create mode 100644 debian/modules/watch/http-ndk create mode 100644 debian/modules/watch/http-subs-filter create mode 100644 debian/modules/watch/http-uploadprogress create mode 100644 debian/modules/watch/nchan create mode 100644 debian/modules/watch/rtmp create mode 100755 debian/ngxmod diff --git a/debian/modules/README.Modules-versions b/debian/modules/README.Modules-versions deleted file mode 100644 index ff5f63b..0000000 --- a/debian/modules/README.Modules-versions +++ /dev/null @@ -1,69 +0,0 @@ -README for Modules versions ---------------------------- - - This file lists third party modules built with nginx in Debian, homepage and - version. - - headers-more-nginx-module - Homepage: https://github.com/agentzh/headers-more-nginx-module - Version: v0.32 - - nginx-development-kit - Homepage: https://github.com/simpl/ngx_devel_kit/ - Version: v0.3.0 - - nginx-auth-pam - Homepage: https://github.com/stogh/ngx_http_auth_pam_module - Version: 1.5.1 - - nginx-echo - Homepage: https://github.com/agentzh/echo-nginx-module - Version: v0.60 - Patch: build-nginx-1.11.11.patch - - nginx-lua - Homepage: https://github.com/openresty/lua-nginx-module - Version: v0.10.10 - Patch: openssl-1.1.0.patch - Patch: discover-luajit-2.1.patch - - nginx-upstream-fair - Homepage: https://github.com/gnosek/nginx-upstream-fair - Version: a18b409 - Patch: dynamic-module.patch - Patch: openssl-1.1.0.patch - Patch: drop-default-port.patch - - nchan - Homepage: https://github.com/slact/nchan - Version: 1.0.8 - - nginx-upload-progress - Homepage: https://github.com/masterzen/nginx-upload-progress-module - rm -r debian/nginx-upload-progress/test - Version: v0.9.2 - - nginx-cache-purge - Homepage: https://github.com/FRiCKLE/ngx_cache_purge/ - Version: 2.3 - Patch: dynamic-module.patch - Patch: segfault-1.11.6.patch - - nginx-dav-ext-module - Homepage: https://github.com/arut/nginx-dav-ext-module - Version: v0.0.3 - Patch: dynamic-module.patch - - ngx-fancyindex - Homepage: https://github.com/aperezdc/ngx-fancyindex - Version: v0.4.1 - - ngx_http_substitutions_filter_module - Homepage: https://github.com/yaoweibin/ngx_http_substitutions_filter_module - Version: v0.6.4 - Patch: dynamic-module.patch - - nginx-rtmp - Homepage: https://github.com/arut/nginx-rtmp-module - rm -r debian/modules/nginx-rtmp-module/test - Version: v1.1.11 diff --git a/debian/modules/control b/debian/modules/control new file mode 100644 index 0000000..5f67e38 --- /dev/null +++ b/debian/modules/control @@ -0,0 +1,71 @@ +Module: http-headers-more-filter +Homepage: https://github.com/agentzh/headers-more-nginx-module +Version: v0.32 +Files-Excluded: .gitignore .gitattributes .travis.yml + +Module: http-ndk +Homepage: https://github.com/simpl/ngx_devel_kit/ +Version: v0.3.0 + +Module: http-auth-pam +Homepage: https://github.com/stogh/ngx_http_auth_pam_module +Version: v1.5.1 + +Module: http-echo +Homepage: https://github.com/agentzh/echo-nginx-module +Version: v0.60 +Files-Excluded: .gitignore .gitattributes .travis.yml +Patch: build-nginx-1.11.11.patch + +Module: http-lua +Homepage: https://github.com/openresty/lua-nginx-module +Version: v0.10.10 +Patch: + openssl-1.1.0.patch + discover-luajit-2.1.patch +Files-Excluded: .gitignore .gitattributes .travis.yml .github + +Module: http-upstream-fair +Homepage: https://github.com/gnosek/nginx-upstream-fair +Version: a18b409 +Patch: + dynamic-module.patch + openssl-1.1.0.patch + drop-default-port.patch + +Module: nchan +Homepage: https://github.com/slact/nchan +Version: v1.0.8 + +Module: http-uploadprogress +Homepage: https://github.com/masterzen/nginx-upload-progress-module +Files-Excluded: test +Version: v0.9.2 + +Module: http-cache-purge +Homepage: https://github.com/FRiCKLE/ngx_cache_purge/ +Version: 2.3 +Patch: + dynamic-module.patch + segfault-1.11.6.patch + +Module: http-dav-ext +Homepage: https://github.com/arut/nginx-dav-ext-module +Version: v0.0.3 +Patch: dynamic-module.patch + +Module: http-fancyindex +Homepage: https://github.com/aperezdc/ngx-fancyindex +Version: v0.4.1 +Files-Excluded: .gitignore .travis.yml + +Module: http-subs-filter +Homepage: https://github.com/yaoweibin/ngx_http_substitutions_filter_module +Version: v0.6.4 +Patch: dynamic-module.patch + +Module: rtmp +Homepage: https://github.com/arut/nginx-rtmp-module +Files-Excluded: test +Version: v1.1.11 + diff --git a/debian/modules/uupdate b/debian/modules/uupdate new file mode 100755 index 0000000..98a5f8b --- /dev/null +++ b/debian/modules/uupdate @@ -0,0 +1,10 @@ +#!/bin/bash + +# debian/modules/uupdate - simple tar wrapper used by uscan to upgrade modules source + +MOD_TAR_NAME=$2 +MOD_TAR_VER=$4 +DESTDIR=debian/modules/$1 + +tar --strip-components=1 -xf ../$MOD_TAR_NAME-$MOD_TAR_VER.tar.gz -C $DESTDIR +echo $MOD_TAR_VER > /tmp/ngx_uupdate_version_$1 diff --git a/debian/modules/watch/http-auth-pam b/debian/modules/watch/http-auth-pam new file mode 100644 index 0000000..eac2f73 --- /dev/null +++ b/debian/modules/watch/http-auth-pam @@ -0,0 +1,4 @@ +version=4 +opts="dversionmangle=s/v//,filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%ngx-mod-http-auth-pam-$1.tar.gz%" \ + https://github.com/stogh/ngx_http_auth_pam_module/tags \ + (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian debian/modules/uupdate http-auth-pam ngx-mod-http-auth-pam diff --git a/debian/modules/watch/http-cache-purge b/debian/modules/watch/http-cache-purge new file mode 100644 index 0000000..2566801 --- /dev/null +++ b/debian/modules/watch/http-cache-purge @@ -0,0 +1,4 @@ +version=4 +opts="dversionmangle=s/v//,filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%ngx-mod-cache-purge-$1.tar.gz%" \ + https://github.com/FRiCKLE/ngx_cache_purge/tags \ + (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian debian/modules/uupdate http-cache-purge ngx-mod-cache-purge diff --git a/debian/modules/watch/http-dav-ext b/debian/modules/watch/http-dav-ext new file mode 100644 index 0000000..d704cfc --- /dev/null +++ b/debian/modules/watch/http-dav-ext @@ -0,0 +1,4 @@ +version=4 +opts="dversionmangle=s/v//,filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%ngx-mod-dav-ext-$1.tar.gz%" \ + https://github.com/arut/nginx-dav-ext-module/tags \ + (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian debian/modules/uupdate http-dav-ext ngx-mod-dav-ext diff --git a/debian/modules/watch/http-echo b/debian/modules/watch/http-echo new file mode 100644 index 0000000..615532b --- /dev/null +++ b/debian/modules/watch/http-echo @@ -0,0 +1,4 @@ +version=4 +opts="dversionmangle=s/v//,filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%ngx-mod-echo-$1.tar.gz%" \ + https://github.com/agentzh/echo-nginx-module/tags \ + (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian debian/modules/uupdate http-echo ngx-mod-echo diff --git a/debian/modules/watch/http-fancyindex b/debian/modules/watch/http-fancyindex new file mode 100644 index 0000000..72435fd --- /dev/null +++ b/debian/modules/watch/http-fancyindex @@ -0,0 +1,4 @@ +version=4 +opts="dversionmangle=s/v//,filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%ngx-mod-fancyindex-$1.tar.gz%" \ + https://github.com/aperezdc/ngx-fancyindex/tags \ + (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian debian/modules/uupdate http-fancyindex ngx-mod-fancyindex diff --git a/debian/modules/watch/http-headers-more-filter b/debian/modules/watch/http-headers-more-filter new file mode 100644 index 0000000..cfe5fc9 --- /dev/null +++ b/debian/modules/watch/http-headers-more-filter @@ -0,0 +1,4 @@ +version=4 +opts="uversionmangle=s/0.261/0.26.1/,dversionmangle=s/v//,filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%ngx-mod-headers-more-$1.tar.gz%" \ + https://github.com/agentzh/headers-more-nginx-module/tags \ + (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian debian/modules/uupdate http-headers-more-filter ngx-mod-headers-more diff --git a/debian/modules/watch/http-lua b/debian/modules/watch/http-lua new file mode 100644 index 0000000..7f1718f --- /dev/null +++ b/debian/modules/watch/http-lua @@ -0,0 +1,4 @@ +version=4 +opts="dversionmangle=s/v//,filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%lua-nginx-module-$1.tar.gz%" \ + https://github.com/openresty/lua-nginx-module/tags \ + (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian debian/modules/uupdate http-lua lua-nginx-module diff --git a/debian/modules/watch/http-ndk b/debian/modules/watch/http-ndk new file mode 100644 index 0000000..43f0cbd --- /dev/null +++ b/debian/modules/watch/http-ndk @@ -0,0 +1,4 @@ +version=4 +opts="dversionmangle=s/v//,filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%ngx-mod-devel-kit-$1.tar.gz%" \ + https://github.com/simpl/ngx_devel_kit/tags \ + (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian debian/modules/uupdate http-ndk ngx-mod-devel-kit diff --git a/debian/modules/watch/http-subs-filter b/debian/modules/watch/http-subs-filter new file mode 100644 index 0000000..cca3e05 --- /dev/null +++ b/debian/modules/watch/http-subs-filter @@ -0,0 +1,4 @@ +version=4 +opts="dversionmangle=s/v//,filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%ngx-mod-http-substitutions-filter-$1.tar.gz%" \ + https://github.com/yaoweibin/ngx_http_substitutions_filter_module/tags \ + (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian debian/modules/uupdate http-subs-filter ngx-mod-http-substitutions-filter diff --git a/debian/modules/watch/http-uploadprogress b/debian/modules/watch/http-uploadprogress new file mode 100644 index 0000000..7c0b7cf --- /dev/null +++ b/debian/modules/watch/http-uploadprogress @@ -0,0 +1,4 @@ +version=4 +opts="dversionmangle=s/v//,filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%ngx-mod-upload-progress-$1.tar.gz%" \ + https://github.com/masterzen/nginx-upload-progress-module/tags \ + (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian debian/modules/uupdate http-uploadprogress ngx-mod-upload-progress diff --git a/debian/modules/watch/nchan b/debian/modules/watch/nchan new file mode 100644 index 0000000..6b95884 --- /dev/null +++ b/debian/modules/watch/nchan @@ -0,0 +1,4 @@ +version=4 +opts="dversionmangle=s/v//,filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%ngx-mod-nchan-$1.tar.gz%" \ + https://github.com/slact/nchan/tags \ + (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian debian/modules/uupdate nchan ngx-mod-nchan diff --git a/debian/modules/watch/rtmp b/debian/modules/watch/rtmp new file mode 100644 index 0000000..f8137a2 --- /dev/null +++ b/debian/modules/watch/rtmp @@ -0,0 +1,4 @@ +version=4 +opts="dversionmangle=s/v//,filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%ngx-mod-rtmp-$1.tar.gz%" \ + https://github.com/arut/nginx-rtmp-module/tags \ + (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian debian/modules/uupdate rtmp ngx-mod-rtmp diff --git a/debian/ngxmod b/debian/ngxmod new file mode 100755 index 0000000..f8180d1 --- /dev/null +++ b/debian/ngxmod @@ -0,0 +1,156 @@ +#!/usr/bin/env python +''' +ngxmod - nginx modules management helper script + +Usage: + ngxmod + +Subcommands: + + uscan - scan/watch upstream nginx module sources for new releases + + It runs uscan for each nginx module listed in debian/modules/control. + + If a new version is available, it will ask you if you want to upgrade. + If you agree it will use uscan to download the tarball, place it in the nginx + source's parent directory and unpack it using modules/uupdate to upgrade + the module's source. + + After the upgrade, it will remove the files listed in the Files-Excluded + field and finally it will commit the changes. +''' + +import deb822 +import os +import sys +import re +from subprocess import call + +MODULES_PATH = 'modules/' +MODULES_CTRL = os.path.join(MODULES_PATH, 'control') + +def prompt(query): + ''' + Ask the given query and wait for an y/N answer. + + :query: The query + :returns: The yes (True) or no (False) answer + ''' + sys.stdout.write('%s [y/N]: ' % query) + choice = raw_input().lower() + + return choice == 'y' + + +def upgrade_module(mi, watchfile): + ''' + Upgrade the given module using uscan and the custom modules/uupdate. + After the upgrade, remove the Files-Excluded. + + :param mi: modules/control info for the module + :param watchfile: The watchfile of the module + :returns: The new module version + ''' + uscan_upgrade_cmd = [ + 'uscan', '--upstream-version', mi['Version'], + '--watchfile', 'debian/%s' % watchfile, '--no-symlink' + ] + upgrade_ret = call(uscan_upgrade_cmd, stdout=open(os.devnull, 'w')) + + if 'Files-Excluded' in mi and upgrade_ret == 0: + print 'Removing Files-Excluded: %s' % mi['Files-Excluded'] + + files = re.split('\s+', mi['Files-Excluded']) + files = filter(None, files) + abs_files = ['%s%s/%s' % (MODULES_PATH, mi['Module'], f) for f in files] + + rm_cmd = ['rm', '-r'] + rm_cmd.extend(abs_files) + + call(rm_cmd) + + return open('/tmp/ngx_uupdate_version_%s' % mi['Module']).read().rstrip() + + +def update_module_version(mi, new_ver): + ''' + Update the given module's version in modules/control. + + :param mi: modules/control info for the module + :param new_ver: The new module version + ''' + modules_info = deb822.Deb822.iter_paragraphs(file(MODULES_CTRL)) + modules_ctrl_new = '%s%s' % (MODULES_CTRL, '.new') + with open(modules_ctrl_new, 'w') as c: + for m in modules_info: + if mi['Module'] == m['Module']: + m['Version'] = re.sub('[^v]+', new_ver, m['Version']) + + c.write(m.dump() + '\n') + c.closed + os.rename(modules_ctrl_new, MODULES_CTRL) + + +def commit_module(mi, new_ver): + ''' + Git-commit the given module's upgraded source. + + :param mi: modules/control info for the module + :param new_ver: The new module version + ''' + module_name = mi['Module'] + module_path = os.path.join(MODULES_PATH, module_name) + + git_add_cmd = ['git', 'add', module_path, MODULES_CTRL] + call(git_add_cmd) + + commit_msg = 'Update %s to v%s' % (module_name, new_ver) + git_commit_cmd = ['git', 'commit', '-m', commit_msg] + call(git_commit_cmd) + + +def usage(): + print(""" +Usage: + ngxmod + +Subcommands: + + uscan - scan/watch upstream nginx module sources for new releases +""") + + +def main(): + modules_info = deb822.Deb822.iter_paragraphs(file(MODULES_CTRL)) + + for mi in modules_info: + sys.stdout.write('Uscanning %s...' % mi['Module']) + sys.stdout.flush() + + watchfile = os.path.join(MODULES_PATH, 'watch', mi['Module']) + + if not os.path.isfile(watchfile): + print 'no watchfile available.' + continue + + uscan_check_cmd = [ + 'uscan', '--upstream-version', mi['Version'], + '--watchfile', watchfile, '--package', + mi['Module'] + ] + check_ret = call(uscan_check_cmd) + + if check_ret == 0: + if prompt('Do you want to upgrade %s?' % mi['Module']): + new_module_ver = upgrade_module(mi, watchfile) + update_module_version(mi, new_module_ver) + commit_module(mi, new_module_ver) + else: + print 'up-to-date.' + + +if __name__ == '__main__': + if len(sys.argv) == 2 and sys.argv[1] == 'uscan': + main() + else: + usage() From 7f899937abcb400b8fc8e5d014ca16af9705eeab Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Mon, 11 Dec 2017 11:46:58 +0200 Subject: [PATCH 230/600] Bits & pieces for ngxmod o Drop d/m/uupdate in favor of ngxmod uupdate subcommand. While at it, take advantage of the canonical module names and drop the last argument. o Move unpacking & commit to uupdate subcommand, that way we don't to have to communicate the upstream version with ngxmod uscan. o Move around a few things, and switch to argparse. --- debian/modules/uupdate | 10 - debian/modules/watch/http-auth-pam | 4 +- debian/modules/watch/http-cache-purge | 4 +- debian/modules/watch/http-dav-ext | 4 +- debian/modules/watch/http-echo | 4 +- debian/modules/watch/http-fancyindex | 4 +- debian/modules/watch/http-headers-more-filter | 4 +- debian/modules/watch/http-lua | 4 +- debian/modules/watch/http-ndk | 4 +- debian/modules/watch/http-subs-filter | 4 +- debian/modules/watch/http-uploadprogress | 4 +- debian/modules/watch/nchan | 4 +- debian/modules/watch/rtmp | 4 +- debian/ngxmod | 278 +++++++++++------- 14 files changed, 194 insertions(+), 142 deletions(-) delete mode 100755 debian/modules/uupdate diff --git a/debian/modules/uupdate b/debian/modules/uupdate deleted file mode 100755 index 98a5f8b..0000000 --- a/debian/modules/uupdate +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -# debian/modules/uupdate - simple tar wrapper used by uscan to upgrade modules source - -MOD_TAR_NAME=$2 -MOD_TAR_VER=$4 -DESTDIR=debian/modules/$1 - -tar --strip-components=1 -xf ../$MOD_TAR_NAME-$MOD_TAR_VER.tar.gz -C $DESTDIR -echo $MOD_TAR_VER > /tmp/ngx_uupdate_version_$1 diff --git a/debian/modules/watch/http-auth-pam b/debian/modules/watch/http-auth-pam index eac2f73..3fb5a27 100644 --- a/debian/modules/watch/http-auth-pam +++ b/debian/modules/watch/http-auth-pam @@ -1,4 +1,4 @@ version=4 -opts="dversionmangle=s/v//,filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%ngx-mod-http-auth-pam-$1.tar.gz%" \ +opts="dversionmangle=s/v//,filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%libnginx-mod-http-auth-pam-$1.tar.gz%" \ https://github.com/stogh/ngx_http_auth_pam_module/tags \ - (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian debian/modules/uupdate http-auth-pam ngx-mod-http-auth-pam + (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian debian/ngxmod uupdate http-auth-pam diff --git a/debian/modules/watch/http-cache-purge b/debian/modules/watch/http-cache-purge index 2566801..e2458f2 100644 --- a/debian/modules/watch/http-cache-purge +++ b/debian/modules/watch/http-cache-purge @@ -1,4 +1,4 @@ version=4 -opts="dversionmangle=s/v//,filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%ngx-mod-cache-purge-$1.tar.gz%" \ +opts="dversionmangle=s/v//,filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%libnginx-mod-http-cache-purge-$1.tar.gz%" \ https://github.com/FRiCKLE/ngx_cache_purge/tags \ - (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian debian/modules/uupdate http-cache-purge ngx-mod-cache-purge + (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian debian/ngxmod uupdate http-cache-purge diff --git a/debian/modules/watch/http-dav-ext b/debian/modules/watch/http-dav-ext index d704cfc..064766a 100644 --- a/debian/modules/watch/http-dav-ext +++ b/debian/modules/watch/http-dav-ext @@ -1,4 +1,4 @@ version=4 -opts="dversionmangle=s/v//,filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%ngx-mod-dav-ext-$1.tar.gz%" \ +opts="dversionmangle=s/v//,filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%libnginx-mod-http-dav-ext-$1.tar.gz%" \ https://github.com/arut/nginx-dav-ext-module/tags \ - (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian debian/modules/uupdate http-dav-ext ngx-mod-dav-ext + (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian debian/ngxmod uupdate http-dav-ext diff --git a/debian/modules/watch/http-echo b/debian/modules/watch/http-echo index 615532b..3d44f5d 100644 --- a/debian/modules/watch/http-echo +++ b/debian/modules/watch/http-echo @@ -1,4 +1,4 @@ version=4 -opts="dversionmangle=s/v//,filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%ngx-mod-echo-$1.tar.gz%" \ +opts="dversionmangle=s/v//,filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%libnginx-mod-http-echo-$1.tar.gz%" \ https://github.com/agentzh/echo-nginx-module/tags \ - (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian debian/modules/uupdate http-echo ngx-mod-echo + (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian debian/ngxmod uupdate http-echo diff --git a/debian/modules/watch/http-fancyindex b/debian/modules/watch/http-fancyindex index 72435fd..5833ccd 100644 --- a/debian/modules/watch/http-fancyindex +++ b/debian/modules/watch/http-fancyindex @@ -1,4 +1,4 @@ version=4 -opts="dversionmangle=s/v//,filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%ngx-mod-fancyindex-$1.tar.gz%" \ +opts="dversionmangle=s/v//,filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%libnginx-mod-http-fancyindex-$1.tar.gz%" \ https://github.com/aperezdc/ngx-fancyindex/tags \ - (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian debian/modules/uupdate http-fancyindex ngx-mod-fancyindex + (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian debian/ngxmod uupdate http-fancyindex diff --git a/debian/modules/watch/http-headers-more-filter b/debian/modules/watch/http-headers-more-filter index cfe5fc9..b0cae5c 100644 --- a/debian/modules/watch/http-headers-more-filter +++ b/debian/modules/watch/http-headers-more-filter @@ -1,4 +1,4 @@ version=4 -opts="uversionmangle=s/0.261/0.26.1/,dversionmangle=s/v//,filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%ngx-mod-headers-more-$1.tar.gz%" \ +opts="uversionmangle=s/0.261/0.26.1/,dversionmangle=s/v//,filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%libnginx-mod-http-headers-more-filter-$1.tar.gz%" \ https://github.com/agentzh/headers-more-nginx-module/tags \ - (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian debian/modules/uupdate http-headers-more-filter ngx-mod-headers-more + (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian debian/ngxmod uupdate http-headers-more-filter diff --git a/debian/modules/watch/http-lua b/debian/modules/watch/http-lua index 7f1718f..193d824 100644 --- a/debian/modules/watch/http-lua +++ b/debian/modules/watch/http-lua @@ -1,4 +1,4 @@ version=4 -opts="dversionmangle=s/v//,filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%lua-nginx-module-$1.tar.gz%" \ +opts="dversionmangle=s/v//,filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%libnginx-mod-http-lua-$1.tar.gz%" \ https://github.com/openresty/lua-nginx-module/tags \ - (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian debian/modules/uupdate http-lua lua-nginx-module + (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian debian/ngxmod uupdate http-lua diff --git a/debian/modules/watch/http-ndk b/debian/modules/watch/http-ndk index 43f0cbd..f359136 100644 --- a/debian/modules/watch/http-ndk +++ b/debian/modules/watch/http-ndk @@ -1,4 +1,4 @@ version=4 -opts="dversionmangle=s/v//,filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%ngx-mod-devel-kit-$1.tar.gz%" \ +opts="dversionmangle=s/v//,filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%libnginx-mod-http-ndk-$1.tar.gz%" \ https://github.com/simpl/ngx_devel_kit/tags \ - (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian debian/modules/uupdate http-ndk ngx-mod-devel-kit + (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian debian/ngxmod uupdate http-ndk diff --git a/debian/modules/watch/http-subs-filter b/debian/modules/watch/http-subs-filter index cca3e05..2d37540 100644 --- a/debian/modules/watch/http-subs-filter +++ b/debian/modules/watch/http-subs-filter @@ -1,4 +1,4 @@ version=4 -opts="dversionmangle=s/v//,filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%ngx-mod-http-substitutions-filter-$1.tar.gz%" \ +opts="dversionmangle=s/v//,filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%libnginx-mod-http-subs-filter-$1.tar.gz%" \ https://github.com/yaoweibin/ngx_http_substitutions_filter_module/tags \ - (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian debian/modules/uupdate http-subs-filter ngx-mod-http-substitutions-filter + (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian debian/ngxmod uupdate http-subs-filter diff --git a/debian/modules/watch/http-uploadprogress b/debian/modules/watch/http-uploadprogress index 7c0b7cf..cccba98 100644 --- a/debian/modules/watch/http-uploadprogress +++ b/debian/modules/watch/http-uploadprogress @@ -1,4 +1,4 @@ version=4 -opts="dversionmangle=s/v//,filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%ngx-mod-upload-progress-$1.tar.gz%" \ +opts="dversionmangle=s/v//,filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%libnginx-mod-http-uploadprogress-$1.tar.gz%" \ https://github.com/masterzen/nginx-upload-progress-module/tags \ - (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian debian/modules/uupdate http-uploadprogress ngx-mod-upload-progress + (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian debian/ngxmod uupdate http-uploadprogress diff --git a/debian/modules/watch/nchan b/debian/modules/watch/nchan index 6b95884..199ab19 100644 --- a/debian/modules/watch/nchan +++ b/debian/modules/watch/nchan @@ -1,4 +1,4 @@ version=4 -opts="dversionmangle=s/v//,filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%ngx-mod-nchan-$1.tar.gz%" \ +opts="dversionmangle=s/v//,filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%libnginx-mod-nchan-$1.tar.gz%" \ https://github.com/slact/nchan/tags \ - (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian debian/modules/uupdate nchan ngx-mod-nchan + (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian debian/ngxmod uupdate nchan diff --git a/debian/modules/watch/rtmp b/debian/modules/watch/rtmp index f8137a2..2a95f4c 100644 --- a/debian/modules/watch/rtmp +++ b/debian/modules/watch/rtmp @@ -1,4 +1,4 @@ version=4 -opts="dversionmangle=s/v//,filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%ngx-mod-rtmp-$1.tar.gz%" \ +opts="dversionmangle=s/v//,filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%libnginx-mod-rtmp-$1.tar.gz%" \ https://github.com/arut/nginx-rtmp-module/tags \ - (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian debian/modules/uupdate rtmp ngx-mod-rtmp + (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian debian/ngxmod uupdate rtmp diff --git a/debian/ngxmod b/debian/ngxmod index f8180d1..7eacaa5 100755 --- a/debian/ngxmod +++ b/debian/ngxmod @@ -1,130 +1,156 @@ #!/usr/bin/env python -''' -ngxmod - nginx modules management helper script +""" +Handy Debian nginx module management helper +""" -Usage: - ngxmod - -Subcommands: - - uscan - scan/watch upstream nginx module sources for new releases - - It runs uscan for each nginx module listed in debian/modules/control. - - If a new version is available, it will ask you if you want to upgrade. - If you agree it will use uscan to download the tarball, place it in the nginx - source's parent directory and unpack it using modules/uupdate to upgrade - the module's source. - - After the upgrade, it will remove the files listed in the Files-Excluded - field and finally it will commit the changes. -''' - -import deb822 +import argparse import os -import sys import re +import shutil +import sys +import tarfile +import tempfile + from subprocess import call -MODULES_PATH = 'modules/' -MODULES_CTRL = os.path.join(MODULES_PATH, 'control') +import deb822 + +DEBIAN_PATH = os.path.dirname(os.path.realpath(__file__)) +MODULES_PATH = os.path.join(DEBIAN_PATH, 'modules') +CTRL_PATH = os.path.join(MODULES_PATH, 'control') +CTRL = [p for p in deb822.Deb822.iter_paragraphs(file(CTRL_PATH))] + + +def ctrl(name): + "Return deb822 paragraph for the selected module" + global CTRL + + for m in CTRL: + if m['Module'] == name: + return m + + +def update_ctrl(): + "Save current control to disk" + global CTRL + + new_ctrl = CTRL_PATH + '.new' + with open(new_ctrl, 'w') as c: + for m in CTRL: + c.write(m.dump() + '\n') + + os.rename(new_ctrl, CTRL_PATH) + def prompt(query): - ''' + """ Ask the given query and wait for an y/N answer. :query: The query :returns: The yes (True) or no (False) answer - ''' + """ sys.stdout.write('%s [y/N]: ' % query) choice = raw_input().lower() return choice == 'y' -def upgrade_module(mi, watchfile): - ''' - Upgrade the given module using uscan and the custom modules/uupdate. - After the upgrade, remove the Files-Excluded. - - :param mi: modules/control info for the module - :param watchfile: The watchfile of the module - :returns: The new module version - ''' - uscan_upgrade_cmd = [ - 'uscan', '--upstream-version', mi['Version'], - '--watchfile', 'debian/%s' % watchfile, '--no-symlink' - ] - upgrade_ret = call(uscan_upgrade_cmd, stdout=open(os.devnull, 'w')) - - if 'Files-Excluded' in mi and upgrade_ret == 0: - print 'Removing Files-Excluded: %s' % mi['Files-Excluded'] - - files = re.split('\s+', mi['Files-Excluded']) - files = filter(None, files) - abs_files = ['%s%s/%s' % (MODULES_PATH, mi['Module'], f) for f in files] - - rm_cmd = ['rm', '-r'] - rm_cmd.extend(abs_files) - - call(rm_cmd) - - return open('/tmp/ngx_uupdate_version_%s' % mi['Module']).read().rstrip() - - -def update_module_version(mi, new_ver): - ''' - Update the given module's version in modules/control. - - :param mi: modules/control info for the module - :param new_ver: The new module version - ''' - modules_info = deb822.Deb822.iter_paragraphs(file(MODULES_CTRL)) - modules_ctrl_new = '%s%s' % (MODULES_CTRL, '.new') - with open(modules_ctrl_new, 'w') as c: - for m in modules_info: - if mi['Module'] == m['Module']: - m['Version'] = re.sub('[^v]+', new_ver, m['Version']) - - c.write(m.dump() + '\n') - c.closed - os.rename(modules_ctrl_new, MODULES_CTRL) - - -def commit_module(mi, new_ver): - ''' +def commit(module, version): + """ Git-commit the given module's upgraded source. - :param mi: modules/control info for the module - :param new_ver: The new module version - ''' - module_name = mi['Module'] - module_path = os.path.join(MODULES_PATH, module_name) + :param module: module name + :param version: The updated module version + """ + module_path = os.path.join(MODULES_PATH, module) - git_add_cmd = ['git', 'add', module_path, MODULES_CTRL] + git_add_cmd = ['git', 'add', '--all', module_path, CTRL_PATH] call(git_add_cmd) - commit_msg = 'Update %s to v%s' % (module_name, new_ver) - git_commit_cmd = ['git', 'commit', '-m', commit_msg] + commit_msg = '%s: Upgrade to v%s' % (module, version) + git_commit_cmd = [ + 'git', 'commit', '-m', commit_msg, + '--', module_path, CTRL_PATH] call(git_commit_cmd) -def usage(): - print(""" -Usage: - ngxmod +def unpack(module, version, exclude): + "Unpack upstream tar file into module path" -Subcommands: + tar_gz = os.path.join( + "..", "libnginx-mod-%s-%s.tar.gz" % (module, version)) + if not os.path.exists(tar_gz): + print "%s doesn't exist!" % tar_gz + exit(1) - uscan - scan/watch upstream nginx module sources for new releases -""") + module_path = os.path.join(MODULES_PATH, module) + tmpdir = tempfile.mkdtemp(prefix="libnginx-mod-%s-%s." % (module, version)) + with tarfile.open(tar_gz) as tar: + members = tar.getmembers() + + # stip top-level directory from tar + topdir = members[0] + if not topdir or not topdir.isdir(): + print "No top directory found!" + exit(1) + + topdir = members[0].path + if any(topdir not in ti.path for ti in members): + print "Not all files are under the top directory '%s'" % topdir + exit(1) + + def remove_topdir_prefix(tarinfo): + "Strip top directory" + tarinfo.path = os.path.relpath(tarinfo.path, topdir) + return tarinfo + members = [remove_topdir_prefix(tarinfo) for tarinfo in members] + tar.extractall(path=tmpdir, members=members) + + shutil.rmtree(module_path) + shutil.move(tmpdir, module_path) + + for e in exclude: + print "Removing %s..." % e + abspath = os.path.join(module_path, e) + if os.path.isdir(abspath): + shutil.rmtree(abspath) + else: + os.remove(abspath) -def main(): - modules_info = deb822.Deb822.iter_paragraphs(file(MODULES_CTRL)) +def cmd_uupdate(args): + "Internal uupdate helper, upgrades & commits the given module" + c = ctrl(args.module) - for mi in modules_info: - sys.stdout.write('Uscanning %s...' % mi['Module']) + exclude = [] + if 'Files-Excluded' in c: + exclude = c['Files-Excluded'].split() + + unpack(args.module, args.upstream_version, exclude) + + # change ctrl version + c['Version'] = re.sub('[^v]+', args.upstream_version, c['Version']) + update_ctrl() + + commit(args.module, args.upstream_version) + + +def cmd_uscan(args): + """ + Run uscan for each nginx module listed in debian/modules/control. + + If a new version is found, it will be downloaded & unpacked to the proper + debian/modules/MODULE path. + + After the upgrade, all files listed in the Files-Excluded: control field + will be removed, debian/modules/control version will be updated and all + changes will be commited to git. + """ + global CTRL + + # For every module that has watchfile... + for mi in CTRL: + sys.stdout.write('Uscanning %s: ' % mi['Module']) sys.stdout.flush() watchfile = os.path.join(MODULES_PATH, 'watch', mi['Module']) @@ -133,24 +159,60 @@ def main(): print 'no watchfile available.' continue + # Check uscan_check_cmd = [ 'uscan', '--upstream-version', mi['Version'], '--watchfile', watchfile, '--package', mi['Module'] ] - check_ret = call(uscan_check_cmd) + if call(uscan_check_cmd) != 0: + print 'up-to-date' + continue - if check_ret == 0: - if prompt('Do you want to upgrade %s?' % mi['Module']): - new_module_ver = upgrade_module(mi, watchfile) - update_module_version(mi, new_module_ver) - commit_module(mi, new_module_ver) - else: - print 'up-to-date.' + # Ask + if not prompt('Do you want to upgrade %s?' % mi['Module']): + continue + + # Upgrade + uscan_upgrade_cmd = [ + 'uscan', '--upstream-version', mi['Version'], + '--watchfile', watchfile, '--no-symlink' + ] + if call(uscan_upgrade_cmd, stdout=open(os.devnull, 'w')) != 0: + print "Uscan for %s failed!" % mi['Module'] + exit(1) + + +def main(): + """ngxmod main""" + + parser = argparse.ArgumentParser( + description=__doc__) + cmds = parser.add_subparsers(title="Commands") + + import textwrap + uscan_cmd = cmds.add_parser( + "uscan", + help="scan/watch upstream nginx module sources for new releases", + description=textwrap.dedent(cmd_uscan.__doc__), + formatter_class=argparse.RawDescriptionHelpFormatter) + uscan_cmd.set_defaults(func=cmd_uscan) + + uupdate_cmd = cmds.add_parser( + "uupdate", + help=cmd_uupdate.__doc__, + description=cmd_uupdate.__doc__) + uupdate_cmd.add_argument("module", metavar="MODULE", help="Module name") + uupdate_cmd.add_argument( + "--upstream-version", + required=True, + metavar="VERSION", + help="Upstream version") + uupdate_cmd.set_defaults(func=cmd_uupdate) + + args = parser.parse_args() + args.func(args) if __name__ == '__main__': - if len(sys.argv) == 2 and sys.argv[1] == 'uscan': - main() - else: - usage() + main() From 33799993fc8fbe4d3aca32b6518cc3a01d4729b7 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Wed, 13 Dec 2017 11:22:21 +0200 Subject: [PATCH 231/600] http-headers-more-filter: Upgrade to 0.33 --- debian/modules/control | 2 +- .../http-headers-more-filter/README.markdown | 40 ++++-- .../src/ngx_http_headers_more_headers_in.c | 63 +++++---- .../http-headers-more-filter/t/builtin.t | 1 - .../http-headers-more-filter/t/input-conn.t | 1 - .../http-headers-more-filter/t/input-ua.t | 1 - .../http-headers-more-filter/t/input.t | 42 +++++- .../http-headers-more-filter/t/phase.t | 1 - .../http-headers-more-filter/t/sanity.t | 1 - .../http-headers-more-filter/t/subrequest.t | 1 - .../http-headers-more-filter/t/unused.t | 1 - .../modules/http-headers-more-filter/t/vars.t | 1 - .../valgrind.suppress | 126 ++++-------------- 13 files changed, 134 insertions(+), 147 deletions(-) diff --git a/debian/modules/control b/debian/modules/control index 5f67e38..71c63eb 100644 --- a/debian/modules/control +++ b/debian/modules/control @@ -1,6 +1,6 @@ Module: http-headers-more-filter Homepage: https://github.com/agentzh/headers-more-nginx-module -Version: v0.32 +Version: v0.33 Files-Excluded: .gitignore .gitattributes .travis.yml Module: http-ndk diff --git a/debian/modules/http-headers-more-filter/README.markdown b/debian/modules/http-headers-more-filter/README.markdown index d584461..452ef1f 100644 --- a/debian/modules/http-headers-more-filter/README.markdown +++ b/debian/modules/http-headers-more-filter/README.markdown @@ -36,7 +36,7 @@ Table of Contents Version ======= -This document describes headers-more-nginx-module [v0.32](https://github.com/openresty/headers-more-nginx-module/tags) released on 4 November 2016. +This document describes headers-more-nginx-module [v0.33](https://github.com/openresty/headers-more-nginx-module/tags) released on 3 November 2017. Synopsis ======== @@ -248,7 +248,8 @@ or See [more_set_headers](#more_set_headers) for more details. -Wildcard `*` can also be used to specify a header name pattern. For example, the following directive effectively clears *any* output headers starting by "`X-Hidden-`": +The wildcard character, `*`, can also be used at the end of the header name to specify a pattern. For example, the following directive +effectively clears *any* output headers starting by "`X-Hidden-`": ```nginx @@ -298,25 +299,40 @@ In fact, ```nginx - more_clear_input_headers -s 404 -t 'text/plain' Foo Baz; + more_clear_input_headers -t 'text/plain' Foo Baz; ``` is exactly equivalent to ```nginx - more_set_input_headers -s 404 -t 'text/plain' "Foo: " "Baz: "; + more_set_input_headers -t 'text/plain' "Foo: " "Baz: "; ``` or ```nginx - more_set_input_headers -s 404 -t 'text/plain' Foo Baz + more_set_input_headers -t 'text/plain' Foo Baz +``` + +To remove request headers "Foo" and "Baz" for all incoming requests regardless of the content type, we can write + +```nginx + + more_clear_input_headers "Foo" "Baz"; ``` See [more_set_input_headers](#more_set_input_headers) for more details. +The wildcard character, `*`, can also be used at the end of the header name to specify a pattern. For example, the following directive +effectively clears *any* input headers starting by "`X-Hidden-`": + +```nginx + + more_clear_input_headers 'X-Hidden-*'; +``` + [Back to TOC](#table-of-contents) Limitations @@ -331,13 +347,13 @@ Installation ============ Grab the nginx source code from [nginx.org](http://nginx.org/), for example, -the version 1.11.2 (see [nginx compatibility](#compatibility)), and then build the source with this module: +the version 1.13.6 (see [nginx compatibility](#compatibility)), and then build the source with this module: ```bash - wget 'http://nginx.org/download/nginx-1.11.2.tar.gz' - tar -xzvf nginx-1.11.2.tar.gz - cd nginx-1.11.2/ + wget 'http://nginx.org/download/nginx-1.13.6.tar.gz' + tar -xzvf nginx-1.13.6.tar.gz + cd nginx-1.13.6/ # Here we assume you would install you nginx under /opt/nginx/. ./configure --prefix=/opt/nginx \ @@ -366,6 +382,8 @@ Compatibility The following versions of Nginx should work with this module: +* **1.13.x** (last tested: 1.13.6) +* **1.12.x** * **1.11.x** (last tested: 1.11.2) * **1.10.x** * **1.9.x** (last tested: 1.9.15) @@ -479,7 +497,7 @@ You'll be very welcomed to submit patches to the [author](#author) or just ask f Authors ======= -* Yichun "agentzh" Zhang (章亦春) *<agentzh@gmail.com>*, CloudFlare Inc. +* Yichun "agentzh" Zhang (章亦春) *<agentzh@gmail.com>*, OpenResty Inc. * Bernd Dorn ( ) This wiki page is also maintained by the author himself, and everybody is encouraged to improve this page as well. @@ -491,7 +509,7 @@ Copyright & License The code base is borrowed directly from the standard [headers](http://nginx.org/en/docs/http/ngx_http_headers_module.html) module in Nginx 0.8.24. This part of code is copyrighted by Igor Sysoev. -Copyright (c) 2009-2014, Yichun "agentzh" Zhang (章亦春) , CloudFlare Inc. +Copyright (c) 2009-2017, Yichun "agentzh" Zhang (章亦春) , OpenResty Inc. Copyright (c) 2010-2013, Bernd Dorn. diff --git a/debian/modules/http-headers-more-filter/src/ngx_http_headers_more_headers_in.c b/debian/modules/http-headers-more-filter/src/ngx_http_headers_more_headers_in.c index bdea8de..c3eb8f7 100644 --- a/debian/modules/http-headers-more-filter/src/ngx_http_headers_more_headers_in.c +++ b/debian/modules/http-headers-more-filter/src/ngx_http_headers_more_headers_in.c @@ -243,42 +243,59 @@ retry: i = 0; } - if (h[i].key.len == hv->key.len + if (!hv->wildcard + && h[i].key.len == hv->key.len && ngx_strncasecmp(h[i].key.data, hv->key.data, h[i].key.len) == 0) { - if (value->len == 0 || (matched && matched != &h[i])) { - h[i].hash = 0; + goto matched; + } - rc = ngx_http_headers_more_rm_header_helper( - &r->headers_in.headers, part, i); + if (hv->wildcard + && value->len == 0 + && h[i].key.len >= hv->key.len - 1 + && ngx_strncasecmp(h[i].key.data, hv->key.data, + hv->key.len - 1) == 0) + { + goto matched; + } - ngx_http_headers_more_assert( - !(r->headers_in.headers.part.next == NULL - && r->headers_in.headers.last - != &r->headers_in.headers.part)); + /* not matched */ + continue; - if (rc == NGX_OK) { - if (output_header) { - *output_header = NULL; - } +matched: - goto retry; + if (value->len == 0 || (matched && matched != &h[i])) { + h[i].hash = 0; + + rc = ngx_http_headers_more_rm_header_helper( + &r->headers_in.headers, part, i); + + ngx_http_headers_more_assert( + !(r->headers_in.headers.part.next == NULL + && r->headers_in.headers.last + != &r->headers_in.headers.part)); + + if (rc == NGX_OK) { + if (output_header) { + *output_header = NULL; } - return NGX_ERROR; + goto retry; } - h[i].value = *value; + return NGX_ERROR; + } - if (output_header) { - *output_header = &h[i]; - dd("setting existing builtin input header"); - } + h[i].value = *value; - if (matched == NULL) { - matched = &h[i]; - } + if (output_header) { + *output_header = &h[i]; + dd("setting existing builtin input header"); + } + + if (matched == NULL) { + matched = &h[i]; } } diff --git a/debian/modules/http-headers-more-filter/t/builtin.t b/debian/modules/http-headers-more-filter/t/builtin.t index f2b5c34..27b20af 100644 --- a/debian/modules/http-headers-more-filter/t/builtin.t +++ b/debian/modules/http-headers-more-filter/t/builtin.t @@ -336,4 +336,3 @@ hello Vary: hello --- response_body hello - diff --git a/debian/modules/http-headers-more-filter/t/input-conn.t b/debian/modules/http-headers-more-filter/t/input-conn.t index a32d4e1..f53e80f 100644 --- a/debian/modules/http-headers-more-filter/t/input-conn.t +++ b/debian/modules/http-headers-more-filter/t/input-conn.t @@ -135,4 +135,3 @@ content: conn type: 0 connection: bad --- no_error_log [error] - diff --git a/debian/modules/http-headers-more-filter/t/input-ua.t b/debian/modules/http-headers-more-filter/t/input-ua.t index 56d2222..da9a60d 100644 --- a/debian/modules/http-headers-more-filter/t/input-ua.t +++ b/debian/modules/http-headers-more-filter/t/input-ua.t @@ -626,4 +626,3 @@ content: konqueror: 1 User-Agent: Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.10 (like Gecko) (Kubuntu) --- no_error_log [error] - diff --git a/debian/modules/http-headers-more-filter/t/input.t b/debian/modules/http-headers-more-filter/t/input.t index 0b8989f..01ae73f 100644 --- a/debian/modules/http-headers-more-filter/t/input.t +++ b/debian/modules/http-headers-more-filter/t/input.t @@ -5,7 +5,7 @@ use Test::Nginx::Socket; # 'no_plan'; repeat_each(2); -plan tests => repeat_each() * 124; +plan tests => repeat_each() * 128; no_long_string(); #no_diff; @@ -1289,3 +1289,43 @@ X-Forwarded-For: 8.8.8.8 Foo: 127.0.0.1 --- no_error_log [error] + + + +=== TEST 50: clear input headers with wildcard +--- config + location /hello { + more_clear_input_headers 'X-Hidden-*'; + content_by_lua ' + ngx.say("X-Hidden-One: ", ngx.var.http_x_hidden_one) + ngx.say("X-Hidden-Two: ", ngx.var.http_x_hidden_two) + '; + } +--- request + GET /hello +--- more_headers +X-Hidden-One: i am hidden +X-Hidden-Two: me 2 +--- response_body +X-Hidden-One: nil +X-Hidden-Two: nil + + + +=== TEST 51: make sure wildcard doesn't affect more_set_input_headers +--- config + location /hello { + more_set_input_headers 'X-Hidden-*: lol'; + content_by_lua ' + ngx.say("X-Hidden-One: ", ngx.var.http_x_hidden_one) + ngx.say("X-Hidden-Two: ", ngx.var.http_x_hidden_two) + '; + } +--- request + GET /hello +--- more_headers +X-Hidden-One: i am hidden +X-Hidden-Two: me 2 +--- response_body +X-Hidden-One: i am hidden +X-Hidden-Two: me 2 diff --git a/debian/modules/http-headers-more-filter/t/phase.t b/debian/modules/http-headers-more-filter/t/phase.t index 343d2e5..11183db 100644 --- a/debian/modules/http-headers-more-filter/t/phase.t +++ b/debian/modules/http-headers-more-filter/t/phase.t @@ -23,4 +23,3 @@ __DATA__ X-Foo: Blah --- response_body_like: 403 Forbidden --- error_code: 403 - diff --git a/debian/modules/http-headers-more-filter/t/sanity.t b/debian/modules/http-headers-more-filter/t/sanity.t index e316cac..d06f5dc 100644 --- a/debian/modules/http-headers-more-filter/t/sanity.t +++ b/debian/modules/http-headers-more-filter/t/sanity.t @@ -565,4 +565,3 @@ hi --- response_body ok --- http09 - diff --git a/debian/modules/http-headers-more-filter/t/subrequest.t b/debian/modules/http-headers-more-filter/t/subrequest.t index 34e84c9..9443eca 100644 --- a/debian/modules/http-headers-more-filter/t/subrequest.t +++ b/debian/modules/http-headers-more-filter/t/subrequest.t @@ -66,4 +66,3 @@ main: dog --- response_headers ! Host --- skip_nginx: 3: < 0.7.46 - diff --git a/debian/modules/http-headers-more-filter/t/unused.t b/debian/modules/http-headers-more-filter/t/unused.t index 1f35adc..c51f91c 100644 --- a/debian/modules/http-headers-more-filter/t/unused.t +++ b/debian/modules/http-headers-more-filter/t/unused.t @@ -172,4 +172,3 @@ bar headers more header handler [error] --- log_level: debug - diff --git a/debian/modules/http-headers-more-filter/t/vars.t b/debian/modules/http-headers-more-filter/t/vars.t index 426c68c..04c75c3 100644 --- a/debian/modules/http-headers-more-filter/t/vars.t +++ b/debian/modules/http-headers-more-filter/t/vars.t @@ -56,4 +56,3 @@ hi dog --- response_headers Host: - diff --git a/debian/modules/http-headers-more-filter/valgrind.suppress b/debian/modules/http-headers-more-filter/valgrind.suppress index bba7217..d51de70 100644 --- a/debian/modules/http-headers-more-filter/valgrind.suppress +++ b/debian/modules/http-headers-more-filter/valgrind.suppress @@ -1,40 +1,9 @@ -{ - -Memcheck:Cond -fun:lj_str_new -} { - Memcheck:Cond - fun:lj_str_new - fun:lua_pushlstring -} -{ - - Memcheck:Addr4 - fun:lj_str_new - fun:lua_pushlstring -} -{ - -Memcheck:Leak -fun:malloc -fun:ngx_alloc -obj:* -} -{ - -Memcheck:Leak -fun:malloc -fun:ngx_alloc -} -{ - -Memcheck:Leak -fun:malloc -fun:ngx_alloc -fun:ngx_palloc_large -fun:ngx_palloc + Memcheck:Leak + fun:malloc + fun:ngx_alloc + obj:* } { @@ -44,27 +13,6 @@ fun:ngx_palloc fun:ngx_calloc fun:ngx_event_process_init } -{ - -Memcheck:Addr4 -fun:lj_str_new -fun:lua_pushlstring -fun:ngx_http_lua_get_output_header -} -{ - - Memcheck:Addr4 - fun:lj_str_new - fun:lua_getfield - fun:ngx_http_lua_cache_load_code -} -{ - - Memcheck:Addr4 - fun:lj_str_new - fun:lua_setfield - fun:ngx_http_lua_cache_store_code -} { Memcheck:Leak @@ -72,34 +20,12 @@ fun:ngx_http_lua_get_output_header fun:ngx_alloc fun:ngx_event_process_init } -{ - - Memcheck:Leak - fun:malloc - fun:ngx_alloc - fun:(below main) -} { Memcheck:Param epoll_ctl(event) fun:epoll_ctl } -{ - - Memcheck:Leak - fun:malloc - fun:ngx_alloc - fun:ngx_create_pool -} -{ - - Memcheck:Leak - fun:malloc - fun:ngx_alloc - fun:ngx_malloc - fun:ngx_palloc_large -} { Memcheck:Cond @@ -108,22 +34,6 @@ fun:ngx_http_lua_get_output_header fun:ngx_log_error_core fun:ngx_http_charset_header_filter } -{ - - Memcheck:Leak - fun:malloc - fun:ngx_alloc - fun:ngx_malloc - fun:ngx_pnalloc -} -{ - - Memcheck:Leak - fun:malloc - fun:ngx_alloc - fun:ngx_malloc - fun:ngx_palloc -} { nginx-core-process-init Memcheck:Leak @@ -185,15 +95,6 @@ fun:ngx_http_lua_get_output_header fun:ngx_epoll_process_events fun:ngx_process_events_and_timers } -{ - - Memcheck:Leak - fun:memalign - fun:posix_memalign - fun:ngx_memalign - fun:ngx_palloc_block - fun:ngx_palloc -} { Memcheck:Addr8 @@ -213,3 +114,22 @@ fun:ngx_http_lua_get_output_header fun:do_preload fun:dl_main } +{ + + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + fun:ngx_alloc + fun:ngx_set_environment + fun:ngx_single_process_cycle +} +{ + + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + fun:ngx_alloc + fun:ngx_set_environment + fun:ngx_worker_process_init + fun:ngx_worker_process_cycle +} From 8acbe3fbc400848abfa345e8db5ffe1bebc9c0bb Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Wed, 13 Dec 2017 11:22:39 +0200 Subject: [PATCH 232/600] http-echo: Upgrade to 0.61 Drop build-nginx-1.11.11 patch now included upstream --- debian/modules/control | 3 +- debian/modules/http-echo/README.markdown | 24 +- .../http-echo/src/ngx_http_echo_module.c | 13 ++ .../http-echo/src/ngx_http_echo_module.h | 4 + .../src/ngx_http_echo_request_info.c | 62 +++++ .../src/ngx_http_echo_request_info.h | 3 + debian/modules/http-echo/valgrind.suppress | 10 + .../http-echo/build-nginx-1.11.11.patch | 212 ------------------ debian/modules/patches/http-echo/series | 1 - 9 files changed, 107 insertions(+), 225 deletions(-) delete mode 100644 debian/modules/patches/http-echo/build-nginx-1.11.11.patch delete mode 100644 debian/modules/patches/http-echo/series diff --git a/debian/modules/control b/debian/modules/control index 71c63eb..b779595 100644 --- a/debian/modules/control +++ b/debian/modules/control @@ -13,9 +13,8 @@ Version: v1.5.1 Module: http-echo Homepage: https://github.com/agentzh/echo-nginx-module -Version: v0.60 +Version: v0.61 Files-Excluded: .gitignore .gitattributes .travis.yml -Patch: build-nginx-1.11.11.patch Module: http-lua Homepage: https://github.com/openresty/lua-nginx-module diff --git a/debian/modules/http-echo/README.markdown b/debian/modules/http-echo/README.markdown index 9de2c0b..71ac080 100644 --- a/debian/modules/http-echo/README.markdown +++ b/debian/modules/http-echo/README.markdown @@ -68,7 +68,7 @@ This module is production ready. Version ======= -This document describes ngx_echo [v0.59](https://github.com/openresty/echo-nginx-module/tags) released on 15 May 2016. +This document describes ngx_echo [v0.61](https://github.com/openresty/echo-nginx-module/tags) released on 8 August 2017. Synopsis ======== @@ -284,9 +284,9 @@ People will also find it useful in real-world applications that need to This is a special dual-role module that can *lazily* serve as a content handler or register itself as an output filter only upon demand. By default, this module does not do anything at all. -Technially, this module has also demonstrated the following techniques that might be helpful for module writers: +Technically, this module has also demonstrated the following techniques that might be helpful for module writers: -1. Issue parallel subreqeusts directly from content handler. +1. Issue parallel subrequests directly from content handler. 1. Issue chained subrequests directly from content handler, by passing continuation along the subrequest chain. 1. Issue subrequests with all HTTP 1.1 methods and even an optional faked HTTP request body. 1. Interact with the Nginx event model directly from content handler using custom events and timers, and resume the content handler back if necessary. @@ -395,7 +395,7 @@ The output on the client side looks like this world ``` -Special characters like newlines (`\n`) and tabs (`\t`) can be escaped using C-style escaping sequences. But a notable exception is the dollar sign (`$`). As of Nginx 0.8.20, there's still no clean way to esacpe this characters. (A work-around might be to use a `$echo_dollor` variable that is always evaluated to the constant `$` character. This feature will possibly be introduced in a future version of this module.) +Special characters like newlines (`\n`) and tabs (`\t`) can be escaped using C-style escaping sequences. But a notable exception is the dollar sign (`$`). As of Nginx 0.8.20, there's still no clean way to escape this character. (A work-around might be to use a `$echo_dollor` variable that is always evaluated to the constant `$` character. This feature will possibly be introduced in a future version of this module.) As of the echo [v0.28](#v028) release, one can suppress the trailing newline character in the output by using the `-n` option, as in @@ -1493,6 +1493,8 @@ Accessing `/echoback` yields Behind the scene, it recovers `r->main->header_in` (or the large header buffers, if any) on the C level and does not construct the headers itself by traversing parsed results in the request object. +This varible is always evaluated to an empty value in HTTP/2 requests for now due to the current implementation. + This variable was first introduced in [version 0.15](#v015). [Back to TOC](#table-of-contents) @@ -1569,13 +1571,13 @@ You're recommended to install this module (as well as the Nginx core and many ot Alternatively, you can install this module manually with the Nginx source: Grab the nginx source code from [nginx.org](http://nginx.org/), for example, -the version 1.9.15 (see [nginx compatibility](#compatibility)), and then build the source with this module: +the version 1.11.2 (see [nginx compatibility](#compatibility)), and then build the source with this module: ```bash - $ wget 'http://nginx.org/download/nginx-1.9.15.tar.gz' - $ tar -xzvf nginx-1.9.15.tar.gz - $ cd nginx-1.9.15/ + $ wget 'http://nginx.org/download/nginx-1.11.2.tar.gz' + $ tar -xzvf nginx-1.11.2.tar.gz + $ cd nginx-1.11.2/ # Here we assume you would install you nginx under /opt/nginx/. $ ./configure --prefix=/opt/nginx \ @@ -1604,6 +1606,8 @@ Compatibility The following versions of Nginx should work with this module: +* **1.11.x** (last tested: 1.11.2) +* **1.10.x** * **1.9.x** (last tested: 1.9.15) * **1.8.x** * **1.7.x** (last tested: 1.7.10) @@ -1796,7 +1800,7 @@ You'll be very welcomed to submit patches to the [author](#author) or just ask f Author ====== -Yichun "agentzh" Zhang (章亦春) *<agentzh@gmail.com>*, CloudFlare Inc. +Yichun "agentzh" Zhang (章亦春) *<agentzh@gmail.com>*, OpenResty Inc. This wiki page is also maintained by the author himself, and everybody is encouraged to improve this page as well. @@ -1805,7 +1809,7 @@ This wiki page is also maintained by the author himself, and everybody is encour Copyright & License =================== -Copyright (c) 2009-2016, Yichun "agentzh" Zhang (章亦春) , CloudFlare Inc. +Copyright (c) 2009-2017, Yichun "agentzh" Zhang (章亦春) , OpenResty Inc. This module is licensed under the terms of the BSD license. diff --git a/debian/modules/http-echo/src/ngx_http_echo_module.c b/debian/modules/http-echo/src/ngx_http_echo_module.c index ae70479..8d736d7 100644 --- a/debian/modules/http-echo/src/ngx_http_echo_module.c +++ b/debian/modules/http-echo/src/ngx_http_echo_module.c @@ -632,6 +632,9 @@ ngx_http_echo_echo_exec(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) static void * ngx_http_echo_create_main_conf(ngx_conf_t *cf) { +#if nginx_version >= 1011011 + ngx_pool_cleanup_t *cln; +#endif ngx_http_echo_main_conf_t *emcf; emcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_echo_main_conf_t)); @@ -643,6 +646,16 @@ ngx_http_echo_create_main_conf(ngx_conf_t *cf) * hmcf->requires_filter = 0; */ +#if nginx_version >= 1011011 + cln = ngx_pool_cleanup_add(cf->pool, 0); + if (cln == NULL) { + return NULL; + } + + cln->data = emcf; + cln->handler = ngx_http_echo_request_headers_cleanup; +#endif + return emcf; } diff --git a/debian/modules/http-echo/src/ngx_http_echo_module.h b/debian/modules/http-echo/src/ngx_http_echo_module.h index 2d212c3..ce0a305 100644 --- a/debian/modules/http-echo/src/ngx_http_echo_module.h +++ b/debian/modules/http-echo/src/ngx_http_echo_module.h @@ -92,6 +92,10 @@ typedef struct { typedef struct { ngx_int_t requires_filter; +#if nginx_version >= 1011011 + ngx_buf_t **busy_buf_ptrs; + ngx_int_t busy_buf_ptr_count; +#endif } ngx_http_echo_main_conf_t; diff --git a/debian/modules/http-echo/src/ngx_http_echo_request_info.c b/debian/modules/http-echo/src/ngx_http_echo_request_info.c index d28ec4d..7dd3683 100644 --- a/debian/modules/http-echo/src/ngx_http_echo_request_info.c +++ b/debian/modules/http-echo/src/ngx_http_echo_request_info.c @@ -17,6 +17,9 @@ static void ngx_http_echo_post_read_request_body(ngx_http_request_t *r); +#if nginx_version >= 1011011 +void ngx_http_echo_request_headers_cleanup(void *data); +#endif ngx_int_t @@ -179,6 +182,11 @@ ngx_http_echo_client_request_headers_variable(ngx_http_request_t *r, ngx_int_t i, j; ngx_buf_t *b, *first = NULL; unsigned found; +#if nginx_version >= 1011011 + ngx_buf_t **bb; + ngx_chain_t *cl; + ngx_http_echo_main_conf_t *emcf; +#endif ngx_connection_t *c; ngx_http_request_t *mr; ngx_http_connection_t *hc; @@ -195,6 +203,10 @@ ngx_http_echo_client_request_headers_variable(ngx_http_request_t *r, } #endif +#if nginx_version >= 1011011 + emcf = ngx_http_get_module_main_conf(r, ngx_http_echo_module); +#endif + size = 0; b = c->buffer; @@ -215,8 +227,35 @@ ngx_http_echo_client_request_headers_variable(ngx_http_request_t *r, if (hc->nbusy) { b = NULL; + +#if nginx_version >= 1011011 + if (hc->nbusy > emcf->busy_buf_ptr_count) { + if (emcf->busy_buf_ptrs) { + ngx_free(emcf->busy_buf_ptrs); + } + + emcf->busy_buf_ptrs = ngx_alloc(hc->nbusy * sizeof(ngx_buf_t *), + r->connection->log); + + if (emcf->busy_buf_ptrs == NULL) { + return NGX_ERROR; + } + + emcf->busy_buf_ptr_count = hc->nbusy; + } + + bb = emcf->busy_buf_ptrs; + for (cl = hc->busy; cl; cl = cl->next) { + *bb++ = cl->buf; + } + + bb = emcf->busy_buf_ptrs; + for (i = hc->nbusy; i > 0; i--) { + b = bb[i - 1]; +#else for (i = 0; i < hc->nbusy; i++) { b = hc->busy[i]; +#endif if (first == NULL) { if (mr->request_line.data >= b->pos @@ -280,8 +319,15 @@ ngx_http_echo_client_request_headers_variable(ngx_http_request_t *r, } if (hc->nbusy) { + +#if nginx_version >= 1011011 + bb = emcf->busy_buf_ptrs; + for (i = hc->nbusy; i > 0; i--) { + b = bb[i - 1]; +#else for (i = 0; i < hc->nbusy; i++) { b = hc->busy[i]; +#endif if (!found) { if (b != first) { @@ -457,4 +503,20 @@ ngx_http_echo_response_status_variable(ngx_http_request_t *r, return NGX_OK; } + +#if nginx_version >= 1011011 +void +ngx_http_echo_request_headers_cleanup(void *data) +{ + ngx_http_echo_main_conf_t *emcf; + + emcf = (ngx_http_echo_main_conf_t *) data; + + if (emcf->busy_buf_ptrs) { + ngx_free(emcf->busy_buf_ptrs); + emcf->busy_buf_ptrs = NULL; + } +} +#endif + /* vi:set ft=c ts=4 sw=4 et fdm=marker: */ diff --git a/debian/modules/http-echo/src/ngx_http_echo_request_info.h b/debian/modules/http-echo/src/ngx_http_echo_request_info.h index 3b3713b..aa5730b 100644 --- a/debian/modules/http-echo/src/ngx_http_echo_request_info.h +++ b/debian/modules/http-echo/src/ngx_http_echo_request_info.h @@ -29,5 +29,8 @@ ngx_int_t ngx_http_echo_request_uri_variable(ngx_http_request_t *r, ngx_int_t ngx_http_echo_response_status_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); +#if nginx_version >= 1011011 +void ngx_http_echo_request_headers_cleanup(void *data); +#endif #endif /* ECHO_REQUEST_INFO_H */ diff --git a/debian/modules/http-echo/valgrind.suppress b/debian/modules/http-echo/valgrind.suppress index 0f8e871..d4bfe63 100644 --- a/debian/modules/http-echo/valgrind.suppress +++ b/debian/modules/http-echo/valgrind.suppress @@ -36,3 +36,13 @@ fun:do_preload fun:dl_main } +{ + + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + fun:ngx_alloc + fun:ngx_set_environment + fun:ngx_single_process_cycle + fun:main +} diff --git a/debian/modules/patches/http-echo/build-nginx-1.11.11.patch b/debian/modules/patches/http-echo/build-nginx-1.11.11.patch deleted file mode 100644 index dbb9ce7..0000000 --- a/debian/modules/patches/http-echo/build-nginx-1.11.11.patch +++ /dev/null @@ -1,212 +0,0 @@ -From 7740e11558b530b66b469c657576f5280b7cdb1b Mon Sep 17 00:00:00 2001 -From: Andrei Belov -Date: Wed, 22 Mar 2017 08:43:30 +0300 -Subject: [PATCH] feature: nginx 1.11.11+ can now build with this module. - -Note: nginx 1.11.11+ are still not an officially supported target yet. -More work needed. - -Closes openresty/echo-nginx-module#64 - -See also: -http://hg.nginx.org/nginx/rev/e662cbf1b932 - -Signed-off-by: Yichun Zhang (agentzh) ---- - src/ngx_http_echo_module.c | 13 +++++++++ - src/ngx_http_echo_module.h | 4 +++ - src/ngx_http_echo_request_info.c | 62 ++++++++++++++++++++++++++++++++++++++++ - src/ngx_http_echo_request_info.h | 3 ++ - valgrind.suppress | 10 +++++++ - 5 files changed, 92 insertions(+) - -diff --git a/src/ngx_http_echo_module.c b/src/ngx_http_echo_module.c -index ae70479..8d736d7 100644 ---- a/src/ngx_http_echo_module.c -+++ b/src/ngx_http_echo_module.c -@@ -632,6 +632,9 @@ ngx_http_echo_echo_exec(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) - static void * - ngx_http_echo_create_main_conf(ngx_conf_t *cf) - { -+#if nginx_version >= 1011011 -+ ngx_pool_cleanup_t *cln; -+#endif - ngx_http_echo_main_conf_t *emcf; - - emcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_echo_main_conf_t)); -@@ -643,6 +646,16 @@ ngx_http_echo_create_main_conf(ngx_conf_t *cf) - * hmcf->requires_filter = 0; - */ - -+#if nginx_version >= 1011011 -+ cln = ngx_pool_cleanup_add(cf->pool, 0); -+ if (cln == NULL) { -+ return NULL; -+ } -+ -+ cln->data = emcf; -+ cln->handler = ngx_http_echo_request_headers_cleanup; -+#endif -+ - return emcf; - } - -diff --git a/src/ngx_http_echo_module.h b/src/ngx_http_echo_module.h -index 2d212c3..ce0a305 100644 ---- a/src/ngx_http_echo_module.h -+++ b/src/ngx_http_echo_module.h -@@ -92,6 +92,10 @@ typedef struct { - - typedef struct { - ngx_int_t requires_filter; -+#if nginx_version >= 1011011 -+ ngx_buf_t **busy_buf_ptrs; -+ ngx_int_t busy_buf_ptr_count; -+#endif - } ngx_http_echo_main_conf_t; - - -diff --git a/src/ngx_http_echo_request_info.c b/src/ngx_http_echo_request_info.c -index d28ec4d..7dd3683 100644 ---- a/src/ngx_http_echo_request_info.c -+++ b/src/ngx_http_echo_request_info.c -@@ -17,6 +17,9 @@ - - - static void ngx_http_echo_post_read_request_body(ngx_http_request_t *r); -+#if nginx_version >= 1011011 -+void ngx_http_echo_request_headers_cleanup(void *data); -+#endif - - - ngx_int_t -@@ -179,6 +182,11 @@ ngx_http_echo_client_request_headers_variable(ngx_http_request_t *r, - ngx_int_t i, j; - ngx_buf_t *b, *first = NULL; - unsigned found; -+#if nginx_version >= 1011011 -+ ngx_buf_t **bb; -+ ngx_chain_t *cl; -+ ngx_http_echo_main_conf_t *emcf; -+#endif - ngx_connection_t *c; - ngx_http_request_t *mr; - ngx_http_connection_t *hc; -@@ -195,6 +203,10 @@ ngx_http_echo_client_request_headers_variable(ngx_http_request_t *r, - } - #endif - -+#if nginx_version >= 1011011 -+ emcf = ngx_http_get_module_main_conf(r, ngx_http_echo_module); -+#endif -+ - size = 0; - b = c->buffer; - -@@ -215,8 +227,35 @@ ngx_http_echo_client_request_headers_variable(ngx_http_request_t *r, - - if (hc->nbusy) { - b = NULL; -+ -+#if nginx_version >= 1011011 -+ if (hc->nbusy > emcf->busy_buf_ptr_count) { -+ if (emcf->busy_buf_ptrs) { -+ ngx_free(emcf->busy_buf_ptrs); -+ } -+ -+ emcf->busy_buf_ptrs = ngx_alloc(hc->nbusy * sizeof(ngx_buf_t *), -+ r->connection->log); -+ -+ if (emcf->busy_buf_ptrs == NULL) { -+ return NGX_ERROR; -+ } -+ -+ emcf->busy_buf_ptr_count = hc->nbusy; -+ } -+ -+ bb = emcf->busy_buf_ptrs; -+ for (cl = hc->busy; cl; cl = cl->next) { -+ *bb++ = cl->buf; -+ } -+ -+ bb = emcf->busy_buf_ptrs; -+ for (i = hc->nbusy; i > 0; i--) { -+ b = bb[i - 1]; -+#else - for (i = 0; i < hc->nbusy; i++) { - b = hc->busy[i]; -+#endif - - if (first == NULL) { - if (mr->request_line.data >= b->pos -@@ -280,8 +319,15 @@ ngx_http_echo_client_request_headers_variable(ngx_http_request_t *r, - } - - if (hc->nbusy) { -+ -+#if nginx_version >= 1011011 -+ bb = emcf->busy_buf_ptrs; -+ for (i = hc->nbusy; i > 0; i--) { -+ b = bb[i - 1]; -+#else - for (i = 0; i < hc->nbusy; i++) { - b = hc->busy[i]; -+#endif - - if (!found) { - if (b != first) { -@@ -457,4 +503,20 @@ ngx_http_echo_response_status_variable(ngx_http_request_t *r, - return NGX_OK; - } - -+ -+#if nginx_version >= 1011011 -+void -+ngx_http_echo_request_headers_cleanup(void *data) -+{ -+ ngx_http_echo_main_conf_t *emcf; -+ -+ emcf = (ngx_http_echo_main_conf_t *) data; -+ -+ if (emcf->busy_buf_ptrs) { -+ ngx_free(emcf->busy_buf_ptrs); -+ emcf->busy_buf_ptrs = NULL; -+ } -+} -+#endif -+ - /* vi:set ft=c ts=4 sw=4 et fdm=marker: */ -diff --git a/src/ngx_http_echo_request_info.h b/src/ngx_http_echo_request_info.h -index 3b3713b..aa5730b 100644 ---- a/src/ngx_http_echo_request_info.h -+++ b/src/ngx_http_echo_request_info.h -@@ -29,5 +29,8 @@ ngx_int_t ngx_http_echo_request_uri_variable(ngx_http_request_t *r, - ngx_int_t ngx_http_echo_response_status_variable(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data); - -+#if nginx_version >= 1011011 -+void ngx_http_echo_request_headers_cleanup(void *data); -+#endif - - #endif /* ECHO_REQUEST_INFO_H */ -diff --git a/valgrind.suppress b/valgrind.suppress -index 0f8e871..d4bfe63 100644 ---- a/valgrind.suppress -+++ b/valgrind.suppress -@@ -36,3 +36,13 @@ - fun:do_preload - fun:dl_main - } -+{ -+ -+ Memcheck:Leak -+ match-leak-kinds: definite -+ fun:malloc -+ fun:ngx_alloc -+ fun:ngx_set_environment -+ fun:ngx_single_process_cycle -+ fun:main -+} --- -2.11.0 - diff --git a/debian/modules/patches/http-echo/series b/debian/modules/patches/http-echo/series deleted file mode 100644 index 7e5c302..0000000 --- a/debian/modules/patches/http-echo/series +++ /dev/null @@ -1 +0,0 @@ -build-nginx-1.11.11.patch From 5fb0700fb278a7a8217233755c6e688ffc8e5e94 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Wed, 13 Dec 2017 11:22:50 +0200 Subject: [PATCH 233/600] http-lua: Upgrade to 0.10.11 Rebase openssl-1.1.0 patch --- debian/modules/control | 2 +- debian/modules/http-lua/README.markdown | 182 +++++++++++++++++- .../modules/http-lua/doc/HttpLuaModule.wiki | 162 +++++++++++++++- .../http-lua/src/api/ngx_http_lua_api.h | 2 +- .../http-lua/src/ngx_http_lua_accessby.c | 10 +- .../http-lua/src/ngx_http_lua_directive.c | 2 +- .../http-lua/src/ngx_http_lua_output.c | 7 +- .../http-lua/src/ngx_http_lua_req_body.c | 6 +- .../http-lua/src/ngx_http_lua_rewriteby.c | 10 +- .../http-lua/src/ngx_http_lua_semaphore.c | 6 +- .../http-lua/src/ngx_http_lua_shdict.c | 167 ++++++++++++++++ .../modules/http-lua/src/ngx_http_lua_sleep.c | 6 +- .../http-lua/src/ngx_http_lua_socket_tcp.c | 25 ++- .../http-lua/src/ngx_http_lua_socket_udp.c | 6 +- .../http-lua/src/ngx_http_lua_ssl_certby.c | 5 +- .../src/ngx_http_lua_ssl_session_fetchby.c | 5 +- .../src/ngx_http_lua_ssl_session_storeby.c | 3 +- .../http-lua/src/ngx_http_lua_subrequest.c | 6 +- .../modules/http-lua/src/ngx_http_lua_util.c | 10 +- .../modules/http-lua/src/ngx_http_lua_util.h | 2 +- debian/modules/http-lua/t/000--init.t | 73 ++++--- debian/modules/http-lua/t/002-content.t | 8 +- debian/modules/http-lua/t/004-require.t | 1 + debian/modules/http-lua/t/017-exec.t | 24 ++- debian/modules/http-lua/t/023-rewrite/exec.t | 24 ++- .../t/023-rewrite/tcp-socket-timeout.t | 44 ++--- debian/modules/http-lua/t/024-access/exec.t | 24 ++- debian/modules/http-lua/t/035-gmatch.t | 1 + debian/modules/http-lua/t/058-tcp-socket.t | 39 +++- .../http-lua/t/065-tcp-socket-timeout.t | 68 ++++--- .../modules/http-lua/t/097-uthread-rewrite.t | 1 + debian/modules/http-lua/t/106-timer.t | 6 +- debian/modules/http-lua/t/129-ssl-socket.t | 6 +- debian/modules/http-lua/t/139-ssl-cert-by.t | 8 +- .../http-lua/t/142-ssl-session-store.t | 7 +- .../http-lua/t/143-ssl-session-fetch.t | 19 +- .../http-lua/t/147-tcp-socket-timeouts.t | 93 +++++++++ debian/modules/http-lua/t/154-semaphore.t | 2 + debian/modules/http-lua/util/build.sh | 4 + debian/modules/http-lua/valgrind.suppress | 68 +++++-- .../patches/http-lua/openssl-1.1.0.patch | 86 ++++----- 41 files changed, 1007 insertions(+), 223 deletions(-) diff --git a/debian/modules/control b/debian/modules/control index b779595..bd7cc0a 100644 --- a/debian/modules/control +++ b/debian/modules/control @@ -18,7 +18,7 @@ Files-Excluded: .gitignore .gitattributes .travis.yml Module: http-lua Homepage: https://github.com/openresty/lua-nginx-module -Version: v0.10.10 +Version: v0.10.11 Patch: openssl-1.1.0.patch discover-luajit-2.1.patch diff --git a/debian/modules/http-lua/README.markdown b/debian/modules/http-lua/README.markdown index fac3a0d..c42bd3e 100644 --- a/debian/modules/http-lua/README.markdown +++ b/debian/modules/http-lua/README.markdown @@ -62,7 +62,7 @@ Production ready. Version ======= -This document describes ngx_lua [v0.10.10](https://github.com/openresty/lua-nginx-module/tags) released on 8 August 2017. +This document describes ngx_lua [v0.10.11](https://github.com/openresty/lua-nginx-module/tags) released on 3 November 2017. Synopsis ======== @@ -249,6 +249,7 @@ Nginx Compatibility The latest version of this module is compatible with the following versions of Nginx: +* 1.13.x (last tested: 1.13.6) * 1.11.x (last tested: 1.11.2) * 1.10.x * 1.9.x (last tested: 1.9.15) @@ -276,9 +277,9 @@ Build the source with this module: ```bash - wget 'http://nginx.org/download/nginx-1.11.2.tar.gz' - tar -xzvf nginx-1.11.2.tar.gz - cd nginx-1.11.2/ + wget 'http://nginx.org/download/nginx-1.13.6.tar.gz' + tar -xzvf nginx-1.13.6.tar.gz + cd nginx-1.13.6/ # tell nginx's build system where to find LuaJIT 2.0: export LUAJIT_LIB=/path/to/luajit/lib @@ -871,6 +872,7 @@ Nginx may terminate a request early with (at least): * 400 (Bad Request) * 405 (Not Allowed) * 408 (Request Timeout) +* 413 (Request Entity Too Large) * 414 (Request URI Too Large) * 494 (Request Headers Too Large) * 499 (Client Closed Request) @@ -1335,16 +1337,19 @@ Runs the Lua code specified by the argument `` on the global Lua When Nginx receives the `HUP` signal and starts reloading the config file, the Lua VM will also be re-created and `init_by_lua` will run again on the new Lua VM. In case that the [lua_code_cache](#lua_code_cache) directive is turned off (default on), the `init_by_lua` handler will run upon every request because in this special mode a standalone Lua VM is always created for each request. -Usually you can register (true) Lua global variables or pre-load Lua modules at server start-up by means of this hook. Here is an example for pre-loading Lua modules: +Usually you can pre-load Lua modules at server start-up by means of this hook and take advantage of modern operating systems' copy-on-write (COW) optimization. Here is an example for pre-loading Lua modules: ```nginx - init_by_lua 'cjson = require "cjson"'; + # this runs before forking out nginx worker processes: + init_by_lua_block { require "cjson" } server { location = /api { content_by_lua_block { - ngx.say(cjson.encode({dog = 5, cat = 6})) + -- the following require() will just return + -- the alrady loaded module from package.loaded: + ngx.say(require "cjson".encode{dog = 5, cat = 6}) } } } @@ -1356,10 +1361,10 @@ You can also initialize the [lua_shared_dict](#lua_shared_dict) shm storage at t lua_shared_dict dogs 1m; - init_by_lua ' + init_by_lua_block { local dogs = ngx.shared.dogs; dogs:set("Tom", 56) - '; + } server { location = /api { @@ -2691,7 +2696,7 @@ ssl_session_store_by_lua_file **context:** *http* -**phase:** *right-before-SSL-handshake* +**phase:** *right-after-SSL-handshake* Equivalent to [ssl_session_store_by_lua_block](#ssl_session_store_by_lua_block), except that the file specified by `` contains the Lua code, or rather, the [Lua/LuaJIT bytecode](#lualuajit-bytecode-support) to be executed. @@ -3188,9 +3193,13 @@ Nginx API for Lua * [ngx.shared.DICT.lpop](#ngxshareddictlpop) * [ngx.shared.DICT.rpop](#ngxshareddictrpop) * [ngx.shared.DICT.llen](#ngxshareddictllen) +* [ngx.shared.DICT.ttl](#ngxshareddictttl) +* [ngx.shared.DICT.expire](#ngxshareddictexpire) * [ngx.shared.DICT.flush_all](#ngxshareddictflush_all) * [ngx.shared.DICT.flush_expired](#ngxshareddictflush_expired) * [ngx.shared.DICT.get_keys](#ngxshareddictget_keys) +* [ngx.shared.DICT.capacity](#ngxshareddictcapacity) +* [ngx.shared.DICT.free_space](#ngxshareddictfree_space) * [ngx.socket.udp](#ngxsocketudp) * [udpsock:setpeername](#udpsocksetpeername) * [udpsock:send](#udpsocksend) @@ -6195,9 +6204,13 @@ The resulting object `dict` has the following methods: * [lpop](#ngxshareddictlpop) * [rpop](#ngxshareddictrpop) * [llen](#ngxshareddictllen) +* [ttl](#ngxshareddictttl) +* [expire](#ngxshareddictexpire) * [flush_all](#ngxshareddictflush_all) * [flush_expired](#ngxshareddictflush_expired) * [get_keys](#ngxshareddictget_keys) +* [capacity](#ngxshareddictcapacity) +* [free_space](#ngxshareddictfree_space) All these methods are *atomic* operations, that is, safe from concurrent accesses from multiple nginx worker processes for the same `lua_shared_dict` zone. @@ -6540,6 +6553,82 @@ See also [ngx.shared.DICT](#ngxshareddict). [Back to TOC](#nginx-api-for-lua) +ngx.shared.DICT.ttl +------------------- +**syntax:** *ttl, err = ngx.shared.DICT:ttl(key)* + +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** + +**requires:** `resty.core.shdict` or `resty.core` + +Retrieves the remaining TTL (time-to-live in seconds) of a key-value pair in the shm-based dictionary [ngx.shared.DICT](#ngxshareddict). Returns the TTL as a number if the operation is successfully completed or `nil` and an error message otherwise. + +If the key does not exist (or has already expired), this method will return `nil` and the error string `"not found"`. + +The TTL is originally determined by the `exptime` argument of the [set](#ngxshareddictset), [add](#ngxshareddictadd), [replace](#ngxshareddictreplace) (and the likes) methods. It has a time resolution of `0.001` seconds. A value of `0` means that the item will never expire. + +Example: + +```lua + + require "resty.core" + + local cats = ngx.shared.cats + local succ, err = cats:set("Marry", "a nice cat", 0.5) + + ngx.sleep(0.2) + + local ttl, err = cats:ttl("Marry") + ngx.say(ttl) -- 0.3 +``` + +This feature was first introduced in the `v0.10.11` release. + +**Note:** This method requires the `resty.core.shdict` or `resty.core` modules from the [lua-resty-core](https://github.com/openresty/lua-resty-core) library. + +See also [ngx.shared.DICT](#ngxshareddict). + +[Back to TOC](#nginx-api-for-lua) + +ngx.shared.DICT.expire +---------------------- +**syntax:** *success, err = ngx.shared.DICT:expire(key, exptime)* + +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** + +**requires:** `resty.core.shdict` or `resty.core` + +Updates the `exptime` (in second) of a key-value pair in the shm-based dictionary [ngx.shared.DICT](#ngxshareddict). Returns a boolean indicating success if the operation completes or `nil` and an error message otherwise. + +If the key does not exist, this method will return `nil` and the error string `"not found"`. + +The `exptime` argument has a resolution of `0.001` seconds. If `exptime` is `0`, then the item will never expire. + +Example: + +```lua + + require "resty.core" + + local cats = ngx.shared.cats + local succ, err = cats:set("Marry", "a nice cat", 0.1) + + succ, err = cats:expire("Marry", 0.5) + + ngx.sleep(0.2) + + local val, err = cats:get("Marry") + ngx.say(val) -- "a nice cat" +``` + +This feature was first introduced in the `v0.10.11` release. + +**Note:** This method requires the `resty.core.shdict` or `resty.core` modules from the [lua-resty-core](https://github.com/openresty/lua-resty-core) library. + +See also [ngx.shared.DICT](#ngxshareddict). + +[Back to TOC](#nginx-api-for-lua) + ngx.shared.DICT.flush_all ------------------------- **syntax:** *ngx.shared.DICT:flush_all()* @@ -6586,6 +6675,79 @@ This feature was first introduced in the `v0.7.3` release. [Back to TOC](#nginx-api-for-lua) +ngx.shared.DICT.capacity +------------------------ +**syntax:** *capacity_bytes = ngx.shared.DICT:capacity()* + +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** + +**requires:** `resty.core.shdict` or `resty.core` + +Retrieves the capacity in bytes for the shm-based dictionary [ngx.shared.DICT](#ngxshareddict) declared with +the [lua_shared_dict](#lua_shared_dict) directive. + +Example: + +```lua + + require "resty.core.shdict" + + local cats = ngx.shared.cats + local capacity_bytes = cats:capacity() +``` + +This feature was first introduced in the `v0.10.11` release. + +**Note:** This method requires the `resty.core.shdict` or `resty.core` modules from the [lua-resty-core](https://github.com/openresty/lua-resty-core) library. + +This feature requires at least nginx core version `0.7.3`. + +See also [ngx.shared.DICT](#ngxshareddict). + +[Back to TOC](#nginx-api-for-lua) + +ngx.shared.DICT.free_space +-------------------------- +**syntax:** *free_page_bytes = ngx.shared.DICT:free_space()* + +**context:** *init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua** + +**requires:** `resty.core.shdict` or `resty.core` + +Retrieves the free page size in bytes for the shm-based dictionary [ngx.shared.DICT](#ngxshareddict). + +**Note:** The memory for ngx.shared.DICT is allocated via the nginx slab allocator which has each slot for +data size ranges like \~8, 9\~16, 17\~32, ..., 1025\~2048, 2048\~ bytes. And pages are assigned to a slot if there +is no room in already assigned pages for the slot. + +So even if the return value of the `free_space` method is zero, there may be room in already assigned pages, so +you may successfully set a new key value pair to the shared dict without getting `true` for `forcible` or +non nil `err` from the `ngx.shared.DICT.set`. + +On the other hand, if already assigned pages for a slot are full and a new key value pair is added to the +slot and there is no free page, you may get `true` for `forcible` or non nil `err` from the +`ngx.shared.DICT.set` method. + +Example: + +```lua + + require "resty.core.shdict" + + local cats = ngx.shared.cats + local free_page_bytes = cats:free_space() +``` + +This feature was first introduced in the `v0.10.11` release. + +**Note:** This method requires the `resty.core.shdict` or `resty.core` modules from the [lua-resty-core](https://github.com/openresty/lua-resty-core) library. + +This feature requires at least nginx core version `1.11.7`. + +See also [ngx.shared.DICT](#ngxshareddict). + +[Back to TOC](#nginx-api-for-lua) + ngx.socket.udp -------------- **syntax:** *udpsock = ngx.socket.udp()* diff --git a/debian/modules/http-lua/doc/HttpLuaModule.wiki b/debian/modules/http-lua/doc/HttpLuaModule.wiki index 8393056..2424d39 100644 --- a/debian/modules/http-lua/doc/HttpLuaModule.wiki +++ b/debian/modules/http-lua/doc/HttpLuaModule.wiki @@ -10,7 +10,7 @@ Production ready. = Version = -This document describes ngx_lua [https://github.com/openresty/lua-nginx-module/tags v0.10.10] released on 8 August 2017. +This document describes ngx_lua [https://github.com/openresty/lua-nginx-module/tags v0.10.11] released on 3 November 2017. = Synopsis = @@ -186,6 +186,7 @@ The Lua state (Lua VM instance) is shared across all the requests handled by a s The latest version of this module is compatible with the following versions of Nginx: +* 1.13.x (last tested: 1.13.6) * 1.11.x (last tested: 1.11.2) * 1.10.x * 1.9.x (last tested: 1.9.15) @@ -209,9 +210,9 @@ Alternatively, ngx_lua can be manually compiled into Nginx: Build the source with this module: - wget 'http://nginx.org/download/nginx-1.11.2.tar.gz' - tar -xzvf nginx-1.11.2.tar.gz - cd nginx-1.11.2/ + wget 'http://nginx.org/download/nginx-1.13.6.tar.gz' + tar -xzvf nginx-1.13.6.tar.gz + cd nginx-1.13.6/ # tell nginx's build system where to find LuaJIT 2.0: export LUAJIT_LIB=/path/to/luajit/lib @@ -706,6 +707,7 @@ Nginx may terminate a request early with (at least): * 400 (Bad Request) * 405 (Not Allowed) * 408 (Request Timeout) +* 413 (Request Entity Too Large) * 414 (Request URI Too Large) * 494 (Request Headers Too Large) * 499 (Client Closed Request) @@ -1057,15 +1059,18 @@ Runs the Lua code specified by the argument on the When Nginx receives the HUP signal and starts reloading the config file, the Lua VM will also be re-created and init_by_lua will run again on the new Lua VM. In case that the [[#lua_code_cache|lua_code_cache]] directive is turned off (default on), the init_by_lua handler will run upon every request because in this special mode a standalone Lua VM is always created for each request. -Usually you can register (true) Lua global variables or pre-load Lua modules at server start-up by means of this hook. Here is an example for pre-loading Lua modules: +Usually you can pre-load Lua modules at server start-up by means of this hook and take advantage of modern operating systems' copy-on-write (COW) optimization. Here is an example for pre-loading Lua modules: - init_by_lua 'cjson = require "cjson"'; + # this runs before forking out nginx worker processes: + init_by_lua_block { require "cjson" } server { location = /api { content_by_lua_block { - ngx.say(cjson.encode({dog = 5, cat = 6})) + -- the following require() will just return + -- the alrady loaded module from package.loaded: + ngx.say(require "cjson".encode{dog = 5, cat = 6}) } } } @@ -1076,10 +1081,10 @@ You can also initialize the [[#lua_shared_dict|lua_shared_dict]] shm storage at lua_shared_dict dogs 1m; - init_by_lua ' + init_by_lua_block { local dogs = ngx.shared.dogs; dogs:set("Tom", 56) - '; + } server { location = /api { @@ -2276,7 +2281,7 @@ Note that: this directive is only allowed to used in '''http context''' from the '''context:''' ''http'' -'''phase:''' ''right-before-SSL-handshake'' +'''phase:''' ''right-after-SSL-handshake'' Equivalent to [[#ssl_session_store_by_lua_block|ssl_session_store_by_lua_block]], except that the file specified by contains the Lua code, or rather, the [[#Lua/LuaJIT bytecode support|Lua/LuaJIT bytecode]] to be executed. @@ -5193,9 +5198,13 @@ The resulting object dict has the following methods: * [[#ngx.shared.DICT.lpop|lpop]] * [[#ngx.shared.DICT.rpop|rpop]] * [[#ngx.shared.DICT.llen|llen]] +* [[#ngx.shared.DICT.ttl|ttl]] +* [[#ngx.shared.DICT.expire|expire]] * [[#ngx.shared.DICT.flush_all|flush_all]] * [[#ngx.shared.DICT.flush_expired|flush_expired]] * [[#ngx.shared.DICT.get_keys|get_keys]] +* [[#ngx.shared.DICT.capacity|capacity]] +* [[#ngx.shared.DICT.free_space|free_space]] All these methods are ''atomic'' operations, that is, safe from concurrent accesses from multiple nginx worker processes for the same lua_shared_dict zone. @@ -5488,6 +5497,74 @@ This feature was first introduced in the v0.10.6 release. See also [[#ngx.shared.DICT|ngx.shared.DICT]]. +== ngx.shared.DICT.ttl == +'''syntax:''' ''ttl, err = ngx.shared.DICT:ttl(key)'' + +'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' + +'''requires:''' resty.core.shdict or resty.core + +Retrieves the remaining TTL (time-to-live in seconds) of a key-value pair in the shm-based dictionary [[#ngx.shared.DICT|ngx.shared.DICT]]. Returns the TTL as a number if the operation is successfully completed or nil and an error message otherwise. + +If the key does not exist (or has already expired), this method will return nil and the error string "not found". + +The TTL is originally determined by the exptime argument of the [[#ngx.shared.DICT.set|set]], [[#ngx.shared.DICT.add|add]], [[#ngx.shared.DICT.replace|replace]] (and the likes) methods. It has a time resolution of 0.001 seconds. A value of 0 means that the item will never expire. + +Example: + + + require "resty.core" + + local cats = ngx.shared.cats + local succ, err = cats:set("Marry", "a nice cat", 0.5) + + ngx.sleep(0.2) + + local ttl, err = cats:ttl("Marry") + ngx.say(ttl) -- 0.3 + + +This feature was first introduced in the v0.10.11 release. + +'''Note:''' This method requires the resty.core.shdict or resty.core modules from the [https://github.com/openresty/lua-resty-core lua-resty-core] library. + +See also [[#ngx.shared.DICT|ngx.shared.DICT]]. + +== ngx.shared.DICT.expire == +'''syntax:''' ''success, err = ngx.shared.DICT:expire(key, exptime)'' + +'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' + +'''requires:''' resty.core.shdict or resty.core + +Updates the exptime (in second) of a key-value pair in the shm-based dictionary [[#ngx.shared.DICT|ngx.shared.DICT]]. Returns a boolean indicating success if the operation completes or nil and an error message otherwise. + +If the key does not exist, this method will return nil and the error string "not found". + +The exptime argument has a resolution of 0.001 seconds. If exptime is 0, then the item will never expire. + +Example: + + + require "resty.core" + + local cats = ngx.shared.cats + local succ, err = cats:set("Marry", "a nice cat", 0.1) + + succ, err = cats:expire("Marry", 0.5) + + ngx.sleep(0.2) + + local val, err = cats:get("Marry") + ngx.say(val) -- "a nice cat" + + +This feature was first introduced in the v0.10.11 release. + +'''Note:''' This method requires the resty.core.shdict or resty.core modules from the [https://github.com/openresty/lua-resty-core lua-resty-core] library. + +See also [[#ngx.shared.DICT|ngx.shared.DICT]]. + == ngx.shared.DICT.flush_all == '''syntax:''' ''ngx.shared.DICT:flush_all()'' @@ -5525,6 +5602,71 @@ By default, only the first 1024 keys (if any) are returned. When the v0.7.3 release. +== ngx.shared.DICT.capacity == +'''syntax:''' ''capacity_bytes = ngx.shared.DICT:capacity()'' + +'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' + +'''requires:''' resty.core.shdict or resty.core + +Retrieves the capacity in bytes for the shm-based dictionary [[#ngx.shared.DICT|ngx.shared.DICT]] declared with +the [[#lua_shared_dict|lua_shared_dict]] directive. + +Example: + + + require "resty.core.shdict" + + local cats = ngx.shared.cats + local capacity_bytes = cats:capacity() + + +This feature was first introduced in the v0.10.11 release. + +'''Note:''' This method requires the resty.core.shdict or resty.core modules from the [https://github.com/openresty/lua-resty-core lua-resty-core] library. + +This feature requires at least nginx core version 0.7.3. + +See also [[#ngx.shared.DICT|ngx.shared.DICT]]. + +== ngx.shared.DICT.free_space == +'''syntax:''' ''free_page_bytes = ngx.shared.DICT:free_space()'' + +'''context:''' ''init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*'' + +'''requires:''' resty.core.shdict or resty.core + +Retrieves the free page size in bytes for the shm-based dictionary [[#ngx.shared.DICT|ngx.shared.DICT]]. + +'''Note:''' The memory for ngx.shared.DICT is allocated via the nginx slab allocator which has each slot for +data size ranges like \~8, 9\~16, 17\~32, ..., 1025\~2048, 2048\~ bytes. And pages are assigned to a slot if there +is no room in already assigned pages for the slot. + +So even if the return value of the free_space method is zero, there may be room in already assigned pages, so +you may successfully set a new key value pair to the shared dict without getting true for forcible or +non nil err from the ngx.shared.DICT.set. + +On the other hand, if already assigned pages for a slot are full and a new key value pair is added to the +slot and there is no free page, you may get true for forcible or non nil err from the +ngx.shared.DICT.set method. + +Example: + + + require "resty.core.shdict" + + local cats = ngx.shared.cats + local free_page_bytes = cats:free_space() + + +This feature was first introduced in the v0.10.11 release. + +'''Note:''' This method requires the resty.core.shdict or resty.core modules from the [https://github.com/openresty/lua-resty-core lua-resty-core] library. + +This feature requires at least nginx core version 1.11.7. + +See also [[#ngx.shared.DICT|ngx.shared.DICT]]. + == ngx.socket.udp == '''syntax:''' ''udpsock = ngx.socket.udp()'' diff --git a/debian/modules/http-lua/src/api/ngx_http_lua_api.h b/debian/modules/http-lua/src/api/ngx_http_lua_api.h index cd64fc8..1e07b71 100644 --- a/debian/modules/http-lua/src/api/ngx_http_lua_api.h +++ b/debian/modules/http-lua/src/api/ngx_http_lua_api.h @@ -19,7 +19,7 @@ /* Public API for other Nginx modules */ -#define ngx_http_lua_version 10010 +#define ngx_http_lua_version 10011 typedef struct { diff --git a/debian/modules/http-lua/src/ngx_http_lua_accessby.c b/debian/modules/http-lua/src/ngx_http_lua_accessby.c index 1a4ba6d..56bf0fa 100644 --- a/debian/modules/http-lua/src/ngx_http_lua_accessby.c +++ b/debian/modules/http-lua/src/ngx_http_lua_accessby.c @@ -238,6 +238,7 @@ ngx_http_lua_access_by_chunk(lua_State *L, ngx_http_request_t *r) { int co_ref; ngx_int_t rc; + ngx_uint_t nreqs; lua_State *co; ngx_event_t *rev; ngx_connection_t *c; @@ -329,6 +330,9 @@ ngx_http_lua_access_by_chunk(lua_State *L, ngx_http_request_t *r) r->read_event_handler = ngx_http_block_reading; } + c = r->connection; + nreqs = c->requests; + rc = ngx_http_lua_run_thread(L, r, ctx, 0); dd("returned %d", (int) rc); @@ -337,10 +341,8 @@ ngx_http_lua_access_by_chunk(lua_State *L, ngx_http_request_t *r) return rc; } - c = r->connection; - if (rc == NGX_AGAIN) { - rc = ngx_http_lua_run_posted_threads(c, L, r, ctx); + rc = ngx_http_lua_run_posted_threads(c, L, r, ctx, nreqs); if (rc == NGX_ERROR || rc == NGX_DONE || rc > NGX_OK) { return rc; @@ -353,7 +355,7 @@ ngx_http_lua_access_by_chunk(lua_State *L, ngx_http_request_t *r) } else if (rc == NGX_DONE) { ngx_http_lua_finalize_request(r, NGX_DONE); - rc = ngx_http_lua_run_posted_threads(c, L, r, ctx); + rc = ngx_http_lua_run_posted_threads(c, L, r, ctx, nreqs); if (rc == NGX_ERROR || rc == NGX_DONE || rc > NGX_OK) { return rc; diff --git a/debian/modules/http-lua/src/ngx_http_lua_directive.c b/debian/modules/http-lua/src/ngx_http_lua_directive.c index 6a562f4..014a472 100644 --- a/debian/modules/http-lua/src/ngx_http_lua_directive.c +++ b/debian/modules/http-lua/src/ngx_http_lua_directive.c @@ -1542,7 +1542,7 @@ ngx_http_lua_conf_read_lua_token(ngx_conf_t *cf, #if nginx_version >= 1009002 if (dump) { - dump->last = ngx_cpymem(dump->last, b->pos, size); + dump->last = ngx_cpymem(dump->last, b->start + len, size); } #endif } diff --git a/debian/modules/http-lua/src/ngx_http_lua_output.c b/debian/modules/http-lua/src/ngx_http_lua_output.c index b410ba4..0fe8840 100644 --- a/debian/modules/http-lua/src/ngx_http_lua_output.c +++ b/debian/modules/http-lua/src/ngx_http_lua_output.c @@ -724,6 +724,7 @@ ngx_http_lua_flush_resume_helper(ngx_http_request_t *r, ngx_http_lua_ctx_t *ctx) int n; lua_State *vm; ngx_int_t rc; + ngx_uint_t nreqs; ngx_connection_t *c; c = r->connection; @@ -748,18 +749,20 @@ ngx_http_lua_flush_resume_helper(ngx_http_request_t *r, ngx_http_lua_ctx_t *ctx) } vm = ngx_http_lua_get_lua_vm(r, ctx); + nreqs = c->requests; + rc = ngx_http_lua_run_thread(vm, r, ctx, n); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua run thread returned %d", rc); if (rc == NGX_AGAIN) { - return ngx_http_lua_run_posted_threads(c, vm, r, ctx); + return ngx_http_lua_run_posted_threads(c, vm, r, ctx, nreqs); } if (rc == NGX_DONE) { ngx_http_lua_finalize_request(r, NGX_DONE); - return ngx_http_lua_run_posted_threads(c, vm, r, ctx); + return ngx_http_lua_run_posted_threads(c, vm, r, ctx, nreqs); } /* rc == NGX_ERROR || rc >= NGX_OK */ diff --git a/debian/modules/http-lua/src/ngx_http_lua_req_body.c b/debian/modules/http-lua/src/ngx_http_lua_req_body.c index 6f2ae38..e6bf3c1 100644 --- a/debian/modules/http-lua/src/ngx_http_lua_req_body.c +++ b/debian/modules/http-lua/src/ngx_http_lua_req_body.c @@ -1125,6 +1125,7 @@ ngx_http_lua_read_body_resume(ngx_http_request_t *r) { lua_State *vm; ngx_int_t rc; + ngx_uint_t nreqs; ngx_connection_t *c; ngx_http_lua_ctx_t *ctx; @@ -1134,6 +1135,7 @@ ngx_http_lua_read_body_resume(ngx_http_request_t *r) c = r->connection; vm = ngx_http_lua_get_lua_vm(r, ctx); + nreqs = c->requests; rc = ngx_http_lua_run_thread(vm, r, ctx, 0); @@ -1141,12 +1143,12 @@ ngx_http_lua_read_body_resume(ngx_http_request_t *r) "lua run thread returned %d", rc); if (rc == NGX_AGAIN) { - return ngx_http_lua_run_posted_threads(c, vm, r, ctx); + return ngx_http_lua_run_posted_threads(c, vm, r, ctx, nreqs); } if (rc == NGX_DONE) { ngx_http_lua_finalize_request(r, NGX_DONE); - return ngx_http_lua_run_posted_threads(c, vm, r, ctx); + return ngx_http_lua_run_posted_threads(c, vm, r, ctx, nreqs); } if (ctx->entered_content_phase) { diff --git a/debian/modules/http-lua/src/ngx_http_lua_rewriteby.c b/debian/modules/http-lua/src/ngx_http_lua_rewriteby.c index 44d8941..077c2d3 100644 --- a/debian/modules/http-lua/src/ngx_http_lua_rewriteby.c +++ b/debian/modules/http-lua/src/ngx_http_lua_rewriteby.c @@ -235,6 +235,7 @@ ngx_http_lua_rewrite_by_chunk(lua_State *L, ngx_http_request_t *r) int co_ref; lua_State *co; ngx_int_t rc; + ngx_uint_t nreqs; ngx_event_t *rev; ngx_connection_t *c; ngx_http_lua_ctx_t *ctx; @@ -324,20 +325,21 @@ ngx_http_lua_rewrite_by_chunk(lua_State *L, ngx_http_request_t *r) r->read_event_handler = ngx_http_block_reading; } + c = r->connection; + nreqs = c->requests; + rc = ngx_http_lua_run_thread(L, r, ctx, 0); if (rc == NGX_ERROR || rc > NGX_OK) { return rc; } - c = r->connection; - if (rc == NGX_AGAIN) { - rc = ngx_http_lua_run_posted_threads(c, L, r, ctx); + rc = ngx_http_lua_run_posted_threads(c, L, r, ctx, nreqs); } else if (rc == NGX_DONE) { ngx_http_lua_finalize_request(r, NGX_DONE); - rc = ngx_http_lua_run_posted_threads(c, L, r, ctx); + rc = ngx_http_lua_run_posted_threads(c, L, r, ctx, nreqs); } if (rc == NGX_OK || rc == NGX_DECLINED) { diff --git a/debian/modules/http-lua/src/ngx_http_lua_semaphore.c b/debian/modules/http-lua/src/ngx_http_lua_semaphore.c index eda0141..0b70aea 100644 --- a/debian/modules/http-lua/src/ngx_http_lua_semaphore.c +++ b/debian/modules/http-lua/src/ngx_http_lua_semaphore.c @@ -258,6 +258,7 @@ ngx_http_lua_sema_resume(ngx_http_request_t *r) lua_State *vm; ngx_connection_t *c; ngx_int_t rc; + ngx_uint_t nreqs; ngx_http_lua_ctx_t *ctx; ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); @@ -269,6 +270,7 @@ ngx_http_lua_sema_resume(ngx_http_request_t *r) c = r->connection; vm = ngx_http_lua_get_lua_vm(r, ctx); + nreqs = c->requests; if (ctx->cur_co_ctx->sem_resume_status == SEMAPHORE_WAIT_SUCC) { lua_pushboolean(ctx->cur_co_ctx->co, 1); @@ -285,12 +287,12 @@ ngx_http_lua_sema_resume(ngx_http_request_t *r) "lua run thread returned %d", rc); if (rc == NGX_AGAIN) { - return ngx_http_lua_run_posted_threads(c, vm, r, ctx); + return ngx_http_lua_run_posted_threads(c, vm, r, ctx, nreqs); } if (rc == NGX_DONE) { ngx_http_lua_finalize_request(r, NGX_DONE); - return ngx_http_lua_run_posted_threads(c, vm, r, ctx); + return ngx_http_lua_run_posted_threads(c, vm, r, ctx, nreqs); } /* rc == NGX_ERROR || rc >= NGX_OK */ diff --git a/debian/modules/http-lua/src/ngx_http_lua_shdict.c b/debian/modules/http-lua/src/ngx_http_lua_shdict.c index d6cad7e..5b48eb4 100644 --- a/debian/modules/http-lua/src/ngx_http_lua_shdict.c +++ b/debian/modules/http-lua/src/ngx_http_lua_shdict.c @@ -2843,6 +2843,173 @@ ngx_http_lua_ffi_shdict_flush_all(ngx_shm_zone_t *zone) return NGX_OK; } + + +static ngx_int_t +ngx_http_lua_shdict_peek(ngx_shm_zone_t *shm_zone, ngx_uint_t hash, + u_char *kdata, size_t klen, ngx_http_lua_shdict_node_t **sdp) +{ + ngx_int_t rc; + ngx_rbtree_node_t *node, *sentinel; + ngx_http_lua_shdict_ctx_t *ctx; + ngx_http_lua_shdict_node_t *sd; + + ctx = shm_zone->data; + + node = ctx->sh->rbtree.root; + sentinel = ctx->sh->rbtree.sentinel; + + while (node != sentinel) { + + if (hash < node->key) { + node = node->left; + continue; + } + + if (hash > node->key) { + node = node->right; + continue; + } + + /* hash == node->key */ + + sd = (ngx_http_lua_shdict_node_t *) &node->color; + + rc = ngx_memn2cmp(kdata, sd->data, klen, (size_t) sd->key_len); + + if (rc == 0) { + *sdp = sd; + + return NGX_OK; + } + + node = (rc < 0) ? node->left : node->right; + } + + *sdp = NULL; + + return NGX_DECLINED; +} + + +int +ngx_http_lua_ffi_shdict_get_ttl(ngx_shm_zone_t *zone, u_char *key, + size_t key_len) +{ + uint32_t hash; + uint64_t now; + uint64_t expires; + ngx_int_t rc; + ngx_time_t *tp; + ngx_http_lua_shdict_ctx_t *ctx; + ngx_http_lua_shdict_node_t *sd; + + if (zone == NULL) { + return NGX_ERROR; + } + + ctx = zone->data; + hash = ngx_crc32_short(key, key_len); + + ngx_shmtx_lock(&ctx->shpool->mutex); + + rc = ngx_http_lua_shdict_peek(zone, hash, key, key_len, &sd); + + if (rc == NGX_DECLINED) { + ngx_shmtx_unlock(&ctx->shpool->mutex); + + return NGX_DECLINED; + } + + /* rc == NGX_OK */ + + expires = sd->expires; + + ngx_shmtx_unlock(&ctx->shpool->mutex); + + if (expires == 0) { + return 0; + } + + tp = ngx_timeofday(); + now = (uint64_t) tp->sec * 1000 + tp->msec; + + return expires - now; +} + + +int +ngx_http_lua_ffi_shdict_set_expire(ngx_shm_zone_t *zone, u_char *key, + size_t key_len, int exptime) +{ + uint32_t hash; + ngx_int_t rc; + ngx_time_t *tp = NULL; + ngx_http_lua_shdict_ctx_t *ctx; + ngx_http_lua_shdict_node_t *sd; + + if (zone == NULL) { + return NGX_ERROR; + } + + if (exptime > 0) { + tp = ngx_timeofday(); + } + + ctx = zone->data; + hash = ngx_crc32_short(key, key_len); + + ngx_shmtx_lock(&ctx->shpool->mutex); + + rc = ngx_http_lua_shdict_peek(zone, hash, key, key_len, &sd); + + if (rc == NGX_DECLINED) { + ngx_shmtx_unlock(&ctx->shpool->mutex); + + return NGX_DECLINED; + } + + /* rc == NGX_OK */ + + if (exptime > 0) { + sd->expires = (uint64_t) tp->sec * 1000 + tp->msec + + (uint64_t) exptime; + + } else { + sd->expires = 0; + } + + ngx_shmtx_unlock(&ctx->shpool->mutex); + + return NGX_OK; +} + + +size_t +ngx_http_lua_ffi_shdict_capacity(ngx_shm_zone_t *zone) +{ + return zone->shm.size; +} + + +# if nginx_version >= 1011007 +size_t +ngx_http_lua_ffi_shdict_free_space(ngx_shm_zone_t *zone) +{ + size_t bytes; + ngx_http_lua_shdict_ctx_t *ctx; + + ctx = zone->data; + + ngx_shmtx_lock(&ctx->shpool->mutex); + bytes = ctx->shpool->pfree * ngx_pagesize; + ngx_shmtx_unlock(&ctx->shpool->mutex); + + return bytes; +} +# endif /* nginx_version >= 1011007 */ + + #endif /* NGX_LUA_NO_FFI_API */ diff --git a/debian/modules/http-lua/src/ngx_http_lua_sleep.c b/debian/modules/http-lua/src/ngx_http_lua_sleep.c index ffee97f..09ea0f6 100644 --- a/debian/modules/http-lua/src/ngx_http_lua_sleep.c +++ b/debian/modules/http-lua/src/ngx_http_lua_sleep.c @@ -180,6 +180,7 @@ ngx_http_lua_sleep_resume(ngx_http_request_t *r) lua_State *vm; ngx_connection_t *c; ngx_int_t rc; + ngx_uint_t nreqs; ngx_http_lua_ctx_t *ctx; ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); @@ -191,6 +192,7 @@ ngx_http_lua_sleep_resume(ngx_http_request_t *r) c = r->connection; vm = ngx_http_lua_get_lua_vm(r, ctx); + nreqs = c->requests; rc = ngx_http_lua_run_thread(vm, r, ctx, 0); @@ -198,12 +200,12 @@ ngx_http_lua_sleep_resume(ngx_http_request_t *r) "lua run thread returned %d", rc); if (rc == NGX_AGAIN) { - return ngx_http_lua_run_posted_threads(c, vm, r, ctx); + return ngx_http_lua_run_posted_threads(c, vm, r, ctx, nreqs); } if (rc == NGX_DONE) { ngx_http_lua_finalize_request(r, NGX_DONE); - return ngx_http_lua_run_posted_threads(c, vm, r, ctx); + return ngx_http_lua_run_posted_threads(c, vm, r, ctx, nreqs); } if (ctx->entered_content_phase) { diff --git a/debian/modules/http-lua/src/ngx_http_lua_socket_tcp.c b/debian/modules/http-lua/src/ngx_http_lua_socket_tcp.c index 382a94d..f0988bc 100644 --- a/debian/modules/http-lua/src/ngx_http_lua_socket_tcp.c +++ b/debian/modules/http-lua/src/ngx_http_lua_socket_tcp.c @@ -474,6 +474,7 @@ ngx_http_lua_socket_tcp_connect(lua_State *L) switch (lua_type(L, -1)) { case LUA_TNUMBER: lua_tostring(L, -1); + /* FALLTHROUGH */ case LUA_TSTRING: custom_pool = 1; @@ -743,6 +744,9 @@ ngx_http_lua_socket_tcp_connect(lua_State *L) u->ft_type |= NGX_HTTP_LUA_SOCKET_FT_RESOLVER; + coctx->cleanup = NULL; + coctx->data = NULL; + u->resolved->ctx = NULL; lua_pushnil(L); lua_pushfstring(L, "%s could not be resolved", host.data); @@ -2708,6 +2712,10 @@ ngx_http_lua_socket_tcp_settimeout(lua_State *L) } timeout = (ngx_int_t) lua_tonumber(L, 2); + if (timeout >> 31) { + return luaL_error(L, "bad timeout value"); + } + lua_pushinteger(L, timeout); lua_pushinteger(L, timeout); @@ -2751,8 +2759,19 @@ ngx_http_lua_socket_tcp_settimeouts(lua_State *L) } connect_timeout = (ngx_int_t) lua_tonumber(L, 2); + if (connect_timeout >> 31) { + return luaL_error(L, "bad timeout value"); + } + send_timeout = (ngx_int_t) lua_tonumber(L, 3); + if (send_timeout >> 31) { + return luaL_error(L, "bad timeout value"); + } + read_timeout = (ngx_int_t) lua_tonumber(L, 4); + if (read_timeout >> 31) { + return luaL_error(L, "bad timeout value"); + } lua_rawseti(L, 1, SOCKET_READ_TIMEOUT_INDEX); lua_rawseti(L, 1, SOCKET_SEND_TIMEOUT_INDEX); @@ -5234,6 +5253,7 @@ ngx_http_lua_socket_tcp_resume_helper(ngx_http_request_t *r, int socket_op) int nret; lua_State *vm; ngx_int_t rc; + ngx_uint_t nreqs; ngx_connection_t *c; ngx_http_lua_ctx_t *ctx; ngx_http_lua_co_ctx_t *coctx; @@ -5284,6 +5304,7 @@ ngx_http_lua_socket_tcp_resume_helper(ngx_http_request_t *r, int socket_op) c = r->connection; vm = ngx_http_lua_get_lua_vm(r, ctx); + nreqs = c->requests; rc = ngx_http_lua_run_thread(vm, r, ctx, nret); @@ -5291,12 +5312,12 @@ ngx_http_lua_socket_tcp_resume_helper(ngx_http_request_t *r, int socket_op) "lua run thread returned %d", rc); if (rc == NGX_AGAIN) { - return ngx_http_lua_run_posted_threads(c, vm, r, ctx); + return ngx_http_lua_run_posted_threads(c, vm, r, ctx, nreqs); } if (rc == NGX_DONE) { ngx_http_lua_finalize_request(r, NGX_DONE); - return ngx_http_lua_run_posted_threads(c, vm, r, ctx); + return ngx_http_lua_run_posted_threads(c, vm, r, ctx, nreqs); } if (ctx->entered_content_phase) { diff --git a/debian/modules/http-lua/src/ngx_http_lua_socket_udp.c b/debian/modules/http-lua/src/ngx_http_lua_socket_udp.c index 1ec0c00..08ba1cc 100644 --- a/debian/modules/http-lua/src/ngx_http_lua_socket_udp.c +++ b/debian/modules/http-lua/src/ngx_http_lua_socket_udp.c @@ -1514,6 +1514,7 @@ ngx_http_lua_socket_udp_resume(ngx_http_request_t *r) int nret; lua_State *vm; ngx_int_t rc; + ngx_uint_t nreqs; ngx_connection_t *c; ngx_http_lua_ctx_t *ctx; ngx_http_lua_co_ctx_t *coctx; @@ -1549,6 +1550,7 @@ ngx_http_lua_socket_udp_resume(ngx_http_request_t *r) c = r->connection; vm = ngx_http_lua_get_lua_vm(r, ctx); + nreqs = c->requests; rc = ngx_http_lua_run_thread(vm, r, ctx, nret); @@ -1556,12 +1558,12 @@ ngx_http_lua_socket_udp_resume(ngx_http_request_t *r) "lua run thread returned %d", rc); if (rc == NGX_AGAIN) { - return ngx_http_lua_run_posted_threads(c, vm, r, ctx); + return ngx_http_lua_run_posted_threads(c, vm, r, ctx, nreqs); } if (rc == NGX_DONE) { ngx_http_lua_finalize_request(r, NGX_DONE); - return ngx_http_lua_run_posted_threads(c, vm, r, ctx); + return ngx_http_lua_run_posted_threads(c, vm, r, ctx, nreqs); } if (ctx->entered_content_phase) { diff --git a/debian/modules/http-lua/src/ngx_http_lua_ssl_certby.c b/debian/modules/http-lua/src/ngx_http_lua_ssl_certby.c index c3591d1..95be47f 100644 --- a/debian/modules/http-lua/src/ngx_http_lua_ssl_certby.c +++ b/debian/modules/http-lua/src/ngx_http_lua_ssl_certby.c @@ -197,7 +197,8 @@ ngx_http_lua_ssl_cert_handler(ngx_ssl_conn_t *ssl_conn, void *data) c = ngx_ssl_get_connection(ssl_conn); - dd("c = %p", c); + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, + "ssl cert: connection reusable: %ud", c->reusable); cctx = ngx_http_lua_ssl_get_ctx(c->ssl->connection); @@ -220,6 +221,8 @@ ngx_http_lua_ssl_cert_handler(ngx_ssl_conn_t *ssl_conn, void *data) dd("first time"); + ngx_reusable_connection(c, 0); + hc = c->data; fc = ngx_http_lua_create_fake_connection(NULL); diff --git a/debian/modules/http-lua/src/ngx_http_lua_ssl_session_fetchby.c b/debian/modules/http-lua/src/ngx_http_lua_ssl_session_fetchby.c index 556b732..3a3c1f5 100644 --- a/debian/modules/http-lua/src/ngx_http_lua_ssl_session_fetchby.c +++ b/debian/modules/http-lua/src/ngx_http_lua_ssl_session_fetchby.c @@ -191,7 +191,8 @@ ngx_http_lua_ssl_sess_fetch_handler(ngx_ssl_conn_t *ssl_conn, u_char *id, c = ngx_ssl_get_connection(ssl_conn); - dd("c = %p", c); + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, + "ssl session fetch: connection reusable: %ud", c->reusable); cctx = ngx_http_lua_ssl_get_ctx(c->ssl->connection); @@ -224,6 +225,8 @@ ngx_http_lua_ssl_sess_fetch_handler(ngx_ssl_conn_t *ssl_conn, u_char *id, dd("first time"); + ngx_reusable_connection(c, 0); + hc = c->data; fc = ngx_http_lua_create_fake_connection(NULL); diff --git a/debian/modules/http-lua/src/ngx_http_lua_ssl_session_storeby.c b/debian/modules/http-lua/src/ngx_http_lua_ssl_session_storeby.c index bae8273..f83e85d 100644 --- a/debian/modules/http-lua/src/ngx_http_lua_ssl_session_storeby.c +++ b/debian/modules/http-lua/src/ngx_http_lua_ssl_session_storeby.c @@ -183,7 +183,8 @@ ngx_http_lua_ssl_sess_store_handler(ngx_ssl_conn_t *ssl_conn, c = ngx_ssl_get_connection(ssl_conn); - dd("c = %p", c); + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, + "ssl session store: connection reusable: %ud", c->reusable); cctx = ngx_http_lua_ssl_get_ctx(c->ssl->connection); diff --git a/debian/modules/http-lua/src/ngx_http_lua_subrequest.c b/debian/modules/http-lua/src/ngx_http_lua_subrequest.c index 6f7aa97..47096e9 100644 --- a/debian/modules/http-lua/src/ngx_http_lua_subrequest.c +++ b/debian/modules/http-lua/src/ngx_http_lua_subrequest.c @@ -1587,6 +1587,7 @@ ngx_http_lua_subrequest_resume(ngx_http_request_t *r) { lua_State *vm; ngx_int_t rc; + ngx_uint_t nreqs; ngx_connection_t *c; ngx_http_lua_ctx_t *ctx; ngx_http_lua_co_ctx_t *coctx; @@ -1620,6 +1621,7 @@ ngx_http_lua_subrequest_resume(ngx_http_request_t *r) c = r->connection; vm = ngx_http_lua_get_lua_vm(r, ctx); + nreqs = c->requests; rc = ngx_http_lua_run_thread(vm, r, ctx, coctx->nsubreqs); @@ -1627,12 +1629,12 @@ ngx_http_lua_subrequest_resume(ngx_http_request_t *r) "lua run thread returned %d", rc); if (rc == NGX_AGAIN) { - return ngx_http_lua_run_posted_threads(c, vm, r, ctx); + return ngx_http_lua_run_posted_threads(c, vm, r, ctx, nreqs); } if (rc == NGX_DONE) { ngx_http_lua_finalize_request(r, NGX_DONE); - return ngx_http_lua_run_posted_threads(c, vm, r, ctx); + return ngx_http_lua_run_posted_threads(c, vm, r, ctx, nreqs); } /* rc == NGX_ERROR || rc >= NGX_OK */ diff --git a/debian/modules/http-lua/src/ngx_http_lua_util.c b/debian/modules/http-lua/src/ngx_http_lua_util.c index c7bee3e..df0aae8 100644 --- a/debian/modules/http-lua/src/ngx_http_lua_util.c +++ b/debian/modules/http-lua/src/ngx_http_lua_util.c @@ -3055,13 +3055,13 @@ ngx_http_lua_create_co_ctx(ngx_http_request_t *r, ngx_http_lua_ctx_t *ctx) /* this is for callers other than the content handler */ ngx_int_t ngx_http_lua_run_posted_threads(ngx_connection_t *c, lua_State *L, - ngx_http_request_t *r, ngx_http_lua_ctx_t *ctx) + ngx_http_request_t *r, ngx_http_lua_ctx_t *ctx, ngx_uint_t nreqs) { ngx_int_t rc; ngx_http_lua_posted_thread_t *pt; for ( ;; ) { - if (c->destroyed) { + if (c->destroyed || c->requests != nreqs) { return NGX_DONE; } @@ -3461,6 +3461,7 @@ ngx_http_lua_on_abort_resume(ngx_http_request_t *r) { lua_State *vm; ngx_int_t rc; + ngx_uint_t nreqs; ngx_connection_t *c; ngx_http_lua_ctx_t *ctx; @@ -3480,6 +3481,7 @@ ngx_http_lua_on_abort_resume(ngx_http_request_t *r) c = r->connection; vm = ngx_http_lua_get_lua_vm(r, ctx); + nreqs = c->requests; rc = ngx_http_lua_run_thread(vm, r, ctx, 0); @@ -3487,12 +3489,12 @@ ngx_http_lua_on_abort_resume(ngx_http_request_t *r) "lua run thread returned %d", rc); if (rc == NGX_AGAIN) { - return ngx_http_lua_run_posted_threads(c, vm, r, ctx); + return ngx_http_lua_run_posted_threads(c, vm, r, ctx, nreqs); } if (rc == NGX_DONE) { ngx_http_lua_finalize_request(r, NGX_DONE); - return ngx_http_lua_run_posted_threads(c, vm, r, ctx); + return ngx_http_lua_run_posted_threads(c, vm, r, ctx, nreqs); } if (ctx->entered_content_phase) { diff --git a/debian/modules/http-lua/src/ngx_http_lua_util.h b/debian/modules/http-lua/src/ngx_http_lua_util.h index a37852f..2f995e0 100644 --- a/debian/modules/http-lua/src/ngx_http_lua_util.h +++ b/debian/modules/http-lua/src/ngx_http_lua_util.h @@ -205,7 +205,7 @@ ngx_http_lua_co_ctx_t *ngx_http_lua_create_co_ctx(ngx_http_request_t *r, ngx_http_lua_ctx_t *ctx); ngx_int_t ngx_http_lua_run_posted_threads(ngx_connection_t *c, lua_State *L, - ngx_http_request_t *r, ngx_http_lua_ctx_t *ctx); + ngx_http_request_t *r, ngx_http_lua_ctx_t *ctx, ngx_uint_t nreqs); ngx_int_t ngx_http_lua_post_thread(ngx_http_request_t *r, ngx_http_lua_ctx_t *ctx, ngx_http_lua_co_ctx_t *coctx); diff --git a/debian/modules/http-lua/t/000--init.t b/debian/modules/http-lua/t/000--init.t index ad2d70e..dbe2c33 100644 --- a/debian/modules/http-lua/t/000--init.t +++ b/debian/modules/http-lua/t/000--init.t @@ -4,7 +4,7 @@ use Test::Nginx::Socket::Lua; repeat_each(1); -plan tests => repeat_each() * (blocks() * 2 + 1); +plan tests => repeat_each() * (blocks() * 3); $ENV{TEST_NGINX_MEMCACHED_PORT} ||= 11211; $ENV{TEST_NGINX_MYSQL_PORT} ||= 3306; @@ -14,9 +14,13 @@ our $http_config = <<'_EOC_'; drizzle_server 127.0.0.1:$TEST_NGINX_MYSQL_PORT protocol=mysql dbname=ngx_test user=ngx_test password=ngx_test; } + + lua_package_path "../lua-resty-mysql/lib/?.lua;;"; _EOC_ no_shuffle(); +no_long_string(); + run_tests(); __DATA__ @@ -25,51 +29,46 @@ __DATA__ --- http_config eval: $::http_config --- config location = /init { - drizzle_pass database; - drizzle_query "DROP TABLE IF EXISTS conv_uid"; + content_by_lua_block { + local mysql = require "resty.mysql" + local db = assert(mysql:new()) + local ok, err, errcode, sqlstate = db:connect{ + host = "127.0.0.1", + port = $TEST_NGINX_MYSQL_PORT, + database = "ngx_test", + user = "ngx_test", + password = "ngx_test", + charset = "utf8", + } + + local queries = { + "DROP TABLE IF EXISTS conv_uid", + "CREATE TABLE conv_uid(id serial primary key, new_uid integer, old_uid integer)", + "INSERT INTO conv_uid(old_uid,new_uid) VALUES(32,56),(35,78)", + } + + for _, query in ipairs(queries) do + local ok, err = db:query(query) + if not ok then + ngx.say("failed to run mysql query \"", query, "\": ", err) + return + end + end + + ngx.say("done!") + } } --- request GET /init ---- error_code: 200 +--- response_body +done! --- timeout: 10 --- no_error_log [error] -=== TEST 2: conv_uid - create table ---- http_config eval: $::http_config ---- config - location = /init { - drizzle_pass database; - drizzle_query "CREATE TABLE conv_uid(id serial primary key, new_uid integer, old_uid integer)"; - } ---- request -GET /init ---- error_code: 200 ---- timeout: 10 ---- no_error_log -[error] - - - -=== TEST 3: conv_uid - insert value ---- http_config eval: $::http_config ---- config - location = /init { - drizzle_pass database; - drizzle_query "INSERT INTO conv_uid(old_uid,new_uid) VALUES(32,56),(35,78)"; - } ---- request -GET /init ---- error_code: 200 ---- timeout: 10 ---- no_error_log -[error] - - - -=== TEST 4: flush data from memcached +=== TEST 2: flush data from memcached --- config location /flush { set $memc_cmd flush_all; diff --git a/debian/modules/http-lua/t/002-content.t b/debian/modules/http-lua/t/002-content.t index 3f2460e..cc92d6f 100644 --- a/debian/modules/http-lua/t/002-content.t +++ b/debian/modules/http-lua/t/002-content.t @@ -10,7 +10,7 @@ use Test::Nginx::Socket::Lua; repeat_each(2); #repeat_each(1); -plan tests => repeat_each() * (blocks() * 2 + 19); +plan tests => repeat_each() * (blocks() * 2 + 23); #no_diff(); #no_long_string(); @@ -539,6 +539,9 @@ GET /main Content-Length: 12 --- response_body chop hello, world +--- no_error_log +[error] +[alert] @@ -761,6 +764,9 @@ Content-Length: 13 hello, world --- timeout: 5 +--- no_error_log +[error] +[alert] diff --git a/debian/modules/http-lua/t/004-require.t b/debian/modules/http-lua/t/004-require.t index ec74116..35e04db 100644 --- a/debian/modules/http-lua/t/004-require.t +++ b/debian/modules/http-lua/t/004-require.t @@ -35,6 +35,7 @@ __DATA__ location /load { content_by_lua ' package.loaded.foo = nil; + collectgarbage() local foo = require "foo"; foo.hi() '; diff --git a/debian/modules/http-lua/t/017-exec.t b/debian/modules/http-lua/t/017-exec.t index 535c4ab..544b8bb 100644 --- a/debian/modules/http-lua/t/017-exec.t +++ b/debian/modules/http-lua/t/017-exec.t @@ -4,7 +4,7 @@ use Test::Nginx::Socket::Lua; repeat_each(2); -plan tests => repeat_each() * (blocks() * 2 + 4); +plan tests => repeat_each() * (blocks() * 2 + 8); $ENV{TEST_NGINX_MEMCACHED_PORT} ||= 11211; @@ -572,3 +572,25 @@ hello, bah ["dummy", "dummy"] --- no_error_log [error] + + + +=== TEST 25: pipelined requests +--- config + location /t { + content_by_lua_block { + ngx.exec("@foo") + } + } + + location @foo { + return 200; + } +--- pipelined_requests eval +["GET /t", "GET /t"] +--- error_code eval +[200, 200] +--- response_body eval +["", ""] +--- no_error_log +[error] diff --git a/debian/modules/http-lua/t/023-rewrite/exec.t b/debian/modules/http-lua/t/023-rewrite/exec.t index bd97968..edd4607 100644 --- a/debian/modules/http-lua/t/023-rewrite/exec.t +++ b/debian/modules/http-lua/t/023-rewrite/exec.t @@ -5,7 +5,7 @@ use Test::Nginx::Socket::Lua; repeat_each(2); #repeat_each(1); -plan tests => blocks() * repeat_each() * 2; +plan tests => repeat_each() * (blocks() * 2 + 4); #no_diff(); #no_long_string(); @@ -376,3 +376,25 @@ ngx.exec("@proxy") GET /main --- response_body hello, bah + + + +=== TEST 17: pipelined requests +--- config + location /t { + rewrite_by_lua_block { + ngx.exec("@foo") + } + } + + location @foo { + return 200; + } +--- pipelined_requests eval +["GET /t", "GET /t"] +--- error_code eval +[200, 200] +--- response_body eval +["", ""] +--- no_error_log +[error] diff --git a/debian/modules/http-lua/t/023-rewrite/tcp-socket-timeout.t b/debian/modules/http-lua/t/023-rewrite/tcp-socket-timeout.t index 15bec7f..a32ed7b 100644 --- a/debian/modules/http-lua/t/023-rewrite/tcp-socket-timeout.t +++ b/debian/modules/http-lua/t/023-rewrite/tcp-socket-timeout.t @@ -24,7 +24,7 @@ use Test::Nginx::Socket::Lua; repeat_each(2); -plan tests => repeat_each() * (blocks() * 4 + 14); +plan tests => repeat_each() * (blocks() * 4 + 8); our $HtmlDir = html_dir; @@ -174,7 +174,7 @@ lua tcp socket connect timeout: 102 -=== TEST 5: sock:settimeout(-1) does not override lua_socket_connect_timeout +=== TEST 5: -1 is bad timeout value --- config server_tokens off; lua_socket_connect_timeout 102ms; @@ -198,14 +198,12 @@ lua tcp socket connect timeout: 102 } --- request GET /t5 ---- response_body -failed to connect: timeout +--- response_body_like chomp +500 Internal Server Error --- error_log -lua tcp socket connect timeout: 102 ---- no_error_log -[error] -[alert] +bad timeout value --- timeout: 10 +--- error_code: 500 @@ -371,7 +369,7 @@ lua tcp socket read timed out -=== TEST 10: sock:settimeout(-1) does not override lua_socket_read_timeout +=== TEST 10: -1 is bad timeout value --- config server_tokens off; lua_socket_read_timeout 102ms; @@ -385,8 +383,6 @@ lua tcp socket read timed out return end - ngx.say("connected: ", ok) - sock:settimeout(-1) local line @@ -402,13 +398,12 @@ lua tcp socket read timed out } --- request GET /t ---- response_body -connected: 1 -failed to receive: timeout +--- response_body_like chomp +500 Internal Server Error --- error_log -lua tcp socket read timeout: 102 -lua tcp socket connect timeout: 60000 -lua tcp socket read timed out +bad timeout value +--- timeout: 10 +--- error_code: 500 @@ -574,7 +569,7 @@ lua tcp socket write timed out -=== TEST 15: sock:settimeout(-1) does not override lua_socket_send_timeout +=== TEST 15: -1 is bad timeout value --- config server_tokens off; lua_socket_send_timeout 102ms; @@ -588,8 +583,6 @@ lua tcp socket write timed out return end - ngx.say("connected: ", ok) - sock:settimeout(-1) local bytes @@ -605,10 +598,9 @@ lua tcp socket write timed out } --- request GET /t ---- response_body -connected: 1 -failed to send: timeout +--- response_body_like chomp +500 Internal Server Error --- error_log -lua tcp socket send timeout: 102 -lua tcp socket connect timeout: 60000 -lua tcp socket write timed out +bad timeout value +--- timeout: 10 +--- error_code: 500 diff --git a/debian/modules/http-lua/t/024-access/exec.t b/debian/modules/http-lua/t/024-access/exec.t index 3fb87be..43c1a77 100644 --- a/debian/modules/http-lua/t/024-access/exec.t +++ b/debian/modules/http-lua/t/024-access/exec.t @@ -4,7 +4,7 @@ use Test::Nginx::Socket::Lua; repeat_each(2); -plan tests => repeat_each() * (blocks() * 2 + 2); +plan tests => repeat_each() * (blocks() * 2 + 6); #no_diff(); #no_long_string(); @@ -369,3 +369,25 @@ GET /read 'unsafe URI "/hi/../" was detected', qr/runtime error: access_by_lua\(nginx.conf:\d+\):2: unsafe uri/, ] + + + +=== TEST 17: pipelined requests +--- config + location /t { + access_by_lua_block { + ngx.exec("@foo") + } + } + + location @foo { + return 200; + } +--- pipelined_requests eval +["GET /t", "GET /t"] +--- error_code eval +[200, 200] +--- response_body eval +["", ""] +--- no_error_log +[error] diff --git a/debian/modules/http-lua/t/035-gmatch.t b/debian/modules/http-lua/t/035-gmatch.t index 5b63ae4..0426997 100644 --- a/debian/modules/http-lua/t/035-gmatch.t +++ b/debian/modules/http-lua/t/035-gmatch.t @@ -440,6 +440,7 @@ done location /main { content_by_lua ' package.loaded.foo = nil + collectgarbage() local res = ngx.location.capture("/t") if res.status == 200 then diff --git a/debian/modules/http-lua/t/058-tcp-socket.t b/debian/modules/http-lua/t/058-tcp-socket.t index 1ee113b..0743dd7 100644 --- a/debian/modules/http-lua/t/058-tcp-socket.t +++ b/debian/modules/http-lua/t/058-tcp-socket.t @@ -4,7 +4,7 @@ use Test::Nginx::Socket::Lua; repeat_each(2); -plan tests => repeat_each() * 190; +plan tests => repeat_each() * 193; our $HtmlDir = html_dir; @@ -3690,3 +3690,40 @@ received: OK close: 1 nil --- no_error_log [error] + + + +=== TEST 61: resolver send query failing immediately in connect() +this case did not clear coctx->cleanup properly and would lead to memory invalid accesses. + +this test case requires the following iptables rule to work properly: + +sudo iptables -I OUTPUT 1 -p udp --dport 10086 -j REJECT + +--- config + location /t { + resolver 127.0.0.1:10086 ipv6=off; + resolver_timeout 10ms; + + content_by_lua_block { + local sock = ngx.socket.tcp() + + for i = 1, 3 do -- retry + local ok, err = sock:connect("www.google.com", 80) + if not ok then + ngx.say("failed to connect: ", err) + end + end + + ngx.say("hello!") + } + } +--- request +GET /t +--- response_body +failed to connect: www.google.com could not be resolved +failed to connect: www.google.com could not be resolved +failed to connect: www.google.com could not be resolved +hello! +--- error_log eval +qr{\[alert\] .*? send\(\) failed \(\d+: Operation not permitted\) while resolving} diff --git a/debian/modules/http-lua/t/065-tcp-socket-timeout.t b/debian/modules/http-lua/t/065-tcp-socket-timeout.t index 212766e..9e5460e 100644 --- a/debian/modules/http-lua/t/065-tcp-socket-timeout.t +++ b/debian/modules/http-lua/t/065-tcp-socket-timeout.t @@ -28,7 +28,7 @@ our $StapScript = $t::StapThread::StapScript; repeat_each(2); -plan tests => repeat_each() * (blocks() * 4 + 12); +plan tests => repeat_each() * (blocks() * 4 + 6); our $HtmlDir = html_dir; @@ -159,7 +159,7 @@ lua tcp socket connect timed out -=== TEST 5: sock:settimeout(-1) does not override lua_socket_connect_timeout +=== TEST 5: -1 is bad timeout value --- config server_tokens off; lua_socket_connect_timeout 102ms; @@ -179,11 +179,11 @@ lua tcp socket connect timed out } --- request GET /t ---- response_body -failed to connect: timeout +--- response_body_like chomp +500 Internal Server Error --- error_log -lua tcp socket connect timeout: 102 -lua tcp socket connect timed out +bad timeout value +--- error_code: 500 @@ -342,7 +342,7 @@ lua tcp socket read timed out -=== TEST 10: sock:settimeout(-1) does not override lua_socket_read_timeout +=== TEST 10: -1 is bad timeout value --- config server_tokens off; lua_socket_read_timeout 102ms; @@ -356,8 +356,6 @@ lua tcp socket read timed out return end - ngx.say("connected: ", ok) - sock:settimeout(-1) local line @@ -371,13 +369,11 @@ lua tcp socket read timed out } --- request GET /t ---- response_body -connected: 1 -failed to receive: timeout +--- response_body_like chomp +500 Internal Server Error +--- error_code: 500 --- error_log -lua tcp socket read timeout: 102 -lua tcp socket connect timeout: 60000 -lua tcp socket read timed out +bad timeout value @@ -563,8 +559,6 @@ lua tcp socket write timed out return end - ngx.say("connected: ", ok) - sock:settimeout(-1) local bytes @@ -578,13 +572,11 @@ lua tcp socket write timed out } --- request GET /t ---- response_body -connected: 1 -failed to send: timeout +--- response_body_like chomp +500 Internal Server Error --- error_log -lua tcp socket send timeout: 102 -lua tcp socket connect timeout: 60000 -lua tcp socket write timed out +bad timeout value +--- error_code: 500 @@ -994,3 +986,33 @@ close: 1 nil --- no_error_log [error] + + + +=== TEST 23: timeout overflow detection +--- config + location /t { + content_by_lua_block { + local sock = ngx.socket.tcp() + local ok, err = pcall(sock.settimeout, sock, (2 ^ 31) - 1) + if not ok then + ngx.say("failed to set timeout: ", err) + else + ngx.say("settimeout: ok") + end + + ok, err = pcall(sock.settimeout, sock, 2 ^ 31) + if not ok then + ngx.say("failed to set timeout: ", err) + else + ngx.say("settimeout: ok") + end + } + } +--- request +GET /t +--- response_body_like +settimeout: ok +failed to set timeout: bad timeout value +--- no_error_log +[error] diff --git a/debian/modules/http-lua/t/097-uthread-rewrite.t b/debian/modules/http-lua/t/097-uthread-rewrite.t index a93adc8..2f0c06f 100644 --- a/debian/modules/http-lua/t/097-uthread-rewrite.t +++ b/debian/modules/http-lua/t/097-uthread-rewrite.t @@ -258,6 +258,7 @@ free request hello foo --- no_error_log [error] +--- wait: 0.1 diff --git a/debian/modules/http-lua/t/106-timer.t b/debian/modules/http-lua/t/106-timer.t index 04a532e..3e4741e 100644 --- a/debian/modules/http-lua/t/106-timer.t +++ b/debian/modules/http-lua/t/106-timer.t @@ -174,7 +174,7 @@ qr/\[lua\] content_by_lua\(nginx\.conf:\d+\):\d+: elapsed: 0\.0(?:4[4-9]|5[0-6]) local begin = ngx.now() local function f() print("my lua timer handler") - ngx.sleep(0.02) + ngx.sleep(0.2) print("elapsed: ", ngx.now() - begin) end local ok, err = ngx.timer.at(0.05, f) @@ -199,7 +199,7 @@ delete thread 2 --- response_body registered timer ---- wait: 0.12 +--- wait: 0.3 --- no_error_log [error] [alert] @@ -208,7 +208,7 @@ registered timer --- error_log eval [ qr/\[lua\] .*? my lua timer handler/, -qr/\[lua\] content_by_lua\(nginx\.conf:\d+\):\d+: elapsed: 0\.0(?:6[4-9]|7[0-6])/, +qr/\[lua\] content_by_lua\(nginx\.conf:\d+\):\d+: elapsed: 0\.(?:1[4-9]|2[0-6]?)/, "lua ngx.timer expired", "http lua close fake http connection" ] diff --git a/debian/modules/http-lua/t/129-ssl-socket.t b/debian/modules/http-lua/t/129-ssl-socket.t index 1c3f7cd..e7447a7 100644 --- a/debian/modules/http-lua/t/129-ssl-socket.t +++ b/debian/modules/http-lua/t/129-ssl-socket.t @@ -1181,7 +1181,7 @@ lua ssl free session: ([0-9A-F]+):1 $/ --- error_log lua ssl server name: "openresty.org" -SSL: TLSv1.2, cipher: "ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 +SSL: TLSv1.2, cipher: "ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2 --- no_error_log SSL reused session [error] @@ -1261,7 +1261,7 @@ lua ssl free session: ([0-9A-F]+):1 $/ --- error_log lua ssl server name: "openresty.org" -SSL: TLSv1.2, cipher: "ECDHE-RSA-AES256-SHA +SSL: TLSv1.2, cipher: "ECDHE-RSA-AES256-SHA SSLv3 --- no_error_log SSL reused session [error] @@ -1341,7 +1341,7 @@ lua ssl free session: ([0-9A-F]+):1 $/ --- error_log lua ssl server name: "openresty.org" -SSL: TLSv1, cipher: "ECDHE-RSA-AES256-SHA +SSL: TLSv1, cipher: "ECDHE-RSA-AES128-SHA SSLv3 --- no_error_log SSL reused session [error] diff --git a/debian/modules/http-lua/t/139-ssl-cert-by.t b/debian/modules/http-lua/t/139-ssl-cert-by.t index c13044f..b521e9e 100644 --- a/debian/modules/http-lua/t/139-ssl-cert-by.t +++ b/debian/modules/http-lua/t/139-ssl-cert-by.t @@ -113,11 +113,17 @@ close: 1 nil --- error_log lua ssl server name: "test.com" -ssl_certificate_by_lua:1: ssl cert by lua is running! --- no_error_log [error] [alert] +--- grep_error_log eval: qr/ssl_certificate_by_lua:.*?,|\bssl cert: connection reusable: \d+|\breusable connection: \d+/ +--- grep_error_log_out eval +qr/reusable connection: 1 +ssl cert: connection reusable: 1 +reusable connection: 0 +ssl_certificate_by_lua:1: ssl cert by lua is running!, +/ diff --git a/debian/modules/http-lua/t/142-ssl-session-store.t b/debian/modules/http-lua/t/142-ssl-session-store.t index 73b6e19..825d016 100644 --- a/debian/modules/http-lua/t/142-ssl-session-store.t +++ b/debian/modules/http-lua/t/142-ssl-session-store.t @@ -82,11 +82,16 @@ close: 1 nil --- error_log lua ssl server name: "test.com" -ssl_session_store_by_lua_block:1: ssl session store by lua is running! --- no_error_log [error] [alert] +--- grep_error_log eval: qr/ssl_session_store_by_lua_block:.*?,|\bssl session store: connection reusable: \d+|\breusable connection: \d+/ +--- grep_error_log_out eval +qr/^reusable connection: 0 +ssl session store: connection reusable: 0 +ssl_session_store_by_lua_block:1: ssl session store by lua is running!, +/m, diff --git a/debian/modules/http-lua/t/143-ssl-session-fetch.t b/debian/modules/http-lua/t/143-ssl-session-fetch.t index 701ead7..7be180f 100644 --- a/debian/modules/http-lua/t/143-ssl-session-fetch.t +++ b/debian/modules/http-lua/t/143-ssl-session-fetch.t @@ -83,16 +83,21 @@ connected: 1 ssl handshake: userdata close: 1 nil ---- grep_error_log eval -qr/ssl_session_fetch_by_lua_block:1: ssl fetch sess by lua is running!/s +--- grep_error_log eval: qr/ssl_session_fetch_by_lua_block:.*?,|\bssl session fetch: connection reusable: \d+|\breusable connection: \d+/ --- grep_error_log_out eval [ -'', -'ssl_session_fetch_by_lua_block:1: ssl fetch sess by lua is running! -', -'ssl_session_fetch_by_lua_block:1: ssl fetch sess by lua is running! -', +qr/\A(?:reusable connection: [01]\n)+\z/s, +qr/^reusable connection: 1 +ssl session fetch: connection reusable: 1 +reusable connection: 0 +ssl_session_fetch_by_lua_block:1: ssl fetch sess by lua is running!, +/m, +qr/^reusable connection: 1 +ssl session fetch: connection reusable: 1 +reusable connection: 0 +ssl_session_fetch_by_lua_block:1: ssl fetch sess by lua is running!, +/m, ] --- no_error_log diff --git a/debian/modules/http-lua/t/147-tcp-socket-timeouts.t b/debian/modules/http-lua/t/147-tcp-socket-timeouts.t index 0689a9b..8199e84 100644 --- a/debian/modules/http-lua/t/147-tcp-socket-timeouts.t +++ b/debian/modules/http-lua/t/147-tcp-socket-timeouts.t @@ -532,3 +532,96 @@ received: ok failed to receive a line: closed [] --- no_error_log [error] + + + +=== TEST 8: connection timeout overflow detection +--- config + location /t { + content_by_lua_block { + local sock = ngx.socket.tcp() + local ok, err = pcall(sock.settimeouts, sock, + (2 ^ 31) - 1, 500, 500) + if not ok then + ngx.say("failed to set timeouts: ", err) + else + ngx.say("settimeouts: ok") + end + + ok, err = pcall(sock.settimeouts, sock, 2 ^ 31, 500, 500) + if not ok then + ngx.say("failed to set timeouts: ", err) + else + ngx.say("settimeouts: ok") + end + } + } +--- request +GET /t +--- response_body_like +settimeouts: ok +failed to set timeouts: bad timeout value +--- no_error_log +[error] + + + +=== TEST 9: send timeout overflow detection +--- config + location /t { + content_by_lua_block { + local sock = ngx.socket.tcp() + local ok, err = pcall(sock.settimeouts, sock, + 500, (2 ^ 31) - 1, 500) + if not ok then + ngx.say("failed to set timeouts: ", err) + else + ngx.say("settimeouts: ok") + end + + ok, err = pcall(sock.settimeouts, sock, 500, 2 ^ 31, 500) + if not ok then + ngx.say("failed to set timeouts: ", err) + else + ngx.say("settimeouts: ok") + end + } + } +--- request +GET /t +--- response_body_like +settimeouts: ok +failed to set timeouts: bad timeout value +--- no_error_log +[error] + + + +=== TEST 10: read timeout overflow detection +--- config + location /t { + content_by_lua_block { + local sock = ngx.socket.tcp() + local ok, err = pcall(sock.settimeouts, sock, + 500, 500, (2 ^ 31) - 1) + if not ok then + ngx.say("failed to set timeouts: ", err) + else + ngx.say("settimeouts: ok") + end + + ok, err = pcall(sock.settimeouts, sock, 500, 500, 2 ^ 31) + if not ok then + ngx.say("failed to set timeouts: ", err) + else + ngx.say("settimeouts: ok") + end + } + } +--- request +GET /t +--- response_body_like +settimeouts: ok +failed to set timeouts: bad timeout value +--- no_error_log +[error] diff --git a/debian/modules/http-lua/t/154-semaphore.t b/debian/modules/http-lua/t/154-semaphore.t index 3c1f004..875f181 100644 --- a/debian/modules/http-lua/t/154-semaphore.t +++ b/debian/modules/http-lua/t/154-semaphore.t @@ -75,6 +75,7 @@ semaphore gc wait queue is not empty === TEST 2: timer + shutdown error log (lua code cache off) +FIXME: this test case leaks memory. --- http_config lua_code_cache off; --- config @@ -116,3 +117,4 @@ hello, world --- shutdown_error_log --- no_shutdown_error_log semaphore gc wait queue is not empty +--- SKIP diff --git a/debian/modules/http-lua/util/build.sh b/debian/modules/http-lua/util/build.sh index e45c00a..164bf9f 100755 --- a/debian/modules/http-lua/util/build.sh +++ b/debian/modules/http-lua/util/build.sh @@ -23,6 +23,7 @@ force=$2 #--with-http_spdy_module \ time ngx-build $force $version \ + --with-pcre-jit \ --with-ipv6 \ --with-cc-opt="-I$PCRE_INC -I$OPENSSL_INC" \ --with-http_v2_module \ @@ -35,6 +36,8 @@ time ngx-build $force $version \ --without-mail_imap_module \ --with-http_image_filter_module \ --without-mail_smtp_module \ + --with-stream \ + --with-stream_ssl_module \ --without-http_upstream_ip_hash_module \ --without-http_memcached_module \ --without-http_auth_basic_module \ @@ -50,6 +53,7 @@ time ngx-build $force $version \ --add-module=$root/../rds-json-nginx-module \ --add-module=$root/../coolkit-nginx-module \ --add-module=$root/../redis2-nginx-module \ + --add-module=$root/../stream-lua-nginx-module \ --add-module=$root/t/data/fake-module \ --add-module=$root/t/data/fake-shm-module \ --add-module=$root/t/data/fake-delayed-load-module \ diff --git a/debian/modules/http-lua/valgrind.suppress b/debian/modules/http-lua/valgrind.suppress index d0bcc56..7273986 100644 --- a/debian/modules/http-lua/valgrind.suppress +++ b/debian/modules/http-lua/valgrind.suppress @@ -1,16 +1,16 @@ { - -Memcheck:Addr1 -fun:ngx_init_cycle -fun:ngx_master_process_cycle -fun:main + + Memcheck:Addr1 + fun:ngx_init_cycle + fun:ngx_master_process_cycle + fun:main } { - -Memcheck:Addr4 -fun:ngx_init_cycle -fun:ngx_master_process_cycle -fun:main + + Memcheck:Addr4 + fun:ngx_init_cycle + fun:ngx_master_process_cycle + fun:main } { @@ -104,11 +104,11 @@ fun:main fun:ngx_event_process_init } { - - Memcheck:Param - sendmsg(mmsg[0].msg_hdr) - fun:sendmmsg - fun:__libc_res_nsend + + Memcheck:Param + sendmsg(mmsg[0].msg_hdr) + fun:sendmmsg + fun:__libc_res_nsend } { @@ -120,11 +120,11 @@ fun:main fun:ngx_start_cache_manager_processes } { - - Memcheck:Cond - fun:ngx_init_cycle - fun:ngx_master_process_cycle - fun:main + + Memcheck:Cond + fun:ngx_init_cycle + fun:ngx_master_process_cycle + fun:main } { @@ -157,10 +157,36 @@ fun:main fun:ngx_alloc fun:ngx_set_environment fun:ngx_single_process_cycle - fun:main } { Memcheck:Cond obj:* } +{ + + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + fun:ngx_alloc + fun:ngx_set_environment + fun:ngx_worker_process_init +} +{ + + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + fun:ngx_alloc + fun:ngx_create_pool + fun:main +} +{ + + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + fun:ngx_alloc + fun:ngx_set_environment + fun:ngx_single_process_cycle +} diff --git a/debian/modules/patches/http-lua/openssl-1.1.0.patch b/debian/modules/patches/http-lua/openssl-1.1.0.patch index 431031b..4dafce2 100644 --- a/debian/modules/patches/http-lua/openssl-1.1.0.patch +++ b/debian/modules/patches/http-lua/openssl-1.1.0.patch @@ -1,4 +1,4 @@ -From 525d5a550f5f256af01de1264358086a4cd1ac4a Mon Sep 17 00:00:00 2001 +From 47ab0d4eca3fa62403c798d7dfad50a5f9f7215a Mon Sep 17 00:00:00 2001 From: Alessandro Ghedini Date: Tue, 13 Sep 2016 22:31:32 +0100 Subject: [PATCH 1/4] bugfix: ssl: don't use SSLv3 in tests. @@ -11,7 +11,7 @@ tickets set ssl_session_tickets to off instead. 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/t/142-ssl-session-store.t b/t/142-ssl-session-store.t -index 73b6e197..260fe490 100644 +index 825d0163..cc3a664c 100644 --- a/t/142-ssl-session-store.t +++ b/t/142-ssl-session-store.t @@ -32,7 +32,7 @@ __DATA__ @@ -23,7 +23,7 @@ index 73b6e197..260fe490 100644 server_tokens off; } -@@ -102,7 +102,7 @@ ssl_session_store_by_lua_block:1: ssl session store by lua is running! +@@ -107,7 +107,7 @@ ssl_session_store_by_lua_block:1: ssl session store by lua is running!, server_name test.com; ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; @@ -32,7 +32,7 @@ index 73b6e197..260fe490 100644 server_tokens off; } -@@ -177,7 +177,7 @@ API disabled in the context of ssl_session_store_by_lua* +@@ -182,7 +182,7 @@ API disabled in the context of ssl_session_store_by_lua* server_name test.com; ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; @@ -41,7 +41,7 @@ index 73b6e197..260fe490 100644 server_tokens off; } -@@ -267,9 +267,9 @@ my timer run! +@@ -272,9 +272,9 @@ my timer run! listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; server_name test.com; @@ -52,7 +52,7 @@ index 73b6e197..260fe490 100644 server_tokens off; } -@@ -335,9 +335,9 @@ API disabled in the context of ssl_session_store_by_lua* +@@ -340,9 +340,9 @@ API disabled in the context of ssl_session_store_by_lua* server { listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; server_name test.com; @@ -63,7 +63,7 @@ index 73b6e197..260fe490 100644 server_tokens off; } -@@ -407,9 +407,9 @@ ngx.exit does not yield and the error code is eaten. +@@ -412,9 +412,9 @@ ngx.exit does not yield and the error code is eaten. server { listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; server_name test.com; @@ -74,7 +74,7 @@ index 73b6e197..260fe490 100644 server_tokens off; } -@@ -480,9 +480,9 @@ ssl_session_store_by_lua*: handler return value: 0, sess new cb exit code: 0 +@@ -485,9 +485,9 @@ ssl_session_store_by_lua*: handler return value: 0, sess new cb exit code: 0 server { listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; server_name test.com; @@ -85,7 +85,7 @@ index 73b6e197..260fe490 100644 server_tokens off; } -@@ -548,9 +548,9 @@ should never reached here +@@ -553,9 +553,9 @@ should never reached here server { listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; server_name test.com; @@ -96,7 +96,7 @@ index 73b6e197..260fe490 100644 server_tokens off; } -@@ -621,7 +621,7 @@ get_phase: ssl_session_store +@@ -626,7 +626,7 @@ get_phase: ssl_session_store } ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; @@ -105,7 +105,7 @@ index 73b6e197..260fe490 100644 server_tokens off; } -@@ -690,7 +690,7 @@ qr/elapsed in ssl cert by lua: 0.(?:09|1[01])\d+,/, +@@ -695,7 +695,7 @@ qr/elapsed in ssl cert by lua: 0.(?:09|1[01])\d+,/, server_name test.com; ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; @@ -114,7 +114,7 @@ index 73b6e197..260fe490 100644 server_tokens off; } -@@ -760,7 +760,6 @@ a.lua:1: ssl store session by lua is running! +@@ -765,7 +765,6 @@ a.lua:1: ssl store session by lua is running! ssl_session_store_by_lua_block { print("handler in test.com") } @@ -122,7 +122,7 @@ index 73b6e197..260fe490 100644 ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; -@@ -770,7 +769,6 @@ a.lua:1: ssl store session by lua is running! +@@ -775,7 +774,6 @@ a.lua:1: ssl store session by lua is running! server { listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; server_name test.com; @@ -130,7 +130,7 @@ index 73b6e197..260fe490 100644 ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; -@@ -836,7 +834,7 @@ qr/\[emerg\] .*? "ssl_session_store_by_lua_block" directive is not allowed here +@@ -841,7 +839,7 @@ qr/\[emerg\] .*? "ssl_session_store_by_lua_block" directive is not allowed here server_name test.com; ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; @@ -140,7 +140,7 @@ index 73b6e197..260fe490 100644 server_tokens off; } diff --git a/t/143-ssl-session-fetch.t b/t/143-ssl-session-fetch.t -index 701ead72..3626f0fb 100644 +index 7be180f8..4dc992d3 100644 --- a/t/143-ssl-session-fetch.t +++ b/t/143-ssl-session-fetch.t @@ -33,7 +33,7 @@ __DATA__ @@ -152,7 +152,7 @@ index 701ead72..3626f0fb 100644 server_tokens off; } -@@ -114,7 +114,7 @@ qr/ssl_session_fetch_by_lua_block:1: ssl fetch sess by lua is running!/s +@@ -119,7 +119,7 @@ ssl_session_fetch_by_lua_block:1: ssl fetch sess by lua is running!, server_name test.com; ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; @@ -161,7 +161,7 @@ index 701ead72..3626f0fb 100644 server_tokens off; } -@@ -198,7 +198,7 @@ qr/elapsed in ssl fetch session by lua: 0.(?:09|1[01])\d+,/, +@@ -203,7 +203,7 @@ qr/elapsed in ssl fetch session by lua: 0.(?:09|1[01])\d+,/, server_name test.com; ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; @@ -170,7 +170,7 @@ index 701ead72..3626f0fb 100644 server_tokens off; } -@@ -297,9 +297,9 @@ qr/my timer run!/s +@@ -302,9 +302,9 @@ qr/my timer run!/s server { listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; server_name test.com; @@ -181,7 +181,7 @@ index 701ead72..3626f0fb 100644 server_tokens off; } -@@ -377,9 +377,9 @@ qr/received memc reply: OK/s +@@ -382,9 +382,9 @@ qr/received memc reply: OK/s server { listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; server_name test.com; @@ -192,7 +192,7 @@ index 701ead72..3626f0fb 100644 server_tokens off; } -@@ -458,9 +458,9 @@ should never reached here +@@ -463,9 +463,9 @@ should never reached here server { listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; server_name test.com; @@ -203,7 +203,7 @@ index 701ead72..3626f0fb 100644 server_tokens off; } -@@ -540,9 +540,9 @@ should never reached here +@@ -545,9 +545,9 @@ should never reached here server { listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; server_name test.com; @@ -214,7 +214,7 @@ index 701ead72..3626f0fb 100644 server_tokens off; } -@@ -621,9 +621,9 @@ should never reached here +@@ -626,9 +626,9 @@ should never reached here server { listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; server_name test.com; @@ -225,7 +225,7 @@ index 701ead72..3626f0fb 100644 server_tokens off; } -@@ -704,9 +704,9 @@ should never reached here +@@ -709,9 +709,9 @@ should never reached here server { listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; server_name test.com; @@ -236,7 +236,7 @@ index 701ead72..3626f0fb 100644 server_tokens off; } -@@ -787,7 +787,7 @@ should never reached here +@@ -792,7 +792,7 @@ should never reached here server_name test.com; ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; @@ -245,7 +245,7 @@ index 701ead72..3626f0fb 100644 server_tokens off; } -@@ -872,7 +872,7 @@ qr/get_phase: ssl_session_fetch/s +@@ -877,7 +877,7 @@ qr/get_phase: ssl_session_fetch/s } ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; @@ -254,7 +254,7 @@ index 701ead72..3626f0fb 100644 server_tokens off; } -@@ -956,7 +956,7 @@ ssl store session by lua is running! +@@ -961,7 +961,7 @@ ssl store session by lua is running! server_name test.com; ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; @@ -263,7 +263,7 @@ index 701ead72..3626f0fb 100644 server_tokens off; } -@@ -1036,7 +1036,7 @@ qr/\S+:\d+: ssl fetch sess by lua is running!/s +@@ -1041,7 +1041,7 @@ qr/\S+:\d+: ssl fetch sess by lua is running!/s server_name test.com; ssl_certificate $TEST_NGINX_CERT_DIR/cert/test.crt; ssl_certificate_key $TEST_NGINX_CERT_DIR/cert/test.key; @@ -273,10 +273,10 @@ index 701ead72..3626f0fb 100644 server_tokens off; } -- -2.14.1 +2.15.1 -From d308b44b3daf7702d9218e2a5620a89a5eca8389 Mon Sep 17 00:00:00 2001 +From 5cb24ce5eccd580d1bd6a2c44d7ea3cef5ad7740 Mon Sep 17 00:00:00 2001 From: Alessandro Ghedini Date: Thu, 12 May 2016 13:12:23 +0100 Subject: [PATCH 2/4] bugfix: ssl: do not access SSL_SESSION struct directly. @@ -288,10 +288,10 @@ In OpenSSL 1.1.0 it was made opaque. 2 files changed, 80 insertions(+), 83 deletions(-) diff --git a/src/ngx_http_lua_socket_tcp.c b/src/ngx_http_lua_socket_tcp.c -index 382a94de..07164746 100644 +index f0988bc5..17d3db2e 100644 --- a/src/ngx_http_lua_socket_tcp.c +++ b/src/ngx_http_lua_socket_tcp.c -@@ -1316,9 +1316,8 @@ ngx_http_lua_socket_tcp_sslhandshake(lua_State *L) +@@ -1320,9 +1320,8 @@ ngx_http_lua_socket_tcp_sslhandshake(lua_State *L) return 2; } @@ -303,7 +303,7 @@ index 382a94de..07164746 100644 } } -@@ -1583,9 +1582,8 @@ ngx_http_lua_ssl_handshake_retval_handler(ngx_http_request_t *r, +@@ -1587,9 +1586,8 @@ ngx_http_lua_ssl_handshake_retval_handler(ngx_http_request_t *r, } else { *ud = ssl_session; @@ -315,7 +315,7 @@ index 382a94de..07164746 100644 /* set up the __gc metamethod */ lua_pushlightuserdata(L, &ngx_http_lua_ssl_session_metatable_key); -@@ -5365,9 +5363,8 @@ ngx_http_lua_ssl_free_session(lua_State *L) +@@ -5386,9 +5384,8 @@ ngx_http_lua_ssl_free_session(lua_State *L) psession = lua_touserdata(L, 1); if (psession && *psession != NULL) { @@ -328,7 +328,7 @@ index 382a94de..07164746 100644 ngx_ssl_free_session(*psession); } diff --git a/t/129-ssl-socket.t b/t/129-ssl-socket.t -index 1c3f7cd0..0cd1f52f 100644 +index e7447a7c..c4bce9e0 100644 --- a/t/129-ssl-socket.t +++ b/t/129-ssl-socket.t @@ -108,10 +108,10 @@ sent http request: 59 bytes. @@ -714,10 +714,10 @@ index 1c3f7cd0..0cd1f52f 100644 --- error_log lua ssl certificate verify error: (18: self signed certificate) -- -2.14.1 +2.15.1 -From 473c121668c658140dffdbeb70aa7df1fc48d2a7 Mon Sep 17 00:00:00 2001 +From 567bca126f4b9e71fbf9d473e85b975f190dcd3c Mon Sep 17 00:00:00 2001 From: Alessandro Ghedini Date: Fri, 10 Jun 2016 13:23:21 +0100 Subject: [PATCH 3/4] bugfix: ssl: do not access SSL struct directly for @@ -745,10 +745,10 @@ index 31b4f243..9ec8b509 100644 return NGX_DECLINED; } -- -2.14.1 +2.15.1 -From 44988918835b8b41e51e75c1618250a560bc11ca Mon Sep 17 00:00:00 2001 +From 840ad10b8447f9ea1f0ddede344916d423029e67 Mon Sep 17 00:00:00 2001 From: Alessandro Ghedini Date: Tue, 13 Sep 2016 22:19:10 +0100 Subject: [PATCH 4/4] bugfix: ssl: make SSL session callback build with OpenSSL @@ -761,7 +761,7 @@ Subject: [PATCH 4/4] bugfix: ssl: make SSL session callback build with OpenSSL 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/ngx_http_lua_ssl_session_fetchby.c b/src/ngx_http_lua_ssl_session_fetchby.c -index 556b7320..5289cb92 100644 +index 3a3c1f54..2c75f6a9 100644 --- a/src/ngx_http_lua_ssl_session_fetchby.c +++ b/src/ngx_http_lua_ssl_session_fetchby.c @@ -171,8 +171,11 @@ ngx_http_lua_ssl_sess_fetch_by_lua(ngx_conf_t *cf, ngx_command_t *cmd, @@ -778,7 +778,7 @@ index 556b7320..5289cb92 100644 { lua_State *L; ngx_int_t rc; -@@ -284,7 +287,7 @@ ngx_http_lua_ssl_sess_fetch_handler(ngx_ssl_conn_t *ssl_conn, u_char *id, +@@ -287,7 +290,7 @@ ngx_http_lua_ssl_sess_fetch_handler(ngx_ssl_conn_t *ssl_conn, u_char *id, cctx->exit_code = 1; /* successful by default */ cctx->connection = c; cctx->request = r; @@ -805,7 +805,7 @@ index 5a6f96f5..50c6616d 100644 diff --git a/src/ngx_http_lua_ssl_session_storeby.c b/src/ngx_http_lua_ssl_session_storeby.c -index bae8273d..dc1fad9b 100644 +index f83e85d9..ce832ea1 100644 --- a/src/ngx_http_lua_ssl_session_storeby.c +++ b/src/ngx_http_lua_ssl_session_storeby.c @@ -172,6 +172,8 @@ int @@ -817,7 +817,7 @@ index bae8273d..dc1fad9b 100644 lua_State *L; ngx_int_t rc; ngx_connection_t *c, *fc = NULL; -@@ -246,11 +248,13 @@ ngx_http_lua_ssl_sess_store_handler(ngx_ssl_conn_t *ssl_conn, +@@ -247,11 +249,13 @@ ngx_http_lua_ssl_sess_store_handler(ngx_ssl_conn_t *ssl_conn, } } @@ -834,5 +834,5 @@ index bae8273d..dc1fad9b 100644 dd("setting cctx"); -- -2.14.1 +2.15.1 From 72b4f71671c9f87f63be9db63f7f821c41aead92 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Wed, 13 Dec 2017 11:23:07 +0200 Subject: [PATCH 234/600] http-dav-ext: Upgrade to 0.1.0 Closes: #878611 --- debian/modules/control | 3 +- debian/modules/http-dav-ext/LICENSE | 22 ++++++++++ debian/modules/http-dav-ext/README | 29 ------------- debian/modules/http-dav-ext/README.rst | 41 +++++++++++++++++++ debian/modules/http-dav-ext/config | 19 ++++++--- .../http-dav-ext/ngx_http_dav_ext_module.c | 9 ++-- .../patches/http-dav-ext/dynamic-module.patch | 41 ------------------- debian/modules/patches/http-dav-ext/series | 1 - 8 files changed, 83 insertions(+), 82 deletions(-) create mode 100644 debian/modules/http-dav-ext/LICENSE delete mode 100644 debian/modules/http-dav-ext/README create mode 100644 debian/modules/http-dav-ext/README.rst delete mode 100644 debian/modules/patches/http-dav-ext/dynamic-module.patch delete mode 100644 debian/modules/patches/http-dav-ext/series diff --git a/debian/modules/control b/debian/modules/control index bd7cc0a..6552957 100644 --- a/debian/modules/control +++ b/debian/modules/control @@ -50,8 +50,7 @@ Patch: Module: http-dav-ext Homepage: https://github.com/arut/nginx-dav-ext-module -Version: v0.0.3 -Patch: dynamic-module.patch +Version: v0.1.0 Module: http-fancyindex Homepage: https://github.com/aperezdc/ngx-fancyindex diff --git a/debian/modules/http-dav-ext/LICENSE b/debian/modules/http-dav-ext/LICENSE new file mode 100644 index 0000000..7be3135 --- /dev/null +++ b/debian/modules/http-dav-ext/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2012-2017, Roman Arutyunyan +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright 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 THE COPYRIGHT HOLDERS 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 THE COPYRIGHT OWNER 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) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/debian/modules/http-dav-ext/README b/debian/modules/http-dav-ext/README deleted file mode 100644 index bc727ff..0000000 --- a/debian/modules/http-dav-ext/README +++ /dev/null @@ -1,29 +0,0 @@ -== nginx-dav-ext-module == - -NGINX WebDAV missing commands support (PROPFIND & OPTIONS) - -(c) 2012 Arutyunyan Roman (arut@qip.ru) - - -For full WebDAV support in NGINX you need to turn on standard NGINX -WebDAV module (providing partial WebDAV implementation) as well as -this module for missing methods - -./configure --with-http_dav_module --add-module= - - - -Requirements: - - libexpat-dev - - -Example config: - - location / { - - dav_methods PUT DELETE MKCOL COPY MOVE; - dav_ext_methods PROPFIND OPTIONS; - - root /var/root/; - } diff --git a/debian/modules/http-dav-ext/README.rst b/debian/modules/http-dav-ext/README.rst new file mode 100644 index 0000000..91c10e3 --- /dev/null +++ b/debian/modules/http-dav-ext/README.rst @@ -0,0 +1,41 @@ +******************** +nginx-dav-ext-module +******************** + +NGINX WebDAV missing commands support (PROPFIND & OPTIONS) + +Copyright |copy| 2012-2017 Arutyunyan Roman (arutyunyan.roman@gmail.com) + +.. |copy| unicode:: U+000A9 .. COPYRIGHT SIGN + +For full WebDAV support in NGINX you need to enable the standard NGINX +WebDAV module (providing partial WebDAV implementation) as well as +this module for missing methods: + +.. code-block:: bash + + $ ./configure --with-http_dav_module --add-module=/path/to/this-module + +The module can be built dynamically: + +.. code-block:: bash + + $ ./configure --with-http_dav_module --add-dynamic-module=/path/to/this-module + +Requirements +============ + +``libexpat-dev`` + + +Example config +============== + +.. code-block:: + + location / { + dav_methods PUT DELETE MKCOL COPY MOVE; + dav_ext_methods PROPFIND OPTIONS; + + root /var/root/; + } diff --git a/debian/modules/http-dav-ext/config b/debian/modules/http-dav-ext/config index 98b2b7a..372620b 100644 --- a/debian/modules/http-dav-ext/config +++ b/debian/modules/http-dav-ext/config @@ -1,9 +1,16 @@ -ngx_addon_name="ngx_http_dav_ext_module" +ngx_addon_name=ngx_http_dav_ext_module -HTTP_MODULES="$HTTP_MODULES \ - ngx_http_dav_ext_module" +if [ -f auto/module ] ; then -NGX_ADDON_SRCS="$NGX_ADDON_SRCS \ - $ngx_addon_dir/ngx_http_dav_ext_module.c" + ngx_module_type=HTTP + ngx_module_name=ngx_http_dav_ext_module + ngx_module_libs=-lexpat + ngx_module_srcs="$ngx_addon_dir/ngx_http_dav_ext_module.c" -CORE_LIBS="$CORE_LIBS -lexpat" + . auto/module + +else + HTTP_MODULES="$HTTP_MODULES ngx_http_dav_ext_module" + NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_dav_ext_module.c" + CORE_LIBS="$CORE_LIBS -lexpat" +fi diff --git a/debian/modules/http-dav-ext/ngx_http_dav_ext_module.c b/debian/modules/http-dav-ext/ngx_http_dav_ext_module.c index 73d86de..ae75fc3 100644 --- a/debian/modules/http-dav-ext/ngx_http_dav_ext_module.c +++ b/debian/modules/http-dav-ext/ngx_http_dav_ext_module.c @@ -1,5 +1,5 @@ /****************************************************************************** - Copyright (c) 2012, Roman Arutyunyan (arut@qip.ru) + Copyright (c) 2012-2017, Roman Arutyunyan (arutyunyan.roman@gmail.com) All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -535,9 +535,12 @@ ngx_http_dav_ext_send_propfind(ngx_http_request_t *r) u_char *p, *uc; if (ngx_http_variable_unknown_header(&vv, &depth_name, - &r->headers_in.headers.part, 0) == NGX_OK - && vv.valid) + &r->headers_in.headers.part, 0) != NGX_OK) { + return NGX_ERROR; + } + + if (!vv.not_found) { if (vv.len == sizeof("infinity") -1 && !ngx_strncasecmp(vv.data, (u_char*)"infinity", vv.len)) { diff --git a/debian/modules/patches/http-dav-ext/dynamic-module.patch b/debian/modules/patches/http-dav-ext/dynamic-module.patch deleted file mode 100644 index c865460..0000000 --- a/debian/modules/patches/http-dav-ext/dynamic-module.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0473d8d1bb63a14afe608ecf46bfc933234e3048 Mon Sep 17 00:00:00 2001 -From: Florian Kinder -Date: Fri, 28 Oct 2016 13:34:21 +0200 -Subject: [PATCH] Added dynamic module support -Origin: other, https://github.com/Fank/nginx-dav-ext-module/pull/1 - ---- - config | 22 +++++++++++++++++----- - 1 file changed, 17 insertions(+), 5 deletions(-) - -diff --git a/config b/config -index 98b2b7a..b6b65de 100644 ---- a/config -+++ b/config -@@ -1,9 +1,21 @@ - ngx_addon_name="ngx_http_dav_ext_module" - --HTTP_MODULES="$HTTP_MODULES \ -- ngx_http_dav_ext_module" - --NGX_ADDON_SRCS="$NGX_ADDON_SRCS \ -- $ngx_addon_dir/ngx_http_dav_ext_module.c" -+if test -n "$ngx_module_link"; then -+ ngx_module_type=HTTP -+ ngx_module_name=ngx_http_dav_ext_module -+ ngx_module_incs= -+ ngx_module_deps= -+ ngx_module_srcs="$ngx_addon_dir/ngx_http_dav_ext_module.c" -+ ngx_module_libs="-lexpat" -+ -+ . auto/module -+else -+ CORE_LIBS="$CORE_LIBS -lexpat" - --CORE_LIBS="$CORE_LIBS -lexpat" -+ HTTP_MODULES="$HTTP_MODULES \ -+ ngx_http_dav_ext_module" -+ -+ NGX_ADDON_SRCS="$NGX_ADDON_SRCS \ -+ $ngx_addon_dir/ngx_http_dav_ext_module.c" -+fi diff --git a/debian/modules/patches/http-dav-ext/series b/debian/modules/patches/http-dav-ext/series deleted file mode 100644 index f9b9360..0000000 --- a/debian/modules/patches/http-dav-ext/series +++ /dev/null @@ -1 +0,0 @@ -dynamic-module.patch From ee4b10edd7fc48819c2c5debcbd422af70bcd406 Mon Sep 17 00:00:00 2001 From: Christos Trochalakis Date: Wed, 13 Dec 2017 11:23:19 +0200 Subject: [PATCH 235/600] http-fancyindex: Upgrade to 0.4.2 --- debian/modules/control | 2 +- debian/modules/http-fancyindex/CHANGELOG.md | 21 ++++++- debian/modules/http-fancyindex/README.rst | 32 ++++++++-- .../ngx_http_fancyindex_module.c | 60 +++++++------------ .../http-fancyindex/t/03-exact_size_off.test | 8 +++ .../t/bug61-empty-file-segfault.test | 16 +++++ debian/modules/http-fancyindex/t/run | 2 +- debian/modules/http-fancyindex/template.h | 25 +++----- debian/modules/http-fancyindex/template.html | 25 +++----- 9 files changed, 110 insertions(+), 81 deletions(-) create mode 100644 debian/modules/http-fancyindex/t/03-exact_size_off.test create mode 100644 debian/modules/http-fancyindex/t/bug61-empty-file-segfault.test diff --git a/debian/modules/control b/debian/modules/control index 6552957..a0aa9ba 100644 --- a/debian/modules/control +++ b/debian/modules/control @@ -54,7 +54,7 @@ Version: v0.1.0 Module: http-fancyindex Homepage: https://github.com/aperezdc/ngx-fancyindex -Version: v0.4.1 +Version: v0.4.2 Files-Excluded: .gitignore .travis.yml Module: http-subs-filter diff --git a/debian/modules/http-fancyindex/CHANGELOG.md b/debian/modules/http-fancyindex/CHANGELOG.md index 9d76ae0..6acc50f 100644 --- a/debian/modules/http-fancyindex/CHANGELOG.md +++ b/debian/modules/http-fancyindex/CHANGELOG.md @@ -3,6 +3,24 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +## [0.4.2] - 2017-08-19 +### Changed +- Generated HTML from the default template is now proper HTML5, and it should + pass validation (#52). +- File sizes now have decimal positions when using `fancyindex_exact_size off`. + (Patch by Anders Trier <>.) +- Multiple updates to `README.rst` (Patches by Danila Vershinin + <>, Iulian Onofrei, Lilian Besson, and Nick Geoghegan + <>.) + +### Fixed +- Sorting by file size now also works correctly for directories which contain + files of sizes bigger than `INT_MAX`. (#74, fix suggestion by Chris Young.) +- Custom headers which fail to declare an UTF-8 encoding no longer cause table + header arrows to be rendered incorrectly by browsers (#50). +- Fix segmentation fault when opening directories with empty files (#61, patch + by Catgirl <>.) + ## [0.4.1] - 2016-08-18 ### Added - New `fancyindex_directories_first` configuration directive (enabled by @@ -100,7 +118,8 @@ All notable changes to this project will be documented in this file. - `NEWS.rst` file, to act as change log. -[Unreleased]: https://github.com/aperezdc/ngx-fancyindex/compare/v0.4.1...HEAD +[Unreleased]: https://github.com/aperezdc/ngx-fancyindex/compare/v0.4.2...HEAD +[0.4.2]: https://github.com/aperezdc/ngx-fancyindex/compare/v0.4.1...v0.4.2 [0.4.1]: https://github.com/aperezdc/ngx-fancyindex/compare/v0.4.0...v0.4.1 [0.4.0]: https://github.com/aperezdc/ngx-fancyindex/compare/v0.3.6...v0.4.0 [0.3.6]: https://github.com/aperezdc/ngx-fancyindex/compare/v0.3.5...v0.3.6 diff --git a/debian/modules/http-fancyindex/README.rst b/debian/modules/http-fancyindex/README.rst index 93a8206..0e3273c 100644 --- a/debian/modules/http-fancyindex/README.rst +++ b/debian/modules/http-fancyindex/README.rst @@ -26,7 +26,27 @@ server written by `Igor Sysoev `__. Requirements ============ -You will need the sources for Nginx_. Any version starting from the 0.7 +CentOS 7 +~~~~~~~~ + +For users of the `official stable `__ Nginx repository, `extra packages repository with dynamic modules `__ is available and fancyindex is included. + +Install directly:: + + yum install https://extras.getpagespeed.com/redhat/7/x86_64/RPMS/nginx-module-fancyindex-1.12.0.0.4.1-1.el7.gps.x86_64.rpm + +Alternatively, add extras repository first (for future updates) and install the module:: + + yum install nginx-module-fancyindex + +Then load the module in `/etc/nginx/nginx.conf` using + + load_module "modules/ngx_http_fancyindex_module.so"; + +Other platforms +~~~~~~~~~~~~~~~ + +In most other cases you will need the sources for Nginx_. Any version starting from the 0.7 series onwards will work. Note that the modules *might* compile with versions in the 0.6 series by applying ``nginx-0.6-support.patch``, but this is unsupported (YMMV). @@ -58,7 +78,8 @@ Building Since version 0.4.0, the module can also be built as a `dynamic module `_, - using ``--add-dynamic-module=…`` instead. + using ``--add-dynamic-module=…`` instead and ``load_module "modules/ngx_http_fancyindex_module.so";` + in the configuration file 4. Build and install the software:: @@ -92,10 +113,9 @@ achieved using the module: * `Theme `__ by `@TheInsomniac `__. Uses custom header and footer. -* `Theme `__ by - nwrd `__. Uses custom header and footer, the - header includes search field to filter by filename using JavaScript - (`demo `__). +* `Theme `__ by + `Naereen `__. Uses custom header and footer, the + header includes search field to filter by filename using JavaScript. Directives diff --git a/debian/modules/http-fancyindex/ngx_http_fancyindex_module.c b/debian/modules/http-fancyindex/ngx_http_fancyindex_module.c index 170167d..10331a5 100644 --- a/debian/modules/http-fancyindex/ngx_http_fancyindex_module.c +++ b/debian/modules/http-fancyindex/ngx_http_fancyindex_module.c @@ -190,6 +190,10 @@ static ngx_conf_enum_t ngx_http_fancyindex_sort_criteria[] = { */ #define ngx_sizeof_ssz(_s) (sizeof(_s) - 1) +/** + * Compute the length of a statically allocated array + */ +#define DIM(x) (sizeof(x)/sizeof(*(x))) /** * Copy a static zero-terminated string. Useful to output template @@ -552,16 +556,20 @@ make_content_buf( off_t length; size_t len, root, copy, allocated; - u_char *filename, *last, scale; + int64_t multiplier; + u_char *filename, *last; ngx_tm_t tm; ngx_array_t entries; ngx_time_t *tp; - ngx_uint_t i; - ngx_int_t size; + ngx_uint_t i, j; ngx_str_t path; ngx_dir_t dir; ngx_buf_t *b; + static const char *sizes[] = { "EiB", "PiB", "TiB", "GiB", "MiB", "KiB", "B" }; + static const int64_t exbibyte = 1024LL * 1024LL * 1024LL * + 1024LL * 1024LL * 1024LL; + /* * NGX_DIR_MASK_LEN is lesser than NGX_HTTP_FANCYINDEX_PREALLOCATE */ @@ -982,41 +990,17 @@ make_content_buf( *b->last++ = '-'; } else { length = entry[i].size; + multiplier = exbibyte; - if (length > 1024 * 1024 * 1024 - 1) { - size = (ngx_int_t) (length / (1024 * 1024 * 1024)); - if ((length % (1024 * 1024 * 1024)) - > (1024 * 1024 * 1024 / 2 - 1)) - { - size++; - } - scale = 'G'; + for (j = 0; j < DIM(sizes) - 1 && length < multiplier; j++) + multiplier /= 1024; - } else if (length > 1024 * 1024 - 1) { - size = (ngx_int_t) (length / (1024 * 1024)); - if ((length % (1024 * 1024)) > (1024 * 1024 / 2 - 1)) { - size++; - } - scale = 'M'; - - } else if (length > 9999) { - size = (ngx_int_t) (length / 1024); - if (length % 1024 > 511) { - size++; - } - scale = 'K'; - - } else { - size = (ngx_int_t) length; - scale = '\0'; - } - - if (scale) { - b->last = ngx_sprintf(b->last, "%6i%c", size, scale); - - } else { - b->last = ngx_sprintf(b->last, " %6i", size); - } + /* If we are showing the filesize in bytes, do not show a decimal */ + if (j == DIM(sizes) - 1) + b->last = ngx_sprintf(b->last, "%O %s", length, sizes[j]); + else + b->last = ngx_sprintf(b->last, "%.1f %s", + (float) length / multiplier, sizes[j]); } } @@ -1245,7 +1229,7 @@ ngx_http_fancyindex_cmp_entries_size_desc(const void *one, const void *two) ngx_http_fancyindex_entry_t *first = (ngx_http_fancyindex_entry_t *) one; ngx_http_fancyindex_entry_t *second = (ngx_http_fancyindex_entry_t *) two; - return (int) (second->size - first->size); + return (first->size > second->size) - (first->size < second->size); } @@ -1275,7 +1259,7 @@ ngx_http_fancyindex_cmp_entries_size_asc(const void *one, const void *two) ngx_http_fancyindex_entry_t *first = (ngx_http_fancyindex_entry_t *) one; ngx_http_fancyindex_entry_t *second = (ngx_http_fancyindex_entry_t *) two; - return (int) (first->size - second->size); + return (first->size > second->size) - (first->size < second->size); } diff --git a/debian/modules/http-fancyindex/t/03-exact_size_off.test b/debian/modules/http-fancyindex/t/03-exact_size_off.test new file mode 100644 index 0000000..cdc61ec --- /dev/null +++ b/debian/modules/http-fancyindex/t/03-exact_size_off.test @@ -0,0 +1,8 @@ +#! /bin/bash +cat <<--- +We test if the output from using "fancyindex_exact_size off" looks sane +-- +nginx_start 'fancyindex_exact_size off;' +content=$(fetch) +grep -e '[1-9]\.[0-9] KiB' <<< "${content}" +grep -E '[0-9]+ B' <<< "${content}" diff --git a/debian/modules/http-fancyindex/t/bug61-empty-file-segfault.test b/debian/modules/http-fancyindex/t/bug61-empty-file-segfault.test new file mode 100644 index 0000000..d9c5a40 --- /dev/null +++ b/debian/modules/http-fancyindex/t/bug61-empty-file-segfault.test @@ -0,0 +1,16 @@ +#! /bin/bash +cat <<--- +Bug #61: Listing a directory with an empty file crashes Nginx +https://github.com/aperezdc/ngx-fancyindex/issues/61 +-- + +# Prepare an empty directory with an empty file +mkdir -p "${TESTDIR}/bug61" +touch "${TESTDIR}/bug61/bug61.txt" + +nginx_start 'fancyindex_exact_size off;' +content=$(fetch /bug61/) +test -n "${content}" || fail "Empty response" +echo "Response:" +echo "${content}" +nginx_is_running || fail "Nginx died" diff --git a/debian/modules/http-fancyindex/t/run b/debian/modules/http-fancyindex/t/run index 2001bff..dda4c59 100755 --- a/debian/modules/http-fancyindex/t/run +++ b/debian/modules/http-fancyindex/t/run @@ -26,7 +26,7 @@ readonly dynamic declare -a t_pass=( ) declare -a t_fail=( ) -for t in "$T"/*.test ; do +for t in `ls "$T"/*.test | sort -R` ; do name="t/${t##*/}" name=${name%.test} printf "${name} ... " diff --git a/debian/modules/http-fancyindex/template.h b/debian/modules/http-fancyindex/template.h index 4881ac7..e08ba01 100644 --- a/debian/modules/http-fancyindex/template.h +++ b/debian/modules/http-fancyindex/template.h @@ -1,12 +1,10 @@ /* Automagically generated, do not edit! */ static const u_char t01_head1[] = "" -"" -"\n" -"" -"\n" +"" +"" "" -"" -"" +"" +"" " diff --git a/html/index.html b/html/index.html index 2ca3b95..e8f5622 100644 --- a/html/index.html +++ b/html/index.html @@ -3,11 +3,9 @@ Welcome to nginx! diff --git a/src/core/nginx.h b/src/core/nginx.h index 7b873a1..329b603 100644 --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1020002 -#define NGINX_VERSION "1.20.2" +#define nginx_version 1022000 +#define NGINX_VERSION "1.22.0" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD diff --git a/src/core/ngx_buf.h b/src/core/ngx_buf.h index 4b66562..fdcd0cd 100644 --- a/src/core/ngx_buf.h +++ b/src/core/ngx_buf.h @@ -90,9 +90,6 @@ struct ngx_output_chain_ctx_s { #if (NGX_HAVE_FILE_AIO || NGX_COMPAT) ngx_output_chain_aio_pt aio_handler; -#if (NGX_HAVE_AIO_SENDFILE || NGX_COMPAT) - ssize_t (*aio_preload)(ngx_buf_t *file); -#endif #endif #if (NGX_THREADS || NGX_COMPAT) diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c index 8339e2b..fe729a7 100644 --- a/src/core/ngx_connection.c +++ b/src/core/ngx_connection.c @@ -495,21 +495,24 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle) return NGX_ERROR; } - if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, - (const void *) &reuseaddr, sizeof(int)) - == -1) - { - ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, - "setsockopt(SO_REUSEADDR) %V failed", - &ls[i].addr_text); + if (ls[i].type != SOCK_DGRAM || !ngx_test_config) { - if (ngx_close_socket(s) == -1) { + if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, + (const void *) &reuseaddr, sizeof(int)) + == -1) + { ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, - ngx_close_socket_n " %V failed", + "setsockopt(SO_REUSEADDR) %V failed", &ls[i].addr_text); - } - return NGX_ERROR; + if (ngx_close_socket(s) == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, + ngx_close_socket_n " %V failed", + &ls[i].addr_text); + } + + return NGX_ERROR; + } } #if (NGX_HAVE_REUSEPORT) diff --git a/src/core/ngx_connection.h b/src/core/ngx_connection.h index 4716da4..8cc1475 100644 --- a/src/core/ngx_connection.h +++ b/src/core/ngx_connection.h @@ -185,7 +185,7 @@ struct ngx_connection_s { unsigned need_last_buf:1; -#if (NGX_HAVE_AIO_SENDFILE || NGX_COMPAT) +#if (NGX_HAVE_SENDFILE_NODISKIO || NGX_COMPAT) unsigned busy_count:2; #endif diff --git a/src/core/ngx_hash.c b/src/core/ngx_hash.c index d9c157c..8215c27 100644 --- a/src/core/ngx_hash.c +++ b/src/core/ngx_hash.c @@ -274,6 +274,10 @@ ngx_hash_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names, ngx_uint_t nelts) } for (n = 0; n < nelts; n++) { + if (names[n].key.data == NULL) { + continue; + } + if (hinit->bucket_size < NGX_HASH_ELT_SIZE(&names[n]) + sizeof(void *)) { ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0, diff --git a/src/core/ngx_module.h b/src/core/ngx_module.h index 8cf3210..6fb4554 100644 --- a/src/core/ngx_module.h +++ b/src/core/ngx_module.h @@ -41,7 +41,7 @@ #define NGX_MODULE_SIGNATURE_3 "0" #endif -#if (NGX_HAVE_AIO_SENDFILE || NGX_COMPAT) +#if (NGX_HAVE_SENDFILE_NODISKIO || NGX_COMPAT) #define NGX_MODULE_SIGNATURE_4 "1" #else #define NGX_MODULE_SIGNATURE_4 "0" diff --git a/src/core/ngx_output_chain.c b/src/core/ngx_output_chain.c index 5c3dbe8..8570742 100644 --- a/src/core/ngx_output_chain.c +++ b/src/core/ngx_output_chain.c @@ -29,10 +29,6 @@ static ngx_inline ngx_int_t ngx_output_chain_as_is(ngx_output_chain_ctx_t *ctx, ngx_buf_t *buf); -#if (NGX_HAVE_AIO_SENDFILE) -static ngx_int_t ngx_output_chain_aio_setup(ngx_output_chain_ctx_t *ctx, - ngx_file_t *file); -#endif static ngx_int_t ngx_output_chain_add_copy(ngx_pool_t *pool, ngx_chain_t **chain, ngx_chain_t *in); static ngx_int_t ngx_output_chain_align_file_buf(ngx_output_chain_ctx_t *ctx, @@ -260,10 +256,6 @@ ngx_output_chain_as_is(ngx_output_chain_ctx_t *ctx, ngx_buf_t *buf) } #endif - if (buf->in_file && buf->file->directio) { - return 0; - } - sendfile = ctx->sendfile; #if (NGX_SENDFILE_LIMIT) @@ -272,6 +264,19 @@ ngx_output_chain_as_is(ngx_output_chain_ctx_t *ctx, ngx_buf_t *buf) sendfile = 0; } +#endif + +#if !(NGX_HAVE_SENDFILE_NODISKIO) + + /* + * With DIRECTIO, disable sendfile() unless sendfile(SF_NOCACHE) + * is available. + */ + + if (buf->in_file && buf->file->directio) { + sendfile = 0; + } + #endif if (!sendfile) { @@ -283,12 +288,6 @@ ngx_output_chain_as_is(ngx_output_chain_ctx_t *ctx, ngx_buf_t *buf) buf->in_file = 0; } -#if (NGX_HAVE_AIO_SENDFILE) - if (ctx->aio_preload && buf->in_file) { - (void) ngx_output_chain_aio_setup(ctx, buf->file); - } -#endif - if (ctx->need_in_memory && !ngx_buf_in_memory(buf)) { return 0; } @@ -301,28 +300,6 @@ ngx_output_chain_as_is(ngx_output_chain_ctx_t *ctx, ngx_buf_t *buf) } -#if (NGX_HAVE_AIO_SENDFILE) - -static ngx_int_t -ngx_output_chain_aio_setup(ngx_output_chain_ctx_t *ctx, ngx_file_t *file) -{ - ngx_event_aio_t *aio; - - if (file->aio == NULL && ngx_file_aio_init(file, ctx->pool) != NGX_OK) { - return NGX_ERROR; - } - - aio = file->aio; - - aio->data = ctx->filter_ctx; - aio->preload_handler = ctx->aio_preload; - - return NGX_OK; -} - -#endif - - static ngx_int_t ngx_output_chain_add_copy(ngx_pool_t *pool, ngx_chain_t **chain, ngx_chain_t *in) @@ -803,6 +780,10 @@ ngx_chain_writer(void *data, ngx_chain_t *in) return NGX_ERROR; } + if (chain && c->write->ready) { + ngx_post_event(c->write, &ngx_posted_next_events); + } + for (cl = ctx->out; cl && cl != chain; /* void */) { ln = cl; cl = cl->next; diff --git a/src/core/ngx_rbtree.h b/src/core/ngx_rbtree.h index 97f0e3e..e8c3582 100644 --- a/src/core/ngx_rbtree.h +++ b/src/core/ngx_rbtree.h @@ -47,6 +47,9 @@ struct ngx_rbtree_s { (tree)->sentinel = s; \ (tree)->insert = i +#define ngx_rbtree_data(node, type, link) \ + (type *) ((u_char *) (node) - offsetof(type, link)) + void ngx_rbtree_insert(ngx_rbtree_t *tree, ngx_rbtree_node_t *node); void ngx_rbtree_delete(ngx_rbtree_t *tree, ngx_rbtree_node_t *node); diff --git a/src/core/ngx_regex.c b/src/core/ngx_regex.c index 52169f6..bebf3b6 100644 --- a/src/core/ngx_regex.c +++ b/src/core/ngx_regex.c @@ -10,15 +10,22 @@ typedef struct { - ngx_flag_t pcre_jit; + ngx_flag_t pcre_jit; + ngx_list_t *studies; } ngx_regex_conf_t; +static ngx_inline void ngx_regex_malloc_init(ngx_pool_t *pool); +static ngx_inline void ngx_regex_malloc_done(void); + +#if (NGX_PCRE2) +static void * ngx_libc_cdecl ngx_regex_malloc(size_t size, void *data); +static void ngx_libc_cdecl ngx_regex_free(void *p, void *data); +#else static void * ngx_libc_cdecl ngx_regex_malloc(size_t size); static void ngx_libc_cdecl ngx_regex_free(void *p); -#if (NGX_HAVE_PCRE_JIT) -static void ngx_pcre_free_studies(void *data); #endif +static void ngx_regex_cleanup(void *data); static ngx_int_t ngx_regex_module_init(ngx_cycle_t *cycle); @@ -65,32 +72,197 @@ ngx_module_t ngx_regex_module = { }; -static ngx_pool_t *ngx_pcre_pool; -static ngx_list_t *ngx_pcre_studies; +static ngx_pool_t *ngx_regex_pool; +static ngx_list_t *ngx_regex_studies; +static ngx_uint_t ngx_regex_direct_alloc; + +#if (NGX_PCRE2) +static pcre2_compile_context *ngx_regex_compile_context; +static pcre2_match_data *ngx_regex_match_data; +static ngx_uint_t ngx_regex_match_data_size; +#endif void ngx_regex_init(void) { +#if !(NGX_PCRE2) pcre_malloc = ngx_regex_malloc; pcre_free = ngx_regex_free; +#endif } static ngx_inline void ngx_regex_malloc_init(ngx_pool_t *pool) { - ngx_pcre_pool = pool; + ngx_regex_pool = pool; + ngx_regex_direct_alloc = (pool == NULL) ? 1 : 0; } static ngx_inline void ngx_regex_malloc_done(void) { - ngx_pcre_pool = NULL; + ngx_regex_pool = NULL; + ngx_regex_direct_alloc = 0; } +#if (NGX_PCRE2) + +ngx_int_t +ngx_regex_compile(ngx_regex_compile_t *rc) +{ + int n, errcode; + char *p; + u_char errstr[128]; + size_t erroff; + uint32_t options; + pcre2_code *re; + ngx_regex_elt_t *elt; + pcre2_general_context *gctx; + pcre2_compile_context *cctx; + + if (ngx_regex_compile_context == NULL) { + /* + * Allocate a compile context if not yet allocated. This uses + * direct allocations from heap, so the result can be cached + * even at runtime. + */ + + ngx_regex_malloc_init(NULL); + + gctx = pcre2_general_context_create(ngx_regex_malloc, ngx_regex_free, + NULL); + if (gctx == NULL) { + ngx_regex_malloc_done(); + goto nomem; + } + + cctx = pcre2_compile_context_create(gctx); + if (cctx == NULL) { + pcre2_general_context_free(gctx); + ngx_regex_malloc_done(); + goto nomem; + } + + ngx_regex_compile_context = cctx; + + pcre2_general_context_free(gctx); + ngx_regex_malloc_done(); + } + + options = 0; + + if (rc->options & NGX_REGEX_CASELESS) { + options |= PCRE2_CASELESS; + } + + if (rc->options & NGX_REGEX_MULTILINE) { + options |= PCRE2_MULTILINE; + } + + if (rc->options & ~(NGX_REGEX_CASELESS|NGX_REGEX_MULTILINE)) { + rc->err.len = ngx_snprintf(rc->err.data, rc->err.len, + "regex \"%V\" compilation failed: invalid options", + &rc->pattern) + - rc->err.data; + return NGX_ERROR; + } + + ngx_regex_malloc_init(rc->pool); + + re = pcre2_compile(rc->pattern.data, rc->pattern.len, options, + &errcode, &erroff, ngx_regex_compile_context); + + /* ensure that there is no current pool */ + ngx_regex_malloc_done(); + + if (re == NULL) { + pcre2_get_error_message(errcode, errstr, 128); + + if ((size_t) erroff == rc->pattern.len) { + rc->err.len = ngx_snprintf(rc->err.data, rc->err.len, + "pcre2_compile() failed: %s in \"%V\"", + errstr, &rc->pattern) + - rc->err.data; + + } else { + rc->err.len = ngx_snprintf(rc->err.data, rc->err.len, + "pcre2_compile() failed: %s in \"%V\" at \"%s\"", + errstr, &rc->pattern, rc->pattern.data + erroff) + - rc->err.data; + } + + return NGX_ERROR; + } + + rc->regex = re; + + /* do not study at runtime */ + + if (ngx_regex_studies != NULL) { + elt = ngx_list_push(ngx_regex_studies); + if (elt == NULL) { + goto nomem; + } + + elt->regex = rc->regex; + elt->name = rc->pattern.data; + } + + n = pcre2_pattern_info(re, PCRE2_INFO_CAPTURECOUNT, &rc->captures); + if (n < 0) { + p = "pcre2_pattern_info(\"%V\", PCRE2_INFO_CAPTURECOUNT) failed: %d"; + goto failed; + } + + if (rc->captures == 0) { + return NGX_OK; + } + + n = pcre2_pattern_info(re, PCRE2_INFO_NAMECOUNT, &rc->named_captures); + if (n < 0) { + p = "pcre2_pattern_info(\"%V\", PCRE2_INFO_NAMECOUNT) failed: %d"; + goto failed; + } + + if (rc->named_captures == 0) { + return NGX_OK; + } + + n = pcre2_pattern_info(re, PCRE2_INFO_NAMEENTRYSIZE, &rc->name_size); + if (n < 0) { + p = "pcre2_pattern_info(\"%V\", PCRE2_INFO_NAMEENTRYSIZE) failed: %d"; + goto failed; + } + + n = pcre2_pattern_info(re, PCRE2_INFO_NAMETABLE, &rc->names); + if (n < 0) { + p = "pcre2_pattern_info(\"%V\", PCRE2_INFO_NAMETABLE) failed: %d"; + goto failed; + } + + return NGX_OK; + +failed: + + rc->err.len = ngx_snprintf(rc->err.data, rc->err.len, p, &rc->pattern, n) + - rc->err.data; + return NGX_ERROR; + +nomem: + + rc->err.len = ngx_snprintf(rc->err.data, rc->err.len, + "regex \"%V\" compilation failed: no memory", + &rc->pattern) + - rc->err.data; + return NGX_ERROR; +} + +#else + ngx_int_t ngx_regex_compile(ngx_regex_compile_t *rc) { @@ -98,11 +270,30 @@ ngx_regex_compile(ngx_regex_compile_t *rc) char *p; pcre *re; const char *errstr; + ngx_uint_t options; ngx_regex_elt_t *elt; + options = 0; + + if (rc->options & NGX_REGEX_CASELESS) { + options |= PCRE_CASELESS; + } + + if (rc->options & NGX_REGEX_MULTILINE) { + options |= PCRE_MULTILINE; + } + + if (rc->options & ~(NGX_REGEX_CASELESS|NGX_REGEX_MULTILINE)) { + rc->err.len = ngx_snprintf(rc->err.data, rc->err.len, + "regex \"%V\" compilation failed: invalid options", + &rc->pattern) + - rc->err.data; + return NGX_ERROR; + } + ngx_regex_malloc_init(rc->pool); - re = pcre_compile((const char *) rc->pattern.data, (int) rc->options, + re = pcre_compile((const char *) rc->pattern.data, (int) options, &errstr, &erroff, NULL); /* ensure that there is no current pool */ @@ -113,13 +304,13 @@ ngx_regex_compile(ngx_regex_compile_t *rc) rc->err.len = ngx_snprintf(rc->err.data, rc->err.len, "pcre_compile() failed: %s in \"%V\"", errstr, &rc->pattern) - - rc->err.data; + - rc->err.data; } else { rc->err.len = ngx_snprintf(rc->err.data, rc->err.len, "pcre_compile() failed: %s in \"%V\" at \"%s\"", errstr, &rc->pattern, rc->pattern.data + erroff) - - rc->err.data; + - rc->err.data; } return NGX_ERROR; @@ -134,8 +325,8 @@ ngx_regex_compile(ngx_regex_compile_t *rc) /* do not study at runtime */ - if (ngx_pcre_studies != NULL) { - elt = ngx_list_push(ngx_pcre_studies); + if (ngx_regex_studies != NULL) { + elt = ngx_list_push(ngx_regex_studies); if (elt == NULL) { goto nomem; } @@ -193,6 +384,83 @@ nomem: return NGX_ERROR; } +#endif + + +#if (NGX_PCRE2) + +ngx_int_t +ngx_regex_exec(ngx_regex_t *re, ngx_str_t *s, int *captures, ngx_uint_t size) +{ + size_t *ov; + ngx_int_t rc; + ngx_uint_t n, i; + + /* + * The pcre2_match() function might allocate memory for backtracking + * frames, typical allocations are from 40k and above. So the allocator + * is configured to do direct allocations from heap during matching. + */ + + ngx_regex_malloc_init(NULL); + + if (ngx_regex_match_data == NULL + || size > ngx_regex_match_data_size) + { + /* + * Allocate a match data if not yet allocated or smaller than + * needed. + */ + + if (ngx_regex_match_data) { + pcre2_match_data_free(ngx_regex_match_data); + } + + ngx_regex_match_data_size = size; + ngx_regex_match_data = pcre2_match_data_create(size / 3, NULL); + + if (ngx_regex_match_data == NULL) { + rc = PCRE2_ERROR_NOMEMORY; + goto failed; + } + } + + rc = pcre2_match(re, s->data, s->len, 0, 0, ngx_regex_match_data, NULL); + + if (rc < 0) { + goto failed; + } + + n = pcre2_get_ovector_count(ngx_regex_match_data); + ov = pcre2_get_ovector_pointer(ngx_regex_match_data); + + if (n > size / 3) { + n = size / 3; + } + + for (i = 0; i < n; i++) { + captures[i * 2] = ov[i * 2]; + captures[i * 2 + 1] = ov[i * 2 + 1]; + } + +failed: + + ngx_regex_malloc_done(); + + return rc; +} + +#else + +ngx_int_t +ngx_regex_exec(ngx_regex_t *re, ngx_str_t *s, int *captures, ngx_uint_t size) +{ + return pcre_exec(re->code, re->extra, (const char *) s->data, s->len, + 0, 0, captures, size); +} + +#endif + ngx_int_t ngx_regex_exec_array(ngx_array_t *a, ngx_str_t *s, ngx_log_t *log) @@ -227,14 +495,40 @@ ngx_regex_exec_array(ngx_array_t *a, ngx_str_t *s, ngx_log_t *log) } +#if (NGX_PCRE2) + +static void * ngx_libc_cdecl +ngx_regex_malloc(size_t size, void *data) +{ + if (ngx_regex_pool) { + return ngx_palloc(ngx_regex_pool, size); + } + + if (ngx_regex_direct_alloc) { + return ngx_alloc(size, ngx_cycle->log); + } + + return NULL; +} + + +static void ngx_libc_cdecl +ngx_regex_free(void *p, void *data) +{ + if (ngx_regex_direct_alloc) { + ngx_free(p); + } + + return; +} + +#else + static void * ngx_libc_cdecl ngx_regex_malloc(size_t size) { - ngx_pool_t *pool; - pool = ngx_pcre_pool; - - if (pool) { - return ngx_palloc(pool, size); + if (ngx_regex_pool) { + return ngx_palloc(ngx_regex_pool, size); } return NULL; @@ -247,19 +541,20 @@ ngx_regex_free(void *p) return; } +#endif -#if (NGX_HAVE_PCRE_JIT) static void -ngx_pcre_free_studies(void *data) +ngx_regex_cleanup(void *data) { - ngx_list_t *studies = data; +#if (NGX_PCRE2 || NGX_HAVE_PCRE_JIT) + ngx_regex_conf_t *rcf = data; ngx_uint_t i; ngx_list_part_t *part; ngx_regex_elt_t *elts; - part = &studies->part; + part = &rcf->studies->part; elts = part->elts; for (i = 0; /* void */ ; i++) { @@ -274,56 +569,83 @@ ngx_pcre_free_studies(void *data) i = 0; } + /* + * The PCRE JIT compiler uses mmap for its executable codes, so we + * have to explicitly call the pcre_free_study() function to free + * this memory. In PCRE2, we call the pcre2_code_free() function + * for the same reason. + */ + +#if (NGX_PCRE2) + pcre2_code_free(elts[i].regex); +#else if (elts[i].regex->extra != NULL) { pcre_free_study(elts[i].regex->extra); } +#endif + } +#endif + + /* + * On configuration parsing errors ngx_regex_module_init() will not + * be called. Make sure ngx_regex_studies is properly cleared anyway. + */ + + ngx_regex_studies = NULL; + +#if (NGX_PCRE2) + + /* + * Free compile context and match data. If needed at runtime by + * the new cycle, these will be re-allocated. + */ + + if (ngx_regex_compile_context) { + pcre2_compile_context_free(ngx_regex_compile_context); + ngx_regex_compile_context = NULL; + } + + if (ngx_regex_match_data) { + pcre2_match_data_free(ngx_regex_match_data); + ngx_regex_match_data = NULL; + ngx_regex_match_data_size = 0; } -} #endif +} static ngx_int_t ngx_regex_module_init(ngx_cycle_t *cycle) { - int opt; - const char *errstr; - ngx_uint_t i; - ngx_list_part_t *part; - ngx_regex_elt_t *elts; + int opt; +#if !(NGX_PCRE2) + const char *errstr; +#endif + ngx_uint_t i; + ngx_list_part_t *part; + ngx_regex_elt_t *elts; + ngx_regex_conf_t *rcf; opt = 0; -#if (NGX_HAVE_PCRE_JIT) - { - ngx_regex_conf_t *rcf; - ngx_pool_cleanup_t *cln; - rcf = (ngx_regex_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_regex_module); +#if (NGX_PCRE2 || NGX_HAVE_PCRE_JIT) + if (rcf->pcre_jit) { +#if (NGX_PCRE2) + opt = 1; +#else opt = PCRE_STUDY_JIT_COMPILE; - - /* - * The PCRE JIT compiler uses mmap for its executable codes, so we - * have to explicitly call the pcre_free_study() function to free - * this memory. - */ - - cln = ngx_pool_cleanup_add(cycle->pool, 0); - if (cln == NULL) { - return NGX_ERROR; - } - - cln->handler = ngx_pcre_free_studies; - cln->data = ngx_pcre_studies; - } +#endif } + #endif ngx_regex_malloc_init(cycle->pool); - part = &ngx_pcre_studies->part; + part = &rcf->studies->part; elts = part->elts; for (i = 0; /* void */ ; i++) { @@ -338,6 +660,23 @@ ngx_regex_module_init(ngx_cycle_t *cycle) i = 0; } +#if (NGX_PCRE2) + + if (opt) { + int n; + + n = pcre2_jit_compile(elts[i].regex, PCRE2_JIT_COMPLETE); + + if (n != 0) { + ngx_log_error(NGX_LOG_INFO, cycle->log, 0, + "pcre2_jit_compile() failed: %d in \"%s\", " + "ignored", + n, elts[i].name); + } + } + +#else + elts[i].regex->extra = pcre_study(elts[i].regex->code, opt, &errstr); if (errstr != NULL) { @@ -360,12 +699,16 @@ ngx_regex_module_init(ngx_cycle_t *cycle) elts[i].name); } } +#endif #endif } ngx_regex_malloc_done(); - ngx_pcre_studies = NULL; + ngx_regex_studies = NULL; +#if (NGX_PCRE2) + ngx_regex_compile_context = NULL; +#endif return NGX_OK; } @@ -374,7 +717,8 @@ ngx_regex_module_init(ngx_cycle_t *cycle) static void * ngx_regex_create_conf(ngx_cycle_t *cycle) { - ngx_regex_conf_t *rcf; + ngx_regex_conf_t *rcf; + ngx_pool_cleanup_t *cln; rcf = ngx_pcalloc(cycle->pool, sizeof(ngx_regex_conf_t)); if (rcf == NULL) { @@ -383,11 +727,21 @@ ngx_regex_create_conf(ngx_cycle_t *cycle) rcf->pcre_jit = NGX_CONF_UNSET; - ngx_pcre_studies = ngx_list_create(cycle->pool, 8, sizeof(ngx_regex_elt_t)); - if (ngx_pcre_studies == NULL) { + cln = ngx_pool_cleanup_add(cycle->pool, 0); + if (cln == NULL) { return NULL; } + cln->handler = ngx_regex_cleanup; + cln->data = rcf; + + rcf->studies = ngx_list_create(cycle->pool, 8, sizeof(ngx_regex_elt_t)); + if (rcf->studies == NULL) { + return NULL; + } + + ngx_regex_studies = rcf->studies; + return rcf; } @@ -412,7 +766,21 @@ ngx_regex_pcre_jit(ngx_conf_t *cf, void *post, void *data) return NGX_CONF_OK; } -#if (NGX_HAVE_PCRE_JIT) +#if (NGX_PCRE2) + { + int r; + uint32_t jit; + + jit = 0; + r = pcre2_config(PCRE2_CONFIG_JIT, &jit); + + if (r != 0 || jit != 1) { + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, + "PCRE2 library does not support JIT"); + *fp = 0; + } + } +#elif (NGX_HAVE_PCRE_JIT) { int jit, r; diff --git a/src/core/ngx_regex.h b/src/core/ngx_regex.h index 680486c..182373a 100644 --- a/src/core/ngx_regex.h +++ b/src/core/ngx_regex.h @@ -12,24 +12,38 @@ #include #include + +#if (NGX_PCRE2) + +#define PCRE2_CODE_UNIT_WIDTH 8 +#include + +#define NGX_REGEX_NO_MATCHED PCRE2_ERROR_NOMATCH /* -1 */ + +typedef pcre2_code ngx_regex_t; + +#else + #include - -#define NGX_REGEX_NO_MATCHED PCRE_ERROR_NOMATCH /* -1 */ - -#define NGX_REGEX_CASELESS PCRE_CASELESS - +#define NGX_REGEX_NO_MATCHED PCRE_ERROR_NOMATCH /* -1 */ typedef struct { pcre *code; pcre_extra *extra; } ngx_regex_t; +#endif + + +#define NGX_REGEX_CASELESS 0x00000001 +#define NGX_REGEX_MULTILINE 0x00000002 + typedef struct { ngx_str_t pattern; ngx_pool_t *pool; - ngx_int_t options; + ngx_uint_t options; ngx_regex_t *regex; int captures; @@ -49,10 +63,14 @@ typedef struct { 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->code, re->extra, (const char *) (s)->data, (s)->len, 0, 0, \ - captures, size) -#define ngx_regex_exec_n "pcre_exec()" +ngx_int_t ngx_regex_exec(ngx_regex_t *re, ngx_str_t *s, int *captures, + ngx_uint_t size); + +#if (NGX_PCRE2) +#define ngx_regex_exec_n "pcre2_match()" +#else +#define ngx_regex_exec_n "pcre_exec()" +#endif ngx_int_t ngx_regex_exec_array(ngx_array_t *a, ngx_str_t *s, ngx_log_t *log); diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c index 58d5f3e..6d129e5 100644 --- a/src/core/ngx_resolver.c +++ b/src/core/ngx_resolver.c @@ -51,9 +51,7 @@ typedef struct { } ngx_resolver_an_t; -#define ngx_resolver_node(n) \ - (ngx_resolver_node_t *) \ - ((u_char *) (n) - offsetof(ngx_resolver_node_t, node)) +#define ngx_resolver_node(n) ngx_rbtree_data(n, ngx_resolver_node_t, node) static ngx_int_t ngx_udp_connect(ngx_resolver_connection_t *rec); diff --git a/src/core/ngx_rwlock.c b/src/core/ngx_rwlock.c index ed2b0f8..e7da8a8 100644 --- a/src/core/ngx_rwlock.c +++ b/src/core/ngx_rwlock.c @@ -89,22 +89,10 @@ ngx_rwlock_rlock(ngx_atomic_t *lock) void ngx_rwlock_unlock(ngx_atomic_t *lock) { - ngx_atomic_uint_t readers; - - readers = *lock; - - if (readers == NGX_RWLOCK_WLOCK) { + if (*lock == NGX_RWLOCK_WLOCK) { (void) ngx_atomic_cmp_set(lock, NGX_RWLOCK_WLOCK, 0); - return; - } - - for ( ;; ) { - - if (ngx_atomic_cmp_set(lock, readers, readers - 1)) { - return; - } - - readers = *lock; + } else { + (void) ngx_atomic_fetch_add(lock, -1); } } diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c index 93f32ea..98f270a 100644 --- a/src/core/ngx_string.c +++ b/src/core/ngx_string.c @@ -1493,19 +1493,32 @@ ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type) uint32_t *escape; static u_char hex[] = "0123456789ABCDEF"; - /* " ", "#", "%", "?", %00-%1F, %7F-%FF */ + /* + * Per RFC 3986 only the following chars are allowed in URIs unescaped: + * + * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + * gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" + * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" + * / "*" / "+" / "," / ";" / "=" + * + * And "%" can appear as a part of escaping itself. The following + * characters are not allowed and need to be escaped: %00-%1F, %7F-%FF, + * " ", """, "<", ">", "\", "^", "`", "{", "|", "}". + */ + + /* " ", "#", "%", "?", not allowed */ static uint32_t uri[] = { 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ - 0x80000029, /* 1000 0000 0000 0000 0000 0000 0010 1001 */ + 0xd000002d, /* 1101 0000 0000 0000 0000 0000 0010 1101 */ /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */ - 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ + 0x50000000, /* 0101 0000 0000 0000 0000 0000 0000 0000 */ /* ~}| {zyx wvut srqp onml kjih gfed cba` */ - 0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */ + 0xb8000001, /* 1011 1000 0000 0000 0000 0000 0000 0001 */ 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ @@ -1513,19 +1526,19 @@ ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type) 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */ }; - /* " ", "#", "%", "&", "+", "?", %00-%1F, %7F-%FF */ + /* " ", "#", "%", "&", "+", ";", "?", not allowed */ static uint32_t args[] = { 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ - 0x88000869, /* 1000 1000 0000 0000 0000 1000 0110 1001 */ + 0xd800086d, /* 1101 1000 0000 0000 0000 1000 0110 1101 */ /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */ - 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ + 0x50000000, /* 0101 0000 0000 0000 0000 0000 0000 0000 */ /* ~}| {zyx wvut srqp onml kjih gfed cba` */ - 0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */ + 0xb8000001, /* 1011 1000 0000 0000 0000 0000 0000 0001 */ 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ @@ -1553,19 +1566,19 @@ ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type) 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */ }; - /* " ", "#", """, "%", "'", %00-%1F, %7F-%FF */ + /* " ", "#", """, "%", "'", not allowed */ static uint32_t html[] = { 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ - 0x000000ad, /* 0000 0000 0000 0000 0000 0000 1010 1101 */ + 0x500000ad, /* 0101 0000 0000 0000 0000 0000 1010 1101 */ /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */ - 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ + 0x50000000, /* 0101 0000 0000 0000 0000 0000 0000 0000 */ /* ~}| {zyx wvut srqp onml kjih gfed cba` */ - 0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */ + 0xb8000001, /* 1011 1000 0000 0000 0000 0000 0000 0001 */ 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ @@ -1573,19 +1586,19 @@ ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type) 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */ }; - /* " ", """, "%", "'", %00-%1F, %7F-%FF */ + /* " ", """, "'", not allowed */ static uint32_t refresh[] = { 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ - 0x00000085, /* 0000 0000 0000 0000 0000 0000 1000 0101 */ + 0x50000085, /* 0101 0000 0000 0000 0000 0000 1000 0101 */ /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */ - 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ + 0x50000000, /* 0101 0000 0000 0000 0000 0000 0000 0000 */ /* ~}| {zyx wvut srqp onml kjih gfed cba` */ - 0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */ + 0xd8000001, /* 1011 1000 0000 0000 0000 0000 0000 0001 */ 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ diff --git a/src/core/ngx_times.c b/src/core/ngx_times.c index 7964b00..16788c9 100644 --- a/src/core/ngx_times.c +++ b/src/core/ngx_times.c @@ -200,10 +200,6 @@ ngx_monotonic_time(time_t sec, ngx_uint_t msec) #if defined(CLOCK_MONOTONIC_FAST) clock_gettime(CLOCK_MONOTONIC_FAST, &ts); - -#elif defined(CLOCK_MONOTONIC_COARSE) - clock_gettime(CLOCK_MONOTONIC_COARSE, &ts); - #else clock_gettime(CLOCK_MONOTONIC, &ts); #endif diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c index 7777d04..47229b5 100644 --- a/src/event/ngx_event.c +++ b/src/event/ngx_event.c @@ -55,6 +55,7 @@ ngx_uint_t ngx_accept_events; ngx_uint_t ngx_accept_mutex_held; ngx_msec_t ngx_accept_mutex_delay; ngx_int_t ngx_accept_disabled; +ngx_uint_t ngx_use_exclusive_accept; #if (NGX_STAT_STUB) @@ -441,20 +442,23 @@ ngx_event_init_conf(ngx_cycle_t *cycle, void *conf) #if (NGX_HAVE_REUSEPORT) - ls = cycle->listening.elts; - for (i = 0; i < cycle->listening.nelts; i++) { - - if (!ls[i].reuseport || ls[i].worker != 0) { - continue; - } - - if (ngx_clone_listening(cycle, &ls[i]) != NGX_OK) { - return NGX_CONF_ERROR; - } - - /* cloning may change cycle->listening.elts */ + if (!ngx_test_config) { ls = cycle->listening.elts; + for (i = 0; i < cycle->listening.nelts; i++) { + + if (!ls[i].reuseport || ls[i].worker != 0) { + continue; + } + + if (ngx_clone_listening(cycle, &ls[i]) != NGX_OK) { + return NGX_CONF_ERROR; + } + + /* cloning may change cycle->listening.elts */ + + ls = cycle->listening.elts; + } } #endif @@ -641,6 +645,8 @@ ngx_event_process_init(ngx_cycle_t *cycle) #endif + ngx_use_exclusive_accept = 0; + ngx_queue_init(&ngx_posted_accept_events); ngx_queue_init(&ngx_posted_next_events); ngx_queue_init(&ngx_posted_events); @@ -886,6 +892,8 @@ ngx_event_process_init(ngx_cycle_t *cycle) if ((ngx_event_flags & NGX_USE_EPOLL_EVENT) && ccf->worker_processes > 1) { + ngx_use_exclusive_accept = 1; + if (ngx_add_event(rev, NGX_READ_EVENT, NGX_EXCLUSIVE_EVENT) == NGX_ERROR) { diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h index 97f9673..548c906 100644 --- a/src/event/ngx_event.h +++ b/src/event/ngx_event.h @@ -147,10 +147,6 @@ struct ngx_event_aio_s { ngx_fd_t fd; -#if (NGX_HAVE_AIO_SENDFILE || NGX_COMPAT) - ssize_t (*preload_handler)(ngx_buf_t *file); -#endif - #if (NGX_HAVE_EVENTFD) int64_t res; #endif @@ -466,6 +462,7 @@ extern ngx_uint_t ngx_accept_events; extern ngx_uint_t ngx_accept_mutex_held; extern ngx_msec_t ngx_accept_mutex_delay; extern ngx_int_t ngx_accept_disabled; +extern ngx_uint_t ngx_use_exclusive_accept; #if (NGX_STAT_STUB) diff --git a/src/event/ngx_event_accept.c b/src/event/ngx_event_accept.c index b05666c..2703879 100644 --- a/src/event/ngx_event_accept.c +++ b/src/event/ngx_event_accept.c @@ -11,6 +11,9 @@ static ngx_int_t ngx_disable_accept_events(ngx_cycle_t *cycle, ngx_uint_t all); +#if (NGX_HAVE_EPOLLEXCLUSIVE) +static void ngx_reorder_accept_events(ngx_listening_t *ls); +#endif static void ngx_close_accepted_connection(ngx_connection_t *c); @@ -314,6 +317,10 @@ ngx_event_accept(ngx_event_t *ev) } } while (ev->available); + +#if (NGX_HAVE_EPOLLEXCLUSIVE) + ngx_reorder_accept_events(ls); +#endif } @@ -420,6 +427,57 @@ ngx_disable_accept_events(ngx_cycle_t *cycle, ngx_uint_t all) } +#if (NGX_HAVE_EPOLLEXCLUSIVE) + +static void +ngx_reorder_accept_events(ngx_listening_t *ls) +{ + ngx_connection_t *c; + + /* + * Linux with EPOLLEXCLUSIVE usually notifies only the process which + * was first to add the listening socket to the epoll instance. As + * a result most of the connections are handled by the first worker + * process. To fix this, we re-add the socket periodically, so other + * workers will get a chance to accept connections. + */ + + if (!ngx_use_exclusive_accept) { + return; + } + +#if (NGX_HAVE_REUSEPORT) + + if (ls->reuseport) { + return; + } + +#endif + + c = ls->connection; + + if (c->requests++ % 16 != 0 + && ngx_accept_disabled <= 0) + { + return; + } + + if (ngx_del_event(c->read, NGX_READ_EVENT, NGX_DISABLE_EVENT) + == NGX_ERROR) + { + return; + } + + if (ngx_add_event(c->read, NGX_READ_EVENT, NGX_EXCLUSIVE_EVENT) + == NGX_ERROR) + { + return; + } +} + +#endif + + static void ngx_close_accepted_connection(ngx_connection_t *c) { diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c index ce2a566..1e6fc96 100644 --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -47,6 +47,8 @@ static void ngx_ssl_write_handler(ngx_event_t *wev); static ssize_t ngx_ssl_write_early(ngx_connection_t *c, u_char *data, size_t size); #endif +static ssize_t ngx_ssl_sendfile(ngx_connection_t *c, ngx_buf_t *file, + size_t size); static void ngx_ssl_read_handler(ngx_event_t *rev); static void ngx_ssl_shutdown_handler(ngx_event_t *ev); static void ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, @@ -299,11 +301,6 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data) SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER); #endif -#ifdef SSL_OP_MSIE_SSLV2_RSA_PADDING - /* this option allow a potential SSL 2.0 rollback (CAN-2005-2969) */ - SSL_CTX_set_options(ssl->ctx, SSL_OP_MSIE_SSLV2_RSA_PADDING); -#endif - #ifdef SSL_OP_SSLEAY_080_CLIENT_DH_BUG SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLEAY_080_CLIENT_DH_BUG); #endif @@ -863,11 +860,6 @@ ngx_ssl_ciphers(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *ciphers, SSL_CTX_set_options(ssl->ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); } -#if (OPENSSL_VERSION_NUMBER < 0x10100001L && !defined LIBRESSL_VERSION_NUMBER) - /* a temporary 512-bit RSA key is required for export versions of MSIE */ - SSL_CTX_set_tmp_rsa_callback(ssl->ctx, ngx_ssl_rsa512_key_callback); -#endif - return NGX_OK; } @@ -1120,32 +1112,6 @@ ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where, int ret) } -#if (OPENSSL_VERSION_NUMBER < 0x10100001L && !defined LIBRESSL_VERSION_NUMBER) - -RSA * -ngx_ssl_rsa512_key_callback(ngx_ssl_conn_t *ssl_conn, int is_export, - int key_length) -{ - static RSA *key; - - if (key_length != 512) { - return NULL; - } - -#ifndef OPENSSL_NO_DEPRECATED - - if (key == NULL) { - key = RSA_generate_key(512, RSA_F4, NULL, NULL); - } - -#endif - - return key; -} - -#endif - - ngx_array_t * ngx_ssl_read_password_file(ngx_conf_t *cf, ngx_str_t *file) { @@ -1417,6 +1383,9 @@ ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file) if (SSL_CTX_set0_tmp_dh_pkey(ssl->ctx, dh) != 1) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "SSL_CTX_set0_tmp_dh_pkey(\%s\") failed", file->data); +#if (OPENSSL_VERSION_NUMBER >= 0x3000001fL) + EVP_PKEY_free(dh); +#endif BIO_free(bio); return NGX_ERROR; } @@ -1798,6 +1767,16 @@ ngx_ssl_handshake(ngx_connection_t *c) #endif #endif +#endif + +#ifdef BIO_get_ktls_send + + if (BIO_get_ktls_send(SSL_get_wbio(c->ssl->connection)) == 1) { + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, + "BIO_get_ktls_send(): 1"); + c->ssl->sendfile = 1; + } + #endif rc = ngx_ssl_ocsp_validate(c); @@ -1935,6 +1914,16 @@ ngx_ssl_try_early_data(ngx_connection_t *c) c->read->ready = 1; c->write->ready = 1; +#ifdef BIO_get_ktls_send + + if (BIO_get_ktls_send(SSL_get_wbio(c->ssl->connection)) == 1) { + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, + "BIO_get_ktls_send(): 1"); + c->ssl->sendfile = 1; + } + +#endif + rc = ngx_ssl_ocsp_validate(c); if (rc == NGX_ERROR) { @@ -2538,10 +2527,11 @@ ngx_ssl_write_handler(ngx_event_t *wev) ngx_chain_t * ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) { - int n; - ngx_uint_t flush; - ssize_t send, size; - ngx_buf_t *buf; + int n; + ngx_uint_t flush; + ssize_t send, size, file_size; + ngx_buf_t *buf; + ngx_chain_t *cl; if (!c->ssl->buffer) { @@ -2615,6 +2605,11 @@ ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) continue; } + if (in->buf->in_file && c->ssl->sendfile) { + flush = 1; + break; + } + size = in->buf->last - in->buf->pos; if (size > buf->end - buf->last) { @@ -2646,8 +2641,35 @@ ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) size = buf->last - buf->pos; if (size == 0) { + + if (in && in->buf->in_file && send < limit) { + + /* coalesce the neighbouring file bufs */ + + cl = in; + file_size = (size_t) ngx_chain_coalesce_file(&cl, limit - send); + + n = ngx_ssl_sendfile(c, in->buf, file_size); + + if (n == NGX_ERROR) { + return NGX_CHAIN_ERROR; + } + + if (n == NGX_AGAIN) { + break; + } + + in = ngx_chain_update_sent(in, n); + + send += n; + flush = 0; + + continue; + } + buf->flush = 0; c->buffered &= ~NGX_SSL_BUFFERED; + return in; } @@ -2672,7 +2694,7 @@ ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) buf->pos = buf->start; buf->last = buf->start; - if (in == NULL || send == limit) { + if (in == NULL || send >= limit) { break; } } @@ -2803,7 +2825,7 @@ ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size) #ifdef SSL_READ_EARLY_DATA_SUCCESS -ssize_t +static ssize_t ngx_ssl_write_early(ngx_connection_t *c, u_char *data, size_t size) { int n, sslerr; @@ -2918,6 +2940,183 @@ ngx_ssl_write_early(ngx_connection_t *c, u_char *data, size_t size) #endif +static ssize_t +ngx_ssl_sendfile(ngx_connection_t *c, ngx_buf_t *file, size_t size) +{ +#ifdef BIO_get_ktls_send + + int sslerr, flags; + ssize_t n; + ngx_err_t err; + + ngx_ssl_clear_error(c->log); + + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, + "SSL to sendfile: @%O %uz", + file->file_pos, size); + + ngx_set_errno(0); + +#if (NGX_HAVE_SENDFILE_NODISKIO) + + flags = (c->busy_count <= 2) ? SF_NODISKIO : 0; + + if (file->file->directio) { + flags |= SF_NOCACHE; + } + +#else + flags = 0; +#endif + + n = SSL_sendfile(c->ssl->connection, file->file->fd, file->file_pos, + size, flags); + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_sendfile: %d", n); + + if (n > 0) { + + if (c->ssl->saved_read_handler) { + + c->read->handler = c->ssl->saved_read_handler; + c->ssl->saved_read_handler = NULL; + c->read->ready = 1; + + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + return NGX_ERROR; + } + + ngx_post_event(c->read, &ngx_posted_events); + } + +#if (NGX_HAVE_SENDFILE_NODISKIO) + c->busy_count = 0; +#endif + + c->sent += n; + + return n; + } + + if (n == 0) { + + /* + * if sendfile returns zero, then someone has truncated the file, + * so the offset became beyond the end of the file + */ + + ngx_log_error(NGX_LOG_ALERT, c->log, 0, + "SSL_sendfile() reported that \"%s\" was truncated at %O", + file->file->name.data, file->file_pos); + + return NGX_ERROR; + } + + sslerr = SSL_get_error(c->ssl->connection, n); + + if (sslerr == SSL_ERROR_ZERO_RETURN) { + + /* + * OpenSSL fails to return SSL_ERROR_SYSCALL if an error + * happens during writing after close_notify alert from the + * peer, and returns SSL_ERROR_ZERO_RETURN instead + */ + + sslerr = SSL_ERROR_SYSCALL; + } + + if (sslerr == SSL_ERROR_SSL + && ERR_GET_REASON(ERR_peek_error()) == SSL_R_UNINITIALIZED + && ngx_errno != 0) + { + /* + * OpenSSL fails to return SSL_ERROR_SYSCALL if an error + * happens in sendfile(), and returns SSL_ERROR_SSL with + * SSL_R_UNINITIALIZED reason instead + */ + + sslerr = SSL_ERROR_SYSCALL; + } + + err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0; + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr); + + if (sslerr == SSL_ERROR_WANT_WRITE) { + + if (c->ssl->saved_read_handler) { + + c->read->handler = c->ssl->saved_read_handler; + c->ssl->saved_read_handler = NULL; + c->read->ready = 1; + + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + return NGX_ERROR; + } + + ngx_post_event(c->read, &ngx_posted_events); + } + +#if (NGX_HAVE_SENDFILE_NODISKIO) + + if (ngx_errno == EBUSY) { + c->busy_count++; + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, + "SSL_sendfile() busy, count:%d", c->busy_count); + + if (c->write->posted) { + ngx_delete_posted_event(c->write); + } + + ngx_post_event(c->write, &ngx_posted_next_events); + } + +#endif + + c->write->ready = 0; + return NGX_AGAIN; + } + + if (sslerr == SSL_ERROR_WANT_READ) { + + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, + "SSL_sendfile: want read"); + + c->read->ready = 0; + + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + return NGX_ERROR; + } + + /* + * we do not set the timer because there is already + * the write event timer + */ + + if (c->ssl->saved_read_handler == NULL) { + c->ssl->saved_read_handler = c->read->handler; + c->read->handler = ngx_ssl_read_handler; + } + + return NGX_AGAIN; + } + + c->ssl->no_wait_shutdown = 1; + c->ssl->no_send_shutdown = 1; + c->write->error = 1; + + ngx_ssl_connection_error(c, sslerr, err, "SSL_sendfile() failed"); + +#else + ngx_log_error(NGX_LOG_ALERT, c->log, 0, + "SSL_sendfile() not available"); +#endif + + return NGX_ERROR; +} + + static void ngx_ssl_read_handler(ngx_event_t *rev) { @@ -3169,6 +3368,9 @@ ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err, #endif #ifdef SSL_R_CALLBACK_FAILED || n == SSL_R_CALLBACK_FAILED /* 234 */ +#endif +#ifdef SSL_R_NO_APPLICATION_PROTOCOL + || n == SSL_R_NO_APPLICATION_PROTOCOL /* 235 */ #endif || n == SSL_R_UNEXPECTED_MESSAGE /* 244 */ || n == SSL_R_UNEXPECTED_RECORD /* 245 */ @@ -4249,7 +4451,21 @@ ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn, return -1; } - return (i == 0) ? 1 : 2 /* renew */; + /* renew if TLSv1.3 */ + +#ifdef TLS1_3_VERSION + if (SSL_version(ssl_conn) == TLS1_3_VERSION) { + return 2; + } +#endif + + /* renew if non-default key */ + + if (i != 0) { + return 2; + } + + return 1; } } @@ -4567,6 +4783,42 @@ ngx_ssl_get_ciphers(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) } +ngx_int_t +ngx_ssl_get_curve(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) +{ +#ifdef SSL_get_negotiated_group + + int nid; + + nid = SSL_get_negotiated_group(c->ssl->connection); + + if (nid != NID_undef) { + + if ((nid & TLSEXT_nid_unknown) == 0) { + s->len = ngx_strlen(OBJ_nid2sn(nid)); + s->data = (u_char *) OBJ_nid2sn(nid); + return NGX_OK; + } + + s->len = sizeof("0x0000") - 1; + + s->data = ngx_pnalloc(pool, s->len); + if (s->data == NULL) { + return NGX_ERROR; + } + + ngx_sprintf(s->data, "0x%04xd", nid & 0xffff); + + return NGX_OK; + } + +#endif + + s->len = 0; + return NGX_OK; +} + + ngx_int_t ngx_ssl_get_curves(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) { @@ -4734,6 +4986,36 @@ ngx_ssl_get_server_name(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) } +ngx_int_t +ngx_ssl_get_alpn_protocol(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) +{ +#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation + + unsigned int len; + const unsigned char *data; + + SSL_get0_alpn_selected(c->ssl->connection, &data, &len); + + if (len > 0) { + + s->data = ngx_pnalloc(pool, len); + if (s->data == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(s->data, data, len); + s->len = len; + + return NGX_OK; + } + +#endif + + s->len = 0; + return NGX_OK; +} + + ngx_int_t ngx_ssl_get_raw_certificate(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) { diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h index 81b87d7..c9e86d9 100644 --- a/src/event/ngx_event_openssl.h +++ b/src/event/ngx_event_openssl.h @@ -29,7 +29,6 @@ #include #endif #include -#include #include #include @@ -110,6 +109,7 @@ struct ngx_ssl_connection_s { unsigned handshake_rejected:1; unsigned renegotiation:1; unsigned buffer:1; + unsigned sendfile:1; unsigned no_wait_shutdown:1; unsigned no_send_shutdown:1; unsigned shutdown_without_free:1; @@ -208,10 +208,6 @@ ngx_int_t ngx_ssl_ocsp_validate(ngx_connection_t *c); ngx_int_t ngx_ssl_ocsp_get_status(ngx_connection_t *c, const char **s); void ngx_ssl_ocsp_cleanup(ngx_connection_t *c); ngx_int_t ngx_ssl_ocsp_cache_init(ngx_shm_zone_t *shm_zone, void *data); -#if (OPENSSL_VERSION_NUMBER < 0x10100001L && !defined LIBRESSL_VERSION_NUMBER) -RSA *ngx_ssl_rsa512_key_callback(ngx_ssl_conn_t *ssl_conn, int is_export, - int key_length); -#endif ngx_array_t *ngx_ssl_read_password_file(ngx_conf_t *cf, ngx_str_t *file); ngx_array_t *ngx_ssl_preserve_passwords(ngx_conf_t *cf, ngx_array_t *passwords); @@ -260,6 +256,8 @@ 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_curve(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, @@ -270,6 +268,8 @@ ngx_int_t ngx_ssl_get_early_data(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s); ngx_int_t ngx_ssl_get_server_name(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s); +ngx_int_t ngx_ssl_get_alpn_protocol(ngx_connection_t *c, ngx_pool_t *pool, + ngx_str_t *s); ngx_int_t ngx_ssl_get_raw_certificate(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s); ngx_int_t ngx_ssl_get_certificate(ngx_connection_t *c, ngx_pool_t *pool, diff --git a/src/event/ngx_event_timer.c b/src/event/ngx_event_timer.c index 698b88f..35052bc 100644 --- a/src/event/ngx_event_timer.c +++ b/src/event/ngx_event_timer.c @@ -73,7 +73,7 @@ ngx_event_expire_timers(void) return; } - ev = (ngx_event_t *) ((char *) node - offsetof(ngx_event_t, timer)); + ev = ngx_rbtree_data(node, ngx_event_t, timer); ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0, "event timer del: %d: %M", @@ -113,7 +113,7 @@ ngx_event_no_timers_left(void) node; node = ngx_rbtree_next(&ngx_event_timer_rbtree, node)) { - ev = (ngx_event_t *) ((char *) node - offsetof(ngx_event_t, timer)); + ev = ngx_rbtree_data(node, ngx_event_t, timer); if (!ev->cancelable) { return NGX_AGAIN; diff --git a/src/http/modules/ngx_http_auth_basic_module.c b/src/http/modules/ngx_http_auth_basic_module.c index ed9df34..0693319 100644 --- a/src/http/modules/ngx_http_auth_basic_module.c +++ b/src/http/modules/ngx_http_auth_basic_module.c @@ -16,7 +16,7 @@ typedef struct { ngx_http_complex_value_t *realm; - ngx_http_complex_value_t user_file; + ngx_http_complex_value_t *user_file; } ngx_http_auth_basic_loc_conf_t; @@ -107,7 +107,7 @@ 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 == NULL || alcf->user_file.value.data == NULL) { + if (alcf->realm == NULL || alcf->user_file == NULL) { return NGX_DECLINED; } @@ -133,7 +133,7 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r) return NGX_HTTP_INTERNAL_SERVER_ERROR; } - if (ngx_http_complex_value(r, &alcf->user_file, &user_file) != NGX_OK) { + if (ngx_http_complex_value(r, alcf->user_file, &user_file) != NGX_OK) { return NGX_ERROR; } @@ -357,6 +357,9 @@ ngx_http_auth_basic_create_loc_conf(ngx_conf_t *cf) return NULL; } + conf->realm = NGX_CONF_UNSET_PTR; + conf->user_file = NGX_CONF_UNSET_PTR; + return conf; } @@ -367,13 +370,8 @@ 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 == NULL) { - conf->realm = prev->realm; - } - - if (conf->user_file.value.data == NULL) { - conf->user_file = prev->user_file; - } + ngx_conf_merge_ptr_value(conf->realm, prev->realm, NULL); + ngx_conf_merge_ptr_value(conf->user_file, prev->user_file, NULL); return NGX_CONF_OK; } @@ -406,17 +404,22 @@ 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.data) { + if (alcf->user_file != NGX_CONF_UNSET_PTR) { return "is duplicate"; } + alcf->user_file = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t)); + if (alcf->user_file == NULL) { + return NGX_CONF_ERROR; + } + value = cf->args->elts; ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); ccv.cf = cf; ccv.value = &value[1]; - ccv.complex_value = &alcf->user_file; + ccv.complex_value = alcf->user_file; ccv.zero = 1; ccv.conf_prefix = 1; diff --git a/src/http/modules/ngx_http_dav_module.c b/src/http/modules/ngx_http_dav_module.c index 8b69e6f..0cc9ae1 100644 --- a/src/http/modules/ngx_http_dav_module.c +++ b/src/http/modules/ngx_http_dav_module.c @@ -1072,6 +1072,10 @@ ngx_http_dav_error(ngx_log_t *log, ngx_err_t err, ngx_int_t not_found, static ngx_int_t ngx_http_dav_location(ngx_http_request_t *r) { + u_char *p; + size_t len; + uintptr_t escape; + r->headers_out.location = ngx_list_push(&r->headers_out.headers); if (r->headers_out.location == NULL) { return NGX_ERROR; @@ -1079,7 +1083,26 @@ ngx_http_dav_location(ngx_http_request_t *r) r->headers_out.location->hash = 1; ngx_str_set(&r->headers_out.location->key, "Location"); - r->headers_out.location->value = r->uri; + + escape = 2 * ngx_escape_uri(NULL, r->uri.data, r->uri.len, NGX_ESCAPE_URI); + + if (escape) { + len = r->uri.len + escape; + + p = ngx_pnalloc(r->pool, len); + if (p == NULL) { + ngx_http_clear_location(r); + return NGX_ERROR; + } + + r->headers_out.location->value.len = len; + r->headers_out.location->value.data = p; + + ngx_escape_uri(p, r->uri.data, r->uri.len, NGX_ESCAPE_URI); + + } else { + r->headers_out.location->value = r->uri; + } return NGX_OK; } diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c index 5191880..4a8dc33 100644 --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -2019,10 +2019,12 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r) break; } - /* there was error while a header line parsing */ + /* rc == NGX_HTTP_PARSE_INVALID_HEADER */ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "upstream sent invalid header"); + "upstream sent invalid header: \"%*s\\x%02xd...\"", + r->header_end - r->header_name_start, + r->header_name_start, *r->header_end); return NGX_HTTP_UPSTREAM_INVALID_HEADER; } diff --git a/src/http/modules/ngx_http_grpc_module.c b/src/http/modules/ngx_http_grpc_module.c index 27a36e8..864fc4f 100644 --- a/src/http/modules/ngx_http_grpc_module.c +++ b/src/http/modules/ngx_http_grpc_module.c @@ -37,9 +37,6 @@ typedef struct { ngx_uint_t ssl_verify_depth; ngx_str_t ssl_trusted_certificate; ngx_str_t ssl_crl; - ngx_str_t ssl_certificate; - ngx_str_t ssl_certificate_key; - ngx_array_t *ssl_passwords; ngx_array_t *ssl_conf_commands; #endif } ngx_http_grpc_loc_conf_t; @@ -426,16 +423,16 @@ static ngx_command_t ngx_http_grpc_commands[] = { { ngx_string("grpc_ssl_certificate"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_http_set_complex_value_zero_slot, NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_grpc_loc_conf_t, ssl_certificate), + offsetof(ngx_http_grpc_loc_conf_t, upstream.ssl_certificate), NULL }, { ngx_string("grpc_ssl_certificate_key"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_http_set_complex_value_zero_slot, NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_grpc_loc_conf_t, ssl_certificate_key), + offsetof(ngx_http_grpc_loc_conf_t, upstream.ssl_certificate_key), NULL }, { ngx_string("grpc_ssl_password_file"), @@ -2180,6 +2177,8 @@ ngx_http_grpc_filter(void *data, ssize_t bytes) } ctx->rst = 1; + + continue; } if (ctx->type == NGX_HTTP_V2_GOAWAY_FRAME) { @@ -3181,10 +3180,10 @@ ngx_http_grpc_parse_fragment(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx, ctx->field_rest -= size; if (ctx->field_huffman) { - if (ngx_http_v2_huff_decode(&ctx->field_state, p, size, - &ctx->field_end, - ctx->field_rest == 0, - r->connection->log) + if (ngx_http_huff_decode(&ctx->field_state, p, size, + &ctx->field_end, + ctx->field_rest == 0, + r->connection->log) != NGX_OK) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, @@ -3290,10 +3289,10 @@ ngx_http_grpc_parse_fragment(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx, ctx->field_rest -= size; if (ctx->field_huffman) { - if (ngx_http_v2_huff_decode(&ctx->field_state, p, size, - &ctx->field_end, - ctx->field_rest == 0, - r->connection->log) + if (ngx_http_huff_decode(&ctx->field_state, p, size, + &ctx->field_end, + ctx->field_rest == 0, + r->connection->log) != NGX_OK) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, @@ -3385,7 +3384,7 @@ ngx_http_grpc_validate_header_name(ngx_http_request_t *r, ngx_str_t *s) return NGX_ERROR; } - if (ch == '\0' || ch == CR || ch == LF) { + if (ch <= 0x20 || ch == 0x7f) { return NGX_ERROR; } } @@ -3487,6 +3486,8 @@ ngx_http_grpc_parse_rst_stream(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx, return NGX_AGAIN; } + ctx->state = ngx_http_grpc_st_start; + return NGX_OK; } @@ -4340,7 +4341,6 @@ ngx_http_grpc_create_loc_conf(ngx_conf_t *cf) * conf->upstream.ignore_headers = 0; * conf->upstream.next_upstream = 0; * conf->upstream.hide_headers_hash = { NULL, 0 }; - * conf->upstream.ssl_name = NULL; * * conf->headers.lengths = NULL; * conf->headers.values = NULL; @@ -4352,8 +4352,6 @@ ngx_http_grpc_create_loc_conf(ngx_conf_t *cf) * conf->ssl_ciphers = { 0, NULL }; * conf->ssl_trusted_certificate = { 0, NULL }; * conf->ssl_crl = { 0, NULL }; - * conf->ssl_certificate = { 0, NULL }; - * conf->ssl_certificate_key = { 0, NULL }; */ conf->upstream.local = NGX_CONF_UNSET_PTR; @@ -4373,10 +4371,13 @@ ngx_http_grpc_create_loc_conf(ngx_conf_t *cf) #if (NGX_HTTP_SSL) conf->upstream.ssl_session_reuse = NGX_CONF_UNSET; + conf->upstream.ssl_name = NGX_CONF_UNSET_PTR; conf->upstream.ssl_server_name = NGX_CONF_UNSET; conf->upstream.ssl_verify = NGX_CONF_UNSET; conf->ssl_verify_depth = NGX_CONF_UNSET_UINT; - conf->ssl_passwords = NGX_CONF_UNSET_PTR; + conf->upstream.ssl_certificate = NGX_CONF_UNSET_PTR; + conf->upstream.ssl_certificate_key = NGX_CONF_UNSET_PTR; + conf->upstream.ssl_passwords = NGX_CONF_UNSET_PTR; conf->ssl_conf_commands = NGX_CONF_UNSET_PTR; #endif @@ -4468,10 +4469,8 @@ ngx_http_grpc_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers, "DEFAULT"); - if (conf->upstream.ssl_name == NULL) { - conf->upstream.ssl_name = prev->upstream.ssl_name; - } - + ngx_conf_merge_ptr_value(conf->upstream.ssl_name, + prev->upstream.ssl_name, NULL); ngx_conf_merge_value(conf->upstream.ssl_server_name, prev->upstream.ssl_server_name, 0); ngx_conf_merge_value(conf->upstream.ssl_verify, @@ -4482,11 +4481,12 @@ ngx_http_grpc_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) prev->ssl_trusted_certificate, ""); ngx_conf_merge_str_value(conf->ssl_crl, prev->ssl_crl, ""); - ngx_conf_merge_str_value(conf->ssl_certificate, - prev->ssl_certificate, ""); - ngx_conf_merge_str_value(conf->ssl_certificate_key, - prev->ssl_certificate_key, ""); - ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL); + ngx_conf_merge_ptr_value(conf->upstream.ssl_certificate, + prev->upstream.ssl_certificate, NULL); + ngx_conf_merge_ptr_value(conf->upstream.ssl_certificate_key, + prev->upstream.ssl_certificate_key, NULL); + ngx_conf_merge_ptr_value(conf->upstream.ssl_passwords, + prev->upstream.ssl_passwords, NULL); ngx_conf_merge_ptr_value(conf->ssl_conf_commands, prev->ssl_conf_commands, NULL); @@ -4842,15 +4842,15 @@ ngx_http_grpc_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ngx_str_t *value; - if (glcf->ssl_passwords != NGX_CONF_UNSET_PTR) { + if (glcf->upstream.ssl_passwords != NGX_CONF_UNSET_PTR) { return "is duplicate"; } value = cf->args->elts; - glcf->ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]); + glcf->upstream.ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]); - if (glcf->ssl_passwords == NULL) { + if (glcf->upstream.ssl_passwords == NULL) { return NGX_CONF_ERROR; } @@ -4896,29 +4896,43 @@ ngx_http_grpc_set_ssl(ngx_conf_t *cf, ngx_http_grpc_loc_conf_t *glcf) cln->handler = ngx_ssl_cleanup_ctx; cln->data = glcf->upstream.ssl; - if (glcf->ssl_certificate.len) { - - if (glcf->ssl_certificate_key.len == 0) { - ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "no \"grpc_ssl_certificate_key\" is defined " - "for certificate \"%V\"", &glcf->ssl_certificate); - return NGX_ERROR; - } - - if (ngx_ssl_certificate(cf, glcf->upstream.ssl, &glcf->ssl_certificate, - &glcf->ssl_certificate_key, glcf->ssl_passwords) - != NGX_OK) - { - return NGX_ERROR; - } - } - if (ngx_ssl_ciphers(cf, glcf->upstream.ssl, &glcf->ssl_ciphers, 0) != NGX_OK) { return NGX_ERROR; } + if (glcf->upstream.ssl_certificate) { + + if (glcf->upstream.ssl_certificate_key == NULL) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "no \"grpc_ssl_certificate_key\" is defined " + "for certificate \"%V\"", + &glcf->upstream.ssl_certificate->value); + return NGX_ERROR; + } + + if (glcf->upstream.ssl_certificate->lengths + || glcf->upstream.ssl_certificate_key->lengths) + { + glcf->upstream.ssl_passwords = + ngx_ssl_preserve_passwords(cf, glcf->upstream.ssl_passwords); + if (glcf->upstream.ssl_passwords == NULL) { + return NGX_ERROR; + } + + } else { + if (ngx_ssl_certificate(cf, glcf->upstream.ssl, + &glcf->upstream.ssl_certificate->value, + &glcf->upstream.ssl_certificate_key->value, + glcf->upstream.ssl_passwords) + != NGX_OK) + { + return NGX_ERROR; + } + } + } + if (glcf->upstream.ssl_verify) { if (glcf->ssl_trusted_certificate.len == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, diff --git a/src/http/modules/ngx_http_mp4_module.c b/src/http/modules/ngx_http_mp4_module.c index 0e93fbd..9c3f627 100644 --- a/src/http/modules/ngx_http_mp4_module.c +++ b/src/http/modules/ngx_http_mp4_module.c @@ -11,31 +11,33 @@ #define NGX_HTTP_MP4_TRAK_ATOM 0 #define NGX_HTTP_MP4_TKHD_ATOM 1 -#define NGX_HTTP_MP4_MDIA_ATOM 2 -#define NGX_HTTP_MP4_MDHD_ATOM 3 -#define NGX_HTTP_MP4_HDLR_ATOM 4 -#define NGX_HTTP_MP4_MINF_ATOM 5 -#define NGX_HTTP_MP4_VMHD_ATOM 6 -#define NGX_HTTP_MP4_SMHD_ATOM 7 -#define NGX_HTTP_MP4_DINF_ATOM 8 -#define NGX_HTTP_MP4_STBL_ATOM 9 -#define NGX_HTTP_MP4_STSD_ATOM 10 -#define NGX_HTTP_MP4_STTS_ATOM 11 -#define NGX_HTTP_MP4_STTS_DATA 12 -#define NGX_HTTP_MP4_STSS_ATOM 13 -#define NGX_HTTP_MP4_STSS_DATA 14 -#define NGX_HTTP_MP4_CTTS_ATOM 15 -#define NGX_HTTP_MP4_CTTS_DATA 16 -#define NGX_HTTP_MP4_STSC_ATOM 17 -#define NGX_HTTP_MP4_STSC_START 18 -#define NGX_HTTP_MP4_STSC_DATA 19 -#define NGX_HTTP_MP4_STSC_END 20 -#define NGX_HTTP_MP4_STSZ_ATOM 21 -#define NGX_HTTP_MP4_STSZ_DATA 22 -#define NGX_HTTP_MP4_STCO_ATOM 23 -#define NGX_HTTP_MP4_STCO_DATA 24 -#define NGX_HTTP_MP4_CO64_ATOM 25 -#define NGX_HTTP_MP4_CO64_DATA 26 +#define NGX_HTTP_MP4_EDTS_ATOM 2 +#define NGX_HTTP_MP4_ELST_ATOM 3 +#define NGX_HTTP_MP4_MDIA_ATOM 4 +#define NGX_HTTP_MP4_MDHD_ATOM 5 +#define NGX_HTTP_MP4_HDLR_ATOM 6 +#define NGX_HTTP_MP4_MINF_ATOM 7 +#define NGX_HTTP_MP4_VMHD_ATOM 8 +#define NGX_HTTP_MP4_SMHD_ATOM 9 +#define NGX_HTTP_MP4_DINF_ATOM 10 +#define NGX_HTTP_MP4_STBL_ATOM 11 +#define NGX_HTTP_MP4_STSD_ATOM 12 +#define NGX_HTTP_MP4_STTS_ATOM 13 +#define NGX_HTTP_MP4_STTS_DATA 14 +#define NGX_HTTP_MP4_STSS_ATOM 15 +#define NGX_HTTP_MP4_STSS_DATA 16 +#define NGX_HTTP_MP4_CTTS_ATOM 17 +#define NGX_HTTP_MP4_CTTS_DATA 18 +#define NGX_HTTP_MP4_STSC_ATOM 19 +#define NGX_HTTP_MP4_STSC_START 20 +#define NGX_HTTP_MP4_STSC_DATA 21 +#define NGX_HTTP_MP4_STSC_END 22 +#define NGX_HTTP_MP4_STSZ_ATOM 23 +#define NGX_HTTP_MP4_STSZ_DATA 24 +#define NGX_HTTP_MP4_STCO_ATOM 25 +#define NGX_HTTP_MP4_STCO_DATA 26 +#define NGX_HTTP_MP4_CO64_ATOM 27 +#define NGX_HTTP_MP4_CO64_DATA 28 #define NGX_HTTP_MP4_LAST_ATOM NGX_HTTP_MP4_CO64_DATA @@ -43,6 +45,7 @@ typedef struct { size_t buffer_size; size_t max_buffer_size; + ngx_flag_t start_key_frame; } ngx_http_mp4_conf_t; @@ -53,6 +56,25 @@ typedef struct { } ngx_mp4_stsc_entry_t; +typedef struct { + u_char size[4]; + u_char name[4]; +} ngx_mp4_edts_atom_t; + + +typedef struct { + u_char size[4]; + u_char name[4]; + u_char version[1]; + u_char flags[3]; + u_char entries[4]; + u_char duration[8]; + u_char media_time[8]; + u_char media_rate[2]; + u_char reserved[2]; +} ngx_mp4_elst_atom_t; + + typedef struct { uint32_t timescale; uint32_t time_to_sample_entries; @@ -70,6 +92,9 @@ typedef struct { ngx_uint_t end_chunk_samples; uint64_t start_chunk_samples_size; uint64_t end_chunk_samples_size; + uint64_t duration; + uint64_t prefix; + uint64_t movie_duration; off_t start_offset; off_t end_offset; @@ -85,6 +110,8 @@ typedef struct { ngx_buf_t trak_atom_buf; ngx_buf_t tkhd_atom_buf; + ngx_buf_t edts_atom_buf; + ngx_buf_t elst_atom_buf; ngx_buf_t mdia_atom_buf; ngx_buf_t mdhd_atom_buf; ngx_buf_t hdlr_atom_buf; @@ -111,6 +138,8 @@ typedef struct { ngx_buf_t co64_atom_buf; ngx_buf_t co64_data_buf; + ngx_mp4_edts_atom_t edts_atom; + ngx_mp4_elst_atom_t elst_atom; ngx_mp4_stsc_entry_t stsc_start_chunk_entry; ngx_mp4_stsc_entry_t stsc_end_chunk_entry; } ngx_http_mp4_trak_t; @@ -186,6 +215,14 @@ typedef struct { ((u_char *) (p))[6] = n3; \ ((u_char *) (p))[7] = n4 +#define ngx_mp4_get_16value(p) \ + ( ((uint16_t) ((u_char *) (p))[0] << 8) \ + + ( ((u_char *) (p))[1]) ) + +#define ngx_mp4_set_16value(p, n) \ + ((u_char *) (p))[0] = (u_char) ((n) >> 8); \ + ((u_char *) (p))[1] = (u_char) (n) + #define ngx_mp4_get_32value(p) \ ( ((uint32_t) ((u_char *) (p))[0] << 24) \ + ( ((u_char *) (p))[1] << 16) \ @@ -253,6 +290,8 @@ static void ngx_http_mp4_update_mdia_atom(ngx_http_mp4_file_t *mp4, ngx_http_mp4_trak_t *trak); static ngx_int_t ngx_http_mp4_read_mdhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size); +static void ngx_http_mp4_update_mdhd_atom(ngx_http_mp4_file_t *mp4, + ngx_http_mp4_trak_t *trak); static ngx_int_t ngx_http_mp4_read_hdlr_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size); static ngx_int_t ngx_http_mp4_read_minf_atom(ngx_http_mp4_file_t *mp4, @@ -267,6 +306,8 @@ static ngx_int_t ngx_http_mp4_read_smhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size); static ngx_int_t ngx_http_mp4_read_stbl_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size); +static void ngx_http_mp4_update_edts_atom(ngx_http_mp4_file_t *mp4, + ngx_http_mp4_trak_t *trak); static void ngx_http_mp4_update_stbl_atom(ngx_http_mp4_file_t *mp4, ngx_http_mp4_trak_t *trak); static ngx_int_t ngx_http_mp4_read_stsd_atom(ngx_http_mp4_file_t *mp4, @@ -277,6 +318,8 @@ static ngx_int_t ngx_http_mp4_update_stts_atom(ngx_http_mp4_file_t *mp4, ngx_http_mp4_trak_t *trak); static ngx_int_t ngx_http_mp4_crop_stts_data(ngx_http_mp4_file_t *mp4, ngx_http_mp4_trak_t *trak, ngx_uint_t start); +static uint32_t ngx_http_mp4_seek_key_frame(ngx_http_mp4_file_t *mp4, + ngx_http_mp4_trak_t *trak, uint32_t start_sample); static ngx_int_t ngx_http_mp4_read_stss_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size); static ngx_int_t ngx_http_mp4_update_stss_atom(ngx_http_mp4_file_t *mp4, @@ -340,6 +383,13 @@ static ngx_command_t ngx_http_mp4_commands[] = { offsetof(ngx_http_mp4_conf_t, max_buffer_size), NULL }, + { ngx_string("mp4_start_key_frame"), + 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_mp4_conf_t, start_key_frame), + NULL }, + ngx_null_command }; @@ -822,10 +872,11 @@ ngx_http_mp4_process(ngx_http_mp4_file_t *mp4) ngx_http_mp4_update_stbl_atom(mp4, &trak[i]); ngx_http_mp4_update_minf_atom(mp4, &trak[i]); - trak[i].size += trak[i].mdhd_size; + ngx_http_mp4_update_mdhd_atom(mp4, &trak[i]); trak[i].size += trak[i].hdlr_size; ngx_http_mp4_update_mdia_atom(mp4, &trak[i]); trak[i].size += trak[i].tkhd_size; + ngx_http_mp4_update_edts_atom(mp4, &trak[i]); ngx_http_mp4_update_trak_atom(mp4, &trak[i]); mp4->moov_size += trak[i].size; @@ -1587,6 +1638,7 @@ ngx_http_mp4_read_tkhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size) trak = ngx_mp4_last_trak(mp4); trak->tkhd_size = atom_size; + trak->movie_duration = duration; ngx_mp4_set_32value(tkhd_atom->size, atom_size); @@ -1749,16 +1801,10 @@ ngx_http_mp4_read_mdhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size) trak = ngx_mp4_last_trak(mp4); trak->mdhd_size = atom_size; trak->timescale = timescale; + trak->duration = duration; ngx_mp4_set_32value(mdhd_atom->size, atom_size); - if (mdhd_atom->version[0] == 0) { - ngx_mp4_set_32value(mdhd_atom->duration, duration); - - } else { - ngx_mp4_set_64value(mdhd64_atom->duration, duration); - } - atom = &trak->mdhd_atom_buf; atom->temporary = 1; atom->pos = atom_header; @@ -1772,6 +1818,33 @@ ngx_http_mp4_read_mdhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size) } +static void +ngx_http_mp4_update_mdhd_atom(ngx_http_mp4_file_t *mp4, + ngx_http_mp4_trak_t *trak) +{ + ngx_buf_t *atom; + ngx_mp4_mdhd_atom_t *mdhd_atom; + ngx_mp4_mdhd64_atom_t *mdhd64_atom; + + atom = trak->out[NGX_HTTP_MP4_MDHD_ATOM].buf; + if (atom == NULL) { + return; + } + + mdhd_atom = (ngx_mp4_mdhd_atom_t *) atom->pos; + mdhd64_atom = (ngx_mp4_mdhd64_atom_t *) atom->pos; + + if (mdhd_atom->version[0] == 0) { + ngx_mp4_set_32value(mdhd_atom->duration, trak->duration); + + } else { + ngx_mp4_set_64value(mdhd64_atom->duration, trak->duration); + } + + trak->size += trak->mdhd_size; +} + + static ngx_int_t ngx_http_mp4_read_hdlr_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size) { @@ -1961,6 +2034,59 @@ ngx_http_mp4_read_stbl_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size) } +static void +ngx_http_mp4_update_edts_atom(ngx_http_mp4_file_t *mp4, + ngx_http_mp4_trak_t *trak) +{ + ngx_buf_t *atom; + ngx_mp4_elst_atom_t *elst_atom; + ngx_mp4_edts_atom_t *edts_atom; + + if (trak->prefix == 0) { + return; + } + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, + "mp4 edts atom update prefix:%uL", trak->prefix); + + edts_atom = &trak->edts_atom; + ngx_mp4_set_32value(edts_atom->size, sizeof(ngx_mp4_edts_atom_t) + + sizeof(ngx_mp4_elst_atom_t)); + ngx_mp4_set_atom_name(edts_atom, 'e', 'd', 't', 's'); + + atom = &trak->edts_atom_buf; + atom->temporary = 1; + atom->pos = (u_char *) edts_atom; + atom->last = (u_char *) edts_atom + sizeof(ngx_mp4_edts_atom_t); + + trak->out[NGX_HTTP_MP4_EDTS_ATOM].buf = atom; + + elst_atom = &trak->elst_atom; + ngx_mp4_set_32value(elst_atom->size, sizeof(ngx_mp4_elst_atom_t)); + ngx_mp4_set_atom_name(elst_atom, 'e', 'l', 's', 't'); + + elst_atom->version[0] = 1; + elst_atom->flags[0] = 0; + elst_atom->flags[1] = 0; + elst_atom->flags[2] = 0; + + ngx_mp4_set_32value(elst_atom->entries, 1); + ngx_mp4_set_64value(elst_atom->duration, trak->movie_duration); + ngx_mp4_set_64value(elst_atom->media_time, trak->prefix); + ngx_mp4_set_16value(elst_atom->media_rate, 1); + ngx_mp4_set_16value(elst_atom->reserved, 0); + + atom = &trak->elst_atom_buf; + atom->temporary = 1; + atom->pos = (u_char *) elst_atom; + atom->last = (u_char *) elst_atom + sizeof(ngx_mp4_elst_atom_t); + + trak->out[NGX_HTTP_MP4_ELST_ATOM].buf = atom; + + trak->size += sizeof(ngx_mp4_edts_atom_t) + sizeof(ngx_mp4_elst_atom_t); +} + + static void ngx_http_mp4_update_stbl_atom(ngx_http_mp4_file_t *mp4, ngx_http_mp4_trak_t *trak) @@ -2159,7 +2285,7 @@ static ngx_int_t ngx_http_mp4_crop_stts_data(ngx_http_mp4_file_t *mp4, ngx_http_mp4_trak_t *trak, ngx_uint_t start) { - uint32_t count, duration, rest; + uint32_t count, duration, rest, key_prefix; uint64_t start_time; ngx_buf_t *data; ngx_uint_t start_sample, entries, start_sec; @@ -2183,7 +2309,7 @@ ngx_http_mp4_crop_stts_data(ngx_http_mp4_file_t *mp4, data = trak->out[NGX_HTTP_MP4_STTS_DATA].buf; - start_time = (uint64_t) start_sec * trak->timescale / 1000; + start_time = (uint64_t) start_sec * trak->timescale / 1000 + trak->prefix; entries = trak->time_to_sample_entries; start_sample = 0; @@ -2229,6 +2355,26 @@ ngx_http_mp4_crop_stts_data(ngx_http_mp4_file_t *mp4, found: if (start) { + key_prefix = ngx_http_mp4_seek_key_frame(mp4, trak, start_sample); + + start_sample -= key_prefix; + + while (rest < key_prefix) { + trak->prefix += rest * duration; + key_prefix -= rest; + + entry--; + entries++; + + count = ngx_mp4_get_32value(entry->count); + duration = ngx_mp4_get_32value(entry->duration); + rest = count; + } + + trak->prefix += key_prefix * duration; + trak->duration += trak->prefix; + rest -= key_prefix; + ngx_mp4_set_32value(entry->count, count - rest); data->pos = (u_char *) entry; trak->time_to_sample_entries = entries; @@ -2253,6 +2399,49 @@ found: } +static uint32_t +ngx_http_mp4_seek_key_frame(ngx_http_mp4_file_t *mp4, ngx_http_mp4_trak_t *trak, + uint32_t start_sample) +{ + uint32_t key_prefix, sample, *entry, *end; + ngx_buf_t *data; + ngx_http_mp4_conf_t *conf; + + conf = ngx_http_get_module_loc_conf(mp4->request, ngx_http_mp4_module); + if (!conf->start_key_frame) { + return 0; + } + + data = trak->out[NGX_HTTP_MP4_STSS_DATA].buf; + if (data == NULL) { + return 0; + } + + entry = (uint32_t *) data->pos; + end = (uint32_t *) data->last; + + /* sync samples starts from 1 */ + start_sample++; + + key_prefix = 0; + + while (entry < end) { + sample = ngx_mp4_get_32value(entry); + if (sample > start_sample) { + break; + } + + key_prefix = start_sample - sample; + entry++; + } + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, + "mp4 key frame prefix:%uD", key_prefix); + + return key_prefix; +} + + typedef struct { u_char size[4]; u_char name[4]; @@ -3590,6 +3779,7 @@ ngx_http_mp4_create_conf(ngx_conf_t *cf) conf->buffer_size = NGX_CONF_UNSET_SIZE; conf->max_buffer_size = NGX_CONF_UNSET_SIZE; + conf->start_key_frame = NGX_CONF_UNSET; return conf; } @@ -3604,6 +3794,7 @@ ngx_http_mp4_merge_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size, 512 * 1024); ngx_conf_merge_size_value(conf->max_buffer_size, prev->max_buffer_size, 10 * 1024 * 1024); + ngx_conf_merge_value(conf->start_key_frame, prev->start_key_frame, 0); return NGX_CONF_OK; } diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c index a63c3ed..7c4061c 100644 --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -124,9 +124,6 @@ typedef struct { ngx_uint_t ssl_verify_depth; ngx_str_t ssl_trusted_certificate; ngx_str_t ssl_crl; - ngx_str_t ssl_certificate; - ngx_str_t ssl_certificate_key; - ngx_array_t *ssl_passwords; ngx_array_t *ssl_conf_commands; #endif } ngx_http_proxy_loc_conf_t; @@ -753,16 +750,16 @@ static ngx_command_t ngx_http_proxy_commands[] = { { ngx_string("proxy_ssl_certificate"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_http_set_complex_value_zero_slot, NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_proxy_loc_conf_t, ssl_certificate), + offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_certificate), NULL }, { ngx_string("proxy_ssl_certificate_key"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_http_set_complex_value_zero_slot, NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_proxy_loc_conf_t, ssl_certificate_key), + offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_certificate_key), NULL }, { ngx_string("proxy_ssl_password_file"), @@ -1189,7 +1186,7 @@ ngx_http_proxy_create_key(ngx_http_request_t *r) loc_len = (r->valid_location && ctx->vars.uri.len) ? plcf->location.len : 0; - if (r->quoted_uri || r->space_in_uri || r->internal) { + if (r->quoted_uri || r->internal) { escape = 2 * ngx_escape_uri(NULL, r->uri.data + loc_len, r->uri.len - loc_len, NGX_ESCAPE_URI); } else { @@ -1302,7 +1299,7 @@ ngx_http_proxy_create_request(ngx_http_request_t *r) loc_len = (r->valid_location && ctx->vars.uri.len) ? plcf->location.len : 0; - if (r->quoted_uri || r->space_in_uri || r->internal) { + if (r->quoted_uri || r->internal) { escape = 2 * ngx_escape_uri(NULL, r->uri.data + loc_len, r->uri.len - loc_len, NGX_ESCAPE_URI); } @@ -2022,10 +2019,12 @@ ngx_http_proxy_process_header(ngx_http_request_t *r) return NGX_AGAIN; } - /* there was error while a header line parsing */ + /* rc == NGX_HTTP_PARSE_INVALID_HEADER */ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "upstream sent invalid header"); + "upstream sent invalid header: \"%*s\\x%02xd...\"", + r->header_end - r->header_name_start, + r->header_name_start, *r->header_end); return NGX_HTTP_UPSTREAM_INVALID_HEADER; } @@ -2338,6 +2337,7 @@ ngx_http_proxy_non_buffered_copy_filter(void *data, ssize_t bytes) ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, "upstream sent more data than specified in " "\"Content-Length\" header"); + u->keepalive = 0; return NGX_OK; } @@ -3327,9 +3327,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf) * conf->upstream.hide_headers_hash = { NULL, 0 }; * conf->upstream.store_lengths = NULL; * conf->upstream.store_values = NULL; - * conf->upstream.ssl_name = NULL; * - * conf->method = NULL; * conf->location = NULL; * conf->url = { 0, NULL }; * conf->headers.lengths = NULL; @@ -3347,8 +3345,6 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf) * conf->ssl_ciphers = { 0, NULL }; * conf->ssl_trusted_certificate = { 0, NULL }; * conf->ssl_crl = { 0, NULL }; - * conf->ssl_certificate = { 0, NULL }; - * conf->ssl_certificate_key = { 0, NULL }; */ conf->upstream.store = NGX_CONF_UNSET; @@ -3400,20 +3396,26 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf) #if (NGX_HTTP_SSL) conf->upstream.ssl_session_reuse = NGX_CONF_UNSET; + conf->upstream.ssl_name = NGX_CONF_UNSET_PTR; conf->upstream.ssl_server_name = NGX_CONF_UNSET; conf->upstream.ssl_verify = NGX_CONF_UNSET; + conf->upstream.ssl_certificate = NGX_CONF_UNSET_PTR; + conf->upstream.ssl_certificate_key = NGX_CONF_UNSET_PTR; + conf->upstream.ssl_passwords = NGX_CONF_UNSET_PTR; conf->ssl_verify_depth = NGX_CONF_UNSET_UINT; - conf->ssl_passwords = NGX_CONF_UNSET_PTR; conf->ssl_conf_commands = NGX_CONF_UNSET_PTR; #endif /* "proxy_cyclic_temp_file" is disabled */ conf->upstream.cyclic_temp_file = 0; + conf->upstream.change_buffering = 1; + conf->headers_source = NGX_CONF_UNSET_PTR; + conf->method = NGX_CONF_UNSET_PTR; + conf->redirect = NGX_CONF_UNSET; - conf->upstream.change_buffering = 1; conf->cookie_domains = NGX_CONF_UNSET_PTR; conf->cookie_paths = NGX_CONF_UNSET_PTR; @@ -3708,10 +3710,6 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) #endif - if (conf->method == NULL) { - conf->method = prev->method; - } - ngx_conf_merge_value(conf->upstream.pass_request_headers, prev->upstream.pass_request_headers, 1); ngx_conf_merge_value(conf->upstream.pass_request_body, @@ -3732,10 +3730,8 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers, "DEFAULT"); - if (conf->upstream.ssl_name == NULL) { - conf->upstream.ssl_name = prev->upstream.ssl_name; - } - + ngx_conf_merge_ptr_value(conf->upstream.ssl_name, + prev->upstream.ssl_name, NULL); ngx_conf_merge_value(conf->upstream.ssl_server_name, prev->upstream.ssl_server_name, 0); ngx_conf_merge_value(conf->upstream.ssl_verify, @@ -3746,11 +3742,12 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) prev->ssl_trusted_certificate, ""); ngx_conf_merge_str_value(conf->ssl_crl, prev->ssl_crl, ""); - ngx_conf_merge_str_value(conf->ssl_certificate, - prev->ssl_certificate, ""); - ngx_conf_merge_str_value(conf->ssl_certificate_key, - prev->ssl_certificate_key, ""); - ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL); + ngx_conf_merge_ptr_value(conf->upstream.ssl_certificate, + prev->upstream.ssl_certificate, NULL); + ngx_conf_merge_ptr_value(conf->upstream.ssl_certificate_key, + prev->upstream.ssl_certificate_key, NULL); + ngx_conf_merge_ptr_value(conf->upstream.ssl_passwords, + prev->upstream.ssl_passwords, NULL); ngx_conf_merge_ptr_value(conf->ssl_conf_commands, prev->ssl_conf_commands, NULL); @@ -3761,6 +3758,8 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) #endif + ngx_conf_merge_ptr_value(conf->method, prev->method, NULL); + ngx_conf_merge_value(conf->redirect, prev->redirect, 1); if (conf->redirect) { @@ -4859,15 +4858,15 @@ ngx_http_proxy_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ngx_str_t *value; - if (plcf->ssl_passwords != NGX_CONF_UNSET_PTR) { + if (plcf->upstream.ssl_passwords != NGX_CONF_UNSET_PTR) { return "is duplicate"; } value = cf->args->elts; - plcf->ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]); + plcf->upstream.ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]); - if (plcf->ssl_passwords == NULL) { + if (plcf->upstream.ssl_passwords == NULL) { return NGX_CONF_ERROR; } @@ -4946,29 +4945,43 @@ ngx_http_proxy_set_ssl(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *plcf) cln->handler = ngx_ssl_cleanup_ctx; cln->data = plcf->upstream.ssl; - if (plcf->ssl_certificate.len) { - - if (plcf->ssl_certificate_key.len == 0) { - ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "no \"proxy_ssl_certificate_key\" is defined " - "for certificate \"%V\"", &plcf->ssl_certificate); - return NGX_ERROR; - } - - if (ngx_ssl_certificate(cf, plcf->upstream.ssl, &plcf->ssl_certificate, - &plcf->ssl_certificate_key, plcf->ssl_passwords) - != NGX_OK) - { - return NGX_ERROR; - } - } - if (ngx_ssl_ciphers(cf, plcf->upstream.ssl, &plcf->ssl_ciphers, 0) != NGX_OK) { return NGX_ERROR; } + if (plcf->upstream.ssl_certificate) { + + if (plcf->upstream.ssl_certificate_key == NULL) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "no \"proxy_ssl_certificate_key\" is defined " + "for certificate \"%V\"", + &plcf->upstream.ssl_certificate->value); + return NGX_ERROR; + } + + if (plcf->upstream.ssl_certificate->lengths + || plcf->upstream.ssl_certificate_key->lengths) + { + plcf->upstream.ssl_passwords = + ngx_ssl_preserve_passwords(cf, plcf->upstream.ssl_passwords); + if (plcf->upstream.ssl_passwords == NULL) { + return NGX_ERROR; + } + + } else { + if (ngx_ssl_certificate(cf, plcf->upstream.ssl, + &plcf->upstream.ssl_certificate->value, + &plcf->upstream.ssl_certificate_key->value, + plcf->upstream.ssl_passwords) + != NGX_OK) + { + return NGX_ERROR; + } + } + } + if (plcf->upstream.ssl_verify) { if (plcf->ssl_trusted_certificate.len == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, diff --git a/src/http/modules/ngx_http_scgi_module.c b/src/http/modules/ngx_http_scgi_module.c index 600999c..e5d31ae 100644 --- a/src/http/modules/ngx_http_scgi_module.c +++ b/src/http/modules/ngx_http_scgi_module.c @@ -1140,10 +1140,12 @@ ngx_http_scgi_process_header(ngx_http_request_t *r) return NGX_AGAIN; } - /* there was error while a header line parsing */ + /* rc == NGX_HTTP_PARSE_INVALID_HEADER */ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "upstream sent invalid header"); + "upstream sent invalid header: \"%*s\\x%02xd...\"", + r->header_end - r->header_name_start, + r->header_name_start, *r->header_end); return NGX_HTTP_UPSTREAM_INVALID_HEADER; } diff --git a/src/http/modules/ngx_http_secure_link_module.c b/src/http/modules/ngx_http_secure_link_module.c index 536e09a..4d4ce6a 100644 --- a/src/http/modules/ngx_http_secure_link_module.c +++ b/src/http/modules/ngx_http_secure_link_module.c @@ -302,11 +302,12 @@ ngx_http_secure_link_create_conf(ngx_conf_t *cf) /* * set by ngx_pcalloc(): * - * conf->variable = NULL; - * conf->md5 = NULL; * conf->secret = { 0, NULL }; */ + conf->variable = NGX_CONF_UNSET_PTR; + conf->md5 = NGX_CONF_UNSET_PTR; + return conf; } @@ -318,6 +319,9 @@ ngx_http_secure_link_merge_conf(ngx_conf_t *cf, void *parent, void *child) ngx_http_secure_link_conf_t *conf = child; if (conf->secret.data) { + ngx_conf_init_ptr_value(conf->variable, NULL); + ngx_conf_init_ptr_value(conf->md5, NULL); + if (conf->variable || conf->md5) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "\"secure_link_secret\" cannot be mixed with " @@ -328,13 +332,8 @@ ngx_http_secure_link_merge_conf(ngx_conf_t *cf, void *parent, void *child) return NGX_CONF_OK; } - if (conf->variable == NULL) { - conf->variable = prev->variable; - } - - if (conf->md5 == NULL) { - conf->md5 = prev->md5; - } + ngx_conf_merge_ptr_value(conf->variable, prev->variable, NULL); + ngx_conf_merge_ptr_value(conf->md5, prev->md5, NULL); if (conf->variable == NULL && conf->md5 == NULL) { conf->secret = prev->secret; diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c index a47d696..d74d460 100644 --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -17,7 +17,7 @@ typedef ngx_int_t (*ngx_ssl_variable_handler_pt)(ngx_connection_t *c, #define NGX_DEFAULT_CIPHERS "HIGH:!aNULL:!MD5" #define NGX_DEFAULT_ECDH_CURVE "auto" -#define NGX_HTTP_NPN_ADVERTISE "\x08http/1.1" +#define NGX_HTTP_ALPN_PROTOS "\x08http/1.1\x08http/1.0\x08http/0.9" #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation @@ -26,11 +26,6 @@ static int ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char *in, unsigned int inlen, void *arg); #endif -#ifdef TLSEXT_TYPE_next_proto_neg -static int ngx_http_ssl_npn_advertised(ngx_ssl_conn_t *ssl_conn, - const unsigned char **out, unsigned int *outlen, void *arg); -#endif - static ngx_int_t ngx_http_ssl_static_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_ssl_variable(ngx_http_request_t *r, @@ -347,6 +342,9 @@ static ngx_http_variable_t ngx_http_ssl_vars[] = { { ngx_string("ssl_ciphers"), NULL, ngx_http_ssl_variable, (uintptr_t) ngx_ssl_get_ciphers, NGX_HTTP_VAR_CHANGEABLE, 0 }, + { ngx_string("ssl_curve"), NULL, ngx_http_ssl_variable, + (uintptr_t) ngx_ssl_get_curve, 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 }, @@ -363,6 +361,9 @@ static ngx_http_variable_t ngx_http_ssl_vars[] = { { ngx_string("ssl_server_name"), NULL, ngx_http_ssl_variable, (uintptr_t) ngx_ssl_get_server_name, NGX_HTTP_VAR_CHANGEABLE, 0 }, + { ngx_string("ssl_alpn_protocol"), NULL, ngx_http_ssl_variable, + (uintptr_t) ngx_ssl_get_alpn_protocol, NGX_HTTP_VAR_CHANGEABLE, 0 }, + { ngx_string("ssl_client_cert"), NULL, ngx_http_ssl_variable, (uintptr_t) ngx_ssl_get_certificate, NGX_HTTP_VAR_CHANGEABLE, 0 }, @@ -444,22 +445,20 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out, hc = c->data; if (hc->addr_conf->http2) { - srv = - (unsigned char *) NGX_HTTP_V2_ALPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE; - srvlen = sizeof(NGX_HTTP_V2_ALPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE) - 1; - + srv = (unsigned char *) NGX_HTTP_V2_ALPN_PROTO NGX_HTTP_ALPN_PROTOS; + srvlen = sizeof(NGX_HTTP_V2_ALPN_PROTO NGX_HTTP_ALPN_PROTOS) - 1; } else #endif { - srv = (unsigned char *) NGX_HTTP_NPN_ADVERTISE; - srvlen = sizeof(NGX_HTTP_NPN_ADVERTISE) - 1; + srv = (unsigned char *) NGX_HTTP_ALPN_PROTOS; + srvlen = sizeof(NGX_HTTP_ALPN_PROTOS) - 1; } if (SSL_select_next_proto((unsigned char **) out, outlen, srv, srvlen, in, inlen) != OPENSSL_NPN_NEGOTIATED) { - return SSL_TLSEXT_ERR_NOACK; + return SSL_TLSEXT_ERR_ALERT_FATAL; } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, @@ -471,44 +470,6 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out, #endif -#ifdef TLSEXT_TYPE_next_proto_neg - -static int -ngx_http_ssl_npn_advertised(ngx_ssl_conn_t *ssl_conn, - const unsigned char **out, unsigned int *outlen, void *arg) -{ -#if (NGX_HTTP_V2 || NGX_DEBUG) - ngx_connection_t *c; - - c = ngx_ssl_get_connection(ssl_conn); - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "SSL NPN advertised"); -#endif - -#if (NGX_HTTP_V2) - { - ngx_http_connection_t *hc; - - hc = c->data; - - if (hc->addr_conf->http2) { - *out = - (unsigned char *) NGX_HTTP_V2_NPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE; - *outlen = sizeof(NGX_HTTP_V2_NPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE) - 1; - - return SSL_TLSEXT_ERR_OK; - } - } -#endif - - *out = (unsigned char *) NGX_HTTP_NPN_ADVERTISE; - *outlen = sizeof(NGX_HTTP_NPN_ADVERTISE) - 1; - - return SSL_TLSEXT_ERR_OK; -} - -#endif - - static ngx_int_t ngx_http_ssl_static_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) @@ -792,10 +753,12 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) SSL_CTX_set_alpn_select_cb(conf->ssl.ctx, ngx_http_ssl_alpn_select, NULL); #endif -#ifdef TLSEXT_TYPE_next_proto_neg - SSL_CTX_set_next_protos_advertised_cb(conf->ssl.ctx, - ngx_http_ssl_npn_advertised, NULL); -#endif + if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers, + conf->prefer_server_ciphers) + != NGX_OK) + { + return NGX_CONF_ERROR; + } if (ngx_http_ssl_compile_certificates(cf, conf) != NGX_OK) { return NGX_CONF_ERROR; @@ -829,13 +792,6 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) } } - if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers, - conf->prefer_server_ciphers) - != NGX_OK) - { - return NGX_CONF_ERROR; - } - conf->ssl.buffer_size = conf->buffer_size; if (conf->verify) { diff --git a/src/http/modules/ngx_http_static_module.c b/src/http/modules/ngx_http_static_module.c index 282d6ee..cf29d5a 100644 --- a/src/http/modules/ngx_http_static_module.c +++ b/src/http/modules/ngx_http_static_module.c @@ -50,6 +50,7 @@ ngx_http_static_handler(ngx_http_request_t *r) { u_char *last, *location; size_t root, len; + uintptr_t escape; ngx_str_t path; ngx_int_t rc; ngx_uint_t level; @@ -155,14 +156,18 @@ ngx_http_static_handler(ngx_http_request_t *r) return NGX_HTTP_INTERNAL_SERVER_ERROR; } - len = r->uri.len + 1; + escape = 2 * ngx_escape_uri(NULL, r->uri.data, r->uri.len, + NGX_ESCAPE_URI); - if (!clcf->alias && r->args.len == 0) { + if (!clcf->alias && r->args.len == 0 && escape == 0) { + len = r->uri.len + 1; location = path.data + root; *last = '/'; } else { + len = r->uri.len + escape + 1; + if (r->args.len) { len += r->args.len + 1; } @@ -173,7 +178,13 @@ ngx_http_static_handler(ngx_http_request_t *r) return NGX_HTTP_INTERNAL_SERVER_ERROR; } - last = ngx_copy(location, r->uri.data, r->uri.len); + if (escape) { + last = (u_char *) ngx_escape_uri(location, r->uri.data, + r->uri.len, NGX_ESCAPE_URI); + + } else { + last = ngx_copy(location, r->uri.data, r->uri.len); + } *last = '/'; diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c index 1334f44..d46741a 100644 --- a/src/http/modules/ngx_http_uwsgi_module.c +++ b/src/http/modules/ngx_http_uwsgi_module.c @@ -54,9 +54,6 @@ typedef struct { ngx_uint_t ssl_verify_depth; ngx_str_t ssl_trusted_certificate; ngx_str_t ssl_crl; - ngx_str_t ssl_certificate; - ngx_str_t ssl_certificate_key; - ngx_array_t *ssl_passwords; ngx_array_t *ssl_conf_commands; #endif } ngx_http_uwsgi_loc_conf_t; @@ -548,16 +545,16 @@ static ngx_command_t ngx_http_uwsgi_commands[] = { { ngx_string("uwsgi_ssl_certificate"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_http_set_complex_value_zero_slot, NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_uwsgi_loc_conf_t, ssl_certificate), + offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ssl_certificate), NULL }, { ngx_string("uwsgi_ssl_certificate_key"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_http_set_complex_value_zero_slot, NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_uwsgi_loc_conf_t, ssl_certificate_key), + offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ssl_certificate_key), NULL }, { ngx_string("uwsgi_ssl_password_file"), @@ -1364,10 +1361,12 @@ ngx_http_uwsgi_process_header(ngx_http_request_t *r) return NGX_AGAIN; } - /* there was error while a header line parsing */ + /* rc == NGX_HTTP_PARSE_INVALID_HEADER */ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "upstream sent invalid header"); + "upstream sent invalid header: \"%*s\\x%02xd...\"", + r->header_end - r->header_name_start, + r->header_name_start, *r->header_end); return NGX_HTTP_UPSTREAM_INVALID_HEADER; } @@ -1509,10 +1508,13 @@ ngx_http_uwsgi_create_loc_conf(ngx_conf_t *cf) #if (NGX_HTTP_SSL) conf->upstream.ssl_session_reuse = NGX_CONF_UNSET; + conf->upstream.ssl_name = NGX_CONF_UNSET_PTR; conf->upstream.ssl_server_name = NGX_CONF_UNSET; conf->upstream.ssl_verify = NGX_CONF_UNSET; conf->ssl_verify_depth = NGX_CONF_UNSET_UINT; - conf->ssl_passwords = NGX_CONF_UNSET_PTR; + conf->upstream.ssl_certificate = NGX_CONF_UNSET_PTR; + conf->upstream.ssl_certificate_key = NGX_CONF_UNSET_PTR; + conf->upstream.ssl_passwords = NGX_CONF_UNSET_PTR; conf->ssl_conf_commands = NGX_CONF_UNSET_PTR; #endif @@ -1824,10 +1826,8 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers, "DEFAULT"); - if (conf->upstream.ssl_name == NULL) { - conf->upstream.ssl_name = prev->upstream.ssl_name; - } - + ngx_conf_merge_ptr_value(conf->upstream.ssl_name, + prev->upstream.ssl_name, NULL); ngx_conf_merge_value(conf->upstream.ssl_server_name, prev->upstream.ssl_server_name, 0); ngx_conf_merge_value(conf->upstream.ssl_verify, @@ -1838,11 +1838,12 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) prev->ssl_trusted_certificate, ""); ngx_conf_merge_str_value(conf->ssl_crl, prev->ssl_crl, ""); - ngx_conf_merge_str_value(conf->ssl_certificate, - prev->ssl_certificate, ""); - ngx_conf_merge_str_value(conf->ssl_certificate_key, - prev->ssl_certificate_key, ""); - ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL); + ngx_conf_merge_ptr_value(conf->upstream.ssl_certificate, + prev->upstream.ssl_certificate, NULL); + ngx_conf_merge_ptr_value(conf->upstream.ssl_certificate_key, + prev->upstream.ssl_certificate_key, NULL); + ngx_conf_merge_ptr_value(conf->upstream.ssl_passwords, + prev->upstream.ssl_passwords, NULL); ngx_conf_merge_ptr_value(conf->ssl_conf_commands, prev->ssl_conf_commands, NULL); @@ -2377,15 +2378,15 @@ ngx_http_uwsgi_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ngx_str_t *value; - if (uwcf->ssl_passwords != NGX_CONF_UNSET_PTR) { + if (uwcf->upstream.ssl_passwords != NGX_CONF_UNSET_PTR) { return "is duplicate"; } value = cf->args->elts; - uwcf->ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]); + uwcf->upstream.ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]); - if (uwcf->ssl_passwords == NULL) { + if (uwcf->upstream.ssl_passwords == NULL) { return NGX_CONF_ERROR; } @@ -2431,29 +2432,43 @@ ngx_http_uwsgi_set_ssl(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *uwcf) cln->handler = ngx_ssl_cleanup_ctx; cln->data = uwcf->upstream.ssl; - if (uwcf->ssl_certificate.len) { - - if (uwcf->ssl_certificate_key.len == 0) { - ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "no \"uwsgi_ssl_certificate_key\" is defined " - "for certificate \"%V\"", &uwcf->ssl_certificate); - return NGX_ERROR; - } - - if (ngx_ssl_certificate(cf, uwcf->upstream.ssl, &uwcf->ssl_certificate, - &uwcf->ssl_certificate_key, uwcf->ssl_passwords) - != NGX_OK) - { - return NGX_ERROR; - } - } - if (ngx_ssl_ciphers(cf, uwcf->upstream.ssl, &uwcf->ssl_ciphers, 0) != NGX_OK) { return NGX_ERROR; } + if (uwcf->upstream.ssl_certificate) { + + if (uwcf->upstream.ssl_certificate_key == NULL) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "no \"uwsgi_ssl_certificate_key\" is defined " + "for certificate \"%V\"", + &uwcf->upstream.ssl_certificate->value); + return NGX_ERROR; + } + + if (uwcf->upstream.ssl_certificate->lengths + || uwcf->upstream.ssl_certificate_key->lengths) + { + uwcf->upstream.ssl_passwords = + ngx_ssl_preserve_passwords(cf, uwcf->upstream.ssl_passwords); + if (uwcf->upstream.ssl_passwords == NULL) { + return NGX_ERROR; + } + + } else { + if (ngx_ssl_certificate(cf, uwcf->upstream.ssl, + &uwcf->upstream.ssl_certificate->value, + &uwcf->upstream.ssl_certificate_key->value, + uwcf->upstream.ssl_passwords) + != NGX_OK) + { + return NGX_ERROR; + } + } + } + if (uwcf->upstream.ssl_verify) { if (uwcf->ssl_trusted_certificate.len == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c index e1d3d00..73c08d5 100644 --- a/src/http/ngx_http.c +++ b/src/http/ngx_http.c @@ -37,6 +37,8 @@ static ngx_int_t ngx_http_init_locations(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, ngx_http_core_loc_conf_t *pclcf); static ngx_int_t ngx_http_init_static_location_trees(ngx_conf_t *cf, ngx_http_core_loc_conf_t *pclcf); +static ngx_int_t ngx_http_escape_location_name(ngx_conf_t *cf, + ngx_http_core_loc_conf_t *clcf); static ngx_int_t ngx_http_cmp_locations(const ngx_queue_t *one, const ngx_queue_t *two); static ngx_int_t ngx_http_join_exact_locations(ngx_conf_t *cf, @@ -882,6 +884,41 @@ ngx_http_add_location(ngx_conf_t *cf, ngx_queue_t **locations, ngx_queue_insert_tail(*locations, &lq->queue); + if (ngx_http_escape_location_name(cf, clcf) != NGX_OK) { + return NGX_ERROR; + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_escape_location_name(ngx_conf_t *cf, ngx_http_core_loc_conf_t *clcf) +{ + u_char *p; + size_t len; + uintptr_t escape; + + escape = 2 * ngx_escape_uri(NULL, clcf->name.data, clcf->name.len, + NGX_ESCAPE_URI); + + if (escape) { + len = clcf->name.len + escape; + + p = ngx_pnalloc(cf->pool, len); + if (p == NULL) { + return NGX_ERROR; + } + + clcf->escaped_name.len = len; + clcf->escaped_name.data = p; + + ngx_escape_uri(p, clcf->name.data, clcf->name.len, NGX_ESCAPE_URI); + + } else { + clcf->escaped_name = clcf->name; + } + return NGX_OK; } @@ -1301,13 +1338,12 @@ ngx_http_add_address(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, } #if (NGX_HTTP_V2 && NGX_HTTP_SSL \ - && !defined TLSEXT_TYPE_application_layer_protocol_negotiation \ - && !defined TLSEXT_TYPE_next_proto_neg) + && !defined TLSEXT_TYPE_application_layer_protocol_negotiation) if (lsopt->http2 && lsopt->ssl) { ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "nginx was built with OpenSSL that lacks ALPN " - "and NPN support, HTTP/2 is not enabled for %V", + "support, HTTP/2 is not enabled for %V", &lsopt->addr_text); } diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h index 8b43857..be8b7cd 100644 --- a/src/http/ngx_http.h +++ b/src/http/ngx_http.h @@ -167,6 +167,14 @@ ngx_uint_t ngx_http_degraded(ngx_http_request_t *); #endif +#if (NGX_HTTP_V2) +ngx_int_t ngx_http_huff_decode(u_char *state, u_char *src, size_t len, + u_char **dst, ngx_uint_t last, ngx_log_t *log); +size_t ngx_http_huff_encode(u_char *src, size_t len, u_char *dst, + ngx_uint_t lower); +#endif + + extern ngx_module_t ngx_http_module; extern ngx_str_t ngx_http_html_default_types[]; diff --git a/src/http/ngx_http_copy_filter_module.c b/src/http/ngx_http_copy_filter_module.c index c8ad5da..bd3028b 100644 --- a/src/http/ngx_http_copy_filter_module.c +++ b/src/http/ngx_http_copy_filter_module.c @@ -19,10 +19,6 @@ typedef struct { static void ngx_http_copy_aio_handler(ngx_output_chain_ctx_t *ctx, ngx_file_t *file); static void ngx_http_copy_aio_event_handler(ngx_event_t *ev); -#if (NGX_HAVE_AIO_SENDFILE) -static ssize_t ngx_http_copy_aio_sendfile_preload(ngx_buf_t *file); -static void ngx_http_copy_aio_sendfile_event_handler(ngx_event_t *ev); -#endif #endif #if (NGX_THREADS) static ngx_int_t ngx_http_copy_thread_handler(ngx_thread_task_t *task, @@ -128,9 +124,6 @@ ngx_http_copy_filter(ngx_http_request_t *r, ngx_chain_t *in) #if (NGX_HAVE_FILE_AIO) if (ngx_file_aio && clcf->aio == NGX_HTTP_AIO_ON) { ctx->aio_handler = ngx_http_copy_aio_handler; -#if (NGX_HAVE_AIO_SENDFILE) - ctx->aio_preload = ngx_http_copy_aio_sendfile_preload; -#endif } #endif @@ -207,53 +200,6 @@ ngx_http_copy_aio_event_handler(ngx_event_t *ev) ngx_http_run_posted_requests(c); } - -#if (NGX_HAVE_AIO_SENDFILE) - -static ssize_t -ngx_http_copy_aio_sendfile_preload(ngx_buf_t *file) -{ - ssize_t n; - static u_char buf[1]; - ngx_event_aio_t *aio; - ngx_http_request_t *r; - ngx_output_chain_ctx_t *ctx; - - n = ngx_file_aio_read(file->file, buf, 1, file->file_pos, NULL); - - if (n == NGX_AGAIN) { - aio = file->file->aio; - aio->handler = ngx_http_copy_aio_sendfile_event_handler; - - r = aio->data; - r->main->blocked++; - r->aio = 1; - - ctx = ngx_http_get_module_ctx(r, ngx_http_copy_filter_module); - ctx->aio = 1; - } - - return n; -} - - -static void -ngx_http_copy_aio_sendfile_event_handler(ngx_event_t *ev) -{ - ngx_event_aio_t *aio; - ngx_http_request_t *r; - - aio = ev->data; - r = aio->data; - - r->main->blocked--; - r->aio = 0; - ev->complete = 0; - - r->connection->write->handler(r->connection->write); -} - -#endif #endif @@ -263,6 +209,7 @@ static ngx_int_t ngx_http_copy_thread_handler(ngx_thread_task_t *task, ngx_file_t *file) { ngx_str_t name; + ngx_connection_t *c; ngx_thread_pool_t *tp; ngx_http_request_t *r; ngx_output_chain_ctx_t *ctx; @@ -270,6 +217,27 @@ ngx_http_copy_thread_handler(ngx_thread_task_t *task, ngx_file_t *file) r = file->thread_ctx; + if (r->aio) { + /* + * tolerate sendfile() calls if another operation is already + * running; this can happen due to subrequests, multiple calls + * of the next body filter from a filter, or in HTTP/2 due to + * a write event on the main connection + */ + + c = r->connection; + +#if (NGX_HTTP_V2) + if (r->stream) { + c = r->stream->connection->connection; + } +#endif + + if (task == c->sendfile_task) { + return NGX_OK; + } + } + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); tp = clcf->thread_pool; @@ -323,6 +291,20 @@ ngx_http_copy_thread_event_handler(ngx_event_t *ev) r->main->blocked--; r->aio = 0; +#if (NGX_HTTP_V2) + + if (r->stream) { + /* + * for HTTP/2, update write event to make sure processing will + * reach the main connection to handle sendfile() in threads + */ + + c->write->ready = 1; + c->write->active = 0; + } + +#endif + if (r->done) { /* * trigger connection event handler if the subrequest was diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index 6664fa6..c7463dc 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -1010,10 +1010,10 @@ ngx_http_core_find_config_phase(ngx_http_request_t *r, ngx_str_set(&r->headers_out.location->key, "Location"); if (r->args.len == 0) { - r->headers_out.location->value = clcf->name; + r->headers_out.location->value = clcf->escaped_name; } else { - len = clcf->name.len + 1 + r->args.len; + len = clcf->escaped_name.len + 1 + r->args.len; p = ngx_pnalloc(r->pool, len); if (p == NULL) { @@ -1025,7 +1025,7 @@ ngx_http_core_find_config_phase(ngx_http_request_t *r, r->headers_out.location->value.len = len; r->headers_out.location->value.data = p; - p = ngx_cpymem(p, clcf->name.data, clcf->name.len); + p = ngx_cpymem(p, clcf->escaped_name.data, clcf->escaped_name.len); *p++ = '?'; ngx_memcpy(p, r->args.data, r->args.len); } @@ -3467,6 +3467,7 @@ ngx_http_core_create_loc_conf(ngx_conf_t *cf) /* * set by ngx_pcalloc(): * + * clcf->escaped_name = { 0, NULL }; * clcf->root = { 0, NULL }; * clcf->limit_except = 0; * clcf->post_action = { 0, NULL }; @@ -3479,8 +3480,6 @@ ngx_http_core_create_loc_conf(ngx_conf_t *cf) * clcf->exact_match = 0; * clcf->auto_redirect = 0; * clcf->alias = 0; - * clcf->limit_rate = NULL; - * clcf->limit_rate_after = NULL; * clcf->gzip_proxied = 0; * clcf->keepalive_disable = 0; */ @@ -3512,6 +3511,8 @@ ngx_http_core_create_loc_conf(ngx_conf_t *cf) clcf->send_timeout = NGX_CONF_UNSET_MSEC; clcf->send_lowat = NGX_CONF_UNSET_SIZE; clcf->postpone_output = NGX_CONF_UNSET_SIZE; + clcf->limit_rate = NGX_CONF_UNSET_PTR; + clcf->limit_rate_after = NGX_CONF_UNSET_PTR; clcf->keepalive_time = NGX_CONF_UNSET_MSEC; clcf->keepalive_timeout = NGX_CONF_UNSET_MSEC; clcf->keepalive_header = NGX_CONF_UNSET; @@ -3719,7 +3720,7 @@ ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_value(conf->internal, prev->internal, 0); ngx_conf_merge_value(conf->sendfile, prev->sendfile, 0); ngx_conf_merge_size_value(conf->sendfile_max_chunk, - prev->sendfile_max_chunk, 0); + prev->sendfile_max_chunk, 2 * 1024 * 1024); ngx_conf_merge_size_value(conf->subrequest_output_buffer_size, prev->subrequest_output_buffer_size, (size_t) ngx_pagesize); @@ -3743,13 +3744,9 @@ ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_size_value(conf->postpone_output, prev->postpone_output, 1460); - if (conf->limit_rate == NULL) { - conf->limit_rate = prev->limit_rate; - } - - if (conf->limit_rate_after == NULL) { - conf->limit_rate_after = prev->limit_rate_after; - } + ngx_conf_merge_ptr_value(conf->limit_rate, prev->limit_rate, NULL); + ngx_conf_merge_ptr_value(conf->limit_rate_after, + prev->limit_rate_after, NULL); ngx_conf_merge_msec_value(conf->keepalive_time, prev->keepalive_time, 3600000); @@ -4571,19 +4568,6 @@ ngx_http_core_set_aio(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) #endif } -#if (NGX_HAVE_AIO_SENDFILE) - - if (ngx_strcmp(value[1].data, "sendfile") == 0) { - clcf->aio = NGX_HTTP_AIO_ON; - - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, - "the \"sendfile\" parameter of " - "the \"aio\" directive is deprecated"); - return NGX_CONF_OK; - } - -#endif - if (ngx_strncmp(value[1].data, "threads", 7) == 0 && (value[1].len == 7 || value[1].data[7] == '=')) { diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h index 2341fd4..004a98e 100644 --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -299,6 +299,7 @@ typedef struct { struct ngx_http_core_loc_conf_s { ngx_str_t name; /* location name */ + ngx_str_t escaped_name; #if (NGX_PCRE) ngx_http_regex_t *regex; @@ -501,8 +502,8 @@ ngx_int_t ngx_http_gzip_ok(ngx_http_request_t *r); ngx_int_t ngx_http_subrequest(ngx_http_request_t *r, - ngx_str_t *uri, ngx_str_t *args, ngx_http_request_t **sr, - ngx_http_post_subrequest_t *psr, ngx_uint_t flags); + ngx_str_t *uri, ngx_str_t *args, ngx_http_request_t **psr, + ngx_http_post_subrequest_t *ps, ngx_uint_t flags); ngx_int_t ngx_http_internal_redirect(ngx_http_request_t *r, ngx_str_t *uri, ngx_str_t *args); ngx_int_t ngx_http_named_location(ngx_http_request_t *r, ngx_str_t *name); diff --git a/src/http/ngx_http_header_filter_module.c b/src/http/ngx_http_header_filter_module.c index 9b89405..76f6e96 100644 --- a/src/http/ngx_http_header_filter_module.c +++ b/src/http/ngx_http_header_filter_module.c @@ -197,6 +197,10 @@ ngx_http_header_filter(ngx_http_request_t *r) } } + if (r->keepalive && (ngx_terminate || ngx_exiting)) { + r->keepalive = 0; + } + len = sizeof("HTTP/1.x ") - 1 + sizeof(CRLF) - 1 /* the end of the header */ + sizeof(CRLF) - 1; diff --git a/src/http/v2/ngx_http_v2_huff_decode.c b/src/http/ngx_http_huff_decode.c similarity index 99% rename from src/http/v2/ngx_http_v2_huff_decode.c rename to src/http/ngx_http_huff_decode.c index 49ca576..14b7b78 100644 --- a/src/http/v2/ngx_http_v2_huff_decode.c +++ b/src/http/ngx_http_huff_decode.c @@ -15,14 +15,14 @@ typedef struct { u_char emit; u_char sym; u_char ending; -} ngx_http_v2_huff_decode_code_t; +} ngx_http_huff_decode_code_t; -static ngx_inline ngx_int_t ngx_http_v2_huff_decode_bits(u_char *state, +static ngx_inline ngx_int_t ngx_http_huff_decode_bits(u_char *state, u_char *ending, ngx_uint_t bits, u_char **dst); -static ngx_http_v2_huff_decode_code_t ngx_http_v2_huff_decode_codes[256][16] = +static ngx_http_huff_decode_code_t ngx_http_huff_decode_codes[256][16] = { /* 0 */ { @@ -2640,7 +2640,7 @@ static ngx_http_v2_huff_decode_code_t ngx_http_v2_huff_decode_codes[256][16] = ngx_int_t -ngx_http_v2_huff_decode(u_char *state, u_char *src, size_t len, u_char **dst, +ngx_http_huff_decode(u_char *state, u_char *src, size_t len, u_char **dst, ngx_uint_t last, ngx_log_t *log) { u_char *end, ch, ending; @@ -2653,7 +2653,7 @@ ngx_http_v2_huff_decode(u_char *state, u_char *src, size_t len, u_char **dst, while (src != end) { ch = *src++; - if (ngx_http_v2_huff_decode_bits(state, &ending, ch >> 4, dst) + if (ngx_http_huff_decode_bits(state, &ending, ch >> 4, dst) != NGX_OK) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, log, 0, @@ -2663,7 +2663,7 @@ ngx_http_v2_huff_decode(u_char *state, u_char *src, size_t len, u_char **dst, return NGX_ERROR; } - if (ngx_http_v2_huff_decode_bits(state, &ending, ch & 0xf, dst) + if (ngx_http_huff_decode_bits(state, &ending, ch & 0xf, dst) != NGX_OK) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, log, 0, @@ -2692,12 +2692,12 @@ ngx_http_v2_huff_decode(u_char *state, u_char *src, size_t len, u_char **dst, static ngx_inline ngx_int_t -ngx_http_v2_huff_decode_bits(u_char *state, u_char *ending, ngx_uint_t bits, +ngx_http_huff_decode_bits(u_char *state, u_char *ending, ngx_uint_t bits, u_char **dst) { - ngx_http_v2_huff_decode_code_t code; + ngx_http_huff_decode_code_t code; - code = ngx_http_v2_huff_decode_codes[*state][bits]; + code = ngx_http_huff_decode_codes[*state][bits]; if (code.next == *state) { return NGX_ERROR; diff --git a/src/http/v2/ngx_http_v2_huff_encode.c b/src/http/ngx_http_huff_encode.c similarity index 93% rename from src/http/v2/ngx_http_v2_huff_encode.c rename to src/http/ngx_http_huff_encode.c index 3f822cd..c03b153 100644 --- a/src/http/v2/ngx_http_v2_huff_encode.c +++ b/src/http/ngx_http_huff_encode.c @@ -14,10 +14,10 @@ typedef struct { uint32_t code; uint32_t len; -} ngx_http_v2_huff_encode_code_t; +} ngx_http_huff_encode_code_t; -static ngx_http_v2_huff_encode_code_t ngx_http_v2_huff_encode_table[256] = +static ngx_http_huff_encode_code_t ngx_http_huff_encode_table[256] = { {0x00001ff8, 13}, {0x007fffd8, 23}, {0x0fffffe2, 28}, {0x0fffffe3, 28}, {0x0fffffe4, 28}, {0x0fffffe5, 28}, {0x0fffffe6, 28}, {0x0fffffe7, 28}, @@ -87,7 +87,7 @@ static ngx_http_v2_huff_encode_code_t ngx_http_v2_huff_encode_table[256] = /* same as above, but embeds lowercase transformation */ -static ngx_http_v2_huff_encode_code_t ngx_http_v2_huff_encode_table_lc[256] = +static ngx_http_huff_encode_code_t ngx_http_huff_encode_table_lc[256] = { {0x00001ff8, 13}, {0x007fffd8, 23}, {0x0fffffe2, 28}, {0x0fffffe3, 28}, {0x0fffffe4, 28}, {0x0fffffe5, 28}, {0x0fffffe6, 28}, {0x0fffffe7, 28}, @@ -161,10 +161,10 @@ static ngx_http_v2_huff_encode_code_t ngx_http_v2_huff_encode_table_lc[256] = #if (NGX_HAVE_LITTLE_ENDIAN) #if (NGX_HAVE_GCC_BSWAP64) -#define ngx_http_v2_huff_encode_buf(dst, buf) \ +#define ngx_http_huff_encode_buf(dst, buf) \ (*(uint64_t *) (dst) = __builtin_bswap64(buf)) #else -#define ngx_http_v2_huff_encode_buf(dst, buf) \ +#define ngx_http_huff_encode_buf(dst, buf) \ ((dst)[0] = (u_char) ((buf) >> 56), \ (dst)[1] = (u_char) ((buf) >> 48), \ (dst)[2] = (u_char) ((buf) >> 40), \ @@ -176,28 +176,28 @@ static ngx_http_v2_huff_encode_code_t ngx_http_v2_huff_encode_table_lc[256] = #endif #else /* !NGX_HAVE_LITTLE_ENDIAN */ -#define ngx_http_v2_huff_encode_buf(dst, buf) \ +#define ngx_http_huff_encode_buf(dst, buf) \ (*(uint64_t *) (dst) = (buf)) #endif #else /* NGX_PTR_SIZE == 4 */ -#define ngx_http_v2_huff_encode_buf(dst, buf) \ +#define ngx_http_huff_encode_buf(dst, buf) \ (*(uint32_t *) (dst) = htonl(buf)) #endif size_t -ngx_http_v2_huff_encode(u_char *src, size_t len, u_char *dst, ngx_uint_t lower) +ngx_http_huff_encode(u_char *src, size_t len, u_char *dst, ngx_uint_t lower) { - u_char *end; - size_t hlen; - ngx_uint_t buf, pending, code; - ngx_http_v2_huff_encode_code_t *table, *next; + u_char *end; + size_t hlen; + ngx_uint_t buf, pending, code; + ngx_http_huff_encode_code_t *table, *next; - table = lower ? ngx_http_v2_huff_encode_table_lc - : ngx_http_v2_huff_encode_table; + table = lower ? ngx_http_huff_encode_table_lc + : ngx_http_huff_encode_table; hlen = 0; buf = 0; pending = 0; @@ -224,7 +224,7 @@ ngx_http_v2_huff_encode(u_char *src, size_t len, u_char *dst, ngx_uint_t lower) buf |= code >> pending; - ngx_http_v2_huff_encode_buf(&dst[hlen], buf); + ngx_http_huff_encode_buf(&dst[hlen], buf); hlen += sizeof(buf); diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c index 20ad89a..6460da2 100644 --- a/src/http/ngx_http_parse.c +++ b/src/http/ngx_http_parse.c @@ -11,7 +11,7 @@ static uint32_t usual[] = { - 0xffffdbfe, /* 1111 1111 1111 1111 1101 1011 1111 1110 */ + 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ 0x7fff37d6, /* 0111 1111 1111 1111 0011 0111 1101 0110 */ @@ -24,7 +24,7 @@ static uint32_t usual[] = { #endif /* ~}| {zyx wvut srqp onml kjih gfed cba` */ - 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0x7fffffff, /* 0111 1111 1111 1111 1111 1111 1111 1111 */ 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ @@ -116,10 +116,8 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b) sw_host_end, sw_host_ip_literal, sw_port, - sw_host_http_09, sw_after_slash_in_uri, sw_check_uri, - sw_check_uri_http_09, sw_uri, sw_http_09, sw_http_H, @@ -246,6 +244,11 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b) r->method = NGX_HTTP_OPTIONS; } + if (ngx_str7_cmp(m, 'C', 'O', 'N', 'N', 'E', 'C', 'T', ' ')) + { + r->method = NGX_HTTP_CONNECT; + } + break; case 8: @@ -393,7 +396,7 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b) */ r->uri_start = r->schema_end + 1; r->uri_end = r->schema_end + 2; - state = sw_host_http_09; + state = sw_http_09; break; default: return NGX_HTTP_PARSE_INVALID_REQUEST; @@ -467,35 +470,13 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b) */ r->uri_start = r->schema_end + 1; r->uri_end = r->schema_end + 2; - state = sw_host_http_09; + state = sw_http_09; break; default: return NGX_HTTP_PARSE_INVALID_REQUEST; } break; - /* space+ after "http://host[:port] " */ - case sw_host_http_09: - switch (ch) { - case ' ': - break; - case CR: - r->http_minor = 9; - state = sw_almost_done; - break; - case LF: - r->http_minor = 9; - goto done; - case 'H': - r->http_protocol.data = p; - state = sw_http_H; - break; - default: - return NGX_HTTP_PARSE_INVALID_REQUEST; - } - break; - - /* check "/.", "//", "%", and "\" (Win32) in URI */ case sw_after_slash_in_uri: @@ -507,7 +488,7 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b) switch (ch) { case ' ': r->uri_end = p; - state = sw_check_uri_http_09; + state = sw_http_09; break; case CR: r->uri_end = p; @@ -547,9 +528,10 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b) case '+': r->plus_in_uri = 1; break; - case '\0': - return NGX_HTTP_PARSE_INVALID_REQUEST; default: + if (ch < 0x20 || ch == 0x7f) { + return NGX_HTTP_PARSE_INVALID_REQUEST; + } state = sw_check_uri; break; } @@ -579,7 +561,7 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b) break; case ' ': r->uri_end = p; - state = sw_check_uri_http_09; + state = sw_http_09; break; case CR: r->uri_end = p; @@ -611,36 +593,14 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b) case '+': r->plus_in_uri = 1; break; - case '\0': - return NGX_HTTP_PARSE_INVALID_REQUEST; - } - break; - - /* space+ after URI */ - case sw_check_uri_http_09: - switch (ch) { - case ' ': - break; - case CR: - r->http_minor = 9; - state = sw_almost_done; - break; - case LF: - r->http_minor = 9; - goto done; - case 'H': - r->http_protocol.data = p; - state = sw_http_H; - break; default: - r->space_in_uri = 1; - state = sw_check_uri; - p--; + if (ch < 0x20 || ch == 0x7f) { + return NGX_HTTP_PARSE_INVALID_REQUEST; + } break; } break; - /* URI */ case sw_uri: @@ -665,8 +625,11 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b) case '#': r->complex_uri = 1; break; - case '\0': - return NGX_HTTP_PARSE_INVALID_REQUEST; + default: + if (ch < 0x20 || ch == 0x7f) { + return NGX_HTTP_PARSE_INVALID_REQUEST; + } + break; } break; @@ -687,10 +650,7 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b) state = sw_http_H; break; default: - r->space_in_uri = 1; - state = sw_uri; - p--; - break; + return NGX_HTTP_PARSE_INVALID_REQUEST; } break; @@ -933,7 +893,8 @@ ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b, break; } - if (ch == '\0') { + if (ch <= 0x20 || ch == 0x7f || ch == ':') { + r->header_end = p; return NGX_HTTP_PARSE_INVALID_HEADER; } @@ -1001,7 +962,8 @@ ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b, break; } - if (ch == '\0') { + if (ch <= 0x20 || ch == 0x7f) { + r->header_end = p; return NGX_HTTP_PARSE_INVALID_HEADER; } @@ -1024,6 +986,7 @@ ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b, r->header_end = p; goto done; case '\0': + r->header_end = p; return NGX_HTTP_PARSE_INVALID_HEADER; default: r->header_start = p; @@ -1047,6 +1010,7 @@ ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b, r->header_end = p; goto done; case '\0': + r->header_end = p; return NGX_HTTP_PARSE_INVALID_HEADER; } break; @@ -1062,6 +1026,7 @@ ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b, case LF: goto done; case '\0': + r->header_end = p; return NGX_HTTP_PARSE_INVALID_HEADER; default: state = sw_value; @@ -1165,10 +1130,6 @@ ngx_http_parse_uri(ngx_http_request_t *r) } switch (ch) { - case ' ': - r->space_in_uri = 1; - state = sw_check_uri; - break; case '.': r->complex_uri = 1; state = sw_uri; @@ -1199,6 +1160,9 @@ ngx_http_parse_uri(ngx_http_request_t *r) r->plus_in_uri = 1; break; default: + if (ch <= 0x20 || ch == 0x7f) { + return NGX_ERROR; + } state = sw_check_uri; break; } @@ -1226,9 +1190,6 @@ ngx_http_parse_uri(ngx_http_request_t *r) case '.': r->uri_ext = p + 1; break; - case ' ': - r->space_in_uri = 1; - break; #if (NGX_WIN32) case '\\': r->complex_uri = 1; @@ -1250,6 +1211,11 @@ ngx_http_parse_uri(ngx_http_request_t *r) case '+': r->plus_in_uri = 1; break; + default: + if (ch <= 0x20 || ch == 0x7f) { + return NGX_ERROR; + } + break; } break; @@ -1261,12 +1227,14 @@ ngx_http_parse_uri(ngx_http_request_t *r) } switch (ch) { - case ' ': - r->space_in_uri = 1; - break; case '#': r->complex_uri = 1; break; + default: + if (ch <= 0x20 || ch == 0x7f) { + return NGX_ERROR; + } + break; } break; } diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c index 136c461..013b715 100644 --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -607,7 +607,7 @@ ngx_http_alloc_request(ngx_connection_t *c) } #if (NGX_HTTP_SSL) - if (c->ssl) { + if (c->ssl && !c->ssl->sendfile) { r->main_filter_need_in_memory = 1; } #endif @@ -806,8 +806,7 @@ ngx_http_ssl_handshake_handler(ngx_connection_t *c) c->ssl->no_wait_shutdown = 1; #if (NGX_HTTP_V2 \ - && (defined TLSEXT_TYPE_application_layer_protocol_negotiation \ - || defined TLSEXT_TYPE_next_proto_neg)) + && defined TLSEXT_TYPE_application_layer_protocol_negotiation) { unsigned int len; const unsigned char *data; @@ -817,19 +816,8 @@ ngx_http_ssl_handshake_handler(ngx_connection_t *c) if (hc->addr_conf->http2) { -#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation SSL_get0_alpn_selected(c->ssl->connection, &data, &len); -#ifdef TLSEXT_TYPE_next_proto_neg - if (len == 0) { - SSL_get0_next_proto_negotiated(c->ssl->connection, &data, &len); - } -#endif - -#else /* TLSEXT_TYPE_next_proto_neg */ - SSL_get0_next_proto_negotiated(c->ssl->connection, &data, &len); -#endif - if (len == 2 && data[0] == 'h' && data[1] == '2') { ngx_http_v2_init(c->read); return; @@ -1043,12 +1031,14 @@ ngx_http_ssl_certificate(ngx_ssl_conn_t *ssl_conn, void *arg) } ngx_http_free_request(r, 0); + c->log->action = "SSL handshaking"; c->destroyed = 0; return 1; failed: ngx_http_free_request(r, 0); + c->log->action = "SSL handshaking"; c->destroyed = 0; return 0; } @@ -1262,7 +1252,7 @@ ngx_http_process_request_uri(ngx_http_request_t *r) r->unparsed_uri.len = r->uri_end - r->uri_start; r->unparsed_uri.data = r->uri_start; - r->valid_unparsed_uri = (r->space_in_uri || r->empty_path_in_uri) ? 0 : 1; + r->valid_unparsed_uri = r->empty_path_in_uri ? 0 : 1; if (r->uri_ext) { if (r->args_start) { @@ -1520,7 +1510,9 @@ ngx_http_process_request_headers(ngx_event_t *rev) /* rc == NGX_HTTP_PARSE_INVALID_HEADER */ ngx_log_error(NGX_LOG_INFO, c->log, 0, - "client sent invalid header line"); + "client sent invalid header line: \"%*s\\x%02xd...\"", + r->header_end - r->header_name_start, + r->header_name_start, *r->header_end); ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); break; @@ -1978,20 +1970,28 @@ ngx_http_process_request_header(ngx_http_request_t *r) } } - if (r->method == NGX_HTTP_TRACE) { - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "client sent TRACE method"); - ngx_http_finalize_request(r, NGX_HTTP_NOT_ALLOWED); - return NGX_ERROR; - } - if (r->headers_in.transfer_encoding) { + if (r->http_version < NGX_HTTP_VERSION_11) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent HTTP/1.0 request with " + "\"Transfer-Encoding\" header"); + ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); + return NGX_ERROR; + } + if (r->headers_in.transfer_encoding->value.len == 7 && ngx_strncasecmp(r->headers_in.transfer_encoding->value.data, (u_char *) "chunked", 7) == 0) { - r->headers_in.content_length = NULL; - r->headers_in.content_length_n = -1; + if (r->headers_in.content_length) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent \"Content-Length\" and " + "\"Transfer-Encoding\" headers " + "at the same time"); + ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); + return NGX_ERROR; + } + r->headers_in.chunked = 1; } else { @@ -2011,6 +2011,20 @@ ngx_http_process_request_header(ngx_http_request_t *r) } } + if (r->method == NGX_HTTP_CONNECT) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent CONNECT method"); + ngx_http_finalize_request(r, NGX_HTTP_NOT_ALLOWED); + return NGX_ERROR; + } + + if (r->method == NGX_HTTP_TRACE) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent TRACE method"); + ngx_http_finalize_request(r, NGX_HTTP_NOT_ALLOWED); + return NGX_ERROR; + } + return NGX_OK; } @@ -2158,15 +2172,16 @@ ngx_http_validate_host(ngx_str_t *host, ngx_pool_t *pool, ngx_uint_t alloc) } break; - case '\0': - return NGX_DECLINED; - default: if (ngx_path_separator(ch)) { return NGX_DECLINED; } + if (ch <= 0x20 || ch == 0x7f) { + return NGX_DECLINED; + } + if (ch >= 'A' && ch <= 'Z') { alloc = 1; } diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h index 6dfb4a4..b1269d2 100644 --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -25,22 +25,23 @@ #define NGX_HTTP_VERSION_11 1001 #define NGX_HTTP_VERSION_20 2000 -#define NGX_HTTP_UNKNOWN 0x0001 -#define NGX_HTTP_GET 0x0002 -#define NGX_HTTP_HEAD 0x0004 -#define NGX_HTTP_POST 0x0008 -#define NGX_HTTP_PUT 0x0010 -#define NGX_HTTP_DELETE 0x0020 -#define NGX_HTTP_MKCOL 0x0040 -#define NGX_HTTP_COPY 0x0080 -#define NGX_HTTP_MOVE 0x0100 -#define NGX_HTTP_OPTIONS 0x0200 -#define NGX_HTTP_PROPFIND 0x0400 -#define NGX_HTTP_PROPPATCH 0x0800 -#define NGX_HTTP_LOCK 0x1000 -#define NGX_HTTP_UNLOCK 0x2000 -#define NGX_HTTP_PATCH 0x4000 -#define NGX_HTTP_TRACE 0x8000 +#define NGX_HTTP_UNKNOWN 0x00000001 +#define NGX_HTTP_GET 0x00000002 +#define NGX_HTTP_HEAD 0x00000004 +#define NGX_HTTP_POST 0x00000008 +#define NGX_HTTP_PUT 0x00000010 +#define NGX_HTTP_DELETE 0x00000020 +#define NGX_HTTP_MKCOL 0x00000040 +#define NGX_HTTP_COPY 0x00000080 +#define NGX_HTTP_MOVE 0x00000100 +#define NGX_HTTP_OPTIONS 0x00000200 +#define NGX_HTTP_PROPFIND 0x00000400 +#define NGX_HTTP_PROPPATCH 0x00000800 +#define NGX_HTTP_LOCK 0x00001000 +#define NGX_HTTP_UNLOCK 0x00002000 +#define NGX_HTTP_PATCH 0x00004000 +#define NGX_HTTP_TRACE 0x00008000 +#define NGX_HTTP_CONNECT 0x00010000 #define NGX_HTTP_CONNECTION_CLOSE 1 #define NGX_HTTP_CONNECTION_KEEP_ALIVE 2 @@ -301,6 +302,9 @@ typedef struct { ngx_chain_t *busy; ngx_http_chunked_t *chunked; ngx_http_client_body_handler_pt post_handler; + unsigned filter_need_buffering:1; + unsigned last_sent:1; + unsigned last_saved:1; } ngx_http_request_body_t; @@ -467,9 +471,6 @@ struct ngx_http_request_s { /* URI with "+" */ unsigned plus_in_uri:1; - /* URI with " " */ - unsigned space_in_uri:1; - /* URI with empty path */ unsigned empty_path_in_uri:1; diff --git a/src/http/ngx_http_request_body.c b/src/http/ngx_http_request_body.c index 0cae88f..ad3549f 100644 --- a/src/http/ngx_http_request_body.c +++ b/src/http/ngx_http_request_body.c @@ -62,11 +62,16 @@ ngx_http_read_client_request_body(ngx_http_request_t *r, /* * set by ngx_pcalloc(): * + * rb->temp_file = NULL; * rb->bufs = NULL; * rb->buf = NULL; * rb->free = NULL; * rb->busy = NULL; * rb->chunked = NULL; + * rb->received = 0; + * rb->filter_need_buffering = 0; + * rb->last_sent = 0; + * rb->last_saved = 0; */ rb->rest = -1; @@ -144,7 +149,7 @@ ngx_http_read_client_request_body(ngx_http_request_t *r, } } - if (rb->rest == 0) { + if (rb->rest == 0 && rb->last_saved) { /* the whole request body was pre-read */ r->request_body_no_buffering = 0; post_handler(r); @@ -172,6 +177,10 @@ ngx_http_read_client_request_body(ngx_http_request_t *r, size += preread; } + if (size == 0) { + size++; + } + } else { size = clcf->client_body_buffer_size; } @@ -270,6 +279,7 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r) size_t size; ssize_t n; ngx_int_t rc; + ngx_uint_t flush; ngx_chain_t out; ngx_connection_t *c; ngx_http_request_body_t *rb; @@ -277,12 +287,17 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r) c = r->connection; rb = r->request_body; + flush = 1; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http read client request body"); for ( ;; ) { for ( ;; ) { + if (rb->rest == 0) { + break; + } + if (rb->buf->last == rb->buf->end) { /* update chains */ @@ -306,12 +321,25 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r) return NGX_AGAIN; } + if (rb->filter_need_buffering) { + clcf = ngx_http_get_module_loc_conf(r, + ngx_http_core_module); + ngx_add_timer(c->read, clcf->client_body_timeout); + + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + return NGX_AGAIN; + } + ngx_log_error(NGX_LOG_ALERT, c->log, 0, "busy buffers after request body flush"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } + flush = 0; rb->buf->pos = rb->buf->start; rb->buf->last = rb->buf->start; } @@ -323,6 +351,10 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r) size = (size_t) rest; } + if (size == 0) { + break; + } + n = c->recv(c, rb->buf->last, size); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, @@ -347,6 +379,7 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r) /* pass buffer to request body filter chain */ + flush = 0; out.buf = rb->buf; out.next = NULL; @@ -368,11 +401,19 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r) ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http client request body rest %O", rb->rest); - if (rb->rest == 0) { + if (flush) { + rc = ngx_http_request_body_filter(r, NULL); + + if (rc != NGX_OK) { + return rc; + } + } + + if (rb->rest == 0 && rb->last_saved) { break; } - if (!c->read->ready) { + if (!c->read->ready || rb->rest == 0) { clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); ngx_add_timer(c->read, clcf->client_body_timeout); @@ -939,15 +980,32 @@ ngx_http_request_body_length_filter(ngx_http_request_t *r, ngx_chain_t *in) rb = r->request_body; + out = NULL; + ll = &out; + if (rb->rest == -1) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http request body content length filter"); rb->rest = r->headers_in.content_length_n; - } - out = NULL; - ll = &out; + if (rb->rest == 0) { + + tl = ngx_chain_get_free_buf(r->pool, &rb->free); + if (tl == NULL) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + b = tl->buf; + + ngx_memzero(b, sizeof(ngx_buf_t)); + + b->last_buf = 1; + + *ll = tl; + ll = &tl->next; + } + } for (cl = in; cl; cl = cl->next) { @@ -1011,6 +1069,9 @@ ngx_http_request_body_chunked_filter(ngx_http_request_t *r, ngx_chain_t *in) rb = r->request_body; + out = NULL; + ll = &out; + if (rb->rest == -1) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, @@ -1027,9 +1088,6 @@ ngx_http_request_body_chunked_filter(ngx_http_request_t *r, ngx_chain_t *in) rb->rest = cscf->large_client_header_buffers.size; } - out = NULL; - ll = &out; - for (cl = in; cl; cl = cl->next) { b = NULL; @@ -1186,15 +1244,16 @@ ngx_int_t ngx_http_request_body_save_filter(ngx_http_request_t *r, ngx_chain_t *in) { ngx_buf_t *b; - ngx_chain_t *cl; + ngx_chain_t *cl, *tl, **ll; ngx_http_request_body_t *rb; rb = r->request_body; -#if (NGX_DEBUG) + ll = &rb->bufs; + + for (cl = rb->bufs; cl; cl = cl->next) { #if 0 - for (cl = rb->bufs; cl; cl = cl->next) { ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0, "http body old buf t:%d f:%d %p, pos %p, size: %z " "file: %O, size: %O", @@ -1203,10 +1262,13 @@ ngx_http_request_body_save_filter(ngx_http_request_t *r, ngx_chain_t *in) cl->buf->last - cl->buf->pos, cl->buf->file_pos, cl->buf->file_last - cl->buf->file_pos); - } #endif + ll = &cl->next; + } + for (cl = in; cl; cl = cl->next) { + ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0, "http body new buf t:%d f:%d %p, pos %p, size: %z " "file: %O, size: %O", @@ -1215,15 +1277,31 @@ ngx_http_request_body_save_filter(ngx_http_request_t *r, ngx_chain_t *in) cl->buf->last - cl->buf->pos, cl->buf->file_pos, cl->buf->file_last - cl->buf->file_pos); + + if (cl->buf->last_buf) { + + if (rb->last_saved) { + ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, + "duplicate last buf in save filter"); + *ll = NULL; + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + rb->last_saved = 1; + } + + tl = ngx_alloc_chain_link(r->pool); + if (tl == NULL) { + *ll = NULL; + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + tl->buf = cl->buf; + *ll = tl; + ll = &tl->next; } -#endif - - /* TODO: coalesce neighbouring buffers */ - - if (ngx_chain_add_copy(r->pool, &rb->bufs, in) != NGX_OK) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } + *ll = NULL; if (r->request_body_no_buffering) { return NGX_OK; @@ -1231,7 +1309,7 @@ ngx_http_request_body_save_filter(ngx_http_request_t *r, ngx_chain_t *in) if (rb->rest > 0) { - if (rb->buf && rb->buf->last == rb->buf->end + if (rb->bufs && rb->buf && rb->buf->last == rb->buf->end && ngx_http_write_request_body(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; @@ -1240,10 +1318,18 @@ ngx_http_request_body_save_filter(ngx_http_request_t *r, ngx_chain_t *in) return NGX_OK; } - /* rb->rest == 0 */ + if (!rb->last_saved) { + return NGX_OK; + } if (rb->temp_file || r->request_body_in_file_only) { + if (rb->bufs && rb->bufs->buf->in_file) { + ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, + "body already in file"); + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + if (ngx_http_write_request_body(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c index 13c57d6..bebdbd9 100644 --- a/src/http/ngx_http_script.c +++ b/src/http/ngx_http_script.c @@ -250,7 +250,7 @@ ngx_http_set_complex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) cv = (ngx_http_complex_value_t **) (p + cmd->offset); - if (*cv != NULL) { + if (*cv != NGX_CONF_UNSET_PTR && *cv != NULL) { return "is duplicate"; } @@ -275,6 +275,44 @@ ngx_http_set_complex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) } +char * +ngx_http_set_complex_value_zero_slot(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) +{ + char *p = conf; + + ngx_str_t *value; + ngx_http_complex_value_t **cv; + ngx_http_compile_complex_value_t ccv; + + cv = (ngx_http_complex_value_t **) (p + cmd->offset); + + if (*cv != NGX_CONF_UNSET_PTR) { + return "is duplicate"; + } + + *cv = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t)); + if (*cv == NULL) { + return NGX_CONF_ERROR; + } + + value = cf->args->elts; + + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[1]; + ccv.complex_value = *cv; + ccv.zero = 1; + + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; +} + + char * ngx_http_set_complex_value_size_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) diff --git a/src/http/ngx_http_script.h b/src/http/ngx_http_script.h index a6b345e..4360038 100644 --- a/src/http/ngx_http_script.h +++ b/src/http/ngx_http_script.h @@ -216,6 +216,8 @@ size_t ngx_http_complex_value_size(ngx_http_request_t *r, ngx_int_t ngx_http_compile_complex_value(ngx_http_compile_complex_value_t *ccv); char *ngx_http_set_complex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +char *ngx_http_set_complex_value_zero_slot(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); char *ngx_http_set_complex_value_size_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c index b682af5..ded833c 100644 --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -187,6 +187,8 @@ static void ngx_http_upstream_ssl_handshake(ngx_http_request_t *, static void ngx_http_upstream_ssl_save_session(ngx_connection_t *c); static ngx_int_t ngx_http_upstream_ssl_name(ngx_http_request_t *r, ngx_http_upstream_t *u, ngx_connection_t *c); +static ngx_int_t ngx_http_upstream_ssl_certificate(ngx_http_request_t *r, + ngx_http_upstream_t *u, ngx_connection_t *c); #endif @@ -1509,8 +1511,9 @@ ngx_http_upstream_check_broken_connection(ngx_http_request_t *r, static void ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u) { - ngx_int_t rc; - ngx_connection_t *c; + ngx_int_t rc; + ngx_connection_t *c; + ngx_http_core_loc_conf_t *clcf; r->connection->log->action = "connecting to upstream"; @@ -1597,10 +1600,12 @@ ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u) /* init or reinit the ngx_output_chain() and ngx_chain_writer() contexts */ + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + u->writer.out = NULL; u->writer.last = &u->writer.out; u->writer.connection = c; - u->writer.limit = 0; + u->writer.limit = clcf->sendfile_max_chunk; if (u->request_sent) { if (ngx_http_upstream_reinit(r, u) != NGX_OK) { @@ -1681,9 +1686,6 @@ ngx_http_upstream_ssl_init_connection(ngx_http_request_t *r, return; } - c->sendfile = 0; - u->output.sendfile = 0; - if (u->conf->ssl_server_name || u->conf->ssl_verify) { if (ngx_http_upstream_ssl_name(r, u, c) != NGX_OK) { ngx_http_upstream_finalize_request(r, u, @@ -1692,6 +1694,16 @@ ngx_http_upstream_ssl_init_connection(ngx_http_request_t *r, } } + if (u->conf->ssl_certificate && (u->conf->ssl_certificate->lengths + || u->conf->ssl_certificate_key->lengths)) + { + if (ngx_http_upstream_ssl_certificate(r, u, c) != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + } + if (u->conf->ssl_session_reuse) { c->ssl->save_session = ngx_http_upstream_ssl_save_session; @@ -1779,6 +1791,11 @@ ngx_http_upstream_ssl_handshake(ngx_http_request_t *r, ngx_http_upstream_t *u, } } + if (!c->ssl->sendfile) { + c->sendfile = 0; + u->output.sendfile = 0; + } + c->write->handler = ngx_http_upstream_handler; c->read->handler = ngx_http_upstream_handler; @@ -1912,6 +1929,45 @@ done: return NGX_OK; } + +static ngx_int_t +ngx_http_upstream_ssl_certificate(ngx_http_request_t *r, + ngx_http_upstream_t *u, ngx_connection_t *c) +{ + ngx_str_t cert, key; + + if (ngx_http_complex_value(r, u->conf->ssl_certificate, &cert) + != NGX_OK) + { + return NGX_ERROR; + } + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http upstream ssl cert: \"%s\"", cert.data); + + if (*cert.data == '\0') { + return NGX_OK; + } + + if (ngx_http_complex_value(r, u->conf->ssl_certificate_key, &key) + != NGX_OK) + { + return NGX_ERROR; + } + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http upstream ssl key: \"%s\"", key.data); + + if (ngx_ssl_connection_certificate(c, r->pool, &cert, &key, + u->conf->ssl_passwords) + != NGX_OK) + { + return NGX_ERROR; + } + + return NGX_OK; +} + #endif @@ -3791,6 +3847,7 @@ ngx_http_upstream_thread_handler(ngx_thread_task_t *task, ngx_file_t *file) { ngx_str_t name; ngx_event_pipe_t *p; + ngx_connection_t *c; ngx_thread_pool_t *tp; ngx_http_request_t *r; ngx_http_core_loc_conf_t *clcf; @@ -3798,6 +3855,27 @@ ngx_http_upstream_thread_handler(ngx_thread_task_t *task, ngx_file_t *file) r = file->thread_ctx; p = r->upstream->pipe; + if (r->aio) { + /* + * tolerate sendfile() calls if another operation is already + * running; this can happen due to subrequests, multiple calls + * of the next body filter from a filter, or in HTTP/2 due to + * a write event on the main connection + */ + + c = r->connection; + +#if (NGX_HTTP_V2) + if (r->stream) { + c = r->stream->connection->connection; + } +#endif + + if (task == c->sendfile_task) { + return NGX_OK; + } + } + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); tp = clcf->thread_pool; @@ -3849,6 +3927,20 @@ ngx_http_upstream_thread_event_handler(ngx_event_t *ev) r->main->blocked--; r->aio = 0; +#if (NGX_HTTP_V2) + + if (r->stream) { + /* + * for HTTP/2, update write event to make sure processing will + * reach the main connection to handle sendfile() in threads + */ + + c->write->ready = 1; + c->write->active = 0; + } + +#endif + if (r->done) { /* * trigger connection event handler if the subrequest was diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h index fd642c2..3db7b06 100644 --- a/src/http/ngx_http_upstream.h +++ b/src/http/ngx_http_upstream.h @@ -234,6 +234,10 @@ typedef struct { ngx_http_complex_value_t *ssl_name; ngx_flag_t ssl_server_name; ngx_flag_t ssl_verify; + + ngx_http_complex_value_t *ssl_certificate; + ngx_http_complex_value_t *ssl_certificate_key; + ngx_array_t *ssl_passwords; #endif ngx_str_t module; diff --git a/src/http/ngx_http_write_filter_module.c b/src/http/ngx_http_write_filter_module.c index 6a5d957..932f26d 100644 --- a/src/http/ngx_http_write_filter_module.c +++ b/src/http/ngx_http_write_filter_module.c @@ -321,18 +321,13 @@ ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in) delay = (ngx_msec_t) ((nsent - sent) * 1000 / r->limit_rate); if (delay > 0) { - limit = 0; c->write->delayed = 1; ngx_add_timer(c->write, delay); } } - if (limit - && c->write->ready - && c->sent - sent >= limit - (off_t) (2 * ngx_pagesize)) - { - c->write->delayed = 1; - ngx_add_timer(c->write, 1); + if (chain && c->write->ready && !c->write->delayed) { + ngx_post_event(c->write, &ngx_posted_next_events); } for (cl = r->out; cl && cl != chain; /* void */) { diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c index 3611a2e..0e45a7b 100644 --- a/src/http/v2/ngx_http_v2.c +++ b/src/http/v2/ngx_http_v2.c @@ -173,7 +173,7 @@ static ngx_int_t ngx_http_v2_construct_cookie_header(ngx_http_request_t *r); static void ngx_http_v2_run_request(ngx_http_request_t *r); static void ngx_http_v2_run_request_handler(ngx_event_t *ev); static ngx_int_t ngx_http_v2_process_request_body(ngx_http_request_t *r, - u_char *pos, size_t size, ngx_uint_t last); + u_char *pos, size_t size, ngx_uint_t last, ngx_uint_t flush); static ngx_int_t ngx_http_v2_filter_request_body(ngx_http_request_t *r); static void ngx_http_v2_read_client_request_body_handler(ngx_http_request_t *r); @@ -1140,9 +1140,10 @@ ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos, h2c->payload_bytes += size; if (r->request_body) { - rc = ngx_http_v2_process_request_body(r, pos, size, stream->in_closed); + rc = ngx_http_v2_process_request_body(r, pos, size, + stream->in_closed, 0); - if (rc != NGX_OK) { + if (rc != NGX_OK && rc != NGX_AGAIN) { stream->skip_data = 1; ngx_http_finalize_request(r, rc); } @@ -1599,10 +1600,10 @@ ngx_http_v2_state_field_huff(ngx_http_v2_connection_t *h2c, u_char *pos, h2c->state.length -= size; h2c->state.field_rest -= size; - if (ngx_http_v2_huff_decode(&h2c->state.field_state, pos, size, - &h2c->state.field_end, - h2c->state.field_rest == 0, - h2c->connection->log) + if (ngx_http_huff_decode(&h2c->state.field_state, pos, size, + &h2c->state.field_end, + h2c->state.field_rest == 0, + h2c->connection->log) != NGX_OK) { ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, @@ -3457,7 +3458,7 @@ ngx_http_v2_validate_header(ngx_http_request_t *r, ngx_http_v2_header_t *header) continue; } - if (ch == '\0' || ch == LF || ch == CR || ch == ':' + if (ch <= 0x20 || ch == 0x7f || ch == ':' || (ch >= 'A' && ch <= 'Z')) { ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, @@ -3606,7 +3607,8 @@ ngx_http_v2_parse_method(ngx_http_request_t *r, ngx_str_t *value) { 4, "LOCK", NGX_HTTP_LOCK }, { 6, "UNLOCK", NGX_HTTP_UNLOCK }, { 5, "PATCH", NGX_HTTP_PATCH }, - { 5, "TRACE", NGX_HTTP_TRACE } + { 5, "TRACE", NGX_HTTP_TRACE }, + { 7, "CONNECT", NGX_HTTP_CONNECT } }, *test; if (r->method_name.len) { @@ -4026,16 +4028,30 @@ ngx_http_v2_read_request_body(ngx_http_request_t *r) return NGX_OK; } + rb->rest = 1; + + /* set rb->filter_need_buffering */ + + rc = ngx_http_top_request_body_filter(r, NULL); + + if (rc != NGX_OK) { + stream->skip_data = 1; + return rc; + } + h2scf = ngx_http_get_module_srv_conf(r, ngx_http_v2_module); clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); len = r->headers_in.content_length_n; - if (r->request_body_no_buffering && !stream->in_closed) { + if (len < 0 || len > (off_t) clcf->client_body_buffer_size) { + len = clcf->client_body_buffer_size; - if (len < 0 || len > (off_t) clcf->client_body_buffer_size) { - len = clcf->client_body_buffer_size; - } + } else { + len++; + } + + if (r->request_body_no_buffering || rb->filter_need_buffering) { /* * We need a room to store data up to the stream's initial window size, @@ -4049,57 +4065,54 @@ ngx_http_v2_read_request_body(ngx_http_request_t *r) if (len > NGX_HTTP_V2_MAX_WINDOW) { len = NGX_HTTP_V2_MAX_WINDOW; } - - rb->buf = ngx_create_temp_buf(r->pool, (size_t) len); - - } else if (len >= 0 && len <= (off_t) clcf->client_body_buffer_size - && !r->request_body_in_file_only) - { - rb->buf = ngx_create_temp_buf(r->pool, (size_t) len); - - } else { - rb->buf = ngx_calloc_buf(r->pool); - - if (rb->buf != NULL) { - rb->buf->sync = 1; - } } + rb->buf = ngx_create_temp_buf(r->pool, (size_t) len); + if (rb->buf == NULL) { stream->skip_data = 1; return NGX_HTTP_INTERNAL_SERVER_ERROR; } - rb->rest = 1; - buf = stream->preread; if (stream->in_closed) { - r->request_body_no_buffering = 0; + if (!rb->filter_need_buffering) { + r->request_body_no_buffering = 0; + } if (buf) { rc = ngx_http_v2_process_request_body(r, buf->pos, - buf->last - buf->pos, 1); + buf->last - buf->pos, 1, 0); ngx_pfree(r->pool, buf->start); + + } else { + rc = ngx_http_v2_process_request_body(r, NULL, 0, 1, 0); + } + + if (rc != NGX_AGAIN) { return rc; } - return ngx_http_v2_process_request_body(r, NULL, 0, 1); + r->read_event_handler = ngx_http_v2_read_client_request_body_handler; + r->write_event_handler = ngx_http_request_empty_handler; + + return NGX_AGAIN; } if (buf) { rc = ngx_http_v2_process_request_body(r, buf->pos, - buf->last - buf->pos, 0); + buf->last - buf->pos, 0, 0); ngx_pfree(r->pool, buf->start); - if (rc != NGX_OK) { + if (rc != NGX_OK && rc != NGX_AGAIN) { stream->skip_data = 1; return rc; } } - if (r->request_body_no_buffering) { + if (r->request_body_no_buffering || rb->filter_need_buffering) { size = (size_t) len - h2scf->preread_size; } else { @@ -4141,9 +4154,9 @@ ngx_http_v2_read_request_body(ngx_http_request_t *r) static ngx_int_t ngx_http_v2_process_request_body(ngx_http_request_t *r, u_char *pos, - size_t size, ngx_uint_t last) + size_t size, ngx_uint_t last, ngx_uint_t flush) { - ngx_buf_t *buf; + size_t n; ngx_int_t rc; ngx_connection_t *fc; ngx_http_request_body_t *rb; @@ -4151,77 +4164,122 @@ ngx_http_v2_process_request_body(ngx_http_request_t *r, u_char *pos, fc = r->connection; rb = r->request_body; - buf = rb->buf; - if (size) { - if (buf->sync) { - buf->pos = buf->start = pos; - buf->last = buf->end = pos + size; + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0, + "http2 process request body"); - r->request_body_in_file_only = 1; + if (size == 0 && !last && !flush) { + return NGX_AGAIN; + } - } else { - if (size > (size_t) (buf->end - buf->last)) { - ngx_log_error(NGX_LOG_INFO, fc->log, 0, - "client intended to send body data " - "larger than declared"); + for ( ;; ) { + for ( ;; ) { + if (rb->buf->last == rb->buf->end && size) { - return NGX_HTTP_BAD_REQUEST; + if (r->request_body_no_buffering) { + + /* should never happen due to flow control */ + + ngx_log_error(NGX_LOG_ALERT, fc->log, 0, + "no space in http2 body buffer"); + + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + /* update chains */ + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0, + "http2 body update chains"); + + rc = ngx_http_v2_filter_request_body(r); + + if (rc != NGX_OK) { + return rc; + } + + if (rb->busy != NULL) { + ngx_log_error(NGX_LOG_ALERT, fc->log, 0, + "busy buffers after request body flush"); + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + rb->buf->pos = rb->buf->start; + rb->buf->last = rb->buf->start; } - buf->last = ngx_cpymem(buf->last, pos, size); + /* copy body data to the buffer */ + + n = rb->buf->end - rb->buf->last; + + if (n > size) { + n = size; + } + + if (n > 0) { + rb->buf->last = ngx_cpymem(rb->buf->last, pos, n); + } + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0, + "http2 request body recv %uz", n); + + pos += n; + size -= n; + + if (size == 0 && last) { + rb->rest = 0; + } + + if (size == 0) { + break; + } + } + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0, + "http2 request body rest %O", rb->rest); + + if (flush) { + rc = ngx_http_v2_filter_request_body(r); + + if (rc != NGX_OK) { + return rc; + } + } + + if (rb->rest == 0 && rb->last_saved) { + break; + } + + if (size == 0) { + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + ngx_add_timer(fc->read, clcf->client_body_timeout); + + if (!flush) { + ngx_post_event(fc->read, &ngx_posted_events); + } + + return NGX_AGAIN; } } - if (last) { - rb->rest = 0; - - if (fc->read->timer_set) { - ngx_del_timer(fc->read); - } - - if (r->request_body_no_buffering) { - ngx_post_event(fc->read, &ngx_posted_events); - return NGX_OK; - } - - rc = ngx_http_v2_filter_request_body(r); - - if (rc != NGX_OK) { - return rc; - } - - if (buf->sync) { - /* prevent reusing this buffer in the upstream module */ - rb->buf = NULL; - } - - if (r->headers_in.chunked) { - r->headers_in.content_length_n = rb->received; - } - - r->read_event_handler = ngx_http_block_reading; - rb->post_handler(r); - - return NGX_OK; + if (fc->read->timer_set) { + ngx_del_timer(fc->read); } - if (size == 0) { - return NGX_OK; - } - - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - ngx_add_timer(fc->read, clcf->client_body_timeout); - if (r->request_body_no_buffering) { - ngx_post_event(fc->read, &ngx_posted_events); + if (!flush) { + ngx_post_event(fc->read, &ngx_posted_events); + } + return NGX_OK; } - if (buf->sync) { - return ngx_http_v2_filter_request_body(r); + if (r->headers_in.chunked) { + r->headers_in.content_length_n = rb->received; } + r->read_event_handler = ngx_http_block_reading; + rb->post_handler(r); + return NGX_OK; } @@ -4238,7 +4296,7 @@ ngx_http_v2_filter_request_body(ngx_http_request_t *r) rb = r->request_body; buf = rb->buf; - if (buf->pos == buf->last && rb->rest) { + if (buf->pos == buf->last && (rb->rest || rb->last_sent)) { cl = NULL; goto update; } @@ -4301,6 +4359,7 @@ ngx_http_v2_filter_request_body(ngx_http_request_t *r) } b->last_buf = 1; + rb->last_sent = 1; } b->tag = (ngx_buf_tag_t) &ngx_http_v2_filter_request_body; @@ -4320,7 +4379,12 @@ update: static void ngx_http_v2_read_client_request_body_handler(ngx_http_request_t *r) { - ngx_connection_t *fc; + size_t window; + ngx_buf_t *buf; + ngx_int_t rc; + ngx_connection_t *fc; + ngx_http_v2_stream_t *stream; + ngx_http_v2_connection_t *h2c; fc = r->connection; @@ -4346,6 +4410,75 @@ ngx_http_v2_read_client_request_body_handler(ngx_http_request_t *r) ngx_http_finalize_request(r, NGX_HTTP_CLIENT_CLOSED_REQUEST); return; } + + rc = ngx_http_v2_process_request_body(r, NULL, 0, r->stream->in_closed, 1); + + if (rc != NGX_OK && rc != NGX_AGAIN) { + r->stream->skip_data = 1; + ngx_http_finalize_request(r, rc); + return; + } + + if (rc == NGX_OK) { + return; + } + + if (r->stream->no_flow_control) { + return; + } + + if (r->request_body->rest == 0) { + return; + } + + if (r->request_body->busy != NULL) { + return; + } + + stream = r->stream; + h2c = stream->connection; + + buf = r->request_body->buf; + + buf->pos = buf->start; + buf->last = buf->start; + + window = buf->end - buf->start; + + if (h2c->state.stream == stream) { + window -= h2c->state.length; + } + + if (window <= stream->recv_window) { + if (window < stream->recv_window) { + ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, + "http2 negative window update"); + + stream->skip_data = 1; + + ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + + return; + } + + if (ngx_http_v2_send_window_update(h2c, stream->node->id, + window - stream->recv_window) + == NGX_ERROR) + { + stream->skip_data = 1; + ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + + stream->recv_window = window; + + if (ngx_http_v2_send_output_queue(h2c) == NGX_ERROR) { + stream->skip_data = 1; + ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } } @@ -4358,11 +4491,13 @@ ngx_http_v2_read_unbuffered_request_body(ngx_http_request_t *r) ngx_connection_t *fc; ngx_http_v2_stream_t *stream; ngx_http_v2_connection_t *h2c; - ngx_http_core_loc_conf_t *clcf; stream = r->stream; fc = r->connection; + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0, + "http2 read unbuffered request body"); + if (fc->read->timedout) { if (stream->recv_window) { stream->skip_data = 1; @@ -4379,17 +4514,21 @@ ngx_http_v2_read_unbuffered_request_body(ngx_http_request_t *r) return NGX_HTTP_BAD_REQUEST; } - rc = ngx_http_v2_filter_request_body(r); + rc = ngx_http_v2_process_request_body(r, NULL, 0, r->stream->in_closed, 1); - if (rc != NGX_OK) { + if (rc != NGX_OK && rc != NGX_AGAIN) { stream->skip_data = 1; return rc; } - if (!r->request_body->rest) { + if (rc == NGX_OK) { return NGX_OK; } + if (r->request_body->rest == 0) { + return NGX_AGAIN; + } + if (r->request_body->busy != NULL) { return NGX_AGAIN; } @@ -4430,11 +4569,6 @@ ngx_http_v2_read_unbuffered_request_body(ngx_http_request_t *r) return NGX_HTTP_INTERNAL_SERVER_ERROR; } - if (stream->recv_window == 0) { - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - ngx_add_timer(fc->read, clcf->client_body_timeout); - } - stream->recv_window = window; return NGX_AGAIN; diff --git a/src/http/v2/ngx_http_v2.h b/src/http/v2/ngx_http_v2.h index 3492297..70ee287 100644 --- a/src/http/v2/ngx_http_v2.h +++ b/src/http/v2/ngx_http_v2.h @@ -13,8 +13,7 @@ #include -#define NGX_HTTP_V2_ALPN_ADVERTISE "\x02h2" -#define NGX_HTTP_V2_NPN_ADVERTISE NGX_HTTP_V2_ALPN_ADVERTISE +#define NGX_HTTP_V2_ALPN_PROTO "\x02h2" #define NGX_HTTP_V2_STATE_BUFFER_SIZE 16 @@ -312,12 +311,6 @@ ngx_int_t ngx_http_v2_add_header(ngx_http_v2_connection_t *h2c, ngx_int_t ngx_http_v2_table_size(ngx_http_v2_connection_t *h2c, size_t size); -ngx_int_t ngx_http_v2_huff_decode(u_char *state, u_char *src, size_t len, - u_char **dst, ngx_uint_t last, ngx_log_t *log); -size_t ngx_http_v2_huff_encode(u_char *src, size_t len, u_char *dst, - ngx_uint_t lower); - - #define ngx_http_v2_prefix(bits) ((1 << (bits)) - 1) diff --git a/src/http/v2/ngx_http_v2_encode.c b/src/http/v2/ngx_http_v2_encode.c index ac79208..8798aa9 100644 --- a/src/http/v2/ngx_http_v2_encode.c +++ b/src/http/v2/ngx_http_v2_encode.c @@ -20,7 +20,7 @@ ngx_http_v2_string_encode(u_char *dst, u_char *src, size_t len, u_char *tmp, { size_t hlen; - hlen = ngx_http_v2_huff_encode(src, len, tmp, lower); + hlen = ngx_http_huff_encode(src, len, tmp, lower); if (hlen > 0) { *dst = NGX_HTTP_V2_ENCODE_HUFF; diff --git a/src/http/v2/ngx_http_v2_filter_module.c b/src/http/v2/ngx_http_v2_filter_module.c index a6e5e7d..9ffb155 100644 --- a/src/http/v2/ngx_http_v2_filter_module.c +++ b/src/http/v2/ngx_http_v2_filter_module.c @@ -1432,6 +1432,9 @@ ngx_http_v2_send_chain(ngx_connection_t *fc, ngx_chain_t *in, off_t limit) size = 0; #endif + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0, + "http2 send chain: %p", in); + while (in) { size = ngx_buf_size(in->buf); @@ -1450,12 +1453,8 @@ ngx_http_v2_send_chain(ngx_connection_t *fc, ngx_chain_t *in, off_t limit) return NGX_CHAIN_ERROR; } - if (stream->queued) { - fc->write->active = 1; - fc->write->ready = 0; - - } else { - fc->buffered &= ~NGX_HTTP_V2_BUFFERED; + if (ngx_http_v2_filter_send(fc, stream) == NGX_ERROR) { + return NGX_CHAIN_ERROR; } return NULL; @@ -1464,9 +1463,16 @@ ngx_http_v2_send_chain(ngx_connection_t *fc, ngx_chain_t *in, off_t limit) h2c = stream->connection; if (size && ngx_http_v2_flow_control(h2c, stream) == NGX_DECLINED) { - fc->write->active = 1; - fc->write->ready = 0; - return in; + + if (ngx_http_v2_filter_send(fc, stream) == NGX_ERROR) { + return NGX_CHAIN_ERROR; + } + + if (ngx_http_v2_flow_control(h2c, stream) == NGX_DECLINED) { + fc->write->active = 1; + fc->write->ready = 0; + return in; + } } if (in->buf->tag == (ngx_buf_tag_t) &ngx_http_v2_filter_get_shadow) { @@ -1809,6 +1815,11 @@ ngx_http_v2_waiting_queue(ngx_http_v2_connection_t *h2c, static ngx_inline ngx_int_t ngx_http_v2_filter_send(ngx_connection_t *fc, ngx_http_v2_stream_t *stream) { + if (stream->queued == 0) { + fc->buffered &= ~NGX_HTTP_V2_BUFFERED; + return NGX_OK; + } + stream->blocked = 1; if (ngx_http_v2_send_output_queue(stream->connection) == NGX_ERROR) { diff --git a/src/mail/ngx_mail.h b/src/mail/ngx_mail.h index b865a3b..e0c62b7 100644 --- a/src/mail/ngx_mail.h +++ b/src/mail/ngx_mail.h @@ -115,6 +115,8 @@ typedef struct { ngx_msec_t timeout; ngx_msec_t resolver_timeout; + ngx_uint_t max_errors; + ngx_str_t server_name; u_char *file_name; @@ -231,14 +233,15 @@ typedef struct { ngx_uint_t command; ngx_array_t args; + ngx_uint_t errors; ngx_uint_t login_attempt; /* used to parse POP3/IMAP/SMTP command */ ngx_uint_t state; + u_char *tag_start; u_char *cmd_start; u_char *arg_start; - u_char *arg_end; ngx_uint_t literal_len; } ngx_mail_session_t; @@ -321,6 +324,7 @@ typedef ngx_int_t (*ngx_mail_parse_command_pt)(ngx_mail_session_t *s); struct ngx_mail_protocol_s { ngx_str_t name; + ngx_str_t alpn; in_port_t port[4]; ngx_uint_t type; diff --git a/src/mail/ngx_mail_auth_http_module.c b/src/mail/ngx_mail_auth_http_module.c index 2a198f4..27f64b9 100644 --- a/src/mail/ngx_mail_auth_http_module.c +++ b/src/mail/ngx_mail_auth_http_module.c @@ -1137,8 +1137,8 @@ ngx_mail_auth_http_create_request(ngx_mail_session_t *s, ngx_pool_t *pool, ngx_str_t login, passwd; ngx_connection_t *c; #if (NGX_MAIL_SSL) - ngx_str_t verify, subject, issuer, serial, fingerprint, - raw_cert, cert; + ngx_str_t protocol, cipher, verify, subject, issuer, + serial, fingerprint, raw_cert, cert; ngx_mail_ssl_conf_t *sslcf; #endif ngx_mail_core_srv_conf_t *cscf; @@ -1155,6 +1155,25 @@ ngx_mail_auth_http_create_request(ngx_mail_session_t *s, ngx_pool_t *pool, #if (NGX_MAIL_SSL) + if (c->ssl) { + + if (ngx_ssl_get_protocol(c, pool, &protocol) != NGX_OK) { + return NULL; + } + + protocol.len = ngx_strlen(protocol.data); + + if (ngx_ssl_get_cipher_name(c, pool, &cipher) != NGX_OK) { + return NULL; + } + + cipher.len = ngx_strlen(cipher.data); + + } else { + ngx_str_null(&protocol); + ngx_str_null(&cipher); + } + sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); if (c->ssl && sslcf->verify) { @@ -1252,6 +1271,10 @@ ngx_mail_auth_http_create_request(ngx_mail_session_t *s, ngx_pool_t *pool, if (c->ssl) { len += sizeof("Auth-SSL: on" CRLF) - 1 + + sizeof("Auth-SSL-Protocol: ") - 1 + protocol.len + + sizeof(CRLF) - 1 + + sizeof("Auth-SSL-Cipher: ") - 1 + cipher.len + + sizeof(CRLF) - 1 + sizeof("Auth-SSL-Verify: ") - 1 + verify.len + sizeof(CRLF) - 1 + sizeof("Auth-SSL-Subject: ") - 1 + subject.len @@ -1373,6 +1396,20 @@ ngx_mail_auth_http_create_request(ngx_mail_session_t *s, ngx_pool_t *pool, b->last = ngx_cpymem(b->last, "Auth-SSL: on" CRLF, sizeof("Auth-SSL: on" CRLF) - 1); + if (protocol.len) { + b->last = ngx_cpymem(b->last, "Auth-SSL-Protocol: ", + sizeof("Auth-SSL-Protocol: ") - 1); + b->last = ngx_copy(b->last, protocol.data, protocol.len); + *b->last++ = CR; *b->last++ = LF; + } + + if (cipher.len) { + b->last = ngx_cpymem(b->last, "Auth-SSL-Cipher: ", + sizeof("Auth-SSL-Cipher: ") - 1); + b->last = ngx_copy(b->last, cipher.data, cipher.len); + *b->last++ = CR; *b->last++ = LF; + } + if (verify.len) { b->last = ngx_cpymem(b->last, "Auth-SSL-Verify: ", sizeof("Auth-SSL-Verify: ") - 1); diff --git a/src/mail/ngx_mail_core_module.c b/src/mail/ngx_mail_core_module.c index 4083124..115671c 100644 --- a/src/mail/ngx_mail_core_module.c +++ b/src/mail/ngx_mail_core_module.c @@ -85,6 +85,13 @@ static ngx_command_t ngx_mail_core_commands[] = { offsetof(ngx_mail_core_srv_conf_t, resolver_timeout), NULL }, + { ngx_string("max_errors"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_core_srv_conf_t, max_errors), + NULL }, + ngx_null_command }; @@ -163,6 +170,8 @@ ngx_mail_core_create_srv_conf(ngx_conf_t *cf) cscf->timeout = NGX_CONF_UNSET_MSEC; cscf->resolver_timeout = NGX_CONF_UNSET_MSEC; + cscf->max_errors = NGX_CONF_UNSET_UINT; + cscf->resolver = NGX_CONF_UNSET_PTR; cscf->file_name = cf->conf_file->file.name.data; @@ -182,6 +191,7 @@ ngx_mail_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_msec_value(conf->resolver_timeout, prev->resolver_timeout, 30000); + ngx_conf_merge_uint_value(conf->max_errors, prev->max_errors, 5); ngx_conf_merge_str_value(conf->server_name, prev->server_name, ""); diff --git a/src/mail/ngx_mail_handler.c b/src/mail/ngx_mail_handler.c index 0aaa0e7..246ba97 100644 --- a/src/mail/ngx_mail_handler.c +++ b/src/mail/ngx_mail_handler.c @@ -833,20 +833,23 @@ ngx_mail_read_command(ngx_mail_session_t *s, ngx_connection_t *c) ngx_str_t l; ngx_mail_core_srv_conf_t *cscf; - n = c->recv(c, s->buffer->last, s->buffer->end - s->buffer->last); + if (s->buffer->last < s->buffer->end) { - if (n == NGX_ERROR || n == 0) { - ngx_mail_close_connection(c); - return NGX_ERROR; - } + n = c->recv(c, s->buffer->last, s->buffer->end - s->buffer->last); - if (n > 0) { - s->buffer->last += n; - } + if (n == NGX_ERROR || n == 0) { + ngx_mail_close_connection(c); + return NGX_ERROR; + } - if (n == NGX_AGAIN) { - if (s->buffer->pos == s->buffer->last) { - return NGX_AGAIN; + if (n > 0) { + s->buffer->last += n; + } + + if (n == NGX_AGAIN) { + if (s->buffer->pos == s->buffer->last) { + return NGX_AGAIN; + } } } @@ -871,7 +874,20 @@ ngx_mail_read_command(ngx_mail_session_t *s, ngx_connection_t *c) return NGX_MAIL_PARSE_INVALID_COMMAND; } - if (rc == NGX_IMAP_NEXT || rc == NGX_MAIL_PARSE_INVALID_COMMAND) { + if (rc == NGX_MAIL_PARSE_INVALID_COMMAND) { + + s->errors++; + + if (s->errors >= cscf->max_errors) { + ngx_log_error(NGX_LOG_INFO, c->log, 0, + "client sent too many invalid commands"); + s->quit = 1; + } + + return rc; + } + + if (rc == NGX_IMAP_NEXT) { return rc; } diff --git a/src/mail/ngx_mail_imap_handler.c b/src/mail/ngx_mail_imap_handler.c index 5dfdd76..291e87a 100644 --- a/src/mail/ngx_mail_imap_handler.c +++ b/src/mail/ngx_mail_imap_handler.c @@ -101,10 +101,9 @@ ngx_mail_imap_init_protocol(ngx_event_t *rev) void ngx_mail_imap_auth_state(ngx_event_t *rev) { - u_char *p, *dst, *src, *end; - ngx_str_t *arg; + u_char *p; ngx_int_t rc; - ngx_uint_t tag, i; + ngx_uint_t tag; ngx_connection_t *c; ngx_mail_session_t *s; @@ -158,27 +157,6 @@ ngx_mail_imap_auth_state(ngx_event_t *rev) ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, "imap auth command: %i", s->command); - if (s->backslash) { - - arg = s->args.elts; - - for (i = 0; i < s->args.nelts; i++) { - dst = arg[i].data; - end = dst + arg[i].len; - - for (src = dst; src < end; dst++) { - *dst = *src; - if (*src++ == '\\') { - *dst = *src++; - } - } - - arg[i].len = dst - arg[i].data; - } - - s->backslash = 0; - } - switch (s->mail_state) { case ngx_imap_start: @@ -248,6 +226,10 @@ ngx_mail_imap_auth_state(ngx_event_t *rev) ngx_str_set(&s->out, imap_next); } + if (s->buffer->pos < s->buffer->last) { + s->blocked = 1; + } + switch (rc) { case NGX_DONE: @@ -297,13 +279,14 @@ ngx_mail_imap_auth_state(ngx_event_t *rev) if (s->state) { /* preserve tag */ - s->arg_start = s->buffer->start + s->tag.len; - s->buffer->pos = s->arg_start; - s->buffer->last = s->arg_start; + s->arg_start = s->buffer->pos; } else { - s->buffer->pos = s->buffer->start; - s->buffer->last = s->buffer->start; + if (s->buffer->pos == s->buffer->last) { + s->buffer->pos = s->buffer->start; + s->buffer->last = s->buffer->start; + } + s->tag.len = 0; } } @@ -481,6 +464,8 @@ ngx_mail_imap_starttls(ngx_mail_session_t *s, ngx_connection_t *c) if (c->ssl == NULL) { sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); if (sslcf->starttls) { + s->buffer->pos = s->buffer->start; + s->buffer->last = s->buffer->start; c->read->handler = ngx_mail_starttls_handler; return NGX_OK; } diff --git a/src/mail/ngx_mail_imap_module.c b/src/mail/ngx_mail_imap_module.c index 1f187fd..02c684c 100644 --- a/src/mail/ngx_mail_imap_module.c +++ b/src/mail/ngx_mail_imap_module.c @@ -46,6 +46,7 @@ static ngx_str_t ngx_mail_imap_auth_methods_names[] = { static ngx_mail_protocol_t ngx_mail_imap_protocol = { ngx_string("imap"), + ngx_string("\x04imap"), { 143, 993, 0, 0 }, NGX_MAIL_IMAP_PROTOCOL, diff --git a/src/mail/ngx_mail_parse.c b/src/mail/ngx_mail_parse.c index 2c2cdff..4db1f18 100644 --- a/src/mail/ngx_mail_parse.c +++ b/src/mail/ngx_mail_parse.c @@ -21,6 +21,8 @@ ngx_mail_pop3_parse_command(ngx_mail_session_t *s) ngx_str_t *arg; enum { sw_start = 0, + sw_command, + sw_invalid, sw_spaces_before_argument, sw_argument, sw_almost_done @@ -35,8 +37,14 @@ ngx_mail_pop3_parse_command(ngx_mail_session_t *s) /* POP3 command */ case sw_start: + s->cmd_start = p; + state = sw_command; + + /* fall through */ + + case sw_command: if (ch == ' ' || ch == CR || ch == LF) { - c = s->buffer->start; + c = s->cmd_start; if (p - c == 4) { @@ -85,6 +93,9 @@ ngx_mail_pop3_parse_command(ngx_mail_session_t *s) goto invalid; } + s->cmd.data = s->cmd_start; + s->cmd.len = p - s->cmd_start; + switch (ch) { case ' ': state = sw_spaces_before_argument; @@ -104,16 +115,17 @@ ngx_mail_pop3_parse_command(ngx_mail_session_t *s) break; + case sw_invalid: + goto invalid; + case sw_spaces_before_argument: switch (ch) { case ' ': break; case CR: state = sw_almost_done; - s->arg_end = p; break; case LF: - s->arg_end = p; goto done; default: if (s->args.nelts <= 2) { @@ -188,37 +200,39 @@ ngx_mail_pop3_parse_command(ngx_mail_session_t *s) done: s->buffer->pos = p + 1; - - if (s->arg_start) { - arg = ngx_array_push(&s->args); - if (arg == NULL) { - return NGX_ERROR; - } - arg->len = s->arg_end - s->arg_start; - arg->data = s->arg_start; - s->arg_start = NULL; - } - s->state = (s->command != NGX_POP3_AUTH) ? sw_start : sw_argument; return NGX_OK; invalid: - s->state = sw_start; - s->arg_start = NULL; + s->state = sw_invalid; - return NGX_MAIL_PARSE_INVALID_COMMAND; + /* skip invalid command till LF */ + + for ( /* void */ ; p < s->buffer->last; p++) { + if (*p == LF) { + s->state = sw_start; + s->buffer->pos = p + 1; + return NGX_MAIL_PARSE_INVALID_COMMAND; + } + } + + s->buffer->pos = p; + + return NGX_AGAIN; } ngx_int_t ngx_mail_imap_parse_command(ngx_mail_session_t *s) { - u_char ch, *p, *c; + u_char ch, *p, *c, *dst, *src, *end; ngx_str_t *arg; enum { sw_start = 0, + sw_tag, + sw_invalid, sw_spaces_before_command, sw_command, sw_spaces_before_argument, @@ -241,31 +255,45 @@ ngx_mail_imap_parse_command(ngx_mail_session_t *s) /* IMAP tag */ case sw_start: + s->tag_start = p; + state = sw_tag; + + /* fall through */ + + case sw_tag: switch (ch) { case ' ': - s->tag.len = p - s->buffer->start + 1; - s->tag.data = s->buffer->start; + s->tag.len = p - s->tag_start + 1; + s->tag.data = s->tag_start; state = sw_spaces_before_command; break; case CR: - s->state = sw_start; - return NGX_MAIL_PARSE_INVALID_COMMAND; case LF: - s->state = sw_start; - return NGX_MAIL_PARSE_INVALID_COMMAND; + goto invalid; + default: + if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z') + && (ch < '0' || ch > '9') && ch != '-' && ch != '.' + && ch != '_') + { + goto invalid; + } + if (p - s->tag_start > 31) { + goto invalid; + } + break; } break; + case sw_invalid: + goto invalid; + case sw_spaces_before_command: switch (ch) { case ' ': break; case CR: - s->state = sw_start; - return NGX_MAIL_PARSE_INVALID_COMMAND; case LF: - s->state = sw_start; - return NGX_MAIL_PARSE_INVALID_COMMAND; + goto invalid; default: s->cmd_start = p; state = sw_command; @@ -385,6 +413,9 @@ ngx_mail_imap_parse_command(ngx_mail_session_t *s) goto invalid; } + s->cmd.data = s->cmd_start; + s->cmd.len = p - s->cmd_start; + switch (ch) { case ' ': state = sw_spaces_before_argument; @@ -410,10 +441,8 @@ ngx_mail_imap_parse_command(ngx_mail_session_t *s) break; case CR: state = sw_almost_done; - s->arg_end = p; break; case LF: - s->arg_end = p; goto done; case '"': if (s->args.nelts <= 2) { @@ -460,6 +489,22 @@ ngx_mail_imap_parse_command(ngx_mail_session_t *s) } arg->len = p - s->arg_start; arg->data = s->arg_start; + + if (s->backslash) { + dst = s->arg_start; + end = p; + + for (src = dst; src < end; dst++) { + *dst = *src; + if (*src++ == '\\') { + *dst = *src++; + } + } + + arg->len = dst - s->arg_start; + s->backslash = 0; + } + s->arg_start = NULL; switch (ch) { @@ -588,34 +633,46 @@ ngx_mail_imap_parse_command(ngx_mail_session_t *s) done: s->buffer->pos = p + 1; - - if (s->arg_start) { - arg = ngx_array_push(&s->args); - if (arg == NULL) { - return NGX_ERROR; - } - arg->len = s->arg_end - s->arg_start; - arg->data = s->arg_start; - - s->arg_start = NULL; - s->cmd_start = NULL; - s->quoted = 0; - s->no_sync_literal = 0; - s->literal_len = 0; - } - s->state = (s->command != NGX_IMAP_AUTHENTICATE) ? sw_start : sw_argument; return NGX_OK; invalid: - s->state = sw_start; + s->state = sw_invalid; s->quoted = 0; + s->backslash = 0; s->no_sync_literal = 0; s->literal_len = 0; - return NGX_MAIL_PARSE_INVALID_COMMAND; + /* skip invalid command till LF */ + + for ( /* void */ ; p < s->buffer->last; p++) { + if (*p == LF) { + s->state = sw_start; + s->buffer->pos = p + 1; + + /* detect non-synchronizing literals */ + + if ((size_t) (p - s->buffer->start) > sizeof("{1+}") - 1) { + p--; + + if (*p == CR) { + p--; + } + + if (*p == '}' && *(p - 1) == '+') { + s->quit = 1; + } + } + + return NGX_MAIL_PARSE_INVALID_COMMAND; + } + } + + s->buffer->pos = p; + + return NGX_AGAIN; } @@ -758,10 +815,8 @@ ngx_mail_smtp_parse_command(ngx_mail_session_t *s) break; case CR: state = sw_almost_done; - s->arg_end = p; break; case LF: - s->arg_end = p; goto done; default: if (s->args.nelts <= 10) { @@ -821,17 +876,6 @@ ngx_mail_smtp_parse_command(ngx_mail_session_t *s) done: s->buffer->pos = p + 1; - - if (s->arg_start) { - arg = ngx_array_push(&s->args); - if (arg == NULL) { - return NGX_ERROR; - } - arg->len = s->arg_end - s->arg_start; - arg->data = s->arg_start; - s->arg_start = NULL; - } - s->state = (s->command != NGX_SMTP_AUTH) ? sw_start : sw_argument; return NGX_OK; @@ -839,21 +883,20 @@ done: invalid: s->state = sw_invalid; - s->arg_start = NULL; /* skip invalid command till LF */ - for (p = s->buffer->pos; p < s->buffer->last; p++) { + for ( /* void */ ; p < s->buffer->last; p++) { if (*p == LF) { s->state = sw_start; - p++; - break; + s->buffer->pos = p + 1; + return NGX_MAIL_PARSE_INVALID_COMMAND; } } s->buffer->pos = p; - return NGX_MAIL_PARSE_INVALID_COMMAND; + return NGX_AGAIN; } diff --git a/src/mail/ngx_mail_pop3_handler.c b/src/mail/ngx_mail_pop3_handler.c index edfd986..226e741 100644 --- a/src/mail/ngx_mail_pop3_handler.c +++ b/src/mail/ngx_mail_pop3_handler.c @@ -262,6 +262,10 @@ ngx_mail_pop3_auth_state(ngx_event_t *rev) } } + if (s->buffer->pos < s->buffer->last) { + s->blocked = 1; + } + switch (rc) { case NGX_DONE: @@ -283,11 +287,14 @@ ngx_mail_pop3_auth_state(ngx_event_t *rev) case NGX_OK: s->args.nelts = 0; - s->buffer->pos = s->buffer->start; - s->buffer->last = s->buffer->start; + + if (s->buffer->pos == s->buffer->last) { + s->buffer->pos = s->buffer->start; + s->buffer->last = s->buffer->start; + } if (s->state) { - s->arg_start = s->buffer->start; + s->arg_start = s->buffer->pos; } if (ngx_handle_read_event(c->read, 0) != NGX_OK) { @@ -400,6 +407,8 @@ ngx_mail_pop3_stls(ngx_mail_session_t *s, ngx_connection_t *c) if (c->ssl == NULL) { sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); if (sslcf->starttls) { + s->buffer->pos = s->buffer->start; + s->buffer->last = s->buffer->start; c->read->handler = ngx_mail_starttls_handler; return NGX_OK; } diff --git a/src/mail/ngx_mail_pop3_module.c b/src/mail/ngx_mail_pop3_module.c index a673070..a257b5a 100644 --- a/src/mail/ngx_mail_pop3_module.c +++ b/src/mail/ngx_mail_pop3_module.c @@ -46,6 +46,7 @@ static ngx_str_t ngx_mail_pop3_auth_methods_names[] = { static ngx_mail_protocol_t ngx_mail_pop3_protocol = { ngx_string("pop3"), + ngx_string("\x04pop3"), { 110, 995, 0, 0 }, NGX_MAIL_POP3_PROTOCOL, diff --git a/src/mail/ngx_mail_proxy_module.c b/src/mail/ngx_mail_proxy_module.c index 66aa0ba..a7ab077 100644 --- a/src/mail/ngx_mail_proxy_module.c +++ b/src/mail/ngx_mail_proxy_module.c @@ -327,6 +327,10 @@ ngx_mail_proxy_pop3_handler(ngx_event_t *rev) c->log->action = NULL; ngx_log_error(NGX_LOG_INFO, c->log, 0, "client logged in"); + if (s->buffer->pos < s->buffer->last) { + ngx_post_event(c->write, &ngx_posted_events); + } + ngx_mail_proxy_handler(s->connection->write); return; @@ -482,6 +486,10 @@ ngx_mail_proxy_imap_handler(ngx_event_t *rev) c->log->action = NULL; ngx_log_error(NGX_LOG_INFO, c->log, 0, "client logged in"); + if (s->buffer->pos < s->buffer->last) { + ngx_post_event(c->write, &ngx_posted_events); + } + ngx_mail_proxy_handler(s->connection->write); return; @@ -813,13 +821,12 @@ ngx_mail_proxy_smtp_handler(ngx_event_t *rev) c->log->action = NULL; ngx_log_error(NGX_LOG_INFO, c->log, 0, "client logged in"); - if (s->buffer->pos == s->buffer->last) { - ngx_mail_proxy_handler(s->connection->write); - - } else { - ngx_mail_proxy_handler(c->write); + if (s->buffer->pos < s->buffer->last) { + ngx_post_event(c->write, &ngx_posted_events); } + ngx_mail_proxy_handler(s->connection->write); + return; default: diff --git a/src/mail/ngx_mail_smtp_module.c b/src/mail/ngx_mail_smtp_module.c index 3b5a2d8..0e05fdc 100644 --- a/src/mail/ngx_mail_smtp_module.c +++ b/src/mail/ngx_mail_smtp_module.c @@ -39,6 +39,7 @@ static ngx_str_t ngx_mail_smtp_auth_methods_names[] = { static ngx_mail_protocol_t ngx_mail_smtp_protocol = { ngx_string("smtp"), + ngx_string("\x04smtp"), { 25, 465, 587, 0 }, NGX_MAIL_SMTP_PROTOCOL, diff --git a/src/mail/ngx_mail_ssl_module.c b/src/mail/ngx_mail_ssl_module.c index 7eae83e..2a1043e 100644 --- a/src/mail/ngx_mail_ssl_module.c +++ b/src/mail/ngx_mail_ssl_module.c @@ -14,6 +14,12 @@ #define NGX_DEFAULT_ECDH_CURVE "auto" +#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation +static int ngx_mail_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, + const unsigned char **out, unsigned char *outlen, + const unsigned char *in, unsigned int inlen, void *arg); +#endif + static void *ngx_mail_ssl_create_conf(ngx_conf_t *cf); static char *ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child); @@ -244,6 +250,54 @@ ngx_module_t ngx_mail_ssl_module = { static ngx_str_t ngx_mail_ssl_sess_id_ctx = ngx_string("MAIL"); +#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation + +static int +ngx_mail_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out, + unsigned char *outlen, const unsigned char *in, unsigned int inlen, + void *arg) +{ + unsigned int srvlen; + unsigned char *srv; + ngx_connection_t *c; + ngx_mail_session_t *s; + ngx_mail_core_srv_conf_t *cscf; +#if (NGX_DEBUG) + unsigned int i; +#endif + + c = ngx_ssl_get_connection(ssl_conn); + s = c->data; + +#if (NGX_DEBUG) + for (i = 0; i < inlen; i += in[i] + 1) { + ngx_log_debug2(NGX_LOG_DEBUG_MAIL, c->log, 0, + "SSL ALPN supported by client: %*s", + (size_t) in[i], &in[i + 1]); + } +#endif + + cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + + srv = cscf->protocol->alpn.data; + srvlen = cscf->protocol->alpn.len; + + if (SSL_select_next_proto((unsigned char **) out, outlen, srv, srvlen, + in, inlen) + != OPENSSL_NPN_NEGOTIATED) + { + return SSL_TLSEXT_ERR_ALERT_FATAL; + } + + ngx_log_debug2(NGX_LOG_DEBUG_MAIL, c->log, 0, + "SSL ALPN selected: %*s", (size_t) *outlen, *out); + + return SSL_TLSEXT_ERR_OK; +} + +#endif + + static void * ngx_mail_ssl_create_conf(ngx_conf_t *cf) { @@ -394,6 +448,17 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) cln->handler = ngx_ssl_cleanup_ctx; cln->data = &conf->ssl; +#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation + SSL_CTX_set_alpn_select_cb(conf->ssl.ctx, ngx_mail_ssl_alpn_select, NULL); +#endif + + if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers, + conf->prefer_server_ciphers) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates, conf->certificate_keys, conf->passwords) != NGX_OK) @@ -430,13 +495,6 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) } } - if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers, - conf->prefer_server_ciphers) - != NGX_OK) - { - return NGX_CONF_ERROR; - } - if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) { return NGX_CONF_ERROR; } diff --git a/src/os/unix/ngx_atomic.h b/src/os/unix/ngx_atomic.h index 74b8b7f..fcab2d6 100644 --- a/src/os/unix/ngx_atomic.h +++ b/src/os/unix/ngx_atomic.h @@ -38,6 +38,39 @@ typedef volatile ngx_atomic_uint_t ngx_atomic_t; #define ngx_cpu_pause() +#elif (NGX_HAVE_GCC_ATOMIC) + +/* GCC 4.1 builtin atomic operations */ + +#define NGX_HAVE_ATOMIC_OPS 1 + +typedef long ngx_atomic_int_t; +typedef unsigned long ngx_atomic_uint_t; + +#if (NGX_PTR_SIZE == 8) +#define NGX_ATOMIC_T_LEN (sizeof("-9223372036854775808") - 1) +#else +#define NGX_ATOMIC_T_LEN (sizeof("-2147483648") - 1) +#endif + +typedef volatile ngx_atomic_uint_t ngx_atomic_t; + + +#define ngx_atomic_cmp_set(lock, old, set) \ + __sync_bool_compare_and_swap(lock, old, set) + +#define ngx_atomic_fetch_add(value, add) \ + __sync_fetch_and_add(value, add) + +#define ngx_memory_barrier() __sync_synchronize() + +#if ( __i386__ || __i386 || __amd64__ || __amd64 ) +#define ngx_cpu_pause() __asm__ ("pause") +#else +#define ngx_cpu_pause() +#endif + + #elif (NGX_DARWIN_ATOMIC) /* @@ -88,39 +121,6 @@ typedef uint32_t ngx_atomic_uint_t; typedef volatile ngx_atomic_uint_t ngx_atomic_t; -#elif (NGX_HAVE_GCC_ATOMIC) - -/* GCC 4.1 builtin atomic operations */ - -#define NGX_HAVE_ATOMIC_OPS 1 - -typedef long ngx_atomic_int_t; -typedef unsigned long ngx_atomic_uint_t; - -#if (NGX_PTR_SIZE == 8) -#define NGX_ATOMIC_T_LEN (sizeof("-9223372036854775808") - 1) -#else -#define NGX_ATOMIC_T_LEN (sizeof("-2147483648") - 1) -#endif - -typedef volatile ngx_atomic_uint_t ngx_atomic_t; - - -#define ngx_atomic_cmp_set(lock, old, set) \ - __sync_bool_compare_and_swap(lock, old, set) - -#define ngx_atomic_fetch_add(value, add) \ - __sync_fetch_and_add(value, add) - -#define ngx_memory_barrier() __sync_synchronize() - -#if ( __i386__ || __i386 || __amd64__ || __amd64 ) -#define ngx_cpu_pause() __asm__ ("pause") -#else -#define ngx_cpu_pause() -#endif - - #elif ( __i386__ || __i386 ) typedef int32_t ngx_atomic_int_t; diff --git a/src/os/unix/ngx_freebsd_sendfile_chain.c b/src/os/unix/ngx_freebsd_sendfile_chain.c index 3d415bd..5c6a830 100644 --- a/src/os/unix/ngx_freebsd_sendfile_chain.c +++ b/src/os/unix/ngx_freebsd_sendfile_chain.c @@ -32,23 +32,22 @@ ngx_chain_t * ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) { - int rc, flags; - off_t send, prev_send, sent; - size_t file_size; - ssize_t n; - ngx_uint_t eintr, eagain; - ngx_err_t err; - ngx_buf_t *file; - ngx_event_t *wev; - ngx_chain_t *cl; - ngx_iovec_t header, trailer; - struct sf_hdtr hdtr; - struct iovec headers[NGX_IOVS_PREALLOCATE]; - struct iovec trailers[NGX_IOVS_PREALLOCATE]; -#if (NGX_HAVE_AIO_SENDFILE) - ngx_uint_t ebusy; - ngx_event_aio_t *aio; + int rc, flags; + off_t send, prev_send, sent; + size_t file_size; + ssize_t n; + ngx_err_t err; + ngx_buf_t *file; + ngx_uint_t eintr, eagain; +#if (NGX_HAVE_SENDFILE_NODISKIO) + ngx_uint_t ebusy; #endif + ngx_event_t *wev; + ngx_chain_t *cl; + ngx_iovec_t header, trailer; + struct sf_hdtr hdtr; + struct iovec headers[NGX_IOVS_PREALLOCATE]; + struct iovec trailers[NGX_IOVS_PREALLOCATE]; wev = c->write; @@ -77,11 +76,6 @@ ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) eagain = 0; flags = 0; -#if (NGX_HAVE_AIO_SENDFILE && NGX_SUPPRESS_WARN) - aio = NULL; - file = NULL; -#endif - header.iovs = headers; header.nalloc = NGX_IOVS_PREALLOCATE; @@ -90,7 +84,7 @@ ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) for ( ;; ) { eintr = 0; -#if (NGX_HAVE_AIO_SENDFILE) +#if (NGX_HAVE_SENDFILE_NODISKIO) ebusy = 0; #endif prev_send = send; @@ -179,9 +173,14 @@ ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) sent = 0; -#if (NGX_HAVE_AIO_SENDFILE) - aio = file->file->aio; - flags = (aio && aio->preload_handler) ? SF_NODISKIO : 0; +#if (NGX_HAVE_SENDFILE_NODISKIO) + + flags = (c->busy_count <= 2) ? SF_NODISKIO : 0; + + if (file->file->directio) { + flags |= SF_NOCACHE; + } + #endif rc = sendfile(file->file->fd, c->fd, file->file_pos, @@ -199,7 +198,7 @@ ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) eintr = 1; break; -#if (NGX_HAVE_AIO_SENDFILE) +#if (NGX_HAVE_SENDFILE_NODISKIO) case NGX_EBUSY: ebusy = 1; break; @@ -252,54 +251,30 @@ ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) in = ngx_chain_update_sent(in, sent); -#if (NGX_HAVE_AIO_SENDFILE) +#if (NGX_HAVE_SENDFILE_NODISKIO) if (ebusy) { - if (aio->event.active) { - /* - * tolerate duplicate calls; they can happen due to subrequests - * or multiple calls of the next body filter from a filter - */ - - if (sent) { - c->busy_count = 0; - } - - return in; - } - if (sent == 0) { c->busy_count++; - if (c->busy_count > 2) { - ngx_log_error(NGX_LOG_ALERT, c->log, 0, - "sendfile(%V) returned busy again", - &file->file->name); - - c->busy_count = 0; - aio->preload_handler = NULL; - - send = prev_send; - continue; - } + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, + "sendfile() busy, count:%d", c->busy_count); } else { c->busy_count = 0; } - n = aio->preload_handler(file); - - if (n > 0) { - send = prev_send + sent; - continue; + if (wev->posted) { + ngx_delete_posted_event(wev); } + ngx_post_event(wev, &ngx_posted_next_events); + + wev->ready = 0; return in; } - if (flags == SF_NODISKIO) { - c->busy_count = 0; - } + c->busy_count = 0; #endif diff --git a/src/os/unix/ngx_linux_sendfile_chain.c b/src/os/unix/ngx_linux_sendfile_chain.c index 5695839..101d91a 100644 --- a/src/os/unix/ngx_linux_sendfile_chain.c +++ b/src/os/unix/ngx_linux_sendfile_chain.c @@ -38,6 +38,9 @@ static void ngx_linux_sendfile_thread_handler(void *data, ngx_log_t *log); * On Linux up to 2.6.16 sendfile() does not allow to pass the count parameter * more than 2G-1 bytes even on 64-bit platforms: it returns EINVAL, * so we limit it to 2G-1 bytes. + * + * On Linux 2.6.16 and later, sendfile() silently limits the count parameter + * to 2G minus the page size, even on 64-bit platforms. */ #define NGX_SENDFILE_MAXSIZE 2147483647L @@ -216,7 +219,6 @@ ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) */ send = prev_send + sent; - continue; } if (send >= limit || in == NULL) { @@ -377,15 +379,6 @@ ngx_linux_sendfile_thread(ngx_connection_t *c, ngx_buf_t *file, size_t size) return ctx->sent; } - if (task->event.active && ctx->file == file) { - /* - * tolerate duplicate calls; they can happen due to subrequests - * or multiple calls of the next body filter from a filter - */ - - return NGX_DONE; - } - ctx->file = file; ctx->socket = c->fd; ctx->size = size; diff --git a/src/os/unix/ngx_process_cycle.c b/src/os/unix/ngx_process_cycle.c index b31485f..07cd05e 100644 --- a/src/os/unix/ngx_process_cycle.c +++ b/src/os/unix/ngx_process_cycle.c @@ -398,6 +398,8 @@ ngx_pass_open_channel(ngx_cycle_t *cycle) ngx_int_t i; ngx_channel_t ch; + ngx_memzero(&ch, sizeof(ngx_channel_t)); + ch.command = NGX_CMD_OPEN_CHANNEL; ch.pid = ngx_processes[ngx_process_slot].pid; ch.slot = ngx_process_slot; diff --git a/src/os/unix/ngx_readv_chain.c b/src/os/unix/ngx_readv_chain.c index a3577ce..b1ae4b5 100644 --- a/src/os/unix/ngx_readv_chain.c +++ b/src/os/unix/ngx_readv_chain.c @@ -96,7 +96,7 @@ ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain, off_t limit) iov->iov_len += n; } else { - if (vec.nelts >= IOV_MAX) { + if (vec.nelts == vec.nalloc) { break; } diff --git a/src/stream/ngx_stream.c b/src/stream/ngx_stream.c index 7835675..3304c84 100644 --- a/src/stream/ngx_stream.c +++ b/src/stream/ngx_stream.c @@ -510,6 +510,10 @@ ngx_stream_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports) ls->ipv6only = addr[i].opt.ipv6only; #endif +#if (NGX_HAVE_TCP_FASTOPEN) + ls->fastopen = addr[i].opt.fastopen; +#endif + #if (NGX_HAVE_REUSEPORT) ls->reuseport = addr[i].opt.reuseport; #endif diff --git a/src/stream/ngx_stream.h b/src/stream/ngx_stream.h index 9e35832..46c3622 100644 --- a/src/stream/ngx_stream.h +++ b/src/stream/ngx_stream.h @@ -65,6 +65,9 @@ typedef struct { int backlog; int rcvbuf; int sndbuf; +#if (NGX_HAVE_TCP_FASTOPEN) + int fastopen; +#endif int type; } ngx_stream_listen_t; diff --git a/src/stream/ngx_stream_core_module.c b/src/stream/ngx_stream_core_module.c index 9b6afe9..d96d27a 100644 --- a/src/stream/ngx_stream_core_module.c +++ b/src/stream/ngx_stream_core_module.c @@ -615,6 +615,10 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ls->type = SOCK_STREAM; ls->ctx = cf->ctx; +#if (NGX_HAVE_TCP_FASTOPEN) + ls->fastopen = -1; +#endif + #if (NGX_HAVE_INET6) ls->ipv6only = 1; #endif @@ -635,6 +639,21 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) continue; } +#if (NGX_HAVE_TCP_FASTOPEN) + if (ngx_strncmp(value[i].data, "fastopen=", 9) == 0) { + ls->fastopen = ngx_atoi(value[i].data + 9, value[i].len - 9); + ls->bind = 1; + + if (ls->fastopen == NGX_ERROR) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid fastopen \"%V\"", &value[i]); + return NGX_CONF_ERROR; + } + + continue; + } +#endif + if (ngx_strncmp(value[i].data, "backlog=", 8) == 0) { ls->backlog = ngx_atoi(value[i].data + 8, value[i].len - 8); ls->bind = 1; @@ -859,6 +878,12 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) if (ls->proxy_protocol) { return "\"proxy_protocol\" parameter is incompatible with \"udp\""; } + +#if (NGX_HAVE_TCP_FASTOPEN) + if (ls->fastopen != -1) { + return "\"fastopen\" parameter is incompatible with \"udp\""; + } +#endif } als = cmcf->listen.elts; diff --git a/src/stream/ngx_stream_proxy_module.c b/src/stream/ngx_stream_proxy_module.c index 01cda7a..934e7d8 100644 --- a/src/stream/ngx_stream_proxy_module.c +++ b/src/stream/ngx_stream_proxy_module.c @@ -31,6 +31,7 @@ typedef struct { ngx_uint_t next_upstream_tries; ngx_flag_t next_upstream; ngx_flag_t proxy_protocol; + ngx_flag_t half_close; ngx_stream_upstream_local_t *local; ngx_flag_t socket_keepalive; @@ -46,8 +47,8 @@ typedef struct { ngx_uint_t ssl_verify_depth; ngx_str_t ssl_trusted_certificate; ngx_str_t ssl_crl; - ngx_str_t ssl_certificate; - ngx_str_t ssl_certificate_key; + ngx_stream_complex_value_t *ssl_certificate; + ngx_stream_complex_value_t *ssl_certificate_key; ngx_array_t *ssl_passwords; ngx_array_t *ssl_conf_commands; @@ -101,6 +102,7 @@ static void ngx_stream_proxy_ssl_init_connection(ngx_stream_session_t *s); static void ngx_stream_proxy_ssl_handshake(ngx_connection_t *pc); static void ngx_stream_proxy_ssl_save_session(ngx_connection_t *c); static ngx_int_t ngx_stream_proxy_ssl_name(ngx_stream_session_t *s); +static ngx_int_t ngx_stream_proxy_ssl_certificate(ngx_stream_session_t *s); static ngx_int_t ngx_stream_proxy_set_ssl(ngx_conf_t *cf, ngx_stream_proxy_srv_conf_t *pscf); @@ -244,6 +246,13 @@ static ngx_command_t ngx_stream_proxy_commands[] = { offsetof(ngx_stream_proxy_srv_conf_t, proxy_protocol), NULL }, + { ngx_string("proxy_half_close"), + NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_STREAM_SRV_CONF_OFFSET, + offsetof(ngx_stream_proxy_srv_conf_t, half_close), + NULL }, + #if (NGX_STREAM_SSL) { ngx_string("proxy_ssl"), @@ -318,14 +327,14 @@ static ngx_command_t ngx_stream_proxy_commands[] = { { ngx_string("proxy_ssl_certificate"), NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_stream_set_complex_value_zero_slot, NGX_STREAM_SRV_CONF_OFFSET, offsetof(ngx_stream_proxy_srv_conf_t, ssl_certificate), NULL }, { ngx_string("proxy_ssl_certificate_key"), NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_stream_set_complex_value_zero_slot, NGX_STREAM_SRV_CONF_OFFSET, offsetof(ngx_stream_proxy_srv_conf_t, ssl_certificate_key), NULL }, @@ -1060,6 +1069,15 @@ ngx_stream_proxy_ssl_init_connection(ngx_stream_session_t *s) } } + if (pscf->ssl_certificate && (pscf->ssl_certificate->lengths + || pscf->ssl_certificate_key->lengths)) + { + if (ngx_stream_proxy_ssl_certificate(s) != NGX_OK) { + ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR); + return; + } + } + if (pscf->ssl_session_reuse) { pc->ssl->save_session = ngx_stream_proxy_ssl_save_session; @@ -1247,6 +1265,50 @@ done: return NGX_OK; } + +static ngx_int_t +ngx_stream_proxy_ssl_certificate(ngx_stream_session_t *s) +{ + ngx_str_t cert, key; + ngx_connection_t *c; + ngx_stream_proxy_srv_conf_t *pscf; + + c = s->upstream->peer.connection; + + pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module); + + if (ngx_stream_complex_value(s, pscf->ssl_certificate, &cert) + != NGX_OK) + { + return NGX_ERROR; + } + + ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0, + "stream upstream ssl cert: \"%s\"", cert.data); + + if (*cert.data == '\0') { + return NGX_OK; + } + + if (ngx_stream_complex_value(s, pscf->ssl_certificate_key, &key) + != NGX_OK) + { + return NGX_ERROR; + } + + ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0, + "stream upstream ssl key: \"%s\"", key.data); + + if (ngx_ssl_connection_certificate(c, c->pool, &cert, &key, + pscf->ssl_passwords) + != NGX_OK) + { + return NGX_ERROR; + } + + return NGX_OK; +} + #endif @@ -1701,6 +1763,24 @@ ngx_stream_proxy_process(ngx_stream_session_t *s, ngx_uint_t from_upstream, } if (dst) { + + if (dst->type == SOCK_STREAM && pscf->half_close + && src->read->eof && !u->half_closed && !dst->buffered) + { + if (ngx_shutdown_socket(dst->fd, NGX_WRITE_SHUTDOWN) == -1) { + ngx_connection_error(c, ngx_socket_errno, + ngx_shutdown_socket_n " failed"); + + ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR); + return; + } + + u->half_closed = 1; + ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0, + "stream proxy %s socket shutdown", + from_upstream ? "client" : "upstream"); + } + if (ngx_handle_write_event(dst->write, 0) != NGX_OK) { ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return; @@ -1779,6 +1859,13 @@ ngx_stream_proxy_test_finalize(ngx_stream_session_t *s, return NGX_DECLINED; } + if (pscf->half_close) { + /* avoid closing live connections until both read ends get EOF */ + if (!(c->read->eof && pc->read->eof && !c->buffered && !pc->buffered)) { + return NGX_DECLINED; + } + } + handler = c->log->handler; c->log->handler = NULL; @@ -1977,14 +2064,9 @@ ngx_stream_proxy_create_srv_conf(ngx_conf_t *cf) * * conf->ssl_protocols = 0; * conf->ssl_ciphers = { 0, NULL }; - * conf->ssl_name = NULL; * conf->ssl_trusted_certificate = { 0, NULL }; * conf->ssl_crl = { 0, NULL }; - * conf->ssl_certificate = { 0, NULL }; - * conf->ssl_certificate_key = { 0, NULL }; * - * conf->upload_rate = NULL; - * conf->download_rate = NULL; * conf->ssl = NULL; * conf->upstream = NULL; * conf->upstream_value = NULL; @@ -1994,6 +2076,8 @@ ngx_stream_proxy_create_srv_conf(ngx_conf_t *cf) conf->timeout = NGX_CONF_UNSET_MSEC; conf->next_upstream_timeout = NGX_CONF_UNSET_MSEC; conf->buffer_size = NGX_CONF_UNSET_SIZE; + conf->upload_rate = NGX_CONF_UNSET_PTR; + conf->download_rate = NGX_CONF_UNSET_PTR; conf->requests = NGX_CONF_UNSET_UINT; conf->responses = NGX_CONF_UNSET_UINT; conf->next_upstream_tries = NGX_CONF_UNSET_UINT; @@ -2001,13 +2085,17 @@ ngx_stream_proxy_create_srv_conf(ngx_conf_t *cf) conf->proxy_protocol = NGX_CONF_UNSET; conf->local = NGX_CONF_UNSET_PTR; conf->socket_keepalive = NGX_CONF_UNSET; + conf->half_close = NGX_CONF_UNSET; #if (NGX_STREAM_SSL) conf->ssl_enable = NGX_CONF_UNSET; conf->ssl_session_reuse = NGX_CONF_UNSET; + conf->ssl_name = NGX_CONF_UNSET_PTR; conf->ssl_server_name = NGX_CONF_UNSET; conf->ssl_verify = NGX_CONF_UNSET; conf->ssl_verify_depth = NGX_CONF_UNSET_UINT; + conf->ssl_certificate = NGX_CONF_UNSET_PTR; + conf->ssl_certificate_key = NGX_CONF_UNSET_PTR; conf->ssl_passwords = NGX_CONF_UNSET_PTR; conf->ssl_conf_commands = NGX_CONF_UNSET_PTR; #endif @@ -2034,13 +2122,9 @@ ngx_stream_proxy_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size, 16384); - if (conf->upload_rate == NULL) { - conf->upload_rate = prev->upload_rate; - } + ngx_conf_merge_ptr_value(conf->upload_rate, prev->upload_rate, NULL); - if (conf->download_rate == NULL) { - conf->download_rate = prev->download_rate; - } + ngx_conf_merge_ptr_value(conf->download_rate, prev->download_rate, NULL); ngx_conf_merge_uint_value(conf->requests, prev->requests, 0); @@ -2060,6 +2144,8 @@ ngx_stream_proxy_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_value(conf->socket_keepalive, prev->socket_keepalive, 0); + ngx_conf_merge_value(conf->half_close, prev->half_close, 0); + #if (NGX_STREAM_SSL) ngx_conf_merge_value(conf->ssl_enable, prev->ssl_enable, 0); @@ -2073,9 +2159,7 @@ ngx_stream_proxy_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers, "DEFAULT"); - if (conf->ssl_name == NULL) { - conf->ssl_name = prev->ssl_name; - } + ngx_conf_merge_ptr_value(conf->ssl_name, prev->ssl_name, NULL); ngx_conf_merge_value(conf->ssl_server_name, prev->ssl_server_name, 0); @@ -2089,11 +2173,11 @@ ngx_stream_proxy_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_str_value(conf->ssl_crl, prev->ssl_crl, ""); - ngx_conf_merge_str_value(conf->ssl_certificate, - prev->ssl_certificate, ""); + ngx_conf_merge_ptr_value(conf->ssl_certificate, + prev->ssl_certificate, NULL); - ngx_conf_merge_str_value(conf->ssl_certificate_key, - prev->ssl_certificate_key, ""); + ngx_conf_merge_ptr_value(conf->ssl_certificate_key, + prev->ssl_certificate_key, NULL); ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL); @@ -2137,27 +2221,41 @@ ngx_stream_proxy_set_ssl(ngx_conf_t *cf, ngx_stream_proxy_srv_conf_t *pscf) cln->handler = ngx_ssl_cleanup_ctx; cln->data = pscf->ssl; - if (pscf->ssl_certificate.len) { - - if (pscf->ssl_certificate_key.len == 0) { - ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "no \"proxy_ssl_certificate_key\" is defined " - "for certificate \"%V\"", &pscf->ssl_certificate); - return NGX_ERROR; - } - - if (ngx_ssl_certificate(cf, pscf->ssl, &pscf->ssl_certificate, - &pscf->ssl_certificate_key, pscf->ssl_passwords) - != NGX_OK) - { - return NGX_ERROR; - } - } - if (ngx_ssl_ciphers(cf, pscf->ssl, &pscf->ssl_ciphers, 0) != NGX_OK) { return NGX_ERROR; } + if (pscf->ssl_certificate) { + + if (pscf->ssl_certificate_key == NULL) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "no \"proxy_ssl_certificate_key\" is defined " + "for certificate \"%V\"", + &pscf->ssl_certificate->value); + return NGX_ERROR; + } + + if (pscf->ssl_certificate->lengths + || pscf->ssl_certificate_key->lengths) + { + pscf->ssl_passwords = + ngx_ssl_preserve_passwords(cf, pscf->ssl_passwords); + if (pscf->ssl_passwords == NULL) { + return NGX_ERROR; + } + + } else { + if (ngx_ssl_certificate(cf, pscf->ssl, + &pscf->ssl_certificate->value, + &pscf->ssl_certificate_key->value, + pscf->ssl_passwords) + != NGX_OK) + { + return NGX_ERROR; + } + } + } + if (pscf->ssl_verify) { if (pscf->ssl_trusted_certificate.len == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, diff --git a/src/stream/ngx_stream_script.c b/src/stream/ngx_stream_script.c index a15f772..c447e15 100644 --- a/src/stream/ngx_stream_script.c +++ b/src/stream/ngx_stream_script.c @@ -252,7 +252,7 @@ ngx_stream_set_complex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd, cv = (ngx_stream_complex_value_t **) (p + cmd->offset); - if (*cv != NULL) { + if (*cv != NGX_CONF_UNSET_PTR && *cv != NULL) { return "is duplicate"; } @@ -277,6 +277,44 @@ ngx_stream_set_complex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd, } +char * +ngx_stream_set_complex_value_zero_slot(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) +{ + char *p = conf; + + ngx_str_t *value; + ngx_stream_complex_value_t **cv; + ngx_stream_compile_complex_value_t ccv; + + cv = (ngx_stream_complex_value_t **) (p + cmd->offset); + + if (*cv != NGX_CONF_UNSET_PTR) { + return "is duplicate"; + } + + *cv = ngx_palloc(cf->pool, sizeof(ngx_stream_complex_value_t)); + if (*cv == NULL) { + return NGX_CONF_ERROR; + } + + value = cf->args->elts; + + ngx_memzero(&ccv, sizeof(ngx_stream_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[1]; + ccv.complex_value = *cv; + ccv.zero = 1; + + if (ngx_stream_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; +} + + char * ngx_stream_set_complex_value_size_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) diff --git a/src/stream/ngx_stream_script.h b/src/stream/ngx_stream_script.h index a481ca3..d8f3740 100644 --- a/src/stream/ngx_stream_script.h +++ b/src/stream/ngx_stream_script.h @@ -112,6 +112,8 @@ ngx_int_t ngx_stream_compile_complex_value( ngx_stream_compile_complex_value_t *ccv); char *ngx_stream_set_complex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +char *ngx_stream_set_complex_value_zero_slot(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); char *ngx_stream_set_complex_value_size_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); diff --git a/src/stream/ngx_stream_ssl_module.c b/src/stream/ngx_stream_ssl_module.c index d8c0471..c530832 100644 --- a/src/stream/ngx_stream_ssl_module.c +++ b/src/stream/ngx_stream_ssl_module.c @@ -23,7 +23,13 @@ static ngx_int_t ngx_stream_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c); static void ngx_stream_ssl_handshake_handler(ngx_connection_t *c); #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME -int ngx_stream_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg); +static int ngx_stream_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, + void *arg); +#endif +#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation +static int ngx_stream_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, + const unsigned char **out, unsigned char *outlen, + const unsigned char *in, unsigned int inlen, void *arg); #endif #ifdef SSL_R_CERT_CB_ERROR static int ngx_stream_ssl_certificate(ngx_ssl_conn_t *ssl_conn, void *arg); @@ -45,6 +51,8 @@ static char *ngx_stream_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_stream_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +static char *ngx_stream_ssl_alpn(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); static char *ngx_stream_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data); @@ -211,6 +219,13 @@ static ngx_command_t ngx_stream_ssl_commands[] = { offsetof(ngx_stream_ssl_conf_t, conf_commands), &ngx_stream_ssl_conf_command_post }, + { ngx_string("ssl_alpn"), + NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_1MORE, + ngx_stream_ssl_alpn, + NGX_STREAM_SRV_CONF_OFFSET, + 0, + NULL }, + ngx_null_command }; @@ -254,6 +269,9 @@ static ngx_stream_variable_t ngx_stream_ssl_vars[] = { { ngx_string("ssl_ciphers"), NULL, ngx_stream_ssl_variable, (uintptr_t) ngx_ssl_get_ciphers, NGX_STREAM_VAR_CHANGEABLE, 0 }, + { ngx_string("ssl_curve"), NULL, ngx_stream_ssl_variable, + (uintptr_t) ngx_ssl_get_curve, 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 }, @@ -266,6 +284,9 @@ static ngx_stream_variable_t ngx_stream_ssl_vars[] = { { ngx_string("ssl_server_name"), NULL, ngx_stream_ssl_variable, (uintptr_t) ngx_ssl_get_server_name, NGX_STREAM_VAR_CHANGEABLE, 0 }, + { ngx_string("ssl_alpn_protocol"), NULL, ngx_stream_ssl_variable, + (uintptr_t) ngx_ssl_get_alpn_protocol, NGX_STREAM_VAR_CHANGEABLE, 0 }, + { ngx_string("ssl_client_cert"), NULL, ngx_stream_ssl_variable, (uintptr_t) ngx_ssl_get_certificate, NGX_STREAM_VAR_CHANGEABLE, 0 }, @@ -434,7 +455,7 @@ ngx_stream_ssl_handshake_handler(ngx_connection_t *c) #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME -int +static int ngx_stream_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg) { return SSL_TLSEXT_ERR_OK; @@ -443,9 +464,49 @@ ngx_stream_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg) #endif +#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation + +static int +ngx_stream_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out, + unsigned char *outlen, const unsigned char *in, unsigned int inlen, + void *arg) +{ + ngx_str_t *alpn; +#if (NGX_DEBUG) + unsigned int i; + ngx_connection_t *c; + + c = ngx_ssl_get_connection(ssl_conn); + + for (i = 0; i < inlen; i += in[i] + 1) { + ngx_log_debug2(NGX_LOG_DEBUG_STREAM, c->log, 0, + "SSL ALPN supported by client: %*s", + (size_t) in[i], &in[i + 1]); + } + +#endif + + alpn = arg; + + if (SSL_select_next_proto((unsigned char **) out, outlen, alpn->data, + alpn->len, in, inlen) + != OPENSSL_NPN_NEGOTIATED) + { + return SSL_TLSEXT_ERR_ALERT_FATAL; + } + + ngx_log_debug2(NGX_LOG_DEBUG_STREAM, c->log, 0, + "SSL ALPN selected: %*s", (size_t) *outlen, *out); + + return SSL_TLSEXT_ERR_OK; +} + +#endif + + #ifdef SSL_R_CERT_CB_ERROR -int +static int ngx_stream_ssl_certificate(ngx_ssl_conn_t *ssl_conn, void *arg) { ngx_str_t cert, key; @@ -602,6 +663,7 @@ ngx_stream_ssl_create_conf(ngx_conf_t *cf) * scf->client_certificate = { 0, NULL }; * scf->trusted_certificate = { 0, NULL }; * scf->crl = { 0, NULL }; + * scf->alpn = { 0, NULL }; * scf->ciphers = { 0, NULL }; * scf->shm_zone = NULL; */ @@ -660,6 +722,7 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_str_value(conf->trusted_certificate, prev->trusted_certificate, ""); ngx_conf_merge_str_value(conf->crl, prev->crl, ""); + ngx_conf_merge_str_value(conf->alpn, prev->alpn, ""); ngx_conf_merge_str_value(conf->ecdh_curve, prev->ecdh_curve, NGX_DEFAULT_ECDH_CURVE); @@ -720,6 +783,20 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) ngx_stream_ssl_servername); #endif +#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation + if (conf->alpn.len) { + SSL_CTX_set_alpn_select_cb(conf->ssl.ctx, ngx_stream_ssl_alpn_select, + &conf->alpn); + } +#endif + + if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers, + conf->prefer_server_ciphers) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + if (ngx_stream_ssl_compile_certificates(cf, conf) != NGX_OK) { return NGX_CONF_ERROR; } @@ -752,13 +829,6 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) } } - if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers, - conf->prefer_server_ciphers) - != NGX_OK) - { - return NGX_CONF_ERROR; - } - if (conf->verify) { if (conf->client_certificate.len == 0 && conf->verify != 3) { @@ -1056,6 +1126,60 @@ invalid: } +static char * +ngx_stream_ssl_alpn(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ +#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation + + ngx_stream_ssl_conf_t *scf = conf; + + u_char *p; + size_t len; + ngx_str_t *value; + ngx_uint_t i; + + if (scf->alpn.len) { + return "is duplicate"; + } + + value = cf->args->elts; + + len = 0; + + for (i = 1; i < cf->args->nelts; i++) { + + if (value[i].len > 255) { + return "protocol too long"; + } + + len += value[i].len + 1; + } + + scf->alpn.data = ngx_pnalloc(cf->pool, len); + if (scf->alpn.data == NULL) { + return NGX_CONF_ERROR; + } + + p = scf->alpn.data; + + for (i = 1; i < cf->args->nelts; i++) { + *p++ = value[i].len; + p = ngx_cpymem(p, value[i].data, value[i].len); + } + + scf->alpn.len = len; + + return NGX_CONF_OK; + +#else + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "the \"ssl_alpn\" directive requires OpenSSL " + "with ALPN support"); + return NGX_CONF_ERROR; +#endif +} + + static char * ngx_stream_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data) { diff --git a/src/stream/ngx_stream_ssl_module.h b/src/stream/ngx_stream_ssl_module.h index c6e24be..e7c825e 100644 --- a/src/stream/ngx_stream_ssl_module.h +++ b/src/stream/ngx_stream_ssl_module.h @@ -42,6 +42,7 @@ typedef struct { ngx_str_t client_certificate; ngx_str_t trusted_certificate; ngx_str_t crl; + ngx_str_t alpn; ngx_str_t ciphers; diff --git a/src/stream/ngx_stream_upstream.h b/src/stream/ngx_stream_upstream.h index 9857e0b..f561779 100644 --- a/src/stream/ngx_stream_upstream.h +++ b/src/stream/ngx_stream_upstream.h @@ -142,6 +142,7 @@ typedef struct { ngx_stream_upstream_state_t *state; unsigned connected:1; unsigned proxy_protocol:1; + unsigned half_closed:1; } ngx_stream_upstream_t; From 24d9bd02907266424ef4a74ad7de298be7723631 Mon Sep 17 00:00:00 2001 From: Thomas Ward Date: Tue, 24 May 2022 14:20:28 -0400 Subject: [PATCH 383/600] Update changelog --- debian/changelog | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/debian/changelog b/debian/changelog index 3b9b5b7..98db79b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,7 +1,9 @@ -nginx (1.20.2-3) UNRELEASED; urgency=medium +nginx (1.22.0-1) UNRELEASED; urgency=medium - * d/conf/mime.types: Fix a typo in font/woff2 extension in - mime.types. (Closes: #1010798) + * New upstream release (1.22.0) + * Additional changes: + * d/conf/mime.types: Fix a typo in font/woff2 extension in + mime.types. (Closes: #1010798) -- Thomas Ward Tue, 10 May 2022 12:08:02 -0400 From 5900bc832a071308bdd1b10ae01796389fbf4e7b Mon Sep 17 00:00:00 2001 From: Thomas Ward Date: Tue, 24 May 2022 14:24:29 -0400 Subject: [PATCH 384/600] Changelog update --- debian/changelog | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/debian/changelog b/debian/changelog index 98db79b..04b3aa1 100644 --- a/debian/changelog +++ b/debian/changelog @@ -4,6 +4,11 @@ nginx (1.22.0-1) UNRELEASED; urgency=medium * Additional changes: * d/conf/mime.types: Fix a typo in font/woff2 extension in mime.types. (Closes: #1010798) + * d/upstream/signing-key.asc: Additional signing keys observed + in upstream (Konstantin Pavlov ) during + upstream merge/import by Thomas Ward, additional signing key + was added to the keyring while keeping Maxim's key in signing + keys as wel. -- Thomas Ward Tue, 10 May 2022 12:08:02 -0400 From c394d8d99931a56d9a37543e2673caf7b321e8ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Moj=C5=BE=C3=AD=C5=A1?= Date: Wed, 25 May 2022 07:01:01 +0200 Subject: [PATCH 385/600] d/p/CVE-2021-3618.patch removed, fix is included in new upstream release --- debian/changelog | 5 ++ debian/patches/CVE-2021-3618.patch | 84 ------------------------------ debian/patches/series | 1 - 3 files changed, 5 insertions(+), 85 deletions(-) delete mode 100644 debian/patches/CVE-2021-3618.patch diff --git a/debian/changelog b/debian/changelog index 04b3aa1..16e6b2d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,5 +1,6 @@ nginx (1.22.0-1) UNRELEASED; urgency=medium + [ Thomas Ward ] * New upstream release (1.22.0) * Additional changes: * d/conf/mime.types: Fix a typo in font/woff2 extension in @@ -10,6 +11,10 @@ nginx (1.22.0-1) UNRELEASED; urgency=medium was added to the keyring while keeping Maxim's key in signing keys as wel. + [ Jan Mojžíš ] + * d/patches/CVE-2021-3618.patch removed, fix is included in new upstream + release + -- Thomas Ward Tue, 10 May 2022 12:08:02 -0400 nginx (1.20.2-2) unstable; urgency=medium diff --git a/debian/patches/CVE-2021-3618.patch b/debian/patches/CVE-2021-3618.patch deleted file mode 100644 index 10f37a9..0000000 --- a/debian/patches/CVE-2021-3618.patch +++ /dev/null @@ -1,84 +0,0 @@ -Subject: Patch mitigation for CVE-2021-3618 - Mail: max_errors directive. - . - Similarly to smtpd_hard_error_limit in Postfix and smtp_max_unknown_commands - in Exim, specifies the number of errors after which the connection is closed. -Origin: upstream, http://hg.nginx.org/nginx/rev/ec1071830799 -Bug-Debian: https://bugs.debian.org/991328 - ---- a/src/mail/ngx_mail.h -+++ b/src/mail/ngx_mail.h -@@ -115,6 +115,8 @@ - ngx_msec_t timeout; - ngx_msec_t resolver_timeout; - -+ ngx_uint_t max_errors; -+ - ngx_str_t server_name; - - u_char *file_name; -@@ -231,6 +233,7 @@ - ngx_uint_t command; - ngx_array_t args; - -+ ngx_uint_t errors; - ngx_uint_t login_attempt; - - /* used to parse POP3/IMAP/SMTP command */ ---- a/src/mail/ngx_mail_core_module.c -+++ b/src/mail/ngx_mail_core_module.c -@@ -85,6 +85,13 @@ - offsetof(ngx_mail_core_srv_conf_t, resolver_timeout), - NULL }, - -+ { ngx_string("max_errors"), -+ NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, -+ ngx_conf_set_num_slot, -+ NGX_MAIL_SRV_CONF_OFFSET, -+ offsetof(ngx_mail_core_srv_conf_t, max_errors), -+ NULL }, -+ - ngx_null_command - }; - -@@ -163,6 +170,8 @@ - cscf->timeout = NGX_CONF_UNSET_MSEC; - cscf->resolver_timeout = NGX_CONF_UNSET_MSEC; - -+ cscf->max_errors = NGX_CONF_UNSET_UINT; -+ - cscf->resolver = NGX_CONF_UNSET_PTR; - - cscf->file_name = cf->conf_file->file.name.data; -@@ -182,6 +191,7 @@ - ngx_conf_merge_msec_value(conf->resolver_timeout, prev->resolver_timeout, - 30000); - -+ ngx_conf_merge_uint_value(conf->max_errors, prev->max_errors, 5); - - ngx_conf_merge_str_value(conf->server_name, prev->server_name, ""); - ---- a/src/mail/ngx_mail_handler.c -+++ b/src/mail/ngx_mail_handler.c -@@ -871,7 +871,20 @@ - return NGX_MAIL_PARSE_INVALID_COMMAND; - } - -- if (rc == NGX_IMAP_NEXT || rc == NGX_MAIL_PARSE_INVALID_COMMAND) { -+ if (rc == NGX_MAIL_PARSE_INVALID_COMMAND) { -+ -+ s->errors++; -+ -+ if (s->errors >= cscf->max_errors) { -+ ngx_log_error(NGX_LOG_INFO, c->log, 0, -+ "client sent too many invalid commands"); -+ s->quit = 1; -+ } -+ -+ return rc; -+ } -+ -+ if (rc == NGX_IMAP_NEXT) { - return rc; - } - diff --git a/debian/patches/series b/debian/patches/series index 4e43575..5b6b799 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -1,3 +1,2 @@ 0002-Make-sure-signature-stays-the-same-in-all-nginx-buil.patch 0003-define_gnu_source-on-other-glibc-based-platforms.patch -CVE-2021-3618.patch From 7224e5e7ca7a1a8bd6f692082b176830ae3657bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Moj=C5=BE=C3=AD=C5=A1?= Date: Wed, 25 May 2022 11:04:30 +0200 Subject: [PATCH 386/600] d/control: removed ppc64el from list of luajit platforms. --- debian/changelog | 1 + debian/control | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index 16e6b2d..eb42d36 100644 --- a/debian/changelog +++ b/debian/changelog @@ -14,6 +14,7 @@ nginx (1.22.0-1) UNRELEASED; urgency=medium [ Jan Mojžíš ] * d/patches/CVE-2021-3618.patch removed, fix is included in new upstream release + * d/control: removed ppc64el from list of luajit platforms. (Closes: #1011303) -- Thomas Ward Tue, 10 May 2022 12:08:02 -0400 diff --git a/debian/control b/debian/control index cc32589..3a2b586 100644 --- a/debian/control +++ b/debian/control @@ -12,8 +12,8 @@ Build-Depends: debhelper-compat (= 13), libgd-dev, libgeoip-dev, libhiredis-dev, - liblua5.1-0-dev [!i386 !amd64 !kfreebsd-i386 !kfreebsd-amd64 !armel !armhf !powerpc !powerpcspe !mips !mipsel !mips64el !arm64 !ppc64 !ppc64el], - libluajit-5.1-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64 armel armhf powerpc powerpcspe mips mipsel mips64el arm64 ppc64 ppc64el], + liblua5.1-0-dev [!i386 !amd64 !kfreebsd-i386 !kfreebsd-amd64 !armel !armhf !powerpc !powerpcspe !mips !mipsel !mips64el !arm64 !ppc64], + libluajit-5.1-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64 armel armhf powerpc powerpcspe mips mipsel mips64el arm64 ppc64], libmaxminddb-dev, libmhash-dev, libpam0g-dev, From a013b18ff66b9ac1d899827ed5725589f9900701 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Moj=C5=BE=C3=AD=C5=A1?= Date: Wed, 25 May 2022 11:19:06 +0200 Subject: [PATCH 387/600] d/changelog fix whitespaces --- debian/changelog | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/debian/changelog b/debian/changelog index eb42d36..713a937 100644 --- a/debian/changelog +++ b/debian/changelog @@ -3,7 +3,7 @@ nginx (1.22.0-1) UNRELEASED; urgency=medium [ Thomas Ward ] * New upstream release (1.22.0) * Additional changes: - * d/conf/mime.types: Fix a typo in font/woff2 extension in + * d/conf/mime.types: Fix a typo in font/woff2 extension in mime.types. (Closes: #1010798) * d/upstream/signing-key.asc: Additional signing keys observed in upstream (Konstantin Pavlov ) during @@ -21,7 +21,7 @@ nginx (1.22.0-1) UNRELEASED; urgency=medium nginx (1.20.2-2) unstable; urgency=medium [ Thomas Ward ] - * d/patches/CVE-2021-3618.patch: Include upstream changeset from NGINX + * d/patches/CVE-2021-3618.patch: Include upstream changeset from NGINX that adds mitigations into the Mail module for CVE-2021-3618.patch. (Closes: #991328) @@ -46,7 +46,7 @@ nginx (1.20.2-1) unstable; urgency=medium * d/conf/mime.types: Update mime.types to more match upstream mime.types and include upstream changes with mime.types from 1.21.x via nginx.org mercurial repository versions. - * d/control: Remove self from Uploaders per other Debian devs, who want + * d/control: Remove self from Uploaders per other Debian devs, who want that commit to be done by someone on the current uploaders/maintainers group instead. @@ -65,7 +65,7 @@ nginx (1.18.0-9) unstable; urgency=medium * d/watch: Update watch syntax to match all even versions of NGINX releases rather than use a watch syntax that is static to one specific version. This will fix the untracked "New upstream stable versions" problem. - * d/control: Update 'uploaders' as Thomas Ward is now a maintainer in + * d/control: Update 'uploaders' as Thomas Ward is now a maintainer in the Salsa repository. -- Jan Mojžíš Tue, 05 Apr 2022 19:11:47 +0200 From 5eec971e2717232ed1d8a88ce193edccb495e582 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Moj=C5=BE=C3=AD=C5=A1?= Date: Wed, 25 May 2022 17:13:14 +0200 Subject: [PATCH 388/600] d/copyright: - bump nginx copyright years - added copyright for src/stream/ngx_stream_set_module.c --- debian/changelog | 2 ++ debian/copyright | 9 +++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index 713a937..53399e7 100644 --- a/debian/changelog +++ b/debian/changelog @@ -15,6 +15,8 @@ nginx (1.22.0-1) UNRELEASED; urgency=medium * d/patches/CVE-2021-3618.patch removed, fix is included in new upstream release * d/control: removed ppc64el from list of luajit platforms. (Closes: #1011303) + * d/copyright: bump nginx copyright years + * d/copyright: added copyright for src/stream/ngx_stream_set_module.c -- Thomas Ward Tue, 10 May 2022 12:08:02 -0400 diff --git a/debian/copyright b/debian/copyright index f82fc2d..a3f59eb 100644 --- a/debian/copyright +++ b/debian/copyright @@ -3,8 +3,8 @@ Upstream-Name: nginx Source: https://nginx.org/en/download.html Files: * -Copyright: 2002-2019, Igor Sysoev - 2011-2019, Nginx, Inc. +Copyright: 2002-2021, Igor Sysoev + 2011-2022, Nginx, Inc. Maxim Dounin Valentin V. Bartenev Roman Arutyunyan @@ -15,6 +15,11 @@ Files: src/core/ngx_murmurhash.c Copyright: Copyright (C) Austin Appleby License: BSD-2-clause +Files: src/stream/ngx_stream_set_module.c +Copyright: Copyright (C) Pavel Pautov + Copyright (C) Nginx, Inc. +License: BSD-2-clause + Files: src/http/modules/ngx_http_scgi_module.c src/http/modules/ngx_http_uwsgi_module.c Copyright: 2009-2010, Unbit S.a.s. From c3f9fc730b23255d7b2fce09b34a98583f9dcfc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Moj=C5=BE=C3=AD=C5=A1?= Date: Wed, 25 May 2022 17:45:49 +0200 Subject: [PATCH 389/600] d/copyright: removed copyright for src/http/v2/ngx_http_v2_huff_encode.c --- debian/changelog | 1 + debian/copyright | 6 ------ 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/debian/changelog b/debian/changelog index 53399e7..1c01d3f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -17,6 +17,7 @@ nginx (1.22.0-1) UNRELEASED; urgency=medium * d/control: removed ppc64el from list of luajit platforms. (Closes: #1011303) * d/copyright: bump nginx copyright years * d/copyright: added copyright for src/stream/ngx_stream_set_module.c + * d/copyright: removed copyright for src/http/v2/ngx_http_v2_huff_encode.c -- Thomas Ward Tue, 10 May 2022 12:08:02 -0400 diff --git a/debian/copyright b/debian/copyright index a3f59eb..d5c191a 100644 --- a/debian/copyright +++ b/debian/copyright @@ -28,12 +28,6 @@ Copyright: 2009-2010, Unbit S.a.s. Nginx, Inc. License: BSD-2-clause -Files: src/http/v2/ngx_http_v2_huff_encode.c -Copyright: 2015, Vlad Krasnov - Nginx, Inc. - Valentin V. Bartenev -License: BSD-2-clause - Files: contrib/geo2nginx.pl Copyright: 2005, Andrei Nigmatulin License: BSD-2-clause From a8ebc4ba0c136b1df2c7bd2effffa467dc821f0d Mon Sep 17 00:00:00 2001 From: Thomas Ward Date: Thu, 26 May 2022 23:15:02 -0400 Subject: [PATCH 390/600] Update d/copyright for murmurhash license being public-domain --- debian/changelog | 5 ++++- debian/copyright | 9 +++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/debian/changelog b/debian/changelog index 1c01d3f..4874df2 100644 --- a/debian/changelog +++ b/debian/changelog @@ -9,7 +9,10 @@ nginx (1.22.0-1) UNRELEASED; urgency=medium in upstream (Konstantin Pavlov ) during upstream merge/import by Thomas Ward, additional signing key was added to the keyring while keeping Maxim's key in signing - keys as wel. + keys as well. + * d/copyright: Updated copyright for src/core/ngx_murmurhash.c + and debian/modules/http-ndk/src/hash/murmurhash2.c to be + public-domain (Closes: #1011936) [ Jan Mojžíš ] * d/patches/CVE-2021-3618.patch removed, fix is included in new upstream diff --git a/debian/copyright b/debian/copyright index d5c191a..59dfc09 100644 --- a/debian/copyright +++ b/debian/copyright @@ -13,7 +13,10 @@ License: BSD-2-clause Files: src/core/ngx_murmurhash.c Copyright: Copyright (C) Austin Appleby -License: BSD-2-clause +License: public-domain + All MurmurHash versions are public domain software, and the author + disclaims all copyright to their code. + Files: src/stream/ngx_stream_set_module.c Copyright: Copyright (C) Pavel Pautov @@ -65,7 +68,9 @@ License: BSD-4-clause Files: debian/modules/http-ndk/src/hash/murmurhash2.c Copyright: Austin Appleby -License: BSD-3-clause +License: public-domain + All MurmurHash versions are public domain software, and the author + disclaims all copyright to their code. Files: debian/modules/http-auth-pam/* Copyright: 2008-2020, Sergio Talens Oliag From 20eb8ab414656c56632795454156ce014532972d Mon Sep 17 00:00:00 2001 From: Thomas Ward Date: Wed, 8 Jun 2022 15:22:49 -0400 Subject: [PATCH 391/600] ppc64el FTBFS fixed in luajit, nginx: no action needed --- debian/changelog | 1 - debian/control | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/debian/changelog b/debian/changelog index 4874df2..3b92437 100644 --- a/debian/changelog +++ b/debian/changelog @@ -17,7 +17,6 @@ nginx (1.22.0-1) UNRELEASED; urgency=medium [ Jan Mojžíš ] * d/patches/CVE-2021-3618.patch removed, fix is included in new upstream release - * d/control: removed ppc64el from list of luajit platforms. (Closes: #1011303) * d/copyright: bump nginx copyright years * d/copyright: added copyright for src/stream/ngx_stream_set_module.c * d/copyright: removed copyright for src/http/v2/ngx_http_v2_huff_encode.c diff --git a/debian/control b/debian/control index 3a2b586..cc32589 100644 --- a/debian/control +++ b/debian/control @@ -12,8 +12,8 @@ Build-Depends: debhelper-compat (= 13), libgd-dev, libgeoip-dev, libhiredis-dev, - liblua5.1-0-dev [!i386 !amd64 !kfreebsd-i386 !kfreebsd-amd64 !armel !armhf !powerpc !powerpcspe !mips !mipsel !mips64el !arm64 !ppc64], - libluajit-5.1-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64 armel armhf powerpc powerpcspe mips mipsel mips64el arm64 ppc64], + liblua5.1-0-dev [!i386 !amd64 !kfreebsd-i386 !kfreebsd-amd64 !armel !armhf !powerpc !powerpcspe !mips !mipsel !mips64el !arm64 !ppc64 !ppc64el], + libluajit-5.1-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64 armel armhf powerpc powerpcspe mips mipsel mips64el arm64 ppc64 ppc64el], libmaxminddb-dev, libmhash-dev, libpam0g-dev, From 4b7212e74500151248dab2f0baf45837e39a266d Mon Sep 17 00:00:00 2001 From: Thomas Ward Date: Wed, 8 Jun 2022 16:15:40 -0400 Subject: [PATCH 392/600] Enable luajit for s390x --- debian/changelog | 5 +++++ debian/control | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index 3b92437..48897b5 100644 --- a/debian/changelog +++ b/debian/changelog @@ -13,6 +13,11 @@ nginx (1.22.0-1) UNRELEASED; urgency=medium * d/copyright: Updated copyright for src/core/ngx_murmurhash.c and debian/modules/http-ndk/src/hash/murmurhash2.c to be public-domain (Closes: #1011936) + * d/control: Use libluajit-5.1-dev for s390x. + Due to src:luajit2 landing in Unstable, superseding src:luajit, + and due to luajit2 having s390x support, we can use s390x now + with luajit instead of standard Lua. + Thanks to Paul Gevers for the heads up on luajit2 supporting s390x. [ Jan Mojžíš ] * d/patches/CVE-2021-3618.patch removed, fix is included in new upstream diff --git a/debian/control b/debian/control index cc32589..bbec75a 100644 --- a/debian/control +++ b/debian/control @@ -12,8 +12,8 @@ Build-Depends: debhelper-compat (= 13), libgd-dev, libgeoip-dev, libhiredis-dev, - liblua5.1-0-dev [!i386 !amd64 !kfreebsd-i386 !kfreebsd-amd64 !armel !armhf !powerpc !powerpcspe !mips !mipsel !mips64el !arm64 !ppc64 !ppc64el], - libluajit-5.1-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64 armel armhf powerpc powerpcspe mips mipsel mips64el arm64 ppc64 ppc64el], + liblua5.1-0-dev [!i386 !amd64 !kfreebsd-i386 !kfreebsd-amd64 !armel !armhf !powerpc !powerpcspe !mips !mipsel !mips64el !arm64 !ppc64 !ppc64el !s390x], + libluajit-5.1-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64 armel armhf powerpc powerpcspe mips mipsel mips64el arm64 ppc64 ppc64el s390x], libmaxminddb-dev, libmhash-dev, libpam0g-dev, From 333875401c6fa18c4f37d39f6ea6411ef1e1b60a Mon Sep 17 00:00:00 2001 From: Thomas Ward Date: Sat, 25 Jun 2022 17:31:16 -0400 Subject: [PATCH 393/600] Return ppc64el to liblua, luajit2 still broken on ppc64el. --- debian/changelog | 2 ++ debian/control | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index 48897b5..fec8e1d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -18,6 +18,8 @@ nginx (1.22.0-1) UNRELEASED; urgency=medium and due to luajit2 having s390x support, we can use s390x now with luajit instead of standard Lua. Thanks to Paul Gevers for the heads up on luajit2 supporting s390x. + * d/control: Use liblua for ppc64el - src:luajit2 is still not ppc64el + stable and there seems to be nobody willing to support it. [ Jan Mojžíš ] * d/patches/CVE-2021-3618.patch removed, fix is included in new upstream diff --git a/debian/control b/debian/control index bbec75a..5ae14c8 100644 --- a/debian/control +++ b/debian/control @@ -12,8 +12,8 @@ Build-Depends: debhelper-compat (= 13), libgd-dev, libgeoip-dev, libhiredis-dev, - liblua5.1-0-dev [!i386 !amd64 !kfreebsd-i386 !kfreebsd-amd64 !armel !armhf !powerpc !powerpcspe !mips !mipsel !mips64el !arm64 !ppc64 !ppc64el !s390x], - libluajit-5.1-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64 armel armhf powerpc powerpcspe mips mipsel mips64el arm64 ppc64 ppc64el s390x], + liblua5.1-0-dev [!i386 !amd64 !kfreebsd-i386 !kfreebsd-amd64 !armel !armhf !powerpc !powerpcspe !mips !mipsel !mips64el !arm64 !ppc64 !s390x], + libluajit-5.1-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64 armel armhf powerpc powerpcspe mips mipsel mips64el arm64 ppc64 s390x], libmaxminddb-dev, libmhash-dev, libpam0g-dev, From d4b9d6a1daf9e64816e6d69d4d10083a032e251c Mon Sep 17 00:00:00 2001 From: Miao Wang Date: Fri, 4 Feb 2022 00:00:41 +0800 Subject: [PATCH 394/600] Adding nginx-dev package for tools for building out-of-tree modules Nginx does not officially provide a mechanism to build out-of-tree modules, however, this can be achieved by using all the headers and the configure scripts in the auto/ directory. As a result, a nginx-dev package can thus be developed for build out-of-tree modules. The detailed steps to build an out-of-tree module in the headers-only nginx source tree is: 1. Execute the configure script of nginx, with the same configure arguments (excluding the reference to other dynamic modules, but including the reference to depending modules as a built-in module). To prevent the configure scripts modifying the nginx ource tree, we can 1. point the build dir to a directory elsewhere, to generate all the build time files outside; 2. slightly patch the configure scripts to prevent generating a makefile directly in the source tree, which simply includes the generated makefile at the build dir. 2. Execute make at the source tree, but providing the generated makefile in the build dir. The command is `make -C /path/to/nginx/source -f /path/to/build_dir/Makefile modules` To make sure the compiled module is compatible with the nginx binary and the nginx binaries with the same upstream version, the key points are: - Module signature: A module signature containing the (upstream) version number and encoding the necessary configuration flags is put in each module as well as the nginx binary itself. When loading a module, nginx will compare the signature on the module with its own. As long as the configure flags, especially those encoded in the signature, and the version of the nginx source used to build the module are the same as thoes used to build the nginx binary, the moudle can pass the signature check. As a result, the module can depend on the exact nginx upstream version, ignoring the debian revison. - ABI compatibility: We should maintain nginx precisely, to prevent making any ABI changes between different debian revisions. - Build check: When building the module, we can perform a simple module loading check via `nginx -t`. This test serves as a "smoking test", to ensure we are actually building loadable modules. Summing all the above up and adding the necessary automation scripts for module packaging, the nginx-dev package can be composed, including the following parts: - The headers and configure scripts: generated and filtered out from the source tree. The scripts are slightly patched to prevent generating a makefile directly in the source tree, as stated above; - The recorded configure options: all the modules built should include these options when configured; - dh_nginx script and its man page: modified from the original dh_nginx script, adding a "--in-nginx-tree" option. When specified, the behavior remains the same as the original version (so the option is added in the rule building the in-package modules). When not specified, the dependency added into misc:Depends will be the exact upstream nginx version, ignoring the debian revision. E.g. nginx-common >= 1.20.2, << 1.20.2.1~ - a debhelper sequence plugin which can be enabled by module packages with `dh --with=nginx`, inserting `dh_nginx` after `dh_install` - a build system plugin which can bu enabled by module packages with `dh --buildsystem=nginx_mod`, automating the module building process using the steps mentioned before. - autoscript templates used by dh_nginx are also installed without modification. Currently. the architecture of nginx-dev is any because nginx has arch related dependencies, which is brought in by http-lua module. After it is removed from the nginx source tree, the architecture can be changed to all since no binary is included in this package. --- debian/control | 13 +++++ debian/debhelper/nginx.pm | 8 +++ debian/debhelper/nginx_mod.pm | 96 +++++++++++++++++++++++++++++++++++ debian/dh_nginx | 18 ++++++- debian/nginx-dev.install | 8 +++ debian/nginx-dev.manpages | 1 + debian/rules | 31 ++++++++--- 7 files changed, 165 insertions(+), 10 deletions(-) create mode 100644 debian/debhelper/nginx.pm create mode 100644 debian/debhelper/nginx_mod.pm create mode 100644 debian/nginx-dev.install create mode 100644 debian/nginx-dev.manpages diff --git a/debian/control b/debian/control index 5ae14c8..9f31ba4 100644 --- a/debian/control +++ b/debian/control @@ -68,6 +68,19 @@ Description: small, powerful, scalable web/proxy server - common files This package contains base configuration files used by all versions of nginx. +Package: nginx-dev +Architecture: any +Depends: ${misc:Depends}, ${S:Build-Depends}, + nginx-core (= ${binary:Version}) | nginx-light (= ${binary:Version}) | nginx-extras (= ${binary:Version}) +Description: nginx web/proxy server - development headers + Nginx ("engine X") is a high-performance web and reverse proxy server + created by Igor Sysoev. It can be used both as a standalone web server + and as a proxy to reduce the load on back-end HTTP or mail servers. + . + This package provides development headers and necessary config scripts + for the nginx web/proxy server, useful to develop and link third party + additions to the Debian nginx web/proxy server packages. + Package: nginx-core Architecture: any Depends: libnginx-mod-http-geoip (= ${binary:Version}), diff --git a/debian/debhelper/nginx.pm b/debian/debhelper/nginx.pm new file mode 100644 index 0000000..0473815 --- /dev/null +++ b/debian/debhelper/nginx.pm @@ -0,0 +1,8 @@ +#!/usr/bin/perl +use warnings; +use strict; +use Debian::Debhelper::Dh_Lib; + +insert_after("dh_install", "dh_nginx"); + +1; diff --git a/debian/debhelper/nginx_mod.pm b/debian/debhelper/nginx_mod.pm new file mode 100644 index 0000000..af37fda --- /dev/null +++ b/debian/debhelper/nginx_mod.pm @@ -0,0 +1,96 @@ +# A build system class for handling nginx modules. +# +# Copyright: © 2022 Miao Wang +# License: MIT + +package Debian::Debhelper::Buildsystem::nginx_mod; + +use strict; +use warnings; +use Debian::Debhelper::Dh_Lib qw(error doit); +use File::Spec; +use parent qw(Debian::Debhelper::Buildsystem::makefile); +use Config; + +sub DESCRIPTION { + "Nginx Module (config)" +} + +sub check_auto_buildable { + my ($this, $step) = @_; + + return 1 if -e $this->get_sourcepath("config"); +} + +sub _NGINX_SRC_DIR { + "/usr/share/nginx/src" +} + +sub new { + my $class=shift; + my $this= $class->SUPER::new(@_); + $this->prefer_out_of_source_building(@_); + return $this; +} + +sub configure { + my $this=shift; + + doit({ + "chdir" => $this->_NGINX_SRC_DIR, + "update_env" => { + "src_dir" => $this->get_sourcedir, + "bld_dir" => $this->get_builddir, + "pwd_dir" => $this->{cwd}, + }, + }, "bash", "-c", '. ./conf_flags + ./configure \\ + --with-cc-opt="$(cd "$pwd_dir/$src_dir"; dpkg-buildflags --get CFLAGS) -fPIC $(cd "$pwd_dir/$src_dir"; dpkg-buildflags --get CPPFLAGS)" \\ + --with-ld-opt="$(cd "$pwd_dir/$src_dir"; dpkg-buildflags --get LDFLAGS) -fPIC" \\ + "${NGX_CONF_FLAGS[@]}" \\ + --add-dynamic-module="$pwd_dir/$src_dir" \\ + --builddir="$pwd_dir/$bld_dir" \\ + "$@"', "dummy", @_); +} + +sub build { + my $this=shift; + + $this->do_make("-f", File::Spec->catfile($this->{cwd}, $this->get_buildpath("Makefile")), "-C", $this->_NGINX_SRC_DIR, "modules"); +} + +sub test { + my $this=shift; + $this->doit_in_builddir("bash", "-e", "-o", "pipefail", "-c", ' + tmp_conf=$(mktemp -p .) + for pre_dep in "$@"; do + echo "load_module modules/$pre_dep;" >> "$tmp_conf" + done + for i in *.so; do + echo "load_module $PWD/$i;" >> "$tmp_conf" + done + echo "events{}" >> "$tmp_conf" + nginx -g "error_log /dev/null; pid /dev/null;" -t -q -c "$PWD/$tmp_conf" + rm -f "$tmp_conf" + ', "dummy", @_); +} + +sub install { + my $this=shift; + my $destdir=shift; + + $this->doit_in_builddir("bash", "-e", "-o", "pipefail", "-c", ' + destdir=$1 + mkdir -p "$destdir/usr/lib/nginx/modules" + for i in *.so; do + cp "$i" "$destdir/usr/lib/nginx/modules/" + done + ', "dummy", $destdir); +} + +sub clean { + my $this=shift; + $this->rmdir_builddir(); +} + +1 diff --git a/debian/dh_nginx b/debian/dh_nginx index 8e6ce3b..4853568 100755 --- a/debian/dh_nginx +++ b/debian/dh_nginx @@ -48,7 +48,7 @@ sub nginx_modules_conf_installdir =head1 SYNOPSIS -B [S>] [B<-n>|B<--noscripts>] +B [S>] [B<-n>|B<--noscripts>] [B<--in-nginx-tree>] =head1 DESCRIPTION @@ -63,6 +63,8 @@ It supports the following configuration types =item * Nginx modules +=back + =head1 INVOCATION %: @@ -128,6 +130,10 @@ configuration by default. Do not modify F/F/F maintainer scripts. +=item B<--in-nginx-tree> + +Specify this option when building in-tree modules along with nginx. When +specified, nginx abi version is not required in package name. =back @@ -150,8 +156,11 @@ dh_nginx is heavily influnced by dh_apache2 written by Arno Toell ## main code starts here ## +my $nginx_in_tree; + init(options => { "e|noenable" => \$dh{NOENABLE}, + "in-nginx-tree" => \$nginx_in_tree, }); foreach my $package ((@{$dh{DOPACKAGES}})) @@ -231,7 +240,12 @@ foreach my $package ((@{$dh{DOPACKAGES}})) { warning("Package $package appears to be an Nginx module. It should comply to the package naming scheme libnginx-mod-\n"); } - addsubstvar($package, "misc:Depends", nginx_depends()); + if ($nginx_in_tree){ + addsubstvar($package, "misc:Depends", nginx_depends()); + } else { + my $ngx_ver = `grep 'define NGINX_VERSION' /usr/share/nginx/src/src/core/nginx.h | sed -e 's/^.*"\\(.*\\)".*/\\1/'`; + addsubstvar($package, "misc:Depends", "nginx-common (>= $ngx_ver), nginx-common (<< $ngx_ver.1~)"); + } my $modules = ""; foreach my $module (@{$PACKAGE_TYPE{'has_a_module'}}) diff --git a/debian/nginx-dev.install b/debian/nginx-dev.install new file mode 100644 index 0000000..6a2ad43 --- /dev/null +++ b/debian/nginx-dev.install @@ -0,0 +1,8 @@ +debian/build-src/auto usr/share/nginx/src/ +debian/build-src/src usr/share/nginx/src/ +debian/build-src/conf_flags usr/share/nginx/src/ +debian/build-src/configure usr/share/nginx/src/ +debian/debhelper/nginx.pm usr/share/perl5/Debian/Debhelper/Sequence/ +debian/dh_nginx usr/bin/ +debian/debhelper/nginx_mod.pm usr/share/perl5/Debian/Debhelper/Buildsystem/ +debian/autoscripts/* usr/share/debhelper/autoscripts/ diff --git a/debian/nginx-dev.manpages b/debian/nginx-dev.manpages new file mode 100644 index 0000000..0ece920 --- /dev/null +++ b/debian/nginx-dev.manpages @@ -0,0 +1 @@ +debian/build-src/dh_nginx.1 diff --git a/debian/rules b/debian/rules index f777843..68ed613 100755 --- a/debian/rules +++ b/debian/rules @@ -32,7 +32,7 @@ DYN_MODS := \ MODULESDIR = $(CURDIR)/debian/modules BASEDIR = $(CURDIR) -$(foreach flavour,$(FLAVOURS),$(eval BUILDDIR_$(flavour) = $(CURDIR)/debian/build-$(flavour))) +$(foreach flavour,$(FLAVOURS) src,$(eval BUILDDIR_$(flavour) = $(CURDIR)/debian/build-$(flavour))) DEB_BUILD_ARCH ?=$(shell dpkg-architecture -qDEB_BUILD_ARCH) ifeq ($(DEB_BUILD_ARCH),sparc) @@ -48,9 +48,7 @@ MODULESPATCHDIR = $(CURDIR)/debian/modules/patches modules_with_patches := $(notdir $(wildcard $(CURDIR)/debian/modules/patches/*)) # configure flags -common_configure_flags := \ - --with-cc-opt="$(debian_cflags)" \ - --with-ld-opt="$(debian_ldflags)" \ +basic_configure_flags := \ --prefix=/usr/share/nginx \ --conf-path=/etc/nginx/nginx.conf \ --http-log-path=/var/log/nginx/access.log \ @@ -75,6 +73,11 @@ common_configure_flags := \ --with-http_slice_module \ --with-threads +common_configure_flags := \ + --with-cc-opt="$(debian_cflags)" \ + --with-ld-opt="$(debian_ldflags)" \ + $(basic_configure_flags) + light_configure_flags := \ $(common_configure_flags) \ --with-http_gzip_static_module \ @@ -132,15 +135,15 @@ extras_configure_flags := \ %: dh $@ --without autoreconf -override_dh_auto_configure: config_patch_modules $(foreach flavour,$(FLAVOURS),config.arch.$(flavour)) -override_dh_auto_build: $(foreach flavour,$(FLAVOURS),build.arch.$(flavour)) +override_dh_auto_configure: config_patch_modules $(foreach flavour,$(FLAVOURS),config.arch.$(flavour)) config.src +override_dh_auto_build: $(foreach flavour,$(FLAVOURS),build.arch.$(flavour)) build.src override_dh_strip: $(foreach flavour,$(FLAVOURS),strip.arch.$(flavour)) $(foreach mod,$(DYN_MODS),strip.mods.$(mod)) -override_dh_clean: clean_patch_modules $(foreach flavour,$(FLAVOURS),clean.$(flavour)) +override_dh_clean: clean_patch_modules $(foreach flavour,$(FLAVOURS),clean.$(flavour)) clean.src dh_clean override_dh_install: dh_install - DH_AUTOSCRIPTDIR=$(CURDIR)/debian/autoscripts debian/dh_nginx + DH_AUTOSCRIPTDIR=$(CURDIR)/debian/autoscripts debian/dh_nginx --in-nginx-tree override_dh_installinit: dh_installinit --no-stop-on-upgrade --no-start --name=nginx @@ -154,6 +157,14 @@ override_dh_installlogrotate: build.arch.%: $(MAKE) -C $(BUILDDIR_$*) build +build.src: + cp -Pa $(CURDIR)/auto $(BUILDDIR_src)/ + sed -i '/^# create Makefile/,/^END$$/d' $(BUILDDIR_src)/auto/make $(BUILDDIR_src)/auto/init $(BUILDDIR_src)/auto/install + find $(CURDIR)/src -type f -name '*.h' -printf 'src/%P\0' | tar -C $(CURDIR) --null --files-from - -c | tar -C $(BUILDDIR_src)/ -x + if [ -e $(CURDIR)/configure ]; then cp $(CURDIR)/configure $(BUILDDIR_src)/; fi + echo "NGX_CONF_FLAGS=(" $(basic_configure_flags) ")" > $(BUILDDIR_src)/conf_flags + pod2man debian/dh_nginx > $(BUILDDIR_src)/dh_nginx.1 + strip.arch.%: dh_strip --package=nginx-$(*) -O--dbgsym-migration='nginx-$(*)-dbg (<< 1.10.1-3~)' @@ -182,6 +193,10 @@ config.arch.%: cp -Pa $(CURDIR)/man $(BUILDDIR_$*)/ cd $(BUILDDIR_$*) && ./configure $($*_configure_flags) +config.src: + dh_testdir + mkdir -p $(BUILDDIR_src) + clean.%: rm -rf $(BUILDDIR_$*) From 87b5e38f6d10b13e7fd567c9e430153c48d7bafc Mon Sep 17 00:00:00 2001 From: Miao Wang Date: Thu, 26 May 2022 15:48:54 +0800 Subject: [PATCH 395/600] nginx-dev: simplify dependencies nginx-dev depends on ${S:Build-Depends} before this commit, to include all the build-depdencies of nginx source packages. However, this also includes build dependency for those in-tree 3rd party modules, which are unnecessary. This commit removes them and explicitly list those packages needed to build a general module. The architecture of nginx-dev can thus be changed to all instead of any. When all 3rd party modules are removed, the dependency can be changed back to ${S:Build-Depends} to make the config less redundant. --- debian/control | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/debian/control b/debian/control index 9f31ba4..f6b11ba 100644 --- a/debian/control +++ b/debian/control @@ -69,9 +69,21 @@ Description: small, powerful, scalable web/proxy server - common files nginx. Package: nginx-dev -Architecture: any -Depends: ${misc:Depends}, ${S:Build-Depends}, - nginx-core (= ${binary:Version}) | nginx-light (= ${binary:Version}) | nginx-extras (= ${binary:Version}) +Architecture: all +Depends: ${misc:Depends}, + debhelper-compat (= 13), + dpkg-dev (>= 1.15.5), + libgd-dev, + libgeoip-dev, + libpcre3-dev, + libperl-dev, + libssl-dev, + libxslt1-dev, + po-debconf, + quilt, + zlib1g-dev, + nginx-core (<< ${source:Version}.1~) | nginx-light (<< ${source:Version}.1~) | nginx-extras (<< ${source:Version}.1~), + nginx-core (>= ${source:Version}) | nginx-light (>= ${source:Version}) | nginx-extras (>= ${source:Version}) Description: nginx web/proxy server - development headers Nginx ("engine X") is a high-performance web and reverse proxy server created by Igor Sysoev. It can be used both as a standalone web server From 2784d3f935d26fab5d485caa6843221f2691686b Mon Sep 17 00:00:00 2001 From: Miao Wang Date: Fri, 27 May 2022 00:09:29 +0800 Subject: [PATCH 396/600] nginx-dev: fix nginx version subtracting in dh_nginx --- debian/dh_nginx | 1 + 1 file changed, 1 insertion(+) diff --git a/debian/dh_nginx b/debian/dh_nginx index 4853568..e07ffe1 100755 --- a/debian/dh_nginx +++ b/debian/dh_nginx @@ -244,6 +244,7 @@ foreach my $package ((@{$dh{DOPACKAGES}})) addsubstvar($package, "misc:Depends", nginx_depends()); } else { my $ngx_ver = `grep 'define NGINX_VERSION' /usr/share/nginx/src/src/core/nginx.h | sed -e 's/^.*"\\(.*\\)".*/\\1/'`; + chomp($ngx_ver); addsubstvar($package, "misc:Depends", "nginx-common (>= $ngx_ver), nginx-common (<< $ngx_ver.1~)"); } From 15c55ec59b0f542e9cecf7205e5e54a0d6beba2e Mon Sep 17 00:00:00 2001 From: Miao Wang Date: Fri, 6 May 2022 18:59:25 +0800 Subject: [PATCH 397/600] dh_nginx: move to debian/debhelper Move dh_nginx script to debian/debhelper so that all debhelper scripts are located together. --- debian/{ => debhelper}/dh_nginx | 0 debian/nginx-dev.install | 2 +- debian/rules | 4 ++-- 3 files changed, 3 insertions(+), 3 deletions(-) rename debian/{ => debhelper}/dh_nginx (100%) diff --git a/debian/dh_nginx b/debian/debhelper/dh_nginx similarity index 100% rename from debian/dh_nginx rename to debian/debhelper/dh_nginx diff --git a/debian/nginx-dev.install b/debian/nginx-dev.install index 6a2ad43..efc1578 100644 --- a/debian/nginx-dev.install +++ b/debian/nginx-dev.install @@ -3,6 +3,6 @@ debian/build-src/src usr/share/nginx/src/ debian/build-src/conf_flags usr/share/nginx/src/ debian/build-src/configure usr/share/nginx/src/ debian/debhelper/nginx.pm usr/share/perl5/Debian/Debhelper/Sequence/ -debian/dh_nginx usr/bin/ +debian/debhelper/dh_nginx usr/bin/ debian/debhelper/nginx_mod.pm usr/share/perl5/Debian/Debhelper/Buildsystem/ debian/autoscripts/* usr/share/debhelper/autoscripts/ diff --git a/debian/rules b/debian/rules index 68ed613..d4ddc7e 100755 --- a/debian/rules +++ b/debian/rules @@ -143,7 +143,7 @@ override_dh_clean: clean_patch_modules $(foreach flavour,$(FLAVOURS),cl override_dh_install: dh_install - DH_AUTOSCRIPTDIR=$(CURDIR)/debian/autoscripts debian/dh_nginx --in-nginx-tree + DH_AUTOSCRIPTDIR=$(CURDIR)/debian/autoscripts debian/debhelper/dh_nginx --in-nginx-tree override_dh_installinit: dh_installinit --no-stop-on-upgrade --no-start --name=nginx @@ -163,7 +163,7 @@ build.src: find $(CURDIR)/src -type f -name '*.h' -printf 'src/%P\0' | tar -C $(CURDIR) --null --files-from - -c | tar -C $(BUILDDIR_src)/ -x if [ -e $(CURDIR)/configure ]; then cp $(CURDIR)/configure $(BUILDDIR_src)/; fi echo "NGX_CONF_FLAGS=(" $(basic_configure_flags) ")" > $(BUILDDIR_src)/conf_flags - pod2man debian/dh_nginx > $(BUILDDIR_src)/dh_nginx.1 + pod2man debian/debhelper/dh_nginx > $(BUILDDIR_src)/dh_nginx.1 strip.arch.%: dh_strip --package=nginx-$(*) -O--dbgsym-migration='nginx-$(*)-dbg (<< 1.10.1-3~)' From 509adba304b06ff3fcb99b0baa8ef689e4bed40d Mon Sep 17 00:00:00 2001 From: Miao Wang Date: Fri, 6 May 2022 19:09:50 +0800 Subject: [PATCH 398/600] dh_nginx: support auto generating module config files This patch adds support of auto generating module config files for modules in the naming pattern of libnginx-mod-* but with missing .nginx file. The module load file and its loading priority is inferred from the package name in this case. Using this feature, the repeated files d/libnginx-mod-*.nginx and d/libnginx-mod.conf/ can be removed, and the packaging for out-of-tree modules can be simplified. --- debian/debhelper/dh_nginx | 122 ++++++++++++++++++++++++-------------- 1 file changed, 79 insertions(+), 43 deletions(-) diff --git a/debian/debhelper/dh_nginx b/debian/debhelper/dh_nginx index e07ffe1..f2b9bb5 100755 --- a/debian/debhelper/dh_nginx +++ b/debian/debhelper/dh_nginx @@ -84,6 +84,11 @@ Lists files to be registered with the Nginx HTTP server. The file is interpreted as line separated list of installation stanzas, where each entry consists of whitespace separated values conforming to the file semantics below. +When this file is missing but the name of the package looks like a nginx module, +the module load file and its loading priority is automatically generated inferring +from the package name. In this case, IB<.install> or other mechanisms +should be used for copying the B<.so> library into the correct place. + =head2 FILE SEMANTICS Each line consists of a triple @@ -171,65 +176,96 @@ foreach my $package ((@{$dh{DOPACKAGES}})) my $file = pkgfile($package, "nginx"); my $tmp = tmpdir($package); + my $installdir = $tmp . "/" . nginx_modules_conf_installdir(); + my $modinstalldir = $tmp . "/" . nginx_api_installdir(); - my @files_to_register = filedoublearray($file, ".") if $file; - foreach my $line (@files_to_register) - { - my $type = lc(shift @{$line}) if $line->[0]; - my $source = shift @{$line} if $line->[0]; - my @arguments = @{$line}; - my $destination; - - $type = "modules" if $type eq "mod"; - my $installdir = $tmp . "/" . nginx_modules_conf_installdir(); - - verbose_print("$type -- $source -- @arguments\n\n"); - - if ($type eq "modules") + if ($file){ + my @files_to_register = filedoublearray($file, ".") if $file; + foreach my $line (@files_to_register) { - my $basesource = basename($source); + my $type = lc(shift @{$line}) if $line->[0]; + my $source = shift @{$line} if $line->[0]; + my @arguments = @{$line}; + my $destination; + + $type = "modules" if $type eq "mod"; + + verbose_print("$type -- $source -- @arguments\n\n"); if ($type eq "modules") { - if ($basesource =~ m/\.conf$/) + my $basesource = basename($source); + + if ($type eq "modules") { - my $enablename = $basesource; - my $prio = $#arguments >= 0 ? $arguments[0] : 50; - $destination = "$prio-$basesource"; - push @{$PACKAGE_TYPE{'has_a_module'}}, "$enablename:$destination"; - verbose_print("Installing module configuration $enablename into $installdir prio:$prio\n"); - } - elsif ($basesource =~ m/\.so$/) - { - my $modinstalldir = $tmp . "/" . nginx_api_installdir(); - verbose_print("Installing module binary $source into $modinstalldir\n"); - if (! -d $modinstalldir) + if ($basesource =~ m/\.conf$/) { - complex_doit("mkdir","-p", $modinstalldir); - complex_doit("chmod","755","$modinstalldir"); + my $enablename = $basesource; + my $prio = $#arguments >= 0 ? $arguments[0] : 50; + $destination = "$prio-$basesource"; + push @{$PACKAGE_TYPE{'has_a_module'}}, "$enablename:$destination"; + verbose_print("Installing module configuration $enablename into $installdir prio:$prio\n"); } - complex_doit("cp", $source, $modinstalldir); - next; + elsif ($basesource =~ m/\.so$/) + { + verbose_print("Installing module binary $source into $modinstalldir\n"); + if (! -d $modinstalldir) + { + complex_doit("mkdir","-p", $modinstalldir); + complex_doit("chmod","755","$modinstalldir"); + } + complex_doit("cp", $source, $modinstalldir); + next; + } + + # TODO + error("module: \"$basesource\" needs .conf, .so or suffix") if $basesource !~ m/\.(conf|so)/; } - # TODO - error("module: \"$basesource\" needs .conf, .so or suffix") if $basesource !~ m/\.(conf|so)/; - } + if (! -d $installdir) + { + complex_doit("mkdir","-p",$installdir); + complex_doit("chmod","755","$installdir"); + } + complex_doit("cp",$source,$installdir); + complex_doit("chmod","644","$installdir/$basesource"); - if (! -d $installdir) + } + else { - complex_doit("mkdir","-p",$installdir); - complex_doit("chmod","755","$installdir"); + error("Unknown parameter: $type\n"); } - complex_doit("cp",$source,$installdir); - complex_doit("chmod","644","$installdir/$basesource"); } - else - { - error("Unknown parameter: $type\n"); - } + } elsif ($package =~ /^libnginx-mod-/){ + verbose_print("$package might be a nginx module\n"); + my $module = $package; + $module =~ s/^libnginx-mod-//; + verbose_print("Guessed module name: $module\n"); + + my $modulepath = $module; + $modulepath =~ s/-/_/g; + + if (-e "$modinstalldir/ngx_${modulepath}_module.so"){ + my $prio = 50; + if ($module =~ /^\w+-/ && !($module =~ /^http-/) ){ + $prio = 70; + } + verbose_print("Guessed load priority: $prio\n"); + + my $conf_name = "mod-$module.conf"; + install_dir($installdir); + verbose_print("Installing module configuration $conf_name into $installdir prio:$prio\n"); + open(MOD_CONF, $dh{NO_ACT} ? ">&STDERR" : ">$installdir/$conf_name") or error("open($installdir/$conf_name): $!"); + print(MOD_CONF "load_module modules/ngx_${modulepath}_module.so;\n"); + close(MOD_CONF); + chmod(0644, "$installdir/$conf_name") or error("chmod(0644, $installdir/$conf_name): $!"); + push @{$PACKAGE_TYPE{'has_a_module'}}, "$conf_name:$prio-$conf_name"; + } else { + verbose_print("$package is not a nginx module because $modinstalldir/ngx_${modulepath}_module.so not found"); + verbose_print("If it is not correct, check if the module is installed before invoking this script"); + } } my @postinst_autoscripts; From ed5bc15213993766af66189792d5a7ed496681e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Moj=C5=BE=C3=AD=C5=A1?= Date: Sun, 15 May 2022 09:12:16 +0200 Subject: [PATCH 399/600] Remove 0002-Make-sure-signature-stays-the-same-in-all-nginx-buil.patch --- ...ure-stays-the-same-in-all-nginx-buil.patch | 28 ------------------- debian/patches/series | 1 - 2 files changed, 29 deletions(-) delete mode 100644 debian/patches/0002-Make-sure-signature-stays-the-same-in-all-nginx-buil.patch diff --git a/debian/patches/0002-Make-sure-signature-stays-the-same-in-all-nginx-buil.patch b/debian/patches/0002-Make-sure-signature-stays-the-same-in-all-nginx-buil.patch deleted file mode 100644 index 9e27e1a..0000000 --- a/debian/patches/0002-Make-sure-signature-stays-the-same-in-all-nginx-buil.patch +++ /dev/null @@ -1,28 +0,0 @@ -From: Christos Trochalakis -Date: Wed, 30 Mar 2016 09:47:11 +0300 -Subject: Make sure signature stays the same in all nginx builds - -NGX_HTTP_HEADERS is part of nginx signature. When a dyn -modules is loaded the signature of the module is compared -to the one of the nginx binary. - -dyn modules are build from nginx-full, so in order to make -them loadable in other flavors we need to make sure all the -binaries share the same signature. ---- - configure | 4 ++++ - 1 file changed, 4 insertions(+) - ---- a/configure -+++ b/configure -@@ -58,6 +58,10 @@ - . auto/unix - fi - -+# Debian -+# Make sure signature stays the same on all nginx flavors -+have=NGX_HTTP_HEADERS . auto/have -+ - . auto/threads - . auto/modules - . auto/lib/conf diff --git a/debian/patches/series b/debian/patches/series index 5b6b799..04030f9 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -1,2 +1 @@ -0002-Make-sure-signature-stays-the-same-in-all-nginx-buil.patch 0003-define_gnu_source-on-other-glibc-based-platforms.patch From 9f1044b9401f8b40ebefa306761ecd9a951750ba Mon Sep 17 00:00:00 2001 From: Miao Wang Date: Sun, 26 Jun 2022 15:26:40 +0800 Subject: [PATCH 400/600] changelog: update changelog --- debian/changelog | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/debian/changelog b/debian/changelog index fec8e1d..581bd2e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -28,6 +28,14 @@ nginx (1.22.0-1) UNRELEASED; urgency=medium * d/copyright: added copyright for src/stream/ngx_stream_set_module.c * d/copyright: removed copyright for src/http/v2/ngx_http_v2_huff_encode.c + [ Miao Wang ] + * dh_nginx: support auto generating module config files + * adding a new nginx-dev package including necessary headers and debhelper + scripts to build and package a 3rd party module. + * d/p/0002-Make-sure-signature-stays-the-same-in-all-nginx-buil.patch + removed, because feature already implemented with --with-compat configure + option since 1.11.5 + -- Thomas Ward Tue, 10 May 2022 12:08:02 -0400 nginx (1.20.2-2) unstable; urgency=medium From 83ca2994f8be7c48e6cfe82236d5268bc3e29f93 Mon Sep 17 00:00:00 2001 From: Thomas Ward Date: Tue, 17 May 2022 15:42:18 -0400 Subject: [PATCH 401/600] Copyright file needed updated (caught by Bage, who emailed a patch to teward) --- debian/changelog | 3 +++ debian/copyright | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/debian/changelog b/debian/changelog index 581bd2e..542e5a6 100644 --- a/debian/changelog +++ b/debian/changelog @@ -28,6 +28,9 @@ nginx (1.22.0-1) UNRELEASED; urgency=medium * d/copyright: added copyright for src/stream/ngx_stream_set_module.c * d/copyright: removed copyright for src/http/v2/ngx_http_v2_huff_encode.c + [ Bastian Germann ] + * d/copyright: Update copyright for d/debhelper/* + [ Miao Wang ] * dh_nginx: support auto generating module config files * adding a new nginx-dev package including necessary headers and debhelper diff --git a/debian/copyright b/debian/copyright index 59dfc09..6449e69 100644 --- a/debian/copyright +++ b/debian/copyright @@ -47,6 +47,10 @@ Copyright: 2007-2009, Fabio Tranchitella 2020-2022, Ondřej Nový License: BSD-2-clause +Files: debian/debhelper/* +Copyright: 2022 Miao Wang +License: Expat + Files: debian/modules/http-headers-more-filter/* Copyright: 2009-2017, Yichun "agentzh" Zhang (章亦春) , CloudFlare Inc. 2010-2013, Bernd Dorn From bf9c433dbbb5d6accb5546a805dacf59e04f5d99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Moj=C5=BE=C3=AD=C5=A1?= Date: Sun, 26 Jun 2022 14:35:33 +0200 Subject: [PATCH 402/600] d/control: bump Standards-Version to 4.6.1, no changes --- debian/changelog | 1 + debian/control | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index 542e5a6..fe5fc20 100644 --- a/debian/changelog +++ b/debian/changelog @@ -27,6 +27,7 @@ nginx (1.22.0-1) UNRELEASED; urgency=medium * d/copyright: bump nginx copyright years * d/copyright: added copyright for src/stream/ngx_stream_set_module.c * d/copyright: removed copyright for src/http/v2/ngx_http_v2_huff_encode.c + * d/control: bump Standards-Version to 4.6.1, no changes [ Bastian Germann ] * d/copyright: Update copyright for d/debhelper/* diff --git a/debian/control b/debian/control index f6b11ba..21eb530 100644 --- a/debian/control +++ b/debian/control @@ -24,7 +24,7 @@ Build-Depends: debhelper-compat (= 13), po-debconf, quilt, zlib1g-dev -Standards-Version: 4.6.0 +Standards-Version: 4.6.1 Homepage: https://nginx.org Vcs-Git: https://salsa.debian.org/nginx-team/nginx.git Vcs-Browser: https://salsa.debian.org/nginx-team/nginx From 7df2636a9d22b2fb385f06af25a61f929b9b4bc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Moj=C5=BE=C3=AD=C5=A1?= Date: Sun, 26 Jun 2022 16:16:08 +0200 Subject: [PATCH 403/600] d/changelog fix whitespace --- debian/changelog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index fe5fc20..68a4ac4 100644 --- a/debian/changelog +++ b/debian/changelog @@ -11,7 +11,7 @@ nginx (1.22.0-1) UNRELEASED; urgency=medium was added to the keyring while keeping Maxim's key in signing keys as well. * d/copyright: Updated copyright for src/core/ngx_murmurhash.c - and debian/modules/http-ndk/src/hash/murmurhash2.c to be + and debian/modules/http-ndk/src/hash/murmurhash2.c to be public-domain (Closes: #1011936) * d/control: Use libluajit-5.1-dev for s390x. Due to src:luajit2 landing in Unstable, superseding src:luajit, From 172eb7b12a8ba0bf4667e54835b5d2024adadc23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Moj=C5=BE=C3=AD=C5=A1?= Date: Sun, 26 Jun 2022 16:16:58 +0200 Subject: [PATCH 404/600] d/changelog close #1013807 bug --- debian/changelog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index 68a4ac4..a12536e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -19,7 +19,7 @@ nginx (1.22.0-1) UNRELEASED; urgency=medium with luajit instead of standard Lua. Thanks to Paul Gevers for the heads up on luajit2 supporting s390x. * d/control: Use liblua for ppc64el - src:luajit2 is still not ppc64el - stable and there seems to be nobody willing to support it. + stable and there seems to be nobody willing to support it. (Closes: 1013807) [ Jan Mojžíš ] * d/patches/CVE-2021-3618.patch removed, fix is included in new upstream From 42508c8556723f6e499bba2850f13a97665374fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Moj=C5=BE=C3=AD=C5=A1?= Date: Sun, 26 Jun 2022 16:20:26 +0200 Subject: [PATCH 405/600] create var/www/html in nginx-common.postinst --- debian/nginx-common.dirs | 1 - debian/nginx-common.lintian-overrides | 2 -- debian/nginx-common.postinst | 1 + 3 files changed, 1 insertion(+), 3 deletions(-) delete mode 100644 debian/nginx-common.lintian-overrides diff --git a/debian/nginx-common.dirs b/debian/nginx-common.dirs index 65bb651..8e5d7bf 100644 --- a/debian/nginx-common.dirs +++ b/debian/nginx-common.dirs @@ -10,4 +10,3 @@ usr/share/vim/addons usr/share/vim/registry var/lib/nginx var/log/nginx -var/www/html diff --git a/debian/nginx-common.lintian-overrides b/debian/nginx-common.lintian-overrides deleted file mode 100644 index 35cc9bc..0000000 --- a/debian/nginx-common.lintian-overrides +++ /dev/null @@ -1,2 +0,0 @@ -# /var/www/html is the default document root -nginx-common: dir-or-file-in-var-www var/www/html/ diff --git a/debian/nginx-common.postinst b/debian/nginx-common.postinst index 9e0610e..0d44608 100644 --- a/debian/nginx-common.postinst +++ b/debian/nginx-common.postinst @@ -39,6 +39,7 @@ case "$1" in # Create a default index page when not already present. if [ ! -e /var/www/html/index.nginx-debian.html ]; then + mkdir -p /var/www/html cp /usr/share/nginx/html/index.html /var/www/html/index.nginx-debian.html fi From 1a3b0014140ee9b085732cf31457435d70f9a713 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Moj=C5=BE=C3=AD=C5=A1?= Date: Sun, 26 Jun 2022 16:41:06 +0200 Subject: [PATCH 406/600] d/changelog close #985133 bug --- debian/changelog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index a12536e..1409f33 100644 --- a/debian/changelog +++ b/debian/changelog @@ -35,7 +35,7 @@ nginx (1.22.0-1) UNRELEASED; urgency=medium [ Miao Wang ] * dh_nginx: support auto generating module config files * adding a new nginx-dev package including necessary headers and debhelper - scripts to build and package a 3rd party module. + scripts to build and package a 3rd party module. (Closes: 985133) * d/p/0002-Make-sure-signature-stays-the-same-in-all-nginx-buil.patch removed, because feature already implemented with --with-compat configure option since 1.11.5 From 035ed7f34a7c35aee9e008eb26f5a5c99f15ca82 Mon Sep 17 00:00:00 2001 From: Thomas Ward Date: Sat, 9 Jul 2022 20:14:24 -0400 Subject: [PATCH 407/600] Unstable upload --- debian/changelog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index 1409f33..46c9e92 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -nginx (1.22.0-1) UNRELEASED; urgency=medium +nginx (1.22.0-1) unstable; urgency=medium [ Thomas Ward ] * New upstream release (1.22.0) From ccd67189200544340c52c67bebd8eeea797a5b01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Moj=C5=BE=C3=AD=C5=A1?= Date: Sun, 10 Jul 2022 08:21:23 +0200 Subject: [PATCH 408/600] d/nginx-common.nginx.service update --- debian/changelog | 12 ++++++++++++ debian/nginx-common.nginx.service | 3 ++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index 46c9e92..609ac41 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,15 @@ +nginx (1.22.0-2) UNRELEASED; urgency=medium + + * d/nginx-common.nginx.service: added Systemd dependency + Wants=network-online.target and updated Systemd "After" dependency to + recommended NGINX values, namely: + - syslog.target + - network-online.target (Closes: 61261) (Closes: 1000406) + - remote-fs.target (Closes: 898896) + - nss-lookup.target + + -- Jan Mojžíš Sun, 10 Jul 2022 07:58:44 +0200 + nginx (1.22.0-1) unstable; urgency=medium [ Thomas Ward ] diff --git a/debian/nginx-common.nginx.service b/debian/nginx-common.nginx.service index 78bf0ce..a46a725 100644 --- a/debian/nginx-common.nginx.service +++ b/debian/nginx-common.nginx.service @@ -13,7 +13,8 @@ [Unit] Description=A high performance web server and a reverse proxy server Documentation=man:nginx(8) -After=network.target nss-lookup.target +After=syslog.target network-online.target remote-fs.target nss-lookup.target +Wants=network-online.target [Service] Type=forking From 88d4d1577a0387abc4cf2d6b039711bfd7c142af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Moj=C5=BE=C3=AD=C5=A1?= Date: Sun, 10 Jul 2022 08:29:08 +0200 Subject: [PATCH 409/600] d/p/0003-define_gnu_source-on-other-glibc-based-platforms.patch forwarded to upstream --- debian/changelog | 2 ++ .../0003-define_gnu_source-on-other-glibc-based-platforms.patch | 1 + 2 files changed, 3 insertions(+) diff --git a/debian/changelog b/debian/changelog index 609ac41..749ec29 100644 --- a/debian/changelog +++ b/debian/changelog @@ -7,6 +7,8 @@ nginx (1.22.0-2) UNRELEASED; urgency=medium - network-online.target (Closes: 61261) (Closes: 1000406) - remote-fs.target (Closes: 898896) - nss-lookup.target + * d/p/0003-define_gnu_source-on-other-glibc-based-platforms.patch: forwarded + to upstream (Closes: 859082) -- Jan Mojžíš Sun, 10 Jul 2022 07:58:44 +0200 diff --git a/debian/patches/0003-define_gnu_source-on-other-glibc-based-platforms.patch b/debian/patches/0003-define_gnu_source-on-other-glibc-based-platforms.patch index d43fd23..caf155f 100644 --- a/debian/patches/0003-define_gnu_source-on-other-glibc-based-platforms.patch +++ b/debian/patches/0003-define_gnu_source-on-other-glibc-based-platforms.patch @@ -1,6 +1,7 @@ Date: Sat, 16 Jul 2016 23:52:50 +0100 From: Steven Chamberlain Subject: Use _GNU_SOURCE on GNU/kFreeBSD +Forwarded: https://trac.nginx.org/nginx/ticket/2366 Define _GNU_SOURCE not only on GNU/Hurd, but also other glibc-based platforms including GNU/kFreeBSD. From ff7cd7012d526745b8b5bc514877e2be0a487da9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Moj=C5=BE=C3=AD=C5=A1?= Date: Sun, 10 Jul 2022 18:32:08 +0200 Subject: [PATCH 410/600] d/t/reboot: added, tests if nginx works after reboot --- debian/changelog | 1 + debian/tests/control | 4 ++++ debian/tests/reboot | 15 +++++++++++++++ 3 files changed, 20 insertions(+) create mode 100644 debian/tests/reboot diff --git a/debian/changelog b/debian/changelog index 749ec29..adf2e41 100644 --- a/debian/changelog +++ b/debian/changelog @@ -9,6 +9,7 @@ nginx (1.22.0-2) UNRELEASED; urgency=medium - nss-lookup.target * d/p/0003-define_gnu_source-on-other-glibc-based-platforms.patch: forwarded to upstream (Closes: 859082) + * d/t/reboot: added, tests if nginx works after reboot -- Jan Mojžíš Sun, 10 Jul 2022 07:58:44 +0200 diff --git a/debian/tests/control b/debian/tests/control index 52690ae..4a24735 100644 --- a/debian/tests/control +++ b/debian/tests/control @@ -125,3 +125,7 @@ Depends: nginx-extras, libnginx-mod-stream-geoip, libnginx-mod-stream-geoip2, libnginx-mod-stream, + +Tests: reboot +Restrictions: isolation-container, needs-root, needs-reboot +Depends: nginx-light, curl diff --git a/debian/tests/reboot b/debian/tests/reboot new file mode 100644 index 0000000..a90a6c9 --- /dev/null +++ b/debian/tests/reboot @@ -0,0 +1,15 @@ +#!/bin/sh +# 20220710 +# Jan Mojzis +# Public domain + +#change directory to $AUTOPKGTEST_TMP +cd "${AUTOPKGTEST_TMP}" + +# do simple curl +curl --silent --fail -o /dev/null -w "response_code: %{http_code}\n" http://127.0.0.1/ + +# test if nginx runs after reboot +if [ x"${AUTOPKGTEST_REBOOT_MARK}" = x ]; then + /tmp/autopkgtest-reboot rebootmark +fi From 461acc4f5141c73b01531283c035580608073e97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Moj=C5=BE=C3=AD=C5=A1?= Date: Sun, 10 Jul 2022 20:12:32 +0200 Subject: [PATCH 411/600] d/nginx-common.nginx.service: remove systemd 'After' dependency syslog.target, is obsolete --- debian/changelog | 1 - debian/nginx-common.nginx.service | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index adf2e41..d9adaf3 100644 --- a/debian/changelog +++ b/debian/changelog @@ -3,7 +3,6 @@ nginx (1.22.0-2) UNRELEASED; urgency=medium * d/nginx-common.nginx.service: added Systemd dependency Wants=network-online.target and updated Systemd "After" dependency to recommended NGINX values, namely: - - syslog.target - network-online.target (Closes: 61261) (Closes: 1000406) - remote-fs.target (Closes: 898896) - nss-lookup.target diff --git a/debian/nginx-common.nginx.service b/debian/nginx-common.nginx.service index a46a725..a63fa0f 100644 --- a/debian/nginx-common.nginx.service +++ b/debian/nginx-common.nginx.service @@ -13,7 +13,7 @@ [Unit] Description=A high performance web server and a reverse proxy server Documentation=man:nginx(8) -After=syslog.target network-online.target remote-fs.target nss-lookup.target +After=network-online.target remote-fs.target nss-lookup.target Wants=network-online.target [Service] From 0d813834ef16b455986c8aea98f9f0a1158eff02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Moj=C5=BE=C3=AD=C5=A1?= Date: Mon, 11 Jul 2022 20:33:33 +0200 Subject: [PATCH 412/600] http-subs-filter add PCRE2 support --- debian/changelog | 1 + .../patches/http-subs-filter/pcre2.patch | 24 +++++++++++++++++++ .../modules/patches/http-subs-filter/series | 1 + 3 files changed, 26 insertions(+) create mode 100644 debian/modules/patches/http-subs-filter/pcre2.patch diff --git a/debian/changelog b/debian/changelog index d9adaf3..9fb216f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -9,6 +9,7 @@ nginx (1.22.0-2) UNRELEASED; urgency=medium * d/p/0003-define_gnu_source-on-other-glibc-based-platforms.patch: forwarded to upstream (Closes: 859082) * d/t/reboot: added, tests if nginx works after reboot + * d/m/p/http-subs-filter/pcre2.patch: added PCRE2 support -- Jan Mojžíš Sun, 10 Jul 2022 07:58:44 +0200 diff --git a/debian/modules/patches/http-subs-filter/pcre2.patch b/debian/modules/patches/http-subs-filter/pcre2.patch new file mode 100644 index 0000000..692257c --- /dev/null +++ b/debian/modules/patches/http-subs-filter/pcre2.patch @@ -0,0 +1,24 @@ +Author: shmux8 <75251845+shmux8@users.noreply.github.com> +Date: Tue Dec 28 11:15:00 2021 +0300 +Subject: [PATCH] pcre2 support +Origin: https://github.com/yaoweibin/ngx_http_substitutions_filter_module/commit/cc494d7f5c5273a7a8ae503faebf1101689d75c0 + + PCRE2 support added + + Use pcre2_pattern_info call if nginx built with PCRE2. + +diff --git a/debian/modules/http-subs-filter/ngx_http_subs_filter_module.c b/debian/modules/http-subs-filter/ngx_http_subs_filter_module.c +index 483c9c3..11a5b79 100644 +--- a/ngx_http_subs_filter_module.c ++++ b/ngx_http_subs_filter_module.c +@@ -1203,7 +1203,9 @@ ngx_http_subs_regex_capture_count(ngx_regex_t *re) + + n = 0; + +-#if defined(nginx_version) && nginx_version >= 1002002 ++#if (NGX_PCRE2) ++ rc = pcre2_pattern_info(re, PCRE2_INFO_CAPTURECOUNT, &n); ++#elif defined(nginx_version) && nginx_version >= 1002002 + rc = pcre_fullinfo(re->code, NULL, PCRE_INFO_CAPTURECOUNT, &n); + #elif defined(nginx_version) && nginx_version >= 1001012 + rc = pcre_fullinfo(re->pcre, NULL, PCRE_INFO_CAPTURECOUNT, &n); diff --git a/debian/modules/patches/http-subs-filter/series b/debian/modules/patches/http-subs-filter/series index f9b9360..4344c0b 100644 --- a/debian/modules/patches/http-subs-filter/series +++ b/debian/modules/patches/http-subs-filter/series @@ -1 +1,2 @@ dynamic-module.patch +pcre2.patch From 0e2eaec4b255c46654b049f593a03368083d7b48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Moj=C5=BE=C3=AD=C5=A1?= Date: Sat, 23 Jul 2022 10:40:40 +0200 Subject: [PATCH 413/600] d/gitlab-ci.yml removed in GL switched to salsa-ci team recipes/debian.yml@salsa-ci-team/pipeline --- debian/gitlab-ci.yml | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 debian/gitlab-ci.yml diff --git a/debian/gitlab-ci.yml b/debian/gitlab-ci.yml deleted file mode 100644 index 557434c..0000000 --- a/debian/gitlab-ci.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -include: - - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/salsa-ci.yml - - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/pipeline-jobs.yml - -# Disable reprotest which is failing now -variables: - SALSA_CI_DISABLE_REPROTEST: 1 From 142c95ade023fd91eed22a5c1b7c2525b79b13d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Moj=C5=BE=C3=AD=C5=A1?= Date: Sat, 23 Jul 2022 10:46:55 +0200 Subject: [PATCH 414/600] add libnginx-mod-http-ndk-dev to nginx to build ngx-lua --- debian/changelog | 5 +++++ debian/control | 16 +++++++++++++++ debian/libnginx-mod-http-ndk-dev.install | 5 +++++ debian/rules | 26 ++++++++++++++++++++---- 4 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 debian/libnginx-mod-http-ndk-dev.install diff --git a/debian/changelog b/debian/changelog index 9fb216f..194e492 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,5 +1,10 @@ nginx (1.22.0-2) UNRELEASED; urgency=medium + [ Miao Wang ] + * adding a new libnginx-mod-http-ndk-dev package including necessary + headers to build a 3rd party module depending on ndk. + + [ Jan Mojžíš ] * d/nginx-common.nginx.service: added Systemd dependency Wants=network-online.target and updated Systemd "After" dependency to recommended NGINX values, namely: diff --git a/debian/control b/debian/control index 21eb530..4736a9f 100644 --- a/debian/control +++ b/debian/control @@ -398,6 +398,22 @@ Description: Nginx Development Kit module features that are seen from a user's point of view - it's just designed to help reduce the code that Nginx module developers need to write. +Package: libnginx-mod-http-ndk-dev +Architecture: all +Depends: libnginx-mod-http-ndk (<< ${source:Version}.1~), libnginx-mod-http-ndk (>= ${source:Version}), + nginx-dev (>= ${source:Version}), nginx-dev (<< ${source:Version}.1~), ${misc:Depends} +Description: Nginx Development Kit module - development files + The NDK is an Nginx module that is designed to extend the core functionality of + the excellent Nginx webserver in a way that can be used as a basis of other + Nginx modules. + . + This package provides development headers and necessary config scripts + for the Nginx development kit module, useful to develop and link third party + additions to the Debian nginx web/proxy server packages using Nginx + development kit module. + . + Development files. + Package: libnginx-mod-nchan Architecture: any Depends: ${misc:Depends}, ${shlibs:Depends}, diff --git a/debian/libnginx-mod-http-ndk-dev.install b/debian/libnginx-mod-http-ndk-dev.install new file mode 100644 index 0000000..980066f --- /dev/null +++ b/debian/libnginx-mod-http-ndk-dev.install @@ -0,0 +1,5 @@ +debian/build-ndksrc/auto usr/share/nginx-ndk/src/ +debian/build-ndksrc/src usr/share/nginx-ndk/src/ +debian/build-ndksrc/objs usr/share/nginx-ndk/src/ +debian/build-ndksrc/config usr/share/nginx-ndk/src/ +debian/build-ndksrc/ngx_auto_lib_core usr/share/nginx-ndk/src/ \ No newline at end of file diff --git a/debian/rules b/debian/rules index d4ddc7e..4471089 100755 --- a/debian/rules +++ b/debian/rules @@ -32,7 +32,7 @@ DYN_MODS := \ MODULESDIR = $(CURDIR)/debian/modules BASEDIR = $(CURDIR) -$(foreach flavour,$(FLAVOURS) src,$(eval BUILDDIR_$(flavour) = $(CURDIR)/debian/build-$(flavour))) +$(foreach flavour,$(FLAVOURS) src ndksrc,$(eval BUILDDIR_$(flavour) = $(CURDIR)/debian/build-$(flavour))) DEB_BUILD_ARCH ?=$(shell dpkg-architecture -qDEB_BUILD_ARCH) ifeq ($(DEB_BUILD_ARCH),sparc) @@ -135,10 +135,10 @@ extras_configure_flags := \ %: dh $@ --without autoreconf -override_dh_auto_configure: config_patch_modules $(foreach flavour,$(FLAVOURS),config.arch.$(flavour)) config.src -override_dh_auto_build: $(foreach flavour,$(FLAVOURS),build.arch.$(flavour)) build.src +override_dh_auto_configure: config_patch_modules $(foreach flavour,$(FLAVOURS),config.arch.$(flavour)) config.src config.ndksrc +override_dh_auto_build: $(foreach flavour,$(FLAVOURS),build.arch.$(flavour)) build.src build.ndksrc override_dh_strip: $(foreach flavour,$(FLAVOURS),strip.arch.$(flavour)) $(foreach mod,$(DYN_MODS),strip.mods.$(mod)) -override_dh_clean: clean_patch_modules $(foreach flavour,$(FLAVOURS),clean.$(flavour)) clean.src +override_dh_clean: clean_patch_modules $(foreach flavour,$(FLAVOURS),clean.$(flavour)) clean.src clean.ndksrc dh_clean override_dh_install: @@ -165,6 +165,16 @@ build.src: echo "NGX_CONF_FLAGS=(" $(basic_configure_flags) ")" > $(BUILDDIR_src)/conf_flags pod2man debian/debhelper/dh_nginx > $(BUILDDIR_src)/dh_nginx.1 +build.ndksrc: + cp -Pa $(CURDIR)/debian/modules/http-ndk/auto \ + $(CURDIR)/debian/modules/http-ndk/config \ + $(CURDIR)/debian/modules/http-ndk/ngx_auto_lib_core $(BUILDDIR_ndksrc)/ + for i in src objs; do \ + find $(CURDIR)/debian/modules/http-ndk/$$i -type f -name '*.h' -printf "$$i/%P\0" | \ + tar -C $(CURDIR)/debian/modules/http-ndk --null --files-from - -c | tar -C $(BUILDDIR_ndksrc)/ -x; \ + done + chmod +x $(CURDIR)/debian/build-ndksrc/auto/build + strip.arch.%: dh_strip --package=nginx-$(*) -O--dbgsym-migration='nginx-$(*)-dbg (<< 1.10.1-3~)' @@ -192,11 +202,19 @@ config.arch.%: cp -Pa $(CURDIR)/src $(BUILDDIR_$*)/ cp -Pa $(CURDIR)/man $(BUILDDIR_$*)/ cd $(BUILDDIR_$*) && ./configure $($*_configure_flags) + if [ "$(BUILDDIR_$*)" = "$(BUILDDIR_extras)" ]; then \ + have="NDK_SET_VAR"; \ + /bin/echo -e "#ifndef $$have\n#define $$have 1\n#endif" >> $(BUILDDIR_$*)/objs/ngx_auto_config.h; \ + fi config.src: dh_testdir mkdir -p $(BUILDDIR_src) +config.ndksrc: + dh_testdir + mkdir -p $(BUILDDIR_ndksrc) + clean.%: rm -rf $(BUILDDIR_$*) From 43b9a879c9a5b7573336e339a0b43113e45a56ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Moj=C5=BE=C3=AD=C5=A1?= Date: Sat, 23 Jul 2022 10:48:06 +0200 Subject: [PATCH 415/600] Remove constraints unnecessary since buster * Build-Depends: Drop versioned constraint on dpkg-dev. * nginx-common: Drop versioned constraint on lsb-base in Depends. * nginx-core: Drop versioned constraint on nginx in Breaks. * nginx-full: Drop versioned constraint on nginx in Breaks. * nginx-light: Drop versioned constraint on nginx in Breaks. * nginx-extras: Drop versioned constraint on nginx in Breaks. * libnginx-mod-http-perl: Drop versioned constraint on nginx-extras in Replaces. * Remove 5 maintscript entries from 1 files. --- debian/changelog | 12 ++++++++++++ debian/control | 10 ++-------- debian/nginx-common.maintscript | 8 -------- 3 files changed, 14 insertions(+), 16 deletions(-) delete mode 100644 debian/nginx-common.maintscript diff --git a/debian/changelog b/debian/changelog index 194e492..c0cbcdb 100644 --- a/debian/changelog +++ b/debian/changelog @@ -16,6 +16,18 @@ nginx (1.22.0-2) UNRELEASED; urgency=medium * d/t/reboot: added, tests if nginx works after reboot * d/m/p/http-subs-filter/pcre2.patch: added PCRE2 support + [ Debian Janitor ] + * Remove constraints unnecessary since buster: + + Build-Depends: Drop versioned constraint on dpkg-dev. + + nginx-common: Drop versioned constraint on lsb-base in Depends. + + nginx-core: Drop versioned constraint on nginx in Breaks. + + nginx-full: Drop versioned constraint on nginx in Breaks. + + nginx-light: Drop versioned constraint on nginx in Breaks. + + nginx-extras: Drop versioned constraint on nginx in Breaks. + + libnginx-mod-http-perl: Drop versioned constraint on nginx-extras in + Replaces. + + Remove 5 maintscript entries from 1 files. + -- Jan Mojžíš Sun, 10 Jul 2022 07:58:44 +0200 nginx (1.22.0-1) unstable; urgency=medium diff --git a/debian/control b/debian/control index 4736a9f..c8aa03c 100644 --- a/debian/control +++ b/debian/control @@ -7,7 +7,6 @@ Uploaders: Christos Trochalakis , Thomas Ward , Jan Mojžíš , Build-Depends: debhelper-compat (= 13), - dpkg-dev (>= 1.15.5), libexpat-dev, libgd-dev, libgeoip-dev, @@ -58,7 +57,7 @@ Description: small, powerful, scalable web/proxy server - documentation Package: nginx-common Architecture: all Multi-Arch: foreign -Depends: lsb-base (>= 3.0-6), ${misc:Depends} +Depends: lsb-base, ${misc:Depends} Suggests: fcgiwrap, nginx-doc, ssl-cert Description: small, powerful, scalable web/proxy server - common files Nginx ("engine X") is a high-performance web and reverse proxy server @@ -105,8 +104,7 @@ Depends: libnginx-mod-http-geoip (= ${binary:Version}), iproute2, ${misc:Depends}, ${shlibs:Depends} -Breaks: nginx (<< 1.4.5-1), - nginx-full (<< 1.18.0-1), +Breaks: nginx-full (<< 1.18.0-1), Replaces: nginx-full (<< 1.18.0-1), Provides: httpd, httpd-cgi, nginx Conflicts: nginx-extras, nginx-light @@ -146,7 +144,6 @@ Depends: libnginx-mod-http-auth-pam, nginx-core (<< ${source:Version}.1~), ${misc:Depends}, ${shlibs:Depends} -Breaks: nginx (<< 1.4.5-1) Provides: httpd, httpd-cgi, nginx Suggests: nginx-doc (= ${source:Version}) Description: nginx web/proxy server (standard version with 3rd parties) @@ -181,7 +178,6 @@ Depends: libnginx-mod-http-echo (= ${binary:Version}), iproute2, ${misc:Depends}, ${shlibs:Depends} -Breaks: nginx (<< 1.4.5-1) Provides: httpd, httpd-cgi, nginx Conflicts: nginx-extras, nginx-core Suggests: nginx-doc (= ${source:Version}) @@ -228,7 +224,6 @@ Depends: libnginx-mod-http-auth-pam (= ${binary:Version}), iproute2, ${misc:Depends}, ${shlibs:Depends} -Breaks: nginx (<< 1.4.5-1) Provides: httpd, httpd-cgi, nginx Conflicts: nginx-core, nginx-light Suggests: nginx-doc (= ${source:Version}) @@ -351,7 +346,6 @@ Package: libnginx-mod-http-perl Architecture: any Depends: ${misc:Depends}, ${perl:Depends}, ${shlibs:Depends}, Recommends: nginx, -Replaces: nginx-extras (<< 1.9.14-1) Description: Perl module for Nginx Embed Perl runtime into nginx. . diff --git a/debian/nginx-common.maintscript b/debian/nginx-common.maintscript deleted file mode 100644 index e1e7f53..0000000 --- a/debian/nginx-common.maintscript +++ /dev/null @@ -1,8 +0,0 @@ -# Handle naxsi removal -rm_conffile /etc/nginx/naxsi.rules 1.6.2-2~ -rm_conffile /etc/nginx/naxsi_core.rules 1.6.2-2~ -rm_conffile /etc/nginx/naxsi-ui.conf.1.4.1 1.6.2-2~ -rm_conffile /etc/nginx/naxsi-ui.conf 1.6.2-2~ - -# Handle upstart removal -rm_conffile /etc/init/nginx.conf 1.13.5-1~ From 861f1be8692fccce5996e26ee7f210c927ea6ceb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Moj=C5=BE=C3=AD=C5=A1?= Date: Sat, 23 Jul 2022 10:49:48 +0200 Subject: [PATCH 416/600] d/p/nginx-fix-pidfile.patch backport from Ubuntu --- debian/changelog | 2 + debian/patches/nginx-fix-pidfile.patch | 89 ++++++++++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 92 insertions(+) create mode 100644 debian/patches/nginx-fix-pidfile.patch diff --git a/debian/changelog b/debian/changelog index c0cbcdb..7d70e35 100644 --- a/debian/changelog +++ b/debian/changelog @@ -15,6 +15,8 @@ nginx (1.22.0-2) UNRELEASED; urgency=medium to upstream (Closes: 859082) * d/t/reboot: added, tests if nginx works after reboot * d/m/p/http-subs-filter/pcre2.patch: added PCRE2 support + * d/p/nginx-fix-pidfile.patch: Fix NGINX PIDfile handling to avoid + SystemD race condition, this fix is backported from Ubuntu (Closes: 876365) [ Debian Janitor ] * Remove constraints unnecessary since buster: diff --git a/debian/patches/nginx-fix-pidfile.patch b/debian/patches/nginx-fix-pidfile.patch new file mode 100644 index 0000000..47a16ff --- /dev/null +++ b/debian/patches/nginx-fix-pidfile.patch @@ -0,0 +1,89 @@ +Description: Fix NGINX pidfile handling +Author: Tj +Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/nginx/+bug/1581864 +Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=876365 +Last-Update: 2020-06-24 +--- +This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ +diff --git a/src/core/nginx.c b/src/core/nginx.c +index 9fcb0eb2..083eba1d 100644 +--- a/src/core/nginx.c ++++ b/src/core/nginx.c +@@ -338,14 +338,21 @@ main(int argc, char *const *argv) + ngx_process = NGX_PROCESS_MASTER; + } + ++ /* tell-tale to detect if this is parent or child process */ ++ ngx_int_t child_pid = NGX_BUSY; ++ + #if !(NGX_WIN32) + + if (ngx_init_signals(cycle->log) != NGX_OK) { + return 1; + } + ++ /* tell-tale that this code has been executed */ ++ child_pid--; ++ + if (!ngx_inherited && ccf->daemon) { +- if (ngx_daemon(cycle->log) != NGX_OK) { ++ child_pid = ngx_daemon(cycle->log); ++ if (child_pid == NGX_ERROR) { + return 1; + } + +@@ -358,8 +365,19 @@ main(int argc, char *const *argv) + + #endif + +- if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) { +- return 1; ++ /* If ngx_daemon() returned the child's PID in the parent process ++ * after the fork() set ngx_pid to the child_pid, which gets ++ * written to the PID file, then exit. ++ * For NGX_WIN32 always write the PID file ++ * For others, only write it from the parent process */ ++ if (child_pid < NGX_OK || child_pid > NGX_OK) { ++ ngx_pid = child_pid > NGX_OK ? child_pid : ngx_pid; ++ if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) { ++ return 1; ++ } ++ } ++ if (child_pid > NGX_OK) { ++ exit(0); + } + + if (ngx_log_redirect_stderr(cycle) != NGX_OK) { +diff --git a/src/os/unix/ngx_daemon.c b/src/os/unix/ngx_daemon.c +index 385c49b6..3719854c 100644 +--- a/src/os/unix/ngx_daemon.c ++++ b/src/os/unix/ngx_daemon.c +@@ -7,14 +7,17 @@ + + #include + #include ++#include + + + ngx_int_t + ngx_daemon(ngx_log_t *log) + { + int fd; ++ /* retain the return value for passing back to caller */ ++ pid_t pid_child = fork(); + +- switch (fork()) { ++ switch (pid_child) { + case -1: + ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "fork() failed"); + return NGX_ERROR; +@@ -23,7 +26,8 @@ ngx_daemon(ngx_log_t *log) + break; + + default: +- exit(0); ++ /* let caller do the exit() */ ++ return pid_child; + } + + ngx_parent = ngx_pid; diff --git a/debian/patches/series b/debian/patches/series index 04030f9..5e15dcc 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -1 +1,2 @@ 0003-define_gnu_source-on-other-glibc-based-platforms.patch +nginx-fix-pidfile.patch From c9a408aa6f2309b43efaa2b04c5cf788aa546fa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Moj=C5=BE=C3=AD=C5=A1?= Date: Sat, 23 Jul 2022 10:50:45 +0200 Subject: [PATCH 417/600] d/apport/source_nginx.py: Add apport hooks for additional bug information gathering, the script is backported from Ubuntu --- debian/apport/source_nginx.py | 19 +++++++++++++++++++ debian/changelog | 3 +++ debian/nginx-common.install | 1 + 3 files changed, 23 insertions(+) create mode 100644 debian/apport/source_nginx.py diff --git a/debian/apport/source_nginx.py b/debian/apport/source_nginx.py new file mode 100644 index 0000000..aec6e8e --- /dev/null +++ b/debian/apport/source_nginx.py @@ -0,0 +1,19 @@ +''' +apport package hook for nginx packages + +Copyright (c) 2015, Thomas Ward +''' + +import apport.hookutils +import os +import subprocess + +def add_info(report, ui): + if (report['Package'].split()[0] != 'nginx-common' + and report['ProblemType'] == 'Package' + and os.path.isdir('/run/systemd/system')): + report['Journalctl_Nginx.txt'] = apport.hookutils.command_output( + ['journalctl', '-xe', '--unit=nginx.service']) + report['SystemctlStatusFull_Nginx.txt'] = subprocess.Popen( + ['systemctl', '-l', 'status', 'nginx.service'], + stdout=subprocess.PIPE).communicate()[0] diff --git a/debian/changelog b/debian/changelog index 7d70e35..0124d12 100644 --- a/debian/changelog +++ b/debian/changelog @@ -17,6 +17,9 @@ nginx (1.22.0-2) UNRELEASED; urgency=medium * d/m/p/http-subs-filter/pcre2.patch: added PCRE2 support * d/p/nginx-fix-pidfile.patch: Fix NGINX PIDfile handling to avoid SystemD race condition, this fix is backported from Ubuntu (Closes: 876365) + * d/apport/source_nginx.py: Add apport hooks for additional bug + information gathering, the script is backported from Ubuntu (Closes: 963668) + * d/nginx-common.install: Add install rule for apport hooks. [ Debian Janitor ] * Remove constraints unnecessary since buster: diff --git a/debian/nginx-common.install b/debian/nginx-common.install index 90f173b..20109fa 100644 --- a/debian/nginx-common.install +++ b/debian/nginx-common.install @@ -1,5 +1,6 @@ contrib/vim/* usr/share/vim/addons debian/conf/* etc/nginx +debian/apport/source_nginx.py usr/share/apport/package-hooks debian/ufw/nginx etc/ufw/applications.d debian/vim/nginx.yaml usr/share/vim/registry html/index.html usr/share/nginx/html/ From 13a5fc3501349113ac90636d8f47d007ffafd033 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Moj=C5=BE=C3=AD=C5=A1?= Date: Sat, 23 Jul 2022 10:40:40 +0200 Subject: [PATCH 418/600] d/gitlab-ci.yml removed in GL switched to salsa-ci team recipes/debian.yml@salsa-ci-team/pipeline --- debian/gitlab-ci.yml | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 debian/gitlab-ci.yml diff --git a/debian/gitlab-ci.yml b/debian/gitlab-ci.yml deleted file mode 100644 index 557434c..0000000 --- a/debian/gitlab-ci.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -include: - - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/salsa-ci.yml - - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/pipeline-jobs.yml - -# Disable reprotest which is failing now -variables: - SALSA_CI_DISABLE_REPROTEST: 1 From 08de4d4bc7e6ba11051ab1f6ef5460989b161513 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Lal?= Date: Sun, 7 Aug 2022 16:15:09 +0200 Subject: [PATCH 419/600] Release to unstable --- debian/changelog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index 0124d12..6bb8afa 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -nginx (1.22.0-2) UNRELEASED; urgency=medium +nginx (1.22.0-2) unstable; urgency=medium [ Miao Wang ] * adding a new libnginx-mod-http-ndk-dev package including necessary @@ -33,7 +33,7 @@ nginx (1.22.0-2) UNRELEASED; urgency=medium Replaces. + Remove 5 maintscript entries from 1 files. - -- Jan Mojžíš Sun, 10 Jul 2022 07:58:44 +0200 + -- Jan Mojžíš Sun, 07 Aug 2022 16:14:59 +0200 nginx (1.22.0-1) unstable; urgency=medium From a316cb99e4dcc4ba7306b4741f474500784c270f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Moj=C5=BE=C3=AD=C5=A1?= Date: Mon, 8 Aug 2022 12:30:21 +0200 Subject: [PATCH 420/600] d/changelog: fix typo in bug number 61261 -> 861261 --- debian/changelog | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index 6bb8afa..9ac858c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +nginx (1.22.0-3) UNRELEASED; urgency=medium + + * d/changelog: fixed typo in bug number 61261 -> 861261 (Closes: 861261) + + -- Jan Mojžíš Mon, 08 Aug 2022 12:29:34 +0200 + nginx (1.22.0-2) unstable; urgency=medium [ Miao Wang ] @@ -8,7 +14,7 @@ nginx (1.22.0-2) unstable; urgency=medium * d/nginx-common.nginx.service: added Systemd dependency Wants=network-online.target and updated Systemd "After" dependency to recommended NGINX values, namely: - - network-online.target (Closes: 61261) (Closes: 1000406) + - network-online.target (Closes: 861261) (Closes: 1000406) - remote-fs.target (Closes: 898896) - nss-lookup.target * d/p/0003-define_gnu_source-on-other-glibc-based-platforms.patch: forwarded From caf389149afa0b5923116bc4425978a179829c26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Moj=C5=BE=C3=AD=C5=A1?= Date: Mon, 8 Aug 2022 12:32:23 +0200 Subject: [PATCH 421/600] d/p/nginx-ssl_cert_cb_yield.patch add --- debian/changelog | 1 + debian/patches/nginx-ssl_cert_cb_yield.patch | 40 ++++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 42 insertions(+) create mode 100644 debian/patches/nginx-ssl_cert_cb_yield.patch diff --git a/debian/changelog b/debian/changelog index 9ac858c..a41d64e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,6 +1,7 @@ nginx (1.22.0-3) UNRELEASED; urgency=medium * d/changelog: fixed typo in bug number 61261 -> 861261 (Closes: 861261) + * d/p/nginx-ssl_cert_cb_yield.patch added (Closes: 884434) -- Jan Mojžíš Mon, 08 Aug 2022 12:29:34 +0200 diff --git a/debian/patches/nginx-ssl_cert_cb_yield.patch b/debian/patches/nginx-ssl_cert_cb_yield.patch new file mode 100644 index 0000000..96e06e1 --- /dev/null +++ b/debian/patches/nginx-ssl_cert_cb_yield.patch @@ -0,0 +1,40 @@ +Description: SSL: handled SSL_CTX_set_cert_cb() callback yielding. +Author: Yichun Zhang +Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=884434 +Origin: https://raw.githubusercontent.com/openresty/openresty/v1.11.2.2/patches/nginx-1.11.2-ssl_cert_cb_yield.patch +Last-Update: 2016-01-02 + +OpenSSL 1.0.2+ introduces SSL_CTX_set_cert_cb() to allow custom +callbacks to serve the SSL certificiates and private keys dynamically +and lazily. The callbacks may yield for nonblocking I/O or sleeping. +Here we added support for such usage in NGINX 3rd-party modules +(like ngx_lua) in NGINX's event handlers for downstream SSL +connections. + +diff -r 78b4e10b4367 -r 449f0461859c src/event/ngx_event_openssl.c +--- a/src/event/ngx_event_openssl.c Thu Dec 17 16:39:15 2015 +0300 ++++ b/src/event/ngx_event_openssl.c Sat Jan 02 11:14:44 2016 -0800 +@@ -1210,6 +1210,23 @@ + return NGX_AGAIN; + } + ++#if OPENSSL_VERSION_NUMBER >= 0x10002000L ++ if (sslerr == SSL_ERROR_WANT_X509_LOOKUP) { ++ 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; ++ } ++ ++ return NGX_AGAIN; ++ } ++#endif ++ + err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0; + + c->ssl->no_wait_shutdown = 1; diff --git a/debian/patches/series b/debian/patches/series index 5e15dcc..52e1dc4 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -1,2 +1,3 @@ 0003-define_gnu_source-on-other-glibc-based-platforms.patch nginx-fix-pidfile.patch +nginx-ssl_cert_cb_yield.patch From 212327ed576d26fc3b35feb30a43079d10fc5cea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Moj=C5=BE=C3=AD=C5=A1?= Date: Mon, 8 Aug 2022 12:34:00 +0200 Subject: [PATCH 422/600] http-lua: remove --- debian/changelog | 1 + debian/control | 18 +- debian/copyright | 9 - debian/libnginx-mod-http-lua.nginx | 13 - debian/modules/http-lua/README.markdown | 8332 ----------------- debian/modules/http-lua/config | 532 -- .../modules/http-lua/doc/HttpLuaModule.wiki | 7073 -------------- .../http-lua/dtrace/ngx_lua_provider.d | 61 - .../http-lua/misc/recv-until-pm/Makefile | 3 - .../misc/recv-until-pm/lib/RecvUntil.pm | 138 - .../http-lua/misc/recv-until-pm/t/sanity.t | 140 - .../http-lua/src/api/ngx_http_lua_api.h | 62 - debian/modules/http-lua/src/ddebug.h | 85 - .../http-lua/src/ngx_http_lua_accessby.c | 398 - .../http-lua/src/ngx_http_lua_accessby.h | 22 - .../modules/http-lua/src/ngx_http_lua_api.c | 216 - .../modules/http-lua/src/ngx_http_lua_args.c | 555 -- .../modules/http-lua/src/ngx_http_lua_args.h | 20 - .../http-lua/src/ngx_http_lua_balancer.c | 763 -- .../http-lua/src/ngx_http_lua_balancer.h | 27 - .../http-lua/src/ngx_http_lua_bodyfilterby.c | 633 -- .../http-lua/src/ngx_http_lua_bodyfilterby.h | 31 - .../modules/http-lua/src/ngx_http_lua_cache.c | 296 - .../modules/http-lua/src/ngx_http_lua_cache.h | 24 - .../http-lua/src/ngx_http_lua_capturefilter.c | 176 - .../http-lua/src/ngx_http_lua_capturefilter.h | 20 - .../http-lua/src/ngx_http_lua_clfactory.c | 887 -- .../http-lua/src/ngx_http_lua_clfactory.h | 22 - .../http-lua/src/ngx_http_lua_common.h | 593 -- .../http-lua/src/ngx_http_lua_config.c | 70 - .../http-lua/src/ngx_http_lua_config.h | 19 - .../http-lua/src/ngx_http_lua_consts.c | 202 - .../http-lua/src/ngx_http_lua_consts.h | 20 - .../http-lua/src/ngx_http_lua_contentby.c | 387 - .../http-lua/src/ngx_http_lua_contentby.h | 26 - .../http-lua/src/ngx_http_lua_control.c | 555 -- .../http-lua/src/ngx_http_lua_control.h | 20 - .../http-lua/src/ngx_http_lua_coroutine.c | 387 - .../http-lua/src/ngx_http_lua_coroutine.h | 23 - .../modules/http-lua/src/ngx_http_lua_ctx.c | 216 - .../modules/http-lua/src/ngx_http_lua_ctx.h | 23 - .../http-lua/src/ngx_http_lua_directive.c | 1831 ---- .../http-lua/src/ngx_http_lua_directive.h | 78 - .../http-lua/src/ngx_http_lua_exception.c | 58 - .../http-lua/src/ngx_http_lua_exception.h | 33 - .../src/ngx_http_lua_headerfilterby.c | 302 - .../src/ngx_http_lua_headerfilterby.h | 29 - .../http-lua/src/ngx_http_lua_headers.c | 1529 --- .../http-lua/src/ngx_http_lua_headers.h | 25 - .../http-lua/src/ngx_http_lua_headers_in.c | 835 -- .../http-lua/src/ngx_http_lua_headers_in.h | 22 - .../http-lua/src/ngx_http_lua_headers_out.c | 637 -- .../http-lua/src/ngx_http_lua_headers_out.h | 23 - .../http-lua/src/ngx_http_lua_initby.c | 42 - .../http-lua/src/ngx_http_lua_initby.h | 23 - .../http-lua/src/ngx_http_lua_initworkerby.c | 357 - .../http-lua/src/ngx_http_lua_initworkerby.h | 25 - .../modules/http-lua/src/ngx_http_lua_lex.c | 8251 ---------------- .../modules/http-lua/src/ngx_http_lua_lex.h | 17 - .../modules/http-lua/src/ngx_http_lua_log.c | 456 - .../modules/http-lua/src/ngx_http_lua_log.h | 24 - .../http-lua/src/ngx_http_lua_log_ringbuf.c | 225 - .../http-lua/src/ngx_http_lua_log_ringbuf.h | 31 - .../modules/http-lua/src/ngx_http_lua_logby.c | 266 - .../modules/http-lua/src/ngx_http_lua_logby.h | 22 - .../modules/http-lua/src/ngx_http_lua_misc.c | 292 - .../modules/http-lua/src/ngx_http_lua_misc.h | 22 - .../http-lua/src/ngx_http_lua_module.c | 1312 --- .../modules/http-lua/src/ngx_http_lua_ndk.c | 191 - .../modules/http-lua/src/ngx_http_lua_ndk.h | 21 - .../http-lua/src/ngx_http_lua_output.c | 808 -- .../http-lua/src/ngx_http_lua_output.h | 28 - .../http-lua/src/ngx_http_lua_pcrefix.c | 106 - .../http-lua/src/ngx_http_lua_pcrefix.h | 23 - .../modules/http-lua/src/ngx_http_lua_phase.c | 128 - .../modules/http-lua/src/ngx_http_lua_phase.h | 13 - .../modules/http-lua/src/ngx_http_lua_probe.h | 86 - .../modules/http-lua/src/ngx_http_lua_regex.c | 2548 ----- .../modules/http-lua/src/ngx_http_lua_regex.h | 24 - .../http-lua/src/ngx_http_lua_req_body.c | 1188 --- .../http-lua/src/ngx_http_lua_req_body.h | 20 - .../http-lua/src/ngx_http_lua_req_method.c | 253 - .../http-lua/src/ngx_http_lua_req_method.h | 19 - .../http-lua/src/ngx_http_lua_rewriteby.c | 380 - .../http-lua/src/ngx_http_lua_rewriteby.h | 22 - .../http-lua/src/ngx_http_lua_script.c | 538 -- .../http-lua/src/ngx_http_lua_script.h | 86 - .../http-lua/src/ngx_http_lua_semaphore.c | 578 -- .../http-lua/src/ngx_http_lua_semaphore.h | 53 - .../modules/http-lua/src/ngx_http_lua_setby.c | 216 - .../modules/http-lua/src/ngx_http_lua_setby.h | 15 - .../http-lua/src/ngx_http_lua_shdict.c | 3027 ------ .../http-lua/src/ngx_http_lua_shdict.h | 67 - .../modules/http-lua/src/ngx_http_lua_sleep.c | 219 - .../modules/http-lua/src/ngx_http_lua_sleep.h | 20 - .../http-lua/src/ngx_http_lua_socket_tcp.c | 5521 ----------- .../http-lua/src/ngx_http_lua_socket_tcp.h | 156 - .../http-lua/src/ngx_http_lua_socket_udp.c | 1657 ---- .../http-lua/src/ngx_http_lua_socket_udp.h | 65 - .../modules/http-lua/src/ngx_http_lua_ssl.c | 37 - .../modules/http-lua/src/ngx_http_lua_ssl.h | 47 - .../http-lua/src/ngx_http_lua_ssl_certby.c | 1325 --- .../http-lua/src/ngx_http_lua_ssl_certby.h | 37 - .../http-lua/src/ngx_http_lua_ssl_ocsp.c | 506 - .../src/ngx_http_lua_ssl_session_fetchby.c | 614 -- .../src/ngx_http_lua_ssl_session_fetchby.h | 38 - .../src/ngx_http_lua_ssl_session_storeby.c | 618 -- .../src/ngx_http_lua_ssl_session_storeby.h | 34 - .../http-lua/src/ngx_http_lua_string.c | 767 -- .../http-lua/src/ngx_http_lua_string.h | 20 - .../http-lua/src/ngx_http_lua_subrequest.c | 1782 ---- .../http-lua/src/ngx_http_lua_subrequest.h | 46 - .../modules/http-lua/src/ngx_http_lua_time.c | 349 - .../modules/http-lua/src/ngx_http_lua_time.h | 21 - .../modules/http-lua/src/ngx_http_lua_timer.c | 909 -- .../modules/http-lua/src/ngx_http_lua_timer.h | 20 - .../modules/http-lua/src/ngx_http_lua_uri.c | 110 - .../modules/http-lua/src/ngx_http_lua_uri.h | 20 - .../http-lua/src/ngx_http_lua_uthread.c | 285 - .../http-lua/src/ngx_http_lua_uthread.h | 36 - .../modules/http-lua/src/ngx_http_lua_util.c | 4132 -------- .../modules/http-lua/src/ngx_http_lua_util.h | 468 - .../http-lua/src/ngx_http_lua_variable.c | 509 - .../http-lua/src/ngx_http_lua_variable.h | 20 - .../http-lua/src/ngx_http_lua_worker.c | 193 - .../http-lua/src/ngx_http_lua_worker.h | 17 - debian/modules/http-lua/t/000--init.t | 85 - debian/modules/http-lua/t/000-sanity.t | 33 - debian/modules/http-lua/t/001-set.t | 797 -- debian/modules/http-lua/t/002-content.t | 844 -- debian/modules/http-lua/t/003-errors.t | 128 - debian/modules/http-lua/t/004-require.t | 211 - debian/modules/http-lua/t/005-exit.t | 725 -- debian/modules/http-lua/t/006-escape.t | 199 - debian/modules/http-lua/t/007-md5.t | 102 - debian/modules/http-lua/t/008-today.t | 38 - debian/modules/http-lua/t/009-log.t | 544 -- debian/modules/http-lua/t/010-request_body.t | 272 - debian/modules/http-lua/t/011-md5_bin.t | 170 - debian/modules/http-lua/t/012-now.t | 118 - debian/modules/http-lua/t/013-base64.t | 245 - debian/modules/http-lua/t/014-bugs.t | 1020 -- debian/modules/http-lua/t/015-status.t | 293 - debian/modules/http-lua/t/016-resp-header.t | 1701 ---- debian/modules/http-lua/t/017-exec.t | 596 -- debian/modules/http-lua/t/018-ndk.t | 173 - debian/modules/http-lua/t/019-const.t | 46 - debian/modules/http-lua/t/020-subrequest.t | 2879 ------ debian/modules/http-lua/t/021-cookie-time.t | 45 - debian/modules/http-lua/t/022-redirect.t | 322 - .../http-lua/t/023-rewrite/client-abort.t | 850 -- debian/modules/http-lua/t/023-rewrite/exec.t | 400 - debian/modules/http-lua/t/023-rewrite/exit.t | 597 -- debian/modules/http-lua/t/023-rewrite/mixed.t | 169 - .../http-lua/t/023-rewrite/multi-capture.t | 394 - .../modules/http-lua/t/023-rewrite/on-abort.t | 656 -- .../modules/http-lua/t/023-rewrite/redirect.t | 164 - .../modules/http-lua/t/023-rewrite/req-body.t | 223 - .../http-lua/t/023-rewrite/req-socket.t | 534 -- .../http-lua/t/023-rewrite/request_body.t | 172 - .../modules/http-lua/t/023-rewrite/sanity.t | 801 -- debian/modules/http-lua/t/023-rewrite/sleep.t | 221 - .../http-lua/t/023-rewrite/socket-keepalive.t | 1009 -- .../http-lua/t/023-rewrite/subrequest.t | 641 -- .../t/023-rewrite/tcp-socket-timeout.t | 606 -- .../http-lua/t/023-rewrite/tcp-socket.t | 2392 ----- .../http-lua/t/023-rewrite/unix-socket.t | 152 - .../http-lua/t/023-rewrite/uthread-exec.t | 345 - .../http-lua/t/023-rewrite/uthread-exit.t | 1331 --- .../http-lua/t/023-rewrite/uthread-redirect.t | 188 - .../http-lua/t/023-rewrite/uthread-spawn.t | 1451 --- debian/modules/http-lua/t/024-access/auth.t | 109 - .../http-lua/t/024-access/client-abort.t | 852 -- debian/modules/http-lua/t/024-access/exec.t | 393 - debian/modules/http-lua/t/024-access/exit.t | 547 -- debian/modules/http-lua/t/024-access/mixed.t | 261 - .../http-lua/t/024-access/multi-capture.t | 394 - .../modules/http-lua/t/024-access/on-abort.t | 651 -- .../modules/http-lua/t/024-access/redirect.t | 124 - .../modules/http-lua/t/024-access/req-body.t | 220 - .../http-lua/t/024-access/request_body.t | 172 - debian/modules/http-lua/t/024-access/sanity.t | 743 -- .../modules/http-lua/t/024-access/satisfy.t | 211 - debian/modules/http-lua/t/024-access/sleep.t | 221 - .../http-lua/t/024-access/subrequest.t | 601 -- .../http-lua/t/024-access/uthread-exec.t | 346 - .../http-lua/t/024-access/uthread-exit.t | 1313 --- .../http-lua/t/024-access/uthread-redirect.t | 189 - .../http-lua/t/024-access/uthread-spawn.t | 1118 --- debian/modules/http-lua/t/025-codecache.t | 1246 --- debian/modules/http-lua/t/026-mysql.t | 130 - debian/modules/http-lua/t/027-multi-capture.t | 754 -- debian/modules/http-lua/t/028-req-header.t | 2010 ---- debian/modules/http-lua/t/029-http-time.t | 87 - debian/modules/http-lua/t/030-uri-args.t | 1549 --- debian/modules/http-lua/t/031-post-args.t | 406 - debian/modules/http-lua/t/032-iolist.t | 78 - debian/modules/http-lua/t/033-ctx.t | 442 - debian/modules/http-lua/t/034-match.t | 1192 --- debian/modules/http-lua/t/035-gmatch.t | 904 -- debian/modules/http-lua/t/036-sub.t | 757 -- debian/modules/http-lua/t/037-gsub.t | 699 -- debian/modules/http-lua/t/038-match-o.t | 742 -- debian/modules/http-lua/t/039-sub-o.t | 580 -- debian/modules/http-lua/t/040-gsub-o.t | 200 - debian/modules/http-lua/t/041-header-filter.t | 796 -- debian/modules/http-lua/t/042-crc32.t | 56 - debian/modules/http-lua/t/043-shdict.t | 2473 ----- debian/modules/http-lua/t/044-req-body.t | 1746 ---- debian/modules/http-lua/t/045-ngx-var.t | 230 - debian/modules/http-lua/t/046-hmac.t | 31 - debian/modules/http-lua/t/047-match-jit.t | 214 - debian/modules/http-lua/t/048-match-dfa.t | 209 - debian/modules/http-lua/t/049-gmatch-jit.t | 228 - debian/modules/http-lua/t/050-gmatch-dfa.t | 338 - debian/modules/http-lua/t/051-sub-jit.t | 149 - debian/modules/http-lua/t/052-sub-dfa.t | 235 - debian/modules/http-lua/t/053-gsub-jit.t | 149 - debian/modules/http-lua/t/054-gsub-dfa.t | 236 - debian/modules/http-lua/t/055-subreq-vars.t | 338 - debian/modules/http-lua/t/056-flush.t | 522 -- debian/modules/http-lua/t/057-flush-timeout.t | 320 - debian/modules/http-lua/t/058-tcp-socket.t | 3810 -------- debian/modules/http-lua/t/059-unix-socket.t | 203 - debian/modules/http-lua/t/060-lua-memcached.t | 168 - debian/modules/http-lua/t/061-lua-redis.t | 184 - debian/modules/http-lua/t/062-count.t | 570 -- debian/modules/http-lua/t/063-abort.t | 1019 -- debian/modules/http-lua/t/064-pcall.t | 106 - .../http-lua/t/065-tcp-socket-timeout.t | 1018 -- .../http-lua/t/066-socket-receiveuntil.t | 1331 --- debian/modules/http-lua/t/067-req-socket.t | 1098 --- .../modules/http-lua/t/068-socket-keepalive.t | 1553 --- debian/modules/http-lua/t/069-null.t | 95 - debian/modules/http-lua/t/070-sha1.t | 70 - debian/modules/http-lua/t/071-idle-socket.t | 433 - .../modules/http-lua/t/072-conditional-get.t | 90 - debian/modules/http-lua/t/073-backtrace.t | 189 - debian/modules/http-lua/t/074-prefix-var.t | 66 - debian/modules/http-lua/t/075-logby.t | 583 -- debian/modules/http-lua/t/076-no-postpone.t | 146 - debian/modules/http-lua/t/077-sleep.t | 502 - debian/modules/http-lua/t/078-hup-vars.t | 64 - .../http-lua/t/079-unused-directives.t | 342 - debian/modules/http-lua/t/080-hup-shdict.t | 84 - debian/modules/http-lua/t/081-bytecode.t | 373 - debian/modules/http-lua/t/082-body-filter.t | 839 -- debian/modules/http-lua/t/083-bad-sock-self.t | 138 - .../http-lua/t/084-inclusive-receiveuntil.t | 745 -- debian/modules/http-lua/t/085-if.t | 200 - debian/modules/http-lua/t/086-init-by.t | 323 - debian/modules/http-lua/t/087-udp-socket.t | 1176 --- debian/modules/http-lua/t/088-req-method.t | 264 - debian/modules/http-lua/t/089-phase.t | 178 - .../http-lua/t/090-log-socket-errors.t | 108 - debian/modules/http-lua/t/091-coroutine.t | 1317 --- debian/modules/http-lua/t/092-eof.t | 82 - debian/modules/http-lua/t/093-uthread-spawn.t | 1674 ---- debian/modules/http-lua/t/094-uthread-exit.t | 1650 ---- debian/modules/http-lua/t/095-uthread-exec.t | 425 - .../modules/http-lua/t/096-uthread-redirect.t | 279 - .../modules/http-lua/t/097-uthread-rewrite.t | 347 - debian/modules/http-lua/t/098-uthread-wait.t | 1323 --- debian/modules/http-lua/t/099-c-api.t | 397 - debian/modules/http-lua/t/100-client-abort.t | 1066 --- debian/modules/http-lua/t/101-on-abort.t | 848 -- .../modules/http-lua/t/102-req-start-time.t | 115 - debian/modules/http-lua/t/103-req-http-ver.t | 48 - .../modules/http-lua/t/104-req-raw-header.t | 990 -- debian/modules/http-lua/t/105-pressure.t | 53 - debian/modules/http-lua/t/106-timer.t | 2195 ----- debian/modules/http-lua/t/107-timer-errors.t | 1422 --- debian/modules/http-lua/t/108-timer-safe.t | 1397 --- debian/modules/http-lua/t/109-timer-hup.t | 502 - debian/modules/http-lua/t/110-etag.t | 83 - debian/modules/http-lua/t/111-req-header-ua.t | 675 -- .../modules/http-lua/t/112-req-header-conn.t | 148 - .../http-lua/t/113-req-header-cookie.t | 249 - debian/modules/http-lua/t/114-config.t | 48 - debian/modules/http-lua/t/115-quote-sql-str.t | 76 - .../modules/http-lua/t/116-raw-req-socket.t | 878 -- .../http-lua/t/117-raw-req-socket-timeout.t | 116 - .../modules/http-lua/t/118-use-default-type.t | 140 - debian/modules/http-lua/t/119-config-prefix.t | 32 - debian/modules/http-lua/t/120-re-find.t | 919 -- debian/modules/http-lua/t/121-version.t | 48 - debian/modules/http-lua/t/122-worker.t | 81 - debian/modules/http-lua/t/123-lua-path.t | 70 - debian/modules/http-lua/t/124-init-worker.t | 955 -- .../modules/http-lua/t/125-configure-args.t | 31 - debian/modules/http-lua/t/126-shdict-frag.t | 1266 --- debian/modules/http-lua/t/127-uthread-kill.t | 507 - .../http-lua/t/128-duplex-tcp-socket.t | 631 -- debian/modules/http-lua/t/129-ssl-socket.t | 2532 ----- debian/modules/http-lua/t/130-internal-api.t | 49 - .../http-lua/t/131-duplex-req-socket.t | 141 - debian/modules/http-lua/t/132-lua-blocks.t | 729 -- debian/modules/http-lua/t/133-worker-count.t | 72 - .../modules/http-lua/t/134-worker-count-5.t | 78 - debian/modules/http-lua/t/135-worker-id.t | 33 - debian/modules/http-lua/t/136-timer-counts.t | 111 - debian/modules/http-lua/t/137-req-misc.t | 61 - debian/modules/http-lua/t/138-balancer.t | 528 -- debian/modules/http-lua/t/139-ssl-cert-by.t | 2077 ---- debian/modules/http-lua/t/140-ssl-c-api.t | 813 -- debian/modules/http-lua/t/141-luajit.t | 48 - .../http-lua/t/142-ssl-session-store.t | 903 -- .../http-lua/t/143-ssl-session-fetch.t | 1116 --- .../modules/http-lua/t/144-shdict-incr-init.t | 226 - debian/modules/http-lua/t/145-shdict-list.t | 745 -- debian/modules/http-lua/t/146-malloc-trim.t | 342 - .../http-lua/t/147-tcp-socket-timeouts.t | 627 -- debian/modules/http-lua/t/148-fake-shm-zone.t | 170 - .../http-lua/t/149-hup-fake-shm-zone.t | 91 - .../http-lua/t/150-fake-delayed-load.t | 56 - debian/modules/http-lua/t/151-initby-hup.t | 168 - debian/modules/http-lua/t/152-timer-every.t | 385 - debian/modules/http-lua/t/153-semaphore-hup.t | 154 - debian/modules/http-lua/t/154-semaphore.t | 120 - debian/modules/http-lua/t/155-tls13.t | 106 - debian/modules/http-lua/t/StapThread.pm | 282 - debian/modules/http-lua/t/cert/dst-ca.crt | 63 - debian/modules/http-lua/t/cert/equifax.crt | 19 - debian/modules/http-lua/t/cert/test.crl | 11 - debian/modules/http-lua/t/cert/test.crt | 17 - debian/modules/http-lua/t/cert/test.key | 15 - debian/modules/http-lua/t/cert/test2.crt | 16 - debian/modules/http-lua/t/cert/test2.key | 15 - debian/modules/http-lua/t/cert/test_ecdsa.crt | 12 - debian/modules/http-lua/t/cert/test_ecdsa.key | 5 - .../t/data/fake-delayed-load-module/config | 3 - .../ngx_http_lua_fake_delayed_load_module.c | 77 - .../http-lua/t/data/fake-module/config | 3 - .../t/data/fake-module/ngx_http_fake_module.c | 118 - .../http-lua/t/data/fake-shm-module/config | 3 - .../ngx_http_lua_fake_shm_module.c | 294 - debian/modules/http-lua/t/lib/CRC32.lua | 173 - debian/modules/http-lua/t/lib/Memcached.lua | 567 -- debian/modules/http-lua/t/lib/Redis.lua | 1120 --- debian/modules/http-lua/t/lib/ljson.lua | 89 - debian/modules/http-lua/tapset/ngx_lua.stp | 5 - debian/modules/http-lua/util/build.sh | 66 - debian/modules/http-lua/util/fix-comments | 27 - debian/modules/http-lua/util/gen-lexer-c | 18 - debian/modules/http-lua/util/ngx-links | 62 - debian/modules/http-lua/util/releng | 8 - debian/modules/http-lua/util/retab | 8 - debian/modules/http-lua/util/revim | 102 - debian/modules/http-lua/util/run_test.sh | 10 - debian/modules/http-lua/util/update-readme.sh | 4 - debian/modules/http-lua/valgrind.suppress | 209 - .../patches/http-lua/CVE-2020-11724.patch | 856 -- .../http-lua/bug-994178-segfault.patch | 31 - .../http-lua/discover-luajit-2.1.patch | 47 - debian/modules/patches/http-lua/series | 3 - debian/rules | 2 - debian/tests/control | 12 +- debian/tests/lua | 18 - 358 files changed, 6 insertions(+), 182310 deletions(-) delete mode 100755 debian/libnginx-mod-http-lua.nginx delete mode 100644 debian/modules/http-lua/README.markdown delete mode 100644 debian/modules/http-lua/config delete mode 100644 debian/modules/http-lua/doc/HttpLuaModule.wiki delete mode 100644 debian/modules/http-lua/dtrace/ngx_lua_provider.d delete mode 100644 debian/modules/http-lua/misc/recv-until-pm/Makefile delete mode 100755 debian/modules/http-lua/misc/recv-until-pm/lib/RecvUntil.pm delete mode 100644 debian/modules/http-lua/misc/recv-until-pm/t/sanity.t delete mode 100644 debian/modules/http-lua/src/api/ngx_http_lua_api.h delete mode 100644 debian/modules/http-lua/src/ddebug.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_accessby.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_accessby.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_api.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_args.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_args.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_balancer.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_balancer.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_bodyfilterby.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_bodyfilterby.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_cache.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_cache.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_capturefilter.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_capturefilter.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_clfactory.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_clfactory.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_common.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_config.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_config.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_consts.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_consts.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_contentby.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_contentby.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_control.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_control.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_coroutine.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_coroutine.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_ctx.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_ctx.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_directive.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_directive.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_exception.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_exception.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_headerfilterby.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_headerfilterby.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_headers.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_headers.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_headers_in.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_headers_in.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_headers_out.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_headers_out.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_initby.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_initby.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_initworkerby.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_initworkerby.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_lex.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_lex.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_log.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_log.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_log_ringbuf.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_log_ringbuf.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_logby.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_logby.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_misc.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_misc.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_module.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_ndk.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_ndk.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_output.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_output.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_pcrefix.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_pcrefix.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_phase.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_phase.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_probe.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_regex.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_regex.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_req_body.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_req_body.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_req_method.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_req_method.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_rewriteby.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_rewriteby.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_script.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_script.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_semaphore.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_semaphore.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_setby.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_setby.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_shdict.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_shdict.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_sleep.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_sleep.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_socket_tcp.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_socket_tcp.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_socket_udp.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_socket_udp.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_ssl.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_ssl.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_ssl_certby.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_ssl_certby.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_ssl_ocsp.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_ssl_session_fetchby.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_ssl_session_fetchby.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_ssl_session_storeby.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_ssl_session_storeby.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_string.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_string.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_subrequest.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_subrequest.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_time.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_time.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_timer.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_timer.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_uri.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_uri.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_uthread.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_uthread.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_util.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_util.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_variable.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_variable.h delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_worker.c delete mode 100644 debian/modules/http-lua/src/ngx_http_lua_worker.h delete mode 100644 debian/modules/http-lua/t/000--init.t delete mode 100644 debian/modules/http-lua/t/000-sanity.t delete mode 100644 debian/modules/http-lua/t/001-set.t delete mode 100644 debian/modules/http-lua/t/002-content.t delete mode 100644 debian/modules/http-lua/t/003-errors.t delete mode 100644 debian/modules/http-lua/t/004-require.t delete mode 100644 debian/modules/http-lua/t/005-exit.t delete mode 100644 debian/modules/http-lua/t/006-escape.t delete mode 100644 debian/modules/http-lua/t/007-md5.t delete mode 100644 debian/modules/http-lua/t/008-today.t delete mode 100644 debian/modules/http-lua/t/009-log.t delete mode 100644 debian/modules/http-lua/t/010-request_body.t delete mode 100644 debian/modules/http-lua/t/011-md5_bin.t delete mode 100644 debian/modules/http-lua/t/012-now.t delete mode 100644 debian/modules/http-lua/t/013-base64.t delete mode 100644 debian/modules/http-lua/t/014-bugs.t delete mode 100644 debian/modules/http-lua/t/015-status.t delete mode 100644 debian/modules/http-lua/t/016-resp-header.t delete mode 100644 debian/modules/http-lua/t/017-exec.t delete mode 100644 debian/modules/http-lua/t/018-ndk.t delete mode 100644 debian/modules/http-lua/t/019-const.t delete mode 100644 debian/modules/http-lua/t/020-subrequest.t delete mode 100644 debian/modules/http-lua/t/021-cookie-time.t delete mode 100644 debian/modules/http-lua/t/022-redirect.t delete mode 100644 debian/modules/http-lua/t/023-rewrite/client-abort.t delete mode 100644 debian/modules/http-lua/t/023-rewrite/exec.t delete mode 100644 debian/modules/http-lua/t/023-rewrite/exit.t delete mode 100644 debian/modules/http-lua/t/023-rewrite/mixed.t delete mode 100644 debian/modules/http-lua/t/023-rewrite/multi-capture.t delete mode 100644 debian/modules/http-lua/t/023-rewrite/on-abort.t delete mode 100644 debian/modules/http-lua/t/023-rewrite/redirect.t delete mode 100644 debian/modules/http-lua/t/023-rewrite/req-body.t delete mode 100644 debian/modules/http-lua/t/023-rewrite/req-socket.t delete mode 100644 debian/modules/http-lua/t/023-rewrite/request_body.t delete mode 100644 debian/modules/http-lua/t/023-rewrite/sanity.t delete mode 100644 debian/modules/http-lua/t/023-rewrite/sleep.t delete mode 100644 debian/modules/http-lua/t/023-rewrite/socket-keepalive.t delete mode 100644 debian/modules/http-lua/t/023-rewrite/subrequest.t delete mode 100644 debian/modules/http-lua/t/023-rewrite/tcp-socket-timeout.t delete mode 100644 debian/modules/http-lua/t/023-rewrite/tcp-socket.t delete mode 100644 debian/modules/http-lua/t/023-rewrite/unix-socket.t delete mode 100644 debian/modules/http-lua/t/023-rewrite/uthread-exec.t delete mode 100644 debian/modules/http-lua/t/023-rewrite/uthread-exit.t delete mode 100644 debian/modules/http-lua/t/023-rewrite/uthread-redirect.t delete mode 100644 debian/modules/http-lua/t/023-rewrite/uthread-spawn.t delete mode 100644 debian/modules/http-lua/t/024-access/auth.t delete mode 100644 debian/modules/http-lua/t/024-access/client-abort.t delete mode 100644 debian/modules/http-lua/t/024-access/exec.t delete mode 100644 debian/modules/http-lua/t/024-access/exit.t delete mode 100644 debian/modules/http-lua/t/024-access/mixed.t delete mode 100644 debian/modules/http-lua/t/024-access/multi-capture.t delete mode 100644 debian/modules/http-lua/t/024-access/on-abort.t delete mode 100644 debian/modules/http-lua/t/024-access/redirect.t delete mode 100644 debian/modules/http-lua/t/024-access/req-body.t delete mode 100644 debian/modules/http-lua/t/024-access/request_body.t delete mode 100644 debian/modules/http-lua/t/024-access/sanity.t delete mode 100644 debian/modules/http-lua/t/024-access/satisfy.t delete mode 100644 debian/modules/http-lua/t/024-access/sleep.t delete mode 100644 debian/modules/http-lua/t/024-access/subrequest.t delete mode 100644 debian/modules/http-lua/t/024-access/uthread-exec.t delete mode 100644 debian/modules/http-lua/t/024-access/uthread-exit.t delete mode 100644 debian/modules/http-lua/t/024-access/uthread-redirect.t delete mode 100644 debian/modules/http-lua/t/024-access/uthread-spawn.t delete mode 100644 debian/modules/http-lua/t/025-codecache.t delete mode 100644 debian/modules/http-lua/t/026-mysql.t delete mode 100644 debian/modules/http-lua/t/027-multi-capture.t delete mode 100644 debian/modules/http-lua/t/028-req-header.t delete mode 100644 debian/modules/http-lua/t/029-http-time.t delete mode 100644 debian/modules/http-lua/t/030-uri-args.t delete mode 100644 debian/modules/http-lua/t/031-post-args.t delete mode 100644 debian/modules/http-lua/t/032-iolist.t delete mode 100644 debian/modules/http-lua/t/033-ctx.t delete mode 100644 debian/modules/http-lua/t/034-match.t delete mode 100644 debian/modules/http-lua/t/035-gmatch.t delete mode 100644 debian/modules/http-lua/t/036-sub.t delete mode 100644 debian/modules/http-lua/t/037-gsub.t delete mode 100644 debian/modules/http-lua/t/038-match-o.t delete mode 100644 debian/modules/http-lua/t/039-sub-o.t delete mode 100644 debian/modules/http-lua/t/040-gsub-o.t delete mode 100644 debian/modules/http-lua/t/041-header-filter.t delete mode 100644 debian/modules/http-lua/t/042-crc32.t delete mode 100644 debian/modules/http-lua/t/043-shdict.t delete mode 100644 debian/modules/http-lua/t/044-req-body.t delete mode 100644 debian/modules/http-lua/t/045-ngx-var.t delete mode 100644 debian/modules/http-lua/t/046-hmac.t delete mode 100644 debian/modules/http-lua/t/047-match-jit.t delete mode 100644 debian/modules/http-lua/t/048-match-dfa.t delete mode 100644 debian/modules/http-lua/t/049-gmatch-jit.t delete mode 100644 debian/modules/http-lua/t/050-gmatch-dfa.t delete mode 100644 debian/modules/http-lua/t/051-sub-jit.t delete mode 100644 debian/modules/http-lua/t/052-sub-dfa.t delete mode 100644 debian/modules/http-lua/t/053-gsub-jit.t delete mode 100644 debian/modules/http-lua/t/054-gsub-dfa.t delete mode 100644 debian/modules/http-lua/t/055-subreq-vars.t delete mode 100644 debian/modules/http-lua/t/056-flush.t delete mode 100644 debian/modules/http-lua/t/057-flush-timeout.t delete mode 100644 debian/modules/http-lua/t/058-tcp-socket.t delete mode 100644 debian/modules/http-lua/t/059-unix-socket.t delete mode 100644 debian/modules/http-lua/t/060-lua-memcached.t delete mode 100644 debian/modules/http-lua/t/061-lua-redis.t delete mode 100644 debian/modules/http-lua/t/062-count.t delete mode 100644 debian/modules/http-lua/t/063-abort.t delete mode 100644 debian/modules/http-lua/t/064-pcall.t delete mode 100644 debian/modules/http-lua/t/065-tcp-socket-timeout.t delete mode 100644 debian/modules/http-lua/t/066-socket-receiveuntil.t delete mode 100644 debian/modules/http-lua/t/067-req-socket.t delete mode 100644 debian/modules/http-lua/t/068-socket-keepalive.t delete mode 100644 debian/modules/http-lua/t/069-null.t delete mode 100644 debian/modules/http-lua/t/070-sha1.t delete mode 100644 debian/modules/http-lua/t/071-idle-socket.t delete mode 100644 debian/modules/http-lua/t/072-conditional-get.t delete mode 100644 debian/modules/http-lua/t/073-backtrace.t delete mode 100644 debian/modules/http-lua/t/074-prefix-var.t delete mode 100644 debian/modules/http-lua/t/075-logby.t delete mode 100644 debian/modules/http-lua/t/076-no-postpone.t delete mode 100644 debian/modules/http-lua/t/077-sleep.t delete mode 100644 debian/modules/http-lua/t/078-hup-vars.t delete mode 100644 debian/modules/http-lua/t/079-unused-directives.t delete mode 100644 debian/modules/http-lua/t/080-hup-shdict.t delete mode 100644 debian/modules/http-lua/t/081-bytecode.t delete mode 100644 debian/modules/http-lua/t/082-body-filter.t delete mode 100644 debian/modules/http-lua/t/083-bad-sock-self.t delete mode 100644 debian/modules/http-lua/t/084-inclusive-receiveuntil.t delete mode 100644 debian/modules/http-lua/t/085-if.t delete mode 100644 debian/modules/http-lua/t/086-init-by.t delete mode 100644 debian/modules/http-lua/t/087-udp-socket.t delete mode 100644 debian/modules/http-lua/t/088-req-method.t delete mode 100644 debian/modules/http-lua/t/089-phase.t delete mode 100644 debian/modules/http-lua/t/090-log-socket-errors.t delete mode 100644 debian/modules/http-lua/t/091-coroutine.t delete mode 100644 debian/modules/http-lua/t/092-eof.t delete mode 100644 debian/modules/http-lua/t/093-uthread-spawn.t delete mode 100644 debian/modules/http-lua/t/094-uthread-exit.t delete mode 100644 debian/modules/http-lua/t/095-uthread-exec.t delete mode 100644 debian/modules/http-lua/t/096-uthread-redirect.t delete mode 100644 debian/modules/http-lua/t/097-uthread-rewrite.t delete mode 100644 debian/modules/http-lua/t/098-uthread-wait.t delete mode 100644 debian/modules/http-lua/t/099-c-api.t delete mode 100644 debian/modules/http-lua/t/100-client-abort.t delete mode 100644 debian/modules/http-lua/t/101-on-abort.t delete mode 100644 debian/modules/http-lua/t/102-req-start-time.t delete mode 100644 debian/modules/http-lua/t/103-req-http-ver.t delete mode 100644 debian/modules/http-lua/t/104-req-raw-header.t delete mode 100644 debian/modules/http-lua/t/105-pressure.t delete mode 100644 debian/modules/http-lua/t/106-timer.t delete mode 100644 debian/modules/http-lua/t/107-timer-errors.t delete mode 100644 debian/modules/http-lua/t/108-timer-safe.t delete mode 100644 debian/modules/http-lua/t/109-timer-hup.t delete mode 100644 debian/modules/http-lua/t/110-etag.t delete mode 100644 debian/modules/http-lua/t/111-req-header-ua.t delete mode 100644 debian/modules/http-lua/t/112-req-header-conn.t delete mode 100644 debian/modules/http-lua/t/113-req-header-cookie.t delete mode 100644 debian/modules/http-lua/t/114-config.t delete mode 100644 debian/modules/http-lua/t/115-quote-sql-str.t delete mode 100644 debian/modules/http-lua/t/116-raw-req-socket.t delete mode 100644 debian/modules/http-lua/t/117-raw-req-socket-timeout.t delete mode 100644 debian/modules/http-lua/t/118-use-default-type.t delete mode 100644 debian/modules/http-lua/t/119-config-prefix.t delete mode 100644 debian/modules/http-lua/t/120-re-find.t delete mode 100644 debian/modules/http-lua/t/121-version.t delete mode 100644 debian/modules/http-lua/t/122-worker.t delete mode 100644 debian/modules/http-lua/t/123-lua-path.t delete mode 100644 debian/modules/http-lua/t/124-init-worker.t delete mode 100644 debian/modules/http-lua/t/125-configure-args.t delete mode 100644 debian/modules/http-lua/t/126-shdict-frag.t delete mode 100644 debian/modules/http-lua/t/127-uthread-kill.t delete mode 100644 debian/modules/http-lua/t/128-duplex-tcp-socket.t delete mode 100644 debian/modules/http-lua/t/129-ssl-socket.t delete mode 100644 debian/modules/http-lua/t/130-internal-api.t delete mode 100644 debian/modules/http-lua/t/131-duplex-req-socket.t delete mode 100644 debian/modules/http-lua/t/132-lua-blocks.t delete mode 100644 debian/modules/http-lua/t/133-worker-count.t delete mode 100644 debian/modules/http-lua/t/134-worker-count-5.t delete mode 100644 debian/modules/http-lua/t/135-worker-id.t delete mode 100644 debian/modules/http-lua/t/136-timer-counts.t delete mode 100644 debian/modules/http-lua/t/137-req-misc.t delete mode 100644 debian/modules/http-lua/t/138-balancer.t delete mode 100644 debian/modules/http-lua/t/139-ssl-cert-by.t delete mode 100644 debian/modules/http-lua/t/140-ssl-c-api.t delete mode 100644 debian/modules/http-lua/t/141-luajit.t delete mode 100644 debian/modules/http-lua/t/142-ssl-session-store.t delete mode 100644 debian/modules/http-lua/t/143-ssl-session-fetch.t delete mode 100644 debian/modules/http-lua/t/144-shdict-incr-init.t delete mode 100644 debian/modules/http-lua/t/145-shdict-list.t delete mode 100644 debian/modules/http-lua/t/146-malloc-trim.t delete mode 100644 debian/modules/http-lua/t/147-tcp-socket-timeouts.t delete mode 100644 debian/modules/http-lua/t/148-fake-shm-zone.t delete mode 100644 debian/modules/http-lua/t/149-hup-fake-shm-zone.t delete mode 100644 debian/modules/http-lua/t/150-fake-delayed-load.t delete mode 100644 debian/modules/http-lua/t/151-initby-hup.t delete mode 100644 debian/modules/http-lua/t/152-timer-every.t delete mode 100644 debian/modules/http-lua/t/153-semaphore-hup.t delete mode 100644 debian/modules/http-lua/t/154-semaphore.t delete mode 100644 debian/modules/http-lua/t/155-tls13.t delete mode 100644 debian/modules/http-lua/t/StapThread.pm delete mode 100644 debian/modules/http-lua/t/cert/dst-ca.crt delete mode 100644 debian/modules/http-lua/t/cert/equifax.crt delete mode 100644 debian/modules/http-lua/t/cert/test.crl delete mode 100644 debian/modules/http-lua/t/cert/test.crt delete mode 100644 debian/modules/http-lua/t/cert/test.key delete mode 100644 debian/modules/http-lua/t/cert/test2.crt delete mode 100644 debian/modules/http-lua/t/cert/test2.key delete mode 100644 debian/modules/http-lua/t/cert/test_ecdsa.crt delete mode 100644 debian/modules/http-lua/t/cert/test_ecdsa.key delete mode 100644 debian/modules/http-lua/t/data/fake-delayed-load-module/config delete mode 100644 debian/modules/http-lua/t/data/fake-delayed-load-module/ngx_http_lua_fake_delayed_load_module.c delete mode 100644 debian/modules/http-lua/t/data/fake-module/config delete mode 100644 debian/modules/http-lua/t/data/fake-module/ngx_http_fake_module.c delete mode 100644 debian/modules/http-lua/t/data/fake-shm-module/config delete mode 100644 debian/modules/http-lua/t/data/fake-shm-module/ngx_http_lua_fake_shm_module.c delete mode 100755 debian/modules/http-lua/t/lib/CRC32.lua delete mode 100755 debian/modules/http-lua/t/lib/Memcached.lua delete mode 100644 debian/modules/http-lua/t/lib/Redis.lua delete mode 100644 debian/modules/http-lua/t/lib/ljson.lua delete mode 100644 debian/modules/http-lua/tapset/ngx_lua.stp delete mode 100755 debian/modules/http-lua/util/build.sh delete mode 100644 debian/modules/http-lua/util/fix-comments delete mode 100755 debian/modules/http-lua/util/gen-lexer-c delete mode 100755 debian/modules/http-lua/util/ngx-links delete mode 100755 debian/modules/http-lua/util/releng delete mode 100755 debian/modules/http-lua/util/retab delete mode 100755 debian/modules/http-lua/util/revim delete mode 100755 debian/modules/http-lua/util/run_test.sh delete mode 100755 debian/modules/http-lua/util/update-readme.sh delete mode 100644 debian/modules/http-lua/valgrind.suppress delete mode 100644 debian/modules/patches/http-lua/CVE-2020-11724.patch delete mode 100644 debian/modules/patches/http-lua/bug-994178-segfault.patch delete mode 100644 debian/modules/patches/http-lua/discover-luajit-2.1.patch delete mode 100644 debian/modules/patches/http-lua/series delete mode 100644 debian/tests/lua diff --git a/debian/changelog b/debian/changelog index a41d64e..fff7b8f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -2,6 +2,7 @@ nginx (1.22.0-3) UNRELEASED; urgency=medium * d/changelog: fixed typo in bug number 61261 -> 861261 (Closes: 861261) * d/p/nginx-ssl_cert_cb_yield.patch added (Closes: 884434) + * http-lua: removed the http-lua module and moved it to a separate package -- Jan Mojžíš Mon, 08 Aug 2022 12:29:34 +0200 diff --git a/debian/control b/debian/control index c8aa03c..206523f 100644 --- a/debian/control +++ b/debian/control @@ -11,8 +11,6 @@ Build-Depends: debhelper-compat (= 13), libgd-dev, libgeoip-dev, libhiredis-dev, - liblua5.1-0-dev [!i386 !amd64 !kfreebsd-i386 !kfreebsd-amd64 !armel !armhf !powerpc !powerpcspe !mips !mipsel !mips64el !arm64 !ppc64 !s390x], - libluajit-5.1-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64 armel armhf powerpc powerpcspe mips mipsel mips64el arm64 ppc64 s390x], libmaxminddb-dev, libmhash-dev, libpam0g-dev, @@ -209,7 +207,7 @@ Depends: libnginx-mod-http-auth-pam (= ${binary:Version}), libnginx-mod-http-geoip2 (= ${binary:Version}), libnginx-mod-http-headers-more-filter (= ${binary:Version}), libnginx-mod-http-image-filter (= ${binary:Version}), - libnginx-mod-http-lua (= ${binary:Version}), + libnginx-mod-http-lua [amd64 arm64 armel armhf i386 mips64el mipsel s390x], libnginx-mod-http-perl (= ${binary:Version}), libnginx-mod-http-subs-filter (= ${binary:Version}), libnginx-mod-http-uploadprogress (= ${binary:Version}), @@ -364,20 +362,6 @@ Description: PAM authentication module for Nginx The module uses PAM as a backend for simple http authentication. It also allows setting the pam service name to allow more fine grained control. -Package: libnginx-mod-http-lua -Architecture: any -Depends: libnginx-mod-http-ndk (= ${binary:Version}), - ${misc:Depends}, - ${shlibs:Depends}, -Recommends: nginx, -Description: Lua module for Nginx - Embed Lua runtime into nginx. - . - This module embeds Lua, via the standard Lua 5.1 interpreter or LuaJIT - 2.0/2.1, into Nginx and by leveraging Nginx's subrequests, allows the - integration of the powerful Lua threads (Lua coroutines) into the Nginx event - model. - Package: libnginx-mod-http-ndk Architecture: any Depends: ${misc:Depends}, ${shlibs:Depends}, diff --git a/debian/copyright b/debian/copyright index 6449e69..2aabc8d 100644 --- a/debian/copyright +++ b/debian/copyright @@ -84,15 +84,6 @@ Files: debian/modules/http-echo/* Copyright: 2009-2014, Yichun "agentzh" Zhang License: BSD-2-clause -Files: debian/modules/http-lua/* -Copyright: 2009-2017, by Xiaozhe Wang (chaoslawful) . - 2009-2018, by Yichun "agentzh" Zhang (章亦春) , OpenResty Inc. -License: BSD-2-clause - -Files: debian/modules/http-lua/t/lib/CRC32.lua -Copyright: 2007-2008, Neil Richardson (nrich@iinet.net.au) -License: Expat - Files: debian/modules/http-upstream-fair/* Copyright: 2007, Grzegorz Nosek Igor Sysoev diff --git a/debian/libnginx-mod-http-lua.nginx b/debian/libnginx-mod-http-lua.nginx deleted file mode 100755 index 78c206f..0000000 --- a/debian/libnginx-mod-http-lua.nginx +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/perl -w - -use File::Basename; - -# Guess module name -$module = basename($0, '.nginx'); -$module =~ s/^libnginx-mod-//; - -$modulepath = $module; -$modulepath =~ s/-/_/g; - -print "mod debian/build-extras/objs/ngx_${modulepath}_module.so\n"; -print "mod debian/libnginx-mod.conf/mod-${module}.conf\n"; diff --git a/debian/modules/http-lua/README.markdown b/debian/modules/http-lua/README.markdown deleted file mode 100644 index 15ad00e..0000000 --- a/debian/modules/http-lua/README.markdown +++ /dev/null @@ -1,8332 +0,0 @@ - - -Name -==== - -ngx_http_lua_module - Embed the power of Lua into Nginx HTTP Servers. - -*This module is not distributed with the Nginx source.* See [the installation instructions](#installation). - -Table of Contents -================= - -* [Name](#name) -* [Status](#status) -* [Version](#version) -* [Synopsis](#synopsis) -* [Description](#description) -* [Typical Uses](#typical-uses) -* [Nginx Compatibility](#nginx-compatibility) -* [Installation](#installation) - * [Building as a dynamic module](#building-as-a-dynamic-module) - * [C Macro Configurations](#c-macro-configurations) - * [Installation on Ubuntu 11.10](#installation-on-ubuntu-1110) -* [Community](#community) - * [English Mailing List](#english-mailing-list) - * [Chinese Mailing List](#chinese-mailing-list) -* [Code Repository](#code-repository) -* [Bugs and Patches](#bugs-and-patches) -* [Lua/LuaJIT bytecode support](#lualuajit-bytecode-support) -* [System Environment Variable Support](#system-environment-variable-support) -* [HTTP 1.0 support](#http-10-support) -* [Statically Linking Pure Lua Modules](#statically-linking-pure-lua-modules) -* [Data Sharing within an Nginx Worker](#data-sharing-within-an-nginx-worker) -* [Known Issues](#known-issues) - * [TCP socket connect operation issues](#tcp-socket-connect-operation-issues) - * [Lua Coroutine Yielding/Resuming](#lua-coroutine-yieldingresuming) - * [Lua Variable Scope](#lua-variable-scope) - * [Locations Configured by Subrequest Directives of Other Modules](#locations-configured-by-subrequest-directives-of-other-modules) - * [Cosockets Not Available Everywhere](#cosockets-not-available-everywhere) - * [Special Escaping Sequences](#special-escaping-sequences) - * [Mixing with SSI Not Supported](#mixing-with-ssi-not-supported) - * [SPDY Mode Not Fully Supported](#spdy-mode-not-fully-supported) - * [Missing data on short circuited requests](#missing-data-on-short-circuited-requests) -* [TODO](#todo) -* [Changes](#changes) -* [Test Suite](#test-suite) -* [Copyright and License](#copyright-and-license) -* [See Also](#see-also) -* [Directives](#directives) -* [Nginx API for Lua](#nginx-api-for-lua) -* [Obsolete Sections](#obsolete-sections) - * [Special PCRE Sequences](#special-pcre-sequences) - -Status -====== - -Production ready. - -Version -======= - -This document describes ngx_lua [v0.10.13](https://github.com/openresty/lua-nginx-module/tags) released on 22 April 2018. - -Synopsis -======== -```nginx - - # set search paths for pure Lua external libraries (';;' is the default path): - lua_package_path '/foo/bar/?.lua;/blah/?.lua;;'; - - # set search paths for Lua external libraries written in C (can also use ';;'): - lua_package_cpath '/bar/baz/?.so;/blah/blah/?.so;;'; - - server { - location /lua_content { - # MIME type determined by default_type: - default_type 'text/plain'; - - content_by_lua_block { - ngx.say('Hello,world!') - } - } - - location /nginx_var { - # MIME type determined by default_type: - default_type 'text/plain'; - - # try access /nginx_var?a=hello,world - content_by_lua_block { - ngx.say(ngx.var.arg_a) - } - } - - location = /request_body { - client_max_body_size 50k; - client_body_buffer_size 50k; - - content_by_lua_block { - ngx.req.read_body() -- explicitly read the req body - local data = ngx.req.get_body_data() - if data then - ngx.say("body data:") - ngx.print(data) - return - end - - -- body may get buffered in a temp file: - local file = ngx.req.get_body_file() - if file then - ngx.say("body is in file ", file) - else - ngx.say("no body found") - end - } - } - - # transparent non-blocking I/O in Lua via subrequests - # (well, a better way is to use cosockets) - location = /lua { - # MIME type determined by default_type: - default_type 'text/plain'; - - content_by_lua_block { - local res = ngx.location.capture("/some_other_location") - if res then - ngx.say("status: ", res.status) - ngx.say("body:") - ngx.print(res.body) - end - } - } - - location = /foo { - rewrite_by_lua_block { - res = ngx.location.capture("/memc", - { args = { cmd = "incr", key = ngx.var.uri } } - ) - } - - proxy_pass http://blah.blah.com; - } - - location = /mixed { - rewrite_by_lua_file /path/to/rewrite.lua; - access_by_lua_file /path/to/access.lua; - content_by_lua_file /path/to/content.lua; - } - - # use nginx var in code path - # CAUTION: contents in nginx var must be carefully filtered, - # otherwise there'll be great security risk! - location ~ ^/app/([-_a-zA-Z0-9/]+) { - set $path $1; - content_by_lua_file /path/to/lua/app/root/$path.lua; - } - - location / { - client_max_body_size 100k; - client_body_buffer_size 100k; - - access_by_lua_block { - -- check the client IP address is in our black list - if ngx.var.remote_addr == "132.5.72.3" then - ngx.exit(ngx.HTTP_FORBIDDEN) - end - - -- check if the URI contains bad words - if ngx.var.uri and - string.match(ngx.var.request_body, "evil") - then - return ngx.redirect("/terms_of_use.html") - end - - -- tests passed - } - - # proxy_pass/fastcgi_pass/etc settings - } - } -``` - -[Back to TOC](#table-of-contents) - -Description -=========== - -This module embeds Lua, via the standard Lua 5.1 interpreter or [LuaJIT 2.0/2.1](http://luajit.org/luajit.html), into Nginx and by leveraging Nginx's subrequests, allows the integration of the powerful Lua threads (Lua coroutines) into the Nginx event model. - -Unlike [Apache's mod_lua](https://httpd.apache.org/docs/trunk/mod/mod_lua.html) and [Lighttpd's mod_magnet](http://redmine.lighttpd.net/wiki/1/Docs:ModMagnet), Lua code executed using this module can be *100% non-blocking* on network traffic as long as the [Nginx API for Lua](#nginx-api-for-lua) provided by this module is used to handle -requests to upstream services such as MySQL, PostgreSQL, Memcached, Redis, or upstream HTTP web services. - -At least the following Lua libraries and Nginx modules can be used with this ngx_lua module: - -* [lua-resty-memcached](https://github.com/openresty/lua-resty-memcached) -* [lua-resty-mysql](https://github.com/openresty/lua-resty-mysql) -* [lua-resty-redis](https://github.com/openresty/lua-resty-redis) -* [lua-resty-dns](https://github.com/openresty/lua-resty-dns) -* [lua-resty-upload](https://github.com/openresty/lua-resty-upload) -* [lua-resty-websocket](https://github.com/openresty/lua-resty-websocket) -* [lua-resty-lock](https://github.com/openresty/lua-resty-lock) -* [lua-resty-logger-socket](https://github.com/cloudflare/lua-resty-logger-socket) -* [lua-resty-lrucache](https://github.com/openresty/lua-resty-lrucache) -* [lua-resty-string](https://github.com/openresty/lua-resty-string) -* [ngx_memc](http://github.com/openresty/memc-nginx-module) -* [ngx_postgres](https://github.com/FRiCKLE/ngx_postgres) -* [ngx_redis2](http://github.com/openresty/redis2-nginx-module) -* [ngx_redis](http://wiki.nginx.org/HttpRedisModule) -* [ngx_proxy](http://nginx.org/en/docs/http/ngx_http_proxy_module.html) -* [ngx_fastcgi](http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html) - -Almost all the Nginx modules can be used with this ngx_lua module by means of [ngx.location.capture](#ngxlocationcapture) or [ngx.location.capture_multi](#ngxlocationcapture_multi) but it is recommended to use those `lua-resty-*` libraries instead of creating subrequests to access the Nginx upstream modules because the former is usually much more flexible and memory-efficient. - -The Lua interpreter or LuaJIT instance is shared across all the requests in a single nginx worker process but request contexts are segregated using lightweight Lua coroutines. - -Loaded Lua modules persist in the nginx worker process level resulting in a small memory footprint in Lua even when under heavy loads. - -This module is plugged into NGINX's "http" subsystem so it can only speaks downstream communication protocols in the HTTP family (HTTP 0.9/1.0/1.1/2.0, WebSockets, and etc). -If you want to do generic TCP communications with the downstream clients, then you should use the [ngx_stream_lua](https://github.com/openresty/stream-lua-nginx-module#readme) module instead -which has a compatible Lua API. - -[Back to TOC](#table-of-contents) - -Typical Uses -============ - -Just to name a few: - -* Mashup'ing and processing outputs of various nginx upstream outputs (proxy, drizzle, postgres, redis, memcached, and etc) in Lua, -* doing arbitrarily complex access control and security checks in Lua before requests actually reach the upstream backends, -* manipulating response headers in an arbitrary way (by Lua) -* fetching backend information from external storage backends (like redis, memcached, mysql, postgresql) and use that information to choose which upstream backend to access on-the-fly, -* coding up arbitrarily complex web applications in a content handler using synchronous but still non-blocking access to the database backends and other storage, -* doing very complex URL dispatch in Lua at rewrite phase, -* using Lua to implement advanced caching mechanism for Nginx's subrequests and arbitrary locations. - -The possibilities are unlimited as the module allows bringing together various elements within Nginx as well as exposing the power of the Lua language to the user. The module provides the full flexibility of scripting while offering performance levels comparable with native C language programs both in terms of CPU time as well as memory footprint. This is particularly the case when LuaJIT 2.x is enabled. - -Other scripting language implementations typically struggle to match this performance level. - -The Lua state (Lua VM instance) is shared across all the requests handled by a single nginx worker process to minimize memory use. - -[Back to TOC](#table-of-contents) - -Nginx Compatibility -=================== - -The latest version of this module is compatible with the following versions of Nginx: - -* 1.13.x (last tested: 1.13.6) -* 1.12.x -* 1.11.x (last tested: 1.11.2) -* 1.10.x -* 1.9.x (last tested: 1.9.15) -* 1.8.x -* 1.7.x (last tested: 1.7.10) -* 1.6.x - -Nginx cores older than 1.6.0 (exclusive) are *not* supported. - -[Back to TOC](#table-of-contents) - -Installation -============ - -It is *highly* recommended to use [OpenResty releases](http://openresty.org) which integrate Nginx, ngx_lua, LuaJIT 2.1, as well as other powerful companion Nginx modules and Lua libraries. It is discouraged to build this module with nginx yourself since it is tricky to set up exactly right. Also, the stock nginx cores have various limitations and long standing bugs that can make some of this modules' features become disabled, not work properly, or run slower. The same applies to LuaJIT as well. OpenResty includes its own version of LuaJIT which gets specifically optimized and enhanced for the OpenResty environment. - -Alternatively, ngx_lua can be manually compiled into Nginx: - -1. Install LuaJIT 2.0 or 2.1 (recommended) or Lua 5.1 (Lua 5.2 is *not* supported yet). LuaJIT can be downloaded from the [LuaJIT project website](http://luajit.org/download.html) and Lua 5.1, from the [Lua project website](http://www.lua.org/). Some distribution package managers also distribute LuaJIT and/or Lua. -1. Download the latest version of the ngx_devel_kit (NDK) module [HERE](https://github.com/simplresty/ngx_devel_kit/tags). -1. Download the latest version of ngx_lua [HERE](https://github.com/openresty/lua-nginx-module/tags). -1. Download the latest version of Nginx [HERE](http://nginx.org/) (See [Nginx Compatibility](#nginx-compatibility)) - -Build the source with this module: - -```bash - - wget 'http://nginx.org/download/nginx-1.13.6.tar.gz' - tar -xzvf nginx-1.13.6.tar.gz - cd nginx-1.13.6/ - - # tell nginx's build system where to find LuaJIT 2.0: - export LUAJIT_LIB=/path/to/luajit/lib - export LUAJIT_INC=/path/to/luajit/include/luajit-2.0 - - # tell nginx's build system where to find LuaJIT 2.1: - export LUAJIT_LIB=/path/to/luajit/lib - export LUAJIT_INC=/path/to/luajit/include/luajit-2.1 - - # or tell where to find Lua if using Lua instead: - #export LUA_LIB=/path/to/lua/lib - #export LUA_INC=/path/to/lua/include - - # Here we assume Nginx is to be installed under /opt/nginx/. - ./configure --prefix=/opt/nginx \ - --with-ld-opt="-Wl,-rpath,/path/to/luajit-or-lua/lib" \ - --add-module=/path/to/ngx_devel_kit \ - --add-module=/path/to/lua-nginx-module - - # Note that you may also want to add `./configure` options which are used in your - # current nginx build. - # You can get usually those options using command nginx -V - - # you can change the parallism number 2 below to fit the number of spare CPU cores in your - # machine. - make -j2 - make install -``` - -[Back to TOC](#table-of-contents) - -Building as a dynamic module ----------------------------- - -Starting from NGINX 1.9.11, you can also compile this module as a dynamic module, by using the `--add-dynamic-module=PATH` option instead of `--add-module=PATH` on the -`./configure` command line above. And then you can explicitly load the module in your `nginx.conf` via the [load_module](http://nginx.org/en/docs/ngx_core_module.html#load_module) -directive, for example, - -```nginx - - load_module /path/to/modules/ndk_http_module.so; # assuming NDK is built as a dynamic module too - load_module /path/to/modules/ngx_http_lua_module.so; -``` - -[Back to TOC](#table-of-contents) - -C Macro Configurations ----------------------- - -While building this module either via OpenResty or with the NGINX core, you can define the following C macros via the C compiler options: - -* `NGX_LUA_USE_ASSERT` - When defined, will enable assertions in the ngx_lua C code base. Recommended for debugging or testing builds. It can introduce some (small) runtime overhead when enabled. This macro was first introduced in the `v0.9.10` release. -* `NGX_LUA_ABORT_AT_PANIC` - When the Lua/LuaJIT VM panics, ngx_lua will instruct the current nginx worker process to quit gracefully by default. By specifying this C macro, ngx_lua will abort the current nginx worker process (which usually result in a core dump file) immediately. This option is useful for debugging VM panics. This option was first introduced in the `v0.9.8` release. -* `NGX_LUA_NO_FFI_API` - Excludes pure C API functions for FFI-based Lua API for NGINX (as required by [lua-resty-core](https://github.com/openresty/lua-resty-core#readme), for example). Enabling this macro can make the resulting binary code size smaller. - -To enable one or more of these macros, just pass extra C compiler options to the `./configure` script of either NGINX or OpenResty. For instance, - - - ./configure --with-cc-opt="-DNGX_LUA_USE_ASSERT -DNGX_LUA_ABORT_AT_PANIC" - - -[Back to TOC](#table-of-contents) - -Installation on Ubuntu 11.10 ----------------------------- - -Note that it is recommended to use LuaJIT 2.0 or LuaJIT 2.1 instead of the standard Lua 5.1 interpreter wherever possible. - -If the standard Lua 5.1 interpreter is required however, run the following command to install it from the Ubuntu repository: - -```bash - - apt-get install -y lua5.1 liblua5.1-0 liblua5.1-0-dev -``` - -Everything should be installed correctly, except for one small tweak. - -Library name `liblua.so` has been changed in liblua5.1 package, it only comes with `liblua5.1.so`, which needs to be symlinked to `/usr/lib` so it could be found during the configuration process. - -```bash - - ln -s /usr/lib/x86_64-linux-gnu/liblua5.1.so /usr/lib/liblua.so -``` - -[Back to TOC](#table-of-contents) - -Community -========= - -[Back to TOC](#table-of-contents) - -English Mailing List --------------------- - -The [openresty-en](https://groups.google.com/group/openresty-en) mailing list is for English speakers. - -[Back to TOC](#table-of-contents) - -Chinese Mailing List --------------------- - -The [openresty](https://groups.google.com/group/openresty) mailing list is for Chinese speakers. - -[Back to TOC](#table-of-contents) - -Code Repository -=============== - -The code repository of this project is hosted on github at [openresty/lua-nginx-module](https://github.com/openresty/lua-nginx-module). - -[Back to TOC](#table-of-contents) - -Bugs and Patches -================ - -Please submit bug reports, wishlists, or patches by - -1. creating a ticket on the [GitHub Issue Tracker](https://github.com/openresty/lua-nginx-module/issues), -1. or posting to the [OpenResty community](#community). - -[Back to TOC](#table-of-contents) - -Lua/LuaJIT bytecode support -=========================== - -As from the `v0.5.0rc32` release, all `*_by_lua_file` configure directives (such as [content_by_lua_file](#content_by_lua_file)) support loading Lua 5.1 and LuaJIT 2.0/2.1 raw bytecode files directly. - -Please note that the bytecode format used by LuaJIT 2.0/2.1 is not compatible with that used by the standard Lua 5.1 interpreter. So if using LuaJIT 2.0/2.1 with ngx_lua, LuaJIT compatible bytecode files must be generated as shown: - -```bash - - /path/to/luajit/bin/luajit -b /path/to/input_file.lua /path/to/output_file.ljbc -``` - -The `-bg` option can be used to include debug information in the LuaJIT bytecode file: - -```bash - - /path/to/luajit/bin/luajit -bg /path/to/input_file.lua /path/to/output_file.ljbc -``` - -Please refer to the official LuaJIT documentation on the `-b` option for more details: - - - -Also, the bytecode files generated by LuaJIT 2.1 is *not* compatible with LuaJIT 2.0, and vice versa. The support for LuaJIT 2.1 bytecode was first added in ngx_lua v0.9.3. - -Similarly, if using the standard Lua 5.1 interpreter with ngx_lua, Lua compatible bytecode files must be generated using the `luac` commandline utility as shown: - -```bash - - luac -o /path/to/output_file.luac /path/to/input_file.lua -``` - -Unlike as with LuaJIT, debug information is included in standard Lua 5.1 bytecode files by default. This can be striped out by specifying the `-s` option as shown: - -```bash - - luac -s -o /path/to/output_file.luac /path/to/input_file.lua -``` - -Attempts to load standard Lua 5.1 bytecode files into ngx_lua instances linked to LuaJIT 2.0/2.1 or vice versa, will result in an error message, such as that below, being logged into the Nginx `error.log` file: - - - [error] 13909#0: *1 failed to load Lua inlined code: bad byte-code header in /path/to/test_file.luac - - -Loading bytecode files via the Lua primitives like `require` and `dofile` should always work as expected. - -[Back to TOC](#table-of-contents) - -System Environment Variable Support -=================================== - -If you want to access the system environment variable, say, `foo`, in Lua via the standard Lua API [os.getenv](http://www.lua.org/manual/5.1/manual.html#pdf-os.getenv), then you should also list this environment variable name in your `nginx.conf` file via the [env directive](http://nginx.org/en/docs/ngx_core_module.html#env). For example, - -```nginx - - env foo; -``` - -[Back to TOC](#table-of-contents) - -HTTP 1.0 support -================ - -The HTTP 1.0 protocol does not support chunked output and requires an explicit `Content-Length` header when the response body is not empty in order to support the HTTP 1.0 keep-alive. -So when a HTTP 1.0 request is made and the [lua_http10_buffering](#lua_http10_buffering) directive is turned `on`, ngx_lua will buffer the -output of [ngx.say](#ngxsay) and [ngx.print](#ngxprint) calls and also postpone sending response headers until all the response body output is received. -At that time ngx_lua can calculate the total length of the body and construct a proper `Content-Length` header to return to the HTTP 1.0 client. -If the `Content-Length` response header is set in the running Lua code, however, this buffering will be disabled even if the [lua_http10_buffering](#lua_http10_buffering) directive is turned `on`. - -For large streaming output responses, it is important to disable the [lua_http10_buffering](#lua_http10_buffering) directive to minimise memory usage. - -Note that common HTTP benchmark tools such as `ab` and `http_load` issue HTTP 1.0 requests by default. -To force `curl` to send HTTP 1.0 requests, use the `-0` option. - -[Back to TOC](#table-of-contents) - -Statically Linking Pure Lua Modules -=================================== - -When LuaJIT 2.x is used, it is possible to statically link the bytecode of pure Lua modules into the Nginx executable. - -Basically you use the `luajit` executable to compile `.lua` Lua module files to `.o` object files containing the exported bytecode data, and then link the `.o` files directly in your Nginx build. - -Below is a trivial example to demonstrate this. Consider that we have the following `.lua` file named `foo.lua`: - -```lua - - -- foo.lua - local _M = {} - - function _M.go() - print("Hello from foo") - end - - return _M -``` - -And then we compile this `.lua` file to `foo.o` file: - - /path/to/luajit/bin/luajit -bg foo.lua foo.o - -What matters here is the name of the `.lua` file, which determines how you use this module later on the Lua land. The file name `foo.o` does not matter at all except the `.o` file extension (which tells `luajit` what output format is used). If you want to strip the Lua debug information from the resulting bytecode, you can just specify the `-b` option above instead of `-bg`. - -Then when building Nginx or OpenResty, pass the `--with-ld-opt="foo.o"` option to the `./configure` script: - -```bash - - ./configure --with-ld-opt="/path/to/foo.o" ... -``` - -Finally, you can just do the following in any Lua code run by ngx_lua: - -```lua - - local foo = require "foo" - foo.go() -``` - -And this piece of code no longer depends on the external `foo.lua` file any more because it has already been compiled into the `nginx` executable. - -If you want to use dot in the Lua module name when calling `require`, as in - -```lua - - local foo = require "resty.foo" -``` - -then you need to rename the `foo.lua` file to `resty_foo.lua` before compiling it down to a `.o` file with the `luajit` command-line utility. - -It is important to use exactly the same version of LuaJIT when compiling `.lua` files to `.o` files as building nginx + ngx_lua. This is because the LuaJIT bytecode format may be incompatible between different LuaJIT versions. When the bytecode format is incompatible, you will see a Lua runtime error saying that the Lua module is not found. - -When you have multiple `.lua` files to compile and link, then just specify their `.o` files at the same time in the value of the `--with-ld-opt` option. For instance, - -```bash - - ./configure --with-ld-opt="/path/to/foo.o /path/to/bar.o" ... -``` - -If you have just too many `.o` files, then it might not be feasible to name them all in a single command. In this case, you can build a static library (or archive) for your `.o` files, as in - -```bash - - ar rcus libmyluafiles.a *.o -``` - -then you can link the `myluafiles` archive as a whole to your nginx executable: - -```bash - - ./configure \ - --with-ld-opt="-L/path/to/lib -Wl,--whole-archive -lmyluafiles -Wl,--no-whole-archive" -``` - -where `/path/to/lib` is the path of the directory containing the `libmyluafiles.a` file. It should be noted that the linker option `--whole-archive` is required here because otherwise our archive will be skipped because no symbols in our archive are mentioned in the main parts of the nginx executable. - -[Back to TOC](#table-of-contents) - -Data Sharing within an Nginx Worker -=================================== - -To globally share data among all the requests handled by the same nginx worker process, encapsulate the shared data into a Lua module, use the Lua `require` builtin to import the module, and then manipulate the shared data in Lua. This works because required Lua modules are loaded only once and all coroutines will share the same copy of the module (both its code and data). Note however that Lua global variables (note, not module-level variables) WILL NOT persist between requests because of the one-coroutine-per-request isolation design. - -Here is a complete small example: - -```lua - - -- mydata.lua - local _M = {} - - local data = { - dog = 3, - cat = 4, - pig = 5, - } - - function _M.get_age(name) - return data[name] - end - - return _M -``` - -and then accessing it from `nginx.conf`: - -```nginx - - location /lua { - content_by_lua_block { - local mydata = require "mydata" - ngx.say(mydata.get_age("dog")) - } - } -``` - -The `mydata` module in this example will only be loaded and run on the first request to the location `/lua`, -and all subsequent requests to the same nginx worker process will use the reloaded instance of the -module as well as the same copy of the data in it, until a `HUP` signal is sent to the Nginx master process to force a reload. -This data sharing technique is essential for high performance Lua applications based on this module. - -Note that this data sharing is on a *per-worker* basis and not on a *per-server* basis. That is, when there are multiple nginx worker processes under an Nginx master, data sharing cannot cross the process boundary between these workers. - -It is usually recommended to share read-only data this way. You can also share changeable data among all the concurrent requests of each nginx worker process as -long as there is *no* nonblocking I/O operations (including [ngx.sleep](#ngxsleep)) -in the middle of your calculations. As long as you do not give the -control back to the nginx event loop and ngx_lua's light thread -scheduler (even implicitly), there can never be any race conditions in -between. For this reason, always be very careful when you want to share changeable data on the -worker level. Buggy optimizations can easily lead to hard-to-debug -race conditions under load. - -If server-wide data sharing is required, then use one or more of the following approaches: - -1. Use the [ngx.shared.DICT](#ngxshareddict) API provided by this module. -1. Use only a single nginx worker and a single server (this is however not recommended when there is a multi core CPU or multiple CPUs in a single machine). -1. Use data storage mechanisms such as `memcached`, `redis`, `MySQL` or `PostgreSQL`. [The OpenResty bundle](http://openresty.org) associated with this module comes with a set of companion Nginx modules and Lua libraries that provide interfaces with these data storage mechanisms. - -[Back to TOC](#table-of-contents) - -Known Issues -============ - -[Back to TOC](#table-of-contents) - -TCP socket connect operation issues ------------------------------------ -The [tcpsock:connect](#tcpsockconnect) method may indicate `success` despite connection failures such as with `Connection Refused` errors. - -However, later attempts to manipulate the cosocket object will fail and return the actual error status message generated by the failed connect operation. - -This issue is due to limitations in the Nginx event model and only appears to affect Mac OS X. - -[Back to TOC](#table-of-contents) - -Lua Coroutine Yielding/Resuming -------------------------------- -* Because Lua's `dofile` and `require` builtins are currently implemented as C functions in both Lua 5.1 and LuaJIT 2.0/2.1, if the Lua file being loaded by `dofile` or `require` invokes [ngx.location.capture*](#ngxlocationcapture), [ngx.exec](#ngxexec), [ngx.exit](#ngxexit), or other API functions requiring yielding in the *top-level* scope of the Lua file, then the Lua error "attempt to yield across C-call boundary" will be raised. To avoid this, put these calls requiring yielding into your own Lua functions in the Lua file instead of the top-level scope of the file. -* As the standard Lua 5.1 interpreter's VM is not fully resumable, the methods [ngx.location.capture](#ngxlocationcapture), [ngx.location.capture_multi](#ngxlocationcapture_multi), [ngx.redirect](#ngxredirect), [ngx.exec](#ngxexec), and [ngx.exit](#ngxexit) cannot be used within the context of a Lua [pcall()](http://www.lua.org/manual/5.1/manual.html#pdf-pcall) or [xpcall()](http://www.lua.org/manual/5.1/manual.html#pdf-xpcall) or even the first line of the `for ... in ...` statement when the standard Lua 5.1 interpreter is used and the `attempt to yield across metamethod/C-call boundary` error will be produced. Please use LuaJIT 2.x, which supports a fully resumable VM, to avoid this. - -[Back to TOC](#table-of-contents) - -Lua Variable Scope ------------------- -Care must be taken when importing modules and this form should be used: - -```lua - - local xxx = require('xxx') -``` - -instead of the old deprecated form: - -```lua - - require('xxx') -``` - -Here is the reason: by design, the global environment has exactly the same lifetime as the Nginx request handler associated with it. Each request handler has its own set of Lua global variables and that is the idea of request isolation. The Lua module is actually loaded by the first Nginx request handler and is cached by the `require()` built-in in the `package.loaded` table for later reference, and the `module()` builtin used by some Lua modules has the side effect of setting a global variable to the loaded module table. But this global variable will be cleared at the end of the request handler, and every subsequent request handler all has its own (clean) global environment. So one will get Lua exception for accessing the `nil` value. - -The use of Lua global variables is a generally inadvisable in the ngx_lua context as: - -1. the misuse of Lua globals has detrimental side effects on concurrent requests when such variables should instead be local in scope, -1. Lua global variables require Lua table look-ups in the global environment which is computationally expensive, and -1. some Lua global variable references may include typing errors which make such difficult to debug. - -It is therefore *highly* recommended to always declare such within an appropriate local scope instead. - -```lua - - -- Avoid - foo = 123 - -- Recommended - local foo = 123 - - -- Avoid - function foo() return 123 end - -- Recommended - local function foo() return 123 end -``` - - -To find all instances of Lua global variables in your Lua code, run the [lua-releng tool](https://github.com/openresty/nginx-devel-utils/blob/master/lua-releng) across all `.lua` source files: - - $ lua-releng - Checking use of Lua global variables in file lib/foo/bar.lua ... - 1 [1489] SETGLOBAL 7 -1 ; contains - 55 [1506] GETGLOBAL 7 -3 ; setvar - 3 [1545] GETGLOBAL 3 -4 ; varexpand - -The output says that the line 1489 of file `lib/foo/bar.lua` writes to a global variable named `contains`, the line 1506 reads from the global variable `setvar`, and line 1545 reads the global `varexpand`. - -This tool will guarantee that local variables in the Lua module functions are all declared with the `local` keyword, otherwise a runtime exception will be thrown. It prevents undesirable race conditions while accessing such variables. See [Data Sharing within an Nginx Worker](#data-sharing-within-an-nginx-worker) for the reasons behind this. - -[Back to TOC](#table-of-contents) - -Locations Configured by Subrequest Directives of Other Modules --------------------------------------------------------------- -The [ngx.location.capture](#ngxlocationcapture) and [ngx.location.capture_multi](#ngxlocationcapture_multi) directives cannot capture locations that include the [add_before_body](http://nginx.org/en/docs/http/ngx_http_addition_module.html#add_before_body), [add_after_body](http://nginx.org/en/docs/http/ngx_http_addition_module.html#add_after_body), [auth_request](http://nginx.org/en/docs/http/ngx_http_auth_request_module.html#auth_request), [echo_location](http://github.com/openresty/echo-nginx-module#echo_location), [echo_location_async](http://github.com/openresty/echo-nginx-module#echo_location_async), [echo_subrequest](http://github.com/openresty/echo-nginx-module#echo_subrequest), or [echo_subrequest_async](http://github.com/openresty/echo-nginx-module#echo_subrequest_async) directives. - -```nginx - - location /foo { - content_by_lua_block { - res = ngx.location.capture("/bar") - } - } - location /bar { - echo_location /blah; - } - location /blah { - echo "Success!"; - } -``` - -```nginx - - $ curl -i http://example.com/foo -``` - -will not work as expected. - -[Back to TOC](#table-of-contents) - -Cosockets Not Available Everywhere ----------------------------------- - -Due to internal limitations in the nginx core, the cosocket API is disabled in the following contexts: [set_by_lua*](#set_by_lua), [log_by_lua*](#log_by_lua), [header_filter_by_lua*](#header_filter_by_lua), and [body_filter_by_lua](#body_filter_by_lua). - -The cosockets are currently also disabled in the [init_by_lua*](#init_by_lua) and [init_worker_by_lua*](#init_worker_by_lua) directive contexts but we may add support for these contexts in the future because there is no limitation in the nginx core (or the limitation might be worked around). - -There exists a work-around, however, when the original context does *not* need to wait for the cosocket results. That is, creating a zero-delay timer via the [ngx.timer.at](#ngxtimerat) API and do the cosocket results in the timer handler, which runs asynchronously as to the original context creating the timer. - -[Back to TOC](#table-of-contents) - -Special Escaping Sequences --------------------------- - -**NOTE** Following the `v0.9.17` release, this pitfall can be avoided by using the `*_by_lua_block {}` configuration directives. - -PCRE sequences such as `\d`, `\s`, or `\w`, require special attention because in string literals, the backslash character, `\`, is stripped out by both the Lua language parser and by the nginx config file parser before processing if not within a `*_by_lua_block {}` directive. So the following snippet will not work as expected: - -```nginx - - # nginx.conf - ? location /test { - ? content_by_lua ' - ? local regex = "\d+" -- THIS IS WRONG OUTSIDE OF A *_by_lua_block DIRECTIVE - ? local m = ngx.re.match("hello, 1234", regex) - ? if m then ngx.say(m[0]) else ngx.say("not matched!") end - ? '; - ? } - # evaluates to "not matched!" -``` - -To avoid this, *double* escape the backslash: - -```nginx - - # nginx.conf - location /test { - content_by_lua ' - local regex = "\\\\d+" - local m = ngx.re.match("hello, 1234", regex) - if m then ngx.say(m[0]) else ngx.say("not matched!") end - '; - } - # evaluates to "1234" -``` - -Here, `\\\\d+` is stripped down to `\\d+` by the Nginx config file parser and this is further stripped down to `\d+` by the Lua language parser before running. - -Alternatively, the regex pattern can be presented as a long-bracketed Lua string literal by encasing it in "long brackets", `[[...]]`, in which case backslashes have to only be escaped once for the Nginx config file parser. - -```nginx - - # nginx.conf - location /test { - content_by_lua ' - local regex = [[\\d+]] - local m = ngx.re.match("hello, 1234", regex) - if m then ngx.say(m[0]) else ngx.say("not matched!") end - '; - } - # evaluates to "1234" -``` - -Here, `[[\\d+]]` is stripped down to `[[\d+]]` by the Nginx config file parser and this is processed correctly. - -Note that a longer from of the long bracket, `[=[...]=]`, may be required if the regex pattern contains `[...]` sequences. -The `[=[...]=]` form may be used as the default form if desired. - -```nginx - - # nginx.conf - location /test { - content_by_lua ' - local regex = [=[[0-9]+]=] - local m = ngx.re.match("hello, 1234", regex) - if m then ngx.say(m[0]) else ngx.say("not matched!") end - '; - } - # evaluates to "1234" -``` - -An alternative approach to escaping PCRE sequences is to ensure that Lua code is placed in external script files and executed using the various `*_by_lua_file` directives. -With this approach, the backslashes are only stripped by the Lua language parser and therefore only need to be escaped once each. - -```lua - - -- test.lua - local regex = "\\d+" - local m = ngx.re.match("hello, 1234", regex) - if m then ngx.say(m[0]) else ngx.say("not matched!") end - -- evaluates to "1234" -``` - -Within external script files, PCRE sequences presented as long-bracketed Lua string literals do not require modification. - -```lua - - -- test.lua - local regex = [[\d+]] - local m = ngx.re.match("hello, 1234", regex) - if m then ngx.say(m[0]) else ngx.say("not matched!") end - -- evaluates to "1234" -``` - -As noted earlier, PCRE sequences presented within `*_by_lua_block {}` directives (available following the `v0.9.17` release) do not require modification. - -```nginx - - # nginx.conf - location /test { - content_by_lua_block { - local regex = [[\d+]] - local m = ngx.re.match("hello, 1234", regex) - if m then ngx.say(m[0]) else ngx.say("not matched!") end - } - } - # evaluates to "1234" -``` - - -[Back to TOC](#table-of-contents) - -Mixing with SSI Not Supported ------------------------------ - -Mixing SSI with ngx_lua in the same Nginx request is not supported at all. Just use ngx_lua exclusively. Everything you can do with SSI can be done atop ngx_lua anyway and it can be more efficient when using ngx_lua. - -[Back to TOC](#table-of-contents) - -SPDY Mode Not Fully Supported ------------------------------ - -Certain Lua APIs provided by ngx_lua do not work in Nginx's SPDY mode yet: [ngx.location.capture](#ngxlocationcapture), [ngx.location.capture_multi](#ngxlocationcapture_multi), and [ngx.req.socket](#ngxreqsocket). - -[Back to TOC](#table-of-contents) - -Missing data on short circuited requests ----------------------------------------- - -Nginx may terminate a request early with (at least): - -* 400 (Bad Request) -* 405 (Not Allowed) -* 408 (Request Timeout) -* 413 (Request Entity Too Large) -* 414 (Request URI Too Large) -* 494 (Request Headers Too Large) -* 499 (Client Closed Request) -* 500 (Internal Server Error) -* 501 (Not Implemented) - -This means that phases that normally run are skipped, such as the rewrite or -access phase. This also means that later phases that are run regardless, e.g. -[log_by_lua](#log_by_lua), will not have access to information that is normally set in those -phases. - -[Back to TOC](#table-of-contents) - -TODO -==== - -* cosocket: implement LuaSocket's unconnected UDP API. -* port this module to the "datagram" subsystem of NGINX for implementing general UDP servers instead of HTTP -servers in Lua. For example, -```lua - - datagram { - server { - listen 1953; - handler_by_lua_block { - -- custom Lua code implementing the special UDP server... - } - } - } -``` -* shm: implement a "shared queue API" to complement the existing [shared dict](#lua_shared_dict) API. -* cosocket: add support in the context of [init_by_lua*](#init_by_lua). -* cosocket: implement the `bind()` method for stream-typed cosockets. -* cosocket: pool-based backend concurrency level control: implement automatic `connect` queueing when the backend concurrency exceeds its connection pool limit. -* cosocket: review and merge aviramc's [patch](https://github.com/openresty/lua-nginx-module/pull/290) for adding the `bsdrecv` method. -* add new API function `ngx.resp.add_header` to emulate the standard `add_header` config directive. -* review and apply vadim-pavlov's patch for [ngx.location.capture](#ngxlocationcapture)'s `extra_headers` option -* use `ngx_hash_t` to optimize the built-in header look-up process for [ngx.req.set_header](#ngxreqset_header), [ngx.header.HEADER](#ngxheaderheader), and etc. -* add configure options for different strategies of handling the cosocket connection exceeding in the pools. -* add directives to run Lua codes when nginx stops. -* add `ignore_resp_headers`, `ignore_resp_body`, and `ignore_resp` options to [ngx.location.capture](#ngxlocationcapture) and [ngx.location.capture_multi](#ngxlocationcapture_multi) methods, to allow micro performance tuning on the user side. -* add automatic Lua code time slicing support by yielding and resuming the Lua VM actively via Lua's debug hooks. -* add `stat` mode similar to [mod_lua](https://httpd.apache.org/docs/trunk/mod/mod_lua.html). -* cosocket: add client SSL certificate support. - -[Back to TOC](#table-of-contents) - -Changes -======= - -The changes made in every release of this module are listed in the change logs of the OpenResty bundle: - - - -[Back to TOC](#table-of-contents) - -Test Suite -========== - -The following dependencies are required to run the test suite: - -* Nginx version >= 1.4.2 - -* Perl modules: - * Test::Nginx: - -* Nginx modules: - * [ngx_devel_kit](https://github.com/simplresty/ngx_devel_kit) - * [ngx_set_misc](https://github.com/openresty/set-misc-nginx-module) - * [ngx_auth_request](http://mdounin.ru/files/ngx_http_auth_request_module-0.2.tar.gz) (this is not needed if you're using Nginx 1.5.4+. - * [ngx_echo](https://github.com/openresty/echo-nginx-module) - * [ngx_memc](https://github.com/openresty/memc-nginx-module) - * [ngx_srcache](https://github.com/openresty/srcache-nginx-module) - * ngx_lua (i.e., this module) - * [ngx_lua_upstream](https://github.com/openresty/lua-upstream-nginx-module) - * [ngx_headers_more](https://github.com/openresty/headers-more-nginx-module) - * [ngx_drizzle](https://github.com/openresty/drizzle-nginx-module) - * [ngx_rds_json](https://github.com/openresty/rds-json-nginx-module) - * [ngx_coolkit](https://github.com/FRiCKLE/ngx_coolkit) - * [ngx_redis2](https://github.com/openresty/redis2-nginx-module) - -The order in which these modules are added during configuration is important because the position of any filter module in the -filtering chain determines the final output, for example. The correct adding order is shown above. - -* 3rd-party Lua libraries: - * [lua-cjson](http://www.kyne.com.au/~mark/software/lua-cjson.php) - -* Applications: - * mysql: create database 'ngx_test', grant all privileges to user 'ngx_test', password is 'ngx_test' - * memcached: listening on the default port, 11211. - * redis: listening on the default port, 6379. - -See also the [developer build script](https://github.com/openresty/lua-nginx-module/blob/master/util/build.sh) for more details on setting up the testing environment. - -To run the whole test suite in the default testing mode: - - cd /path/to/lua-nginx-module - export PATH=/path/to/your/nginx/sbin:$PATH - prove -I/path/to/test-nginx/lib -r t - - -To run specific test files: - - cd /path/to/lua-nginx-module - export PATH=/path/to/your/nginx/sbin:$PATH - prove -I/path/to/test-nginx/lib t/002-content.t t/003-errors.t - - -To run a specific test block in a particular test file, add the line `--- ONLY` to the test block you want to run, and then use the `prove` utility to run that `.t` file. - -There are also various testing modes based on mockeagain, valgrind, and etc. Refer to the [Test::Nginx documentation](http://search.cpan.org/perldoc?Test::Nginx) for more details for various advanced testing modes. See also the test reports for the Nginx test cluster running on Amazon EC2: . - -[Back to TOC](#table-of-contents) - -Copyright and License -===================== - -This module is licensed under the BSD license. - -Copyright (C) 2009-2017, by Xiaozhe Wang (chaoslawful) . - -Copyright (C) 2009-2018, by Yichun "agentzh" Zhang (章亦春) , OpenResty Inc. - -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright 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 THE COPYRIGHT HOLDERS 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 THE COPYRIGHT HOLDER 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) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -[Back to TOC](#table-of-contents) - -See Also -======== - -* [ngx_stream_lua_module](https://github.com/openresty/stream-lua-nginx-module#readme) for an official port of this module for the NGINX "stream" subsystem (doing generic downstream TCP communications). -* [lua-resty-memcached](https://github.com/openresty/lua-resty-memcached) library based on ngx_lua cosocket. -* [lua-resty-redis](https://github.com/openresty/lua-resty-redis) library based on ngx_lua cosocket. -* [lua-resty-mysql](https://github.com/openresty/lua-resty-mysql) library based on ngx_lua cosocket. -* [lua-resty-upload](https://github.com/openresty/lua-resty-upload) library based on ngx_lua cosocket. -* [lua-resty-dns](https://github.com/openresty/lua-resty-dns) library based on ngx_lua cosocket. -* [lua-resty-websocket](https://github.com/openresty/lua-resty-websocket) library for both WebSocket server and client, based on ngx_lua cosocket. -* [lua-resty-string](https://github.com/openresty/lua-resty-string) library based on [LuaJIT FFI](http://luajit.org/ext_ffi.html). -* [lua-resty-lock](https://github.com/openresty/lua-resty-lock) library for a nonblocking simple lock API. -* [lua-resty-cookie](https://github.com/cloudflare/lua-resty-cookie) library for HTTP cookie manipulation. -* [Routing requests to different MySQL queries based on URI arguments](http://openresty.org/#RoutingMySQLQueriesBasedOnURIArgs) -* [Dynamic Routing Based on Redis and Lua](http://openresty.org/#DynamicRoutingBasedOnRedis) -* [Using LuaRocks with ngx_lua](http://openresty.org/#UsingLuaRocks) -* [Introduction to ngx_lua](https://github.com/openresty/lua-nginx-module/wiki/Introduction) -* [ngx_devel_kit](https://github.com/simplresty/ngx_devel_kit) -* [echo-nginx-module](http://github.com/openresty/echo-nginx-module) -* [drizzle-nginx-module](http://github.com/openresty/drizzle-nginx-module) -* [postgres-nginx-module](https://github.com/FRiCKLE/ngx_postgres) -* [memc-nginx-module](http://github.com/openresty/memc-nginx-module) -* [The OpenResty bundle](http://openresty.org) -* [Nginx Systemtap Toolkit](https://github.com/openresty/nginx-systemtap-toolkit) - -[Back to TOC](#table-of-contents) - -Directives -========== - -* [lua_capture_error_log](#lua_capture_error_log) -* [lua_use_default_type](#lua_use_default_type) -* [lua_malloc_trim](#lua_malloc_trim) -* [lua_code_cache](#lua_code_cache) -* [lua_regex_cache_max_entries](#lua_regex_cache_max_entries) -* [lua_regex_match_limit](#lua_regex_match_limit) -* [lua_package_path](#lua_package_path) -* [lua_package_cpath](#lua_package_cpath) -* [init_by_lua](#init_by_lua) -* [init_by_lua_block](#init_by_lua_block) -* [init_by_lua_file](#init_by_lua_file) -* [init_worker_by_lua](#init_worker_by_lua) -* [init_worker_by_lua_block](#init_worker_by_lua_block) -* [init_worker_by_lua_file](#init_worker_by_lua_file) -* [set_by_lua](#set_by_lua) -* [set_by_lua_block](#set_by_lua_block) -* [set_by_lua_file](#set_by_lua_file) -* [content_by_lua](#content_by_lua) -* [content_by_lua_block](#content_by_lua_block) -* [content_by_lua_file](#content_by_lua_file) -* [rewrite_by_lua](#rewrite_by_lua) -* [rewrite_by_lua_block](#rewrite_by_lua_block) -* [rewrite_by_lua_file](#rewrite_by_lua_file) -* [access_by_lua](#access_by_lua) -* [access_by_lua_block](#access_by_lua_block) -* [access_by_lua_file](#access_by_lua_file) -* [header_filter_by_lua](#header_filter_by_lua) -* [header_filter_by_lua_block](#header_filter_by_lua_block) -* [header_filter_by_lua_file](#header_filter_by_lua_file) -* [body_filter_by_lua](#body_filter_by_lua) -* [body_filter_by_lua_block](#body_filter_by_lua_block) -* [body_filter_by_lua_file](#body_filter_by_lua_file) -* [log_by_lua](#log_by_lua) -* [log_by_lua_block](#log_by_lua_block) -* [log_by_lua_file](#log_by_lua_file) -* [balancer_by_lua_block](#balancer_by_lua_block) -* [balancer_by_lua_file](#balancer_by_lua_file) -* [lua_need_request_body](#lua_need_request_body) -* [ssl_certificate_by_lua_block](#ssl_certificate_by_lua_block) -* [ssl_certificate_by_lua_file](#ssl_certificate_by_lua_file) -* [ssl_session_fetch_by_lua_block](#ssl_session_fetch_by_lua_block) -* [ssl_session_fetch_by_lua_file](#ssl_session_fetch_by_lua_file) -* [ssl_session_store_by_lua_block](#ssl_session_store_by_lua_block) -* [ssl_session_store_by_lua_file](#ssl_session_store_by_lua_file) -* [lua_shared_dict](#lua_shared_dict) -* [lua_socket_connect_timeout](#lua_socket_connect_timeout) -* [lua_socket_send_timeout](#lua_socket_send_timeout) -* [lua_socket_send_lowat](#lua_socket_send_lowat) -* [lua_socket_read_timeout](#lua_socket_read_timeout) -* [lua_socket_buffer_size](#lua_socket_buffer_size) -* [lua_socket_pool_size](#lua_socket_pool_size) -* [lua_socket_keepalive_timeout](#lua_socket_keepalive_timeout) -* [lua_socket_log_errors](#lua_socket_log_errors) -* [lua_ssl_ciphers](#lua_ssl_ciphers) -* [lua_ssl_crl](#lua_ssl_crl) -* [lua_ssl_protocols](#lua_ssl_protocols) -* [lua_ssl_trusted_certificate](#lua_ssl_trusted_certificate) -* [lua_ssl_verify_depth](#lua_ssl_verify_depth) -* [lua_http10_buffering](#lua_http10_buffering) -* [rewrite_by_lua_no_postpone](#rewrite_by_lua_no_postpone) -* [access_by_lua_no_postpone](#access_by_lua_no_postpone) -* [lua_transform_underscores_in_response_headers](#lua_transform_underscores_in_response_headers) -* [lua_check_client_abort](#lua_check_client_abort) -* [lua_max_pending_timers](#lua_max_pending_timers) -* [lua_max_running_timers](#lua_max_running_timers) - - -The basic building blocks of scripting Nginx with Lua are directives. Directives are used to specify when the user Lua code is run and -how the result will be used. Below is a diagram showing the order in which directives are executed. - -![Lua Nginx Modules Directives](https://cloud.githubusercontent.com/assets/2137369/15272097/77d1c09e-1a37-11e6-97ef-d9767035fc3e.png) - -[Back to TOC](#table-of-contents) - -lua_capture_error_log ---------------------- -**syntax:** *lua_capture_error_log size* - -**default:** *none* - -**context:** *http* - -Enables a buffer of the specified `size` for capturing all the nginx error log message data (not just those produced -by this module or the nginx http subsystem, but everything) without touching files or disks. - -You can use units like `k` and `m` in the `size` value, as in - -```nginx - - lua_capture_error_log 100k; -``` - -As a rule of thumb, a 4KB buffer can usually hold about 20 typical error log messages. So do the maths! - -This buffer never grows. If it is full, new error log messages will replace the oldest ones in the buffer. - -The size of the buffer must be bigger than the maximum length of a single error log message (which is 4K in OpenResty and 2K in stock NGINX). - -You can read the messages in the buffer on the Lua land via the -[get_logs()](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/errlog.md#get_logs) -function of the -[ngx.errlog](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/errlog.md#readme) -module of the [lua-resty-core](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/errlog.md#readme) -library. This Lua API function will return the captured error log messages and -also remove these already read from the global capturing buffer, making room -for any new error log data. For this reason, the user should not configure this -buffer to be too big if the user read the buffered error log data fast enough. - -Note that the log level specified in the standard [error_log](http://nginx.org/r/error_log) directive -*does* have effect on this capturing facility. It only captures log -messages of a level no lower than the specified log level in the [error_log](http://nginx.org/r/error_log) directive. -The user can still choose to set an even higher filtering log level on the fly via the Lua API function -[errlog.set_filter_level](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/errlog.md#set_filter_level). -So it is more flexible than the static [error_log](http://nginx.org/r/error_log) directive. - -It is worth noting that there is no way to capture the debugging logs -without building OpenResty or NGINX with the `./configure` -option `--with-debug`. And enabling debugging logs is -strongly discouraged in production builds due to high overhead. - -This directive was first introduced in the `v0.10.9` release. - -[Back to TOC](#directives) - -lua_use_default_type --------------------- -**syntax:** *lua_use_default_type on | off* - -**default:** *lua_use_default_type on* - -**context:** *http, server, location, location if* - -Specifies whether to use the MIME type specified by the [default_type](http://nginx.org/en/docs/http/ngx_http_core_module.html#default_type) directive for the default value of the `Content-Type` response header. Deactivate this directive if a default `Content-Type` response header for Lua request handlers is not desired. - -This directive is turned on by default. - -This directive was first introduced in the `v0.9.1` release. - -[Back to TOC](#directives) - -lua_malloc_trim ---------------- -**syntax:** *lua_malloc_trim <request-count>* - -**default:** *lua_malloc_trim 1000* - -**context:** *http* - -Asks the underlying `libc` runtime library to release its cached free memory back to the operating system every -`N` requests processed by the NGINX core. By default, `N` is 1000. You can configure the request count -by using your own numbers. Smaller numbers mean more frequent releases, which may introduce higher CPU time consumption and -smaller memory footprint while larger numbers usually lead to less CPU time overhead and relatively larger memory footprint. -Just tune the number for your own use cases. - -Configuring the argument to `0` essentially turns off the periodical memory trimming altogether. - -```nginx - - lua_malloc_trim 0; # turn off trimming completely -``` - -The current implementation uses an NGINX log phase handler to do the request counting. So the appearance of the -[log_subrequest on](http://nginx.org/en/docs/http/ngx_http_core_module.html#log_subrequest) directives in `nginx.conf` -may make the counting faster when subrequests are involved. By default, only "main requests" count. - -Note that this directive does *not* affect the memory allocated by LuaJIT's own allocator based on the `mmap` -system call. - -This directive was first introduced in the `v0.10.7` release. - -[Back to TOC](#directives) - -lua_code_cache --------------- -**syntax:** *lua_code_cache on | off* - -**default:** *lua_code_cache on* - -**context:** *http, server, location, location if* - -Enables or disables the Lua code cache for Lua code in `*_by_lua_file` directives (like [set_by_lua_file](#set_by_lua_file) and -[content_by_lua_file](#content_by_lua_file)) and Lua modules. - -When turning off, every request served by ngx_lua will run in a separate Lua VM instance, starting from the `0.9.3` release. So the Lua files referenced in [set_by_lua_file](#set_by_lua_file), -[content_by_lua_file](#content_by_lua_file), [access_by_lua_file](#access_by_lua_file), -and etc will not be cached -and all Lua modules used will be loaded from scratch. With this in place, developers can adopt an edit-and-refresh approach. - -Please note however, that Lua code written inlined within nginx.conf -such as those specified by [set_by_lua](#set_by_lua), [content_by_lua](#content_by_lua), -[access_by_lua](#access_by_lua), and [rewrite_by_lua](#rewrite_by_lua) will not be updated when you edit the inlined Lua code in your `nginx.conf` file because only the Nginx config file parser can correctly parse the `nginx.conf` -file and the only way is to reload the config file -by sending a `HUP` signal or just to restart Nginx. - -Even when the code cache is enabled, Lua files which are loaded by `dofile` or `loadfile` -in *_by_lua_file cannot be cached (unless you cache the results yourself). Usually you can either use the [init_by_lua](#init_by_lua) -or [init_by_lua_file](#init-by_lua_file) directives to load all such files or just make these Lua files true Lua modules -and load them via `require`. - -The ngx_lua module does not support the `stat` mode available with the -Apache `mod_lua` module (yet). - -Disabling the Lua code cache is strongly -discouraged for production use and should only be used during -development as it has a significant negative impact on overall performance. For example, the performance of a "hello world" Lua example can drop by an order of magnitude after disabling the Lua code cache. - -[Back to TOC](#directives) - -lua_regex_cache_max_entries ---------------------------- -**syntax:** *lua_regex_cache_max_entries <num>* - -**default:** *lua_regex_cache_max_entries 1024* - -**context:** *http* - -Specifies the maximum number of entries allowed in the worker process level compiled regex cache. - -The regular expressions used in [ngx.re.match](#ngxrematch), [ngx.re.gmatch](#ngxregmatch), [ngx.re.sub](#ngxresub), and [ngx.re.gsub](#ngxregsub) will be cached within this cache if the regex option `o` (i.e., compile-once flag) is specified. - -The default number of entries allowed is 1024 and when this limit is reached, new regular expressions will not be cached (as if the `o` option was not specified) and there will be one, and only one, warning in the `error.log` file: - - - 2011/08/27 23:18:26 [warn] 31997#0: *1 lua exceeding regex cache max entries (1024), ... - - -If you are using the `ngx.re.*` implementation of [lua-resty-core](https://github.com/openresty/lua-resty-core) by loading the `resty.core.regex` module (or just the `resty.core` module), then an LRU cache is used for the regex cache being used here. - -Do not activate the `o` option for regular expressions (and/or `replace` string arguments for [ngx.re.sub](#ngxresub) and [ngx.re.gsub](#ngxregsub)) that are generated *on the fly* and give rise to infinite variations to avoid hitting the specified limit. - -[Back to TOC](#directives) - -lua_regex_match_limit ---------------------- -**syntax:** *lua_regex_match_limit <num>* - -**default:** *lua_regex_match_limit 0* - -**context:** *http* - -Specifies the "match limit" used by the PCRE library when executing the [ngx.re API](#ngxrematch). To quote the PCRE manpage, "the limit ... has the effect of limiting the amount of backtracking that can take place." - -When the limit is hit, the error string "pcre_exec() failed: -8" will be returned by the [ngx.re API](#ngxrematch) functions on the Lua land. - -When setting the limit to 0, the default "match limit" when compiling the PCRE library is used. And this is the default value of this directive. - -This directive was first introduced in the `v0.8.5` release. - -[Back to TOC](#directives) - -lua_package_path ----------------- - -**syntax:** *lua_package_path <lua-style-path-str>* - -**default:** *The content of LUA_PATH environment variable or Lua's compiled-in defaults.* - -**context:** *http* - -Sets the Lua module search path used by scripts specified by [set_by_lua](#set_by_lua), -[content_by_lua](#content_by_lua) and others. The path string is in standard Lua path form, and `;;` -can be used to stand for the original search paths. - -As from the `v0.5.0rc29` release, the special notation `$prefix` or `${prefix}` can be used in the search path string to indicate the path of the `server prefix` usually determined by the `-p PATH` command-line option while starting the Nginx server. - -[Back to TOC](#directives) - -lua_package_cpath ------------------ - -**syntax:** *lua_package_cpath <lua-style-cpath-str>* - -**default:** *The content of LUA_CPATH environment variable or Lua's compiled-in defaults.* - -**context:** *http* - -Sets the Lua C-module search path used by scripts specified by [set_by_lua](#set_by_lua), -[content_by_lua](#content_by_lua) and others. The cpath string is in standard Lua cpath form, and `;;` -can be used to stand for the original cpath. - -As from the `v0.5.0rc29` release, the special notation `$prefix` or `${prefix}` can be used in the search path string to indicate the path of the `server prefix` usually determined by the `-p PATH` command-line option while starting the Nginx server. - -[Back to TOC](#directives) - -init_by_lua ------------ - -**syntax:** *init_by_lua <lua-script-str>* - -**context:** *http* - -**phase:** *loading-config* - -**NOTE** Use of this directive is *discouraged* following the `v0.9.17` release. Use the [init_by_lua_block](#init_by_lua_block) directive instead. - -Runs the Lua code specified by the argument `` on the global Lua VM level when the Nginx master process (if any) is loading the Nginx config file. - -When Nginx receives the `HUP` signal and starts reloading the config file, the Lua VM will also be re-created and `init_by_lua` will run again on the new Lua VM. In case that the [lua_code_cache](#lua_code_cache) directive is turned off (default on), the `init_by_lua` handler will run upon every request because in this special mode a standalone Lua VM is always created for each request. - -Usually you can pre-load Lua modules at server start-up by means of this hook and take advantage of modern operating systems' copy-on-write (COW) optimization. Here is an example for pre-loading Lua modules: - -```nginx - - # this runs before forking out nginx worker processes: - init_by_lua_block { require "cjson" } - - server { - location = /api { - content_by_lua_block { - -- the following require() will just return - -- the alrady loaded module from package.loaded: - ngx.say(require "cjson".encode{dog = 5, cat = 6}) - } - } - } -``` - -You can also initialize the [lua_shared_dict](#lua_shared_dict) shm storage at this phase. Here is an example for this: - -```nginx - - lua_shared_dict dogs 1m; - - init_by_lua_block { - local dogs = ngx.shared.dogs; - dogs:set("Tom", 56) - } - - server { - location = /api { - content_by_lua_block { - local dogs = ngx.shared.dogs; - ngx.say(dogs:get("Tom")) - } - } - } -``` - -But note that, the [lua_shared_dict](#lua_shared_dict)'s shm storage will not be cleared through a config reload (via the `HUP` signal, for example). So if you do *not* want to re-initialize the shm storage in your `init_by_lua` code in this case, then you just need to set a custom flag in the shm storage and always check the flag in your `init_by_lua` code. - -Because the Lua code in this context runs before Nginx forks its worker processes (if any), data or code loaded here will enjoy the [Copy-on-write (COW)](http://en.wikipedia.org/wiki/Copy-on-write) feature provided by many operating systems among all the worker processes, thus saving a lot of memory. - -Do *not* initialize your own Lua global variables in this context because use of Lua global variables have performance penalties and can lead to global namespace pollution (see the [Lua Variable Scope](#lua-variable-scope) section for more details). The recommended way is to use proper [Lua module](http://www.lua.org/manual/5.1/manual.html#5.3) files (but do not use the standard Lua function [module()](http://www.lua.org/manual/5.1/manual.html#pdf-module) to define Lua modules because it pollutes the global namespace as well) and call [require()](http://www.lua.org/manual/5.1/manual.html#pdf-require) to load your own module files in `init_by_lua` or other contexts ([require()](http://www.lua.org/manual/5.1/manual.html#pdf-require) does cache the loaded Lua modules in the global `package.loaded` table in the Lua registry so your modules will only loaded once for the whole Lua VM instance). - -Only a small set of the [Nginx API for Lua](#nginx-api-for-lua) is supported in this context: - -* Logging APIs: [ngx.log](#ngxlog) and [print](#print), -* Shared Dictionary API: [ngx.shared.DICT](#ngxshareddict). - -More Nginx APIs for Lua may be supported in this context upon future user requests. - -Basically you can safely use Lua libraries that do blocking I/O in this very context because blocking the master process during server start-up is completely okay. Even the Nginx core does blocking I/O (at least on resolving upstream's host names) at the configure-loading phase. - -You should be very careful about potential security vulnerabilities in your Lua code registered in this context because the Nginx master process is often run under the `root` account. - -This directive was first introduced in the `v0.5.5` release. - -[Back to TOC](#directives) - -init_by_lua_block ------------------ - -**syntax:** *init_by_lua_block { lua-script }* - -**context:** *http* - -**phase:** *loading-config* - -Similar to the [init_by_lua](#init_by_lua) directive except that this directive inlines -the Lua source directly -inside a pair of curly braces (`{}`) instead of in an NGINX string literal (which requires -special character escaping). - -For instance, - -```nginx - - init_by_lua_block { - print("I need no extra escaping here, for example: \r\nblah") - } -``` - -This directive was first introduced in the `v0.9.17` release. - -[Back to TOC](#directives) - -init_by_lua_file ----------------- - -**syntax:** *init_by_lua_file <path-to-lua-script-file>* - -**context:** *http* - -**phase:** *loading-config* - -Equivalent to [init_by_lua](#init_by_lua), except that the file specified by `` contains the Lua code or [Lua/LuaJIT bytecode](#lualuajit-bytecode-support) to be executed. - -When a relative path like `foo/bar.lua` is given, they will be turned into the absolute path relative to the `server prefix` path determined by the `-p PATH` command-line option while starting the Nginx server. - -This directive was first introduced in the `v0.5.5` release. - -[Back to TOC](#directives) - -init_worker_by_lua ------------------- - -**syntax:** *init_worker_by_lua <lua-script-str>* - -**context:** *http* - -**phase:** *starting-worker* - -**NOTE** Use of this directive is *discouraged* following the `v0.9.17` release. Use the [init_worker_by_lua_block](#init_worker_by_lua_block) directive instead. - -Runs the specified Lua code upon every Nginx worker process's startup when the master process is enabled. When the master process is disabled, this hook will just run after [init_by_lua*](#init_by_lua). - -This hook is often used to create per-worker reoccurring timers (via the [ngx.timer.at](#ngxtimerat) Lua API), either for backend health-check or other timed routine work. Below is an example, - -```nginx - - init_worker_by_lua ' - local delay = 3 -- in seconds - local new_timer = ngx.timer.at - local log = ngx.log - local ERR = ngx.ERR - local check - - check = function(premature) - if not premature then - -- do the health check or other routine work - local ok, err = new_timer(delay, check) - if not ok then - log(ERR, "failed to create timer: ", err) - return - end - end - end - - local hdl, err = new_timer(delay, check) - if not hdl then - log(ERR, "failed to create timer: ", err) - return - end - '; -``` - -This directive was first introduced in the `v0.9.5` release. - -This hook no longer runs in the cache manager and cache loader processes since the `v0.10.12` release. - -[Back to TOC](#directives) - -init_worker_by_lua_block ------------------------- - -**syntax:** *init_worker_by_lua_block { lua-script }* - -**context:** *http* - -**phase:** *starting-worker* - -Similar to the [init_worker_by_lua](#init_worker_by_lua) directive except that this directive inlines -the Lua source directly -inside a pair of curly braces (`{}`) instead of in an NGINX string literal (which requires -special character escaping). - -For instance, - -```nginx - - init_worker_by_lua_block { - print("I need no extra escaping here, for example: \r\nblah") - } -``` - -This directive was first introduced in the `v0.9.17` release. - -This hook no longer runs in the cache manager and cache loader processes since the `v0.10.12` release. - -[Back to TOC](#directives) - -init_worker_by_lua_file ------------------------ - -**syntax:** *init_worker_by_lua_file <lua-file-path>* - -**context:** *http* - -**phase:** *starting-worker* - -Similar to [init_worker_by_lua](#init_worker_by_lua), but accepts the file path to a Lua source file or Lua bytecode file. - -This directive was first introduced in the `v0.9.5` release. - -This hook no longer runs in the cache manager and cache loader processes since the `v0.10.12` release. - -[Back to TOC](#directives) - -set_by_lua ----------- - -**syntax:** *set_by_lua $res <lua-script-str> [$arg1 $arg2 ...]* - -**context:** *server, server if, location, location if* - -**phase:** *rewrite* - -**NOTE** Use of this directive is *discouraged* following the `v0.9.17` release. Use the [set_by_lua_block](#set_by_lua_block) directive instead. - -Executes code specified in `` with optional input arguments `$arg1 $arg2 ...`, and returns string output to `$res`. -The code in `` can make [API calls](#nginx-api-for-lua) and can retrieve input arguments from the `ngx.arg` table (index starts from `1` and increases sequentially). - -This directive is designed to execute short, fast running code blocks as the Nginx event loop is blocked during code execution. Time consuming code sequences should therefore be avoided. - -This directive is implemented by injecting custom commands into the standard [ngx_http_rewrite_module](http://nginx.org/en/docs/http/ngx_http_rewrite_module.html)'s command list. Because [ngx_http_rewrite_module](http://nginx.org/en/docs/http/ngx_http_rewrite_module.html) does not support nonblocking I/O in its commands, Lua APIs requiring yielding the current Lua "light thread" cannot work in this directive. - -At least the following API functions are currently disabled within the context of `set_by_lua`: - -* Output API functions (e.g., [ngx.say](#ngxsay) and [ngx.send_headers](#ngxsend_headers)) -* Control API functions (e.g., [ngx.exit](#ngxexit)) -* Subrequest API functions (e.g., [ngx.location.capture](#ngxlocationcapture) and [ngx.location.capture_multi](#ngxlocationcapture_multi)) -* Cosocket API functions (e.g., [ngx.socket.tcp](#ngxsockettcp) and [ngx.req.socket](#ngxreqsocket)). -* Sleeping API function [ngx.sleep](#ngxsleep). - -In addition, note that this directive can only write out a value to a single Nginx variable at -a time. However, a workaround is possible using the [ngx.var.VARIABLE](#ngxvarvariable) interface. - -```nginx - - location /foo { - set $diff ''; # we have to predefine the $diff variable here - - set_by_lua $sum ' - local a = 32 - local b = 56 - - ngx.var.diff = a - b; -- write to $diff directly - return a + b; -- return the $sum value normally - '; - - echo "sum = $sum, diff = $diff"; - } -``` - -This directive can be freely mixed with all directives of the [ngx_http_rewrite_module](http://nginx.org/en/docs/http/ngx_http_rewrite_module.html), [set-misc-nginx-module](http://github.com/openresty/set-misc-nginx-module), and [array-var-nginx-module](http://github.com/openresty/array-var-nginx-module) modules. All of these directives will run in the same order as they appear in the config file. - -```nginx - - set $foo 32; - set_by_lua $bar 'return tonumber(ngx.var.foo) + 1'; - set $baz "bar: $bar"; # $baz == "bar: 33" -``` - -As from the `v0.5.0rc29` release, Nginx variable interpolation is disabled in the `` argument of this directive and therefore, the dollar sign character (`$`) can be used directly. - -This directive requires the [ngx_devel_kit](https://github.com/simplresty/ngx_devel_kit) module. - -[Back to TOC](#directives) - -set_by_lua_block ----------------- - -**syntax:** *set_by_lua_block $res { lua-script }* - -**context:** *server, server if, location, location if* - -**phase:** *rewrite* - -Similar to the [set_by_lua](#set_by_lua) directive except that - -1. this directive inlines the Lua source directly -inside a pair of curly braces (`{}`) instead of in an NGINX string literal (which requires -special character escaping), and -1. this directive does not support extra arguments after the Lua script as in [set_by_lua](#set_by_lua). - -For example, - -```nginx - - set_by_lua_block $res { return 32 + math.cos(32) } - # $res now has the value "32.834223360507" or alike. -``` - -No special escaping is required in the Lua code block. - -This directive was first introduced in the `v0.9.17` release. - -[Back to TOC](#directives) - -set_by_lua_file ---------------- -**syntax:** *set_by_lua_file $res <path-to-lua-script-file> [$arg1 $arg2 ...]* - -**context:** *server, server if, location, location if* - -**phase:** *rewrite* - -Equivalent to [set_by_lua](#set_by_lua), except that the file specified by `` contains the Lua code, or, as from the `v0.5.0rc32` release, the [Lua/LuaJIT bytecode](#lualuajit-bytecode-support) to be executed. - -Nginx variable interpolation is supported in the `` argument string of this directive. But special care must be taken for injection attacks. - -When a relative path like `foo/bar.lua` is given, they will be turned into the absolute path relative to the `server prefix` path determined by the `-p PATH` command-line option while starting the Nginx server. - -When the Lua code cache is turned on (by default), the user code is loaded once at the first request and cached -and the Nginx config must be reloaded each time the Lua source file is modified. -The Lua code cache can be temporarily disabled during development by -switching [lua_code_cache](#lua_code_cache) `off` in `nginx.conf` to avoid reloading Nginx. - -This directive requires the [ngx_devel_kit](https://github.com/simplresty/ngx_devel_kit) module. - -[Back to TOC](#directives) - -content_by_lua --------------- - -**syntax:** *content_by_lua <lua-script-str>* - -**context:** *location, location if* - -**phase:** *content* - -**NOTE** Use of this directive is *discouraged* following the `v0.9.17` release. Use the [content_by_lua_block](#content_by_lua_block) directive instead. - -Acts as a "content handler" and executes Lua code string specified in `` for every request. -The Lua code may make [API calls](#nginx-api-for-lua) and is executed as a new spawned coroutine in an independent global environment (i.e. a sandbox). - -Do not use this directive and other content handler directives in the same location. For example, this directive and the [proxy_pass](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass) directive should not be used in the same location. - -[Back to TOC](#directives) - -content_by_lua_block --------------------- - -**syntax:** *content_by_lua_block { lua-script }* - -**context:** *location, location if* - -**phase:** *content* - -Similar to the [content_by_lua](#content_by_lua) directive except that this directive inlines -the Lua source directly -inside a pair of curly braces (`{}`) instead of in an NGINX string literal (which requires -special character escaping). - -For instance, - -```nginx - - content_by_lua_block { - ngx.say("I need no extra escaping here, for example: \r\nblah") - } -``` - -This directive was first introduced in the `v0.9.17` release. - -[Back to TOC](#directives) - -content_by_lua_file -------------------- - -**syntax:** *content_by_lua_file <path-to-lua-script-file>* - -**context:** *location, location if* - -**phase:** *content* - -Equivalent to [content_by_lua](#content_by_lua), except that the file specified by `` contains the Lua code, or, as from the `v0.5.0rc32` release, the [Lua/LuaJIT bytecode](#lualuajit-bytecode-support) to be executed. - -Nginx variables can be used in the `` string to provide flexibility. This however carries some risks and is not ordinarily recommended. - -When a relative path like `foo/bar.lua` is given, they will be turned into the absolute path relative to the `server prefix` path determined by the `-p PATH` command-line option while starting the Nginx server. - -When the Lua code cache is turned on (by default), the user code is loaded once at the first request and cached -and the Nginx config must be reloaded each time the Lua source file is modified. -The Lua code cache can be temporarily disabled during development by -switching [lua_code_cache](#lua_code_cache) `off` in `nginx.conf` to avoid reloading Nginx. - -Nginx variables are supported in the file path for dynamic dispatch, for example: - -```nginx - - # CAUTION: contents in nginx var must be carefully filtered, - # otherwise there'll be great security risk! - location ~ ^/app/([-_a-zA-Z0-9/]+) { - set $path $1; - content_by_lua_file /path/to/lua/app/root/$path.lua; - } -``` - -But be very careful about malicious user inputs and always carefully validate or filter out the user-supplied path components. - -[Back to TOC](#directives) - -rewrite_by_lua --------------- - -**syntax:** *rewrite_by_lua <lua-script-str>* - -**context:** *http, server, location, location if* - -**phase:** *rewrite tail* - -**NOTE** Use of this directive is *discouraged* following the `v0.9.17` release. Use the [rewrite_by_lua_block](#rewrite_by_lua_block) directive instead. - -Acts as a rewrite phase handler and executes Lua code string specified in `` for every request. -The Lua code may make [API calls](#nginx-api-for-lua) and is executed as a new spawned coroutine in an independent global environment (i.e. a sandbox). - -Note that this handler always runs *after* the standard [ngx_http_rewrite_module](http://nginx.org/en/docs/http/ngx_http_rewrite_module.html). So the following will work as expected: - -```nginx - - location /foo { - set $a 12; # create and initialize $a - set $b ""; # create and initialize $b - rewrite_by_lua 'ngx.var.b = tonumber(ngx.var.a) + 1'; - echo "res = $b"; - } -``` - -because `set $a 12` and `set $b ""` run *before* [rewrite_by_lua](#rewrite_by_lua). - -On the other hand, the following will not work as expected: - -```nginx - - ? location /foo { - ? set $a 12; # create and initialize $a - ? set $b ''; # create and initialize $b - ? rewrite_by_lua 'ngx.var.b = tonumber(ngx.var.a) + 1'; - ? if ($b = '13') { - ? rewrite ^ /bar redirect; - ? break; - ? } - ? - ? echo "res = $b"; - ? } -``` - -because `if` runs *before* [rewrite_by_lua](#rewrite_by_lua) even if it is placed after [rewrite_by_lua](#rewrite_by_lua) in the config. - -The right way of doing this is as follows: - -```nginx - - location /foo { - set $a 12; # create and initialize $a - set $b ''; # create and initialize $b - rewrite_by_lua ' - ngx.var.b = tonumber(ngx.var.a) + 1 - if tonumber(ngx.var.b) == 13 then - return ngx.redirect("/bar"); - end - '; - - echo "res = $b"; - } -``` - -Note that the [ngx_eval](http://www.grid.net.ru/nginx/eval.en.html) module can be approximated by using [rewrite_by_lua](#rewrite_by_lua). For example, - -```nginx - - location / { - eval $res { - proxy_pass http://foo.com/check-spam; - } - - if ($res = 'spam') { - rewrite ^ /terms-of-use.html redirect; - } - - fastcgi_pass ...; - } -``` - -can be implemented in ngx_lua as: - -```nginx - - location = /check-spam { - internal; - proxy_pass http://foo.com/check-spam; - } - - location / { - rewrite_by_lua ' - local res = ngx.location.capture("/check-spam") - if res.body == "spam" then - return ngx.redirect("/terms-of-use.html") - end - '; - - fastcgi_pass ...; - } -``` - -Just as any other rewrite phase handlers, [rewrite_by_lua](#rewrite_by_lua) also runs in subrequests. - -Note that when calling `ngx.exit(ngx.OK)` within a [rewrite_by_lua](#rewrite_by_lua) handler, the nginx request processing control flow will still continue to the content handler. To terminate the current request from within a [rewrite_by_lua](#rewrite_by_lua) handler, calling [ngx.exit](#ngxexit) with status >= 200 (`ngx.HTTP_OK`) and status < 300 (`ngx.HTTP_SPECIAL_RESPONSE`) for successful quits and `ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)` (or its friends) for failures. - -If the [ngx_http_rewrite_module](http://nginx.org/en/docs/http/ngx_http_rewrite_module.html)'s [rewrite](http://nginx.org/en/docs/http/ngx_http_rewrite_module.html#rewrite) directive is used to change the URI and initiate location re-lookups (internal redirections), then any [rewrite_by_lua](#rewrite_by_lua) or [rewrite_by_lua_file](#rewrite_by_lua_file) code sequences within the current location will not be executed. For example, - -```nginx - - location /foo { - rewrite ^ /bar; - rewrite_by_lua 'ngx.exit(503)'; - } - location /bar { - ... - } -``` - -Here the Lua code `ngx.exit(503)` will never run. This will be the case if `rewrite ^ /bar last` is used as this will similarly initiate an internal redirection. If the `break` modifier is used instead, there will be no internal redirection and the `rewrite_by_lua` code will be executed. - -The `rewrite_by_lua` code will always run at the end of the `rewrite` request-processing phase unless [rewrite_by_lua_no_postpone](#rewrite_by_lua_no_postpone) is turned on. - -[Back to TOC](#directives) - -rewrite_by_lua_block --------------------- - -**syntax:** *rewrite_by_lua_block { lua-script }* - -**context:** *http, server, location, location if* - -**phase:** *rewrite tail* - -Similar to the [rewrite_by_lua](#rewrite_by_lua) directive except that this directive inlines -the Lua source directly -inside a pair of curly braces (`{}`) instead of in an NGINX string literal (which requires -special character escaping). - -For instance, - -```nginx - - rewrite_by_lua_block { - do_something("hello, world!\nhiya\n") - } -``` - -This directive was first introduced in the `v0.9.17` release. - -[Back to TOC](#directives) - -rewrite_by_lua_file -------------------- - -**syntax:** *rewrite_by_lua_file <path-to-lua-script-file>* - -**context:** *http, server, location, location if* - -**phase:** *rewrite tail* - -Equivalent to [rewrite_by_lua](#rewrite_by_lua), except that the file specified by `` contains the Lua code, or, as from the `v0.5.0rc32` release, the [Lua/LuaJIT bytecode](#lualuajit-bytecode-support) to be executed. - -Nginx variables can be used in the `` string to provide flexibility. This however carries some risks and is not ordinarily recommended. - -When a relative path like `foo/bar.lua` is given, they will be turned into the absolute path relative to the `server prefix` path determined by the `-p PATH` command-line option while starting the Nginx server. - -When the Lua code cache is turned on (by default), the user code is loaded once at the first request and cached and the Nginx config must be reloaded each time the Lua source file is modified. The Lua code cache can be temporarily disabled during development by switching [lua_code_cache](#lua_code_cache) `off` in `nginx.conf` to avoid reloading Nginx. - -The `rewrite_by_lua_file` code will always run at the end of the `rewrite` request-processing phase unless [rewrite_by_lua_no_postpone](#rewrite_by_lua_no_postpone) is turned on. - -Nginx variables are supported in the file path for dynamic dispatch just as in [content_by_lua_file](#content_by_lua_file). - -[Back to TOC](#directives) - -access_by_lua -------------- - -**syntax:** *access_by_lua <lua-script-str>* - -**context:** *http, server, location, location if* - -**phase:** *access tail* - -**NOTE** Use of this directive is *discouraged* following the `v0.9.17` release. Use the [access_by_lua_block](#access_by_lua_block) directive instead. - -Acts as an access phase handler and executes Lua code string specified in `` for every request. -The Lua code may make [API calls](#nginx-api-for-lua) and is executed as a new spawned coroutine in an independent global environment (i.e. a sandbox). - -Note that this handler always runs *after* the standard [ngx_http_access_module](http://nginx.org/en/docs/http/ngx_http_access_module.html). So the following will work as expected: - -```nginx - - location / { - deny 192.168.1.1; - allow 192.168.1.0/24; - allow 10.1.1.0/16; - deny all; - - access_by_lua ' - local res = ngx.location.capture("/mysql", { ... }) - ... - '; - - # proxy_pass/fastcgi_pass/... - } -``` - -That is, if a client IP address is in the blacklist, it will be denied before the MySQL query for more complex authentication is executed by [access_by_lua](#access_by_lua). - -Note that the [ngx_auth_request](http://mdounin.ru/hg/ngx_http_auth_request_module/) module can be approximated by using [access_by_lua](#access_by_lua): - -```nginx - - location / { - auth_request /auth; - - # proxy_pass/fastcgi_pass/postgres_pass/... - } -``` - -can be implemented in ngx_lua as: - -```nginx - - location / { - access_by_lua ' - local res = ngx.location.capture("/auth") - - if res.status == ngx.HTTP_OK then - return - end - - if res.status == ngx.HTTP_FORBIDDEN then - ngx.exit(res.status) - end - - ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) - '; - - # proxy_pass/fastcgi_pass/postgres_pass/... - } -``` - -As with other access phase handlers, [access_by_lua](#access_by_lua) will *not* run in subrequests. - -Note that when calling `ngx.exit(ngx.OK)` within a [access_by_lua](#access_by_lua) handler, the nginx request processing control flow will still continue to the content handler. To terminate the current request from within a [access_by_lua](#access_by_lua) handler, calling [ngx.exit](#ngxexit) with status >= 200 (`ngx.HTTP_OK`) and status < 300 (`ngx.HTTP_SPECIAL_RESPONSE`) for successful quits and `ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)` (or its friends) for failures. - -Starting from the `v0.9.20` release, you can use the [access_by_lua_no_postpone](#access_by_lua_no_postpone) -directive to control when to run this handler inside the "access" request-processing phase -of NGINX. - -[Back to TOC](#directives) - -access_by_lua_block -------------------- - -**syntax:** *access_by_lua_block { lua-script }* - -**context:** *http, server, location, location if* - -**phase:** *access tail* - -Similar to the [access_by_lua](#access_by_lua) directive except that this directive inlines -the Lua source directly -inside a pair of curly braces (`{}`) instead of in an NGINX string literal (which requires -special character escaping). - -For instance, - -```nginx - - access_by_lua_block { - do_something("hello, world!\nhiya\n") - } -``` - -This directive was first introduced in the `v0.9.17` release. - -[Back to TOC](#directives) - -access_by_lua_file ------------------- - -**syntax:** *access_by_lua_file <path-to-lua-script-file>* - -**context:** *http, server, location, location if* - -**phase:** *access tail* - -Equivalent to [access_by_lua](#access_by_lua), except that the file specified by `` contains the Lua code, or, as from the `v0.5.0rc32` release, the [Lua/LuaJIT bytecode](#lualuajit-bytecode-support) to be executed. - -Nginx variables can be used in the `` string to provide flexibility. This however carries some risks and is not ordinarily recommended. - -When a relative path like `foo/bar.lua` is given, they will be turned into the absolute path relative to the `server prefix` path determined by the `-p PATH` command-line option while starting the Nginx server. - -When the Lua code cache is turned on (by default), the user code is loaded once at the first request and cached -and the Nginx config must be reloaded each time the Lua source file is modified. -The Lua code cache can be temporarily disabled during development by switching [lua_code_cache](#lua_code_cache) `off` in `nginx.conf` to avoid repeatedly reloading Nginx. - -Nginx variables are supported in the file path for dynamic dispatch just as in [content_by_lua_file](#content_by_lua_file). - -[Back to TOC](#directives) - -header_filter_by_lua --------------------- - -**syntax:** *header_filter_by_lua <lua-script-str>* - -**context:** *http, server, location, location if* - -**phase:** *output-header-filter* - -**NOTE** Use of this directive is *discouraged* following the `v0.9.17` release. Use the [header_filter_by_lua_block](#header_filter_by_lua_block) directive instead. - -Uses Lua code specified in `` to define an output header filter. - -Note that the following API functions are currently disabled within this context: - -* Output API functions (e.g., [ngx.say](#ngxsay) and [ngx.send_headers](#ngxsend_headers)) -* Control API functions (e.g., [ngx.redirect](#ngxredirect) and [ngx.exec](#ngxexec)) -* Subrequest API functions (e.g., [ngx.location.capture](#ngxlocationcapture) and [ngx.location.capture_multi](#ngxlocationcapture_multi)) -* Cosocket API functions (e.g., [ngx.socket.tcp](#ngxsockettcp) and [ngx.req.socket](#ngxreqsocket)). - -Here is an example of overriding a response header (or adding one if absent) in our Lua header filter: - -```nginx - - location / { - proxy_pass http://mybackend; - header_filter_by_lua 'ngx.header.Foo = "blah"'; - } -``` - -This directive was first introduced in the `v0.2.1rc20` release. - -[Back to TOC](#directives) - -header_filter_by_lua_block --------------------------- - -**syntax:** *header_filter_by_lua_block { lua-script }* - -**context:** *http, server, location, location if* - -**phase:** *output-header-filter* - -Similar to the [header_filter_by_lua](#header_filter_by_lua) directive except that this directive inlines -the Lua source directly -inside a pair of curly braces (`{}`) instead of in an NGINX string literal (which requires -special character escaping). - -For instance, - -```nginx - - header_filter_by_lua_block { - ngx.header["content-length"] = nil - } -``` - -This directive was first introduced in the `v0.9.17` release. - -[Back to TOC](#directives) - -header_filter_by_lua_file -------------------------- - -**syntax:** *header_filter_by_lua_file <path-to-lua-script-file>* - -**context:** *http, server, location, location if* - -**phase:** *output-header-filter* - -Equivalent to [header_filter_by_lua](#header_filter_by_lua), except that the file specified by `` contains the Lua code, or as from the `v0.5.0rc32` release, the [Lua/LuaJIT bytecode](#lualuajit-bytecode-support) to be executed. - -When a relative path like `foo/bar.lua` is given, they will be turned into the absolute path relative to the `server prefix` path determined by the `-p PATH` command-line option while starting the Nginx server. - -This directive was first introduced in the `v0.2.1rc20` release. - -[Back to TOC](#directives) - -body_filter_by_lua ------------------- - -**syntax:** *body_filter_by_lua <lua-script-str>* - -**context:** *http, server, location, location if* - -**phase:** *output-body-filter* - -**NOTE** Use of this directive is *discouraged* following the `v0.9.17` release. Use the [body_filter_by_lua_block](#body_filter_by_lua_block) directive instead. - -Uses Lua code specified in `` to define an output body filter. - -The input data chunk is passed via [ngx.arg](#ngxarg)\[1\] (as a Lua string value) and the "eof" flag indicating the end of the response body data stream is passed via [ngx.arg](#ngxarg)\[2\] (as a Lua boolean value). - -Behind the scene, the "eof" flag is just the `last_buf` (for main requests) or `last_in_chain` (for subrequests) flag of the Nginx chain link buffers. (Before the `v0.7.14` release, the "eof" flag does not work at all in subrequests.) - -The output data stream can be aborted immediately by running the following Lua statement: - -```lua - - return ngx.ERROR -``` - -This will truncate the response body and usually result in incomplete and also invalid responses. - -The Lua code can pass its own modified version of the input data chunk to the downstream Nginx output body filters by overriding [ngx.arg](#ngxarg)\[1\] with a Lua string or a Lua table of strings. For example, to transform all the lowercase letters in the response body, we can just write: - -```nginx - - location / { - proxy_pass http://mybackend; - body_filter_by_lua 'ngx.arg[1] = string.upper(ngx.arg[1])'; - } -``` - -When setting `nil` or an empty Lua string value to `ngx.arg[1]`, no data chunk will be passed to the downstream Nginx output filters at all. - -Likewise, new "eof" flag can also be specified by setting a boolean value to [ngx.arg](#ngxarg)\[2\]. For example, - -```nginx - - location /t { - echo hello world; - echo hiya globe; - - body_filter_by_lua ' - local chunk = ngx.arg[1] - if string.match(chunk, "hello") then - ngx.arg[2] = true -- new eof - return - end - - -- just throw away any remaining chunk data - ngx.arg[1] = nil - '; - } -``` - -Then `GET /t` will just return the output - - - hello world - - -That is, when the body filter sees a chunk containing the word "hello", then it will set the "eof" flag to true immediately, resulting in truncated but still valid responses. - -When the Lua code may change the length of the response body, then it is required to always clear out the `Content-Length` response header (if any) in a header filter to enforce streaming output, as in - -```nginx - - location /foo { - # fastcgi_pass/proxy_pass/... - - header_filter_by_lua_block { ngx.header.content_length = nil } - body_filter_by_lua 'ngx.arg[1] = string.len(ngx.arg[1]) .. "\\n"'; - } -``` - -Note that the following API functions are currently disabled within this context due to the limitations in NGINX output filter's current implementation: - -* Output API functions (e.g., [ngx.say](#ngxsay) and [ngx.send_headers](#ngxsend_headers)) -* Control API functions (e.g., [ngx.exit](#ngxexit) and [ngx.exec](#ngxexec)) -* Subrequest API functions (e.g., [ngx.location.capture](#ngxlocationcapture) and [ngx.location.capture_multi](#ngxlocationcapture_multi)) -* Cosocket API functions (e.g., [ngx.socket.tcp](#ngxsockettcp) and [ngx.req.socket](#ngxreqsocket)). - -Nginx output filters may be called multiple times for a single request because response body may be delivered in chunks. Thus, the Lua code specified by in this directive may also run multiple times in the lifetime of a single HTTP request. - -This directive was first introduced in the `v0.5.0rc32` release. - -[Back to TOC](#directives) - -body_filter_by_lua_block ------------------------- - -**syntax:** *body_filter_by_lua_block { lua-script-str }* - -**context:** *http, server, location, location if* - -**phase:** *output-body-filter* - -Similar to the [body_filter_by_lua](#body_filter_by_lua) directive except that this directive inlines -the Lua source directly -inside a pair of curly braces (`{}`) instead of in an NGINX string literal (which requires -special character escaping). - -For instance, - -```nginx - - body_filter_by_lua_block { - local data, eof = ngx.arg[1], ngx.arg[2] - } -``` - -This directive was first introduced in the `v0.9.17` release. - -[Back to TOC](#directives) - -body_filter_by_lua_file ------------------------ - -**syntax:** *body_filter_by_lua_file <path-to-lua-script-file>* - -**context:** *http, server, location, location if* - -**phase:** *output-body-filter* - -Equivalent to [body_filter_by_lua](#body_filter_by_lua), except that the file specified by `` contains the Lua code, or, as from the `v0.5.0rc32` release, the [Lua/LuaJIT bytecode](#lualuajit-bytecode-support) to be executed. - -When a relative path like `foo/bar.lua` is given, they will be turned into the absolute path relative to the `server prefix` path determined by the `-p PATH` command-line option while starting the Nginx server. - -This directive was first introduced in the `v0.5.0rc32` release. - -[Back to TOC](#directives) - -log_by_lua ----------- - -**syntax:** *log_by_lua <lua-script-str>* - -**context:** *http, server, location, location if* - -**phase:** *log* - -**NOTE** Use of this directive is *discouraged* following the `v0.9.17` release. Use the [log_by_lua_block](#log_by_lua_block) directive instead. - -Runs the Lua source code inlined as the `` at the `log` request processing phase. This does not replace the current access logs, but runs before. - -Note that the following API functions are currently disabled within this context: - -* Output API functions (e.g., [ngx.say](#ngxsay) and [ngx.send_headers](#ngxsend_headers)) -* Control API functions (e.g., [ngx.exit](#ngxexit)) -* Subrequest API functions (e.g., [ngx.location.capture](#ngxlocationcapture) and [ngx.location.capture_multi](#ngxlocationcapture_multi)) -* Cosocket API functions (e.g., [ngx.socket.tcp](#ngxsockettcp) and [ngx.req.socket](#ngxreqsocket)). - -Here is an example of gathering average data for [$upstream_response_time](http://nginx.org/en/docs/http/ngx_http_upstream_module.html#var_upstream_response_time): - -```nginx - - lua_shared_dict log_dict 5M; - - server { - location / { - proxy_pass http://mybackend; - - log_by_lua ' - local log_dict = ngx.shared.log_dict - local upstream_time = tonumber(ngx.var.upstream_response_time) - - local sum = log_dict:get("upstream_time-sum") or 0 - sum = sum + upstream_time - log_dict:set("upstream_time-sum", sum) - - local newval, err = log_dict:incr("upstream_time-nb", 1) - if not newval and err == "not found" then - log_dict:add("upstream_time-nb", 0) - log_dict:incr("upstream_time-nb", 1) - end - '; - } - - location = /status { - content_by_lua_block { - local log_dict = ngx.shared.log_dict - local sum = log_dict:get("upstream_time-sum") - local nb = log_dict:get("upstream_time-nb") - - if nb and sum then - ngx.say("average upstream response time: ", sum / nb, - " (", nb, " reqs)") - else - ngx.say("no data yet") - end - } - } - } -``` - -This directive was first introduced in the `v0.5.0rc31` release. - -[Back to TOC](#directives) - -log_by_lua_block ----------------- - -**syntax:** *log_by_lua_block { lua-script }* - -**context:** *http, server, location, location if* - -**phase:** *log* - -Similar to the [log_by_lua](#log_by_lua) directive except that this directive inlines -the Lua source directly -inside a pair of curly braces (`{}`) instead of in an NGINX string literal (which requires -special character escaping). - -For instance, - -```nginx - - log_by_lua_block { - print("I need no extra escaping here, for example: \r\nblah") - } -``` - -This directive was first introduced in the `v0.9.17` release. - -[Back to TOC](#directives) - -log_by_lua_file ---------------- - -**syntax:** *log_by_lua_file <path-to-lua-script-file>* - -**context:** *http, server, location, location if* - -**phase:** *log* - -Equivalent to [log_by_lua](#log_by_lua), except that the file specified by `` contains the Lua code, or, as from the `v0.5.0rc32` release, the [Lua/LuaJIT bytecode](#lualuajit-bytecode-support) to be executed. - -When a relative path like `foo/bar.lua` is given, they will be turned into the absolute path relative to the `server prefix` path determined by the `-p PATH` command-line option while starting the Nginx server. - -This directive was first introduced in the `v0.5.0rc31` release. - -[Back to TOC](#directives) - -balancer_by_lua_block ---------------------- - -**syntax:** *balancer_by_lua_block { lua-script }* - -**context:** *upstream* - -**phase:** *content* - -This directive runs Lua code as an upstream balancer for any upstream entities defined -by the `upstream {}` configuration block. - -For instance, - -```nginx - - upstream foo { - server 127.0.0.1; - balancer_by_lua_block { - -- use Lua to do something interesting here - -- as a dynamic balancer - } - } - - server { - location / { - proxy_pass http://foo; - } - } -``` - -The resulting Lua load balancer can work with any existing nginx upstream modules -like [ngx_proxy](http://nginx.org/en/docs/http/ngx_http_proxy_module.html) and -[ngx_fastcgi](http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html). - -Also, the Lua load balancer can work with the standard upstream connection pool mechanism, -i.e., the standard [keepalive](http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive) directive. -Just ensure that the [keepalive](http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive) directive -is used *after* this `balancer_by_lua_block` directive in a single `upstream {}` configuration block. - -The Lua load balancer can totally ignore the list of servers defined in the `upstream {}` block -and select peer from a completely dynamic server list (even changing per request) via the -[ngx.balancer](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/balancer.md) module -from the [lua-resty-core](https://github.com/openresty/lua-resty-core) library. - -The Lua code handler registered by this directive might get called more than once in a single -downstream request when the nginx upstream mechanism retries the request on conditions -specified by directives like the [proxy_next_upstream](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_next_upstream) -directive. - -This Lua code execution context does not support yielding, so Lua APIs that may yield -(like cosockets and "light threads") are disabled in this context. One can usually work -around this limitation by doing such operations in an earlier phase handler (like -[access_by_lua*](#access_by_lua)) and passing along the result into this context -via the [ngx.ctx](#ngxctx) table. - -This directive was first introduced in the `v0.10.0` release. - -[Back to TOC](#directives) - -balancer_by_lua_file --------------------- - -**syntax:** *balancer_by_lua_file <path-to-lua-script-file>* - -**context:** *upstream* - -**phase:** *content* - -Equivalent to [balancer_by_lua_block](#balancer_by_lua_block), except that the file specified by `` contains the Lua code, or, as from the `v0.5.0rc32` release, the [Lua/LuaJIT bytecode](#lualuajit-bytecode-support) to be executed. - -When a relative path like `foo/bar.lua` is given, they will be turned into the absolute path relative to the `server prefix` path determined by the `-p PATH` command-line option while starting the Nginx server. - -This directive was first introduced in the `v0.10.0` release. - -[Back to TOC](#directives) - -lua_need_request_body ---------------------- - -**syntax:** *lua_need_request_body <on|off>* - -**default:** *off* - -**context:** *http, server, location, location if* - -**phase:** *depends on usage* - -Determines whether to force the request body data to be read before running rewrite/access/access_by_lua* or not. The Nginx core does not read the client request body by default and if request body data is required, then this directive should be turned `on` or the [ngx.req.read_body](#ngxreqread_body) function should be called within the Lua code. - -To read the request body data within the [$request_body](http://nginx.org/en/docs/http/ngx_http_core_module.html#var_request_body) variable, -[client_body_buffer_size](http://nginx.org/en/docs/http/ngx_http_core_module.html#client_body_buffer_size) must have the same value as [client_max_body_size](http://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size). Because when the content length exceeds [client_body_buffer_size](http://nginx.org/en/docs/http/ngx_http_core_module.html#client_body_buffer_size) but less than [client_max_body_size](http://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size), Nginx will buffer the data into a temporary file on the disk, which will lead to empty value in the [$request_body](http://nginx.org/en/docs/http/ngx_http_core_module.html#var_request_body) variable. - -If the current location includes [rewrite_by_lua*](#rewrite_by_lua) directives, -then the request body will be read just before the [rewrite_by_lua*](#rewrite_by_lua) code is run (and also at the -`rewrite` phase). Similarly, if only [content_by_lua](#content_by_lua) is specified, -the request body will not be read until the content handler's Lua code is -about to run (i.e., the request body will be read during the content phase). - -It is recommended however, to use the [ngx.req.read_body](#ngxreqread_body) and [ngx.req.discard_body](#ngxreqdiscard_body) functions for finer control over the request body reading process instead. - -This also applies to [access_by_lua*](#access_by_lua). - -[Back to TOC](#directives) - -ssl_certificate_by_lua_block ----------------------------- - -**syntax:** *ssl_certificate_by_lua_block { lua-script }* - -**context:** *server* - -**phase:** *right-before-SSL-handshake* - -This directive runs user Lua code when NGINX is about to start the SSL handshake for the downstream -SSL (https) connections. - -It is particularly useful for setting the SSL certificate chain and the corresponding private key on a per-request -basis. It is also useful to load such handshake configurations nonblockingly from the remote (for example, -with the [cosocket](#ngxsockettcp) API). And one can also do per-request OCSP stapling handling in pure -Lua here as well. - -Another typical use case is to do SSL handshake traffic control nonblockingly in this context, -with the help of the [lua-resty-limit-traffic#readme](https://github.com/openresty/lua-resty-limit-traffic) -library, for example. - -One can also do interesting things with the SSL handshake requests from the client side, like -rejecting old SSL clients using the SSLv3 protocol or even below selectively. - -The [ngx.ssl](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ssl.md) -and [ngx.ocsp](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ocsp.md) Lua modules -provided by the [lua-resty-core](https://github.com/openresty/lua-resty-core/#readme) -library are particularly useful in this context. You can use the Lua API offered by these two Lua modules -to manipulate the SSL certificate chain and private key for the current SSL connection -being initiated. - -This Lua handler does not run at all, however, when NGINX/OpenSSL successfully resumes -the SSL session via SSL session IDs or TLS session tickets for the current SSL connection. In -other words, this Lua handler only runs when NGINX has to initiate a full SSL handshake. - -Below is a trivial example using the -[ngx.ssl](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ssl.md) module -at the same time: - -```nginx - - server { - listen 443 ssl; - server_name test.com; - - ssl_certificate_by_lua_block { - print("About to initiate a new SSL handshake!") - } - - location / { - root html; - } - } -``` - -See more complicated examples in the [ngx.ssl](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ssl.md) -and [ngx.ocsp](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ocsp.md) -Lua modules' official documentation. - -Uncaught Lua exceptions in the user Lua code immediately abort the current SSL session, so does the -[ngx.exit](#ngxexit) call with an error code like `ngx.ERROR`. - -This Lua code execution context *does* support yielding, so Lua APIs that may yield -(like cosockets, sleeping, and "light threads") -are enabled in this context. - -Note, however, you still need to configure the [ssl_certificate](http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_certificate) and -[ssl_certificate_key](http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_certificate_key) -directives even though you will not use this static certificate and private key at all. This is -because the NGINX core requires their appearance otherwise you are seeing the following error -while starting NGINX: - - - nginx: [emerg] no ssl configured for the server - - -This directive currently requires the following NGINX core patch to work correctly: - - - -The bundled version of the NGINX core in OpenResty 1.9.7.2 (or above) already has this -patch applied. - -Furthermore, one needs at least OpenSSL 1.0.2e for this directive to work. - -This directive was first introduced in the `v0.10.0` release. - -[Back to TOC](#directives) - -ssl_certificate_by_lua_file ---------------------------- - -**syntax:** *ssl_certificate_by_lua_file <path-to-lua-script-file>* - -**context:** *server* - -**phase:** *right-before-SSL-handshake* - -Equivalent to [ssl_certificate_by_lua_block](#ssl_certificate_by_lua_block), except that the file specified by `` contains the Lua code, or, as from the `v0.5.0rc32` release, the [Lua/LuaJIT bytecode](#lualuajit-bytecode-support) to be executed. - -When a relative path like `foo/bar.lua` is given, they will be turned into the absolute path relative to the `server prefix` path determined by the `-p PATH` command-line option while starting the Nginx server. - -This directive was first introduced in the `v0.10.0` release. - -[Back to TOC](#directives) - -ssl_session_fetch_by_lua_block ------------------------------- - -**syntax:** *ssl_session_fetch_by_lua_block { lua-script }* - -**context:** *http* - -**phase:** *right-before-SSL-handshake* - -This directive runs Lua code to look up and load the SSL session (if any) according to the session ID -provided by the current SSL handshake request for the downstream. - -The Lua API for obtaining the current session ID and loading a cached SSL session data -is provided in the [ngx.ssl.session](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ssl/session.md) -Lua module shipped with the [lua-resty-core](https://github.com/openresty/lua-resty-core#readme) -library. - -Lua APIs that may yield, like [ngx.sleep](#ngxsleep) and [cosockets](#ngxsockettcp), -are enabled in this context. - -This hook, together with the [ssl_session_store_by_lua*](#ssl_session_store_by_lua_block) hook, -can be used to implement distributed caching mechanisms in pure Lua (based -on the [cosocket](#ngxsockettcp) API, for example). If a cached SSL session is found -and loaded into the current SSL connection context, -SSL session resumption can then get immediately initiated and bypass the full SSL handshake process which is very expensive in terms of CPU time. - -Please note that TLS session tickets are very different and it is the clients' responsibility -to cache the SSL session state when session tickets are used. SSL session resumptions based on -TLS session tickets would happen automatically without going through this hook (nor the -[ssl_session_store_by_lua_block](#ssl_session_store_by_lua) hook). This hook is mainly -for older or less capable SSL clients that can only do SSL sessions by session IDs. - -When [ssl_certificate_by_lua*](#ssl_certificate_by_lua_block) is specified at the same time, -this hook usually runs before [ssl_certificate_by_lua*](#ssl_certificate_by_lua_block). -When the SSL session is found and successfully loaded for the current SSL connection, -SSL session resumption will happen and thus bypass the [ssl_certificate_by_lua*](#ssl_certificate_by_lua_block) -hook completely. In this case, NGINX also bypasses the [ssl_session_store_by_lua_block](#ssl_session_store_by_lua) -hook, for obvious reasons. - -To easily test this hook locally with a modern web browser, you can temporarily put the following line -in your https server block to disable the TLS session ticket support: - - ssl_session_tickets off; - -But do not forget to comment this line out before publishing your site to the world. - -If you are using the [official pre-built packages](http://openresty.org/en/linux-packages.html) for [OpenResty](https://openresty.org/) -1.11.2.1 or later, then everything should work out of the box. - -If you are using OpenSSL libraries not provided by [OpenResty](https://openresty.org), -then you need to apply the following patch for OpenSSL 1.0.2h or later: - - - -If you are not using the NGINX core shipped with [OpenResty](https://openresty.org) 1.11.2.1 or later, then you need to -apply the following patch to the standard NGINX core 1.11.2 or later: - - - -This directive was first introduced in the `v0.10.6` release. - -Note that: this directive is only allowed to used in **http context** from the `v0.10.7` release -(because SSL session resumption happens before server name dispatch). - -[Back to TOC](#directives) - -ssl_session_fetch_by_lua_file ------------------------------ - -**syntax:** *ssl_session_fetch_by_lua_file <path-to-lua-script-file>* - -**context:** *http* - -**phase:** *right-before-SSL-handshake* - -Equivalent to [ssl_session_fetch_by_lua_block](#ssl_session_fetch_by_lua_block), except that the file specified by `` contains the Lua code, or rather, the [Lua/LuaJIT bytecode](#lualuajit-bytecode-support) to be executed. - -When a relative path like `foo/bar.lua` is given, they will be turned into the absolute path relative to the `server prefix` path determined by the `-p PATH` command-line option while starting the Nginx server. - -This directive was first introduced in the `v0.10.6` release. - -Note that: this directive is only allowed to used in **http context** from the `v0.10.7` release -(because SSL session resumption happens before server name dispatch). - -[Back to TOC](#directives) - -ssl_session_store_by_lua_block ------------------------------- - -**syntax:** *ssl_session_store_by_lua_block { lua-script }* - -**context:** *http* - -**phase:** *right-after-SSL-handshake* - -This directive runs Lua code to fetch and save the SSL session (if any) according to the session ID -provided by the current SSL handshake request for the downstream. The saved or cached SSL -session data can be used for future SSL connections to resume SSL sessions without going -through the full SSL handshake process (which is very expensive in terms of CPU time). - -Lua APIs that may yield, like [ngx.sleep](#ngxsleep) and [cosockets](#ngxsockettcp), -are *disabled* in this context. You can still, however, use the [ngx.timer.at](#ngxtimerat) API -to create 0-delay timers to save the SSL session data asynchronously to external services (like `redis` or `memcached`). - -The Lua API for obtaining the current session ID and the associated session state data -is provided in the [ngx.ssl.session](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ssl/session.md#readme) -Lua module shipped with the [lua-resty-core](https://github.com/openresty/lua-resty-core#readme) -library. - -To easily test this hook locally with a modern web browser, you can temporarily put the following line -in your https server block to disable the TLS session ticket support: - - ssl_session_tickets off; - -But do not forget to comment this line out before publishing your site to the world. - -This directive was first introduced in the `v0.10.6` release. - -Note that: this directive is only allowed to used in **http context** from the `v0.10.7` release -(because SSL session resumption happens before server name dispatch). - -[Back to TOC](#directives) - -ssl_session_store_by_lua_file ------------------------------ - -**syntax:** *ssl_session_store_by_lua_file <path-to-lua-script-file>* - -**context:** *http* - -**phase:** *right-after-SSL-handshake* - -Equivalent to [ssl_session_store_by_lua_block](#ssl_session_store_by_lua_block), except that the file specified by `` contains the Lua code, or rather, the [Lua/LuaJIT bytecode](#lualuajit-bytecode-support) to be executed. - -When a relative path like `foo/bar.lua` is given, they will be turned into the absolute path relative to the `server prefix` path determined by the `-p PATH` command-line option while starting the Nginx server. - -This directive was first introduced in the `v0.10.6` release. - -Note that: this directive is only allowed to used in **http context** from the `v0.10.7` release -(because SSL session resumption happens before server name dispatch). - -[Back to TOC](#directives) - -lua_shared_dict ---------------- - -**syntax:** *lua_shared_dict <name> <size>* - -**default:** *no* - -**context:** *http* - -**phase:** *depends on usage* - -Declares a shared memory zone, ``, to serve as storage for the shm based Lua dictionary `ngx.shared.`. - -Shared memory zones are always shared by all the nginx worker processes in the current nginx server instance. - -The `` argument accepts size units such as `k` and `m`: - -```nginx - - http { - lua_shared_dict dogs 10m; - ... - } -``` - -The hard-coded minimum size is 8KB while the practical minimum size depends -on actual user data set (some people start with 12KB). - -See [ngx.shared.DICT](#ngxshareddict) for details. - -This directive was first introduced in the `v0.3.1rc22` release. - -[Back to TOC](#directives) - -lua_socket_connect_timeout --------------------------- - -**syntax:** *lua_socket_connect_timeout <time>* - -**default:** *lua_socket_connect_timeout 60s* - -**context:** *http, server, location* - -This directive controls the default timeout value used in TCP/unix-domain socket object's [connect](#tcpsockconnect) method and can be overridden by the [settimeout](#tcpsocksettimeout) or [settimeouts](#tcpsocksettimeouts) methods. - -The `