diff options
| author | Jeremy Lainé <jeremy.laine@m4x.org> | 2010-03-04 18:50:18 +0000 |
|---|---|---|
| committer | Jeremy Lainé <jeremy.laine@m4x.org> | 2010-03-04 18:50:18 +0000 |
| commit | ab47ccf582b4be8f57eb3f09d28f6085a3f96244 (patch) | |
| tree | e19221e785fa75e441dbedec6069c261f6a15a9f /source | |
| parent | 7c55f728ba4606ec7c821132b1be04f9d171ac19 (diff) | |
| download | qxmpp-ab47ccf582b4be8f57eb3f09d28f6085a3f96244.tar.gz | |
rework SOCKS5 API
Diffstat (limited to 'source')
| -rw-r--r-- | source/QXmppSocks.cpp | 99 | ||||
| -rw-r--r-- | source/QXmppSocks.h | 17 | ||||
| -rw-r--r-- | source/QXmppTransferManager.cpp | 90 | ||||
| -rw-r--r-- | source/QXmppTransferManager.h | 11 |
4 files changed, 90 insertions, 127 deletions
diff --git a/source/QXmppSocks.cpp b/source/QXmppSocks.cpp index c11c6584..c2e3ecec 100644 --- a/source/QXmppSocks.cpp +++ b/source/QXmppSocks.cpp @@ -215,7 +215,6 @@ void QXmppSocksClient::slotReadyRead() // FIXME : what do we do with the resulting name / port? // from now on, forward signals - connect(m_socket, SIGNAL(bytesWritten(qint64)), this, SIGNAL(bytesWritten(qint64))); disconnect(m_socket, SIGNAL(readyRead()), this, SLOT(slotReadyRead())); connect(m_socket, SIGNAL(readyRead()), this, SIGNAL(readyRead())); @@ -244,11 +243,13 @@ qint64 QXmppSocksClient::write(const QByteArray &data) return m_socket->write(data); } +QTcpSocket *QXmppSocksClient::socket() +{ + return m_socket; +} + QXmppSocksServer::QXmppSocksServer(QObject *parent) - : QObject(parent), - m_hostPort(0), - m_socket(0), - m_step(ConnectState) + : QObject(parent) { m_server = new QTcpServer(this); connect(m_server, SIGNAL(newConnection()), this, SLOT(slotNewConnection())); @@ -257,8 +258,6 @@ QXmppSocksServer::QXmppSocksServer(QObject *parent) void QXmppSocksServer::close() { m_server->close(); - if (m_socket) - m_socket->close(); } bool QXmppSocksServer::listen(const QHostAddress &address, quint16 port) @@ -266,11 +265,6 @@ bool QXmppSocksServer::listen(const QHostAddress &address, quint16 port) return m_server->listen(address, port); } -QByteArray QXmppSocksServer::readAll() -{ - return m_socket->readAll(); -} - QHostAddress QXmppSocksServer::serverAddress() const { return m_server->serverAddress(); @@ -283,30 +277,33 @@ quint16 QXmppSocksServer::serverPort() const void QXmppSocksServer::slotNewConnection() { - m_socket = m_server->nextPendingConnection(); - if (!m_socket) + QTcpSocket *socket = m_server->nextPendingConnection(); + if (!socket) return; - // don't accept any further connections - m_server->close(); - connect(m_socket, SIGNAL(disconnected()), this, SIGNAL(disconnected())); - connect(m_socket, SIGNAL(readyRead()), this, SLOT(slotReadyRead())); + // register socket + m_states.insert(socket, ConnectState); + connect(socket, SIGNAL(readyRead()), this, SLOT(slotReadyRead())); } void QXmppSocksServer::slotReadyRead() { - if (m_step == ConnectState) + QTcpSocket *socket = qobject_cast<QTcpSocket*>(sender()); + if (!socket || !m_states.contains(socket)) + return; + + if (m_states.value(socket) == ConnectState) { - m_step++; + m_states.insert(socket, CommandState); // receive connect to server request - QByteArray buffer = m_socket->readAll(); + QByteArray buffer = socket->readAll(); if (buffer.size() < 3 || buffer.at(0) != SocksVersion || buffer.at(1) + 2 != buffer.size()) { qWarning("QXmppSocksServer received invalid handshake"); - m_socket->close(); + socket->close(); return; } @@ -323,7 +320,7 @@ void QXmppSocksServer::slotReadyRead() if (!foundMethod) { qWarning("QXmppSocksServer received bad authentication method"); - m_socket->close(); + socket->close(); return; } @@ -331,20 +328,23 @@ void QXmppSocksServer::slotReadyRead() buffer.resize(2); buffer[0] = SocksVersion; buffer[1] = NoAuthentication; - m_socket->write(buffer); + socket->write(buffer); - } else if (m_step == CommandState) { - m_step++; + } else if (m_states.value(socket) == CommandState) { + m_states.insert(socket, ReadyState); + + // disconnect from signals + disconnect(socket, SIGNAL(readyRead()), this, SLOT(slotReadyRead())); // receive command - QByteArray buffer = m_socket->readAll(); + QByteArray buffer = socket->readAll(); if (buffer.size() < 4 || buffer.at(0) != SocksVersion || buffer.at(1) != ConnectCommand || buffer.at(2) != 0x00) { qWarning("QXmppSocksServer received an invalid command"); - m_socket->close(); + socket->close(); return; } @@ -355,16 +355,13 @@ void QXmppSocksServer::slotReadyRead() if (!parseHostAndPort(buffer.mid(3), hostType, hostName, hostPort)) { qWarning("QXmppSocksServer could not parse type/host/port"); - m_socket->close(); - return; - } - if (hostName != m_hostName || hostPort != m_hostPort) - { - qWarning("QXmppSocksServer got wrong host or port"); - m_socket->close(); + socket->close(); return; } + // notify of connection + emit newConnection(socket, hostName, hostPort); + // send response buffer.resize(3); buffer[0] = SocksVersion; @@ -372,35 +369,9 @@ void QXmppSocksServer::slotReadyRead() buffer[2] = 0x00; buffer.append(encodeHostAndPort( DomainName, - m_hostName.toAscii(), - m_hostPort)); - m_socket->write(buffer); - - // from now on, forward signals - connect(m_socket, SIGNAL(bytesWritten(qint64)), this, SIGNAL(bytesWritten(qint64))); - disconnect(m_socket, SIGNAL(readyRead()), this, SLOT(slotReadyRead())); - connect(m_socket, SIGNAL(readyRead()), this, SIGNAL(readyRead())); - - // notify of connection - emit connected(); + hostName, + hostPort)); + socket->write(buffer); } } -void QXmppSocksServer::setHostName(const QString &hostName) -{ - m_hostName = hostName; -} - -void QXmppSocksServer::setHostPort(quint16 hostPort) -{ - m_hostPort = hostPort; -} - -qint64 QXmppSocksServer::write(const QByteArray &data) -{ - if (m_socket) - return m_socket->write(data); - else - return -1; -} - diff --git a/source/QXmppSocks.h b/source/QXmppSocks.h index a28e73c0..e99c7618 100644 --- a/source/QXmppSocks.h +++ b/source/QXmppSocks.h @@ -43,8 +43,9 @@ public: bool waitForConnected(int msecs = 30000); qint64 write(const QByteArray &data); + QTcpSocket *socket(); + signals: - void bytesWritten(qint64); void connected(); void disconnected(); void readyRead(); @@ -70,30 +71,20 @@ public: QXmppSocksServer(QObject *parent=0); void close(); bool listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0); - QByteArray readAll(); - qint64 write(const QByteArray &data); QHostAddress serverAddress() const; quint16 serverPort() const; - void setHostName(const QString &hostName); - void setHostPort(quint16 hostPort); signals: - void bytesWritten(qint64); - void connected(); - void disconnected(); - void readyRead(); + void newConnection(QTcpSocket *socket, QString hostName, quint16 port); private slots: void slotNewConnection(); void slotReadyRead(); private: - QString m_hostName; - quint16 m_hostPort; QTcpServer *m_server; - QTcpSocket *m_socket; - int m_step; + QMap<QTcpSocket*, int> m_states; }; #endif diff --git a/source/QXmppTransferManager.cpp b/source/QXmppTransferManager.cpp index d920ebd2..c9f53b1c 100644 --- a/source/QXmppTransferManager.cpp +++ b/source/QXmppTransferManager.cpp @@ -58,7 +58,8 @@ QXmppTransferJob::QXmppTransferJob(const QString &jid, QXmppTransferJob::Directi m_fileSize(0), m_ibbSequence(0), m_socksClient(0), - m_socksServer(0) + m_socksServer(0), + m_socksSocket(0) { } @@ -174,6 +175,8 @@ void QXmppTransferJob::terminate(QXmppTransferJob::Error cause) m_socksClient->close(); if (m_socksServer) m_socksServer->close(); + if (m_socksSocket) + m_socksSocket->close(); // emit signals later QTimer::singleShot(0, this, SLOT(slotTerminated())); @@ -256,7 +259,7 @@ void QXmppTransferManager::byteStreamResultReceived(const QXmppByteStreamIq &iq) // connect to proxy const QString hostName = streamHash(job->m_sid, - m_client->getConfiguration().jid(), + m_client->getConfiguration().getJid(), job->m_jid); job->m_socksClient = new QXmppSocksClient(streamHost.host(), streamHost.port(), job); @@ -271,7 +274,7 @@ void QXmppTransferManager::byteStreamResultReceived(const QXmppByteStreamIq &iq) // activate stream QXmppByteStreamIq streamIq; streamIq.setType(QXmppIq::Set); - streamIq.setFrom(m_client->getConfiguration().jid()); + streamIq.setFrom(m_client->getConfiguration().getJid()); streamIq.setTo(streamHost.jid()); streamIq.setSid(job->m_sid); streamIq.setActivate(job->m_jid); @@ -281,9 +284,15 @@ void QXmppTransferManager::byteStreamResultReceived(const QXmppByteStreamIq &iq) } // direction connection, start sending data + if (!job->m_socksSocket) + { + qWarning("Client says they connected to our SOCKS server, but they did not"); + job->terminate(QXmppTransferJob::ProtocolError); + return; + } job->setState(QXmppTransferJob::TransferState); - connect(job->m_socksServer, SIGNAL(bytesWritten(qint64)), this, SLOT(socksServerDataSent())); - connect(job->m_socksServer, SIGNAL(disconnected()), this, SLOT(socksServerDisconnected())); + connect(job->m_socksSocket, SIGNAL(bytesWritten(qint64)), this, SLOT(socksSocketDataSent())); + connect(job->m_socksSocket, SIGNAL(disconnected()), this, SLOT(socksSocketDisconnected())); socksServerSendData(job); } @@ -319,7 +328,7 @@ void QXmppTransferManager::byteStreamSetReceived(const QXmppByteStreamIq &iq) const QString hostName = streamHash(job->m_sid, job->m_jid, - m_client->getConfiguration().jid()); + m_client->getConfiguration().getJid()); // try to connect to stream host job->m_socksClient = new QXmppSocksClient(streamHost.host(), streamHost.port(), job); @@ -379,10 +388,10 @@ QXmppTransferJob* QXmppTransferManager::getJobBySocksClient(QXmppSocksClient *so return 0; } -QXmppTransferJob* QXmppTransferManager::getJobBySocksServer(QXmppSocksServer *socksServer) +QXmppTransferJob* QXmppTransferManager::getJobBySocksSocket(QTcpSocket *socksSocket) { foreach (QXmppTransferJob *job, m_jobs) - if (job->m_socksServer == socksServer) + if (job->m_socksSocket == socksSocket) return job; return 0; } @@ -557,8 +566,9 @@ void QXmppTransferManager::iqReceived(const QXmppIq &iq) { // proxy stream activated, start sending data job->setState(QXmppTransferJob::TransferState); - connect(job->m_socksClient, SIGNAL(bytesWritten(qint64)), this, SLOT(socksProxyDataSent())); - connect(job->m_socksClient, SIGNAL(disconnected()), this, SLOT(socksProxyDisconnected())); + job->m_socksSocket = job->m_socksClient->socket(); + connect(job->m_socksSocket, SIGNAL(bytesWritten(qint64)), this, SLOT(socksSocketDataSent())); + connect(job->m_socksSocket, SIGNAL(disconnected()), this, SLOT(socksSocketDisconnected())); socksServerSendData(job); } else if (iq.type() == QXmppIq::Error) { // proxy stream not activated, terminate @@ -718,32 +728,30 @@ void QXmppTransferManager::socksClientDisconnected() job->checkData(); } -void QXmppTransferManager::socksProxyDataSent() -{ - QXmppSocksClient *socksClient = qobject_cast<QXmppSocksClient*>(sender()); - QXmppTransferJob *job = getJobBySocksClient(socksClient); - if (!job || job->state() != QXmppTransferJob::TransferState) - return; - - // send next data block - socksServerSendData(job); -} - -void QXmppTransferManager::socksProxyDisconnected() +void QXmppTransferManager::socksServerConnected(QTcpSocket *socket, const QString &hostName, quint16 port) { - QXmppSocksClient *socksClient = qobject_cast<QXmppSocksClient*>(sender()); - QXmppTransferJob *job = getJobBySocksClient(socksClient); - if (!job || job->state() == QXmppTransferJob::FinishedState) - return; - - // terminate transfer - job->terminate(QXmppTransferJob::ProtocolError); + QXmppSocksServer *socksServer = qobject_cast<QXmppSocksServer*>(sender()); + foreach (QXmppTransferJob *job, m_jobs) + { + if (job->m_socksServer == socksServer) + { + const QString ownJid = m_client->getConfiguration().getJid(); + if (hostName == streamHash(job->m_sid, ownJid, job->jid()) || port == 0) + { + job->m_socksSocket = socket; + return; + } + // don't accept any further connections + job->m_socksServer->close(); + } + } + socket->close(); } -void QXmppTransferManager::socksServerDataSent() +void QXmppTransferManager::socksSocketDataSent() { - QXmppSocksServer *socksServer = qobject_cast<QXmppSocksServer*>(sender()); - QXmppTransferJob *job = getJobBySocksServer(socksServer); + QTcpSocket *socksSocket = qobject_cast<QTcpSocket*>(sender()); + QXmppTransferJob *job = getJobBySocksSocket(socksSocket); if (!job || job->state() != QXmppTransferJob::TransferState) return; @@ -751,10 +759,10 @@ void QXmppTransferManager::socksServerDataSent() socksServerSendData(job); } -void QXmppTransferManager::socksServerDisconnected() +void QXmppTransferManager::socksSocketDisconnected() { - QXmppSocksServer *socksServer = qobject_cast<QXmppSocksServer*>(sender()); - QXmppTransferJob *job = getJobBySocksServer(socksServer); + QTcpSocket *socksSocket = qobject_cast<QTcpSocket*>(sender()); + QXmppTransferJob *job = getJobBySocksSocket(socksSocket); if (!job || job->state() == QXmppTransferJob::FinishedState) return; @@ -767,11 +775,7 @@ void QXmppTransferManager::socksServerSendData(QXmppTransferJob *job) const QByteArray buffer = job->m_iodevice->read(job->m_blockSize); if (buffer.size()) { - if (job->m_socksClient) - job->m_socksClient->write(buffer); - else - job->m_socksServer->write(buffer); - + job->m_socksSocket->write(buffer); job->m_done += buffer.size(); job->progress(job->m_done, job->fileSize()); } else { @@ -782,7 +786,7 @@ void QXmppTransferManager::socksServerSendData(QXmppTransferJob *job) void QXmppTransferManager::socksServerSendOffer(QXmppTransferJob *job) { - const QString ownJid = m_client->getConfiguration().jid(); + const QString ownJid = m_client->getConfiguration().getJid(); // discover local IPs QList<QXmppByteStreamIq::StreamHost> streamHosts; @@ -875,12 +879,8 @@ void QXmppTransferManager::streamInitiationResultReceived(const QXmppStreamIniti job->m_requestId = openIq.id(); m_client->sendPacket(openIq); } else if (job->method() == QXmppTransferJob::SocksMethod) { - const QString ownJid = m_client->getConfiguration().jid(); - // start listening job->m_socksServer = new QXmppSocksServer(this); - job->m_socksServer->setHostName(streamHash(job->m_sid, ownJid, job->jid())); - job->m_socksServer->setHostPort(0); if (!job->m_socksServer->listen()) { qWarning() << "QXmppSocksServer could not start listening"; diff --git a/source/QXmppTransferManager.h b/source/QXmppTransferManager.h index 442c0c3b..45d87172 100644 --- a/source/QXmppTransferManager.h +++ b/source/QXmppTransferManager.h @@ -31,6 +31,7 @@ #include "QXmppIq.h" #include "QXmppByteStreamIq.h" +class QTcpSocket; class QXmppByteStreamIq; class QXmppClient; class QXmppIbbCloseIq; @@ -136,6 +137,7 @@ private: // for socks5 bytestreams QXmppSocksClient *m_socksClient; QXmppSocksServer *m_socksServer; + QTcpSocket *m_socksSocket; QXmppByteStreamIq::StreamHost m_socksProxy; friend class QXmppTransferManager; @@ -164,17 +166,16 @@ private slots: void iqReceived(const QXmppIq&); void socksClientDataReceived(); void socksClientDisconnected(); - void socksProxyDataSent(); - void socksProxyDisconnected(); - void socksServerDataSent(); - void socksServerDisconnected(); + void socksServerConnected(QTcpSocket *socket, const QString &hostName, quint16 port); + void socksSocketDataSent(); + void socksSocketDisconnected(); void streamInitiationIqReceived(const QXmppStreamInitiationIq&); private: QXmppTransferJob *getJobByRequestId(const QString &jid, const QString &id); QXmppTransferJob *getJobBySid(const QString &jid, const QString &sid); QXmppTransferJob *getJobBySocksClient(QXmppSocksClient *socksClient); - QXmppTransferJob *getJobBySocksServer(QXmppSocksServer *socksServer); + QXmppTransferJob *getJobBySocksSocket(QTcpSocket *socksSocket); void byteStreamResponseReceived(const QXmppIq&); void byteStreamResultReceived(const QXmppByteStreamIq&); void byteStreamSetReceived(const QXmppByteStreamIq&); |
