Ring Daemon 16.0.0
Loading...
Searching...
No Matches
routing_table.h
Go to the documentation of this file.
1/*
2 * Copyright (C) 2004-2025 Savoir-faire Linux Inc.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17#pragma once
18
19#include "manager.h"
20
21#include <dhtnet/multiplexed_socket.h>
22
23#include <opendht/infohash.h>
24
25#include <asio.hpp>
26#include <asio/detail/deadline_timer_service.hpp>
27
28#include <vector>
29#include <memory>
30#include <list>
31#include <set>
32#include <algorithm>
33
34using NodeId = dht::PkId;
35
36namespace jami {
37
38static constexpr const std::chrono::minutes FIND_PERIOD {10};
39
41{
42 bool isMobile_ {false};
43 std::shared_ptr<dhtnet::ChannelSocketInterface> socket {};
45 NodeInfo() = delete;
46 NodeInfo(NodeInfo&&) = default;
47 NodeInfo(std::shared_ptr<dhtnet::ChannelSocketInterface> socket_)
48 : socket(socket_)
49 {}
50 NodeInfo(bool mobile, std::shared_ptr<dhtnet::ChannelSocketInterface> socket_)
52 , socket(socket_)
53 {}
54};
55
56class Bucket
57
58{
59public:
60 static constexpr int BUCKET_MAX_SIZE = 2;
61
62 Bucket() = delete;
63 Bucket(const Bucket&) = delete;
64 Bucket(const NodeId&);
65
71 bool addNode(const std::shared_ptr<dhtnet::ChannelSocketInterface>& socket);
72
78 bool addNode(NodeInfo&& info);
79
86 bool removeNode(const NodeId& nodeId);
87
92 std::map<NodeId, NodeInfo>& getNodes() { return nodes; }
93
98 std::set<NodeId> getNodeIds() const;
99
105 bool hasNode(const NodeId& nodeId) const;
106
112 bool addKnownNode(const NodeId& nodeId);
113
118 void removeKnownNode(const NodeId& nodeId) { known_nodes.erase(nodeId); }
119
124 const std::set<NodeId>& getKnownNodes() const { return known_nodes; }
125
131 NodeId getKnownNode(unsigned index) const;
132
138 bool hasKnownNode(const NodeId& nodeId) const
139 {
140 return known_nodes.find(nodeId) != known_nodes.end();
141 }
142
148 bool addMobileNode(const NodeId& nodeId);
149
154 void removeMobileNode(const NodeId& nodeId) { mobile_nodes.erase(nodeId); }
155
161 bool hasMobileNode(const NodeId& nodeId)
162 {
163 return mobile_nodes.find(nodeId) != mobile_nodes.end();
164 }
165
170 const std::set<NodeId>& getMobileNodes() const { return mobile_nodes; }
171
178 bool addConnectingNode(const NodeId& nodeId);
179
184 void removeConnectingNode(const NodeId& nodeId) { connecting_nodes.erase(nodeId); }
185
189 const std::set<NodeId>& getConnectingNodes() const { return connecting_nodes; };
190
196 bool hasConnectingNode(const NodeId& nodeId) const
197 {
198 return connecting_nodes.find(nodeId) != connecting_nodes.end();
199 }
200
201 bool isEmpty() const { return nodes.empty(); }
202
207 bool isFull() const { return nodes.size() == BUCKET_MAX_SIZE; };
208
215 std::set<NodeId> getKnownNodesRandom(unsigned numberNodes, std::mt19937_64& rd) const;
216
222 NodeId randomId(std::mt19937_64& rd) const
223 {
224 auto node = getKnownNodesRandom(1, rd);
225 return *node.begin();
226 }
227
233 asio::steady_timer& getNodeTimer(const std::shared_ptr<dhtnet::ChannelSocketInterface>& socket);
234
241 bool shutdownNode(const NodeId& nodeId);
242
246 void shutdownAllNodes();
247
251 void printBucket(unsigned number) const;
252
256 void changeMobility(const NodeId& nodeId, bool isMobile);
257
262 unsigned getNodesSize() const { return nodes.size(); }
263
268 unsigned getKnownNodesSize() const { return known_nodes.size(); }
269
274 unsigned getConnectingNodesSize() const { return connecting_nodes.size(); }
275
280 NodeId getLowerLimit() const { return lowerLimit_; };
281
286 void setLowerLimit(const NodeId& nodeId) { lowerLimit_ = nodeId; }
287
288 // For tests
289
294 std::set<std::shared_ptr<dhtnet::ChannelSocketInterface>> getNodeSockets() const;
295
296private:
297 NodeId lowerLimit_;
298 std::map<NodeId, NodeInfo> nodes;
299 std::set<NodeId> known_nodes;
300 std::set<NodeId> connecting_nodes;
301 std::set<NodeId> mobile_nodes;
302 mutable std::mutex mutex;
303};
304
305// ####################################################################################################
306
308{
309public:
310 RoutingTable();
311
317 bool addNode(const std::shared_ptr<dhtnet::ChannelSocketInterface>& socket);
318
325 bool addNode(const std::shared_ptr<dhtnet::ChannelSocketInterface>& channel,
326 std::list<Bucket>::iterator& bucket);
327
334 bool removeNode(const NodeId& nodeId);
335
341 bool hasNode(const NodeId& nodeId);
342
348 bool addKnownNode(const NodeId& nodeId);
349
355 bool hasKnownNode(const NodeId& nodeId) const
356 {
357 auto bucket = findBucket(nodeId);
358 return bucket->hasKnownNode(nodeId);
359 }
360
366 bool addMobileNode(const NodeId& nodeId);
367
373 void removeMobileNode(const NodeId& nodeId);
374
380 bool hasMobileNode(const NodeId& nodeId);
381
387 bool addConnectingNode(const NodeId& nodeId);
388
394 void removeConnectingNode(const NodeId& nodeId);
395
401 bool hasConnectingNode(const NodeId& nodeId) const
402 {
403 auto bucket = findBucket(nodeId);
404 return bucket->hasConnectingNode(nodeId);
405 }
406
412 std::list<Bucket>::iterator findBucket(const NodeId& nodeId);
413
419 inline const std::list<Bucket>::const_iterator findBucket(const NodeId& nodeId) const
420 {
421 return std::list<Bucket>::const_iterator(
422 const_cast<RoutingTable*>(this)->findBucket(nodeId));
423 }
424
431 std::vector<NodeId> closestNodes(const NodeId& nodeId, unsigned count);
432
437 unsigned getRoutingTableSize() const { return buckets.size(); }
438
444 {
445 size_t count = 0;
446 for (const auto& b : buckets)
447 count += b.getNodesSize();
448 return count;
449 }
450
454 void printRoutingTable() const;
455
460 void shutdownNode(const NodeId& nodeId);
461
466 {
467 for (auto& bucket : buckets)
468 bucket.shutdownAllNodes();
469 }
470
475 void setId(const NodeId& node) { id_ = node; }
476
481 NodeId getId() const { return id_; }
482
487 std::list<Bucket>& getBuckets() { return buckets; }
488
493 std::vector<NodeId> getNodes() const;
494
499 std::vector<NodeId> getKnownNodes() const;
500
505 std::vector<NodeId> getMobileNodes() const;
506
511 std::vector<NodeId> getConnectingNodes() const;
512
517 std::vector<NodeId> getBucketMobileNodes() const;
518
525 bool contains(const std::list<Bucket>::iterator& it, const NodeId& nodeId) const;
526
530 std::vector<NodeId> getAllNodes() const;
531
535 void deleteNode(const NodeId& nodeId);
536
537private:
538 RoutingTable(const RoutingTable&) = delete;
539 RoutingTable& operator=(const RoutingTable&) = delete;
540
546 NodeId middle(std::list<Bucket>::iterator& it) const;
547
553 unsigned depth(std::list<Bucket>::iterator& bucket) const;
554
560 bool split(std::list<Bucket>::iterator& bucket);
561
562 NodeId id_;
563
564 std::list<Bucket> buckets;
565
566 mutable std::mutex mutex_;
567};
568}; // namespace jami
void setLowerLimit(const NodeId &nodeId)
Set bucket's lower limit.
void shutdownAllNodes()
Shutdowns all sockets in nodes through shutdownNode.
unsigned getNodesSize() const
Returns number of nodes in bucket.
bool addNode(const std::shared_ptr< dhtnet::ChannelSocketInterface > &socket)
Add Node socket to bucket.
bool removeNode(const NodeId &nodeId)
Remove NodeId socket from bucket and insert it in known_nodes or mobile_nodes depending on its type.
void removeMobileNode(const NodeId &nodeId)
Remove NodeId from mobile_nodes.
const std::set< NodeId > & getMobileNodes() const
Get NodeIds from mobile_nodes.
Bucket()=delete
bool shutdownNode(const NodeId &nodeId)
Shutdowns socket and removes it from nodes.
unsigned getKnownNodesSize() const
Returns number of knwon_nodes in bucket.
NodeId getLowerLimit() const
Returns bucket lower limit.
NodeId randomId(std::mt19937_64 &rd) const
Returns random NodeId from known_nodes.
Bucket(const Bucket &)=delete
bool addMobileNode(const NodeId &nodeId)
Add NodeId to mobile_nodes if it doesn't exist in nodes.
void removeConnectingNode(const NodeId &nodeId)
Remove NodeId from connecting_nodes.
const std::set< NodeId > & getConnectingNodes() const
Get NodeIds of connecting_nodes.
bool hasNode(const NodeId &nodeId) const
Test if socket exists in nodes.
std::set< NodeId > getNodeIds() const
Get NodeIds from bucket.
static constexpr int BUCKET_MAX_SIZE
bool hasKnownNode(const NodeId &nodeId) const
Test if NodeId exist in known_nodes.
bool addConnectingNode(const NodeId &nodeId)
Add NodeId to connecting_nodes if it doesn't exist in nodes.
bool hasMobileNode(const NodeId &nodeId)
Test if NodeId exist in mobile_nodes.
NodeId getKnownNode(unsigned index) const
Returns NodeId from known_nodes at index.
void printBucket(unsigned number) const
Prints bucket and bucket's number.
bool addKnownNode(const NodeId &nodeId)
Add NodeId to known_nodes if it doesn't exist in nodes.
bool isFull() const
Indicate if bucket is full.
std::set< std::shared_ptr< dhtnet::ChannelSocketInterface > > getNodeSockets() const
Get sockets from bucket.
std::map< NodeId, NodeInfo > & getNodes()
Get connected nodes from bucket.
bool hasConnectingNode(const NodeId &nodeId) const
Test if NodeId exist in connecting_nodes.
asio::steady_timer & getNodeTimer(const std::shared_ptr< dhtnet::ChannelSocketInterface > &socket)
Returns socket's timer.
const std::set< NodeId > & getKnownNodes() const
Get NodeIds from known_nodes.
bool isEmpty() const
unsigned getConnectingNodesSize() const
Returns number of mobile_nodes in bucket.
std::set< NodeId > getKnownNodesRandom(unsigned numberNodes, std::mt19937_64 &rd) const
Returns random numberNodes NodeId from known_nodes.
void changeMobility(const NodeId &nodeId, bool isMobile)
Change mobility of specific node, mobile or not.
void removeKnownNode(const NodeId &nodeId)
Remove NodeId from known_nodes.
static LIBJAMI_TEST_EXPORT Manager & instance()
Definition manager.cpp:676
std::shared_ptr< asio::io_context > ioContext() const
Definition manager.cpp:1712
bool hasMobileNode(const NodeId &nodeId)
Check if mobile node exists in routing table.
std::vector< NodeId > getAllNodes() const
Return every node from each bucket.
std::vector< NodeId > getConnectingNodes() const
Returns all routing table's connecting nodes.
void deleteNode(const NodeId &nodeId)
Delete node from every table in bucket.
bool addKnownNode(const NodeId &nodeId)
Add known node to routing table.
std::vector< NodeId > closestNodes(const NodeId &nodeId, unsigned count)
Returns the count closest nodes to a specific nodeId.
std::vector< NodeId > getBucketMobileNodes() const
Returns mobile nodes corresponding to the swarm's id.
void shutdownAllNodes()
Shutdowns all nodes in routing table and add them to known_nodes or mobile_nodes.
void shutdownNode(const NodeId &nodeId)
Shutdowns a node.
unsigned getRoutingTableNodeCount() const
Returns number of total nodes in routing table.
bool addMobileNode(const NodeId &nodeId)
Add mobile node to routing table.
std::list< Bucket >::iterator findBucket(const NodeId &nodeId)
Returns bucket iterator containing nodeId.
std::vector< NodeId > getMobileNodes() const
Returns all routing table's mobile nodes.
bool hasKnownNode(const NodeId &nodeId) const
Checks if known node exists in routing table.
bool removeNode(const NodeId &nodeId)
Removes node from routing table Adds it to known_nodes or mobile_nodes depending on mobility.
void removeConnectingNode(const NodeId &nodeId)
Remove connecting connecting node to routing table.
bool hasNode(const NodeId &nodeId)
Check if connected node exsits in routing table.
unsigned getRoutingTableSize() const
Returns number of buckets in routing table.
bool hasConnectingNode(const NodeId &nodeId) const
Check if Connecting node exists in routing table.
std::vector< NodeId > getKnownNodes() const
Returns all routing table's known nodes.
std::vector< NodeId > getNodes() const
Returns all routing table's connected nodes.
bool contains(const std::list< Bucket >::iterator &it, const NodeId &nodeId) const
Test if connected nodeId is in specific bucket.
void printRoutingTable() const
Prints routing table.
std::list< Bucket > & getBuckets()
Returns buckets in routing table.
bool addConnectingNode(const NodeId &nodeId)
Add connecting node to routing table.
const std::list< Bucket >::const_iterator findBucket(const NodeId &nodeId) const
Returns bucket iterator containing nodeId.
NodeId getId() const
Returns id for routing table.
void removeMobileNode(const NodeId &nodeId)
Remove mobile node to routing table.
bool addNode(const std::shared_ptr< dhtnet::ChannelSocketInterface > &socket)
Add socket to bucket.
void setId(const NodeId &node)
Sets id for routing table.
dht::h256 NodeId
static constexpr const std::chrono::minutes FIND_PERIOD
void emitSignal(Args... args)
Definition ring_signal.h:64
dht::PkId NodeId
std::shared_ptr< dhtnet::ChannelSocketInterface > socket
NodeInfo(NodeInfo &&)=default
NodeInfo(std::shared_ptr< dhtnet::ChannelSocketInterface > socket_)
asio::steady_timer refresh_timer
NodeInfo(bool mobile, std::shared_ptr< dhtnet::ChannelSocketInterface > socket_)
NodeInfo()=delete