Major Update:

- Implemented global var DebugLevel
- Update LogCore to check DebugLevel
- Added many log messages and standadised all log messages
- Further improved validation checks on all methods
- Updated SelectCore, only remove SelectHandle from list during Test()
- Close Handles in SelectableCore destructor
Bug fixes:
- Non-blocking Client Socket Connection now working correctly
- Remove FD from Select lists at the correct time
This commit is contained in:
Charl Wentzel
2016-05-26 15:03:13 +02:00
parent 9ace97c1a3
commit c01c8f5e9b
8 changed files with 532 additions and 235 deletions

View File

@@ -17,6 +17,11 @@
//---------------------------------------------------------------------------
extern char ProcessName[];
extern char LogStr[]; // Access to global temporary log messages string
//---------------------------------------------------------------------------
// Life cycle
CFunctionCore::CFunctionCore( const char * FunctionName )
{
@@ -31,6 +36,10 @@ CFunctionCore::CFunctionCore( const char * FunctionName )
// IO Functions
FirstIO = NULL;
// Report status
sprintf( LogStr, "Function '%s' - Created", FunctionName );
LogMessage( ProcessName, dlLow, LogStr );
}
//---------------------------------------------------------------------------
@@ -39,11 +48,6 @@ CFunctionCore::~CFunctionCore()
TLocalIO * NextIO = NULL;
TLinkedIO * NextLinkedIO = NULL;
// Destroy pointers
if (Name) {
free( Name );
}
// Destroy IO
while (FirstIO)
{
@@ -78,6 +82,16 @@ CFunctionCore::~CFunctionCore()
free( FirstIO );
FirstIO = NextIO;
}
// Report status
sprintf( LogStr, "Function '%s' - Destroyed", Name );
LogMessage( ProcessName, dlLow, LogStr );
// Destroy Name
if (Name) {
free( Name );
}
}
//---------------------------------------------------------------------------
@@ -105,56 +119,16 @@ TLocalIO * CFunctionCore::AddLocalIO( const char * IOName )
// Set Name
(*LocalIO)->Name = (char*)malloc( strlen(IOName)+1 );
strcpy( (*LocalIO)->Name, IOName );
// Log Event
sprintf( LogStr, "Local IO '%s' - Created", IOName );
LogMessage( Name, dlMedium, LogStr );
}
return *LocalIO;
}
//---------------------------------------------------------------------------
// Manual Data Input/Output
int CFunctionCore::Input( const char * IOName, const char * Buffer, int MaxLen )
{
TLocalIO * LocalIO = NULL;
// Validate
if (!IOName || !Buffer) {
return 0;
}
else if (MaxLen == -1) {
MaxLen = strlen( Buffer );
}
// Get IO
if (!(LocalIO = GetLocalIO( IOName ))) {
return 0;
}
// Do something and acknowledge size received
return MaxLen;
}
//---------------------------------------------------------------------------
int CFunctionCore::Output( const char * IOName, const char * Buffer, int Len )
{
TLocalIO * LocalIO = NULL;
// Validate
if (!IOName || !Buffer) {
return 0;
} else if (Len == -1) {
Len = strlen( Buffer );
}
// Get IO
if (!(LocalIO = GetLocalIO( IOName ))) {
return 0;
}
// Do something and acknowledge size received
return Len;
}
//---------------------------------------------------------------------------
// Automated Data Input/Output
bool CFunctionCore::AddInput( const char * IOName, CFunctionCore * OutFunction, const char * OutputName )
{
@@ -162,7 +136,7 @@ bool CFunctionCore::AddInput( const char * IOName, CFunctionCore * OutFunction,
TLinkedIO ** LinkedIO = NULL;
// Get IO
if (!(LocalIO = GetLocalIO( IOName ))) {
if (!OutFunction || !OutFunction || !(LocalIO = GetLocalIO( IOName ))) {
return false;
}
@@ -183,6 +157,10 @@ bool CFunctionCore::AddInput( const char * IOName, CFunctionCore * OutFunction,
(*LinkedIO)->Function = OutFunction;
(*LinkedIO)->IOName = (char*)malloc( strlen(OutputName)+1 );
strcpy( (*LinkedIO)->IOName, OutputName );
// Log Event
sprintf( LogStr, "Input Linked - '%s'/'%s' <-- '%s'/'%s'", Name, IOName, OutFunction->GetName(), OutputName );
LogMessage( Name, dlMedium, LogStr );
}
return true;
@@ -195,7 +173,7 @@ bool CFunctionCore::AddOutput( const char * IOName, CFunctionCore * InFunction,
TLinkedIO ** LinkedIO = NULL;
// Get IO
if (!(LocalIO = GetLocalIO( IOName ))) {
if (!InFunction || !InputName || !(LocalIO = GetLocalIO( IOName ))) {
return false;
}
@@ -216,10 +194,73 @@ bool CFunctionCore::AddOutput( const char * IOName, CFunctionCore * InFunction,
(*LinkedIO)->Function = InFunction;
(*LinkedIO)->IOName = (char*)malloc( strlen(InputName)+1 );
strcpy( (*LinkedIO)->IOName, InputName );
}
// Log Event
sprintf( LogStr, "Output Linked - '%s'/'%s' --> '%s'/'%s'", Name, IOName, InFunction->GetName(), InputName );
LogMessage( Name, dlMedium, LogStr );
}
return true;
}
//---------------------------------------------------------------------------
// Manual Data Input/Output
int CFunctionCore::Input( const char * IOName, const char * Data, int MaxLen )
{
TLocalIO * LocalIO = NULL;
// Validate
if (!IOName || !Data) {
return 0;
}
else if (MaxLen == -1) {
MaxLen = strlen( Data );
}
// Get IO
if (!(LocalIO = GetLocalIO( IOName )))
{
// Log event
sprintf( LogStr, "%s: Local IO '%s' - Input rejected, Local IO not found", Name, IOName );
LogMessage( Name, dlMedium, LogStr );
return 0;
}
// Log event
sprintf( LogStr, "%s: Local IO '%s' - IN:", Name, IOName );
ShowOutput( LogStr, dlMedium, OUT_NORMAL, Data, MaxLen );
// Return processed bytes
return MaxLen;
}
//---------------------------------------------------------------------------
int CFunctionCore::Output( const char * IOName, const char * Data, int Len )
{
TLocalIO * LocalIO = NULL;
// Validate
if (!IOName || !Data) {
return 0;
} else if (Len == -1) {
Len = strlen( Data );
}
// Get IO
if (!(LocalIO = GetLocalIO( IOName )))
{
// Log Event
sprintf( LogStr, "%s: Local IO '%s' - Output rejected, Local IO not found", Name, IOName );
LogMessage( Name, dlMedium, LogStr );
return 0;
}
// Log event
sprintf( LogStr, "%s: Local IO '%s' - OUT:", Name, IOName );
ShowOutput( LogStr, dlMedium, OUT_NORMAL, Data, Len );
// Return processed bytes
return Len;
}
//---------------------------------------------------------------------------

View File

@@ -68,12 +68,15 @@ public:
CFunctionCore( const char * ObjectName );
virtual ~CFunctionCore();
// Miscellaneous
inline const char * GetName() { return Name; };
// Manage IOs
virtual TLocalIO * AddLocalIO( const char * IOName );
// Manual Data Input/Output
virtual int Input( const char * IOName, const char * Buffer, int MaxLen = -1 );
virtual int Output( const char * IOName, const char * Buffer, int Len = -1 );
virtual int Input( const char * IOName, const char * Data, int MaxLen = -1 );
virtual int Output( const char * IOName, const char * Data, int Len = -1 );
// Automated Data Input/Output
virtual bool AddInput( const char * IOName, CFunctionCore * OutFunction, const char * OutputName );

View File

@@ -17,16 +17,22 @@
//---------------------------------------------------------------------------
// Global vars
char ProcessName[20] = "Connect";
EDebugLevel DebugLevel = dlLow;
char LogStr[1000]; // Temporary var to create log messages, globally available to save on memory operations
//---------------------------------------------------------------------------
bool LogMessage( const char * Heading, const char *Message )
bool LogMessage( const char * Heading, EDebugLevel Level, const char *Message )
{
// Validate values
if (!Message)
return false;
// Check debug level
if (Level > DebugLevel) {
return true;
}
// Show normal output
if (!Heading) {
printf( "%s\n", Message );
@@ -38,7 +44,7 @@ bool LogMessage( const char * Heading, const char *Message )
}
//---------------------------------------------------------------------------
bool ShowOutput( const char * Heading, const short Show, const char * Buffer, int Len )
bool ShowOutput( const char * Heading, EDebugLevel Level, const short Show, const char * Buffer, int Len )
{
// Validate values
if (!Buffer)
@@ -46,6 +52,11 @@ bool ShowOutput( const char * Heading, const short Show, const char * Buffer, in
if (Len == -1)
Len = strlen( Buffer );
// Check debug level
if (Level > DebugLevel) {
return true;
}
// Show Hex output
if (Show & OUT_HEX) {
printf( "%s [%d]: ", Heading, Len );

View File

@@ -25,9 +25,13 @@ const short
//---------------------------------------------------------------------------
bool LogMessage( const char * Heading, const char * Message );
typedef enum { dlNone = 0, dlLow = 1, dlMedium = 2, dlHigh = 3 } EDebugLevel;
bool ShowOutput( const char * Heading, const short Show, const char * Buffer, int Len = -1 );
//---------------------------------------------------------------------------
bool LogMessage( const char * Heading, EDebugLevel Level, const char * Message );
bool ShowOutput( const char * Heading, EDebugLevel Level, const short Show, const char * Buffer, int Len = -1 );
//---------------------------------------------------------------------------

View File

@@ -6,12 +6,20 @@
*/
// redA Libraries
#include "SelectableCore.h"
#include "TimingCore.h"
#include "LogCore.h"
// Standard C/C++ Libraries
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "SelectableCore.h"
//---------------------------------------------------------------------------
extern char ProcessName[];
extern char LogStr[]; // Access to global temporary log messages string
//---------------------------------------------------------------------------
@@ -30,12 +38,27 @@ CSelect::CSelect( long SelectTimeout )
// Set Timeout
SetInterval( &Timeout, SelectTimeout );
// Show status
LogMessage( ProcessName, dlMedium, "Select - Created" );
}
//---------------------------------------------------------------------------
// Destroy Select
CSelect::~CSelect()
{
TSelectHandle * NextHandle;
// Destroy handles
while (FirstHandle)
{
NextHandle = FirstHandle->Next;
free( FirstHandle );
FirstHandle = NextHandle;
}
// Show status
LogMessage( ProcessName, dlMedium, "Select - Destroyed" );
return;
}
//---------------------------------------------------------------------------
@@ -75,15 +98,23 @@ void CSelect::Add( int FD, bool Read, bool Write, CSelectableCore * Function )
}
// Add Read select
if (Read) {
if (Read && !(*Handle)->Read) {
(*Handle)->Read = true;
FD_SET( FD, &ReadTestFDS );
// Log event
sprintf( LogStr, "FD [%d] - Add Read", FD );
LogMessage( "Select", dlMedium, LogStr );
}
// Add Write Select
if (Write) {
if (Write && !(*Handle)->Write) {
(*Handle)->Write = true;
FD_SET( FD, &WriteTestFDS );
// Log event
sprintf( LogStr, "FD [%d] - Add Write", FD );
LogMessage( "Select", dlMedium, LogStr );
}
// Check Maximum File Handle
@@ -95,8 +126,6 @@ void CSelect::Add( int FD, bool Read, bool Write, CSelectableCore * Function )
void CSelect::Remove( int FD, bool Read, bool Write )
{
TSelectHandle ** Handle = NULL;
TSelectHandle * NextHandle = NULL;
int TestFD = 0;
// Check if Handle already exists
Handle = &FirstHandle;
@@ -108,42 +137,34 @@ void CSelect::Remove( int FD, bool Read, bool Write )
return;
// Remove from set for select read check
if (Read) {
if (Read && (*Handle)->Read) {
(*Handle)->Read = false;
FD_CLR( FD, &ReadTestFDS);
// Log event
sprintf( LogStr, "FD [%d] - Remove Read", FD );
LogMessage( "Select", dlMedium, LogStr );
}
// Remove from set for select write check
if (Write) {
if (Write && (*Handle)->Write) {
(*Handle)->Write = false;
FD_CLR( FD, &WriteTestFDS);
}
// Check if to remove from list
if (!(*Handle)->Read && !(*Handle)->Write)
{
// Remove from list
NextHandle = (*Handle)->Next;
free( *Handle );
*Handle = NextHandle;
// Update Maximum Test FD
if (FD == MaxFD-1) {
for (TestFD = MaxFD-1; TestFD >= 0; TestFD--) {
if (FD_ISSET( TestFD, &ReadTestFDS ) || FD_ISSET( TestFD, &WriteTestFDS )) {
break;
}
}
MaxFD = TestFD+1;
}
// Log event
sprintf( LogStr, "FD [%d] - Remove Write", FD );
LogMessage( "Select", dlMedium, LogStr );
}
// Handle will be removed in Test() if both Read & Write flags are false
}
//---------------------------------------------------------------------------
bool CSelect::Test()
{
TSelectHandle * Handle = NULL;
int Events = 0;
TSelectHandle * Handle = NULL;
TSelectHandle ** HandlePtr = NULL;
int TestFD = 0;
int Events = 0;
// Set Test sets
ReadFDS = ReadTestFDS;
@@ -153,7 +174,7 @@ bool CSelect::Test()
Events = select( MaxFD, &ReadFDS, &WriteFDS, (fd_set*)NULL, &Timeout );
if (Events < 0)
{
printf( "Select operation failed (%s)\n", strerror(errno) );
LogMessage( "Select", dlMedium, "Select operation failed" );
return false;
}
@@ -161,16 +182,42 @@ bool CSelect::Test()
Handle = FirstHandle;
while (Handle)
{
// Check read Event
if (FD_ISSET( Handle->FD, &ReadFDS ) && Handle->Function) {
Handle->Function->Read( Handle->FD );
}
// Check if to remove from list
if (!Handle->Read && !Handle->Write)
{
// Update Maximum Test FD
if (Handle->FD == MaxFD-1) {
for (TestFD = MaxFD-1; TestFD >= 0; TestFD--) {
if (FD_ISSET( TestFD, &ReadTestFDS ) || FD_ISSET( TestFD, &WriteTestFDS )) {
break;
}
}
MaxFD = TestFD+1;
}
// Check Write Event
if (FD_ISSET( Handle->FD, &WriteFDS ) && Handle->Function) {
Handle->Function->Write( Handle->FD );
}
// Remove from list
HandlePtr = &FirstHandle;
while (*HandlePtr && (*HandlePtr != Handle))
HandlePtr = &((*HandlePtr)->Next);
*HandlePtr = (*HandlePtr)->Next;
// Destroy and go to next
free( Handle );
Handle = *HandlePtr;
continue;
}
else
{
// Check read Event
if (FD_ISSET( Handle->FD, &ReadFDS ) && Handle->Function) {
Handle->Function->Read( Handle->FD );
}
// Check Write Event
if (FD_ISSET( Handle->FD, &WriteFDS ) && Handle->Function) {
Handle->Function->Write( Handle->FD );
}
}
// Next
Handle = Handle->Next;
}

View File

@@ -7,7 +7,6 @@
// redA Libraries
#include "SelectableCore.h"
#include "TimingCore.h"
#include "LogCore.h"
@@ -31,6 +30,12 @@
//---------------------------------------------------------------------------
//extern char ProcessName[];
extern EDebugLevel DebugLevel;
extern char LogStr[]; // Access to global temporary log messages string
//---------------------------------------------------------------------------
CSelectableCore::CSelectableCore( const char * Name, CSelect * Selector ) :
CFunctionCore( Name )
{
@@ -47,7 +52,13 @@ CSelectableCore::~CSelectableCore()
THandle * NextHandle = NULL;
// Destroy File Handles
while (FirstHandle) {
while (FirstHandle)
{
// Close handle if open
if ((FirstHandle->State == csOpen) || (FirstHandle->State == csWaitingtoOpen)) {
Close( FirstHandle, true );
}
NextHandle = FirstHandle->Next;
DestroyHandle( FirstHandle );
FirstHandle = NextHandle;
@@ -79,6 +90,10 @@ THandle * CSelectableCore::CreateHandle( const char * HandleName, bool CreateIO
// Set File Descriptor
(*Handle)->FD = -1;
// Log event
sprintf( LogStr, "Handle '%s' - Created", HandleName );
LogMessage( Name, dlMedium, LogStr );
}
// Create Matching IO point
@@ -109,6 +124,10 @@ bool CSelectableCore::RemoveHandle( THandle * Handle )
*HandlePtr = (*HandlePtr)->Next;
}
// Log event
sprintf( LogStr, "Handle '%s' - Removed", Handle->Name );
LogMessage( Name, dlMedium, LogStr );
// Destroy Child handle
DestroyHandle( Handle );
return true;
@@ -164,6 +183,10 @@ bool CSelectableCore::SetPortHandle( THandle * Handle, const char * FileName )
Handle->FileName = (char*)malloc( strlen(FileName)+1 );
strcpy( Handle->FileName, FileName );
// Log event
sprintf( LogStr, "Handle '%s' - Set as Port [%s]", Handle->Name, FileName );
LogMessage( Name, dlMedium, LogStr );
return true;
}
//---------------------------------------------------------------------------
@@ -189,6 +212,10 @@ bool CSelectableCore::SetSocketHandle( THandle * Handle, EConnectType Type, con
strcpy( Handle->Address, Address );
Handle->PortNo = PortNo;
// Log event
sprintf( LogStr, "Handle '%s' - Set as %s [%s:%d]", Handle->Name, ConnectTypeName[Type], Address, PortNo );
LogMessage( Name, dlMedium, LogStr );
return true;
}
//---------------------------------------------------------------------------
@@ -214,6 +241,10 @@ bool CSelectableCore::ClearHandle( THandle * Handle )
// Reset Parameters
Handle->Type = ctNone;
// Log event
sprintf( LogStr, "Handle '%s' - Set as None", Handle->Name );
LogMessage( Name, dlMedium, LogStr );
return true;
}
//---------------------------------------------------------------------------
@@ -270,7 +301,9 @@ int CSelectableCore::OpenPort( THandle * Handle )
// Check if port exits
if (access( Handle->FileName, F_OK ) != 0)
{
printf( "Port: %s -> Could not find port\n", Handle->FileName );
// Log event
sprintf( LogStr, "Handle '%s' - Port not found [%s]", Handle->Name, Handle->FileName );
LogMessage( Name, dlMedium, LogStr );
return -1;
}
@@ -278,13 +311,23 @@ int CSelectableCore::OpenPort( THandle * Handle )
Handle->FD = open( Handle->FileName, O_RDWR );
if (Handle->FD == -1)
{
printf( "Port: %s -> Could not open port\n", Handle->FileName );
// Log event
sprintf( LogStr, "Handle '%s' - Could not open Port [%s]", Handle->Name, Handle->FileName );
LogMessage( Name, dlMedium, LogStr );
return -1;
}
// Confirm open
// Log Event
sprintf( LogStr, "Handle '%s' - Port opened [%s]", Handle->Name, Handle->FileName );
LogMessage( Name, dlMedium, LogStr );
// Add to Select Lists
if (Select) {
Select->Add( Handle->FD, true, false, this );
}
// Set state
Handle->State = csOpen;
printf( "Port: %s -> Port opened\n", Handle->Name );
return Handle->FD;
}
@@ -320,7 +363,11 @@ int CSelectableCore::OpenServerSocket( THandle * Handle )
// Create socket
if ((Handle->FD = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf( "Server Socket: %s [%d] -> Failed to create server socket (%s)\n", Handle->Address, Handle->PortNo, strerror(errno) );
// Log Event
sprintf( LogStr, "Handle '%s' - Failed to create Server socket [%s:%d] (%s)", Handle->Name, Handle->Address, Handle->PortNo, strerror(errno) );
LogMessage( Name, dlMedium, LogStr );
// Set state
Handle->State = csFailed;
return -1;
};
@@ -329,7 +376,11 @@ int CSelectableCore::OpenServerSocket( THandle * Handle )
if ((setsockopt( Handle->FD, SOL_SOCKET, SO_LINGER, &ServerLinger_opt, sizeof(ServerLinger_opt)) == -1) ||
(setsockopt( Handle->FD, SOL_SOCKET, SO_REUSEADDR, &Reuse_opt, sizeof(Reuse_opt)) == -1))
{
printf( "Server Socket: %s [%d] -> Could not set socket options (%s)\n", Handle->Address, Handle->PortNo, strerror(errno) );
// Log Event
sprintf( LogStr, "Handle '%s' - Could not set socket options [%s:%d] (%s)", Handle->Name, Handle->Address, Handle->PortNo, strerror(errno) );
LogMessage( Name, dlMedium, LogStr );
// Set state
Handle->State = csFailed;
return -1;
}
@@ -341,7 +392,11 @@ int CSelectableCore::OpenServerSocket( THandle * Handle )
(setsockopt( Handle->FD, SOL_TCP, TCP_KEEPCNT, &TCPcnt_opt, sizeof(TCPcnt_opt)) == -1) ||
(setsockopt( Handle->FD, SOL_TCP, TCP_KEEPINTVL, &TCPint_opt, sizeof(TCPint_opt)) == -1) ))
{
printf( "Server Socket: %s [%d] -> Could not set socket keepalive options (%s)\n", Handle->Address, Handle->PortNo, strerror(errno) );
// Log Event
sprintf( LogStr, "Handle '%s' - Could not set KeepAlive options [%s:%d] (%s)", Handle->Name, Handle->Address, Handle->PortNo, strerror(errno) );
LogMessage( Name, dlMedium, LogStr );
// Set state
Handle->State = csFailed;
return -1;
}
@@ -353,8 +408,13 @@ int CSelectableCore::OpenServerSocket( THandle * Handle )
// Bind socket
if (bind( Handle->FD, (struct sockaddr *)&address, addr_len ) < 0)
{
printf( "Server Socket: %s [%d] -> Failed to bind server to socket (%s)\n", Handle->Address, Handle->PortNo, strerror(errno) );
// Log Event
sprintf( LogStr, "Handle '%s' - Failed to bind Server socket [%s:%d] (%s)", Handle->Name, Handle->Address, Handle->PortNo, strerror(errno) );
LogMessage( Name, dlMedium, LogStr );
// Set state
close( Handle->FD );
Handle->FD = -1;
Handle->State = csFailed;
return -1;
};
@@ -362,15 +422,28 @@ int CSelectableCore::OpenServerSocket( THandle * Handle )
// Create que for 5 connections
if (listen( Handle->FD, 5 ) < 0)
{
printf( "Server Socket: %s [%d] -> Failed to create server socket listen que (%s)\n", Handle->Address, Handle->PortNo, strerror(errno) );
// Log Event
sprintf( LogStr, "Handle '%s' - Failed to listen on Server socket [%s:%d] (%s)", Handle->Name, Handle->Address, Handle->PortNo, strerror(errno) );
LogMessage( Name, dlMedium, LogStr );
// Set state
close( Handle->FD );
Handle->FD = -1;
Handle->State = csFailed;
return -1;
};
};
// Server open
// Log Event
sprintf( LogStr, "Handle '%s' - Server binded and listening [%s:%d]", Handle->Name, Handle->Address, Handle->PortNo );
LogMessage( Name, dlMedium, LogStr );
// Add to Select Lists
if (Select) {
Select->Add( Handle->FD, true, true, this );
}
// Set state
Handle->State = csOpen;
printf( "Server Socket: %s [%d] -> Socket binded and listening\n", Handle->Address, Handle->PortNo );
return Handle->FD;
}
//---------------------------------------------------------------------------
@@ -398,9 +471,12 @@ int CSelectableCore::OpenRemoteClientSocket( THandle * Handle )
if ((ClientFD = accept( Handle->FD, (struct sockaddr *)&address, &addr_len)) == -1)
{
if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
printf( "Remote Socket: %s [*] -> Failed to accept blocking connection (%s)\n", Handle->Address, strerror(errno) );
sprintf( LogStr, "Handle '%s' - Server failed to accept blocking connection (%s)", Handle->Name, strerror(errno) );
else
printf( "Remote Socket: %s [*] -> Failed to accept connection (%s)\n", Handle->Address, strerror(errno) );
sprintf( LogStr, "Handle '%s' - Server failed to accept connection (%s)", Handle->Name, strerror(errno) );
// Log Event
LogMessage( Name, dlMedium, LogStr );
return -1;
}
@@ -432,17 +508,34 @@ int CSelectableCore::OpenRemoteClientSocket( THandle * Handle )
(*RemoteClient)->Parent = Handle;
(*RemoteClient)->State = csWaitingtoOpen;
printf( "Remote Socket: %s -> Server accepted connection from client (%s)\n", Handle->Address, ClientAddress );
(*RemoteClient)->Address = (char*)malloc( strlen(ClientAddress)+1 );
strcpy( (*RemoteClient)->Address, ClientAddress );
// Log Event
sprintf( LogStr, "Handle '%s' - Server accepted Remote Client connection [%s]", Handle->Name, ClientAddress );
LogMessage( Name, dlMedium, LogStr );
// Add to Select Lists
if (Select) {
Select->Add( (*RemoteClient)->FD, true, true, this );
}
return (*RemoteClient)->FD;
}
else if (Handle->Type == ctRemoteClient)
{
// Check state
if (Handle->State == csOpen) {
if (Handle->State == csOpen)
{
// Already open
return Handle->FD;
}
else if (Handle->State == csWaitingtoOpen) {
else if (Handle->State == csWaitingtoOpen)
{
// Log Event
sprintf( LogStr, "Handle '%s' - Remote Client connection open [%s]", Handle->Name, Handle->Address );
LogMessage( Name, dlMedium, LogStr );
// Update state
Handle->State = csOpen;
return Handle->FD;
@@ -468,32 +561,42 @@ int CSelectableCore::OpenClientSocket( THandle * Handle )
// Already open
return Handle->FD;
}
else if (Handle->State == csWaitingtoOpen) {
// Update state
Handle->State = csOpen;
return Handle->FD;
}
// Create File descriptor
if ((Handle->FD = socket( AF_INET, SOCK_STREAM, 0 )) < 0)
if (Handle->State != csWaitingtoOpen)
{
printf( "Client Socket: %s [*] -> Failed to create Client Socket (%s)\n", Handle->Address, strerror(errno) );
return -1;
};
// Create File descriptor
if ((Handle->FD = socket( AF_INET, SOCK_STREAM, 0 )) < 0)
{
// Log Event
sprintf( LogStr, "Handle '%s' - Failed to create Client socket [%s:%d] (%s)", Handle->Name, Handle->Address, Handle->PortNo, strerror(errno) );
LogMessage( Name, dlMedium, LogStr );
// Set Non blocking open
int flags = fcntl( Handle->FD, F_GETFL, 0 );
fcntl( Handle->FD, F_SETFL, O_NONBLOCK|flags );
// Set Status
Handle->State = csFailed;
return -1;
};
// Configure TCP keep alive settings
if (Handle->KeepAlive &&
((setsockopt( Handle->FD, SOL_SOCKET, SO_KEEPALIVE, &KeepAlive_opt, sizeof(KeepAlive_opt)) == -1) ||
(setsockopt( Handle->FD, SOL_TCP, TCP_KEEPIDLE, &TCPidle_opt, sizeof(TCPidle_opt)) == -1) ||
(setsockopt( Handle->FD, SOL_TCP, TCP_KEEPCNT, &TCPcnt_opt, sizeof(TCPcnt_opt)) == -1) ||
(setsockopt( Handle->FD, SOL_TCP, TCP_KEEPINTVL, &TCPint_opt, sizeof(TCPint_opt)) == -1) ))
{
printf( "Client Socket: %s -> Could not set socket keepalive options (%s)\n", Handle->Address, strerror(errno) );
return -1;
// Set Non blocking open
int flags = fcntl( Handle->FD, F_GETFL, 0 );
fcntl( Handle->FD, F_SETFL, O_NONBLOCK|flags );
// Configure TCP keep alive settings
if (Handle->KeepAlive &&
((setsockopt( Handle->FD, SOL_SOCKET, SO_KEEPALIVE, &KeepAlive_opt, sizeof(KeepAlive_opt)) == -1) ||
(setsockopt( Handle->FD, SOL_TCP, TCP_KEEPIDLE, &TCPidle_opt, sizeof(TCPidle_opt)) == -1) ||
(setsockopt( Handle->FD, SOL_TCP, TCP_KEEPCNT, &TCPcnt_opt, sizeof(TCPcnt_opt)) == -1) ||
(setsockopt( Handle->FD, SOL_TCP, TCP_KEEPINTVL, &TCPint_opt, sizeof(TCPint_opt)) == -1) ))
{
// Log Event
sprintf( LogStr, "Handle %s - Could not set KeepAlive options [%s:%d] (%s)", Handle->Name, Handle->Address, Handle->PortNo, strerror(errno) );
LogMessage( Name, dlMedium, LogStr );
// Set State
close( Handle->FD );
Handle->FD = -1;
Handle->State = csFailed;
return -1;
}
}
// Declare address
@@ -504,13 +607,28 @@ int CSelectableCore::OpenClientSocket( THandle * Handle )
if (!connect( Handle->FD, (struct sockaddr *)&address, addr_len ))
{
sprintf( LogStr, "Handle %s - Client connected [%s:%d]", Handle->Name, Handle->Address, Handle->PortNo );
LogMessage( Name, dlMedium, LogStr );
// Add to Select Lists
if (Select) {
Select->Add( Handle->FD, true, true, this );
}
// Set status
Handle->State = csOpen;
return Handle->FD;
}
else if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
else if ((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINPROGRESS) || (errno == EALREADY))
{
printf( "Client Socket: %s -> Client waiting to connect (%s)\n", Handle->Address, strerror(errno) );
// Log Event
sprintf( LogStr, "Handle '%s' - Client waiting to connect [%s:%d] (%s)", Handle->Name, Handle->Address, Handle->PortNo, strerror(errno) );
LogMessage( Name, dlMedium, LogStr );
// Add to Select Lists
if (Select) {
Select->Add( Handle->FD, true, true, this );
}
// Set status
Handle->State = csWaitingtoOpen;
@@ -518,13 +636,19 @@ int CSelectableCore::OpenClientSocket( THandle * Handle )
}
else
{
printf( "Client Socket: %s -> Client failed to connect (%s)\n", Handle->Address, strerror(errno) );
// Log Event
sprintf( LogStr, "Handle '%s' - Client could not connect [%s:%d] (%s)", Handle->Name, Handle->Address, Handle->PortNo, strerror(errno) );
LogMessage( Name, dlMedium, LogStr );
// Set status
Handle->State = csFailed;
// Remove from Select List
if (Select) {
Select->Remove( Handle->FD, true, true );
}
// Close socket
close( Handle->FD );
Handle->FD = -1;
Handle->State = csFailed;
return -1;
}
}
@@ -557,11 +681,6 @@ int CSelectableCore::Open( const char * HandleName )
default:
FD = -1;
}
// Add to Select Lists
if (Select && FD != -1) {
Select->Add( FD, true, true, this );
}
return FD;
};
//---------------------------------------------------------------------------
@@ -573,6 +692,10 @@ bool CSelectableCore::Close( THandle * Handle, bool CloseChildren )
THandle * ChildHandle = NULL;
THandle * NextHandle = NULL;
// Validate
if (!Handle || (Handle->FD == -1))
return false;
// Close Children
if (CloseChildren && (Handle->Type == ctServer)) {
ChildHandle = FirstHandle;
@@ -592,41 +715,44 @@ bool CSelectableCore::Close( THandle * Handle, bool CloseChildren )
}
}
// Remove from Select List
if (Select) {
Select->Remove( Handle->FD, true, true );
}
// Close Handle
Fail = (close( Handle->FD ))? true : false;
Handle->State = ((Fail)? csFailed : csClosed);
Handle->FD = ((Fail)? Handle->FD : -1);
// Show action
switch (Handle->Type)
{
case ctPort:
printf( "Port: %s -> Port %s\n", Handle->FileName, ((Fail)? "failed" : "closed") );
// Log Event
sprintf( LogStr, "Handle '%s' - Port %s [%s]", Handle->Name, ((Fail)? "failed" : "closed"), Handle->FileName );
break;
case ctServer:
printf( "Server Socket: %s -> Server %s\n", Handle->Address, ((Fail)? "failed" : "closed") );
sprintf( LogStr, "Handle '%s' - Server %s [%s:%d]", Handle->Name, ((Fail)? "failed" : "closed"), Handle->Address, Handle->PortNo );
break;
case ctRemoteClient:
printf( "Remote Client: %s -> Connection to client %s\n", Handle->Address, ((Fail)? "failed" : "closed") );
sprintf( LogStr, "Handle '%s' - Remote Client connection %s [%s]", Handle->Name, ((Fail)? "failed" : "closed"), Handle->Address );
break;
case ctClient:
printf( "Client Socket: %s -> Connection to server %s\n", Handle->Address, ((Fail)? "failed" : "closed") );
sprintf( LogStr, "Handle '%s' - Client connection %s [%s:%d]", Handle->Name, ((Fail)? "failed" : "closed"), Handle->Address, Handle->PortNo );
break;
case ctNone:
default:
printf( "Socket : %s -> Cannot %s socket (invalid socket type)\n", Handle->Address, ((Fail)? "fail" : "close") );
sprintf( LogStr, "Handle '%s' - %s, invalid Handle type", Handle->Name, ((Fail)? "failed" : "closed") );
break;
};
LogMessage( Name, dlMedium, LogStr );
// Remove from Select List
if (!Fail && Select) {
Select->Remove( Handle->FD, true, true );
}
// Reset FD
Handle->FD = ((Fail)? Handle->FD : -1);
return true;
}
//---------------------------------------------------------------------------
@@ -643,6 +769,12 @@ bool CSelectableCore::Read( THandle * Handle )
return false;
}
// Log Read Event
if (DebugLevel >= dlMedium) {
sprintf( LogStr, "Handle '%s' - Read Event", Handle->Name );
LogMessage( Name, dlMedium, LogStr );
}
// Check for closing/opening event on Socket
if (Handle->Type == ctServer)
{
@@ -658,6 +790,17 @@ bool CSelectableCore::Read( THandle * Handle )
}
else if ((Handle->Type == ctRemoteClient) || (Handle->Type == ctClient))
{
// Check if socket ready (non-block open in progress)
if (Handle->State == csWaitingtoOpen)
{
if (Handle->Type == ctRemoteClient) {
OpenRemoteClientSocket( Handle );
} else if (Handle->Type == ctClient) {
OpenClientSocket( Handle );
}
return true;
}
// Check if anything to read
ioctl( Handle->FD, FIONREAD, &BytesWaiting );
@@ -673,12 +816,6 @@ bool CSelectableCore::Read( THandle * Handle )
}
return false;
}
// Check if socket ready (non-block open in progress)
else if (Handle->State == csWaitingtoOpen)
{
printf( "Socket: %s -> Cannot read from socket in waiting\n", Name );
return false;
}
}
// Validate
@@ -703,13 +840,21 @@ bool CSelectableCore::Read( THandle * Handle )
bool CSelectableCore::Write( THandle * Handle )
{
int BytesWritten = 0;
int Len = 0;
char * Data = NULL;
int BytesWritten = 0;
// Validate
if (!Handle) {
return false;
}
// Log Read Event
if (DebugLevel >= dlMedium) {
sprintf( LogStr, "Handle '%s' - Write Event", Handle->Name );
LogMessage( Name, dlMedium, LogStr );
}
if (Handle->State == csWaitingtoOpen)
{
// Complete socket open process
@@ -730,7 +875,15 @@ bool CSelectableCore::Write( THandle * Handle )
if (Handle->OutBuffer)
{
// Write to FD directly from buffer
if ((BytesWritten = Handle->OutBuffer->WriteToFD( Handle->FD ))) {
if ((BytesWritten = Handle->OutBuffer->WriteToFD( Handle->FD )))
{
if (DebugLevel >= dlHigh) {
// Show event
Len = Handle->InBuffer->Peek( &Data );
sprintf( LogStr, "%s: Handle '%s' - OUT:", Name, Handle->Name );
ShowOutput( LogStr, dlHigh, OUT_NORMAL, Data, Len );
}
// Update Buffer
Handle->OutBuffer->Clear( BytesWritten );
}
@@ -764,6 +917,7 @@ bool CSelectableCore::ProcessBuffer( THandle * Handle, bool Force )
char * Data = NULL;
TLocalIO * LocalIO = NULL;
TLinkedIO * Output = NULL;
char HeadStr[50];
// Check if buffered data
if (!Handle || !Handle->InBuffer->Len()) {
@@ -774,8 +928,11 @@ bool CSelectableCore::ProcessBuffer( THandle * Handle, bool Force )
if (Force)
{
// Show Packet
Len = Handle->InBuffer->Peek( &Data );
ShowOutput( "Port In", OUT_NORMAL, Data, Len );
if (DebugLevel >= dlHigh) {
Len = Handle->InBuffer->Peek( &Data );
sprintf( HeadStr, "%s: Handle '%s' - IN-F:", Name, Handle->Name );
ShowOutput( HeadStr, dlHigh, OUT_NORMAL, Data, Len );
}
// Write buffer to Outputs
if (Handle->Type == ctRemoteClient) {
@@ -796,12 +953,19 @@ bool CSelectableCore::ProcessBuffer( THandle * Handle, bool Force )
}
else
{
// Log header
if (DebugLevel >= dlHigh) {
sprintf( HeadStr, "%s: Handle '%s' - IN-M:", Name, Handle->Name );
}
// Search for end of packet marker
while (Handle->InBuffer->FindStr( Handle->InMarker, Handle->InMarkerLen, Pos ))
{
// Show Packet
Len = Handle->InBuffer->Peek( &Data, 0, Pos+1 );
ShowOutput( "Port In", OUT_NORMAL, Data, Len );
if (DebugLevel >= dlHigh) {
// Show Packet
Len = Handle->InBuffer->Peek( &Data, 0, Pos+1 );
ShowOutput( HeadStr, dlHigh, OUT_NORMAL, Data, Len );
}
// Write buffer to Outputs
if (Handle->Type == ctRemoteClient) {
@@ -898,58 +1062,81 @@ int CSelectableCore::Input( const char * IOName, const char * Data, int Len )
}
// Get File handle
if ((Handle = GetHandle( IOName )))
if (!(Handle = GetHandle( IOName )))
{
if (Handle->Type == ctServer)
{
// Cannot write to server socket, so Update Remote Client connections individually
ChildHandle = FirstHandle;
while (ChildHandle)
{
// Check if child
if (ChildHandle->Parent == Handle)
{
// Decide where to put data
if (ChildHandle->OutBuffer)
{
// Write to buffer
BytesWritten = ChildHandle->OutBuffer->Push( Data, Len );
// Log event
sprintf( LogStr, "%s: Local IO '%s' - Input rejected, Input not found", Name, IOName );
LogMessage( Name, dlMedium, LogStr );
// Add to select write list
if (BytesWritten) {
Select->Add( ChildHandle->FD, false, true, this );
}
}
else
{
// Write directly to handle
BytesWritten = WriteToFD( ChildHandle->FD, Data, Len );
return 0;
}
// Log event
sprintf( LogStr, "%s: LocalIO '%s' - IN:", Name, IOName );
ShowOutput( LogStr, dlMedium, OUT_NORMAL, Data, Len );
if (Handle->Type == ctServer)
{
// Cannot write to server socket, so Update Remote Client connections individually
ChildHandle = FirstHandle;
while (ChildHandle)
{
// Check if child
if (ChildHandle->Parent == Handle)
{
// Decide where to put data
if (ChildHandle->OutBuffer)
{
// Write to buffer
BytesWritten = ChildHandle->OutBuffer->Push( Data, Len );
// Add to select write list
if (BytesWritten) {
Select->Add( ChildHandle->FD, false, true, this );
}
}
// Next
ChildHandle = ChildHandle->Next;
else
{
if (DebugLevel >= dlHigh) {
// Show event
sprintf( LogStr, "%s: Handle '%s' - OUT:", Name, Handle->Name );
ShowOutput( LogStr, dlHigh, OUT_NORMAL, Data, Len );
}
// Write directly to handle
BytesWritten = WriteToFD( ChildHandle->FD, Data, Len );
}
}
// Next
ChildHandle = ChildHandle->Next;
}
// Cannot verify individually, so assume all bytes was written
BytesWritten = Len;
}
else
{
// Decide where to put data
if (Handle->OutBuffer)
{
// Write to buffer
BytesWritten = Handle->OutBuffer->Push( Data, Len );
// Add to select write list
if (BytesWritten) {
Select->Add( Handle->FD, false, true, this );
}
// Cannot verify individually, so assume all bytes was written
BytesWritten = Len;
}
else
{
// Decide where to put data
if (Handle->OutBuffer)
{
// Write to buffer
BytesWritten = Handle->OutBuffer->Push( Data, Len );
if (DebugLevel >= dlHigh) {
// Show event
sprintf( LogStr, "%s: Handle '%s' - OUT:", Name, Handle->Name );
ShowOutput( LogStr, dlHigh, OUT_NORMAL, Data, Len );
}
// Add to select write list
if (BytesWritten) {
Select->Add( Handle->FD, false, true, this );
}
}
else
{
// Write directly to handle
BytesWritten = WriteToFD( Handle->FD, Data, Len );
}
// Write directly to handle
BytesWritten = WriteToFD( Handle->FD, Data, Len );
}
}
@@ -1119,12 +1306,16 @@ bool CSelectableCore::SerialConfig( THandle * Handle, int Baud, short DataBits,
// Set Options (second time)
if (tcsetattr( Handle->FD, TCSANOW, &newtio ) != 0)
{
printf( "Port: %s -> Could not configure port\n", Name );
// Log event
sprintf( LogStr, "Handle '%s' - Port not configured", Handle->Name );
LogMessage( Name, dlMedium, LogStr );
return false;
}
// Port configured
printf( "Port: %s -> Port configured\n", Name );
// Log event
sprintf( LogStr, "Handle '%s' - Port configured", Handle->Name );
LogMessage( Name, dlMedium, LogStr );
return true;
}
//---------------------------------------------------------------------------

View File

@@ -145,24 +145,6 @@ protected:
bool RemoveHandle( THandle * Handle );
bool DestroyHandle( THandle * Handle );
// Finding Handles
inline THandle * GetHandle( const char * HandleName )
{
if (!HandleName) return NULL;
THandle * Handle = FirstHandle;
while ( Handle && strcmp( HandleName, Handle->Name ))
Handle = Handle->Next;
return Handle;
}
inline THandle * GetHandle( int FD )
{
if (FD < 0) return NULL;
THandle * Handle = FirstHandle;
while ( Handle && (FD != Handle->FD))
Handle = Handle->Next;
return Handle;
}
// Get Parameters
inline int GetFD( const char * HandleName ) {
THandle * Handle = GetHandle( HandleName );
@@ -201,6 +183,24 @@ public:
CSelectableCore( const char * Name, CSelect * Selector );
~CSelectableCore();
// Finding Handles
inline THandle * GetHandle( const char * HandleName )
{
if (!HandleName) return NULL;
THandle * Handle = FirstHandle;
while ( Handle && strcmp( HandleName, Handle->Name ))
Handle = Handle->Next;
return Handle;
}
inline THandle * GetHandle( int FD )
{
if (FD < 0) return NULL;
THandle * Handle = FirstHandle;
while ( Handle && (FD != Handle->FD))
Handle = Handle->Next;
return Handle;
}
// Configuration
THandle * CreateHandle( const char * HandleName, bool CreateIO = false );
bool SetBuffers( THandle * Handle, int InBufSize, int OutBufSize, int InTimeout, const char * InMarker, int InMarkerLen );

View File

@@ -89,7 +89,7 @@ void SignalTerminate( int sig )
// Create Log Entry
sprintf( LogMsg, " ** %s signal received [%d] **", SigName, TermCount );
LogMessage( ProcessName, LogMsg );//, ltDefault, -1 );
LogMessage( ProcessName, dlNone, LogMsg );//, ltDefault, -1 );
if (TermCount < MaxTermCount)
{
@@ -129,7 +129,7 @@ void SignalAbort( int sig )
// Create Log Entry - but don't post
sprintf( LogMsg, " ** %s signal received **", SigName );
LogMessage( ProcessName, LogMsg );//, ltDefault, -1 );
LogMessage( ProcessName, dlNone, LogMsg );//, ltDefault, -1 );
std::cerr << ProcessName << ": ** Terminating immediately! **\n";
std::cerr << ProcessName << ": ********************************\n\n";