QUIC: ngx_quic_set_error() function.

The function sets QUIC error unless it was set before.  Previously, a new
error always reset the old error.  Now the original error stays unchanged
for logging and sending to client.
This commit is contained in:
Roman Arutyunyan 2025-05-23 13:53:33 +04:00
parent eed8765a5f
commit 77c082903e
7 changed files with 146 additions and 108 deletions

View File

@ -135,8 +135,8 @@ ngx_quic_apply_transport_params(ngx_connection_t *c, ngx_quic_tp_t *ctp)
if (scid.len != ctp->initial_scid.len
|| ngx_memcmp(scid.data, ctp->initial_scid.data, scid.len) != 0)
{
qc->error = NGX_QUIC_ERR_TRANSPORT_PARAMETER_ERROR;
qc->error_reason = "invalid initial_source_connection_id";
ngx_quic_set_error(c, NGX_QUIC_ERR_TRANSPORT_PARAMETER_ERROR,
"invalid initial_source_connection_id");
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"quic client initial_source_connection_id mismatch");
@ -146,8 +146,8 @@ ngx_quic_apply_transport_params(ngx_connection_t *c, ngx_quic_tp_t *ctp)
if (ctp->max_udp_payload_size < NGX_QUIC_MIN_INITIAL_SIZE
|| ctp->max_udp_payload_size > NGX_QUIC_MAX_UDP_PAYLOAD_SIZE)
{
qc->error = NGX_QUIC_ERR_TRANSPORT_PARAMETER_ERROR;
qc->error_reason = "invalid maximum packet size";
ngx_quic_set_error(c, NGX_QUIC_ERR_TRANSPORT_PARAMETER_ERROR,
"invalid maximum packet size");
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"quic maximum packet size is invalid");
@ -155,8 +155,8 @@ ngx_quic_apply_transport_params(ngx_connection_t *c, ngx_quic_tp_t *ctp)
}
if (ctp->active_connection_id_limit < 2) {
qc->error = NGX_QUIC_ERR_TRANSPORT_PARAMETER_ERROR;
qc->error_reason = "invalid active_connection_id_limit";
ngx_quic_set_error(c, NGX_QUIC_ERR_TRANSPORT_PARAMETER_ERROR,
"invalid active_connection_id_limit");
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"quic active_connection_id_limit is invalid");
@ -164,8 +164,8 @@ ngx_quic_apply_transport_params(ngx_connection_t *c, ngx_quic_tp_t *ctp)
}
if (ctp->ack_delay_exponent > 20) {
qc->error = NGX_QUIC_ERR_TRANSPORT_PARAMETER_ERROR;
qc->error_reason = "invalid ack_delay_exponent";
ngx_quic_set_error(c, NGX_QUIC_ERR_TRANSPORT_PARAMETER_ERROR,
"invalid ack_delay_exponent");
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"quic ack_delay_exponent is invalid");
@ -173,8 +173,8 @@ ngx_quic_apply_transport_params(ngx_connection_t *c, ngx_quic_tp_t *ctp)
}
if (ctp->max_ack_delay >= 16384) {
qc->error = NGX_QUIC_ERR_TRANSPORT_PARAMETER_ERROR;
qc->error_reason = "invalid max_ack_delay";
ngx_quic_set_error(c, NGX_QUIC_ERR_TRANSPORT_PARAMETER_ERROR,
"invalid max_ack_delay");
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"quic max_ack_delay is invalid");
@ -426,8 +426,7 @@ ngx_quic_input_handler(ngx_event_t *rev)
c->close = 0;
if (!ngx_exiting || !qc->streams.initialized) {
qc->error = NGX_QUIC_ERR_NO_ERROR;
qc->error_reason = "graceful shutdown";
ngx_quic_set_error(c, NGX_QUIC_ERR_NO_ERROR, "graceful shutdown");
ngx_quic_close_connection(c, NGX_ERROR);
return;
}
@ -520,9 +519,9 @@ ngx_quic_close_connection(ngx_connection_t *c, ngx_int_t rc)
* to terminate the connection immediately.
*/
if (qc->error == 0 && rc == NGX_ERROR) {
qc->error = NGX_QUIC_ERR_INTERNAL_ERROR;
qc->error_app = 0;
if (rc == NGX_ERROR) {
ngx_quic_set_error(c, NGX_QUIC_ERR_INTERNAL_ERROR,
"internal server error");
}
ngx_log_debug5(NGX_LOG_DEBUG_EVENT, c->log, 0,
@ -621,6 +620,25 @@ quic_done:
}
void
ngx_quic_set_error(ngx_connection_t *c, ngx_uint_t err, const char *reason)
{
ngx_quic_connection_t *qc;
qc = ngx_quic_get_connection(c);
if (qc->error) {
return;
}
qc->error = err;
qc->error_reason = reason;
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic error c:%ui r:\"%s\"",
err, reason);
}
void
ngx_quic_finalize_connection(ngx_connection_t *c, ngx_uint_t err,
const char *reason)
@ -629,7 +647,7 @@ ngx_quic_finalize_connection(ngx_connection_t *c, ngx_uint_t err,
qc = ngx_quic_get_connection(c);
if (qc->closing) {
if (qc->error) {
return;
}
@ -637,6 +655,9 @@ ngx_quic_finalize_connection(ngx_connection_t *c, ngx_uint_t err,
qc->error_reason = reason;
qc->error_app = 1;
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic error app c:%ui r:\"%s\"", err, reason);
ngx_post_event(&qc->close, &ngx_posted_events);
}
@ -764,8 +785,8 @@ ngx_quic_handle_datagram(ngx_connection_t *c, ngx_buf_t *b,
{
ngx_log_error(NGX_LOG_INFO, c->log, 0, "quic flood detected");
qc->error = NGX_QUIC_ERR_NO_ERROR;
qc->error_reason = "QUIC flood detected";
ngx_quic_set_error(c, NGX_QUIC_ERR_NO_ERROR,
"quic flood detected");
return NGX_ERROR;
}
}
@ -993,8 +1014,7 @@ ngx_quic_handle_payload(ngx_connection_t *c, ngx_quic_header_t *pkt)
rc = ngx_quic_decrypt(pkt, &ctx->largest_pn);
if (rc != NGX_OK) {
qc->error = pkt->error;
qc->error_reason = "failed to decrypt packet";
ngx_quic_set_error(c, pkt->error, "failed to decrypt packet");
return rc;
}
@ -1053,9 +1073,10 @@ ngx_quic_handle_payload(ngx_connection_t *c, ngx_quic_header_t *pkt)
*/
qc->error_level = pkt->level;
qc->error = NGX_QUIC_ERR_NO_ERROR;
qc->error_reason = "connection is closing, packet discarded";
qc->error_app = 0;
ngx_quic_set_error(c, NGX_QUIC_ERR_NO_ERROR,
"connection is closing, packet discarded");
return ngx_quic_send_cc(c);
}
@ -1202,7 +1223,7 @@ ngx_quic_handle_frames(ngx_connection_t *c, ngx_quic_header_t *pkt)
len = ngx_quic_parse_frame(pkt, p, end, &frame);
if (len < 0) {
qc->error = pkt->error;
ngx_quic_set_error(c, pkt->error, "failed to parse frame");
return NGX_ERROR;
}
@ -1405,6 +1426,9 @@ ngx_quic_handle_frames(ngx_connection_t *c, ngx_quic_header_t *pkt)
default:
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic missing frame handler");
ngx_quic_set_error(c, NGX_QUIC_ERR_PROTOCOL_VIOLATION,
"unexpected frame type");
return NGX_ERROR;
}
@ -1417,7 +1441,8 @@ ngx_quic_handle_frames(ngx_connection_t *c, ngx_quic_header_t *pkt)
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"quic trailing garbage in payload:%ui bytes", end - p);
qc->error = NGX_QUIC_ERR_FRAME_ENCODING_ERROR;
ngx_quic_set_error(c, NGX_QUIC_ERR_FRAME_ENCODING_ERROR,
"trailing garbage in quic payload");
return NGX_ERROR;
}

