Fix race in adding connections to connsByPeer
Side A could already be running Identify with side B before B had the
connection in the connsByPeer, this lead to Connectedness returning
NotConnected and Identify failing.
@@ -160,22 +160,20 @@ func (pn *peernet) connect(p peer.ID) (*conn, error) {
func (pn *peernet) openConn(r peer.ID, l *link) *conn {
lc, rc := l.newConnPair(pn)
log.Debugf("%s opening connection to %s", pn.LocalPeer(), lc.RemotePeer())
+ addConnPair(pn, rc.net, lc, rc)
+
go rc.net.remoteOpenedConn(rc)
pn.addConn(lc)
return lc
}
-func (pn *peernet) remoteOpenedConn(c *conn) {
- log.Debugf("%s accepting connection from %s", pn.LocalPeer(), c.RemotePeer())
- pn.addConn(c)
- pn.handleNewConn(c)
-}
-
-// addConn constructs and adds a connection
-// to given remote peer over given link
-func (pn *peernet) addConn(c *conn) {
- pn.Lock()
+// addConnPair adds connection to both peernets at the same time
+// must be followerd by pn1.addConn(c1) and pn2.addConn(c2)
+func addConnPair(pn1, pn2 *peernet, c1, c2 *conn) {
+ pn1.Lock()
+ pn2.Lock()
+ add := func(pn *peernet, c *conn) {
_, found := pn.connsByPeer[c.RemotePeer()]
if !found {
pn.connsByPeer[c.RemotePeer()] = map[*conn]struct{}{}
@@ -187,11 +185,26 @@ func (pn *peernet) addConn(c *conn) {
pn.connsByLink[c.link] = map[*conn]struct{}{}
}
pn.connsByLink[c.link][c] = struct{}{}
+ }
+ add(pn1, c1)
+ add(pn2, c2)
- c.notifLk.Lock()
- defer c.notifLk.Unlock()
- pn.Unlock()
+ c1.notifLk.Lock()
+ c2.notifLk.Lock()
+ pn2.Unlock()
+ pn1.Unlock()
+}
+
+func (pn *peernet) remoteOpenedConn(c *conn) {
+ log.Debugf("%s accepting connection from %s", pn.LocalPeer(), c.RemotePeer())
+ pn.addConn(c)
+ pn.handleNewConn(c)
+}
+// addConn constructs and adds a connection
+// to given remote peer over given link
+func (pn *peernet) addConn(c *conn) {
+ defer c.notifLk.Unlock()
// Call this after unlocking as it might cause us to immediately close
// the connection and remove it from the swarm.
c.setup()
