QXmpp Version: 1.10.0
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 "QXmppClient.h"
9#include "QXmppE2eeMetadata.h"
10#include "QXmppFutureUtils_p.h"
11#include "QXmppIq.h"
12
13#include <QDomElement>
14
15namespace QXmpp {
16
17namespace Private {
18
19 QXMPP_EXPORT void sendIqReply(QXmppClient *client,
20 const QString &requestId,
21 const QString &requestFrom,
22 const std::optional<QXmppE2eeMetadata> &e2eeMetadata,
23 QXmppIq &&iq);
24
25 QXMPP_EXPORT std::tuple<bool, QString, QString> checkIsIqRequest(const QDomElement &el);
26
27 template<typename... VariantTypes>
28 void processHandleIqResult(QXmppClient *client,
29 const QString &requestId,
30 const QString &requestFrom,
31 const std::optional<QXmppE2eeMetadata> &e2eeMetadata,
32 std::variant<VariantTypes...> &&result)
33 {
34 std::visit([&](auto &&value) {
35 using T = std::decay_t<decltype(value)>;
36
37 static_assert(
38 std::is_base_of_v<QXmppIq, T> || std::is_same_v<QXmppStanza::Error, T>,
39 "QXmppIq based type or QXmppStanza::Error required");
40
41 if constexpr (std::is_base_of_v<QXmppIq, T>) {
42 sendIqReply(client, requestId, requestFrom, e2eeMetadata, std::move(value));
43 } else if constexpr (std::is_same_v<QXmppStanza::Error, T>) {
44 QXmppIq iq;
46 iq.setError(value);
47 sendIqReply(client, requestId, requestFrom, e2eeMetadata, std::move(iq));
48 }
49 },
50 std::move(result));
51 }
52
53 template<typename T>
54 void processHandleIqResult(QXmppClient *client,
55 const QString &requestId,
56 const QString &requestFrom,
57 const std::optional<QXmppE2eeMetadata> &e2eeMetadata,
58 QXmppTask<T> future)
59 {
60 future.then(client, [client, requestId, requestFrom, e2eeMetadata](T result) {
61 processHandleIqResult(client, requestId, requestFrom, e2eeMetadata, result);
62 });
63 }
64
65 template<typename T, typename = std::enable_if_t<std::is_base_of_v<QXmppIq, T>, void>>
66 void processHandleIqResult(QXmppClient *client,
67 const QString &requestId,
68 const QString &requestFrom,
69 const std::optional<QXmppE2eeMetadata> &e2eeMetadata,
70 T &&result)
71 {
72 sendIqReply(client, requestId, requestFrom, e2eeMetadata, std::move(result));
73 }
74
75 template<typename Handler, typename IqType>
76 auto invokeIqHandler(Handler handler, IqType &&iq)
77 {
78 if constexpr (std::is_invocable<Handler, IqType &&>()) {
79 return handler(std::move(iq));
80 } else {
81 return handler->handleIq(std::move(iq));
82 }
83 }
84
85 template<typename IqType, typename Handler>
86 bool handleIqType(Handler handler,
87 QXmppClient *client,
88 const QDomElement &element,
89 const std::optional<QXmppE2eeMetadata> &e2eeMetadata,
90 const QString &tagName,
91 const QString &xmlNamespace)
92 {
93 if (IqType::checkIqType(tagName, xmlNamespace)) {
94 IqType iq;
95 iq.parse(element);
96 iq.setE2eeMetadata(e2eeMetadata);
97
98 auto id = iq.id(), from = iq.from();
99
100 processHandleIqResult(client, id, from, e2eeMetadata,
101 invokeIqHandler(std::forward<Handler>(handler), std::move(iq)));
102 return true;
103 }
104 return false;
105 }
106
107} // namespace Private
108
185template<typename... IqTypes, typename Handler>
186bool handleIqRequests(const QDomElement &element,
187 const std::optional<QXmppE2eeMetadata> &e2eeMetadata,
188 QXmppClient *client,
189 Handler handler)
190{
191 if (auto [isRequest, tagName, xmlns] = Private::checkIsIqRequest(element); isRequest) {
192 return (Private::handleIqType<IqTypes>(handler, client, element, e2eeMetadata, tagName, xmlns) || ...);
193 }
194 return false;
195}
196
268template<typename... IqTypes, typename Handler>
269bool handleIqRequests(const QDomElement &element, QXmppClient *client, Handler handler)
270{
271 return handleIqRequests<IqTypes...>(element, std::nullopt, client, std::forward<Handler>(handler));
272}
273
274} // namespace QXmpp
275
276#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:65
virtual void parse(const QDomElement &)=0
The Error class represents a stanza error.
Definition: QXmppStanza.h:94
void setError(const QXmppStanza::Error &error)
Definition: QXmppStanza.cpp:928
Definition: QXmppTask.h:62
void then(const QObject *context, Continuation continuation)
Definition: QXmppTask.h:101
Definition: Algorithms.h:12
bool handleIqRequests(const QDomElement &element, const std::optional< QXmppE2eeMetadata > &e2eeMetadata, QXmppClient *client, Handler handler)
Definition: QXmppIqHandling.h:186