1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtNetwork module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#ifndef QSOCKS5SOCKETENGINE_P_H
41#define QSOCKS5SOCKETENGINE_P_H
42
43//
44// W A R N I N G
45// -------------
46//
47// This file is not part of the Qt API. It exists purely as an
48// implementation detail. This header file may change from version to
49// version without notice, or even be removed.
50//
51// We mean it.
52//
53
54#include <QtNetwork/private/qtnetworkglobal_p.h>
55#include "qabstractsocketengine_p.h"
56#include "qnetworkproxy.h"
57
58QT_REQUIRE_CONFIG(socks5);
59
60QT_BEGIN_NAMESPACE
61
62class QSocks5SocketEnginePrivate;
63
64class Q_AUTOTEST_EXPORT QSocks5SocketEngine : public QAbstractSocketEngine
65{
66 Q_OBJECT
67public:
68 QSocks5SocketEngine(QObject *parent = nullptr);
69 ~QSocks5SocketEngine();
70
71 bool initialize(QAbstractSocket::SocketType type, QAbstractSocket::NetworkLayerProtocol protocol = QAbstractSocket::IPv4Protocol) override;
72 bool initialize(qintptr socketDescriptor, QAbstractSocket::SocketState socketState = QAbstractSocket::ConnectedState) override;
73
74 void setProxy(const QNetworkProxy &networkProxy);
75
76 qintptr socketDescriptor() const override;
77
78 bool isValid() const override;
79
80 bool connectInternal();
81 bool connectToHost(const QHostAddress &address, quint16 port) override;
82 bool connectToHostByName(const QString &name, quint16 port) override;
83 bool bind(const QHostAddress &address, quint16 port) override;
84 bool listen() override;
85 int accept() override;
86 void close() override;
87
88 qint64 bytesAvailable() const override;
89
90 qint64 read(char *data, qint64 maxlen) override;
91 qint64 write(const char *data, qint64 len) override;
92
93#ifndef QT_NO_UDPSOCKET
94#ifndef QT_NO_NETWORKINTERFACE
95 bool joinMulticastGroup(const QHostAddress &groupAddress,
96 const QNetworkInterface &interface) override;
97 bool leaveMulticastGroup(const QHostAddress &groupAddress,
98 const QNetworkInterface &interface) override;
99 QNetworkInterface multicastInterface() const override;
100 bool setMulticastInterface(const QNetworkInterface &iface) override;
101#endif // QT_NO_NETWORKINTERFACE
102
103 bool hasPendingDatagrams() const override;
104 qint64 pendingDatagramSize() const override;
105#endif // QT_NO_UDPSOCKET
106
107 qint64 readDatagram(char *data, qint64 maxlen, QIpPacketHeader * = nullptr,
108 PacketHeaderOptions = WantNone) override;
109 qint64 writeDatagram(const char *data, qint64 len, const QIpPacketHeader &) override;
110 qint64 bytesToWrite() const override;
111
112 int option(SocketOption option) const override;
113 bool setOption(SocketOption option, int value) override;
114
115 bool waitForRead(int msecs = 30000, bool *timedOut = nullptr) override;
116 bool waitForWrite(int msecs = 30000, bool *timedOut = nullptr) override;
117 bool waitForReadOrWrite(bool *readyToRead, bool *readyToWrite,
118 bool checkRead, bool checkWrite,
119 int msecs = 30000, bool *timedOut = nullptr) override;
120
121 bool isReadNotificationEnabled() const override;
122 void setReadNotificationEnabled(bool enable) override;
123 bool isWriteNotificationEnabled() const override;
124 void setWriteNotificationEnabled(bool enable) override;
125 bool isExceptionNotificationEnabled() const override;
126 void setExceptionNotificationEnabled(bool enable) override;
127
128private:
129 Q_DECLARE_PRIVATE(QSocks5SocketEngine)
130 Q_DISABLE_COPY_MOVE(QSocks5SocketEngine)
131 Q_PRIVATE_SLOT(d_func(), void _q_controlSocketConnected())
132 Q_PRIVATE_SLOT(d_func(), void _q_controlSocketReadNotification())
133 Q_PRIVATE_SLOT(d_func(), void _q_controlSocketErrorOccurred(QAbstractSocket::SocketError))
134#ifndef QT_NO_UDPSOCKET
135 Q_PRIVATE_SLOT(d_func(), void _q_udpSocketReadNotification())
136#endif
137 Q_PRIVATE_SLOT(d_func(), void _q_controlSocketBytesWritten())
138 Q_PRIVATE_SLOT(d_func(), void _q_emitPendingReadNotification())
139 Q_PRIVATE_SLOT(d_func(), void _q_emitPendingWriteNotification())
140 Q_PRIVATE_SLOT(d_func(), void _q_emitPendingConnectionNotification())
141 Q_PRIVATE_SLOT(d_func(), void _q_controlSocketDisconnected())
142 Q_PRIVATE_SLOT(d_func(), void _q_controlSocketStateChanged(QAbstractSocket::SocketState))
143
144};
145
146
147class QTcpSocket;
148
149class QSocks5Authenticator
150{
151public:
152 QSocks5Authenticator();
153 virtual ~QSocks5Authenticator();
154 virtual char methodId();
155 virtual bool beginAuthenticate(QTcpSocket *socket, bool *completed);
156 virtual bool continueAuthenticate(QTcpSocket *socket, bool *completed);
157
158 virtual bool seal(const QByteArray &buf, QByteArray *sealedBuf);
159 virtual bool unSeal(const QByteArray &sealedBuf, QByteArray *buf);
160 virtual bool unSeal(QTcpSocket *sealedSocket, QByteArray *buf);
161
162 virtual QString errorString() { return QString(); }
163};
164
165class QSocks5PasswordAuthenticator : public QSocks5Authenticator
166{
167public:
168 QSocks5PasswordAuthenticator(const QString &userName, const QString &password);
169 char methodId() override;
170 bool beginAuthenticate(QTcpSocket *socket, bool *completed) override;
171 bool continueAuthenticate(QTcpSocket *socket, bool *completed) override;
172
173 QString errorString() override;
174
175private:
176 QString userName;
177 QString password;
178};
179
180struct QSocks5Data;
181struct QSocks5ConnectData;
182struct QSocks5UdpAssociateData;
183struct QSocks5BindData;
184
185class QSocks5SocketEnginePrivate : public QAbstractSocketEnginePrivate
186{
187 Q_DECLARE_PUBLIC(QSocks5SocketEngine)
188public:
189 QSocks5SocketEnginePrivate();
190 ~QSocks5SocketEnginePrivate();
191
192 enum Socks5State
193 {
194 Uninitialized = 0,
195 ConnectError,
196 AuthenticationMethodsSent,
197 Authenticating,
198 AuthenticatingError,
199 RequestMethodSent,
200 RequestError,
201 Connected,
202 UdpAssociateSuccess,
203 BindSuccess,
204 ControlSocketError,
205 SocksError,
206 HostNameLookupError
207 };
208 Socks5State socks5State;
209
210 enum Socks5Mode
211 {
212 NoMode,
213 ConnectMode,
214 BindMode,
215 UdpAssociateMode
216 };
217 Socks5Mode mode;
218
219 enum Socks5Error
220 {
221 SocksFailure = 0x01,
222 ConnectionNotAllowed = 0x02,
223 NetworkUnreachable = 0x03,
224 HostUnreachable = 0x04,
225 ConnectionRefused = 0x05,
226 TTLExpired = 0x06,
227 CommandNotSupported = 0x07,
228 AddressTypeNotSupported = 0x08,
229 LastKnownError = AddressTypeNotSupported,
230 UnknownError
231 };
232
233 void initialize(Socks5Mode socks5Mode);
234
235 void setErrorState(Socks5State state, const QString &extraMessage = QString());
236 void setErrorState(Socks5State state, Socks5Error socks5error);
237
238 void reauthenticate();
239 void parseAuthenticationMethodReply();
240 void parseAuthenticatingReply();
241 void sendRequestMethod();
242 void parseRequestMethodReply();
243 void parseNewConnection();
244
245 bool waitForConnected(int msecs, bool *timedOut);
246
247 void _q_controlSocketConnected();
248 void _q_controlSocketReadNotification();
249 void _q_controlSocketErrorOccurred(QAbstractSocket::SocketError);
250#ifndef QT_NO_UDPSOCKET
251 void _q_udpSocketReadNotification();
252#endif
253 void _q_controlSocketBytesWritten();
254 void _q_controlSocketDisconnected();
255 void _q_controlSocketStateChanged(QAbstractSocket::SocketState);
256
257 QNetworkProxy proxyInfo;
258
259 bool readNotificationEnabled, writeNotificationEnabled, exceptNotificationEnabled;
260
261 qintptr socketDescriptor;
262
263 QSocks5Data *data;
264 QSocks5ConnectData *connectData;
265#ifndef QT_NO_UDPSOCKET
266 QSocks5UdpAssociateData *udpData;
267#endif
268 QSocks5BindData *bindData;
269 QString peerName;
270 QByteArray receivedHeaderFragment;
271
272 mutable bool readNotificationActivated;
273 mutable bool writeNotificationActivated;
274
275 bool readNotificationPending;
276 void _q_emitPendingReadNotification();
277 void emitReadNotification();
278 bool writeNotificationPending;
279 void _q_emitPendingWriteNotification();
280 void emitWriteNotification();
281 bool connectionNotificationPending;
282 void _q_emitPendingConnectionNotification();
283 void emitConnectionNotification();
284};
285
286class Q_AUTOTEST_EXPORT QSocks5SocketEngineHandler : public QSocketEngineHandler
287{
288public:
289 virtual QAbstractSocketEngine *createSocketEngine(QAbstractSocket::SocketType socketType,
290 const QNetworkProxy &, QObject *parent) override;
291 virtual QAbstractSocketEngine *createSocketEngine(qintptr socketDescriptor, QObject *parent) override;
292};
293
294QT_END_NAMESPACE
295
296#endif // QSOCKS5SOCKETENGINE_H
297