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:
Charl Wentzel
2016-05-25 14:17:40 +02:00
parent e83c09ecb6
commit 9ace97c1a3
6 changed files with 439 additions and 157 deletions

View File

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