mirror of
https://github.com/nginx/nginx.git
synced 2025-06-22 22:10:45 +08:00
Added boundaries checks into frame parser.
The ngx_quic_parse_frame() functions now has new 'pkt' argument: the packet header of a currently processed frame. This allows to log errors/debug closer to reasons and perform additional checks regarding possible frame types. The handler only performs processing of good frames. A number of functions like read_uint32(), parse_int[_multi] probably should be implemented as a macro, but currently it is better to have them as functions for simpler debugging.
This commit is contained in:
parent
4cbfc07394
commit
18ce6d5ebf
@ -721,10 +721,8 @@ ngx_quic_payload_handler(ngx_connection_t *c, ngx_quic_header_t *pkt)
|
|||||||
|
|
||||||
while (p < end) {
|
while (p < end) {
|
||||||
|
|
||||||
len = ngx_quic_parse_frame(p, end, &frame);
|
len = ngx_quic_parse_frame(pkt, p, end, &frame);
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
|
||||||
"failed to parse frame type 0x%xi", frame.type);
|
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -733,14 +731,6 @@ ngx_quic_payload_handler(ngx_connection_t *c, ngx_quic_header_t *pkt)
|
|||||||
switch (frame.type) {
|
switch (frame.type) {
|
||||||
|
|
||||||
case NGX_QUIC_FT_ACK:
|
case NGX_QUIC_FT_ACK:
|
||||||
|
|
||||||
ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
|
||||||
"ACK: { largest=%ui delay=%ui first=%ui count=%ui}",
|
|
||||||
frame.u.ack.largest,
|
|
||||||
frame.u.ack.delay,
|
|
||||||
frame.u.ack.first_range,
|
|
||||||
frame.u.ack.range_count);
|
|
||||||
|
|
||||||
if (ngx_quic_handle_ack_frame(c, pkt, &frame.u.ack) != NGX_OK) {
|
if (ngx_quic_handle_ack_frame(c, pkt, &frame.u.ack) != NGX_OK) {
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
@ -749,15 +739,6 @@ ngx_quic_payload_handler(ngx_connection_t *c, ngx_quic_header_t *pkt)
|
|||||||
|
|
||||||
case NGX_QUIC_FT_CRYPTO:
|
case NGX_QUIC_FT_CRYPTO:
|
||||||
|
|
||||||
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
|
||||||
"quic CRYPTO frame length: %uL off:%uL pp:%p",
|
|
||||||
frame.u.crypto.len, frame.u.crypto.offset,
|
|
||||||
frame.u.crypto.data);
|
|
||||||
|
|
||||||
ngx_quic_hexdump0(c->log, "CRYPTO frame contents",
|
|
||||||
frame.u.crypto.data, frame.u.crypto.len);
|
|
||||||
|
|
||||||
|
|
||||||
if (ngx_quic_handle_crypto_frame(c, pkt, &frame.u.crypto)
|
if (ngx_quic_handle_crypto_frame(c, pkt, &frame.u.crypto)
|
||||||
!= NGX_OK)
|
!= NGX_OK)
|
||||||
{
|
{
|
||||||
@ -776,20 +757,9 @@ ngx_quic_payload_handler(ngx_connection_t *c, ngx_quic_header_t *pkt)
|
|||||||
|
|
||||||
case NGX_QUIC_FT_NEW_CONNECTION_ID:
|
case NGX_QUIC_FT_NEW_CONNECTION_ID:
|
||||||
ack_this = 1;
|
ack_this = 1;
|
||||||
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
|
||||||
"NCID: { seq=%ui retire=%ui len=%ui}",
|
|
||||||
frame.u.ncid.seqnum,
|
|
||||||
frame.u.ncid.retire,
|
|
||||||
frame.u.ncid.len);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NGX_QUIC_FT_CONNECTION_CLOSE:
|
case NGX_QUIC_FT_CONNECTION_CLOSE:
|
||||||
ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
|
||||||
"CONN.CLOSE: { %s (0x%xi) type=0x%xi reason='%V'}",
|
|
||||||
ngx_quic_error_text(frame.u.close.error_code),
|
|
||||||
frame.u.close.error_code,
|
|
||||||
frame.u.close.frame_type,
|
|
||||||
&frame.u.close.reason);
|
|
||||||
|
|
||||||
do_close = 1;
|
do_close = 1;
|
||||||
break;
|
break;
|
||||||
@ -803,19 +773,6 @@ ngx_quic_payload_handler(ngx_connection_t *c, ngx_quic_header_t *pkt)
|
|||||||
case NGX_QUIC_FT_STREAM6:
|
case NGX_QUIC_FT_STREAM6:
|
||||||
case NGX_QUIC_FT_STREAM7:
|
case NGX_QUIC_FT_STREAM7:
|
||||||
|
|
||||||
ngx_log_debug7(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
|
||||||
"STREAM frame { 0x%xi id 0x%xi offset 0x%xi len 0x%xi bits:off=%d len=%d fin=%d }",
|
|
||||||
frame.type,
|
|
||||||
frame.u.stream.stream_id,
|
|
||||||
frame.u.stream.offset,
|
|
||||||
frame.u.stream.length,
|
|
||||||
frame.u.stream.off,
|
|
||||||
frame.u.stream.len,
|
|
||||||
frame.u.stream.fin);
|
|
||||||
|
|
||||||
ngx_quic_hexdump0(c->log, "STREAM frame contents",
|
|
||||||
frame.u.stream.data, frame.u.stream.length);
|
|
||||||
|
|
||||||
if (ngx_quic_handle_stream_frame(c, pkt, &frame.u.stream)
|
if (ngx_quic_handle_stream_frame(c, pkt, &frame.u.stream)
|
||||||
!= NGX_OK)
|
!= NGX_OK)
|
||||||
{
|
{
|
||||||
@ -826,44 +783,24 @@ ngx_quic_payload_handler(ngx_connection_t *c, ngx_quic_header_t *pkt)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case NGX_QUIC_FT_MAX_DATA:
|
case NGX_QUIC_FT_MAX_DATA:
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
|
||||||
"MAX_DATA frame"
|
|
||||||
" { Maximum Data %ui }",
|
|
||||||
frame.u.max_data.max_data);
|
|
||||||
|
|
||||||
c->quic->max_data = frame.u.max_data.max_data;
|
c->quic->max_data = frame.u.max_data.max_data;
|
||||||
ack_this = 1;
|
ack_this = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NGX_QUIC_FT_RESET_STREAM:
|
case NGX_QUIC_FT_RESET_STREAM:
|
||||||
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
/* TODO: handle */
|
||||||
"RESET STREAM frame"
|
|
||||||
" { id 0x%xi error_code 0x%xi final_size 0x%xi }",
|
|
||||||
frame.u.reset_stream.id,
|
|
||||||
frame.u.reset_stream.error_code,
|
|
||||||
frame.u.reset_stream.final_size);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NGX_QUIC_FT_STOP_SENDING:
|
case NGX_QUIC_FT_STOP_SENDING:
|
||||||
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
/* TODO: handle; need ack ? */
|
||||||
"STOP SENDING frame"
|
|
||||||
" { id 0x%xi error_code 0x%xi}",
|
|
||||||
frame.u.stop_sending.id,
|
|
||||||
frame.u.stop_sending.error_code);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NGX_QUIC_FT_STREAMS_BLOCKED:
|
case NGX_QUIC_FT_STREAMS_BLOCKED:
|
||||||
case NGX_QUIC_FT_STREAMS_BLOCKED2:
|
case NGX_QUIC_FT_STREAMS_BLOCKED2:
|
||||||
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
/* TODO: handle; need ack ? */
|
||||||
"STREAMS BLOCKED frame"
|
|
||||||
" { limit %i bidi: %d }",
|
|
||||||
frame.u.streams_blocked.limit,
|
|
||||||
frame.u.streams_blocked.bidi);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ngx_log_error(NGX_LOG_INFO, c->log, 0,
|
|
||||||
"unsupported frame type 0x%xd in packet", frame.type);
|
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,9 +51,17 @@
|
|||||||
: 8)
|
: 8)
|
||||||
|
|
||||||
|
|
||||||
static uint64_t ngx_quic_parse_int(u_char **pos);
|
static u_char *ngx_quic_parse_int(u_char *pos, u_char *end, uint64_t *out);
|
||||||
|
static u_char *ngx_quic_parse_int_multi(u_char *pos, u_char *end, ...);
|
||||||
static void ngx_quic_build_int(u_char **pos, uint64_t value);
|
static void ngx_quic_build_int(u_char **pos, uint64_t value);
|
||||||
|
|
||||||
|
static u_char *ngx_quic_read_uint8(u_char *pos, u_char *end, uint8_t *value);
|
||||||
|
static u_char *ngx_quic_read_uint32(u_char *pos, u_char *end, uint32_t *value);
|
||||||
|
static u_char *ngx_quic_read_bytes(u_char *pos, u_char *end, size_t len,
|
||||||
|
u_char **out);
|
||||||
|
static u_char *ngx_quic_copy_bytes(u_char *pos, u_char *end, size_t len,
|
||||||
|
u_char *dst);
|
||||||
|
|
||||||
static size_t ngx_quic_create_ack(u_char *p, ngx_quic_ack_frame_t *ack);
|
static size_t ngx_quic_create_ack(u_char *p, ngx_quic_ack_frame_t *ack);
|
||||||
static size_t ngx_quic_create_crypto(u_char *p,
|
static size_t ngx_quic_create_crypto(u_char *p,
|
||||||
ngx_quic_crypto_frame_t *crypto);
|
ngx_quic_crypto_frame_t *crypto);
|
||||||
@ -81,23 +89,117 @@ static char *ngx_quic_errors[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static uint64_t
|
static ngx_inline u_char *
|
||||||
ngx_quic_parse_int(u_char **pos)
|
ngx_quic_parse_int(u_char *pos, u_char *end, uint64_t *out)
|
||||||
{
|
{
|
||||||
u_char *p;
|
u_char *p;
|
||||||
uint64_t value;
|
uint64_t value;
|
||||||
ngx_uint_t len;
|
ngx_uint_t len;
|
||||||
|
|
||||||
p = *pos;
|
if (pos >= end) {
|
||||||
|
printf("OOPS >=\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = pos;
|
||||||
len = 1 << ((*p & 0xc0) >> 6);
|
len = 1 << ((*p & 0xc0) >> 6);
|
||||||
|
|
||||||
value = *p++ & 0x3f;
|
value = *p++ & 0x3f;
|
||||||
|
|
||||||
|
if ((size_t)(end - p) < (len - 1)) {
|
||||||
|
printf("LEN TOO BIG: need %ld have %ld\n", len, end - p);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
while (--len) {
|
while (--len) {
|
||||||
value = (value << 8) + *p++;
|
value = (value << 8) + *p++;
|
||||||
}
|
}
|
||||||
|
|
||||||
*pos = p;
|
*out = value;
|
||||||
return value;
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_inline u_char *
|
||||||
|
ngx_quic_parse_int_multi(u_char *pos, u_char *end, ...)
|
||||||
|
{
|
||||||
|
u_char *p;
|
||||||
|
va_list ap;
|
||||||
|
uint64_t *item;
|
||||||
|
|
||||||
|
p = pos;
|
||||||
|
|
||||||
|
va_start(ap, end);
|
||||||
|
|
||||||
|
do {
|
||||||
|
item = va_arg(ap, uint64_t *);
|
||||||
|
if (item == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = ngx_quic_parse_int(p, end, item);
|
||||||
|
if (p == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
} while (1);
|
||||||
|
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_inline u_char *
|
||||||
|
ngx_quic_read_uint8(u_char *pos, u_char *end, uint8_t *value)
|
||||||
|
{
|
||||||
|
if ((size_t)(end - pos) < 1) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*value = *pos;
|
||||||
|
|
||||||
|
return pos + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_inline u_char *
|
||||||
|
ngx_quic_read_uint32(u_char *pos, u_char *end, uint32_t *value)
|
||||||
|
{
|
||||||
|
if ((size_t)(end - pos) < sizeof(uint32_t)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*value = ngx_quic_parse_uint32(pos);
|
||||||
|
|
||||||
|
return pos + sizeof(uint32_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_inline u_char *
|
||||||
|
ngx_quic_read_bytes(u_char *pos, u_char *end, size_t len, u_char **out)
|
||||||
|
{
|
||||||
|
if ((size_t)(end - pos) < len) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out = pos;
|
||||||
|
|
||||||
|
return pos + len;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static u_char *
|
||||||
|
ngx_quic_copy_bytes(u_char *pos, u_char *end, size_t len, u_char *dst)
|
||||||
|
{
|
||||||
|
if ((size_t)(end - pos) < len) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_memcpy(dst, pos, len);
|
||||||
|
|
||||||
|
return pos + len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -141,37 +243,72 @@ ngx_quic_error_text(uint64_t error_code)
|
|||||||
ngx_int_t
|
ngx_int_t
|
||||||
ngx_quic_parse_long_header(ngx_quic_header_t *pkt)
|
ngx_quic_parse_long_header(ngx_quic_header_t *pkt)
|
||||||
{
|
{
|
||||||
u_char *p;
|
u_char *p, *end;
|
||||||
|
uint8_t idlen;
|
||||||
|
|
||||||
p = pkt->data;
|
p = pkt->data;
|
||||||
|
end = pkt->data + pkt->len;
|
||||||
|
|
||||||
ngx_quic_hexdump0(pkt->log, "long input", pkt->data, pkt->len);
|
ngx_quic_hexdump0(pkt->log, "long input", pkt->data, pkt->len);
|
||||||
|
|
||||||
if (!(p[0] & NGX_QUIC_PKT_LONG)) {
|
p = ngx_quic_read_uint8(p, end, &pkt->flags);
|
||||||
ngx_log_error(NGX_LOG_INFO, pkt->log, 0, "not a long packet");
|
if (p == NULL) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0,
|
||||||
|
"packet is too short to read flags");
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
pkt->flags = *p++;
|
if (!(pkt->flags & NGX_QUIC_PKT_LONG)) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0, "not a long packet");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
pkt->version = ngx_quic_parse_uint32(p);
|
p = ngx_quic_read_uint32(p, end, &pkt->version);
|
||||||
p += sizeof(uint32_t);
|
if (p == NULL) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0,
|
||||||
|
"packet is too short to read version");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, pkt->log, 0,
|
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, pkt->log, 0,
|
||||||
"quic flags:%xi version:%xD", pkt->flags, pkt->version);
|
"quic flags:%xi version:%xD", pkt->flags, pkt->version);
|
||||||
|
|
||||||
if (pkt->version != quic_version) {
|
if (pkt->version != quic_version) {
|
||||||
ngx_log_error(NGX_LOG_INFO, pkt->log, 0, "unsupported quic version");
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0, "unsupported quic version");
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
pkt->dcid.len = *p++;
|
p = ngx_quic_read_uint8(p, end, &idlen);
|
||||||
pkt->dcid.data = p;
|
if (p == NULL) {
|
||||||
p += pkt->dcid.len;
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0,
|
||||||
|
"packet is too short to read dcid len");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
pkt->scid.len = *p++;
|
pkt->dcid.len = idlen;
|
||||||
pkt->scid.data = p;
|
|
||||||
p += pkt->scid.len;
|
p = ngx_quic_read_bytes(p, end, idlen, &pkt->dcid.data);
|
||||||
|
if (p == NULL) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0,
|
||||||
|
"packet is too short to read dcid");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = ngx_quic_read_uint8(p, end, &idlen);
|
||||||
|
if (p == NULL) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0,
|
||||||
|
"packet is too short to read scid len");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
pkt->scid.len = idlen;
|
||||||
|
|
||||||
|
p = ngx_quic_read_bytes(p, end, idlen, &pkt->scid.data);
|
||||||
|
if (p == NULL) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0,
|
||||||
|
"packet is too short to read scid");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
pkt->raw->pos = p;
|
pkt->raw->pos = p;
|
||||||
|
|
||||||
@ -214,30 +351,41 @@ ngx_quic_create_long_header(ngx_quic_header_t *pkt, ngx_str_t *out,
|
|||||||
ngx_int_t
|
ngx_int_t
|
||||||
ngx_quic_parse_short_header(ngx_quic_header_t *pkt, ngx_str_t *dcid)
|
ngx_quic_parse_short_header(ngx_quic_header_t *pkt, ngx_str_t *dcid)
|
||||||
{
|
{
|
||||||
u_char *p;
|
u_char *p, *end;
|
||||||
|
|
||||||
p = pkt->data;
|
p = pkt->data;
|
||||||
|
end = pkt->data + pkt->len;
|
||||||
|
|
||||||
ngx_quic_hexdump0(pkt->log, "short input", pkt->data, pkt->len);
|
ngx_quic_hexdump0(pkt->log, "short input", pkt->data, pkt->len);
|
||||||
|
|
||||||
if ((p[0] & NGX_QUIC_PKT_LONG)) {
|
p = ngx_quic_read_uint8(p, end, &pkt->flags);
|
||||||
ngx_log_error(NGX_LOG_INFO, pkt->log, 0, "not a short packet");
|
if (p == NULL) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0,
|
||||||
|
"packet is too short to read flags");
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
pkt->flags = *p++;
|
if (pkt->flags & NGX_QUIC_PKT_LONG) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0, "not a short packet");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, pkt->log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, pkt->log, 0,
|
||||||
"quic flags:%xi", pkt->flags);
|
"quic flags:%xi", pkt->flags);
|
||||||
|
|
||||||
if (ngx_memcmp(p, dcid->data, dcid->len) != 0) {
|
if (ngx_memcmp(p, dcid->data, dcid->len) != 0) {
|
||||||
ngx_log_error(NGX_LOG_INFO, pkt->log, 0, "unexpected quic dcid");
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0, "unexpected quic dcid");
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
pkt->dcid.len = dcid->len;
|
pkt->dcid.len = dcid->len;
|
||||||
pkt->dcid.data = p;
|
|
||||||
p += pkt->dcid.len;
|
p = ngx_quic_read_bytes(p, end, dcid->len, &pkt->dcid.data);
|
||||||
|
if (p == NULL) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0,
|
||||||
|
"packet is too short to read dcid");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
pkt->raw->pos = p;
|
pkt->raw->pos = p;
|
||||||
|
|
||||||
@ -248,23 +396,39 @@ ngx_quic_parse_short_header(ngx_quic_header_t *pkt, ngx_str_t *dcid)
|
|||||||
ngx_int_t
|
ngx_int_t
|
||||||
ngx_quic_parse_initial_header(ngx_quic_header_t *pkt)
|
ngx_quic_parse_initial_header(ngx_quic_header_t *pkt)
|
||||||
{
|
{
|
||||||
u_char *p;
|
u_char *p, *end;
|
||||||
ngx_int_t plen;
|
uint64_t plen;
|
||||||
|
|
||||||
p = pkt->raw->pos;
|
p = pkt->raw->pos;
|
||||||
|
|
||||||
pkt->token.len = ngx_quic_parse_int(&p);
|
end = pkt->raw->last;
|
||||||
pkt->token.data = p;
|
|
||||||
|
|
||||||
p += pkt->token.len;
|
pkt->log->action = "parsing quic initial header";
|
||||||
|
|
||||||
plen = ngx_quic_parse_int(&p);
|
p = ngx_quic_parse_int(p, end, &pkt->token.len);
|
||||||
|
if (p == NULL) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0, "failed to parse token length");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = ngx_quic_read_bytes(p, end, pkt->token.len, &pkt->token.data);
|
||||||
|
if (p == NULL) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0,
|
||||||
|
"packet too short to read token data");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = ngx_quic_parse_int(p, end, &plen);
|
||||||
|
if (p == NULL) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0, "bad packet length");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, pkt->log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, pkt->log, 0,
|
||||||
"quic packet length: %d", plen);
|
"quic packet length: %d", plen);
|
||||||
|
|
||||||
if (plen > pkt->data + pkt->len - p) {
|
if (plen > (uint64_t) ((pkt->data + pkt->len) - p)) {
|
||||||
ngx_log_error(NGX_LOG_INFO, pkt->log, 0, "truncated initial packet");
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0, "truncated initial packet");
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -275,9 +439,6 @@ ngx_quic_parse_initial_header(ngx_quic_header_t *pkt)
|
|||||||
ngx_quic_hexdump0(pkt->log, "SCID", pkt->scid.data, pkt->scid.len);
|
ngx_quic_hexdump0(pkt->log, "SCID", pkt->scid.data, pkt->scid.len);
|
||||||
ngx_quic_hexdump0(pkt->log, "token", pkt->token.data, pkt->token.len);
|
ngx_quic_hexdump0(pkt->log, "token", pkt->token.data, pkt->token.len);
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, pkt->log, 0,
|
|
||||||
"quic packet length: %d", plen);
|
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,27 +446,31 @@ ngx_quic_parse_initial_header(ngx_quic_header_t *pkt)
|
|||||||
ngx_int_t
|
ngx_int_t
|
||||||
ngx_quic_parse_handshake_header(ngx_quic_header_t *pkt)
|
ngx_quic_parse_handshake_header(ngx_quic_header_t *pkt)
|
||||||
{
|
{
|
||||||
u_char *p;
|
u_char *p, *end;
|
||||||
ngx_int_t plen;
|
uint64_t plen;
|
||||||
|
|
||||||
p = pkt->raw->pos;
|
p = pkt->raw->pos;
|
||||||
|
end = pkt->raw->last;
|
||||||
|
|
||||||
plen = ngx_quic_parse_int(&p);
|
pkt->log->action = "parsing quic handshake header";
|
||||||
|
|
||||||
|
p = ngx_quic_parse_int(p, end, &plen);
|
||||||
|
if (p == NULL) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0, "bad packet length");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, pkt->log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, pkt->log, 0,
|
||||||
"quic packet length: %d", plen);
|
"quic packet length: %d", plen);
|
||||||
|
|
||||||
if (plen > pkt->data + pkt->len - p) {
|
if (plen > (uint64_t)((pkt->data + pkt->len) - p)) {
|
||||||
ngx_log_error(NGX_LOG_INFO, pkt->log, 0, "truncated handshake packet");
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0, "truncated handshake packet");
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
pkt->raw->pos = p;
|
pkt->raw->pos = p;
|
||||||
pkt->len = plen;
|
pkt->len = plen;
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, pkt->log, 0,
|
|
||||||
"quic packet length: %d", plen);
|
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,30 +480,59 @@ ngx_quic_parse_handshake_header(ngx_quic_header_t *pkt)
|
|||||||
#define ngx_quic_stream_bit_fin(val) (((val) & 0x01) ? 1 : 0)
|
#define ngx_quic_stream_bit_fin(val) (((val) & 0x01) ? 1 : 0)
|
||||||
|
|
||||||
ssize_t
|
ssize_t
|
||||||
ngx_quic_parse_frame(u_char *start, u_char *end, ngx_quic_frame_t *frame)
|
ngx_quic_parse_frame(ngx_quic_header_t *pkt, u_char *start, u_char *end,
|
||||||
|
ngx_quic_frame_t *f)
|
||||||
{
|
{
|
||||||
u_char *p;
|
u_char *p;
|
||||||
|
|
||||||
size_t npad;
|
|
||||||
|
|
||||||
p = start;
|
p = start;
|
||||||
|
|
||||||
frame->type = *p++; // TODO: check overflow (p < end)
|
/* TODO: add a check if frame is allowed in this type of packet */
|
||||||
|
|
||||||
switch (frame->type) {
|
p = ngx_quic_parse_int(p, end, &f->type);
|
||||||
|
if (p == NULL) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0,
|
||||||
|
"failed to obtain quic frame type");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (f->type) {
|
||||||
|
|
||||||
case NGX_QUIC_FT_CRYPTO:
|
case NGX_QUIC_FT_CRYPTO:
|
||||||
frame->u.crypto.offset = *p++;
|
|
||||||
frame->u.crypto.len = ngx_quic_parse_int(&p);
|
|
||||||
frame->u.crypto.data = p;
|
|
||||||
p += frame->u.crypto.len;
|
|
||||||
|
|
||||||
|
p = ngx_quic_parse_int(p, end, &f->u.crypto.offset);
|
||||||
|
if (p == NULL) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0,
|
||||||
|
"failed to parse crypto frame offset");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = ngx_quic_parse_int(p, end, &f->u.crypto.len);
|
||||||
|
if (p == NULL) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0,
|
||||||
|
"failed to parse crypto frame len");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = ngx_quic_read_bytes(p, end, f->u.crypto.len, &f->u.crypto.data);
|
||||||
|
if (p == NULL) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0,
|
||||||
|
"failed to parse crypto frame data");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, pkt->log, 0,
|
||||||
|
"quic CRYPTO frame length: %uL off:%uL pp:%p",
|
||||||
|
f->u.crypto.len, f->u.crypto.offset,
|
||||||
|
f->u.crypto.data);
|
||||||
|
|
||||||
|
ngx_quic_hexdump0(pkt->log, "CRYPTO frame contents",
|
||||||
|
f->u.crypto.data, f->u.crypto.len);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NGX_QUIC_FT_PADDING:
|
case NGX_QUIC_FT_PADDING:
|
||||||
npad = 0;
|
while (p < end && *p == NGX_QUIC_FT_PADDING) {
|
||||||
while (p < end && *p == NGX_QUIC_FT_PADDING) { // XXX
|
p++;
|
||||||
p++; npad++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -346,19 +540,38 @@ ngx_quic_parse_frame(u_char *start, u_char *end, ngx_quic_frame_t *frame)
|
|||||||
case NGX_QUIC_FT_ACK:
|
case NGX_QUIC_FT_ACK:
|
||||||
case NGX_QUIC_FT_ACK_ECN:
|
case NGX_QUIC_FT_ACK_ECN:
|
||||||
|
|
||||||
frame->u.ack.largest = ngx_quic_parse_int(&p);
|
p = ngx_quic_parse_int_multi(p, end, &f->u.ack.largest,
|
||||||
frame->u.ack.delay = ngx_quic_parse_int(&p);
|
&f->u.ack.delay, &f->u.ack.range_count,
|
||||||
frame->u.ack.range_count =ngx_quic_parse_int(&p);
|
&f->u.ack.first_range, NULL);
|
||||||
frame->u.ack.first_range =ngx_quic_parse_int(&p);
|
if (p == NULL) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0,
|
||||||
if (frame->u.ack.range_count) {
|
"failed to parse ack frame");
|
||||||
frame->u.ack.ranges[0] = ngx_quic_parse_int(&p);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (frame->type ==NGX_QUIC_FT_ACK_ECN) {
|
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (f->u.ack.range_count) {
|
||||||
|
p = ngx_quic_parse_int(p, end, &f->u.ack.ranges[0]);
|
||||||
|
if (p == NULL) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0,
|
||||||
|
"failed to parse ack frame first range");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (f->type == NGX_QUIC_FT_ACK_ECN) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0,
|
||||||
|
"TODO: parse ECN ack frames");
|
||||||
|
/* TODO: add parsing of such frames */
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug4(NGX_LOG_DEBUG_EVENT, pkt->log, 0,
|
||||||
|
"ACK: { largest=%ui delay=%ui first=%ui count=%ui}",
|
||||||
|
f->u.ack.largest,
|
||||||
|
f->u.ack.delay,
|
||||||
|
f->u.ack.first_range,
|
||||||
|
f->u.ack.range_count);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NGX_QUIC_FT_PING:
|
case NGX_QUIC_FT_PING:
|
||||||
@ -366,28 +579,72 @@ ngx_quic_parse_frame(u_char *start, u_char *end, ngx_quic_frame_t *frame)
|
|||||||
|
|
||||||
case NGX_QUIC_FT_NEW_CONNECTION_ID:
|
case NGX_QUIC_FT_NEW_CONNECTION_ID:
|
||||||
|
|
||||||
frame->u.ncid.seqnum = ngx_quic_parse_int(&p);
|
p = ngx_quic_parse_int_multi(p, end, &f->u.ncid.seqnum,
|
||||||
frame->u.ncid.retire = ngx_quic_parse_int(&p);
|
&f->u.ncid.retire, NULL);
|
||||||
frame->u.ncid.len = *p++;
|
if (p == NULL) {
|
||||||
ngx_memcpy(frame->u.ncid.cid, p, frame->u.ncid.len);
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0,
|
||||||
p += frame->u.ncid.len;
|
"failed to parse new connection id frame");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
ngx_memcpy(frame->u.ncid.srt, p, 16);
|
p = ngx_quic_read_uint8(p, end, &f->u.ncid.len);
|
||||||
p += 16;
|
if (p == NULL) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0,
|
||||||
|
"failed to parse new connection id length");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = ngx_quic_copy_bytes(p, end, f->u.ncid.len, f->u.ncid.cid);
|
||||||
|
if (p == NULL) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0,
|
||||||
|
"failed to parse new connection id cid");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = ngx_quic_copy_bytes(p, end, 16, f->u.ncid.srt);
|
||||||
|
if (p == NULL) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0,
|
||||||
|
"failed to parse new connection id srt");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, pkt->log, 0,
|
||||||
|
"NCID: { seq=%ui retire=%ui len=%ui}",
|
||||||
|
f->u.ncid.seqnum, f->u.ncid.retire, f->u.ncid.len);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NGX_QUIC_FT_CONNECTION_CLOSE:
|
case NGX_QUIC_FT_CONNECTION_CLOSE:
|
||||||
|
|
||||||
frame->u.close.error_code = ngx_quic_parse_int(&p);
|
p = ngx_quic_parse_int_multi(p, end, &f->u.close.error_code,
|
||||||
frame->u.close.frame_type = ngx_quic_parse_int(&p); // not in 0x1d CC
|
&f->u.close.frame_type,
|
||||||
frame->u.close.reason.len = ngx_quic_parse_int(&p);
|
&f->u.close.reason.len, NULL);
|
||||||
frame->u.close.reason.data = p;
|
if (p == NULL) {
|
||||||
p += frame->u.close.reason.len;
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0,
|
||||||
|
"failed to parse close connection frame");
|
||||||
if (frame->u.close.error_code > NGX_QUIC_ERR_LAST) {
|
return NGX_ERROR;
|
||||||
frame->u.close.error_code = NGX_QUIC_ERR_LAST;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p = ngx_quic_read_bytes(p, end, f->u.close.reason.len,
|
||||||
|
&f->u.close.reason.data);
|
||||||
|
if (p == NULL) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0,
|
||||||
|
"failed to parse close reason");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (f->u.close.error_code > NGX_QUIC_ERR_LAST) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0,
|
||||||
|
"unkown error code: %ui, truncated",
|
||||||
|
f->u.close.error_code);
|
||||||
|
f->u.close.error_code = NGX_QUIC_ERR_LAST;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug4(NGX_LOG_DEBUG_EVENT, pkt->log, 0,
|
||||||
|
"CONN.CLOSE: { %s (0x%xi) type=0x%xi reason='%V'}",
|
||||||
|
ngx_quic_error_text(f->u.close.error_code),
|
||||||
|
f->u.close.error_code, f->u.close.frame_type,
|
||||||
|
&f->u.close.reason);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NGX_QUIC_FT_STREAM0:
|
case NGX_QUIC_FT_STREAM0:
|
||||||
@ -399,57 +656,134 @@ ngx_quic_parse_frame(u_char *start, u_char *end, ngx_quic_frame_t *frame)
|
|||||||
case NGX_QUIC_FT_STREAM6:
|
case NGX_QUIC_FT_STREAM6:
|
||||||
case NGX_QUIC_FT_STREAM7:
|
case NGX_QUIC_FT_STREAM7:
|
||||||
|
|
||||||
frame->u.stream.type = frame->type;
|
f->u.stream.type = f->type;
|
||||||
|
|
||||||
frame->u.stream.off = ngx_quic_stream_bit_off(frame->type);
|
f->u.stream.off = ngx_quic_stream_bit_off(f->type);
|
||||||
frame->u.stream.len = ngx_quic_stream_bit_len(frame->type);
|
f->u.stream.len = ngx_quic_stream_bit_len(f->type);
|
||||||
frame->u.stream.fin = ngx_quic_stream_bit_fin(frame->type);
|
f->u.stream.fin = ngx_quic_stream_bit_fin(f->type);
|
||||||
|
|
||||||
frame->u.stream.stream_id = ngx_quic_parse_int(&p);
|
p = ngx_quic_parse_int(p, end, &f->u.stream.stream_id);
|
||||||
if (frame->type & 0x04) {
|
if (p == NULL) {
|
||||||
frame->u.stream.offset = ngx_quic_parse_int(&p);
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0,
|
||||||
} else {
|
"failed to parse stream frame id");
|
||||||
frame->u.stream.offset = 0;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frame->type & 0x02) {
|
if (f->type & 0x04) {
|
||||||
frame->u.stream.length = ngx_quic_parse_int(&p);
|
p = ngx_quic_parse_int(p, end, &f->u.stream.offset);
|
||||||
} else {
|
if (p == NULL) {
|
||||||
frame->u.stream.length = end - p; /* up to packet end */
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0,
|
||||||
|
"failed to parse stream frame offset");
|
||||||
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
frame->u.stream.data = p;
|
} else {
|
||||||
|
f->u.stream.offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
p += frame->u.stream.length;
|
if (f->type & 0x02) {
|
||||||
|
p = ngx_quic_parse_int(p, end, &f->u.stream.length);
|
||||||
|
if (p == NULL) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0,
|
||||||
|
"failed to parse stream frame length");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
f->u.stream.length = end - p; /* up to packet end */
|
||||||
|
}
|
||||||
|
|
||||||
|
p = ngx_quic_read_bytes(p, end, f->u.stream.length,
|
||||||
|
&f->u.stream.data);
|
||||||
|
if (p == NULL) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0,
|
||||||
|
"failed to parse stream frame data");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug7(NGX_LOG_DEBUG_EVENT, pkt->log, 0,
|
||||||
|
"STREAM frame { 0x%xi id 0x%xi offset 0x%xi "
|
||||||
|
"len 0x%xi bits:off=%d len=%d fin=%d }",
|
||||||
|
f->type, f->u.stream.stream_id, f->u.stream.offset,
|
||||||
|
f->u.stream.length, f->u.stream.off, f->u.stream.len,
|
||||||
|
f->u.stream.fin);
|
||||||
|
|
||||||
|
ngx_quic_hexdump0(pkt->log, "STREAM frame contents",
|
||||||
|
f->u.stream.data, f->u.stream.length);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NGX_QUIC_FT_MAX_DATA:
|
case NGX_QUIC_FT_MAX_DATA:
|
||||||
frame->u.max_data.max_data = ngx_quic_parse_int(&p);
|
|
||||||
|
p = ngx_quic_parse_int(p, end, &f->u.max_data.max_data);
|
||||||
|
if (p == NULL) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0,
|
||||||
|
"failed to parse max data frame");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, pkt->log, 0,
|
||||||
|
"MAX_DATA frame { Maximum Data %ui }",
|
||||||
|
f->u.max_data.max_data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NGX_QUIC_FT_RESET_STREAM:
|
case NGX_QUIC_FT_RESET_STREAM:
|
||||||
frame->u.reset_stream.id = ngx_quic_parse_int(&p);
|
|
||||||
frame->u.reset_stream.error_code = ngx_quic_parse_int(&p);
|
p = ngx_quic_parse_int_multi(p, end, &f->u.reset_stream.id,
|
||||||
frame->u.reset_stream.final_size = ngx_quic_parse_int(&p);
|
&f->u.reset_stream.error_code,
|
||||||
|
&f->u.reset_stream.final_size, NULL);
|
||||||
|
if (p == NULL) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0,
|
||||||
|
"failed to parse reset stream frame");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, pkt->log, 0,
|
||||||
|
"RESET STREAM frame"
|
||||||
|
" { id 0x%xi error_code 0x%xi final_size 0x%xi }",
|
||||||
|
f->u.reset_stream.id, f->u.reset_stream.error_code,
|
||||||
|
f->u.reset_stream.final_size);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NGX_QUIC_FT_STOP_SENDING:
|
case NGX_QUIC_FT_STOP_SENDING:
|
||||||
frame->u.stop_sending.id = ngx_quic_parse_int(&p);
|
|
||||||
frame->u.stop_sending.error_code = ngx_quic_parse_int(&p);
|
p = ngx_quic_parse_int_multi(p, end, &f->u.stop_sending.id,
|
||||||
|
&f->u.stop_sending.error_code, NULL);
|
||||||
|
if (p == NULL) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0,
|
||||||
|
"failed to parse stop sending frame");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, pkt->log, 0,
|
||||||
|
"STOP SENDING frame { id 0x%xi error_code 0x%xi}",
|
||||||
|
f->u.stop_sending.id, f->u.stop_sending.error_code);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NGX_QUIC_FT_STREAMS_BLOCKED:
|
case NGX_QUIC_FT_STREAMS_BLOCKED:
|
||||||
frame->u.streams_blocked.limit = ngx_quic_parse_int(&p);
|
|
||||||
frame->u.streams_blocked.bidi = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NGX_QUIC_FT_STREAMS_BLOCKED2:
|
case NGX_QUIC_FT_STREAMS_BLOCKED2:
|
||||||
frame->u.streams_blocked.limit = ngx_quic_parse_int(&p);
|
|
||||||
frame->u.streams_blocked.bidi = 0;
|
p = ngx_quic_parse_int(p, end, &f->u.streams_blocked.limit);
|
||||||
|
if (p == NULL) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0,
|
||||||
|
"failed to parse streams blocked frame limit");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
f->u.streams_blocked.bidi =
|
||||||
|
(f->type == NGX_QUIC_FT_STREAMS_BLOCKED) ? 1 : 0;
|
||||||
|
|
||||||
|
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, pkt->log, 0,
|
||||||
|
"STREAMS BLOCKED frame { limit %i bidi: %d }",
|
||||||
|
f->u.streams_blocked.limit,
|
||||||
|
f->u.streams_blocked.bidi);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
ngx_log_error(NGX_LOG_ERR, pkt->log, 0,
|
||||||
|
"unsupported frame type 0x%xd in packet", f->type);
|
||||||
|
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,8 +82,8 @@ typedef struct {
|
|||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
size_t offset;
|
uint64_t offset;
|
||||||
size_t len;
|
uint64_t len;
|
||||||
u_char *data;
|
u_char *data;
|
||||||
} ngx_quic_crypto_frame_t;
|
} ngx_quic_crypto_frame_t;
|
||||||
|
|
||||||
@ -91,7 +91,7 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
uint64_t seqnum;
|
uint64_t seqnum;
|
||||||
uint64_t retire;
|
uint64_t retire;
|
||||||
uint64_t len;
|
uint8_t len;
|
||||||
u_char cid[20];
|
u_char cid[20];
|
||||||
u_char srt[16];
|
u_char srt[16];
|
||||||
} ngx_quic_new_conn_id_frame_t;
|
} ngx_quic_new_conn_id_frame_t;
|
||||||
@ -167,7 +167,7 @@ typedef struct {
|
|||||||
struct ngx_quic_secret_s *secret;
|
struct ngx_quic_secret_s *secret;
|
||||||
ngx_uint_t type;
|
ngx_uint_t type;
|
||||||
ngx_uint_t *number;
|
ngx_uint_t *number;
|
||||||
ngx_uint_t flags;
|
uint8_t flags;
|
||||||
uint32_t version;
|
uint32_t version;
|
||||||
ngx_str_t token;
|
ngx_str_t token;
|
||||||
enum ssl_encryption_level_t level;
|
enum ssl_encryption_level_t level;
|
||||||
@ -197,7 +197,7 @@ ngx_int_t ngx_quic_parse_short_header(ngx_quic_header_t *pkt,
|
|||||||
ngx_int_t ngx_quic_parse_initial_header(ngx_quic_header_t *pkt);
|
ngx_int_t ngx_quic_parse_initial_header(ngx_quic_header_t *pkt);
|
||||||
ngx_int_t ngx_quic_parse_handshake_header(ngx_quic_header_t *pkt);
|
ngx_int_t ngx_quic_parse_handshake_header(ngx_quic_header_t *pkt);
|
||||||
|
|
||||||
ssize_t ngx_quic_parse_frame(u_char *start, u_char *end,
|
ssize_t ngx_quic_parse_frame(ngx_quic_header_t *pkt, u_char *start, u_char *end,
|
||||||
ngx_quic_frame_t *frame);
|
ngx_quic_frame_t *frame);
|
||||||
ssize_t ngx_quic_create_frame(u_char *p, u_char *end, ngx_quic_frame_t *f);
|
ssize_t ngx_quic_create_frame(u_char *p, u_char *end, ngx_quic_frame_t *f);
|
||||||
size_t ngx_quic_frame_len(ngx_quic_frame_t *frame);
|
size_t ngx_quic_frame_len(ngx_quic_frame_t *frame);
|
||||||
|
Loading…
Reference in New Issue
Block a user