QUIC: separate files for connection id related processing.
This commit is contained in:
parent
0da176b67b
commit
4106995b34
5 changed files with 566 additions and 530 deletions
|
@ -1343,10 +1343,12 @@ if [ $USE_OPENSSL$USE_OPENSSL_QUIC = YESYES ]; then
|
|||
src/event/quic/ngx_event_quic_transport.h \
|
||||
src/event/quic/ngx_event_quic_protection.h \
|
||||
src/event/quic/ngx_event_quic_connection.h \
|
||||
src/event/quic/ngx_event_quic_connid.h \
|
||||
src/event/quic/ngx_event_quic_migration.h"
|
||||
ngx_module_srcs="src/event/quic/ngx_event_quic.c \
|
||||
src/event/quic/ngx_event_quic_transport.c \
|
||||
src/event/quic/ngx_event_quic_protection.c \
|
||||
src/event/quic/ngx_event_quic_connid.c \
|
||||
src/event/quic/ngx_event_quic_migration.c"
|
||||
|
||||
ngx_module_libs=
|
||||
|
|
|
@ -23,8 +23,6 @@
|
|||
|
||||
#define NGX_QUIC_STREAM_GONE (void *) -1
|
||||
|
||||
#define NGX_QUIC_UNSET_PN (uint64_t) -1
|
||||
|
||||
/*
|
||||
* Endpoints MUST discard packets that are too small to be valid QUIC
|
||||
* packets. With the set of AEAD functions defined in [QUIC-TLS],
|
||||
|
@ -66,20 +64,12 @@ static ngx_int_t ngx_quic_apply_transport_params(ngx_connection_t *c,
|
|||
ngx_quic_tp_t *ctp);
|
||||
static ngx_quic_connection_t *ngx_quic_new_connection(ngx_connection_t *c,
|
||||
ngx_quic_conf_t *conf, ngx_quic_header_t *pkt);
|
||||
static ngx_int_t ngx_quic_setup_connection_ids(ngx_connection_t *c,
|
||||
ngx_quic_connection_t *qc, ngx_quic_header_t *pkt);
|
||||
static ngx_int_t ngx_quic_send_stateless_reset(ngx_connection_t *c,
|
||||
ngx_quic_conf_t *conf, ngx_quic_header_t *pkt);
|
||||
static ngx_int_t ngx_quic_new_sr_token(ngx_connection_t *c, ngx_str_t *cid,
|
||||
u_char *secret, u_char *token);
|
||||
static ngx_int_t ngx_quic_process_stateless_reset(ngx_connection_t *c,
|
||||
ngx_quic_header_t *pkt);
|
||||
static ngx_int_t ngx_quic_negotiate_version(ngx_connection_t *c,
|
||||
ngx_quic_header_t *inpkt);
|
||||
static ngx_int_t ngx_quic_create_server_id(ngx_connection_t *c, u_char *id);
|
||||
#if (NGX_QUIC_BPF)
|
||||
static ngx_int_t ngx_quic_bpf_attach_id(ngx_connection_t *c, u_char *id);
|
||||
#endif
|
||||
static ngx_int_t ngx_quic_send_retry(ngx_connection_t *c,
|
||||
ngx_quic_conf_t *conf, ngx_quic_header_t *pkt);
|
||||
static ngx_int_t ngx_quic_new_token(ngx_connection_t *c, u_char *key,
|
||||
|
@ -163,20 +153,6 @@ static 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);
|
||||
static ngx_int_t ngx_quic_handle_max_streams_frame(ngx_connection_t *c,
|
||||
ngx_quic_header_t *pkt, ngx_quic_max_streams_frame_t *f);
|
||||
static ngx_int_t ngx_quic_handle_new_connection_id_frame(ngx_connection_t *c,
|
||||
ngx_quic_header_t *pkt, ngx_quic_new_conn_id_frame_t *f);
|
||||
static ngx_int_t ngx_quic_retire_connection_id(ngx_connection_t *c,
|
||||
enum ssl_encryption_level_t level, uint64_t seqnum);
|
||||
static ngx_int_t ngx_quic_handle_retire_connection_id_frame(ngx_connection_t *c,
|
||||
ngx_quic_header_t *pkt, ngx_quic_retire_cid_frame_t *f);
|
||||
static ngx_int_t ngx_quic_issue_server_ids(ngx_connection_t *c);
|
||||
static void ngx_quic_clear_temp_server_ids(ngx_connection_t *c);
|
||||
static ngx_quic_server_id_t *ngx_quic_insert_server_id(ngx_connection_t *c,
|
||||
ngx_quic_connection_t *qc, ngx_str_t *id);
|
||||
static ngx_quic_client_id_t *ngx_quic_alloc_client_id(ngx_connection_t *c,
|
||||
ngx_quic_connection_t *qc);
|
||||
static ngx_quic_server_id_t *ngx_quic_alloc_server_id(ngx_connection_t *c,
|
||||
ngx_quic_connection_t *qc);
|
||||
|
||||
static ngx_int_t ngx_quic_output(ngx_connection_t *c);
|
||||
static ngx_uint_t ngx_quic_get_padding_level(ngx_connection_t *c);
|
||||
|
@ -1035,84 +1011,6 @@ ngx_quic_new_connection(ngx_connection_t *c, ngx_quic_conf_t *conf,
|
|||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_quic_setup_connection_ids(ngx_connection_t *c, ngx_quic_connection_t *qc,
|
||||
ngx_quic_header_t *pkt)
|
||||
{
|
||||
ngx_quic_server_id_t *sid, *osid;
|
||||
ngx_quic_client_id_t *cid;
|
||||
|
||||
/*
|
||||
* qc->nclient_ids = 0
|
||||
* qc->nserver_ids = 0
|
||||
* qc->max_retired_seqnum = 0
|
||||
*/
|
||||
|
||||
ngx_queue_init(&qc->client_ids);
|
||||
ngx_queue_init(&qc->server_ids);
|
||||
ngx_queue_init(&qc->free_client_ids);
|
||||
ngx_queue_init(&qc->free_server_ids);
|
||||
|
||||
qc->odcid.len = pkt->odcid.len;
|
||||
qc->odcid.data = ngx_pstrdup(c->pool, &pkt->odcid);
|
||||
if (qc->odcid.data == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
qc->tp.original_dcid = qc->odcid;
|
||||
|
||||
qc->scid.len = pkt->scid.len;
|
||||
qc->scid.data = ngx_pstrdup(c->pool, &pkt->scid);
|
||||
if (qc->scid.data == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
qc->dcid.len = NGX_QUIC_SERVER_CID_LEN;
|
||||
qc->dcid.data = ngx_pnalloc(c->pool, qc->dcid.len);
|
||||
if (qc->dcid.data == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (ngx_quic_create_server_id(c, qc->dcid.data) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
qc->tp.initial_scid = qc->dcid;
|
||||
|
||||
cid = ngx_quic_alloc_client_id(c, qc);
|
||||
if (cid == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
cid->seqnum = 0;
|
||||
cid->len = pkt->scid.len;
|
||||
ngx_memcpy(cid->id, pkt->scid.data, pkt->scid.len);
|
||||
|
||||
ngx_queue_insert_tail(&qc->client_ids, &cid->queue);
|
||||
qc->nclient_ids++;
|
||||
qc->client_seqnum = 0;
|
||||
|
||||
qc->server_seqnum = NGX_QUIC_UNSET_PN;
|
||||
|
||||
osid = ngx_quic_insert_server_id(c, qc, &qc->odcid);
|
||||
if (osid == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
qc->server_seqnum = 0;
|
||||
|
||||
sid = ngx_quic_insert_server_id(c, qc, &qc->dcid);
|
||||
if (sid == NULL) {
|
||||
ngx_rbtree_delete(&c->listening->rbtree, &osid->udp.node);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
c->udp = &sid->udp;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_quic_send_stateless_reset(ngx_connection_t *c, ngx_quic_conf_t *conf,
|
||||
ngx_quic_header_t *pkt)
|
||||
|
@ -1164,7 +1062,7 @@ ngx_quic_send_stateless_reset(ngx_connection_t *c, ngx_quic_conf_t *conf,
|
|||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_int_t
|
||||
ngx_quic_new_sr_token(ngx_connection_t *c, ngx_str_t *cid, u_char *secret,
|
||||
u_char *token)
|
||||
{
|
||||
|
@ -1262,56 +1160,6 @@ ngx_quic_negotiate_version(ngx_connection_t *c, ngx_quic_header_t *inpkt)
|
|||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_quic_create_server_id(ngx_connection_t *c, u_char *id)
|
||||
{
|
||||
if (RAND_bytes(id, NGX_QUIC_SERVER_CID_LEN) != 1) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
#if (NGX_QUIC_BPF)
|
||||
if (ngx_quic_bpf_attach_id(c, id) != NGX_OK) {
|
||||
ngx_log_error(NGX_LOG_ERR, c->log, 0,
|
||||
"quic bpf failed to generate socket key");
|
||||
/* ignore error, things still may work */
|
||||
}
|
||||
#endif
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"quic create server id %*xs",
|
||||
(size_t) NGX_QUIC_SERVER_CID_LEN, id);
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
#if (NGX_QUIC_BPF)
|
||||
|
||||
static ngx_int_t
|
||||
ngx_quic_bpf_attach_id(ngx_connection_t *c, u_char *id)
|
||||
{
|
||||
int fd;
|
||||
uint64_t cookie;
|
||||
socklen_t optlen;
|
||||
|
||||
fd = c->listening->fd;
|
||||
|
||||
optlen = sizeof(cookie);
|
||||
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_COOKIE, &cookie, &optlen) == -1) {
|
||||
ngx_log_error(NGX_LOG_ERR, c->log, ngx_socket_errno,
|
||||
"quic getsockopt(SO_COOKIE) failed");
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_quic_dcid_encode_key(id, cookie);
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_quic_send_retry(ngx_connection_t *c, ngx_quic_conf_t *conf,
|
||||
ngx_quic_header_t *inpkt)
|
||||
|
@ -4390,381 +4238,6 @@ ngx_quic_handle_max_streams_frame(ngx_connection_t *c,
|
|||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_quic_handle_new_connection_id_frame(ngx_connection_t *c,
|
||||
ngx_quic_header_t *pkt, ngx_quic_new_conn_id_frame_t *f)
|
||||
{
|
||||
ngx_queue_t *q;
|
||||
ngx_quic_client_id_t *cid, *item;
|
||||
ngx_quic_connection_t *qc;
|
||||
|
||||
qc = ngx_quic_get_connection(c);
|
||||
|
||||
if (f->seqnum < qc->max_retired_seqnum) {
|
||||
/*
|
||||
* An endpoint that receives a NEW_CONNECTION_ID frame with
|
||||
* a sequence number smaller than the Retire Prior To field
|
||||
* of a previously received NEW_CONNECTION_ID frame MUST send
|
||||
* a corresponding RETIRE_CONNECTION_ID frame that retires
|
||||
* the newly received connection ID, unless it has already
|
||||
* done so for that sequence number.
|
||||
*/
|
||||
|
||||
if (ngx_quic_retire_connection_id(c, pkt->level, f->seqnum) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
goto retire;
|
||||
}
|
||||
|
||||
cid = NULL;
|
||||
|
||||
for (q = ngx_queue_head(&qc->client_ids);
|
||||
q != ngx_queue_sentinel(&qc->client_ids);
|
||||
q = ngx_queue_next(q))
|
||||
{
|
||||
item = ngx_queue_data(q, ngx_quic_client_id_t, queue);
|
||||
|
||||
if (item->seqnum == f->seqnum) {
|
||||
cid = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cid) {
|
||||
/*
|
||||
* Transmission errors, timeouts and retransmissions might cause the
|
||||
* same NEW_CONNECTION_ID frame to be received multiple times
|
||||
*/
|
||||
|
||||
if (cid->len != f->len
|
||||
|| ngx_strncmp(cid->id, f->cid, f->len) != 0
|
||||
|| ngx_strncmp(cid->sr_token, f->srt, NGX_QUIC_SR_TOKEN_LEN) != 0)
|
||||
{
|
||||
/*
|
||||
* ..a sequence number is used for different connection IDs,
|
||||
* 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";
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
cid = ngx_quic_alloc_client_id(c, qc);
|
||||
if (cid == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
cid->seqnum = f->seqnum;
|
||||
cid->len = f->len;
|
||||
ngx_memcpy(cid->id, f->cid, f->len);
|
||||
|
||||
ngx_memcpy(cid->sr_token, f->srt, NGX_QUIC_SR_TOKEN_LEN);
|
||||
|
||||
ngx_queue_insert_tail(&qc->client_ids, &cid->queue);
|
||||
qc->nclient_ids++;
|
||||
|
||||
/* always use latest available connection id */
|
||||
if (f->seqnum > qc->client_seqnum) {
|
||||
qc->scid.len = cid->len;
|
||||
qc->scid.data = cid->id;
|
||||
qc->client_seqnum = f->seqnum;
|
||||
}
|
||||
}
|
||||
|
||||
retire:
|
||||
|
||||
if (qc->max_retired_seqnum && f->retire <= qc->max_retired_seqnum) {
|
||||
/*
|
||||
* Once a sender indicates a Retire Prior To value, smaller values sent
|
||||
* in subsequent NEW_CONNECTION_ID frames have no effect. A receiver
|
||||
* MUST ignore any Retire Prior To fields that do not increase the
|
||||
* largest received Retire Prior To value.
|
||||
*/
|
||||
goto done;
|
||||
}
|
||||
|
||||
qc->max_retired_seqnum = f->retire;
|
||||
|
||||
q = ngx_queue_head(&qc->client_ids);
|
||||
|
||||
while (q != ngx_queue_sentinel(&qc->client_ids)) {
|
||||
|
||||
cid = ngx_queue_data(q, ngx_quic_client_id_t, queue);
|
||||
q = ngx_queue_next(q);
|
||||
|
||||
if (cid->seqnum >= f->retire) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* this connection id must be retired */
|
||||
|
||||
if (ngx_quic_retire_connection_id(c, pkt->level, cid->seqnum)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_queue_remove(&cid->queue);
|
||||
ngx_queue_insert_head(&qc->free_client_ids, &cid->queue);
|
||||
qc->nclient_ids--;
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
if (qc->nclient_ids > qc->tp.active_connection_id_limit) {
|
||||
/*
|
||||
* After processing a NEW_CONNECTION_ID frame and
|
||||
* adding and retiring active connection IDs, if the number of active
|
||||
* connection IDs exceeds the value advertised in its
|
||||
* 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";
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_quic_retire_connection_id(ngx_connection_t *c,
|
||||
enum ssl_encryption_level_t level, uint64_t seqnum)
|
||||
{
|
||||
ngx_quic_frame_t *frame;
|
||||
ngx_quic_connection_t *qc;
|
||||
|
||||
qc = ngx_quic_get_connection(c);
|
||||
|
||||
frame = ngx_quic_alloc_frame(c);
|
||||
if (frame == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
frame->level = level;
|
||||
frame->type = NGX_QUIC_FT_RETIRE_CONNECTION_ID;
|
||||
frame->u.retire_cid.sequence_number = seqnum;
|
||||
|
||||
ngx_quic_queue_frame(qc, frame);
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_quic_handle_retire_connection_id_frame(ngx_connection_t *c,
|
||||
ngx_quic_header_t *pkt, ngx_quic_retire_cid_frame_t *f)
|
||||
{
|
||||
ngx_queue_t *q;
|
||||
ngx_quic_server_id_t *sid;
|
||||
ngx_quic_connection_t *qc;
|
||||
|
||||
qc = ngx_quic_get_connection(c);
|
||||
|
||||
for (q = ngx_queue_head(&qc->server_ids);
|
||||
q != ngx_queue_sentinel(&qc->server_ids);
|
||||
q = ngx_queue_next(q))
|
||||
{
|
||||
sid = ngx_queue_data(q, ngx_quic_server_id_t, queue);
|
||||
|
||||
if (sid->seqnum == f->sequence_number) {
|
||||
ngx_queue_remove(q);
|
||||
ngx_queue_insert_tail(&qc->free_server_ids, &sid->queue);
|
||||
ngx_rbtree_delete(&c->listening->rbtree, &sid->udp.node);
|
||||
qc->nserver_ids--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ngx_quic_issue_server_ids(c);
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_quic_issue_server_ids(ngx_connection_t *c)
|
||||
{
|
||||
ngx_str_t dcid;
|
||||
ngx_uint_t n;
|
||||
ngx_quic_frame_t *frame;
|
||||
ngx_quic_server_id_t *sid;
|
||||
ngx_quic_connection_t *qc;
|
||||
u_char id[NGX_QUIC_SERVER_CID_LEN];
|
||||
|
||||
qc = ngx_quic_get_connection(c);
|
||||
|
||||
n = ngx_min(NGX_QUIC_MAX_SERVER_IDS, qc->ctp.active_connection_id_limit);
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"quic issue server ids has:%ui max:%ui", qc->nserver_ids, n);
|
||||
|
||||
while (qc->nserver_ids < n) {
|
||||
if (ngx_quic_create_server_id(c, id) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
dcid.len = NGX_QUIC_SERVER_CID_LEN;
|
||||
dcid.data = id;
|
||||
|
||||
sid = ngx_quic_insert_server_id(c, qc, &dcid);
|
||||
if (sid == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
frame = ngx_quic_alloc_frame(c);
|
||||
if (frame == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
frame->level = ssl_encryption_application;
|
||||
frame->type = NGX_QUIC_FT_NEW_CONNECTION_ID;
|
||||
frame->u.ncid.seqnum = sid->seqnum;
|
||||
frame->u.ncid.retire = 0;
|
||||
frame->u.ncid.len = NGX_QUIC_SERVER_CID_LEN;
|
||||
ngx_memcpy(frame->u.ncid.cid, id, NGX_QUIC_SERVER_CID_LEN);
|
||||
|
||||
if (ngx_quic_new_sr_token(c, &dcid, qc->conf->sr_token_key,
|
||||
frame->u.ncid.srt)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_quic_queue_frame(qc, frame);
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ngx_quic_clear_temp_server_ids(ngx_connection_t *c)
|
||||
{
|
||||
ngx_queue_t *q, *next;
|
||||
ngx_quic_server_id_t *sid;
|
||||
ngx_quic_connection_t *qc;
|
||||
|
||||
qc = ngx_quic_get_connection(c);
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"quic clear temp server ids");
|
||||
|
||||
for (q = ngx_queue_head(&qc->server_ids);
|
||||
q != ngx_queue_sentinel(&qc->server_ids);
|
||||
q = next)
|
||||
{
|
||||
next = ngx_queue_next(q);
|
||||
sid = ngx_queue_data(q, ngx_quic_server_id_t, queue);
|
||||
|
||||
if (sid->seqnum != NGX_QUIC_UNSET_PN) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ngx_queue_remove(q);
|
||||
ngx_queue_insert_tail(&qc->free_server_ids, &sid->queue);
|
||||
ngx_rbtree_delete(&c->listening->rbtree, &sid->udp.node);
|
||||
qc->nserver_ids--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static ngx_quic_server_id_t *
|
||||
ngx_quic_insert_server_id(ngx_connection_t *c, ngx_quic_connection_t *qc,
|
||||
ngx_str_t *id)
|
||||
{
|
||||
ngx_str_t dcid;
|
||||
ngx_quic_server_id_t *sid;
|
||||
|
||||
sid = ngx_quic_alloc_server_id(c, qc);
|
||||
if (sid == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sid->quic = qc;
|
||||
|
||||
sid->seqnum = qc->server_seqnum;
|
||||
|
||||
if (qc->server_seqnum != NGX_QUIC_UNSET_PN) {
|
||||
qc->server_seqnum++;
|
||||
}
|
||||
|
||||
sid->len = id->len;
|
||||
ngx_memcpy(sid->id, id->data, id->len);
|
||||
|
||||
ngx_queue_insert_tail(&qc->server_ids, &sid->queue);
|
||||
qc->nserver_ids++;
|
||||
|
||||
dcid.data = sid->id;
|
||||
dcid.len = sid->len;
|
||||
|
||||
ngx_insert_udp_connection(c, &sid->udp, &dcid);
|
||||
|
||||
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"quic insert server id seqnum:%uL id len:%uz %xV",
|
||||
sid->seqnum, id->len, id);
|
||||
|
||||
return sid;
|
||||
}
|
||||
|
||||
|
||||
static ngx_quic_client_id_t *
|
||||
ngx_quic_alloc_client_id(ngx_connection_t *c, ngx_quic_connection_t *qc)
|
||||
{
|
||||
ngx_queue_t *q;
|
||||
ngx_quic_client_id_t *cid;
|
||||
|
||||
if (!ngx_queue_empty(&qc->free_client_ids)) {
|
||||
|
||||
q = ngx_queue_head(&qc->free_client_ids);
|
||||
cid = ngx_queue_data(q, ngx_quic_client_id_t, queue);
|
||||
|
||||
ngx_queue_remove(&cid->queue);
|
||||
|
||||
ngx_memzero(cid, sizeof(ngx_quic_client_id_t));
|
||||
|
||||
} else {
|
||||
|
||||
cid = ngx_pcalloc(c->pool, sizeof(ngx_quic_client_id_t));
|
||||
if (cid == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return cid;
|
||||
}
|
||||
|
||||
|
||||
static ngx_quic_server_id_t *
|
||||
ngx_quic_alloc_server_id(ngx_connection_t *c, ngx_quic_connection_t *qc)
|
||||
{
|
||||
ngx_queue_t *q;
|
||||
ngx_quic_server_id_t *sid;
|
||||
|
||||
if (!ngx_queue_empty(&qc->free_server_ids)) {
|
||||
|
||||
q = ngx_queue_head(&qc->free_server_ids);
|
||||
sid = ngx_queue_data(q, ngx_quic_server_id_t, queue);
|
||||
|
||||
ngx_queue_remove(&sid->queue);
|
||||
|
||||
ngx_memzero(sid, sizeof(ngx_quic_server_id_t));
|
||||
|
||||
} else {
|
||||
|
||||
sid = ngx_pcalloc(c->pool, sizeof(ngx_quic_server_id_t));
|
||||
if (sid == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return sid;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ngx_quic_queue_frame(ngx_quic_connection_t *qc, ngx_quic_frame_t *frame)
|
||||
{
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
typedef struct ngx_quic_connection_s ngx_quic_connection_t;
|
||||
|
||||
#include <ngx_event_quic_migration.h>
|
||||
#include <ngx_event_quic_connid.h>
|
||||
|
||||
|
||||
#define NGX_QUIC_MAX_SHORT_HEADER 25 /* 1 flags + 20 dcid + 4 pn */
|
||||
|
@ -44,10 +45,10 @@ typedef struct ngx_quic_connection_s ngx_quic_connection_t;
|
|||
|
||||
#define NGX_QUIC_CC_MIN_INTERVAL 1000 /* 1s */
|
||||
|
||||
#define NGX_QUIC_MAX_SERVER_IDS 8
|
||||
|
||||
#define NGX_QUIC_BUFFER_SIZE 4096
|
||||
|
||||
#define NGX_QUIC_UNSET_PN (uint64_t) -1
|
||||
|
||||
#define NGX_QUIC_SEND_CTX_LAST (NGX_QUIC_ENCRYPTION_LAST - 1)
|
||||
|
||||
/* 0-RTT and 1-RTT data exist in the same packet number space,
|
||||
|
@ -223,6 +224,9 @@ void ngx_quic_queue_frame(ngx_quic_connection_t *qc, ngx_quic_frame_t *frame);
|
|||
void ngx_quic_close_connection(ngx_connection_t *c, ngx_int_t rc);
|
||||
ngx_msec_t ngx_quic_pto(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx);
|
||||
|
||||
ngx_int_t ngx_quic_new_sr_token(ngx_connection_t *c, ngx_str_t *cid,
|
||||
u_char *secret, u_char *token);
|
||||
|
||||
/********************************* DEBUG *************************************/
|
||||
|
||||
/* #define NGX_QUIC_DEBUG_PACKETS */ /* dump packet contents */
|
||||
|
|
532
src/event/quic/ngx_event_quic_connid.c
Normal file
532
src/event/quic/ngx_event_quic_connid.c
Normal file
|
@ -0,0 +1,532 @@
|
|||
|
||||
/*
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_event.h>
|
||||
#include <ngx_event_quic_connection.h>
|
||||
|
||||
|
||||
#define NGX_QUIC_MAX_SERVER_IDS 8
|
||||
|
||||
|
||||
static ngx_int_t ngx_quic_create_server_id(ngx_connection_t *c, u_char *id);
|
||||
#if (NGX_QUIC_BPF)
|
||||
static ngx_int_t ngx_quic_bpf_attach_id(ngx_connection_t *c, u_char *id);
|
||||
#endif
|
||||
static ngx_int_t ngx_quic_retire_connection_id(ngx_connection_t *c,
|
||||
enum ssl_encryption_level_t level, uint64_t seqnum);
|
||||
static ngx_quic_server_id_t *ngx_quic_insert_server_id(ngx_connection_t *c,
|
||||
ngx_quic_connection_t *qc, ngx_str_t *id);
|
||||
static ngx_quic_client_id_t *ngx_quic_alloc_client_id(ngx_connection_t *c,
|
||||
ngx_quic_connection_t *qc);
|
||||
static ngx_quic_server_id_t *ngx_quic_alloc_server_id(ngx_connection_t *c,
|
||||
ngx_quic_connection_t *qc);
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_quic_setup_connection_ids(ngx_connection_t *c, ngx_quic_connection_t *qc,
|
||||
ngx_quic_header_t *pkt)
|
||||
{
|
||||
ngx_quic_server_id_t *sid, *osid;
|
||||
ngx_quic_client_id_t *cid;
|
||||
|
||||
/*
|
||||
* qc->nclient_ids = 0
|
||||
* qc->nserver_ids = 0
|
||||
* qc->max_retired_seqnum = 0
|
||||
*/
|
||||
|
||||
ngx_queue_init(&qc->client_ids);
|
||||
ngx_queue_init(&qc->server_ids);
|
||||
ngx_queue_init(&qc->free_client_ids);
|
||||
ngx_queue_init(&qc->free_server_ids);
|
||||
|
||||
qc->odcid.len = pkt->odcid.len;
|
||||
qc->odcid.data = ngx_pstrdup(c->pool, &pkt->odcid);
|
||||
if (qc->odcid.data == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
qc->tp.original_dcid = qc->odcid;
|
||||
|
||||
qc->scid.len = pkt->scid.len;
|
||||
qc->scid.data = ngx_pstrdup(c->pool, &pkt->scid);
|
||||
if (qc->scid.data == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
qc->dcid.len = NGX_QUIC_SERVER_CID_LEN;
|
||||
qc->dcid.data = ngx_pnalloc(c->pool, qc->dcid.len);
|
||||
if (qc->dcid.data == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (ngx_quic_create_server_id(c, qc->dcid.data) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
qc->tp.initial_scid = qc->dcid;
|
||||
|
||||
cid = ngx_quic_alloc_client_id(c, qc);
|
||||
if (cid == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
cid->seqnum = 0;
|
||||
cid->len = pkt->scid.len;
|
||||
ngx_memcpy(cid->id, pkt->scid.data, pkt->scid.len);
|
||||
|
||||
ngx_queue_insert_tail(&qc->client_ids, &cid->queue);
|
||||
qc->nclient_ids++;
|
||||
qc->client_seqnum = 0;
|
||||
|
||||
qc->server_seqnum = NGX_QUIC_UNSET_PN;
|
||||
|
||||
osid = ngx_quic_insert_server_id(c, qc, &qc->odcid);
|
||||
if (osid == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
qc->server_seqnum = 0;
|
||||
|
||||
sid = ngx_quic_insert_server_id(c, qc, &qc->dcid);
|
||||
if (sid == NULL) {
|
||||
ngx_rbtree_delete(&c->listening->rbtree, &osid->udp.node);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
c->udp = &sid->udp;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_quic_create_server_id(ngx_connection_t *c, u_char *id)
|
||||
{
|
||||
if (RAND_bytes(id, NGX_QUIC_SERVER_CID_LEN) != 1) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
#if (NGX_QUIC_BPF)
|
||||
if (ngx_quic_bpf_attach_id(c, id) != NGX_OK) {
|
||||
ngx_log_error(NGX_LOG_ERR, c->log, 0,
|
||||
"quic bpf failed to generate socket key");
|
||||
/* ignore error, things still may work */
|
||||
}
|
||||
#endif
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"quic create server id %*xs",
|
||||
(size_t) NGX_QUIC_SERVER_CID_LEN, id);
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
#if (NGX_QUIC_BPF)
|
||||
|
||||
static ngx_int_t
|
||||
ngx_quic_bpf_attach_id(ngx_connection_t *c, u_char *id)
|
||||
{
|
||||
int fd;
|
||||
uint64_t cookie;
|
||||
socklen_t optlen;
|
||||
|
||||
fd = c->listening->fd;
|
||||
|
||||
optlen = sizeof(cookie);
|
||||
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_COOKIE, &cookie, &optlen) == -1) {
|
||||
ngx_log_error(NGX_LOG_ERR, c->log, ngx_socket_errno,
|
||||
"quic getsockopt(SO_COOKIE) failed");
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_quic_dcid_encode_key(id, cookie);
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_quic_handle_new_connection_id_frame(ngx_connection_t *c,
|
||||
ngx_quic_header_t *pkt, ngx_quic_new_conn_id_frame_t *f)
|
||||
{
|
||||
ngx_queue_t *q;
|
||||
ngx_quic_client_id_t *cid, *item;
|
||||
ngx_quic_connection_t *qc;
|
||||
|
||||
qc = ngx_quic_get_connection(c);
|
||||
|
||||
if (f->seqnum < qc->max_retired_seqnum) {
|
||||
/*
|
||||
* An endpoint that receives a NEW_CONNECTION_ID frame with
|
||||
* a sequence number smaller than the Retire Prior To field
|
||||
* of a previously received NEW_CONNECTION_ID frame MUST send
|
||||
* a corresponding RETIRE_CONNECTION_ID frame that retires
|
||||
* the newly received connection ID, unless it has already
|
||||
* done so for that sequence number.
|
||||
*/
|
||||
|
||||
if (ngx_quic_retire_connection_id(c, pkt->level, f->seqnum) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
goto retire;
|
||||
}
|
||||
|
||||
cid = NULL;
|
||||
|
||||
for (q = ngx_queue_head(&qc->client_ids);
|
||||
q != ngx_queue_sentinel(&qc->client_ids);
|
||||
q = ngx_queue_next(q))
|
||||
{
|
||||
item = ngx_queue_data(q, ngx_quic_client_id_t, queue);
|
||||
|
||||
if (item->seqnum == f->seqnum) {
|
||||
cid = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cid) {
|
||||
/*
|
||||
* Transmission errors, timeouts and retransmissions might cause the
|
||||
* same NEW_CONNECTION_ID frame to be received multiple times
|
||||
*/
|
||||
|
||||
if (cid->len != f->len
|
||||
|| ngx_strncmp(cid->id, f->cid, f->len) != 0
|
||||
|| ngx_strncmp(cid->sr_token, f->srt, NGX_QUIC_SR_TOKEN_LEN) != 0)
|
||||
{
|
||||
/*
|
||||
* ..a sequence number is used for different connection IDs,
|
||||
* 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";
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
cid = ngx_quic_alloc_client_id(c, qc);
|
||||
if (cid == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
cid->seqnum = f->seqnum;
|
||||
cid->len = f->len;
|
||||
ngx_memcpy(cid->id, f->cid, f->len);
|
||||
|
||||
ngx_memcpy(cid->sr_token, f->srt, NGX_QUIC_SR_TOKEN_LEN);
|
||||
|
||||
ngx_queue_insert_tail(&qc->client_ids, &cid->queue);
|
||||
qc->nclient_ids++;
|
||||
|
||||
/* always use latest available connection id */
|
||||
if (f->seqnum > qc->client_seqnum) {
|
||||
qc->scid.len = cid->len;
|
||||
qc->scid.data = cid->id;
|
||||
qc->client_seqnum = f->seqnum;
|
||||
}
|
||||
}
|
||||
|
||||
retire:
|
||||
|
||||
if (qc->max_retired_seqnum && f->retire <= qc->max_retired_seqnum) {
|
||||
/*
|
||||
* Once a sender indicates a Retire Prior To value, smaller values sent
|
||||
* in subsequent NEW_CONNECTION_ID frames have no effect. A receiver
|
||||
* MUST ignore any Retire Prior To fields that do not increase the
|
||||
* largest received Retire Prior To value.
|
||||
*/
|
||||
goto done;
|
||||
}
|
||||
|
||||
qc->max_retired_seqnum = f->retire;
|
||||
|
||||
q = ngx_queue_head(&qc->client_ids);
|
||||
|
||||
while (q != ngx_queue_sentinel(&qc->client_ids)) {
|
||||
|
||||
cid = ngx_queue_data(q, ngx_quic_client_id_t, queue);
|
||||
q = ngx_queue_next(q);
|
||||
|
||||
if (cid->seqnum >= f->retire) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* this connection id must be retired */
|
||||
|
||||
if (ngx_quic_retire_connection_id(c, pkt->level, cid->seqnum)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_queue_remove(&cid->queue);
|
||||
ngx_queue_insert_head(&qc->free_client_ids, &cid->queue);
|
||||
qc->nclient_ids--;
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
if (qc->nclient_ids > qc->tp.active_connection_id_limit) {
|
||||
/*
|
||||
* After processing a NEW_CONNECTION_ID frame and
|
||||
* adding and retiring active connection IDs, if the number of active
|
||||
* connection IDs exceeds the value advertised in its
|
||||
* 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";
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_quic_retire_connection_id(ngx_connection_t *c,
|
||||
enum ssl_encryption_level_t level, uint64_t seqnum)
|
||||
{
|
||||
ngx_quic_frame_t *frame;
|
||||
ngx_quic_connection_t *qc;
|
||||
|
||||
qc = ngx_quic_get_connection(c);
|
||||
|
||||
frame = ngx_quic_alloc_frame(c);
|
||||
if (frame == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
frame->level = level;
|
||||
frame->type = NGX_QUIC_FT_RETIRE_CONNECTION_ID;
|
||||
frame->u.retire_cid.sequence_number = seqnum;
|
||||
|
||||
ngx_quic_queue_frame(qc, frame);
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_quic_handle_retire_connection_id_frame(ngx_connection_t *c,
|
||||
ngx_quic_header_t *pkt, ngx_quic_retire_cid_frame_t *f)
|
||||
{
|
||||
ngx_queue_t *q;
|
||||
ngx_quic_server_id_t *sid;
|
||||
ngx_quic_connection_t *qc;
|
||||
|
||||
qc = ngx_quic_get_connection(c);
|
||||
|
||||
for (q = ngx_queue_head(&qc->server_ids);
|
||||
q != ngx_queue_sentinel(&qc->server_ids);
|
||||
q = ngx_queue_next(q))
|
||||
{
|
||||
sid = ngx_queue_data(q, ngx_quic_server_id_t, queue);
|
||||
|
||||
if (sid->seqnum == f->sequence_number) {
|
||||
ngx_queue_remove(q);
|
||||
ngx_queue_insert_tail(&qc->free_server_ids, &sid->queue);
|
||||
ngx_rbtree_delete(&c->listening->rbtree, &sid->udp.node);
|
||||
qc->nserver_ids--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ngx_quic_issue_server_ids(c);
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_quic_issue_server_ids(ngx_connection_t *c)
|
||||
{
|
||||
ngx_str_t dcid;
|
||||
ngx_uint_t n;
|
||||
ngx_quic_frame_t *frame;
|
||||
ngx_quic_server_id_t *sid;
|
||||
ngx_quic_connection_t *qc;
|
||||
u_char id[NGX_QUIC_SERVER_CID_LEN];
|
||||
|
||||
qc = ngx_quic_get_connection(c);
|
||||
|
||||
n = ngx_min(NGX_QUIC_MAX_SERVER_IDS, qc->ctp.active_connection_id_limit);
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"quic issue server ids has:%ui max:%ui", qc->nserver_ids, n);
|
||||
|
||||
while (qc->nserver_ids < n) {
|
||||
if (ngx_quic_create_server_id(c, id) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
dcid.len = NGX_QUIC_SERVER_CID_LEN;
|
||||
dcid.data = id;
|
||||
|
||||
sid = ngx_quic_insert_server_id(c, qc, &dcid);
|
||||
if (sid == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
frame = ngx_quic_alloc_frame(c);
|
||||
if (frame == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
frame->level = ssl_encryption_application;
|
||||
frame->type = NGX_QUIC_FT_NEW_CONNECTION_ID;
|
||||
frame->u.ncid.seqnum = sid->seqnum;
|
||||
frame->u.ncid.retire = 0;
|
||||
frame->u.ncid.len = NGX_QUIC_SERVER_CID_LEN;
|
||||
ngx_memcpy(frame->u.ncid.cid, id, NGX_QUIC_SERVER_CID_LEN);
|
||||
|
||||
if (ngx_quic_new_sr_token(c, &dcid, qc->conf->sr_token_key,
|
||||
frame->u.ncid.srt)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_quic_queue_frame(qc, frame);
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ngx_quic_clear_temp_server_ids(ngx_connection_t *c)
|
||||
{
|
||||
ngx_queue_t *q, *next;
|
||||
ngx_quic_server_id_t *sid;
|
||||
ngx_quic_connection_t *qc;
|
||||
|
||||
qc = ngx_quic_get_connection(c);
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"quic clear temp server ids");
|
||||
|
||||
for (q = ngx_queue_head(&qc->server_ids);
|
||||
q != ngx_queue_sentinel(&qc->server_ids);
|
||||
q = next)
|
||||
{
|
||||
next = ngx_queue_next(q);
|
||||
sid = ngx_queue_data(q, ngx_quic_server_id_t, queue);
|
||||
|
||||
if (sid->seqnum != NGX_QUIC_UNSET_PN) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ngx_queue_remove(q);
|
||||
ngx_queue_insert_tail(&qc->free_server_ids, &sid->queue);
|
||||
ngx_rbtree_delete(&c->listening->rbtree, &sid->udp.node);
|
||||
qc->nserver_ids--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static ngx_quic_server_id_t *
|
||||
ngx_quic_insert_server_id(ngx_connection_t *c, ngx_quic_connection_t *qc,
|
||||
ngx_str_t *id)
|
||||
{
|
||||
ngx_str_t dcid;
|
||||
ngx_quic_server_id_t *sid;
|
||||
|
||||
sid = ngx_quic_alloc_server_id(c, qc);
|
||||
if (sid == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sid->quic = qc;
|
||||
|
||||
sid->seqnum = qc->server_seqnum;
|
||||
|
||||
if (qc->server_seqnum != NGX_QUIC_UNSET_PN) {
|
||||
qc->server_seqnum++;
|
||||
}
|
||||
|
||||
sid->len = id->len;
|
||||
ngx_memcpy(sid->id, id->data, id->len);
|
||||
|
||||
ngx_queue_insert_tail(&qc->server_ids, &sid->queue);
|
||||
qc->nserver_ids++;
|
||||
|
||||
dcid.data = sid->id;
|
||||
dcid.len = sid->len;
|
||||
|
||||
ngx_insert_udp_connection(c, &sid->udp, &dcid);
|
||||
|
||||
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"quic insert server id seqnum:%uL id len:%uz %xV",
|
||||
sid->seqnum, id->len, id);
|
||||
|
||||
return sid;
|
||||
}
|
||||
|
||||
|
||||
static ngx_quic_client_id_t *
|
||||
ngx_quic_alloc_client_id(ngx_connection_t *c, ngx_quic_connection_t *qc)
|
||||
{
|
||||
ngx_queue_t *q;
|
||||
ngx_quic_client_id_t *cid;
|
||||
|
||||
if (!ngx_queue_empty(&qc->free_client_ids)) {
|
||||
|
||||
q = ngx_queue_head(&qc->free_client_ids);
|
||||
cid = ngx_queue_data(q, ngx_quic_client_id_t, queue);
|
||||
|
||||
ngx_queue_remove(&cid->queue);
|
||||
|
||||
ngx_memzero(cid, sizeof(ngx_quic_client_id_t));
|
||||
|
||||
} else {
|
||||
|
||||
cid = ngx_pcalloc(c->pool, sizeof(ngx_quic_client_id_t));
|
||||
if (cid == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return cid;
|
||||
}
|
||||
|
||||
|
||||
static ngx_quic_server_id_t *
|
||||
ngx_quic_alloc_server_id(ngx_connection_t *c, ngx_quic_connection_t *qc)
|
||||
{
|
||||
ngx_queue_t *q;
|
||||
ngx_quic_server_id_t *sid;
|
||||
|
||||
if (!ngx_queue_empty(&qc->free_server_ids)) {
|
||||
|
||||
q = ngx_queue_head(&qc->free_server_ids);
|
||||
sid = ngx_queue_data(q, ngx_quic_server_id_t, queue);
|
||||
|
||||
ngx_queue_remove(&sid->queue);
|
||||
|
||||
ngx_memzero(sid, sizeof(ngx_quic_server_id_t));
|
||||
|
||||
} else {
|
||||
|
||||
sid = ngx_pcalloc(c->pool, sizeof(ngx_quic_server_id_t));
|
||||
if (sid == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return sid;
|
||||
}
|
25
src/event/quic/ngx_event_quic_connid.h
Normal file
25
src/event/quic/ngx_event_quic_connid.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
|
||||
/*
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _NGX_EVENT_QUIC_CONNID_H_INCLUDED_
|
||||
#define _NGX_EVENT_QUIC_CONNID_H_INCLUDED_
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
ngx_int_t ngx_quic_setup_connection_ids(ngx_connection_t *c,
|
||||
ngx_quic_connection_t *qc, ngx_quic_header_t *pkt);
|
||||
void ngx_quic_clear_temp_server_ids(ngx_connection_t *c);
|
||||
ngx_int_t ngx_quic_issue_server_ids(ngx_connection_t *c);
|
||||
|
||||
ngx_int_t ngx_quic_handle_retire_connection_id_frame(ngx_connection_t *c,
|
||||
ngx_quic_header_t *pkt, ngx_quic_retire_cid_frame_t *f);
|
||||
ngx_int_t ngx_quic_handle_new_connection_id_frame(ngx_connection_t *c,
|
||||
ngx_quic_header_t *pkt, ngx_quic_new_conn_id_frame_t *f);
|
||||
|
||||
#endif /* _NGX_EVENT_QUIC_CONNID_H_INCLUDED_ */
|
Loading…
Reference in a new issue