]> Sergey Matveev's repositories - btrtrc.git/commitdiff
Ignore dial rate limits for holepunch connects
authorMatt Joiner <anacrolix@gmail.com>
Thu, 18 May 2023 01:37:46 +0000 (11:37 +1000)
committerMatt Joiner <anacrolix@gmail.com>
Thu, 18 May 2023 01:38:10 +0000 (11:38 +1000)
client.go
torrent.go
ut-holepunching_test.go

index 21f213b325b7163ab9d1597fbbff825a1566340c..70b98482820e1bd488c161383c176c02dd3f14d4 100644 (file)
--- a/client.go
+++ b/client.go
@@ -731,9 +731,18 @@ func doProtocolHandshakeOnDialResult(
 
 // Returns nil connection and nil error if no connection could be established for valid reasons.
 func (cl *Client) dialAndCompleteHandshake(opts outgoingConnOpts) (c *PeerConn, err error) {
-       err = cl.config.DialRateLimiter.Wait(context.Background())
-       if err != nil {
-               return
+       // It would be better if dial rate limiting could be tested when considering to open connections
+       // instead. Doing it here means if the limit is low, and the half-open limit is high, we could
+       // end up with lots of outgoing connection attempts pending that were initiated on stale data.
+       {
+               dialReservation := cl.config.DialRateLimiter.Reserve()
+               if !opts.receivedHolepunchConnect {
+                       if !dialReservation.OK() {
+                               err = errors.New("can't make dial limit reservation")
+                               return
+                       }
+                       time.Sleep(dialReservation.Delay())
+               }
        }
        torrent.Add("establish outgoing connection", 1)
        addr := opts.peerInfo.Addr
index 49ae06054d4b362c87f892652f15e9c1e0a7bed4..553fa5db25e8bdf98e0e39f1f52a13254f48650b 100644 (file)
@@ -2801,6 +2801,7 @@ func (t *Torrent) handleReceivedUtHolepunchMsg(msg utHolepunch.Msg, sender *Peer
                }
                return nil
        case utHolepunch.Connect:
+               t.logger.Printf("got holepunch connect request for %v from %p", msg.AddrPort, sender)
                opts := outgoingConnOpts{
                        peerInfo: PeerInfo{
                                Addr:         msg.AddrPort,
index 5df98bfbb11b6e1fe74215ef44f98e60ee17966d..18521195cec547999f9e09fc436a714ceb6bceb1 100644 (file)
@@ -18,6 +18,7 @@ import (
        qt "github.com/frankban/quicktest"
        "github.com/stretchr/testify/assert"
        "github.com/stretchr/testify/require"
+       "golang.org/x/time/rate"
 
        "github.com/anacrolix/torrent/internal/testutil"
 )
@@ -36,9 +37,12 @@ func TestHolepunchConnect(t *testing.T) {
        cfg.DisablePEX = true
        cfg.Debug = true
        cfg.AcceptPeerConnections = false
-       // Listening, even without accepting, still means the leecher-leecher completes the dial to the seeder, and so it
-       // won't attempt to holepunch.
+       // Listening, even without accepting, still means the leecher-leecher completes the dial to the
+       // seeder, and so it won't attempt to holepunch.
        cfg.DisableTCP = true
+       // Ensure that responding to holepunch connects don't wait around for the dial limit. We also
+       // have to allow the initial connection to the leecher though, so it can rendezvous for us.
+       cfg.DialRateLimiter = rate.NewLimiter(0, 1)
        seeder, err := NewClient(cfg)
        require.NoError(t, err)
        defer seeder.Close()
@@ -65,7 +69,7 @@ func TestHolepunchConnect(t *testing.T) {
        cfg.Seed = false
        cfg.DataDir = t.TempDir()
        cfg.MaxAllocPeerRequestDataPerConn = 4
-       cfg.Debug = true
+       //cfg.Debug = true
        cfg.NominalDialTimeout = time.Second
        //cfg.DisableUTP = true
        leecherLeecher, _ := NewClient(cfg)