From 7906d14d074d8ba13d3a5fe767bfd563a922c687 Mon Sep 17 00:00:00 2001 From: nginx Date: Tue, 4 Feb 2014 12:34:41 +0000 Subject: Changes with nginx 1.5.10 04 Feb 2014 *) Feature: the ngx_http_spdy_module now uses SPDY 3.1 protocol. Thanks to Automattic and MaxCDN for sponsoring this work. *) Feature: the ngx_http_mp4_module now skips tracks too short for a seek requested. *) Bugfix: a segmentation fault might occur in a worker process if the $ssl_session_id variable was used in logs; the bug had appeared in 1.5.9. *) Bugfix: the $date_local and $date_gmt variables used wrong format outside of the ngx_http_ssi_filter_module. *) Bugfix: client connections might be immediately closed if deferred accept was used; the bug had appeared in 1.3.15. *) Bugfix: alerts "getsockopt(TCP_FASTOPEN) ... failed" appeared in logs during binary upgrade on Linux; the bug had appeared in 1.5.8. Thanks to Piotr Sikora. --- CHANGES | 23 + CHANGES.ru | 25 + auto/cc/clang | 2 +- src/core/nginx.h | 4 +- src/core/ngx_connection.c | 20 +- src/core/ngx_string.c | 49 +- src/core/ngx_string.h | 1 + src/event/ngx_event_openssl.c | 4 + src/http/modules/ngx_http_mp4_module.c | 46 +- src/http/modules/ngx_http_range_filter_module.c | 2 +- src/http/modules/ngx_http_ssi_filter_module.c | 13 +- src/http/modules/ngx_http_ssl_module.c | 72 ++- src/http/ngx_http.c | 8 +- src/http/ngx_http_request.c | 42 +- src/http/ngx_http_spdy.c | 735 +++++++++++++++++++++--- src/http/ngx_http_spdy.h | 49 +- src/http/ngx_http_spdy_filter_module.c | 166 ++++-- src/http/ngx_http_spdy_module.c | 4 +- src/http/ngx_http_upstream.c | 2 +- src/os/unix/ngx_errno.h | 1 + 20 files changed, 1062 insertions(+), 206 deletions(-) diff --git a/CHANGES b/CHANGES index 5b1678eea..e53487e69 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,27 @@ +Changes with nginx 1.5.10 04 Feb 2014 + + *) Feature: the ngx_http_spdy_module now uses SPDY 3.1 protocol. + Thanks to Automattic and MaxCDN for sponsoring this work. + + *) Feature: the ngx_http_mp4_module now skips tracks too short for a + seek requested. + + *) Bugfix: a segmentation fault might occur in a worker process if the + $ssl_session_id variable was used in logs; the bug had appeared in + 1.5.9. + + *) Bugfix: the $date_local and $date_gmt variables used wrong format + outside of the ngx_http_ssi_filter_module. + + *) Bugfix: client connections might be immediately closed if deferred + accept was used; the bug had appeared in 1.3.15. + + *) Bugfix: alerts "getsockopt(TCP_FASTOPEN) ... failed" appeared in logs + during binary upgrade on Linux; the bug had appeared in 1.5.8. + Thanks to Piotr Sikora. + + Changes with nginx 1.5.9 22 Jan 2014 *) Change: now nginx expects escaped URIs in "X-Accel-Redirect" headers. diff --git a/CHANGES.ru b/CHANGES.ru index 580bba300..006b364a5 100644 --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,29 @@ +Изменения в nginx 1.5.10 04.02.2014 + + *) Добавление: модуль ngx_http_spdy_module теперь использует протокол + SPDY 3.1. + Спасибо Automattic и MaxCDN за спонсирование разработки. + + *) Добавление: модуль ngx_http_mp4_module теперь пропускает дорожки, + имеющие меньшую длину, чем запрошенная перемотка. + + *) Исправление: в рабочем процессе мог произойти segmentation fault, + если переменная $ssl_session_id использовалась при логгировании; + ошибка появилась в 1.5.9. + + *) Исправление: переменные $date_local и $date_gmt использовали неверный + формат вне модуля ngx_http_ssi_filter_module. + + *) Исправление: клиентские соединения могли сразу закрываться, если + использовался отложенный accept; ошибка появилась в 1.3.15. + + *) Исправление: сообщения "getsockopt(TCP_FASTOPEN) ... failed" + записывались в лог в процессе обновления исполняемого файла на Linux; + ошибка появилась в 1.5.8. + Спасибо Piotr Sikora. + + Изменения в nginx 1.5.9 22.01.2014 *) Изменение: теперь в заголовке X-Accel-Redirect nginx ожидает diff --git a/auto/cc/clang b/auto/cc/clang index 0cca3442e..baaf4baa2 100644 --- a/auto/cc/clang +++ b/auto/cc/clang @@ -89,7 +89,7 @@ CFLAGS="$CFLAGS -Wconditional-uninitialized" CFLAGS="$CFLAGS -Wno-unused-parameter" # stop on warning -#CFLAGS="$CFLAGS -Werror" +CFLAGS="$CFLAGS -Werror" # debug CFLAGS="$CFLAGS -g" diff --git a/src/core/nginx.h b/src/core/nginx.h index 76d43c6d4..71a71230c 100644 --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1005009 -#define NGINX_VERSION "1.5.9" +#define nginx_version 1005010 +#define NGINX_VERSION "1.5.10" #define NGINX_VER "nginx/" NGINX_VERSION #define NGINX_VAR "NGINX" diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c index 08a547d42..15f4f3c90 100644 --- a/src/core/ngx_connection.c +++ b/src/core/ngx_connection.c @@ -97,7 +97,7 @@ ngx_set_inherited_sockets(ngx_cycle_t *cycle) ngx_uint_t i; ngx_listening_t *ls; socklen_t olen; -#if (NGX_HAVE_DEFERRED_ACCEPT) +#if (NGX_HAVE_DEFERRED_ACCEPT || NGX_HAVE_TCP_FASTOPEN) ngx_err_t err; #endif #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) @@ -223,9 +223,13 @@ ngx_set_inherited_sockets(ngx_cycle_t *cycle) (void *) &ls[i].fastopen, &olen) == -1) { - ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno, - "getsockopt(TCP_FASTOPEN) %V failed, ignored", - &ls[i].addr_text); + err = ngx_socket_errno; + + if (err != NGX_EOPNOTSUPP && err != NGX_ENOPROTOOPT) { + ngx_log_error(NGX_LOG_NOTICE, cycle->log, err, + "getsockopt(TCP_FASTOPEN) %V failed, ignored", + &ls[i].addr_text); + } ls[i].fastopen = -1; } @@ -701,7 +705,13 @@ ngx_configure_listening_sockets(ngx_cycle_t *cycle) if (ls[i].add_deferred || ls[i].delete_deferred) { if (ls[i].add_deferred) { - value = (int) (ls[i].post_accept_timeout / 1000); + /* + * There is no way to find out how long a connection was + * in queue (and a connection may bypass deferred queue at all + * if syncookies were used), hence we use 1 second timeout + * here. + */ + value = 1; } else { value = 0; diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c index fe6b1ee71..4e279176c 100644 --- a/src/core/ngx_string.c +++ b/src/core/ngx_string.c @@ -11,6 +11,8 @@ static u_char *ngx_sprintf_num(u_char *buf, u_char *last, uint64_t ui64, u_char zero, ngx_uint_t hexadecimal, ngx_uint_t width); +static void ngx_encode_base64_internal(ngx_str_t *dst, ngx_str_t *src, + const u_char *basis, ngx_uint_t padding); static ngx_int_t ngx_decode_base64_internal(ngx_str_t *dst, ngx_str_t *src, const u_char *basis); @@ -1100,38 +1102,61 @@ ngx_hex_dump(u_char *dst, u_char *src, size_t len) void ngx_encode_base64(ngx_str_t *dst, ngx_str_t *src) { - u_char *d, *s; - size_t len; static u_char basis64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + ngx_encode_base64_internal(dst, src, basis64, 1); +} + + +void +ngx_encode_base64url(ngx_str_t *dst, ngx_str_t *src) +{ + static u_char basis64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; + + ngx_encode_base64_internal(dst, src, basis64, 0); +} + + +static void +ngx_encode_base64_internal(ngx_str_t *dst, ngx_str_t *src, const u_char *basis, + ngx_uint_t padding) +{ + u_char *d, *s; + size_t len; + len = src->len; s = src->data; d = dst->data; while (len > 2) { - *d++ = basis64[(s[0] >> 2) & 0x3f]; - *d++ = basis64[((s[0] & 3) << 4) | (s[1] >> 4)]; - *d++ = basis64[((s[1] & 0x0f) << 2) | (s[2] >> 6)]; - *d++ = basis64[s[2] & 0x3f]; + *d++ = basis[(s[0] >> 2) & 0x3f]; + *d++ = basis[((s[0] & 3) << 4) | (s[1] >> 4)]; + *d++ = basis[((s[1] & 0x0f) << 2) | (s[2] >> 6)]; + *d++ = basis[s[2] & 0x3f]; s += 3; len -= 3; } if (len) { - *d++ = basis64[(s[0] >> 2) & 0x3f]; + *d++ = basis[(s[0] >> 2) & 0x3f]; if (len == 1) { - *d++ = basis64[(s[0] & 3) << 4]; - *d++ = '='; + *d++ = basis[(s[0] & 3) << 4]; + if (padding) { + *d++ = '='; + } } else { - *d++ = basis64[((s[0] & 3) << 4) | (s[1] >> 4)]; - *d++ = basis64[(s[1] & 0x0f) << 2]; + *d++ = basis[((s[0] & 3) << 4) | (s[1] >> 4)]; + *d++ = basis[(s[1] & 0x0f) << 2]; } - *d++ = '='; + if (padding) { + *d++ = '='; + } } dst->len = d - dst->data; diff --git a/src/core/ngx_string.h b/src/core/ngx_string.h index 99bdbda6f..712e7d0bf 100644 --- a/src/core/ngx_string.h +++ b/src/core/ngx_string.h @@ -183,6 +183,7 @@ u_char *ngx_hex_dump(u_char *dst, u_char *src, size_t len); #define ngx_base64_decoded_length(len) (((len + 3) / 4) * 3) void ngx_encode_base64(ngx_str_t *dst, ngx_str_t *src); +void ngx_encode_base64url(ngx_str_t *dst, ngx_str_t *src); ngx_int_t ngx_decode_base64(ngx_str_t *dst, ngx_str_t *src); ngx_int_t ngx_decode_base64url(ngx_str_t *dst, ngx_str_t *src); diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c index 9935fb098..cbe4136a1 100644 --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -2508,6 +2508,10 @@ ngx_ssl_get_session_id(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) SSL_SESSION *sess; sess = SSL_get0_session(c->ssl->connection); + if (sess == NULL) { + s->len = 0; + return NGX_OK; + } buf = sess->session_id; len = sess->session_id_length; diff --git a/src/http/modules/ngx_http_mp4_module.c b/src/http/modules/ngx_http_mp4_module.c index d900fb8d1..c29ab1ce5 100644 --- a/src/http/modules/ngx_http_mp4_module.c +++ b/src/http/modules/ngx_http_mp4_module.c @@ -1208,7 +1208,7 @@ ngx_http_mp4_read_mvhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size) u_char *atom_header; size_t atom_size; uint32_t timescale; - uint64_t duration; + uint64_t duration, start_time; ngx_buf_t *atom; ngx_mp4_mvhd_atom_t *mvhd_atom; ngx_mp4_mvhd64_atom_t *mvhd64_atom; @@ -1251,7 +1251,16 @@ ngx_http_mp4_read_mvhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size) "mvhd timescale:%uD, duration:%uL, time:%.3fs", timescale, duration, (double) duration / timescale); - duration -= (uint64_t) mp4->start * timescale / 1000; + start_time = (uint64_t) mp4->start * timescale / 1000; + + if (duration < start_time) { + ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, + "\"%s\" mp4 start time exceeds file duration", + mp4->file.name.data); + return NGX_ERROR; + } + + duration -= start_time; ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mvhd new duration:%uL, time:%.3fs", @@ -1398,7 +1407,7 @@ ngx_http_mp4_read_tkhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size) { u_char *atom_header; size_t atom_size; - uint64_t duration; + uint64_t duration, start_time; ngx_buf_t *atom; ngx_http_mp4_trak_t *trak; ngx_mp4_tkhd_atom_t *tkhd_atom; @@ -1438,7 +1447,15 @@ ngx_http_mp4_read_tkhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size) "tkhd duration:%uL, time:%.3fs", duration, (double) duration / mp4->timescale); - duration -= (uint64_t) mp4->start * mp4->timescale / 1000; + start_time = (uint64_t) mp4->start * mp4->timescale / 1000; + + if (duration < start_time) { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, + "tkhd duration is less than start time"); + return NGX_DECLINED; + } + + duration -= start_time; ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "tkhd new duration:%uL, time:%.3fs", @@ -1541,7 +1558,7 @@ ngx_http_mp4_read_mdhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size) u_char *atom_header; size_t atom_size; uint32_t timescale; - uint64_t duration; + uint64_t duration, start_time; ngx_buf_t *atom; ngx_http_mp4_trak_t *trak; ngx_mp4_mdhd_atom_t *mdhd_atom; @@ -1583,7 +1600,15 @@ ngx_http_mp4_read_mdhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size) "mdhd timescale:%uD, duration:%uL, time:%.3fs", timescale, duration, (double) duration / timescale); - duration -= (uint64_t) mp4->start * timescale / 1000; + start_time = (uint64_t) mp4->start * timescale / 1000; + + if (duration < start_time) { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, + "mdhd duration is less than start time"); + return NGX_DECLINED; + } + + duration -= start_time; ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mdhd new duration:%uL, time:%.3fs", @@ -2153,11 +2178,8 @@ ngx_http_mp4_update_stss_atom(ngx_http_mp4_file_t *mp4, entry++; } - ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0, - "start sample is out of mp4 stss atom in \"%s\"", - mp4->file.name.data); - - return NGX_ERROR; + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, + "start sample is out of mp4 stss atom"); found: @@ -2472,7 +2494,7 @@ ngx_http_mp4_update_stsc_atom(ngx_http_mp4_file_t *mp4, entry++; } - next_chunk = trak->chunks; + next_chunk = trak->chunks + 1; ngx_log_debug4(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "start_sample:%uD, chunk:%uD, chunks:%uD, samples:%uD", diff --git a/src/http/modules/ngx_http_range_filter_module.c b/src/http/modules/ngx_http_range_filter_module.c index 82c202d33..6143a8786 100644 --- a/src/http/modules/ngx_http_range_filter_module.c +++ b/src/http/modules/ngx_http_range_filter_module.c @@ -22,7 +22,7 @@ * ... data ... * * - * the mutlipart format: + * the multipart format: * * "HTTP/1.0 206 Partial Content" CRLF * ... header ... diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c index a53cd1472..aeb1376b7 100644 --- a/src/http/modules/ngx_http_ssi_filter_module.c +++ b/src/http/modules/ngx_http_ssi_filter_module.c @@ -213,6 +213,7 @@ static ngx_http_output_body_filter_pt ngx_http_next_body_filter; static u_char ngx_http_ssi_string[] = "