From 10c093a617929db5c6b201dbf03d6070b12b36b4 Mon Sep 17 00:00:00 2001 From: Manjeet Dahiya Date: Tue, 27 Oct 2009 12:04:03 +0000 Subject: Issue 15: Implement XEP-0047 --- source/QXmppIbbTransferJob.cpp | 230 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 230 insertions(+) create mode 100644 source/QXmppIbbTransferJob.cpp (limited to 'source/QXmppIbbTransferJob.cpp') diff --git a/source/QXmppIbbTransferJob.cpp b/source/QXmppIbbTransferJob.cpp new file mode 100644 index 00000000..4835596a --- /dev/null +++ b/source/QXmppIbbTransferJob.cpp @@ -0,0 +1,230 @@ +#include "QXmppIbbTransferJob.h" + +#include +#include +#include "QXmppIbbIqs.h" +#include "QXmppDataIq.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 QXmppDataIq &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++; + QXmppDataIq 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 ); + } +} -- cgit v1.2.3