11 "github.com/anacrolix/dht/v2/krpc"
12 "github.com/anacrolix/missinggo/v2"
14 "github.com/anacrolix/torrent/tracker/udp"
25 conns map[udp.ConnectionId]struct{}
26 t map[[20]byte]torrent
29 func marshal(parts ...interface{}) (ret []byte, err error) {
31 for _, p := range parts {
32 err = binary.Write(&buf, binary.BigEndian, p)
41 func (s *server) respond(addr net.Addr, rh udp.ResponseHeader, parts ...interface{}) (err error) {
42 b, err := marshal(append([]interface{}{rh}, parts...)...)
46 _, err = s.pc.WriteTo(b, addr)
50 func (s *server) newConn() (ret udp.ConnectionId) {
53 s.conns = make(map[udp.ConnectionId]struct{})
55 s.conns[ret] = struct{}{}
59 func (s *server) serveOne() (err error) {
60 b := make([]byte, 0x10000)
61 n, addr, err := s.pc.ReadFrom(b)
65 r := bytes.NewReader(b[:n])
66 var h udp.RequestHeader
72 case udp.ActionConnect:
73 if h.ConnectionId != udp.ConnectRequestConnectionId {
77 err = s.respond(addr, udp.ResponseHeader{
80 }, udp.ConnectionResponse{
84 case udp.ActionAnnounce:
85 if _, ok := s.conns[h.ConnectionId]; !ok {
86 s.respond(addr, udp.ResponseHeader{
87 TransactionId: h.TransactionId,
88 Action: udp.ActionError,
89 }, []byte("not connected"))
92 var ar AnnounceRequest
93 err = udp.Read(r, &ar)
98 bm := func() encoding.BinaryMarshaler {
99 ip := missinggo.AddrIP(addr)
101 return krpc.CompactIPv4NodeAddrs(t.Peers)
103 return krpc.CompactIPv6NodeAddrs(t.Peers)
105 b, err = bm.MarshalBinary()
109 err = s.respond(addr, udp.ResponseHeader{
110 TransactionId: h.TransactionId,
111 Action: udp.ActionAnnounce,
112 }, udp.AnnounceResponseHeader{
114 Leechers: t.Leechers,
119 err = fmt.Errorf("unhandled action: %d", h.Action)
120 s.respond(addr, udp.ResponseHeader{
121 TransactionId: h.TransactionId,
122 Action: udp.ActionError,
123 }, []byte("unhandled action"))