Proper handling of packet number in header.
- fixed setting of largest received packet number. - sending properly truncated packet number - added support for multi-byte packet number
This commit is contained in:
parent
3d9b7f1c8b
commit
7e1e892a8a
|
@ -48,7 +48,7 @@ typedef struct {
|
|||
ngx_quic_secret_t server_secret;
|
||||
|
||||
uint64_t pnum;
|
||||
uint64_t largest;
|
||||
uint64_t largest; /* number received from peer */
|
||||
|
||||
ngx_queue_t frames;
|
||||
ngx_queue_t sent;
|
||||
|
@ -150,6 +150,9 @@ static ngx_int_t ngx_quic_output_ns(ngx_connection_t *c,
|
|||
ngx_quic_namespace_t *ns, ngx_uint_t nsi);
|
||||
static void ngx_quic_free_frames(ngx_connection_t *c, ngx_queue_t *frames);
|
||||
static ngx_int_t ngx_quic_send_frames(ngx_connection_t *c, ngx_queue_t *frames);
|
||||
|
||||
static void ngx_quic_set_packet_number(ngx_quic_header_t *pkt,
|
||||
ngx_quic_namespace_t *ns);
|
||||
static void ngx_quic_retransmit_handler(ngx_event_t *ev);
|
||||
static ngx_int_t ngx_quic_retransmit_ns(ngx_connection_t *c,
|
||||
ngx_quic_namespace_t *ns, ngx_msec_t *waitp);
|
||||
|
@ -1235,7 +1238,7 @@ ngx_quic_handle_ack_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
|
|||
|
||||
if (ack->largest <= ns->pnum) {
|
||||
/* duplicate ACK or ACK for non-ack-eliciting frame */
|
||||
return NGX_OK;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ngx_log_error(NGX_LOG_INFO, c->log, 0,
|
||||
|
@ -1244,9 +1247,13 @@ ngx_quic_handle_ack_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
|
|||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
/* 13.2.3. Receiver Tracking of ACK Frames */
|
||||
if (ns->largest < ack->largest) {
|
||||
ack->largest = ns->largest;
|
||||
ns->largest = ack->largest;
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"updated largest received: %ui", ns->largest);
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
|
@ -1740,7 +1747,6 @@ ngx_quic_send_frames(ngx_connection_t *c, ngx_queue_t *frames)
|
|||
keys = &c->quic->keys[start->level];
|
||||
|
||||
pkt.secret = &keys->server;
|
||||
pkt.number = ns->pnum;
|
||||
|
||||
if (start->level == ssl_encryption_initial) {
|
||||
pkt.flags = NGX_QUIC_PKT_INITIAL;
|
||||
|
@ -1748,8 +1754,13 @@ ngx_quic_send_frames(ngx_connection_t *c, ngx_queue_t *frames)
|
|||
|
||||
} else if (start->level == ssl_encryption_handshake) {
|
||||
pkt.flags = NGX_QUIC_PKT_HANDSHAKE;
|
||||
|
||||
} else {
|
||||
pkt.flags = 0x40; // TODO: macro, set FIXED bit
|
||||
}
|
||||
|
||||
ngx_quic_set_packet_number(&pkt, ns);
|
||||
|
||||
pkt.log = c->log;
|
||||
pkt.level = start->level;
|
||||
pkt.dcid = qc->dcid;
|
||||
|
@ -1779,6 +1790,36 @@ ngx_quic_send_frames(ngx_connection_t *c, ngx_queue_t *frames)
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
ngx_quic_set_packet_number(ngx_quic_header_t *pkt, ngx_quic_namespace_t *ns)
|
||||
{
|
||||
uint64_t delta;
|
||||
|
||||
delta = ns->pnum - ns->largest;
|
||||
pkt->number = ns->pnum;
|
||||
|
||||
if (delta <= 0x7F) {
|
||||
pkt->num_len = 1;
|
||||
pkt->trunc = ns->pnum & 0xff;
|
||||
|
||||
} else if (delta <= 0x7FFF) {
|
||||
pkt->num_len = 2;
|
||||
pkt->flags |= 0x1;
|
||||
pkt->trunc = ns->pnum & 0xffff;
|
||||
|
||||
} else if (delta <= 0x7FFFFF) {
|
||||
pkt->num_len = 3;
|
||||
pkt->flags |= 0x2;
|
||||
pkt->trunc = ns->pnum & 0xffffff;
|
||||
|
||||
} else {
|
||||
pkt->num_len = 4;
|
||||
pkt->flags |= 0x3;
|
||||
pkt->trunc = ns->pnum & 0xffffffff;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ngx_quic_retransmit_handler(ngx_event_t *ev)
|
||||
{
|
||||
|
|
|
@ -656,6 +656,7 @@ ngx_quic_create_long_packet(ngx_quic_header_t *pkt, ngx_ssl_conn_t *ssl_conn,
|
|||
{
|
||||
u_char *pnp, *sample;
|
||||
ngx_str_t ad, out;
|
||||
ngx_uint_t i;
|
||||
ngx_quic_ciphers_t ciphers;
|
||||
u_char nonce[12], mask[16];
|
||||
|
||||
|
@ -685,7 +686,7 @@ ngx_quic_create_long_packet(ngx_quic_header_t *pkt, ngx_ssl_conn_t *ssl_conn,
|
|||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
sample = &out.data[3]; // pnl=0
|
||||
sample = &out.data[4 - pkt->num_len];
|
||||
if (ngx_quic_tls_hp(pkt->log, ciphers.hp, pkt->secret, mask, sample)
|
||||
!= NGX_OK)
|
||||
{
|
||||
|
@ -696,9 +697,12 @@ ngx_quic_create_long_packet(ngx_quic_header_t *pkt, ngx_ssl_conn_t *ssl_conn,
|
|||
ngx_quic_hexdump0(pkt->log, "mask", mask, 16);
|
||||
ngx_quic_hexdump0(pkt->log, "hp_key", pkt->secret->hp.data, 16);
|
||||
|
||||
// header protection, pnl = 0
|
||||
/* quic-tls: 5.4.1. Header Protection Application */
|
||||
ad.data[0] ^= mask[0] & 0x0f;
|
||||
*pnp ^= mask[1];
|
||||
|
||||
for (i = 0; i < pkt->num_len; i++) {
|
||||
pnp[i] ^= mask[i + 1];
|
||||
}
|
||||
|
||||
res->len = ad.len + out.len;
|
||||
|
||||
|
@ -712,6 +716,7 @@ ngx_quic_create_short_packet(ngx_quic_header_t *pkt, ngx_ssl_conn_t *ssl_conn,
|
|||
{
|
||||
u_char *pnp, *sample;
|
||||
ngx_str_t ad, out;
|
||||
ngx_uint_t i;
|
||||
ngx_quic_ciphers_t ciphers;
|
||||
u_char nonce[12], mask[16];
|
||||
|
||||
|
@ -743,7 +748,7 @@ ngx_quic_create_short_packet(ngx_quic_header_t *pkt, ngx_ssl_conn_t *ssl_conn,
|
|||
|
||||
ngx_quic_hexdump0(pkt->log, "out", out.data, out.len);
|
||||
|
||||
sample = &out.data[3]; // pnl=0
|
||||
sample = &out.data[4 - pkt->num_len];
|
||||
if (ngx_quic_tls_hp(pkt->log, ciphers.hp, pkt->secret, mask, sample)
|
||||
!= NGX_OK)
|
||||
{
|
||||
|
@ -754,9 +759,12 @@ ngx_quic_create_short_packet(ngx_quic_header_t *pkt, ngx_ssl_conn_t *ssl_conn,
|
|||
ngx_quic_hexdump0(pkt->log, "mask", mask, 16);
|
||||
ngx_quic_hexdump0(pkt->log, "hp_key", pkt->secret->hp.data, 16);
|
||||
|
||||
// header protection, pnl = 0
|
||||
/* quic-tls: 5.4.1. Header Protection Application */
|
||||
ad.data[0] ^= mask[0] & 0x1f;
|
||||
*pnp ^= mask[1];
|
||||
|
||||
for (i = 0; i < pkt->num_len; i++) {
|
||||
pnp[i] ^= mask[i + 1];
|
||||
}
|
||||
|
||||
res->len = ad.len + out.len;
|
||||
|
||||
|
|
|
@ -37,6 +37,11 @@
|
|||
|
||||
#endif
|
||||
|
||||
#define ngx_quic_write_uint24(p, s) \
|
||||
((p)[0] = (u_char) ((s) >> 16), \
|
||||
(p)[1] = (u_char) ((s) >> 8), \
|
||||
(p)[2] = (u_char) (s), \
|
||||
(p) + 3)
|
||||
|
||||
#define ngx_quic_write_uint16_aligned(p, s) \
|
||||
(*(uint16_t *) (p) = htons((uint16_t) (s)), (p) + sizeof(uint16_t))
|
||||
|
@ -362,11 +367,24 @@ ngx_quic_create_long_header(ngx_quic_header_t *pkt, u_char *out,
|
|||
ngx_quic_build_int(&p, pkt->token.len);
|
||||
}
|
||||
|
||||
ngx_quic_build_int(&p, pkt_len + 1); // length (inc. pnl)
|
||||
ngx_quic_build_int(&p, pkt_len + pkt->num_len);
|
||||
|
||||
*pnp = p;
|
||||
|
||||
*p++ = pkt->number; // XXX: uint64
|
||||
switch (pkt->num_len) {
|
||||
case 1:
|
||||
*p++ = pkt->trunc;
|
||||
break;
|
||||
case 2:
|
||||
p = ngx_quic_write_uint16(p, pkt->trunc);
|
||||
break;
|
||||
case 3:
|
||||
p = ngx_quic_write_uint24(p, pkt->trunc);
|
||||
break;
|
||||
case 4:
|
||||
p = ngx_quic_write_uint32(p, pkt->trunc);
|
||||
break;
|
||||
}
|
||||
|
||||
return p - start;
|
||||
}
|
||||
|
@ -380,13 +398,26 @@ ngx_quic_create_short_header(ngx_quic_header_t *pkt, u_char *out,
|
|||
|
||||
p = start = out;
|
||||
|
||||
*p++ = 0x40;
|
||||
*p++ = pkt->flags;
|
||||
|
||||
p = ngx_cpymem(p, pkt->scid.data, pkt->scid.len);
|
||||
|
||||
*pnp = p;
|
||||
|
||||
*p++ = pkt->number; // XXX: uint64
|
||||
switch (pkt->num_len) {
|
||||
case 1:
|
||||
*p++ = pkt->trunc;
|
||||
break;
|
||||
case 2:
|
||||
p = ngx_quic_write_uint16(p, pkt->trunc);
|
||||
break;
|
||||
case 3:
|
||||
p = ngx_quic_write_uint24(p, pkt->trunc);
|
||||
break;
|
||||
case 4:
|
||||
p = ngx_quic_write_uint32(p, pkt->trunc);
|
||||
break;
|
||||
}
|
||||
|
||||
return p - start;
|
||||
}
|
||||
|
|
|
@ -238,6 +238,8 @@ typedef struct {
|
|||
|
||||
struct ngx_quic_secret_s *secret;
|
||||
uint64_t number;
|
||||
uint8_t num_len;
|
||||
uint32_t trunc;
|
||||
uint8_t flags;
|
||||
uint32_t version;
|
||||
ngx_str_t token;
|
||||
|
|
Loading…
Reference in New Issue