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:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user