Mercurial > hg > nginx-quic
comparison src/event/ngx_event_quic.c @ 8241: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
8240:43f3574b3e6f | 8241: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 } |