Initial Commit:
- Create single library for all Core RedA functions/classes - Working version
This commit is contained in:
3
CMakeLists.txt
Normal file
3
CMakeLists.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
PROJECT(lib_redAcore)
|
||||||
|
|
||||||
|
ADD_LIBRARY(redAcore LogCore.cpp TimingCore.cpp PortCore.cpp SocketCore.cpp SelectCore.cpp)
|
||||||
45
LogCore.cpp
Normal file
45
LogCore.cpp
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* LogCore.cpp
|
||||||
|
*
|
||||||
|
* Created on: 17 May 2016
|
||||||
|
* Author: wentzelc
|
||||||
|
*/
|
||||||
|
|
||||||
|
// redA Libraries
|
||||||
|
#include "LogCore.h"
|
||||||
|
|
||||||
|
// Standard C/C++ Libraries
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void ShowOutput( const char * Name, const char * Buffer, const int Len, const long Duration )
|
||||||
|
{
|
||||||
|
// Show Duration delay
|
||||||
|
if (Duration) {
|
||||||
|
printf( "Delay: %ld", Duration );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show Hex output
|
||||||
|
if (ShowOutBytes) {
|
||||||
|
printf( "%s in (hex): ", Name );
|
||||||
|
for (int i=0; i<Len; i++) {
|
||||||
|
printf( "%02X ", Buffer[i] );
|
||||||
|
}
|
||||||
|
printf( "\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show normal output
|
||||||
|
if (ShowOutHex) {
|
||||||
|
printf( "%s in [%d]: %s", Name, Len, Buffer );
|
||||||
|
if (Buffer[Len-1] != '\n') {
|
||||||
|
printf( "\n" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
29
LogCore.h
Normal file
29
LogCore.h
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* LogCore.h
|
||||||
|
*
|
||||||
|
* Created on: 17 May 2016
|
||||||
|
* Author: wentzelc
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LOGCORE_H_
|
||||||
|
#define LOGCORE_H_
|
||||||
|
|
||||||
|
// redA Libraries
|
||||||
|
/* none */
|
||||||
|
|
||||||
|
// Standard C/C++ Libraries
|
||||||
|
/* none */
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Debug options
|
||||||
|
bool ShowOutBytes = true;
|
||||||
|
bool ShowOutHex = true;
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void ShowOutput( const char * Name, const char * Buffer, const int Len, const long Duration );
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#endif /* LOGCORE_H_ */
|
||||||
272
PortCore.cpp
Normal file
272
PortCore.cpp
Normal file
@@ -0,0 +1,272 @@
|
|||||||
|
/*
|
||||||
|
* PortCore.cpp
|
||||||
|
*
|
||||||
|
* Created on: 13 May 2016
|
||||||
|
* Author: wentzelc
|
||||||
|
*/
|
||||||
|
|
||||||
|
// redA Libraries
|
||||||
|
#include "TimingCore.h"
|
||||||
|
#include "PortCore.h"
|
||||||
|
|
||||||
|
// Standard C/C++ Libraries
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Port Def
|
||||||
|
int PortHandle = -1;
|
||||||
|
char * PortName = NULL;
|
||||||
|
|
||||||
|
// PortIn buffer
|
||||||
|
char PortInBuffer[500] = "";
|
||||||
|
int PortInBufLen = 500;
|
||||||
|
int PortInLen = 0;
|
||||||
|
int PortBytesRead = 0;
|
||||||
|
|
||||||
|
// PortIn Timer
|
||||||
|
timeval PortInStart = { 0, 0 };
|
||||||
|
long PortInTimeout = 100; // millisecs
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
int OpenPort( const char * pPortName )
|
||||||
|
{
|
||||||
|
// Copy Port name
|
||||||
|
PortName = (char*)malloc( strlen(pPortName)+ 1);
|
||||||
|
strcpy( PortName, pPortName );
|
||||||
|
|
||||||
|
// Check if port exits
|
||||||
|
if (access( PortName, F_OK ) != 0)
|
||||||
|
{
|
||||||
|
printf( "Port: %s -> Could not find port\n", PortName );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open Port
|
||||||
|
PortHandle = open( PortName, O_RDWR );
|
||||||
|
if (PortHandle == -1)
|
||||||
|
{
|
||||||
|
printf( "Port: %s -> Could not open port\n", PortName );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Confirm open
|
||||||
|
printf( "Port: %s -> Port opened\n", PortName );
|
||||||
|
return PortHandle;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool ClosePort()
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
// Close port
|
||||||
|
result = close( PortHandle );
|
||||||
|
if (result) {
|
||||||
|
printf( "Port: %s -> Port not closed properly\n", PortName );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Port closed
|
||||||
|
printf( "Port: %s -> Port closed\n", PortName );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Set serial port configuration parameters
|
||||||
|
bool ConfigSerialPort( int Baud, short DataBits, short StopBits, short Parity, short FlowCtrl, int Wait )
|
||||||
|
{
|
||||||
|
struct termios newtio;
|
||||||
|
int flags = 0;
|
||||||
|
speed_t _baud = 0;
|
||||||
|
int mcs = 0;
|
||||||
|
|
||||||
|
// Flush Data from port
|
||||||
|
tcflush( PortHandle, TCIFLUSH );
|
||||||
|
|
||||||
|
// Set Open flags
|
||||||
|
flags = fcntl( PortHandle, F_GETFL, 0 );
|
||||||
|
fcntl( PortHandle, F_SETFL, flags & ~O_NDELAY );
|
||||||
|
|
||||||
|
// Read options
|
||||||
|
if (tcgetattr( PortHandle, &newtio ) != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Process the baud rate
|
||||||
|
switch (Baud)
|
||||||
|
{
|
||||||
|
case 921600: _baud = B921600; break;
|
||||||
|
case 576000: _baud = B576000; break;
|
||||||
|
case 460800: _baud = B460800; break;
|
||||||
|
case 230400: _baud = B230400; break;
|
||||||
|
//case 128000: _baud = B128000; break;
|
||||||
|
case 115200: _baud = B115200; break;
|
||||||
|
//case 76800: _baud = B76800; break;
|
||||||
|
case 57600: _baud = B57600; break;
|
||||||
|
case 38400: _baud = B38400; break;
|
||||||
|
//case 28800: _baud = B28800; break;
|
||||||
|
case 19200: _baud = B19200; break;
|
||||||
|
//case 14400: _baud = B14400; break;
|
||||||
|
case 9600: _baud = B9600; break;
|
||||||
|
case 4800: _baud = B4800; break;
|
||||||
|
case 2400: _baud = B2400; break;
|
||||||
|
case 1800: _baud = B1800; break;
|
||||||
|
case 1200: _baud = B1200; break;
|
||||||
|
case 600: _baud = B600; break;
|
||||||
|
case 300: _baud = B300; break;
|
||||||
|
case 200: _baud = B200; break;
|
||||||
|
case 150: _baud = B150; break;
|
||||||
|
case 134: _baud = B134; break;
|
||||||
|
case 110: _baud = B110; break;
|
||||||
|
case 75: _baud = B75; break;
|
||||||
|
case 50: _baud = B50; break;
|
||||||
|
|
||||||
|
default: _baud = B9600; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set Baud rate
|
||||||
|
cfsetospeed( &newtio, (speed_t)_baud );
|
||||||
|
cfsetispeed( &newtio, (speed_t)_baud );
|
||||||
|
|
||||||
|
// Generate Mark/Space parity
|
||||||
|
if ((DataBits == 7) && ((Parity == MARK_PARITY) || (Parity == SPACE_PARITY)))
|
||||||
|
DataBits = 8;
|
||||||
|
|
||||||
|
// Process the data bits
|
||||||
|
newtio.c_cflag &= ~CSIZE;
|
||||||
|
switch (DataBits)
|
||||||
|
{
|
||||||
|
case 5: newtio.c_cflag |= CS5; break;
|
||||||
|
case 6: newtio.c_cflag |= CS6; break;
|
||||||
|
case 7: newtio.c_cflag |= CS7; break;
|
||||||
|
case 8: newtio.c_cflag |= CS8; break;
|
||||||
|
|
||||||
|
default: newtio.c_cflag |= CS8; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set other flags
|
||||||
|
newtio.c_cflag |= CLOCAL | CREAD;
|
||||||
|
|
||||||
|
// Process Parity
|
||||||
|
newtio.c_cflag &= ~(PARENB | PARODD);
|
||||||
|
if (Parity == EVEN_PARITY)
|
||||||
|
newtio.c_cflag |= PARENB;
|
||||||
|
else if (Parity == ODD_PARITY)
|
||||||
|
newtio.c_cflag |= (PARENB | PARODD);
|
||||||
|
|
||||||
|
// Flow Control (for now)
|
||||||
|
newtio.c_cflag &= ~CRTSCTS;
|
||||||
|
|
||||||
|
// Process Stop Bits
|
||||||
|
if (StopBits == 2)
|
||||||
|
newtio.c_cflag |= CSTOPB;
|
||||||
|
else
|
||||||
|
newtio.c_cflag &= ~CSTOPB;
|
||||||
|
|
||||||
|
newtio.c_iflag = IGNBRK;
|
||||||
|
|
||||||
|
// Software Flow Control
|
||||||
|
if (FlowCtrl == SW_FLOWCTRL)
|
||||||
|
newtio.c_iflag |= IXON | IXOFF;
|
||||||
|
else
|
||||||
|
newtio.c_iflag &= ~(IXON | IXOFF | IXANY);
|
||||||
|
|
||||||
|
// Set RAW input & output
|
||||||
|
newtio.c_lflag=0;
|
||||||
|
newtio.c_oflag=0;
|
||||||
|
|
||||||
|
// Set wait parameters
|
||||||
|
newtio.c_cc[VTIME] = Wait; // Blocking: Allow at least a tenth of a second to wait for data
|
||||||
|
newtio.c_cc[VMIN] = 0; // Non-blocking: Don't set min bytes to receive
|
||||||
|
|
||||||
|
// Set Options (first time)
|
||||||
|
//tcflush( Handle, TCIFLUSH);
|
||||||
|
if (tcsetattr( PortHandle, TCSANOW, &newtio)!=0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Set Terminal options
|
||||||
|
ioctl( PortHandle, TIOCMGET, &mcs);
|
||||||
|
mcs |= TIOCM_RTS;
|
||||||
|
ioctl( PortHandle, TIOCMSET, &mcs);
|
||||||
|
|
||||||
|
// Get Options (again)
|
||||||
|
if (tcgetattr( PortHandle, &newtio) != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Process Hardware Flow Control
|
||||||
|
if (FlowCtrl == HW_FLOWCTRL)
|
||||||
|
newtio.c_cflag |= CRTSCTS;
|
||||||
|
else
|
||||||
|
newtio.c_cflag &= ~CRTSCTS;
|
||||||
|
|
||||||
|
// Set Options (second time)
|
||||||
|
if (tcsetattr( PortHandle, TCSANOW, &newtio ) != 0)
|
||||||
|
{
|
||||||
|
printf( "Port: %s -> Could not configure port\n", PortName );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Port configured
|
||||||
|
printf( "Port: %s -> Port configured\n", PortName );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool ReadPort()
|
||||||
|
{
|
||||||
|
// Handle read event
|
||||||
|
PortBytesRead = read( PortHandle, &PortInBuffer[PortInLen], PortInBufLen-PortInLen );
|
||||||
|
if (PortBytesRead > 0)
|
||||||
|
{
|
||||||
|
// Process Reply
|
||||||
|
PortInLen += PortBytesRead;
|
||||||
|
|
||||||
|
// Reset timer
|
||||||
|
SetStartTime( &PortInStart );
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool MaintainPort( int SocketHandle )
|
||||||
|
{
|
||||||
|
// Misc
|
||||||
|
long Duration = 0;
|
||||||
|
int BytesWritten = 0;
|
||||||
|
int StartWrite = 0;
|
||||||
|
|
||||||
|
if (PortInLen > 0)
|
||||||
|
{
|
||||||
|
// Check duration since last PortIn
|
||||||
|
Duration = TimePassed( PortInStart );
|
||||||
|
if (Duration > PortInTimeout)
|
||||||
|
{
|
||||||
|
// Handle buffer as packet
|
||||||
|
PortInBuffer[ PortInLen ] = 0;
|
||||||
|
//ShowOutput( "Port", PortInBuffer, PortInLen, Duration );
|
||||||
|
|
||||||
|
// Write output to Port
|
||||||
|
BytesWritten = 0;
|
||||||
|
StartWrite = 0;
|
||||||
|
while (StartWrite < PortInLen) {
|
||||||
|
BytesWritten = write( SocketHandle, &PortInBuffer[StartWrite], PortInLen );
|
||||||
|
StartWrite += BytesWritten;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset buffer and timer
|
||||||
|
PortInLen = 0;
|
||||||
|
SetInterval( &PortInStart, 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
40
PortCore.h
Normal file
40
PortCore.h
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* PortCore.h
|
||||||
|
*
|
||||||
|
* Created on: 13 May 2016
|
||||||
|
* Author: wentzelc
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PORTCORE_H_
|
||||||
|
#define PORTCORE_H_
|
||||||
|
|
||||||
|
// redA Libraries
|
||||||
|
/* none */
|
||||||
|
|
||||||
|
// Standard C/C++ Libraries
|
||||||
|
/* none */
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Defines required to configure port
|
||||||
|
#define NO_PARITY 0
|
||||||
|
#define ODD_PARITY 1
|
||||||
|
#define EVEN_PARITY 2
|
||||||
|
#define MARK_PARITY 3
|
||||||
|
#define SPACE_PARITY 4
|
||||||
|
|
||||||
|
#define NO_FLOWCTRL 0
|
||||||
|
#define HW_FLOWCTRL 1
|
||||||
|
#define SW_FLOWCTRL 2
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Port Functions
|
||||||
|
int OpenPort( const char * PortName );
|
||||||
|
bool ClosePort();
|
||||||
|
bool ConfigSerialPort( int Baud, short DataBits, short StopBits, short Parity, short FlowCtrl, int Wait );
|
||||||
|
|
||||||
|
bool ReadPort();
|
||||||
|
bool MaintainPort( int SocketHandle );
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#endif /* PORTCORE_H_ */
|
||||||
123
SelectCore.cpp
Normal file
123
SelectCore.cpp
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
/*
|
||||||
|
* Select.cpp
|
||||||
|
*
|
||||||
|
* Created on: 13 May 2016
|
||||||
|
* Author: wentzelc
|
||||||
|
*/
|
||||||
|
|
||||||
|
// redA Libraries
|
||||||
|
#include "TimingCore.h"
|
||||||
|
#include "SelectCore.h"
|
||||||
|
|
||||||
|
// Standard C/C++ Libraries
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Select Variables
|
||||||
|
fd_set ReadTestFDS;
|
||||||
|
fd_set WriteTestFDS;
|
||||||
|
fd_set ReadFDS;
|
||||||
|
fd_set WriteFDS;
|
||||||
|
int MaxFD = 0;
|
||||||
|
timeval SelectTime;
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Clear Select File Descriptors
|
||||||
|
void SelectClear()
|
||||||
|
{
|
||||||
|
// Clear Select sets
|
||||||
|
FD_ZERO( &ReadTestFDS );
|
||||||
|
FD_ZERO( &WriteTestFDS );
|
||||||
|
|
||||||
|
// Reset maximum File Descriptor
|
||||||
|
MaxFD = 0;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Set Select timeout
|
||||||
|
void SelectConfig( long SelectTimeout )
|
||||||
|
{
|
||||||
|
// Set Timeout
|
||||||
|
SetInterval( &SelectTime, SelectTimeout );
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Add Select File Descriptor
|
||||||
|
void SelectAdd( int FD, bool Read, bool Write )
|
||||||
|
{
|
||||||
|
// Add Read select
|
||||||
|
if (Read)
|
||||||
|
FD_SET( FD, &ReadTestFDS );
|
||||||
|
|
||||||
|
// Add Write Select
|
||||||
|
if (Write)
|
||||||
|
FD_SET( FD, &WriteTestFDS );
|
||||||
|
|
||||||
|
// Check Maximum File Handle
|
||||||
|
if (MaxFD <= FD)
|
||||||
|
MaxFD = FD+1;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void SelectRemove( int FD, bool Read, bool Write )
|
||||||
|
{
|
||||||
|
// Remove from set for select read check
|
||||||
|
if (Read)
|
||||||
|
FD_CLR( FD, &ReadTestFDS);
|
||||||
|
|
||||||
|
// Remove from set for select write check
|
||||||
|
if (Write)
|
||||||
|
FD_CLR( FD, &WriteTestFDS);
|
||||||
|
|
||||||
|
// Check Maximum file handle
|
||||||
|
if (FD == MaxFD) {
|
||||||
|
for (int test = MaxFD-1; test >= 0; test--) {
|
||||||
|
if (FD_ISSET( test, &ReadTestFDS ) || FD_ISSET( test, &WriteTestFDS )) {
|
||||||
|
MaxFD = test+1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool SelectTest()
|
||||||
|
{
|
||||||
|
int Result = 0;
|
||||||
|
|
||||||
|
// Set Test sets
|
||||||
|
ReadFDS = ReadTestFDS;
|
||||||
|
WriteFDS = WriteTestFDS;
|
||||||
|
|
||||||
|
// Perform select
|
||||||
|
Result = select( MaxFD, &ReadFDS, &WriteFDS, (fd_set*)NULL, &SelectTime );
|
||||||
|
if (Result < 0)
|
||||||
|
{
|
||||||
|
printf( "Select operation failed (%s)\n", strerror(errno) );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return success
|
||||||
|
return (bool)Result;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Add Select File Descriptor
|
||||||
|
bool SelectCheck( int FD, bool &Read, bool &Write )
|
||||||
|
{
|
||||||
|
// Add Read select
|
||||||
|
Read = (bool)(FD_ISSET( FD, &ReadFDS ));
|
||||||
|
|
||||||
|
// Add Write Select
|
||||||
|
Write = (bool)(FD_ISSET( FD, &WriteFDS ));
|
||||||
|
|
||||||
|
return (Read || Write);
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
28
SelectCore.h
Normal file
28
SelectCore.h
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Select.h
|
||||||
|
*
|
||||||
|
* Created on: 13 May 2016
|
||||||
|
* Author: wentzelc
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SELECTCORE_H_
|
||||||
|
#define SELECTCORE_H_
|
||||||
|
|
||||||
|
// redA Libraries
|
||||||
|
/* none */
|
||||||
|
|
||||||
|
// Standard C/C++ Libraries
|
||||||
|
/* none */
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void SelectConfig( long Timeout );
|
||||||
|
void SelectClear();
|
||||||
|
void SelectAdd( int FD, bool Read, bool Write );
|
||||||
|
void SelectRemove( int FD, bool Read, bool Write );
|
||||||
|
bool SelectTest();
|
||||||
|
bool SelectCheck( int FD, bool &Read, bool &Write );
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#endif /* SELECTCORE_H_ */
|
||||||
375
SocketCore.cpp
Normal file
375
SocketCore.cpp
Normal file
@@ -0,0 +1,375 @@
|
|||||||
|
/*
|
||||||
|
* SocketCore.h
|
||||||
|
*
|
||||||
|
* Created on: 13 May 2016
|
||||||
|
* Author: wentzelc
|
||||||
|
*/
|
||||||
|
|
||||||
|
// redA Libraries
|
||||||
|
#include "TimingCore.h"
|
||||||
|
#include "SocketCore.h"
|
||||||
|
|
||||||
|
// Standard C/C++ Libraries
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netinet/tcp.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Variables
|
||||||
|
char * ServerName = NULL;
|
||||||
|
char ServerAddress[25] = "";
|
||||||
|
int PortNo = 0;
|
||||||
|
char ClientAddress[25] = "";
|
||||||
|
|
||||||
|
int ServerHandle = -1;
|
||||||
|
ESocketState ServerState = ssNone;
|
||||||
|
|
||||||
|
int ClientHandle = -1;
|
||||||
|
ESocketState ClientState = ssNone;
|
||||||
|
|
||||||
|
char SockInBuffer[500] = "";
|
||||||
|
int SockInBufLen = 500;
|
||||||
|
int SockInLen = 0;
|
||||||
|
|
||||||
|
// SockIn Timer
|
||||||
|
timeval SockInStart = { 0, 0 };
|
||||||
|
long SockInTimeout = 100; // millisecs
|
||||||
|
|
||||||
|
int SockBytesRead = 0;
|
||||||
|
int SockBytesWaiting = 0;
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
int OpenTCPserverSocket( const char *pName, const char *pAddress, int pPortNo, bool KeepAlive )
|
||||||
|
{
|
||||||
|
socklen_t addr_len;
|
||||||
|
struct sockaddr_in address;
|
||||||
|
|
||||||
|
ServerName = (char*)malloc( strlen(pName)+1 );
|
||||||
|
strcpy( ServerName, pName );
|
||||||
|
strcpy( ServerAddress, pAddress );
|
||||||
|
PortNo = pPortNo;
|
||||||
|
|
||||||
|
// Socket options
|
||||||
|
struct linger ServerLinger_opt;
|
||||||
|
ServerLinger_opt.l_onoff = 1;
|
||||||
|
ServerLinger_opt.l_linger = 5;
|
||||||
|
|
||||||
|
int Reuse_opt = 1;
|
||||||
|
int KeepAlive_opt = 1;
|
||||||
|
int TCPidle_opt = 60;
|
||||||
|
int TCPint_opt = 15;
|
||||||
|
int TCPcnt_opt = 3;
|
||||||
|
|
||||||
|
// Create address
|
||||||
|
address.sin_family = AF_INET;
|
||||||
|
address.sin_addr.s_addr = inet_addr(ServerAddress);
|
||||||
|
address.sin_port = htons(PortNo);
|
||||||
|
addr_len = sizeof(address);
|
||||||
|
|
||||||
|
// Set default socket state
|
||||||
|
ServerState = ssNone;
|
||||||
|
|
||||||
|
// Create socket
|
||||||
|
if ((ServerHandle = socket(AF_INET, SOCK_STREAM, 0)) < 0)
|
||||||
|
{
|
||||||
|
printf( "Server Socket: %s [%d] -> Failed to create server socket (%s)\n", ServerName, PortNo, strerror(errno) );
|
||||||
|
ServerState = ssFailed;
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Configure connection
|
||||||
|
if ((setsockopt( ServerHandle, SOL_SOCKET, SO_LINGER, &ServerLinger_opt, sizeof(ServerLinger_opt)) == -1) ||
|
||||||
|
(setsockopt( ServerHandle, SOL_SOCKET, SO_REUSEADDR, &Reuse_opt, sizeof(Reuse_opt)) == -1))
|
||||||
|
{
|
||||||
|
printf( "Server Socket: %s [%d] -> Could not set socket options (%s)\n", ServerName, PortNo, strerror(errno) );
|
||||||
|
ServerState = ssFailed;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure TCP keep alive settings
|
||||||
|
if (KeepAlive &&
|
||||||
|
((setsockopt( ServerHandle, SOL_SOCKET, SO_KEEPALIVE, &KeepAlive_opt, sizeof(KeepAlive_opt)) == -1) ||
|
||||||
|
(setsockopt( ServerHandle, SOL_TCP, TCP_KEEPIDLE, &TCPidle_opt, sizeof(TCPidle_opt)) == -1) ||
|
||||||
|
(setsockopt( ServerHandle, SOL_TCP, TCP_KEEPCNT, &TCPcnt_opt, sizeof(TCPcnt_opt)) == -1) ||
|
||||||
|
(setsockopt( ServerHandle, SOL_TCP, TCP_KEEPINTVL, &TCPint_opt, sizeof(TCPint_opt)) == -1) ))
|
||||||
|
{
|
||||||
|
printf( "Server Socket: %s [%d] -> Could not set socket keepalive options (%s)\n", ServerName, PortNo, strerror(errno) );
|
||||||
|
ServerState = ssFailed;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind socket
|
||||||
|
if (bind( ServerHandle, (struct sockaddr *)&address, addr_len ) < 0)
|
||||||
|
{
|
||||||
|
printf( "Server Socket: %s [%d] -> Failed to bind server to socket (%s)\n", ServerName, PortNo, strerror(errno) );
|
||||||
|
close( ServerHandle );
|
||||||
|
ServerState = ssFailed;
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create que for 5 connections
|
||||||
|
if (listen( ServerHandle, 5 ) < 0)
|
||||||
|
{
|
||||||
|
printf( "Server Socket: %s [%d] -> Failed to create server socket listen que (%s)\n", ServerName, PortNo, strerror(errno) );
|
||||||
|
close( ServerHandle );
|
||||||
|
ServerState = ssFailed;
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Server open
|
||||||
|
ServerState = ssOpen;
|
||||||
|
printf( "Server Socket: %s [%d] -> Socket binded and listening\n", ServerName, PortNo );
|
||||||
|
return ServerHandle;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
int OpenTCPinClientSocket()
|
||||||
|
{
|
||||||
|
socklen_t addr_len;
|
||||||
|
struct sockaddr_in address;
|
||||||
|
|
||||||
|
|
||||||
|
// Set default socket state
|
||||||
|
if (ClientHandle == -1)
|
||||||
|
{
|
||||||
|
// Accept connection on current socket
|
||||||
|
addr_len = sizeof( address );
|
||||||
|
if ((ClientHandle = accept( ServerHandle, (struct sockaddr *)&address, &addr_len)) == -1)
|
||||||
|
{
|
||||||
|
if (errno == EWOULDBLOCK)
|
||||||
|
printf( "Remote Socket: %s [*] -> Failed to accept blocking connection (%s)\n", ServerName, strerror(errno) );
|
||||||
|
else
|
||||||
|
printf( "Remote Socket: %s [*] -> Failed to accept connection (%s)\n", ServerName, strerror(errno) );
|
||||||
|
close( ClientHandle );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return client address
|
||||||
|
strcpy( ClientAddress, inet_ntoa(address.sin_addr) );
|
||||||
|
ClientState = ssOpen;
|
||||||
|
printf( "Remote Socket: %s -> Server accepted connection from client (%s)\n", ServerName, ClientAddress );
|
||||||
|
}
|
||||||
|
else if (ClientState == ssWaitingtoOpen)
|
||||||
|
{
|
||||||
|
// Clear non blocking flag
|
||||||
|
int flags = fcntl( ClientHandle, F_GETFL, 0 );
|
||||||
|
fcntl( ClientHandle, F_SETFL, (!O_NONBLOCK)&flags );
|
||||||
|
|
||||||
|
// Log event
|
||||||
|
printf( "Socket: %s -> Client now connected to server (%s)\n", ServerName, ServerAddress );
|
||||||
|
|
||||||
|
// Trigger handler & set new state
|
||||||
|
ClientState = ssOpen;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ClientHandle;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
int OpenTCPoutClientSocket( const char *pName, const char *pAddress, int pPortNo, bool KeepAlive )
|
||||||
|
{
|
||||||
|
socklen_t addr_len;
|
||||||
|
struct sockaddr_in address;
|
||||||
|
|
||||||
|
ServerName = (char*)malloc( strlen(pName)+1 );
|
||||||
|
strcpy( ServerName, pName );
|
||||||
|
strcpy( ServerAddress, pAddress );
|
||||||
|
PortNo = pPortNo;
|
||||||
|
|
||||||
|
// Socket options
|
||||||
|
int KeepAlive_opt = 1;
|
||||||
|
int TCPidle_opt = 5;
|
||||||
|
int TCPcnt_opt = 3;
|
||||||
|
int TCPint_opt = 2;
|
||||||
|
|
||||||
|
// Set default socket state
|
||||||
|
ClientState = ssNone;
|
||||||
|
|
||||||
|
// Create File descriptor
|
||||||
|
if ((ClientHandle = socket( AF_INET, SOCK_STREAM, 0 )) < 0)
|
||||||
|
{
|
||||||
|
printf( "Client Socket: %s [*] -> Failed to create Client Socket (%s)\n", ServerName, strerror(errno) );
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set Non blocking open
|
||||||
|
int flags = fcntl( ClientHandle, F_GETFL, 0 );
|
||||||
|
fcntl( ClientHandle, F_SETFL, O_NONBLOCK|flags );
|
||||||
|
|
||||||
|
// Configure TCP keep alive settings
|
||||||
|
if (KeepAlive &&
|
||||||
|
((setsockopt( ClientHandle, SOL_SOCKET, SO_KEEPALIVE, &KeepAlive_opt, sizeof(KeepAlive_opt)) == -1) ||
|
||||||
|
(setsockopt( ClientHandle, SOL_TCP, TCP_KEEPIDLE, &TCPidle_opt, sizeof(TCPidle_opt)) == -1) ||
|
||||||
|
(setsockopt( ClientHandle, SOL_TCP, TCP_KEEPCNT, &TCPcnt_opt, sizeof(TCPcnt_opt)) == -1) ||
|
||||||
|
(setsockopt( ClientHandle, SOL_TCP, TCP_KEEPINTVL, &TCPint_opt, sizeof(TCPint_opt)) == -1) ))
|
||||||
|
{
|
||||||
|
printf( "Client Socket: %s -> Could not set socket keepalive options (%s)\n", ServerName, strerror(errno) );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Declare address
|
||||||
|
address.sin_family = AF_INET;
|
||||||
|
address.sin_addr.s_addr = inet_addr( ServerAddress );
|
||||||
|
address.sin_port = htons(PortNo);
|
||||||
|
addr_len = sizeof(address);
|
||||||
|
|
||||||
|
if (!connect( ClientHandle, (struct sockaddr *)&address, addr_len ))
|
||||||
|
{
|
||||||
|
// Set status
|
||||||
|
ClientState = ssOpen;
|
||||||
|
return ClientHandle;
|
||||||
|
}
|
||||||
|
else if (errno == EINPROGRESS)
|
||||||
|
{
|
||||||
|
// Set status
|
||||||
|
ClientState = ssWaitingtoOpen;
|
||||||
|
return ClientHandle;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf( "Client Socket: %s -> Client failed to connect (%s)\n", ServerName, strerror(errno) );
|
||||||
|
|
||||||
|
// Set status
|
||||||
|
ClientState = ssFailed;
|
||||||
|
|
||||||
|
// Close socket
|
||||||
|
close( ClientHandle );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Delete socket
|
||||||
|
bool CloseTCPSocket( ESockConnectType SocketType )
|
||||||
|
{
|
||||||
|
bool Fail;
|
||||||
|
|
||||||
|
if (SocketType == ctServer) {
|
||||||
|
Fail = (close( ServerHandle ))? true : false;
|
||||||
|
ServerState = ((Fail)? ssFailed : ssClosed);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Fail = (close( ClientHandle ))? true : false;
|
||||||
|
ClientState = ((Fail)? ssFailed : ssClosed);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show action
|
||||||
|
switch (SocketType)
|
||||||
|
{
|
||||||
|
case ctServer:
|
||||||
|
printf( "Server Socket: %s -> Server %s\n", ServerName, ((Fail)? "failed" : "closed") );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ctRemoteClient:
|
||||||
|
printf( "Remote Client: %s -> Connection to client %s\n", ServerName, ((Fail)? "failed" : "closed") );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ctClient:
|
||||||
|
printf( "Client Socket: %s -> Connection to server %s\n", ServerName, ((Fail)? "failed" : "closed") );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ctNone:
|
||||||
|
default:
|
||||||
|
printf( "Socket : %s -> Cannot %s socket (invalid socket type)\n", ServerName, ((Fail)? "fail" : "close") );
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool ReadClientSocket()
|
||||||
|
{
|
||||||
|
// Check if anything to read
|
||||||
|
ioctl( ClientHandle, FIONREAD, &SockBytesWaiting );
|
||||||
|
|
||||||
|
if (SockBytesWaiting)
|
||||||
|
{
|
||||||
|
// Handle Incoming Data
|
||||||
|
// Check if socket ready (non-block open not in progress)
|
||||||
|
if (ClientState == ssWaitingtoOpen)
|
||||||
|
{
|
||||||
|
printf( "Socket: %s -> Cannot read from socket in waiting\n", ServerName );
|
||||||
|
SockBytesWaiting = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Read data into buffer
|
||||||
|
SockBytesRead = read( ClientHandle, &SockInBuffer[SockInLen], SockBytesWaiting ); // SockInBufLen-SockInLen
|
||||||
|
|
||||||
|
// Check of errors
|
||||||
|
if (SockBytesRead == -1)
|
||||||
|
{
|
||||||
|
printf( "Socket: %s -> Cannot read from socket (%s)\n", ServerName, strerror(errno) );
|
||||||
|
SockBytesRead = 0;
|
||||||
|
|
||||||
|
// Check of non-blocking write
|
||||||
|
// bool Blocked = ((errno == EAGAIN)? true : false );
|
||||||
|
}
|
||||||
|
else if (SockBytesRead > 0)
|
||||||
|
{
|
||||||
|
// Process Reply
|
||||||
|
SockInLen += SockBytesRead;
|
||||||
|
|
||||||
|
// Reset timer
|
||||||
|
SetStartTime( &SockInStart );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // if (!SockBytesWaiting)
|
||||||
|
{
|
||||||
|
// EOF from server (close connection)
|
||||||
|
CloseTCPSocket( ctRemoteClient );
|
||||||
|
ClientHandle = -1;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool MaintainSocket( int PortHandle )
|
||||||
|
{
|
||||||
|
// Init vars
|
||||||
|
long Duration = 0;
|
||||||
|
int BytesWritten = 0;
|
||||||
|
int StartWrite = 0;
|
||||||
|
|
||||||
|
if (SockInLen > 0)
|
||||||
|
{
|
||||||
|
// Check duration since last PortIn
|
||||||
|
Duration = TimePassed( SockInStart );
|
||||||
|
if (Duration > SockInTimeout)
|
||||||
|
{
|
||||||
|
// Handle buffer as packet
|
||||||
|
SockInBuffer[ SockInLen ] = 0;
|
||||||
|
//ShowOutput( "Sock", SockInBuffer, SockInLen, Duration );
|
||||||
|
|
||||||
|
// Write output to Port
|
||||||
|
BytesWritten = 0;
|
||||||
|
StartWrite = 0;
|
||||||
|
while (StartWrite < SockInLen) {
|
||||||
|
BytesWritten = write( PortHandle, &SockInBuffer[StartWrite], SockInLen );
|
||||||
|
StartWrite += BytesWritten;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset buffer and timer
|
||||||
|
SockInLen = 0;
|
||||||
|
SetInterval( &SockInStart, 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
42
SocketCore.h
Normal file
42
SocketCore.h
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* SocketCore.h
|
||||||
|
*
|
||||||
|
* Created on: 13 May 2016
|
||||||
|
* Author: wentzelc
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SOCKETCORE_H_
|
||||||
|
#define SOCKETCORE_H_
|
||||||
|
|
||||||
|
// redA Libraries
|
||||||
|
/* none */
|
||||||
|
|
||||||
|
// Standard C/C++ Libraries
|
||||||
|
/* none */
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Types required for sockets
|
||||||
|
typedef enum { ctNone = 0, ctServer = 1, ctRemoteClient = 2, ctClient = 3 } ESockConnectType;
|
||||||
|
const char SockConnectTypeName[][15] = { "None", "Server", "RemoteClient", "Client" };
|
||||||
|
|
||||||
|
typedef enum { ssNone = 0, ssWaitingtoOpen = 1, ssOpen = 2, ssDataWaiting = 3, ssClosed = 4, ssFailed = 5 } ESocketState;
|
||||||
|
const char SocketStateName[][15] = { "None", "WaitingToOpen", "Open", "DataWaiting", "Closed", "Failed" };
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Socket Functions
|
||||||
|
int OpenTCPserverSocket( const char *pServerName, const char *ServerAddress, int PortNo, bool KeepAlive );
|
||||||
|
int OpenTCPinClientSocket();
|
||||||
|
int OpenTCPoutClientSocket( const char *pServerName, const char *ServerAddress, int PortNo, bool KeepAlive );
|
||||||
|
|
||||||
|
ESocketState GetServerState();
|
||||||
|
ESocketState GetClientState();
|
||||||
|
|
||||||
|
bool CloseTCPSocket( ESockConnectType SocketType );
|
||||||
|
|
||||||
|
bool ReadClientSocket();
|
||||||
|
bool MaintainSocket( int PortHandle );
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#endif /* SOCKETCORE_H_ */
|
||||||
51
TimingCore.cpp
Normal file
51
TimingCore.cpp
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Timing.cpp
|
||||||
|
*
|
||||||
|
* Created on: 13 May 2016
|
||||||
|
* Author: wentzelc
|
||||||
|
*/
|
||||||
|
|
||||||
|
// redA Librarie
|
||||||
|
#include "TimingCore.h"
|
||||||
|
|
||||||
|
// Standard C/C++ Libraries
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Set time
|
||||||
|
void SetInterval( timeval * Time, long MilliSeconds )
|
||||||
|
{
|
||||||
|
// milli-seconds -> seconds
|
||||||
|
Time->tv_sec = MilliSeconds / 1000;
|
||||||
|
// milli-seconds -> micro-seconds
|
||||||
|
Time->tv_usec = (MilliSeconds % 1000) * 1000;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Populated start time
|
||||||
|
void SetStartTime( timeval * StartTime )
|
||||||
|
{
|
||||||
|
// Get current time
|
||||||
|
gettimeofday( StartTime, NULL );
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Calculate TimePassed from Start Time (in milli-seconds)
|
||||||
|
long TimePassed( timeval StartTime )
|
||||||
|
{
|
||||||
|
timeval CurrTime;
|
||||||
|
long Duration;
|
||||||
|
|
||||||
|
// Get current time
|
||||||
|
gettimeofday( &CurrTime, NULL );
|
||||||
|
|
||||||
|
// Get time passed in milli-seconds
|
||||||
|
Duration = (CurrTime.tv_sec - StartTime.tv_sec) * 1000 +
|
||||||
|
(CurrTime.tv_usec - StartTime.tv_usec) / 1000;
|
||||||
|
|
||||||
|
return Duration;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
25
TimingCore.h
Normal file
25
TimingCore.h
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Timing.h
|
||||||
|
*
|
||||||
|
* Created on: 13 May 2016
|
||||||
|
* Author: wentzelc
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TIMINGCORE_H_
|
||||||
|
#define TIMINGCORE_H_
|
||||||
|
|
||||||
|
// redA Libraries
|
||||||
|
/* none */
|
||||||
|
|
||||||
|
// Standard C/C++ Libraries
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void SetInterval( timeval *Time, long MilliSeconds );
|
||||||
|
void SetStartTime( timeval *StartTime );
|
||||||
|
long TimePassed( timeval StartTime );
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#endif /* TIMINGCORE_H_ */
|
||||||
Reference in New Issue
Block a user