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
|
||||
BufRemain = BufSize - BufEnd;
|
||||
BytesRead = read( Handle, &Buffer[BufEnd], ((BufRemain > DataRemain)? DataRemain : BufRemain) );
|
||||
if (BytesRead < 0)
|
||||
if (BytesRead <= 0)
|
||||
break;
|
||||
|
||||
// Update Buffer Pointers
|
||||
@@ -283,7 +283,7 @@ int CBuffer::WriteToFD( int Handle, int MaxLen )
|
||||
// Read Data into buffer
|
||||
ReadPos = BufStart;
|
||||
DataRemain = (MaxLen == -1)? BufLen : MaxLen;
|
||||
while ((TotalWritten < MaxLen) && (BufLen > 0))
|
||||
while (DataRemain)
|
||||
{
|
||||
// Read from file descriptor
|
||||
BufRemain = BufSize - ReadPos;
|
||||
@@ -336,10 +336,12 @@ char CBuffer::PeekChar( int Pos, bool ClearChar )
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
// 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 * Limit;
|
||||
char * CheckPos = NULL;
|
||||
char * CheckLimit = NULL;
|
||||
char * MatchPos = NULL;
|
||||
char * MatchLimit = NULL;
|
||||
|
||||
// Check if buffer exists
|
||||
if (!BufLen) {
|
||||
@@ -353,24 +355,35 @@ bool CBuffer::FindChar( char SearchChar, int &FoundPos, int StartPos )
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get Search start point
|
||||
if (BufStart + StartPos < BufSize) {
|
||||
CheckPos = &Buffer[ BufStart+StartPos ];
|
||||
} else {
|
||||
CheckPos = &Buffer[ (BufStart+StartPos)-BufSize ];
|
||||
}
|
||||
// Get Search start point and limit
|
||||
CheckPos = (BufStart + StartPos < BufSize)? &Buffer[ BufStart+StartPos ] : &Buffer[ (BufStart+StartPos)-BufSize ];
|
||||
CheckLimit = &Buffer[BufSize-1];
|
||||
|
||||
// Set Match start point and limit
|
||||
MatchPos = (char*)SearchStr;
|
||||
MatchLimit = (char*)&SearchStr[SearchLen-1];
|
||||
|
||||
// Search for char
|
||||
FoundPos = StartPos;
|
||||
Limit = &Buffer[BufSize-1];
|
||||
while (FoundPos < BufLen)
|
||||
{
|
||||
if (*CheckPos == SearchChar)
|
||||
return true;
|
||||
// Check if char match
|
||||
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
|
||||
FoundPos++;
|
||||
if (CheckPos == Limit) {
|
||||
if (CheckPos == CheckLimit) {
|
||||
CheckPos = Buffer; // Roll-over, Start at beginning of buffer
|
||||
} else {
|
||||
CheckPos++;
|
||||
|
||||
@@ -52,7 +52,7 @@ public:
|
||||
|
||||
// Character Operations
|
||||
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
|
||||
inline int Size() { return BufSize; };
|
||||
|
||||
169
FunctionCore.cpp
169
FunctionCore.cpp
@@ -30,42 +30,193 @@ CFunctionCore::CFunctionCore( const char * FunctionName )
|
||||
}
|
||||
|
||||
// IO Functions
|
||||
OutFunction = NULL;
|
||||
FirstIO = NULL;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
CFunctionCore::~CFunctionCore()
|
||||
{
|
||||
TLocalIO * NextIO = NULL;
|
||||
TLinkedIO * NextLinkedIO = NULL;
|
||||
|
||||
// Destroy pointers
|
||||
if (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
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -12,30 +12,72 @@
|
||||
#include "BufferCore.h"
|
||||
|
||||
// Standard C/C++ Libraries
|
||||
#include <string.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
|
||||
{
|
||||
protected:
|
||||
// Function Definition
|
||||
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:
|
||||
// Life cycle
|
||||
CFunctionCore( const char * ObjectName );
|
||||
virtual ~CFunctionCore();
|
||||
|
||||
// Manage IOs
|
||||
virtual TLocalIO * AddLocalIO( const char * IOName );
|
||||
|
||||
// Manual Data Input/Output
|
||||
virtual int Input( int InputID, const char * Buffer, int MaxLen );
|
||||
virtual int Output( int OutputID, const char * Buffer, int Len );
|
||||
virtual int Input( const char * IOName, const char * Buffer, int MaxLen = -1 );
|
||||
virtual int Output( const char * IOName, const char * Buffer, int Len = -1 );
|
||||
|
||||
// Automated Data Input/Output
|
||||
virtual bool AddInput( int InputID, CFunctionCore * OutFunction, int OutputID );
|
||||
virtual bool AddOutput( int OutputID, CFunctionCore * InFunction, int InputID );
|
||||
virtual bool AddInput( const char * IOName, CFunctionCore * OutFunction, const char * OutputName );
|
||||
virtual bool AddOutput( const char * IOName, CFunctionCore * InFunction, const char * InputName );
|
||||
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
|
||||
Handle = &FirstHandle;
|
||||
@@ -80,6 +80,12 @@ THandle * CSelectableCore::CreateHandle( const char * HandleName )
|
||||
// Set File Descriptor
|
||||
(*Handle)->FD = -1;
|
||||
}
|
||||
|
||||
// Create Matching IO point
|
||||
if (CreateIO) {
|
||||
(*Handle)->LocalIO = AddLocalIO( HandleName );
|
||||
}
|
||||
|
||||
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
|
||||
if (!FileName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Search for file handle
|
||||
if (!(Handle = GetHandle( HandleName )) || (Handle->Type != ctNone)) {
|
||||
if (!Handle || (Handle->Type != ctNone) || !FileName) {
|
||||
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
|
||||
if (!Address || (Type == ctNone) || (Type == ctPort)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Search for file handle
|
||||
if (!(Handle = GetHandle( HandleName )) || (Handle->Type != ctNone)) {
|
||||
if (!Handle || (Handle->Type != ctNone) || !Address || (Type == ctNone) || (Type == ctPort)) {
|
||||
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;
|
||||
|
||||
// Search for file handle
|
||||
if (!(Handle = GetHandle( HandleName ))) {
|
||||
// Validate
|
||||
if (!Handle) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Clear File Name
|
||||
// Reset Type related parameters
|
||||
if (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;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
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
|
||||
if (!HandleName) {
|
||||
if (!Handle) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get Handle
|
||||
if (!(Handle = GetHandle( HandleName ))) {
|
||||
return false;;
|
||||
}
|
||||
|
||||
// Input Buffer
|
||||
if (Handle->InBuffer) {
|
||||
delete Handle->InBuffer;
|
||||
@@ -427,9 +420,14 @@ int CSelectableCore::OpenRemoteClientSocket( THandle * Handle )
|
||||
// Create Remote Client Handle
|
||||
sprintf( ClientName, "%s-%d", Handle->Name, ClientFD );
|
||||
*RemoteClient = CreateHandle( ClientName );
|
||||
SetSocketHandle( ClientName, ctRemoteClient, ClientAddress, 0, Handle->KeepAlive );
|
||||
SetBuffers( ClientName, 20, 0, 50, "\n", 1 );
|
||||
SetSocketHandle( *RemoteClient, ctRemoteClient, ClientAddress, 0, Handle->KeepAlive );
|
||||
|
||||
// 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)->Parent = Handle;
|
||||
(*RemoteClient)->State = csWaitingtoOpen;
|
||||
@@ -714,7 +712,7 @@ bool CSelectableCore::Write( THandle * Handle )
|
||||
|
||||
if (Handle->State == csWaitingtoOpen)
|
||||
{
|
||||
// Complete socket open
|
||||
// Complete socket open process
|
||||
if (Handle->Type == ctRemoteClient) {
|
||||
OpenRemoteClientSocket( Handle );
|
||||
} else if (Handle->Type == ctClient) {
|
||||
@@ -732,15 +730,13 @@ bool CSelectableCore::Write( THandle * Handle )
|
||||
if (Handle->OutBuffer)
|
||||
{
|
||||
// Write to FD directly from buffer
|
||||
if (!(BytesWritten = Handle->OutBuffer->WriteToFD( Handle->FD ))) {
|
||||
return false;
|
||||
if ((BytesWritten = Handle->OutBuffer->WriteToFD( Handle->FD ))) {
|
||||
// Update Buffer
|
||||
Handle->OutBuffer->Clear( BytesWritten );
|
||||
}
|
||||
|
||||
// Update Buffer
|
||||
Handle->OutBuffer->Clear( BytesWritten );
|
||||
|
||||
// Check if Buffer emtpy
|
||||
if (Handle->OutBuffer->Len()) {
|
||||
if (!Handle->OutBuffer->Len()) {
|
||||
// Add to Select Write list
|
||||
if (Select) {
|
||||
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;
|
||||
long Duration = 0;
|
||||
int Pos = 0;
|
||||
int Len = 0;
|
||||
char * Data = NULL;
|
||||
TLocalIO * LocalIO = NULL;
|
||||
TLinkedIO * Output = NULL;
|
||||
|
||||
// Check all Input buffers
|
||||
Handle = FirstHandle;
|
||||
while (Handle)
|
||||
// Check if buffered data
|
||||
if (!Handle || !Handle->InBuffer->Len()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if forced processed
|
||||
if (Force)
|
||||
{
|
||||
if (Handle->InBuffer && (Handle->InBuffer->Len() > 0))
|
||||
{
|
||||
// Check duration since last PortIn
|
||||
Duration = TimePassed( Handle->InStart );
|
||||
if (Duration > Handle->InTimeout)
|
||||
{
|
||||
// Process Input
|
||||
ProcessBuffer( Handle, true );
|
||||
// Show Packet
|
||||
Len = Handle->InBuffer->Peek( &Data );
|
||||
ShowOutput( "Port In", OUT_NORMAL, Data, Len );
|
||||
|
||||
// Reset timer
|
||||
SetInterval( &(Handle->InStart), 0 );
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
@@ -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 * ChildHandle = NULL;
|
||||
int BytesWritten = 0;
|
||||
|
||||
// Validate
|
||||
if (!IOName || !Data) {
|
||||
return 0;
|
||||
}
|
||||
else if (Len == -1) {
|
||||
Len = strlen( Data );
|
||||
}
|
||||
|
||||
// Get File handle
|
||||
if ((Handle = GetHandle( "Serial Port" )) || (Handle = GetHandle( "Client" ))) {
|
||||
// Write to handle
|
||||
BytesWritten = WriteToFD( Handle->FD, Data, Len );
|
||||
if ((Handle = GetHandle( IOName )))
|
||||
{
|
||||
if (Handle->Type == ctServer)
|
||||
{
|
||||
// Cannot write to server socket, so Update Remote Client connections individually
|
||||
ChildHandle = FirstHandle;
|
||||
while (ChildHandle)
|
||||
{
|
||||
// Check if child
|
||||
if (ChildHandle->Parent == Handle)
|
||||
{
|
||||
// Decide where to put data
|
||||
if (ChildHandle->OutBuffer)
|
||||
{
|
||||
// Write to buffer
|
||||
BytesWritten = ChildHandle->OutBuffer->Push( Data, Len );
|
||||
|
||||
// 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;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool CSelectableCore::ProcessBuffer( THandle * Handle, bool Force )
|
||||
bool CSelectableCore::Process()
|
||||
{
|
||||
int Pos = 0;
|
||||
int Len = 0;
|
||||
char * Data = NULL;
|
||||
THandle * Handle = NULL;
|
||||
long Duration = 0;
|
||||
|
||||
// Check if buffered data
|
||||
if (!Handle || !Handle->InBuffer->Len()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if forced processed
|
||||
if (Force)
|
||||
// Check all Input buffers
|
||||
Handle = FirstHandle;
|
||||
while (Handle)
|
||||
{
|
||||
// Show Packet
|
||||
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 ))
|
||||
if (Handle->InBuffer && (Handle->InBuffer->Len() > 0))
|
||||
{
|
||||
// Show Packet
|
||||
Len = Handle->InBuffer->Peek( &Data, 0, Pos+1 );
|
||||
ShowOutput( "Port In", OUT_NORMAL, Data, Len );
|
||||
// Check duration since last PortIn
|
||||
Duration = TimePassed( Handle->InStart );
|
||||
if (Duration > Handle->InTimeout)
|
||||
{
|
||||
// Process Input
|
||||
ProcessBuffer( Handle, true );
|
||||
|
||||
// Write buffer to Port
|
||||
if (OutFunction)
|
||||
OutFunction->Input( 0, Data, Len );
|
||||
|
||||
// Clear processed bytes from buffer
|
||||
Handle->InBuffer->Clear( Len );
|
||||
// Reset timer
|
||||
SetInterval( &(Handle->InStart), 0 );
|
||||
}
|
||||
}
|
||||
Handle = Handle->Next;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
// 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;
|
||||
int flags = 0;
|
||||
speed_t _baud = 0;
|
||||
int mcs = 0;
|
||||
|
||||
// Get Handle
|
||||
if (!(Handle = GetHandle( PortName ))) {
|
||||
return false;
|
||||
}
|
||||
else if (Handle->Type != ctPort) {
|
||||
if (!Handle || (Handle->Type != ctPort)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -91,6 +91,7 @@ struct SHandle {
|
||||
long InTimeout; // millisecs
|
||||
|
||||
// List / Tree
|
||||
TLocalIO * LocalIO;
|
||||
THandle * Parent;
|
||||
THandle * Next;
|
||||
};
|
||||
@@ -144,7 +145,7 @@ protected:
|
||||
bool RemoveHandle( THandle * Handle );
|
||||
bool DestroyHandle( THandle * Handle );
|
||||
|
||||
// Finding files
|
||||
// Finding Handles
|
||||
inline THandle * GetHandle( const char * HandleName )
|
||||
{
|
||||
if (!HandleName) return NULL;
|
||||
@@ -162,6 +163,20 @@ protected:
|
||||
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
|
||||
virtual int OpenPort( THandle * Handle );
|
||||
|
||||
@@ -187,15 +202,16 @@ public:
|
||||
~CSelectableCore();
|
||||
|
||||
// Configuration
|
||||
THandle * CreateHandle( const char * HandleName );
|
||||
bool SetBuffers( const char * HandleName, 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 );
|
||||
THandle * CreateHandle( const char * HandleName, bool CreateIO = false );
|
||||
bool SetBuffers( THandle * Handle, int InBufSize, int OutBufSize, int InTimeout, const char * InMarker, int InMarkerLen );
|
||||
bool SerialConfig( THandle * Handle, int Baud, short DataBits, short StopBits, short Parity, short FlowCtrl, int Wait );
|
||||
|
||||
// Device Interface
|
||||
bool SetPortHandle( const char * HandleName, const char * FileName );
|
||||
bool SetSocketHandle( const char * HandleName, EConnectType Type, const char * Address, const int PortNo, bool KeepAlive );
|
||||
bool ClearHandle( const char * HandleName );
|
||||
bool SetPortHandle( THandle * Handle, const char * FileName );
|
||||
bool SetSocketHandle( THandle * Handle, EConnectType Type, const char * Address, const int PortNo, bool KeepAlive );
|
||||
bool ClearHandle( THandle * Handle );
|
||||
|
||||
// FD operations
|
||||
virtual int Open( const char * HandleName );
|
||||
|
||||
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( 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
|
||||
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();
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user