View File

@ -120,7 +120,9 @@ ngx_quic_handle_ack_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
*/
if (ack->first_range > ack->largest) {
qc->error = NGX_QUIC_ERR_FRAME_ENCODING_ERROR;
ngx_quic_set_error(c, NGX_QUIC_ERR_FRAME_ENCODING_ERROR,
"invalid first range in ack frame");
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"quic invalid first range in ack frame");
return NGX_ERROR;
@ -177,7 +179,9 @@ ngx_quic_handle_ack_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
pos += n;
if (gap + 2 > min) {
qc->error = NGX_QUIC_ERR_FRAME_ENCODING_ERROR;
ngx_quic_set_error(c, NGX_QUIC_ERR_FRAME_ENCODING_ERROR,
"invalid range in ack frame");
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"quic invalid range:%ui in ack frame", i);
return NGX_ERROR;
@ -186,7 +190,9 @@ ngx_quic_handle_ack_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
max = min - gap - 2;
if (range > max) {
qc->error = NGX_QUIC_ERR_FRAME_ENCODING_ERROR;
ngx_quic_set_error(c, NGX_QUIC_ERR_FRAME_ENCODING_ERROR,
"invalid range in ack frame");
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"quic invalid range:%ui in ack frame", i);
return NGX_ERROR;
@ -324,8 +330,8 @@ ngx_quic_handle_ack_frame_range(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"quic ACK for the packet not sent");
qc->error = NGX_QUIC_ERR_PROTOCOL_VIOLATION;
qc->error_reason = "unknown packet number";
ngx_quic_set_error(c, NGX_QUIC_ERR_PROTOCOL_VIOLATION,
"unsent packet acknowledged");
return NGX_ERROR;
}

