new base classes and back to UnixDgrmSocket

dev
Tom Early 2 years ago
parent 80bec7ff0b
commit c7afc69935

@ -20,17 +20,34 @@
// base class for all modems
#include <sys/select.h>
#include <string>
#include <atomic>
class CKRBase
class CBase
{
public:
CKRBase();
bool IsRunning();
void SetState(bool state);
CBase() { keep_running = true; }
virtual ~CBase() {}
virtual bool Initialize(const std::string &path) = 0;
virtual void Run() = 0;
virtual void Close() = 0;
void Stop() { keep_running = false; }
protected:
static std::atomic<bool> keep_running;
static void SigHandler(int sig);
void AddFDSet(int &max, int newfd, fd_set *set);
std::atomic<bool> keep_running;
void AddFDSet(int &max, int newfd, fd_set *set)
{
if (newfd > max)
max = newfd;
FD_SET(newfd, set);
}
};
class CModem : public CBase
{
public:
CModem(int index = -1) : CBase(), m_index(index) {}
virtual ~CModem() {}
protected:
int m_index;
};

@ -1,63 +0,0 @@
/*
* Copyright (C) 2020 by Thomas 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
* 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 <csignal>
#include <iostream>
#include "KRBase.h"
std::atomic<bool> CKRBase::keep_running(true);
CKRBase::CKRBase()
{
std::signal(SIGINT, CKRBase::SigHandler);
std::signal(SIGHUP, CKRBase::SigHandler);
std::signal(SIGTERM, CKRBase::SigHandler);
}
bool CKRBase::IsRunning()
{
return keep_running;
}
void CKRBase::SetState(bool state)
{
keep_running = state;
}
void CKRBase::SigHandler(int sig)
{
switch (sig)
{
case SIGINT:
case SIGHUP:
case SIGTERM:
keep_running = false;
break;
default:
std::cerr << "caught an unexpected signal=" << sig << std::endl;
break;
}
}
void CKRBase::AddFDSet(int &max, int newfd, fd_set *set)
{
if (newfd > max)
max = newfd;
FD_SET(newfd, set);
}

@ -52,25 +52,25 @@ dvrptr : qndvrptr
itap : qnitap
modem : qnmodem
qngateway : QnetGateway.o KRBase.o aprs.o UnixDgramSocket.o UnixPacketSock.o TCPReaderWriterClient.o QnetConfigure.o QnetDB.o CacheManager.o DStarDecode.o Location.o $(IRCOBJS)
qngateway : QnetGateway.o aprs.o UnixDgramSocket.o TCPReaderWriterClient.o QnetConfigure.o QnetDB.o CacheManager.o DStarDecode.o Location.o $(IRCOBJS)
g++ -o $@ $^ $(LDFLAGS) -l sqlite3 -pthread
qnlink : QnetLink.o KRBase.o DPlusAuthenticator.o TCPReaderWriterClient.o UnixPacketSock.o UDPSocket.o QnetConfigure.o QnetDB.o
qnlink : QnetLink.o DPlusAuthenticator.o TCPReaderWriterClient.o UnixDgramSocket.o UDPSocket.o QnetConfigure.o QnetDB.o
g++ -o $@ $^ $(LDFLAGS) -l sqlite3 -pthread
qnrelay : QnetRelay.o KRBase.o UnixPacketSock.o QnetConfigure.o
qnrelay : QnetRelay.o UnixDgramSocket.o QnetConfigure.o
g++ -o $@ $^ $(LDFLAGS)
qnitap : QnetITAP.o KRBase.o UnixPacketSock.o QnetConfigure.o
qnitap : QnetITAP.o UnixDgramSocket.o QnetConfigure.o
g++ -o $@ $^ $(LDFLAGS)
qnmodem : QnetModem.o KRBase.o UnixPacketSock.o QnetConfigure.o
qnmodem : QnetModem.o UnixDgramSocket.o QnetConfigure.o
g++ -o $@ $^ $(LDFLAGS)
qndvap : QnetDVAP.o KRBase.o DVAPDongle.o UnixPacketSock.o QnetConfigure.o DStarDecode.o
qndvap : QnetDVAP.o DVAPDongle.o UnixDgramSocket.o QnetConfigure.o DStarDecode.o
g++ -o $@ $^ $(LDFLAGS) -pthread
qndvrptr : QnetDVRPTR.o KRBase.o UnixPacketSock.o QnetConfigure.o DStarDecode.o
qndvrptr : QnetDVRPTR.o UnixDgramSocket.o QnetConfigure.o DStarDecode.o
g++ -o $@ $^ $(LDFLAGS)
qnremote : QnetRemote.o UnixDgramSocket.o QnetConfigure.o

@ -40,9 +40,9 @@ char *CQnetConfigure::Trim(char *s)
return s;
}
bool CQnetConfigure::ReadConfigFile(const char *configfile, std::map<std::string, std::string> &amap)
bool CQnetConfigure::ReadConfigFile(const std::string &configfile, std::map<std::string, std::string> &amap)
{
FILE *fp = fopen(configfile, "r");
FILE *fp = fopen(configfile.c_str(), "r");
if (fp)
{
char line[2048];
@ -69,11 +69,11 @@ bool CQnetConfigure::ReadConfigFile(const char *configfile, std::map<std::string
fclose(fp);
return false;
}
fprintf(stderr, "could not open file %s\n", configfile);
fprintf(stderr, "could not open file %s\n", configfile.c_str());
return true;
}
bool CQnetConfigure::Initialize(const char *file)
bool CQnetConfigure::Initialize(const std::string &file)
{
std::string filename(CFG_DIR);
filename.append("/defaults");

@ -26,7 +26,7 @@ class CQnetConfigure
public:
CQnetConfigure();
virtual ~CQnetConfigure();
bool Initialize(const char *configfile);
bool Initialize(const std::string &path);
bool GetValue(const std::string &path, const std::string &mod, bool &value);
bool GetValue(const std::string &path, const std::string &mod, double &value, const double min, const double max);
bool GetValue(const std::string &path, const std::string &mod, int &value, const int min, const int max);
@ -38,7 +38,7 @@ private:
std::map<std::string, std::string> cfg;
char *Trim(char *s);
bool ReadConfigFile(const char *file, std::map<std::string, std::string> &amap);
bool ReadConfigFile(const std::string &file, std::map<std::string, std::string> &amap);
bool GetDefaultBool (const std::string &key, const std::string &mod, bool &dval);
bool GetDefaultDouble(const std::string &key, const std::string &mod, double &dval);
bool GetDefaultInt (const std::string &key, const std::string &mod, int &dval);

@ -43,13 +43,12 @@
#include "DVAPDongle.h"
#include "QnetTypeDefs.h"
#include "Random.h"
#include "UnixPacketSock.h"
#include "QnetConfigure.h"
#include "Timer.h"
#include "DStarDecode.h"
#include "QnetDVAP.h"
#define DVAP_VERSION "QnetDVAP-40411"
#define DVAP_VERSION "QnetDVAP-40417"
#define CALL_SIZE 8
#define IP_SIZE 15
@ -94,18 +93,18 @@ void CQnetDVAP::calcPFCS(unsigned char *packet, unsigned char *pfcs)
}
/* process configuration file */
bool CQnetDVAP::ReadConfig(const char *cfgFile)
bool CQnetDVAP::ReadConfig(const std::string &cfgFile)
{
CQnetConfigure cfg;
printf("Reading file %s\n", cfgFile);
printf("Reading file %s\n", cfgFile.c_str());
if (cfg.Initialize(cfgFile))
return true;
const std::string estr; // an empty string
std::string type;
std::string dvap_path("module_");
if (0 > assigned_module)
if (0 > m_index)
{
// we need to find the lone dvap module
for (int i=0; i<3; i++)
@ -118,11 +117,11 @@ bool CQnetDVAP::ReadConfig(const char *cfgFile)
if (type.compare("dvap"))
continue; // this ain't it!
dvap_path.assign(test);
assigned_module = i;
m_index = i;
break;
}
}
if (0 > assigned_module)
if (0 > m_index)
{
fprintf(stderr, "Error: no 'dvap' module found\n!");
return true;
@ -131,7 +130,7 @@ bool CQnetDVAP::ReadConfig(const char *cfgFile)
else
{
// make sure dvap module is defined
dvap_path.append(1, 'a' + assigned_module);
dvap_path.append(1, 'a' + m_index);
if (cfg.KeyExists(dvap_path))
{
cfg.GetValue(dvap_path, estr, type, 1, 16);
@ -143,12 +142,11 @@ bool CQnetDVAP::ReadConfig(const char *cfgFile)
}
else
{
fprintf(stderr, "Module '%c' is not defined.\n", 'a'+assigned_module);
fprintf(stderr, "Module '%c' is not defined.\n", 'a'+m_index);
return true;
}
}
RPTR_MOD = 'A' + assigned_module;
cfg.GetValue("gateway_tomodem"+std::string(1, 'a'+assigned_module), estr, togate, 1, FILENAME_MAX);
RPTR_MOD = 'A' + m_index;
if (cfg.KeyExists(dvap_path+"_callsign"))
{
if (cfg.GetValue(dvap_path+"_callsign", type, RPTR, 3, 6))
@ -233,13 +231,13 @@ void CQnetDVAP::ReadFromGateway()
tv.tv_sec = 0;
tv.tv_usec = MODULE_PACKET_WAIT;
FD_ZERO (&readfd);
int fd = ToGate.GetFD();
int fd = FromGate.GetFD();
FD_SET (fd, &readfd);
select(fd + 1, &readfd, NULL, NULL, &tv);
if (FD_ISSET(fd, &readfd))
{
len = ToGate.Read(dsvt.title, 56);
len = FromGate.Read(dsvt.title, 56);
if (len == 56)
{
if (busy20000)
@ -494,7 +492,6 @@ void CQnetDVAP::ReadFromGateway()
break;
}
}
return;
}
void CQnetDVAP::RptrAckThread(SDVAP_ACK_ARG *parg)
@ -872,13 +869,11 @@ void CQnetDVAP::ReadDVAPThread()
return;
}
bool CQnetDVAP::Init(const char *file, const int amod)
bool CQnetDVAP::Initialize(const std::string &file)
{
assigned_module = amod;
if (ReadConfig(file))
{
printf("Failed to process config file %s\n", file);
printf("Failed to process config file %s\n", file.c_str());
return true;
}
@ -910,12 +905,20 @@ bool CQnetDVAP::Init(const char *file, const int amod)
if (!dongle.Initialize(MODULE_DEVICE.c_str(), MODULE_SERIAL_NUMBER.c_str(), MODULE_FREQUENCY, MODULE_OFFSET, MODULE_POWER, MODULE_SQUELCH))
return true;
if (ToGate.Open(togate.c_str(), this))
std::string name("Gate2Modem");
name.append(1, RPTR_MOD);
printf("Opening %s\n", name.c_str());
if (FromGate.Open(name.c_str()))
{
dongle.Stop();
close(serfd);
return true;
}
name.assign("Modem");
name.append(1, RPTR_MOD);
name.append("2Gate");
ToGate.SetUp(name.c_str());
printf("DVAP opened and initialized!\n");
return false;
}
@ -923,10 +926,9 @@ bool CQnetDVAP::Init(const char *file, const int amod)
void CQnetDVAP::Run()
{
CTimer ackpoint;
std::future<void> readthread;
try
{
readthread = std::async(std::launch::async, &CQnetDVAP::ReadDVAPThread, this);
m_readThread = std::async(std::launch::async, &CQnetDVAP::ReadDVAPThread, this);
}
catch (const std::exception &e)
{
@ -972,16 +974,35 @@ void CQnetDVAP::Run()
}
}
}
}
readthread.get();
ToGate.Close();
void CQnetDVAP::Close()
{
m_readThread.get();
FromGate.Close();
printf("QnetDVAP exiting\n");
return;
}
int main(int argc, char *argv[])
std::unique_ptr<CQnetDVAP> pdvap;
static void HandleSignal(int sig)
{
switch (sig)
{
case SIGINT:
case SIGHUP:
case SIGTERM:
pdvap->Stop();
break;
default:
fprintf(stderr, "Caught an unknown signal: %d\n", sig);
break;
}
}
int main(int argc, char **argv)
{
setvbuf(stdout, NULL, _IOLBF, 0);
printf("%s\n", DVAP_VERSION);
if (argc != 2)
@ -992,7 +1013,7 @@ int main(int argc, char *argv[])
if ('-' == argv[1][0])
{
printf("%s Copyright (C) 2018-2020 by Thomas A. Early N7TAE\n", DVAP_VERSION);
printf("%s Copyright (C) 2018-2024 by Thomas A. Early N7TAE\n", DVAP_VERSION);
printf("QnetDVAP comes with ABSOLUTELY NO WARRANTY; see the LICENSE for details.\n");
printf("This is free software, and you are welcome to distribute it\nunder certain conditions that are discussed in the LICENSE file.\nS");
return EXIT_SUCCESS;
@ -1026,9 +1047,26 @@ int main(int argc, char *argv[])
return 1;
}
CQnetDVAP dvap;
if (dvap.Init(argv[1], mod))
pdvap = std::unique_ptr<CQnetDVAP>(new CQnetDVAP(mod));
if (! pdvap)
{
std::fprintf(stderr, "Could not make a DVAP!\n");
return EXIT_FAILURE;
}
std::signal(SIGINT, HandleSignal);
std::signal(SIGHUP, HandleSignal);
std::signal(SIGTERM, HandleSignal);
if (pdvap->Initialize(argv[1]))
return EXIT_FAILURE;
dvap.Run();
pdvap->Run();
pdvap->Close();
pdvap.reset();
return EXIT_SUCCESS;
}

