Line data Source code
1 : /* 2 : * Copyright (C) 2024 Savoir-faire Linux Inc. 3 : * 4 : * Author: Fadi Shehadeh <fadi.shehadeh@savoirfairelinux.com> 5 : * 6 : * This program is free software; you can redistribute it and/or modify 7 : * it under the terms of the GNU General Public License as published by 8 : * the Free Software Foundation; either version 3 of the License, or 9 : * (at your option) any later version. 10 : * 11 : * This program is distributed in the hope that it will be useful, 12 : * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 : * GNU General Public License for more details. 15 : * 16 : * You should have received a copy of the GNU General Public License 17 : * along with this program; if not, write to the Free Software 18 : * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 : */ 20 : 21 : #pragma once 22 : 23 : #include "routing_table.h" 24 : #include "swarm_protocol.h" 25 : 26 : #include <iostream> 27 : #include <memory> 28 : 29 : namespace jami { 30 : 31 : using namespace swarm_protocol; 32 : 33 : class SwarmManager : public std::enable_shared_from_this<SwarmManager> 34 : { 35 : using ChannelCb = std::function<bool(const std::shared_ptr<dhtnet::ChannelSocketInterface>&)>; 36 : using NeedSocketCb = std::function<void(const std::string&, ChannelCb&&)>; 37 : using ToConnectCb = std::function<bool(const NodeId&)>; 38 : using OnConnectionChanged = std::function<void(bool ok)>; 39 : 40 : public: 41 : explicit SwarmManager(const NodeId&, const std::mt19937_64& rand, ToConnectCb&& toConnectCb); 42 : ~SwarmManager(); 43 : 44 : NeedSocketCb needSocketCb_; 45 : 46 5101 : std::weak_ptr<SwarmManager> weak() { return weak_from_this(); } 47 : 48 : /** 49 : * Get swarm manager id 50 : * @return NodeId 51 : */ 52 2431 : const NodeId& getId() const { return id_; } 53 : 54 : /** 55 : * Set list of nodes to the routing table known_nodes 56 : * @param known_nodes 57 : * @return if some are new 58 : */ 59 : bool setKnownNodes(const std::vector<NodeId>& known_nodes); 60 : 61 : /** 62 : * Set list of nodes to the routing table mobile_nodes 63 : * @param mobile_nodes 64 : */ 65 : void setMobileNodes(const std::vector<NodeId>& mobile_nodes); 66 : 67 : /** 68 : * Add channel to routing table 69 : * @param channel 70 : */ 71 : void addChannel(const std::shared_ptr<dhtnet::ChannelSocketInterface>& channel); 72 : 73 : /** 74 : * Remove channel from routing table 75 : * @param channel 76 : */ 77 : void removeNode(const NodeId& nodeId); 78 : 79 : /** 80 : * Change mobility of specific node 81 : * @param nodeId 82 : * @param isMobile 83 : */ 84 : void changeMobility(const NodeId& nodeId, bool isMobile); 85 : 86 : /** 87 : * get all nodes from the different tables in bucket 88 : */ 89 : std::vector<NodeId> getAllNodes() const; 90 : 91 : /** 92 : * Delete nodes from the different tables in bucket 93 : */ 94 : void deleteNode(std::vector<NodeId> nodes); 95 : 96 : // For tests 97 : 98 : /** 99 : * Get routing table 100 : * @return RoutingTable 101 : */ 102 6419 : RoutingTable& getRoutingTable() { return routing_table; }; 103 : 104 : /** 105 : * Get buckets of routing table 106 : * @return buckets list 107 : */ 108 : std::list<Bucket>& getBuckets() { return routing_table.getBuckets(); }; 109 : 110 : /** 111 : * Shutdown swarm manager 112 : */ 113 : void shutdown(); 114 : 115 : /** 116 : * Display swarm manager info 117 : */ 118 : void display() 119 : { 120 : JAMI_DEBUG("SwarmManager {:s} has {:d} nodes in table [P = {}]", 121 : getId().to_c_str(), 122 : routing_table.getRoutingTableNodeCount(), 123 : isMobile_); 124 : // print nodes of routingtable 125 : for (auto& bucket : routing_table.getBuckets()) { 126 : for (auto& node : bucket.getNodes()) { 127 : JAMI_DEBUG("Node {:s}", node.first.toString()); 128 : } 129 : } 130 : } 131 : 132 : /* 133 : * Callback for connection changed 134 : * @param cb 135 : */ 136 286 : void onConnectionChanged(OnConnectionChanged cb) { onConnectionChanged_ = std::move(cb); } 137 : 138 : /** 139 : * Set mobility of swarm manager 140 : * @param isMobile 141 : */ 142 363 : void setMobility(bool isMobile) { isMobile_ = isMobile; } 143 : 144 : /** 145 : * Get mobility of swarm manager 146 : * @return true if mobile, false if not 147 : */ 148 9 : bool isMobile() const { return isMobile_; } 149 : 150 : /** 151 : * Maintain/Update buckets 152 : * @param toConnect Nodes to connect 153 : */ 154 : void maintainBuckets(const std::set<NodeId>& toConnect = {}); 155 : 156 : /** 157 : * Check if we're connected with a specific device 158 : * @param deviceId 159 : * @return true if connected, false if not 160 : */ 161 : bool isConnectedWith(const NodeId& deviceId); 162 : 163 : /** 164 : * Check if swarm manager is shutdown 165 : * @return true if shutdown, false if not 166 : */ 167 830 : bool isShutdown() { return isShutdown_; }; 168 : 169 : private: 170 : /** 171 : * Add node to the known_nodes list 172 : * @param nodeId 173 : * @return if node inserted 174 : */ 175 : bool addKnownNode(const NodeId& nodeId); 176 : 177 : /** 178 : * Add node to the mobile_Nodes list 179 : * @param nodeId 180 : */ 181 : void addMobileNodes(const NodeId& nodeId); 182 : 183 : /** 184 : * Send nodes request to fill known_nodes list 185 : * @param socket 186 : * @param nodeId 187 : * @param q 188 : * @param numberNodes 189 : */ 190 : void sendRequest(const std::shared_ptr<dhtnet::ChannelSocketInterface>& socket, 191 : NodeId& nodeId, 192 : Query q, 193 : int numberNodes = Bucket::BUCKET_MAX_SIZE); 194 : 195 : /** 196 : * Send answer to request 197 : * @param socket 198 : * @param msg 199 : */ 200 : void sendAnswer(const std::shared_ptr<dhtnet::ChannelSocketInterface>& socket, const Message& msg_); 201 : 202 : /** 203 : * Interpret received message 204 : * @param socket 205 : */ 206 : void receiveMessage(const std::shared_ptr<dhtnet::ChannelSocketInterface>& socket); 207 : 208 : /** 209 : * Reset node's timer expiry 210 : * @param ec 211 : * @param socket 212 : * @param node 213 : */ 214 : void resetNodeExpiry(const asio::error_code& ec, 215 : const std::shared_ptr<dhtnet::ChannelSocketInterface>& socket, 216 : NodeId node = {}); 217 : 218 : /** 219 : * Try to establich connexion with specific node 220 : * @param nodeId 221 : */ 222 : void tryConnect(const NodeId& nodeId); 223 : 224 : /** 225 : * Remove node from routing table 226 : * @param nodeId 227 : */ 228 : void removeNodeInternal(const NodeId& nodeId); 229 : 230 : const NodeId id_; 231 : bool isMobile_ {false}; 232 : std::mt19937_64 rd; 233 : mutable std::mutex mutex; 234 : RoutingTable routing_table; 235 : 236 : std::atomic_bool isShutdown_ {false}; 237 : 238 : OnConnectionChanged onConnectionChanged_ {}; 239 : 240 : ToConnectCb toConnectCb_; 241 : }; 242 : 243 : } // namespace jami