diff --git a/include/opendht/dht.h b/include/opendht/dht.h
index d11b5b895e4f56a815dcf9a6fad6cf3a18791526..676c3bbc471f9c6b6d21ee8f413c6ec26dfd7031 100644
--- a/include/opendht/dht.h
+++ b/include/opendht/dht.h
@@ -812,8 +812,8 @@ private:
     int sendPing(const sockaddr*, socklen_t, TransId tid);
     int sendPong(const sockaddr*, socklen_t, TransId tid);
 
-    int sendFindNode(const sockaddr*, socklen_t, TransId tid,
-                        const InfoHash& target, want_t want, int confirm);
+    int sendFindNode (const sockaddr*, socklen_t, TransId tid, const InfoHash& target, want_t want, int confirm);
+    int sendGetValues(const sockaddr*, socklen_t, TransId tid, const InfoHash& target, want_t want, int confirm);
 
     int sendNodesValues(const sockaddr*, socklen_t, TransId tid,
                               const uint8_t *nodes, unsigned nodes_len,
@@ -824,8 +824,6 @@ private:
                                const InfoHash& id, want_t want, const Blob& token={},
                                const std::vector<ValueStorage>& st = {});
 
-    int sendGetValues(const sockaddr*, socklen_t, TransId tid,
-                            const InfoHash& infohash, want_t want, int confirm);
 
     int sendListen(const sockaddr*, socklen_t, TransId,
                             const InfoHash&, const Blob& token, int confirm);
diff --git a/src/dht.cpp b/src/dht.cpp
index b5ded203ff849de19a9406df3f38bde5f20fb7a1..fbfe88f6e42faf458ae7a419203eef317677a2e9 100644
--- a/src/dht.cpp
+++ b/src/dht.cpp
@@ -919,7 +919,10 @@ Dht::searchSendGetValues(Search& sr, SearchNode* pn, bool update)
         print_addr(n->node->ss, n->node->sslen).c_str(),
         n->node->pinged, print_dt(now-n->getStatus.request_time));
 
