Mercurial > hg > nginx
comparison src/event/ngx_event_quic.c @ 8504:d277e25e37fc quic
QUIC: create streams for STREAM_DATA_BLOCKED and MAX_STREAM_DATA.
Creating client-initiated streams is moved from ngx_quic_handle_stream_frame()
to a separate function ngx_quic_create_client_stream(). This function is
responsible for creating streams with lower ids as well.
Also, simplified and fixed initial data buffering in
ngx_quic_handle_stream_frame(). It is now done before calling the initial
handler as the handler can destroy the stream.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Tue, 11 Aug 2020 19:10:57 +0300 |
parents | b66a2a041d7e |
children | 240931629995 |
comparison
equal
deleted
inserted
replaced
8503:b66a2a041d7e | 8504:d277e25e37fc |
---|---|
31 /* | 31 /* |
32 * 7.4. Cryptographic Message Buffering | 32 * 7.4. Cryptographic Message Buffering |
33 * Implementations MUST support buffering at least 4096 bytes of data | 33 * Implementations MUST support buffering at least 4096 bytes of data |
34 */ | 34 */ |
35 #define NGX_QUIC_MAX_BUFFERED 65535 | 35 #define NGX_QUIC_MAX_BUFFERED 65535 |
36 | |
37 #define NGX_QUIC_STREAM_GONE (void *) -1 | |
36 | 38 |
37 | 39 |
38 typedef struct { | 40 typedef struct { |
39 ngx_rbtree_t tree; | 41 ngx_rbtree_t tree; |
40 ngx_rbtree_node_t sentinel; | 42 ngx_rbtree_node_t sentinel; |
268 | 270 |
269 static void ngx_quic_rbtree_insert_stream(ngx_rbtree_node_t *temp, | 271 static void ngx_quic_rbtree_insert_stream(ngx_rbtree_node_t *temp, |
270 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); | 272 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); |
271 static ngx_quic_stream_t *ngx_quic_find_stream(ngx_rbtree_t *rbtree, | 273 static ngx_quic_stream_t *ngx_quic_find_stream(ngx_rbtree_t *rbtree, |
272 uint64_t id); | 274 uint64_t id); |
275 static ngx_quic_stream_t *ngx_quic_create_client_stream(ngx_connection_t *c, | |
276 uint64_t id); | |
273 static ngx_quic_stream_t *ngx_quic_create_stream(ngx_connection_t *c, | 277 static ngx_quic_stream_t *ngx_quic_create_stream(ngx_connection_t *c, |
274 uint64_t id, size_t rcvbuf_size); | 278 uint64_t id, size_t rcvbuf_size); |
275 static ssize_t ngx_quic_stream_recv(ngx_connection_t *c, u_char *buf, | 279 static ssize_t ngx_quic_stream_recv(ngx_connection_t *c, u_char *buf, |
276 size_t size); | 280 size_t size); |
277 static ssize_t ngx_quic_stream_send(ngx_connection_t *c, u_char *buf, | 281 static ssize_t ngx_quic_stream_send(ngx_connection_t *c, u_char *buf, |
2891 | 2895 |
2892 static ngx_int_t | 2896 static ngx_int_t |
2893 ngx_quic_handle_stream_frame(ngx_connection_t *c, ngx_quic_header_t *pkt, | 2897 ngx_quic_handle_stream_frame(ngx_connection_t *c, ngx_quic_header_t *pkt, |
2894 ngx_quic_frame_t *frame) | 2898 ngx_quic_frame_t *frame) |
2895 { | 2899 { |
2896 size_t n; | 2900 ngx_pool_t *pool; |
2897 uint64_t id; | 2901 ngx_connection_t *sc; |
2898 ngx_buf_t *b; | |
2899 ngx_event_t *rev; | |
2900 ngx_quic_stream_t *sn; | 2902 ngx_quic_stream_t *sn; |
2901 ngx_quic_connection_t *qc; | 2903 ngx_quic_connection_t *qc; |
2902 ngx_quic_stream_frame_t *f; | 2904 ngx_quic_stream_frame_t *f; |
2903 ngx_quic_frames_stream_t *fs; | 2905 ngx_quic_frames_stream_t *fs; |
2904 | 2906 |
2913 } | 2915 } |
2914 | 2916 |
2915 sn = ngx_quic_find_stream(&qc->streams.tree, f->stream_id); | 2917 sn = ngx_quic_find_stream(&qc->streams.tree, f->stream_id); |
2916 | 2918 |
2917 if (sn == NULL) { | 2919 if (sn == NULL) { |
2918 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | 2920 sn = ngx_quic_create_client_stream(c, f->stream_id); |
2919 "quic stream id 0x%xL is new", f->stream_id); | 2921 |
2920 | 2922 if (sn == NULL) { |
2921 if (f->stream_id & NGX_QUIC_STREAM_SERVER_INITIATED) { | |
2922 qc->error = NGX_QUIC_ERR_STREAM_STATE_ERROR; | |
2923 return NGX_ERROR; | 2923 return NGX_ERROR; |
2924 } | 2924 } |
2925 | 2925 |
2926 if (f->stream_id & NGX_QUIC_STREAM_UNIDIRECTIONAL) { | 2926 if (sn == NGX_QUIC_STREAM_GONE) { |
2927 if ((f->stream_id >> 2) < qc->streams.client_streams_uni) { | 2927 return NGX_OK; |
2928 return NGX_OK; | 2928 } |
2929 } | 2929 |
2930 | 2930 sc = sn->c; |
2931 if ((f->stream_id >> 2) >= qc->streams.client_max_streams_uni) { | 2931 fs = &sn->fs; |
2932 qc->error = NGX_QUIC_ERR_STREAM_LIMIT_ERROR; | 2932 |
2933 return NGX_ERROR; | 2933 if (ngx_quic_handle_ordered_frame(c, fs, frame, ngx_quic_stream_input, |
2934 } | 2934 sn) |
2935 | 2935 != NGX_OK) |
2936 id = (qc->streams.client_streams_uni << 2) | 2936 { |
2937 | NGX_QUIC_STREAM_UNIDIRECTIONAL; | 2937 pool = sc->pool; |
2938 qc->streams.client_streams_uni = (f->stream_id >> 2) + 1; | 2938 |
2939 n = qc->tp.initial_max_stream_data_uni; | 2939 ngx_close_connection(sc); |
2940 | 2940 ngx_destroy_pool(pool); |
2941 } else { | 2941 |
2942 if ((f->stream_id >> 2) < qc->streams.client_streams_bidi) { | |
2943 return NGX_OK; | |
2944 } | |
2945 | |
2946 if ((f->stream_id >> 2) >= qc->streams.client_max_streams_bidi) { | |
2947 qc->error = NGX_QUIC_ERR_STREAM_LIMIT_ERROR; | |
2948 return NGX_ERROR; | |
2949 } | |
2950 | |
2951 id = (qc->streams.client_streams_bidi << 2); | |
2952 qc->streams.client_streams_bidi = (f->stream_id >> 2) + 1; | |
2953 n = qc->tp.initial_max_stream_data_bidi_remote; | |
2954 } | |
2955 | |
2956 if (n < NGX_QUIC_STREAM_BUFSIZE) { | |
2957 n = NGX_QUIC_STREAM_BUFSIZE; | |
2958 } | |
2959 | |
2960 if (n < f->length) { | |
2961 ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
2962 "quic no space in stream buffer"); | |
2963 return NGX_ERROR; | 2942 return NGX_ERROR; |
2964 } | 2943 } |
2965 | 2944 |
2966 /* | 2945 sc->listening->handler(sc); |
2967 * 2.1. Stream Types and Identifiers | 2946 |
2968 * | 2947 return NGX_OK; |
2969 * Within each type, streams are created with numerically increasing | |
2970 * stream IDs. A stream ID that is used out of order results in all | |
2971 * streams of that type with lower-numbered stream IDs also being | |
2972 * opened. | |
2973 */ | |
2974 | |
2975 for ( /* void */ ; id <= f->stream_id; id += 0x04) { | |
2976 | |
2977 sn = ngx_quic_create_stream(c, id, n); | |
2978 if (sn == NULL) { | |
2979 return NGX_ERROR; | |
2980 } | |
2981 | |
2982 if (id == f->stream_id && f->offset == 0) { | |
2983 b = sn->b; | |
2984 b->last = ngx_cpymem(b->last, f->data, f->length); | |
2985 | |
2986 sn->fs.received += f->length; | |
2987 | |
2988 rev = sn->c->read; | |
2989 rev->ready = 1; | |
2990 | |
2991 if (f->fin) { | |
2992 rev->pending_eof = 1; | |
2993 } | |
2994 } | |
2995 | |
2996 sn->c->listening->handler(sn->c); | |
2997 } | |
2998 | |
2999 if (f->offset == 0) { | |
3000 return NGX_OK; | |
3001 } | |
3002 | |
3003 /* out-of-order stream: proceed to buffering */ | |
3004 } | 2948 } |
3005 | 2949 |
3006 fs = &sn->fs; | 2950 fs = &sn->fs; |
3007 | 2951 |
3008 return ngx_quic_handle_ordered_frame(c, fs, frame, ngx_quic_stream_input, | 2952 return ngx_quic_handle_ordered_frame(c, fs, frame, ngx_quic_stream_input, |
3024 sn = data; | 2968 sn = data; |
3025 | 2969 |
3026 f = &frame->u.stream; | 2970 f = &frame->u.stream; |
3027 id = f->stream_id; | 2971 id = f->stream_id; |
3028 | 2972 |
3029 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic existing stream"); | |
3030 | |
3031 b = sn->b; | 2973 b = sn->b; |
3032 | 2974 |
3033 if ((size_t) ((b->pos - b->start) + (b->end - b->last)) < f->length) { | 2975 if ((size_t) ((b->pos - b->start) + (b->end - b->last)) < f->length) { |
3034 ngx_log_error(NGX_LOG_INFO, c->log, 0, | 2976 ngx_log_error(NGX_LOG_INFO, c->log, 0, |
3035 "quic no space in stream buffer"); | 2977 "quic no space in stream buffer"); |
3130 } | 3072 } |
3131 | 3073 |
3132 sn = ngx_quic_find_stream(&qc->streams.tree, f->id); | 3074 sn = ngx_quic_find_stream(&qc->streams.tree, f->id); |
3133 | 3075 |
3134 if (sn == NULL) { | 3076 if (sn == NULL) { |
3135 ngx_log_error(NGX_LOG_INFO, c->log, 0, | 3077 sn = ngx_quic_create_client_stream(c, f->id); |
3136 "quic unknown stream id:0x%xL", f->id); | 3078 |
3137 return NGX_ERROR; | 3079 if (sn == NULL) { |
3138 } | 3080 return NGX_ERROR; |
3139 | 3081 } |
3140 b = sn->b; | 3082 |
3141 n = sn->fs.received + (b->pos - b->start) + (b->end - b->last); | 3083 if (sn == NGX_QUIC_STREAM_GONE) { |
3084 return NGX_OK; | |
3085 } | |
3086 | |
3087 b = sn->b; | |
3088 n = b->end - b->last; | |
3089 | |
3090 sn->c->listening->handler(sn->c); | |
3091 | |
3092 } else { | |
3093 b = sn->b; | |
3094 n = sn->fs.received + (b->pos - b->start) + (b->end - b->last); | |
3095 } | |
3142 | 3096 |
3143 frame = ngx_quic_alloc_frame(c, 0); | 3097 frame = ngx_quic_alloc_frame(c, 0); |
3144 if (frame == NULL) { | 3098 if (frame == NULL) { |
3145 return NGX_ERROR; | 3099 return NGX_ERROR; |
3146 } | 3100 } |
3180 } | 3134 } |
3181 | 3135 |
3182 sn = ngx_quic_find_stream(&qc->streams.tree, f->id); | 3136 sn = ngx_quic_find_stream(&qc->streams.tree, f->id); |
3183 | 3137 |
3184 if (sn == NULL) { | 3138 if (sn == NULL) { |
3185 ngx_log_error(NGX_LOG_INFO, c->log, 0, | 3139 sn = ngx_quic_create_client_stream(c, f->id); |
3186 "unknown stream id:0x%xL", f->id); | 3140 |
3187 | 3141 if (sn == NULL) { |
3188 if (f->id & NGX_QUIC_STREAM_SERVER_INITIATED) { | 3142 return NGX_ERROR; |
3189 qc->error = NGX_QUIC_ERR_STREAM_STATE_ERROR; | 3143 } |
3190 } | 3144 |
3191 | 3145 if (sn == NGX_QUIC_STREAM_GONE) { |
3192 return NGX_ERROR; | 3146 return NGX_OK; |
3147 } | |
3148 | |
3149 if (f->limit > sn->send_max_data) { | |
3150 sn->send_max_data = f->limit; | |
3151 } | |
3152 | |
3153 sn->c->listening->handler(sn->c); | |
3154 | |
3155 return NGX_OK; | |
3193 } | 3156 } |
3194 | 3157 |
3195 if (f->limit <= sn->send_max_data) { | 3158 if (f->limit <= sn->send_max_data) { |
3196 return NGX_OK; | 3159 return NGX_OK; |
3197 } | 3160 } |
3885 return NULL; | 3848 return NULL; |
3886 } | 3849 } |
3887 | 3850 |
3888 | 3851 |
3889 static ngx_quic_stream_t * | 3852 static ngx_quic_stream_t * |
3853 ngx_quic_create_client_stream(ngx_connection_t *c, uint64_t id) | |
3854 { | |
3855 size_t n; | |
3856 uint64_t min_id; | |
3857 ngx_quic_stream_t *sn; | |
3858 ngx_quic_connection_t *qc; | |
3859 | |
3860 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
3861 "quic stream id 0x%xL is new", id); | |
3862 | |
3863 qc = c->quic; | |
3864 | |
3865 if (id & NGX_QUIC_STREAM_UNIDIRECTIONAL) { | |
3866 | |
3867 if (id & NGX_QUIC_STREAM_SERVER_INITIATED) { | |
3868 if ((id >> 2) < qc->streams.server_streams_uni) { | |
3869 return NGX_QUIC_STREAM_GONE; | |
3870 } | |
3871 | |
3872 qc->error = NGX_QUIC_ERR_STREAM_STATE_ERROR; | |
3873 return NULL; | |
3874 } | |
3875 | |
3876 if ((id >> 2) < qc->streams.client_streams_uni) { | |
3877 return NGX_QUIC_STREAM_GONE; | |
3878 } | |
3879 | |
3880 if ((id >> 2) >= qc->streams.client_max_streams_uni) { | |
3881 qc->error = NGX_QUIC_ERR_STREAM_LIMIT_ERROR; | |
3882 return NULL; | |
3883 } | |
3884 | |
3885 min_id = (qc->streams.client_streams_uni << 2) | |
3886 | NGX_QUIC_STREAM_UNIDIRECTIONAL; | |
3887 qc->streams.client_streams_uni = (id >> 2) + 1; | |
3888 n = qc->tp.initial_max_stream_data_uni; | |
3889 | |
3890 } else { | |
3891 | |
3892 if (id & NGX_QUIC_STREAM_SERVER_INITIATED) { | |
3893 if ((id >> 2) < qc->streams.server_streams_bidi) { | |
3894 return NGX_QUIC_STREAM_GONE; | |
3895 } | |
3896 | |
3897 qc->error = NGX_QUIC_ERR_STREAM_STATE_ERROR; | |
3898 return NULL; | |
3899 } | |
3900 | |
3901 if ((id >> 2) < qc->streams.client_streams_bidi) { | |
3902 return NGX_QUIC_STREAM_GONE; | |
3903 } | |
3904 | |
3905 if ((id >> 2) >= qc->streams.client_max_streams_bidi) { | |
3906 qc->error = NGX_QUIC_ERR_STREAM_LIMIT_ERROR; | |
3907 return NULL; | |
3908 } | |
3909 | |
3910 min_id = (qc->streams.client_streams_bidi << 2); | |
3911 qc->streams.client_streams_bidi = (id >> 2) + 1; | |
3912 n = qc->tp.initial_max_stream_data_bidi_remote; | |
3913 } | |
3914 | |
3915 if (n < NGX_QUIC_STREAM_BUFSIZE) { | |
3916 n = NGX_QUIC_STREAM_BUFSIZE; | |
3917 } | |
3918 | |
3919 /* | |
3920 * 2.1. Stream Types and Identifiers | |
3921 * | |
3922 * Within each type, streams are created with numerically increasing | |
3923 * stream IDs. A stream ID that is used out of order results in all | |
3924 * streams of that type with lower-numbered stream IDs also being | |
3925 * opened. | |
3926 */ | |
3927 | |
3928 for ( /* void */ ; min_id < id; min_id += 0x04) { | |
3929 | |
3930 sn = ngx_quic_create_stream(c, min_id, n); | |
3931 if (sn == NULL) { | |
3932 return NULL; | |
3933 } | |
3934 | |
3935 sn->c->listening->handler(sn->c); | |
3936 } | |
3937 | |
3938 return ngx_quic_create_stream(c, id, n); | |
3939 } | |
3940 | |
3941 | |
3942 static ngx_quic_stream_t * | |
3890 ngx_quic_create_stream(ngx_connection_t *c, uint64_t id, size_t rcvbuf_size) | 3943 ngx_quic_create_stream(ngx_connection_t *c, uint64_t id, size_t rcvbuf_size) |
3891 { | 3944 { |
3892 ngx_log_t *log; | 3945 ngx_log_t *log; |
3893 ngx_pool_t *pool; | 3946 ngx_pool_t *pool; |
3894 ngx_quic_stream_t *sn; | 3947 ngx_quic_stream_t *sn; |