QXmpp  Version: 1.5.1
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 
15 namespace QXmpp {
16 
17 namespace 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  processHandleIqResult(
99  client,
100  iq.id(),
101  iq.from(),
102  e2eeMetadata,
103  invokeIqHandler(std::forward<Handler>(handler), std::move(iq)));
104  return true;
105  }
106  return false;
107  }
108 
109 } // namespace Private
110 
187 template<typename... IqTypes, typename Handler>
188 bool handleIqRequests(const QDomElement &element,
189  const std::optional<QXmppE2eeMetadata> &e2eeMetadata,
190  QXmppClient *client,
191  Handler handler)
192 {
193  if (auto [isRequest, tagName, xmlns] = Private::checkIsIqRequest(element); isRequest) {
194  return (Private::handleIqType<IqTypes>(handler, client, element, e2eeMetadata, tagName, xmlns) || ...);
195  }
196  return false;
197 }
198 
270 template<typename... IqTypes, typename Handler>
271 bool handleIqRequests(const QDomElement &element, QXmppClient *client, Handler handler)
272 {
273  return handleIqRequests<IqTypes...>(element, std::nullopt, client, std::forward<Handler>(handler));
274 }
275 
276 } // namespace QXmpp
277 
278 #endif // QXMPPIQHANDLING_H
The QXmppClient class is the main class for using QXmpp.
Definition: QXmppClient.h:84
The QXmppIq class is the base class for all IQs.
Definition: QXmppIq.h:23
void setType(QXmppIq::Type)
Definition: QXmppIq.cpp:61
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:927
Definition: QXmppTask.h:62
void then(QObject *context, Continuation continuation)
Definition: QXmppTask.h:101
bool handleIqRequests(const QDomElement &element, const std::optional< QXmppE2eeMetadata > &e2eeMetadata, QXmppClient *client, Handler handler)
Definition: QXmppIqHandling.h:188