cl.dopplegangerAddrs[addr] = struct{}{}
return
}
- cl.runHandshookConn(c, t)
+ cl.runHandshookConn(c, t, true)
}
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)
}
// 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
}
}
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
}
}