comparison src/event/ngx_event_quic.c @ 8657:2dfc5ef29973 quic

QUIC: introduced QUIC buffers. Buffers are used to hold frame data. They have a fixed size and are reused after being freed.
author Roman Arutyunyan <arut@nginx.com>
date Tue, 01 Dec 2020 19:11:01 +0000
parents 43f3574b3e6f
children 0af4ec6d1f92
comparison
equal deleted inserted replaced
8656:43f3574b3e6f 8657:2dfc5ef29973
141 ngx_quic_conf_t *conf; 141 ngx_quic_conf_t *conf;
142 142
143 ngx_event_t push; 143 ngx_event_t push;
144 ngx_event_t pto; 144 ngx_event_t pto;
145 ngx_event_t close; 145 ngx_event_t close;
146 ngx_queue_t free_frames;
147 ngx_msec_t last_cc; 146 ngx_msec_t last_cc;
148 147
149 ngx_msec_t latest_rtt; 148 ngx_msec_t latest_rtt;
150 ngx_msec_t avg_rtt; 149 ngx_msec_t avg_rtt;
151 ngx_msec_t min_rtt; 150 ngx_msec_t min_rtt;
152 ngx_msec_t rttvar; 151 ngx_msec_t rttvar;
153 152
154 ngx_uint_t pto_count; 153 ngx_uint_t pto_count;
155 154
156 #if (NGX_DEBUG) 155 ngx_queue_t free_frames;
156 ngx_chain_t *free_bufs;
157
158 #ifdef NGX_QUIC_DEBUG_ALLOC
157 ngx_uint_t nframes; 159 ngx_uint_t nframes;
160 ngx_uint_t nbufs;
158 #endif 161 #endif
159 162
160 ngx_quic_streams_t streams; 163 ngx_quic_streams_t streams;
161 ngx_quic_congestion_t congestion; 164 ngx_quic_congestion_t congestion;
162 size_t received; 165 size_t received;
263 ngx_quic_send_ctx_t *ctx); 266 ngx_quic_send_ctx_t *ctx);
264 static ngx_int_t ngx_quic_send_cc(ngx_connection_t *c); 267 static ngx_int_t ngx_quic_send_cc(ngx_connection_t *c);
265 static ngx_int_t ngx_quic_send_new_token(ngx_connection_t *c); 268 static ngx_int_t ngx_quic_send_new_token(ngx_connection_t *c);
266 269
267 static ngx_int_t ngx_quic_handle_ack_frame(ngx_connection_t *c, 270 static ngx_int_t ngx_quic_handle_ack_frame(ngx_connection_t *c,
268 ngx_quic_header_t *pkt, ngx_quic_ack_frame_t *f); 271 ngx_quic_header_t *pkt, ngx_quic_frame_t *f);
269 static ngx_int_t ngx_quic_handle_ack_frame_range(ngx_connection_t *c, 272 static ngx_int_t ngx_quic_handle_ack_frame_range(ngx_connection_t *c,
270 ngx_quic_send_ctx_t *ctx, uint64_t min, uint64_t max, 273 ngx_quic_send_ctx_t *ctx, uint64_t min, uint64_t max,
271 ngx_msec_t *send_time); 274 ngx_msec_t *send_time);
272 static void ngx_quic_rtt_sample(ngx_connection_t *c, ngx_quic_ack_frame_t *ack, 275 static void ngx_quic_rtt_sample(ngx_connection_t *c, ngx_quic_ack_frame_t *ack,
273 enum ssl_encryption_level_t level, ngx_msec_t send_time); 276 enum ssl_encryption_level_t level, ngx_msec_t send_time);
359 static ngx_chain_t *ngx_quic_stream_send_chain(ngx_connection_t *c, 362 static ngx_chain_t *ngx_quic_stream_send_chain(ngx_connection_t *c,
360 ngx_chain_t *in, off_t limit); 363 ngx_chain_t *in, off_t limit);
361 static size_t ngx_quic_max_stream_frame(ngx_quic_connection_t *qc); 364 static size_t ngx_quic_max_stream_frame(ngx_quic_connection_t *qc);
362 static size_t ngx_quic_max_stream_flow(ngx_connection_t *c); 365 static size_t ngx_quic_max_stream_flow(ngx_connection_t *c);
363 static void ngx_quic_stream_cleanup_handler(void *data); 366 static void ngx_quic_stream_cleanup_handler(void *data);
364 static ngx_quic_frame_t *ngx_quic_alloc_frame(ngx_connection_t *c, size_t size); 367 static ngx_quic_frame_t *ngx_quic_alloc_frame(ngx_connection_t *c);
365 static void ngx_quic_free_frame(ngx_connection_t *c, ngx_quic_frame_t *frame); 368 static void ngx_quic_free_frame(ngx_connection_t *c, ngx_quic_frame_t *frame);
366 369
367 static void ngx_quic_congestion_ack(ngx_connection_t *c, 370 static void ngx_quic_congestion_ack(ngx_connection_t *c,
368 ngx_quic_frame_t *frame); 371 ngx_quic_frame_t *frame);
369 static void ngx_quic_congestion_lost(ngx_connection_t *c, 372 static void ngx_quic_congestion_lost(ngx_connection_t *c,
370 ngx_quic_frame_t *frame); 373 ngx_quic_frame_t *frame);
374
375 static ngx_chain_t *ngx_quic_alloc_buf(ngx_connection_t *c);
376 static void ngx_quic_free_bufs(ngx_connection_t *c, ngx_chain_t *in);
377 static ngx_chain_t *ngx_quic_copy_buf(ngx_connection_t *c, u_char *data,
378 size_t len);
379 static ngx_chain_t *ngx_quic_copy_chain(ngx_connection_t *c, ngx_chain_t *in,
380 size_t limit);
371 381
372 382
373 static SSL_QUIC_METHOD quic_method = { 383 static SSL_QUIC_METHOD quic_method = {
374 #if BORINGSSL_API_VERSION >= 10 384 #if BORINGSSL_API_VERSION >= 10
375 ngx_quic_set_read_secret, 385 ngx_quic_set_read_secret,
412 case NGX_QUIC_FT_ACK_ECN: 422 case NGX_QUIC_FT_ACK_ECN:
413 423
414 p = ngx_slprintf(p, last, "ACK n:%ui delay:%uL ", 424 p = ngx_slprintf(p, last, "ACK n:%ui delay:%uL ",
415 f->u.ack.range_count, f->u.ack.delay); 425 f->u.ack.range_count, f->u.ack.delay);
416 426
417 pos = f->u.ack.ranges_start; 427 if (f->data) {
418 end = f->u.ack.ranges_end; 428 pos = f->data->buf->pos;
429 end = f->data->buf->end;
430
431 } else {
432 pos = NULL;
433 end = NULL;
434 }
419 435
420 largest = f->u.ack.largest; 436 largest = f->u.ack.largest;
421 smallest = f->u.ack.largest - f->u.ack.first_range; 437 smallest = f->u.ack.largest - f->u.ack.first_range;
422 438
423 if (largest == smallest) { 439 if (largest == smallest) {
505 if (f->u.stream.fin) { 521 if (f->u.stream.fin) {
506 p = ngx_slprintf(p, last, " fin:1"); 522 p = ngx_slprintf(p, last, " fin:1");
507 } 523 }
508 524
509 #ifdef NGX_QUIC_DEBUG_FRAMES 525 #ifdef NGX_QUIC_DEBUG_FRAMES
510 p = ngx_slprintf(p, last, " data len:%uL %*xs", f->u.stream.length, 526 {
511 (size_t) f->u.stream.length, f->u.stream.data); 527 ngx_chain_t *cl;
528
529 p = ngx_slprintf(p, last, " data:");
530
531 for (cl = f->data; cl; cl = cl->next) {
532 p = ngx_slprintf(p, last, "%*xs",
533 cl->buf->last - cl->buf->pos, cl->buf->pos);
534 }
535 }
512 #endif 536 #endif
513 537
514 break; 538 break;
515 539
516 case NGX_QUIC_FT_MAX_DATA: 540 case NGX_QUIC_FT_MAX_DATA:
883 907
884 while (p < end) { 908 while (p < end) {
885 909
886 fsize = ngx_min(limit, (size_t) (end - p)); 910 fsize = ngx_min(limit, (size_t) (end - p));
887 911
888 frame = ngx_quic_alloc_frame(c, fsize); 912 frame = ngx_quic_alloc_frame(c);
889 if (frame == NULL) { 913 if (frame == NULL) {
890 return 0; 914 return 0;
891 } 915 }
892 916
893 ngx_memcpy(frame->data, p, fsize); 917 frame->data = ngx_quic_copy_buf(c, p, fsize);
918 if (frame->data == NGX_CHAIN_ERROR) {
919 return 0;
920 }
894 921
895 frame->level = level; 922 frame->level = level;
896 frame->type = NGX_QUIC_FT_CRYPTO; 923 frame->type = NGX_QUIC_FT_CRYPTO;
897 frame->u.crypto.offset = fs->sent; 924 frame->u.crypto.offset = fs->sent;
898 frame->u.crypto.length = fsize; 925 frame->u.crypto.length = fsize;
899 frame->u.crypto.data = frame->data;
900 926
901 fs->sent += fsize; 927 fs->sent += fsize;
902 p += fsize; 928 p += fsize;
903 929
904 ngx_quic_queue_frame(qc, frame); 930 ngx_quic_queue_frame(qc, frame);
1866 ngx_del_timer(&qc->pto); 1892 ngx_del_timer(&qc->pto);
1867 } 1893 }
1868 1894
1869 if (qc->push.posted) { 1895 if (qc->push.posted) {
1870 ngx_delete_posted_event(&qc->push); 1896 ngx_delete_posted_event(&qc->push);
1871 }
1872
1873 for (i = 0; i < NGX_QUIC_ENCRYPTION_LAST; i++) {
1874 ngx_quic_free_frames(c, &qc->crypto[i].frames);
1875 }
1876
1877 for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) {
1878 ngx_quic_free_frames(c, &qc->send_ctx[i].frames);
1879 ngx_quic_free_frames(c, &qc->send_ctx[i].sent);
1880 } 1897 }
1881 1898
1882 while (!ngx_queue_empty(&qc->server_ids)) { 1899 while (!ngx_queue_empty(&qc->server_ids)) {
1883 q = ngx_queue_head(&qc->server_ids); 1900 q = ngx_queue_head(&qc->server_ids);
1884 sid = ngx_queue_data(q, ngx_quic_server_id_t, queue); 1901 sid = ngx_queue_data(q, ngx_quic_server_id_t, queue);
2436 static ngx_int_t 2453 static ngx_int_t
2437 ngx_quic_payload_handler(ngx_connection_t *c, ngx_quic_header_t *pkt) 2454 ngx_quic_payload_handler(ngx_connection_t *c, ngx_quic_header_t *pkt)
2438 { 2455 {
2439 u_char *end, *p; 2456 u_char *end, *p;
2440 ssize_t len; 2457 ssize_t len;
2458 ngx_buf_t buf;
2441 ngx_uint_t do_close; 2459 ngx_uint_t do_close;
2460 ngx_chain_t chain;
2442 ngx_quic_frame_t frame; 2461 ngx_quic_frame_t frame;
2443 ngx_quic_connection_t *qc; 2462 ngx_quic_connection_t *qc;
2444 2463
2445 qc = ngx_quic_get_connection(c); 2464 qc = ngx_quic_get_connection(c);
2446 2465
2470 2489
2471 while (p < end) { 2490 while (p < end) {
2472 2491
2473 c->log->action = "parsing frames"; 2492 c->log->action = "parsing frames";
2474 2493
2494 ngx_memzero(&buf, sizeof(ngx_buf_t));
2495
2496 chain.buf = &buf;
2497 chain.next = NULL;
2498 frame.data = &chain;
2499
2475 len = ngx_quic_parse_frame(pkt, p, end, &frame); 2500 len = ngx_quic_parse_frame(pkt, p, end, &frame);
2476 2501
2477 if (len < 0) { 2502 if (len < 0) {
2478 qc->error = pkt->error; 2503 qc->error = pkt->error;
2479 return NGX_ERROR; 2504 return NGX_ERROR;
2486 p += len; 2511 p += len;
2487 2512
2488 switch (frame.type) { 2513 switch (frame.type) {
2489 2514
2490 case NGX_QUIC_FT_ACK: 2515 case NGX_QUIC_FT_ACK:
2491 if (ngx_quic_handle_ack_frame(c, pkt, &frame.u.ack) != NGX_OK) { 2516 if (ngx_quic_handle_ack_frame(c, pkt, &frame) != NGX_OK) {
2492 return NGX_ERROR; 2517 return NGX_ERROR;
2493 } 2518 }
2494 2519
2495 continue; 2520 continue;
2496 2521
2920 ngx_quic_send_ack_range(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx, 2945 ngx_quic_send_ack_range(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
2921 uint64_t smallest, uint64_t largest) 2946 uint64_t smallest, uint64_t largest)
2922 { 2947 {
2923 ngx_quic_frame_t *frame; 2948 ngx_quic_frame_t *frame;
2924 2949
2925 frame = ngx_quic_alloc_frame(c, 0); 2950 frame = ngx_quic_alloc_frame(c);
2926 if (frame == NULL) { 2951 if (frame == NULL) {
2927 return NGX_ERROR; 2952 return NGX_ERROR;
2928 } 2953 }
2929 2954
2930 frame->level = ctx->level; 2955 frame->level = ctx->level;
2997 3022
2998 3023
2999 static ngx_int_t 3024 static ngx_int_t
3000 ngx_quic_send_ack(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx) 3025 ngx_quic_send_ack(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx)
3001 { 3026 {
3002 u_char *p; 3027 size_t len, left;
3003 size_t ranges_len;
3004 uint64_t ack_delay; 3028 uint64_t ack_delay;
3029 ngx_buf_t *b;
3005 ngx_uint_t i; 3030 ngx_uint_t i;
3031 ngx_chain_t *cl, **ll;
3006 ngx_quic_frame_t *frame; 3032 ngx_quic_frame_t *frame;
3007 ngx_quic_connection_t *qc; 3033 ngx_quic_connection_t *qc;
3008 3034
3009 qc = ngx_quic_get_connection(c); 3035 qc = ngx_quic_get_connection(c);
3010 3036
3015 3041
3016 } else { 3042 } else {
3017 ack_delay = 0; 3043 ack_delay = 0;
3018 } 3044 }
3019 3045
3020 ranges_len = 0; 3046 frame = ngx_quic_alloc_frame(c);
3021
3022 for (i = 0; i < ctx->nranges; i++) {
3023 ranges_len += ngx_quic_create_ack_range(NULL, ctx->ranges[i].gap,
3024 ctx->ranges[i].range);
3025 }
3026
3027 frame = ngx_quic_alloc_frame(c, ranges_len);
3028 if (frame == NULL) { 3047 if (frame == NULL) {
3029 return NGX_ERROR; 3048 return NGX_ERROR;
3030 } 3049 }
3031 3050
3032 p = frame->data; 3051 ll = &frame->data;
3052 b = NULL;
3033 3053
3034 for (i = 0; i < ctx->nranges; i++) { 3054 for (i = 0; i < ctx->nranges; i++) {
3035 p += ngx_quic_create_ack_range(p, ctx->ranges[i].gap, 3055 len = ngx_quic_create_ack_range(NULL, ctx->ranges[i].gap,
3036 ctx->ranges[i].range); 3056 ctx->ranges[i].range);
3037 } 3057
3058 left = b ? b->end - b->last : 0;
3059
3060 if (left < len) {
3061 cl = ngx_quic_alloc_buf(c);
3062 if (cl == NULL) {
3063 return NGX_ERROR;
3064 }
3065
3066 *ll = cl;
3067 ll = &cl->next;
3068
3069 b = cl->buf;
3070 left = b->end - b->last;
3071
3072 if (left < len) {
3073 return NGX_ERROR;
3074 }
3075 }
3076
3077 b->last += ngx_quic_create_ack_range(b->last, ctx->ranges[i].gap,
3078 ctx->ranges[i].range);
3079
3080 frame->u.ack.ranges_length += len;
3081 }
3082
3083 *ll = NULL;
3038 3084
3039 frame->level = ctx->level; 3085 frame->level = ctx->level;
3040 frame->type = NGX_QUIC_FT_ACK; 3086 frame->type = NGX_QUIC_FT_ACK;
3041 frame->u.ack.largest = ctx->largest_range; 3087 frame->u.ack.largest = ctx->largest_range;
3042 frame->u.ack.delay = ack_delay; 3088 frame->u.ack.delay = ack_delay;
3043 frame->u.ack.range_count = ctx->nranges; 3089 frame->u.ack.range_count = ctx->nranges;
3044 frame->u.ack.first_range = ctx->first_range; 3090 frame->u.ack.first_range = ctx->first_range;
3045 frame->u.ack.ranges_start = frame->data;
3046 frame->u.ack.ranges_end = frame->data + ranges_len;
3047 3091
3048 ngx_quic_queue_frame(qc, frame); 3092 ngx_quic_queue_frame(qc, frame);
3049 3093
3050 return NGX_OK; 3094 return NGX_OK;
3051 } 3095 }
3075 { 3119 {
3076 /* dot not send CC too often */ 3120 /* dot not send CC too often */
3077 return NGX_OK; 3121 return NGX_OK;
3078 } 3122 }
3079 3123
3080 frame = ngx_quic_alloc_frame(c, 0); 3124 frame = ngx_quic_alloc_frame(c);
3081 if (frame == NULL) { 3125 if (frame == NULL) {
3082 return NGX_ERROR; 3126 return NGX_ERROR;
3083 } 3127 }
3084 3128
3085 frame->level = qc->error_level; 3129 frame->level = qc->error_level;
3116 3160
3117 if (ngx_quic_new_token(c, &token) != NGX_OK) { 3161 if (ngx_quic_new_token(c, &token) != NGX_OK) {
3118 return NGX_ERROR; 3162 return NGX_ERROR;
3119 } 3163 }
3120 3164
3121 frame = ngx_quic_alloc_frame(c, 0); 3165 frame = ngx_quic_alloc_frame(c);
3122 if (frame == NULL) { 3166 if (frame == NULL) {
3123 return NGX_ERROR; 3167 return NGX_ERROR;
3124 } 3168 }
3125 3169
3126 frame->level = ssl_encryption_application; 3170 frame->level = ssl_encryption_application;
3134 } 3178 }
3135 3179
3136 3180
3137 static ngx_int_t 3181 static ngx_int_t
3138 ngx_quic_handle_ack_frame(ngx_connection_t *c, ngx_quic_header_t *pkt, 3182 ngx_quic_handle_ack_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
3139 ngx_quic_ack_frame_t *ack) 3183 ngx_quic_frame_t *f)
3140 { 3184 {
3141 ssize_t n; 3185 ssize_t n;
3142 u_char *pos, *end; 3186 u_char *pos, *end;
3143 uint64_t min, max, gap, range; 3187 uint64_t min, max, gap, range;
3144 ngx_msec_t send_time; 3188 ngx_msec_t send_time;
3145 ngx_uint_t i; 3189 ngx_uint_t i;
3146 ngx_quic_send_ctx_t *ctx; 3190 ngx_quic_send_ctx_t *ctx;
3191 ngx_quic_ack_frame_t *ack;
3147 ngx_quic_connection_t *qc; 3192 ngx_quic_connection_t *qc;
3148 3193
3149 qc = ngx_quic_get_connection(c); 3194 qc = ngx_quic_get_connection(c);
3150 3195
3151 ctx = ngx_quic_get_send_ctx(qc, pkt->level); 3196 ctx = ngx_quic_get_send_ctx(qc, pkt->level);
3152 3197
3153 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, 3198 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
3154 "quic ngx_quic_handle_ack_frame level:%d", pkt->level); 3199 "quic ngx_quic_handle_ack_frame level:%d", pkt->level);
3200
3201 ack = &f->u.ack;
3155 3202
3156 /* 3203 /*
3157 * If any computed packet number is negative, an endpoint MUST 3204 * If any computed packet number is negative, an endpoint MUST
3158 * generate a connection error of type FRAME_ENCODING_ERROR. 3205 * generate a connection error of type FRAME_ENCODING_ERROR.
3159 * (19.3.1) 3206 * (19.3.1)
3192 if (send_time != NGX_TIMER_INFINITE) { 3239 if (send_time != NGX_TIMER_INFINITE) {
3193 ngx_quic_rtt_sample(c, ack, pkt->level, send_time); 3240 ngx_quic_rtt_sample(c, ack, pkt->level, send_time);
3194 } 3241 }
3195 } 3242 }
3196 3243
3197 pos = ack->ranges_start; 3244 if (f->data) {
3198 end = ack->ranges_end; 3245 pos = f->data->buf->pos;
3246 end = f->data->buf->last;
3247
3248 } else {
3249 pos = NULL;
3250 end = NULL;
3251 }
3199 3252
3200 for (i = 0; i < ack->range_count; i++) { 3253 for (i = 0; i < ack->range_count; i++) {
3201 3254
3202 n = ngx_quic_parse_ack_range(pkt->log, pos, end, &gap, &range); 3255 n = ngx_quic_parse_ack_range(pkt->log, pos, end, &gap, &range);
3203 if (n == NGX_ERROR) { 3256 if (n == NGX_ERROR) {
3535 3588
3536 static ngx_int_t 3589 static ngx_int_t
3537 ngx_quic_adjust_frame_offset(ngx_connection_t *c, ngx_quic_frame_t *frame, 3590 ngx_quic_adjust_frame_offset(ngx_connection_t *c, ngx_quic_frame_t *frame,
3538 uint64_t offset_in) 3591 uint64_t offset_in)
3539 { 3592 {
3540 size_t tail; 3593 size_t tail, n;
3594 ngx_buf_t *b;
3595 ngx_chain_t *cl;
3541 ngx_quic_ordered_frame_t *f; 3596 ngx_quic_ordered_frame_t *f;
3542 3597
3543 f = &frame->u.ord; 3598 f = &frame->u.ord;
3544 3599
3545 tail = offset_in - f->offset; 3600 tail = offset_in - f->offset;
3556 "quic adjusted ordered frame data start to expected offset"); 3611 "quic adjusted ordered frame data start to expected offset");
3557 3612
3558 /* intersecting range: adjust data size */ 3613 /* intersecting range: adjust data size */
3559 3614
3560 f->offset += tail; 3615 f->offset += tail;
3561 f->data += tail;
3562 f->length -= tail; 3616 f->length -= tail;
3617
3618 for (cl = frame->data; cl; cl = cl->next) {
3619 b = cl->buf;
3620 n = ngx_buf_size(b);
3621
3622 if (n >= tail) {
3623 b->pos += tail;
3624 break;
3625 }
3626
3627 cl->buf->pos = cl->buf->last;
3628 tail -= n;
3629 }
3563 3630
3564 return NGX_OK; 3631 return NGX_OK;
3565 } 3632 }
3566 3633
3567 3634
3568 static ngx_int_t 3635 static ngx_int_t
3569 ngx_quic_buffer_frame(ngx_connection_t *c, ngx_quic_frames_stream_t *fs, 3636 ngx_quic_buffer_frame(ngx_connection_t *c, ngx_quic_frames_stream_t *fs,
3570 ngx_quic_frame_t *frame) 3637 ngx_quic_frame_t *frame)
3571 { 3638 {
3572 u_char *data;
3573 ngx_queue_t *q; 3639 ngx_queue_t *q;
3574 ngx_quic_frame_t *dst, *item; 3640 ngx_quic_frame_t *dst, *item;
3575 ngx_quic_ordered_frame_t *f, *df; 3641 ngx_quic_ordered_frame_t *f, *df;
3576 3642
3577 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, 3643 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
3579 3645
3580 f = &frame->u.ord; 3646 f = &frame->u.ord;
3581 3647
3582 /* frame start offset is in the future, buffer it */ 3648 /* frame start offset is in the future, buffer it */
3583 3649
3584 dst = ngx_quic_alloc_frame(c, f->length); 3650 dst = ngx_quic_alloc_frame(c);
3585 if (dst == NULL) { 3651 if (dst == NULL) {
3586 return NGX_ERROR; 3652 return NGX_ERROR;
3587 } 3653 }
3588 3654
3589 data = dst->data;
3590 ngx_memcpy(dst, frame, sizeof(ngx_quic_frame_t)); 3655 ngx_memcpy(dst, frame, sizeof(ngx_quic_frame_t));
3591 dst->data = data; 3656
3592 3657 dst->data = ngx_quic_copy_chain(c, frame->data, 0);
3593 ngx_memcpy(dst->data, f->data, f->length); 3658 if (dst->data == NGX_CHAIN_ERROR) {
3659 return NGX_ERROR;
3660 }
3594 3661
3595 df = &dst->u.ord; 3662 df = &dst->u.ord;
3596 df->data = dst->data;
3597 3663
3598 fs->total += f->length; 3664 fs->total += f->length;
3599 3665
3600 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, 3666 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
3601 "quic ordered frame with unexpected offset:" 3667 "quic ordered frame with unexpected offset:"
3669 3735
3670 3736
3671 static ngx_int_t 3737 static ngx_int_t
3672 ngx_quic_crypto_input(ngx_connection_t *c, ngx_quic_frame_t *frame, void *data) 3738 ngx_quic_crypto_input(ngx_connection_t *c, ngx_quic_frame_t *frame, void *data)
3673 { 3739 {
3674 int n, sslerr; 3740 int n, sslerr;
3675 ngx_ssl_conn_t *ssl_conn; 3741 ngx_buf_t *b;
3676 ngx_quic_connection_t *qc; 3742 ngx_chain_t *cl;
3677 ngx_quic_crypto_frame_t *f; 3743 ngx_ssl_conn_t *ssl_conn;
3744 ngx_quic_connection_t *qc;
3678 3745
3679 qc = ngx_quic_get_connection(c); 3746 qc = ngx_quic_get_connection(c);
3680
3681 f = &frame->u.crypto;
3682 3747
3683 ssl_conn = c->ssl->connection; 3748 ssl_conn = c->ssl->connection;
3684 3749
3685 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, 3750 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
3686 "quic SSL_quic_read_level:%d SSL_quic_write_level:%d", 3751 "quic SSL_quic_read_level:%d SSL_quic_write_level:%d",
3687 (int) SSL_quic_read_level(ssl_conn), 3752 (int) SSL_quic_read_level(ssl_conn),
3688 (int) SSL_quic_write_level(ssl_conn)); 3753 (int) SSL_quic_write_level(ssl_conn));
3689 3754
3690 if (!SSL_provide_quic_data(ssl_conn, SSL_quic_read_level(ssl_conn), 3755 for (cl = frame->data; cl; cl = cl->next) {
3691 f->data, f->length)) 3756 b = cl->buf;
3692 { 3757
3693 ngx_ssl_error(NGX_LOG_INFO, c->log, 0, 3758 if (!SSL_provide_quic_data(ssl_conn, SSL_quic_read_level(ssl_conn),
3694 "SSL_provide_quic_data() failed"); 3759 b->pos, b->last - b->pos))
3695 return NGX_ERROR; 3760 {
3761 ngx_ssl_error(NGX_LOG_INFO, c->log, 0,
3762 "SSL_provide_quic_data() failed");
3763 return NGX_ERROR;
3764 }
3696 } 3765 }
3697 3766
3698 n = SSL_do_handshake(ssl_conn); 3767 n = SSL_do_handshake(ssl_conn);
3699 3768
3700 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, 3769 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
3728 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, 3797 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
3729 "quic handshake completed successfully"); 3798 "quic handshake completed successfully");
3730 3799
3731 c->ssl->handshaked = 1; 3800 c->ssl->handshaked = 1;
3732 3801
3733 frame = ngx_quic_alloc_frame(c, 0); 3802 frame = ngx_quic_alloc_frame(c);
3734 if (frame == NULL) { 3803 if (frame == NULL) {
3735 return NGX_ERROR; 3804 return NGX_ERROR;
3736 } 3805 }
3737 3806
3738 /* 12.4 Frames and frame types, figure 8 */ 3807 /* 12.4 Frames and frame types, figure 8 */
3856 ngx_quic_stream_input(ngx_connection_t *c, ngx_quic_frame_t *frame, void *data) 3925 ngx_quic_stream_input(ngx_connection_t *c, ngx_quic_frame_t *frame, void *data)
3857 { 3926 {
3858 uint64_t id; 3927 uint64_t id;
3859 ngx_buf_t *b; 3928 ngx_buf_t *b;
3860 ngx_event_t *rev; 3929 ngx_event_t *rev;
3930 ngx_chain_t *cl;
3861 ngx_quic_stream_t *sn; 3931 ngx_quic_stream_t *sn;
3862 ngx_quic_connection_t *qc; 3932 ngx_quic_connection_t *qc;
3863 ngx_quic_stream_frame_t *f; 3933 ngx_quic_stream_frame_t *f;
3864 3934
3865 qc = ngx_quic_get_connection(c); 3935 qc = ngx_quic_get_connection(c);
3879 if ((size_t) (b->end - b->last) < f->length) { 3949 if ((size_t) (b->end - b->last) < f->length) {
3880 b->last = ngx_movemem(b->start, b->pos, b->last - b->pos); 3950 b->last = ngx_movemem(b->start, b->pos, b->last - b->pos);
3881 b->pos = b->start; 3951 b->pos = b->start;
3882 } 3952 }
3883 3953
3884 b->last = ngx_cpymem(b->last, f->data, f->length); 3954 for (cl = frame->data; cl; cl = cl->next) {
3955 b->last = ngx_cpymem(b->last, cl->buf->pos,
3956 cl->buf->last - cl->buf->pos);
3957 }
3885 3958
3886 rev = sn->c->read; 3959 rev = sn->c->read;
3887 rev->ready = 1; 3960 rev->ready = 1;
3888 3961
3889 if (f->fin) { 3962 if (f->fin) {
3990 } else { 4063 } else {
3991 b = sn->b; 4064 b = sn->b;
3992 n = sn->fs.received + (b->pos - b->start) + (b->end - b->last); 4065 n = sn->fs.received + (b->pos - b->start) + (b->end - b->last);
3993 } 4066 }
3994 4067
3995 frame = ngx_quic_alloc_frame(c, 0); 4068 frame = ngx_quic_alloc_frame(c);
3996 if (frame == NULL) { 4069 if (frame == NULL) {
3997 return NGX_ERROR; 4070 return NGX_ERROR;
3998 } 4071 }
3999 4072
4000 frame->level = pkt->level; 4073 frame->level = pkt->level;
4213 ngx_quic_frame_t *frame; 4286 ngx_quic_frame_t *frame;
4214 ngx_quic_connection_t *qc; 4287 ngx_quic_connection_t *qc;
4215 4288
4216 qc = ngx_quic_get_connection(c); 4289 qc = ngx_quic_get_connection(c);
4217 4290
4218 frame = ngx_quic_alloc_frame(c, 0); 4291 frame = ngx_quic_alloc_frame(c);
4219 if (frame == NULL) { 4292 if (frame == NULL) {
4220 return NGX_ERROR; 4293 return NGX_ERROR;
4221 } 4294 }
4222 4295
4223 frame->level = pkt->level; 4296 frame->level = pkt->level;
4379 ngx_quic_frame_t *frame; 4452 ngx_quic_frame_t *frame;
4380 ngx_quic_connection_t *qc; 4453 ngx_quic_connection_t *qc;
4381 4454
4382 qc = ngx_quic_get_connection(c); 4455 qc = ngx_quic_get_connection(c);
4383 4456
4384 frame = ngx_quic_alloc_frame(c, 0); 4457 frame = ngx_quic_alloc_frame(c);
4385 if (frame == NULL) { 4458 if (frame == NULL) {
4386 return NGX_ERROR; 4459 return NGX_ERROR;
4387 } 4460 }
4388 4461
4389 frame->level = level; 4462 frame->level = level;
4453 sid = ngx_quic_insert_server_id(c, &dcid); 4526 sid = ngx_quic_insert_server_id(c, &dcid);
4454 if (sid == NULL) { 4527 if (sid == NULL) {
4455 return NGX_ERROR; 4528 return NGX_ERROR;
4456 } 4529 }
4457 4530
4458 frame = ngx_quic_alloc_frame(c, 0); 4531 frame = ngx_quic_alloc_frame(c);
4459 if (frame == NULL) { 4532 if (frame == NULL) {
4460 return NGX_ERROR; 4533 return NGX_ERROR;
4461 } 4534 }
4462 4535
4463 frame->level = ssl_encryption_application; 4536 frame->level = ssl_encryption_application;
5632 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, 5705 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
5633 "quic stream id:0x%xL recv len:%z of size:%uz", 5706 "quic stream id:0x%xL recv len:%z of size:%uz",
5634 qs->id, len, size); 5707 qs->id, len, size);
5635 5708
5636 if (!rev->pending_eof) { 5709 if (!rev->pending_eof) {
5637 frame = ngx_quic_alloc_frame(pc, 0); 5710 frame = ngx_quic_alloc_frame(pc);
5638 if (frame == NULL) { 5711 if (frame == NULL) {
5639 return NGX_ERROR; 5712 return NGX_ERROR;
5640 } 5713 }
5641 5714
5642 frame->level = ssl_encryption_application; 5715 frame->level = ssl_encryption_application;
5648 ngx_quic_queue_frame(qc, frame); 5721 ngx_quic_queue_frame(qc, frame);
5649 } 5722 }
5650 5723
5651 if ((qc->streams.recv_max_data / 2) < qc->streams.received) { 5724 if ((qc->streams.recv_max_data / 2) < qc->streams.received) {
5652 5725
5653 frame = ngx_quic_alloc_frame(pc, 0); 5726 frame = ngx_quic_alloc_frame(pc);
5654 5727
5655 if (frame == NULL) { 5728 if (frame == NULL) {
5656 return NGX_ERROR; 5729 return NGX_ERROR;
5657 } 5730 }
5658 5731
5701 5774
5702 5775
5703 static ngx_chain_t * 5776 static ngx_chain_t *
5704 ngx_quic_stream_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) 5777 ngx_quic_stream_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
5705 { 5778 {
5706 u_char *p; 5779 size_t n, max, max_frame, max_flow, max_limit;
5707 size_t n, max, max_frame, max_flow, max_limit, len;
5708 #if (NGX_DEBUG) 5780 #if (NGX_DEBUG)
5709 size_t sent; 5781 size_t sent;
5710 #endif
5711 ngx_buf_t *b;
5712 #if (NGX_DEBUG)
5713 ngx_uint_t nframes; 5782 ngx_uint_t nframes;
5714 #endif 5783 #endif
5715 ngx_event_t *wev; 5784 ngx_event_t *wev;
5716 ngx_chain_t *cl; 5785 ngx_chain_t *cl;
5717 ngx_connection_t *pc; 5786 ngx_connection_t *pc;
5761 if (n == 0) { 5830 if (n == 0) {
5762 wev->ready = (max_flow ? 1 : 0); 5831 wev->ready = (max_flow ? 1 : 0);
5763 break; 5832 break;
5764 } 5833 }
5765 5834
5766 frame = ngx_quic_alloc_frame(pc, n); 5835 frame = ngx_quic_alloc_frame(pc);
5767 if (frame == NULL) { 5836 if (frame == NULL) {
5768 return NGX_CHAIN_ERROR; 5837 return NGX_CHAIN_ERROR;
5769 } 5838 }
5770 5839
5771 frame->level = ssl_encryption_application; 5840 frame->level = ssl_encryption_application;
5776 5845
5777 frame->u.stream.type = frame->type; 5846 frame->u.stream.type = frame->type;
5778 frame->u.stream.stream_id = qs->id; 5847 frame->u.stream.stream_id = qs->id;
5779 frame->u.stream.offset = c->sent; 5848 frame->u.stream.offset = c->sent;
5780 frame->u.stream.length = n; 5849 frame->u.stream.length = n;
5781 frame->u.stream.data = frame->data;
5782 5850
5783 c->sent += n; 5851 c->sent += n;
5784 qc->streams.sent += n; 5852 qc->streams.sent += n;
5785 max_flow -= n; 5853 max_flow -= n;
5786 5854
5791 #if (NGX_DEBUG) 5859 #if (NGX_DEBUG)
5792 sent += n; 5860 sent += n;
5793 nframes++; 5861 nframes++;
5794 #endif 5862 #endif
5795 5863
5796 for (p = frame->data; n > 0; cl = cl->next) { 5864 frame->data = ngx_quic_copy_chain(pc, cl, n);
5797 b = cl->buf; 5865 if (frame->data == NGX_CHAIN_ERROR) {
5798 5866 return NGX_CHAIN_ERROR;
5799 if (!ngx_buf_in_memory(b)) {
5800 continue;
5801 }
5802
5803 len = ngx_min(n, (size_t) (b->last - b->pos));
5804 p = ngx_cpymem(p, b->pos, len);
5805
5806 b->pos += len;
5807 n -= len;
5808 } 5867 }
5809 5868
5810 ngx_quic_queue_frame(qc, frame); 5869 ngx_quic_queue_frame(qc, frame);
5811 } 5870 }
5812 5871
5914 5973
5915 if ((qs->id & NGX_QUIC_STREAM_SERVER_INITIATED) == 0 5974 if ((qs->id & NGX_QUIC_STREAM_SERVER_INITIATED) == 0
5916 || (qs->id & NGX_QUIC_STREAM_UNIDIRECTIONAL) == 0) 5975 || (qs->id & NGX_QUIC_STREAM_UNIDIRECTIONAL) == 0)
5917 { 5976 {
5918 if (!c->read->pending_eof && !c->read->error) { 5977 if (!c->read->pending_eof && !c->read->error) {
5919 frame = ngx_quic_alloc_frame(pc, 0); 5978 frame = ngx_quic_alloc_frame(pc);
5920 if (frame == NULL) { 5979 if (frame == NULL) {
5921 return; 5980 return;
5922 } 5981 }
5923 5982
5924 frame->level = ssl_encryption_application; 5983 frame->level = ssl_encryption_application;
5929 ngx_quic_queue_frame(qc, frame); 5988 ngx_quic_queue_frame(qc, frame);
5930 } 5989 }
5931 } 5990 }
5932 5991
5933 if ((qs->id & NGX_QUIC_STREAM_SERVER_INITIATED) == 0) { 5992 if ((qs->id & NGX_QUIC_STREAM_SERVER_INITIATED) == 0) {
5934 frame = ngx_quic_alloc_frame(pc, 0); 5993 frame = ngx_quic_alloc_frame(pc);
5935 if (frame == NULL) { 5994 if (frame == NULL) {
5936 return; 5995 return;
5937 } 5996 }
5938 5997
5939 frame->level = ssl_encryption_application; 5998 frame->level = ssl_encryption_application;
5957 } 6016 }
5958 6017
5959 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, 6018 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
5960 "quic stream id:0x%xL send fin", qs->id); 6019 "quic stream id:0x%xL send fin", qs->id);
5961 6020
5962 frame = ngx_quic_alloc_frame(pc, 0); 6021 frame = ngx_quic_alloc_frame(pc);
5963 if (frame == NULL) { 6022 if (frame == NULL) {
5964 return; 6023 return;
5965 } 6024 }
5966 6025
5967 frame->level = ssl_encryption_application; 6026 frame->level = ssl_encryption_application;
5972 6031
5973 frame->u.stream.type = frame->type; 6032 frame->u.stream.type = frame->type;
5974 frame->u.stream.stream_id = qs->id; 6033 frame->u.stream.stream_id = qs->id;
5975 frame->u.stream.offset = c->sent; 6034 frame->u.stream.offset = c->sent;
5976 frame->u.stream.length = 0; 6035 frame->u.stream.length = 0;
5977 frame->u.stream.data = NULL;
5978 6036
5979 ngx_quic_queue_frame(qc, frame); 6037 ngx_quic_queue_frame(qc, frame);
5980 6038
5981 (void) ngx_quic_output(pc); 6039 (void) ngx_quic_output(pc);
5982 } 6040 }
5983 6041
5984 6042
5985 static ngx_quic_frame_t * 6043 static ngx_quic_frame_t *
5986 ngx_quic_alloc_frame(ngx_connection_t *c, size_t size) 6044 ngx_quic_alloc_frame(ngx_connection_t *c)
5987 { 6045 {
5988 u_char *p;
5989 ngx_queue_t *q; 6046 ngx_queue_t *q;
5990 ngx_quic_frame_t *frame; 6047 ngx_quic_frame_t *frame;
5991 ngx_quic_connection_t *qc; 6048 ngx_quic_connection_t *qc;
5992 6049
5993 if (size) {
5994 p = ngx_alloc(size, c->log);
5995 if (p == NULL) {
5996 return NULL;
5997 }
5998
5999 } else {
6000 p = NULL;
6001 }
6002
6003 qc = ngx_quic_get_connection(c); 6050 qc = ngx_quic_get_connection(c);
6004 6051
6005 if (!ngx_queue_empty(&qc->free_frames)) { 6052 if (!ngx_queue_empty(&qc->free_frames)) {
6006 6053
6007 q = ngx_queue_head(&qc->free_frames); 6054 q = ngx_queue_head(&qc->free_frames);
6008 frame = ngx_queue_data(q, ngx_quic_frame_t, queue); 6055 frame = ngx_queue_data(q, ngx_quic_frame_t, queue);
6009 6056
6010 ngx_queue_remove(&frame->queue); 6057 ngx_queue_remove(&frame->queue);
6011 6058
6012 #ifdef NGX_QUIC_DEBUG_FRAMES_ALLOC 6059 #ifdef NGX_QUIC_DEBUG_ALLOC
6013 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, 6060 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
6014 "quic reuse frame n:%ui", qc->nframes); 6061 "quic reuse frame n:%ui", qc->nframes);
6015 #endif 6062 #endif
6016 6063
6017 } else { 6064 } else {
6018 frame = ngx_pcalloc(c->pool, sizeof(ngx_quic_frame_t)); 6065 frame = ngx_pcalloc(c->pool, sizeof(ngx_quic_frame_t));
6019 if (frame == NULL) { 6066 if (frame == NULL) {
6020 ngx_free(p);
6021 return NULL; 6067 return NULL;
6022 } 6068 }
6023 6069
6024 #if (NGX_DEBUG) 6070 #ifdef NGX_QUIC_DEBUG_ALLOC
6025 ++qc->nframes; 6071 ++qc->nframes;
6026 #endif 6072
6027
6028 #ifdef NGX_QUIC_DEBUG_FRAMES_ALLOC
6029 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, 6073 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
6030 "quic alloc frame n:%ui", qc->nframes); 6074 "quic alloc frame n:%ui", qc->nframes);
6031 #endif 6075 #endif
6032 } 6076 }
6033 6077
6034 ngx_memzero(frame, sizeof(ngx_quic_frame_t)); 6078 ngx_memzero(frame, sizeof(ngx_quic_frame_t));
6035
6036 frame->data = p;
6037 6079
6038 return frame; 6080 return frame;
6039 } 6081 }
6040 6082
6041 6083
6138 ngx_quic_connection_t *qc; 6180 ngx_quic_connection_t *qc;
6139 6181
6140 qc = ngx_quic_get_connection(c); 6182 qc = ngx_quic_get_connection(c);
6141 6183
6142 if (frame->data) { 6184 if (frame->data) {
6143 ngx_free(frame->data); 6185 ngx_quic_free_bufs(c, frame->data);
6144 frame->data = NULL;
6145 } 6186 }
6146 6187
6147 ngx_queue_insert_head(&qc->free_frames, &frame->queue); 6188 ngx_queue_insert_head(&qc->free_frames, &frame->queue);
6148 6189
6149 #ifdef NGX_QUIC_DEBUG_FRAMES_ALLOC 6190 #ifdef NGX_QUIC_DEBUG_ALLOC
6150 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, 6191 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
6151 "quic free frame n:%ui", qc->nframes); 6192 "quic free frame n:%ui", qc->nframes);
6152 #endif 6193 #endif
6153 } 6194 }
6154 6195
6163 6204
6164 version = qc->version; 6205 version = qc->version;
6165 6206
6166 return (version & 0xff000000) == 0xff000000 ? version & 0xff : version; 6207 return (version & 0xff000000) == 0xff000000 ? version & 0xff : version;
6167 } 6208 }
6209
6210
6211 static ngx_chain_t *
6212 ngx_quic_alloc_buf(ngx_connection_t *c)
6213 {
6214 ngx_buf_t *b;
6215 ngx_chain_t *cl;
6216 ngx_quic_connection_t *qc;
6217
6218 qc = ngx_quic_get_connection(c);
6219
6220 if (qc->free_bufs) {
6221 cl = qc->free_bufs;
6222 qc->free_bufs = cl->next;
6223
6224 b = cl->buf;
6225 b->pos = b->start;
6226 b->last = b->start;
6227
6228 #ifdef NGX_QUIC_DEBUG_ALLOC
6229 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
6230 "quic reuse buffer n:%ui", qc->nbufs);
6231 #endif
6232
6233 return cl;
6234 }
6235
6236 cl = ngx_alloc_chain_link(c->pool);
6237 if (cl == NULL) {
6238 return NULL;
6239 }
6240
6241 b = ngx_create_temp_buf(c->pool, NGX_QUIC_BUFFER_SIZE);
6242 if (b == NULL) {
6243 return NULL;
6244 }
6245
6246 b->tag = (ngx_buf_tag_t) &ngx_quic_alloc_buf;
6247
6248 cl->buf = b;
6249
6250 #ifdef NGX_QUIC_DEBUG_ALLOC
6251 ++qc->nbufs;
6252
6253 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
6254 "quic alloc buffer n:%ui", qc->nbufs);
6255 #endif
6256
6257 return cl;
6258 }
6259
6260
6261 static void
6262 ngx_quic_free_bufs(ngx_connection_t *c, ngx_chain_t *in)
6263 {
6264 ngx_chain_t *cl;
6265 ngx_quic_connection_t *qc;
6266
6267 qc = ngx_quic_get_connection(c);
6268
6269 while (in) {
6270 #ifdef NGX_QUIC_DEBUG_ALLOC
6271 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
6272 "quic free buffer n:%ui", qc->nbufs);
6273 #endif
6274
6275 cl = in;
6276 in = in->next;
6277
6278 cl->next = qc->free_bufs;
6279 qc->free_bufs = cl;
6280 }
6281 }
6282
6283
6284 static ngx_chain_t *
6285 ngx_quic_copy_buf(ngx_connection_t *c, u_char *data, size_t len)
6286 {
6287 size_t n;
6288 ngx_buf_t *b;
6289 ngx_chain_t *cl, *out, **ll;
6290
6291 out = NULL;
6292 ll = &out;
6293
6294 while (len) {
6295 cl = ngx_quic_alloc_buf(c);
6296 if (cl == NULL) {
6297 return NGX_CHAIN_ERROR;
6298 }
6299
6300 b = cl->buf;
6301 n = ngx_min((size_t) (b->end - b->last), len);
6302
6303 b->last = ngx_cpymem(b->last, data, n);
6304
6305 data += n;
6306 len -= n;
6307
6308 *ll = cl;
6309 ll = &cl->next;
6310 }
6311
6312 *ll = NULL;
6313
6314 return out;
6315 }
6316
6317
6318 static ngx_chain_t *
6319 ngx_quic_copy_chain(ngx_connection_t *c, ngx_chain_t *in, size_t limit)
6320 {
6321 size_t n;
6322 ngx_buf_t *b;
6323 ngx_chain_t *cl, *out, **ll;
6324
6325 out = NULL;
6326 ll = &out;
6327
6328 while (in) {
6329 if (!ngx_buf_in_memory(in->buf) || ngx_buf_size(in->buf) == 0) {
6330 in = in->next;
6331 continue;
6332 }
6333
6334 cl = ngx_quic_alloc_buf(c);
6335 if (cl == NULL) {
6336 return NGX_CHAIN_ERROR;
6337 }
6338
6339 *ll = cl;
6340 ll = &cl->next;
6341
6342 b = cl->buf;
6343
6344 while (in && b->last != b->end) {
6345
6346 n = ngx_min(in->buf->last - in->buf->pos, b->end - b->last);
6347
6348 if (limit > 0 && n > limit) {
6349 n = limit;
6350 }
6351
6352 b->last = ngx_cpymem(b->last, in->buf->pos, n);
6353
6354 in->buf->pos += n;
6355 if (in->buf->pos == in->buf->last) {
6356 in = in->next;
6357 }
6358
6359 if (limit > 0) {
6360 if (limit == n) {
6361 goto done;
6362 }
6363
6364 limit -= n;
6365 }
6366 }
6367
6368 }
6369
6370 done:
6371
6372 *ll = NULL;
6373
6374 return out;
6375 }