mirror of
https://github.com/nginx/nginx.git
synced 2024-11-21 16:28:40 +00:00
QUIC: send DATA_BLOCKED frame
This commit is contained in:
parent
00637cce36
commit
9b1b2c4220
@ -628,6 +628,12 @@ ngx_quic_resend_frames(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx)
|
||||
ngx_quic_queue_frame(qc, f);
|
||||
break;
|
||||
|
||||
case NGX_QUIC_FT_DATA_BLOCKED:
|
||||
if (qc->streams.send_max_data == f->u.data_blocked.limit) {
|
||||
ngx_queue_insert_tail(&ctx->frames, &f->queue);
|
||||
}
|
||||
break;
|
||||
|
||||
case NGX_QUIC_FT_STREAM:
|
||||
qs = ngx_quic_find_stream(&qc->streams.tree, f->u.stream.stream_id);
|
||||
|
||||
|
@ -159,8 +159,8 @@ typedef struct {
|
||||
uint64_t client_streams_uni;
|
||||
uint64_t client_streams_bidi;
|
||||
|
||||
ngx_uint_t initialized;
|
||||
/* unsigned initialized:1; */
|
||||
unsigned initialized:1;
|
||||
unsigned flow_control_blocked:1;
|
||||
} ngx_quic_streams_t;
|
||||
|
||||
|
||||
|
@ -1046,6 +1046,30 @@ ngx_quic_stream_flush(ngx_quic_stream_t *qs)
|
||||
}
|
||||
|
||||
if (len == 0 && !last) {
|
||||
/*
|
||||
* RFC 9000, 4.1. Data Flow Control
|
||||
*
|
||||
* A sender SHOULD send a STREAM_DATA_BLOCKED or DATA_BLOCKED frame to
|
||||
* indicate to the receiver that it has data to write but is blocked by
|
||||
* flow control limits.
|
||||
*/
|
||||
if (qc->streams.send_max_data == qc->streams.send_offset
|
||||
&& !qc->streams.flow_control_blocked)
|
||||
{
|
||||
qc->streams.flow_control_blocked = 1;
|
||||
|
||||
frame = ngx_quic_alloc_frame(pc);
|
||||
if (frame == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
frame->level = ssl_encryption_application;
|
||||
frame->type = NGX_QUIC_FT_DATA_BLOCKED;
|
||||
frame->u.data_blocked.limit = qc->streams.send_max_data;
|
||||
|
||||
ngx_quic_queue_frame(qc, frame);
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
@ -1336,6 +1360,8 @@ ngx_quic_handle_max_data_frame(ngx_connection_t *c,
|
||||
}
|
||||
|
||||
qc->streams.send_max_data = f->max_data;
|
||||
qc->streams.flow_control_blocked = 0;
|
||||
|
||||
node = ngx_rbtree_min(tree->root, tree->sentinel);
|
||||
|
||||
while (node && qc->streams.send_offset < qc->streams.send_max_data) {
|
||||
|
@ -118,6 +118,8 @@ static size_t ngx_quic_create_max_stream_data(u_char *p,
|
||||
ngx_quic_max_stream_data_frame_t *ms);
|
||||
static size_t ngx_quic_create_max_data(u_char *p,
|
||||
ngx_quic_max_data_frame_t *md);
|
||||
static size_t ngx_quic_create_data_blocked(u_char *p,
|
||||
ngx_quic_data_blocked_frame_t *db);
|
||||
static size_t ngx_quic_create_path_challenge(u_char *p,
|
||||
ngx_quic_path_challenge_frame_t *pc);
|
||||
static size_t ngx_quic_create_path_response(u_char *p,
|
||||
@ -1323,6 +1325,9 @@ ngx_quic_create_frame(u_char *p, ngx_quic_frame_t *f)
|
||||
case NGX_QUIC_FT_MAX_DATA:
|
||||
return ngx_quic_create_max_data(p, &f->u.max_data);
|
||||
|
||||
case NGX_QUIC_FT_DATA_BLOCKED:
|
||||
return ngx_quic_create_data_blocked(p, &f->u.data_blocked);
|
||||
|
||||
case NGX_QUIC_FT_PATH_CHALLENGE:
|
||||
return ngx_quic_create_path_challenge(p, &f->u.path_challenge);
|
||||
|
||||
@ -1884,6 +1889,27 @@ ngx_quic_create_max_data(u_char *p, ngx_quic_max_data_frame_t *md)
|
||||
}
|
||||
|
||||
|
||||
static size_t
|
||||
ngx_quic_create_data_blocked(u_char *p, ngx_quic_data_blocked_frame_t *db)
|
||||
{
|
||||
size_t len;
|
||||
u_char *start;
|
||||
|
||||
if (p == NULL) {
|
||||
len = ngx_quic_varint_len(NGX_QUIC_FT_DATA_BLOCKED);
|
||||
len += ngx_quic_varint_len(db->limit);
|
||||
return len;
|
||||
}
|
||||
|
||||
start = p;
|
||||
|
||||
ngx_quic_build_int(&p, NGX_QUIC_FT_DATA_BLOCKED);
|
||||
ngx_quic_build_int(&p, db->limit);
|
||||
|
||||
return p - start;
|
||||
}
|
||||
|
||||
|
||||
static size_t
|
||||
ngx_quic_create_path_challenge(u_char *p, ngx_quic_path_challenge_frame_t *pc)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user