client.go | 8 ++++---- torrent.go | 13 ++++++++++++- diff --git a/client.go b/client.go index e49f39bb5573ee91b814dee39f0aab9edf61cf61..a24e0aeb2b4188ac2e74a54fcd5ef854ddd58cec 100644 --- a/client.go +++ b/client.go @@ -899,7 +899,7 @@ addr := c.conn.RemoteAddr().String() cl.dopplegangerAddrs[addr] = struct{}{} return } - cl.runHandshookConn(c, t) + cl.runHandshookConn(c, t, true) } func (cl *Client) runReceivedConn(c *connection) { @@ -926,14 +926,14 @@ // as a doppleganger. Instead, the initiator can record *us* as the // 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) diff --git a/torrent.go b/torrent.go index 4d36209c5a825440b317a06d16bd335452716b46..ba3500254c10da25ce5d43dc7d7597ea095c8941 100644 --- a/torrent.go +++ b/torrent.go @@ -1296,7 +1296,7 @@ return len(peers) } // 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 @@ return false } 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 } }