From 0db9f243880ff1dc4c7f3703eec15c0a3e4d829c Mon Sep 17 00:00:00 2001
From: Adrien Beraud <adreien.beraud@savoirfairelinux.com>
Date: Thu, 30 May 2024 16:05:21 -0400
Subject: [PATCH] dht: add support to behave as a client node

---
 include/opendht/callbacks.h      |  3 ++
 include/opendht/network_engine.h |  1 +
 src/dht.cpp                      |  1 +
 src/network_engine.cpp           | 77 +++++++++++++++++++++++++-------
 4 files changed, 66 insertions(+), 16 deletions(-)

diff --git a/include/opendht/callbacks.h b/include/opendht/callbacks.h
index 829b7876..556f0de9 100644
--- a/include/opendht/callbacks.h
+++ b/include/opendht/callbacks.h
@@ -143,6 +143,9 @@ struct OPENDHT_PUBLIC Config {
      *   - Larger listen refresh time
      */
     bool public_stable {false};
+
+    /* Client mode, node will not be used by other nodes to store data. */
+    bool client_mode {false};
 };
 
 /**
diff --git a/include/opendht/network_engine.h b/include/opendht/network_engine.h
index 5b584b25..3d7f3280 100644
--- a/include/opendht/network_engine.h
+++ b/include/opendht/network_engine.h
@@ -52,6 +52,7 @@ struct NetworkConfig {
     NetId network {0};
     ssize_t max_req_per_sec {0};
     ssize_t max_peer_req_per_sec {0};
+    bool is_client {false};
 };
 
 class DhtProtocolException : public DhtException {
diff --git a/src/dht.cpp b/src/dht.cpp
index f30abb7b..f969de94 100644
--- a/src/dht.cpp
+++ b/src/dht.cpp
@@ -1812,6 +1812,7 @@ fromDhtConfig(const Config& config)
     netConf.max_peer_req_per_sec = config.max_peer_req_per_sec
         ? config.max_peer_req_per_sec
         : netConf.max_req_per_sec/8;
+    netConf.is_client = config.client_mode;
     return netConf;
 }
 
diff --git a/src/network_engine.cpp b/src/network_engine.cpp
index 54b9d6b9..d36a01e7 100644
--- a/src/network_engine.cpp
+++ b/src/network_engine.cpp
@@ -143,7 +143,7 @@ NetworkEngine::tellListenerRefreshed(const Sp<Node>& n, Tid socket_id, const Inf
     msgpack::sbuffer buffer;
     msgpack::packer<msgpack::sbuffer> pk(&buffer);
 
-    pk.pack_map(4 + (version >= 1 ? 1 : 0) + (config.network?1:0));
+    pk.pack_map(4 + (version >= 1 ? 1 : 0) + (config.network?1:0)+(config.is_client?1:0));
 
     pk.pack(version >= 1 ? KEY_A : KEY_U);
         pk.pack_map(1 + (version >= 1 ? 1 : 0) + (not values.empty()?1:0) + (not token.empty()?1:0));
@@ -166,6 +166,9 @@ NetworkEngine::tellListenerRefreshed(const Sp<Node>& n, Tid socket_id, const Inf
     if (config.network) {
         pk.pack(KEY_NETID); pk.pack(config.network);
     }
+    if (config.is_client) {
+        pk.pack(KEY_ISCLIENT); pk.pack(config.is_client);
+    }
 
     if (version >= 1) {
         Tid tid (n->getNewTid());
@@ -194,7 +197,7 @@ NetworkEngine::tellListenerExpired(const Sp<Node>& n, Tid socket_id, const InfoH
     msgpack::sbuffer buffer;
     msgpack::packer<msgpack::sbuffer> pk(&buffer);
 
-    pk.pack_map(4 + (version >= 1 ? 1 : 0) + (config.network?1:0));
+    pk.pack_map(4 + (version >= 1 ? 1 : 0) + (config.network?1:0)+(config.is_client?1:0));
 
     pk.pack(version >= 1 ? KEY_A : KEY_U);
         pk.pack_map(1 + (version >= 1 ? 1 : 0) + (not values.empty()?1:0) + (not token.empty()?1:0));
@@ -217,6 +220,9 @@ NetworkEngine::tellListenerExpired(const Sp<Node>& n, Tid socket_id, const InfoH
     if (config.network) {
         pk.pack(KEY_NETID); pk.pack(config.network);
     }
+    if (config.is_client) {
+        pk.pack(KEY_ISCLIENT); pk.pack(config.is_client);
+    }
 
     if (version >= 1) {
         Tid tid (n->getNewTid());
@@ -704,7 +710,7 @@ NetworkEngine::sendPing(const Sp<Node>& node, RequestCb&& on_done, RequestExpire
     Tid tid (node->getNewTid());
     msgpack::sbuffer buffer;
     msgpack::packer<msgpack::sbuffer> pk(&buffer);
-    pk.pack_map(5+(config.network?1:0));
+    pk.pack_map(5+(config.network?1:0)+(config.is_client?1:0));
 
     pk.pack(KEY_A); pk.pack_map(1);
      pk.pack(KEY_REQ_ID); pk.pack(myid);
@@ -716,6 +722,9 @@ NetworkEngine::sendPing(const Sp<Node>& node, RequestCb&& on_done, RequestExpire
     if (config.network) {
         pk.pack(KEY_NETID); pk.pack(config.network);
     }
+    if (config.is_client) {
+        pk.pack(KEY_ISCLIENT); pk.pack(config.is_client);
+    }
 
     auto req = std::make_shared<Request>(MessageType::Ping, tid, node,
         Blob(buffer.data(), buffer.data() + buffer.size()),
@@ -741,7 +750,7 @@ void
 NetworkEngine::sendPong(const SockAddr& addr, Tid tid) {
     msgpack::sbuffer buffer;
     msgpack::packer<msgpack::sbuffer> pk(&buffer);
-    pk.pack_map(4+(config.network?1:0));
+    pk.pack_map(4+(config.network?1:0)+(config.is_client?1:0));
 
     pk.pack(KEY_R); pk.pack_map(2);
       pk.pack(KEY_REQ_ID); pk.pack(myid);
@@ -753,6 +762,9 @@ NetworkEngine::sendPong(const SockAddr& addr, Tid tid) {
     if (config.network) {
         pk.pack(KEY_NETID); pk.pack(config.network);
     }
+    if (config.is_client) {
+        pk.pack(KEY_ISCLIENT); pk.pack(config.is_client);
+    }
 
     send(addr, buffer.data(), buffer.size());
 }
@@ -763,7 +775,7 @@ NetworkEngine::sendFindNode(const Sp<Node>& n, const InfoHash& target, want_t wa
     Tid tid (n->getNewTid());
     msgpack::sbuffer buffer;
     msgpack::packer<msgpack::sbuffer> pk(&buffer);
-    pk.pack_map(5+(config.network?1:0));
+    pk.pack_map(5+(config.network?1:0)+(config.is_client?1:0));
 
     pk.pack(KEY_A); pk.pack_map(2 + (want>0?1:0));
       pk.pack(KEY_REQ_ID);     pk.pack(myid);
@@ -782,6 +794,9 @@ NetworkEngine::sendFindNode(const Sp<Node>& n, const InfoHash& target, want_t wa
     if (config.network) {
         pk.pack(KEY_NETID); pk.pack(config.network);
     }
+    if (config.is_client) {
+        pk.pack(KEY_ISCLIENT); pk.pack(config.is_client);
+    }
 
     auto req = std::make_shared<Request>(MessageType::FindNode, tid, n,
         Blob(buffer.data(), buffer.data() + buffer.size()),
@@ -808,7 +823,7 @@ NetworkEngine::sendGetValues(const Sp<Node>& n, const InfoHash& info_hash, const
     Tid tid (n->getNewTid());
     msgpack::sbuffer buffer;
     msgpack::packer<msgpack::sbuffer> pk(&buffer);
-    pk.pack_map(5+(config.network?1:0));
+    pk.pack_map(5+(config.network?1:0)+(config.is_client?1:0));
 
     unsigned sendQuery = (not query.where.empty() or not query.select.empty()) ? 1 : 0;
     unsigned sendWant = (want > 0) ? 1 : 0;
@@ -835,7 +850,10 @@ NetworkEngine::sendGetValues(const Sp<Node>& n, const InfoHash& info_hash, const
     if (config.network) {
         pk.pack(KEY_NETID); pk.pack(config.network);
     }
-
+    if (config.is_client) {
+        pk.pack(KEY_ISCLIENT); pk.pack(config.is_client);
+    }
+    
     auto req = std::make_shared<Request>(MessageType::GetValues, tid, n,
         Blob(buffer.data(), buffer.data() + buffer.size()),
         [=](const Request& req_status, ParsedMessage&& msg) { /* on done */
