Skip to content

Instantly share code, notes, and snippets.

@flano-yuki
Created August 16, 2015 05:37
Show Gist options
  • Save flano-yuki/9aef64fc6defa3303467 to your computer and use it in GitHub Desktop.
Save flano-yuki/9aef64fc6defa3303467 to your computer and use it in GitHub Desktop.
nginx http/2 patch diff v2 from v2
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