Merge branch 'master' into ModbusCore
This commit is contained in:
@@ -27,9 +27,9 @@ CApplication::CApplication( EDebugLevel pLogLevel )
|
|||||||
// Set signal handlers
|
// Set signal handlers
|
||||||
ConfigureSignalHandlers();
|
ConfigureSignalHandlers();
|
||||||
|
|
||||||
DefinitionFile = NULL;
|
DefinitionFile = NULL;
|
||||||
ConfigFile = NULL;
|
ConfigFile = NULL;
|
||||||
AddressFile = NULL;
|
AddressFile = NULL;
|
||||||
|
|
||||||
// Create output logger
|
// Create output logger
|
||||||
Log = new CLogCore( stdout );
|
Log = new CLogCore( stdout );
|
||||||
@@ -420,9 +420,9 @@ bool CApplication::Run( bool TerminateOnError )
|
|||||||
{
|
{
|
||||||
ProcessTerminate = !FunctionItem->Function->Process();
|
ProcessTerminate = !FunctionItem->Function->Process();
|
||||||
if (TerminateOnError) {
|
if (TerminateOnError) {
|
||||||
if (ProcessTerminate)
|
if (ProcessTerminate) // Raise terminate flag for other processes
|
||||||
Terminate = true;
|
Terminate = true;
|
||||||
if (FunctionItem->Function->WaitToTerminate && !ProcessTerminate)
|
if (FunctionItem->Function->WaitToTerminate && !ProcessTerminate) // If needed, allow process to terminate cleanly
|
||||||
CleanTerminate = false;
|
CleanTerminate = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -131,10 +131,8 @@ CDataMember * CDataMember::CreateChild( const char * Name, const int Len )
|
|||||||
bool CDataMember::Clear()
|
bool CDataMember::Clear()
|
||||||
{
|
{
|
||||||
// Clear value
|
// Clear value
|
||||||
if (Value) {
|
if (Value)
|
||||||
free( Value );
|
free( Value );
|
||||||
Value = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear children
|
// Clear children
|
||||||
while (FirstChild) {
|
while (FirstChild) {
|
||||||
@@ -142,7 +140,9 @@ bool CDataMember::Clear()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Reset value
|
// Reset value
|
||||||
Type = jtNull;
|
Type = jtNull;
|
||||||
|
Value = NULL;
|
||||||
|
Len = 0;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|||||||
250
DateTimeCore.cpp
250
DateTimeCore.cpp
@@ -20,24 +20,24 @@ static char ReturnStr[30];
|
|||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
// Set current time on real-time clock
|
|
||||||
bool SetTime( unsigned char Hours, unsigned char Minutes, unsigned char Seconds )
|
bool SetTime( unsigned char Hours, unsigned char Minutes, unsigned char Seconds )
|
||||||
{
|
{
|
||||||
struct tm NewTime;
|
struct tm NewTime;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
struct timezone tz;
|
struct timezone tz;
|
||||||
|
|
||||||
// Get current date and time
|
// Get current Epoch (UTC)
|
||||||
gettimeofday( &tv, &tz);
|
gettimeofday( &tv, &tz);
|
||||||
|
|
||||||
// Change to new time
|
// Convert to local time
|
||||||
localtime_r( &tv.tv_sec, &NewTime );
|
localtime_r( &tv.tv_sec, &NewTime );
|
||||||
|
|
||||||
|
// Set new time (keep date as is)
|
||||||
NewTime.tm_hour = Hours;
|
NewTime.tm_hour = Hours;
|
||||||
NewTime.tm_min = Minutes;
|
NewTime.tm_min = Minutes;
|
||||||
NewTime.tm_sec = Seconds;
|
NewTime.tm_sec = Seconds;
|
||||||
|
|
||||||
// Convert back
|
// Convert back from local time to epoch time
|
||||||
tv.tv_sec = mktime( &NewTime );
|
tv.tv_sec = mktime( &NewTime );
|
||||||
tv.tv_usec = 0;
|
tv.tv_usec = 0;
|
||||||
|
|
||||||
@@ -47,43 +47,24 @@ bool SetTime( unsigned char Hours, unsigned char Minutes, unsigned char Seconds
|
|||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
// Get current time from real-time clock
|
|
||||||
bool GetTime( unsigned char &Hours, unsigned char &Minutes, unsigned char &Seconds )
|
|
||||||
{
|
|
||||||
struct tm CurrentTime;
|
|
||||||
time_t UTC;
|
|
||||||
|
|
||||||
// Get current date and time
|
|
||||||
time( &UTC );
|
|
||||||
localtime_r( &UTC, &CurrentTime );
|
|
||||||
|
|
||||||
// Extract time
|
|
||||||
Hours = CurrentTime.tm_hour;
|
|
||||||
Minutes = CurrentTime.tm_min;
|
|
||||||
Seconds = CurrentTime.tm_sec;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// Set current date on real-time clock
|
|
||||||
bool SetDate( unsigned char Day, unsigned char Month, unsigned Year )
|
bool SetDate( unsigned char Day, unsigned char Month, unsigned Year )
|
||||||
{
|
{
|
||||||
struct tm NewDate;
|
struct tm NewDate;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
struct timezone tz;
|
struct timezone tz;
|
||||||
|
|
||||||
// Get current date and time
|
// Get current Epoch (UTC)
|
||||||
gettimeofday( &tv, &tz );
|
gettimeofday( &tv, &tz );
|
||||||
|
|
||||||
// Change to new time
|
// Convert to local time
|
||||||
localtime_r( &tv.tv_sec, &NewDate );
|
localtime_r( &tv.tv_sec, &NewDate );
|
||||||
|
|
||||||
|
// Set new date (keep time as is)
|
||||||
NewDate.tm_year = Year - 1900;
|
NewDate.tm_year = Year - 1900;
|
||||||
NewDate.tm_mon = Month - 1;
|
NewDate.tm_mon = Month - 1;
|
||||||
NewDate.tm_mday = Day;
|
NewDate.tm_mday = Day;
|
||||||
|
|
||||||
// Convert back
|
// Convert back from local time to epoch time
|
||||||
tv.tv_sec = mktime( &NewDate );
|
tv.tv_sec = mktime( &NewDate );
|
||||||
tv.tv_usec = 0;
|
tv.tv_usec = 0;
|
||||||
|
|
||||||
@@ -94,17 +75,70 @@ bool SetDate( unsigned char Day, unsigned char Month, unsigned Year )
|
|||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
// Get current data from real-time clock
|
bool SetDateTime( unsigned char Day, unsigned char Month, unsigned Year,
|
||||||
|
unsigned char Hours, unsigned char Minutes, unsigned char Seconds )
|
||||||
|
{
|
||||||
|
struct tm NewTime;
|
||||||
|
struct timeval tv;
|
||||||
|
struct timezone tz;
|
||||||
|
|
||||||
|
// Get current Epoch (UTC)
|
||||||
|
gettimeofday( &tv, &tz);
|
||||||
|
|
||||||
|
// Convert to local time
|
||||||
|
localtime_r( &tv.tv_sec, &NewTime );
|
||||||
|
|
||||||
|
// Set new date & time
|
||||||
|
NewTime.tm_year = Year - 1900;
|
||||||
|
NewTime.tm_mon = Month - 1;
|
||||||
|
NewTime.tm_mday = Day;
|
||||||
|
|
||||||
|
NewTime.tm_hour = Hours;
|
||||||
|
NewTime.tm_min = Minutes;
|
||||||
|
NewTime.tm_sec = Seconds;
|
||||||
|
|
||||||
|
// Convert back from local time to epoch time
|
||||||
|
tv.tv_sec = mktime( &NewTime );
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
|
||||||
|
// Set date and new time
|
||||||
|
settimeofday( &tv, &tz);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool GetTime( unsigned char &Hours, unsigned char &Minutes, unsigned char &Seconds )
|
||||||
|
{
|
||||||
|
struct tm CurrentTime;
|
||||||
|
time_t UTC;
|
||||||
|
|
||||||
|
// Get current UTC date and time
|
||||||
|
time( &UTC );
|
||||||
|
|
||||||
|
// Convert to local time
|
||||||
|
localtime_r( &UTC, &CurrentTime );
|
||||||
|
|
||||||
|
// Extract time only
|
||||||
|
Hours = CurrentTime.tm_hour;
|
||||||
|
Minutes = CurrentTime.tm_min;
|
||||||
|
Seconds = CurrentTime.tm_sec;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool GetDate( unsigned char &Day, unsigned char &Month, unsigned &Year )
|
bool GetDate( unsigned char &Day, unsigned char &Month, unsigned &Year )
|
||||||
{
|
{
|
||||||
struct tm CurrentDate;
|
struct tm CurrentDate;
|
||||||
time_t UTC;
|
time_t UTC;
|
||||||
|
|
||||||
// Get current date and time
|
// Get current UTC date and time
|
||||||
time( &UTC );
|
time( &UTC );
|
||||||
|
|
||||||
|
// Convert to local time
|
||||||
localtime_r( &UTC, &CurrentDate );
|
localtime_r( &UTC, &CurrentDate );
|
||||||
|
|
||||||
// Extract date
|
// Extract date only
|
||||||
Day = CurrentDate.tm_mday;
|
Day = CurrentDate.tm_mday;
|
||||||
Month = CurrentDate.tm_mon + 1;
|
Month = CurrentDate.tm_mon + 1;
|
||||||
Year = CurrentDate.tm_year + 1900;
|
Year = CurrentDate.tm_year + 1900;
|
||||||
@@ -113,7 +147,31 @@ bool GetDate( unsigned char &Day, unsigned char &Month, unsigned &Year )
|
|||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
// Get the current date in a string
|
bool GetDateTime( unsigned char &Day, unsigned char &Month, unsigned &Year,
|
||||||
|
unsigned char &Hours, unsigned char &Minutes, unsigned char &Seconds )
|
||||||
|
{
|
||||||
|
struct tm CurrentTime;
|
||||||
|
time_t UTC;
|
||||||
|
|
||||||
|
// Get current UTC date and time
|
||||||
|
time( &UTC );
|
||||||
|
|
||||||
|
// Convert to local time
|
||||||
|
localtime_r( &UTC, &CurrentTime );
|
||||||
|
|
||||||
|
// Extract Date & time
|
||||||
|
Day = CurrentTime.tm_mday;
|
||||||
|
Month = CurrentTime.tm_mon + 1;
|
||||||
|
Year = CurrentTime.tm_year + 1900;
|
||||||
|
|
||||||
|
Hours = CurrentTime.tm_hour;
|
||||||
|
Minutes = CurrentTime.tm_min;
|
||||||
|
Seconds = CurrentTime.tm_sec;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
char const * GetDateStr( const char * DateSeparator )
|
char const * GetDateStr( const char * DateSeparator )
|
||||||
{
|
{
|
||||||
unsigned char Day;
|
unsigned char Day;
|
||||||
@@ -172,12 +230,15 @@ char const * GetDateTimeStr( const char * DateSeparator, const char * TimeSepar
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
// Get current time from real-time clock
|
// Get current time from real-time clock
|
||||||
bool ReadTime( const time_t EpochTime, unsigned char &Hours, unsigned char &Minutes, unsigned char &Seconds )
|
bool ReadTime( const time_t EpochTime, bool LocalTime, unsigned char &Hours, unsigned char &Minutes, unsigned char &Seconds )
|
||||||
{
|
{
|
||||||
struct tm CurrentTime;
|
struct tm CurrentTime;
|
||||||
|
|
||||||
// Get current date and time
|
// Get current date and time
|
||||||
localtime_r( &EpochTime, &CurrentTime );
|
if (LocalTime)
|
||||||
|
localtime_r( &EpochTime, &CurrentTime );
|
||||||
|
else
|
||||||
|
gmtime_r( &EpochTime, &CurrentTime );
|
||||||
|
|
||||||
// Extract time
|
// Extract time
|
||||||
Hours = CurrentTime.tm_hour;
|
Hours = CurrentTime.tm_hour;
|
||||||
@@ -188,12 +249,15 @@ bool ReadTime( const time_t EpochTime, unsigned char &Hours, unsigned char &Minu
|
|||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool ReadDate( const time_t EpochTime, unsigned char &Day, unsigned char &Month, unsigned &Year )
|
bool ReadDate( const time_t EpochTime, bool LocalTime, unsigned char &Day, unsigned char &Month, unsigned &Year )
|
||||||
{
|
{
|
||||||
struct tm CurrentDate;
|
struct tm CurrentDate;
|
||||||
|
|
||||||
// Get current date and time
|
// Get current date and time
|
||||||
localtime_r( &EpochTime, &CurrentDate );
|
if (LocalTime)
|
||||||
|
localtime_r( &EpochTime, &CurrentDate );
|
||||||
|
else
|
||||||
|
gmtime_r( &EpochTime, &CurrentDate );
|
||||||
|
|
||||||
// Extract date
|
// Extract date
|
||||||
Day = CurrentDate.tm_mday;
|
Day = CurrentDate.tm_mday;
|
||||||
@@ -204,15 +268,118 @@ bool ReadDate( const time_t EpochTime, unsigned char &Day, unsigned char &Month,
|
|||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool ReadDateTime( const time_t EpochTime, bool LocalTime, unsigned char &Day, unsigned char &Month, unsigned &Year,
|
||||||
|
unsigned char &Hours, unsigned char &Minutes, unsigned char &Seconds )
|
||||||
|
{
|
||||||
|
struct tm CurrentTime;
|
||||||
|
|
||||||
|
// Get current date and time
|
||||||
|
if (LocalTime)
|
||||||
|
localtime_r( &EpochTime, &CurrentTime );
|
||||||
|
else
|
||||||
|
gmtime_r( &EpochTime, &CurrentTime );
|
||||||
|
|
||||||
|
// Extract time
|
||||||
|
Hours = CurrentTime.tm_hour;
|
||||||
|
Minutes = CurrentTime.tm_min;
|
||||||
|
Seconds = CurrentTime.tm_sec;
|
||||||
|
|
||||||
|
// Extract date
|
||||||
|
Day = CurrentTime.tm_mday;
|
||||||
|
Month = CurrentTime.tm_mon + 1;
|
||||||
|
Year = CurrentTime.tm_year + 1900;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Read components from date/time string
|
||||||
|
bool ReadTimeStr( const char *DateTimeStr, unsigned char &Hours, unsigned char &Minutes, unsigned char &Seconds, bool Maxtime )
|
||||||
|
{
|
||||||
|
int ItemsAssigned;
|
||||||
|
int TempDay;
|
||||||
|
int TempMonth;
|
||||||
|
int TempYear;
|
||||||
|
int TempHours = -1;
|
||||||
|
int TempMinutes = -1;
|
||||||
|
int TempSeconds = -1;
|
||||||
|
|
||||||
|
// Read string
|
||||||
|
ItemsAssigned = sscanf( DateTimeStr, "%d%*[/-]%d%*[/-]%d%*[ ]%d%*[:]%d%*[:]%d",
|
||||||
|
&TempYear, &TempMonth, &TempDay, &TempHours, &TempMinutes, &TempSeconds );
|
||||||
|
|
||||||
|
// Return Values
|
||||||
|
Hours = (TempHours != -1)? TempHours : (Maxtime)? 23 : 0;
|
||||||
|
Minutes = (TempMinutes != -1)? TempMinutes : (Maxtime)? 59 : 0;
|
||||||
|
Seconds = (TempSeconds != -1)? TempSeconds : (Maxtime)? 59 : 0;
|
||||||
|
|
||||||
|
// Check if success
|
||||||
|
return ((ItemsAssigned >= 3)? true : false);
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool ReadDateStr( const char *DateTimeStr, unsigned char &Day, unsigned char &Month, unsigned &Year )
|
||||||
|
{
|
||||||
|
int ItemsAssigned;
|
||||||
|
int TempDay;
|
||||||
|
int TempMonth;
|
||||||
|
int TempYear;
|
||||||
|
int TempHours = -1;
|
||||||
|
int TempMinutes = -1;
|
||||||
|
int TempSeconds = -1;
|
||||||
|
|
||||||
|
// Read string
|
||||||
|
ItemsAssigned = sscanf( DateTimeStr, "%d%*[/-]%d%*[/-]%d%*[ ]%d%*[:]%d%*[:]%d",
|
||||||
|
&TempYear, &TempMonth, &TempDay, &TempHours, &TempMinutes, &TempSeconds );
|
||||||
|
|
||||||
|
// Return Values
|
||||||
|
Day = TempDay;
|
||||||
|
Month = TempMonth;
|
||||||
|
Year = TempYear;
|
||||||
|
|
||||||
|
// Check if success
|
||||||
|
return ((ItemsAssigned >= 3)? true : false);
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool ReadDateTimeStr( const char *DateTimeStr, unsigned char &Day, unsigned char &Month, unsigned &Year,
|
||||||
|
unsigned char &Hours, unsigned char &Minutes, unsigned char &Seconds, bool Maxtime )
|
||||||
|
{
|
||||||
|
int ItemsAssigned;
|
||||||
|
int TempDay;
|
||||||
|
int TempMonth;
|
||||||
|
int TempYear;
|
||||||
|
int TempHours = -1;
|
||||||
|
int TempMinutes = -1;
|
||||||
|
int TempSeconds = -1;
|
||||||
|
|
||||||
|
// Read string
|
||||||
|
ItemsAssigned = sscanf( DateTimeStr, "%d%*[/-]%d%*[/-]%d%*[ ]%d%*[:]%d%*[:]%d",
|
||||||
|
&TempYear, &TempMonth, &TempDay, &TempHours, &TempMinutes, &TempSeconds );
|
||||||
|
|
||||||
|
// Return Values
|
||||||
|
Day = TempDay;
|
||||||
|
Month = TempMonth;
|
||||||
|
Year = TempYear;
|
||||||
|
|
||||||
|
Hours = (TempHours != -1)? TempHours : (Maxtime)? 23 : 0;
|
||||||
|
Minutes = (TempMinutes != -1)? TempMinutes : (Maxtime)? 59 : 0;
|
||||||
|
Seconds = (TempSeconds != -1)? TempSeconds : (Maxtime)? 59 : 0;
|
||||||
|
|
||||||
|
// Check if success
|
||||||
|
return ((ItemsAssigned >= 3)? true : false);
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
// Get the current date in a string
|
// Get the current date in a string
|
||||||
char const * BuildDateStr( const time_t EpochTime, const char * DateSeparator )
|
char const * BuildDateStr( const time_t EpochTime, bool LocalTime, const char * DateSeparator )
|
||||||
{
|
{
|
||||||
unsigned char Day;
|
unsigned char Day;
|
||||||
unsigned char Month;
|
unsigned char Month;
|
||||||
unsigned int Year;
|
unsigned int Year;
|
||||||
|
|
||||||
// Get Date
|
// Get Date
|
||||||
ReadDate( EpochTime, Day, Month, Year );
|
ReadDate( EpochTime, LocalTime, Day, Month, Year );
|
||||||
|
|
||||||
// Build String
|
// Build String
|
||||||
sprintf( ReturnStr, "%04d%s%02d%s%02d",
|
sprintf( ReturnStr, "%04d%s%02d%s%02d",
|
||||||
@@ -223,14 +390,14 @@ char const * BuildDateStr( const time_t EpochTime, const char * DateSeparator )
|
|||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
char const * BuildTimeStr( const time_t EpochTime, const char * TimeSeparator )
|
char const * BuildTimeStr( const time_t EpochTime, bool LocalTime, const char * TimeSeparator )
|
||||||
{
|
{
|
||||||
unsigned char Hours;
|
unsigned char Hours;
|
||||||
unsigned char Minutes;
|
unsigned char Minutes;
|
||||||
unsigned char Seconds;
|
unsigned char Seconds;
|
||||||
|
|
||||||
// Get Date & Time
|
// Get Date & Time
|
||||||
ReadTime( EpochTime, Hours, Minutes, Seconds );
|
ReadTime( EpochTime, LocalTime, Hours, Minutes, Seconds );
|
||||||
|
|
||||||
// Build String
|
// Build String
|
||||||
sprintf( ReturnStr, "%02d%s%02d%s%02d",
|
sprintf( ReturnStr, "%02d%s%02d%s%02d",
|
||||||
@@ -240,7 +407,7 @@ char const * BuildTimeStr( const time_t EpochTime, const char * TimeSeparator )
|
|||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
char const * BuildDateTimeStr( const time_t EpochTime, const char * DateSeparator, const char * TimeSeparator )
|
char const * BuildDateTimeStr( const time_t EpochTime, bool LocalTime, const char * DateSeparator, const char * TimeSeparator )
|
||||||
{
|
{
|
||||||
unsigned char Day;
|
unsigned char Day;
|
||||||
unsigned char Month;
|
unsigned char Month;
|
||||||
@@ -250,8 +417,7 @@ char const * BuildDateTimeStr( const time_t EpochTime, const char * DateSeparato
|
|||||||
unsigned char Seconds;
|
unsigned char Seconds;
|
||||||
|
|
||||||
// Get Date & Time
|
// Get Date & Time
|
||||||
ReadDate( EpochTime, Day, Month, Year );
|
ReadDateTime( EpochTime, LocalTime, Day, Month, Year, Hours, Minutes, Seconds );
|
||||||
ReadTime( EpochTime, Hours, Minutes, Seconds );
|
|
||||||
|
|
||||||
// Build String
|
// Build String
|
||||||
sprintf( ReturnStr, "%04d%s%02d%s%02d %02d%s%02d%s%02d",
|
sprintf( ReturnStr, "%04d%s%02d%s%02d %02d%s%02d%s%02d",
|
||||||
|
|||||||
@@ -17,11 +17,15 @@
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
// Get and set System Date and Time
|
// Get and set System Date and Time
|
||||||
bool SetTime( unsigned char Hours, unsigned char Minutes, unsigned char Seconds );
|
|
||||||
bool GetTime( unsigned char &Hours, unsigned char &Minutes, unsigned char &Seconds );
|
bool GetTime( unsigned char &Hours, unsigned char &Minutes, unsigned char &Seconds );
|
||||||
|
|
||||||
bool SetDate( unsigned char Day, unsigned char Month, unsigned Year );
|
|
||||||
bool GetDate( unsigned char &Day, unsigned char &Month, unsigned &Year );
|
bool GetDate( unsigned char &Day, unsigned char &Month, unsigned &Year );
|
||||||
|
bool GetDateTime( unsigned char &Day, unsigned char &Month, unsigned &Year,
|
||||||
|
unsigned char &Hours, unsigned char &Minutes, unsigned char &Seconds );
|
||||||
|
|
||||||
|
bool SetTime( unsigned char Hours, unsigned char Minutes, unsigned char Seconds );
|
||||||
|
bool SetDate( unsigned char Day, unsigned char Month, unsigned Year );
|
||||||
|
bool SetDateTime( unsigned char Day, unsigned char Month, unsigned Year,
|
||||||
|
unsigned char Hours, unsigned char Minutes, unsigned char Seconds );
|
||||||
|
|
||||||
char const * GetDateStr( const char * DateSeparator = "/" );
|
char const * GetDateStr( const char * DateSeparator = "/" );
|
||||||
char const * GetTimeStr( const char * TimeSeparator = ":" );
|
char const * GetTimeStr( const char * TimeSeparator = ":" );
|
||||||
@@ -29,12 +33,20 @@ char const * GetDateTimeStr( const char * DateSeparator = "/", const char * Tim
|
|||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool ReadTime( const time_t EpochTime, unsigned char &Hours, unsigned char &Minutes, unsigned char &Seconds );
|
// Build or interpret time data
|
||||||
bool ReadDate( const time_t EpochTime, unsigned char &Day, unsigned char &Month, unsigned &Year );
|
bool ReadTime( const time_t EpochTime, bool LocalTime, unsigned char &Hours, unsigned char &Minutes, unsigned char &Seconds );
|
||||||
|
bool ReadDate( const time_t EpochTime, bool LocalTime, unsigned char &Day, unsigned char &Month, unsigned &Year );
|
||||||
|
bool ReadDateTime( const time_t EpochTime, bool LocalTime, unsigned char &Day, unsigned char &Month, unsigned &Year,
|
||||||
|
unsigned char &Hours, unsigned char &Minutes, unsigned char &Seconds );
|
||||||
|
|
||||||
char const * BuildDateStr( const time_t EpochTime, const char * DateSeparator = "/" );
|
bool ReadTimeStr( const char *DateTimeStr, unsigned char &Hours, unsigned char &Minutes, unsigned char &Seconds, bool Maxtime );
|
||||||
char const * BuildTimeStr( const time_t EpochTime, const char * TimeSeparator = ":" );
|
bool ReadDateStr( const char *DateTimeStr, unsigned char &Day, unsigned char &Month, unsigned &Year );
|
||||||
char const * BuildDateTimeStr( const time_t EpochTime, const char * DateSeparator = "/", const char * TimeSeparator = ":" );
|
bool ReadDateTimeStr( const char *DateTimeStr, unsigned char &Day, unsigned char &Month, unsigned &Year,
|
||||||
|
unsigned char &Hours, unsigned char &Minutes, unsigned char &Seconds, bool Maxtime );
|
||||||
|
|
||||||
|
char const * BuildDateStr( const time_t EpochTime, bool LocalTime, const char * DateSeparator = "/" );
|
||||||
|
char const * BuildTimeStr( const time_t EpochTime, bool LocalTime, const char * TimeSeparator = ":" );
|
||||||
|
char const * BuildDateTimeStr( const time_t EpochTime, bool LocalTime, const char * DateSeparator = "/", const char * TimeSeparator = ":" );
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
// Global Vars
|
// Global Vars
|
||||||
extern char * ProcessName;
|
extern char * ProcessName;
|
||||||
extern CApplication * Application;
|
//extern CApplication * Application;
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -30,20 +30,9 @@ extern CApplication * Application;
|
|||||||
CDeviceCore::CDeviceCore( const char * pName, const char * pType ) : CFunctionCore( pName, pType )
|
CDeviceCore::CDeviceCore( const char * pName, const char * pType ) : CFunctionCore( pName, pType )
|
||||||
{
|
{
|
||||||
// Polling
|
// Polling
|
||||||
PollCycle = 0;
|
|
||||||
PollStep = 0;
|
|
||||||
PollInterval = 250;
|
|
||||||
SetStartTime( &PollWait );
|
SetStartTime( &PollWait );
|
||||||
|
|
||||||
WaitingForReply = false;
|
|
||||||
ReplyTimeout = 200;
|
|
||||||
InvalidReply = false;
|
|
||||||
|
|
||||||
PollRetry = 0;
|
|
||||||
MaxRetries = 3;
|
|
||||||
|
|
||||||
// Data Structures
|
// Data Structures
|
||||||
DeviceInit = true;
|
|
||||||
ConfigTypes = new CDataMember();
|
ConfigTypes = new CDataMember();
|
||||||
ValueTree = new CDataMember();
|
ValueTree = new CDataMember();
|
||||||
JSONparse = new CJSONparse();
|
JSONparse = new CJSONparse();
|
||||||
@@ -69,7 +58,6 @@ CDeviceCore::~CDeviceCore()
|
|||||||
bool CDeviceCore::Init( CDataMember * FunctionConfig )
|
bool CDeviceCore::Init( CDataMember * FunctionConfig )
|
||||||
{
|
{
|
||||||
char * PersistFile = NULL;
|
char * PersistFile = NULL;
|
||||||
char * ConfigName = NULL;
|
|
||||||
CDataMember * PollConfig = NULL;
|
CDataMember * PollConfig = NULL;
|
||||||
int IntVal1;
|
int IntVal1;
|
||||||
int IntVal2;
|
int IntVal2;
|
||||||
@@ -80,18 +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", CH_ready );
|
||||||
if (!(DeviceChannel = GetChannel( "Device" )))
|
else
|
||||||
DeviceChannel = AddChannel( "Device", true, true );
|
SetChannelInState( CmdChannel, CH_ready );
|
||||||
if (!(EventChannel = GetChannel( "Event" )))
|
|
||||||
EventChannel = AddChannel( "Event", true, true );
|
|
||||||
|
|
||||||
// Get configuration
|
if (!(DeviceChannel = GetChannel( "Device" )))
|
||||||
if ((Config = FunctionConfig->GetChild( "Config", true )) && Config->isString()) {
|
DeviceChannel = AddChannel( "Device", CH_ready );
|
||||||
ConfigName = (char*)FunctionConfig->GetChStr( "Config" );
|
else
|
||||||
Config = Application->Config->GetChild( ConfigName, true );
|
SetChannelInState( DeviceChannel, CH_ready );
|
||||||
}
|
|
||||||
if (Config->isNull()) Config->SetObject();
|
if (!(EventChannel = GetChannel( "Event" )))
|
||||||
|
EventChannel = AddChannel( "Event", CH_ready );
|
||||||
|
else
|
||||||
|
SetChannelInState( EventChannel, CH_ready );
|
||||||
|
|
||||||
// Load Polling configuration
|
// Load Polling configuration
|
||||||
PollConfig = Config->GetChild( "Polling", true );
|
PollConfig = Config->GetChild( "Polling", true );
|
||||||
@@ -442,6 +431,7 @@ bool CDeviceCore::SetPollParam( int pPollInterval )
|
|||||||
|
|
||||||
bool CDeviceCore::SetReplyParam( int pReplyTimeout, int pMaxRetries )
|
bool CDeviceCore::SetReplyParam( int pReplyTimeout, int pMaxRetries )
|
||||||
{
|
{
|
||||||
|
DefReplyTimeout = pReplyTimeout;
|
||||||
ReplyTimeout = pReplyTimeout;
|
ReplyTimeout = pReplyTimeout;
|
||||||
MaxRetries = pMaxRetries;
|
MaxRetries = pMaxRetries;
|
||||||
return true;
|
return true;
|
||||||
@@ -466,12 +456,13 @@ bool CDeviceCore::DeviceOnline( TDevice * Device, bool Online )
|
|||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
void CDeviceCore::SetWaitForReply()
|
void CDeviceCore::SetWaitForReply( int CustomTimeout )
|
||||||
{
|
{
|
||||||
// Start timer
|
// Start timer
|
||||||
SetStartTime( &PollWait );
|
SetStartTime( &PollWait );
|
||||||
|
|
||||||
// Set flag
|
// Set flag
|
||||||
|
ReplyTimeout = (CustomTimeout >= 0)? CustomTimeout : DefReplyTimeout;
|
||||||
WaitingForReply = true;
|
WaitingForReply = true;
|
||||||
InvalidReply = false;
|
InvalidReply = false;
|
||||||
}
|
}
|
||||||
@@ -1622,7 +1613,7 @@ bool CDeviceCore::GetCmdParam( const char * Start, char * Param, char ** NextPar
|
|||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
int CDeviceCore::HandleCommand( const char *ChannelName, const char * Data, const int MaxLen )
|
int CDeviceCore::HandleCommand( const char *ChannelName, const char * SourceRef, const char * Data, const int MaxLen )
|
||||||
{
|
{
|
||||||
int Len;
|
int Len;
|
||||||
char Value[50];
|
char Value[50];
|
||||||
@@ -1671,7 +1662,7 @@ int CDeviceCore::HandleCommand( const char *ChannelName, const char * Data, cons
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
strcat( OutputStr, "\n" );
|
strcat( OutputStr, "\n" );
|
||||||
Output( ChannelName, OutputStr, strlen(OutputStr) );
|
Output( ChannelName, NULL, true, OutputStr, strlen(OutputStr) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1680,7 +1671,7 @@ int CDeviceCore::HandleCommand( const char *ChannelName, const char * Data, cons
|
|||||||
Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' Get",
|
Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' Get",
|
||||||
ProcessName, Name, ChannelName, OutputStr );
|
ProcessName, Name, ChannelName, OutputStr );
|
||||||
strcat( OutputStr, "\n" );
|
strcat( OutputStr, "\n" );
|
||||||
Output( ChannelName, OutputStr, strlen(OutputStr) );
|
Output( ChannelName, NULL, true, OutputStr, strlen(OutputStr) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!strcasecmp( "set", Value ))
|
else if (!strcasecmp( "set", Value ))
|
||||||
@@ -1717,7 +1708,7 @@ int CDeviceCore::HandleCommand( const char *ChannelName, const char * Data, cons
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
sprintf( OutputStr, "> set %s,%s = %s\n", Device->Name, Param->Name, Value );
|
sprintf( OutputStr, "> set %s,%s = %s\n", Device->Name, Param->Name, Value );
|
||||||
Output( ChannelName, OutputStr );
|
Output( ChannelName, NULL, true, OutputStr );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1726,7 +1717,7 @@ int CDeviceCore::HandleCommand( const char *ChannelName, const char * Data, cons
|
|||||||
Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' Set",
|
Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' Set",
|
||||||
ProcessName, Name, ChannelName, OutputStr );
|
ProcessName, Name, ChannelName, OutputStr );
|
||||||
strcat( OutputStr, "\n" );
|
strcat( OutputStr, "\n" );
|
||||||
Output( ChannelName, OutputStr, strlen(OutputStr) );
|
Output( ChannelName, NULL, true, OutputStr, strlen(OutputStr) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!strcasecmp( "status", Value ))
|
else if (!strcasecmp( "status", Value ))
|
||||||
@@ -1746,7 +1737,7 @@ int CDeviceCore::HandleCommand( const char *ChannelName, const char * Data, cons
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
sprintf( OutputStr, "> %s - %s\n", Device->Name, ((Device->Online)? "online" : "offline") );
|
sprintf( OutputStr, "> %s - %s\n", Device->Name, ((Device->Online)? "online" : "offline") );
|
||||||
Output( ChannelName, OutputStr );
|
Output( ChannelName, NULL, true, OutputStr );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Report error
|
// Report error
|
||||||
@@ -1754,7 +1745,7 @@ int CDeviceCore::HandleCommand( const char *ChannelName, const char * Data, cons
|
|||||||
Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' Status",
|
Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s' Status",
|
||||||
ProcessName, Name, ChannelName, OutputStr );
|
ProcessName, Name, ChannelName, OutputStr );
|
||||||
strcat( OutputStr, "\n" );
|
strcat( OutputStr, "\n" );
|
||||||
Output( ChannelName, OutputStr, strlen(OutputStr) );
|
Output( ChannelName, NULL, true, OutputStr, strlen(OutputStr) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1764,7 +1755,7 @@ int CDeviceCore::HandleCommand( const char *ChannelName, const char * Data, cons
|
|||||||
Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s', %s%s",
|
Log->Message( LogLevel, dlMedium, "%s/%s: Channel '%s', %s%s",
|
||||||
ProcessName, Name, ChannelName, Value, OutputStr );
|
ProcessName, Name, ChannelName, Value, OutputStr );
|
||||||
strcat( OutputStr, " (comma separated values)\n" );
|
strcat( OutputStr, " (comma separated values)\n" );
|
||||||
Output( ChannelName, OutputStr, strlen(OutputStr) );
|
Output( ChannelName, NULL, true, OutputStr, strlen(OutputStr) );
|
||||||
}
|
}
|
||||||
return MaxLen;
|
return MaxLen;
|
||||||
}
|
}
|
||||||
@@ -1819,7 +1810,7 @@ bool CDeviceCore::EventOutput( TDeviceParam * Param, bool Force )
|
|||||||
default :
|
default :
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Output( Param->EventChannel, Message, strlen(Message) );
|
Output( Param->EventChannel, NULL, true, Message, strlen(Message) );
|
||||||
|
|
||||||
// Reset timer
|
// Reset timer
|
||||||
if (Param->EventInterval) {
|
if (Param->EventInterval) {
|
||||||
|
|||||||
38
DeviceCore.h
38
DeviceCore.h
@@ -121,11 +121,10 @@ class CDeviceCore : public CFunctionCore
|
|||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
// Configuration
|
// Configuration
|
||||||
CDataMember * Config = NULL;
|
CDataMember * ConfigTypes = NULL;
|
||||||
CDataMember * ConfigTypes = NULL;
|
CDataMember * ValueTree = NULL;
|
||||||
CDataMember * ValueTree = NULL;
|
CJSONparse * JSONparse = NULL;
|
||||||
CJSONparse * JSONparse = NULL;
|
bool DeviceInit = false; // Initialise device on start
|
||||||
bool DeviceInit = false;
|
|
||||||
|
|
||||||
// Devices & Type
|
// Devices & Type
|
||||||
TDevice * FirstDeviceType = NULL;
|
TDevice * FirstDeviceType = NULL;
|
||||||
@@ -133,24 +132,25 @@ protected:
|
|||||||
TDevice * ActiveDevice = NULL;
|
TDevice * ActiveDevice = NULL;
|
||||||
|
|
||||||
// Standard channels
|
// Standard channels
|
||||||
TChannel * DeviceChannel = NULL;
|
TChannel * DeviceChannel = NULL;
|
||||||
TChannel * CmdChannel = NULL;
|
TChannel * CmdChannel = NULL;
|
||||||
TChannel * EventChannel = NULL;
|
TChannel * EventChannel = NULL;
|
||||||
|
|
||||||
// Poll
|
// Poll
|
||||||
int PollCycle; // Device Polling state, e.g. Init, Connect, Run, Disonnect, Shutdown
|
int PollCycle = 0; // Device Polling state, e.g. Init, Connect, Run, Disonnect, Shutdown
|
||||||
int PollStep; // Position in polling sequence
|
int PollStep = 0; // Position in polling sequence
|
||||||
timeval PollWait; // Time at which last poll was done
|
timeval PollWait = {0,0}; // Time at which last poll was done
|
||||||
long PollInterval; // Minimum delay between polls
|
long PollInterval = 250; // Minimum delay between polls
|
||||||
|
|
||||||
// Reply
|
// Reply
|
||||||
bool WaitingForReply; // Command sent, waiting for reply
|
bool WaitingForReply = false; // Command sent, waiting for reply
|
||||||
bool InvalidReply; // Invalid reply received
|
bool InvalidReply = false; // Invalid reply received
|
||||||
long ReplyTimeout; // Max waiting time for reply
|
long DefReplyTimeout = 500; // Default Max waiting time for reply
|
||||||
|
long ReplyTimeout = 500; // Max waiting time for reply
|
||||||
|
|
||||||
// Retry
|
// Retry
|
||||||
int PollRetry; // No of polling retries that has timed out
|
int PollRetry = 0; // No of polling retries that has timed out
|
||||||
int MaxRetries; // Max allowed retries
|
int MaxRetries = 3; // Max allowed retries
|
||||||
|
|
||||||
// Manage Devices
|
// Manage Devices
|
||||||
bool DestroyDevice( TDevice ** Device );
|
bool DestroyDevice( TDevice ** Device );
|
||||||
@@ -309,7 +309,7 @@ protected:
|
|||||||
virtual bool DeviceOnline( TDevice * Device, bool Online );
|
virtual bool DeviceOnline( TDevice * Device, bool Online );
|
||||||
|
|
||||||
// Handle Reply Timing
|
// Handle Reply Timing
|
||||||
virtual void SetWaitForReply();
|
virtual void SetWaitForReply( int CustomTimeout = -1 );
|
||||||
virtual void ValidReplyReceived();
|
virtual void ValidReplyReceived();
|
||||||
virtual bool CheckReplyTimeout();
|
virtual bool CheckReplyTimeout();
|
||||||
|
|
||||||
@@ -389,7 +389,7 @@ public:
|
|||||||
|
|
||||||
// Handle Interface Commands
|
// Handle Interface Commands
|
||||||
bool GetCmdParam( const char * Start, char * Param, char ** NextParam );
|
bool GetCmdParam( const char * Start, char * Param, char ** NextParam );
|
||||||
int HandleCommand( const char *ChannelName, const char * Data, const int MaxLen );
|
int HandleCommand( const char *ChannelName, const char * SourceRef, const char * Data, const int MaxLen );
|
||||||
|
|
||||||
// Command Text Interfaces
|
// Command Text Interfaces
|
||||||
bool SetValue( TDeviceParam * Param, const char * Value, const int Len, bool Force );
|
bool SetValue( TDeviceParam * Param, const char * Value, const int Len, bool Force );
|
||||||
|
|||||||
@@ -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, CH_ready );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set Parameters
|
// Set Parameters
|
||||||
@@ -260,7 +260,7 @@ int CFileCore::WriteToFD( int FD, const char * Data, int Len )
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
// Manual Data Input/Output
|
// Manual Data Input/Output
|
||||||
int CFileCore::Input( const char * ChannelName, const char * Data, int Len )
|
int CFileCore::Input( const char * ChannelName, const char * SourceRef, const char * Data, int Len )
|
||||||
{
|
{
|
||||||
TFileHandle * FileHandle = NULL;
|
TFileHandle * FileHandle = NULL;
|
||||||
int BytesWritten = 0;
|
int BytesWritten = 0;
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ public:
|
|||||||
virtual bool SetFilePersistence( TFileHandle * FileHandle, bool Persistent, int PersistTimeout );
|
virtual bool SetFilePersistence( TFileHandle * FileHandle, bool Persistent, int PersistTimeout );
|
||||||
|
|
||||||
// Data Input
|
// Data Input
|
||||||
virtual int Input( const char * ChannelName, const char * Data, int Len = -1 );
|
virtual int Input( const char * ChannelName, const char * SourceRef, const char * Data, int Len = -1 );
|
||||||
|
|
||||||
// Processing data
|
// Processing data
|
||||||
virtual bool Process();
|
virtual bool Process();
|
||||||
|
|||||||
@@ -1,222 +0,0 @@
|
|||||||
/*
|
|
||||||
* FunctionCore.h
|
|
||||||
*
|
|
||||||
* Created on: 18 May 2016
|
|
||||||
* Author: wentzelc
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef REDACORE_FUNCTIONCORE_H_
|
|
||||||
#define REDACORE_FUNCTIONCORE_H_
|
|
||||||
|
|
||||||
// Standard C/C++ Libraries
|
|
||||||
/* none */
|
|
||||||
|
|
||||||
// redA Libraries
|
|
||||||
#include "LogCore.h"
|
|
||||||
#include "DataTreeCore.h"
|
|
||||||
#include "CharBufferCore.h"
|
|
||||||
#include "ItemBufferCore.h"
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// Preview
|
|
||||||
typedef struct SChannel TChannel;
|
|
||||||
typedef struct SChannelLink TChannelLink;
|
|
||||||
typedef struct SProcessBuffer TProcessBuffer;
|
|
||||||
typedef struct SProcessItem TProcessItem;
|
|
||||||
|
|
||||||
class CFunctionCore;
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
struct SChannel
|
|
||||||
{
|
|
||||||
char * Name;
|
|
||||||
|
|
||||||
TChannelLink * FirstInput;
|
|
||||||
TChannelLink * FirstOutput;
|
|
||||||
|
|
||||||
bool InputEnabled;
|
|
||||||
bool OutputEnabled;
|
|
||||||
|
|
||||||
TProcessBuffer * InputBuffer;
|
|
||||||
|
|
||||||
TChannel * Next;
|
|
||||||
};
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
struct SChannelLink
|
|
||||||
{
|
|
||||||
CFunctionCore * Function;
|
|
||||||
char * Name;
|
|
||||||
|
|
||||||
SChannelLink * Next;
|
|
||||||
};
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
struct SProcessBuffer
|
|
||||||
{
|
|
||||||
// Process buffer
|
|
||||||
char * Name; // Name of buffer;
|
|
||||||
CItemBufferCore Buffer; // Message buffer
|
|
||||||
unsigned long LastRefNo; // Last RefNo for item
|
|
||||||
|
|
||||||
// Input parameters
|
|
||||||
bool PassthroughCallback; // Send Callback once processed message has been passed on, else once processed
|
|
||||||
|
|
||||||
// Output parameters
|
|
||||||
TChannel * OutputChannel; // Channel to which to pass buffer output
|
|
||||||
bool OutputCallback; // Expect callback on output?
|
|
||||||
|
|
||||||
TProcessBuffer * Next; // Next buffer in list
|
|
||||||
};
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
struct SProcessItem
|
|
||||||
{
|
|
||||||
// Input Parameters
|
|
||||||
TChannel * SourceChannel;
|
|
||||||
char * SourceRef;
|
|
||||||
bool SourceCallback;
|
|
||||||
|
|
||||||
// Processing Parameters
|
|
||||||
bool Processed;
|
|
||||||
bool Completed;
|
|
||||||
|
|
||||||
// Output Parameters
|
|
||||||
timeval CallbackTimer;
|
|
||||||
TChannelLink FirstOutput;
|
|
||||||
|
|
||||||
// Input Data
|
|
||||||
void * DataIn;
|
|
||||||
int DataInLen;
|
|
||||||
|
|
||||||
// Output Data
|
|
||||||
void * DataOut;
|
|
||||||
int DateOutLen;
|
|
||||||
};
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
class CFunctionCore_not_used
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
// Function Definition
|
|
||||||
char * Name;
|
|
||||||
char * Type;
|
|
||||||
|
|
||||||
// Configuration
|
|
||||||
CDataTree * DataTree;
|
|
||||||
TDataMember * ConfigMember;
|
|
||||||
TDataMember * LinkConfigMember;
|
|
||||||
|
|
||||||
// Channels
|
|
||||||
TChannel * FirstChannel;
|
|
||||||
|
|
||||||
// Processing Queues
|
|
||||||
TProcessBuffer * FirstProcessBuffer;
|
|
||||||
|
|
||||||
// Logging
|
|
||||||
CLogCore * Log;
|
|
||||||
EDebugLevel LogLevel;
|
|
||||||
int LogOutput;
|
|
||||||
|
|
||||||
// Stored Output
|
|
||||||
char * StoredOutput;
|
|
||||||
int StoredOutputLen;
|
|
||||||
|
|
||||||
// Manage Channel
|
|
||||||
inline TChannel * GetChannel( const char * Name ) {
|
|
||||||
if (!Name) return NULL;
|
|
||||||
TChannel * Channel = FirstChannel;
|
|
||||||
while (Channel && strcmp( Name, Channel->Name ))
|
|
||||||
Channel = Channel->Next;
|
|
||||||
return Channel;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load configuration
|
|
||||||
virtual bool LoadConfigData();
|
|
||||||
virtual bool LoadChannelLinkData();
|
|
||||||
|
|
||||||
// Data Input/Output
|
|
||||||
virtual int Output( const TChannel * Channel, const char * Data, int Len );
|
|
||||||
virtual bool PullInput( TChannel * Channel );
|
|
||||||
|
|
||||||
// Processing Queue
|
|
||||||
TProcessItem * CreateProcessItem();
|
|
||||||
|
|
||||||
public:
|
|
||||||
// Life cycle
|
|
||||||
CFunctionCore_not_used( const char * pName, const char * Type );
|
|
||||||
virtual ~CFunctionCore_not_used();
|
|
||||||
|
|
||||||
// Load Configuration
|
|
||||||
virtual bool Init();
|
|
||||||
|
|
||||||
bool InitConfig( const char * pConfigPath );
|
|
||||||
bool InitConfig( TDataMember * pConfigMember );
|
|
||||||
|
|
||||||
bool InitChannelLinks( const char * pLinkConfigPath );
|
|
||||||
bool InitChannelLinks( TDataMember *pLinkConfigMember );
|
|
||||||
|
|
||||||
// Set Parameters Manually
|
|
||||||
bool SetLogParam( EDebugLevel pDebugLevel, int pOutputDisplay );
|
|
||||||
bool SetLogLevel( EDebugLevel pDebugLevel );
|
|
||||||
|
|
||||||
// Miscellaneous
|
|
||||||
inline const char * GetName() { return Name; };
|
|
||||||
inline const char * GetType() { return Type; };
|
|
||||||
|
|
||||||
// Manage Channels
|
|
||||||
virtual TChannel * AddChannel( const char * ChannelName, const bool pInputEnable = true, const bool pOutputEnabled = true );
|
|
||||||
inline bool SetChannelOutEnable( const char * ChannelName, const bool pOutputEnable ) {
|
|
||||||
TChannel * Channel = GetChannel( ChannelName );
|
|
||||||
if (!Channel) return false;
|
|
||||||
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
|
|
||||||
virtual int Output( const char * ChannelName, const char * Data, int Len = -1 );
|
|
||||||
virtual int Input( const char * ChannelName, const char * Data, int Len = -1 );
|
|
||||||
|
|
||||||
// Pulling Data Input <- Output
|
|
||||||
virtual bool PullInput( const char * ChannelName );
|
|
||||||
virtual bool PullOutput( const char * ChannelName, char ** Data, int * Len = NULL );
|
|
||||||
|
|
||||||
// Manages Process Buffers
|
|
||||||
TProcessBuffer * CreateProcessBuffer( const char * Name );
|
|
||||||
TProcessBuffer * GetProcessBuffer( const char * Name );
|
|
||||||
|
|
||||||
TProcessItem * CreateProcessItem( const char * BufferName );
|
|
||||||
TProcessItem * GetProcessItem( const char BufferName, const int Ref );
|
|
||||||
bool DestroyProcessItem( const char * BufferName, const int Ref );
|
|
||||||
|
|
||||||
// Queued Output
|
|
||||||
virtual bool OutputMessage( TChannel * SourceChannel, const char * TargetChannelName, const int RefNo, bool Callback, const char * Data, int Len = -1 );
|
|
||||||
virtual bool OutputMessageCallback( TChannel * SourceChannel, const char * TargetChannelName, const int RefNo, const bool Success, const char * Error );
|
|
||||||
virtual bool InputMessage( TChannel * SourceChannel, const char * TargetChannelName, const int RefNo, bool Callback, const char * Data, int Len = -1 );
|
|
||||||
virtual bool InputMessageCancel( TChannel * SourceChannel, const char * TargetChannelName, const int RefNo );
|
|
||||||
|
|
||||||
// Automated Data Input/Output
|
|
||||||
virtual bool LinkInputChannel( const char * ChannelName, const char * OutFunctionName, const char * OutChannelName, bool Bidirectional );
|
|
||||||
virtual bool LinkOutputChannel( const char * ChannelName, const char * InFunctionName, const char * InChannelName, bool Bidirectional );
|
|
||||||
virtual bool Process() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#endif /* REDACORE_FUNCTIONCORE_H_ */
|
|
||||||
452
FunctionCore.cpp
452
FunctionCore.cpp
@@ -30,9 +30,8 @@ extern CApplication * Application;
|
|||||||
CFunctionCore::CFunctionCore( const char * pName, const char * pType ) : Type( pType )
|
CFunctionCore::CFunctionCore( const char * pName, const char * pType ) : Type( pType )
|
||||||
{
|
{
|
||||||
// Set name
|
// Set name
|
||||||
if (pName) {
|
if (pName)
|
||||||
Name = strdup( pName );
|
Name = strdup( pName );
|
||||||
}
|
|
||||||
|
|
||||||
// Logging
|
// Logging
|
||||||
Log = Application->Log;
|
Log = Application->Log;
|
||||||
@@ -44,35 +43,19 @@ CFunctionCore::CFunctionCore( const char * pName, const char * pType ) : Type( p
|
|||||||
CFunctionCore::~CFunctionCore()
|
CFunctionCore::~CFunctionCore()
|
||||||
{
|
{
|
||||||
TChannel * NextChannel = NULL;
|
TChannel * NextChannel = NULL;
|
||||||
TChannelLink * NextLinkedChannel = NULL;
|
|
||||||
|
|
||||||
// Destroy Channels
|
// Destroy Channels
|
||||||
while (FirstChannel)
|
while (FirstChannel)
|
||||||
{
|
{
|
||||||
|
// Destroy Linked Channels
|
||||||
|
while (FirstChannel->FirstLink)
|
||||||
|
UnlinkChannel( FirstChannel->Name, FirstChannel->FirstLink->Function->Name, FirstChannel->FirstLink->Channel->Name );
|
||||||
|
|
||||||
// Destroy Parameters
|
// Destroy Parameters
|
||||||
if (FirstChannel->Name) {
|
if (FirstChannel->Name)
|
||||||
free( FirstChannel->Name );
|
free( FirstChannel->Name );
|
||||||
}
|
if (FirstChannel->Ref)
|
||||||
|
free( FirstChannel->Ref );
|
||||||
// Destroy Linked Inputs
|
|
||||||
while (FirstChannel->FirstInput) {
|
|
||||||
if (FirstChannel->FirstInput->Name) {
|
|
||||||
free( FirstChannel->FirstInput->Name );
|
|
||||||
}
|
|
||||||
NextLinkedChannel = FirstChannel->FirstInput->Next;
|
|
||||||
delete FirstChannel->FirstInput;
|
|
||||||
FirstChannel->FirstInput = NextLinkedChannel;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destroy Linked Outputs
|
|
||||||
while (FirstChannel->FirstOutput) {
|
|
||||||
if (FirstChannel->FirstOutput->Name) {
|
|
||||||
free( FirstChannel->FirstOutput->Name );
|
|
||||||
}
|
|
||||||
NextLinkedChannel = FirstChannel->FirstOutput->Next;
|
|
||||||
delete FirstChannel->FirstOutput;
|
|
||||||
FirstChannel->FirstOutput = NextLinkedChannel;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destroy Channel
|
// Destroy Channel
|
||||||
NextChannel = FirstChannel->Next;
|
NextChannel = FirstChannel->Next;
|
||||||
@@ -95,11 +78,15 @@ bool CFunctionCore::Init( CDataMember * FunctionConfig )
|
|||||||
CDataMember * ChannelConfig;
|
CDataMember * ChannelConfig;
|
||||||
EDebugLevel pLogLevel;
|
EDebugLevel pLogLevel;
|
||||||
int pLogOutput;
|
int pLogOutput;
|
||||||
|
char * ConfigName = NULL;
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
if (!FunctionConfig )
|
if (!FunctionConfig )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// Set Type
|
||||||
|
FunctionConfig->SetChStr( "Type", Type );
|
||||||
|
|
||||||
// Configure Logging/Debugging
|
// Configure Logging/Debugging
|
||||||
LogConfig = FunctionConfig->GetChild( "Log", true );
|
LogConfig = FunctionConfig->GetChild( "Log", true );
|
||||||
pLogLevel = Log->ReadLogLevel( LogConfig );
|
pLogLevel = Log->ReadLogLevel( LogConfig );
|
||||||
@@ -108,16 +95,17 @@ 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(), CH_off );
|
||||||
if (ChannelConfig->GetName()) {
|
|
||||||
AddChannel( ChannelConfig->GetName(),
|
|
||||||
ChannelConfig->GetChBool( "InputEnabled", true, true ),
|
|
||||||
ChannelConfig->GetChBool( "OutputEnabled", false, true ));
|
|
||||||
}
|
|
||||||
ChannelConfig = ChannelConfig->GetNextPeer();
|
ChannelConfig = ChannelConfig->GetNextPeer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get main configuration
|
||||||
|
if ((Config = FunctionConfig->GetChild( "Config", true )) && Config->isString()) {
|
||||||
|
ConfigName = (char*)FunctionConfig->GetChStr( "Config" );
|
||||||
|
Config = Application->Config->GetChild( ConfigName, true );
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -142,10 +130,11 @@ bool CFunctionCore::InitChannelLinks( CDataMember * LinkConfig )
|
|||||||
while (FunctionMember)
|
while (FunctionMember)
|
||||||
{
|
{
|
||||||
// Get Parameters
|
// Get Parameters
|
||||||
LinkOutputChannel( 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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -173,7 +162,7 @@ bool CFunctionCore::SetLogLevel( EDebugLevel pDebugLevel )
|
|||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
TChannel * CFunctionCore::AddChannel( const char * ChannelName, const bool pInputEnable, const bool pOutputEnable )
|
TChannel * CFunctionCore::AddChannel( const char * ChannelName, const EChannelState State )
|
||||||
{
|
{
|
||||||
TChannel ** Channel = NULL;
|
TChannel ** Channel = NULL;
|
||||||
|
|
||||||
@@ -195,166 +184,263 @@ 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 );
|
||||||
|
(*Channel)->InState = State;
|
||||||
|
(*Channel)->OutState = CH_off;
|
||||||
|
|
||||||
// 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', In:%s, Out:%s",
|
||||||
ProcessName, Name, ChannelName );
|
ProcessName, Name, ChannelName, (*Channel)->Ref,
|
||||||
|
ChannelStateName[(*Channel)->InState], ChannelStateName[(*Channel)->OutState]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set parameters
|
|
||||||
(*Channel)->InputEnabled = pInputEnable;
|
|
||||||
(*Channel)->OutputEnabled = pOutputEnable;
|
|
||||||
|
|
||||||
return *Channel;
|
return *Channel;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
// Automated Data Input/Output
|
bool CFunctionCore::SetChannelInState( TChannel * Channel, const EChannelState State )
|
||||||
bool CFunctionCore::LinkInputChannel( const char * ChannelName, const char * OutFunctionName, const char * OutChannelName, bool Bidirectional )
|
|
||||||
{
|
{
|
||||||
CFunctionCore * OutFunction = NULL;
|
EChannelState OldState = Channel->InState;
|
||||||
TChannel * Channel = NULL;
|
TChannelLink * LinkChannel;
|
||||||
TChannelLink ** LinkedChannel = NULL;
|
|
||||||
|
|
||||||
// Get Channel
|
// Validate
|
||||||
if (!(OutFunction = Application->GetFunction( OutFunctionName )) || !(Channel = GetChannel( ChannelName ))) {
|
if (!Channel)
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
// Check if linked Channel exists
|
// Update state
|
||||||
LinkedChannel = &(Channel->FirstInput);
|
Channel->InState = State;
|
||||||
while (*LinkedChannel && (((*LinkedChannel)->Function != OutFunction) || strcmp( (*LinkedChannel)->Name, OutChannelName ) )) {
|
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Update Channel '%s' - In:%s",
|
||||||
LinkedChannel = &((*LinkedChannel)->Next);
|
ProcessName, Name, Channel->Ref, ChannelStateName[State] );
|
||||||
}
|
|
||||||
|
|
||||||
// Create if not found
|
// Update linked channels
|
||||||
if (!*LinkedChannel)
|
LinkChannel = Channel->FirstLink;
|
||||||
{
|
while (LinkChannel) {
|
||||||
// Create
|
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Update Link Channel '%s'-->'%s' - In:%s",
|
||||||
*LinkedChannel = new TChannelLink;
|
ProcessName, Name, Channel->Ref, LinkChannel->Channel->Ref, ChannelStateName[State] );
|
||||||
|
|
||||||
// Set Parameters
|
// Trigger Linked Channel Events
|
||||||
(*LinkedChannel)->Function = OutFunction;
|
LinkChannel->Function->UpdateChannelOutState( LinkChannel->Channel );
|
||||||
(*LinkedChannel)->Name = strdup( OutChannelName );
|
LinkChannel->Function->ChannelStateEvent( LinkChannel->Channel, Channel->Ref, OldState, State );
|
||||||
|
|
||||||
// Log Event
|
LinkChannel = LinkChannel->Next;
|
||||||
if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Input Linked - '%s'/'%s' <-- '%s'/'%s'",
|
|
||||||
ProcessName, Name, Name, ChannelName, OutFunction->GetName(), OutChannelName );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Link Return direction as well
|
|
||||||
if (Bidirectional) {
|
|
||||||
return OutFunction->LinkInputChannel( OutChannelName, Name, ChannelName, false );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CFunctionCore::LinkOutputChannel( const char * ChannelName, const char * InFunctionName, const char * InChannelName, bool Bidirectional )
|
bool CFunctionCore::UpdateChannelOutState( TChannel * Channel )
|
||||||
{
|
{
|
||||||
TChannel * OutChannel = NULL;
|
TChannelLink * LinkChannel;
|
||||||
CFunctionCore * InFunction = NULL;
|
EChannelState OutState;
|
||||||
TChannel * InChannel = NULL;
|
|
||||||
|
// Check if channel Out state changed
|
||||||
|
OutState = CH_off;
|
||||||
|
LinkChannel = Channel->FirstLink;
|
||||||
|
while (LinkChannel) {
|
||||||
|
if (LinkChannel->Channel->InState > OutState)
|
||||||
|
OutState = LinkChannel->Channel->InState;
|
||||||
|
LinkChannel = LinkChannel->Next;
|
||||||
|
}
|
||||||
|
if (OutState != Channel->OutState) {
|
||||||
|
// Update output state
|
||||||
|
Channel->OutState = OutState;
|
||||||
|
|
||||||
|
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Update Channel '%s' - Out:%s",
|
||||||
|
ProcessName, Name, Channel->Ref, ChannelStateName[OutState] );
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
EChannelState CFunctionCore::GetChannelOutState( TChannel * Channel, const char * TargetRef )
|
||||||
|
{
|
||||||
|
TChannelLink * LinkChannel = NULL;
|
||||||
|
|
||||||
|
// Validate
|
||||||
|
if (!Channel) {
|
||||||
|
return CH_off;
|
||||||
|
}
|
||||||
|
else if (!TargetRef || !*TargetRef) {
|
||||||
|
return Channel->OutState;
|
||||||
|
}
|
||||||
|
else if ((LinkChannel = GetLinkChannel( Channel, TargetRef ))) {
|
||||||
|
return LinkChannel->Channel->InState;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return CH_off;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// 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( InFunctionName )) ||
|
!(LinkFunction = Application->GetFunction( LinkFunctionName )) ||
|
||||||
!(InChannel = InFunction->GetChannel( InChannelName )) ) {
|
!(LinkChannel = LinkFunction->GetChannel( LinkChannelName )) ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if linked Channel exists
|
// Check if linked Channel exists
|
||||||
LinkedChannel = &(OutChannel->FirstOutput);
|
LinkedChannel = &(Channel->FirstLink);
|
||||||
while (*LinkedChannel && (((*LinkedChannel)->Function != InFunction) || strcmp( (*LinkedChannel)->Name, InChannelName ) )) {
|
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( InChannelName );
|
(*LinkedChannel)->Channel = LinkChannel;
|
||||||
|
(*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, InFunction->GetName(), InChannelName );
|
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->LinkOutputChannel( InChannelName, 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") );
|
||||||
|
|
||||||
|
// Trigger Forward Channel Events
|
||||||
|
LinkFunction->UpdateChannelOutState( LinkChannel );
|
||||||
|
LinkFunction->ChannelStateEvent( LinkChannel, Channel->Ref, CH_off, Channel->InState );
|
||||||
|
|
||||||
|
// Trigger Reverse Channel Events
|
||||||
|
UpdateChannelOutState( Channel );
|
||||||
|
ChannelStateEvent( Channel, LinkChannel->Ref, CH_off, LinkChannel->InState );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
// Manual Data Input/Output
|
bool CFunctionCore::UnlinkChannel( const char * ChannelName, const char * LinkFunctionName, const char * LinkChannelName )
|
||||||
int CFunctionCore::Input( const char * ChannelName, const char * Data, int Len )
|
|
||||||
{
|
{
|
||||||
TChannel * Channel = NULL;
|
TChannel * Channel = NULL;
|
||||||
|
CFunctionCore * LinkFunction = NULL;
|
||||||
|
TChannel * LinkChannel = NULL;
|
||||||
|
TChannelLink ** LinkedChannel = NULL;
|
||||||
|
TChannelLink * NextLinkedChannel = NULL;
|
||||||
|
|
||||||
|
// Check if Channels & Function exist
|
||||||
|
if (!(Channel = GetChannel( ChannelName )) ||
|
||||||
|
!(LinkFunction = Application->GetFunction( LinkFunctionName )) ||
|
||||||
|
!(LinkChannel = LinkFunction->GetChannel( LinkChannelName )) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if linked Channel exists
|
||||||
|
LinkedChannel = &(Channel->FirstLink);
|
||||||
|
while (*LinkedChannel && ((*LinkedChannel)->Channel != LinkChannel))
|
||||||
|
LinkedChannel = &((*LinkedChannel)->Next);
|
||||||
|
|
||||||
|
// Unlink channel
|
||||||
|
if (*LinkedChannel) {
|
||||||
|
if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Forward Channel Unlinked - '%s'-x->'%s'",
|
||||||
|
ProcessName, Name, Channel->Ref, (*LinkedChannel)->Channel->Ref );
|
||||||
|
NextLinkedChannel = (*LinkedChannel)->Next;
|
||||||
|
delete *LinkedChannel;
|
||||||
|
*LinkedChannel = NextLinkedChannel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find Linked channel on remote function
|
||||||
|
LinkedChannel = &(LinkChannel->FirstLink);
|
||||||
|
while (*LinkedChannel && ((*LinkedChannel)->Channel != Channel))
|
||||||
|
LinkedChannel = &((*LinkedChannel)->Next);
|
||||||
|
|
||||||
|
// Unlink channel
|
||||||
|
if (*LinkedChannel) {
|
||||||
|
if (Log) Log->Message( LogLevel, dlLow, "%s/%s: Reverse Channel Unlinked - '%s'-x->'%s'",
|
||||||
|
ProcessName, Name, LinkChannel->Ref, (*LinkedChannel)->Channel->Ref );
|
||||||
|
NextLinkedChannel = (*LinkedChannel)->Next;
|
||||||
|
delete *LinkedChannel;
|
||||||
|
*LinkedChannel = NextLinkedChannel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trigger Channel Events
|
||||||
|
LinkFunction->UpdateChannelOutState( LinkChannel );
|
||||||
|
UpdateChannelOutState( Channel );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
int CFunctionCore::Input( const char * ChannelName, const char * SourceRef, const char * Data, int Len )
|
||||||
|
{
|
||||||
|
TChannel * Channel = NULL;
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
if (!ChannelName || !Data) {
|
if (!ChannelName || !*ChannelName || !Data) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get Channel
|
// Get Channel
|
||||||
if (!(Channel = GetChannel( ChannelName ))) {
|
if (!(Channel = GetChannel( ChannelName ))) {
|
||||||
// Channel not found
|
// Channel not found
|
||||||
if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Channel '%s' - Input rejected, Channel not found",
|
if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Channel '%s'->'%s' - Input rejected, Channel not found",
|
||||||
ProcessName, Name, ChannelName );
|
ProcessName, Name, ((SourceRef && *SourceRef)? SourceRef : "(Any)"), ChannelName );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (!Channel->InputEnabled) {
|
else if (!Channel->InState) {
|
||||||
// Channel disabled
|
if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Channel '%s'->'%s' - Input rejected, Channel %s",
|
||||||
if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Channel '%s' - Input rejected, Channel input disabled",
|
ProcessName, Name, ((SourceRef && *SourceRef)? SourceRef : "(Any)"), ChannelName, ChannelStateName[Channel->InState] );
|
||||||
ProcessName, Name, ChannelName );
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
// Return processed bytes
|
// Return processed bytes
|
||||||
if (Len == -1) {
|
if (Len == -1) {
|
||||||
Len = strlen( Data );
|
Len = strlen( Data );
|
||||||
}
|
|
||||||
if (Log) Log->Output( LogLevel, dlHigh, LogOutput, Data, Len, "%s/%s: Channel '%s' - IN:",
|
|
||||||
ProcessName, Name, ChannelName );
|
|
||||||
return Len;
|
|
||||||
}
|
}
|
||||||
|
if (Log) Log->Output( LogLevel, dlHigh, LogOutput, Data, Len, "%s/%s: Channel '%s'->'%s' - IN:",
|
||||||
|
ProcessName, Name, ((SourceRef && *SourceRef)? SourceRef : "(Any)"), ChannelName );
|
||||||
|
return Len;
|
||||||
|
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
int CFunctionCore::Output( const char * ChannelName, const char * Data, int Len )
|
int CFunctionCore::Output( const char * ChannelName, const char * TargetRef, const bool SourceRef, const char * Data, int Len )
|
||||||
{
|
{
|
||||||
TChannel * Channel = NULL;
|
TChannel * Channel = NULL;
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
if (!ChannelName) {
|
if (!ChannelName || !*ChannelName) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get Channel
|
// Get Channel
|
||||||
if (!(Channel = GetChannel( ChannelName ))) {
|
if (!(Channel = GetChannel( ChannelName ))) {
|
||||||
if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Channel '%s' - Output rejected, Channel not found",
|
if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Channel '%s'->'%s' - Output rejected, Output Channel not found",
|
||||||
ProcessName, Name, ChannelName );
|
ProcessName, Name, ChannelName, ((TargetRef && *TargetRef)? TargetRef : "(All)") );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Return processed bytes
|
// Return processed bytes
|
||||||
return Output( Channel, Data, Len );
|
return Output( Channel, TargetRef, SourceRef, Data, Len );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
int CFunctionCore::Output( const TChannel * Channel, 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;
|
||||||
|
|
||||||
@@ -363,123 +449,23 @@ int CFunctionCore::Output( const TChannel * Channel, const char * Data, int Len,
|
|||||||
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 );
|
|
||||||
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 );
|
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 );
|
||||||
}
|
LinkChannel = Channel->FirstLink;
|
||||||
OutChannel = Channel->FirstOutput;
|
while (LinkChannel) {
|
||||||
while (OutChannel) {
|
if (!TargetRef || !*TargetRef || !strcasecmp( TargetRef, LinkChannel->Channel->Ref )) {
|
||||||
TempLen = OutChannel->Function->Input( OutChannel->Name, 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
|
||||||
return OutLen;
|
return OutLen;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CFunctionCore::PullInput( const char * ChannelName )
|
|
||||||
{
|
|
||||||
TChannel * Channel = NULL;
|
|
||||||
|
|
||||||
// Validate
|
|
||||||
if (!ChannelName) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get Channel
|
|
||||||
if (!(Channel = GetChannel( ChannelName ))) {
|
|
||||||
// Channel not found
|
|
||||||
if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Channel '%s' - Input failed, Channel not found",
|
|
||||||
ProcessName, Name, ChannelName );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Return success
|
|
||||||
return PullInput( Channel );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
bool CFunctionCore::PullInput( TChannel * Channel )
|
|
||||||
{
|
|
||||||
TChannelLink * InChannel = NULL;
|
|
||||||
char ** Data = NULL;
|
|
||||||
int * Len = NULL;
|
|
||||||
|
|
||||||
// Validate
|
|
||||||
if (!Channel) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if enabled
|
|
||||||
if (!Channel->InputEnabled) {
|
|
||||||
if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Channel '%s' - Input failed, Channel input disabled",
|
|
||||||
ProcessName, Name, Channel->Name );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pass output to all linked inputs
|
|
||||||
InChannel = Channel->FirstInput;
|
|
||||||
while (InChannel)
|
|
||||||
{
|
|
||||||
// Pull Output from Channel
|
|
||||||
if (InChannel->Function->PullOutput( InChannel->Name, Data, Len ))
|
|
||||||
{
|
|
||||||
// Use input
|
|
||||||
Input( Channel->Name, *Data, ((*Len)? *Len : -1) );
|
|
||||||
}
|
|
||||||
InChannel = InChannel->Next;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return success
|
|
||||||
return Len;
|
|
||||||
}
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
bool CFunctionCore::PullOutput( const char * ChannelName, char ** Data, int * Len )
|
|
||||||
{
|
|
||||||
TChannel * Channel = NULL;
|
|
||||||
int TempLen = 0;
|
|
||||||
|
|
||||||
// Validate
|
|
||||||
if (!ChannelName || !Data) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get Channel
|
|
||||||
if (!(Channel = GetChannel( ChannelName ))) {
|
|
||||||
// Channel not found
|
|
||||||
if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Channel '%s' - Output failed, Channel not found",
|
|
||||||
ProcessName, Name, ChannelName );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else if (!Channel->InputEnabled) {
|
|
||||||
// Channel disabled
|
|
||||||
if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Channel '%s' - Output failed, Channel output disabled",
|
|
||||||
ProcessName, Name, ChannelName );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Return processed bytes
|
|
||||||
*Data = StoredOutput;
|
|
||||||
TempLen = (*Data)? strlen(*Data) : 0;
|
|
||||||
if (Len) *Len = TempLen;
|
|
||||||
if (Log) Log->Output( LogLevel, dlHigh, LogOutput, ((*Data)? *Data : "(NULL)"), TempLen, "%s/%s: Channel '%s' - IN:",
|
|
||||||
ProcessName, Name, ChannelName );
|
|
||||||
return Len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -28,12 +34,12 @@ class CFunctionCore;
|
|||||||
struct SChannel
|
struct SChannel
|
||||||
{
|
{
|
||||||
char * Name = NULL;
|
char * Name = NULL;
|
||||||
|
char * Ref = NULL;
|
||||||
|
|
||||||
TChannelLink * FirstInput = NULL;
|
TChannelLink * FirstLink = NULL; // List of channels linked for input/output
|
||||||
TChannelLink * FirstOutput = NULL;
|
|
||||||
|
|
||||||
bool InputEnabled = NULL;
|
EChannelState InState = CH_off; // Channel ready to receive input (determined by parent function)
|
||||||
bool OutputEnabled = NULL;
|
EChannelState OutState = CH_off; // Channel ready to send output (determined by InStates of linked channels)
|
||||||
|
|
||||||
TChannel * Next = NULL;
|
TChannel * Next = NULL;
|
||||||
};
|
};
|
||||||
@@ -42,7 +48,10 @@ struct SChannel
|
|||||||
struct SChannelLink
|
struct SChannelLink
|
||||||
{
|
{
|
||||||
CFunctionCore * Function = NULL;
|
CFunctionCore * Function = NULL;
|
||||||
char * Name = NULL;
|
TChannel * Channel = NULL;
|
||||||
|
|
||||||
|
bool Input = false;
|
||||||
|
bool Output = false;
|
||||||
|
|
||||||
SChannelLink * Next = NULL;
|
SChannelLink * Next = NULL;
|
||||||
};
|
};
|
||||||
@@ -62,6 +71,9 @@ protected:
|
|||||||
char * Name = NULL;
|
char * Name = NULL;
|
||||||
bool WaitToTerminate = false;
|
bool WaitToTerminate = false;
|
||||||
|
|
||||||
|
// JSON Config
|
||||||
|
CDataMember * Config = NULL;
|
||||||
|
|
||||||
// Channels
|
// Channels
|
||||||
TChannel * FirstChannel = NULL;
|
TChannel * FirstChannel = NULL;
|
||||||
|
|
||||||
@@ -70,10 +82,6 @@ protected:
|
|||||||
EDebugLevel LogLevel = dlNone;
|
EDebugLevel LogLevel = dlNone;
|
||||||
int LogOutput = loNone;
|
int LogOutput = loNone;
|
||||||
|
|
||||||
// Stored Output
|
|
||||||
char * StoredOutput = NULL;
|
|
||||||
int StoredOutputLen = 0;
|
|
||||||
|
|
||||||
// Manage Channel
|
// Manage Channel
|
||||||
inline TChannel * GetChannel( const char * pName ) {
|
inline TChannel * GetChannel( const char * pName ) {
|
||||||
if (!pName) return NULL;
|
if (!pName) return NULL;
|
||||||
@@ -82,10 +90,16 @@ 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 * 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 );
|
||||||
virtual bool PullInput( TChannel * Channel );
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Life cycle
|
// Life cycle
|
||||||
@@ -105,39 +119,20 @@ 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 EChannelState State );
|
||||||
inline bool SetChannelOutEnable( const char * ChannelName, const bool pOutputEnable ) {
|
|
||||||
TChannel * Channel = GetChannel( ChannelName );
|
virtual bool SetChannelInState( TChannel * Channel, const EChannelState State );
|
||||||
if (!Channel) return false;
|
virtual bool ChannelStateEvent( TChannel * Channel, const char * SourceRef, const EChannelState OldState, const EChannelState NewState ) { return true; };
|
||||||
Channel->OutputEnabled = pOutputEnable;
|
virtual bool UpdateChannelOutState( TChannel * Channel );
|
||||||
return true;
|
virtual EChannelState GetChannelOutState( TChannel * Channel, const char * TargetRef );
|
||||||
}
|
|
||||||
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 * 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 * Data, int Len = -1 );
|
virtual int Input( const char * ChannelName, const char * SourceRef, const char * Data, int Len = -1 );
|
||||||
|
|
||||||
// Pulling Data Input <- Output
|
|
||||||
virtual bool PullInput( const char * ChannelName );
|
|
||||||
virtual bool PullOutput( const char * ChannelName, char ** Data, int * Len = NULL );
|
|
||||||
|
|
||||||
// Automated Data Input/Output
|
// Automated Data Input/Output
|
||||||
virtual bool LinkInputChannel( const char * ChannelName, const char * OutFunctionName, const char * OutChannelName, bool Bidirectional );
|
virtual bool LinkChannel( const char * ChannelName, const char * LinkFunctionName, const char * LinkChannelName, bool Input, bool Output );
|
||||||
virtual bool LinkOutputChannel( const char * ChannelName, const char * InFunctionName, const char * InChannelName, bool Bidirectional );
|
virtual bool UnlinkChannel( const char * ChannelName, const char * LinkFunctionName, const char * LinkChannelName );
|
||||||
virtual bool Process() = 0;
|
virtual bool Process() = 0;
|
||||||
|
|
||||||
friend class CApplication;
|
friend class CApplication;
|
||||||
|
|||||||
@@ -272,7 +272,7 @@ bool CJSONparse::ReadFromHandle( const char * BasePath, int Handle, bool pRefill
|
|||||||
InputHandle = Handle;
|
InputHandle = Handle;
|
||||||
|
|
||||||
// Load Buffer
|
// Load Buffer
|
||||||
CreateBuffer( 500 );
|
CreateBuffer( 1000 );
|
||||||
if (!FillBuffer()) {
|
if (!FillBuffer()) {
|
||||||
Error = true;
|
Error = true;
|
||||||
sprintf( ErrorText, "Could not read from file" );
|
sprintf( ErrorText, "Could not read from file" );
|
||||||
@@ -690,7 +690,7 @@ bool CJSONparse::ParseArray( CDataMember * Array )
|
|||||||
SkipWhiteSpace();
|
SkipWhiteSpace();
|
||||||
if (!ParseObject( *Member ) && !Error && !ParseArray( *Member ) && !Error && !ParseString( *Member ) && !Error && !ParsePrimitive( *Member ) ) {}
|
if (!ParseObject( *Member ) && !Error && !ParseArray( *Member ) && !Error && !ParseString( *Member ) && !Error && !ParsePrimitive( *Member ) ) {}
|
||||||
if (Error) {
|
if (Error) {
|
||||||
delete Member;
|
delete *Member;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
// Global vars
|
// Global vars
|
||||||
char LogStr[1000]; // Temporary var to create log messages, globally available to save on memory operations
|
char LogStr[5000]; // Temporary var to create log messages, globally available to save on memory operations
|
||||||
|
|
||||||
const char * LogOutputName[] = { "None", "Raw", "Normal", "Hex", "Bin" };
|
const char * LogOutputName[] = { "None", "Raw", "Normal", "Hex", "Bin" };
|
||||||
|
|
||||||
|
|||||||
@@ -38,9 +38,6 @@ CSelectableBare::CSelectableBare( const char * pName, const char * pType ) : CFu
|
|||||||
{
|
{
|
||||||
// Quick access
|
// Quick access
|
||||||
Selector = Application->Selector;
|
Selector = Application->Selector;
|
||||||
|
|
||||||
// Handles
|
|
||||||
FirstHandle = NULL;
|
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -97,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) {
|
||||||
@@ -106,7 +103,8 @@ THandle * CSelectableBare::CreateHandle( const char * HandleName, bool CreateCh
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set File Descriptor
|
// Set File Descriptor
|
||||||
(*Handle)->FD = -1;
|
(*Handle)->Function = this;
|
||||||
|
(*Handle)->FD = -1;
|
||||||
|
|
||||||
// Log event
|
// Log event
|
||||||
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Created",
|
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Created",
|
||||||
@@ -115,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 );
|
(*Handle)->Channel = AddChannel( HandleName, CH_off );
|
||||||
}
|
}
|
||||||
|
|
||||||
return *Handle;
|
return *Handle;
|
||||||
@@ -162,61 +160,39 @@ 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 )
|
||||||
{
|
{
|
||||||
|
EChannelState ChannelState = CH_off;
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
if (!Handle) {
|
if (!Handle || (Handle->State == State))
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
// Reset Type related parameters
|
// Set Call back
|
||||||
if (Handle->Path) {
|
if (Handle->StateCallback[ (int)State ])
|
||||||
free( Handle->Path );
|
(Handle->StateCallback[ (int)State ])( this, Handle, State );
|
||||||
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
|
// Change state
|
||||||
Handle->Type = ctNone;
|
Handle->State = State;
|
||||||
|
|
||||||
// Log event
|
// Update Channel
|
||||||
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Set as None",
|
if (Handle->Channel) {
|
||||||
ProcessName, Name, Handle->Name );
|
if ((Handle->State == csPreparing) || (Handle->State == csPrepared) || (Handle->State == csWaitingtoOpen))
|
||||||
|
ChannelState = CH_wait;
|
||||||
|
else if ((Handle->State == csOpen) || (Handle->State == csDataWaiting))
|
||||||
|
ChannelState = CH_ready;
|
||||||
|
else
|
||||||
|
ChannelState = CH_off;
|
||||||
|
if (Handle->Channel->InState != ChannelState)
|
||||||
|
SetChannelInState( Handle->Channel, ChannelState );
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -322,9 +298,9 @@ bool CSelectableBare::ProcessInputBuffer( THandle * Handle, bool Force )
|
|||||||
|
|
||||||
// Write buffer to Outputs
|
// Write buffer to Outputs
|
||||||
if ((Handle->Type == ctTCPremote) || (Handle->Type == ctUNIXremote)) {
|
if ((Handle->Type == ctTCPremote) || (Handle->Type == ctUNIXremote)) {
|
||||||
Output( Handle->Parent->Channel, Data, Len );
|
Output( Handle->Parent->Channel, NULL, true, Data, Len );
|
||||||
} else {
|
} else {
|
||||||
Output( Handle->Channel, Data, Len );
|
Output( Handle->Channel, NULL, true, Data, Len );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear processed bytes from buffer
|
// Clear processed bytes from buffer
|
||||||
@@ -342,9 +318,9 @@ bool CSelectableBare::ProcessInputBuffer( THandle * Handle, bool Force )
|
|||||||
|
|
||||||
// Write buffer to Outputs
|
// Write buffer to Outputs
|
||||||
if ((Handle->Type == ctTCPremote) || (Handle->Type == ctUNIXremote)) {
|
if ((Handle->Type == ctTCPremote) || (Handle->Type == ctUNIXremote)) {
|
||||||
Output( Handle->Parent->Channel, Data, Len );
|
Output( Handle->Parent->Channel, NULL, true, Data, Len );
|
||||||
} else {
|
} else {
|
||||||
Output( Handle->Channel, Data, Len );
|
Output( Handle->Channel, NULL, true, Data, Len );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear processed bytes from buffer
|
// Clear processed bytes from buffer
|
||||||
@@ -355,10 +331,11 @@ bool CSelectableBare::ProcessInputBuffer( THandle * Handle, bool Force )
|
|||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
int CSelectableBare::Open( THandle * Handle, bool DelayResolve )
|
int CSelectableBare::Open( THandle * Handle )
|
||||||
{
|
{
|
||||||
THandle * NewHandle = NULL;
|
THandle * NewHandle = NULL;
|
||||||
|
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
if (!Handle || (Handle->Type == ctNone)) {
|
if (!Handle || (Handle->Type == ctNone)) {
|
||||||
return -1;
|
return -1;
|
||||||
@@ -394,11 +371,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
|
||||||
|
HandleState( Handle, csOpen );
|
||||||
return (NewHandle)? NewHandle->FD : -1;
|
return (NewHandle)? NewHandle->FD : -1;
|
||||||
};
|
};
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -414,7 +391,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)
|
||||||
@@ -426,15 +412,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) {
|
HandleState( 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;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -534,7 +513,7 @@ bool CSelectableBare::Write( THandle * Handle )
|
|||||||
else if (Timeout( Handle->LastAction, Handle->ReopenDelay ))
|
else if (Timeout( Handle->LastAction, Handle->ReopenDelay ))
|
||||||
{
|
{
|
||||||
// Attempt to re-open port
|
// Attempt to re-open port
|
||||||
Open( Handle, true );
|
Open( Handle );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -678,7 +657,7 @@ int CSelectableBare::WriteToFD( int FD, const char * Data, int Len, bool Force )
|
|||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
int CSelectableBare::Input( const char * ChannelName, const char * Data, int Len )
|
int CSelectableBare::Input( const char * ChannelName, const char * SourceRef, const char * Data, int Len )
|
||||||
{
|
{
|
||||||
TChannel * Channel = NULL;
|
TChannel * Channel = NULL;
|
||||||
THandle * Handle = NULL;
|
THandle * Handle = NULL;
|
||||||
@@ -694,20 +673,20 @@ int CSelectableBare::Input( const char * ChannelName, const char * Data, int Len
|
|||||||
// Get Channel
|
// Get Channel
|
||||||
if (!(Channel = GetChannel( ChannelName ))) {
|
if (!(Channel = GetChannel( ChannelName ))) {
|
||||||
// Channel not found
|
// Channel not found
|
||||||
if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Channel '%s' - Input rejected, Channel not found",
|
if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Channel '%s'->'%s' - Input rejected, Channel not found",
|
||||||
ProcessName, Name, ChannelName );
|
ProcessName, Name, ((SourceRef && *SourceRef)? SourceRef : "(Any)"), ChannelName );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (!Channel->InputEnabled) {
|
else if (Channel->InState != CH_ready) {
|
||||||
// Channel disabled
|
// Channel disabled
|
||||||
if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Channel '%s' - Input rejected, Channel input disabled",
|
if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Channel '%s'->'%s' - Input rejected, Channel not Ready",
|
||||||
ProcessName, Name, ChannelName );
|
ProcessName, Name, ((SourceRef && *SourceRef)? SourceRef : "(Any)"), ChannelName );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log event
|
// Log event
|
||||||
if (Log) Log->Output( LogLevel, dlHigh, LogOutput, Data, Len, "%s/%s: Channel '%s' - IN:",
|
if (Log) Log->Output( LogLevel, dlHigh, LogOutput, Data, Len, "%s/%s: Channel '%s'->'%s' - IN:",
|
||||||
ProcessName, Name, ChannelName );
|
ProcessName, Name, ((SourceRef && *SourceRef)? SourceRef : "(Any)"), ChannelName );
|
||||||
|
|
||||||
// Find Linked handle
|
// Find Linked handle
|
||||||
Handle = FirstHandle;
|
Handle = FirstHandle;
|
||||||
@@ -725,8 +704,8 @@ int CSelectableBare::Input( const char * ChannelName, const char * Data, int Len
|
|||||||
|
|
||||||
if (!HandleCount) {
|
if (!HandleCount) {
|
||||||
// Handle not found
|
// Handle not found
|
||||||
if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Channel '%s' - Input rejected, No Handles found",
|
if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Channel '%s'->'%s' - Input rejected, No Handles found",
|
||||||
ProcessName, Name, ChannelName );
|
ProcessName, Name, ((SourceRef && *SourceRef)? SourceRef : "(Any)"), ChannelName );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -752,11 +731,11 @@ int CSelectableBare::OutputHandle( THandle * Handle, const char * Data, int Len
|
|||||||
else if (Timeout( Handle->LastAction, Handle->ReopenDelay ))
|
else if (Timeout( Handle->LastAction, Handle->ReopenDelay ))
|
||||||
{
|
{
|
||||||
// Complete opening process
|
// Complete opening process
|
||||||
Open( Handle, true );
|
Open( Handle );
|
||||||
|
|
||||||
// Check if Handle is open
|
// Check if Handle is open
|
||||||
if (Handle->State == csOpenRequest) {
|
if ((Handle->State == csPreparing) || (Handle->State == csPrepared)) {
|
||||||
if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Handle '%s' - Input rejected, Request to resolve (auto-managed) Handle",
|
if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Handle '%s' - Input rejected, Preparing (auto-managed) Handle",
|
||||||
ProcessName, Name, Handle->Name );
|
ProcessName, Name, Handle->Name );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -833,27 +812,21 @@ bool CSelectableBare::Process()
|
|||||||
while (Handle)
|
while (Handle)
|
||||||
{
|
{
|
||||||
// Auto manage handles
|
// Auto manage handles
|
||||||
if ((Handle->State == csOpenRequest))
|
if (Handle->State == csPrepared) {
|
||||||
{
|
// Proceed to open
|
||||||
// Resolve then open socket
|
Open( Handle );
|
||||||
if (Timeout( Handle->LastAction, Handle->ResolveDelay )) {
|
|
||||||
Open( Handle, false );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (((Handle->State != csOpen) && Handle->AutoManage && Handle->Persistent) )
|
else if ((Handle->State != csOpen) && Handle->AutoManage && Handle->Persistent) {
|
||||||
{
|
|
||||||
// Try to re-open port after delay
|
// Try to re-open port after delay
|
||||||
if (Timeout( Handle->LastAction, Handle->ReopenDelay )) {
|
if (Timeout( Handle->LastAction, Handle->ReopenDelay )) {
|
||||||
Open( Handle, false );
|
Open( Handle );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check Input buffers
|
// Check Input buffers
|
||||||
if (Handle->InBuffer && (Handle->InBuffer->Len() > 0))
|
if (Handle->InBuffer && (Handle->InBuffer->Len() > 0)) {
|
||||||
{
|
|
||||||
// Check duration since last PortIn
|
// Check duration since last PortIn
|
||||||
if (Timeout( Handle->InStart, Handle->InTimeout ))
|
if (Timeout( Handle->InStart, Handle->InTimeout )) {
|
||||||
{
|
|
||||||
// Process Input
|
// Process Input
|
||||||
ProcessInputBuffer( Handle, true );
|
ProcessInputBuffer( Handle, true );
|
||||||
|
|
||||||
@@ -863,95 +836,14 @@ bool CSelectableBare::Process()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check for auto close (but not on servers)
|
// Check for auto close (but not on servers)
|
||||||
if ((Handle->State == csOpen) && (Handle->Type != ctTCPserver) && (Handle->Type != ctUNIXserver) && Handle->AutoManage && !Handle->Persistent)
|
if ((Handle->State == csOpen) && Handle->AutoManage && !Handle->Persistent) {
|
||||||
{
|
|
||||||
// Close port after timeout
|
// Close port after timeout
|
||||||
if (Timeout( Handle->LastAction, Handle->CloseTimeout )) {
|
if (Timeout( Handle->LastAction, Handle->CloseTimeout )) {
|
||||||
Close( Handle, true );
|
Close( Handle, true );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Handle = Handle->Next;
|
Handle = Handle->Next;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CSelectableBare::BuildArgs( const char * ExecPath, int &Count, char * Args[] )
|
|
||||||
{
|
|
||||||
bool ParamStarted = false;
|
|
||||||
bool OpenQuotes = false;
|
|
||||||
char * MatchPos = NULL;
|
|
||||||
char * StartPos = NULL;
|
|
||||||
int Len;
|
|
||||||
|
|
||||||
// Validate
|
|
||||||
if (!ExecPath || !*ExecPath) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Split params
|
|
||||||
MatchPos = (char*)ExecPath;
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
// Look for whitespace
|
|
||||||
if (!ParamStarted)
|
|
||||||
{
|
|
||||||
// Quotes starts quoted parameter
|
|
||||||
if (*MatchPos == '"') {
|
|
||||||
ParamStarted = true;
|
|
||||||
OpenQuotes = true;
|
|
||||||
StartPos = MatchPos+1; // Skip starting quote
|
|
||||||
}
|
|
||||||
// Non-whitespace starts normal parameter
|
|
||||||
else if ((*MatchPos != ' ') && (*MatchPos != 0)) {
|
|
||||||
ParamStarted = true;
|
|
||||||
StartPos = MatchPos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (OpenQuotes)
|
|
||||||
{
|
|
||||||
// Another quote ends parameter
|
|
||||||
if (*MatchPos == '"') {
|
|
||||||
Len = MatchPos-StartPos-1; // Skip end quote
|
|
||||||
Args[Count] = (char*)malloc( Len+1 );
|
|
||||||
strncpy( Args[Count], StartPos, Len );
|
|
||||||
Args[Count][Len] = 0;
|
|
||||||
Count++;
|
|
||||||
ParamStarted = false;
|
|
||||||
OpenQuotes = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Whitespace ends parameter
|
|
||||||
if ((*MatchPos == ' ') || (*MatchPos == 0)) {
|
|
||||||
Len = MatchPos-StartPos;
|
|
||||||
Args[Count] = (char*)malloc( Len+1 );
|
|
||||||
strncpy( Args[Count], StartPos, Len );
|
|
||||||
Args[Count][Len] = 0;
|
|
||||||
Count++;
|
|
||||||
ParamStarted = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Next char, unless NULL
|
|
||||||
if (*MatchPos)
|
|
||||||
MatchPos++;
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check all parameters closed
|
|
||||||
if (ParamStarted) {
|
|
||||||
Count = 0;
|
|
||||||
Args[0] = NULL;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set last Param to NULL
|
|
||||||
Args[Count] = NULL;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|||||||
@@ -40,24 +40,57 @@ 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 )
|
||||||
{
|
{
|
||||||
// Quick access
|
// Configure resolve signal handler
|
||||||
Selector = Application->Selector;
|
ResolveAct.sa_sigaction = &ResolveHandler;
|
||||||
|
sigemptyset( &ResolveAct.sa_mask );
|
||||||
|
ResolveAct.sa_flags = SA_SIGINFO;
|
||||||
|
|
||||||
|
sigaction( SIGRTMIN, &ResolveAct, NULL );
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
CSelectableCore::~CSelectableCore()
|
CSelectableCore::~CSelectableCore()
|
||||||
{
|
{
|
||||||
THandle * NextHandle = NULL;
|
THandle * NextHandle = NULL;
|
||||||
|
bool Result;
|
||||||
|
|
||||||
// Destroy File Handles
|
// Destroy File Handles
|
||||||
while (FirstHandle)
|
while (FirstHandle)
|
||||||
{
|
{
|
||||||
|
// Close active resolve request
|
||||||
|
if (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
|
// Close handle if open
|
||||||
if ((FirstHandle->State == csOpen) || (FirstHandle->State == csWaitingtoOpen)) {
|
if ((FirstHandle->State == csOpen) || (FirstHandle->State == csWaitingtoOpen))
|
||||||
Close( FirstHandle, false );
|
Close( FirstHandle, false );
|
||||||
}
|
|
||||||
|
|
||||||
NextHandle = FirstHandle->Next;
|
NextHandle = FirstHandle->Next;
|
||||||
DestroyHandle( FirstHandle );
|
DestroyHandle( FirstHandle );
|
||||||
@@ -81,7 +114,6 @@ bool CSelectableCore::Init( CDataMember * FunctionConfig )
|
|||||||
short Parity;
|
short Parity;
|
||||||
short FlowCtrl;
|
short FlowCtrl;
|
||||||
short Queue;
|
short Queue;
|
||||||
long Delay;
|
|
||||||
|
|
||||||
// Call Previous load config
|
// Call Previous load config
|
||||||
if (!CFunctionCore::Init( FunctionConfig ))
|
if (!CFunctionCore::Init( FunctionConfig ))
|
||||||
@@ -177,8 +209,7 @@ bool CSelectableCore::Init( CDataMember * FunctionConfig )
|
|||||||
Address = (char*)HandleConfig->GetChStr( "Socket/Address", NULL, true ); // Get default Address value
|
Address = (char*)HandleConfig->GetChStr( "Socket/Address", NULL, true ); // Get default Address value
|
||||||
Port = (char*)HandleConfig->GetChStr( "Socket/Port", "0", true ); // Get default Port value
|
Port = (char*)HandleConfig->GetChStr( "Socket/Port", "0", true ); // Get default Port value
|
||||||
}
|
}
|
||||||
Delay = HandleConfig->GetChInt( "Socket/ResolveDelay", 0, true );
|
SetSocketHandle( Handle, ctUDPserver, Address, strlcase(Port), 0 );
|
||||||
SetSocketHandle( Handle, ctUDPserver, Address, strlcase(Port), 0, Delay );
|
|
||||||
}
|
}
|
||||||
else if (!strcasecmp( Type, "UDPclient" ))
|
else if (!strcasecmp( Type, "UDPclient" ))
|
||||||
{
|
{
|
||||||
@@ -189,8 +220,7 @@ bool CSelectableCore::Init( CDataMember * FunctionConfig )
|
|||||||
Address = (char*)HandleConfig->GetChStr( "Socket/Address", NULL, true ); // Get default Address value
|
Address = (char*)HandleConfig->GetChStr( "Socket/Address", NULL, true ); // Get default Address value
|
||||||
Port = (char*)HandleConfig->GetChStr( "Socket/Port", "0", true ); // Get default Port value
|
Port = (char*)HandleConfig->GetChStr( "Socket/Port", "0", true ); // Get default Port value
|
||||||
}
|
}
|
||||||
Delay = HandleConfig->GetChInt( "Socket/ResolveDelay", 0, true );
|
SetSocketHandle( Handle, ctUDPclient, Address, strlcase(Port), 0 );
|
||||||
SetSocketHandle( Handle, ctUDPclient, Address, strlcase(Port), 0, Delay );
|
|
||||||
}
|
}
|
||||||
else if (!strcasecmp( Type, "TCPserver" ))
|
else if (!strcasecmp( Type, "TCPserver" ))
|
||||||
{
|
{
|
||||||
@@ -201,9 +231,8 @@ bool CSelectableCore::Init( CDataMember * FunctionConfig )
|
|||||||
Address = (char*)HandleConfig->GetChStr( "Socket/Address", NULL, true ); // Get default Address value
|
Address = (char*)HandleConfig->GetChStr( "Socket/Address", NULL, true ); // Get default Address value
|
||||||
Port = (char*)HandleConfig->GetChStr( "Socket/Port", "0", true ); // Get default Port value
|
Port = (char*)HandleConfig->GetChStr( "Socket/Port", "0", true ); // Get default Port value
|
||||||
}
|
}
|
||||||
Delay = HandleConfig->GetChInt( "Socket/ResolveDelay", 0, true );
|
|
||||||
Queue = HandleConfig->GetChInt( "Socket/Queue", 2, true );
|
Queue = HandleConfig->GetChInt( "Socket/Queue", 2, true );
|
||||||
SetSocketHandle( Handle, ctTCPserver, Address, strlcase(Port), Queue, Delay );
|
SetSocketHandle( Handle, ctTCPserver, Address, strlcase(Port), Queue );
|
||||||
}
|
}
|
||||||
else if (!strcasecmp( Type, "TCPclient" ))
|
else if (!strcasecmp( Type, "TCPclient" ))
|
||||||
{
|
{
|
||||||
@@ -214,8 +243,7 @@ bool CSelectableCore::Init( CDataMember * FunctionConfig )
|
|||||||
Address = (char*)HandleConfig->GetChStr( "Socket/Address", NULL, true ); // Get default Address value
|
Address = (char*)HandleConfig->GetChStr( "Socket/Address", NULL, true ); // Get default Address value
|
||||||
Port = (char*)HandleConfig->GetChStr( "Socket/Port", "0", true ); // Get default Port value
|
Port = (char*)HandleConfig->GetChStr( "Socket/Port", "0", true ); // Get default Port value
|
||||||
}
|
}
|
||||||
Delay = HandleConfig->GetChInt( "Socket/ResolveDelay", 0, true );
|
SetSocketHandle( Handle, ctTCPclient, Address, strlcase(Port), 0 );
|
||||||
SetSocketHandle( Handle, ctTCPclient, Address, strlcase(Port), 0, Delay );
|
|
||||||
}
|
}
|
||||||
else if (!strcasecmp( Type, "ForkPipe" )) {
|
else if (!strcasecmp( Type, "ForkPipe" )) {
|
||||||
Address = (char*)HandleConfig->GetChStr( "Fork/ExecPath", NULL, true ); // Get default value
|
Address = (char*)HandleConfig->GetChStr( "Fork/ExecPath", NULL, true ); // Get default value
|
||||||
@@ -243,6 +271,87 @@ bool CSelectableCore::Init( CDataMember * FunctionConfig )
|
|||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool CSelectableCore::DestroyHandle( THandle * Handle )
|
||||||
|
{
|
||||||
|
int Result;
|
||||||
|
|
||||||
|
// Validate Handle
|
||||||
|
if (!Handle)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Destroy Resolve request
|
||||||
|
if (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
|
||||||
@@ -353,7 +462,7 @@ bool CSelectableCore::SetUnixHandle( THandle * Handle, EConnectType Type, const
|
|||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CSelectableCore::SetSocketHandle( THandle * Handle, EConnectType Type, const char * HostName, const char * PortName, short Queue, long ResolveDelay )
|
bool CSelectableCore::SetSocketHandle( THandle * Handle, EConnectType Type, const char * HostName, const char * PortName, short Queue )
|
||||||
{
|
{
|
||||||
// Validate
|
// Validate
|
||||||
if (!Handle || !HostName || !PortName ||
|
if (!Handle || !HostName || !PortName ||
|
||||||
@@ -364,7 +473,6 @@ bool CSelectableCore::SetSocketHandle( THandle * Handle, EConnectType Type, con
|
|||||||
|
|
||||||
// Set Type
|
// Set Type
|
||||||
Handle->Type = Type;
|
Handle->Type = Type;
|
||||||
Handle->ResolveDelay = ResolveDelay;
|
|
||||||
|
|
||||||
// Clear HostName & Port Name
|
// Clear HostName & Port Name
|
||||||
if (Handle->HostName)
|
if (Handle->HostName)
|
||||||
@@ -443,7 +551,7 @@ THandle * CSelectableCore::OpenSerialPort( THandle * Handle )
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set state
|
// Set state
|
||||||
ChangeState( Handle, csOpen );
|
HandleState( Handle, csOpen );
|
||||||
return Handle;
|
return Handle;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -486,7 +594,7 @@ THandle * CSelectableCore::OpenLinePrinterPort( THandle * Handle )
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set state
|
// Set state
|
||||||
ChangeState( Handle, csOpen );
|
HandleState( Handle, csOpen );
|
||||||
return Handle;
|
return Handle;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -588,7 +696,7 @@ THandle * CSelectableCore::OpenForkPipe( THandle * Handle )
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set state
|
// Set state
|
||||||
ChangeState( Handle, csOpen );
|
HandleState( Handle, csOpen );
|
||||||
return Handle;
|
return Handle;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -612,7 +720,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -624,7 +732,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;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -648,7 +756,8 @@ THandle * CSelectableCore::OpenUNIXserverSocket( THandle * Handle )
|
|||||||
// Set state
|
// Set state
|
||||||
close( Handle->FD );
|
close( Handle->FD );
|
||||||
Handle->FD = -1;
|
Handle->FD = -1;
|
||||||
ChangeState( Handle, csFailed );
|
|
||||||
|
HandleState( Handle, csFailed );
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -662,7 +771,8 @@ THandle * CSelectableCore::OpenUNIXserverSocket( THandle * Handle )
|
|||||||
// Set state
|
// Set state
|
||||||
close( Handle->FD );
|
close( Handle->FD );
|
||||||
Handle->FD = -1;
|
Handle->FD = -1;
|
||||||
ChangeState( Handle, csFailed );
|
|
||||||
|
HandleState( Handle, csFailed );
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -676,7 +786,7 @@ THandle * CSelectableCore::OpenUNIXserverSocket( THandle * Handle )
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set state
|
// Set state
|
||||||
ChangeState( Handle, csOpen );
|
HandleState( Handle, csOpen );
|
||||||
return Handle;
|
return Handle;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -702,7 +812,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;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -729,7 +839,7 @@ THandle * CSelectableCore::OpenUNIXclientSocket( THandle * Handle )
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set status
|
// Set status
|
||||||
ChangeState( Handle, csWaitingtoOpen );
|
HandleState( Handle, csWaitingtoOpen );
|
||||||
return Handle;
|
return Handle;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -745,11 +855,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
|
HandleState( Handle, csFailed );
|
||||||
Handle->FD = -1;
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -764,7 +873,7 @@ THandle * CSelectableCore::OpenUNIXclientSocket( THandle * Handle )
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set status
|
// Set status
|
||||||
ChangeState( Handle, csOpen );
|
HandleState( Handle, csOpen );
|
||||||
return Handle;
|
return Handle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -861,7 +970,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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -869,14 +978,19 @@ THandle * CSelectableCore::OpenUNIXremoteSocket( THandle * Handle )
|
|||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CSelectableCore::ResolveAddress( THandle * Handle, bool DelayResolve )
|
bool CSelectableCore::ResolveAddress( THandle * Handle )
|
||||||
{
|
{
|
||||||
struct addrinfo hints;
|
struct addrinfo * Hints;
|
||||||
int result;
|
TResolveReq * ResolveReq;
|
||||||
|
sigevent ResolveEvt;
|
||||||
|
int Result;
|
||||||
|
|
||||||
|
// Ignore if busy resolving
|
||||||
|
if (Handle->State == csPreparing)
|
||||||
|
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;
|
||||||
@@ -907,47 +1021,108 @@ 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()
|
// Resolve Host & Port Names
|
||||||
if (DelayResolve)
|
HandleState( Handle, csPreparing );
|
||||||
{
|
|
||||||
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Delay resolving of Host Name [%s:%s]",
|
if ((Result = getaddrinfo_a( GAI_NOWAIT, &(Handle->ResolveReq->Request), 1, &ResolveEvt )) != 0) {
|
||||||
ProcessName, Name, Handle->Name, Handle->HostName, Handle->PortName );
|
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Error resolving Host Name [%s:%s] (%s)",
|
||||||
ChangeState( Handle, csOpenRequest );
|
ProcessName, Name, Handle->Name, Handle->HostName, Handle->PortName, gai_strerror(Result) );
|
||||||
|
DestroyResolveReq( Handle, true );
|
||||||
|
|
||||||
|
HandleState( Handle, csFailed );
|
||||||
|
SetStartTime( &Handle->LastAction ); // Allow delay before retrying resolve
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool CSelectableCore::DestroyResolveReq( THandle * Handle, bool DestroyResult )
|
||||||
|
{
|
||||||
|
// Validate
|
||||||
|
if (!Handle || !Handle->ResolveReq)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
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 );
|
||||||
|
SetStartTime( &Handle->LastAction ); // Allow delay before retrying resolve
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve Host & Port Names
|
// Read result
|
||||||
if ((result = getaddrinfo( Handle->HostName, Handle->PortName, &hints, &(Handle->AddressList))) != 0)
|
Handle->AddressList = Handle->ResolveReq->Request->ar_result;
|
||||||
{
|
Handle->AddressInfo = Handle->AddressList;
|
||||||
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Failed to resolve Host Name [%s:%s] (%s)",
|
|
||||||
ProcessName, Name, Handle->Name, Handle->HostName, Handle->PortName, gai_strerror(result) );
|
|
||||||
ChangeState( Handle, csFailed );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Select first address, skip "0.0.0.0"
|
// Select first address, skip "0.0.0.0"
|
||||||
Handle->AddressInfo = Handle->AddressList;
|
|
||||||
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 );
|
||||||
|
SetStartTime( &Handle->LastAction ); // Allow delay before retrying resolve
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -956,11 +1131,15 @@ 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 );
|
||||||
|
HandleState( Handle, csPrepared );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
THandle * CSelectableCore::OpenUDPserverSocket( THandle * Handle, bool DelayResolve )
|
THandle * CSelectableCore::OpenUDPserverSocket( THandle * Handle )
|
||||||
{
|
{
|
||||||
// Validate Handle
|
// Validate Handle
|
||||||
if (Handle->Type != ctUDPserver) {
|
if (Handle->Type != ctUDPserver) {
|
||||||
@@ -968,7 +1147,7 @@ THandle * CSelectableCore::OpenUDPserverSocket( THandle * Handle, bool DelayReso
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Resolve Host & Port Names
|
// Resolve Host & Port Names
|
||||||
if (!ResolveAddress( Handle, DelayResolve ))
|
if (!ResolveAddress( Handle ))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// Create socket
|
// Create socket
|
||||||
@@ -979,7 +1158,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;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -994,11 +1173,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
|
||||||
|
HandleState( Handle, csFailed );
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1012,7 +1193,7 @@ THandle * CSelectableCore::OpenUDPserverSocket( THandle * Handle, bool DelayReso
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set state
|
// Set state
|
||||||
ChangeState( Handle, csOpen );
|
HandleState( Handle, csOpen );
|
||||||
return Handle;
|
return Handle;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -1042,7 +1223,7 @@ THandle * CSelectableCore::OpenUDPremoteSocket( THandle * Handle, char * ClientA
|
|||||||
// Create Remote Client Handle
|
// Create Remote Client Handle
|
||||||
sprintf( ClientName, "%s-%d", Handle->Name, ClientCount );
|
sprintf( ClientName, "%s-%d", Handle->Name, ClientCount );
|
||||||
*RemoteClient = CreateHandle( ClientName, false );
|
*RemoteClient = CreateHandle( ClientName, false );
|
||||||
if (!SetSocketHandle( *RemoteClient, ctUDPremote, ClientAddress, ClientPort, 0, 0 )) {
|
if (!SetSocketHandle( *RemoteClient, ctUDPremote, ClientAddress, ClientPort, 0 )) {
|
||||||
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - UDP Server failed to configure Remote Client connection (%s)",
|
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - UDP Server failed to configure Remote Client connection (%s)",
|
||||||
ProcessName, Name, Handle->Name, strerror(errno) );
|
ProcessName, Name, Handle->Name, strerror(errno) );
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -1074,7 +1255,7 @@ THandle * CSelectableCore::OpenUDPremoteSocket( THandle * Handle, char * ClientA
|
|||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
THandle * CSelectableCore::OpenUDPclientSocket( THandle * Handle, bool DelayResolve )
|
THandle * CSelectableCore::OpenUDPclientSocket( THandle * Handle )
|
||||||
{
|
{
|
||||||
// Check state
|
// Check state
|
||||||
if (Handle->State == csOpen) {
|
if (Handle->State == csOpen) {
|
||||||
@@ -1083,7 +1264,7 @@ THandle * CSelectableCore::OpenUDPclientSocket( THandle * Handle, bool DelayReso
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Resolve IP Address
|
// Resolve IP Address
|
||||||
if (!ResolveAddress( Handle, DelayResolve ))
|
if (!ResolveAddress( Handle ))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// Create File descriptor
|
// Create File descriptor
|
||||||
@@ -1094,7 +1275,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;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1111,12 +1292,12 @@ THandle * CSelectableCore::OpenUDPclientSocket( THandle * Handle, bool DelayReso
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set status
|
// Set status
|
||||||
ChangeState( Handle, csOpen );
|
HandleState( Handle, csOpen );
|
||||||
return Handle;
|
return Handle;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
THandle * CSelectableCore::OpenTCPserverSocket( THandle * Handle, bool DelayResolve )
|
THandle * CSelectableCore::OpenTCPserverSocket( THandle * Handle )
|
||||||
{
|
{
|
||||||
// Socket options
|
// Socket options
|
||||||
struct linger ServerLinger_opt;
|
struct linger ServerLinger_opt;
|
||||||
@@ -1135,7 +1316,7 @@ THandle * CSelectableCore::OpenTCPserverSocket( THandle * Handle, bool DelayReso
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Resolve Host & Port Names
|
// Resolve Host & Port Names
|
||||||
if (!ResolveAddress( Handle, DelayResolve ))
|
if (!ResolveAddress( Handle ))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// Create socket
|
// Create socket
|
||||||
@@ -1146,7 +1327,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;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1159,7 +1340,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1174,7 +1355,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1189,11 +1370,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;
|
||||||
|
|
||||||
|
HandleState( Handle, csFailed );
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1204,11 +1386,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;
|
||||||
|
|
||||||
|
HandleState( Handle, csFailed );
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1222,7 +1405,7 @@ THandle * CSelectableCore::OpenTCPserverSocket( THandle * Handle, bool DelayReso
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set state
|
// Set state
|
||||||
ChangeState( Handle, csOpen );
|
HandleState( Handle, csOpen );
|
||||||
return Handle;
|
return Handle;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -1270,7 +1453,6 @@ THandle * CSelectableCore::OpenTCPremoteSocket( THandle * Handle )
|
|||||||
strcpy( ClientAddress, inet_ntoa(address.sin_addr) );
|
strcpy( ClientAddress, inet_ntoa(address.sin_addr) );
|
||||||
sprintf( ClientPort, "%d", ntohs(address.sin_port) );
|
sprintf( ClientPort, "%d", ntohs(address.sin_port) );
|
||||||
|
|
||||||
|
|
||||||
// Get end of client list
|
// Get end of client list
|
||||||
RemoteClient = &FirstHandle;
|
RemoteClient = &FirstHandle;
|
||||||
while (*RemoteClient) {
|
while (*RemoteClient) {
|
||||||
@@ -1280,7 +1462,7 @@ THandle * CSelectableCore::OpenTCPremoteSocket( THandle * Handle )
|
|||||||
// Create Remote Client Handle
|
// Create Remote Client Handle
|
||||||
sprintf( ClientName, "%s-%d", Handle->Name, ClientFD );
|
sprintf( ClientName, "%s-%d", Handle->Name, ClientFD );
|
||||||
*RemoteClient = CreateHandle( ClientName, false );
|
*RemoteClient = CreateHandle( ClientName, false );
|
||||||
if (!SetSocketHandle( *RemoteClient, ctTCPremote, ClientAddress, ClientPort, 0, 0 )) {
|
if (!SetSocketHandle( *RemoteClient, ctTCPremote, ClientAddress, ClientPort, 0 )) {
|
||||||
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - TCP Server failed to configure Remote Client connection (%s)",
|
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - TCP Server failed to configure Remote Client connection (%s)",
|
||||||
ProcessName, Name, Handle->Name, strerror(errno) );
|
ProcessName, Name, Handle->Name, strerror(errno) );
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -1325,7 +1507,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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1333,13 +1515,14 @@ THandle * CSelectableCore::OpenTCPremoteSocket( THandle * Handle )
|
|||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
THandle * CSelectableCore::OpenTCPclientSocket( THandle * Handle, bool DelayResolve )
|
THandle * CSelectableCore::OpenTCPclientSocket( THandle * Handle )
|
||||||
{
|
{
|
||||||
// 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) {
|
||||||
@@ -1350,7 +1533,7 @@ THandle * CSelectableCore::OpenTCPclientSocket( THandle * Handle, bool DelayReso
|
|||||||
if (Handle->State != csWaitingtoOpen)
|
if (Handle->State != csWaitingtoOpen)
|
||||||
{
|
{
|
||||||
// Resolve IP Address
|
// Resolve IP Address
|
||||||
if (!ResolveAddress( Handle, DelayResolve ))
|
if (!ResolveAddress( Handle ))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// Create File descriptor
|
// Create File descriptor
|
||||||
@@ -1361,7 +1544,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;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1373,16 +1556,18 @@ 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)",
|
||||||
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 );
|
|
||||||
|
HandleState( Handle, csFailed );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1399,7 +1584,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))
|
||||||
@@ -1414,7 +1599,7 @@ THandle * CSelectableCore::OpenTCPclientSocket( THandle * Handle, bool DelayReso
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set status
|
// Set status
|
||||||
ChangeState( Handle, csWaitingtoOpen );
|
HandleState( Handle, csWaitingtoOpen );
|
||||||
return Handle;
|
return Handle;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1430,17 +1615,16 @@ 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
|
HandleState( Handle, csFailed );
|
||||||
Handle->FD = -1;
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
int CSelectableCore::Open( THandle * Handle, bool DelayResolve )
|
int CSelectableCore::Open( THandle * Handle )
|
||||||
{
|
{
|
||||||
THandle * NewHandle = NULL;
|
THandle * NewHandle = NULL;
|
||||||
|
|
||||||
@@ -1467,16 +1651,16 @@ int CSelectableCore::Open( THandle * Handle, bool DelayResolve )
|
|||||||
NewHandle = OpenUNIXclientSocket( Handle );
|
NewHandle = OpenUNIXclientSocket( Handle );
|
||||||
break;
|
break;
|
||||||
case ctUDPserver :
|
case ctUDPserver :
|
||||||
NewHandle = OpenUDPserverSocket( Handle, DelayResolve );
|
NewHandle = OpenUDPserverSocket( Handle );
|
||||||
break;
|
break;
|
||||||
case ctUDPclient :
|
case ctUDPclient :
|
||||||
NewHandle = OpenUDPclientSocket( Handle, DelayResolve );
|
NewHandle = OpenUDPclientSocket( Handle );
|
||||||
break;
|
break;
|
||||||
case ctTCPserver :
|
case ctTCPserver :
|
||||||
NewHandle = OpenTCPserverSocket( Handle, DelayResolve );
|
NewHandle = OpenTCPserverSocket( Handle );
|
||||||
break;
|
break;
|
||||||
case ctTCPclient :
|
case ctTCPclient :
|
||||||
NewHandle = OpenTCPclientSocket( Handle, DelayResolve );
|
NewHandle = OpenTCPclientSocket( Handle );
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
NewHandle = NULL;
|
NewHandle = NULL;
|
||||||
@@ -1532,7 +1716,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)
|
||||||
@@ -1616,15 +1809,8 @@ bool CSelectableCore::Close( THandle * Handle, bool QuickReopen )
|
|||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Remove from Select List
|
// Change State
|
||||||
if (!Fail && Selector) {
|
HandleState( 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;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -1680,7 +1866,7 @@ bool CSelectableCore::Read( THandle * Handle )
|
|||||||
if (Handle->Type == ctTCPremote) {
|
if (Handle->Type == ctTCPremote) {
|
||||||
OpenTCPremoteSocket( Handle );
|
OpenTCPremoteSocket( Handle );
|
||||||
} else if (Handle->Type == ctTCPclient) {
|
} else if (Handle->Type == ctTCPclient) {
|
||||||
OpenTCPclientSocket( Handle, true );
|
OpenTCPclientSocket( Handle );
|
||||||
} else if (Handle->Type == ctUNIXremote) {
|
} else if (Handle->Type == ctUNIXremote) {
|
||||||
OpenUNIXremoteSocket( Handle );
|
OpenUNIXremoteSocket( Handle );
|
||||||
} else if (Handle->Type == ctUNIXclient) {
|
} else if (Handle->Type == ctUNIXclient) {
|
||||||
@@ -1842,7 +2028,7 @@ bool CSelectableCore::Write( THandle * Handle )
|
|||||||
else if (Timeout( Handle->LastAction, Handle->ReopenDelay ))
|
else if (Timeout( Handle->LastAction, Handle->ReopenDelay ))
|
||||||
{
|
{
|
||||||
// Attempt to re-open port
|
// Attempt to re-open port
|
||||||
Open( Handle, true );
|
Open( Handle );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1856,7 +2042,7 @@ bool CSelectableCore::Write( THandle * Handle )
|
|||||||
if (Handle->Type == ctTCPremote) {
|
if (Handle->Type == ctTCPremote) {
|
||||||
OpenTCPremoteSocket( Handle );
|
OpenTCPremoteSocket( Handle );
|
||||||
} else if (Handle->Type == ctTCPclient) {
|
} else if (Handle->Type == ctTCPclient) {
|
||||||
OpenTCPclientSocket( Handle, true );
|
OpenTCPclientSocket( Handle );
|
||||||
} else if (Handle->Type == ctUNIXremote) {
|
} else if (Handle->Type == ctUNIXremote) {
|
||||||
OpenUNIXremoteSocket( Handle );
|
OpenUNIXremoteSocket( Handle );
|
||||||
} else if (Handle->Type == ctUNIXclient) {
|
} else if (Handle->Type == ctUNIXclient) {
|
||||||
@@ -2007,11 +2193,11 @@ int CSelectableCore::OutputHandle( THandle * Handle, const char * Data, int Len
|
|||||||
else if (Timeout( Handle->LastAction, Handle->ReopenDelay ))
|
else if (Timeout( Handle->LastAction, Handle->ReopenDelay ))
|
||||||
{
|
{
|
||||||
// Complete opening process
|
// Complete opening process
|
||||||
Open( Handle, true );
|
Open( Handle );
|
||||||
|
|
||||||
// Check if Handle is open
|
// Check if Handle is open
|
||||||
if (Handle->State == csOpenRequest) {
|
if (Handle->State == csPreparing) {
|
||||||
if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Handle '%s' - Input rejected, Request to resolve (auto-managed) Handle",
|
if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Handle '%s' - Input rejected, Resolving (auto-managed) Handle",
|
||||||
ProcessName, Name, Handle->Name );
|
ProcessName, Name, Handle->Name );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -2153,16 +2339,14 @@ bool CSelectableCore::Process()
|
|||||||
while (Handle)
|
while (Handle)
|
||||||
{
|
{
|
||||||
// Auto manage handles
|
// Auto manage handles
|
||||||
if ((Handle->State == csOpenRequest)) {
|
if (Handle->State == csPrepared) {
|
||||||
// Resolve then open socket
|
// Proceed to open
|
||||||
if (Timeout( Handle->LastAction, Handle->ResolveDelay )) {
|
Open( Handle );
|
||||||
Open( Handle, false );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (((Handle->State != csOpen) && Handle->AutoManage && Handle->Persistent) ) {
|
else if ((Handle->State != csOpen) && Handle->AutoManage && Handle->Persistent) {
|
||||||
// Try to re-open port after delay
|
// Try to re-open port after delay
|
||||||
if (Timeout( Handle->LastAction, Handle->ReopenDelay )) {
|
if (Timeout( Handle->LastAction, Handle->ReopenDelay )) {
|
||||||
Open( Handle, false );
|
Open( Handle );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2471,3 +2655,80 @@ bool CSelectableCore::ReadSerialConfig( THandle * Handle )
|
|||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool CSelectableCore::BuildArgs( const char * ExecPath, int &Count, char * Args[] )
|
||||||
|
{
|
||||||
|
bool ParamStarted = false;
|
||||||
|
bool OpenQuotes = false;
|
||||||
|
char * MatchPos = NULL;
|
||||||
|
char * StartPos = NULL;
|
||||||
|
int Len;
|
||||||
|
|
||||||
|
// Validate
|
||||||
|
if (!ExecPath || !*ExecPath) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Split params
|
||||||
|
MatchPos = (char*)ExecPath;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
// Look for whitespace
|
||||||
|
if (!ParamStarted)
|
||||||
|
{
|
||||||
|
// Quotes starts quoted parameter
|
||||||
|
if (*MatchPos == '"') {
|
||||||
|
ParamStarted = true;
|
||||||
|
OpenQuotes = true;
|
||||||
|
StartPos = MatchPos+1; // Skip starting quote
|
||||||
|
}
|
||||||
|
// Non-whitespace starts normal parameter
|
||||||
|
else if ((*MatchPos != ' ') && (*MatchPos != 0)) {
|
||||||
|
ParamStarted = true;
|
||||||
|
StartPos = MatchPos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (OpenQuotes)
|
||||||
|
{
|
||||||
|
// Another quote ends parameter
|
||||||
|
if (*MatchPos == '"') {
|
||||||
|
Len = MatchPos-StartPos-1; // Skip end quote
|
||||||
|
Args[Count] = (char*)malloc( Len+1 );
|
||||||
|
strncpy( Args[Count], StartPos, Len );
|
||||||
|
Args[Count][Len] = 0;
|
||||||
|
Count++;
|
||||||
|
ParamStarted = false;
|
||||||
|
OpenQuotes = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Whitespace ends parameter
|
||||||
|
if ((*MatchPos == ' ') || (*MatchPos == 0)) {
|
||||||
|
Len = MatchPos-StartPos;
|
||||||
|
Args[Count] = (char*)malloc( Len+1 );
|
||||||
|
strncpy( Args[Count], StartPos, Len );
|
||||||
|
Args[Count][Len] = 0;
|
||||||
|
Count++;
|
||||||
|
ParamStarted = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Next char, unless NULL
|
||||||
|
if (*MatchPos)
|
||||||
|
MatchPos++;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check all parameters closed
|
||||||
|
if (ParamStarted) {
|
||||||
|
Count = 0;
|
||||||
|
Args[0] = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set last Param to NULL
|
||||||
|
Args[Count] = NULL;
|
||||||
|
|
||||||
|
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"
|
||||||
@@ -22,8 +24,8 @@ typedef enum { ctNone = 0, ctSerial = 1, ctLinePrinter = 2, ctForkPipe = 3, ctUN
|
|||||||
const char ConnectTypeName[][20] = { "None", "Serial Port", "Line Printer", "Fork Pipe", "UNIX Server", "UNIX Client", "UNIX Remote Client",
|
const char ConnectTypeName[][20] = { "None", "Serial Port", "Line Printer", "Fork Pipe", "UNIX Server", "UNIX Client", "UNIX Remote Client",
|
||||||
"UDP Server", "UDP Client", "UDP Remote Client", "TCP Server", "TCP Client", "TCP Remote Client", "Custom" };
|
"UDP Server", "UDP Client", "UDP Remote Client", "TCP Server", "TCP Client", "TCP Remote Client", "Custom" };
|
||||||
|
|
||||||
typedef enum { csNone = 0, csOpenRequest = 1, csWaitingtoOpen = 2, csOpen = 3, csDataWaiting = 4, csClosed = 5, csFailed = 6 } EConnectState;
|
typedef enum { csNone = 0, csPreparing = 1, csPrepared = 2, csWaitingtoOpen = 3, csOpen = 4, csDataWaiting = 5, csClosed = 6, csFailed = 7 } EConnectState;
|
||||||
const char ConnectStateName[][15] = { "None", "OpenRequest", "WaitingToOpen", "Open", "DataWaiting", "Closed", "Failed" };
|
const char ConnectStateName[][15] = { "None", "Preparing", "Prepared", "WaitingToOpen", "Open", "DataWaiting", "Closed", "Failed" };
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -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;
|
||||||
@@ -88,7 +91,7 @@ struct SHandle {
|
|||||||
long CloseTimeout = 1000; // millisecs of no traffic before closing socket
|
long CloseTimeout = 1000; // millisecs of no traffic before closing socket
|
||||||
|
|
||||||
// Callback functions
|
// Callback functions
|
||||||
FHandleCallback StateCallback[ 7 ] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL};
|
FHandleCallback StateCallback[ 8 ] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||||
|
|
||||||
// Type specific parameters
|
// Type specific parameters
|
||||||
char * Path = NULL; // Port (file)name or Exec path
|
char * Path = NULL; // Port (file)name or Exec path
|
||||||
@@ -103,7 +106,8 @@ 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
|
|
||||||
|
TResolveReq * ResolveReq = NULL; // DNS resolve request
|
||||||
|
|
||||||
// Serial Port config
|
// Serial Port config
|
||||||
bool SerialConfig = false;
|
bool SerialConfig = false;
|
||||||
@@ -132,6 +136,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,8 +206,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 );
|
||||||
|
virtual bool HandleState( THandle * Handle, EConnectState State );
|
||||||
|
|
||||||
// Get Parameters
|
// Get Parameters
|
||||||
inline int GetFD( const char * HandleName ) {
|
inline int GetFD( const char * HandleName ) {
|
||||||
@@ -201,15 +216,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 );
|
||||||
@@ -217,9 +223,6 @@ protected:
|
|||||||
// Buffer operations
|
// Buffer operations
|
||||||
virtual bool ProcessInputBuffer( THandle * Handle, bool Force );
|
virtual bool ProcessInputBuffer( THandle * Handle, bool Force );
|
||||||
|
|
||||||
// Specific operations
|
|
||||||
bool BuildArgs( const char * ExecPath, int &Count, char * Args[] );
|
|
||||||
|
|
||||||
// Convert string to lower case
|
// Convert string to lower case
|
||||||
inline char * strlcase( char * Str ) {
|
inline char * strlcase( char * Str ) {
|
||||||
for (char * Ch = Str; *Ch; Ch++ )
|
for (char * Ch = Str; *Ch; Ch++ )
|
||||||
@@ -233,19 +236,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))
|
||||||
@@ -254,7 +255,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 );
|
||||||
@@ -262,17 +263,14 @@ 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 ) = 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 );
|
||||||
|
|
||||||
// FD operations
|
// FD operations
|
||||||
inline virtual int Open( const char * HandleName, bool DelayResolve = false ) { return (Open( GetHandle( HandleName ), DelayResolve)); };
|
inline virtual int Open( const char * HandleName ) { return (Open( GetHandle( HandleName ))); };
|
||||||
|
|
||||||
inline virtual bool Close( const char * HandleName, bool QuickReopen ) { return (Close( GetHandle( HandleName ), QuickReopen )); };
|
inline virtual bool Close( const char * HandleName, bool QuickReopen ) { return (Close( GetHandle( HandleName ), QuickReopen )); };
|
||||||
inline virtual bool Close( int FD, bool QuickReopen ) { return (Close( GetHandle( FD ), QuickReopen )); };
|
inline virtual bool Close( int FD, bool QuickReopen ) { return (Close( GetHandle( FD ), QuickReopen )); };
|
||||||
@@ -294,8 +292,8 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Function Interface
|
// Function Interface
|
||||||
virtual int Input( const char * ChannelName, const char * Buffer, int BufLen = -1 );
|
virtual int Input( const char * ChannelName, const char * SourceRef, const char * Data, int Len = -1 );
|
||||||
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();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -304,6 +302,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 );
|
||||||
@@ -318,18 +318,27 @@ protected:
|
|||||||
THandle * OpenUNIXremoteSocket( THandle * Handle );
|
THandle * OpenUNIXremoteSocket( THandle * Handle );
|
||||||
|
|
||||||
// Socket Operations
|
// Socket Operations
|
||||||
bool ResolveAddress( THandle * Handle, bool DelayResolve );
|
bool ResolveAddress( THandle * Handle );
|
||||||
THandle * OpenUDPserverSocket( 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 );
|
||||||
THandle * OpenUDPremoteSocket( THandle * Handle, char * RemoteAddr, char * RemotePort );
|
THandle * OpenUDPremoteSocket( THandle * Handle, char * RemoteAddr, char * RemotePort );
|
||||||
THandle * OpenUDPclientSocket( THandle * Handle, bool DelayResolve );
|
THandle * OpenUDPclientSocket( THandle * Handle );
|
||||||
THandle * OpenTCPserverSocket( THandle * Handle, bool DelayResolve );
|
THandle * OpenTCPserverSocket( THandle * Handle );
|
||||||
THandle * OpenTCPremoteSocket( THandle * Handle );
|
THandle * OpenTCPremoteSocket( THandle * Handle );
|
||||||
THandle * OpenTCPclientSocket( THandle * Handle, bool DelayResolve );
|
THandle * OpenTCPclientSocket( THandle * Handle );
|
||||||
|
|
||||||
// Mutual Operations
|
// Mutual Operations
|
||||||
int ReadFromUDP( THandle * Handle, char * RemoteAddr, char * RemotePort, char * Data, int MaxLen );
|
int ReadFromUDP( THandle * Handle, char * RemoteAddr, char * RemotePort, char * Data, int MaxLen );
|
||||||
int WriteToUDP( THandle * Handle, const char * Data, int Len, bool Force );
|
int WriteToUDP( THandle * Handle, const char * Data, int Len, bool Force );
|
||||||
|
|
||||||
|
// Specific operations
|
||||||
|
bool BuildArgs( const char * ExecPath, int &Count, char * Args[] );
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Life Cycle
|
// Life Cycle
|
||||||
CSelectableCore( const char * Name, const char * Type = TYPE_SELECTABLE );
|
CSelectableCore( const char * Name, const char * Type = TYPE_SELECTABLE );
|
||||||
@@ -339,22 +348,26 @@ 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 );
|
||||||
bool SetForkPipeHandle( THandle * Handle, const char * ExecPath );
|
bool SetForkPipeHandle( THandle * Handle, const char * ExecPath );
|
||||||
bool SetUnixHandle( THandle * Handle, EConnectType Type, const char * FileName, short Queue );
|
bool SetUnixHandle( THandle * Handle, EConnectType Type, const char * FileName, short Queue );
|
||||||
bool SetSocketHandle( THandle * Handle, EConnectType Type, const char * HostName, const char * PortName, short Queue, long ResolveDelay );
|
bool SetSocketHandle( THandle * Handle, EConnectType Type, const char * HostName, const char * PortName, short Queue );
|
||||||
|
|
||||||
// FD Operations
|
// FD Operations
|
||||||
virtual int Open( THandle * Handle, bool DelayResolve = false );
|
virtual int Open( THandle * Handle );
|
||||||
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 );
|
||||||
|
|
||||||
// Function Interface
|
// Function Interface
|
||||||
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 );
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
43
TimingCore.h
43
TimingCore.h
@@ -12,6 +12,7 @@
|
|||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
// redA Libraries
|
// redA Libraries
|
||||||
/* none */
|
/* none */
|
||||||
@@ -23,19 +24,22 @@ inline void SetInterval( timeval * Time, long MilliSeconds ) {
|
|||||||
Time->tv_sec = MilliSeconds / 1000;
|
Time->tv_sec = MilliSeconds / 1000;
|
||||||
Time->tv_usec = (MilliSeconds % 1000) * 1000;
|
Time->tv_usec = (MilliSeconds % 1000) * 1000;
|
||||||
};
|
};
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
// Mark start time
|
// Mark start time
|
||||||
inline void SetStartTime( timeval *StartTime ) {
|
inline void SetStartTime( timeval *StartTime ) {
|
||||||
gettimeofday( StartTime, NULL );
|
gettimeofday( StartTime, NULL );
|
||||||
};
|
};
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
// Clear timer
|
// Clear timer
|
||||||
inline void ClearStartTime( timeval * StartTime ) {
|
inline void ClearStartTime( timeval * StartTime ) {
|
||||||
StartTime->tv_sec = 0;
|
StartTime->tv_sec = 0;
|
||||||
StartTime->tv_usec = 0;
|
StartTime->tv_usec = 0;
|
||||||
};
|
};
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
// Time passed since start time
|
// Milli-seconds passed since start time
|
||||||
inline long TimePassed( timeval StartTime ) {
|
inline long TimePassed( timeval StartTime ) {
|
||||||
timeval CurrTime;
|
timeval CurrTime;
|
||||||
long Duration;
|
long Duration;
|
||||||
@@ -47,17 +51,54 @@ inline long TimePassed( timeval StartTime ) {
|
|||||||
Duration = LONG_MAX;
|
Duration = LONG_MAX;
|
||||||
return Duration;
|
return Duration;
|
||||||
};
|
};
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
inline long SecondsPassed( timeval StartTime ) {
|
||||||
|
timeval CurrTime;
|
||||||
|
long Duration;
|
||||||
|
|
||||||
|
gettimeofday( &CurrTime, NULL );
|
||||||
|
Duration = CurrTime.tv_sec - StartTime.tv_sec;
|
||||||
|
return Duration;
|
||||||
|
};
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
// Time remaining from Start time to given time out
|
// Time remaining from Start time to given time out
|
||||||
inline long TimeLeft( timeval StartTime, long MilliSeconds ) {
|
inline long TimeLeft( timeval StartTime, long MilliSeconds ) {
|
||||||
return (MilliSeconds - TimePassed(StartTime));
|
return (MilliSeconds - TimePassed(StartTime));
|
||||||
};
|
};
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
// Has give time expired after start time
|
// Has give time expired after start time
|
||||||
inline bool Timeout( timeval StartTime, long MilliSeconds ) {
|
inline bool Timeout( timeval StartTime, long MilliSeconds ) {
|
||||||
return ((TimePassed(StartTime) > MilliSeconds)? true : false);
|
return ((TimePassed(StartTime) > MilliSeconds)? true : false);
|
||||||
};
|
};
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Get Upcount in seconds from start time (with string output)
|
||||||
|
inline long GetUpCounter( timeval StartTime, char * TextStr ) {
|
||||||
|
long Duration;
|
||||||
|
int Days, Hours, Minutes, Seconds;
|
||||||
|
|
||||||
|
// Get duration
|
||||||
|
Duration = SecondsPassed( StartTime );
|
||||||
|
|
||||||
|
// Create string
|
||||||
|
if (TextStr) {
|
||||||
|
// Get Parts
|
||||||
|
Minutes = Duration / 60;
|
||||||
|
Hours = Minutes / 60;
|
||||||
|
Days = Hours / 24;
|
||||||
|
|
||||||
|
// Get modulus
|
||||||
|
Seconds = Duration % 60;
|
||||||
|
Minutes = Minutes % 60;
|
||||||
|
Hours = Hours % 24;
|
||||||
|
|
||||||
|
sprintf( TextStr, "%dd %02d:%02d:%02d", Days, Hours, Minutes, Seconds );
|
||||||
|
}
|
||||||
|
return Duration;
|
||||||
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
#endif /* REDACORE_TIMINGCORE_H_ */
|
#endif /* REDACORE_TIMINGCORE_H_ */
|
||||||
|
|||||||
@@ -40,7 +40,10 @@ char * BytesToSafeStr( const char * Bytes, const int Len, const bool NoCrLf, con
|
|||||||
|
|
||||||
// Remove special char
|
// Remove special char
|
||||||
for (int i=0; i<Len; i++) {
|
for (int i=0; i<Len; i++) {
|
||||||
if (((Bytes[i] < 32) || (Bytes[i] > 126)) ||
|
if ((Bytes[i] == '\r') || (Bytes[i] == '\n')) {
|
||||||
|
*BufPos = (NoCrLf)? SpecChar : Bytes[i];
|
||||||
|
}
|
||||||
|
else if (((Bytes[i] < 32) || (Bytes[i] > 126)) ||
|
||||||
(NoCrLf && ((Bytes[i] == '\r') || (Bytes[i] == '\n')))) {
|
(NoCrLf && ((Bytes[i] == '\r') || (Bytes[i] == '\n')))) {
|
||||||
*BufPos = SpecChar;
|
*BufPos = SpecChar;
|
||||||
}
|
}
|
||||||
@@ -75,7 +78,7 @@ char * BytesToHexStr( const char * Bytes, const int Len, const char * Separator,
|
|||||||
|
|
||||||
// Print Hex values of individual bytes
|
// Print Hex values of individual bytes
|
||||||
for (int i=0; i<Len; i++) {
|
for (int i=0; i<Len; i++) {
|
||||||
sprintf( BufPos, "%s%02X", ((First)? "" : Separator), (unsigned char)Bytes[i] );
|
sprintf( BufPos, "%s%02X", ((First || !Separator)? "" : Separator), (unsigned char)Bytes[i] );
|
||||||
BufPos += (First)? 2 : 2+SepLen;
|
BufPos += (First)? 2 : 2+SepLen;
|
||||||
First = false;
|
First = false;
|
||||||
}
|
}
|
||||||
@@ -105,7 +108,7 @@ char * BytesToBinStr( const char * Bytes, const int Len, const char * Separator,
|
|||||||
|
|
||||||
// Print each byte as 8-bit binary
|
// Print each byte as 8-bit binary
|
||||||
for (int i=0; i<Len; i++) {
|
for (int i=0; i<Len; i++) {
|
||||||
sprintf( BufPos, "%s%c%c%c%c%c%c%c%c", ((First)? "" : Separator),
|
sprintf( BufPos, "%s%c%c%c%c%c%c%c%c", ((First || !Separator)? "" : Separator),
|
||||||
(Bytes[i] & 0x80)?'1':'0', (Bytes[i] & 0x40)?'1':'0', (Bytes[i] & 0x20)?'1':'0', (Bytes[i] & 0x10)?'1':'0',
|
(Bytes[i] & 0x80)?'1':'0', (Bytes[i] & 0x40)?'1':'0', (Bytes[i] & 0x20)?'1':'0', (Bytes[i] & 0x10)?'1':'0',
|
||||||
(Bytes[i] & 0x08)?'1':'0', (Bytes[i] & 0x04)?'1':'0', (Bytes[i] & 0x02)?'1':'0', (Bytes[i] & 0x01)?'1':'0' );
|
(Bytes[i] & 0x08)?'1':'0', (Bytes[i] & 0x04)?'1':'0', (Bytes[i] & 0x02)?'1':'0', (Bytes[i] & 0x01)?'1':'0' );
|
||||||
BufPos += (First)? 8 : 8+SepLen;
|
BufPos += (First)? 8 : 8+SepLen;
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ inline u_int8_t HexToInt( char Digit ) {
|
|||||||
else if ((Digit >= 'a') && (Digit <= 'f')) return (Digit - 'a'+10);
|
else if ((Digit >= 'a') && (Digit <= 'f')) return (Digit - 'a'+10);
|
||||||
else return 0;
|
else return 0;
|
||||||
}
|
}
|
||||||
char * HexStrToBytes( const char * Str, const int Len, const char * Separator, char * OutBuf );
|
char * HexStrToBytes( const char * Str, const int Len, const char * Separator = NULL, char * OutBuf = NULL );
|
||||||
char * BinStrToBytes( const char * Str, const int Len, const char *Separator = NULL, char * OutBuf = NULL );
|
char * BinStrToBytes( const char * Str, const int Len, const char * Separator = NULL, char * OutBuf = NULL );
|
||||||
|
|
||||||
// Search string data
|
// Search string data
|
||||||
char * StrSearch( const char * Haystack, const char * Needle, const int hLen = 0, const int nLen = 0 );
|
char * StrSearch( const char * Haystack, const char * Needle, const int hLen = 0, const int nLen = 0 );
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ bool CWatchdogCore::Init( CDataMember * FunctionConfig )
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Set specific parameters
|
// Set specific parameters
|
||||||
SetInterval( FunctionConfig->GetChInt( "Parameters/PingInterval", 500, true ));
|
SetInterval( Config->GetChInt( "PingInterval", 500, true ));
|
||||||
|
|
||||||
// Create handle and set reference, if not done
|
// Create handle and set reference, if not done
|
||||||
if (!(Ping = GetHandle( "Ping" )))
|
if (!(Ping = GetHandle( "Ping" )))
|
||||||
|
|||||||
Reference in New Issue
Block a user