From 7f39f8b985a93a1996899c40cd04a234cef871a6 Mon Sep 17 00:00:00 2001 From: Charl Wentzel Date: Wed, 6 Dec 2017 08:43:25 +0200 Subject: [PATCH] Important update: - SelectableCore: - Rename methods: SetSerialPortConfig() -> WriteSerialConfig(), GetSerialPortConfig() -> ReadSerialConfig(), InputHandle() -> OutputHandle(), ProcessBuffer() -> ProcessInputBuffer() SetPortHandle(config)() -> SetSerialHandle(Config)() - Rename serial port identification: "Port" -> "SerialPort" - Update logs accordingly - Add LinePrinter Port - Add to LoadConfig() - Add SetLinePrinterHandle() & OpenLinePrinterPort() methods - Add handling for open/read/write/close events - Add CloseDelay for AutoManage (non-persistent) ports - Rename handle timer: ReopenStart -> LastAction - Reset timer on all open/read/write/close events - Check for Close timeout in Process() and close port - Remove CloseChildren parameter on Close() method - Add QuickReopen parameter to Close() method - SelectCore: - Overwrite existing handle - not yet removed - Handle In/Out baudrate on serial port separately --- SelectCore.cpp | 18 +- SelectableCore.cpp | 454 +++++++++++++++++++++++++++++++-------------- SelectableCore.h | 52 +++--- WatchdogCore.cpp | 4 +- 4 files changed, 352 insertions(+), 176 deletions(-) diff --git a/SelectCore.cpp b/SelectCore.cpp index 56a652a..f6d2ed0 100644 --- a/SelectCore.cpp +++ b/SelectCore.cpp @@ -93,18 +93,20 @@ void CSelect::Add( int FD, bool Read, bool Write, CSelectableCore * Function ) while (*Handle && ((*Handle)->FD != FD)) { Handle = &((*Handle)->Next); } - - // Create if not exist - if (!*Handle) { - // Create + if (*Handle) { + // Old handle not yet removed, remove from read/write lists + Remove( FD, true, true ); + } + else { + // Create if not exist *Handle = (TSelectHandle*)malloc( sizeof(TSelectHandle) ); memset( *Handle, 0, sizeof(TSelectHandle) ); - - // Set Parameters - (*Handle)->FD = FD; - (*Handle)->Function = Function; + (*Handle)->FD = FD; } + // Set Parameters + (*Handle)->Function = Function; + // Add Read select if (Read && !(*Handle)->Read) { (*Handle)->Read = true; diff --git a/SelectableCore.cpp b/SelectableCore.cpp index f7f5449..c704505 100644 --- a/SelectableCore.cpp +++ b/SelectableCore.cpp @@ -53,7 +53,7 @@ CSelectableCore::~CSelectableCore() { // Close handle if open if ((FirstHandle->State == csOpen) || (FirstHandle->State == csWaitingtoOpen)) { - Close( FirstHandle, true ); + Close( FirstHandle, false ); } NextHandle = FirstHandle->Next; @@ -94,14 +94,14 @@ bool CSelectableCore::LoadConfigData() Handle->Channel = GetChannel( DataTree->GetStr( TempMember, "Channel" ) ); Type = (char*)DataTree->GetStr( TempMember, "Type", "TCPclient", true ); - if (!strcasecmp( Type, "Port" )) + if (!strcasecmp( Type, "Serial" )) { Address = (char*)DataTree->GetStr( TempMember, "Port/Address", NULL ); // Get default value if ((Name = (char*)DataTree->GetStr( TempMember, "Port/Name", NULL ))) { sprintf( Path, "Address/%s/Address", Name ); Address = (char*)DataTree->GetStr( NULL, Path, Address, true ); // Get address list value } - SetPortHandle( Handle, Address ); + SetSerialHandle( Handle, Address ); // Update configuration if specified if ((SerialConfig = DataTree->GetMember( TempMember, "Port/SerialConfig", false ))) @@ -125,12 +125,21 @@ bool CSelectableCore::LoadConfigData() FlowCtrl = SW_FLOWCTRL; Handle->SerialConfig = true; - SetPortHandleSerial( Handle, DataTree->GetInt( SerialConfig, "BaudRate", 19200, true ), + SetSerialHandleConfig( Handle, DataTree->GetInt( SerialConfig, "BaudRate", 19200, true ), DataTree->GetInt( SerialConfig, "DataBits", 8, true ), Parity, DataTree->GetInt( SerialConfig, "StopBits", 1, true ), FlowCtrl, DataTree->GetInt( SerialConfig, "DataWait", 0, true )); } } + else if (!strcasecmp( Type, "LinePrinter" )) + { + Address = (char*)DataTree->GetStr( TempMember, "Port/Address", NULL ); // Get default value + if ((Name = (char*)DataTree->GetStr( TempMember, "Port/Name", NULL ))) { + sprintf( Path, "Address/%s/Address", Name ); + Address = (char*)DataTree->GetStr( NULL, Path, Address, true ); // Get address list value + } + SetLinePrinterHandle( Handle, Address ); + } else if (!strcasecmp( Type, "TCPserver" )) { Address = (char*)DataTree->GetStr( TempMember, "Socket/Address", NULL ); // Get default Address value @@ -163,7 +172,8 @@ bool CSelectableCore::LoadConfigData() // Set Auto Mange SetAutoManage( Handle, DataTree->GetBool( TempMember, "AutoManage/Enabled", true, true ), DataTree->GetBool( TempMember, "AutoManage/Persistent", false, true ), - DataTree->GetInt( TempMember, "AutoManage/ReopenDelay", 2000, true ) ); + DataTree->GetInt( TempMember, "AutoManage/ReopenDelay", 2000, true ), + DataTree->GetInt( TempMember, "AutoManage/CloseDelay", 2000, true )); // Input buffer SetInBuffer( Handle, DataTree->GetInt( TempMember, "InputBuffer/Size", 0 ), @@ -279,15 +289,15 @@ bool CSelectableCore::DestroyHandle( THandle * Handle ) } //--------------------------------------------------------------------------- -bool CSelectableCore::SetPortHandle( THandle * Handle, const char * FileName ) +bool CSelectableCore::SetSerialHandle( THandle * Handle, const char * FileName ) { // Validate - if (!Handle || ((Handle->Type != ctNone) && (Handle->Type != ctPort)) || !FileName) { + if (!Handle || ((Handle->Type != ctNone) && (Handle->Type != ctSerial)) || !FileName) { return false; } // Set Type - Handle->Type = ctPort; + Handle->Type = ctSerial; // Clear File Name if (Handle->Path) { @@ -304,24 +314,50 @@ bool CSelectableCore::SetPortHandle( THandle * Handle, const char * FileName ) } //--------------------------------------------------------------------------- -bool CSelectableCore::SetPortHandleSerial( THandle * Handle, int Baudrate, short DataBits, short Parity, short StopBits, short FlowCtrl, int DataWait ) +bool CSelectableCore::SetSerialHandleConfig( THandle * Handle, int Baudrate, short DataBits, short Parity, short StopBits, short FlowCtrl, int DataWait ) { // Validate - if (!Handle || (Handle->Type != ctPort)) { + if (!Handle || (Handle->Type != ctSerial)) { return false; } - Handle->Baudrate = Baudrate; - Handle->DataBits = DataBits; - Handle->Parity = Parity; - Handle->StopBits = StopBits; - Handle->FlowCtrl = FlowCtrl; - Handle->DataWait = DataWait; + Handle->InBaudrate = Baudrate; + Handle->OutBaudrate = Baudrate; + Handle->DataBits = DataBits; + Handle->Parity = Parity; + Handle->StopBits = StopBits; + Handle->FlowCtrl = FlowCtrl; + Handle->DataWait = DataWait; return true; } //--------------------------------------------------------------------------- +bool CSelectableCore::SetLinePrinterHandle( THandle * Handle, const char * FileName ) +{ + // Validate + if (!Handle || ((Handle->Type != ctNone) && (Handle->Type != ctLinePrinter)) || !FileName) { + return false; + } + + // Set Type + Handle->Type = ctLinePrinter; + + // Clear File Name + if (Handle->Path) { + free( Handle->Path ); + } + + // Set name + Handle->Path = (char*)malloc( strlen(FileName)+1 ); + strcpy( Handle->Path, FileName ); + + // Log event + if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Set as Port [%s]", Name, Handle->Name, FileName ); + return true; +} +//--------------------------------------------------------------------------- + bool CSelectableCore::SetForkPipeHandle( THandle * Handle, const char * ExecPath ) { // Validate @@ -429,7 +465,7 @@ bool CSelectableCore::SetCallback( THandle * Handle, EConnectState pState, FHand } //--------------------------------------------------------------------------- -bool CSelectableCore::SetAutoManage( THandle * Handle, bool AutoManage, bool Persistent, int ReopenDelay ) +bool CSelectableCore::SetAutoManage( THandle * Handle, bool AutoManage, bool Persistent, int ReopenDelay, int CloseTimeout ) { // Validate if (!Handle) { @@ -437,9 +473,10 @@ bool CSelectableCore::SetAutoManage( THandle * Handle, bool AutoManage, bool Per } // Set params - Handle->AutoManage = AutoManage; - Handle->Persistent = Persistent; - Handle->ReopenDelay = ReopenDelay; + Handle->AutoManage = AutoManage; + Handle->Persistent = Persistent; + Handle->ReopenDelay = ReopenDelay; + Handle->CloseTimeout = CloseTimeout; return true; } //--------------------------------------------------------------------------- @@ -495,7 +532,7 @@ bool CSelectableCore::SetOutBuffer( THandle * Handle, int OutBufSize ) } //--------------------------------------------------------------------------- -int CSelectableCore::OpenPort( THandle * Handle ) +int CSelectableCore::OpenSerialPort( THandle * Handle ) { // Validate if (!Handle || (Handle->Type == ctNone)) { @@ -508,7 +545,7 @@ int CSelectableCore::OpenPort( THandle * Handle ) if (access( Handle->Path, F_OK ) != 0) { // Log event - if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Port not found [%s]", Name, Handle->Name, Handle->Path ); + if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Serial Port not found [%s]", Name, Handle->Name, Handle->Path ); return -1; } @@ -517,20 +554,20 @@ int CSelectableCore::OpenPort( THandle * Handle ) if (Handle->FD == -1) { // Log event - if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Could not open Port [%s]", Name, Handle->Name, Handle->Path ); + if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Could not open Serial Port [%s]", Name, Handle->Name, Handle->Path ); return -1; } // Log Event - if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Port opened [%s]", Name, Handle->Name, Handle->Path ); + if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Serial Port opened [%s]", Name, Handle->Name, Handle->Path ); // Update port configuration if (Handle->SerialConfig) - SetSerialPortConfig( Handle ); + WriteSerialConfig( Handle ); else - GetSerialPortConfig( Handle ); - if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Port config, B:%d, D:%d, P:%d, S:%d, F:%d", Name, Handle->Name, - Handle->Baudrate, Handle->DataBits, Handle->Parity, Handle->StopBits, Handle->FlowCtrl ); + ReadSerialConfig( Handle ); + if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Serial Port config, IB:%d, OB:%d, D:%d, P:%d, S:%d, F:%d", Name, Handle->Name, + Handle->InBaudrate, Handle->OutBaudrate, Handle->DataBits, Handle->Parity, Handle->StopBits, Handle->FlowCtrl ); // Add to Select Lists if (Selector) { @@ -541,7 +578,46 @@ int CSelectableCore::OpenPort( THandle * Handle ) ChangeState( Handle, csOpen ); return Handle->FD; } +//--------------------------------------------------------------------------- +int CSelectableCore::OpenLinePrinterPort( THandle * Handle ) +{ + // Validate + if (!Handle || (Handle->Type == ctNone)) { + return -1; + } else if (Handle->State == csOpen) { + return Handle->FD; + } + + // Check if port exits + if (access( Handle->Path, F_OK ) != 0) + { + // Log event + if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Printer Port not found [%s]", Name, Handle->Name, Handle->Path ); + return -1; + } + + // Open Port + Handle->FD = open( Handle->Path, O_RDWR ); + if (Handle->FD == -1) + { + // Log event + if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Could not open Printer Port [%s]", Name, Handle->Name, Handle->Path ); + return -1; + } + + // Log Event + if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Printer Port opened [%s]", Name, Handle->Name, Handle->Path ); + + // Add to Select Lists + if (Selector) { + Selector->Add( Handle->FD, true, false, this ); + } + + // Set state + ChangeState( Handle, csOpen ); + return Handle->FD; +} //--------------------------------------------------------------------------- int CSelectableCore::OpenForkPipe( THandle * Handle ) @@ -892,6 +968,9 @@ int CSelectableCore::OpenRemoteClientSocket( THandle * Handle ) (*RemoteClient)->Parent = Handle; (*RemoteClient)->State = csWaitingtoOpen; + // Reset Timer + SetStartTime( &((*RemoteClient)->LastAction) ); + // Log Event if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - TCP Server accepted Remote TCP Client connection [%s]", Name, Handle->Name, ClientAddress ); @@ -1024,9 +1103,6 @@ int CSelectableCore::OpenClientSocket( THandle * Handle ) ChangeState( Handle, csFailed ); Handle->AddressFailed = true; - // Start re-open timer - SetStartTime( &(Handle->ReopenStart) ); - // Reset Handle Handle->FD = -1; return -1; @@ -1045,8 +1121,11 @@ int CSelectableCore::Open( THandle * Handle ) // Open correctly switch (Handle->Type) { - case ctPort : - FD = OpenPort( Handle ); + case ctSerial : + FD = OpenSerialPort( Handle ); + break; + case ctLinePrinter : + FD = OpenLinePrinterPort( Handle ); break; case ctForkPipe : FD = OpenForkPipe( Handle ); @@ -1064,16 +1143,14 @@ int CSelectableCore::Open( THandle * Handle ) FD = -1; } - // Clear timer - if ((Handle->State == csOpen) || (Handle->State == csWaitingtoOpen)) { - ClearStartTime( &Handle->ReopenStart ); - } + // Set timer (for re-open or auto-close) + SetStartTime( &Handle->LastAction ); return FD; }; //--------------------------------------------------------------------------- // Delete socket -bool CSelectableCore::Close( THandle * Handle, bool CloseChildren ) +bool CSelectableCore::Close( THandle * Handle, bool QuickReopen ) { bool Fail; THandle * ChildHandle = NULL; @@ -1084,7 +1161,7 @@ bool CSelectableCore::Close( THandle * Handle, bool CloseChildren ) return false; // Close Children - if (CloseChildren && (Handle->Type == ctServer)) + if (Handle->Type == ctServer) { ChildHandle = FirstHandle; while (ChildHandle) @@ -1093,7 +1170,7 @@ bool CSelectableCore::Close( THandle * Handle, bool CloseChildren ) { // Close and remove handle NextHandle = ChildHandle->Next; - Close( ChildHandle ); + Close( ChildHandle, false ); ChildHandle = NextHandle; } else @@ -1108,15 +1185,23 @@ bool CSelectableCore::Close( THandle * Handle, bool CloseChildren ) Fail = (close( Handle->FD ))? true : false; ChangeState( Handle, ((Fail)? csFailed : csClosed) ); - // Start re-open timer - SetStartTime( &(Handle->ReopenStart) ); + // Start timer (for re-open) + if (QuickReopen) + ClearStartTime( &(Handle->LastAction) ); + else + SetStartTime( &(Handle->LastAction) ); // Show action switch (Handle->Type) { - case ctPort: + case ctSerial: // Log Event - if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Port %s [%s]", Name, Handle->Name, ((Fail)? "failed" : "closed"), Handle->Path ); + if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Serial Port %s [%s]", Name, Handle->Name, ((Fail)? "failed" : "closed"), Handle->Path ); + break; + + case ctLinePrinter: + // Log Event + if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Printer Port %s [%s]", Name, Handle->Name, ((Fail)? "failed" : "closed"), Handle->Path ); break; case ctForkPipe: @@ -1176,6 +1261,8 @@ bool CSelectableCore::Read( THandle * Handle ) if (ClientFD == -1) { return false; } + // Reset Timer + SetStartTime( &(Handle->LastAction) ); // Add to Select Lists if (Selector) { @@ -1193,17 +1280,24 @@ bool CSelectableCore::Read( THandle * Handle ) } else if (Handle->Type == ctClient) { OpenClientSocket( Handle ); } + // Reset Timer (for auto-close) + SetStartTime( &(Handle->LastAction) ); + return true; } // Check if anything to read ioctl( Handle->FD, FIONREAD, &BytesWaiting ); - // EOF from server + // Error or EOF from server if (BytesWaiting < 1) { + // Log if there is an error + if (Log && (BytesWaiting < 1)) + Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Error: [%d] $s", Name, Handle->Name, errno, strerror(errno) ); + // Close Handle - Close( Handle ); + Close( Handle, false ); // Destroy Client if (Handle->Type == ctRemoteClient) { @@ -1212,24 +1306,36 @@ bool CSelectableCore::Read( THandle * Handle ) return false; } } - else if (Handle->Type == ctPort) + else if (Handle->Type == ctSerial) { // Check if anything to read ioctl( Handle->FD, FIONREAD, &BytesWaiting ); - // EOF from port - if (BytesWaiting < 1) + // Error on port + if (BytesWaiting < 0) { - // Close Handle - Close( Handle ); + if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Error: [%d] $s", Name, Handle->Name, errno, strerror(errno) ); - // Destroy Port - if (Handle->Type == ctRemoteClient) { - RemoveHandle( Handle ); - } + // Close Handle + Close( Handle, false ); return false; } } + else if (Handle->Type == ctLinePrinter) + { +// // Check if anything to read +// ioctl( Handle->FD, FIONREAD, &BytesWaiting ); <-- Not valid ioctl for lp port +// +// // Error on port +// if (BytesWaiting < 0) +// { +// if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Error: [%d] $s", Name, Handle->Name, errno, strerror(errno) ); +// +// // Close Handle +// Close( Handle, false ); +// return false; +// } + } // Validate if (Handle->State != csOpen) { @@ -1240,7 +1346,7 @@ bool CSelectableCore::Read( THandle * Handle ) if (Handle->InBuffer && (BytesRead = Handle->InBuffer->ReadFromFD( Handle->FD, BytesWaiting ))) { // Process Buffer - ProcessBuffer( Handle, false ); + ProcessInputBuffer( Handle, false ); } // Reset timer @@ -1269,13 +1375,10 @@ bool CSelectableCore::Write( THandle * Handle ) // Must be opened manually return false; } - else if (Timeout( Handle->ReopenStart, Handle->ReopenDelay )) + else if (Timeout( Handle->LastAction, Handle->ReopenDelay )) { - // Complete opening process - if (Open( Handle ) == -1) { - // Reset Timer - SetStartTime( &(Handle->ReopenStart) ); - } + // Attempt to re-open port + Open( Handle ); } } @@ -1290,6 +1393,8 @@ bool CSelectableCore::Write( THandle * Handle ) } else if (Handle->Type == ctClient) { OpenClientSocket( Handle ); } + // Reset Timer (for auto-close) + SetStartTime( &(Handle->LastAction) ); // Remove from set for select write if (Selector) { @@ -1312,6 +1417,9 @@ bool CSelectableCore::Write( THandle * Handle ) // Update Buffer Handle->OutBuffer->Clear( BytesWritten ); + + // Reset Timer + SetStartTime( &(Handle->LastAction) ); } // Check if Buffer emtpy @@ -1336,7 +1444,7 @@ bool CSelectableCore::Write( THandle * Handle ) } //--------------------------------------------------------------------------- -bool CSelectableCore::ProcessBuffer( THandle * Handle, bool Force ) +bool CSelectableCore::ProcessInputBuffer( THandle * Handle, bool Force ) { int Pos = 0; int Len = 0; @@ -1481,7 +1589,7 @@ int CSelectableCore::Input( const char * ChannelName, const char * Data, int Len if (Handle->Channel && !strcasecmp( ChannelName, Handle->Channel->Name )) { // Input to Handle - TempWritten = InputHandle( Handle, Data, Len ); + TempWritten = OutputHandle( Handle, Data, Len ); BytesWritten = (TempWritten > BytesWritten)? TempWritten : BytesWritten; HandleCount++; } @@ -1498,7 +1606,7 @@ int CSelectableCore::Input( const char * ChannelName, const char * Data, int Len } //--------------------------------------------------------------------------- -int CSelectableCore::InputHandle( THandle * Handle, const char * Data, int Len ) +int CSelectableCore::OutputHandle( THandle * Handle, const char * Data, int Len ) { THandle * ChildHandle = NULL; int BytesWritten = 0; @@ -1512,13 +1620,10 @@ int CSelectableCore::InputHandle( THandle * Handle, const char * Data, int Len ) if (Log) Log->Message( LogLevel, dlHigh, "%s: Handle '%s' - Input rejected, Handle not Open (not auto-managed)", Name, Handle->Name ); return 0; } - else if (Timeout( Handle->ReopenStart, Handle->ReopenDelay )) + else if (Timeout( Handle->LastAction, Handle->ReopenDelay )) { // Complete opening process - if (Open( Handle ) == -1) { - // Reset Timer - SetStartTime( &(Handle->ReopenStart) ); - } + Open( Handle ); // Check if Handle is open if (Handle->State == csWaitingtoOpen) { @@ -1533,7 +1638,7 @@ int CSelectableCore::InputHandle( THandle * Handle, const char * Data, int Len ) else { if (Log) Log->Message( LogLevel, dlHigh, "%s: Handle '%s' - Input rejected, Retry (auto-managed) Handle re-open in %d ms", Name, Handle->Name, - TimeLeft( Handle->ReopenStart, Handle->ReopenDelay) ); + TimeLeft( Handle->LastAction, Handle->ReopenDelay) ); return 0; } } @@ -1565,11 +1670,14 @@ int CSelectableCore::InputHandle( THandle * Handle, const char * Data, int Len ) } else { + // Show event + if (Log) Log->Output( LogLevel, dlHigh, LogOutput, Data, Len, "%s: Handle '%s' - OUT:", Name, ChildHandle->Name ); + // Write directly to handle BytesWritten = WriteToFD( ChildHandle->FD, Data, Len, true ); - // Show event - if (Log) Log->Output( LogLevel, dlHigh, LogOutput, Data, Len, "%s: Handle '%s' - OUT:", Name, ChildHandle->Name ); + // Reset Timer + SetStartTime( &(Handle->LastAction) ); } } // Next @@ -1598,7 +1706,11 @@ int CSelectableCore::InputHandle( THandle * Handle, const char * Data, int Len ) if (Log) Log->Output( LogLevel, dlHigh, LogOutput, Data, Len, "%s: Handle '%s' - OUT:", Name, Handle->Name ); // Write directly to handle - BytesWritten = WriteToFD( Handle->FD, Data, Len, true ); + if ((BytesWritten = WriteToFD( Handle->FD, Data, Len, true ))) + { + // Reset Timer + SetStartTime( &(Handle->LastAction) ); + } } } @@ -1617,15 +1729,9 @@ bool CSelectableCore::Process() // Auto manage handles if ((Handle->State != csOpen) && Handle->AutoManage && Handle->Persistent) { - // Check duration since last PortIn - if (Timeout( Handle->ReopenStart, Handle->ReopenDelay )) - { - // Complete opening process - if (Open( Handle ) == -1) - { - // Reset Timer - SetStartTime( &(Handle->ReopenStart) ); - } + // Try to re-open port after delay + if (Timeout( Handle->LastAction, Handle->ReopenDelay )) { + Open( Handle ); } } @@ -1636,12 +1742,22 @@ bool CSelectableCore::Process() if (Timeout( Handle->InStart, Handle->InTimeout )) { // Process Input - ProcessBuffer( Handle, true ); + ProcessInputBuffer( Handle, true ); // Reset timer ClearStartTime( &(Handle->InStart) ); } } + + // Check for auto close (but not on servers) + if ((Handle->State == csOpen) && (Handle->Type != ctServer) && Handle->AutoManage && !Handle->Persistent) + { + // Close port after timeout + if (Timeout( Handle->LastAction, Handle->CloseTimeout )) { + Close( Handle, true ); + } + } + Handle = Handle->Next; } return true; @@ -1649,15 +1765,16 @@ bool CSelectableCore::Process() //--------------------------------------------------------------------------- // Set serial port configuration parameters -bool CSelectableCore::SetSerialPortConfig( THandle * Handle ) +bool CSelectableCore::WriteSerialConfig( THandle * Handle ) { struct termios newtio; int flags = 0; - speed_t baud = 0; + speed_t inbaud = 0; + speed_t outbaud = 0; int mcs = 0; // Get Handle - if (!Handle || (Handle->Type != ctPort)) { + if (!Handle || (Handle->Type != ctSerial)) { return false; } @@ -1673,40 +1790,70 @@ bool CSelectableCore::SetSerialPortConfig( THandle * Handle ) return false; // Process the baud rate - switch (Handle->Baudrate) + switch (Handle->InBaudrate) { - case 921600: baud = B921600; break; - case 576000: baud = B576000; break; - case 460800: baud = B460800; break; - case 230400: baud = B230400; break; - //case 128000: _baud = B128000; break; - case 115200: baud = B115200; break; - //case 76800: _baud = B76800; break; - case 57600: baud = B57600; break; - case 38400: baud = B38400; break; - //case 28800: _baud = B28800; break; - case 19200: baud = B19200; break; - //case 14400: _baud = B14400; break; - case 9600: baud = B9600; break; - case 4800: baud = B4800; break; - case 2400: baud = B2400; break; - case 1800: baud = B1800; break; - case 1200: baud = B1200; break; - case 600: baud = B600; break; - case 300: baud = B300; break; - case 200: baud = B200; break; - case 150: baud = B150; break; - case 134: baud = B134; break; - case 110: baud = B110; break; - case 75: baud = B75; break; - case 50: baud = B50; break; + case 921600: inbaud = B921600; break; + case 576000: inbaud = B576000; break; + case 460800: inbaud = B460800; break; + case 230400: inbaud = B230400; break; + //case 128000: _inbaud = B128000; break; + case 115200: inbaud = B115200; break; + //case 76800: _inbaud = B76800; break; + case 57600: inbaud = B57600; break; + case 38400: inbaud = B38400; break; + //case 28800: _inbaud = B28800; break; + case 19200: inbaud = B19200; break; + //case 14400: _inbaud = B14400; break; + case 9600: inbaud = B9600; break; + case 4800: inbaud = B4800; break; + case 2400: inbaud = B2400; break; + case 1800: inbaud = B1800; break; + case 1200: inbaud = B1200; break; + case 600: inbaud = B600; break; + case 300: inbaud = B300; break; + case 200: inbaud = B200; break; + case 150: inbaud = B150; break; + case 134: inbaud = B134; break; + case 110: inbaud = B110; break; + case 75: inbaud = B75; break; + case 50: inbaud = B50; break; - default: baud = B9600; break; + default: inbaud = B9600; break; + } + switch (Handle->OutBaudrate) + { + case 921600: outbaud = B921600; break; + case 576000: outbaud = B576000; break; + case 460800: outbaud = B460800; break; + case 230400: outbaud = B230400; break; + //case 128000: _outbaud = B128000; break; + case 115200: outbaud = B115200; break; + //case 76800: _outbaud = B76800; break; + case 57600: outbaud = B57600; break; + case 38400: outbaud = B38400; break; + //case 28800: _outbaud = B28800; break; + case 19200: outbaud = B19200; break; + //case 14400: _outbaud = B14400; break; + case 9600: outbaud = B9600; break; + case 4800: outbaud = B4800; break; + case 2400: outbaud = B2400; break; + case 1800: outbaud = B1800; break; + case 1200: outbaud = B1200; break; + case 600: outbaud = B600; break; + case 300: outbaud = B300; break; + case 200: outbaud = B200; break; + case 150: outbaud = B150; break; + case 134: outbaud = B134; break; + case 110: outbaud = B110; break; + case 75: outbaud = B75; break; + case 50: outbaud = B50; break; + + default: outbaud = B9600; break; } // Set Baud rate - cfsetospeed( &newtio, (speed_t)baud ); - cfsetispeed( &newtio, (speed_t)baud ); + cfsetispeed( &newtio, (speed_t)inbaud ); + cfsetospeed( &newtio, (speed_t)outbaud ); // Generate Mark/Space parity if ((Handle->DataBits == 7) && ((Handle->Parity == MARK_PARITY) || (Handle->Parity == SPACE_PARITY))) @@ -1795,44 +1942,69 @@ bool CSelectableCore::SetSerialPortConfig( THandle * Handle ) //--------------------------------------------------------------------------- // Get serial port configuration parameters -bool CSelectableCore::GetSerialPortConfig( THandle * Handle ) +bool CSelectableCore::ReadSerialConfig( THandle * Handle ) { - int speed; + int inspeed; + int outspeed; unsigned char bits; struct termios getTermios; // Validate handle - if (!Handle || (Handle->Type != ctPort)) { + if (!Handle || (Handle->Type != ctSerial)) { return false; } // Get port setup tcgetattr( Handle->FD, &getTermios ); + inspeed = cfgetispeed( &getTermios ); + outspeed = cfgetospeed( &getTermios ); // Get Baud Rate - speed = cfgetispeed( &getTermios ); - switch (speed) + switch (inspeed) { - case B0 : Handle->Baudrate = 0; break; - case B50 : Handle->Baudrate = 50; break; - case B75 : Handle->Baudrate = 75; break; - case B110 : Handle->Baudrate = 110; break; - case B134 : Handle->Baudrate = 134; break; - case B150 : Handle->Baudrate = 150; break; - case B200 : Handle->Baudrate = 200; break; - case B300 : Handle->Baudrate = 300; break; - case B600 : Handle->Baudrate = 600; break; - case B1200 : Handle->Baudrate = 1200; break; - case B1800: Handle->Baudrate = 1800; break; - case B2400: Handle->Baudrate = 2400; break; - case B4800: Handle->Baudrate = 4800; break; - case B9600: Handle->Baudrate = 9600; break; - case B19200: Handle->Baudrate = 19200; break; - case B38400: Handle->Baudrate = 38400; break; - case B57600: Handle->Baudrate = 57600; break; - case B115200: Handle->Baudrate = 115200; break; - case B230400: Handle->Baudrate = 230400; break; - default: Handle->Baudrate = 999; break; + case B0 : Handle->InBaudrate = 0; break; + case B50 : Handle->InBaudrate = 50; break; + case B75 : Handle->InBaudrate = 75; break; + case B110 : Handle->InBaudrate = 110; break; + case B134 : Handle->InBaudrate = 134; break; + case B150 : Handle->InBaudrate = 150; break; + case B200 : Handle->InBaudrate = 200; break; + case B300 : Handle->InBaudrate = 300; break; + case B600 : Handle->InBaudrate = 600; break; + case B1200 : Handle->InBaudrate = 1200; break; + case B1800: Handle->InBaudrate = 1800; break; + case B2400: Handle->InBaudrate = 2400; break; + case B4800: Handle->InBaudrate = 4800; break; + case B9600: Handle->InBaudrate = 9600; break; + case B19200: Handle->InBaudrate = 19200; break; + case B38400: Handle->InBaudrate = 38400; break; + case B57600: Handle->InBaudrate = 57600; break; + case B115200: Handle->InBaudrate = 115200; break; + case B230400: Handle->InBaudrate = 230400; break; + default: Handle->InBaudrate = 0; break; + } + switch (outspeed) + { + case B0 : Handle->OutBaudrate = 0; break; + case B50 : Handle->OutBaudrate = 50; break; + case B75 : Handle->OutBaudrate = 75; break; + case B110 : Handle->OutBaudrate = 110; break; + case B134 : Handle->OutBaudrate = 134; break; + case B150 : Handle->OutBaudrate = 150; break; + case B200 : Handle->OutBaudrate = 200; break; + case B300 : Handle->OutBaudrate = 300; break; + case B600 : Handle->OutBaudrate = 600; break; + case B1200 : Handle->OutBaudrate = 1200; break; + case B1800: Handle->OutBaudrate = 1800; break; + case B2400: Handle->OutBaudrate = 2400; break; + case B4800: Handle->OutBaudrate = 4800; break; + case B9600: Handle->OutBaudrate = 9600; break; + case B19200: Handle->OutBaudrate = 19200; break; + case B38400: Handle->OutBaudrate = 38400; break; + case B57600: Handle->OutBaudrate = 57600; break; + case B115200: Handle->OutBaudrate = 115200; break; + case B230400: Handle->OutBaudrate = 230400; break; + default: Handle->OutBaudrate = 0 ; break; } // Get Data Bits diff --git a/SelectableCore.h b/SelectableCore.h index d77069e..43bf3ee 100644 --- a/SelectableCore.h +++ b/SelectableCore.h @@ -17,7 +17,7 @@ //--------------------------------------------------------------------------- // Types required for connections -typedef enum { ctNone = 0, ctPort = 1, ctForkPipe = 2, ctServer = 3, ctRemoteClient = 4, ctClient = 5 } EConnectType; +typedef enum { ctNone = 0, ctSerial = 1, ctLinePrinter = 2, ctServer = 3, ctRemoteClient = 4, ctClient = 5, ctForkPipe = 6 } EConnectType; const char ConnectTypeName[][15] = { "None", "Port", "ForkPipe", "Server", "RemoteClient", "Client" }; typedef enum { csNone = 0, csWaitingtoOpen = 1, csOpen = 2, csDataWaiting = 3, csClosed = 4, csFailed = 5 } EConnectState; @@ -76,8 +76,11 @@ struct SHandle { int FD; EConnectState State; - bool AutoManage; - bool Persistent; + bool AutoManage; + bool Persistent; + timeval LastAction; + long ReopenDelay; // millisecs + long CloseTimeout; // millisecs // Callback functions FHandleCallback StateCallback[ 6 ]; @@ -95,7 +98,8 @@ struct SHandle { bool KeepAlive; // Socket keep alive bool SerialConfig; - int Baudrate; + int InBaudrate; + int OutBaudrate; short DataBits; short Parity; short StopBits; @@ -114,10 +118,6 @@ struct SHandle { timeval InStart; long InTimeout; // millisecs - // Reopen Timer - timeval ReopenStart; - long ReopenDelay; // millisecs - // List / Tree TChannel * Channel; THandle * Parent; @@ -199,23 +199,27 @@ protected: } // Port Operations - virtual int OpenPort( THandle * Handle ); + int OpenSerialPort( THandle * Handle ); + bool WriteSerialConfig( THandle * Handle ); + bool ReadSerialConfig( THandle * Handle ); + + int OpenLinePrinterPort( THandle * Handle ); // ForkPipe Operations - virtual int OpenForkPipe( THandle * Handle ); + int OpenForkPipe( THandle * Handle ); // Socket Operations - bool ResolveAddress( THandle * Handle ); - virtual int OpenServerSocket( THandle * Handle ); - virtual int OpenRemoteClientSocket( THandle * Handle ); - virtual int OpenClientSocket( THandle * Handle ); + bool ResolveAddress( THandle * Handle ); + int OpenServerSocket( THandle * Handle ); + int OpenRemoteClientSocket( THandle * Handle ); + int OpenClientSocket( THandle * Handle ); // 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 ProcessBuffer( THandle * Handle, bool Force ); + virtual bool ProcessInputBuffer( THandle * Handle, bool Force ); // Specific operations bool BuildArgs( const char * ExecPath, int &Count, char * Args[] ); @@ -253,28 +257,29 @@ public: // 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 ReopenTime = 0 ); + 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 SetPortHandle( THandle * Handle, const char * FileName ); - bool SetPortHandleSerial( THandle * Handle, int Baudrate, short DataBits, short Parity, short StopBits, short FlowCtrl, int DataWait ); + 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 SetSocketHandle( THandle * Handle, EConnectType Type, const char * HostName, const char * PortName, bool KeepAlive ); bool ClearHandle( THandle * Handle ); // FD Operations virtual int Open( THandle * Handle ); - virtual bool Close( THandle * Handle, bool CloseChildren = 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 ) { return (Open( GetHandle( HandleName ))); }; - inline virtual bool Close( const char * HandleName, bool CloseChildren = false ) { return (Close( GetHandle( HandleName ), CloseChildren )); }; - inline virtual bool Close( int FD, bool CloseChildren = false ) { return (Close( GetHandle( FD ), CloseChildren )); }; + 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 ))); }; @@ -282,9 +287,6 @@ public: inline virtual bool Write( const char * HandleName ) { return (Write( GetHandle( HandleName ))); }; inline virtual bool Write( int FD ) { return (Write( GetHandle( FD ))); }; - bool SetSerialPortConfig( THandle * Handle ); - bool GetSerialPortConfig( THandle * Handle ); - // Info inline EConnectType GetType( const char * HandleName ) { THandle * Handle = GetHandle( HandleName ); @@ -297,7 +299,7 @@ public: // Function Interface virtual int Input( const char * ChannelName, const char * Buffer, int BufLen = -1 ); - int InputHandle( THandle * Handle, const char * Data, int Len ); + int OutputHandle( THandle * Handle, const char * Data, int Len ); virtual bool Process(); }; diff --git a/WatchdogCore.cpp b/WatchdogCore.cpp index 346fc51..8e47b3c 100644 --- a/WatchdogCore.cpp +++ b/WatchdogCore.cpp @@ -49,7 +49,7 @@ bool CWatchdogCore::LoadConfigData() // Call Previous load config CSelectableCore::LoadConfigData(); - // Set Auto Mange + // Set specific parameters SetInterval( DataTree->GetInt( ConfigMember, "Parameters/PingInterval", 500, true )); return true; @@ -83,7 +83,7 @@ bool CWatchdogCore::Process() if (Timeout( PingTimer, PingInterval )) { // Send command - InputHandle( Ping, Protocol->GetCommandStr(), Protocol->GetCommandLen() ); + OutputHandle( Ping, Protocol->GetCommandStr(), Protocol->GetCommandLen() ); // Reset timer SetStartTime( &PingTimer );