diff options
| author | Jeremy Lainé <jeremy.laine@m4x.org> | 2010-02-25 16:16:23 +0000 |
|---|---|---|
| committer | Jeremy Lainé <jeremy.laine@m4x.org> | 2010-02-25 16:16:23 +0000 |
| commit | fadaa31cbe9ba78cc0abc8538f97ff57b77c88ce (patch) | |
| tree | ee3c234cb8dbab7360792ccee8b37a3c4d73d806 /source | |
| parent | a0de7d05622d74decbae5b26f3423f53aad45b85 (diff) | |
| download | qxmpp-fadaa31cbe9ba78cc0abc8538f97ff57b77c88ce.tar.gz | |
improve termination of file transfers
Diffstat (limited to 'source')
| -rw-r--r-- | source/QXmppSocks.cpp | 13 | ||||
| -rw-r--r-- | source/QXmppSocks.h | 2 | ||||
| -rw-r--r-- | source/QXmppTransferManager.cpp | 94 | ||||
| -rw-r--r-- | source/QXmppTransferManager.h | 17 |
4 files changed, 93 insertions, 33 deletions
diff --git a/source/QXmppSocks.cpp b/source/QXmppSocks.cpp index 6b8bfa5d..ab386114 100644 --- a/source/QXmppSocks.cpp +++ b/source/QXmppSocks.cpp @@ -114,6 +114,11 @@ QXmppSocksClient::QXmppSocksClient(const QHostAddress &proxyAddress, quint16 pro m_socket = new QTcpSocket(this); } +void QXmppSocksClient::close() +{ + m_socket->close(); +} + void QXmppSocksClient::connectToHost(const QString &hostName, quint16 hostPort) { m_hostName = hostName; @@ -203,6 +208,13 @@ QXmppSocksServer::QXmppSocksServer(QObject *parent) connect(m_server, SIGNAL(newConnection()), this, SLOT(slotNewConnection())); } +void QXmppSocksServer::close() +{ + m_server->close(); + if (m_socket) + m_socket->close(); +} + bool QXmppSocksServer::listen(const QHostAddress &address, quint16 port) { return m_server->listen(address, port); @@ -287,6 +299,7 @@ void QXmppSocksServer::slotNewConnection() m_socket->write(buffer); // connect signals + m_server->close(); connect(m_socket, SIGNAL(disconnected()), this, SIGNAL(disconnected())); connect(m_socket, SIGNAL(bytesWritten(qint64)), this, SIGNAL(bytesWritten(qint64))); } diff --git a/source/QXmppSocks.h b/source/QXmppSocks.h index f9a7e71c..ab2c84ec 100644 --- a/source/QXmppSocks.h +++ b/source/QXmppSocks.h @@ -36,6 +36,7 @@ class QXmppSocksClient : public QObject public: QXmppSocksClient(const QHostAddress &proxyAddress, quint16 proxyPort, QObject *parent=0); + void close(); void connectToHost(const QString &hostName, quint16 hostPort); QString errorString() const; QByteArray readAll(); @@ -59,6 +60,7 @@ class QXmppSocksServer : public QObject public: QXmppSocksServer(QObject *parent=0); + void close(); bool listen(const QHostAddress &address, quint16 port = 0); QHostAddress serverAddress() const; quint16 serverPort() const; diff --git a/source/QXmppTransferManager.cpp b/source/QXmppTransferManager.cpp index ad9ae231..1b0274df 100644 --- a/source/QXmppTransferManager.cpp +++ b/source/QXmppTransferManager.cpp @@ -44,9 +44,10 @@ static QString streamHash(const QString &sid, const QString &initiatorJid, const return hash.result().toHex(); } -QXmppTransferJob::QXmppTransferJob(const QString &jid, QXmppTransferManager *manager) - : QObject(manager), +QXmppTransferJob::QXmppTransferJob(const QString &jid, QXmppTransferJob::Direction direction, QObject *parent) + : QObject(parent), m_blockSize(16384), + m_direction(direction), m_done(0), m_error(NoError), m_iodevice(0), @@ -66,6 +67,11 @@ void QXmppTransferJob::accept(QIODevice *iodevice) m_iodevice = iodevice; } +QXmppTransferJob::Direction QXmppTransferJob::direction() const +{ + return m_direction; +} + QXmppTransferJob::Error QXmppTransferJob::error() const { return m_error; @@ -76,6 +82,16 @@ QString QXmppTransferJob::jid() const return m_jid; } +QString QXmppTransferJob::localFilePath() const +{ + return m_localFilePath; +} + +void QXmppTransferJob::setLocalFilePath(const QString &path) +{ + m_localFilePath = path; +} + QDateTime QXmppTransferJob::fileDate() const { return m_fileDate; @@ -117,14 +133,25 @@ void QXmppTransferJob::setState(QXmppTransferJob::State state) void QXmppTransferJob::terminate(QXmppTransferJob::Error cause) { - // close IO device - m_iodevice->close(); + if (m_state == FinishedState) + return; // change state - setState(FinishedState); - - // emit signal m_error = cause; + m_state = FinishedState; + + // close IO device + if (m_iodevice) + m_iodevice->close(); + + // close sockets + if (m_socksClient) + m_socksClient->close(); + if (m_socksServer) + m_socksServer->close(); + + // emit signals + emit stateChanged(m_state); if (cause == NoError) emit finished(); else @@ -155,10 +182,7 @@ void QXmppTransferManager::byteStreamResponseReceived(const QXmppIq &iq) return; if (iq.getType() == QXmppIq::Error) - { - // FIXME : close sockets? job->terminate(QXmppTransferJob::ProtocolError); - } } /// Handle a bytestream result, i.e. after the remote party has connected to our stream host. @@ -440,13 +464,17 @@ void QXmppTransferManager::iqReceived(const QXmppIq &iq) ibbResponseReceived(iq); else if (job->method() == QXmppTransferJob::SocksMethod) byteStreamResponseReceived(iq); + else if (iq.getType() == QXmppIq::Error) { + // remote user cancelled stream initiation + job->terminate(QXmppTransferJob::ProtocolError); + } } QXmppTransferJob *QXmppTransferManager::sendFile(const QString &jid, const QString &fileName) { // create job - QXmppTransferJob *job = new QXmppTransferJob(jid, this); + QXmppTransferJob *job = new QXmppTransferJob(jid, QXmppTransferJob::OutgoingDirection, this); // open file QFile *fileIo = new QFile(fileName, job); @@ -454,7 +482,6 @@ QXmppTransferJob *QXmppTransferManager::sendFile(const QString &jid, const QStri QFileInfo info(*fileIo); job->m_iodevice = fileIo; - job->m_methods = m_supportedMethods; job->m_sid = generateStanzaHash(); job->m_fileDate = info.lastModified(); job->m_fileName = info.fileName(); @@ -489,7 +516,7 @@ QXmppTransferJob *QXmppTransferManager::sendFile(const QString &jid, const QStri x.appendChild(field); // add supported stream methods - if (job->m_methods & QXmppTransferJob::InBandMethod) + if (m_supportedMethods & QXmppTransferJob::InBandMethod) { QXmppElement option; option.setTagName("option"); @@ -500,7 +527,7 @@ QXmppTransferJob *QXmppTransferManager::sendFile(const QString &jid, const QStri value.setValue(ns_ibb); option.appendChild(value); } - if (job->m_methods & QXmppTransferJob::SocksMethod) + if (m_supportedMethods & QXmppTransferJob::SocksMethod) { QXmppElement option; option.setTagName("option"); @@ -530,7 +557,7 @@ void QXmppTransferManager::socksClientDataReceived() { QXmppSocksClient *socks = qobject_cast<QXmppSocksClient*>(sender()); QXmppTransferJob *job = getJobBySocksClient(socks); - if (!job) + if (!job || job->state() != QXmppTransferJob::TransferState) return; QByteArray data = job->m_socksClient->readAll(); @@ -543,7 +570,7 @@ void QXmppTransferManager::socksClientDisconnected() { QXmppSocksClient *socks = qobject_cast<QXmppSocksClient*>(sender()); QXmppTransferJob *job = getJobBySocksClient(socks); - if (!job) + if (!job || job->state() == QXmppTransferJob::FinishedState) return; // terminate the transfer @@ -557,8 +584,7 @@ void QXmppTransferManager::socksServerDataSent() { QXmppSocksServer *socksServer = qobject_cast<QXmppSocksServer*>(sender()); QXmppTransferJob *job = getJobBySocksServer(socksServer); - if (!job || - job->state() != QXmppTransferJob::TransferState) + if (!job || job->state() != QXmppTransferJob::TransferState) return; // send next data block @@ -567,7 +593,13 @@ void QXmppTransferManager::socksServerDataSent() void QXmppTransferManager::socksServerDisconnected() { - qWarning("Socks server disconnected"); + QXmppSocksServer *socksServer = qobject_cast<QXmppSocksServer*>(sender()); + QXmppTransferJob *job = getJobBySocksServer(socksServer); + if (!job || job->state() == QXmppTransferJob::FinishedState) + return; + + // terminate transfer + job->terminate(QXmppTransferJob::ProtocolError); } void QXmppTransferManager::socksServerSendData(QXmppTransferJob *job) @@ -609,10 +641,10 @@ void QXmppTransferManager::streamInitiationResultReceived(const QXmppStreamIniti if (field.attribute("var") == "stream-method") { if ((field.firstChildElement("value").value() == ns_ibb) && - (job->m_methods & QXmppTransferJob::InBandMethod)) + (m_supportedMethods & QXmppTransferJob::InBandMethod)) job->m_method = QXmppTransferJob::InBandMethod; else if ((field.firstChildElement("value").value() == ns_bytestreams) && - (job->m_methods & QXmppTransferJob::SocksMethod)) + (m_supportedMethods & QXmppTransferJob::SocksMethod)) job->m_method = QXmppTransferJob::SocksMethod; } field = field.nextSiblingElement("field"); @@ -636,7 +668,6 @@ void QXmppTransferManager::streamInitiationResultReceived(const QXmppStreamIniti streamIq.setTo(job->m_jid); streamIq.setSid(job->m_sid); - quint16 port = 40123; const QString ownJid = m_client->getConfiguration().getJid(); QList<QXmppByteStreamIq::StreamHost> streamHosts; @@ -657,7 +688,8 @@ void QXmppTransferManager::streamInitiationResultReceived(const QXmppStreamIniti entry.netmask() == QHostAddress::Broadcast) continue; - if (!job->m_socksServer->listen(entry.ip(), port)) + // we let the server pick a port + if (!job->m_socksServer->listen(entry.ip())) { qWarning() << "QXmppSocksServer could not listen on address" << entry.ip(); continue; @@ -705,8 +737,8 @@ void QXmppTransferManager::streamInitiationSetReceived(const QXmppStreamInitiati } // check the stream type - QXmppTransferJob *job = new QXmppTransferJob(iq.getFrom(), this); - job->m_methods = QXmppTransferJob::NoMethod; + QXmppTransferJob *job = new QXmppTransferJob(iq.getFrom(), QXmppTransferJob::IncomingDirection, this); + int offeredMethods = QXmppTransferJob::NoMethod; job->m_sid = iq.getSiId(); job->m_mimeType = iq.getMimeType(); foreach (const QXmppElement &item, iq.getSiItems()) @@ -722,9 +754,9 @@ void QXmppTransferManager::streamInitiationSetReceived(const QXmppStreamInitiati while (!option.isNull()) { if (option.firstChildElement("value").value() == ns_ibb) - job->m_methods = job->m_methods | QXmppTransferJob::InBandMethod; + offeredMethods = offeredMethods | QXmppTransferJob::InBandMethod; else if (option.firstChildElement("value").value() == ns_bytestreams) - job->m_methods = job->m_methods | QXmppTransferJob::SocksMethod; + offeredMethods = offeredMethods | QXmppTransferJob::SocksMethod; option = option.nextSiblingElement("option"); } } @@ -740,11 +772,13 @@ void QXmppTransferManager::streamInitiationSetReceived(const QXmppStreamInitiati } } - if (job->m_methods & QXmppTransferJob::SocksMethod) + // select a method supported by both parties + int sharedMethods = (offeredMethods & m_supportedMethods); + if (sharedMethods & QXmppTransferJob::SocksMethod) job->m_method = QXmppTransferJob::SocksMethod; - else if (job->m_methods & QXmppTransferJob::InBandMethod) + else if (sharedMethods & QXmppTransferJob::InBandMethod) job->m_method = QXmppTransferJob::InBandMethod; - if (!job->m_methods) + else { // FIXME : we should add: // <no-valid-streams xmlns='http://jabber.org/protocol/si'/> diff --git a/source/QXmppTransferManager.h b/source/QXmppTransferManager.h index 927d5c8e..ca743f51 100644 --- a/source/QXmppTransferManager.h +++ b/source/QXmppTransferManager.h @@ -37,13 +37,18 @@ class QXmppIbbOpenIq; class QXmppSocksClient; class QXmppSocksServer; class QXmppStreamInitiationIq; -class QXmppTransferManager; class QXmppTransferJob : public QObject { Q_OBJECT public: + enum Direction + { + IncomingDirection, + OutgoingDirection, + }; + enum Error { NoError = 0, @@ -68,7 +73,10 @@ public: void accept(QIODevice *output); + QXmppTransferJob::Direction direction() const; QXmppTransferJob::Error error() const; + QString localFilePath() const; + void setLocalFilePath(const QString &path); QString jid() const; QXmppTransferJob::Method method() const; QXmppTransferJob::State state() const; @@ -86,22 +94,25 @@ signals: void stateChanged(QXmppTransferJob::State state); private: - QXmppTransferJob(const QString &jid, QXmppTransferManager *manager); + QXmppTransferJob(const QString &jid, QXmppTransferJob::Direction direction, QObject *parent); void setState(QXmppTransferJob::State state); void terminate(QXmppTransferJob::Error error); int m_blockSize; + QXmppTransferJob::Direction m_direction; int m_done; QXmppTransferJob::Error m_error; QIODevice *m_iodevice; QString m_jid; QString m_sid; Method m_method; - int m_methods; QString m_mimeType; QString m_requestId; State m_state; + // local path to file + QString m_localFilePath; + // file meta-data QDateTime m_fileDate; QString m_fileHash; |
