00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "socks5bytestreammanager.h"
00015 #include "socks5bytestreamhandler.h"
00016 #include "socks5bytestreamserver.h"
00017 #include "socks5bytestream.h"
00018 #include "clientbase.h"
00019 #include "disco.h"
00020 #include "connectionbase.h"
00021 #include "sha.h"
00022
00023 #include <cstdlib>
00024
00025 namespace gloox
00026 {
00027
00028 SOCKS5BytestreamManager::SOCKS5BytestreamManager( ClientBase *parent, SOCKS5BytestreamHandler* s5bh )
00029 : m_parent( parent ), m_socks5BytestreamHandler( s5bh )
00030 {
00031 if( m_parent )
00032 m_parent->registerIqHandler( this, XMLNS_BYTESTREAMS );
00033 }
00034
00035 SOCKS5BytestreamManager::~SOCKS5BytestreamManager()
00036 {
00037 if( m_parent )
00038 {
00039 m_parent->removeIqHandler( XMLNS_BYTESTREAMS );
00040 m_parent->removeIDHandler( this );
00041 }
00042
00043 S5BMap::iterator it = m_s5bMap.begin();
00044 for( ; it != m_s5bMap.end(); ++it )
00045 {
00046 delete (*it).second;
00047 (*it).second = 0;
00048 }
00049 }
00050
00051 void SOCKS5BytestreamManager::addStreamHost( const JID& jid, const std::string& host, int port )
00052 {
00053 StreamHost sh;
00054 sh.jid = jid;
00055 sh.host = host;
00056 sh.port = port;
00057 m_hosts.push_back( sh );
00058 }
00059
00060 bool SOCKS5BytestreamManager::requestSOCKS5Bytestream( const JID& to, S5BMode ,
00061 const std::string& sid )
00062 {
00063 if( !m_parent )
00064 return false;
00065
00066 if( m_hosts.empty() )
00067 {
00068 m_parent->logInstance().log( LogLevelWarning, LogAreaClassS5BManager,
00069 "No stream hosts set, cannot request bytestream." );
00070 return false;
00071 }
00072
00073 const std::string& msid = sid.empty() ? m_parent->getID() : sid;
00074 const std::string& id = m_parent->getID();
00075 Tag *iq = new Tag( "iq" );
00076 iq->addAttribute( "type", "set" );
00077 iq->addAttribute( "to", to.full() );
00078 iq->addAttribute( "id", id );
00079 Tag *q = new Tag( iq, "query", "xmlns", XMLNS_BYTESTREAMS );
00080 q->addAttribute( "sid", msid );
00081 q->addAttribute( "mode", "tcp" );
00082
00083 StreamHostList::const_iterator it = m_hosts.begin();
00084 for( ; it != m_hosts.end(); ++it )
00085 {
00086 Tag* s = new Tag( q, "streamhost", "jid", (*it).jid.full() );
00087 s->addAttribute( "host", (*it).host );
00088 s->addAttribute( "port", (*it).port );
00089 }
00090
00091 if( m_server )
00092 {
00093 SHA sha;
00094 sha.feed( msid );
00095 sha.feed( m_parent->jid().full() );
00096 sha.feed( to.full() );
00097 m_server->registerHash( sha.hex() );
00098 }
00099
00100 AsyncS5BItem asi;
00101 asi.sHosts = m_hosts;
00102 asi.id = id;
00103 asi.from = to;
00104 asi.incoming = false;
00105 m_asyncTrackMap[msid] = asi;
00106
00107 m_trackMap[id] = msid;
00108 m_parent->trackID( this, id, S5BOpenStream );
00109 m_parent->send( iq );
00110
00111 return true;
00112 }
00113
00114 void SOCKS5BytestreamManager::acknowledgeStreamHost( bool success, const JID& jid,
00115 const std::string& sid )
00116 {
00117 AsyncTrackMap::const_iterator it = m_asyncTrackMap.find( sid );
00118 if( it == m_asyncTrackMap.end() || !m_parent )
00119 return;
00120
00121 Tag *iq = new Tag( "iq" );
00122
00123 if( (*it).second.incoming )
00124 {
00125 iq->addAttribute( "to", (*it).second.from.full() );
00126 iq->addAttribute( "id", (*it).second.id );
00127
00128 if( success )
00129 {
00130 iq->addAttribute( "type", "result" );
00131 Tag* q = new Tag( iq, "query", "xmlns", XMLNS_BYTESTREAMS );
00132 new Tag( q, "streamhost-used", "jid", jid.full() );
00133 }
00134 else
00135 {
00136 iq->addAttribute( "type", "error" );
00137 Tag* e = new Tag( iq, "error" );
00138 e->addAttribute( "code", "404" );
00139 e->addAttribute( "type", "cancel" );
00140 new Tag( e, "item-not-found", "xmlns", XMLNS_XMPP_STANZAS );
00141 }
00142 }
00143 else
00144 {
00145 if( success )
00146 {
00147 const std::string& id = m_parent->getID();
00148 iq->addAttribute( "to", jid.full() );
00149 iq->addAttribute( "id", id );
00150 iq->addAttribute( "type", "set" );
00151 Tag* q = new Tag( iq, "query", "xmlns", XMLNS_BYTESTREAMS );
00152 q->addAttribute( "sid", sid );
00153 new Tag( q, "activate", (*it).second.from.full() );
00154
00155 m_trackMap[id] = sid;
00156 m_parent->trackID( this, id, S5BActivateStream );
00157 }
00158 }
00159
00160 m_parent->send( iq );
00161 }
00162
00163 bool SOCKS5BytestreamManager::handleIq( Stanza *stanza )
00164 {
00165 Tag* q = stanza->findChild( "query", "xmlns", XMLNS_BYTESTREAMS );
00166 if( !q || !m_socks5BytestreamHandler )
00167 return false;
00168
00169 if( m_trackMap.find( stanza->id() ) != m_trackMap.end() )
00170 return false;
00171
00172 switch( stanza->subtype() )
00173 {
00174 case StanzaIqSet:
00175 {
00176 const std::string& sid = q->findAttribute( "sid" );
00177 const std::string& mode = q->findAttribute( "mode" );
00178 if( haveStream( stanza->from() ) || sid.empty() || mode == "udp" )
00179 {
00180 rejectSOCKS5Bytestream( stanza->from(), stanza->id(), StanzaErrorNotAcceptable );
00181 return true;
00182 }
00183 AsyncS5BItem asi;
00184 Tag::TagList& l = q->children();
00185 Tag::TagList::const_iterator it = l.begin();
00186 for( ; it != l.end(); ++it )
00187 {
00188 if( (*it)->name() == "streamhost" && (*it)->hasAttribute( "jid" )
00189 && (*it)->hasAttribute( "host" ) && (*it)->hasAttribute( "port" ) )
00190 {
00191 StreamHost sh;
00192 sh.jid = (*it)->findAttribute( "jid" );
00193 sh.host = (*it)->findAttribute( "host" );
00194 sh.port = atoi( (*it)->findAttribute( "port" ).c_str() );
00195 asi.sHosts.push_back( sh );
00196 }
00197 }
00198 asi.id = stanza->id();
00199 asi.from = stanza->from();
00200 asi.incoming = true;
00201 m_asyncTrackMap[sid] = asi;
00202 m_socks5BytestreamHandler->handleIncomingSOCKS5BytestreamRequest( sid, stanza->from() );
00203 break;
00204 }
00205 case StanzaIqError:
00206 m_socks5BytestreamHandler->handleSOCKS5BytestreamError( stanza, std::string() );
00207 break;
00208 default:
00209 break;
00210 }
00211
00212 return true;
00213 }
00214
00215 const StreamHost* SOCKS5BytestreamManager::findProxy( const JID& from, const std::string& hostjid,
00216 const std::string& sid )
00217 {
00218 AsyncTrackMap::const_iterator it = m_asyncTrackMap.find( sid );
00219 if( it == m_asyncTrackMap.end() )
00220 return 0;
00221
00222 if( (*it).second.from == from )
00223 {
00224 StreamHostList::const_iterator it2 = (*it).second.sHosts.begin();
00225 for( ; it2 != (*it).second.sHosts.end(); ++it2 )
00226 {
00227 if( (*it2).jid == hostjid )
00228 {
00229 return &(*it2);
00230 }
00231 }
00232 }
00233
00234 return 0;
00235 }
00236
00237 bool SOCKS5BytestreamManager::haveStream( const JID& from )
00238 {
00239 S5BMap::const_iterator it = m_s5bMap.begin();
00240 for( ; it != m_s5bMap.end(); ++it )
00241 {
00242 if( (*it).second && (*it).second->target() == from )
00243 return true;
00244 }
00245 return false;
00246 }
00247
00248 void SOCKS5BytestreamManager::acceptSOCKS5Bytestream( const std::string& sid )
00249 {
00250 AsyncTrackMap::iterator it = m_asyncTrackMap.find( sid );
00251 if( it == m_asyncTrackMap.end() || !m_socks5BytestreamHandler )
00252 return;
00253
00254 SOCKS5Bytestream* s5b = new SOCKS5Bytestream( this, m_parent->connectionImpl()->newInstance(),
00255 m_parent->logInstance(),
00256 (*it).second.from, m_parent->jid(), sid );
00257 s5b->setStreamHosts( (*it).second.sHosts );
00258 m_s5bMap[sid] = s5b;
00259 m_socks5BytestreamHandler->handleIncomingSOCKS5Bytestream( s5b );
00260 }
00261
00262 void SOCKS5BytestreamManager::rejectSOCKS5Bytestream( const std::string& sid )
00263 {
00264 AsyncTrackMap::iterator it = m_asyncTrackMap.find( sid );
00265 if( it != m_asyncTrackMap.end() )
00266 {
00267 rejectSOCKS5Bytestream( (*it).second.from, (*it).second.id, StanzaErrorNotAcceptable );
00268 m_asyncTrackMap.erase( it );
00269 }
00270 }
00271
00272 void SOCKS5BytestreamManager::rejectSOCKS5Bytestream( const JID& from, const std::string& id,
00273 StanzaError reason )
00274 {
00275 Tag *iq = new Tag( "iq" );
00276 iq->addAttribute( "type", "error" );
00277 iq->addAttribute( "to", from.full() );
00278 iq->addAttribute( "id", id );
00279 Tag *e = new Tag( iq, "error" );
00280 switch( reason )
00281 {
00282 case StanzaErrorForbidden:
00283 {
00284 new Tag( iq, "query", "xmlns", XMLNS_BYTESTREAMS );
00285 e->addAttribute( "code", "403" );
00286 e->addAttribute( "type", "auth" );
00287 Tag *f = new Tag( e, "forbidden" );
00288 f->addAttribute( "xmlns", XMLNS_XMPP_STANZAS );
00289 break;
00290 }
00291 case StanzaErrorFeatureNotImplemented:
00292 {
00293 e->addAttribute( "code", "404" );
00294 e->addAttribute( "type", "cancel" );
00295 Tag *f = new Tag( e, "item-not-found" );
00296 f->addAttribute( "xmlns", XMLNS_XMPP_STANZAS );
00297 break;
00298 }
00299 case StanzaErrorNotAllowed:
00300 {
00301 new Tag( iq, "query", "xmlns", XMLNS_BYTESTREAMS );
00302 e->addAttribute( "code", "405" );
00303 e->addAttribute( "type", "cancel" );
00304 Tag *f = new Tag( e, "not-allowed" );
00305 f->addAttribute( "xmlns", XMLNS_XMPP_STANZAS );
00306 break;
00307 }
00308 case StanzaErrorNotAcceptable:
00309 default:
00310 {
00311 e->addAttribute( "code", "406" );
00312 e->addAttribute( "type", "auth" );
00313 Tag *f = new Tag( e, "not-acceptable" );
00314 f->addAttribute( "xmlns", XMLNS_XMPP_STANZAS );
00315 break;
00316 }
00317 }
00318 m_parent->send( iq );
00319 }
00320
00321 bool SOCKS5BytestreamManager::handleIqID( Stanza *stanza, int context )
00322 {
00323 StringMap::iterator it = m_trackMap.find( stanza->id() );
00324 if( it == m_trackMap.end() )
00325 return false;
00326
00327 switch( context )
00328 {
00329 case S5BOpenStream:
00330 {
00331 switch( stanza->subtype() )
00332 {
00333 case StanzaIqResult:
00334 {
00335 Tag* q = stanza->findChild( "query", "xmlns", XMLNS_BYTESTREAMS );
00336 if( !q || !m_socks5BytestreamHandler )
00337 return false;
00338
00339 Tag* s = q->findChild( "streamhost-used" );
00340 if( !s || !s->hasAttribute( "jid" ) )
00341 return false;
00342
00343 const std::string & proxy = s->findAttribute( "jid" );
00344 const StreamHost* sh = findProxy( stanza->from(), proxy, (*it).second );
00345 if( sh )
00346 {
00347 SOCKS5Bytestream* s5b = 0;
00348 bool selfProxy = ( proxy == m_parent->jid().full() && m_server );
00349 if( selfProxy )
00350 {
00351 SHA sha;
00352 sha.feed( (*it).second );
00353 sha.feed( m_parent->jid().full() );
00354 sha.feed( stanza->from().full() );
00355 s5b = new SOCKS5Bytestream( this, m_server->getConnection( sha.hex() ),
00356 m_parent->logInstance(),
00357 m_parent->jid(), stanza->from(),
00358 (*it).second );
00359 }
00360 else
00361 {
00362 s5b = new SOCKS5Bytestream( this, m_parent->connectionImpl()->newInstance(),
00363 m_parent->logInstance(),
00364 m_parent->jid(), stanza->from(),
00365 (*it).second );
00366 StreamHostList shl;
00367 shl.push_back( *sh );
00368 s5b->setStreamHosts( shl );
00369 }
00370 m_s5bMap[(*it).second] = s5b;
00371 m_socks5BytestreamHandler->handleOutgoingSOCKS5Bytestream( s5b );
00372 if( selfProxy )
00373 s5b->activate();
00374 }
00375 break;
00376 }
00377 case StanzaIqError:
00378 m_socks5BytestreamHandler->handleSOCKS5BytestreamError( stanza, (*it).second );
00379 break;
00380 default:
00381 break;
00382 }
00383 break;
00384 }
00385 case S5BActivateStream:
00386 {
00387 switch( stanza->subtype() )
00388 {
00389 case StanzaIqResult:
00390 {
00391 S5BMap::const_iterator it5 = m_s5bMap.find( (*it).second );
00392 if( it5 != m_s5bMap.end() )
00393 (*it5).second->activate();
00394 break;
00395 }
00396 case StanzaIqError:
00397 m_socks5BytestreamHandler->handleSOCKS5BytestreamError( stanza, (*it).second );
00398 break;
00399 default:
00400 break;
00401 }
00402 break;
00403 }
00404 default:
00405 break;
00406 }
00407 m_trackMap.erase( it );
00408
00409 return false;
00410 }
00411
00412 bool SOCKS5BytestreamManager::dispose( SOCKS5Bytestream* s5b )
00413 {
00414 S5BMap::iterator it = m_s5bMap.find( s5b->sid() );
00415 if( it != m_s5bMap.end() )
00416 {
00417 delete s5b;
00418 m_s5bMap.erase( it );
00419 return true;
00420 }
00421
00422 return false;
00423 }
00424
00425 }