📄 qsocks5socketengine.cpp
字号:
QSOCKS5_Q_DEBUG << "close()"; Q_D(QSocks5SocketEngine); if (d->data && d->data->controlSocket) { if (d->data->controlSocket->state() == QAbstractSocket::ConnectedState) { int msecs = 100; QTime stopWatch; stopWatch.start(); while (!d->data->controlSocket->bytesToWrite()) { if (!d->data->controlSocket->waitForBytesWritten(qt_timeout_value(msecs, stopWatch.elapsed()))) break; } } d->data->controlSocket->close(); }#ifndef QT_NO_UDPSOCKET if (d->udpData && d->udpData->udpSocket) d->udpData->udpSocket->close();#endif}qint64 QSocks5SocketEngine::bytesAvailable() const{ Q_D(const QSocks5SocketEngine); if (d->mode == QSocks5SocketEnginePrivate::ConnectMode) return d->connectData->readBuffer.size();#ifndef QT_NO_UDPSOCKET else if (d->mode == QSocks5SocketEnginePrivate::UdpAssociateMode && !d->udpData->pendingDatagrams.isEmpty()) return d->udpData->pendingDatagrams.first().data.size();#endif return 0;}qint64 QSocks5SocketEngine::read(char *data, qint64 maxlen){ Q_D(QSocks5SocketEngine); QSOCKS5_Q_DEBUG << "read( , maxlen = " << maxlen << ")"; if (d->mode == QSocks5SocketEnginePrivate::ConnectMode) { if (d->connectData->readBuffer.size() == 0) { //imitate remote closed close(); setError(QAbstractSocket::RemoteHostClosedError, QLatin1String("Remote host closed connection###")); setState(QAbstractSocket::UnconnectedState); return -1; } qint64 copy = qMin<qint64>(d->connectData->readBuffer.size(), maxlen); memcpy(data, d->connectData->readBuffer.constData(), copy); d->connectData->readBuffer.remove(0, copy); QSOCKS5_DEBUG << "read" << dump(QByteArray(data, copy)); return copy;#ifndef QT_NO_UDPSOCKET } else if (d->mode == QSocks5SocketEnginePrivate::UdpAssociateMode) { return readDatagram(data, maxlen);#endif } return 0;}qint64 QSocks5SocketEngine::write(const char *data, qint64 len){ Q_D(QSocks5SocketEngine); QSOCKS5_Q_DEBUG << "write" << dump(QByteArray(data, len)); if (d->mode == QSocks5SocketEnginePrivate::ConnectMode) { int msecs = 10; QTime stopWatch; stopWatch.start(); qint64 totalWritten = 0; while (totalWritten < len && stopWatch.elapsed() < msecs) { QByteArray buf(data + totalWritten, qMin<int>(len - totalWritten, 49152)); QByteArray sealedBuf; if (!d->data->authenticator->seal(buf, &sealedBuf)) { // ### Handle this error. } int written = d->data->controlSocket->write(sealedBuf); if (written != sealedBuf.size()) { QSOCKS5_Q_DEBUG << "control socket write failed :" << d->data->controlSocket->errorString(); setError(d->data->controlSocket->error(), d->data->controlSocket->errorString()); return -1; //### ????? } totalWritten += buf.size(); while(d->data->controlSocket->bytesToWrite()) { if (!d->data->controlSocket->waitForBytesWritten(qt_timeout_value(msecs, stopWatch.elapsed()))) { QSOCKS5_Q_DEBUG << "controlSocket->waitForBytesWritten() retruned false"; break; } } if (d->data->controlSocket->error() != QAbstractSocket::UnknownSocketError && d->data->controlSocket->error() != QAbstractSocket::SocketTimeoutError) { QSOCKS5_DEBUG << "control socket error while writing. -- " << d->data->controlSocket->errorString(); totalWritten = -1; break; } } QSOCKS5_DEBUG << "wrote" << totalWritten; return totalWritten;#ifndef QT_NO_UDPSOCKET } else if (d->mode == QSocks5SocketEnginePrivate::UdpAssociateMode) { // send to connected address return writeDatagram(data, len, d->peerAddress, d->peerPort);#endif } //### set an error ??? return -1;}#ifndef QT_NO_UDPSOCKETqint64 QSocks5SocketEngine::readDatagram(char *data, qint64 maxlen, QHostAddress *addr, quint16 *port){ Q_D(QSocks5SocketEngine); d->checkForDatagrams(); if (d->udpData->pendingDatagrams.isEmpty()) return 0; QSocks5RevivedDatagram datagram = d->udpData->pendingDatagrams.dequeue(); int copyLen = qMin<int>(maxlen, datagram.data.size()); memcpy(data, datagram.data.constData(), copyLen); if (addr) *addr = datagram.address; if (port) *port = datagram.port; return copyLen;}qint64 QSocks5SocketEngine::writeDatagram(const char *data, qint64 len, const QHostAddress &address, quint16 port){ Q_D(QSocks5SocketEngine); // it is possible to send with out first binding with udp, but socks5 requires a bind. if (!d->data) { d->initialize(QSocks5SocketEnginePrivate::UdpAssociateMode); // all udp needs to be bound if (!bind(QHostAddress(QLatin1String("0.0.0.0")), 0)) { //### set error return -1; } } QByteArray outBuf; outBuf.reserve(270 + len); int pos = 0; outBuf[pos++] = 0x00; outBuf[pos++] = 0x00; outBuf[pos++] = 0x00; if (!qt_socks5_set_host_address_and_port(address, port, &outBuf, &pos)) { } outBuf += QByteArray(data, len); QSOCKS5_DEBUG << "sending" << dump(outBuf); QByteArray sealedBuf; if (!d->data->authenticator->seal(outBuf, &sealedBuf)) { QSOCKS5_DEBUG << "sealing data failed"; setError(QAbstractSocket::SocketAccessError, d->data->authenticator->errorString()); return -1; } if (d->udpData->udpSocket->writeDatagram(sealedBuf, d->udpData->associateAddress, d->udpData->associatePort) != sealedBuf.size()) { //### try frgamenting if (d->udpData->udpSocket->error() == QAbstractSocket::DatagramTooLargeError) setError(d->udpData->udpSocket->error(), d->udpData->udpSocket->errorString()); //### else maybe more serious error return -1; } return len;}bool QSocks5SocketEngine::hasPendingDatagrams() const{ Q_D(const QSocks5SocketEngine); Q_INIT_CHECK(false); d->checkForDatagrams(); return !d->udpData->pendingDatagrams.isEmpty();}qint64 QSocks5SocketEngine::pendingDatagramSize() const{ Q_D(const QSocks5SocketEngine); d->checkForDatagrams(); if (!d->udpData->pendingDatagrams.isEmpty()) return d->udpData->pendingDatagrams.head().data.size(); return 0;}#endif // QT_NO_UDPSOCKETint QSocks5SocketEngine::option(SocketOption option) const{ Q_UNUSED(option); return -1;}bool QSocks5SocketEngine::setOption(SocketOption option, int value){ Q_UNUSED(option); Q_UNUSED(value); return false;}bool QSocks5SocketEngine::waitForRead(int msecs, bool *timedOut) const{ Q_D(const QSocks5SocketEngine); QSOCKS5_DEBUG << "waitForRead" << msecs; d->readNotificationActivated = false; QTime stopWatch; stopWatch.start(); if (socketType() == QAbstractSocket::TcpSocket) { // check for pending data if (d->data->controlSocket->bytesAvailable()) const_cast<QSocks5SocketEnginePrivate*>(d)->_q_controlSocketReadNotification(); bool success = true; while (!d->readNotificationActivated && (success = d->data->controlSocket->waitForReadyRead(qt_timeout_value(msecs, stopWatch.elapsed())))) { QSOCKS5_DEBUG << "looping"; } if (!success) { setError(d->data->controlSocket->error(), d->data->controlSocket->errorString()); if (timedOut && d->data->controlSocket->error() == QAbstractSocket::SocketTimeoutError) *timedOut = true; if (d->data->controlSocket->state() == QAbstractSocket::UnconnectedState) d->readNotificationActivated = true; }#ifndef QT_NO_UDPSOCKET } else { // what about if the tcp socket is disconnected ... while (!d->readNotificationActivated && d->udpData->udpSocket->waitForReadyRead(qt_timeout_value(msecs, stopWatch.elapsed()))) { QSOCKS5_DEBUG << "looping"; } if (d->udpData->udpSocket->error() != QAbstractSocket::UnknownSocketError) { setError(d->udpData->udpSocket->error(), d->udpData->udpSocket->errorString()); if (timedOut && d->udpData->udpSocket->error() == QAbstractSocket::SocketTimeoutError) *timedOut = true; }#endif // QT_NO_UDPSOCKET } bool ret = d->readNotificationActivated; d->readNotificationActivated = false; QSOCKS5_DEBUG << "waitForRead returned" << ret; return ret;}bool QSocks5SocketEngine::waitForWrite(int msecs, bool *timedOut) const{ Q_D(const QSocks5SocketEngine); QSOCKS5_DEBUG << "waitForWrite" << msecs; if (d->socketState == QAbstractSocket::ConnectingState) { d->writeNotificationActivated = false; QSOCKS5_DEBUG << "waitForWrite ... waiting for connected"; QTime stopWatch; stopWatch.start(); if (!d->data->controlSocket->waitForConnected(qt_timeout_value(msecs, stopWatch.elapsed()))) { // qDebug() << "failed to connect to proxy"; if (timedOut && d->data->controlSocket->error() == QAbstractSocket::SocketTimeoutError) *timedOut = true; return false; // ??? } QSOCKS5_DEBUG << "waitForWrite ... waiting for proxy init" << msecs; while (!d->writeNotificationActivated && d->data->controlSocket->waitForReadyRead(qt_timeout_value(msecs, stopWatch.elapsed()))) { QSOCKS5_DEBUG << "looping"; } if (timedOut && d->data->controlSocket->error() == QAbstractSocket::SocketTimeoutError) { QSOCKS5_DEBUG << "timeout"; *timedOut = true; } bool ret = d->writeNotificationActivated; d->writeNotificationActivated = false; return ret; } // probably just return true unless we are not set up ?? if (d->socketState == QAbstractSocket::ConnectedState) { if (d->mode == QSocks5SocketEnginePrivate::ConnectMode) { //### check for time out; while(d->data->controlSocket->bytesToWrite()) d->data->controlSocket->waitForBytesWritten(); } return true; } return false;}bool QSocks5SocketEngine::waitForReadOrWrite(bool *readyToRead, bool *readyToWrite, bool checkRead, bool checkWrite, int msecs, bool *timedOut) const{ Q_UNUSED(checkRead); if (!checkWrite) { bool canRead = waitForRead(msecs, timedOut); if (readyToRead) *readyToRead = canRead; return canRead; } bool canWrite = waitForWrite(msecs, timedOut); if (readyToWrite) *readyToWrite = canWrite; return canWrite;}bool QSocks5SocketEngine::isReadNotificationEnabled() const{ Q_D(const QSocks5SocketEngine); return d->readNotificationEnabled;}void QSocks5SocketEngine::setReadNotificationEnabled(bool enable){ Q_D(QSocks5SocketEngine); QSOCKS5_Q_DEBUG << "setReadNotificationEnabled(" << enable << ")"; bool emitSignal = false; if (!d->readNotificationEnabled && enable) { if (d->mode == QSocks5SocketEnginePrivate::ConnectMode) emitSignal = !d->connectData->readBuffer.isEmpty();#ifndef QT_NO_UDPSOCKET else if (d->mode == QSocks5SocketEnginePrivate::UdpAssociateMode) emitSignal = !d->udpData->pendingDatagrams.isEmpty();#endif else if (d->mode == QSocks5SocketEnginePrivate::BindMode && d->socketState == QAbstractSocket::ListeningState && d->socks5State == QSocks5SocketEnginePrivate::BindSuccess) emitSignal = true; } d->readNotificationEnabled = enable; if (emitSignal) d->emitReadNotification();}bool QSocks5SocketEngine::isWriteNotificationEnabled() const{ Q_D(const QSocks5SocketEngine); return d->writeNotificationEnabled;}void QSocks5SocketEngine::setWriteNotificationEnabled(bool enable){ Q_D(QSocks5SocketEngine); d->writeNotificationEnabled = enable; if (enable && d->socketState == QAbstractSocket::ConnectedState) { if (d->mode == QSocks5SocketEnginePrivate::ConnectMode && d->data->controlSocket->bytesToWrite()) return; // will be emitted as a result of bytes written d->emitWriteNotification(); d->writeNotificationActivated = false; }}bool QSocks5SocketEngine::isExceptionNotificationEnabled() const{ Q_D(const QSocks5SocketEngine); return d->exceptNotificationEnabled;}void QSocks5SocketEngine::setExceptionNotificationEnabled(bool enable){ Q_D(QSocks5SocketEngine); d->exceptNotificationEnabled = enable;}QAbstractSocketEngine *QSocks5SocketEngineHandler::createSocketEngine(const QHostAddress &address, QAbstractSocket::SocketType socketType, QObject *parent){ Q_UNUSED(socketType); QSOCKS5_DEBUG << "createSocketEngine" << address; if (address == QHostAddress::LocalHost || address == QHostAddress::LocalHostIPv6) { QSOCKS5_DEBUG << "not proxying"; return 0; } QNetworkProxy proxy; // find proxy info if (qobject_cast<QAbstractSocket *>(parent)) { QAbstractSocket *abstractSocket = qobject_cast<QAbstractSocket *>(parent); if (abstractSocket->proxy().type() != QNetworkProxy::DefaultProxy) proxy = abstractSocket->proxy(); } else if (qobject_cast<QTcpServer *>(parent)) { QTcpServer *server = qobject_cast<QTcpServer *>(parent); if (server->proxy().type() != QNetworkProxy::DefaultProxy) proxy = server->proxy(); } if (proxy.type() == QNetworkProxy::DefaultProxy) { proxy = QNetworkProxy::applicationProxy(); } if (proxy.type() == QNetworkProxy::DefaultProxy || proxy.type() == QNetworkProxy::NoProxy || proxy.type() != QNetworkProxy::Socks5Proxy) { QSOCKS5_DEBUG << "not proxying"; return 0; } QSOCKS5_DEBUG << "use proxy for" << address; QSocks5SocketEngine *engine = new QSocks5SocketEngine(parent); engine->setProxy(proxy); return engine;}QAbstractSocketEngine *QSocks5SocketEngineHandler::createSocketEngine(int socketDescriptor, QObject *parent){ QSOCKS5_DEBUG << "createSocketEngine" << socketDescriptor; if (socks5BindStore()->contains(socketDescriptor)) { QSOCKS5_DEBUG << "bind store contains" << socketDescriptor; return new QSocks5SocketEngine(parent); } return 0;}#endif // QT_NO_SOCKS5
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -