Important Update:

- Converted Select functions into new class CSelectCore
- Move Read/Write code from main() to SelectableCore Read()/Write()
- Pass CSelectCore object to CSelectableCore on create
- Updated SelectCore Read/Write lists directly from SelectableCore
- SelectCore->Test() checks all FDs directly and call Read/Write functions
- Improved checking/validating for methods in SelectableCore
This commit is contained in:
Charl Wentzel
2016-05-24 15:02:51 +02:00
parent dcfbd85efa
commit e83c09ecb6
4 changed files with 361 additions and 113 deletions

View File

@@ -55,8 +55,8 @@ public:
bool FindChar( char SearchChar, int &FoundPos, int StartPos = 0 ); bool FindChar( char SearchChar, int &FoundPos, int StartPos = 0 );
// Miscellaneous // Miscellaneous
int Size() { return BufSize; }; inline int Size() { return BufSize; };
int Len() { return BufLen; }; inline int Len() { return BufLen; };
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View File

@@ -8,24 +8,40 @@
// redA Libraries // redA Libraries
#include "TimingCore.h" #include "TimingCore.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include "SelectableCore.h" #include "SelectableCore.h"
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Select Variables // Create Select
fd_set ReadTestFDS; CSelect::CSelect( long SelectTimeout )
fd_set WriteTestFDS; {
fd_set ReadFDS; // Clear List
fd_set WriteFDS; FirstHandle = NULL;
int MaxFD = 0;
timeval SelectTime;
// Clear Select sets
FD_ZERO( &ReadTestFDS );
FD_ZERO( &WriteTestFDS );
// Reset maximum File Descriptor
MaxFD = 0;
// Set Timeout
SetInterval( &Timeout, SelectTimeout );
}
//---------------------------------------------------------------------------
// Destroy Select
CSelect::~CSelect()
{
return;
}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Clear Select File Descriptors // Clear Select File Descriptors
void SelectClear() void CSelect::Clear()
{ {
// Clear Select sets // Clear Select sets
FD_ZERO( &ReadTestFDS ); FD_ZERO( &ReadTestFDS );
@@ -36,24 +52,39 @@ void SelectClear()
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Set Select timeout
void SelectConfig( long SelectTimeout )
{
// Set Timeout
SetInterval( &SelectTime, SelectTimeout );
}
//---------------------------------------------------------------------------
// Add Select File Descriptor // Add Select File Descriptor
void SelectAdd( int FD, bool Read, bool Write ) void CSelect::Add( int FD, bool Read, bool Write, CSelectableCore * Function )
{ {
TSelectHandle ** Handle = NULL;
// Check if Handle already exists
Handle = &FirstHandle;
while (*Handle && ((*Handle)->FD != FD)) {
Handle = &((*Handle)->Next);
}
// Create if not exist
if (!*Handle) {
// Create
*Handle = (TSelectHandle*)malloc( sizeof(TSelectHandle) );
memset( *Handle, 0, sizeof(TSelectHandle) );
// Set Parameters
(*Handle)->FD = FD;
(*Handle)->Function = Function;
}
// Add Read select // Add Read select
if (Read) if (Read) {
(*Handle)->Read = true;
FD_SET( FD, &ReadTestFDS ); FD_SET( FD, &ReadTestFDS );
}
// Add Write Select // Add Write Select
if (Write) if (Write) {
(*Handle)->Write = true;
FD_SET( FD, &WriteTestFDS ); FD_SET( FD, &WriteTestFDS );
}
// Check Maximum File Handle // Check Maximum File Handle
if (MaxFD <= FD) if (MaxFD <= FD)
@@ -61,19 +92,42 @@ void SelectAdd( int FD, bool Read, bool Write )
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void SelectRemove( int FD, bool Read, bool Write ) void CSelect::Remove( int FD, bool Read, bool Write )
{ {
TSelectHandle ** Handle = NULL;
TSelectHandle * NextHandle = NULL;
int TestFD = 0; int TestFD = 0;
// Check if Handle already exists
Handle = &FirstHandle;
while (*Handle && ((*Handle)->FD != FD)) {
Handle = &((*Handle)->Next);
}
// Check if found
if (!*Handle)
return;
// Remove from set for select read check // Remove from set for select read check
if (Read) if (Read) {
(*Handle)->Read = false;
FD_CLR( FD, &ReadTestFDS); FD_CLR( FD, &ReadTestFDS);
}
// Remove from set for select write check // Remove from set for select write check
if (Write) if (Write) {
(*Handle)->Write = false;
FD_CLR( FD, &WriteTestFDS); FD_CLR( FD, &WriteTestFDS);
}
// Check Maximum file handle // Check if to remove from list
if (!(*Handle)->Read && !(*Handle)->Write)
{
// Remove from list
NextHandle = (*Handle)->Next;
free( *Handle );
*Handle = NextHandle;
// Update Maximum Test FD
if (FD == MaxFD-1) { if (FD == MaxFD-1) {
for (TestFD = MaxFD-1; TestFD >= 0; TestFD--) { for (TestFD = MaxFD-1; TestFD >= 0; TestFD--) {
if (FD_ISSET( TestFD, &ReadTestFDS ) || FD_ISSET( TestFD, &WriteTestFDS )) { if (FD_ISSET( TestFD, &ReadTestFDS ) || FD_ISSET( TestFD, &WriteTestFDS )) {
@@ -82,39 +136,46 @@ void SelectRemove( int FD, bool Read, bool Write )
} }
MaxFD = TestFD+1; MaxFD = TestFD+1;
} }
}
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool SelectTest() bool CSelect::Test()
{ {
int Result = 0; TSelectHandle * Handle = NULL;
int Events = 0;
// Set Test sets // Set Test sets
ReadFDS = ReadTestFDS; ReadFDS = ReadTestFDS;
WriteFDS = WriteTestFDS; WriteFDS = WriteTestFDS;
// Perform select // Perform select
Result = select( MaxFD, &ReadFDS, &WriteFDS, (fd_set*)NULL, &SelectTime ); Events = select( MaxFD, &ReadFDS, &WriteFDS, (fd_set*)NULL, &Timeout );
if (Result < 0) if (Events < 0)
{ {
printf( "Select operation failed (%s)\n", strerror(errno) ); printf( "Select operation failed (%s)\n", strerror(errno) );
return false; return false;
} }
// Check all descriptors for events
Handle = FirstHandle;
while (Handle)
{
// Check read Event
if (FD_ISSET( Handle->FD, &ReadFDS ) && Handle->Function) {
Handle->Function->Read( Handle->FD );
}
// Check Write Event
if (FD_ISSET( Handle->FD, &WriteFDS ) && Handle->Function) {
Handle->Function->Write( Handle->FD );
}
// Next
Handle = Handle->Next;
}
// return success // return success
return (bool)Result; return (bool)Events;
}
//---------------------------------------------------------------------------
// Add Select File Descriptor
bool SelectCheck( int FD, bool &Read, bool &Write )
{
// Add Read select
Read = (bool)(FD_ISSET( FD, &ReadFDS ));
// Add Write Select
Write = (bool)(FD_ISSET( FD, &WriteFDS ));
return (Read || Write);
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View File

@@ -31,11 +31,14 @@
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
CSelectableCore::CSelectableCore( const char * Name ) : CSelectableCore::CSelectableCore( const char * Name, CSelect * Selector ) :
CFunctionCore( Name ) CFunctionCore( Name )
{ {
// Handles // Handles
FirstHandle = NULL; FirstHandle = NULL;
// Select
Select = Selector;
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@@ -86,7 +89,7 @@ bool CSelectableCore::RemoveHandle( THandle * Handle )
THandle ** HandlePtr = NULL; THandle ** HandlePtr = NULL;
// Validate // Validate
if (!Handle || (Handle->Type != ctRemoteClient)) { if (!Handle || (Handle->State == csOpen) || (Handle->State == csWaitingtoOpen)) {
return false; return false;
} }
@@ -146,7 +149,7 @@ bool CSelectableCore::SetPortHandle( const char * HandleName, const char * FileN
} }
// Search for file handle // Search for file handle
if (!(Handle = GetHandle( HandleName ))) { if (!(Handle = GetHandle( HandleName )) || (Handle->Type != ctNone)) {
return false; return false;
} }
@@ -171,20 +174,15 @@ bool CSelectableCore::SetSocketHandle( const char * HandleName, EConnectType Ty
THandle * Handle = NULL; THandle * Handle = NULL;
// Validate // Validate
if (!Address || (Type == ctNone)) { if (!Address || (Type == ctNone) || (Type == ctPort)) {
return false; return false;
} }
// Search for file handle // Search for file handle
if (!(Handle = GetHandle( HandleName ))) { if (!(Handle = GetHandle( HandleName )) || (Handle->Type != ctNone)) {
return false; return false;
} }
// Clear File Name
if (Handle->FileName) {
free( Handle->FileName );
}
// Set Type // Set Type
Handle->Type = Type; Handle->Type = Type;
Handle->KeepAlive = KeepAlive; Handle->KeepAlive = KeepAlive;
@@ -292,6 +290,7 @@ int CSelectableCore::OpenPort( THandle * Handle )
} }
// Confirm open // Confirm open
Handle->State = csOpen;
printf( "Port: %s -> Port opened\n", Handle->Name ); printf( "Port: %s -> Port opened\n", Handle->Name );
return Handle->FD; return Handle->FD;
} }
@@ -354,6 +353,10 @@ int CSelectableCore::OpenServerSocket( THandle * Handle )
return -1; return -1;
} }
// Set non-blocking flag
int flags = fcntl( Handle->FD, F_GETFL, 0 );
fcntl( Handle->FD, F_SETFL, flags | O_NONBLOCK );
// Bind socket // Bind socket
if (bind( Handle->FD, (struct sockaddr *)&address, addr_len ) < 0) if (bind( Handle->FD, (struct sockaddr *)&address, addr_len ) < 0)
{ {
@@ -383,14 +386,15 @@ int CSelectableCore::OpenRemoteClientSocket( THandle * Handle )
{ {
THandle ** RemoteClient; THandle ** RemoteClient;
int ClientFD; int ClientFD;
char ClientAddress[25]; char ClientAddress[100];
char ClientName[100];
socklen_t addr_len; socklen_t addr_len;
struct sockaddr_in address; struct sockaddr_in address;
// Validate // Validate
if (!Handle) { if (!Handle) {
return false; return -1;
} }
// Check Handle type // Check Handle type
@@ -400,14 +404,17 @@ int CSelectableCore::OpenRemoteClientSocket( THandle * Handle )
addr_len = sizeof( address ); addr_len = sizeof( address );
if ((ClientFD = accept( Handle->FD, (struct sockaddr *)&address, &addr_len)) == -1) if ((ClientFD = accept( Handle->FD, (struct sockaddr *)&address, &addr_len)) == -1)
{ {
if (errno == EWOULDBLOCK) if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
printf( "Remote Socket: %s [*] -> Failed to accept blocking connection (%s)\n", (*RemoteClient)->Address, strerror(errno) ); printf( "Remote Socket: %s [*] -> Failed to accept blocking connection (%s)\n", Handle->Address, strerror(errno) );
else else
printf( "Remote Socket: %s [*] -> Failed to accept connection (%s)\n", (*RemoteClient)->Address, strerror(errno) ); printf( "Remote Socket: %s [*] -> Failed to accept connection (%s)\n", Handle->Address, strerror(errno) );
close( ClientFD );
return -1; return -1;
} }
// Set non-blocking flag
int flags = fcntl( ClientFD, F_GETFL, 0 );
fcntl( ClientFD, F_SETFL, flags | O_NONBLOCK );
// Return client address // Return client address
strcpy( ClientAddress, inet_ntoa(address.sin_addr) ); strcpy( ClientAddress, inet_ntoa(address.sin_addr) );
@@ -418,32 +425,31 @@ int CSelectableCore::OpenRemoteClientSocket( THandle * Handle )
} }
// Create Remote Client Handle // Create Remote Client Handle
*RemoteClient = CreateHandle( "Client" ); sprintf( ClientName, "%s-%d", Handle->Name, ClientFD );
SetSocketHandle( "Client", ctRemoteClient, ClientAddress, 0, Handle->KeepAlive ); *RemoteClient = CreateHandle( ClientName );
SetBuffers( "Client", 20, 0, 50, "\n", 1 ); SetSocketHandle( ClientName, ctRemoteClient, ClientAddress, 0, Handle->KeepAlive );
SetBuffers( ClientName, 20, 0, 50, "\n", 1 );
(*RemoteClient)->FD = ClientFD; (*RemoteClient)->FD = ClientFD;
(*RemoteClient)->Parent = Handle; (*RemoteClient)->Parent = Handle;
(*RemoteClient)->State = csOpen; (*RemoteClient)->State = csWaitingtoOpen;
printf( "Remote Socket: %s -> Server accepted connection from client (%s)\n", Handle->Address, ClientAddress ); printf( "Remote Socket: %s -> Server accepted connection from client (%s)\n", Handle->Address, ClientAddress );
return (*RemoteClient)->FD; return (*RemoteClient)->FD;
} }
else if (Handle->Type == ctRemoteClient) else if (Handle->Type == ctRemoteClient)
{ {
if (Handle->State == csWaitingtoOpen) // Check state
{ if (Handle->State == csOpen) {
// Clear non blocking flag // Already open
int flags = fcntl( Handle->FD, F_GETFL, 0 );
fcntl( Handle->FD, F_SETFL, (!O_NONBLOCK)&flags );
// Set new state
Handle->State = csOpen;
// Log event
printf( "Socket: %s -> Client now connected to server (%s)\n", Handle->Address, Handle->Parent->Address );
}
return Handle->FD; return Handle->FD;
} }
else if (Handle->State == csWaitingtoOpen) {
// Update state
Handle->State = csOpen;
return Handle->FD;
}
}
return -1; return -1;
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@@ -459,6 +465,17 @@ int CSelectableCore::OpenClientSocket( THandle * Handle )
int TCPcnt_opt = 3; int TCPcnt_opt = 3;
int TCPint_opt = 2; int TCPint_opt = 2;
// Check state
if (Handle->State == csOpen) {
// Already open
return Handle->FD;
}
else if (Handle->State == csWaitingtoOpen) {
// Update state
Handle->State = csOpen;
return Handle->FD;
}
// Create File descriptor // Create File descriptor
if ((Handle->FD = socket( AF_INET, SOCK_STREAM, 0 )) < 0) if ((Handle->FD = socket( AF_INET, SOCK_STREAM, 0 )) < 0)
{ {
@@ -493,8 +510,10 @@ int CSelectableCore::OpenClientSocket( THandle * Handle )
Handle->State = csOpen; Handle->State = csOpen;
return Handle->FD; return Handle->FD;
} }
else if (errno == EINPROGRESS) else if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
{ {
printf( "Client Socket: %s -> Client waiting to connect (%s)\n", Handle->Address, strerror(errno) );
// Set status // Set status
Handle->State = csWaitingtoOpen; Handle->State = csWaitingtoOpen;
return Handle->FD; return Handle->FD;
@@ -515,6 +534,7 @@ int CSelectableCore::OpenClientSocket( THandle * Handle )
int CSelectableCore::Open( const char * HandleName ) int CSelectableCore::Open( const char * HandleName )
{ {
int FD = -1;
THandle * Handle = NULL; THandle * Handle = NULL;
// Validate // Validate
@@ -525,16 +545,26 @@ int CSelectableCore::Open( const char * HandleName )
// Open correctly // Open correctly
switch (Handle->Type) { switch (Handle->Type) {
case ctPort : case ctPort :
return OpenPort( Handle ); FD = OpenPort( Handle );
break;
case ctServer : case ctServer :
return OpenServerSocket( Handle ); FD = OpenServerSocket( Handle );
break;
case ctClient : case ctClient :
return OpenClientSocket( Handle ); FD = OpenClientSocket( Handle );
break;
case ctRemoteClient : case ctRemoteClient :
return OpenRemoteClientSocket( Handle ); FD = OpenRemoteClientSocket( Handle );
break;
default: default:
return -1; FD = -1;
} }
// Add to Select Lists
if (Select && FD != -1) {
Select->Add( FD, true, true, this );
}
return FD;
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@@ -551,9 +581,10 @@ bool CSelectableCore::Close( THandle * Handle, bool CloseChildren )
while (ChildHandle) { while (ChildHandle) {
if (ChildHandle->Parent == Handle) { if (ChildHandle->Parent == Handle) {
NextHandle = ChildHandle->Next; NextHandle = ChildHandle->Next;
// Close and Destroy handle
// Close
Close( ChildHandle ); Close( ChildHandle );
RemoveHandle( ChildHandle );
// Next Handle // Next Handle
ChildHandle = NextHandle; ChildHandle = NextHandle;
} else { } else {
@@ -563,6 +594,11 @@ bool CSelectableCore::Close( THandle * Handle, bool CloseChildren )
} }
} }
// Remove from Select List
if (Select) {
Select->Remove( Handle->FD, true, true );
}
// Close Handle // Close Handle
Fail = (close( Handle->FD ))? true : false; Fail = (close( Handle->FD ))? true : false;
Handle->State = ((Fail)? csFailed : csClosed); Handle->State = ((Fail)? csFailed : csClosed);
@@ -600,28 +636,48 @@ bool CSelectableCore::Close( THandle * Handle, bool CloseChildren )
// Device Interface // Device Interface
bool CSelectableCore::Read( THandle * Handle ) bool CSelectableCore::Read( THandle * Handle )
{ {
int ClientFD = -1;
int BytesRead = 0; int BytesRead = 0;
int BytesWaiting = 0; int BytesWaiting = -1;
// Validate // Validate
if (!Handle) { if (!Handle) {
return false; return false;
} }
// Check for closing event on Socket // Check for closing/opening event on Socket
if ((Handle->Type == ctRemoteClient) || (Handle->Type == ctClient)) if (Handle->Type == ctServer)
{
// Incoming client request
ClientFD = OpenRemoteClientSocket( Handle );
if (ClientFD != -1) {
// Add to Select Lists
if (Select) {
Select->Add( ClientFD, true, true, this );
}
return true;
}
}
else if ((Handle->Type == ctRemoteClient) || (Handle->Type == ctClient))
{ {
// Check if anything to read // Check if anything to read
ioctl( Handle->FD, FIONREAD, &BytesWaiting ); ioctl( Handle->FD, FIONREAD, &BytesWaiting );
if (!BytesWaiting) { // EOF from server
// EOF from server (close connection) if (!BytesWaiting)
{
// Close Handle
Close( Handle ); Close( Handle );
// Destroy Remote Client
if (Handle->Type == ctRemoteClient) {
RemoveHandle( Handle ); RemoveHandle( Handle );
}
return false; return false;
} }
// Check if socket ready (non-block open not in progress) // Check if socket ready (non-block open in progress)
else if (Handle->State == csWaitingtoOpen) { else if (Handle->State == csWaitingtoOpen)
{
printf( "Socket: %s -> Cannot read from socket in waiting\n", Name ); printf( "Socket: %s -> Cannot read from socket in waiting\n", Name );
return false; return false;
} }
@@ -633,8 +689,9 @@ bool CSelectableCore::Read( THandle * Handle )
} }
// Read File directly into buffer // Read File directly into buffer
if (!(BytesRead = Handle->InBuffer->ReadFromFD( Handle->FD ))) if (!(BytesRead = Handle->InBuffer->ReadFromFD( Handle->FD ))) {
return false; return false;
}
// Process Buffer // Process Buffer
ProcessBuffer( Handle, false ); ProcessBuffer( Handle, false );
@@ -648,12 +705,59 @@ bool CSelectableCore::Read( THandle * Handle )
bool CSelectableCore::Write( THandle * Handle ) bool CSelectableCore::Write( THandle * Handle )
{ {
int BytesWritten = 0;
// Validate // Validate
if (!Handle || (Handle->State != csOpen)) { if (!Handle) {
return false; return false;
} }
if (Handle->State == csWaitingtoOpen)
{
// Complete socket open
if (Handle->Type == ctRemoteClient) {
OpenRemoteClientSocket( Handle );
} else if (Handle->Type == ctClient) {
OpenClientSocket( Handle );
}
// Remove from set for select write
if (Select) {
Select->Remove( Handle->FD, false, true );
}
return true; return true;
}
else if (Handle->State == csOpen)
{
if (Handle->OutBuffer)
{
// Write to FD directly from buffer
if (!(BytesWritten = Handle->OutBuffer->WriteToFD( Handle->FD ))) {
return false;
}
// Update Buffer
Handle->OutBuffer->Clear( BytesWritten );
// Check if Buffer emtpy
if (Handle->OutBuffer->Len()) {
// Add to Select Write list
if (Select) {
Select->Remove( Handle->FD, false, true );
}
}
}
else
{
// No Output buffer, so remove from Write list
if (Select) {
Select->Remove( Handle->FD, false, true );
}
}
return true;
}
return false;
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@@ -685,6 +789,35 @@ bool CSelectableCore::Process()
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
int CSelectableCore::ReadFromFD( int FD, char * Data, int MaxLen )
{
int BytesRead = 0;
int TotalRead = 0;
int DataRemain = 0;
// Check if buffer created
if ((FD == -1) || !Data) {
return 0;
}
// Read Data into buffer
DataRemain = (MaxLen == -1)? strlen(Data) : MaxLen;
while (DataRemain)
{
// Read from file descriptor
BytesRead = read( FD, Data, DataRemain );
if (BytesRead <= 0)
break;
// Update Data Pointers
TotalRead += BytesRead;
DataRemain -= BytesRead;
}
return TotalRead;
}
//---------------------------------------------------------------------------
int CSelectableCore::WriteToFD( int FD, const char * Data, int Len ) int CSelectableCore::WriteToFD( int FD, const char * Data, int Len )
{ {
int BytesWritten = 0; int BytesWritten = 0;
@@ -720,7 +853,7 @@ int CSelectableCore::Input( int FD, const char * Data, int Len )
int BytesWritten = 0; int BytesWritten = 0;
// Get File handle // Get File handle
if ((Handle = GetHandle( FD ))) { if ((Handle = GetHandle( "Serial Port" )) || (Handle = GetHandle( "Client" ))) {
// Write to handle // Write to handle
BytesWritten = WriteToFD( Handle->FD, Data, Len ); BytesWritten = WriteToFD( Handle->FD, Data, Len );
} }

View File

@@ -38,16 +38,32 @@ const char ConnectStateName[][15] = { "None", "WaitingToOpen", "Open", "DataWait
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void SelectConfig( long Timeout ); // Previews
void SelectClear(); typedef struct SSelectHandle TSelectHandle;
void SelectAdd( int FD, bool Read, bool Write ); typedef struct SHandle THandle;
void SelectRemove( int FD, bool Read, bool Write );
bool SelectTest(); class CSelect;
bool SelectCheck( int FD, bool &Read, bool &Write ); class CSelectableCore;
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
typedef struct SHandle THandle; // List of Handles for Select Object
struct SSelectHandle {
// File Descriptor
int FD;
bool Read;
bool Write;
// Event Object
CSelectableCore * Function;
// List
TSelectHandle * Next;
};
//---------------------------------------------------------------------------
// List or Handles for Selectable Function Object
struct SHandle { struct SHandle {
// Description // Description
char * Name; char * Name;
@@ -74,18 +90,56 @@ struct SHandle {
timeval InStart; timeval InStart;
long InTimeout; // millisecs long InTimeout; // millisecs
// List / Tree
THandle * Parent; THandle * Parent;
THandle * Next; THandle * Next;
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
class CSelect
{
protected:
// List
TSelectHandle * FirstHandle;
// Select Variables
fd_set ReadTestFDS;
fd_set WriteTestFDS;
fd_set ReadFDS;
fd_set WriteFDS;
// Configuration
int MaxFD;
timeval Timeout;
public:
// Life Cycle
CSelect( long SelectTimeout );
~CSelect();
// Manage FDs
void Clear();
void Add( int FD, bool Read, bool Write, CSelectableCore * Function = NULL);
void Remove( int FD, bool Read, bool Write );
// Testing FDs
bool Test();
bool Check( int FD, bool &Read, bool &Write );
};
//---------------------------------------------------------------------------
class CSelectableCore : public CFunctionCore class CSelectableCore : public CFunctionCore
{ {
protected: protected:
// Device Interfaces // FDs
THandle * FirstHandle; THandle * FirstHandle;
// Select interface
CSelect * Select;
// Managing File Handles // Managing File Handles
bool RemoveHandle( THandle * Handle ); bool RemoveHandle( THandle * Handle );
bool DestroyHandle( THandle * Handle ); bool DestroyHandle( THandle * Handle );
@@ -113,7 +167,7 @@ protected:
// Socket Operations // Socket Operations
virtual int OpenServerSocket( THandle * Handle ); virtual int OpenServerSocket( THandle * Handle );
//virtual int OpenRemoteClientSocket( THandle * Handle ); virtual int OpenRemoteClientSocket( THandle * Handle );
virtual int OpenClientSocket( THandle * Handle ); virtual int OpenClientSocket( THandle * Handle );
// Mutual Operations // Mutual Operations
@@ -121,6 +175,7 @@ protected:
virtual bool Read( THandle * Handle ); virtual bool Read( THandle * Handle );
virtual bool Write( THandle * Handle ); virtual bool Write( THandle * Handle );
int ReadFromFD( int FD, char * Data, int MaxLen );
int WriteToFD( int FD, const char * Data, int Len ); int WriteToFD( int FD, const char * Data, int Len );
// Buffer operations // Buffer operations
@@ -128,7 +183,7 @@ protected:
public: public:
// Life Cycle // Life Cycle
CSelectableCore( const char * Name ); CSelectableCore( const char * Name, CSelect * Selector );
~CSelectableCore(); ~CSelectableCore();
// Configuration // Configuration
@@ -142,7 +197,6 @@ public:
bool ClearHandle( const char * HandleName ); bool ClearHandle( const char * HandleName );
virtual int Open( const char * HandleName ); virtual int Open( const char * HandleName );
virtual int OpenRemoteClientSocket( THandle * Handle );
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 )); };
virtual bool Close( int FD, bool CloseChildren = false ) { return (Close( GetHandle( FD ), CloseChildren )); }; virtual bool Close( int FD, bool CloseChildren = false ) { return (Close( GetHandle( FD ), CloseChildren )); };