Release 2.10.2

- [BUGFIX] Do not delay ACKs for Initial and Handshake packets.
- [BUGFIX] Send PATH_CHALLENGE if path changed before mini conn promotion.
- Logging improvements.
- http_client: discard data faster.
This commit is contained in:
Dmitri Tikhonov 2020-01-30 17:12:47 -05:00
parent 4ab453a184
commit 8c1565cb1c
12 changed files with 127 additions and 54 deletions

View file

@ -1,3 +1,11 @@
2020-01-30
- 2.10.2
- [BUGFIX] Do not delay ACKs for Initial and Handshake packets.
- [BUGFIX] Send PATH_CHALLENGE if path changed before mini conn
promotion.
- Logging improvements.
- http_client: discard data faster.
2020-01-29 2020-01-29
- 2.10.1 - 2.10.1
- [BUGFIX] Coalesced packets could get longer than normal packet - [BUGFIX] Coalesced packets could get longer than normal packet

View file

@ -25,7 +25,7 @@ extern "C" {
#define LSQUIC_MAJOR_VERSION 2 #define LSQUIC_MAJOR_VERSION 2
#define LSQUIC_MINOR_VERSION 10 #define LSQUIC_MINOR_VERSION 10
#define LSQUIC_PATCH_VERSION 1 #define LSQUIC_PATCH_VERSION 2
/** /**
* Engine flags: * Engine flags:

View file

@ -27,6 +27,7 @@ enum alarm_id {
AL_RETX_APP = AL_RETX_INIT + PNS_APP, AL_RETX_APP = AL_RETX_INIT + PNS_APP,
AL_PING, AL_PING,
AL_IDLE, AL_IDLE,
/* TODO: remove AL_ACK_INIT and AL_ACK_HSK when LSQVER_ID24 is removed */
AL_ACK_INIT, AL_ACK_INIT,
AL_ACK_HSK = AL_ACK_INIT + PNS_HSK, AL_ACK_HSK = AL_ACK_INIT + PNS_HSK,
AL_ACK_APP = AL_ACK_INIT + PNS_APP, AL_ACK_APP = AL_ACK_INIT + PNS_APP,

View file

@ -481,10 +481,10 @@ ack_alarm_expired (enum alarm_id al_id, void *ctx, lsquic_time_t expiry,
lsquic_time_t now) lsquic_time_t now)
{ {
struct ietf_full_conn *conn = ctx; struct ietf_full_conn *conn = ctx;
enum packnum_space pns = al_id - AL_ACK_INIT; assert(al_id == AL_ACK_APP);
LSQ_DEBUG("%s ACK timer expired (%"PRIu64" < %"PRIu64"): ACK queued", LSQ_DEBUG("%s ACK timer expired (%"PRIu64" < %"PRIu64"): ACK queued",
lsquic_pns2str[pns], expiry, now); lsquic_pns2str[PNS_APP], expiry, now);
conn->ifc_flags |= IFC_ACK_QUED_INIT << pns; conn->ifc_flags |= IFC_ACK_QUED_APP;
} }
@ -671,7 +671,7 @@ log_scids (const struct ietf_full_conn *conn)
if (cce->cce_flags & CCE_REG) flags[fi++] = 'r'; if (cce->cce_flags & CCE_REG) flags[fi++] = 'r';
if (cce->cce_flags & CCE_SEQNO) flags[fi++] = 's'; if (cce->cce_flags & CCE_SEQNO) flags[fi++] = 's';
if (cce->cce_flags & CCE_USED) flags[fi++] = 'u'; if (cce->cce_flags & CCE_USED) flags[fi++] = 'u';
flags[fi] = '\0'; flags[fi] = '\0';
if (lconn->cn_cces_mask & (1 << idx)) if (lconn->cn_cces_mask & (1 << idx))
{ {
if (cce->cce_flags & CCE_PORT) if (cce->cce_flags & CCE_PORT)
@ -1038,8 +1038,6 @@ ietf_full_conn_init (struct ietf_full_conn *conn,
lsquic_alarmset_init(&conn->ifc_alset, &conn->ifc_conn); lsquic_alarmset_init(&conn->ifc_alset, &conn->ifc_conn);
lsquic_alarmset_init_alarm(&conn->ifc_alset, AL_IDLE, idle_alarm_expired, conn); lsquic_alarmset_init_alarm(&conn->ifc_alset, AL_IDLE, idle_alarm_expired, conn);
lsquic_alarmset_init_alarm(&conn->ifc_alset, AL_ACK_APP, ack_alarm_expired, conn); lsquic_alarmset_init_alarm(&conn->ifc_alset, AL_ACK_APP, ack_alarm_expired, conn);
lsquic_alarmset_init_alarm(&conn->ifc_alset, AL_ACK_INIT, ack_alarm_expired, conn);
lsquic_alarmset_init_alarm(&conn->ifc_alset, AL_ACK_HSK, ack_alarm_expired, conn);
lsquic_alarmset_init_alarm(&conn->ifc_alset, AL_PING, ping_alarm_expired, conn); lsquic_alarmset_init_alarm(&conn->ifc_alset, AL_PING, ping_alarm_expired, conn);
lsquic_alarmset_init_alarm(&conn->ifc_alset, AL_HANDSHAKE, handshake_alarm_expired, conn); lsquic_alarmset_init_alarm(&conn->ifc_alset, AL_HANDSHAKE, handshake_alarm_expired, conn);
lsquic_alarmset_init_alarm(&conn->ifc_alset, AL_CID_THROT, cid_throt_alarm_expired, conn); lsquic_alarmset_init_alarm(&conn->ifc_alset, AL_CID_THROT, cid_throt_alarm_expired, conn);
@ -1279,6 +1277,11 @@ lsquic_ietf_full_conn_server_new (struct lsquic_engine_public *enpub,
conn->ifc_paths[0].cop_path = imc->imc_path; conn->ifc_paths[0].cop_path = imc->imc_path;
conn->ifc_paths[0].cop_flags = COP_VALIDATED; conn->ifc_paths[0].cop_flags = COP_VALIDATED;
conn->ifc_used_paths = 1 << 0; conn->ifc_used_paths = 1 << 0;
if (imc->imc_flags & IMC_PATH_CHANGED)
{
LSQ_DEBUG("path changed during mini conn: schedule PATH_CHALLENGE");
conn->ifc_send_flags |= SF_SEND_PATH_CHAL_PATH_0;
}
#ifndef NDEBUG #ifndef NDEBUG
if (getenv("LSQUIC_CN_PACK_SIZE")) if (getenv("LSQUIC_CN_PACK_SIZE"))
{ {
@ -1524,10 +1527,14 @@ generate_ack_frame_for_pns (struct ietf_full_conn *conn,
} }
conn->ifc_n_slack_akbl[pns] = 0; conn->ifc_n_slack_akbl[pns] = 0;
if (PNS_APP == pns)
conn->ifc_n_slack_all = 0;
conn->ifc_flags &= ~(IFC_ACK_QUED_INIT << pns); conn->ifc_flags &= ~(IFC_ACK_QUED_INIT << pns);
lsquic_alarmset_unset(&conn->ifc_alset, AL_ACK_INIT + pns); if (pns == PNS_APP)
{
conn->ifc_n_slack_all = 0;
lsquic_alarmset_unset(&conn->ifc_alset, AL_ACK_APP);
}
else
assert(!lsquic_alarmset_is_set(&conn->ifc_alset, AL_ACK_INIT + pns));
lsquic_send_ctl_sanity_check(&conn->ifc_send_ctl); lsquic_send_ctl_sanity_check(&conn->ifc_send_ctl);
LSQ_DEBUG("%s ACK state reset", lsquic_pns2str[pns]); LSQ_DEBUG("%s ACK state reset", lsquic_pns2str[pns]);
@ -1968,6 +1975,8 @@ generate_max_stream_data_frame (struct ietf_full_conn *conn,
ABORT_ERROR("Generating MAX_STREAM_DATA frame failed"); ABORT_ERROR("Generating MAX_STREAM_DATA frame failed");
return 0; return 0;
} }
EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "generated %d-byte MAX_STREAM_DATA "
"frame; stream_id: %"PRIu64"; offset: %"PRIu64, sz, stream->id, off);
lsquic_send_ctl_incr_pack_sz(&conn->ifc_send_ctl, packet_out, sz); lsquic_send_ctl_incr_pack_sz(&conn->ifc_send_ctl, packet_out, sz);
packet_out->po_frame_types |= 1 << QUIC_FRAME_MAX_STREAM_DATA; packet_out->po_frame_types |= 1 << QUIC_FRAME_MAX_STREAM_DATA;
lsquic_stream_max_stream_data_sent(stream); lsquic_stream_max_stream_data_sent(stream);
@ -1998,6 +2007,8 @@ generate_stream_blocked_frame (struct ietf_full_conn *conn,
ABORT_ERROR("Generating STREAM_BLOCKED frame failed"); ABORT_ERROR("Generating STREAM_BLOCKED frame failed");
return 0; return 0;
} }
EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "generated %d-byte STREAM_BLOCKED "
"frame; stream_id: %"PRIu64"; offset: %"PRIu64, sz, stream->id, off);
lsquic_send_ctl_incr_pack_sz(&conn->ifc_send_ctl, packet_out, sz); lsquic_send_ctl_incr_pack_sz(&conn->ifc_send_ctl, packet_out, sz);
packet_out->po_frame_types |= 1 << QUIC_FRAME_STREAM_BLOCKED; packet_out->po_frame_types |= 1 << QUIC_FRAME_STREAM_BLOCKED;
lsquic_stream_blocked_frame_sent(stream); lsquic_stream_blocked_frame_sent(stream);
@ -4860,6 +4871,8 @@ process_max_data_frame (struct ietf_full_conn *conn,
if (parsed_len < 0) if (parsed_len < 0)
return 0; return 0;
EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "MAX_DATA frame in; offset: %"PRIu64,
max_data);
if (max_data > conn->ifc_pub.conn_cap.cc_max) if (max_data > conn->ifc_pub.conn_cap.cc_max)
{ {
LSQ_DEBUG("max data goes from %"PRIu64" to %"PRIu64, LSQ_DEBUG("max data goes from %"PRIu64" to %"PRIu64,
@ -4888,6 +4901,8 @@ process_max_stream_data_frame (struct ietf_full_conn *conn,
if (parsed_len < 0) if (parsed_len < 0)
return 0; return 0;
EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "MAX_STREAM_DATA frame in; "
"stream_id: %"PRIu64"; offset: %"PRIu64, stream_id, max_data);
if (conn_is_receive_only_stream(conn, stream_id)) if (conn_is_receive_only_stream(conn, stream_id))
{ {
ABORT_QUIETLY(0, TEC_STREAM_STATE_ERROR, ABORT_QUIETLY(0, TEC_STREAM_STATE_ERROR,
@ -5585,26 +5600,26 @@ many_in_and_will_write (struct ietf_full_conn *conn)
static void static void
try_queueing_ack (struct ietf_full_conn *conn, enum packnum_space pns, try_queueing_ack_app (struct ietf_full_conn *conn,
int was_missing, lsquic_time_t now) int was_missing, lsquic_time_t now)
{ {
lsquic_time_t srtt, ack_timeout; lsquic_time_t srtt, ack_timeout;
if (conn->ifc_n_slack_akbl[pns] >= MAX_RETR_PACKETS_SINCE_LAST_ACK if (conn->ifc_n_slack_akbl[PNS_APP] >= MAX_RETR_PACKETS_SINCE_LAST_ACK
|| ((conn->ifc_flags & IFC_ACK_HAD_MISS) || ((conn->ifc_flags & IFC_ACK_HAD_MISS)
&& was_missing && conn->ifc_n_slack_akbl[pns] > 0) && was_missing && conn->ifc_n_slack_akbl[PNS_APP] > 0)
|| (PNS_APP == pns && many_in_and_will_write(conn))) || many_in_and_will_write(conn))
{ {
lsquic_alarmset_unset(&conn->ifc_alset, AL_ACK_INIT + pns); lsquic_alarmset_unset(&conn->ifc_alset, AL_ACK_APP);
lsquic_send_ctl_sanity_check(&conn->ifc_send_ctl); lsquic_send_ctl_sanity_check(&conn->ifc_send_ctl);
conn->ifc_flags |= IFC_ACK_QUED_INIT << pns; conn->ifc_flags |= IFC_ACK_QUED_APP;
LSQ_DEBUG("%s ACK queued: ackable: %u; all: %u; had_miss: %d; " LSQ_DEBUG("%s ACK queued: ackable: %u; all: %u; had_miss: %d; "
"was_missing: %d", "was_missing: %d",
lsquic_pns2str[pns], conn->ifc_n_slack_akbl[pns], lsquic_pns2str[PNS_APP], conn->ifc_n_slack_akbl[PNS_APP],
conn->ifc_n_slack_all, conn->ifc_n_slack_all,
!!(conn->ifc_flags & IFC_ACK_HAD_MISS), was_missing); !!(conn->ifc_flags & IFC_ACK_HAD_MISS), was_missing);
} }
else if (conn->ifc_n_slack_akbl[pns] > 0) else if (conn->ifc_n_slack_akbl[PNS_APP] > 0)
{ {
/* See https://github.com/quicwg/base-drafts/issues/3304 for more */ /* See https://github.com/quicwg/base-drafts/issues/3304 for more */
srtt = lsquic_rtt_stats_get_srtt(&conn->ifc_pub.rtt_stats); srtt = lsquic_rtt_stats_get_srtt(&conn->ifc_pub.rtt_stats);
@ -5612,14 +5627,38 @@ try_queueing_ack (struct ietf_full_conn *conn, enum packnum_space pns,
ack_timeout = MAX(1000, MIN(ACK_TIMEOUT, srtt / 4)); ack_timeout = MAX(1000, MIN(ACK_TIMEOUT, srtt / 4));
else else
ack_timeout = ACK_TIMEOUT; ack_timeout = ACK_TIMEOUT;
lsquic_alarmset_set(&conn->ifc_alset, AL_ACK_INIT + pns, lsquic_alarmset_set(&conn->ifc_alset, AL_ACK_APP,
now + ack_timeout); now + ack_timeout);
LSQ_DEBUG("%s ACK alarm set to %"PRIu64, lsquic_pns2str[pns], LSQ_DEBUG("%s ACK alarm set to %"PRIu64, lsquic_pns2str[PNS_APP],
now + ack_timeout); now + ack_timeout);
} }
} }
static void
try_queueing_ack_init_or_hsk (struct ietf_full_conn *conn,
enum packnum_space pns)
{
if (conn->ifc_n_slack_akbl[pns] > 0)
{
conn->ifc_flags |= IFC_ACK_QUED_INIT << pns;
LSQ_DEBUG("%s ACK queued: ackable: %u",
lsquic_pns2str[pns], conn->ifc_n_slack_akbl[pns]);
}
}
static void
try_queueing_ack (struct ietf_full_conn *conn, enum packnum_space pns,
int was_missing, lsquic_time_t now)
{
if (PNS_APP == pns)
try_queueing_ack_app(conn, was_missing, now);
else
try_queueing_ack_init_or_hsk(conn, pns);
}
static int static int
maybe_queue_opp_ack (struct ietf_full_conn *conn) maybe_queue_opp_ack (struct ietf_full_conn *conn)
{ {
@ -5736,9 +5775,6 @@ process_retry_packet (struct ietf_full_conn *conn,
lsquic_alarmset_unset(&conn->ifc_alset, AL_RETX_INIT); lsquic_alarmset_unset(&conn->ifc_alset, AL_RETX_INIT);
lsquic_alarmset_unset(&conn->ifc_alset, AL_RETX_HSK); lsquic_alarmset_unset(&conn->ifc_alset, AL_RETX_HSK);
lsquic_alarmset_unset(&conn->ifc_alset, AL_RETX_APP); lsquic_alarmset_unset(&conn->ifc_alset, AL_RETX_APP);
lsquic_alarmset_unset(&conn->ifc_alset, AL_ACK_INIT);
lsquic_alarmset_unset(&conn->ifc_alset, AL_ACK_HSK);
lsquic_alarmset_unset(&conn->ifc_alset, AL_ACK_APP);
LSQ_INFO("Received a retry packet. Will retry."); LSQ_INFO("Received a retry packet. Will retry.");
conn->ifc_flags |= IFC_RETRIED; conn->ifc_flags |= IFC_RETRIED;
@ -5821,7 +5857,6 @@ ignore_init (struct ietf_full_conn *conn)
LSQ_DEBUG("henceforth, no Initial packets shall be sent or received"); LSQ_DEBUG("henceforth, no Initial packets shall be sent or received");
conn->ifc_flags |= IFC_IGNORE_INIT; conn->ifc_flags |= IFC_IGNORE_INIT;
conn->ifc_flags &= ~(IFC_ACK_QUED_INIT << PNS_INIT); conn->ifc_flags &= ~(IFC_ACK_QUED_INIT << PNS_INIT);
lsquic_alarmset_unset(&conn->ifc_alset, AL_ACK_INIT + PNS_INIT);
lsquic_send_ctl_empty_pns(&conn->ifc_send_ctl, PNS_INIT); lsquic_send_ctl_empty_pns(&conn->ifc_send_ctl, PNS_INIT);
lsquic_rechist_cleanup(&conn->ifc_rechist[PNS_INIT]); lsquic_rechist_cleanup(&conn->ifc_rechist[PNS_INIT]);
if (!(conn->ifc_flags & IFC_SERVER)) if (!(conn->ifc_flags & IFC_SERVER))
@ -5842,7 +5877,6 @@ ignore_hsk (struct ietf_full_conn *conn)
LSQ_DEBUG("henceforth, no Handshake packets shall be sent or received"); LSQ_DEBUG("henceforth, no Handshake packets shall be sent or received");
conn->ifc_flags |= IFC_IGNORE_HSK; conn->ifc_flags |= IFC_IGNORE_HSK;
conn->ifc_flags &= ~(IFC_ACK_QUED_INIT << PNS_HSK); conn->ifc_flags &= ~(IFC_ACK_QUED_INIT << PNS_HSK);
lsquic_alarmset_unset(&conn->ifc_alset, AL_ACK_HSK);
lsquic_send_ctl_empty_pns(&conn->ifc_send_ctl, PNS_HSK); lsquic_send_ctl_empty_pns(&conn->ifc_send_ctl, PNS_HSK);
lsquic_rechist_cleanup(&conn->ifc_rechist[PNS_HSK]); lsquic_rechist_cleanup(&conn->ifc_rechist[PNS_HSK]);
if (!(conn->ifc_flags & IFC_SERVER)) if (!(conn->ifc_flags & IFC_SERVER))
@ -5854,28 +5888,6 @@ ignore_hsk (struct ietf_full_conn *conn)
} }
/* Returns true if socket addresses are equal, false otherwise. Only
* families, IP addresses, and ports are compared.
*/
static int
sockaddr_eq (const struct sockaddr *a, const struct sockaddr *b)
{
if (a->sa_family == AF_INET)
return a->sa_family == b->sa_family
&& ((struct sockaddr_in *) a)->sin_addr.s_addr
== ((struct sockaddr_in *) b)->sin_addr.s_addr
&& ((struct sockaddr_in *) a)->sin_port
== ((struct sockaddr_in *) b)->sin_port;
else
return a->sa_family == b->sa_family
&& ((struct sockaddr_in6 *) a)->sin6_port ==
((struct sockaddr_in6 *) b)->sin6_port
&& 0 == memcmp(&((struct sockaddr_in6 *) a)->sin6_addr,
&((struct sockaddr_in6 *) b)->sin6_addr,
sizeof(((struct sockaddr_in6 *) b)->sin6_addr));
}
static void static void
record_dcid (struct ietf_full_conn *conn, record_dcid (struct ietf_full_conn *conn,
const struct lsquic_packet_in *packet_in) const struct lsquic_packet_in *packet_in)
@ -5929,12 +5941,12 @@ process_regular_packet (struct ietf_full_conn *conn,
NP_IS_IPv6(&conn->ifc_paths[packet_in->pi_path_id].cop_path)) NP_IS_IPv6(&conn->ifc_paths[packet_in->pi_path_id].cop_path))
{ {
case (1 << 1) | 1: /* IPv6 */ case (1 << 1) | 1: /* IPv6 */
if (sockaddr_eq(NP_PEER_SA(CUR_NPATH(conn)), NP_PEER_SA( if (lsquic_sockaddr_eq(NP_PEER_SA(CUR_NPATH(conn)), NP_PEER_SA(
&conn->ifc_paths[packet_in->pi_path_id].cop_path))) &conn->ifc_paths[packet_in->pi_path_id].cop_path)))
goto known_peer_addr; goto known_peer_addr;
break; break;
case (0 << 1) | 0: /* IPv4 */ case (0 << 1) | 0: /* IPv4 */
if (sockaddr_eq(NP_PEER_SA(CUR_NPATH(conn)), NP_PEER_SA( if (lsquic_sockaddr_eq(NP_PEER_SA(CUR_NPATH(conn)), NP_PEER_SA(
&conn->ifc_paths[packet_in->pi_path_id].cop_path))) &conn->ifc_paths[packet_in->pi_path_id].cop_path)))
goto known_peer_addr; goto known_peer_addr;
break; break;
@ -6710,7 +6722,7 @@ static int
path_matches_local_sa (const struct network_path *path, path_matches_local_sa (const struct network_path *path,
const struct sockaddr *local_sa) const struct sockaddr *local_sa)
{ {
return sockaddr_eq(NP_LOCAL_SA(path), local_sa); return lsquic_sockaddr_eq(NP_LOCAL_SA(path), local_sa);
} }
@ -6758,8 +6770,8 @@ path_matches (const struct network_path *path,
const struct sockaddr *local_sa, const struct sockaddr *peer_sa) const struct sockaddr *local_sa, const struct sockaddr *peer_sa)
{ {
return local_sa->sa_family == NP_LOCAL_SA(path)->sa_family return local_sa->sa_family == NP_LOCAL_SA(path)->sa_family
&& sockaddr_eq(local_sa, NP_LOCAL_SA(path)) && lsquic_sockaddr_eq(local_sa, NP_LOCAL_SA(path))
&& sockaddr_eq(peer_sa, NP_PEER_SA(path)); && lsquic_sockaddr_eq(peer_sa, NP_PEER_SA(path));
} }

View file

@ -1766,6 +1766,7 @@ ietf_mini_conn_ci_record_addrs (struct lsquic_conn *lconn, void *peer_ctx,
const struct sockaddr *local_sa, const struct sockaddr *peer_sa) const struct sockaddr *local_sa, const struct sockaddr *peer_sa)
{ {
struct ietf_mini_conn *conn = (struct ietf_mini_conn *) lconn; struct ietf_mini_conn *conn = (struct ietf_mini_conn *) lconn;
const struct sockaddr *orig_peer_sa;
struct lsquic_packet_out *packet_out; struct lsquic_packet_out *packet_out;
size_t len; size_t len;
@ -1774,6 +1775,12 @@ ietf_mini_conn_ci_record_addrs (struct lsquic_conn *lconn, void *peer_ctx,
if ((packet_out->po_flags & (PO_SENT|PO_ENCRYPTED)) == PO_ENCRYPTED) if ((packet_out->po_flags & (PO_SENT|PO_ENCRYPTED)) == PO_ENCRYPTED)
imico_return_enc_data(conn, packet_out); imico_return_enc_data(conn, packet_out);
orig_peer_sa = NP_PEER_SA(&conn->imc_path);
if (orig_peer_sa->sa_family != 0
&& !(lsquic_sockaddr_eq(NP_PEER_SA(&conn->imc_path), peer_sa)
&& lsquic_sockaddr_eq(NP_LOCAL_SA(&conn->imc_path), local_sa)))
conn->imc_flags |= IMC_PATH_CHANGED;
len = local_sa->sa_family == AF_INET ? sizeof(struct sockaddr_in) len = local_sa->sa_family == AF_INET ? sizeof(struct sockaddr_in)
: sizeof(struct sockaddr_in6); : sizeof(struct sockaddr_in6);

View file

@ -56,6 +56,7 @@ struct ietf_mini_conn
IMC_HSK_PACKET_SENT = 1 << 18, IMC_HSK_PACKET_SENT = 1 << 18,
IMC_CLOSE_RECVD = 1 << 19, IMC_CLOSE_RECVD = 1 << 19,
IMC_PARSE_FAILED = 1 << 20, IMC_PARSE_FAILED = 1 << 20,
IMC_PATH_CHANGED = 1 << 21,
} imc_flags; } imc_flags;
struct mini_crypto_stream imc_streams[N_ENC_LEVS]; struct mini_crypto_stream imc_streams[N_ENC_LEVS];
void *imc_stream_ps[N_ENC_LEVS]; void *imc_stream_ps[N_ENC_LEVS];

View file

@ -1498,6 +1498,7 @@ lsquic_send_ctl_expire_all (lsquic_send_ctl_t *ctl)
} }
#ifndef NDEBUG
void void
lsquic_send_ctl_do_sanity_check (const struct lsquic_send_ctl *ctl) lsquic_send_ctl_do_sanity_check (const struct lsquic_send_ctl *ctl)
{ {
@ -1540,6 +1541,7 @@ lsquic_send_ctl_do_sanity_check (const struct lsquic_send_ctl *ctl)
assert(count == ctl->sc_n_scheduled); assert(count == ctl->sc_n_scheduled);
assert(bytes == ctl->sc_bytes_scheduled); assert(bytes == ctl->sc_bytes_scheduled);
} }
#endif
void void

View file

@ -180,10 +180,14 @@ lsquic_send_ctl_expire_all (lsquic_send_ctl_t *ctl);
void void
lsquic_send_ctl_do_sanity_check (const struct lsquic_send_ctl *ctl); lsquic_send_ctl_do_sanity_check (const struct lsquic_send_ctl *ctl);
#ifndef NDEBUG
#define lsquic_send_ctl_sanity_check(ctl) do { \ #define lsquic_send_ctl_sanity_check(ctl) do { \
if ((ctl)->sc_flags & SC_SANITY_CHECK) \ if ((ctl)->sc_flags & SC_SANITY_CHECK) \
lsquic_send_ctl_do_sanity_check(ctl); \ lsquic_send_ctl_do_sanity_check(ctl); \
} while (0) } while (0)
#else
#define lsquic_send_ctl_sanity_check(ctl)
#endif
int int
lsquic_send_ctl_have_outgoing_stream_frames (const lsquic_send_ctl_t *); lsquic_send_ctl_have_outgoing_stream_frames (const lsquic_send_ctl_t *);

View file

@ -128,7 +128,7 @@ lsquic_tp_encode (const struct transport_params *params,
else else
{ {
LSQ_DEBUG("numeric value is too large (%"PRIu64" vs maximum " LSQ_DEBUG("numeric value is too large (%"PRIu64" vs maximum "
"of %"PRIu64, params->tp_numerics_u.a[tpi2idx[tpi]], "of %"PRIu64")", params->tp_numerics_u.a[tpi2idx[tpi]],
max_vals[tpi]); max_vals[tpi]);
return -1; return -1;
} }

View file

@ -14,6 +14,7 @@
#else #else
#include <vc_compat.h> #include <vc_compat.h>
#endif #endif
#include <netinet/in.h>
#if !(defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0) && defined(__APPLE__) #if !(defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0) && defined(__APPLE__)
#include <mach/mach_time.h> #include <mach/mach_time.h>
@ -254,3 +255,25 @@ lsquic_hexdump (const void *src_void, size_t src_sz, char *out, size_t out_sz)
return out + out_sz - out_end; return out + out_sz - out_end;
} }
/* Returns true if socket addresses are equal, false otherwise. Only
* families, IP addresses, and ports are compared.
*/
int
lsquic_sockaddr_eq (const struct sockaddr *a, const struct sockaddr *b)
{
if (a->sa_family == AF_INET)
return a->sa_family == b->sa_family
&& ((struct sockaddr_in *) a)->sin_addr.s_addr
== ((struct sockaddr_in *) b)->sin_addr.s_addr
&& ((struct sockaddr_in *) a)->sin_port
== ((struct sockaddr_in *) b)->sin_port;
else
return a->sa_family == b->sa_family
&& ((struct sockaddr_in6 *) a)->sin6_port ==
((struct sockaddr_in6 *) b)->sin6_port
&& 0 == memcmp(&((struct sockaddr_in6 *) a)->sin6_addr,
&((struct sockaddr_in6 *) b)->sin6_addr,
sizeof(((struct sockaddr_in6 *) b)->sin6_addr));
}

View file

@ -10,6 +10,8 @@
extern "C" { extern "C" {
#endif #endif
struct sockaddr;
lsquic_time_t lsquic_time_t
lsquic_time_now (void); lsquic_time_now (void);
@ -38,6 +40,9 @@ lsquic_hexstr (const unsigned char *buf, size_t bufsz, char *out, size_t outsz);
#define HEXSTR(buf, bufsz, out) \ #define HEXSTR(buf, bufsz, out) \
(lsquic_hexstr(buf, bufsz, out, sizeof(out)), out) (lsquic_hexstr(buf, bufsz, out, sizeof(out)), out)
int
lsquic_sockaddr_eq (const struct sockaddr *a, const struct sockaddr *b);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -659,6 +659,13 @@ http_client_on_write (lsquic_stream_t *stream, lsquic_stream_ctx_t *st_h)
} }
static size_t
discard (void *ctx, const unsigned char *buf, size_t sz, int fin)
{
return sz;
}
static void static void
http_client_on_read (lsquic_stream_t *stream, lsquic_stream_ctx_t *st_h) http_client_on_read (lsquic_stream_t *stream, lsquic_stream_ctx_t *st_h)
{ {
@ -691,7 +698,10 @@ http_client_on_read (lsquic_stream_t *stream, lsquic_stream_ctx_t *st_h)
hset_destroy(hset); hset_destroy(hset);
st_h->sh_flags |= PROCESSED_HEADERS; st_h->sh_flags |= PROCESSED_HEADERS;
} }
else if (nread = lsquic_stream_read(stream, buf, sizeof(buf)), nread > 0) else if (nread = (s_discard_response
? lsquic_stream_readf(stream, discard, NULL)
: lsquic_stream_read(stream, buf, sizeof(buf))),
nread > 0)
{ {
s_stat_downloaded_bytes += nread; s_stat_downloaded_bytes += nread;
/* test stream_reset after some number of read bytes */ /* test stream_reset after some number of read bytes */