func (p *DHT) FindNearestNode(findid utils.NodeID) []utils.NodeInfo { reqch := make(chan utils.NodeInfo, 100) endch := make(chan struct{}, 100) f := func(id utils.NodeID, command dhtRPCCommand) { defer func() { endch <- struct{}{} }() ret, err := p.sendAndWaitPacket(id, command) if err == nil { if _, ok := ret.command.Args["nodes"]; ok { var nodes []utils.NodeInfo ret.command.getArgs("nodes", &nodes) for _, n := range nodes { if n.ID.Digest.Cmp(p.id.Digest) != 0 { p.table.insert(n) reqch <- n } } } } } var res []utils.NodeInfo nodes := p.table.nearestNodes(findid) if len(nodes) == 0 { return res } for _, n := range nodes { reqch <- n } count := 0 requested := make(map[utils.NodeID]utils.NodeInfo) loop: for { select { case node := <-reqch: if _, ok := requested[node.ID]; !ok { requested[node.ID] = node c := p.newRPCCommand("find-node", map[string]interface{}{ "id": string(findid.Bytes()), }) go f(node.ID, c) count++ } case <-endch: count-- if count == 0 { break loop } } } for _, v := range requested { res = append(res, v) } sorter := utils.NodeInfoSorter{Nodes: res, ID: findid} sort.Sort(sorter) if len(sorter.Nodes) > p.k { return sorter.Nodes[:p.k] } return sorter.Nodes }