Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 17 additions & 15 deletions include/libp2p/peer/user_agent_repository.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#pragma once

#include <libp2p/basic/garbage_collectable.hpp>
#include <optional>
#include <string>
#include <string_view>
Expand All @@ -18,24 +19,31 @@ namespace libp2p::peer {
/**
* @brief Storage for mapping between peer and its known protocols.
*/
class UserAgentRepository {
class UserAgentRepository : public basic::GarbageCollectable {
public:
virtual ~UserAgentRepository() = default;
using Milliseconds = std::chrono::milliseconds;

~UserAgentRepository() override = default;

/**
* @brief Set agent for a peer.
* @brief Update user-agent with new {@param ttl} or insert new
* user-agent with new {@param ttl}
* @param p peer
* @param agent type of agent-name
* @return peer error, if no peer {@param p} found
* @param ua user-agent type
* @param ttl ttl
* @return true/false if at least one new user-agent was added or not,
*/
virtual void setUserAgent(const PeerId &p, std::string_view ua) = 0;
virtual void updateUserAgent(const PeerId &p,
std::string_view ua,
Milliseconds ttl) = 0;

/**
* @brief Removes user-agent of the peer.
* @brief Bump ttl of a given peer {@param p}
* @param p peer
* @return peer error, if no peer {@param p} found
* @param ttl time to live for user-agent
* @return error when no peer has been found
*/
virtual void unsetUserAgent(const PeerId &) = 0;
virtual void updateTtl(const PeerId &p, Milliseconds ttl) = 0;

/**
* @brief Get user-agent by given peer {@param p}
Expand All @@ -45,12 +53,6 @@ namespace libp2p::peer {
*/
[[nodiscard]] virtual std::optional<std::string> 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<PeerId> getPeers() const = 0;
};

} // namespace libp2p::peer
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <optional>
#include <unordered_map>

#include <libp2p/peer/address_repository/inmem_address_repository.hpp>
#include <libp2p/peer/user_agent_repository.hpp>

namespace libp2p::peer {
Expand All @@ -21,17 +22,21 @@ namespace libp2p::peer {
public:
~InmemUserAgentRepository() override = default;

void setUserAgent(const PeerId &p, std::string_view ua) override;
void updateUserAgent(const PeerId &p,
std::string_view ua,
Milliseconds ttl) override;

void unsetUserAgent(const PeerId &p) override;
void updateTtl(const PeerId &p, Milliseconds ttl) override;

[[nodiscard]] std::optional<std::string> getUserAgent(
const PeerId &p) const override;

[[nodiscard]] std::unordered_set<PeerId> getPeers() const override;
void collectGarbage() override;

private:
std::unordered_map<PeerId, std::string> db_;
std::unordered_map<PeerId, std::pair<std::string, Clock::time_point>> db_;

[[nodiscard]] Clock::time_point calculateExpirationTime(const Milliseconds &ttl) const;
};

} // namespace libp2p::peer
46 changes: 34 additions & 12 deletions src/peer/user_agent_repository/inmem_user_agent_repository.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,53 @@

#include <ranges>

#include <libp2p/peer/errors.hpp>

namespace libp2p::peer {

void InmemUserAgentRepository::setUserAgent(const PeerId &p,
std::string_view ua) {
db_.insert_or_assign(p, ua);
Clock::time_point InmemUserAgentRepository::calculateExpirationTime(
const Milliseconds &ttl) const {
static const auto max_time = Clock::time_point::max();
const auto now = Clock::now();
if (now >= max_time - ttl) {
return max_time;
}
return now + ttl;
}

void InmemUserAgentRepository::updateUserAgent(const PeerId &p,
std::string_view ua,
Milliseconds ttl) {
db_.insert_or_assign(
p, std::pair(std::string(ua), calculateExpirationTime(ttl)));
}

void InmemUserAgentRepository::unsetUserAgent(const PeerId &p) {
db_.erase(p);
void InmemUserAgentRepository::updateTtl(const PeerId &p, Milliseconds ttl) {
if (ttl > std::chrono::milliseconds::zero()) {
if (auto it = db_.find(p); it != db_.end()) {
it->second.second = calculateExpirationTime(ttl);
}
} else {
db_.erase(p);
}
}

std::optional<std::string> InmemUserAgentRepository::getUserAgent(
const PeerId &p) const {
if (auto it = db_.find(p); it != db_.end()) {
return it->second;
return it->second.first;
}
return std::nullopt;
}

std::unordered_set<PeerId> InmemUserAgentRepository::getPeers() const {
return db_
| std::ranges::views::transform([](const auto &p) { return p.first; })
| std::ranges::to<std::unordered_set<PeerId>>();
void InmemUserAgentRepository::collectGarbage() {
auto now = Clock::now();
for (auto it = db_.begin(); it != db_.end();) {
const auto &expiration_time = it->second.second;
if (now >= expiration_time) {
it = db_.erase(it);
} else {
++it;
}
}
}

} // namespace libp2p::peer
3 changes: 2 additions & 1 deletion src/protocol/identify/identify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,8 @@ namespace libp2p::protocol {
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);
user_agent_repo.updateUserAgent(
peer_id, message.agent_version, peer::ttl::kRecentlyConnected);

host_->getBus().getChannel<OnIdentifyChannel>().publish(message);
co_return outcome::success();
Expand Down
Loading