From 3e9a5a4aec4c8158384056ce6f865c49739de625 Mon Sep 17 00:00:00 2001 From: Matt Joiner Date: Thu, 23 Apr 2020 13:03:35 +1000 Subject: [PATCH] Expose ClientConfig.Extensions Also run the storage failure test with fast disabled for the seeder. This probably would have tickled some issues in the past, so it seems like a good place to try it out. --- client.go | 10 ++++------ config.go | 4 ++++ peer_protocol/handshake.go | 10 +++++++--- peerconn.go | 2 +- test/issue377_test.go | 12 ++++++++++++ torrent_test.go | 2 +- 6 files changed, 29 insertions(+), 11 deletions(-) diff --git a/client.go b/client.go index 4c2d58a7..5ca405a5 100644 --- a/client.go +++ b/client.go @@ -64,8 +64,6 @@ type Client struct { listeners []Listener dhtServers []DhtServer ipBlockList iplist.Ranger - // Our BitTorrent protocol extension bytes, sent in our BT handshakes. - extensionBytes pp.PeerExtensionBits // Set of addresses that have our client ID. This intentionally will // include ourselves if we end up trying to connect to our own address @@ -122,6 +120,7 @@ func (cl *Client) WriteStatus(_w io.Writer) { defer w.Flush() fmt.Fprintf(w, "Listen port: %d\n", cl.LocalPort()) fmt.Fprintf(w, "Peer ID: %+q\n", cl.PeerID()) + fmt.Fprintf(w, "Extension bits: %v\n", cl.config.Extensions) fmt.Fprintf(w, "Announce key: %x\n", cl.announceKey()) fmt.Fprintf(w, "Banned IPs: %d\n", len(cl.badPeerIPsLocked())) cl.eachDhtServer(func(s DhtServer) { @@ -186,7 +185,6 @@ func NewClient(cfg *ClientConfig) (cl *Client, err error) { } cl.Close() }() - cl.extensionBytes = defaultPeerExtensionBytes() cl.event.L = cl.locker() storageImpl := cfg.DefaultStorage if storageImpl == nil { @@ -847,7 +845,7 @@ func (cl *Client) receiveHandshakes(c *PeerConn) (t *Torrent, err error) { } func (cl *Client) connBtHandshake(c *PeerConn, ih *metainfo.Hash) (ret metainfo.Hash, err error) { - res, err := pp.Handshake(c.rw(), ih, cl.peerID, cl.extensionBytes) + res, err := pp.Handshake(c.rw(), ih, cl.peerID, cl.config.Extensions) if err != nil { return } @@ -927,7 +925,7 @@ func (cl *Client) runHandshookConn(c *PeerConn, t *Torrent) error { // See the order given in Transmission's tr_peerMsgsNew. func (cl *Client) sendInitialMessages(conn *PeerConn, torrent *Torrent) { - if conn.PeerExtensionBytes.SupportsExtended() && cl.extensionBytes.SupportsExtended() { + if conn.PeerExtensionBytes.SupportsExtended() && cl.config.Extensions.SupportsExtended() { conn.post(pp.Message{ Type: pp.Extended, ExtendedID: pp.HandshakeExtendedID, @@ -968,7 +966,7 @@ func (cl *Client) sendInitialMessages(conn *PeerConn, torrent *Torrent) { } conn.postBitfield() }() - if conn.PeerExtensionBytes.SupportsDHT() && cl.extensionBytes.SupportsDHT() && cl.haveDhtServer() { + if conn.PeerExtensionBytes.SupportsDHT() && cl.config.Extensions.SupportsDHT() && cl.haveDhtServer() { conn.post(pp.Message{ Type: pp.Port, Port: cl.dhtPort(), diff --git a/config.go b/config.go index 1c9be6ef..105e8674 100644 --- a/config.go +++ b/config.go @@ -128,6 +128,8 @@ type ClientConfig struct { DHTOnQuery func(query *krpc.Msg, source net.Addr) (propagate bool) DefaultRequestStrategy RequestStrategyMaker + + Extensions PeerExtensionBits } func (cfg *ClientConfig) SetListenAddr(addr string) *ClientConfig { @@ -169,6 +171,8 @@ func NewDefaultClientConfig() *ClientConfig { Logger: log.Default, DefaultRequestStrategy: RequestStrategyDuplicateRequestTimeout(5 * time.Second), + + Extensions: defaultPeerExtensionBytes(), } //cc.ConnTracker.SetNoMaxEntries() //cc.ConnTracker.Timeout = func(conntrack.Entry) time.Duration { return 0 } diff --git a/peer_protocol/handshake.go b/peer_protocol/handshake.go index 09d9343e..e23f8b62 100644 --- a/peer_protocol/handshake.go +++ b/peer_protocol/handshake.go @@ -41,7 +41,7 @@ func (me PeerExtensionBits) String() string { func NewPeerExtensionBytes(bits ...ExtensionBit) (ret PeerExtensionBits) { for _, b := range bits { - ret.SetBit(b) + ret.SetBit(b, true) } return } @@ -58,8 +58,12 @@ func (pex PeerExtensionBits) SupportsFast() bool { return pex.GetBit(ExtensionBitFast) } -func (pex *PeerExtensionBits) SetBit(bit ExtensionBit) { - pex[7-bit/8] |= 1 << (bit % 8) +func (pex *PeerExtensionBits) SetBit(bit ExtensionBit, on bool) { + if on { + pex[7-bit/8] |= 1 << (bit % 8) + } else { + pex[7-bit/8] &^= 1 << (bit % 8) + } } func (pex PeerExtensionBits) GetBit(bit ExtensionBit) bool { diff --git a/peerconn.go b/peerconn.go index 9bb51fac..0e267a78 100644 --- a/peerconn.go +++ b/peerconn.go @@ -934,7 +934,7 @@ func (c *PeerConn) lastHelpful() (ret time.Time) { } func (c *PeerConn) fastEnabled() bool { - return c.PeerExtensionBytes.SupportsFast() && c.t.cl.extensionBytes.SupportsFast() + return c.PeerExtensionBytes.SupportsFast() && c.t.cl.config.Extensions.SupportsFast() } func (c *PeerConn) reject(r request) { diff --git a/test/issue377_test.go b/test/issue377_test.go index b6f76178..c723e51a 100644 --- a/test/issue377_test.go +++ b/test/issue377_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/anacrolix/log" + pp "github.com/anacrolix/torrent/peer_protocol" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -22,7 +23,15 @@ func justOneNetwork(cc *torrent.ClientConfig) { cc.DisableIPv4 = true } +func TestReceiveChunkStorageFailureSeederFastExtensionDisabled(t *testing.T) { + testReceiveChunkStorageFailure(t, false) +} + func TestReceiveChunkStorageFailure(t *testing.T) { + testReceiveChunkStorageFailure(t, true) +} + +func testReceiveChunkStorageFailure(t *testing.T, seederFast bool) { seederDataDir, metainfo := testutil.GreetingTestTorrent() defer os.RemoveAll(seederDataDir) seederClientConfig := torrent.TestingConfig() @@ -33,6 +42,7 @@ func TestReceiveChunkStorageFailure(t *testing.T) { seederClientConfig.DefaultStorage = seederClientStorage seederClientConfig.Seed = true seederClientConfig.Debug = true + seederClientConfig.Extensions.SetBit(pp.ExtensionBitFast, seederFast) seederClient, err := torrent.NewClient(seederClientConfig) require.NoError(t, err) defer seederClient.Close() @@ -64,6 +74,8 @@ func TestReceiveChunkStorageFailure(t *testing.T) { seederTorrent.AddClientPeer(leecherClient) <-leecherTorrent.GotInfo() assertReadAllGreeting(t, leecherTorrent.NewReader()) + // TODO: Check that PeerConns fastEnabled matches seederFast? + //select {} } type pieceState struct { diff --git a/torrent_test.go b/torrent_test.go index 5ecd93b4..6c47a80c 100644 --- a/torrent_test.go +++ b/torrent_test.go @@ -183,7 +183,7 @@ func TestTorrentMetainfoIncompleteMetadata(t *testing.T) { defer nc.Close() var pex PeerExtensionBits - pex.SetBit(pp.ExtensionBitExtended) + pex.SetBit(pp.ExtensionBitExtended, true) hr, err := pp.Handshake(nc, &ih, [20]byte{}, pex) require.NoError(t, err) assert.True(t, hr.PeerExtensionBits.GetBit(pp.ExtensionBitExtended)) -- 2.48.1