much simpler, read-blocking aprs thread

dev
Tom Early 1 week ago
parent 29aee45b3a
commit 393e5ba83c

@ -47,7 +47,7 @@ CDPlusAuthenticator::~CDPlusAuthenticator()
int CDPlusAuthenticator::Process(CQnetDB &db, const bool reflectors, const bool repeaters)
// return true if everything went okay
{
int result = client.Open(m_address, AF_UNSPEC, "20001");
int result = client.Open(m_address, AF_UNSPEC, "20001", false);
if (result)
{
fprintf(stderr, "DPlus Authorization failed: %s\n", gai_strerror(result));

@ -43,6 +43,7 @@
#include <thread>
#include <chrono>
#include <csignal>
#include <iomanip>
#include "IRCDDB.h"
#include "IRCutils.h"
@ -50,7 +51,7 @@
#include "QnetGateway.h"
#include "Utilities.h"
const std::string GW_VERSION("QnetGateway-60706");
const std::string GW_VERSION("QnetGateway-261105");
int CQnetGateway::FindIndex(const int i) const
{
@ -335,6 +336,7 @@ bool CQnetGateway::ReadConfig(const std::string &cfgFile)
cfg.GetValue(path+"irc", estr, LOG_IRC);
cfg.GetValue(path+"dtmf", estr, LOG_DTMF);
cfg.GetValue(path+"debug", estr, LOG_DEBUG);
cfg.GetValue(path+"aprs", estr, LOG_APRS);
// file
path.assign("file_");
@ -2184,186 +2186,53 @@ void CQnetGateway::APRSBeaconThread()
char rcv_buf[512];
time_t tnow = 0;
/*
Every 20 seconds, the remote APRS host sends a KEEPALIVE packet-comment
on the TCP/APRS port.
If we have not received any KEEPALIVE packet-comment after 5 minutes
we must assume that the remote APRS host is down or disappeared
or has dropped the connection. In these cases, we must re-connect.
There are 3 keepalive packets in one minute, or every 20 seconds.
In 5 minutes, we should have received a total of 15 keepalive packets.
*/
int16_t THRESHOLD_COUNTDOWN = 15;
time_t last_keepalive_time;
time(&last_keepalive_time);
time_t last_beacon_time = 0;
/* This thread is also saying to the APRS_HOST that we are ALIVE */
while (keep_running)
{
if (aprs->aprs_sock.GetFD() == -1)
// start up the aprs client
while (keep_running and (aprs->aprs_sock.GetFD() < 0))
{
aprs->Open(OWNER);
aprs->Open(OWNER, GW_VERSION);
if (aprs->aprs_sock.GetFD() == -1)
sleep(1);
else
THRESHOLD_COUNTDOWN = 15;
sleep(5);
}
// see if it's time to update aprs beacon
time(&tnow);
if ((tnow - last_beacon_time) > (Rptr.aprs_interval * 60))
if ((tnow - last_beacon_time) >= (Rptr.aprs_interval * 60))
{
for (int16_t i=0; i<3; i++)
// update each channel, A B C
for (int i=0; i<3; i++)
{
if (Rptr.mod[i].defined)
if (Rptr.mod[i].defined and aprs->aprs_sock.GetFD() >= 0)
{
float tmp_lat = fabs(Rptr.mod[i].latitude);
float tmp_lon = fabs(Rptr.mod[i].longitude);
float lat = floor(tmp_lat);
float lon = floor(tmp_lon);
lat = (tmp_lat - lat) * 60.0F + lat * 100.0F;
lon = (tmp_lon - lon) * 60.0F + lon * 100.0F;
char lat_s[15], lon_s[15];
if (lat >= 1000.0F)
sprintf(lat_s, "%.2f", lat);
else if (lat >= 100.0F)
sprintf(lat_s, "0%.2f", lat);
else if (lat >= 10.0F)
sprintf(lat_s, "00%.2f", lat);
else
sprintf(lat_s, "000%.2f", lat);
if (lon >= 10000.0F)
sprintf(lon_s, "%.2f", lon);
else if (lon >= 1000.0F)
sprintf(lon_s, "0%.2f", lon);
else if (lon >= 100.0F)
sprintf(lon_s, "00%.2f", lon);
else if (lon >= 10.0F)
sprintf(lon_s, "000%.2f", lon);
else
sprintf(lon_s, "0000%.2f", lon);
/* send to aprs */
sprintf(snd_buf, "%s>APJI23,TCPIP*,qAC,%sS:!%s%cD%s%c&RNG%04u %s %s",
Rptr.mod[i].call.c_str(), Rptr.mod[i].call.c_str(),
lat_s, (Rptr.mod[i].latitude < 0.0) ? 'S' : 'N',
lon_s, (Rptr.mod[i].longitude < 0.0) ? 'W' : 'E',
(unsigned int)Rptr.mod[i].range, Rptr.mod[i].band.c_str(), GW_VERSION.c_str());
if (LOG_DEBUG)
printf("APRS Beacon =[%s]\n", snd_buf);
strcat(snd_buf, "\r\n");
while (keep_running)
{
if (aprs->aprs_sock.GetFD() == -1)
{
aprs->Open(OWNER);
if (aprs->aprs_sock.GetFD() == -1)
sleep(1);
else
THRESHOLD_COUNTDOWN = 15;
}
else
{
int rc = aprs->aprs_sock.Write((uint8_t *)snd_buf, strlen(snd_buf));
if (rc < 0)
{
if ((errno == EPIPE) ||
(errno == ECONNRESET) ||
(errno == ETIMEDOUT) ||
(errno == ECONNABORTED) ||
(errno == ESHUTDOWN) ||
(errno == EHOSTUNREACH) ||
(errno == ENETRESET) ||
(errno == ENETDOWN) ||
(errno == ENETUNREACH) ||
(errno == EHOSTDOWN) ||
(errno == ENOTCONN))
{
printf("send_aprs_beacon: APRS_HOST closed connection,error=%d\n",errno);
aprs->aprs_sock.Close();
}
else if (errno == EWOULDBLOCK)
{
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
else
{
/* Cant do nothing about it */
printf("send_aprs_beacon failed, error=%d\n", errno);
break;
}
}
else
{
// printf("APRS beacon sent\n");
break;
auto line = Rptr.mod[i].position_ss.str();
if (aprs->aprs_sock.WriteLine(line)) {
aprs->aprs_sock.Close();
} else {
if (aprs->aprs_sock.ReadLine(line)) {
aprs->aprs_sock.Close();
} else {
if (aprs->m_debug) {
printf("APRS packet ackn: %s\n", line.c_str());
}
time(&last_beacon_time);
}
int rc = aprs->aprs_sock.Read((uint8_t *)rcv_buf, sizeof(rcv_buf));
if (rc > 0)
THRESHOLD_COUNTDOWN = 15;
}
}
int rc = aprs->aprs_sock.Read((uint8_t *)rcv_buf, sizeof(rcv_buf));
if (rc > 0)
THRESHOLD_COUNTDOWN = 15;
}
time(&last_beacon_time);
}
/*
Are we still receiving from APRS host ?
*/
int rc = aprs->aprs_sock.Read((uint8_t *)rcv_buf, sizeof(rcv_buf));
if (rc < 0)
{
if ((errno == EPIPE) ||
(errno == ECONNRESET) ||
(errno == ETIMEDOUT) ||
(errno == ECONNABORTED) ||
(errno == ESHUTDOWN) ||
(errno == EHOSTUNREACH) ||
(errno == ENETRESET) ||
(errno == ENETDOWN) ||
(errno == ENETUNREACH) ||
(errno == EHOSTDOWN) ||
(errno == ENOTCONN))
{
printf("send_aprs_beacon: recv error: APRS_HOST closed connection,error=%d\n",errno);
aprs->aprs_sock.Close();
}
}
else if (rc == 0)
{
printf("send_aprs_beacon: recv: APRS shutdown\n");
aprs->aprs_sock.Close();
}
else
THRESHOLD_COUNTDOWN = 15;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
/* 20 seconds passed already ? */
time(&tnow);
if ((tnow - last_keepalive_time) > 20)
{
/* we should be receving keepalive packets ONLY if the connection is alive */
if (aprs->aprs_sock.GetFD() >= 0)
{
if (THRESHOLD_COUNTDOWN > 0)
THRESHOLD_COUNTDOWN--;
if (THRESHOLD_COUNTDOWN == 0)
{
printf("APRS host keepalive timeout\n");
aprs->aprs_sock.Close();
}
// Are we still receiving keepalives from APRS host ?
if (keep_running and aprs->aprs_sock.GetFD() >= 0) {
std::string line;
if (aprs->aprs_sock.ReadLine(line)) {
aprs->aprs_sock.Close();
} else {
if (aprs->m_debug)
printf("APRS keep alive: %s\n", line.c_str());
}
/* reset timer */
time(&last_keepalive_time);
}
}
printf("APRS beacon thread exiting...\n");
@ -2535,6 +2404,28 @@ void CQnetGateway::qrgs_and_maps()
return;
}
// Helper to convert decimal degrees to APRS DDMM.hh format
std::string CQnetGateway::convertToAprsCoordinate(double decimalDegrees, bool isLatitude)
{
double absolute = std::abs(decimalDegrees);
int degrees = static_cast<int>(absolute);
double minutes = (absolute - degrees) * 60.0;
std::stringstream ss;
if (isLatitude) {
// DDMM.hh (2 digits for degrees)
ss << std::setw(2) << std::setfill('0') << degrees;
ss << std::setw(5) << std::setfill('0') << std::fixed << std::setprecision(2) << minutes;
ss << (decimalDegrees >= 0 ? 'N' : 'S');
} else {
// DDDMM.hh (3 digits for degrees)
ss << std::setw(3) << std::setfill('0') << degrees;
ss << std::setw(5) << std::setfill('0') << std::fixed << std::setprecision(2) << minutes;
ss << (decimalDegrees >= 0 ? 'E' : 'W');
}
return ss.str();
}
bool CQnetGateway::Initialize(const std::string &path)
{
int16_t i;
@ -2631,7 +2522,7 @@ bool CQnetGateway::Initialize(const std::string &path)
if (APRS_ENABLE)
{
aprs = new CAPRS(&Rptr);
aprs = new CAPRS(&Rptr, LOG_APRS);
if (aprs)
aprs->Init();
else
@ -2639,8 +2530,17 @@ bool CQnetGateway::Initialize(const std::string &path)
printf("aprs class init failed!\nAPRS will be turned off");
APRS_ENABLE = false;
}
for (int i=0; i<3; i++) {
if (Rptr.mod[i].defined) {
Rptr.mod[i].position_ss << Rptr.mod[i].call << ">APRS,TCPIP*:"
<< '!' << convertToAprsCoordinate(Rptr.mod[i].latitude, true) << 'D' << convertToAprsCoordinate(Rptr.mod[i].longitude,false) << '&'
<< Rptr.mod[i].band << " Voice (DStar) "
<< std::fixed << std::setprecision(4) << std::showpos
<< Rptr.mod[i].frequency << "MHz " << Rptr.mod[i].offset << "MHz QnetGateway";
}
}
compute_aprs_hash();
}
compute_aprs_hash();
for (int j=0; j<2; j++)
{

@ -115,7 +115,7 @@ private:
std::string OWNER, owner, FILE_DTMF, FILE_ECHOTEST, IRCDDB_PASSWORD[2], FILE_QNVOICE_FILE, DASH_SHOW_ORDER;
bool GATEWAY_SEND_QRGS_MAP, GATEWAY_HEADER_REGEN, APRS_ENABLE, playNotInCache, showLastHeard;
bool LOG_DEBUG, LOG_IRC, LOG_DTMF, LOG_QSO, IS_HF[3];
bool LOG_APRS, LOG_DEBUG, LOG_IRC, LOG_DTMF, LOG_QSO, IS_HF[3];
int DASH_REFRESH, TIMING_PLAY_WAIT, TIMING_PLAY_DELAY, TIMING_TIMEOUT_ECHO, TIMING_TIMEOUT_VOICEMAIL, TIMING_TIMEOUT_REMOTE_G2, TIMING_TIMEOUT_LOCAL_RPTR, dtmf_digit;
@ -178,6 +178,9 @@ private:
int dtmf_last_frame[3];
unsigned int dtmf_counter[3];
// helper
std::string convertToAprsCoordinate(double decimalDegrees, bool isLatitude);
bool VoicePacketIsSync(const uint8_t *text) const;
int open_port(const SPORTIP *pip, int family);
void calcPFCS(uint8_t *packet, int len);

@ -1,6 +1,6 @@
/*
* Copyright (C) 2010-2013 by Jonathan Naylor G4KLX
* Copyright (C) 2019 by Thomas A. Early N7TAE
* Copyright (C) 2019,2026 by Thomas A. Early N7TAE
*
* 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
@ -27,25 +27,26 @@ CTCPReaderWriterClient::CTCPReaderWriterClient() : m_fd(-1)
{
}
bool CTCPReaderWriterClient::Open(const std::string &address, int family, const std::string &port)
bool CTCPReaderWriterClient::Open(const std::string &address, int family, const std::string &port, const bool debug)
{
const char *where { "TCP Open ERROR:" };
m_address = address;
m_port = port;
if (m_fd != -1)
{
fprintf(stderr, "ERROR: port for '%s' is already open!\n", m_address.c_str());
fprintf(stderr, "%s port for '%s' is already open!\n", where, m_address.c_str());
return true;
}
if (0 == m_address.size() || 0 == m_port.size() || 0 == std::stoul(m_port))
{
fprintf(stderr, "ERROR: '[%s]:%s' is malformed!\n", m_address.c_str(), m_port.c_str());
fprintf(stderr, "%s '[%s]:%s' is malformed!\n", where, m_address.c_str(), m_port.c_str());
return true;
}
if (AF_INET!=family && AF_INET6!=family && AF_UNSPEC!=family)
if (AF_INET!=family and AF_INET6!=family and AF_UNSPEC!=family)
{
fprintf(stderr, "ERROR: family must be AF_INET, AF_INET6 or AF_UNSPEC\n");
fprintf(stderr, "%s family must be AF_INET, AF_INET6 or AF_UNSPEC\n", where);
return true;
}
@ -53,19 +54,18 @@ bool CTCPReaderWriterClient::Open(const std::string &address, int family, const
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = family;
hints.ai_socktype = SOCK_STREAM;
//hints.ai_flags = AI_PASSIVE;
hints.ai_protocol = IPPROTO_TCP;
struct addrinfo *res;
int s = EAI_AGAIN;
int count = 0;
while (EAI_AGAIN==s and count++<20)
while (s and count++<20)
{
// connecting to a server, so we can wait until it's ready
s = getaddrinfo(m_address.c_str(), m_port.c_str(), &hints, &res);
if (s && s != EAI_AGAIN)
{
fprintf(stderr, "ERROR: getaddrinfo of %s: %s\n", m_address.c_str(), gai_strerror(s));
fprintf(stderr, "%s getaddrinfo of %s: %s\n", where, m_address.c_str(), gai_strerror(s));
return true;
}
std::this_thread::sleep_for(std::chrono::seconds(3));
@ -73,7 +73,7 @@ bool CTCPReaderWriterClient::Open(const std::string &address, int family, const
if (EAI_AGAIN == s)
{
fprintf(stderr, "ERROR getaddrinfo of %s failed 20 times\n", m_address.c_str());
fprintf(stderr, "%s getaddrinfo of %s failed 20 times\n", where, m_address.c_str());
return true;
}
@ -82,10 +82,21 @@ bool CTCPReaderWriterClient::Open(const std::string &address, int family, const
{
m_fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (m_fd == -1)
{
if (debug) fprintf(stderr, "%s socket() error - %s\n", where, strerror(errno));
continue;
}
int flag = 1;
if (setsockopt(m_fd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag)))
{
if (debug) fprintf(stderr, "%s setsockopt(TCP_NODELAY) - %s\n", where, strerror(errno));
Close();
continue;
}
if (connect(m_fd, rp->ai_addr, rp->ai_addrlen))
{
if (debug) fprintf(stderr, "%s connect() - %s\n", where, strerror(errno));
Close();
continue;
}
@ -104,7 +115,7 @@ bool CTCPReaderWriterClient::Open(const std::string &address, int family, const
addr = &(addr6->sin6_addr);
}
if (inet_ntop(rp->ai_family, addr, buf, INET6_ADDRSTRLEN))
fprintf(stderr, "Successfully connected to %s at [%s]:%s\n", m_address.c_str(), buf, m_port.c_str());
printf("Successfully connected to %s at [%s]:%s\n", m_address.c_str(), buf, m_port.c_str());
break;
}
}
@ -112,7 +123,7 @@ bool CTCPReaderWriterClient::Open(const std::string &address, int family, const
if (rp == NULL)
{
fprintf(stderr, "Could not connect to any system returned by %s\n", m_address.c_str());
fprintf(stderr, "%s Could not connect to %s\n", where, m_address.c_str());
m_fd = -1;
return true;
}
@ -122,17 +133,15 @@ bool CTCPReaderWriterClient::Open(const std::string &address, int family, const
int CTCPReaderWriterClient::ReadExact(uint8_t *buf, const unsigned int length)
{
unsigned int offset = 0U;
unsigned int read = 0U;
do
{
int n = Read(buf + offset, length - offset);
if (n < 0)
do {
int n = Read(buf + read, length - read);
if (n < 1)
return n;
offset += n;
}
while ((length - offset) > 0U);
read += n;
} while ((length - read) > 0U);
return length;
}
@ -147,68 +156,57 @@ int CTCPReaderWriterClient::Read(uint8_t* buffer, const unsigned int length)
if (len <= 0)
{
if (len < 0)
fprintf(stderr, "Error returned from recv, err=%d\n", errno);
fprintf(stderr, "TCP Read() ERROR: %s\n", strerror(errno));
else
fprintf(stderr, "TCP Read() ERROR: Port closed by server\n");
return -1;
}
return len;
}
int CTCPReaderWriterClient::ReadLine(std::string& line)
bool CTCPReaderWriterClient::ReadLine(std::string& line)
{
uint8_t c;
int resultCode;
int len = 0;
line = "";
int rtv;
do
{
resultCode = Read(&c, 1);
if(resultCode == 1)
{
do {
rtv = Read(&c, 1);
if (('\r' != c) and ('\n' != c) and (rtv == 1))
line += c;
len++;
}
}
while(c != '\n' && resultCode == 1);
} while(c != '\n' && rtv == 1);
return resultCode <= 0 ? resultCode : len;
return (rtv <= 0) ? true : false;
}
int CTCPReaderWriterClient::Write(const uint8_t *buffer, const unsigned int length)
bool CTCPReaderWriterClient::Write(const void *pvoid, const unsigned int length)
{
assert(buffer != NULL);
assert(pvoid != NULL);
assert(length > 0U);
assert(m_fd != -1);
unsigned int wrote = 0;
uint8_t *buffer = (uint8_t *)pvoid;
ssize_t ret = send(m_fd, (char *)buffer, length, 0);
if (ret != ssize_t(length))
{
if (ret < 0)
fprintf(stderr, "Error returned from send, err=%s\n", strerror(errno));
else
fprintf(stderr, "Error only wrote %d of %d bytes\n", int(ret), int(length));
return -1;
while (wrote < length) {
ssize_t ret = send(m_fd, buffer+wrote, length-wrote, 0);
if (ret <= 0)
{
if (ret < 0)
fprintf(stderr, "ERROR - TCP Write send(): %s\n", strerror(errno));
else
fprintf(stderr, "ERROR - TCP Write: port closed by server\n");
return true;
}
wrote += ret;
}
return ret;
return false;
}
bool CTCPReaderWriterClient::WriteLine(const std::string& line)
bool CTCPReaderWriterClient::WriteLine(std::string& line)
{
std::string lineCopy(line);
if(lineCopy.size() > 0 && lineCopy.at(lineCopy.size() - 1) != '\n')
lineCopy.append("\n");
size_t len = lineCopy.size();
bool result = true;
for(size_t i = 0; i < len && result; i++)
{
uint8_t c = lineCopy.at(i);
result = Write(&c, 1);
}
return result;
line.append("\r\n");
return Write(line.c_str(), line.size());
}
void CTCPReaderWriterClient::Close()

@ -3,7 +3,7 @@
/* end of inma once */
/*
* Copyright (C) 2010,2011,2012,2013 by Jonathan Naylor G4KLX
* Copyright (C) 2019 by Thomas A. Early N7TAE
* Copyright (C) 2019,2026 by Thomas A. Early N7TAE
*
* 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
@ -38,12 +38,12 @@ class CTCPReaderWriterClient
public:
CTCPReaderWriterClient();
bool Open(const std::string &address, int family, const std::string &port);
bool Open(const std::string &address, int family, const std::string &port, bool debug);
int ReadExact(uint8_t *buffer, const unsigned int length);
int Read(uint8_t *buffer, const unsigned int length);
int ReadLine(std::string &line);
int Write(const uint8_t* buffer, const unsigned int length);
bool WriteLine(const std::string &line);
bool ReadLine(std::string &line);
bool Write(const void* buffer, const unsigned int length);
bool WriteLine(std::string &line);
int GetFD() { return m_fd; }
void Close();

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016-2020 by Thomas A. Early N7TAE
* Copyright (C) 2016-2020,2026 by Thomas A. Early N7TAE
*
* 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
@ -26,9 +26,17 @@
#include <thread>
#include <chrono>
#include <sstream>
#include "aprs.h"
CAPRS::CAPRS(SRPTR *prptr, bool debug) : m_rptr(prptr), m_debug(debug) {}
CAPRS::~CAPRS()
{
aprs_sock.Close();
}
// This is called when header comes in from repeater
void CAPRS::SelectBand(int16_t rptr_idx, uint16_t streamID)
{
@ -120,16 +128,16 @@ void CAPRS::ProcessText(uint16_t streamID, uint8_t seq, uint8_t *buf)
if (rc == -1)
{
if ((errno == EPIPE) ||
(errno == ECONNRESET) ||
(errno == ETIMEDOUT) ||
(errno == ECONNABORTED) ||
(errno == ESHUTDOWN) ||
(errno == EHOSTUNREACH) ||
(errno == ENETRESET) ||
(errno == ENETDOWN) ||
(errno == ENETUNREACH) ||
(errno == EHOSTDOWN) ||
(errno == ENOTCONN))
(errno == ECONNRESET) ||
(errno == ETIMEDOUT) ||
(errno == ECONNABORTED) ||
(errno == ESHUTDOWN) ||
(errno == EHOSTUNREACH) ||
(errno == ENETRESET) ||
(errno == ENETDOWN) ||
(errno == ENETUNREACH) ||
(errno == EHOSTDOWN) ||
(errno == ENOTCONN))
{
printf("CAPRS::ProcessText(): APRS_HOST closed connection, error=%d\n",errno);
aprs_sock.Close();
@ -251,11 +259,9 @@ unsigned int CAPRS::GetData(int16_t rptr_idx, uint8_t *data, unsigned int len)
return l;
}
void CAPRS::Open(const std::string OWNER)
void CAPRS::Open(const std::string &OWNER, const std::string &NAME)
{
char snd_buf[512];
char rcv_buf[512];
while (aprs_sock.Open(m_rptr->aprs.ip, AF_UNSPEC, std::to_string(m_rptr->aprs.port)))
while (aprs_sock.Open(m_rptr->aprs.ip, AF_UNSPEC, std::to_string(m_rptr->aprs.port), m_debug))
{
fprintf(stderr, "Failed to open %s, retry in 10 seconds...\n", m_rptr->aprs.ip.c_str());
std::this_thread::sleep_for(std::chrono::seconds(10));
@ -263,41 +269,32 @@ void CAPRS::Open(const std::string OWNER)
/* login to aprs */
//sprintf(snd_buf, "user %s pass %d vers QnetGateway 9 UDP 5 ", OWNER.c_str(), m_rptr->aprs_hash);
sprintf(snd_buf, "user %s pass %d vers QnetGateway-9 ", OWNER.c_str(), m_rptr->aprs_hash);
std::stringstream ss;
ss << "user " << OWNER << " pass " << m_rptr->aprs_hash << " version " << NAME;
/* add the user's filter */
if (m_rptr->aprs_filter.length())
{
strcat(snd_buf, "filter ");
strcat(snd_buf, m_rptr->aprs_filter.c_str());
ss << " filter " << m_rptr->aprs_filter;
}
//printf("APRS Login command:[%s]\n", snd_buf);
strcat(snd_buf, "\r\n");
std::string str(ss.str());
if (m_debug)
printf("APRS Login: %s\n", str.c_str());
while (true)
{
int rc = aprs_sock.Write((uint8_t *)snd_buf, strlen(snd_buf));
if (rc < 0)
{
if (errno == EWOULDBLOCK)
{
aprs_sock.Read((uint8_t *)rcv_buf, sizeof(rcv_buf));
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
else
{
printf("APRS Login command failed, error=%d\n", errno);
break;
}
}
else
{
// printf("APRS Login command sent\n");
break;
}
if (aprs_sock.WriteLine(str)) {
fprintf(stderr, "Could write login into aprs\n");
aprs_sock.Close();
return;
}
if (aprs_sock.ReadLine(str)) {
fprintf(stderr, "Did not receive aprs login ackn\n");
aprs_sock.Close();
return;
}
aprs_sock.Read((uint8_t *)rcv_buf, sizeof(rcv_buf));
//printf("APRS Login returned: %s", rcv_buf);
if (m_debug)
printf("APRS Login returned: %s\n", str.c_str());
return;
}
@ -457,18 +454,3 @@ unsigned int CAPRS::CalcCRC(uint8_t* buf, unsigned int len)
}
return (~my_crc & 0xffff);
}
CAPRS::CAPRS(SRPTR *prptr)
{
m_rptr = prptr;
}
CAPRS::~CAPRS()
{
aprs_sock.Close();
}
void CAPRS::CloseSock()
{
aprs_sock.Close();
}

@ -1,7 +1,6 @@
#pragma once
/*
* Copyright (C) 2016 by Thomas A. Early N7TAE
/* Copyright (C) 2016,2026 by Thomas A. Early N7TAE
*
* 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,6 +18,7 @@
*/
#include <string>
#include <sstream>
#include <time.h>
#include <sys/socket.h>
#include <netinet/in.h>
@ -43,6 +43,7 @@ using SMOD = struct aprs_module
std::string band; /* 23cm ... */
double frequency, offset, latitude, longitude, range, agl;
std::string desc1, desc2, url, package_version;
std::stringstream position_ss;
};
using SRPTR = struct aprs_info
@ -59,15 +60,16 @@ using SRPTR = struct aprs_info
class CAPRS
{
public:
// data
const bool m_debug;
// functions
CAPRS(SRPTR *prptr);
CAPRS(SRPTR *prptr, bool debug);
~CAPRS();
SRPTR *m_rptr;
void SelectBand(int16_t rptr_idx, uint16_t streamID);
void ProcessText(uint16_t streamID, uint8_t seq, uint8_t *buf);
void Open(const std::string OWNER);
void Open(const std::string &OWNER, const std::string &NAME);
void Init();
void CloseSock();
CTCPReaderWriterClient aprs_sock;
private:

@ -174,6 +174,7 @@ log_qso_d=false # QSO info goes into the log
log_irc_d=false # IRC debug info
log_dtmf_d=false # DTMF debug info
log_debug_d=false # WARNING, can produce a large number of log entries!
log_aprs_d=false # APRS debug info
##########################################################################################################################
#

@ -8,8 +8,9 @@
#include "IRCutils.h"
#include "IRCDDBApp.h"
IRCClient::IRCClient(IRCDDBApp *app, const std::string &update_channel, const std::string &hostName, unsigned int port, const std::string &callsign, const std::string &password, const std::string &versionInfo)
IRCClient::IRCClient(IRCDDBApp *app, const std::string &update_channel, const std::string &hostName, unsigned int port, const std::string &callsign, const std::string &password, const std::string &versionInfo, bool logirc)
{
logIRC = logirc;
safeStringCopy(host_name, hostName.c_str(), sizeof host_name);
@ -79,7 +80,7 @@ void IRCClient::Entry()
else if (0 == strcmp(host_name, "ircv6.openquad.net"))
fam = AF_INET6;
if (! ircSock.Open(host_name, fam, std::to_string(port)))
if (! ircSock.Open(host_name, fam, std::to_string(port), logIRC))
{
state = 4;
timer = 0;

@ -14,7 +14,7 @@ class IRCDDBApp;
class IRCClient
{
public:
IRCClient(IRCDDBApp *app, const std::string &update_channel, const std::string &hostName, unsigned int port, const std::string &callsign, const std::string &password, const std::string &versionInfo);
IRCClient(IRCDDBApp *app, const std::string &update_channel, const std::string &hostName, unsigned int port, const std::string &callsign, const std::string &password, const std::string &versionInfo, bool logirc);
virtual ~IRCClient();
bool startWork();
@ -34,6 +34,7 @@ private:
std::string password;
bool terminateThread;
bool logIRC;
IRCReceiver receiver;
IRCMessageQueue *recvQ;

@ -10,7 +10,7 @@ CIRCDDB::CIRCDDB(const std::string &hostName, unsigned int port, const std::stri
const std::string update_channel("#dstar");
app = new IRCDDBApp(update_channel, &cache, log_irc);
client = new IRCClient(app, update_channel, hostName, port, callsign, password, versionInfo);
client = new IRCClient(app, update_channel, hostName, port, callsign, password, versionInfo, log_irc);
}
CIRCDDB::~CIRCDDB()

@ -178,6 +178,7 @@ FileMenu () {
fi
echo
echo " Additional entries in log files (in /usr/local/var)"
echo -n "al : APRS logging = "; EvaluateVar log_aprs{,d}
echo -n "cl : Call(QSO) logging = "; EvaluateVar log_qso{,_d}
echo -n "il : IRC logging = "; EvaluateVar log_irc{,_d}
echo -n "dl : DTMF logging = "; EvaluateVar log_dtmf{,_d}
@ -209,6 +210,7 @@ FileMenu () {
elif [[ "$key" == vf* ]]; then file_qnvoicefile="$value"
elif [[ "$key" == gf* ]]; then file_gwys="$value"
elif [[ "$key" == ad* ]]; then file_announce_dir="$value"
elif [[ "$key" == al* ]]; then SetBooleanValue log_aprs "$value"
elif [[ "$key" == cl* ]]; then SetBooleanValue log_qso "$value"
elif [[ "$key" == il* ]]; then SetBooleanValue log_irc "$value"
elif [[ "$key" == dl* ]]; then SetBooleanValue log_dtmf "$value"
@ -690,6 +692,7 @@ WriteCFGFile () {
[ -z "${link_acknowledge+x}" ] || echo "link_acknowledge=${link_acknowledge}" >> $outFile
[ -z "${link_max_dongles+x}" ] || echo "link_max_dongles=${link_max_dongles}" >> $outFile
# log_ section
[ -z "${log_aprs+x}" ] || echo "log_aprs=${log_aprs}" >> $outFile
[ -z "${log_qso+x}" ] || echo "log_qso=${log_qso}" >> $outFile
[ -z "${log_irc+x}" ] || echo "log_irc=${log_irc}" >> $outFile
[ -z "${log_dtmf+x}" ] || echo "log_dtmf=${log_dtmf}" >> $outFile

Loading…
Cancel
Save

Powered by TurnKey Linux.