The HTTP/2 implementation (RFC 7240, 7241).
The SPDY support is removed, as it's incompatible with the new module.
This commit is contained in:
parent
1119b74df7
commit
02f6fb29a2
26 changed files with 9250 additions and 5701 deletions
|
@ -7,7 +7,7 @@ echo "creating $NGX_MAKEFILE"
|
|||
|
||||
mkdir -p $NGX_OBJS/src/core $NGX_OBJS/src/event $NGX_OBJS/src/event/modules \
|
||||
$NGX_OBJS/src/os/unix $NGX_OBJS/src/os/win32 \
|
||||
$NGX_OBJS/src/http $NGX_OBJS/src/http/modules \
|
||||
$NGX_OBJS/src/http $NGX_OBJS/src/http/v2 $NGX_OBJS/src/http/modules \
|
||||
$NGX_OBJS/src/http/modules/perl \
|
||||
$NGX_OBJS/src/mail \
|
||||
$NGX_OBJS/src/stream \
|
||||
|
|
18
auto/modules
18
auto/modules
|
@ -94,7 +94,7 @@ fi
|
|||
# ngx_http_write_filter
|
||||
# ngx_http_header_filter
|
||||
# ngx_http_chunked_filter
|
||||
# ngx_http_spdy_filter
|
||||
# ngx_http_v2_filter
|
||||
# ngx_http_range_header_filter
|
||||
# ngx_http_gzip_filter
|
||||
# ngx_http_postpone_filter
|
||||
|
@ -115,8 +115,8 @@ HTTP_FILTER_MODULES="$HTTP_WRITE_FILTER_MODULE \
|
|||
$HTTP_HEADER_FILTER_MODULE \
|
||||
$HTTP_CHUNKED_FILTER_MODULE"
|
||||
|
||||
if [ $HTTP_SPDY = YES ]; then
|
||||
HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_SPDY_FILTER_MODULE"
|
||||
if [ $HTTP_V2 = YES ]; then
|
||||
HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_V2_FILTER_MODULE"
|
||||
fi
|
||||
|
||||
HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_RANGE_HEADER_FILTER_MODULE"
|
||||
|
@ -180,12 +180,12 @@ if [ $HTTP_USERID = YES ]; then
|
|||
fi
|
||||
|
||||
|
||||
if [ $HTTP_SPDY = YES ]; then
|
||||
have=NGX_HTTP_SPDY . auto/have
|
||||
USE_ZLIB=YES
|
||||
HTTP_MODULES="$HTTP_MODULES $HTTP_SPDY_MODULE"
|
||||
HTTP_DEPS="$HTTP_DEPS $HTTP_SPDY_DEPS"
|
||||
HTTP_SRCS="$HTTP_SRCS $HTTP_SPDY_SRCS"
|
||||
if [ $HTTP_V2 = YES ]; then
|
||||
have=NGX_HTTP_V2 . auto/have
|
||||
HTTP_MODULES="$HTTP_MODULES $HTTP_V2_MODULE"
|
||||
HTTP_INCS="$HTTP_INCS $HTTP_V2_INCS"
|
||||
HTTP_DEPS="$HTTP_DEPS $HTTP_V2_DEPS"
|
||||
HTTP_SRCS="$HTTP_SRCS $HTTP_V2_SRCS"
|
||||
fi
|
||||
|
||||
HTTP_MODULES="$HTTP_MODULES $HTTP_STATIC_MODULE"
|
||||
|
|
|
@ -58,7 +58,7 @@ HTTP_CACHE=YES
|
|||
HTTP_CHARSET=YES
|
||||
HTTP_GZIP=YES
|
||||
HTTP_SSL=NO
|
||||
HTTP_SPDY=NO
|
||||
HTTP_V2=NO
|
||||
HTTP_SSI=YES
|
||||
HTTP_POSTPONE=NO
|
||||
HTTP_REALIP=NO
|
||||
|
@ -210,7 +210,7 @@ do
|
|||
--http-scgi-temp-path=*) NGX_HTTP_SCGI_TEMP_PATH="$value" ;;
|
||||
|
||||
--with-http_ssl_module) HTTP_SSL=YES ;;
|
||||
--with-http_spdy_module) HTTP_SPDY=YES ;;
|
||||
--with-http_v2_module) HTTP_V2=YES ;;
|
||||
--with-http_realip_module) HTTP_REALIP=YES ;;
|
||||
--with-http_addition_module) HTTP_ADDITION=YES ;;
|
||||
--with-http_xslt_module) HTTP_XSLT=YES ;;
|
||||
|
@ -378,7 +378,7 @@ cat << END
|
|||
--with-ipv6 enable IPv6 support
|
||||
|
||||
--with-http_ssl_module enable ngx_http_ssl_module
|
||||
--with-http_spdy_module enable ngx_http_spdy_module
|
||||
--with-http_v2_module enable ngx_http_v2_module
|
||||
--with-http_realip_module enable ngx_http_realip_module
|
||||
--with-http_addition_module enable ngx_http_addition_module
|
||||
--with-http_xslt_module enable ngx_http_xslt_module
|
||||
|
|
18
auto/sources
18
auto/sources
|
@ -317,13 +317,17 @@ HTTP_POSTPONE_FILTER_SRCS=src/http/ngx_http_postpone_filter_module.c
|
|||
HTTP_FILE_CACHE_SRCS=src/http/ngx_http_file_cache.c
|
||||
|
||||
|
||||
HTTP_SPDY_MODULE=ngx_http_spdy_module
|
||||
HTTP_SPDY_FILTER_MODULE=ngx_http_spdy_filter_module
|
||||
HTTP_SPDY_DEPS="src/http/ngx_http_spdy.h \
|
||||
src/http/ngx_http_spdy_module.h"
|
||||
HTTP_SPDY_SRCS="src/http/ngx_http_spdy.c \
|
||||
src/http/ngx_http_spdy_module.c \
|
||||
src/http/ngx_http_spdy_filter_module.c"
|
||||
HTTP_V2_MODULE=ngx_http_v2_module
|
||||
HTTP_V2_FILTER_MODULE=ngx_http_v2_filter_module
|
||||
HTTP_V2_INCS="src/http/v2"
|
||||
HTTP_V2_DEPS="src/http/v2/ngx_http_v2.h \
|
||||
src/http/v2/ngx_http_v2_module.h"
|
||||
HTTP_V2_SRCS="src/http/v2/ngx_http_v2.c \
|
||||
src/http/v2/ngx_http_v2_table.c \
|
||||
src/http/v2/ngx_http_v2_huff_decode.c \
|
||||
src/http/v2/ngx_http_v2_huff_encode.c \
|
||||
src/http/v2/ngx_http_v2_module.c \
|
||||
src/http/v2/ngx_http_v2_filter_module.c"
|
||||
|
||||
|
||||
HTTP_CHARSET_FILTER_MODULE=ngx_http_charset_filter_module
|
||||
|
|
|
@ -118,7 +118,7 @@ typedef enum {
|
|||
|
||||
#define NGX_LOWLEVEL_BUFFERED 0x0f
|
||||
#define NGX_SSL_BUFFERED 0x01
|
||||
#define NGX_SPDY_BUFFERED 0x02
|
||||
#define NGX_HTTP_V2_BUFFERED 0x02
|
||||
|
||||
|
||||
struct ngx_connection_s {
|
||||
|
|
|
@ -326,10 +326,10 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out,
|
|||
#if (NGX_DEBUG)
|
||||
unsigned int i;
|
||||
#endif
|
||||
#if (NGX_HTTP_SPDY)
|
||||
#if (NGX_HTTP_V2)
|
||||
ngx_http_connection_t *hc;
|
||||
#endif
|
||||
#if (NGX_HTTP_SPDY || NGX_DEBUG)
|
||||
#if (NGX_HTTP_V2 || NGX_DEBUG)
|
||||
ngx_connection_t *c;
|
||||
|
||||
c = ngx_ssl_get_connection(ssl_conn);
|
||||
|
@ -342,12 +342,13 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out,
|
|||
}
|
||||
#endif
|
||||
|
||||
#if (NGX_HTTP_SPDY)
|
||||
#if (NGX_HTTP_V2)
|
||||
hc = c->data;
|
||||
|
||||
if (hc->addr_conf->spdy) {
|
||||
srv = (unsigned char *) NGX_SPDY_NPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE;
|
||||
srvlen = sizeof(NGX_SPDY_NPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE) - 1;
|
||||
if (hc->addr_conf->http2) {
|
||||
srv =
|
||||
(unsigned char *) NGX_HTTP_V2_ALPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE;
|
||||
srvlen = sizeof(NGX_HTTP_V2_ALPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE) - 1;
|
||||
|
||||
} else
|
||||
#endif
|
||||
|
@ -378,22 +379,23 @@ static int
|
|||
ngx_http_ssl_npn_advertised(ngx_ssl_conn_t *ssl_conn,
|
||||
const unsigned char **out, unsigned int *outlen, void *arg)
|
||||
{
|
||||
#if (NGX_HTTP_SPDY || NGX_DEBUG)
|
||||
#if (NGX_HTTP_V2 || NGX_DEBUG)
|
||||
ngx_connection_t *c;
|
||||
|
||||
c = ngx_ssl_get_connection(ssl_conn);
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "SSL NPN advertised");
|
||||
#endif
|
||||
|
||||
#if (NGX_HTTP_SPDY)
|
||||
#if (NGX_HTTP_V2)
|
||||
{
|
||||
ngx_http_connection_t *hc;
|
||||
|
||||
hc = c->data;
|
||||
|
||||
if (hc->addr_conf->spdy) {
|
||||
*out = (unsigned char *) NGX_SPDY_NPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE;
|
||||
*outlen = sizeof(NGX_SPDY_NPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE) - 1;
|
||||
if (hc->addr_conf->http2) {
|
||||
*out =
|
||||
(unsigned char *) NGX_HTTP_V2_NPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE;
|
||||
*outlen = sizeof(NGX_HTTP_V2_NPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE) - 1;
|
||||
|
||||
return SSL_TLSEXT_ERR_OK;
|
||||
}
|
||||
|
|
|
@ -1233,8 +1233,8 @@ ngx_http_add_addresses(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
|
|||
#if (NGX_HTTP_SSL)
|
||||
ngx_uint_t ssl;
|
||||
#endif
|
||||
#if (NGX_HTTP_SPDY)
|
||||
ngx_uint_t spdy;
|
||||
#if (NGX_HTTP_V2)
|
||||
ngx_uint_t http2;
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -1290,8 +1290,8 @@ ngx_http_add_addresses(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
|
|||
#if (NGX_HTTP_SSL)
|
||||
ssl = lsopt->ssl || addr[i].opt.ssl;
|
||||
#endif
|
||||
#if (NGX_HTTP_SPDY)
|
||||
spdy = lsopt->spdy || addr[i].opt.spdy;
|
||||
#if (NGX_HTTP_V2)
|
||||
http2 = lsopt->http2 || addr[i].opt.http2;
|
||||
#endif
|
||||
|
||||
if (lsopt->set) {
|
||||
|
@ -1324,8 +1324,8 @@ ngx_http_add_addresses(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
|
|||
#if (NGX_HTTP_SSL)
|
||||
addr[i].opt.ssl = ssl;
|
||||
#endif
|
||||
#if (NGX_HTTP_SPDY)
|
||||
addr[i].opt.spdy = spdy;
|
||||
#if (NGX_HTTP_V2)
|
||||
addr[i].opt.http2 = http2;
|
||||
#endif
|
||||
|
||||
return NGX_OK;
|
||||
|
@ -1357,14 +1357,17 @@ ngx_http_add_address(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
|
|||
}
|
||||
}
|
||||
|
||||
#if (NGX_HTTP_SPDY && NGX_HTTP_SSL \
|
||||
#if (NGX_HTTP_V2 && NGX_HTTP_SSL \
|
||||
&& !defined TLSEXT_TYPE_application_layer_protocol_negotiation \
|
||||
&& !defined TLSEXT_TYPE_next_proto_neg)
|
||||
if (lsopt->spdy && lsopt->ssl) {
|
||||
|
||||
if (lsopt->http2 && lsopt->ssl) {
|
||||
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
|
||||
"nginx was built without OpenSSL ALPN or NPN "
|
||||
"support, SPDY is not enabled for %s", lsopt->addr);
|
||||
"nginx was built with OpenSSL that lacks ALPN "
|
||||
"and NPN support, HTTP/2 is not enabled for %s",
|
||||
lsopt->addr);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
addr = ngx_array_push(&port->addrs);
|
||||
|
@ -1856,8 +1859,8 @@ ngx_http_add_addrs(ngx_conf_t *cf, ngx_http_port_t *hport,
|
|||
#if (NGX_HTTP_SSL)
|
||||
addrs[i].conf.ssl = addr[i].opt.ssl;
|
||||
#endif
|
||||
#if (NGX_HTTP_SPDY)
|
||||
addrs[i].conf.spdy = addr[i].opt.spdy;
|
||||
#if (NGX_HTTP_V2)
|
||||
addrs[i].conf.http2 = addr[i].opt.http2;
|
||||
#endif
|
||||
addrs[i].conf.proxy_protocol = addr[i].opt.proxy_protocol;
|
||||
|
||||
|
@ -1921,8 +1924,8 @@ ngx_http_add_addrs6(ngx_conf_t *cf, ngx_http_port_t *hport,
|
|||
#if (NGX_HTTP_SSL)
|
||||
addrs6[i].conf.ssl = addr[i].opt.ssl;
|
||||
#endif
|
||||
#if (NGX_HTTP_SPDY)
|
||||
addrs6[i].conf.spdy = addr[i].opt.spdy;
|
||||
#if (NGX_HTTP_V2)
|
||||
addrs6[i].conf.http2 = addr[i].opt.http2;
|
||||
#endif
|
||||
|
||||
if (addr[i].hash.buckets == NULL
|
||||
|
|
|
@ -20,8 +20,8 @@ typedef struct ngx_http_file_cache_s ngx_http_file_cache_t;
|
|||
typedef struct ngx_http_log_ctx_s ngx_http_log_ctx_t;
|
||||
typedef struct ngx_http_chunked_s ngx_http_chunked_t;
|
||||
|
||||
#if (NGX_HTTP_SPDY)
|
||||
typedef struct ngx_http_spdy_stream_s ngx_http_spdy_stream_t;
|
||||
#if (NGX_HTTP_V2)
|
||||
typedef struct ngx_http_v2_stream_s ngx_http_v2_stream_t;
|
||||
#endif
|
||||
|
||||
typedef ngx_int_t (*ngx_http_header_handler_pt)(ngx_http_request_t *r,
|
||||
|
@ -38,8 +38,8 @@ typedef u_char *(*ngx_http_log_handler_pt)(ngx_http_request_t *r,
|
|||
#include <ngx_http_upstream_round_robin.h>
|
||||
#include <ngx_http_core_module.h>
|
||||
|
||||
#if (NGX_HTTP_SPDY)
|
||||
#include <ngx_http_spdy.h>
|
||||
#if (NGX_HTTP_V2)
|
||||
#include <ngx_http_v2.h>
|
||||
#endif
|
||||
#if (NGX_HTTP_CACHE)
|
||||
#include <ngx_http_cache.h>
|
||||
|
|
|
@ -2132,13 +2132,6 @@ ngx_http_gzip_ok(ngx_http_request_t *r)
|
|||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
#if (NGX_HTTP_SPDY)
|
||||
if (r->spdy_stream) {
|
||||
r->gzip_ok = 1;
|
||||
return NGX_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
ae = r->headers_in.accept_encoding;
|
||||
if (ae == NULL) {
|
||||
return NGX_DECLINED;
|
||||
|
@ -2480,8 +2473,8 @@ ngx_http_subrequest(ngx_http_request_t *r,
|
|||
|
||||
sr->request_body = r->request_body;
|
||||
|
||||
#if (NGX_HTTP_SPDY)
|
||||
sr->spdy_stream = r->spdy_stream;
|
||||
#if (NGX_HTTP_V2)
|
||||
sr->stream = r->stream;
|
||||
#endif
|
||||
|
||||
sr->method = NGX_HTTP_GET;
|
||||
|
@ -4203,18 +4196,26 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||
#endif
|
||||
}
|
||||
|
||||
if (ngx_strcmp(value[n].data, "spdy") == 0) {
|
||||
#if (NGX_HTTP_SPDY)
|
||||
lsopt.spdy = 1;
|
||||
if (ngx_strcmp(value[n].data, "http2") == 0) {
|
||||
#if (NGX_HTTP_V2)
|
||||
lsopt.http2 = 1;
|
||||
continue;
|
||||
#else
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"the \"spdy\" parameter requires "
|
||||
"ngx_http_spdy_module");
|
||||
"the \"http2\" parameter requires "
|
||||
"ngx_http_v2_module");
|
||||
return NGX_CONF_ERROR;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (ngx_strcmp(value[n].data, "spdy") == 0) {
|
||||
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
|
||||
"invalid parameter \"spdy\": "
|
||||
"ngx_http_spdy_module was superseded "
|
||||
"by ngx_http_v2_module");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ngx_strncmp(value[n].data, "so_keepalive=", 13) == 0) {
|
||||
|
||||
if (ngx_strcmp(&value[n].data[13], "on") == 0) {
|
||||
|
|
|
@ -79,8 +79,8 @@ typedef struct {
|
|||
#if (NGX_HTTP_SSL)
|
||||
unsigned ssl:1;
|
||||
#endif
|
||||
#if (NGX_HTTP_SPDY)
|
||||
unsigned spdy:1;
|
||||
#if (NGX_HTTP_V2)
|
||||
unsigned http2:1;
|
||||
#endif
|
||||
#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
|
||||
unsigned ipv6only:1;
|
||||
|
@ -248,8 +248,8 @@ struct ngx_http_addr_conf_s {
|
|||
#if (NGX_HTTP_SSL)
|
||||
unsigned ssl:1;
|
||||
#endif
|
||||
#if (NGX_HTTP_SPDY)
|
||||
unsigned spdy:1;
|
||||
#if (NGX_HTTP_V2)
|
||||
unsigned http2:1;
|
||||
#endif
|
||||
unsigned proxy_protocol:1;
|
||||
};
|
||||
|
|
|
@ -312,9 +312,9 @@ ngx_http_init_connection(ngx_connection_t *c)
|
|||
rev->handler = ngx_http_wait_request_handler;
|
||||
c->write->handler = ngx_http_empty_handler;
|
||||
|
||||
#if (NGX_HTTP_SPDY)
|
||||
if (hc->addr_conf->spdy) {
|
||||
rev->handler = ngx_http_spdy_init;
|
||||
#if (NGX_HTTP_V2)
|
||||
if (hc->addr_conf->http2) {
|
||||
rev->handler = ngx_http_v2_init;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -764,13 +764,12 @@ ngx_http_ssl_handshake_handler(ngx_connection_t *c)
|
|||
|
||||
c->ssl->no_wait_shutdown = 1;
|
||||
|
||||
#if (NGX_HTTP_SPDY \
|
||||
#if (NGX_HTTP_V2 \
|
||||
&& (defined TLSEXT_TYPE_application_layer_protocol_negotiation \
|
||||
|| defined TLSEXT_TYPE_next_proto_neg))
|
||||
{
|
||||
unsigned int len;
|
||||
const unsigned char *data;
|
||||
static const ngx_str_t spdy = ngx_string(NGX_SPDY_NPN_NEGOTIATED);
|
||||
unsigned int len;
|
||||
const unsigned char *data;
|
||||
|
||||
#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
|
||||
SSL_get0_alpn_selected(c->ssl->connection, &data, &len);
|
||||
|
@ -785,8 +784,8 @@ ngx_http_ssl_handshake_handler(ngx_connection_t *c)
|
|||
SSL_get0_next_proto_negotiated(c->ssl->connection, &data, &len);
|
||||
#endif
|
||||
|
||||
if (len == spdy.len && ngx_strncmp(data, spdy.data, spdy.len) == 0) {
|
||||
ngx_http_spdy_init(c->read);
|
||||
if (len == 2 && data[0] == 'h' && data[1] == '2') {
|
||||
ngx_http_v2_init(c->read);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -2499,8 +2498,8 @@ ngx_http_finalize_connection(ngx_http_request_t *r)
|
|||
{
|
||||
ngx_http_core_loc_conf_t *clcf;
|
||||
|
||||
#if (NGX_HTTP_SPDY)
|
||||
if (r->spdy_stream) {
|
||||
#if (NGX_HTTP_V2)
|
||||
if (r->stream) {
|
||||
ngx_http_close_request(r, 0);
|
||||
return;
|
||||
}
|
||||
|
@ -2565,8 +2564,8 @@ ngx_http_set_write_handler(ngx_http_request_t *r)
|
|||
ngx_http_test_reading;
|
||||
r->write_event_handler = ngx_http_writer;
|
||||
|
||||
#if (NGX_HTTP_SPDY)
|
||||
if (r->spdy_stream) {
|
||||
#if (NGX_HTTP_V2)
|
||||
if (r->stream) {
|
||||
return NGX_OK;
|
||||
}
|
||||
#endif
|
||||
|
@ -2656,8 +2655,8 @@ ngx_http_writer(ngx_http_request_t *r)
|
|||
|
||||
if (r->buffered || r->postponed || (r == r->main && c->buffered)) {
|
||||
|
||||
#if (NGX_HTTP_SPDY)
|
||||
if (r->spdy_stream) {
|
||||
#if (NGX_HTTP_V2)
|
||||
if (r->stream) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
@ -2724,9 +2723,9 @@ ngx_http_test_reading(ngx_http_request_t *r)
|
|||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http test reading");
|
||||
|
||||
#if (NGX_HTTP_SPDY)
|
||||
#if (NGX_HTTP_V2)
|
||||
|
||||
if (r->spdy_stream) {
|
||||
if (r->stream) {
|
||||
if (c->error) {
|
||||
err = 0;
|
||||
goto closed;
|
||||
|
@ -3399,9 +3398,9 @@ ngx_http_close_request(ngx_http_request_t *r, ngx_int_t rc)
|
|||
return;
|
||||
}
|
||||
|
||||
#if (NGX_HTTP_SPDY)
|
||||
if (r->spdy_stream) {
|
||||
ngx_http_spdy_close_stream(r->spdy_stream, rc);
|
||||
#if (NGX_HTTP_V2)
|
||||
if (r->stream) {
|
||||
ngx_http_v2_close_stream(r->stream, rc);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -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,8 +432,8 @@ struct ngx_http_request_s {
|
|||
ngx_uint_t err_status;
|
||||
|
||||
ngx_http_connection_t *http_connection;
|
||||
#if (NGX_HTTP_SPDY)
|
||||
ngx_http_spdy_stream_t *spdy_stream;
|
||||
#if (NGX_HTTP_V2)
|
||||
ngx_http_v2_stream_t *stream;
|
||||
#endif
|
||||
|
||||
ngx_http_log_handler_pt log_handler;
|
||||
|
|
|
@ -40,10 +40,10 @@ ngx_http_read_client_request_body(ngx_http_request_t *r,
|
|||
|
||||
r->main->count++;
|
||||
|
||||
#if (NGX_HTTP_SPDY)
|
||||
if (r->spdy_stream && r == r->main) {
|
||||
#if (NGX_HTTP_V2)
|
||||
if (r->stream && r == r->main) {
|
||||
r->request_body_no_buffering = 0;
|
||||
rc = ngx_http_spdy_read_request_body(r, post_handler);
|
||||
rc = ngx_http_v2_read_request_body(r, post_handler);
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
|
@ -570,9 +570,9 @@ ngx_http_discard_request_body(ngx_http_request_t *r)
|
|||
ngx_int_t rc;
|
||||
ngx_event_t *rev;
|
||||
|
||||
#if (NGX_HTTP_SPDY)
|
||||
if (r->spdy_stream && r == r->main) {
|
||||
r->spdy_stream->skip_data = NGX_SPDY_DATA_DISCARD;
|
||||
#if (NGX_HTTP_V2)
|
||||
if (r->stream && r == r->main) {
|
||||
r->stream->skip_data = NGX_HTTP_V2_DATA_DISCARD;
|
||||
return NGX_OK;
|
||||
}
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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 <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_http.h>
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
|
||||
#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_ */
|
File diff suppressed because it is too large
Load diff
|
@ -1,408 +0,0 @@
|
|||
|
||||
/*
|
||||
* Copyright (C) Nginx, Inc.
|
||||
* Copyright (C) Valentin V. Bartenev
|
||||
*/
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_http.h>
|
||||
#include <ngx_http_spdy_module.h>
|
||||
|
||||
|
||||
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;
|
||||
}
|
|
@ -475,8 +475,8 @@ ngx_http_upstream_init(ngx_http_request_t *r)
|
|||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
||||
"http init upstream, client timer: %d", c->read->timer_set);
|
||||
|
||||
#if (NGX_HTTP_SPDY)
|
||||
if (r->spdy_stream) {
|
||||
#if (NGX_HTTP_V2)
|
||||
if (r->stream) {
|
||||
ngx_http_upstream_init_request(r);
|
||||
return;
|
||||
}
|
||||
|
@ -1151,8 +1151,8 @@ ngx_http_upstream_check_broken_connection(ngx_http_request_t *r,
|
|||
return;
|
||||
}
|
||||
|
||||
#if (NGX_HTTP_SPDY)
|
||||
if (r->spdy_stream) {
|
||||
#if (NGX_HTTP_V2)
|
||||
if (r->stream) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
|
3964
src/http/v2/ngx_http_v2.c
Normal file
3964
src/http/v2/ngx_http_v2.c
Normal file
File diff suppressed because it is too large
Load diff
334
src/http/v2/ngx_http_v2.h
Normal file
334
src/http/v2/ngx_http_v2.h
Normal file
|
@ -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 <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_http.h>
|
||||
|
||||
|
||||
#define NGX_HTTP_V2_ALPN_ADVERTISE "\x02h2"
|
||||
#define NGX_HTTP_V2_NPN_ADVERTISE NGX_HTTP_V2_ALPN_ADVERTISE
|
||||
|
||||
#define NGX_HTTP_V2_STATE_BUFFER_SIZE 16
|
||||
|
||||
#define NGX_HTTP_V2_MAX_FRAME_SIZE ((1 << 24) - 1)
|
||||
|
||||
#define NGX_HTTP_V2_INT_OCTETS 4
|
||||
#define NGX_HTTP_V2_MAX_FIELD ((1 << NGX_HTTP_V2_INT_OCTETS * 7) - 1)
|
||||
|
||||
#define NGX_HTTP_V2_DATA_DISCARD 1
|
||||
#define NGX_HTTP_V2_DATA_ERROR 2
|
||||
#define NGX_HTTP_V2_DATA_INTERNAL_ERROR 3
|
||||
|
||||
#define NGX_HTTP_V2_FRAME_HEADER_SIZE 9
|
||||
|
||||
/* frame types */
|
||||
#define NGX_HTTP_V2_DATA_FRAME 0x0
|
||||
#define NGX_HTTP_V2_HEADERS_FRAME 0x1
|
||||
#define NGX_HTTP_V2_PRIORITY_FRAME 0x2
|
||||
#define NGX_HTTP_V2_RST_STREAM_FRAME 0x3
|
||||
#define NGX_HTTP_V2_SETTINGS_FRAME 0x4
|
||||
#define NGX_HTTP_V2_PUSH_PROMISE_FRAME 0x5
|
||||
#define NGX_HTTP_V2_PING_FRAME 0x6
|
||||
#define NGX_HTTP_V2_GOAWAY_FRAME 0x7
|
||||
#define NGX_HTTP_V2_WINDOW_UPDATE_FRAME 0x8
|
||||
#define NGX_HTTP_V2_CONTINUATION_FRAME 0x9
|
||||
|
||||
/* frame flags */
|
||||
#define NGX_HTTP_V2_NO_FLAG 0x00
|
||||
#define NGX_HTTP_V2_ACK_FLAG 0x01
|
||||
#define NGX_HTTP_V2_END_STREAM_FLAG 0x01
|
||||
#define NGX_HTTP_V2_END_HEADERS_FLAG 0x04
|
||||
#define NGX_HTTP_V2_PADDED_FLAG 0x08
|
||||
#define NGX_HTTP_V2_PRIORITY_FLAG 0x20
|
||||
|
||||
|
||||
typedef struct ngx_http_v2_connection_s ngx_http_v2_connection_t;
|
||||
typedef struct ngx_http_v2_node_s ngx_http_v2_node_t;
|
||||
typedef struct ngx_http_v2_out_frame_s ngx_http_v2_out_frame_t;
|
||||
|
||||
|
||||
typedef u_char *(*ngx_http_v2_handler_pt) (ngx_http_v2_connection_t *h2c,
|
||||
u_char *pos, u_char *end);
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_str_t name;
|
||||
ngx_str_t value;
|
||||
} ngx_http_v2_header_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_uint_t sid;
|
||||
size_t length;
|
||||
size_t padding;
|
||||
unsigned flags:8;
|
||||
|
||||
unsigned incomplete:1;
|
||||
|
||||
/* HPACK */
|
||||
unsigned parse_name:1;
|
||||
unsigned parse_value:1;
|
||||
unsigned index:1;
|
||||
ngx_http_v2_header_t header;
|
||||
size_t header_limit;
|
||||
size_t field_limit;
|
||||
u_char field_state;
|
||||
u_char *field_start;
|
||||
u_char *field_end;
|
||||
size_t field_rest;
|
||||
ngx_pool_t *pool;
|
||||
|
||||
ngx_http_v2_stream_t *stream;
|
||||
|
||||
u_char buffer[NGX_HTTP_V2_STATE_BUFFER_SIZE];
|
||||
size_t buffer_used;
|
||||
ngx_http_v2_handler_pt handler;
|
||||
} ngx_http_v2_state_t;
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_http_v2_header_t **entries;
|
||||
|
||||
ngx_uint_t added;
|
||||
ngx_uint_t deleted;
|
||||
ngx_uint_t reused;
|
||||
ngx_uint_t allocated;
|
||||
|
||||
size_t size;
|
||||
size_t free;
|
||||
u_char *storage;
|
||||
u_char *pos;
|
||||
} ngx_http_v2_hpack_t;
|
||||
|
||||
|
||||
struct ngx_http_v2_connection_s {
|
||||
ngx_connection_t *connection;
|
||||
ngx_http_connection_t *http_connection;
|
||||
|
||||
ngx_uint_t processing;
|
||||
|
||||
size_t send_window;
|
||||
size_t recv_window;
|
||||
size_t init_window;
|
||||
|
||||
size_t frame_size;
|
||||
|
||||
ngx_queue_t waiting;
|
||||
|
||||
ngx_http_v2_state_t state;
|
||||
|
||||
ngx_http_v2_hpack_t hpack;
|
||||
|
||||
ngx_pool_t *pool;
|
||||
|
||||
ngx_http_v2_out_frame_t *free_frames;
|
||||
ngx_connection_t *free_fake_connections;
|
||||
|
||||
ngx_http_v2_node_t **streams_index;
|
||||
|
||||
ngx_http_v2_out_frame_t *last_out;
|
||||
|
||||
ngx_queue_t posted;
|
||||
ngx_queue_t dependencies;
|
||||
ngx_queue_t closed;
|
||||
|
||||
ngx_uint_t last_sid;
|
||||
|
||||
unsigned closed_nodes:8;
|
||||
unsigned blocked:1;
|
||||
};
|
||||
|
||||
|
||||
struct ngx_http_v2_node_s {
|
||||
ngx_uint_t id;
|
||||
ngx_http_v2_node_t *index;
|
||||
ngx_http_v2_node_t *parent;
|
||||
ngx_queue_t queue;
|
||||
ngx_queue_t children;
|
||||
ngx_queue_t reuse;
|
||||
ngx_uint_t rank;
|
||||
ngx_uint_t weight;
|
||||
double rel_weight;
|
||||
ngx_http_v2_stream_t *stream;
|
||||
};
|
||||
|
||||
|
||||
struct ngx_http_v2_stream_s {
|
||||
ngx_http_request_t *request;
|
||||
ngx_http_v2_connection_t *connection;
|
||||
ngx_http_v2_node_t *node;
|
||||
|
||||
ngx_uint_t header_buffers;
|
||||
ngx_uint_t queued;
|
||||
|
||||
/*
|
||||
* A change to SETTINGS_INITIAL_WINDOW_SIZE could cause the
|
||||
* send_window to become negative, hence it's signed.
|
||||
*/
|
||||
ssize_t send_window;
|
||||
size_t recv_window;
|
||||
|
||||
ngx_http_v2_out_frame_t *free_frames;
|
||||
ngx_chain_t *free_data_headers;
|
||||
ngx_chain_t *free_bufs;
|
||||
|
||||
ngx_queue_t queue;
|
||||
|
||||
ngx_array_t *cookies;
|
||||
|
||||
size_t header_limit;
|
||||
|
||||
unsigned handled:1;
|
||||
unsigned blocked:1;
|
||||
unsigned exhausted:1;
|
||||
unsigned end_headers: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_ */
|
1290
src/http/v2/ngx_http_v2_filter_module.c
Normal file
1290
src/http/v2/ngx_http_v2_filter_module.c
Normal file
File diff suppressed because it is too large
Load diff
2714
src/http/v2/ngx_http_v2_huff_decode.c
Normal file
2714
src/http/v2/ngx_http_v2_huff_decode.c
Normal file
File diff suppressed because it is too large
Load diff
10
src/http/v2/ngx_http_v2_huff_encode.c
Normal file
10
src/http/v2/ngx_http_v2_huff_encode.c
Normal file
|
@ -0,0 +1,10 @@
|
|||
|
||||
/*
|
||||
* Copyright (C) Nginx, Inc.
|
||||
* Copyright (C) Valentin V. Bartenev
|
||||
*/
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_http.h>
|
469
src/http/v2/ngx_http_v2_module.c
Normal file
469
src/http/v2/ngx_http_v2_module.c
Normal file
|
@ -0,0 +1,469 @@
|
|||
|
||||
/*
|
||||
* Copyright (C) Nginx, Inc.
|
||||
* Copyright (C) Valentin V. Bartenev
|
||||
*/
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_http.h>
|
||||
#include <ngx_http_v2_module.h>
|
||||
|
||||
|
||||
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;
|
||||
}
|
|
@ -5,8 +5,8 @@
|
|||
*/
|
||||
|
||||
|
||||
#ifndef _NGX_HTTP_SPDY_MODULE_H_INCLUDED_
|
||||
#define _NGX_HTTP_SPDY_MODULE_H_INCLUDED_
|
||||
#ifndef _NGX_HTTP_V2_MODULE_H_INCLUDED_
|
||||
#define _NGX_HTTP_V2_MODULE_H_INCLUDED_
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
|
@ -17,25 +17,26 @@
|
|||
typedef struct {
|
||||
size_t recv_buffer_size;
|
||||
u_char *recv_buffer;
|
||||
} ngx_http_spdy_main_conf_t;
|
||||
} ngx_http_v2_main_conf_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
size_t pool_size;
|
||||
ngx_uint_t concurrent_streams;
|
||||
size_t max_field_size;
|
||||
size_t max_header_size;
|
||||
ngx_uint_t streams_index_mask;
|
||||
ngx_msec_t recv_timeout;
|
||||
ngx_msec_t keepalive_timeout;
|
||||
ngx_int_t headers_comp;
|
||||
} ngx_http_spdy_srv_conf_t;
|
||||
ngx_msec_t idle_timeout;
|
||||
} ngx_http_v2_srv_conf_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
size_t chunk_size;
|
||||
} ngx_http_spdy_loc_conf_t;
|
||||
} ngx_http_v2_loc_conf_t;
|
||||
|
||||
|
||||
extern ngx_module_t ngx_http_spdy_module;
|
||||
extern ngx_module_t ngx_http_v2_module;
|
||||
|
||||
|
||||
#endif /* _NGX_HTTP_SPDY_MODULE_H_INCLUDED_ */
|
||||
#endif /* _NGX_HTTP_V2_MODULE_H_INCLUDED_ */
|
349
src/http/v2/ngx_http_v2_table.c
Normal file
349
src/http/v2/ngx_http_v2_table.c
Normal file
|
@ -0,0 +1,349 @@
|
|||
|
||||
/*
|
||||
* Copyright (C) Nginx, Inc.
|
||||
* Copyright (C) Valentin V. Bartenev
|
||||
*/
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_http.h>
|
||||
|
||||
|
||||
#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;
|
||||
}
|
Loading…
Reference in a new issue