Files
redAcore/SelectableCore.h
Charl Wentzel 5899bf9892 Merge branch 'master' into HitNotBLE
# Conflicts:
#	SelectableCore.cpp
#	SelectableCore.h
2019-04-03 17:02:52 +02:00

363 lines
13 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
#define RS485_FLOWCTRL 3
//---------------------------------------------------------------------------
// Previews
typedef struct SSelectHandle TSelectHandle;
typedef struct SHandle THandle;
class CSelect;
class CSelectableBare;
class CSelectableCore;
// Callback function for handle events
typedef void (*FHandleCallback)( CSelectableBare * Function, THandle * Handle, EConnectState State );
//---------------------------------------------------------------------------
// List of Handles for Select Object
struct SSelectHandle {
// File Descriptor
int FD = -1;
bool Read = false;
bool Write = false;
// Event Object
THandle * Handle = NULL;
CSelectableBare * Function = NULL;
// List
TSelectHandle * Next = NULL;
};
//---------------------------------------------------------------------------
// List or Handles for Selectable Function Object
struct SHandle {
// Description
char * Name = NULL;
EConnectType Type = ctNone;
// State
int FD = -1;
EConnectState State = csNone;
bool AutoManage = false;
bool Persistent = false;
timeval LastAction = {0,0};
long ReopenDelay = 1000; // millisecs before trying to re-open socket
long CloseTimeout = 1000; // millisecs of no traffic before closing socket
// Callback functions
FHandleCallback StateCallback[ 7 ] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL};
// Type specific parameters
char * Path = NULL; // Port (file)name or Exec path
// Fork config
pid_t ChildPID; // Forked child PID
// Socket config
char * HostName = NULL; // Host name or IP adddress
char * PortName = NULL; // Socket port no or protocol, e.g. "80" or "HTTP"
struct addrinfo * AddressList = NULL; // List of resolved IP Addresses for host name
struct addrinfo * AddressInfo = NULL; // Current selected IP Address
bool AddressFailed = false; // Indicate failure to connect to address
short Queue = 2; // Max waiting connections
long ResolveDelay = 0; // Delay before resolving hostname via DNS
// Serial Port config
bool SerialConfig = false;
int InBaudrate = 0;
int OutBaudrate = 0;
short DataBits = 0;
short Parity = NO_PARITY;
short StopBits = 0;
short FlowCtrl = NO_FLOWCTRL;
int DataWait = 0;
// Buffers
CRollingBuffer * InBuffer = NULL;
CRollingBuffer * OutBuffer = NULL;
// Input Markers
char * InMarker = NULL;
int InMarkerLen = 0;
// Input Timer
timeval InStart = {0,0};
long InTimeout = 0; // millisecs
// List / Tree
TChannel * Channel = NULL;
THandle * Parent = NULL;
THandle * Next = NULL;
};
//---------------------------------------------------------------------------
class CSelect
{
protected:
// List
TSelectHandle * FirstHandle = NULL;
// Select Variables
fd_set ReadTestFDS;
fd_set WriteTestFDS;
fd_set ReadFDS;
fd_set WriteFDS;
// Configuration
int MaxFD = 0;
timeval Timeout = {0,0};
// Output
CLogCore * Log = NULL;
EDebugLevel LogLevel = dlNone;
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, CSelectableBare * 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 CSelectableBare : public CFunctionCore
{
protected:
// FDs
THandle * FirstHandle = NULL;
// Select interface
CSelect * Selector = NULL;
// 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;
}
// Mutual Operations
int ReadFromFD( int FD, char * Data, int MaxLen );
int WriteToFD( int FD, 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
CSelectableBare( const char * Name, const char * Type = TYPE_SELECTABLE );
virtual ~CSelectableBare();
// Configuration
virtual bool Init( CDataMember * FunctionConfig ) = 0;
// 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 );
virtual CDataMember * GetHandleAddress( THandle * Handle, const char * HandleRef );
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 ClearHandle( THandle * Handle );
// FD Operations
virtual int Open( THandle * Handle, bool DelayResolve = false ) = 0;
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();
};
//---------------------------------------------------------------------------
class CSelectableCore : public CSelectableBare
{
protected:
// 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 ReadFromUDP( THandle * Handle, char * RemoteAddr, char * RemotePort, char * Data, int MaxLen );
int WriteToUDP( THandle * Handle, const char * Data, int Len, bool Force );
public:
// Life Cycle
CSelectableCore( const char * Name, const char * Type = TYPE_SELECTABLE );
virtual ~CSelectableCore();
// Configuration
virtual bool Init( CDataMember * FunctionConfig );
// 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 );
// 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 );
// Function Interface
int OutputHandle( THandle * Handle, const char * Data, int Len );
virtual bool Process();
};
//---------------------------------------------------------------------------
#endif /* REDACORE_SELECTABLECORE_H_ */