Major Update:
- FunctionCore
- Replace Channel->Ready with Channel->State (off/waiting/ready)
- Add Function reference to Handle
- SelectableBare/Core:
- Implement async address resolve with event handling
- Create ResolveHandler() signal handler (friend) function
- Change Create/Remove/DestroyHandle() methods to virtual methods
- Move socket specific code to SelectableCore
- Rename ChangeState() to virtual HandleState()
- Move ClearHandle() from SelectableBare -> SelectableCore
- Implement new/delete from THandle
- Set max TCP SYN count on connect
This commit is contained in:
@@ -68,19 +68,19 @@ bool CDeviceCore::Init( CDataMember * FunctionConfig )
|
|||||||
|
|
||||||
// Add Channels
|
// Add Channels
|
||||||
if (!(CmdChannel = GetChannel( "Command" )))
|
if (!(CmdChannel = GetChannel( "Command" )))
|
||||||
CmdChannel = AddChannel( "Command", true );
|
CmdChannel = AddChannel( "Command", CH_ready );
|
||||||
else
|
else
|
||||||
SetChannelState( CmdChannel, true );
|
SetChannelState( CmdChannel, CH_ready );
|
||||||
|
|
||||||
if (!(DeviceChannel = GetChannel( "Device" )))
|
if (!(DeviceChannel = GetChannel( "Device" )))
|
||||||
DeviceChannel = AddChannel( "Device", true );
|
DeviceChannel = AddChannel( "Device", CH_ready );
|
||||||
else
|
else
|
||||||
SetChannelState( DeviceChannel, true );
|
SetChannelState( DeviceChannel, CH_ready );
|
||||||
|
|
||||||
if (!(EventChannel = GetChannel( "Event" )))
|
if (!(EventChannel = GetChannel( "Event" )))
|
||||||
EventChannel = AddChannel( "Event", true );
|
EventChannel = AddChannel( "Event", CH_ready );
|
||||||
else
|
else
|
||||||
SetChannelState( EventChannel, true );
|
SetChannelState( EventChannel, CH_ready );
|
||||||
|
|
||||||
// Load Polling configuration
|
// Load Polling configuration
|
||||||
PollConfig = Config->GetChild( "Polling", true );
|
PollConfig = Config->GetChild( "Polling", true );
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ TFileHandle * CFileCore::AddFile( const char * Name, const char * Path, bool Ap
|
|||||||
|
|
||||||
// Create Channel if necessary
|
// Create Channel if necessary
|
||||||
if (CreateChannel) {
|
if (CreateChannel) {
|
||||||
AddChannel( Name, false );
|
AddChannel( Name, CH_ready );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set Parameters
|
// Set Parameters
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ bool CFunctionCore::Init( CDataMember * FunctionConfig )
|
|||||||
// Load Channels
|
// Load Channels
|
||||||
ChannelConfig = FunctionConfig->GetChFirstChild( "Channels", true );
|
ChannelConfig = FunctionConfig->GetChFirstChild( "Channels", true );
|
||||||
while (ChannelConfig) {
|
while (ChannelConfig) {
|
||||||
AddChannel( ChannelConfig->GetName(), false );
|
AddChannel( ChannelConfig->GetName(), CH_off );
|
||||||
ChannelConfig = ChannelConfig->GetNextPeer();
|
ChannelConfig = ChannelConfig->GetNextPeer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,7 +166,7 @@ bool CFunctionCore::SetLogLevel( EDebugLevel pDebugLevel )
|
|||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
TChannel * CFunctionCore::AddChannel( const char * ChannelName, bool Ready )
|
TChannel * CFunctionCore::AddChannel( const char * ChannelName, const EChannelState State )
|
||||||
{
|
{
|
||||||
TChannel ** Channel = NULL;
|
TChannel ** Channel = NULL;
|
||||||
|
|
||||||
@@ -190,17 +190,17 @@ TChannel * CFunctionCore::AddChannel( const char * ChannelName, bool Ready )
|
|||||||
(*Channel)->Name = strdup( ChannelName );
|
(*Channel)->Name = strdup( ChannelName );
|
||||||
(*Channel)->Ref = (char*)malloc( strlen(Name)+strlen(ChannelName)+2 );
|
(*Channel)->Ref = (char*)malloc( strlen(Name)+strlen(ChannelName)+2 );
|
||||||
sprintf( (*Channel)->Ref, "%s/%s", Name, ChannelName );
|
sprintf( (*Channel)->Ref, "%s/%s", Name, ChannelName );
|
||||||
(*Channel)->Ready = Ready;
|
(*Channel)->State = State;
|
||||||
|
|
||||||
// Log Event
|
// Log Event
|
||||||
if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Channel '%s' - Created, Ref:'%s', Ready:%s",
|
if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Channel '%s' - Created, Ref:'%s', State:%s",
|
||||||
ProcessName, Name, ChannelName, (*Channel)->Ref, (((*Channel)->Ready)? "Yes" : "No") );
|
ProcessName, Name, ChannelName, (*Channel)->Ref, ChannelStateName[(*Channel)->State] );
|
||||||
}
|
}
|
||||||
return *Channel;
|
return *Channel;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CFunctionCore::SetChannelState( TChannel * Channel, const bool Ready )
|
bool CFunctionCore::SetChannelState( TChannel * Channel, const EChannelState State )
|
||||||
{
|
{
|
||||||
TChannelLink * LinkChannel;
|
TChannelLink * LinkChannel;
|
||||||
|
|
||||||
@@ -209,14 +209,14 @@ bool CFunctionCore::SetChannelState( TChannel * Channel, const bool Ready )
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Update state
|
// Update state
|
||||||
Channel->Ready = Ready;
|
Channel->State = State;
|
||||||
if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Update Channel '%s' - Ready:%s",
|
if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Update Channel '%s' - State:%s",
|
||||||
ProcessName, Name, Channel->Name, ((Ready)? "Yes" : "No") );
|
ProcessName, Name, Channel->Name, ChannelStateName[State] );
|
||||||
|
|
||||||
// Update linked channels
|
// Update linked channels
|
||||||
LinkChannel = Channel->FirstLink;
|
LinkChannel = Channel->FirstLink;
|
||||||
while (LinkChannel) {
|
while (LinkChannel) {
|
||||||
LinkChannel->Function->ChannelStateEvent( LinkChannel->Channel, Channel->Ref, Ready );
|
LinkChannel->Function->ChannelStateEvent( LinkChannel->Channel, Channel->Ref, State );
|
||||||
LinkChannel = LinkChannel->Next;
|
LinkChannel = LinkChannel->Next;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,7 +224,7 @@ bool CFunctionCore::SetChannelState( TChannel * Channel, const bool Ready )
|
|||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CFunctionCore::ChannelStateEvent( TChannel * Channel, const char * SourceRef, const bool Ready )
|
bool CFunctionCore::ChannelStateEvent( TChannel * Channel, const char * SourceRef, const EChannelState State )
|
||||||
{
|
{
|
||||||
TChannelLink * LinkChannel;
|
TChannelLink * LinkChannel;
|
||||||
|
|
||||||
@@ -233,8 +233,8 @@ bool CFunctionCore::ChannelStateEvent( TChannel * Channel, const char * SourceRe
|
|||||||
if (!(LinkChannel = GetLinkChannel( Channel, SourceRef )))
|
if (!(LinkChannel = GetLinkChannel( Channel, SourceRef )))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Update Link Channel '%s'-->'%s' - Ready:%s",
|
if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Update Link Channel '%s'-->'%s' - State:%s",
|
||||||
ProcessName, Name, Channel->Name, LinkChannel->Channel->Ref, ((Ready)? "Yes" : "No") );
|
ProcessName, Name, Channel->Name, LinkChannel->Channel->Ref, ChannelStateName[State] );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -308,9 +308,9 @@ int CFunctionCore::Input( const char * ChannelName, const char * SourceRef, cons
|
|||||||
ProcessName, Name, ((SourceRef && *SourceRef)? SourceRef : "(Any)"), ChannelName );
|
ProcessName, Name, ((SourceRef && *SourceRef)? SourceRef : "(Any)"), ChannelName );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (!Channel->Ready) {
|
else if (!Channel->State) {
|
||||||
if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Channel '%s'->'%s' - Input rejected, Channel not Ready",
|
if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Channel '%s'->'%s' - Input rejected, Channel %s",
|
||||||
ProcessName, Name, ((SourceRef && *SourceRef)? SourceRef : "(Any)"), ChannelName );
|
ProcessName, Name, ((SourceRef && *SourceRef)? SourceRef : "(Any)"), ChannelName, ChannelStateName[Channel->State] );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,12 @@
|
|||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Enumarate Types
|
||||||
|
typedef enum { CH_off = 0, CH_wait = 1, CH_ready = 2 } EChannelState;
|
||||||
|
const char ChannelStateName[][15] = { "Off", "Waiting", "Ready" };
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
// Preview
|
// Preview
|
||||||
typedef struct SChannel TChannel;
|
typedef struct SChannel TChannel;
|
||||||
typedef struct SChannelLink TChannelLink;
|
typedef struct SChannelLink TChannelLink;
|
||||||
@@ -32,7 +38,7 @@ struct SChannel
|
|||||||
|
|
||||||
TChannelLink * FirstLink = NULL; // List of channels linked for input/output
|
TChannelLink * FirstLink = NULL; // List of channels linked for input/output
|
||||||
|
|
||||||
bool Ready = false; // Channel ready to receive input
|
EChannelState State = CH_off; // Channel ready to receive input
|
||||||
|
|
||||||
TChannel * Next = NULL;
|
TChannel * Next = NULL;
|
||||||
};
|
};
|
||||||
@@ -112,10 +118,10 @@ public:
|
|||||||
inline const char * GetType() { return Type; };
|
inline const char * GetType() { return Type; };
|
||||||
|
|
||||||
// Manage Channels
|
// Manage Channels
|
||||||
virtual TChannel * AddChannel( const char * ChannelName, const bool Ready );
|
virtual TChannel * AddChannel( const char * ChannelName, const EChannelState State );
|
||||||
|
|
||||||
virtual bool SetChannelState( TChannel * Channel, const bool Ready );
|
virtual bool SetChannelState( TChannel * Channel, const EChannelState State );
|
||||||
virtual bool ChannelStateEvent( TChannel * Channel, const char * SourceRef, const bool Ready );
|
virtual bool ChannelStateEvent( TChannel * Channel, const char * SourceRef, const EChannelState State );
|
||||||
|
|
||||||
// Pushing Data Output -> Input
|
// Pushing Data Output -> Input
|
||||||
virtual int Output( const char * ChannelName, const char * TargetRef, const bool SourceRef, const char * Data, int Len = -1 );
|
virtual int Output( const char * ChannelName, const char * TargetRef, const bool SourceRef, const char * Data, int Len = -1 );
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ THandle * CSelectableBare::CreateHandle( const char * HandleName, bool CreateCh
|
|||||||
if (!*Handle)
|
if (!*Handle)
|
||||||
{
|
{
|
||||||
// Create File handle at end of list
|
// Create File handle at end of list
|
||||||
*Handle = (THandle*)calloc( 1, sizeof(THandle) );
|
*Handle = new THandle;
|
||||||
|
|
||||||
// Set name
|
// Set name
|
||||||
if (HandleName) {
|
if (HandleName) {
|
||||||
@@ -103,6 +103,7 @@ THandle * CSelectableBare::CreateHandle( const char * HandleName, bool CreateCh
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set File Descriptor
|
// Set File Descriptor
|
||||||
|
(*Handle)->Function = this;
|
||||||
(*Handle)->FD = -1;
|
(*Handle)->FD = -1;
|
||||||
|
|
||||||
// Log event
|
// Log event
|
||||||
@@ -112,7 +113,7 @@ THandle * CSelectableBare::CreateHandle( const char * HandleName, bool CreateCh
|
|||||||
|
|
||||||
// Create Matching Channel
|
// Create Matching Channel
|
||||||
if (CreateChannel) {
|
if (CreateChannel) {
|
||||||
(*Handle)->Channel = AddChannel( HandleName, false );
|
(*Handle)->Channel = AddChannel( HandleName, CH_off );
|
||||||
}
|
}
|
||||||
|
|
||||||
return *Handle;
|
return *Handle;
|
||||||
@@ -159,68 +160,16 @@ bool CSelectableBare::DestroyHandle( THandle * Handle )
|
|||||||
free( Handle->Name );
|
free( Handle->Name );
|
||||||
if (Handle->Path)
|
if (Handle->Path)
|
||||||
free( Handle->Path );
|
free( Handle->Path );
|
||||||
if (Handle->HostName)
|
|
||||||
free( Handle->HostName );
|
|
||||||
if (Handle->PortName)
|
|
||||||
free( Handle->PortName );
|
|
||||||
if (Handle->AddressInfo)
|
|
||||||
freeaddrinfo( Handle->AddressList );
|
|
||||||
|
|
||||||
// Destroy Buffers
|
|
||||||
if (Handle->InBuffer)
|
|
||||||
delete Handle->InBuffer;
|
|
||||||
if (Handle->OutBuffer)
|
|
||||||
delete Handle->OutBuffer;
|
|
||||||
|
|
||||||
// Clear Input Markers
|
|
||||||
if (Handle->InMarker)
|
|
||||||
free( Handle->InMarker );
|
|
||||||
|
|
||||||
// Destroy Pointer
|
// Destroy Pointer
|
||||||
free( Handle );
|
delete Handle;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CSelectableBare::ClearHandle( THandle * Handle )
|
bool CSelectableBare::HandleState( THandle * Handle, EConnectState State )
|
||||||
{
|
{
|
||||||
// Validate
|
EChannelState ChannelState = CH_off;
|
||||||
if (!Handle) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset Type related parameters
|
|
||||||
if (Handle->Path) {
|
|
||||||
free( Handle->Path );
|
|
||||||
Handle->Path = NULL;
|
|
||||||
}
|
|
||||||
if (Handle->HostName) {
|
|
||||||
free( Handle->HostName );
|
|
||||||
Handle->HostName = NULL;
|
|
||||||
}
|
|
||||||
if (Handle->PortName) {
|
|
||||||
free( Handle->PortName );
|
|
||||||
Handle->PortName = NULL;
|
|
||||||
}
|
|
||||||
if (Handle->AddressList) {
|
|
||||||
freeaddrinfo( Handle->AddressList );
|
|
||||||
Handle->AddressList = NULL;
|
|
||||||
Handle->AddressInfo = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset Parameters
|
|
||||||
Handle->Type = ctNone;
|
|
||||||
|
|
||||||
// Log event
|
|
||||||
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Set as None",
|
|
||||||
ProcessName, Name, Handle->Name );
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
bool CSelectableBare::ChangeState( THandle * Handle, EConnectState State )
|
|
||||||
{
|
|
||||||
bool Ready;
|
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
if (!Handle || (Handle->State == State))
|
if (!Handle || (Handle->State == State))
|
||||||
@@ -235,9 +184,14 @@ bool CSelectableBare::ChangeState( THandle * Handle, EConnectState State )
|
|||||||
|
|
||||||
// Update Channel
|
// Update Channel
|
||||||
if (Handle->Channel) {
|
if (Handle->Channel) {
|
||||||
Ready = ((Handle->State == csOpen) || (Handle->State == csDataWaiting));
|
if ((Handle->State == csOpenRequest) || (Handle->State == csWaitingtoOpen))
|
||||||
if (Handle->Channel->Ready != Ready)
|
ChannelState = CH_wait;
|
||||||
SetChannelState( Handle->Channel, Ready );
|
else if ((Handle->State == csOpen) || (Handle->State == csDataWaiting))
|
||||||
|
ChannelState = CH_ready;
|
||||||
|
else
|
||||||
|
ChannelState = CH_off;
|
||||||
|
if (Handle->Channel->State != ChannelState)
|
||||||
|
SetChannelState( Handle->Channel, ChannelState );
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -421,7 +375,7 @@ int CSelectableBare::Open( THandle * Handle, bool DelayResolve )
|
|||||||
SetStartTime( &Handle->LastAction );
|
SetStartTime( &Handle->LastAction );
|
||||||
|
|
||||||
// Set state
|
// Set state
|
||||||
ChangeState( Handle, csOpen );
|
HandleState( Handle, csOpen );
|
||||||
return (NewHandle)? NewHandle->FD : -1;
|
return (NewHandle)? NewHandle->FD : -1;
|
||||||
};
|
};
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -459,7 +413,7 @@ bool CSelectableBare::Close( THandle * Handle, bool QuickReopen )
|
|||||||
ProcessName, Name, Handle->Name, ((Fail)? "failed" : "closed") );
|
ProcessName, Name, Handle->Name, ((Fail)? "failed" : "closed") );
|
||||||
|
|
||||||
// Set State
|
// Set State
|
||||||
ChangeState( Handle, ((Fail)? csFailed : csClosed) );
|
HandleState( Handle, ((Fail)? csFailed : csClosed) );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -723,7 +677,7 @@ int CSelectableBare::Input( const char * ChannelName, const char * SourceRef, co
|
|||||||
ProcessName, Name, ((SourceRef && *SourceRef)? SourceRef : "(Any)"), ChannelName );
|
ProcessName, Name, ((SourceRef && *SourceRef)? SourceRef : "(Any)"), ChannelName );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (!Channel->Ready) {
|
else if (Channel->State != CH_ready) {
|
||||||
// Channel disabled
|
// Channel disabled
|
||||||
if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Channel '%s'->'%s' - Input rejected, Channel not Ready",
|
if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Channel '%s'->'%s' - Input rejected, Channel not Ready",
|
||||||
ProcessName, Name, ((SourceRef && *SourceRef)? SourceRef : "(Any)"), ChannelName );
|
ProcessName, Name, ((SourceRef && *SourceRef)? SourceRef : "(Any)"), ChannelName );
|
||||||
|
|||||||
@@ -40,13 +40,62 @@ CFunctionCore * NewSelectableCore( const char * Name ) {
|
|||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Resolve action handlder
|
||||||
|
void ResolveHandler( int Signal, siginfo_t * SignalInfo, void * Context )
|
||||||
|
{
|
||||||
|
TResolveReq * ResolveReq;
|
||||||
|
THandle * Handle;
|
||||||
|
|
||||||
|
// Validate signal
|
||||||
|
if ((SignalInfo->si_code != SI_ASYNCNL) ||
|
||||||
|
(SignalInfo->si_signo != SIGRTMIN))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Get Handle & Request
|
||||||
|
ResolveReq = (TResolveReq*)(SignalInfo->si_value.sival_ptr);
|
||||||
|
Handle = ResolveReq->Handle;
|
||||||
|
|
||||||
|
((CSelectableCore*)Handle->Function)->HandleResolve( Handle );
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
CSelectableCore::CSelectableCore( const char * pName, const char * pType ) : CSelectableBare( pName, pType )
|
CSelectableCore::CSelectableCore( const char * pName, const char * pType ) : CSelectableBare( pName, pType )
|
||||||
{
|
{
|
||||||
|
// Configure resolve signal handler
|
||||||
|
ResolveAct.sa_sigaction = &ResolveHandler;
|
||||||
|
sigemptyset( &ResolveAct.sa_mask );
|
||||||
|
ResolveAct.sa_flags = SA_SIGINFO;
|
||||||
|
|
||||||
|
sigaction( SIGRTMIN, &ResolveAct, NULL );
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
CSelectableCore::~CSelectableCore()
|
CSelectableCore::~CSelectableCore()
|
||||||
{
|
{
|
||||||
|
THandle * NextHandle = NULL;
|
||||||
|
bool Result;
|
||||||
|
|
||||||
|
// Destroy File Handles
|
||||||
|
while (FirstHandle)
|
||||||
|
{
|
||||||
|
// Close active resolve request
|
||||||
|
if (FirstHandle->Resolving && FirstHandle->ResolveReq) {
|
||||||
|
if ((Result = gai_cancel( FirstHandle->ResolveReq->Request )) != 0) {
|
||||||
|
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Error canceling Host Name resolve [%s:%s] (%s)",
|
||||||
|
ProcessName, Name, FirstHandle->Name, FirstHandle->HostName, FirstHandle->PortName, gai_strerror(Result) );
|
||||||
|
DestroyResolveReq( FirstHandle, true );
|
||||||
|
HandleState( FirstHandle, csFailed );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close handle if open
|
||||||
|
if ((FirstHandle->State == csOpen) || (FirstHandle->State == csWaitingtoOpen))
|
||||||
|
Close( FirstHandle, false );
|
||||||
|
|
||||||
|
NextHandle = FirstHandle->Next;
|
||||||
|
DestroyHandle( FirstHandle );
|
||||||
|
FirstHandle = NextHandle;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -227,6 +276,87 @@ bool CSelectableCore::Init( CDataMember * FunctionConfig )
|
|||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool CSelectableCore::DestroyHandle( THandle * Handle )
|
||||||
|
{
|
||||||
|
int Result;
|
||||||
|
|
||||||
|
// Validate Handle
|
||||||
|
if (!Handle)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Destroy Resolve request
|
||||||
|
if (Handle->Resolving && Handle->ResolveReq) {
|
||||||
|
if ((Result = gai_cancel( Handle->ResolveReq->Request )) != 0) {
|
||||||
|
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Error canceling Host Name resolve [%s:%s] (%s)",
|
||||||
|
ProcessName, Name, Handle->Name, Handle->HostName, Handle->PortName, gai_strerror(Result) );
|
||||||
|
}
|
||||||
|
DestroyResolveReq( Handle, true );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear parameters
|
||||||
|
if (Handle->Name)
|
||||||
|
free( Handle->Name );
|
||||||
|
if (Handle->Path)
|
||||||
|
free( Handle->Path );
|
||||||
|
if (Handle->HostName)
|
||||||
|
free( Handle->HostName );
|
||||||
|
if (Handle->PortName)
|
||||||
|
free( Handle->PortName );
|
||||||
|
if (Handle->AddressList)
|
||||||
|
freeaddrinfo( Handle->AddressList );
|
||||||
|
|
||||||
|
// Destroy Buffers
|
||||||
|
if (Handle->InBuffer)
|
||||||
|
delete Handle->InBuffer;
|
||||||
|
if (Handle->OutBuffer)
|
||||||
|
delete Handle->OutBuffer;
|
||||||
|
|
||||||
|
// Clear Input Markers
|
||||||
|
if (Handle->InMarker)
|
||||||
|
free( Handle->InMarker );
|
||||||
|
|
||||||
|
// Destroy Pointer
|
||||||
|
delete Handle;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool CSelectableCore::ClearHandle( THandle * Handle )
|
||||||
|
{
|
||||||
|
// Validate
|
||||||
|
if (!Handle) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset Type related parameters
|
||||||
|
if (Handle->Path) {
|
||||||
|
free( Handle->Path );
|
||||||
|
Handle->Path = NULL;
|
||||||
|
}
|
||||||
|
if (Handle->HostName) {
|
||||||
|
free( Handle->HostName );
|
||||||
|
Handle->HostName = NULL;
|
||||||
|
}
|
||||||
|
if (Handle->PortName) {
|
||||||
|
free( Handle->PortName );
|
||||||
|
Handle->PortName = NULL;
|
||||||
|
}
|
||||||
|
if (Handle->AddressList) {
|
||||||
|
freeaddrinfo( Handle->AddressList );
|
||||||
|
Handle->AddressList = NULL;
|
||||||
|
Handle->AddressInfo = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset Parameters
|
||||||
|
Handle->Type = ctNone;
|
||||||
|
|
||||||
|
// Log event
|
||||||
|
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Set as None",
|
||||||
|
ProcessName, Name, Handle->Name );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CSelectableCore::SetSerialHandle( THandle * Handle, const char * FileName )
|
bool CSelectableCore::SetSerialHandle( THandle * Handle, const char * FileName )
|
||||||
{
|
{
|
||||||
// Validate
|
// Validate
|
||||||
@@ -427,7 +557,7 @@ THandle * CSelectableCore::OpenSerialPort( THandle * Handle )
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set state
|
// Set state
|
||||||
ChangeState( Handle, csOpen );
|
HandleState( Handle, csOpen );
|
||||||
return Handle;
|
return Handle;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -470,7 +600,7 @@ THandle * CSelectableCore::OpenLinePrinterPort( THandle * Handle )
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set state
|
// Set state
|
||||||
ChangeState( Handle, csOpen );
|
HandleState( Handle, csOpen );
|
||||||
return Handle;
|
return Handle;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -572,7 +702,7 @@ THandle * CSelectableCore::OpenForkPipe( THandle * Handle )
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set state
|
// Set state
|
||||||
ChangeState( Handle, csOpen );
|
HandleState( Handle, csOpen );
|
||||||
return Handle;
|
return Handle;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -596,7 +726,7 @@ THandle * CSelectableCore::OpenUNIXserverSocket( THandle * Handle )
|
|||||||
ProcessName, Name, Handle->Name, Handle->Path, strerror(errno) );
|
ProcessName, Name, Handle->Name, Handle->Path, strerror(errno) );
|
||||||
|
|
||||||
// Set state
|
// Set state
|
||||||
ChangeState( Handle, csFailed );
|
HandleState( Handle, csFailed );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -608,7 +738,7 @@ THandle * CSelectableCore::OpenUNIXserverSocket( THandle * Handle )
|
|||||||
ProcessName, Name, Handle->Name, Handle->Path, strerror(errno) );
|
ProcessName, Name, Handle->Name, Handle->Path, strerror(errno) );
|
||||||
|
|
||||||
// Set state
|
// Set state
|
||||||
ChangeState( Handle, csFailed );
|
HandleState( Handle, csFailed );
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -633,7 +763,7 @@ THandle * CSelectableCore::OpenUNIXserverSocket( THandle * Handle )
|
|||||||
close( Handle->FD );
|
close( Handle->FD );
|
||||||
Handle->FD = -1;
|
Handle->FD = -1;
|
||||||
|
|
||||||
ChangeState( Handle, csFailed );
|
HandleState( Handle, csFailed );
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -648,7 +778,7 @@ THandle * CSelectableCore::OpenUNIXserverSocket( THandle * Handle )
|
|||||||
close( Handle->FD );
|
close( Handle->FD );
|
||||||
Handle->FD = -1;
|
Handle->FD = -1;
|
||||||
|
|
||||||
ChangeState( Handle, csFailed );
|
HandleState( Handle, csFailed );
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -662,7 +792,7 @@ THandle * CSelectableCore::OpenUNIXserverSocket( THandle * Handle )
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set state
|
// Set state
|
||||||
ChangeState( Handle, csOpen );
|
HandleState( Handle, csOpen );
|
||||||
return Handle;
|
return Handle;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -688,7 +818,7 @@ THandle * CSelectableCore::OpenUNIXclientSocket( THandle * Handle )
|
|||||||
ProcessName, Name, Handle->Name, Handle->Path, strerror(errno) );
|
ProcessName, Name, Handle->Name, Handle->Path, strerror(errno) );
|
||||||
|
|
||||||
// Set state
|
// Set state
|
||||||
ChangeState( Handle, csFailed );
|
HandleState( Handle, csFailed );
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -715,7 +845,7 @@ THandle * CSelectableCore::OpenUNIXclientSocket( THandle * Handle )
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set status
|
// Set status
|
||||||
ChangeState( Handle, csWaitingtoOpen );
|
HandleState( Handle, csWaitingtoOpen );
|
||||||
return Handle;
|
return Handle;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -734,7 +864,7 @@ THandle * CSelectableCore::OpenUNIXclientSocket( THandle * Handle )
|
|||||||
Handle->FD = -1;
|
Handle->FD = -1;
|
||||||
Handle->AddressFailed = true;
|
Handle->AddressFailed = true;
|
||||||
|
|
||||||
ChangeState( Handle, csFailed );
|
HandleState( Handle, csFailed );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -749,7 +879,7 @@ THandle * CSelectableCore::OpenUNIXclientSocket( THandle * Handle )
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set status
|
// Set status
|
||||||
ChangeState( Handle, csOpen );
|
HandleState( Handle, csOpen );
|
||||||
return Handle;
|
return Handle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -846,7 +976,7 @@ THandle * CSelectableCore::OpenUNIXremoteSocket( THandle * Handle )
|
|||||||
ProcessName, Name, Handle->Name, Handle->Path );
|
ProcessName, Name, Handle->Name, Handle->Path );
|
||||||
|
|
||||||
// Update state
|
// Update state
|
||||||
ChangeState( Handle, csOpen );
|
HandleState( Handle, csOpen );
|
||||||
return Handle;
|
return Handle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -856,12 +986,17 @@ THandle * CSelectableCore::OpenUNIXremoteSocket( THandle * Handle )
|
|||||||
|
|
||||||
bool CSelectableCore::ResolveAddress( THandle * Handle, bool DelayResolve )
|
bool CSelectableCore::ResolveAddress( THandle * Handle, bool DelayResolve )
|
||||||
{
|
{
|
||||||
struct addrinfo hints;
|
struct addrinfo * Hints;
|
||||||
int result;
|
TResolveReq * ResolveReq;
|
||||||
|
sigevent ResolveEvt;
|
||||||
|
int Result;
|
||||||
|
|
||||||
|
// Ignore if busy resolving
|
||||||
|
if (Handle->Resolving)
|
||||||
|
return false;
|
||||||
|
|
||||||
// Check if resolved address available
|
// Check if resolved address available
|
||||||
if (Handle->AddressInfo)
|
if (Handle->AddressInfo) {
|
||||||
{
|
|
||||||
// Return if address still valid
|
// Return if address still valid
|
||||||
if (!Handle->AddressFailed)
|
if (!Handle->AddressFailed)
|
||||||
return true;
|
return true;
|
||||||
@@ -892,47 +1027,117 @@ bool CSelectableCore::ResolveAddress( THandle * Handle, bool DelayResolve )
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set address specification
|
// Set address specification
|
||||||
memset( &hints, 0, sizeof hints );
|
Hints = (struct addrinfo*)calloc( 1, sizeof(struct addrinfo) );
|
||||||
if ((Handle->Type == ctTCPserver) || (Handle->Type == ctTCPclient)) {
|
if ((Handle->Type == ctTCPserver) || (Handle->Type == ctTCPclient)) {
|
||||||
hints.ai_family = AF_UNSPEC; // use AF_INET6 to force IPv6
|
Hints->ai_family = AF_UNSPEC; // use AF_INET6 to force IPv6
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
Hints->ai_socktype = SOCK_STREAM;
|
||||||
} else {
|
} else {
|
||||||
hints.ai_family = AF_UNSPEC; // use AF_INET6 to force IPv6
|
Hints->ai_family = AF_UNSPEC; // use AF_INET6 to force IPv6
|
||||||
hints.ai_socktype = SOCK_DGRAM;
|
Hints->ai_socktype = SOCK_DGRAM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create request data
|
||||||
|
ResolveReq = new TResolveReq;
|
||||||
|
Handle->ResolveReq = ResolveReq;
|
||||||
|
|
||||||
|
ResolveReq->Handle = Handle;
|
||||||
|
ResolveReq->Request = (gaicb*)calloc( 1, sizeof(gaicb) );
|
||||||
|
|
||||||
|
// DNS request / reply structure
|
||||||
|
ResolveReq->Request->ar_name = Handle->HostName;
|
||||||
|
ResolveReq->Request->ar_service = Handle->PortName;
|
||||||
|
ResolveReq->Request->ar_request = Hints;
|
||||||
|
ResolveReq->Request->ar_result = NULL;
|
||||||
|
|
||||||
|
// Configure signal event
|
||||||
|
ResolveEvt.sigev_notify = SIGEV_SIGNAL;
|
||||||
|
ResolveEvt.sigev_signo = SIGRTMIN;
|
||||||
|
ResolveEvt.sigev_value.sival_ptr = ResolveReq;
|
||||||
|
|
||||||
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Resolving Host name [%s:%s]...",
|
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Resolving Host name [%s:%s]...",
|
||||||
ProcessName, Name, Handle->Name, Handle->HostName, Handle->PortName );
|
ProcessName, Name, Handle->Name, Handle->HostName, Handle->PortName );
|
||||||
|
|
||||||
// Should address be resolved later during process()
|
// Should address be resolved later during process()
|
||||||
if (DelayResolve)
|
if (DelayResolve) {
|
||||||
{
|
|
||||||
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Delay resolving of Host Name [%s:%s]",
|
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Delay resolving of Host Name [%s:%s]",
|
||||||
ProcessName, Name, Handle->Name, Handle->HostName, Handle->PortName );
|
ProcessName, Name, Handle->Name, Handle->HostName, Handle->PortName );
|
||||||
ChangeState( Handle, csOpenRequest );
|
|
||||||
|
HandleState( Handle, csOpenRequest );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve Host & Port Names
|
// Resolve Host & Port Names
|
||||||
if ((result = getaddrinfo( Handle->HostName, Handle->PortName, &hints, &(Handle->AddressList))) != 0)
|
Handle->Resolving = true;
|
||||||
{
|
if ((Result = getaddrinfo_a( GAI_NOWAIT, &(Handle->ResolveReq->Request), 1, &ResolveEvt )) != 0) {
|
||||||
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Failed to resolve Host Name [%s:%s] (%s)",
|
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Error resolving Host Name [%s:%s] (%s)",
|
||||||
ProcessName, Name, Handle->Name, Handle->HostName, Handle->PortName, gai_strerror(result) );
|
ProcessName, Name, Handle->Name, Handle->HostName, Handle->PortName, gai_strerror(Result) );
|
||||||
ChangeState( Handle, csFailed );
|
DestroyResolveReq( Handle, true );
|
||||||
|
|
||||||
|
HandleState( Handle, csFailed );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool CSelectableCore::DestroyResolveReq( THandle * Handle, bool DestroyResult )
|
||||||
|
{
|
||||||
|
// Validate
|
||||||
|
if (!Handle || !Handle->ResolveReq)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Destroying resolve request [%s:%s]",
|
||||||
|
ProcessName, Name, Handle->Name, Handle->HostName, Handle->PortName );
|
||||||
|
|
||||||
|
// Destroy
|
||||||
|
if (DestroyResult) {
|
||||||
|
if (Handle->ResolveReq->Request->ar_result)
|
||||||
|
freeaddrinfo( Handle->ResolveReq->Request->ar_result );
|
||||||
|
}
|
||||||
|
if (Handle->ResolveReq->Request->ar_request)
|
||||||
|
free( (void*)Handle->ResolveReq->Request->ar_request );
|
||||||
|
if (Handle->ResolveReq->Request)
|
||||||
|
free( Handle->ResolveReq->Request );
|
||||||
|
if (Handle->ResolveReq)
|
||||||
|
delete Handle->ResolveReq;
|
||||||
|
|
||||||
|
// Reset request
|
||||||
|
Handle->ResolveReq = NULL;
|
||||||
|
Handle->Resolving = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool CSelectableCore::HandleResolve( THandle * Handle )
|
||||||
|
{
|
||||||
|
bool Result;
|
||||||
|
|
||||||
|
// Validate result
|
||||||
|
if ((Result = gai_error( Handle->ResolveReq->Request )) != 0) {
|
||||||
|
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Error resolving Host Name [%s:%s] (%s)",
|
||||||
|
ProcessName, Name, Handle->Name, Handle->HostName, Handle->PortName, gai_strerror(Result) );
|
||||||
|
DestroyResolveReq( Handle, true );
|
||||||
|
|
||||||
|
HandleState( Handle, csFailed );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Select first address, skip "0.0.0.0"
|
// Read result
|
||||||
|
Handle->AddressList = Handle->ResolveReq->Request->ar_result;
|
||||||
Handle->AddressInfo = Handle->AddressList;
|
Handle->AddressInfo = Handle->AddressList;
|
||||||
|
|
||||||
|
// Select first address, skip "0.0.0.0"
|
||||||
if (!strcmp( inet_ntoa(((struct sockaddr_in *)Handle->AddressInfo->ai_addr)->sin_addr), "0.0.0.0" ))
|
if (!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;
|
||||||
|
|
||||||
if (!Handle->AddressInfo) {
|
if (!Handle->AddressInfo) {
|
||||||
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Failed to resolve Host Name [%s:%s] (%s)",
|
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Failed to resolve Host Name [%s:%s] (No Result)",
|
||||||
ProcessName, Name, Handle->Name, Handle->HostName, Handle->PortName, gai_strerror(result) );
|
ProcessName, Name, Handle->Name, Handle->HostName, Handle->PortName );
|
||||||
freeaddrinfo( Handle->AddressList );
|
freeaddrinfo( Handle->AddressList );
|
||||||
Handle->AddressList = NULL;
|
Handle->AddressList = NULL;
|
||||||
Handle->AddressInfo = NULL;
|
Handle->AddressInfo = NULL;
|
||||||
ChangeState( Handle, csFailed );
|
|
||||||
|
HandleState( Handle, csFailed );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -941,6 +1146,9 @@ bool CSelectableCore::ResolveAddress( THandle * Handle, bool DelayResolve )
|
|||||||
ProcessName, Name, Handle->Name, Handle->HostName, Handle->PortName,
|
ProcessName, Name, Handle->Name, Handle->HostName, Handle->PortName,
|
||||||
inet_ntoa(((struct sockaddr_in *)Handle->AddressInfo->ai_addr)->sin_addr),
|
inet_ntoa(((struct sockaddr_in *)Handle->AddressInfo->ai_addr)->sin_addr),
|
||||||
ntohs(((struct sockaddr_in *)Handle->AddressInfo->ai_addr)->sin_port) );
|
ntohs(((struct sockaddr_in *)Handle->AddressInfo->ai_addr)->sin_port) );
|
||||||
|
|
||||||
|
// Destroy request
|
||||||
|
DestroyResolveReq( Handle, false );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -964,7 +1172,7 @@ THandle * CSelectableCore::OpenUDPserverSocket( THandle * Handle, bool DelayReso
|
|||||||
ProcessName, Name, Handle->Name, Handle->HostName, Handle->PortName, strerror(errno) );
|
ProcessName, Name, Handle->Name, Handle->HostName, Handle->PortName, strerror(errno) );
|
||||||
|
|
||||||
// Set state
|
// Set state
|
||||||
ChangeState( Handle, csFailed );
|
HandleState( Handle, csFailed );
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -985,7 +1193,7 @@ THandle * CSelectableCore::OpenUDPserverSocket( THandle * Handle, bool DelayReso
|
|||||||
Handle->AddressFailed = true;
|
Handle->AddressFailed = true;
|
||||||
|
|
||||||
// Change state
|
// Change state
|
||||||
ChangeState( Handle, csFailed );
|
HandleState( Handle, csFailed );
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -999,7 +1207,7 @@ THandle * CSelectableCore::OpenUDPserverSocket( THandle * Handle, bool DelayReso
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set state
|
// Set state
|
||||||
ChangeState( Handle, csOpen );
|
HandleState( Handle, csOpen );
|
||||||
return Handle;
|
return Handle;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -1081,7 +1289,7 @@ THandle * CSelectableCore::OpenUDPclientSocket( THandle * Handle, bool DelayReso
|
|||||||
ProcessName, Name, Handle->Name, Handle->HostName, Handle->PortName, strerror(errno) );
|
ProcessName, Name, Handle->Name, Handle->HostName, Handle->PortName, strerror(errno) );
|
||||||
|
|
||||||
// Set Status
|
// Set Status
|
||||||
ChangeState( Handle, csFailed );
|
HandleState( Handle, csFailed );
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1098,7 +1306,7 @@ THandle * CSelectableCore::OpenUDPclientSocket( THandle * Handle, bool DelayReso
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set status
|
// Set status
|
||||||
ChangeState( Handle, csOpen );
|
HandleState( Handle, csOpen );
|
||||||
return Handle;
|
return Handle;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -1133,7 +1341,7 @@ THandle * CSelectableCore::OpenTCPserverSocket( THandle * Handle, bool DelayReso
|
|||||||
ProcessName, Name, Handle->Name, Handle->HostName, Handle->PortName, strerror(errno) );
|
ProcessName, Name, Handle->Name, Handle->HostName, Handle->PortName, strerror(errno) );
|
||||||
|
|
||||||
// Set state
|
// Set state
|
||||||
ChangeState( Handle, csFailed );
|
HandleState( Handle, csFailed );
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1146,7 +1354,7 @@ THandle * CSelectableCore::OpenTCPserverSocket( THandle * Handle, bool DelayReso
|
|||||||
ProcessName, Name, Handle->Name, Handle->HostName, Handle->PortName, strerror(errno) );
|
ProcessName, Name, Handle->Name, Handle->HostName, Handle->PortName, strerror(errno) );
|
||||||
|
|
||||||
// Set state
|
// Set state
|
||||||
ChangeState( Handle, csFailed );
|
HandleState( Handle, csFailed );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1161,7 +1369,7 @@ THandle * CSelectableCore::OpenTCPserverSocket( THandle * Handle, bool DelayReso
|
|||||||
ProcessName, Name, Handle->Name, Handle->HostName, Handle->PortName, strerror(errno) );
|
ProcessName, Name, Handle->Name, Handle->HostName, Handle->PortName, strerror(errno) );
|
||||||
|
|
||||||
// Set state
|
// Set state
|
||||||
ChangeState( Handle, csFailed );
|
HandleState( Handle, csFailed );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1181,7 +1389,7 @@ THandle * CSelectableCore::OpenTCPserverSocket( THandle * Handle, bool DelayReso
|
|||||||
Handle->FD = -1;
|
Handle->FD = -1;
|
||||||
Handle->AddressFailed = true;
|
Handle->AddressFailed = true;
|
||||||
|
|
||||||
ChangeState( Handle, csFailed );
|
HandleState( Handle, csFailed );
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1197,7 +1405,7 @@ THandle * CSelectableCore::OpenTCPserverSocket( THandle * Handle, bool DelayReso
|
|||||||
Handle->FD = -1;
|
Handle->FD = -1;
|
||||||
Handle->AddressFailed = true;
|
Handle->AddressFailed = true;
|
||||||
|
|
||||||
ChangeState( Handle, csFailed );
|
HandleState( Handle, csFailed );
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1211,7 +1419,7 @@ THandle * CSelectableCore::OpenTCPserverSocket( THandle * Handle, bool DelayReso
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set state
|
// Set state
|
||||||
ChangeState( Handle, csOpen );
|
HandleState( Handle, csOpen );
|
||||||
return Handle;
|
return Handle;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -1313,7 +1521,7 @@ THandle * CSelectableCore::OpenTCPremoteSocket( THandle * Handle )
|
|||||||
ProcessName, Name, Handle->Name, Handle->HostName );
|
ProcessName, Name, Handle->Name, Handle->HostName );
|
||||||
|
|
||||||
// Update state
|
// Update state
|
||||||
ChangeState( Handle, csOpen );
|
HandleState( Handle, csOpen );
|
||||||
return Handle;
|
return Handle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1324,10 +1532,11 @@ THandle * CSelectableCore::OpenTCPremoteSocket( THandle * Handle )
|
|||||||
THandle * CSelectableCore::OpenTCPclientSocket( THandle * Handle, bool DelayResolve )
|
THandle * CSelectableCore::OpenTCPclientSocket( THandle * Handle, bool DelayResolve )
|
||||||
{
|
{
|
||||||
// Socket options
|
// Socket options
|
||||||
int KeepAlive_opt = 1;
|
int KeepAlive_opt = 1; // Enable/disable keep alive
|
||||||
int TCPidle_opt = 5;
|
int TCPidle_opt = 5; // Idle time on socket before sending first keep alive signal
|
||||||
int TCPcnt_opt = 3;
|
int TCPint_opt = 2; // Interval between keep alive signals
|
||||||
int TCPint_opt = 2;
|
int TCPcnt_opt = 3; // No of missed keep alive response before connection fail
|
||||||
|
int TCPsyn_opt = 3; // Max SYN (connect retries) before open fails
|
||||||
|
|
||||||
// Check state
|
// Check state
|
||||||
if (Handle->State == csOpen) {
|
if (Handle->State == csOpen) {
|
||||||
@@ -1349,7 +1558,7 @@ THandle * CSelectableCore::OpenTCPclientSocket( THandle * Handle, bool DelayReso
|
|||||||
ProcessName, Name, Handle->Name, Handle->HostName, Handle->PortName, strerror(errno) );
|
ProcessName, Name, Handle->Name, Handle->HostName, Handle->PortName, strerror(errno) );
|
||||||
|
|
||||||
// Set Status
|
// Set Status
|
||||||
ChangeState( Handle, csFailed );
|
HandleState( Handle, csFailed );
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1361,7 +1570,8 @@ THandle * CSelectableCore::OpenTCPclientSocket( THandle * Handle, bool DelayReso
|
|||||||
if ((setsockopt( Handle->FD, SOL_SOCKET, SO_KEEPALIVE, &KeepAlive_opt, sizeof(KeepAlive_opt)) == -1) ||
|
if ((setsockopt( Handle->FD, SOL_SOCKET, SO_KEEPALIVE, &KeepAlive_opt, sizeof(KeepAlive_opt)) == -1) ||
|
||||||
(setsockopt( Handle->FD, SOL_TCP, TCP_KEEPIDLE, &TCPidle_opt, sizeof(TCPidle_opt)) == -1) ||
|
(setsockopt( Handle->FD, SOL_TCP, TCP_KEEPIDLE, &TCPidle_opt, sizeof(TCPidle_opt)) == -1) ||
|
||||||
(setsockopt( Handle->FD, SOL_TCP, TCP_KEEPCNT, &TCPcnt_opt, sizeof(TCPcnt_opt)) == -1) ||
|
(setsockopt( Handle->FD, SOL_TCP, TCP_KEEPCNT, &TCPcnt_opt, sizeof(TCPcnt_opt)) == -1) ||
|
||||||
(setsockopt( Handle->FD, SOL_TCP, TCP_KEEPINTVL, &TCPint_opt, sizeof(TCPint_opt)) == -1) )
|
(setsockopt( Handle->FD, SOL_TCP, TCP_KEEPINTVL, &TCPint_opt, sizeof(TCPint_opt)) == -1) ||
|
||||||
|
(setsockopt( Handle->FD, SOL_TCP, TCP_SYNCNT, &TCPsyn_opt, sizeof(TCPsyn_opt)) == -1) )
|
||||||
{
|
{
|
||||||
// Log Event
|
// Log Event
|
||||||
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Could not set KeepAlive options [%s:%s] (%s)",
|
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Could not set KeepAlive options [%s:%s] (%s)",
|
||||||
@@ -1371,7 +1581,7 @@ THandle * CSelectableCore::OpenTCPclientSocket( THandle * Handle, bool DelayReso
|
|||||||
close( Handle->FD );
|
close( Handle->FD );
|
||||||
Handle->FD = -1;
|
Handle->FD = -1;
|
||||||
|
|
||||||
ChangeState( Handle, csFailed );
|
HandleState( Handle, csFailed );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1388,7 +1598,7 @@ THandle * CSelectableCore::OpenTCPclientSocket( THandle * Handle, bool DelayReso
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set status
|
// Set status
|
||||||
ChangeState( Handle, csOpen );
|
HandleState( Handle, csOpen );
|
||||||
return Handle;
|
return Handle;
|
||||||
}
|
}
|
||||||
else if ((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINPROGRESS) || (errno == EALREADY))
|
else if ((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINPROGRESS) || (errno == EALREADY))
|
||||||
@@ -1403,7 +1613,7 @@ THandle * CSelectableCore::OpenTCPclientSocket( THandle * Handle, bool DelayReso
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set status
|
// Set status
|
||||||
ChangeState( Handle, csWaitingtoOpen );
|
HandleState( Handle, csWaitingtoOpen );
|
||||||
return Handle;
|
return Handle;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1422,7 +1632,7 @@ THandle * CSelectableCore::OpenTCPclientSocket( THandle * Handle, bool DelayReso
|
|||||||
Handle->FD = -1;
|
Handle->FD = -1;
|
||||||
Handle->AddressFailed = true;
|
Handle->AddressFailed = true;
|
||||||
|
|
||||||
ChangeState( Handle, csFailed );
|
HandleState( Handle, csFailed );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1614,7 +1824,7 @@ bool CSelectableCore::Close( THandle * Handle, bool QuickReopen )
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Change State
|
// Change State
|
||||||
ChangeState( Handle, ((Fail)? csFailed : csClosed) );
|
HandleState( Handle, ((Fail)? csFailed : csClosed) );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
|
|
||||||
// Standard C/C++ Libraries
|
// Standard C/C++ Libraries
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
|
||||||
// redA Libraries
|
// redA Libraries
|
||||||
#include "FunctionCore.h"
|
#include "FunctionCore.h"
|
||||||
@@ -44,13 +46,14 @@ const char ConnectStateName[][15] = { "None", "OpenRequest", "WaitingToOpen", "O
|
|||||||
// Previews
|
// Previews
|
||||||
typedef struct SSelectHandle TSelectHandle;
|
typedef struct SSelectHandle TSelectHandle;
|
||||||
typedef struct SHandle THandle;
|
typedef struct SHandle THandle;
|
||||||
|
typedef struct SResolveReq TResolveReq;
|
||||||
|
|
||||||
class CSelect;
|
class CSelect;
|
||||||
class CSelectableBare;
|
class CSelectableBare;
|
||||||
class CSelectableCore;
|
class CSelectableCore;
|
||||||
|
|
||||||
// Callback function for handle events
|
// Callback function for handle events
|
||||||
typedef void (*FHandleCallback)( CSelectableBare * Function, THandle * Handle, EConnectState State );
|
typedef void (*FHandleCallback)( CSelectableBare * Function, THandle * Handle, EConnectState OldState );
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -68,7 +71,6 @@ struct SSelectHandle {
|
|||||||
// List
|
// List
|
||||||
TSelectHandle * Next = NULL;
|
TSelectHandle * Next = NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
// List or Handles for Selectable Function Object
|
// List or Handles for Selectable Function Object
|
||||||
@@ -76,6 +78,7 @@ struct SHandle {
|
|||||||
// Description
|
// Description
|
||||||
char * Name = NULL;
|
char * Name = NULL;
|
||||||
EConnectType Type = ctNone;
|
EConnectType Type = ctNone;
|
||||||
|
CSelectableBare * Function = NULL;
|
||||||
|
|
||||||
// State
|
// State
|
||||||
int FD = -1;
|
int FD = -1;
|
||||||
@@ -103,7 +106,10 @@ struct SHandle {
|
|||||||
struct addrinfo * AddressInfo = NULL; // Current selected IP Address
|
struct addrinfo * AddressInfo = NULL; // Current selected IP Address
|
||||||
bool AddressFailed = false; // Indicate failure to connect to address
|
bool AddressFailed = false; // Indicate failure to connect to address
|
||||||
short Queue = 2; // Max waiting connections
|
short Queue = 2; // Max waiting connections
|
||||||
|
|
||||||
long ResolveDelay = 0; // Delay before resolving hostname via DNS
|
long ResolveDelay = 0; // Delay before resolving hostname via DNS
|
||||||
|
TResolveReq * ResolveReq = NULL; // DNS resolve request
|
||||||
|
bool Resolving = false; // Busy resolving address
|
||||||
|
|
||||||
// Serial Port config
|
// Serial Port config
|
||||||
bool SerialConfig = false;
|
bool SerialConfig = false;
|
||||||
@@ -132,6 +138,16 @@ struct SHandle {
|
|||||||
THandle * Parent = NULL;
|
THandle * Parent = NULL;
|
||||||
THandle * Next = NULL;
|
THandle * Next = NULL;
|
||||||
};
|
};
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
struct SResolveReq {
|
||||||
|
THandle * Handle = NULL;
|
||||||
|
gaicb * Request = NULL;
|
||||||
|
};
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Resolving
|
||||||
|
void ResolveHandler( int Signal, siginfo_t * SignalInfo, void * Context );
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -192,9 +208,9 @@ protected:
|
|||||||
CSelect * Selector = NULL;
|
CSelect * Selector = NULL;
|
||||||
|
|
||||||
// Managing File Handles
|
// Managing File Handles
|
||||||
bool RemoveHandle( THandle * Handle );
|
virtual bool RemoveHandle( THandle * Handle );
|
||||||
bool DestroyHandle( THandle * Handle );
|
virtual bool DestroyHandle( THandle * Handle );
|
||||||
bool ChangeState( THandle * Handle, EConnectState State );
|
virtual bool HandleState( THandle * Handle, EConnectState State );
|
||||||
|
|
||||||
// Get Parameters
|
// Get Parameters
|
||||||
inline int GetFD( const char * HandleName ) {
|
inline int GetFD( const char * HandleName ) {
|
||||||
@@ -241,7 +257,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// General port parameters
|
// General port parameters
|
||||||
THandle * CreateHandle( const char * HandleName, bool CreateChannel );
|
virtual THandle * CreateHandle( const char * HandleName, bool CreateChannel );
|
||||||
virtual CDataMember * GetHandleAddress( THandle * Handle, const char * HandleRef );
|
virtual CDataMember * GetHandleAddress( THandle * Handle, const char * HandleRef );
|
||||||
|
|
||||||
bool SetCallback( THandle * Handle, EConnectState pState, FHandleCallback pCallback );
|
bool SetCallback( THandle * Handle, EConnectState pState, FHandleCallback pCallback );
|
||||||
@@ -249,9 +265,6 @@ public:
|
|||||||
bool SetInBuffer( THandle * Handle, int InBufSize, int InTimeout, const char * InMarker, int InMarkerLen );
|
bool SetInBuffer( THandle * Handle, int InBufSize, int InTimeout, const char * InMarker, int InMarkerLen );
|
||||||
bool SetOutBuffer( THandle * Handle, int OutBufSize );
|
bool SetOutBuffer( THandle * Handle, int OutBufSize );
|
||||||
|
|
||||||
// Specific port parameters
|
|
||||||
bool ClearHandle( THandle * Handle );
|
|
||||||
|
|
||||||
// FD Operations
|
// FD Operations
|
||||||
virtual int Open( THandle * Handle, bool DelayResolve = false ) = 0;
|
virtual int Open( THandle * Handle, bool DelayResolve = false ) = 0;
|
||||||
virtual bool Close( THandle * Handle, bool QuickReopen );
|
virtual bool Close( THandle * Handle, bool QuickReopen );
|
||||||
@@ -291,6 +304,8 @@ public:
|
|||||||
class CSelectableCore : public CSelectableBare
|
class CSelectableCore : public CSelectableBare
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
struct sigaction ResolveAct;
|
||||||
|
|
||||||
// Port Operations
|
// Port Operations
|
||||||
THandle * OpenSerialPort( THandle * Handle );
|
THandle * OpenSerialPort( THandle * Handle );
|
||||||
bool WriteSerialConfig( THandle * Handle );
|
bool WriteSerialConfig( THandle * Handle );
|
||||||
@@ -306,6 +321,11 @@ protected:
|
|||||||
|
|
||||||
// Socket Operations
|
// Socket Operations
|
||||||
bool ResolveAddress( THandle * Handle, bool DelayResolve );
|
bool ResolveAddress( THandle * Handle, bool DelayResolve );
|
||||||
|
bool HandleResolve( THandle * Handle );
|
||||||
|
bool DestroyResolveReq( THandle * Handle, bool DestroyResult );
|
||||||
|
|
||||||
|
// Managing File Handles
|
||||||
|
virtual bool DestroyHandle( THandle * Handle );
|
||||||
|
|
||||||
THandle * OpenUDPserverSocket( THandle * Handle, bool DelayResolve );
|
THandle * OpenUDPserverSocket( THandle * Handle, bool DelayResolve );
|
||||||
THandle * OpenUDPremoteSocket( THandle * Handle, char * RemoteAddr, char * RemotePort );
|
THandle * OpenUDPremoteSocket( THandle * Handle, char * RemoteAddr, char * RemotePort );
|
||||||
@@ -330,6 +350,8 @@ public:
|
|||||||
virtual bool Init( CDataMember * FunctionConfig );
|
virtual bool Init( CDataMember * FunctionConfig );
|
||||||
|
|
||||||
// Specific port parameters
|
// Specific port parameters
|
||||||
|
bool ClearHandle( THandle * Handle );
|
||||||
|
|
||||||
bool SetSerialHandle( THandle * Handle, const char * FileName );
|
bool SetSerialHandle( THandle * Handle, const char * FileName );
|
||||||
bool SetSerialHandleConfig( THandle * Handle, int Baudrate, short DataBits, short Parity, short StopBits, short FlowCtrl, int DataWait );
|
bool SetSerialHandleConfig( THandle * Handle, int Baudrate, short DataBits, short Parity, short StopBits, short FlowCtrl, int DataWait );
|
||||||
bool SetLinePrinterHandle( THandle * Handle, const char * FileName );
|
bool SetLinePrinterHandle( THandle * Handle, const char * FileName );
|
||||||
@@ -346,6 +368,8 @@ public:
|
|||||||
// Function Interface
|
// Function Interface
|
||||||
virtual int OutputHandle( THandle * Handle, const char * Data, int Len );
|
virtual int OutputHandle( THandle * Handle, const char * Data, int Len );
|
||||||
virtual bool Process();
|
virtual bool Process();
|
||||||
|
|
||||||
|
friend void ResolveHandler( int Signal, siginfo_t * SignalInfo, void * Context );
|
||||||
};
|
};
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -41,21 +41,21 @@ void ConfigureSignalHandlers()
|
|||||||
sigemptyset( &TermAct.sa_mask );
|
sigemptyset( &TermAct.sa_mask );
|
||||||
TermAct.sa_flags = SA_RESTART;
|
TermAct.sa_flags = SA_RESTART;
|
||||||
|
|
||||||
sigaction( SIGHUP, &TermAct, 0 );
|
sigaction( SIGHUP, &TermAct, NULL );
|
||||||
sigaction( SIGINT, &TermAct, 0 );
|
sigaction( SIGINT, &TermAct, NULL );
|
||||||
sigaction( SIGQUIT, &TermAct, 0 );
|
sigaction( SIGQUIT, &TermAct, NULL );
|
||||||
sigaction( SIGTERM, &TermAct, 0 );
|
sigaction( SIGTERM, &TermAct, NULL );
|
||||||
sigaction( SIGTSTP, &TermAct, 0 );
|
sigaction( SIGTSTP, &TermAct, NULL );
|
||||||
|
|
||||||
// Signals for immediate termination
|
// Signals for immediate termination
|
||||||
AbortAct.sa_handler = SignalAbort;
|
AbortAct.sa_handler = SignalAbort;
|
||||||
sigemptyset( &AbortAct.sa_mask );
|
sigemptyset( &AbortAct.sa_mask );
|
||||||
AbortAct.sa_flags = 0;
|
AbortAct.sa_flags = 0;
|
||||||
|
|
||||||
sigaction( SIGABRT, &AbortAct, 0 );
|
sigaction( SIGABRT, &AbortAct, NULL );
|
||||||
sigaction( SIGFPE, &AbortAct, 0 );
|
sigaction( SIGFPE, &AbortAct, NULL );
|
||||||
sigaction( SIGILL, &AbortAct, 0 );
|
sigaction( SIGILL, &AbortAct, NULL );
|
||||||
sigaction( SIGSEGV, &AbortAct, 0 );
|
sigaction( SIGSEGV, &AbortAct, NULL );
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user