From: Matt Joiner Date: Wed, 17 Nov 2021 03:00:50 +0000 (+1100) Subject: Avoid calling net.Conn methods with the Client mutex locked X-Git-Tag: v1.39.0~54 X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=0f81e0011ffa601c12a3d21d8537a0e436d4da28;p=btrtrc.git Avoid calling net.Conn methods with the Client mutex locked The utp firewall callback might want to use it. I can't think of a better way to determine with an incoming connection request should be blocked. --- diff --git a/client.go b/client.go index cb988201..ebe35ee0 100644 --- a/client.go +++ b/client.go @@ -260,7 +260,7 @@ func NewClient(cfg *ClientConfig) (cl *Client, err error) { 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 @@ func (cl *Client) establishOutgoingConn(t *Torrent, addr PeerRemoteAddr) (c *Pee 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 @@ func (cl *Client) runReceivedConn(c *PeerConn) { 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 @@ func (cl *Client) runHandshookConn(c *PeerConn, t *Torrent) error { 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 @@ func (cl *Client) runHandshookConn(c *PeerConn, t *Torrent) error { 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 9a3fb0fc..bd0bce2e 100644 --- a/peerconn.go +++ b/peerconn.go @@ -138,7 +138,8 @@ type PeerConn struct { 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 @@ func (cn *PeerConn) onClose() { } 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 441f613c..cd8d273d 100644 --- a/torrent.go +++ b/torrent.go @@ -1468,6 +1468,7 @@ func (t *Torrent) onWebRtcConn( } else { pc.Discovery = PeerSourceIncoming } + pc.conn.SetWriteDeadline(time.Time{}) t.cl.lock() defer t.cl.unlock() err = t.cl.runHandshookConn(pc, t)