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