QXmpp: QXmppOutgoingClient.h Source File

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