client.go | 9 ++++++--- peerconn.go | 5 +++-- torrent.go | 1 + diff --git a/client.go b/client.go index cb988201c9cc8fee9abaabbb15bd900c30ac1456..ebe35ee02e4ab4db0f3bc368c0ce68e6ae2cf284 100644 --- a/client.go +++ b/client.go @@ -260,7 +260,7 @@ cl.LocalPort() for _, _s := range sockets { s := _s // Go is fucking retarded. - cl.onClose = append(cl.onClose, func() { s.Close() }) + cl.onClose = append(cl.onClose, func() { go s.Close() }) if peerNetworkEnabled(parseNetworkString(s.Addr().Network()), cl.config) { cl.dialers = append(cl.dialers, s) cl.listeners = append(cl.listeners, s) @@ -758,6 +758,9 @@ // considered half-open. func (cl *Client) outgoingConnection(t *Torrent, addr PeerRemoteAddr, ps PeerSource, trusted bool) { cl.dialRateLimiter.Wait(context.Background()) c, err := cl.establishOutgoingConn(t, addr) + if err == nil { + c.conn.SetWriteDeadline(time.Time{}) + } cl.lock() defer cl.unlock() // Don't release lock between here and addPeerConn, unless it's for @@ -927,6 +930,7 @@ cl.unlock() return } torrent.Add("received handshake for loaded torrent", 1) + c.conn.SetWriteDeadline(time.Time{}) cl.lock() defer cl.unlock() t.runHandshookConnLoggingErr(c) @@ -943,7 +947,7 @@ } if c.PeerID == cl.peerID { if c.outgoing { connsToSelf.Add(1) - addr := c.conn.RemoteAddr().String() + addr := c.RemoteAddr.String() cl.dopplegangerAddrs[addr] = struct{}{} } /* else { // Because the remote address is not necessarily the same as its client's torrent listen @@ -953,7 +957,6 @@ } */ t.logger.WithLevel(log.Debug).Printf("local and remote peer ids are the same") return nil } - c.conn.SetWriteDeadline(time.Time{}) c.r = deadlineReader{c.conn, c.r} completedHandshakeConnectionFlags.Add(c.connectionFlags(), 1) if connIsIpv6(c.conn) { diff --git a/peerconn.go b/peerconn.go index 9a3fb0fc0491bc0f6a75dd96f02ab1cb4cdfc488..bd0bce2e47e1ee50bbb3e241f1c9a381772a9842 100644 --- a/peerconn.go +++ b/peerconn.go @@ -138,7 +138,8 @@ // See BEP 3 etc. PeerID PeerID PeerExtensionBytes pp.PeerExtensionBits - // The actual Conn, used for closing, and setting socket options. + // The actual Conn, used for closing, and setting socket options. Do not use methods on this + // while holding any mutexes. conn net.Conn // The Reader and Writer for this Conn, with hooks installed for stats, // limiting, deadlines etc. @@ -426,7 +427,7 @@ cn.pex.Close() } cn.tickleWriter() if cn.conn != nil { - cn.conn.Close() + go cn.conn.Close() } if cb := cn.callbacks.PeerConnClosed; cb != nil { cb(cn) diff --git a/torrent.go b/torrent.go index 441f613c17d5242ec4719c32354da9ca6ec524a3..cd8d273d4e2b117b142c4d6316c0b56337eed285 100644 --- a/torrent.go +++ b/torrent.go @@ -1468,6 +1468,7 @@ pc.Discovery = PeerSourceTracker } else { pc.Discovery = PeerSourceIncoming } + pc.conn.SetWriteDeadline(time.Time{}) t.cl.lock() defer t.cl.unlock() err = t.cl.runHandshookConn(pc, t)