aboutsummaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorJeremy Lainé <jeremy.laine@m4x.org>2010-03-04 18:50:18 +0000
committerJeremy Lainé <jeremy.laine@m4x.org>2010-03-04 18:50:18 +0000
commitab47ccf582b4be8f57eb3f09d28f6085a3f96244 (patch)
treee19221e785fa75e441dbedec6069c261f6a15a9f /source
parent7c55f728ba4606ec7c821132b1be04f9d171ac19 (diff)
downloadqxmpp-ab47ccf582b4be8f57eb3f09d28f6085a3f96244.tar.gz
rework SOCKS5 API
Diffstat (limited to 'source')
-rw-r--r--source/QXmppSocks.cpp99
-rw-r--r--source/QXmppSocks.h17
-rw-r--r--source/QXmppTransferManager.cpp90
-rw-r--r--source/QXmppTransferManager.h11
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&);