The current system time must only be sampled once to establish the
unit test epoch. Because test time doesn't advance unless told to,
this was causing connections to sometimes receive packets from before
they were created, causing odd warnings and potentially other
unintended behavior.
Closes#1820
The fix:
- Endpoint now maintains a slab with an entry for each pending Incoming
to buffer received data.
- ConnectionIndex now maps initial DCID to that slab key immediately
upon construction of Incoming.
- If Incoming is accepted, association is overridden with association
with ConnectionHandle, and all buffered datagrams are fed to newly
constructed Connection.
- If Incoming is refused/retried/ignored, or accepting errors,
association and slab entry are cleaned up to prevent memory leak.
Additional considerations:
- The Incoming::ignore operation can no longer be implemented as just
dropping it. To help prevent incorrect API usage, proto::Incoming is
modified to log a warning if it is dropped without being passed to
Endpoint::accept/refuse/retry/ignore.
- Three things protect against memory exhaustion attacks here:
1. The MAX_INCOMING_CONNECTIONS limit is moved from quinn to proto,
limiting the number of concurrent incoming connections for which
datagrams will be buffered before the application decides what to
do with them. Also, it is changed from a constant to a field of the
server config, max_incoming.
2. Per-incoming buffered data is limited to a new limit stored in the
server config, incoming_buffer_size, beyond which subsequent
packets are discarded if received in these conditions.
3. The sum total of all incoming buffered data is limited to a new
limit stored in the server config, incoming_buffer_size_total,
beyond which subsequent packets are discarded if received in these
conditions.
As we no longer buffer multiple transmits in memory, this complexity
is unused. GSO is expected to account for most, if not all, of the
performance benefit.
`UdpState` was removed some time ago, and various other interface
details have changed. As a result, the build would fail on platforms
without native support.