Major Update:
- Minor fix: Set correct names in comments at top of file - New FileCore Class: - Writing data to output file - BufferCore: - Check for "EAGAIN" on write and retry write - FunctionCore: - Add new Output method that references LocalIO directly - SelectableCore: - New method SetAutomanage to specify auto re-open parameters - Re-open timer implemented to slow re-open events - Only call ProcessBuffer() if data received on socket - Force processing input data when no input marker set - Use new Output method to simplify code - Bug fix: Read correctly from buffer on multiple reads/writes on FD - Check for "EAGAIN" on write to FD and retry write
This commit is contained in:
@@ -13,6 +13,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -310,8 +311,9 @@ int CBuffer::ReadFromFD( int Handle, int MaxRead )
|
|||||||
// Read from file descriptor
|
// Read from file descriptor
|
||||||
BufRemain = BufSize - BufEnd;
|
BufRemain = BufSize - BufEnd;
|
||||||
BytesRead = read( Handle, &Buffer[BufEnd], ((BufRemain > DataRemain)? DataRemain : BufRemain) );
|
BytesRead = read( Handle, &Buffer[BufEnd], ((BufRemain > DataRemain)? DataRemain : BufRemain) );
|
||||||
if (BytesRead <= 0)
|
if (BytesRead <= 0) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Update Buffer Pointers
|
// Update Buffer Pointers
|
||||||
DataRemain -= BytesRead;
|
DataRemain -= BytesRead;
|
||||||
@@ -328,7 +330,6 @@ int CBuffer::ReadFromFD( int Handle, int MaxRead )
|
|||||||
BufStart = BufEnd;
|
BufStart = BufEnd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return TotalRead;
|
return TotalRead;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -355,8 +356,9 @@ int CBuffer::WriteToFD( int Handle, int MaxLen )
|
|||||||
// Read from file descriptor
|
// Read from file descriptor
|
||||||
BufRemain = BufSize - ReadPos;
|
BufRemain = BufSize - ReadPos;
|
||||||
BytesWritten = write( Handle, &Buffer[ReadPos], ((BufRemain > DataRemain)? DataRemain : BufRemain) );
|
BytesWritten = write( Handle, &Buffer[ReadPos], ((BufRemain > DataRemain)? DataRemain : BufRemain) );
|
||||||
if (BytesWritten <= 0)
|
if ((BytesWritten <= 0) && (errno != EAGAIN)) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Update Data Pointers
|
// Update Data Pointers
|
||||||
TotalWritten += BytesWritten;
|
TotalWritten += BytesWritten;
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
PROJECT(lib_redAcore)
|
PROJECT(lib_redAcore)
|
||||||
|
|
||||||
ADD_LIBRARY(redAcore TimingCore.cpp LogCore.cpp SignalCore.cpp BufferCore.cpp FunctionCore.cpp SelectCore.cpp SelectableCore.cpp)
|
ADD_LIBRARY(redAcore TimingCore.cpp LogCore.cpp SignalCore.cpp BufferCore.cpp FunctionCore.cpp FileCore.cpp SelectCore.cpp SelectableCore.cpp)
|
||||||
|
|||||||
330
FileCore.cpp
Normal file
330
FileCore.cpp
Normal file
@@ -0,0 +1,330 @@
|
|||||||
|
/*
|
||||||
|
* FileCore.cpp
|
||||||
|
*
|
||||||
|
* Created on: 1 Jun 2016
|
||||||
|
* Author: wentzelc
|
||||||
|
*/
|
||||||
|
|
||||||
|
// redA Libraries
|
||||||
|
#include "FileCore.h"
|
||||||
|
#include "FunctionCore.h"
|
||||||
|
#include "TimingCore.h"
|
||||||
|
#include "LogCore.h"
|
||||||
|
|
||||||
|
// Standard C/C++ Libraries
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
const float PI = 3.1415927;
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
CFileCore::CFileCore( const char * Name, EDebugLevel pDebugLevel, int pOuputDisplay ) :
|
||||||
|
CFunctionCore( Name, pDebugLevel, pOuputDisplay )
|
||||||
|
{
|
||||||
|
FirstFile = NULL;
|
||||||
|
|
||||||
|
// temp
|
||||||
|
count = 0;
|
||||||
|
x = 0;
|
||||||
|
// temp
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
CFileCore::~CFileCore()
|
||||||
|
{
|
||||||
|
TFileHandle * NextFile = NULL;
|
||||||
|
|
||||||
|
// Destroy file specs
|
||||||
|
while (FirstFile)
|
||||||
|
{
|
||||||
|
// Close file if open
|
||||||
|
CloseFile( FirstFile );
|
||||||
|
|
||||||
|
// Destroy file parameters
|
||||||
|
if (FirstFile->Name)
|
||||||
|
free( FirstFile->Name );
|
||||||
|
if (FirstFile->Path)
|
||||||
|
free( FirstFile->Path );
|
||||||
|
|
||||||
|
// Destroy File
|
||||||
|
NextFile = FirstFile->Next;
|
||||||
|
delete FirstFile;
|
||||||
|
FirstFile = NextFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
TFileHandle * CFileCore::AddFile( const char * Name, const char * Path, bool Append, bool CreateLocalIO )
|
||||||
|
{
|
||||||
|
TFileHandle ** FileHandle = NULL;
|
||||||
|
|
||||||
|
// Validate
|
||||||
|
if (!Name || !*Name || !Path || !*Path) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find File or End of list
|
||||||
|
FileHandle = &FirstFile;
|
||||||
|
while (*FileHandle && strcmp( Name, (*FileHandle)->Name )) {
|
||||||
|
FileHandle = &((*FileHandle)->Next);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if found
|
||||||
|
if (!*FileHandle)
|
||||||
|
{
|
||||||
|
// Create new
|
||||||
|
*FileHandle = (TFileHandle*)calloc( 1, sizeof(TFileHandle) );
|
||||||
|
|
||||||
|
// Set name & Path
|
||||||
|
(*FileHandle)->Name = (char*)malloc( strlen(Name)+1 );
|
||||||
|
strcpy( (*FileHandle)->Name, Name );
|
||||||
|
(*FileHandle)->Path = (char*)malloc( strlen(Path)+1 );
|
||||||
|
strcpy( (*FileHandle)->Path, Path );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create IO if necessary
|
||||||
|
if (CreateLocalIO) {
|
||||||
|
AddLocalIO( Name );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set Parameters
|
||||||
|
(*FileHandle)->Append = Append;
|
||||||
|
(*FileHandle)->FD = NO_FD;
|
||||||
|
|
||||||
|
// Return File
|
||||||
|
return (*FileHandle);
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool CFileCore::SetFilePersistence( TFileHandle * FileHandle, bool Persistent, int PersistTimeout )
|
||||||
|
{
|
||||||
|
// Validate
|
||||||
|
if (!FileHandle) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set parameters
|
||||||
|
FileHandle->Persistent = Persistent;
|
||||||
|
FileHandle->PersistTimeout = PersistTimeout;
|
||||||
|
|
||||||
|
// Open persistent file
|
||||||
|
if (Persistent && (!PersistTimeout)) {
|
||||||
|
OpenFile( FileHandle );
|
||||||
|
SetStartTime( &(FileHandle->PersistTime) );
|
||||||
|
}
|
||||||
|
// Close non-persistent file
|
||||||
|
else if (!Persistent && isOpen(FileHandle)) {
|
||||||
|
CloseFile( FileHandle );
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool CFileCore::OpenFile( TFileHandle * FileHandle )
|
||||||
|
{
|
||||||
|
// Validate
|
||||||
|
if (!FileHandle) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open file if not already open
|
||||||
|
if (!isOpen( FileHandle ))
|
||||||
|
{
|
||||||
|
// temp
|
||||||
|
//char FilePath[50];
|
||||||
|
//sprintf( FilePath, "%s%03d", FileHandle->Path, x++ );
|
||||||
|
//LogMessage( DebugLevel, dlNone, "f: %s", FilePath );
|
||||||
|
// temp
|
||||||
|
|
||||||
|
// GEt file handle
|
||||||
|
(FileHandle)->FD = open( FileHandle->Path, O_WRONLY | O_CREAT | ((FileHandle->Append)? O_APPEND : O_TRUNC), 0664 );
|
||||||
|
|
||||||
|
// Report event
|
||||||
|
if (isOpen(FileHandle))
|
||||||
|
{
|
||||||
|
// Set timer
|
||||||
|
SetStartTime( &(FileHandle->PersistTime) );
|
||||||
|
|
||||||
|
// temp
|
||||||
|
count = 0;
|
||||||
|
// temp
|
||||||
|
|
||||||
|
// Report result
|
||||||
|
LogMessage( DebugLevel, dlHigh, "%s: File '%s' - Opened", Name, FileHandle->Name );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if failed
|
||||||
|
if (!isOpen(FileHandle))
|
||||||
|
{
|
||||||
|
// Report result
|
||||||
|
LogMessage( DebugLevel, dlHigh, "%s: File '%s' - Could not open (%d) %s", Name, FileHandle->Name, errno, strerror(errno) );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool CFileCore::CloseFile( TFileHandle * FileHandle )
|
||||||
|
{
|
||||||
|
// Validate
|
||||||
|
if (!FileHandle) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close file if not already open
|
||||||
|
if (isOpen(FileHandle))
|
||||||
|
{
|
||||||
|
// Close file
|
||||||
|
close( FileHandle->FD );
|
||||||
|
FileHandle->FD = NO_FD;
|
||||||
|
|
||||||
|
// Report result
|
||||||
|
if (!isOpen(FileHandle)) {
|
||||||
|
LogMessage( DebugLevel, dlHigh, "%s: File '%s' - Closed", Name, FileHandle->Name );
|
||||||
|
} else {
|
||||||
|
LogMessage( DebugLevel, dlHigh, "%s: File '%s' - Could not close", Name, FileHandle->Name );
|
||||||
|
}
|
||||||
|
|
||||||
|
// temp
|
||||||
|
LogMessage( DebugLevel, dlNone, "%s: File '%s' - Bytes written %d (%d)", Name, FileHandle->Name, count, (count-5038848) );
|
||||||
|
// temp
|
||||||
|
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
int CFileCore::ReadFromFD( int FD, char * Data, int MaxLen )
|
||||||
|
{
|
||||||
|
int BytesRead = 0;
|
||||||
|
int TotalRead = 0;
|
||||||
|
int DataRemain = 0;
|
||||||
|
|
||||||
|
// Check if buffer created
|
||||||
|
if ((FD == -1) || !Data) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read Data into buffer
|
||||||
|
DataRemain = (MaxLen == -1)? strlen(Data) : MaxLen;
|
||||||
|
while (DataRemain)
|
||||||
|
{
|
||||||
|
// Read from file descriptor
|
||||||
|
BytesRead = read( FD, &Data[TotalRead], DataRemain );
|
||||||
|
if (BytesRead <= 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Update Data Pointers
|
||||||
|
TotalRead += BytesRead;
|
||||||
|
DataRemain -= BytesRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TotalRead;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
int CFileCore::WriteToFD( int FD, const char * Data, int Len )
|
||||||
|
{
|
||||||
|
int BytesWritten = 0;
|
||||||
|
int TotalWritten = 0;
|
||||||
|
int DataRemain = 0;
|
||||||
|
|
||||||
|
// Check if buffer created
|
||||||
|
if ((FD == -1) || !Data) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read Data into buffer
|
||||||
|
DataRemain = (Len == -1)? strlen(Data) : Len;
|
||||||
|
while (DataRemain)
|
||||||
|
{
|
||||||
|
// Read from file descriptor
|
||||||
|
BytesWritten = write( FD, &Data[TotalWritten], DataRemain );
|
||||||
|
if ((BytesWritten <= 0) && (errno != EAGAIN))
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Update Data Pointers
|
||||||
|
TotalWritten += BytesWritten;
|
||||||
|
DataRemain -= BytesWritten;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TotalWritten;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Manual Data Input/Output
|
||||||
|
int CFileCore::Input( const char * IOName, const char * Data, int MaxLen )
|
||||||
|
{
|
||||||
|
TFileHandle * FileHandle = NULL;
|
||||||
|
int BytesWritten = 0;
|
||||||
|
|
||||||
|
// Validate
|
||||||
|
if (!IOName || !Data) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (MaxLen == -1) {
|
||||||
|
MaxLen = strlen( Data );
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get IO
|
||||||
|
if (!(FileHandle = GetFile( IOName )))
|
||||||
|
{
|
||||||
|
// Log event
|
||||||
|
LogMessage( DebugLevel, dlHigh, "%s: Local IO '%s' - Input rejected, Local IO not found", Name, IOName );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log event
|
||||||
|
//ShowOutput( DebugLevel, dlHigh, OutputDisplay, Data, MaxLen, "%s: Local IO '%s' - IN:", Name, IOName );
|
||||||
|
|
||||||
|
// Open file
|
||||||
|
if (!OpenFile( FileHandle )) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle Incoming data
|
||||||
|
BytesWritten = WriteToFD( FileHandle->FD, Data, MaxLen );
|
||||||
|
SetStartTime( &(FileHandle->PersistTime) );
|
||||||
|
|
||||||
|
// temp
|
||||||
|
count += BytesWritten;
|
||||||
|
// temp
|
||||||
|
|
||||||
|
// Return processed bytes
|
||||||
|
return BytesWritten;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool CFileCore::Process()
|
||||||
|
{
|
||||||
|
TFileHandle * FileHandle;
|
||||||
|
|
||||||
|
// Close Persistent files not used
|
||||||
|
FileHandle = FirstFile;
|
||||||
|
while (FileHandle)
|
||||||
|
{
|
||||||
|
if (isOpen(FileHandle) &&
|
||||||
|
(!FileHandle->Persistent ||
|
||||||
|
(FileHandle->PersistTimeout && Timeout( FileHandle->PersistTime, FileHandle->PersistTimeout )))) {
|
||||||
|
CloseFile( FileHandle );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next
|
||||||
|
FileHandle = FileHandle->Next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
83
FileCore.h
Normal file
83
FileCore.h
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* FileCore.h
|
||||||
|
*
|
||||||
|
* Created on: 1 Jun 2016
|
||||||
|
* Author: wentzelc
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef JOANETELEMETRY_FILECORE_H_
|
||||||
|
#define JOANETELEMETRY_FILECORE_H_
|
||||||
|
|
||||||
|
// redA Libraries
|
||||||
|
#include "FunctionCore.h"
|
||||||
|
|
||||||
|
// Standard C/C++ Libraries
|
||||||
|
/* none */
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
const int NO_FD = -1;
|
||||||
|
|
||||||
|
typedef struct SFileHandle TFileHandle;
|
||||||
|
struct SFileHandle
|
||||||
|
{
|
||||||
|
char * Name; // Quick reference
|
||||||
|
char * Path; // Actual location of file
|
||||||
|
int FD; // File Descriptor
|
||||||
|
|
||||||
|
bool Append; // Append data to end of file
|
||||||
|
|
||||||
|
bool Persistent; // Keep file open after write
|
||||||
|
timeval PersistTime; // Time opened/last written to
|
||||||
|
bool PersistTimeout; // Time to remain open, 0 = permanently open
|
||||||
|
|
||||||
|
TFileHandle * Next;
|
||||||
|
};
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class CFileCore : public CFunctionCore
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
// File
|
||||||
|
TFileHandle * FirstFile;
|
||||||
|
|
||||||
|
// temp
|
||||||
|
int count;
|
||||||
|
int x;
|
||||||
|
// temp
|
||||||
|
|
||||||
|
// Manage File
|
||||||
|
virtual bool OpenFile( TFileHandle * FileHandle );
|
||||||
|
virtual bool CloseFile( TFileHandle * FileHandle );
|
||||||
|
|
||||||
|
virtual int ReadFromFD( int FD, char * Data, int MaxLen );
|
||||||
|
virtual int WriteToFD( int FD, const char * Data, int Len );
|
||||||
|
|
||||||
|
inline TFileHandle * GetFile( const char * Name ) {
|
||||||
|
if (!Name || !*Name) return NULL;
|
||||||
|
TFileHandle * FileHandle = FirstFile;
|
||||||
|
while (FileHandle && strcmp( Name, FileHandle->Name ))
|
||||||
|
FileHandle = FileHandle->Next;
|
||||||
|
return FileHandle;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool isOpen( TFileHandle * FileHandle ) { return (FileHandle->FD != NO_FD); };
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Life cycle
|
||||||
|
CFileCore( const char * Name, EDebugLevel pDebugLevel, int pOuputDisplay );
|
||||||
|
~CFileCore();
|
||||||
|
|
||||||
|
// Manage files
|
||||||
|
virtual TFileHandle * AddFile( const char * Name, const char * Path, bool Append = true, bool CreateLocalIO = true );
|
||||||
|
virtual bool SetFilePersistence( TFileHandle * FileHandle, bool Persistent, int PersistTimeout );
|
||||||
|
|
||||||
|
// Data Input
|
||||||
|
virtual int Input( const char * IOName, const char * Data, int MaxLen = -1 );
|
||||||
|
|
||||||
|
// Processing data
|
||||||
|
virtual bool Process();
|
||||||
|
};
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#endif /* JOANETELEMETRY_FILECORE_H_ */
|
||||||
@@ -260,8 +260,31 @@ int CFunctionCore::Output( const char * IOName, const char * Data, int Len )
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return processed bytes
|
||||||
|
return Output( LocalIO, Data, Len );
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
int CFunctionCore::Output( const TLocalIO * LocalIO, const char * Data, int Len )
|
||||||
|
{
|
||||||
|
TLinkedIO * Output = NULL;
|
||||||
|
|
||||||
|
// Validate
|
||||||
|
if (!LocalIO || !Data) {
|
||||||
|
return 0;
|
||||||
|
} else if (Len == -1) {
|
||||||
|
Len = strlen( Data );
|
||||||
|
}
|
||||||
|
|
||||||
// Log event
|
// Log event
|
||||||
ShowOutput( DebugLevel, dlHigh, OutputDisplay, Data, Len, "%s: Local IO '%s' - OUT:", Name, IOName );
|
ShowOutput( DebugLevel, dlHigh, OutputDisplay, Data, Len, "%s: Local IO '%s' - OUT:", Name, LocalIO->Name );
|
||||||
|
|
||||||
|
// Pass output to all linked inputs
|
||||||
|
Output = LocalIO->FirstOutput;
|
||||||
|
while (Output) {
|
||||||
|
Output->Function->Input( Output->IOName, Data, Len );
|
||||||
|
Output = Output->Next;
|
||||||
|
}
|
||||||
|
|
||||||
// Return processed bytes
|
// Return processed bytes
|
||||||
return Len;
|
return Len;
|
||||||
|
|||||||
@@ -68,6 +68,9 @@ protected:
|
|||||||
return LocalIO;
|
return LocalIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Low Level Local IO interfaces
|
||||||
|
virtual int Output( const TLocalIO * LocalIO, const char * Data, int Len );
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Life cycle
|
// Life cycle
|
||||||
CFunctionCore( const char * ObjectName, EDebugLevel pDebugLevel, int pOuputDisplay );
|
CFunctionCore( const char * ObjectName, EDebugLevel pDebugLevel, int pOuputDisplay );
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Select.cpp
|
* SelectCore.cpp
|
||||||
*
|
*
|
||||||
* Created on: 13 May 2016
|
* Created on: 13 May 2016
|
||||||
* Author: wentzelc
|
* Author: wentzelc
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* CSelectableCore.cpp
|
* SelectableCore.cpp
|
||||||
*
|
*
|
||||||
* Created on: 20 May 2016
|
* Created on: 20 May 2016
|
||||||
* Author: wentzelc
|
* Author: wentzelc
|
||||||
@@ -60,7 +60,7 @@ CSelectableCore::~CSelectableCore()
|
|||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
THandle * CSelectableCore::CreateHandle( const char * HandleName, bool CreateLocalIO, bool AutoManage )
|
THandle * CSelectableCore::CreateHandle( const char * HandleName, bool CreateLocalIO )
|
||||||
{
|
{
|
||||||
THandle ** Handle = NULL;
|
THandle ** Handle = NULL;
|
||||||
|
|
||||||
@@ -73,8 +73,7 @@ THandle * CSelectableCore::CreateHandle( const char * HandleName, bool CreateLo
|
|||||||
if (!*Handle)
|
if (!*Handle)
|
||||||
{
|
{
|
||||||
// Create File handle at end of list
|
// Create File handle at end of list
|
||||||
*Handle = (THandle*)malloc( sizeof(THandle) );
|
*Handle = (THandle*)calloc( 1, sizeof(THandle) );
|
||||||
memset( *Handle, 0, sizeof(THandle) );
|
|
||||||
|
|
||||||
// Set name
|
// Set name
|
||||||
if (HandleName) {
|
if (HandleName) {
|
||||||
@@ -94,9 +93,6 @@ THandle * CSelectableCore::CreateHandle( const char * HandleName, bool CreateLo
|
|||||||
(*Handle)->LocalIO = AddLocalIO( HandleName );
|
(*Handle)->LocalIO = AddLocalIO( HandleName );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set other params
|
|
||||||
(*Handle)->Auto = AutoManage;
|
|
||||||
|
|
||||||
return *Handle;
|
return *Handle;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -238,6 +234,20 @@ bool CSelectableCore::ClearHandle( THandle * Handle )
|
|||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool CSelectableCore::SetAutoManage( THandle * Handle, bool AutoManage, int ReopenTime )
|
||||||
|
{
|
||||||
|
// Validate
|
||||||
|
if (!Handle) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set params
|
||||||
|
Handle->Auto = AutoManage;
|
||||||
|
Handle->ReopenTimeout = ReopenTime;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CSelectableCore::SetBuffers( THandle * Handle, int InBufSize, int OutBufSize, int InTimeout, const char * InMarker, int InMarkerLen )
|
bool CSelectableCore::SetBuffers( THandle * Handle, int InBufSize, int OutBufSize, int InTimeout, const char * InMarker, int InMarkerLen )
|
||||||
{
|
{
|
||||||
// Validate
|
// Validate
|
||||||
@@ -473,7 +483,7 @@ int CSelectableCore::OpenRemoteClientSocket( 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, false );
|
*RemoteClient = CreateHandle( ClientName, false );
|
||||||
SetSocketHandle( *RemoteClient, ctRemoteClient, ClientAddress, 0, Handle->KeepAlive );
|
SetSocketHandle( *RemoteClient, ctRemoteClient, ClientAddress, 0, Handle->KeepAlive );
|
||||||
|
|
||||||
// Copy Parent Buffer setup
|
// Copy Parent Buffer setup
|
||||||
@@ -560,7 +570,7 @@ int CSelectableCore::OpenClientSocket( THandle * Handle )
|
|||||||
(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) ))
|
||||||
{
|
{
|
||||||
// Log Event
|
// Log Event
|
||||||
LogMessage( DebugLevel, dlMedium, "%s: Handle %s - Could not set KeepAlive options [%s:%d] (%s)", Name, Handle->Name, Handle->Address, Handle->PortNo, strerror(errno) );
|
LogMessage( DebugLevel, dlMedium, "%s: Handle '%s' - Could not set KeepAlive options [%s:%d] (%s)", Name, Handle->Name, Handle->Address, Handle->PortNo, strerror(errno) );
|
||||||
|
|
||||||
// Set State
|
// Set State
|
||||||
close( Handle->FD );
|
close( Handle->FD );
|
||||||
@@ -578,7 +588,7 @@ int CSelectableCore::OpenClientSocket( THandle * Handle )
|
|||||||
|
|
||||||
if (!connect( Handle->FD, (struct sockaddr *)&address, addr_len ))
|
if (!connect( Handle->FD, (struct sockaddr *)&address, addr_len ))
|
||||||
{
|
{
|
||||||
LogMessage( DebugLevel, dlMedium, "%s: Handle %s - Client connected [%s:%d]", Name, Handle->Name, Handle->Address, Handle->PortNo );
|
LogMessage( DebugLevel, dlMedium, "%s: Handle '%s' - Client connected [%s:%d]", Name, Handle->Name, Handle->Address, Handle->PortNo );
|
||||||
|
|
||||||
// Add to Select Lists
|
// Add to Select Lists
|
||||||
if (Select) {
|
if (Select) {
|
||||||
@@ -615,8 +625,13 @@ int CSelectableCore::OpenClientSocket( THandle * Handle )
|
|||||||
|
|
||||||
// Close socket
|
// Close socket
|
||||||
close( Handle->FD );
|
close( Handle->FD );
|
||||||
Handle->FD = -1;
|
|
||||||
Handle->State = csFailed;
|
Handle->State = csFailed;
|
||||||
|
|
||||||
|
// Start re-open timer
|
||||||
|
SetStartTime( &(Handle->ReopenStart) );
|
||||||
|
|
||||||
|
// Reset Handle
|
||||||
|
Handle->FD = -1;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -686,6 +701,9 @@ bool CSelectableCore::Close( THandle * Handle, bool CloseChildren )
|
|||||||
Fail = (close( Handle->FD ))? true : false;
|
Fail = (close( Handle->FD ))? true : false;
|
||||||
Handle->State = ((Fail)? csFailed : csClosed);
|
Handle->State = ((Fail)? csFailed : csClosed);
|
||||||
|
|
||||||
|
// Start re-open timer
|
||||||
|
SetStartTime( &(Handle->ReopenStart) );
|
||||||
|
|
||||||
// Show action
|
// Show action
|
||||||
switch (Handle->Type)
|
switch (Handle->Type)
|
||||||
{
|
{
|
||||||
@@ -787,17 +805,16 @@ bool CSelectableCore::Read( THandle * Handle )
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Read File directly into buffer
|
// Read File directly into buffer
|
||||||
if (!Handle->InBuffer || !(BytesRead = Handle->InBuffer->ReadFromFD( Handle->FD ))) {
|
if (Handle->InBuffer && (BytesRead = Handle->InBuffer->ReadFromFD( Handle->FD )))
|
||||||
return false;
|
{
|
||||||
|
// Process Buffer
|
||||||
|
ProcessBuffer( Handle, false );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process Buffer
|
|
||||||
ProcessBuffer( Handle, false );
|
|
||||||
|
|
||||||
// Reset timer
|
// Reset timer
|
||||||
SetStartTime( &(Handle->InStart) );
|
SetStartTime( &(Handle->InStart) );
|
||||||
|
|
||||||
return true;
|
return (bool)BytesRead;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -874,8 +891,6 @@ bool CSelectableCore::ProcessBuffer( THandle * Handle, bool Force )
|
|||||||
int Pos = 0;
|
int Pos = 0;
|
||||||
int Len = 0;
|
int Len = 0;
|
||||||
char * Data = NULL;
|
char * Data = NULL;
|
||||||
TLocalIO * LocalIO = NULL;
|
|
||||||
TLinkedIO * Output = NULL;
|
|
||||||
|
|
||||||
// Check if buffered data
|
// Check if buffered data
|
||||||
if (!Handle || !Handle->InBuffer || !Handle->InBuffer->Len()) {
|
if (!Handle || !Handle->InBuffer || !Handle->InBuffer->Len()) {
|
||||||
@@ -883,7 +898,7 @@ bool CSelectableCore::ProcessBuffer( THandle * Handle, bool Force )
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if forced processed
|
// Check if forced processed
|
||||||
if (Force)
|
if (Force || !Handle->InMarkerLen)
|
||||||
{
|
{
|
||||||
// Show Packet
|
// Show Packet
|
||||||
Len = Handle->InBuffer->Peek( &Data );
|
Len = Handle->InBuffer->Peek( &Data );
|
||||||
@@ -891,18 +906,9 @@ bool CSelectableCore::ProcessBuffer( THandle * Handle, bool Force )
|
|||||||
|
|
||||||
// Write buffer to Outputs
|
// Write buffer to Outputs
|
||||||
if (Handle->Type == ctRemoteClient) {
|
if (Handle->Type == ctRemoteClient) {
|
||||||
LocalIO = Handle->Parent->LocalIO;
|
Output( Handle->Parent->LocalIO, Data, Len );
|
||||||
} else {
|
} else {
|
||||||
LocalIO = Handle->LocalIO;
|
Output( Handle->LocalIO, Data, Len );
|
||||||
}
|
|
||||||
if (LocalIO) {
|
|
||||||
ShowOutput( DebugLevel, dlHigh, OutputDisplay, Data, Len, "%s: LocalIO '%s' - OUT:", Name, LocalIO->Name );
|
|
||||||
|
|
||||||
Output = LocalIO->FirstOutput;
|
|
||||||
while (Output) {
|
|
||||||
Output->Function->Input( Output->IOName, Data, Len );
|
|
||||||
Output = Output->Next;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear processed bytes from buffer
|
// Clear processed bytes from buffer
|
||||||
@@ -919,18 +925,9 @@ bool CSelectableCore::ProcessBuffer( THandle * Handle, bool Force )
|
|||||||
|
|
||||||
// Write buffer to Outputs
|
// Write buffer to Outputs
|
||||||
if (Handle->Type == ctRemoteClient) {
|
if (Handle->Type == ctRemoteClient) {
|
||||||
LocalIO = Handle->Parent->LocalIO;
|
Output( Handle->Parent->LocalIO, Data, Len );
|
||||||
} else {
|
} else {
|
||||||
LocalIO = Handle->LocalIO;
|
Output( Handle->LocalIO, Data, Len );
|
||||||
}
|
|
||||||
if (LocalIO) {
|
|
||||||
ShowOutput( DebugLevel, dlHigh, OutputDisplay, Data, Len, "%s: LocalIO '%s' - OUT:", Name, LocalIO->Name );
|
|
||||||
|
|
||||||
Output = LocalIO->FirstOutput;
|
|
||||||
while (Output) {
|
|
||||||
Output->Function->Input( Output->IOName, Data, Len );
|
|
||||||
Output = Output->Next;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear processed bytes from buffer
|
// Clear processed bytes from buffer
|
||||||
@@ -957,15 +954,15 @@ int CSelectableCore::ReadFromFD( int FD, char * Data, int MaxLen )
|
|||||||
while (DataRemain)
|
while (DataRemain)
|
||||||
{
|
{
|
||||||
// Read from file descriptor
|
// Read from file descriptor
|
||||||
BytesRead = read( FD, Data, DataRemain );
|
BytesRead = read( FD, &Data[TotalRead], DataRemain );
|
||||||
if (BytesRead <= 0)
|
if ((BytesRead <= 0)) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Update Data Pointers
|
// Update Data Pointers
|
||||||
TotalRead += BytesRead;
|
TotalRead += BytesRead;
|
||||||
DataRemain -= BytesRead;
|
DataRemain -= BytesRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TotalRead;
|
return TotalRead;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -986,16 +983,15 @@ int CSelectableCore::WriteToFD( int FD, const char * Data, int Len )
|
|||||||
while (DataRemain)
|
while (DataRemain)
|
||||||
{
|
{
|
||||||
// Read from file descriptor
|
// Read from file descriptor
|
||||||
BytesWritten = write( FD, Data, DataRemain );
|
BytesWritten = write( FD, &Data[TotalWritten], DataRemain );
|
||||||
//write( FD, "\n", 1 );
|
if ((BytesWritten <= 0) && (errno != EAGAIN)) {
|
||||||
if (BytesWritten <= 0)
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Update Data Pointers
|
// Update Data Pointers
|
||||||
TotalWritten += BytesWritten;
|
TotalWritten += BytesWritten;
|
||||||
DataRemain -= BytesWritten;
|
DataRemain -= BytesWritten;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TotalWritten;
|
return TotalWritten;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -1106,8 +1102,16 @@ bool CSelectableCore::Process()
|
|||||||
// Auto manage handles
|
// Auto manage handles
|
||||||
if (Handle->Auto && ((Handle->State == csNone) || (Handle->State == csFailed) || (Handle->State == csClosed)))
|
if (Handle->Auto && ((Handle->State == csNone) || (Handle->State == csFailed) || (Handle->State == csClosed)))
|
||||||
{
|
{
|
||||||
// Complete opening process
|
// Check duration since last PortIn
|
||||||
Open( Handle );
|
if (Timeout( Handle->ReopenStart, Handle->ReopenTimeout ))
|
||||||
|
{
|
||||||
|
// Complete opening process
|
||||||
|
if (Open( Handle ) == -1)
|
||||||
|
{
|
||||||
|
// Reset Timer
|
||||||
|
SetStartTime( &(Handle->ReopenStart) );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check Input buffers
|
// Check Input buffers
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Select.h
|
* SelectableCore.h
|
||||||
*
|
*
|
||||||
* Created on: 13 May 2016
|
* Created on: 13 May 2016
|
||||||
* Author: wentzelc
|
* Author: wentzelc
|
||||||
@@ -91,6 +91,10 @@ struct SHandle {
|
|||||||
timeval InStart;
|
timeval InStart;
|
||||||
long InTimeout; // millisecs
|
long InTimeout; // millisecs
|
||||||
|
|
||||||
|
// Reopen Timer
|
||||||
|
timeval ReopenStart;
|
||||||
|
long ReopenTimeout; // millisecs
|
||||||
|
|
||||||
// List / Tree
|
// List / Tree
|
||||||
TLocalIO * LocalIO;
|
TLocalIO * LocalIO;
|
||||||
THandle * Parent;
|
THandle * Parent;
|
||||||
@@ -207,7 +211,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Configuration
|
// Configuration
|
||||||
THandle * CreateHandle( const char * HandleName, bool CreateIO, bool AutoManage );
|
THandle * CreateHandle( const char * HandleName, bool CreateIO );
|
||||||
|
bool SetAutoManage( THandle * Handle, bool AutoManage, int ReopenTime = 0 );
|
||||||
bool SetBuffers( THandle * Handle, int InBufSize, int OutBufSize, int InTimeout, const char * InMarker, int InMarkerLen );
|
bool SetBuffers( THandle * Handle, int InBufSize, int OutBufSize, int InTimeout, const char * InMarker, int InMarkerLen );
|
||||||
bool SerialConfig( THandle * Handle, int Baud, short DataBits, short StopBits, short Parity, short FlowCtrl, int Wait );
|
bool SerialConfig( THandle * Handle, int Baud, short DataBits, short StopBits, short Parity, short FlowCtrl, int Wait );
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Timing.cpp
|
* TimingCore.cpp
|
||||||
*
|
*
|
||||||
* Created on: 13 May 2016
|
* Created on: 13 May 2016
|
||||||
* Author: wentzelc
|
* Author: wentzelc
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Timing.h
|
* TimingCore.h
|
||||||
*
|
*
|
||||||
* Created on: 13 May 2016
|
* Created on: 13 May 2016
|
||||||
* Author: wentzelc
|
* Author: wentzelc
|
||||||
|
|||||||
Reference in New Issue
Block a user