Important Update:
- FunctionCore
- So not set Function JSON "config" param to empty object by default
- Change TChannelLink to reference Channel direct
- Add Input/Output to TChannelLink
- Replace LinkChannel() Bidirectional param with Input/Output param
- Update JSON config as well
- Implement Channel "Ready" state and events
- Remove Input/OutputEnabled parameters and related methods
- Remove from JSON config as well
- Update AddChannel() method accordingly
- Add Ref param to struct TChannel
- SelectableCore:
- Convert inline ChangeState() to non-inline method
- Move ChangeState() to last step in open/close methods
- Add Channels in Not Ready state
- Change Channel state when Handle state changed
- DeviceCore:
- Add Channels in Ready state
- FileCore:
- Add Channel in Not Ready state
This commit is contained in:
@@ -68,11 +68,19 @@ bool CDeviceCore::Init( CDataMember * FunctionConfig )
|
|||||||
|
|
||||||
// Add Channels
|
// Add Channels
|
||||||
if (!(CmdChannel = GetChannel( "Command" )))
|
if (!(CmdChannel = GetChannel( "Command" )))
|
||||||
CmdChannel = AddChannel( "Command", true, true );
|
CmdChannel = AddChannel( "Command", true );
|
||||||
|
else
|
||||||
|
SetChannelState( CmdChannel, true );
|
||||||
|
|
||||||
if (!(DeviceChannel = GetChannel( "Device" )))
|
if (!(DeviceChannel = GetChannel( "Device" )))
|
||||||
DeviceChannel = AddChannel( "Device", true, true );
|
DeviceChannel = AddChannel( "Device", true );
|
||||||
|
else
|
||||||
|
SetChannelState( DeviceChannel, true );
|
||||||
|
|
||||||
if (!(EventChannel = GetChannel( "Event" )))
|
if (!(EventChannel = GetChannel( "Event" )))
|
||||||
EventChannel = AddChannel( "Event", true, true );
|
EventChannel = AddChannel( "Event", true );
|
||||||
|
else
|
||||||
|
SetChannelState( EventChannel, true );
|
||||||
|
|
||||||
// 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 );
|
AddChannel( Name, false );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set Parameters
|
// Set Parameters
|
||||||
|
|||||||
162
FunctionCore.cpp
162
FunctionCore.cpp
@@ -54,12 +54,8 @@ CFunctionCore::~CFunctionCore()
|
|||||||
free( FirstChannel->Ref );
|
free( FirstChannel->Ref );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destroy Linked Outputs
|
// Destroy Linked Channels
|
||||||
while (FirstChannel->FirstLink) {
|
while (FirstChannel->FirstLink) {
|
||||||
if (FirstChannel->FirstLink->Name) {
|
|
||||||
free( FirstChannel->FirstLink->Name );
|
|
||||||
free( FirstChannel->FirstLink->Ref );
|
|
||||||
}
|
|
||||||
NextLinkedChannel = FirstChannel->FirstLink->Next;
|
NextLinkedChannel = FirstChannel->FirstLink->Next;
|
||||||
delete FirstChannel->FirstLink;
|
delete FirstChannel->FirstLink;
|
||||||
FirstChannel->FirstLink = NextLinkedChannel;
|
FirstChannel->FirstLink = NextLinkedChannel;
|
||||||
@@ -103,13 +99,8 @@ 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 );
|
||||||
if (ChannelConfig->GetName()) {
|
|
||||||
AddChannel( ChannelConfig->GetName(),
|
|
||||||
ChannelConfig->GetChBool( "InputEnabled", true, true ),
|
|
||||||
ChannelConfig->GetChBool( "OutputEnabled", false, true ));
|
|
||||||
}
|
|
||||||
ChannelConfig = ChannelConfig->GetNextPeer();
|
ChannelConfig = ChannelConfig->GetNextPeer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,7 +109,6 @@ bool CFunctionCore::Init( CDataMember * FunctionConfig )
|
|||||||
ConfigName = (char*)FunctionConfig->GetChStr( "Config" );
|
ConfigName = (char*)FunctionConfig->GetChStr( "Config" );
|
||||||
Config = Application->Config->GetChild( ConfigName, true );
|
Config = Application->Config->GetChild( ConfigName, true );
|
||||||
}
|
}
|
||||||
if (Config->isNull()) Config->SetObject();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -145,9 +135,10 @@ bool CFunctionCore::InitChannelLinks( CDataMember * LinkConfig )
|
|||||||
{
|
{
|
||||||
// Get Parameters
|
// Get Parameters
|
||||||
LinkChannel( Channel->Name,
|
LinkChannel( Channel->Name,
|
||||||
FunctionMember->GetChStr( "Function" ),
|
FunctionMember->GetChStr( "Function", NULL, true ),
|
||||||
FunctionMember->GetChStr( "Channel" ),
|
FunctionMember->GetChStr( "Channel", NULL, true ),
|
||||||
FunctionMember->GetChBool( "Bidirectional" ) );
|
FunctionMember->GetChBool( "Input", false, true ),
|
||||||
|
FunctionMember->GetChBool( "Output", false, true ) );
|
||||||
FunctionMember = FunctionMember->GetNextPeer();
|
FunctionMember = FunctionMember->GetNextPeer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -175,7 +166,7 @@ bool CFunctionCore::SetLogLevel( EDebugLevel pDebugLevel )
|
|||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
TChannel * CFunctionCore::AddChannel( const char * ChannelName, const bool pInputEnable, const bool pOutputEnable )
|
TChannel * CFunctionCore::AddChannel( const char * ChannelName, bool Ready )
|
||||||
{
|
{
|
||||||
TChannel ** Channel = NULL;
|
TChannel ** Channel = NULL;
|
||||||
|
|
||||||
@@ -197,63 +188,106 @@ TChannel * CFunctionCore::AddChannel( const char * ChannelName, const bool pInpu
|
|||||||
|
|
||||||
// Set Name
|
// Set Name
|
||||||
(*Channel)->Name = strdup( ChannelName );
|
(*Channel)->Name = strdup( ChannelName );
|
||||||
|
(*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;
|
||||||
|
|
||||||
// Log Event
|
// Log Event
|
||||||
if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Channel '%s' - Created",
|
if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Channel '%s' - Created, Ref:'%s', Ready:%s",
|
||||||
ProcessName, Name, ChannelName );
|
ProcessName, Name, ChannelName, (*Channel)->Ref, (((*Channel)->Ready)? "Yes" : "No") );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set parameters
|
|
||||||
(*Channel)->InputEnabled = pInputEnable;
|
|
||||||
(*Channel)->OutputEnabled = pOutputEnable;
|
|
||||||
|
|
||||||
return *Channel;
|
return *Channel;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
// Automated Data Input/Output
|
bool CFunctionCore::SetChannelState( TChannel * Channel, const bool Ready )
|
||||||
bool CFunctionCore::LinkChannel( const char * ChannelName, const char * LinkFunctionName, const char * LinkChannelName, bool Bidirectional )
|
|
||||||
{
|
{
|
||||||
TChannel * OutChannel = NULL;
|
TChannelLink * LinkChannel;
|
||||||
CFunctionCore * InFunction = NULL;
|
|
||||||
TChannel * InChannel = NULL;
|
// Validate
|
||||||
|
if (!Channel)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Update state
|
||||||
|
Channel->Ready = Ready;
|
||||||
|
if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Update Channel '%s' - Ready:%s",
|
||||||
|
ProcessName, Name, Channel->Name, ((Ready)? "Yes" : "No") );
|
||||||
|
|
||||||
|
// Update linked channels
|
||||||
|
LinkChannel = Channel->FirstLink;
|
||||||
|
while (LinkChannel) {
|
||||||
|
LinkChannel->Function->ChannelStateEvent( LinkChannel->Channel, Channel->Ref, Ready );
|
||||||
|
LinkChannel = LinkChannel->Next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool CFunctionCore::ChannelStateEvent( TChannel * Channel, const char * SourceRef, const bool Ready )
|
||||||
|
{
|
||||||
|
TChannelLink * LinkChannel;
|
||||||
|
|
||||||
|
if (!Channel)
|
||||||
|
return false;
|
||||||
|
if (!(LinkChannel = GetLinkChannel( Channel, SourceRef )))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Update Link Channel '%s'-->'%s' - Ready:%s",
|
||||||
|
ProcessName, Name, Channel->Name, LinkChannel->Channel->Ref, ((Ready)? "Yes" : "No") );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Automated Data Input/Output
|
||||||
|
bool CFunctionCore::LinkChannel( const char * ChannelName, const char * LinkFunctionName, const char * LinkChannelName, bool Input, bool Output )
|
||||||
|
{
|
||||||
|
TChannel * Channel = NULL;
|
||||||
|
CFunctionCore * LinkFunction = NULL;
|
||||||
|
TChannel * LinkChannel = NULL;
|
||||||
TChannelLink ** LinkedChannel = NULL;
|
TChannelLink ** LinkedChannel = NULL;
|
||||||
|
|
||||||
// Check if Channels & Function exist
|
// Check if Channels & Function exist
|
||||||
if (!(OutChannel = GetChannel( ChannelName )) ||
|
if (!(Channel = GetChannel( ChannelName )) ||
|
||||||
!(InFunction = Application->GetFunction( LinkFunctionName )) ||
|
!(LinkFunction = Application->GetFunction( LinkFunctionName )) ||
|
||||||
!(InChannel = InFunction->GetChannel( LinkChannelName )) ) {
|
!(LinkChannel = LinkFunction->GetChannel( LinkChannelName )) ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if linked Channel exists
|
// Check if linked Channel exists
|
||||||
LinkedChannel = &(OutChannel->FirstLink);
|
LinkedChannel = &(Channel->FirstLink);
|
||||||
while (*LinkedChannel && (((*LinkedChannel)->Function != InFunction) || strcmp( (*LinkedChannel)->Name, LinkChannelName ) )) {
|
while (*LinkedChannel && ((*LinkedChannel)->Channel == LinkChannel))
|
||||||
LinkedChannel = &((*LinkedChannel)->Next);
|
LinkedChannel = &((*LinkedChannel)->Next);
|
||||||
}
|
|
||||||
|
|
||||||
// Create if not found
|
|
||||||
if (!*LinkedChannel)
|
if (!*LinkedChannel)
|
||||||
{
|
|
||||||
// Create
|
|
||||||
*LinkedChannel = new TChannelLink;
|
*LinkedChannel = new TChannelLink;
|
||||||
|
|
||||||
// Set Parameters
|
// Set Parameters
|
||||||
(*LinkedChannel)->Function = InFunction;
|
(*LinkedChannel)->Function = LinkFunction;
|
||||||
(*LinkedChannel)->Name = strdup( LinkChannelName );
|
(*LinkedChannel)->Channel = LinkChannel;
|
||||||
sprintf( (*LinkedChannel)->Ref, "%s/%s", LinkFunctionName, LinkChannelName );
|
(*LinkedChannel)->Input = Input;
|
||||||
|
(*LinkedChannel)->Output = Output;
|
||||||
|
|
||||||
// Log Event
|
// Log Event
|
||||||
if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Output Linked - '%s/%s' --> '%s/%s'",
|
if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Forward Channel Linked - '%s'-->'%s' - In:%s, Out:%s",
|
||||||
ProcessName, Name, Name, ChannelName, LinkFunctionName, LinkChannelName );
|
ProcessName, Name, Channel->Ref, (*LinkedChannel)->Channel->Ref, ((Input)? "Yes" : "No"), ((Output)? "Yes" : "No") );
|
||||||
}
|
|
||||||
|
|
||||||
// Link return direction as well
|
// Find Linked channel on remote function
|
||||||
if (Bidirectional) {
|
LinkedChannel = &(LinkChannel->FirstLink);
|
||||||
return InFunction->LinkChannel( LinkChannelName, Name, ChannelName, false );
|
while (*LinkedChannel && ((*LinkedChannel)->Channel == Channel))
|
||||||
}
|
LinkedChannel = &((*LinkedChannel)->Next);
|
||||||
|
if (!*LinkedChannel)
|
||||||
|
*LinkedChannel = new TChannelLink;
|
||||||
|
|
||||||
|
// Set Parameters
|
||||||
|
(*LinkedChannel)->Function = this;
|
||||||
|
(*LinkedChannel)->Channel = Channel;
|
||||||
|
(*LinkedChannel)->Input = Output;
|
||||||
|
(*LinkedChannel)->Output = Input;
|
||||||
|
|
||||||
|
// Log Event
|
||||||
|
if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Reverse Channel Linked - '%s'-->'%s' - In:%s, Out:%s",
|
||||||
|
ProcessName, Name, LinkChannel->Ref, (*LinkedChannel)->Channel->Ref, ((Output)? "Yes" : "No"), ((Input)? "Yes" : "No") );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -274,9 +308,8 @@ 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->InputEnabled) {
|
else if (!Channel->Ready) {
|
||||||
// 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 input disabled",
|
|
||||||
ProcessName, Name, ((SourceRef && *SourceRef)? SourceRef : "(Any)"), ChannelName );
|
ProcessName, Name, ((SourceRef && *SourceRef)? SourceRef : "(Any)"), ChannelName );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -316,7 +349,7 @@ int CFunctionCore::Output( const char * ChannelName, const char * TargetRef, con
|
|||||||
|
|
||||||
int CFunctionCore::Output( const TChannel * Channel, const char * TargetRef, const bool SourceRef, const char * Data, int Len, int OutputFormat )
|
int CFunctionCore::Output( const TChannel * Channel, const char * TargetRef, const bool SourceRef, const char * Data, int Len, int OutputFormat )
|
||||||
{
|
{
|
||||||
TChannelLink * OutChannel = NULL;
|
TChannelLink * LinkChannel = NULL;
|
||||||
int TempLen = 0;
|
int TempLen = 0;
|
||||||
int OutLen = 0;
|
int OutLen = 0;
|
||||||
|
|
||||||
@@ -325,27 +358,20 @@ int CFunctionCore::Output( const TChannel * Channel, const char * TargetRef, con
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if enabled
|
|
||||||
if (!Channel->OutputEnabled) {
|
|
||||||
if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Channel '%s' - Output rejected, Channel output disabled",
|
|
||||||
ProcessName, Name, Channel->Name, ((TargetRef && *TargetRef)? TargetRef : "(All)") );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log event
|
// Log event
|
||||||
if (Log) Log->Output( LogLevel, dlHigh, ((!OutputFormat)? LogOutput : OutputFormat), Data, Len, "%s/%s: Channel '%s' - OUT:",
|
if (Log) Log->Output( LogLevel, dlHigh, ((!OutputFormat)? LogOutput : OutputFormat), Data, Len, "%s/%s: Channel '%s'->'%s' - OUT:",
|
||||||
ProcessName, Name, Channel->Name, ((TargetRef && *TargetRef)? TargetRef : "(All)") );
|
ProcessName, Name, Channel->Name, ((TargetRef && *TargetRef)? TargetRef : "(All)") );
|
||||||
|
|
||||||
// Pass output to all linked inputs
|
// Pass output to all linked inputs
|
||||||
if (Len == -1)
|
if (Len == -1)
|
||||||
Len = strlen( Data );
|
Len = strlen( Data );
|
||||||
OutChannel = Channel->FirstLink;
|
LinkChannel = Channel->FirstLink;
|
||||||
while (OutChannel) {
|
while (LinkChannel) {
|
||||||
if (!TargetRef || !*TargetRef || !strcasecmp( TargetRef, OutChannel->Ref )) {
|
if (!TargetRef || !*TargetRef || !strcasecmp( TargetRef, LinkChannel->Channel->Ref )) {
|
||||||
TempLen = OutChannel->Function->Input( OutChannel->Name, ((SourceRef)? Channel->Ref : NULL), Data, Len );
|
TempLen = LinkChannel->Function->Input( LinkChannel->Channel->Name, ((SourceRef)? Channel->Ref : NULL), Data, Len );
|
||||||
OutLen = (TempLen > OutLen)? TempLen : OutLen;
|
OutLen = (TempLen > OutLen)? TempLen : OutLen;
|
||||||
}
|
}
|
||||||
OutChannel = OutChannel->Next;
|
LinkChannel = LinkChannel->Next;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return processed bytes
|
// Return processed bytes
|
||||||
|
|||||||
@@ -30,10 +30,7 @@ struct SChannel
|
|||||||
char * Name = NULL;
|
char * Name = NULL;
|
||||||
char * Ref = NULL;
|
char * Ref = NULL;
|
||||||
|
|
||||||
TChannelLink * FirstLink = NULL; // List of channels from which input can be received
|
TChannelLink * FirstLink = NULL; // List of channels linked for input/output
|
||||||
|
|
||||||
bool InputEnabled = NULL; // Can Channel receive input
|
|
||||||
bool OutputEnabled = NULL; // Can channel receive output
|
|
||||||
|
|
||||||
bool Ready = false; // Channel ready to receive input
|
bool Ready = false; // Channel ready to receive input
|
||||||
|
|
||||||
@@ -44,8 +41,10 @@ struct SChannel
|
|||||||
struct SChannelLink
|
struct SChannelLink
|
||||||
{
|
{
|
||||||
CFunctionCore * Function = NULL;
|
CFunctionCore * Function = NULL;
|
||||||
char * Name = NULL;
|
TChannel * Channel = NULL;
|
||||||
char * Ref = NULL;
|
|
||||||
|
bool Input = false;
|
||||||
|
bool Output = false;
|
||||||
|
|
||||||
SChannelLink * Next = NULL;
|
SChannelLink * Next = NULL;
|
||||||
};
|
};
|
||||||
@@ -84,6 +83,13 @@ protected:
|
|||||||
Channel = Channel->Next;
|
Channel = Channel->Next;
|
||||||
return Channel;
|
return Channel;
|
||||||
}
|
}
|
||||||
|
inline TChannelLink * GetLinkChannel( TChannel * Channel, const char * LinkRef ) {
|
||||||
|
if (!Channel || !LinkRef ) return NULL;
|
||||||
|
SChannelLink * LinkChannel = Channel->FirstLink;
|
||||||
|
while (LinkChannel && strcmp( LinkRef, LinkChannel->Channel->Ref ))
|
||||||
|
LinkChannel = LinkChannel->Next;
|
||||||
|
return LinkChannel;
|
||||||
|
}
|
||||||
|
|
||||||
// Data Input/Output
|
// Data Input/Output
|
||||||
virtual int Output( const TChannel * Channel, const char * TargetRef, const bool SourceRef, const char * Data, int Len, int OutputFormat = loNone );
|
virtual int Output( const TChannel * Channel, const char * TargetRef, const bool SourceRef, const char * Data, int Len, int OutputFormat = loNone );
|
||||||
@@ -106,34 +112,17 @@ 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 pInputEnable = true, const bool pOutputEnabled = true );
|
virtual TChannel * AddChannel( const char * ChannelName, const bool Ready );
|
||||||
inline bool SetChannelOutEnable( const char * ChannelName, const bool pOutputEnable ) {
|
|
||||||
TChannel * Channel = GetChannel( ChannelName );
|
virtual bool SetChannelState( TChannel * Channel, const bool Ready );
|
||||||
if (!Channel) return false;
|
virtual bool ChannelStateEvent( TChannel * Channel, const char * SourceRef, const bool Ready );
|
||||||
Channel->OutputEnabled = pOutputEnable;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
inline bool SetChannelInEnable( const char * ChannelName, const bool pInputEnable ) {
|
|
||||||
TChannel * Channel = GetChannel( ChannelName );
|
|
||||||
if (!Channel) return false;
|
|
||||||
Channel->InputEnabled = pInputEnable;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
inline bool isInputEnabled( const char * ChannelName ) {
|
|
||||||
TChannel * Channel = GetChannel( ChannelName );
|
|
||||||
return ((Channel)? Channel->InputEnabled : false);
|
|
||||||
}
|
|
||||||
inline bool isOutputEnabled( const char * ChannelName ) {
|
|
||||||
TChannel * Channel = GetChannel( ChannelName );
|
|
||||||
return ((Channel)? Channel->OutputEnabled : false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 );
|
||||||
virtual int Input( const char * ChannelName, const char * SourceRef, const char * Data, int Len = -1 );
|
virtual int Input( const char * ChannelName, const char * SourceRef, const char * Data, int Len = -1 );
|
||||||
|
|
||||||
// Automated Data Input/Output
|
// Automated Data Input/Output
|
||||||
virtual bool LinkChannel( const char * ChannelName, const char * LinkFunctionName, const char * LinkChannelName, bool Bidirectional );
|
virtual bool LinkChannel( const char * ChannelName, const char * LinkFunctionName, const char * LinkChannelName, bool Input, bool Output );
|
||||||
virtual bool Process() = 0;
|
virtual bool Process() = 0;
|
||||||
|
|
||||||
friend class CApplication;
|
friend class CApplication;
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ THandle * CSelectableBare::CreateHandle( const char * HandleName, bool CreateCh
|
|||||||
|
|
||||||
// Create Matching Channel
|
// Create Matching Channel
|
||||||
if (CreateChannel) {
|
if (CreateChannel) {
|
||||||
(*Handle)->Channel = AddChannel( HandleName );
|
(*Handle)->Channel = AddChannel( HandleName, false );
|
||||||
}
|
}
|
||||||
|
|
||||||
return *Handle;
|
return *Handle;
|
||||||
@@ -218,6 +218,31 @@ bool CSelectableBare::ClearHandle( THandle * Handle )
|
|||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool CSelectableBare::ChangeState( THandle * Handle, EConnectState State )
|
||||||
|
{
|
||||||
|
bool Ready;
|
||||||
|
|
||||||
|
// Validate
|
||||||
|
if (!Handle || (Handle->State == State))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Set Call back
|
||||||
|
if (Handle->StateCallback[ (int)State ])
|
||||||
|
(Handle->StateCallback[ (int)State ])( this, Handle, State );
|
||||||
|
|
||||||
|
// Change state
|
||||||
|
Handle->State = State;
|
||||||
|
|
||||||
|
// Update Channel
|
||||||
|
if (Handle->Channel) {
|
||||||
|
Ready = ((Handle->State == csOpen) || (Handle->State == csDataWaiting));
|
||||||
|
if (Handle->Channel->Ready != Ready)
|
||||||
|
SetChannelState( Handle->Channel, Ready );
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CSelectableBare::SetCallback( THandle * Handle, EConnectState pState, FHandleCallback pCallback )
|
bool CSelectableBare::SetCallback( THandle * Handle, EConnectState pState, FHandleCallback pCallback )
|
||||||
{
|
{
|
||||||
// Validate
|
// Validate
|
||||||
@@ -356,6 +381,7 @@ int CSelectableBare::Open( THandle * Handle, bool DelayResolve )
|
|||||||
{
|
{
|
||||||
THandle * NewHandle = NULL;
|
THandle * NewHandle = NULL;
|
||||||
|
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
if (!Handle || (Handle->Type == ctNone)) {
|
if (!Handle || (Handle->Type == ctNone)) {
|
||||||
return -1;
|
return -1;
|
||||||
@@ -391,11 +417,11 @@ int CSelectableBare::Open( THandle * Handle, bool DelayResolve )
|
|||||||
Selector->Add( Handle->FD, true, false, Handle, this );
|
Selector->Add( Handle->FD, true, false, Handle, this );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set state
|
|
||||||
ChangeState( Handle, csOpen );
|
|
||||||
|
|
||||||
// Set timer (for re-open or auto-close)
|
// Set timer (for re-open or auto-close)
|
||||||
SetStartTime( &Handle->LastAction );
|
SetStartTime( &Handle->LastAction );
|
||||||
|
|
||||||
|
// Set state
|
||||||
|
ChangeState( Handle, csOpen );
|
||||||
return (NewHandle)? NewHandle->FD : -1;
|
return (NewHandle)? NewHandle->FD : -1;
|
||||||
};
|
};
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -411,7 +437,16 @@ bool CSelectableBare::Close( THandle * Handle, bool QuickReopen )
|
|||||||
|
|
||||||
// Close Handle
|
// Close Handle
|
||||||
Fail = (close( Handle->FD ))? true : false;
|
Fail = (close( Handle->FD ))? true : false;
|
||||||
ChangeState( Handle, ((Fail)? csFailed : csClosed) );
|
|
||||||
|
// Remove from Select List
|
||||||
|
if (!Fail && Selector) {
|
||||||
|
if (Handle->Type != ctUDPremote) {
|
||||||
|
Selector->Remove( Handle->FD, true, true );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset FD
|
||||||
|
Handle->FD = ((Fail)? Handle->FD : -1);
|
||||||
|
|
||||||
// Start timer (for re-open)
|
// Start timer (for re-open)
|
||||||
if (QuickReopen)
|
if (QuickReopen)
|
||||||
@@ -423,15 +458,8 @@ bool CSelectableBare::Close( THandle * Handle, bool QuickReopen )
|
|||||||
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - %s",
|
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - %s",
|
||||||
ProcessName, Name, Handle->Name, ((Fail)? "failed" : "closed") );
|
ProcessName, Name, Handle->Name, ((Fail)? "failed" : "closed") );
|
||||||
|
|
||||||
// Remove from Select List
|
// Set State
|
||||||
if (!Fail && Selector) {
|
ChangeState( Handle, ((Fail)? csFailed : csClosed) );
|
||||||
if (Handle->Type != ctUDPremote) {
|
|
||||||
Selector->Remove( Handle->FD, true, true );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset FD
|
|
||||||
Handle->FD = ((Fail)? Handle->FD : -1);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -695,9 +723,9 @@ 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->InputEnabled) {
|
else if (!Channel->Ready) {
|
||||||
// Channel disabled
|
// Channel disabled
|
||||||
if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Channel '%s'->'%s' - Input rejected, Channel input disabled",
|
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 );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -632,6 +632,7 @@ THandle * CSelectableCore::OpenUNIXserverSocket( THandle * Handle )
|
|||||||
// Set state
|
// Set state
|
||||||
close( Handle->FD );
|
close( Handle->FD );
|
||||||
Handle->FD = -1;
|
Handle->FD = -1;
|
||||||
|
|
||||||
ChangeState( Handle, csFailed );
|
ChangeState( Handle, csFailed );
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
@@ -646,6 +647,7 @@ THandle * CSelectableCore::OpenUNIXserverSocket( THandle * Handle )
|
|||||||
// Set state
|
// Set state
|
||||||
close( Handle->FD );
|
close( Handle->FD );
|
||||||
Handle->FD = -1;
|
Handle->FD = -1;
|
||||||
|
|
||||||
ChangeState( Handle, csFailed );
|
ChangeState( Handle, csFailed );
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
@@ -729,11 +731,10 @@ THandle * CSelectableCore::OpenUNIXclientSocket( THandle * Handle )
|
|||||||
|
|
||||||
// Close socket
|
// Close socket
|
||||||
close( Handle->FD );
|
close( Handle->FD );
|
||||||
ChangeState( Handle, csFailed );
|
Handle->FD = -1;
|
||||||
Handle->AddressFailed = true;
|
Handle->AddressFailed = true;
|
||||||
|
|
||||||
// Reset Handle
|
ChangeState( Handle, csFailed );
|
||||||
Handle->FD = -1;
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -978,11 +979,13 @@ THandle * CSelectableCore::OpenUDPserverSocket( THandle * Handle, bool DelayReso
|
|||||||
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Failed to bind UDP socket [%s:%s] (%s)",
|
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Failed to bind UDP socket [%s:%s] (%s)",
|
||||||
ProcessName, Name, Handle->Name, Handle->HostName, Handle->PortName, strerror(errno) );
|
ProcessName, Name, Handle->Name, Handle->HostName, Handle->PortName, strerror(errno) );
|
||||||
|
|
||||||
// Set state
|
// Close handle
|
||||||
close( Handle->FD );
|
close( Handle->FD );
|
||||||
Handle->FD = -1;
|
Handle->FD = -1;
|
||||||
ChangeState( Handle, csFailed );
|
|
||||||
Handle->AddressFailed = true;
|
Handle->AddressFailed = true;
|
||||||
|
|
||||||
|
// Change state
|
||||||
|
ChangeState( Handle, csFailed );
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1173,11 +1176,12 @@ THandle * CSelectableCore::OpenTCPserverSocket( THandle * Handle, bool DelayReso
|
|||||||
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Failed to bind TCP Server socket [%s:%s] (%s)",
|
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Failed to bind TCP Server socket [%s:%s] (%s)",
|
||||||
ProcessName, Name, Handle->Name, Handle->HostName, Handle->PortName, strerror(errno) );
|
ProcessName, Name, Handle->Name, Handle->HostName, Handle->PortName, strerror(errno) );
|
||||||
|
|
||||||
// Set state
|
// Close handle
|
||||||
close( Handle->FD );
|
close( Handle->FD );
|
||||||
Handle->FD = -1;
|
Handle->FD = -1;
|
||||||
ChangeState( Handle, csFailed );
|
|
||||||
Handle->AddressFailed = true;
|
Handle->AddressFailed = true;
|
||||||
|
|
||||||
|
ChangeState( Handle, csFailed );
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1188,11 +1192,12 @@ THandle * CSelectableCore::OpenTCPserverSocket( THandle * Handle, bool DelayReso
|
|||||||
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Failed to listen on TCP Server socket [%s:%s] (%s)",
|
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Failed to listen on TCP Server socket [%s:%s] (%s)",
|
||||||
ProcessName, Name, Handle->Name, Handle->HostName, Handle->PortName, strerror(errno) );
|
ProcessName, Name, Handle->Name, Handle->HostName, Handle->PortName, strerror(errno) );
|
||||||
|
|
||||||
// Set state
|
// Close handle
|
||||||
close( Handle->FD );
|
close( Handle->FD );
|
||||||
Handle->FD = -1;
|
Handle->FD = -1;
|
||||||
ChangeState( Handle, csFailed );
|
|
||||||
Handle->AddressFailed = true;
|
Handle->AddressFailed = true;
|
||||||
|
|
||||||
|
ChangeState( Handle, csFailed );
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1362,9 +1367,10 @@ THandle * CSelectableCore::OpenTCPclientSocket( THandle * Handle, bool DelayReso
|
|||||||
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)",
|
||||||
ProcessName, Name, Handle->Name, Handle->HostName, Handle->PortName, strerror(errno) );
|
ProcessName, Name, Handle->Name, Handle->HostName, Handle->PortName, strerror(errno) );
|
||||||
|
|
||||||
// Set State
|
// Close handle
|
||||||
close( Handle->FD );
|
close( Handle->FD );
|
||||||
Handle->FD = -1;
|
Handle->FD = -1;
|
||||||
|
|
||||||
ChangeState( Handle, csFailed );
|
ChangeState( Handle, csFailed );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -1413,11 +1419,10 @@ THandle * CSelectableCore::OpenTCPclientSocket( THandle * Handle, bool DelayReso
|
|||||||
|
|
||||||
// Close socket
|
// Close socket
|
||||||
close( Handle->FD );
|
close( Handle->FD );
|
||||||
ChangeState( Handle, csFailed );
|
Handle->FD = -1;
|
||||||
Handle->AddressFailed = true;
|
Handle->AddressFailed = true;
|
||||||
|
|
||||||
// Reset Handle
|
ChangeState( Handle, csFailed );
|
||||||
Handle->FD = -1;
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1515,7 +1520,16 @@ bool CSelectableCore::Close( THandle * Handle, bool QuickReopen )
|
|||||||
} else {
|
} else {
|
||||||
Fail = (close( Handle->FD ))? true : false;
|
Fail = (close( Handle->FD ))? true : false;
|
||||||
}
|
}
|
||||||
ChangeState( Handle, ((Fail)? csFailed : csClosed) );
|
|
||||||
|
// Remove from Select List
|
||||||
|
if (!Fail && Selector) {
|
||||||
|
if (Handle->Type != ctUDPremote) {
|
||||||
|
Selector->Remove( Handle->FD, true, true );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset FD
|
||||||
|
Handle->FD = ((Fail)? Handle->FD : -1);
|
||||||
|
|
||||||
// Start timer (for re-open)
|
// Start timer (for re-open)
|
||||||
if (QuickReopen)
|
if (QuickReopen)
|
||||||
@@ -1599,15 +1613,8 @@ bool CSelectableCore::Close( THandle * Handle, bool QuickReopen )
|
|||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Remove from Select List
|
// Change State
|
||||||
if (!Fail && Selector) {
|
ChangeState( Handle, ((Fail)? csFailed : csClosed) );
|
||||||
if (Handle->Type != ctUDPremote) {
|
|
||||||
Selector->Remove( Handle->FD, true, true );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset FD
|
|
||||||
Handle->FD = ((Fail)? Handle->FD : -1);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -194,6 +194,7 @@ protected:
|
|||||||
// Managing File Handles
|
// Managing File Handles
|
||||||
bool RemoveHandle( THandle * Handle );
|
bool RemoveHandle( THandle * Handle );
|
||||||
bool DestroyHandle( THandle * Handle );
|
bool DestroyHandle( THandle * Handle );
|
||||||
|
bool ChangeState( THandle * Handle, EConnectState State );
|
||||||
|
|
||||||
// Get Parameters
|
// Get Parameters
|
||||||
inline int GetFD( const char * HandleName ) {
|
inline int GetFD( const char * HandleName ) {
|
||||||
@@ -201,15 +202,6 @@ protected:
|
|||||||
return ((Handle)? Handle->FD : -1);
|
return ((Handle)? Handle->FD : -1);
|
||||||
};
|
};
|
||||||
|
|
||||||
// General fucntions
|
|
||||||
inline bool ChangeState( THandle * Handle, EConnectState State ) {
|
|
||||||
if (!Handle || (Handle->State == State)) return false;
|
|
||||||
if (Handle->StateCallback[ (int)State ])
|
|
||||||
(Handle->StateCallback[ (int)State ])( this, Handle, State );
|
|
||||||
Handle->State = State;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mutual Operations
|
// Mutual Operations
|
||||||
int ReadFromFD( int FD, char * Data, int MaxLen );
|
int ReadFromFD( int FD, char * Data, int MaxLen );
|
||||||
int WriteToFD( int FD, const char * Data, int Len, bool Force );
|
int WriteToFD( int FD, const char * Data, int Len, bool Force );
|
||||||
@@ -230,19 +222,17 @@ public:
|
|||||||
virtual ~CSelectableBare();
|
virtual ~CSelectableBare();
|
||||||
|
|
||||||
// Configuration
|
// Configuration
|
||||||
virtual bool Init( CDataMember * FunctionConfig ) = 0;
|
virtual bool Init( CDataMember * FunctionConfig ) = 0;
|
||||||
|
|
||||||
// Finding Handles
|
// Finding Handles
|
||||||
inline THandle * GetHandle( const char * HandleName )
|
inline THandle * GetHandle( const char * HandleName ) {
|
||||||
{
|
|
||||||
if (!HandleName) return NULL;
|
if (!HandleName) return NULL;
|
||||||
THandle * Handle = FirstHandle;
|
THandle * Handle = FirstHandle;
|
||||||
while ( Handle && strcmp( HandleName, Handle->Name ))
|
while ( Handle && strcmp( HandleName, Handle->Name ))
|
||||||
Handle = Handle->Next;
|
Handle = Handle->Next;
|
||||||
return Handle;
|
return Handle;
|
||||||
}
|
}
|
||||||
inline THandle * GetHandle( int FD )
|
inline THandle * GetHandle( int FD ) {
|
||||||
{
|
|
||||||
if (FD < 0) return NULL;
|
if (FD < 0) return NULL;
|
||||||
THandle * Handle = FirstHandle;
|
THandle * Handle = FirstHandle;
|
||||||
while ( Handle && (FD != Handle->FD))
|
while ( Handle && (FD != Handle->FD))
|
||||||
@@ -263,7 +253,7 @@ public:
|
|||||||
bool ClearHandle( THandle * Handle );
|
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 );
|
||||||
virtual bool Read( THandle * Handle );
|
virtual bool Read( THandle * Handle );
|
||||||
virtual bool Write( THandle * Handle );
|
virtual bool Write( THandle * Handle );
|
||||||
|
|||||||
Reference in New Issue
Block a user