New API for connection monitoring
Change-Id: If63c8121351f81b869b5b48b3df64eb412dd6f79
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 @@
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 @@
*/
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 @@
* 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
@@ -142,6 +142,11 @@
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 @@
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 @@
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 @@
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