Mercurial > hg > nginx-quic
comparison src/event/ngx_event_quic.c @ 7689:61f9b873e2e7 quic
Firefox fixes.
+ support for more than one initial packet
+ workaround for trailing zeroes in packet
+ ignore application data packet if no keys yet (issue in draft 27/ff nightly)
+ fixed PING frame parser
+ STREAM frames need to be acknowledged
The following HTTP configuration is used for firefox (v74):
http {
ssl_certificate_key localhost.key;
ssl_certificate localhost.crt;
ssl_protocols TLSv1.2 TLSv1.3;
server {
listen 127.0.0.1:10368 reuseport http3;
ssl_quic on;
server_name localhost;
location / {
return 200 "This-is-QUICK\n";
}
}
server {
listen 127.0.0.1:5555 ssl; # point the browser here
server_name localhost;
location / {
add_header Alt-Svc 'h3-24=":10368";ma=100';
return 200 "ALT-SVC";
}
}
}
author | Vladimir Homutov <vl@nginx.com> |
---|---|
date | Tue, 17 Mar 2020 14:10:37 +0300 |
parents | bec4cd55361e |
children | ae35ccba7aa6 |
comparison
equal
deleted
inserted
replaced
7688:bec4cd55361e | 7689:61f9b873e2e7 |
---|---|
203 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); | 203 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); |
204 | 204 |
205 static void ngx_quic_handshake_handler(ngx_event_t *rev); | 205 static void ngx_quic_handshake_handler(ngx_event_t *rev); |
206 static ngx_int_t ngx_quic_handshake_input(ngx_connection_t *c, | 206 static ngx_int_t ngx_quic_handshake_input(ngx_connection_t *c, |
207 ngx_quic_header_t *pkt); | 207 ngx_quic_header_t *pkt); |
208 static ngx_int_t ngx_quic_initial_input(ngx_connection_t *c, | |
209 ngx_quic_header_t *pkt); | |
208 static ngx_int_t ngx_quic_app_input(ngx_connection_t *c, | 210 static ngx_int_t ngx_quic_app_input(ngx_connection_t *c, |
209 ngx_quic_header_t *pkt); | 211 ngx_quic_header_t *pkt); |
210 | 212 |
211 | 213 |
212 #if BORINGSSL_API_VERSION >= 10 | 214 #if BORINGSSL_API_VERSION >= 10 |
387 | 389 |
388 static ngx_int_t | 390 static ngx_int_t |
389 ngx_quic_input(ngx_connection_t *c, ngx_buf_t *b) | 391 ngx_quic_input(ngx_connection_t *c, ngx_buf_t *b) |
390 { | 392 { |
391 u_char *p; | 393 u_char *p; |
394 ngx_int_t rc; | |
392 ngx_quic_header_t pkt; | 395 ngx_quic_header_t pkt; |
393 | 396 |
394 if (c->quic == NULL) { | 397 if (c->quic == NULL) { |
395 // XXX: possible? | 398 // XXX: possible? |
396 ngx_log_error(NGX_LOG_INFO, c->log, 0, "BUG: no QUIC in connection"); | 399 ngx_log_error(NGX_LOG_INFO, c->log, 0, "BUG: no QUIC in connection"); |
403 ngx_memzero(&pkt, sizeof(ngx_quic_header_t)); | 406 ngx_memzero(&pkt, sizeof(ngx_quic_header_t)); |
404 pkt.raw = b; | 407 pkt.raw = b; |
405 pkt.data = p; | 408 pkt.data = p; |
406 pkt.len = b->last - p; | 409 pkt.len = b->last - p; |
407 | 410 |
411 if (p[0] == 0) { | |
412 /* XXX: no idea WTF is this, just ignore */ | |
413 ngx_log_error(NGX_LOG_ALERT, c->log, 0, "FIREFOX: ZEROES"); | |
414 break; | |
415 } | |
416 | |
417 // TODO: check current state | |
408 if (p[0] & NGX_QUIC_PKT_LONG) { | 418 if (p[0] & NGX_QUIC_PKT_LONG) { |
409 // TODO: check current state | 419 |
410 if (ngx_quic_handshake_input(c, &pkt) != NGX_OK) { | 420 if ((p[0] & 0xf0) == NGX_QUIC_PKT_INITIAL) { |
421 rc = ngx_quic_initial_input(c, &pkt); | |
422 | |
423 } else if ((p[0] & 0xf0) == NGX_QUIC_PKT_HANDSHAKE) { | |
424 rc = ngx_quic_handshake_input(c, &pkt); | |
425 | |
426 } else { | |
427 ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
428 "BUG: unknown quic state"); | |
411 return NGX_ERROR; | 429 return NGX_ERROR; |
412 } | 430 } |
431 | |
413 } else { | 432 } else { |
414 | 433 rc = ngx_quic_app_input(c, &pkt); |
415 if (ngx_quic_app_input(c, &pkt) != NGX_OK) { | 434 } |
416 return NGX_ERROR; | 435 |
417 } | 436 if (rc == NGX_ERROR) { |
437 return NGX_ERROR; | |
418 } | 438 } |
419 | 439 |
420 /* b->pos is at header end, adjust by actual packet length */ | 440 /* b->pos is at header end, adjust by actual packet length */ |
421 p = b->pos + pkt.len; | 441 p = b->pos + pkt.len; |
422 b->pos = p; /* reset b->pos to the next packet start */ | 442 b->pos = p; /* reset b->pos to the next packet start */ |
1071 | 1091 |
1072 break; | 1092 break; |
1073 | 1093 |
1074 case NGX_QUIC_FT_PING: | 1094 case NGX_QUIC_FT_PING: |
1075 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "PING frame"); | 1095 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "PING frame"); |
1076 p++; | |
1077 break; | 1096 break; |
1078 | 1097 |
1079 case NGX_QUIC_FT_NEW_CONNECTION_ID: | 1098 case NGX_QUIC_FT_NEW_CONNECTION_ID: |
1080 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "NCID frame"); | 1099 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "NCID frame"); |
1081 | 1100 |
1487 case NGX_QUIC_FT_STREAM4: | 1506 case NGX_QUIC_FT_STREAM4: |
1488 case NGX_QUIC_FT_STREAM5: | 1507 case NGX_QUIC_FT_STREAM5: |
1489 case NGX_QUIC_FT_STREAM6: | 1508 case NGX_QUIC_FT_STREAM6: |
1490 case NGX_QUIC_FT_STREAM7: | 1509 case NGX_QUIC_FT_STREAM7: |
1491 | 1510 |
1511 ack_this = 1; | |
1512 | |
1492 ngx_log_debug7(NGX_LOG_DEBUG_EVENT, c->log, 0, | 1513 ngx_log_debug7(NGX_LOG_DEBUG_EVENT, c->log, 0, |
1493 "STREAM frame 0x%xi id 0x%xi offset 0x%xi len 0x%xi bits:off=%d len=%d fin=%d", | 1514 "STREAM frame 0x%xi id 0x%xi offset 0x%xi len 0x%xi bits:off=%d len=%d fin=%d", |
1494 frame.type, | 1515 frame.type, |
1495 frame.u.stream.stream_id, | 1516 frame.u.stream.stream_id, |
1496 frame.u.stream.offset, | 1517 frame.u.stream.offset, |
1773 return ngx_quic_payload_handler(c, pkt); | 1794 return ngx_quic_payload_handler(c, pkt); |
1774 } | 1795 } |
1775 | 1796 |
1776 | 1797 |
1777 static ngx_int_t | 1798 static ngx_int_t |
1799 ngx_quic_initial_input(ngx_connection_t *c, ngx_quic_header_t *pkt) | |
1800 { | |
1801 ngx_ssl_conn_t *ssl_conn; | |
1802 ngx_quic_connection_t *qc; | |
1803 | |
1804 qc = c->quic; | |
1805 ssl_conn = c->ssl->connection; | |
1806 | |
1807 if (ngx_quic_process_long_header(c, pkt) != NGX_OK) { | |
1808 return NGX_ERROR; | |
1809 } | |
1810 | |
1811 if (ngx_quic_process_initial_header(c, pkt) != NGX_OK) { | |
1812 return NGX_ERROR; | |
1813 } | |
1814 | |
1815 pkt->secret = &qc->secrets.client.in; | |
1816 pkt->level = ssl_encryption_initial; | |
1817 | |
1818 if (ngx_quic_decrypt(c->pool, ssl_conn, pkt) != NGX_OK) { | |
1819 return NGX_ERROR; | |
1820 } | |
1821 | |
1822 return ngx_quic_payload_handler(c, pkt); | |
1823 } | |
1824 | |
1825 | |
1826 static ngx_int_t | |
1778 ngx_quic_handshake_input(ngx_connection_t *c, ngx_quic_header_t *pkt) | 1827 ngx_quic_handshake_input(ngx_connection_t *c, ngx_quic_header_t *pkt) |
1779 { | 1828 { |
1780 ngx_ssl_conn_t *ssl_conn; | 1829 ngx_ssl_conn_t *ssl_conn; |
1781 ngx_quic_connection_t *qc; | 1830 ngx_quic_connection_t *qc; |
1782 | 1831 |
1834 { | 1883 { |
1835 ngx_quic_connection_t *qc; | 1884 ngx_quic_connection_t *qc; |
1836 | 1885 |
1837 qc = c->quic; | 1886 qc = c->quic; |
1838 | 1887 |
1839 /* TODO: this is a stub, untested */ | 1888 if (qc->secrets.client.ad.key.len == 0) { |
1889 ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
1890 "no read keys yet, packet ignored"); | |
1891 return NGX_DECLINED; | |
1892 } | |
1840 | 1893 |
1841 if (ngx_quic_process_short_header(c, pkt) != NGX_OK) { | 1894 if (ngx_quic_process_short_header(c, pkt) != NGX_OK) { |
1842 return NGX_ERROR; | 1895 return NGX_ERROR; |
1843 } | 1896 } |
1844 | 1897 |