Important Update:
- Split SelectableCore.cpp into two classes: SelectableBare & SelectableCore
This commit is contained in:
@@ -40,7 +40,7 @@ CFunctionCore * NewSelectableCore( const char * Name ) {
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
CSelectableCore::CSelectableCore( const char * pName, const char * pType ) : CFunctionCore( pName, pType )
|
||||
CSelectableCore::CSelectableCore( const char * pName, const char * pType ) : CSelectableBare( pName, pType )
|
||||
{
|
||||
// Quick access
|
||||
Selector = Application->Selector;
|
||||
@@ -243,107 +243,6 @@ bool CSelectableCore::Init( CDataMember * FunctionConfig )
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
THandle * CSelectableCore::CreateHandle( const char * HandleName, bool CreateChannel )
|
||||
{
|
||||
THandle ** Handle = NULL;
|
||||
|
||||
// Find Handle by Name or get end of list
|
||||
Handle = &FirstHandle;
|
||||
while ( *Handle && strcmp( HandleName, (*Handle)->Name ))
|
||||
Handle = &((*Handle)->Next);
|
||||
|
||||
// Create if necessary
|
||||
if (!*Handle)
|
||||
{
|
||||
// Create File handle at end of list
|
||||
*Handle = (THandle*)calloc( 1, sizeof(THandle) );
|
||||
|
||||
// Set name
|
||||
if (HandleName) {
|
||||
(*Handle)->Name = (char*)malloc( strlen(HandleName)+1 );
|
||||
strcpy( (*Handle)->Name, HandleName );
|
||||
}
|
||||
|
||||
// Set File Descriptor
|
||||
(*Handle)->FD = -1;
|
||||
|
||||
// Log event
|
||||
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Created",
|
||||
ProcessName, Name, HandleName );
|
||||
}
|
||||
|
||||
// Create Matching Channel
|
||||
if (CreateChannel) {
|
||||
(*Handle)->Channel = AddChannel( HandleName );
|
||||
}
|
||||
|
||||
return *Handle;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool CSelectableCore::RemoveHandle( THandle * Handle )
|
||||
{
|
||||
THandle ** HandlePtr = NULL;
|
||||
|
||||
// Validate
|
||||
if (!Handle || (Handle->State == csOpen) || (Handle->State == csWaitingtoOpen)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find in List
|
||||
HandlePtr = &FirstHandle;
|
||||
while (*HandlePtr && (*HandlePtr != Handle)) {
|
||||
HandlePtr = &((*HandlePtr)->Next);
|
||||
}
|
||||
// Remove from list if found
|
||||
if (*HandlePtr) {
|
||||
*HandlePtr = (*HandlePtr)->Next;
|
||||
}
|
||||
|
||||
// Log event
|
||||
if (Log) Log->Message( LogLevel, dlMedium, "%s/%s: Handle '%s' - Removed",
|
||||
ProcessName, Name, Handle->Name );
|
||||
|
||||
// Destroy Child handle
|
||||
DestroyHandle( Handle );
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool CSelectableCore::DestroyHandle( THandle * Handle )
|
||||
{
|
||||
// Validate Handle
|
||||
if (!Handle)
|
||||
return false;
|
||||
|
||||
// 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->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
|
||||
free( Handle );
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool CSelectableCore::SetSerialHandle( THandle * Handle, const char * FileName )
|
||||
{
|
||||
// Validate
|
||||
@@ -510,122 +409,6 @@ bool CSelectableCore::SetSocketHandle( THandle * Handle, EConnectType Type, con
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
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::SetCallback( THandle * Handle, EConnectState pState, FHandleCallback pCallback )
|
||||
{
|
||||
// Validate
|
||||
if (!Handle) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set callback
|
||||
Handle->StateCallback[ (int)pState ] = pCallback;
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool CSelectableCore::SetAutoManage( THandle * Handle, bool AutoManage, bool Persistent, int ReopenDelay, int CloseTimeout )
|
||||
{
|
||||
// Validate
|
||||
if (!Handle) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set params
|
||||
Handle->AutoManage = AutoManage;
|
||||
Handle->Persistent = Persistent;
|
||||
Handle->ReopenDelay = ReopenDelay;
|
||||
Handle->CloseTimeout = CloseTimeout;
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool CSelectableCore::SetInBuffer( THandle * Handle, int InBufSize, int InTimeout, const char * InMarker, int InMarkerLen )
|
||||
{
|
||||
// Validate
|
||||
if (!Handle) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Input Buffer
|
||||
if (Handle->InBuffer) {
|
||||
delete Handle->InBuffer;
|
||||
Handle->InBuffer = NULL;
|
||||
}
|
||||
if (InBufSize) {
|
||||
Handle->InBuffer = (CRollingBuffer*) new CRollingBuffer( InBufSize );
|
||||
}
|
||||
|
||||
// Set Input Timeout
|
||||
Handle->InTimeout = InTimeout;
|
||||
|
||||
// Set Input Markers
|
||||
if (InMarkerLen && InMarker) {
|
||||
Handle->InMarkerLen = InMarkerLen;
|
||||
Handle->InMarker = (char *)malloc( InMarkerLen+1 );
|
||||
memcpy( Handle->InMarker, InMarker, InMarkerLen );
|
||||
Handle->InMarker[InMarkerLen] = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool CSelectableCore::SetOutBuffer( THandle * Handle, int OutBufSize )
|
||||
{
|
||||
// Validate
|
||||
if (!Handle) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Output Buffer
|
||||
if (Handle->OutBuffer) {
|
||||
delete Handle->OutBuffer;
|
||||
Handle->OutBuffer = NULL;
|
||||
}
|
||||
if (OutBufSize) {
|
||||
Handle->OutBuffer = (CRollingBuffer*) new CRollingBuffer( OutBufSize );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
THandle * CSelectableCore::OpenSerialPort( THandle * Handle )
|
||||
{
|
||||
// Validate
|
||||
@@ -2153,130 +1936,6 @@ bool CSelectableCore::Write( THandle * Handle )
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool CSelectableCore::ProcessInputBuffer( THandle * Handle, bool Force )
|
||||
{
|
||||
int Pos = 0;
|
||||
int Len = 0;
|
||||
char * Data = NULL;
|
||||
|
||||
// Check if buffered data
|
||||
if (!Handle || !Handle->InBuffer || !Handle->InBuffer->Len()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if forced processed
|
||||
if (Force || !Handle->InMarkerLen)
|
||||
{
|
||||
// Show Packet
|
||||
Len = Handle->InBuffer->Peek( &Data );
|
||||
if (Log) Log->Output( LogLevel, dlHigh, LogOutput, Data, Len, "%s/%s: Handle '%s' - IN-T:",
|
||||
ProcessName, Name, Handle->Name );
|
||||
|
||||
// Write buffer to Outputs
|
||||
if ((Handle->Type == ctTCPremote) || (Handle->Type == ctUNIXremote)) {
|
||||
Output( Handle->Parent->Channel, Data, Len );
|
||||
} else {
|
||||
Output( Handle->Channel, Data, Len );
|
||||
}
|
||||
|
||||
// Clear processed bytes from buffer
|
||||
Handle->InBuffer->Clear( Len );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Search for end of packet marker
|
||||
while (Handle->InBuffer->FindStr( Handle->InMarker, Handle->InMarkerLen, Pos ))
|
||||
{
|
||||
// Show Packet
|
||||
Len = Handle->InBuffer->Peek( &Data, 0, Pos+Handle->InMarkerLen );
|
||||
if (Log) Log->Output( LogLevel, dlHigh, LogOutput, Data, Len, "%s/%s: Handle '%s' - IN-M:",
|
||||
ProcessName, Name, Handle->Name );
|
||||
|
||||
// Write buffer to Outputs
|
||||
if ((Handle->Type == ctTCPremote) || (Handle->Type == ctUNIXremote)) {
|
||||
Output( Handle->Parent->Channel, Data, Len );
|
||||
} else {
|
||||
Output( Handle->Channel, Data, Len );
|
||||
}
|
||||
|
||||
// Clear processed bytes from buffer
|
||||
Handle->InBuffer->Clear( Len );
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
int CSelectableCore::ReadFromFD( int FD, char * Data, int MaxLen )
|
||||
{
|
||||
int BytesRead = 0;
|
||||
int TotalRead = 0;
|
||||
int DataRemain = MaxLen;
|
||||
bool Error = false;
|
||||
|
||||
// Check if buffer created
|
||||
if ((FD == -1) || (MaxLen < 1)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Read Data into buffer
|
||||
while (DataRemain)
|
||||
{
|
||||
// Read from file descriptor
|
||||
BytesRead = read( FD, &Data[TotalRead], DataRemain );
|
||||
if ((BytesRead < 0)) {
|
||||
Error = true;
|
||||
errno = (!BytesRead)? 0 : errno; // No error if no bytes written
|
||||
break;
|
||||
}
|
||||
|
||||
// Update Data Pointers
|
||||
TotalRead += BytesRead;
|
||||
DataRemain -= BytesRead;
|
||||
|
||||
if (DataRemain) {
|
||||
usleep( 500 );
|
||||
}
|
||||
}
|
||||
return (Error)? -TotalRead : TotalRead; // Report negative total on error
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
int CSelectableCore::WriteToFD( int FD, const char * Data, int Len, bool Force )
|
||||
{
|
||||
int BytesWritten = 0;
|
||||
int TotalWritten = 0;
|
||||
int DataRemain = (Len != -1)? Len : (Data)? strlen(Data) : 0;
|
||||
bool Error = false;
|
||||
|
||||
// Check if buffer created
|
||||
if ((FD == -1) || !DataRemain) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Read Data into buffer
|
||||
while (DataRemain)
|
||||
{
|
||||
// Read from file descriptor
|
||||
BytesWritten = write( FD, &Data[TotalWritten], DataRemain );
|
||||
if ((BytesWritten <= 0) && (!Force || (errno != EAGAIN))) {
|
||||
Error = true;
|
||||
errno = (!BytesWritten)? 0 : errno; // No error if no bytes written
|
||||
break;
|
||||
}
|
||||
|
||||
// Update Data Pointers
|
||||
TotalWritten += BytesWritten;
|
||||
DataRemain -= BytesWritten;
|
||||
|
||||
if (DataRemain) {
|
||||
usleep( 500 );
|
||||
}
|
||||
}
|
||||
return (Error)? -TotalWritten : TotalWritten; // Report negative total on error
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
int CSelectableCore::ReadFromUDP( THandle * Handle, char * RemoteAddr, char * RemotePort, char * Data, int MaxLen )
|
||||
{
|
||||
int BytesRead = 0;
|
||||
@@ -2324,62 +1983,6 @@ int CSelectableCore::WriteToUDP( THandle * Handle, const char * Data, int Len, b
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
int CSelectableCore::Input( const char * ChannelName, const char * Data, int Len )
|
||||
{
|
||||
TChannel * Channel = NULL;
|
||||
THandle * Handle = NULL;
|
||||
int HandleCount = 0;
|
||||
int TempWritten = 0;
|
||||
int BytesWritten = 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' - Input rejected, Channel not found",
|
||||
ProcessName, Name, ChannelName );
|
||||
return 0;
|
||||
}
|
||||
else if (!Channel->InputEnabled) {
|
||||
// Channel disabled
|
||||
if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Channel '%s' - Input rejected, Channel input disabled",
|
||||
ProcessName, Name, ChannelName );
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Log event
|
||||
if (Log) Log->Output( LogLevel, dlHigh, LogOutput, Data, Len, "%s/%s: Channel '%s' - IN:",
|
||||
ProcessName, Name, ChannelName );
|
||||
|
||||
// Find Linked handle
|
||||
Handle = FirstHandle;
|
||||
while( Handle )
|
||||
{
|
||||
if (Handle->Channel && !strcasecmp( ChannelName, Handle->Channel->Name ))
|
||||
{
|
||||
// Input to Handle
|
||||
TempWritten = OutputHandle( Handle, Data, Len );
|
||||
BytesWritten = (TempWritten > BytesWritten)? TempWritten : BytesWritten;
|
||||
HandleCount++;
|
||||
}
|
||||
Handle = Handle->Next;
|
||||
}
|
||||
|
||||
if (!HandleCount) {
|
||||
// Handle not found
|
||||
if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Channel '%s' - Input rejected, No Handles not found",
|
||||
ProcessName, Name, ChannelName );
|
||||
return 0;
|
||||
}
|
||||
|
||||
return BytesWritten;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
int CSelectableCore::OutputHandle( THandle * Handle, const char * Data, int Len )
|
||||
{
|
||||
THandle * ChildHandle = NULL;
|
||||
@@ -2868,82 +2471,3 @@ bool CSelectableCore::ReadSerialConfig( THandle * Handle )
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
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;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
Reference in New Issue
Block a user