From c5c197c5623746a7c7f075e9214f6ebca59061bb Mon Sep 17 00:00:00 2001 From: bqv Date: Sun, 20 Mar 2022 13:50:48 +0000 Subject: [PATCH] well hey it works --- connection.cpp | 44 +++++-------- xmpp/node.cpp | 8 +++ xmpp/node.hh | 164 +++++++++++++++++++++++++--------------------- xmpp/xep-0030.inl | 32 +++++++++ 4 files changed, 149 insertions(+), 99 deletions(-) create mode 100644 xmpp/xep-0030.inl diff --git a/connection.cpp b/connection.cpp index 82651f2..ae85420 100644 --- a/connection.cpp +++ b/connection.cpp @@ -103,17 +103,16 @@ int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void clientid = fmt::format("{}#{}", node, ver); - std::string to = binding.to ? binding.to->full : ""; - char *uuid = xmpp_uuid_gen(account->context); - - xmpp_stanza_t *children[2] = {NULL}; - children[0] = stanza__iq_query(account->context, NULL, - with_noop("http://jabber.org/protocol/disco#info"), NULL); - children[0] = stanza__iq(account->context, NULL, children, NULL, - uuid, to.size() ? strdup(to.data()) : NULL, - binding.from ? strdup(binding.from->full.data()) : NULL, strdup("get")); - xmpp_send(conn, children[0]); - xmpp_stanza_release(children[0]); + xmpp_send(conn, stanza::iq() + .from(binding.to ? binding.to->full : "") + .to(binding.from + .transform([](auto& x) { return x.full; }) + .value_or(std::string())) + .type("get") + .id(stanza::uuid(account->context)) + .query() + .build(account->context) + .get()); } channel = channel__search(account, binding.from->bare.data()); @@ -1170,21 +1169,14 @@ int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userd intext = xmpp_stanza_get_text(text); } - { - xmpp_stanza_t *children[2] = {0}; - char *uuid = xmpp_uuid_gen(account->context); - - children[0] = stanza__iq_query(account->context, NULL, - with_noop("http://jabber.org/protocol/disco#info"), NULL); - children[0] = - stanza__iq(account->context, NULL, children, - NULL, uuid, - strdup(to), strdup(jid), - strdup("get")); - - xmpp_send(conn, children[0]); - xmpp_stanza_release(children[0]); - } + xmpp_send(conn, stanza::iq() + .from(to) + .to(jid) + .type("get") + .id(stanza::uuid(account->context)) + .query() + .build(account->context) + .get()); if (weechat_strcasecmp(autojoin, "true") == 0) { char **command = weechat_string_dyn_alloc(256); diff --git a/xmpp/node.cpp b/xmpp/node.cpp index 368d2d1..64a4ca9 100644 --- a/xmpp/node.cpp +++ b/xmpp/node.cpp @@ -9,6 +9,14 @@ #include "ns.hh" #pragma GCC visibility pop +std::string stanza::uuid(xmpp_ctx_t *context) { + std::shared_ptr uuid { + xmpp_uuid_gen(context), + [=](auto x) { xmpp_free(context, x); } + }; + return uuid.get(); +} + std::string get_name(xmpp_stanza_t *stanza) { const char *result = NULL; result = xmpp_stanza_get_name(stanza); diff --git a/xmpp/node.hh b/xmpp/node.hh index bc5d3c2..758f400 100644 --- a/xmpp/node.hh +++ b/xmpp/node.hh @@ -44,6 +44,8 @@ public: bool is_bare() const; }; +class xmlns; + namespace xml { class node { @@ -77,7 +79,7 @@ namespace xml { return {}; } - template + template::value, int> = 0> inline std::vector> get_children(std::string_view name) { std::vector> list; @@ -85,7 +87,7 @@ namespace xml { std::back_inserter(list), [&](node& x) { return x.name == name - && x.ns == std::string_view(xmlns()); + && x.ns == std::string_view(X()); }); return list; } @@ -102,93 +104,109 @@ namespace xml { } }; - namespace builder { - template struct overloaded : Ts... { using Ts::operator()...; }; +} - class spec { - protected: - explicit spec(std::string_view tag): tag(tag) {} +namespace stanza { + template struct overloaded : Ts... { using Ts::operator()...; }; - void child(spec& ch) { - children.push_back(ch); - } + extern std::string uuid(xmpp_ctx_t *context); - void attr(std::string k, std::string_view v) { - attributes[k] = v; - } + class spec { + protected: + explicit spec(std::string_view tag): tag(tag) {} - inline void text(std::string_view s) { - children.push_back(std::string(s)); - } + void child(spec& ch) { + children.push_back(ch); + } - private: - const std::string tag; - std::map attributes; - std::vector> children; - - public: - std::shared_ptr build(xmpp_ctx_t *context) { - auto stanza = xmpp_stanza_new(context); - xmpp_stanza_set_name(stanza, tag.data()); - for (auto& at : attributes) { - xmpp_stanza_set_attribute(stanza, at.first.data(), at.second.data()); - } - for (auto& ch : children) { - std::visit(overloaded { - [&](spec& child) { - xmpp_stanza_add_child(stanza, child.build(context).get()); - }, - [&](std::string s) { - auto child = xmpp_stanza_new(context); - xmpp_stanza_set_text(child, s.data()); - xmpp_stanza_add_child(stanza, child); - xmpp_stanza_release(child); - } - }, ch); - } - return { stanza, &xmpp_stanza_release }; - } - }; + void attr(std::string k, std::string_view v) { + attributes[k] = v; + } - struct body : public spec { - body() : body("") {} - body(std::string_view s) : spec("body") { - text(s); + void text(std::string_view s) { + children.push_back(std::string(s)); + } + + template::value, int> = 0> + void xmlns() { + attr("xmlns", X().ns()); + } + + private: + const std::string tag; + std::map attributes; + std::vector> children; + + public: + std::shared_ptr build(xmpp_ctx_t *context) { + auto stanza = xmpp_stanza_new(context); + xmpp_stanza_set_name(stanza, tag.data()); + for (auto& at : attributes) { + xmpp_stanza_set_attribute(stanza, at.first.data(), at.second.data()); + } + for (auto& ch : children) { + std::visit(overloaded { + [&](spec& child) { + xmpp_stanza_add_child(stanza, child.build(context).get()); + }, + [&](std::string s) { + auto child = xmpp_stanza_new(context); + xmpp_stanza_set_text(child, s.data()); + xmpp_stanza_add_child(stanza, child); + xmpp_stanza_release(child); + } + }, ch); } - }; + return { stanza, &xmpp_stanza_release }; + } + }; +}; + +#include "xep-0027.inl" +#include "xep-0030.inl" +#include "xep-0045.inl" +#include "xep-0115.inl" +#include "xep-0319.inl" + +namespace stanza { + struct body : virtual public spec { + body() : body("") {} + body(std::string_view s) : spec("body") { + text(s); + } + }; - struct message : public spec { - message() : spec("message") {} + struct message : virtual public spec { + message() : spec("message") {} - message& id(std::string_view s) { attr("id", s); return *this; } - message& from(std::string_view s) { attr("from", s); return *this; } - message& to(std::string_view s) { attr("to", s); return *this; } - message& type(std::string_view s) { attr("type", s); return *this; } + message& id(std::string_view s) { attr("id", s); return *this; } + message& from(std::string_view s) { attr("from", s); return *this; } + message& to(std::string_view s) { attr("to", s); return *this; } + message& type(std::string_view s) { attr("type", s); return *this; } - message& body(builder::body b) { child(b); return *this; } - message& body(std::string_view s) { return body(builder::body(s)); } - }; + message& body(stanza::body b) { child(b); return *this; } + message& body(std::string_view s) { return body(stanza::body(s)); } + }; - struct presence : public spec { - presence() : spec("presence") {} - }; + struct presence : virtual public spec { + presence() : spec("presence") {} + }; - struct iq : public spec { - iq() : spec("iq") {} - }; + struct iq : virtual public spec, + public xep0030::iq { + iq() : spec("iq") {} - struct error : public spec { - error() : spec("error") {} - }; - } + iq& id(std::string_view s) { attr("id", s); return *this; } + iq& from(std::string_view s) { attr("from", s); return *this; } + iq& to(std::string_view s) { attr("to", s); return *this; } + iq& type(std::string_view s) { attr("type", s); return *this; } + }; + struct error : virtual public spec { + error() : spec("error") {} + }; } -#include "xep-0027.inl" -#include "xep-0045.inl" -#include "xep-0115.inl" -#include "xep-0319.inl" - namespace xml { class message : virtual public node, diff --git a/xmpp/xep-0030.inl b/xmpp/xep-0030.inl new file mode 100644 index 0000000..35dc626 --- /dev/null +++ b/xmpp/xep-0030.inl @@ -0,0 +1,32 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, version 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#pragma once + +#include +#include + +#include "node.hh" +#pragma GCC visibility push(default) +#include "ns.hh" +#pragma GCC visibility pop + +namespace stanza { + + /* Service Discovery */ + struct xep0030 { + struct query : virtual public spec { + query() : spec("query") { + xmlns(); + } + }; + + struct iq : virtual public spec { + iq() : spec("iq") {} + + iq& query(query q = xep0030::query()) { child(q); return *this; } + }; + }; + +}