@ -21,7 +21,8 @@
#include <future>
#include <queue>
#include "KRBase.h"
#include "UnixDgramSocket.h"
#include "Base.h"
using SDVAP_ACK_ARG = struct davp_ack_arg_tag
{
@ -29,14 +30,17 @@ using SDVAP_ACK_ARG = struct davp_ack_arg_tag
float ber;
};
class CQnetDVAP : public CKRBase
class CQnetDVAP : public CModem
{
public:
bool Init(const char *file, const int amod);
CQnetDVAP(int index) : CModem(index) {}
~CQnetDVAP() {}
bool Initialize(const std::string &path);
void Run();
void Close();
private:
bool ReadConfig(const char *file);
bool ReadConfig(const std::string &path);
void ReadFromGateway();
void calcPFCS(unsigned char *packet, unsigned char *pfcs);
void ReadDVAPThread();
@ -50,11 +54,11 @@ private:
// data
std::queue<std::future<void>> m_fqueue;
int assigned_module;
std::future<void> m_readThread;
// unix sockets
std::string togate;
CUnixPacketClient ToGate;
CUnixDgramWriter ToGate;
CUnixDgramReader FromGate;
/* Default configuration data */
std::string RPTR;
std::string OWNER;

@ -34,6 +34,8 @@
#include <termios.h>
#include <wchar.h>
#include <sys/file.h>
#include <csignal>
#include <memory>
#include "Random.h"
#include "QnetConfigure.h"
@ -1248,18 +1250,18 @@ void CQnetDVRPTR::calcPFCS(unsigned char *packet) //Netzwerk CRC
}
/* process configuration file */
bool CQnetDVRPTR::ReadConfig(const char *cfgFile)
bool CQnetDVRPTR::ReadConfig(const std::string &cfgFile)
{
CQnetConfigure cfg;
printf("Reading file %s\n", cfgFile);
printf("Reading file %s\n", cfgFile.c_str());
if (cfg.Initialize(cfgFile))
return true;
const std::string estr; // an empty string
std::string type;
std::string path("module_");
if (0 > assigned_module)
if (0 > m_index)
{
// we need to find the lone dvrptr module
for (int i=0; i<3; i++)
@ -1272,11 +1274,11 @@ bool CQnetDVRPTR::ReadConfig(const char *cfgFile)
if (type.compare("dvrptr"))
continue; // this ain't it!
path.assign(test);
assigned_module = i;
m_index = i;
break;
}
}
if (0 > assigned_module)
if (0 > m_index)
{
fprintf(stderr, "Error: no 'dvrptr' module found\n!");
return true;
@ -1285,7 +1287,7 @@ bool CQnetDVRPTR::ReadConfig(const char *cfgFile)
else
{
// make sure dvrptr module is defined
path.append(1, 'a' + assigned_module);
path.append(1, 'a' + m_index);
if (cfg.KeyExists(path))
{
cfg.GetValue(path, estr, type, 1, 16);
@ -1297,12 +1299,11 @@ bool CQnetDVRPTR::ReadConfig(const char *cfgFile)
}
else
{
fprintf(stderr, "Module '%c' is not defined.\n", 'a'+assigned_module);
fprintf(stderr, "Module '%c' is not defined.\n", 'a'+m_index);
return true;
}
}
DVRPTR_MOD = 'A' + assigned_module;
cfg.GetValue(std::string("gateway_tomodem")+std::string(1, 'a'+assigned_module), estr, togate, 1, FILENAME_MAX);
DVRPTR_MOD = 'A' + m_index;
std::string call;
if (cfg.GetValue("ircddb_login", type, call, 3, 6))
@ -1636,7 +1637,7 @@ void CQnetDVRPTR::readFrom20000()
unsigned char ctrl_in = 0x80;
bool written_to_q = false;
int fd = ToGate.GetFD();
int fd = FromGate.GetFD();
while (keep_running)
{
written_to_q = false;
@ -1648,7 +1649,7 @@ void CQnetDVRPTR::readFrom20000()
select(fd + 1, &readfd, NULL, NULL, &tv);
if (FD_ISSET(fd, &readfd))
{
len = ToGate.Read(recv_buf.title, 56);
len = FromGate.Read(recv_buf.title, 56);
if (len == 56)
{
if (busy20000)
@ -1980,67 +1981,11 @@ bool CQnetDVRPTR::check_serial()
return match;
}
int main(int argc, const char **argv)
{
setvbuf(stdout, NULL, _IOLBF, 0);
printf("dvrptr VERSION %s\n", DVRPTR_VERSION);
if (argc != 2)
{
fprintf(stderr, "Usage: %s <config_file>\n", argv[0]);
return 1;
}
if ('-' == argv[1][0])
{
printf("%s Copyright (C) 2018-2019 by Thomas A. Early N7TAE\n", DVRPTR_VERSION);
printf("QnetDVRPTR comes with ABSOLUTELY NO WARRANTY; see the LICENSE for details.\n");
printf("This is free software, and you are welcome to distribute it\nunder certain conditions that are discussed in the LICENSE file.\n");
return 0;
}
const char *qn = strstr(argv[0], "qndvrptr");
if (NULL == qn)
{
fprintf(stderr, "Error finding 'qndvrptr' in %s!\n", argv[0]);
return 1;
}
qn += 8;
int mod;
switch (*qn)
{
case 0:
mod = -1;
break;
case 'a':
mod = 0;
break;
case 'b':
mod = 1;
break;
case 'c':
mod = 2;
break;
default:
fprintf(stderr, "ERROR: '%s' is not a valid module\nassigned module must be a, b or c\n", argv[1]);
return 1;
}
CQnetDVRPTR dvrptr;
if (dvrptr.Init(argv[1], mod))
return EXIT_FAILURE;
dvrptr.Run();
return EXIT_SUCCESS;
}
bool CQnetDVRPTR::Init(const char *file, int mod)
bool CQnetDVRPTR::Initialize(const std::string &file)
{
assigned_module = mod;
if (ReadConfig(file))
{
fprintf(stderr, "Failed to process config file %s\n", file);
fprintf(stderr, "Failed to process config file %s\n", file.c_str());
return true;
}
@ -2074,8 +2019,15 @@ bool CQnetDVRPTR::Init(const char *file, int mod)
strcpy(DVCALL_and_MOD, DVCALL);
DVCALL_and_MOD[7] = DVRPTR_MOD;
if (ToGate.Open(togate.c_str(), this))
std::string name("Gate2Modem");
name.append(1, DVRPTR_MOD);
printf("Opening %s\n", name.c_str());
if (FromGate.Open(name.c_str()))
return true;
name.assign("Modem");
name.append(1, DVRPTR_MOD);
name.append("2Gate");
ToGate.SetUp(name.c_str());
if (RX_Inverse == true)
{
@ -2603,9 +2555,95 @@ void CQnetDVRPTR::Run()
}
}
}
}
ToGate.Close();
void CQnetDVRPTR::Close()
{
FromGate.Close();
printf("dvrptr exiting...\n");
}
return;
std::unique_ptr<CQnetDVRPTR> pdvrptr;
void SignalHandler(int sig)
{
switch (sig)
{
case SIGINT:
case SIGHUP:
case SIGTERM:
if (pdvrptr)
pdvrptr->Stop();
break;
default:
fprintf(stderr, "Caught an unexpected signal: %d\n", sig);
}
}
int main(int argc, const char **argv)
{
std::signal(SIGINT, SignalHandler);
std::signal(SIGHUP, SignalHandler);
std::signal(SIGTERM, SignalHandler);
printf("dvrptr VERSION %s\n", DVRPTR_VERSION);
if (argc != 2)
{
fprintf(stderr, "Usage: %s <config_file>\n", argv[0]);
return 1;
}
if ('-' == argv[1][0])
{
printf("%s Copyright (C) 2018-2019 by Thomas A. Early N7TAE\n", DVRPTR_VERSION);
printf("QnetDVRPTR comes with ABSOLUTELY NO WARRANTY; see the LICENSE for details.\n");
printf("This is free software, and you are welcome to distribute it\nunder certain conditions that are discussed in the LICENSE file.\n");
return 0;
}
const char *qn = strstr(argv[0], "qndvrptr");
if (NULL == qn)
{
fprintf(stderr, "Error finding 'qndvrptr' in %s!\n", argv[0]);
return 1;
}
qn += 8;
int mod;
switch (*qn)
{
case 0:
mod = -1;
break;
case 'a':
mod = 0;
break;
case 'b':
mod = 1;
break;
case 'c':
mod = 2;
break;
default:
fprintf(stderr, "ERROR: '%s' is not a valid module\nassigned module must be a, b or c\n", argv[1]);
return 1;
}
pdvrptr = std::unique_ptr<CQnetDVRPTR>(new CQnetDVRPTR(mod));
if (!pdvrptr)
{
fprintf(stderr, "Could not make a DVRPTR at %d\n", mod);
return EXIT_FAILURE;
}
if (pdvrptr->Initialize(argv[1]))
return EXIT_FAILURE;
pdvrptr->Run();
pdvrptr->Close();
pdvrptr.reset();
return EXIT_SUCCESS;
}

@ -20,10 +20,10 @@
#include <cstdint>
#include <string>
#include "UnixPacketSock.h"
#include "UnixDgramSocket.h"
#include "DStarDecode.h"
#include "QnetTypeDefs.h"
#include "KRBase.h"
#include "Base.h"
using tambevoicefec = unsigned char[9];
using tambevoice = unsigned char[6];
@ -35,15 +35,18 @@ using tambevoice = unsigned char[6];
#define GORLAY_MASK12 0xfffff800 // auxiliary vector for testing
#define GORLAY_GENPOL 0x00000c75 // generator polinomial, g(x)
class CQnetDVRPTR : public CKRBase
class CQnetDVRPTR : public CModem
{
public:
bool Init(const char *file, int assigned_module);
CQnetDVRPTR(int index) : CModem(index) {}
~CQnetDVRPTR() {}
bool Initialize(const std::string &file);
void Run();
void Close();
private:
CDStarDecode decode;
bool ReadConfig(const char *cfgFile);
bool ReadConfig(const std::string &cfgFile);
void readFrom20000();
bool check_serial();
void CleanCall(std::string &callsign);
@ -97,9 +100,8 @@ private:
unsigned char Modem_STATUS[6]= {0xD0,0x01,0x00,0x10,0x00,0x00}; // Status Abfragr
unsigned char Modem_SERIAL[6]= {0xD0,0x01,0x00,0x12,0x00,0x00};
int assigned_module;
std::string togate;
CUnixPacketClient ToGate;
CUnixDgramWriter ToGate;
CUnixDgramReader FromGate;
std::string DVRPTR_SERIAL;
char DVCALL[CALL_SIZE + 1];

@ -203,7 +203,7 @@ void CQnetGateway::calcPFCS(unsigned char *packet, int len)
}
/* process configuration file */
bool CQnetGateway::ReadConfig(char *cfgFile)
bool CQnetGateway::ReadConfig(const std::string &cfgFile)
{
const std::string estr; // an empty string
CQnetConfigure cfg;
@ -298,13 +298,10 @@ bool CQnetGateway::ReadConfig(char *cfgFile)
cfg.GetValue(path+"ipv6_port", estr, g2_ipv6_external.port, 1024, 65535);
cfg.GetValue(path+"header_regen", estr, GATEWAY_HEADER_REGEN);
cfg.GetValue(path+"send_qrgs_maps", estr, GATEWAY_SEND_QRGS_MAP);
cfg.GetValue(path+"tolink", estr, tolink, 1, FILENAME_MAX);
cfg.GetValue(path+"fromremote", estr, fromremote, 1, FILENAME_MAX);
for (int m=0; m<3; m++)
{
if (Rptr.mod[m].defined)
{
cfg.GetValue(path+"tomodem"+std::string(1, 'a'+m), estr, tomodem[m], 1, FILENAME_MAX);
cfg.GetValue(path+"latitude", estr, Rptr.mod[m].latitude, -90.0, 90.0);
cfg.GetValue(path+"longitude", estr, Rptr.mod[m].longitude, -180.0, 180.0);
cfg.GetValue(path+"desc1", estr, Rptr.mod[m].desc1, 0, 20);
@ -404,7 +401,7 @@ void CQnetGateway::GetIRCDataThread(const int i)
not_announced[i] = Rptr.mod[i].defined; // announce to all modules that are defined!
bool is_quadnet = (std::string::npos != ircddb[i].ip.find(".openquad.net"));
bool doFind = true;
while (IsRunning())
while (keep_running)
{
int rc = ii[i]->getConnectionState();
if (rc > 5 && rc < 8 && is_quadnet)
@ -476,7 +473,7 @@ void CQnetGateway::GetIRCDataThread(const int i)
threshold = 0;
}
while (((type = ii[i]->getMessageType()) != IDRT_NONE) && IsRunning())
while (((type = ii[i]->getMessageType()) != IDRT_NONE) && keep_running)
{
switch (type)
{
@ -504,7 +501,7 @@ void CQnetGateway::GetIRCDataThread(const int i)
default:
break;
} // switch (type)
} // while (IsRunning())
} // while (keep_running)
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
printf("GetIRCDataThread[%i] exiting...\n", i);
@ -1148,7 +1145,7 @@ void CQnetGateway::ProcessG2Header(const SDSVT &g2buf, const int source_sock)
if (source_sock >= 0)
printf("IP=[%s]:%u\n", fromDstar.GetAddress(), fromDstar.GetPort());
else
printf("UnixSock=%s\n", tolink.c_str());
printf("UnixSock=Link2Gate\n");
}
lhcallsign[i].assign((const char *)g2buf.hdr.mycall, 8);
if (showLastHeard && memcmp(g2buf.hdr.sfx, "RPTR", 4) && std::regex_match(lhcallsign[i].c_str(), preg))
@ -2031,7 +2028,7 @@ void CQnetGateway::ProcessModem(const ssize_t recvlen, SDSVT &dsvt)
}
/* run the main loop for QnetGateway */
void CQnetGateway::Process()
void CQnetGateway::Run()
{
// dtmf stuff initialize
for (int i=0; i<3; i++)
@ -2068,16 +2065,16 @@ void CQnetGateway::Process()
catch (const std::exception &e)
{
printf("Failed to start GetIRCDataThread[%d]. Exception: %s\n", i, e.what());
SetState(false);
keep_running = false;
}
if (IsRunning())
if (keep_running)
printf("get_irc_data thread[%d] started\n", i);
ii[i]->kickWatchdog(GW_VERSION);
}
}
while (IsRunning())
while (keep_running)
{
if (! m_fqueue.empty())
{
@ -2105,11 +2102,11 @@ void CQnetGateway::Process()
AddFDSet(max_nfds, g2_sock[0], &fdset);
if (g2_sock[1] >= 0)
AddFDSet(max_nfds, g2_sock[1], &fdset);
AddFDSet(max_nfds, ToLink.GetFD(), &fdset);
AddFDSet(max_nfds, FromLink.GetFD(), &fdset);
for (int i=0; i<3; i++)
{
if (Rptr.mod[i].defined)
AddFDSet(max_nfds, ToModem[i].GetFD(), &fdset);
AddFDSet(max_nfds, FromModem[i].GetFD(), &fdset);
}
AddFDSet(max_nfds, FromRemote.GetFD(), &fdset);
struct timeval tv;
@ -2122,7 +2119,7 @@ void CQnetGateway::Process()
{
if (g2_sock[i] < 0)
continue;
if (IsRunning() && FD_ISSET(g2_sock[i], &fdset))
if (keep_running && FD_ISSET(g2_sock[i], &fdset))
{
SDSVT dsvt;
socklen_t fromlen = sizeof(struct sockaddr_storage);
@ -2136,7 +2133,7 @@ void CQnetGateway::Process()
}
// process packets from qnremote
if (IsRunning() && FD_ISSET(FromRemote.GetFD(), &fdset))
if (keep_running && FD_ISSET(FromRemote.GetFD(), &fdset))
{
SDSVT dsvt;
const ssize_t len = FromRemote.Read(dsvt.title, 56);
@ -2145,10 +2142,10 @@ void CQnetGateway::Process()
}
// process packets from qnlink
if (IsRunning() && FD_ISSET(ToLink.GetFD(), &fdset))
if (keep_running && FD_ISSET(FromLink.GetFD(), &fdset))
{
SDSVT dsvt;
ssize_t g2buflen = ToLink.Read(dsvt.title, 56);
ssize_t g2buflen = FromLink.Read(dsvt.title, 56);
if (16==g2buflen && 0==memcmp(dsvt.title, "LINK", 4))
{
SLINKFAMILY fam;
@ -2167,19 +2164,19 @@ void CQnetGateway::Process()
{
ProcessG2(g2buflen, dsvt, -1);
}
FD_CLR(ToLink.GetFD(), &fdset);
FD_CLR(FromLink.GetFD(), &fdset);
}
// process packets coming from local repeater module(s)
for (int i=0; i<3; i++)
{
if (IsRunning() && FD_ISSET(ToModem[i].GetFD(), &fdset))
if (keep_running && FD_ISSET(FromModem[i].GetFD(), &fdset))
{
SDSVT dsvt;
const ssize_t len = ToModem[i].Read(dsvt.title, 56);
const ssize_t len = FromModem[i].Read(dsvt.title, 56);
if (Rptr.mod[i].defined)
ProcessModem(len, dsvt);
FD_CLR(ToModem[i].GetFD(), &fdset);
FD_CLR(FromModem[i].GetFD(), &fdset);
}
}
}
@ -2246,7 +2243,7 @@ void CQnetGateway::APRSBeaconThread()
time_t last_beacon_time = 0;
/* This thread is also saying to the APRS_HOST that we are ALIVE */
while (IsRunning())
while (keep_running)
{
if (aprs->aprs_sock.GetFD() == -1)
{
@ -2302,7 +2299,7 @@ void CQnetGateway::APRSBeaconThread()
printf("APRS Beacon =[%s]\n", snd_buf);
strcat(snd_buf, "\r\n");
while (IsRunning())
while (keep_running)
{
if (aprs->aprs_sock.GetFD() == -1)
{
@ -2581,7 +2578,7 @@ void CQnetGateway::qrgs_and_maps()
return;
}
bool CQnetGateway::Init(char *cfgfile)
bool CQnetGateway::Initialize(const std::string &path)
{
short int i;
@ -2597,9 +2594,9 @@ bool CQnetGateway::Init(char *cfgfile)
}
/* process configuration file */
if ( ReadConfig(cfgfile) )
if ( ReadConfig(path) )
{
printf("Failed to process config file %s\n", cfgfile);
printf("Failed to process config file %s\n", path.c_str());
return true;
}
@ -2611,20 +2608,28 @@ bool CQnetGateway::Init(char *cfgfile)
qnDB.ClearLH();
// Open unix sockets between qngateway and qnremote
printf("Connecting to qnlink at %s\n", tolink.c_str());
if (ToLink.Open(tolink.c_str(), this))
printf("Opening Link2Gate\n");
if (FromLink.Open("Link2Gate"))
return true;
printf("Opening remote port at %s\n", fromremote.c_str());
if (FromRemote.Open(fromremote.c_str()))
ToLink.SetUp("Gate2Link");
printf("Opening Remote2Gate\n");
if (FromRemote.Open("Remote2Gate"))
return true;
for (i=0; i<3; i++)
{
if (Rptr.mod[i].defined) // open unix sockets between qngateway and each defined modem
{
printf("Connecting to modem at %s\n", tomodem[i].c_str());
if (ToModem[i].Open(tomodem[i].c_str(), this))
const char mod = 'A'+i;
std::string name("Modem");
name.append(1, mod);
name.append("2Gate");
printf("Opening %s\n", name.c_str());
if (FromModem[i].Open(name.c_str()))
return true;
name.assign("Gate2Modem");
name.append(1, mod);
ToModem[i].SetUp(name.c_str());
}
// recording for echotest on local repeater modules
recd[i].last_time = 0;
@ -2714,7 +2719,7 @@ bool CQnetGateway::Init(char *cfgfile)
else
break;
if (!IsRunning())
if (!keep_running)
break;
if (i > 5)
@ -2811,19 +2816,19 @@ bool CQnetGateway::Init(char *cfgfile)
return false;
}
CQnetGateway::CQnetGateway()
CQnetGateway::CQnetGateway() : CBase()
{
ii[0] = ii[1] = NULL;
}
CQnetGateway::~CQnetGateway()
void CQnetGateway::Close()
{
ToLink.Close();
FromLink.Close();
FromRemote.Close();
for (int i=0; i<3; i++)
{
if (Rptr.mod[i].defined)
ToModem[i].Close();
FromModem[i].Close();
}
if (APRS_ENABLE)
@ -2864,19 +2869,43 @@ CQnetGateway::~CQnetGateway()
printf("QnetGateway exiting\n");
}
CQnetGateway QnetGateway;
static void HandleSignal(int sig)
{
switch (sig)
{
case SIGINT:
case SIGHUP:
case SIGTERM:
QnetGateway.Stop();
break;
default:
fprintf(stderr, "Caught an unknown signal: %d\n", sig);
break;
}
}
int main(int argc, char **argv)
{
std::signal(SIGINT, HandleSignal);
std::signal(SIGHUP, HandleSignal);
std::signal(SIGTERM, HandleSignal);
printf("VERSION %s\n", GW_VERSION.c_str());
if (argc != 2)
{
printf("usage: %s qn.cfg\n", argv[0]);
return 1;
return EXIT_FAILURE;
}
CQnetGateway QnetGateway;
if (QnetGateway.Init(argv[1]))
if (QnetGateway.Initialize(argv[1]))
{
return 1;
return EXIT_FAILURE;
}
QnetGateway.Process();
QnetGateway.Run();
QnetGateway.Close();
printf("Leaving processing loop...\n");
return EXIT_SUCCESS;
}

@ -25,12 +25,11 @@
#include "QnetTypeDefs.h"
#include "SEcho.h"
#include "UnixDgramSocket.h"
#include "UnixPacketSock.h"
#include "aprs.h"
#include "SockAddress.h"
#include "QnetDB.h"
#include "DStarDecode.h"
#include "KRBase.h"
#include "Base.h"
#include "Location.h"
#define MAXHOSTNAMELEN 64
@ -93,13 +92,13 @@ using SSD = struct sd_tag
void Init() { ih = im = ig = 0; first = true; }
};
class CQnetGateway : public CKRBase
class CQnetGateway : public CBase
{
public:
CQnetGateway();
~CQnetGateway();
void Process();
bool Init(char *cfgfile);
bool Initialize(const std::string &path);
void Run();
void Close();
private:
std::queue<std::future<void>> m_fqueue;
@ -112,10 +111,8 @@ private:
SPORTIP g2_external, g2_ipv6_external, ircddb[2];
CUnixDgramReader FromRemote;
CUnixPacketServer ToLink, ToModem[3];
std::string tolink, fromremote, tomodem[3];
CUnixDgramReader FromRemote, FromLink, FromModem[3];
CUnixDgramWriter ToLink, ToModem[3];
std::string OWNER, owner, FILE_DTMF, FILE_ECHOTEST, IRCDDB_PASSWORD[2], FILE_QNVOICE_FILE, DASH_SHOW_ORDER;
@ -194,7 +191,6 @@ private:
void APRSBeaconThread();
bool Printable(unsigned char *string);
void ProcessTimeouts();
void ProcessSlowData(unsigned char *data, const unsigned short sid);
void ProcessIncomingSD(const SDSVT &dsvt, const int source_sock);
void ProcessOutGoingSD(const SDSVT &dsvt, const int mod);
bool ProcessG2Msg(const unsigned char *data, const int mod, std::string &smrtgrp);
@ -207,7 +203,7 @@ private:
int FindIndex(const int i) const;
// read configuration file
bool ReadConfig(char *);
bool ReadConfig(const std::string &path);
void qrgs_and_maps();

@ -39,29 +39,32 @@
#include <errno.h>
#include <thread>
#include <chrono>
#include <memory>
#include "QnetITAP.h"
#include "QnetTypeDefs.h"
#include "QnetConfigure.h"
#include "Timer.h"
#define ITAP_VERSION "QnetITAP-20307"
#define ITAP_VERSION "QnetITAP-40419"
CQnetITAP::CQnetITAP(int mod)
: assigned_module(mod)
{
}
CQnetITAP::~CQnetITAP()
{
}
bool CQnetITAP::Initialize(const char *cfgfile)
bool CQnetITAP::Initialize(const std::string &cfgfile)
{
if (ReadConfig(cfgfile))
return true;
if (ToGate.Open(togate.c_str(), this))
std::string name("Gate2Modem");
std::string(1, RPTR_MOD);
printf("Opening %s\n", name.c_str());
if (FromGate.Open(name.c_str()))
return true;
name.assign("Modem");
name.append(1, RPTR_MOD);
name.append("2Gate");
ToGate.SetUp(name.c_str());
serfd = OpenITAP();
if (serfd < 0)
return true;
return false;
@ -209,19 +212,8 @@ REPLY_TYPE CQnetITAP::GetITAPData(unsigned char *buf)
}
}
void CQnetITAP::Run(const char *cfgfile)
void CQnetITAP::Run()
{
if (Initialize(cfgfile))
return;
serfd = OpenITAP();
if (serfd < 0)
return;
int ug2m = ToGate.GetFD();
printf("gate2modem=%d, serial=%d\n", ug2m, serfd);
keep_running = true;
unsigned int poll_counter = 0;
bool initialized = false;
bool alive = true;
@ -231,10 +223,11 @@ void CQnetITAP::Run(const char *cfgfile)
CTimer pingTimer;
double pingtime = 0.001;
const double ackwait = AP_MODE ? 0.4 : 0.06;
int ug2m = FromGate.GetFD();
printf("gate2modem=%d, serial=%d\n", ug2m, serfd);
while (keep_running)
{
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(serfd, &readfds);
@ -357,7 +350,7 @@ void CQnetITAP::Run(const char *cfgfile)
if (keep_running && FD_ISSET(ug2m, &readfds))
{
ssize_t len = ToGate.Read(buf, 100);
ssize_t len = FromGate.Read(buf, 100);
if (len < 0)
{
@ -422,9 +415,12 @@ void CQnetITAP::Run(const char *cfgfile)
}
}
}
}
void CQnetITAP::Close()
{
close(serfd);
ToGate.Close();
FromGate.Close();
}
void CQnetITAP::SendToIcom(const unsigned char *buf)
@ -600,17 +596,17 @@ bool CQnetITAP::ProcessITAP(const unsigned char *buf)
}
// process configuration file and return true if there was a problem
bool CQnetITAP::ReadConfig(const char *cfgFile)
bool CQnetITAP::ReadConfig(const std::string &cfgFile)
{
CQnetConfigure cfg;
printf("Reading file %s\n", cfgFile);
printf("Reading file %s\n", cfgFile.c_str());
if (cfg.Initialize(cfgFile))
return true;
const std::string estr; // an empty string
std::string type;
std::string itap_path("module_");
if (0 > assigned_module)
if (0 > m_index)
{
// we need to find the lone itap module
for (int i=0; i<3; i++)
@ -623,11 +619,11 @@ bool CQnetITAP::ReadConfig(const char *cfgFile)
if (type.compare("itap"))
continue; // this ain't it!
itap_path.assign(test);
assigned_module = i;
m_index = i;
break;
}
}
if (0 > assigned_module)
if (0 > m_index)
{
fprintf(stderr, "Error: no 'itap' module found\n!");
return true;
@ -636,7 +632,7 @@ bool CQnetITAP::ReadConfig(const char *cfgFile)
else
{
// make sure itap module is defined
itap_path.append(1, 'a' + assigned_module);
itap_path.append(1, 'a' + m_index);
if (cfg.KeyExists(itap_path))
{
cfg.GetValue(itap_path, estr, type, 1, 16);
@ -648,11 +644,11 @@ bool CQnetITAP::ReadConfig(const char *cfgFile)
}
else
{
fprintf(stderr, "Module '%c' is not defined.\n", 'a'+assigned_module);
fprintf(stderr, "Module '%c' is not defined.\n", 'a'+m_index);
return true;
}
}
RPTR_MOD = 'A' + assigned_module;
RPTR_MOD = 'A' + m_index;
cfg.GetValue(itap_path+"_device", type, ITAP_DEVICE, 7, FILENAME_MAX);
cfg.GetValue(itap_path+"_ap_mode", type, AP_MODE);
@ -688,7 +684,6 @@ bool CQnetITAP::ReadConfig(const char *cfgFile)
RPTR.resize(CALL_SIZE, ' ');
}
cfg.GetValue(std::string("gateway_tomodem")+std::string(1, 'a'+assigned_module), estr, togate, 1, FILENAME_MAX);
cfg.GetValue("log_qso", estr, LOG_QSO);
cfg.GetValue("log_debug", estr, LOG_DEBUG);
return false;
@ -733,8 +728,31 @@ void CQnetITAP::calcPFCS(const unsigned char *packet, unsigned char *pfcs)
return;
}
std::unique_ptr<CQnetITAP> pitap;
static void SignalHandler(int sig)
{
switch (sig)
{
case SIGINT:
case SIGHUP:
case SIGTERM:
if (pitap)
pitap->Stop();
break;
default:
fprintf(stderr, "Caught an unknown signal: %d\n", sig);
break;
}
}
int main(int argc, const char **argv)
{
std::signal(SIGINT, SignalHandler);
std::signal(SIGHUP, SignalHandler);
std::signal(SIGTERM, SignalHandler);
setbuf(stdout, NULL);
if (2 != argc)
{
@ -744,7 +762,7 @@ int main(int argc, const char **argv)
if ('-' == argv[1][0])
{
printf("%s Copyright (C) 2018-2019 by Thomas A. Early N7TAE\n", ITAP_VERSION);
printf("%s Copyright (C) 2018-2024 by Thomas A. Early N7TAE\n", ITAP_VERSION);
printf("QnetITAP comes with ABSOLUTELY NO WARRANTY; see the LICENSE for details.\n");
printf("This is free software, and you are welcome to distribute it\nunder certain conditions that are discussed in the LICENSE file.\n");
return 0;
@ -778,11 +796,27 @@ int main(int argc, const char **argv)
return 1;
}
CQnetITAP qnitap(assigned_module);
pitap = std::unique_ptr<CQnetITAP>(new CQnetITAP(assigned_module));
if (!pitap)
{
fprintf(stderr, "Could not make a CQnetITAP\n");
return EXIT_FAILURE;
}
if (pitap->Initialize(argv[1]))
{
pitap.reset();
return EXIT_FAILURE;
}
qnitap.Run(argv[1]);
pitap->Run();
pitap->Close();
printf("%s is closing.\n", argv[0]);
pitap.reset();
return 0;
}

@ -25,8 +25,8 @@
#include <netinet/in.h>
#include "Random.h" // for streamid generation
#include "UnixPacketSock.h"
#include "KRBase.h"
#include "UnixDgramSocket.h"
#include "Base.h"
#define CALL_SIZE 8
#define IP_SIZE 15
@ -105,20 +105,20 @@ private:
SITAP frame;
};
class CQnetITAP : CKRBase
class CQnetITAP : public CModem
{
public:
// functions
CQnetITAP(int mod);
~CQnetITAP();
void Run(const char *cfgfile);
CQnetITAP(int mod) : CModem(mod) {}
~CQnetITAP() {}
bool Initialize(const std::string &cfgfile);
void Run();
void Close();
// data
private:
int assigned_module;
// functions
bool Initialize(const char *cfgfile);
bool ProcessGateway(const int len, const unsigned char *raw);
bool ProcessITAP(const unsigned char *raw);
int OpenITAP();
@ -128,7 +128,7 @@ private:
void DumpSerialPacket(const char *title, const unsigned char *);
// read configuration file
bool ReadConfig(const char *);
bool ReadConfig(const std::string &path);
// config data
char RPTR_MOD;
@ -143,8 +143,8 @@ private:
CRandom random;
// unix sockets
std::string togate;
CUnixPacketClient ToGate;
CUnixDgramWriter ToGate;
CUnixDgramReader FromGate;
// Queue
std::queue<CFrame> queue;

@ -56,7 +56,7 @@
#define LINK_VERSION "QnetLink-40411"
CQnetLink::CQnetLink()
CQnetLink::CQnetLink() : CBase()
{
}
@ -643,12 +643,12 @@ void CQnetLink::PrintCallsigns(const std::string &key, const std::set<std::strin
}
/* process configuration file */
bool CQnetLink::ReadConfig(const char *cfgFile)
bool CQnetLink::ReadConfig(const std::string &cfgFile)
{
CQnetConfigure cfg;
const std::string estr; // an empty string
printf("Reading file %s\n", cfgFile);
printf("Reading file %s\n", cfgFile.c_str());
if (cfg.Initialize(cfgFile))
return true;
@ -737,8 +737,6 @@ bool CQnetLink::ReadConfig(const char *cfgFile)
saved_max_dongles = max_dongles = (unsigned int)maxdongle;
key.assign("gateway_");
cfg.GetValue(key+"tolink", estr, togate, 1, FILENAME_MAX);
cfg.GetValue("log_qso", estr, qso_details);
cfg.GetValue("log_debug", estr, log_debug);
@ -788,12 +786,13 @@ bool CQnetLink::srv_open()
}
/* create our gateway unix sockets */
printf("Connecting to qngateway at %s\n", togate.c_str());
if (ToGate.Open(togate.c_str(), this))
printf("Opening Gate2Link\n");
if (FromGate.Open("Gate2Link"))
{
srv_close();
return true;
}
ToGate.SetUp("Link2Gate");
/* initialize all remote links */
for (int i = 0; i < 3; i++)
@ -819,7 +818,7 @@ void CQnetLink::srv_close()
XRFSock4.Close();
DCSSock4.Close();
REFSock4.Close();
ToGate.Close();
FromGate.Close();
}
/* find the repeater IP by callsign and link to it */
@ -2715,14 +2714,14 @@ void CQnetLink::ProcessREF(unsigned char *buf, const int length)
}
}
void CQnetLink::Process()
void CQnetLink::Run()
{
tnow = 0;
auto heartbeat = time(NULL);
if (uses_ipv6)
printf("xrf6=%d, dcs6=%d, ref6=%d ", XRFSock6.GetSocket(), DCSSock6.GetSocket(), REFSock6.GetSocket());
printf("xrf4=%d, dcs4=%d, ref4=%d, gateway=%d\n", XRFSock4.GetSocket(), DCSSock4.GetSocket(), REFSock4.GetSocket(), ToGate.GetFD());
printf("xrf4=%d, dcs4=%d, ref4=%d, gateway=%d\n", XRFSock4.GetSocket(), DCSSock4.GetSocket(), REFSock4.GetSocket(), FromGate.GetFD());
// initialize all request links
bool first = true;
@ -2806,7 +2805,7 @@ void CQnetLink::Process()
AddFDSet(max_nfds, DCSSock6.GetSocket(), &fdset);
AddFDSet(max_nfds, REFSock6.GetSocket(), &fdset);
}
AddFDSet(max_nfds, ToGate.GetFD(), &fdset);
AddFDSet(max_nfds, FromGate.GetFD(), &fdset);
tv.tv_sec = 0;
tv.tv_usec = 20000;
auto sval = select(max_nfds + 1, &fdset, 0, 0, &tv);
@ -2868,11 +2867,11 @@ void CQnetLink::Process()
}
}
if (keep_running && FD_ISSET(ToGate.GetFD(), &fdset))
if (keep_running && FD_ISSET(FromGate.GetFD(), &fdset))
{
unsigned char your[3] = { 'C', 'C', 'C' };
SDSVT dsvt;
int length = ToGate.Read(dsvt.title, 56);
int length = FromGate.Read(dsvt.title, 56);
if ((length==56 || length==27) && 0==memcmp(dsvt.title,"DSVT", 4U) && dsvt.id==0x20U && (dsvt.config==0x10U || dsvt.config==0x20U))
{
@ -2880,7 +2879,7 @@ void CQnetLink::Process()
if (length == 56)
{
if (qso_details)
printf("START from local g2: streamID=%04x, flags=%02x:%02x:%02x, my=%.8s/%.4s, ur=%.8s, rpt1=%.8s, rpt2=%.8s, %d bytes on %s\n", ntohs(dsvt.streamid), dsvt.hdr.flag[0], dsvt.hdr.flag[1], dsvt.hdr.flag[2], dsvt.hdr.mycall, dsvt.hdr.sfx, dsvt.hdr.urcall, dsvt.hdr.rpt1, dsvt.hdr.rpt2, length, togate.c_str());
printf("START from local g2: streamID=%04x, flags=%02x:%02x:%02x, my=%.8s/%.4s, ur=%.8s, rpt1=%.8s, rpt2=%.8s, %d bytes on Gate2Link\n", ntohs(dsvt.streamid), dsvt.hdr.flag[0], dsvt.hdr.flag[1], dsvt.hdr.flag[2], dsvt.hdr.mycall, dsvt.hdr.sfx, dsvt.hdr.urcall, dsvt.hdr.rpt1, dsvt.hdr.rpt2, length);
// save mycall
char call[CALL_SIZE + 1];
@ -3412,7 +3411,7 @@ void CQnetLink::Process()
}
}
}
FD_CLR (ToGate.GetFD(), &fdset);
FD_CLR (FromGate.GetFD(), &fdset);
}
for (int i=0; i<3 && keep_running; i++)
{
@ -3666,7 +3665,7 @@ void CQnetLink::AudioNotifyThread(SECHO &edata)
return;
}
bool CQnetLink::Init(const char *cfgfile)
bool CQnetLink::Initialize(const std::string &cfgfile)
{
tzset();
setvbuf(stdout, (char *)NULL, _IOLBF, 0);
@ -3701,7 +3700,7 @@ bool CQnetLink::Init(const char *cfgfile)
/* process configuration file */
if (ReadConfig(cfgfile))
{
printf("Failed to process config file %s\n", cfgfile);
printf("Failed to process config file %s\n", cfgfile.c_str());
return true;
}
// open sqlite
@ -3750,7 +3749,7 @@ bool CQnetLink::Init(const char *cfgfile)
return false;
}
void CQnetLink::Shutdown()
void CQnetLink::Close()
{
char unlink_request[CALL_SIZE + 3];
char cmd_2_dcs[19];
@ -3810,18 +3809,44 @@ void CQnetLink::Shutdown()
return;
}
CQnetLink qnlink;
static void SignalHandler(int sig)
{
switch (sig)
{
case SIGINT:
case SIGHUP:
case SIGTERM:
qnlink.Stop();
break;
default:
fprintf(stderr, "Caught an unknown signal: %d\n", sig);
break;
}
}
int main(int argc, char **argv)
{
std::signal(SIGINT, SignalHandler);
std::signal(SIGHUP, SignalHandler);
std::signal(SIGTERM, SignalHandler);
if (argc != 2)
{
printf("Usage: %s configuration_file\n", argv[0]);
return 1;
return EXIT_FAILURE;
}
CQnetLink qnlink;
if (qnlink.Init(argv[1]))
return 1;
if (qnlink.Initialize(argv[1]))
return EXIT_FAILURE;
printf("QnetLink %s initialized...entering processing loop\n", LINK_VERSION);
qnlink.Process();
qnlink.Run();
printf("QnetLink exiting\n");
qnlink.Shutdown();
qnlink.Close();
return EXIT_SUCCESS;
}

