#include "cio_thread.h"
#include <QTcpSocket>
#include <QHostAddress>
#include <QEvent>
#include "cio_event.h"
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
{
pSocket = 0;
Terminating = false;
}
//-----------------------------------------------------------------------------
// Connection
//-----------------------------------------------------------------------------
const char* CIO_Thread::Socket_State()
{
if ( pSocket == 0 ) return "The socket is unitialized";
switch ( pSocket->state() )
{
return "The socket is not connected";
return "The socket is performing a host name lookup";
return "The socket has started establishing a connection";
return "A connection is established";
return "The socket is bound to an address and port (for servers)";
return "The socket is about to close (data may still be waiting to be written)";
return "For internal use only";
default:
return "The socket state is unknown";
}
}
{
if ( pSocket == 0 ) return "Nobody";
QString Peer
= "Name = " + pSocket
->peerName
() + ", ";
Peer += "Address = " + pSocket->peerAddress().toString() + ", ";
Peer
+= "Port = " + QString::number( pSocket
->peerPort
() );
return Peer;
}
void CIO_Thread::Socket_Disconnect()
{
pSocket->disconnectFromHost();
{
pSocket->waitForDisconnected();
}
pSocket = 0;
emit Termination_Emit();
}
void CIO_Thread::Disconnect_Internal( bool Notify_Buddy )
{
if ( Notify_Buddy ) Data.Command_Write_Terminate();
Terminating = true;
quit();
}
//-----------------------------------------------------------------------------
bool CIO_Thread::Connect()
{
Terminating = false;
start();
return true;
}
void CIO_Thread::Disconnect()
{
if ( !isRunning() ) return;
Termination_Message = "Disconnection by request (socket state = ";
Termination_Message += Socket_State();
Termination_Message += ").";
Disconnect_Internal( true );
}
//-----------------------------------------------------------------------------
// Connection States
//-----------------------------------------------------------------------------
CIO_Thread::Connection_States CIO_Thread::Connection_State()
{
if ( !isRunning() ) return DISCONNECTED;
if ( pSocket == 0 ) return DISCONNECTED;
if ( pSocket
->state
() == QAbstractSocket::ConnectedState ) return CONNECTED;
return CONNECTING;
}
//-----------------------------------------------------------------------------
// Data
//-----------------------------------------------------------------------------
bool CIO_Thread::DW_Terminate()
{
if ( !Data.Error_Is() ) return false;
Termination_Message = Data.Error_Get();
Disconnect_Internal( true );
return true;
}
void CIO_Thread::Data_Write()
{
while ( Data.Messages_Out_Write() );
if ( DW_Terminate() ) return;
while ( Data.XML_Out_Write() );
if ( DW_Terminate() ) return;
while ( Data.File_Out_Write() );
if ( DW_Terminate() ) return;
pSocket->flush();
}
//-----------------------------------------------------------------------------
void CIO_Thread::Path_Set( const QString& Path )
{
Data.File_Save_Path = Path;
}
{
return Data.File_Save_Path;
}
//-----------------------------------------------------------------------------
// Overrides
//-----------------------------------------------------------------------------
void CIO_Thread::run()
{
Data.Stream_Activate( pSocket );
// Start Loop
exec();
// Blow this taco stand
Socket_Disconnect();
}
void CIO_Thread
::customEvent( QEvent* event
) {
if ( Terminating ) return;
if ( pSocket == 0 ) return;
event->accept();
// Process Command
CIO_Event* pEvent = (CIO_Event*) event;
switch ( pEvent->Command )
{
case CIO_Event::WRITE_MESSAGE :
Data.Messages_Out_Add( pEvent->Text );
break;
case CIO_Event::WRITE_XML :
Data.XML_Out_Add( pEvent->xDoc );
break;
case CIO_Event::WRITE_FILE :
Data.File_Out_Add( pEvent->Text );
break;
}
Data_Write();
}
//-----------------------------------------------------------------------------
// Slots
//-----------------------------------------------------------------------------
void CIO_Thread::Slots_Connect( QTcpSocket& Socket )
{
pSocket = &Socket;
// Initialize Socket Handlers
connect
(
pSocket, SIGNAL( hostFound () ),
this , SLOT ( Socket_Host_Found() ),
Qt::QueuedConnection
);
connect
(
pSocket, SIGNAL( connected () ),
this , SLOT ( Socket_Connected() ),
Qt::QueuedConnection
);
qRegisterMetaType<QAbstractSocket::SocketError>( "QAbstractSocket::SocketError" );
connect
(
this , SLOT ( Socket_Error( ) ),
Qt::QueuedConnection
);
// Initialize Data Handlers
connect
(
pSocket, SIGNAL( readyRead() ),
this , SLOT ( Data_Read() ),
Qt::QueuedConnection
);
}
//-----------------------------------------------------------------------------
void CIO_Thread::Socket_Host_Found()
{
Host_Found_Emit();
}
void CIO_Thread::Socket_Connected()
{
emit Connected( Socket_State() );
}
void CIO_Thread::Socket_Error()
{
if ( pSocket == 0 ) return;
Termination_Message = "Socket Error - " + pSocket->errorString();
Disconnect_Internal( false );
}
//-----------------------------------------------------------------------------
void CIO_Thread::Data_Read()
{
if ( Terminating ) return;
// Process incoming data
bool Stuff = pSocket->bytesAvailable() > 0;
while ( Stuff )
{
if ( !Data.Command_Read() )
{
Termination_Message = Data.Error_Get();
Disconnect_Internal( true );
return;
}
if ( Data.Command_Is_Terminate() )
{
Termination_Message = "Peer requested termination.";
Disconnect_Internal( false );
return;
}
Stuff = pSocket->bytesAvailable() > 0;
}
// Notify your master
while ( Data.Messages_In_Present() )
{
Message_Read_Emit( Data.Messages_In_Get() );
}
while ( Data.XML_In_Present() )
{
XML_Read_Emit( Data.XML_In_Get() );
}
while ( Data.File_In_Present() )
{
File_Read_Emit( Data.File_In_Get() );
}
}
void CIO_Thread::Data_Write_Message( const QString& Message )
{
Data.Message_Write( Message );
}
Bookmarks