/**
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "commthread.h"
#include "messages.h"
//----------------------------------------------------------------------------------
CommThread::CommThread( const os::Messenger &cTarget ):os::Looper( "CommThread" )
{
m_cTarget = cTarget;
m_eState = S_STOP;
sockfd = -1;
}
void CommThread::SendReceiveLoop( void )
{
if( !SendReceiveLoop( m_eState ) )
sleep( 1 );
SendReceiveLoop();
}
/** CREDIT: BeOS DirKeeper::Idle(), see directoryview.cpp in libatheos
*
* return true if bgnet.Select() is ready for reading and
* bgnet.ReadLine() has bytes actually read into the buffer
*/
bool CommThread::SendReceiveLoop( state_t eState )
{
m_eState = eState;
switch ( m_eState )
{
case S_START:
{
if( bgnet.Select( sockfd ) == 0 ) {
printf( "(Read) Timeout occured! No data after 2.5 seconds. \n" );
return ( false );
}
static char buf[PIPE_BUF];
if( bgnet.Receive( sockfd, buf, PIPE_BUF ) > 0 ) {
os::String cName( buf );
if( !cName.empty() && !PingPong( cName ) )
SendMessage( cName );
m_eState = S_START;
return ( true );
} else {
m_eState = S_STOP;
return( false );
}
break;
}
case S_STOP:
return ( false );
}
return ( false );
}
void CommThread::HandleMessage( os::Message *pcMessage )
{
switch ( pcMessage->GetCode() )
{
case MSG_TOLOOPER_START:
{
// skip bgnet.Connect() if already connected
if( m_eState == S_START )
break;
if( (sockfd = bgnet.Connect( GetHost().c_str(), atoi( GetPort().c_str() ) )) > 0 )
{
// authenticate to the server
os::String cTempString = os::String().Format( "NICK %s\r\n", GetNickname().c_str() );
bgnet.SendAll( sockfd, cTempString.c_str(), cTempString.Length() );
cTempString.Format( "USER %s 0 * :%s\r\n", GetUsername().c_str(), GetRealname().c_str() );
bgnet.SendAll( sockfd, cTempString.c_str(), cTempString.Length() );
// start SendReceiveLoop() looper
m_eState = S_START;
SendReceiveLoop();
}
break;
}
case MSG_TOLOOPER_STOP:
{
// block bgnet.Disconnect() if not connected
if( m_eState == S_START )
{
bgnet.Disconnect( sockfd );
m_eState = S_STOP;
}
break;
}
default:
{
os::Looper::HandleMessage( pcMessage );
break;
}
}
}
// skip bgnet.Send() if not connected
void CommThread::Send( const os::String cSend )
{
if( m_eState == S_STOP )
return;
bgnet.SendAll( sockfd, cSend.c_str(), cSend.Length() );
}
// return true if ping command found
bool CommThread::PingPong( const os::String cData )
{
std::string str( cData );
if( str.at( 0 ) != ':' )
{
if( str.find( "PING", 0 ) != std::string::npos )
{
std::cout << "Ping? Pong!" << std::endl;
Send( os::String().Format( "PONG%s", str.substr( 4 ).c_str() ) );
return ( true );
}
}
return ( false );
}
// send server data to the MainView textview
void CommThread::SendMessage( const os::String& cName )
{
try
{
os::Message cMsg( MSG_FROMLOOPER_NEW_MESSAGE );
cMsg.AddString( "name", cName );
m_cTarget.SendMessage( &cMsg, m_cTarget );
}
catch( ... ) { }
}
// return true if connected to a server
bool CommThread::IsConnected( void )
{
return (m_eState == S_STOP) ? false:true;
}