Mercurial > hg > nginx
comparison src/event/ngx_event_quic.c @ 8365:fab75acb1f72 quic
Respect MAX_DATA and MAX_STREAM_DATA from QUIC client.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Tue, 28 Apr 2020 16:37:32 +0300 |
parents | eee307399229 |
children | c10e7d48aa85 |
comparison
equal
deleted
inserted
replaced
8364:eee307399229 | 8365:fab75acb1f72 |
---|---|
46 ngx_rbtree_node_t sentinel; | 46 ngx_rbtree_node_t sentinel; |
47 ngx_connection_handler_pt handler; | 47 ngx_connection_handler_pt handler; |
48 | 48 |
49 ngx_uint_t id_counter; | 49 ngx_uint_t id_counter; |
50 | 50 |
51 uint64_t total_received; | 51 uint64_t received; |
52 uint64_t max_data; | 52 uint64_t sent; |
53 uint64_t recv_max_data; | |
54 uint64_t send_max_data; | |
53 } ngx_quic_streams_t; | 55 } ngx_quic_streams_t; |
54 | 56 |
55 | 57 |
56 typedef struct { | 58 typedef struct { |
57 size_t in_flight; | 59 size_t in_flight; |
110 ngx_uint_t nframes; | 112 ngx_uint_t nframes; |
111 #endif | 113 #endif |
112 | 114 |
113 ngx_quic_streams_t streams; | 115 ngx_quic_streams_t streams; |
114 ngx_quic_congestion_t congestion; | 116 ngx_quic_congestion_t congestion; |
115 ngx_uint_t max_data; | |
116 | 117 |
117 uint64_t cur_streams; | 118 uint64_t cur_streams; |
118 uint64_t max_streams; | 119 uint64_t max_streams; |
119 | 120 |
120 unsigned send_timer_set:1; | 121 unsigned send_timer_set:1; |
199 ngx_quic_header_t *pkt, ngx_quic_frame_t *frame); | 200 ngx_quic_header_t *pkt, ngx_quic_frame_t *frame); |
200 static ngx_int_t ngx_quic_stream_input(ngx_connection_t *c, | 201 static ngx_int_t ngx_quic_stream_input(ngx_connection_t *c, |
201 ngx_quic_frame_t *frame); | 202 ngx_quic_frame_t *frame); |
202 | 203 |
203 static ngx_int_t ngx_quic_handle_max_streams(ngx_connection_t *c); | 204 static ngx_int_t ngx_quic_handle_max_streams(ngx_connection_t *c); |
205 static ngx_int_t ngx_quic_handle_max_data_frame(ngx_connection_t *c, | |
206 ngx_quic_max_data_frame_t *f); | |
204 static ngx_int_t ngx_quic_handle_streams_blocked_frame(ngx_connection_t *c, | 207 static ngx_int_t ngx_quic_handle_streams_blocked_frame(ngx_connection_t *c, |
205 ngx_quic_header_t *pkt, ngx_quic_streams_blocked_frame_t *f); | 208 ngx_quic_header_t *pkt, ngx_quic_streams_blocked_frame_t *f); |
206 static ngx_int_t ngx_quic_handle_stream_data_blocked_frame(ngx_connection_t *c, | 209 static ngx_int_t ngx_quic_handle_stream_data_blocked_frame(ngx_connection_t *c, |
207 ngx_quic_header_t *pkt, ngx_quic_stream_data_blocked_frame_t *f); | 210 ngx_quic_header_t *pkt, ngx_quic_stream_data_blocked_frame_t *f); |
211 static ngx_int_t ngx_quic_handle_max_stream_data_frame(ngx_connection_t *c, | |
212 ngx_quic_header_t *pkt, ngx_quic_max_stream_data_frame_t *f); | |
208 | 213 |
209 static void ngx_quic_queue_frame(ngx_quic_connection_t *qc, | 214 static void ngx_quic_queue_frame(ngx_quic_connection_t *qc, |
210 ngx_quic_frame_t *frame); | 215 ngx_quic_frame_t *frame); |
211 | 216 |
212 static ngx_int_t ngx_quic_output(ngx_connection_t *c); | 217 static ngx_int_t ngx_quic_output(ngx_connection_t *c); |
597 ctp = &qc->ctp; | 602 ctp = &qc->ctp; |
598 ctp->max_packet_size = NGX_QUIC_DEFAULT_MAX_PACKET_SIZE; | 603 ctp->max_packet_size = NGX_QUIC_DEFAULT_MAX_PACKET_SIZE; |
599 ctp->ack_delay_exponent = NGX_QUIC_DEFAULT_ACK_DELAY_EXPONENT; | 604 ctp->ack_delay_exponent = NGX_QUIC_DEFAULT_ACK_DELAY_EXPONENT; |
600 ctp->max_ack_delay = NGX_QUIC_DEFAULT_MAX_ACK_DELAY; | 605 ctp->max_ack_delay = NGX_QUIC_DEFAULT_MAX_ACK_DELAY; |
601 | 606 |
602 qc->streams.max_data = qc->tp.initial_max_data; | 607 qc->streams.recv_max_data = qc->tp.initial_max_data; |
603 | 608 |
604 qc->congestion.window = ngx_min(10 * qc->tp.max_packet_size, | 609 qc->congestion.window = ngx_min(10 * qc->tp.max_packet_size, |
605 ngx_max(2 * qc->tp.max_packet_size, 14720)); | 610 ngx_max(2 * qc->tp.max_packet_size, 14720)); |
606 qc->congestion.ssthresh = NGX_MAX_SIZE_T_VALUE; | 611 qc->congestion.ssthresh = NGX_MAX_SIZE_T_VALUE; |
607 qc->congestion.recovery_start = ngx_current_msec; | 612 qc->congestion.recovery_start = ngx_current_msec; |
1414 | 1419 |
1415 ack_this = 1; | 1420 ack_this = 1; |
1416 break; | 1421 break; |
1417 | 1422 |
1418 case NGX_QUIC_FT_MAX_DATA: | 1423 case NGX_QUIC_FT_MAX_DATA: |
1419 c->quic->max_data = frame.u.max_data.max_data; | 1424 |
1425 if (ngx_quic_handle_max_data_frame(c, &frame.u.max_data) != NGX_OK) | |
1426 { | |
1427 return NGX_ERROR; | |
1428 } | |
1429 | |
1420 ack_this = 1; | 1430 ack_this = 1; |
1421 break; | 1431 break; |
1422 | 1432 |
1423 case NGX_QUIC_FT_STREAMS_BLOCKED: | 1433 case NGX_QUIC_FT_STREAMS_BLOCKED: |
1424 case NGX_QUIC_FT_STREAMS_BLOCKED2: | 1434 case NGX_QUIC_FT_STREAMS_BLOCKED2: |
1435 | 1445 |
1436 case NGX_QUIC_FT_STREAM_DATA_BLOCKED: | 1446 case NGX_QUIC_FT_STREAM_DATA_BLOCKED: |
1437 | 1447 |
1438 if (ngx_quic_handle_stream_data_blocked_frame(c, pkt, | 1448 if (ngx_quic_handle_stream_data_blocked_frame(c, pkt, |
1439 &frame.u.stream_data_blocked) | 1449 &frame.u.stream_data_blocked) |
1450 != NGX_OK) | |
1451 { | |
1452 return NGX_ERROR; | |
1453 } | |
1454 | |
1455 ack_this = 1; | |
1456 break; | |
1457 | |
1458 case NGX_QUIC_FT_MAX_STREAM_DATA: | |
1459 | |
1460 if (ngx_quic_handle_max_stream_data_frame(c, pkt, | |
1461 &frame.u.max_stream_data) | |
1440 != NGX_OK) | 1462 != NGX_OK) |
1441 { | 1463 { |
1442 return NGX_ERROR; | 1464 return NGX_ERROR; |
1443 } | 1465 } |
1444 | 1466 |
1450 case NGX_QUIC_FT_NEW_TOKEN: | 1472 case NGX_QUIC_FT_NEW_TOKEN: |
1451 case NGX_QUIC_FT_RESET_STREAM: | 1473 case NGX_QUIC_FT_RESET_STREAM: |
1452 case NGX_QUIC_FT_STOP_SENDING: | 1474 case NGX_QUIC_FT_STOP_SENDING: |
1453 case NGX_QUIC_FT_PATH_CHALLENGE: | 1475 case NGX_QUIC_FT_PATH_CHALLENGE: |
1454 case NGX_QUIC_FT_PATH_RESPONSE: | 1476 case NGX_QUIC_FT_PATH_RESPONSE: |
1455 case NGX_QUIC_FT_MAX_STREAM_DATA: | |
1456 | 1477 |
1457 /* TODO: handle */ | 1478 /* TODO: handle */ |
1458 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, | 1479 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, |
1459 "quic frame handler not implemented"); | 1480 "quic frame handler not implemented"); |
1460 ack_this = 1; | 1481 ack_this = 1; |
2206 return NGX_OK; | 2227 return NGX_OK; |
2207 } | 2228 } |
2208 | 2229 |
2209 | 2230 |
2210 static ngx_int_t | 2231 static ngx_int_t |
2232 ngx_quic_handle_max_data_frame(ngx_connection_t *c, | |
2233 ngx_quic_max_data_frame_t *f) | |
2234 { | |
2235 ngx_event_t *wev; | |
2236 ngx_rbtree_t *tree; | |
2237 ngx_rbtree_node_t *node; | |
2238 ngx_quic_stream_t *qs; | |
2239 ngx_quic_connection_t *qc; | |
2240 | |
2241 qc = c->quic; | |
2242 tree = &qc->streams.tree; | |
2243 | |
2244 if (f->max_data <= qc->streams.send_max_data) { | |
2245 return NGX_OK; | |
2246 } | |
2247 | |
2248 if (qc->streams.sent >= qc->streams.send_max_data) { | |
2249 | |
2250 for (node = ngx_rbtree_min(tree->root, tree->sentinel); | |
2251 node; | |
2252 node = ngx_rbtree_next(tree, node)) | |
2253 { | |
2254 qs = (ngx_quic_stream_t *) node; | |
2255 wev = qs->c->write; | |
2256 | |
2257 if (wev->active) { | |
2258 wev->ready = 1; | |
2259 ngx_post_event(wev, &ngx_posted_events); | |
2260 } | |
2261 } | |
2262 } | |
2263 | |
2264 qc->streams.send_max_data = f->max_data; | |
2265 | |
2266 return NGX_OK; | |
2267 } | |
2268 | |
2269 | |
2270 static ngx_int_t | |
2211 ngx_quic_handle_streams_blocked_frame(ngx_connection_t *c, | 2271 ngx_quic_handle_streams_blocked_frame(ngx_connection_t *c, |
2212 ngx_quic_header_t *pkt, ngx_quic_streams_blocked_frame_t *f) | 2272 ngx_quic_header_t *pkt, ngx_quic_streams_blocked_frame_t *f) |
2213 { | 2273 { |
2214 ngx_quic_frame_t *frame; | 2274 ngx_quic_frame_t *frame; |
2215 | 2275 |
2272 (int) frame->u.max_stream_data.id, | 2332 (int) frame->u.max_stream_data.id, |
2273 (int) frame->u.max_stream_data.limit, | 2333 (int) frame->u.max_stream_data.limit, |
2274 frame->level); | 2334 frame->level); |
2275 | 2335 |
2276 ngx_quic_queue_frame(c->quic, frame); | 2336 ngx_quic_queue_frame(c->quic, frame); |
2337 | |
2338 return NGX_OK; | |
2339 } | |
2340 | |
2341 | |
2342 static ngx_int_t | |
2343 ngx_quic_handle_max_stream_data_frame(ngx_connection_t *c, | |
2344 ngx_quic_header_t *pkt, ngx_quic_max_stream_data_frame_t *f) | |
2345 { | |
2346 uint64_t sent; | |
2347 ngx_event_t *wev; | |
2348 ngx_quic_stream_t *sn; | |
2349 ngx_quic_connection_t *qc; | |
2350 | |
2351 qc = c->quic; | |
2352 sn = ngx_quic_find_stream(&qc->streams.tree, f->id); | |
2353 | |
2354 if (sn == NULL) { | |
2355 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unknown stream id:%uL", f->id); | |
2356 return NGX_ERROR; | |
2357 } | |
2358 | |
2359 if (f->limit <= sn->send_max_data) { | |
2360 return NGX_OK; | |
2361 } | |
2362 | |
2363 sent = sn->c->sent; | |
2364 | |
2365 if (sent >= sn->send_max_data) { | |
2366 wev = sn->c->write; | |
2367 | |
2368 if (wev->active) { | |
2369 wev->ready = 1; | |
2370 ngx_post_event(wev, &ngx_posted_events); | |
2371 } | |
2372 } | |
2373 | |
2374 sn->send_max_data = f->limit; | |
2277 | 2375 |
2278 return NGX_OK; | 2376 return NGX_OK; |
2279 } | 2377 } |
2280 | 2378 |
2281 | 2379 |
2808 | 2906 |
2809 | 2907 |
2810 static ngx_quic_stream_t * | 2908 static ngx_quic_stream_t * |
2811 ngx_quic_create_stream(ngx_connection_t *c, uint64_t id, size_t rcvbuf_size) | 2909 ngx_quic_create_stream(ngx_connection_t *c, uint64_t id, size_t rcvbuf_size) |
2812 { | 2910 { |
2813 ngx_log_t *log; | 2911 ngx_log_t *log; |
2814 ngx_pool_t *pool; | 2912 ngx_pool_t *pool; |
2815 ngx_quic_stream_t *sn; | 2913 ngx_quic_stream_t *sn; |
2816 ngx_pool_cleanup_t *cln; | 2914 ngx_pool_cleanup_t *cln; |
2915 ngx_quic_connection_t *qc; | |
2916 | |
2917 qc = c->quic; | |
2817 | 2918 |
2818 pool = ngx_create_pool(NGX_DEFAULT_POOL_SIZE, c->log); | 2919 pool = ngx_create_pool(NGX_DEFAULT_POOL_SIZE, c->log); |
2819 if (pool == NULL) { | 2920 if (pool == NULL) { |
2820 return NULL; | 2921 return NULL; |
2821 } | 2922 } |
2875 || (id & NGX_QUIC_STREAM_SERVER_INITIATED)) | 2976 || (id & NGX_QUIC_STREAM_SERVER_INITIATED)) |
2876 { | 2977 { |
2877 sn->c->write->ready = 1; | 2978 sn->c->write->ready = 1; |
2878 } | 2979 } |
2879 | 2980 |
2981 if (id & NGX_QUIC_STREAM_UNIDIRECTIONAL) { | |
2982 if (id & NGX_QUIC_STREAM_SERVER_INITIATED) { | |
2983 sn->send_max_data = qc->ctp.initial_max_stream_data_uni; | |
2984 } | |
2985 | |
2986 } else { | |
2987 if (id & NGX_QUIC_STREAM_SERVER_INITIATED) { | |
2988 sn->send_max_data = qc->ctp.initial_max_stream_data_bidi_remote; | |
2989 } else { | |
2990 sn->send_max_data = qc->ctp.initial_max_stream_data_bidi_local; | |
2991 } | |
2992 } | |
2993 | |
2880 cln = ngx_pool_cleanup_add(pool, 0); | 2994 cln = ngx_pool_cleanup_add(pool, 0); |
2881 if (cln == NULL) { | 2995 if (cln == NULL) { |
2882 ngx_close_connection(sn->c); | 2996 ngx_close_connection(sn->c); |
2883 ngx_destroy_pool(pool); | 2997 ngx_destroy_pool(pool); |
2884 return NULL; | 2998 return NULL; |
2930 len = ngx_min(b->last - b->pos, (ssize_t) size); | 3044 len = ngx_min(b->last - b->pos, (ssize_t) size); |
2931 | 3045 |
2932 ngx_memcpy(buf, b->pos, len); | 3046 ngx_memcpy(buf, b->pos, len); |
2933 | 3047 |
2934 b->pos += len; | 3048 b->pos += len; |
2935 qc->streams.total_received += len; | 3049 qc->streams.received += len; |
2936 | 3050 |
2937 if (b->pos == b->last) { | 3051 if (b->pos == b->last) { |
2938 b->pos = b->start; | 3052 b->pos = b->start; |
2939 b->last = b->start; | 3053 b->last = b->start; |
2940 rev->ready = rev->pending_eof; | 3054 rev->ready = rev->pending_eof; |
2961 frame->level); | 3075 frame->level); |
2962 | 3076 |
2963 ngx_quic_queue_frame(pc->quic, frame); | 3077 ngx_quic_queue_frame(pc->quic, frame); |
2964 } | 3078 } |
2965 | 3079 |
2966 if ((qc->streams.max_data / 2) < qc->streams.total_received) { | 3080 if ((qc->streams.recv_max_data / 2) < qc->streams.received) { |
2967 | 3081 |
2968 frame = ngx_quic_alloc_frame(pc, 0); | 3082 frame = ngx_quic_alloc_frame(pc, 0); |
2969 | 3083 |
2970 if (frame == NULL) { | 3084 if (frame == NULL) { |
2971 return NGX_ERROR; | 3085 return NGX_ERROR; |
2972 } | 3086 } |
2973 | 3087 |
2974 qc->streams.max_data *= 2; | 3088 qc->streams.recv_max_data *= 2; |
2975 | 3089 |
2976 frame->level = ssl_encryption_application; | 3090 frame->level = ssl_encryption_application; |
2977 frame->type = NGX_QUIC_FT_MAX_DATA; | 3091 frame->type = NGX_QUIC_FT_MAX_DATA; |
2978 frame->u.max_data.max_data = qc->streams.max_data; | 3092 frame->u.max_data.max_data = qc->streams.recv_max_data; |
2979 | 3093 |
2980 ngx_sprintf(frame->info, "MAX_DATA max_data:%d level=%d on recv", | 3094 ngx_sprintf(frame->info, "MAX_DATA max_data:%d level=%d on recv", |
2981 (int) frame->u.max_data.max_data, frame->level); | 3095 (int) frame->u.max_data.max_data, frame->level); |
2982 | 3096 |
2983 ngx_quic_queue_frame(pc->quic, frame); | 3097 ngx_quic_queue_frame(pc->quic, frame); |
2984 | 3098 |
2985 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, | 3099 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, |
2986 "quic stream id 0x%xi recv: increased max data: %ui", | 3100 "quic stream id 0x%xi recv: increased max data: %ui", |
2987 qs->id, qc->streams.max_data); | 3101 qs->id, qc->streams.recv_max_data); |
2988 } | 3102 } |
2989 | 3103 |
2990 return len; | 3104 return len; |
2991 } | 3105 } |
2992 | 3106 |
3022 | 3136 |
3023 len = size; | 3137 len = size; |
3024 sent = c->sent; | 3138 sent = c->sent; |
3025 unacked = sent - qs->acked; | 3139 unacked = sent - qs->acked; |
3026 | 3140 |
3141 if (qc->streams.send_max_data == 0) { | |
3142 qc->streams.send_max_data = qc->ctp.initial_max_data; | |
3143 } | |
3144 | |
3027 if (unacked >= NGX_QUIC_STREAM_BUFSIZE) { | 3145 if (unacked >= NGX_QUIC_STREAM_BUFSIZE) { |
3028 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, | 3146 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, |
3029 "quic send hit buffer size"); | 3147 "quic send hit buffer size"); |
3030 len = 0; | 3148 len = 0; |
3031 | 3149 |
3032 } else if (unacked + len > NGX_QUIC_STREAM_BUFSIZE) { | 3150 } else if (unacked + len > NGX_QUIC_STREAM_BUFSIZE) { |
3033 len = NGX_QUIC_STREAM_BUFSIZE - unacked; | 3151 len = NGX_QUIC_STREAM_BUFSIZE - unacked; |
3152 } | |
3153 | |
3154 if (qc->streams.sent >= qc->streams.send_max_data) { | |
3155 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
3156 "quic send hit MAX_DATA"); | |
3157 len = 0; | |
3158 | |
3159 } else if (qc->streams.sent + len > qc->streams.send_max_data) { | |
3160 len = qc->streams.send_max_data - qc->streams.sent; | |
3161 } | |
3162 | |
3163 if (sent >= qs->send_max_data) { | |
3164 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
3165 "quic send hit MAX_STREAM_DATA"); | |
3166 len = 0; | |
3167 | |
3168 } else if (sent + len > qs->send_max_data) { | |
3169 len = qs->send_max_data - sent; | |
3034 } | 3170 } |
3035 | 3171 |
3036 p = (u_char *) buf; | 3172 p = (u_char *) buf; |
3037 end = (u_char *) buf + len; | 3173 end = (u_char *) buf + len; |
3038 n = 0; | 3174 n = 0; |
3059 frame->u.stream.offset = c->sent; | 3195 frame->u.stream.offset = c->sent; |
3060 frame->u.stream.length = fsize; | 3196 frame->u.stream.length = fsize; |
3061 frame->u.stream.data = frame->data; | 3197 frame->u.stream.data = frame->data; |
3062 | 3198 |
3063 c->sent += fsize; | 3199 c->sent += fsize; |
3200 qc->streams.sent += fsize; | |
3064 p += fsize; | 3201 p += fsize; |
3065 n += fsize; | 3202 n += fsize; |
3066 | 3203 |
3067 ngx_sprintf(frame->info, "stream 0x%xi len=%ui level=%d", | 3204 ngx_sprintf(frame->info, "stream 0x%xi len=%ui level=%d", |
3068 qs->id, fsize, frame->level); | 3205 qs->id, fsize, frame->level); |
3069 | 3206 |
3070 ngx_quic_queue_frame(qc, frame); | 3207 ngx_quic_queue_frame(qc, frame); |
3071 } | 3208 } |
3072 | 3209 |
3073 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, | 3210 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0, |
3074 "quic stream send %uz sent:%O, unacked:%uL", | 3211 "quic send %uz of %uz, sent:%O, unacked:%uL", |
3075 n, c->sent, (uint64_t) c->sent - qs->acked); | 3212 n, size, c->sent, (uint64_t) c->sent - qs->acked); |
3076 | 3213 |
3077 if (n != size) { | 3214 if (n != size) { |
3078 c->write->ready = 0; | 3215 c->write->ready = 0; |
3079 } | 3216 } |
3080 | 3217 |