mirror of
https://gitea.invidious.io/iv-org/litespeed-quic.git
synced 2024-08-15 00:53:43 +00:00
Release 1.19.0
- [FEATURE, API Change] 0-RTT support. Add function to export 0-RTT information; it can be supplied to a subsequent connect() call. - [FEATURE] Add -0 flag to http_client to exercise 0-RTT support. - [BUGFIX] Resuscitate the Windows build. - [BUGFIX] Send HTTP settings (max header list size) if necessary. - [BUGFIX] Buffered packets can contain ACK frames. - [BUGFIX] Make packet writeable once all STREAM frames are elided. - [BUGFIX] Fix potential null dereference when realloc fails. - cmake: simplify build configuration.
This commit is contained in:
parent
03fb93526e
commit
8ca33e0e19
21 changed files with 631 additions and 381 deletions
|
@ -47,6 +47,7 @@ hsk_client_on_read (lsquic_stream_t *stream, struct lsquic_stream_ctx *sh)
|
|||
struct client_hsk_ctx *const c_hsk = (struct client_hsk_ctx *) sh;
|
||||
ssize_t nread;
|
||||
int s;
|
||||
enum lsquic_hsk_status status;
|
||||
|
||||
if (!c_hsk->buf_in)
|
||||
{
|
||||
|
@ -95,7 +96,7 @@ hsk_client_on_read (lsquic_stream_t *stream, struct lsquic_stream_ctx *sh)
|
|||
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_handshake_failed(c_hsk->lconn);
|
||||
c_hsk->lconn->cn_if->ci_hsk_done(c_hsk->lconn, LSQ_HSK_FAIL);
|
||||
lsquic_conn_close(c_hsk->lconn);
|
||||
}
|
||||
break;
|
||||
|
@ -106,7 +107,9 @@ hsk_client_on_read (lsquic_stream_t *stream, struct lsquic_stream_ctx *sh)
|
|||
if (c_hsk->lconn->cn_esf->esf_is_hsk_done(c_hsk->lconn->cn_enc_session))
|
||||
{
|
||||
LSQ_DEBUG("handshake is successful, inform connection");
|
||||
c_hsk->lconn->cn_if->ci_handshake_ok(c_hsk->lconn);
|
||||
status = (c_hsk->lconn->cn_esf->esf_did_zero_rtt_succeed(
|
||||
c_hsk->lconn->cn_enc_session)) ? LSQ_HSK_0RTT_OK : LSQ_HSK_OK;
|
||||
c_hsk->lconn->cn_if->ci_hsk_done(c_hsk->lconn, status);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -122,7 +125,7 @@ hsk_client_on_read (lsquic_stream_t *stream, struct lsquic_stream_ctx *sh)
|
|||
LSQ_INFO("lsquic_enc_session_handle_chlo_reply returned an error");
|
||||
c_hsk->buf_in = NULL;
|
||||
lsquic_stream_wantread(stream, 0);
|
||||
c_hsk->lconn->cn_if->ci_handshake_failed(c_hsk->lconn);
|
||||
c_hsk->lconn->cn_if->ci_hsk_done(c_hsk->lconn, LSQ_HSK_FAIL);
|
||||
lsquic_conn_close(c_hsk->lconn);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -150,3 +150,16 @@ lsquic_conn_get_server_cert_chain (struct lsquic_conn *lconn)
|
|||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
lsquic_conn_get_zero_rtt(const lsquic_conn_t *lconn,
|
||||
unsigned char *zero_rtt, size_t zero_rtt_len)
|
||||
{
|
||||
ssize_t ret = -1;
|
||||
if (lconn->cn_enc_session && (lconn->cn_flags & LSCONN_VER_SET))
|
||||
ret = lconn->cn_esf->esf_get_zero_rtt(lconn->cn_enc_session,
|
||||
lconn->cn_version,
|
||||
zero_rtt, zero_rtt_len);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -73,10 +73,7 @@ struct conn_iface
|
|||
(*ci_packet_not_sent) (struct lsquic_conn *, struct lsquic_packet_out *);
|
||||
|
||||
void
|
||||
(*ci_handshake_ok) (struct lsquic_conn *);
|
||||
|
||||
void
|
||||
(*ci_handshake_failed) (struct lsquic_conn *);
|
||||
(*ci_hsk_done) (struct lsquic_conn *, enum lsquic_hsk_status);
|
||||
|
||||
void
|
||||
(*ci_destroy) (struct lsquic_conn *);
|
||||
|
|
|
@ -453,7 +453,8 @@ maybe_grow_conn_heaps (struct lsquic_engine *engine)
|
|||
|
||||
static lsquic_conn_t *
|
||||
new_full_conn_client (lsquic_engine_t *engine, const char *hostname,
|
||||
unsigned short max_packet_size)
|
||||
unsigned short max_packet_size, const unsigned char *zero_rtt,
|
||||
size_t zero_rtt_len)
|
||||
{
|
||||
lsquic_conn_t *conn;
|
||||
unsigned flags;
|
||||
|
@ -461,7 +462,8 @@ new_full_conn_client (lsquic_engine_t *engine, const char *hostname,
|
|||
return NULL;
|
||||
flags = engine->flags & (ENG_SERVER|ENG_HTTP);
|
||||
conn = full_conn_client_new(&engine->pub, engine->stream_if,
|
||||
engine->stream_if_ctx, flags, hostname, max_packet_size);
|
||||
engine->stream_if_ctx, flags, hostname,
|
||||
max_packet_size, zero_rtt, zero_rtt_len);
|
||||
if (!conn)
|
||||
return NULL;
|
||||
++engine->n_conns;
|
||||
|
@ -662,7 +664,8 @@ lsquic_conn_t *
|
|||
lsquic_engine_connect (lsquic_engine_t *engine, const struct sockaddr *local_sa,
|
||||
const struct sockaddr *peer_sa,
|
||||
void *peer_ctx, lsquic_conn_ctx_t *conn_ctx,
|
||||
const char *hostname, unsigned short max_packet_size)
|
||||
const char *hostname, unsigned short max_packet_size,
|
||||
const unsigned char *zero_rtt, size_t zero_rtt_len)
|
||||
{
|
||||
lsquic_conn_t *conn;
|
||||
ENGINE_IN(engine);
|
||||
|
@ -693,7 +696,8 @@ lsquic_engine_connect (lsquic_engine_t *engine, const struct sockaddr *local_sa,
|
|||
}
|
||||
}
|
||||
|
||||
conn = new_full_conn_client(engine, hostname, max_packet_size);
|
||||
conn = new_full_conn_client(engine, hostname, max_packet_size,
|
||||
zero_rtt, zero_rtt_len);
|
||||
if (!conn)
|
||||
goto err;
|
||||
lsquic_conn_record_sockaddr(conn, local_sa, peer_sa);
|
||||
|
|
|
@ -418,14 +418,16 @@ check_headers_size (const struct lsquic_frame_writer *fw,
|
|||
headers_sz = calc_headers_size(headers);
|
||||
if (extra_headers)
|
||||
headers_sz += calc_headers_size(extra_headers);
|
||||
if (headers_sz > fw->fw_max_header_list_sz)
|
||||
|
||||
if (headers_sz <= fw->fw_max_header_list_sz)
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
LSQ_INFO("Headers size %u is larger than max allowed (%u)",
|
||||
headers_sz, fw->fw_max_header_list_sz);
|
||||
errno = EMSGSIZE;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -435,7 +435,6 @@ send_smhl (const struct full_conn *conn)
|
|||
{
|
||||
uint32_t smhl;
|
||||
return conn->fc_conn.cn_enc_session
|
||||
&& (conn->fc_conn.cn_flags & LSCONN_HANDSHAKE_DONE)
|
||||
&& 0 == conn->fc_conn.cn_esf->esf_get_peer_setting(
|
||||
conn->fc_conn.cn_enc_session, QTAG_SMHL, &smhl)
|
||||
&& 1 == smhl;
|
||||
|
@ -509,8 +508,6 @@ apply_peer_settings (struct full_conn *conn)
|
|||
LSQ_DEBUG("peer settings: CFCW: %u; SFCW: %u; MIDS: %u",
|
||||
cfcw, sfcw, mids);
|
||||
conn_on_peer_config(conn, cfcw, sfcw, mids);
|
||||
if (conn->fc_flags & FC_HTTP)
|
||||
maybe_send_settings(conn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -640,7 +637,8 @@ struct lsquic_conn *
|
|||
full_conn_client_new (struct lsquic_engine_public *enpub,
|
||||
const struct lsquic_stream_if *stream_if,
|
||||
void *stream_if_ctx, unsigned flags,
|
||||
const char *hostname, unsigned short max_packet_size)
|
||||
const char *hostname, unsigned short max_packet_size,
|
||||
const unsigned char *zero_rtt, size_t zero_rtt_len)
|
||||
{
|
||||
struct full_conn *conn;
|
||||
enum lsquic_version version;
|
||||
|
@ -656,7 +654,8 @@ full_conn_client_new (struct lsquic_engine_public *enpub,
|
|||
return NULL;
|
||||
conn->fc_conn.cn_esf = esf;
|
||||
conn->fc_conn.cn_enc_session =
|
||||
conn->fc_conn.cn_esf->esf_create_client(hostname, cid, conn->fc_enpub);
|
||||
conn->fc_conn.cn_esf->esf_create_client(hostname, cid, conn->fc_enpub,
|
||||
zero_rtt, zero_rtt_len);
|
||||
if (!conn->fc_conn.cn_enc_session)
|
||||
{
|
||||
LSQ_WARN("could not create enc session: %s", strerror(errno));
|
||||
|
@ -2985,7 +2984,9 @@ full_conn_ci_tick (lsquic_conn_t *lconn, lsquic_time_t now)
|
|||
}
|
||||
|
||||
lsquic_send_ctl_set_buffer_stream_packets(&conn->fc_send_ctl, 0);
|
||||
if (!(conn->fc_conn.cn_flags & LSCONN_HANDSHAKE_DONE))
|
||||
if (!(conn->fc_conn.cn_flags & LSCONN_HANDSHAKE_DONE) &&
|
||||
!conn->fc_conn.cn_esf->esf_is_zero_rtt_enabled(
|
||||
conn->fc_conn.cn_enc_session))
|
||||
{
|
||||
process_hsk_stream_write_events(conn);
|
||||
goto end_write;
|
||||
|
@ -3145,29 +3146,30 @@ full_conn_ci_packet_not_sent (lsquic_conn_t *lconn, lsquic_packet_out_t *packet_
|
|||
|
||||
|
||||
static void
|
||||
full_conn_ci_handshake_ok (lsquic_conn_t *lconn)
|
||||
full_conn_ci_hsk_done (lsquic_conn_t *lconn, enum lsquic_hsk_status status)
|
||||
{
|
||||
struct full_conn *conn = (struct full_conn *) lconn;
|
||||
LSQ_DEBUG("handshake reportedly done");
|
||||
lsquic_alarmset_unset(&conn->fc_alset, AL_HANDSHAKE);
|
||||
if (0 == apply_peer_settings(conn))
|
||||
lconn->cn_flags |= LSCONN_HANDSHAKE_DONE;
|
||||
else
|
||||
conn->fc_flags |= FC_ERROR;
|
||||
switch (status)
|
||||
{
|
||||
case LSQ_HSK_FAIL:
|
||||
conn->fc_flags |= FC_HSK_FAILED;
|
||||
break;
|
||||
case LSQ_HSK_OK:
|
||||
case LSQ_HSK_0RTT_OK:
|
||||
if (0 == apply_peer_settings(conn))
|
||||
{
|
||||
if (conn->fc_flags & FC_HTTP)
|
||||
maybe_send_settings(conn);
|
||||
lconn->cn_flags |= LSCONN_HANDSHAKE_DONE;
|
||||
}
|
||||
else
|
||||
conn->fc_flags |= FC_ERROR;
|
||||
break;
|
||||
}
|
||||
if (conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_hsk_done)
|
||||
conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_hsk_done(lconn, 1);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
full_conn_ci_handshake_failed (lsquic_conn_t *lconn)
|
||||
{
|
||||
struct full_conn *conn = (struct full_conn *) lconn;
|
||||
LSQ_DEBUG("handshake failed");
|
||||
lsquic_alarmset_unset(&conn->fc_alset, AL_HANDSHAKE);
|
||||
conn->fc_flags |= FC_HSK_FAILED;
|
||||
if (conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_hsk_done)
|
||||
conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_hsk_done(lconn, 0);
|
||||
conn->fc_stream_ifs[STREAM_IF_STD].stream_if->on_hsk_done(lconn,
|
||||
status);
|
||||
}
|
||||
|
||||
|
||||
|
@ -3539,7 +3541,9 @@ full_conn_ci_is_tickable (lsquic_conn_t *lconn)
|
|||
return 1;
|
||||
if (!TAILQ_EMPTY(&conn->fc_pub.sending_streams))
|
||||
return 1;
|
||||
if (conn->fc_conn.cn_flags & LSCONN_HANDSHAKE_DONE)
|
||||
if ((conn->fc_conn.cn_flags & LSCONN_HANDSHAKE_DONE) ||
|
||||
conn->fc_conn.cn_esf->esf_is_zero_rtt_enabled(
|
||||
conn->fc_conn.cn_enc_session))
|
||||
{
|
||||
TAILQ_FOREACH(stream, &conn->fc_pub.write_streams,
|
||||
next_write_stream)
|
||||
|
@ -3617,8 +3621,7 @@ static const struct conn_iface full_conn_iface = {
|
|||
#if LSQUIC_CONN_STATS
|
||||
.ci_get_stats = full_conn_ci_get_stats,
|
||||
#endif
|
||||
.ci_handshake_failed = full_conn_ci_handshake_failed,
|
||||
.ci_handshake_ok = full_conn_ci_handshake_ok,
|
||||
.ci_hsk_done = full_conn_ci_hsk_done,
|
||||
.ci_is_tickable = full_conn_ci_is_tickable,
|
||||
.ci_next_packet_to_send = full_conn_ci_next_packet_to_send,
|
||||
.ci_next_tick_time = full_conn_ci_next_tick_time,
|
||||
|
|
|
@ -11,7 +11,8 @@ full_conn_client_new (struct lsquic_engine_public *,
|
|||
const struct lsquic_stream_if *,
|
||||
void *stream_if_ctx,
|
||||
unsigned flags /* Only FC_SERVER and FC_HTTP */,
|
||||
const char *hostname, unsigned short max_packet_size);
|
||||
const char *hostname, unsigned short max_packet_size,
|
||||
const unsigned char *zero_rtt, size_t zero_rtt_len);
|
||||
|
||||
void
|
||||
full_conn_client_call_on_new (struct lsquic_conn *);
|
||||
|
|
|
@ -115,6 +115,9 @@ typedef struct hs_ctx_st
|
|||
struct lsquic_enc_session
|
||||
{
|
||||
enum handshake_state hsk_state;
|
||||
enum {
|
||||
ES_RECV_REJ = 1 << 2,
|
||||
} es_flags;
|
||||
|
||||
uint8_t have_key; /* 0, no 1, I, 2, D, 3, F */
|
||||
uint8_t peer_have_final_key;
|
||||
|
@ -138,6 +141,7 @@ struct lsquic_enc_session
|
|||
|
||||
hs_ctx_t hs_ctx;
|
||||
lsquic_session_cache_info_t *info;
|
||||
c_cert_item_t *cert_item;
|
||||
SSL_CTX * ssl_ctx;
|
||||
const struct lsquic_engine_public *enpub;
|
||||
struct lsquic_str * cert_ptr; /* pointer to the leaf cert of the server, not real copy */
|
||||
|
@ -152,29 +156,10 @@ struct lsquic_enc_session
|
|||
};
|
||||
|
||||
|
||||
/***
|
||||
* client side, it will store the domain/certs as cache cert
|
||||
*/
|
||||
static struct lsquic_hash *s_cached_client_certs;
|
||||
|
||||
/**
|
||||
* client side will save the session_info for next time 0rtt
|
||||
*/
|
||||
static struct lsquic_hash *s_cached_client_session_infos;
|
||||
|
||||
/* save to hash table */
|
||||
static lsquic_session_cache_info_t *retrieve_session_info_entry(const char *key);
|
||||
static void remove_expire_session_info_entry();
|
||||
static void remove_session_info_entry(struct lsquic_str *key);
|
||||
|
||||
static void free_info (lsquic_session_cache_info_t *);
|
||||
|
||||
|
||||
/* client */
|
||||
static cert_hash_item_t *make_cert_hash_item(struct lsquic_str *domain, struct lsquic_str **certs, int count);
|
||||
static int c_insert_certs(cert_hash_item_t *item);
|
||||
static void c_erase_certs(struct lsquic_hash_elem *el);
|
||||
static void c_free_cert_hash_item (cert_hash_item_t *item);
|
||||
static c_cert_item_t *make_c_cert_item(struct lsquic_str **certs, int count);
|
||||
static void free_c_cert_item(c_cert_item_t *item);
|
||||
|
||||
static int get_tag_val_u32 (unsigned char *v, int len, uint32_t *val);
|
||||
static int init_hs_hash_tables(int flags);
|
||||
|
@ -207,42 +192,9 @@ lsquic_handshake_init(int flags)
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
cleanup_hs_hash_tables (void)
|
||||
{
|
||||
struct lsquic_hash_elem *el;
|
||||
|
||||
if (s_cached_client_session_infos)
|
||||
{
|
||||
for (el = lsquic_hash_first(s_cached_client_session_infos); el;
|
||||
el = lsquic_hash_next(s_cached_client_session_infos))
|
||||
{
|
||||
lsquic_session_cache_info_t *entry = lsquic_hashelem_getdata(el);
|
||||
free_info(entry);
|
||||
}
|
||||
lsquic_hash_destroy(s_cached_client_session_infos);
|
||||
s_cached_client_session_infos = NULL;
|
||||
}
|
||||
|
||||
if (s_cached_client_certs)
|
||||
{
|
||||
for (el = lsquic_hash_first(s_cached_client_certs); el;
|
||||
el = lsquic_hash_next(s_cached_client_certs))
|
||||
{
|
||||
cert_hash_item_t *item = lsquic_hashelem_getdata(el);
|
||||
c_free_cert_hash_item(item);
|
||||
}
|
||||
lsquic_hash_destroy(s_cached_client_certs);
|
||||
s_cached_client_certs = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
lsquic_handshake_cleanup (void)
|
||||
{
|
||||
cleanup_hs_hash_tables();
|
||||
lsquic_crt_cleanup();
|
||||
}
|
||||
|
||||
|
@ -250,63 +202,26 @@ lsquic_handshake_cleanup (void)
|
|||
/* return -1 for fail, 0 OK*/
|
||||
static int init_hs_hash_tables(int flags)
|
||||
{
|
||||
if (flags & LSQUIC_GLOBAL_CLIENT)
|
||||
{
|
||||
s_cached_client_session_infos = lsquic_hash_create();
|
||||
if (!s_cached_client_session_infos)
|
||||
return -1;
|
||||
|
||||
s_cached_client_certs = lsquic_hash_create();
|
||||
if (!s_cached_client_certs)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* client */
|
||||
struct lsquic_hash_elem *
|
||||
c_get_certs_elem (const lsquic_str_t *domain)
|
||||
{
|
||||
if (!s_cached_client_certs)
|
||||
return NULL;
|
||||
|
||||
return lsquic_hash_find(s_cached_client_certs, lsquic_str_cstr(domain),
|
||||
lsquic_str_len(domain));
|
||||
}
|
||||
|
||||
|
||||
/* client */
|
||||
cert_hash_item_t *
|
||||
c_find_certs (const lsquic_str_t *domain)
|
||||
{
|
||||
struct lsquic_hash_elem *el = c_get_certs_elem(domain);
|
||||
|
||||
if (el == NULL)
|
||||
return NULL;
|
||||
|
||||
return lsquic_hashelem_getdata(el);
|
||||
}
|
||||
|
||||
|
||||
/* client */
|
||||
/* certs is an array of lsquic_str_t * */
|
||||
static cert_hash_item_t *
|
||||
make_cert_hash_item (lsquic_str_t *domain, lsquic_str_t **certs, int count)
|
||||
static c_cert_item_t *
|
||||
make_c_cert_item (lsquic_str_t **certs, int count)
|
||||
{
|
||||
int i;
|
||||
uint64_t hash;
|
||||
cert_hash_item_t *item = (cert_hash_item_t *)malloc(sizeof(cert_hash_item_t));
|
||||
c_cert_item_t *item = (c_cert_item_t *)malloc(sizeof(c_cert_item_t));
|
||||
item->crts = (lsquic_str_t *)malloc(count * sizeof(lsquic_str_t));
|
||||
item->domain = lsquic_str_new(NULL, 0);
|
||||
item->hashs = lsquic_str_new(NULL, 0);
|
||||
lsquic_str_copy(item->domain, domain);
|
||||
item->count = count;
|
||||
for(i=0; i<count; ++i)
|
||||
for (i = 0; i < count; ++i)
|
||||
{
|
||||
lsquic_str_copy(&item->crts[i], certs[i]);
|
||||
hash = fnv1a_64((const uint8_t *)lsquic_str_cstr(certs[i]), lsquic_str_len(certs[i]));
|
||||
hash = fnv1a_64((const uint8_t *)lsquic_str_cstr(certs[i]),
|
||||
lsquic_str_len(certs[i]));
|
||||
lsquic_str_append(item->hashs, (char *)&hash, 8);
|
||||
}
|
||||
return item;
|
||||
|
@ -315,13 +230,12 @@ make_cert_hash_item (lsquic_str_t *domain, lsquic_str_t **certs, int count)
|
|||
|
||||
/* client */
|
||||
static void
|
||||
c_free_cert_hash_item (cert_hash_item_t *item)
|
||||
free_c_cert_item (c_cert_item_t *item)
|
||||
{
|
||||
int i;
|
||||
if (item)
|
||||
{
|
||||
lsquic_str_delete(item->hashs);
|
||||
lsquic_str_delete(item->domain);
|
||||
for(i=0; i<item->count; ++i)
|
||||
lsquic_str_d(&item->crts[i]);
|
||||
free(item->crts);
|
||||
|
@ -330,112 +244,134 @@ c_free_cert_hash_item (cert_hash_item_t *item)
|
|||
}
|
||||
|
||||
|
||||
/* client */
|
||||
static int
|
||||
c_insert_certs (cert_hash_item_t *item)
|
||||
enum rtt_deserialize_return_type
|
||||
{
|
||||
if (lsquic_hash_insert(s_cached_client_certs,
|
||||
lsquic_str_cstr(item->domain),
|
||||
lsquic_str_len(item->domain), item) == NULL)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
RTT_DESERIALIZE_OK = 0,
|
||||
RTT_DESERIALIZE_BAD_QUIC_VER = 1,
|
||||
RTT_DESERIALIZE_BAD_SERIAL_VER = 2,
|
||||
RTT_DESERIALIZE_BAD_CERT_SIZE = 3,
|
||||
};
|
||||
|
||||
#define RTT_SERIALIZER_VERSION (1 << 0)
|
||||
|
||||
/* client */
|
||||
static void
|
||||
c_erase_certs (struct lsquic_hash_elem *el)
|
||||
lsquic_enc_session_serialize_zero_rtt(struct lsquic_zero_rtt_storage *storage,
|
||||
enum lsquic_version version,
|
||||
const lsquic_session_cache_info_t *info,
|
||||
const c_cert_item_t *cert_item)
|
||||
{
|
||||
if (s_cached_client_certs && el)
|
||||
lsquic_hash_erase(s_cached_client_certs, el);
|
||||
}
|
||||
|
||||
|
||||
static int save_session_info_entry(lsquic_str_t *key, lsquic_session_cache_info_t *entry)
|
||||
{
|
||||
lsquic_str_setto(&entry->sni_key, lsquic_str_cstr(key), lsquic_str_len(key));
|
||||
if (lsquic_hash_insert(s_cached_client_session_infos,
|
||||
lsquic_str_cstr(&entry->sni_key),
|
||||
lsquic_str_len(&entry->sni_key), entry) == NULL)
|
||||
uint32_t i;
|
||||
uint8_t *next_cert;
|
||||
struct lsquic_cert_storage *cert_storage;
|
||||
/*
|
||||
* assign versions
|
||||
*/
|
||||
storage->quic_version_tag = lsquic_ver2tag(version);
|
||||
storage->serializer_version = RTT_SERIALIZER_VERSION;
|
||||
/*
|
||||
* server config
|
||||
*/
|
||||
storage->ver = info->ver;
|
||||
storage->aead = info->aead;
|
||||
storage->kexs = info->kexs;
|
||||
storage->pdmd = info->pdmd;
|
||||
storage->orbt = info->orbt;
|
||||
storage->expy = info->expy;
|
||||
storage->sstk_len = lsquic_str_len(&info->sstk);
|
||||
storage->scfg_len = lsquic_str_len(&info->scfg);
|
||||
storage->scfg_flag = info->scfg_flag;
|
||||
memcpy(storage->sstk, lsquic_str_buf(&info->sstk), storage->sstk_len);
|
||||
memcpy(storage->scfg, lsquic_str_buf(&info->scfg), storage->scfg_len);
|
||||
memcpy(storage->sscid, &info->sscid, SCID_LENGTH);
|
||||
memcpy(storage->spubs, &info->spubs, MAX_SPUBS_LENGTH);
|
||||
/*
|
||||
* certificate chain
|
||||
*/
|
||||
storage->cert_count = (uint32_t)cert_item->count;
|
||||
next_cert = (uint8_t *)&storage->cert_storage;
|
||||
for (i = 0; i < storage->cert_count; i++)
|
||||
{
|
||||
lsquic_str_d(&entry->sni_key);
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* If entry updated and need to remove cached entry */
|
||||
static void
|
||||
remove_session_info_entry (lsquic_str_t *key)
|
||||
{
|
||||
lsquic_session_cache_info_t *entry;
|
||||
struct lsquic_hash_elem *el;
|
||||
el = lsquic_hash_find(s_cached_client_session_infos,
|
||||
lsquic_str_cstr(key), lsquic_str_len(key));
|
||||
if (el)
|
||||
{
|
||||
entry = lsquic_hashelem_getdata(el);
|
||||
lsquic_str_d(&entry->sni_key);
|
||||
lsquic_hash_erase(s_cached_client_session_infos, el);
|
||||
cert_storage = (struct lsquic_cert_storage *)next_cert;
|
||||
cert_storage->len = lsquic_str_len(&cert_item->crts[i]);
|
||||
memcpy(cert_storage->data, lsquic_str_buf(&cert_item->crts[i]),
|
||||
cert_storage->len);
|
||||
next_cert += sizeof(struct lsquic_cert_storage) + cert_storage->len;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* client */
|
||||
static lsquic_session_cache_info_t *
|
||||
retrieve_session_info_entry (const char *key)
|
||||
#define CHECK_SPACE(need, start, end) \
|
||||
do { if ((intptr_t) (need) > ( (intptr_t) (end) - (intptr_t) (start))) \
|
||||
{ return RTT_DESERIALIZE_BAD_CERT_SIZE; } \
|
||||
} while (0) \
|
||||
|
||||
static enum rtt_deserialize_return_type
|
||||
lsquic_enc_session_deserialize_zero_rtt(
|
||||
const struct lsquic_zero_rtt_storage *storage,
|
||||
size_t storage_size,
|
||||
const struct lsquic_engine_settings *settings,
|
||||
lsquic_session_cache_info_t *info,
|
||||
c_cert_item_t *cert_item)
|
||||
{
|
||||
lsquic_session_cache_info_t *entry;
|
||||
struct lsquic_hash_elem *el;
|
||||
|
||||
if (!s_cached_client_session_infos)
|
||||
return NULL;
|
||||
|
||||
if (!key)
|
||||
return NULL;
|
||||
|
||||
el = lsquic_hash_find(s_cached_client_session_infos, key, strlen(key));
|
||||
if (el == NULL)
|
||||
return NULL;
|
||||
|
||||
entry = lsquic_hashelem_getdata(el);
|
||||
LSQ_DEBUG("[QUIC]retrieve_session_info_entry find cached session info %p.\n", entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
|
||||
/* call it in timer() */
|
||||
#if __GNUC__
|
||||
__attribute__((unused))
|
||||
#endif
|
||||
static void
|
||||
remove_expire_session_info_entry (void)
|
||||
{
|
||||
time_t tm = time(NULL);
|
||||
struct lsquic_hash_elem *el;
|
||||
|
||||
for (el = lsquic_hash_first(s_cached_client_session_infos); el;
|
||||
el = lsquic_hash_next(s_cached_client_session_infos))
|
||||
uint32_t i, len;
|
||||
uint64_t hash;
|
||||
uint8_t *next_cert;
|
||||
struct lsquic_cert_storage *cert_storage;
|
||||
void *storage_end = (uint8_t *)storage + storage_size;
|
||||
/*
|
||||
* check versions
|
||||
*/
|
||||
if (lsquic_tag2ver(storage->quic_version_tag) & ~settings->es_versions)
|
||||
return RTT_DESERIALIZE_BAD_QUIC_VER;
|
||||
if (storage->serializer_version != RTT_SERIALIZER_VERSION)
|
||||
return RTT_DESERIALIZE_BAD_SERIAL_VER;
|
||||
/*
|
||||
* server config
|
||||
*/
|
||||
info->ver = storage->ver;
|
||||
info->aead = storage->aead;
|
||||
info->kexs = storage->kexs;
|
||||
info->pdmd = storage->pdmd;
|
||||
info->orbt = storage->orbt;
|
||||
info->expy = storage->expy;
|
||||
info->scfg_flag = storage->scfg_flag;
|
||||
lsquic_str_setto(&info->sstk, storage->sstk, storage->sstk_len);
|
||||
lsquic_str_setto(&info->scfg, storage->scfg, storage->scfg_len);
|
||||
memcpy(&info->sscid, storage->sscid, SCID_LENGTH);
|
||||
memcpy(&info->spubs, storage->spubs, MAX_SPUBS_LENGTH);
|
||||
/*
|
||||
* certificate chain
|
||||
*/
|
||||
cert_item->count = storage->cert_count;
|
||||
cert_item->crts = malloc(cert_item->count * sizeof(lsquic_str_t));
|
||||
cert_item->hashs = lsquic_str_new(NULL, 0);
|
||||
next_cert = (uint8_t *)storage->cert_storage;
|
||||
for (i = 0; i < storage->cert_count; i++)
|
||||
{
|
||||
lsquic_session_cache_info_t *entry = lsquic_hashelem_getdata(el);
|
||||
if ((uint64_t)tm > entry->expy)
|
||||
{
|
||||
free_info(entry);
|
||||
lsquic_hash_erase(s_cached_client_session_infos, el);
|
||||
}
|
||||
CHECK_SPACE(sizeof(struct lsquic_cert_storage), next_cert, storage_end);
|
||||
cert_storage = (struct lsquic_cert_storage *)next_cert;
|
||||
memcpy(&len, cert_storage, sizeof(len));
|
||||
CHECK_SPACE(len, cert_storage->data, storage_end);
|
||||
lsquic_str_prealloc(&cert_item->crts[i], len);
|
||||
lsquic_str_setlen(&cert_item->crts[i], len);
|
||||
memcpy(lsquic_str_buf(&cert_item->crts[i]), cert_storage->data, len);
|
||||
hash = fnv1a_64((const uint8_t *)cert_storage->data, len);
|
||||
lsquic_str_append(cert_item->hashs, (char *)&hash, 8);
|
||||
next_cert += sizeof(struct lsquic_cert_storage) + len;
|
||||
}
|
||||
return RTT_DESERIALIZE_OK;
|
||||
}
|
||||
|
||||
|
||||
static lsquic_enc_session_t *
|
||||
lsquic_enc_session_create_client (const char *domain, lsquic_cid_t cid,
|
||||
const struct lsquic_engine_public *enpub)
|
||||
const struct lsquic_engine_public *enpub,
|
||||
const unsigned char *zero_rtt, size_t zero_rtt_len)
|
||||
{
|
||||
lsquic_session_cache_info_t *info;
|
||||
lsquic_enc_session_t *enc_session;
|
||||
c_cert_item_t *item;
|
||||
const struct lsquic_zero_rtt_storage *zero_rtt_storage;
|
||||
|
||||
if (!domain)
|
||||
{
|
||||
|
@ -447,19 +383,47 @@ lsquic_enc_session_create_client (const char *domain, lsquic_cid_t cid,
|
|||
if (!enc_session)
|
||||
return NULL;
|
||||
|
||||
info = retrieve_session_info_entry(domain);
|
||||
if (info)
|
||||
memcpy(enc_session->hs_ctx.pubs, info->spubs, 32);
|
||||
else
|
||||
/* have to allocate every time */
|
||||
info = calloc(1, sizeof(*info));
|
||||
if (!info)
|
||||
{
|
||||
info = calloc(1, sizeof(*info));
|
||||
if (!info)
|
||||
{
|
||||
free(enc_session);
|
||||
return NULL;
|
||||
}
|
||||
free(enc_session);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (zero_rtt && zero_rtt_len > sizeof(struct lsquic_zero_rtt_storage))
|
||||
{
|
||||
item = calloc(1, sizeof(*item));
|
||||
if (!item)
|
||||
{
|
||||
free(enc_session);
|
||||
free(info);
|
||||
return NULL;
|
||||
}
|
||||
zero_rtt_storage = (const struct lsquic_zero_rtt_storage *)zero_rtt;
|
||||
switch (lsquic_enc_session_deserialize_zero_rtt(zero_rtt_storage,
|
||||
zero_rtt_len,
|
||||
&enpub->enp_settings,
|
||||
info, item))
|
||||
{
|
||||
case RTT_DESERIALIZE_BAD_QUIC_VER:
|
||||
LSQ_ERROR("provided zero_rtt has unsupported QUIC version");
|
||||
free(item);
|
||||
break;
|
||||
case RTT_DESERIALIZE_BAD_SERIAL_VER:
|
||||
LSQ_ERROR("provided zero_rtt has bad serializer version");
|
||||
free(item);
|
||||
break;
|
||||
case RTT_DESERIALIZE_BAD_CERT_SIZE:
|
||||
LSQ_ERROR("provided zero_rtt has bad cert size");
|
||||
free(item);
|
||||
break;
|
||||
case RTT_DESERIALIZE_OK:
|
||||
memcpy(enc_session->hs_ctx.pubs, info->spubs, 32);
|
||||
enc_session->cert_item = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
enc_session->enpub = enpub;
|
||||
enc_session->cid = cid;
|
||||
enc_session->info = info;
|
||||
|
@ -507,21 +471,23 @@ lsquic_enc_session_destroy (lsquic_enc_session_t *enc_session)
|
|||
EVP_AEAD_CTX_cleanup(enc_session->enc_ctx_f);
|
||||
free(enc_session->enc_ctx_f);
|
||||
}
|
||||
if (enc_session->info)
|
||||
{
|
||||
lsquic_str_d(&enc_session->info->sstk);
|
||||
lsquic_str_d(&enc_session->info->scfg);
|
||||
lsquic_str_d(&enc_session->info->sni_key);
|
||||
free(enc_session->info);
|
||||
}
|
||||
if (enc_session->cert_item)
|
||||
{
|
||||
free_c_cert_item(enc_session->cert_item);
|
||||
enc_session->cert_item = NULL;
|
||||
}
|
||||
free(enc_session);
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
free_info (lsquic_session_cache_info_t *info)
|
||||
{
|
||||
lsquic_str_d(&info->sstk);
|
||||
lsquic_str_d(&info->scfg);
|
||||
lsquic_str_d(&info->sni_key);
|
||||
free(info);
|
||||
}
|
||||
|
||||
|
||||
static int get_hs_state(lsquic_enc_session_t *enc_session)
|
||||
{
|
||||
return enc_session->hsk_state;
|
||||
|
@ -663,11 +629,9 @@ static int parse_hs_data (lsquic_enc_session_t *enc_session, uint32_t tag,
|
|||
break;
|
||||
|
||||
case QTAG_STK:
|
||||
if (lsquic_str_len(&enc_session->info->sstk) > 0)
|
||||
remove_session_info_entry(&enc_session->info->sstk);
|
||||
lsquic_str_setto(&enc_session->info->sstk, val, len);
|
||||
ESHIST_APPEND(enc_session, ESHE_SET_STK);
|
||||
break;
|
||||
ESHIST_APPEND(enc_session, ESHE_SET_STK);
|
||||
break;
|
||||
|
||||
case QTAG_SCID:
|
||||
if (len != SCID_LENGTH)
|
||||
|
@ -952,8 +916,7 @@ lsquic_enc_session_gen_chlo (lsquic_enc_session_t *enc_session,
|
|||
const lsquic_str_t *const ccs = get_common_certs_hash();
|
||||
const struct lsquic_engine_settings *const settings =
|
||||
&enc_session->enpub->enp_settings;
|
||||
cert_hash_item_t *const cached_certs_item =
|
||||
c_find_certs(&enc_session->hs_ctx.sni);
|
||||
c_cert_item_t *const cert_item = enc_session->cert_item;
|
||||
unsigned char pub_key[32];
|
||||
size_t ua_len;
|
||||
uint32_t opts[1]; /* Only NSTP is supported for now */
|
||||
|
@ -1006,10 +969,10 @@ lsquic_enc_session_gen_chlo (lsquic_enc_session_t *enc_session,
|
|||
MSG_LEN_ADD(msg_len, lsquic_str_len(&enc_session->hs_ctx.sni));
|
||||
++n_tags; /* SNI */
|
||||
MSG_LEN_ADD(msg_len, lsquic_str_len(ccs)); ++n_tags; /* CCS */
|
||||
if (cached_certs_item)
|
||||
if (cert_item)
|
||||
{
|
||||
enc_session->cert_ptr = &cached_certs_item->crts[0];
|
||||
MSG_LEN_ADD(msg_len, lsquic_str_len(cached_certs_item->hashs));
|
||||
enc_session->cert_ptr = &cert_item->crts[0];
|
||||
MSG_LEN_ADD(msg_len, lsquic_str_len(cert_item->hashs));
|
||||
++n_tags; /* CCRT */
|
||||
MSG_LEN_ADD(msg_len, 8); ++n_tags; /* XLCT */
|
||||
}
|
||||
|
@ -1083,14 +1046,14 @@ lsquic_enc_session_gen_chlo (lsquic_enc_session_t *enc_session,
|
|||
MW_WRITE_UINT32(&mw, QTAG_MIDS, settings->es_max_streams_in);
|
||||
MW_WRITE_UINT32(&mw, QTAG_SCLS, settings->es_silent_close);
|
||||
MW_WRITE_UINT32(&mw, QTAG_KEXS, settings->es_kexs);
|
||||
if (cached_certs_item)
|
||||
MW_WRITE_BUFFER(&mw, QTAG_XLCT, lsquic_str_buf(cached_certs_item->hashs), 8);
|
||||
if (cert_item)
|
||||
MW_WRITE_BUFFER(&mw, QTAG_XLCT, lsquic_str_buf(cert_item->hashs), 8);
|
||||
/* CSCT is empty on purpose (retained from original code) */
|
||||
MW_WRITE_TABLE_ENTRY(&mw, QTAG_CSCT, 0);
|
||||
if (n_opts > 0)
|
||||
MW_WRITE_BUFFER(&mw, QTAG_COPT, opts, n_opts * sizeof(opts[0]));
|
||||
if (cached_certs_item)
|
||||
MW_WRITE_LS_STR(&mw, QTAG_CCRT, cached_certs_item->hashs);
|
||||
if (cert_item)
|
||||
MW_WRITE_LS_STR(&mw, QTAG_CCRT, cert_item->hashs);
|
||||
MW_WRITE_UINT32(&mw, QTAG_CFCW, settings->es_cfcw);
|
||||
MW_WRITE_UINT32(&mw, QTAG_SFCW, settings->es_sfcw);
|
||||
MW_END(&mw);
|
||||
|
@ -1337,16 +1300,16 @@ static int determine_keys(lsquic_enc_session_t *enc_session)
|
|||
|
||||
|
||||
/* 0 Match */
|
||||
static int cached_certs_match(cert_hash_item_t *cached_certs_item, lsquic_str_t **certs,
|
||||
int certs_count)
|
||||
static int cached_certs_match(c_cert_item_t *item,
|
||||
lsquic_str_t **certs, int count)
|
||||
{
|
||||
int i;
|
||||
if (!cached_certs_item || cached_certs_item->count != certs_count)
|
||||
if (!item || item->count != count)
|
||||
return -1;
|
||||
|
||||
for (i=0; i<certs_count; ++i)
|
||||
for (i=0; i<count; ++i)
|
||||
{
|
||||
if (lsquic_str_bcmp(certs[i], &cached_certs_item->crts[i]) != 0)
|
||||
if (lsquic_str_bcmp(certs[i], &item->crts[i]) != 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1383,12 +1346,7 @@ lsquic_enc_session_handle_chlo_reply (lsquic_enc_session_t *enc_session,
|
|||
uint32_t head_tag;
|
||||
int ret;
|
||||
lsquic_session_cache_info_t *info = enc_session->info;
|
||||
hs_ctx_t * hs_ctx = &enc_session->hs_ctx;
|
||||
cert_hash_item_t *cached_certs_item = NULL;
|
||||
struct lsquic_hash_elem *el = c_get_certs_elem(&hs_ctx->sni);
|
||||
|
||||
if (el)
|
||||
cached_certs_item = lsquic_hashelem_getdata(el);
|
||||
c_cert_item_t *cert_item = enc_session->cert_item;
|
||||
|
||||
/* FIXME get the number first */
|
||||
lsquic_str_t **out_certs = NULL;
|
||||
|
@ -1407,7 +1365,10 @@ lsquic_enc_session_handle_chlo_reply (lsquic_enc_session_t *enc_session,
|
|||
}
|
||||
|
||||
if (head_tag == QTAG_SREJ || head_tag == QTAG_REJ)
|
||||
{
|
||||
enc_session->hsk_state = HSK_CHLO_REJ;
|
||||
enc_session->es_flags |= ES_RECV_REJ;
|
||||
}
|
||||
else if(head_tag == QTAG_SHLO)
|
||||
{
|
||||
enc_session->hsk_state = HSK_COMPLETED;
|
||||
|
@ -1428,7 +1389,7 @@ lsquic_enc_session_handle_chlo_reply (lsquic_enc_session_t *enc_session,
|
|||
out_certs_count = get_certs_count(&enc_session->hs_ctx.crt);
|
||||
if (out_certs_count > 0)
|
||||
{
|
||||
out_certs = (lsquic_str_t **)malloc(out_certs_count * sizeof(lsquic_str_t *));
|
||||
out_certs = malloc(out_certs_count * sizeof(lsquic_str_t *));
|
||||
if (!out_certs)
|
||||
{
|
||||
ret = -1;
|
||||
|
@ -1440,30 +1401,22 @@ lsquic_enc_session_handle_chlo_reply (lsquic_enc_session_t *enc_session,
|
|||
|
||||
ret = handle_chlo_reply_verify_prof(enc_session, out_certs,
|
||||
&out_certs_count,
|
||||
(cached_certs_item ? cached_certs_item->crts : NULL),
|
||||
(cached_certs_item ? cached_certs_item->count : 0));
|
||||
(cert_item ? cert_item->crts : NULL),
|
||||
(cert_item ? cert_item->count : 0));
|
||||
if (ret == 0)
|
||||
{
|
||||
if (out_certs_count > 0)
|
||||
{
|
||||
if (cached_certs_item &&
|
||||
cached_certs_match(cached_certs_item, out_certs, out_certs_count) == 0)
|
||||
;
|
||||
else
|
||||
if (cached_certs_match(cert_item, out_certs,
|
||||
out_certs_count) != 0)
|
||||
{
|
||||
if (el)
|
||||
c_erase_certs(el);
|
||||
if (cached_certs_item)
|
||||
c_free_cert_hash_item(cached_certs_item);
|
||||
|
||||
cached_certs_item = make_cert_hash_item(&hs_ctx->sni,
|
||||
out_certs, out_certs_count);
|
||||
c_insert_certs(cached_certs_item);
|
||||
cert_item = make_c_cert_item(out_certs,
|
||||
out_certs_count);
|
||||
enc_session->cert_item = cert_item;
|
||||
enc_session->cert_ptr = &cert_item->crts[0];
|
||||
}
|
||||
enc_session->cert_ptr = &cached_certs_item->crts[0];
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<out_certs_count; ++i)
|
||||
lsquic_str_delete(out_certs[i]);
|
||||
free(out_certs);
|
||||
|
@ -1476,8 +1429,6 @@ lsquic_enc_session_handle_chlo_reply (lsquic_enc_session_t *enc_session,
|
|||
|
||||
if (enc_session->hsk_state == HSK_COMPLETED)
|
||||
{
|
||||
if (!lsquic_str_buf(&info->sni_key))
|
||||
save_session_info_entry(&enc_session->hs_ctx.sni, info);
|
||||
ret = determine_keys(enc_session
|
||||
); /* FIXME: check ret */
|
||||
enc_session->have_key = 3;
|
||||
|
@ -1894,15 +1845,36 @@ lsquic_enc_session_verify_reset_token (lsquic_enc_session_t *enc_session,
|
|||
}
|
||||
|
||||
|
||||
static int
|
||||
lsquic_enc_session_did_zero_rtt_succeed (const lsquic_enc_session_t *enc_session)
|
||||
{
|
||||
return !(enc_session->es_flags & ES_RECV_REJ);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
lsquic_enc_session_is_zero_rtt_enabled (const lsquic_enc_session_t *enc_session)
|
||||
{
|
||||
return enc_session->info && enc_session->cert_item;
|
||||
}
|
||||
|
||||
|
||||
static c_cert_item_t *
|
||||
lsquic_enc_session_get_cert_item (const lsquic_enc_session_t *enc_session)
|
||||
{
|
||||
return enc_session->cert_item;
|
||||
}
|
||||
|
||||
|
||||
static STACK_OF(X509) *
|
||||
lsquic_enc_session_get_server_cert_chain (lsquic_enc_session_t *enc_session)
|
||||
{
|
||||
const struct cert_hash_item_st *item;
|
||||
const struct c_cert_item_st *item;
|
||||
STACK_OF(X509) *chain;
|
||||
X509 *cert;
|
||||
int i;
|
||||
|
||||
item = c_find_certs(&enc_session->hs_ctx.sni);
|
||||
item = enc_session->cert_item;
|
||||
if (!item)
|
||||
{
|
||||
LSQ_WARN("could not find certificates for `%.*s'",
|
||||
|
@ -1929,6 +1901,37 @@ lsquic_enc_session_get_server_cert_chain (lsquic_enc_session_t *enc_session)
|
|||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
lsquic_enc_session_get_zero_rtt (lsquic_enc_session_t *enc_session,
|
||||
enum lsquic_version version,
|
||||
void *buf, size_t len)
|
||||
{
|
||||
int i;
|
||||
size_t sz = 0;
|
||||
if (!enc_session->info || !enc_session->cert_item)
|
||||
{
|
||||
LSQ_DEBUG("client asked for rtt_into but it is not available");
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < enc_session->cert_item->count; ++i)
|
||||
{
|
||||
sz += sizeof(struct lsquic_cert_storage);
|
||||
sz += lsquic_str_len(&enc_session->cert_item->crts[i]);
|
||||
}
|
||||
sz += sizeof(struct lsquic_zero_rtt_storage);
|
||||
if (len < sz)
|
||||
{
|
||||
LSQ_DEBUG("client provided buf is too small %lu < %lu", len, sz);
|
||||
errno = ENOBUFS;
|
||||
return -1;
|
||||
}
|
||||
lsquic_enc_session_serialize_zero_rtt((struct lsquic_zero_rtt_storage *)buf,
|
||||
version, enc_session->info,
|
||||
enc_session->cert_item);
|
||||
return sz;
|
||||
}
|
||||
|
||||
|
||||
#ifdef NDEBUG
|
||||
const
|
||||
#endif
|
||||
|
@ -1951,7 +1954,11 @@ struct enc_session_funcs lsquic_enc_session_gquic_1 =
|
|||
.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,
|
||||
.esf_did_zero_rtt_succeed = lsquic_enc_session_did_zero_rtt_succeed,
|
||||
.esf_is_zero_rtt_enabled = lsquic_enc_session_is_zero_rtt_enabled,
|
||||
.esf_get_cert_item = lsquic_enc_session_get_cert_item,
|
||||
.esf_get_server_cert_chain = lsquic_enc_session_get_server_cert_chain,
|
||||
.esf_get_zero_rtt = lsquic_enc_session_get_zero_rtt,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@ struct stack_st_X509;
|
|||
|
||||
typedef struct lsquic_enc_session lsquic_enc_session_t;
|
||||
|
||||
#define MAX_SCFG_LENGTH 512
|
||||
#define MAX_SPUBS_LENGTH 32
|
||||
#define STK_LENGTH 60
|
||||
#define SNO_LENGTH 56
|
||||
#define SCID_LENGTH 16
|
||||
|
@ -37,6 +39,14 @@ enum enc_level
|
|||
|
||||
extern const char *const lsquic_enclev2str[];
|
||||
|
||||
/* client */
|
||||
typedef struct c_cert_item_st
|
||||
{
|
||||
struct lsquic_str* crts;
|
||||
struct lsquic_str* hashs;
|
||||
int count;
|
||||
} c_cert_item_t;
|
||||
|
||||
/* client side need to store 0rtt info per STK */
|
||||
typedef struct lsquic_session_cache_info_st
|
||||
{
|
||||
|
@ -55,6 +65,33 @@ typedef struct lsquic_session_cache_info_st
|
|||
|
||||
} lsquic_session_cache_info_t;
|
||||
|
||||
struct lsquic_cert_storage
|
||||
{
|
||||
uint32_t len;
|
||||
uint8_t data[0];
|
||||
};
|
||||
|
||||
struct lsquic_zero_rtt_storage
|
||||
{
|
||||
uint32_t quic_version_tag;
|
||||
uint32_t serializer_version;
|
||||
uint32_t ver;
|
||||
uint32_t aead;
|
||||
uint32_t kexs;
|
||||
uint32_t pdmd;
|
||||
uint64_t orbt;
|
||||
uint64_t expy;
|
||||
uint64_t sstk_len;
|
||||
uint64_t scfg_len;
|
||||
uint64_t scfg_flag;
|
||||
uint8_t sstk[STK_LENGTH];
|
||||
uint8_t scfg[MAX_SCFG_LENGTH];
|
||||
uint8_t sscid[SCID_LENGTH];
|
||||
uint8_t spubs[MAX_SPUBS_LENGTH];
|
||||
uint32_t cert_count;
|
||||
struct lsquic_cert_storage cert_storage[0];
|
||||
};
|
||||
|
||||
#ifndef LSQUIC_KEEP_ENC_SESS_HISTORY
|
||||
# ifndef NDEBUG
|
||||
# define LSQUIC_KEEP_ENC_SESS_HISTORY 1
|
||||
|
@ -120,7 +157,8 @@ struct enc_session_funcs
|
|||
/* Create client session */
|
||||
lsquic_enc_session_t *
|
||||
(*esf_create_client) (const char *domain, lsquic_cid_t cid,
|
||||
const struct lsquic_engine_public *);
|
||||
const struct lsquic_engine_public *,
|
||||
const unsigned char *, size_t);
|
||||
|
||||
/* Generate connection ID */
|
||||
lsquic_cid_t (*esf_generate_cid) (void);
|
||||
|
@ -141,8 +179,21 @@ struct enc_session_funcs
|
|||
(*esf_verify_reset_token) (lsquic_enc_session_t *, const unsigned char *,
|
||||
size_t);
|
||||
|
||||
int
|
||||
(*esf_did_zero_rtt_succeed) (const lsquic_enc_session_t *);
|
||||
|
||||
int
|
||||
(*esf_is_zero_rtt_enabled) (const lsquic_enc_session_t *);
|
||||
|
||||
c_cert_item_t *
|
||||
(*esf_get_cert_item) (const lsquic_enc_session_t *);
|
||||
|
||||
struct stack_st_X509 *
|
||||
(*esf_get_server_cert_chain) (lsquic_enc_session_t *);
|
||||
|
||||
ssize_t
|
||||
(*esf_get_zero_rtt) (lsquic_enc_session_t *, enum lsquic_version,
|
||||
void *, size_t);
|
||||
};
|
||||
|
||||
extern
|
||||
|
@ -154,14 +205,4 @@ struct enc_session_funcs lsquic_enc_session_gquic_1;
|
|||
#define select_esf_by_ver(ver) \
|
||||
(ver ? &lsquic_enc_session_gquic_1 : &lsquic_enc_session_gquic_1)
|
||||
|
||||
/* client side, certs and hashs
|
||||
*/
|
||||
typedef struct cert_hash_item_st
|
||||
{
|
||||
struct lsquic_str* domain; /*with port, such as "xyz.com:8088" as the key */
|
||||
struct lsquic_str* crts;
|
||||
struct lsquic_str* hashs;
|
||||
int count;
|
||||
} cert_hash_item_t;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -323,7 +323,10 @@ lsquic_packet_out_elide_reset_stream_frames (lsquic_packet_out_t *packet_out,
|
|||
|
||||
assert(n_stream_frames);
|
||||
if (n_elided == n_stream_frames)
|
||||
{
|
||||
packet_out->po_frame_types &= ~(1 << QUIC_FRAME_STREAM);
|
||||
packet_out->po_flags &= ~PO_STREAM_END;
|
||||
}
|
||||
|
||||
return adj;
|
||||
}
|
||||
|
|
|
@ -674,8 +674,6 @@ lsquic_send_ctl_got_ack (lsquic_send_ctl_t *ctl,
|
|||
const struct ack_info *acki,
|
||||
lsquic_time_t ack_recv_time)
|
||||
{
|
||||
struct lsquic_packets_tailq acked_acks =
|
||||
TAILQ_HEAD_INITIALIZER(acked_acks);
|
||||
const struct lsquic_packno_range *range =
|
||||
&acki->ranges[ acki->n_ranges - 1 ];
|
||||
lsquic_packet_out_t *packet_out, *next;
|
||||
|
@ -1401,18 +1399,20 @@ lsquic_send_ctl_elide_stream_frames (lsquic_send_ctl_t *ctl, uint32_t stream_id)
|
|||
packet_out; packet_out = next)
|
||||
{
|
||||
next = TAILQ_NEXT(packet_out, po_next);
|
||||
assert(packet_out->po_frame_types & (1 << QUIC_FRAME_STREAM));
|
||||
lsquic_packet_out_elide_reset_stream_frames(packet_out, stream_id);
|
||||
if (0 == packet_out->po_frame_types)
|
||||
if (packet_out->po_frame_types & (1 << QUIC_FRAME_STREAM))
|
||||
{
|
||||
LSQ_DEBUG("cancel buffered packet in queue #%u after eliding "
|
||||
"frames for stream %"PRIu32, n, stream_id);
|
||||
TAILQ_REMOVE(&ctl->sc_buffered_packets[n].bpq_packets,
|
||||
packet_out, po_next);
|
||||
--ctl->sc_buffered_packets[n].bpq_count;
|
||||
send_ctl_destroy_packet(ctl, packet_out);
|
||||
LSQ_DEBUG("Elide packet from buffered queue #%u; count: %u",
|
||||
n, ctl->sc_buffered_packets[n].bpq_count);
|
||||
lsquic_packet_out_elide_reset_stream_frames(packet_out, stream_id);
|
||||
if (0 == packet_out->po_frame_types)
|
||||
{
|
||||
LSQ_DEBUG("cancel buffered packet in queue #%u after eliding "
|
||||
"frames for stream %"PRIu32, n, stream_id);
|
||||
TAILQ_REMOVE(&ctl->sc_buffered_packets[n].bpq_packets,
|
||||
packet_out, po_next);
|
||||
--ctl->sc_buffered_packets[n].bpq_count;
|
||||
send_ctl_destroy_packet(ctl, packet_out);
|
||||
LSQ_DEBUG("Elide packet from buffered queue #%u; count: %u",
|
||||
n, ctl->sc_buffered_packets[n].bpq_count);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1687,7 +1687,6 @@ send_ctl_get_buffered_packet (lsquic_send_ctl_t *ctl,
|
|||
if (packet_q->bpq_count >= send_ctl_max_bpq_count(ctl, packet_type))
|
||||
return NULL;
|
||||
|
||||
bits = lsquic_send_ctl_guess_packno_bits(ctl);
|
||||
if (packet_q->bpq_count == 0)
|
||||
{
|
||||
/* If ACK was written to the low-priority queue first, steal it */
|
||||
|
|
|
@ -109,7 +109,7 @@ find_and_set_lowest_priority (struct stream_prio_iter *iter)
|
|||
if (iter->spi_set[ set ])
|
||||
break;
|
||||
|
||||
if (set == 4)
|
||||
if (set >= 4)
|
||||
{
|
||||
//SPI_DEBUG("%s: cannot find any", __func__);
|
||||
return -1;
|
||||
|
|
|
@ -5860,7 +5860,7 @@ henc_huffman_enc (const unsigned char *src, const unsigned char *const src_end,
|
|||
bits_left -= cur_enc_code.bits;
|
||||
while (bits_left <= 32)
|
||||
{
|
||||
*p_dst++ = bits >> 32;
|
||||
*p_dst++ = (unsigned char) (bits >> 32);
|
||||
bits <<= 8;
|
||||
bits_left += 8;
|
||||
if (p_dst == dst_end)
|
||||
|
@ -5872,7 +5872,7 @@ henc_huffman_enc (const unsigned char *src, const unsigned char *const src_end,
|
|||
{
|
||||
assert(bits_left < 40 && bits_left > 0);
|
||||
bits |= ((uint64_t)1 << bits_left) - 1;
|
||||
*p_dst++ = bits >> 32;
|
||||
*p_dst++ = (unsigned char) (bits >> 32);
|
||||
}
|
||||
|
||||
return p_dst - dst;
|
||||
|
@ -5925,7 +5925,7 @@ lshpack_enc_enc_str (unsigned char *const dst, size_t dst_len,
|
|||
{
|
||||
if (str_len < 127)
|
||||
{
|
||||
*dst = str_len;
|
||||
*dst = (unsigned char) str_len;
|
||||
memcpy(dst + 1, str, str_len);
|
||||
return 1 + str_len;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue