Release 2.24.0

- [FEATURE] QUIC and HTTP/3 Internet Draft 31 support.  Drop ID-30
  and ID-31 support.
- [BUGFIX] Divide-by-zero in newly enabled conn stats code when no
  packets were sent.
- [BUGFIX] Memory leak in gQUIC client when server hello cannot be
  parsed.
- [BUGFIX] Server Initial packet size calculation.
- Log user-agent and CONN_CLOSE reason when peer reports error.
- Example programs: Specify ALPN for echo and md5 clients and servers
  (issue #184).
- Example programs: Don't add "QUIC_" prefix to lines in keylog file
  (issue #185).
- http_server: Fix fd leak in preadv mode; fix preadv() usage when
  reading from disk.
This commit is contained in:
Dmitri Tikhonov 2020-10-28 08:10:17 -04:00
parent 078f53798c
commit 4429f8ea1e
33 changed files with 249 additions and 117 deletions

View file

@ -1,3 +1,20 @@
2020-10-28
- 2.24.0
- [FEATURE] QUIC and HTTP/3 Internet Draft 31 support. Drop ID-30
and ID-31 support.
- [BUGFIX] Divide-by-zero in newly enabled conn stats code when no
packets were sent.
- [BUGFIX] Memory leak in gQUIC client when server hello cannot be
parsed.
- [BUGFIX] Server Initial packet size calculation.
- Log user-agent and CONN_CLOSE reason when peer reports error.
- Example programs: Specify ALPN for echo and md5 clients and servers
(issue #184).
- Example programs: Don't add "QUIC_" prefix to lines in keylog file
(issue #185).
- http_server: Fix fd leak in preadv mode; fix preadv() usage when
reading from disk.
2020-10-22
- 2.23.3
- [BUGFIX] Update packetization threshold when writing to stream

View file

@ -14,8 +14,7 @@ distribution is used in our own products: LiteSpeed Web Server, LiteSpeed ADC,
and OpenLiteSpeed.
Currently supported QUIC versions are Q043, Q046, Q050, ID-27, ID-28, ID-29,
ID-30, and ID-31. Support for newer versions is added soon after they
are released.
and ID-32. Support for newer versions is added soon after they are released.
Documentation
-------------

View file

@ -213,6 +213,7 @@ main (int argc, char **argv)
TAILQ_INIT(&sports);
prog_init(&prog, 0, &sports, &client_echo_stream_if, &client_ctx);
prog.prog_api.ea_alpn = "echo";
while (-1 != (opt = getopt(argc, argv, PROG_OPTS "h")))
{

View file

@ -20,6 +20,8 @@
#include "lsquic.h"
#include "test_common.h"
#include "../src/liblsquic/lsquic_hash.h"
#include "test_cert.h"
#include "prog.h"
#include "../src/liblsquic/lsquic_logger.h"
@ -218,6 +220,7 @@ main (int argc, char **argv)
}
}
add_alpn("echo");
if (0 != prog_prep(&prog))
{
LSQ_ERROR("could not prep");

View file

@ -582,13 +582,39 @@ my_preadv (void *user_data, const struct iovec *iov, int iovcnt)
{
#if HAVE_PREADV
lsquic_stream_ctx_t *const st_h = user_data;
return preadv(st_h->file_fd, iov, iovcnt, st_h->written);
ssize_t nread = preadv(st_h->file_fd, iov, iovcnt, st_h->written);
LSQ_DEBUG("%s: wrote %zd bytes", __func__, (size_t) nread);
return nread;
#else
return -1;
#endif
}
static size_t
pwritev_fallback_read (void *lsqr_ctx, void *buf, size_t count)
{
lsquic_stream_ctx_t *const st_h = lsqr_ctx;
struct iovec iov;
size_t ntoread;
ntoread = st_h->file_size - st_h->written;
if (ntoread > count)
count = ntoread;
iov.iov_base = buf;
iov.iov_len = count;
return my_preadv(lsqr_ctx, &iov, 1);
}
static size_t
pwritev_fallback_size (void *lsqr_ctx)
{
lsquic_stream_ctx_t *const st_h = lsqr_ctx;
return st_h->file_size - st_h->written;
}
static void
http_server_on_write (lsquic_stream_t *stream, lsquic_stream_ctx_t *st_h)
{
@ -624,11 +650,17 @@ http_server_on_write (lsquic_stream_t *stream, lsquic_stream_ctx_t *st_h)
to_write = s_pwritev;
nw = lsquic_stream_pwritev(stream, my_preadv, st_h, to_write);
if (nw == 0)
goto use_reader;
{
struct lsquic_reader reader = {
.lsqr_read = pwritev_fallback_read,
.lsqr_size = pwritev_fallback_size,
.lsqr_ctx = st_h,
};
nw = lsquic_stream_writef(stream, &reader);
}
}
else
{
use_reader:
nw = lsquic_stream_writef(stream, &st_h->reader);
}
if (nw < 0)
@ -1006,6 +1038,8 @@ http_server_on_close (lsquic_stream_t *stream, lsquic_stream_ctx_t *st_h)
free(st_h->req_path);
if (st_h->reader.lsqr_ctx)
destroy_lsquic_reader_ctx(st_h->reader.lsqr_ctx);
if (s_pwritev)
close(st_h->file_fd);
if (st_h->req)
interop_server_hset_destroy(st_h->req);
free(st_h);

View file

@ -460,6 +460,7 @@ main (int argc, char **argv)
TAILQ_INIT(&sports);
prog_init(&prog, 0, &sports, &client_file_stream_if, &client_ctx);
prog.prog_api.ea_alpn = "md5";
while (-1 != (opt = getopt(argc, argv, PROG_OPTS "bhr:f:p:")))
{

View file

@ -19,6 +19,8 @@
#include "lsquic.h"
#include "test_common.h"
#include "../src/liblsquic/lsquic_hash.h"
#include "test_cert.h"
#include "prog.h"
#include "../src/liblsquic/lsquic_logger.h"
@ -325,6 +327,7 @@ main (int argc, char **argv)
}
}
add_alpn("md5");
if (0 != prog_prep(&prog))
{
LSQ_ERROR("could not prep");

View file

@ -610,11 +610,6 @@ keylog_open (void *ctx, lsquic_conn_t *conn)
static void
keylog_log_line (void *handle, const char *line)
{
size_t len;
len = strlen(line);
if (len < sizeof("QUIC_") - 1 || strncmp(line, "QUIC_", 5))
fputs("QUIC_", handle);
fputs(line, handle);
fputs("\n", handle);
fflush(handle);

View file

@ -58,13 +58,9 @@ developed by the IETF. Both types are included in a single enum:
IETF QUIC version ID 29
.. member:: LSQVER_ID30
.. member:: LSQVER_ID32
IETF QUIC version ID 30; this version is deprecated.
.. member:: LSQVER_ID31
IETF QUIC version ID 31
IETF QUIC version ID 32
.. member:: N_LSQVER

View file

@ -24,9 +24,9 @@ copyright = u'2020, LiteSpeed Technologies'
author = u'LiteSpeed Technologies'
# The short X.Y version
version = u'2.23'
version = u'2.24'
# The full version, including alpha/beta/rc tags
release = u'2.23.3'
release = u'2.24.0'
# -- General configuration ---------------------------------------------------

View file

@ -17,7 +17,7 @@ Most of the code in this distribution has been used in our own products
since 2017.
Currently supported QUIC versions are Q043, Q046, Q050, ID-27, ID-28,
ID-29, ID-30, and ID-31.
ID-29, and ID-32.
Support for newer versions will be added soon after they are released.
LSQUIC is licensed under the `MIT License`_; see LICENSE in the source

View file

@ -24,8 +24,8 @@ extern "C" {
#endif
#define LSQUIC_MAJOR_VERSION 2
#define LSQUIC_MINOR_VERSION 23
#define LSQUIC_PATCH_VERSION 3
#define LSQUIC_MINOR_VERSION 24
#define LSQUIC_PATCH_VERSION 0
/**
* Engine flags:
@ -92,14 +92,9 @@ enum lsquic_version
LSQVER_ID29,
/**
* IETF QUIC Draft-30
* IETF QUIC Draft-32
*/
LSQVER_ID30,
/**
* IETF QUIC Draft-31
*/
LSQVER_ID31,
LSQVER_ID32,
/**
* Special version to trigger version negotiation.
@ -112,7 +107,7 @@ enum lsquic_version
/**
* We currently support versions 43, 46, 50, Draft-27, Draft-28, Draft-29,
* Draft-30, and Draft-31.
* and Draft-32.
* @see lsquic_version
*/
#define LSQUIC_SUPPORTED_VERSIONS ((1 << N_LSQVER) - 1)
@ -125,18 +120,17 @@ enum lsquic_version
#define LSQUIC_EXPERIMENTAL_VERSIONS ( \
(1 << LSQVER_VERNEG) | LSQUIC_EXPERIMENTAL_Q098)
#define LSQUIC_DEPRECATED_VERSIONS ((1 << LSQVER_ID27) | (1 << LSQVER_ID28) \
| (1 << LSQVER_ID30))
#define LSQUIC_DEPRECATED_VERSIONS ((1 << LSQVER_ID27) | (1 << LSQVER_ID28))
#define LSQUIC_GQUIC_HEADER_VERSIONS (1 << LSQVER_043)
#define LSQUIC_IETF_VERSIONS ((1 << LSQVER_ID27) | (1 << LSQVER_ID28) \
| (1 << LSQVER_ID29) | (1 << LSQVER_ID30) \
| (1 << LSQVER_ID31) | (1 << LSQVER_VERNEG))
| (1 << LSQVER_ID29) \
| (1 << LSQVER_ID32) | (1 << LSQVER_VERNEG))
#define LSQUIC_IETF_DRAFT_VERSIONS ((1 << LSQVER_ID27) | (1 << LSQVER_ID28) \
| (1 << LSQVER_ID29) | (1 << LSQVER_ID30) \
| (1 << LSQVER_ID31) | (1 << LSQVER_VERNEG))
| (1 << LSQVER_ID29) \
| (1 << LSQVER_ID32) | (1 << LSQVER_VERNEG))
enum lsquic_hsk_status
{

View file

@ -133,6 +133,7 @@ hsk_client_on_read (lsquic_stream_t *stream, struct lsquic_stream_ctx *sh)
/* fallthru */
case DATA_FORMAT_ERROR:
LSQ_INFO("lsquic_enc_session_handle_chlo_reply returned an error");
lsquic_mm_put_16k(c_hsk->mm, c_hsk->buf_in);
c_hsk->buf_in = NULL;
lsquic_stream_wantread(stream, 0);
c_hsk->lconn->cn_if->ci_hsk_done(c_hsk->lconn, LSQ_HSK_FAIL);

View file

@ -338,8 +338,7 @@ extern const struct enc_session_funcs_iquic lsquic_enc_session_iquic_ietf_v1;
ver == LSQVER_ID27 ? &lsquic_enc_session_common_ietf_v1 : \
ver == LSQVER_ID28 ? &lsquic_enc_session_common_ietf_v1 : \
ver == LSQVER_ID29 ? &lsquic_enc_session_common_ietf_v1 : \
ver == LSQVER_ID30 ? &lsquic_enc_session_common_ietf_v1 : \
ver == LSQVER_ID31 ? &lsquic_enc_session_common_ietf_v1 : \
ver == LSQVER_ID32 ? &lsquic_enc_session_common_ietf_v1 : \
ver == LSQVER_VERNEG ? &lsquic_enc_session_common_ietf_v1 : \
ver == LSQVER_050 ? &lsquic_enc_session_common_gquic_2 : \
&lsquic_enc_session_common_gquic_1 )

