#21 make it a real daemon

pull/32/head
Geoffrey Merck 4 years ago
parent 88f51f75b3
commit 75abc130c1

@ -25,6 +25,8 @@
#include <vector>
#include <signal.h>
#include <exception>
#include <cassert>
#include <unistd.h>
#ifdef DEBUG_DSTARGW
#include <boost/stacktrace.hpp>
#endif
@ -45,6 +47,7 @@
#include "LogConsoleTarget.h"
#include "APRSGPSDIdFrameProvider.h"
#include "APRSFixedIdFrameProvider.h"
#include "Daemon.h"
CDStarGatewayApp * CDStarGatewayApp::g_app = nullptr;
@ -70,16 +73,52 @@ int main(int argc, char *argv[])
return 1;
}
printf("\n%s Copyright (C) %s\n", FULL_PRODUCT_NAME.c_str(), VENDOR_NAME.c_str());
printf("DStarGateway 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\n");
if ('-' == argv[1][0]) {
printf("\n%s Copyright (C) %s\n", FULL_PRODUCT_NAME.c_str(), VENDOR_NAME.c_str());
printf("DStarGateway 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\n");
return 0;
}
std::string cfgFile(argv[1]);
CDStarGatewayConfig * config = new CDStarGatewayConfig(std::string((argv[1])));
if(!config->load()) {
CLog::logFatal("Invalid configuration, aborting");
return false;
}
TDaemon daemon;
config->getGeneral(daemon);
if (daemon.daemon) {
CLog::logInfo("Configured as a daemon, detaching ...");
auto res = CDaemon::daemonize(daemon.pidFile);
switch (res)
{
case DR_PARENT:
return 0;
case DR_CHILD:
break;
case DR_PIDFILE_FAILED:
break;
case DR_FAILURE:
[[fallthrough]];
default:
CLog::logFatal("Fork failed, exiting");
delete config;
return 1;
}
}
// Setup Log
TLog logConf;
config->getLog(logConf);
CLog::finalise();
if(logConf.m_displayLevel != LOG_NONE && !daemon.daemon) CLog::addTarget(new CLogConsoleTarget(logConf.m_displayLevel));
if(logConf.m_fileLevel != LOG_NONE) CLog::addTarget(new CLogFileTarget(logConf.m_fileLevel, logConf.logDir, logConf.m_fileRotate));
CDStarGatewayApp gateway(cfgFile);
CDStarGatewayApp gateway(config);
if (!gateway.init()) {
return 1;
@ -87,22 +126,30 @@ int main(int argc, char *argv[])
gateway.run();
if(daemon.daemon) {
CDaemon::finalize();
}
return 0;
}
CDStarGatewayApp::CDStarGatewayApp(const std::string &configFile) : m_configFile(configFile), m_thread(NULL)
CDStarGatewayApp::CDStarGatewayApp(CDStarGatewayConfig * config) :
m_config(config),
m_thread(NULL)
{
assert(config != nullptr);
g_app = this;
}
CDStarGatewayApp::~CDStarGatewayApp()
{
delete m_config;
delete m_thread;
}
bool CDStarGatewayApp::init()
{
return createThread();
//2021-12-31 F4FXL This is ugly, if we failed to create the thread we do not clean up ... :(
}
void CDStarGatewayApp::run()
@ -115,30 +162,18 @@ void CDStarGatewayApp::run()
bool CDStarGatewayApp::createThread()
{
printf("\n%s Copyright (C) %s\n", FULL_PRODUCT_NAME.c_str(), VENDOR_NAME.c_str());
printf("DStarGateway 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\n");
CDStarGatewayConfig config(m_configFile);
if(!config.load()) {
CLog::logFatal("Invalid configuration, aborting");
return false;
}
// Setup Log
// Log
TLog log;
config.getLog(log);
CLog::finalise();
if(log.m_displayLevel != LOG_NONE) CLog::addTarget(new CLogConsoleTarget(log.m_displayLevel));
if(log.m_fileLevel != LOG_NONE) CLog::addTarget(new CLogFileTarget(log.m_fileLevel, log.logDir, log.m_fileRotate));
m_config->getLog(log);
// Paths
Tpaths paths;
config.getPaths(paths);
m_config->getPaths(paths);
m_thread = new CDStarGatewayThread(log.logDir, paths.dataDir, "");
// Setup the gateway
TGateway gatewayConfig;
config.getGateway(gatewayConfig);
m_config->getGateway(gatewayConfig);
m_thread->setGateway(gatewayConfig.type, gatewayConfig.callsign, gatewayConfig.address);
m_thread->setLanguage(gatewayConfig.language);
m_thread->setLocation(gatewayConfig.latitude, gatewayConfig.longitude);
@ -146,12 +181,12 @@ bool CDStarGatewayApp::createThread()
#ifdef USE_GPSD
// Setup GPSD
TGPSD gpsdConfig;
config.getGPSD(gpsdConfig);
m_config->getGPSD(gpsdConfig);
#endif
// Setup APRS
TAPRS aprsConfig;
config.getAPRS(aprsConfig);
m_config->getAPRS(aprsConfig);
CAPRSHandler * aprsWriter = NULL;
if(aprsConfig.enabled && !aprsConfig.password.empty()) {
aprsWriter = new CAPRSHandler(aprsConfig.hostname, aprsConfig.port, gatewayConfig.callsign, aprsConfig.password, gatewayConfig.address);
@ -176,9 +211,9 @@ bool CDStarGatewayApp::createThread()
bool ddEnabled = false;
bool atLeastOneRepeater = false;
CRepeaterProtocolHandlerFactory repeaterProtocolFactory;
for(unsigned int i = 0U; i < config.getRepeaterCount(); i++) {
for(unsigned int i = 0U; i < m_config->getRepeaterCount(); i++) {
TRepeater rptrConfig;
config.getRepeater(i, rptrConfig);
m_config->getRepeater(i, rptrConfig);
auto repeaterProtocolHandler = repeaterProtocolFactory.getRepeaterProtocolHandler(rptrConfig.hwType, gatewayConfig, rptrConfig.address, rptrConfig.port);
if(repeaterProtocolHandler == nullptr)
continue;
@ -221,9 +256,9 @@ bool CDStarGatewayApp::createThread()
// Setup ircddb
auto ircddbVersionInfo = "linux_" + PRODUCT_NAME + "-" + VERSION;
std::vector<CIRCDDB *> clients;
for(unsigned int i=0; i < config.getIrcDDBCount(); i++) {
for(unsigned int i=0; i < m_config->getIrcDDBCount(); i++) {
TircDDB ircDDBConfig;
config.getIrcDDB(i, ircDDBConfig);
m_config->getIrcDDB(i, ircDDBConfig);
CLog::logInfo("ircDDB Network %d set to %s user: %s, Quadnet %d", i + 1,ircDDBConfig.hostname.c_str(), ircDDBConfig.username.c_str(), ircDDBConfig.isQuadNet);
CIRCDDB * ircDDB = new CIRCDDBClient(ircDDBConfig.hostname, 9007U, ircDDBConfig.username, ircDDBConfig.password, ircddbVersionInfo, gatewayConfig.address, ircDDBConfig.isQuadNet);
clients.push_back(ircDDB);
@ -240,31 +275,31 @@ bool CDStarGatewayApp::createThread()
// Setup Dextra
TDextra dextraConfig;
config.getDExtra(dextraConfig);
m_config->getDExtra(dextraConfig);
CLog::logInfo("DExtra enabled: %d, max. dongles: %u", int(dextraConfig.enabled), dextraConfig.maxDongles);
m_thread->setDExtra(dextraConfig.enabled, dextraConfig.maxDongles);
// Setup DCS
TDCS dcsConfig;
config.getDCS(dcsConfig);
m_config->getDCS(dcsConfig);
CLog::logInfo("DCS enabled: %d", int(dcsConfig.enabled));
m_thread->setDCS(dcsConfig.enabled);
// Setup DPlus
TDplus dplusConfig;
config.getDPlus(dplusConfig);
m_config->getDPlus(dplusConfig);
CLog::logInfo("D-Plus enabled: %d, max. dongles: %u, login: %s", int(dplusConfig.enabled), dplusConfig.maxDongles, dplusConfig.login.c_str());
m_thread->setDPlus(dplusConfig.enabled, dplusConfig.maxDongles, dplusConfig.login);
// Setup XLX
TXLX xlxConfig;
config.getXLX(xlxConfig);
m_config->getXLX(xlxConfig);
CLog::logInfo("XLX enabled: %d, Hosts file url: %s", int(xlxConfig.enabled), xlxConfig.url.c_str());
m_thread->setXLX(xlxConfig.enabled, xlxConfig.enabled ? CXLXHostsFileDownloader::download(xlxConfig.url) : "");
// Setup Remote
TRemote remoteConfig;
config.getRemote(remoteConfig);
m_config->getRemote(remoteConfig);
CLog::logInfo("Remote enabled: %d, port %u", int(remoteConfig.enabled), remoteConfig.port);
m_thread->setRemote(remoteConfig.enabled, remoteConfig.password, remoteConfig.port);
@ -287,6 +322,8 @@ void CDStarGatewayApp::sigHandler(int sig)
if(g_app != nullptr && g_app->m_thread != nullptr) {
g_app->m_thread->kill();
}
CDaemon::finalize();
}
void CDStarGatewayApp::sigHandlerFatal(int sig)

@ -20,18 +20,18 @@
#pragma once
#include "DStarGatewayThread.h"
#include "DStarGatewayConfig.h"
class CDStarGatewayApp
{
private:
std::string m_configFile;
CDStarGatewayThread *m_thread;
CDStarGatewayConfig * m_config;
CDStarGatewayThread * m_thread;
bool createThread();
static CDStarGatewayApp * g_app;
public:
CDStarGatewayApp(const std::string &configFile);
CDStarGatewayApp(CDStarGatewayConfig * config);
~CDStarGatewayApp();
bool init();

@ -55,6 +55,7 @@ bool CDStarGatewayConfig::load()
#ifdef USE_GPSD
ret = loadGPSD(cfg) && ret;
#endif
ret = loadDaemon(cfg) && ret;
}
if(ret) {
@ -69,6 +70,13 @@ bool CDStarGatewayConfig::load()
return ret;
}
bool CDStarGatewayConfig::loadDaemon(const CConfig & cfg)
{
bool ret = cfg.getValue("daemon", "daemon", m_general.daemon, false);
ret = cfg.getValue("daemon", "pidfile", m_general.pidFile, 0, 1024, "") && ret;
return ret;
}
bool CDStarGatewayConfig::loadXLX(const CConfig & cfg)
{
bool ret = cfg.getValue("xlx", "enabled", m_xlx.enabled, true);
@ -438,3 +446,8 @@ void CDStarGatewayConfig::getGPSD(TGPSD & gpsd) const
gpsd = m_gpsd;
}
#endif
void CDStarGatewayConfig::getGeneral(TDaemon & gen) const
{
gen = m_general;
}

@ -25,6 +25,11 @@
#include "Config.h"
#include "LogSeverity.h"
typedef struct {
bool daemon;
std::string pidFile;
} TDaemon;
typedef struct {
GATEWAY_TYPE type;
std::string callsign;
@ -150,6 +155,7 @@ public:
#ifdef USE_GPSD
void getGPSD(TGPSD & gpsd) const;
#endif
void getGeneral(TDaemon & gen) const;
private:
bool open(CConfig & cfg);
@ -167,6 +173,7 @@ private:
#ifdef USE_GPSD
bool loadGPSD(const CConfig & cfg);
#endif
bool loadDaemon(const CConfig & cfg);
std::string m_fileName;
TGateway m_gateway;
@ -181,6 +188,8 @@ private:
#ifdef USE_GPSD
TGPSD m_gpsd;
#endif
TDaemon m_general;
std::vector<TRepeater *> m_repeaters;
std::vector<TircDDB *> m_ircDDB;
};

@ -21,6 +21,7 @@ install: dstargateway
@cp -fn example.cfg $(CFG_DIR)/dstargateway.cfg
@sed -i "s|path=/var/log/dstargateway/|path=$(LOG_DIR)|g" $(CFG_DIR)/dstargateway.cfg
@sed -i "s|data=/usr/local/share/dstargateway.d/|data=$(DATA_DIR)|g" $(CFG_DIR)/dstargateway.cfg
@sed -i "s|daemon=false|daemon=true|g" $(CFG_DIR)/dstargateway.cfg
../APRS/APRS.a:
../Common/Common.a:

@ -2,7 +2,6 @@
# The order of the sections or key/values pairs inside the sections does not matter nor does casing.
# Boolean values can be set using true, false, 1 or 0
# Floating point values must use . (point) as decimal separator
[Gateway]
type= # repeater, hotspot, dongle. Defaults to repeater
callsign=
@ -22,7 +21,7 @@ language= # valid values: english_uk, deutsch, dansk, francais, ita
[ircddb_1]
enabled=true
hostname=ircv4.openquad.net
username= # The ircDDB username default to the value defined for gateway callsign.
username= # The ircDDB username defaults to the value defined for gateway callsign.
password=
[ircddb_2]
@ -178,3 +177,7 @@ enabled=false
port=4242
password=CHANGE_ME # If password is left blank, remote will be disabled regardless of the enabled field
[Daemon]
daemon=false
# pid file is in our case useless when running as a daemon using systemd as systemd handles all the pid stuff for us
pidfile=#/var/run/dstargateway/dstargateway.pid
Loading…
Cancel
Save

Powered by TurnKey Linux.