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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
@@ -310,8 +311,9 @@ int CBuffer::ReadFromFD( int Handle, int MaxRead )
|
||||
// Read from file descriptor
|
||||
BufRemain = BufSize - BufEnd;
|
||||
BytesRead = read( Handle, &Buffer[BufEnd], ((BufRemain > DataRemain)? DataRemain : BufRemain) );
|
||||
if (BytesRead <= 0)
|
||||
if (BytesRead <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Update Buffer Pointers
|
||||
DataRemain -= BytesRead;
|
||||
@@ -328,7 +330,6 @@ int CBuffer::ReadFromFD( int Handle, int MaxRead )
|
||||
BufStart = BufEnd;
|
||||
}
|
||||
}
|
||||
|
||||
return TotalRead;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
@@ -355,8 +356,9 @@ int CBuffer::WriteToFD( int Handle, int MaxLen )
|
||||
// Read from file descriptor
|
||||
BufRemain = BufSize - ReadPos;
|
||||
BytesWritten = write( Handle, &Buffer[ReadPos], ((BufRemain > DataRemain)? DataRemain : BufRemain) );
|
||||
if (BytesWritten <= 0)
|
||||
if ((BytesWritten <= 0) && (errno != EAGAIN)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Update Data Pointers
|
||||
TotalWritten += BytesWritten;
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
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 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
|
||||
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 Len;
|
||||
|
||||
@@ -68,6 +68,9 @@ protected:
|
||||
return LocalIO;
|
||||
}
|
||||
|
||||
// Low Level Local IO interfaces
|
||||
virtual int Output( const TLocalIO * LocalIO, const char * Data, int Len );
|
||||
|
||||
public:
|
||||
// Life cycle
|
||||
CFunctionCore( const char * ObjectName, EDebugLevel pDebugLevel, int pOuputDisplay );
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Select.cpp
|
||||
* SelectCore.cpp
|
||||
*
|
||||
* Created on: 13 May 2016
|
||||
* Author: wentzelc
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* CSelectableCore.cpp
|
||||
* SelectableCore.cpp
|
||||
*
|
||||
* Created on: 20 May 2016
|
||||
* 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;
|
||||
|
||||
@@ -73,8 +73,7 @@ THandle * CSelectableCore::CreateHandle( const char * HandleName, bool CreateLo
|
||||
if (!*Handle)
|
||||
{
|
||||
// Create File handle at end of list
|
||||
*Handle = (THandle*)malloc( sizeof(THandle) );
|
||||
memset( *Handle, 0, sizeof(THandle) );
|
||||
*Handle = (THandle*)calloc( 1, sizeof(THandle) );
|
||||
|
||||
// Set name
|
||||
if (HandleName) {
|
||||
@@ -94,9 +93,6 @@ THandle * CSelectableCore::CreateHandle( const char * HandleName, bool CreateLo
|
||||
(*Handle)->LocalIO = AddLocalIO( HandleName );
|
||||
}
|
||||
|
||||
// Set other params
|
||||
(*Handle)->Auto = AutoManage;
|
||||
|
||||
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 )
|
||||
{
|
||||
// Validate
|
||||
@@ -473,7 +483,7 @@ int CSelectableCore::OpenRemoteClientSocket( THandle * Handle )
|
||||
|
||||
// Create Remote Client Handle
|
||||
sprintf( ClientName, "%s-%d", Handle->Name, ClientFD );
|
||||
*RemoteClient = CreateHandle( ClientName, false, false );
|
||||
*RemoteClient = CreateHandle( ClientName, false );
|
||||
SetSocketHandle( *RemoteClient, ctRemoteClient, ClientAddress, 0, Handle->KeepAlive );
|
||||
|
||||
// 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) ))
|
||||
{
|
||||
// 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
|
||||
close( Handle->FD );
|
||||
@@ -578,7 +588,7 @@ int CSelectableCore::OpenClientSocket( THandle * Handle )
|
||||
|
||||
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
|
||||
if (Select) {
|
||||
@@ -615,8 +625,13 @@ int CSelectableCore::OpenClientSocket( THandle * Handle )
|
||||
|
||||
// Close socket
|
||||
close( Handle->FD );
|
||||
Handle->FD = -1;
|
||||
Handle->State = csFailed;
|
||||
|
||||
// Start re-open timer
|
||||
SetStartTime( &(Handle->ReopenStart) );
|
||||
|
||||
// Reset Handle
|
||||
Handle->FD = -1;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -686,6 +701,9 @@ bool CSelectableCore::Close( THandle * Handle, bool CloseChildren )
|
||||
Fail = (close( Handle->FD ))? true : false;
|
||||
Handle->State = ((Fail)? csFailed : csClosed);
|
||||
|
||||
// Start re-open timer
|
||||
SetStartTime( &(Handle->ReopenStart) );
|
||||
|
||||
// Show action
|
||||
switch (Handle->Type)
|
||||
{
|
||||
@@ -787,17 +805,16 @@ bool CSelectableCore::Read( THandle * Handle )
|
||||
}
|
||||
|
||||
// Read File directly into buffer
|
||||
if (!Handle->InBuffer || !(BytesRead = Handle->InBuffer->ReadFromFD( Handle->FD ))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Handle->InBuffer && (BytesRead = Handle->InBuffer->ReadFromFD( Handle->FD )))
|
||||
{
|
||||
// Process Buffer
|
||||
ProcessBuffer( Handle, false );
|
||||
}
|
||||
|
||||
// Reset timer
|
||||
SetStartTime( &(Handle->InStart) );
|
||||
|
||||
return true;
|
||||
return (bool)BytesRead;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
@@ -874,8 +891,6 @@ bool CSelectableCore::ProcessBuffer( THandle * Handle, bool Force )
|
||||
int Pos = 0;
|
||||
int Len = 0;
|
||||
char * Data = NULL;
|
||||
TLocalIO * LocalIO = NULL;
|
||||
TLinkedIO * Output = NULL;
|
||||
|
||||
// Check if buffered data
|
||||
if (!Handle || !Handle->InBuffer || !Handle->InBuffer->Len()) {
|
||||
@@ -883,7 +898,7 @@ bool CSelectableCore::ProcessBuffer( THandle * Handle, bool Force )
|
||||
}
|
||||
|
||||
// Check if forced processed
|
||||
if (Force)
|
||||
if (Force || !Handle->InMarkerLen)
|
||||
{
|
||||
// Show Packet
|
||||
Len = Handle->InBuffer->Peek( &Data );
|
||||
@@ -891,18 +906,9 @@ bool CSelectableCore::ProcessBuffer( THandle * Handle, bool Force )
|
||||
|
||||
// Write buffer to Outputs
|
||||
if (Handle->Type == ctRemoteClient) {
|
||||
LocalIO = Handle->Parent->LocalIO;
|
||||
Output( Handle->Parent->LocalIO, Data, Len );
|
||||
} else {
|
||||
LocalIO = Handle->LocalIO;
|
||||
}
|
||||
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;
|
||||
}
|
||||
Output( Handle->LocalIO, Data, Len );
|
||||
}
|
||||
|
||||
// Clear processed bytes from buffer
|
||||
@@ -919,18 +925,9 @@ bool CSelectableCore::ProcessBuffer( THandle * Handle, bool Force )
|
||||
|
||||
// Write buffer to Outputs
|
||||
if (Handle->Type == ctRemoteClient) {
|
||||
LocalIO = Handle->Parent->LocalIO;
|
||||
Output( Handle->Parent->LocalIO, Data, Len );
|
||||
} else {
|
||||
LocalIO = Handle->LocalIO;
|
||||
}
|
||||
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;
|
||||
}
|
||||
Output( Handle->LocalIO, Data, Len );
|
||||
}
|
||||
|
||||
// Clear processed bytes from buffer
|
||||
@@ -957,15 +954,15 @@ int CSelectableCore::ReadFromFD( int FD, char * Data, int MaxLen )
|
||||
while (DataRemain)
|
||||
{
|
||||
// Read from file descriptor
|
||||
BytesRead = read( FD, Data, DataRemain );
|
||||
if (BytesRead <= 0)
|
||||
BytesRead = read( FD, &Data[TotalRead], DataRemain );
|
||||
if ((BytesRead <= 0)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Update Data Pointers
|
||||
TotalRead += BytesRead;
|
||||
DataRemain -= BytesRead;
|
||||
}
|
||||
|
||||
return TotalRead;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
@@ -986,16 +983,15 @@ int CSelectableCore::WriteToFD( int FD, const char * Data, int Len )
|
||||
while (DataRemain)
|
||||
{
|
||||
// Read from file descriptor
|
||||
BytesWritten = write( FD, Data, DataRemain );
|
||||
//write( FD, "\n", 1 );
|
||||
if (BytesWritten <= 0)
|
||||
BytesWritten = write( FD, &Data[TotalWritten], DataRemain );
|
||||
if ((BytesWritten <= 0) && (errno != EAGAIN)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Update Data Pointers
|
||||
TotalWritten += BytesWritten;
|
||||
DataRemain -= BytesWritten;
|
||||
}
|
||||
|
||||
return TotalWritten;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
@@ -1105,9 +1101,17 @@ bool CSelectableCore::Process()
|
||||
{
|
||||
// Auto manage handles
|
||||
if (Handle->Auto && ((Handle->State == csNone) || (Handle->State == csFailed) || (Handle->State == csClosed)))
|
||||
{
|
||||
// Check duration since last PortIn
|
||||
if (Timeout( Handle->ReopenStart, Handle->ReopenTimeout ))
|
||||
{
|
||||
// Complete opening process
|
||||
Open( Handle );
|
||||
if (Open( Handle ) == -1)
|
||||
{
|
||||
// Reset Timer
|
||||
SetStartTime( &(Handle->ReopenStart) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check Input buffers
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Select.h
|
||||
* SelectableCore.h
|
||||
*
|
||||
* Created on: 13 May 2016
|
||||
* Author: wentzelc
|
||||
@@ -91,6 +91,10 @@ struct SHandle {
|
||||
timeval InStart;
|
||||
long InTimeout; // millisecs
|
||||
|
||||
// Reopen Timer
|
||||
timeval ReopenStart;
|
||||
long ReopenTimeout; // millisecs
|
||||
|
||||
// List / Tree
|
||||
TLocalIO * LocalIO;
|
||||
THandle * Parent;
|
||||
@@ -207,7 +211,8 @@ public:
|
||||
}
|
||||
|
||||
// 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 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
|
||||
* Author: wentzelc
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Timing.h
|
||||
* TimingCore.h
|
||||
*
|
||||
* Created on: 13 May 2016
|
||||
* Author: wentzelc
|
||||
|
||||
Reference in New Issue
Block a user