1
0
Fork 0

Convert to using the APRSGateway.

ycs232-kbc
Jonathan Naylor 4 years ago
parent 815165141c
commit 7759575bbb

@ -10,6 +10,6 @@ The Gateway and Reflector have ini files that contain the parameters for running
The MMDVM .ini file should have the IP address and port number of the client in the [System Fusion Network] settings.
They build on 32-bit and 64-bit Linux as well as on Windows using Visual Studio 2017 on x86 and x64.
They build on 32-bit and 64-bit Linux as well as on Windows using Visual Studio 2019 on x86 and x64.
This software is licenced under the GPL v2 and is intended for amateur and educational use only. Use of this software for commercial purposes is strictly forbidden.

@ -25,8 +25,7 @@
#include <cstring>
#include <cmath>
CAPRSWriter::CAPRSWriter(const std::string& callsign, const std::string& rptSuffix, const std::string& password, const std::string& address, unsigned int port, const std::string& suffix) :
m_thread(NULL),
CAPRSWriter::CAPRSWriter(const std::string& callsign, const std::string& rptSuffix, const std::string& address, unsigned int port, const std::string& suffix) :
m_idTimer(1000U),
m_callsign(callsign),
m_txFrequency(0U),
@ -36,12 +35,14 @@ m_longitude(0.0F),
m_height(0),
m_desc(),
m_suffix(suffix),
m_aprsAddress(),
m_aprsPort(port),
m_aprsSocket(),
m_mobileGPSAddress(),
m_mobileGPSPort(0U),
m_socket(NULL)
m_mobileSocket(NULL)
{
assert(!callsign.empty());
assert(!password.empty());
assert(!address.empty());
assert(port > 0U);
@ -50,7 +51,7 @@ m_socket(NULL)
m_callsign.append(rptSuffix.substr(0U, 1U));
}
m_thread = new CAPRSWriterThread(m_callsign, password, address, port);
m_aprsAddress = CUDPSocket::lookup(address);
}
CAPRSWriter::~CAPRSWriter()
@ -79,16 +80,16 @@ void CAPRSWriter::setMobileLocation(const std::string& address, unsigned int por
m_mobileGPSAddress = CUDPSocket::lookup(address);
m_mobileGPSPort = port;
m_socket = new CUDPSocket;
m_mobileSocket = new CUDPSocket;
}
bool CAPRSWriter::open()
{
if (m_socket != NULL) {
bool ret = m_socket->open();
if (m_mobileSocket != NULL) {
bool ret = m_mobileSocket->open();
if (!ret) {
delete m_socket;
m_socket = NULL;
delete m_mobileSocket;
m_mobileSocket = NULL;
return false;
}
@ -100,7 +101,7 @@ bool CAPRSWriter::open()
m_idTimer.start();
return m_thread->start();
return m_aprsSocket.open();
}
void CAPRSWriter::write(const unsigned char* source, const char* type, unsigned char radio, float fLatitude, float fLongitude)
@ -155,22 +156,20 @@ void CAPRSWriter::write(const unsigned char* source, const char* type, unsigned
}
char output[300U];
::sprintf(output, "%s>APDPRS,C4FM*,qAR,%s:!%s%c/%s%c%c %s via MMDVM",
::sprintf(output, "%s>APDPRS,C4FM*,qAR,%s:!%s%c/%s%c%c %s via MMDVM\r\n",
callsign, m_callsign.c_str(),
lat, (fLatitude < 0.0F) ? 'S' : 'N',
lon, (fLongitude < 0.0F) ? 'W' : 'E',
symbol, type);
m_thread->write(output);
m_aprsSocket.write((unsigned char*)output, (unsigned int)::strlen(output), m_aprsAddress, m_aprsPort);
}
void CAPRSWriter::clock(unsigned int ms)
{
m_idTimer.clock(ms);
m_thread->clock(ms);
if (m_socket != NULL) {
if (m_mobileSocket != NULL) {
if (m_idTimer.hasExpired()) {
pollGPS();
m_idTimer.start();
@ -187,26 +186,23 @@ void CAPRSWriter::clock(unsigned int ms)
void CAPRSWriter::close()
{
if (m_socket != NULL) {
m_socket->close();
delete m_socket;
}
m_aprsSocket.close();
m_thread->stop();
if (m_mobileSocket != NULL) {
m_mobileSocket->close();
delete m_mobileSocket;
}
}
bool CAPRSWriter::pollGPS()
{
assert(m_socket != NULL);
assert(m_mobileSocket != NULL);
return m_socket->write((unsigned char*)"YSFGateway", 10U, m_mobileGPSAddress, m_mobileGPSPort);
return m_mobileSocket->write((unsigned char*)"YSFGateway", 10U, m_mobileGPSAddress, m_mobileGPSPort);
}
void CAPRSWriter::sendIdFrameFixed()
{
if (!m_thread->isConnected())
return;
// Default values aren't passed on
if (m_latitude == 0.0F && m_longitude == 0.0F)
return;
@ -257,13 +253,13 @@ void CAPRSWriter::sendIdFrameFixed()
server.append("S");
char output[500U];
::sprintf(output, "%s>APDG03,TCPIP*,qAC,%s:!%s%cD%s%c&/A=%06.0f%s %s",
::sprintf(output, "%s>APDG03,TCPIP*,qAC,%s:!%s%cD%s%c&/A=%06.0f%s %s\r\n",
m_callsign.c_str(), server.c_str(),
lat, (m_latitude < 0.0F) ? 'S' : 'N',
lon, (m_longitude < 0.0F) ? 'W' : 'E',
float(m_height) * 3.28F, band, desc);
m_thread->write(output);
m_aprsSocket.write((unsigned char*)output, (unsigned int)::strlen(output), m_aprsAddress, m_aprsPort);
}
void CAPRSWriter::sendIdFrameMobile()
@ -272,13 +268,10 @@ void CAPRSWriter::sendIdFrameMobile()
unsigned char buffer[200U];
in_addr address;
unsigned int port;
int ret = m_socket->read(buffer, 200U, address, port);
int ret = m_mobileSocket->read(buffer, 200U, address, port);
if (ret <= 0)
return;
if (!m_thread->isConnected())
return;
buffer[ret] = '\0';
// Parse the GPS data
@ -353,7 +346,7 @@ void CAPRSWriter::sendIdFrameMobile()
::sprintf(output + ::strlen(output), "%03.0f/%03.0f", rawBearing, rawVelocity * 0.539957F);
}
::sprintf(output + ::strlen(output), "/A=%06.0f%s %s", float(rawAltitude) * 3.28F, band, desc);
::sprintf(output + ::strlen(output), "/A=%06.0f%s %s\r\n", float(rawAltitude) * 3.28F, band, desc);
m_thread->write(output);
m_aprsSocket.write((unsigned char*)output, (unsigned int)::strlen(output), m_aprsAddress, m_aprsPort);
}

@ -1,5 +1,5 @@
/*
* Copyright (C) 2010,2011,2012,2016,2017,2018 by Jonathan Naylor G4KLX
* Copyright (C) 2010,2011,2012,2016,2017,2018,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -19,7 +19,6 @@
#ifndef APRSWriter_H
#define APRSWriter_H
#include "APRSWriterThread.h"
#include "UDPSocket.h"
#include "Timer.h"
@ -40,7 +39,7 @@
class CAPRSWriter {
public:
CAPRSWriter(const std::string& callsign, const std::string& rptSuffix, const std::string& password, const std::string& address, unsigned int port, const std::string& suffix);
CAPRSWriter(const std::string& callsign, const std::string& rptSuffix, const std::string& address, unsigned int port, const std::string& suffix);
~CAPRSWriter();
bool open();
@ -58,19 +57,21 @@ public:
void close();
private:
CAPRSWriterThread* m_thread;
CTimer m_idTimer;
std::string m_callsign;
unsigned int m_txFrequency;
unsigned int m_rxFrequency;
float m_latitude;
float m_longitude;
int m_height;
std::string m_desc;
std::string m_suffix;
in_addr m_mobileGPSAddress;
unsigned int m_mobileGPSPort;
CUDPSocket* m_socket;
CTimer m_idTimer;
std::string m_callsign;
unsigned int m_txFrequency;
unsigned int m_rxFrequency;
float m_latitude;
float m_longitude;
int m_height;
std::string m_desc;
std::string m_suffix;
in_addr m_aprsAddress;
unsigned int m_aprsPort;
CUDPSocket m_aprsSocket;
in_addr m_mobileGPSAddress;
unsigned int m_mobileGPSPort;
CUDPSocket* m_mobileSocket;
bool pollGPS();
void sendIdFrameFixed();

@ -1,279 +0,0 @@
/*
* Copyright (C) 2010-2014,2016,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "APRSWriterThread.h"
#include "Utils.h"
#include "Log.h"
#include <algorithm>
#include <functional>
#include <cctype>
#include <cstdint>
#include <cstdio>
#include <cassert>
// #define DUMP_TX
const unsigned int CALLSIGN_LENGTH = 8U;
const unsigned int APRS_TIMEOUT = 10U;
CAPRSWriterThread::CAPRSWriterThread(const std::string& callsign, const std::string& password, const std::string& address, unsigned int port) :
CThread(),
m_username(callsign),
m_password(password),
m_socket(address, port),
m_queue(20U, "APRS Queue"),
m_exit(false),
m_connected(false),
m_reconnectTimer(1000U),
m_tries(1U),
m_APRSReadCallback(NULL),
m_filter(),
m_clientName("YSFGateway")
{
assert(!callsign.empty());
assert(!password.empty());
assert(!address.empty());
assert(port > 0U);
m_username.resize(CALLSIGN_LENGTH, ' ');
m_username.erase(std::find_if(m_username.rbegin(), m_username.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), m_username.end());
std::transform(m_username.begin(), m_username.end(), m_username.begin(), ::toupper);
}
CAPRSWriterThread::CAPRSWriterThread(const std::string& callsign, const std::string& password, const std::string& address, unsigned int port, const std::string& filter, const std::string& clientName) :
CThread(),
m_username(callsign),
m_password(password),
m_socket(address, port),
m_queue(20U, "APRS Queue"),
m_exit(false),
m_connected(false),
m_reconnectTimer(1000U),
m_tries(1U),
m_APRSReadCallback(NULL),
m_filter(filter),
m_clientName(clientName)
{
assert(!callsign.empty());
assert(!password.empty());
assert(!address.empty());
assert(port > 0U);
m_username.resize(CALLSIGN_LENGTH, ' ');
m_username.erase(std::find_if(m_username.rbegin(), m_username.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), m_username.end());
std::transform(m_username.begin(), m_username.end(), m_username.begin(), ::toupper);
}
CAPRSWriterThread::~CAPRSWriterThread()
{
m_username.clear();
}
bool CAPRSWriterThread::start()
{
run();
return true;
}
void CAPRSWriterThread::entry()
{
LogMessage("Starting the APRS Writer thread");
m_connected = connect();
if (!m_connected) {
LogError("Connect attempt to the APRS server has failed");
startReconnectionTimer();
}
try {
while (!m_exit) {
if (!m_connected) {
if (m_reconnectTimer.isRunning() && m_reconnectTimer.hasExpired()) {
m_reconnectTimer.stop();
m_connected = connect();
if (!m_connected) {
LogError("Reconnect attempt to the APRS server has failed");
startReconnectionTimer();
}
}
}
if (m_connected) {
m_tries = 0U;
if (!m_queue.isEmpty()){
char* p = NULL;
m_queue.getData(&p, 1U);
LogMessage("APRS ==> %s", p);
::strcat(p, "\r\n");
bool ret = m_socket.write((unsigned char*)p, (unsigned int)::strlen(p));
if (!ret) {
m_connected = false;
m_socket.close();
LogError("Connection to the APRS thread has failed");
startReconnectionTimer();
}
delete[] p;
}
{
std::string line;
int length = m_socket.readLine(line, APRS_TIMEOUT);
if (length < 0) {
m_connected = false;
m_socket.close();
LogError("Error when reading from the APRS server");
startReconnectionTimer();
}
if(length > 0 && line.at(0U) != '#'//check if we have something and if that something is an APRS frame
&& m_APRSReadCallback != NULL)//do we have someone wanting an APRS Frame?
{
//wxLogMessage(wxT("Received APRS Frame : ") + line);
m_APRSReadCallback(std::string(line));
}
}
}
}
if (m_connected)
m_socket.close();
while (!m_queue.isEmpty()) {
char* p = NULL;
m_queue.getData(&p, 1U);
delete[] p;
}
}
catch (std::exception& e) {
LogError("Exception raised in the APRS Writer thread - \"%s\"", e.what());
}
catch (...) {
LogError("Unknown exception raised in the APRS Writer thread");
}
LogMessage("Stopping the APRS Writer thread");
}
void CAPRSWriterThread::setReadAPRSCallback(ReadAPRSFrameCallback cb)
{
m_APRSReadCallback = cb;
}
void CAPRSWriterThread::write(const char* data)
{
assert(data != NULL);
if (!m_connected)
return;
unsigned int len = (unsigned int)::strlen(data);
char* p = new char[len + 5U];
::strcpy(p, data);
m_queue.addData(&p, 1U);
}
bool CAPRSWriterThread::isConnected() const
{
return m_connected;
}
void CAPRSWriterThread::stop()
{
m_exit = true;
wait();
}
void CAPRSWriterThread::clock(unsigned int ms)
{
m_reconnectTimer.clock(ms);
}
bool CAPRSWriterThread::connect()
{
bool ret = m_socket.open();
if (!ret)
return false;
//wait for lgin banner
int length;
std::string serverResponse;
length = m_socket.readLine(serverResponse, APRS_TIMEOUT);
if (length == 0) {
LogError("No reply from the APRS server after %u seconds", APRS_TIMEOUT);
m_socket.close();
return false;
}
LogMessage("Received login banner : %s", serverResponse.c_str());
std::string filter(m_filter);
if (filter.length() > 0)
filter.insert(0U, " filter ");
char connectString[200U];
::sprintf(connectString, "user %s pass %s vers %s%s\n", m_username.c_str(), m_password.c_str(), (m_clientName.length() ? m_clientName : "YSFGateway").c_str(), filter.c_str());
ret = m_socket.writeLine(std::string(connectString));
if (!ret) {
m_socket.close();
return false;
}
length = m_socket.readLine(serverResponse, APRS_TIMEOUT);
if (length == 0) {
LogError("No reply from the APRS server after %u seconds", APRS_TIMEOUT);
m_socket.close();
return false;
}
if (length < 0) {
LogError("Error when reading from the APRS server");
m_socket.close();
return false;
}
LogMessage("Response from APRS server: %s", serverResponse.c_str());
LogMessage("Connected to the APRS server");
return true;
}
void CAPRSWriterThread::startReconnectionTimer()
{
// Clamp at a ten minutes reconnect time
m_tries++;
if (m_tries > 10U)
m_tries = 10U;
m_reconnectTimer.setTimeout(m_tries * 60U);
m_reconnectTimer.start();
}

@ -1,68 +0,0 @@
/*
* Copyright (C) 2010,2011,2012,2016,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef APRSWriterThread_H
#define APRSWriterThread_H
#include "TCPSocket.h"
#include "RingBuffer.h"
#include "Timer.h"
#include "Thread.h"
#include <string>
typedef void (*ReadAPRSFrameCallback)(const std::string&);
class CAPRSWriterThread : public CThread {
public:
CAPRSWriterThread(const std::string& callsign, const std::string& password, const std::string& address, unsigned int port);
CAPRSWriterThread(const std::string& callsign, const std::string& password, const std::string& address, unsigned int port, const std::string& filter, const std::string& clientName);
virtual ~CAPRSWriterThread();
virtual bool start();
virtual bool isConnected() const;
virtual void write(const char* data);
virtual void entry();
virtual void stop();
void setReadAPRSCallback(ReadAPRSFrameCallback cb);
void clock(unsigned int ms);
private:
std::string m_username;
std::string m_password;
CTCPSocket m_socket;
CRingBuffer<char*> m_queue;
bool m_exit;
bool m_connected;
CTimer m_reconnectTimer;
unsigned int m_tries;
ReadAPRSFrameCallback m_APRSReadCallback;
std::string m_filter;
std::string m_clientName;
bool connect();
void startReconnectionTimer();
};
#endif

@ -31,7 +31,7 @@ enum SECTION {
SECTION_GENERAL,
SECTION_INFO,
SECTION_LOG,
SECTION_APRS_FI,
SECTION_APRS,
SECTION_NETWORK,
SECTION_YSF_NETWORK,
SECTION_FCS_NETWORK,
@ -64,9 +64,8 @@ m_logFileLevel(0U),
m_logFilePath(),
m_logFileRoot(),
m_aprsEnabled(false),
m_aprsServer(),
m_aprsAddress(),
m_aprsPort(0U),
m_aprsPassword(),
m_aprsSuffix(),
m_aprsDescription(),
m_networkStartup(),
@ -122,8 +121,8 @@ bool CConf::read()
section = SECTION_INFO;
else if (::strncmp(buffer, "[Log]", 5U) == 0)
section = SECTION_LOG;
else if (::strncmp(buffer, "[aprs.fi]", 9U) == 0)
section = SECTION_APRS_FI;
else if (::strncmp(buffer, "[APRS]", 6U) == 0)
section = SECTION_APRS;
else if (::strncmp(buffer, "[Network]", 9U) == 0)
section = SECTION_NETWORK;
else if (::strncmp(buffer, "[YSF Network]", 13U) == 0)
@ -198,15 +197,13 @@ bool CConf::read()
m_logFileLevel = (unsigned int)::atoi(value);
else if (::strcmp(key, "DisplayLevel") == 0)
m_logDisplayLevel = (unsigned int)::atoi(value);
} else if (section == SECTION_APRS_FI) {
} else if (section == SECTION_APRS) {
if (::strcmp(key, "Enable") == 0)
m_aprsEnabled = ::atoi(value) == 1;
else if (::strcmp(key, "Server") == 0)
m_aprsServer = value;
else if (::strcmp(key, "Address") == 0)
m_aprsAddress = value;
else if (::strcmp(key, "Port") == 0)
m_aprsPort = (unsigned int)::atoi(value);
else if (::strcmp(key, "Password") == 0)
m_aprsPassword = value;
else if (::strcmp(key, "Suffix") == 0)
m_aprsSuffix = value;
else if (::strcmp(key, "Description") == 0)
@ -387,9 +384,9 @@ bool CConf::getAPRSEnabled() const
return m_aprsEnabled;
}
std::string CConf::getAPRSServer() const
std::string CConf::getAPRSAddress() const
{
return m_aprsServer;
return m_aprsAddress;
}
unsigned int CConf::getAPRSPort() const
@ -397,11 +394,6 @@ unsigned int CConf::getAPRSPort() const
return m_aprsPort;
}
std::string CConf::getAPRSPassword() const
{
return m_aprsPassword;
}
std::string CConf::getAPRSSuffix() const
{
return m_aprsSuffix;

@ -57,11 +57,10 @@ public:
std::string getLogFilePath() const;
std::string getLogFileRoot() const;
// The aprs.fi section
// The APRS section
bool getAPRSEnabled() const;
std::string getAPRSServer() const;
std::string getAPRSAddress() const;
unsigned int getAPRSPort() const;
std::string getAPRSPassword() const;
std::string getAPRSSuffix() const;
std::string getAPRSDescription() const;
@ -127,9 +126,8 @@ private:
std::string m_logFileRoot;
bool m_aprsEnabled;
std::string m_aprsServer;
std::string m_aprsAddress;
unsigned int m_aprsPort;
std::string m_aprsPassword;
std::string m_aprsSuffix;
std::string m_aprsDescription;

@ -4,7 +4,7 @@ CFLAGS = -g -O3 -Wall -std=c++0x -pthread
LIBS = -lm -lpthread
LDFLAGS = -g
OBJECTS = APRSWriterThread.o APRSWriter.o Conf.o CRC.o DTMF.o FCSNetwork.o Golay24128.o GPS.o Log.o StopWatch.o Sync.o TCPSocket.o Thread.o Timer.o \
OBJECTS = APRSWriter.o Conf.o CRC.o DTMF.o FCSNetwork.o Golay24128.o GPS.o Log.o StopWatch.o Sync.o Thread.o Timer.o \
UDPSocket.o Utils.o WiresX.o YSFConvolution.o YSFFICH.o YSFGateway.o YSFNetwork.o YSFPayload.o YSFReflectors.o
all: YSFGateway

@ -4,7 +4,7 @@ CFLAGS = -g -O3 -Wall -std=c++0x -pthread
LIBS = -lm -lpthread -lsocket
LDFLAGS = -g
OBJECTS = APRSWriterThread.o APRSWriter.o Conf.o CRC.o DTMF.o FCSNetwork.o Golay24128.o GPS.o Log.o StopWatch.o Sync.o TCPSocket.o Thread.o Timer.o \
OBJECTS = APRSWriter.o Conf.o CRC.o DTMF.o FCSNetwork.o Golay24128.o GPS.o Log.o StopWatch.o Sync.o Thread.o Timer.o \
UDPSocket.o Utils.o WiresX.o YSFConvolution.o YSFFICH.o YSFGateway.o YSFNetwork.o YSFPayload.o YSFReflectors.o
all: YSFGateway

@ -1,232 +0,0 @@
/*
* Copyright (C) 2010-2013,2016 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "TCPSocket.h"
#include "UDPSocket.h"
#include "Log.h"
#include <cstdio>
#include <cassert>
#include <cstring>
#if defined(_WIN32) || defined(_WIN64)
typedef int ssize_t;
#else
#include <cerrno>
#endif
CTCPSocket::CTCPSocket(const std::string& address, unsigned int port) :
m_address(address),
m_port(port),
m_fd(-1)
{
assert(!address.empty());
assert(port > 0U);
#if defined(_WIN32) || defined(_WIN64)
WSAData data;
int wsaRet = ::WSAStartup(MAKEWORD(2, 2), &data);
if (wsaRet != 0)
LogError("Error from WSAStartup");
#endif
}
CTCPSocket::~CTCPSocket()
{
#if defined(_WIN32) || defined(_WIN64)
::WSACleanup();
#endif
}
bool CTCPSocket::open()
{
if (m_fd != -1)
return true;
if (m_address.empty() || m_port == 0U)
return false;
m_fd = ::socket(PF_INET, SOCK_STREAM, 0);
if (m_fd < 0) {
#if defined(_WIN32) || defined(_WIN64)
LogError("Cannot create the TCP client socket, err=%d", ::GetLastError());
#else
LogError("Cannot create the TCP client socket, err=%d", errno);
#endif
return false;
}
struct sockaddr_in addr;
::memset(&addr, 0x00, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = htons(m_port);
addr.sin_addr = CUDPSocket::lookup(m_address);
if (addr.sin_addr.s_addr == INADDR_NONE) {
close();
return false;
}
if (::connect(m_fd, (sockaddr*)&addr, sizeof(struct sockaddr_in)) == -1) {
#if defined(_WIN32) || defined(_WIN64)
LogError("Cannot connect the TCP client socket, err=%d", ::GetLastError());
#else
LogError("Cannot connect the TCP client socket, err=%d", errno);
#endif
close();
return false;
}
int noDelay = 1;
if (::setsockopt(m_fd, IPPROTO_TCP, TCP_NODELAY, (char *)&noDelay, sizeof(noDelay)) == -1) {
#if defined(_WIN32) || defined(_WIN64)
LogError("Cannot set the TCP client socket option, err=%d", ::GetLastError());
#else
LogError("Cannot set the TCP client socket option, err=%d", errno);
#endif
close();
return false;
}
return true;
}
int CTCPSocket::read(unsigned char* buffer, unsigned int length, unsigned int secs, unsigned int msecs)
{
assert(buffer != NULL);
assert(length > 0U);
assert(m_fd != -1);
// Check that the recv() won't block
fd_set readFds;
FD_ZERO(&readFds);
#if defined(_WIN32) || defined(_WIN64)
FD_SET((unsigned int)m_fd, &readFds);
#else
FD_SET(m_fd, &readFds);
#endif
// Return after timeout
timeval tv;
tv.tv_sec = secs;
tv.tv_usec = msecs * 1000;
int ret = ::select(m_fd + 1, &readFds, NULL, NULL, &tv);
if (ret < 0) {
#if defined(_WIN32) || defined(_WIN64)
LogError("Error returned from TCP client select, err=%d", ::GetLastError());
#else
LogError("Error returned from TCP client select, err=%d", errno);
#endif
return -1;
}
#if defined(_WIN32) || defined(_WIN64)
if (!FD_ISSET((unsigned int)m_fd, &readFds))
return 0;
#else
if (!FD_ISSET(m_fd, &readFds))
return 0;
#endif
ssize_t len = ::recv(m_fd, (char*)buffer, length, 0);
if (len == 0) {
return -2;
} else if (len < 0) {
#if defined(_WIN32) || defined(_WIN64)
LogError("Error returned from recv, err=%d", ::GetLastError());
#else
LogError("Error returned from recv, err=%d", errno);
#endif
return -1;
}
return len;
}
int CTCPSocket::readLine(std::string& line, unsigned int secs)
{
// Maybe there is a better way to do this like reading blocks, pushing them for later calls
// Nevermind, we'll read one char at a time for the time being.
int resultCode;
int len = 0;
line.clear();
char c[2U];
c[1U] = 0x00U;
do
{
resultCode = read((unsigned char*)c, 1U, secs);
if (resultCode == 1){
line.append(c);
len++;
}
} while (c[0U] != '\n' && resultCode == 1);
return resultCode <= 0 ? resultCode : len;
}
bool CTCPSocket::write(const unsigned char* buffer, unsigned int length)
{
assert(buffer != NULL);
assert(length > 0U);
assert(m_fd != -1);
ssize_t ret = ::send(m_fd, (char *)buffer, length, 0);
if (ret != ssize_t(length)) {
#if defined(_WIN32) || defined(_WIN64)
LogError("Error returned from send, err=%d", ::GetLastError());
#else
LogError("Error returned from send, err=%d", errno);
#endif
return false;
}
return true;
}
bool CTCPSocket::writeLine(const std::string& line)
{
std::string lineCopy(line);
if (lineCopy.length() > 0 && lineCopy.at(lineCopy.length() - 1) != '\n')
lineCopy.append("\n");
//stupidly write one char after the other
size_t len = lineCopy.length();
bool result = true;
for (size_t i = 0U; i < len && result; i++){
unsigned char c = lineCopy.at(i);
result = write(&c , 1);
}
return result;
}
void CTCPSocket::close()
{
if (m_fd != -1) {
#if defined(_WIN32) || defined(_WIN64)
::closesocket(m_fd);
#else
::close(m_fd);
#endif
m_fd = -1;
}
}

@ -1,58 +0,0 @@
/*
* Copyright (C) 2010,2011,2012,2013,2016 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef TCPSocket_H
#define TCPSocket_H
#if !defined(_WIN32) && !defined(_WIN64)
#include <netdb.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <errno.h>
#else
#include <winsock.h>
#endif
#include <string>
class CTCPSocket {
public:
CTCPSocket(const std::string& address, unsigned int port);
~CTCPSocket();
bool open();
int read(unsigned char* buffer, unsigned int length, unsigned int secs, unsigned int msecs = 0U);
int readLine(std::string& line, unsigned int secs);
bool write(const unsigned char* buffer, unsigned int length);
bool writeLine(const std::string& line);
void close();
private:
std::string m_address;
unsigned short m_port;
int m_fd;
};
#endif

@ -19,6 +19,6 @@
#if !defined(VERSION_H)
#define VERSION_H
const char* VERSION = "20200405";
const char* VERSION = "20200601";
#endif

@ -454,12 +454,11 @@ void CYSFGateway::createGPS()
if (!m_conf.getAPRSEnabled())
return;
std::string hostname = m_conf.getAPRSServer();
unsigned int port = m_conf.getAPRSPort();
std::string password = m_conf.getAPRSPassword();
std::string suffix = m_conf.getAPRSSuffix();
std::string address = m_conf.getAPRSAddress();
unsigned int port = m_conf.getAPRSPort();
std::string suffix = m_conf.getAPRSSuffix();
m_writer = new CAPRSWriter(m_callsign, m_suffix, password, hostname, port, suffix);
m_writer = new CAPRSWriter(m_callsign, m_suffix, address, port, suffix);
unsigned int txFrequency = m_conf.getTxFrequency();
unsigned int rxFrequency = m_conf.getRxFrequency();

@ -28,12 +28,10 @@ FileLevel=1
FilePath=.
FileRoot=YSFGateway
[aprs.fi]
[APRS]
Enable=0
# Server=noam.aprs2.net
Server=euro.aprs2.net
Port=14580
Password=9999
Address=127.0.0.1
Port=8673
Description=APRS Description
Suffix=Y

@ -147,7 +147,6 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="APRSWriter.h" />
<ClInclude Include="APRSWriterThread.h" />
<ClInclude Include="Conf.h" />
<ClInclude Include="CRC.h" />
<ClInclude Include="DTMF.h" />
@ -158,7 +157,6 @@
<ClInclude Include="RingBuffer.h" />
<ClInclude Include="StopWatch.h" />
<ClInclude Include="Sync.h" />
<ClInclude Include="TCPSocket.h" />
<ClInclude Include="Thread.h" />
<ClInclude Include="Timer.h" />
<ClInclude Include="UDPSocket.h" />
@ -175,7 +173,6 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="APRSWriter.cpp" />
<ClCompile Include="APRSWriterThread.cpp" />
<ClCompile Include="Conf.cpp" />
<ClCompile Include="CRC.cpp" />
<ClCompile Include="DTMF.cpp" />
@ -185,7 +182,6 @@
<ClCompile Include="Log.cpp" />
<ClCompile Include="StopWatch.cpp" />
<ClCompile Include="Sync.cpp" />
<ClCompile Include="TCPSocket.cpp" />
<ClCompile Include="Thread.cpp" />
<ClCompile Include="Timer.cpp" />
<ClCompile Include="UDPSocket.cpp" />

@ -59,12 +59,6 @@
<ClInclude Include="WiresX.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="TCPSocket.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="APRSWriterThread.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Thread.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -130,12 +124,6 @@
<ClCompile Include="WiresX.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="TCPSocket.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="APRSWriterThread.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Thread.cpp">
<Filter>Source Files</Filter>
</ClCompile>

Loading…
Cancel
Save