diff options
Diffstat (limited to 'src/network/socket/qsocks5socketengine.cpp')
-rw-r--r-- | src/network/socket/qsocks5socketengine.cpp | 78 |
1 files changed, 37 insertions, 41 deletions
diff --git a/src/network/socket/qsocks5socketengine.cpp b/src/network/socket/qsocks5socketengine.cpp index 8e1f9a5e34..0564ad7a33 100644 --- a/src/network/socket/qsocks5socketengine.cpp +++ b/src/network/socket/qsocks5socketengine.cpp @@ -9,6 +9,7 @@ #include "qdebug.h" #include "qhash.h" #include "qqueue.h" +#include "qdeadlinetimer.h" #include "qelapsedtimer.h" #include "qmutex.h" #include "qthread.h" @@ -20,18 +21,21 @@ #include <qendian.h> #include <qnetworkinterface.h> +#include <QtCore/qpointer.h> + #include <memory> QT_BEGIN_NAMESPACE using namespace Qt::StringLiterals; +using namespace std::chrono_literals; static const int MaxWriteBufferSize = 128*1024; //#define QSOCKS5SOCKETLAYER_DEBUG #define MAX_DATA_DUMP 256 -#define SOCKS5_BLOCKING_BIND_TIMEOUT 5000 +static constexpr auto Socks5BlockingBindTimeout = 5s; #define Q_INIT_CHECK(returnValue) do { \ if (!d->data) { \ @@ -154,11 +158,11 @@ static bool qt_socks5_set_host_name_and_port(const QString &hostname, quint16 po QByteArray encodedHostName = QUrl::toAce(hostname); QByteArray &buf = *pBuf; - if (encodedHostName.length() > 255) + if (encodedHostName.size() > 255) return false; buf.append(S5_DOMAINNAME); - buf.append(uchar(encodedHostName.length())); + buf.append(uchar(encodedHostName.size())); buf.append(encodedHostName); // add port @@ -317,9 +321,10 @@ void QSocks5BindStore::add(qintptr socketDescriptor, QSocks5BindData *bindData) } bindData->timeStamp.start(); store.insert(socketDescriptor, bindData); + // start sweep timer if not started if (sweepTimerId == -1) - sweepTimerId = startTimer(60000); + sweepTimerId = startTimer(1min); } bool QSocks5BindStore::contains(qintptr socketDescriptor) @@ -1325,11 +1330,8 @@ bool QSocks5SocketEngine::bind(const QHostAddress &addr, quint16 port) return false; } - int msecs = SOCKS5_BLOCKING_BIND_TIMEOUT; - QElapsedTimer stopWatch; - stopWatch.start(); d->data->controlSocket->connectToHost(d->proxyInfo.hostName(), d->proxyInfo.port()); - if (!d->waitForConnected(msecs, nullptr) || + if (!d->waitForConnected(QDeadlineTimer{Socks5BlockingBindTimeout}, nullptr) || d->data->controlSocket->state() == QAbstractSocket::UnconnectedState) { // waitForConnected sets the error state and closes the socket QSOCKS5_Q_DEBUG << "waitForConnected to proxy server" << d->data->controlSocket->errorString(); @@ -1379,7 +1381,7 @@ bool QSocks5SocketEngine::listen(int backlog) return false; } -int QSocks5SocketEngine::accept() +qintptr QSocks5SocketEngine::accept() { Q_D(QSocks5SocketEngine); // check we are listing --- @@ -1420,11 +1422,9 @@ void QSocks5SocketEngine::close() Q_D(QSocks5SocketEngine); if (d->data && d->data->controlSocket) { if (d->data->controlSocket->state() == QAbstractSocket::ConnectedState) { - int msecs = 100; - QElapsedTimer stopWatch; - stopWatch.start(); + QDeadlineTimer deadline(100ms); while (!d->data->controlSocket->bytesToWrite()) { - if (!d->data->controlSocket->waitForBytesWritten(qt_subtract_from_timeout(msecs, stopWatch.elapsed()))) + if (!d->data->controlSocket->waitForBytesWritten(deadline.remainingTime())) break; } } @@ -1445,7 +1445,7 @@ qint64 QSocks5SocketEngine::bytesAvailable() const #ifndef QT_NO_UDPSOCKET else if (d->mode == QSocks5SocketEnginePrivate::UdpAssociateMode && !d->udpData->pendingDatagrams.isEmpty()) - return d->udpData->pendingDatagrams.first().data.size(); + return d->udpData->pendingDatagrams.constFirst().data.size(); #endif return 0; } @@ -1677,7 +1677,7 @@ bool QSocks5SocketEngine::setOption(SocketOption option, int value) return false; } -bool QSocks5SocketEnginePrivate::waitForConnected(int msecs, bool *timedOut) +bool QSocks5SocketEnginePrivate::waitForConnected(QDeadlineTimer deadline, bool *timedOut) { if (data->controlSocket->state() == QAbstractSocket::UnconnectedState) return false; @@ -1687,11 +1687,8 @@ bool QSocks5SocketEnginePrivate::waitForConnected(int msecs, bool *timedOut) mode == BindMode ? BindSuccess : UdpAssociateSuccess; - QElapsedTimer stopWatch; - stopWatch.start(); - while (socks5State != wantedState) { - if (!data->controlSocket->waitForReadyRead(qt_subtract_from_timeout(msecs, stopWatch.elapsed()))) { + if (!data->controlSocket->waitForReadyRead(deadline.remainingTime())) { if (data->controlSocket->state() == QAbstractSocket::UnconnectedState) return true; @@ -1705,18 +1702,15 @@ bool QSocks5SocketEnginePrivate::waitForConnected(int msecs, bool *timedOut) return true; } -bool QSocks5SocketEngine::waitForRead(int msecs, bool *timedOut) +bool QSocks5SocketEngine::waitForRead(QDeadlineTimer deadline, bool *timedOut) { Q_D(QSocks5SocketEngine); - QSOCKS5_DEBUG << "waitForRead" << msecs; + QSOCKS5_DEBUG << "waitForRead" << deadline.remainingTimeAsDuration(); d->readNotificationActivated = false; - QElapsedTimer stopWatch; - stopWatch.start(); - // are we connected yet? - if (!d->waitForConnected(msecs, timedOut)) + if (!d->waitForConnected(deadline, timedOut)) return false; if (d->data->controlSocket->state() == QAbstractSocket::UnconnectedState) return true; @@ -1730,7 +1724,7 @@ bool QSocks5SocketEngine::waitForRead(int msecs, bool *timedOut) if (d->mode == QSocks5SocketEnginePrivate::ConnectMode || d->mode == QSocks5SocketEnginePrivate::BindMode) { while (!d->readNotificationActivated) { - if (!d->data->controlSocket->waitForReadyRead(qt_subtract_from_timeout(msecs, stopWatch.elapsed()))) { + if (!d->data->controlSocket->waitForReadyRead(deadline.remainingTime())) { if (d->data->controlSocket->state() == QAbstractSocket::UnconnectedState) return true; @@ -1743,7 +1737,7 @@ bool QSocks5SocketEngine::waitForRead(int msecs, bool *timedOut) #ifndef QT_NO_UDPSOCKET } else { while (!d->readNotificationActivated) { - if (!d->udpData->udpSocket->waitForReadyRead(qt_subtract_from_timeout(msecs, stopWatch.elapsed()))) { + if (!d->udpData->udpSocket->waitForReadyRead(deadline.remainingTime())) { setError(d->udpData->udpSocket->error(), d->udpData->udpSocket->errorString()); if (timedOut && d->udpData->udpSocket->error() == QAbstractSocket::SocketTimeoutError) *timedOut = true; @@ -1762,16 +1756,13 @@ bool QSocks5SocketEngine::waitForRead(int msecs, bool *timedOut) } -bool QSocks5SocketEngine::waitForWrite(int msecs, bool *timedOut) +bool QSocks5SocketEngine::waitForWrite(QDeadlineTimer deadline, bool *timedOut) { Q_D(QSocks5SocketEngine); - QSOCKS5_DEBUG << "waitForWrite" << msecs; - - QElapsedTimer stopWatch; - stopWatch.start(); + QSOCKS5_DEBUG << "waitForWrite" << deadline.remainingTimeAsDuration(); // are we connected yet? - if (!d->waitForConnected(msecs, timedOut)) + if (!d->waitForConnected(deadline, timedOut)) return false; if (d->data->controlSocket->state() == QAbstractSocket::UnconnectedState) return true; @@ -1780,27 +1771,32 @@ bool QSocks5SocketEngine::waitForWrite(int msecs, bool *timedOut) // flush any bytes we may still have buffered in the time that we have left if (d->data->controlSocket->bytesToWrite()) - d->data->controlSocket->waitForBytesWritten(qt_subtract_from_timeout(msecs, stopWatch.elapsed())); - while ((msecs == -1 || stopWatch.elapsed() < msecs) - && d->data->controlSocket->state() == QAbstractSocket::ConnectedState - && d->data->controlSocket->bytesToWrite() >= MaxWriteBufferSize) - d->data->controlSocket->waitForBytesWritten(qt_subtract_from_timeout(msecs, stopWatch.elapsed())); + d->data->controlSocket->waitForBytesWritten(deadline.remainingTime()); + + auto shouldWriteBytes = [&]() { + return d->data->controlSocket->state() == QAbstractSocket::ConnectedState + && d->data->controlSocket->bytesToWrite() >= MaxWriteBufferSize; + }; + + qint64 remainingTime = deadline.remainingTime(); + for (; remainingTime > 0 && shouldWriteBytes(); remainingTime = deadline.remainingTime()) + d->data->controlSocket->waitForBytesWritten(remainingTime); return d->data->controlSocket->bytesToWrite() < MaxWriteBufferSize; } bool QSocks5SocketEngine::waitForReadOrWrite(bool *readyToRead, bool *readyToWrite, bool checkRead, bool checkWrite, - int msecs, bool *timedOut) + QDeadlineTimer deadline, bool *timedOut) { Q_UNUSED(checkRead); if (!checkWrite) { - bool canRead = waitForRead(msecs, timedOut); + bool canRead = waitForRead(deadline, timedOut); if (readyToRead) *readyToRead = canRead; return canRead; } - bool canWrite = waitForWrite(msecs, timedOut); + bool canWrite = waitForWrite(deadline, timedOut); if (readyToWrite) *readyToWrite = canWrite; return canWrite; |