@ -30,12 +30,12 @@
#include "QnetTypeDefs.h"
#include "SEcho.h"
#include "Random.h"
#include "UnixPacketSock.h"
#include "UnixDgramSocket.h"
#include "UDPSocket.h"
#include "UDPSocket.h"
#include "Timer.h"
#include "QnetDB.h"
#include "KRBase.h"
#include "Base.h"
/*** version number must be x.xx ***/
#define CALL_SIZE 8
@ -80,15 +80,15 @@ using STRACING = struct tracing_tag
};
class CQnetLink : CKRBase
class CQnetLink : public CBase
{
public:
// functions
CQnetLink();
~CQnetLink();
bool Init(const char *cfgfile);
void Process();
void Shutdown();
bool Initialize(const std::string &path);
void Run();
void Close();
private:
// functions
void ToUpper(std::string &s);
@ -96,7 +96,7 @@ private:
void PrintCallsigns(const std::string &key, const std::set<std::string> &set);
void LoadGateways(const std::string &filename);
void calcPFCS(unsigned char *packet, int len);
bool ReadConfig(const char *);
bool ReadConfig(const std::string &path);
bool srv_open();
void srv_close();
void g2link(const char from_mod, const char *call, const char to_mod);
@ -163,8 +163,8 @@ private:
CSockAddress fromDst4;
// unix sockets to gateway
std::string togate;
CUnixPacketClient ToGate;
CUnixDgramWriter ToGate;
CUnixDgramReader FromGate;
struct timeval tv;

@ -40,6 +40,7 @@
#include <errno.h>
#include <thread>
#include <chrono>
#include <memory>
#include "QnetModem.h"
#include "QnetConfigure.h"
@ -65,16 +66,6 @@ const unsigned char TYPE_EOT = 0x13U;
const unsigned char TYPE_ACK = 0x70U;
const unsigned char TYPE_NACK = 0x7FU;
CQnetModem::CQnetModem(int mod)
: assigned_module(mod)
, dstarSpace(0U)
{
}
CQnetModem::~CQnetModem()
{
}
bool CQnetModem::VoicePacketIsSync(const unsigned char *text)
{
return *text==0x55U && *(text+1)==0x2DU && *(text+2)==0x16U;
@ -221,14 +212,20 @@ bool CQnetModem::SetFrequency()
return false;
}
bool CQnetModem::Initialize(const char *cfgfile)
bool CQnetModem::Initialize(const std::string &cfgfile)
{
if (ReadConfig(cfgfile))
return true;
printf("Connecting to qngateway at %s\n", togate.c_str());
if (ToGate.Open(togate.c_str(), this))
std::string name("Gate2Modem");
name.append(1, RPTR_MOD);
printf("Opening %s\n", name.c_str());
if (FromGate.Open(name.c_str()))
return true;
name.assign("Modem");
name.append(1, RPTR_MOD);
name.append("2Gate");
ToGate.SetUp(name.c_str());
serfd = OpenModem();
if (serfd < 0)
@ -465,12 +462,9 @@ EModemResponse CQnetModem::GetModemData(unsigned char *buf, unsigned int size)
};
}
void CQnetModem::Run(const char *cfgfile)
void CQnetModem::Run()
{
if (Initialize(cfgfile))
return;
int ug2m = ToGate.GetFD();
int ug2m = FromGate.GetFD();
printf("gate2modem=%d, serial=%d\n", ug2m, serfd);
keep_running = true;
@ -540,7 +534,7 @@ void CQnetModem::Run(const char *cfgfile)
if (keep_running && FD_ISSET(ug2m, &readfds))
{
SDSVT dsvt;
ssize_t len = ToGate.Read(dsvt.title, sizeof(SDSVT));
ssize_t len = FromGate.Read(dsvt.title, sizeof(SDSVT));
if (len <= 0)
{
@ -594,8 +588,12 @@ void CQnetModem::Run(const char *cfgfile)
}
}
}
}
void CQnetModem::Close()
{
close(serfd);
ToGate.Close();
FromGate.Close();
}
int CQnetModem::SendToModem(const unsigned char *buf)
@ -821,17 +819,17 @@ bool CQnetModem::ProcessModem(const SMODEM &frame)
}
// process configuration file and return true if there was a problem
bool CQnetModem::ReadConfig(const char *cfgFile)
bool CQnetModem::ReadConfig(const std::string &cfgFile)
{
CQnetConfigure cfg;
printf("Reading file %s\n", cfgFile);
printf("Reading file %s\n", cfgFile.c_str());
if (cfg.Initialize(cfgFile))
return true;
const std::string estr; // an empty string
std::string type;
std::string modem_path("module_");
if (0 > assigned_module)
if (0 > m_index)
{
// we need to find the lone mmdvmmodem module
for (int i=0; i<3; i++)
@ -844,11 +842,11 @@ bool CQnetModem::ReadConfig(const char *cfgFile)
if (type.compare("mmdvmmodem"))
continue; // this ain't it!
modem_path.assign(test);
assigned_module = i;
m_index = i;
break;
}
}
if (0 > assigned_module)
if (0 > m_index)
{
fprintf(stderr, "Error: no 'mmdvmmodem' module found\n!");
return true;
@ -857,7 +855,7 @@ bool CQnetModem::ReadConfig(const char *cfgFile)
else
{
// make sure mmdvmmodem module is defined
modem_path.append(1, 'a' + assigned_module);
modem_path.append(1, 'a' + m_index);
if (cfg.KeyExists(modem_path))
{
cfg.GetValue(modem_path, estr, type, 1, 16);
@ -869,14 +867,13 @@ bool CQnetModem::ReadConfig(const char *cfgFile)
}
else
{
fprintf(stderr, "Module '%c' is not defined.\n", 'a'+assigned_module);
fprintf(stderr, "Module '%c' is not defined.\n", 'a'+m_index);
return true;
}
}
RPTR_MOD = 'A' + assigned_module;
RPTR_MOD = 'A' + m_index;
cfg.GetValue(modem_path+"_device", type, MODEM_DEVICE, 7, FILENAME_MAX);
cfg.GetValue(std::string("gateway_tomodem")+std::string(1, 'a'+assigned_module), estr, togate, 1, FILENAME_MAX);
if (cfg.GetValue(modem_path+"_tx_frequency", type, TX_FREQUENCY, 1.0, 6000.0))
return true; // we have to have a valid frequency
@ -933,6 +930,25 @@ bool CQnetModem::ReadConfig(const char *cfgFile)
return false;
}
std::unique_ptr<CQnetModem> pmodem;
static void SignalHandler(int sig)
{
switch (sig)
{
case SIGINT:
case SIGHUP:
case SIGTERM:
if (pmodem)
pmodem->Stop();
break;
default:
fprintf(stderr, "Caught an unexpected signal: %d\n", sig);
break;
}
}
int main(int argc, const char **argv)
{
setbuf(stdout, NULL);
@ -944,7 +960,7 @@ int main(int argc, const char **argv)
if ('-' == argv[1][0])
{
printf("%s Copyright (C) 2019 by Thomas A. Early N7TAE\n", MODEM_VERSION);
printf("%s Copyright (C) 2019,2024 by Thomas A. Early N7TAE\n", MODEM_VERSION);
printf("QnetModem comes with ABSOLUTELY NO WARRANTY; see the LICENSE for details.\n");
printf("This is free software, and you are welcome to distribute it\n");
printf("under certain conditions that are discussed in the LICENSE file.\n");
@ -959,31 +975,47 @@ int main(int argc, const char **argv)
}
qn += 7;
int assigned_module;
int mod;
switch (*qn)
{
case 0:
assigned_module = -1;
mod = -1;
break;
case 'a':
assigned_module = 0;
mod = 0;
break;
case 'b':
assigned_module = 1;
mod = 1;
break;
case 'c':
assigned_module = 2;
mod = 2;
break;
default:
fprintf(stderr, "assigned module must be a, b or c\n");
return 1;
}
CQnetModem qnmodem(assigned_module);
pmodem = std::unique_ptr<CQnetModem>(new CQnetModem(mod));
if (!pmodem)
{
fprintf(stderr, "Could not make a CQnetModem!\n");
return EXIT_FAILURE;
}
if (pmodem->Initialize(argv[1]))
{
pmodem.reset();
return EXIT_FAILURE;
}
qnmodem.Run(argv[1]);
pmodem->Run();
pmodem->Close();
pmodem.reset();
printf("%s is closing.\n", argv[0]);
return 0;
return EXIT_SUCCESS;
}

