11 "github.com/anacrolix/dht/v2/krpc"
12 "github.com/anacrolix/missinggo/v2"
13 "github.com/anacrolix/torrent/tracker/udp"
24 conns map[int64]struct{}
25 t map[[20]byte]torrent
28 func marshal(parts ...interface{}) (ret []byte, err error) {
30 for _, p := range parts {
31 err = binary.Write(&buf, binary.BigEndian, p)
40 func (s *server) respond(addr net.Addr, rh udp.ResponseHeader, parts ...interface{}) (err error) {
41 b, err := marshal(append([]interface{}{rh}, parts...)...)
45 _, err = s.pc.WriteTo(b, addr)
49 func (s *server) newConn() (ret int64) {
52 s.conns = make(map[int64]struct{})
54 s.conns[ret] = struct{}{}
58 func (s *server) serveOne() (err error) {
59 b := make([]byte, 0x10000)
60 n, addr, err := s.pc.ReadFrom(b)
64 r := bytes.NewReader(b[:n])
65 var h udp.RequestHeader
71 case udp.ActionConnect:
72 if h.ConnectionId != udp.ConnectRequestConnectionId {
76 err = s.respond(addr, udp.ResponseHeader{
79 }, udp.ConnectionResponse{
83 case udp.ActionAnnounce:
84 if _, ok := s.conns[h.ConnectionId]; !ok {
85 s.respond(addr, udp.ResponseHeader{
86 TransactionId: h.TransactionId,
87 Action: udp.ActionError,
88 }, []byte("not connected"))
91 var ar AnnounceRequest
92 err = udp.Read(r, &ar)
97 bm := func() encoding.BinaryMarshaler {
98 ip := missinggo.AddrIP(addr)
100 return krpc.CompactIPv4NodeAddrs(t.Peers)
102 return krpc.CompactIPv6NodeAddrs(t.Peers)
104 b, err = bm.MarshalBinary()
108 err = s.respond(addr, udp.ResponseHeader{
109 TransactionId: h.TransactionId,
110 Action: udp.ActionAnnounce,
111 }, udp.AnnounceResponseHeader{
113 Leechers: t.Leechers,
118 err = fmt.Errorf("unhandled action: %d", h.Action)
119 s.respond(addr, udp.ResponseHeader{
120 TransactionId: h.TransactionId,
121 Action: udp.ActionError,
122 }, []byte("unhandled action"))