/** @file GTalkBotImpl.cpp * @author Alessandro Polo * @version $Id: GTalkBotImpl.cpp 435 2009-08-21 02:15:11Z alex $ * @brief * File containing methods for the GTalkBotImpl class. * The header for this class can be found in GTalkBotImpl.h, check that file * for class description. ****************************************************************************/ /* Copyright (c) 2007-2009, WOSH - Wide Open Smart Home * by Alessandro Polo - OpenSmartHome.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the OpenSmartHome.com WOSH nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ****************************************************************************/ #include "GTalkBotImpl.h" #include #include #include #include #include #include using namespace std; using namespace wosh; using namespace gloox; ////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////// CONSTRUCTORS GTalkBotImpl::GTalkBotImpl() : wosh::ThreadWorker("wosh.Service.GTalkBot.WorkerThread") { this->gtalkListener = NULL; this->xmppJclient = NULL; this->xmppServerAddress = ""; this->xmppServerPort = 0; this->xmppAccountName = ""; this->xmppAccountPwd = ""; this->xmppAutoPresence = true; this->xmppPriority = 5; } GTalkBotImpl::~GTalkBotImpl() { if ( log != NULL ) log->log( Logger::VERBOSE, ":~GTalkBotImpl(): Destroying.." ); if ( isThreadRunning() ) { quitThread(); } } //////////////////////////////////////////////////////////////////////////////////////////////// CONSTRUCTORS ////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////// RUN THREAD void GTalkBotImpl::runThread() { if ( log != NULL ) log->log( Logger::VERBOSE, " worker:runThread(): Configuring XMPP client.." ); JID jid( this->xmppAccountName ); this->xmppJclient = new Client( jid, this->xmppAccountPwd, this->xmppServerPort ); this->xmppJclient->setServer( this->xmppServerAddress ); this->xmppJclient->setPort( this->xmppServerPort ); //clientbase // map log this->xmppJclient->logInstance().registerLogHandler( LogLevelDebug, LogAreaAll, this ); //clientbase // setup common config this->xmppJclient->disco()->setVersion( "wosh::GTalkBot", "0.1" ); //clientbase this->xmppJclient->disco()->setIdentity( "client", "wosh::GTalkBot" ); //clientbase // this->xmppJclient->setAutoPresence( this->xmppAutoPresence ); //client // this->xmppJclient->setInitialPriority( this->xmppPriority ); //client // register callbacks this->xmppJclient->registerConnectionListener( this ); this->xmppJclient->registerMessageHandler( this ); this->xmppJclient->registerPresenceHandler( this ); this->xmppJclient->registerSubscriptionHandler( this ); if ( log != NULL ) log->log( Logger::VERBOSE, " worker:runThread(): Connecting to XMPP Server.." ); // connect SYNCH bool connected = this->xmppJclient->connect( false ); if ( !connected ) { if ( log != NULL ) log->log( Logger::CRITICAL, " worker:runThread(): Can't connect to XMPP Server.." ); this->xmppJclient->disconnect(); delete this->xmppJclient; this->xmppJclient = NULL; if ( log != NULL ) log->log( Logger::CRITICAL, " worker:runThread(): Exiting (FAILURE)" ); return; } if ( log != NULL ) log->log( Logger::VERBOSE, " worker:runThread(): Entering Loop.." ); ConnectionError ce = ConnNoError; while( ce == ConnNoError ) { ce = this->xmppJclient->recv( 2 ); if ( !this->running ) break; } ce = this->xmppJclient->recv( 1 ); if ( log != NULL ) log->log( Logger::VERBOSE, " worker:runThread(): Exited Loop, Disconnecting.." ); this->xmppJclient->disconnect(); ce = this->xmppJclient->recv( 1 ); ce = this->xmppJclient->recv( 2 ); if ( log != NULL ) log->log( Logger::VERBOSE, " worker:runThread(): Freeing resources.." ); ce = this->xmppJclient->recv( 1 ); delete this->xmppJclient; this->xmppJclient = NULL; // log->log( Logger::VERBOSE, " worker:runThread(): Exiting run().." ); } ////////////////////////////////////////////////////////////////////////////////////////////////// RUN THREAD ////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////// LogHandler INTERFACE void GTalkBotImpl::handleLog( LogLevel level, LogArea area, const std::string& message ) { (void)level; (void)area; (void)message; // log->log( Logger::VERBOSE, " worker:handleLog(): %d, area: %d, %s", level, area, message.c_str() ); //printf("GTalkBotImpl///log: level: %d, area: %d, %s\n", level, area, message.c_str() ); } //////////////////////////////////////////////////////////////////////////////////////// LogHandler INTERFACE ////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// ConnectionListener INTERFACE void GTalkBotImpl::onConnect() { if ( log != NULL ) log->log( Logger::VERBOSE, " worker:onConnect(): Connection estabilished!" ); } void GTalkBotImpl::onDisconnect( gloox::ConnectionError e ) { if ( log != NULL ) { log->log( Logger::CRITICAL, " worker:onDisconnect(): Disconnected [error %i]!", (int)e ); if ( (int)e == 16 ) log->log( Logger::WARNING, "Account Blocked? try Accessing manualy to restore", (int)e ); } } bool GTalkBotImpl::onTLSConnect( const gloox::CertInfo& info ) { (void)info; if ( log != NULL ) log->log( Logger::VERBOSE, " worker:onTLSConnect(): Secure Connection estabilished!" ); return true; } //////////////////////////////////////////////////////////////////////////////// ConnectionListener INTERFACE ////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// MessageHandler INTERFACE void GTalkBotImpl::handleMessage( gloox::Stanza* stanza, gloox::MessageSession* session ) { (void)session; if ( stanza == NULL ) return; if ( log != NULL ) { if ( log->getLevel() == Logger::VERBOSE ) log->log( Logger::VERBOSE, " worker:handleMessage(): %s by %s", stanza->body().c_str(), stanza->from().bare().c_str() ); } if ( this->xmppJclient == NULL ) { if ( log != NULL ) log->log( Logger::CRITICAL, " worker:handleMessage(): xmppJclient is NULL!" ); return; } if ( stanza->error() != gloox::StanzaErrorUndefined ) { if ( log != NULL ) log->log( Logger::WARNING, " worker:handleMessage(): Stanza Error #%i ''", (int)stanza->error(), stanza->errorText().c_str() ); return; } if ( this->gtalkListener != NULL ) { this->gtalkListener->gtalkbot_Message( this, stanza->from().bare(), stanza->body() ); } // Stanza *s = Stanza::createMessageStanza( stanza->from().full(), "got 2it! :" + stanza->body() ); // this->xmppJclient->send( s ); } //////////////////////////////////////////////////////////////////////////////////// MessageHandler INTERFACE ////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////// PresenceHandler INTERFACE void GTalkBotImpl::handlePresence( gloox::Stanza* stanza ) { if ( stanza == NULL ) return; if ( log != NULL ) log->log( Logger::VERBOSE, " worker:handlePresence(): status of %s is '%s' !", stanza->from().full().c_str(), stanza->status().c_str() ); // btw.. this is periodic if ( this->xmppAccountName == stanza->from().bare() ) { // mmh.. great i hope so! // we don't notify that.. return; } if ( this->gtalkListener == NULL ) return; int status = -1; // switch( stanza->show() ) { switch( stanza->presence() ) { case gloox::PresenceUnavailable: status = 0; break; case gloox::PresenceUnknown: status = 0; break; case gloox::PresenceXa: status = 0; break; default: status = 1; break; } ///@bug offline not handled! this->gtalkListener->gtalkbot_UserStatus(this, stanza->from().bare(), status ); } /////////////////////////////////////////////////////////////////////////////////// PresenceHandler INTERFACE ////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// SubscriptionHandler INTERFACE void GTalkBotImpl::handleSubscription( gloox::Stanza* stanza ) { log->log( Logger::VERBOSE, " worker:handleSubscription(): User %s trying to join chat!", stanza->from().full().c_str() ); // sort of SECURIY WARNING ! } /////////////////////////////////////////////////////////////////////////////// SubscriptionHandler INTERFACE ////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool GTalkBotImpl::sendMessage( const std::string& user, const std::string& message ) { if ( !isThreadRunning() ) return false; if ( this->xmppJclient == NULL ) return false; Stanza *s = Stanza::createMessageStanza( user, message ); this->xmppJclient->send( s ); log->log( Logger::VERBOSE, " worker:sendMessage(): sending '%s' to %s..", message.c_str(), user.c_str() ); return true; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////// void GTalkBotImpl::setGTalkBotListener( IGTalkBotListener* listener ) { this->gtalkListener = listener; } bool GTalkBotImpl::setServer( const std::string& address, int port ) { if ( isThreadRunning() ) return false; this->xmppServerAddress = address; this->xmppServerPort = port; return true; } bool GTalkBotImpl::setServerAddress( const std::string& address ) { if ( isThreadRunning() ) return false; this->xmppServerAddress = address; return true; } bool GTalkBotImpl::setServerPort( int port ) { if ( isThreadRunning() ) return false; this->xmppServerPort = port; return true; } bool GTalkBotImpl::setAccount( const std::string& name, const std::string& pwd ) { if ( isThreadRunning() ) return false; this->xmppAccountName = name; this->xmppAccountPwd = pwd; return true; } bool GTalkBotImpl::setAccountUserName( const std::string& name ) { if ( isThreadRunning() ) return false; this->xmppAccountName = name; return true; } bool GTalkBotImpl::setAccountUserPassword( const std::string& pwd ) { if ( isThreadRunning() ) return false; this->xmppAccountPwd = pwd; return true; } bool GTalkBotImpl::setAutoPresence( bool value ) { if ( isThreadRunning() ) return false; this->xmppAutoPresence = value; return true; } bool GTalkBotImpl::setPriority( int value ) { if ( isThreadRunning() ) return false; this->xmppPriority = value; return true; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////