@@ -952,10 +970,13 @@ NetworkEngine::sendValueParts(Tid tid, const std::vector<Blob>& svals, const Soc
             end = std::min(start + MTU, v.size());
             buffer.clear();
             msgpack::packer<msgpack::sbuffer> pk(&buffer);
-            pk.pack_map(3+(config.network?1:0));
+            pk.pack_map(3+(config.network?1:0)+(config.is_client?1:0));
             if (config.network) {
                 pk.pack(KEY_NETID); pk.pack(config.network);
             }
+            if (config.is_client) {
+                pk.pack(KEY_ISCLIENT); pk.pack(config.is_client);
+            }
             pk.pack(KEY_Y); pk.pack(KEY_V);
             pk.pack(KEY_TID); pk.pack(tid);
             pk.pack(KEY_V); pk.pack_map(1);
@@ -976,7 +997,7 @@ NetworkEngine::sendNodesValues(const SockAddr& addr, Tid tid, const Blob& nodes,
 {
     msgpack::sbuffer buffer;
     msgpack::packer<msgpack::sbuffer> pk(&buffer);
-    pk.pack_map(4+(config.network?1:0));
+    pk.pack_map(4+(config.network?1:0)+(config.is_client?1:0));
 
     pk.pack(KEY_R);
     pk.pack_map(2 + (not st.empty()?1:0) + (nodes.size()>0?1:0) + (nodes6.size()>0?1:0) + (not token.empty()?1:0));
@@ -1018,6 +1039,9 @@ NetworkEngine::sendNodesValues(const SockAddr& addr, Tid tid, const Blob& nodes,
     if (config.network) {
         pk.pack(KEY_NETID); pk.pack(config.network);
     }
+    if (config.is_client) {
+        pk.pack(KEY_ISCLIENT); pk.pack(config.is_client);
+    }
 
     // send response
     send(addr, buffer.data(), buffer.size());
@@ -1089,7 +1113,7 @@ NetworkEngine::sendListen(const Sp<Node>& n,
     Tid tid (n->getNewTid());
     msgpack::sbuffer buffer;
     msgpack::packer<msgpack::sbuffer> pk(&buffer);
-    pk.pack_map(5+(config.network?1:0));
+    pk.pack_map(5+(config.network?1:0)+(config.is_client?1:0));
 
     auto has_query = not query.where.empty() or not query.select.empty();
     pk.pack(KEY_A); pk.pack_map(5 + has_query);
@@ -1109,6 +1133,9 @@ NetworkEngine::sendListen(const Sp<Node>& n,
     if (config.network) {
         pk.pack(KEY_NETID); pk.pack(config.network);
     }
+    if (config.is_client) {
+        pk.pack(KEY_ISCLIENT); pk.pack(config.is_client);
+    }
 
     auto req = std::make_shared<Request>(MessageType::Listen, tid, n,
         Blob(buffer.data(), buffer.data() + buffer.size()),
@@ -1130,7 +1157,7 @@ void
 NetworkEngine::sendListenConfirmation(const SockAddr& addr, Tid tid) {
     msgpack::sbuffer buffer;
     msgpack::packer<msgpack::sbuffer> pk(&buffer);
-    pk.pack_map(4+(config.network?1:0));
+    pk.pack_map(4+(config.network?1:0)+(config.is_client?1:0));
 
     pk.pack(KEY_R); pk.pack_map(2);
       pk.pack(KEY_REQ_ID); pk.pack(myid);
@@ -1142,6 +1169,9 @@ NetworkEngine::sendListenConfirmation(const SockAddr& addr, Tid tid) {
     if (config.network) {
         pk.pack(KEY_NETID); pk.pack(config.network);
     }
+    if (config.is_client) {
+        pk.pack(KEY_ISCLIENT); pk.pack(config.is_client);
+    }
 
     send(addr, buffer.data(), buffer.size());
 }
@@ -1158,7 +1188,7 @@ NetworkEngine::sendAnnounceValue(const Sp<Node>& n,
     Tid tid (n->getNewTid());
     msgpack::sbuffer buffer;
     msgpack::packer<msgpack::sbuffer> pk(&buffer);
-    pk.pack_map(5+(config.network?1:0));
+    pk.pack_map(5+(config.network?1:0)+(config.is_client?1:0));
 
     bool add_created = created < scheduler.time();
     pk.pack(KEY_A); pk.pack_map(add_created ? 5 : 4);
@@ -1178,6 +1208,9 @@ NetworkEngine::sendAnnounceValue(const Sp<Node>& n,
     if (config.network) {
         pk.pack(KEY_NETID); pk.pack(config.network);
     }
+    if (config.is_client) {
+        pk.pack(KEY_ISCLIENT); pk.pack(config.is_client);
+    }
 
     auto req = std::make_shared<Request>(MessageType::AnnounceValue, tid, n,
         Blob(buffer.data(), buffer.data() + buffer.size()),
@@ -1244,7 +1277,7 @@ NetworkEngine::sendUpdateValues(const Sp<Node>& n,
 
     msgpack::sbuffer buffer;
     msgpack::packer<msgpack::sbuffer> pk(&buffer);
-    pk.pack_map(5+(config.network?1:0));
+    pk.pack_map(5+(config.network?1:0)+(config.is_client?1:0));
 
     pk.pack(KEY_A); pk.pack_map((created < scheduler.time() ? 7 : 6));
       pk.pack(KEY_REQ_ID);     pk.pack(myid);
@@ -1265,6 +1298,9 @@ NetworkEngine::sendUpdateValues(const Sp<Node>& n,
     if (config.network) {
         pk.pack(KEY_NETID); pk.pack(config.network);
     }
+    if (config.is_client) {
+        pk.pack(KEY_ISCLIENT); pk.pack(config.is_client);
+    }
 
     auto req = std::make_shared<Request>(MessageType::UpdateValue, tid, n,
         Blob(buffer.data(), buffer.data() + buffer.size()),
@@ -1289,7 +1325,7 @@ NetworkEngine::sendRefreshValue(const Sp<Node>& n,
     Tid tid (n->getNewTid());
     msgpack::sbuffer buffer;
     msgpack::packer<msgpack::sbuffer> pk(&buffer);
-    pk.pack_map(5+(config.network?1:0));
+    pk.pack_map(5+(config.network?1:0)+(config.is_client?1:0));
 
     pk.pack(KEY_A); pk.pack_map(4);
       pk.pack(KEY_REQ_ID);       pk.pack(myid);
@@ -1304,6 +1340,9 @@ NetworkEngine::sendRefreshValue(const Sp<Node>& n,
     if (config.network) {
         pk.pack(KEY_NETID); pk.pack(config.network);
     }
+    if (config.is_client) {
+        pk.pack(KEY_ISCLIENT); pk.pack(config.is_client);
+    }
 
     auto req = std::make_shared<Request>(MessageType::Refresh, tid, n,
         Blob(buffer.data(), buffer.data() + buffer.size()),
@@ -1335,7 +1374,7 @@ void
 NetworkEngine::sendValueAnnounced(const SockAddr& addr, Tid tid, Value::Id vid) {
     msgpack::sbuffer buffer;
     msgpack::packer<msgpack::sbuffer> pk(&buffer);
-    pk.pack_map(4+(config.network?1:0));
+    pk.pack_map(4+(config.network?1:0)+(config.is_client?1:0));
 
     pk.pack(KEY_R); pk.pack_map(3);
       pk.pack(KEY_REQ_ID);  pk.pack(myid);
@@ -1348,6 +1387,9 @@ NetworkEngine::sendValueAnnounced(const SockAddr& addr, Tid tid, Value::Id vid)
     if (config.network) {
         pk.pack(KEY_NETID); pk.pack(config.network);
     }
+    if (config.is_client) {
+        pk.pack(KEY_ISCLIENT); pk.pack(config.is_client);
+    }
 
     send(addr, buffer.data(), buffer.size());
 }
@@ -1361,7 +1403,7 @@ NetworkEngine::sendError(const SockAddr& addr,
 {
     msgpack::sbuffer buffer;
     msgpack::packer<msgpack::sbuffer> pk(&buffer);
-    pk.pack_map(4 + (include_id?1:0) + (config.network?1:0));
+    pk.pack_map(4 + (include_id?1:0) + (config.network?1:0)+(config.is_client?1:0));
 
     pk.pack(KEY_E); pk.pack_array(2);
       pk.pack(code);
@@ -1378,6 +1420,9 @@ NetworkEngine::sendError(const SockAddr& addr,
     if (config.network) {
         pk.pack(KEY_NETID); pk.pack(config.network);
     }
+    if (config.is_client) {
+        pk.pack(KEY_ISCLIENT); pk.pack(config.is_client);
+    }
 
     send(addr, buffer.data(), buffer.size());
 }
-- 
GitLab