client.go | 5 +++++ cmd/torrent/main.go | 7 +++++++ config.go | 2 ++ test/issue377_test.go | 3 +++ testing.go | 3 +++ torrent_test.go | 2 ++ diff --git a/client.go b/client.go index b4d3f17a7e439bd1048ea85940de851c10755e62..6e90fa7583bf3a13db0ee71f9d92ea4770689e14 100644 --- a/client.go +++ b/client.go @@ -932,6 +932,11 @@ // Client lock must be held before entering this. func (cl *Client) runHandshookConn(c *PeerConn, t *Torrent) error { c.setTorrent(t) + for i, b := range cl.config.MinPeerExtensions { + if c.PeerExtensionBytes[i]&b != b { + return fmt.Errorf("peer did not meet minimum peer extensions: %x", c.PeerExtensionBytes) + } + } if c.PeerID == cl.peerID { if c.outgoing { connsToSelf.Add(1) diff --git a/cmd/torrent/main.go b/cmd/torrent/main.go index 06b76f6b52373f9f4211f5e617ed3c6971531b18..50604cf689a66922cec489cf2830325ab09797d5 100644 --- a/cmd/torrent/main.go +++ b/cmd/torrent/main.go @@ -22,6 +22,7 @@ "github.com/anacrolix/log" "github.com/anacrolix/missinggo/v2" "github.com/anacrolix/tagflag" "github.com/anacrolix/torrent/bencode" + pp "github.com/anacrolix/torrent/peer_protocol" "github.com/anacrolix/torrent/version" "github.com/davecgh/go-spew/spew" "github.com/dustin/go-humanize" @@ -186,6 +187,9 @@ TcpPeers bool `default:"true"` UtpPeers bool `default:"true"` Webtorrent bool `default:"true"` DisableWebseeds bool + // Don't progress past handshake for peer connections where the peer doesn't offer the fast + // extension. + RequireFastExtension bool Ipv4 bool `default:"true"` Ipv6 bool `default:"true"` @@ -315,6 +319,9 @@ clientConfig.DownloadRateLimiter = rate.NewLimiter(rate.Limit(*flags.DownloadRate), 1<<20) } if flags.Quiet { clientConfig.Logger = log.Discard + } + if flags.RequireFastExtension { + clientConfig.MinPeerExtensions.SetBit(pp.ExtensionBitFast, true) } clientConfig.MaxUnverifiedBytes = flags.MaxUnverifiedBytes.Int64() diff --git a/config.go b/config.go index 14c129cf977b9226f0b49f69ba41f38b7d98c198..3d370d55fca2f38c182f34f94b0b15e2607c124c 100644 --- a/config.go +++ b/config.go @@ -146,6 +146,8 @@ // OnQuery hook func DHTOnQuery func(query *krpc.Msg, source net.Addr) (propagate bool) Extensions PeerExtensionBits + // Bits that peers must have set to proceed past handshakes. + MinPeerExtensions PeerExtensionBits DisableWebtorrent bool DisableWebseeds bool diff --git a/test/issue377_test.go b/test/issue377_test.go index 7456e9c452901bdfed35d0e9a15ca6ffa5690784..01caaed680ca783a1dc05c2e40eddce31d903d4f 100644 --- a/test/issue377_test.go +++ b/test/issue377_test.go @@ -51,6 +51,9 @@ defer seederClient.Close() defer testutil.ExportStatusWriter(seederClient, "s", t)() leecherClientConfig := torrent.TestingConfig(t) leecherClientConfig.Debug = true + // Don't require fast extension, whether the seeder will provide it or not (so we can test mixed + // cases). + leecherClientConfig.MinPeerExtensions.SetBit(pp.ExtensionBitFast, false) justOneNetwork(leecherClientConfig) leecherClient, err := torrent.NewClient(leecherClientConfig) require.NoError(t, err) diff --git a/testing.go b/testing.go index 6a9d892d4dbeaad495c9ac08a8b2d535a028f4eb..d681796d911b8248355945953b2558a1128cd4ff 100644 --- a/testing.go +++ b/testing.go @@ -3,6 +3,8 @@ import ( "testing" "time" + + pp "github.com/anacrolix/torrent/peer_protocol" ) func TestingConfig(t testing.TB) *ClientConfig { @@ -15,6 +17,7 @@ cfg.NoDefaultPortForwarding = true cfg.DisableAcceptRateLimiting = true cfg.ListenPort = 0 cfg.KeepAliveTimeout = time.Millisecond + cfg.MinPeerExtensions.SetBit(pp.ExtensionBitFast, true) //cfg.Debug = true //cfg.Logger = cfg.Logger.WithText(func(m log.Msg) string { // t := m.Text() diff --git a/torrent_test.go b/torrent_test.go index 02e56e2dc5f5baf2ba9f6d0f517a70169b00ce34..2b96f19157421ebab0c5eb8979bd8b44bb4e2774 100644 --- a/torrent_test.go +++ b/torrent_test.go @@ -163,6 +163,8 @@ // Check the behaviour of Torrent.Metainfo when metadata is not completed. func TestTorrentMetainfoIncompleteMetadata(t *testing.T) { cfg := TestingConfig(t) cfg.Debug = true + // Disable this just because we manually initiate a connection without it. + cfg.MinPeerExtensions.SetBit(pp.ExtensionBitFast, false) cl, err := NewClient(cfg) require.NoError(t, err) defer cl.Close()