View file

@ -74,9 +74,8 @@ static const struct alpn_map {
{ LSQVER_ID27, (unsigned char *) "\x05h3-27", },
{ LSQVER_ID28, (unsigned char *) "\x05h3-28", },
{ LSQVER_ID29, (unsigned char *) "\x05h3-29", },
{ LSQVER_ID30, (unsigned char *) "\x05h3-30", },
{ LSQVER_ID31, (unsigned char *) "\x05h3-31", },
{ LSQVER_VERNEG, (unsigned char *) "\x05h3-31", },
{ LSQVER_ID32, (unsigned char *) "\x05h3-32", },
{ LSQVER_VERNEG, (unsigned char *) "\x05h3-32", },
};
struct enc_sess_iquic;

View file

@ -1114,7 +1114,8 @@ full_conn_ci_destroy (lsquic_conn_t *lconn)
conn->fc_stats.in.packets, conn->fc_stats.in.undec_packets,
conn->fc_stats.in.dup_packets, conn->fc_stats.in.err_packets,
conn->fc_stats.out.packets,
conn->fc_stats.out.stream_data_sz / conn->fc_stats.out.packets);
conn->fc_stats.out.stream_data_sz /
(conn->fc_stats.out.packets ? conn->fc_stats.out.packets : 1));
LSQ_NOTICE("ACKs: in: %lu; processed: %lu; merged: %lu",
conn->fc_stats.in.n_acks, conn->fc_stats.in.n_acks_proc,
conn->fc_stats.in.n_acks_merged);

