334 lines
11 KiB
C++
334 lines
11 KiB
C++
/*
|
|
* SelectableCore.h
|
|
*
|
|
* Created on: 13 May 2016
|
|
* Author: wentzelc
|
|
*/
|
|
|
|
#ifndef REDACORE_SELECTABLECORE_H_
|
|
#define REDACORE_SELECTABLECORE_H_
|
|
|
|
// Standard C/C++ Libraries
|
|
#include <ctype.h>
|
|
|
|
// redA Libraries
|
|
#include "FunctionCore.h"
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
// Types required for connections
|
|
typedef enum { ctNone = 0, ctSerial = 1, ctLinePrinter = 2, ctForkPipe = 3, ctUNIXserver = 4, ctUNIXclient = 5, ctUNIXremote = 6,
|
|
ctUDPserver = 7, ctUDPclient = 8, ctUDPremote = 9, ctTCPserver = 10, ctTCPclient = 11, ctTCPremote = 12, ctCustom } EConnectType;
|
|
const char ConnectTypeName[][20] = { "None", "Serial Port", "Line Printer", "Fork Pipe", "UNIX Server", "UNIX Client", "UNIX Remote Client",
|
|
"UDP Server", "UDP Client", "UDP Remote Client", "TCP Server", "TCP Client", "TCP Remote Client", "Custom" };
|
|
|
|
typedef enum { csNone = 0, csOpenRequest = 1, csWaitingtoOpen = 2, csOpen = 3, csDataWaiting = 4, csClosed = 5, csFailed = 6 } EConnectState;
|
|
const char ConnectStateName[][15] = { "None", "OpenRequest", "WaitingToOpen", "Open", "DataWaiting", "Closed", "Failed" };
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
// Defines required to configure port
|
|
#define NO_PARITY 0
|
|
#define ODD_PARITY 1
|
|
#define EVEN_PARITY 2
|
|
#define MARK_PARITY 3
|
|
#define SPACE_PARITY 4
|
|
|
|
#define NO_FLOWCTRL 0
|
|
#define HW_FLOWCTRL 1
|
|
#define SW_FLOWCTRL 2
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
// Previews
|
|
typedef struct SSelectHandle TSelectHandle;
|
|
typedef struct SHandle THandle;
|
|
|
|
class CSelect;
|
|
class CSelectableCore;
|
|
|
|
// Callback function for handle events
|
|
typedef void (*FHandleCallback)( CSelectableCore * Function, THandle * Handle, EConnectState State );
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
// List of Handles for Select Object
|
|
struct SSelectHandle {
|
|
// File Descriptor
|
|
int FD;
|
|
bool Read;
|
|
bool Write;
|
|
|
|
// Event Object
|
|
THandle * Handle;
|
|
CSelectableCore * Function;
|
|
|
|
// List
|
|
TSelectHandle * Next;
|
|
};
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
// List or Handles for Selectable Function Object
|
|
struct SHandle {
|
|
// Description
|
|
char * Name;
|
|
EConnectType Type;
|
|
|
|
// State
|
|
int FD;
|
|
EConnectState State;
|
|
|
|
bool AutoManage;
|
|
bool Persistent;
|
|
timeval LastAction;
|
|
long ReopenDelay; // millisecs before trying to re-open socket
|
|
long CloseTimeout; // millisecs of no traffic before closing socket
|
|
|
|
// Callback functions
|
|
FHandleCallback StateCallback[ 7 ];
|
|
|
|
// Type specific parameters
|
|
char * Path; // Port (file)name or Exec path
|
|
|
|
// Fork config
|
|
pid_t ChildPID; // Forked child PID
|
|
|
|
// Socket config
|
|
char * HostName; // Host name or IP adddress
|
|
char * PortName; // Socket port no or protocol, e.g. "80" or "HTTP"
|
|
struct addrinfo * AddressList; // List of resolved IP Addresses for host name
|
|
struct addrinfo * AddressInfo; // Current selected IP Address
|
|
bool AddressFailed; // Indicate failure to connect to address
|
|
short Queue; // Max waiting connections
|
|
long ResolveDelay; // Delay before resolving hostname via DNS
|
|
|
|
// Serial Port config
|
|
bool SerialConfig;
|
|
int InBaudrate;
|
|
int OutBaudrate;
|
|
short DataBits;
|
|
short Parity;
|
|
short StopBits;
|
|
short FlowCtrl;
|
|
int DataWait;
|
|
|
|
// Buffers
|
|
CRollingBuffer * InBuffer;
|
|
CRollingBuffer * OutBuffer;
|
|
|
|
// Input Markers
|
|
char * InMarker;
|
|
int InMarkerLen;
|
|
|
|
// Input Timer
|
|
timeval InStart;
|
|
long InTimeout; // millisecs
|
|
|
|
// List / Tree
|
|
TChannel * Channel;
|
|
THandle * Parent;
|
|
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;
|
|
|
|
// Output
|
|
CLogCore * Log;
|
|
EDebugLevel LogLevel;
|
|
|
|
public:
|
|
// Life Cycle
|
|
CSelect( long SelectTimeout, EDebugLevel pLogLevel );
|
|
~CSelect();
|
|
|
|
// Parameters
|
|
bool SetLogLevel( EDebugLevel pDebugLevel );
|
|
|
|
// Manage FDs
|
|
void Clear();
|
|
void Add( int FD, bool Read, bool Write, THandle * Handle, CSelectableCore * Function = NULL);
|
|
void Remove( int FD, bool Read, bool Write );
|
|
|
|
// Testing FDs
|
|
bool Test();
|
|
bool Check( int FD, bool &Read, bool &Write );
|
|
};
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
// Function Constructor
|
|
#define TYPE_SELECTABLE "Selectable"
|
|
CFunctionCore * NewSelectableCore( const char * Name );
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
class CSelectableCore : public CFunctionCore
|
|
{
|
|
protected:
|
|
// FDs
|
|
THandle * FirstHandle;
|
|
|
|
// Select interface
|
|
CSelect * Selector;
|
|
|
|
// Managing File Handles
|
|
bool RemoveHandle( THandle * Handle );
|
|
bool DestroyHandle( THandle * Handle );
|
|
|
|
// Get Parameters
|
|
inline int GetFD( const char * HandleName ) {
|
|
THandle * Handle = GetHandle( HandleName );
|
|
return ((Handle)? Handle->FD : -1);
|
|
};
|
|
|
|
// General fucntions
|
|
inline bool ChangeState( THandle * Handle, EConnectState State ) {
|
|
if (!Handle || (Handle->State == State)) return false;
|
|
if (Handle->StateCallback[ (int)State ])
|
|
(Handle->StateCallback[ (int)State ])( this, Handle, State );
|
|
Handle->State = State;
|
|
return true;
|
|
}
|
|
|
|
// Port Operations
|
|
THandle * OpenSerialPort( THandle * Handle );
|
|
bool WriteSerialConfig( THandle * Handle );
|
|
bool ReadSerialConfig( THandle * Handle );
|
|
|
|
THandle * OpenLinePrinterPort( THandle * Handle );
|
|
|
|
// File Socket Operations
|
|
THandle * OpenForkPipe( THandle * Handle );
|
|
THandle * OpenUNIXserverSocket( THandle * Handle );
|
|
THandle * OpenUNIXclientSocket( THandle * Handle );
|
|
THandle * OpenUNIXremoteSocket( THandle * Handle );
|
|
|
|
// Socket Operations
|
|
bool ResolveAddress( THandle * Handle, bool DelayResolve );
|
|
THandle * OpenUDPserverSocket( THandle * Handle, bool DelayResolve );
|
|
THandle * OpenUDPremoteSocket( THandle * Handle, char * RemoteAddr, char * RemotePort );
|
|
THandle * OpenUDPclientSocket( THandle * Handle, bool DelayResolve );
|
|
THandle * OpenTCPserverSocket( THandle * Handle, bool DelayResolve );
|
|
THandle * OpenTCPremoteSocket( THandle * Handle );
|
|
THandle * OpenTCPclientSocket( THandle * Handle, bool DelayResolve );
|
|
|
|
// Mutual Operations
|
|
int ReadFromFD( int FD, char * Data, int MaxLen );
|
|
int WriteToFD( int FD, const char * Data, int Len, bool Force );
|
|
|
|
int ReadFromUDP( THandle * Handle, char * RemoteAddr, char * RemotePort, char * Data, int MaxLen );
|
|
int WriteToUDP( THandle * Handle, const char * Data, int Len, bool Force );
|
|
|
|
// Buffer operations
|
|
virtual bool ProcessInputBuffer( THandle * Handle, bool Force );
|
|
|
|
// Specific operations
|
|
bool BuildArgs( const char * ExecPath, int &Count, char * Args[] );
|
|
|
|
// Convert string to lower case
|
|
inline char * strlcase( char * Str ) {
|
|
for (char * Ch = Str; *Ch; Ch++ )
|
|
*Ch = tolower(*Ch);
|
|
return Str;
|
|
}
|
|
|
|
public:
|
|
// Life Cycle
|
|
CSelectableCore( const char * Name, const char * Type = TYPE_SELECTABLE );
|
|
virtual ~CSelectableCore();
|
|
|
|
// Configuration
|
|
virtual bool Init( CDataMember * FunctionConfig );
|
|
|
|
// Finding Handles
|
|
inline THandle * GetHandle( const char * HandleName )
|
|
{
|
|
if (!HandleName) return NULL;
|
|
THandle * Handle = FirstHandle;
|
|
while ( Handle && strcmp( HandleName, Handle->Name ))
|
|
Handle = Handle->Next;
|
|
return Handle;
|
|
}
|
|
inline THandle * GetHandle( int FD )
|
|
{
|
|
if (FD < 0) return NULL;
|
|
THandle * Handle = FirstHandle;
|
|
while ( Handle && (FD != Handle->FD))
|
|
Handle = Handle->Next;
|
|
return Handle;
|
|
}
|
|
|
|
// General port parameters
|
|
THandle * CreateHandle( const char * HandleName, bool CreateChannel );
|
|
|
|
bool SetCallback( THandle * Handle, EConnectState pState, FHandleCallback pCallback );
|
|
bool SetAutoManage( THandle * Handle, bool AutoManage, bool Persistent, int ReopenDelay = 0, int CloseTimeout = 0 );
|
|
bool SetInBuffer( THandle * Handle, int InBufSize, int InTimeout, const char * InMarker, int InMarkerLen );
|
|
bool SetOutBuffer( THandle * Handle, int OutBufSize );
|
|
|
|
// Specific port parameters
|
|
bool SetSerialHandle( THandle * Handle, const char * FileName );
|
|
bool SetSerialHandleConfig( THandle * Handle, int Baudrate, short DataBits, short Parity, short StopBits, short FlowCtrl, int DataWait );
|
|
bool SetLinePrinterHandle( THandle * Handle, const char * FileName );
|
|
bool SetForkPipeHandle( THandle * Handle, const char * ExecPath );
|
|
bool SetUnixHandle( THandle * Handle, EConnectType Type, const char * FileName, short Queue );
|
|
bool SetSocketHandle( THandle * Handle, EConnectType Type, const char * HostName, const char * PortName, short Queue, long ResolveDelay );
|
|
|
|
bool ClearHandle( THandle * Handle );
|
|
|
|
// FD Operations
|
|
virtual int Open( THandle * Handle, bool DelayResolve = false );
|
|
virtual bool Close( THandle * Handle, bool QuickReopen );
|
|
virtual bool Read( THandle * Handle );
|
|
virtual bool Write( THandle * Handle );
|
|
|
|
// FD operations
|
|
inline virtual int Open( const char * HandleName, bool DelayResolve = false ) { return (Open( GetHandle( HandleName ), DelayResolve)); };
|
|
|
|
inline virtual bool Close( const char * HandleName, bool QuickReopen ) { return (Close( GetHandle( HandleName ), QuickReopen )); };
|
|
inline virtual bool Close( int FD, bool QuickReopen ) { return (Close( GetHandle( FD ), QuickReopen )); };
|
|
|
|
inline virtual bool Read( const char * HandleName ) { return (Read( GetHandle( HandleName ))); };
|
|
inline virtual bool Read( int FD ) { return (Read( GetHandle( FD ))); };
|
|
|
|
inline virtual bool Write( const char * HandleName ) { return (Write( GetHandle( HandleName ))); };
|
|
inline virtual bool Write( int FD ) { return (Write( GetHandle( FD ))); };
|
|
|
|
// Info
|
|
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( const char * ChannelName, const char * Buffer, int BufLen = -1 );
|
|
int OutputHandle( THandle * Handle, const char * Data, int Len );
|
|
virtual bool Process();
|
|
};
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
#endif /* REDACORE_SELECTABLECORE_H_ */
|