mirror of
https://gitea.invidious.io/iv-org/litespeed-quic.git
synced 2024-08-15 00:53:43 +00:00
1.11.0: [FEATURE] Add support for Q044
This commit is contained in:
parent
c6457e4258
commit
9626cfc25b
34 changed files with 1157 additions and 279 deletions
|
@ -1,3 +1,8 @@
|
|||
2018-08-15
|
||||
|
||||
- 1.11.0
|
||||
- [FEATURE] Add support for Q044.
|
||||
|
||||
2018-08-09
|
||||
|
||||
- 1.10.2
|
||||
|
|
|
@ -13,10 +13,10 @@ our own products: LiteSpeed Web Server and ADC. We think it is free of
|
|||
major problems. Nevertheless, do not hesitate to report bugs back to us.
|
||||
Even better, send us fixes and improvements!
|
||||
|
||||
Currently supported QUIC versions are Q035, Q039, and Q043. Support for
|
||||
newer versions will be added soon after they are released. The version(s)
|
||||
specified by IETF QUIC WG will be added once the IETF version of the
|
||||
protocol settles down a little.
|
||||
Currently supported QUIC versions are Q035, Q039, Q043, and Q044. Support
|
||||
for newer versions will be added soon after they are released. The
|
||||
version(s) specified by IETF QUIC WG will be added once the IETF version
|
||||
of the protocol settles down a little.
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
|
|
@ -24,8 +24,8 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
#define LSQUIC_MAJOR_VERSION 1
|
||||
#define LSQUIC_MINOR_VERSION 10
|
||||
#define LSQUIC_PATCH_VERSION 2
|
||||
#define LSQUIC_MINOR_VERSION 11
|
||||
#define LSQUIC_PATCH_VERSION 0
|
||||
|
||||
/**
|
||||
* Engine flags:
|
||||
|
@ -97,23 +97,45 @@ enum lsquic_version
|
|||
*/
|
||||
LSQVER_043,
|
||||
|
||||
/**
|
||||
* Q044. IETF-like packet headers are used. Frames are the same as
|
||||
* in Q043. Server never includes CIDs in short packets.
|
||||
*/
|
||||
LSQVER_044,
|
||||
|
||||
#if LSQUIC_USE_Q098
|
||||
/**
|
||||
* Q098. This is a made-up, experimental version used to test version
|
||||
* negotiation. The choice of 98 is similar to Google's choice of 99
|
||||
* as the "IETF" version.
|
||||
*/
|
||||
LSQVER_098,
|
||||
#define LSQUIC_EXPERIMENTAL_Q098 (1 << LSQVER_098)
|
||||
#else
|
||||
#define LSQUIC_EXPERIMENTAL_Q098 0
|
||||
#endif
|
||||
|
||||
N_LSQVER
|
||||
};
|
||||
|
||||
/**
|
||||
* We currently support versions 35, 39, and 43.
|
||||
* We currently support versions 35, 39, 43, and 44.
|
||||
* @see lsquic_version
|
||||
*/
|
||||
#define LSQUIC_SUPPORTED_VERSIONS ((1 << N_LSQVER) - 1)
|
||||
|
||||
#define LSQUIC_EXPERIMENTAL_VERSIONS 0
|
||||
#define LSQUIC_EXPERIMENTAL_VERSIONS (0 \
|
||||
| LSQUIC_EXPERIMENTAL_Q098)
|
||||
|
||||
#define LSQUIC_DEPRECATED_VERSIONS 0
|
||||
|
||||
#define LSQUIC_GQUIC_HEADER_VERSIONS ( \
|
||||
(1 << LSQVER_035) | (1 << LSQVER_039) | (1 << LSQVER_043))
|
||||
|
||||
/**
|
||||
* List of version in which the server does not include CID in short packets.
|
||||
* List of versions in which the server never includes CID in short packets.
|
||||
*/
|
||||
#define LSQUIC_FORCED_TCID0_VERSIONS 0
|
||||
#define LSQUIC_FORCED_TCID0_VERSIONS (1 << LSQVER_044)
|
||||
|
||||
/**
|
||||
* @struct lsquic_stream_if
|
||||
|
@ -330,6 +352,9 @@ struct lsquic_engine_settings {
|
|||
* (source-addr, dest-addr) tuple, thereby making it necessary to create
|
||||
* a socket for each connection.
|
||||
*
|
||||
* This option has no effect in Q044, as the server never includes CIDs
|
||||
* in the short packets.
|
||||
*
|
||||
* The default is @ref LSQUIC_DF_SUPPORT_TCID0.
|
||||
*/
|
||||
int es_support_tcid0;
|
||||
|
|
|
@ -6,6 +6,8 @@ SET(lsquic_STAT_SRCS
|
|||
lsquic_chsk_stream.c
|
||||
lsquic_engine.c
|
||||
lsquic_parse_gquic_common.c
|
||||
lsquic_parse_iquic_common.c
|
||||
lsquic_parse_common.c
|
||||
lsquic_parse_gquic_le.c
|
||||
lsquic_parse_gquic_be.c
|
||||
lsquic_packet_in.c
|
||||
|
@ -50,6 +52,7 @@ SET(lsquic_STAT_SRCS
|
|||
lsquic_buf.c
|
||||
lsquic_min_heap.c
|
||||
lshpack.c
|
||||
lsquic_parse_Q044.c
|
||||
)
|
||||
|
||||
|
||||
|
|
23
src/liblsquic/lsquic_byteswap.h
Normal file
23
src/liblsquic/lsquic_byteswap.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
/* Copyright (c) 2017 - 2018 LiteSpeed Technologies Inc. See LICENSE. */
|
||||
#ifndef LSQUIC_BYTESWAP_H
|
||||
#define LSQUIC_BYTESWAP_H 1
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__)
|
||||
#include <sys/endian.h>
|
||||
#define bswap_16 bswap16
|
||||
#define bswap_32 bswap32
|
||||
#define bswap_64 bswap64
|
||||
#elif defined(__APPLE__)
|
||||
#include <libkern/OSByteOrder.h>
|
||||
#define bswap_16 OSSwapInt16
|
||||
#define bswap_32 OSSwapInt32
|
||||
#define bswap_64 OSSwapInt64
|
||||
#elif defined(WIN32)
|
||||
#define bswap_16 _byteswap_ushort
|
||||
#define bswap_32 _byteswap_ulong
|
||||
#define bswap_64 _byteswap_uint64
|
||||
#else
|
||||
#include <byteswap.h>
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -126,8 +126,8 @@ lsquic_conn_decrypt_packet (lsquic_conn_t *lconn,
|
|||
| (enc_level << PIBIT_ENC_LEV_SHIFT);
|
||||
packet_in->pi_header_sz = header_len;
|
||||
packet_in->pi_data_sz = out_len + header_len;
|
||||
EV_LOG_CONN_EVENT(lconn->cn_cid, "decrypted packet %"PRIu64,
|
||||
packet_in->pi_packno);
|
||||
EV_LOG_CONN_EVENT(lconn->cn_cid, "decrypted packet %"PRIu64" crypto: %s",
|
||||
packet_in->pi_packno, lsquic_enclev2str[ enc_level ]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "lsquic.h"
|
||||
#include "lsquic_types.h"
|
||||
#include "lsquic_alarmset.h"
|
||||
#include "lsquic_parse_common.h"
|
||||
#include "lsquic_parse.h"
|
||||
#include "lsquic_packet_in.h"
|
||||
#include "lsquic_packet_out.h"
|
||||
|
@ -261,6 +262,18 @@ static const struct lsquic_packout_mem_if stock_pmi =
|
|||
};
|
||||
|
||||
|
||||
static int
|
||||
hash_conns_by_addr (const struct lsquic_engine *engine)
|
||||
{
|
||||
if (engine->pub.enp_settings.es_versions & LSQUIC_FORCED_TCID0_VERSIONS)
|
||||
return 1;
|
||||
if ((engine->pub.enp_settings.es_versions & LSQUIC_GQUIC_HEADER_VERSIONS)
|
||||
&& engine->pub.enp_settings.es_support_tcid0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
lsquic_engine_t *
|
||||
lsquic_engine_new (unsigned flags,
|
||||
const struct lsquic_engine_api *api)
|
||||
|
@ -295,7 +308,7 @@ lsquic_engine_new (unsigned flags,
|
|||
engine->pub.enp_settings = *api->ea_settings;
|
||||
else
|
||||
lsquic_engine_init_settings(&engine->pub.enp_settings, flags);
|
||||
tag_buf_len = gen_ver_tags(engine->pub.enp_ver_tags_buf,
|
||||
tag_buf_len = lsquic_gen_ver_tags(engine->pub.enp_ver_tags_buf,
|
||||
sizeof(engine->pub.enp_ver_tags_buf),
|
||||
engine->pub.enp_settings.es_versions);
|
||||
if (tag_buf_len <= 0)
|
||||
|
@ -324,8 +337,7 @@ lsquic_engine_new (unsigned flags,
|
|||
}
|
||||
engine->pub.enp_engine = engine;
|
||||
conn_hash_init(&engine->conns_hash,
|
||||
!(flags & ENG_SERVER) && engine->pub.enp_settings.es_support_tcid0 ?
|
||||
CHF_USE_ADDR : 0);
|
||||
hash_conns_by_addr(engine) ? CHF_USE_ADDR : 0);
|
||||
engine->attq = attq_create();
|
||||
eng_hist_init(&engine->history);
|
||||
engine->batch_size = INITIAL_OUT_BATCH_SIZE;
|
||||
|
@ -498,7 +510,7 @@ process_packet_in (lsquic_engine_t *engine, lsquic_packet_in_t *packet_in,
|
|||
{
|
||||
lsquic_conn_t *conn;
|
||||
|
||||
if (lsquic_packet_in_is_prst(packet_in)
|
||||
if (lsquic_packet_in_is_gquic_prst(packet_in)
|
||||
&& !engine->pub.enp_settings.es_honor_prst)
|
||||
{
|
||||
lsquic_mm_put_packet_in(&engine->pub.enp_mm, packet_in);
|
||||
|
@ -758,44 +770,34 @@ lsquic_engine_process_conns (lsquic_engine_t *engine)
|
|||
}
|
||||
|
||||
|
||||
static int
|
||||
generate_header (const lsquic_packet_out_t *packet_out,
|
||||
const struct parse_funcs *pf, lsquic_cid_t cid,
|
||||
unsigned char *buf, size_t bufsz)
|
||||
{
|
||||
return pf->pf_gen_reg_pkt_header(buf, bufsz,
|
||||
packet_out->po_flags & PO_CONN_ID ? &cid : NULL,
|
||||
packet_out->po_flags & PO_VERSION ? &packet_out->po_ver_tag : NULL,
|
||||
packet_out->po_flags & PO_NONCE ? packet_out->po_nonce : NULL,
|
||||
packet_out->po_packno, lsquic_packet_out_packno_bits(packet_out));
|
||||
}
|
||||
|
||||
|
||||
static ssize_t
|
||||
really_encrypt_packet (const lsquic_conn_t *conn,
|
||||
const lsquic_packet_out_t *packet_out,
|
||||
struct lsquic_packet_out *packet_out,
|
||||
unsigned char *buf, size_t bufsz)
|
||||
{
|
||||
int enc, header_sz, is_hello_packet;
|
||||
int header_sz, is_hello_packet;
|
||||
enum enc_level enc_level;
|
||||
size_t packet_sz;
|
||||
unsigned char header_buf[QUIC_MAX_PUBHDR_SZ];
|
||||
|
||||
header_sz = generate_header(packet_out, conn->cn_pf, conn->cn_cid,
|
||||
header_sz = conn->cn_pf->pf_gen_reg_pkt_header(conn, packet_out,
|
||||
header_buf, sizeof(header_buf));
|
||||
if (header_sz < 0)
|
||||
return -1;
|
||||
|
||||
is_hello_packet = !!(packet_out->po_flags & PO_HELLO);
|
||||
enc = conn->cn_esf->esf_encrypt(conn->cn_enc_session, conn->cn_version, 0,
|
||||
enc_level = conn->cn_esf->esf_encrypt(conn->cn_enc_session,
|
||||
conn->cn_version, 0,
|
||||
packet_out->po_packno, header_buf, header_sz,
|
||||
packet_out->po_data, packet_out->po_data_sz,
|
||||
buf, bufsz, &packet_sz, is_hello_packet);
|
||||
if (0 == enc)
|
||||
if ((int) enc_level >= 0)
|
||||
{
|
||||
LSQ_DEBUG("encrypted packet %"PRIu64"; plaintext is %u bytes, "
|
||||
lsquic_packet_out_set_enc_level(packet_out, enc_level);
|
||||
LSQ_DEBUG("encrypted packet %"PRIu64"; plaintext is %zu bytes, "
|
||||
"ciphertext is %zd bytes",
|
||||
packet_out->po_packno,
|
||||
lsquic_po_header_length(packet_out->po_flags) +
|
||||
conn->cn_pf->pf_packout_header_size(conn, packet_out->po_flags) +
|
||||
packet_out->po_data_sz,
|
||||
packet_sz);
|
||||
return packet_sz;
|
||||
|
@ -814,7 +816,7 @@ encrypt_packet (lsquic_engine_t *engine, const lsquic_conn_t *conn,
|
|||
unsigned sent_sz;
|
||||
unsigned char *buf;
|
||||
|
||||
bufsz = lsquic_po_header_length(packet_out->po_flags) +
|
||||
bufsz = conn->cn_pf->pf_packout_header_size(conn, packet_out->po_flags) +
|
||||
packet_out->po_data_sz + QUIC_PACKET_HASH_SZ;
|
||||
buf = engine->pub.enp_pmi->pmi_allocate(engine->pub.enp_pmi_ctx, bufsz);
|
||||
if (!buf)
|
||||
|
@ -1281,6 +1283,8 @@ lsquic_engine_packet_in (lsquic_engine_t *engine,
|
|||
{
|
||||
struct packin_parse_state ppstate;
|
||||
lsquic_packet_in_t *packet_in;
|
||||
int (*parse_packet_in_begin) (struct lsquic_packet_in *, size_t length,
|
||||
int is_server, struct packin_parse_state *);
|
||||
|
||||
if (packet_in_size > QUIC_MAX_PACKET_SZ)
|
||||
{
|
||||
|
@ -1290,6 +1294,20 @@ lsquic_engine_packet_in (lsquic_engine_t *engine,
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (conn_hash_using_addr(&engine->conns_hash))
|
||||
{
|
||||
const struct lsquic_conn *conn;
|
||||
conn = conn_hash_find_by_addr(&engine->conns_hash, sa_local);
|
||||
if (!conn)
|
||||
return -1;
|
||||
if ((1 << conn->cn_version) & LSQUIC_GQUIC_HEADER_VERSIONS)
|
||||
parse_packet_in_begin = lsquic_gquic_parse_packet_in_begin;
|
||||
else
|
||||
parse_packet_in_begin = lsquic_iquic_parse_packet_in_begin;
|
||||
}
|
||||
else
|
||||
parse_packet_in_begin = lsquic_parse_packet_in_begin;
|
||||
|
||||
packet_in = lsquic_mm_get_packet_in(&engine->pub.enp_mm);
|
||||
if (!packet_in)
|
||||
return -1;
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#include "lsquic_parse.h"
|
||||
#include "lsquic_frame_common.h"
|
||||
#include "lsquic_frame_reader.h"
|
||||
#include "lsquic_str.h"
|
||||
#include "lsquic_handshake.h"
|
||||
#include "lsquic_ev_log.h"
|
||||
|
||||
#define LSQUIC_LOGGER_MODULE LSQLM_EVENT
|
||||
|
@ -39,7 +41,17 @@
|
|||
void
|
||||
lsquic_ev_log_packet_in (lsquic_cid_t cid, const lsquic_packet_in_t *packet_in)
|
||||
{
|
||||
LCID("packet in: %"PRIu64, packet_in->pi_packno);
|
||||
switch (packet_in->pi_flags & (
|
||||
PI_GQUIC))
|
||||
{
|
||||
case PI_GQUIC:
|
||||
LCID("packet in: %"PRIu64, packet_in->pi_packno);
|
||||
break;
|
||||
default:
|
||||
LCID("packet in: %"PRIu64", type: %s",
|
||||
packet_in->pi_packno, lsquic_hety2str[packet_in->pi_header_type]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -153,7 +165,7 @@ lsquic_ev_log_packet_sent (lsquic_cid_t cid,
|
|||
packet_out->po_data_sz);
|
||||
else if (lsquic_packet_out_pubres(packet_out))
|
||||
LCID("sent public reset packet, size %hu", packet_out->po_data_sz);
|
||||
else
|
||||
else if (packet_out->po_flags & PO_GQUIC)
|
||||
LCID("sent packet %"PRIu64", size %hu, frame types: %s",
|
||||
packet_out->po_packno, packet_out->po_enc_data_sz,
|
||||
/* Frame types is a list of different frames types contained
|
||||
|
@ -162,6 +174,18 @@ lsquic_ev_log_packet_sent (lsquic_cid_t cid,
|
|||
*/
|
||||
lsquic_frame_types_to_str(frames, sizeof(frames),
|
||||
packet_out->po_frame_types));
|
||||
else
|
||||
LCID("sent packet %"PRIu64", type %s, crypto: %s, size %hu, frame "
|
||||
"types: %s",
|
||||
packet_out->po_packno, lsquic_hety2str[packet_out->po_header_type],
|
||||
lsquic_enclev2str[ lsquic_packet_out_enc_level(packet_out) ],
|
||||
packet_out->po_enc_data_sz,
|
||||
/* Frame types is a list of different frames types contained
|
||||
* in the packet, no more. Count and order of frames is not
|
||||
* printed.
|
||||
*/
|
||||
lsquic_frame_types_to_str(frames, sizeof(frames),
|
||||
packet_out->po_frame_types));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -383,6 +383,7 @@ set_versions (struct full_conn *conn, unsigned versions)
|
|||
conn->fc_ver_neg.vn_ver = highest_bit_set(versions);
|
||||
conn->fc_ver_neg.vn_buf = lsquic_ver2tag(conn->fc_ver_neg.vn_ver);
|
||||
conn->fc_conn.cn_version = conn->fc_ver_neg.vn_ver;
|
||||
conn->fc_conn.cn_pf = select_pf_by_ver(conn->fc_ver_neg.vn_ver);
|
||||
LSQ_DEBUG("negotiating version %s",
|
||||
lsquic_ver2str[conn->fc_ver_neg.vn_ver]);
|
||||
}
|
||||
|
@ -675,7 +676,6 @@ full_conn_client_new (struct lsquic_engine_public *enpub,
|
|||
.stream_if = &lsquic_client_hsk_stream_if;
|
||||
conn->fc_stream_ifs[STREAM_IF_HSK].stream_if_ctx = &conn->fc_hsk_ctx.client;
|
||||
init_ver_neg(conn, conn->fc_settings->es_versions);
|
||||
conn->fc_conn.cn_pf = select_pf_by_ver(conn->fc_ver_neg.vn_ver);
|
||||
if (conn->fc_settings->es_handshake_to)
|
||||
lsquic_alarmset_set(&conn->fc_alset, AL_HANDSHAKE,
|
||||
lsquic_time_now() + conn->fc_settings->es_handshake_to);
|
||||
|
@ -1872,6 +1872,18 @@ parse_regular_packet (struct full_conn *conn, lsquic_packet_in_t *packet_in)
|
|||
}
|
||||
|
||||
|
||||
static int
|
||||
conn_is_stateless_reset (const struct full_conn *conn,
|
||||
const struct lsquic_packet_in *packet_in)
|
||||
{
|
||||
return packet_in->pi_data_sz > SRST_LENGTH
|
||||
&& 0 == conn->fc_conn.cn_esf->esf_verify_reset_token(
|
||||
conn->fc_conn.cn_enc_session,
|
||||
packet_in->pi_data + packet_in->pi_data_sz - SRST_LENGTH,
|
||||
SRST_LENGTH);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
process_regular_packet (struct full_conn *conn, lsquic_packet_in_t *packet_in)
|
||||
{
|
||||
|
@ -1893,11 +1905,20 @@ process_regular_packet (struct full_conn *conn, lsquic_packet_in_t *packet_in)
|
|||
if (0 == (packet_in->pi_flags & PI_DECRYPTED) &&
|
||||
0 != conn_decrypt_packet(conn, packet_in))
|
||||
{
|
||||
LSQ_INFO("could not decrypt packet");
|
||||
if (conn_is_stateless_reset(conn, packet_in))
|
||||
{
|
||||
LSQ_INFO("received public reset packet: aborting connection");
|
||||
conn->fc_flags |= FC_GOT_PRST;
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
LSQ_INFO("could not decrypt packet");
|
||||
#if FULL_CONN_STATS
|
||||
++conn->fc_stats.n_undec_packets;
|
||||
++conn->fc_stats.n_undec_packets;
|
||||
#endif
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
st = lsquic_rechist_received(&conn->fc_rechist, packet_in->pi_packno,
|
||||
|
@ -1937,13 +1958,18 @@ process_regular_packet (struct full_conn *conn, lsquic_packet_in_t *packet_in)
|
|||
static int
|
||||
process_incoming_packet (struct full_conn *conn, lsquic_packet_in_t *packet_in)
|
||||
{
|
||||
int is_prst, is_verneg;
|
||||
|
||||
recent_packet_hist_new(conn, 0, packet_in->pi_received);
|
||||
LSQ_DEBUG("Processing packet %"PRIu64, packet_in->pi_packno);
|
||||
|
||||
is_prst = lsquic_packet_in_is_gquic_prst(packet_in);
|
||||
is_verneg = lsquic_packet_in_is_verneg(packet_in);
|
||||
|
||||
/* See flowchart in Section 4.1 of [draft-ietf-quic-transport-00]. We test
|
||||
* for the common case first.
|
||||
*/
|
||||
const unsigned flags = lsquic_packet_in_public_flags(packet_in);
|
||||
if (0 == (flags & (PACKET_PUBLIC_FLAGS_RST|PACKET_PUBLIC_FLAGS_VERSION)))
|
||||
if (0 == is_prst && 0 == is_verneg)
|
||||
{
|
||||
if (conn->fc_ver_neg.vn_tag)
|
||||
{
|
||||
|
@ -1966,7 +1992,7 @@ process_incoming_packet (struct full_conn *conn, lsquic_packet_in_t *packet_in)
|
|||
}
|
||||
return process_regular_packet(conn, packet_in);
|
||||
}
|
||||
else if (flags & PACKET_PUBLIC_FLAGS_RST)
|
||||
else if (is_prst)
|
||||
{
|
||||
LSQ_INFO("received public reset packet: aborting connection");
|
||||
conn->fc_flags |= FC_GOT_PRST;
|
||||
|
|
|
@ -60,6 +60,7 @@ enum enc_sess_history_event
|
|||
ESHE_SET_STK = 'K',
|
||||
ESHE_SET_SCID = 'D',
|
||||
ESHE_SET_PROF = 'P',
|
||||
ESHE_SET_SRST = 'S',
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -71,6 +72,7 @@ typedef struct hs_ctx_st
|
|||
HSET_SMHL = (1 << 1), /* smhl is set */
|
||||
HSET_SCID = (1 << 2),
|
||||
HSET_IRTT = (1 << 3),
|
||||
HSET_SRST = (1 << 4),
|
||||
} set;
|
||||
enum {
|
||||
HOPT_NSTP = (1 << 0), /* NSTP option present in COPT */
|
||||
|
@ -95,6 +97,7 @@ typedef struct hs_ctx_st
|
|||
//unsigned char chlo_hash[32]; //SHA256 HASH of CHLO
|
||||
unsigned char nonc[DNONC_LENGTH]; /* 4 tm, 8 orbit ---> REJ, 20 rand */
|
||||
unsigned char pubs[32];
|
||||
unsigned char srst[SRST_LENGTH];
|
||||
|
||||
uint32_t rrej;
|
||||
struct lsquic_str ccs;
|
||||
|
@ -684,6 +687,18 @@ static int parse_hs_data (lsquic_enc_session_t *enc_session, uint32_t tag,
|
|||
hs_ctx->sttl = get_tag_value_i64(val, len);
|
||||
break;
|
||||
|
||||
case QTAG_SRST:
|
||||
if (len != sizeof(hs_ctx->srst))
|
||||
{
|
||||
LSQ_INFO("Unexpected size of SRST: %u instead of %zu bytes",
|
||||
len, sizeof(hs_ctx->srst));
|
||||
return -1;
|
||||
}
|
||||
memcpy(hs_ctx->srst, val, len);
|
||||
hs_ctx->set |= HSET_SRST;
|
||||
ESHIST_APPEND(enc_session, ESHE_SET_SRST);
|
||||
break;
|
||||
|
||||
default:
|
||||
LSQ_DEBUG("Ignored tag '%.*s'", 4, (char *)&tag);
|
||||
break;
|
||||
|
@ -848,7 +863,7 @@ struct message_writer
|
|||
memset(data_ptr + 4 + 2, 0, 2); \
|
||||
(mw)->mw_entry = (void *) (data_ptr + 8); \
|
||||
(mw)->mw_p = data_ptr + 8 + \
|
||||
n_entries * sizeof((mw)->mw_entry[0]); \
|
||||
(n_entries) * sizeof((mw)->mw_entry[0]); \
|
||||
(mw)->mw_first_dummy_entry.tag = 0; \
|
||||
(mw)->mw_first_dummy_entry.off = 0; \
|
||||
(mw)->mw_prev_entry = &(mw)->mw_first_dummy_entry; \
|
||||
|
@ -1575,7 +1590,7 @@ lsquic_enc_session_decrypt (lsquic_enc_session_t *enc_session,
|
|||
}
|
||||
|
||||
|
||||
static int
|
||||
static enum enc_level
|
||||
lsquic_enc_session_encrypt (lsquic_enc_session_t *enc_session,
|
||||
enum lsquic_version version,
|
||||
uint8_t path_id, uint64_t pack_num,
|
||||
|
@ -1587,6 +1602,7 @@ lsquic_enc_session_encrypt (lsquic_enc_session_t *enc_session,
|
|||
uint8_t md[HS_PKT_HASH_LENGTH];
|
||||
uint128 hash;
|
||||
int ret;
|
||||
enum enc_level enc_level;
|
||||
int is_chlo = (is_hello && ((IS_SERVER(enc_session)) == 0));
|
||||
int is_shlo = (is_hello && (IS_SERVER(enc_session)));
|
||||
|
||||
|
@ -1620,7 +1636,7 @@ lsquic_enc_session_encrypt (lsquic_enc_session_t *enc_session,
|
|||
memcpy(buf_out, header, header_len);
|
||||
memcpy(buf_out + header_len, md, HS_PKT_HASH_LENGTH);
|
||||
memcpy(buf_out + header_len + HS_PKT_HASH_LENGTH, data, data_len);
|
||||
return 0;
|
||||
return ENC_LEV_CLEAR;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1635,12 +1651,14 @@ lsquic_enc_session_encrypt (lsquic_enc_session_t *enc_session,
|
|||
{
|
||||
enc_session->server_start_use_final_key = 1;
|
||||
}
|
||||
enc_level = ENC_LEV_INIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
LSQ_DEBUG("lsquic_enc_session_encrypt using 'F' key...");
|
||||
key = enc_session->enc_ctx_f;
|
||||
memcpy(nonce, enc_session->enc_key_nonce_f, 4);
|
||||
enc_level = ENC_LEV_FORW;
|
||||
}
|
||||
path_id_packet_number = combine_path_id_pack_num(path_id, pack_num);
|
||||
memcpy(nonce + 4, &path_id_packet_number,
|
||||
|
@ -1651,8 +1669,13 @@ lsquic_enc_session_encrypt (lsquic_enc_session_t *enc_session,
|
|||
|
||||
ret = aes_aead_enc(key, header, header_len, nonce, 12, data,
|
||||
data_len, buf_out + header_len, out_len);
|
||||
*out_len += header_len;
|
||||
return ret;
|
||||
if (ret == 0)
|
||||
{
|
||||
*out_len += header_len;
|
||||
return enc_level;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1801,6 +1824,19 @@ lsquic_enc_session_mem_used (struct lsquic_enc_session *enc_session)
|
|||
}
|
||||
|
||||
|
||||
static int
|
||||
lsquic_enc_session_verify_reset_token (lsquic_enc_session_t *enc_session,
|
||||
const unsigned char *buf, size_t bufsz)
|
||||
{
|
||||
if (bufsz == SRST_LENGTH
|
||||
&& (enc_session->hs_ctx.set & HSET_SRST)
|
||||
&& 0 == memcmp(buf, enc_session->hs_ctx.srst, SRST_LENGTH))
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#ifdef NDEBUG
|
||||
const
|
||||
#endif
|
||||
|
@ -1822,4 +1858,14 @@ struct enc_session_funcs lsquic_enc_session_gquic_1 =
|
|||
.esf_gen_chlo = lsquic_enc_session_gen_chlo,
|
||||
.esf_handle_chlo_reply = lsquic_enc_session_handle_chlo_reply,
|
||||
.esf_mem_used = lsquic_enc_session_mem_used,
|
||||
.esf_verify_reset_token = lsquic_enc_session_verify_reset_token,
|
||||
};
|
||||
|
||||
|
||||
const char *const lsquic_enclev2str[] =
|
||||
{
|
||||
[ENC_LEV_UNSET] = "unset",
|
||||
[ENC_LEV_CLEAR] = "clear",
|
||||
[ENC_LEV_INIT] = "initial",
|
||||
[ENC_LEV_FORW] = "forw-secure",
|
||||
};
|
||||
|
|
|
@ -13,6 +13,7 @@ typedef struct lsquic_enc_session lsquic_enc_session_t;
|
|||
#define DNONC_LENGTH 32
|
||||
#define aes128_key_len 16
|
||||
#define aes128_iv_len 4
|
||||
#define SRST_LENGTH 16
|
||||
|
||||
enum handshake_error /* TODO: rename this enum */
|
||||
{
|
||||
|
@ -33,6 +34,8 @@ enum enc_level
|
|||
ENC_LEV_FORW,
|
||||
};
|
||||
|
||||
extern const char *const lsquic_enclev2str[];
|
||||
|
||||
/* client side need to store 0rtt info per STK */
|
||||
typedef struct lsquic_session_cache_info_st
|
||||
{
|
||||
|
@ -86,8 +89,8 @@ struct enc_session_funcs
|
|||
int (*esf_is_hsk_done)(lsquic_enc_session_t *enc_session);
|
||||
|
||||
/* Encrypt buffer */
|
||||
int (*esf_encrypt)(lsquic_enc_session_t *enc_session, enum lsquic_version,
|
||||
uint8_t path_id, uint64_t pack_num,
|
||||
enum enc_level (*esf_encrypt)(lsquic_enc_session_t *enc_session,
|
||||
enum lsquic_version, uint8_t path_id, uint64_t pack_num,
|
||||
const unsigned char *header, size_t header_len,
|
||||
const unsigned char *data, size_t data_len,
|
||||
unsigned char *buf_out, size_t max_out_len, size_t *out_len,
|
||||
|
@ -132,6 +135,10 @@ struct enc_session_funcs
|
|||
|
||||
size_t
|
||||
(*esf_mem_used)(lsquic_enc_session_t *);
|
||||
|
||||
int
|
||||
(*esf_verify_reset_token) (lsquic_enc_session_t *, const unsigned char *,
|
||||
size_t);
|
||||
};
|
||||
|
||||
extern
|
||||
|
|
|
@ -88,3 +88,14 @@ restore_packno (lsquic_packno_t cur_packno,
|
|||
|
||||
return candidates[min];
|
||||
}
|
||||
|
||||
|
||||
const char *const lsquic_hety2str[] =
|
||||
{
|
||||
[HETY_NOT_SET] = "Short",
|
||||
[HETY_VERNEG] = "Version Negotiation",
|
||||
[HETY_INITIAL] = "Initial",
|
||||
[HETY_RETRY] = "Retry",
|
||||
[HETY_HANDSHAKE] = "Handshake",
|
||||
[HETY_0RTT] = "0-RTT",
|
||||
};
|
||||
|
|
|
@ -116,10 +116,25 @@ lsquic_frame_types_to_str (char *buf, size_t bufsz, enum quic_ft_bit);
|
|||
#define QFRAME_RETRANSMITTABLE(frame_type) \
|
||||
((1 << (frame_type)) & QFRAME_RETRANSMITTABLE_MASK)
|
||||
|
||||
#define QUIC_MAX_PUBHDR_SZ (1 /* Type */ + 8 /* CID */ + 4 /* Version */ \
|
||||
#define GQUIC_MAX_PUBHDR_SZ (1 /* Type */ + 8 /* CID */ + 4 /* Version */ \
|
||||
+ 32 /* Nonce */ + 6 /* Packet Number */ )
|
||||
|
||||
#define QUIC_MIN_PUBHDR_SZ (1 /* Type */ + 1 /* Packet number */)
|
||||
#define GQUIC_MIN_PUBHDR_SZ (1 /* Type */ + 1 /* Packet number */)
|
||||
|
||||
#define GQUIC_IETF_LONG_HEADER_SIZE (1 /* Type */ + 4 /* Version */ \
|
||||
+ 1 /* DCIL/SCIL */ + 8 /* CID */ + 4 /* Packet number */)
|
||||
|
||||
/* XXX Nonce? */
|
||||
#define IQUIC_MAX_PUBHDR_SZ GQUIC_IETF_LONG_HEADER_SIZE
|
||||
|
||||
#define IQUIC_MIN_PUBHDR_SZ (1 /* Type */ + 8 /* CID */ \
|
||||
+ 1 /* Packet number */)
|
||||
|
||||
#define QUIC_MAX_PUBHDR_SZ (GQUIC_MAX_PUBHDR_SZ > IQUIC_MAX_PUBHDR_SZ \
|
||||
? GQUIC_MAX_PUBHDR_SZ : IQUIC_MAX_PUBHDR_SZ)
|
||||
|
||||
#define QUIC_MIN_PUBHDR_SZ (GQUIC_MIN_PUBHDR_SZ < IQUIC_MIN_PUBHDR_SZ \
|
||||
? GQUIC_MIN_PUBHDR_SZ : IQUIC_MIN_PUBHDR_SZ)
|
||||
|
||||
/* 12 bytes of FNV hash or encryption IV */
|
||||
#define QUIC_PACKET_HASH_SZ 12
|
||||
|
@ -151,6 +166,19 @@ enum lsquic_packno_bits
|
|||
PACKNO_LEN_6 = 3,
|
||||
};
|
||||
|
||||
|
||||
enum header_type
|
||||
{
|
||||
HETY_NOT_SET, /* This value must be zero */
|
||||
HETY_VERNEG,
|
||||
HETY_INITIAL,
|
||||
HETY_RETRY,
|
||||
HETY_HANDSHAKE,
|
||||
HETY_0RTT,
|
||||
};
|
||||
|
||||
extern const char *const lsquic_hety2str[];
|
||||
|
||||
enum lsquic_packno_bits
|
||||
calc_packno_bits (lsquic_packno_t packno, lsquic_packno_t least_unacked,
|
||||
uint64_t n_in_flight);
|
||||
|
|
|
@ -60,7 +60,9 @@ typedef struct lsquic_packet_in
|
|||
#define PIBIT_ENC_LEV_SHIFT 5
|
||||
PI_ENC_LEV_BIT_0= (1 << 5), /* Encodes encryption level */
|
||||
PI_ENC_LEV_BIT_1= (1 << 6), /* (see enum enc_level). */
|
||||
PI_GQUIC = (1 << 7),
|
||||
} pi_flags:8;
|
||||
enum header_type pi_header_type:8;
|
||||
/* If PI_OWN_DATA flag is not set, `pi_data' points to user-supplied
|
||||
* packet data, which is NOT TO BE MODIFIED.
|
||||
*/
|
||||
|
@ -69,11 +71,19 @@ typedef struct lsquic_packet_in
|
|||
|
||||
#define lsquic_packet_in_public_flags(p) ((p)->pi_data[0])
|
||||
|
||||
#define lsquic_packet_in_is_prst(p) \
|
||||
(lsquic_packet_in_public_flags(p) & PACKET_PUBLIC_FLAGS_RST)
|
||||
#define lsquic_packet_in_is_gquic_prst(p) \
|
||||
(((p)->pi_flags & PI_GQUIC) \
|
||||
&& (lsquic_packet_in_public_flags(p) & PACKET_PUBLIC_FLAGS_RST))
|
||||
|
||||
#define lsquic_packet_in_is_verneg(p) \
|
||||
(((p)->pi_flags & PI_GQUIC) ? \
|
||||
lsquic_packet_in_public_flags(p) & PACKET_PUBLIC_FLAGS_VERSION : \
|
||||
(p)->pi_header_type == HETY_VERNEG)
|
||||
|
||||
#define lsquic_packet_in_packno_bits(p) \
|
||||
((lsquic_packet_in_public_flags(p) >> 4) & 3)
|
||||
(((p)->pi_flags & PI_GQUIC) ? \
|
||||
((lsquic_packet_in_public_flags(p) >> 4) & 3) : \
|
||||
((p)->pi_data[0] & 3))
|
||||
|
||||
#define lsquic_packet_in_upref(p) (++(p)->pi_refcnt)
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "lsquic_stream.h"
|
||||
#include "lsquic_logger.h"
|
||||
#include "lsquic_ev_log.h"
|
||||
#include "lsquic_conn.h"
|
||||
|
||||
typedef char _stream_rec_arr_is_at_most_64bytes[
|
||||
(sizeof(struct stream_rec_arr) <= 64)? 1: - 1];
|
||||
|
@ -212,12 +213,12 @@ lsquic_packet_out_add_stream (lsquic_packet_out_t *packet_out,
|
|||
|
||||
lsquic_packet_out_t *
|
||||
lsquic_packet_out_new (struct lsquic_mm *mm, struct malo *malo, int use_cid,
|
||||
unsigned short max_size, enum lsquic_packno_bits bits,
|
||||
const struct lsquic_conn *lconn, enum lsquic_packno_bits bits,
|
||||
const lsquic_ver_tag_t *ver_tag, const unsigned char *nonce)
|
||||
{
|
||||
lsquic_packet_out_t *packet_out;
|
||||
enum packet_out_flags flags;
|
||||
unsigned short header_size;
|
||||
unsigned short header_size, max_size;
|
||||
|
||||
flags = bits << POBIT_SHIFT;
|
||||
if (ver_tag)
|
||||
|
@ -226,8 +227,22 @@ lsquic_packet_out_new (struct lsquic_mm *mm, struct malo *malo, int use_cid,
|
|||
flags |= PO_NONCE;
|
||||
if (use_cid)
|
||||
flags |= PO_CONN_ID;
|
||||
if ((1 << lconn->cn_version) & LSQUIC_GQUIC_HEADER_VERSIONS)
|
||||
flags |= PO_GQUIC;
|
||||
if (
|
||||
0 == (lconn->cn_flags & LSCONN_HANDSHAKE_DONE)
|
||||
)
|
||||
{
|
||||
flags |= PO_LONGHEAD;
|
||||
if (!((1 << lconn->cn_version) & LSQUIC_GQUIC_HEADER_VERSIONS))
|
||||
{
|
||||
flags &= ~(3 << POBIT_SHIFT);
|
||||
flags |= PACKNO_LEN_4 << POBIT_SHIFT;
|
||||
}
|
||||
}
|
||||
|
||||
header_size = lsquic_po_header_length(flags);
|
||||
header_size = lsquic_po_header_length(lconn, flags);
|
||||
max_size = lconn->cn_pack_size;
|
||||
if (header_size + QUIC_PACKET_HASH_SZ >= max_size)
|
||||
{
|
||||
errno = EINVAL;
|
||||
|
@ -255,6 +270,8 @@ lsquic_packet_out_new (struct lsquic_mm *mm, struct malo *malo, int use_cid,
|
|||
}
|
||||
memcpy(packet_out->po_nonce, nonce, 32);
|
||||
}
|
||||
if (flags & PO_LONGHEAD)
|
||||
packet_out->po_header_type = HETY_HANDSHAKE;
|
||||
|
||||
return packet_out;
|
||||
}
|
||||
|
@ -602,6 +619,8 @@ verify_srecs (lsquic_packet_out_t *packet_out)
|
|||
|
||||
assert(packet_out->po_data_sz == off);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <sys/queue.h>
|
||||
|
||||
struct malo;
|
||||
struct lsquic_conn;
|
||||
struct lsquic_engine_public;
|
||||
struct lsquic_mm;
|
||||
struct lsquic_stream;
|
||||
|
@ -84,7 +85,12 @@ typedef struct lsquic_packet_out
|
|||
*/
|
||||
PO_SCHED = (1 <<14), /* On scheduled queue */
|
||||
PO_SENT_SZ = (1 <<15),
|
||||
} po_flags:16;
|
||||
PO_LONGHEAD = (1 <<16),
|
||||
PO_GQUIC = (1 <<17), /* Used for logging */
|
||||
#define POLEV_SHIFT 18
|
||||
PO_BITS_2 = (1 <<18), /* PO_BITS_2 and PO_BITS_3 encode the */
|
||||
PO_BITS_3 = (1 <<19), /* crypto level. Used for logging. */
|
||||
} po_flags;
|
||||
enum quic_ft_bit po_frame_types:16; /* Bitmask of QUIC_FRAME_* */
|
||||
unsigned short po_data_sz; /* Number of usable bytes in data */
|
||||
unsigned short po_enc_data_sz; /* Number of usable bytes in data */
|
||||
|
@ -95,6 +101,7 @@ typedef struct lsquic_packet_out
|
|||
* frames.
|
||||
*/
|
||||
unsigned short po_n_alloc; /* Total number of bytes allocated in po_data */
|
||||
enum header_type po_header_type:8;
|
||||
unsigned char *po_data;
|
||||
lsquic_packno_t po_ack2ed; /* If packet has ACK frame, value of
|
||||
* largest acked in it.
|
||||
|
@ -135,33 +142,27 @@ typedef struct lsquic_packet_out
|
|||
(p)->po_flags |= ((b) & 0x3) << POBIT_SHIFT; \
|
||||
} while (0)
|
||||
|
||||
#define lsquic_po_header_length(po_flags) ( \
|
||||
1 /* Type */ \
|
||||
+ (!!((po_flags) & PO_CONN_ID) << 3) /* Connection ID */ \
|
||||
+ (!!((po_flags) & PO_VERSION) << 2) /* Version */ \
|
||||
+ (!!((po_flags) & PO_NONCE) << 5) /* Nonce */ \
|
||||
+ packno_bits2len(((po_flags) >> POBIT_SHIFT) & 0x3) /* Packet number */ \
|
||||
)
|
||||
#define lsquic_po_header_length(lconn, po_flags) ( \
|
||||
lconn->cn_pf->pf_packout_header_size(lconn, po_flags))
|
||||
|
||||
#define lsquic_packet_out_total_sz(p) \
|
||||
((p)->po_data_sz + lsquic_po_header_length((p)->po_flags) \
|
||||
+ QUIC_PACKET_HASH_SZ)
|
||||
#define lsquic_packet_out_total_sz(lconn, p) (\
|
||||
lconn->cn_pf->pf_packout_size(lconn, p))
|
||||
|
||||
#if __GNUC__
|
||||
#if LSQUIC_EXTRA_CHECKS
|
||||
#define lsquic_packet_out_sent_sz(p) ( \
|
||||
#define lsquic_packet_out_sent_sz(lconn, p) ( \
|
||||
__builtin_expect(((p)->po_flags & PO_SENT_SZ), 1) ? \
|
||||
(assert((p)->po_sent_sz == lsquic_packet_out_total_sz(p)), \
|
||||
(p)->po_sent_sz) : lsquic_packet_out_total_sz(p))
|
||||
(assert((p)->po_sent_sz == lsquic_packet_out_total_sz(lconn, p)), \
|
||||
(p)->po_sent_sz) : lsquic_packet_out_total_sz(lconn, p))
|
||||
# else
|
||||
#define lsquic_packet_out_sent_sz(p) ( \
|
||||
#define lsquic_packet_out_sent_sz(lconn, p) ( \
|
||||
__builtin_expect(((p)->po_flags & PO_SENT_SZ), 1) ? \
|
||||
(p)->po_sent_sz : lsquic_packet_out_total_sz(p))
|
||||
(p)->po_sent_sz : lsquic_packet_out_total_sz(lconn, p))
|
||||
#endif
|
||||
#else
|
||||
# define lsquic_packet_out_sent_sz(p) ( \
|
||||
# define lsquic_packet_out_sent_sz(lconn, p) ( \
|
||||
(p)->po_flags & PO_SENT_SZ ? \
|
||||
(p)->po_sent_sz : lsquic_packet_out_total_sz(p))
|
||||
(p)->po_sent_sz : lsquic_packet_out_total_sz(lconn, p))
|
||||
#endif
|
||||
|
||||
#define lsquic_packet_out_verneg(p) \
|
||||
|
@ -170,6 +171,13 @@ typedef struct lsquic_packet_out
|
|||
#define lsquic_packet_out_pubres(p) \
|
||||
(((p)->po_flags & (PO_NOENCRYPT|PO_VERNEG)) == PO_NOENCRYPT )
|
||||
|
||||
#define lsquic_packet_out_set_enc_level(p, level) do { \
|
||||
(p)->po_flags &= ~(3 << POLEV_SHIFT); \
|
||||
(p)->po_flags |= level << POLEV_SHIFT; \
|
||||
} while (0)
|
||||
|
||||
#define lsquic_packet_out_enc_level(p) (((p)->po_flags >> POLEV_SHIFT) & 3)
|
||||
|
||||
struct packet_out_srec_iter {
|
||||
lsquic_packet_out_t *packet_out;
|
||||
struct stream_rec_arr *cur_srec_arr;
|
||||
|
@ -185,7 +193,7 @@ posi_next (struct packet_out_srec_iter *posi);
|
|||
|
||||
lsquic_packet_out_t *
|
||||
lsquic_packet_out_new (struct lsquic_mm *, struct malo *, int use_cid,
|
||||
unsigned short size, enum lsquic_packno_bits,
|
||||
const struct lsquic_conn *, enum lsquic_packno_bits,
|
||||
const lsquic_ver_tag_t *, const unsigned char *nonce);
|
||||
|
||||
void
|
||||
|
|
|
@ -7,7 +7,10 @@
|
|||
#include "lsquic_packet_common.h"
|
||||
|
||||
struct lsquic_packet_in;
|
||||
struct lsquic_packet_out;
|
||||
struct packin_parse_state;
|
||||
struct stream_frame;
|
||||
enum packet_out_flags;
|
||||
|
||||
#define LSQUIC_PARSE_ACK_TIMESTAMPS 0
|
||||
|
||||
|
@ -54,27 +57,17 @@ typedef lsquic_time_t
|
|||
/* gsf_: generate stream frame */
|
||||
typedef size_t (*gsf_read_f) (void *stream, void *buf, size_t len, int *fin);
|
||||
|
||||
struct packin_parse_state {
|
||||
const unsigned char *pps_p; /* Pointer to packet number */
|
||||
unsigned pps_nbytes; /* Number of bytes in packet number */
|
||||
};
|
||||
|
||||
/* This structure contains functions that parse and generate packets and
|
||||
* frames in version-specific manner. To begin with, there is difference
|
||||
* between GQUIC's little-endian (Q038 and lower) and big-endian formats
|
||||
* (Q039 and higher).
|
||||
* (Q039 and higher). Q044 uses different format for packet headers.
|
||||
*/
|
||||
struct parse_funcs
|
||||
{
|
||||
int
|
||||
(*pf_gen_ver_nego_pkt) (unsigned char *buf, size_t bufsz, uint64_t conn_id,
|
||||
unsigned version_bitmask);
|
||||
/* Return buf length */
|
||||
int
|
||||
(*pf_gen_reg_pkt_header) (unsigned char *buf, size_t bufsz,
|
||||
const lsquic_cid_t *, const lsquic_ver_tag_t *,
|
||||
const unsigned char *nonce, lsquic_packno_t,
|
||||
enum lsquic_packno_bits);
|
||||
(*pf_gen_reg_pkt_header) (const struct lsquic_conn *,
|
||||
const struct lsquic_packet_out *, unsigned char *, size_t);
|
||||
void
|
||||
(*pf_parse_packet_in_finish) (struct lsquic_packet_in *packet_in,
|
||||
struct packin_parse_state *);
|
||||
|
@ -154,28 +147,57 @@ struct parse_funcs
|
|||
(*pf_calc_stream_frame_header_sz) (uint32_t stream_id, uint64_t offset);
|
||||
void
|
||||
(*pf_turn_on_fin) (unsigned char *);
|
||||
|
||||
size_t
|
||||
(*pf_packout_size) (const struct lsquic_conn *,
|
||||
const struct lsquic_packet_out *);
|
||||
|
||||
size_t
|
||||
(*pf_packout_header_size) (const struct lsquic_conn *,
|
||||
enum packet_out_flags);
|
||||
};
|
||||
|
||||
extern const struct parse_funcs lsquic_parse_funcs_gquic_le;
|
||||
/* Q039 and later are big-endian: */
|
||||
extern const struct parse_funcs lsquic_parse_funcs_gquic_Q039;
|
||||
extern const struct parse_funcs lsquic_parse_funcs_gquic_Q044;
|
||||
|
||||
#define select_pf_by_ver(ver) ( \
|
||||
((1 << (ver)) & (1 << LSQVER_035)) \
|
||||
? &lsquic_parse_funcs_gquic_le \
|
||||
: &lsquic_parse_funcs_gquic_Q039)
|
||||
: (ver) < LSQVER_044 \
|
||||
? &lsquic_parse_funcs_gquic_Q039 \
|
||||
: &lsquic_parse_funcs_gquic_Q044)
|
||||
|
||||
/* This function is QUIC-version independent */
|
||||
int
|
||||
parse_packet_in_begin (struct lsquic_packet_in *, size_t length,
|
||||
lsquic_gquic_parse_packet_in_begin (struct lsquic_packet_in *, size_t length,
|
||||
int is_server, struct packin_parse_state *);
|
||||
|
||||
int
|
||||
lsquic_iquic_parse_packet_in_long_begin (struct lsquic_packet_in *,
|
||||
size_t length, int is_server, struct packin_parse_state *state);
|
||||
|
||||
int
|
||||
lsquic_iquic_parse_packet_in_short_begin (struct lsquic_packet_in *,
|
||||
size_t length, int is_server, struct packin_parse_state *state);
|
||||
|
||||
enum QUIC_FRAME_TYPE
|
||||
parse_frame_type_gquic_Q035_thru_Q039 (unsigned char first_byte);
|
||||
|
||||
size_t
|
||||
calc_stream_frame_header_sz_gquic (uint32_t stream_id, uint64_t offset);
|
||||
|
||||
size_t
|
||||
lsquic_gquic_packout_size (const struct lsquic_conn *,
|
||||
const struct lsquic_packet_out *);
|
||||
|
||||
size_t
|
||||
lsquic_gquic_packout_header_size (const struct lsquic_conn *conn,
|
||||
enum packet_out_flags flags);
|
||||
|
||||
size_t
|
||||
lsquic_gquic_po_header_sz (enum packet_out_flags flags);
|
||||
|
||||
/* This maps two bits as follows:
|
||||
* 00 -> 1
|
||||
* 01 -> 2
|
||||
|
|
213
src/liblsquic/lsquic_parse_Q044.c
Normal file
213
src/liblsquic/lsquic_parse_Q044.c
Normal file
|
@ -0,0 +1,213 @@
|
|||
/* Copyright (c) 2017 - 2018 LiteSpeed Technologies Inc. See LICENSE. */
|
||||
/*
|
||||
* lsquic_parse_Q044.c -- Parsing functions specific to GQUIC Q044
|
||||
*/
|
||||
|
||||
#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_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_conn.h"
|
||||
|
||||
#define LSQUIC_LOGGER_MODULE LSQLM_PARSE
|
||||
#include "lsquic_logger.h"
|
||||
|
||||
|
||||
|
||||
|
||||
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 lsquic_packno_bits bits;
|
||||
uint32_t packno;
|
||||
|
||||
bits = (packet_out->po_flags >> POBIT_SHIFT) & 0x3;
|
||||
packno_len = packno_bits2len(bits);
|
||||
|
||||
need = 1 + 8 /* CID */ + packno_len;
|
||||
|
||||
if (need > bufsz)
|
||||
return -1;
|
||||
|
||||
*buf++ = 0x30 | bits;
|
||||
|
||||
memcpy(buf, &lconn->cn_cid, 8);
|
||||
buf += 8;
|
||||
|
||||
packno = packet_out->po_packno;
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
packno = bswap_32(packno);
|
||||
#endif
|
||||
memcpy(buf, (unsigned char *) &packno + 4 - packno_len, packno_len);
|
||||
|
||||
return need;
|
||||
}
|
||||
|
||||
|
||||
static size_t
|
||||
gquic_Q044_packout_header_size_long (const struct lsquic_conn *lconn,
|
||||
enum packet_out_flags flags)
|
||||
{
|
||||
return GQUIC_IETF_LONG_HEADER_SIZE;
|
||||
}
|
||||
|
||||
|
||||
static const unsigned char header_type_to_bin[] = {
|
||||
[HETY_NOT_SET] = 0x00,
|
||||
[HETY_INITIAL] = 0x7F,
|
||||
[HETY_RETRY] = 0x7E,
|
||||
[HETY_HANDSHAKE] = 0x7D,
|
||||
[HETY_0RTT] = 0x7C,
|
||||
};
|
||||
|
||||
|
||||
static int
|
||||
gen_long_pkt_header (const struct lsquic_conn *lconn,
|
||||
const struct lsquic_packet_out *packet_out, unsigned char *buf,
|
||||
size_t bufsz)
|
||||
{
|
||||
lsquic_ver_tag_t ver_tag;
|
||||
unsigned char *p;
|
||||
uint32_t packno;
|
||||
size_t need;
|
||||
|
||||
need = gquic_Q044_packout_header_size_long(lconn, packet_out->po_flags);
|
||||
if (need > bufsz)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
p = buf;
|
||||
*p++ = 0x80 | header_type_to_bin[ packet_out->po_header_type ];
|
||||
ver_tag = lsquic_ver2tag(lconn->cn_version);
|
||||
memcpy(p, &ver_tag, sizeof(ver_tag));
|
||||
p += sizeof(ver_tag);
|
||||
|
||||
*p++ = 0x50;
|
||||
|
||||
memcpy(p, &lconn->cn_cid, 8);
|
||||
p += 8;
|
||||
|
||||
packno = packet_out->po_packno;
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
packno = bswap_32(packno);
|
||||
#endif
|
||||
memcpy(p, &packno, 4);
|
||||
p += 4;
|
||||
|
||||
|
||||
assert(need = p - buf);
|
||||
return p - buf;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
gquic_Q044_gen_reg_pkt_header (const struct lsquic_conn *lconn,
|
||||
const struct lsquic_packet_out *packet_out, unsigned char *buf,
|
||||
size_t bufsz)
|
||||
{
|
||||
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_Q044_packout_header_size_short (const struct lsquic_conn *lconn,
|
||||
enum packet_out_flags flags)
|
||||
{
|
||||
enum lsquic_packno_bits bits;
|
||||
size_t sz;
|
||||
|
||||
bits = (flags >> POBIT_SHIFT) & 0x3;
|
||||
sz = 1; /* Type */
|
||||
sz += 8; /* CID */
|
||||
sz += packno_bits2len(bits);
|
||||
|
||||
return sz;
|
||||
}
|
||||
|
||||
|
||||
static size_t
|
||||
gquic_Q044_packout_header_size (const struct lsquic_conn *lconn,
|
||||
enum packet_out_flags flags)
|
||||
{
|
||||
if (0 == (flags & PO_LONGHEAD))
|
||||
return gquic_Q044_packout_header_size_short(lconn, flags);
|
||||
else
|
||||
return gquic_Q044_packout_header_size_long(lconn, flags);
|
||||
}
|
||||
|
||||
|
||||
static size_t
|
||||
gquic_Q044_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_Q044_packout_header_size_short(lconn, packet_out->po_flags);
|
||||
else
|
||||
sz = gquic_Q044_packout_header_size_long(lconn, packet_out->po_flags);
|
||||
|
||||
sz += packet_out->po_data_sz;
|
||||
sz += QUIC_PACKET_HASH_SZ;
|
||||
|
||||
return sz;
|
||||
}
|
||||
|
||||
|
||||
const struct parse_funcs lsquic_parse_funcs_gquic_Q044 =
|
||||
{
|
||||
.pf_gen_reg_pkt_header = gquic_Q044_gen_reg_pkt_header,
|
||||
.pf_parse_packet_in_finish = gquic_be_parse_packet_in_finish,
|
||||
.pf_gen_stream_frame = gquic_be_gen_stream_frame,
|
||||
.pf_calc_stream_frame_header_sz = calc_stream_frame_header_sz_gquic,
|
||||
.pf_parse_stream_frame = gquic_be_parse_stream_frame,
|
||||
.pf_parse_ack_frame = gquic_be_parse_ack_frame,
|
||||
.pf_gen_ack_frame = gquic_be_gen_ack_frame,
|
||||
.pf_gen_stop_waiting_frame = gquic_be_gen_stop_waiting_frame,
|
||||
.pf_parse_stop_waiting_frame = gquic_be_parse_stop_waiting_frame,
|
||||
.pf_skip_stop_waiting_frame = gquic_be_skip_stop_waiting_frame,
|
||||
.pf_gen_window_update_frame = gquic_be_gen_window_update_frame,
|
||||
.pf_parse_window_update_frame = gquic_be_parse_window_update_frame,
|
||||
.pf_gen_blocked_frame = gquic_be_gen_blocked_frame,
|
||||
.pf_parse_blocked_frame = gquic_be_parse_blocked_frame,
|
||||
.pf_gen_rst_frame = gquic_be_gen_rst_frame,
|
||||
.pf_parse_rst_frame = gquic_be_parse_rst_frame,
|
||||
.pf_gen_connect_close_frame = gquic_be_gen_connect_close_frame,
|
||||
.pf_parse_connect_close_frame = gquic_be_parse_connect_close_frame,
|
||||
.pf_gen_goaway_frame = gquic_be_gen_goaway_frame,
|
||||
.pf_parse_goaway_frame = gquic_be_parse_goaway_frame,
|
||||
.pf_gen_ping_frame = gquic_be_gen_ping_frame,
|
||||
#ifndef NDEBUG
|
||||
.pf_write_float_time16 = gquic_be_write_float_time16,
|
||||
.pf_read_float_time16 = gquic_be_read_float_time16,
|
||||
#endif
|
||||
.pf_parse_frame_type = parse_frame_type_gquic_Q035_thru_Q039,
|
||||
.pf_turn_on_fin = lsquic_turn_on_fin_Q035_thru_Q039,
|
||||
.pf_packout_size = gquic_Q044_packout_size,
|
||||
.pf_packout_header_size = gquic_Q044_packout_header_size,
|
||||
};
|
56
src/liblsquic/lsquic_parse_common.c
Normal file
56
src/liblsquic/lsquic_parse_common.c
Normal file
|
@ -0,0 +1,56 @@
|
|||
/* Copyright (c) 2017 - 2018 LiteSpeed Technologies Inc. See LICENSE. */
|
||||
#include <string.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "lsquic_types.h"
|
||||
#include "lsquic_int_types.h"
|
||||
#include "lsquic_packet_common.h"
|
||||
#include "lsquic_packet_in.h"
|
||||
#include "lsquic_parse_common.h"
|
||||
#include "lsquic_parse.h"
|
||||
|
||||
|
||||
int
|
||||
lsquic_parse_packet_in_begin (lsquic_packet_in_t *packet_in, size_t length,
|
||||
int is_server, struct packin_parse_state *state)
|
||||
{
|
||||
if (length > 0)
|
||||
{
|
||||
switch (packet_in->pi_data[0] & 0x88)
|
||||
{
|
||||
case 0x88:
|
||||
case 0x80:
|
||||
return lsquic_iquic_parse_packet_in_long_begin(packet_in, length,
|
||||
is_server, state);
|
||||
case 0x08:
|
||||
return lsquic_gquic_parse_packet_in_begin(packet_in, length,
|
||||
is_server, state);
|
||||
default:
|
||||
return lsquic_iquic_parse_packet_in_short_begin(packet_in, length,
|
||||
is_server, state);
|
||||
}
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
lsquic_iquic_parse_packet_in_begin (struct lsquic_packet_in *packet_in,
|
||||
size_t length, int is_server, struct packin_parse_state *state)
|
||||
{
|
||||
if (length > 0)
|
||||
{
|
||||
if (0 == (packet_in->pi_data[0] & 0x80))
|
||||
return lsquic_iquic_parse_packet_in_short_begin(packet_in, length,
|
||||
is_server, state);
|
||||
else
|
||||
return lsquic_iquic_parse_packet_in_long_begin(packet_in, length,
|
||||
is_server, state);
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
24
src/liblsquic/lsquic_parse_common.h
Normal file
24
src/liblsquic/lsquic_parse_common.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
/* Copyright (c) 2017 - 2018 LiteSpeed Technologies Inc. See LICENSE. */
|
||||
/*
|
||||
* lsquic_parse_common.h
|
||||
*/
|
||||
|
||||
#ifndef LSQUIC_PARSE_COMMON_H
|
||||
#define LSQUIC_PARSE_COMMON_H 1
|
||||
|
||||
struct lsquic_packet_in;
|
||||
|
||||
struct packin_parse_state {
|
||||
const unsigned char *pps_p; /* Pointer to packet number */
|
||||
unsigned pps_nbytes; /* Number of bytes in packet number */
|
||||
};
|
||||
|
||||
int
|
||||
lsquic_parse_packet_in_begin (struct lsquic_packet_in *,
|
||||
size_t length, int is_server, struct packin_parse_state *);
|
||||
|
||||
int
|
||||
lsquic_iquic_parse_packet_in_begin (struct lsquic_packet_in *,
|
||||
size_t length, int is_server, struct packin_parse_state *);
|
||||
|
||||
#endif
|
|
@ -20,7 +20,9 @@
|
|||
#include "lsquic_alarmset.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_rechist.h"
|
||||
#include "lsquic_sfcw.h"
|
||||
#include "lsquic_stream.h"
|
||||
|
@ -28,7 +30,9 @@
|
|||
#include "lsquic_malo.h"
|
||||
#include "lsquic_version.h"
|
||||
#include "lsquic.h"
|
||||
#include "lsquic_conn.h"
|
||||
#include "lsquic_parse_gquic_be.h" /* Include to catch mismatches */
|
||||
#include "lsquic_byteswap.h"
|
||||
|
||||
#define LSQUIC_LOGGER_MODULE LSQLM_PARSE
|
||||
#include "lsquic_logger.h"
|
||||
|
@ -98,41 +102,20 @@ gquic_be_parse_packet_in_finish (lsquic_packet_in_t *packet_in,
|
|||
}
|
||||
|
||||
|
||||
int
|
||||
gquic_be_gen_ver_nego_pkt (unsigned char *buf, size_t bufsz, uint64_t conn_id,
|
||||
unsigned version_bitmask)
|
||||
{
|
||||
int sz;
|
||||
unsigned char *p = buf;
|
||||
unsigned char *const pend = p + bufsz;
|
||||
|
||||
CHECK_SPACE(1, p, pend);
|
||||
*p = PACKET_PUBLIC_FLAGS_VERSION | PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID;
|
||||
++p;
|
||||
|
||||
CHECK_SPACE(8, p, pend);
|
||||
memcpy(p, &conn_id, 8);
|
||||
p += 8;
|
||||
|
||||
sz = gen_ver_tags(p, pend - p, version_bitmask);
|
||||
if (sz < 0)
|
||||
return -1;
|
||||
|
||||
return p + sz - buf;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
gquic_be_gen_reg_pkt_header (unsigned char *buf, size_t bufsz, const lsquic_cid_t *conn_id,
|
||||
const lsquic_ver_tag_t *ver, const unsigned char *nonce,
|
||||
lsquic_packno_t packno, enum lsquic_packno_bits bits)
|
||||
static int
|
||||
gquic_be_gen_reg_pkt_header (const struct lsquic_conn *lconn,
|
||||
const struct lsquic_packet_out *packet_out, unsigned char *buf,
|
||||
size_t bufsz)
|
||||
{
|
||||
unsigned packnum_len, header_len;
|
||||
enum lsquic_packno_bits bits;
|
||||
lsquic_packno_t packno;
|
||||
unsigned char *p;
|
||||
|
||||
bits = lsquic_packet_out_packno_bits(packet_out);
|
||||
packnum_len = packno_bits2len(bits);
|
||||
|
||||
if (!(conn_id || ver || nonce))
|
||||
if (0 == (packet_out->po_flags & (PO_CONN_ID|PO_VERSION|PO_NONCE)))
|
||||
{
|
||||
header_len = 1 + packnum_len;
|
||||
if (header_len > bufsz)
|
||||
|
@ -146,8 +129,16 @@ gquic_be_gen_reg_pkt_header (unsigned char *buf, size_t bufsz, const lsquic_cid_
|
|||
}
|
||||
else
|
||||
{
|
||||
header_len = 1 + (!!conn_id << 3) + (!!ver << 2) + ((!!nonce) << 5)
|
||||
+ packnum_len;
|
||||
const int
|
||||
have_cid = packet_out->po_flags & PO_CONN_ID,
|
||||
have_ver = packet_out->po_flags & PO_VERSION,
|
||||
have_nonce = packet_out->po_flags & PO_NONCE;
|
||||
header_len = 1
|
||||
+ (!!have_cid << 3)
|
||||
+ (!!have_ver << 2)
|
||||
+ (!!have_nonce << 5)
|
||||
+ packnum_len
|
||||
;
|
||||
if (header_len > bufsz)
|
||||
{
|
||||
errno = ENOBUFS;
|
||||
|
@ -156,31 +147,32 @@ gquic_be_gen_reg_pkt_header (unsigned char *buf, size_t bufsz, const lsquic_cid_
|
|||
|
||||
p = buf;
|
||||
|
||||
*p = (!!conn_id << 3)
|
||||
*p = (!!have_cid << 3)
|
||||
| (bits << 4)
|
||||
| ((!!nonce) << 2)
|
||||
| !!ver;
|
||||
| ((!!have_nonce) << 2)
|
||||
| !!have_ver;
|
||||
++p;
|
||||
|
||||
if (conn_id)
|
||||
if (have_cid)
|
||||
{
|
||||
memcpy(p, conn_id , sizeof(*conn_id));
|
||||
p += sizeof(*conn_id);
|
||||
memcpy(p, &lconn->cn_cid, sizeof(lconn->cn_cid));
|
||||
p += sizeof(lconn->cn_cid);
|
||||
}
|
||||
|
||||
if (ver)
|
||||
if (have_ver)
|
||||
{
|
||||
memcpy(p, ver, 4);
|
||||
memcpy(p, &packet_out->po_ver_tag, 4);
|
||||
p += 4;
|
||||
}
|
||||
|
||||
if (nonce)
|
||||
if (have_nonce)
|
||||
{
|
||||
memcpy(p, nonce , 32);
|
||||
memcpy(p, packet_out->po_nonce , 32);
|
||||
p += 32;
|
||||
}
|
||||
}
|
||||
|
||||
packno = packet_out->po_packno;
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
packno = bswap_64(packno);
|
||||
#endif
|
||||
|
@ -955,7 +947,6 @@ gquic_be_gen_ack_frame (unsigned char *outbuf, size_t outbuf_sz,
|
|||
|
||||
const struct parse_funcs lsquic_parse_funcs_gquic_Q039 =
|
||||
{
|
||||
.pf_gen_ver_nego_pkt = gquic_be_gen_ver_nego_pkt,
|
||||
.pf_gen_reg_pkt_header = gquic_be_gen_reg_pkt_header,
|
||||
.pf_parse_packet_in_finish = gquic_be_parse_packet_in_finish,
|
||||
.pf_gen_stream_frame = gquic_be_gen_stream_frame,
|
||||
|
@ -983,4 +974,6 @@ const struct parse_funcs lsquic_parse_funcs_gquic_Q039 =
|
|||
#endif
|
||||
.pf_parse_frame_type = parse_frame_type_gquic_Q035_thru_Q039,
|
||||
.pf_turn_on_fin = lsquic_turn_on_fin_Q035_thru_Q039,
|
||||
.pf_packout_size = lsquic_gquic_packout_size,
|
||||
.pf_packout_header_size = lsquic_gquic_packout_header_size,
|
||||
};
|
||||
|
|
|
@ -8,24 +8,6 @@
|
|||
* and that would be a mess.
|
||||
*/
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__)
|
||||
#include <sys/endian.h>
|
||||
#define bswap_16 bswap16
|
||||
#define bswap_32 bswap32
|
||||
#define bswap_64 bswap64
|
||||
#elif defined(__APPLE__)
|
||||
#include <libkern/OSByteOrder.h>
|
||||
#define bswap_16 OSSwapInt16
|
||||
#define bswap_32 OSSwapInt32
|
||||
#define bswap_64 OSSwapInt64
|
||||
#elif defined(WIN32)
|
||||
#define bswap_16 _byteswap_ushort
|
||||
#define bswap_32 _byteswap_ulong
|
||||
#define bswap_64 _byteswap_uint64
|
||||
#else
|
||||
#include <byteswap.h>
|
||||
#endif
|
||||
|
||||
#define CHECK_SPACE(need, pstart, pend) \
|
||||
do { if ((intptr_t) (need) > ((pend) - (pstart))) { return -1; } } while (0)
|
||||
|
||||
|
@ -58,11 +40,6 @@ int
|
|||
gquic_be_gen_ver_nego_pkt (unsigned char *buf, size_t bufsz, uint64_t conn_id,
|
||||
unsigned version_bitmask);
|
||||
|
||||
int
|
||||
gquic_be_gen_reg_pkt_header (unsigned char *buf, size_t bufsz, const lsquic_cid_t *conn_id,
|
||||
const lsquic_ver_tag_t *ver, const unsigned char *nonce,
|
||||
lsquic_packno_t packno, enum lsquic_packno_bits bits);
|
||||
|
||||
int
|
||||
gquic_be_gen_stream_frame (unsigned char *buf, size_t buf_len, uint32_t stream_id,
|
||||
uint64_t offset, int fin, size_t size,
|
||||
|
|
|
@ -17,8 +17,11 @@
|
|||
|
||||
#include "lsquic_types.h"
|
||||
#include "lsquic_packet_common.h"
|
||||
#include "lsquic_packet_out.h"
|
||||
#include "lsquic_packet_in.h"
|
||||
#include "lsquic_parse.h"
|
||||
#include "lsquic_parse_common.h"
|
||||
#include "lsquic_version.h"
|
||||
#include "lsquic.h"
|
||||
|
||||
#define LSQUIC_LOGGER_MODULE LSQLM_PARSE
|
||||
|
@ -35,8 +38,8 @@
|
|||
* pf_parse_packet_in_finish() routine.
|
||||
*/
|
||||
int
|
||||
parse_packet_in_begin (lsquic_packet_in_t *packet_in, size_t length,
|
||||
int is_server, struct packin_parse_state *state)
|
||||
lsquic_gquic_parse_packet_in_begin (struct lsquic_packet_in *packet_in,
|
||||
size_t length, int is_server, struct packin_parse_state *state)
|
||||
{
|
||||
int nbytes;
|
||||
enum PACKET_PUBLIC_FLAGS public_flags;
|
||||
|
@ -128,6 +131,7 @@ parse_packet_in_begin (lsquic_packet_in_t *packet_in, size_t length,
|
|||
packet_in->pi_data_sz = length;
|
||||
packet_in->pi_refcnt = 0;
|
||||
packet_in->pi_received = 0;
|
||||
packet_in->pi_flags |= PI_GQUIC;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -462,3 +466,36 @@ acki2str (const struct ack_info *acki, size_t *sz)
|
|||
*sz = off;
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
lsquic_gquic_po_header_sz (enum packet_out_flags flags)
|
||||
{
|
||||
return 1 /* Type */
|
||||
+ (!!(flags & PO_CONN_ID) << 3) /* Connection ID */
|
||||
+ (!!(flags & PO_VERSION) << 2) /* Version */
|
||||
+ (!!(flags & PO_NONCE) << 5) /* Nonce */
|
||||
+ packno_bits2len((flags >> POBIT_SHIFT) & 0x3) /* Packet number */
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
lsquic_gquic_packout_size (const struct lsquic_conn *conn,
|
||||
const struct lsquic_packet_out *packet_out)
|
||||
{
|
||||
return lsquic_gquic_po_header_sz(packet_out->po_flags)
|
||||
+ packet_out->po_data_sz
|
||||
+ QUIC_PACKET_HASH_SZ
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
lsquic_gquic_packout_header_size (const struct lsquic_conn *conn,
|
||||
enum packet_out_flags flags)
|
||||
{
|
||||
return lsquic_gquic_po_header_sz(flags);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -20,7 +20,9 @@
|
|||
#include "lsquic_alarmset.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_rechist.h"
|
||||
#include "lsquic_sfcw.h"
|
||||
#include "lsquic_stream.h"
|
||||
|
@ -28,6 +30,7 @@
|
|||
#include "lsquic_malo.h"
|
||||
#include "lsquic_version.h"
|
||||
#include "lsquic.h"
|
||||
#include "lsquic_conn.h"
|
||||
|
||||
#define LSQUIC_LOGGER_MODULE LSQLM_PARSE
|
||||
#include "lsquic_logger.h"
|
||||
|
@ -118,41 +121,23 @@ gquic_le_parse_packet_in_finish (lsquic_packet_in_t *packet_in,
|
|||
|
||||
|
||||
static int
|
||||
gquic_le_gen_ver_nego_pkt (unsigned char *buf, size_t bufsz, uint64_t conn_id,
|
||||
unsigned version_bitmask)
|
||||
{
|
||||
int sz;
|
||||
unsigned char *p = buf;
|
||||
unsigned char *const pend = p + bufsz;
|
||||
|
||||
CHECK_SPACE(1, p, pend);
|
||||
*p = PACKET_PUBLIC_FLAGS_VERSION | PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID;
|
||||
++p;
|
||||
|
||||
CHECK_SPACE(8, p, pend);
|
||||
memcpy(p, &conn_id, 8);
|
||||
p += 8;
|
||||
|
||||
sz = gen_ver_tags(p, pend - p, version_bitmask);
|
||||
if (sz < 0)
|
||||
return -1;
|
||||
|
||||
return p + sz - buf;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
gquic_le_gen_reg_pkt_header (unsigned char *buf, size_t bufsz, const lsquic_cid_t *conn_id,
|
||||
const lsquic_ver_tag_t *ver, const unsigned char *nonce,
|
||||
lsquic_packno_t packno, enum lsquic_packno_bits bits)
|
||||
gquic_le_gen_reg_pkt_header (const struct lsquic_conn *lconn,
|
||||
const struct lsquic_packet_out *packet_out, unsigned char *buf,
|
||||
size_t bufsz)
|
||||
{
|
||||
unsigned packnum_len, header_len;
|
||||
unsigned char *p;
|
||||
enum lsquic_packno_bits bits;
|
||||
|
||||
bits = lsquic_packet_out_packno_bits(packet_out);
|
||||
packnum_len = packno_bits2len(bits);
|
||||
|
||||
header_len = 1 + (!!conn_id << 3) + (!!ver << 2) + ((!!nonce) << 5)
|
||||
+ packnum_len;
|
||||
header_len = 1
|
||||
+ (!!(packet_out->po_flags & PO_CONN_ID) << 3)
|
||||
+ (!!(packet_out->po_flags & PO_VERSION) << 2)
|
||||
+ (!!(packet_out->po_flags & PO_NONCE) << 5)
|
||||
+ packnum_len
|
||||
;
|
||||
if (header_len > bufsz)
|
||||
{
|
||||
errno = ENOBUFS;
|
||||
|
@ -161,32 +146,32 @@ gquic_le_gen_reg_pkt_header (unsigned char *buf, size_t bufsz, const lsquic_cid_
|
|||
|
||||
p = buf;
|
||||
|
||||
*p = (!!conn_id << 3)
|
||||
*p = (!!(packet_out->po_flags & PO_CONN_ID) << 3)
|
||||
| (bits << 4)
|
||||
| ((!!nonce) << 2)
|
||||
| !!ver;
|
||||
| ((!!(packet_out->po_flags & PO_NONCE)) << 2)
|
||||
| !!(packet_out->po_flags & PO_VERSION);
|
||||
++p;
|
||||
|
||||
if (conn_id)
|
||||
if (packet_out->po_flags & PO_CONN_ID)
|
||||
{
|
||||
memcpy(p, conn_id , sizeof(*conn_id));
|
||||
p += sizeof(*conn_id);
|
||||
memcpy(p, &lconn->cn_cid, sizeof(lconn->cn_cid));
|
||||
p += sizeof(lconn->cn_cid);
|
||||
}
|
||||
|
||||
if (ver)
|
||||
if (packet_out->po_flags & PO_VERSION)
|
||||
{
|
||||
memcpy(p, ver, 4);
|
||||
memcpy(p, &packet_out->po_ver_tag, 4);
|
||||
p += 4;
|
||||
}
|
||||
|
||||
if (nonce)
|
||||
if (packet_out->po_flags & PO_NONCE)
|
||||
{
|
||||
memcpy(p, nonce , 32);
|
||||
memcpy(p, packet_out->po_nonce, 32);
|
||||
p += 32;
|
||||
}
|
||||
|
||||
/* ENDIAN */
|
||||
memcpy(p, &packno, packnum_len);
|
||||
memcpy(p, &packet_out->po_packno, packnum_len);
|
||||
p += packnum_len;
|
||||
|
||||
assert(p - buf == (intptr_t) header_len);
|
||||
|
@ -832,7 +817,6 @@ gquic_le_gen_ack_frame (unsigned char *outbuf, size_t outbuf_sz,
|
|||
|
||||
const struct parse_funcs lsquic_parse_funcs_gquic_le =
|
||||
{
|
||||
.pf_gen_ver_nego_pkt = gquic_le_gen_ver_nego_pkt,
|
||||
.pf_gen_reg_pkt_header = gquic_le_gen_reg_pkt_header,
|
||||
.pf_parse_packet_in_finish = gquic_le_parse_packet_in_finish,
|
||||
.pf_gen_stream_frame = gquic_le_gen_stream_frame,
|
||||
|
@ -860,4 +844,6 @@ const struct parse_funcs lsquic_parse_funcs_gquic_le =
|
|||
#endif
|
||||
.pf_parse_frame_type = parse_frame_type_gquic_Q035_thru_Q039,
|
||||
.pf_turn_on_fin = lsquic_turn_on_fin_Q035_thru_Q039,
|
||||
.pf_packout_size = lsquic_gquic_packout_size,
|
||||
.pf_packout_header_size = lsquic_gquic_packout_header_size,
|
||||
};
|
||||
|
|
185
src/liblsquic/lsquic_parse_iquic_common.c
Normal file
185
src/liblsquic/lsquic_parse_iquic_common.c
Normal file
|
@ -0,0 +1,185 @@
|
|||
/* Copyright (c) 2017 - 2018 LiteSpeed Technologies Inc. See LICENSE. */
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <openssl/rand.h>
|
||||
|
||||
#include "lsquic_types.h"
|
||||
#include "lsquic_int_types.h"
|
||||
#include "lsquic_packet_common.h"
|
||||
#include "lsquic_packet_in.h"
|
||||
#include "lsquic_parse_common.h"
|
||||
#include "lsquic_parse.h"
|
||||
#include "lsquic_version.h"
|
||||
#include "lsquic.h"
|
||||
#include "lsquic_logger.h"
|
||||
#include "lsquic_byteswap.h"
|
||||
#include "lsquic_str.h"
|
||||
#include "lsquic_handshake.h"
|
||||
|
||||
|
||||
static const enum header_type bin_2_header_type[0x100] =
|
||||
{
|
||||
[0x80 | 0x7F] = HETY_INITIAL,
|
||||
[0x80 | 0x7E] = HETY_RETRY,
|
||||
[0x80 | 0x7D] = HETY_HANDSHAKE,
|
||||
[0x80 | 0x7C] = HETY_0RTT,
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
lsquic_iquic_parse_packet_in_long_begin (lsquic_packet_in_t *packet_in,
|
||||
size_t length, int is_server, struct packin_parse_state *state)
|
||||
{
|
||||
const unsigned char *p = packet_in->pi_data;
|
||||
const unsigned char *const end = p + length;
|
||||
lsquic_ver_tag_t tag;
|
||||
enum header_type header_type;
|
||||
unsigned dcil, scil;
|
||||
int verneg;
|
||||
unsigned char first_byte;
|
||||
const unsigned cid_len = 8;
|
||||
|
||||
if (length < 6)
|
||||
return -1;
|
||||
first_byte = *p++;
|
||||
|
||||
memcpy(&tag, p, 4);
|
||||
p += 4;
|
||||
verneg = 0 == tag;
|
||||
if (!verneg)
|
||||
{
|
||||
header_type = bin_2_header_type[ first_byte ];
|
||||
if (!header_type)
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
header_type = HETY_VERNEG;
|
||||
|
||||
packet_in->pi_header_type = header_type;
|
||||
|
||||
dcil = p[0] >> 4;
|
||||
if (dcil)
|
||||
dcil += 3;
|
||||
scil = p[0] & 0xF;
|
||||
if (scil)
|
||||
scil += 3;
|
||||
++p;
|
||||
|
||||
/* Chromium comments state that the client sends packets with destination
|
||||
* CID of 8 bytes and source CID of 0 bytes and the server does it the
|
||||
* other way around.
|
||||
*
|
||||
* XXX When IETF branch is merged, this check for Q044 will have to be
|
||||
* moved to the pf_parse_packet_in_finish().
|
||||
*/
|
||||
if (is_server)
|
||||
{
|
||||
if (!(dcil == cid_len && scil == 0))
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(dcil == 0 && scil == cid_len))
|
||||
return -1;
|
||||
}
|
||||
|
||||
const unsigned packet_len = 4;
|
||||
/* XXX This checks both packet length or the first version of the version
|
||||
* array in a version negotiation packet. This is because the sizes of
|
||||
* the packet number field and the version tag are the same. The check
|
||||
* will probably have to be split in the future.
|
||||
*/
|
||||
if (end - p < dcil + scil + packet_len)
|
||||
return -1;
|
||||
|
||||
memcpy(&packet_in->pi_conn_id, p, cid_len);
|
||||
p += cid_len;
|
||||
packet_in->pi_flags |= PI_CONN_ID;
|
||||
|
||||
packet_in->pi_packno = 0;
|
||||
|
||||
if (!verneg)
|
||||
{
|
||||
state->pps_p = p;
|
||||
state->pps_nbytes = packet_len;
|
||||
p += packet_len;
|
||||
packet_in->pi_quic_ver = 1;
|
||||
if (is_server || HETY_0RTT != header_type)
|
||||
packet_in->pi_nonce = 0;
|
||||
else
|
||||
{
|
||||
packet_in->pi_nonce = p - packet_in->pi_data;
|
||||
p += 32;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((end - p) & 3)
|
||||
return -1;
|
||||
state->pps_p = NULL;
|
||||
state->pps_nbytes = 0;
|
||||
packet_in->pi_quic_ver = p - packet_in->pi_data;
|
||||
p = packet_in->pi_data + length;
|
||||
packet_in->pi_nonce = 0;
|
||||
}
|
||||
|
||||
packet_in->pi_header_sz = p - packet_in->pi_data;
|
||||
packet_in->pi_frame_types = 0;
|
||||
packet_in->pi_data_sz = length;
|
||||
packet_in->pi_refcnt = 0;
|
||||
packet_in->pi_received = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
lsquic_iquic_parse_packet_in_short_begin (lsquic_packet_in_t *packet_in,
|
||||
size_t length, int is_server, struct packin_parse_state *state)
|
||||
{
|
||||
const unsigned char *p = packet_in->pi_data;
|
||||
const unsigned char *const pend = packet_in->pi_data + length;
|
||||
unsigned cid_len = 8; /* XXX this will need to be passed in */
|
||||
unsigned packet_len;
|
||||
|
||||
if ((*p & 0x30) != 0x30 || (*p & 3) == 3)
|
||||
return -1;
|
||||
|
||||
packet_len = 1 << (*p & 3);
|
||||
if (pend - p < 1 + cid_len + packet_len)
|
||||
return -1;
|
||||
|
||||
++p;
|
||||
|
||||
if (is_server)
|
||||
{
|
||||
memcpy(&packet_in->pi_conn_id, p, cid_len);
|
||||
p += cid_len;
|
||||
packet_in->pi_flags = PI_CONN_ID;
|
||||
}
|
||||
|
||||
/* We could read in the packet number here, but we choose to do it in
|
||||
* the finish() call instead.
|
||||
*/
|
||||
packet_in->pi_packno = 0;
|
||||
state->pps_p = p;
|
||||
state->pps_nbytes = packet_len;
|
||||
p += packet_len;
|
||||
|
||||
packet_in->pi_header_type = HETY_NOT_SET;
|
||||
packet_in->pi_quic_ver = 0;
|
||||
packet_in->pi_nonce = 0;
|
||||
packet_in->pi_header_sz = p - packet_in->pi_data;
|
||||
packet_in->pi_frame_types = 0;
|
||||
packet_in->pi_data_sz = length;
|
||||
packet_in->pi_refcnt = 0;
|
||||
packet_in->pi_received = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -56,4 +56,7 @@
|
|||
*/
|
||||
#define QTAG_NSTP TAG('N', 'S', 'T', 'P')
|
||||
|
||||
/* Stateless reset token. Used in Q044 and later. */
|
||||
#define QTAG_SRST TAG('S', 'R', 'S', 'T')
|
||||
|
||||
#endif
|
||||
|
|
|
@ -45,6 +45,10 @@
|
|||
#define MIN_RTO_DELAY 1000000 /* Microseconds */
|
||||
#define N_NACKS_BEFORE_RETX 3
|
||||
|
||||
#define packet_out_total_sz(p) \
|
||||
lsquic_packet_out_total_sz(ctl->sc_conn_pub->lconn, p)
|
||||
#define packet_out_sent_sz(p) \
|
||||
lsquic_packet_out_sent_sz(ctl->sc_conn_pub->lconn, p)
|
||||
|
||||
enum retx_mode {
|
||||
RETX_MODE_HANDSHAKE,
|
||||
|
@ -402,11 +406,11 @@ send_ctl_unacked_append (struct lsquic_send_ctl *ctl,
|
|||
struct lsquic_packet_out *packet_out)
|
||||
{
|
||||
TAILQ_INSERT_TAIL(&ctl->sc_unacked_packets, packet_out, po_next);
|
||||
ctl->sc_bytes_unacked_all += lsquic_packet_out_total_sz(packet_out);
|
||||
ctl->sc_bytes_unacked_all += packet_out_total_sz(packet_out);
|
||||
ctl->sc_n_in_flight_all += 1;
|
||||
if (packet_out->po_frame_types & QFRAME_RETRANSMITTABLE_MASK)
|
||||
{
|
||||
ctl->sc_bytes_unacked_retx += lsquic_packet_out_total_sz(packet_out);
|
||||
ctl->sc_bytes_unacked_retx += packet_out_total_sz(packet_out);
|
||||
++ctl->sc_n_in_flight_retx;
|
||||
}
|
||||
}
|
||||
|
@ -434,7 +438,7 @@ send_ctl_sched_Xpend_common (struct lsquic_send_ctl *ctl,
|
|||
{
|
||||
packet_out->po_flags |= PO_SCHED;
|
||||
++ctl->sc_n_scheduled;
|
||||
ctl->sc_bytes_scheduled += lsquic_packet_out_total_sz(packet_out);
|
||||
ctl->sc_bytes_scheduled += packet_out_total_sz(packet_out);
|
||||
lsquic_send_ctl_sanity_check(ctl);
|
||||
}
|
||||
|
||||
|
@ -465,7 +469,7 @@ send_ctl_sched_remove (struct lsquic_send_ctl *ctl,
|
|||
packet_out->po_flags &= ~PO_SCHED;
|
||||
assert(ctl->sc_n_scheduled);
|
||||
--ctl->sc_n_scheduled;
|
||||
ctl->sc_bytes_scheduled -= lsquic_packet_out_total_sz(packet_out);
|
||||
ctl->sc_bytes_scheduled -= packet_out_total_sz(packet_out);
|
||||
lsquic_send_ctl_sanity_check(ctl);
|
||||
}
|
||||
|
||||
|
@ -479,7 +483,7 @@ lsquic_send_ctl_sent_packet (lsquic_send_ctl_t *ctl,
|
|||
packet_out->po_packno, lsquic_frame_types_to_str(frames,
|
||||
sizeof(frames), packet_out->po_frame_types));
|
||||
if (account)
|
||||
ctl->sc_bytes_out -= lsquic_packet_out_total_sz(packet_out);
|
||||
ctl->sc_bytes_out -= packet_out_total_sz(packet_out);
|
||||
lsquic_senhist_add(&ctl->sc_senhist, packet_out->po_packno);
|
||||
send_ctl_unacked_append(ctl, packet_out);
|
||||
if (packet_out->po_frame_types & QFRAME_RETRANSMITTABLE_MASK)
|
||||
|
@ -540,7 +544,7 @@ send_ctl_handle_lost_packet (lsquic_send_ctl_t *ctl,
|
|||
unsigned packet_sz;
|
||||
|
||||
assert(ctl->sc_n_in_flight_all);
|
||||
packet_sz = lsquic_packet_out_sent_sz(packet_out);
|
||||
packet_sz = packet_out_sent_sz(packet_out);
|
||||
send_ctl_unacked_remove(ctl, packet_out, packet_sz);
|
||||
if (packet_out->po_flags & PO_ENCRYPTED)
|
||||
send_ctl_release_enc_data(ctl, packet_out);
|
||||
|
@ -740,7 +744,7 @@ lsquic_send_ctl_got_ack (lsquic_send_ctl_t *ctl,
|
|||
if (!now)
|
||||
now = lsquic_time_now();
|
||||
after_checks:
|
||||
packet_sz = lsquic_packet_out_sent_sz(packet_out);
|
||||
packet_sz = packet_out_sent_sz(packet_out);
|
||||
ctl->sc_largest_acked_packno = packet_out->po_packno;
|
||||
ctl->sc_largest_acked_sent_time = packet_out->po_sent;
|
||||
send_ctl_unacked_remove(ctl, packet_out, packet_sz);
|
||||
|
@ -856,7 +860,7 @@ lsquic_send_ctl_cleanup (lsquic_send_ctl_t *ctl)
|
|||
while ((packet_out = TAILQ_FIRST(&ctl->sc_unacked_packets)))
|
||||
{
|
||||
TAILQ_REMOVE(&ctl->sc_unacked_packets, packet_out, po_next);
|
||||
ctl->sc_bytes_unacked_all -= lsquic_packet_out_total_sz(packet_out);
|
||||
ctl->sc_bytes_unacked_all -= packet_out_total_sz(packet_out);
|
||||
lsquic_packet_out_destroy(packet_out, ctl->sc_enpub);
|
||||
--ctl->sc_n_in_flight_all;
|
||||
}
|
||||
|
@ -1008,7 +1012,7 @@ lsquic_send_ctl_sanity_check (const lsquic_send_ctl_t *ctl)
|
|||
count = 0, bytes = 0;
|
||||
TAILQ_FOREACH(packet_out, &ctl->sc_unacked_packets, po_next)
|
||||
{
|
||||
bytes += lsquic_packet_out_sent_sz(packet_out);
|
||||
bytes += packet_out_sent_sz(packet_out);
|
||||
++count;
|
||||
}
|
||||
assert(count == ctl->sc_n_in_flight_all);
|
||||
|
@ -1018,7 +1022,7 @@ lsquic_send_ctl_sanity_check (const lsquic_send_ctl_t *ctl)
|
|||
TAILQ_FOREACH(packet_out, &ctl->sc_scheduled_packets, po_next)
|
||||
{
|
||||
assert(packet_out->po_flags & PO_SCHED);
|
||||
bytes += lsquic_packet_out_total_sz(packet_out);
|
||||
bytes += packet_out_total_sz(packet_out);
|
||||
++count;
|
||||
}
|
||||
assert(count == ctl->sc_n_scheduled);
|
||||
|
@ -1090,7 +1094,7 @@ lsquic_send_ctl_next_packet_to_send (lsquic_send_ctl_t *ctl)
|
|||
}
|
||||
|
||||
send_ctl_sched_remove(ctl, packet_out);
|
||||
ctl->sc_bytes_out += lsquic_packet_out_total_sz(packet_out);
|
||||
ctl->sc_bytes_out += packet_out_total_sz(packet_out);
|
||||
return packet_out;
|
||||
}
|
||||
|
||||
|
@ -1100,7 +1104,7 @@ lsquic_send_ctl_delayed_one (lsquic_send_ctl_t *ctl,
|
|||
lsquic_packet_out_t *packet_out)
|
||||
{
|
||||
send_ctl_sched_prepend(ctl, packet_out);
|
||||
ctl->sc_bytes_out -= lsquic_packet_out_total_sz(packet_out);
|
||||
ctl->sc_bytes_out -= packet_out_total_sz(packet_out);
|
||||
LSQ_DEBUG("packet %"PRIu64" has been delayed", packet_out->po_packno);
|
||||
#if LSQUIC_SEND_STATS
|
||||
++ctl->sc_stats.n_delayed;
|
||||
|
@ -1139,7 +1143,7 @@ send_ctl_allocate_packet (lsquic_send_ctl_t *ctl, enum lsquic_packno_bits bits,
|
|||
|
||||
packet_out = lsquic_packet_out_new(&ctl->sc_enpub->enp_mm,
|
||||
ctl->sc_conn_pub->packet_out_malo,
|
||||
!(ctl->sc_flags & SC_TCID0), ctl->sc_pack_size, bits,
|
||||
!(ctl->sc_flags & SC_TCID0), ctl->sc_conn_pub->lconn, bits,
|
||||
ctl->sc_ver_neg->vn_tag, NULL);
|
||||
if (!packet_out)
|
||||
return NULL;
|
||||
|
|
|
@ -1369,8 +1369,10 @@ lsquic_stream_flush_threshold (const struct lsquic_stream *stream)
|
|||
flags = bits << POBIT_SHIFT;
|
||||
if (!(stream->conn_pub->lconn->cn_flags & LSCONN_TCID0))
|
||||
flags |= PO_CONN_ID;
|
||||
if (LSQUIC_STREAM_HANDSHAKE == stream->id)
|
||||
flags |= PO_LONGHEAD;
|
||||
|
||||
packet_header_sz = lsquic_po_header_length(flags);
|
||||
packet_header_sz = lsquic_po_header_length(stream->conn_pub->lconn, flags);
|
||||
stream_header_sz = stream->conn_pub->lconn->cn_pf
|
||||
->pf_calc_stream_frame_header_sz(stream->id, stream->tosend_off);
|
||||
|
||||
|
@ -1542,6 +1544,9 @@ stream_write_to_packet (struct frame_gen_ctx *fg_ctx, const size_t size)
|
|||
packet_out = get_packet[hsk](send_ctl, need_at_least, stream);
|
||||
if (!packet_out)
|
||||
return SWTP_STOP;
|
||||
if (hsk)
|
||||
packet_out->po_header_type = stream->tosend_off == 0
|
||||
? HETY_INITIAL : HETY_HANDSHAKE;
|
||||
|
||||
off = packet_out->po_data_sz;
|
||||
len = pf->pf_gen_stream_frame(
|
||||
|
|
|
@ -11,6 +11,10 @@ static const unsigned char version_tags[N_LSQVER][4] =
|
|||
[LSQVER_035] = { 'Q', '0', '3', '5', },
|
||||
[LSQVER_039] = { 'Q', '0', '3', '9', },
|
||||
[LSQVER_043] = { 'Q', '0', '4', '3', },
|
||||
[LSQVER_044] = { 'Q', '0', '4', '4', },
|
||||
#if LSQUIC_USE_Q098
|
||||
[LSQVER_098] = { 'Q', '0', '9', '8', },
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
@ -58,11 +62,15 @@ const char *const lsquic_ver2str[N_LSQVER] = {
|
|||
[LSQVER_035] = "Q035",
|
||||
[LSQVER_039] = "Q039",
|
||||
[LSQVER_043] = "Q043",
|
||||
[LSQVER_044] = "Q044",
|
||||
#if LSQUIC_USE_Q098
|
||||
[LSQVER_098] = "Q098",
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
gen_ver_tags (unsigned char *buf, size_t bufsz, unsigned version_bitmask)
|
||||
lsquic_gen_ver_tags (unsigned char *buf, size_t bufsz, unsigned version_bitmask)
|
||||
{
|
||||
unsigned n;
|
||||
lsquic_ver_tag_t tag;
|
||||
|
|
|
@ -17,6 +17,6 @@ lsquic_tag2ver (uint32_t ver_tag);
|
|||
extern const char *const lsquic_ver2str[];
|
||||
|
||||
int
|
||||
gen_ver_tags (unsigned char *buf, size_t bufsz, unsigned versions);
|
||||
lsquic_gen_ver_tags (unsigned char *buf, size_t bufsz, unsigned versions);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -11,8 +11,10 @@
|
|||
#include "lsquic_int_types.h"
|
||||
#include "lsquic_packet_common.h"
|
||||
#include "lsquic_parse.h"
|
||||
#include "lsquic_parse_common.h"
|
||||
#include "lsquic_packet_in.h"
|
||||
#include "lsquic_engine_public.h"
|
||||
#include "lsquic_version.h"
|
||||
|
||||
|
||||
struct parse_packet_in_test
|
||||
|
@ -22,8 +24,7 @@ struct parse_packet_in_test
|
|||
unsigned char ppit_buf[0x100];
|
||||
unsigned ppit_bufsz;
|
||||
int ppit_is_server;
|
||||
const struct parse_funcs *
|
||||
ppit_pf;
|
||||
enum lsquic_version ppit_version;
|
||||
/* Output */
|
||||
int ppit_retval;
|
||||
int ppit_pi_flags;
|
||||
|
@ -49,7 +50,7 @@ static const struct parse_packet_in_test tests[] = {
|
|||
},
|
||||
.ppit_bufsz = 1 + 8 + 4 + 1 + 7,
|
||||
.ppit_is_server = 1,
|
||||
.ppit_pf = select_pf_by_ver(LSQVER_035),
|
||||
.ppit_version = LSQVER_035,
|
||||
.ppit_retval = 0,
|
||||
.ppit_pi_flags = PI_CONN_ID,
|
||||
.ppit_conn_id = 0x5500000000000000,
|
||||
|
@ -72,7 +73,7 @@ static const struct parse_packet_in_test tests[] = {
|
|||
},
|
||||
.ppit_bufsz = 1 + 8 + 4 + 2 + 7,
|
||||
.ppit_is_server = 1,
|
||||
.ppit_pf = select_pf_by_ver(LSQVER_035),
|
||||
.ppit_version = LSQVER_035,
|
||||
.ppit_retval = 0,
|
||||
.ppit_pi_flags = PI_CONN_ID,
|
||||
.ppit_conn_id = 0x5500000000000000,
|
||||
|
@ -95,7 +96,7 @@ static const struct parse_packet_in_test tests[] = {
|
|||
},
|
||||
.ppit_bufsz = 1 + 8 + 4 + 4 + 7,
|
||||
.ppit_is_server = 1,
|
||||
.ppit_pf = select_pf_by_ver(LSQVER_035),
|
||||
.ppit_version = LSQVER_035,
|
||||
.ppit_retval = 0,
|
||||
.ppit_pi_flags = PI_CONN_ID,
|
||||
.ppit_conn_id = 0x5500000000000000,
|
||||
|
@ -118,7 +119,7 @@ static const struct parse_packet_in_test tests[] = {
|
|||
},
|
||||
.ppit_bufsz = 1 + 8 + 4 + 6 + 7,
|
||||
.ppit_is_server = 1,
|
||||
.ppit_pf = select_pf_by_ver(LSQVER_035),
|
||||
.ppit_version = LSQVER_035,
|
||||
.ppit_retval = 0,
|
||||
.ppit_pi_flags = PI_CONN_ID,
|
||||
.ppit_conn_id = 0x5500000000000000,
|
||||
|
@ -138,7 +139,7 @@ static const struct parse_packet_in_test tests[] = {
|
|||
},
|
||||
.ppit_bufsz = 1 + 0 + 4 + 1 + 7,
|
||||
.ppit_is_server = 1,
|
||||
.ppit_pf = select_pf_by_ver(LSQVER_035),
|
||||
.ppit_version = LSQVER_035,
|
||||
.ppit_retval = 0,
|
||||
.ppit_pi_flags = 0,
|
||||
.ppit_conn_id = 0,
|
||||
|
@ -157,7 +158,7 @@ static const struct parse_packet_in_test tests[] = {
|
|||
},
|
||||
.ppit_bufsz = 1 + 0 + 0 + 1 + 7,
|
||||
.ppit_is_server = 1,
|
||||
.ppit_pf = select_pf_by_ver(LSQVER_035),
|
||||
.ppit_version = LSQVER_035,
|
||||
.ppit_retval = 0,
|
||||
.ppit_pi_flags = 0,
|
||||
.ppit_conn_id = 0,
|
||||
|
@ -179,7 +180,7 @@ static const struct parse_packet_in_test tests[] = {
|
|||
},
|
||||
.ppit_bufsz = 1 + 8 + 4,
|
||||
.ppit_is_server = 1,
|
||||
.ppit_pf = select_pf_by_ver(LSQVER_035),
|
||||
.ppit_version = LSQVER_035,
|
||||
.ppit_retval = -1,
|
||||
},
|
||||
|
||||
|
@ -198,7 +199,7 @@ static const struct parse_packet_in_test tests[] = {
|
|||
},
|
||||
.ppit_bufsz = 1 + 8 + 32+ 2 + 7,
|
||||
.ppit_is_server = 0,
|
||||
.ppit_pf = select_pf_by_ver(LSQVER_035),
|
||||
.ppit_version = LSQVER_035,
|
||||
.ppit_retval = 0,
|
||||
.ppit_pi_flags = PI_CONN_ID,
|
||||
.ppit_conn_id = 0x5500000000000000,
|
||||
|
@ -223,7 +224,7 @@ static const struct parse_packet_in_test tests[] = {
|
|||
},
|
||||
.ppit_bufsz = 1 + 8 + 32+ 1 + 7,
|
||||
.ppit_is_server = 0,
|
||||
.ppit_pf = select_pf_by_ver(LSQVER_035),
|
||||
.ppit_version = LSQVER_035,
|
||||
.ppit_retval = 0,
|
||||
.ppit_pi_flags = PI_CONN_ID,
|
||||
.ppit_conn_id = 0x5500000000000000,
|
||||
|
@ -247,7 +248,7 @@ static const struct parse_packet_in_test tests[] = {
|
|||
},
|
||||
.ppit_bufsz = 1 + 8 + 4 + 4 + 7,
|
||||
.ppit_is_server = 1,
|
||||
.ppit_pf = select_pf_by_ver(LSQVER_035),
|
||||
.ppit_version = LSQVER_035,
|
||||
.ppit_retval = 0,
|
||||
.ppit_pi_flags = PI_CONN_ID,
|
||||
.ppit_conn_id = 0x5500000000000000,
|
||||
|
@ -270,7 +271,7 @@ static const struct parse_packet_in_test tests[] = {
|
|||
},
|
||||
.ppit_bufsz = 1 + 8 + 4 + 1 + 7,
|
||||
.ppit_is_server = 1,
|
||||
.ppit_pf = select_pf_by_ver(LSQVER_035),
|
||||
.ppit_version = LSQVER_035,
|
||||
.ppit_retval = 0,
|
||||
.ppit_pi_flags = PI_CONN_ID,
|
||||
.ppit_conn_id = 0x5500000000000000,
|
||||
|
@ -294,7 +295,7 @@ static const struct parse_packet_in_test tests[] = {
|
|||
},
|
||||
.ppit_bufsz = 1 + 8 + 4 + 6 + 7,
|
||||
.ppit_is_server = 1,
|
||||
.ppit_pf = select_pf_by_ver(LSQVER_035),
|
||||
.ppit_version = LSQVER_035,
|
||||
.ppit_retval = 0,
|
||||
.ppit_pi_flags = PI_CONN_ID,
|
||||
.ppit_conn_id = 0x5500000000000000,
|
||||
|
@ -315,7 +316,7 @@ static const struct parse_packet_in_test tests[] = {
|
|||
},
|
||||
.ppit_bufsz = 1 + 8 + 8,
|
||||
.ppit_is_server = 0,
|
||||
.ppit_pf = select_pf_by_ver(LSQVER_035),
|
||||
.ppit_version = LSQVER_035,
|
||||
.ppit_retval = 0,
|
||||
.ppit_pi_flags = PI_CONN_ID,
|
||||
.ppit_conn_id = 0x5500000000000000,
|
||||
|
@ -340,7 +341,7 @@ static const struct parse_packet_in_test tests[] = {
|
|||
},
|
||||
.ppit_bufsz = 1 + 8 + 4 + 1 + 7,
|
||||
.ppit_is_server = 1,
|
||||
.ppit_pf = select_pf_by_ver(LSQVER_039),
|
||||
.ppit_version = LSQVER_039,
|
||||
.ppit_retval = 0,
|
||||
.ppit_pi_flags = PI_CONN_ID,
|
||||
.ppit_conn_id = 0x5500000000000000,
|
||||
|
@ -363,7 +364,7 @@ static const struct parse_packet_in_test tests[] = {
|
|||
},
|
||||
.ppit_bufsz = 1 + 8 + 4 + 2 + 7,
|
||||
.ppit_is_server = 1,
|
||||
.ppit_pf = select_pf_by_ver(LSQVER_039),
|
||||
.ppit_version = LSQVER_039,
|
||||
.ppit_retval = 0,
|
||||
.ppit_pi_flags = PI_CONN_ID,
|
||||
.ppit_conn_id = 0x5500000000000000,
|
||||
|
@ -386,7 +387,7 @@ static const struct parse_packet_in_test tests[] = {
|
|||
},
|
||||
.ppit_bufsz = 1 + 8 + 4 + 4 + 7,
|
||||
.ppit_is_server = 1,
|
||||
.ppit_pf = select_pf_by_ver(LSQVER_039),
|
||||
.ppit_version = LSQVER_039,
|
||||
.ppit_retval = 0,
|
||||
.ppit_pi_flags = PI_CONN_ID,
|
||||
.ppit_conn_id = 0x5500000000000000,
|
||||
|
@ -409,7 +410,7 @@ static const struct parse_packet_in_test tests[] = {
|
|||
},
|
||||
.ppit_bufsz = 1 + 8 + 4 + 6 + 7,
|
||||
.ppit_is_server = 1,
|
||||
.ppit_pf = select_pf_by_ver(LSQVER_039),
|
||||
.ppit_version = LSQVER_039,
|
||||
.ppit_retval = 0,
|
||||
.ppit_pi_flags = PI_CONN_ID,
|
||||
.ppit_conn_id = 0x5500000000000000,
|
||||
|
@ -429,7 +430,7 @@ static const struct parse_packet_in_test tests[] = {
|
|||
},
|
||||
.ppit_bufsz = 1 + 0 + 4 + 1 + 7,
|
||||
.ppit_is_server = 1,
|
||||
.ppit_pf = select_pf_by_ver(LSQVER_039),
|
||||
.ppit_version = LSQVER_039,
|
||||
.ppit_retval = 0,
|
||||
.ppit_pi_flags = 0,
|
||||
.ppit_conn_id = 0,
|
||||
|
@ -448,7 +449,7 @@ static const struct parse_packet_in_test tests[] = {
|
|||
},
|
||||
.ppit_bufsz = 1 + 0 + 0 + 1 + 7,
|
||||
.ppit_is_server = 1,
|
||||
.ppit_pf = select_pf_by_ver(LSQVER_039),
|
||||
.ppit_version = LSQVER_039,
|
||||
.ppit_retval = 0,
|
||||
.ppit_pi_flags = 0,
|
||||
.ppit_conn_id = 0,
|
||||
|
@ -470,7 +471,7 @@ static const struct parse_packet_in_test tests[] = {
|
|||
},
|
||||
.ppit_bufsz = 1 + 8 + 4,
|
||||
.ppit_is_server = 1,
|
||||
.ppit_pf = select_pf_by_ver(LSQVER_039),
|
||||
.ppit_version = LSQVER_039,
|
||||
.ppit_retval = -1,
|
||||
},
|
||||
|
||||
|
@ -489,7 +490,7 @@ static const struct parse_packet_in_test tests[] = {
|
|||
},
|
||||
.ppit_bufsz = 1 + 8 + 32+ 2 + 7,
|
||||
.ppit_is_server = 0,
|
||||
.ppit_pf = select_pf_by_ver(LSQVER_039),
|
||||
.ppit_version = LSQVER_039,
|
||||
.ppit_retval = 0,
|
||||
.ppit_pi_flags = PI_CONN_ID,
|
||||
.ppit_conn_id = 0x5500000000000000,
|
||||
|
@ -514,7 +515,7 @@ static const struct parse_packet_in_test tests[] = {
|
|||
},
|
||||
.ppit_bufsz = 1 + 8 + 32+ 1 + 7,
|
||||
.ppit_is_server = 0,
|
||||
.ppit_pf = select_pf_by_ver(LSQVER_039),
|
||||
.ppit_version = LSQVER_039,
|
||||
.ppit_retval = 0,
|
||||
.ppit_pi_flags = PI_CONN_ID,
|
||||
.ppit_conn_id = 0x5500000000000000,
|
||||
|
@ -538,7 +539,7 @@ static const struct parse_packet_in_test tests[] = {
|
|||
},
|
||||
.ppit_bufsz = 1 + 8 + 4 + 4 + 7,
|
||||
.ppit_is_server = 1,
|
||||
.ppit_pf = select_pf_by_ver(LSQVER_039),
|
||||
.ppit_version = LSQVER_039,
|
||||
.ppit_retval = 0,
|
||||
.ppit_pi_flags = PI_CONN_ID,
|
||||
.ppit_conn_id = 0x5500000000000000,
|
||||
|
@ -561,7 +562,7 @@ static const struct parse_packet_in_test tests[] = {
|
|||
},
|
||||
.ppit_bufsz = 1 + 8 + 4 + 1 + 7,
|
||||
.ppit_is_server = 1,
|
||||
.ppit_pf = select_pf_by_ver(LSQVER_039),
|
||||
.ppit_version = LSQVER_039,
|
||||
.ppit_retval = 0,
|
||||
.ppit_pi_flags = PI_CONN_ID,
|
||||
.ppit_conn_id = 0x5500000000000000,
|
||||
|
@ -585,7 +586,7 @@ static const struct parse_packet_in_test tests[] = {
|
|||
},
|
||||
.ppit_bufsz = 1 + 8 + 4 + 6 + 7,
|
||||
.ppit_is_server = 1,
|
||||
.ppit_pf = select_pf_by_ver(LSQVER_039),
|
||||
.ppit_version = LSQVER_039,
|
||||
.ppit_retval = 0,
|
||||
.ppit_pi_flags = PI_CONN_ID,
|
||||
.ppit_conn_id = 0x5500000000000000,
|
||||
|
@ -606,7 +607,7 @@ static const struct parse_packet_in_test tests[] = {
|
|||
},
|
||||
.ppit_bufsz = 1 + 8 + 8,
|
||||
.ppit_is_server = 0,
|
||||
.ppit_pf = select_pf_by_ver(LSQVER_039),
|
||||
.ppit_version = LSQVER_039,
|
||||
.ppit_retval = 0,
|
||||
.ppit_pi_flags = PI_CONN_ID,
|
||||
.ppit_conn_id = 0x5500000000000000,
|
||||
|
@ -616,6 +617,83 @@ static const struct parse_packet_in_test tests[] = {
|
|||
.ppit_quic_ver = 1 + 8,
|
||||
.ppit_nonce = 0,
|
||||
},
|
||||
|
||||
{ .ppit_lineno = __LINE__,
|
||||
.ppit_buf = {
|
||||
/* Flags: */ 0x30,
|
||||
/* CID: */ 0x01, 0x02, 0x03, 0x04, 0x50, 0x60, 0x70, 0x80,
|
||||
/* Packet number: */0x9B,
|
||||
/* Payload: */ 'P', 'A', 'Y', 'L', 'O', 'A', 'D',
|
||||
},
|
||||
.ppit_bufsz = 1 + 8 + 1 + 7,
|
||||
.ppit_is_server = 1,
|
||||
.ppit_version = LSQVER_044,
|
||||
.ppit_retval = 0,
|
||||
.ppit_pi_flags = PI_CONN_ID,
|
||||
.ppit_conn_id = 0x8070605004030201,
|
||||
.ppit_packno = 0x9B,
|
||||
.ppit_header_sz = 1 + 8 + 1,
|
||||
.ppit_data_sz = 1 + 8 + 1 + 7,
|
||||
.ppit_quic_ver = 0,
|
||||
.ppit_nonce = 0,
|
||||
},
|
||||
|
||||
{ .ppit_lineno = __LINE__,
|
||||
.ppit_buf = {
|
||||
/* Flags: */ 0x32,
|
||||
/* CID: */ 0x01, 0x02, 0x03, 0x04, 0x50, 0x60, 0x70, 0x80,
|
||||
/* Packet number: */0x9B, 0x03, 0x02, 0x01,
|
||||
/* Payload: */ 'P', 'A', 'Y', 'L', 'O', 'A', 'D',
|
||||
},
|
||||
.ppit_bufsz = 1 + 8 + 4 + 7,
|
||||
.ppit_is_server = 1,
|
||||
.ppit_version = LSQVER_044,
|
||||
.ppit_retval = 0,
|
||||
.ppit_pi_flags = PI_CONN_ID,
|
||||
.ppit_conn_id = 0x8070605004030201,
|
||||
.ppit_packno = 0x9B030201,
|
||||
.ppit_header_sz = 1 + 8 + 4,
|
||||
.ppit_data_sz = 1 + 8 + 4 + 7,
|
||||
.ppit_quic_ver = 0,
|
||||
.ppit_nonce = 0,
|
||||
},
|
||||
|
||||
{ .ppit_lineno = __LINE__,
|
||||
.ppit_buf = {
|
||||
/* Flags: */ 0x30
|
||||
| 0x3 /* <--- Invalid type */,
|
||||
/* CID: */ 0x01, 0x02, 0x03, 0x04, 0x50, 0x60, 0x70, 0x80,
|
||||
/* Packet number: */0x9B,
|
||||
/* Payload: */ 'P', 'A', 'Y', 'L', 'O', 'A', 'D',
|
||||
},
|
||||
.ppit_bufsz = 1 + 8 + 1 + 7,
|
||||
.ppit_is_server = 1,
|
||||
.ppit_version = LSQVER_044,
|
||||
.ppit_retval = -1,
|
||||
},
|
||||
|
||||
{ .ppit_lineno = __LINE__,
|
||||
.ppit_buf = {
|
||||
/* Type: */ 0xFF /* Initial */,
|
||||
/* Version: */ 'Q', '0', '4', '4',
|
||||
/* DCIL/SCIL: */ 0x5 /* DCIL */ << 4 | 0x0 /* SCIL */,
|
||||
/* CID: */ 0x01, 0x02, 0x03, 0x04, 0x50, 0x60, 0x70, 0x80,
|
||||
/* Packet number: */0x21, 0x22, 0x23, 0x34,
|
||||
/* Payload: */ 'P', 'A', 'Y', 'L', 'O', 'A', 'D',
|
||||
},
|
||||
.ppit_bufsz = 1 + 4 + 1 + 8 + 4 + 7,
|
||||
.ppit_is_server = 1,
|
||||
.ppit_version = LSQVER_044,
|
||||
.ppit_retval = 0,
|
||||
.ppit_pi_flags = PI_CONN_ID,
|
||||
.ppit_conn_id = 0x8070605004030201,
|
||||
.ppit_packno = 0x21222334,
|
||||
.ppit_header_sz = 1 + 4 + 1 + 8 + 4,
|
||||
.ppit_data_sz = 1 + 4 + 1 + 8 + 4 + 7,
|
||||
.ppit_quic_ver = 1,
|
||||
.ppit_nonce = 0,
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -630,10 +708,47 @@ run_ppi_test (struct lsquic_mm *mm, const struct parse_packet_in_test *ppit)
|
|||
packet_in->pi_data = lsquic_mm_get_1370(mm);
|
||||
packet_in->pi_flags |= PI_OWN_DATA;
|
||||
memcpy(packet_in->pi_data, ppit->ppit_buf, ppit->ppit_bufsz);
|
||||
s = parse_packet_in_begin(packet_in, ppit->ppit_bufsz, ppit->ppit_is_server, &ppstate);
|
||||
|
||||
/* Server should be able to differentiate different header formats
|
||||
* because it expect the connection ID to be there, while the client
|
||||
* needs help.
|
||||
*/
|
||||
if (ppit->ppit_is_server &&
|
||||
/* In addition, some tests verify parsing of GQUIC packets in
|
||||
* server mode where there is no connection ID. This is for
|
||||
* completeness and does not represent a real-life scenario,
|
||||
* as the server will always require the client to send the
|
||||
* connection ID.
|
||||
*/
|
||||
!(!(ppit->ppit_pi_flags & PI_CONN_ID)
|
||||
&& ppit->ppit_version < LSQVER_044))
|
||||
s = lsquic_parse_packet_in_begin(packet_in, ppit->ppit_bufsz,
|
||||
ppit->ppit_is_server, &ppstate);
|
||||
else if (ppit->ppit_version < LSQVER_044)
|
||||
s = lsquic_gquic_parse_packet_in_begin(packet_in, ppit->ppit_bufsz,
|
||||
ppit->ppit_is_server, &ppstate);
|
||||
else
|
||||
s = lsquic_iquic_parse_packet_in_begin(packet_in, ppit->ppit_bufsz,
|
||||
ppit->ppit_is_server, &ppstate);
|
||||
|
||||
assert(s == ppit->ppit_retval);
|
||||
if (0 == s)
|
||||
ppit->ppit_pf->pf_parse_packet_in_finish(packet_in, &ppstate);
|
||||
{
|
||||
const struct parse_funcs *pf;
|
||||
if (ppit->ppit_quic_ver && ppit->ppit_is_server /* Server packets
|
||||
with version are version negotiation packets. */)
|
||||
{
|
||||
uint32_t tag;
|
||||
enum lsquic_version ver;
|
||||
assert(packet_in->pi_quic_ver);
|
||||
memcpy(&tag, packet_in->pi_data + packet_in->pi_quic_ver, 4);
|
||||
ver = lsquic_tag2ver(tag);
|
||||
assert((enum lsquic_version) -1 != ver);
|
||||
assert(ver == ppit->ppit_version);
|
||||
}
|
||||
pf = select_pf_by_ver(ppit->ppit_version);
|
||||
pf->pf_parse_packet_in_finish(packet_in, &ppstate);
|
||||
}
|
||||
|
||||
if (0 == s)
|
||||
{
|
||||
|
|
|
@ -8,10 +8,12 @@
|
|||
#endif
|
||||
|
||||
#include "lsquic_types.h"
|
||||
#include "lsquic.h"
|
||||
#include "lsquic_alarmset.h"
|
||||
#include "lsquic_packet_common.h"
|
||||
#include "lsquic_packet_out.h"
|
||||
#include "lsquic_conn.h"
|
||||
#include "lsquic_parse.h"
|
||||
#include "lsquic.h"
|
||||
|
||||
struct test {
|
||||
/* Inputs. */
|
||||
|
@ -232,11 +234,23 @@ run_test (int i)
|
|||
{
|
||||
const struct test *const test = &tests[i];
|
||||
|
||||
struct lsquic_packet_out packet_out =
|
||||
{
|
||||
.po_flags = (test->cid ? PO_CONN_ID : 0)
|
||||
| (test->ver.val ? PO_VERSION : 0)
|
||||
| (test->nonce ? PO_NONCE: 0)
|
||||
,
|
||||
.po_nonce = (unsigned char *) test->nonce,
|
||||
.po_ver_tag = test->ver.val,
|
||||
.po_packno = test->packno,
|
||||
};
|
||||
lsquic_packet_out_set_packno_bits(&packet_out, test->bits);
|
||||
|
||||
struct lsquic_conn lconn = { .cn_cid = test->cid, };
|
||||
|
||||
unsigned char out[QUIC_MAX_PUBHDR_SZ];
|
||||
int len = test->pf->pf_gen_reg_pkt_header(out, sizeof(out),
|
||||
(test->cid ? &test->cid : NULL),
|
||||
(test->ver.val ? &test->ver.val : NULL),
|
||||
(unsigned char *) test->nonce, test->packno, test->bits);
|
||||
int len = test->pf->pf_gen_reg_pkt_header(&lconn, &packet_out, out,
|
||||
sizeof(out));
|
||||
|
||||
assert(("Packet length is correct", len == test->len));
|
||||
|
||||
|
|
|
@ -62,6 +62,7 @@ lsquic_stream_tosend_sz (const lsquic_stream_t *stream)
|
|||
|
||||
static int make_complex_packet(unsigned char *pkt_buf, int max_buf_len)
|
||||
{
|
||||
#if 0 /* What is this function testing? Seems useless. */
|
||||
unsigned char *p = pkt_buf;
|
||||
unsigned char *const pend = p + 1500;
|
||||
lsquic_stream_t *stream = lsquic_stream_new(12345, NULL, NULL, NULL, 0, 0);
|
||||
|
@ -90,6 +91,8 @@ static int make_complex_packet(unsigned char *pkt_buf, int max_buf_len)
|
|||
free(stream);
|
||||
|
||||
return p - pkt_buf;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -13,12 +13,12 @@
|
|||
#include "lsquic_alarmset.h"
|
||||
#include "lsquic_packet_common.h"
|
||||
#include "lsquic_parse.h"
|
||||
#include "lsquic_parse_common.h"
|
||||
#include "lsquic_mm.h"
|
||||
#include "lsquic_packet_in.h"
|
||||
#include "lsquic_engine_public.h"
|
||||
#include "lsquic_version.h"
|
||||
|
||||
static const struct parse_funcs *const pf = select_pf_by_ver(LSQVER_035);
|
||||
|
||||
|
||||
/* The struct is used to test both generation and parsing of version
|
||||
|
@ -100,7 +100,7 @@ test_parsing_ver_nego (const struct gen_ver_nego_test *gvnt)
|
|||
packet_in->pi_data = lsquic_mm_get_1370(&mm);
|
||||
packet_in->pi_flags |= PI_OWN_DATA;
|
||||
memcpy(packet_in->pi_data, gvnt->gvnt_buf, gvnt->gvnt_len);
|
||||
s = parse_packet_in_begin(packet_in, gvnt->gvnt_len, 0, &ppstate);
|
||||
s = lsquic_parse_packet_in_begin(packet_in, gvnt->gvnt_len, 0, &ppstate);
|
||||
assert(s == 0);
|
||||
|
||||
for (s = packet_in_ver_first(packet_in, &vi, &ver_tag); s;
|
||||
|
@ -119,32 +119,12 @@ test_parsing_ver_nego (const struct gen_ver_nego_test *gvnt)
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
run_gvnt (int i)
|
||||
{
|
||||
const struct gen_ver_nego_test *const gvnt = &tests[i];
|
||||
|
||||
unsigned char out[0x40];
|
||||
assert(sizeof(out) <= sizeof(gvnt->gvnt_buf)); /* Internal sanity check */
|
||||
int len = pf->pf_gen_ver_nego_pkt(out, gvnt->gvnt_bufsz, gvnt->gvnt_cid,
|
||||
gvnt->gvnt_versions);
|
||||
|
||||
assert(("Packet length is correct", len == gvnt->gvnt_len));
|
||||
|
||||
if (gvnt->gvnt_len > 0)
|
||||
{
|
||||
assert(("Packet contents are correct",
|
||||
0 == memcmp(out, gvnt->gvnt_buf, gvnt->gvnt_len)));
|
||||
test_parsing_ver_nego(gvnt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i)
|
||||
run_gvnt(i);
|
||||
if (tests[i].gvnt_len > 0)
|
||||
test_parsing_ver_nego(&tests[i]);
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue