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 )
|
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;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -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,8 +1169,25 @@ 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))
|
||||||
return false;
|
{
|
||||||
|
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
|
// 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 );
|
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
|
{
|
||||||
if (Log) Log->Message( LogLevel, dlHigh, "%s: Channel '%s' - Input rejected, Handle not Open", Name, ChannelName );
|
// Check if auto-managed handle
|
||||||
return 0;
|
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
|
// Log event
|
||||||
@@ -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 ))
|
||||||
|
|||||||
@@ -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 );
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user