From 77c082903ea1cbcca65c92a758f932aea539359a Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Fri, 23 May 2025 13:53:33 +0400 Subject: [PATCH] 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. --- src/event/quic/ngx_event_quic.c | 75 +++++++++++++------- src/event/quic/ngx_event_quic_ack.c | 16 +++-- src/event/quic/ngx_event_quic_connection.h | 2 + src/event/quic/ngx_event_quic_connid.c | 18 ++--- src/event/quic/ngx_event_quic_migration.c | 4 +- src/event/quic/ngx_event_quic_ssl.c | 58 ++++++++-------- src/event/quic/ngx_event_quic_streams.c | 81 ++++++++++++---------- 7 files changed, 146 insertions(+), 108 deletions(-) diff --git a/src/event/quic/ngx_event_quic.c b/src/event/quic/ngx_event_quic.c index 7931256c7..c95270ff6 100644 --- a/src/event/quic/ngx_event_quic.c +++ b/src/event/quic/ngx_event_quic.c @@ -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; } diff --git a/src/event/quic/ngx_event_quic_ack.c b/src/event/quic/ngx_event_quic_ack.c index 73908136f..7f822691b 100644 --- a/src/event/quic/ngx_event_quic_ack.c +++ b/src/event/quic/ngx_event_quic_ack.c @@ -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; } diff --git a/src/event/quic/ngx_event_quic_connection.h b/src/event/quic/ngx_event_quic_connection.h index 33922cf80..5887bdcc9 100644 --- a/src/event/quic/ngx_event_quic_connection.h +++ b/src/event/quic/ngx_event_quic_connection.h @@ -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); diff --git a/src/event/quic/ngx_event_quic_connid.c b/src/event/quic/ngx_event_quic_connid.c index 4e7b8dc22..40ab1aef1 100644 --- a/src/event/quic/ngx_event_quic_connid.c +++ b/src/event/quic/ngx_event_quic_connid.c @@ -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; } diff --git a/src/event/quic/ngx_event_quic_migration.c b/src/event/quic/ngx_event_quic_migration.c index 42354ca66..382ae5819 100644 --- a/src/event/quic/ngx_event_quic_migration.c +++ b/src/event/quic/ngx_event_quic_migration.c @@ -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; } diff --git a/src/event/quic/ngx_event_quic_ssl.c b/src/event/quic/ngx_event_quic_ssl.c index e961c80cd..a859cc24f 100644 --- a/src/event/quic/ngx_event_quic_ssl.c +++ b/src/event/quic/ngx_event_quic_ssl.c @@ -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; } diff --git a/src/event/quic/ngx_event_quic_streams.c b/src/event/quic/ngx_event_quic_streams.c index 18fffeabe..753e2db69 100644 --- a/src/event/quic/ngx_event_quic_streams.c +++ b/src/event/quic/ngx_event_quic_streams.c @@ -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; } @@ -1380,15 +1389,13 @@ ngx_int_t 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); + ngx_quic_stream_t *qs; 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; } @@ -1410,15 +1417,13 @@ ngx_int_t 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); + ngx_quic_stream_t *qs; 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; } @@ -1452,16 +1457,14 @@ ngx_int_t ngx_quic_handle_reset_stream_frame(ngx_connection_t *c, ngx_quic_header_t *pkt, ngx_quic_reset_stream_frame_t *f) { - ngx_event_t *rev; - ngx_quic_stream_t *qs; - ngx_quic_connection_t *qc; - - qc = ngx_quic_get_connection(c); + ngx_event_t *rev; + ngx_quic_stream_t *qs; 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; } @@ -1522,15 +1527,13 @@ ngx_int_t 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); + ngx_quic_stream_t *qs; 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; }