tear down connections that have no (initial) udp connectivity
Prior to the introduction of gossip, a tcp connection would not see regular communication until it had been marked as 'established', because the topology communication scheme would periodically send 'FetchAll' only after that. So in the absence of udp connectivity we'd time out. The timeout could of course occur for other reasons, namely disrupted tcp connectivity, but the combination of a timeout and 'not established' pointed to a lack of udp connectivity as a likely cause. So that's what we checked for. In the new gossip-based topology communication, however, gossip (of anything, not just topology) occurs as soon as we have tcp connectivity. Therefore we will no longer encounter a timeout when just udp connectivity is disrupted. Which makes our check invalid. So instead we introduce a one-shot timer, created on handshake completion and cancelled when we mark the connection as 'established'. When the timer fires, and the connection still hasn't been established, we shut down the connection with an error indicating lack of udp connectivity.
This commit is contained in:
1 parent
17f6653cae
commit
c1dd2e3a09
2 files changed
+34
-24
No files matched your search
+33
-24
@@ -38,26 +38,27 @@ type RemoteConnection struct {
|
||||
type LocalConnection struct {
|
||||
sync.RWMutex
|
||||
RemoteConnection
|
||||
TCPConn *net.TCPConn
|
||||
tcpSender TCPSender
|
||||
remoteUDPAddr *net.UDPAddr
|
||||
established bool
|
||||
receivedHeartbeat bool
|
||||
stackFrag bool
|
||||
effectivePMTU int
|
||||
SessionKey *[32]byte
|
||||
heartbeatFrame *ForwardedFrame
|
||||
heartbeat *time.Ticker
|
||||
fragTest *time.Ticker
|
||||
forwardChan chan<- *ForwardedFrame
|
||||
forwardChanDF chan<- *ForwardedFrame
|
||||
stopForward chan<- interface{}
|
||||
stopForwardDF chan<- interface{}
|
||||
verifyPMTU chan<- int
|
||||
Decryptor Decryptor
|
||||
Router *Router
|
||||
uid uint64
|
||||
queryChan chan<- *ConnectionInteraction
|
||||
TCPConn *net.TCPConn
|
||||
tcpSender TCPSender
|
||||
remoteUDPAddr *net.UDPAddr
|
||||
established bool
|
||||
receivedHeartbeat bool
|
||||
stackFrag bool
|
||||
effectivePMTU int
|
||||
SessionKey *[32]byte
|
||||
establishedTimeout *time.Timer
|
||||
heartbeatFrame *ForwardedFrame
|
||||
heartbeat *time.Ticker
|
||||
fragTest *time.Ticker
|
||||
forwardChan chan<- *ForwardedFrame
|
||||
forwardChanDF chan<- *ForwardedFrame
|
||||
stopForward chan<- interface{}
|
||||
stopForwardDF chan<- interface{}
|
||||
verifyPMTU chan<- int
|
||||
Decryptor Decryptor
|
||||
Router *Router
|
||||
uid uint64
|
||||
queryChan chan<- *ConnectionInteraction
|
||||
}
|
||||
|
||||
type ConnectionInteraction struct {
|
||||
@@ -253,10 +254,9 @@ func (conn *LocalConnection) run(queryChan <-chan *ConnectionInteraction, accept
|
||||
}
|
||||
}
|
||||
|
||||
err := conn.queryLoop(queryChan)
|
||||
if netErr, ok := err.(net.Error); ok && netErr.Timeout() && !conn.established {
|
||||
conn.log("connection shutting down due to timeout; possibly caused by blocked UDP connectivity")
|
||||
} else if err != nil {
|
||||
conn.establishedTimeout = time.NewTimer(EstablishedTimeout)
|
||||
|
||||
if err := conn.queryLoop(queryChan); err != nil {
|
||||
conn.log("connection shutting down due to error:", err)
|
||||
} else {
|
||||
conn.log("connection shutting down")
|
||||
@@ -278,10 +278,15 @@ func (conn *LocalConnection) queryLoop(queryChan <-chan *ConnectionInteraction)
|
||||
case CReceivedHeartbeat:
|
||||
err = conn.handleReceivedHeartbeat(query.payload.(*net.UDPAddr))
|
||||
case CSetEstablished:
|
||||
conn.establishedTimeout.Stop()
|
||||
err = conn.handleSetEstablished()
|
||||
case CSendProtocolMsg:
|
||||
err = conn.handleSendProtocolMsg(query.payload.(ProtocolMsg))
|
||||
}
|
||||
case <-conn.establishedTimeout.C:
|
||||
if !conn.established {
|
||||
err = fmt.Errorf("failed to establish UDP connectivity")
|
||||
}
|
||||
case <-tickerChan(conn.heartbeat):
|
||||
conn.Forward(true, conn.heartbeatFrame, nil)
|
||||
case <-tickerChan(conn.fragTest):
|
||||
@@ -368,6 +373,10 @@ func (conn *LocalConnection) handleShutdown() {
|
||||
conn.Router.Ourself.DeleteConnection(conn)
|
||||
}
|
||||
|
||||
if conn.establishedTimeout != nil {
|
||||
conn.establishedTimeout.Stop()
|
||||
}
|
||||
|
||||
stopTicker(conn.heartbeat)
|
||||
stopTicker(conn.fragTest)
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ const (
|
||||
FastHeartbeat = 500 * time.Millisecond
|
||||
SlowHeartbeat = 10 * time.Second
|
||||
FragTestInterval = 5 * time.Minute
|
||||
EstablishedTimeout = 30 * time.Second
|
||||
ReadTimeout = 1 * time.Minute
|
||||
PMTUVerifyAttempts = 8
|
||||
PMTUVerifyTimeout = 10 * time.Millisecond // gets doubled with every attempt
|
||||
|
||||
Reference in new issue
Block a user