Overly aggressive sending of ACKNACKs eats bandwidth and causes
unnecessary retransmits and lowers performance; but overly timid sending
of them also reduces performance. This commit reduces the
aggressiveness.
* It keeps more careful track of what ACKNACK (or NACKFRAG) was last
sent and when, suppressing ACKs that don't provide new information for
a few milliseconds and suppressing NACKs for the NackDelay
setting. (The setting was there all long, but it didn't honor it when
the writer asked for a response.)
* It ignores the NackDelay when all that was requested has arrived, or
when it receives a directed heartbeat from a Cyclone peer. The latter
is taken as an indication that no more is following, and allows the
recipient to ask far arbitrary amounts of data and rely on the sender
to limit the retransmit to what seems reasonable. (For NACKFRAG one
can do it in the recipient, but for ACKNACK one cannot, and so one
might as well do it at the sender always.)
* Sufficient state is maintained in the match object for the ACKNACK
generator to decide whether or not to send an ACKNACK following the
rules, and it may decide to send just an ACK even though there is data
missing, or nothing at all.
* If HEARTBEAT processing requires an immediate response, the response
message is generated by the receive thread, but still queued for
transmission. If a delayed response is required, it schedules the
ACKNACK event.
Signed-off-by: Erik Boasson <eb@ilities.com>