/src/network/socket/qsocks5socketengine.cpp

https://bitbucket.org/ultra_iter/qt-vtl · C++ · 1930 lines · 1561 code · 240 blank · 129 comment · 381 complexity · 5eef866aec1054926e65260d262e64b6 MD5 · raw file

  1. /****************************************************************************
  2. **
  3. ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  4. ** All rights reserved.
  5. ** Contact: Nokia Corporation (qt-info@nokia.com)
  6. **
  7. ** This file is part of the QtNetwork module of the Qt Toolkit.
  8. **
  9. ** $QT_BEGIN_LICENSE:LGPL$
  10. ** GNU Lesser General Public License Usage
  11. ** This file may be used under the terms of the GNU Lesser General Public
  12. ** License version 2.1 as published by the Free Software Foundation and
  13. ** appearing in the file LICENSE.LGPL included in the packaging of this
  14. ** file. Please review the following information to ensure the GNU Lesser
  15. ** General Public License version 2.1 requirements will be met:
  16. ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
  17. **
  18. ** In addition, as a special exception, Nokia gives you certain additional
  19. ** rights. These rights are described in the Nokia Qt LGPL Exception
  20. ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
  21. **
  22. ** GNU General Public License Usage
  23. ** Alternatively, this file may be used under the terms of the GNU General
  24. ** Public License version 3.0 as published by the Free Software Foundation
  25. ** and appearing in the file LICENSE.GPL included in the packaging of this
  26. ** file. Please review the following information to ensure the GNU General
  27. ** Public License version 3.0 requirements will be met:
  28. ** http://www.gnu.org/copyleft/gpl.html.
  29. **
  30. ** Other Usage
  31. ** Alternatively, this file may be used in accordance with the terms and
  32. ** conditions contained in a signed written agreement between you and Nokia.
  33. **
  34. **
  35. **
  36. **
  37. **
  38. ** $QT_END_LICENSE$
  39. **
  40. ****************************************************************************/
  41. #include "qsocks5socketengine_p.h"
  42. #ifndef QT_NO_SOCKS5
  43. #include "qtcpsocket.h"
  44. #include "qudpsocket.h"
  45. #include "qtcpserver.h"
  46. #include "qdebug.h"
  47. #include "qhash.h"
  48. #include "qqueue.h"
  49. #include "qelapsedtimer.h"
  50. #include "qmutex.h"
  51. #include "qthread.h"
  52. #include "qcoreapplication.h"
  53. #include "qurl.h"
  54. #include "qauthenticator.h"
  55. #include <qendian.h>
  56. #include <qnetworkinterface.h>
  57. QT_BEGIN_NAMESPACE
  58. #ifdef Q_OS_SYMBIAN
  59. static const int MaxWriteBufferSize = 4*1024;
  60. #else
  61. static const int MaxWriteBufferSize = 128*1024;
  62. #endif
  63. //#define QSOCKS5SOCKETLAYER_DEBUG
  64. #define MAX_DATA_DUMP 256
  65. #if !defined(Q_OS_WINCE)
  66. #define SOCKS5_BLOCKING_BIND_TIMEOUT 5000
  67. #else
  68. #define SOCKS5_BLOCKING_BIND_TIMEOUT 10000
  69. #endif
  70. #define Q_INIT_CHECK(returnValue) do { \
  71. if (!d->data) { \
  72. return returnValue; \
  73. } } while (0)
  74. #define S5_VERSION_5 0x05
  75. #define S5_CONNECT 0x01
  76. #define S5_BIND 0x02
  77. #define S5_UDP_ASSOCIATE 0x03
  78. #define S5_IP_V4 0x01
  79. #define S5_DOMAINNAME 0x03
  80. #define S5_IP_V6 0x04
  81. #define S5_SUCCESS 0x00
  82. #define S5_R_ERROR_SOCKS_FAILURE 0x01
  83. #define S5_R_ERROR_CON_NOT_ALLOWED 0x02
  84. #define S5_R_ERROR_NET_UNREACH 0x03
  85. #define S5_R_ERROR_HOST_UNREACH 0x04
  86. #define S5_R_ERROR_CONN_REFUSED 0x05
  87. #define S5_R_ERROR_TTL 0x06
  88. #define S5_R_ERROR_CMD_NOT_SUPPORTED 0x07
  89. #define S5_R_ERROR_ADD_TYPE_NOT_SUPORTED 0x08
  90. #define S5_AUTHMETHOD_NONE 0x00
  91. #define S5_AUTHMETHOD_PASSWORD 0x02
  92. #define S5_AUTHMETHOD_NOTACCEPTABLE 0xFF
  93. #define S5_PASSWORDAUTH_VERSION 0x01
  94. #ifdef QSOCKS5SOCKETLAYER_DEBUG
  95. # define QSOCKS5_Q_DEBUG qDebug() << this
  96. # define QSOCKS5_D_DEBUG qDebug() << q_ptr
  97. # define QSOCKS5_DEBUG qDebug() << "[QSocks5]"
  98. static QString s5StateToString(QSocks5SocketEnginePrivate::Socks5State s)
  99. {
  100. switch (s) {
  101. case QSocks5SocketEnginePrivate::Uninitialized: return QLatin1String("Uninitialized");
  102. case QSocks5SocketEnginePrivate::ConnectError: return QLatin1String("ConnectError");
  103. case QSocks5SocketEnginePrivate::AuthenticationMethodsSent: return QLatin1String("AuthenticationMethodsSent");
  104. case QSocks5SocketEnginePrivate::Authenticating: return QLatin1String("Authenticating");
  105. case QSocks5SocketEnginePrivate::AuthenticatingError: return QLatin1String("AuthenticatingError");
  106. case QSocks5SocketEnginePrivate::RequestMethodSent: return QLatin1String("RequestMethodSent");
  107. case QSocks5SocketEnginePrivate::RequestError: return QLatin1String("RequestError");
  108. case QSocks5SocketEnginePrivate::Connected: return QLatin1String("Connected");
  109. case QSocks5SocketEnginePrivate::UdpAssociateSuccess: return QLatin1String("UdpAssociateSuccess");
  110. case QSocks5SocketEnginePrivate::BindSuccess: return QLatin1String("BindSuccess");
  111. case QSocks5SocketEnginePrivate::ControlSocketError: return QLatin1String("ControlSocketError");
  112. case QSocks5SocketEnginePrivate::SocksError: return QLatin1String("SocksError");
  113. case QSocks5SocketEnginePrivate::HostNameLookupError: return QLatin1String("HostNameLookupError");
  114. default: break;
  115. }
  116. return QLatin1String("unknown state");
  117. }
  118. static QString dump(const QByteArray &buf)
  119. {
  120. QString data;
  121. for (int i = 0; i < qMin<int>(MAX_DATA_DUMP, buf.size()); ++i) {
  122. if (i) data += QLatin1Char(' ');
  123. uint val = (unsigned char)buf.at(i);
  124. // data += QString("0x%1").arg(val, 3, 16, QLatin1Char('0'));
  125. data += QString::number(val);
  126. }
  127. if (buf.size() > MAX_DATA_DUMP)
  128. data += QLatin1String(" ...");
  129. return QString::fromLatin1("size: %1 data: { %2 }").arg(buf.size()).arg(data);
  130. }
  131. #else
  132. # define QSOCKS5_DEBUG if (0) qDebug()
  133. # define QSOCKS5_Q_DEBUG if (0) qDebug()
  134. # define QSOCKS5_D_DEBUG if (0) qDebug()
  135. static inline QString s5StateToString(QSocks5SocketEnginePrivate::Socks5State) { return QString(); }
  136. static inline QString dump(const QByteArray &) { return QString(); }
  137. #endif
  138. /*
  139. inserts the host address in buf at pos and updates pos.
  140. if the func fails the data in buf and the vallue of pos is undefined
  141. */
  142. static bool qt_socks5_set_host_address_and_port(const QHostAddress &address, quint16 port, QByteArray *pBuf)
  143. {
  144. QSOCKS5_DEBUG << "setting [" << address << ':' << port << ']';
  145. union {
  146. quint16 port;
  147. quint32 ipv4;
  148. QIPv6Address ipv6;
  149. char ptr;
  150. } data;
  151. // add address
  152. if (address.protocol() == QAbstractSocket::IPv4Protocol) {
  153. data.ipv4 = qToBigEndian<quint32>(address.toIPv4Address());
  154. pBuf->append(S5_IP_V4);
  155. pBuf->append(QByteArray::fromRawData(&data.ptr, sizeof data.ipv4));
  156. } else if (address.protocol() == QAbstractSocket::IPv6Protocol) {
  157. data.ipv6 = address.toIPv6Address();
  158. pBuf->append(S5_IP_V6);
  159. pBuf->append(QByteArray::fromRawData(&data.ptr, sizeof data.ipv6));
  160. } else {
  161. return false;
  162. }
  163. // add port
  164. data.port = qToBigEndian<quint16>(port);
  165. pBuf->append(QByteArray::fromRawData(&data.ptr, sizeof data.port));
  166. return true;
  167. }
  168. /*
  169. like above, but for a hostname
  170. */
  171. static bool qt_socks5_set_host_name_and_port(const QString &hostname, quint16 port, QByteArray *pBuf)
  172. {
  173. QSOCKS5_DEBUG << "setting [" << hostname << ':' << port << ']';
  174. QByteArray encodedHostName = QUrl::toAce(hostname);
  175. QByteArray &buf = *pBuf;
  176. if (encodedHostName.length() > 255)
  177. return false;
  178. buf.append(S5_DOMAINNAME);
  179. buf.append(uchar(encodedHostName.length()));
  180. buf.append(encodedHostName);
  181. // add port
  182. union {
  183. quint16 port;
  184. char ptr;
  185. } data;
  186. data.port = qToBigEndian<quint16>(port);
  187. buf.append(QByteArray::fromRawData(&data.ptr, sizeof data.port));
  188. return true;
  189. }
  190. /*
  191. retrives the host address in buf at pos and updates pos.
  192. if the func fails the value of the address and the pos is undefined
  193. */
  194. static bool qt_socks5_get_host_address_and_port(const QByteArray &buf, QHostAddress *pAddress, quint16 *pPort, int *pPos)
  195. {
  196. bool ret = false;
  197. int pos = *pPos;
  198. const unsigned char *pBuf = reinterpret_cast<const unsigned char*>(buf.constData());
  199. QHostAddress address;
  200. quint16 port = 0;
  201. if (buf.size() - pos < 1) {
  202. QSOCKS5_DEBUG << "need more data address/port";
  203. return false;
  204. }
  205. if (pBuf[pos] == S5_IP_V4) {
  206. pos++;
  207. if (buf.size() - pos < 4) {
  208. QSOCKS5_DEBUG << "need more data for ip4 address";
  209. return false;
  210. }
  211. address.setAddress(qFromBigEndian<quint32>(&pBuf[pos]));
  212. pos += 4;
  213. ret = true;
  214. } else if (pBuf[pos] == S5_IP_V6) {
  215. pos++;
  216. if (buf.size() - pos < 16) {
  217. QSOCKS5_DEBUG << "need more data for ip6 address";
  218. return false;
  219. }
  220. QIPv6Address add;
  221. for (int i = 0; i < 16; ++i)
  222. add[i] = buf[pos++];
  223. ret = true;
  224. } else if (pBuf[pos] == S5_DOMAINNAME){
  225. // just skip it
  226. pos++;
  227. qDebug() << "skipping hostname of len" << uint(pBuf[pos]);
  228. pos += uchar(pBuf[pos]);
  229. } else {
  230. QSOCKS5_DEBUG << "invalid address type" << (int)pBuf[pos];
  231. ret = false;
  232. }
  233. if (ret) {
  234. if (buf.size() - pos < 2) {
  235. QSOCKS5_DEBUG << "need more data for port";
  236. return false;
  237. }
  238. port = qFromBigEndian<quint16>(&pBuf[pos]);
  239. pos += 2;
  240. }
  241. if (ret) {
  242. QSOCKS5_DEBUG << "got [" << address << ':' << port << ']';
  243. *pAddress = address;
  244. *pPort = port;
  245. *pPos = pos;
  246. }
  247. return ret;
  248. }
  249. /*
  250. Returns the difference between msecs and elapsed. If msecs is -1,
  251. however, -1 is returned.
  252. */
  253. static int qt_timeout_value(int msecs, int elapsed)
  254. {
  255. if (msecs == -1)
  256. return -1;
  257. int timeout = msecs - elapsed;
  258. return timeout < 0 ? 0 : timeout;
  259. }
  260. struct QSocks5Data
  261. {
  262. QTcpSocket *controlSocket;
  263. QSocks5Authenticator *authenticator;
  264. };
  265. struct QSocks5ConnectData : public QSocks5Data
  266. {
  267. QByteArray readBuffer;
  268. };
  269. struct QSocks5BindData : public QSocks5Data
  270. {
  271. QHostAddress localAddress;
  272. quint16 localPort;
  273. QHostAddress peerAddress;
  274. quint16 peerPort;
  275. QElapsedTimer timeStamp;
  276. };
  277. struct QSocks5RevivedDatagram
  278. {
  279. QByteArray data;
  280. QHostAddress address;
  281. quint16 port;
  282. };
  283. #ifndef QT_NO_UDPSOCKET
  284. struct QSocks5UdpAssociateData : public QSocks5Data
  285. {
  286. QUdpSocket *udpSocket;
  287. QHostAddress associateAddress;
  288. quint16 associatePort;
  289. QQueue<QSocks5RevivedDatagram> pendingDatagrams;
  290. };
  291. #endif
  292. // needs to be thread safe
  293. class QSocks5BindStore : public QObject
  294. {
  295. public:
  296. QSocks5BindStore();
  297. ~QSocks5BindStore();
  298. void add(int socketDescriptor, QSocks5BindData *bindData);
  299. bool contains(int socketDescriptor);
  300. QSocks5BindData *retrieve(int socketDescriptor);
  301. protected:
  302. void timerEvent(QTimerEvent * event);
  303. QMutex mutex;
  304. int sweepTimerId;
  305. //socket descriptor, data, timestamp
  306. QHash<int, QSocks5BindData *> store;
  307. };
  308. Q_GLOBAL_STATIC(QSocks5BindStore, socks5BindStore)
  309. QSocks5BindStore::QSocks5BindStore()
  310. : mutex(QMutex::Recursive)
  311. , sweepTimerId(-1)
  312. {
  313. QCoreApplication *app = QCoreApplication::instance();
  314. if (app && app->thread() != thread())
  315. moveToThread(app->thread());
  316. }
  317. QSocks5BindStore::~QSocks5BindStore()
  318. {
  319. }
  320. void QSocks5BindStore::add(int socketDescriptor, QSocks5BindData *bindData)
  321. {
  322. QMutexLocker lock(&mutex);
  323. if (store.contains(socketDescriptor)) {
  324. // qDebug() << "delete it";
  325. }
  326. bindData->timeStamp.start();
  327. store.insert(socketDescriptor, bindData);
  328. // start sweep timer if not started
  329. if (sweepTimerId == -1)
  330. sweepTimerId = startTimer(60000);
  331. }
  332. bool QSocks5BindStore::contains(int socketDescriptor)
  333. {
  334. QMutexLocker lock(&mutex);
  335. return store.contains(socketDescriptor);
  336. }
  337. QSocks5BindData *QSocks5BindStore::retrieve(int socketDescriptor)
  338. {
  339. QMutexLocker lock(&mutex);
  340. if (!store.contains(socketDescriptor))
  341. return 0;
  342. QSocks5BindData *bindData = store.take(socketDescriptor);
  343. if (bindData) {
  344. if (bindData->controlSocket->thread() != QThread::currentThread()) {
  345. qWarning("Can not access socks5 bind data from different thread");
  346. return 0;
  347. }
  348. } else {
  349. QSOCKS5_DEBUG << "__ERROR__ binddata == 0";
  350. }
  351. // stop the sweep timer if not needed
  352. if (store.isEmpty()) {
  353. killTimer(sweepTimerId);
  354. sweepTimerId = -1;
  355. }
  356. return bindData;
  357. }
  358. void QSocks5BindStore::timerEvent(QTimerEvent * event)
  359. {
  360. QMutexLocker lock(&mutex);
  361. if (event->timerId() == sweepTimerId) {
  362. QSOCKS5_DEBUG << "QSocks5BindStore performing sweep";
  363. QMutableHashIterator<int, QSocks5BindData *> it(store);
  364. while (it.hasNext()) {
  365. it.next();
  366. if (it.value()->timeStamp.hasExpired(350000)) {
  367. QSOCKS5_DEBUG << "QSocks5BindStore removing JJJJ";
  368. it.remove();
  369. }
  370. }
  371. }
  372. }
  373. QSocks5Authenticator::QSocks5Authenticator()
  374. {
  375. }
  376. QSocks5Authenticator::~QSocks5Authenticator()
  377. {
  378. }
  379. char QSocks5Authenticator::methodId()
  380. {
  381. return 0x00;
  382. }
  383. bool QSocks5Authenticator::beginAuthenticate(QTcpSocket *socket, bool *completed)
  384. {
  385. Q_UNUSED(socket);
  386. *completed = true;
  387. return true;
  388. }
  389. bool QSocks5Authenticator::continueAuthenticate(QTcpSocket *socket, bool *completed)
  390. {
  391. Q_UNUSED(socket);
  392. *completed = true;
  393. return true;
  394. }
  395. bool QSocks5Authenticator::seal(const QByteArray buf, QByteArray *sealedBuf)
  396. {
  397. *sealedBuf = buf;
  398. return true;
  399. }
  400. bool QSocks5Authenticator::unSeal(const QByteArray sealedBuf, QByteArray *buf)
  401. {
  402. *buf = sealedBuf;
  403. return true;
  404. }
  405. bool QSocks5Authenticator::unSeal(QTcpSocket *sealedSocket, QByteArray *buf)
  406. {
  407. return unSeal(sealedSocket->readAll(), buf);
  408. }
  409. QSocks5PasswordAuthenticator::QSocks5PasswordAuthenticator(const QString &userName, const QString &password)
  410. {
  411. this->userName = userName;
  412. this->password = password;
  413. }
  414. char QSocks5PasswordAuthenticator::methodId()
  415. {
  416. return 0x02;
  417. }
  418. bool QSocks5PasswordAuthenticator::beginAuthenticate(QTcpSocket *socket, bool *completed)
  419. {
  420. *completed = false;
  421. QByteArray uname = userName.toLatin1();
  422. QByteArray passwd = password.toLatin1();
  423. QByteArray dataBuf(3 + uname.size() + passwd.size(), 0);
  424. char *buf = dataBuf.data();
  425. int pos = 0;
  426. buf[pos++] = S5_PASSWORDAUTH_VERSION;
  427. buf[pos++] = uname.size();
  428. memcpy(&buf[pos], uname.data(), uname.size());
  429. pos += uname.size();
  430. buf[pos++] = passwd.size();
  431. memcpy(&buf[pos], passwd.data(), passwd.size());
  432. return socket->write(dataBuf) == dataBuf.size();
  433. }
  434. bool QSocks5PasswordAuthenticator::continueAuthenticate(QTcpSocket *socket, bool *completed)
  435. {
  436. *completed = false;
  437. if (socket->bytesAvailable() < 2)
  438. return true;
  439. QByteArray buf = socket->read(2);
  440. if (buf.at(0) == S5_PASSWORDAUTH_VERSION && buf.at(1) == 0x00) {
  441. *completed = true;
  442. return true;
  443. }
  444. // must disconnect
  445. socket->close();
  446. return false;
  447. }
  448. QString QSocks5PasswordAuthenticator::errorString()
  449. {
  450. return QLatin1String("Socks5 user name or password incorrect");
  451. }
  452. QSocks5SocketEnginePrivate::QSocks5SocketEnginePrivate()
  453. : socks5State(Uninitialized)
  454. , readNotificationEnabled(false)
  455. , writeNotificationEnabled(false)
  456. , exceptNotificationEnabled(false)
  457. , socketDescriptor(-1)
  458. , data(0)
  459. , connectData(0)
  460. #ifndef QT_NO_UDPSOCKET
  461. , udpData(0)
  462. #endif
  463. , bindData(0)
  464. , readNotificationActivated(false)
  465. , writeNotificationActivated(false)
  466. , readNotificationPending(false)
  467. , writeNotificationPending(false)
  468. , connectionNotificationPending(false)
  469. {
  470. mode = NoMode;
  471. }
  472. QSocks5SocketEnginePrivate::~QSocks5SocketEnginePrivate()
  473. {
  474. }
  475. void QSocks5SocketEnginePrivate::initialize(Socks5Mode socks5Mode)
  476. {
  477. Q_Q(QSocks5SocketEngine);
  478. mode = socks5Mode;
  479. if (mode == ConnectMode) {
  480. connectData = new QSocks5ConnectData;
  481. data = connectData;
  482. #ifndef QT_NO_UDPSOCKET
  483. } else if (mode == UdpAssociateMode) {
  484. udpData = new QSocks5UdpAssociateData;
  485. data = udpData;
  486. udpData->udpSocket = new QUdpSocket(q);
  487. #ifndef QT_NO_BEARERMANAGEMENT
  488. udpData->udpSocket->setProperty("_q_networksession", q->property("_q_networksession"));
  489. #endif
  490. udpData->udpSocket->setProxy(QNetworkProxy::NoProxy);
  491. QObject::connect(udpData->udpSocket, SIGNAL(readyRead()),
  492. q, SLOT(_q_udpSocketReadNotification()),
  493. Qt::DirectConnection);
  494. #endif // QT_NO_UDPSOCKET
  495. } else if (mode == BindMode) {
  496. bindData = new QSocks5BindData;
  497. data = bindData;
  498. }
  499. data->controlSocket = new QTcpSocket(q);
  500. #ifndef QT_NO_BEARERMANAGEMENT
  501. data->controlSocket->setProperty("_q_networksession", q->property("_q_networksession"));
  502. #endif
  503. data->controlSocket->setProxy(QNetworkProxy::NoProxy);
  504. QObject::connect(data->controlSocket, SIGNAL(connected()), q, SLOT(_q_controlSocketConnected()),
  505. Qt::DirectConnection);
  506. QObject::connect(data->controlSocket, SIGNAL(readyRead()), q, SLOT(_q_controlSocketReadNotification()),
  507. Qt::DirectConnection);
  508. QObject::connect(data->controlSocket, SIGNAL(bytesWritten(qint64)), q, SLOT(_q_controlSocketBytesWritten()),
  509. Qt::DirectConnection);
  510. QObject::connect(data->controlSocket, SIGNAL(error(QAbstractSocket::SocketError)),
  511. q, SLOT(_q_controlSocketError(QAbstractSocket::SocketError)),
  512. Qt::DirectConnection);
  513. QObject::connect(data->controlSocket, SIGNAL(disconnected()), q, SLOT(_q_controlSocketDisconnected()),
  514. Qt::DirectConnection);
  515. QObject::connect(data->controlSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
  516. q, SLOT(_q_controlSocketStateChanged(QAbstractSocket::SocketState)),
  517. Qt::DirectConnection);
  518. if (!proxyInfo.user().isEmpty() || !proxyInfo.password().isEmpty()) {
  519. QSOCKS5_D_DEBUG << "using username/password authentication; user =" << proxyInfo.user();
  520. data->authenticator = new QSocks5PasswordAuthenticator(proxyInfo.user(), proxyInfo.password());
  521. } else {
  522. QSOCKS5_D_DEBUG << "not using authentication";
  523. data->authenticator = new QSocks5Authenticator();
  524. }
  525. }
  526. void QSocks5SocketEnginePrivate::setErrorState(Socks5State state, const QString &extraMessage)
  527. {
  528. Q_Q(QSocks5SocketEngine);
  529. switch (state) {
  530. case Uninitialized:
  531. case Authenticating:
  532. case AuthenticationMethodsSent:
  533. case RequestMethodSent:
  534. case Connected:
  535. case UdpAssociateSuccess:
  536. case BindSuccess:
  537. // these aren't error states
  538. return;
  539. case ConnectError:
  540. case ControlSocketError: {
  541. QAbstractSocket::SocketError controlSocketError = data->controlSocket->error();
  542. if (socks5State != Connected) {
  543. switch (controlSocketError) {
  544. case QAbstractSocket::ConnectionRefusedError:
  545. q->setError(QAbstractSocket::ProxyConnectionRefusedError,
  546. QSocks5SocketEngine::tr("Connection to proxy refused"));
  547. break;
  548. case QAbstractSocket::RemoteHostClosedError:
  549. q->setError(QAbstractSocket::ProxyConnectionClosedError,
  550. QSocks5SocketEngine::tr("Connection to proxy closed prematurely"));
  551. break;
  552. case QAbstractSocket::HostNotFoundError:
  553. q->setError(QAbstractSocket::ProxyNotFoundError,
  554. QSocks5SocketEngine::tr("Proxy host not found"));
  555. break;
  556. case QAbstractSocket::SocketTimeoutError:
  557. if (state == ConnectError) {
  558. q->setError(QAbstractSocket::ProxyConnectionTimeoutError,
  559. QSocks5SocketEngine::tr("Connection to proxy timed out"));
  560. break;
  561. }
  562. /* fall through */
  563. default:
  564. q->setError(controlSocketError, data->controlSocket->errorString());
  565. break;
  566. }
  567. } else {
  568. q->setError(controlSocketError, data->controlSocket->errorString());
  569. }
  570. break;
  571. }
  572. case AuthenticatingError:
  573. q->setError(QAbstractSocket::ProxyAuthenticationRequiredError,
  574. extraMessage.isEmpty() ?
  575. QSocks5SocketEngine::tr("Proxy authentication failed") :
  576. QSocks5SocketEngine::tr("Proxy authentication failed: %1").arg(extraMessage));
  577. break;
  578. case RequestError:
  579. // error code set by caller (overload)
  580. break;
  581. case SocksError:
  582. q->setError(QAbstractSocket::ProxyProtocolError,
  583. QSocks5SocketEngine::tr("SOCKS version 5 protocol error"));
  584. break;
  585. case HostNameLookupError:
  586. q->setError(QAbstractSocket::HostNotFoundError,
  587. QAbstractSocket::tr("Host not found"));
  588. break;
  589. }
  590. q->setState(QAbstractSocket::UnconnectedState);
  591. socks5State = state;
  592. }
  593. void QSocks5SocketEnginePrivate::setErrorState(Socks5State state, Socks5Error socks5error)
  594. {
  595. Q_Q(QSocks5SocketEngine);
  596. switch (socks5error) {
  597. case SocksFailure:
  598. q->setError(QAbstractSocket::NetworkError,
  599. QSocks5SocketEngine::tr("General SOCKSv5 server failure"));
  600. break;
  601. case ConnectionNotAllowed:
  602. q->setError(QAbstractSocket::SocketAccessError,
  603. QSocks5SocketEngine::tr("Connection not allowed by SOCKSv5 server"));
  604. break;
  605. case NetworkUnreachable:
  606. q->setError(QAbstractSocket::NetworkError,
  607. QAbstractSocket::tr("Network unreachable"));
  608. break;
  609. case HostUnreachable:
  610. q->setError(QAbstractSocket::HostNotFoundError,
  611. QAbstractSocket::tr("Host not found"));
  612. break;
  613. case ConnectionRefused:
  614. q->setError(QAbstractSocket::ConnectionRefusedError,
  615. QAbstractSocket::tr("Connection refused"));
  616. break;
  617. case TTLExpired:
  618. q->setError(QAbstractSocket::NetworkError,
  619. QSocks5SocketEngine::tr("TTL expired"));
  620. break;
  621. case CommandNotSupported:
  622. q->setError(QAbstractSocket::UnsupportedSocketOperationError,
  623. QSocks5SocketEngine::tr("SOCKSv5 command not supported"));
  624. break;
  625. case AddressTypeNotSupported:
  626. q->setError(QAbstractSocket::UnsupportedSocketOperationError,
  627. QSocks5SocketEngine::tr("Address type not supported"));
  628. break;
  629. default:
  630. q->setError(QAbstractSocket::UnknownSocketError,
  631. QSocks5SocketEngine::tr("Unknown SOCKSv5 proxy error code 0x%1").arg(int(socks5error), 16));
  632. break;
  633. }
  634. setErrorState(state, QString());
  635. }
  636. void QSocks5SocketEnginePrivate::reauthenticate()
  637. {
  638. Q_Q(QSocks5SocketEngine);
  639. // we require authentication
  640. QAuthenticator auth;
  641. emit q->proxyAuthenticationRequired(proxyInfo, &auth);
  642. if (!auth.user().isEmpty() || !auth.password().isEmpty()) {
  643. // we have new credentials, let's try again
  644. QSOCKS5_DEBUG << "authentication failure: retrying connection";
  645. socks5State = QSocks5SocketEnginePrivate::Uninitialized;
  646. delete data->authenticator;
  647. proxyInfo.setUser(auth.user());
  648. proxyInfo.setPassword(auth.password());
  649. data->authenticator = new QSocks5PasswordAuthenticator(proxyInfo.user(), proxyInfo.password());
  650. data->controlSocket->blockSignals(true);
  651. data->controlSocket->abort();
  652. data->controlSocket->blockSignals(false);
  653. data->controlSocket->connectToHost(proxyInfo.hostName(), proxyInfo.port());
  654. } else {
  655. // authentication failure
  656. setErrorState(AuthenticatingError);
  657. data->controlSocket->close();
  658. emitConnectionNotification();
  659. }
  660. }
  661. void QSocks5SocketEnginePrivate::parseAuthenticationMethodReply()
  662. {
  663. // not enough data to begin
  664. if (data->controlSocket->bytesAvailable() < 2)
  665. return;
  666. QByteArray buf = data->controlSocket->read(2);
  667. if (buf.at(0) != S5_VERSION_5) {
  668. QSOCKS5_D_DEBUG << "Socks5 version incorrect";
  669. setErrorState(SocksError);
  670. data->controlSocket->close();
  671. emitConnectionNotification();
  672. return;
  673. }
  674. bool authComplete = false;
  675. if (uchar(buf.at(1)) == S5_AUTHMETHOD_NONE) {
  676. authComplete = true;
  677. } else if (uchar(buf.at(1)) == S5_AUTHMETHOD_NOTACCEPTABLE) {
  678. reauthenticate();
  679. return;
  680. } else if (buf.at(1) != data->authenticator->methodId()
  681. || !data->authenticator->beginAuthenticate(data->controlSocket, &authComplete)) {
  682. setErrorState(AuthenticatingError, QLatin1String("Socks5 host did not support authentication method."));
  683. socketError = QAbstractSocket::SocketAccessError; // change the socket error
  684. emitConnectionNotification();
  685. return;
  686. }
  687. if (authComplete)
  688. sendRequestMethod();
  689. else
  690. socks5State = Authenticating;
  691. }
  692. void QSocks5SocketEnginePrivate::parseAuthenticatingReply()
  693. {
  694. bool authComplete = false;
  695. if (!data->authenticator->continueAuthenticate(data->controlSocket, &authComplete)) {
  696. reauthenticate();
  697. return;
  698. }
  699. if (authComplete)
  700. sendRequestMethod();
  701. }
  702. void QSocks5SocketEnginePrivate::sendRequestMethod()
  703. {
  704. QHostAddress address;
  705. quint16 port = 0;
  706. char command = 0;
  707. if (mode == ConnectMode) {
  708. command = S5_CONNECT;
  709. address = peerAddress;
  710. port = peerPort;
  711. } else if (mode == BindMode) {
  712. command = S5_BIND;
  713. address = localAddress;
  714. port = localPort;
  715. } else {
  716. #ifndef QT_NO_UDPSOCKET
  717. command = S5_UDP_ASSOCIATE;
  718. address = localAddress; //data->controlSocket->localAddress();
  719. port = localPort;
  720. #endif
  721. }
  722. QByteArray buf;
  723. buf.reserve(270); // big enough for domain name;
  724. buf[0] = S5_VERSION_5;
  725. buf[1] = command;
  726. buf[2] = 0x00;
  727. if (peerName.isEmpty() && !qt_socks5_set_host_address_and_port(address, port, &buf)) {
  728. QSOCKS5_DEBUG << "error setting address" << address << " : " << port;
  729. //### set error code ....
  730. return;
  731. } else if (!peerName.isEmpty() && !qt_socks5_set_host_name_and_port(peerName, port, &buf)) {
  732. QSOCKS5_DEBUG << "error setting address" << address << " : " << port;
  733. //### set error code ....
  734. return;
  735. }
  736. QSOCKS5_DEBUG << "sending" << dump(buf);
  737. QByteArray sealedBuf;
  738. if (!data->authenticator->seal(buf, &sealedBuf)) {
  739. // ### Handle this error.
  740. }
  741. data->controlSocket->write(sealedBuf);
  742. data->controlSocket->flush();
  743. socks5State = RequestMethodSent;
  744. }
  745. void QSocks5SocketEnginePrivate::parseRequestMethodReply()
  746. {
  747. Q_Q(QSocks5SocketEngine);
  748. QSOCKS5_DEBUG << "parseRequestMethodReply()";
  749. QByteArray inBuf;
  750. if (!data->authenticator->unSeal(data->controlSocket, &inBuf)) {
  751. // ### check error and not just not enough data
  752. QSOCKS5_DEBUG << "unSeal failed, needs more data";
  753. return;
  754. }
  755. QSOCKS5_DEBUG << dump(inBuf);
  756. if (inBuf.size() < 2) {
  757. QSOCKS5_DEBUG << "need more data for request reply header .. put this data somewhere";
  758. return;
  759. }
  760. QHostAddress address;
  761. quint16 port = 0;
  762. if (inBuf.at(0) != S5_VERSION_5 || inBuf.length() < 3 || inBuf.at(2) != 0x00) {
  763. QSOCKS5_DEBUG << "socks protocol error";
  764. setErrorState(SocksError);
  765. } else if (inBuf.at(1) != S5_SUCCESS) {
  766. Socks5Error socks5Error = Socks5Error(inBuf.at(1));
  767. QSOCKS5_DEBUG << "Request error :" << socks5Error;
  768. if ((socks5Error == SocksFailure || socks5Error == ConnectionNotAllowed)
  769. && !peerName.isEmpty()) {
  770. // Dante seems to use this error code to indicate hostname resolution failure
  771. setErrorState(HostNameLookupError);
  772. } else {
  773. setErrorState(RequestError, socks5Error);
  774. }
  775. } else {
  776. // connection success, retrieve the remote addresses
  777. int pos = 3;
  778. if (!qt_socks5_get_host_address_and_port(inBuf, &address, &port, &pos)) {
  779. QSOCKS5_DEBUG << "error getting address";
  780. setErrorState(SocksError);
  781. } else {
  782. inBuf.remove(0, pos);
  783. for (int i = inBuf.size() - 1; i >= 0 ; --i)
  784. data->controlSocket->ungetChar(inBuf.at(i));
  785. }
  786. }
  787. if (socks5State == RequestMethodSent) {
  788. // no error
  789. localAddress = address;
  790. localPort = port;
  791. if (mode == ConnectMode) {
  792. socks5State = Connected;
  793. // notify the upper layer that we're done
  794. q->setState(QAbstractSocket::ConnectedState);
  795. emitConnectionNotification();
  796. } else if (mode == BindMode) {
  797. socks5State = BindSuccess;
  798. q->setState(QAbstractSocket::ListeningState);
  799. } else {
  800. socks5State = UdpAssociateSuccess;
  801. }
  802. } else if (socks5State == BindSuccess) {
  803. // no error and we got a connection
  804. bindData->peerAddress = address;
  805. bindData->peerPort = port;
  806. emitReadNotification();
  807. } else {
  808. // got an error
  809. data->controlSocket->close();
  810. emitConnectionNotification();
  811. }
  812. }
  813. void QSocks5SocketEnginePrivate::_q_emitPendingReadNotification()
  814. {
  815. Q_Q(QSocks5SocketEngine);
  816. readNotificationPending = false;
  817. if (readNotificationEnabled) {
  818. QSOCKS5_D_DEBUG << "emitting readNotification";
  819. QPointer<QSocks5SocketEngine> qq = q;
  820. emit q->readNotification();
  821. if (!qq)
  822. return;
  823. // check if there needs to be a new zero read notification
  824. if (data && data->controlSocket->state() == QAbstractSocket::UnconnectedState
  825. && data->controlSocket->error() == QAbstractSocket::RemoteHostClosedError) {
  826. connectData->readBuffer.clear();
  827. emitReadNotification();
  828. }
  829. }
  830. }
  831. void QSocks5SocketEnginePrivate::emitReadNotification()
  832. {
  833. Q_Q(QSocks5SocketEngine);
  834. readNotificationActivated = true;
  835. if (readNotificationEnabled && !readNotificationPending) {
  836. QSOCKS5_D_DEBUG << "queueing readNotification";
  837. readNotificationPending = true;
  838. QMetaObject::invokeMethod(q, "_q_emitPendingReadNotification", Qt::QueuedConnection);
  839. }
  840. }
  841. void QSocks5SocketEnginePrivate::_q_emitPendingWriteNotification()
  842. {
  843. writeNotificationPending = false;
  844. Q_Q(QSocks5SocketEngine);
  845. if (writeNotificationEnabled) {
  846. QSOCKS5_D_DEBUG << "emitting writeNotification";
  847. emit q->writeNotification();
  848. }
  849. }
  850. void QSocks5SocketEnginePrivate::emitWriteNotification()
  851. {
  852. Q_Q(QSocks5SocketEngine);
  853. writeNotificationActivated = true;
  854. if (writeNotificationEnabled && !writeNotificationPending) {
  855. QSOCKS5_D_DEBUG << "queueing writeNotification";
  856. writeNotificationPending = true;
  857. QMetaObject::invokeMethod(q, "_q_emitPendingWriteNotification", Qt::QueuedConnection);
  858. }
  859. }
  860. void QSocks5SocketEnginePrivate::_q_emitPendingConnectionNotification()
  861. {
  862. connectionNotificationPending = false;
  863. Q_Q(QSocks5SocketEngine);
  864. QSOCKS5_D_DEBUG << "emitting connectionNotification";
  865. emit q->connectionNotification();
  866. }
  867. void QSocks5SocketEnginePrivate::emitConnectionNotification()
  868. {
  869. Q_Q(QSocks5SocketEngine);
  870. QSOCKS5_D_DEBUG << "queueing connectionNotification";
  871. connectionNotificationPending = true;
  872. QMetaObject::invokeMethod(q, "_q_emitPendingConnectionNotification", Qt::QueuedConnection);
  873. }
  874. QSocks5SocketEngine::QSocks5SocketEngine(QObject *parent)
  875. :QAbstractSocketEngine(*new QSocks5SocketEnginePrivate(), parent)
  876. {
  877. }
  878. QSocks5SocketEngine::~QSocks5SocketEngine()
  879. {
  880. Q_D(QSocks5SocketEngine);
  881. if (d->data) {
  882. delete d->data->authenticator;
  883. delete d->data->controlSocket;
  884. }
  885. if (d->connectData)
  886. delete d->connectData;
  887. #ifndef QT_NO_UDPSOCKET
  888. if (d->udpData) {
  889. delete d->udpData->udpSocket;
  890. delete d->udpData;
  891. }
  892. #endif
  893. if (d->bindData)
  894. delete d->bindData;
  895. }
  896. static QBasicAtomicInt descriptorCounter = Q_BASIC_ATOMIC_INITIALIZER(1);
  897. bool QSocks5SocketEngine::initialize(QAbstractSocket::SocketType type, QAbstractSocket::NetworkLayerProtocol protocol)
  898. {
  899. Q_D(QSocks5SocketEngine);
  900. d->socketDescriptor = descriptorCounter.fetchAndAddRelaxed(1);
  901. d->socketType = type;
  902. d->socketProtocol = protocol;
  903. return true;
  904. }
  905. bool QSocks5SocketEngine::initialize(int socketDescriptor, QAbstractSocket::SocketState socketState)
  906. {
  907. Q_D(QSocks5SocketEngine);
  908. QSOCKS5_Q_DEBUG << "initialize" << socketDescriptor;
  909. // this is only valid for the other side of a bind, nothing else is supported
  910. if (socketState != QAbstractSocket::ConnectedState) {
  911. //### must be connected state ???
  912. return false;
  913. }
  914. QSocks5BindData *bindData = socks5BindStore()->retrieve(socketDescriptor);
  915. if (bindData) {
  916. d->socketState = QAbstractSocket::ConnectedState;
  917. d->socketType = QAbstractSocket::TcpSocket;
  918. d->connectData = new QSocks5ConnectData;
  919. d->data = d->connectData;
  920. d->mode = QSocks5SocketEnginePrivate::ConnectMode;
  921. d->data->controlSocket = bindData->controlSocket;
  922. bindData->controlSocket = 0;
  923. d->data->controlSocket->setParent(this);
  924. d->socketProtocol = d->data->controlSocket->localAddress().protocol();
  925. d->data->authenticator = bindData->authenticator;
  926. bindData->authenticator = 0;
  927. d->localPort = bindData->localPort;
  928. d->localAddress = bindData->localAddress;
  929. d->peerPort = bindData->peerPort;
  930. d->peerAddress = bindData->peerAddress;
  931. delete bindData;
  932. QObject::connect(d->data->controlSocket, SIGNAL(connected()), this, SLOT(_q_controlSocketConnected()),
  933. Qt::DirectConnection);
  934. QObject::connect(d->data->controlSocket, SIGNAL(readyRead()), this, SLOT(_q_controlSocketReadNotification()),
  935. Qt::DirectConnection);
  936. QObject::connect(d->data->controlSocket, SIGNAL(bytesWritten(qint64)), this, SLOT(_q_controlSocketBytesWritten()),
  937. Qt::DirectConnection);
  938. QObject::connect(d->data->controlSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(_q_controlSocketError(QAbstractSocket::SocketError)),
  939. Qt::DirectConnection);
  940. QObject::connect(d->data->controlSocket, SIGNAL(disconnected()), this, SLOT(_q_controlSocketDisconnected()),
  941. Qt::DirectConnection);
  942. QObject::connect(d->data->controlSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
  943. this, SLOT(_q_controlSocketStateChanged(QAbstractSocket::SocketState)),
  944. Qt::DirectConnection);
  945. d->socks5State = QSocks5SocketEnginePrivate::Connected;
  946. if (d->data->controlSocket->bytesAvailable() != 0)
  947. d->_q_controlSocketReadNotification();
  948. return true;
  949. }
  950. return false;
  951. }
  952. void QSocks5SocketEngine::setProxy(const QNetworkProxy &networkProxy)
  953. {
  954. Q_D(QSocks5SocketEngine);
  955. d->proxyInfo = networkProxy;
  956. }
  957. int QSocks5SocketEngine::socketDescriptor() const
  958. {
  959. Q_D(const QSocks5SocketEngine);
  960. return d->socketDescriptor;
  961. }
  962. bool QSocks5SocketEngine::isValid() const
  963. {
  964. Q_D(const QSocks5SocketEngine);
  965. return d->socketType != QAbstractSocket::UnknownSocketType
  966. && d->socks5State != QSocks5SocketEnginePrivate::SocksError
  967. && (d->socketError == QAbstractSocket::UnknownSocketError
  968. || d->socketError == QAbstractSocket::SocketTimeoutError
  969. || d->socketError == QAbstractSocket::UnfinishedSocketOperationError);
  970. }
  971. bool QSocks5SocketEngine::connectInternal()
  972. {
  973. Q_D(QSocks5SocketEngine);
  974. if (!d->data) {
  975. if (socketType() == QAbstractSocket::TcpSocket) {
  976. d->initialize(QSocks5SocketEnginePrivate::ConnectMode);
  977. #ifndef QT_NO_UDPSOCKET
  978. } else if (socketType() == QAbstractSocket::UdpSocket) {
  979. d->initialize(QSocks5SocketEnginePrivate::UdpAssociateMode);
  980. // all udp needs to be bound
  981. if (!bind(QHostAddress(QLatin1String("0.0.0.0")), 0))
  982. return false;
  983. setState(QAbstractSocket::ConnectedState);
  984. return true;
  985. #endif
  986. } else {
  987. qFatal("QSocks5SocketEngine::connectToHost: in QTcpServer mode");
  988. return false;
  989. }
  990. }
  991. if (d->socks5State == QSocks5SocketEnginePrivate::Uninitialized
  992. && d->socketState != QAbstractSocket::ConnectingState) {
  993. setState(QAbstractSocket::ConnectingState);
  994. //limit buffer in internal socket, data is buffered in the external socket under application control
  995. d->data->controlSocket->setReadBufferSize(65536);
  996. d->data->controlSocket->connectToHost(d->proxyInfo.hostName(), d->proxyInfo.port());
  997. return false;
  998. }
  999. return false;
  1000. }
  1001. bool QSocks5SocketEngine::connectToHost(const QHostAddress &address, quint16 port)
  1002. {
  1003. Q_D(QSocks5SocketEngine);
  1004. QSOCKS5_DEBUG << "connectToHost" << address << ':' << port;
  1005. setPeerAddress(address);
  1006. setPeerPort(port);
  1007. d->peerName.clear();
  1008. return connectInternal();
  1009. }
  1010. bool QSocks5SocketEngine::connectToHostByName(const QString &hostname, quint16 port)
  1011. {
  1012. Q_D(QSocks5SocketEngine);
  1013. setPeerAddress(QHostAddress());
  1014. setPeerPort(port);
  1015. d->peerName = hostname;
  1016. return connectInternal();
  1017. }
  1018. void QSocks5SocketEnginePrivate::_q_controlSocketConnected()
  1019. {
  1020. QSOCKS5_DEBUG << "_q_controlSocketConnected";
  1021. QByteArray buf(3, 0);
  1022. buf[0] = S5_VERSION_5;
  1023. buf[1] = 0x01;
  1024. buf[2] = data->authenticator->methodId();
  1025. data->controlSocket->write(buf);
  1026. socks5State = AuthenticationMethodsSent;
  1027. }
  1028. void QSocks5SocketEnginePrivate::_q_controlSocketReadNotification()
  1029. {
  1030. QSOCKS5_D_DEBUG << "_q_controlSocketReadNotification socks5state" << s5StateToString(socks5State)
  1031. << "bytes available" << data->controlSocket->bytesAvailable();
  1032. if (data->controlSocket->bytesAvailable() == 0) {
  1033. QSOCKS5_D_DEBUG << "########## bogus read why do we get these ... on windows only";
  1034. return;
  1035. }
  1036. switch (socks5State) {
  1037. case AuthenticationMethodsSent:
  1038. parseAuthenticationMethodReply();
  1039. break;
  1040. case Authenticating:
  1041. parseAuthenticatingReply();
  1042. break;
  1043. case RequestMethodSent:
  1044. parseRequestMethodReply();
  1045. break;
  1046. case Connected: {
  1047. QByteArray buf;
  1048. if (!data->authenticator->unSeal(data->controlSocket, &buf)) {
  1049. // qDebug() << "unseal error maybe need to wait for more data";
  1050. }
  1051. if (buf.size()) {
  1052. QSOCKS5_DEBUG << dump(buf);
  1053. connectData->readBuffer += buf;
  1054. emitReadNotification();
  1055. }
  1056. break;
  1057. }
  1058. case BindSuccess:
  1059. // only get here if command is bind
  1060. if (mode == BindMode) {
  1061. parseRequestMethodReply();
  1062. break;
  1063. }
  1064. // fall through
  1065. default:
  1066. qWarning("QSocks5SocketEnginePrivate::_q_controlSocketReadNotification: "
  1067. "Unexpectedly received data while in state=%d and mode=%d",
  1068. socks5State, mode);
  1069. break;
  1070. };
  1071. }
  1072. void QSocks5SocketEnginePrivate::_q_controlSocketBytesWritten()
  1073. {
  1074. QSOCKS5_DEBUG << "_q_controlSocketBytesWritten";
  1075. if (socks5State != Connected
  1076. || (mode == ConnectMode
  1077. && data->controlSocket->bytesToWrite()))
  1078. return;
  1079. if (data->controlSocket->bytesToWrite() < MaxWriteBufferSize) {
  1080. emitWriteNotification();
  1081. writeNotificationActivated = false;
  1082. }
  1083. }
  1084. void QSocks5SocketEnginePrivate::_q_controlSocketError(QAbstractSocket::SocketError error)
  1085. {
  1086. QSOCKS5_D_DEBUG << "controlSocketError" << error << data->controlSocket->errorString();
  1087. if (error == QAbstractSocket::SocketTimeoutError)
  1088. return; // ignore this error -- comes from the waitFor* functions
  1089. if (error == QAbstractSocket::RemoteHostClosedError
  1090. && socks5State == Connected) {
  1091. // clear the read buffer in connect mode so that bytes available returns 0
  1092. // if there already is a read notification pending then this will be processed first
  1093. if (!readNotificationPending)
  1094. connectData->readBuffer.clear();
  1095. emitReadNotification();
  1096. data->controlSocket->close();
  1097. // cause a disconnect in the outer socket
  1098. emitWriteNotification();
  1099. } else if (socks5State == Uninitialized
  1100. || socks5State == AuthenticationMethodsSent
  1101. || socks5State == Authenticating
  1102. || socks5State == RequestMethodSent) {
  1103. setErrorState(socks5State == Uninitialized ? ConnectError : ControlSocketError);
  1104. data->controlSocket->close();
  1105. emitConnectionNotification();
  1106. } else {
  1107. q_func()->setError(data->controlSocket->error(), data->controlSocket->errorString());
  1108. emitReadNotification();
  1109. emitWriteNotification();
  1110. }
  1111. }
  1112. void QSocks5SocketEnginePrivate::_q_controlSocketDisconnected()
  1113. {
  1114. QSOCKS5_D_DEBUG << "_q_controlSocketDisconnected";
  1115. }
  1116. void QSocks5SocketEnginePrivate::_q_controlSocketStateChanged(QAbstractSocket::SocketState state)
  1117. {
  1118. QSOCKS5_D_DEBUG << "_q_controlSocketStateChanged" << state;
  1119. }
  1120. #ifndef QT_NO_UDPSOCKET
  1121. void QSocks5SocketEnginePrivate::checkForDatagrams() const
  1122. {
  1123. // udp should be unbuffered so we need to do some polling at certain points
  1124. if (udpData->udpSocket->hasPendingDatagrams())
  1125. const_cast<QSocks5SocketEnginePrivate *>(this)->_q_udpSocketReadNotification();
  1126. }
  1127. void QSocks5SocketEnginePrivate::_q_udpSocketReadNotification()
  1128. {
  1129. QSOCKS5_D_DEBUG << "_q_udpSocketReadNotification()";
  1130. // check some state stuff
  1131. if (!udpData->udpSocket->hasPendingDatagrams()) {
  1132. QSOCKS5_D_DEBUG << "false read ??";
  1133. return;
  1134. }
  1135. while (udpData->udpSocket->hasPendingDatagrams()) {
  1136. QByteArray sealedBuf(udpData->udpSocket->pendingDatagramSize(), 0);
  1137. QSOCKS5_D_DEBUG << "new datagram";
  1138. udpData->udpSocket->readDatagram(sealedBuf.data(), sealedBuf.size());
  1139. QByteArray inBuf;
  1140. if (!data->authenticator->unSeal(sealedBuf, &inBuf)) {
  1141. QSOCKS5_D_DEBUG << "failed unsealing datagram discarding";
  1142. return;
  1143. }
  1144. QSOCKS5_DEBUG << dump(inBuf);
  1145. int pos = 0;
  1146. const char *buf = inBuf.constData();
  1147. if (inBuf.size() < 4) {
  1148. QSOCKS5_D_DEBUG << "bugus udp data, discarding";
  1149. return;
  1150. }
  1151. QSocks5RevivedDatagram datagram;
  1152. if (buf[pos++] != 0 || buf[pos++] != 0) {
  1153. QSOCKS5_D_DEBUG << "invalid datagram discarding";
  1154. return;
  1155. }
  1156. if (buf[pos++] != 0) { //### add fragmentation reading support
  1157. QSOCKS5_D_DEBUG << "don't support fragmentation yet disgarding";
  1158. return;
  1159. }
  1160. if (!qt_socks5_get_host_address_and_port(inBuf, &datagram.address, &datagram.port, &pos)) {
  1161. QSOCKS5_D_DEBUG << "failed to get address from datagram disgarding";
  1162. return;
  1163. }
  1164. datagram.data = QByteArray(&buf[pos], inBuf.size() - pos);
  1165. udpData->pendingDatagrams.enqueue(datagram);
  1166. }
  1167. emitReadNotification();
  1168. }
  1169. #endif // QT_NO_UDPSOCKET
  1170. bool QSocks5SocketEngine::bind(const QHostAddress &address, quint16 port)
  1171. {
  1172. Q_D(QSocks5SocketEngine);
  1173. // when bind wee will block until the bind is finished as the info from the proxy server is needed
  1174. if (!d->data) {
  1175. if (socketType() == QAbstractSocket::TcpSocket) {
  1176. d->initialize(QSocks5SocketEnginePrivate::BindMode);
  1177. #ifndef QT_NO_UDPSOCKET
  1178. } else if (socketType() == QAbstractSocket::UdpSocket) {
  1179. d->initialize(QSocks5SocketEnginePrivate::UdpAssociateMode);
  1180. #endif
  1181. } else {
  1182. //### something invalid
  1183. return false;
  1184. }
  1185. }
  1186. #ifndef QT_NO_UDPSOCKET
  1187. if (d->mode == QSocks5SocketEnginePrivate::UdpAssociateMode) {
  1188. if (!d->udpData->udpSocket->bind(address, port)) {
  1189. QSOCKS5_Q_DEBUG << "local udp bind failed";
  1190. setError(d->udpData->udpSocket->error(), d->udpData->udpSocket->errorString());
  1191. return false;
  1192. }
  1193. d->localAddress = d->udpData->udpSocket->localAddress();
  1194. d->localPort = d->udpData->udpSocket->localPort();
  1195. } else
  1196. #endif
  1197. if (d->mode == QSocks5SocketEnginePrivate::BindMode) {
  1198. d->localAddress = address;
  1199. d->localPort = port;
  1200. } else {
  1201. //### something invalid
  1202. return false;
  1203. }
  1204. int msecs = SOCKS5_BLOCKING_BIND_TIMEOUT;
  1205. QElapsedTimer stopWatch;
  1206. stopWatch.start();
  1207. d->data->controlSocket->connectToHost(d->proxyInfo.hostName(), d->proxyInfo.port());
  1208. if (!d->waitForConnected(msecs, 0) ||
  1209. d->data->controlSocket->state() == QAbstractSocket::UnconnectedState) {
  1210. // waitForConnected sets the error state and closes the socket
  1211. QSOCKS5_Q_DEBUG << "waitForConnected to proxy server" << d->data->controlSocket->errorString();
  1212. return false;
  1213. }
  1214. if (d->socks5State == QSocks5SocketEnginePrivate::BindSuccess) {
  1215. setState(QAbstractSocket::BoundState);
  1216. return true;
  1217. #ifndef QT_NO_UDPSOCKET
  1218. } else if (d->socks5State == QSocks5SocketEnginePrivate::UdpAssociateSuccess) {
  1219. setState(QAbstractSocket::BoundState);
  1220. d->udpData->associateAddress = d->localAddress;
  1221. d->localAddress = QHostAddress();
  1222. d->udpData->associatePort = d->localPort;
  1223. d->localPort = 0;
  1224. QUdpSocket dummy;
  1225. #ifndef QT_NO_BEARERMANAGEMENT
  1226. dummy.setProperty("_q_networksession", property("_q_networksession"));
  1227. #endif
  1228. dummy.setProxy(QNetworkProxy::NoProxy);
  1229. if (!dummy.bind()
  1230. || writeDatagram(0,0, d->data->controlSocket->localAddress(), dummy.localPort()) != 0
  1231. || !dummy.waitForReadyRead(qt_timeout_value(msecs, stopWatch.elapsed()))
  1232. || dummy.readDatagram(0,0, &d->localAddress, &d->localPort) != 0) {
  1233. QSOCKS5_DEBUG << "udp actual address and port lookup failed";
  1234. setState(QAbstractSocket::UnconnectedState);
  1235. setError(dummy.error(), dummy.errorString());
  1236. d->data->controlSocket->close();
  1237. //### reset and error
  1238. return false;
  1239. }
  1240. QSOCKS5_DEBUG << "udp actual address and port" << d->localAddress << ':' << d->localPort;
  1241. return true;
  1242. #endif // QT_NO_UDPSOCKET
  1243. }
  1244. // binding timed out
  1245. setError(QAbstractSocket::SocketTimeoutError,
  1246. QLatin1String(QT_TRANSLATE_NOOP("QSocks5SocketEngine", "Network operation timed out")));
  1247. ///### delete d->udpSocket;
  1248. ///### d->udpSocket = 0;
  1249. return false;
  1250. }
  1251. bool QSocks5SocketEngine::listen()
  1252. {
  1253. Q_D(QSocks5SocketEngine);
  1254. QSOCKS5_Q_DEBUG << "listen()";
  1255. // check that we are in bound and then go to listening.
  1256. if (d->socketState == QAbstractSocket::BoundState) {
  1257. d->socketState = QAbstractSocket::ListeningState;
  1258. // check if we already have a connection
  1259. if (d->socks5State == QSocks5SocketEnginePrivate::BindSuccess)
  1260. d->emitReadNotification();
  1261. return true;
  1262. }
  1263. return false;
  1264. }
  1265. int QSocks5SocketEngine::accept()
  1266. {
  1267. Q_D(QSocks5SocketEngine);
  1268. // check we are listing ---
  1269. QSOCKS5_Q_DEBUG << "accept()";
  1270. if (d->socks5State == QSocks5SocketEnginePrivate::BindSuccess) {
  1271. QSOCKS5_Q_DEBUG << "BindSuccess adding" << d->socketDescriptor << "to the bind store";
  1272. d->data->controlSocket->disconnect();
  1273. d->data->controlSocket->setParent(0);
  1274. d->bindData->localAddress = d->localAddress;
  1275. d->bindData->localPort = d->localPort;
  1276. int sd = d->socketDescriptor;
  1277. socks5BindStore()->add(sd, d->bindData);
  1278. d->data = 0;
  1279. d->bindData = 0;
  1280. d->socketDescriptor = 0;
  1281. //### do something about this socket layer ... set it closed and an error about why ...
  1282. // reset state and local port/address
  1283. d->socks5State = QSocks5SocketEnginePrivate::Uninitialized; // ..??
  1284. d->socketState = QAbstractSocket::UnconnectedState;
  1285. return sd;
  1286. }
  1287. return -1;
  1288. }
  1289. void QSocks5SocketEngine::close()
  1290. {
  1291. QSOCKS5_Q_DEBUG << "close()";
  1292. Q_D(QSocks5SocketEngine);
  1293. if (d->data && d->data->controlSocket) {
  1294. if (d->data->controlSocket->state() == QAbstractSocket::ConnectedState) {
  1295. int msecs = 100;
  1296. QElapsedTimer stopWatch;
  1297. stopWatch.start();
  1298. while (!d->data->controlSocket->bytesToWrite()) {
  1299. if (!d->data->controlSocket->waitForBytesWritten(qt_timeout_value(msecs, stopWatch.elapsed())))
  1300. break;
  1301. }
  1302. }
  1303. d->data->controlSocket->close();
  1304. }
  1305. #ifndef QT_NO_UDPSOCKET
  1306. if (d->udpData && d->udpData->udpSocket)
  1307. d->udpData->udpSocket->close();
  1308. #endif
  1309. }
  1310. qint64 QSocks5SocketEngine::bytesAvailable() const
  1311. {
  1312. Q_D(const QSocks5SocketEngine);
  1313. if (d->mode == QSocks5SocketEnginePrivate::ConnectMode)
  1314. return d->connectData->readBuffer.size();
  1315. #ifndef QT_NO_UDPSOCKET
  1316. else if (d->mode == QSocks5SocketEnginePrivate::UdpAssociateMode
  1317. && !d->udpData->pendingDatagrams.isEmpty())
  1318. return d->udpData->pendingDatagrams.first().data.size();
  1319. #endif
  1320. return 0;
  1321. }
  1322. qint64 QSocks5SocketEngine::read(char *data, qint64 maxlen)
  1323. {
  1324. Q_D(QSocks5SocketEngine);
  1325. QSOCKS5_Q_DEBUG << "read( , maxlen = " << maxlen << ')';
  1326. if (d->mode == QSocks5SocketEnginePrivate::ConnectMode) {
  1327. if (d->connectData->readBuffer.size() == 0) {
  1328. if (d->data->controlSocket->state() == QAbstractSocket::UnconnectedState) {
  1329. //imitate remote closed
  1330. close();
  1331. setError(QAbstractSocket::RemoteHostClosedError,
  1332. QLatin1String("Remote host closed connection###"));
  1333. setState(QAbstractSocket::UnconnectedState);
  1334. return -1;
  1335. } else {
  1336. return 0; // nothing to be read
  1337. }
  1338. }
  1339. qint64 copy = qMin<qint64>(d->connectData->readBuffer.size(), maxlen);
  1340. memcpy(data, d->connectData->readBuffer.constData(), copy);
  1341. d->connectData->readBuffer.remove(0, copy);
  1342. QSOCKS5_DEBUG << "read" << dump(QByteArray(data, copy));
  1343. return copy;
  1344. #ifndef QT_NO_UDPSOCKET
  1345. } else if (d->mode == QSocks5SocketEnginePrivate::UdpAssociateMode) {
  1346. return readDatagram(data, maxlen);
  1347. #endif
  1348. }
  1349. return 0;
  1350. }
  1351. qint64 QSocks5SocketEngine::write(const char *data, qint64 len)
  1352. {
  1353. Q_D(QSocks5SocketEngine);
  1354. QSOCKS5_Q_DEBUG << "write" << dump(QByteArray(data, len));
  1355. if (d->mode == QSocks5SocketEnginePrivate::ConnectMode) {
  1356. // clamp down the amount of bytes to transfer at once
  1357. len = qMin<qint64>(len, MaxWriteBufferSize) - d->data->controlSocket->bytesToWrite();
  1358. if (len <= 0)
  1359. return 0;
  1360. QByteArray buf = QByteArray::fromRawData(data, len);
  1361. QByteArray sealedBuf;
  1362. if (!d->data->authenticator->seal(buf, &sealedBuf)) {
  1363. // ### Handle this error.
  1364. }
  1365. qint64 written = d->data->controlSocket->write(sealedBuf);
  1366. if (written <= 0) {
  1367. QSOCKS5_Q_DEBUG << "native write returned" << written;
  1368. return written;
  1369. }
  1370. d->data->controlSocket->waitForBytesWritten(0);
  1371. //NB: returning len rather than written for the OK case, because the "sealing" may increase the length
  1372. return len;
  1373. #ifndef QT_NO_UDPSOCKET
  1374. } else if (d->mode == QSocks5SocketEnginePrivate::UdpAssociateMode) {
  1375. // send to connected address
  1376. return writeDatagram(data, len, d->peerAddress, d->peerPort);
  1377. #endif
  1378. }
  1379. //### set an error ???
  1380. return -1;
  1381. }
  1382. #ifndef QT_NO_UDPSOCKET
  1383. #ifndef QT_NO_NETWORKINTERFACE
  1384. bool QSocks5SocketEngine::joinMulticastGroup(const QHostAddress &,
  1385. const QNetworkInterface &)
  1386. {
  1387. setError(QAbstractSocket::UnsupportedSocketOperationError,
  1388. QLatin1String("Operation on socket is not supported"));
  1389. return false;
  1390. }
  1391. bool QSocks5SocketEngine::leaveMulticastGroup(const QHostAddress &,
  1392. const QNetworkInterface &)
  1393. {
  1394. setError(QAbstractSocket::UnsupportedSocketOperationError,
  1395. QLatin1String("Operation on socket is not supported"));
  1396. return false;
  1397. }
  1398. QNetworkInterface QSocks5SocketEngine::multicastInterface() const
  1399. {
  1400. return QNetworkInterface();
  1401. }
  1402. bool QSocks5SocketEngine::setMulticastInterface(const QNetworkInterface &)
  1403. {
  1404. setError(QAbstractSocket::UnsupportedSocketOperationError,
  1405. QLatin1String("Operation on socket is not supported"));
  1406. return false;
  1407. }
  1408. #endif // QT_NO_NETWORKINTERFACE
  1409. qint64 QSocks5SocketEngine::readDatagram(char *data, qint64 maxlen, QHostAddress *addr,
  1410. quint16 *port)
  1411. {
  1412. Q_D(QSocks5SocketEngine);
  1413. d->checkForDatagrams();
  1414. if (d->udpData->pendingDatagrams.isEmpty())
  1415. return 0;
  1416. QSocks5RevivedDatagram datagram = d->udpData->pendingDatagrams.dequeue();
  1417. int copyLen = qMin<int>(maxlen, datagram.data.size());
  1418. memcpy(data, datagram.data.constData(), copyLen);
  1419. if (addr)
  1420. *addr = datagram.address;
  1421. if (port)
  1422. *port = datagram.port;
  1423. return copyLen;
  1424. }
  1425. qint64 QSocks5SocketEngine::writeDatagram(const char *data, qint64 len, const QHostAddress &address,
  1426. quint16 port)
  1427. {
  1428. Q_D(QSocks5SocketEngine);
  1429. // it is possible to send with out first binding with udp, but socks5 requires a bind.
  1430. if (!d->data) {
  1431. d->initialize(QSocks5SocketEnginePrivate::UdpAssociateMode);
  1432. // all udp needs to be bound
  1433. if (!bind(QHostAddress(QLatin1String("0.0.0.0")), 0)) {
  1434. //### set error
  1435. return -1;
  1436. }
  1437. }
  1438. QByteArray outBuf;
  1439. outBuf.reserve(270 + len);
  1440. outBuf[0] = 0x00;
  1441. outBuf[1] = 0x00;
  1442. outBuf[2] = 0x00;
  1443. if (!qt_socks5_set_host_address_and_port(address, port, &outBuf)) {
  1444. }
  1445. outBuf += QByteArray(data, len);
  1446. QSOCKS5_DEBUG << "sending" << dump(outBuf);
  1447. QByteArray sealedBuf;
  1448. if (!d->data->authenticator->seal(outBuf, &sealedBuf)) {
  1449. QSOCKS5_DEBUG << "sealing data failed";
  1450. setError(QAbstractSocket::SocketAccessError, d->data->authenticator->errorString());
  1451. return -1;
  1452. }
  1453. if (d->udpData->udpSocket->writeDatagram(sealedBuf, d->udpData->associateAddress, d->udpData->associatePort) != sealedBuf.size()) {
  1454. //### try frgamenting
  1455. if (d->udpData->udpSocket->error() == QAbstractSocket::DatagramTooLargeError)
  1456. setError(d->udpData->udpSocket->error(), d->udpData->udpSocket->errorString());
  1457. //### else maybe more serious error
  1458. return -1;
  1459. }
  1460. return len;
  1461. }
  1462. bool QSocks5SocketEngine::hasPendingDatagrams() const
  1463. {
  1464. Q_D(const QSocks5SocketEngine);
  1465. Q_INIT_CHECK(false);
  1466. d->checkForDatagrams();
  1467. return !d->udpData->pendingDatagrams.isEmpty();
  1468. }
  1469. qint64 QSocks5SocketEngine::pendingDatagramSize() const
  1470. {
  1471. Q_D(const QSocks5SocketEngine);
  1472. d->checkForDatagrams();
  1473. if (!d->udpData->pendingDatagrams.isEmpty())
  1474. return d->udpData->pendingDatagrams.head().data.size();
  1475. return 0;
  1476. }
  1477. #endif // QT_NO_UDPSOCKET
  1478. qint64 QSocks5SocketEngine::bytesToWrite() const
  1479. {
  1480. Q_D(const QSocks5SocketEngine);
  1481. if (d->data && d->data->controlSocket) {
  1482. return d->data->controlSocket->bytesToWrite();
  1483. } else {
  1484. return 0;
  1485. }
  1486. }
  1487. int QSocks5SocketEngine::option(SocketOption option) const
  1488. {
  1489. Q_D(const QSocks5SocketEngine);
  1490. if (d->data && d->data->controlSocket) {
  1491. // convert the enum and call the real socket
  1492. if (option == QAbstractSocketEngine::LowDelayOption)
  1493. return d->data->controlSocket->socketOption(QAbstractSocket::LowDelayOption).toInt();
  1494. if (option == QAbstractSocketEngine::KeepAliveOption)
  1495. return d->data->controlSocket->socketOption(QAbstractSocket::KeepAliveOption).toInt();
  1496. }
  1497. return -1;
  1498. }
  1499. bool QSocks5SocketEngine::setOption(SocketOption option, int value)
  1500. {
  1501. Q_D(QSocks5SocketEngine);
  1502. if (d->data && d->data->controlSocket) {
  1503. // convert the enum and call the real socket
  1504. if (option == QAbstractSocketEngine::LowDelayOption)
  1505. d->data->controlSocket->setSocketOption(QAbstractSocket::LowDelayOption, value);
  1506. if (option == QAbstractSocketEngine::KeepAliveOption)
  1507. d->data->controlSocket->setSocketOption(QAbstractSocket::KeepAliveOption, value);
  1508. return true;
  1509. }
  1510. return false;
  1511. }
  1512. bool QSocks5SocketEnginePrivate::waitForConnected(int msecs, bool *timedOut)
  1513. {
  1514. if (data->controlSocket->state() == QAbstractSocket::UnconnectedState)
  1515. return false;
  1516. const Socks5State wantedState =
  1517. mode == ConnectMode ? Connected :
  1518. mode == BindMode ? BindSuccess :
  1519. UdpAssociateSuccess;
  1520. QElapsedTimer stopWatch;
  1521. stopWatch.start();
  1522. while (socks5State != wantedState) {
  1523. if (!data->controlSocket->waitForReadyRead(qt_timeout_value(msecs, stopWatch.elapsed()))) {
  1524. if (data->controlSocket->state() == QAbstractSocket::UnconnectedState)
  1525. return true;
  1526. setErrorState(QSocks5SocketEnginePrivate::ControlSocketError);
  1527. if (timedOut && data->controlSocket->error() == QAbstractSocket::SocketTimeoutError)
  1528. *timedOut = true;
  1529. return false;
  1530. }
  1531. }
  1532. return true;
  1533. }
  1534. bool QSocks5SocketEngine::waitForRead(int msecs, bool *timedOut)
  1535. {
  1536. Q_D(QSocks5SocketEngine);
  1537. QSOCKS5_DEBUG << "waitForRead" << msecs;
  1538. d->readNotificationActivated = false;
  1539. QElapsedTimer stopWatch;
  1540. stopWatch.start();
  1541. // are we connected yet?
  1542. if (!d->waitForConnected(msecs, timedOut))
  1543. return false;
  1544. if (d->data->controlSocket->state() == QAbstractSocket::UnconnectedState)
  1545. return true;
  1546. // we're connected
  1547. if (d->mode == QSocks5SocketEnginePrivate::ConnectMode ||
  1548. d->mode == QSocks5SocketEnginePrivate::BindMode) {
  1549. while (!d->readNotificationActivated) {
  1550. if (!d->data->controlSocket->waitForReadyRead(qt_timeout_value(msecs, stopWatch.elapsed()))) {
  1551. if (d->data->controlSocket->state() == QAbstractSocket::UnconnectedState)
  1552. return true;
  1553. setError(d->data->controlSocket->error(), d->data->controlSocket->errorString());
  1554. if (timedOut && d->data->controlSocket->error() == QAbstractSocket::SocketTimeoutError)
  1555. *timedOut = true;
  1556. return false;
  1557. }
  1558. }
  1559. #ifndef QT_NO_UDPSOCKET
  1560. } else {
  1561. while (!d->readNotificationActivated) {
  1562. if (!d->udpData->udpSocket->waitForReadyRead(qt_timeout_value(msecs, stopWatch.elapsed()))) {
  1563. setError(d->udpData->udpSocket->error(), d->udpData->udpSocket->errorString());
  1564. if (timedOut && d->udpData->udpSocket->error() == QAbstractSocket::SocketTimeoutError)
  1565. *timedOut = true;
  1566. return false;
  1567. }
  1568. }
  1569. #endif // QT_NO_UDPSOCKET
  1570. }
  1571. bool ret = d->readNotificationActivated;
  1572. d->readNotificationActivated = false;
  1573. QSOCKS5_DEBUG << "waitForRead returned" << ret;
  1574. return ret;
  1575. }
  1576. bool QSocks5SocketEngine::waitForWrite(int msecs, bool *timedOut)
  1577. {
  1578. Q_D(QSocks5SocketEngine);
  1579. QSOCKS5_DEBUG << "waitForWrite" << msecs;
  1580. QElapsedTimer stopWatch;
  1581. stopWatch.start();
  1582. // are we connected yet?
  1583. if (!d->waitForConnected(msecs, timedOut))
  1584. return false;
  1585. if (d->data->controlSocket->state() == QAbstractSocket::UnconnectedState)
  1586. return true;
  1587. // we're connected
  1588. // flush any bytes we may still have buffered in the time that we have left
  1589. if (d->data->controlSocket->bytesToWrite())
  1590. d->data->controlSocket->waitForBytesWritten(qt_timeout_value(msecs, stopWatch.elapsed()));
  1591. while ((msecs == -1 || stopWatch.elapsed() < msecs)
  1592. && d->data->controlSocket->state() == QAbstractSocket::ConnectedState
  1593. && d->data->controlSocket->bytesToWrite() >= MaxWriteBufferSize)
  1594. d->data->controlSocket->waitForBytesWritten(qt_timeout_value(msecs, stopWatch.elapsed()));
  1595. return d->data->controlSocket->bytesToWrite() < MaxWriteBufferSize;
  1596. }
  1597. bool QSocks5SocketEngine::waitForReadOrWrite(bool *readyToRead, bool *readyToWrite,
  1598. bool checkRead, bool checkWrite,
  1599. int msecs, bool *timedOut)
  1600. {
  1601. Q_UNUSED(checkRead);
  1602. if (!checkWrite) {
  1603. bool canRead = waitForRead(msecs, timedOut);
  1604. if (readyToRead)
  1605. *readyToRead = canRead;
  1606. return canRead;
  1607. }
  1608. bool canWrite = waitForWrite(msecs, timedOut);
  1609. if (readyToWrite)
  1610. *readyToWrite = canWrite;
  1611. return canWrite;
  1612. }
  1613. bool QSocks5SocketEngine::isReadNotificationEnabled() const
  1614. {
  1615. Q_D(const QSocks5SocketEngine);
  1616. return d->readNotificationEnabled;
  1617. }
  1618. void QSocks5SocketEngine::setReadNotificationEnabled(bool enable)
  1619. {
  1620. Q_D(QSocks5SocketEngine);
  1621. QSOCKS5_Q_DEBUG << "setReadNotificationEnabled(" << enable << ')';
  1622. bool emitSignal = false;
  1623. if (!d->readNotificationEnabled
  1624. && enable) {
  1625. if (d->mode == QSocks5SocketEnginePrivate::ConnectMode)
  1626. emitSignal = !d->connectData->readBuffer.isEmpty();
  1627. #ifndef QT_NO_UDPSOCKET
  1628. else if (d->mode == QSocks5SocketEnginePrivate::UdpAssociateMode)
  1629. emitSignal = !d->udpData->pendingDatagrams.isEmpty();
  1630. #endif
  1631. else if (d->mode == QSocks5SocketEnginePrivate::BindMode
  1632. && d->socketState == QAbstractSocket::ListeningState
  1633. && d->socks5State == QSocks5SocketEnginePrivate::BindSuccess)
  1634. emitSignal = true;
  1635. }
  1636. d->readNotificationEnabled = enable;
  1637. if (emitSignal)
  1638. d->emitReadNotification();
  1639. }
  1640. bool QSocks5SocketEngine::isWriteNotificationEnabled() const
  1641. {
  1642. Q_D(const QSocks5SocketEngine);
  1643. return d->writeNotificationEnabled;
  1644. }
  1645. void QSocks5SocketEngine::setWriteNotificationEnabled(bool enable)
  1646. {
  1647. Q_D(QSocks5SocketEngine);
  1648. d->writeNotificationEnabled = enable;
  1649. if (enable && d->socketState == QAbstractSocket::ConnectedState) {
  1650. if (d->mode == QSocks5SocketEnginePrivate::ConnectMode && d->data->controlSocket->bytesToWrite())
  1651. return; // will be emitted as a result of bytes written
  1652. d->emitWriteNotification();
  1653. d->writeNotificationActivated = false;
  1654. }
  1655. }
  1656. bool QSocks5SocketEngine::isExceptionNotificationEnabled() const
  1657. {
  1658. Q_D(const QSocks5SocketEngine);
  1659. return d->exceptNotificationEnabled;
  1660. }
  1661. void QSocks5SocketEngine::setExceptionNotificationEnabled(bool enable)
  1662. {
  1663. Q_D(QSocks5SocketEngine);
  1664. d->exceptNotificationEnabled = enable;
  1665. }
  1666. QAbstractSocketEngine *
  1667. QSocks5SocketEngineHandler::createSocketEngine(QAbstractSocket::SocketType socketType,
  1668. const QNetworkProxy &proxy, QObject *parent)
  1669. {
  1670. Q_UNUSED(socketType);
  1671. // proxy type must have been resolved by now
  1672. if (proxy.type() != QNetworkProxy::Socks5Proxy) {
  1673. QSOCKS5_DEBUG << "not proxying";
  1674. return 0;
  1675. }
  1676. QScopedPointer<QSocks5SocketEngine> engine(new QSocks5SocketEngine(parent));
  1677. engine->setProxy(proxy);
  1678. return engine.take();
  1679. }
  1680. QAbstractSocketEngine *QSocks5SocketEngineHandler::createSocketEngine(int socketDescriptor, QObject *parent)
  1681. {
  1682. QSOCKS5_DEBUG << "createSocketEngine" << socketDescriptor;
  1683. if (socks5BindStore()->contains(socketDescriptor)) {
  1684. QSOCKS5_DEBUG << "bind store contains" << socketDescriptor;
  1685. return new QSocks5SocketEngine(parent);
  1686. }
  1687. return 0;
  1688. }
  1689. #endif // QT_NO_SOCKS5
  1690. QT_END_NAMESPACE