View File

@ -309,6 +309,8 @@ struct ngx_quic_connection_s {
};
void ngx_quic_set_error(ngx_connection_t *c, ngx_uint_t err,
const char *reason);
ngx_int_t ngx_quic_apply_transport_params(ngx_connection_t *c,
ngx_quic_tp_t *ctp);
void ngx_quic_discard_ctx(ngx_connection_t *c, ngx_uint_t level);

View File

@ -137,8 +137,9 @@ ngx_quic_handle_new_connection_id_frame(ngx_connection_t *c,
* the endpoint MAY treat that receipt as a connection error
* of type PROTOCOL_VIOLATION.
*/
qc->error = NGX_QUIC_ERR_PROTOCOL_VIOLATION;
qc->error_reason = "seqnum refers to different connection id/token";
ngx_quic_set_error(c, NGX_QUIC_ERR_PROTOCOL_VIOLATION,
"seqnum refers to different "
"connection id/token");
return NGX_ERROR;
}
@ -194,8 +195,8 @@ done:
* active_connection_id_limit transport parameter, an endpoint MUST
* close the connection with an error of type CONNECTION_ID_LIMIT_ERROR.
*/
qc->error = NGX_QUIC_ERR_CONNECTION_ID_LIMIT_ERROR;
qc->error_reason = "too many connection ids received";
ngx_quic_set_error(c, NGX_QUIC_ERR_CONNECTION_ID_LIMIT_ERROR,
"too many connection ids received");
return NGX_ERROR;
}
@ -357,8 +358,8 @@ ngx_quic_handle_retire_connection_id_frame(ngx_connection_t *c,
* number greater than any previously sent to the peer MUST be
* treated as a connection error of type PROTOCOL_VIOLATION.
*/
qc->error = NGX_QUIC_ERR_PROTOCOL_VIOLATION;
qc->error_reason = "sequence number of id to retire was never issued";
ngx_quic_set_error(c, NGX_QUIC_ERR_PROTOCOL_VIOLATION,
"sequence number of id to retire was never issued");
return NGX_ERROR;
}
@ -375,9 +376,8 @@ ngx_quic_handle_retire_connection_id_frame(ngx_connection_t *c,
* which the frame is contained. The peer MAY treat this as a
* connection error of type PROTOCOL_VIOLATION.
*/
qc->error = NGX_QUIC_ERR_PROTOCOL_VIOLATION;
qc->error_reason = "sequence number of id to retire refers DCID";
ngx_quic_set_error(c, NGX_QUIC_ERR_PROTOCOL_VIOLATION,
"sequence number of id to retire refers DCID");
return NGX_ERROR;
}

