diff --git a/go.mod b/go.mod index 342e7bb81..e98b010c9 100644 --- a/go.mod +++ b/go.mod @@ -19,6 +19,7 @@ require ( github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 github.com/stretchr/testify v1.8.4 + github.com/timandy/routine v1.1.1 github.com/vishvananda/netlink v1.1.0 golang.org/x/crypto v0.12.0 golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53 @@ -43,7 +44,6 @@ require ( github.com/prometheus/common v0.42.0 // indirect github.com/prometheus/procfs v0.10.1 // indirect github.com/rogpeppe/go-internal v1.10.0 // indirect - github.com/timandy/routine v1.1.1 // indirect github.com/vishvananda/netns v0.0.4 // indirect golang.org/x/mod v0.10.0 // indirect golang.org/x/tools v0.8.0 // indirect diff --git a/handshake_ix.go b/handshake_ix.go index 52efdf5e6..09c65ad22 100644 --- a/handshake_ix.go +++ b/handshake_ix.go @@ -130,6 +130,7 @@ func ixHandshakeStage1(f *Interface, addr *udp.Addr, via *ViaSender, packet []by } hostinfo := &HostInfo{ + syncRWMutex: newSyncRWMutex(mutexKey{Type: mutexKeyTypeHostInfo, ID: uint32(vpnIp)}), ConnectionState: ci, localIndexId: myIndex, remoteIndexId: hs.Details.InitiatorIndex, diff --git a/handshake_manager.go b/handshake_manager.go index a70f4dbc3..1a172d373 100644 --- a/handshake_manager.go +++ b/handshake_manager.go @@ -7,7 +7,6 @@ import ( "encoding/binary" "errors" "net" - "sync" "time" "github.com/rcrowley/go-metrics" @@ -44,7 +43,7 @@ type HandshakeConfig struct { type HandshakeManager struct { // Mutex for interacting with the vpnIps and indexes maps - sync.RWMutex + syncRWMutex vpnIps map[iputil.VpnIp]*HostInfo indexes map[uint32]*HostInfo @@ -65,6 +64,7 @@ type HandshakeManager struct { func NewHandshakeManager(l *logrus.Logger, tunCidr *net.IPNet, preferredRanges []*net.IPNet, mainHostMap *HostMap, lightHouse *LightHouse, outside udp.Conn, config HandshakeConfig) *HandshakeManager { return &HandshakeManager{ + syncRWMutex: newSyncRWMutex(mutexKey{Type: mutexKeyTypeHandshakeManager}), vpnIps: map[iputil.VpnIp]*HostInfo{}, indexes: map[uint32]*HostInfo{}, mainHostMap: mainHostMap, @@ -308,6 +308,7 @@ func (c *HandshakeManager) AddVpnIp(vpnIp iputil.VpnIp, init func(*HostInfo)) *H } hostinfo := &HostInfo{ + syncRWMutex: newSyncRWMutex(mutexKey{Type: mutexKeyTypeHostInfo, ID: uint32(vpnIp)}), vpnIp: vpnIp, HandshakePacket: make(map[uint8][]byte, 0), relayState: RelayState{ diff --git a/hostmap.go b/hostmap.go index c82d73bc3..5f2a846a5 100644 --- a/hostmap.go +++ b/hostmap.go @@ -264,7 +264,7 @@ func NewHostMap(l *logrus.Logger, vpnCIDR *net.IPNet, preferredRanges []*net.IPN r := map[uint32]*HostInfo{} relays := map[uint32]*HostInfo{} m := HostMap{ - syncRWMutex: newSyncRWMutex(mutexKey{Type: "hostmap"}), + syncRWMutex: newSyncRWMutex(mutexKey{Type: mutexKeyTypeHostMap}), Indexes: i, Relays: relays, RemoteIndexes: r, diff --git a/mutex.go b/mutex.go index 181767468..1bb3c20a6 100644 --- a/mutex.go +++ b/mutex.go @@ -9,12 +9,19 @@ import ( type syncRWMutex = sync.RWMutex +type mutexKeyType string + +const ( + mutexKeyTypeHostMap mutexKeyType = "hostmap" + mutexKeyTypeHostInfo = "hostinfo" + mutexKeyTypeHandshakeManager = "handshake-manager" +) + func newSyncRWMutex(mutexKey) syncRWMutex { return sync.RWMutex{} } type mutexKey struct { - Type string - SubType string - ID uint32 + Type mutexKeyType + ID uint32 } diff --git a/mutex_debug.go b/mutex_debug.go index 3210b1ed2..169316c59 100644 --- a/mutex_debug.go +++ b/mutex_debug.go @@ -13,10 +13,17 @@ import ( var threadLocal routine.ThreadLocal = routine.NewThreadLocalWithInitial(func() any { return map[mutexKey]mutexValue{} }) +type mutexKeyType string + +const ( + mutexKeyTypeHostMap mutexKeyType = "hostmap" + mutexKeyTypeHostInfo = "hostinfo" + mutexKeyTypeHandshakeManager = "handshake-manager" +) + type mutexKey struct { - Type string - SubType string - ID uint32 + Type mutexKeyType + ID uint32 } type mutexValue struct { @@ -37,22 +44,22 @@ func newSyncRWMutex(key mutexKey) syncRWMutex { func checkMutex(state map[mutexKey]mutexValue, add mutexKey) { switch add.Type { - case "hostinfo": + case mutexKeyTypeHostInfo: // Check for any other hostinfo keys: for k := range state { - if k.Type == "hostinfo" { + if k.Type == mutexKeyTypeHostInfo { panic(fmt.Errorf("grabbing hostinfo lock and already have a hostinfo lock: state=%v add=%v", state, add)) } } - if _, ok := state[mutexKey{Type: "hostmap", SubType: "main"}]; ok { - panic(fmt.Errorf("grabbing hostinfo lock and already have hostmap-main: state=%v add=%v", state, add)) + if _, ok := state[mutexKey{Type: mutexKeyTypeHostMap}]; ok { + panic(fmt.Errorf("grabbing hostinfo lock and already have hostmap: state=%v add=%v", state, add)) } - if _, ok := state[mutexKey{Type: "hostmap", SubType: "pending"}]; ok { - panic(fmt.Errorf("grabbing hostinfo lock and already have hostmap-pending: state=%v add=%v", state, add)) + if _, ok := state[mutexKey{Type: mutexKeyTypeHandshakeManager}]; ok { + panic(fmt.Errorf("grabbing hostinfo lock and already have handshake-manager: state=%v add=%v", state, add)) } - case "hostmap-pending": - if _, ok := state[mutexKey{Type: "hostmap", SubType: "main"}]; ok { - panic(fmt.Errorf("grabbing hostmap-pending lock and already have hostmap-main: state=%v add=%v", state, add)) + case mutexKeyTypeHandshakeManager: + if _, ok := state[mutexKey{Type: mutexKeyTypeHostMap}]; ok { + panic(fmt.Errorf("grabbing handshake-manager lock and already have hostmap: state=%v add=%v", state, add)) } } }