diff --git a/FunctionCore.cpp b/FunctionCore.cpp index e9f336f..60aca62 100644 --- a/FunctionCore.cpp +++ b/FunctionCore.cpp @@ -469,7 +469,9 @@ int CFunctionCore::Output( const char * ChannelName, const char * Data, int Len int CFunctionCore::Output( const TChannel * Channel, const char * Data, int Len ) { - TChannelLink * OutChannel = NULL; + TChannelLink * OutChannel = NULL; + int TempLen = 0; + int OutLen = 0; // Validate if (!Channel || !Data) { @@ -491,12 +493,13 @@ int CFunctionCore::Output( const TChannel * Channel, const char * Data, int Len } OutChannel = Channel->FirstOutput; while (OutChannel) { - OutChannel->Function->Input( OutChannel->Name, Data, Len ); + TempLen = OutChannel->Function->Input( OutChannel->Name, Data, Len ); + OutLen = (TempLen > OutLen)? TempLen : OutLen; OutChannel = OutChannel->Next; } // Return processed bytes - return Len; + return OutLen; } //--------------------------------------------------------------------------- diff --git a/SelectableCore.cpp b/SelectableCore.cpp index 83a5265..e4cea7b 100644 --- a/SelectableCore.cpp +++ b/SelectableCore.cpp @@ -129,6 +129,7 @@ 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 ) ); // Input buffer @@ -377,7 +378,7 @@ bool CSelectableCore::SetCallback( THandle * Handle, EConnectState pState, FHand } //--------------------------------------------------------------------------- -bool CSelectableCore::SetAutoManage( THandle * Handle, bool AutoManage, int ReopenDelay ) +bool CSelectableCore::SetAutoManage( THandle * Handle, bool AutoManage, bool Persistent, int ReopenDelay ) { // Validate if (!Handle) { @@ -386,6 +387,7 @@ bool CSelectableCore::SetAutoManage( THandle * Handle, bool AutoManage, int Reop // Set params Handle->AutoManage = AutoManage; + Handle->Persistent = Persistent; Handle->ReopenDelay = ReopenDelay; return true; } @@ -574,13 +576,23 @@ bool CSelectableCore::ResolveAddress( THandle * Handle ) struct addrinfo hints; int result; - // Check if more addresses + // Check if resolved address available if (Handle->AddressInfo) + { + // Return if address still valid + if (!Handle->AddressFailed) + return true; + + // Get next address Handle->AddressInfo = Handle->AddressInfo->ai_next; + Handle->AddressFailed = false; + } + + // Dismiss invalid "0.0.0.0" address if (Handle->AddressInfo && !strcmp( inet_ntoa(((struct sockaddr_in *)Handle->AddressInfo->ai_addr)->sin_addr), "0.0.0.0" )) Handle->AddressInfo = Handle->AddressInfo->ai_next; - // Return address + // Check valid address if (Handle->AddressInfo) { if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Use next resolved Address [%s:%s]->[%s:%u]", Name, Handle->Name, Handle->HostName, Handle->PortName, @@ -712,6 +724,7 @@ int CSelectableCore::OpenServerSocket( THandle * Handle ) close( Handle->FD ); Handle->FD = -1; ChangeState( Handle, csFailed ); + Handle->AddressFailed = true; return -1; }; @@ -725,6 +738,7 @@ int CSelectableCore::OpenServerSocket( THandle * Handle ) close( Handle->FD ); Handle->FD = -1; ChangeState( Handle, csFailed ); + Handle->AddressFailed = true; return -1; }; @@ -938,6 +952,7 @@ int CSelectableCore::OpenClientSocket( THandle * Handle ) // Close socket close( Handle->FD ); ChangeState( Handle, csFailed ); + Handle->AddressFailed = true; // Start re-open timer SetStartTime( &(Handle->ReopenStart) ); @@ -978,6 +993,11 @@ int CSelectableCore::Open( THandle * Handle ) default: FD = -1; } + + // Clear timer + if ((Handle->State == csOpen) || (Handle->State == csWaitingtoOpen)) { + ClearStartTime( &Handle->ReopenStart ); + } return FD; }; //--------------------------------------------------------------------------- @@ -1149,8 +1169,25 @@ bool CSelectableCore::Write( THandle * Handle ) int BytesWritten = 0; // Validate - if (!Handle || (Handle->State == csNone) || (Handle->State == csFailed) || (Handle->State == csClosed)) { - return false; + if (!Handle || (Handle->State == csNone) || (Handle->State == csFailed) || (Handle->State == csClosed)) + { + if (Handle->AutoManage) + { + // Check duration since last PortIn + if (Timeout( Handle->ReopenStart, Handle->ReopenDelay )) + { + // Complete opening process + if (Open( Handle ) == -1) { + // Reset Timer + SetStartTime( &(Handle->ReopenStart) ); + } + } + } + else + { + // Must be opened manually + return false; + } } // Log Ready for Write Event @@ -1348,10 +1385,27 @@ int CSelectableCore::Input( const char * ChannelName, const char * Data, int Len if (Log) Log->Message( LogLevel, dlHigh, "%s: Channel '%s' - Input rejected, Channel input disabled", Name, ChannelName ); return 0; } - else if (Handle->State != csOpen) { - // Handle is not open - if (Log) Log->Message( LogLevel, dlHigh, "%s: Channel '%s' - Input rejected, Handle not Open", Name, ChannelName ); - return 0; + else if ((Handle->State != csOpen)) + { + // Check if auto-managed handle + if (!Handle->AutoManage) + { + // Handle is not open or auto-managed + if (Log) Log->Message( LogLevel, dlHigh, "%s: Channel '%s' - Input rejected, Handle not Open (not auto-managed)", Name, ChannelName ); + return 0; + } + else + { + // Try to Open handle + if (Log) Log->Message( LogLevel, dlHigh, "%s: Channel '%s' - Input held, Trying to open (auto-managed) Handle", Name, ChannelName ); + Open( Handle ); + + // Check if Handle is open + if (Handle->State != csOpen) { + if (Log) Log->Message( LogLevel, dlHigh, "%s: Channel '%s' - Input rejected, Handle not Open", Name, ChannelName ); + return 0; + } + } } // Log event @@ -1434,7 +1488,7 @@ bool CSelectableCore::Process() while (Handle) { // Auto manage handles - if (Handle->AutoManage && ((Handle->State == csNone) || (Handle->State == csFailed) || (Handle->State == csClosed))) + if (Handle->AutoManage && Handle->Persistent && ((Handle->State == csNone) || (Handle->State == csFailed) || (Handle->State == csClosed))) { // Check duration since last PortIn if (Timeout( Handle->ReopenStart, Handle->ReopenDelay )) diff --git a/SelectableCore.h b/SelectableCore.h index f1f6448..80f1d9e 100644 --- a/SelectableCore.h +++ b/SelectableCore.h @@ -75,7 +75,9 @@ struct SHandle { // State int FD; EConnectState State; + bool AutoManage; + bool Persistent; // Callback functions FHandleCallback StateCallback[ 6 ]; @@ -89,6 +91,7 @@ struct SHandle { 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 bool KeepAlive; // Socket keep alive // Buffers @@ -241,7 +244,7 @@ public: THandle * CreateHandle( const char * HandleName, bool CreateChannel ); bool SetCallback( THandle * Handle, EConnectState pState, FHandleCallback pCallback ); - bool SetAutoManage( THandle * Handle, bool AutoManage, int ReopenTime = 0 ); + bool SetAutoManage( THandle * Handle, bool AutoManage, bool Persistent, int ReopenTime = 0 ); bool SetBuffers( THandle * Handle, int InBufSize, int OutBufSize, int InTimeout, const char * InMarker, int InMarkerLen ); bool SerialConfig( THandle * Handle, int Baud, short DataBits, short StopBits, short Parity, short FlowCtrl, int Wait );