mirror of
https://github.com/nginx/nginx.git
synced 2024-12-05 06:19:01 +08:00
QUIC: refactored packet processing.
- split ngx_quic_process_packet() in two functions with the second one called ngx_quic_process_payload() in charge of decrypring and handling the payload - renamed ngx_quic_payload_handler() to ngx_quic_handle_frames() - moved error cleanup from ngx_quic_input() to ngx_quic_process_payload() - moved handling closed connection from ngx_quic_handle_frames() to ngx_quic_process_payload() - minor fixes
This commit is contained in:
parent
89dda20510
commit
fef3360466
@ -255,13 +255,15 @@ static ngx_int_t ngx_quic_input(ngx_connection_t *c, ngx_buf_t *b,
|
||||
ngx_quic_conf_t *conf);
|
||||
static ngx_int_t ngx_quic_process_packet(ngx_connection_t *c,
|
||||
ngx_quic_conf_t *conf, ngx_quic_header_t *pkt);
|
||||
static ngx_int_t ngx_quic_process_payload(ngx_connection_t *c,
|
||||
ngx_quic_header_t *pkt);
|
||||
static ngx_int_t ngx_quic_send_early_cc(ngx_connection_t *c,
|
||||
ngx_quic_header_t *inpkt, ngx_uint_t err, const char *reason);
|
||||
static void ngx_quic_discard_ctx(ngx_connection_t *c,
|
||||
enum ssl_encryption_level_t level);
|
||||
static ngx_int_t ngx_quic_check_peer(ngx_quic_connection_t *qc,
|
||||
ngx_quic_header_t *pkt);
|
||||
static ngx_int_t ngx_quic_payload_handler(ngx_connection_t *c,
|
||||
static ngx_int_t ngx_quic_handle_frames(ngx_connection_t *c,
|
||||
ngx_quic_header_t *pkt);
|
||||
static ngx_int_t ngx_quic_ack_packet(ngx_connection_t *c,
|
||||
ngx_quic_header_t *pkt);
|
||||
@ -2120,11 +2122,10 @@ ngx_quic_close_streams(ngx_connection_t *c, ngx_quic_connection_t *qc)
|
||||
static ngx_int_t
|
||||
ngx_quic_input(ngx_connection_t *c, ngx_buf_t *b, ngx_quic_conf_t *conf)
|
||||
{
|
||||
u_char *p;
|
||||
ngx_int_t rc;
|
||||
ngx_uint_t good;
|
||||
ngx_quic_header_t pkt;
|
||||
ngx_quic_connection_t *qc;
|
||||
u_char *p;
|
||||
ngx_int_t rc;
|
||||
ngx_uint_t good;
|
||||
ngx_quic_header_t pkt;
|
||||
|
||||
good = 0;
|
||||
|
||||
@ -2140,12 +2141,6 @@ ngx_quic_input(ngx_connection_t *c, ngx_buf_t *b, ngx_quic_conf_t *conf)
|
||||
pkt.flags = p[0];
|
||||
pkt.raw->pos++;
|
||||
|
||||
qc = ngx_quic_get_connection(c);
|
||||
if (qc) {
|
||||
qc->error = 0;
|
||||
qc->error_reason = 0;
|
||||
}
|
||||
|
||||
rc = ngx_quic_process_packet(c, conf, &pkt);
|
||||
|
||||
#if (NGX_DEBUG)
|
||||
@ -2212,11 +2207,8 @@ ngx_quic_process_packet(ngx_connection_t *c, ngx_quic_conf_t *conf,
|
||||
ngx_quic_header_t *pkt)
|
||||
{
|
||||
ngx_int_t rc;
|
||||
ngx_quic_send_ctx_t *ctx;
|
||||
ngx_quic_connection_t *qc;
|
||||
|
||||
static u_char buf[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];
|
||||
|
||||
c->log->action = "parsing quic packet";
|
||||
|
||||
rc = ngx_quic_parse_packet(pkt);
|
||||
@ -2229,8 +2221,6 @@ ngx_quic_process_packet(ngx_connection_t *c, ngx_quic_conf_t *conf,
|
||||
|
||||
c->log->action = "processing quic packet";
|
||||
|
||||
qc = ngx_quic_get_connection(c);
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"quic packet rx dcid len:%uz %xV",
|
||||
pkt->dcid.len, &pkt->dcid);
|
||||
@ -2249,6 +2239,8 @@ ngx_quic_process_packet(ngx_connection_t *c, ngx_quic_conf_t *conf,
|
||||
}
|
||||
#endif
|
||||
|
||||
qc = ngx_quic_get_connection(c);
|
||||
|
||||
if (qc) {
|
||||
|
||||
if (rc == NGX_ABORT) {
|
||||
@ -2284,84 +2276,103 @@ ngx_quic_process_packet(ngx_connection_t *c, ngx_quic_conf_t *conf,
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (rc == NGX_ABORT) {
|
||||
return ngx_quic_negotiate_version(c, pkt);
|
||||
}
|
||||
|
||||
if (pkt->level == ssl_encryption_initial) {
|
||||
c->log->action = "processing initial packet";
|
||||
|
||||
if (pkt->dcid.len < NGX_QUIC_CID_LEN_MIN) {
|
||||
/* 7.2. Negotiating Connection IDs */
|
||||
ngx_log_error(NGX_LOG_INFO, c->log, 0,
|
||||
"quic too short dcid in initial"
|
||||
" packet: len:%i", pkt->dcid.len);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
/* process retry and initialize connection IDs */
|
||||
|
||||
if (pkt->token.len) {
|
||||
|
||||
rc = ngx_quic_validate_token(c, conf->token_key, pkt);
|
||||
|
||||
if (rc == NGX_ERROR) {
|
||||
/* internal error */
|
||||
return NGX_ERROR;
|
||||
|
||||
} else if (rc == NGX_ABORT) {
|
||||
/* token cannot be decrypted */
|
||||
return ngx_quic_send_early_cc(c, pkt,
|
||||
NGX_QUIC_ERR_INVALID_TOKEN,
|
||||
"cannot decrypt token");
|
||||
} else if (rc == NGX_DECLINED) {
|
||||
/* token is invalid */
|
||||
|
||||
if (pkt->retried) {
|
||||
/* invalid Retry token */
|
||||
return ngx_quic_send_early_cc(c, pkt,
|
||||
NGX_QUIC_ERR_INVALID_TOKEN,
|
||||
"invalid token");
|
||||
} else if (conf->retry) {
|
||||
/* invalid NEW_TOKEN */
|
||||
return ngx_quic_send_retry(c, conf, pkt);
|
||||
}
|
||||
}
|
||||
|
||||
/* NGX_OK */
|
||||
|
||||
} else if (conf->retry) {
|
||||
return ngx_quic_send_retry(c, conf, pkt);
|
||||
|
||||
} else {
|
||||
pkt->odcid = pkt->dcid;
|
||||
}
|
||||
|
||||
if (ngx_terminate || ngx_exiting) {
|
||||
if (conf->retry) {
|
||||
return ngx_quic_send_retry(c, conf, pkt);
|
||||
}
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
c->log->action = "creating quic connection";
|
||||
|
||||
qc = ngx_quic_new_connection(c, conf, pkt);
|
||||
if (qc == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
} else if (pkt->level == ssl_encryption_application) {
|
||||
return ngx_quic_send_stateless_reset(c, conf, pkt);
|
||||
|
||||
} else {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
return ngx_quic_process_payload(c, pkt);
|
||||
}
|
||||
|
||||
/* packet does not belong to a connection */
|
||||
|
||||
if (rc == NGX_ABORT) {
|
||||
return ngx_quic_negotiate_version(c, pkt);
|
||||
}
|
||||
|
||||
if (pkt->level == ssl_encryption_application) {
|
||||
return ngx_quic_send_stateless_reset(c, conf, pkt);
|
||||
}
|
||||
|
||||
if (pkt->level != ssl_encryption_initial) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
c->log->action = "processing initial packet";
|
||||
|
||||
if (pkt->dcid.len < NGX_QUIC_CID_LEN_MIN) {
|
||||
/* 7.2. Negotiating Connection IDs */
|
||||
ngx_log_error(NGX_LOG_INFO, c->log, 0,
|
||||
"quic too short dcid in initial"
|
||||
" packet: len:%i", pkt->dcid.len);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
/* process retry and initialize connection IDs */
|
||||
|
||||
if (pkt->token.len) {
|
||||
|
||||
rc = ngx_quic_validate_token(c, conf->token_key, pkt);
|
||||
|
||||
if (rc == NGX_ERROR) {
|
||||
/* internal error */
|
||||
return NGX_ERROR;
|
||||
|
||||
} else if (rc == NGX_ABORT) {
|
||||
/* token cannot be decrypted */
|
||||
return ngx_quic_send_early_cc(c, pkt,
|
||||
NGX_QUIC_ERR_INVALID_TOKEN,
|
||||
"cannot decrypt token");
|
||||
} else if (rc == NGX_DECLINED) {
|
||||
/* token is invalid */
|
||||
|
||||
if (pkt->retried) {
|
||||
/* invalid Retry token */
|
||||
return ngx_quic_send_early_cc(c, pkt,
|
||||
NGX_QUIC_ERR_INVALID_TOKEN,
|
||||
"invalid token");
|
||||
} else if (conf->retry) {
|
||||
/* invalid NEW_TOKEN */
|
||||
return ngx_quic_send_retry(c, conf, pkt);
|
||||
}
|
||||
}
|
||||
|
||||
/* NGX_OK */
|
||||
|
||||
} else if (conf->retry) {
|
||||
return ngx_quic_send_retry(c, conf, pkt);
|
||||
|
||||
} else {
|
||||
pkt->odcid = pkt->dcid;
|
||||
}
|
||||
|
||||
if (ngx_terminate || ngx_exiting) {
|
||||
if (conf->retry) {
|
||||
return ngx_quic_send_retry(c, conf, pkt);
|
||||
}
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
c->log->action = "creating quic connection";
|
||||
|
||||
qc = ngx_quic_new_connection(c, conf, pkt);
|
||||
if (qc == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
return ngx_quic_process_payload(c, pkt);
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_quic_process_payload(ngx_connection_t *c, ngx_quic_header_t *pkt)
|
||||
{
|
||||
ngx_int_t rc;
|
||||
ngx_quic_send_ctx_t *ctx;
|
||||
ngx_quic_connection_t *qc;
|
||||
static u_char buf[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];
|
||||
|
||||
qc = ngx_quic_get_connection(c);
|
||||
|
||||
qc->error = 0;
|
||||
qc->error_reason = 0;
|
||||
|
||||
c->log->action = "decrypting packet";
|
||||
|
||||
if (!ngx_quic_keys_available(qc->keys, pkt->level)) {
|
||||
@ -2404,16 +2415,35 @@ ngx_quic_process_packet(ngx_connection_t *c, ngx_quic_conf_t *conf,
|
||||
}
|
||||
}
|
||||
|
||||
if (qc->closing) {
|
||||
/*
|
||||
* 10.1 Closing and Draining Connection States
|
||||
* ... delayed or reordered packets are properly discarded.
|
||||
*
|
||||
* An endpoint retains only enough information to generate
|
||||
* a packet containing a CONNECTION_CLOSE frame and to identify
|
||||
* packets as belonging to the connection.
|
||||
*/
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
pkt->received = ngx_current_msec;
|
||||
|
||||
c->log->action = "handling payload";
|
||||
|
||||
if (pkt->level != ssl_encryption_application) {
|
||||
return ngx_quic_payload_handler(c, pkt);
|
||||
return ngx_quic_handle_frames(c, pkt);
|
||||
}
|
||||
|
||||
if (!pkt->key_update) {
|
||||
return ngx_quic_payload_handler(c, pkt);
|
||||
return ngx_quic_handle_frames(c, pkt);
|
||||
}
|
||||
|
||||
/* switch keys and generate next on Key Phase change */
|
||||
@ -2421,7 +2451,7 @@ ngx_quic_process_packet(ngx_connection_t *c, ngx_quic_conf_t *conf,
|
||||
qc->key_phase ^= 1;
|
||||
ngx_quic_keys_switch(c, qc->keys);
|
||||
|
||||
rc = ngx_quic_payload_handler(c, pkt);
|
||||
rc = ngx_quic_handle_frames(c, pkt);
|
||||
if (rc != NGX_OK) {
|
||||
return rc;
|
||||
}
|
||||
@ -2581,7 +2611,7 @@ ngx_quic_check_peer(ngx_quic_connection_t *qc, ngx_quic_header_t *pkt)
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_quic_payload_handler(ngx_connection_t *c, ngx_quic_header_t *pkt)
|
||||
ngx_quic_handle_frames(ngx_connection_t *c, ngx_quic_header_t *pkt)
|
||||
{
|
||||
u_char *end, *p;
|
||||
ssize_t len;
|
||||
@ -2593,25 +2623,6 @@ ngx_quic_payload_handler(ngx_connection_t *c, ngx_quic_header_t *pkt)
|
||||
|
||||
qc = ngx_quic_get_connection(c);
|
||||
|
||||
if (qc->closing) {
|
||||
/*
|
||||
* 10.1 Closing and Draining Connection States
|
||||
* ... delayed or reordered packets are properly discarded.
|
||||
*
|
||||
* An endpoint retains only enough information to generate
|
||||
* a packet containing a CONNECTION_CLOSE frame and to identify
|
||||
* packets as belonging to the connection.
|
||||
*/
|
||||
|
||||
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;
|
||||
end = p + pkt->payload.len;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user