There were situations, such as deleting another connection as result
of it losing a tie-break, where lifecycle events of connections on the
local peer weren't logged.
Fixing that entails moving the logging closer to (i.e. right after)
the state change action. This in turn requires promotion of logging to
the Connection interface instead of it LocalConnection. Which in turn
requires a change from 'log' to 'Log', for consistency with other
interface methods.
Fixes#449.
If forwarding of a broadcast frame resulted in a FrameTooBigError, we
would generate an ICMP "fragmentation needed" packet that contravened
RFC1122 on two counts: First, we should not produce a ICMP error
message in response to a broadcast/multicast packet. Secondly, we
should not produce an IP packet with a broadcast/multicast source IP
address. (It also gave an ethernet frame with a broadcast source MAC,
which probably contravenes some IEEE spec.)
So when RelayBroadcast gets a FrameTooBigError, it should just drop
the packet.
Futhermore, if we fail to relay a broadcast on one connection, that's
not a good reason to give up entirely - we can proceed to attempt to
relay on the other next hop connections. Errors other than
FrameTooBigError that propagated upwards were simply logged, so that
logging is moved down into RelayBroadcast.
Topology gossip can be received on a connection before that connection
has been marked as 'established'. If we do not include unestablished
connections in topology gossip, then parts of the topology can be
removed by gc, since they are deemed unreachable, which can cause
subsequent incremental topology gossips to be rejected due to them
containing references to peers that have been removed by the gc.
Including unestablished connections in topology gossip requires:
- removing the check for 'established' connections in the encoding of
peers for topology gossip,
- adding the 'established' flag to the internal representation of
remote connections,
- adding the 'established' flag to to encoding of connections in
topology gossip,
- treating the *addition* of a connection as an update to the local
peer.
The latter entails
- bumping the peer version on connection addition (as well as on
marking 'established' as previously),
- bumping the peer version *unconditionally* on connection deletion
(rather than only when the connection was 'established', as
previously),
- moving the initial sending of complete topology on the connection,
and the broadcasting of a topology update containing the two peers
at the ends of the connection, from the connection 'established'
logic to the connection addition logic,
- broadcasting just an topology update for the local peer when a
connection gets marked as 'established',
- broadcasting a topology update for the local peer *unconditionally*
when a connection is removed (rather than only doing this when the
connection was 'established', as previously).
Caused by a race between adding the connection to our map and
receiving a topology gossip on it.
We remove the race by making AddConnection synchronous and invoking it
prior to entering the tcp receive loop.
Fixes#367.
1) log more lifecycle events
- acceptance
- handshake completion
- added & removed (from our connection map)
The latter is a bit verbose but may help us track down the cause for
going to introduce here, then this would fall in the 'debug' category.
2) better error logging
- log error as part of "shutting down" log event rather than separately
- indicate "blocked UDP connectivity" as a possible cause when
getting a timeout on a not-fully-established connection.
The rationale for the latter is that inbound connections get
marked as established when first receiving a heartbeat frame over
UDP, which are the only frames that get transmitted prior to the
connection being fully established. Note that outbound
connections get marked as established when receiving the
ConnectionEstablished message over TCP, which is sent by the peer
when it first receives a heartbeat. See #342.
Closes#340.