comparison src/event/ngx_event_quic.c @ 7842: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
7841:eee307399229 7842: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