Merge pull request #67 from Arceliar/sessionping

Try using session pings before searches for active sessions
This commit is contained in:
Neil Alexander 2018-04-22 22:04:03 +01:00 committed by GitHub
commit 275345f3c6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 33 additions and 9 deletions

View File

@ -141,12 +141,27 @@ func (r *router) sendPacket(bs []byte) {
// No or unintiialized session, so we need to search first // No or unintiialized session, so we need to search first
doSearch(bs) doSearch(bs)
case time.Since(sinfo.time) > 6*time.Second: case time.Since(sinfo.time) > 6*time.Second:
// We haven't heard from the dest in a while; they may have changed coords if sinfo.time.Before(sinfo.pingTime) && time.Since(sinfo.pingTime) > 6*time.Second {
// Maybe the connection is idle, or maybe one of us changed coords // We haven't heard from the dest in a while
// Try searching to either ping them (a little overhead) or fix the coords // We tried pinging but didn't get a response
doSearch(nil) // They may have changed coords
fallthrough // Try searching to discover new coords
//default: go func() { sinfo.send<-bs }() // Note that search spam is throttled internally
doSearch(nil)
} else {
// We haven't heard about the dest in a while
now := time.Now()
if !sinfo.time.Before(sinfo.pingTime) {
// Update pingTime to start the clock for searches (above)
sinfo.pingTime = now
}
if time.Since(sinfo.pingSend) > time.Second {
// Send at most 1 ping per second
sinfo.pingSend = now
r.core.sessions.sendPingPong(sinfo, false)
}
}
fallthrough // Also send the packet
default: default:
// Generate an ICMPv6 Packet Too Big for packets larger than session MTU // Generate an ICMPv6 Packet Too Big for packets larger than session MTU
if len(bs) > int(sinfo.getMTU()) { if len(bs) > int(sinfo.getMTU()) {

View File

@ -30,6 +30,8 @@ type sessionInfo struct {
nonceMask uint64 nonceMask uint64
tstamp int64 // tstamp from their last session ping, replay attack mitigation tstamp int64 // tstamp from their last session ping, replay attack mitigation
mtuTime time.Time // time myMTU was last changed mtuTime time.Time // time myMTU was last changed
pingTime time.Time // time the first ping was sent since the last received packet
pingSend time.Time // time the last ping was sent
} }
type sessionPing struct { type sessionPing struct {
@ -64,7 +66,8 @@ func (s *sessionInfo) update(p *sessionPing) bool {
s.theirMTU = p.mtu s.theirMTU = p.mtu
} }
s.coords = append([]byte{}, p.coords...) s.coords = append([]byte{}, p.coords...)
s.time = time.Now() now := time.Now()
s.time = now
s.tstamp = p.tstamp s.tstamp = p.tstamp
s.init = true s.init = true
return true return true
@ -153,7 +156,11 @@ func (ss *sessions) createSession(theirPermKey *boxPubKey) *sessionInfo {
sinfo.myNonce = *newBoxNonce() sinfo.myNonce = *newBoxNonce()
sinfo.theirMTU = 1280 sinfo.theirMTU = 1280
sinfo.myMTU = uint16(ss.core.tun.mtu) sinfo.myMTU = uint16(ss.core.tun.mtu)
sinfo.mtuTime = time.Now() now := time.Now()
sinfo.time = now
sinfo.mtuTime = now
sinfo.pingTime = now
sinfo.pingSend = now
higher := false higher := false
for idx := range ss.core.boxPub { for idx := range ss.core.boxPub {
if ss.core.boxPub[idx] > sinfo.theirPermPub[idx] { if ss.core.boxPub[idx] > sinfo.theirPermPub[idx] {
@ -176,7 +183,6 @@ func (ss *sessions) createSession(theirPermKey *boxPubKey) *sessionInfo {
sinfo.send = make(chan []byte, 32) sinfo.send = make(chan []byte, 32)
sinfo.recv = make(chan *wire_trafficPacket, 32) sinfo.recv = make(chan *wire_trafficPacket, 32)
go sinfo.doWorker() go sinfo.doWorker()
sinfo.time = time.Now()
// Do some cleanup // Do some cleanup
// Time thresholds almost certainly could use some adjusting // Time thresholds almost certainly could use some adjusting
for _, s := range ss.sinfos { for _, s := range ss.sinfos {
@ -255,6 +261,9 @@ func (ss *sessions) sendPingPong(sinfo *sessionInfo, isPong bool) {
} }
packet := p.encode() packet := p.encode()
ss.core.router.out(packet) ss.core.router.out(packet)
if !isPong {
sinfo.pingSend = time.Now()
}
} }
func (ss *sessions) handlePing(ping *sessionPing) { func (ss *sessions) handlePing(ping *sessionPing) {