mirror of
https://github.com/yggdrasil-network/yggdrasil-go.git
synced 2024-11-27 20:15:23 +00:00
have the tunConn close things after a 2 minute timeout
This commit is contained in:
parent
5ea864869a
commit
b2513fce56
@ -2,6 +2,7 @@ package tuntap
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/yggdrasil-network/yggdrasil-go/src/address"
|
"github.com/yggdrasil-network/yggdrasil-go/src/address"
|
||||||
"github.com/yggdrasil-network/yggdrasil-go/src/util"
|
"github.com/yggdrasil-network/yggdrasil-go/src/util"
|
||||||
@ -14,19 +15,28 @@ type tunConn struct {
|
|||||||
addr address.Address
|
addr address.Address
|
||||||
snet address.Subnet
|
snet address.Subnet
|
||||||
send chan []byte
|
send chan []byte
|
||||||
stop chan interface{}
|
stop chan struct{}
|
||||||
|
alive chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *tunConn) close() {
|
func (s *tunConn) close() {
|
||||||
s.tun.mutex.Lock()
|
s.tun.mutex.Lock()
|
||||||
|
defer s.tun.mutex.Unlock()
|
||||||
s._close_nomutex()
|
s._close_nomutex()
|
||||||
s.tun.mutex.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *tunConn) _close_nomutex() {
|
func (s *tunConn) _close_nomutex() {
|
||||||
|
s.conn.Close()
|
||||||
delete(s.tun.addrToConn, s.addr)
|
delete(s.tun.addrToConn, s.addr)
|
||||||
delete(s.tun.subnetToConn, s.snet)
|
delete(s.tun.subnetToConn, s.snet)
|
||||||
close(s.stop)
|
func() {
|
||||||
|
defer func() { recover() }()
|
||||||
|
close(s.stop) // Closes reader/writer goroutines
|
||||||
|
}()
|
||||||
|
func() {
|
||||||
|
defer func() { recover() }()
|
||||||
|
close(s.alive) // Closes timeout goroutine
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *tunConn) reader() error {
|
func (s *tunConn) reader() error {
|
||||||
@ -43,7 +53,7 @@ func (s *tunConn) reader() error {
|
|||||||
b := make([]byte, 65535)
|
b := make([]byte, 65535)
|
||||||
for {
|
for {
|
||||||
go func() {
|
go func() {
|
||||||
// TODO read timeout and close
|
// TODO don't start a new goroutine for every packet read, this is probably a big part of the slowdowns we saw when refactoring
|
||||||
if n, err = s.conn.Read(b); err != nil {
|
if n, err = s.conn.Read(b); err != nil {
|
||||||
s.tun.log.Errorln(s.conn.String(), "TUN/TAP conn read error:", err)
|
s.tun.log.Errorln(s.conn.String(), "TUN/TAP conn read error:", err)
|
||||||
return
|
return
|
||||||
@ -60,6 +70,7 @@ func (s *tunConn) reader() error {
|
|||||||
util.PutBytes(bs)
|
util.PutBytes(bs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
s.stillAlive() // TODO? Only stay alive if we read >0 bytes?
|
||||||
case <-s.stop:
|
case <-s.stop:
|
||||||
s.tun.log.Debugln("Stopping conn reader for", s)
|
s.tun.log.Debugln("Stopping conn reader for", s)
|
||||||
return nil
|
return nil
|
||||||
@ -89,6 +100,33 @@ func (s *tunConn) writer() error {
|
|||||||
s.tun.log.Errorln(s.conn.String(), "TUN/TAP conn write error:", err)
|
s.tun.log.Errorln(s.conn.String(), "TUN/TAP conn write error:", err)
|
||||||
}
|
}
|
||||||
util.PutBytes(b)
|
util.PutBytes(b)
|
||||||
|
s.stillAlive()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *tunConn) stillAlive() {
|
||||||
|
select {
|
||||||
|
case s.alive <- struct{}{}:
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *tunConn) checkForTimeouts() error {
|
||||||
|
const timeout = 2 * time.Minute
|
||||||
|
timer := time.NewTimer(timeout)
|
||||||
|
defer util.TimerStop(timer)
|
||||||
|
defer s.close()
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case _, ok := <-s.alive:
|
||||||
|
if !ok {
|
||||||
|
return errors.New("connection closed")
|
||||||
|
}
|
||||||
|
util.TimerStop(timer)
|
||||||
|
timer.Reset(timeout)
|
||||||
|
case <-timer.C:
|
||||||
|
return errors.New("timed out")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -232,7 +232,8 @@ func (tun *TunAdapter) wrap(conn *yggdrasil.Conn) (c *tunConn, err error) {
|
|||||||
tun: tun,
|
tun: tun,
|
||||||
conn: conn,
|
conn: conn,
|
||||||
send: make(chan []byte, 32), // TODO: is this a sensible value?
|
send: make(chan []byte, 32), // TODO: is this a sensible value?
|
||||||
stop: make(chan interface{}),
|
stop: make(chan struct{}),
|
||||||
|
alive: make(chan struct{}, 1),
|
||||||
}
|
}
|
||||||
// Get the remote address and subnet of the other side
|
// Get the remote address and subnet of the other side
|
||||||
remoteNodeID := conn.RemoteAddr()
|
remoteNodeID := conn.RemoteAddr()
|
||||||
@ -259,6 +260,7 @@ func (tun *TunAdapter) wrap(conn *yggdrasil.Conn) (c *tunConn, err error) {
|
|||||||
// Start the connection goroutines
|
// Start the connection goroutines
|
||||||
go s.reader()
|
go s.reader()
|
||||||
go s.writer()
|
go s.writer()
|
||||||
|
go s.checkForTimeouts()
|
||||||
// Return
|
// Return
|
||||||
return c, err
|
return c, err
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user