wgengine/magicsock: close stale DERP connections

This commit is contained in:
Brad Fitzpatrick 2020-03-05 12:47:54 -08:00
parent cf4aacde57
commit 12b77f30ad

View File

@ -91,9 +91,10 @@ type Conn struct {
// activeDerp contains fields for an active DERP connection. // activeDerp contains fields for an active DERP connection.
type activeDerp struct { type activeDerp struct {
c *derphttp.Client c *derphttp.Client
cancel context.CancelFunc cancel context.CancelFunc
writeCh chan<- derpWriteRequest writeCh chan<- derpWriteRequest
lastWrite *time.Time
} }
// udpAddr is the key in the addrsByUDP map. // udpAddr is the key in the addrsByUDP map.
@ -227,6 +228,7 @@ func (c *Conn) epUpdate(ctx context.Context) {
defer close(lastDone) defer close(lastDone)
c.updateNetInfo() // best effort c.updateNetInfo() // best effort
c.cleanStaleDerp()
endpoints, err := c.determineEndpoints(epCtx) endpoints, err := c.determineEndpoints(epCtx)
if err != nil { if err != nil {
@ -643,17 +645,18 @@ func (c *Conn) derpWriteChanOfAddr(addr *net.UDPAddr) chan<- derpWriteRequest {
dc.TLSConfig = c.derpTLSConfig dc.TLSConfig = c.derpTLSConfig
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
// TODO: close derp channels (if addr.Port != myDerp) on inactivity timer
ch := make(chan derpWriteRequest, bufferedDerpWritesBeforeDrop) ch := make(chan derpWriteRequest, bufferedDerpWritesBeforeDrop)
ad.c = dc ad.c = dc
ad.writeCh = ch ad.writeCh = ch
ad.cancel = cancel ad.cancel = cancel
ad.lastWrite = new(time.Time)
c.activeDerp[addr.Port] = ad c.activeDerp[addr.Port] = ad
go c.runDerpReader(ctx, addr, dc) go c.runDerpReader(ctx, addr, dc)
go c.runDerpWriter(ctx, addr, dc, ch) go c.runDerpWriter(ctx, addr, dc, ch)
} }
*ad.lastWrite = time.Now()
return ad.writeCh return ad.writeCh
} }
@ -926,6 +929,22 @@ func (c *Conn) closeDerpLocked(node int) {
} }
} }
func (c *Conn) cleanStaleDerp() {
c.derpMu.Lock()
defer c.derpMu.Unlock()
const inactivityTime = 60 * time.Second
tooOld := time.Now().Add(-inactivityTime)
for i, ad := range c.activeDerp {
if i == c.myDerp {
continue
}
if ad.lastWrite.Before(tooOld) {
c.logf("closing stale DERP connection to derp%v", i)
c.closeDerpLocked(i)
}
}
}
func (c *Conn) SetMark(value uint32) error { return nil } func (c *Conn) SetMark(value uint32) error { return nil }
func (c *Conn) LastMark() uint32 { return 0 } func (c *Conn) LastMark() uint32 { return 0 }