diff --git a/ApplicationCore.cpp b/ApplicationCore.cpp index 5c5542c..85ac748 100644 --- a/ApplicationCore.cpp +++ b/ApplicationCore.cpp @@ -12,6 +12,7 @@ #include "ApplicationCore.h" #include "WatchdogCore.h" #include "FileCore.h" +#include "DeviceCore.h" //--------------------------------------------------------------------------- @@ -25,13 +26,9 @@ CApplication::CApplication( EDebugLevel pLogLevel ) // Set signal handlers ConfigureSignalHandlers(); - // Variables used for configuration - ConfigMember = NULL; - FunctionConfigMember = NULL; - LinkConfigMember = NULL; - - ConfigFile = NULL; - AddressFile = NULL; + DefinitionFile = NULL; + ConfigFile = NULL; + AddressFile = NULL; // Create output logger Log = new CLogCore( stdout ); @@ -39,31 +36,49 @@ CApplication::CApplication( EDebugLevel pLogLevel ) LogOutput = OUT_NORMAL; // Create Configuration - DataTree = new CDataMember(); - JSONparser = new CJSONparse( DataTree ); + DataTree = new CDataMember(); + Config = DataTree->GetChild( "Config", true ); + Definition = DataTree->GetChild( "Definition", true ); + AddressList = DataTree->GetChild( "AddressList", true ); + JSONparser = new CJSONparse( DataTree ); // Selector - Selector = NULL; + Selector = NULL; // List - FirstFunction = NULL; + FirstFunctionType = NULL; + FirstFunction = NULL; + + // Add Core Function Types + //AddFunctionType( TYPE_FUNCTION, NewFunctionCore ); // <-- Can't add virtual function + AddFunctionType( TYPE_SELECTABLE, NewSelectableCore ); + AddFunctionType( TYPE_WATCHDOG, NewWatchdogCore ); + AddFunctionType( TYPE_FILE, NewFileCore ); + //AddFunctionType( TYPE_DEVICE, NewDeviceCore ); // <-- Can't add virtual function } //--------------------------------------------------------------------------- CApplication::~CApplication() { TFunctionItem * NextFunction; + TFunctionType * NextType; - if (FirstFunction) + // Destroy functions + while (FirstFunction) { - // Destroy functions - while (FirstFunction) - { - NextFunction = FirstFunction->Next; - delete( FirstFunction->Function ); - free( FirstFunction ); - FirstFunction = NextFunction; - } + NextFunction = FirstFunction->Next; + delete( FirstFunction->Function ); + free( FirstFunction ); + FirstFunction = NextFunction; + } + + // Destroy function types + while (FirstFunctionType) + { + NextType = FirstFunctionType->Next; + free( FirstFunctionType->Name ); + free( FirstFunctionType ); + FirstFunctionType = NextType; } // Show Completion @@ -98,7 +113,7 @@ void CApplication::GetProcessName( char ** ProcessName, char * pFilePath ) } //--------------------------------------------------------------------------- -bool CApplication::LoadConfig( int argc, char *argv[], const char * pConfigPath ) +bool CApplication::ReadParam( int argc, char *argv[] ) { // Read Parameters if ((argc != 2)) @@ -116,16 +131,49 @@ bool CApplication::LoadConfig( int argc, char *argv[], const char * pConfigPath // Load parameters GetProcessName( &ProcessName, argv[1] ); ConfigFile = argv[1]; + return true; } +} +//--------------------------------------------------------------------------- - // Load Application List - if (JSONparser->ReadFromFile( pConfigPath, ConfigFile )) { - if (Log) Log->Message( dlLow, dlLow, "%s: Config file loaded (%s)", ProcessName, ConfigFile ); - } else { - if (Log) Log->Message( dlLow, dlLow, "%s: Fail to load config file (%s)- %s", ProcessName, ConfigFile, JSONparser->GetError() ); +bool CApplication::LoadConfig() +{ + // Load Configuration Data + if (!JSONparser->ReadFromFile( "Config", ConfigFile )) { + if (Log) Log->Message( dlLow, dlLow, "%s: Fail to load Configuration file (%s)- %s", ProcessName, ConfigFile, JSONparser->GetError() ); return false; } - //JSONparser->WriteToScreen( pConfigPath, 2 ); + else { + //JSONparser->WriteToScreen( "config", 2 ); + if (Log) Log->Message( dlLow, dlLow, "%s: Configuration file loaded (%s)", ProcessName, ConfigFile ); + } + + // Load Application Definition + if (!(DefinitionFile = (char*)Config->GetChStr( "DefinitionFile" ))) { + if (Log) Log->Message( dlLow, dlLow, "%s: No Application Definition file specified", ProcessName ); + return false; + } + else if (!JSONparser->ReadFromFile( "Definition", DefinitionFile )) { + if (Log) Log->Message( dlLow, dlLow, "%s: Fail to load Application Definition file (%s)- %s", ProcessName, DefinitionFile, JSONparser->GetError() ); + return false; + } + else { + //JSONparser->WriteToScreen( "application", 2 ); + if (Log) Log->Message( dlLow, dlLow, "%s: Application Definition file loaded (%s)", ProcessName, DefinitionFile ); + } + + // Load Address List + if (!(AddressFile = (char*)Config->GetChStr( "AddressFile" ))) { + if (Log) Log->Message( dlLow, dlLow, "%s: No Address List file specified", ProcessName ); + } + else if (!JSONparser->ReadFromFile( "AddressList", AddressFile )) { + if (Log) Log->Message( dlLow, dlLow, "%s: Fail to load Address List file (%s)- %s", ProcessName, AddressFile, JSONparser->GetError() ); + return false; + } + else { + //JSONparser->WriteToScreen( "address", 2 ); + if (Log) Log->Message( dlLow, dlLow, "%s: Address List file loaded (%s)", ProcessName, AddressFile ); + } // Loaded successfully return true; @@ -136,79 +184,11 @@ bool CApplication::SaveConfig() { // Save updated configuration if (ConfigFile && *ConfigFile) - JSONparser->WriteToFile( "config", ConfigFile ); + JSONparser->WriteToFile( "Config", ConfigFile ); + if (DefinitionFile && *DefinitionFile) + JSONparser->WriteToFile( "Definition", DefinitionFile ); if (AddressFile && *AddressFile ) - JSONparser->WriteToFile( "address", AddressFile ); - return true; -} -//--------------------------------------------------------------------------- - -bool CApplication::LoadConfigData() -{ - CDataMember * TempMember; - EDebugLevel pLogLevel; - int pLogOutput; - char * TempStr; - - // Get debug level - pLogLevel = dlNone; - TempStr = (char*)ConfigMember->GetChStr( "Log/Level", "Medium", true ); - if (TempStr) - { - if (!strcasecmp( TempStr, "Low" )) - pLogLevel = dlLow; - else if (!strcasecmp( TempStr, "Medium" )) - pLogLevel = dlMedium; - else if (!strcasecmp( TempStr, "High" )) - pLogLevel = dlHigh; - } - - // Set debug output - pLogOutput = 0; - if ((TempMember = ConfigMember->GetChild( "Log/Output", true ))) - { - TempMember = TempMember->GetFirstChild(); - while (TempMember) - { - if ((TempStr = (char*)TempMember->GetStr())) - { - if (!strcasecmp( TempStr, "Normal")) - pLogOutput |= OUT_NORMAL; - else if (!strcasecmp( TempStr, "Bin")) - pLogOutput |= OUT_BIN; - else if (!strcasecmp( TempStr, "Hex")) - pLogOutput |= OUT_HEX; - else if (!strcasecmp( TempStr, "Count")) - pLogOutput |= OUT_COUNT; - else if (!strcasecmp( TempStr, "AsIs")) - pLogOutput |= OUT_ASIS; - else if (!strcasecmp( TempStr, "CRLF")) - pLogOutput |= OUT_CRLF; - } - - // Next - TempMember = TempMember->GetNextPeer(); - } - } - SetLogParam( pLogLevel, pLogOutput ); - - // Load Address List - if ((AddressFile = (char*)ConfigMember->GetChStr( "AddressList/Path", NULL ))) - { - if (JSONparser->ReadFromFile( "address", AddressFile )) { - if (Log) Log->Message( dlLow, dlLow, "%s: Address file loaded (%s)", ProcessName, AddressFile ); - } else { - if (Log) Log->Message( dlLow, dlLow, "%s: Fail to load Address file (%s) - %s", ProcessName, AddressFile, JSONparser->GetError() ); - } - //JSONparser->WriteToScreen( pAddressListPath, 2 ); - } - - // Configure Selector - if ((TempMember = ConfigMember->GetChild( "Selector" ))) - { - // Create Selector - Selector = new CSelect( (int)TempMember->GetChInt( "Wait", 5, true ), LogLevel ); - } + JSONparser->WriteToFile( "AddressList", AddressFile ); return true; } //--------------------------------------------------------------------------- @@ -223,117 +203,220 @@ bool CApplication::SetLogParam( EDebugLevel pDebugLevel, int pOutputDisplay ) } //--------------------------------------------------------------------------- -bool CApplication::Init() +bool CApplication::InitApplication() { - // Report status - if (Log) Log->Message( LogLevel, dlLow, "%s: Application Initialised", ProcessName ); + CDataMember * CoreConfig; + CDataMember * ItemConfig; + CDataMember * SelectConfig; + EDebugLevel pLogLevel; + int pLogOutput; + char * TempStr; - return true; -} -//--------------------------------------------------------------------------- + // Get Core definition + CoreConfig = Definition->GetChild( "Core", true ); -bool CApplication::InitConfig( const char * pConfigPath ) -{ - // Check if Datatree exists - if (!DataTree || !(ConfigMember = DataTree->GetChild( pConfigPath ))) { - return false; + // Get debug level + pLogLevel = dlNone; + TempStr = (char*)CoreConfig->GetChStr( "Log/Level", "Medium", true ); + if (TempStr) + { + if (!strcasecmp( TempStr, "Low" )) + pLogLevel = dlLow; + else if (!strcasecmp( TempStr, "Medium" )) + pLogLevel = dlMedium; + else if (!strcasecmp( TempStr, "High" )) + pLogLevel = dlHigh; } - // LoadConfiguration - LoadConfigData(); - Init(); + // Set debug output + pLogOutput = 0; + ItemConfig = CoreConfig->GetChild( "Log/Output[0]", true ); // Create first element if not exist + while (ItemConfig) + { + if ((TempStr = (char*)ItemConfig->GetStr( "Normal" ))) // Set default value "Normal" if not set + { + if (!strcasecmp( TempStr, "Normal")) // Normal ASCII -> Unless "AsIs", print special chars as "." + pLogOutput |= OUT_NORMAL; + else if (!strcasecmp( TempStr, "Bin")) // Print as Binary value ('1' and '0') + pLogOutput |= OUT_BIN; + else if (!strcasecmp( TempStr, "Hex")) // Print as Hexadecimal value (0-9,A-F) + pLogOutput |= OUT_HEX; + else if (!strcasecmp( TempStr, "Count")) // Print number of characters + pLogOutput |= OUT_COUNT; + else if (!strcasecmp( TempStr, "AsIs")) // Use with "Normal" -> Do not print special chars as "." + pLogOutput |= OUT_ASIS; + else if (!strcasecmp( TempStr, "CRLF")) // Add \r\n at end of line if not present + pLogOutput |= OUT_CRLF; + else + pLogOutput |= OUT_NORMAL; + } + ItemConfig = ItemConfig->GetNextPeer(); + } + SetLogParam( pLogLevel, pLogOutput ); + + // Configure Selector + if ((SelectConfig = CoreConfig->GetChild( "Selector" ))) { + Selector = new CSelect( (int)SelectConfig->GetChInt( "Wait", 5, true ), LogLevel ); + } + + // Show status + if (Log) Log->Message( LogLevel, dlLow, "%s: Application Core configured.", ProcessName ); return true; } //--------------------------------------------------------------------------- -bool CApplication::InitFunctions( const char * pConfigPath ) +bool CApplication::InitFunction( CFunctionCore * Function ) { + char FunctionPath[100]; + CDataMember * FunctionConfig = NULL; + + // Validate + if (!Function) + return false; + + // Load configuration + sprintf( FunctionPath, "FunctionBlocks/%s", Function->GetName() ); + if (!(FunctionConfig = Definition->GetChild( FunctionPath, true ))) { + if (Log) Log->Message( LogLevel, dlMedium, "%s: Function '%s' - Type '%s' cannot create config!", + ProcessName, Function->GetName(), Function->GetType() ); + } + // Configure Function + else if (!Function->Init( FunctionConfig )) { + if (Log) Log->Message( LogLevel, dlMedium, "%s: Function '%s' - Type '%s' init failed!", + ProcessName, Function->GetName(), Function->GetType() ); + return false; + } + else { + if (Log) Log->Message( LogLevel, dlMedium, "%s: Function '%s' - Type '%s' configured.", + ProcessName, Function->GetName(), Function->GetType() ); + } + return true; +} +//--------------------------------------------------------------------------- + +bool CApplication::InitFunctions() +{ + CDataMember * FunctionList; + CDataMember * FunctionConfig; CFunctionCore * Function; - CDataMember * TempMember; char * Type; // Check of path exists - if (!DataTree || !(FunctionConfigMember = DataTree->GetChild( pConfigPath ))) + if (!(FunctionList = Definition->GetChild( "FunctionBlocks" ))) { + if (Log) Log->Message( LogLevel, dlLow, "%s: No Function Block specified", ProcessName ); return false; + } // Process each Channel - TempMember = FunctionConfigMember->GetFirstChild(); - while (TempMember) + FunctionConfig = FunctionList->GetFirstChild(); + while (FunctionConfig) { // Get function parameters - Type = (char*)TempMember->GetChStr( "Type", "Custom", true ); + Type = (char*)FunctionConfig->GetChStr( "Type", "Custom", true ); + + if (Log) Log->Message( LogLevel, dlLow, "%s: Function '%s' - Type '%s' initialising...", + ProcessName, FunctionConfig->GetName(), Type ); // Get or create function - if (!strcasecmp( Type, "WatchdogClient" )) { - Function = new CWatchdogCore( TempMember->GetName() ); - } - else if (!strcasecmp( Type, "Selectable" )) { - Function = new CSelectableCore( TempMember->GetName() ); - } - else if (!strcasecmp( Type, "File" )) { - Function = new CFileCore( TempMember->GetName() ); - } - else { - Function = GetFunction( TempMember->GetName() ); - } + Function = AddFunction( Type, FunctionConfig->GetName() ); // Load Function configuration and Initialise - if (Function) { - Function->InitConfig( TempMember ); + if (!Function) { + if (Log) Log->Message( LogLevel, dlMedium, "%s: Function '%s' - Type '%s' not found!", + ProcessName, FunctionConfig->GetName(), Type ); + } + else if (!Function->Init( FunctionConfig )) { + if (Log) Log->Message( LogLevel, dlMedium, "%s: Function '%s' - Type '%s' init failed!", + ProcessName, Function->GetName(), Function->GetType() ); + } + else { + if (Log) Log->Message( LogLevel, dlMedium, "%s: Function '%s' - Type '%s' configured.", + ProcessName, Function->GetName(), Function->GetType() ); } // Next - TempMember = TempMember->GetNextPeer(); + FunctionConfig = FunctionConfig->GetNextPeer(); } - return true; } //--------------------------------------------------------------------------- -bool CApplication::InitFunctionLinks( const char * pConfigPath ) +bool CApplication::InitFunctionLinks() { + CDataMember * LinkList; + CDataMember * LinkConfig; TFunctionItem * FunctionItem; - CDataMember * TempMember; // Check of path exists - if (!DataTree || !(LinkConfigMember = DataTree->GetChild( pConfigPath ))) + if (!(LinkList = Definition->GetChild( "ChannelLinks", true ))) { + if (Log) Log->Message( LogLevel, dlMedium, "%s: No Function Channel links specified.", ProcessName ); return false; + } + else { + if (Log) Log->Message( LogLevel, dlLow, "%s: Linking Function Block Channels...", ProcessName ); + } // Process each Channel FunctionItem = FirstFunction; while (FunctionItem) { // Build links for function - if ((TempMember = LinkConfigMember->GetChild( FunctionItem->Function->GetName() ))) - FunctionItem->Function->InitChannelLinks( TempMember ); + if ((LinkConfig = LinkList->GetChild( FunctionItem->Function->GetName() ))) + FunctionItem->Function->InitChannelLinks( LinkConfig ); // Next FunctionItem = FunctionItem->Next; } + if (Log) Log->Message( LogLevel, dlLow, "%s: Function Block Channels linked.", ProcessName ); + return true; } //--------------------------------------------------------------------------- +bool CApplication::AddFunctionType( const char * Type, FFuncConstructor Constructor ) +{ + TFunctionType ** FunctionType; + + // Get end of list + FunctionType = &FirstFunctionType; + while (*FunctionType) + FunctionType = &((*FunctionType)->Next); + + // Add new Type + *FunctionType = (TFunctionType*)calloc( sizeof(TFunctionType), 1 ); + + (*FunctionType)->Name = (char*)malloc( strlen(Type)+1 ); + strcpy( (*FunctionType)->Name, Type ); + (*FunctionType)->Constructor = Constructor; + + return true; +}; +//--------------------------------------------------------------------------- + // Build List -bool CApplication::AddFunction( CFunctionCore * Function ) +CFunctionCore * CApplication::AddFunction( const char * Type, const char * Name ) { TFunctionItem ** FunctionPtr; + TFunctionType * FunctionType; // Check if unique, else get end of list FunctionPtr = &FirstFunction; - while (*FunctionPtr && strcasecmp( (*FunctionPtr)->Function->GetName(), Function->GetName() )) + while (*FunctionPtr && strcasecmp( (*FunctionPtr)->Function->GetName(), Name )) FunctionPtr = &((*FunctionPtr)->Next); + if (*FunctionPtr) return NULL; // Can't overwrite existing function - // Check if exists - if (*FunctionPtr) - return false; + // Check if type is valid + FunctionType = FirstFunctionType; + while (FunctionType && strcasecmp( FunctionType->Name, Type )) + FunctionType = FunctionType->Next; + if (!FunctionType) return NULL; // Type not defined // Add to end of list *FunctionPtr = (TFunctionItem*)calloc( sizeof(TFunctionItem), 1 ); - (*FunctionPtr)->Function = Function; - return true; + (*FunctionPtr)->Function = FunctionType->Constructor( Name ); + return (*FunctionPtr)->Function; } //--------------------------------------------------------------------------- diff --git a/ApplicationCore.h b/ApplicationCore.h index 561ba0e..cf036f7 100644 --- a/ApplicationCore.h +++ b/ApplicationCore.h @@ -23,16 +23,25 @@ //--------------------------------------------------------------------------- // Preview -typedef struct SFunctionItem TFunctionItem; +typedef struct SFunctionType TFunctionType; +typedef struct SFunctionItem TFunctionItem; + +typedef CFunctionCore * (*FFuncConstructor)( const char * Name ); class Application; //--------------------------------------------------------------------------- +struct SFunctionType { + char * Name; + FFuncConstructor Constructor; + TFunctionType * Next; +}; +//--------------------------------------------------------------------------- + struct SFunctionItem { CFunctionCore * Function; - SFunctionItem * Next; }; //--------------------------------------------------------------------------- @@ -42,50 +51,54 @@ class CApplication protected: // Variables used for configuration char * ConfigFile; + char * DefinitionFile; char * AddressFile; + // Configuration + CDataMember * DataTree; + CJSONparse * JSONparser = NULL; + // List + TFunctionType * FirstFunctionType; TFunctionItem * FirstFunction; // Output EDebugLevel LogLevel; int LogOutput; - // Configuration - CDataMember * ConfigMember; - CDataMember * FunctionConfigMember; - CDataMember * LinkConfigMember; - - bool LoadConfigData(); - public: // Public function vars - CDataMember * DataTree; CLogCore * Log; CSelect * Selector; - CJSONparse * JSONparser = NULL; + + // Configuration + CDataMember * Config; + CDataMember * Definition; + CDataMember * AddressList; // Life Cycle CApplication( EDebugLevel pDebugLevel ); virtual ~CApplication(); // Manage Config File + bool ReadParam( int argc, char *argv[] ); void GetProcessName( char ** ProcessName, char * pFilePath ); - bool LoadConfig( int argc, char *argv[], const char * pConfigPath ); + bool LoadConfig(); bool SaveConfig(); // Manually set configuration bool SetLogParam( EDebugLevel pDebugLevel, int pOutputDisplay ); // Init application - virtual bool Init(); - - bool InitConfig( const char * pConfigPath ); - bool InitFunctions( const char * pConfigPath ); - bool InitFunctionLinks( const char * pConfigPath ); + bool InitApplication(); + bool InitFunctions(); + bool InitFunction( CFunctionCore * Function ); + bool InitFunctionLinks(); // Manage Functions - bool AddFunction( CFunctionCore * Function ); + bool AddFunctionType( const char * Type, FFuncConstructor Constructor ); + + CFunctionCore * AddFunction( const char * Type, const char * Name ); CFunctionCore * GetFunction( const char * Name ); // Run Application diff --git a/DataTreeCore.cpp b/DataTreeCore.cpp index 4672827..d6511ff 100644 --- a/DataTreeCore.cpp +++ b/DataTreeCore.cpp @@ -226,7 +226,7 @@ CDataMember * CDataMember::GetChild( const char * Path, bool Create ) // Create element if needed if (!*Child && Create) { - if ((Index == -1) || (Index = Count + 1)) { + if ((Index == -1) || (Index == Count)) { *Child = new CDataMember( Member, NULL ); } } @@ -271,35 +271,41 @@ CDataMember * CDataMember::GetChild( const char * Path, bool Create ) } //--------------------------------------------------------------------------- -CDataMember * CDataMember::GetChFirstChild( const char * Path ) +CDataMember * CDataMember::GetChFirstChild( const char * Path, bool Create ) { CDataMember * Member = NULL; // Find member - Member = (!Path || !*Path)? this : GetChild( Path, false ); + Member = (!Path || !*Path)? this : GetChild( Path, Create ); // Check if valid type if (!Member || ((Member->Type != jtObject) && (Member->Type != jtNull))) { return NULL; } + else if (Create && (Member->Type == jtNull)) { + Member->SetObject(); // Set newly created member to object + } return Member->FirstChild; } //--------------------------------------------------------------------------- -CDataMember * CDataMember::GetChElement( const char * Path, const int Index ) +CDataMember * CDataMember::GetChElement( const char * Path, const int Index, bool Create ) { CDataMember * Member = NULL; CDataMember * Child = NULL; int Count; // Find Member - Member = (!Path || !*Path)? this : GetChild( Path, false ); + Member = (!Path || !*Path)? this : GetChild( Path, Create ); // Check if valid type if (!Member || ((Member->Type != jtArray) && (Member->Type != jtNull))) { return NULL; } + else if (Create && (Member->Type == jtNull)) { + Member->SetArray(); // Set newly created member to array + } // Find element at position Count = 0; @@ -526,7 +532,7 @@ const char * CDataMember::GetChStr( const char * Path, const char * Default, boo return Member->Value; } else if (Member && Create && (Member->Type == jtNull)) { - Member->SetValue( jtString, Default ); + Member->SetStr( Default ); return Member->Value; } else { @@ -546,7 +552,7 @@ const char * CDataMember::GetChStr( const char * Path, int &Len, const char * De return Member->Value; } else if (Member && Create && (Member->Type == jtNull)) { - Member->SetValue( jtString, Default ); + Member->SetStr( Default ); Len = Member->Len; return Member->Value; } diff --git a/DataTreeCore.h b/DataTreeCore.h index 7f68c4f..da36048 100644 --- a/DataTreeCore.h +++ b/DataTreeCore.h @@ -41,7 +41,7 @@ class CDataMember CDataMember * CreateChild( const char * Name, const int Len = -1 ); // Set Member value - bool SetValue( EDataType Type, const char * Value = NULL, int Len = -1 ); + bool SetValue( EDataType Type, const char * Value = NULL, int Len = -1 ); bool SetValuePtr( EDataType pType, const char * pValue, int pLen = -1 ); public: @@ -67,11 +67,11 @@ public: const int GetLen( const char * Path ); CDataMember * GetChild( const char * Path, bool Create = false ); - CDataMember * GetChFirstChild( const char * Path ); - CDataMember * GetChElement( const char * Path, const int Index ); + CDataMember * GetChFirstChild( const char * Path, bool Create = false ); + CDataMember * GetChElement( const char * Path, const int Index, bool Create = false ); - inline CDataMember * GetFirstChild() { return FirstChild; }; - inline CDataMember * GetElement( const int Index ) { return GetChElement( NULL, Index ); }; + inline CDataMember * GetFirstChild() { return GetChFirstChild( NULL, false ); }; + inline CDataMember * GetElement( const int Index ) { return GetChElement( NULL, Index, false ); }; inline CDataMember * GetParent() { return Parent; }; inline CDataMember * GetPrevPeer() { return PrevPeer; }; @@ -83,11 +83,11 @@ public: const long GetChInt( const char * Path, long Default = 0, bool Create = false, const char * Mask = NULL ); const double GetChFloat( const char * Path, double Default = 0.0, bool Create = false, const char * Mask = NULL ); - inline const char * GetStr( const char * Default = NULL, bool Create = false ) { return GetChStr( NULL, Default, Create ); }; - inline const char * GetStr( int &Len, const char * Default = NULL, bool Create = false ) { return GetChStr( NULL, Len, Default, Create ); }; - inline const bool GetBool( bool Default = false, bool Create = false ) { return GetChBool( NULL, Default, Create ); }; - inline const long GetInt( long Default = 0, bool Create = false, const char * Mask = NULL ) { return GetChInt( NULL, Default, Create, Mask ); }; - inline const double GetFloat( double Default = 0.0, bool Create = false, const char * Mask = NULL ) { return GetChFloat( NULL, Default, Create, Mask ); }; + inline const char * GetStr( const char * Default = NULL ) { return GetChStr( NULL, Default, false ); }; + inline const char * GetStr( int &Len, const char * Default = NULL ) { return GetChStr( NULL, Len, Default, false ); }; + inline const bool GetBool( bool Default = false ) { return GetChBool( NULL, Default, false ); }; + inline const long GetInt( long Default = 0, const char * Mask = NULL ) { return GetChInt( NULL, Default, false, Mask ); }; + inline const double GetFloat( double Default = 0.0, const char * Mask = NULL ) { return GetChFloat( NULL, Default, false, Mask ); }; bool SetChBool( const char * Path, const bool Value ); bool SetChInt( const char * Path, const long Value, const char * Mask = NULL ); diff --git a/DeviceCore.cpp b/DeviceCore.cpp index 2583dd7..2f91420 100644 --- a/DeviceCore.cpp +++ b/DeviceCore.cpp @@ -22,8 +22,12 @@ extern char * ProcessName; //--------------------------------------------------------------------------- -CDeviceCore::CDeviceCore( const char * pName, const char * pType ) : - CFunctionCore( pName, pType ) +//CFunctionCore * NewDeviceCore( const char * Name ) { +// return (CFunctionCore*) new CDeviceCore( Name ); +//} +//--------------------------------------------------------------------------- + +CDeviceCore::CDeviceCore( const char * pName, const char * pType ) : CFunctionCore( pName, pType ) { // Clear Parameters FirstDevice = NULL; diff --git a/DeviceCore.h b/DeviceCore.h index 55fff74..365b3b5 100644 --- a/DeviceCore.h +++ b/DeviceCore.h @@ -61,6 +61,12 @@ struct SDeviceParam { //--------------------------------------------------------------------------- +// Function Constructor List +#define TYPE_DEVICE "Device" +//CFunctionCore * NewDeviceCore( const char * Name ); + +//--------------------------------------------------------------------------- + class CDeviceCore : public CFunctionCore { protected: @@ -168,7 +174,7 @@ protected: public: // Life cycle - CDeviceCore( const char * pName, const char * Type = "Device" ); + CDeviceCore( const char * pName, const char * pType = TYPE_DEVICE ); virtual ~CDeviceCore(); // Generate events diff --git a/FileCore.cpp b/FileCore.cpp index 6327146..2a56b62 100644 --- a/FileCore.cpp +++ b/FileCore.cpp @@ -22,8 +22,13 @@ extern char * ProcessName; //--------------------------------------------------------------------------- -CFileCore::CFileCore( const char * pName, const char * pType ) : - CFunctionCore( pName, pType ) +// Function Constructor +CFunctionCore * NewFileCore( const char * Name ) { + return (CFunctionCore*) new CFileCore( Name ); +} +//--------------------------------------------------------------------------- + +CFileCore::CFileCore( const char * pName, const char * pType ) : CFunctionCore( pName, pType ) { FirstFile = NULL; } diff --git a/FileCore.h b/FileCore.h index 9e48122..e414270 100644 --- a/FileCore.h +++ b/FileCore.h @@ -35,6 +35,11 @@ struct SFileHandle }; //--------------------------------------------------------------------------- +// Function Constructor List +#define TYPE_FILE "File" +CFunctionCore * NewFileCore( const char * Name ); + +//--------------------------------------------------------------------------- class CFileCore : public CFunctionCore { private: @@ -60,7 +65,7 @@ private: public: // Life cycle - CFileCore( const char * pName, const char * pType = "File" ); + CFileCore( const char * pName, const char * pType = TYPE_FILE ); virtual ~CFileCore(); // Manage files diff --git a/FunctionCore.cpp b/FunctionCore.cpp index a1f1353..afb9d1f 100644 --- a/FunctionCore.cpp +++ b/FunctionCore.cpp @@ -20,8 +20,14 @@ extern CApplication * Application; //--------------------------------------------------------------------------- +// Function Constructor +//CFunctionCore * NewFunctionCore( const char * Name ) { +// return new CFunctionCore( Name, "Function" ); +//} +//--------------------------------------------------------------------------- + // Life cycle -CFunctionCore::CFunctionCore( const char * pName, const char * pType ) +CFunctionCore::CFunctionCore( const char * pName, const char * pType ) : Type( pType ) { // Set name if (pName) { @@ -32,25 +38,8 @@ CFunctionCore::CFunctionCore( const char * pName, const char * pType ) Name = NULL; } - // Set Type - if (pType) { - Type = (char*)malloc( strlen(pType)+1 ); - strcpy( Type, pType ); - } - else { - Type = NULL; - } - // Channels - FirstChannel = NULL; - - // List - Application->AddFunction( this ); - - // Data Tree - DataTree = Application->DataTree; - ConfigMember = NULL; - LinkConfigMember = NULL; + FirstChannel = NULL; // Logging Log = Application->Log; @@ -107,20 +96,25 @@ CFunctionCore::~CFunctionCore() // Destroy Name if (Name) free( Name ); - if (Type) free( Type ); } //--------------------------------------------------------------------------- -bool CFunctionCore::LoadConfigData() +bool CFunctionCore::Init( CDataMember * FunctionConfig ) { - CDataMember * TempMember; + // Load configuration + CDataMember * ItemConfig; + CDataMember * ChannelConfig; EDebugLevel pLogLevel; int pLogOutput; char * TempStr; + // Validate + if (!FunctionConfig ) + return false; + // Get debug level pLogLevel = dlNone; - TempStr = (char*)ConfigMember->GetChStr( "Log/Level", "Medium", true ); + TempStr = (char*)FunctionConfig->GetChStr( "Log/Level", "Medium", true ); if (TempStr) { if (!strcasecmp( TempStr, "Low" )) @@ -133,66 +127,63 @@ bool CFunctionCore::LoadConfigData() // Set debug output pLogOutput = 0; - if ((TempMember = ConfigMember->GetChild( "Log/Output", true ))) + ItemConfig = FunctionConfig->GetChild( "Log/Output[0]", true ); // Create first element if not exist + while (ItemConfig) { - TempMember = TempMember->GetFirstChild(); - while (TempMember) + if ((TempStr = (char*)ItemConfig->GetStr( "Normal" ))) // Set default value "Normal" if not set { - if ((TempStr = (char*)TempMember->GetStr())) - { - if (!strcasecmp( TempStr, "Normal")) - pLogOutput |= OUT_NORMAL; - else if (!strcasecmp( TempStr, "Bin")) - pLogOutput |= OUT_BIN; - else if (!strcasecmp( TempStr, "Hex")) - pLogOutput |= OUT_HEX; - else if (!strcasecmp( TempStr, "Count")) - pLogOutput |= OUT_COUNT; - else if (!strcasecmp( TempStr, "AsIs")) - pLogOutput |= OUT_ASIS; - else if (!strcasecmp( TempStr, "CRLF")) - pLogOutput |= OUT_CRLF; - } - - // Next - TempMember = TempMember->GetNextPeer(); + if (!strcasecmp( TempStr, "Normal")) // Normal ASCII -> Unless "AsIs", print special chars as "." + pLogOutput |= OUT_NORMAL; + else if (!strcasecmp( TempStr, "Bin")) // Print as Binary value ('1' and '0') + pLogOutput |= OUT_BIN; + else if (!strcasecmp( TempStr, "Hex")) // Print as Hexadecimal value (0-9,A-F) + pLogOutput |= OUT_HEX; + else if (!strcasecmp( TempStr, "Count")) // Print number of characters + pLogOutput |= OUT_COUNT; + else if (!strcasecmp( TempStr, "AsIs")) // Use with "Normal" -> Do not print special chars as "." + pLogOutput |= OUT_ASIS; + else if (!strcasecmp( TempStr, "CRLF")) // Add \r\n at end of line if not present + pLogOutput |= OUT_CRLF; + else + pLogOutput |= OUT_NORMAL; } + ItemConfig = ItemConfig->GetNextPeer(); } - - // Set Logging SetLogParam( pLogLevel, pLogOutput ); // Load Channels - TempMember = ConfigMember->GetChFirstChild( "Channels" ); - while (TempMember) + ChannelConfig = FunctionConfig->GetChFirstChild( "Channels", true ); + while (ChannelConfig) { - if (TempMember->GetName()) { - AddChannel( TempMember->GetName(), - TempMember->GetChBool( "InputEnabled", true, true ), - TempMember->GetChBool( "OutputEnabled", false, true )); + if (ChannelConfig->GetName()) { + AddChannel( ChannelConfig->GetName(), + ChannelConfig->GetChBool( "InputEnabled", true, true ), + ChannelConfig->GetChBool( "OutputEnabled", false, true )); } - - // Next - TempMember = TempMember->GetNextPeer(); + ChannelConfig = ChannelConfig->GetNextPeer(); } return true; } //--------------------------------------------------------------------------- -bool CFunctionCore::LoadChannelLinkData() +bool CFunctionCore::InitChannelLinks( CDataMember * LinkConfig ) { TChannel * Channel; CDataMember * ChannelMember; CDataMember * FunctionMember; + // Validate + if (!LinkConfig) + return false; + // Process each Channel - ChannelMember = LinkConfigMember->GetFirstChild(); + ChannelMember = LinkConfig->GetFirstChild(); while (ChannelMember) { if ((Channel = GetChannel( ChannelMember->GetName() ))) { - FunctionMember = ChannelMember->GetFirstChild(); + FunctionMember = ChannelMember->GetElement( 0 ); while (FunctionMember) { // Get Parameters @@ -200,11 +191,9 @@ bool CFunctionCore::LoadChannelLinkData() FunctionMember->GetChStr( "Function" ), FunctionMember->GetChStr( "Channel" ), FunctionMember->GetChBool( "Bidirectional" ) ); - // Next FunctionMember = FunctionMember->GetNextPeer(); } } - // Next ChannelMember = ChannelMember->GetNextPeer(); } @@ -212,69 +201,6 @@ bool CFunctionCore::LoadChannelLinkData() } //--------------------------------------------------------------------------- -bool CFunctionCore::Init() -{ - // Report status - if (Log) Log->Message( LogLevel, dlLow, "%s: Function '%s' - Initialised", ProcessName, Name ); - - return true; -} -//--------------------------------------------------------------------------- - -bool CFunctionCore::InitConfig( const char * pConfigPath ) -{ - // Validate - if (!DataTree || !(ConfigMember = DataTree->GetChild( pConfigPath, true ))) - return false; - - // Load configuration - LoadConfigData(); - Init(); - - return true; -} -//--------------------------------------------------------------------------- - -bool CFunctionCore::InitConfig( CDataMember * pBaseMember ) -{ - // Validate - if (!DataTree || !(ConfigMember = pBaseMember )) - return false; - - // Load configuration - LoadConfigData(); - Init(); - - return true; -} -//--------------------------------------------------------------------------- - -bool CFunctionCore::InitChannelLinks( const char * pLinkConfigPath ) -{ - // Validate - if (!DataTree || !(LinkConfigMember = DataTree->GetChild( pLinkConfigPath, true ))) - return false; - - // Load configuration - LoadChannelLinkData(); - - return true; -} -//--------------------------------------------------------------------------- - -bool CFunctionCore::InitChannelLinks( CDataMember *pLinkConfigMember ) -{ - // Validate - if (!DataTree || !(LinkConfigMember = pLinkConfigMember)) - return false; - - // Load configuration - LoadChannelLinkData(); - - return true; -} -//--------------------------------------------------------------------------- - bool CFunctionCore::SetLogParam( EDebugLevel pDebugLevel, int pOutputDisplay ) { // Output diff --git a/FunctionCore.h b/FunctionCore.h index 3817137..e262bf3 100644 --- a/FunctionCore.h +++ b/FunctionCore.h @@ -48,20 +48,21 @@ struct SChannelLink }; //--------------------------------------------------------------------------- +// Function Constructor +#define TYPE_FUNCTION "Function" +//CFunctionCore * NewFunctionCore( const char * Name ); + +//--------------------------------------------------------------------------- + class CFunctionCore { protected: // Function Definition - char * Name; - char * Type; - - // Configuration - CDataMember * DataTree; - CDataMember * ConfigMember; - CDataMember * LinkConfigMember; + const char * Type; + char * Name; // Channels - TChannel * FirstChannel; + TChannel * FirstChannel; // Logging CLogCore * Log; @@ -73,35 +74,26 @@ protected: int StoredOutputLen; // Manage Channel - inline TChannel * GetChannel( const char * Name ) { - if (!Name) return NULL; + inline TChannel * GetChannel( const char * pName ) { + if (!pName) return NULL; TChannel * Channel = FirstChannel; - while (Channel && strcmp( Name, Channel->Name )) + while (Channel && strcmp( pName, Channel->Name )) Channel = Channel->Next; return Channel; } - // Load configuration - virtual bool LoadConfigData(); - virtual bool LoadChannelLinkData(); - // Data Input/Output virtual int Output( const TChannel * Channel, const char * Data, int Len ); virtual bool PullInput( TChannel * Channel ); public: // Life cycle - CFunctionCore( const char * pName, const char * Type ); + CFunctionCore( const char * pName, const char * pType = TYPE_FUNCTION ); virtual ~CFunctionCore(); // Load Configuration - virtual bool Init(); - - bool InitConfig( const char * pConfigPath ); - bool InitConfig( CDataMember * pConfigMember ); - - bool InitChannelLinks( const char * pLinkConfigPath ); - bool InitChannelLinks( CDataMember *pLinkConfigMember ); + virtual bool Init( CDataMember * FunctionConfig ); + virtual bool InitChannelLinks( CDataMember *LinkConfig ); // Set Parameters Manually bool SetLogParam( EDebugLevel pDebugLevel, int pOutputDisplay ); diff --git a/JSONparseCore.cpp b/JSONparseCore.cpp index 48284b4..6bf9c24 100644 --- a/JSONparseCore.cpp +++ b/JSONparseCore.cpp @@ -819,6 +819,13 @@ bool CJSONparse::PrintObject( CDataMember * Object, const int Indent ) if (write( OutputHandle, "{", 1 ) < 0) return false; + // Check if empty + if (Object->Len == 0) { + if (write( OutputHandle, "}", 1 ) < 0) + return false; + return true; + } + // Extend spacer if (Indent) { memset( &Spacer[SpacerLen], ' ', 2 ); @@ -930,6 +937,13 @@ bool CJSONparse::PrintArray( CDataMember * Array, const int Indent ) if (write( OutputHandle, "[", 1 ) < 0) return false; + // Check if empty + if (Array->Len == 0) { + if (write( OutputHandle, "]", 1 ) < 0) + return false; + return true; + } + // Extend spacer if (Indent) { memset( &Spacer[SpacerLen], ' ', 2 ); diff --git a/SelectableCore.cpp b/SelectableCore.cpp index b277310..c8dd01f 100644 --- a/SelectableCore.cpp +++ b/SelectableCore.cpp @@ -34,8 +34,13 @@ extern CApplication * Application; //--------------------------------------------------------------------------- -CSelectableCore::CSelectableCore( const char * pName, const char * pType ) : - CFunctionCore( pName, pType ) +// Function Constructor +CFunctionCore * NewSelectableCore( const char * Name ) { + return (CFunctionCore*) new CSelectableCore( Name ); +} +//--------------------------------------------------------------------------- + +CSelectableCore::CSelectableCore( const char * pName, const char * pType ) : CFunctionCore( pName, pType ) { // Quick access Selector = Application->Selector; @@ -64,53 +69,47 @@ CSelectableCore::~CSelectableCore() } //--------------------------------------------------------------------------- -bool CSelectableCore::LoadConfigData() +bool CSelectableCore::Init( CDataMember * FunctionConfig ) { - CDataMember * TempMember; + CDataMember * HandleConfig; + CDataMember * AddressDef; CDataMember * SerialConfig; THandle * Handle; char * Type; char * Name; - char Path[100]; char * Address; char * Port; char * ParityText; char * FlowCtrlText; short Parity; short FlowCtrl; + short Queue; long Delay; // Call Previous load config - CFunctionCore::LoadConfigData(); + if (!CFunctionCore::Init( FunctionConfig )) + return false; // Load Handles - if ((TempMember = ConfigMember->GetChild( "Handles", false ))) { - TempMember = TempMember->GetFirstChild(); - } - while (TempMember) + HandleConfig = FunctionConfig->GetChFirstChild( "Handles", true ); + while (HandleConfig) { - // Check if name is valid - if (!TempMember->GetName() || !*TempMember->GetName()) - continue; - // Create Handle and channel link - Handle = CreateHandle( TempMember->GetName(), false ); - Handle->Channel = GetChannel( TempMember->GetChStr( "Channel" ) ); + Handle = CreateHandle( HandleConfig->GetName(), false ); + Handle->Channel = GetChannel( HandleConfig->GetChStr( "Channel" ) ); - Type = (char*)TempMember->GetChStr( "Type", "TCPclient", true ); + Type = (char*)HandleConfig->GetChStr( "Type", "TCPclient", true ); if (!strcasecmp( Type, "Serial" )) { - if ((Name = (char*)TempMember->GetChStr( "Port/Name", NULL ))) { - sprintf( Path, "Address/%s/Address", Name ); - Address = (char*)DataTree->GetChStr( Path, NULL, true ); // Get address list value - } - else { - Address = (char*)TempMember->GetChStr( "Port/Address", NULL, true ); // Get default value + if ((Name = (char*)HandleConfig->GetChStr( "Port/Name", NULL )) && (AddressDef = Application->AddressList->GetChild( Name ))) { + Address = (char*)AddressDef->GetChStr( "Address", NULL, true ); // Get address list value + } else { + Address = (char*)HandleConfig->GetChStr( "Port/Address", NULL, true ); // Get default value } SetSerialHandle( Handle, Address ); // Update configuration if specified - if ((SerialConfig = TempMember->GetChild( "Port/SerialConfig", false ))) + if ((SerialConfig = HandleConfig->GetChild( "Port/SerialConfig", false ))) { ParityText = (char*)SerialConfig->GetChStr( "Parity", "none", true ); if (!strcasecmp( ParityText, "none" )) @@ -143,117 +142,101 @@ bool CSelectableCore::LoadConfigData() } else if (!strcasecmp( Type, "LinePrinter" )) { - if ((Name = (char*)TempMember->GetChStr( "Port/Name", NULL ))) { - sprintf( Path, "Address/%s/Address", Name ); - Address = (char*)DataTree->GetChStr( Path, NULL, true ); // Get address list value - } - else { - Address = (char*)TempMember->GetChStr( "Port/Address", NULL, true ); // Get default value + if ((Name = (char*)HandleConfig->GetChStr( "Port/Name", NULL )) && (AddressDef = Application->AddressList->GetChild( Name ))) { + Address = (char*)AddressDef->GetChStr( "Address", NULL, true ); // Get address list value + } else { + Address = (char*)HandleConfig->GetChStr( "Port/Address", NULL, true ); // Get default value } SetLinePrinterHandle( Handle, Address ); } else if (!strcasecmp( Type, "UNIXserver" )) { - if ((Name = (char*)TempMember->GetChStr( "Socket/Name", NULL ))) { - sprintf( Path, "Address/%s/Address", Name ); - Address = (char*)DataTree->GetChStr( Path, NULL, true ); // Get AddressList Address value + if ((Name = (char*)HandleConfig->GetChStr( "Socket/Name", NULL )) && (AddressDef = Application->AddressList->GetChild( Name ))) { + Address = (char*)AddressDef->GetChStr( "Address", NULL, true ); // Get address list value + } else { + Address = (char*)HandleConfig->GetChStr( "Socket/Address", NULL, true ); // Get default Address value } - else { - Address = (char*)TempMember->GetChStr( "Socket/Address", NULL, true ); // Get default Address value - } - SetUnixHandle( Handle, ctUNIXserver, Address ); + Queue = HandleConfig->GetChInt( "Socket/Queue", 2, true ); + SetUnixHandle( Handle, ctUNIXserver, Address, Queue ); } else if (!strcasecmp( Type, "UNIXclient" )) { - if ((Name = (char*)TempMember->GetChStr( "Socket/Name", NULL ))) { - sprintf( Path, "Address/%s/Address", Name ); - Address = (char*)DataTree->GetChStr( Path, NULL, true ); // Get AddressList Address value + if ((Name = (char*)HandleConfig->GetChStr( "Socket/Name", NULL )) && (AddressDef = Application->AddressList->GetChild( Name ))) { + Address = (char*)AddressDef->GetChStr( "Address", NULL, true ); // Get address list value + } else { + Address = (char*)HandleConfig->GetChStr( "Socket/Address", NULL, true ); // Get default Address value } - else { - Address = (char*)TempMember->GetChStr( "Socket/Address", NULL, true ); // Get default Address value - } - SetUnixHandle( Handle, ctUNIXclient, Address ); + SetUnixHandle( Handle, ctUNIXclient, Address, 0 ); } else if (!strcasecmp( Type, "UDPserver" )) { - if ((Name = (char*)TempMember->GetChStr( "Socket/Name", NULL ))) { - sprintf( Path, "Address/%s/Address", Name ); - Address = (char*)DataTree->GetChStr( Path, NULL, true ); // Get AddressList Address value - sprintf( Path, "Address/%s/Port", Name ); - Port = (char*)DataTree->GetChStr( Path, "0", true ); // Get AddressList Port value + if ((Name = (char*)HandleConfig->GetChStr( "Socket/Name", NULL )) && (AddressDef = Application->AddressList->GetChild( Name ))) { + Address = (char*)AddressDef->GetChStr( "Address", NULL, true ); // Get address list value + Port = (char*)AddressDef->GetChStr( "Port", "0", true ); // Get AddressList Port value + } else { + Address = (char*)HandleConfig->GetChStr( "Socket/Address", NULL, true ); // Get default Address value + Port = (char*)HandleConfig->GetChStr( "Socket/Port", "0", true ); // Get default Port value } - else { - Address = (char*)TempMember->GetChStr( "Socket/Address", NULL, true ); // Get default Address value - Port = (char*)TempMember->GetChStr( "Socket/Port", "0", true ); // Get default Port value - } - Delay = TempMember->GetChInt( "Socket/ResolveDelay", 0, true ); - SetSocketHandle( Handle, ctUDPserver, Address, strlcase(Port), Delay ); + Delay = HandleConfig->GetChInt( "Socket/ResolveDelay", 0, true ); + SetSocketHandle( Handle, ctUDPserver, Address, strlcase(Port), 0, Delay ); } else if (!strcasecmp( Type, "UDPclient" )) { - if ((Name = (char*)TempMember->GetChStr( "Socket/Name", NULL ))) { - sprintf( Path, "Address/%s/Address", Name ); - Address = (char*)DataTree->GetChStr( Path, NULL, true ); // Get AddressList Address value - sprintf( Path, "Address/%s/Port", Name ); - Port = (char*)DataTree->GetChStr( Path, "0", true ); // Get AddressList Port value + if ((Name = (char*)HandleConfig->GetChStr( "Socket/Name", NULL )) && (AddressDef = Application->AddressList->GetChild( Name ))) { + Address = (char*)AddressDef->GetChStr( "Address", NULL, true ); // Get address list value + Port = (char*)AddressDef->GetChStr( "Port", "0", true ); // Get AddressList Port value + } else { + Address = (char*)HandleConfig->GetChStr( "Socket/Address", NULL, true ); // Get default Address value + Port = (char*)HandleConfig->GetChStr( "Socket/Port", "0", true ); // Get default Port value } - else { - Address = (char*)TempMember->GetChStr( "Socket/Address", NULL, true ); // Get default Address value - Port = (char*)TempMember->GetChStr( "Socket/Port", "0", true ); // Get default Port value - } - Delay = TempMember->GetChInt( "Socket/ResolveDelay", 0, true ); - SetSocketHandle( Handle, ctUDPclient, Address, strlcase(Port), Delay ); + Delay = HandleConfig->GetChInt( "Socket/ResolveDelay", 0, true ); + SetSocketHandle( Handle, ctUDPclient, Address, strlcase(Port), 0, Delay ); } else if (!strcasecmp( Type, "TCPserver" )) { - if ((Name = (char*)TempMember->GetChStr( "Socket/Name", NULL ))) { - sprintf( Path, "Address/%s/Address", Name ); - Address = (char*)DataTree->GetChStr( Path, NULL, true ); // Get AddressList Address value - sprintf( Path, "Address/%s/Port", Name ); - Port = (char*)DataTree->GetChStr( Path, "0", true ); // Get AddressList Port value + if ((Name = (char*)HandleConfig->GetChStr( "Socket/Name", NULL )) && (AddressDef = Application->AddressList->GetChild( Name ))) { + Address = (char*)AddressDef->GetChStr( "Address", NULL, true ); // Get address list value + Port = (char*)AddressDef->GetChStr( "Port", "0", true ); // Get AddressList Port value + } else { + Address = (char*)HandleConfig->GetChStr( "Socket/Address", NULL, true ); // Get default Address value + Port = (char*)HandleConfig->GetChStr( "Socket/Port", "0", true ); // Get default Port value } - else { - Address = (char*)TempMember->GetChStr( "Socket/Address", NULL, true ); // Get default Address value - Port = (char*)TempMember->GetChStr( "Socket/Port", "0", true ); // Get default Port value - } - Delay = TempMember->GetChInt( "Socket/ResolveDelay", 0, true ); - SetSocketHandle( Handle, ctTCPserver, Address, strlcase(Port), Delay ); + Delay = HandleConfig->GetChInt( "Socket/ResolveDelay", 0, true ); + Queue = HandleConfig->GetChInt( "Socket/Queue", 2, true ); + SetSocketHandle( Handle, ctTCPserver, Address, strlcase(Port), Queue, Delay ); } else if (!strcasecmp( Type, "TCPclient" )) { - if ((Name = (char*)TempMember->GetChStr( "Socket/Name", NULL ))) { - sprintf( Path, "Address/%s/Address", Name ); - Address = (char*)DataTree->GetChStr( Path, NULL, true ); // Get AddressList Address value - sprintf( Path, "Address/%s/Port", Name ); - Port = (char*)DataTree->GetChStr( Path, "0", true ); // Get AddressList Port value + if ((Name = (char*)HandleConfig->GetChStr( "Socket/Name", NULL )) && (AddressDef = Application->AddressList->GetChild( Name ))) { + Address = (char*)AddressDef->GetChStr( "Address", NULL, true ); // Get address list value + Port = (char*)AddressDef->GetChStr( "Port", "0", true ); // Get AddressList Port value + } else { + Address = (char*)HandleConfig->GetChStr( "Socket/Address", NULL, true ); // Get default Address value + Port = (char*)HandleConfig->GetChStr( "Socket/Port", "0", true ); // Get default Port value } - else { - Address = (char*)TempMember->GetChStr( "Socket/Address", NULL, true ); // Get default Address value - Port = (char*)TempMember->GetChStr( "Socket/Port", "0", true ); // Get default Port value - } - Delay = TempMember->GetChInt( "Socket/ResolveDelay", 0, true ); - SetSocketHandle( Handle, ctTCPclient, Address, strlcase(Port), Delay ); + Delay = HandleConfig->GetChInt( "Socket/ResolveDelay", 0, true ); + SetSocketHandle( Handle, ctTCPclient, Address, strlcase(Port), 0, Delay ); } else if (!strcasecmp( Type, "ForkPipe" )) { - Address = (char*)TempMember->GetChStr( "Fork/ExecPath", NULL, true ); // Get default value + Address = (char*)HandleConfig->GetChStr( "Fork/ExecPath", NULL, true ); // Get default value SetForkPipeHandle( Handle, Address ); } - // Set Auto Mange - SetAutoManage( Handle, TempMember->GetChBool( "AutoManage/Enabled", true, true ), - TempMember->GetChBool( "AutoManage/Persistent", false, true ), - TempMember->GetChInt( "AutoManage/ReopenDelay", 2000, true ), - TempMember->GetChInt( "AutoManage/CloseTimeout", 2000, true )); + // Set Auto Manage + SetAutoManage( Handle, HandleConfig->GetChBool( "AutoManage/Enabled", true, true ), + HandleConfig->GetChBool( "AutoManage/Persistent", false, true ), + HandleConfig->GetChInt( "AutoManage/ReopenDelay", 2000, true ), + HandleConfig->GetChInt( "AutoManage/CloseTimeout", 2000, true )); // Input buffer - SetInBuffer( Handle, TempMember->GetChInt( "InputBuffer/Size", 0 ), - TempMember->GetChInt( "InputBuffer/Timeout", 250 ), - TempMember->GetChStr( "InputBuffer/Marker", "" ), - TempMember->GetChInt( "InputBuffer/MarkerLen", 0 ) ); - SetOutBuffer( Handle, TempMember->GetChInt( "OutputBuffer/Size", 0 ) ); + SetInBuffer( Handle, HandleConfig->GetChInt( "InputBuffer/Size", 0 ), + HandleConfig->GetChInt( "InputBuffer/Timeout", 250 ), + HandleConfig->GetChStr( "InputBuffer/Marker", "" ), + HandleConfig->GetChInt( "InputBuffer/MarkerLen", 0 ) ); + SetOutBuffer( Handle, HandleConfig->GetChInt( "OutputBuffer/Size", 0 ) ); // Next - TempMember = TempMember->GetNextPeer(); + HandleConfig = HandleConfig->GetNextPeer(); } return true; @@ -458,7 +441,7 @@ bool CSelectableCore::SetForkPipeHandle( THandle * Handle, const char * ExecPath } //--------------------------------------------------------------------------- -bool CSelectableCore::SetUnixHandle( THandle * Handle, EConnectType Type, const char * FileName ) +bool CSelectableCore::SetUnixHandle( THandle * Handle, EConnectType Type, const char * FileName, short Queue ) { // Validate if (!Handle || !FileName || @@ -478,6 +461,7 @@ bool CSelectableCore::SetUnixHandle( THandle * Handle, EConnectType Type, const // Set name Handle->Path = (char*)malloc( strlen(FileName)+1 ); strcpy( Handle->Path, FileName ); + Handle->Queue = Queue; // Log event if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Set as %s [%s]", @@ -486,7 +470,7 @@ bool CSelectableCore::SetUnixHandle( THandle * Handle, EConnectType Type, const } //--------------------------------------------------------------------------- -bool CSelectableCore::SetSocketHandle( THandle * Handle, EConnectType Type, const char * HostName, const char * PortName, long ResolveDelay ) +bool CSelectableCore::SetSocketHandle( THandle * Handle, EConnectType Type, const char * HostName, const char * PortName, short Queue, long ResolveDelay ) { // Validate if (!Handle || !HostName || !PortName || @@ -517,6 +501,8 @@ bool CSelectableCore::SetSocketHandle( THandle * Handle, EConnectType Type, con Handle->AddressList = NULL; Handle->AddressInfo = NULL; + Handle->Queue = Queue; + // Log event if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Set as %s [%s:%s]", ProcessName, Name, Handle->Name, ConnectTypeName[Type], HostName, PortName ); @@ -897,7 +883,7 @@ THandle * CSelectableCore::OpenUNIXserverSocket( THandle * Handle ) }; // Create que for 5 connections - if (listen( Handle->FD, 5 ) < 0) + if (listen( Handle->FD, Handle->Queue ) < 0) { // Log Event if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Failed to listen on UNIX Server socket [%s] (%s)", @@ -1060,7 +1046,7 @@ THandle * CSelectableCore::OpenUNIXremoteSocket( THandle * Handle ) // Create Remote Client Handle sprintf( ClientName, "%s-%d", Handle->Name, ClientFD ); *RemoteClient = CreateHandle( ClientName, false ); - if (!SetUnixHandle( *RemoteClient, ctUNIXremote, Handle->Path )) { + if (!SetUnixHandle( *RemoteClient, ctUNIXremote, Handle->Path, 0 )) { if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - UNIX Server failed to configure Remote Client connection (%s)", ProcessName, Name, Handle->Name, strerror(errno) ); return NULL; @@ -1286,7 +1272,7 @@ THandle * CSelectableCore::OpenUDPremoteSocket( THandle * Handle, char * ClientA // Create Remote Client Handle sprintf( ClientName, "%s-%d", Handle->Name, ClientCount ); *RemoteClient = CreateHandle( ClientName, false ); - if (!SetSocketHandle( *RemoteClient, ctUDPremote, ClientAddress, ClientPort, 0 )) { + if (!SetSocketHandle( *RemoteClient, ctUDPremote, ClientAddress, ClientPort, 0, 0 )) { if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - UDP Server failed to configure Remote Client connection (%s)", ProcessName, Name, Handle->Name, strerror(errno) ); return NULL; @@ -1442,7 +1428,7 @@ THandle * CSelectableCore::OpenTCPserverSocket( THandle * Handle, bool DelayReso }; // Create que for 5 connections - if (listen( Handle->FD, 5 ) < 0) + if (listen( Handle->FD, Handle->Queue ) < 0) { // Log Event if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Failed to listen on TCP Server socket [%s:%s] (%s)", @@ -1524,7 +1510,7 @@ THandle * CSelectableCore::OpenTCPremoteSocket( THandle * Handle ) // Create Remote Client Handle sprintf( ClientName, "%s-%d", Handle->Name, ClientFD ); *RemoteClient = CreateHandle( ClientName, false ); - if (!SetSocketHandle( *RemoteClient, ctTCPremote, ClientAddress, ClientPort, 0 )) { + if (!SetSocketHandle( *RemoteClient, ctTCPremote, ClientAddress, ClientPort, 0, 0 )) { if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - TCP Server failed to configure Remote Client connection (%s)", ProcessName, Name, Handle->Name, strerror(errno) ); return NULL; diff --git a/SelectableCore.h b/SelectableCore.h index dd3d71c..0324f9f 100644 --- a/SelectableCore.h +++ b/SelectableCore.h @@ -100,6 +100,7 @@ struct SHandle { struct addrinfo * AddressList; // List of resolved IP Addresses for host name struct addrinfo * AddressInfo; // Current selected IP Address bool AddressFailed; // Indicate failure to connect to address + short Queue; // Max waiting connections long ResolveDelay; // Delay before resolving hostname via DNS // Serial Port config @@ -173,6 +174,12 @@ public: //--------------------------------------------------------------------------- +// Function Constructor +#define TYPE_SELECTABLE "Selectable" +CFunctionCore * NewSelectableCore( const char * Name ); + +//--------------------------------------------------------------------------- + class CSelectableCore : public CFunctionCore { protected: @@ -182,9 +189,6 @@ protected: // Select interface CSelect * Selector; - // Configuration - virtual bool LoadConfigData(); - // Managing File Handles bool RemoveHandle( THandle * Handle ); bool DestroyHandle( THandle * Handle ); @@ -248,9 +252,12 @@ protected: public: // Life Cycle - CSelectableCore( const char * Name, const char * pType = "Selectable" ); + CSelectableCore( const char * Name, const char * Type = TYPE_SELECTABLE ); virtual ~CSelectableCore(); + // Configuration + virtual bool Init( CDataMember * FunctionConfig ); + // Finding Handles inline THandle * GetHandle( const char * HandleName ) { @@ -281,8 +288,8 @@ public: bool SetSerialHandleConfig( THandle * Handle, int Baudrate, short DataBits, short Parity, short StopBits, short FlowCtrl, int DataWait ); bool SetLinePrinterHandle( THandle * Handle, const char * FileName ); bool SetForkPipeHandle( THandle * Handle, const char * ExecPath ); - bool SetUnixHandle( THandle * Handle, EConnectType Type, const char * FileName ); - bool SetSocketHandle( THandle * Handle, EConnectType Type, const char * HostName, const char * PortName, long ResolveDelay ); + bool SetUnixHandle( THandle * Handle, EConnectType Type, const char * FileName, short Queue ); + bool SetSocketHandle( THandle * Handle, EConnectType Type, const char * HostName, const char * PortName, short Queue, long ResolveDelay ); bool ClearHandle( THandle * Handle ); // FD Operations diff --git a/WatchdogCore.cpp b/WatchdogCore.cpp index 79638e2..af11199 100644 --- a/WatchdogCore.cpp +++ b/WatchdogCore.cpp @@ -20,8 +20,13 @@ extern char * ProcessName; //--------------------------------------------------------------------------- -CWatchdogCore::CWatchdogCore( const char * pName ) : - CSelectableCore( pName, "WatchdogClient" ) +// Function Constructor +CFunctionCore * NewWatchdogCore( const char * Name ) { + return (CFunctionCore*) new CWatchdogCore( Name ); +} +//--------------------------------------------------------------------------- + +CWatchdogCore::CWatchdogCore( const char * pName, const char * pType ) : CSelectableCore( pName, pType ) { // Create protocol Protocol = new CLiteProtocol( 50, '\x02', '\x03', '\x00' ); @@ -44,18 +49,6 @@ CWatchdogCore::~CWatchdogCore() } //--------------------------------------------------------------------------- -bool CWatchdogCore::LoadConfigData() -{ - // Call Previous load config - CSelectableCore::LoadConfigData(); - - // Set specific parameters - SetInterval( ConfigMember->GetChInt( "Parameters/PingInterval", 500, true )); - - return true; -} -//--------------------------------------------------------------------------- - bool CWatchdogCore::SetInterval( int pPingInterval ) { PingInterval = pPingInterval; @@ -63,14 +56,20 @@ bool CWatchdogCore::SetInterval( int pPingInterval ) } //--------------------------------------------------------------------------- -bool CWatchdogCore::Init() +bool CWatchdogCore::Init( CDataMember * FunctionConfig ) { + // Call Previous ingi + if (!CSelectableCore::Init( FunctionConfig )) + return false; + + // Set specific parameters + SetInterval( FunctionConfig->GetChInt( "Parameters/PingInterval", 500, true )); + // Create handle and set reference, if not done if (!(Ping = GetHandle( "Ping" ))) Ping = CreateHandle( "Ping", false ); - // Previous init - return CSelectableCore::Init(); + return true; } //--------------------------------------------------------------------------- diff --git a/WatchdogCore.h b/WatchdogCore.h index 7b9a802..1ac7767 100644 --- a/WatchdogCore.h +++ b/WatchdogCore.h @@ -17,6 +17,12 @@ //--------------------------------------------------------------------------- +// Function Constructor +#define TYPE_WATCHDOG "Watchdog" +CFunctionCore * NewWatchdogCore( const char * Name ); + +//--------------------------------------------------------------------------- + class CWatchdogCore : public CSelectableCore { private: @@ -32,17 +38,14 @@ private: public: // Life Cycle - CWatchdogCore( const char * pName ); + CWatchdogCore( const char * pName, const char * pType = TYPE_WATCHDOG ); virtual ~CWatchdogCore(); - // Load Configuration - virtual bool LoadConfigData(); - // Manually set Configuration bool SetInterval( int pPingInterval ); // Initialisation - virtual bool Init(); + virtual bool Init( CDataMember * FunctionConfig ); // Process virtual bool Process();