]> Sergey Matveev's repositories - btrtrc.git/commitdiff
bug fix: race condition between outgoing connection and incoming connection
authorluffyma(马林) <luffyma@tencent.com>
Wed, 10 May 2017 03:04:31 +0000 (11:04 +0800)
committerluffyma(马林) <luffyma@tencent.com>
Wed, 10 May 2017 10:31:19 +0000 (18:31 +0800)
client.go
torrent.go

index e49f39bb5573ee91b814dee39f0aab9edf61cf61..a24e0aeb2b4188ac2e74a54fcd5ef854ddd58cec 100644 (file)
--- a/client.go
+++ b/client.go
@@ -899,7 +899,7 @@ func (cl *Client) runInitiatedHandshookConn(c *connection, t *Torrent) {
                cl.dopplegangerAddrs[addr] = struct{}{}
                return
        }
-       cl.runHandshookConn(c, t)
+       cl.runHandshookConn(c, t, true)
 }
 
 func (cl *Client) runReceivedConn(c *connection) {
@@ -926,14 +926,14 @@ func (cl *Client) runReceivedConn(c *connection) {
                // doppleganger.
                return
        }
-       cl.runHandshookConn(c, t)
+       cl.runHandshookConn(c, t, false)
 }
 
-func (cl *Client) runHandshookConn(c *connection, t *Torrent) {
+func (cl *Client) runHandshookConn(c *connection, t *Torrent, outgoing bool) {
        c.conn.SetWriteDeadline(time.Time{})
        c.r = deadlineReader{c.conn, c.r}
        completedHandshakeConnectionFlags.Add(c.connectionFlags(), 1)
-       if !t.addConnection(c) {
+       if !t.addConnection(c, outgoing) {
                return
        }
        defer t.dropConnection(c)
index 4d36209c5a825440b317a06d16bd335452716b46..ba3500254c10da25ce5d43dc7d7597ea095c8941 100644 (file)
@@ -1296,7 +1296,7 @@ func (t *Torrent) numTotalPeers() int {
 }
 
 // Returns true if the connection is added.
-func (t *Torrent) addConnection(c *connection) bool {
+func (t *Torrent) addConnection(c *connection, outgoing bool) bool {
        if t.cl.closed.IsSet() {
                return false
        }
@@ -1305,8 +1305,19 @@ func (t *Torrent) addConnection(c *connection) bool {
        }
        for c0 := range t.conns {
                if c.PeerID == c0.PeerID {
+                       // Retain the connection from lower peer ID to higher.
+                       lower := string(t.cl.peerID[:]) < string(c.PeerID[:])
+                       if (outgoing && lower) || (!outgoing && !lower) {
+                               c0.Close()
+                               t.deleteConnection(c0)
+                               duplicateClientConns.Add(1)
+                               log.Printf("Drop connection: %s, %s, %s", t.name(), c0.localAddr(), c0.remoteAddr())
+                               continue
+                       }
+
                        // Already connected to a client with that ID.
                        duplicateClientConns.Add(1)
+                       log.Printf("Drop connection: %s, %s, %s", t.name(), c.localAddr(), c.remoteAddr())
                        return false
                }
        }