HTTP/3: send GOAWAY when last request is accepted.

The last request in connection is determined according to the keepalive_requests
directive.  Requests beyond keepalive_requests are rejected.
This commit is contained in:
Roman Arutyunyan 2021-03-15 19:26:04 +03:00
parent d8fd0b3161
commit 190b5d961c
3 changed files with 56 additions and 0 deletions

View File

@ -161,6 +161,7 @@ ngx_int_t ngx_http_v3_init_session(ngx_connection_t *c);
void ngx_http_v3_init_uni_stream(ngx_connection_t *c);
ngx_connection_t *ngx_http_v3_create_push_stream(ngx_connection_t *c,
uint64_t push_id);
ngx_int_t ngx_http_v3_send_goaway(ngx_connection_t *c, uint64_t id);
ngx_int_t ngx_http_v3_ref_insert(ngx_connection_t *c, ngx_uint_t dynamic,
ngx_uint_t index, ngx_str_t *value);
ngx_int_t ngx_http_v3_insert(ngx_connection_t *c, ngx_str_t *name,

View File

@ -52,10 +52,12 @@ void
ngx_http_v3_init(ngx_connection_t *c)
{
size_t size;
uint64_t n;
ngx_buf_t *b;
ngx_event_t *rev;
ngx_http_request_t *r;
ngx_http_connection_t *hc;
ngx_http_core_loc_conf_t *clcf;
ngx_http_core_srv_conf_t *cscf;
if (ngx_http_v3_init_session(c) != NGX_OK) {
@ -74,6 +76,25 @@ ngx_http_v3_init(ngx_connection_t *c)
hc = c->data;
clcf = ngx_http_get_module_loc_conf(hc->conf_ctx, ngx_http_core_module);
n = c->quic->id >> 2;
if (n >= clcf->keepalive_requests) {
ngx_quic_reset_stream(c, NGX_HTTP_V3_ERR_REQUEST_REJECTED);
ngx_http_close_connection(c);
return;
}
if (n + 1 == clcf->keepalive_requests) {
if (ngx_http_v3_send_goaway(c, (n + 1) << 2) != NGX_OK) {
ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_INTERNAL_ERROR,
"goaway error");
ngx_http_close_connection(c);
return;
}
}
cscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_core_module);
size = cscf->client_header_buffer_size;

View File

@ -522,6 +522,40 @@ failed:
}
ngx_int_t
ngx_http_v3_send_goaway(ngx_connection_t *c, uint64_t id)
{
u_char *p, buf[NGX_HTTP_V3_VARLEN_INT_LEN * 3];
size_t n;
ngx_connection_t *cc;
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 send goaway %uL", id);
cc = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_CONTROL);
if (cc == NULL) {
return NGX_DECLINED;
}
n = ngx_http_v3_encode_varlen_int(NULL, id);
p = (u_char *) ngx_http_v3_encode_varlen_int(buf, NGX_HTTP_V3_FRAME_GOAWAY);
p = (u_char *) ngx_http_v3_encode_varlen_int(p, n);
p = (u_char *) ngx_http_v3_encode_varlen_int(p, id);
n = p - buf;
if (cc->send(cc, buf, n) != (ssize_t) n) {
goto failed;
}
return NGX_OK;
failed:
ngx_http_v3_close_uni_stream(cc);
return NGX_ERROR;
}
ngx_int_t
ngx_http_v3_client_ref_insert(ngx_connection_t *c, ngx_uint_t dynamic,
ngx_uint_t index, ngx_str_t *value)