📄 qsocks5socketengine.cpp
字号:
Q_UNUSED(socket); *completed = true; return true;}bool QSocks5Authenticator::continueAuthenticate(QTcpSocket *socket, bool *completed){ Q_UNUSED(socket); *completed = true; return true;}bool QSocks5Authenticator::seal(const QByteArray buf, QByteArray *sealedBuf){ *sealedBuf = buf; return true;}bool QSocks5Authenticator::unSeal(const QByteArray sealedBuf, QByteArray *buf){ *buf = sealedBuf; return true;}bool QSocks5Authenticator::unSeal(QTcpSocket *sealedSocket, QByteArray *buf){ return unSeal(sealedSocket->readAll(), buf);}QSocks5PasswordAuthenticator::QSocks5PasswordAuthenticator(const QString &userName, const QString &password){ this->userName = userName; this->password = password;}char QSocks5PasswordAuthenticator::methodId(){ return 0x02;}bool QSocks5PasswordAuthenticator::beginAuthenticate(QTcpSocket *socket, bool *completed){ *completed = false; QByteArray uname = userName.toLatin1(); QByteArray passwd = password.toLatin1(); QByteArray dataBuf(3 + uname.size() + passwd.size(), 0); char *buf = dataBuf.data(); int pos = 0; buf[pos++] = 0x01; buf[pos++] = uname.size(); memcpy(&buf[pos], uname.data(), uname.size()); pos += uname.size(); buf[pos++] = passwd.size(); memcpy(&buf[pos], passwd.data(), passwd.size()); return socket->write(dataBuf) == dataBuf.size();}bool QSocks5PasswordAuthenticator::continueAuthenticate(QTcpSocket *socket, bool *completed){ *completed = false; if (socket->bytesAvailable() < 2) return true; QByteArray buf = socket->read(2); if (buf.at(0) == 0x01) { *completed = true; return buf.at(1) == 0x00; } return false;}QString QSocks5PasswordAuthenticator::errorString(){ return QLatin1String("Socks5 user name or password incorrect");}QSocks5SocketEnginePrivate::QSocks5SocketEnginePrivate() : socks5State(unInitialized) , readNotificationEnabled(false) , writeNotificationEnabled(false) , exceptNotificationEnabled(false) , socketDescriptor(-1) , data(0) , connectData(0)#ifndef QT_NO_UDPSOCKET , udpData(0)#endif , bindData(0) , readNotificationActivated(false) , writeNotificationActivated(false) , readNotificationPending(false) , writeNotificationPending(false){ mode = NoMode;}QSocks5SocketEnginePrivate::~QSocks5SocketEnginePrivate(){}void QSocks5SocketEnginePrivate::initialize(Socks5Mode socks5Mode){ Q_Q(QSocks5SocketEngine); mode = socks5Mode; if (mode == ConnectMode) { connectData = new QSocks5ConnectData; data = connectData;#ifndef QT_NO_UDPSOCKET } else if (mode == UdpAssociateMode) { udpData = new QSocks5UdpAssociateData; data = udpData; udpData->udpSocket = new QUdpSocket(q); QNetworkProxy proxy; proxy.setType(QNetworkProxy::NoProxy); udpData->udpSocket->setProxy(proxy); QObject::connect(udpData->udpSocket, SIGNAL(readyRead()), q, SLOT(_q_udpSocketReadNotification()));#endif // QT_NO_UDPSOCKET } else if (mode == BindMode) { bindData = new QSocks5BindData; data = bindData; } data->controlSocket = new QTcpSocket(q); QNetworkProxy proxy; proxy.setType(QNetworkProxy::NoProxy); data->controlSocket->setProxy(proxy); QObject::connect(data->controlSocket, SIGNAL(connected()), q, SLOT(_q_controlSocketConnected())); QObject::connect(data->controlSocket, SIGNAL(readyRead()), q, SLOT(_q_controlSocketReadNotification())); QObject::connect(data->controlSocket, SIGNAL(bytesWritten(qint64)), q, SLOT(_q_controlSocketBytesWritten())); QObject::connect(data->controlSocket, SIGNAL(error(QAbstractSocket::SocketError)), q, SLOT(_q_controlSocketError(QAbstractSocket::SocketError))); QObject::connect(data->controlSocket, SIGNAL(disconnected()), q, SLOT(_q_controlSocketDisconnected())); QObject::connect(data->controlSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), q, SLOT(_q_controlSocketStateChanged(QAbstractSocket::SocketState))); //### this should be some where else when authentication methods are public if (!proxyInfo.user().isEmpty() || !proxyInfo.password().isEmpty()) { data->authenticator = new QSocks5PasswordAuthenticator(proxyInfo.user(), proxyInfo.password()); } else { data->authenticator = new QSocks5Authenticator(); }}void QSocks5SocketEnginePrivate::parseAuthenticationMethodReply(){ Q_Q(QSocks5SocketEngine); // not enough data to begin if (data->controlSocket->bytesAvailable() < 2) return; QByteArray buf(2, 0); if (data->controlSocket->read(buf.data(), 2) != 2) { QSOCKS5_D_DEBUG << "Control socket read failure"; socks5State = AuthenticatingError; q->setError(QAbstractSocket::NetworkError, QLatin1String("Socks5 read error on control socket")); data->controlSocket->close(); emitWriteNotification(); return; } if (buf.at(0) != S5_VERSION_5) { QSOCKS5_D_DEBUG << "Socks5 version incorrect"; socks5State = AuthenticatingError; q->setError(QAbstractSocket::NetworkError, QLatin1String("Socks5 version incorrect")); data->controlSocket->close(); emitWriteNotification(); return; } if (uchar(buf.at(1)) == 0xFF) { QSOCKS5_D_DEBUG << "Authentication method not supported"; socks5State = AuthenticatingError; q->setError(QAbstractSocket::SocketAccessError, QLatin1String("Socks5 host did not support authentication method.")); emitWriteNotification(); return; } if (buf.at(1) != data->authenticator->methodId()) { QSOCKS5_D_DEBUG << "Authentication method was not what we sent"; socks5State = AuthenticatingError; q->setError(QAbstractSocket::SocketAccessError, QLatin1String("Socks5 host did not support authentication method.")); emitWriteNotification(); return; } bool AuthComplete = false; if (!data->authenticator->beginAuthenticate(data->controlSocket, &AuthComplete)) { QSOCKS5_D_DEBUG << "Authentication faled" << data->authenticator->errorString(); socks5State = AuthenticatingError; q->setError(QAbstractSocket::SocketAccessError, data->authenticator->errorString()); emitWriteNotification(); return; } if (AuthComplete) { sendRequestMethod(); return; } socks5State = Authenticating;}void QSocks5SocketEnginePrivate::parseAuthenticatingReply(){ Q_Q(QSocks5SocketEngine); bool authComplete = false; if (!data->authenticator->continueAuthenticate(data->controlSocket, &authComplete)) { QSOCKS5_D_DEBUG << "Authentication faled" << data->authenticator->errorString(); socks5State = AuthenticatingError; q->setError(QAbstractSocket::SocketAccessError, data->authenticator->errorString()); emitWriteNotification(); return; } if (authComplete) sendRequestMethod();}void QSocks5SocketEnginePrivate::sendRequestMethod(){ QHostAddress address; quint16 port = 0; char command = 0; if (mode == ConnectMode) { command = S5_CONNECT; address = peerAddress; port = peerPort; } else if (mode == BindMode) { command = S5_BIND; address = localAddress; port = localPort; } else {#ifndef QT_NO_UDPSOCKET command = S5_UDP_ASSOCIATE; address = localAddress; //data->controlSocket->localAddress(); port = localPort;#endif } QByteArray buf; buf.reserve(270); // big enough for domain name; int pos = 0; buf[pos++] = S5_VERSION_5; buf[pos++] = command; buf[pos++] = 0x00; if (!qt_socks5_set_host_address_and_port(address, port, &buf, &pos)) { QSOCKS5_DEBUG << "error setting address" << address << " : " << port; //### set error code .... return; } QSOCKS5_DEBUG << "sending" << dump(buf); QByteArray sealedBuf; if (!data->authenticator->seal(buf, &sealedBuf)) { // ### Handle this error. } data->controlSocket->write(sealedBuf); data->controlSocket->flush(); socks5State = RequestMethodSent;}void QSocks5SocketEnginePrivate::parseRequestMethodReply(){ QSOCKS5_DEBUG << "parseRequestMethodReply()"; QByteArray inBuf; if (!data->authenticator->unSeal(data->controlSocket, &inBuf)) { // ### check error and not just not enough data QSOCKS5_DEBUG << "unSeal failed, needs more data"; return; } QSOCKS5_DEBUG << dump(inBuf); int pos = 0; const char *buf = inBuf.constData(); if (inBuf.size() < 2) { QSOCKS5_DEBUG << "need more data for request reply header .. put this data somewhere"; return; } if (buf[pos++] != S5_VERSION_5) { QSOCKS5_DEBUG << "totally lost"; } if (buf[pos++] != S5_SUCCESS ) { socks5Error = Socks5Error(buf[pos-1]); socks5State = RequestError; socks5ErrorString = s5RequestErrorToString(socks5Error); QSOCKS5_DEBUG << "Request error :" << s5RequestErrorToString(socks5Error); emitWriteNotification(); return; } if (buf[pos++] != 0x00) { QSOCKS5_DEBUG << "totally lost"; } if (!qt_socks5_get_host_address_and_port(inBuf, &localAddress, &localPort, &pos)) { QSOCKS5_DEBUG << "error getting address"; //### set error code .... return; } // need a better place to keep this stuff and any others untill connect called again // should use peek inBuf.remove(0, pos); for (int i = inBuf.size() - 1; i >= 0 ; --i) data->controlSocket->ungetChar(inBuf.at(i)); socks5State = RequestSuccess; // fire writeNotifier for connect and wait for the next call to conectTOHost if (mode == ConnectMode) emitWriteNotification();}void QSocks5SocketEnginePrivate::parseNewConnection(){ QSOCKS5_D_DEBUG << "parseNewConnection()"; // only emit readyRead if in listening state ... QByteArray inBuf; if (!data->authenticator->unSeal(data->controlSocket, &inBuf)) { // ### check error and not just not enough data QSOCKS5_DEBUG << "unSeal failed, needs more data"; return; } QSOCKS5_D_DEBUG << dump(inBuf); int pos = 0; const char *buf = inBuf.constData(); if (inBuf.length() < 2) { QSOCKS5_D_DEBUG << "need more data for request reply header .. put this data somewhere"; return; } if (buf[pos++] != S5_VERSION_5) { QSOCKS5_D_DEBUG << "totally lost"; } if (buf[pos++] != S5_SUCCESS) { QSOCKS5_D_DEBUG << "Request error :" << s5RequestErrorToString(buf[pos-1]); socks5State = BindError; socks5Error = Socks5Error(buf[pos-1]); socks5ErrorString = s5RequestErrorToString(socks5Error); // #### now what return; } if (buf[pos++] != 0x00) { QSOCKS5_D_DEBUG << "totally lost"; } if (!qt_socks5_get_host_address_and_port(inBuf, &bindData->peerAddress, &bindData->peerPort, &pos)) { QSOCKS5_D_DEBUG << "error getting address"; //### set error code .... return; } // need a better place to keep this stuff and any others untill connect called again // should use peek inBuf.remove(0, pos); for (int i = inBuf.size() - 1; i >= 0 ; --i) data->controlSocket->ungetChar(inBuf.at(i)); // got a successful reply socks5State = BindSuccess; if (socketState == QAbstractSocket::ListeningState) emitReadNotification();}void QSocks5SocketEnginePrivate::_q_emitPendingReadNotification(){ Q_Q(QSocks5SocketEngine); readNotificationPending = false; if (readNotificationEnabled) { QSOCKS5_D_DEBUG << "emitting readNotification"; QPointer<QSocks5SocketEngine> qq = q; emit q->readNotification(); if (!qq) return; // check if there needs to be a new zero read notifcation if (socks5State == ControlSocketError && data->controlSocket->error() == QAbstractSocket::RemoteHostClosedError) { connectData->readBuffer.clear(); emitReadNotification(); } }}void QSocks5SocketEnginePrivate::emitReadNotification(){ Q_Q(QSocks5SocketEngine); readNotificationActivated = true; if (readNotificationEnabled && !readNotificationPending) { QSOCKS5_D_DEBUG << "queueing readNotification"; readNotificationPending = true; QMetaObject::invokeMethod(q, "_q_emitPendingReadNotification", Qt::QueuedConnection); }}void QSocks5SocketEnginePrivate::_q_emitPendingWriteNotification(){ writeNotificationPending = false; Q_Q(QSocks5SocketEngine); if (writeNotificationEnabled) { QSOCKS5_D_DEBUG << "emitting writeNotification"; emit q->writeNotification(); }}void QSocks5SocketEnginePrivate::emitWriteNotification(){ Q_Q(QSocks5SocketEngine); writeNotificationActivated = true; if (writeNotificationEnabled && !writeNotificationPending) { QSOCKS5_D_DEBUG << "queueing writeNotification"; writeNotificationPending = true; QMetaObject::invokeMethod(q, "_q_emitPendingWriteNotification", Qt::QueuedConnection); }}QSocks5SocketEngine::QSocks5SocketEngine(QObject *parent):QAbstractSocketEngine(*new QSocks5SocketEnginePrivate(), parent){}QSocks5SocketEngine::~QSocks5SocketEngine(){ Q_D(QSocks5SocketEngine); if (d->data) { delete d->data->authenticator; delete d->data->controlSocket; } if (d->connectData) delete d->connectData;#ifndef QT_NO_UDPSOCKET if (d->udpData) { delete d->udpData->udpSocket; delete d->udpData; }#endif if (d->bindData) delete d->bindData;}static QBasicAtomic descriptorCounter = Q_ATOMIC_INIT(1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -