7 pp "github.com/anacrolix/torrent/peer_protocol"
9 qt "github.com/frankban/quicktest"
11 "github.com/anacrolix/torrent/internal/testutil"
13 "github.com/anacrolix/sync"
15 . "github.com/anacrolix/torrent"
19 testRepliesToOddsExtensionName = "pm_me_odds"
20 testRepliesToEvensExtensionName = "pm_me_evens"
26 // Name of the endpoint that this handler is for, for logging.
28 // Whether we expect evens or odds
30 // Extension name of messages we expect to handle.
31 answerToName pp.ExtensionName,
32 // Extension name of messages we expect to send.
33 replyToName pp.ExtensionName,
34 // Signal done when this value is seen.
36 ) func(event PeerConnReadExtensionMessageEvent) {
37 return func(event PeerConnReadExtensionMessageEvent) {
38 // Read handshake, don't look it up.
39 if event.ExtensionNumber == 0 {
42 name, builtin, err := event.PeerConn.LocalLtepProtocolMap.LookupId(event.ExtensionNumber)
43 c.Assert(err, qt.IsNil)
44 // Not a user protocol.
50 u64, err := strconv.ParseUint(string(event.Payload), 10, 0)
51 c.Assert(err, qt.IsNil)
53 c.Logf("%v got %d", handlerName, i)
58 c.Assert(i%2, qt.Equals, expectedMod2)
61 event.PeerConn.WriteExtendedMessage(
63 []byte(strconv.FormatUint(uint64(i+1), 10))),
67 c.Fatalf("got unexpected extension name %q", name)
72 func TestUserLtep(t *testing.T) {
76 makeCfg := func() *ClientConfig {
77 cfg := TestingConfig(t)
78 // Only want a single connection to between the clients.
80 cfg.DisableIPv6 = true
85 evensCfg.Callbacks.ReadExtendedHandshake = func(pc *PeerConn, msg *pp.ExtendedHandshakeMessage) {
86 // The client lock is held while handling this event, so we have to do synchronous work in a
87 // separate goroutine.
89 // Check sending an extended message for a protocol the peer doesn't support is an error.
90 c.Check(pc.WriteExtendedMessage("pm_me_floats", []byte("3.142")), qt.IsNotNil)
91 // Kick things off by sending a 1.
92 c.Check(pc.WriteExtendedMessage(testRepliesToOddsExtensionName, []byte("1")), qt.IsNil)
95 evensCfg.Callbacks.PeerConnReadExtensionMessage = append(
96 evensCfg.Callbacks.PeerConnReadExtensionMessage,
97 countHandler(c, &wg, "evens", 0, testRepliesToEvensExtensionName, testRepliesToOddsExtensionName, 100))
98 evensCfg.Callbacks.PeerConnAdded = append(evensCfg.Callbacks.PeerConnAdded, func(conn *PeerConn) {
99 conn.LocalLtepProtocolMap.AddUserProtocol(testRepliesToEvensExtensionName)
100 c.Assert(conn.LocalLtepProtocolMap.Index[conn.LocalLtepProtocolMap.NumBuiltin:], qt.HasLen, 1)
104 oddsCfg.Callbacks.PeerConnAdded = append(oddsCfg.Callbacks.PeerConnAdded, func(conn *PeerConn) {
105 conn.LocalLtepProtocolMap.AddUserProtocol(testRepliesToOddsExtensionName)
106 c.Assert(conn.LocalLtepProtocolMap.Index[conn.LocalLtepProtocolMap.NumBuiltin:], qt.HasLen, 1)
108 oddsCfg.Callbacks.PeerConnReadExtensionMessage = append(
109 oddsCfg.Callbacks.PeerConnReadExtensionMessage,
110 countHandler(c, &wg, "odds", 1, testRepliesToOddsExtensionName, testRepliesToEvensExtensionName, 100))
112 cl1, err := NewClient(oddsCfg)
113 c.Assert(err, qt.IsNil)
115 cl2, err := NewClient(evensCfg)
116 c.Assert(err, qt.IsNil)
118 addOpts := AddTorrentOpts{}
119 t1, _ := cl1.AddTorrentOpt(addOpts)
120 t2, _ := cl2.AddTorrentOpt(addOpts)
121 defer testutil.ExportStatusWriter(cl1, "cl1", t)()
122 defer testutil.ExportStatusWriter(cl2, "cl2", t)()
123 // Expect one PeerConn to see the value.
125 added := t1.AddClientPeer(cl2)
126 // Ensure some addresses for the other client were added.
127 c.Assert(added, qt.Not(qt.Equals), 0)