From 947076fe8f1aff3d2ec5dc77c67621c60014182b Mon Sep 17 00:00:00 2001 From: Ivan-lis Date: Fri, 15 Nov 2024 21:17:55 +0000 Subject: [PATCH] Make Roster code better --- library/include/larra/bind.hpp | 3 +- library/include/larra/client/client.hpp | 48 ++++++++++--------------- library/include/larra/jid.hpp | 39 ++++++++++---------- library/include/larra/roster.hpp | 26 ++++++++++++-- library/include/larra/utils.hpp | 14 ++++++++ 5 files changed, 79 insertions(+), 51 deletions(-) diff --git a/library/include/larra/bind.hpp b/library/include/larra/bind.hpp index d43f550..bac1e51 100644 --- a/library/include/larra/bind.hpp +++ b/library/include/larra/bind.hpp @@ -48,7 +48,6 @@ using ResultBind = Result; using IqBind = Iq; auto MakeSetBind() { - IqBind iq_bind{std::in_place_type, SetBind{.id = "1", .payload = Bind{}}}; - return iq_bind; + return SetBind{.id = "1", .payload = Bind{}}; } } // namespace larra::xmpp::iq diff --git a/library/include/larra/client/client.hpp b/library/include/larra/client/client.hpp index 7a5e855..8cd828c 100644 --- a/library/include/larra/client/client.hpp +++ b/library/include/larra/client/client.hpp @@ -42,7 +42,8 @@ namespace larra::xmpp::client { template struct Client { - constexpr Client(BareJid jid, XmlStream connection) : jid(std::move(jid)), connection(std::move(connection)) {}; + constexpr Client(BareJid jid, XmlStream connection) : jid(std::move(jid)), connection(std::move(connection)) { + } template Token = boost::asio::use_awaitable_t<>> constexpr auto Close(Token token = {}) { this->active = false; @@ -76,45 +77,35 @@ struct Client { auto Send(const T& object) -> boost::asio::awaitable { co_await this->connection.Send(object); } - [[nodiscard]] constexpr auto Jid() const -> const BareJid& { + [[nodiscard]] constexpr auto Jid() const -> const FullJid& { return this->jid; } auto CreateResourceBind() -> boost::asio::awaitable { SPDLOG_INFO("Send IQ: Set::Bind"); - co_await std::visit( - [&](auto&& query) -> boost::asio::awaitable { - co_await this->Send(query); - }, - ::iq::MakeSetBind()); + co_await this->Send(::iq::MakeSetBind()); auto bind_result = co_await connection.template Read<::iq::ResultBind>(); - resource_bind = std::move(bind_result.payload.jid->resource); + jid.resource = std::move(bind_result.payload.jid->resource); co_return; } auto UpdateListOfContacts() -> boost::asio::awaitable { SPDLOG_INFO("Send IQ: Get::Roster"); - co_await std::visit( - [&](auto&& query) -> boost::asio::awaitable { - co_await this->Send(query); - }, - ::iq::MakeGetRoster(FullJid{}.Username(jid.username).Server(jid.server).Resource(resource_bind))); + co_await this->Send(::iq::MakeGetRoster(jid)); - // IqRoster roster = co_await connection.template Read(); - // const auto& roster_result = std::get<::iq::ResultRoster>(roster); const auto roster_result = co_await connection.template Read<::iq::ResultRoster>(); - for(const auto& jid : roster_result.payload.items) { - SPDLOG_INFO("\t'{}'", ToString(jid)); - } + roster = std::move(roster_result.payload); + + SPDLOG_INFO("{}", ToString(roster)); co_return; } private: bool active = true; XmlStream connection{}; - BareJid jid; - std::string resource_bind; + FullJid jid; + ::iq::Roster roster; }; struct StartTlsNegotiationError : std::runtime_error { @@ -155,15 +146,14 @@ struct Challenge { throw std::runtime_error(std::format("Invalid name {} for challenge", node->get_name())); } std::string decoded = DecodeBase64(node->get_first_child_text()->get_content()); - auto params = std::views::split(decoded, ',') // - | std::views::transform([](auto param) { // - return std::string_view{param}; // - }) // - | std::views::transform([](std::string_view param) -> std::pair { // - auto v = param.find("="); // - return {param.substr(0, v), param.substr(v + 1)}; // - }) // - | std::ranges::to>(); + auto params = std::views::split(decoded, ',') | std::views::transform([](auto param) { + return std::string_view{param}; + }) | + std::views::transform([](std::string_view param) -> std::pair { + auto v = param.find("="); + return {param.substr(0, v), param.substr(v + 1)}; + }) | + std::ranges::to>(); return {.body = std::move(decoded), .serverNonce = params.at("r"), .salt = DecodeBase64(params.at("s")), diff --git a/library/include/larra/jid.hpp b/library/include/larra/jid.hpp index 78fa043..1ea3cd8 100644 --- a/library/include/larra/jid.hpp +++ b/library/include/larra/jid.hpp @@ -7,24 +7,6 @@ namespace larra::xmpp { -struct BareJid { - std::string username; - std::string server; - [[nodiscard]] static auto Parse(std::string_view jid) -> BareJid; - friend auto ToString(const BareJid& jid) -> std::string; - - constexpr auto operator==(const BareJid&) const -> bool = default; - template - [[nodiscard]] constexpr auto Username(this Self&& self, std::string username) -> std::decay_t { - return utils::FieldSetHelper::With<"username", BareJid>(std::forward(self), std::move(username)); - } - - template - [[nodiscard]] constexpr auto Server(this Self&& self, std::string server) -> std::decay_t { - return utils::FieldSetHelper::With<"server", BareJid>(std::forward(self), std::move(server)); - } -}; - struct BareResourceJid { std::string server; std::string resource; @@ -69,6 +51,27 @@ struct FullJid { } }; +struct BareJid { + std::string username; + std::string server; + constexpr operator FullJid() const { + return FullJid{.username = username, .server = server, .resource = ""}; + } + [[nodiscard]] static auto Parse(std::string_view jid) -> BareJid; + friend auto ToString(const BareJid& jid) -> std::string; + + constexpr auto operator==(const BareJid&) const -> bool = default; + template + [[nodiscard]] constexpr auto Username(this Self&& self, std::string username) -> std::decay_t { + return utils::FieldSetHelper::With<"username", BareJid>(std::forward(self), std::move(username)); + } + + template + [[nodiscard]] constexpr auto Server(this Self&& self, std::string server) -> std::decay_t { + return utils::FieldSetHelper::With<"server", BareJid>(std::forward(self), std::move(server)); + } +}; + using JidVariant = std::variant; struct Jid : JidVariant { diff --git a/library/include/larra/roster.hpp b/library/include/larra/roster.hpp index a0a4fe1..5c8dba3 100644 --- a/library/include/larra/roster.hpp +++ b/library/include/larra/roster.hpp @@ -4,7 +4,9 @@ #include #include +#include #include +#include #include namespace larra::xmpp::iq { @@ -15,6 +17,27 @@ struct Roster { std::vector items; + friend auto ToString(const Roster& roster) -> std::string { + static constexpr std::string_view prefix = "Roster: ["; + static constexpr std::string_view suffix = "]"; + std::size_t total_length = std::ranges::fold_left(roster.items | std::views::transform([](const auto& el) { + return larra::xmpp::utils::AccumulateFieldLength(el) + 2; + }), + std::size_t{0}, + std::plus<>{}) + + prefix.length() + suffix.length(); + + std::string s; + s.resize(total_length); + s = prefix; + for(const auto& el : roster.items) { + s += ToString(el); + s += "\n\t"; + } + s += suffix; + + return s; + } friend constexpr auto operator<<(xmlpp::Element* element, const Roster& roster) { element->set_attribute("xmlns", "jabber:iq:roster"); } @@ -46,8 +69,7 @@ using ResultRoster = Result; using IqRoster = Iq; auto MakeGetRoster(const FullJid& jid) { - IqRoster iq_roster{std::in_place_type, GetRoster{.id = "1", .from = ToString(jid), .payload = Roster{}}}; - return iq_roster; + return GetRoster{.id = "1", .from = ToString(jid), .payload = Roster{}}; } } // namespace larra::xmpp::iq diff --git a/library/include/larra/utils.hpp b/library/include/larra/utils.hpp index 1fb05a5..f3a702e 100644 --- a/library/include/larra/utils.hpp +++ b/library/include/larra/utils.hpp @@ -295,4 +295,18 @@ struct RangeToWrapper : T { : T{std::forward(args)...} {}; }; +template +concept LengthCalculatable = requires(const T& obj) { + { obj.length() } -> std::convertible_to; // Checks if obj has a length() method returning a type convertible to std::size_t +} || std::convertible_to; + +template +auto AccumulateFieldLength(const T& obj) -> std::size_t { + std::size_t total_length = 0; + boost::pfr::for_each_field(obj, [&](const LengthCalculatable auto& field) { + total_length += field.length(); // Accumulate length of each field + }); + return total_length; +} + } // namespace larra::xmpp::utils