-    sendGetValues((sockaddr*)&n->node->ss, n->node->sslen, TransId {TransPrefix::GET_VALUES, sr.tid}, sr.id, -1, n->node->reply_time >= now - UDP_REPLY_TIME);
+    if (sr.callbacks.empty() and sr.listeners.empty())
+        sendFindNode((sockaddr*)&n->node->ss, n->node->sslen, TransId {TransPrefix::FIND_NODE, sr.tid}, sr.id, -1, n->node->reply_time >= now - UDP_REPLY_TIME);
+    else
+        sendGetValues((sockaddr*)&n->node->ss, n->node->sslen, TransId {TransPrefix::GET_VALUES, sr.tid}, sr.id, -1, n->node->reply_time >= now - UDP_REPLY_TIME);
     n->getStatus.request_time = now;
     pinged(*n->node);
     if (n->node->pinged > 1 and not n->candidate) {
@@ -1388,6 +1391,8 @@ Dht::search(const InfoHash& id, sa_family_t af, GetCallback callback, DoneCallba
         sr->nodes.clear();
         sr->nodes.reserve(SEARCH_NODES+1);
         DHT_WARN("[search %s IPv%c] new search", id.toString().c_str(), (af == AF_INET) ? '4' : '6');
+        if (search_id == 0)
+            search_id++;
     }
 
     if (callback)
@@ -2424,7 +2429,7 @@ Dht::processMessage(const uint8_t *buf, size_t buflen, const sockaddr *from, soc
             bool gp = false;
             Search *sr = nullptr;
             std::shared_ptr<Node> n;
-            if (msg.tid.matches(TransPrefix::GET_VALUES, &ttid)) {
+            if (msg.tid.matches(TransPrefix::GET_VALUES, &ttid) or msg.tid.matches(TransPrefix::FIND_NODE, &ttid)) {
                 gp = true;
                 sr = findSearch(ttid, from->sa_family);
             }
@@ -2576,13 +2581,15 @@ Dht::processMessage(const uint8_t *buf, size_t buflen, const sockaddr *from, soc
         //DHT_DEBUG("Sending pong.");
         sendPong(from, fromlen, msg.tid);
         break;
-    case MessageType::FindNode:
+    case MessageType::FindNode: {
         in_stats.find++;
         newNode(msg.id, from, fromlen, 1);
         DHT_DEBUG("[node %s %s] got 'find' request (%d).", msg.id.toString().c_str(), print_addr(from, fromlen).c_str(), msg.want);
-        sendClosestNodes(from, fromlen, msg.tid, msg.target, msg.want);
+        Blob ntoken = makeToken(from, false);
+        sendClosestNodes(from, fromlen, msg.tid, msg.target, msg.want, ntoken);
         break;
-    case MessageType::GetValues:
+    }
+    case MessageType::GetValues: {
         in_stats.get++;
         DHT_DEBUG("[node %s %s] got 'get' request for %s.", msg.id.toString().c_str(), print_addr(from, fromlen).c_str(), msg.info_hash.toString().c_str());
         newNode(msg.id, from, fromlen, 1);
@@ -2602,6 +2609,7 @@ Dht::processMessage(const uint8_t *buf, size_t buflen, const sockaddr *from, soc
             }
         }
         break;
+    }
     case MessageType::AnnounceValue:
         in_stats.put++;
         DHT_DEBUG("[node %s %s] got 'put' request for %s.",
@@ -2988,6 +2996,36 @@ Dht::sendFindNode(const sockaddr *sa, socklen_t salen, TransId tid,
     return send(buffer.data(), buffer.size(), confirm ? 0 : MSG_CONFIRM, sa, salen);
 }
 
+int
+Dht::sendGetValues(const sockaddr *sa, socklen_t salen,
+               TransId tid, const InfoHash& infohash,
+               want_t want, int confirm)
+{
+    msgpack::sbuffer buffer;
+    msgpack::packer<msgpack::sbuffer> pk(&buffer);
+    pk.pack_map(5);
+
+    pk.pack(std::string("a"));  pk.pack_map(2 + (want>0?1:0));
+      pk.pack(std::string("id")); pk.pack(myid);
+      pk.pack(std::string("h"));  pk.pack(infohash);
+    if (want > 0) {
+      pk.pack(std::string("w"));
+      pk.pack_array(((want & WANT4)?1:0) + ((want & WANT6)?1:0));
+      if (want & WANT4) pk.pack(AF_INET);
+      if (want & WANT6) pk.pack(AF_INET6);
+    }
+
+    pk.pack(std::string("q")); pk.pack(std::string("get"));
+    pk.pack(std::string("t")); pk.pack_bin(tid.size());
+                               pk.pack_bin_body((const char*)tid.data(), tid.size());
+    pk.pack(std::string("y")); pk.pack(std::string("q"));
+    pk.pack(std::string("v")); pk.pack(my_v);
+
+    out_stats.get++;
+
+    return send(buffer.data(), buffer.size(), confirm ? 0 : MSG_CONFIRM, sa, salen);
+}
+
 void
 packToken(msgpack::packer<msgpack::sbuffer>& pk, Blob token)
 {
@@ -3149,36 +3187,6 @@ Dht::sendClosestNodes(const sockaddr *sa, socklen_t salen, TransId tid,
     }
 }
 
-int
-Dht::sendGetValues(const sockaddr *sa, socklen_t salen,
-               TransId tid, const InfoHash& infohash,
-               want_t want, int confirm)
-{
-    msgpack::sbuffer buffer;
-    msgpack::packer<msgpack::sbuffer> pk(&buffer);
-    pk.pack_map(5);
-
-    pk.pack(std::string("a"));  pk.pack_map(2 + (want>0?1:0));
-      pk.pack(std::string("id")); pk.pack(myid);
-      pk.pack(std::string("h"));  pk.pack(infohash);
-    if (want > 0) {
-      pk.pack(std::string("w"));
-      pk.pack_array(((want & WANT4)?1:0) + ((want & WANT6)?1:0));
-      if (want & WANT4) pk.pack(AF_INET);
-      if (want & WANT6) pk.pack(AF_INET6);
-    }
-
-    pk.pack(std::string("q")); pk.pack(std::string("get"));
-    pk.pack(std::string("t")); pk.pack_bin(tid.size());
-                               pk.pack_bin_body((const char*)tid.data(), tid.size());
-    pk.pack(std::string("y")); pk.pack(std::string("q"));
-    pk.pack(std::string("v")); pk.pack(my_v);
-
-    out_stats.get++;
-
-    return send(buffer.data(), buffer.size(), confirm ? 0 : MSG_CONFIRM, sa, salen);
-}
-
 int
 Dht::sendListen(const sockaddr* sa, socklen_t salen, TransId tid,
                         const InfoHash& infohash, const Blob& token, int confirm)