diff --git a/include/opendht/network_engine.h b/include/opendht/network_engine.h index af526c5101fb0da85d69152e44dbfd8543006a20..637ed05e6f94dca4b361390d8f2b7d3e6d7a674f 100644 --- a/include/opendht/network_engine.h +++ b/include/opendht/network_engine.h @@ -477,12 +477,13 @@ private: const Blob& nodes6, const std::vector<std::shared_ptr<Value>>& st, const Blob& token); - unsigned insertClosestNode(uint8_t *nodes, unsigned numnodes, const InfoHash& id, const Node& n); + Blob bufferNodes(sa_family_t af, const InfoHash& id, std::vector<std::shared_ptr<Node>>& nodes); + std::pair<Blob, Blob> bufferNodes(sa_family_t af, const InfoHash& id, want_t want, - const std::vector<std::shared_ptr<Node>>& nodes, - const std::vector<std::shared_ptr<Node>>& nodes6); + std::vector<std::shared_ptr<Node>>& nodes, + std::vector<std::shared_ptr<Node>>& nodes6); /* answer to a listen request */ void sendListenConfirmation(const sockaddr* sa, socklen_t salen, TransId tid); /* answer to put request */ diff --git a/src/network_engine.cpp b/src/network_engine.cpp index 4c08830f5319c3bad978d69c662862e52c5408e7..49ae581291a73a728e59c79410e3d057cd046355 100644 --- a/src/network_engine.cpp +++ b/src/network_engine.cpp @@ -81,17 +81,6 @@ struct ParsedMessage { NetworkEngine::RequestAnswer::RequestAnswer(ParsedMessage&& msg) : ntoken(std::move(msg.token)), values(std::move(msg.values)), nodes4(std::move(msg.nodes4)), nodes6(std::move(msg.nodes6)) {} - -/* Called whenever we send a request to a node, increases the ping count - and, if that reaches 3, sends a ping to a new candidate. */ -/*void -NetworkEngine::pinged(Node& n) -{ - const auto& now = scheduler.time(); - if (not n.isExpired(now)) - n.requested(now); -}*/ - void NetworkEngine::tellListener(std::shared_ptr<Node> node, uint16_t rid, InfoHash hash, want_t want, Blob ntoken, std::vector<std::shared_ptr<Node>> nodes, std::vector<std::shared_ptr<Node>> nodes6, @@ -271,7 +260,7 @@ NetworkEngine::processMessage(const uint8_t *buf, size_t buflen, const sockaddr* node = cache.getNode(msg.id, from, fromlen, now, 2); req->node = node; } else - node->update(from, fromlen); + node->update(from, fromlen); onNewNode(node, 2); onReportedAddr(msg.id, (sockaddr*)&msg.addr.first, msg.addr.second); @@ -650,76 +639,54 @@ NetworkEngine::sendNodesValues(const sockaddr* sa, socklen_t salen, TransId tid, send(buffer.data(), buffer.size(), 0, sa, salen); } -unsigned -NetworkEngine::insertClosestNode(uint8_t *nodes, unsigned numnodes, const InfoHash& id, const Node& n) +Blob +NetworkEngine::bufferNodes(sa_family_t af, const InfoHash& id, std::vector<std::shared_ptr<Node>>& nodes) { - unsigned i, size; - - if (n.ss.ss_family == AF_INET) - size = HASH_LEN + sizeof(in_addr) + sizeof(in_port_t); // 26 - else if (n.ss.ss_family == AF_INET6) - size = HASH_LEN + sizeof(in6_addr) + sizeof(in_port_t); // 38 - else - return numnodes; - - for (i = 0; i < numnodes; i++) { - const InfoHash* nid = reinterpret_cast<const InfoHash*>(nodes + size * i); - if (InfoHash::cmp(n.id, *nid) == 0) - return numnodes; - if (id.xorCmp(n.id, *nid) < 0) - break; - } - - if (i >= TARGET_NODES) - return numnodes; - - if (numnodes < TARGET_NODES) - ++numnodes; - - if (i < numnodes - 1) - memmove(nodes + size * (i + 1), nodes + size * i, size * (numnodes - i - 1)); - - if (n.ss.ss_family == AF_INET) { - sockaddr_in *sin = (sockaddr_in*)&n.ss; - memcpy(nodes + size * i, n.id.data(), HASH_LEN); - memcpy(nodes + size * i + HASH_LEN, &sin->sin_addr, sizeof(in_addr)); - memcpy(nodes + size * i + HASH_LEN + sizeof(in_addr), &sin->sin_port, 2); - } - else if (n.ss.ss_family == AF_INET6) { - sockaddr_in6 *sin6 = (sockaddr_in6*)&n.ss; - memcpy(nodes + size * i, n.id.data(), HASH_LEN); - memcpy(nodes + size * i + HASH_LEN, &sin6->sin6_addr, sizeof(in6_addr)); - memcpy(nodes + size * i + HASH_LEN + sizeof(in6_addr), &sin6->sin6_port, 2); + std::sort(nodes.begin(), nodes.end(), [&](const std::shared_ptr<Node>& a, const std::shared_ptr<Node>& b){ + return id.xorCmp(a->id, b->id) < 0; + }); + size_t nnode = std::min<size_t>(TARGET_NODES, nodes.size()); + Blob bnodes; + if (af == AF_INET) { + bnodes.resize(NODE4_INFO_BUF_LEN * nnode); + const constexpr size_t size = HASH_LEN + sizeof(in_addr) + sizeof(in_port_t); // 26 + for (size_t i=0; i<nnode; i++) { + const Node& n = *nodes[i]; + sockaddr_in *sin = (sockaddr_in*)&n.ss; + auto dest = bnodes.data() + size * i; + memcpy(dest, n.id.data(), HASH_LEN); + memcpy(dest + HASH_LEN, &sin->sin_addr, sizeof(in_addr)); + memcpy(dest + HASH_LEN + sizeof(in_addr), &sin->sin_port, 2); + } + } else if (af == AF_INET6) { + bnodes.resize(NODE6_INFO_BUF_LEN * nnode); + const constexpr size_t size = HASH_LEN + sizeof(in6_addr) + sizeof(in_port_t); // 38 + for (size_t i=0; i<nnode; i++) { + const Node& n = *nodes[i]; + sockaddr_in6 *sin6 = (sockaddr_in6*)&n.ss; + auto dest = bnodes.data() + size * i; + memcpy(dest, n.id.data(), HASH_LEN); + memcpy(dest + HASH_LEN, &sin6->sin6_addr, sizeof(in6_addr)); + memcpy(dest + HASH_LEN + sizeof(in6_addr), &sin6->sin6_port, 2); + } } - - return numnodes; + return bnodes; } std::pair<Blob, Blob> NetworkEngine::bufferNodes(sa_family_t af, const InfoHash& id, want_t want, - const std::vector<std::shared_ptr<Node>>& nodes, const std::vector<std::shared_ptr<Node>>& nodes6) + std::vector<std::shared_ptr<Node>>& nodes4, std::vector<std::shared_ptr<Node>>& nodes6) { if (want < 0) want = af == AF_INET ? WANT4 : WANT6; - auto buff = [=](Blob& nodes, const InfoHash& id, const std::vector<std::shared_ptr<Node>>& closest_nodes) { - size_t numnodes = 0; - for (const auto& n : closest_nodes) - numnodes = insertClosestNode(nodes.data(), numnodes, id, *n); - return numnodes; - }; - Blob bnodes4; - if (want & WANT4) { - bnodes4.resize(NODE4_INFO_BUF_LEN * TARGET_NODES); - bnodes4.resize(NODE4_INFO_BUF_LEN * buff(bnodes4, id, nodes)); - } + if (want & WANT4) + bnodes4 = bufferNodes(AF_INET, id, nodes4); Blob bnodes6; - if (want & WANT6) { - bnodes6.resize(NODE6_INFO_BUF_LEN * TARGET_NODES); - bnodes6.resize(NODE6_INFO_BUF_LEN * buff(bnodes6, id, nodes6)); - } + if (want & WANT6) + bnodes6 = bufferNodes(AF_INET6, id, nodes6); return {std::move(bnodes4), std::move(bnodes6)}; }