Major update:
- General bug fixes - Implement search for multi-character marker search in BufferCore Replaced FindChar() method with FindStr() method - Implemented LocalIO and LinkedIO in FunctionCore - Connect LocalIO with FD in SelectableCore - Implement Write buffer with Write Select in SelectableCore - Improve validation checks in SelectableCore - Use Handle ptr instead of Handle Names for Config methods
This commit is contained in:
@@ -243,7 +243,7 @@ int CBuffer::ReadFromFD( int Handle, int MaxRead )
|
|||||||
// Read from file descriptor
|
// Read from file descriptor
|
||||||
BufRemain = BufSize - BufEnd;
|
BufRemain = BufSize - BufEnd;
|
||||||
BytesRead = read( Handle, &Buffer[BufEnd], ((BufRemain > DataRemain)? DataRemain : BufRemain) );
|
BytesRead = read( Handle, &Buffer[BufEnd], ((BufRemain > DataRemain)? DataRemain : BufRemain) );
|
||||||
if (BytesRead < 0)
|
if (BytesRead <= 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Update Buffer Pointers
|
// Update Buffer Pointers
|
||||||
@@ -283,7 +283,7 @@ int CBuffer::WriteToFD( int Handle, int MaxLen )
|
|||||||
// Read Data into buffer
|
// Read Data into buffer
|
||||||
ReadPos = BufStart;
|
ReadPos = BufStart;
|
||||||
DataRemain = (MaxLen == -1)? BufLen : MaxLen;
|
DataRemain = (MaxLen == -1)? BufLen : MaxLen;
|
||||||
while ((TotalWritten < MaxLen) && (BufLen > 0))
|
while (DataRemain)
|
||||||
{
|
{
|
||||||
// Read from file descriptor
|
// Read from file descriptor
|
||||||
BufRemain = BufSize - ReadPos;
|
BufRemain = BufSize - ReadPos;
|
||||||
@@ -336,10 +336,12 @@ char CBuffer::PeekChar( int Pos, bool ClearChar )
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
// Look for first occurrence of character in buffer
|
// Look for first occurrence of character in buffer
|
||||||
bool CBuffer::FindChar( char SearchChar, int &FoundPos, int StartPos )
|
bool CBuffer::FindStr( const char * SearchStr, int SearchLen, int &FoundPos, int StartPos )
|
||||||
{
|
{
|
||||||
char * CheckPos;
|
char * CheckPos = NULL;
|
||||||
char * Limit;
|
char * CheckLimit = NULL;
|
||||||
|
char * MatchPos = NULL;
|
||||||
|
char * MatchLimit = NULL;
|
||||||
|
|
||||||
// Check if buffer exists
|
// Check if buffer exists
|
||||||
if (!BufLen) {
|
if (!BufLen) {
|
||||||
@@ -353,24 +355,35 @@ bool CBuffer::FindChar( char SearchChar, int &FoundPos, int StartPos )
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get Search start point
|
// Get Search start point and limit
|
||||||
if (BufStart + StartPos < BufSize) {
|
CheckPos = (BufStart + StartPos < BufSize)? &Buffer[ BufStart+StartPos ] : &Buffer[ (BufStart+StartPos)-BufSize ];
|
||||||
CheckPos = &Buffer[ BufStart+StartPos ];
|
CheckLimit = &Buffer[BufSize-1];
|
||||||
} else {
|
|
||||||
CheckPos = &Buffer[ (BufStart+StartPos)-BufSize ];
|
// Set Match start point and limit
|
||||||
}
|
MatchPos = (char*)SearchStr;
|
||||||
|
MatchLimit = (char*)&SearchStr[SearchLen-1];
|
||||||
|
|
||||||
// Search for char
|
// Search for char
|
||||||
FoundPos = StartPos;
|
FoundPos = StartPos;
|
||||||
Limit = &Buffer[BufSize-1];
|
|
||||||
while (FoundPos < BufLen)
|
while (FoundPos < BufLen)
|
||||||
{
|
{
|
||||||
if (*CheckPos == SearchChar)
|
// Check if char match
|
||||||
return true;
|
if (*CheckPos == *MatchPos) {
|
||||||
|
if (MatchPos == MatchLimit)
|
||||||
|
// Full match found
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
// Next char to match
|
||||||
|
MatchPos++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Reset match point
|
||||||
|
MatchPos = (char*)SearchStr;
|
||||||
|
}
|
||||||
|
|
||||||
// Next char
|
// Next char
|
||||||
FoundPos++;
|
FoundPos++;
|
||||||
if (CheckPos == Limit) {
|
if (CheckPos == CheckLimit) {
|
||||||
CheckPos = Buffer; // Roll-over, Start at beginning of buffer
|
CheckPos = Buffer; // Roll-over, Start at beginning of buffer
|
||||||
} else {
|
} else {
|
||||||
CheckPos++;
|
CheckPos++;
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ public:
|
|||||||
|
|
||||||
// Character Operations
|
// Character Operations
|
||||||
char PeekChar( int Pos = 0, bool ClearChar = false );
|
char PeekChar( int Pos = 0, bool ClearChar = false );
|
||||||
bool FindChar( char SearchChar, int &FoundPos, int StartPos = 0 );
|
bool FindStr( const char * SearchStr, int SearchLen, int &FoundPos, int StartPos = 0 );
|
||||||
|
|
||||||
// Miscellaneous
|
// Miscellaneous
|
||||||
inline int Size() { return BufSize; };
|
inline int Size() { return BufSize; };
|
||||||
|
|||||||
169
FunctionCore.cpp
169
FunctionCore.cpp
@@ -30,42 +30,193 @@ CFunctionCore::CFunctionCore( const char * FunctionName )
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IO Functions
|
// IO Functions
|
||||||
OutFunction = NULL;
|
FirstIO = NULL;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
CFunctionCore::~CFunctionCore()
|
CFunctionCore::~CFunctionCore()
|
||||||
{
|
{
|
||||||
|
TLocalIO * NextIO = NULL;
|
||||||
|
TLinkedIO * NextLinkedIO = NULL;
|
||||||
|
|
||||||
// Destroy pointers
|
// Destroy pointers
|
||||||
if (Name) {
|
if (Name) {
|
||||||
free( Name );
|
free( Name );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Destroy IO
|
||||||
|
while (FirstIO)
|
||||||
|
{
|
||||||
|
// Destroy Parameters
|
||||||
|
if (FirstIO->Name) {
|
||||||
|
free( FirstIO->Name );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy Linked Inputs
|
||||||
|
while (FirstIO->FirstInput) {
|
||||||
|
if (FirstIO->FirstInput->IOName) {
|
||||||
|
free( FirstIO->FirstInput->IOName );
|
||||||
|
}
|
||||||
|
NextLinkedIO = FirstIO->FirstInput->Next;
|
||||||
|
free( FirstIO->FirstInput );
|
||||||
|
FirstIO->FirstInput = NextLinkedIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy Linked Outputs
|
||||||
|
while (FirstIO->FirstOutput) {
|
||||||
|
if (FirstIO->FirstOutput->IOName) {
|
||||||
|
free( FirstIO->FirstOutput->IOName );
|
||||||
|
}
|
||||||
|
NextLinkedIO = FirstIO->FirstOutput->Next;
|
||||||
|
free( FirstIO->FirstOutput );
|
||||||
|
FirstIO->FirstOutput = NextLinkedIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy Local IO
|
||||||
|
// Destroy Local IO
|
||||||
|
NextIO = FirstIO->Next;
|
||||||
|
free( FirstIO );
|
||||||
|
FirstIO = NextIO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
TLocalIO * CFunctionCore::AddLocalIO( const char * IOName )
|
||||||
|
{
|
||||||
|
TLocalIO ** LocalIO = NULL;
|
||||||
|
|
||||||
|
// Validate
|
||||||
|
if (!IOName) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if exists
|
||||||
|
LocalIO = &FirstIO;
|
||||||
|
while (*LocalIO && strcmp( IOName, (*LocalIO)->Name )) {
|
||||||
|
LocalIO = &((*LocalIO)->Next);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create if not exist
|
||||||
|
if (!*LocalIO) {
|
||||||
|
// Create
|
||||||
|
*LocalIO = (TLocalIO*)malloc( sizeof(TLocalIO) );
|
||||||
|
memset( *LocalIO, 0, sizeof(TLocalIO) );
|
||||||
|
|
||||||
|
// Set Name
|
||||||
|
(*LocalIO)->Name = (char*)malloc( strlen(IOName)+1 );
|
||||||
|
strcpy( (*LocalIO)->Name, IOName );
|
||||||
|
}
|
||||||
|
|
||||||
|
return *LocalIO;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
// Manual Data Input/Output
|
// Manual Data Input/Output
|
||||||
int CFunctionCore::Input( int InputID, const char * Buffer, int MaxLen )
|
int CFunctionCore::Input( const char * IOName, const char * Buffer, int MaxLen )
|
||||||
{
|
{
|
||||||
return 0;
|
TLocalIO * LocalIO = NULL;
|
||||||
|
|
||||||
|
// Validate
|
||||||
|
if (!IOName || !Buffer) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (MaxLen == -1) {
|
||||||
|
MaxLen = strlen( Buffer );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get IO
|
||||||
|
if (!(LocalIO = GetLocalIO( IOName ))) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do something and acknowledge size received
|
||||||
|
return MaxLen;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
int CFunctionCore::Output( int OutputID, const char * Buffer, int Len )
|
int CFunctionCore::Output( const char * IOName, const char * Buffer, int Len )
|
||||||
{
|
{
|
||||||
return 0;
|
TLocalIO * LocalIO = NULL;
|
||||||
|
|
||||||
|
// Validate
|
||||||
|
if (!IOName || !Buffer) {
|
||||||
|
return 0;
|
||||||
|
} else if (Len == -1) {
|
||||||
|
Len = strlen( Buffer );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get IO
|
||||||
|
if (!(LocalIO = GetLocalIO( IOName ))) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do something and acknowledge size received
|
||||||
|
return Len;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
// Automated Data Input/Output
|
// Automated Data Input/Output
|
||||||
bool CFunctionCore::AddInput( int InputID, CFunctionCore * OutFunction, int OutputID )
|
bool CFunctionCore::AddInput( const char * IOName, CFunctionCore * OutFunction, const char * OutputName )
|
||||||
{
|
{
|
||||||
return false;
|
TLocalIO * LocalIO = NULL;
|
||||||
|
TLinkedIO ** LinkedIO = NULL;
|
||||||
|
|
||||||
|
// Get IO
|
||||||
|
if (!(LocalIO = GetLocalIO( IOName ))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if linked IO exists
|
||||||
|
LinkedIO = &(LocalIO->FirstInput);
|
||||||
|
while (*LinkedIO && (((*LinkedIO)->Function != OutFunction) || strcmp( (*LinkedIO)->IOName, OutputName ) )) {
|
||||||
|
LinkedIO = &((*LinkedIO)->Next);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create if not found
|
||||||
|
if (!*LinkedIO)
|
||||||
|
{
|
||||||
|
// Create
|
||||||
|
*LinkedIO = (TLinkedIO*)malloc( sizeof(TLinkedIO) );
|
||||||
|
memset( *LinkedIO, 0, sizeof( TLinkedIO ));
|
||||||
|
|
||||||
|
// Set Parameters
|
||||||
|
(*LinkedIO)->Function = OutFunction;
|
||||||
|
(*LinkedIO)->IOName = (char*)malloc( strlen(OutputName)+1 );
|
||||||
|
strcpy( (*LinkedIO)->IOName, OutputName );
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CFunctionCore::AddOutput( int OutputID, CFunctionCore * InFunction, int InputID )
|
bool CFunctionCore::AddOutput( const char * IOName, CFunctionCore * InFunction, const char * InputName )
|
||||||
{
|
{
|
||||||
OutFunction = InFunction;
|
TLocalIO * LocalIO = NULL;
|
||||||
|
TLinkedIO ** LinkedIO = NULL;
|
||||||
|
|
||||||
|
// Get IO
|
||||||
|
if (!(LocalIO = GetLocalIO( IOName ))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if linked IO exists
|
||||||
|
LinkedIO = &(LocalIO->FirstOutput);
|
||||||
|
while (*LinkedIO && (((*LinkedIO)->Function != InFunction) || strcmp( (*LinkedIO)->IOName, InputName ) )) {
|
||||||
|
LinkedIO = &((*LinkedIO)->Next);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create if not found
|
||||||
|
if (!*LinkedIO)
|
||||||
|
{
|
||||||
|
// Create
|
||||||
|
*LinkedIO = (TLinkedIO*)malloc( sizeof(TLinkedIO) );
|
||||||
|
memset( *LinkedIO, 0, sizeof( TLinkedIO ));
|
||||||
|
|
||||||
|
// Set Parameters
|
||||||
|
(*LinkedIO)->Function = InFunction;
|
||||||
|
(*LinkedIO)->IOName = (char*)malloc( strlen(InputName)+1 );
|
||||||
|
strcpy( (*LinkedIO)->IOName, InputName );
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,30 +12,72 @@
|
|||||||
#include "BufferCore.h"
|
#include "BufferCore.h"
|
||||||
|
|
||||||
// Standard C/C++ Libraries
|
// Standard C/C++ Libraries
|
||||||
|
#include <string.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Preview
|
||||||
|
typedef struct SLocalIO TLocalIO;
|
||||||
|
typedef struct SLinkedIO TLinkedIO;
|
||||||
|
|
||||||
|
class CFunctionCore;
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
struct SLocalIO
|
||||||
|
{
|
||||||
|
char * Name;
|
||||||
|
|
||||||
|
TLinkedIO * FirstInput;
|
||||||
|
TLinkedIO * FirstOutput;
|
||||||
|
|
||||||
|
TLocalIO * Next;
|
||||||
|
};
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
struct SLinkedIO
|
||||||
|
{
|
||||||
|
CFunctionCore * Function;
|
||||||
|
char * IOName;
|
||||||
|
|
||||||
|
SLinkedIO * Next;
|
||||||
|
};
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
class CFunctionCore
|
class CFunctionCore
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
// Function Definition
|
// Function Definition
|
||||||
char * Name;
|
char * Name;
|
||||||
|
|
||||||
CFunctionCore * OutFunction;
|
// IOs
|
||||||
|
TLocalIO * FirstIO;
|
||||||
|
|
||||||
|
// Manage IO
|
||||||
|
inline TLocalIO * GetLocalIO( const char * Name ) {
|
||||||
|
TLocalIO * LocalIO = FirstIO;
|
||||||
|
while (LocalIO && strcmp( Name, LocalIO->Name )) {
|
||||||
|
LocalIO = LocalIO->Next;
|
||||||
|
}
|
||||||
|
return LocalIO;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Life cycle
|
// Life cycle
|
||||||
CFunctionCore( const char * ObjectName );
|
CFunctionCore( const char * ObjectName );
|
||||||
virtual ~CFunctionCore();
|
virtual ~CFunctionCore();
|
||||||
|
|
||||||
|
// Manage IOs
|
||||||
|
virtual TLocalIO * AddLocalIO( const char * IOName );
|
||||||
|
|
||||||
// Manual Data Input/Output
|
// Manual Data Input/Output
|
||||||
virtual int Input( int InputID, const char * Buffer, int MaxLen );
|
virtual int Input( const char * IOName, const char * Buffer, int MaxLen = -1 );
|
||||||
virtual int Output( int OutputID, const char * Buffer, int Len );
|
virtual int Output( const char * IOName, const char * Buffer, int Len = -1 );
|
||||||
|
|
||||||
// Automated Data Input/Output
|
// Automated Data Input/Output
|
||||||
virtual bool AddInput( int InputID, CFunctionCore * OutFunction, int OutputID );
|
virtual bool AddInput( const char * IOName, CFunctionCore * OutFunction, const char * OutputName );
|
||||||
virtual bool AddOutput( int OutputID, CFunctionCore * InFunction, int InputID );
|
virtual bool AddOutput( const char * IOName, CFunctionCore * InFunction, const char * InputName );
|
||||||
virtual bool Process() = 0;
|
virtual bool Process() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -55,9 +55,9 @@ CSelectableCore::~CSelectableCore()
|
|||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
THandle * CSelectableCore::CreateHandle( const char * HandleName )
|
THandle * CSelectableCore::CreateHandle( const char * HandleName, bool CreateIO )
|
||||||
{
|
{
|
||||||
THandle ** Handle = NULL;
|
THandle ** Handle = NULL;
|
||||||
|
|
||||||
// Find Handle by Name or get end of list
|
// Find Handle by Name or get end of list
|
||||||
Handle = &FirstHandle;
|
Handle = &FirstHandle;
|
||||||
@@ -80,6 +80,12 @@ THandle * CSelectableCore::CreateHandle( const char * HandleName )
|
|||||||
// Set File Descriptor
|
// Set File Descriptor
|
||||||
(*Handle)->FD = -1;
|
(*Handle)->FD = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create Matching IO point
|
||||||
|
if (CreateIO) {
|
||||||
|
(*Handle)->LocalIO = AddLocalIO( HandleName );
|
||||||
|
}
|
||||||
|
|
||||||
return *Handle;
|
return *Handle;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -139,17 +145,10 @@ bool CSelectableCore::DestroyHandle( THandle * Handle )
|
|||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CSelectableCore::SetPortHandle( const char * HandleName, const char * FileName )
|
bool CSelectableCore::SetPortHandle( THandle * Handle, const char * FileName )
|
||||||
{
|
{
|
||||||
THandle * Handle = NULL;
|
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
if (!FileName) {
|
if (!Handle || (Handle->Type != ctNone) || !FileName) {
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search for file handle
|
|
||||||
if (!(Handle = GetHandle( HandleName )) || (Handle->Type != ctNone)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,17 +168,10 @@ bool CSelectableCore::SetPortHandle( const char * HandleName, const char * FileN
|
|||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CSelectableCore::SetSocketHandle( const char * HandleName, EConnectType Type, const char * Address, const int PortNo, bool KeepAlive )
|
bool CSelectableCore::SetSocketHandle( THandle * Handle, EConnectType Type, const char * Address, const int PortNo, bool KeepAlive )
|
||||||
{
|
{
|
||||||
THandle * Handle = NULL;
|
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
if (!Address || (Type == ctNone) || (Type == ctPort)) {
|
if (!Handle || (Handle->Type != ctNone) || !Address || (Type == ctNone) || (Type == ctPort)) {
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search for file handle
|
|
||||||
if (!(Handle = GetHandle( HandleName )) || (Handle->Type != ctNone)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,37 +193,38 @@ bool CSelectableCore::SetSocketHandle( const char * HandleName, EConnectType Ty
|
|||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CSelectableCore::ClearHandle( const char * HandleName )
|
bool CSelectableCore::ClearHandle( THandle * Handle )
|
||||||
{
|
{
|
||||||
THandle * Handle = NULL;
|
// Validate
|
||||||
|
if (!Handle) {
|
||||||
// Search for file handle
|
|
||||||
if (!(Handle = GetHandle( HandleName ))) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear File Name
|
// Reset Type related parameters
|
||||||
if (Handle->FileName) {
|
if (Handle->FileName) {
|
||||||
free( Handle->FileName );
|
free( Handle->FileName );
|
||||||
|
Handle->FileName = NULL;
|
||||||
}
|
}
|
||||||
|
if (Handle->Address) {
|
||||||
|
free( Handle->Address );
|
||||||
|
Handle->Address = NULL;
|
||||||
|
}
|
||||||
|
Handle->PortNo = 0;
|
||||||
|
|
||||||
|
// Reset Parameters
|
||||||
|
Handle->Type = ctNone;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CSelectableCore::SetBuffers( const char * HandleName, int InBufSize, int OutBufSize, int InTimeout, const char * InMarker, int InMarkerLen )
|
bool CSelectableCore::SetBuffers( THandle * Handle, int InBufSize, int OutBufSize, int InTimeout, const char * InMarker, int InMarkerLen )
|
||||||
{
|
{
|
||||||
THandle * Handle = NULL;
|
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
if (!HandleName) {
|
if (!Handle) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get Handle
|
|
||||||
if (!(Handle = GetHandle( HandleName ))) {
|
|
||||||
return false;;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Input Buffer
|
// Input Buffer
|
||||||
if (Handle->InBuffer) {
|
if (Handle->InBuffer) {
|
||||||
delete Handle->InBuffer;
|
delete Handle->InBuffer;
|
||||||
@@ -427,9 +420,14 @@ int CSelectableCore::OpenRemoteClientSocket( THandle * Handle )
|
|||||||
// Create Remote Client Handle
|
// Create Remote Client Handle
|
||||||
sprintf( ClientName, "%s-%d", Handle->Name, ClientFD );
|
sprintf( ClientName, "%s-%d", Handle->Name, ClientFD );
|
||||||
*RemoteClient = CreateHandle( ClientName );
|
*RemoteClient = CreateHandle( ClientName );
|
||||||
SetSocketHandle( ClientName, ctRemoteClient, ClientAddress, 0, Handle->KeepAlive );
|
SetSocketHandle( *RemoteClient, ctRemoteClient, ClientAddress, 0, Handle->KeepAlive );
|
||||||
SetBuffers( ClientName, 20, 0, 50, "\n", 1 );
|
|
||||||
|
|
||||||
|
// Copy Parent Buffer setup
|
||||||
|
SetBuffers( *RemoteClient, ((Handle->InBuffer)? Handle->InBuffer->Size() : 0),
|
||||||
|
((Handle->OutBuffer)? Handle->OutBuffer->Size() : 0),
|
||||||
|
Handle->InTimeout, Handle->InMarker, Handle->InMarkerLen );
|
||||||
|
|
||||||
|
// Set Key parameters
|
||||||
(*RemoteClient)->FD = ClientFD;
|
(*RemoteClient)->FD = ClientFD;
|
||||||
(*RemoteClient)->Parent = Handle;
|
(*RemoteClient)->Parent = Handle;
|
||||||
(*RemoteClient)->State = csWaitingtoOpen;
|
(*RemoteClient)->State = csWaitingtoOpen;
|
||||||
@@ -714,7 +712,7 @@ bool CSelectableCore::Write( THandle * Handle )
|
|||||||
|
|
||||||
if (Handle->State == csWaitingtoOpen)
|
if (Handle->State == csWaitingtoOpen)
|
||||||
{
|
{
|
||||||
// Complete socket open
|
// Complete socket open process
|
||||||
if (Handle->Type == ctRemoteClient) {
|
if (Handle->Type == ctRemoteClient) {
|
||||||
OpenRemoteClientSocket( Handle );
|
OpenRemoteClientSocket( Handle );
|
||||||
} else if (Handle->Type == ctClient) {
|
} else if (Handle->Type == ctClient) {
|
||||||
@@ -732,15 +730,13 @@ bool CSelectableCore::Write( THandle * Handle )
|
|||||||
if (Handle->OutBuffer)
|
if (Handle->OutBuffer)
|
||||||
{
|
{
|
||||||
// Write to FD directly from buffer
|
// Write to FD directly from buffer
|
||||||
if (!(BytesWritten = Handle->OutBuffer->WriteToFD( Handle->FD ))) {
|
if ((BytesWritten = Handle->OutBuffer->WriteToFD( Handle->FD ))) {
|
||||||
return false;
|
// Update Buffer
|
||||||
|
Handle->OutBuffer->Clear( BytesWritten );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update Buffer
|
|
||||||
Handle->OutBuffer->Clear( BytesWritten );
|
|
||||||
|
|
||||||
// Check if Buffer emtpy
|
// Check if Buffer emtpy
|
||||||
if (Handle->OutBuffer->Len()) {
|
if (!Handle->OutBuffer->Len()) {
|
||||||
// Add to Select Write list
|
// Add to Select Write list
|
||||||
if (Select) {
|
if (Select) {
|
||||||
Select->Remove( Handle->FD, false, true );
|
Select->Remove( Handle->FD, false, true );
|
||||||
@@ -761,29 +757,69 @@ bool CSelectableCore::Write( THandle * Handle )
|
|||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CSelectableCore::Process()
|
bool CSelectableCore::ProcessBuffer( THandle * Handle, bool Force )
|
||||||
{
|
{
|
||||||
THandle * Handle = NULL;
|
int Pos = 0;
|
||||||
long Duration = 0;
|
int Len = 0;
|
||||||
|
char * Data = NULL;
|
||||||
|
TLocalIO * LocalIO = NULL;
|
||||||
|
TLinkedIO * Output = NULL;
|
||||||
|
|
||||||
// Check all Input buffers
|
// Check if buffered data
|
||||||
Handle = FirstHandle;
|
if (!Handle || !Handle->InBuffer->Len()) {
|
||||||
while (Handle)
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if forced processed
|
||||||
|
if (Force)
|
||||||
{
|
{
|
||||||
if (Handle->InBuffer && (Handle->InBuffer->Len() > 0))
|
// Show Packet
|
||||||
{
|
Len = Handle->InBuffer->Peek( &Data );
|
||||||
// Check duration since last PortIn
|
ShowOutput( "Port In", OUT_NORMAL, Data, Len );
|
||||||
Duration = TimePassed( Handle->InStart );
|
|
||||||
if (Duration > Handle->InTimeout)
|
|
||||||
{
|
|
||||||
// Process Input
|
|
||||||
ProcessBuffer( Handle, true );
|
|
||||||
|
|
||||||
// Reset timer
|
// Write buffer to Outputs
|
||||||
SetInterval( &(Handle->InStart), 0 );
|
if (Handle->Type == ctRemoteClient) {
|
||||||
|
LocalIO = Handle->Parent->LocalIO;
|
||||||
|
} else {
|
||||||
|
LocalIO = Handle->LocalIO;
|
||||||
|
}
|
||||||
|
if (LocalIO) {
|
||||||
|
Output = LocalIO->FirstOutput;
|
||||||
|
while (Output) {
|
||||||
|
Output->Function->Input( Output->IOName, Data, Len );
|
||||||
|
Output = Output->Next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Handle = Handle->Next;
|
|
||||||
|
// Clear processed bytes from buffer
|
||||||
|
Handle->InBuffer->Clear( Len );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Search for end of packet marker
|
||||||
|
while (Handle->InBuffer->FindStr( Handle->InMarker, Handle->InMarkerLen, Pos ))
|
||||||
|
{
|
||||||
|
// Show Packet
|
||||||
|
Len = Handle->InBuffer->Peek( &Data, 0, Pos+1 );
|
||||||
|
ShowOutput( "Port In", OUT_NORMAL, Data, Len );
|
||||||
|
|
||||||
|
// Write buffer to Outputs
|
||||||
|
if (Handle->Type == ctRemoteClient) {
|
||||||
|
LocalIO = Handle->Parent->LocalIO;
|
||||||
|
} else {
|
||||||
|
LocalIO = Handle->LocalIO;
|
||||||
|
}
|
||||||
|
if (LocalIO) {
|
||||||
|
Output = LocalIO->FirstOutput;
|
||||||
|
while (Output) {
|
||||||
|
Output->Function->Input( Output->IOName, Data, Len );
|
||||||
|
Output = Output->Next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear processed bytes from buffer
|
||||||
|
Handle->InBuffer->Clear( Len );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -847,81 +883,118 @@ int CSelectableCore::WriteToFD( int FD, const char * Data, int Len )
|
|||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
int CSelectableCore::Input( int FD, const char * Data, int Len )
|
int CSelectableCore::Input( const char * IOName, const char * Data, int Len )
|
||||||
{
|
{
|
||||||
THandle * Handle = NULL;
|
THandle * Handle = NULL;
|
||||||
|
THandle * ChildHandle = NULL;
|
||||||
int BytesWritten = 0;
|
int BytesWritten = 0;
|
||||||
|
|
||||||
|
// Validate
|
||||||
|
if (!IOName || !Data) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (Len == -1) {
|
||||||
|
Len = strlen( Data );
|
||||||
|
}
|
||||||
|
|
||||||
// Get File handle
|
// Get File handle
|
||||||
if ((Handle = GetHandle( "Serial Port" )) || (Handle = GetHandle( "Client" ))) {
|
if ((Handle = GetHandle( IOName )))
|
||||||
// Write to handle
|
{
|
||||||
BytesWritten = WriteToFD( Handle->FD, Data, Len );
|
if (Handle->Type == ctServer)
|
||||||
|
{
|
||||||
|
// Cannot write to server socket, so Update Remote Client connections individually
|
||||||
|
ChildHandle = FirstHandle;
|
||||||
|
while (ChildHandle)
|
||||||
|
{
|
||||||
|
// Check if child
|
||||||
|
if (ChildHandle->Parent == Handle)
|
||||||
|
{
|
||||||
|
// Decide where to put data
|
||||||
|
if (ChildHandle->OutBuffer)
|
||||||
|
{
|
||||||
|
// Write to buffer
|
||||||
|
BytesWritten = ChildHandle->OutBuffer->Push( Data, Len );
|
||||||
|
|
||||||
|
// Add to select write list
|
||||||
|
if (BytesWritten) {
|
||||||
|
Select->Add( ChildHandle->FD, false, true, this );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Write directly to handle
|
||||||
|
BytesWritten = WriteToFD( ChildHandle->FD, Data, Len );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Next
|
||||||
|
ChildHandle = ChildHandle->Next;
|
||||||
|
}
|
||||||
|
// Cannot verify individually, so assume all bytes was written
|
||||||
|
BytesWritten = Len;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Decide where to put data
|
||||||
|
if (Handle->OutBuffer)
|
||||||
|
{
|
||||||
|
// Write to buffer
|
||||||
|
BytesWritten = Handle->OutBuffer->Push( Data, Len );
|
||||||
|
|
||||||
|
// Add to select write list
|
||||||
|
if (BytesWritten) {
|
||||||
|
Select->Add( Handle->FD, false, true, this );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Write directly to handle
|
||||||
|
BytesWritten = WriteToFD( Handle->FD, Data, Len );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return BytesWritten;
|
return BytesWritten;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CSelectableCore::ProcessBuffer( THandle * Handle, bool Force )
|
bool CSelectableCore::Process()
|
||||||
{
|
{
|
||||||
int Pos = 0;
|
THandle * Handle = NULL;
|
||||||
int Len = 0;
|
long Duration = 0;
|
||||||
char * Data = NULL;
|
|
||||||
|
|
||||||
// Check if buffered data
|
// Check all Input buffers
|
||||||
if (!Handle || !Handle->InBuffer->Len()) {
|
Handle = FirstHandle;
|
||||||
return false;
|
while (Handle)
|
||||||
}
|
|
||||||
|
|
||||||
// Check if forced processed
|
|
||||||
if (Force)
|
|
||||||
{
|
{
|
||||||
// Show Packet
|
if (Handle->InBuffer && (Handle->InBuffer->Len() > 0))
|
||||||
Len = Handle->InBuffer->Peek( &Data );
|
|
||||||
ShowOutput( "Port In", OUT_NORMAL, Data, Len );
|
|
||||||
|
|
||||||
// Write buffer to Port
|
|
||||||
if (OutFunction)
|
|
||||||
OutFunction->Input( 0, Data, Len );
|
|
||||||
|
|
||||||
// Clear processed bytes from buffer
|
|
||||||
Handle->InBuffer->Clear( Len );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Search for end of packet marker
|
|
||||||
while (Handle->InBuffer->FindChar( '\n', Pos ))
|
|
||||||
{
|
{
|
||||||
// Show Packet
|
// Check duration since last PortIn
|
||||||
Len = Handle->InBuffer->Peek( &Data, 0, Pos+1 );
|
Duration = TimePassed( Handle->InStart );
|
||||||
ShowOutput( "Port In", OUT_NORMAL, Data, Len );
|
if (Duration > Handle->InTimeout)
|
||||||
|
{
|
||||||
|
// Process Input
|
||||||
|
ProcessBuffer( Handle, true );
|
||||||
|
|
||||||
// Write buffer to Port
|
// Reset timer
|
||||||
if (OutFunction)
|
SetInterval( &(Handle->InStart), 0 );
|
||||||
OutFunction->Input( 0, Data, Len );
|
}
|
||||||
|
|
||||||
// Clear processed bytes from buffer
|
|
||||||
Handle->InBuffer->Clear( Len );
|
|
||||||
}
|
}
|
||||||
|
Handle = Handle->Next;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
// Set serial port configuration parameters
|
// Set serial port configuration parameters
|
||||||
bool CSelectableCore::SerialConfig( const char *PortName, int Baud, short DataBits, short StopBits, short Parity, short FlowCtrl, int Wait )
|
bool CSelectableCore::SerialConfig( THandle * Handle, int Baud, short DataBits, short StopBits, short Parity, short FlowCtrl, int Wait )
|
||||||
{
|
{
|
||||||
THandle * Handle = NULL;
|
|
||||||
struct termios newtio;
|
struct termios newtio;
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
speed_t _baud = 0;
|
speed_t _baud = 0;
|
||||||
int mcs = 0;
|
int mcs = 0;
|
||||||
|
|
||||||
// Get Handle
|
// Get Handle
|
||||||
if (!(Handle = GetHandle( PortName ))) {
|
if (!Handle || (Handle->Type != ctPort)) {
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if (Handle->Type != ctPort) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -91,6 +91,7 @@ struct SHandle {
|
|||||||
long InTimeout; // millisecs
|
long InTimeout; // millisecs
|
||||||
|
|
||||||
// List / Tree
|
// List / Tree
|
||||||
|
TLocalIO * LocalIO;
|
||||||
THandle * Parent;
|
THandle * Parent;
|
||||||
THandle * Next;
|
THandle * Next;
|
||||||
};
|
};
|
||||||
@@ -144,7 +145,7 @@ protected:
|
|||||||
bool RemoveHandle( THandle * Handle );
|
bool RemoveHandle( THandle * Handle );
|
||||||
bool DestroyHandle( THandle * Handle );
|
bool DestroyHandle( THandle * Handle );
|
||||||
|
|
||||||
// Finding files
|
// Finding Handles
|
||||||
inline THandle * GetHandle( const char * HandleName )
|
inline THandle * GetHandle( const char * HandleName )
|
||||||
{
|
{
|
||||||
if (!HandleName) return NULL;
|
if (!HandleName) return NULL;
|
||||||
@@ -162,6 +163,20 @@ protected:
|
|||||||
return Handle;
|
return Handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get Parameters
|
||||||
|
inline int GetFD( const char * HandleName ) {
|
||||||
|
THandle * Handle = GetHandle( HandleName );
|
||||||
|
return ((Handle)? Handle->FD : -1);
|
||||||
|
};
|
||||||
|
inline EConnectType GetType( const char * HandleName ) {
|
||||||
|
THandle * Handle = GetHandle( HandleName );
|
||||||
|
return ((Handle)? Handle->Type : ctNone);
|
||||||
|
};
|
||||||
|
inline EConnectState GetState( const char * HandleName ) {
|
||||||
|
THandle * Handle = GetHandle( HandleName );
|
||||||
|
return ((Handle)? Handle->State : csNone);
|
||||||
|
};
|
||||||
|
|
||||||
// Port Operations
|
// Port Operations
|
||||||
virtual int OpenPort( THandle * Handle );
|
virtual int OpenPort( THandle * Handle );
|
||||||
|
|
||||||
@@ -187,15 +202,16 @@ public:
|
|||||||
~CSelectableCore();
|
~CSelectableCore();
|
||||||
|
|
||||||
// Configuration
|
// Configuration
|
||||||
THandle * CreateHandle( const char * HandleName );
|
THandle * CreateHandle( const char * HandleName, bool CreateIO = false );
|
||||||
bool SetBuffers( const char * HandleName, int InBufSize, int OutBufSize, int InTimeout, const char * InMarker, int InMarkerLen );
|
bool SetBuffers( THandle * Handle, int InBufSize, int OutBufSize, int InTimeout, const char * InMarker, int InMarkerLen );
|
||||||
bool SerialConfig( const char * HandleName, int Baud, short DataBits, short StopBits, short Parity, short FlowCtrl, int Wait );
|
bool SerialConfig( THandle * Handle, int Baud, short DataBits, short StopBits, short Parity, short FlowCtrl, int Wait );
|
||||||
|
|
||||||
// Device Interface
|
// Device Interface
|
||||||
bool SetPortHandle( const char * HandleName, const char * FileName );
|
bool SetPortHandle( THandle * Handle, const char * FileName );
|
||||||
bool SetSocketHandle( const char * HandleName, EConnectType Type, const char * Address, const int PortNo, bool KeepAlive );
|
bool SetSocketHandle( THandle * Handle, EConnectType Type, const char * Address, const int PortNo, bool KeepAlive );
|
||||||
bool ClearHandle( const char * HandleName );
|
bool ClearHandle( THandle * Handle );
|
||||||
|
|
||||||
|
// FD operations
|
||||||
virtual int Open( const char * HandleName );
|
virtual int Open( const char * HandleName );
|
||||||
|
|
||||||
virtual bool Close( const char * HandleName, bool CloseChildren = false ) { return (Close( GetHandle( HandleName ), CloseChildren )); };
|
virtual bool Close( const char * HandleName, bool CloseChildren = false ) { return (Close( GetHandle( HandleName ), CloseChildren )); };
|
||||||
@@ -207,21 +223,8 @@ public:
|
|||||||
virtual bool Write( const char * HandleName ) { return (Write( GetHandle( HandleName ))); };
|
virtual bool Write( const char * HandleName ) { return (Write( GetHandle( HandleName ))); };
|
||||||
virtual bool Write( int FD ) { return (Write( GetHandle( FD ))); };
|
virtual bool Write( int FD ) { return (Write( GetHandle( FD ))); };
|
||||||
|
|
||||||
inline int GetFD( const char * HandleName ) {
|
|
||||||
THandle * Handle = GetHandle( HandleName );
|
|
||||||
return ((Handle)? Handle->FD : -1);
|
|
||||||
};
|
|
||||||
inline EConnectType GetType( const char * HandleName ) {
|
|
||||||
THandle * Handle = GetHandle( HandleName );
|
|
||||||
return ((Handle)? Handle->Type : ctNone);
|
|
||||||
};
|
|
||||||
inline EConnectState GetState( const char * HandleName ) {
|
|
||||||
THandle * Handle = GetHandle( HandleName );
|
|
||||||
return ((Handle)? Handle->State : csNone);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Function Interface
|
// Function Interface
|
||||||
virtual int Input( int FD, const char * Buffer, int BufLen );
|
virtual int Input( const char *IOName, const char * Buffer, int BufLen = -1 );
|
||||||
virtual bool Process();
|
virtual bool Process();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user