QXmpp Version: 1.12.0
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([&](auto &&value) {
39 using T = std::decay_t<decltype(value)>;
40
41 static_assert(
42 std::is_base_of_v<QXmppIq, T> || std::is_same_v<QXmppStanza::Error, T>,
43 "QXmppIq based type or QXmppStanza::Error required");
44
45 if constexpr (std::is_base_of_v<QXmppIq, T>) {
46 sendIqReply(client, requestId, requestFrom, e2eeMetadata, std::move(value));
47 } else if constexpr (std::is_same_v<QXmppStanza::Error, T>) {
48 QXmppIq iq;
50 iq.setError(value);
51 sendIqReply(client, requestId, requestFrom, e2eeMetadata, std::move(iq));
52 }
53 },
54 std::move(result));
55}
56
57template<typename T>
58void processHandleIqResult(QXmppClient *client,
59 const QString &requestId,
60 const QString &requestFrom,
61 const std::optional<QXmppE2eeMetadata> &e2eeMetadata,
62 QXmppTask<T> future)
63{
64 future.then(client, [client, requestId, requestFrom, e2eeMetadata](T result) {
65 processHandleIqResult(client, requestId, requestFrom, e2eeMetadata, result);
66 });
67}
68
69template<typename T, typename = std::enable_if_t<std::is_base_of_v<QXmppIq, T>, void>>
70void processHandleIqResult(QXmppClient *client,
71 const QString &requestId,
72 const QString &requestFrom,
73 const std::optional<QXmppE2eeMetadata> &e2eeMetadata,
74 T &&result)
75{
76 sendIqReply(client, requestId, requestFrom, e2eeMetadata, std::move(result));
77}
78
79template<typename Handler, typename IqType>
80auto invokeIqHandler(Handler handler, IqType &&iq)
81{
82 if constexpr (std::is_invocable<Handler, IqType &&>()) {
83 return handler(std::move(iq));
84 } else {
85 return handler->handleIq(std::move(iq));
86 }
87}
88
89template<typename IqType, typename Handler>
90bool handleIqType(Handler handler,
91 QXmppClient *client,
92 const QDomElement &element,
93 const std::optional<QXmppE2eeMetadata> &e2eeMetadata,
94 const QString &tagName,
95 const QString &xmlNamespace)
96{
97 if (isPayloadType<IqType>(std::tuple { tagName, xmlNamespace })) {
98 if (auto iq = parseElement<IqType>(element)) {
99 if constexpr (std::is_base_of_v<QXmppIq, IqType>) {
100 iq->setE2eeMetadata(e2eeMetadata);
101 }
102
103 processHandleIqResult(client, element.attribute(u"id"_s), element.attribute(u"from"_s), e2eeMetadata,
104 invokeIqHandler(std::forward<Handler>(handler), std::move(*iq)));
105 return true;
106 }
107 }
108 return false;
109}
110
111} // namespace Private
112
189template<typename... IqTypes, typename Handler>
190bool handleIqRequests(const QDomElement &element,
191 const std::optional<QXmppE2eeMetadata> &e2eeMetadata,
192 QXmppClient *client,
193 Handler handler)
194{
195 if (auto [isRequest, tagName, xmlns] = Private::checkIsIqRequest(element); isRequest) {
196 return (Private::handleIqType<IqTypes>(handler, client, element, e2eeMetadata, tagName, xmlns) || ...);
197 }
198 return false;
199}
200
272template<typename... IqTypes, typename Handler>
273bool handleIqRequests(const QDomElement &element, QXmppClient *client, Handler handler)
274{
275 return handleIqRequests<IqTypes...>(element, std::nullopt, client, std::forward<Handler>(handler));
276}
277
278} // namespace QXmpp
279
280#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:96
void setError(const QXmppStanza::Error &error)
Definition QXmppStanza.cpp:772
void setE2eeMetadata(const std::optional< QXmppE2eeMetadata > &e2eeMetadata)
Definition QXmppStanza.cpp:849
Definition QXmppTask.h:46
void then(const QObject *context, Continuation continuation)
Definition QXmppTask.h:89
Definition Algorithms.h:14
bool handleIqRequests(const QDomElement &element, const std::optional< QXmppE2eeMetadata > &e2eeMetadata, QXmppClient *client, Handler handler)
Definition QXmppIqHandling.h:190