Packages
hackney
3.0.1
4.7.2
4.7.1
4.7.0
4.6.1
4.6.0
4.5.2
4.5.1
4.5.0
4.4.5
4.4.3
4.4.2
4.4.1
4.4.0
4.3.0
4.2.3
4.2.2
4.2.1
4.2.0
4.1.0
4.0.3
4.0.2
4.0.1
4.0.0
3.2.1
3.2.0
3.1.2
3.1.1
3.1.0
3.0.3
3.0.2
3.0.1
3.0.0
retired
2.0.1
2.0.0
2.0.0-beta.1
1.25.0
1.24.1
1.24.0
1.23.0
1.22.0
1.21.0
1.20.1
1.20.0
1.19.1
1.19.0
1.18.2
1.18.1
1.18.0
1.17.4
1.17.3
1.17.2
1.17.1
1.17.0
1.16.0
1.15.2
1.15.1
1.15.0
1.14.3
1.14.2
1.14.0
1.13.0
1.12.1
1.12.0
1.11.0
1.10.1
1.10.0
1.9.0
1.8.6
1.8.5
1.8.4
1.8.3
1.8.2
1.8.0
1.7.1
1.7.0
1.6.6
retired
1.6.5
1.6.4
retired
1.6.3
1.6.2
1.6.1
1.6.0
1.5.7
1.5.6
1.5.5
1.5.4
1.5.3
1.5.2
1.5.1
1.5.0
1.4.10
1.4.8
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.2
1.3.1
1.3.0
1.2.0
1.1.0
1.0.6
1.0.5
1.0.2
1.0.1
0.15.2
0.15.0
0.14.3
0.14.2
0.14.1
0.14.0
0.13.1
Simple HTTP client with HTTP/1.1, HTTP/2, and HTTP/3 support
Security advisory:
This version has known vulnerabilities.
View advisories
Current section
Files
Jump to
Current section
Files
c_src/lsquic/src/liblsquic/lsquic_parse_Q046.c
/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc. See LICENSE. */
/*
* lsquic_parse_Q046.c -- Parsing functions specific to GQUIC Q046
*/
#include <assert.h>
#include <errno.h>
#include <inttypes.h>
#include <string.h>
#include <sys/queue.h>
#ifndef WIN32
#include <sys/types.h>
#else
#include <vc_compat.h>
#endif
#include "lsquic_types.h"
#include "lsquic_int_types.h"
#include "lsquic_packet_common.h"
#include "lsquic_packet_in.h"
#include "lsquic_packet_out.h"
#include "lsquic_parse.h"
#include "lsquic_parse_common.h"
#include "lsquic_version.h"
#include "lsquic.h"
#include "lsquic_parse_gquic_be.h"
#include "lsquic_byteswap.h"
#include "lsquic_hash.h"
#include "lsquic_conn.h"
#define LSQUIC_LOGGER_MODULE LSQLM_PARSE
#include "lsquic_logger.h"
static unsigned
gquic_Q046_packno_bits2len (enum packno_bits bits)
{
return bits + 1;
}
#define iquic_packno_bits2len gquic_Q046_packno_bits2len
static enum packno_bits
gquic_Q046_calc_packno_bits (lsquic_packno_t packno,
lsquic_packno_t least_unacked, uint64_t n_in_flight)
{
uint64_t delta;
unsigned bits;
delta = packno - least_unacked;
if (n_in_flight > delta)
delta = n_in_flight;
delta *= 4;
bits = (delta >= (1ULL << 8))
+ (delta >= (1ULL << 16))
+ (delta >= (1ULL << 24))
;
return bits;
}
static unsigned
write_packno (unsigned char *p, lsquic_packno_t packno, enum packno_bits bits)
{
unsigned char *const begin = p;
switch (bits)
{
case IQUIC_PACKNO_LEN_4:
*p++ = packno >> 24;
/* fall-through */
case IQUIC_PACKNO_LEN_3:
*p++ = packno >> 16;
/* fall-through */
case IQUIC_PACKNO_LEN_2:
*p++ = packno >> 8;
/* fall-through */
default:
*p++ = packno;
}
return p - begin;
}
static int
gen_short_pkt_header (const struct lsquic_conn *lconn,
const struct lsquic_packet_out *packet_out, unsigned char *buf,
size_t bufsz)
{
unsigned packno_len, need;
enum packno_bits bits;
bits = lsquic_packet_out_packno_bits(packet_out);
packno_len = iquic_packno_bits2len(bits);
if (lconn->cn_flags & LSCONN_SERVER)
need = 1 + packno_len;
else
need = 1 + 8 /* CID */ + packno_len;
if (need > bufsz)
return -1;
*buf++ = 0x40 | bits;
if (0 == (lconn->cn_flags & LSCONN_SERVER))
{
memcpy(buf, lconn->cn_cid.idbuf, 8);
buf += 8;
}
(void) write_packno(buf, packet_out->po_packno, bits);
return need;
}
static size_t
gquic_Q046_packout_header_size_long (const struct lsquic_conn *lconn,
enum packet_out_flags flags)
{
if ((lconn->cn_flags & LSCONN_SERVER) && (flags & PO_NONCE))
return GQUIC_IETF_LONG_HEADER_SIZE + 32;
return GQUIC_IETF_LONG_HEADER_SIZE;
}
/* [draft-ietf-quic-transport-17] Section-17.2 */
static const unsigned char header_type_to_bin[] = {
[HETY_INITIAL] = 0x0,
[HETY_0RTT] = 0x1,
[HETY_HANDSHAKE] = 0x2,
[HETY_RETRY] = 0x3,
};
static int
gen_long_pkt_header (const struct lsquic_conn *lconn,
const struct lsquic_packet_out *packet_out, unsigned char *buf,
size_t bufsz)
{
enum packno_bits packno_bits;
lsquic_ver_tag_t ver_tag;
unsigned char *p;
size_t need;
need = gquic_Q046_packout_header_size_long(lconn, packet_out->po_flags);
if (need > bufsz)
{
errno = EINVAL;
return -1;
}
p = buf;
packno_bits = IQUIC_PACKNO_LEN_4;
*p++ = 0x80 | 0x40
| (header_type_to_bin[ packet_out->po_header_type ] << 4)
| packno_bits;
ver_tag = lsquic_ver2tag(lconn->cn_version);
memcpy(p, &ver_tag, sizeof(ver_tag));
p += sizeof(ver_tag);
if (lconn->cn_flags & LSCONN_SERVER)
*p++ = 0x05;
else
*p++ = 0x50;
memcpy(p, lconn->cn_cid.idbuf, 8);
p += 8;
p += write_packno(p, packet_out->po_packno, packno_bits);
if (packet_out->po_nonce)
{
memcpy(p, packet_out->po_nonce, 32);
p += 32;
}
assert(need == (unsigned int)(p - buf));
return p - buf;
}
static int
gquic_Q046_gen_reg_pkt_header (const struct lsquic_conn *lconn,
const struct lsquic_packet_out *packet_out, unsigned char *buf,
size_t bufsz, unsigned *packno_off_UNUSED, unsigned *packno_len_UNUSED)
{
if (0 == (packet_out->po_flags & PO_LONGHEAD))
return gen_short_pkt_header(lconn, packet_out, buf, bufsz);
else
return gen_long_pkt_header(lconn, packet_out, buf, bufsz);
}
static size_t
gquic_Q046_packout_header_size_short (const struct lsquic_conn *lconn,
enum packet_out_flags flags)
{
enum packno_bits bits;
size_t sz;
bits = (flags >> POBIT_SHIFT) & 0x3;
sz = 1; /* Type */
sz += (lconn->cn_flags & LSCONN_SERVER) ? 0 : 8;
sz += iquic_packno_bits2len(bits);
return sz;
}
static size_t
gquic_Q046_packout_header_size (const struct lsquic_conn *lconn,
enum packet_out_flags flags, size_t dcid_len_unused,
enum header_type unused)
{
if (0 == (flags & PO_LONGHEAD))
return gquic_Q046_packout_header_size_short(lconn, flags);
else
return gquic_Q046_packout_header_size_long(lconn, flags);
}
static size_t
gquic_Q046_packout_size (const struct lsquic_conn *lconn,
const struct lsquic_packet_out *packet_out)
{
size_t sz;
if (0 == (packet_out->po_flags & PO_LONGHEAD))
sz = gquic_Q046_packout_header_size_short(lconn, packet_out->po_flags);
else
sz = gquic_Q046_packout_header_size_long(lconn, packet_out->po_flags);
sz += packet_out->po_data_sz;
sz += GQUIC_PACKET_HASH_SZ;
return sz;
}
static void
gquic_Q046_parse_packet_in_finish (struct lsquic_packet_in *packet_in,
struct packin_parse_state *state)
{
lsquic_packno_t packno;
if (packet_in->pi_header_type == HETY_NOT_SET
/* We can't check in the beginning because we don't know whether
* this is Q046 or ID-18. This is a bit hacky.
*/
&& state->pps_p + state->pps_nbytes
<= packet_in->pi_data + packet_in->pi_data_sz)
{
READ_UINT(packno, 64, state->pps_p, state->pps_nbytes);
packet_in->pi_packno = packno;
packet_in->pi_header_sz += state->pps_nbytes;
}
}
static int
gquic_Q046_gen_crypto_frame (unsigned char *buf, size_t buf_len,
lsquic_stream_id_t stream_id, uint64_t offset, int fin, size_t size,
gsf_read_f gsf_read, void *stream)
{
assert(0);
return -1;
}
static int
gquic_Q046_parse_crypto_frame (const unsigned char *buf, size_t rem_packet_sz,
struct stream_frame *stream_frame)
{
assert(0);
return -1;
}
/* No simple PRST for Q046 */
static ssize_t
gquic_Q046_generate_simple_prst (const lsquic_cid_t *cidp, unsigned char *buf,
size_t buf_sz)
{
return -1;
}
static unsigned
gquic_Q046_handshake_done_frame_size (void)
{
return 0;
}
static int
gquic_Q046_gen_handshake_done_frame (unsigned char *buf, size_t buf_len)
{
return -1;
}
static int
gquic_Q046_parse_handshake_done_frame (const unsigned char *buf, size_t buf_len)
{
return -1;
}
const struct parse_funcs lsquic_parse_funcs_gquic_Q046 =
{
.pf_gen_reg_pkt_header = gquic_Q046_gen_reg_pkt_header,
.pf_parse_packet_in_finish = gquic_Q046_parse_packet_in_finish,
.pf_gen_stream_frame = lsquic_gquic_be_gen_stream_frame,
.pf_calc_stream_frame_header_sz = lsquic_calc_stream_frame_header_sz_gquic,
.pf_parse_stream_frame = lsquic_gquic_be_parse_stream_frame,
.pf_dec_stream_frame_size = lsquic_gquic_be_dec_stream_frame_size,
.pf_parse_ack_frame = lsquic_gquic_be_parse_ack_frame,
.pf_gen_ack_frame = lsquic_gquic_be_gen_ack_frame,
.pf_gen_stop_waiting_frame = lsquic_gquic_be_gen_stop_waiting_frame,
.pf_parse_stop_waiting_frame = lsquic_gquic_be_parse_stop_waiting_frame,
.pf_skip_stop_waiting_frame = lsquic_gquic_be_skip_stop_waiting_frame,
.pf_gen_window_update_frame = lsquic_gquic_be_gen_window_update_frame,
.pf_parse_window_update_frame = lsquic_gquic_be_parse_window_update_frame,
.pf_gen_blocked_frame = lsquic_gquic_be_gen_blocked_frame,
.pf_parse_blocked_frame = lsquic_gquic_be_parse_blocked_frame,
.pf_gen_rst_frame = lsquic_gquic_be_gen_rst_frame,
.pf_parse_rst_frame = lsquic_gquic_be_parse_rst_frame,
.pf_connect_close_frame_size = lsquic_gquic_be_connect_close_frame_size,
.pf_gen_connect_close_frame = lsquic_gquic_be_gen_connect_close_frame,
.pf_parse_connect_close_frame = lsquic_gquic_be_parse_connect_close_frame,
.pf_gen_goaway_frame = lsquic_gquic_be_gen_goaway_frame,
.pf_parse_goaway_frame = lsquic_gquic_be_parse_goaway_frame,
.pf_gen_ping_frame = lsquic_gquic_be_gen_ping_frame,
#ifndef NDEBUG
.pf_write_float_time16 = lsquic_gquic_be_write_float_time16,
.pf_read_float_time16 = lsquic_gquic_be_read_float_time16,
#endif
.pf_generate_simple_prst = gquic_Q046_generate_simple_prst,
.pf_parse_frame_type = lsquic_parse_frame_type_gquic_Q035_thru_Q046,
.pf_turn_on_fin = lsquic_turn_on_fin_Q035_thru_Q046,
.pf_packout_size = gquic_Q046_packout_size,
.pf_packout_max_header_size = gquic_Q046_packout_header_size,
.pf_calc_packno_bits = gquic_Q046_calc_packno_bits,
.pf_packno_bits2len = gquic_Q046_packno_bits2len,
.pf_gen_crypto_frame = gquic_Q046_gen_crypto_frame,
.pf_parse_crypto_frame = gquic_Q046_parse_crypto_frame,
.pf_gen_handshake_done_frame = gquic_Q046_gen_handshake_done_frame,
.pf_parse_handshake_done_frame = gquic_Q046_parse_handshake_done_frame,
.pf_handshake_done_frame_size = gquic_Q046_handshake_done_frame_size,
};