// 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)
+ cfg.Logger = cfg.Logger.WithContextText("seeder")
seeder, err := NewClient(cfg)
require.NoError(t, err)
defer seeder.Close()
cfg.Seed = true
cfg.DataDir = t.TempDir()
cfg.AlwaysWantConns = true
+ cfg.Logger = cfg.Logger.WithContextText("leecher")
// This way the leecher leecher will still try to use this peer as a relay, but won't be told
// about the seeder via PEX.
//cfg.DisablePEX = true
- //cfg.Debug = true
+ cfg.Debug = true
leecher, err := NewClient(cfg)
require.NoError(t, err)
defer leecher.Close()
cfg.Seed = false
cfg.DataDir = t.TempDir()
cfg.MaxAllocPeerRequestDataPerConn = 4
- //cfg.Debug = true
+ cfg.Debug = true
cfg.NominalDialTimeout = time.Second
+ cfg.Logger = cfg.Logger.WithContextText("leecher-leecher")
//cfg.DisableUTP = true
leecherLeecher, _ := NewClient(cfg)
require.NoError(t, err)
// get separate connections. This means that holepunch connect may result in an accept (and dial)
// for one or both peers involved.
func TestUtpSimultaneousOpen(t *testing.T) {
+ t.Parallel()
c := qt.New(t)
const network = "udp"
ctx := context.Background()
c.Assert(err, qt.IsNil)
return socket
}
- first := newUtpSocket("localhost:3000")
+ first := newUtpSocket("localhost:0")
defer first.Close()
- second := newUtpSocket("localhost:3001")
+ second := newUtpSocket("localhost:0")
defer second.Close()
getDial := func(sock utpSocket, addr string) func() (net.Conn, error) {
return func() (net.Conn, error) {
return sock.DialContext(ctx, network, addr)
}
}
- err := testSimultaneousOpen(
- c.Cleanup,
- getDial(first, "localhost:3001"),
- getDial(second, "localhost:3000"),
- )
- c.Assert(err, qt.ErrorIs, errMsgNotReceived)
+ t.Logf("first addr is %v. second addr is %v", first.Addr().String(), second.Addr().String())
+ for range iter.N(10) {
+ err := testSimultaneousOpen(
+ c.Cleanup,
+ getDial(first, second.Addr().String()),
+ getDial(second, first.Addr().String()),
+ )
+ if err == nil {
+ t.Fatal("expected utp to fail simultaneous open")
+ }
+ if errors.Is(err, errMsgNotReceived) {
+ return
+ }
+ skipGoUtpDialIssue(t, err)
+ t.Log(err)
+ time.Sleep(time.Second)
+ }
+ t.FailNow()
}
-func testDirectDialMsg(c *qt.C, r, w net.Conn) {
+func writeAndReadMsg(r, w net.Conn) error {
go writeMsg(w)
- err := readMsg(r)
- c.Assert(err, qt.IsNil)
+ return readMsg(r)
+}
+
+func skipGoUtpDialIssue(t *testing.T, err error) {
+ if err.Error() == "timed out waiting for ack" {
+ t.Skip("anacrolix go utp implementation has issues. Use anacrolix/go-libutp by enabling CGO.")
+ }
}
// Show that dialling one socket and accepting from the other results in them having ends of the
// same connection.
func TestUtpDirectDialMsg(t *testing.T) {
+ t.Parallel()
c := qt.New(t)
- const network = "udp"
+ const network = "udp4"
ctx := context.Background()
newUtpSocket := func(addr string) utpSocket {
socket, err := NewUtpSocket(network, addr, func(net.Addr) bool {
c.Assert(err, qt.IsNil)
return socket
}
- first := newUtpSocket("localhost:0")
- defer first.Close()
- second := newUtpSocket("localhost:0")
- defer second.Close()
- writer, err := first.DialContext(ctx, network, second.Addr().String())
- c.Assert(err, qt.IsNil)
- defer writer.Close()
- reader, err := second.Accept()
- defer reader.Close()
- c.Assert(err, qt.IsNil)
- testDirectDialMsg(c, reader, writer)
+ for range iter.N(10) {
+ err := func() error {
+ first := newUtpSocket("localhost:0")
+ defer first.Close()
+ second := newUtpSocket("localhost:0")
+ defer second.Close()
+ writer, err := first.DialContext(ctx, network, second.Addr().String())
+ if err != nil {
+ return err
+ }
+ defer writer.Close()
+ reader, err := second.Accept()
+ defer reader.Close()
+ c.Assert(err, qt.IsNil)
+ return writeAndReadMsg(reader, writer)
+ }()
+ if err == nil {
+ return
+ }
+ skipGoUtpDialIssue(t, err)
+ t.Log(err)
+ time.Sleep(time.Second)
+ }
+ t.FailNow()
}