Mercurial > hg > nginx
comparison src/event/ngx_event_quic.c @ 8628:45db1b5c1706 quic
QUIC: connection multiplexing per port.
Also, connection migration within a single worker is implemented.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Wed, 11 Nov 2020 11:57:50 +0000 |
parents | 405b6e8eb523 |
children | feec2cc762f6 |
comparison
equal
deleted
inserted
replaced
8627:405b6e8eb523 | 8628:45db1b5c1706 |
---|---|
119 ngx_str_t scid; /* initial client ID */ | 119 ngx_str_t scid; /* initial client ID */ |
120 ngx_str_t dcid; /* server (our own) ID */ | 120 ngx_str_t dcid; /* server (our own) ID */ |
121 ngx_str_t odcid; /* original server ID */ | 121 ngx_str_t odcid; /* original server ID */ |
122 ngx_str_t token; | 122 ngx_str_t token; |
123 | 123 |
124 struct sockaddr *sockaddr; | |
125 socklen_t socklen; | |
126 | |
124 ngx_queue_t client_ids; | 127 ngx_queue_t client_ids; |
128 ngx_queue_t server_ids; | |
125 ngx_queue_t free_client_ids; | 129 ngx_queue_t free_client_ids; |
130 ngx_queue_t free_server_ids; | |
126 ngx_uint_t nclient_ids; | 131 ngx_uint_t nclient_ids; |
132 ngx_uint_t nserver_ids; | |
127 uint64_t max_retired_seqnum; | 133 uint64_t max_retired_seqnum; |
128 uint64_t client_seqnum; | 134 uint64_t client_seqnum; |
135 uint64_t server_seqnum; | |
129 | 136 |
130 ngx_uint_t client_tp_done; | 137 ngx_uint_t client_tp_done; |
131 ngx_quic_tp_t tp; | 138 ngx_quic_tp_t tp; |
132 ngx_quic_tp_t ctp; | 139 ngx_quic_tp_t ctp; |
133 | 140 |
181 uint64_t seqnum; | 188 uint64_t seqnum; |
182 size_t len; | 189 size_t len; |
183 u_char id[NGX_QUIC_CID_LEN_MAX]; | 190 u_char id[NGX_QUIC_CID_LEN_MAX]; |
184 u_char sr_token[NGX_QUIC_SR_TOKEN_LEN]; | 191 u_char sr_token[NGX_QUIC_SR_TOKEN_LEN]; |
185 } ngx_quic_client_id_t; | 192 } ngx_quic_client_id_t; |
193 | |
194 | |
195 typedef struct { | |
196 ngx_udp_connection_t udp; | |
197 ngx_queue_t queue; | |
198 uint64_t seqnum; | |
199 size_t len; | |
200 u_char id[NGX_QUIC_CID_LEN_MAX]; | |
201 } ngx_quic_server_id_t; | |
186 | 202 |
187 | 203 |
188 typedef ngx_int_t (*ngx_quic_frame_handler_pt)(ngx_connection_t *c, | 204 typedef ngx_int_t (*ngx_quic_frame_handler_pt)(ngx_connection_t *c, |
189 ngx_quic_frame_t *frame, void *data); | 205 ngx_quic_frame_t *frame, void *data); |
190 | 206 |
215 ngx_quic_conf_t *conf, ngx_quic_header_t *pkt); | 231 ngx_quic_conf_t *conf, ngx_quic_header_t *pkt); |
216 static ngx_int_t ngx_quic_process_stateless_reset(ngx_connection_t *c, | 232 static ngx_int_t ngx_quic_process_stateless_reset(ngx_connection_t *c, |
217 ngx_quic_header_t *pkt); | 233 ngx_quic_header_t *pkt); |
218 static ngx_int_t ngx_quic_negotiate_version(ngx_connection_t *c, | 234 static ngx_int_t ngx_quic_negotiate_version(ngx_connection_t *c, |
219 ngx_quic_header_t *inpkt); | 235 ngx_quic_header_t *inpkt); |
220 static ngx_int_t ngx_quic_new_dcid(ngx_connection_t *c, | 236 static ngx_int_t ngx_quic_create_server_id(ngx_connection_t *c, u_char *id); |
221 ngx_quic_connection_t *qc, ngx_str_t *odcid); | |
222 static ngx_int_t ngx_quic_send_retry(ngx_connection_t *c); | 237 static ngx_int_t ngx_quic_send_retry(ngx_connection_t *c); |
223 static ngx_int_t ngx_quic_new_token(ngx_connection_t *c, ngx_str_t *token); | 238 static ngx_int_t ngx_quic_new_token(ngx_connection_t *c, ngx_str_t *token); |
224 static ngx_int_t ngx_quic_validate_token(ngx_connection_t *c, | 239 static ngx_int_t ngx_quic_validate_token(ngx_connection_t *c, |
225 ngx_quic_header_t *pkt); | 240 ngx_quic_header_t *pkt); |
226 static ngx_int_t ngx_quic_init_connection(ngx_connection_t *c); | 241 static ngx_int_t ngx_quic_init_connection(ngx_connection_t *c); |
302 ngx_quic_header_t *pkt, ngx_quic_path_challenge_frame_t *f); | 317 ngx_quic_header_t *pkt, ngx_quic_path_challenge_frame_t *f); |
303 static ngx_int_t ngx_quic_handle_new_connection_id_frame(ngx_connection_t *c, | 318 static ngx_int_t ngx_quic_handle_new_connection_id_frame(ngx_connection_t *c, |
304 ngx_quic_header_t *pkt, ngx_quic_new_conn_id_frame_t *f); | 319 ngx_quic_header_t *pkt, ngx_quic_new_conn_id_frame_t *f); |
305 static ngx_int_t ngx_quic_retire_connection_id(ngx_connection_t *c, | 320 static ngx_int_t ngx_quic_retire_connection_id(ngx_connection_t *c, |
306 enum ssl_encryption_level_t level, uint64_t seqnum); | 321 enum ssl_encryption_level_t level, uint64_t seqnum); |
322 static ngx_int_t ngx_quic_handle_retire_connection_id_frame(ngx_connection_t *c, | |
323 ngx_quic_header_t *pkt, ngx_quic_retire_cid_frame_t *f); | |
324 static ngx_int_t ngx_quic_issue_server_ids(ngx_connection_t *c); | |
325 static void ngx_quic_clear_temp_server_ids(ngx_connection_t *c); | |
326 static ngx_quic_server_id_t *ngx_quic_insert_server_id(ngx_connection_t *c, | |
327 ngx_str_t *id); | |
307 static ngx_quic_client_id_t *ngx_quic_alloc_client_id(ngx_connection_t *c, | 328 static ngx_quic_client_id_t *ngx_quic_alloc_client_id(ngx_connection_t *c, |
329 ngx_quic_connection_t *qc); | |
330 static ngx_quic_server_id_t *ngx_quic_alloc_server_id(ngx_connection_t *c, | |
308 ngx_quic_connection_t *qc); | 331 ngx_quic_connection_t *qc); |
309 | 332 |
310 static void ngx_quic_queue_frame(ngx_quic_connection_t *qc, | 333 static void ngx_quic_queue_frame(ngx_quic_connection_t *qc, |
311 ngx_quic_frame_t *frame); | 334 ngx_quic_frame_t *frame); |
312 | 335 |
437 case NGX_QUIC_FT_PING: | 460 case NGX_QUIC_FT_PING: |
438 p = ngx_slprintf(p, last, "PING"); | 461 p = ngx_slprintf(p, last, "PING"); |
439 break; | 462 break; |
440 | 463 |
441 case NGX_QUIC_FT_NEW_CONNECTION_ID: | 464 case NGX_QUIC_FT_NEW_CONNECTION_ID: |
442 p = ngx_slprintf(p, last, "NCID seq:%uL retire:%uL len:%ud", | 465 p = ngx_slprintf(p, last, |
466 "NEW_CONNECTION_ID seq:%uL retire:%uL len:%ud", | |
443 f->u.ncid.seqnum, f->u.ncid.retire, f->u.ncid.len); | 467 f->u.ncid.seqnum, f->u.ncid.retire, f->u.ncid.len); |
444 break; | 468 break; |
445 | 469 |
446 case NGX_QUIC_FT_RETIRE_CONNECTION_ID: | 470 case NGX_QUIC_FT_RETIRE_CONNECTION_ID: |
447 p = ngx_slprintf(p, last, "RETIRE_CONNECTION_ID seqnum:%uL", | 471 p = ngx_slprintf(p, last, "RETIRE_CONNECTION_ID seqnum:%uL", |
981 ngx_queue_init(&qc->crypto[i].frames); | 1005 ngx_queue_init(&qc->crypto[i].frames); |
982 } | 1006 } |
983 | 1007 |
984 ngx_queue_init(&qc->free_frames); | 1008 ngx_queue_init(&qc->free_frames); |
985 ngx_queue_init(&qc->client_ids); | 1009 ngx_queue_init(&qc->client_ids); |
1010 ngx_queue_init(&qc->server_ids); | |
986 ngx_queue_init(&qc->free_client_ids); | 1011 ngx_queue_init(&qc->free_client_ids); |
1012 ngx_queue_init(&qc->free_server_ids); | |
987 | 1013 |
988 qc->avg_rtt = NGX_QUIC_INITIAL_RTT; | 1014 qc->avg_rtt = NGX_QUIC_INITIAL_RTT; |
989 qc->rttvar = NGX_QUIC_INITIAL_RTT / 2; | 1015 qc->rttvar = NGX_QUIC_INITIAL_RTT / 2; |
990 qc->min_rtt = NGX_TIMER_INFINITE; | 1016 qc->min_rtt = NGX_TIMER_INFINITE; |
991 | 1017 |
992 /* | 1018 /* |
993 * qc->latest_rtt = 0 | 1019 * qc->latest_rtt = 0 |
994 * qc->nclient_ids = 0 | 1020 * qc->nclient_ids = 0 |
1021 * qc->nserver_ids = 0 | |
995 * qc->max_retired_seqnum = 0 | 1022 * qc->max_retired_seqnum = 0 |
996 */ | 1023 */ |
997 | 1024 |
998 qc->received = pkt->raw->last - pkt->raw->start; | 1025 qc->received = pkt->raw->last - pkt->raw->start; |
999 | 1026 |
1007 qc->push.handler = ngx_quic_push_handler; | 1034 qc->push.handler = ngx_quic_push_handler; |
1008 qc->push.cancelable = 1; | 1035 qc->push.cancelable = 1; |
1009 | 1036 |
1010 qc->conf = conf; | 1037 qc->conf = conf; |
1011 qc->tp = conf->tp; | 1038 qc->tp = conf->tp; |
1039 | |
1040 if (qc->tp.disable_active_migration) { | |
1041 qc->sockaddr = ngx_palloc(c->pool, c->socklen); | |
1042 if (qc->sockaddr == NULL) { | |
1043 return NULL; | |
1044 } | |
1045 | |
1046 ngx_memcpy(qc->sockaddr, c->sockaddr, c->socklen); | |
1047 qc->socklen = c->socklen; | |
1048 } | |
1012 | 1049 |
1013 ctp = &qc->ctp; | 1050 ctp = &qc->ctp; |
1014 ctp->max_udp_payload_size = ngx_quic_max_udp_payload(c); | 1051 ctp->max_udp_payload_size = ngx_quic_max_udp_payload(c); |
1015 ctp->ack_delay_exponent = NGX_QUIC_DEFAULT_ACK_DELAY_EXPONENT; | 1052 ctp->ack_delay_exponent = NGX_QUIC_DEFAULT_ACK_DELAY_EXPONENT; |
1016 ctp->max_ack_delay = NGX_QUIC_DEFAULT_MAX_ACK_DELAY; | 1053 ctp->max_ack_delay = NGX_QUIC_DEFAULT_MAX_ACK_DELAY; |
1024 ngx_max(2 * qc->tp.max_udp_payload_size, | 1061 ngx_max(2 * qc->tp.max_udp_payload_size, |
1025 14720)); | 1062 14720)); |
1026 qc->congestion.ssthresh = (size_t) -1; | 1063 qc->congestion.ssthresh = (size_t) -1; |
1027 qc->congestion.recovery_start = ngx_current_msec; | 1064 qc->congestion.recovery_start = ngx_current_msec; |
1028 | 1065 |
1029 if (ngx_quic_new_dcid(c, qc, &pkt->dcid) != NGX_OK) { | 1066 qc->odcid.len = pkt->dcid.len; |
1067 qc->odcid.data = ngx_pstrdup(c->pool, &pkt->dcid); | |
1068 if (qc->odcid.data == NULL) { | |
1069 return NULL; | |
1070 } | |
1071 | |
1072 qc->dcid.len = NGX_QUIC_SERVER_CID_LEN; | |
1073 qc->dcid.data = ngx_pnalloc(c->pool, qc->dcid.len); | |
1074 if (qc->dcid.data == NULL) { | |
1075 return NULL; | |
1076 } | |
1077 | |
1078 if (ngx_quic_create_server_id(c, qc->dcid.data) != NGX_OK) { | |
1030 return NULL; | 1079 return NULL; |
1031 } | 1080 } |
1032 | 1081 |
1033 #if (NGX_QUIC_DRAFT_VERSION >= 28) | 1082 #if (NGX_QUIC_DRAFT_VERSION >= 28) |
1034 qc->tp.original_dcid = qc->odcid; | 1083 qc->tp.original_dcid = qc->odcid; |
1052 ngx_memcpy(cid->id, pkt->scid.data, pkt->scid.len); | 1101 ngx_memcpy(cid->id, pkt->scid.data, pkt->scid.len); |
1053 | 1102 |
1054 ngx_queue_insert_tail(&qc->client_ids, &cid->queue); | 1103 ngx_queue_insert_tail(&qc->client_ids, &cid->queue); |
1055 qc->nclient_ids++; | 1104 qc->nclient_ids++; |
1056 qc->client_seqnum = 0; | 1105 qc->client_seqnum = 0; |
1106 | |
1107 qc->server_seqnum = NGX_QUIC_UNSET_PN; | |
1057 | 1108 |
1058 return qc; | 1109 return qc; |
1059 } | 1110 } |
1060 | 1111 |
1061 | 1112 |
1184 return NGX_ERROR; | 1235 return NGX_ERROR; |
1185 } | 1236 } |
1186 | 1237 |
1187 | 1238 |
1188 static ngx_int_t | 1239 static ngx_int_t |
1189 ngx_quic_new_dcid(ngx_connection_t *c, ngx_quic_connection_t *qc, | 1240 ngx_quic_create_server_id(ngx_connection_t *c, u_char *id) |
1190 ngx_str_t *odcid) | 1241 { |
1191 { | 1242 if (RAND_bytes(id, NGX_QUIC_SERVER_CID_LEN) != 1) { |
1192 qc->dcid.len = NGX_QUIC_SERVER_CID_LEN; | |
1193 qc->dcid.data = ngx_pnalloc(c->pool, NGX_QUIC_SERVER_CID_LEN); | |
1194 if (qc->dcid.data == NULL) { | |
1195 return NGX_ERROR; | 1243 return NGX_ERROR; |
1196 } | 1244 } |
1197 | 1245 |
1198 if (RAND_bytes(qc->dcid.data, NGX_QUIC_SERVER_CID_LEN) != 1) { | 1246 ngx_quic_hexdump(c->log, "quic create server id", |
1199 return NGX_ERROR; | 1247 id, NGX_QUIC_SERVER_CID_LEN); |
1200 } | |
1201 | |
1202 ngx_quic_hexdump(c->log, "quic server CID", qc->dcid.data, qc->dcid.len); | |
1203 | |
1204 qc->odcid.len = odcid->len; | |
1205 qc->odcid.data = ngx_pstrdup(c->pool, odcid); | |
1206 if (qc->odcid.data == NULL) { | |
1207 return NGX_ERROR; | |
1208 } | |
1209 | 1248 |
1210 return NGX_OK; | 1249 return NGX_OK; |
1211 } | 1250 } |
1212 | 1251 |
1213 | 1252 |
1251 #if (NGX_QUIC_DRAFT_VERSION < 28) | 1290 #if (NGX_QUIC_DRAFT_VERSION < 28) |
1252 c->quic->tp.original_dcid = c->quic->odcid; | 1291 c->quic->tp.original_dcid = c->quic->odcid; |
1253 #endif | 1292 #endif |
1254 c->quic->tp.retry_scid = c->quic->dcid; | 1293 c->quic->tp.retry_scid = c->quic->dcid; |
1255 c->quic->in_retry = 1; | 1294 c->quic->in_retry = 1; |
1295 | |
1296 if (ngx_quic_insert_server_id(c, &c->quic->dcid) == NULL) { | |
1297 return NGX_ERROR; | |
1298 } | |
1256 | 1299 |
1257 return NGX_OK; | 1300 return NGX_OK; |
1258 } | 1301 } |
1259 | 1302 |
1260 | 1303 |
1627 c->read->eof = 1; | 1670 c->read->eof = 1; |
1628 ngx_quic_close_connection(c, NGX_ERROR); | 1671 ngx_quic_close_connection(c, NGX_ERROR); |
1629 return; | 1672 return; |
1630 } | 1673 } |
1631 | 1674 |
1675 if (qc->tp.disable_active_migration) { | |
1676 if (c->socklen != qc->socklen | |
1677 || ngx_memcmp(c->sockaddr, qc->sockaddr, c->socklen) != 0) | |
1678 { | |
1679 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
1680 "quic dropping packet from new address"); | |
1681 return; | |
1682 } | |
1683 } | |
1684 | |
1632 b.last += n; | 1685 b.last += n; |
1633 qc->received += n; | 1686 qc->received += n; |
1634 | 1687 |
1635 rc = ngx_quic_input(c, &b, NULL); | 1688 rc = ngx_quic_input(c, &b, NULL); |
1636 | 1689 |
1692 | 1745 |
1693 static ngx_int_t | 1746 static ngx_int_t |
1694 ngx_quic_close_quic(ngx_connection_t *c, ngx_int_t rc) | 1747 ngx_quic_close_quic(ngx_connection_t *c, ngx_int_t rc) |
1695 { | 1748 { |
1696 ngx_uint_t i; | 1749 ngx_uint_t i; |
1750 ngx_queue_t *q; | |
1697 ngx_quic_send_ctx_t *ctx; | 1751 ngx_quic_send_ctx_t *ctx; |
1752 ngx_quic_server_id_t *sid; | |
1698 ngx_quic_connection_t *qc; | 1753 ngx_quic_connection_t *qc; |
1699 | 1754 |
1700 qc = c->quic; | 1755 qc = c->quic; |
1701 | 1756 |
1702 if (!qc->closing) { | 1757 if (!qc->closing) { |
1797 } | 1852 } |
1798 | 1853 |
1799 for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) { | 1854 for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) { |
1800 ngx_quic_free_frames(c, &qc->send_ctx[i].frames); | 1855 ngx_quic_free_frames(c, &qc->send_ctx[i].frames); |
1801 ngx_quic_free_frames(c, &qc->send_ctx[i].sent); | 1856 ngx_quic_free_frames(c, &qc->send_ctx[i].sent); |
1857 } | |
1858 | |
1859 while (!ngx_queue_empty(&qc->server_ids)) { | |
1860 q = ngx_queue_head(&qc->server_ids); | |
1861 sid = ngx_queue_data(q, ngx_quic_server_id_t, queue); | |
1862 | |
1863 ngx_queue_remove(q); | |
1864 ngx_rbtree_delete(&c->listening->rbtree, &sid->udp.node); | |
1865 qc->nserver_ids--; | |
1802 } | 1866 } |
1803 | 1867 |
1804 if (qc->close.timer_set) { | 1868 if (qc->close.timer_set) { |
1805 return NGX_AGAIN; | 1869 return NGX_AGAIN; |
1806 } | 1870 } |
2063 ngx_log_error(NGX_LOG_INFO, c->log, 0, | 2127 ngx_log_error(NGX_LOG_INFO, c->log, 0, |
2064 "quic discard retry packet without token"); | 2128 "quic discard retry packet without token"); |
2065 return NGX_DECLINED; | 2129 return NGX_DECLINED; |
2066 } | 2130 } |
2067 | 2131 |
2068 if (ngx_quic_new_dcid(c, qc, &pkt->dcid) != NGX_OK) { | 2132 qc->odcid.len = pkt->dcid.len; |
2133 qc->odcid.data = ngx_pstrdup(c->pool, &pkt->dcid); | |
2134 if (qc->odcid.data == NULL) { | |
2135 return NGX_ERROR; | |
2136 } | |
2137 | |
2138 ngx_quic_clear_temp_server_ids(c); | |
2139 | |
2140 if (ngx_quic_create_server_id(c, qc->dcid.data) != NGX_OK) { | |
2141 return NGX_ERROR; | |
2142 } | |
2143 | |
2144 qc->server_seqnum = 0; | |
2145 | |
2146 if (ngx_quic_insert_server_id(c, &qc->dcid) == NULL) { | |
2069 return NGX_ERROR; | 2147 return NGX_ERROR; |
2070 } | 2148 } |
2071 | 2149 |
2072 qc->tp.initial_scid = qc->dcid; | 2150 qc->tp.initial_scid = qc->dcid; |
2073 qc->in_retry = 0; | 2151 qc->in_retry = 0; |
2135 | 2213 |
2136 if (ngx_quic_init_secrets(c) != NGX_OK) { | 2214 if (ngx_quic_init_secrets(c) != NGX_OK) { |
2137 return NGX_ERROR; | 2215 return NGX_ERROR; |
2138 } | 2216 } |
2139 | 2217 |
2218 if (ngx_quic_insert_server_id(c, &qc->odcid) == NULL) { | |
2219 return NGX_ERROR; | |
2220 } | |
2221 | |
2222 qc->server_seqnum = 0; | |
2223 | |
2224 if (ngx_quic_insert_server_id(c, &qc->dcid) == NULL) { | |
2225 return NGX_ERROR; | |
2226 } | |
2227 | |
2140 } else if (pkt->level == ssl_encryption_application) { | 2228 } else if (pkt->level == ssl_encryption_application) { |
2141 return ngx_quic_send_stateless_reset(c, conf, pkt); | 2229 return ngx_quic_send_stateless_reset(c, conf, pkt); |
2142 | 2230 |
2143 } else { | 2231 } else { |
2144 return NGX_ERROR; | 2232 return NGX_ERROR; |
2268 f = ngx_queue_data(q, ngx_quic_frame_t, queue); | 2356 f = ngx_queue_data(q, ngx_quic_frame_t, queue); |
2269 ngx_quic_congestion_ack(c, f); | 2357 ngx_quic_congestion_ack(c, f); |
2270 ngx_quic_free_frame(c, f); | 2358 ngx_quic_free_frame(c, f); |
2271 } | 2359 } |
2272 | 2360 |
2361 if (level == ssl_encryption_initial) { | |
2362 ngx_quic_clear_temp_server_ids(c); | |
2363 } | |
2364 | |
2273 ctx->send_ack = 0; | 2365 ctx->send_ack = 0; |
2274 } | 2366 } |
2275 | 2367 |
2276 | 2368 |
2277 static ngx_int_t | 2369 static ngx_int_t |
2278 ngx_quic_check_peer(ngx_quic_connection_t *qc, ngx_quic_header_t *pkt) | 2370 ngx_quic_check_peer(ngx_quic_connection_t *qc, ngx_quic_header_t *pkt) |
2279 { | 2371 { |
2280 ngx_str_t *dcid; | |
2281 ngx_queue_t *q; | 2372 ngx_queue_t *q; |
2282 ngx_quic_send_ctx_t *ctx; | |
2283 ngx_quic_client_id_t *cid; | 2373 ngx_quic_client_id_t *cid; |
2284 | 2374 |
2285 dcid = (pkt->level == ssl_encryption_early_data) ? &qc->odcid : &qc->dcid; | 2375 if (pkt->level == ssl_encryption_application) { |
2286 | 2376 return NGX_OK; |
2287 if (pkt->dcid.len == dcid->len | 2377 } |
2288 && ngx_memcmp(pkt->dcid.data, dcid->data, dcid->len) == 0) | |
2289 { | |
2290 if (pkt->level == ssl_encryption_application) { | |
2291 return NGX_OK; | |
2292 } | |
2293 | |
2294 goto found; | |
2295 } | |
2296 | |
2297 /* | |
2298 * a packet sent in response to an initial client packet might be lost, | |
2299 * thus check also for old dcid | |
2300 */ | |
2301 ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_initial); | |
2302 | |
2303 if (pkt->level == ssl_encryption_initial | |
2304 && ctx->largest_ack == NGX_QUIC_UNSET_PN) | |
2305 { | |
2306 if (pkt->dcid.len == qc->odcid.len | |
2307 && ngx_memcmp(pkt->dcid.data, qc->odcid.data, qc->odcid.len) == 0) | |
2308 { | |
2309 goto found; | |
2310 } | |
2311 } | |
2312 | |
2313 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, "quic unexpected quic dcid"); | |
2314 return NGX_ERROR; | |
2315 | |
2316 found: | |
2317 | 2378 |
2318 for (q = ngx_queue_head(&qc->client_ids); | 2379 for (q = ngx_queue_head(&qc->client_ids); |
2319 q != ngx_queue_sentinel(&qc->client_ids); | 2380 q != ngx_queue_sentinel(&qc->client_ids); |
2320 q = ngx_queue_next(q)) | 2381 q = ngx_queue_next(q)) |
2321 { | 2382 { |
2531 } | 2592 } |
2532 | 2593 |
2533 break; | 2594 break; |
2534 | 2595 |
2535 case NGX_QUIC_FT_RETIRE_CONNECTION_ID: | 2596 case NGX_QUIC_FT_RETIRE_CONNECTION_ID: |
2597 | |
2598 if (ngx_quic_handle_retire_connection_id_frame(c, pkt, | |
2599 &frame.u.retire_cid) | |
2600 != NGX_OK) | |
2601 { | |
2602 return NGX_ERROR; | |
2603 } | |
2604 | |
2605 break; | |
2606 | |
2536 case NGX_QUIC_FT_PATH_RESPONSE: | 2607 case NGX_QUIC_FT_PATH_RESPONSE: |
2537 | 2608 |
2538 /* TODO: handle */ | 2609 /* TODO: handle */ |
2539 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, | 2610 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, |
2540 "quic frame handler not implemented"); | 2611 "quic frame handler not implemented"); |
3635 /* | 3706 /* |
3636 * 4.10.2 An endpoint MUST discard its handshake keys | 3707 * 4.10.2 An endpoint MUST discard its handshake keys |
3637 * when the TLS handshake is confirmed | 3708 * when the TLS handshake is confirmed |
3638 */ | 3709 */ |
3639 ngx_quic_discard_ctx(c, ssl_encryption_handshake); | 3710 ngx_quic_discard_ctx(c, ssl_encryption_handshake); |
3711 | |
3712 if (ngx_quic_issue_server_ids(c) != NGX_OK) { | |
3713 return NGX_ERROR; | |
3714 } | |
3640 | 3715 |
3641 return NGX_OK; | 3716 return NGX_OK; |
3642 } | 3717 } |
3643 | 3718 |
3644 | 3719 |
4263 | 4338 |
4264 return NGX_OK; | 4339 return NGX_OK; |
4265 } | 4340 } |
4266 | 4341 |
4267 | 4342 |
4343 static ngx_int_t | |
4344 ngx_quic_handle_retire_connection_id_frame(ngx_connection_t *c, | |
4345 ngx_quic_header_t *pkt, ngx_quic_retire_cid_frame_t *f) | |
4346 { | |
4347 ngx_queue_t *q; | |
4348 ngx_quic_server_id_t *sid; | |
4349 ngx_quic_connection_t *qc; | |
4350 | |
4351 qc = c->quic; | |
4352 | |
4353 for (q = ngx_queue_head(&qc->server_ids); | |
4354 q != ngx_queue_sentinel(&qc->server_ids); | |
4355 q = ngx_queue_next(q)) | |
4356 { | |
4357 sid = ngx_queue_data(q, ngx_quic_server_id_t, queue); | |
4358 | |
4359 if (sid->seqnum == f->sequence_number) { | |
4360 ngx_queue_remove(q); | |
4361 ngx_rbtree_delete(&c->listening->rbtree, &sid->udp.node); | |
4362 qc->nserver_ids--; | |
4363 | |
4364 if (c->udp != &sid->udp) { | |
4365 ngx_queue_insert_tail(&qc->free_server_ids, &sid->queue); | |
4366 } | |
4367 | |
4368 break; | |
4369 } | |
4370 } | |
4371 | |
4372 return ngx_quic_issue_server_ids(c); | |
4373 } | |
4374 | |
4375 | |
4376 static ngx_int_t | |
4377 ngx_quic_issue_server_ids(ngx_connection_t *c) | |
4378 { | |
4379 ngx_str_t dcid; | |
4380 ngx_uint_t n; | |
4381 ngx_quic_frame_t *frame; | |
4382 ngx_quic_server_id_t *sid; | |
4383 ngx_quic_connection_t *qc; | |
4384 u_char id[NGX_QUIC_SERVER_CID_LEN]; | |
4385 | |
4386 qc = c->quic; | |
4387 | |
4388 n = ngx_min(NGX_QUIC_MAX_SERVER_IDS, qc->ctp.active_connection_id_limit); | |
4389 | |
4390 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
4391 "quic issue server ids has:%ui max:%ui", qc->nserver_ids, n); | |
4392 | |
4393 while (qc->nserver_ids < n) { | |
4394 if (ngx_quic_create_server_id(c, id) != NGX_OK) { | |
4395 return NGX_ERROR; | |
4396 } | |
4397 | |
4398 dcid.len = NGX_QUIC_SERVER_CID_LEN; | |
4399 dcid.data = id; | |
4400 | |
4401 sid = ngx_quic_insert_server_id(c, &dcid); | |
4402 if (sid == NULL) { | |
4403 return NGX_ERROR; | |
4404 } | |
4405 | |
4406 frame = ngx_quic_alloc_frame(c, 0); | |
4407 if (frame == NULL) { | |
4408 return NGX_ERROR; | |
4409 } | |
4410 | |
4411 frame->level = ssl_encryption_application; | |
4412 frame->type = NGX_QUIC_FT_NEW_CONNECTION_ID; | |
4413 frame->u.ncid.seqnum = sid->seqnum; | |
4414 frame->u.ncid.retire = 0; | |
4415 frame->u.ncid.len = NGX_QUIC_SERVER_CID_LEN; | |
4416 ngx_memcpy(frame->u.ncid.cid, id, NGX_QUIC_SERVER_CID_LEN); | |
4417 | |
4418 if (ngx_quic_new_sr_token(c, &dcid, &qc->conf->sr_token_key, | |
4419 frame->u.ncid.srt) | |
4420 != NGX_OK) | |
4421 { | |
4422 return NGX_ERROR; | |
4423 } | |
4424 | |
4425 ngx_quic_queue_frame(c->quic, frame); | |
4426 } | |
4427 | |
4428 return NGX_OK; | |
4429 } | |
4430 | |
4431 | |
4432 static void | |
4433 ngx_quic_clear_temp_server_ids(ngx_connection_t *c) | |
4434 { | |
4435 ngx_queue_t *q, *next; | |
4436 ngx_quic_server_id_t *sid; | |
4437 ngx_quic_connection_t *qc; | |
4438 | |
4439 qc = c->quic; | |
4440 | |
4441 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
4442 "quic clear temp server ids"); | |
4443 | |
4444 for (q = ngx_queue_head(&qc->server_ids); | |
4445 q != ngx_queue_sentinel(&qc->server_ids); | |
4446 q = next) | |
4447 { | |
4448 next = ngx_queue_next(q); | |
4449 sid = ngx_queue_data(q, ngx_quic_server_id_t, queue); | |
4450 | |
4451 if (sid->seqnum != NGX_QUIC_UNSET_PN) { | |
4452 continue; | |
4453 } | |
4454 | |
4455 ngx_queue_remove(q); | |
4456 ngx_rbtree_delete(&c->listening->rbtree, &sid->udp.node); | |
4457 qc->nserver_ids--; | |
4458 | |
4459 if (c->udp != &sid->udp) { | |
4460 ngx_queue_insert_tail(&qc->free_server_ids, &sid->queue); | |
4461 } | |
4462 } | |
4463 } | |
4464 | |
4465 | |
4466 static ngx_quic_server_id_t * | |
4467 ngx_quic_insert_server_id(ngx_connection_t *c, ngx_str_t *id) | |
4468 { | |
4469 ngx_str_t dcid; | |
4470 ngx_quic_server_id_t *sid; | |
4471 ngx_quic_connection_t *qc; | |
4472 | |
4473 qc = c->quic; | |
4474 | |
4475 sid = ngx_quic_alloc_server_id(c, qc); | |
4476 if (sid == NULL) { | |
4477 return NULL; | |
4478 } | |
4479 | |
4480 sid->seqnum = qc->server_seqnum; | |
4481 | |
4482 if (qc->server_seqnum != NGX_QUIC_UNSET_PN) { | |
4483 qc->server_seqnum++; | |
4484 } | |
4485 | |
4486 sid->len = id->len; | |
4487 ngx_memcpy(sid->id, id->data, id->len); | |
4488 | |
4489 ngx_queue_insert_tail(&qc->server_ids, &sid->queue); | |
4490 qc->nserver_ids++; | |
4491 | |
4492 dcid.data = sid->id; | |
4493 dcid.len = sid->len; | |
4494 | |
4495 ngx_insert_udp_connection(c, &sid->udp, &dcid); | |
4496 | |
4497 if (c->udp == NULL) { | |
4498 c->udp = &sid->udp; | |
4499 } | |
4500 | |
4501 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
4502 "quic insert server id seqnum:%uL", sid->seqnum); | |
4503 | |
4504 ngx_quic_hexdump(c->log, "quic server id", id->data, id->len); | |
4505 | |
4506 return sid; | |
4507 } | |
4508 | |
4509 | |
4268 static ngx_quic_client_id_t * | 4510 static ngx_quic_client_id_t * |
4269 ngx_quic_alloc_client_id(ngx_connection_t *c, ngx_quic_connection_t *qc) | 4511 ngx_quic_alloc_client_id(ngx_connection_t *c, ngx_quic_connection_t *qc) |
4270 { | 4512 { |
4271 ngx_queue_t *q; | 4513 ngx_queue_t *q; |
4272 ngx_quic_client_id_t *cid; | 4514 ngx_quic_client_id_t *cid; |
4287 return NULL; | 4529 return NULL; |
4288 } | 4530 } |
4289 } | 4531 } |
4290 | 4532 |
4291 return cid; | 4533 return cid; |
4534 } | |
4535 | |
4536 | |
4537 static ngx_quic_server_id_t * | |
4538 ngx_quic_alloc_server_id(ngx_connection_t *c, ngx_quic_connection_t *qc) | |
4539 { | |
4540 ngx_queue_t *q; | |
4541 ngx_quic_server_id_t *sid; | |
4542 | |
4543 if (!ngx_queue_empty(&qc->free_server_ids)) { | |
4544 | |
4545 q = ngx_queue_head(&qc->free_server_ids); | |
4546 sid = ngx_queue_data(q, ngx_quic_server_id_t, queue); | |
4547 | |
4548 ngx_queue_remove(&sid->queue); | |
4549 | |
4550 ngx_memzero(sid, sizeof(ngx_quic_server_id_t)); | |
4551 | |
4552 } else { | |
4553 | |
4554 sid = ngx_pcalloc(c->pool, sizeof(ngx_quic_server_id_t)); | |
4555 if (sid == NULL) { | |
4556 return NULL; | |
4557 } | |
4558 } | |
4559 | |
4560 return sid; | |
4292 } | 4561 } |
4293 | 4562 |
4294 | 4563 |
4295 static void | 4564 static void |
4296 ngx_quic_queue_frame(ngx_quic_connection_t *qc, ngx_quic_frame_t *frame) | 4565 ngx_quic_queue_frame(ngx_quic_connection_t *qc, ngx_quic_frame_t *frame) |