LCOV - code coverage report
Current view: top level - src/jamidht/swarm - swarm_manager.h (source / functions) Coverage Total Hit
Test: jami-coverage-filtered.info Lines: 100.0 % 8 8
Test Date: 2026-06-13 09:18:46 Functions: 100.0 % 8 8

            Line data    Source code
       1              : /*
       2              :  *  Copyright (C) 2004-2026 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 "routing_table.h"
      20              : #include "swarm_protocol.h"
      21              : 
      22              : #include <memory>
      23              : 
      24              : namespace jami {
      25              : 
      26              : using namespace swarm_protocol;
      27              : 
      28              : class SwarmManager : public std::enable_shared_from_this<SwarmManager>
      29              : {
      30              :     using ChannelCb = std::function<bool(const std::shared_ptr<dhtnet::ChannelSocketInterface>&)>;
      31              :     using NeedSocketCb = std::function<void(const std::string&, ChannelCb&&, bool noNewSocket)>;
      32              :     using ToConnectCb = std::function<bool(const NodeId&)>;
      33              :     using OnConnectionChanged = std::function<void(bool ok)>;
      34              : 
      35              : public:
      36              :     explicit SwarmManager(const NodeId&, const std::mt19937_64& rand, ToConnectCb&& toConnectCb);
      37              :     ~SwarmManager();
      38              : 
      39              :     NeedSocketCb needSocketCb_;
      40              : 
      41         6226 :     std::weak_ptr<SwarmManager> weak() { return weak_from_this(); }
      42              : 
      43              :     /**
      44              :      * Get swarm manager id
      45              :      * @return NodeId
      46              :      */
      47         2614 :     const NodeId& getId() const { return id_; }
      48              : 
      49              :     /**
      50              :      * Set list of nodes to the routing table known_nodes
      51              :      * @param known_nodes
      52              :      * @return if some are new
      53              :      */
      54              :     bool setKnownNodes(const std::vector<NodeId>& known_nodes);
      55              : 
      56              :     /**
      57              :      * Set list of nodes to the routing table mobile_nodes
      58              :      * @param mobile_nodes
      59              :      */
      60              :     void setMobileNodes(const std::vector<NodeId>& mobile_nodes);
      61              : 
      62              :     /**
      63              :      * Add channel to routing table
      64              :      * @param channel
      65              :      */
      66              :     void addChannel(const std::shared_ptr<dhtnet::ChannelSocketInterface>& channel);
      67              : 
      68              :     /**
      69              :      * Remove channel from routing table
      70              :      * @param channel
      71              :      */
      72              :     void removeNode(const NodeId& nodeId);
      73              : 
      74              :     /**
      75              :      * Change mobility of specific node
      76              :      * @param nodeId
      77              :      * @param isMobile
      78              :      */
      79              :     void changeMobility(const NodeId& nodeId, bool isMobile);
      80              : 
      81              :     /**
      82              :      * Check if swarm manager is connected
      83              :      * @return true if the swarm has at least one connected node, false if not
      84              :      */
      85              :     bool isConnected() const;
      86              : 
      87              :     /**
      88              :      * get all nodes from the different tables in bucket
      89              :      */
      90              :     std::vector<NodeId> getAllNodes() const;
      91              : 
      92              :     std::vector<NodeId> getConnectedNodes() const;
      93              : 
      94              :     std::vector<std::map<std::string, std::string>> getRoutingTableInfo() const;
      95              : 
      96          452 :     unsigned getActiveNodesCount() const { return routing_table.getActiveNodesCount(); }
      97              : 
      98              :     /**
      99              :      * Delete nodes from the different tables in bucket
     100              :      */
     101              :     void deleteNode(const std::vector<NodeId>& nodes);
     102              : 
     103              :     // For tests
     104              : 
     105              :     /**
     106              :      * Get routing table
     107              :      * @return RoutingTable
     108              :      */
     109          229 :     RoutingTable& getRoutingTable() { return routing_table; };
     110              : 
     111              :     /**
     112              :      * Get buckets of routing table
     113              :      * @return buckets list
     114              :      */
     115              :     std::list<Bucket>& getBuckets() { return routing_table.getBuckets(); };
     116              : 
     117              :     /**
     118              :      * Shutdown swarm manager
     119              :      */
     120              :     void shutdown();
     121              : 
     122              :     /**
     123              :      * Restart the swarm manager.
     124              :      *
     125              :      * This function must be called in situations where we want
     126              :      * to use a swarm manager that was previously shut down.
     127              :      */
     128              :     void restart();
     129              : 
     130              :     /**
     131              :      * Display swarm manager info
     132              :      */
     133              :     void display()
     134              :     {
     135              :         JAMI_DEBUG("SwarmManager {:s} has {:d} nodes in table [P = {}]",
     136              :                    getId().to_c_str(),
     137              :                    routing_table.getNodeCount(),
     138              :                    isMobile_);
     139              :         // print nodes of routingtable
     140              :         for (auto& bucket : routing_table.getBuckets()) {
     141              :             for (auto& node : bucket.getNodes()) {
     142              :                 JAMI_DEBUG("Node {:s}", node.first.toString());
     143              :             }
     144              :         }
     145              :     }
     146              : 
     147              :     /*
     148              :      * Callback for connection changed
     149              :      * @param cb
     150              :      */
     151          512 :     void onConnectionChanged(OnConnectionChanged cb) { onConnectionChanged_ = std::move(cb); }
     152              : 
     153              :     /**
     154              :      * Set mobility of swarm manager
     155              :      * @param isMobile
     156              :      */
     157          163 :     void setMobility(bool isMobile) { isMobile_ = isMobile; }
     158              : 
     159              :     /**
     160              :      * Get mobility of swarm manager
     161              :      * @return true if mobile, false if not
     162              :      */
     163            9 :     bool isMobile() const { return isMobile_; }
     164              : 
     165              :     /**
     166              :      * Maintain/Update buckets
     167              :      * @param toConnect         Nodes to connect
     168              :      */
     169              :     void maintainBuckets(const std::set<NodeId>& toConnect = {});
     170              : 
     171              :     /**
     172              :      * Proactively connect to a node, bypassing bucket capacity checks.
     173              :      * The node is registered as known and a connection is attempted with
     174              :      * noNewSocket=true (reuses an existing transport).
     175              :      * @param nodeId
     176              :      */
     177              :     void connectNode(const NodeId& nodeId);
     178              : 
     179              :     /**
     180              :      * Check if swarm manager is shutdown
     181              :      * @return true if shutdown, false if not
     182              :      */
     183         1045 :     bool isShutdown() { return isShutdown_; };
     184              : 
     185              : private:
     186              :     /**
     187              :      * Check if we're connected with a specific device
     188              :      * @param deviceId
     189              :      * @return true if connected, false if not
     190              :      */
     191              :     bool isConnectedWith(const NodeId& deviceId);
     192              : 
     193              :     /**
     194              :      * Add node to the known_nodes list
     195              :      * @param nodeId
     196              :      * @return if node inserted
     197              :      */
     198              :     bool addKnownNode(const NodeId& nodeId);
     199              : 
     200              :     /**
     201              :      * Add node to the mobile_Nodes list
     202              :      * @param nodeId
     203              :      */
     204              :     void addMobileNodes(const NodeId& nodeId);
     205              : 
     206              :     /**
     207              :      * Send nodes request to fill known_nodes list
     208              :      * @param socket
     209              :      * @param nodeId
     210              :      * @param q
     211              :      * @param numberNodes
     212              :      */
     213              :     void sendRequest(const std::shared_ptr<dhtnet::ChannelSocketInterface>& socket,
     214              :                      const NodeId& nodeId,
     215              :                      Query q,
     216              :                      int numberNodes = Bucket::BUCKET_MAX_SIZE);
     217              : 
     218              :     /**
     219              :      * Send answer to request
     220              :      * @param socket
     221              :      * @param msg
     222              :      */
     223              :     void sendAnswer(const std::shared_ptr<dhtnet::ChannelSocketInterface>& socket, const Message& msg_);
     224              : 
     225              :     /**
     226              :      * Interpret received message
     227              :      * @param socket
     228              :      */
     229              :     void receiveMessage(const std::shared_ptr<dhtnet::ChannelSocketInterface>& socket);
     230              : 
     231              :     /**
     232              :      * Reset node's timer expiry
     233              :      * @param ec
     234              :      * @param socket
     235              :      * @param node
     236              :      */
     237              :     void resetNodeExpiry(const asio::error_code& ec,
     238              :                          const std::shared_ptr<dhtnet::ChannelSocketInterface>& socket,
     239              :                          NodeId node = {});
     240              : 
     241              :     /**
     242              :      * Try to establish connection with specific node
     243              :      * @param nodeId
     244              :      * @param noNewSocket  If true, reuse an existing transport (no new ICE negotiation)
     245              :      */
     246              :     void tryConnect(const NodeId& nodeId, bool noNewSocket = false);
     247              : 
     248              :     /**
     249              :      * Remove node from routing table
     250              :      * @param nodeId
     251              :      */
     252              :     void removeNodeInternal(const NodeId& nodeId);
     253              : 
     254              :     const NodeId id_;
     255              :     bool isMobile_ {false};
     256              :     std::mt19937_64 rd;
     257              :     mutable std::mutex mutex;
     258              :     RoutingTable routing_table;
     259              : 
     260              :     std::atomic_bool isShutdown_ {false};
     261              : 
     262              :     OnConnectionChanged onConnectionChanged_ {};
     263              : 
     264              :     ToConnectCb toConnectCb_;
     265              : };
     266              : 
     267              : } // namespace jami
        

Generated by: LCOV version 2.0-1