diff -Nru nginx-1.9.3/auto/endianness nginx-1.9.6/auto/endianness --- nginx-1.9.3/auto/endianness 2015-07-14 12:46:06.000000000 -0400 +++ nginx-1.9.6/auto/endianness 2015-10-27 09:47:30.000000000 -0400 @@ -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 -Nru nginx-1.9.3/auto/make nginx-1.9.6/auto/make --- nginx-1.9.3/auto/make 2015-07-14 12:46:06.000000000 -0400 +++ nginx-1.9.6/auto/make 2015-10-27 09:47:30.000000000 -0400 @@ -7,7 +7,7 @@ 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 -Nru nginx-1.9.3/auto/modules nginx-1.9.6/auto/modules --- nginx-1.9.3/auto/modules 2015-07-14 12:46:06.000000000 -0400 +++ nginx-1.9.6/auto/modules 2015-10-27 09:47:30.000000000 -0400 @@ -94,7 +94,7 @@ # 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_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 @@ 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 -Nru nginx-1.9.3/auto/options nginx-1.9.6/auto/options --- nginx-1.9.3/auto/options 2015-07-14 12:46:06.000000000 -0400 +++ nginx-1.9.6/auto/options 2015-10-27 09:47:30.000000000 -0400 @@ -58,7 +58,7 @@ 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 @@ --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 @@ --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 -Nru nginx-1.9.3/auto/sources nginx-1.9.6/auto/sources --- nginx-1.9.3/auto/sources 2015-07-14 12:46:06.000000000 -0400 +++ nginx-1.9.6/auto/sources 2015-10-27 09:47:30.000000000 -0400 @@ -317,13 +317,17 @@ 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 -Nru nginx-1.9.3/auto/types/uintptr_t nginx-1.9.6/auto/types/uintptr_t --- nginx-1.9.3/auto/types/uintptr_t 2015-07-14 12:46:06.000000000 -0400 +++ nginx-1.9.6/auto/types/uintptr_t 2015-10-27 09:47:30.000000000 -0400 @@ -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 -Nru nginx-1.9.3/CHANGES nginx-1.9.6/CHANGES --- nginx-1.9.3/CHANGES 2015-07-14 12:46:12.000000000 -0400 +++ nginx-1.9.6/CHANGES 2015-10-27 09:47:35.000000000 -0400 @@ -1,4 +1,92 @@ +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). + 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" + 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 +145,7 @@ *) 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 -Nru nginx-1.9.3/CHANGES.ru nginx-1.9.6/CHANGES.ru --- nginx-1.9.3/CHANGES.ru 2015-07-14 12:46:10.000000000 -0400 +++ nginx-1.9.6/CHANGES.ru 2015-10-27 09:47:33.000000000 -0400 @@ -1,4 +1,95 @@ +Изменения в 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 (заменяет модуль + 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 + в модуле 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 +147,7 @@ поддерживаются. *) Добавление: параметр reuseport директивы listen. - Спасибо Sepherosa Ziehau и Yingqi Lu. + Спасибо Yingqi Lu из Intel и Sepherosa Ziehau. *) Добавление: переменная $upstream_connect_time. diff -Nru nginx-1.9.3/debian/changelog nginx-1.9.6/debian/changelog --- nginx-1.9.3/debian/changelog 2015-07-22 11:39:55.000000000 -0400 +++ nginx-1.9.6/debian/changelog 2015-12-15 10:55:27.000000000 -0500 @@ -1,3 +1,55 @@ +nginx (1.9.6-2ubuntu1) xenial; urgency=medium + + * Merge from Debian unstable. Remaining changes: (LP: #1510096) + - debian/patches/ubuntu-branding.patch: add Ubuntu branding (refreshed) + - d/{control,rules,nginx-core.*}: add new binary package for main, + nginx-core, which contains only source-tarball-included modules + and no third-party modules. + - debian/tests/control: add nginx-core test. + - debian/control: drop luajit from Build-Depends as it is in universe. + - debian/apport/source_nginx.py: Add apport hooks for additional bug + information gathering. + - debian/nginx-common.install: Add install rule for apport hooks. + * Additional changes: + * debian/rules: + - Update nginx-core configure flags to match nginx-full config flags, + due to refreshing the nginx-core 'enabled modules' to match the + nginx-full modules (minus third-party modules) + - Disable HTTP/2 module support in all flavors, per Ubuntu Security + Team mandate. + * debian/control: + - Update nginx-core description to match nginx-full description of the + standard and optional HTTP modules that are enabled. + - Remove HTTP/2 references in package descriptions, per Ubuntu + Security Team mandate to disable HTTP/2 support. + + -- Thomas Ward Mon, 14 Dec 2015 10:34:42 -0500 + +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:08:01 +0200 + +nginx (1.9.6-1) unstable; urgency=medium + + [ Christos Trochalakis] + * New upstream release. + * Enable http2 module in nginx-full & nginx-extras + + -- Christos Trochalakis Tue, 03 Nov 2015 08:59:21 +0200 + +nginx (1.9.4-1) unstable; urgency=medium + + [ Christos Trochalakis] + * New upstream release. + * debian/copyright: + + Fix licence order. + + -- Christos Trochalakis Mon, 24 Aug 2015 16:23:20 +0300 + nginx (1.9.3-1ubuntu1) wily; urgency=medium * Merge from Debian. Remaining changes: (LP: #1476811) diff -Nru nginx-1.9.3/debian/control nginx-1.9.6/debian/control --- nginx-1.9.3/debian/control 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/control 2015-12-15 10:00:47.000000000 -0500 @@ -96,16 +96,16 @@ standard modules included (but omitting some of those included in nginx-extras). . - STANDARD HTTP MODULES: Core, Access, Auth Basic, Auto Index, Browser, - Charset, Empty GIF, FastCGI, Geo, Gzip, Headers, Index, Limit Requests, - Limit Zone, Log, Map, Memcached, Proxy, Referer, Rewrite, SCGI, - Split Clients, SSI, Upstream, User ID, UWSGI. + STANDARD HTTP MODULES: Core, Access, Auth Basic, Auto Index, Browser, Empty + GIF, FastCGI, Geo, Limit Connections, Limit Requests, Map, Memcached, Proxy, + Referer, Rewrite, SCGI, Split Clients, UWSGI. . - OPTIONAL HTTP MODULES: Addition, Debug, GeoIP, Gzip Precompression, HTTP Sub, - Image Filter, IPv6, Real IP, Spdy, SSL, Stub Status, Substitution, WebDAV, + OPTIONAL HTTP MODULES: Addition, Auth Request, Charset, WebDAV, GeoIP, Gunzip, + Gzip, Gzip Precompression, Headers, Image Filter, Index, Log, Real IP, + SSI, SSL, Stream, Stub Status, Substitution, Thread Pool, Upstream, User ID, XSLT. . - MAIL MODULES: Mail Core, IMAP, POP3, SMTP, SSL. + MAIL MODULES: Mail Core, Auth HTTP, Proxy, SSL, IMAP, POP3, SMTP. . NOTE: This is identical to the -full build, but without any third party modules built in. @@ -145,7 +145,7 @@ 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, Image Filter, Index, Log, Real IP, SSI, SSL, Stream, Stub Status, Substitution, Thread Pool, Upstream, User ID, XSLT. . @@ -232,8 +232,8 @@ 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 -Nru nginx-1.9.3/debian/copyright nginx-1.9.6/debian/copyright --- nginx-1.9.3/debian/copyright 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/copyright 2015-11-13 17:30:26.000000000 -0500 @@ -7,29 +7,36 @@ 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 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 +96,6 @@ 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. . diff -Nru nginx-1.9.3/debian/modules/nginx-lua/config nginx-1.9.6/debian/modules/nginx-lua/config --- nginx-1.9.3/debian/modules/nginx-lua/config 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/config 2015-11-13 17:30:29.000000000 -0500 @@ -14,32 +14,77 @@ 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 + 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" - . auto/feature + # 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_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)" + # 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 @@ 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 @@ . 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 @@ 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_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_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 -Nru nginx-1.9.3/debian/modules/nginx-lua/doc/HttpLuaModule.wiki nginx-1.9.6/debian/modules/nginx-lua/doc/HttpLuaModule.wiki --- nginx-1.9.3/debian/modules/nginx-lua/doc/HttpLuaModule.wiki 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/doc/HttpLuaModule.wiki 2015-11-13 17:30:29.000000000 -0500 @@ -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 @@ = 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 @@ 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 @@ 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; - - content_by_lua 'ngx.print(ngx.var.request_body)'; + 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 - 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 @@ } 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 @@ * [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 @@ = 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 @@ 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 @@ 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 @@ # 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 @@ 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 @@ = 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 @@ '''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 @@ 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 @@ '''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 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 @@ '''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 @@ 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 @@ 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 @@ 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 @@ '''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 @@ '''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 @@ 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 @@ '''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 @@ 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 @@ '''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 @@ 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 @@ '''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 @@ 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 @@ '''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 @@ 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 @@ 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. ngx.var.args = nil @@ -2125,6 +2300,8 @@ to prevent (temporary) memory leaking within the current request's lifetime. Another way of caching the result is to use the [[#ngx.ctx|ngx.ctx]] 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. == Core constants == @@ -2349,7 +2526,7 @@ 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. @@ -2884,7 +3061,7 @@ '''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 @@ 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 @@ 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 @@ 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 -Nru nginx-1.9.3/debian/modules/nginx-lua/README.markdown nginx-1.9.6/debian/modules/nginx-lua/README.markdown --- nginx-1.9.3/debian/modules/nginx-lua/README.markdown 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/README.markdown 2015-11-13 17:30:29.000000000 -0500 @@ -6,7 +6,7 @@ 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 @@ 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 @@ 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 @@ 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_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 - content_by_lua 'ngx.print(ngx.var.request_body)'; + -- 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 @@ } 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 @@ * [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 @@ =================== 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 @@ 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 @@ ```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 @@ # 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 @@ 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 @@ 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 @@ * [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 @@ **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 @@ [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 @@ **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 @@ [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 @@ **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 @@ 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 @@ ```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 @@ [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 @@ **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 @@ [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 @@ **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 @@ [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 @@ **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 @@ [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 @@ **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 @@ [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 @@ **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 @@ [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 @@ **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 @@ [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 @@ 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 @@ 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 @@ 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 @@ **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 @@ 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 @@ 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 @@ 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 @@ ```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 -Nru nginx-1.9.3/debian/modules/nginx-lua/src/api/ngx_http_lua_api.h nginx-1.9.6/debian/modules/nginx-lua/src/api/ngx_http_lua_api.h --- nginx-1.9.3/debian/modules/nginx-lua/src/api/ngx_http_lua_api.h 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/src/api/ngx_http_lua_api.h 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/src/ddebug.h nginx-1.9.6/debian/modules/nginx-lua/src/ddebug.h --- nginx-1.9.3/debian/modules/nginx-lua/src/ddebug.h 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/src/ddebug.h 2015-11-13 17:30:30.000000000 -0500 @@ -28,7 +28,8 @@ #include -static void dd(const char *fmt, ...) { +static ngx_inline void +dd(const char *fmt, ...) { } # endif @@ -43,7 +44,8 @@ #include -static void dd(const char *fmt, ...) { +static ngx_inline void +dd(const char *fmt, ...) { } # endif diff -Nru nginx-1.9.3/debian/modules/nginx-lua/src/ngx_http_lua_directive.c nginx-1.9.6/debian/modules/nginx-lua/src/ngx_http_lua_directive.c --- nginx-1.9.3/debian/modules/nginx-lua/src/ngx_http_lua_directive.c 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/src/ngx_http_lua_directive.c 2015-11-13 17:30:30.000000000 -0500 @@ -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 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 * @@ -190,6 +221,25 @@ #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) { u_char *p; @@ -373,6 +423,25 @@ 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) { u_char *p, *chunkname; @@ -468,6 +537,25 @@ 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) { u_char *p, *chunkname; @@ -559,6 +647,25 @@ 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) { u_char *p; @@ -583,6 +690,9 @@ 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, @@ -660,6 +770,25 @@ 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) { u_char *p, *chunkname; @@ -750,6 +879,25 @@ 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) { @@ -831,6 +979,25 @@ 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) { @@ -913,6 +1080,25 @@ 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) { @@ -961,6 +1147,25 @@ 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 @@ } +/* 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 -Nru nginx-1.9.3/debian/modules/nginx-lua/src/ngx_http_lua_directive.h nginx-1.9.6/debian/modules/nginx-lua/src/ngx_http_lua_directive.h --- nginx-1.9.3/debian/modules/nginx-lua/src/ngx_http_lua_directive.h 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/src/ngx_http_lua_directive.h 2015-11-13 17:30:29.000000000 -0500 @@ -17,26 +17,44 @@ 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 -Nru nginx-1.9.3/debian/modules/nginx-lua/src/ngx_http_lua_headers_in.c nginx-1.9.6/debian/modules/nginx-lua/src/ngx_http_lua_headers_in.c --- nginx-1.9.3/debian/modules/nginx-lua/src/ngx_http_lua_headers_in.c 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/src/ngx_http_lua_headers_in.c 2015-11-13 17:30:30.000000000 -0500 @@ -44,17 +44,6 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 -Nru nginx-1.9.3/debian/modules/nginx-lua/src/ngx_http_lua_headers_out.c nginx-1.9.6/debian/modules/nginx-lua/src/ngx_http_lua_headers_out.c --- nginx-1.9.3/debian/modules/nginx-lua/src/ngx_http_lua_headers_out.c 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/src/ngx_http_lua_headers_out.c 2015-11-13 17:30:30.000000000 -0500 @@ -385,7 +385,19 @@ 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 -Nru nginx-1.9.3/debian/modules/nginx-lua/src/ngx_http_lua_initworkerby.c nginx-1.9.6/debian/modules/nginx-lua/src/ngx_http_lua_initworkerby.c --- nginx-1.9.3/debian/modules/nginx-lua/src/ngx_http_lua_initworkerby.c 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/src/ngx_http_lua_initworkerby.c 2015-11-13 17:30:30.000000000 -0500 @@ -167,6 +167,8 @@ 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 @@ goto failed; } } - - http_ctx.srv_conf[ngx_modules[i]->ctx_index] = cur; } if (module->create_loc_conf) { @@ -188,6 +188,8 @@ 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 @@ goto failed; } } - - http_ctx.loc_conf[ngx_modules[i]->ctx_index] = cur; } } diff -Nru nginx-1.9.3/debian/modules/nginx-lua/src/ngx_http_lua_lex.c nginx-1.9.6/debian/modules/nginx-lua/src/ngx_http_lua_lex.c --- nginx-1.9.3/debian/modules/nginx-lua/src/ngx_http_lua_lex.c 1969-12-31 19:00:00.000000000 -0500 +++ nginx-1.9.6/debian/modules/nginx-lua/src/ngx_http_lua_lex.c 2015-11-13 09:08:16.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/src/ngx_http_lua_lex.h nginx-1.9.6/debian/modules/nginx-lua/src/ngx_http_lua_lex.h --- nginx-1.9.3/debian/modules/nginx-lua/src/ngx_http_lua_lex.h 1969-12-31 19:00:00.000000000 -0500 +++ nginx-1.9.6/debian/modules/nginx-lua/src/ngx_http_lua_lex.h 2015-11-13 09:08:16.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/src/ngx_http_lua_module.c nginx-1.9.6/debian/modules/nginx-lua/src/ngx_http_lua_module.c --- nginx-1.9.3/debian/modules/nginx-lua/src/ngx_http_lua_module.c 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/src/ngx_http_lua_module.c 2015-11-13 17:30:29.000000000 -0500 @@ -149,6 +149,13 @@ 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 @@ 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 @@ (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 @@ (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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 -Nru nginx-1.9.3/debian/modules/nginx-lua/src/ngx_http_lua_shdict.c nginx-1.9.6/debian/modules/nginx-lua/src/ngx_http_lua_shdict.c --- nginx-1.9.3/debian/modules/nginx-lua/src/ngx_http_lua_shdict.c 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/src/ngx_http_lua_shdict.c 2015-11-13 17:30:29.000000000 -0500 @@ -36,11 +36,20 @@ 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 @@ 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 @@ } +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 @@ "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 @@ 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 @@ 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 @@ "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 @@ "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 @@ } 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 @@ 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 @@ if (name->len == name_len && ngx_strncmp(name->data, name_data, name_len) == 0) { - return zone; + return &zone[i]; } } @@ -1522,7 +1555,7 @@ } 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 -Nru nginx-1.9.3/debian/modules/nginx-lua/src/ngx_http_lua_socket_tcp.c nginx-1.9.6/debian/modules/nginx-lua/src/ngx_http_lua_socket_tcp.c --- nginx-1.9.3/debian/modules/nginx-lua/src/ngx_http_lua_socket_tcp.c 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/src/ngx_http_lua_socket_tcp.c 2015-11-13 17:30:29.000000000 -0500 @@ -223,7 +223,7 @@ /* {{{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 @@ /* {{{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 @@ } #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 -Nru nginx-1.9.3/debian/modules/nginx-lua/src/ngx_http_lua_socket_udp.c nginx-1.9.6/debian/modules/nginx-lua/src/ngx_http_lua_socket_udp.c --- nginx-1.9.3/debian/modules/nginx-lua/src/ngx_http_lua_socket_udp.c 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/src/ngx_http_lua_socket_udp.c 2015-11-13 17:30:30.000000000 -0500 @@ -82,7 +82,7 @@ /* 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 -Nru nginx-1.9.3/debian/modules/nginx-lua/src/ngx_http_lua_subrequest.c nginx-1.9.6/debian/modules/nginx-lua/src/ngx_http_lua_subrequest.c --- nginx-1.9.3/debian/modules/nginx-lua/src/ngx_http_lua_subrequest.c 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/src/ngx_http_lua_subrequest.c 2015-11-13 17:30:29.000000000 -0500 @@ -116,7 +116,7 @@ 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 @@ 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 @@ 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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/000--init.t nginx-1.9.6/debian/modules/nginx-lua/t/000--init.t --- nginx-1.9.3/debian/modules/nginx-lua/t/000--init.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/000--init.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/000-sanity.t nginx-1.9.6/debian/modules/nginx-lua/t/000-sanity.t --- nginx-1.9.3/debian/modules/nginx-lua/t/000-sanity.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/000-sanity.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/001-set.t nginx-1.9.6/debian/modules/nginx-lua/t/001-set.t --- nginx-1.9.3/debian/modules/nginx-lua/t/001-set.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/001-set.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/002-content.t nginx-1.9.6/debian/modules/nginx-lua/t/002-content.t --- nginx-1.9.3/debian/modules/nginx-lua/t/002-content.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/002-content.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/003-errors.t nginx-1.9.6/debian/modules/nginx-lua/t/003-errors.t --- nginx-1.9.3/debian/modules/nginx-lua/t/003-errors.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/003-errors.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/004-require.t nginx-1.9.6/debian/modules/nginx-lua/t/004-require.t --- nginx-1.9.3/debian/modules/nginx-lua/t/004-require.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/004-require.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/005-exit.t nginx-1.9.6/debian/modules/nginx-lua/t/005-exit.t --- nginx-1.9.3/debian/modules/nginx-lua/t/005-exit.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/005-exit.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/006-escape.t nginx-1.9.6/debian/modules/nginx-lua/t/006-escape.t --- nginx-1.9.3/debian/modules/nginx-lua/t/006-escape.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/006-escape.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/007-md5.t nginx-1.9.6/debian/modules/nginx-lua/t/007-md5.t --- nginx-1.9.3/debian/modules/nginx-lua/t/007-md5.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/007-md5.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/008-today.t nginx-1.9.6/debian/modules/nginx-lua/t/008-today.t --- nginx-1.9.3/debian/modules/nginx-lua/t/008-today.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/008-today.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/009-log.t nginx-1.9.6/debian/modules/nginx-lua/t/009-log.t --- nginx-1.9.3/debian/modules/nginx-lua/t/009-log.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/009-log.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/010-request_body.t nginx-1.9.6/debian/modules/nginx-lua/t/010-request_body.t --- nginx-1.9.3/debian/modules/nginx-lua/t/010-request_body.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/010-request_body.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/011-md5_bin.t nginx-1.9.6/debian/modules/nginx-lua/t/011-md5_bin.t --- nginx-1.9.3/debian/modules/nginx-lua/t/011-md5_bin.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/011-md5_bin.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/012-now.t nginx-1.9.6/debian/modules/nginx-lua/t/012-now.t --- nginx-1.9.3/debian/modules/nginx-lua/t/012-now.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/012-now.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/013-base64.t nginx-1.9.6/debian/modules/nginx-lua/t/013-base64.t --- nginx-1.9.3/debian/modules/nginx-lua/t/013-base64.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/013-base64.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/014-bugs.t nginx-1.9.6/debian/modules/nginx-lua/t/014-bugs.t --- nginx-1.9.3/debian/modules/nginx-lua/t/014-bugs.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/014-bugs.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/015-status.t nginx-1.9.6/debian/modules/nginx-lua/t/015-status.t --- nginx-1.9.3/debian/modules/nginx-lua/t/015-status.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/015-status.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/016-resp-header.t nginx-1.9.6/debian/modules/nginx-lua/t/016-resp-header.t --- nginx-1.9.3/debian/modules/nginx-lua/t/016-resp-header.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/016-resp-header.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 @@ 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 @@ --- 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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/017-exec.t nginx-1.9.6/debian/modules/nginx-lua/t/017-exec.t --- nginx-1.9.3/debian/modules/nginx-lua/t/017-exec.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/017-exec.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/018-ndk.t nginx-1.9.6/debian/modules/nginx-lua/t/018-ndk.t --- nginx-1.9.3/debian/modules/nginx-lua/t/018-ndk.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/018-ndk.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/019-const.t nginx-1.9.6/debian/modules/nginx-lua/t/019-const.t --- nginx-1.9.3/debian/modules/nginx-lua/t/019-const.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/019-const.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/020-subrequest.t nginx-1.9.6/debian/modules/nginx-lua/t/020-subrequest.t --- nginx-1.9.3/debian/modules/nginx-lua/t/020-subrequest.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/020-subrequest.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 @@ #log_level('warn'); #master_process_enabled(1); +no_root_location; repeat_each(2); plan tests => repeat_each() * (blocks() * 3 + 22); @@ -2797,3 +2798,76 @@ --- 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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/021-cookie-time.t nginx-1.9.6/debian/modules/nginx-lua/t/021-cookie-time.t --- nginx-1.9.3/debian/modules/nginx-lua/t/021-cookie-time.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/021-cookie-time.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/022-redirect.t nginx-1.9.6/debian/modules/nginx-lua/t/022-redirect.t --- nginx-1.9.3/debian/modules/nginx-lua/t/022-redirect.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/022-redirect.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/client-abort.t nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/client-abort.t --- nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/client-abort.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/client-abort.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/exec.t nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/exec.t --- nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/exec.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/exec.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/exit.t nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/exit.t --- nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/exit.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/exit.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/mixed.t nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/mixed.t --- nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/mixed.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/mixed.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/multi-capture.t nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/multi-capture.t --- nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/multi-capture.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/multi-capture.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/on-abort.t nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/on-abort.t --- nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/on-abort.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/on-abort.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/redirect.t nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/redirect.t --- nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/redirect.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/redirect.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/req-body.t nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/req-body.t --- nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/req-body.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/req-body.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/req-socket.t nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/req-socket.t --- nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/req-socket.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/req-socket.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/request_body.t nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/request_body.t --- nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/request_body.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/request_body.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/sanity.t nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/sanity.t --- nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/sanity.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/sanity.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/sleep.t nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/sleep.t --- nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/sleep.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/sleep.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/socket-keepalive.t nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/socket-keepalive.t --- nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/socket-keepalive.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/socket-keepalive.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/subrequest.t nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/subrequest.t --- nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/subrequest.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/subrequest.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/tcp-socket.t nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/tcp-socket.t --- nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/tcp-socket.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/tcp-socket.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/tcp-socket-timeout.t nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/tcp-socket-timeout.t --- nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/tcp-socket-timeout.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/tcp-socket-timeout.t 2015-11-13 17:30:31.000000000 -0500 @@ -20,7 +20,6 @@ $ENV{MOCKEAGAIN_WRITE_TIMEOUT_PATTERN} = 'get helloworld'; } -use lib 'lib'; use Test::Nginx::Socket::Lua; repeat_each(2); diff -Nru nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/unix-socket.t nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/unix-socket.t --- nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/unix-socket.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/unix-socket.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/uthread-exec.t nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/uthread-exec.t --- nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/uthread-exec.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/uthread-exec.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/uthread-exit.t nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/uthread-exit.t --- nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/uthread-exit.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/uthread-exit.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/uthread-redirect.t nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/uthread-redirect.t --- nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/uthread-redirect.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/uthread-redirect.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/uthread-spawn.t nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/uthread-spawn.t --- nginx-1.9.3/debian/modules/nginx-lua/t/023-rewrite/uthread-spawn.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/023-rewrite/uthread-spawn.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/024-access/auth.t nginx-1.9.6/debian/modules/nginx-lua/t/024-access/auth.t --- nginx-1.9.3/debian/modules/nginx-lua/t/024-access/auth.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/024-access/auth.t 2015-11-13 17:30:32.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/024-access/client-abort.t nginx-1.9.6/debian/modules/nginx-lua/t/024-access/client-abort.t --- nginx-1.9.3/debian/modules/nginx-lua/t/024-access/client-abort.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/024-access/client-abort.t 2015-11-13 17:30:32.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/024-access/exec.t nginx-1.9.6/debian/modules/nginx-lua/t/024-access/exec.t --- nginx-1.9.3/debian/modules/nginx-lua/t/024-access/exec.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/024-access/exec.t 2015-11-13 17:30:32.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/024-access/exit.t nginx-1.9.6/debian/modules/nginx-lua/t/024-access/exit.t --- nginx-1.9.3/debian/modules/nginx-lua/t/024-access/exit.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/024-access/exit.t 2015-11-13 17:30:32.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/024-access/mixed.t nginx-1.9.6/debian/modules/nginx-lua/t/024-access/mixed.t --- nginx-1.9.3/debian/modules/nginx-lua/t/024-access/mixed.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/024-access/mixed.t 2015-11-13 17:30:32.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/024-access/multi-capture.t nginx-1.9.6/debian/modules/nginx-lua/t/024-access/multi-capture.t --- nginx-1.9.3/debian/modules/nginx-lua/t/024-access/multi-capture.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/024-access/multi-capture.t 2015-11-13 17:30:32.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/024-access/on-abort.t nginx-1.9.6/debian/modules/nginx-lua/t/024-access/on-abort.t --- nginx-1.9.3/debian/modules/nginx-lua/t/024-access/on-abort.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/024-access/on-abort.t 2015-11-13 17:30:32.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/024-access/redirect.t nginx-1.9.6/debian/modules/nginx-lua/t/024-access/redirect.t --- nginx-1.9.3/debian/modules/nginx-lua/t/024-access/redirect.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/024-access/redirect.t 2015-11-13 17:30:32.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/024-access/req-body.t nginx-1.9.6/debian/modules/nginx-lua/t/024-access/req-body.t --- nginx-1.9.3/debian/modules/nginx-lua/t/024-access/req-body.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/024-access/req-body.t 2015-11-13 17:30:32.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/024-access/request_body.t nginx-1.9.6/debian/modules/nginx-lua/t/024-access/request_body.t --- nginx-1.9.3/debian/modules/nginx-lua/t/024-access/request_body.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/024-access/request_body.t 2015-11-13 17:30:32.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/024-access/sanity.t nginx-1.9.6/debian/modules/nginx-lua/t/024-access/sanity.t --- nginx-1.9.3/debian/modules/nginx-lua/t/024-access/sanity.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/024-access/sanity.t 2015-11-13 17:30:32.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/024-access/satisfy.t nginx-1.9.6/debian/modules/nginx-lua/t/024-access/satisfy.t --- nginx-1.9.3/debian/modules/nginx-lua/t/024-access/satisfy.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/024-access/satisfy.t 2015-11-13 17:30:32.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/024-access/sleep.t nginx-1.9.6/debian/modules/nginx-lua/t/024-access/sleep.t --- nginx-1.9.3/debian/modules/nginx-lua/t/024-access/sleep.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/024-access/sleep.t 2015-11-13 17:30:32.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/024-access/subrequest.t nginx-1.9.6/debian/modules/nginx-lua/t/024-access/subrequest.t --- nginx-1.9.3/debian/modules/nginx-lua/t/024-access/subrequest.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/024-access/subrequest.t 2015-11-13 17:30:32.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/024-access/uthread-exec.t nginx-1.9.6/debian/modules/nginx-lua/t/024-access/uthread-exec.t --- nginx-1.9.3/debian/modules/nginx-lua/t/024-access/uthread-exec.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/024-access/uthread-exec.t 2015-11-13 17:30:32.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/024-access/uthread-exit.t nginx-1.9.6/debian/modules/nginx-lua/t/024-access/uthread-exit.t --- nginx-1.9.3/debian/modules/nginx-lua/t/024-access/uthread-exit.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/024-access/uthread-exit.t 2015-11-13 17:30:32.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/024-access/uthread-redirect.t nginx-1.9.6/debian/modules/nginx-lua/t/024-access/uthread-redirect.t --- nginx-1.9.3/debian/modules/nginx-lua/t/024-access/uthread-redirect.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/024-access/uthread-redirect.t 2015-11-13 17:30:32.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/024-access/uthread-spawn.t nginx-1.9.6/debian/modules/nginx-lua/t/024-access/uthread-spawn.t --- nginx-1.9.3/debian/modules/nginx-lua/t/024-access/uthread-spawn.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/024-access/uthread-spawn.t 2015-11-13 17:30:32.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/025-codecache.t nginx-1.9.6/debian/modules/nginx-lua/t/025-codecache.t --- nginx-1.9.3/debian/modules/nginx-lua/t/025-codecache.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/025-codecache.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/026-mysql.t nginx-1.9.6/debian/modules/nginx-lua/t/026-mysql.t --- nginx-1.9.3/debian/modules/nginx-lua/t/026-mysql.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/026-mysql.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/027-multi-capture.t nginx-1.9.6/debian/modules/nginx-lua/t/027-multi-capture.t --- nginx-1.9.3/debian/modules/nginx-lua/t/027-multi-capture.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/027-multi-capture.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/028-req-header.t nginx-1.9.6/debian/modules/nginx-lua/t/028-req-header.t --- nginx-1.9.3/debian/modules/nginx-lua/t/028-req-header.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/028-req-header.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 @@ 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 @@ --- 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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/029-http-time.t nginx-1.9.6/debian/modules/nginx-lua/t/029-http-time.t --- nginx-1.9.3/debian/modules/nginx-lua/t/029-http-time.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/029-http-time.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/030-uri-args.t nginx-1.9.6/debian/modules/nginx-lua/t/030-uri-args.t --- nginx-1.9.3/debian/modules/nginx-lua/t/030-uri-args.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/030-uri-args.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/031-post-args.t nginx-1.9.6/debian/modules/nginx-lua/t/031-post-args.t --- nginx-1.9.3/debian/modules/nginx-lua/t/031-post-args.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/031-post-args.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/032-iolist.t nginx-1.9.6/debian/modules/nginx-lua/t/032-iolist.t --- nginx-1.9.3/debian/modules/nginx-lua/t/032-iolist.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/032-iolist.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/033-ctx.t nginx-1.9.6/debian/modules/nginx-lua/t/033-ctx.t --- nginx-1.9.3/debian/modules/nginx-lua/t/033-ctx.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/033-ctx.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/035-gmatch.t nginx-1.9.6/debian/modules/nginx-lua/t/035-gmatch.t --- nginx-1.9.3/debian/modules/nginx-lua/t/035-gmatch.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/035-gmatch.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/036-sub.t nginx-1.9.6/debian/modules/nginx-lua/t/036-sub.t --- nginx-1.9.3/debian/modules/nginx-lua/t/036-sub.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/036-sub.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/037-gsub.t nginx-1.9.6/debian/modules/nginx-lua/t/037-gsub.t --- nginx-1.9.3/debian/modules/nginx-lua/t/037-gsub.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/037-gsub.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/038-match-o.t nginx-1.9.6/debian/modules/nginx-lua/t/038-match-o.t --- nginx-1.9.3/debian/modules/nginx-lua/t/038-match-o.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/038-match-o.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/039-sub-o.t nginx-1.9.6/debian/modules/nginx-lua/t/039-sub-o.t --- nginx-1.9.3/debian/modules/nginx-lua/t/039-sub-o.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/039-sub-o.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/040-gsub-o.t nginx-1.9.6/debian/modules/nginx-lua/t/040-gsub-o.t --- nginx-1.9.3/debian/modules/nginx-lua/t/040-gsub-o.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/040-gsub-o.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/041-header-filter.t nginx-1.9.6/debian/modules/nginx-lua/t/041-header-filter.t --- nginx-1.9.3/debian/modules/nginx-lua/t/041-header-filter.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/041-header-filter.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/042-crc32.t nginx-1.9.6/debian/modules/nginx-lua/t/042-crc32.t --- nginx-1.9.3/debian/modules/nginx-lua/t/042-crc32.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/042-crc32.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/043-shdict.t nginx-1.9.6/debian/modules/nginx-lua/t/043-shdict.t --- nginx-1.9.3/debian/modules/nginx-lua/t/043-shdict.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/043-shdict.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 @@ #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 @@ --- 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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/044-req-body.t nginx-1.9.6/debian/modules/nginx-lua/t/044-req-body.t --- nginx-1.9.3/debian/modules/nginx-lua/t/044-req-body.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/044-req-body.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/045-ngx-var.t nginx-1.9.6/debian/modules/nginx-lua/t/045-ngx-var.t --- nginx-1.9.3/debian/modules/nginx-lua/t/045-ngx-var.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/045-ngx-var.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/046-hmac.t nginx-1.9.6/debian/modules/nginx-lua/t/046-hmac.t --- nginx-1.9.3/debian/modules/nginx-lua/t/046-hmac.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/046-hmac.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/047-match-jit.t nginx-1.9.6/debian/modules/nginx-lua/t/047-match-jit.t --- nginx-1.9.3/debian/modules/nginx-lua/t/047-match-jit.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/047-match-jit.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/048-match-dfa.t nginx-1.9.6/debian/modules/nginx-lua/t/048-match-dfa.t --- nginx-1.9.3/debian/modules/nginx-lua/t/048-match-dfa.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/048-match-dfa.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/049-gmatch-jit.t nginx-1.9.6/debian/modules/nginx-lua/t/049-gmatch-jit.t --- nginx-1.9.3/debian/modules/nginx-lua/t/049-gmatch-jit.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/049-gmatch-jit.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/050-gmatch-dfa.t nginx-1.9.6/debian/modules/nginx-lua/t/050-gmatch-dfa.t --- nginx-1.9.3/debian/modules/nginx-lua/t/050-gmatch-dfa.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/050-gmatch-dfa.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/051-sub-jit.t nginx-1.9.6/debian/modules/nginx-lua/t/051-sub-jit.t --- nginx-1.9.3/debian/modules/nginx-lua/t/051-sub-jit.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/051-sub-jit.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/052-sub-dfa.t nginx-1.9.6/debian/modules/nginx-lua/t/052-sub-dfa.t --- nginx-1.9.3/debian/modules/nginx-lua/t/052-sub-dfa.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/052-sub-dfa.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/053-gsub-jit.t nginx-1.9.6/debian/modules/nginx-lua/t/053-gsub-jit.t --- nginx-1.9.3/debian/modules/nginx-lua/t/053-gsub-jit.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/053-gsub-jit.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/054-gsub-dfa.t nginx-1.9.6/debian/modules/nginx-lua/t/054-gsub-dfa.t --- nginx-1.9.3/debian/modules/nginx-lua/t/054-gsub-dfa.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/054-gsub-dfa.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/055-subreq-vars.t nginx-1.9.6/debian/modules/nginx-lua/t/055-subreq-vars.t --- nginx-1.9.3/debian/modules/nginx-lua/t/055-subreq-vars.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/055-subreq-vars.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/056-flush.t nginx-1.9.6/debian/modules/nginx-lua/t/056-flush.t --- nginx-1.9.3/debian/modules/nginx-lua/t/056-flush.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/056-flush.t 2015-11-13 17:30:31.000000000 -0500 @@ -4,7 +4,6 @@ $ENV{TEST_NGINX_POSTPONE_OUTPUT} = 1; } -use lib 'lib'; use Test::Nginx::Socket::Lua; #worker_connections(1014); diff -Nru nginx-1.9.3/debian/modules/nginx-lua/t/057-flush-timeout.t nginx-1.9.6/debian/modules/nginx-lua/t/057-flush-timeout.t --- nginx-1.9.3/debian/modules/nginx-lua/t/057-flush-timeout.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/057-flush-timeout.t 2015-11-13 17:30:31.000000000 -0500 @@ -21,7 +21,6 @@ $ENV{TEST_NGINX_POSTPONE_OUTPUT} = 1; } -use lib 'lib'; use Test::Nginx::Socket::Lua; use t::StapThread; diff -Nru nginx-1.9.3/debian/modules/nginx-lua/t/058-tcp-socket.t nginx-1.9.6/debian/modules/nginx-lua/t/058-tcp-socket.t --- nginx-1.9.3/debian/modules/nginx-lua/t/058-tcp-socket.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/058-tcp-socket.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/059-unix-socket.t nginx-1.9.6/debian/modules/nginx-lua/t/059-unix-socket.t --- nginx-1.9.3/debian/modules/nginx-lua/t/059-unix-socket.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/059-unix-socket.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/060-lua-memcached.t nginx-1.9.6/debian/modules/nginx-lua/t/060-lua-memcached.t --- nginx-1.9.3/debian/modules/nginx-lua/t/060-lua-memcached.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/060-lua-memcached.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/061-lua-redis.t nginx-1.9.6/debian/modules/nginx-lua/t/061-lua-redis.t --- nginx-1.9.3/debian/modules/nginx-lua/t/061-lua-redis.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/061-lua-redis.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/062-count.t nginx-1.9.6/debian/modules/nginx-lua/t/062-count.t --- nginx-1.9.3/debian/modules/nginx-lua/t/062-count.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/062-count.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 @@ -=== 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 @@ --- 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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/063-abort.t nginx-1.9.6/debian/modules/nginx-lua/t/063-abort.t --- nginx-1.9.3/debian/modules/nginx-lua/t/063-abort.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/063-abort.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/064-pcall.t nginx-1.9.6/debian/modules/nginx-lua/t/064-pcall.t --- nginx-1.9.3/debian/modules/nginx-lua/t/064-pcall.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/064-pcall.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/065-tcp-socket-timeout.t nginx-1.9.6/debian/modules/nginx-lua/t/065-tcp-socket-timeout.t --- nginx-1.9.3/debian/modules/nginx-lua/t/065-tcp-socket-timeout.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/065-tcp-socket-timeout.t 2015-11-13 17:30:31.000000000 -0500 @@ -20,7 +20,6 @@ $ENV{MOCKEAGAIN_WRITE_TIMEOUT_PATTERN} = 'get helloworld'; } -use lib 'lib'; use Test::Nginx::Socket::Lua; use t::StapThread; diff -Nru nginx-1.9.3/debian/modules/nginx-lua/t/066-socket-receiveuntil.t nginx-1.9.6/debian/modules/nginx-lua/t/066-socket-receiveuntil.t --- nginx-1.9.3/debian/modules/nginx-lua/t/066-socket-receiveuntil.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/066-socket-receiveuntil.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/067-req-socket.t nginx-1.9.6/debian/modules/nginx-lua/t/067-req-socket.t --- nginx-1.9.3/debian/modules/nginx-lua/t/067-req-socket.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/067-req-socket.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/068-socket-keepalive.t nginx-1.9.6/debian/modules/nginx-lua/t/068-socket-keepalive.t --- nginx-1.9.3/debian/modules/nginx-lua/t/068-socket-keepalive.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/068-socket-keepalive.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/069-null.t nginx-1.9.6/debian/modules/nginx-lua/t/069-null.t --- nginx-1.9.3/debian/modules/nginx-lua/t/069-null.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/069-null.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/070-sha1.t nginx-1.9.6/debian/modules/nginx-lua/t/070-sha1.t --- nginx-1.9.3/debian/modules/nginx-lua/t/070-sha1.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/070-sha1.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/071-idle-socket.t nginx-1.9.6/debian/modules/nginx-lua/t/071-idle-socket.t --- nginx-1.9.3/debian/modules/nginx-lua/t/071-idle-socket.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/071-idle-socket.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/072-conditional-get.t nginx-1.9.6/debian/modules/nginx-lua/t/072-conditional-get.t --- nginx-1.9.3/debian/modules/nginx-lua/t/072-conditional-get.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/072-conditional-get.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/073-backtrace.t nginx-1.9.6/debian/modules/nginx-lua/t/073-backtrace.t --- nginx-1.9.3/debian/modules/nginx-lua/t/073-backtrace.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/073-backtrace.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/074-prefix-var.t nginx-1.9.6/debian/modules/nginx-lua/t/074-prefix-var.t --- nginx-1.9.3/debian/modules/nginx-lua/t/074-prefix-var.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/074-prefix-var.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/075-logby.t nginx-1.9.6/debian/modules/nginx-lua/t/075-logby.t --- nginx-1.9.3/debian/modules/nginx-lua/t/075-logby.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/075-logby.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/076-no-postpone.t nginx-1.9.6/debian/modules/nginx-lua/t/076-no-postpone.t --- nginx-1.9.3/debian/modules/nginx-lua/t/076-no-postpone.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/076-no-postpone.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/077-sleep.t nginx-1.9.6/debian/modules/nginx-lua/t/077-sleep.t --- nginx-1.9.3/debian/modules/nginx-lua/t/077-sleep.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/077-sleep.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/078-hup-vars.t nginx-1.9.6/debian/modules/nginx-lua/t/078-hup-vars.t --- nginx-1.9.3/debian/modules/nginx-lua/t/078-hup-vars.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/078-hup-vars.t 2015-11-13 17:30:31.000000000 -0500 @@ -12,7 +12,6 @@ } } -use lib 'lib'; use Test::Nginx::Socket::Lua $SkipReason ? (skip_all => $SkipReason) : (); #worker_connections(1014); diff -Nru nginx-1.9.3/debian/modules/nginx-lua/t/079-unused-directives.t nginx-1.9.6/debian/modules/nginx-lua/t/079-unused-directives.t --- nginx-1.9.3/debian/modules/nginx-lua/t/079-unused-directives.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/079-unused-directives.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 @@ repeat_each(2); -plan tests => repeat_each() * 120; +plan tests => repeat_each() * 110; #no_diff(); #no_long_string(); @@ -264,6 +263,9 @@ === 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 @@ === 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 @@ === 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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/080-hup-shdict.t nginx-1.9.6/debian/modules/nginx-lua/t/080-hup-shdict.t --- nginx-1.9.3/debian/modules/nginx-lua/t/080-hup-shdict.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/080-hup-shdict.t 2015-11-13 17:30:30.000000000 -0500 @@ -12,7 +12,6 @@ } } -use lib 'lib'; use Test::Nginx::Socket::Lua $SkipReason ? (skip_all => $SkipReason) : (); #worker_connections(1014); diff -Nru nginx-1.9.3/debian/modules/nginx-lua/t/081-bytecode.t nginx-1.9.6/debian/modules/nginx-lua/t/081-bytecode.t --- nginx-1.9.3/debian/modules/nginx-lua/t/081-bytecode.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/081-bytecode.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/082-body-filter.t nginx-1.9.6/debian/modules/nginx-lua/t/082-body-filter.t --- nginx-1.9.3/debian/modules/nginx-lua/t/082-body-filter.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/082-body-filter.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/083-bad-sock-self.t nginx-1.9.6/debian/modules/nginx-lua/t/083-bad-sock-self.t --- nginx-1.9.3/debian/modules/nginx-lua/t/083-bad-sock-self.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/083-bad-sock-self.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/084-inclusive-receiveuntil.t nginx-1.9.6/debian/modules/nginx-lua/t/084-inclusive-receiveuntil.t --- nginx-1.9.3/debian/modules/nginx-lua/t/084-inclusive-receiveuntil.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/084-inclusive-receiveuntil.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/085-if.t nginx-1.9.6/debian/modules/nginx-lua/t/085-if.t --- nginx-1.9.3/debian/modules/nginx-lua/t/085-if.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/085-if.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/086-init-by.t nginx-1.9.6/debian/modules/nginx-lua/t/086-init-by.t --- nginx-1.9.3/debian/modules/nginx-lua/t/086-init-by.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/086-init-by.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/087-udp-socket.t nginx-1.9.6/debian/modules/nginx-lua/t/087-udp-socket.t --- nginx-1.9.3/debian/modules/nginx-lua/t/087-udp-socket.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/087-udp-socket.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/088-req-method.t nginx-1.9.6/debian/modules/nginx-lua/t/088-req-method.t --- nginx-1.9.3/debian/modules/nginx-lua/t/088-req-method.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/088-req-method.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/090-log-socket-errors.t nginx-1.9.6/debian/modules/nginx-lua/t/090-log-socket-errors.t --- nginx-1.9.3/debian/modules/nginx-lua/t/090-log-socket-errors.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/090-log-socket-errors.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/091-coroutine.t nginx-1.9.6/debian/modules/nginx-lua/t/091-coroutine.t --- nginx-1.9.3/debian/modules/nginx-lua/t/091-coroutine.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/091-coroutine.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/092-eof.t nginx-1.9.6/debian/modules/nginx-lua/t/092-eof.t --- nginx-1.9.3/debian/modules/nginx-lua/t/092-eof.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/092-eof.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/093-uthread-spawn.t nginx-1.9.6/debian/modules/nginx-lua/t/093-uthread-spawn.t --- nginx-1.9.3/debian/modules/nginx-lua/t/093-uthread-spawn.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/093-uthread-spawn.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/094-uthread-exit.t nginx-1.9.6/debian/modules/nginx-lua/t/094-uthread-exit.t --- nginx-1.9.3/debian/modules/nginx-lua/t/094-uthread-exit.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/094-uthread-exit.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/095-uthread-exec.t nginx-1.9.6/debian/modules/nginx-lua/t/095-uthread-exec.t --- nginx-1.9.3/debian/modules/nginx-lua/t/095-uthread-exec.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/095-uthread-exec.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/096-uthread-redirect.t nginx-1.9.6/debian/modules/nginx-lua/t/096-uthread-redirect.t --- nginx-1.9.3/debian/modules/nginx-lua/t/096-uthread-redirect.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/096-uthread-redirect.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/097-uthread-rewrite.t nginx-1.9.6/debian/modules/nginx-lua/t/097-uthread-rewrite.t --- nginx-1.9.3/debian/modules/nginx-lua/t/097-uthread-rewrite.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/097-uthread-rewrite.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/098-uthread-wait.t nginx-1.9.6/debian/modules/nginx-lua/t/098-uthread-wait.t --- nginx-1.9.3/debian/modules/nginx-lua/t/098-uthread-wait.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/098-uthread-wait.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/099-c-api.t nginx-1.9.6/debian/modules/nginx-lua/t/099-c-api.t --- nginx-1.9.3/debian/modules/nginx-lua/t/099-c-api.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/099-c-api.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 @@ --- 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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/100-client-abort.t nginx-1.9.6/debian/modules/nginx-lua/t/100-client-abort.t --- nginx-1.9.3/debian/modules/nginx-lua/t/100-client-abort.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/100-client-abort.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/101-on-abort.t nginx-1.9.6/debian/modules/nginx-lua/t/101-on-abort.t --- nginx-1.9.3/debian/modules/nginx-lua/t/101-on-abort.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/101-on-abort.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/102-req-start-time.t nginx-1.9.6/debian/modules/nginx-lua/t/102-req-start-time.t --- nginx-1.9.3/debian/modules/nginx-lua/t/102-req-start-time.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/102-req-start-time.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/103-req-http-ver.t nginx-1.9.6/debian/modules/nginx-lua/t/103-req-http-ver.t --- nginx-1.9.3/debian/modules/nginx-lua/t/103-req-http-ver.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/103-req-http-ver.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/104-req-raw-header.t nginx-1.9.6/debian/modules/nginx-lua/t/104-req-raw-header.t --- nginx-1.9.3/debian/modules/nginx-lua/t/104-req-raw-header.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/104-req-raw-header.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/105-pressure.t nginx-1.9.6/debian/modules/nginx-lua/t/105-pressure.t --- nginx-1.9.3/debian/modules/nginx-lua/t/105-pressure.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/105-pressure.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/106-timer.t nginx-1.9.6/debian/modules/nginx-lua/t/106-timer.t --- nginx-1.9.3/debian/modules/nginx-lua/t/106-timer.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/106-timer.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/107-timer-errors.t nginx-1.9.6/debian/modules/nginx-lua/t/107-timer-errors.t --- nginx-1.9.3/debian/modules/nginx-lua/t/107-timer-errors.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/107-timer-errors.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/108-timer-safe.t nginx-1.9.6/debian/modules/nginx-lua/t/108-timer-safe.t --- nginx-1.9.3/debian/modules/nginx-lua/t/108-timer-safe.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/108-timer-safe.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/109-timer-hup.t nginx-1.9.6/debian/modules/nginx-lua/t/109-timer-hup.t --- nginx-1.9.3/debian/modules/nginx-lua/t/109-timer-hup.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/109-timer-hup.t 2015-11-13 17:30:30.000000000 -0500 @@ -12,7 +12,6 @@ } } -use lib 'lib'; use Test::Nginx::Socket::Lua $SkipReason ? (skip_all => $SkipReason) : (); diff -Nru nginx-1.9.3/debian/modules/nginx-lua/t/110-etag.t nginx-1.9.6/debian/modules/nginx-lua/t/110-etag.t --- nginx-1.9.3/debian/modules/nginx-lua/t/110-etag.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/110-etag.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/111-req-header-ua.t nginx-1.9.6/debian/modules/nginx-lua/t/111-req-header-ua.t --- nginx-1.9.3/debian/modules/nginx-lua/t/111-req-header-ua.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/111-req-header-ua.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/112-req-header-conn.t nginx-1.9.6/debian/modules/nginx-lua/t/112-req-header-conn.t --- nginx-1.9.3/debian/modules/nginx-lua/t/112-req-header-conn.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/112-req-header-conn.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/113-req-header-cookie.t nginx-1.9.6/debian/modules/nginx-lua/t/113-req-header-cookie.t --- nginx-1.9.3/debian/modules/nginx-lua/t/113-req-header-cookie.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/113-req-header-cookie.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/114-config.t nginx-1.9.6/debian/modules/nginx-lua/t/114-config.t --- nginx-1.9.3/debian/modules/nginx-lua/t/114-config.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/114-config.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/115-quote-sql-str.t nginx-1.9.6/debian/modules/nginx-lua/t/115-quote-sql-str.t --- nginx-1.9.3/debian/modules/nginx-lua/t/115-quote-sql-str.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/115-quote-sql-str.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/116-raw-req-socket.t nginx-1.9.6/debian/modules/nginx-lua/t/116-raw-req-socket.t --- nginx-1.9.3/debian/modules/nginx-lua/t/116-raw-req-socket.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/116-raw-req-socket.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/117-raw-req-socket-timeout.t nginx-1.9.6/debian/modules/nginx-lua/t/117-raw-req-socket-timeout.t --- nginx-1.9.3/debian/modules/nginx-lua/t/117-raw-req-socket-timeout.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/117-raw-req-socket-timeout.t 2015-11-13 17:30:31.000000000 -0500 @@ -21,7 +21,6 @@ $ENV{TEST_NGINX_POSTPONE_OUTPUT} = 1; } -use lib 'lib'; use Test::Nginx::Socket::Lua; use t::StapThread; diff -Nru nginx-1.9.3/debian/modules/nginx-lua/t/118-use-default-type.t nginx-1.9.6/debian/modules/nginx-lua/t/118-use-default-type.t --- nginx-1.9.3/debian/modules/nginx-lua/t/118-use-default-type.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/118-use-default-type.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/119-config-prefix.t nginx-1.9.6/debian/modules/nginx-lua/t/119-config-prefix.t --- nginx-1.9.3/debian/modules/nginx-lua/t/119-config-prefix.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/119-config-prefix.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/121-version.t nginx-1.9.6/debian/modules/nginx-lua/t/121-version.t --- nginx-1.9.3/debian/modules/nginx-lua/t/121-version.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/121-version.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/123-lua-path.t nginx-1.9.6/debian/modules/nginx-lua/t/123-lua-path.t --- nginx-1.9.3/debian/modules/nginx-lua/t/123-lua-path.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/123-lua-path.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/124-init-worker.t nginx-1.9.6/debian/modules/nginx-lua/t/124-init-worker.t --- nginx-1.9.3/debian/modules/nginx-lua/t/124-init-worker.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/124-init-worker.t 2015-11-13 17:30:31.000000000 -0500 @@ -9,7 +9,7 @@ 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 @@ 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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/125-configure-args.t nginx-1.9.6/debian/modules/nginx-lua/t/125-configure-args.t --- nginx-1.9.3/debian/modules/nginx-lua/t/125-configure-args.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/125-configure-args.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/126-shdict-frag.t nginx-1.9.6/debian/modules/nginx-lua/t/126-shdict-frag.t --- nginx-1.9.3/debian/modules/nginx-lua/t/126-shdict-frag.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/126-shdict-frag.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/127-uthread-kill.t nginx-1.9.6/debian/modules/nginx-lua/t/127-uthread-kill.t --- nginx-1.9.3/debian/modules/nginx-lua/t/127-uthread-kill.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/127-uthread-kill.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/128-duplex-tcp-socket.t nginx-1.9.6/debian/modules/nginx-lua/t/128-duplex-tcp-socket.t --- nginx-1.9.3/debian/modules/nginx-lua/t/128-duplex-tcp-socket.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/128-duplex-tcp-socket.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/129-ssl-socket.t nginx-1.9.6/debian/modules/nginx-lua/t/129-ssl-socket.t --- nginx-1.9.3/debian/modules/nginx-lua/t/129-ssl-socket.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/129-ssl-socket.t 2015-11-13 17:30:31.000000000 -0500 @@ -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 @@ --- 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 @@ --- 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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/130-internal-api.t nginx-1.9.6/debian/modules/nginx-lua/t/130-internal-api.t --- nginx-1.9.3/debian/modules/nginx-lua/t/130-internal-api.t 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/t/130-internal-api.t 2015-11-13 17:30:30.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/132-lua-blocks.t nginx-1.9.6/debian/modules/nginx-lua/t/132-lua-blocks.t --- nginx-1.9.3/debian/modules/nginx-lua/t/132-lua-blocks.t 1969-12-31 19:00:00.000000000 -0500 +++ nginx-1.9.6/debian/modules/nginx-lua/t/132-lua-blocks.t 2015-11-13 09:08:16.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/data/fake-module/config nginx-1.9.6/debian/modules/nginx-lua/t/data/fake-module/config --- nginx-1.9.3/debian/modules/nginx-lua/t/data/fake-module/config 1969-12-31 19:00:00.000000000 -0500 +++ nginx-1.9.6/debian/modules/nginx-lua/t/data/fake-module/config 2015-11-13 09:08:16.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/t/data/fake-module/ngx_http_fake_module.c nginx-1.9.6/debian/modules/nginx-lua/t/data/fake-module/ngx_http_fake_module.c --- nginx-1.9.3/debian/modules/nginx-lua/t/data/fake-module/ngx_http_fake_module.c 1969-12-31 19:00:00.000000000 -0500 +++ nginx-1.9.6/debian/modules/nginx-lua/t/data/fake-module/ngx_http_fake_module.c 2015-11-13 09:08:16.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/util/build2.sh nginx-1.9.6/debian/modules/nginx-lua/util/build2.sh --- nginx-1.9.3/debian/modules/nginx-lua/util/build2.sh 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/util/build2.sh 2015-11-13 17:30:30.000000000 -0500 @@ -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 @@ #--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 @@ --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 -Nru nginx-1.9.3/debian/modules/nginx-lua/util/build.sh nginx-1.9.6/debian/modules/nginx-lua/util/build.sh --- nginx-1.9.3/debian/modules/nginx-lua/util/build.sh 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/util/build.sh 1969-12-31 19:00:00.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/util/gen-lexer-c nginx-1.9.6/debian/modules/nginx-lua/util/gen-lexer-c --- nginx-1.9.3/debian/modules/nginx-lua/util/gen-lexer-c 1969-12-31 19:00:00.000000000 -0500 +++ nginx-1.9.6/debian/modules/nginx-lua/util/gen-lexer-c 2015-11-13 09:08:16.000000000 -0500 @@ -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 -Nru nginx-1.9.3/debian/modules/nginx-lua/valgrind.suppress nginx-1.9.6/debian/modules/nginx-lua/valgrind.suppress --- nginx-1.9.3/debian/modules/nginx-lua/valgrind.suppress 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/nginx-lua/valgrind.suppress 2015-11-13 17:30:29.000000000 -0500 @@ -104,6 +104,13 @@ fun:ngx_event_process_init } { + + Memcheck:Param + sendmsg(mmsg[0].msg_hdr) + fun:sendmmsg + fun:__libc_res_nsend +} +{ Memcheck:Param sendmsg(msg.msg_iov[0]) diff -Nru nginx-1.9.3/debian/modules/README.Modules-versions nginx-1.9.6/debian/modules/README.Modules-versions --- nginx-1.9.3/debian/modules/README.Modules-versions 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/modules/README.Modules-versions 2015-11-13 17:30:26.000000000 -0500 @@ -22,7 +22,7 @@ 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 -Nru nginx-1.9.3/debian/nginx-common.NEWS nginx-1.9.6/debian/nginx-common.NEWS --- nginx-1.9.3/debian/nginx-common.NEWS 2015-07-22 11:39:05.000000000 -0400 +++ nginx-1.9.6/debian/nginx-common.NEWS 2015-11-13 17:30:26.000000000 -0500 @@ -1,3 +1,10 @@ +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. + + -- 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 diff -Nru nginx-1.9.3/debian/patches/ubuntu-branding.patch nginx-1.9.6/debian/patches/ubuntu-branding.patch --- nginx-1.9.3/debian/patches/ubuntu-branding.patch 2015-07-22 11:39:27.000000000 -0400 +++ nginx-1.9.6/debian/patches/ubuntu-branding.patch 2015-12-14 09:38:54.000000000 -0500 @@ -1,7 +1,7 @@ Description: Add Ubuntu token to NGINX_VER Author: Adam Conrad Forwarded: not-needed -Last-Update: 2015-07-21 +Last-Update: 2015-12-14 Index: b/src/core/nginx.h =================================================================== @@ -9,8 +9,8 @@ +++ b/src/core/nginx.h @@ -11,7 +11,7 @@ - #define nginx_version 1009003 - #define NGINX_VERSION "1.9.3" + #define nginx_version 1009006 + #define NGINX_VERSION "1.9.6" -#define NGINX_VER "nginx/" NGINX_VERSION +#define NGINX_VER "nginx/" NGINX_VERSION " (Ubuntu)" diff -Nru nginx-1.9.3/debian/rules nginx-1.9.6/debian/rules --- nginx-1.9.3/debian/rules 2015-07-22 11:39:38.000000000 -0400 +++ nginx-1.9.6/debian/rules 2015-12-15 10:01:03.000000000 -0500 @@ -50,17 +50,20 @@ --with-http_auth_request_module core_configure_flags := \ - $(common_configure_flags) \ - --with-http_addition_module \ - --with-http_dav_module \ - --with-http_geoip_module \ - --with-http_gzip_static_module \ - --with-http_image_filter_module \ - --with-http_spdy_module \ - --with-http_sub_module \ - --with-http_xslt_module \ - --with-mail \ - --with-mail_ssl_module + $(common_configure_flags) \ + --with-http_addition_module \ + --with-http_dav_module \ + --with-http_geoip_module \ + --with-http_gunzip_module \ + --with-http_gzip_static_module \ + --with-http_image_filter_module \ + --with-http_sub_module \ + --with-http_xslt_module \ + --with-stream \ + --with-stream_ssl_module \ + --with-mail \ + --with-mail_ssl_module \ + --with-threads light_configure_flags := \ $(common_configure_flags) \ @@ -86,7 +89,6 @@ --with-http_gunzip_module \ --with-http_gzip_static_module \ --with-http_image_filter_module \ - --with-http_spdy_module \ --with-http_sub_module \ --with-http_xslt_module \ --with-stream \ @@ -113,7 +115,6 @@ --with-http_perl_module \ --with-http_random_index_module \ --with-http_secure_link_module \ - --with-http_spdy_module \ --with-http_sub_module \ --with-http_xslt_module \ --with-mail \ diff -Nru nginx-1.9.3/src/core/nginx.c nginx-1.9.6/src/core/nginx.c --- nginx-1.9.3/src/core/nginx.c 2015-07-14 12:46:06.000000000 -0400 +++ nginx-1.9.6/src/core/nginx.c 2015-10-27 09:47:30.000000000 -0400 @@ -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 @@ } 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 @@ } +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 @@ 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 @@ 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 -Nru nginx-1.9.3/src/core/nginx.h nginx-1.9.6/src/core/nginx.h --- nginx-1.9.3/src/core/nginx.h 2015-07-14 12:46:06.000000000 -0400 +++ nginx-1.9.6/src/core/nginx.h 2015-10-27 09:47:30.000000000 -0400 @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1009003 -#define NGINX_VERSION "1.9.3" +#define nginx_version 1009006 +#define NGINX_VERSION "1.9.6" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD diff -Nru nginx-1.9.3/src/core/ngx_connection.c nginx-1.9.6/src/core/ngx_connection.c --- nginx-1.9.3/src/core/ngx_connection.c 2015-07-14 12:46:06.000000000 -0400 +++ nginx-1.9.6/src/core/ngx_connection.c 2015-10-27 09:47:30.000000000 -0400 @@ -567,9 +567,19 @@ #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 @@ &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; @@ -1144,6 +1162,26 @@ } } + +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 != (ngx_socket_t) -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, diff -Nru nginx-1.9.3/src/core/ngx_connection.h nginx-1.9.6/src/core/ngx_connection.h --- nginx-1.9.3/src/core/ngx_connection.h 2015-07-14 12:46:06.000000000 -0400 +++ nginx-1.9.6/src/core/ngx_connection.h 2015-10-27 09:47:30.000000000 -0400 @@ -118,7 +118,7 @@ #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 { @@ -215,6 +215,7 @@ 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 -Nru nginx-1.9.3/src/core/ngx_hash.c nginx-1.9.6/src/core/ngx_hash.c --- nginx-1.9.3/src/core/ngx_hash.c 2015-07-14 12:46:06.000000000 -0400 +++ nginx-1.9.6/src/core/ngx_hash.c 2015-10-27 09:47:30.000000000 -0400 @@ -257,11 +257,19 @@ 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; @@ -735,6 +743,10 @@ 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 -Nru nginx-1.9.3/src/core/ngx_open_file_cache.c nginx-1.9.6/src/core/ngx_open_file_cache.c --- nginx-1.9.3/src/core/ngx_open_file_cache.c 2015-07-14 12:46:06.000000000 -0400 +++ nginx-1.9.6/src/core/ngx_open_file_cache.c 2015-10-27 09:47:30.000000000 -0400 @@ -128,7 +128,7 @@ 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 -Nru nginx-1.9.3/src/core/ngx_rwlock.c nginx-1.9.6/src/core/ngx_rwlock.c --- nginx-1.9.3/src/core/ngx_rwlock.c 2015-07-14 12:46:06.000000000 -0400 +++ nginx-1.9.6/src/core/ngx_rwlock.c 2015-10-27 09:47:30.000000000 -0400 @@ -111,7 +111,7 @@ #else -#if (NGX_HTTP_UPSTREAM_ZONE) +#if (NGX_HTTP_UPSTREAM_ZONE || NGX_STREAM_UPSTREAM_ZONE) #error ngx_atomic_cmp_set() is not defined! diff -Nru nginx-1.9.3/src/event/ngx_event.c nginx-1.9.6/src/event/ngx_event.c --- nginx-1.9.3/src/event/ngx_event.c 2015-07-14 12:46:06.000000000 -0400 +++ nginx-1.9.6/src/event/ngx_event.c 2015-10-27 09:47:30.000000000 -0400 @@ -670,6 +670,15 @@ } } +#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 -Nru nginx-1.9.3/src/event/ngx_event_openssl.c nginx-1.9.6/src/event/ngx_event_openssl.c --- nginx-1.9.3/src/event/ngx_event_openssl.c 2015-07-14 12:46:06.000000000 -0400 +++ nginx-1.9.6/src/event/ngx_event_openssl.c 2015-10-27 09:47:30.000000000 -0400 @@ -1038,6 +1038,8 @@ 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 @@ 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) */ @@ -1166,6 +1169,7 @@ } #endif +#endif return NGX_OK; } @@ -2043,7 +2047,7 @@ (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 @@ 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_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 @@ 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 @@ 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_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 -Nru nginx-1.9.3/src/event/ngx_event_openssl.h nginx-1.9.6/src/event/ngx_event_openssl.h --- nginx-1.9.3/src/event/ngx_event_openssl.h 2015-07-14 12:46:06.000000000 -0400 +++ nginx-1.9.6/src/event/ngx_event_openssl.h 2015-10-27 09:47:30.000000000 -0400 @@ -46,6 +46,7 @@ typedef struct { ngx_ssl_conn_t *connection; + SSL_CTX *session_ctx; ngx_int_t last; ngx_buf_t *buf; diff -Nru nginx-1.9.3/src/http/modules/ngx_http_fastcgi_module.c nginx-1.9.6/src/http/modules/ngx_http_fastcgi_module.c --- nginx-1.9.3/src/http/modules/ngx_http_fastcgi_module.c 2015-07-14 12:46:06.000000000 -0400 +++ nginx-1.9.6/src/http/modules/ngx_http_fastcgi_module.c 2015-10-27 09:47:30.000000000 -0400 @@ -1770,7 +1770,6 @@ #if (NGX_HTTP_CACHE) if (f->large_stderr && r->cache) { - u_char *start; ssize_t len; ngx_http_fastcgi_header_t *fh; diff -Nru nginx-1.9.3/src/http/modules/ngx_http_map_module.c nginx-1.9.6/src/http/modules/ngx_http_map_module.c --- nginx-1.9.3/src/http/modules/ngx_http_map_module.c 2015-07-14 12:46:06.000000000 -0400 +++ nginx-1.9.6/src/http/modules/ngx_http_map_module.c 2015-10-27 09:47:30.000000000 -0400 @@ -375,7 +375,7 @@ 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 @@ 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 -Nru nginx-1.9.3/src/http/modules/ngx_http_rewrite_module.c nginx-1.9.6/src/http/modules/ngx_http_rewrite_module.c --- nginx-1.9.3/src/http/modules/ngx_http_rewrite_module.c 2015-07-14 12:46:06.000000000 -0400 +++ nginx-1.9.6/src/http/modules/ngx_http_rewrite_module.c 2015-10-27 09:47:30.000000000 -0400 @@ -612,7 +612,7 @@ 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 -Nru nginx-1.9.3/src/http/modules/ngx_http_ssl_module.c nginx-1.9.6/src/http/modules/ngx_http_ssl_module.c --- nginx-1.9.3/src/http/modules/ngx_http_ssl_module.c 2015-07-14 12:46:06.000000000 -0400 +++ nginx-1.9.6/src/http/modules/ngx_http_ssl_module.c 2015-10-27 09:47:30.000000000 -0400 @@ -326,10 +326,10 @@ #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 @@ } #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 @@ 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 -Nru nginx-1.9.3/src/http/modules/ngx_http_sub_filter_module.c nginx-1.9.6/src/http/modules/ngx_http_sub_filter_module.c --- nginx-1.9.3/src/http/modules/ngx_http_sub_filter_module.c 2015-07-14 12:46:06.000000000 -0400 +++ nginx-1.9.6/src/http/modules/ngx_http_sub_filter_module.c 2015-10-27 09:47:30.000000000 -0400 @@ -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 @@ 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 @@ 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 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_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 @@ return NGX_ERROR; } - ctx->saved.data = ngx_pnalloc(r->pool, slcf->match.len); + if (slcf->dynamic == 0) { + ctx->tables = slcf->tables; + ctx->matches = slcf->matches; + + } 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->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, slcf->match.len); + ctx->looked.data = ngx_pnalloc(r->pool, ctx->tables->max_match_len - 1); if (ctx->looked.data == NULL) { return NGX_ERROR; } - ngx_http_set_ctx(r, ctx, ngx_http_sub_filter_module); - - ctx->match = slcf->match; + ctx->offset = ctx->tables->min_match_len - 1; ctx->last_out = &ctx->out; r->filter_need_in_memory = 1; @@ -194,8 +284,10 @@ { 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 @@ 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 @@ 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 @@ 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; + } + } + + sub = &ctx->sub[ctx->index]; - if (ngx_http_complex_value(r, &slcf->value, &ctx->sub) + 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 @@ *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 @@ } 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 @@ 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; - if (ctx->once) { - ctx->copy_start = ctx->pos; - ctx->copy_end = ctx->buf->last; - ctx->pos = ctx->buf->last; - ctx->looked.len = 0; + slcf = ngx_http_get_module_loc_conf(r, ngx_http_sub_filter_module); + tables = ctx->tables; - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "once"); + offset = ctx->offset; + end = ctx->buf->last - ctx->pos; - return NGX_AGAIN; + if (ctx->once) { + /* 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); + c = ngx_tolower(c); - if (state == sub_start_state) { + shift = tables->shift[c]; + if (shift > 0) { + offset += shift; + continue; + } - /* the tight loop */ + /* a potential match */ - match = ctx->match.data[0]; + start = offset - (ngx_int_t) tables->min_match_len + 1; + match = ctx->matches->elts; - for ( ;; ) { - if (ch == match) { + i = ngx_max(tables->index[c], ctx->index); + j = tables->index[c + 1]; - if (ctx->match.len == 1) { - ctx->pos = p + 1; - ctx->copy_end = p; + while (i != j) { - return NGX_OK; - } + if (slcf->once && ctx->sub && ctx->sub[i].data) { + goto next; + } - copy_end = p; - ctx->looked.data[0] = *p; - looked = 1; - state = sub_match_state; + m = &match[i].match; - goto match_started; - } + pat = m->data; + pat_end = m->data + m->len; - if (++p == last) { - break; - } + if (start >= 0) { + p = ctx->pos + start; - ch = *p; - ch = ngx_tolower(ch); - } + } else { + last = ctx->looked.data + ctx->looked.len; + p = last + start; - ctx->state = state; - ctx->pos = p; - ctx->looked.len = looked; - ctx->copy_end = p; + while (p < last && pat < pat_end) { + if (ngx_tolower(*p) != *pat) { + goto next; + } + + p++; + pat++; + } - if (ctx->copy_start == NULL) { - ctx->copy_start = ctx->buf->pos; + p = ctx->pos; } - return NGX_AGAIN; + while (p < ctx->buf->last && pat < pat_end) { + if (ngx_tolower(*p) != *pat) { + goto next; + } - match_started: + p++; + pat++; + } - continue; - } + ctx->index = i; - /* state == sub_match_state */ + if (pat != pat_end) { + /* partial match */ + goto again; + } - if (ch == ctx->match.data[looked]) { - ctx->looked.data[looked] = *p; - looked++; + ctx->offset = offset + (ngx_int_t) m->len; + next = start + (ngx_int_t) m->len; + end = ngx_max(next, 0); + rc = NGX_OK; - if (looked == ctx->match.len) { + goto done; - ctx->state = sub_start_state; - ctx->pos = p + 1; - ctx->looked.len = 0; - ctx->saved.len = 0; - ctx->copy_end = copy_end; + next: - if (ctx->copy_start == NULL && copy_end) { - ctx->copy_start = ctx->buf->pos; - } + i++; + } - return NGX_OK; - } + offset++; + ctx->index = 0; + } - } else { - /* - * check if there is another partial match in previously - * matched substring to catch cases like "aab" in "aaab" - */ - - ctx->looked.data[looked] = *p; - looked++; - - for (i = 1; i < looked; i++) { - if (ngx_strncasecmp(ctx->looked.data + i, - ctx->match.data, looked - i) - == 0) - { - break; - } - } +again: - if (i < looked) { - if (ctx->saved.len > i) { - ctx->saved.len = i; - } + ctx->offset = offset; + start = offset - (ngx_int_t) tables->min_match_len + 1; + next = start; + rc = NGX_AGAIN; - if ((size_t) (p + 1 - ctx->buf->pos) >= looked - i) { - copy_end = p + 1 - (looked - i); - } +done: - ngx_memmove(ctx->looked.data, ctx->looked.data + i, looked - i); - looked = looked - i; + /* send [ - looked.len, start ] to client */ - } else { - copy_end = p; - looked = 0; - state = sub_start_state; - } + ctx->saved.len = ctx->looked.len + ngx_min(start, 0); + ngx_memcpy(ctx->saved.data, ctx->looked.data, ctx->saved.len); - if (ctx->saved.len) { - p++; - goto out; - } - } - } + ctx->copy_start = ctx->pos; + ctx->copy_end = ctx->pos + ngx_max(start, 0); - ctx->saved.len = 0; + /* save [ next, end ] in looked */ -out: + len = ngx_min(next, 0); + p = ctx->looked.data; + p = ngx_movemem(p, p + ctx->looked.len + len, - len); - ctx->state = state; - ctx->pos = p; - ctx->looked.len = looked; + len = ngx_max(next, 0); + p = ngx_cpymem(p, ctx->pos + len, end - len); + ctx->looked.len = p - ctx->looked.data; - ctx->copy_end = (state == sub_start_state) ? p : copy_end; + /* update position */ - if (ctx->copy_start == NULL && ctx->copy_end) { - ctx->copy_start = ctx->buf->pos; - } + ctx->pos += end; + ctx->offset -= end; - return NGX_AGAIN; + return rc; } @@ -674,23 +737,60 @@ 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; } - value = cf->args->elts; + 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 @@ /* * 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 @@ 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,109 @@ return NGX_CONF_ERROR; } + if (conf->pairs == NULL) { + conf->dynamic = prev->dynamic; + conf->pairs = prev->pairs; + conf->matches = prev->matches; + conf->tables = prev->tables; + } + + if (conf->pairs && conf->dynamic == 0 && conf->tables == NULL) { + 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 -Nru nginx-1.9.3/src/http/modules/ngx_http_upstream_keepalive_module.c nginx-1.9.6/src/http/modules/ngx_http_upstream_keepalive_module.c --- nginx-1.9.3/src/http/modules/ngx_http_upstream_keepalive_module.c 2015-07-14 12:46:06.000000000 -0400 +++ nginx-1.9.6/src/http/modules/ngx_http_upstream_keepalive_module.c 2015-10-27 09:47:30.000000000 -0400 @@ -302,6 +302,10 @@ goto invalid; } + if (ngx_terminate || ngx_exiting) { + goto invalid; + } + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { goto invalid; } diff -Nru nginx-1.9.3/src/http/modules/ngx_http_upstream_zone_module.c nginx-1.9.6/src/http/modules/ngx_http_upstream_zone_module.c --- nginx-1.9.3/src/http/modules/ngx_http_upstream_zone_module.c 2015-07-14 12:46:06.000000000 -0400 +++ nginx-1.9.6/src/http/modules/ngx_http_upstream_zone_module.c 2015-10-27 09:47:30.000000000 -0400 @@ -159,7 +159,7 @@ /* 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 -Nru nginx-1.9.3/src/http/modules/perl/nginx.xs nginx-1.9.6/src/http/modules/perl/nginx.xs --- nginx-1.9.3/src/http/modules/perl/nginx.xs 2015-07-14 12:46:06.000000000 -0400 +++ nginx-1.9.6/src/http/modules/perl/nginx.xs 2015-10-27 09:47:30.000000000 -0400 @@ -98,6 +98,9 @@ MODULE = nginx PACKAGE = nginx +PROTOTYPES: DISABLE + + void status(r, code) CODE: @@ -268,19 +271,16 @@ } #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 -Nru nginx-1.9.3/src/http/ngx_http.c nginx-1.9.6/src/http/ngx_http.c --- nginx-1.9.3/src/http/ngx_http.c 2015-07-14 12:46:06.000000000 -0400 +++ nginx-1.9.6/src/http/ngx_http.c 2015-10-27 09:47:30.000000000 -0400 @@ -1233,8 +1233,8 @@ #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 @@ #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 @@ #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 @@ } } -#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 @@ #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 @@ #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 -Nru nginx-1.9.3/src/http/ngx_http_copy_filter_module.c nginx-1.9.6/src/http/ngx_http_copy_filter_module.c --- nginx-1.9.3/src/http/ngx_http_copy_filter_module.c 2015-07-14 12:46:06.000000000 -0400 +++ nginx-1.9.6/src/http/ngx_http_copy_filter_module.c 2015-10-27 09:47:30.000000000 -0400 @@ -327,7 +327,7 @@ 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 -Nru nginx-1.9.3/src/http/ngx_http_core_module.c nginx-1.9.6/src/http/ngx_http_core_module.c --- nginx-1.9.3/src/http/ngx_http_core_module.c 2015-07-14 12:46:06.000000000 -0400 +++ nginx-1.9.6/src/http/ngx_http_core_module.c 2015-10-27 09:47:30.000000000 -0400 @@ -1239,7 +1239,9 @@ *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 @@ } } 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 @@ 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); @@ -2128,13 +2132,6 @@ 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; @@ -2423,12 +2420,19 @@ 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; } @@ -2469,8 +2473,8 @@ 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; @@ -2533,6 +2537,7 @@ 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; @@ -3184,7 +3189,7 @@ pclcf = pctx->loc_conf[ngx_http_core_module.ctx_index]; - if (pclcf->name.len) { + if (cf->cmd_type == NGX_HTTP_LOC_CONF) { /* nested location */ @@ -4191,18 +4196,26 @@ #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) { @@ -4476,7 +4489,9 @@ 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 -Nru nginx-1.9.3/src/http/ngx_http_core_module.h nginx-1.9.6/src/http/ngx_http_core_module.h --- nginx-1.9.3/src/http/ngx_http_core_module.h 2015-07-14 12:46:06.000000000 -0400 +++ nginx-1.9.6/src/http/ngx_http_core_module.h 2015-10-27 09:47:30.000000000 -0400 @@ -79,8 +79,8 @@ #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 @@ #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 -Nru nginx-1.9.3/src/http/ngx_http_file_cache.c nginx-1.9.6/src/http/ngx_http_file_cache.c --- nginx-1.9.3/src/http/ngx_http_file_cache.c 2015-07-14 12:46:06.000000000 -0400 +++ nginx-1.9.6/src/http/ngx_http_file_cache.c 2015-10-27 09:47:30.000000000 -0400 @@ -521,9 +521,12 @@ 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 @@ 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 @@ 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 -Nru nginx-1.9.3/src/http/ngx_http.h nginx-1.9.6/src/http/ngx_http.h --- nginx-1.9.3/src/http/ngx_http.h 2015-07-14 12:46:06.000000000 -0400 +++ nginx-1.9.6/src/http/ngx_http.h 2015-10-27 09:47:30.000000000 -0400 @@ -20,8 +20,8 @@ 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 @@ #include #include -#if (NGX_HTTP_SPDY) -#include +#if (NGX_HTTP_V2) +#include #endif #if (NGX_HTTP_CACHE) #include diff -Nru nginx-1.9.3/src/http/ngx_http_request_body.c nginx-1.9.6/src/http/ngx_http_request_body.c --- nginx-1.9.3/src/http/ngx_http_request_body.c 2015-07-14 12:46:07.000000000 -0400 +++ nginx-1.9.6/src/http/ngx_http_request_body.c 2015-10-27 09:47:30.000000000 -0400 @@ -40,10 +40,10 @@ 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_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 -Nru nginx-1.9.3/src/http/ngx_http_request.c nginx-1.9.6/src/http/ngx_http_request.c --- nginx-1.9.3/src/http/ngx_http_request.c 2015-07-14 12:46:07.000000000 -0400 +++ nginx-1.9.6/src/http/ngx_http_request.c 2015-10-27 09:47:30.000000000 -0400 @@ -312,9 +312,9 @@ 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 @@ 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 @@ 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 @@ if (r == c->data) { r->main->count--; - r->main->subrequests++; if (!r->logged) { @@ -2500,8 +2498,8 @@ { 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_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 @@ 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_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 @@ 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 -Nru nginx-1.9.3/src/http/ngx_http_request.h nginx-1.9.6/src/http/ngx_http_request.h --- nginx-1.9.3/src/http/ngx_http_request.h 2015-07-14 12:46:07.000000000 -0400 +++ nginx-1.9.6/src/http/ngx_http_request.h 2015-10-27 09:47:30.000000000 -0400 @@ -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 @@ 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 -Nru nginx-1.9.3/src/http/ngx_http_spdy.c nginx-1.9.6/src/http/ngx_http_spdy.c --- nginx-1.9.3/src/http/ngx_http_spdy.c 2015-07-14 12:46:07.000000000 -0400 +++ nginx-1.9.6/src/http/ngx_http_spdy.c 1969-12-31 19:00:00.000000000 -0500 @@ -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 -Nru nginx-1.9.3/src/http/ngx_http_spdy_filter_module.c nginx-1.9.6/src/http/ngx_http_spdy_filter_module.c --- nginx-1.9.3/src/http/ngx_http_spdy_filter_module.c 2015-07-14 12:46:07.000000000 -0400 +++ nginx-1.9.6/src/http/ngx_http_spdy_filter_module.c 1969-12-31 19:00:00.000000000 -0500 @@ -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 -Nru nginx-1.9.3/src/http/ngx_http_spdy.h nginx-1.9.6/src/http/ngx_http_spdy.h --- nginx-1.9.3/src/http/ngx_http_spdy.h 2015-07-14 12:46:07.000000000 -0400 +++ nginx-1.9.6/src/http/ngx_http_spdy.h 1969-12-31 19:00:00.000000000 -0500 @@ -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 -Nru nginx-1.9.3/src/http/ngx_http_spdy_module.c nginx-1.9.6/src/http/ngx_http_spdy_module.c --- nginx-1.9.3/src/http/ngx_http_spdy_module.c 2015-07-14 12:46:07.000000000 -0400 +++ nginx-1.9.6/src/http/ngx_http_spdy_module.c 1969-12-31 19:00:00.000000000 -0500 @@ -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 -Nru nginx-1.9.3/src/http/ngx_http_spdy_module.h nginx-1.9.6/src/http/ngx_http_spdy_module.h --- nginx-1.9.3/src/http/ngx_http_spdy_module.h 2015-07-14 12:46:07.000000000 -0400 +++ nginx-1.9.6/src/http/ngx_http_spdy_module.h 1969-12-31 19:00:00.000000000 -0500 @@ -1,41 +0,0 @@ - -/* - * Copyright (C) Nginx, Inc. - * Copyright (C) Valentin V. Bartenev - */ - - -#ifndef _NGX_HTTP_SPDY_MODULE_H_INCLUDED_ -#define _NGX_HTTP_SPDY_MODULE_H_INCLUDED_ - - -#include -#include -#include - - -typedef struct { - size_t recv_buffer_size; - u_char *recv_buffer; -} ngx_http_spdy_main_conf_t; - - -typedef struct { - size_t pool_size; - ngx_uint_t concurrent_streams; - 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; - - -typedef struct { - size_t chunk_size; -} ngx_http_spdy_loc_conf_t; - - -extern ngx_module_t ngx_http_spdy_module; - - -#endif /* _NGX_HTTP_SPDY_MODULE_H_INCLUDED_ */ diff -Nru nginx-1.9.3/src/http/ngx_http_upstream.c nginx-1.9.6/src/http/ngx_http_upstream.c --- nginx-1.9.3/src/http/ngx_http_upstream.c 2015-07-14 12:46:07.000000000 -0400 +++ nginx-1.9.6/src/http/ngx_http_upstream.c 2015-10-27 09:47:30.000000000 -0400 @@ -475,8 +475,8 @@ 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 @@ 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 @@ 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 @@ return; } -#if (NGX_HTTP_SPDY) - if (r->spdy_stream) { +#if (NGX_HTTP_V2) + if (r->stream) { return; } #endif diff -Nru nginx-1.9.3/src/http/ngx_http_variables.c nginx-1.9.6/src/http/ngx_http_variables.c --- nginx-1.9.3/src/http/ngx_http_variables.c 2015-07-14 12:46:07.000000000 -0400 +++ nginx-1.9.6/src/http/ngx_http_variables.c 2015-10-27 09:47:30.000000000 -0400 @@ -575,7 +575,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ } } - 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 @@ 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 @@ 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 -Nru nginx-1.9.3/src/http/v2/ngx_http_v2.c nginx-1.9.6/src/http/v2/ngx_http_v2.c --- nginx-1.9.3/src/http/v2/ngx_http_v2.c 1969-12-31 19:00:00.000000000 -0500 +++ nginx-1.9.6/src/http/v2/ngx_http_v2.c 2015-10-27 09:47:30.000000000 -0400 @@ -0,0 +1,4061 @@ + +/* + * 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); + } + + 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); +} + + +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) { + 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 (stream->in_closed) { + 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; + + 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); + + 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(4); + } + + 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(); + } + + 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 - start > NGX_HTTP_V2_INT_OCTETS) { + end = start + NGX_HTTP_V2_INT_OCTETS; + } + + 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) >= h2c->state.length) { + return NGX_ERROR; + } + + if (end == start + NGX_HTTP_V2_INT_OCTETS) { + return NGX_DECLINED; + } + + 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; + } + + ngx_str_set(&r->http_protocol, "HTTP/2.0"); + + 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; + } + + 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) { + child->weight = 1; + } + } + + 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; + + 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) { + (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, *q; + ngx_http_v2_node_t *parent, *child, *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) { + 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); + } + + 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 -Nru nginx-1.9.3/src/http/v2/ngx_http_v2_filter_module.c nginx-1.9.6/src/http/v2/ngx_http_v2_filter_module.c --- nginx-1.9.3/src/http/v2/ngx_http_v2_filter_module.c 1969-12-31 19:00:00.000000000 -0500 +++ nginx-1.9.6/src/http/v2/ngx_http_v2_filter_module.c 2015-10-27 09:47:30.000000000 -0400 @@ -0,0 +1,1283 @@ + +/* + * Copyright (C) Nginx, Inc. + * Copyright (C) Valentin V. Bartenev + */ + + +#include +#include +#include +#include +#include + + +/* + * 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) + +#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 +#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 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); + +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, *pos, *start, *p; + size_t len; + ngx_str_t host, location; + 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_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 += 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) + { + 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; + } + + pos = ngx_palloc(r->pool, len); + if (pos == NULL) { + return NGX_ERROR; + } + + start = pos; + + if (status) { + *pos++ = status; + + } else { + *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) { + *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); + + } else { + *pos++ = NGX_HTTP_V2_ENCODE_RAW | (sizeof("nginx") - 1); + pos = ngx_cpymem(pos, "nginx", sizeof("nginx") - 1); + } + } + + 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; + + pos = ngx_cpymem(pos, ngx_cached_http_time.data, + ngx_cached_http_time.len); + } + + if (r->headers_out.content_type.len) { + *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) + { + *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 = pos; + + pos = ngx_cpymem(pos, r->headers_out.content_type.data, + r->headers_out.content_type.len); + + pos = ngx_cpymem(pos, "; charset=", sizeof("; charset=") - 1); + + 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 = 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); + } + } + + if (r->headers_out.content_length == NULL + && r->headers_out.content_length_n >= 0) + { + *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_CONTENT_LENGTH_INDEX); + + 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) + { + *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); + } + + if (r->headers_out.location && r->headers_out.location->value.len) { + *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_LOCATION_INDEX); + + *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) { + *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 + + 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; + } + + *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_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); + } + + frame = ngx_http_v2_create_headers_frame(r, start, pos); + if (frame == NULL) { + return NGX_ERROR; + } + + ngx_http_v2_queue_blocked_frame(r->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 = r->stream; + + r->stream->queued = 1; + + fc->send_chain = ngx_http_v2_send_chain; + fc->need_last_buf = 1; + + return ngx_http_v2_filter_send(fc, r->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 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 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; + + stream = r->stream; + rest = end - pos; + + frame = ngx_palloc(r->pool, sizeof(ngx_http_v2_out_frame_t)); + if (frame == NULL) { + return NULL; + } + + 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; + } +} + + +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 -Nru nginx-1.9.3/src/http/v2/ngx_http_v2.h nginx-1.9.6/src/http/v2/ngx_http_v2.h --- nginx-1.9.3/src/http/v2/ngx_http_v2.h 1969-12-31 19:00:00.000000000 -0500 +++ nginx-1.9.6/src/http/v2/ngx_http_v2.h 2015-10-27 09:47:30.000000000 -0400 @@ -0,0 +1,334 @@ +/* + * 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 \ + (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 */ +#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 -Nru nginx-1.9.3/src/http/v2/ngx_http_v2_huff_decode.c nginx-1.9.6/src/http/v2/ngx_http_v2_huff_decode.c --- nginx-1.9.3/src/http/v2/ngx_http_v2_huff_decode.c 1969-12-31 19:00:00.000000000 -0500 +++ nginx-1.9.6/src/http/v2/ngx_http_v2_huff_decode.c 2015-10-27 09:47:30.000000000 -0400 @@ -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 -Nru nginx-1.9.3/src/http/v2/ngx_http_v2_huff_encode.c nginx-1.9.6/src/http/v2/ngx_http_v2_huff_encode.c --- nginx-1.9.3/src/http/v2/ngx_http_v2_huff_encode.c 1969-12-31 19:00:00.000000000 -0500 +++ nginx-1.9.6/src/http/v2/ngx_http_v2_huff_encode.c 2015-10-27 09:47:30.000000000 -0400 @@ -0,0 +1,10 @@ + +/* + * Copyright (C) Nginx, Inc. + * Copyright (C) Valentin V. Bartenev + */ + + +#include +#include +#include diff -Nru nginx-1.9.3/src/http/v2/ngx_http_v2_module.c nginx-1.9.6/src/http/v2/ngx_http_v2_module.c --- nginx-1.9.3/src/http/v2/ngx_http_v2_module.c 1969-12-31 19:00:00.000000000 -0500 +++ nginx-1.9.6/src/http/v2/ngx_http_v2_module.c 2015-10-27 09:47:30.000000000 -0400 @@ -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 -Nru nginx-1.9.3/src/http/v2/ngx_http_v2_module.h nginx-1.9.6/src/http/v2/ngx_http_v2_module.h --- nginx-1.9.3/src/http/v2/ngx_http_v2_module.h 1969-12-31 19:00:00.000000000 -0500 +++ nginx-1.9.6/src/http/v2/ngx_http_v2_module.h 2015-10-27 09:47:30.000000000 -0400 @@ -0,0 +1,42 @@ + +/* + * Copyright (C) Nginx, Inc. + * Copyright (C) Valentin V. Bartenev + */ + + +#ifndef _NGX_HTTP_V2_MODULE_H_INCLUDED_ +#define _NGX_HTTP_V2_MODULE_H_INCLUDED_ + + +#include +#include +#include + + +typedef struct { + size_t recv_buffer_size; + u_char *recv_buffer; +} 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 idle_timeout; +} ngx_http_v2_srv_conf_t; + + +typedef struct { + size_t chunk_size; +} ngx_http_v2_loc_conf_t; + + +extern ngx_module_t ngx_http_v2_module; + + +#endif /* _NGX_HTTP_V2_MODULE_H_INCLUDED_ */ diff -Nru nginx-1.9.3/src/http/v2/ngx_http_v2_table.c nginx-1.9.6/src/http/v2/ngx_http_v2_table.c --- nginx-1.9.3/src/http/v2/ngx_http_v2_table.c 1969-12-31 19:00:00.000000000 -0500 +++ nginx-1.9.6/src/http/v2/ngx_http_v2_table.c 2015-10-27 09:47:30.000000000 -0400 @@ -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 -Nru nginx-1.9.3/src/mail/ngx_mail_core_module.c nginx-1.9.6/src/mail/ngx_mail_core_module.c --- nginx-1.9.3/src/mail/ngx_mail_core_module.c 2015-07-14 12:46:07.000000000 -0400 +++ nginx-1.9.6/src/mail/ngx_mail_core_module.c 2015-10-27 09:47:30.000000000 -0400 @@ -434,8 +434,7 @@ 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 -Nru nginx-1.9.3/src/os/unix/ngx_files.c nginx-1.9.6/src/os/unix/ngx_files.c --- nginx-1.9.3/src/os/unix/ngx_files.c 2015-07-14 12:46:07.000000000 -0400 +++ nginx-1.9.6/src/os/unix/ngx_files.c 2015-10-27 09:47:30.000000000 -0400 @@ -264,6 +264,7 @@ 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 @@ 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; } diff -Nru nginx-1.9.3/src/os/unix/ngx_process_cycle.c nginx-1.9.6/src/os/unix/ngx_process_cycle.c --- nginx-1.9.3/src/os/unix/ngx_process_cycle.c 2015-07-14 12:46:07.000000000 -0400 +++ nginx-1.9.6/src/os/unix/ngx_process_cycle.c 2015-10-27 09:47:30.000000000 -0400 @@ -728,9 +728,6 @@ { 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 @@ 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_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 -Nru nginx-1.9.3/src/stream/ngx_stream_core_module.c nginx-1.9.6/src/stream/ngx_stream_core_module.c --- nginx-1.9.3/src/stream/ngx_stream_core_module.c 2015-07-14 12:46:07.000000000 -0400 +++ nginx-1.9.6/src/stream/ngx_stream_core_module.c 2015-10-27 09:47:31.000000000 -0400 @@ -45,6 +45,13 @@ 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 @@ 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_conf_merge_value(conf->tcp_nodelay, prev->tcp_nodelay, 1); + return NGX_CONF_OK; } @@ -362,8 +372,7 @@ 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 -Nru nginx-1.9.3/src/stream/ngx_stream.h nginx-1.9.6/src/stream/ngx_stream.h --- nginx-1.9.3/src/stream/ngx_stream.h 2015-07-14 12:46:07.000000000 -0400 +++ nginx-1.9.6/src/stream/ngx_stream.h 2015-10-27 09:47:30.000000000 -0400 @@ -132,6 +132,7 @@ 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 -Nru nginx-1.9.3/src/stream/ngx_stream_handler.c nginx-1.9.6/src/stream/ngx_stream_handler.c --- nginx-1.9.3/src/stream/ngx_stream_handler.c 2015-07-14 12:46:07.000000000 -0400 +++ nginx-1.9.6/src/stream/ngx_stream_handler.c 2015-10-27 09:47:31.000000000 -0400 @@ -23,6 +23,7 @@ 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 @@ } } + 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 @@ 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 -Nru nginx-1.9.3/src/stream/ngx_stream_proxy_module.c nginx-1.9.6/src/stream/ngx_stream_proxy_module.c --- nginx-1.9.3/src/stream/ngx_stream_proxy_module.c 2015-07-14 12:46:07.000000000 -0400 +++ nginx-1.9.6/src/stream/ngx_stream_proxy_module.c 2015-10-27 09:47:31.000000000 -0400 @@ -17,9 +17,8 @@ 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 @@ #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,25 +135,32 @@ offsetof(ngx_stream_proxy_srv_conf_t, timeout), NULL }, - { ngx_string("proxy_downstream_buffer"), + { 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, downstream_buf_size), + offsetof(ngx_stream_proxy_srv_conf_t, buffer_size), NULL }, - { ngx_string("proxy_upload_rate"), + { 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, upload_rate), - 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, upstream_buf_size), + 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, + ngx_conf_set_size_slot, + NGX_STREAM_SRV_CONF_OFFSET, + offsetof(ngx_stream_proxy_srv_conf_t, upload_rate), NULL }, { ngx_string("proxy_download_rate"), @@ -358,14 +373,14 @@ 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 @@ #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 @@ 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 @@ 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 @@ 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 @@ 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; @@ -725,6 +759,10 @@ 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; @@ -1295,9 +1333,8 @@ 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 +1369,12 @@ 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 -Nru nginx-1.9.3/src/stream/ngx_stream_upstream_zone_module.c nginx-1.9.6/src/stream/ngx_stream_upstream_zone_module.c --- nginx-1.9.3/src/stream/ngx_stream_upstream_zone_module.c 2015-07-14 12:46:07.000000000 -0400 +++ nginx-1.9.6/src/stream/ngx_stream_upstream_zone_module.c 2015-10-27 09:47:31.000000000 -0400 @@ -155,7 +155,7 @@ /* 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];