From c01c8f5e9bff8b30546fb38d90fe9754ddf39795 Mon Sep 17 00:00:00 2001 From: Charl Wentzel Date: Thu, 26 May 2016 15:03:13 +0200 Subject: [PATCH] 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 --- FunctionCore.cpp | 145 +++++++++------ FunctionCore.h | 7 +- LogCore.cpp | 17 +- LogCore.h | 8 +- SelectCore.cpp | 119 +++++++++---- SelectableCore.cpp | 431 ++++++++++++++++++++++++++++++++------------- SelectableCore.h | 36 ++-- SignalCore.cpp | 4 +- 8 files changed, 532 insertions(+), 235 deletions(-) diff --git a/FunctionCore.cpp b/FunctionCore.cpp index c9ef47f..404532f 100644 --- a/FunctionCore.cpp +++ b/FunctionCore.cpp @@ -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; +} +//--------------------------------------------------------------------------- diff --git a/FunctionCore.h b/FunctionCore.h index b2600cc..e9654bc 100644 --- a/FunctionCore.h +++ b/FunctionCore.h @@ -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 ); diff --git a/LogCore.cpp b/LogCore.cpp index 1acc8ee..a4dd2c6 100644 --- a/LogCore.cpp +++ b/LogCore.cpp @@ -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 ); diff --git a/LogCore.h b/LogCore.h index a0b2b8d..e97c4bb 100644 --- a/LogCore.h +++ b/LogCore.h @@ -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 ); //--------------------------------------------------------------------------- diff --git a/SelectCore.cpp b/SelectCore.cpp index 53a73fa..1377989 100644 --- a/SelectCore.cpp +++ b/SelectCore.cpp @@ -6,12 +6,20 @@ */ // redA Libraries +#include "SelectableCore.h" #include "TimingCore.h" +#include "LogCore.h" + +// Standard C/C++ Libraries #include #include #include #include -#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; } diff --git a/SelectableCore.cpp b/SelectableCore.cpp index 1e2b198..65db3e0 100644 --- a/SelectableCore.cpp +++ b/SelectableCore.cpp @@ -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; } //--------------------------------------------------------------------------- diff --git a/SelectableCore.h b/SelectableCore.h index 41ff2e7..d7867eb 100644 --- a/SelectableCore.h +++ b/SelectableCore.h @@ -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 ); diff --git a/SignalCore.cpp b/SignalCore.cpp index 58b67b8..0b5090d 100644 --- a/SignalCore.cpp +++ b/SignalCore.cpp @@ -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";