func (s *Server) handleQuery(source Addr, m krpc.Msg) { node := s.getNode(source, m.SenderID()) node.lastGotQuery = time.Now() if s.config.OnQuery != nil { propagate := s.config.OnQuery(&m, source.UDPAddr()) if !propagate { return } } // Don't respond. if s.config.Passive { return } args := m.A switch m.Q { case "ping": s.reply(source, m.T, krpc.Return{}) case "get_peers": // TODO: Extract common behaviour with find_node. targetID := args.InfoHash if len(targetID) != 20 { break } var rNodes []krpc.NodeInfo // TODO: Reply with "values" list if we have peers instead. for _, node := range s.closestGoodNodes(8, targetID) { rNodes = append(rNodes, node.NodeInfo()) } s.reply(source, m.T, krpc.Return{ Nodes: rNodes, // TODO: Generate this dynamically, and store it for the source. Token: "hi", }) case "find_node": // TODO: Extract common behaviour with get_peers. targetID := args.Target if len(targetID) != 20 { log.Printf("bad DHT query: %v", m) return } var rNodes []krpc.NodeInfo if node := s.nodeByID(targetID); node != nil { rNodes = append(rNodes, node.NodeInfo()) } else { // This will probably cause a crash for IPv6, but meh. for _, node := range s.closestGoodNodes(8, targetID) { rNodes = append(rNodes, node.NodeInfo()) } } s.reply(source, m.T, krpc.Return{ Nodes: rNodes, }) case "announce_peer": // TODO(anacrolix): Implement this lolz. // log.Print(m) case "vote": // TODO(anacrolix): Or reject, I don't think I want this. default: log.Printf("%s: not handling received query: q=%s", s, m.Q) return } }
func (s *Server) processPacket(b []byte, addr Addr) { if len(b) < 2 || b[0] != 'd' || b[len(b)-1] != 'e' { // KRPC messages are bencoded dicts. readNotKRPCDict.Add(1) return } var d krpc.Msg err := bencode.Unmarshal(b, &d) if err != nil { readUnmarshalError.Add(1) func() { if se, ok := err.(*bencode.SyntaxError); ok { // The message was truncated. if int(se.Offset) == len(b) { return } // Some messages seem to drop to nul chars abrubtly. if int(se.Offset) < len(b) && b[se.Offset] == 0 { return } // The message isn't bencode from the first. if se.Offset == 0 { return } } // if missinggo.CryHeard() { // log.Printf("%s: received bad krpc message from %s: %s: %+q", s, addr, err, b) // } }() return } s.mu.Lock() defer s.mu.Unlock() if s.closed.IsSet() { return } if d.Y == "q" { readQuery.Add(1) s.handleQuery(addr, d) return } t := s.findResponseTransaction(d.T, addr) if t == nil { //log.Printf("unexpected message: %#v", d) return } node := s.getNode(addr, d.SenderID()) node.lastGotResponse = time.Now() // TODO: Update node ID as this is an authoritative packet. go t.handleResponse(d) s.deleteTransaction(t) }