- Remove comment: MSPC is obsolete (no code changes)
- Prog: use lsquic_str2ver() when processing -o version flag
- Remove unused CTIM and SRBF transport parameters
- Disable QUIC versions Q037 and Q038 by default
- Fix Windows compilation by including compat header file in lshpack.c
- Address warnings produced by newer versions of gcc
- Future-proof: turn off -Werror
- Do not create gap in sent packnos when squeezing delayed
packets.
- sendctl checks for all unacked bytes, not just retx bytes.
- connections with blocked scheduled packets are not tickable
for sending.
- Fix busy loop: tickable must make progress. When connection is
self-reporting as tickable, it must make progress when ticked. There
are two issues:
1. If there are buffered packets, the connection is only tickable if
they can be sent out.
2. A connection is tickable if there are streams on the servicing
queue. When the tick occurs, we must service the stream
independent of whether any packets are sent.
- Fix assertion in pacer which can be incorrect under some
conditions.
- cmake: do not turn on address sanitizer if in Travis.
- [BUGFIX] Add connection to Tickable Queue on stream write
- cmake: use MSVC variable instead of trying to detect
- engine: improve connection incref/decref logging
- stream: don't ignore errors that may occur on triggered flush
- connection: remove obsolete method
- engine: indicate connection as tickable if previous call went
over threshold
The API is simplified: do not expose the user code to several
queues. A "connection queue" is now an internal concept.
The user processes connections using the single function
lsquic_engine_process_conns(). When this function is called,
only those connections are processed that need to be processed.
A connection needs to be processed when:
1. New incoming packets have been fed to the connection.
2. User wants to read from a stream that is readable.
3. User wants to write to a stream that is writeable.
4. There are buffered packets that can be sent out. (This
means that the user wrote to a stream outside of the
lsquic library callback.)
5. A control frame (such as BLOCKED) needs to be sent out.
6. A stream needs to be serviced or delayed stream needs to
be created.
7. An alarm rings.
8. Pacer timer expires.
To achieve this, the library places the connections into two
priority queues (min heaps):
1. Tickable Queue; and
2. Advisory Tick Time queue (ATTQ).
Each time lsquic_engine_process_conns() is called, the Tickable
Queue is emptied. After the connections have been ticked, they are
queried again: if a connection is not being closed, it is placed
either in the Tickable Queue if it is ready to be ticked again or
it is placed in the Advisory Tick Time Queue. It is assumed that
a connection always has at least one timer set (the idle alarm).
The connections in the Tickable Queue are arranged in the least
recently ticked order. This lets connections that have been quiet
longer to get their packets scheduled first.
This change means that the library no longer needs to be ticked
periodically. The user code can query the library when is the
next tick event and schedule it exactly. When connections are
processed, only the tickable connections are processed, not *all*
the connections. When there are no tick events, it means that no
timer event is necessary -- only the file descriptor READ event
is active.
The following are improvements and simplifications that have
been triggered:
- Queue of connections with incoming packets is gone.
- "Pending Read/Write Events" Queue is gone (along with its
history and progress checks). This queue has become the
Tickable Queue.
- The connection hash no longer needs to track the connection
insertion order.
- [OPTIMIZATION] Merge series of ACKs if possible
Parsed single-range ACK frames (that is the majority of frames) are
saved in the connection and their processing is deferred until the
connection is ticked. If several ACKs come in a series between
adjacent ticks, we check whether the latest ACK is a strict superset
of the saved ACK. If it is, the older ACK is not processed.
If ACK frames can be merged, they are merged and only one of them is
either processed or saved.
- [OPTIMIZATION] Speed up ACK verification by simplifying send history.
Never generate a gap in the sent packet number sequence. This reduces
the send history to a single number instead of potentially a series of
packet ranges and thereby speeds up ACK verification.
By default, detecting a gap in the send history is not fatal: only a
single warning is generated per connection. The connection can continue
to operate even if the ACK verification code is not able to detect some
inconsistencies.
- [OPTIMIZATION] Rearrange the lsquic_send_ctl struct
The first part of struct lsquic_send_ctl now consists of members that
are used in lsquic_send_ctl_got_ack() (in the absense of packet loss,
which is the normal case). To speed up reads and writes, we no longer
try to save space by using 8- and 16-bit integers. Use regular integer
width for everything.
- [OPTIMIZATION] Cache size of sent packet.
- [OPTIMIZATION] Keep track of the largest ACKed in packet_out
Instead of parsing our own ACK frames when packet has been acked,
use the value saved in the packet_out structure when the ACK frame
was generated.
- [OPTIMIZATION] Take RTT sampling conditional out of ACK loop
- [OPTIMIZATION] ACK processing: only call clock_gettime() if needed
- [OPTIMIZATION] Several code-level optimizations to ACK processing.
- Fix: http_client: fix -I flag; switch assert() to abort()