@ -24,10 +24,10 @@
#include <netinet/in.h>
#include "Random.h" // for streamid generation
#include "UnixPacketSock.h"
#include "UnixDgramSocket.h"
#include "QnetTypeDefs.h"
#include "Timer.h"
#include "KRBase.h"
#include "Base.h"
#define CALL_SIZE 8
#define IP_SIZE 15
@ -193,21 +193,21 @@ private:
SMODEM frame;
};
class CQnetModem : CKRBase
class CQnetModem : public CModem
{
public:
// functions
CQnetModem(int mod);
~CQnetModem();
void Run(const char *cfgfile);
CQnetModem(int mod) : CModem(mod), dstarSpace(0) {}
~CQnetModem() {}
bool Initialize(const std::string &cfgfile);
void Run();
void Close();
private:
int assigned_module;
unsigned int dstarSpace;
// functions
bool VoicePacketIsSync(const unsigned char *);
bool Initialize(const char *cfgfile);
void ProcessGateway(const SDSVT &dsvt);
bool ProcessModem(const SMODEM &frame);
int OpenModem();
@ -219,7 +219,7 @@ private:
bool SetConfiguration();
// read configuration file
bool ReadConfig(const char *);
bool ReadConfig(const std::string &path);
// config data
char RPTR_MOD;
@ -238,8 +238,8 @@ private:
CTimer PacketWait;
// unix sockets
std::string togate;
CUnixPacketClient ToGate;
CUnixDgramWriter ToGate;
CUnixDgramReader FromGate;
// Queue
std::queue<CFrame> queue;

@ -22,6 +22,7 @@
#include <cstring>
#include <csignal>
#include <ctime>
#include <memory>
#include <cstdlib>
#include <netdb.h>
#include <sys/time.h>
@ -38,21 +39,24 @@
#define RELAY_VERSION "QnetRelay-20307"
CQnetRelay::CQnetRelay(int mod) :
assigned_module(mod),
seed(time(NULL)),
COUNTER(0)
bool CQnetRelay::Initialize(const std::string &cfgfile)
{
}
if (ReadConfig(cfgfile))
return true;
CQnetRelay::~CQnetRelay()
{
}
msock = OpenSocket(MMDVM_INTERNAL_IP, MMDVM_OUT_PORT);
if (msock < 0)
return true;
bool CQnetRelay::Initialize(const char *cfgfile)
{
if (ReadConfig(cfgfile))
std::string name("Gate2Modem");
name.append(1, RPTR_MOD);
printf("Opening %s\n", name.c_str());
if (FromGate.Open(name.c_str()))
return true;
name.assign("Modem");
name.append(1, RPTR_MOD);
name.append("2Gate");
ToGate.SetUp(name.c_str());
return false;
}
@ -107,19 +111,9 @@ int CQnetRelay::OpenSocket(const std::string &address, unsigned short port)
return fd;
}
bool CQnetRelay::Run(const char *cfgfile)
void CQnetRelay::Run()
{
if (Initialize(cfgfile))
return true;
msock = OpenSocket(MMDVM_INTERNAL_IP, MMDVM_OUT_PORT);
if (msock < 0)
return true;
if (ToGate.Open(togate.c_str(), this))
return true;
int fd = ToGate.GetFD();
int fd = FromGate.GetFD();
printf("msock=%d, gateway=%d\n", msock, fd);
@ -168,7 +162,7 @@ bool CQnetRelay::Run(const char *cfgfile)
if (FD_ISSET(fd, &readfds))
{
len = ToGate.Read(buf, 100);
len = FromGate.Read(buf, 100);
if (len < 0)
{
@ -204,10 +198,12 @@ bool CQnetRelay::Run(const char *cfgfile)
fprintf(stderr, "DEBUG: Run: received unknow packet '%s' len=%d\n", title, (int)len);
}
}
}
void CQnetRelay::Close()
{
::close(msock);
ToGate.Close();
return false;
FromGate.Close();
}
int CQnetRelay::SendTo(const int fd, const unsigned char *buf, const int size, const std::string &address, const unsigned short port)
@ -371,10 +367,10 @@ bool CQnetRelay::ProcessMMDVM(const int len, const unsigned char *raw)
}
// process configuration file and return true if there was a problem
bool CQnetRelay::ReadConfig(const char *cfgFile)
bool CQnetRelay::ReadConfig(const std::string &cfgFile)
{
CQnetConfigure cfg;
printf("Reading file %s\n", cfgFile);
printf("Reading file %s\n", cfgFile.c_str());
if (cfg.Initialize(cfgFile))
return true;
@ -382,7 +378,7 @@ bool CQnetRelay::ReadConfig(const char *cfgFile)
std::string mmdvm_path("module_");
std::string type;
if (0 > assigned_module)
if (0 > m_index)
{
// we need to find the lone mmdvmhost module
for (int i=0; i<3; i++)
@ -395,11 +391,11 @@ bool CQnetRelay::ReadConfig(const char *cfgFile)
if (type.compare("mmdvmhost"))
continue; // this ain't it!
mmdvm_path.assign(test);
assigned_module = i;
m_index = i;
break;
}
}
if (0 > assigned_module)
if (0 > m_index)
{
fprintf(stderr, "Error: no 'mmdvmhost' module found\n!");
return true;
@ -408,7 +404,7 @@ bool CQnetRelay::ReadConfig(const char *cfgFile)
else
{
// make sure mmdvmhost module is defined
mmdvm_path.append(1, 'a' + assigned_module);
mmdvm_path.append(1, 'a' + m_index);
if (cfg.KeyExists(mmdvm_path))
{
cfg.GetValue(mmdvm_path, estr, type, 1, 16);
@ -420,13 +416,12 @@ bool CQnetRelay::ReadConfig(const char *cfgFile)
}
else
{
fprintf(stderr, "Module '%c' is not defined.\n", 'a'+assigned_module);
fprintf(stderr, "Module '%c' is not defined.\n", 'a'+m_index);
return true;
}
}
RPTR_MOD = 'A' + assigned_module;
RPTR_MOD = 'A' + m_index;
cfg.GetValue("gateway_tomodem"+std::string(1, 'a'+assigned_module), estr, togate, 1, FILENAME_MAX);
cfg.GetValue(mmdvm_path+"_internal_ip", type, MMDVM_INTERNAL_IP, 7, IP_SIZE);
cfg.GetValue(mmdvm_path+"_target_ip", type, MMDVM_TARGET_IP, 7, IP_SIZE);
@ -442,6 +437,25 @@ bool CQnetRelay::ReadConfig(const char *cfgFile)
return false;
}
std::unique_ptr<CQnetRelay> prelay;
static void SignalHandler(int sig)
{
switch (sig)
{
case SIGINT:
case SIGHUP:
case SIGTERM:
if (prelay)
prelay->Stop();
break;
default:
fprintf(stderr, "Caught an unexpected signal: %d\n", sig);
break;
}
}
int main(int argc, const char **argv)
{
setbuf(stdout, NULL);
@ -453,7 +467,7 @@ int main(int argc, const char **argv)
if ('-' == argv[1][0])
{
printf("%s Copyright (C) 2018-2021 by Thomas A. Early N7TAE\n", RELAY_VERSION);
printf("%s Copyright (C) 2018-2024 by Thomas A. Early N7TAE\n", RELAY_VERSION);
printf("QnetRelay comes with ABSOLUTELY NO WARRANTY; see the LICENSE for details.\n");
printf("This is free software, and you are welcome to distribute it\nunder certain conditions that are discussed in the LICENSE file.\n");
return 0;
@ -486,11 +500,25 @@ int main(int argc, const char **argv)
return 1;
}
CQnetRelay qnmmdvm(module);
prelay = std::unique_ptr<CQnetRelay>(new CQnetRelay(module));
if (!prelay)
{
fprintf(stderr, "Could not make a CQnetRelay!\n");
return EXIT_FAILURE;
}
if (prelay->Initialize(argv[1]))
{
prelay.reset();
return EXIT_FAILURE;
}
prelay->Run();
bool trouble = qnmmdvm.Run(argv[1]);
prelay->Close();
printf("%s is closing.\n", argv[0]);
return trouble ? 1 : 0;
return EXIT_SUCCESS;
}

