/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

Large files are truncated click here to view the full 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->controlSocke