QXmpp  Version: 1.8.1
QXmppOutgoingClient_p.h
1 // SPDX-FileCopyrightText: 2024 Linus Jahn <lnj@kaidan.im>
2 //
3 // SPDX-License-Identifier: LGPL-2.1-or-later
4 
5 #ifndef QXMPPOUTGOINGCLIENT_P_H
6 #define QXMPPOUTGOINGCLIENT_P_H
7 
8 #include "QXmppOutgoingClient.h"
9 #include "QXmppPromise.h"
10 #include "QXmppSaslManager_p.h"
11 #include "QXmppSasl_p.h"
12 #include "QXmppStreamError_p.h"
13 #include "QXmppStreamManagement_p.h"
14 
15 #include "XmppSocket.h"
16 
17 #include <QDnsLookup>
18 #include <QDomElement>
19 
20 class QTimer;
21 class QXmppPacket;
22 
23 // this leaks into other files, maybe better put QXmppOutgoingClientPrivate into QXmpp::Private
24 using namespace QXmpp::Private;
25 
26 namespace QXmpp::Private {
27 
28 using LegacyError = std::variant<QAbstractSocket::SocketError, QXmpp::TimeoutError, QXmppStanza::Error::Condition>;
29 
30 // STARTTLS
31 class StarttlsManager
32 {
33 public:
34  QXmppTask<void> task() { return m_promise.task(); }
35  HandleElementResult handleElement(const QDomElement &el);
36 
37 private:
38  QXmppPromise<void> m_promise;
39 };
40 
41 struct ProtocolError {
42  QString text;
43 };
44 
45 struct BoundAddress {
46  QString user;
47  QString domain;
48  QString resource;
49 };
50 
51 // Resource Binding
52 class BindManager
53 {
54 public:
55  using Result = std::variant<BoundAddress, QXmppStanza::Error, ProtocolError>;
56 
57  explicit BindManager(SendDataInterface *socket) : m_socket(socket) { }
58 
59  QXmppTask<Result> bindAddress(const QString &resource);
60  HandleElementResult handleElement(const QDomElement &el);
61 
62 private:
63  SendDataInterface *m_socket;
64  QString m_iqId;
65  std::optional<QXmppPromise<Result>> m_promise;
66 };
67 
68 struct NonSaslAuthOptions {
69  bool plain;
70  bool digest;
71 };
72 
73 // Authentication using Non-SASL auth
74 class NonSaslAuthManager
75 {
76 public:
77  using OptionsResult = std::variant<NonSaslAuthOptions, QXmppError>;
78  using AuthResult = std::variant<Success, QXmppError>;
79 
80  explicit NonSaslAuthManager(SendDataInterface *socket) : m_socket(socket) { }
81 
82  QXmppTask<OptionsResult> queryOptions(const QString &streamFrom, const QString &username);
83  QXmppTask<AuthResult> authenticate(bool plainText, const QString &username, const QString &password, const QString &resource, const QString &streamId);
84  HandleElementResult handleElement(const QDomElement &el);
85 
86 private:
87  struct NoQuery {
88  };
89  struct OptionsQuery {
91  };
92  struct AuthQuery {
94  QString id;
95  };
96 
97  SendDataInterface *m_socket;
98  std::variant<NoQuery, OptionsQuery, AuthQuery> m_query;
99 };
100 
101 // XEP-0199: XMPP Ping
102 class PingManager
103 {
104 public:
105  explicit PingManager(QXmppOutgoingClient *q);
106 
107  void onDataReceived();
108 
109 private:
110  void sendPing();
111 
112  QXmppOutgoingClient *q;
113  QTimer *pingTimer;
114  QTimer *timeoutTimer;
115 };
116 
117 using IqResult = QXmppOutgoingClient::IqResult;
118 
119 struct IqState {
120  QXmppPromise<IqResult> interface;
121  QString jid;
122 };
123 
124 // Manager for creating tasks for outgoing IQ requests
125 class OutgoingIqManager
126 {
127 public:
128  OutgoingIqManager(QXmppLoggable *l, StreamAckManager &streamAckMananger);
129  ~OutgoingIqManager();
130 
131  QXmppTask<IqResult> sendIq(QXmppIq &&, const QString &to);
132  QXmppTask<IqResult> sendIq(QXmppPacket &&, const QString &id, const QString &to);
133 
134  bool hasId(const QString &id) const;
135  bool isIdValid(const QString &id) const;
136 
137  QXmppTask<IqResult> start(const QString &id, const QString &to);
138  void finish(const QString &id, IqResult &&result);
139  void cancelAll();
140 
141  void onSessionOpened(const SessionBegin &);
142  void onSessionClosed(const SessionEnd &);
143  bool handleStanza(const QDomElement &stanza);
144 
145 private:
146  void warning(const QString &message);
147 
148  QXmppLoggable *l;
149  StreamAckManager &m_streamAckManager;
150  std::unordered_map<QString, IqState> m_requests;
151 };
152 
153 } // namespace QXmpp::Private
154 
155 class QXmppOutgoingClientPrivate
156 {
157 public:
158  struct Error {
159  QString text;
160  QXmppOutgoingClient::ConnectionError details;
161  LegacyError legacyError;
162  };
163 
164  explicit QXmppOutgoingClientPrivate(QXmppOutgoingClient *q);
165  void connectToHost(const ServerAddress &);
166  void connectToAddressList(std::vector<ServerAddress> &&);
167  void connectToNextAddress();
168 
169  // This object provides the configuration
170  // required for connecting to the XMPP server.
171  QXmppConfiguration config;
172  std::optional<Error> error;
173 
174  // Core stream
175  XmppSocket socket;
176  StreamAckManager streamAckManager;
177  OutgoingIqManager iqManager;
178 
179  // DNS
180  std::vector<ServerAddress> serverAddresses;
181  std::size_t nextServerAddressIndex = 0;
182  enum {
183  Current,
184  TryNext,
185  } nextAddressState = Current;
186 
187  // Stream
188  QString streamId;
189  QString streamFrom;
190  QString streamVersion;
191 
192  // Redirection
193  std::optional<StreamErrorElement::SeeOtherHost> redirect;
194 
195  // Authentication & Session
196  bool isAuthenticated = false;
197  bool bindModeAvailable = false;
198  bool sessionStarted = false;
199  AuthenticationMethod authenticationMethod = AuthenticationMethod::Sasl;
200  std::optional<Bind2Bound> bind2Bound;
201 
202  std::variant<QXmppOutgoingClient *, StarttlsManager, NonSaslAuthManager, SaslManager, Sasl2Manager, C2sStreamManager *, BindManager> listener;
203  FastTokenManager fastTokenManager;
204  C2sStreamManager c2sStreamManager;
205  CarbonManager carbonManager;
206  CsiManager csiManager;
207  PingManager pingManager;
208 
209  template<typename T, typename... Args>
210  T &setListener(Args... args)
211  {
212  listener = T { args... };
213  return std::get<T>(listener);
214  }
215 
216 private:
217  QXmppOutgoingClient *q;
218 };
219 
220 #endif // QXMPPOUTGOINGCLIENT_P_H
The QXmppConfiguration class holds configuration options.
Definition: QXmppConfiguration.h:36
The QXmppLoggable class represents a source of logging messages.
Definition: QXmppLogger.h:109
Definition: QXmppTask.h:61
The QXmppIq class is the base class for all IQs.
Definition: QXmppIq.h:22
Definition: Algorithms.h:12