@ -22,35 +22,35 @@
#include <string>
#include <netinet/in.h>
#include "UnixPacketSock.h"
#include "KRBase.h"
#include "UnixDgramSocket.h"
#include "Base.h"
#define CALL_SIZE 8
#define IP_SIZE 15
class CQnetRelay : CKRBase
class CQnetRelay : public CModem
{
public:
// functions
CQnetRelay(int mod);
~CQnetRelay();
bool Run(const char *cfgfile);
CQnetRelay(int mod) : CModem(mod), seed(time(NULL)), COUNTER(0) {}
~CQnetRelay() {}
bool Initialize(const std::string &cfgfile);
void Run();
void Close();
private:
// functions
bool Initialize(const char *cfgfile);
bool ProcessGateway(const int len, const unsigned char *raw);
bool ProcessMMDVM(const int len, const unsigned char *raw);
int OpenSocket(const std::string &address, unsigned short port);
int SendTo(const int fd, const unsigned char *buf, const int size, const std::string &address, const unsigned short port);
// read configuration file
bool ReadConfig(const char *);
bool ReadConfig(const std::string &);
// Unix sockets
int assigned_module;
std::string togate;
CUnixPacketClient ToGate;
CUnixDgramWriter ToGate;
CUnixDgramReader FromGate;
// config data
char RPTR_MOD;

@ -1,207 +0,0 @@
/*
* Copyright (C) 2020 by Thomas 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
* 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 <iostream>
#include <string>
#include <thread>
#include <chrono>
#include <unistd.h>
#include <sys/un.h>
#include <sys/socket.h>
#include "UnixPacketSock.h"
CUnixPacket::CUnixPacket() : m_fd(-1), m_host(NULL) {}
ssize_t CUnixPacket::Read(void *buffer, const ssize_t size)
{
if (0 > m_fd)
return -1;
ssize_t len = read(m_fd, buffer, size);
if (len < 1)
{
if (-1 == len)
{
std::cerr << "Read error on '" << m_name << "': " << strerror(errno) << std::endl;
}
else if (0 == len)
{
std::cerr << "Read error on '" << m_name << "': EOF" << std::endl;
}
if (Restart())
return -1;
else
return 0;
}
return len;
}
bool CUnixPacket::Write(const void *buffer, const ssize_t size)
{
if (0 > m_fd)
return true;
ssize_t written = write(m_fd, buffer, size);
if (written != size)
{
if (-1 == written)
{
std::cerr << "Write error on '" << m_name << "': " << strerror(errno) << std::endl;
}
else
{
std::cout << "Write error on '" << m_name << "': Only wrote " << written << " of " << size << " bytes" << std::endl;
}
return Restart();
}
return false;
}
bool CUnixPacket::Restart()
{
if (! m_host->IsRunning())
return true;
std::cout << "Restarting '" << m_name << "'... " << std::endl;
Close();
std::string name(m_name);
return Open(name.c_str(), m_host);
}
int CUnixPacket::GetFD()
{
return m_fd;
}
CUnixPacketServer::CUnixPacketServer() : m_server(-1) {}
CUnixPacketServer::~CUnixPacketServer()
{
Close();
}
bool CUnixPacketServer::Open(const char *name, CKRBase *host)
{
m_server = socket(AF_UNIX, SOCK_SEQPACKET, 0);
m_host = host;
if (m_server < 0)
{
std::cerr << "Cannot open '" << name << "' socket: " << strerror(errno) << std::endl;
return true;
}
struct sockaddr_un addr;
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
memcpy(addr.sun_path+1, name, strlen(name));
if (-1 == bind(m_server, (struct sockaddr *)&addr, sizeof(addr)))
{
std::cerr << "Cannot bind '" << name << "' socket: " << strerror(errno) << std::endl;
Close();
return true;
}
if (-1 == listen(m_server, 1))
{
std::cerr << "Cannot listen on '" << name << "' socket: " << strerror(errno) << std::endl;
Close();
return true;
}
m_fd = accept(m_server, nullptr, 0);
if (m_fd < 0)
{
std::cerr << "Cannot accept on '" << name << "' socket: " << strerror(errno) << std::endl;
Close();
return true;
}
strncpy(m_name, name, 108);
return false;
}
void CUnixPacketServer::Close()
{
if (m_server >= 0)
{
close(m_server);
m_server = -1;
}
if (m_fd >= 0)
{
close(m_fd);
m_fd = -1;
}
}
CUnixPacketClient::~CUnixPacketClient()
{
Close();
}
bool CUnixPacketClient::Open(const char *name, CKRBase *host)
{
m_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
if (m_fd < 0)
{
std::cerr << "Cannot open unix client socket " << name << std::endl;
return true;
}
struct sockaddr_un addr;
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
memcpy(addr.sun_path+1, name, strlen(name));
int rval = -1;
int tries = 0;
while (rval < 0)
{
rval = connect(m_fd, (struct sockaddr *)&addr, sizeof(addr));
if (rval < 0)
{
if (ECONNREFUSED == errno)
{
if (0 == tries++ % 20)
std::cout << "Waiting for " << name << " server to start..." << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(250));
}
else
{
std::cerr << "Cannot connect '" << name << "' socket: " << strerror(errno) << std::endl;
Close();
return true;
}
}
if (! m_host->IsRunning())
{
Close();
return true;
}
}
m_host = host;
strncpy(m_name, name, 108);
return false;
}
void CUnixPacketClient::Close()
{
if (m_fd >= 0)
{
close(m_fd);
m_fd = -1;
}
}

@ -1,58 +0,0 @@
#pragma once
/*
* Copyright (C) 2020 by Thomas 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
* 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 <sys/types.h>
#include "KRBase.h"
class CUnixPacket
{
public:
CUnixPacket();
virtual bool Open(const char *name, CKRBase *host) = 0;
virtual void Close() = 0;
bool Write(const void *buffer, const ssize_t size);
ssize_t Read(void *buffer, const ssize_t size);
int GetFD();
protected:
bool Restart();
int m_fd;
CKRBase *m_host;
char m_name[108];
};
class CUnixPacketServer : public CUnixPacket
{
public:
CUnixPacketServer();
~CUnixPacketServer();
bool Open(const char *name, CKRBase *host);
void Close();
protected:
int m_server;
};
class CUnixPacketClient : public CUnixPacket
{
public:
~CUnixPacketClient();
bool Open(const char *name, CKRBase *host);
void Close();
};

@ -53,11 +53,6 @@ gateway_ip_d='ANY_PORT' # the g2 port
gateway_port_d=40000 # don't change
gateway_ipv6_ip_d='ANY_PORT'
gateway_ipv6_port_d=9011 # IANA-approved DStar rouing port
gateway_tolink_d='tolink' # Unix SOCK_SEQPACKET to qnlink
gateway_tomodema_d='tomodema' # Unix SOCK_SEQPACKET to modem on module A
gateway_tomodemb_d='tomodemb' # Unix SOCK_SEQPACKET to modem on module B
gateway_tomodemc_d='tomodemc' # Unix SOCK_SEQPACKET to modem on module C
gateway_fromremote_d='fromremote' # Unix SOCK_DRAM from remote to gateway
gateway_latitude_d=0 # you can leave this unspecified for a mobile rig
gateway_longitude_d=0 # like the latitude
gateway_desc1_d='' # maximum of 20 characters, most special symbols are not allowed

Loading…
Cancel
Save

Powered by TurnKey Linux.