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 const std::string ClientBase::getID()
00401 {
00402 std::ostringstream oss;
00403 oss << ++m_idCount;
00404 return std::string( "uid" ) + oss.str();
00405 }
00406
00407 bool ClientBase::checkStreamVersion( const std::string& version )
00408 {
00409 if( version.empty() )
00410 return false;
00411
00412 int major = 0;
00413 int minor = 0;
00414 int myMajor = XMPP_STREAM_VERSION_MAJOR;
00415
00416 size_t dot = version.find( "." );
00417 if( !version.empty() && dot && dot != std::string::npos )
00418 {
00419 major = atoi( version.substr( 0, dot ).c_str() );
00420 minor = atoi( version.substr( dot ).c_str() );
00421 }
00422
00423 if( myMajor < major )
00424 return false;
00425 else
00426 return true;
00427 }
00428
00429 LogSink& ClientBase::logInstance()
00430 {
00431 return m_logInstance;
00432 }
00433
00434 void ClientBase::handleStreamError( Stanza *stanza )
00435 {
00436 Tag::TagList& c = stanza->children();
00437 Tag::TagList::const_iterator it = c.begin();
00438 for( ; it != c.end(); ++it )
00439 {
00440 if( (*it)->name() == "bad-format" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00441 m_streamError = StreamErrorBadFormat;
00442 else if( (*it)->name() == "bad-namespace-prefix" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00443 m_streamError = StreamErrorBadNamespacePrefix;
00444 else if( (*it)->name() == "conflict" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00445 m_streamError = StreamErrorConflict;
00446 else if( (*it)->name() == "connection-timeout" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00447 m_streamError = StreamErrorConnectionTimeout;
00448 else if( (*it)->name() == "host-gone" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00449 m_streamError = StreamErrorHostGone;
00450 else if( (*it)->name() == "host-unknown" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00451 m_streamError = StreamErrorHostUnknown;
00452 else if( (*it)->name() == "improper-addressing" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00453 m_streamError = StreamErrorImproperAddressing;
00454 else if( (*it)->name() == "internal-server-error" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00455 m_streamError = StreamErrorInternalServerError;
00456 else if( (*it)->name() == "invalid-from" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00457 m_streamError = StreamErrorInvalidFrom;
00458 else if( (*it)->name() == "invalid-id" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00459 m_streamError = StreamErrorInvalidId;
00460 else if( (*it)->name() == "invalid-namespace" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00461 m_streamError = StreamErrorInvalidNamespace;
00462 else if( (*it)->name() == "invalid-xml" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00463 m_streamError = StreamErrorInvalidXml;
00464 else if( (*it)->name() == "not-authorized" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00465 m_streamError = StreamErrorNotAuthorized;
00466 else if( (*it)->name() == "policy-violation" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00467 m_streamError = StreamErrorPolicyViolation;
00468 else if( (*it)->name() == "remote-connection-failed" &&
00469 (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00470 m_streamError = StreamErrorRemoteConnectionFailed;
00471 else if( (*it)->name() == "resource-constraint" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00472 m_streamError = StreamErrorResourceConstraint;
00473 else if( (*it)->name() == "restricted-xml" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00474 m_streamError = StreamErrorRestrictedXml;
00475 else if( (*it)->name() == "see-other-host" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00476 {
00477 m_streamError = StreamErrorSeeOtherHost;
00478 m_streamErrorCData = stanza->findChild( "see-other-host" )->cdata();
00479 }
00480 else if( (*it)->name() == "system-shutdown" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00481 m_streamError = StreamErrorSystemShutdown;
00482 else if( (*it)->name() == "undefined-condition" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00483 m_streamError = StreamErrorUndefinedCondition;
00484 else if( (*it)->name() == "unsupported-encoding" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00485 m_streamError = StreamErrorUnsupportedEncoding;
00486 else if( (*it)->name() == "unsupported-stanza-type" &&
00487 (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00488 m_streamError = StreamErrorUnsupportedStanzaType;
00489 else if( (*it)->name() == "unsupported-version" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00490 m_streamError = StreamErrorUnsupportedVersion;
00491 else if( (*it)->name() == "xml-not-well-formed" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00492 m_streamError = StreamErrorXmlNotWellFormed;
00493 else if( (*it)->name() == "text" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STREAM ) )
00494 {
00495 const std::string lang = (*it)->findAttribute( "xml:lang" );
00496 if( !lang.empty() )
00497 m_streamErrorText[lang] = (*it)->cdata();
00498 else
00499 m_streamErrorText["default"] = (*it)->cdata();
00500 }
00501 else
00502 m_streamErrorAppCondition = (*it);
00503 }
00504 }
00505
00506 const std::string ClientBase::streamErrorText( const std::string& lang ) const
00507 {
00508 StringMap::const_iterator it = m_streamErrorText.find( lang );
00509 if( it != m_streamErrorText.end() )
00510 return (*it).second;
00511 else
00512 return "";
00513 }
00514
00515 void ClientBase::setAutoMessageSession( bool autoMS, MessageSessionHandler *msh )
00516 {
00517 if( autoMS && msh )
00518 {
00519 m_messageSessionHandler = msh;
00520 m_autoMessageSession = true;
00521 }
00522 else
00523 {
00524 m_autoMessageSession = false;
00525 m_messageSessionHandler = 0;
00526 }
00527 }
00528
00529 int ClientBase::fileDescriptor()
00530 {
00531 if( m_connection )
00532 {
00533 m_fdRequested = true;
00534 return m_connection->fileDescriptor();
00535 }
00536 else
00537 return -1;
00538 }
00539
00540 void ClientBase::registerPresenceHandler( PresenceHandler *ph )
00541 {
00542 if( ph )
00543 m_presenceHandlers.push_back( ph );
00544 }
00545
00546 void ClientBase::removePresenceHandler( PresenceHandler *ph )
00547 {
00548 if( ph )
00549 m_presenceHandlers.remove( ph );
00550 }
00551
00552 void ClientBase::registerIqHandler( IqHandler *ih, const std::string& xmlns )
00553 {
00554 if( ih && !xmlns.empty() )
00555 m_iqNSHandlers[xmlns] = ih;
00556 }
00557
00558 void ClientBase::trackID( IqHandler *ih, const std::string& id, int context )
00559 {
00560 if( ih && !id.empty() )
00561 {
00562 TrackStruct track;
00563 track.ih = ih;
00564 track.context = context;
00565 m_iqIDHandlers[id] = track;
00566 }
00567 }
00568
00569 void ClientBase::removeIqHandler( const std::string& xmlns )
00570 {
00571 if( !xmlns.empty() )
00572 m_iqNSHandlers.erase( xmlns );
00573 }
00574
00575 void ClientBase::registerMessageHandler( const std::string& jid, MessageHandler *mh )
00576 {
00577 if( mh && !jid.empty() )
00578 m_messageJidHandlers[jid] = mh;
00579 }
00580
00581 void ClientBase::registerMessageHandler( MessageHandler *mh )
00582 {
00583 if( mh )
00584 m_messageHandlers.push_back( mh );
00585 }
00586
00587 void ClientBase::removeMessageHandler( const std::string& jid )
00588 {
00589 MessageHandlerMap::iterator it = m_messageJidHandlers.find( jid );
00590 if( it != m_messageJidHandlers.end() )
00591 m_messageJidHandlers.erase( it );
00592 }
00593
00594 void ClientBase::removeMessageHandler( MessageHandler *mh )
00595 {
00596 if( mh )
00597 m_messageHandlers.remove( mh );
00598 }
00599
00600 void ClientBase::registerSubscriptionHandler( SubscriptionHandler *sh )
00601 {
00602 if( sh )
00603 m_subscriptionHandlers.push_back( sh );
00604 }
00605
00606 void ClientBase::registerTagHandler( TagHandler *th, const std::string& tag, const std::string& xmlns )
00607 {
00608 if( th && !tag.empty() )
00609 {
00610 TagHandlerStruct ths;
00611 ths.tag = tag;
00612 ths.xmlns = xmlns;
00613 ths.th = th;
00614 m_tagHandlers.push_back( ths );
00615 }
00616 }
00617
00618 void ClientBase::removeSubscriptionHandler( SubscriptionHandler *sh )
00619 {
00620 if( sh )
00621 m_subscriptionHandlers.remove( sh );
00622 }
00623
00624 void ClientBase::registerConnectionListener( ConnectionListener *cl )
00625 {
00626 if( cl )
00627 m_connectionListeners.push_back( cl );
00628 }
00629
00630 void ClientBase::removeConnectionListener( ConnectionListener *cl )
00631 {
00632 if( cl )
00633 m_connectionListeners.remove( cl );
00634 }
00635
00636 void ClientBase::removeTagHandler( TagHandler *th, const std::string& tag, const std::string& xmlns )
00637 {
00638 if( th )
00639 {
00640 TagHandlerList::iterator it = m_tagHandlers.begin();
00641 for( ; it != m_tagHandlers.end(); ++it )
00642 {
00643 if( (*it).th == th && (*it).tag == tag && (*it).xmlns == xmlns )
00644 m_tagHandlers.erase( it );
00645 }
00646 }
00647 }
00648
00649 void ClientBase::notifyOnConnect()
00650 {
00651 ConnectionListenerList::const_iterator it = m_connectionListeners.begin();
00652 for( ; it != m_connectionListeners.end(); ++it )
00653 {
00654 (*it)->onConnect();
00655 }
00656 }
00657
00658 void ClientBase::notifyOnDisconnect( ConnectionError e )
00659 {
00660 ConnectionListenerList::const_iterator it = m_connectionListeners.begin();
00661 for( ; it != m_connectionListeners.end(); ++it )
00662 {
00663 (*it)->onDisconnect( e );
00664 }
00665
00666 cleanup();
00667 }
00668
00669 bool ClientBase::notifyOnTLSConnect( const CertInfo& info )
00670 {
00671 ConnectionListenerList::const_iterator it = m_connectionListeners.begin();
00672 for( ; it != m_connectionListeners.end(); ++it )
00673 {
00674 if( !(*it)->onTLSConnect( info ) )
00675 return false;
00676 }
00677
00678 return true;
00679 }
00680
00681 void ClientBase::notifyOnResourceBindError( ResourceBindError error )
00682 {
00683 ConnectionListenerList::const_iterator it = m_connectionListeners.begin();
00684 for( ; it != m_connectionListeners.end(); ++it )
00685 {
00686 (*it)->onResourceBindError( error );
00687 }
00688 }
00689
00690 void ClientBase::notifyOnSessionCreateError( SessionCreateError error )
00691 {
00692 ConnectionListenerList::const_iterator it = m_connectionListeners.begin();
00693 for( ; it != m_connectionListeners.end(); ++it )
00694 {
00695 (*it)->onSessionCreateError( error );
00696 }
00697 }
00698
00699 void ClientBase::notifyPresenceHandlers( Stanza *stanza )
00700 {
00701 PresenceHandlerList::const_iterator it = m_presenceHandlers.begin();
00702 for( ; it != m_presenceHandlers.end(); ++it )
00703 {
00704 (*it)->handlePresence( stanza );
00705 }
00706 }
00707
00708 void ClientBase::notifySubscriptionHandlers( Stanza *stanza )
00709 {
00710 SubscriptionHandlerList::const_iterator it = m_subscriptionHandlers.begin();
00711 for( ; it != m_subscriptionHandlers.end(); ++it )
00712 {
00713 (*it)->handleSubscription( stanza );
00714 }
00715 }
00716
00717 void ClientBase::notifyIqHandlers( Stanza *stanza )
00718 {
00719 bool res = false;
00720
00721 IqHandlerMap::const_iterator it = m_iqNSHandlers.begin();
00722 for( ; it != m_iqNSHandlers.end(); ++it )
00723 {
00724 if( stanza->hasChildWithAttrib( "xmlns", (*it).first ) )
00725 {
00726 if( (*it).second->handleIq( stanza ) )
00727 res = true;
00728 }
00729 }
00730
00731 IqTrackMap::iterator it_id = m_iqIDHandlers.find( stanza->id() );
00732 if( it_id != m_iqIDHandlers.end() )
00733 {
00734 if( (*it_id).second.ih->handleIqID( stanza, (*it_id).second.context ) )
00735 res = true;
00736 m_iqIDHandlers.erase( it_id );
00737 }
00738
00739 if( !res && ( stanza->type() == StanzaIq ) &&
00740 ( ( stanza->subtype() == StanzaIqGet ) || ( stanza->subtype() == StanzaIqSet ) ) )
00741 {
00742 Tag *iq = new Tag( "iq" );
00743 iq->addAttribute( "type", "result" );
00744 iq->addAttribute( "id", stanza->id() );
00745 iq->addAttribute( "to", stanza->from().full() );
00746 send( iq );
00747 }
00748 }
00749
00750 void ClientBase::notifyMessageHandlers( Stanza *stanza )
00751 {
00752 MessageHandlerMap::const_iterator it1 = m_messageJidHandlers.find( stanza->from().full() );
00753 if( it1 != m_messageJidHandlers.end() )
00754 {
00755 (*it1).second->handleMessage( stanza );
00756 return;
00757 }
00758
00759 if( m_autoMessageSession && m_messageSessionHandler )
00760 {
00761 MessageSession *session = new MessageSession( this, stanza->from() );
00762 m_messageSessionHandler->handleMessageSession( session );
00763 notifyMessageHandlers( stanza );
00764 return;
00765 }
00766
00767 MessageHandlerList::const_iterator it = m_messageHandlers.begin();
00768 for( ; it != m_messageHandlers.end(); ++it )
00769 {
00770 (*it)->handleMessage( stanza );
00771 }
00772 }
00773
00774 void ClientBase::notifyTagHandlers( Stanza *stanza )
00775 {
00776 TagHandlerList::const_iterator it = m_tagHandlers.begin();
00777 for( ; it != m_tagHandlers.end(); ++it )
00778 {
00779 if( (*it).tag == stanza->name() && (*it).xmlns == stanza->xmlns() )
00780 (*it).th->handleTag( stanza );
00781 }
00782 }
00783
00784 void ClientBase::cleanup()
00785 {
00786
00787 }
00788
00789 }