From: Matt Joiner <anacrolix@gmail.com>
Date: Mon, 14 Aug 2023 01:38:47 +0000 (+1000)
Subject: Remove unnecessary use of SO_REUSEPORT
X-Git-Tag: v1.52.5
X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=5a335520955f5501239feb699fc38e62b7cf8698;p=btrtrc.git

Remove unnecessary use of SO_REUSEPORT

Fixes https://github.com/anacrolix/torrent/discussions/856.
---

diff --git a/client_test.go b/client_test.go
index 22281efd..d2a88e9e 100644
--- a/client_test.go
+++ b/client_test.go
@@ -897,7 +897,7 @@ func TestBadPeerIpPort(t *testing.T) {
 
 // https://github.com/anacrolix/torrent/issues/837
 func TestClientConfigSetHandlerNotIgnored(t *testing.T) {
-	cfg := NewDefaultClientConfig()
+	cfg := TestingConfig(t)
 	cfg.Logger.SetHandlers(log.DiscardHandler)
 	c := qt.New(t)
 	cl, err := NewClient(cfg)
diff --git a/fs/go.mod b/fs/go.mod
index 67c01ef0..004cee72 100644
--- a/fs/go.mod
+++ b/fs/go.mod
@@ -5,7 +5,7 @@ go 1.20
 require (
 	github.com/anacrolix/envpprof v1.2.1
 	github.com/anacrolix/fuse v0.2.0
-	github.com/anacrolix/log v0.14.0
+	github.com/anacrolix/log v0.14.1
 	github.com/anacrolix/missinggo/v2 v2.7.2-0.20230527121029-a582b4f397b9
 	github.com/anacrolix/tagflag v1.3.0
 	github.com/anacrolix/torrent v1.47.1-0.20221102120345-c63f7e1bd720
diff --git a/fs/go.sum b/fs/go.sum
index 3f7daed3..b32d6e43 100644
--- a/fs/go.sum
+++ b/fs/go.sum
@@ -46,6 +46,8 @@ github.com/anacrolix/log v0.10.1-0.20220123034749-3920702c17f8/go.mod h1:GmnE2c0
 github.com/anacrolix/log v0.13.1/go.mod h1:D4+CvN8SnruK6zIFS/xPoRJmtvtnxs+CSfDQ+BFxZ68=
 github.com/anacrolix/log v0.14.0 h1:mYhTSemILe/Z8tIxbGdTIWWpPspI8W/fhZHpoFbDaL0=
 github.com/anacrolix/log v0.14.0/go.mod h1:1OmJESOtxQGNMlUO5rcv96Vpp9mfMqXXbe2RdinFLdY=
+github.com/anacrolix/log v0.14.1 h1:j2FcIpYZ5FbANetUcm5JNu+zUBGADSp/VbjhUPrAY0k=
+github.com/anacrolix/log v0.14.1/go.mod h1:1OmJESOtxQGNMlUO5rcv96Vpp9mfMqXXbe2RdinFLdY=
 github.com/anacrolix/lsan v0.0.0-20211126052245-807000409a62 h1:P04VG6Td13FHMgS5ZBcJX23NPC/fiC4cp9bXwYujdYM=
 github.com/anacrolix/lsan v0.0.0-20211126052245-807000409a62/go.mod h1:66cFKPCO7Sl4vbFnAaSq7e4OXtdMhRSBagJGWgmpJbM=
 github.com/anacrolix/missinggo v0.0.0-20180725070939-60ef2fbf63df/go.mod h1:kwGiTUTZ0+p4vAz3VbAI5a30t2YbvemcmspjKwrAz5s=
diff --git a/socket.go b/socket.go
index c1fb97fd..2d4ea863 100644
--- a/socket.go
+++ b/socket.go
@@ -37,10 +37,17 @@ func listen(n network, addr string, f firewallCallback, logger log.Logger) (sock
 	}
 }
 
+// Dialing TCP from a local port limits us to a single outgoing TCP connection to each remote
+// client. Instead, this should be a last resort if we need to use holepunching, and only then to
+// connect to other clients that actually try to holepunch TCP.
+const dialTcpFromListenPort = false
+
 var tcpListenConfig = net.ListenConfig{
 	Control: func(network, address string, c syscall.RawConn) (err error) {
 		controlErr := c.Control(func(fd uintptr) {
-			err = setReusePortSockOpts(fd)
+			if dialTcpFromListenPort {
+				err = setReusePortSockOpts(fd)
+			}
 		})
 		if err != nil {
 			return
@@ -54,38 +61,49 @@ var tcpListenConfig = net.ListenConfig{
 
 func listenTcp(network, address string) (s socket, err error) {
 	l, err := tcpListenConfig.Listen(context.Background(), network, address)
-	return tcpSocket{
+	if err != nil {
+		return
+	}
+	netDialer := net.Dialer{
+		// We don't want fallback, as we explicitly manage the IPv4/IPv6 distinction ourselves,
+		// although it's probably not triggered as I think the network is already constrained to
+		// tcp4 or tcp6 at this point.
+		FallbackDelay: -1,
+		// BitTorrent connections manage their own keepalives.
+		KeepAlive: tcpListenConfig.KeepAlive,
+		Control: func(network, address string, c syscall.RawConn) (err error) {
+			controlErr := c.Control(func(fd uintptr) {
+				err = setSockNoLinger(fd)
+				if err != nil {
+					// Failing to disable linger is undesirable, but not fatal.
+					log.Levelf(log.Debug, "error setting linger socket option on tcp socket: %v", err)
+					err = nil
+				}
+				// This is no longer required I think, see
+				// https://github.com/anacrolix/torrent/discussions/856. I added this originally to
+				// allow dialling out from the client's listen port, but that doesn't really work. I
+				// think Linux older than ~2013 doesn't support SO_REUSEPORT.
+				if dialTcpFromListenPort {
+					err = setReusePortSockOpts(fd)
+				}
+			})
+			if err == nil {
+				err = controlErr
+			}
+			return
+		},
+	}
+	if dialTcpFromListenPort {
+		netDialer.LocalAddr = l.Addr()
+	}
+	s = tcpSocket{
 		Listener: l,
 		NetworkDialer: NetworkDialer{
 			Network: network,
-			Dialer: &net.Dialer{
-				// Dialling TCP from a local port limits us to a single outgoing TCP connection to
-				// each remote client. Instead this should be a last resort if we need to use holepunching, and only then to connect to other clients that actually try to holepunch TCP.
-				//LocalAddr: l.Addr(),
-
-				// We don't want fallback, as we explicitly manage the IPv4/IPv6 distinction
-				// ourselves, although it's probably not triggered as I think the network is already
-				// constrained to tcp4 or tcp6 at this point.
-				FallbackDelay: -1,
-				// BitTorrent connections manage their own keep-alives.
-				KeepAlive: tcpListenConfig.KeepAlive,
-				Control: func(network, address string, c syscall.RawConn) (err error) {
-					controlErr := c.Control(func(fd uintptr) {
-						err = setSockNoLinger(fd)
-						if err != nil {
-							// Failing to disable linger is undesirable, but not fatal.
-							log.Printf("error setting linger socket option on tcp socket: %v", err)
-						}
-						err = setReusePortSockOpts(fd)
-					})
-					if err == nil {
-						err = controlErr
-					}
-					return
-				},
-			},
+			Dialer:  &netDialer,
 		},
-	}, err
+	}
+	return
 }
 
 type tcpSocket struct {