11 "github.com/anacrolix/dht/v2/krpc"
12 "github.com/anacrolix/missinggo"
23 conns map[int64]struct{}
24 t map[[20]byte]torrent
27 func marshal(parts ...interface{}) (ret []byte, err error) {
29 for _, p := range parts {
30 err = binary.Write(&buf, binary.BigEndian, p)
39 func (s *server) respond(addr net.Addr, rh ResponseHeader, parts ...interface{}) (err error) {
40 b, err := marshal(append([]interface{}{rh}, parts...)...)
44 _, err = s.pc.WriteTo(b, addr)
48 func (s *server) newConn() (ret int64) {
51 s.conns = make(map[int64]struct{})
53 s.conns[ret] = struct{}{}
57 func (s *server) serveOne() (err error) {
58 b := make([]byte, 0x10000)
59 n, addr, err := s.pc.ReadFrom(b)
63 r := bytes.NewReader(b[:n])
71 if h.ConnectionId != connectRequestConnectionId {
75 err = s.respond(addr, ResponseHeader{
78 }, ConnectionResponse{
83 if _, ok := s.conns[h.ConnectionId]; !ok {
84 s.respond(addr, ResponseHeader{
85 TransactionId: h.TransactionId,
87 }, []byte("not connected"))
90 var ar AnnounceRequest
91 err = readBody(r, &ar)
96 bm := func() encoding.BinaryMarshaler {
97 ip := missinggo.AddrIP(addr)
99 return krpc.CompactIPv4NodeAddrs(t.Peers)
101 return krpc.CompactIPv6NodeAddrs(t.Peers)
103 b, err = bm.MarshalBinary()
107 err = s.respond(addr, ResponseHeader{
108 TransactionId: h.TransactionId,
109 Action: ActionAnnounce,
110 }, AnnounceResponseHeader{
112 Leechers: t.Leechers,
117 err = fmt.Errorf("unhandled action: %d", h.Action)
118 s.respond(addr, ResponseHeader{
119 TransactionId: h.TransactionId,
121 }, []byte("unhandled action"))