Major Update:
- Implement consistent Function addition to application
- Use TYPE_XXX constants to declare function type
- Use NewXXXX() methods to call constructor correctly
- Add FunctionType list (with constructor) to Application
- Create Function by comparison to FunctionType list
- Simplify LoadConfig() and Init() methods for functions
- Combine methods into Init() method
- Pass relevant data member to Init() method
- Remove all CDataMember references on functions
- ApplicationCore:
- Split ReadParam() method from LoadConfig() method
- Split main configuration into separate files:
- config/ - main config file, general application settings
- definition/ - application definition, e.g. function blocks
- Definition and Address List files specified in config file
- Load address file in address/ branch
- Made DataTree & JSONparser private
- Made Config, Definition & Address branches public
- Removed unnecessary branch references
- Improved event logging
- DataTreeCore:
- Allow GetChFirstChild & GetChElement to create parent branches
with correct type, ie. Object/Array
- Remove unnecessary Create param from GetXxx functions
- Bug fix: Print empty objects/arrays correct, ie. empty brackets
- Bug fix: Adding element at specific index
- Bug fix: Error when get/create string value with "null"
- FunctionCore:
- Type param now set as constant via constructor
- Create empty Handles & Channels objects if none in Config
- SelectableCore:
- Add Queue length parameter to handles for UNIX and TCP sockets
- DeviceCore:
- Bug fix: missing Process() method
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
#include "ApplicationCore.h"
|
||||
#include "WatchdogCore.h"
|
||||
#include "FileCore.h"
|
||||
#include "DeviceCore.h"
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
@@ -25,11 +26,7 @@ CApplication::CApplication( EDebugLevel pLogLevel )
|
||||
// Set signal handlers
|
||||
ConfigureSignalHandlers();
|
||||
|
||||
// Variables used for configuration
|
||||
ConfigMember = NULL;
|
||||
FunctionConfigMember = NULL;
|
||||
LinkConfigMember = NULL;
|
||||
|
||||
DefinitionFile = NULL;
|
||||
ConfigFile = NULL;
|
||||
AddressFile = NULL;
|
||||
|
||||
@@ -40,22 +37,32 @@ CApplication::CApplication( EDebugLevel pLogLevel )
|
||||
|
||||
// Create Configuration
|
||||
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;
|
||||
|
||||
// List
|
||||
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)
|
||||
{
|
||||
@@ -64,6 +71,14 @@ CApplication::~CApplication()
|
||||
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;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -23,16 +23,25 @@
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
// Preview
|
||||
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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
158
FunctionCore.cpp
158
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,26 +38,9 @@ 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;
|
||||
|
||||
// Logging
|
||||
Log = Application->Log;
|
||||
LogLevel = dlNone;
|
||||
@@ -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"))
|
||||
if (!strcasecmp( TempStr, "Normal")) // Normal ASCII -> Unless "AsIs", print special chars as "."
|
||||
pLogOutput |= OUT_NORMAL;
|
||||
else if (!strcasecmp( TempStr, "Bin"))
|
||||
else if (!strcasecmp( TempStr, "Bin")) // Print as Binary value ('1' and '0')
|
||||
pLogOutput |= OUT_BIN;
|
||||
else if (!strcasecmp( TempStr, "Hex"))
|
||||
else if (!strcasecmp( TempStr, "Hex")) // Print as Hexadecimal value (0-9,A-F)
|
||||
pLogOutput |= OUT_HEX;
|
||||
else if (!strcasecmp( TempStr, "Count"))
|
||||
else if (!strcasecmp( TempStr, "Count")) // Print number of characters
|
||||
pLogOutput |= OUT_COUNT;
|
||||
else if (!strcasecmp( TempStr, "AsIs"))
|
||||
else if (!strcasecmp( TempStr, "AsIs")) // Use with "Normal" -> Do not print special chars as "."
|
||||
pLogOutput |= OUT_ASIS;
|
||||
else if (!strcasecmp( TempStr, "CRLF"))
|
||||
else if (!strcasecmp( TempStr, "CRLF")) // Add \r\n at end of line if not present
|
||||
pLogOutput |= OUT_CRLF;
|
||||
else
|
||||
pLogOutput |= OUT_NORMAL;
|
||||
}
|
||||
|
||||
// Next
|
||||
TempMember = TempMember->GetNextPeer();
|
||||
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
|
||||
|
||||
@@ -48,17 +48,18 @@ struct SChannelLink
|
||||
};
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
// Function Constructor
|
||||
#define TYPE_FUNCTION "Function"
|
||||
//CFunctionCore * NewFunctionCore( const char * Name );
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
class CFunctionCore
|
||||
{
|
||||
protected:
|
||||
// Function Definition
|
||||
const char * Type;
|
||||
char * Name;
|
||||
char * Type;
|
||||
|
||||
// Configuration
|
||||
CDataMember * DataTree;
|
||||
CDataMember * ConfigMember;
|
||||
CDataMember * LinkConfigMember;
|
||||
|
||||
// Channels
|
||||
TChannel * FirstChannel;
|
||||
@@ -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 );
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user