Mercurial > hg > nginx
comparison src/event/quic/ngx_event_quic.c @ 8748:e0cb1e58ca13 quic
QUIC: separate files for connection id related processing.
author | Vladimir Homutov <vl@nginx.com> |
---|---|
date | Tue, 13 Apr 2021 14:37:41 +0300 |
parents | c8bda5e1e662 |
children | 660c4a2f95f3 |
comparison
equal
deleted
inserted
replaced
8747:c8bda5e1e662 | 8748:e0cb1e58ca13 |
---|---|
20 * Implementations MUST support buffering at least 4096 bytes of data | 20 * Implementations MUST support buffering at least 4096 bytes of data |
21 */ | 21 */ |
22 #define NGX_QUIC_MAX_BUFFERED 65535 | 22 #define NGX_QUIC_MAX_BUFFERED 65535 |
23 | 23 |
24 #define NGX_QUIC_STREAM_GONE (void *) -1 | 24 #define NGX_QUIC_STREAM_GONE (void *) -1 |
25 | |
26 #define NGX_QUIC_UNSET_PN (uint64_t) -1 | |
27 | 25 |
28 /* | 26 /* |
29 * Endpoints MUST discard packets that are too small to be valid QUIC | 27 * Endpoints MUST discard packets that are too small to be valid QUIC |
30 * packets. With the set of AEAD functions defined in [QUIC-TLS], | 28 * packets. With the set of AEAD functions defined in [QUIC-TLS], |
31 * packets that are smaller than 21 bytes are never valid. | 29 * packets that are smaller than 21 bytes are never valid. |
64 | 62 |
65 static ngx_int_t ngx_quic_apply_transport_params(ngx_connection_t *c, | 63 static ngx_int_t ngx_quic_apply_transport_params(ngx_connection_t *c, |
66 ngx_quic_tp_t *ctp); | 64 ngx_quic_tp_t *ctp); |
67 static ngx_quic_connection_t *ngx_quic_new_connection(ngx_connection_t *c, | 65 static ngx_quic_connection_t *ngx_quic_new_connection(ngx_connection_t *c, |
68 ngx_quic_conf_t *conf, ngx_quic_header_t *pkt); | 66 ngx_quic_conf_t *conf, ngx_quic_header_t *pkt); |
69 static ngx_int_t ngx_quic_setup_connection_ids(ngx_connection_t *c, | |
70 ngx_quic_connection_t *qc, ngx_quic_header_t *pkt); | |
71 static ngx_int_t ngx_quic_send_stateless_reset(ngx_connection_t *c, | 67 static ngx_int_t ngx_quic_send_stateless_reset(ngx_connection_t *c, |
72 ngx_quic_conf_t *conf, ngx_quic_header_t *pkt); | 68 ngx_quic_conf_t *conf, ngx_quic_header_t *pkt); |
73 static ngx_int_t ngx_quic_new_sr_token(ngx_connection_t *c, ngx_str_t *cid, | |
74 u_char *secret, u_char *token); | |
75 static ngx_int_t ngx_quic_process_stateless_reset(ngx_connection_t *c, | 69 static ngx_int_t ngx_quic_process_stateless_reset(ngx_connection_t *c, |
76 ngx_quic_header_t *pkt); | 70 ngx_quic_header_t *pkt); |
77 static ngx_int_t ngx_quic_negotiate_version(ngx_connection_t *c, | 71 static ngx_int_t ngx_quic_negotiate_version(ngx_connection_t *c, |
78 ngx_quic_header_t *inpkt); | 72 ngx_quic_header_t *inpkt); |
79 static ngx_int_t ngx_quic_create_server_id(ngx_connection_t *c, u_char *id); | |
80 #if (NGX_QUIC_BPF) | |
81 static ngx_int_t ngx_quic_bpf_attach_id(ngx_connection_t *c, u_char *id); | |
82 #endif | |
83 static ngx_int_t ngx_quic_send_retry(ngx_connection_t *c, | 73 static ngx_int_t ngx_quic_send_retry(ngx_connection_t *c, |
84 ngx_quic_conf_t *conf, ngx_quic_header_t *pkt); | 74 ngx_quic_conf_t *conf, ngx_quic_header_t *pkt); |
85 static ngx_int_t ngx_quic_new_token(ngx_connection_t *c, u_char *key, | 75 static ngx_int_t ngx_quic_new_token(ngx_connection_t *c, u_char *key, |
86 ngx_str_t *token, ngx_str_t *odcid, time_t expires, ngx_uint_t is_retry); | 76 ngx_str_t *token, ngx_str_t *odcid, time_t expires, ngx_uint_t is_retry); |
87 static void ngx_quic_address_hash(ngx_connection_t *c, ngx_uint_t no_port, | 77 static void ngx_quic_address_hash(ngx_connection_t *c, ngx_uint_t no_port, |
161 ngx_quic_header_t *pkt, ngx_quic_reset_stream_frame_t *f); | 151 ngx_quic_header_t *pkt, ngx_quic_reset_stream_frame_t *f); |
162 static ngx_int_t ngx_quic_handle_stop_sending_frame(ngx_connection_t *c, | 152 static ngx_int_t ngx_quic_handle_stop_sending_frame(ngx_connection_t *c, |
163 ngx_quic_header_t *pkt, ngx_quic_stop_sending_frame_t *f); | 153 ngx_quic_header_t *pkt, ngx_quic_stop_sending_frame_t *f); |
164 static ngx_int_t ngx_quic_handle_max_streams_frame(ngx_connection_t *c, | 154 static ngx_int_t ngx_quic_handle_max_streams_frame(ngx_connection_t *c, |
165 ngx_quic_header_t *pkt, ngx_quic_max_streams_frame_t *f); | 155 ngx_quic_header_t *pkt, ngx_quic_max_streams_frame_t *f); |
166 static ngx_int_t ngx_quic_handle_new_connection_id_frame(ngx_connection_t *c, | |
167 ngx_quic_header_t *pkt, ngx_quic_new_conn_id_frame_t *f); | |
168 static ngx_int_t ngx_quic_retire_connection_id(ngx_connection_t *c, | |
169 enum ssl_encryption_level_t level, uint64_t seqnum); | |
170 static ngx_int_t ngx_quic_handle_retire_connection_id_frame(ngx_connection_t *c, | |
171 ngx_quic_header_t *pkt, ngx_quic_retire_cid_frame_t *f); | |
172 static ngx_int_t ngx_quic_issue_server_ids(ngx_connection_t *c); | |
173 static void ngx_quic_clear_temp_server_ids(ngx_connection_t *c); | |
174 static ngx_quic_server_id_t *ngx_quic_insert_server_id(ngx_connection_t *c, | |
175 ngx_quic_connection_t *qc, ngx_str_t *id); | |
176 static ngx_quic_client_id_t *ngx_quic_alloc_client_id(ngx_connection_t *c, | |
177 ngx_quic_connection_t *qc); | |
178 static ngx_quic_server_id_t *ngx_quic_alloc_server_id(ngx_connection_t *c, | |
179 ngx_quic_connection_t *qc); | |
180 | 156 |
181 static ngx_int_t ngx_quic_output(ngx_connection_t *c); | 157 static ngx_int_t ngx_quic_output(ngx_connection_t *c); |
182 static ngx_uint_t ngx_quic_get_padding_level(ngx_connection_t *c); | 158 static ngx_uint_t ngx_quic_get_padding_level(ngx_connection_t *c); |
183 static ngx_int_t ngx_quic_generate_ack(ngx_connection_t *c, | 159 static ngx_int_t ngx_quic_generate_ack(ngx_connection_t *c, |
184 ngx_quic_send_ctx_t *ctx); | 160 ngx_quic_send_ctx_t *ctx); |
1034 return qc; | 1010 return qc; |
1035 } | 1011 } |
1036 | 1012 |
1037 | 1013 |
1038 static ngx_int_t | 1014 static ngx_int_t |
1039 ngx_quic_setup_connection_ids(ngx_connection_t *c, ngx_quic_connection_t *qc, | |
1040 ngx_quic_header_t *pkt) | |
1041 { | |
1042 ngx_quic_server_id_t *sid, *osid; | |
1043 ngx_quic_client_id_t *cid; | |
1044 | |
1045 /* | |
1046 * qc->nclient_ids = 0 | |
1047 * qc->nserver_ids = 0 | |
1048 * qc->max_retired_seqnum = 0 | |
1049 */ | |
1050 | |
1051 ngx_queue_init(&qc->client_ids); | |
1052 ngx_queue_init(&qc->server_ids); | |
1053 ngx_queue_init(&qc->free_client_ids); | |
1054 ngx_queue_init(&qc->free_server_ids); | |
1055 | |
1056 qc->odcid.len = pkt->odcid.len; | |
1057 qc->odcid.data = ngx_pstrdup(c->pool, &pkt->odcid); | |
1058 if (qc->odcid.data == NULL) { | |
1059 return NGX_ERROR; | |
1060 } | |
1061 | |
1062 qc->tp.original_dcid = qc->odcid; | |
1063 | |
1064 qc->scid.len = pkt->scid.len; | |
1065 qc->scid.data = ngx_pstrdup(c->pool, &pkt->scid); | |
1066 if (qc->scid.data == NULL) { | |
1067 return NGX_ERROR; | |
1068 } | |
1069 | |
1070 qc->dcid.len = NGX_QUIC_SERVER_CID_LEN; | |
1071 qc->dcid.data = ngx_pnalloc(c->pool, qc->dcid.len); | |
1072 if (qc->dcid.data == NULL) { | |
1073 return NGX_ERROR; | |
1074 } | |
1075 | |
1076 if (ngx_quic_create_server_id(c, qc->dcid.data) != NGX_OK) { | |
1077 return NGX_ERROR; | |
1078 } | |
1079 | |
1080 qc->tp.initial_scid = qc->dcid; | |
1081 | |
1082 cid = ngx_quic_alloc_client_id(c, qc); | |
1083 if (cid == NULL) { | |
1084 return NGX_ERROR; | |
1085 } | |
1086 | |
1087 cid->seqnum = 0; | |
1088 cid->len = pkt->scid.len; | |
1089 ngx_memcpy(cid->id, pkt->scid.data, pkt->scid.len); | |
1090 | |
1091 ngx_queue_insert_tail(&qc->client_ids, &cid->queue); | |
1092 qc->nclient_ids++; | |
1093 qc->client_seqnum = 0; | |
1094 | |
1095 qc->server_seqnum = NGX_QUIC_UNSET_PN; | |
1096 | |
1097 osid = ngx_quic_insert_server_id(c, qc, &qc->odcid); | |
1098 if (osid == NULL) { | |
1099 return NGX_ERROR; | |
1100 } | |
1101 | |
1102 qc->server_seqnum = 0; | |
1103 | |
1104 sid = ngx_quic_insert_server_id(c, qc, &qc->dcid); | |
1105 if (sid == NULL) { | |
1106 ngx_rbtree_delete(&c->listening->rbtree, &osid->udp.node); | |
1107 return NGX_ERROR; | |
1108 } | |
1109 | |
1110 c->udp = &sid->udp; | |
1111 | |
1112 return NGX_OK; | |
1113 } | |
1114 | |
1115 | |
1116 static ngx_int_t | |
1117 ngx_quic_send_stateless_reset(ngx_connection_t *c, ngx_quic_conf_t *conf, | 1015 ngx_quic_send_stateless_reset(ngx_connection_t *c, ngx_quic_conf_t *conf, |
1118 ngx_quic_header_t *pkt) | 1016 ngx_quic_header_t *pkt) |
1119 { | 1017 { |
1120 u_char *token; | 1018 u_char *token; |
1121 size_t len, max; | 1019 size_t len, max; |
1162 | 1060 |
1163 return NGX_DECLINED; | 1061 return NGX_DECLINED; |
1164 } | 1062 } |
1165 | 1063 |
1166 | 1064 |
1167 static ngx_int_t | 1065 ngx_int_t |
1168 ngx_quic_new_sr_token(ngx_connection_t *c, ngx_str_t *cid, u_char *secret, | 1066 ngx_quic_new_sr_token(ngx_connection_t *c, ngx_str_t *cid, u_char *secret, |
1169 u_char *token) | 1067 u_char *token) |
1170 { | 1068 { |
1171 ngx_str_t tmp; | 1069 ngx_str_t tmp; |
1172 | 1070 |
1258 | 1156 |
1259 (void) ngx_quic_send(c, buf, len); | 1157 (void) ngx_quic_send(c, buf, len); |
1260 | 1158 |
1261 return NGX_ERROR; | 1159 return NGX_ERROR; |
1262 } | 1160 } |
1263 | |
1264 | |
1265 static ngx_int_t | |
1266 ngx_quic_create_server_id(ngx_connection_t *c, u_char *id) | |
1267 { | |
1268 if (RAND_bytes(id, NGX_QUIC_SERVER_CID_LEN) != 1) { | |
1269 return NGX_ERROR; | |
1270 } | |
1271 | |
1272 #if (NGX_QUIC_BPF) | |
1273 if (ngx_quic_bpf_attach_id(c, id) != NGX_OK) { | |
1274 ngx_log_error(NGX_LOG_ERR, c->log, 0, | |
1275 "quic bpf failed to generate socket key"); | |
1276 /* ignore error, things still may work */ | |
1277 } | |
1278 #endif | |
1279 | |
1280 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
1281 "quic create server id %*xs", | |
1282 (size_t) NGX_QUIC_SERVER_CID_LEN, id); | |
1283 return NGX_OK; | |
1284 } | |
1285 | |
1286 | |
1287 #if (NGX_QUIC_BPF) | |
1288 | |
1289 static ngx_int_t | |
1290 ngx_quic_bpf_attach_id(ngx_connection_t *c, u_char *id) | |
1291 { | |
1292 int fd; | |
1293 uint64_t cookie; | |
1294 socklen_t optlen; | |
1295 | |
1296 fd = c->listening->fd; | |
1297 | |
1298 optlen = sizeof(cookie); | |
1299 | |
1300 if (getsockopt(fd, SOL_SOCKET, SO_COOKIE, &cookie, &optlen) == -1) { | |
1301 ngx_log_error(NGX_LOG_ERR, c->log, ngx_socket_errno, | |
1302 "quic getsockopt(SO_COOKIE) failed"); | |
1303 | |
1304 return NGX_ERROR; | |
1305 } | |
1306 | |
1307 ngx_quic_dcid_encode_key(id, cookie); | |
1308 | |
1309 return NGX_OK; | |
1310 } | |
1311 | |
1312 #endif | |
1313 | 1161 |
1314 | 1162 |
1315 static ngx_int_t | 1163 static ngx_int_t |
1316 ngx_quic_send_retry(ngx_connection_t *c, ngx_quic_conf_t *conf, | 1164 ngx_quic_send_retry(ngx_connection_t *c, ngx_quic_conf_t *conf, |
1317 ngx_quic_header_t *inpkt) | 1165 ngx_quic_header_t *inpkt) |
4388 | 4236 |
4389 return NGX_OK; | 4237 return NGX_OK; |
4390 } | 4238 } |
4391 | 4239 |
4392 | 4240 |
4393 static ngx_int_t | |
4394 ngx_quic_handle_new_connection_id_frame(ngx_connection_t *c, | |
4395 ngx_quic_header_t *pkt, ngx_quic_new_conn_id_frame_t *f) | |
4396 { | |
4397 ngx_queue_t *q; | |
4398 ngx_quic_client_id_t *cid, *item; | |
4399 ngx_quic_connection_t *qc; | |
4400 | |
4401 qc = ngx_quic_get_connection(c); | |
4402 | |
4403 if (f->seqnum < qc->max_retired_seqnum) { | |
4404 /* | |
4405 * An endpoint that receives a NEW_CONNECTION_ID frame with | |
4406 * a sequence number smaller than the Retire Prior To field | |
4407 * of a previously received NEW_CONNECTION_ID frame MUST send | |
4408 * a corresponding RETIRE_CONNECTION_ID frame that retires | |
4409 * the newly received connection ID, unless it has already | |
4410 * done so for that sequence number. | |
4411 */ | |
4412 | |
4413 if (ngx_quic_retire_connection_id(c, pkt->level, f->seqnum) != NGX_OK) { | |
4414 return NGX_ERROR; | |
4415 } | |
4416 | |
4417 goto retire; | |
4418 } | |
4419 | |
4420 cid = NULL; | |
4421 | |
4422 for (q = ngx_queue_head(&qc->client_ids); | |
4423 q != ngx_queue_sentinel(&qc->client_ids); | |
4424 q = ngx_queue_next(q)) | |
4425 { | |
4426 item = ngx_queue_data(q, ngx_quic_client_id_t, queue); | |
4427 | |
4428 if (item->seqnum == f->seqnum) { | |
4429 cid = item; | |
4430 break; | |
4431 } | |
4432 } | |
4433 | |
4434 if (cid) { | |
4435 /* | |
4436 * Transmission errors, timeouts and retransmissions might cause the | |
4437 * same NEW_CONNECTION_ID frame to be received multiple times | |
4438 */ | |
4439 | |
4440 if (cid->len != f->len | |
4441 || ngx_strncmp(cid->id, f->cid, f->len) != 0 | |
4442 || ngx_strncmp(cid->sr_token, f->srt, NGX_QUIC_SR_TOKEN_LEN) != 0) | |
4443 { | |
4444 /* | |
4445 * ..a sequence number is used for different connection IDs, | |
4446 * the endpoint MAY treat that receipt as a connection error | |
4447 * of type PROTOCOL_VIOLATION. | |
4448 */ | |
4449 qc->error = NGX_QUIC_ERR_PROTOCOL_VIOLATION; | |
4450 qc->error_reason = "seqnum refers to different connection id/token"; | |
4451 return NGX_ERROR; | |
4452 } | |
4453 | |
4454 } else { | |
4455 | |
4456 cid = ngx_quic_alloc_client_id(c, qc); | |
4457 if (cid == NULL) { | |
4458 return NGX_ERROR; | |
4459 } | |
4460 | |
4461 cid->seqnum = f->seqnum; | |
4462 cid->len = f->len; | |
4463 ngx_memcpy(cid->id, f->cid, f->len); | |
4464 | |
4465 ngx_memcpy(cid->sr_token, f->srt, NGX_QUIC_SR_TOKEN_LEN); | |
4466 | |
4467 ngx_queue_insert_tail(&qc->client_ids, &cid->queue); | |
4468 qc->nclient_ids++; | |
4469 | |
4470 /* always use latest available connection id */ | |
4471 if (f->seqnum > qc->client_seqnum) { | |
4472 qc->scid.len = cid->len; | |
4473 qc->scid.data = cid->id; | |
4474 qc->client_seqnum = f->seqnum; | |
4475 } | |
4476 } | |
4477 | |
4478 retire: | |
4479 | |
4480 if (qc->max_retired_seqnum && f->retire <= qc->max_retired_seqnum) { | |
4481 /* | |
4482 * Once a sender indicates a Retire Prior To value, smaller values sent | |
4483 * in subsequent NEW_CONNECTION_ID frames have no effect. A receiver | |
4484 * MUST ignore any Retire Prior To fields that do not increase the | |
4485 * largest received Retire Prior To value. | |
4486 */ | |
4487 goto done; | |
4488 } | |
4489 | |
4490 qc->max_retired_seqnum = f->retire; | |
4491 | |
4492 q = ngx_queue_head(&qc->client_ids); | |
4493 | |
4494 while (q != ngx_queue_sentinel(&qc->client_ids)) { | |
4495 | |
4496 cid = ngx_queue_data(q, ngx_quic_client_id_t, queue); | |
4497 q = ngx_queue_next(q); | |
4498 | |
4499 if (cid->seqnum >= f->retire) { | |
4500 continue; | |
4501 } | |
4502 | |
4503 /* this connection id must be retired */ | |
4504 | |
4505 if (ngx_quic_retire_connection_id(c, pkt->level, cid->seqnum) | |
4506 != NGX_OK) | |
4507 { | |
4508 return NGX_ERROR; | |
4509 } | |
4510 | |
4511 ngx_queue_remove(&cid->queue); | |
4512 ngx_queue_insert_head(&qc->free_client_ids, &cid->queue); | |
4513 qc->nclient_ids--; | |
4514 } | |
4515 | |
4516 done: | |
4517 | |
4518 if (qc->nclient_ids > qc->tp.active_connection_id_limit) { | |
4519 /* | |
4520 * After processing a NEW_CONNECTION_ID frame and | |
4521 * adding and retiring active connection IDs, if the number of active | |
4522 * connection IDs exceeds the value advertised in its | |
4523 * active_connection_id_limit transport parameter, an endpoint MUST | |
4524 * close the connection with an error of type CONNECTION_ID_LIMIT_ERROR. | |
4525 */ | |
4526 qc->error = NGX_QUIC_ERR_CONNECTION_ID_LIMIT_ERROR; | |
4527 qc->error_reason = "too many connection ids received"; | |
4528 return NGX_ERROR; | |
4529 } | |
4530 | |
4531 return NGX_OK; | |
4532 } | |
4533 | |
4534 | |
4535 static ngx_int_t | |
4536 ngx_quic_retire_connection_id(ngx_connection_t *c, | |
4537 enum ssl_encryption_level_t level, uint64_t seqnum) | |
4538 { | |
4539 ngx_quic_frame_t *frame; | |
4540 ngx_quic_connection_t *qc; | |
4541 | |
4542 qc = ngx_quic_get_connection(c); | |
4543 | |
4544 frame = ngx_quic_alloc_frame(c); | |
4545 if (frame == NULL) { | |
4546 return NGX_ERROR; | |
4547 } | |
4548 | |
4549 frame->level = level; | |
4550 frame->type = NGX_QUIC_FT_RETIRE_CONNECTION_ID; | |
4551 frame->u.retire_cid.sequence_number = seqnum; | |
4552 | |
4553 ngx_quic_queue_frame(qc, frame); | |
4554 | |
4555 return NGX_OK; | |
4556 } | |
4557 | |
4558 | |
4559 static ngx_int_t | |
4560 ngx_quic_handle_retire_connection_id_frame(ngx_connection_t *c, | |
4561 ngx_quic_header_t *pkt, ngx_quic_retire_cid_frame_t *f) | |
4562 { | |
4563 ngx_queue_t *q; | |
4564 ngx_quic_server_id_t *sid; | |
4565 ngx_quic_connection_t *qc; | |
4566 | |
4567 qc = ngx_quic_get_connection(c); | |
4568 | |
4569 for (q = ngx_queue_head(&qc->server_ids); | |
4570 q != ngx_queue_sentinel(&qc->server_ids); | |
4571 q = ngx_queue_next(q)) | |
4572 { | |
4573 sid = ngx_queue_data(q, ngx_quic_server_id_t, queue); | |
4574 | |
4575 if (sid->seqnum == f->sequence_number) { | |
4576 ngx_queue_remove(q); | |
4577 ngx_queue_insert_tail(&qc->free_server_ids, &sid->queue); | |
4578 ngx_rbtree_delete(&c->listening->rbtree, &sid->udp.node); | |
4579 qc->nserver_ids--; | |
4580 break; | |
4581 } | |
4582 } | |
4583 | |
4584 return ngx_quic_issue_server_ids(c); | |
4585 } | |
4586 | |
4587 | |
4588 static ngx_int_t | |
4589 ngx_quic_issue_server_ids(ngx_connection_t *c) | |
4590 { | |
4591 ngx_str_t dcid; | |
4592 ngx_uint_t n; | |
4593 ngx_quic_frame_t *frame; | |
4594 ngx_quic_server_id_t *sid; | |
4595 ngx_quic_connection_t *qc; | |
4596 u_char id[NGX_QUIC_SERVER_CID_LEN]; | |
4597 | |
4598 qc = ngx_quic_get_connection(c); | |
4599 | |
4600 n = ngx_min(NGX_QUIC_MAX_SERVER_IDS, qc->ctp.active_connection_id_limit); | |
4601 | |
4602 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
4603 "quic issue server ids has:%ui max:%ui", qc->nserver_ids, n); | |
4604 | |
4605 while (qc->nserver_ids < n) { | |
4606 if (ngx_quic_create_server_id(c, id) != NGX_OK) { | |
4607 return NGX_ERROR; | |
4608 } | |
4609 | |
4610 dcid.len = NGX_QUIC_SERVER_CID_LEN; | |
4611 dcid.data = id; | |
4612 | |
4613 sid = ngx_quic_insert_server_id(c, qc, &dcid); | |
4614 if (sid == NULL) { | |
4615 return NGX_ERROR; | |
4616 } | |
4617 | |
4618 frame = ngx_quic_alloc_frame(c); | |
4619 if (frame == NULL) { | |
4620 return NGX_ERROR; | |
4621 } | |
4622 | |
4623 frame->level = ssl_encryption_application; | |
4624 frame->type = NGX_QUIC_FT_NEW_CONNECTION_ID; | |
4625 frame->u.ncid.seqnum = sid->seqnum; | |
4626 frame->u.ncid.retire = 0; | |
4627 frame->u.ncid.len = NGX_QUIC_SERVER_CID_LEN; | |
4628 ngx_memcpy(frame->u.ncid.cid, id, NGX_QUIC_SERVER_CID_LEN); | |
4629 | |
4630 if (ngx_quic_new_sr_token(c, &dcid, qc->conf->sr_token_key, | |
4631 frame->u.ncid.srt) | |
4632 != NGX_OK) | |
4633 { | |
4634 return NGX_ERROR; | |
4635 } | |
4636 | |
4637 ngx_quic_queue_frame(qc, frame); | |
4638 } | |
4639 | |
4640 return NGX_OK; | |
4641 } | |
4642 | |
4643 | |
4644 static void | |
4645 ngx_quic_clear_temp_server_ids(ngx_connection_t *c) | |
4646 { | |
4647 ngx_queue_t *q, *next; | |
4648 ngx_quic_server_id_t *sid; | |
4649 ngx_quic_connection_t *qc; | |
4650 | |
4651 qc = ngx_quic_get_connection(c); | |
4652 | |
4653 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
4654 "quic clear temp server ids"); | |
4655 | |
4656 for (q = ngx_queue_head(&qc->server_ids); | |
4657 q != ngx_queue_sentinel(&qc->server_ids); | |
4658 q = next) | |
4659 { | |
4660 next = ngx_queue_next(q); | |
4661 sid = ngx_queue_data(q, ngx_quic_server_id_t, queue); | |
4662 | |
4663 if (sid->seqnum != NGX_QUIC_UNSET_PN) { | |
4664 continue; | |
4665 } | |
4666 | |
4667 ngx_queue_remove(q); | |
4668 ngx_queue_insert_tail(&qc->free_server_ids, &sid->queue); | |
4669 ngx_rbtree_delete(&c->listening->rbtree, &sid->udp.node); | |
4670 qc->nserver_ids--; | |
4671 } | |
4672 } | |
4673 | |
4674 | |
4675 static ngx_quic_server_id_t * | |
4676 ngx_quic_insert_server_id(ngx_connection_t *c, ngx_quic_connection_t *qc, | |
4677 ngx_str_t *id) | |
4678 { | |
4679 ngx_str_t dcid; | |
4680 ngx_quic_server_id_t *sid; | |
4681 | |
4682 sid = ngx_quic_alloc_server_id(c, qc); | |
4683 if (sid == NULL) { | |
4684 return NULL; | |
4685 } | |
4686 | |
4687 sid->quic = qc; | |
4688 | |
4689 sid->seqnum = qc->server_seqnum; | |
4690 | |
4691 if (qc->server_seqnum != NGX_QUIC_UNSET_PN) { | |
4692 qc->server_seqnum++; | |
4693 } | |
4694 | |
4695 sid->len = id->len; | |
4696 ngx_memcpy(sid->id, id->data, id->len); | |
4697 | |
4698 ngx_queue_insert_tail(&qc->server_ids, &sid->queue); | |
4699 qc->nserver_ids++; | |
4700 | |
4701 dcid.data = sid->id; | |
4702 dcid.len = sid->len; | |
4703 | |
4704 ngx_insert_udp_connection(c, &sid->udp, &dcid); | |
4705 | |
4706 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
4707 "quic insert server id seqnum:%uL id len:%uz %xV", | |
4708 sid->seqnum, id->len, id); | |
4709 | |
4710 return sid; | |
4711 } | |
4712 | |
4713 | |
4714 static ngx_quic_client_id_t * | |
4715 ngx_quic_alloc_client_id(ngx_connection_t *c, ngx_quic_connection_t *qc) | |
4716 { | |
4717 ngx_queue_t *q; | |
4718 ngx_quic_client_id_t *cid; | |
4719 | |
4720 if (!ngx_queue_empty(&qc->free_client_ids)) { | |
4721 | |
4722 q = ngx_queue_head(&qc->free_client_ids); | |
4723 cid = ngx_queue_data(q, ngx_quic_client_id_t, queue); | |
4724 | |
4725 ngx_queue_remove(&cid->queue); | |
4726 | |
4727 ngx_memzero(cid, sizeof(ngx_quic_client_id_t)); | |
4728 | |
4729 } else { | |
4730 | |
4731 cid = ngx_pcalloc(c->pool, sizeof(ngx_quic_client_id_t)); | |
4732 if (cid == NULL) { | |
4733 return NULL; | |
4734 } | |
4735 } | |
4736 | |
4737 return cid; | |
4738 } | |
4739 | |
4740 | |
4741 static ngx_quic_server_id_t * | |
4742 ngx_quic_alloc_server_id(ngx_connection_t *c, ngx_quic_connection_t *qc) | |
4743 { | |
4744 ngx_queue_t *q; | |
4745 ngx_quic_server_id_t *sid; | |
4746 | |
4747 if (!ngx_queue_empty(&qc->free_server_ids)) { | |
4748 | |
4749 q = ngx_queue_head(&qc->free_server_ids); | |
4750 sid = ngx_queue_data(q, ngx_quic_server_id_t, queue); | |
4751 | |
4752 ngx_queue_remove(&sid->queue); | |
4753 | |
4754 ngx_memzero(sid, sizeof(ngx_quic_server_id_t)); | |
4755 | |
4756 } else { | |
4757 | |
4758 sid = ngx_pcalloc(c->pool, sizeof(ngx_quic_server_id_t)); | |
4759 if (sid == NULL) { | |
4760 return NULL; | |
4761 } | |
4762 } | |
4763 | |
4764 return sid; | |
4765 } | |
4766 | |
4767 | |
4768 void | 4241 void |
4769 ngx_quic_queue_frame(ngx_quic_connection_t *qc, ngx_quic_frame_t *frame) | 4242 ngx_quic_queue_frame(ngx_quic_connection_t *qc, ngx_quic_frame_t *frame) |
4770 { | 4243 { |
4771 ngx_quic_send_ctx_t *ctx; | 4244 ngx_quic_send_ctx_t *ctx; |
4772 | 4245 |