Important Updates:

- FunctionCore:
  - Output() returns largest no of bytes written to linked input
- SelectableCore:
  - Auto-manage:
    - Add AutoManage param -> Persistent
    - Will automatic open port if written to when Auto-Manage enabled
    - Will keep port open (re-open if closed) if Persistent = true
  - DNS resolve:
    - Set AddressFailed if port could not open/bind
    - Only use next resolved address if current address failed
This commit is contained in:
Charl Wentzel
2017-11-18 17:06:32 +02:00
parent abba077ed0
commit 7ef3d71af9
3 changed files with 74 additions and 14 deletions

View File

@@ -470,6 +470,8 @@ int CFunctionCore::Output( const char * ChannelName, const char * Data, int Len
int CFunctionCore::Output( const TChannel * Channel, 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 // Validate
if (!Channel || !Data) { if (!Channel || !Data) {
@@ -491,12 +493,13 @@ int CFunctionCore::Output( const TChannel * Channel, const char * Data, int Len
} }
OutChannel = Channel->FirstOutput; OutChannel = Channel->FirstOutput;
while (OutChannel) { 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; OutChannel = OutChannel->Next;
} }
// Return processed bytes // Return processed bytes
return Len; return OutLen;
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View File

@@ -129,6 +129,7 @@ bool CSelectableCore::LoadConfigData()
// Set Auto Mange // Set Auto Mange
SetAutoManage( Handle, DataTree->GetBool( TempMember, "AutoManage/Enabled", true, true ), 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 ) );
// Input buffer // 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 // Validate
if (!Handle) { if (!Handle) {
@@ -386,6 +387,7 @@ bool CSelectableCore::SetAutoManage( THandle * Handle, bool AutoManage, int Reop
// Set params // Set params
Handle->AutoManage = AutoManage; Handle->AutoManage = AutoManage;
Handle->Persistent = Persistent;
Handle->ReopenDelay = ReopenDelay; Handle->ReopenDelay = ReopenDelay;
return true; return true;
} }
@@ -574,13 +576,23 @@ bool CSelectableCore::ResolveAddress( THandle * Handle )
struct addrinfo hints; struct addrinfo hints;
int result; int result;
// Check if more addresses // Check if resolved address available
if (Handle->AddressInfo) if (Handle->AddressInfo)
{
// Return if address still valid
if (!Handle->AddressFailed)
return true;
// Get next address
Handle->AddressInfo = Handle->AddressInfo->ai_next; 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" )) 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; Handle->AddressInfo = Handle->AddressInfo->ai_next;
// Return address // Check valid address
if (Handle->AddressInfo) { if (Handle->AddressInfo) {
if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Use next resolved Address [%s:%s]->[%s:%u]", if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Use next resolved Address [%s:%s]->[%s:%u]",
Name, Handle->Name, Handle->HostName, Handle->PortName, Name, Handle->Name, Handle->HostName, Handle->PortName,
@@ -712,6 +724,7 @@ int CSelectableCore::OpenServerSocket( THandle * Handle )
close( Handle->FD ); close( Handle->FD );
Handle->FD = -1; Handle->FD = -1;
ChangeState( Handle, csFailed ); ChangeState( Handle, csFailed );
Handle->AddressFailed = true;
return -1; return -1;
}; };
@@ -725,6 +738,7 @@ int CSelectableCore::OpenServerSocket( THandle * Handle )
close( Handle->FD ); close( Handle->FD );
Handle->FD = -1; Handle->FD = -1;
ChangeState( Handle, csFailed ); ChangeState( Handle, csFailed );
Handle->AddressFailed = true;
return -1; return -1;
}; };
@@ -938,6 +952,7 @@ int CSelectableCore::OpenClientSocket( THandle * Handle )
// Close socket // Close socket
close( Handle->FD ); close( Handle->FD );
ChangeState( Handle, csFailed ); ChangeState( Handle, csFailed );
Handle->AddressFailed = true;
// Start re-open timer // Start re-open timer
SetStartTime( &(Handle->ReopenStart) ); SetStartTime( &(Handle->ReopenStart) );
@@ -978,6 +993,11 @@ int CSelectableCore::Open( THandle * Handle )
default: default:
FD = -1; FD = -1;
} }
// Clear timer
if ((Handle->State == csOpen) || (Handle->State == csWaitingtoOpen)) {
ClearStartTime( &Handle->ReopenStart );
}
return FD; return FD;
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@@ -1149,9 +1169,26 @@ bool CSelectableCore::Write( THandle * Handle )
int BytesWritten = 0; int BytesWritten = 0;
// Validate // Validate
if (!Handle || (Handle->State == csNone) || (Handle->State == csFailed) || (Handle->State == csClosed)) { 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; return false;
} }
}
// Log Ready for Write Event // Log Ready for Write Event
if (Log) Log->Message( LogLevel, dlHigh, "%s: Handle '%s' - Write Event", Name, Handle->Name ); if (Log) Log->Message( LogLevel, dlHigh, "%s: Handle '%s' - Write Event", Name, Handle->Name );
@@ -1348,11 +1385,28 @@ 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 ); if (Log) Log->Message( LogLevel, dlHigh, "%s: Channel '%s' - Input rejected, Channel input disabled", Name, ChannelName );
return 0; return 0;
} }
else if (Handle->State != csOpen) { else if ((Handle->State != csOpen))
// Handle is not open {
// 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 ); if (Log) Log->Message( LogLevel, dlHigh, "%s: Channel '%s' - Input rejected, Handle not Open", Name, ChannelName );
return 0; return 0;
} }
}
}
// Log event // Log event
if (Log) Log->Output( LogLevel, dlHigh, LogOutput, Data, Len, "%s: Channel '%s' - IN:", Name, ChannelName ); if (Log) Log->Output( LogLevel, dlHigh, LogOutput, Data, Len, "%s: Channel '%s' - IN:", Name, ChannelName );
@@ -1434,7 +1488,7 @@ bool CSelectableCore::Process()
while (Handle) while (Handle)
{ {
// Auto manage handles // 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 // Check duration since last PortIn
if (Timeout( Handle->ReopenStart, Handle->ReopenDelay )) if (Timeout( Handle->ReopenStart, Handle->ReopenDelay ))

View File

@@ -75,7 +75,9 @@ struct SHandle {
// State // State
int FD; int FD;
EConnectState State; EConnectState State;
bool AutoManage; bool AutoManage;
bool Persistent;
// Callback functions // Callback functions
FHandleCallback StateCallback[ 6 ]; FHandleCallback StateCallback[ 6 ];
@@ -89,6 +91,7 @@ struct SHandle {
char * PortName; // Socket port no or protocol, e.g. "80" or "HTTP" 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 * AddressList; // List of resolved IP Addresses for host name
struct addrinfo * AddressInfo; // Current selected IP Address struct addrinfo * AddressInfo; // Current selected IP Address
bool AddressFailed; // Indicate failure to connect to address
bool KeepAlive; // Socket keep alive bool KeepAlive; // Socket keep alive
// Buffers // Buffers
@@ -241,7 +244,7 @@ public:
THandle * CreateHandle( const char * HandleName, bool CreateChannel ); THandle * CreateHandle( const char * HandleName, bool CreateChannel );
bool SetCallback( THandle * Handle, EConnectState pState, FHandleCallback pCallback ); 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 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 ); bool SerialConfig( THandle * Handle, int Baud, short DataBits, short StopBits, short Parity, short FlowCtrl, int Wait );