comparison src/http/v2/ngx_http_v2.c @ 9119:08ef02ad5c54

HTTP/2: "http2" directive. The directive enables HTTP/2 in the current server. The previous way to enable HTTP/2 via "listen ... http2" is now deprecated. The new approach allows to share HTTP/2 and HTTP/0.9-1.1 on the same port. For SSL connections, HTTP/2 is now selected by ALPN callback based on whether the protocol is enabled in the virtual server chosen by SNI. This however only works since OpenSSL 1.0.2h, where ALPN callback is invoked after SNI callback. For older versions of OpenSSL, HTTP/2 is enabled based on the default virtual server configuration. For plain TCP connections, HTTP/2 is now auto-detected by HTTP/2 preface, if HTTP/2 is enabled in the default virtual server. If preface is not matched, HTTP/0.9-1.1 is assumed.
author Roman Arutyunyan <arut@nginx.com>
date Tue, 16 May 2023 16:30:08 +0400
parents 9db24374123b
children 262c01782566
comparison
equal deleted inserted replaced
9118:b4a57278bf24 9119:08ef02ad5c54
61 static void ngx_http_v2_write_handler(ngx_event_t *wev); 61 static void ngx_http_v2_write_handler(ngx_event_t *wev);
62 static void ngx_http_v2_handle_connection(ngx_http_v2_connection_t *h2c); 62 static void ngx_http_v2_handle_connection(ngx_http_v2_connection_t *h2c);
63 static void ngx_http_v2_lingering_close(ngx_connection_t *c); 63 static void ngx_http_v2_lingering_close(ngx_connection_t *c);
64 static void ngx_http_v2_lingering_close_handler(ngx_event_t *rev); 64 static void ngx_http_v2_lingering_close_handler(ngx_event_t *rev);
65 65
66 static u_char *ngx_http_v2_state_proxy_protocol(ngx_http_v2_connection_t *h2c,
67 u_char *pos, u_char *end);
68 static u_char *ngx_http_v2_state_preface(ngx_http_v2_connection_t *h2c, 66 static u_char *ngx_http_v2_state_preface(ngx_http_v2_connection_t *h2c,
69 u_char *pos, u_char *end); 67 u_char *pos, u_char *end);
70 static u_char *ngx_http_v2_state_preface_end(ngx_http_v2_connection_t *h2c, 68 static u_char *ngx_http_v2_state_preface_end(ngx_http_v2_connection_t *h2c,
71 u_char *pos, u_char *end); 69 u_char *pos, u_char *end);
72 static u_char *ngx_http_v2_state_head(ngx_http_v2_connection_t *h2c, 70 static u_char *ngx_http_v2_state_head(ngx_http_v2_connection_t *h2c,
230 228
231 229
232 void 230 void
233 ngx_http_v2_init(ngx_event_t *rev) 231 ngx_http_v2_init(ngx_event_t *rev)
234 { 232 {
233 u_char *p, *end;
235 ngx_connection_t *c; 234 ngx_connection_t *c;
236 ngx_pool_cleanup_t *cln; 235 ngx_pool_cleanup_t *cln;
237 ngx_http_connection_t *hc; 236 ngx_http_connection_t *hc;
238 ngx_http_v2_srv_conf_t *h2scf; 237 ngx_http_v2_srv_conf_t *h2scf;
239 ngx_http_v2_main_conf_t *h2mcf; 238 ngx_http_v2_main_conf_t *h2mcf;
312 { 311 {
313 ngx_http_close_connection(c); 312 ngx_http_close_connection(c);
314 return; 313 return;
315 } 314 }
316 315
317 h2c->state.handler = hc->proxy_protocol ? ngx_http_v2_state_proxy_protocol 316 h2c->state.handler = ngx_http_v2_state_preface;
318 : ngx_http_v2_state_preface;
319 317
320 ngx_queue_init(&h2c->waiting); 318 ngx_queue_init(&h2c->waiting);
321 ngx_queue_init(&h2c->dependencies); 319 ngx_queue_init(&h2c->dependencies);
322 ngx_queue_init(&h2c->closed); 320 ngx_queue_init(&h2c->closed);
323 321
332 ngx_add_timer(rev, cscf->client_header_timeout); 330 ngx_add_timer(rev, cscf->client_header_timeout);
333 } 331 }
334 332
335 c->idle = 1; 333 c->idle = 1;
336 ngx_reusable_connection(c, 0); 334 ngx_reusable_connection(c, 0);
335
336 if (c->buffer) {
337 p = c->buffer->pos;
338 end = c->buffer->last;
339
340 do {
341 p = h2c->state.handler(h2c, p, end);
342
343 if (p == NULL) {
344 return;
345 }
346
347 } while (p != end);
348
349 h2c->total_bytes += p - c->buffer->pos;
350 c->buffer->pos = p;
351 }
337 352
338 ngx_http_v2_read_handler(rev); 353 ngx_http_v2_read_handler(rev);
339 } 354 }
340 355
341 356
845 ngx_add_timer(rev, timer); 860 ngx_add_timer(rev, timer);
846 } 861 }
847 862
848 863
849 static u_char * 864 static u_char *
850 ngx_http_v2_state_proxy_protocol(ngx_http_v2_connection_t *h2c, u_char *pos,
851 u_char *end)
852 {
853 ngx_log_t *log;
854
855 log = h2c->connection->log;
856 log->action = "reading PROXY protocol";
857
858 pos = ngx_proxy_protocol_read(h2c->connection, pos, end);
859
860 log->action = "processing HTTP/2 connection";
861
862 if (pos == NULL) {
863 return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR);
864 }
865
866 return ngx_http_v2_state_preface(h2c, pos, end);
867 }
868
869
870 static u_char *
871 ngx_http_v2_state_preface(ngx_http_v2_connection_t *h2c, u_char *pos, 865 ngx_http_v2_state_preface(ngx_http_v2_connection_t *h2c, u_char *pos,
872 u_char *end) 866 u_char *end)
873 { 867 {
874 static const u_char preface[] = "PRI * HTTP/2.0\r\n"; 868 static const u_char preface[] = NGX_HTTP_V2_PREFACE_START;
875 869
876 if ((size_t) (end - pos) < sizeof(preface) - 1) { 870 if ((size_t) (end - pos) < sizeof(preface) - 1) {
877 return ngx_http_v2_state_save(h2c, pos, end, ngx_http_v2_state_preface); 871 return ngx_http_v2_state_save(h2c, pos, end, ngx_http_v2_state_preface);
878 } 872 }
879 873
890 884
891 static u_char * 885 static u_char *
892 ngx_http_v2_state_preface_end(ngx_http_v2_connection_t *h2c, u_char *pos, 886 ngx_http_v2_state_preface_end(ngx_http_v2_connection_t *h2c, u_char *pos,
893 u_char *end) 887 u_char *end)
894 { 888 {
895 static const u_char preface[] = "\r\nSM\r\n\r\n"; 889 static const u_char preface[] = NGX_HTTP_V2_PREFACE_END;
896 890
897 if ((size_t) (end - pos) < sizeof(preface) - 1) { 891 if ((size_t) (end - pos) < sizeof(preface) - 1) {
898 return ngx_http_v2_state_save(h2c, pos, end, 892 return ngx_http_v2_state_save(h2c, pos, end,
899 ngx_http_v2_state_preface_end); 893 ngx_http_v2_state_preface_end);
900 } 894 }
3941 3935
3942 static void 3936 static void
3943 ngx_http_v2_run_request(ngx_http_request_t *r) 3937 ngx_http_v2_run_request(ngx_http_request_t *r)
3944 { 3938 {
3945 ngx_connection_t *fc; 3939 ngx_connection_t *fc;
3940 ngx_http_v2_srv_conf_t *h2scf;
3946 ngx_http_v2_connection_t *h2c; 3941 ngx_http_v2_connection_t *h2c;
3947 3942
3948 fc = r->connection; 3943 fc = r->connection;
3944
3945 h2scf = ngx_http_get_module_srv_conf(r, ngx_http_v2_module);
3946
3947 if (!h2scf->enable && !r->http_connection->addr_conf->http2) {
3948 ngx_log_error(NGX_LOG_INFO, fc->log, 0,
3949 "client attempted to request the server name "
3950 "for which the negotiated protocol is disabled");
3951
3952 ngx_http_finalize_request(r, NGX_HTTP_MISDIRECTED_REQUEST);
3953 goto failed;
3954 }
3949 3955
3950 if (ngx_http_v2_construct_request_line(r) != NGX_OK) { 3956 if (ngx_http_v2_construct_request_line(r) != NGX_OK) {
3951 goto failed; 3957 goto failed;
3952 } 3958 }
3953 3959