]> Sergey Matveev's repositories - btrtrc.git/blob - ut-holepunching_test.go
Synchronize holepunch connect messages with existing rendezvous
[btrtrc.git] / ut-holepunching_test.go
1 package torrent
2
3 import (
4         "os"
5         "sync"
6         "testing"
7         "testing/iotest"
8
9         "github.com/anacrolix/torrent/internal/testutil"
10         qt "github.com/frankban/quicktest"
11         "github.com/stretchr/testify/assert"
12         "github.com/stretchr/testify/require"
13 )
14
15 // Check that after completing leeching, a leecher transitions to a seeding
16 // correctly. Connected in a chain like so: Seeder <-> Leecher <-> LeecherLeecher.
17 func TestHolepunchConnect(t *testing.T) {
18         greetingTempDir, mi := testutil.GreetingTestTorrent()
19         defer os.RemoveAll(greetingTempDir)
20
21         cfg := TestingConfig(t)
22         cfg.Seed = true
23         cfg.MaxAllocPeerRequestDataPerConn = 4
24         cfg.DataDir = greetingTempDir
25         cfg.DisablePEX = true
26         //cfg.Debug = true
27         cfg.AcceptPeerConnections = false
28         seeder, err := NewClient(cfg)
29         require.NoError(t, err)
30         defer seeder.Close()
31         defer testutil.ExportStatusWriter(seeder, "s", t)()
32         seederTorrent, ok, err := seeder.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
33         require.NoError(t, err)
34         assert.True(t, ok)
35         seederTorrent.VerifyData()
36
37         cfg = TestingConfig(t)
38         cfg.Seed = true
39         cfg.DataDir = t.TempDir()
40         cfg.AlwaysWantConns = true
41         // This way the leecher leecher will still try to use this peer as a relay, but won't be told
42         // about the seeder via PEX.
43         //cfg.DisablePEX = true
44         //cfg.Debug = true
45         leecher, err := NewClient(cfg)
46         require.NoError(t, err)
47         defer leecher.Close()
48         defer testutil.ExportStatusWriter(leecher, "l", t)()
49
50         cfg = TestingConfig(t)
51         cfg.Seed = false
52         cfg.DataDir = t.TempDir()
53         cfg.MaxAllocPeerRequestDataPerConn = 4
54         cfg.Debug = true
55         //cfg.DisableUTP = true
56         leecherLeecher, _ := NewClient(cfg)
57         require.NoError(t, err)
58         defer leecherLeecher.Close()
59         defer testutil.ExportStatusWriter(leecherLeecher, "ll", t)()
60         leecherGreeting, ok, err := leecher.AddTorrentSpec(func() (ret *TorrentSpec) {
61                 ret = TorrentSpecFromMetaInfo(mi)
62                 ret.ChunkSize = 2
63                 return
64         }())
65         _ = leecherGreeting
66         require.NoError(t, err)
67         assert.True(t, ok)
68         llg, ok, err := leecherLeecher.AddTorrentSpec(func() (ret *TorrentSpec) {
69                 ret = TorrentSpecFromMetaInfo(mi)
70                 ret.ChunkSize = 3
71                 return
72         }())
73         require.NoError(t, err)
74         assert.True(t, ok)
75
76         var wg sync.WaitGroup
77         wg.Add(1)
78         go func() {
79                 defer wg.Done()
80                 r := llg.NewReader()
81                 defer r.Close()
82                 qt.Check(t, iotest.TestReader(r, []byte(testutil.GreetingFileContents)), qt.IsNil)
83         }()
84         go seederTorrent.AddClientPeer(leecher)
85         waitForConns(seederTorrent)
86         go llg.AddClientPeer(leecher)
87         waitForConns(llg)
88         llg.cl.lock()
89         llg.initiateConn(PeerInfo{
90                 Addr: seeder.ListenAddrs()[0],
91         }, true, false)
92         llg.cl.unlock()
93         wg.Wait()
94 }
95
96 func waitForConns(t *Torrent) {
97         t.cl.lock()
98         defer t.cl.unlock()
99         for {
100                 for range t.conns {
101                         return
102                 }
103                 t.cl.event.Wait()
104         }
105 }