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