From 77640de2e97b7235e6e3824227b83c67f35cd392 Mon Sep 17 00:00:00 2001 From: Ivan-lis Date: Sun, 17 Nov 2024 23:25:41 +0000 Subject: [PATCH] Feature: iq::Bind --- library/include/larra/bind.hpp | 53 ++++++++++++++++++++++++++++++++++ library/include/larra/iq.hpp | 28 +++++++++++++++++- library/include/larra/jid.hpp | 39 +++++++++++++------------ 3 files changed, 101 insertions(+), 19 deletions(-) create mode 100644 library/include/larra/bind.hpp diff --git a/library/include/larra/bind.hpp b/library/include/larra/bind.hpp new file mode 100644 index 0000000..ccc2a57 --- /dev/null +++ b/library/include/larra/bind.hpp @@ -0,0 +1,53 @@ +#pragma once +#include +#include + +#include +#include +#include + +namespace larra::xmpp::iq { + +struct Bind { + static constexpr auto kDefaultName = "bind"; + static constexpr auto kDefaultNamespace = "urn:ietf:params:xml:ns:xmpp-bind"; + + std::optional jid; + + friend constexpr auto operator<<(xmlpp::Element* element, const Bind& bind) { + element->set_attribute("xmlns", Bind::kDefaultNamespace); + + if(bind.jid) { + auto* jid_el = element->add_child_element("jid"); + jid_el->add_child_text(ToString(*bind.jid)); + } + } + [[nodiscard]] static constexpr auto Parse(xmlpp::Element* element) -> Bind { + const auto* jid_node = element->get_first_child("jid"); + if(!jid_node) { + SPDLOG_DEBUG("No Jid Node at Iq::Bind"); + return {}; + } + + auto* jid_el = dynamic_cast(jid_node); + if(!jid_el) { + throw std::runtime_error("dynamic_cast to const xmlpp::Element* failed"); + } + + const auto* text = jid_el->get_first_child_text(); + if(!jid_el) { + throw std::runtime_error("No text at Iq::Bind jid child"); + } + + return {.jid = (jid_node ? std::optional{FullJid::Parse(text->get_content())} : std::nullopt)}; + } +}; + +using SetBind = Set; +using ResultBind = Result; +using IqBind = Iq; + +inline auto MakeSetBind() { + return SetBind{.id = "1", .payload = Bind{}}; +} +} // namespace larra::xmpp::iq diff --git a/library/include/larra/iq.hpp b/library/include/larra/iq.hpp index bd7b291..5efd612 100644 --- a/library/include/larra/iq.hpp +++ b/library/include/larra/iq.hpp @@ -2,6 +2,7 @@ #include #include #include +#include #include namespace larra::xmpp { @@ -11,6 +12,8 @@ namespace iq { template struct BaseImplWithPayload { std::string id; + std::optional from{}; + std::optional to{}; PayloadType payload; static const inline std::string kName = Name; static constexpr auto kDefaultName = "iq"; @@ -19,16 +22,32 @@ struct BaseImplWithPayload { [[nodiscard]] constexpr auto Id(this Self&& self, std::string id) -> std::decay_t { return utils::FieldSetHelper::With<"id", BaseImplWithPayload>(std::forward(self), std::move(id)); } + template + [[nodiscard]] constexpr auto To(this Self&& self, std::string to) -> std::decay_t { + return utils::FieldSetHelper::With<"to", BaseImplWithPayload>(std::forward(self), std::move(to)); + } + template + [[nodiscard]] constexpr auto From(this Self&& self, std::string from) -> std::decay_t { + return utils::FieldSetHelper::With<"from", BaseImplWithPayload>(std::forward(self), std::move(from)); + } template [[nodiscard]] constexpr auto Payload(this Self&& self, NewPayloadType value) { return utils::FieldSetHelper::With<"payload", BaseImplWithPayload, false>(std::forward(self), std::move(value)); } friend constexpr auto operator<<(xmlpp::Element* element, const BaseImplWithPayload& self) { element->set_attribute("id", self.id); + + if (self.to) { + element->set_attribute("to", *self.to); + } + if (self.from) { + element->set_attribute("from", *self.from); + } element->set_attribute("type", kName); using S = Serialization; S::Serialize(element->add_child_element(S::kDefaultName, S::kPrefix), self.payload); } + [[nodiscard]] static constexpr auto Parse(xmlpp::Element* element) -> BaseImplWithPayload { auto node = element->get_attribute("type"); if(!node) { @@ -41,6 +60,9 @@ struct BaseImplWithPayload { if(!idNode) { throw std::runtime_error("Not found attribute id for parse Iq"); } + auto from = element->get_attribute("from"); + auto to = element->get_attribute("to"); + using S = Serialization; auto payload = element->get_first_child(S::kDefaultName); @@ -51,7 +73,11 @@ struct BaseImplWithPayload { if(!payload2) { throw std::runtime_error("Invalid payload for parse Iq"); } - return {.id = idNode->get_value(), .payload = S::Parse(payload2)}; + return { + .id = idNode->get_value(), + .from = (from ? std::optional{from->get_value()} : std::nullopt), + .to = (to ? std::optional{to->get_value()} : std::nullopt), + .payload = S::Parse(payload2)}; } }; static constexpr auto kGetName = "get"; 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 {