udp.go 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. package tracker
  2. import (
  3. "context"
  4. "encoding/binary"
  5. "github.com/anacrolix/generics"
  6. trHttp "github.com/anacrolix/torrent/tracker/http"
  7. "github.com/anacrolix/torrent/tracker/udp"
  8. "github.com/anacrolix/torrent/types/infohash"
  9. )
  10. type udpClient struct {
  11. cl *udp.ConnClient
  12. requestUri string
  13. }
  14. func (c *udpClient) Scrape(ctx context.Context, ihs []infohash.T) (out udp.ScrapeResponse, err error) {
  15. return c.cl.Client.Scrape(
  16. ctx,
  17. generics.SliceMap(ihs, func(from infohash.T) udp.InfoHash {
  18. return from
  19. }),
  20. )
  21. }
  22. func (c *udpClient) Close() error {
  23. return c.cl.Close()
  24. }
  25. func (c *udpClient) Announce(
  26. ctx context.Context,
  27. req AnnounceRequest,
  28. opts trHttp.AnnounceOpt,
  29. ) (res AnnounceResponse, err error) {
  30. if req.IPAddress == 0 && opts.ClientIp4 != nil {
  31. // I think we're taking bytes in big-endian order (all IPs), and writing it to a natively
  32. // ordered uint32. This will be correctly ordered when written back out by the UDP client
  33. // later. I'm ignoring the fact that IPv6 announces shouldn't have an IP address, we have a
  34. // perfectly good IPv4 address.
  35. req.IPAddress = binary.BigEndian.Uint32(opts.ClientIp4.To4())
  36. }
  37. h, nas, err := c.cl.Announce(ctx, req, udp.Options{RequestUri: c.requestUri})
  38. if err != nil {
  39. return
  40. }
  41. res.Interval = h.Interval
  42. res.Leechers = h.Leechers
  43. res.Seeders = h.Seeders
  44. for _, cp := range nas.NodeAddrs() {
  45. res.Peers = append(res.Peers, trHttp.Peer{}.FromNodeAddr(cp))
  46. }
  47. return
  48. }