14 #include "inbandbytestream.h"
16 #include "bytestreamdatahandler.h"
18 #include "clientbase.h"
29 static const char* typeValues[] =
31 "open",
"data",
"close"
34 InBandBytestream::IBB::IBB(
const std::string& sid,
int blocksize )
35 : StanzaExtension(
ExtIBB ), m_sid ( sid ), m_seq( 0 ), m_blockSize( blocksize ),
40 InBandBytestream::IBB::IBB(
const std::string& sid,
int seq,
const std::string& data )
41 : StanzaExtension(
ExtIBB ), m_sid ( sid ), m_seq( seq ), m_blockSize( 0 ),
42 m_data( data ), m_type( IBBData )
46 InBandBytestream::IBB::IBB(
const std::string& sid )
47 : StanzaExtension(
ExtIBB ), m_sid ( sid ), m_seq( 0 ), m_blockSize( 0 ),
52 InBandBytestream::IBB::IBB(
const Tag* tag )
53 : StanzaExtension(
ExtIBB ), m_type( IBBInvalid )
55 if( !tag || tag->xmlns() != XMLNS_IBB )
58 m_type =
static_cast<IBBType
>( util::lookup( tag->name(), typeValues ) );
59 m_blockSize = atoi( tag->findAttribute(
"block-size" ).c_str() );
60 m_seq = atoi( tag->findAttribute(
"seq" ).c_str() );
61 m_sid = tag->findAttribute(
"sid" );
62 m_data = Base64::decode64( tag->cdata() );
65 InBandBytestream::IBB::~IBB()
69 const std::string& InBandBytestream::IBB::filterString()
const
71 static const std::string filter =
"/iq/open[@xmlns='" +
XMLNS_IBB +
"']"
73 "|/message/data[@xmlns='" +
XMLNS_IBB +
"']"
78 Tag* InBandBytestream::IBB::tag()
const
80 if( m_type == IBBInvalid )
83 Tag* t =
new Tag( util::lookup( m_type, typeValues ) );
84 t->setXmlns( XMLNS_IBB );
85 t->addAttribute(
"sid", m_sid );
86 if( m_type == IBBData )
88 t->setCData( Base64::encode64( m_data ) );
89 t->addAttribute(
"seq", m_seq );
91 else if( m_type == IBBOpen )
92 t->addAttribute(
"block-size", m_blockSize );
99 InBandBytestream::InBandBytestream( ClientBase* clientbase, LogSink& logInstance,
const JID& initiator,
100 const JID& target,
const std::string& sid )
101 : Bytestream( Bytestream::IBB, logInstance, initiator, target, sid ),
102 m_clientbase( clientbase ), m_blockSize( 4096 ), m_sequence( -1 ), m_lastChunkReceived( -1 )
106 m_clientbase->registerStanzaExtension(
new IBB() );
107 m_clientbase->registerIqHandler(
this, ExtIBB );
108 m_clientbase->registerMessageHandler(
this );
114 InBandBytestream::~InBandBytestream()
123 m_clientbase->removeMessageHandler(
this );
124 m_clientbase->removeIqHandler(
this,
ExtIBB );
125 m_clientbase->removeIDHandler(
this );
129 bool InBandBytestream::connect()
134 if( m_target == m_clientbase->jid() )
137 const std::string&
id = m_clientbase->getID();
138 IQ iq( IQ::Set, m_target,
id );
140 m_clientbase->send( iq,
this, IBBOpen );
144 void InBandBytestream::handleIqID(
const IQ& iq,
int context )
149 if( context == IBBOpen && m_handler )
151 m_handler->handleBytestreamOpen(
this );
154 else if( context == IBBData && m_handler )
156 m_handler->handleBytestreamDataAck(
this );
167 bool InBandBytestream::handleIq(
const IQ& iq )
170 if( !i || !m_handler || iq.
subtype() != IQ::Set || i->sid() != this->sid() )
175 if( i->type() == IBBOpen )
177 returnResult( iq.
from(), iq.
id() );
179 m_handler->handleBytestreamOpen(
this );
185 if( i->type() == IBBClose )
187 returnResult( iq.
from(), iq.
id() );
192 if( ++m_lastChunkReceived != i->seq() )
199 if( m_lastChunkReceived == 65535 )
200 m_lastChunkReceived = -1;
202 if( i->data().empty() )
209 returnResult( iq.
from(), iq.
id() );
210 m_handler->handleBytestreamData(
this, i->data() );
217 if( msg.
from() != m_target || !m_handler )
227 if( m_lastChunkReceived != i->seq() )
233 if( i->data().empty() )
239 m_handler->handleBytestreamData(
this, i->data() );
240 m_lastChunkReceived++;
243 void InBandBytestream::returnResult(
const JID& to,
const std::string&
id )
245 IQ iq( IQ::Result, to,
id );
246 m_clientbase->send( iq );
249 void InBandBytestream::returnError(
const JID& to,
const std::string&
id, StanzaErrorType type, StanzaError error )
251 IQ iq( IQ::Error, to,
id );
252 iq.addExtension(
new Error( type, error ) );
253 m_clientbase->send( iq );
256 bool InBandBytestream::send(
const std::string& data )
258 if( !m_open || !m_clientbase )
262 size_t len = data.length();
265 const std::string&
id = m_clientbase->getID();
266 IQ iq( IQ::Set, m_clientbase->jid() == m_target ? m_initiator : m_target,
id );
267 iq.
addExtension(
new IBB( m_sid, ++m_sequence, data.substr( pos, m_blockSize ) ) );
268 m_clientbase->send( iq,
this, IBBData );
271 if( m_sequence == 65535 )
279 void InBandBytestream::closed()
287 m_handler->handleBytestreamClose(
this );
290 void InBandBytestream::close()
297 const std::string&
id = m_clientbase->getID();
298 IQ iq( IQ::Set, m_target,
id );
300 m_clientbase->send( iq,
this, IBBClose );
303 m_handler->handleBytestreamClose(
this );
An abstraction of an IQ stanza.
An abstraction of a message session between any two entities.
An abstraction of a message stanza.
void addExtension(const StanzaExtension *se)
const std::string & id() const
const StanzaExtension * findExtension(int type) const
The namespace for the gloox library.
const std::string XMLNS_IBB
@ StanzaErrorItemNotFound