comparison src/event/ngx_event_quic.c @ 8496:c5324bb3a704 quic

QUIC: limited the number of client-initiated streams. The limits on active bidi and uni client streams are maintained at their initial values initial_max_streams_bidi and initial_max_streams_uni by sending a MAX_STREAMS frame upon each client stream closure. Also, the following is changed for data arriving to non-existing streams: - if a stream was already closed, such data is ignored - when creating a new stream, all streams of the same type with lower ids are created too
author Roman Arutyunyan <arut@nginx.com>
date Mon, 27 Jul 2020 19:15:17 +0300
parents 455a8536eaa7
children b0e74a54c98b
comparison
equal deleted inserted replaced
8495:455a8536eaa7 8496:c5324bb3a704
46 46
47 uint64_t server_max_streams_uni; 47 uint64_t server_max_streams_uni;
48 uint64_t server_max_streams_bidi; 48 uint64_t server_max_streams_bidi;
49 uint64_t server_streams_uni; 49 uint64_t server_streams_uni;
50 uint64_t server_streams_bidi; 50 uint64_t server_streams_bidi;
51
52 uint64_t client_max_streams_uni;
53 uint64_t client_max_streams_bidi;
54 uint64_t client_streams_uni;
55 uint64_t client_streams_bidi;
51 } ngx_quic_streams_t; 56 } ngx_quic_streams_t;
52 57
53 58
54 typedef struct { 59 typedef struct {
55 size_t in_flight; 60 size_t in_flight;
119 #endif 124 #endif
120 125
121 ngx_quic_streams_t streams; 126 ngx_quic_streams_t streams;
122 ngx_quic_congestion_t congestion; 127 ngx_quic_congestion_t congestion;
123 size_t received; 128 size_t received;
124
125 uint64_t cur_streams;
126 uint64_t max_streams;
127 129
128 ngx_uint_t error; 130 ngx_uint_t error;
129 enum ssl_encryption_level_t error_level; 131 enum ssl_encryption_level_t error_level;
130 ngx_uint_t error_ftype; 132 ngx_uint_t error_ftype;
131 const char *error_reason; 133 const char *error_reason;
231 static ngx_int_t ngx_quic_handle_stream_frame(ngx_connection_t *c, 233 static ngx_int_t ngx_quic_handle_stream_frame(ngx_connection_t *c,
232 ngx_quic_header_t *pkt, ngx_quic_frame_t *frame); 234 ngx_quic_header_t *pkt, ngx_quic_frame_t *frame);
233 static ngx_int_t ngx_quic_stream_input(ngx_connection_t *c, 235 static ngx_int_t ngx_quic_stream_input(ngx_connection_t *c,
234 ngx_quic_frame_t *frame, void *data); 236 ngx_quic_frame_t *frame, void *data);
235 237
236 static ngx_int_t ngx_quic_handle_max_streams(ngx_connection_t *c);
237 static ngx_int_t ngx_quic_handle_max_data_frame(ngx_connection_t *c, 238 static ngx_int_t ngx_quic_handle_max_data_frame(ngx_connection_t *c,
238 ngx_quic_max_data_frame_t *f); 239 ngx_quic_max_data_frame_t *f);
239 static ngx_int_t ngx_quic_handle_streams_blocked_frame(ngx_connection_t *c, 240 static ngx_int_t ngx_quic_handle_streams_blocked_frame(ngx_connection_t *c,
240 ngx_quic_header_t *pkt, ngx_quic_streams_blocked_frame_t *f); 241 ngx_quic_header_t *pkt, ngx_quic_streams_blocked_frame_t *f);
241 static ngx_int_t ngx_quic_handle_stream_data_blocked_frame(ngx_connection_t *c, 242 static ngx_int_t ngx_quic_handle_stream_data_blocked_frame(ngx_connection_t *c,
720 ctp->ack_delay_exponent = NGX_QUIC_DEFAULT_ACK_DELAY_EXPONENT; 721 ctp->ack_delay_exponent = NGX_QUIC_DEFAULT_ACK_DELAY_EXPONENT;
721 ctp->max_ack_delay = NGX_QUIC_DEFAULT_MAX_ACK_DELAY; 722 ctp->max_ack_delay = NGX_QUIC_DEFAULT_MAX_ACK_DELAY;
722 723
723 qc->streams.recv_max_data = qc->tp.initial_max_data; 724 qc->streams.recv_max_data = qc->tp.initial_max_data;
724 725
726 qc->streams.client_max_streams_uni = qc->tp.initial_max_streams_uni;
727 qc->streams.client_max_streams_bidi = qc->tp.initial_max_streams_bidi;
728
725 qc->congestion.window = ngx_min(10 * qc->tp.max_udp_payload_size, 729 qc->congestion.window = ngx_min(10 * qc->tp.max_udp_payload_size,
726 ngx_max(2 * qc->tp.max_udp_payload_size, 730 ngx_max(2 * qc->tp.max_udp_payload_size,
727 14720)); 731 14720));
728 qc->congestion.ssthresh = NGX_MAX_SIZE_T_VALUE; 732 qc->congestion.ssthresh = NGX_MAX_SIZE_T_VALUE;
729 qc->congestion.recovery_start = ngx_current_msec; 733 qc->congestion.recovery_start = ngx_current_msec;
1179 ngx_log_error(NGX_LOG_INFO, c->log, 0, 1183 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1180 "quic SSL_set_quic_early_data_context() failed"); 1184 "quic SSL_set_quic_early_data_context() failed");
1181 return NGX_ERROR; 1185 return NGX_ERROR;
1182 } 1186 }
1183 #endif 1187 #endif
1184
1185 qc->max_streams = qc->tp.initial_max_streams_bidi;
1186 1188
1187 return NGX_OK; 1189 return NGX_OK;
1188 } 1190 }
1189 1191
1190 1192
2883 static ngx_int_t 2885 static ngx_int_t
2884 ngx_quic_handle_stream_frame(ngx_connection_t *c, ngx_quic_header_t *pkt, 2886 ngx_quic_handle_stream_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
2885 ngx_quic_frame_t *frame) 2887 ngx_quic_frame_t *frame)
2886 { 2888 {
2887 size_t n; 2889 size_t n;
2890 uint64_t id;
2888 ngx_buf_t *b; 2891 ngx_buf_t *b;
2889 ngx_event_t *rev; 2892 ngx_event_t *rev;
2890 ngx_quic_stream_t *sn; 2893 ngx_quic_stream_t *sn;
2891 ngx_quic_connection_t *qc; 2894 ngx_quic_connection_t *qc;
2892 ngx_quic_stream_frame_t *f; 2895 ngx_quic_stream_frame_t *f;
2911 if (f->stream_id & NGX_QUIC_STREAM_SERVER_INITIATED) { 2914 if (f->stream_id & NGX_QUIC_STREAM_SERVER_INITIATED) {
2912 qc->error = NGX_QUIC_ERR_STREAM_STATE_ERROR; 2915 qc->error = NGX_QUIC_ERR_STREAM_STATE_ERROR;
2913 return NGX_ERROR; 2916 return NGX_ERROR;
2914 } 2917 }
2915 2918
2916 n = (f->stream_id & NGX_QUIC_STREAM_UNIDIRECTIONAL) 2919 if (f->stream_id & NGX_QUIC_STREAM_UNIDIRECTIONAL) {
2917 ? qc->tp.initial_max_stream_data_uni 2920 if ((f->stream_id >> 2) < qc->streams.client_streams_uni) {
2918 : qc->tp.initial_max_stream_data_bidi_remote; 2921 return NGX_OK;
2922 }
2923
2924 if ((f->stream_id >> 2) >= qc->streams.client_max_streams_uni) {
2925 qc->error = NGX_QUIC_ERR_STREAM_LIMIT_ERROR;
2926 return NGX_ERROR;
2927 }
2928
2929 id = (qc->streams.client_streams_uni << 2)
2930 | NGX_QUIC_STREAM_UNIDIRECTIONAL;
2931 qc->streams.client_streams_uni = (f->stream_id >> 2) + 1;
2932 n = qc->tp.initial_max_stream_data_uni;
2933
2934 } else {
2935 if ((f->stream_id >> 2) < qc->streams.client_streams_bidi) {
2936 return NGX_OK;
2937 }
2938
2939 if ((f->stream_id >> 2) >= qc->streams.client_max_streams_bidi) {
2940 qc->error = NGX_QUIC_ERR_STREAM_LIMIT_ERROR;
2941 return NGX_ERROR;
2942 }
2943
2944 id = (qc->streams.client_streams_bidi << 2);
2945 qc->streams.client_streams_bidi = (f->stream_id >> 2) + 1;
2946 n = qc->tp.initial_max_stream_data_bidi_remote;
2947 }
2919 2948
2920 if (n < NGX_QUIC_STREAM_BUFSIZE) { 2949 if (n < NGX_QUIC_STREAM_BUFSIZE) {
2921 n = NGX_QUIC_STREAM_BUFSIZE; 2950 n = NGX_QUIC_STREAM_BUFSIZE;
2922 } 2951 }
2923 2952
2926 "quic no space in stream buffer"); 2955 "quic no space in stream buffer");
2927 return NGX_ERROR; 2956 return NGX_ERROR;
2928 } 2957 }
2929 2958
2930 /* 2959 /*
2931 * TODO: check IDs are increasing ? create all lower-numbered?
2932 *
2933 * 2.1. Stream Types and Identifiers 2960 * 2.1. Stream Types and Identifiers
2934 * 2961 *
2935 * Within each type, streams are created with numerically increasing 2962 * Within each type, streams are created with numerically increasing
2936 * stream IDs. A stream ID that is used out of order results in all 2963 * stream IDs. A stream ID that is used out of order results in all
2937 * streams of that type with lower-numbered stream IDs also being 2964 * streams of that type with lower-numbered stream IDs also being
2938 * opened. 2965 * opened.
2939 */ 2966 */
2940 sn = ngx_quic_create_stream(c, f->stream_id, n); 2967
2941 if (sn == NULL) { 2968 for ( /* void */ ; id <= f->stream_id; id += 0x04) {
2942 return NGX_ERROR; 2969
2943 } 2970 sn = ngx_quic_create_stream(c, id, n);
2944 2971 if (sn == NULL) {
2945 rev = sn->c->read; 2972 return NGX_ERROR;
2946
2947 if (f->offset == 0) {
2948
2949 b = sn->b;
2950 b->last = ngx_cpymem(b->last, f->data, f->length);
2951
2952 sn->fs.received += f->length;
2953
2954 rev->ready = 1;
2955
2956 if (f->fin) {
2957 rev->pending_eof = 1;
2958 } 2973 }
2959 2974
2960 } else { 2975 if (id == f->stream_id && f->offset == 0) {
2961 rev->ready = 0; 2976 b = sn->b;
2962 } 2977 b->last = ngx_cpymem(b->last, f->data, f->length);
2963 2978
2964 if ((f->stream_id & NGX_QUIC_STREAM_UNIDIRECTIONAL) == 0) { 2979 sn->fs.received += f->length;
2965 ngx_quic_handle_max_streams(c); 2980
2966 } 2981 rev = sn->c->read;
2967 2982 rev->ready = 1;
2968 sn->c->listening->handler(sn->c); 2983
2984 if (f->fin) {
2985 rev->pending_eof = 1;
2986 }
2987 }
2988
2989 sn->c->listening->handler(sn->c);
2990 }
2969 2991
2970 if (f->offset == 0) { 2992 if (f->offset == 0) {
2971 return NGX_OK; 2993 return NGX_OK;
2972 } 2994 }
2973 2995
3025 3047
3026 /* check if stream was destroyed by handler */ 3048 /* check if stream was destroyed by handler */
3027 if (ngx_quic_find_stream(&qc->streams.tree, f->stream_id) == NULL) { 3049 if (ngx_quic_find_stream(&qc->streams.tree, f->stream_id) == NULL) {
3028 return NGX_DONE; 3050 return NGX_DONE;
3029 } 3051 }
3030
3031 return NGX_OK;
3032 }
3033
3034
3035 static ngx_int_t
3036 ngx_quic_handle_max_streams(ngx_connection_t *c)
3037 {
3038 ngx_quic_frame_t *frame;
3039 ngx_quic_connection_t *qc;
3040
3041 qc = c->quic;
3042 qc->cur_streams++;
3043
3044 if (qc->cur_streams + NGX_QUIC_STREAMS_INC / 2 < qc->max_streams) {
3045 return NGX_OK;
3046 }
3047
3048 frame = ngx_quic_alloc_frame(c, 0);
3049 if (frame == NULL) {
3050 return NGX_ERROR;
3051 }
3052
3053 qc->max_streams = ngx_max(qc->max_streams + NGX_QUIC_STREAMS_INC,
3054 NGX_QUIC_STREAMS_LIMIT);
3055
3056 frame->level = ssl_encryption_application;
3057 frame->type = NGX_QUIC_FT_MAX_STREAMS;
3058 frame->u.max_streams.limit = qc->max_streams;
3059 frame->u.max_streams.bidi = 1;
3060
3061 ngx_sprintf(frame->info, "MAX_STREAMS limit:%d bidi:%d level=%d",
3062 (int) frame->u.max_streams.limit,
3063 (int) frame->u.max_streams.bidi,
3064 frame->level);
3065
3066 ngx_quic_queue_frame(qc, frame);
3067 3052
3068 return NGX_OK; 3053 return NGX_OK;
3069 } 3054 }
3070 3055
3071 3056
3110 3095
3111 static ngx_int_t 3096 static ngx_int_t
3112 ngx_quic_handle_streams_blocked_frame(ngx_connection_t *c, 3097 ngx_quic_handle_streams_blocked_frame(ngx_connection_t *c,
3113 ngx_quic_header_t *pkt, ngx_quic_streams_blocked_frame_t *f) 3098 ngx_quic_header_t *pkt, ngx_quic_streams_blocked_frame_t *f)
3114 { 3099 {
3115 ngx_quic_frame_t *frame;
3116
3117 frame = ngx_quic_alloc_frame(c, 0);
3118 if (frame == NULL) {
3119 return NGX_ERROR;
3120 }
3121
3122 frame->level = pkt->level;
3123 frame->type = NGX_QUIC_FT_MAX_STREAMS;
3124 frame->u.max_streams.limit = ngx_max(f->limit * 2, NGX_QUIC_STREAMS_LIMIT);
3125 frame->u.max_streams.bidi = f->bidi;
3126
3127 c->quic->max_streams = frame->u.max_streams.limit;
3128
3129 ngx_sprintf(frame->info, "MAX_STREAMS limit:%d bidi:%d level=%d",
3130 (int) frame->u.max_streams.limit,
3131 (int) frame->u.max_streams.bidi,
3132 frame->level);
3133
3134 ngx_quic_queue_frame(c->quic, frame);
3135
3136 return NGX_OK; 3100 return NGX_OK;
3137 } 3101 }
3138 3102
3139 3103
3140 static ngx_int_t 3104 static ngx_int_t
3919 ngx_pool_t *pool; 3883 ngx_pool_t *pool;
3920 ngx_quic_stream_t *sn; 3884 ngx_quic_stream_t *sn;
3921 ngx_pool_cleanup_t *cln; 3885 ngx_pool_cleanup_t *cln;
3922 ngx_quic_connection_t *qc; 3886 ngx_quic_connection_t *qc;
3923 3887
3888 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
3889 "quic stream id 0x%uL create", id);
3890
3924 qc = c->quic; 3891 qc = c->quic;
3925 3892
3926 pool = ngx_create_pool(NGX_DEFAULT_POOL_SIZE, c->log); 3893 pool = ngx_create_pool(NGX_DEFAULT_POOL_SIZE, c->log);
3927 if (pool == NULL) { 3894 if (pool == NULL) {
3928 return NULL; 3895 return NULL;
4255 /* schedule handler call to continue ngx_quic_close_connection() */ 4222 /* schedule handler call to continue ngx_quic_close_connection() */
4256 ngx_post_event(pc->read, &ngx_posted_events); 4223 ngx_post_event(pc->read, &ngx_posted_events);
4257 return; 4224 return;
4258 } 4225 }
4259 4226
4260 if ((qs->id & 0x03) == NGX_QUIC_STREAM_UNIDIRECTIONAL) { 4227 if ((qs->id & NGX_QUIC_STREAM_SERVER_INITIATED) == 0) {
4261 /* do not send fin for client unidirectional streams */ 4228 frame = ngx_quic_alloc_frame(pc, 0);
4262 return; 4229 if (frame == NULL) {
4230 return;
4231 }
4232
4233 frame->level = ssl_encryption_application;
4234 frame->type = NGX_QUIC_FT_MAX_STREAMS;
4235
4236 if (qs->id & NGX_QUIC_STREAM_UNIDIRECTIONAL) {
4237 frame->u.max_streams.limit = ++qc->streams.client_max_streams_uni;
4238 frame->u.max_streams.bidi = 0;
4239
4240 } else {
4241 frame->u.max_streams.limit = ++qc->streams.client_max_streams_bidi;
4242 frame->u.max_streams.bidi = 1;
4243 }
4244
4245 ngx_sprintf(frame->info, "MAX_STREAMS limit:%uL bidi:%ui level=%d",
4246 frame->u.max_streams.limit,
4247 frame->u.max_streams.bidi,
4248 (int) frame->level);
4249
4250 ngx_quic_queue_frame(qc, frame);
4251
4252 if (qs->id & NGX_QUIC_STREAM_UNIDIRECTIONAL) {
4253 /* do not send fin for client unidirectional streams */
4254 return;
4255 }
4263 } 4256 }
4264 4257
4265 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, 4258 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
4266 "quic stream id 0x%xL send fin", qs->id); 4259 "quic stream id 0x%xL send fin", qs->id);
4267 4260