github.com/anacrolix/torrent@v1.61.0/tracker/udp/udp_test.go (about)

     1  package udp
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"crypto/rand"
     7  	"encoding/binary"
     8  	"io"
     9  	"net"
    10  	"sync"
    11  	"testing"
    12  	"time"
    13  
    14  	"github.com/anacrolix/dht/v2/krpc"
    15  	_ "github.com/anacrolix/envpprof"
    16  	"github.com/anacrolix/missinggo/v2/iter"
    17  	qt "github.com/go-quicktest/qt"
    18  	"github.com/stretchr/testify/require"
    19  )
    20  
    21  // Ensure net.IPs are stored big-endian, to match the way they're read from
    22  // the wire.
    23  func TestNetIPv4Bytes(t *testing.T) {
    24  	ip := net.IP([]byte{127, 0, 0, 1})
    25  	if ip.String() != "127.0.0.1" {
    26  		t.FailNow()
    27  	}
    28  	if string(ip) != "\x7f\x00\x00\x01" {
    29  		t.Fatal([]byte(ip))
    30  	}
    31  }
    32  
    33  func TestMarshalAnnounceResponse(t *testing.T) {
    34  	peers := krpc.CompactIPv4NodeAddrs{
    35  		{[]byte{127, 0, 0, 1}, 2},
    36  		{[]byte{255, 0, 0, 3}, 4},
    37  	}
    38  	b, err := peers.MarshalBinary()
    39  	require.NoError(t, err)
    40  	require.EqualValues(t,
    41  		"\x7f\x00\x00\x01\x00\x02\xff\x00\x00\x03\x00\x04",
    42  		b)
    43  	require.EqualValues(t, 12, binary.Size(AnnounceResponseHeader{}))
    44  }
    45  
    46  // Failure to write an entire packet to UDP is expected to given an error.
    47  func TestLongWriteUDP(t *testing.T) {
    48  	t.Parallel()
    49  	l, err := net.ListenUDP("udp4", nil)
    50  	require.NoError(t, err)
    51  	defer l.Close()
    52  	c, err := net.DialUDP("udp", nil, l.LocalAddr().(*net.UDPAddr))
    53  	if err != nil {
    54  		t.Fatal(err)
    55  	}
    56  	defer c.Close()
    57  	for msgLen := 1; ; msgLen *= 2 {
    58  		n, err := c.Write(make([]byte, msgLen))
    59  		if err != nil {
    60  			if isErrMessageTooLong(err) {
    61  				return
    62  			}
    63  			t.Fatalf("expected message too long error: %v", err)
    64  		}
    65  		if n < msgLen {
    66  			t.FailNow()
    67  		}
    68  	}
    69  }
    70  
    71  func TestShortBinaryRead(t *testing.T) {
    72  	var data ResponseHeader
    73  	err := binary.Read(bytes.NewBufferString("\x00\x00\x00\x01"), binary.BigEndian, &data)
    74  	if err != io.ErrUnexpectedEOF {
    75  		t.FailNow()
    76  	}
    77  }
    78  
    79  func TestConvertInt16ToInt(t *testing.T) {
    80  	i := 50000
    81  	if int(uint16(int16(i))) != 50000 {
    82  		t.FailNow()
    83  	}
    84  }
    85  
    86  func TestConnClientLogDispatchUnknownTransactionId(t *testing.T) {
    87  	const network = "udp"
    88  	cc, err := NewConnClient(NewConnClientOpts{
    89  		Network: network,
    90  	})
    91  	qt.Assert(t, qt.IsNil(err))
    92  	defer cc.Close()
    93  	pc, err := net.ListenPacket(network, ":0")
    94  	qt.Assert(t, qt.IsNil(err))
    95  	defer pc.Close()
    96  	ccAddr := *cc.LocalAddr().(*net.UDPAddr)
    97  	ipAddrs, err := net.DefaultResolver.LookupIPAddr(context.Background(), "localhost")
    98  	qt.Assert(t, qt.IsNil(err))
    99  	ccAddr.IP = ipAddrs[0].IP
   100  	ccAddr.Zone = ipAddrs[0].Zone
   101  	_, err = pc.WriteTo(make([]byte, 30), &ccAddr)
   102  	qt.Assert(t, qt.IsNil(err))
   103  }
   104  
   105  func TestConnectionIdMismatch(t *testing.T) {
   106  	t.Skip("Server host returns consistent connection ID in limited tests and so isn't effective.")
   107  	cl, err := NewConnClient(NewConnClientOpts{
   108  		// This host seems to return `Connection ID missmatch.\x00` every 2 minutes or so under
   109  		// heavy use.
   110  		Host: "tracker.torrent.eu.org:451",
   111  		//Host:    "tracker.opentrackr.org:1337",
   112  		Network: "udp",
   113  	})
   114  	qt.Assert(t, qt.IsNil(err))
   115  	defer cl.Close()
   116  	ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
   117  	defer cancel()
   118  	// Force every request to use a different connection ID. It's racey, but we want to get a
   119  	// different ID issued before a request can be sent with an old ID.
   120  	cl.Client.shouldReconnectOverride = func() bool { return true }
   121  	started := time.Now()
   122  	var wg sync.WaitGroup
   123  	for range iter.N(2) {
   124  		ar := AnnounceRequest{
   125  			NumWant: -1,
   126  			Event:   2,
   127  		}
   128  		rand.Read(ar.InfoHash[:])
   129  		rand.Read(ar.PeerId[:])
   130  		//spew.Dump(ar)
   131  		wg.Add(1)
   132  		go func() {
   133  			defer wg.Done()
   134  			_, _, err := cl.Announce(ctx, ar, Options{})
   135  			// I'm looking for `error response: "Connection ID missmatch.\x00"`.
   136  			t.Logf("announce error after %v: %v", time.Since(started), err)
   137  		}()
   138  	}
   139  	wg.Wait()
   140  }