comparison src/event/quic/ngx_event_quic_connid.c @ 8763:4117aa7fa38e quic

QUIC: connection migration. The patch adds proper transitions between multiple networking addresses that can be used by a single quic connection. New networking paths are validated using PATH_CHALLENGE/PATH_RESPONSE frames.
author Vladimir Homutov <vl@nginx.com>
date Thu, 29 Apr 2021 15:35:02 +0300
parents e0cb1e58ca13
children d5f93733c17d
comparison
equal deleted inserted replaced
8762:12f18e0bca09 8763:4117aa7fa38e
7 #include <ngx_config.h> 7 #include <ngx_config.h>
8 #include <ngx_core.h> 8 #include <ngx_core.h>
9 #include <ngx_event.h> 9 #include <ngx_event.h>
10 #include <ngx_event_quic_connection.h> 10 #include <ngx_event_quic_connection.h>
11 11
12
13 #define NGX_QUIC_MAX_SERVER_IDS 8 12 #define NGX_QUIC_MAX_SERVER_IDS 8
14 13
15 14
16 static ngx_int_t ngx_quic_create_server_id(ngx_connection_t *c, u_char *id);
17 #if (NGX_QUIC_BPF) 15 #if (NGX_QUIC_BPF)
18 static ngx_int_t ngx_quic_bpf_attach_id(ngx_connection_t *c, u_char *id); 16 static ngx_int_t ngx_quic_bpf_attach_id(ngx_connection_t *c, u_char *id);
19 #endif 17 #endif
20 static ngx_int_t ngx_quic_retire_connection_id(ngx_connection_t *c, 18 static ngx_int_t ngx_quic_send_retire_connection_id(ngx_connection_t *c,
21 enum ssl_encryption_level_t level, uint64_t seqnum); 19 enum ssl_encryption_level_t level, uint64_t seqnum);
22 static ngx_quic_server_id_t *ngx_quic_insert_server_id(ngx_connection_t *c, 20
23 ngx_quic_connection_t *qc, ngx_str_t *id);
24 static ngx_quic_client_id_t *ngx_quic_alloc_client_id(ngx_connection_t *c, 21 static ngx_quic_client_id_t *ngx_quic_alloc_client_id(ngx_connection_t *c,
25 ngx_quic_connection_t *qc); 22 ngx_quic_connection_t *qc);
26 static ngx_quic_server_id_t *ngx_quic_alloc_server_id(ngx_connection_t *c, 23 static ngx_int_t ngx_quic_replace_retired_client_id(ngx_connection_t *c,
27 ngx_quic_connection_t *qc); 24 ngx_quic_client_id_t *retired_cid);
25 static ngx_int_t ngx_quic_send_server_id(ngx_connection_t *c,
26 ngx_quic_server_id_t *sid);
28 27
29 28
30 ngx_int_t 29 ngx_int_t
31 ngx_quic_setup_connection_ids(ngx_connection_t *c, ngx_quic_connection_t *qc,
32 ngx_quic_header_t *pkt)
33 {
34 ngx_quic_server_id_t *sid, *osid;
35 ngx_quic_client_id_t *cid;
36
37 /*
38 * qc->nclient_ids = 0
39 * qc->nserver_ids = 0
40 * qc->max_retired_seqnum = 0
41 */
42
43 ngx_queue_init(&qc->client_ids);
44 ngx_queue_init(&qc->server_ids);
45 ngx_queue_init(&qc->free_client_ids);
46 ngx_queue_init(&qc->free_server_ids);
47
48 qc->odcid.len = pkt->odcid.len;
49 qc->odcid.data = ngx_pstrdup(c->pool, &pkt->odcid);
50 if (qc->odcid.data == NULL) {
51 return NGX_ERROR;
52 }
53
54 qc->tp.original_dcid = qc->odcid;
55
56 qc->scid.len = pkt->scid.len;
57 qc->scid.data = ngx_pstrdup(c->pool, &pkt->scid);
58 if (qc->scid.data == NULL) {
59 return NGX_ERROR;
60 }
61
62 qc->dcid.len = NGX_QUIC_SERVER_CID_LEN;
63 qc->dcid.data = ngx_pnalloc(c->pool, qc->dcid.len);
64 if (qc->dcid.data == NULL) {
65 return NGX_ERROR;
66 }
67
68 if (ngx_quic_create_server_id(c, qc->dcid.data) != NGX_OK) {
69 return NGX_ERROR;
70 }
71
72 qc->tp.initial_scid = qc->dcid;
73
74 cid = ngx_quic_alloc_client_id(c, qc);
75 if (cid == NULL) {
76 return NGX_ERROR;
77 }
78
79 cid->seqnum = 0;
80 cid->len = pkt->scid.len;
81 ngx_memcpy(cid->id, pkt->scid.data, pkt->scid.len);
82
83 ngx_queue_insert_tail(&qc->client_ids, &cid->queue);
84 qc->nclient_ids++;
85 qc->client_seqnum = 0;
86
87 qc->server_seqnum = NGX_QUIC_UNSET_PN;
88
89 osid = ngx_quic_insert_server_id(c, qc, &qc->odcid);
90 if (osid == NULL) {
91 return NGX_ERROR;
92 }
93
94 qc->server_seqnum = 0;
95
96 sid = ngx_quic_insert_server_id(c, qc, &qc->dcid);
97 if (sid == NULL) {
98 ngx_rbtree_delete(&c->listening->rbtree, &osid->udp.node);
99 return NGX_ERROR;
100 }
101
102 c->udp = &sid->udp;
103
104 return NGX_OK;
105 }
106
107
108 static ngx_int_t
109 ngx_quic_create_server_id(ngx_connection_t *c, u_char *id) 30 ngx_quic_create_server_id(ngx_connection_t *c, u_char *id)
110 { 31 {
111 if (RAND_bytes(id, NGX_QUIC_SERVER_CID_LEN) != 1) { 32 if (RAND_bytes(id, NGX_QUIC_SERVER_CID_LEN) != 1) {
112 return NGX_ERROR; 33 return NGX_ERROR;
113 } 34 }
118 "quic bpf failed to generate socket key"); 39 "quic bpf failed to generate socket key");
119 /* ignore error, things still may work */ 40 /* ignore error, things still may work */
120 } 41 }
121 #endif 42 #endif
122 43
123 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
124 "quic create server id %*xs",
125 (size_t) NGX_QUIC_SERVER_CID_LEN, id);
126 return NGX_OK; 44 return NGX_OK;
127 } 45 }
128 46
129 47
130 #if (NGX_QUIC_BPF) 48 #if (NGX_QUIC_BPF)
153 } 71 }
154 72
155 #endif 73 #endif
156 74
157 75
158
159
160 ngx_int_t 76 ngx_int_t
161 ngx_quic_handle_new_connection_id_frame(ngx_connection_t *c, 77 ngx_quic_handle_new_connection_id_frame(ngx_connection_t *c,
162 ngx_quic_header_t *pkt, ngx_quic_new_conn_id_frame_t *f) 78 ngx_quic_header_t *pkt, ngx_quic_new_conn_id_frame_t *f)
163 { 79 {
80 ngx_str_t id;
164 ngx_queue_t *q; 81 ngx_queue_t *q;
165 ngx_quic_client_id_t *cid, *item; 82 ngx_quic_client_id_t *cid, *item;
166 ngx_quic_connection_t *qc; 83 ngx_quic_connection_t *qc;
167 84
168 qc = ngx_quic_get_connection(c); 85 qc = ngx_quic_get_connection(c);
175 * a corresponding RETIRE_CONNECTION_ID frame that retires 92 * a corresponding RETIRE_CONNECTION_ID frame that retires
176 * the newly received connection ID, unless it has already 93 * the newly received connection ID, unless it has already
177 * done so for that sequence number. 94 * done so for that sequence number.
178 */ 95 */
179 96
180 if (ngx_quic_retire_connection_id(c, pkt->level, f->seqnum) != NGX_OK) { 97 if (ngx_quic_send_retire_connection_id(c, pkt->level, f->seqnum)
98 != NGX_OK)
99 {
181 return NGX_ERROR; 100 return NGX_ERROR;
182 } 101 }
183 102
184 goto retire; 103 goto retire;
185 } 104 }
218 return NGX_ERROR; 137 return NGX_ERROR;
219 } 138 }
220 139
221 } else { 140 } else {
222 141
223 cid = ngx_quic_alloc_client_id(c, qc); 142 id.data = f->cid;
224 if (cid == NULL) { 143 id.len = f->len;
225 return NGX_ERROR; 144
226 } 145 if (ngx_quic_create_client_id(c, &id, f->seqnum, f->srt) == NULL) {
227 146 return NGX_ERROR;
228 cid->seqnum = f->seqnum;
229 cid->len = f->len;
230 ngx_memcpy(cid->id, f->cid, f->len);
231
232 ngx_memcpy(cid->sr_token, f->srt, NGX_QUIC_SR_TOKEN_LEN);
233
234 ngx_queue_insert_tail(&qc->client_ids, &cid->queue);
235 qc->nclient_ids++;
236
237 /* always use latest available connection id */
238 if (f->seqnum > qc->client_seqnum) {
239 qc->scid.len = cid->len;
240 qc->scid.data = cid->id;
241 qc->client_seqnum = f->seqnum;
242 } 147 }
243 } 148 }
244 149
245 retire: 150 retire:
246 151
267 continue; 172 continue;
268 } 173 }
269 174
270 /* this connection id must be retired */ 175 /* this connection id must be retired */
271 176
272 if (ngx_quic_retire_connection_id(c, pkt->level, cid->seqnum) 177 if (ngx_quic_send_retire_connection_id(c, pkt->level, cid->seqnum)
273 != NGX_OK) 178 != NGX_OK)
274 { 179 {
275 return NGX_ERROR; 180 return NGX_ERROR;
276 } 181 }
277 182
278 ngx_queue_remove(&cid->queue); 183 if (cid->refcnt) {
279 ngx_queue_insert_head(&qc->free_client_ids, &cid->queue); 184 /* we are going to retire client id which is in use */
280 qc->nclient_ids--; 185 if (ngx_quic_replace_retired_client_id(c, cid) != NGX_OK) {
186 return NGX_ERROR;
187 }
188 }
189
190 ngx_quic_unref_client_id(c, cid);
281 } 191 }
282 192
283 done: 193 done:
284 194
285 if (qc->nclient_ids > qc->tp.active_connection_id_limit) { 195 if (qc->nclient_ids > qc->tp.active_connection_id_limit) {
298 return NGX_OK; 208 return NGX_OK;
299 } 209 }
300 210
301 211
302 static ngx_int_t 212 static ngx_int_t
303 ngx_quic_retire_connection_id(ngx_connection_t *c, 213 ngx_quic_send_retire_connection_id(ngx_connection_t *c,
304 enum ssl_encryption_level_t level, uint64_t seqnum) 214 enum ssl_encryption_level_t level, uint64_t seqnum)
305 { 215 {
306 ngx_quic_frame_t *frame; 216 ngx_quic_frame_t *frame;
307 ngx_quic_connection_t *qc; 217 ngx_quic_connection_t *qc;
308 218
317 frame->type = NGX_QUIC_FT_RETIRE_CONNECTION_ID; 227 frame->type = NGX_QUIC_FT_RETIRE_CONNECTION_ID;
318 frame->u.retire_cid.sequence_number = seqnum; 228 frame->u.retire_cid.sequence_number = seqnum;
319 229
320 ngx_quic_queue_frame(qc, frame); 230 ngx_quic_queue_frame(qc, frame);
321 231
322 return NGX_OK; 232 /* we are no longer going to use this client id */
233
234 return NGX_OK;
235 }
236
237
238 static ngx_quic_client_id_t *
239 ngx_quic_alloc_client_id(ngx_connection_t *c, ngx_quic_connection_t *qc)
240 {
241 ngx_queue_t *q;
242 ngx_quic_client_id_t *cid;
243
244 if (!ngx_queue_empty(&qc->free_client_ids)) {
245
246 q = ngx_queue_head(&qc->free_client_ids);
247 cid = ngx_queue_data(q, ngx_quic_client_id_t, queue);
248
249 ngx_queue_remove(&cid->queue);
250
251 ngx_memzero(cid, sizeof(ngx_quic_client_id_t));
252
253 } else {
254
255 cid = ngx_pcalloc(c->pool, sizeof(ngx_quic_client_id_t));
256 if (cid == NULL) {
257 return NULL;
258 }
259 }
260
261 return cid;
262 }
263
264
265 ngx_quic_client_id_t *
266 ngx_quic_create_client_id(ngx_connection_t *c, ngx_str_t *id,
267 uint64_t seqnum, u_char *token)
268 {
269 ngx_quic_client_id_t *cid;
270 ngx_quic_connection_t *qc;
271
272 qc = ngx_quic_get_connection(c);
273
274 cid = ngx_quic_alloc_client_id(c, qc);
275 if (cid == NULL) {
276 return NULL;
277 }
278
279 cid->seqnum = seqnum;
280
281 cid->len = id->len;
282 ngx_memcpy(cid->id, id->data, id->len);
283
284 if (token) {
285 ngx_memcpy(cid->sr_token, token, NGX_QUIC_SR_TOKEN_LEN);
286 }
287
288 ngx_queue_insert_tail(&qc->client_ids, &cid->queue);
289 qc->nclient_ids++;
290
291 if (seqnum > qc->client_seqnum) {
292 qc->client_seqnum = seqnum;
293 }
294
295 ngx_log_debug5(NGX_LOG_DEBUG_EVENT, c->log, 0,
296 "quic cid #%uL received id:%uz:%xV:%*xs",
297 cid->seqnum, id->len, id,
298 (size_t) NGX_QUIC_SR_TOKEN_LEN, cid->sr_token);
299
300 return cid;
301 }
302
303
304 ngx_quic_client_id_t *
305 ngx_quic_next_client_id(ngx_connection_t *c)
306 {
307 ngx_queue_t *q;
308 ngx_quic_client_id_t *cid;
309 ngx_quic_connection_t *qc;
310
311 qc = ngx_quic_get_connection(c);
312
313 for (q = ngx_queue_head(&qc->client_ids);
314 q != ngx_queue_sentinel(&qc->client_ids);
315 q = ngx_queue_next(q))
316 {
317 cid = ngx_queue_data(q, ngx_quic_client_id_t, queue);
318
319 if (cid->refcnt == 0) {
320 return cid;
321 }
322 }
323
324 return NULL;
323 } 325 }
324 326
325 327
326 ngx_int_t 328 ngx_int_t
327 ngx_quic_handle_retire_connection_id_frame(ngx_connection_t *c, 329 ngx_quic_handle_retire_connection_id_frame(ngx_connection_t *c,
328 ngx_quic_header_t *pkt, ngx_quic_retire_cid_frame_t *f) 330 ngx_quic_header_t *pkt, ngx_quic_retire_cid_frame_t *f)
329 { 331 {
332 ngx_quic_path_t *path;
333 ngx_quic_socket_t *qsock, **tmp;
334 ngx_quic_client_id_t *cid;
335 ngx_quic_connection_t *qc;
336
337 qc = ngx_quic_get_connection(c);
338
339 qsock = ngx_quic_find_socket(c, f->sequence_number);
340 if (qsock == NULL) {
341 return NGX_OK;
342 }
343
344 if (qsock->sid.seqnum == qc->socket->sid.seqnum) {
345 tmp = &qc->socket;
346
347 } else if (qc->backup && qsock->sid.seqnum == qc->backup->sid.seqnum) {
348 tmp = &qc->backup;
349
350 } else {
351 tmp = NULL;
352 }
353
354 if (ngx_quic_create_sockets(c) != NGX_OK) {
355 return NGX_ERROR;
356 }
357
358 if (tmp) {
359 /* replace socket in use (active or backup) */
360
361 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
362 "quic %s socket #%uL:%uL:%uL retired",
363 (*tmp) == qc->socket ? "active" : "backup",
364 (*tmp)->sid.seqnum, (*tmp)->cid->seqnum,
365 (*tmp)->path->seqnum);
366
367 qsock = ngx_quic_get_unconnected_socket(c);
368 if (qsock == NULL) {
369 return NGX_ERROR;
370 }
371
372 path = (*tmp)->path;
373 cid = (*tmp)->cid;
374
375 ngx_quic_connect(c, qsock, path, cid);
376
377
378 ngx_log_debug5(NGX_LOG_DEBUG_EVENT, c->log, 0,
379 "quic %s socket is now #%uL:%uL:%uL (%s)",
380 (*tmp) == qc->socket ? "active" : "backup",
381 qsock->sid.seqnum, qsock->cid->seqnum,
382 qsock->path->seqnum,
383 ngx_quic_path_state_str(qsock->path));
384
385 ngx_quic_close_socket(c, *tmp); /* no longer used */
386
387 *tmp = qsock;
388 }
389
390 return NGX_OK;
391 }
392
393
394 ngx_int_t
395 ngx_quic_create_sockets(ngx_connection_t *c)
396 {
397 ngx_uint_t n;
398 ngx_quic_socket_t *qsock;
399 ngx_quic_connection_t *qc;
400
401 qc = ngx_quic_get_connection(c);
402
403 n = ngx_min(NGX_QUIC_MAX_SERVER_IDS, qc->ctp.active_connection_id_limit);
404
405 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
406 "quic create sockets has:%ui max:%ui", qc->nsockets, n);
407
408 while (qc->nsockets < n) {
409
410 qsock = ngx_quic_alloc_socket(c, qc);
411 if (qsock == NULL) {
412 return NGX_ERROR;
413 }
414
415 if (ngx_quic_listen(c, qc, qsock) != NGX_OK) {
416 return NGX_ERROR;
417 }
418
419 if (ngx_quic_send_server_id(c, &qsock->sid) != NGX_OK) {
420 return NGX_ERROR;
421 }
422 }
423
424 return NGX_OK;
425 }
426
427
428 static ngx_int_t
429 ngx_quic_send_server_id(ngx_connection_t *c, ngx_quic_server_id_t *sid)
430 {
431 ngx_str_t dcid;
432 ngx_quic_frame_t *frame;
433 ngx_quic_connection_t *qc;
434
435 qc = ngx_quic_get_connection(c);
436
437 dcid.len = sid->len;
438 dcid.data = sid->id;
439
440 frame = ngx_quic_alloc_frame(c);
441 if (frame == NULL) {
442 return NGX_ERROR;
443 }
444
445 frame->level = ssl_encryption_application;
446 frame->type = NGX_QUIC_FT_NEW_CONNECTION_ID;
447 frame->u.ncid.seqnum = sid->seqnum;
448 frame->u.ncid.retire = 0;
449 frame->u.ncid.len = NGX_QUIC_SERVER_CID_LEN;
450 ngx_memcpy(frame->u.ncid.cid, sid->id, NGX_QUIC_SERVER_CID_LEN);
451
452 if (ngx_quic_new_sr_token(c, &dcid, qc->conf->sr_token_key,
453 frame->u.ncid.srt)
454 != NGX_OK)
455 {
456 return NGX_ERROR;
457 }
458
459 ngx_quic_queue_frame(qc, frame);
460
461 return NGX_OK;
462 }
463
464
465 static ngx_int_t
466 ngx_quic_replace_retired_client_id(ngx_connection_t *c,
467 ngx_quic_client_id_t *retired_cid)
468 {
330 ngx_queue_t *q; 469 ngx_queue_t *q;
331 ngx_quic_server_id_t *sid; 470 ngx_quic_socket_t *qsock;
332 ngx_quic_connection_t *qc; 471 ngx_quic_client_id_t *cid;
333 472 ngx_quic_connection_t *qc;
334 qc = ngx_quic_get_connection(c); 473
335 474 qc = ngx_quic_get_connection(c);
336 for (q = ngx_queue_head(&qc->server_ids); 475
337 q != ngx_queue_sentinel(&qc->server_ids); 476 for (q = ngx_queue_head(&qc->sockets);
477 q != ngx_queue_sentinel(&qc->sockets);
338 q = ngx_queue_next(q)) 478 q = ngx_queue_next(q))
339 { 479 {
340 sid = ngx_queue_data(q, ngx_quic_server_id_t, queue); 480 qsock = ngx_queue_data(q, ngx_quic_socket_t, queue);
341 481
342 if (sid->seqnum == f->sequence_number) { 482 if (qsock->cid == retired_cid) {
343 ngx_queue_remove(q); 483
344 ngx_queue_insert_tail(&qc->free_server_ids, &sid->queue); 484 cid = ngx_quic_next_client_id(c);
345 ngx_rbtree_delete(&c->listening->rbtree, &sid->udp.node); 485 if (cid == NULL) {
346 qc->nserver_ids--; 486 return NGX_ERROR;
347 break; 487 }
348 } 488
349 } 489 qsock->cid = cid;
350 490 cid->refcnt++;
351 return ngx_quic_issue_server_ids(c); 491
352 } 492 ngx_quic_unref_client_id(c, retired_cid);
353 493
354 494 if (retired_cid->refcnt == 0) {
355 ngx_int_t 495 return NGX_OK;
356 ngx_quic_issue_server_ids(ngx_connection_t *c) 496 }
357 { 497 }
358 ngx_str_t dcid;
359 ngx_uint_t n;
360 ngx_quic_frame_t *frame;
361 ngx_quic_server_id_t *sid;
362 ngx_quic_connection_t *qc;
363 u_char id[NGX_QUIC_SERVER_CID_LEN];
364
365 qc = ngx_quic_get_connection(c);
366
367 n = ngx_min(NGX_QUIC_MAX_SERVER_IDS, qc->ctp.active_connection_id_limit);
368
369 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
370 "quic issue server ids has:%ui max:%ui", qc->nserver_ids, n);
371
372 while (qc->nserver_ids < n) {
373 if (ngx_quic_create_server_id(c, id) != NGX_OK) {
374 return NGX_ERROR;
375 }
376
377 dcid.len = NGX_QUIC_SERVER_CID_LEN;
378 dcid.data = id;
379
380 sid = ngx_quic_insert_server_id(c, qc, &dcid);
381 if (sid == NULL) {
382 return NGX_ERROR;
383 }
384
385 frame = ngx_quic_alloc_frame(c);
386 if (frame == NULL) {
387 return NGX_ERROR;
388 }
389
390 frame->level = ssl_encryption_application;
391 frame->type = NGX_QUIC_FT_NEW_CONNECTION_ID;
392 frame->u.ncid.seqnum = sid->seqnum;
393 frame->u.ncid.retire = 0;
394 frame->u.ncid.len = NGX_QUIC_SERVER_CID_LEN;
395 ngx_memcpy(frame->u.ncid.cid, id, NGX_QUIC_SERVER_CID_LEN);
396
397 if (ngx_quic_new_sr_token(c, &dcid, qc->conf->sr_token_key,
398 frame->u.ncid.srt)
399 != NGX_OK)
400 {
401 return NGX_ERROR;
402 }
403
404 ngx_quic_queue_frame(qc, frame);
405 } 498 }
406 499
407 return NGX_OK; 500 return NGX_OK;
408 } 501 }
409 502
410 503
411 void 504 void
412 ngx_quic_clear_temp_server_ids(ngx_connection_t *c) 505 ngx_quic_unref_client_id(ngx_connection_t *c, ngx_quic_client_id_t *cid)
413 { 506 {
414 ngx_queue_t *q, *next; 507 ngx_quic_connection_t *qc;
415 ngx_quic_server_id_t *sid; 508
416 ngx_quic_connection_t *qc; 509 cid->refcnt--;
417 510
418 qc = ngx_quic_get_connection(c); 511 if (cid->refcnt) {
419 512 return;
420 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, 513 }
421 "quic clear temp server ids"); 514
422 515 qc = ngx_quic_get_connection(c);
423 for (q = ngx_queue_head(&qc->server_ids); 516
424 q != ngx_queue_sentinel(&qc->server_ids); 517 ngx_queue_remove(&cid->queue);
425 q = next) 518 ngx_queue_insert_head(&qc->free_client_ids, &cid->queue);
426 { 519
427 next = ngx_queue_next(q); 520 qc->nclient_ids--;
428 sid = ngx_queue_data(q, ngx_quic_server_id_t, queue); 521 }
429
430 if (sid->seqnum != NGX_QUIC_UNSET_PN) {
431 continue;
432 }
433
434 ngx_queue_remove(q);
435 ngx_queue_insert_tail(&qc->free_server_ids, &sid->queue);
436 ngx_rbtree_delete(&c->listening->rbtree, &sid->udp.node);
437 qc->nserver_ids--;
438 }
439 }
440
441
442 static ngx_quic_server_id_t *
443 ngx_quic_insert_server_id(ngx_connection_t *c, ngx_quic_connection_t *qc,
444 ngx_str_t *id)
445 {
446 ngx_str_t dcid;
447 ngx_quic_server_id_t *sid;
448
449 sid = ngx_quic_alloc_server_id(c, qc);
450 if (sid == NULL) {
451 return NULL;
452 }
453
454 sid->quic = qc;
455
456 sid->seqnum = qc->server_seqnum;
457
458 if (qc->server_seqnum != NGX_QUIC_UNSET_PN) {
459 qc->server_seqnum++;
460 }
461
462 sid->len = id->len;
463 ngx_memcpy(sid->id, id->data, id->len);
464
465 ngx_queue_insert_tail(&qc->server_ids, &sid->queue);
466 qc->nserver_ids++;
467
468 dcid.data = sid->id;
469 dcid.len = sid->len;
470
471 ngx_insert_udp_connection(c, &sid->udp, &dcid);
472
473 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
474 "quic insert server id seqnum:%uL id len:%uz %xV",
475 sid->seqnum, id->len, id);
476
477 return sid;
478 }
479
480
481 static ngx_quic_client_id_t *
482 ngx_quic_alloc_client_id(ngx_connection_t *c, ngx_quic_connection_t *qc)
483 {
484 ngx_queue_t *q;
485 ngx_quic_client_id_t *cid;
486
487 if (!ngx_queue_empty(&qc->free_client_ids)) {
488
489 q = ngx_queue_head(&qc->free_client_ids);
490 cid = ngx_queue_data(q, ngx_quic_client_id_t, queue);
491
492 ngx_queue_remove(&cid->queue);
493
494 ngx_memzero(cid, sizeof(ngx_quic_client_id_t));
495
496 } else {
497
498 cid = ngx_pcalloc(c->pool, sizeof(ngx_quic_client_id_t));
499 if (cid == NULL) {
500 return NULL;
501 }
502 }
503
504 return cid;
505 }
506
507
508 static ngx_quic_server_id_t *
509 ngx_quic_alloc_server_id(ngx_connection_t *c, ngx_quic_connection_t *qc)
510 {
511 ngx_queue_t *q;
512 ngx_quic_server_id_t *sid;
513
514 if (!ngx_queue_empty(&qc->free_server_ids)) {
515
516 q = ngx_queue_head(&qc->free_server_ids);
517 sid = ngx_queue_data(q, ngx_quic_server_id_t, queue);
518
519 ngx_queue_remove(&sid->queue);
520
521 ngx_memzero(sid, sizeof(ngx_quic_server_id_t));
522
523 } else {
524
525 sid = ngx_pcalloc(c->pool, sizeof(ngx_quic_server_id_t));
526 if (sid == NULL) {
527 return NULL;
528 }
529 }
530
531 return sid;
532 }