mirror of
https://github.com/nginx/nginx.git
synced 2025-01-07 17:27:48 +08:00
QUIC: Introduced ngx_quic_finalize_connection().
The function finalizes QUIC connection with an application protocol error code and sends a CONNECTION_CLOSE frame with type=0x1d. Also, renamed NGX_QUIC_FT_CONNECTION_CLOSE2 to NGX_QUIC_FT_CONNECTION_CLOSE_APP.
This commit is contained in:
parent
86e287a2de
commit
90f5c334f1
@ -110,9 +110,11 @@ struct ngx_quic_connection_s {
|
|||||||
uint64_t max_streams;
|
uint64_t max_streams;
|
||||||
|
|
||||||
ngx_uint_t error;
|
ngx_uint_t error;
|
||||||
|
enum ssl_encryption_level_t error_level;
|
||||||
ngx_uint_t error_ftype;
|
ngx_uint_t error_ftype;
|
||||||
const char *error_reason;
|
const char *error_reason;
|
||||||
|
|
||||||
|
unsigned error_app:1;
|
||||||
unsigned send_timer_set:1;
|
unsigned send_timer_set:1;
|
||||||
unsigned closing:1;
|
unsigned closing:1;
|
||||||
unsigned draining:1;
|
unsigned draining:1;
|
||||||
@ -181,9 +183,7 @@ static ngx_int_t ngx_quic_app_input(ngx_connection_t *c,
|
|||||||
static ngx_int_t ngx_quic_payload_handler(ngx_connection_t *c,
|
static ngx_int_t ngx_quic_payload_handler(ngx_connection_t *c,
|
||||||
ngx_quic_header_t *pkt);
|
ngx_quic_header_t *pkt);
|
||||||
static ngx_int_t ngx_quic_send_ack(ngx_connection_t *c, ngx_quic_header_t *pkt);
|
static ngx_int_t ngx_quic_send_ack(ngx_connection_t *c, ngx_quic_header_t *pkt);
|
||||||
static ngx_int_t ngx_quic_send_cc(ngx_connection_t *c,
|
static ngx_int_t ngx_quic_send_cc(ngx_connection_t *c);
|
||||||
enum ssl_encryption_level_t level, ngx_uint_t err, ngx_uint_t frame_type,
|
|
||||||
const char *reason);
|
|
||||||
static ngx_int_t ngx_quic_send_new_token(ngx_connection_t *c);
|
static ngx_int_t ngx_quic_send_new_token(ngx_connection_t *c);
|
||||||
|
|
||||||
static ngx_int_t ngx_quic_handle_ack_frame(ngx_connection_t *c,
|
static ngx_int_t ngx_quic_handle_ack_frame(ngx_connection_t *c,
|
||||||
@ -541,6 +541,7 @@ ngx_quic_send_alert(ngx_ssl_conn_t *ssl_conn, enum ssl_encryption_level_t level,
|
|||||||
uint8_t alert)
|
uint8_t alert)
|
||||||
{
|
{
|
||||||
ngx_connection_t *c;
|
ngx_connection_t *c;
|
||||||
|
ngx_quic_connection_t *qc;
|
||||||
|
|
||||||
c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
|
c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
|
||||||
|
|
||||||
@ -548,13 +549,18 @@ ngx_quic_send_alert(ngx_ssl_conn_t *ssl_conn, enum ssl_encryption_level_t level,
|
|||||||
"quic ngx_quic_send_alert(), lvl=%d, alert=%d",
|
"quic ngx_quic_send_alert(), lvl=%d, alert=%d",
|
||||||
(int) level, (int) alert);
|
(int) level, (int) alert);
|
||||||
|
|
||||||
if (c->quic == NULL) {
|
qc = c->quic;
|
||||||
|
if (qc == NULL) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ngx_quic_send_cc(c, level, NGX_QUIC_ERR_CRYPTO(alert), 0, "TLS alert")
|
qc->error_level = level;
|
||||||
!= NGX_OK)
|
qc->error = NGX_QUIC_ERR_CRYPTO(alert);
|
||||||
{
|
qc->error_reason = "TLS alert";
|
||||||
|
qc->error_app = 0;
|
||||||
|
qc->error_ftype = 0;
|
||||||
|
|
||||||
|
if (ngx_quic_send_cc(c) != NGX_OK) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1262,10 +1268,9 @@ ngx_quic_close_connection(ngx_connection_t *c, ngx_int_t rc)
|
|||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_quic_close_quic(ngx_connection_t *c, ngx_int_t rc)
|
ngx_quic_close_quic(ngx_connection_t *c, ngx_int_t rc)
|
||||||
{
|
{
|
||||||
ngx_uint_t i, err;
|
ngx_uint_t i;
|
||||||
ngx_quic_send_ctx_t *ctx;
|
ngx_quic_send_ctx_t *ctx;
|
||||||
ngx_quic_connection_t *qc;
|
ngx_quic_connection_t *qc;
|
||||||
enum ssl_encryption_level_t level;
|
|
||||||
|
|
||||||
qc = c->quic;
|
qc = c->quic;
|
||||||
|
|
||||||
@ -1311,27 +1316,28 @@ ngx_quic_close_quic(ngx_connection_t *c, ngx_int_t rc)
|
|||||||
|
|
||||||
ngx_add_timer(&qc->close, 3 * NGX_QUIC_HARDCODED_PTO);
|
ngx_add_timer(&qc->close, 3 * NGX_QUIC_HARDCODED_PTO);
|
||||||
|
|
||||||
err = NGX_QUIC_ERR_NO_ERROR;
|
qc->error = NGX_QUIC_ERR_NO_ERROR;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
err = qc->error ? qc->error : NGX_QUIC_ERR_INTERNAL_ERROR;
|
if (qc->error == 0 && !qc->error_app) {
|
||||||
|
qc->error = NGX_QUIC_ERR_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||||
"quic immediate close due to error: %ui %s",
|
"quic immediate close due to %serror: %ui %s",
|
||||||
qc->error,
|
qc->error_app ? "app " : "", qc->error,
|
||||||
qc->error_reason ? qc->error_reason : "");
|
qc->error_reason ? qc->error_reason : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
level = c->ssl ? SSL_quic_read_level(c->ssl->connection)
|
qc->error_level = c->ssl ? SSL_quic_read_level(c->ssl->connection)
|
||||||
: ssl_encryption_initial;
|
: ssl_encryption_initial;
|
||||||
|
|
||||||
(void) ngx_quic_send_cc(c, level, err, qc->error_ftype,
|
(void) ngx_quic_send_cc(c);
|
||||||
qc->error_reason);
|
|
||||||
|
|
||||||
if (level == ssl_encryption_handshake) {
|
if (qc->error_level == ssl_encryption_handshake) {
|
||||||
/* for clients that might not have handshake keys */
|
/* for clients that might not have handshake keys */
|
||||||
(void) ngx_quic_send_cc(c, ssl_encryption_initial, err,
|
qc->error_level = ssl_encryption_initial;
|
||||||
qc->error_ftype, qc->error_reason);
|
(void) ngx_quic_send_cc(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1382,6 +1388,22 @@ ngx_quic_close_quic(ngx_connection_t *c, ngx_int_t rc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ngx_quic_finalize_connection(ngx_connection_t *c, ngx_uint_t err,
|
||||||
|
const char *reason)
|
||||||
|
{
|
||||||
|
ngx_quic_connection_t *qc;
|
||||||
|
|
||||||
|
qc = c->quic;
|
||||||
|
qc->error = err;
|
||||||
|
qc->error_reason = reason;
|
||||||
|
qc->error_app = 1;
|
||||||
|
qc->error_ftype = 0;
|
||||||
|
|
||||||
|
ngx_quic_close_connection(c, NGX_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ngx_quic_close_timer_handler(ngx_event_t *ev)
|
ngx_quic_close_timer_handler(ngx_event_t *ev)
|
||||||
{
|
{
|
||||||
@ -1887,8 +1909,14 @@ ngx_quic_payload_handler(ngx_connection_t *c, ngx_quic_header_t *pkt)
|
|||||||
* a packet containing a CONNECTION_CLOSE frame and to identify
|
* a packet containing a CONNECTION_CLOSE frame and to identify
|
||||||
* packets as belonging to the connection.
|
* packets as belonging to the connection.
|
||||||
*/
|
*/
|
||||||
return ngx_quic_send_cc(c, pkt->level, NGX_QUIC_ERR_NO_ERROR, 0,
|
|
||||||
"connection is closing, packet discarded");
|
qc->error_level = pkt->level;
|
||||||
|
qc->error = NGX_QUIC_ERR_NO_ERROR;
|
||||||
|
qc->error_reason = "connection is closing, packet discarded";
|
||||||
|
qc->error_ftype = 0;
|
||||||
|
qc->error_app = 0;
|
||||||
|
|
||||||
|
return ngx_quic_send_cc(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
p = pkt->payload.data;
|
p = pkt->payload.data;
|
||||||
@ -1926,7 +1954,7 @@ ngx_quic_payload_handler(ngx_connection_t *c, ngx_quic_header_t *pkt)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
case NGX_QUIC_FT_CONNECTION_CLOSE:
|
case NGX_QUIC_FT_CONNECTION_CLOSE:
|
||||||
case NGX_QUIC_FT_CONNECTION_CLOSE2:
|
case NGX_QUIC_FT_CONNECTION_CLOSE_APP:
|
||||||
do_close = 1;
|
do_close = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -2098,8 +2126,7 @@ ngx_quic_send_ack(ngx_connection_t *c, ngx_quic_header_t *pkt)
|
|||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_quic_send_cc(ngx_connection_t *c, enum ssl_encryption_level_t level,
|
ngx_quic_send_cc(ngx_connection_t *c)
|
||||||
ngx_uint_t err, ngx_uint_t frame_type, const char *reason)
|
|
||||||
{
|
{
|
||||||
ngx_quic_frame_t *frame;
|
ngx_quic_frame_t *frame;
|
||||||
ngx_quic_connection_t *qc;
|
ngx_quic_connection_t *qc;
|
||||||
@ -2122,19 +2149,21 @@ ngx_quic_send_cc(ngx_connection_t *c, enum ssl_encryption_level_t level,
|
|||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
frame->level = level;
|
frame->level = qc->error_level;
|
||||||
frame->type = NGX_QUIC_FT_CONNECTION_CLOSE;
|
frame->type = NGX_QUIC_FT_CONNECTION_CLOSE;
|
||||||
frame->u.close.error_code = err;
|
frame->u.close.error_code = qc->error;
|
||||||
frame->u.close.frame_type = frame_type;
|
frame->u.close.frame_type = qc->error_ftype;
|
||||||
|
frame->u.close.app = qc->error_app;
|
||||||
|
|
||||||
if (reason) {
|
if (qc->error_reason) {
|
||||||
frame->u.close.reason.len = ngx_strlen(reason);
|
frame->u.close.reason.len = ngx_strlen(qc->error_reason);
|
||||||
frame->u.close.reason.data = (u_char *) reason;
|
frame->u.close.reason.data = (u_char *) qc->error_reason;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngx_snprintf(frame->info, sizeof(frame->info) - 1,
|
ngx_snprintf(frame->info, sizeof(frame->info) - 1,
|
||||||
"cc from send_cc err=%ui level=%d ft=%ui reason \"%s\"",
|
"CONNECTION_CLOSE%s err:%ui level:%d ft:%ui reason:\"%s\"",
|
||||||
err, level, frame_type, reason ? reason : "-");
|
qc->error_app ? "_APP" : "", qc->error, qc->error_level,
|
||||||
|
qc->error_ftype, qc->error_reason ? qc->error_reason : "-");
|
||||||
|
|
||||||
ngx_quic_queue_frame(c->quic, frame);
|
ngx_quic_queue_frame(c->quic, frame);
|
||||||
|
|
||||||
|
@ -103,6 +103,8 @@ struct ngx_quic_stream_s {
|
|||||||
void ngx_quic_run(ngx_connection_t *c, ngx_ssl_t *ssl, ngx_quic_tp_t *tp,
|
void ngx_quic_run(ngx_connection_t *c, ngx_ssl_t *ssl, ngx_quic_tp_t *tp,
|
||||||
ngx_connection_handler_pt handler);
|
ngx_connection_handler_pt handler);
|
||||||
ngx_connection_t *ngx_quic_create_uni_stream(ngx_connection_t *c);
|
ngx_connection_t *ngx_quic_create_uni_stream(ngx_connection_t *c);
|
||||||
|
void ngx_quic_finalize_connection(ngx_connection_t *c, ngx_uint_t err,
|
||||||
|
const char *reason);
|
||||||
|
|
||||||
|
|
||||||
/********************************* DEBUG *************************************/
|
/********************************* DEBUG *************************************/
|
||||||
|
@ -726,10 +726,8 @@ ngx_quic_parse_frame(ngx_quic_header_t *pkt, u_char *start, u_char *end,
|
|||||||
f->u.ncid.seqnum, f->u.ncid.retire, f->u.ncid.len);
|
f->u.ncid.seqnum, f->u.ncid.retire, f->u.ncid.len);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NGX_QUIC_FT_CONNECTION_CLOSE2:
|
|
||||||
/* fall through */
|
|
||||||
|
|
||||||
case NGX_QUIC_FT_CONNECTION_CLOSE:
|
case NGX_QUIC_FT_CONNECTION_CLOSE:
|
||||||
|
case NGX_QUIC_FT_CONNECTION_CLOSE_APP:
|
||||||
|
|
||||||
p = ngx_quic_parse_int(p, end, &f->u.close.error_code);
|
p = ngx_quic_parse_int(p, end, &f->u.close.error_code);
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
@ -767,7 +765,7 @@ ngx_quic_parse_frame(ngx_quic_header_t *pkt, u_char *start, u_char *end,
|
|||||||
} else {
|
} else {
|
||||||
|
|
||||||
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, pkt->log, 0,
|
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, pkt->log, 0,
|
||||||
"quic frame in: CONNECTION_CLOSE2:"
|
"quic frame in: CONNECTION_CLOSE_APP:"
|
||||||
" code:0x%xi reason:'%V'",
|
" code:0x%xi reason:'%V'",
|
||||||
f->u.close.error_code, &f->u.close.reason);
|
f->u.close.error_code, &f->u.close.reason);
|
||||||
}
|
}
|
||||||
@ -1174,6 +1172,7 @@ ngx_quic_create_frame(u_char *p, ngx_quic_frame_t *f)
|
|||||||
return ngx_quic_create_stream(p, &f->u.stream);
|
return ngx_quic_create_stream(p, &f->u.stream);
|
||||||
|
|
||||||
case NGX_QUIC_FT_CONNECTION_CLOSE:
|
case NGX_QUIC_FT_CONNECTION_CLOSE:
|
||||||
|
case NGX_QUIC_FT_CONNECTION_CLOSE_APP:
|
||||||
f->need_ack = 0;
|
f->need_ack = 0;
|
||||||
return ngx_quic_create_close(p, &f->u.close);
|
return ngx_quic_create_close(p, &f->u.close);
|
||||||
|
|
||||||
@ -1744,11 +1743,19 @@ ngx_quic_create_close(u_char *p, ngx_quic_close_frame_t *cl)
|
|||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
u_char *start;
|
u_char *start;
|
||||||
|
ngx_uint_t type;
|
||||||
|
|
||||||
|
type = cl->app ? NGX_QUIC_FT_CONNECTION_CLOSE_APP
|
||||||
|
: NGX_QUIC_FT_CONNECTION_CLOSE;
|
||||||
|
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
len = ngx_quic_varint_len(NGX_QUIC_FT_CONNECTION_CLOSE);
|
len = ngx_quic_varint_len(type);
|
||||||
len += ngx_quic_varint_len(cl->error_code);
|
len += ngx_quic_varint_len(cl->error_code);
|
||||||
|
|
||||||
|
if (!cl->app) {
|
||||||
len += ngx_quic_varint_len(cl->frame_type);
|
len += ngx_quic_varint_len(cl->frame_type);
|
||||||
|
}
|
||||||
|
|
||||||
len += ngx_quic_varint_len(cl->reason.len);
|
len += ngx_quic_varint_len(cl->reason.len);
|
||||||
len += cl->reason.len;
|
len += cl->reason.len;
|
||||||
|
|
||||||
@ -1757,9 +1764,13 @@ ngx_quic_create_close(u_char *p, ngx_quic_close_frame_t *cl)
|
|||||||
|
|
||||||
start = p;
|
start = p;
|
||||||
|
|
||||||
ngx_quic_build_int(&p, NGX_QUIC_FT_CONNECTION_CLOSE);
|
ngx_quic_build_int(&p, type);
|
||||||
ngx_quic_build_int(&p, cl->error_code);
|
ngx_quic_build_int(&p, cl->error_code);
|
||||||
|
|
||||||
|
if (!cl->app) {
|
||||||
ngx_quic_build_int(&p, cl->frame_type);
|
ngx_quic_build_int(&p, cl->frame_type);
|
||||||
|
}
|
||||||
|
|
||||||
ngx_quic_build_int(&p, cl->reason.len);
|
ngx_quic_build_int(&p, cl->reason.len);
|
||||||
p = ngx_cpymem(p, cl->reason.data, cl->reason.len);
|
p = ngx_cpymem(p, cl->reason.data, cl->reason.len);
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@
|
|||||||
#define NGX_QUIC_FT_PATH_CHALLENGE 0x1A
|
#define NGX_QUIC_FT_PATH_CHALLENGE 0x1A
|
||||||
#define NGX_QUIC_FT_PATH_RESPONSE 0x1B
|
#define NGX_QUIC_FT_PATH_RESPONSE 0x1B
|
||||||
#define NGX_QUIC_FT_CONNECTION_CLOSE 0x1C
|
#define NGX_QUIC_FT_CONNECTION_CLOSE 0x1C
|
||||||
#define NGX_QUIC_FT_CONNECTION_CLOSE2 0x1D
|
#define NGX_QUIC_FT_CONNECTION_CLOSE_APP 0x1D
|
||||||
#define NGX_QUIC_FT_HANDSHAKE_DONE 0x1E
|
#define NGX_QUIC_FT_HANDSHAKE_DONE 0x1E
|
||||||
|
|
||||||
/* 22.4. QUIC Transport Error Codes Registry */
|
/* 22.4. QUIC Transport Error Codes Registry */
|
||||||
@ -185,6 +185,7 @@ typedef struct {
|
|||||||
uint64_t error_code;
|
uint64_t error_code;
|
||||||
uint64_t frame_type;
|
uint64_t frame_type;
|
||||||
ngx_str_t reason;
|
ngx_str_t reason;
|
||||||
|
ngx_uint_t app; /* unsigned app:1; */
|
||||||
} ngx_quic_close_frame_t;
|
} ngx_quic_close_frame_t;
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user