⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 clientbase.cpp

📁 Jabber code library, developed with c
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/*  Copyright (c) 2005-2008 by Jakob Schroeter <js@camaya.net>  This file is part of the gloox library. http://camaya.net/gloox  This software is distributed under a license. The full license  agreement can be found in the file LICENSE in this distribution.  This software may not be copied, modified, sold or distributed  other than expressed in the named license agreement.  This software is distributed without any warranty.*/#ifdef _WIN32# include "../config.h.win"#elif defined( _WIN32_WCE )# include "../config.h.win"#else# include "config.h"#endif#include "clientbase.h"#include "connectionbase.h"#include "tlsbase.h"#include "compressionbase.h"#include "connectiontcpclient.h"#include "disco.h"#include "messagesessionhandler.h"#include "parser.h"#include "tag.h"#include "stanza.h"#include "connectionlistener.h"#include "iqhandler.h"#include "messagehandler.h"#include "presencehandler.h"#include "rosterlistener.h"#include "subscriptionhandler.h"#include "loghandler.h"#include "taghandler.h"#include "mucinvitationhandler.h"#include "jid.h"#include "base64.h"#include "md5.h"#include "tlsdefault.h"#include "compressionzlib.h"#include <cstdlib>#include <string>#include <map>#include <list>#include <algorithm>#ifndef _WIN32_WCE# include <sstream># include <iomanip>#endifnamespace gloox{  ClientBase::ClientBase( const std::string& ns, const std::string& server, int port )    : m_connection( 0 ), m_encryption( 0 ), m_compression( 0 ), m_disco( 0 ), m_namespace( ns ),      m_xmllang( "en" ), m_server( server ), m_compressionActive( false ), m_encryptionActive( false ),      m_compress( true ), m_authed( false ), m_sasl( true ), m_tls( TLSOptional ), m_port( port ),      m_availableSaslMechs( SaslMechAll ),      m_statisticsHandler( 0 ), m_mucInvitationHandler( 0 ),      m_messageSessionHandlerChat( 0 ), m_messageSessionHandlerGroupchat( 0 ),      m_messageSessionHandlerHeadline( 0 ), m_messageSessionHandlerNormal( 0 ),      m_parser( 0 ), m_authError( AuthErrorUndefined ), m_streamError( StreamErrorUndefined ),      m_streamErrorAppCondition( 0 ), m_selectedSaslMech( SaslMechNone ),      m_idCount( 0 ), m_autoMessageSession( false )  {    init();  }  ClientBase::ClientBase( const std::string& ns, const std::string& password,                          const std::string& server, int port )    : m_connection( 0 ), m_encryption( 0 ), m_compression( 0 ), m_disco( 0 ), m_namespace( ns ),      m_password( password ),      m_xmllang( "en" ), m_server( server ), m_compressionActive( false ), m_encryptionActive( false ),      m_compress( true ), m_authed( false ), m_block( false ), m_sasl( true ), m_tls( TLSOptional ),      m_port( port ), m_availableSaslMechs( SaslMechAll ),      m_statisticsHandler( 0 ), m_mucInvitationHandler( 0 ),      m_messageSessionHandlerChat( 0 ), m_messageSessionHandlerGroupchat( 0 ),      m_messageSessionHandlerHeadline( 0 ), m_messageSessionHandlerNormal( 0 ),      m_parser( 0 ), m_authError( AuthErrorUndefined ), m_streamError( StreamErrorUndefined ),      m_streamErrorAppCondition( 0 ), m_selectedSaslMech( SaslMechNone ),      m_idCount( 0 ), m_autoMessageSession( false )  {    init();  }  void ClientBase::init()  {    if( !m_disco )    {      m_disco = new Disco( this );      m_disco->setVersion( "based on gloox", GLOOX_VERSION );    }    m_streamError = StreamErrorUndefined;    m_block = false;    m_stats.totalBytesSent = 0;    m_stats.totalBytesReceived = 0;    m_stats.compressedBytesSent = 0;    m_stats.compressedBytesReceived = 0;    m_stats.uncompressedBytesSent = 0;    m_stats.uncompressedBytesReceived = 0;    m_stats.totalStanzasSent = 0;    m_stats.totalStanzasReceived = 0;    m_stats.iqStanzasSent = 0;    m_stats.iqStanzasReceived = 0;    m_stats.messageStanzasSent = 0;    m_stats.messageStanzasReceived = 0;    m_stats.s10nStanzasSent = 0;    m_stats.s10nStanzasReceived = 0;    m_stats.presenceStanzasSent = 0;    m_stats.presenceStanzasReceived = 0;    m_stats.encryption = false;    m_stats.compression = false;    cleanup();  }  ClientBase::~ClientBase()  {    delete m_connection;    delete m_encryption;    delete m_compression;    delete m_parser;    delete m_disco;    MessageSessionList::const_iterator it = m_messageSessions.begin();    for( ; it != m_messageSessions.end(); ++it )      delete (*it);    PresenceJidHandlerList::const_iterator it1 = m_presenceJidHandlers.begin();    for( ; it1 != m_presenceJidHandlers.end(); ++it1 )      delete (*it1).jid;  }  ConnectionError ClientBase::recv( int timeout )  {    if( !m_connection || m_connection->state() == StateDisconnected )      return ConnNotConnected;    return m_connection->recv( timeout );  }  bool ClientBase::connect( bool block )  {    if( m_server.empty() )      return false;    if( !m_parser )      m_parser = new Parser( this );    if( !m_connection )      m_connection = new ConnectionTCPClient( this, m_logInstance, m_server, m_port );    if( m_connection->state() >= StateConnecting )      return true;    if( !m_encryption )      m_encryption = getDefaultEncryption();    if( m_encryption )    {      m_encryption->setCACerts( m_cacerts );      m_encryption->setClientCert( m_clientKey, m_clientCerts );    }    if( !m_compression )      m_compression = getDefaultCompression();    m_logInstance.log( LogLevelDebug, LogAreaClassClientbase, "This is gloox " + GLOOX_VERSION                                                              + ", connecting..." );    m_block = block;    ConnectionError ret = m_connection->connect();    return ret == ConnNoError;  }  void ClientBase::handleTag( Tag *tag )  {    if( !tag )    {      logInstance().log( LogLevelDebug, LogAreaClassClientbase, "stream closed" );      disconnect( ConnStreamClosed );      return;    }    Stanza *stanza = new Stanza( tag );    logInstance().log( LogLevelDebug, LogAreaXmlIncoming, stanza->xml() );    ++m_stats.totalStanzasReceived;    if( tag->name() == "stream:stream" )    {      const std::string& version = stanza->findAttribute( "version" );      if( !checkStreamVersion( version ) )      {        logInstance().log( LogLevelDebug, LogAreaClassClientbase, "This server is not XMPP-compliant"            " (it does not send a 'version' attribute). Please fix it or try another one.\n" );        disconnect( ConnStreamVersionError );      }      m_sid = stanza->findAttribute( "id" );      handleStartNode();    }    else if( tag->name() == "stream:error" )    {      handleStreamError( stanza );      disconnect( ConnStreamError );    }    else    {      if( !handleNormalNode( stanza ) )      {        switch( stanza->type() )        {          case StanzaIq:            notifyIqHandlers( stanza );            ++m_stats.iqStanzasReceived;            break;          case StanzaPresence:            notifyPresenceHandlers( stanza );            ++m_stats.presenceStanzasReceived;            break;          case StanzaS10n:            notifySubscriptionHandlers( stanza );            ++m_stats.s10nStanzasReceived;            break;          case StanzaMessage:            notifyMessageHandlers( stanza );            ++m_stats.messageStanzasReceived;            break;          default:            notifyTagHandlers( tag );            break;        }      }    }    if( m_statisticsHandler )      m_statisticsHandler->handleStatistics( getStatistics() );    delete stanza;  }  void ClientBase::handleCompressedData( const std::string& data )  {    if( m_encryption && m_encryptionActive )      m_encryption->encrypt( data );    else if( m_connection )      m_connection->send( data );    else      m_logInstance.log( LogLevelError, LogAreaClassClientbase, "Compression finished, but chain broken" );  }  void ClientBase::handleDecompressedData( const std::string& data )  {    if( m_parser )      parse( data );    else      m_logInstance.log( LogLevelError, LogAreaClassClientbase, "Decompression finished, but chain broken" );  }  void ClientBase::handleEncryptedData( const TLSBase* /*base*/, const std::string& data )  {    if( m_connection )      m_connection->send( data );    else      m_logInstance.log( LogLevelError, LogAreaClassClientbase, "Encryption finished, but chain broken" );  }  void ClientBase::handleDecryptedData( const TLSBase* /*base*/, const std::string& data )  {    if( m_compression && m_compressionActive )      m_compression->decompress( data );    else if( m_parser )      parse( data );    else      m_logInstance.log( LogLevelError, LogAreaClassClientbase, "Decryption finished, but chain broken" );  }  void ClientBase::handleHandshakeResult( const TLSBase* /*base*/, bool success, CertInfo &certinfo )  {    if( success )    {      if( !notifyOnTLSConnect( certinfo ) )      {        logInstance().log( LogLevelError, LogAreaClassClientbase, "Server's certificate rejected!" );        disconnect( ConnTlsFailed );      }      else      {        logInstance().log( LogLevelDebug, LogAreaClassClientbase, "connection encryption active" );        header();      }    }    else    {      logInstance().log( LogLevelError, LogAreaClassClientbase, "TLS handshake failed!" );      disconnect( ConnTlsFailed );    }  }  void ClientBase::handleReceivedData( const ConnectionBase* /*connection*/, const std::string& data )  {    if( m_encryption && m_encryptionActive )      m_encryption->decrypt( data );    else if( m_compression && m_compressionActive )      m_compression->decompress( data );    else if( m_parser )      parse( data );    else      m_logInstance.log( LogLevelError, LogAreaClassClientbase, "Received data, but chain broken" );  }  void ClientBase::handleConnect( const ConnectionBase* /*connection*/ )  {    header();    if( m_block && m_connection )    {      m_connection->receive();    }  }  void ClientBase::handleDisconnect( const ConnectionBase* /*connection*/, ConnectionError reason )  {    if( m_connection )      m_connection->cleanup();    notifyOnDisconnect( reason );  }  void ClientBase::disconnect( ConnectionError reason )  {    if( m_connection && m_connection->state() >= StateConnecting )    {      if( reason != ConnTlsFailed )        send( "</stream:stream>" );      m_connection->disconnect();      m_connection->cleanup();      if( m_encryption )        m_encryption->cleanup();      m_encryptionActive = false;      m_compressionActive = false;      notifyOnDisconnect( reason );    }  }  void ClientBase::parse( const std::string& data )  {    if( m_parser && !m_parser->feed( data ) )    {      m_logInstance.log( LogLevelError, LogAreaClassClientbase, "parse error: " + data );      Tag* e = new Tag( "stream:error" );      new Tag( e, "restricted-xml", "xmlns", XMLNS_XMPP_STREAM );      send( e );      disconnect( ConnParseError );    }  }  void ClientBase::header()  {    std::string head = "<?xml version='1.0' ?>";    head += "<stream:stream to='" + m_jid.server() + "' xmlns='" + m_namespace + "' ";    head += "xmlns:stream='http://etherx.jabber.org/streams'  xml:lang='" + m_xmllang + "' ";    head += "version='" + XMPP_STREAM_VERSION_MAJOR + "." + XMPP_STREAM_VERSION_MINOR + "'>";    send( head );  }  bool ClientBase::hasTls()  {#if defined( HAVE_GNUTLS ) || defined( HAVE_OPENSSL ) || defined( HAVE_WINTLS )    return true;#else    return false;#endif  }  void ClientBase::startTls()  {    Tag *start = new Tag( "starttls" );    start->addAttribute( "xmlns", XMLNS_STREAM_TLS );    send( start );  }  void ClientBase::setServer( const std::string &server )  {    m_server = server;    if( m_connection )      m_connection->setServer( server );  }  void ClientBase::setClientCert( const std::string& clientKey, const std::string& clientCerts )  {    m_clientKey = clientKey;    m_clientCerts = clientCerts;  }  void ClientBase::startSASL( SaslMechanism type )  {    m_selectedSaslMech = type;    Tag *a = new Tag( "auth" );    a->addAttribute( "xmlns", XMLNS_STREAM_SASL );    switch( type )    {      case SaslMechDigestMd5:        a->addAttribute( "mechanism", "DIGEST-MD5" );        break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -