Merge pull request #413 from awh/373_detect_udp_connectivity_breakage

Tear down connections on prolonged loss of UDP heartbeat.

Closes #373.
This commit is contained in:
rade committed 2015-02-25 18:09:05 +00:00
commit 47ef9ff85e
2 files changed
+46 -47

No files matched your search

+27 -29
View File
@@ -37,27 +37,27 @@ type RemoteConnection struct {
type LocalConnection struct {
sync.RWMutex
RemoteConnection
TCPConn *net.TCPConn
tcpSender TCPSender
remoteUDPAddr *net.UDPAddr
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
finished <-chan struct{} // closed to signal that queryLoop has finished
TCPConn *net.TCPConn
tcpSender TCPSender
remoteUDPAddr *net.UDPAddr
receivedHeartbeat bool
stackFrag bool
effectivePMTU int
SessionKey *[32]byte
heartbeatTimeout *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
finished <-chan struct{} // closed to signal that queryLoop has finished
}
type ConnectionInteraction struct {
@@ -270,7 +270,7 @@ func (conn *LocalConnection) run(queryChan <-chan *ConnectionInteraction, finish
}
}
conn.establishedTimeout = time.NewTimer(EstablishedTimeout)
conn.heartbeatTimeout = time.NewTimer(HeartbeatTimeout)
if err := conn.queryLoop(queryChan); err != nil {
conn.log("connection shutting down due to error:", err)
@@ -305,15 +305,12 @@ 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 <-conn.heartbeatTimeout.C:
err = fmt.Errorf("timed out waiting for UDP heartbeat")
case <-tickerChan(conn.heartbeat):
conn.Forward(true, conn.heartbeatFrame, nil)
case <-tickerChan(conn.fragTest):
@@ -338,6 +335,7 @@ func (conn *LocalConnection) handleReceivedHeartbeat(remoteUDPAddr *net.UDPAddr)
conn.remoteUDPAddr = remoteUDPAddr
conn.receivedHeartbeat = true
conn.Unlock()
conn.heartbeatTimeout.Reset(HeartbeatTimeout)
if !old {
if err := conn.handleSendSimpleProtocolMsg(ProtocolConnectionEstablished); err != nil {
return err
@@ -400,8 +398,8 @@ func (conn *LocalConnection) handleShutdown() {
conn.Router.Ourself.DeleteConnection(conn)
}
if conn.establishedTimeout != nil {
conn.establishedTimeout.Stop()
if conn.heartbeatTimeout != nil {
conn.heartbeatTimeout.Stop()
}
stopTicker(conn.heartbeat)
+19 -18
View File
@@ -6,24 +6,25 @@ import (
)
const (
EthernetOverhead = 14
UDPOverhead = 28 // 20 bytes for IPv4, 8 bytes for UDP
Port = 6783
HttpPort = Port + 1
DefaultPMTU = 65535
MaxUDPPacketSize = 65536
ChannelSize = 16
UDPNonceSendAt = 8192
FragTestSize = 60001
PMTUDiscoverySize = 60000
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
MaxDuration = time.Duration(math.MaxInt64)
EthernetOverhead = 14
UDPOverhead = 28 // 20 bytes for IPv4, 8 bytes for UDP
Port = 6783
HttpPort = Port + 1
DefaultPMTU = 65535
MaxUDPPacketSize = 65536
ChannelSize = 16
UDPNonceSendAt = 8192
FragTestSize = 60001
PMTUDiscoverySize = 60000
FastHeartbeat = 500 * time.Millisecond
SlowHeartbeat = 10 * time.Second
FragTestInterval = 5 * time.Minute
ReadTimeout = 1 * time.Minute
PMTUVerifyAttempts = 8
PMTUVerifyTimeout = 10 * time.Millisecond // gets doubled with every attempt
MaxDuration = time.Duration(math.MaxInt64)
MaxMissedHeartbeats = 3
HeartbeatTimeout = MaxMissedHeartbeats * SlowHeartbeat
)
var (