aboutsummaryrefslogtreecommitdiff
path: root/src/client
diff options
context:
space:
mode:
authorJeremy Lainé <jeremy.laine@m4x.org>2012-04-12 07:51:21 +0000
committerJeremy Lainé <jeremy.laine@m4x.org>2012-04-12 07:51:21 +0000
commitc6623e6a7e86fab1c973900ede0de1eb2e488230 (patch)
treed1f98598bf425df2173a0d5ef83e3024a7e4c59e /src/client
parentb93f06fbc497305180792f8b4a9029fa097d8a49 (diff)
downloadqxmpp-c6623e6a7e86fab1c973900ede0de1eb2e488230.tar.gz
remove last blocking code in QXmppTransferManager
Diffstat (limited to 'src/client')
-rw-r--r--src/client/QXmppTransferManager.cpp469
-rw-r--r--src/client/QXmppTransferManager.h16
-rw-r--r--src/client/QXmppTransferManager_p.h77
-rw-r--r--src/client/client.pri1
4 files changed, 377 insertions, 186 deletions
diff --git a/src/client/QXmppTransferManager.cpp b/src/client/QXmppTransferManager.cpp
index b9d71408..f7949024 100644
--- a/src/client/QXmppTransferManager.cpp
+++ b/src/client/QXmppTransferManager.cpp
@@ -39,6 +39,7 @@
#include "QXmppSocks.h"
#include "QXmppStreamInitiationIq.h"
#include "QXmppTransferManager.h"
+#include "QXmppTransferManager_p.h"
#include "QXmppUtils.h"
// time to try to connect to a SOCKS host (7 seconds)
@@ -110,6 +111,7 @@ public:
QXmppTransferJobPrivate();
int blockSize;
+ QXmppClient *client;
QXmppTransferJob::Direction direction;
qint64 done;
QXmppTransferJob::Error error;
@@ -138,6 +140,7 @@ public:
QXmppTransferJobPrivate::QXmppTransferJobPrivate()
: blockSize(16384),
+ client(0),
done(0),
error(QXmppTransferJob::NoError),
hash(QCryptographicHash::Md5),
@@ -149,10 +152,11 @@ QXmppTransferJobPrivate::QXmppTransferJobPrivate()
{
}
-QXmppTransferJob::QXmppTransferJob(const QString &jid, QXmppTransferJob::Direction direction, QObject *parent)
+QXmppTransferJob::QXmppTransferJob(const QString &jid, QXmppTransferJob::Direction direction, QXmppClient *client, QObject *parent)
: QXmppLoggable(parent),
d(new QXmppTransferJobPrivate)
{
+ d->client = client;
d->direction = direction;
d->jid = jid;
}
@@ -350,7 +354,160 @@ void QXmppTransferJob::_q_disconnected()
}
}
-void QXmppTransferJob::_q_receiveData()
+void QXmppTransferJob::_q_terminated()
+{
+ emit stateChanged(d->state);
+ if (d->error != NoError)
+ emit error(d->error);
+ emit finished();
+}
+
+void QXmppTransferJob::terminate(QXmppTransferJob::Error cause)
+{
+ if (d->state == FinishedState)
+ return;
+
+ // change state
+ d->error = cause;
+ d->state = FinishedState;
+
+ // close IO device
+ if (d->iodevice)
+ d->iodevice->close();
+
+ // close socket
+ if (d->socksSocket)
+ {
+ d->socksSocket->flush();
+ d->socksSocket->close();
+ }
+
+ // emit signals later
+ QTimer::singleShot(0, this, SLOT(_q_terminated()));
+}
+
+bool QXmppTransferJob::writeData(const QByteArray &data)
+{
+ const qint64 written = d->iodevice->write(data);
+ if (written < 0)
+ return false;
+ d->done += written;
+ if (!d->fileInfo.hash().isEmpty())
+ d->hash.addData(data);
+ progress(d->done, d->fileInfo.size());
+ return true;
+}
+
+QXmppTransferIncomingJob::QXmppTransferIncomingJob(const QString& jid, QXmppClient* client, QObject* parent)
+ : QXmppTransferJob(jid, IncomingDirection, client, parent)
+ , m_candidateClient(0)
+{
+}
+
+void QXmppTransferIncomingJob::connectToNextHost()
+{
+ bool check;
+ Q_UNUSED(check);
+
+ if (m_streamCandidates.isEmpty()) {
+ // could not connect to any stream host
+ QXmppByteStreamIq response;
+ response.setId(m_streamOfferId);
+ response.setTo(m_streamOfferFrom);
+ QXmppStanza::Error error(QXmppStanza::Error::Cancel, QXmppStanza::Error::ItemNotFound);
+ error.setCode(404);
+ response.setType(QXmppIq::Error);
+ response.setError(error);
+ d->client->sendPacket(response);
+
+ terminate(QXmppTransferJob::ProtocolError);
+ return;
+ }
+
+ // try next host
+ m_candidateHost = m_streamCandidates.takeFirst();
+ info(QString("Connecting to streamhost: %1 (%2:%3)").arg(
+ m_candidateHost.jid(),
+ m_candidateHost.host().toString(),
+ QString::number(m_candidateHost.port())));
+
+ const QString hostName = streamHash(d->sid,
+ d->jid,
+ d->client->configuration().jid());
+
+ // try to connect to stream host
+ m_candidateClient = new QXmppSocksClient(m_candidateHost.host(), m_candidateHost.port(), this);
+
+ check = connect(m_candidateClient, SIGNAL(disconnected()),
+ this, SLOT(_q_candidateDisconnected()));
+ Q_ASSERT(check);
+
+ check = connect(m_candidateClient, SIGNAL(ready()),
+ this, SLOT(_q_candidateReady()));
+ Q_ASSERT(check);
+
+ m_candidateClient->connectToHost(hostName, 0);
+}
+
+void QXmppTransferIncomingJob::connectToHosts(const QXmppByteStreamIq &iq)
+{
+ bool check;
+ Q_UNUSED(check);
+
+ m_streamCandidates = iq.streamHosts();
+ m_streamOfferId = iq.id();
+ m_streamOfferFrom = iq.from();
+
+ connectToNextHost();
+}
+
+void QXmppTransferIncomingJob::_q_candidateReady()
+{
+ bool check;
+ Q_UNUSED(check);
+
+ if (!m_candidateClient)
+ return;
+
+ setState(QXmppTransferJob::TransferState);
+ d->socksSocket = m_candidateClient;
+ m_candidateClient = 0;
+
+ check = connect(d->socksSocket, SIGNAL(readyRead()),
+ this, SLOT(_q_receiveData()));
+ Q_ASSERT(check);
+
+ check = connect(d->socksSocket, SIGNAL(disconnected()),
+ this, SLOT(_q_disconnected()));
+ Q_ASSERT(check);
+
+ QXmppByteStreamIq ackIq;
+ ackIq.setId(m_streamOfferId);
+ ackIq.setTo(m_streamOfferFrom);
+ ackIq.setType(QXmppIq::Result);
+ ackIq.setSid(d->sid);
+ ackIq.setStreamHostUsed(m_candidateHost.jid());
+ d->client->sendPacket(ackIq);
+}
+
+void QXmppTransferIncomingJob::_q_candidateDisconnected()
+{
+ if (!m_candidateClient)
+ return;
+
+ warning(QString("Failed to connect to streamhost: %1 (%2:%3)").arg(
+ m_candidateHost.jid(),
+ m_candidateHost.host().toString(),
+ QString::number(m_candidateHost.port())));
+
+ m_candidateClient->deleteLater();
+ m_candidateClient = 0;
+
+ // try next host
+ connectToNextHost();
+}
+
+void QXmppTransferIncomingJob::_q_receiveData()
{
if (d->state != QXmppTransferJob::TransferState)
return;
@@ -366,7 +523,71 @@ void QXmppTransferJob::_q_receiveData()
}
}
-void QXmppTransferJob::_q_sendData()
+QXmppTransferOutgoingJob::QXmppTransferOutgoingJob(const QString& jid, QXmppClient* client, QObject* parent)
+ : QXmppTransferJob(jid, OutgoingDirection, client, parent)
+{
+}
+
+void QXmppTransferOutgoingJob::connectToProxy()
+{
+ bool check;
+ Q_UNUSED(check);
+
+ info(QString("Connecting to proxy: %1 (%2:%3)").arg(
+ d->socksProxy.jid(),
+ d->socksProxy.host().toString(),
+ QString::number(d->socksProxy.port())));
+
+ const QString hostName = streamHash(d->sid,
+ d->client->configuration().jid(),
+ d->jid);
+
+ QXmppSocksClient *socksClient = new QXmppSocksClient(d->socksProxy.host(), d->socksProxy.port(), this);
+
+ check = connect(socksClient, SIGNAL(disconnected()),
+ this, SLOT(_q_disconnected()));
+ Q_ASSERT(check);
+
+ check = connect(socksClient, SIGNAL(ready()),
+ this, SLOT(_q_proxyReady()));
+ Q_ASSERT(check);
+
+ d->socksSocket = socksClient;
+ socksClient->connectToHost(hostName, 0);
+}
+
+void QXmppTransferOutgoingJob::startSending()
+{
+ bool check;
+ Q_ASSERT(check);
+
+ setState(QXmppTransferJob::TransferState);
+
+ check = connect(d->socksSocket, SIGNAL(bytesWritten(qint64)),
+ this, SLOT(_q_sendData()));
+ Q_ASSERT(check);
+
+ check = connect(d->iodevice, SIGNAL(readyRead()),
+ this, SLOT(_q_sendData()));
+ Q_ASSERT(check);
+
+ _q_sendData();
+}
+
+void QXmppTransferOutgoingJob::_q_proxyReady()
+{
+ // activate stream
+ QXmppByteStreamIq streamIq;
+ streamIq.setType(QXmppIq::Set);
+ streamIq.setFrom(d->client->configuration().jid());
+ streamIq.setTo(d->socksProxy.jid());
+ streamIq.setSid(d->sid);
+ streamIq.setActivate(d->jid);
+ d->requestId = streamIq.id();
+ d->client->sendPacket(streamIq);
+}
+
+void QXmppTransferOutgoingJob::_q_sendData()
{
if (d->state != QXmppTransferJob::TransferState)
return;
@@ -400,48 +621,53 @@ void QXmppTransferJob::_q_sendData()
}
}
-void QXmppTransferJob::_q_terminated()
+class QXmppTransferManagerPrivate
{
- emit stateChanged(d->state);
- if (d->error != NoError)
- emit error(d->error);
- emit finished();
-}
+public:
+ QXmppTransferManagerPrivate(QXmppTransferManager *qq);
-void QXmppTransferJob::terminate(QXmppTransferJob::Error cause)
-{
- if (d->state == FinishedState)
- return;
+ QXmppTransferIncomingJob *getIncomingJobByRequestId(const QString &jid, const QString &id);
+ QXmppTransferIncomingJob *getIncomingJobBySid(const QString &jid, const QString &sid);
+ QXmppTransferOutgoingJob *getOutgoingJobByRequestId(const QString &jid, const QString &id);
- // change state
- d->error = cause;
- d->state = FinishedState;
+private:
+ QXmppTransferJob *getJobByRequestId(QXmppTransferJob::Direction direction, const QString &jid, const QString &id);
+ QXmppTransferManager *q;
+};
- // close IO device
- if (d->iodevice)
- d->iodevice->close();
+QXmppTransferManagerPrivate::QXmppTransferManagerPrivate(QXmppTransferManager *qq)
+ : q(qq)
+{
+}
- // close socket
- if (d->socksSocket)
- {
- d->socksSocket->flush();
- d->socksSocket->close();
- }
+QXmppTransferJob* QXmppTransferManagerPrivate::getJobByRequestId(QXmppTransferJob::Direction direction, const QString &jid, const QString &id)
+{
+ foreach (QXmppTransferJob *job, q->m_jobs)
+ if (job->d->direction == direction &&
+ job->d->jid == jid &&
+ job->d->requestId == id)
+ return job;
+ return 0;
+}
- // emit signals later
- QTimer::singleShot(0, this, SLOT(_q_terminated()));
+QXmppTransferIncomingJob *QXmppTransferManagerPrivate::getIncomingJobByRequestId(const QString &jid, const QString &id)
+{
+ return static_cast<QXmppTransferIncomingJob*>(getJobByRequestId(QXmppTransferJob::IncomingDirection, jid, id));
}
-bool QXmppTransferJob::writeData(const QByteArray &data)
+QXmppTransferIncomingJob* QXmppTransferManagerPrivate::getIncomingJobBySid(const QString &jid, const QString &sid)
{
- const qint64 written = d->iodevice->write(data);
- if (written < 0)
- return false;
- d->done += written;
- if (!d->fileInfo.hash().isEmpty())
- d->hash.addData(data);
- progress(d->done, d->fileInfo.size());
- return true;
+ foreach (QXmppTransferJob *job, q->m_jobs)
+ if (job->d->direction == QXmppTransferJob::IncomingDirection &&
+ job->d->jid == jid &&
+ job->d->sid == sid)
+ return static_cast<QXmppTransferIncomingJob*>(job);
+ return 0;
+}
+
+QXmppTransferOutgoingJob *QXmppTransferManagerPrivate::getOutgoingJobByRequestId(const QString &jid, const QString &id)
+{
+ return static_cast<QXmppTransferOutgoingJob*>(getJobByRequestId(QXmppTransferJob::OutgoingDirection, jid, id));
}
/// Constructs a QXmppTransferManager to handle incoming and outgoing
@@ -456,6 +682,8 @@ QXmppTransferManager::QXmppTransferManager()
bool check;
Q_UNUSED(check);
+ d = new QXmppTransferManagerPrivate(this);
+
// start SOCKS server
m_socksServer = new QXmppSocksServer(this);
if (m_socksServer->listen()) {
@@ -467,6 +695,11 @@ QXmppTransferManager::QXmppTransferManager()
}
}
+QXmppTransferManager::~QXmppTransferManager()
+{
+ delete d;
+}
+
void QXmppTransferManager::setClient(QXmppClient *client)
{
bool check;
@@ -506,7 +739,7 @@ void QXmppTransferManager::byteStreamIqReceived(const QXmppByteStreamIq &iq)
/// that we connected to a stream host.
void QXmppTransferManager::byteStreamResponseReceived(const QXmppIq &iq)
{
- QXmppTransferJob *job = getJobByRequestId(QXmppTransferJob::IncomingDirection, iq.from(), iq.id());
+ QXmppTransferJob *job = d->getIncomingJobByRequestId(iq.from(), iq.id());
if (!job ||
job->method() != QXmppTransferJob::SocksMethod ||
job->state() != QXmppTransferJob::StartState)
@@ -523,7 +756,7 @@ void QXmppTransferManager::byteStreamResultReceived(const QXmppByteStreamIq &iq)
bool check;
Q_UNUSED(check);
- QXmppTransferJob *job = getJobByRequestId(QXmppTransferJob::OutgoingDirection, iq.from(), iq.id());
+ QXmppTransferOutgoingJob *job = d->getOutgoingJobByRequestId(iq.from(), iq.id());
if (!job ||
job->method() != QXmppTransferJob::SocksMethod ||
job->state() != QXmppTransferJob::StartState)
@@ -532,44 +765,7 @@ void QXmppTransferManager::byteStreamResultReceived(const QXmppByteStreamIq &iq)
// check the stream host
if (iq.streamHostUsed() == job->d->socksProxy.jid())
{
- const QXmppByteStreamIq::StreamHost streamHost = job->d->socksProxy;
- info(QString("Connecting to proxy: %1 (%2:%3)").arg(
- streamHost.jid(),
- streamHost.host().toString(),
- QString::number(streamHost.port())));
-
- // connect to proxy
- const QString hostName = streamHash(job->d->sid,
- client()->configuration().jid(),
- job->d->jid);
-
- QXmppSocksClient *socksClient = new QXmppSocksClient(streamHost.host(), streamHost.port(), job);
- socksClient->connectToHost(hostName, 0);
- // FIXME : this should probably be made asynchronous as it blocks XMPP packet handling
- if (!socksClient->waitForReady(socksTimeout))
- {
- warning(QString("Failed to connect to proxy: %1 (%2:%3)").arg(
- streamHost.jid(),
- streamHost.host().toString(),
- QString::number(streamHost.port())));
- delete socksClient;
- job->terminate(QXmppTransferJob::ProtocolError);
- return;
- }
- job->d->socksSocket = socksClient;
- check = connect(job->d->socksSocket, SIGNAL(disconnected()),
- job, SLOT(_q_disconnected()));
- Q_ASSERT(check);
-
- // activate stream
- QXmppByteStreamIq streamIq;
- streamIq.setType(QXmppIq::Set);
- streamIq.setFrom(client()->configuration().jid());
- streamIq.setTo(streamHost.jid());
- streamIq.setSid(job->d->sid);
- streamIq.setActivate(job->d->jid);
- job->d->requestId = streamIq.id();
- client()->sendPacket(streamIq);
+ job->connectToProxy();
return;
}
@@ -580,20 +776,11 @@ void QXmppTransferManager::byteStreamResultReceived(const QXmppByteStreamIq &iq)
job->terminate(QXmppTransferJob::ProtocolError);
return;
}
- job->setState(QXmppTransferJob::TransferState);
check = connect(job->d->socksSocket, SIGNAL(disconnected()),
job, SLOT(_q_disconnected()));
Q_ASSERT(check);
- check = connect(job->d->socksSocket, SIGNAL(bytesWritten(qint64)),
- job, SLOT(_q_sendData()));
- Q_ASSERT(check);
-
- check = connect(job->d->iodevice, SIGNAL(readyRead()),
- job, SLOT(_q_sendData()));
- Q_ASSERT(check);
-
- job->_q_sendData();
+ job->startSending();
}
/// Handle a bytestream set, i.e. an invitation from the remote party to connect
@@ -607,7 +794,7 @@ void QXmppTransferManager::byteStreamSetReceived(const QXmppByteStreamIq &iq)
response.setId(iq.id());
response.setTo(iq.from());
- QXmppTransferJob *job = getJobBySid(QXmppTransferJob::IncomingDirection, iq.from(), iq.sid());
+ QXmppTransferIncomingJob *job = d->getIncomingJobBySid(iq.from(), iq.sid());
if (!job ||
job->method() != QXmppTransferJob::SocksMethod ||
job->state() != QXmppTransferJob::StartState)
@@ -621,59 +808,7 @@ void QXmppTransferManager::byteStreamSetReceived(const QXmppByteStreamIq &iq)
return;
}
- // try connecting to the offered stream hosts
- foreach (const QXmppByteStreamIq::StreamHost &streamHost, iq.streamHosts())
- {
- info(QString("Connecting to streamhost: %1 (%2:%3)").arg(
- streamHost.jid(),
- streamHost.host().toString(),
- QString::number(streamHost.port())));
-
- const QString hostName = streamHash(job->d->sid,
- job->d->jid,
- client()->configuration().jid());
-
- // try to connect to stream host
- QXmppSocksClient *socksClient = new QXmppSocksClient(streamHost.host(), streamHost.port(), job);
- socksClient->connectToHost(hostName, 0);
- // FIXME : this should probably be made asynchronous as it blocks XMPP packet handling
- if (socksClient->waitForReady(socksTimeout)) {
- job->setState(QXmppTransferJob::TransferState);
- job->d->socksSocket = socksClient;
-
- check = connect(job->d->socksSocket, SIGNAL(readyRead()),
- job, SLOT(_q_receiveData()));
- Q_ASSERT(check);
-
- check = connect(job->d->socksSocket, SIGNAL(disconnected()),
- job, SLOT(_q_disconnected()));
- Q_ASSERT(check);
-
- QXmppByteStreamIq ackIq;
- ackIq.setId(iq.id());
- ackIq.setTo(iq.from());
- ackIq.setType(QXmppIq::Result);
- ackIq.setSid(job->d->sid);
- ackIq.setStreamHostUsed(streamHost.jid());
- client()->sendPacket(ackIq);
- return;
- } else {
- warning(QString("Failed to connect to streamhost: %1 (%2:%3)").arg(
- streamHost.jid(),
- streamHost.host().toString(),
- QString::number(streamHost.port())));
- delete socksClient;
- }
- }
-
- // could not connect to any stream host
- QXmppStanza::Error error(QXmppStanza::Error::Cancel, QXmppStanza::Error::ItemNotFound);
- error.setCode(404);
- response.setType(QXmppIq::Error);
- response.setError(error);
- client()->sendPacket(response);
-
- job->terminate(QXmppTransferJob::ProtocolError);
+ job->connectToHosts(iq);
}
QStringList QXmppTransferManager::discoveryFeatures() const
@@ -732,33 +867,13 @@ bool QXmppTransferManager::handleStanza(const QDomElement &element)
return false;
}
-QXmppTransferJob* QXmppTransferManager::getJobByRequestId(QXmppTransferJob::Direction direction, const QString &jid, const QString &id)
-{
- foreach (QXmppTransferJob *job, m_jobs)
- if (job->d->direction == direction &&
- job->d->jid == jid &&
- job->d->requestId == id)
- return job;
- return 0;
-}
-
-QXmppTransferJob* QXmppTransferManager::getJobBySid(QXmppTransferJob::Direction direction, const QString &jid, const QString &sid)
-{
- foreach (QXmppTransferJob *job, m_jobs)
- if (job->d->direction == direction &&
- job->d->jid == jid &&
- job->d->sid == sid)
- return job;
- return 0;
-}
-
void QXmppTransferManager::ibbCloseIqReceived(const QXmppIbbCloseIq &iq)
{
QXmppIq response;
response.setTo(iq.from());
response.setId(iq.id());
- QXmppTransferJob *job = getJobBySid(QXmppTransferJob::IncomingDirection, iq.from(), iq.sid());
+ QXmppTransferJob *job = d->getIncomingJobBySid(iq.from(), iq.sid());
if (!job ||
job->method() != QXmppTransferJob::InBandMethod)
{
@@ -784,7 +899,7 @@ void QXmppTransferManager::ibbDataIqReceived(const QXmppIbbDataIq &iq)
response.setTo(iq.from());
response.setId(iq.id());
- QXmppTransferJob *job = getJobBySid(QXmppTransferJob::IncomingDirection, iq.from(), iq.sid());
+ QXmppTransferJob *job = d->getIncomingJobBySid(iq.from(), iq.sid());
if (!job ||
job->method() != QXmppTransferJob::InBandMethod ||
job->state() != QXmppTransferJob::TransferState)
@@ -822,7 +937,7 @@ void QXmppTransferManager::ibbOpenIqReceived(const QXmppIbbOpenIq &iq)
response.setTo(iq.from());
response.setId(iq.id());
- QXmppTransferJob *job = getJobBySid(QXmppTransferJob::IncomingDirection, iq.from(), iq.sid());
+ QXmppTransferJob *job = d->getIncomingJobBySid(iq.from(), iq.sid());
if (!job ||
job->method() != QXmppTransferJob::InBandMethod)
{
@@ -854,7 +969,7 @@ void QXmppTransferManager::ibbOpenIqReceived(const QXmppIbbOpenIq &iq)
void QXmppTransferManager::ibbResponseReceived(const QXmppIq &iq)
{
- QXmppTransferJob *job = getJobByRequestId(QXmppTransferJob::OutgoingDirection, iq.from(), iq.id());
+ QXmppTransferJob *job = d->getOutgoingJobByRequestId(iq.from(), iq.id());
if (!job ||
job->method() != QXmppTransferJob::InBandMethod ||
job->state() == QXmppTransferJob::FinishedState)
@@ -910,28 +1025,19 @@ void QXmppTransferManager::_q_iqReceived(const QXmppIq &iq)
bool check;
Q_UNUSED(check);
- foreach (QXmppTransferJob *job, m_jobs)
+ foreach (QXmppTransferJob *ptr, m_jobs)
{
// handle IQ from proxy
- if (job->d->socksProxy.jid() == iq.from() && job->d->requestId == iq.id())
+ if (ptr->direction() == QXmppTransferJob::OutgoingDirection && ptr->d->socksProxy.jid() == iq.from() && ptr->d->requestId == iq.id())
{
+ QXmppTransferOutgoingJob *job = static_cast<QXmppTransferOutgoingJob*>(ptr);
if (job->d->socksSocket)
{
// proxy connection activation result
if (iq.type() == QXmppIq::Result)
{
// proxy stream activated, start sending data
- job->setState(QXmppTransferJob::TransferState);
-
- check = connect(job->d->socksSocket, SIGNAL(bytesWritten(qint64)),
- job, SLOT(_q_sendData()));
- Q_ASSERT(check);
-
- check = connect(job->d->iodevice, SIGNAL(readyRead()),
- job, SLOT(_q_sendData()));
- Q_ASSERT(check);
-
- job->_q_sendData();
+ job->startSending();
} else if (iq.type() == QXmppIq::Error) {
// proxy stream not activated, terminate
warning("Could not activate SOCKS5 proxy bytestream");
@@ -946,8 +1052,9 @@ void QXmppTransferManager::_q_iqReceived(const QXmppIq &iq)
}
// handle IQ from peer
- else if (job->d->jid == iq.from() && job->d->requestId == iq.id())
+ else if (ptr->d->jid == iq.from() && ptr->d->requestId == iq.id())
{
+ QXmppTransferJob *job = ptr;
if (job->direction() == QXmppTransferJob::OutgoingDirection &&
job->method() == QXmppTransferJob::InBandMethod)
{
@@ -1139,7 +1246,7 @@ QXmppTransferJob *QXmppTransferManager::sendFile(const QString &jid, QIODevice *
return 0;
}
- QXmppTransferJob *job = new QXmppTransferJob(jid, QXmppTransferJob::OutgoingDirection, this);
+ QXmppTransferOutgoingJob *job = new QXmppTransferOutgoingJob(jid, client(), this);
if (sid.isEmpty())
job->d->sid = generateStanzaHash();
else
@@ -1324,7 +1431,7 @@ void QXmppTransferManager::streamInitiationIqReceived(const QXmppStreamInitiatio
// The remote party has accepted an outgoing transfer.
void QXmppTransferManager::streamInitiationResultReceived(const QXmppStreamInitiationIq &iq)
{
- QXmppTransferJob *job = getJobByRequestId(QXmppTransferJob::OutgoingDirection, iq.from(), iq.id());
+ QXmppTransferJob *job = d->getOutgoingJobByRequestId(iq.from(), iq.id());
if (!job ||
job->state() != QXmppTransferJob::OfferState)
return;
@@ -1426,7 +1533,7 @@ void QXmppTransferManager::streamInitiationSetReceived(const QXmppStreamInitiati
}
// check the stream type
- QXmppTransferJob *job = new QXmppTransferJob(iq.from(), QXmppTransferJob::IncomingDirection, this);
+ QXmppTransferIncomingJob *job = new QXmppTransferIncomingJob(iq.from(), client(), this);
int offeredMethods = QXmppTransferJob::NoMethod;
job->d->offerId = iq.id();
job->d->sid = iq.siId();
diff --git a/src/client/QXmppTransferManager.h b/src/client/QXmppTransferManager.h
index 900d2163..33b103e2 100644
--- a/src/client/QXmppTransferManager.h
+++ b/src/client/QXmppTransferManager.h
@@ -41,6 +41,8 @@ class QXmppSocksClient;
class QXmppSocksServer;
class QXmppStreamInitiationIq;
class QXmppTransferJobPrivate;
+class QXmppTransferManager;
+class QXmppTransferManagerPrivate;
class QXmppTransferFileInfo
{
@@ -176,12 +178,10 @@ public slots:
private slots:
void _q_disconnected();
- void _q_receiveData();
- void _q_sendData();
void _q_terminated();
private:
- QXmppTransferJob(const QString &jid, QXmppTransferJob::Direction direction, QObject *parent);
+ QXmppTransferJob(const QString &jid, QXmppTransferJob::Direction direction, QXmppClient *client, QObject *parent);
void checkData();
void setState(QXmppTransferJob::State state);
void terminate(QXmppTransferJob::Error error);
@@ -189,6 +189,9 @@ private:
QXmppTransferJobPrivate *const d;
friend class QXmppTransferManager;
+ friend class QXmppTransferManagerPrivate;
+ friend class QXmppTransferIncomingJob;
+ friend class QXmppTransferOutgoingJob;
};
/// \brief The QXmppTransferManager class provides support for sending and
@@ -217,6 +220,7 @@ class QXmppTransferManager : public QXmppClientExtension
public:
QXmppTransferManager();
+ ~QXmppTransferManager();
QString proxy() const;
void setProxy(const QString &proxyJid);
@@ -265,8 +269,8 @@ private slots:
void _q_socksServerConnected(QTcpSocket *socket, const QString &hostName, quint16 port);
private:
- QXmppTransferJob *getJobByRequestId(QXmppTransferJob::Direction direction, const QString &jid, const QString &id);
- QXmppTransferJob *getJobBySid(QXmppTransferJob::Direction, const QString &jid, const QString &sid);
+ QXmppTransferManagerPrivate *d;
+
void byteStreamIqReceived(const QXmppByteStreamIq&);
void byteStreamResponseReceived(const QXmppIq&);
void byteStreamResultReceived(const QXmppByteStreamIq&);
@@ -286,6 +290,8 @@ private:
bool m_proxyOnly;
QXmppSocksServer *m_socksServer;
QXmppTransferJob::Methods m_supportedMethods;
+
+ friend class QXmppTransferManagerPrivate;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QXmppTransferJob::Methods)
diff --git a/src/client/QXmppTransferManager_p.h b/src/client/QXmppTransferManager_p.h
new file mode 100644
index 00000000..d3b2d62a
--- /dev/null
+++ b/src/client/QXmppTransferManager_p.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2008-2011 The QXmpp developers
+ *
+ * Author:
+ * Jeremy Lainé
+ *
+ * Source:
+ * http://code.google.com/p/qxmpp
+ *
+ * This file is a part of QXmpp library.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ */
+
+#ifndef QXMPPTRANSFERMANAGER_P_H
+#define QXMPPTRANSFERMANAGER_P_H
+
+#include "QXmppTransferManager.h"
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the QXmpp API. It exists for the convenience
+// of the QXmppTransferManager class. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+class QXmppTransferIncomingJob : public QXmppTransferJob
+{
+ Q_OBJECT
+
+public:
+ QXmppTransferIncomingJob(const QString &jid, QXmppClient *client, QObject *parent);
+ void connectToHosts(const QXmppByteStreamIq &iq);
+
+private slots:
+ void _q_candidateDisconnected();
+ void _q_candidateReady();
+ void _q_receiveData();
+
+private:
+ void connectToNextHost();
+
+ QXmppByteStreamIq::StreamHost m_candidateHost;
+ QXmppSocksClient *m_candidateClient;
+ QList<QXmppByteStreamIq::StreamHost> m_streamCandidates;
+ QString m_streamOfferId;
+ QString m_streamOfferFrom;
+};
+
+class QXmppTransferOutgoingJob : public QXmppTransferJob
+{
+ Q_OBJECT
+
+public:
+ QXmppTransferOutgoingJob(const QString &jid, QXmppClient *client, QObject *parent);
+ void connectToProxy();
+ void startSending();
+
+private slots:
+ void _q_proxyReady();
+ void _q_sendData();
+};
+
+#endif
diff --git a/src/client/client.pri b/src/client/client.pri
index c031cbaa..aa138442 100644
--- a/src/client/client.pri
+++ b/src/client/client.pri
@@ -17,6 +17,7 @@ INSTALL_HEADERS += \
client/QXmppRosterManager.h \
client/QXmppRpcManager.h \
client/QXmppTransferManager.h \
+ client/QXmppTransferManager_p.h \
client/QXmppVCardManager.h \
client/QXmppVersionManager.h