View File

@ -799,8 +799,8 @@ ngx_quic_expire_path_validation(ngx_connection_t *c, ngx_quic_path_t *path)
bkp = ngx_quic_get_path(c, NGX_QUIC_PATH_BACKUP);
if (bkp == NULL) {
qc->error = NGX_QUIC_ERR_NO_VIABLE_PATH;
qc->error_reason = "no viable path";
ngx_quic_set_error(c, NGX_QUIC_ERR_NO_VIABLE_PATH,
"no viable path");
return NGX_ERROR;
}

View File

@ -88,8 +88,9 @@ ngx_quic_cbs_send(ngx_ssl_conn_t *ssl_conn,
SSL_get0_alpn_selected(ssl_conn, &alpn_data, &alpn_len);
if (alpn_len == 0) {
qc->error = NGX_QUIC_ERR_CRYPTO(SSL_AD_NO_APPLICATION_PROTOCOL);
qc->error_reason = "missing ALPN extension";
ngx_quic_set_error(c,
NGX_QUIC_ERR_CRYPTO(SSL_AD_NO_APPLICATION_PROTOCOL),
"missing ALPN extension");
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"quic missing ALPN extension");
@ -98,8 +99,8 @@ ngx_quic_cbs_send(ngx_ssl_conn_t *ssl_conn,
if (!qc->client_tp_done) {
/* RFC 9001, 8.2. QUIC Transport Parameters Extension */
qc->error = NGX_QUIC_ERR_CRYPTO(SSL_AD_MISSING_EXTENSION);
qc->error_reason = "missing transport parameters";
ngx_quic_set_error(c, NGX_QUIC_ERR_CRYPTO(SSL_AD_MISSING_EXTENSION),
"missing transport parameters");
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"missing transport parameters");
@ -110,13 +111,13 @@ ngx_quic_cbs_send(ngx_ssl_conn_t *ssl_conn,
out = ngx_quic_copy_buffer(c, (u_char *) data, len);
if (out == NGX_CHAIN_ERROR) {
qc->error = NGX_QUIC_ERR_INTERNAL_ERROR;
ngx_quic_set_error(c, NGX_QUIC_ERR_INTERNAL_ERROR, "buffer error");
return 1;
}
frame = ngx_quic_alloc_frame(c);
if (frame == NULL) {
qc->error = NGX_QUIC_ERR_INTERNAL_ERROR;
ngx_quic_set_error(c, NGX_QUIC_ERR_INTERNAL_ERROR, "memory error");
return 1;
}
@ -190,7 +191,7 @@ ngx_quic_cbs_release_rcd(ngx_ssl_conn_t *ssl_conn, size_t bytes_read, void *arg)
cl = ngx_quic_read_buffer(c, &ctx->crypto, bytes_read);
if (cl == NGX_CHAIN_ERROR) {
qc->error = NGX_QUIC_ERR_INTERNAL_ERROR;
ngx_quic_set_error(c, NGX_QUIC_ERR_INTERNAL_ERROR, "buffer error");
return 1;
}
@ -241,7 +242,7 @@ ngx_quic_cbs_yield_secret(ngx_ssl_conn_t *ssl_conn, uint32_t ssl_level,
cipher, secret, secret_len)
!= NGX_OK)
{
qc->error = NGX_QUIC_ERR_INTERNAL_ERROR;
ngx_quic_set_error(c, NGX_QUIC_ERR_INTERNAL_ERROR, "key error");
return 1;
}
@ -279,9 +280,8 @@ ngx_quic_cbs_got_transport_params(ngx_ssl_conn_t *ssl_conn,
end = p + params_len;
if (ngx_quic_parse_transport_params(p, end, &ctp, c->log) != NGX_OK) {
qc->error = NGX_QUIC_ERR_TRANSPORT_PARAMETER_ERROR;
qc->error_reason = "failed to process transport parameters";
ngx_quic_set_error(c, NGX_QUIC_ERR_TRANSPORT_PARAMETER_ERROR,
"failed to process transport parameters");
return 1;
}
@ -312,8 +312,7 @@ ngx_quic_cbs_alert(ngx_ssl_conn_t *ssl_conn, unsigned char alert, void *arg)
return 1;
}
qc->error = NGX_QUIC_ERR_CRYPTO(alert);
qc->error_reason = "handshake failed";
ngx_quic_set_error(c, NGX_QUIC_ERR_CRYPTO(alert), "handshake error");
return 1;
}
@ -365,7 +364,7 @@ ngx_quic_set_read_secret(ngx_ssl_conn_t *ssl_conn,
cipher, rsecret, secret_len)
!= NGX_OK)
{
qc->error = NGX_QUIC_ERR_INTERNAL_ERROR;
ngx_quic_set_error(c, NGX_QUIC_ERR_INTERNAL_ERROR, "key error");
}
return 1;
@ -397,7 +396,7 @@ ngx_quic_set_write_secret(ngx_ssl_conn_t *ssl_conn,
cipher, wsecret, secret_len)
!= NGX_OK)
{
qc->error = NGX_QUIC_ERR_INTERNAL_ERROR;
ngx_quic_set_error(c, NGX_QUIC_ERR_INTERNAL_ERROR, "key error");
}
return 1;
@ -434,7 +433,7 @@ ngx_quic_set_encryption_secrets(ngx_ssl_conn_t *ssl_conn,
cipher, rsecret, secret_len)
!= NGX_OK)
{
qc->error = NGX_QUIC_ERR_INTERNAL_ERROR;
ngx_quic_set_error(c, NGX_QUIC_ERR_INTERNAL_ERROR, "key error");
return 1;
}
@ -452,7 +451,7 @@ ngx_quic_set_encryption_secrets(ngx_ssl_conn_t *ssl_conn,
cipher, wsecret, secret_len)
!= NGX_OK)
{
qc->error = NGX_QUIC_ERR_INTERNAL_ERROR;
ngx_quic_set_error(c, NGX_QUIC_ERR_INTERNAL_ERROR, "key error");
}
return 1;
@ -496,8 +495,9 @@ ngx_quic_add_handshake_data(ngx_ssl_conn_t *ssl_conn,
if (alpn_len == 0) {
if (qc->error == 0) {
qc->error = NGX_QUIC_ERR_CRYPTO(SSL_AD_NO_APPLICATION_PROTOCOL);
qc->error_reason = "missing ALPN extension";
ngx_quic_set_error(c,
NGX_QUIC_ERR_CRYPTO(SSL_AD_NO_APPLICATION_PROTOCOL),
"missing ALPN extension");
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"quic missing ALPN extension");
@ -517,8 +517,9 @@ ngx_quic_add_handshake_data(ngx_ssl_conn_t *ssl_conn,
/* RFC 9001, 8.2. QUIC Transport Parameters Extension */
if (qc->error == 0) {
qc->error = NGX_QUIC_ERR_CRYPTO(SSL_AD_MISSING_EXTENSION);
qc->error_reason = "missing transport parameters";
ngx_quic_set_error(c,
NGX_QUIC_ERR_CRYPTO(SSL_AD_MISSING_EXTENSION),
"missing transport parameters");
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"missing transport parameters");
@ -536,9 +537,8 @@ ngx_quic_add_handshake_data(ngx_ssl_conn_t *ssl_conn,
if (ngx_quic_parse_transport_params(p, end, &ctp, c->log)
!= NGX_OK)
{
qc->error = NGX_QUIC_ERR_TRANSPORT_PARAMETER_ERROR;
qc->error_reason = "failed to process transport parameters";
ngx_quic_set_error(c, NGX_QUIC_ERR_TRANSPORT_PARAMETER_ERROR,
"failed to process transport parameters");
return 1;
}
@ -553,13 +553,13 @@ ngx_quic_add_handshake_data(ngx_ssl_conn_t *ssl_conn,
out = ngx_quic_copy_buffer(c, (u_char *) data, len);
if (out == NGX_CHAIN_ERROR) {
qc->error = NGX_QUIC_ERR_INTERNAL_ERROR;
ngx_quic_set_error(c, NGX_QUIC_ERR_INTERNAL_ERROR, "buffer error");
return 1;
}
frame = ngx_quic_alloc_frame(c);
if (frame == NULL) {
qc->error = NGX_QUIC_ERR_INTERNAL_ERROR;
ngx_quic_set_error(c, NGX_QUIC_ERR_INTERNAL_ERROR, "memory error");
return 1;
}
@ -612,8 +612,7 @@ ngx_quic_send_alert(ngx_ssl_conn_t *ssl_conn,
return 1;
}
qc->error = NGX_QUIC_ERR_CRYPTO(alert);
qc->error_reason = "handshake failed";
ngx_quic_set_error(c, NGX_QUIC_ERR_CRYPTO(alert), "handshake error");
return 1;
}
@ -643,7 +642,8 @@ ngx_quic_handle_crypto_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
last = f->offset + f->length;
if (last > ctx->crypto.offset + NGX_QUIC_MAX_BUFFERED) {
qc->error = NGX_QUIC_ERR_CRYPTO_BUFFER_EXCEEDED;
ngx_quic_set_error(c, NGX_QUIC_ERR_CRYPTO_BUFFER_EXCEEDED,
"crypto buffer exceeded");
return NGX_ERROR;
}

View File

@ -408,7 +408,8 @@ ngx_quic_get_stream(ngx_connection_t *c, uint64_t id)
return NGX_QUIC_STREAM_GONE;
}
qc->error = NGX_QUIC_ERR_STREAM_STATE_ERROR;
ngx_quic_set_error(c, NGX_QUIC_ERR_STREAM_STATE_ERROR,
"peer attempted to open a local stream");
return NULL;
}
@ -417,7 +418,8 @@ ngx_quic_get_stream(ngx_connection_t *c, uint64_t id)
}
if ((id >> 2) >= qc->streams.client_max_streams_uni) {
qc->error = NGX_QUIC_ERR_STREAM_LIMIT_ERROR;
ngx_quic_set_error(c, NGX_QUIC_ERR_STREAM_LIMIT_ERROR,
"peer exceeded stream limit");
return NULL;
}
@ -432,7 +434,8 @@ ngx_quic_get_stream(ngx_connection_t *c, uint64_t id)
return NGX_QUIC_STREAM_GONE;
}
qc->error = NGX_QUIC_ERR_STREAM_STATE_ERROR;
ngx_quic_set_error(c, NGX_QUIC_ERR_STREAM_STATE_ERROR,
"peer attempted to open a local stream");
return NULL;
}
@ -441,7 +444,8 @@ ngx_quic_get_stream(ngx_connection_t *c, uint64_t id)
}
if ((id >> 2) >= qc->streams.client_max_streams_bidi) {
qc->error = NGX_QUIC_ERR_STREAM_LIMIT_ERROR;
ngx_quic_set_error(c, NGX_QUIC_ERR_STREAM_LIMIT_ERROR,
"peer exceeded stream limit");
return NULL;
}
@ -1096,12 +1100,14 @@ ngx_quic_stream_cleanup_handler(void *data)
{
ngx_connection_t *c = data;
ngx_connection_t *pc;
ngx_quic_stream_t *qs;
ngx_quic_connection_t *qc;
qs = c->quic;
pc = qs->parent;
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, qs->parent->log, 0,
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, pc->log, 0,
"quic stream id:0x%xL cleanup", qs->id);
if (ngx_quic_shutdown_stream(c, NGX_RDWR_SHUTDOWN) != NGX_OK) {
@ -1119,8 +1125,9 @@ ngx_quic_stream_cleanup_handler(void *data)
failed:
qc = ngx_quic_get_connection(qs->parent);
qc->error = NGX_QUIC_ERR_INTERNAL_ERROR;
ngx_quic_set_error(pc, NGX_QUIC_ERR_INTERNAL_ERROR, "stream cleanup error");
qc = ngx_quic_get_connection(pc);
ngx_post_event(&qc->close, &ngx_posted_events);
}
@ -1234,16 +1241,15 @@ ngx_quic_handle_stream_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
{
uint64_t last;
ngx_quic_stream_t *qs;
ngx_quic_connection_t *qc;
ngx_quic_stream_frame_t *f;
qc = ngx_quic_get_connection(c);
f = &frame->u.stream;
if ((f->stream_id & NGX_QUIC_STREAM_UNIDIRECTIONAL)
&& (f->stream_id & NGX_QUIC_STREAM_SERVER_INITIATED))
{
qc->error = NGX_QUIC_ERR_STREAM_STATE_ERROR;
ngx_quic_set_error(c, NGX_QUIC_ERR_STREAM_STATE_ERROR,
"peer sent data on local uni stream");
return NGX_ERROR;
}
@ -1271,7 +1277,8 @@ ngx_quic_handle_stream_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
}
if (qs->recv_final_size != (uint64_t) -1 && last > qs->recv_final_size) {
qc->error = NGX_QUIC_ERR_FINAL_SIZE_ERROR;
ngx_quic_set_error(c, NGX_QUIC_ERR_FINAL_SIZE_ERROR,
"peer sent data beyond stream end");
return NGX_ERROR;
}
@ -1282,12 +1289,14 @@ ngx_quic_handle_stream_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
if (f->fin) {
if (qs->recv_final_size != (uint64_t) -1 && qs->recv_final_size != last)
{
qc->error = NGX_QUIC_ERR_FINAL_SIZE_ERROR;
ngx_quic_set_error(c, NGX_QUIC_ERR_FINAL_SIZE_ERROR,
"peer sent data beyond stream end");
return NGX_ERROR;
}
if (qs->recv_last > last) {
qc->error = NGX_QUIC_ERR_FINAL_SIZE_ERROR;
ngx_quic_set_error(c, NGX_QUIC_ERR_FINAL_SIZE_ERROR,
"peer sent data beyond stream end");
return NGX_ERROR;
}
@ -1381,14 +1390,12 @@ ngx_quic_handle_stream_data_blocked_frame(ngx_connection_t *c,
ngx_quic_header_t *pkt, ngx_quic_stream_data_blocked_frame_t *f)
{
ngx_quic_stream_t *qs;
ngx_quic_connection_t *qc;
qc = ngx_quic_get_connection(c);
if ((f->id & NGX_QUIC_STREAM_UNIDIRECTIONAL)
&& (f->id & NGX_QUIC_STREAM_SERVER_INITIATED))
{
qc->error = NGX_QUIC_ERR_STREAM_STATE_ERROR;
ngx_quic_set_error(c, NGX_QUIC_ERR_STREAM_STATE_ERROR,
"peer sent data blocked for local uni stream");
return NGX_ERROR;
}
@ -1411,14 +1418,12 @@ ngx_quic_handle_max_stream_data_frame(ngx_connection_t *c,
ngx_quic_header_t *pkt, ngx_quic_max_stream_data_frame_t *f)
{
ngx_quic_stream_t *qs;
ngx_quic_connection_t *qc;
qc = ngx_quic_get_connection(c);
if ((f->id & NGX_QUIC_STREAM_UNIDIRECTIONAL)
&& (f->id & NGX_QUIC_STREAM_SERVER_INITIATED) == 0)
{
qc->error = NGX_QUIC_ERR_STREAM_STATE_ERROR;
ngx_quic_set_error(c, NGX_QUIC_ERR_STREAM_STATE_ERROR,
"peer sent flow control for local uni stream");
return NGX_ERROR;
}
@ -1454,14 +1459,12 @@ ngx_quic_handle_reset_stream_frame(ngx_connection_t *c,
{
ngx_event_t *rev;
ngx_quic_stream_t *qs;
ngx_quic_connection_t *qc;
qc = ngx_quic_get_connection(c);
if ((f->id & NGX_QUIC_STREAM_UNIDIRECTIONAL)
&& (f->id & NGX_QUIC_STREAM_SERVER_INITIATED))
{
qc->error = NGX_QUIC_ERR_STREAM_STATE_ERROR;
ngx_quic_set_error(c, NGX_QUIC_ERR_STREAM_STATE_ERROR,
"peer sent reset for local uni stream");
return NGX_ERROR;
}
@ -1490,12 +1493,14 @@ ngx_quic_handle_reset_stream_frame(ngx_connection_t *c,
if (qs->recv_final_size != (uint64_t) -1
&& qs->recv_final_size != f->final_size)
{
qc->error = NGX_QUIC_ERR_FINAL_SIZE_ERROR;
ngx_quic_set_error(c, NGX_QUIC_ERR_FINAL_SIZE_ERROR,
"peer sent data beyond stream end");
return NGX_ERROR;
}
if (qs->recv_last > f->final_size) {
qc->error = NGX_QUIC_ERR_FINAL_SIZE_ERROR;
ngx_quic_set_error(c, NGX_QUIC_ERR_FINAL_SIZE_ERROR,
"peer sent data beyond stream end");
return NGX_ERROR;
}
@ -1523,14 +1528,12 @@ ngx_quic_handle_stop_sending_frame(ngx_connection_t *c,
ngx_quic_header_t *pkt, ngx_quic_stop_sending_frame_t *f)
{
ngx_quic_stream_t *qs;
ngx_quic_connection_t *qc;
qc = ngx_quic_get_connection(c);
if ((f->id & NGX_QUIC_STREAM_UNIDIRECTIONAL)
&& (f->id & NGX_QUIC_STREAM_SERVER_INITIATED) == 0)
{
qc->error = NGX_QUIC_ERR_STREAM_STATE_ERROR;
ngx_quic_set_error(c, NGX_QUIC_ERR_STREAM_STATE_ERROR,
"peer sent stop sending for local uni stream");
return NGX_ERROR;
}
@ -1683,14 +1686,16 @@ ngx_quic_control_flow(ngx_quic_stream_t *qs, uint64_t last)
if (qs->recv_state == NGX_QUIC_STREAM_RECV_RECV
&& qs->recv_last > qs->recv_max_data)
{
qc->error = NGX_QUIC_ERR_FLOW_CONTROL_ERROR;
ngx_quic_set_error(pc, NGX_QUIC_ERR_FLOW_CONTROL_ERROR,
"peer sent data beyond stream flow control");
return NGX_ERROR;
}
qc->streams.recv_last += len;
if (qc->streams.recv_last > qc->streams.recv_max_data) {
qc->error = NGX_QUIC_ERR_FLOW_CONTROL_ERROR;
ngx_quic_set_error(pc, NGX_QUIC_ERR_FLOW_CONTROL_ERROR,
"peer sent data beyond flow control");
return NGX_ERROR;
}