Created
August 16, 2015 05:37
-
-
Save flano-yuki/9aef64fc6defa3303467 to your computer and use it in GitHub Desktop.
nginx http/2 patch diff v2 from v2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff -ur ./patched/v1/ngx_http_v2.c ./patched/v2/ngx_http_v2.c | |
--- ./patched/v1/ngx_http_v2.c 2015-08-16 14:30:09.292710298 +0900 | |
+++ ./patched/v2/ngx_http_v2.c 2015-08-16 14:32:58.870572942 +0900 | |
@@ -80,6 +80,8 @@ | |
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, | |
@@ -167,8 +169,9 @@ | |
static ngx_int_t ngx_http_v2_parse_method(ngx_http_request_t *r); | |
static ngx_int_t ngx_http_v2_parse_scheme(ngx_http_request_t *r); | |
static ngx_int_t ngx_http_v2_parse_authority(ngx_http_request_t *r); | |
-static ngx_int_t ngx_http_v2_construct_request_line(ngx_http_request_t *r); | |
static void ngx_http_v2_run_request(ngx_http_request_t *r); | |
+static ngx_int_t ngx_http_v2_construct_request_line(ngx_http_request_t *r); | |
+static ngx_int_t ngx_http_v2_concatenate_cookie_header(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, | |
@@ -266,9 +269,8 @@ | |
cln->handler = ngx_http_v2_pool_cleanup; | |
cln->data = h2c; | |
- h2c->streams_index = ngx_pcalloc(h2c->pool, | |
- ngx_http_v2_index_size(h2scf) | |
- * sizeof(ngx_http_v2_node_t *)); | |
+ 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; | |
@@ -287,7 +289,8 @@ | |
return; | |
} | |
- h2c->state.handler = ngx_http_v2_state_preface; | |
+ 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); | |
@@ -647,6 +650,27 @@ | |
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) | |
{ | |
@@ -746,7 +770,7 @@ | |
if (h2c->state.length == 0) { | |
ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, | |
"client sent padded DATA frame " | |
- "with incorrect lenght: %uz", | |
+ "with incorrect length: %uz", | |
h2c->state.length); | |
return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR); | |
@@ -758,7 +782,7 @@ | |
if (h2c->state.padding > h2c->state.length) { | |
ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, | |
"client sent padded DATA frame " | |
- "with incorrect lenght: %uz, padding: %uz", | |
+ "with incorrect length: %uz, padding: %uz", | |
h2c->state.length, h2c->state.padding); | |
return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR); | |
@@ -1073,7 +1097,7 @@ | |
if (h2c->state.padding > h2c->state.length) { | |
ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, | |
"client sent padded HEADERS frame " | |
- "with incorrect lenght: %uz, padding: %uz", | |
+ "with incorrect length: %uz, padding: %uz", | |
h2c->state.length, h2c->state.padding); | |
return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR); | |
@@ -1258,7 +1282,7 @@ | |
if ((len == 0 && huff) || (size_t) len > h2c->state.length) { | |
// FIXME | |
ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, | |
- "invalid header lenght %i %uz", len, h2c->state.length); | |
+ "invalid header length %i %uz", len, h2c->state.length); | |
return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_COMP_ERROR); | |
} | |
@@ -2437,7 +2461,7 @@ | |
break; | |
- case 11: | |
+ case 9: | |
if (ngx_memcmp(r->header_name_start, "authority", | |
sizeof("authority") - 1) | |
== 0) | |
@@ -2594,36 +2618,79 @@ | |
static ngx_int_t | |
ngx_http_v2_parse_authority(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"); | |
+ ngx_table_elt_t *h; | |
+ ngx_http_header_t *hh; | |
+ ngx_http_core_main_conf_t *cmcf; | |
- return NGX_HTTP_PARSE_INVALID_HEADER; | |
- } | |
+ static ngx_str_t host = ngx_string("host"); | |
h = ngx_list_push(&r->headers_in.headers); | |
if (h == NULL) { | |
return NGX_ERROR; | |
} | |
- r->headers_in.host = h; | |
+ h->hash = ngx_hash_key(host.data, host.len); | |
- h->hash = r->header_hash; | |
- | |
- h->key.len = r->header_name_end - r->header_name_start; | |
- h->key.data = r->header_name_start; | |
+ h->key.len = host.len; | |
+ h->key.data = host.data; | |
h->value.len = r->header_end - r->header_start; | |
h->value.data = r->header_start; | |
- h->lowcase_key = h->key.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 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_concatenate_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_construct_request_line(ngx_http_request_t *r) | |
{ | |
@@ -2661,37 +2728,66 @@ | |
/* 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 void | |
-ngx_http_v2_run_request(ngx_http_request_t *r) | |
+static ngx_int_t | |
+ngx_http_v2_concatenate_cookie_header(ngx_http_request_t *r) | |
{ | |
- if (ngx_http_v2_construct_request_line(r) != NGX_OK) { | |
- return; | |
+ size_t len; | |
+ u_char *p, *end, *buf; | |
+ ngx_uint_t i; | |
+ ngx_array_t *a; | |
+ ngx_table_elt_t **h; | |
+ | |
+ a = &r->headers_in.cookies; | |
+ | |
+ if (a->nelts <= 1) { | |
+ return NGX_OK; | |
} | |
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
- "http2 http request line: \"%V\"", &r->request_line); | |
+ h = a->elts; | |
- r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE; | |
+ i = 0; | |
+ len = 0; | |
- if (ngx_http_process_request_header(r) != NGX_OK) { | |
- return; | |
+ do { | |
+ len += h[i]->value.len + 2; | |
+ } while (++i != a->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; | |
} | |
- 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"); | |
+ p = buf; | |
+ end = buf + len; | |
- r->stream->skip_data = NGX_HTTP_V2_DATA_ERROR; | |
+ for (i = 0; /* void */ ; i++) { | |
- ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); | |
- return; | |
+ p = ngx_cpymem(p, h[i]->value.data, h[i]->value.len); | |
+ | |
+ if (p == end) { | |
+ *p = '\0'; | |
+ break; | |
+ } | |
+ | |
+ *p++ = ';'; *p++ = ' '; | |
} | |
- ngx_http_process_request(r); | |
+ h[0]->value.len = len; | |
+ h[0]->value.data = buf; | |
+ | |
+ a->nelts = 1; | |
+ | |
+ return NGX_OK; | |
} | |
@@ -3043,14 +3139,6 @@ | |
return; | |
} | |
- h2c->streams_index = ngx_pcalloc(h2c->pool, | |
- ngx_http_v2_index_size(h2scf) | |
- * sizeof(ngx_http_v2_stream_t *)); | |
- if (h2c->streams_index == NULL) { | |
- ngx_http_close_connection(c); | |
- return; | |
- } | |
- | |
c->write->handler = ngx_http_v2_write_handler; | |
rev->handler = ngx_http_v2_read_handler; | |
@@ -3210,7 +3298,7 @@ | |
exclusive = 0; | |
} | |
- node->rel_weight = (1 / 256) * node->weight; | |
+ node->rel_weight = (1.0 / 256) * node->weight; | |
children = &h2c->dependencies; | |
@@ -3228,7 +3316,7 @@ | |
if (node->parent == NGX_HTTP_V2_ROOT) { | |
parent->rank = 0; | |
- parent->rel_weight = (1 / 256) * parent->weight; | |
+ parent->rel_weight = (1.0 / 256) * parent->weight; | |
} else { | |
parent->rank = node->parent->rank + 1; | |
diff -ur ./patched/v1/ngx_http_v2_filter_module.c ./patched/v2/ngx_http_v2_filter_module.c | |
--- ./patched/v1/ngx_http_v2_filter_module.c 2015-08-16 14:30:09.292710298 +0900 | |
+++ ./patched/v2/ngx_http_v2_filter_module.c 2015-08-16 14:32:58.870572942 +0900 | |
@@ -113,7 +113,7 @@ | |
u_char status, *p; | |
size_t len; | |
ngx_buf_t *b; | |
- ngx_str_t host; | |
+ ngx_str_t host, location; | |
ngx_uint_t i, port; | |
ngx_chain_t *cl; | |
ngx_list_part_t *part; | |
@@ -242,72 +242,97 @@ | |
fc = r->connection; | |
- 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 (r->headers_out.location && r->headers_out.location->value.len) { | |
- if (ngx_connection_local_sockaddr(fc, &host, 0) != NGX_OK) { | |
- return NGX_ERROR; | |
+ 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) { | |
+ 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; | |
+ 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; | |
+ case AF_UNIX: | |
+ port = 0; | |
+ break; | |
#endif | |
- default: /* AF_INET */ | |
- sin = (struct sockaddr_in *) fc->local_sockaddr; | |
- port = ntohs(sin->sin_port); | |
- break; | |
- } | |
+ default: /* AF_INET */ | |
+ sin = (struct sockaddr_in *) fc->local_sockaddr; | |
+ port = ntohs(sin->sin_port); | |
+ break; | |
+ } | |
- len += NGX_HTTP_V2_INT_OCTETS | |
- + sizeof("https://") - 1 | |
- + host.len | |
- + r->headers_out.location->value.len; | |
+ location.len = sizeof("https://") - 1 + host.len | |
+ + r->headers_out.location->value.len; | |
- if (clcf->port_in_redirect) { | |
+ if (clcf->port_in_redirect) { | |
#if (NGX_HTTP_SSL) | |
- if (fc->ssl) | |
- port = (port == 443) ? 0 : port; | |
- else | |
+ if (fc->ssl) | |
+ port = (port == 443) ? 0 : port; | |
+ else | |
#endif | |
- port = (port == 80) ? 0 : port; | |
+ port = (port == 80) ? 0 : port; | |
- } else { | |
- port = 0; | |
- } | |
+ } else { | |
+ port = 0; | |
+ } | |
- if (port) { | |
- len += sizeof(":65535") - 1; | |
+ 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"); | |
} | |
- } else { | |
- ngx_str_null(&host); | |
- port = 0; | |
+ r->headers_out.location->hash = 0; | |
+ | |
+ len += 1 + NGX_HTTP_V2_INT_OCTETS + r->headers_out.location->value.len; | |
} | |
#if (NGX_HTTP_GZIP) | |
@@ -441,8 +466,14 @@ | |
*p = (u_char) (b->last - p - 1); | |
} | |
- if (host.data) { | |
- /* TODO */ | |
+ if (r->headers_out.location && r->headers_out.location->value.len) { | |
+ *b->last++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_LOCATION_INDEX); | |
+ | |
+ *b->last = 0; | |
+ b->last = ngx_http_v2_write_int(b->last, ngx_http_v2_prefix(7), | |
+ r->headers_out.location->value.len); | |
+ b->last = ngx_cpymem(b->last, r->headers_out.location->value.data, | |
+ r->headers_out.location->value.len); | |
} | |
#if (NGX_HTTP_GZIP) | |
diff -ur ./patched/v1/ngx_http_v2.h ./patched/v2/ngx_http_v2.h | |
--- ./patched/v1/ngx_http_v2.h 2015-08-16 14:30:09.292710298 +0900 | |
+++ ./patched/v2/ngx_http_v2.h 2015-08-16 14:32:58.870572942 +0900 | |
@@ -14,6 +14,7 @@ | |
#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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment