QXmpp Version: 1.15.1
Loading...
Searching...
No Matches
QXmppIqHandling.h
1// SPDX-FileCopyrightText: 2022 Linus Jahn <lnj@kaidan.im>
2//
3// SPDX-License-Identifier: LGPL-2.1-or-later
4
5#ifndef QXMPPIQHANDLING_H
6#define QXMPPIQHANDLING_H
7
8#include "QXmppAsync_p.h"
9#include "QXmppClient.h"
10#include "QXmppE2eeMetadata.h"
11#include "QXmppIq.h"
12#include "QXmppUtils_p.h"
13#include "QXmppXmlTags_p.h"
14
15#include "StringLiterals.h"
16
17#include <QDomElement>
18
19namespace QXmpp {
20
21namespace Private {
22
23QXMPP_EXPORT void sendIqReply(QXmppClient *client,
24 const QString &requestId,
25 const QString &requestFrom,
26 const std::optional<QXmppE2eeMetadata> &e2eeMetadata,
27 QXmppIq &&iq);
28
29QXMPP_EXPORT std::tuple<bool, QString, QString> checkIsIqRequest(const QDomElement &el);
30
31template<typename... VariantTypes>
32void processHandleIqResult(QXmppClient *client,
33 const QString &requestId,
34 const QString &requestFrom,
35 const std::optional<QXmppE2eeMetadata> &e2eeMetadata,
36 std::variant<VariantTypes...> &&result)
37{
38 std::visit(
39 [&]<typename T>(T &&value) {
40 static_assert(
41 std::is_base_of_v<QXmppIq, T> || std::is_same_v<QXmppStanza::Error, T> || IsTask<T>,
42 "QXmppIq based type, QXmppStanza::Error or QXmppTask required");
43
44 if constexpr (std::is_base_of_v<QXmppIq, T>) {
45 sendIqReply(client, requestId, requestFrom, e2eeMetadata, std::move(value));
46 } else if constexpr (std::is_same_v<QXmppStanza::Error, T>) {
47 QXmppIq iq;
49 iq.setError(value);
50 sendIqReply(client, requestId, requestFrom, e2eeMetadata, std::move(iq));
51 } else if constexpr (IsTask<T>) {
52 value.then(client, [=](TaskValueType<T> &&v) {
53 processHandleIqResult(client, requestId, requestFrom, e2eeMetadata, std::move(v));
54 });
55 }
56 },
57 std::move(result));
58}
59
60template<typename T>
61void processHandleIqResult(QXmppClient *client,
62 const QString &requestId,
63 const QString &requestFrom,
64 const std::optional<QXmppE2eeMetadata> &e2eeMetadata,
65 QXmppTask<T> task)
66{
67 task.then(client, [client, requestId, requestFrom, e2eeMetadata](T result) {
68 processHandleIqResult(client, requestId, requestFrom, e2eeMetadata, result);
69 });
70}
71
72template<typename T, typename = std::enable_if_t<std::is_base_of_v<QXmppIq, T>, void>>
73void processHandleIqResult(QXmppClient *client,
74 const QString &requestId,
75 const QString &requestFrom,
76 const std::optional<QXmppE2eeMetadata> &e2eeMetadata,
77 T &&result)
78{
79 sendIqReply(client, requestId, requestFrom, e2eeMetadata, std::move(result));
80}
81
82template<typename Handler, typename IqType>
83auto invokeIqHandler(Handler handler, IqType &&iq)
84{
85 if constexpr (std::is_invocable<Handler, IqType &&>()) {
86 return handler(std::move(iq));
87 } else {
88 return handler->handleIq(std::move(iq));
89 }
90}
91
92template<typename IqType, typename Handler>
93bool handleIqType(Handler handler,
94 QXmppClient *client,
95 const QDomElement &element,
96 const std::optional<QXmppE2eeMetadata> &e2eeMetadata,
97 const QString &tagName,
98 const QString &xmlNamespace)
99{
100 if (isPayloadType<IqType>(std::tuple { tagName, xmlNamespace })) {
101 if (auto iq = parseElement<IqType>(element)) {
102 if constexpr (std::is_base_of_v<QXmppIq, IqType>) {
103 iq->setE2eeMetadata(e2eeMetadata);
104 }
105
106 processHandleIqResult(client, element.attribute(u"id"_s), element.attribute(u"from"_s), e2eeMetadata,
107 invokeIqHandler(std::forward<Handler>(handler), std::move(*iq)));
108 return true;
109 }
110 }
111 return false;
112}
113
114} // namespace Private
115
192template<typename... IqTypes, typename Handler>
193bool handleIqRequests(const QDomElement &element,
194 const std::optional<QXmppE2eeMetadata> &e2eeMetadata,
195 QXmppClient *client,
196 Handler handler)
197{
198 if (auto [isRequest, tagName, xmlns] = Private::checkIsIqRequest(element); isRequest) {
199 return (Private::handleIqType<IqTypes>(handler, client, element, e2eeMetadata, tagName, xmlns) || ...);
200 }
201 return false;
202}
203
275template<typename... IqTypes, typename Handler>
276bool handleIqRequests(const QDomElement &element, QXmppClient *client, Handler handler)
277{
278 return handleIqRequests<IqTypes...>(element, std::nullopt, client, std::forward<Handler>(handler));
279}
280
281} // namespace QXmpp
282
283#endif // QXMPPIQHANDLING_H
Main class for starting and managing connections to XMPP servers.
Definition QXmppClient.h:62
The QXmppIq class is the base class for all IQs.
Definition QXmppIq.h:23
void setType(QXmppIq::Type)
Definition QXmppIq.cpp:70
The Error class represents a stanza error.
Definition QXmppStanza.h:112
void setError(const QXmppStanza::Error &error)
Definition QXmppStanza.cpp:811
void setE2eeMetadata(const std::optional< QXmppE2eeMetadata > &e2eeMetadata)
Definition QXmppStanza.cpp:888
Definition QXmppTask.h:330
auto then(const QObject *context, Continuation continuation) -> QXmppTask< QXmpp::Private::InvokeContinuationResult< Continuation, T > >
Definition QXmppTask.h:453
Definition Algorithms.h:14
bool handleIqRequests(const QDomElement &element, const std::optional< QXmppE2eeMetadata > &e2eeMetadata, QXmppClient *client, Handler handler)
Definition QXmppIqHandling.h:193