Mercurial > hg > nginx
comparison src/event/quic/ngx_event_quic.c @ 8750:41807e581de9 quic
QUIC: separate files for stream related processing.
author | Vladimir Homutov <vl@nginx.com> |
---|---|
date | Tue, 13 Apr 2021 14:40:00 +0300 |
parents | 660c4a2f95f3 |
children | bc910a5ec737 |
comparison
equal
deleted
inserted
replaced
8749:660c4a2f95f3 | 8750:41807e581de9 |
---|---|
18 /* | 18 /* |
19 * 7.4. Cryptographic Message Buffering | 19 * 7.4. Cryptographic Message Buffering |
20 * Implementations MUST support buffering at least 4096 bytes of data | 20 * Implementations MUST support buffering at least 4096 bytes of data |
21 */ | 21 */ |
22 #define NGX_QUIC_MAX_BUFFERED 65535 | 22 #define NGX_QUIC_MAX_BUFFERED 65535 |
23 | |
24 #define NGX_QUIC_STREAM_GONE (void *) -1 | |
25 | 23 |
26 /* | 24 /* |
27 * Endpoints MUST discard packets that are too small to be valid QUIC | 25 * Endpoints MUST discard packets that are too small to be valid QUIC |
28 * packets. With the set of AEAD functions defined in [QUIC-TLS], | 26 * packets. With the set of AEAD functions defined in [QUIC-TLS], |
29 * packets that are smaller than 21 bytes are never valid. | 27 * packets that are smaller than 21 bytes are never valid. |
78 static ngx_inline size_t ngx_quic_max_udp_payload(ngx_connection_t *c); | 76 static ngx_inline size_t ngx_quic_max_udp_payload(ngx_connection_t *c); |
79 static void ngx_quic_input_handler(ngx_event_t *rev); | 77 static void ngx_quic_input_handler(ngx_event_t *rev); |
80 | 78 |
81 static ngx_int_t ngx_quic_close_quic(ngx_connection_t *c, ngx_int_t rc); | 79 static ngx_int_t ngx_quic_close_quic(ngx_connection_t *c, ngx_int_t rc); |
82 static void ngx_quic_close_timer_handler(ngx_event_t *ev); | 80 static void ngx_quic_close_timer_handler(ngx_event_t *ev); |
83 static ngx_int_t ngx_quic_close_streams(ngx_connection_t *c, | |
84 ngx_quic_connection_t *qc); | |
85 | 81 |
86 static ngx_int_t ngx_quic_input(ngx_connection_t *c, ngx_buf_t *b, | 82 static ngx_int_t ngx_quic_input(ngx_connection_t *c, ngx_buf_t *b, |
87 ngx_quic_conf_t *conf); | 83 ngx_quic_conf_t *conf); |
88 static ngx_int_t ngx_quic_process_packet(ngx_connection_t *c, | 84 static ngx_int_t ngx_quic_process_packet(ngx_connection_t *c, |
89 ngx_quic_conf_t *conf, ngx_quic_header_t *pkt); | 85 ngx_quic_conf_t *conf, ngx_quic_header_t *pkt); |
113 static ngx_int_t ngx_quic_handle_ack_frame_range(ngx_connection_t *c, | 109 static ngx_int_t ngx_quic_handle_ack_frame_range(ngx_connection_t *c, |
114 ngx_quic_send_ctx_t *ctx, uint64_t min, uint64_t max, | 110 ngx_quic_send_ctx_t *ctx, uint64_t min, uint64_t max, |
115 ngx_msec_t *send_time); | 111 ngx_msec_t *send_time); |
116 static void ngx_quic_rtt_sample(ngx_connection_t *c, ngx_quic_ack_frame_t *ack, | 112 static void ngx_quic_rtt_sample(ngx_connection_t *c, ngx_quic_ack_frame_t *ack, |
117 enum ssl_encryption_level_t level, ngx_msec_t send_time); | 113 enum ssl_encryption_level_t level, ngx_msec_t send_time); |
118 static void ngx_quic_handle_stream_ack(ngx_connection_t *c, | |
119 ngx_quic_frame_t *f); | |
120 | 114 |
121 static ngx_int_t ngx_quic_handle_crypto_frame(ngx_connection_t *c, | 115 static ngx_int_t ngx_quic_handle_crypto_frame(ngx_connection_t *c, |
122 ngx_quic_header_t *pkt, ngx_quic_frame_t *frame); | 116 ngx_quic_header_t *pkt, ngx_quic_frame_t *frame); |
123 ngx_int_t ngx_quic_crypto_input(ngx_connection_t *c, | 117 ngx_int_t ngx_quic_crypto_input(ngx_connection_t *c, |
124 ngx_quic_frame_t *frame, void *data); | 118 ngx_quic_frame_t *frame, void *data); |
125 static ngx_int_t ngx_quic_handle_stream_frame(ngx_connection_t *c, | 119 |
126 ngx_quic_header_t *pkt, ngx_quic_frame_t *frame); | |
127 static ngx_int_t ngx_quic_stream_input(ngx_connection_t *c, | |
128 ngx_quic_frame_t *frame, void *data); | |
129 | |
130 static ngx_int_t ngx_quic_handle_max_data_frame(ngx_connection_t *c, | |
131 ngx_quic_max_data_frame_t *f); | |
132 static ngx_int_t ngx_quic_handle_streams_blocked_frame(ngx_connection_t *c, | |
133 ngx_quic_header_t *pkt, ngx_quic_streams_blocked_frame_t *f); | |
134 static ngx_int_t ngx_quic_handle_stream_data_blocked_frame(ngx_connection_t *c, | |
135 ngx_quic_header_t *pkt, ngx_quic_stream_data_blocked_frame_t *f); | |
136 static ngx_int_t ngx_quic_handle_max_stream_data_frame(ngx_connection_t *c, | |
137 ngx_quic_header_t *pkt, ngx_quic_max_stream_data_frame_t *f); | |
138 static ngx_int_t ngx_quic_handle_reset_stream_frame(ngx_connection_t *c, | |
139 ngx_quic_header_t *pkt, ngx_quic_reset_stream_frame_t *f); | |
140 static ngx_int_t ngx_quic_handle_stop_sending_frame(ngx_connection_t *c, | |
141 ngx_quic_header_t *pkt, ngx_quic_stop_sending_frame_t *f); | |
142 static ngx_int_t ngx_quic_handle_max_streams_frame(ngx_connection_t *c, | |
143 ngx_quic_header_t *pkt, ngx_quic_max_streams_frame_t *f); | |
144 | |
145 static ngx_int_t ngx_quic_output(ngx_connection_t *c); | |
146 static ngx_uint_t ngx_quic_get_padding_level(ngx_connection_t *c); | 120 static ngx_uint_t ngx_quic_get_padding_level(ngx_connection_t *c); |
147 static ngx_int_t ngx_quic_generate_ack(ngx_connection_t *c, | 121 static ngx_int_t ngx_quic_generate_ack(ngx_connection_t *c, |
148 ngx_quic_send_ctx_t *ctx); | 122 ngx_quic_send_ctx_t *ctx); |
149 static ssize_t ngx_quic_output_packet(ngx_connection_t *c, | 123 static ssize_t ngx_quic_output_packet(ngx_connection_t *c, |
150 ngx_quic_send_ctx_t *ctx, u_char *data, size_t max, size_t min); | 124 ngx_quic_send_ctx_t *ctx, u_char *data, size_t max, size_t min); |
157 static ngx_int_t ngx_quic_detect_lost(ngx_connection_t *c); | 131 static ngx_int_t ngx_quic_detect_lost(ngx_connection_t *c); |
158 static void ngx_quic_set_lost_timer(ngx_connection_t *c); | 132 static void ngx_quic_set_lost_timer(ngx_connection_t *c); |
159 static void ngx_quic_resend_frames(ngx_connection_t *c, | 133 static void ngx_quic_resend_frames(ngx_connection_t *c, |
160 ngx_quic_send_ctx_t *ctx); | 134 ngx_quic_send_ctx_t *ctx); |
161 static void ngx_quic_push_handler(ngx_event_t *ev); | 135 static void ngx_quic_push_handler(ngx_event_t *ev); |
162 | |
163 static void ngx_quic_rbtree_insert_stream(ngx_rbtree_node_t *temp, | |
164 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); | |
165 static ngx_quic_stream_t *ngx_quic_find_stream(ngx_rbtree_t *rbtree, | |
166 uint64_t id); | |
167 static ngx_quic_stream_t *ngx_quic_create_client_stream(ngx_connection_t *c, | |
168 uint64_t id); | |
169 static ngx_quic_stream_t *ngx_quic_create_stream(ngx_connection_t *c, | |
170 uint64_t id, size_t rcvbuf_size); | |
171 static ssize_t ngx_quic_stream_recv(ngx_connection_t *c, u_char *buf, | |
172 size_t size); | |
173 static ssize_t ngx_quic_stream_send(ngx_connection_t *c, u_char *buf, | |
174 size_t size); | |
175 static ngx_chain_t *ngx_quic_stream_send_chain(ngx_connection_t *c, | |
176 ngx_chain_t *in, off_t limit); | |
177 static size_t ngx_quic_max_stream_flow(ngx_connection_t *c); | |
178 static void ngx_quic_stream_cleanup_handler(void *data); | |
179 static void ngx_quic_shutdown_quic(ngx_connection_t *c); | |
180 | 136 |
181 static void ngx_quic_congestion_ack(ngx_connection_t *c, | 137 static void ngx_quic_congestion_ack(ngx_connection_t *c, |
182 ngx_quic_frame_t *frame); | 138 ngx_quic_frame_t *frame); |
183 static void ngx_quic_congestion_lost(ngx_connection_t *c, | 139 static void ngx_quic_congestion_lost(ngx_connection_t *c, |
184 ngx_quic_frame_t *frame); | 140 ngx_quic_frame_t *frame); |
1602 | 1558 |
1603 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0, "quic close timer"); | 1559 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0, "quic close timer"); |
1604 | 1560 |
1605 c = ev->data; | 1561 c = ev->data; |
1606 ngx_quic_close_connection(c, NGX_DONE); | 1562 ngx_quic_close_connection(c, NGX_DONE); |
1607 } | |
1608 | |
1609 | |
1610 static ngx_int_t | |
1611 ngx_quic_close_streams(ngx_connection_t *c, ngx_quic_connection_t *qc) | |
1612 { | |
1613 ngx_event_t *rev, *wev; | |
1614 ngx_rbtree_t *tree; | |
1615 ngx_rbtree_node_t *node; | |
1616 ngx_quic_stream_t *qs; | |
1617 | |
1618 #if (NGX_DEBUG) | |
1619 ngx_uint_t ns; | |
1620 #endif | |
1621 | |
1622 tree = &qc->streams.tree; | |
1623 | |
1624 if (tree->root == tree->sentinel) { | |
1625 return NGX_OK; | |
1626 } | |
1627 | |
1628 #if (NGX_DEBUG) | |
1629 ns = 0; | |
1630 #endif | |
1631 | |
1632 for (node = ngx_rbtree_min(tree->root, tree->sentinel); | |
1633 node; | |
1634 node = ngx_rbtree_next(tree, node)) | |
1635 { | |
1636 qs = (ngx_quic_stream_t *) node; | |
1637 | |
1638 rev = qs->c->read; | |
1639 rev->error = 1; | |
1640 rev->ready = 1; | |
1641 | |
1642 wev = qs->c->write; | |
1643 wev->error = 1; | |
1644 wev->ready = 1; | |
1645 | |
1646 ngx_post_event(rev, &ngx_posted_events); | |
1647 | |
1648 if (rev->timer_set) { | |
1649 ngx_del_timer(rev); | |
1650 } | |
1651 | |
1652 #if (NGX_DEBUG) | |
1653 ns++; | |
1654 #endif | |
1655 } | |
1656 | |
1657 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
1658 "quic connection has %ui active streams", ns); | |
1659 | |
1660 return NGX_AGAIN; | |
1661 } | |
1662 | |
1663 | |
1664 ngx_int_t | |
1665 ngx_quic_reset_stream(ngx_connection_t *c, ngx_uint_t err) | |
1666 { | |
1667 ngx_event_t *wev; | |
1668 ngx_connection_t *pc; | |
1669 ngx_quic_frame_t *frame; | |
1670 ngx_quic_stream_t *qs; | |
1671 ngx_quic_connection_t *qc; | |
1672 | |
1673 qs = c->quic; | |
1674 pc = qs->parent; | |
1675 qc = ngx_quic_get_connection(pc); | |
1676 | |
1677 frame = ngx_quic_alloc_frame(pc); | |
1678 if (frame == NULL) { | |
1679 return NGX_ERROR; | |
1680 } | |
1681 | |
1682 frame->level = ssl_encryption_application; | |
1683 frame->type = NGX_QUIC_FT_RESET_STREAM; | |
1684 frame->u.reset_stream.id = qs->id; | |
1685 frame->u.reset_stream.error_code = err; | |
1686 frame->u.reset_stream.final_size = c->sent; | |
1687 | |
1688 ngx_quic_queue_frame(qc, frame); | |
1689 | |
1690 wev = c->write; | |
1691 wev->error = 1; | |
1692 wev->ready = 1; | |
1693 | |
1694 return NGX_OK; | |
1695 } | 1563 } |
1696 | 1564 |
1697 | 1565 |
1698 static ngx_int_t | 1566 static ngx_int_t |
1699 ngx_quic_input(ngx_connection_t *c, ngx_buf_t *b, ngx_quic_conf_t *conf) | 1567 ngx_quic_input(ngx_connection_t *c, ngx_buf_t *b, ngx_quic_conf_t *conf) |
3150 | 3018 |
3151 return duration; | 3019 return duration; |
3152 } | 3020 } |
3153 | 3021 |
3154 | 3022 |
3155 static void | |
3156 ngx_quic_handle_stream_ack(ngx_connection_t *c, ngx_quic_frame_t *f) | |
3157 { | |
3158 uint64_t sent, unacked; | |
3159 ngx_event_t *wev; | |
3160 ngx_quic_stream_t *sn; | |
3161 ngx_quic_connection_t *qc; | |
3162 | |
3163 qc = ngx_quic_get_connection(c); | |
3164 | |
3165 sn = ngx_quic_find_stream(&qc->streams.tree, f->u.stream.stream_id); | |
3166 if (sn == NULL) { | |
3167 return; | |
3168 } | |
3169 | |
3170 wev = sn->c->write; | |
3171 sent = sn->c->sent; | |
3172 unacked = sent - sn->acked; | |
3173 | |
3174 if (unacked >= NGX_QUIC_STREAM_BUFSIZE && wev->active) { | |
3175 wev->ready = 1; | |
3176 ngx_post_event(wev, &ngx_posted_events); | |
3177 } | |
3178 | |
3179 sn->acked += f->u.stream.length; | |
3180 | |
3181 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, sn->c->log, 0, | |
3182 "quic stream ack len:%uL acked:%uL unacked:%uL", | |
3183 f->u.stream.length, sn->acked, sent - sn->acked); | |
3184 } | |
3185 | |
3186 | |
3187 static ngx_int_t | 3023 static ngx_int_t |
3188 ngx_quic_handle_crypto_frame(ngx_connection_t *c, ngx_quic_header_t *pkt, | 3024 ngx_quic_handle_crypto_frame(ngx_connection_t *c, ngx_quic_header_t *pkt, |
3189 ngx_quic_frame_t *frame) | 3025 ngx_quic_frame_t *frame) |
3190 { | 3026 { |
3191 uint64_t last; | 3027 uint64_t last; |
3332 | 3168 |
3333 return NGX_OK; | 3169 return NGX_OK; |
3334 } | 3170 } |
3335 | 3171 |
3336 | 3172 |
3337 static ngx_int_t | 3173 ngx_int_t |
3338 ngx_quic_handle_stream_frame(ngx_connection_t *c, ngx_quic_header_t *pkt, | |
3339 ngx_quic_frame_t *frame) | |
3340 { | |
3341 size_t window; | |
3342 uint64_t last; | |
3343 ngx_buf_t *b; | |
3344 ngx_pool_t *pool; | |
3345 ngx_connection_t *sc; | |
3346 ngx_quic_stream_t *sn; | |
3347 ngx_quic_connection_t *qc; | |
3348 ngx_quic_stream_frame_t *f; | |
3349 ngx_quic_frames_stream_t *fs; | |
3350 | |
3351 qc = ngx_quic_get_connection(c); | |
3352 f = &frame->u.stream; | |
3353 | |
3354 if ((f->stream_id & NGX_QUIC_STREAM_UNIDIRECTIONAL) | |
3355 && (f->stream_id & NGX_QUIC_STREAM_SERVER_INITIATED)) | |
3356 { | |
3357 qc->error = NGX_QUIC_ERR_STREAM_STATE_ERROR; | |
3358 return NGX_ERROR; | |
3359 } | |
3360 | |
3361 /* no overflow since both values are 62-bit */ | |
3362 last = f->offset + f->length; | |
3363 | |
3364 sn = ngx_quic_find_stream(&qc->streams.tree, f->stream_id); | |
3365 | |
3366 if (sn == NULL) { | |
3367 sn = ngx_quic_create_client_stream(c, f->stream_id); | |
3368 | |
3369 if (sn == NULL) { | |
3370 return NGX_ERROR; | |
3371 } | |
3372 | |
3373 if (sn == NGX_QUIC_STREAM_GONE) { | |
3374 return NGX_OK; | |
3375 } | |
3376 | |
3377 sc = sn->c; | |
3378 fs = &sn->fs; | |
3379 b = sn->b; | |
3380 window = b->end - b->last; | |
3381 | |
3382 if (last > window) { | |
3383 qc->error = NGX_QUIC_ERR_FLOW_CONTROL_ERROR; | |
3384 goto cleanup; | |
3385 } | |
3386 | |
3387 if (ngx_quic_handle_ordered_frame(c, fs, frame, ngx_quic_stream_input, | |
3388 sn) | |
3389 != NGX_OK) | |
3390 { | |
3391 goto cleanup; | |
3392 } | |
3393 | |
3394 sc->listening->handler(sc); | |
3395 | |
3396 return NGX_OK; | |
3397 } | |
3398 | |
3399 fs = &sn->fs; | |
3400 b = sn->b; | |
3401 window = (b->pos - b->start) + (b->end - b->last); | |
3402 | |
3403 if (last > fs->received && last - fs->received > window) { | |
3404 qc->error = NGX_QUIC_ERR_FLOW_CONTROL_ERROR; | |
3405 return NGX_ERROR; | |
3406 } | |
3407 | |
3408 return ngx_quic_handle_ordered_frame(c, fs, frame, ngx_quic_stream_input, | |
3409 sn); | |
3410 | |
3411 cleanup: | |
3412 | |
3413 pool = sc->pool; | |
3414 | |
3415 ngx_close_connection(sc); | |
3416 ngx_destroy_pool(pool); | |
3417 | |
3418 return NGX_ERROR; | |
3419 } | |
3420 | |
3421 | |
3422 static ngx_int_t | |
3423 ngx_quic_stream_input(ngx_connection_t *c, ngx_quic_frame_t *frame, void *data) | |
3424 { | |
3425 uint64_t id; | |
3426 ngx_buf_t *b; | |
3427 ngx_event_t *rev; | |
3428 ngx_chain_t *cl; | |
3429 ngx_quic_stream_t *sn; | |
3430 ngx_quic_connection_t *qc; | |
3431 ngx_quic_stream_frame_t *f; | |
3432 | |
3433 qc = ngx_quic_get_connection(c); | |
3434 sn = data; | |
3435 | |
3436 f = &frame->u.stream; | |
3437 id = f->stream_id; | |
3438 | |
3439 b = sn->b; | |
3440 | |
3441 if ((size_t) ((b->pos - b->start) + (b->end - b->last)) < f->length) { | |
3442 ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
3443 "quic no space in stream buffer"); | |
3444 return NGX_ERROR; | |
3445 } | |
3446 | |
3447 if ((size_t) (b->end - b->last) < f->length) { | |
3448 b->last = ngx_movemem(b->start, b->pos, b->last - b->pos); | |
3449 b->pos = b->start; | |
3450 } | |
3451 | |
3452 for (cl = frame->data; cl; cl = cl->next) { | |
3453 b->last = ngx_cpymem(b->last, cl->buf->pos, | |
3454 cl->buf->last - cl->buf->pos); | |
3455 } | |
3456 | |
3457 rev = sn->c->read; | |
3458 rev->ready = 1; | |
3459 | |
3460 if (f->fin) { | |
3461 rev->pending_eof = 1; | |
3462 } | |
3463 | |
3464 if (rev->active) { | |
3465 rev->handler(rev); | |
3466 } | |
3467 | |
3468 /* check if stream was destroyed by handler */ | |
3469 if (ngx_quic_find_stream(&qc->streams.tree, id) == NULL) { | |
3470 return NGX_DONE; | |
3471 } | |
3472 | |
3473 return NGX_OK; | |
3474 } | |
3475 | |
3476 | |
3477 static ngx_int_t | |
3478 ngx_quic_handle_max_data_frame(ngx_connection_t *c, | |
3479 ngx_quic_max_data_frame_t *f) | |
3480 { | |
3481 ngx_event_t *wev; | |
3482 ngx_rbtree_t *tree; | |
3483 ngx_rbtree_node_t *node; | |
3484 ngx_quic_stream_t *qs; | |
3485 ngx_quic_connection_t *qc; | |
3486 | |
3487 qc = ngx_quic_get_connection(c); | |
3488 tree = &qc->streams.tree; | |
3489 | |
3490 if (f->max_data <= qc->streams.send_max_data) { | |
3491 return NGX_OK; | |
3492 } | |
3493 | |
3494 if (qc->streams.sent >= qc->streams.send_max_data) { | |
3495 | |
3496 for (node = ngx_rbtree_min(tree->root, tree->sentinel); | |
3497 node; | |
3498 node = ngx_rbtree_next(tree, node)) | |
3499 { | |
3500 qs = (ngx_quic_stream_t *) node; | |
3501 wev = qs->c->write; | |
3502 | |
3503 if (wev->active) { | |
3504 wev->ready = 1; | |
3505 ngx_post_event(wev, &ngx_posted_events); | |
3506 } | |
3507 } | |
3508 } | |
3509 | |
3510 qc->streams.send_max_data = f->max_data; | |
3511 | |
3512 return NGX_OK; | |
3513 } | |
3514 | |
3515 | |
3516 static ngx_int_t | |
3517 ngx_quic_handle_streams_blocked_frame(ngx_connection_t *c, | |
3518 ngx_quic_header_t *pkt, ngx_quic_streams_blocked_frame_t *f) | |
3519 { | |
3520 return NGX_OK; | |
3521 } | |
3522 | |
3523 | |
3524 static ngx_int_t | |
3525 ngx_quic_handle_stream_data_blocked_frame(ngx_connection_t *c, | |
3526 ngx_quic_header_t *pkt, ngx_quic_stream_data_blocked_frame_t *f) | |
3527 { | |
3528 size_t n; | |
3529 ngx_buf_t *b; | |
3530 ngx_quic_frame_t *frame; | |
3531 ngx_quic_stream_t *sn; | |
3532 ngx_quic_connection_t *qc; | |
3533 | |
3534 qc = ngx_quic_get_connection(c); | |
3535 | |
3536 if ((f->id & NGX_QUIC_STREAM_UNIDIRECTIONAL) | |
3537 && (f->id & NGX_QUIC_STREAM_SERVER_INITIATED)) | |
3538 { | |
3539 qc->error = NGX_QUIC_ERR_STREAM_STATE_ERROR; | |
3540 return NGX_ERROR; | |
3541 } | |
3542 | |
3543 sn = ngx_quic_find_stream(&qc->streams.tree, f->id); | |
3544 | |
3545 if (sn == NULL) { | |
3546 sn = ngx_quic_create_client_stream(c, f->id); | |
3547 | |
3548 if (sn == NULL) { | |
3549 return NGX_ERROR; | |
3550 } | |
3551 | |
3552 if (sn == NGX_QUIC_STREAM_GONE) { | |
3553 return NGX_OK; | |
3554 } | |
3555 | |
3556 b = sn->b; | |
3557 n = b->end - b->last; | |
3558 | |
3559 sn->c->listening->handler(sn->c); | |
3560 | |
3561 } else { | |
3562 b = sn->b; | |
3563 n = sn->fs.received + (b->pos - b->start) + (b->end - b->last); | |
3564 } | |
3565 | |
3566 frame = ngx_quic_alloc_frame(c); | |
3567 if (frame == NULL) { | |
3568 return NGX_ERROR; | |
3569 } | |
3570 | |
3571 frame->level = pkt->level; | |
3572 frame->type = NGX_QUIC_FT_MAX_STREAM_DATA; | |
3573 frame->u.max_stream_data.id = f->id; | |
3574 frame->u.max_stream_data.limit = n; | |
3575 | |
3576 ngx_quic_queue_frame(qc, frame); | |
3577 | |
3578 return NGX_OK; | |
3579 } | |
3580 | |
3581 | |
3582 static ngx_int_t | |
3583 ngx_quic_handle_max_stream_data_frame(ngx_connection_t *c, | |
3584 ngx_quic_header_t *pkt, ngx_quic_max_stream_data_frame_t *f) | |
3585 { | |
3586 uint64_t sent; | |
3587 ngx_event_t *wev; | |
3588 ngx_quic_stream_t *sn; | |
3589 ngx_quic_connection_t *qc; | |
3590 | |
3591 qc = ngx_quic_get_connection(c); | |
3592 | |
3593 if ((f->id & NGX_QUIC_STREAM_UNIDIRECTIONAL) | |
3594 && (f->id & NGX_QUIC_STREAM_SERVER_INITIATED) == 0) | |
3595 { | |
3596 qc->error = NGX_QUIC_ERR_STREAM_STATE_ERROR; | |
3597 return NGX_ERROR; | |
3598 } | |
3599 | |
3600 sn = ngx_quic_find_stream(&qc->streams.tree, f->id); | |
3601 | |
3602 if (sn == NULL) { | |
3603 sn = ngx_quic_create_client_stream(c, f->id); | |
3604 | |
3605 if (sn == NULL) { | |
3606 return NGX_ERROR; | |
3607 } | |
3608 | |
3609 if (sn == NGX_QUIC_STREAM_GONE) { | |
3610 return NGX_OK; | |
3611 } | |
3612 | |
3613 if (f->limit > sn->send_max_data) { | |
3614 sn->send_max_data = f->limit; | |
3615 } | |
3616 | |
3617 sn->c->listening->handler(sn->c); | |
3618 | |
3619 return NGX_OK; | |
3620 } | |
3621 | |
3622 if (f->limit <= sn->send_max_data) { | |
3623 return NGX_OK; | |
3624 } | |
3625 | |
3626 sent = sn->c->sent; | |
3627 | |
3628 if (sent >= sn->send_max_data) { | |
3629 wev = sn->c->write; | |
3630 | |
3631 if (wev->active) { | |
3632 wev->ready = 1; | |
3633 ngx_post_event(wev, &ngx_posted_events); | |
3634 } | |
3635 } | |
3636 | |
3637 sn->send_max_data = f->limit; | |
3638 | |
3639 return NGX_OK; | |
3640 } | |
3641 | |
3642 | |
3643 static ngx_int_t | |
3644 ngx_quic_handle_reset_stream_frame(ngx_connection_t *c, | |
3645 ngx_quic_header_t *pkt, ngx_quic_reset_stream_frame_t *f) | |
3646 { | |
3647 ngx_event_t *rev; | |
3648 ngx_connection_t *sc; | |
3649 ngx_quic_stream_t *sn; | |
3650 ngx_quic_connection_t *qc; | |
3651 | |
3652 qc = ngx_quic_get_connection(c); | |
3653 | |
3654 if ((f->id & NGX_QUIC_STREAM_UNIDIRECTIONAL) | |
3655 && (f->id & NGX_QUIC_STREAM_SERVER_INITIATED)) | |
3656 { | |
3657 qc->error = NGX_QUIC_ERR_STREAM_STATE_ERROR; | |
3658 return NGX_ERROR; | |
3659 } | |
3660 | |
3661 sn = ngx_quic_find_stream(&qc->streams.tree, f->id); | |
3662 | |
3663 if (sn == NULL) { | |
3664 sn = ngx_quic_create_client_stream(c, f->id); | |
3665 | |
3666 if (sn == NULL) { | |
3667 return NGX_ERROR; | |
3668 } | |
3669 | |
3670 if (sn == NGX_QUIC_STREAM_GONE) { | |
3671 return NGX_OK; | |
3672 } | |
3673 | |
3674 sc = sn->c; | |
3675 | |
3676 rev = sc->read; | |
3677 rev->error = 1; | |
3678 rev->ready = 1; | |
3679 | |
3680 sc->listening->handler(sc); | |
3681 | |
3682 return NGX_OK; | |
3683 } | |
3684 | |
3685 rev = sn->c->read; | |
3686 rev->error = 1; | |
3687 rev->ready = 1; | |
3688 | |
3689 if (rev->active) { | |
3690 rev->handler(rev); | |
3691 } | |
3692 | |
3693 return NGX_OK; | |
3694 } | |
3695 | |
3696 | |
3697 static ngx_int_t | |
3698 ngx_quic_handle_stop_sending_frame(ngx_connection_t *c, | |
3699 ngx_quic_header_t *pkt, ngx_quic_stop_sending_frame_t *f) | |
3700 { | |
3701 ngx_event_t *wev; | |
3702 ngx_connection_t *sc; | |
3703 ngx_quic_stream_t *sn; | |
3704 ngx_quic_connection_t *qc; | |
3705 | |
3706 qc = ngx_quic_get_connection(c); | |
3707 | |
3708 if ((f->id & NGX_QUIC_STREAM_UNIDIRECTIONAL) | |
3709 && (f->id & NGX_QUIC_STREAM_SERVER_INITIATED) == 0) | |
3710 { | |
3711 qc->error = NGX_QUIC_ERR_STREAM_STATE_ERROR; | |
3712 return NGX_ERROR; | |
3713 } | |
3714 | |
3715 sn = ngx_quic_find_stream(&qc->streams.tree, f->id); | |
3716 | |
3717 if (sn == NULL) { | |
3718 sn = ngx_quic_create_client_stream(c, f->id); | |
3719 | |
3720 if (sn == NULL) { | |
3721 return NGX_ERROR; | |
3722 } | |
3723 | |
3724 if (sn == NGX_QUIC_STREAM_GONE) { | |
3725 return NGX_OK; | |
3726 } | |
3727 | |
3728 sc = sn->c; | |
3729 | |
3730 wev = sc->write; | |
3731 wev->error = 1; | |
3732 wev->ready = 1; | |
3733 | |
3734 sc->listening->handler(sc); | |
3735 | |
3736 return NGX_OK; | |
3737 } | |
3738 | |
3739 wev = sn->c->write; | |
3740 wev->error = 1; | |
3741 wev->ready = 1; | |
3742 | |
3743 if (wev->active) { | |
3744 wev->handler(wev); | |
3745 } | |
3746 | |
3747 return NGX_OK; | |
3748 } | |
3749 | |
3750 | |
3751 static ngx_int_t | |
3752 ngx_quic_handle_max_streams_frame(ngx_connection_t *c, | |
3753 ngx_quic_header_t *pkt, ngx_quic_max_streams_frame_t *f) | |
3754 { | |
3755 ngx_quic_connection_t *qc; | |
3756 | |
3757 qc = ngx_quic_get_connection(c); | |
3758 | |
3759 if (f->bidi) { | |
3760 if (qc->streams.server_max_streams_bidi < f->limit) { | |
3761 qc->streams.server_max_streams_bidi = f->limit; | |
3762 | |
3763 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
3764 "quic max_streams_bidi:%uL", f->limit); | |
3765 } | |
3766 | |
3767 } else { | |
3768 if (qc->streams.server_max_streams_uni < f->limit) { | |
3769 qc->streams.server_max_streams_uni = f->limit; | |
3770 | |
3771 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
3772 "quic max_streams_uni:%uL", f->limit); | |
3773 } | |
3774 } | |
3775 | |
3776 return NGX_OK; | |
3777 } | |
3778 | |
3779 | |
3780 static ngx_int_t | |
3781 ngx_quic_output(ngx_connection_t *c) | 3174 ngx_quic_output(ngx_connection_t *c) |
3782 { | 3175 { |
3783 off_t max; | 3176 off_t max; |
3784 size_t len, min, in_flight; | 3177 size_t len, min, in_flight; |
3785 ssize_t n; | 3178 ssize_t n; |
4553 | 3946 |
4554 ngx_post_event(&qc->push, &ngx_posted_events); | 3947 ngx_post_event(&qc->push, &ngx_posted_events); |
4555 } | 3948 } |
4556 | 3949 |
4557 | 3950 |
4558 ngx_connection_t * | 3951 void |
4559 ngx_quic_open_stream(ngx_connection_t *c, ngx_uint_t bidi) | |
4560 { | |
4561 size_t rcvbuf_size; | |
4562 uint64_t id; | |
4563 ngx_quic_stream_t *qs, *sn; | |
4564 ngx_quic_connection_t *qc; | |
4565 | |
4566 qs = c->quic; | |
4567 qc = ngx_quic_get_connection(qs->parent); | |
4568 | |
4569 if (bidi) { | |
4570 if (qc->streams.server_streams_bidi | |
4571 >= qc->streams.server_max_streams_bidi) | |
4572 { | |
4573 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
4574 "quic too many server bidi streams:%uL", | |
4575 qc->streams.server_streams_bidi); | |
4576 return NULL; | |
4577 } | |
4578 | |
4579 id = (qc->streams.server_streams_bidi << 2) | |
4580 | NGX_QUIC_STREAM_SERVER_INITIATED; | |
4581 | |
4582 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
4583 "quic creating server bidi stream" | |
4584 " streams:%uL max:%uL id:0x%xL", | |
4585 qc->streams.server_streams_bidi, | |
4586 qc->streams.server_max_streams_bidi, id); | |
4587 | |
4588 qc->streams.server_streams_bidi++; | |
4589 rcvbuf_size = qc->tp.initial_max_stream_data_bidi_local; | |
4590 | |
4591 } else { | |
4592 if (qc->streams.server_streams_uni | |
4593 >= qc->streams.server_max_streams_uni) | |
4594 { | |
4595 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
4596 "quic too many server uni streams:%uL", | |
4597 qc->streams.server_streams_uni); | |
4598 return NULL; | |
4599 } | |
4600 | |
4601 id = (qc->streams.server_streams_uni << 2) | |
4602 | NGX_QUIC_STREAM_SERVER_INITIATED | |
4603 | NGX_QUIC_STREAM_UNIDIRECTIONAL; | |
4604 | |
4605 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
4606 "quic creating server uni stream" | |
4607 " streams:%uL max:%uL id:0x%xL", | |
4608 qc->streams.server_streams_uni, | |
4609 qc->streams.server_max_streams_uni, id); | |
4610 | |
4611 qc->streams.server_streams_uni++; | |
4612 rcvbuf_size = 0; | |
4613 } | |
4614 | |
4615 sn = ngx_quic_create_stream(qs->parent, id, rcvbuf_size); | |
4616 if (sn == NULL) { | |
4617 return NULL; | |
4618 } | |
4619 | |
4620 return sn->c; | |
4621 } | |
4622 | |
4623 | |
4624 static void | |
4625 ngx_quic_rbtree_insert_stream(ngx_rbtree_node_t *temp, | |
4626 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel) | |
4627 { | |
4628 ngx_rbtree_node_t **p; | |
4629 ngx_quic_stream_t *qn, *qnt; | |
4630 | |
4631 for ( ;; ) { | |
4632 qn = (ngx_quic_stream_t *) node; | |
4633 qnt = (ngx_quic_stream_t *) temp; | |
4634 | |
4635 p = (qn->id < qnt->id) ? &temp->left : &temp->right; | |
4636 | |
4637 if (*p == sentinel) { | |
4638 break; | |
4639 } | |
4640 | |
4641 temp = *p; | |
4642 } | |
4643 | |
4644 *p = node; | |
4645 node->parent = temp; | |
4646 node->left = sentinel; | |
4647 node->right = sentinel; | |
4648 ngx_rbt_red(node); | |
4649 } | |
4650 | |
4651 | |
4652 static ngx_quic_stream_t * | |
4653 ngx_quic_find_stream(ngx_rbtree_t *rbtree, uint64_t id) | |
4654 { | |
4655 ngx_rbtree_node_t *node, *sentinel; | |
4656 ngx_quic_stream_t *qn; | |
4657 | |
4658 node = rbtree->root; | |
4659 sentinel = rbtree->sentinel; | |
4660 | |
4661 while (node != sentinel) { | |
4662 qn = (ngx_quic_stream_t *) node; | |
4663 | |
4664 if (id == qn->id) { | |
4665 return qn; | |
4666 } | |
4667 | |
4668 node = (id < qn->id) ? node->left : node->right; | |
4669 } | |
4670 | |
4671 return NULL; | |
4672 } | |
4673 | |
4674 | |
4675 static ngx_quic_stream_t * | |
4676 ngx_quic_create_client_stream(ngx_connection_t *c, uint64_t id) | |
4677 { | |
4678 size_t n; | |
4679 uint64_t min_id; | |
4680 ngx_quic_stream_t *sn; | |
4681 ngx_quic_connection_t *qc; | |
4682 | |
4683 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
4684 "quic stream id:0x%xL is new", id); | |
4685 | |
4686 qc = ngx_quic_get_connection(c); | |
4687 | |
4688 if (qc->shutdown) { | |
4689 return NGX_QUIC_STREAM_GONE; | |
4690 } | |
4691 | |
4692 if (id & NGX_QUIC_STREAM_UNIDIRECTIONAL) { | |
4693 | |
4694 if (id & NGX_QUIC_STREAM_SERVER_INITIATED) { | |
4695 if ((id >> 2) < qc->streams.server_streams_uni) { | |
4696 return NGX_QUIC_STREAM_GONE; | |
4697 } | |
4698 | |
4699 qc->error = NGX_QUIC_ERR_STREAM_STATE_ERROR; | |
4700 return NULL; | |
4701 } | |
4702 | |
4703 if ((id >> 2) < qc->streams.client_streams_uni) { | |
4704 return NGX_QUIC_STREAM_GONE; | |
4705 } | |
4706 | |
4707 if ((id >> 2) >= qc->streams.client_max_streams_uni) { | |
4708 qc->error = NGX_QUIC_ERR_STREAM_LIMIT_ERROR; | |
4709 return NULL; | |
4710 } | |
4711 | |
4712 min_id = (qc->streams.client_streams_uni << 2) | |
4713 | NGX_QUIC_STREAM_UNIDIRECTIONAL; | |
4714 qc->streams.client_streams_uni = (id >> 2) + 1; | |
4715 n = qc->tp.initial_max_stream_data_uni; | |
4716 | |
4717 } else { | |
4718 | |
4719 if (id & NGX_QUIC_STREAM_SERVER_INITIATED) { | |
4720 if ((id >> 2) < qc->streams.server_streams_bidi) { | |
4721 return NGX_QUIC_STREAM_GONE; | |
4722 } | |
4723 | |
4724 qc->error = NGX_QUIC_ERR_STREAM_STATE_ERROR; | |
4725 return NULL; | |
4726 } | |
4727 | |
4728 if ((id >> 2) < qc->streams.client_streams_bidi) { | |
4729 return NGX_QUIC_STREAM_GONE; | |
4730 } | |
4731 | |
4732 if ((id >> 2) >= qc->streams.client_max_streams_bidi) { | |
4733 qc->error = NGX_QUIC_ERR_STREAM_LIMIT_ERROR; | |
4734 return NULL; | |
4735 } | |
4736 | |
4737 min_id = (qc->streams.client_streams_bidi << 2); | |
4738 qc->streams.client_streams_bidi = (id >> 2) + 1; | |
4739 n = qc->tp.initial_max_stream_data_bidi_remote; | |
4740 } | |
4741 | |
4742 if (n < NGX_QUIC_STREAM_BUFSIZE) { | |
4743 n = NGX_QUIC_STREAM_BUFSIZE; | |
4744 } | |
4745 | |
4746 /* | |
4747 * 2.1. Stream Types and Identifiers | |
4748 * | |
4749 * Within each type, streams are created with numerically increasing | |
4750 * stream IDs. A stream ID that is used out of order results in all | |
4751 * streams of that type with lower-numbered stream IDs also being | |
4752 * opened. | |
4753 */ | |
4754 | |
4755 for ( /* void */ ; min_id < id; min_id += 0x04) { | |
4756 | |
4757 sn = ngx_quic_create_stream(c, min_id, n); | |
4758 if (sn == NULL) { | |
4759 return NULL; | |
4760 } | |
4761 | |
4762 sn->c->listening->handler(sn->c); | |
4763 | |
4764 if (qc->shutdown) { | |
4765 return NGX_QUIC_STREAM_GONE; | |
4766 } | |
4767 } | |
4768 | |
4769 return ngx_quic_create_stream(c, id, n); | |
4770 } | |
4771 | |
4772 | |
4773 static ngx_quic_stream_t * | |
4774 ngx_quic_create_stream(ngx_connection_t *c, uint64_t id, size_t rcvbuf_size) | |
4775 { | |
4776 ngx_log_t *log; | |
4777 ngx_pool_t *pool; | |
4778 ngx_quic_stream_t *sn; | |
4779 ngx_pool_cleanup_t *cln; | |
4780 ngx_quic_connection_t *qc; | |
4781 | |
4782 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
4783 "quic stream id:0x%xL create", id); | |
4784 | |
4785 qc = ngx_quic_get_connection(c); | |
4786 | |
4787 pool = ngx_create_pool(NGX_DEFAULT_POOL_SIZE, c->log); | |
4788 if (pool == NULL) { | |
4789 return NULL; | |
4790 } | |
4791 | |
4792 sn = ngx_pcalloc(pool, sizeof(ngx_quic_stream_t)); | |
4793 if (sn == NULL) { | |
4794 ngx_destroy_pool(pool); | |
4795 return NULL; | |
4796 } | |
4797 | |
4798 sn->node.key = id; | |
4799 sn->parent = c; | |
4800 sn->id = id; | |
4801 | |
4802 sn->b = ngx_create_temp_buf(pool, rcvbuf_size); | |
4803 if (sn->b == NULL) { | |
4804 ngx_destroy_pool(pool); | |
4805 return NULL; | |
4806 } | |
4807 | |
4808 ngx_queue_init(&sn->fs.frames); | |
4809 | |
4810 log = ngx_palloc(pool, sizeof(ngx_log_t)); | |
4811 if (log == NULL) { | |
4812 ngx_destroy_pool(pool); | |
4813 return NULL; | |
4814 } | |
4815 | |
4816 *log = *c->log; | |
4817 pool->log = log; | |
4818 | |
4819 sn->c = ngx_get_connection(-1, log); | |
4820 if (sn->c == NULL) { | |
4821 ngx_destroy_pool(pool); | |
4822 return NULL; | |
4823 } | |
4824 | |
4825 sn->c->quic = sn; | |
4826 sn->c->type = SOCK_STREAM; | |
4827 sn->c->pool = pool; | |
4828 sn->c->ssl = c->ssl; | |
4829 sn->c->sockaddr = c->sockaddr; | |
4830 sn->c->listening = c->listening; | |
4831 sn->c->addr_text = c->addr_text; | |
4832 sn->c->local_sockaddr = c->local_sockaddr; | |
4833 sn->c->local_socklen = c->local_socklen; | |
4834 sn->c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1); | |
4835 | |
4836 sn->c->recv = ngx_quic_stream_recv; | |
4837 sn->c->send = ngx_quic_stream_send; | |
4838 sn->c->send_chain = ngx_quic_stream_send_chain; | |
4839 | |
4840 sn->c->read->log = log; | |
4841 sn->c->write->log = log; | |
4842 | |
4843 log->connection = sn->c->number; | |
4844 | |
4845 if ((id & NGX_QUIC_STREAM_UNIDIRECTIONAL) == 0 | |
4846 || (id & NGX_QUIC_STREAM_SERVER_INITIATED)) | |
4847 { | |
4848 sn->c->write->ready = 1; | |
4849 } | |
4850 | |
4851 if (id & NGX_QUIC_STREAM_UNIDIRECTIONAL) { | |
4852 if (id & NGX_QUIC_STREAM_SERVER_INITIATED) { | |
4853 sn->send_max_data = qc->ctp.initial_max_stream_data_uni; | |
4854 } | |
4855 | |
4856 } else { | |
4857 if (id & NGX_QUIC_STREAM_SERVER_INITIATED) { | |
4858 sn->send_max_data = qc->ctp.initial_max_stream_data_bidi_remote; | |
4859 } else { | |
4860 sn->send_max_data = qc->ctp.initial_max_stream_data_bidi_local; | |
4861 } | |
4862 } | |
4863 | |
4864 cln = ngx_pool_cleanup_add(pool, 0); | |
4865 if (cln == NULL) { | |
4866 ngx_close_connection(sn->c); | |
4867 ngx_destroy_pool(pool); | |
4868 return NULL; | |
4869 } | |
4870 | |
4871 cln->handler = ngx_quic_stream_cleanup_handler; | |
4872 cln->data = sn->c; | |
4873 | |
4874 ngx_rbtree_insert(&qc->streams.tree, &sn->node); | |
4875 | |
4876 return sn; | |
4877 } | |
4878 | |
4879 | |
4880 static ssize_t | |
4881 ngx_quic_stream_recv(ngx_connection_t *c, u_char *buf, size_t size) | |
4882 { | |
4883 ssize_t len; | |
4884 ngx_buf_t *b; | |
4885 ngx_event_t *rev; | |
4886 ngx_connection_t *pc; | |
4887 ngx_quic_frame_t *frame; | |
4888 ngx_quic_stream_t *qs; | |
4889 ngx_quic_connection_t *qc; | |
4890 | |
4891 qs = c->quic; | |
4892 b = qs->b; | |
4893 pc = qs->parent; | |
4894 qc = ngx_quic_get_connection(pc); | |
4895 rev = c->read; | |
4896 | |
4897 if (rev->error) { | |
4898 return NGX_ERROR; | |
4899 } | |
4900 | |
4901 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
4902 "quic stream recv id:0x%xL eof:%d avail:%z", | |
4903 qs->id, rev->pending_eof, b->last - b->pos); | |
4904 | |
4905 if (b->pos == b->last) { | |
4906 rev->ready = 0; | |
4907 | |
4908 if (rev->pending_eof) { | |
4909 rev->eof = 1; | |
4910 return 0; | |
4911 } | |
4912 | |
4913 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
4914 "quic stream id:0x%xL recv() not ready", qs->id); | |
4915 return NGX_AGAIN; | |
4916 } | |
4917 | |
4918 len = ngx_min(b->last - b->pos, (ssize_t) size); | |
4919 | |
4920 ngx_memcpy(buf, b->pos, len); | |
4921 | |
4922 b->pos += len; | |
4923 qc->streams.received += len; | |
4924 | |
4925 if (b->pos == b->last) { | |
4926 b->pos = b->start; | |
4927 b->last = b->start; | |
4928 rev->ready = rev->pending_eof; | |
4929 } | |
4930 | |
4931 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
4932 "quic stream id:0x%xL recv len:%z of size:%uz", | |
4933 qs->id, len, size); | |
4934 | |
4935 if (!rev->pending_eof) { | |
4936 frame = ngx_quic_alloc_frame(pc); | |
4937 if (frame == NULL) { | |
4938 return NGX_ERROR; | |
4939 } | |
4940 | |
4941 frame->level = ssl_encryption_application; | |
4942 frame->type = NGX_QUIC_FT_MAX_STREAM_DATA; | |
4943 frame->u.max_stream_data.id = qs->id; | |
4944 frame->u.max_stream_data.limit = qs->fs.received + (b->pos - b->start) | |
4945 + (b->end - b->last); | |
4946 | |
4947 ngx_quic_queue_frame(qc, frame); | |
4948 } | |
4949 | |
4950 if ((qc->streams.recv_max_data / 2) < qc->streams.received) { | |
4951 | |
4952 frame = ngx_quic_alloc_frame(pc); | |
4953 | |
4954 if (frame == NULL) { | |
4955 return NGX_ERROR; | |
4956 } | |
4957 | |
4958 qc->streams.recv_max_data *= 2; | |
4959 | |
4960 frame->level = ssl_encryption_application; | |
4961 frame->type = NGX_QUIC_FT_MAX_DATA; | |
4962 frame->u.max_data.max_data = qc->streams.recv_max_data; | |
4963 | |
4964 ngx_quic_queue_frame(qc, frame); | |
4965 | |
4966 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
4967 "quic stream id:0x%xL recv: increased max_data:%uL", | |
4968 qs->id, qc->streams.recv_max_data); | |
4969 } | |
4970 | |
4971 return len; | |
4972 } | |
4973 | |
4974 | |
4975 static ssize_t | |
4976 ngx_quic_stream_send(ngx_connection_t *c, u_char *buf, size_t size) | |
4977 { | |
4978 ngx_buf_t b; | |
4979 ngx_chain_t cl; | |
4980 | |
4981 ngx_memzero(&b, sizeof(ngx_buf_t)); | |
4982 | |
4983 b.memory = 1; | |
4984 b.pos = buf; | |
4985 b.last = buf + size; | |
4986 | |
4987 cl.buf = &b; | |
4988 cl.next = NULL; | |
4989 | |
4990 if (ngx_quic_stream_send_chain(c, &cl, 0) == NGX_CHAIN_ERROR) { | |
4991 return NGX_ERROR; | |
4992 } | |
4993 | |
4994 if (b.pos == buf) { | |
4995 return NGX_AGAIN; | |
4996 } | |
4997 | |
4998 return b.pos - buf; | |
4999 } | |
5000 | |
5001 | |
5002 static ngx_chain_t * | |
5003 ngx_quic_stream_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) | |
5004 { | |
5005 size_t n, flow; | |
5006 ngx_event_t *wev; | |
5007 ngx_chain_t *cl; | |
5008 ngx_connection_t *pc; | |
5009 ngx_quic_frame_t *frame; | |
5010 ngx_quic_stream_t *qs; | |
5011 ngx_quic_connection_t *qc; | |
5012 | |
5013 qs = c->quic; | |
5014 pc = qs->parent; | |
5015 qc = ngx_quic_get_connection(pc); | |
5016 wev = c->write; | |
5017 | |
5018 if (wev->error) { | |
5019 return NGX_CHAIN_ERROR; | |
5020 } | |
5021 | |
5022 flow = ngx_quic_max_stream_flow(c); | |
5023 if (flow == 0) { | |
5024 wev->ready = 0; | |
5025 return in; | |
5026 } | |
5027 | |
5028 n = (limit && (size_t) limit < flow) ? (size_t) limit : flow; | |
5029 | |
5030 frame = ngx_quic_alloc_frame(pc); | |
5031 if (frame == NULL) { | |
5032 return NGX_CHAIN_ERROR; | |
5033 } | |
5034 | |
5035 frame->data = ngx_quic_copy_chain(pc, in, n); | |
5036 if (frame->data == NGX_CHAIN_ERROR) { | |
5037 return NGX_CHAIN_ERROR; | |
5038 } | |
5039 | |
5040 for (n = 0, cl = frame->data; cl; cl = cl->next) { | |
5041 n += ngx_buf_size(cl->buf); | |
5042 } | |
5043 | |
5044 while (in && ngx_buf_size(in->buf) == 0) { | |
5045 in = in->next; | |
5046 } | |
5047 | |
5048 frame->level = ssl_encryption_application; | |
5049 frame->type = NGX_QUIC_FT_STREAM6; /* OFF=1 LEN=1 FIN=0 */ | |
5050 frame->u.stream.off = 1; | |
5051 frame->u.stream.len = 1; | |
5052 frame->u.stream.fin = 0; | |
5053 | |
5054 frame->u.stream.type = frame->type; | |
5055 frame->u.stream.stream_id = qs->id; | |
5056 frame->u.stream.offset = c->sent; | |
5057 frame->u.stream.length = n; | |
5058 | |
5059 c->sent += n; | |
5060 qc->streams.sent += n; | |
5061 | |
5062 ngx_quic_queue_frame(qc, frame); | |
5063 | |
5064 wev->ready = (n < flow) ? 1 : 0; | |
5065 | |
5066 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
5067 "quic send_chain sent:%uz", n); | |
5068 | |
5069 return in; | |
5070 } | |
5071 | |
5072 | |
5073 static size_t | |
5074 ngx_quic_max_stream_flow(ngx_connection_t *c) | |
5075 { | |
5076 size_t size; | |
5077 uint64_t sent, unacked; | |
5078 ngx_quic_stream_t *qs; | |
5079 ngx_quic_connection_t *qc; | |
5080 | |
5081 qs = c->quic; | |
5082 qc = ngx_quic_get_connection(qs->parent); | |
5083 | |
5084 size = NGX_QUIC_STREAM_BUFSIZE; | |
5085 sent = c->sent; | |
5086 unacked = sent - qs->acked; | |
5087 | |
5088 if (qc->streams.send_max_data == 0) { | |
5089 qc->streams.send_max_data = qc->ctp.initial_max_data; | |
5090 } | |
5091 | |
5092 if (unacked >= NGX_QUIC_STREAM_BUFSIZE) { | |
5093 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
5094 "quic send flow hit buffer size"); | |
5095 return 0; | |
5096 } | |
5097 | |
5098 if (unacked + size > NGX_QUIC_STREAM_BUFSIZE) { | |
5099 size = NGX_QUIC_STREAM_BUFSIZE - unacked; | |
5100 } | |
5101 | |
5102 if (qc->streams.sent >= qc->streams.send_max_data) { | |
5103 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
5104 "quic send flow hit MAX_DATA"); | |
5105 return 0; | |
5106 } | |
5107 | |
5108 if (qc->streams.sent + size > qc->streams.send_max_data) { | |
5109 size = qc->streams.send_max_data - qc->streams.sent; | |
5110 } | |
5111 | |
5112 if (sent >= qs->send_max_data) { | |
5113 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
5114 "quic send flow hit MAX_STREAM_DATA"); | |
5115 return 0; | |
5116 } | |
5117 | |
5118 if (sent + size > qs->send_max_data) { | |
5119 size = qs->send_max_data - sent; | |
5120 } | |
5121 | |
5122 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
5123 "quic send flow:%uz", size); | |
5124 | |
5125 return size; | |
5126 } | |
5127 | |
5128 | |
5129 static void | |
5130 ngx_quic_stream_cleanup_handler(void *data) | |
5131 { | |
5132 ngx_connection_t *c = data; | |
5133 | |
5134 ngx_connection_t *pc; | |
5135 ngx_quic_frame_t *frame; | |
5136 ngx_quic_stream_t *qs; | |
5137 ngx_quic_connection_t *qc; | |
5138 | |
5139 qs = c->quic; | |
5140 pc = qs->parent; | |
5141 qc = ngx_quic_get_connection(pc); | |
5142 | |
5143 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
5144 "quic stream id:0x%xL cleanup", qs->id); | |
5145 | |
5146 ngx_rbtree_delete(&qc->streams.tree, &qs->node); | |
5147 ngx_quic_free_frames(pc, &qs->fs.frames); | |
5148 | |
5149 if (qc->closing) { | |
5150 /* schedule handler call to continue ngx_quic_close_connection() */ | |
5151 ngx_post_event(pc->read, &ngx_posted_events); | |
5152 return; | |
5153 } | |
5154 | |
5155 if ((qs->id & NGX_QUIC_STREAM_SERVER_INITIATED) == 0 | |
5156 || (qs->id & NGX_QUIC_STREAM_UNIDIRECTIONAL) == 0) | |
5157 { | |
5158 if (!c->read->pending_eof && !c->read->error) { | |
5159 frame = ngx_quic_alloc_frame(pc); | |
5160 if (frame == NULL) { | |
5161 goto done; | |
5162 } | |
5163 | |
5164 frame->level = ssl_encryption_application; | |
5165 frame->type = NGX_QUIC_FT_STOP_SENDING; | |
5166 frame->u.stop_sending.id = qs->id; | |
5167 frame->u.stop_sending.error_code = 0x100; /* HTTP/3 no error */ | |
5168 | |
5169 ngx_quic_queue_frame(qc, frame); | |
5170 } | |
5171 } | |
5172 | |
5173 if ((qs->id & NGX_QUIC_STREAM_SERVER_INITIATED) == 0) { | |
5174 frame = ngx_quic_alloc_frame(pc); | |
5175 if (frame == NULL) { | |
5176 goto done; | |
5177 } | |
5178 | |
5179 frame->level = ssl_encryption_application; | |
5180 frame->type = NGX_QUIC_FT_MAX_STREAMS; | |
5181 | |
5182 if (qs->id & NGX_QUIC_STREAM_UNIDIRECTIONAL) { | |
5183 frame->u.max_streams.limit = ++qc->streams.client_max_streams_uni; | |
5184 frame->u.max_streams.bidi = 0; | |
5185 | |
5186 } else { | |
5187 frame->u.max_streams.limit = ++qc->streams.client_max_streams_bidi; | |
5188 frame->u.max_streams.bidi = 1; | |
5189 } | |
5190 | |
5191 ngx_quic_queue_frame(qc, frame); | |
5192 | |
5193 if (qs->id & NGX_QUIC_STREAM_UNIDIRECTIONAL) { | |
5194 /* do not send fin for client unidirectional streams */ | |
5195 goto done; | |
5196 } | |
5197 } | |
5198 | |
5199 if (c->write->error) { | |
5200 goto done; | |
5201 } | |
5202 | |
5203 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
5204 "quic stream id:0x%xL send fin", qs->id); | |
5205 | |
5206 frame = ngx_quic_alloc_frame(pc); | |
5207 if (frame == NULL) { | |
5208 goto done; | |
5209 } | |
5210 | |
5211 frame->level = ssl_encryption_application; | |
5212 frame->type = NGX_QUIC_FT_STREAM7; /* OFF=1 LEN=1 FIN=1 */ | |
5213 frame->u.stream.off = 1; | |
5214 frame->u.stream.len = 1; | |
5215 frame->u.stream.fin = 1; | |
5216 | |
5217 frame->u.stream.type = frame->type; | |
5218 frame->u.stream.stream_id = qs->id; | |
5219 frame->u.stream.offset = c->sent; | |
5220 frame->u.stream.length = 0; | |
5221 | |
5222 ngx_quic_queue_frame(qc, frame); | |
5223 | |
5224 done: | |
5225 | |
5226 (void) ngx_quic_output(pc); | |
5227 | |
5228 if (qc->shutdown) { | |
5229 ngx_quic_shutdown_quic(pc); | |
5230 } | |
5231 } | |
5232 | |
5233 | |
5234 static void | |
5235 ngx_quic_shutdown_quic(ngx_connection_t *c) | 3952 ngx_quic_shutdown_quic(ngx_connection_t *c) |
5236 { | 3953 { |
5237 ngx_rbtree_t *tree; | 3954 ngx_rbtree_t *tree; |
5238 ngx_rbtree_node_t *node; | 3955 ngx_rbtree_node_t *node; |
5239 ngx_quic_stream_t *qs; | 3956 ngx_quic_stream_t *qs; |