QXmpp  Version: 1.7.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  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 
185 template<typename... IqTypes, typename Handler>
186 bool 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 
268 template<typename... IqTypes, typename Handler>
269 bool 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
The QXmppClient class is the main class for using QXmpp.
Definition: QXmppClient.h:85
The QXmppIq class is the base class for all IQs.
Definition: QXmppIq.h:23
void setType(QXmppIq::Type)
Definition: QXmppIq.cpp:63
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:926
Definition: QXmppTask.h:62
void then(const QObject *context, Continuation continuation)
Definition: QXmppTask.h:101
Definition: Algorithms.h:10
bool handleIqRequests(const QDomElement &element, const std::optional< QXmppE2eeMetadata > &e2eeMetadata, QXmppClient *client, Handler handler)
Definition: QXmppIqHandling.h:186