mirror of
https://github.com/yggdrasil-network/yggdrasil-go.git
synced 2025-04-29 06:35:07 +03:00
a couple race fixes and use timer.AfterFunc instead of sleeping goroutines or ticker in a few places
This commit is contained in:
parent
a3d4d8125b
commit
502f2937a9
11 changed files with 66 additions and 98 deletions
|
@ -23,7 +23,7 @@ type tunConn struct {
|
|||
addr address.Address
|
||||
snet address.Subnet
|
||||
stop chan struct{}
|
||||
alive chan struct{}
|
||||
alive *time.Timer // From calling time.AfterFunc
|
||||
}
|
||||
|
||||
func (s *tunConn) close() {
|
||||
|
@ -40,10 +40,6 @@ func (s *tunConn) _close_nomutex() {
|
|||
defer func() { recover() }()
|
||||
close(s.stop) // Closes reader/writer goroutines
|
||||
}()
|
||||
func() {
|
||||
defer func() { recover() }()
|
||||
close(s.alive) // Closes timeout goroutine
|
||||
}()
|
||||
}
|
||||
|
||||
func (s *tunConn) _read(bs []byte) (err error) {
|
||||
|
@ -228,27 +224,8 @@ func (s *tunConn) _write(bs []byte) (err error) {
|
|||
}
|
||||
|
||||
func (s *tunConn) stillAlive() {
|
||||
defer func() { recover() }()
|
||||
select {
|
||||
case s.alive <- struct{}{}:
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
func (s *tunConn) checkForTimeouts() error {
|
||||
timer := time.NewTimer(tunConnTimeout)
|
||||
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(tunConnTimeout)
|
||||
case <-timer.C:
|
||||
return errors.New("timed out")
|
||||
}
|
||||
if s.alive != nil {
|
||||
s.alive.Stop()
|
||||
}
|
||||
s.alive = time.AfterFunc(tunConnTimeout, s.close)
|
||||
}
|
||||
|
|
|
@ -227,10 +227,9 @@ func (tun *TunAdapter) handler() error {
|
|||
func (tun *TunAdapter) wrap(conn *yggdrasil.Conn) (c *tunConn, err error) {
|
||||
// Prepare a session wrapper for the given connection
|
||||
s := tunConn{
|
||||
tun: tun,
|
||||
conn: conn,
|
||||
stop: make(chan struct{}),
|
||||
alive: make(chan struct{}, 1),
|
||||
tun: tun,
|
||||
conn: conn,
|
||||
stop: make(chan struct{}),
|
||||
}
|
||||
c = &s
|
||||
// Get the remote address and subnet of the other side
|
||||
|
@ -255,13 +254,13 @@ func (tun *TunAdapter) wrap(conn *yggdrasil.Conn) (c *tunConn, err error) {
|
|||
// we receive a packet through the interface for this address
|
||||
tun.addrToConn[s.addr] = &s
|
||||
tun.subnetToConn[s.snet] = &s
|
||||
// Set the read callback and start the timeout goroutine
|
||||
// Set the read callback and start the timeout
|
||||
conn.SetReadCallback(func(bs []byte) {
|
||||
s.RecvFrom(conn, func() {
|
||||
s._read(bs)
|
||||
})
|
||||
})
|
||||
go s.checkForTimeouts()
|
||||
s.RecvFrom(nil, s.stillAlive)
|
||||
// Return
|
||||
return c, err
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue