QXmpp Version: 1.10.4
 
Loading...
Searching...
No Matches
QXmppOutgoingClient.h
1// SPDX-FileCopyrightText: 2010 Manjeet Dahiya <manjeetdahiya@gmail.com>
2// SPDX-FileCopyrightText: 2010 Jeremy Lainé <jeremy.laine@m4x.org>
3// SPDX-FileCopyrightText: 2020 Linus Jahn <lnj@kaidan.im>
4//
5// SPDX-License-Identifier: LGPL-2.1-or-later
6
7#ifndef QXMPPOUTGOINGCLIENT_H
8#define QXMPPOUTGOINGCLIENT_H
9
10#include "QXmppAuthenticationError.h"
11#include "QXmppBindError.h"
12#include "QXmppClient.h"
13#include "QXmppPromise.h"
14#include "QXmppStanza.h"
15#include "QXmppStreamError.h"
16
17#include <QAbstractSocket>
18
19class QDomElement;
20class QSslError;
21class QSslSocket;
22
24class QXmppPresence;
25class QXmppIq;
26class QXmppMessage;
28class QXmppOutgoingClientPrivate;
29class TestClient;
30
31namespace QXmpp::Private {
32class C2sStreamManager;
33class CarbonManager;
34class CsiManager;
35class OutgoingIqManager;
36class PingManager;
37class SendDataInterface;
38class StreamAckManager;
39class XmppSocket;
40struct Bind2Request;
41struct Bind2Bound;
42struct SmEnabled;
43struct SmFailed;
44struct SmResumed;
45struct StreamErrorElement;
46
47enum HandleElementResult {
48 Accepted,
49 Rejected,
50 Finished,
51};
52
53enum class AuthenticationMethod {
54 NonSasl,
55 Sasl,
56 Sasl2,
57};
58
59struct SessionBegin {
60 bool smEnabled;
61 bool smResumed;
62 bool bind2Used;
63 bool fastTokenChanged;
64 AuthenticationMethod authenticationMethod;
65};
66
67struct SessionEnd {
68 bool smCanResume;
69};
70} // namespace QXmpp::Private
71
72namespace QXmpp::Private::Sasl2 {
73struct Authenticate;
74struct StreamFeature;
75struct Success;
76} // namespace QXmpp::Private::Sasl2
77
78// The QXmppOutgoingClient class represents an outgoing XMPP stream to an XMPP server.
79class QXMPP_EXPORT QXmppOutgoingClient : public QXmppLoggable
80{
81 Q_OBJECT
82
83public:
84 using IqResult = std::variant<QDomElement, QXmppError>;
85 using ConnectionError = std::variant<QAbstractSocket::SocketError, QXmpp::TimeoutError, QXmpp::StreamError, QXmpp::AuthenticationError, QXmpp::BindError>;
86 static constexpr QStringView TaskName = u"client session";
87
88 explicit QXmppOutgoingClient(QObject *parent);
89 ~QXmppOutgoingClient() override;
90
91 void connectToHost();
92 void disconnectFromHost();
93 bool isAuthenticated() const;
94 bool isConnected() const;
95 QXmppTask<IqResult> sendIq(QXmppIq &&);
96
98 QSslSocket *socket() const;
99 QXmppStanza::Error::Condition xmppStreamError();
100
101 QXmppConfiguration &configuration();
102
103 QXmpp::Private::XmppSocket &xmppSocket() const;
104 QXmpp::Private::StreamAckManager &streamAckManager() const;
105 QXmpp::Private::OutgoingIqManager &iqManager() const;
106 QXmpp::Private::C2sStreamManager &c2sStreamManager() const;
107 QXmpp::Private::CarbonManager &carbonManager() const;
108 QXmpp::Private::CsiManager &csiManager() const;
109
111 Q_SIGNAL void connected(const QXmpp::Private::SessionBegin &);
112
114 Q_SIGNAL void disconnected(const QXmpp::Private::SessionEnd &);
115
117 Q_SIGNAL void errorOccurred(const QString &text, const QXmppOutgoingClient::ConnectionError &details, QXmppClient::Error oldError);
118
120 Q_SIGNAL void elementReceived(const QDomElement &element, bool &handled);
121
123 Q_SIGNAL void presenceReceived(const QXmppPresence &);
124
126 Q_SIGNAL void messageReceived(const QXmppMessage &);
127
130 Q_SIGNAL void iqReceived(const QXmppIq &);
131
133 Q_SIGNAL void sslErrors(const QList<QSslError> &errors);
134
135private:
136 void handleStart();
137 void handleStream(const QDomElement &element);
138 void handlePacketReceived(const QDomElement &element);
139 QXmpp::Private::HandleElementResult handleElement(const QDomElement &nodeRecv);
140 void handleStreamFeatures(const QXmppStreamFeatures &features);
141 void handleStreamError(const QXmpp::Private::StreamErrorElement &streamError);
142 bool handleStanza(const QDomElement &);
143 bool handleStarttls(const QXmppStreamFeatures &features);
144
145 void _q_socketDisconnected();
146 void socketError(QAbstractSocket::SocketError);
147 void socketSslErrors(const QList<QSslError> &);
148
149 void startSasl2Auth(const QXmpp::Private::Sasl2::StreamFeature &sasl2Feature);
150 void startNonSaslAuth();
151 void startSmResume();
152 void startSmEnable();
153 void startResourceBinding();
154 void openSession();
155 void closeSession();
156 void setError(const QString &text, ConnectionError &&details);
157 void throwKeepAliveError();
158
159 // for unit tests, see TestClient
160 void enableStreamManagement(bool resetSequenceNumber);
161 bool handleIqResponse(const QDomElement &);
162
163 friend class QXmppOutgoingClientPrivate;
164 friend class QXmpp::Private::PingManager;
165 friend class QXmpp::Private::C2sStreamManager;
166 friend class QXmppRegistrationManager;
167 friend class TestClient;
168
169 const std::unique_ptr<QXmppOutgoingClientPrivate> d;
170};
171
172namespace QXmpp::Private {
173
174class C2sStreamManager
175{
176public:
177 using Result = std::variant<Success, QXmppError>;
178 static constexpr QStringView TaskName = u"stream management";
179
180 explicit C2sStreamManager(QXmppOutgoingClient *q);
181
182 HandleElementResult handleElement(const QDomElement &);
183 bool hasResumeAddress() const { return m_canResume && !m_resumeHost.isEmpty() && m_resumePort; }
184 std::pair<QString, quint16> resumeAddress() const { return { m_resumeHost, m_resumePort }; }
185 void onStreamStart();
186 void onStreamFeatures(const QXmppStreamFeatures &);
187 void onStreamClosed();
188 void onSasl2Authenticate(Sasl2::Authenticate &auth, const Sasl2::StreamFeature &feature);
189 void onSasl2Success(const Sasl2::Success &success);
190 void onBind2Request(Bind2Request &request, const std::vector<QString> &bind2Features);
191 void onBind2Bound(const Bind2Bound &);
192 bool canResume() const { return m_canResume; }
193 bool enabled() const { return m_enabled; }
194 bool streamResumed() const { return m_streamResumed; }
195 bool canRequestResume() const { return m_smAvailable && !m_enabled && m_canResume; }
196 QXmppTask<void> requestResume();
197 bool canRequestEnable() const { return m_smAvailable && !m_enabled; }
198 QXmppTask<void> requestEnable();
199 bool hasOngoingRequest() const { return !std::holds_alternative<NoRequest>(m_request); }
200
201private:
202 friend class ::TestClient;
203
204 void onEnabled(const SmEnabled &enabled);
205 void onEnableFailed(const SmFailed &failed);
206 void onResumed(const SmResumed &resumed);
207 void onResumeFailed(const SmFailed &failed);
208 bool setResumeAddress(const QString &address);
209 void setEnabled(bool enabled) { m_enabled = enabled; }
210 void setResumed(bool resumed) { m_streamResumed = resumed; }
211
212 struct NoRequest { };
213 struct ResumeRequest {
214 QXmppPromise<void> p;
215 };
216 struct EnableRequest {
217 QXmppPromise<void> p;
218 };
219
220 QXmppOutgoingClient *q;
221
222 std::variant<NoRequest, ResumeRequest, EnableRequest> m_request;
223 bool m_smAvailable = false;
224 QString m_smId;
225 bool m_canResume = false;
226 QString m_resumeHost;
227 quint16 m_resumePort = 0;
228 bool m_enabled = false;
229 bool m_streamResumed = false;
230};
231
232// XEP-0280: Message Carbons
233class CarbonManager
234{
235public:
236 void setEnableViaBind2(bool enable) { m_enableViaBind2 = enable; }
237 bool enabled() const { return m_enabled; }
238 void onBind2Request(Bind2Request &request, const std::vector<QString> &bind2Features);
239 void onSessionOpened(const SessionBegin &session);
240
241private:
242 // whether to enable carbons via bind2 if available
243 bool m_enableViaBind2 = false;
244 // whether carbons have been enabled via bind2
245 bool m_enabled = false;
246 bool m_requested = false;
247};
248
249// XEP-0352: Client State Indication
250class CsiManager
251{
252public:
253 enum State {
254 Active,
255 Inactive,
256 };
257
258 explicit CsiManager(QXmppOutgoingClient *client);
259
260 State state() const { return m_state; }
261 void setState(State);
262 void onSessionOpened(const SessionBegin &);
263 void onStreamFeatures(const QXmppStreamFeatures &);
264 void onBind2Request(Bind2Request &request, const std::vector<QString> &bind2Features);
265
266private:
267 void sendState();
268
269 QXmppOutgoingClient *m_client;
270 State m_state = Active;
271 bool m_synced = true;
272 bool m_featureAvailable = false;
273 bool m_bind2InactiveSet = false;
274};
275
276} // namespace QXmpp::Private
277
278#endif // QXMPPOUTGOINGCLIENT_H
Error
Definition QXmppClient.h:76
The QXmppConfiguration class holds configuration options.
Definition QXmppConfiguration.h:37
The QXmppIq class is the base class for all IQs.
Definition QXmppIq.h:23
The QXmppLoggable class represents a source of logging messages.
Definition QXmppLogger.h:110
The QXmppMessage class represents an XMPP message.
Definition QXmppMessage.h:64
The QXmppPresence class represents an XMPP presence stanza.
Definition QXmppPresence.h:22
Condition
A detailed condition of the error.
Definition QXmppStanza.h:110
The QXmppStreamFeatures class represents the features returned by an XMPP server or client.
Definition QXmppStreamFeatures.h:23