clientbase.cpp

00001 /*
00002   Copyright (c) 2005 by Jakob Schroeter <js@camaya.net>
00003   This file is part of the gloox library. http://camaya.net/gloox
00004 
00005   This software is distributed under a license. The full license
00006   agreement can be found in the file LICENSE in this distribution.
00007   This software may not be copied, modified, sold or distributed
00008   other than expressed in the named license agreement.
00009 
00010   This software is distributed without any warranty.
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 }

Generated on Mon Jan 16 16:19:54 2006 for gloox by  doxygen 1.4.6