Instead of following the usual actor pattern, we use a 1-place channel
with a non-blocking send. Essentially, if there is already a pending
recalculation request queued up, there is no point enqueuing another
one.
we simply reset the vars controlling backoff for that address
Note that we do not interrupt any current connection attempt, since
that is hard.
Closes#499.
d5eb76f32 replaced (*Peer)ForEachConnection into (*Peer)Connections(),
and consequently converted some nested functions into for loops. But
the "return" statements in those nested functions were left as-was,
and so exited the outer function rather than moving on to the next
iteration.
Fixes#497
The previous scheme set the reference to main channel to nil and then
drained it. That was racy and hence could lead to deadlock in the
following scenario:
1. multiple senders obtain the main channel from the stored reference
2. main channel reference is set to nil
3. main channel is drained
4. multiple senders send to main channel
So the issue here is that the entire forwarder stopping sequence
occurs between senders obtaining of the reference to the main channel,
and then sending on that channel. If more senders sent than there is
capacity in the channel then this leads to deadlock.
The crypto layer doesn't need it, and the cost of an additional
closure allocation for each incoming UDP packet is modest.
Also, make the FrameConsumer the last parameter to IterateFrames.
It seems a more natural ordering.
Treat the no-error case the same as the error case...
- use the standard sendAction to communicate with the actor, which
ensures that we don't block when the actor has terminated
- run in a goroutine to prevent delaying the caller when the actor's
channel is backed up.
The only slight trickiness is Shutdown. Generally connections shut
down when an error is encountered, but we also need to be able to shut
down connections w/o an error. Rather than making all the actor
methods return a (terminated bool, error) tuple, we signal the
non-error shutdown by sending nil as the action (instead of a
closure).