00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #ifdef WIN32
00016 #include "../config.h.win"
00017 #else
00018 #include "config.h"
00019 #endif
00020
00021 #include "clientbase.h"
00022 #include "connection.h"
00023 #include "parser.h"
00024 #include "tag.h"
00025 #include "stanza.h"
00026
00027 #include <iksemel.h>
00028
00029 #include <string>
00030 #include <map>
00031 #include <list>
00032 #include <sstream>
00033
00034 namespace gloox
00035 {
00036
00037 ClientBase::ClientBase( const std::string& ns, const std::string& server, int port )
00038 : m_connection( 0 ), m_namespace( ns ), m_xmllang( "en" ), m_server( server ),
00039 m_authed( false ), m_sasl( true ), m_tls( true ), m_port( port ), m_parser( 0 ),
00040 m_authError( AUTH_ERROR_UNDEFINED ), m_streamError( ERROR_UNDEFINED ),
00041 m_streamErrorAppCondition( 0 ), m_idCount( 0 )
00042 {
00043 }
00044
00045 ClientBase::ClientBase( const std::string& ns, const std::string& password,
00046 const std::string& server, int port )
00047 : m_connection( 0 ), m_namespace( ns ), m_password( password ), m_xmllang( "en" ), m_server( server ),
00048 m_authed( false ), m_sasl( true ), m_tls( true ), m_port( port ), m_parser( 0 ),
00049 m_authError( AUTH_ERROR_UNDEFINED ), m_streamError( ERROR_UNDEFINED ),
00050 m_streamErrorAppCondition( 0 ), m_idCount( 0 )
00051 {
00052 }
00053
00054 ClientBase::~ClientBase()
00055 {
00056 delete m_connection;
00057 delete m_parser;
00058 }
00059
00060 ConnectionError ClientBase::recv( int timeout )
00061 {
00062 ConnectionError e = m_connection->recv( timeout );
00063 if( e != CONN_OK )
00064 notifyOnDisconnect( e );
00065 return e;
00066 }
00067
00068 bool ClientBase::connect( bool block )
00069 {
00070 if( m_server.empty() )
00071 return false;
00072
00073 if( !m_parser )
00074 m_parser = new Parser( this );
00075
00076 if( !m_connection )
00077 m_connection = new Connection( m_parser, m_server, m_port );
00078
00079 #ifdef HAVE_TLS
00080 m_connection->setCACerts( m_cacerts );
00081 #endif
00082 int ret = m_connection->connect();
00083 if( ret == STATE_CONNECTED )
00084 {
00085 header();
00086 if( block )
00087 {
00088 ConnectionError e = m_connection->receive();
00089 notifyOnDisconnect( e );
00090 return false;
00091 }
00092 else
00093 return true;
00094 }
00095 else
00096 return false;
00097 }
00098
00099 void ClientBase::filter( NodeType type, Stanza *stanza )
00100 {
00101 if( stanza )
00102 log( stanza->xml(), true );
00103
00104 switch( type )
00105 {
00106 case NODE_STREAM_START:
00107 {
00108 const std::string version = stanza->findAttribute( "version" );
00109 if( !version.empty() )
00110 {
00111 if( !checkStreamVersion( version ) )
00112 disconnect( CONN_STREAM_ERROR );
00113 }
00114 else
00115 {
00116 printf( "This server is not XMPP-compliant (it does not send a 'version' attribute). Please try another one.\n" );
00117 disconnect( CONN_STREAM_ERROR );
00118 }
00119
00120 m_sid = stanza->findAttribute( "id" );
00121 handleStartNode();
00122 break;
00123 }
00124 case NODE_STREAM_CHILD:
00125 if( !handleNormalNode( stanza ) )
00126 {
00127 switch( stanza->type() )
00128 {
00129 case STANZA_IQ:
00130 notifyIqHandlers( stanza );
00131 break;
00132 case STANZA_PRESENCE:
00133 notifyPresenceHandlers( stanza );
00134 break;
00135 case STANZA_S10N:
00136 notifySubscriptionHandlers( stanza );
00137 break;
00138 case STANZA_MESSAGE:
00139 notifyMessageHandlers( stanza );
00140 break;
00141 default:
00142 notifyTagHandlers( stanza );
00143 break;
00144 }
00145 }
00146 break;
00147 case NODE_STREAM_ERROR:
00148 handleStreamError( stanza );
00149 break;
00150 case NODE_STREAM_CLOSE:
00151 #ifdef DEBUG
00152 printf( "stream closed\n" );
00153 #endif
00154 disconnect( CONN_STREAM_CLOSED );
00155 break;
00156 }
00157 }
00158
00159 void ClientBase::disconnect()
00160 {
00161 disconnect( CONN_USER_DISCONNECTED );
00162 }
00163
00164 void ClientBase::disconnect( ConnectionError reason )
00165 {
00166 if( m_connection )
00167 {
00168 if( reason == CONN_USER_DISCONNECTED )
00169 m_streamError = ERROR_UNDEFINED;
00170 m_connection->disconnect( reason );
00171 }
00172 }
00173
00174 void ClientBase::header()
00175 {
00176 std::string xml = "<?xml version='1.0' ?>";
00177 xml += "<stream:stream to='" + m_jid.server()+ "' xmlns='" + m_namespace + "' ";
00178 xml += "xmlns:stream='http://etherx.jabber.org/streams' xml:lang='" + m_xmllang + "' ";
00179 xml += "version='";
00180 xml += XMPP_STREAM_VERSION_MAJOR;
00181 xml += ".";
00182 xml += XMPP_STREAM_VERSION_MINOR;
00183 xml += "'>";
00184 send( xml );
00185 }
00186
00187 bool ClientBase::hasTls()
00188 {
00189 #ifdef HAVE_TLS
00190 return true;
00191 #else
00192 return false;
00193 #endif
00194 }
00195
00196 #ifdef HAVE_TLS
00197 void ClientBase::startTls()
00198 {
00199 Tag *start = new Tag( "starttls" );
00200 start->addAttrib( "xmlns", XMLNS_STREAM_TLS );
00201 send( start );
00202 }
00203 #endif
00204
00205 void ClientBase::startSASL( SaslMechanisms type )
00206 {
00207 Tag *a = new Tag( "auth" );
00208 a->addAttrib( "xmlns", XMLNS_STREAM_SASL );
00209
00210 switch( type )
00211 {
00212 case SASL_DIGEST_MD5:
00213 a->addAttrib( "mechanism", "DIGEST-MD5" );
00214 break;
00215 case SASL_PLAIN:
00216 {
00217 a->addAttrib( "mechanism", "PLAIN" );
00218 int len = m_jid.username().length() + m_password.length() + 2;
00219 char *tmp = (char*)iks_malloc( len + 80 );
00220 char *result;
00221 sprintf( tmp, "%c%s%c%s", 0, m_jid.username().c_str(), 0, m_password.c_str() );
00222 result = iks_base64_encode( tmp, len );
00223
00224 a->setCData( result );
00225 iks_free( result );
00226 iks_free( tmp );
00227 break;
00228 }
00229 case SASL_ANONYMOUS:
00230 a->addAttrib( "mechanism", "ANONYMOUS" );
00231 a->setCData( getID() );
00232 break;
00233 }
00234
00235 send( a );
00236 }
00237
00238 void ClientBase::processSASLChallenge( const std::string& challenge )
00239 {
00240 const int CNONCE_LEN = 4;
00241 Tag *t;
00242 std::string decoded, nonce, realm, response;
00243 char *b = iks_base64_decode( challenge.c_str() );
00244 if( b )
00245 decoded = b;
00246 else
00247 return;
00248
00249 if( decoded.substr( 0, 7 ) == "rspauth" )
00250 {
00251 t = new Tag( "response" );
00252 }
00253 else
00254 {
00255 char cnonce[CNONCE_LEN*8 + 1];
00256 unsigned char a1_h[16];
00257 char a1[33], a2[33], response_value[33];
00258 char *response_coded;
00259 iksmd5 *md5;
00260 int i;
00261
00262 unsigned int r_pos = decoded.find( "realm=" );
00263 if( r_pos != std::string::npos )
00264 {
00265 unsigned int r_end = decoded.find( "\"", r_pos + 7 );
00266 realm = decoded.substr( r_pos + 7, r_end - (r_pos + 7 ) );
00267 }
00268 else
00269 realm = m_jid.server();
00270
00271 unsigned int n_pos = decoded.find( "nonce=" );
00272 if( n_pos != std::string::npos )
00273 {
00274 unsigned int n_end = decoded.find( "\"", n_pos + 7 );
00275 while( decoded.substr( n_end-1, 1 ) == "\\" )
00276 n_end = decoded.find( "\"", n_end + 1 );
00277 nonce = decoded.substr( n_pos + 7, n_end - ( n_pos + 7 ) );
00278 }
00279 else
00280 {
00281 iks_free( b );
00282 return;
00283 }
00284
00285 for( i=0; i<CNONCE_LEN; ++i )
00286 sprintf( cnonce + i*8, "%08x", rand() );
00287
00288 md5 = iks_md5_new();
00289 iks_md5_hash( md5, (const unsigned char*)m_jid.username().c_str(), m_jid.username().length(), 0 );
00290 iks_md5_hash( md5, (const unsigned char*)":", 1, 0 );
00291 iks_md5_hash( md5, (const unsigned char*)realm.c_str(), realm.length(), 0 );
00292 iks_md5_hash( md5, (const unsigned char*)":", 1, 0 );
00293 iks_md5_hash( md5, (const unsigned char*)m_password.c_str(), m_password.length(), 1 );
00294 iks_md5_digest( md5, a1_h );
00295 iks_md5_reset( md5 );
00296 iks_md5_hash( md5, a1_h, 16, 0 );
00297 iks_md5_hash( md5, (const unsigned char*)":", 1, 0 );
00298 iks_md5_hash( md5, (const unsigned char*)nonce.c_str(), nonce.length(), 0 );
00299 iks_md5_hash( md5, (const unsigned char*)":", 1, 0 );
00300 iks_md5_hash( md5, (const unsigned char*)cnonce, iks_strlen( cnonce ), 1 );
00301 iks_md5_print( md5, a1 );
00302 iks_md5_reset( md5 );
00303 iks_md5_hash( md5, (const unsigned char*)"AUTHENTICATE:xmpp/", 18, 0 );
00304 iks_md5_hash( md5, (const unsigned char*)m_jid.server().c_str(), m_jid.server().length(), 1 );
00305 iks_md5_print( md5, a2 );
00306 iks_md5_reset( md5 );
00307 iks_md5_hash( md5, (const unsigned char*)a1, 32, 0 );
00308 iks_md5_hash( md5, (const unsigned char*)":", 1, 0 );
00309 iks_md5_hash( md5, (const unsigned char*)nonce.c_str(), nonce.length(), 0 );
00310 iks_md5_hash( md5, (const unsigned char*)":00000001:", 10, 0 );
00311 iks_md5_hash( md5, (const unsigned char*)cnonce, iks_strlen( cnonce ), 0 );
00312 iks_md5_hash( md5, (const unsigned char*)":auth:", 6, 0 );
00313 iks_md5_hash( md5, (const unsigned char*)a2, 32, 1 );
00314 iks_md5_print( md5, response_value );
00315 iks_md5_delete( md5 );
00316
00317 i = m_jid.username().length() + realm.length() +
00318 nonce.length() + m_jid.server().length() +
00319 CNONCE_LEN*8 + 136;
00320
00321 std::string response = "username=\"" + m_jid.username() + "\",realm=\"" + realm;
00322 response += "\",nonce=\""+ nonce + "\",cnonce=\"";
00323 response += cnonce;
00324 response += "\",nc=00000001,qop=auth,digest-uri=\"xmpp/" + m_jid.server() + "\",response=";
00325 response += response_value;
00326 response += ",charset=utf-8";
00327 response_coded = iks_base64_encode( response.c_str(), response.length() );
00328
00329 t = new Tag( "response", response_coded );
00330
00331 iks_free( response_coded );
00332 }
00333 t->addAttrib( "xmlns", XMLNS_STREAM_SASL );
00334 send( t );
00335 iks_free( b );
00336
00337 }
00338
00339 void ClientBase::processSASLError( Stanza *stanza )
00340 {
00341 if( stanza->hasChild( "aborted" ) )
00342 m_authError = SASL_ABORTED;
00343 else if( stanza->hasChild( "incorrect-encoding" ) )
00344 m_authError = SASL_INCORRECT_ENCODING;
00345 else if( stanza->hasChild( "invalid-authzid" ) )
00346 m_authError = SASL_INVALID_AUTHZID;
00347 else if( stanza->hasChild( "invalid-mechanism" ) )
00348 m_authError = SASL_INVALID_MECHANISM;
00349 else if( stanza->hasChild( "mechanism-too-weak" ) )
00350 m_authError = SASL_MECHANISM_TOO_WEAK;
00351 else if( stanza->hasChild( "not-authorized" ) )
00352 m_authError = SASL_NOT_AUTHORIZED;
00353 else if( stanza->hasChild( "temporary-auth-failure" ) )
00354 m_authError = SASL_TEMPORARY_AUTH_FAILURE;
00355 }
00356
00357 void ClientBase::send( Tag *tag )
00358 {
00359 if( !tag )
00360 return;
00361
00362 send( tag->xml() );
00363
00364 if( tag->type() == STANZA_UNDEFINED )
00365 delete( tag );
00366 else
00367 {
00368 Stanza *s = dynamic_cast<Stanza*>( tag );
00369 delete( s );
00370 }
00371 }
00372
00373 void ClientBase::send( const std::string& xml )
00374 {
00375 log( xml, false );
00376
00377 if( m_connection )
00378 m_connection->send( xml );
00379 }
00380
00381 ConnectionState ClientBase::state() const{
00382 if( m_connection )
00383 return m_connection->state();
00384 else
00385 return STATE_DISCONNECTED;
00386 }
00387
00388 const std::string ClientBase::getID()
00389 {
00390 std::ostringstream oss;
00391 oss << ++m_idCount;
00392 return std::string( "uid" ) + oss.str();
00393 }
00394
00395 bool ClientBase::checkStreamVersion( const std::string& version )
00396 {
00397 int major = 0;
00398 int minor = 0;
00399 int myMajor = atoi( XMPP_STREAM_VERSION_MAJOR );
00400
00401 unsigned int dot = version.find( "." );
00402 if( !version.empty() && dot && dot != std::string::npos )
00403 {
00404 major = atoi( version.substr( 0, dot ).c_str() );
00405 minor = atoi( version.substr( dot ).c_str() );
00406 }
00407
00408 if( myMajor < major )
00409 return false;
00410 else
00411 return true;
00412 }
00413
00414 void ClientBase::handleStreamError( Stanza *stanza )
00415 {
00416 Tag::TagList& c = stanza->children();
00417 Tag::TagList::const_iterator it = c.begin();
00418 for( ; it != c.end(); ++it )
00419 {
00420 if( (*it)->name() == "bad-format" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00421 m_streamError = ERROR_BAD_FORMAT;
00422 else if( (*it)->name() == "bad-namespace-prefix" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00423 m_streamError = ERROR_BAD_NAMESPACE_PREFIX;
00424 else if( (*it)->name() == "conflict" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00425 m_streamError = ERROR_CONFLICT;
00426 else if( (*it)->name() == "connection-timeout" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00427 m_streamError = ERROR_CONNECTION_TIMEOUT;
00428 else if( (*it)->name() == "host-gone" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00429 m_streamError = ERROR_HOST_GONE;
00430 else if( (*it)->name() == "host-unknown" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00431 m_streamError = ERROR_HOST_UNKNOWN;
00432 else if( (*it)->name() == "improper-addressing" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00433 m_streamError = ERROR_IMPROPER_ADDRESSING;
00434 else if( (*it)->name() == "internal-server-error" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00435 m_streamError = ERROR_INTERNAL_SERVER_ERROR;
00436 else if( (*it)->name() == "invalid-from" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00437 m_streamError = ERROR_INVALID_FROM;
00438 else if( (*it)->name() == "invalid-id" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00439 m_streamError = ERROR_INVALID_ID;
00440 else if( (*it)->name() == "invalid-namespace" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00441 m_streamError = ERROR_INVALID_NAMESPACE;
00442 else if( (*it)->name() == "invalid-xml" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00443 m_streamError = ERROR_INVALID_XML;
00444 else if( (*it)->name() == "not-authorized" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00445 m_streamError = ERROR_NOT_AUTHORIZED;
00446 else if( (*it)->name() == "policy-violation" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00447 m_streamError = ERROR_POLICY_VIOLATION;
00448 else if( (*it)->name() == "remote-connection-failed" &&
00449 (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00450 m_streamError = ERROR_REMOTE_CONNECTION_FAILED;
00451 else if( (*it)->name() == "resource-constraint" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00452 m_streamError = ERROR_RESOURCE_CONSTRAINT;
00453 else if( (*it)->name() == "restricted-xml" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00454 m_streamError = ERROR_RESTRICTED_XML;
00455 else if( (*it)->name() == "see-other-host" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00456 {
00457 m_streamError = ERROR_SEE_OTHER_HOST;
00458 m_streamErrorCData = stanza->findChild( "see-other-host" )->cdata();
00459 }
00460 else if( (*it)->name() == "system-shutdown" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00461 m_streamError = ERROR_SYSTEM_SHUTDOWN;
00462 else if( (*it)->name() == "undefined-condition" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00463 m_streamError = ERROR_UNDEFINED_CONDITION;
00464 else if( (*it)->name() == "unsupported-encoding" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00465 m_streamError = ERROR_UNSUPPORTED_ENCODING;
00466 else if( (*it)->name() == "unsupported-stanza-type" &&
00467 (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00468 m_streamError = ERROR_UNSUPPORTED_STANZA_TYPE;
00469 else if( (*it)->name() == "unsupported-version" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00470 m_streamError = ERROR_UNSUPPORTED_VERSION;
00471 else if( (*it)->name() == "xml-not-well-formed" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00472 m_streamError = ERROR_XML_NOT_WELL_FORMED;
00473 else if( (*it)->name() == "text" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00474 {
00475 const std::string lang = (*it)->findAttribute( "xml:lang" );
00476 if( !lang.empty() )
00477 m_streamErrorText[lang] = (*it)->cdata();
00478 else
00479 m_streamErrorText["default"] = (*it)->cdata();
00480 }
00481 else
00482 m_streamErrorAppCondition = (*it);
00483 }
00484
00485 disconnect( CONN_STREAM_ERROR );
00486 }
00487
00488 const std::string ClientBase::streamErrorText( const std::string& lang ) const
00489 {
00490 StringMap::const_iterator it = m_streamErrorText.find( lang );
00491 if( it != m_streamErrorText.end() )
00492 return (*it).second;
00493 else
00494 return "";
00495 }
00496
00497 void ClientBase::log( const std::string& xml, bool incoming )
00498 {
00499 #ifdef DEBUG
00500 if ( m_connection->isSecure() )
00501 printf( "Sec" );
00502
00503 if( incoming )
00504 printf( "RECV " );
00505 else
00506 printf( "SEND " );
00507
00508 printf( "[%s]", xml.c_str() );
00509 if( xml.substr( xml.length()-2, 1 ) != "\n" )
00510 printf( "\n" );
00511 #endif
00512 notifyLogHandlers( xml, incoming );
00513 }
00514
00515 int ClientBase::fileDescriptor() const
00516 {
00517 if( m_connection )
00518 return m_connection->fileDescriptor();
00519 else
00520 return -1;
00521 }
00522
00523 void ClientBase::registerPresenceHandler( PresenceHandler *ph )
00524 {
00525 if( ph )
00526 m_presenceHandlers.push_back( ph );
00527 }
00528
00529 void ClientBase::removePresenceHandler( PresenceHandler *ph )
00530 {
00531 if( ph )
00532 m_presenceHandlers.remove( ph );
00533 }
00534
00535 void ClientBase::registerLogHandler( LogHandler *lh )
00536 {
00537 m_logHandlers.push_back( lh );
00538 }
00539
00540 void ClientBase::removeLogHandler( LogHandler *lh )
00541 {
00542 m_logHandlers.remove( lh );
00543 }
00544
00545 void ClientBase::registerIqHandler( IqHandler *ih, const std::string& xmlns )
00546 {
00547 if( ih && !xmlns.empty() )
00548 m_iqNSHandlers[xmlns] = ih;
00549 }
00550
00551 void ClientBase::trackID( IqHandler *ih, const std::string& id, int context )
00552 {
00553 if( ih && !id.empty() )
00554 {
00555 TrackStruct track;
00556 track.ih = ih;
00557 track.context = context;
00558 m_iqIDHandlers[id] = track;
00559 }
00560 }
00561
00562 void ClientBase::removeIqHandler( const std::string& xmlns )
00563 {
00564 if( !xmlns.empty() )
00565 m_iqNSHandlers.erase( xmlns );
00566 }
00567
00568 void ClientBase::registerMessageHandler( MessageHandler *mh )
00569 {
00570 if( mh )
00571 m_messageHandlers.push_back( mh );
00572 }
00573
00574 void ClientBase::removeMessageHandler( MessageHandler *mh )
00575 {
00576 if( mh )
00577 m_messageHandlers.remove( mh );
00578 }
00579
00580 void ClientBase::registerSubscriptionHandler( SubscriptionHandler *sh )
00581 {
00582 if( sh )
00583 m_subscriptionHandlers.push_back( sh );
00584 }
00585
00586 void ClientBase::registerTagHandler( TagHandler *th, const std::string& tag, const std::string& xmlns )
00587 {
00588 if( th && !tag.empty() )
00589 {
00590 TagHandlerStruct ths;
00591 ths.tag = tag;
00592 ths.xmlns = xmlns;
00593 ths.th = th;
00594 m_tagHandlers.push_back( ths );
00595 }
00596 }
00597
00598 void ClientBase::removeSubscriptionHandler( SubscriptionHandler *sh )
00599 {
00600 if( sh )
00601 m_subscriptionHandlers.remove( sh );
00602 }
00603
00604 void ClientBase::registerConnectionListener( ConnectionListener *cl )
00605 {
00606 if( cl )
00607 m_connectionListeners.push_back( cl );
00608 }
00609
00610 void ClientBase::removeConnectionListener( ConnectionListener *cl )
00611 {
00612 if( cl )
00613 m_connectionListeners.remove( cl );
00614 }
00615
00616 void ClientBase::removeTagHandler( TagHandler *th, const std::string& tag, const std::string& xmlns )
00617 {
00618 if( th )
00619 {
00620 TagHandlerList::iterator it = m_tagHandlers.begin();
00621 for( ; it != m_tagHandlers.end(); ++it )
00622 {
00623 if( (*it).th == th && (*it).tag == tag && (*it).xmlns == xmlns )
00624 m_tagHandlers.erase( it );
00625 }
00626 }
00627 }
00628
00629 void ClientBase::notifyOnConnect()
00630 {
00631 ConnectionListenerList::const_iterator it = m_connectionListeners.begin();
00632 for( ; it != m_connectionListeners.end(); ++it )
00633 {
00634 (*it)->onConnect();
00635 }
00636 }
00637
00638 void ClientBase::notifyOnDisconnect( ConnectionError e )
00639 {
00640 ConnectionListenerList::const_iterator it = m_connectionListeners.begin();
00641 for( ; it != m_connectionListeners.end(); ++it )
00642 {
00643 (*it)->onDisconnect( e );
00644 }
00645 }
00646
00647 bool ClientBase::notifyOnTLSConnect( const CertInfo& info )
00648 {
00649 ConnectionListenerList::const_iterator it = m_connectionListeners.begin();
00650 for( ; it != m_connectionListeners.end(); ++it )
00651 {
00652 return (*it)->onTLSConnect( info );
00653 }
00654
00655 return false;
00656 }
00657
00658 void ClientBase::notifyOnResourceBindError( ConnectionListener::ResourceBindError error )
00659 {
00660 ConnectionListenerList::const_iterator it = m_connectionListeners.begin();
00661 for( ; it != m_connectionListeners.end(); ++it )
00662 {
00663 (*it)->onResourceBindError( error );
00664 }
00665 }
00666
00667 void ClientBase::notifyOnSessionCreateError( ConnectionListener::SessionCreateError error )
00668 {
00669 ConnectionListenerList::const_iterator it = m_connectionListeners.begin();
00670 for( ; it != m_connectionListeners.end(); ++it )
00671 {
00672 (*it)->onSessionCreateError( error );
00673 }
00674 }
00675
00676 void ClientBase::notifyPresenceHandlers( Stanza *stanza )
00677 {
00678 PresenceHandlerList::const_iterator it = m_presenceHandlers.begin();
00679 for( ; it != m_presenceHandlers.end(); ++it )
00680 {
00681 (*it)->handlePresence( stanza );
00682 }
00683 }
00684
00685 void ClientBase::notifySubscriptionHandlers( Stanza *stanza )
00686 {
00687 SubscriptionHandlerList::const_iterator it = m_subscriptionHandlers.begin();
00688 for( ; it != m_subscriptionHandlers.end(); ++it )
00689 {
00690 (*it)->handleSubscription( stanza );
00691 }
00692 }
00693
00694 void ClientBase::notifyIqHandlers( Stanza *stanza )
00695 {
00696 bool res = false;
00697
00698 IqHandlerMap::const_iterator it = m_iqNSHandlers.begin();
00699 for( ; it != m_iqNSHandlers.end(); ++it )
00700 {
00701 if( stanza->hasChildWithAttrib( "xmlns", (*it).first ) )
00702 {
00703 if( (*it).second->handleIq( stanza ) )
00704 res = true;
00705 }
00706 }
00707
00708 IqTrackMap::iterator it_id = m_iqIDHandlers.find( stanza->id() );
00709 if( it_id != m_iqIDHandlers.end() )
00710 {
00711 if( (*it_id).second.ih->handleIqID( stanza, (*it_id).second.context ) )
00712 res = true;
00713 m_iqIDHandlers.erase( it_id );
00714 }
00715
00716 if( !res && ( stanza->type() == STANZA_IQ ) &&
00717 ( ( stanza->subtype() == STANZA_IQ_GET ) || ( stanza->subtype() == STANZA_IQ_SET ) ) )
00718 {
00719 Tag *iq = new Tag( "iq" );
00720 iq->addAttrib( "type", "result" );
00721 iq->addAttrib( "id", stanza->id() );
00722 iq->addAttrib( "to", stanza->from().full() );
00723 send( iq );
00724 }
00725 }
00726
00727 void ClientBase::notifyMessageHandlers( Stanza *stanza )
00728 {
00729 MessageHandlerList::const_iterator it = m_messageHandlers.begin();
00730 for( ; it != m_messageHandlers.end(); ++it )
00731 {
00732 (*it)->handleMessage( stanza );
00733 }
00734 }
00735
00736 void ClientBase::notifyLogHandlers( const std::string& xml, bool incoming )
00737 {
00738 LogHandlerList::const_iterator it = m_logHandlers.begin();
00739 for( ; it != m_logHandlers.end(); ++it )
00740 {
00741 (*it)->handleLog( xml, incoming );
00742 }
00743 }
00744
00745 void ClientBase::notifyTagHandlers( Stanza *stanza )
00746 {
00747 TagHandlerList::const_iterator it = m_tagHandlers.begin();
00748 for( ; it != m_tagHandlers.end(); ++it )
00749 {
00750 if( (*it).tag == stanza->name() && (*it).xmlns == stanza->xmlns() )
00751 (*it).th->handleTag( stanza );
00752 }
00753 }
00754
00755 }