From 951c15417c1b23188ff77c4f95935402a100abeb Mon Sep 17 00:00:00 2001 From: Dmitriy Khaustov aka xDimon Date: Fri, 30 Jan 2026 18:26:58 +0800 Subject: [PATCH 1/3] feature: user agent repository --- include/libp2p/injector/host_injector.hpp | 2 + include/libp2p/peer/peer_repository.hpp | 19 +++++-- include/libp2p/peer/user_agent_repository.hpp | 56 +++++++++++++++++++ .../inmem_user_agent_repository.hpp | 37 ++++++++++++ src/CMakeLists.txt | 1 + src/peer/CMakeLists.txt | 1 + src/peer/peer_repository.cpp | 11 +++- src/peer/user_agent_repository/CMakeLists.txt | 15 +++++ .../inmem_user_agent_repository.cpp | 39 +++++++++++++ src/protocol/identify/identify.cpp | 2 + src/protocol/ping.cpp | 2 +- 11 files changed, 177 insertions(+), 8 deletions(-) create mode 100644 include/libp2p/peer/user_agent_repository.hpp create mode 100644 include/libp2p/peer/user_agent_repository/inmem_user_agent_repository.hpp create mode 100644 src/peer/user_agent_repository/CMakeLists.txt create mode 100644 src/peer/user_agent_repository/inmem_user_agent_repository.cpp diff --git a/include/libp2p/injector/host_injector.hpp b/include/libp2p/injector/host_injector.hpp index f9605936..91f2b44f 100644 --- a/include/libp2p/injector/host_injector.hpp +++ b/include/libp2p/injector/host_injector.hpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -98,6 +99,7 @@ namespace libp2p::injector { di::bind.to(), di::bind.to(), di::bind.to(), + di::bind.to(), di::bind.to(), di::bind.to(), di::bind.to(), diff --git a/include/libp2p/peer/peer_repository.hpp b/include/libp2p/peer/peer_repository.hpp index d43c7227..09472712 100644 --- a/include/libp2p/peer/peer_repository.hpp +++ b/include/libp2p/peer/peer_repository.hpp @@ -13,6 +13,7 @@ #include #include #include +#include namespace libp2p::peer { /** @@ -21,9 +22,10 @@ namespace libp2p::peer { */ class PeerRepository { public: - PeerRepository(std::shared_ptr addrRepo, - std::shared_ptr keyRepo, - std::shared_ptr protocolRepo); + PeerRepository(std::shared_ptr addr_repo, + std::shared_ptr key_repo, + std::shared_ptr protocol_repo, + std::shared_ptr uagent_repo); /** * @brief Getter for an address repository. * @return associated instance of an address repository. @@ -42,11 +44,17 @@ namespace libp2p::peer { */ ProtocolRepository &getProtocolRepository(); + /** + * @brief Getter for a user-agent repository. + * @return associated instance of a protocol repository. + */ + UserAgentRepository &getUserAgentRepository(); + /** * @brief Returns set of peer ids known by this peer repository. * @return unordered set of peers */ - std::unordered_set getPeers() const; + [[nodiscard]] std::unordered_set getPeers() const; /** * @brief Derive a PeerInfo object from the PeerId; can be useful, for @@ -55,11 +63,12 @@ namespace libp2p::peer { * @param peer_id to get PeerInfo for * @return PeerInfo */ - PeerInfo getPeerInfo(const PeerId &peer_id) const; + [[nodiscard]] PeerInfo getPeerInfo(const PeerId &peer_id) const; private: std::shared_ptr addr_; std::shared_ptr key_; std::shared_ptr proto_; + std::shared_ptr uagent_; }; } // namespace libp2p::peer diff --git a/include/libp2p/peer/user_agent_repository.hpp b/include/libp2p/peer/user_agent_repository.hpp new file mode 100644 index 00000000..974aac75 --- /dev/null +++ b/include/libp2p/peer/user_agent_repository.hpp @@ -0,0 +1,56 @@ +/** + * Copyright Quadrivium LLC + * All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include +#include + +#include + +namespace libp2p::peer { + + /** + * @brief Storage for mapping between peer and its known protocols. + */ + class UserAgentRepository { + public: + virtual ~UserAgentRepository() = default; + + /** + * @brief Set agent for a peer. + * @param p peer + * @param agent type of agent-name + * @return peer error, if no peer {@param p} found + */ + virtual void setUserAgent(const PeerId &p, std::string_view ua) = 0; + + /** + * @brief Removes user-agent of the peer. + * @param p peer + * @return peer error, if no peer {@param p} found + */ + virtual void unsetUserAgent(const PeerId &) = 0; + + /** + * @brief Get user-agent by given peer {@param p} + * @param p peer + * @return user-agent (may be "unknown") or peer error, if no peer + * {@param p} found + */ + [[nodiscard]] virtual std::optional getUserAgent( + const PeerId &p) const = 0; + + /** + * @brief Returns set of peer ids known by this repository. + * @return unordered set of peers + */ + [[nodiscard]] virtual std::unordered_set getPeers() const = 0; + }; + +} // namespace libp2p::peer diff --git a/include/libp2p/peer/user_agent_repository/inmem_user_agent_repository.hpp b/include/libp2p/peer/user_agent_repository/inmem_user_agent_repository.hpp new file mode 100644 index 00000000..fcee2e78 --- /dev/null +++ b/include/libp2p/peer/user_agent_repository/inmem_user_agent_repository.hpp @@ -0,0 +1,37 @@ +/** + * Copyright Quadrivium LLC + * All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include + +#include + +namespace libp2p::peer { + + /** + * @brief In-memory implementation of UserAgent repository. For each peer + * stores UserAgent data. + */ + class InmemUserAgentRepository : public UserAgentRepository { + public: + ~InmemUserAgentRepository() override = default; + + void setUserAgent(const PeerId &p, std::string_view ua) override; + + void unsetUserAgent(const PeerId &p) override; + + [[nodiscard]] std::optional getUserAgent( + const PeerId &p) const override; + + [[nodiscard]] std::unordered_set getPeers() const override; + + private: + std::unordered_map db_; + }; + +} // namespace libp2p::peer diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 158598f2..7acb0f01 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -41,6 +41,7 @@ target_link_libraries(libp2p p2p_inmem_address_repository p2p_inmem_key_repository p2p_inmem_protocol_repository + p2p_inmem_user_agent_repository p2p_key_validator p2p_listener_manager p2p_literals diff --git a/src/peer/CMakeLists.txt b/src/peer/CMakeLists.txt index f77815df..25baffff 100644 --- a/src/peer/CMakeLists.txt +++ b/src/peer/CMakeLists.txt @@ -7,6 +7,7 @@ add_subdirectory(address_repository) add_subdirectory(key_repository) add_subdirectory(protocol_repository) +add_subdirectory(user_agent_repository) libp2p_add_library(p2p_peer_errors errors.cpp diff --git a/src/peer/peer_repository.cpp b/src/peer/peer_repository.cpp index 563c7853..bc3cc970 100644 --- a/src/peer/peer_repository.cpp +++ b/src/peer/peer_repository.cpp @@ -23,13 +23,16 @@ namespace libp2p::peer { PeerRepository::PeerRepository( std::shared_ptr addr_repo, std::shared_ptr key_repo, - std::shared_ptr protocol_repo) + std::shared_ptr protocol_repo, + std::shared_ptr uagent_repository) : addr_(std::move(addr_repo)), key_(std::move(key_repo)), - proto_(std::move(protocol_repo)) { + proto_(std::move(protocol_repo)) , + uagent_(std::move(uagent_repository)) { BOOST_ASSERT(addr_ != nullptr); BOOST_ASSERT(key_ != nullptr); BOOST_ASSERT(proto_ != nullptr); + BOOST_ASSERT(uagent_ != nullptr); } AddressRepository &PeerRepository::getAddressRepository() { @@ -44,6 +47,10 @@ namespace libp2p::peer { return *proto_; } + UserAgentRepository &PeerRepository::getUserAgentRepository() { + return *uagent_; + } + std::unordered_set PeerRepository::getPeers() const { std::unordered_set peers; merge_sets(peers, addr_->getPeers()); diff --git a/src/peer/user_agent_repository/CMakeLists.txt b/src/peer/user_agent_repository/CMakeLists.txt new file mode 100644 index 00000000..3f3b34b0 --- /dev/null +++ b/src/peer/user_agent_repository/CMakeLists.txt @@ -0,0 +1,15 @@ +# +# Copyright Quadrivium LLC +# All Rights Reserved +# SPDX-License-Identifier: Apache-2.0 +# + +libp2p_add_library(p2p_inmem_user_agent_repository + inmem_user_agent_repository.cpp + ) +target_link_libraries(p2p_inmem_user_agent_repository + Boost::boost + p2p_peer_errors + p2p_multihash + p2p_peer_id + ) diff --git a/src/peer/user_agent_repository/inmem_user_agent_repository.cpp b/src/peer/user_agent_repository/inmem_user_agent_repository.cpp new file mode 100644 index 00000000..c5bcf919 --- /dev/null +++ b/src/peer/user_agent_repository/inmem_user_agent_repository.cpp @@ -0,0 +1,39 @@ +/** + * Copyright Quadrivium LLC + * All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include <__ranges/transform_view.h> + +#include +#include + +namespace libp2p::peer { + + void InmemUserAgentRepository::setUserAgent(const PeerId &p, + std::string_view ua) { + db_.insert_or_assign(p, ua); + } + + void InmemUserAgentRepository::unsetUserAgent(const PeerId &p) { + db_.erase(p); + } + + std::optional InmemUserAgentRepository::getUserAgent( + const PeerId &p) const { + if (auto it = db_.find(p); it != db_.end()) { + return it->second; + } + return std::nullopt; + } + + std::unordered_set InmemUserAgentRepository::getPeers() const { + return db_ + | std::ranges::views::transform([](const auto &p) { return p.first; }) + | std::ranges::to>(); + } + +} // namespace libp2p::peer diff --git a/src/protocol/identify/identify.cpp b/src/protocol/identify/identify.cpp index bc735dd9..db984637 100644 --- a/src/protocol/identify/identify.cpp +++ b/src/protocol/identify/identify.cpp @@ -120,6 +120,8 @@ namespace libp2p::protocol { .upsertAddresses( peer_id, message.listen_addresses, peer::ttl::kRecentlyConnected) .value(); + auto &user_agent_repo = peer_repo.getUserAgentRepository(); + user_agent_repo.setUserAgent(peer_id, message.agent_version); host_->getBus().getChannel().publish(message); co_return outcome::success(); diff --git a/src/protocol/ping.cpp b/src/protocol/ping.cpp index f99090de..299d7cc3 100644 --- a/src/protocol/ping.cpp +++ b/src/protocol/ping.cpp @@ -102,7 +102,7 @@ namespace libp2p::protocol { } auto stream = stream_result.value(); auto res = co_await ping(stream, timeout); - stream->close(); + std::ignore = stream->close(); co_return res; } From d9cd796a2ce5efe448ade89565f21df7a73a812e Mon Sep 17 00:00:00 2001 From: Dmitriy Khaustov aka xDimon Date: Fri, 30 Jan 2026 18:40:08 +0800 Subject: [PATCH 2/3] feature: getter for peer id list of connected peers --- include/libp2p/host/basic_host.hpp | 6 ++++-- include/libp2p/network/connection_manager.hpp | 4 +++- src/host/basic_host.cpp | 4 ++++ src/network/connection_manager.cpp | 6 ++++++ 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/include/libp2p/host/basic_host.hpp b/include/libp2p/host/basic_host.hpp index 5cd7dbb5..6e91c307 100644 --- a/include/libp2p/host/basic_host.hpp +++ b/include/libp2p/host/basic_host.hpp @@ -227,9 +227,11 @@ namespace libp2p::host { /** * Get list of protocols that were passed to `listenProtocol`. */ - StreamProtocols getSupportedProtocols() const; + [[nodiscard]] StreamProtocols getSupportedProtocols() const; - size_t getConnectedPeerCount() const; + [[nodiscard]] std::vector getConnectedPeers() const; + + [[nodiscard]] size_t getConnectedPeerCount() const; private: std::shared_ptr idmgr_; diff --git a/include/libp2p/network/connection_manager.hpp b/include/libp2p/network/connection_manager.hpp index 3e6d4852..7d478a36 100644 --- a/include/libp2p/network/connection_manager.hpp +++ b/include/libp2p/network/connection_manager.hpp @@ -58,7 +58,9 @@ namespace libp2p::network { const peer::PeerId &peer_id, const std::shared_ptr &conn); - size_t getConnectedPeerCount() const; + [[nodiscard]] std::vector getConnectedPeers() const; + + [[nodiscard]] size_t getConnectedPeerCount() const; private: std::unordered_map> diff --git a/src/host/basic_host.cpp b/src/host/basic_host.cpp index f9a103b6..f1eabe14 100644 --- a/src/host/basic_host.cpp +++ b/src/host/basic_host.cpp @@ -239,6 +239,10 @@ namespace libp2p::host { return listener_->getSupportedProtocols(); } + std::vector BasicHost::getConnectedPeers() const { + return connection_manager_->getConnectedPeers(); + } + size_t BasicHost::getConnectedPeerCount() const { return connection_manager_->getConnectedPeerCount(); } diff --git a/src/network/connection_manager.cpp b/src/network/connection_manager.cpp index 16f4d8ed..4eb15c89 100644 --- a/src/network/connection_manager.cpp +++ b/src/network/connection_manager.cpp @@ -7,6 +7,7 @@ #include #include +#include namespace libp2p::network { @@ -166,6 +167,11 @@ namespace libp2p::network { } } + std::vector ConnectionManager::getConnectedPeers() const { + return connections_ | std::views::keys + | std::ranges::to>(); + } + size_t ConnectionManager::getConnectedPeerCount() const { return connections_.size(); } From 1a46fef5262952ef5e0f29451a6050f684c3cdae Mon Sep 17 00:00:00 2001 From: Dmitriy Khaustov aka xDimon Date: Mon, 2 Feb 2026 16:12:43 +0800 Subject: [PATCH 3/3] hotfix --- src/peer/user_agent_repository/inmem_user_agent_repository.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/peer/user_agent_repository/inmem_user_agent_repository.cpp b/src/peer/user_agent_repository/inmem_user_agent_repository.cpp index c5bcf919..9b039429 100644 --- a/src/peer/user_agent_repository/inmem_user_agent_repository.cpp +++ b/src/peer/user_agent_repository/inmem_user_agent_repository.cpp @@ -6,10 +6,9 @@ #include -#include <__ranges/transform_view.h> +#include #include -#include namespace libp2p::peer {