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:
@@ -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;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -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 ))
|
||||
|
||||
@@ -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 );
|
||||
|
||||
|
||||
Reference in New Issue
Block a user