aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Lainé <jeremy.laine@m4x.org>2010-02-24 10:33:02 +0000
committerJeremy Lainé <jeremy.laine@m4x.org>2010-02-24 10:33:02 +0000
commit95d3dfef904b3a90b64c8b28f93b3f4c04701048 (patch)
tree99fa0ba9138ad6de46464f921c121f955f690b99
parenteaa17977f41d1fa3568540824bf33fd725c40afa (diff)
downloadqxmpp-95d3dfef904b3a90b64c8b28f93b3f4c04701048.tar.gz
replace QXmppIbbTransfer* by QXmppTransferManager
-rw-r--r--source/QXmppClient.cpp22
-rw-r--r--source/QXmppClient.h5
-rw-r--r--source/QXmppIbbTransferJob.cpp229
-rw-r--r--source/QXmppIbbTransferJob.h66
-rw-r--r--source/QXmppIbbTransferManager.cpp95
-rw-r--r--source/QXmppIbbTransferManager.h61
-rw-r--r--source/QXmppInformationRequestResult.cpp8
-rw-r--r--source/QXmppStream.cpp116
-rw-r--r--source/QXmppStream.h10
-rw-r--r--source/QXmppTransferManager.cpp496
-rw-r--r--source/QXmppTransferManager.h125
-rw-r--r--source/source.pro6
12 files changed, 719 insertions, 520 deletions
diff --git a/source/QXmppClient.cpp b/source/QXmppClient.cpp
index c5f67402..4070cdda 100644
--- a/source/QXmppClient.cpp
+++ b/source/QXmppClient.cpp
@@ -27,7 +27,6 @@
#include "QXmppRoster.h"
#include "QXmppMessage.h"
#include "QXmppReconnectionManager.h"
-#include "QXmppIbbTransferManager.h"
#include "QXmppInvokable.h"
#include "QXmppRpcIq.h"
#include "QXmppRemoteMethod.h"
@@ -39,7 +38,7 @@
QXmppClient::QXmppClient(QObject *parent)
: QObject(parent), m_stream(0), m_clientPrecence(QXmppPresence::Available),
- m_reconnectionManager(0), m_ibbTransferManager(0)
+ m_reconnectionManager(0)
{
m_stream = new QXmppStream(this);
@@ -73,8 +72,6 @@ QXmppClient::QXmppClient(QObject *parent)
check = setReconnectionManager(new QXmppReconnectionManager(this));
Q_ASSERT(check);
-
- m_ibbTransferManager = new QXmppIbbTransferManager(this);
}
/// Destructor, destroys the QXmppClient object.
@@ -448,11 +445,6 @@ void QXmppClient::invokeInterfaceMethod( const QXmppRpcInvokeIq &iq )
m_stream->sendPacket( errorIq );
}
-QXmppIbbTransferManager* QXmppClient::getIbbTransferManager() const
-{
- return m_ibbTransferManager;
-}
-
QXmppRemoteMethodResult QXmppClient::callRemoteMethod( const QString &jid,
const QString &interface,
const QVariant &arg1,
@@ -496,3 +488,15 @@ QXmppArchiveManager& QXmppClient::getArchiveManager()
{
return m_stream->getArchiveManager();
}
+
+/// Returns the reference to QXmppTransferManager, implementation of:
+///
+/// * XEP-0047: In-Band Bytestreams
+/// * XEP-0095: Stream Initiation
+/// * XEP-0096: SI File Transfer
+///
+
+QXmppTransferManager& QXmppClient::getTransferManager()
+{
+ return m_stream->getTransferManager();
+}
diff --git a/source/QXmppClient.h b/source/QXmppClient.h
index 1692e6fb..57077222 100644
--- a/source/QXmppClient.h
+++ b/source/QXmppClient.h
@@ -58,10 +58,10 @@ class QXmppVCardManager;
class QXmppInvokable;
class QXmppRpcInvokeIq;
class QXmppRemoteMethod;
-class QXmppIbbTransferManager;
class QXmppRemoteMethodResult;
class QXmppArchiveManager;
class QXmppDiscoveryIq;
+class QXmppTransferManager;
class QXmppClient : public QObject
{
@@ -112,8 +112,8 @@ public:
bool setReconnectionManager(QXmppReconnectionManager*);
const QXmppPresence& getClientPresence() const;
QXmppVCardManager& getVCardManager();
- QXmppIbbTransferManager* getIbbTransferManager() const;
QXmppArchiveManager& getArchiveManager();
+ QXmppTransferManager& getTransferManager();
signals:
@@ -207,7 +207,6 @@ private:
QXmppPresence m_clientPrecence; ///< Stores the current presence of connected client
QXmppReconnectionManager* m_reconnectionManager; ///< Pointer to the reconnection manager
QHash<QString,QXmppInvokable *> m_interfaces;
- QXmppIbbTransferManager* m_ibbTransferManager; ///< Pointer to the ibb transfer manager
};
#endif // QXMPPCLIENT_H
diff --git a/source/QXmppIbbTransferJob.cpp b/source/QXmppIbbTransferJob.cpp
deleted file mode 100644
index f6af11e6..00000000
--- a/source/QXmppIbbTransferJob.cpp
+++ /dev/null
@@ -1,229 +0,0 @@
-#include "QXmppIbbTransferJob.h"
-
-#include <QIODevice>
-#include <QUuid>
-#include "QXmppIbbIqs.h"
-#include "QXmppClient.h"
-#include "QXmppUtils.h"
-
-QXmppIbbTransferJob::QXmppIbbTransferJob( QXmppClient *parent )
- : QObject (parent ), m_client(parent), m_io(0), m_blockSize(4096),
- m_streamBlockSize(0), m_sequence(0), m_state(Idle)
-{
- m_localJid = parent->getConfiguration().getJid();
- m_id = generateStanzaHash();
- m_sid = generateStanzaHash();
-}
-
-QXmppIbbTransferJob::~QXmppIbbTransferJob()
-{
-}
-
-QString QXmppIbbTransferJob::getSid() const
-{
- return m_sid;
-}
-
-void QXmppIbbTransferJob::setSid( const QString &sid )
-{
- m_sid = sid;
-}
-
-void QXmppIbbTransferJob::setRemoteJid( const QString &jid )
-{
- m_remoteJid = jid;
-}
-
-QString QXmppIbbTransferJob::getRemoteJid( ) const
-{
- return m_remoteJid;
-}
-
-QString QXmppIbbTransferJob::getId() const
-{
- return m_id;
-}
-
-void QXmppIbbTransferJob::setId( const QString &id )
-{
- m_id = id;
-}
-
-void QXmppIbbTransferJob::requestTransfer( )
-{
- m_state = Requesting;
- QXmppIbbOpenIq request;
- request.setBlockSize(m_blockSize);
- request.setTo( m_remoteJid );
- request.setFrom( m_localJid );
- request.setSid( m_sid );
- request.generateAndSetNextId();
- m_id = request.getId();
-
- m_client->sendPacket( request );
-
-}
-
-void QXmppIbbTransferJob::acceptTransfer( )
-{
- if( m_state != Pending )
- {
- return;
- }
-
- m_state = TransferringIn;
- QXmppIbbAckIq ack;
- ack.setTo( m_remoteJid );
- ack.setFrom( m_localJid );
- ack.setId( m_id );
- m_client->sendPacket( ack );
- emit transferStarted(m_sid);
-}
-
-void QXmppIbbTransferJob::cancelTransfer( )
-{
- QXmppIbbErrorIq cancel;
- cancel.setId(m_id);
- cancel.setErrorType( QXmppIbbErrorIq::Cancel );
- m_client->sendPacket( cancel );
-}
-
-void QXmppIbbTransferJob::setIoDevice( QIODevice *io )
-{
- m_io = io;
-}
-
-void QXmppIbbTransferJob::setBlockSize( long size)
-{
- m_blockSize = size;
-}
-
-void QXmppIbbTransferJob::gotAck()
-{
- if( m_state == Requesting )
- {
- // start transfer
- m_state = TransferringOut;
- sendNextBlock();
- }
- else if ( m_state == TransferringOut )
- {
- // send next packet
- sendNextBlock();
- }
- else if ( m_state == Idle )
- {
- emit readyForTeardown(m_sid);
- }
- else
- {
-
- }
-}
-
-void QXmppIbbTransferJob::gotOpen( const QXmppIbbOpenIq &open )
-{
- m_sid = open.getSid();
- m_id = open.getId();
- m_remoteJid = open.getFrom();
- if( open.getBlockSize() > m_blockSize )
- {
- // cancel
- m_state = Idle;
- QXmppIbbErrorIq modifyError;
- modifyError.setId(m_id);
- modifyError.setErrorType( QXmppIbbErrorIq::Modify );
- m_client->sendPacket( modifyError );
- emit readyForTeardown(m_sid);
- }
- else
- {
- m_streamBlockSize = open.getBlockSize();
- m_state = Pending;
- emit transferRequested( m_sid , m_remoteJid );
- }
-}
-
-void QXmppIbbTransferJob::gotClose( const QXmppIbbCloseIq &close )
-{
- m_state = Idle;
- QXmppIbbAckIq ack;
- ack.setTo( m_remoteJid );
- ack.setFrom( m_localJid );
- ack.setId( m_id );
- m_client->sendPacket( ack );
- emit transferFinished(m_sid, "Closed");
- emit readyForTeardown(m_sid);
-}
-
-void QXmppIbbTransferJob::gotError( const QXmppIbbErrorIq &err )
-{
- m_state = Idle;
- emit transferCanceled(m_sid,err.getError().getConditionStr());
- emit readyForTeardown(m_sid);
-}
-
-void QXmppIbbTransferJob::gotData( const QXmppIbbDataIq &data )
-{
- if( m_io &&
- (data.getSequence() == 0 || data.getSequence() > m_sequence) )
- {
- m_io->write( data.getPayload() );
- m_sequence = data.getSequence();
- QXmppIbbAckIq ack;
- ack.setId(m_id);
- ack.setTo(m_remoteJid);
- ack.setFrom(m_localJid);
- m_client->sendPacket( ack );
- }
- else
- {
- QXmppIbbErrorIq error;
- error.setId(m_id);
- error.setTo(m_remoteJid);
- error.setFrom(m_localJid);
- error.setErrorType(QXmppIbbErrorIq::Cancel);
- m_client->sendPacket( error );
- }
-}
-
-void QXmppIbbTransferJob::sendNextBlock()
-{
-
- if( m_io == 0 || !m_io->isReadable() )
- {
- QXmppIbbErrorIq error;
- error.setId(m_id);
- error.setTo(m_remoteJid);
- error.setFrom(m_localJid);
- error.setErrorType(QXmppIbbErrorIq::Cancel);
- m_client->sendPacket( error );
- }
- else if( m_io->atEnd() || !m_io->isOpen() )
- {
- QXmppIbbCloseIq close;
- close.setId(m_id);
- close.setTo(m_remoteJid);
- close.setFrom(m_localJid);
- close.setSid(m_sid);
- m_client->sendPacket( close );
- m_state = Idle;
- emit transferFinished(m_sid, "Send finished");
- }
- else
- {
- //FIXME: work better with sockets and other stream devices.
- QByteArray buffer = m_io->read( m_blockSize );
-
- m_sequence++;
- QXmppIbbDataIq sendData;
- sendData.setId(m_id);
- sendData.setTo(m_remoteJid);
- sendData.setFrom(m_localJid);
- sendData.setSid(m_sid);
- sendData.setSequence(m_sequence);
- sendData.setPayload( buffer );
-
- m_client->sendPacket( sendData );
- }
-}
diff --git a/source/QXmppIbbTransferJob.h b/source/QXmppIbbTransferJob.h
deleted file mode 100644
index a3bf1140..00000000
--- a/source/QXmppIbbTransferJob.h
+++ /dev/null
@@ -1,66 +0,0 @@
-#ifndef QXMPPIBBTRANSFERJOB_H
-#define QXMPPIBBTRANSFERJOB_H
-
-#include <QObject>
-class QIODevice;
-class QXmppIbbOpenIq;
-class QXmppIbbCloseIq;
-class QXmppIbbErrorIq;
-class QXmppIbbDataIq;
-class QXmppClient;
-
-class QXmppIbbTransferJob : public QObject
-{
- Q_OBJECT
-public:
-
- QXmppIbbTransferJob(QXmppClient *parent = 0);
- ~QXmppIbbTransferJob();
- QString getSid() const;
- void setSid( const QString &sid );
- QString getRemoteJid( ) const;
- void setRemoteJid( const QString &jid );
- QString getId() const;
- void setId( const QString &id );
-
-// Used by the client
-public slots:
- void requestTransfer( );
- void acceptTransfer( );
- void cancelTransfer( );
-
-signals:
- void transferRequested( const QString &sid, const QString &remoteJid );
- void transferStarted( const QString &sid );
- void transferFinished( const QString &sid, const QString &reason);
- void transferCanceled( const QString &sid, const QString &reason );
- void readyForTeardown( const QString &sid );
-
-public:
- void setIoDevice( QIODevice *io );
- void setBlockSize( long size);
-
- // Used by the stream.
- void gotAck();
- void gotOpen( const QXmppIbbOpenIq &open );
- void gotClose( const QXmppIbbCloseIq &close );
- void gotError( const QXmppIbbErrorIq &err );
- void gotData( const QXmppIbbDataIq &data );
-
-private:
- enum TransferState { Idle, Requesting, Pending, TransferringIn, TransferringOut };
- void sendNextBlock();
-
- QXmppClient *m_client;
- QIODevice *m_io;
- long m_blockSize;
- qint64 m_streamBlockSize;
- quint16 m_sequence;
- QString m_sid;
- QString m_id;
- QString m_localJid;
- QString m_remoteJid;
- TransferState m_state;
-};
-
-#endif // QXMPPIBBTRANSFERJOB_H
diff --git a/source/QXmppIbbTransferManager.cpp b/source/QXmppIbbTransferManager.cpp
deleted file mode 100644
index e9437b5b..00000000
--- a/source/QXmppIbbTransferManager.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-#include "QXmppIbbTransferManager.h"
-#include "QXmppClient.h"
-
-QXmppIbbTransferManager::QXmppIbbTransferManager(QXmppClient* client):
- m_client(client)
-{
-}
-
-void QXmppIbbTransferManager::teardownIbbTransferManager( const QString &sid )
-{
- QString id = getIbbTransferJobBySid(sid)->getId();
- delete m_activeTransfers[id];
- m_activeTransfers.remove(id);
-}
-
-void QXmppIbbTransferManager::addIbbTransferManager( QXmppIbbTransferJob *mgr )
-{
- m_activeTransfers[mgr->getId()] = mgr;
- connect( mgr, SIGNAL(transferCanceled(QString,QString)),
- this, SIGNAL(byteStreamCanceled(QString,QString)));
- connect( mgr, SIGNAL(transferFinished(QString,QString)),
- this, SIGNAL(byteStreamClosed(QString,QString)));
- connect( mgr, SIGNAL(transferRequested(QString,QString)),
- this, SIGNAL(byteStreamRequestReceived(QString,QString)));
- connect( mgr, SIGNAL(transferStarted(QString)),
- this, SIGNAL(byteStreamOpened(QString)));
- connect( mgr, SIGNAL(readyForTeardown(QString)),
- this, SLOT(teardownIbbTransferManager(QString)));
-}
-
-QXmppIbbTransferJob *QXmppIbbTransferManager::getIbbTransferJob( const QString &id )
-{
- QXmppIbbTransferJob *mgr = m_activeTransfers[id];
- if( mgr == 0 )
- {
- mgr = new QXmppIbbTransferJob(m_client);
- mgr->setId(id);
- addIbbTransferManager(mgr);
- }
- return mgr;
-}
-
-bool QXmppIbbTransferManager::isIbbTransferJobId( const QString &id )
-{
- return m_activeTransfers.keys().contains(id);
-}
-
-QXmppIbbTransferJob *QXmppIbbTransferManager::getIbbTransferJobBySid( const QString &sid )
-{
- foreach( QXmppIbbTransferJob *mgr, m_activeTransfers )
- {
- if ( mgr->getSid() == sid )
- return mgr;
- }
-
- return 0;
-}
-
-void QXmppIbbTransferManager::sendByteStreamRequest( const QString &sid, const QString &bareRemoteJid, QIODevice *io)
-{
-
- QXmppIbbTransferJob *mgr = new QXmppIbbTransferJob(m_client);
- mgr->setSid( sid );
- mgr->setRemoteJid( bareRemoteJid ); //FIXME: make like send message
- mgr->setIoDevice( io );
- mgr->requestTransfer();
- addIbbTransferManager( mgr );
-
-}
-
-void QXmppIbbTransferManager::acceptByteStreamRequest( const QString &sid, QIODevice *io )
-{
- QXmppIbbTransferJob *mgr = getIbbTransferJobBySid(sid);
- if( mgr == 0 )
- return;
-
- mgr->setIoDevice(io);
- mgr->acceptTransfer();
-}
-
-void QXmppIbbTransferManager::rejectByteStreamRequest( const QString &sid )
-{
- QXmppIbbTransferJob *mgr = getIbbTransferJobBySid(sid);
- if( mgr == 0 )
- return;
- mgr->cancelTransfer();
-}
-
-void QXmppIbbTransferManager::cancelByteStreamRequest( const QString &sid )
-{
- QXmppIbbTransferJob *mgr = getIbbTransferJobBySid(sid);
- if( mgr == 0 )
- return;
- mgr->cancelTransfer();
-}
diff --git a/source/QXmppIbbTransferManager.h b/source/QXmppIbbTransferManager.h
deleted file mode 100644
index 014b20cf..00000000
--- a/source/QXmppIbbTransferManager.h
+++ /dev/null
@@ -1,61 +0,0 @@
-#ifndef QXMPPIBBTRANSFERMANAGER_H
-#define QXMPPIBBTRANSFERMANAGER_H
-
-#include <QObject>
-#include <QHash>
-#include "QXmppIbbTransferJob.h"
-
-class QXmppClient;
-
-class QXmppIbbTransferManager : public QObject
-{
- Q_OBJECT
-public:
- QXmppIbbTransferManager(QXmppClient* client);
-
-signals:
- /// Notifies that a XMPP bytestream request has been received. The
- /// program must either reply with an acceptByteStreamRequest(...) or
- /// a rejectByteStreamRequest(...) depending on the desired response.
- void byteStreamRequestReceived( const QString &sid, const QString &remoteJid );
- /// Notifies that a XMPP bytestream has been closed.
- void byteStreamClosed( const QString &sid , const QString &reason );
- /// Notifies that a XMPP bytestream was canceled by the remote peer.
- /// The reason is given for the cancelation.
- void byteStreamCanceled( const QString &sid , const QString &reason );
- /// Notifes that the XMPP bytestream has been opened and the transfer
- /// has started.
- void byteStreamOpened( const QString &sid );
-
-public:
- QXmppIbbTransferJob *getIbbTransferJob( const QString &id );
- bool isIbbTransferJobId( const QString &id );
-
-public slots:
- /// Send a request to open a bytestream to a specific jid. Once the
- /// stream is opened then the data is read from the QIODevice. The
- /// QIODevice MUST be be open and ready for reading otherwise the
- /// transfer will fail. When there are no more bytes available to
- /// send from the QIODevice then the bytestream is closed.
- void sendByteStreamRequest( const QString &sid, const QString &bareJid, QIODevice *io);
- /// Accept a bytestream with a specific sid. Data from the remote
- /// peer is then written to the QIODevice. Therefor the QIODevice must
- /// be open and ready for writing before this method is called.
- void acceptByteStreamRequest( const QString &sid, QIODevice *io );
- /// Rejects a bytestream from a specific sid.
- void rejectByteStreamRequest( const QString &sid );
- /// Cacels a currenly connected bytestream with a specific sid.
- void cancelByteStreamRequest( const QString &sid );
-
-private slots:
- void addIbbTransferManager( QXmppIbbTransferJob *mgr );
- void teardownIbbTransferManager( const QString &sid );
-
-private:
- QXmppIbbTransferJob *getIbbTransferJobBySid( const QString &sid );
-
- QXmppClient* m_client;
- QHash<QString, QXmppIbbTransferJob*> m_activeTransfers;
-};
-
-#endif // QXMPPIBBTRANSFERMANAGER_H
diff --git a/source/QXmppInformationRequestResult.cpp b/source/QXmppInformationRequestResult.cpp
index 072bc75f..964d6cfc 100644
--- a/source/QXmppInformationRequestResult.cpp
+++ b/source/QXmppInformationRequestResult.cpp
@@ -35,5 +35,13 @@ void QXmppInformationRequestResult::toXmlElementFromChild(QXmlStreamWriter *writ
writer->writeAttribute("var", ns_chat_states);
writer->writeEndElement();
+ writer->writeStartElement("feature");
+ writer->writeAttribute("var", ns_stream_initiation);
+ writer->writeEndElement();
+
+ writer->writeStartElement("feature");
+ writer->writeAttribute("var", ns_stream_initiation_file_transfer);
+ writer->writeEndElement();
+
writer->writeEndElement();
}
diff --git a/source/QXmppStream.cpp b/source/QXmppStream.cpp
index d01b4130..05967a47 100644
--- a/source/QXmppStream.cpp
+++ b/source/QXmppStream.cpp
@@ -39,13 +39,12 @@
#include "QXmppInformationRequestResult.h"
#include "QXmppIbbIqs.h"
#include "QXmppRpcIq.h"
-#include "QXmppIbbTransferManager.h"
#include "QXmppArchiveIq.h"
#include "QXmppDiscoveryIq.h"
#include "QXmppPingIq.h"
#include "QXmppLogger.h"
-#include "QXmppUtils.h"
-
+#include "QXmppStreamInitiationIq.h"
+#include "QXmppTransferManager.h"
#include <QDomDocument>
#include <QStringList>
@@ -58,8 +57,10 @@ static const QByteArray streamRootElementEnd = "</stream:stream>";
QXmppStream::QXmppStream(QXmppClient* client)
: QObject(client), m_client(client), m_roster(this),
- m_sessionAvaliable(false), m_vCardManager(m_client),
+ m_sessionAvaliable(false),
m_archiveManager(m_client),
+ m_transferManager(m_client),
+ m_vCardManager(m_client),
m_authStep(0)
{
bool check = QObject::connect(&m_socket, SIGNAL(hostFound()),
@@ -121,6 +122,28 @@ QXmppStream::QXmppStream(QXmppClient* client)
check = QObject::connect(this, SIGNAL(archivePrefIqReceived(const QXmppArchivePrefIq&)),
&m_archiveManager, SLOT(archivePrefIqReceived(const QXmppArchivePrefIq&)));
Q_ASSERT(check);
+
+ // XEP-0047: In-Band Bytestreams
+ check = QObject::connect(this, SIGNAL(iqReceived(const QXmppIq&)),
+ &m_transferManager, SLOT(iqReceived(const QXmppIq&)));
+ Q_ASSERT(check);
+
+ check = QObject::connect(this, SIGNAL(ibbCloseIqReceived(const QXmppIbbCloseIq&)),
+ &m_transferManager, SLOT(ibbCloseIqReceived(const QXmppIbbCloseIq&)));
+ Q_ASSERT(check);
+
+ check = QObject::connect(this, SIGNAL(ibbDataIqReceived(const QXmppIbbDataIq&)),
+ &m_transferManager, SLOT(ibbDataIqReceived(const QXmppIbbDataIq&)));
+ Q_ASSERT(check);
+
+ check = QObject::connect(this, SIGNAL(ibbOpenIqReceived(const QXmppIbbOpenIq&)),
+ &m_transferManager, SLOT(ibbOpenIqReceived(const QXmppIbbOpenIq&)));
+ Q_ASSERT(check);
+
+ // XEP-0095: Stream Initiation
+ check = QObject::connect(this, SIGNAL(streamInitiationIqReceived(const QXmppStreamInitiationIq&)),
+ &m_transferManager, SLOT(streamInitiationIqReceived(const QXmppStreamInitiationIq&)));
+ Q_ASSERT(check);
}
QXmppStream::~QXmppStream()
@@ -433,53 +456,7 @@ void QXmppStream::parser(const QByteArray& data)
QDomElement elemen = nodeRecv.firstChildElement("error");
QXmppStanza::Error error = QXmppStanza::parseError(elemen);
- if( QXmppIbbOpenIq::isIbbOpenIq( nodeRecv ) )
- {
- QXmppIbbOpenIq openIqPacket;
- openIqPacket.parse( nodeRecv );
-
- QXmppIbbTransferJob *mgr = m_client->getIbbTransferManager()->
- getIbbTransferJob(openIqPacket.getId());
- mgr->gotOpen( openIqPacket );
- }
- else if( QXmppIbbErrorIq::isIbbErrorIq( nodeRecv ) &&
- m_client->getIbbTransferManager()->isIbbTransferJobId( id ))
- {
- QXmppIbbErrorIq errorIqPacket;
- errorIqPacket.parse(nodeRecv);
-
- QXmppIbbTransferJob *mgr = m_client->getIbbTransferManager()->
- getIbbTransferJob(errorIqPacket.getId());
- mgr->gotError( errorIqPacket );
- }
- else if( QXmppIbbAckIq::isIbbAckIq( nodeRecv ) &&
- m_client->getIbbTransferManager()->isIbbTransferJobId( id ))
- {
- QXmppIbbAckIq ackIqPacket;
- ackIqPacket.parse(nodeRecv);
-
- QXmppIbbTransferJob *mgr = m_client->getIbbTransferManager()->getIbbTransferJob(ackIqPacket.getId());
- mgr->gotAck();
- }
- else if( QXmppIbbDataIq::isIbbDataIq( nodeRecv ) &&
- m_client->getIbbTransferManager()->isIbbTransferJobId( id ))
- {
- QXmppIbbDataIq dataIqPacket;
- dataIqPacket.parse(nodeRecv);
-
- QXmppIbbTransferJob *mgr = m_client->getIbbTransferManager()->getIbbTransferJob(dataIqPacket.getId());
- mgr->gotData(dataIqPacket);
- }
- else if( QXmppIbbCloseIq::isIbbCloseIq( nodeRecv ) &&
- m_client->getIbbTransferManager()->isIbbTransferJobId( id ))
- {
- QXmppIbbCloseIq closeIqPacket;
- closeIqPacket.parse(nodeRecv);
-
- QXmppIbbTransferJob *mgr = m_client->getIbbTransferManager()->getIbbTransferJob(closeIqPacket.getId());
- mgr->gotClose(closeIqPacket);
- }
- else if( QXmppRpcInvokeIq::isRpcInvokeIq( nodeRecv ) )
+ if( QXmppRpcInvokeIq::isRpcInvokeIq( nodeRecv ) )
{
QXmppRpcInvokeIq rpcIqPacket;
rpcIqPacket.parse(nodeRecv);
@@ -625,7 +602,37 @@ void QXmppStream::parser(const QByteArray& data)
sendNonSASLAuth(plainText);
}
}
- // XEP-0136 message archiving
+ // XEP-0047 In-Band Bytestreams
+ else if(QXmppIbbCloseIq::isIbbCloseIq(nodeRecv))
+ {
+ QXmppIbbCloseIq ibbCloseIq;
+ ibbCloseIq.parse(nodeRecv);
+ emit ibbCloseIqReceived(ibbCloseIq);
+ iqPacket = ibbCloseIq;
+ }
+ else if(QXmppIbbDataIq::isIbbDataIq(nodeRecv))
+ {
+ QXmppIbbDataIq ibbDataIq;
+ ibbDataIq.parse(nodeRecv);
+ emit ibbDataIqReceived(ibbDataIq);
+ iqPacket = ibbDataIq;
+ }
+ else if(QXmppIbbOpenIq::isIbbOpenIq(nodeRecv))
+ {
+ QXmppIbbOpenIq ibbOpenIq;
+ ibbOpenIq.parse(nodeRecv);
+ emit ibbOpenIqReceived(ibbOpenIq);
+ iqPacket = ibbOpenIq;
+ }
+ // XEP-0095: Stream Initiation
+ else if(QXmppStreamInitiationIq::isStreamInitiationIq(nodeRecv))
+ {
+ QXmppStreamInitiationIq siIq;
+ siIq.parse(nodeRecv);
+ emit streamInitiationIqReceived(siIq);
+ iqPacket = siIq;
+ }
+ // XEP-0136: Message Archiving
else if(QXmppArchiveChatIq::isArchiveChatIq(nodeRecv))
{
QXmppArchiveChatIq archiveIq;
@@ -1075,3 +1082,8 @@ QXmppArchiveManager& QXmppStream::getArchiveManager()
{
return m_archiveManager;
}
+
+QXmppTransferManager& QXmppStream::getTransferManager()
+{
+ return m_transferManager;
+}
diff --git a/source/QXmppStream.h b/source/QXmppStream.h
index 2890d38e..8de103b3 100644
--- a/source/QXmppStream.h
+++ b/source/QXmppStream.h
@@ -32,6 +32,7 @@
#include "QXmppStanza.h"
#include "QXmppVCardManager.h"
#include "QXmppArchiveManager.h"
+#include "QXmppTransferManager.h"
class QDomElement;
@@ -64,6 +65,7 @@ public:
void disconnect();
QXmppArchiveManager& getArchiveManager();
QXmppRoster& getRoster();
+ QXmppTransferManager& getTransferManager();
QXmppVCardManager& getVCardManager();
void sendPacket(const QXmppPacket&);
@@ -101,6 +103,11 @@ signals:
void discoveryIqReceived(const QXmppDiscoveryIq&);
+ void ibbCloseIqReceived(const QXmppIbbCloseIq&);
+ void ibbDataIqReceived(const QXmppIbbDataIq&);
+ void ibbOpenIqReceived(const QXmppIbbOpenIq&);
+ void streamInitiationIqReceived(const QXmppStreamInitiationIq&);
+
private slots:
void socketHostFound();
void socketReadReady();
@@ -126,8 +133,9 @@ private:
QXmppClient::StreamError m_xmppStreamError;
// m_xmppStanzaError;
- QXmppVCardManager m_vCardManager;
QXmppArchiveManager m_archiveManager;
+ QXmppTransferManager m_transferManager;
+ QXmppVCardManager m_vCardManager;
int m_authStep;
QXmppConfiguration& getConfiguration();
diff --git a/source/QXmppTransferManager.cpp b/source/QXmppTransferManager.cpp
new file mode 100644
index 00000000..511933b8
--- /dev/null
+++ b/source/QXmppTransferManager.cpp
@@ -0,0 +1,496 @@
+/*
+ * Copyright (C) 2010 Bolloré telecom
+ *
+ * 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.
+ *
+ */
+
+#include <QDomElement>
+#include <QFile>
+#include <QFileInfo>
+
+#include "QXmppClient.h"
+#include "QXmppConstants.h"
+#include "QXmppIbbIqs.h"
+#include "QXmppStreamInitiationIq.h"
+#include "QXmppTransferManager.h"
+#include "QXmppUtils.h"
+
+QXmppTransferJob::QXmppTransferJob(const QString &jid, QXmppTransferManager *manager)
+ : QObject(manager),
+ m_done(0),
+ m_error(NoError),
+ m_iodevice(0),
+ m_jid(jid),
+ m_fileSize(0),
+ m_ibbSequence(0)
+{
+}
+
+void QXmppTransferJob::accept(QIODevice *iodevice)
+{
+ if (!m_iodevice)
+ m_iodevice = iodevice;
+}
+
+QXmppTransferJob::Error QXmppTransferJob::error() const
+{
+ return m_error;
+}
+
+QString QXmppTransferJob::jid() const
+{
+ return m_jid;
+}
+
+QDateTime QXmppTransferJob::fileDate() const
+{
+ return m_fileDate;
+}
+
+QString QXmppTransferJob::fileHash() const
+{
+ return m_fileHash;
+}
+
+QString QXmppTransferJob::fileName() const
+{
+ return m_fileName;
+}
+
+int QXmppTransferJob::fileSize() const
+{
+ return m_fileSize;
+}
+
+void QXmppTransferJob::terminate(QXmppTransferJob::Error cause)
+{
+ // close IO device
+ m_iodevice->close();
+
+ // emit signal
+ m_error = cause;
+ if (cause == NoError)
+ emit finished();
+ else
+ emit error(m_error);
+}
+
+QXmppTransferManager::QXmppTransferManager(QXmppClient *client)
+ : m_client(client), m_ibbBlockSize(4096)
+{
+}
+
+QXmppTransferJob* QXmppTransferManager::getJobByRequestId(const QString &jid, const QString &id)
+{
+ foreach (QXmppTransferJob *job, m_jobs)
+ if (job->m_jid == jid && job->m_requestId == id)
+ return job;
+ return 0;
+}
+
+QXmppTransferJob* QXmppTransferManager::getJobBySid(const QString &jid, const QString &sid)
+{
+ foreach (QXmppTransferJob *job, m_jobs)
+ if (job->m_jid == jid && job->m_sid == sid)
+ return job;
+ return 0;
+}
+
+void QXmppTransferManager::ibbCloseIqReceived(const QXmppIbbCloseIq &iq)
+{
+ QXmppIq response;
+ response.setTo(iq.getFrom());
+ response.setId(iq.getId());
+
+ QXmppTransferJob *job = getJobBySid(iq.getFrom(), iq.getSid());
+ if (!job)
+ {
+ // the job is unknown, cancel it
+ QXmppStanza::Error error(QXmppStanza::Error::Cancel, QXmppStanza::Error::ItemNotFound);
+ response.setType(QXmppIq::Error);
+ response.setError(error);
+ m_client->sendPacket(response);
+ return;
+ }
+
+ // acknowledge the packet
+ response.setType(QXmppIq::Result);
+ m_client->sendPacket(response);
+
+ // terminate the transfer
+ if (job->fileSize() && job->m_done != job->fileSize())
+ job->terminate(QXmppTransferJob::FileCorruptError);
+ else
+ job->terminate(QXmppTransferJob::NoError);
+}
+
+void QXmppTransferManager::ibbDataIqReceived(const QXmppIbbDataIq &iq)
+{
+ QXmppIq response;
+ response.setTo(iq.getFrom());
+ response.setId(iq.getId());
+
+ QXmppTransferJob *job = getJobBySid(iq.getFrom(), iq.getSid());
+ if (!job)
+ {
+ // the job is unknown, cancel it
+ QXmppStanza::Error error(QXmppStanza::Error::Cancel, QXmppStanza::Error::ItemNotFound);
+ response.setType(QXmppIq::Error);
+ response.setError(error);
+ m_client->sendPacket(response);
+ return;
+ }
+
+ if (iq.getSequence() != job->m_ibbSequence)
+ {
+ // the packet is out of sequence
+ QXmppStanza::Error error(QXmppStanza::Error::Cancel, QXmppStanza::Error::UnexpectedRequest);
+ response.setType(QXmppIq::Error);
+ response.setError(error);
+ m_client->sendPacket(response);
+ return;
+ }
+
+ // write data
+ const QByteArray data = iq.getPayload();
+ job->m_iodevice->write(data);
+ job->m_done += data.size();
+ job->m_ibbSequence++;
+ job->progress(job->m_done, job->fileSize());
+
+ // acknowledge the packet
+ response.setType(QXmppIq::Result);
+ m_client->sendPacket(response);
+}
+
+void QXmppTransferManager::ibbOpenIqReceived(const QXmppIbbOpenIq &iq)
+{
+ QXmppIq response;
+ response.setTo(iq.getFrom());
+ response.setId(iq.getId());
+
+ QXmppTransferJob *job = getJobBySid(iq.getFrom(), iq.getSid());
+ if (!job)
+ {
+ // the job is unknown, cancel it
+ QXmppStanza::Error error(QXmppStanza::Error::Cancel, QXmppStanza::Error::ItemNotFound);
+ response.setType(QXmppIq::Error);
+ response.setError(error);
+ m_client->sendPacket(response);
+ return;
+ }
+
+ if (iq.getBlockSize() > m_ibbBlockSize)
+ {
+ // we prefer a smaller block size
+ QXmppStanza::Error error(QXmppStanza::Error::Modify, QXmppStanza::Error::ResourceConstraint);
+ response.setType(QXmppIq::Error);
+ response.setError(error);
+ m_client->sendPacket(response);
+ return;
+ }
+
+ // accept transfer
+ response.setType(QXmppIq::Result);
+ m_client->sendPacket(response);
+}
+
+void QXmppTransferManager::iqReceived(const QXmppIq &iq)
+{
+ QXmppTransferJob *job = getJobByRequestId(iq.getFrom(), iq.getId());
+ if (!job)
+ return;
+
+ // if the IO device is closed, do nothing
+ if (!job->m_iodevice->isOpen())
+ return;
+
+ if (iq.getType() == QXmppIq::Result)
+ {
+ const QByteArray buffer = job->m_iodevice->read(m_ibbBlockSize);
+
+ if (buffer.size())
+ {
+ // send next data block
+ QXmppIbbDataIq dataIq;
+ dataIq.setTo(job->m_jid);
+ dataIq.setSid(job->m_sid);
+ dataIq.setSequence(job->m_ibbSequence);
+ dataIq.setPayload(buffer);
+ m_client->sendPacket(dataIq);
+
+ job->m_done += buffer.size();
+ job->m_requestId = dataIq.getId();
+ job->m_ibbSequence++;
+ job->progress(job->m_done, job->fileSize());
+ } else {
+ // close the bytestream
+ QXmppIbbCloseIq closeIq;
+ closeIq.setTo(job->m_jid);
+ closeIq.setSid(job->m_sid);
+ m_client->sendPacket(closeIq);
+
+ job->m_requestId = closeIq.getId();
+ job->terminate(QXmppTransferJob::NoError);
+ }
+ }
+ else if (iq.getType() == QXmppIq::Error)
+ {
+ // close the bytestream
+ QXmppIbbCloseIq closeIq;
+ closeIq.setTo(job->m_jid);
+ closeIq.setSid(job->m_sid);
+ m_client->sendPacket(closeIq);
+
+ job->m_requestId = closeIq.getId();
+ job->terminate(QXmppTransferJob::ProtocolError);
+
+ }
+}
+
+QXmppTransferJob *QXmppTransferManager::sendFile(const QString &jid, const QString &fileName)
+{
+ // open file
+ QFile *fileIo = new QFile(fileName, this);
+ fileIo->open(QIODevice::ReadOnly);
+ QFileInfo info(*fileIo);
+
+ // create job
+ QXmppTransferJob *job = new QXmppTransferJob(jid, this);
+ job->m_iodevice = fileIo;
+ job->m_sid = generateStanzaHash();
+ job->m_fileDate = info.lastModified();
+ job->m_fileName = info.fileName();
+ job->m_fileSize = info.size();
+ m_jobs.append(job);
+
+ // prepare negotiation
+ QXmppElementList items;
+
+ QXmppElement file;
+ file.setTagName("file");
+ file.setAttribute("xmlns", ns_stream_initiation_file_transfer);
+ file.setAttribute("date", datetimeToString(job->fileDate()));
+ file.setAttribute("name", job->fileName());
+ file.setAttribute("size", QString::number(job->fileSize()));
+ items.append(file);
+
+ QXmppElement feature;
+ feature.setTagName("feature");
+ feature.setAttribute("xmlns", ns_feature_negotiation);
+
+ QXmppElement x;
+ x.setTagName("x");
+ x.setAttribute("xmlns", "jabber:x:data");
+ x.setAttribute("type", "form");
+ feature.appendChild(x);
+
+ QXmppElement field;
+ field.setTagName("field");
+ field.setAttribute("var", "stream-method");
+ field.setAttribute("type", "list-single");
+ x.appendChild(field);
+
+ QXmppElement option;
+ option.setTagName("option");
+ field.appendChild(option);
+
+ QXmppElement value;
+ value.setTagName("value");
+ value.setValue(ns_ibb);
+ option.appendChild(value);
+ items.append(feature);
+
+ QXmppStreamInitiationIq request;
+ request.setType(QXmppIq::Set);
+ request.setTo(jid);
+ request.setProfile(QXmppStreamInitiationIq::FileTransfer);
+ request.setSiItems(items);
+ request.setSiId(job->m_sid);
+ job->m_requestId = request.getId();
+ m_client->sendPacket(request);
+
+ return job;
+}
+
+void QXmppTransferManager::streamInitiationIqReceived(const QXmppStreamInitiationIq &iq)
+{
+ if (iq.getType() == QXmppIq::Result)
+ streamInitiationResultReceived(iq);
+ else if (iq.getType() == QXmppIq::Set)
+ streamInitiationSetReceived(iq);
+}
+
+void QXmppTransferManager::streamInitiationResultReceived(const QXmppStreamInitiationIq &iq)
+{
+ QXmppTransferJob *job = getJobByRequestId(iq.getFrom(), iq.getId());
+ if (!job)
+ return;
+
+ int method = 0;
+ foreach (const QXmppElement &item, iq.getSiItems())
+ {
+ if (item.tagName() == "feature" && item.attribute("xmlns") == ns_feature_negotiation)
+ {
+ QXmppElement field = item.firstChildElement("x").firstChildElement("field");
+ while (!field.isNull())
+ {
+ if (field.attribute("var") == "stream-method")
+ {
+ if (field.firstChildElement("value").value() == ns_ibb)
+ method = QXmppTransferJob::InBandByteStream;
+/*
+ else if (field.firstChildElement("value").value() == ns_bytestreams)
+ method = QXmppTransferJob::SocksByteStream;
+*/
+ }
+ field = field.nextSiblingElement("field");
+ }
+ }
+ }
+
+ if (method == QXmppTransferJob::InBandByteStream)
+ {
+ QXmppIbbOpenIq openIq;
+ openIq.setTo(job->m_jid);
+ openIq.setSid(job->m_sid);
+ openIq.setBlockSize(m_ibbBlockSize);
+ m_client->sendPacket(openIq);
+ }
+}
+
+void QXmppTransferManager::streamInitiationSetReceived(const QXmppStreamInitiationIq &iq)
+{
+ QXmppStreamInitiationIq response;
+ response.setTo(iq.getFrom());
+ response.setId(iq.getId());
+
+ // check we support the profile
+ if (iq.getProfile() != QXmppStreamInitiationIq::FileTransfer)
+ {
+ // FIXME : we should add:
+ // <bad-profile xmlns='http://jabber.org/protocol/si'/>
+ QXmppStanza::Error error(QXmppStanza::Error::Cancel, QXmppStanza::Error::BadRequest);
+ error.setCode(400);
+
+ response.setType(QXmppIq::Error);
+ response.setError(error);
+ m_client->sendPacket(response);
+ return;
+ }
+
+ // check the stream type
+ QXmppTransferJob *job = new QXmppTransferJob(iq.getFrom(), this);
+ job->m_methods = 0;
+ job->m_sid = iq.getSiId();
+ job->m_mimeType = iq.getMimeType();
+ foreach (const QXmppElement &item, iq.getSiItems())
+ {
+ if (item.tagName() == "feature" && item.attribute("xmlns") == ns_feature_negotiation)
+ {
+ QXmppElement field = item.firstChildElement("x").firstChildElement("field");
+ while (!field.isNull())
+ {
+ if (field.attribute("var") == "stream-method" && field.attribute("type") == "list-single")
+ {
+ QXmppElement option = field.firstChildElement("option");
+ while (!option.isNull())
+ {
+ if (option.firstChildElement("value").value() == ns_ibb)
+ job->m_methods = job->m_methods | QXmppTransferJob::InBandByteStream;
+/*
+ else if (option.firstChildElement("value").value() == ns_bytestreams)
+ job->m_methods = job->m_methods | QXmppTransferJob::SocksByteStream;
+*/
+ option = option.nextSiblingElement("option");
+ }
+ }
+ field = field.nextSiblingElement("field");
+ }
+ }
+ else if (item.tagName() == "file" && item.attribute("xmlns") == ns_stream_initiation_file_transfer)
+ {
+ job->m_fileDate = datetimeFromString(item.attribute("date"));
+ job->m_fileHash = item.attribute("hash");
+ job->m_fileName = item.attribute("name");
+ job->m_fileSize = item.attribute("size").toInt();
+ }
+ }
+
+ if (!job->m_methods)
+ {
+ // FIXME : we should add:
+ // <no-valid-streams xmlns='http://jabber.org/protocol/si'/>
+ QXmppStanza::Error error(QXmppStanza::Error::Cancel, QXmppStanza::Error::BadRequest);
+ error.setCode(400);
+
+ response.setType(QXmppIq::Error);
+ response.setError(error);
+ m_client->sendPacket(response);
+
+ delete job;
+ return;
+ }
+
+ // allow user to accept or decline the job
+ emit fileReceived(job);
+ if (!job->m_iodevice)
+ {
+ QXmppStanza::Error error(QXmppStanza::Error::Cancel, QXmppStanza::Error::Forbidden);
+ error.setCode(403);
+
+ response.setType(QXmppIq::Error);
+ response.setError(error);
+ m_client->sendPacket(response);
+
+ delete job;
+ return;
+ }
+
+ // the job was accepted
+ m_jobs.append(job);
+
+ QXmppElement value;
+ value.setTagName("value");
+ value.setValue(ns_ibb);
+
+ QXmppElement field;
+ field.setTagName("field");
+ field.setAttribute("var", "stream-method");
+ field.appendChild(value);
+
+ QXmppElement x;
+ x.setTagName("x");
+ x.setAttribute("xmlns", "jabber:x:data");
+ x.setAttribute("type", "submit");
+ x.appendChild(field);
+
+ QXmppElement feature;
+ feature.setTagName("feature");
+ feature.setAttribute("xmlns", ns_feature_negotiation);
+ feature.appendChild(x);
+
+ response.setType(QXmppIq::Result);
+ response.setProfile(iq.getProfile());
+ response.setSiItems(feature);
+
+ m_client->sendPacket(response);
+}
+
diff --git a/source/QXmppTransferManager.h b/source/QXmppTransferManager.h
new file mode 100644
index 00000000..bfd781b3
--- /dev/null
+++ b/source/QXmppTransferManager.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2010 Bolloré telecom
+ *
+ * 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_H
+#define QXMPPTRANSFERMANAGER_H
+
+#include <QDateTime>
+
+#include "QXmppIq.h"
+
+class QXmppClient;
+class QXmppIbbCloseIq;
+class QXmppIbbDataIq;
+class QXmppIbbOpenIq;
+class QXmppStreamInitiationIq;
+
+class QXmppTransferManager;
+
+class QXmppTransferJob : public QObject
+{
+ Q_OBJECT
+
+public:
+ enum Error
+ {
+ NoError = 0,
+ FileCorruptError,
+ ProtocolError,
+ };
+
+ enum Method
+ {
+ InBandByteStream = 1,
+ SocksByteStream = 2,
+ };
+
+ void accept(QIODevice *output);
+
+ QXmppTransferJob::Error error() const;
+ QString jid() const;
+
+ // XEP-0096 : File transfer
+ QDateTime fileDate() const;
+ QString fileHash() const;
+ QString fileName() const;
+ int fileSize() const;
+
+signals:
+ void error(QXmppTransferJob::Error error);
+ void finished();
+ void progress(qint64 done, qint64 total);
+
+private:
+ QXmppTransferJob(const QString &jid, QXmppTransferManager *manager);
+ void terminate(QXmppTransferJob::Error error);
+
+ int m_done;
+ QXmppTransferJob::Error m_error;
+ QIODevice *m_iodevice;
+ QString m_jid;
+ QString m_sid;
+ int m_methods;
+ QString m_mimeType;
+
+ QDateTime m_fileDate;
+ QString m_fileHash;
+ QString m_fileName;
+ int m_fileSize;
+
+ QString m_requestId;
+ int m_ibbSequence;
+ friend class QXmppTransferManager;
+};
+
+class QXmppTransferManager : public QObject
+{
+ Q_OBJECT
+
+public:
+ QXmppTransferManager(QXmppClient* client);
+ QXmppTransferJob *sendFile(const QString &jid, const QString &fileName);
+
+signals:
+ void fileReceived(QXmppTransferJob *offer);
+
+private slots:
+ void ibbCloseIqReceived(const QXmppIbbCloseIq&);
+ void ibbDataIqReceived(const QXmppIbbDataIq&);
+ void ibbOpenIqReceived(const QXmppIbbOpenIq&);
+ void iqReceived(const QXmppIq&);
+ void streamInitiationIqReceived(const QXmppStreamInitiationIq&);
+
+private:
+ QXmppTransferJob *getJobByRequestId(const QString &jid, const QString &id);
+ QXmppTransferJob *getJobBySid(const QString &jid, const QString &sid);
+ void streamInitiationResultReceived(const QXmppStreamInitiationIq&);
+ void streamInitiationSetReceived(const QXmppStreamInitiationIq&);
+
+ // reference to client object (no ownership)
+ QXmppClient* m_client;
+ QList<QXmppTransferJob*> m_jobs;
+ int m_ibbBlockSize;
+};
+
+#endif
diff --git a/source/source.pro b/source/source.pro
index 46b70925..7d1368a8 100644
--- a/source/source.pro
+++ b/source/source.pro
@@ -33,6 +33,7 @@ HEADERS += QXmppUtils.h \
QXmppStanza.h \
QXmppStream.h \
QXmppStreamInitiationIq.h \
+ QXmppTransferManager.h \
QXmppLogger.h \
QXmppReconnectionManager.h \
QXmppVCardManager.h \
@@ -40,8 +41,6 @@ HEADERS += QXmppUtils.h \
QXmppNonSASLAuth.h \
QXmppInformationRequestResult.h \
QXmppIbbIqs.h \
- QXmppIbbTransferJob.h \
- QXmppIbbTransferManager.h \
xmlrpc.h \
QXmppInvokable.h \
QXmppRpcIq.h \
@@ -68,6 +67,7 @@ SOURCES += QXmppUtils.cpp \
QXmppStanza.cpp \
QXmppStream.cpp \
QXmppStreamInitiationIq.cpp \
+ QXmppTransferManager.cpp \
QXmppLogger.cpp \
QXmppReconnectionManager.cpp \
QXmppVCardManager.cpp \
@@ -75,8 +75,6 @@ SOURCES += QXmppUtils.cpp \
QXmppNonSASLAuth.cpp \
QXmppInformationRequestResult.cpp \
QXmppIbbIqs.cpp \
- QXmppIbbTransferJob.cpp \
- QXmppIbbTransferManager.cpp \
xmlrpc.cpp \
QXmppInvokable.cpp \
QXmppRpcIq.cpp \