/* * SelectableCore.h * * Created on: 13 May 2016 * Author: wentzelc */ #ifndef REDACORE_SELECTABLECORE_H_ #define REDACORE_SELECTABLECORE_H_ // Standard C/C++ Libraries #include // 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 ); bool ChangeState( THandle * Handle, EConnectState State ); // Get Parameters inline int GetFD( const char * HandleName ) { THandle * Handle = GetHandle( HandleName ); return ((Handle)? Handle->FD : -1); }; // 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 ); // 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 * SourceRef, const char * Data, int Len = -1 ); virtual 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 ); // Specific operations bool BuildArgs( const char * ExecPath, int &Count, char * Args[] ); 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 virtual int OutputHandle( THandle * Handle, const char * Data, int Len ); virtual bool Process(); }; //--------------------------------------------------------------------------- #endif /* REDACORE_SELECTABLECORE_H_ */