View file

@ -3103,7 +3103,8 @@ ietf_full_conn_ci_destroy (struct lsquic_conn *lconn)
conn->ifc_stats.in.packets, conn->ifc_stats.in.undec_packets,
conn->ifc_stats.in.dup_packets, conn->ifc_stats.in.err_packets,
conn->ifc_stats.out.packets,
conn->ifc_stats.out.stream_data_sz / conn->ifc_stats.out.packets);
conn->ifc_stats.out.stream_data_sz /
(conn->ifc_stats.out.packets ? conn->ifc_stats.out.packets : 1));
LSQ_NOTICE("ACKs: in: %lu; processed: %lu; merged: %lu",
conn->ifc_stats.in.n_acks, conn->ifc_stats.in.n_acks_proc,
conn->ifc_stats.in.n_acks_merged);
@ -4471,6 +4472,24 @@ generate_ack_frequency_frame (struct ietf_full_conn *conn, lsquic_time_t unused)
}
static void
maybe_pad_packet (struct ietf_full_conn *conn,
struct lsquic_packet_out *packet_out)
{
unsigned short avail;
avail = lsquic_packet_out_avail(packet_out);
if (avail)
{
memset(packet_out->po_data + packet_out->po_data_sz, 0, avail);
lsquic_send_ctl_incr_pack_sz(&conn->ifc_send_ctl, packet_out, avail);
packet_out->po_frame_types |= QUIC_FTBIT_PADDING;
LSQ_DEBUG("added %hu-byte PADDING frame to packet %"PRIu64, avail,
packet_out->po_packno);
}
}
static void
generate_path_chal_frame (struct ietf_full_conn *conn, lsquic_time_t now,
unsigned path_id)
@ -4530,6 +4549,7 @@ generate_path_chal_frame (struct ietf_full_conn *conn, lsquic_time_t now,
packet_out->po_frame_types |= QUIC_FTBIT_PATH_CHALLENGE;
lsquic_send_ctl_incr_pack_sz(&conn->ifc_send_ctl, packet_out, w);
packet_out->po_regen_sz += w;
maybe_pad_packet(conn, packet_out);
conn->ifc_send_flags &= ~(SF_SEND_PATH_CHAL << path_id);
lsquic_alarmset_set(&conn->ifc_alset, AL_PATH_CHAL + path_id,
now + (INITIAL_CHAL_TIMEOUT << (copath->cop_n_chals - 1)));
@ -4600,6 +4620,7 @@ generate_path_resp_frame (struct ietf_full_conn *conn, lsquic_time_t now,
}
packet_out->po_frame_types |= QUIC_FTBIT_PATH_RESPONSE;
lsquic_send_ctl_incr_pack_sz(&conn->ifc_send_ctl, packet_out, w);
maybe_pad_packet(conn, packet_out);
packet_out->po_regen_sz += w;
conn->ifc_send_flags &= ~(SF_SEND_PATH_RESP << path_id);
}
@ -5699,6 +5720,34 @@ process_ping_frame (struct ietf_full_conn *conn,
}
static int
is_benign_transport_error_code (uint64_t error_code)
{
switch (error_code)
{
case TEC_NO_ERROR:
case TEC_INTERNAL_ERROR:
return 1;
default:
return 0;
}
}
static int
is_benign_application_error_code (uint64_t error_code)
{
switch (error_code)
{
case HEC_NO_ERROR:
case HEC_INTERNAL_ERROR:
return 1;
default:
return 0;
}
}
static unsigned
process_connection_close_frame (struct ietf_full_conn *conn,
struct lsquic_packet_in *packet_in, const unsigned char *p, size_t len)
@ -5709,6 +5758,7 @@ process_connection_close_frame (struct ietf_full_conn *conn,
uint16_t reason_len;
uint8_t reason_off;
int parsed_len, app_error;
const char *ua;
parsed_len = conn->ifc_conn.cn_pf->pf_parse_connect_close_frame(p, len,
&app_error, &error_code, &reason_len, &reason_off);
@ -5716,7 +5766,25 @@ process_connection_close_frame (struct ietf_full_conn *conn,
return 0;
EV_LOG_CONNECTION_CLOSE_FRAME_IN(LSQUIC_LOG_CONN_ID, error_code,
(int) reason_len, (const char *) p + reason_off);
LSQ_INFO("Received CONNECTION_CLOSE frame (%s-level code: %"PRIu64"; "
if (LSQ_LOG_ENABLED(LSQ_LOG_NOTICE)
&& !( (!app_error && is_benign_transport_error_code(error_code))
||( app_error && is_benign_application_error_code(error_code))))
{
if (conn->ifc_flags & IFC_HTTP)
{
ua = lsquic_qdh_get_ua(&conn->ifc_qdh);
if (!ua)
ua = "unknown peer";
}
else
ua = "non-HTTP/3 peer";
LSQ_NOTICE("Received CONNECTION_CLOSE from <%s> with %s-level error "
"code %"PRIu64", reason: `%.*s'", ua,
app_error ? "application" : "transport", error_code,
(int) reason_len, (const char *) p + reason_off);
}
else
LSQ_INFO("Received CONNECTION_CLOSE frame (%s-level code: %"PRIu64"; "
"reason: %.*s)", app_error ? "application" : "transport",
error_code, (int) reason_len, (const char *) p + reason_off);
conn->ifc_flags |= IFC_RECV_CLOSE;
@ -9126,16 +9194,14 @@ hcsi_on_new (void *stream_if_ctx, struct lsquic_stream *stream)
callbacks = &hcsi_callbacks_server_28;
break;
case (0 << 8) | LSQVER_ID29:
case (0 << 8) | LSQVER_ID30:
case (0 << 8) | LSQVER_ID31:
case (0 << 8) | LSQVER_ID32:
callbacks = &hcsi_callbacks_client_29;
break;
default:
assert(0);
/* fallthru */
case (1 << 8) | LSQVER_ID29:
case (1 << 8) | LSQVER_ID30:
case (1 << 8) | LSQVER_ID31:
case (1 << 8) | LSQVER_ID32:
callbacks = &hcsi_callbacks_server_29;
break;
}

View file

@ -887,7 +887,8 @@ allocate_packet_out (struct mini_conn *mc, const unsigned char *nonce)
return NULL;
}
packet_out = lsquic_packet_out_new(&mc->mc_enpub->enp_mm, NULL, 1,
&mc->mc_conn, GQUIC_PACKNO_LEN_1, NULL, nonce, &mc->mc_path);
&mc->mc_conn, GQUIC_PACKNO_LEN_1, NULL, nonce, &mc->mc_path,
HETY_NOT_SET);
if (!packet_out)
{
LSQ_WARN("could not allocate packet: %s", strerror(errno));

View file

@ -121,7 +121,8 @@ imico_get_packet_out (struct ietf_mini_conn *conn,
}
packet_out = lsquic_packet_out_new(&conn->imc_enpub->enp_mm, NULL, 1,
&conn->imc_conn, IQUIC_PACKNO_LEN_1, NULL, NULL, &conn->imc_path);
&conn->imc_conn, IQUIC_PACKNO_LEN_1, NULL, NULL, &conn->imc_path,
header_type);
if (!packet_out)
{
LSQ_WARN("could not allocate packet: %s", strerror(errno));
@ -696,6 +697,18 @@ imico_can_send (const struct ietf_mini_conn *conn, size_t size)
}
static void
imico_zero_pad (struct lsquic_packet_out *packet_out)
{
size_t pad_size;
pad_size = lsquic_packet_out_avail(packet_out);
memset(packet_out->po_data + packet_out->po_data_sz, 0, pad_size);
packet_out->po_data_sz += pad_size;
packet_out->po_frame_types |= QUIC_FTBIT_PADDING;
}
static struct lsquic_packet_out *
ietf_mini_conn_ci_next_packet_to_send (struct lsquic_conn *lconn,
const struct to_coal *to_coal)
@ -708,6 +721,16 @@ ietf_mini_conn_ci_next_packet_to_send (struct lsquic_conn *lconn,
{
if (packet_out->po_flags & PO_SENT)
continue;
/* [draft-ietf-quic-transport-32] Section 14.1:
" a server MUST expand the payload of all UDP datagrams carrying
" ack-eliciting Initial packets to at least the smallest allowed
" maximum datagram size of 1200 bytes.
*/
if (packet_out->po_header_type == HETY_INITIAL
&& !(packet_out->po_frame_types & (1 << QUIC_FRAME_PADDING))
&& (packet_out->po_frame_types & IQUIC_FRAME_ACKABLE_MASK)
&& lsquic_packet_out_avail(packet_out) > 0)
imico_zero_pad(packet_out);
packet_size = lsquic_packet_out_total_sz(lconn, packet_out);
if (!(to_coal
&& (packet_size + to_coal->prev_sz_sum

View file

@ -204,7 +204,7 @@ lsquic_packet_out_t *
lsquic_packet_out_new (struct lsquic_mm *mm, struct malo *malo, int use_cid,
const struct lsquic_conn *lconn, enum packno_bits bits,
const lsquic_ver_tag_t *ver_tag, const unsigned char *nonce,
const struct network_path *path)
const struct network_path *path, enum header_type header_type)
{
lsquic_packet_out_t *packet_out;
enum packet_out_flags flags;
@ -222,7 +222,7 @@ lsquic_packet_out_new (struct lsquic_mm *mm, struct malo *malo, int use_cid,
flags |= PO_LONGHEAD;
header_size = lconn->cn_pf->pf_packout_max_header_size(lconn, flags,
path->np_dcid.len);
path->np_dcid.len, header_type);
tag_len = lconn->cn_esf_c->esf_tag_len;
max_size = path->np_pack_size;
if (header_size + tag_len >= max_size)

View file

@ -229,8 +229,9 @@ typedef struct lsquic_packet_out
(p)->po_flags |= ((b) & 1) << POSPIN_SHIFT; \
} while (0)
#define lsquic_po_header_length(lconn, po_flags, dcid_len) ( \
lconn->cn_pf->pf_packout_max_header_size(lconn, po_flags, dcid_len))
#define lsquic_po_header_length(lconn, po_flags, dcid_len, header_type) ( \
lconn->cn_pf->pf_packout_max_header_size(lconn, po_flags, dcid_len, \
header_type)) \
#define lsquic_packet_out_total_sz(lconn, p) (\
(lconn)->cn_pf->pf_packout_size(lconn, p))
@ -308,7 +309,7 @@ lsquic_packet_out_t *
lsquic_packet_out_new (struct lsquic_mm *, struct malo *, int use_cid,
const struct lsquic_conn *, enum packno_bits,
const lsquic_ver_tag_t *, const unsigned char *nonce,
const struct network_path *);
const struct network_path *, enum header_type);
void
lsquic_packet_out_destroy (lsquic_packet_out_t *,

View file

@ -222,7 +222,7 @@ struct parse_funcs
*/
size_t
(*pf_packout_max_header_size) (const struct lsquic_conn *,
enum packet_out_flags, size_t dcid_len);
enum packet_out_flags, size_t dcid_len, enum header_type);
enum packno_bits
(*pf_calc_packno_bits) (lsquic_packno_t packno,
@ -381,7 +381,7 @@ lsquic_gquic_packout_size (const struct lsquic_conn *,
size_t
lsquic_gquic_packout_header_size (const struct lsquic_conn *conn,
enum packet_out_flags flags, size_t unused);
enum packet_out_flags flags, size_t unused, enum header_type);
size_t
lsquic_gquic_po_header_sz (enum packet_out_flags flags);

View file

@ -215,7 +215,8 @@ gquic_Q046_packout_header_size_short (const struct lsquic_conn *lconn,
static size_t
gquic_Q046_packout_header_size (const struct lsquic_conn *lconn,
enum packet_out_flags flags, size_t dcid_len_unused)
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);

View file

@ -459,7 +459,8 @@ gquic_Q050_packout_header_size_short (const struct lsquic_conn *lconn,
static size_t
gquic_Q050_packout_max_header_size (const struct lsquic_conn *lconn,
enum packet_out_flags flags, size_t dcid_len_unused)
enum packet_out_flags flags, size_t dcid_len_unused,
enum header_type unused)
{
if (lconn->cn_flags & LSCONN_SERVER)
{

View file

@ -220,37 +220,7 @@ lsquic_cid_from_packet (const unsigned char *buf, size_t bufsz,
/* See [draft-ietf-quic-transport-28], Section 12.4 (Table 3) */
const enum quic_ft_bit lsquic_legal_frames_by_level[N_LSQVER][N_ENC_LEVS] =
{
[LSQVER_ID31] = {
[ENC_LEV_CLEAR] = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
| QUIC_FTBIT_ACK | QUIC_FTBIT_CONNECTION_CLOSE,
[ENC_LEV_EARLY] = QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
| QUIC_FTBIT_STREAM | QUIC_FTBIT_RST_STREAM
| QUIC_FTBIT_BLOCKED | QUIC_FTBIT_CONNECTION_CLOSE
| QUIC_FTBIT_MAX_DATA | QUIC_FTBIT_MAX_STREAM_DATA
| QUIC_FTBIT_MAX_STREAMS | QUIC_FTBIT_STREAM_BLOCKED
| QUIC_FTBIT_STREAMS_BLOCKED
| QUIC_FTBIT_NEW_CONNECTION_ID | QUIC_FTBIT_STOP_SENDING
| QUIC_FTBIT_PATH_CHALLENGE | QUIC_FTBIT_PATH_RESPONSE
| QUIC_FTBIT_DATAGRAM
| QUIC_FTBIT_RETIRE_CONNECTION_ID,
[ENC_LEV_INIT] = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
| QUIC_FTBIT_ACK| QUIC_FTBIT_CONNECTION_CLOSE,
[ENC_LEV_FORW] = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
| QUIC_FTBIT_ACK | QUIC_FTBIT_CONNECTION_CLOSE
| QUIC_FTBIT_STREAM | QUIC_FTBIT_RST_STREAM
| QUIC_FTBIT_BLOCKED
| QUIC_FTBIT_MAX_DATA | QUIC_FTBIT_MAX_STREAM_DATA
| QUIC_FTBIT_MAX_STREAMS | QUIC_FTBIT_STREAM_BLOCKED
| QUIC_FTBIT_STREAMS_BLOCKED
| QUIC_FTBIT_NEW_CONNECTION_ID | QUIC_FTBIT_STOP_SENDING
| QUIC_FTBIT_PATH_CHALLENGE | QUIC_FTBIT_PATH_RESPONSE
| QUIC_FTBIT_HANDSHAKE_DONE | QUIC_FTBIT_ACK_FREQUENCY
| QUIC_FTBIT_RETIRE_CONNECTION_ID | QUIC_FTBIT_NEW_TOKEN
| QUIC_FTBIT_TIMESTAMP
| QUIC_FTBIT_DATAGRAM
,
},
[LSQVER_ID30] = {
[LSQVER_ID32] = {
[ENC_LEV_CLEAR] = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
| QUIC_FTBIT_ACK | QUIC_FTBIT_CONNECTION_CLOSE,
[ENC_LEV_EARLY] = QUIC_FTBIT_PADDING | QUIC_FTBIT_PING

View file

@ -574,7 +574,8 @@ lsquic_gquic_packout_size (const struct lsquic_conn *conn,
size_t
lsquic_gquic_packout_header_size (const struct lsquic_conn *conn,
enum packet_out_flags flags, size_t dcid_len)
enum packet_out_flags flags, size_t dcid_len,
enum header_type unused)
{
return lsquic_gquic_po_header_sz(flags);
}

View file

@ -122,8 +122,7 @@ ietf_v1_packout_header_size_long_by_packet (const struct lsquic_conn *lconn,
static size_t
ietf_v1_packout_header_size_short (const struct lsquic_conn *lconn,
enum packet_out_flags flags, size_t dcid_len)
ietf_v1_packout_header_size_short (enum packet_out_flags flags, size_t dcid_len)
{
enum packno_bits bits;
size_t sz;
@ -140,19 +139,13 @@ ietf_v1_packout_header_size_short (const struct lsquic_conn *lconn,
static size_t
ietf_v1_packout_max_header_size (const struct lsquic_conn *lconn,
enum packet_out_flags flags, size_t dcid_len)
enum packet_out_flags flags, size_t dcid_len, enum header_type header_type)
{
if (lconn->cn_flags & LSCONN_HANDSHAKE_DONE)
return ietf_v1_packout_header_size_short(lconn, flags, dcid_len);
else if (lconn->cn_flags & LSCONN_SERVER)
/* Server does not set the token in its Initial packet header: set
* the packet type to something else in order not to overestimate
* header size.
*/
return ietf_v1_packout_header_size_long_by_flags(lconn, HETY_HANDSHAKE,
flags, dcid_len);
if ((lconn->cn_flags & LSCONN_HANDSHAKE_DONE)
&& header_type == HETY_NOT_SET)
return ietf_v1_packout_header_size_short(flags, dcid_len);
else
return ietf_v1_packout_header_size_long_by_flags(lconn, HETY_INITIAL,
return ietf_v1_packout_header_size_long_by_flags(lconn, header_type,
flags, dcid_len);
}
@ -309,7 +302,7 @@ ietf_v1_packout_size (const struct lsquic_conn *lconn,
if ((lconn->cn_flags & LSCONN_HANDSHAKE_DONE)
&& packet_out->po_header_type == HETY_NOT_SET)
sz = ietf_v1_packout_header_size_short(lconn, packet_out->po_flags,
sz = ietf_v1_packout_header_size_short(packet_out->po_flags,
packet_out->po_path->np_dcid.len);
else
sz = ietf_v1_packout_header_size_long_by_packet(lconn, packet_out);

View file

@ -165,6 +165,8 @@ lsquic_qdh_init (struct qpack_dec_hdl *qdh, struct lsquic_conn *conn,
if (enpub->enp_hsi_if->hsi_flags & LSQUIC_HSI_HASH_NAMEVAL)
dec_opts |= LSQPACK_DEC_OPT_HASH_NAMEVAL;
if (conn->cn_flags & LSCONN_SERVER)
qdh->qdh_flags |= QDH_SERVER;
if (enpub->enp_settings.es_qpack_experiment)
{
qdh->qdh_exp_rec = lsquic_qpack_exp_new();
@ -176,6 +178,8 @@ lsquic_qdh_init (struct qpack_dec_hdl *qdh, struct lsquic_conn *conn,
qdh->qdh_exp_rec->qer_used_max_blocked = max_risked_streams;
}
}
if (!qdh->qdh_exp_rec && LSQ_LOG_ENABLED_EXT(LSQ_LOG_NOTICE, LSQLM_CONN))
qdh->qdh_flags |= QDH_SAVE_UA;
qdh->qdh_conn = conn;
lsquic_frab_list_init(&qdh->qdh_fral, 0x400, NULL, NULL, NULL);
@ -226,6 +230,11 @@ lsquic_qdh_cleanup (struct qpack_dec_hdl *qdh)
LSQ_DEBUG("cleanup");
if (qdh->qdh_exp_rec)
qdh_log_and_clean_exp_rec(qdh);
if (qdh->qdh_ua)
{
free(qdh->qdh_ua);
qdh->qdh_ua = NULL;
}
lsqpack_dec_cleanup(&qdh->qdh_decoder);
lsquic_frab_list_cleanup(&qdh->qdh_fral);
qdh->qdh_flags &= ~QDH_INITIALIZED;
@ -531,17 +540,16 @@ qdh_prepare_decode (void *stream_p, struct lsxpack_header *xhdr, size_t space)
static void
qdh_maybe_set_user_agent (struct qpack_dec_hdl *qdh,
const struct lsxpack_header *xhdr)
const struct lsxpack_header *xhdr, char **ua)
{
/* Flipped: we are the *decoder* */
const char *const name = qdh->qdh_exp_rec->qer_flags & QER_SERVER ?
const char *const name = qdh->qdh_flags & QDH_SERVER ?
"user-agent" : "server";
const size_t len = qdh->qdh_exp_rec->qer_flags & QER_SERVER ? 10 : 6;
const size_t len = qdh->qdh_flags & QDH_SERVER ? 10 : 6;
if (len == xhdr->name_len
&& 0 == memcmp(name, lsxpack_header_get_name(xhdr), len))
qdh->qdh_exp_rec->qer_user_agent
= strndup(lsxpack_header_get_value(xhdr), xhdr->val_len);
*ua = strndup(lsxpack_header_get_value(xhdr), xhdr->val_len);
}
@ -572,7 +580,9 @@ qdh_process_header (void *stream_p, struct lsxpack_header *xhdr)
sizeof(*stream->conn_pub->mm->acki));
}
else if (qdh->qdh_exp_rec && !qdh->qdh_exp_rec->qer_user_agent)
qdh_maybe_set_user_agent(qdh, xhdr);
qdh_maybe_set_user_agent(qdh, xhdr, &qdh->qdh_exp_rec->qer_user_agent);
else if ((qdh->qdh_flags & QDH_SAVE_UA) && !qdh->qdh_ua)
qdh_maybe_set_user_agent(qdh, xhdr, &qdh->qdh_ua);
return qdh->qdh_enpub->enp_hsi_if->hsi_process_header(u->ctx.hset, xhdr);
}
@ -844,3 +854,15 @@ lsquic_qdh_arm_if_unsent (struct qpack_dec_hdl *qdh, void (*func)(void *),
return 1;
}
}
const char *
lsquic_qdh_get_ua (const struct qpack_dec_hdl *qdh)
{
if (qdh->qdh_ua)
return qdh->qdh_ua;
else if (qdh->qdh_exp_rec && qdh->qdh_exp_rec->qer_user_agent)
return qdh->qdh_exp_rec->qer_user_agent;
else
return NULL;
}

View file

@ -23,6 +23,8 @@ struct qpack_dec_hdl
enum {
QDH_INITIALIZED = 1 << 0,
QDH_PUSH_PROMISE = 1 << 1,
QDH_SAVE_UA = 1 << 2,
QDH_SERVER = 1 << 3,
} qdh_flags;
struct lsqpack_dec qdh_decoder;
struct lsquic_stream *qdh_enc_sm_in;
@ -35,6 +37,7 @@ struct qpack_dec_hdl
void (*qdh_on_dec_sent_func)(void *);
void *qdh_on_dec_sent_ctx;
struct qpack_exp_record *qdh_exp_rec;
char *qdh_ua;
};
int
@ -74,6 +77,9 @@ lsquic_qdh_cancel_stream_id (struct qpack_dec_hdl *, lsquic_stream_id_t);
int
lsquic_qdh_arm_if_unsent (struct qpack_dec_hdl *, void (*)(void *), void *);
const char *
lsquic_qdh_get_ua (const struct qpack_dec_hdl *);
extern const struct lsquic_stream_if *const lsquic_qdh_enc_sm_in_if;
extern const struct lsquic_stream_if *const lsquic_qdh_dec_sm_out_if;

View file

@ -2043,12 +2043,18 @@ send_ctl_allocate_packet (struct lsquic_send_ctl *ctl, enum packno_bits bits,
unsigned need_at_least, enum packnum_space pns,
const struct network_path *path)
{
static const enum header_type pns2hety[] =
{
[PNS_INIT] = HETY_INITIAL,
[PNS_HSK] = HETY_HANDSHAKE,
[PNS_APP] = HETY_NOT_SET,
};
lsquic_packet_out_t *packet_out;
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_conn_pub->lconn, bits,
ctl->sc_ver_neg->vn_tag, NULL, path);
ctl->sc_ver_neg->vn_tag, NULL, path, pns2hety[pns]);
if (!packet_out)
return NULL;

View file

@ -2483,7 +2483,7 @@ lsquic_stream_flush_threshold (const struct lsquic_stream *stream,
flags |= PO_LONGHEAD;
packet_header_sz = lsquic_po_header_length(stream->conn_pub->lconn, flags,
stream->conn_pub->path->np_dcid.len);
stream->conn_pub->path->np_dcid.len, HETY_NOT_SET);
stream_header_sz = stream->sm_frame_header_sz(stream, data_sz);
tag_len = stream->conn_pub->lconn->cn_esf_c->esf_tag_len;

View file

@ -21,8 +21,7 @@ static const unsigned char version_tags[N_LSQVER][4] =
[LSQVER_ID27] = { 0xFF, 0, 0, 27, },
[LSQVER_ID28] = { 0xFF, 0, 0, 28, },
[LSQVER_ID29] = { 0xFF, 0, 0, 29, },
[LSQVER_ID30] = { 0xFF, 0, 0, 30, },
[LSQVER_ID31] = { 0xFF, 0, 0, 31, },
[LSQVER_ID32] = { 0xFF, 0, 0, 32, },
[LSQVER_VERNEG] = { 0xFA, 0xFA, 0xFA, 0xFA, },
};
@ -62,8 +61,7 @@ const char *const lsquic_ver2str[N_LSQVER] = {
[LSQVER_ID27] = "FF00001B",
[LSQVER_ID28] = "FF00001C",
[LSQVER_ID29] = "FF00001D",
[LSQVER_ID30] = "FF00001E",
[LSQVER_ID31] = "FF00001F",
[LSQVER_ID32] = "FF000020",
[LSQVER_VERNEG] = "FAFAFAFA",
};

View file

@ -214,7 +214,7 @@ new_packet (struct test_ctx *ctx)
*/
packet_out = lsquic_packet_out_new(&ctx->enpub.enp_mm, ctx->enpub.enp_mm.malo.packet_out, 1,
&ctx->lconn, PACKNO_BITS_0, 0, NULL, &ctx->path);
&ctx->lconn, PACKNO_BITS_0, 0, NULL, &ctx->path, HETY_NOT_SET);
if (packet_out)
packet_out->po_packno = packno++;