From 31791e5e58fb338b2c2a476bb3d3b639c350fa37 Mon Sep 17 00:00:00 2001 From: Amna <amna.snene@savoirfairelinux.com> Date: Thu, 3 Aug 2023 12:40:57 -0400 Subject: [PATCH] New API for connection monitoring Change-Id: If63c8121351f81b869b5b48b3df64eb412dd6f79 --- include/connectionmanager.h | 42 ++++++++++++++ include/multiplexed_socket.h | 5 ++ src/connectionmanager.cpp | 104 +++++++++++++++++++++++++++++++++++ src/multiplexed_socket.cpp | 17 ++++++ 4 files changed, 168 insertions(+) diff --git a/include/connectionmanager.h b/include/connectionmanager.h index 17300dc..ae08212 100644 --- a/include/connectionmanager.h +++ b/include/connectionmanager.h @@ -42,6 +42,7 @@ class Controller; namespace tls { class CertificateStore; } +enum class ConnectionStatus : int { Connected, TLS, ICE, Connecting, Waiting }; /** * A PeerConnectionRequest is a request which ask for an initial connection @@ -211,6 +212,46 @@ public: */ void storeActiveIpAddress(std::function<void()>&& cb = {}); + /** + * Retrieve the list of connections. + * + * @param device The device ID to filter the connections (optional). + * @return The list of connections as a vector of maps, where each map represents a connection. + * + * Note: The connections are represented as maps with string keys and string values. The map + * contains the following key-value pairs: + * - "id": The unique identifier of the connection. + * - "userUri": The user URI associated with the connection (if available). + * - "status": The status of the connection, represented as an integer: + * - 0: ConnectionStatus::Connected + * - 1: ConnectionStatus::TLS + * - 2: ConnectionStatus::ICE + * - 3: ConnectionStatus::Connecting (for pending operations) + * - 4: ConnectionStatus::Waiting (for pending operations) + * - "remoteAddress": The remote IP address of the connection (if available). + * - "remotePort": The remote port of the connection (if available). + * + * If a specific device ID is provided, the returned list will only include connections + * associated with that device. Otherwise, connections from all devices will be included. + */ + std::vector<std::map<std::string, std::string>> getConnectionList( + const DeviceId& device = {}) const; + + /** + * Retrieve the list of channels associated with a connection. + * + * @param connectionId The ID of the connection to fetch the channels from. + * @return The list of channels as a vector of maps, where each map represents a channel + * and contains key-value pairs of channel ID and channel name. + * + * If the specified connection ID is valid and associated with a connection, + * the method returns the list of channels associated with that connection. + * Otherwise, an empty vector is returned. + */ + std::vector<std::map<std::string, std::string>> getChannelList( + const std::string& connectionId) const; + + std::shared_ptr<Config> getConfig(); private: @@ -273,6 +314,7 @@ struct ConnectionManager::Config * ie: if it is able to make port mappings */ bool getUPnPActive() const; + }; } // namespace dhtnet \ No newline at end of file diff --git a/include/multiplexed_socket.h b/include/multiplexed_socket.h index b440891..1d37166 100644 --- a/include/multiplexed_socket.h +++ b/include/multiplexed_socket.h @@ -141,6 +141,11 @@ public: const std::shared_ptr<Logger>& logger(); + /** + * Get the list of channels + */ + std::vector<std::map<std::string, std::string>> getChannelList() const; + /** * Send a beacon on the socket and close if no response come * @param timeout diff --git a/src/connectionmanager.cpp b/src/connectionmanager.cpp index b3d8b79..9fda75c 100644 --- a/src/connectionmanager.cpp +++ b/src/connectionmanager.cpp @@ -41,7 +41,23 @@ static constexpr uint64_t ID_MAX_VAL = 9007199254740992; using ValueIdDist = std::uniform_int_distribution<dht::Value::Id>; using CallbackId = std::pair<dhtnet::DeviceId, dht::Value::Id>; +std::string +callbackIdToString(const dhtnet::DeviceId& did, const dht::Value::Id& vid) +{ + return fmt::format("{} {}", did.to_view(), vid); +} + +CallbackId parseCallbackId(std::string_view ci) +{ + auto sep = ci.find(' '); + std::string_view deviceIdString = ci.substr(0, sep); + std::string_view vidString = ci.substr(sep + 1); + + dhtnet::DeviceId deviceId(deviceIdString); + dht::Value::Id vid = std::stoul(std::string(vidString), nullptr, 10); + return CallbackId(deviceId, vid); +} struct ConnectionInfo { ~ConnectionInfo() @@ -1756,4 +1772,92 @@ ConnectionManager::getConfig() return pimpl_->config_; } +std::vector<std::map<std::string, std::string>> +ConnectionManager::getConnectionList(const DeviceId& device) const +{ + std::vector<std::map<std::string, std::string>> connectionsList; + std::lock_guard<std::mutex> lk(pimpl_->infosMtx_); + + for (const auto& [key, ci] : pimpl_->infos_) { + if (device && key.first != device) + continue; + std::map<std::string, std::string> connectionInfo; + connectionInfo["id"] = callbackIdToString(key.first, key.second); + if (ci->tls_ && ci->tls_->peerCertificate()) { + auto cert = ci->tls_->peerCertificate(); + connectionInfo["userUri"] = cert->issuer->getId().toString(); + } + if (ci->socket_) { + connectionInfo["status"] = std::to_string(static_cast<int>(ConnectionStatus::Connected)); + } else if (ci->tls_) { + connectionInfo["status"] = std::to_string(static_cast<int>(ConnectionStatus::TLS)); + } else if(ci->ice_) + { + connectionInfo["status"] = std::to_string(static_cast<int>(ConnectionStatus::ICE)); + } + if (ci->tls_) { + std::string remoteAddress = ci->tls_->getRemoteAddress(); + std::string remoteAddressIp = remoteAddress.substr(0, remoteAddress.find(':')); + std::string remoteAddressPort = remoteAddress.substr(remoteAddress.find(':') + 1); + connectionInfo["remoteAdress"] = remoteAddressIp; + connectionInfo["remotePort"] = remoteAddressPort; + } + connectionsList.emplace_back(std::move(connectionInfo)); + } + + if (device) { + auto it = pimpl_->pendingOperations_.find(device); + if (it != pimpl_->pendingOperations_.end()) { + const auto& po = it->second; + for (const auto& [vid, ci] : po.connecting) { + std::map<std::string, std::string> connectionInfo; + connectionInfo["id"] = callbackIdToString(device, vid); + connectionInfo["deviceId"] = vid; + connectionInfo["status"] = std::to_string(static_cast<int>(ConnectionStatus::Connecting)); + connectionsList.emplace_back(std::move(connectionInfo)); + } + + for (const auto& [vid, ci] : po.waiting) { + std::map<std::string, std::string> connectionInfo; + connectionInfo["id"] = callbackIdToString(device, vid); + connectionInfo["deviceId"] = vid; + connectionInfo["status"] = std::to_string(static_cast<int>(ConnectionStatus::Waiting)); + connectionsList.emplace_back(std::move(connectionInfo)); + } + } + } + else { + for (const auto& [key, po] : pimpl_->pendingOperations_) { + for (const auto& [vid, ci] : po.connecting) { + std::map<std::string, std::string> connectionInfo; + connectionInfo["id"] = callbackIdToString(device, vid); + connectionInfo["deviceId"] = vid; + connectionInfo["status"] = std::to_string(static_cast<int>(ConnectionStatus::Connecting)); + connectionsList.emplace_back(std::move(connectionInfo)); + } + + for (const auto& [vid, ci] : po.waiting) { + std::map<std::string, std::string> connectionInfo; + connectionInfo["id"] = callbackIdToString(device, vid); + connectionInfo["deviceId"] = vid; + connectionInfo["status"] = std::to_string(static_cast<int>(ConnectionStatus::Waiting)); + connectionsList.emplace_back(std::move(connectionInfo)); + } + } + } + return connectionsList; +} + +std::vector<std::map<std::string, std::string>> +ConnectionManager::getChannelList(const std::string& connectionId) const +{ + std::lock_guard<std::mutex> lk(pimpl_->infosMtx_); + CallbackId cbid = parseCallbackId(connectionId); + if (pimpl_->infos_.count(cbid) > 0) { + return pimpl_->infos_[cbid]->socket_->getChannelList(); + } else { + return {}; + } +} + } // namespace dhtnet diff --git a/src/multiplexed_socket.cpp b/src/multiplexed_socket.cpp index 7b58922..9c6d59d 100644 --- a/src/multiplexed_socket.cpp +++ b/src/multiplexed_socket.cpp @@ -1204,4 +1204,21 @@ ChannelSocket::getRemoteAddress() const return {}; } +std::vector<std::map<std::string, std::string>> +MultiplexedSocket::getChannelList() const +{ + std::vector<std::map<std::string, std::string>> channelsList; + + for (const auto& [_, channel] : pimpl_->sockets) { + if (channel) { + std::map<std::string, std::string> channelMap; + channelMap["channel"] = std::to_string(channel->channel()); + channelMap["channelName"]= channel->name(); + channelsList.emplace_back(std::move(channelMap)); + } + } + + return channelsList; +} + } // namespace dhtnet -- GitLab