00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "inbandbytestreammanager.h"
00015 #include "inbandbytestreamhandler.h"
00016 #include "inbandbytestream.h"
00017 #include "clientbase.h"
00018
00019 namespace gloox
00020 {
00021
00022 InBandBytestreamManager::InBandBytestreamManager( ClientBase *parent, Disco *disco )
00023 : m_parent( parent ), m_inbandBytestreamHandler( 0 ), m_syncInbandBytestreams( true ),
00024 m_blockSize( 4096 )
00025 {
00026 if( m_parent )
00027 m_parent->registerIqHandler( this, XMLNS_IBB );
00028
00029 if( disco )
00030 disco->addFeature( XMLNS_IBB );
00031 }
00032
00033 InBandBytestreamManager::~InBandBytestreamManager()
00034 {
00035 if( m_parent )
00036 m_parent->removeIqHandler( XMLNS_IBB );
00037
00038 IBBMap::iterator it = m_ibbMap.begin();
00039 for( ; it != m_ibbMap.end(); ++it )
00040 {
00041 delete (*it).second;
00042 m_ibbMap.erase( it );
00043 }
00044 }
00045
00046 bool InBandBytestreamManager::requestInBandBytestream( const JID& to, InBandBytestreamHandler *ibbh )
00047 {
00048 if( !m_parent || !ibbh )
00049 return false;
00050
00051 const std::string sid = m_parent->getID();
00052 const std::string id = m_parent->getID();
00053 Tag *iq = new Tag( "iq" );
00054 iq->addAttribute( "type", "set" );
00055 iq->addAttribute( "to", to.full() );
00056 iq->addAttribute( "id", id );
00057 Tag *o = new Tag( iq, "open" );
00058 o->addAttribute( "sid", sid );
00059 o->addAttribute( "block-size", m_blockSize );
00060 o->addAttribute( "xmlns", XMLNS_IBB );
00061
00062 TrackItem item;
00063 item.sid = sid;
00064 item.ibbh = ibbh;
00065 m_trackMap[id] = item;
00066 m_parent->trackID( this, id, IBBOpenStream );
00067 m_parent->send( iq );
00068
00069 return true;
00070 }
00071
00072 bool InBandBytestreamManager::handleIq( Stanza *stanza )
00073 {
00074 Tag *o = 0;
00075 if( ( stanza->subtype() == StanzaIqSet ) &&
00076 ( ( o = stanza->findChild( "open", "xmlns", XMLNS_IBB ) ) != 0 ) )
00077 {
00078 InBandBytestream *ibb = new InBandBytestream( 0, m_parent );
00079 const std::string sid = o->findAttribute( "sid" );
00080 ibb->setSid( sid );
00081
00082 if( !m_inbandBytestreamHandler )
00083 rejectInBandBytestream( ibb, stanza->from(), stanza->id() );
00084
00085 if( !m_syncInbandBytestreams )
00086 {
00087 AsyncIBBItem item;
00088 item.ibb = ibb;
00089 item.from = stanza->from();
00090 item.id = stanza->id();
00091 m_asyncTrackMap[sid] = item;
00092 }
00093
00094 bool t = m_inbandBytestreamHandler->handleIncomingInBandBytestream( stanza->from(), ibb );
00095 if( m_syncInbandBytestreams && t )
00096 {
00097 acceptInBandBytestream( ibb, stanza->from(), stanza->id() );
00098 }
00099 else if( m_syncInbandBytestreams && !t )
00100 {
00101 rejectInBandBytestream( ibb, stanza->from(), stanza->id() );
00102 }
00103 }
00104 else if( ( stanza->subtype() == StanzaIqSet ) &&
00105 ( ( o = stanza->findChild( "close", "xmlns", XMLNS_IBB ) ) != 0 ) &&
00106 o->hasAttribute( "sid" ) )
00107 {
00108 IBBMap::iterator it = m_ibbMap.find( o->findAttribute( "sid" ) );
00109 if( it != m_ibbMap.end() )
00110 {
00111 (*it).second->closed();
00112
00113 Tag *iq = new Tag( "iq" );
00114 iq->addAttribute( "type", "result" );
00115 iq->addAttribute( "to", stanza->from().full() );
00116 iq->addAttribute( "id", stanza->id() );
00117
00118 m_parent->send( iq );
00119 }
00120 }
00121 else
00122 {
00123 return false;
00124 }
00125
00126 return true;
00127 }
00128
00129 void InBandBytestreamManager::acceptInBandBytestream( InBandBytestream *ibb )
00130 {
00131 if( m_syncInbandBytestreams )
00132 return;
00133
00134 AsyncTrackMap::iterator it = m_asyncTrackMap.find( ibb->sid() );
00135 if( it != m_asyncTrackMap.end() )
00136 {
00137 acceptInBandBytestream( ibb, (*it).second.from, (*it).second.id );
00138 m_asyncTrackMap.erase( it );
00139 }
00140 }
00141
00142 void InBandBytestreamManager::rejectInBandBytestream( InBandBytestream *ibb )
00143 {
00144 if( m_syncInbandBytestreams )
00145 return;
00146
00147 AsyncTrackMap::iterator it = m_asyncTrackMap.find( ibb->sid() );
00148 if( it != m_asyncTrackMap.end() )
00149 {
00150 rejectInBandBytestream( ibb, (*it).second.from, (*it).second.id );
00151 m_asyncTrackMap.erase( it );
00152 }
00153 }
00154
00155 void InBandBytestreamManager::acceptInBandBytestream( InBandBytestream *ibb,
00156 const JID& from, const std::string& id )
00157 {
00158 m_ibbMap[ibb->sid()] = ibb;
00159 Tag *iq = new Tag( "iq" );
00160 iq->addAttribute( "type", "result" );
00161 iq->addAttribute( "to", from.full() );
00162 iq->addAttribute( "id", id );
00163 m_parent->send( iq );
00164 }
00165
00166 void InBandBytestreamManager::rejectInBandBytestream( InBandBytestream *ibb,
00167 const JID& from, const std::string& id )
00168 {
00169 delete ibb;
00170 Tag *iq = new Tag( "iq" );
00171 iq->addAttribute( "type", "error" );
00172 iq->addAttribute( "to", from.full() );
00173 iq->addAttribute( "id", id );
00174 Tag *e = new Tag( iq, "error" );
00175 e->addAttribute( "code", "501" );
00176 e->addAttribute( "type", "cancel" );
00177 Tag *f = new Tag( e, "feature-not-implemented" );
00178 f->addAttribute( "xmlns", XMLNS_XMPP_STANZAS );
00179 m_parent->send( iq );
00180 }
00181
00182 bool InBandBytestreamManager::handleIqID( Stanza *stanza, int context )
00183 {
00184 switch( context )
00185 {
00186 case IBBOpenStream:
00187 {
00188 TrackMap::iterator it = m_trackMap.find( stanza->id() );
00189 if( it != m_trackMap.end() )
00190 {
00191 switch( stanza->subtype() )
00192 {
00193 case StanzaIqResult:
00194 {
00195 InBandBytestream *ibb = new InBandBytestream( 0, m_parent );
00196 ibb->setSid( (*it).second.sid );
00197 ibb->setBlockSize( m_blockSize );
00198 m_ibbMap[(*it).second.sid] = ibb;
00199 InBandBytestreamHandler *t = (*it).second.ibbh;
00200 m_trackMap.erase( it );
00201 t->handleOutgoingInBandBytestream( stanza->from(), ibb );
00202 break;
00203 }
00204 case StanzaIqError:
00205 (*it).second.ibbh->handleInBandBytestreamError( stanza->from(), stanza->error() );
00206 break;
00207 default:
00208 break;
00209 }
00210 }
00211 break;
00212 }
00213 default:
00214 break;
00215 }
00216
00217 return false;
00218 }
00219
00220 bool InBandBytestreamManager::dispose( InBandBytestream *ibb )
00221 {
00222 IBBMap::iterator it = m_ibbMap.find( ibb->sid() );
00223 if( it != m_ibbMap.end() )
00224 {
00225 delete ibb;
00226 m_ibbMap.erase( it );
00227 return true;
00228 }
00229
00230 return false;
00231 }
00232
00233 void InBandBytestreamManager::registerInBandBytestreamHandler( InBandBytestreamHandler *ibbh,
00234 bool sync )
00235 {
00236 m_inbandBytestreamHandler = ibbh;
00237 m_syncInbandBytestreams = sync;
00238 }
00239
00240 void InBandBytestreamManager::removeInBandBytestreamHandler()
00241 {
00242 m_inbandBytestreamHandler = 0;
00243 }
00244
00245 }