Fix race on tun conns, but still deadlocks if more than one connection is opened

This commit is contained in:
Neil Alexander 2019-04-21 12:00:31 +01:00
parent 79bcfbf175
commit 781cd7571f
No known key found for this signature in database
GPG key ID: A02A2019A2BB0944
3 changed files with 18 additions and 8 deletions

View file

@ -30,7 +30,6 @@ type TunAdapter struct {
config *config.NodeState
log *log.Logger
reconfigure chan chan error
conns map[crypto.NodeID]*yggdrasil.Conn
listener *yggdrasil.Listener
dialer *yggdrasil.Dialer
addr address.Address
@ -39,6 +38,7 @@ type TunAdapter struct {
mtu int
iface *water.Interface
mutex sync.RWMutex // Protects the below
conns map[crypto.NodeID]*yggdrasil.Conn
isOpen bool
}
@ -173,13 +173,24 @@ func (tun *TunAdapter) handler() error {
tun.log.Errorln("TUN/TAP error accepting connection:", err)
return err
}
tun.log.Println("Accepted connection from", conn.RemoteAddr())
go tun.connReader(conn)
}
}
func (tun *TunAdapter) connReader(conn *yggdrasil.Conn) error {
tun.conns[conn.RemoteAddr()] = conn
remoteNodeID := conn.RemoteAddr()
tun.mutex.Lock()
if _, isIn := tun.conns[remoteNodeID]; isIn {
tun.mutex.Unlock()
return errors.New("duplicate connection")
}
tun.conns[remoteNodeID] = conn
tun.mutex.Unlock()
defer func() {
tun.mutex.Lock()
delete(tun.conns, remoteNodeID)
tun.mutex.Unlock()
}()
b := make([]byte, 65535)
for {
n, err := conn.Read(b)
@ -242,8 +253,9 @@ func (tun *TunAdapter) ifaceReader() error {
}
dstNodeID, dstNodeIDMask = dstAddr.GetNodeIDandMask()
// Do we have an active connection for this node ID?
tun.mutex.Lock()
if conn, isIn := tun.conns[*dstNodeID]; isIn {
tun.log.Println("Got", &conn)
tun.mutex.Unlock()
w, err := conn.Write(bs)
if err != nil {
tun.log.Println("Unable to write to remote:", err)
@ -253,11 +265,12 @@ func (tun *TunAdapter) ifaceReader() error {
continue
}
} else {
tun.log.Println("Opening connection for", *dstNodeID)
if conn, err := tun.dialer.DialByNodeIDandMask(dstNodeID, dstNodeIDMask); err == nil {
tun.conns[*dstNodeID] = &conn
tun.mutex.Unlock()
go tun.connReader(&conn)
} else {
tun.mutex.Unlock()
tun.log.Println("Error dialing:", err)
}
}

View file

@ -2,7 +2,6 @@ package yggdrasil
import (
"errors"
"fmt"
"sync"
"sync/atomic"
"time"
@ -124,7 +123,6 @@ func (c *Conn) Write(b []byte) (bytesWritten int, err error) {
return 0, errors.New("session is closed")
}
if c.session == nil {
fmt.Println("No session found, starting search for", &c)
c.core.router.doAdmin(func() {
c.startSearch()
})