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:
Charl Wentzel
2018-11-24 13:35:23 +02:00
parent 7434334280
commit a972fb9101
15 changed files with 518 additions and 469 deletions

View File

@@ -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;