You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1253 lines
34 KiB
1253 lines
34 KiB
/*
|
|
* Copyright (C) 2010-2015,2018 by Jonathan Naylor G4KLX
|
|
* Copyright (c) 2021 by Geoffrey F4FXL / KC3FRA
|
|
*
|
|
* 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 <arpa/inet.h>
|
|
#include <chrono>
|
|
#include <iostream>
|
|
#include <fstream>
|
|
|
|
#include "DStarGatewayThread.h"
|
|
#include "DStarGatewayDefs.h"
|
|
#include "RepeaterHandler.h"
|
|
#ifdef USE_STARNET
|
|
#include "StarNetHandler.h"
|
|
#endif
|
|
#ifdef USE_CALLSIGN_SERVER
|
|
#include "CallsignServer.h"
|
|
#endif
|
|
#include "DExtraHandler.h"
|
|
#include "DPlusHandler.h"
|
|
#include "HeaderLogger.h"
|
|
#include "ConnectData.h"
|
|
#ifdef USE_CCS
|
|
#include "CCSHandler.h"
|
|
#endif
|
|
#include "HeaderData.h"
|
|
#include "StatusData.h"
|
|
#include "DCSHandler.h"
|
|
#include "DDHandler.h"
|
|
#include "G2Handler.h"
|
|
#include "HeardData.h"
|
|
#include "PollData.h"
|
|
#include "AMBEData.h"
|
|
#include "HostFile.h"
|
|
#include "CCSData.h"
|
|
#include "DDData.h"
|
|
#include "Utils.h"
|
|
#include "Defs.h"
|
|
#include "Log.h"
|
|
#include "StringUtils.h"
|
|
#include "HostsFilesManager.h"
|
|
#include "HostsFileDownloader.h"
|
|
|
|
const std::string LOOPBACK_ADDRESS("127.0.0.1");
|
|
|
|
const unsigned int REMOTE_DUMMY_PORT = 65016U;
|
|
|
|
CDStarGatewayThread::CDStarGatewayThread(const std::string& logDir, const std::string& dataDir, const std::string& name) :
|
|
CThread("Gateway"),
|
|
m_logDir(logDir),
|
|
m_dataDir(dataDir),
|
|
m_name(name),
|
|
m_killed(false),
|
|
m_stopped(true),
|
|
m_gatewayType(GT_REPEATER),
|
|
m_gatewayCallsign(),
|
|
m_gatewayAddress(),
|
|
m_icomRepeaterHandler(nullptr),
|
|
m_hbRepeaterHandler(nullptr),
|
|
m_dummyRepeaterHandler(nullptr),
|
|
m_dextraPool(nullptr),
|
|
m_dplusPool(nullptr),
|
|
m_dcsPool(nullptr),
|
|
m_g2HandlerPool(nullptr),
|
|
m_outgoingAprsHandler(nullptr),
|
|
m_incomingAprsHandler(nullptr),
|
|
m_irc(nullptr),
|
|
m_cache(),
|
|
m_language(TL_ENGLISH_UK),
|
|
m_dextraEnabled(true),
|
|
m_dextraMaxDongles(0U),
|
|
m_dplusEnabled(false),
|
|
m_dplusMaxDongles(0U),
|
|
m_dplusLogin(),
|
|
m_dcsEnabled(true),
|
|
m_xlxEnabled(true),
|
|
m_ccsEnabled(true),
|
|
m_ccsHost(),
|
|
m_infoEnabled(true),
|
|
m_echoEnabled(true),
|
|
m_dtmfEnabled(true),
|
|
m_logEnabled(false),
|
|
m_logIRCDDB(false),
|
|
m_ddModeEnabled(false),
|
|
m_lastStatus(IS_DISABLED),
|
|
m_statusTimer1(1000U, 1U), // 1 second
|
|
m_statusTimer2(1000U, 1U), // 1 second
|
|
m_remoteEnabled(false),
|
|
m_remotePassword(),
|
|
m_remotePort(0U),
|
|
m_remote(NULL),
|
|
m_statusFileTimer(1000U, 2U * 60U), // 2 minutes
|
|
m_status1(),
|
|
m_status2(),
|
|
m_status3(),
|
|
m_status4(),
|
|
m_status5(),
|
|
m_latitude(0.0),
|
|
m_longitude(0.0),
|
|
m_whiteList(nullptr),
|
|
m_blackList(nullptr),
|
|
m_restrictList(nullptr)
|
|
{
|
|
CHeaderData::initialise();
|
|
CG2Handler::initialise(MAX_ROUTES);
|
|
CDExtraHandler::initialise(MAX_DEXTRA_LINKS);
|
|
CDPlusHandler::initialise(MAX_DPLUS_LINKS);
|
|
CDCSHandler::initialise(MAX_DCS_LINKS);
|
|
CRepeaterHandler::initialise(MAX_REPEATERS);
|
|
#ifdef USE_STARNET
|
|
CStarNetHandler::initialise(MAX_STARNETS, m_name);
|
|
#endif
|
|
#ifdef USE_CCS
|
|
CCCSHandler::initialise(MAX_REPEATERS);
|
|
#endif
|
|
CAudioUnit::initialise();
|
|
}
|
|
|
|
CDStarGatewayThread::~CDStarGatewayThread()
|
|
{
|
|
|
|
}
|
|
|
|
void* CDStarGatewayThread::Entry()
|
|
{
|
|
CHostsFilesManager::setCache(&m_cache);
|
|
CHostsFilesManager::setDownloadCallback(CHostsFileDownloader::download);
|
|
CHostsFilesManager::UpdateHosts();
|
|
|
|
// Truncate the old Links.log file
|
|
std::string fullName = m_logDir + "/" + LINKS_BASE_NAME + ".log";
|
|
if (!m_name.empty()) {
|
|
fullName += fullName + m_name;
|
|
}
|
|
CUtils::truncateFile(fullName);
|
|
CLog::logInfo("Truncating %s", fullName.c_str());
|
|
|
|
#ifdef USE_STARNET
|
|
// Truncate the old StarNet.log file
|
|
std::string fullName = m_logDir + "/" + STARNET_BASE_NAME + ".log";
|
|
if (!m_name.empty()) {
|
|
fullName += fullName + m_name;
|
|
}
|
|
CUtils::truncateFile(fullName);
|
|
CLog::logInfo("Truncating %s", fullName.c_str());
|
|
#endif
|
|
|
|
std::string dextraAddress = m_dextraEnabled ? m_gatewayAddress : LOOPBACK_ADDRESS;
|
|
m_dextraPool = new CDExtraProtocolHandlerPool(DEXTRA_PORT, dextraAddress);
|
|
// Allocate the incoming port
|
|
CDExtraProtocolHandler* dextraHandler = m_dextraPool->getIncomingHandler();
|
|
if(dextraHandler != NULL) {
|
|
CDExtraHandler::setDExtraProtocolIncoming(dextraHandler);
|
|
CDExtraHandler::setDExtraProtocolHandlerPool(m_dextraPool);
|
|
}
|
|
else {
|
|
CLog::logError("Failed to allocate incoming DExtra handler\n");
|
|
}
|
|
|
|
std::string dplusAddress = m_dplusEnabled ? m_gatewayAddress : LOOPBACK_ADDRESS;
|
|
m_dplusPool = new CDPlusProtocolHandlerPool(DPLUS_PORT, dplusAddress);
|
|
CDPlusProtocolHandler* dplusHandler = m_dplusPool->getIncomingHandler();
|
|
if(dplusHandler != NULL) {
|
|
CDPlusHandler::setDPlusProtocolIncoming(dplusHandler);
|
|
CDPlusHandler::setDPlusProtocolHandlerPool(m_dplusPool);
|
|
} else {
|
|
CLog::logError("Failed to allocate incoming DPlus handler\n");
|
|
}
|
|
|
|
std::string dcsAddress = m_dcsEnabled ? m_gatewayAddress : LOOPBACK_ADDRESS;
|
|
m_dcsPool = new CDCSProtocolHandlerPool(DCS_PORT, dcsAddress);
|
|
CDCSProtocolHandler* dcsHandler = m_dcsPool->getIncomingHandler();
|
|
if(dcsHandler != NULL) {
|
|
CDCSHandler::setDCSProtocolIncoming(dcsHandler);
|
|
CDCSHandler::setDCSProtocolHandlerPool(m_dcsPool);
|
|
} else {
|
|
CLog::logError("Failed to allocate incoming DCS handler\n");
|
|
}
|
|
|
|
m_g2HandlerPool = new CG2ProtocolHandlerPool(G2_DV_PORT, m_gatewayAddress);
|
|
bool ret = m_g2HandlerPool->open();
|
|
if (!ret) {
|
|
CLog::logError("Could not open the G2 protocol handler");
|
|
delete m_g2HandlerPool;
|
|
m_g2HandlerPool = NULL;
|
|
}
|
|
|
|
// Wait here until we have the essentials to run
|
|
while (!m_killed && (m_dextraPool == NULL || m_dplusPool == NULL || m_dcsPool == NULL || m_g2HandlerPool == NULL || (m_icomRepeaterHandler == NULL && m_hbRepeaterHandler == NULL && m_dummyRepeaterHandler == NULL) || m_gatewayCallsign.empty()))
|
|
::std::this_thread::sleep_for(std::chrono::milliseconds(500UL)); // 1/2 sec
|
|
|
|
if (m_killed)
|
|
return NULL;
|
|
|
|
m_stopped = false;
|
|
|
|
CLog::logInfo("Starting the ircDDB Gateway thread");
|
|
|
|
CHeaderLogger* headerLogger = NULL;
|
|
if (m_logEnabled) {
|
|
m_statusTimer1.start();
|
|
|
|
headerLogger = new CHeaderLogger(m_logDir, m_name);
|
|
ret = headerLogger->open();
|
|
if (!ret) {
|
|
delete headerLogger;
|
|
headerLogger = NULL;
|
|
}
|
|
}
|
|
|
|
CG2Handler::setG2ProtocolHandlerPool(m_g2HandlerPool);
|
|
CG2Handler::setHeaderLogger(headerLogger);
|
|
|
|
CDExtraHandler::setCallsign(m_gatewayCallsign);
|
|
CDExtraHandler::setHeaderLogger(headerLogger);
|
|
CDExtraHandler::setMaxDongles(m_dextraMaxDongles);
|
|
|
|
CDPlusHandler::setCallsign(m_gatewayCallsign);
|
|
CDPlusHandler::setDPlusLogin(m_dplusLogin);
|
|
CDPlusHandler::setHeaderLogger(headerLogger);
|
|
CDPlusHandler::setMaxDongles(m_dplusMaxDongles);
|
|
if (m_dplusEnabled)
|
|
CDPlusHandler::startAuthenticator(m_gatewayAddress, &m_cache);
|
|
|
|
CDCSHandler::setGatewayType(m_gatewayType);
|
|
CDCSHandler::setHeaderLogger(headerLogger);
|
|
|
|
CRepeaterHandler::setLocalAddress(m_gatewayAddress);
|
|
CRepeaterHandler::setG2HandlerPool(m_g2HandlerPool);
|
|
|
|
if (m_irc != NULL)
|
|
CRepeaterHandler::setIRC(m_irc);
|
|
|
|
CRepeaterHandler::setCache(&m_cache);
|
|
CRepeaterHandler::setGateway(m_gatewayCallsign);
|
|
CRepeaterHandler::setLanguage(m_language);
|
|
CRepeaterHandler::setDExtraEnabled(m_dextraEnabled);
|
|
CRepeaterHandler::setDPlusEnabled(m_dplusEnabled);
|
|
CRepeaterHandler::setDCSEnabled(m_dcsEnabled);
|
|
CRepeaterHandler::setHeaderLogger(headerLogger);
|
|
CRepeaterHandler::setAPRSHandlers(m_outgoingAprsHandler, m_incomingAprsHandler);
|
|
CRepeaterHandler::setInfoEnabled(m_infoEnabled);
|
|
CRepeaterHandler::setEchoEnabled(m_echoEnabled);
|
|
CRepeaterHandler::setDTMFEnabled(m_dtmfEnabled);
|
|
if (m_whiteList != NULL) {
|
|
CDExtraHandler::setWhiteList(m_whiteList);
|
|
CDPlusHandler::setWhiteList(m_whiteList);
|
|
CDCSHandler::setWhiteList(m_whiteList);
|
|
}
|
|
if (m_blackList != NULL) {
|
|
CDExtraHandler::setBlackList(m_blackList);
|
|
CDPlusHandler::setBlackList(m_blackList);
|
|
CDCSHandler::setBlackList(m_blackList);
|
|
}
|
|
if (m_restrictList != NULL)
|
|
CRepeaterHandler::setRestrictList(m_restrictList);
|
|
|
|
CAudioUnit::setLanguage(m_dataDir, m_language);
|
|
|
|
#ifdef USE_STARNET
|
|
CStarNetHandler::setCache(&m_cache);
|
|
CStarNetHandler::setGateway(m_gatewayCallsign);
|
|
CStarNetHandler::setG2HandlerPool(m_g2HandlerPool);
|
|
|
|
if (m_irc != NULL)
|
|
CStarNetHandler::setIRC(m_irc);
|
|
|
|
CStarNetHandler::setLogging(m_logEnabled, m_logDir);
|
|
#if defined(DEXTRA_LINK) || defined(DCS_LINK)
|
|
CStarNetHandler::link();
|
|
#endif
|
|
#endif
|
|
|
|
if (m_ddModeEnabled) {
|
|
CDDHandler::initialise(MAX_DD_ROUTES, m_name);
|
|
CDDHandler::setLogging(m_logEnabled, m_logDir);
|
|
CDDHandler::setHeaderLogger(headerLogger);
|
|
|
|
if (m_irc != NULL)
|
|
CDDHandler::setIRC(m_irc);
|
|
}
|
|
|
|
#ifdef USE_CCS
|
|
std::string ccsAddress = m_ccsEnabled ? m_gatewayAddress : LOOPBACK_ADDRESS;
|
|
CCCSHandler::setLocalAddress(ccsAddress);
|
|
CCCSHandler::setHeaderLogger(headerLogger);
|
|
CCCSHandler::setHost(m_ccsHost);
|
|
#endif
|
|
|
|
if (m_remoteEnabled && !m_remotePassword.empty() && m_remotePort > 0U) {
|
|
m_remote = new CRemoteHandler(m_remotePassword, m_remotePort, m_gatewayAddress);
|
|
bool res = m_remote->open();
|
|
if (!res) {
|
|
delete m_remote;
|
|
m_remote = NULL;
|
|
}
|
|
}
|
|
|
|
CRepeaterHandler::startup();
|
|
|
|
#ifdef USE_CALLSIGN_SERVER
|
|
CCallsignServer* server = NULL;
|
|
if (m_dextraEnabled || m_dcsEnabled) {
|
|
server = new CCallsignServer(m_gatewayCallsign, m_gatewayAddress, &m_cache);
|
|
server->start();
|
|
}
|
|
#endif
|
|
|
|
auto timePoint = std::chrono::steady_clock::now();
|
|
|
|
m_statusFileTimer.start();
|
|
m_statusTimer2.start();
|
|
|
|
#ifndef DEBUG_DSTARGW
|
|
try {
|
|
#endif
|
|
while (!m_killed) {
|
|
if (m_icomRepeaterHandler != NULL)
|
|
processRepeater(m_icomRepeaterHandler);
|
|
|
|
if (m_hbRepeaterHandler != NULL)
|
|
processRepeater(m_hbRepeaterHandler);
|
|
|
|
if (m_dummyRepeaterHandler != NULL)
|
|
processRepeater(m_dummyRepeaterHandler);
|
|
|
|
if (m_irc != NULL)
|
|
processIrcDDB();
|
|
|
|
processDExtra();
|
|
processDPlus();
|
|
processDCS();
|
|
processG2();
|
|
#ifdef USE_CCS
|
|
CCCSHandler::process();
|
|
#endif
|
|
|
|
if (m_ddModeEnabled)
|
|
processDD();
|
|
|
|
if (m_remote != NULL)
|
|
m_remote->process();
|
|
|
|
unsigned long ms = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now()- timePoint).count();
|
|
timePoint = std::chrono::steady_clock::now();
|
|
|
|
CRepeaterHandler::clock(ms);
|
|
CG2Handler::clock(ms);
|
|
CDExtraHandler::clock(ms);
|
|
CDPlusHandler::clock(ms);
|
|
CDCSHandler::clock(ms);
|
|
#ifdef USE_STARNET
|
|
CStarNetHandler::clock(ms);
|
|
#endif
|
|
CDDHandler::clock(ms);
|
|
#ifdef USE_CCS
|
|
CCCSHandler::clock(ms);
|
|
#endif
|
|
|
|
m_statusTimer2.clock(ms);
|
|
|
|
m_statusFileTimer.clock(ms);
|
|
if (m_statusFileTimer.hasExpired()) {
|
|
readStatusFiles();
|
|
m_statusFileTimer.start();
|
|
}
|
|
|
|
if (m_outgoingAprsHandler != NULL)
|
|
m_outgoingAprsHandler->clock(ms);
|
|
|
|
if (m_logEnabled) {
|
|
m_statusTimer1.clock(ms);
|
|
if (m_statusTimer1.hasExpired()) {
|
|
bool ret1 = CDExtraHandler::stateChange();
|
|
bool ret2 = CDPlusHandler::stateChange();
|
|
bool ret3 = CDCSHandler::stateChange();
|
|
#ifdef USE_CCS
|
|
bool ret4 = CCCSHandler::stateChange();
|
|
if (ret1 || ret2 || ret3 || ret4)
|
|
writeStatus();
|
|
#else
|
|
if (ret1 || ret2 || ret3)
|
|
writeStatus();
|
|
#endif
|
|
|
|
m_statusTimer1.start();
|
|
}
|
|
}
|
|
|
|
::std::this_thread::sleep_for(std::chrono::milliseconds(TIME_PER_TIC_MS));
|
|
}
|
|
#ifndef DEBUG_DSTARGW
|
|
}
|
|
catch (std::exception& e) {
|
|
std::string message(e.what());
|
|
CLog::logFatal("Exception raised in the DStar Gateway thread - \"%s\"", message.c_str());
|
|
throw;
|
|
}
|
|
catch (...) {
|
|
CLog::logFatal("Unknown exception raised in the DStar Gateway thread");
|
|
throw;
|
|
}
|
|
#endif
|
|
|
|
CLog::logInfo("Stopping the DStar Gateway thread");
|
|
|
|
// Unlink from all reflectors
|
|
CDExtraHandler::unlink();
|
|
CDPlusHandler::unlink();
|
|
CDCSHandler::unlink();
|
|
#ifdef USE_CSS
|
|
CCCSHandler::disconnect();
|
|
#endif
|
|
|
|
if (m_ddModeEnabled)
|
|
CDDHandler::finalise();
|
|
|
|
#ifdef USE_CALLSIGN_SERVER
|
|
if (server != NULL)
|
|
server->stop();
|
|
#endif
|
|
|
|
m_dextraPool->close();
|
|
delete m_dextraPool;
|
|
|
|
m_dplusPool->close();
|
|
delete m_dplusPool;
|
|
|
|
m_dcsPool->close();
|
|
delete m_dcsPool;
|
|
|
|
m_g2HandlerPool->close();
|
|
delete m_g2HandlerPool;
|
|
|
|
if (m_irc != NULL) {
|
|
m_irc->close();
|
|
delete m_irc;
|
|
}
|
|
|
|
if (m_icomRepeaterHandler != NULL) {
|
|
m_icomRepeaterHandler->close();
|
|
delete m_icomRepeaterHandler;
|
|
}
|
|
|
|
if (m_hbRepeaterHandler != NULL) {
|
|
m_hbRepeaterHandler->close();
|
|
delete m_hbRepeaterHandler;
|
|
}
|
|
|
|
if (m_dummyRepeaterHandler != NULL) {
|
|
m_dummyRepeaterHandler->close();
|
|
delete m_dummyRepeaterHandler;
|
|
}
|
|
|
|
if (m_remote != NULL) {
|
|
m_remote->close();
|
|
delete m_remote;
|
|
}
|
|
|
|
if(m_outgoingAprsHandler != nullptr) {
|
|
m_outgoingAprsHandler->close();
|
|
delete m_outgoingAprsHandler;
|
|
}
|
|
|
|
if (headerLogger != NULL) {
|
|
headerLogger->close();
|
|
delete headerLogger;
|
|
}
|
|
|
|
CHeaderData::finalise();
|
|
CG2Handler::finalise();
|
|
CDExtraHandler::finalise();
|
|
CDPlusHandler::finalise();
|
|
CDCSHandler::finalise();
|
|
CRepeaterHandler::finalise();
|
|
#ifdef USE_STARNET
|
|
CStarNetHandler::finalise();
|
|
#endif
|
|
#ifdef USE_CCS
|
|
CCCSHandler::finalise();
|
|
#endif
|
|
CAudioUnit::finalise();
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void CDStarGatewayThread::kill()
|
|
{
|
|
m_killed = true;
|
|
}
|
|
|
|
void CDStarGatewayThread::setGateway(GATEWAY_TYPE gatewayType, const std::string& gatewayCallsign, const std::string& gatewayAddress)
|
|
{
|
|
if (!m_stopped)
|
|
return;
|
|
|
|
m_gatewayType = gatewayType;
|
|
m_gatewayCallsign = gatewayCallsign;
|
|
m_gatewayAddress = gatewayAddress;
|
|
}
|
|
|
|
|
|
void CDStarGatewayThread::addRepeater(const std::string& callsign, const std::string& band, const std::string& address, unsigned int port, HW_TYPE hwType, const std::string& reflector, bool atStartup, RECONNECT reconnect, bool dratsEnabled, double frequency, double offset, double range, double latitude, double longitude, double agl, const std::string& description1, const std::string& description2, const std::string& url, IRepeaterProtocolHandler* handler, unsigned char band1, unsigned char band2, unsigned char band3)
|
|
{
|
|
CRepeaterHandler::add(callsign, band, address, port, hwType, reflector, atStartup, reconnect, dratsEnabled, frequency, offset, range, latitude, longitude, agl, description1, description2, url, handler, band1, band2, band3);
|
|
|
|
std::string repeater = callsign;
|
|
repeater.resize(LONG_CALLSIGN_LENGTH - 1U);
|
|
repeater += band;
|
|
|
|
// Add a fixed address and protocol for the local repeaters
|
|
m_cache.updateRepeater(repeater, m_gatewayCallsign, "127.0.0.1", DP_LOOPBACK, true, true);
|
|
|
|
CLog::logInfo("Adding %s to the cache as a local repeater", repeater.c_str());
|
|
}
|
|
|
|
#ifdef USE_STARNET
|
|
#if defined(DEXTRA_LINK) || defined(DCS_LINK)
|
|
void CDStarGatewayThread::addStarNet(const std::string& callsign, const std::string& logoff, const std::string& repeater, const std::string& infoText, const std::string& permanent, unsigned int userTimeout, unsigned int groupTimeout, STARNET_CALLSIGN_SWITCH callsignSwitch, bool txMsgSwitch, const std::string& reflector)
|
|
{
|
|
CStarNetHandler::add(callsign, logoff, repeater, infoText, permanent, userTimeout, groupTimeout, callsignSwitch, txMsgSwitch, reflector);
|
|
}
|
|
#else
|
|
void CDStarGatewayThread::addStarNet(const std::string& callsign, const std::string& logoff, const std::string& repeater, const std::string& infoText, const std::string& permanent, unsigned int userTimeout, unsigned int groupTimeout, STARNET_CALLSIGN_SWITCH callsignSwitch, bool txMsgSwitch)
|
|
{
|
|
CStarNetHandler::add(callsign, logoff, repeater, infoText, permanent, userTimeout, groupTimeout, callsignSwitch, txMsgSwitch);
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
void CDStarGatewayThread::setIcomRepeaterHandler(CIcomRepeaterProtocolHandler* handler)
|
|
{
|
|
m_icomRepeaterHandler = handler;
|
|
}
|
|
|
|
void CDStarGatewayThread::setHBRepeaterHandler(CHBRepeaterProtocolHandler* handler)
|
|
{
|
|
m_hbRepeaterHandler = handler;
|
|
}
|
|
|
|
void CDStarGatewayThread::setDummyRepeaterHandler(CDummyRepeaterProtocolHandler* handler)
|
|
{
|
|
m_dummyRepeaterHandler = handler;
|
|
}
|
|
|
|
void CDStarGatewayThread::setIRC(CIRCDDB* irc)
|
|
{
|
|
assert(irc != NULL);
|
|
|
|
m_irc = irc;
|
|
|
|
m_lastStatus = IS_DISCONNECTED;
|
|
}
|
|
|
|
void CDStarGatewayThread::setLanguage(TEXT_LANG language)
|
|
{
|
|
m_language = language;
|
|
}
|
|
|
|
void CDStarGatewayThread::setDExtra(bool enabled, unsigned int maxDongles)
|
|
{
|
|
if (enabled) {
|
|
m_dextraEnabled = true;
|
|
m_dextraMaxDongles = maxDongles;
|
|
} else {
|
|
m_dextraEnabled = false;
|
|
m_dextraMaxDongles = 0U;
|
|
}
|
|
}
|
|
|
|
void CDStarGatewayThread::setDPlus(bool enabled, unsigned int maxDongles, const std::string& login)
|
|
{
|
|
if (enabled) {
|
|
m_dplusEnabled = true;
|
|
m_dplusMaxDongles = maxDongles;
|
|
} else {
|
|
m_dplusEnabled = false;
|
|
m_dplusMaxDongles = 0U;
|
|
}
|
|
|
|
m_dplusLogin = login;
|
|
}
|
|
|
|
void CDStarGatewayThread::setDCS(bool enabled)
|
|
{
|
|
m_dcsEnabled = enabled;
|
|
}
|
|
|
|
void CDStarGatewayThread::setXLX(bool enabled)
|
|
{
|
|
m_xlxEnabled = enabled;
|
|
}
|
|
|
|
#ifdef USE_CCS
|
|
void CDStarGatewayThread::setCCS(bool enabled, const std::string& host)
|
|
{
|
|
m_ccsEnabled = enabled;
|
|
|
|
wxFileName fileName(wxFileName::GetHomeDir(), CCS_HOSTS_FILE_NAME);
|
|
|
|
if (!fileName.IsFileReadable()) {
|
|
CLog::logInfo("File %s not readable", fileName.GetFullPath().c_str());
|
|
#if defined(__WINDOWS__)
|
|
fileName.Assign(::wxGetCwd(), CCS_HOSTS_FILE_NAME);
|
|
#else
|
|
fileName.Assign(wxT(m_dataDir), CCS_HOSTS_FILE_NAME);
|
|
#endif
|
|
if (!fileName.IsFileReadable()) {
|
|
CLog::logInfo("File %s not readable", fileName.GetFullPath().c_str());
|
|
m_ccsEnabled = false;
|
|
return;
|
|
}
|
|
}
|
|
|
|
CHostFile hostFile(fileName.GetFullPath(), true);
|
|
|
|
m_ccsHost = hostFile.getAddress(host);
|
|
}
|
|
#endif
|
|
|
|
void CDStarGatewayThread::setLog(bool enabled, bool logIRCDDBTraffic)
|
|
{
|
|
m_logEnabled = enabled;
|
|
m_logIRCDDB = logIRCDDBTraffic;
|
|
}
|
|
|
|
void CDStarGatewayThread::setAPRSWriters(CAPRSHandler* outgoingWriter, CAPRSHandler* incomingWriter)
|
|
{
|
|
m_outgoingAprsHandler = outgoingWriter;
|
|
m_incomingAprsHandler = incomingWriter;
|
|
}
|
|
|
|
void CDStarGatewayThread::setInfoEnabled(bool enabled)
|
|
{
|
|
m_infoEnabled = enabled;
|
|
}
|
|
|
|
void CDStarGatewayThread::setEchoEnabled(bool enabled)
|
|
{
|
|
m_echoEnabled = enabled;
|
|
}
|
|
|
|
void CDStarGatewayThread::setDTMFEnabled(bool enabled)
|
|
{
|
|
m_dtmfEnabled = enabled;
|
|
}
|
|
|
|
void CDStarGatewayThread::setDDModeEnabled(bool enabled)
|
|
{
|
|
m_ddModeEnabled = enabled;
|
|
}
|
|
|
|
void CDStarGatewayThread::setLocation(double latitude, double longitude)
|
|
{
|
|
m_latitude = latitude;
|
|
m_longitude = longitude;
|
|
}
|
|
|
|
void CDStarGatewayThread::setRemote(bool enabled, const std::string& password, unsigned int port)
|
|
{
|
|
if (enabled) {
|
|
m_remoteEnabled = true;
|
|
m_remotePassword = password;
|
|
m_remotePort = port;
|
|
} else {
|
|
m_remoteEnabled = false;
|
|
m_remotePassword = password;
|
|
m_remotePort = REMOTE_DUMMY_PORT;
|
|
}
|
|
}
|
|
|
|
void CDStarGatewayThread::setWhiteList(CCallsignList* list)
|
|
{
|
|
assert(list != NULL);
|
|
|
|
m_whiteList = list;
|
|
}
|
|
|
|
void CDStarGatewayThread::setBlackList(CCallsignList* list)
|
|
{
|
|
assert(list != NULL);
|
|
|
|
m_blackList = list;
|
|
}
|
|
|
|
void CDStarGatewayThread::setRestrictList(CCallsignList* list)
|
|
{
|
|
assert(list != NULL);
|
|
|
|
m_restrictList = list;
|
|
}
|
|
|
|
void CDStarGatewayThread::processIrcDDB()
|
|
{
|
|
// Once per second
|
|
if (m_statusTimer2.hasExpired()) {
|
|
int status = m_irc->getConnectionState();
|
|
switch (status) {
|
|
case 0:
|
|
case 10:
|
|
if (m_lastStatus != IS_DISCONNECTED) {
|
|
CLog::logInfo("Disconnected from ircDDB");
|
|
m_lastStatus = IS_DISCONNECTED;
|
|
}
|
|
break;
|
|
case 7:
|
|
if (m_lastStatus != IS_CONNECTED) {
|
|
CLog::logInfo("Connected to ircDDB");
|
|
m_lastStatus = IS_CONNECTED;
|
|
}
|
|
break;
|
|
default:
|
|
if (m_lastStatus != IS_CONNECTING) {
|
|
CLog::logInfo("Connecting to ircDDB");
|
|
m_lastStatus = IS_CONNECTING;
|
|
}
|
|
break;
|
|
}
|
|
|
|
m_statusTimer2.start();
|
|
}
|
|
|
|
|
|
// Process incoming ircDDB messages, updating the caches
|
|
for (;;) {
|
|
IRCDDB_RESPONSE_TYPE type = m_irc->getMessageType();
|
|
|
|
switch (type) {
|
|
case IDRT_USER: {
|
|
std::string user, repeater, gateway, address, timestamp;
|
|
bool res = m_irc->receiveUser(user, repeater, gateway, address, timestamp);
|
|
if (!res)
|
|
break;
|
|
|
|
if(m_logIRCDDB) {
|
|
if (!address.empty()) {
|
|
CLog::logInfo("USER: %s %s %s %s", user.c_str(), repeater.c_str(), gateway.c_str(), address.c_str());
|
|
m_cache.updateUser(user, repeater, gateway, address, timestamp, DP_DEXTRA, false, false);
|
|
} else {
|
|
CLog::logInfo("USER: %s NOT FOUND", user.c_str());
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case IDRT_REPEATER: {
|
|
std::string repeater, gateway, address;
|
|
bool res = m_irc->receiveRepeater(repeater, gateway, address);
|
|
if (!res)
|
|
break;
|
|
|
|
CRepeaterHandler::resolveRepeater(repeater, gateway, address, DP_DEXTRA);
|
|
if(m_logIRCDDB) {
|
|
if (!address.empty()) {
|
|
CLog::logInfo("REPEATER: %s %s %s", repeater.c_str(), gateway.c_str(), address.c_str());
|
|
m_cache.updateRepeater(repeater, gateway, address, DP_DEXTRA, false, false);
|
|
} else {
|
|
CLog::logInfo("REPEATER: %s NOT FOUND", repeater.c_str());
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case IDRT_GATEWAY: {
|
|
std::string gateway, address;
|
|
bool res = m_irc->receiveGateway(gateway, address);
|
|
if (!res)
|
|
break;
|
|
|
|
CDExtraHandler::gatewayUpdate(gateway, address);
|
|
CDPlusHandler::gatewayUpdate(gateway, address);
|
|
|
|
if(m_logIRCDDB) {
|
|
if (!address.empty()) {
|
|
CLog::logInfo("GATEWAY: %s %s", gateway.c_str(), address.c_str());
|
|
m_cache.updateGateway(gateway, address, DP_DEXTRA, false, false);
|
|
} else {
|
|
CLog::logInfo("GATEWAY: %s NOT FOUND", gateway.c_str());
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case IDRT_NATTRAVERSAL_G2: {
|
|
std::string address;
|
|
bool res = m_irc->receiveNATTraversalG2(address);
|
|
if(!res)
|
|
return;
|
|
|
|
if(m_g2HandlerPool != nullptr) {
|
|
CLog::logInfo("%s wants to G2 route to us, punching UDP Holes through NAT", address.c_str());
|
|
m_g2HandlerPool->traverseNat(address);
|
|
}
|
|
else {
|
|
CLog::logInfo("%s wants to G2 route to us, but G2 is disabled", address.c_str());
|
|
}
|
|
}
|
|
break;
|
|
case IDRT_NATTRAVERSAL_DEXTRA: {
|
|
std::string address, remotePort;
|
|
bool res = m_irc->receiveNATTraversalDextra(address, remotePort);
|
|
if(!res)
|
|
return;
|
|
|
|
auto remotePortInt = CStringUtils::stringToPort(remotePort);
|
|
if(m_dextraEnabled && remotePortInt > 0U && m_dextraPool != nullptr && m_dextraPool->getIncomingHandler() != nullptr) {
|
|
CLog::logInfo("%s wants to DExtra connect to us, punching UDP Holes through NAT, remote port %s", address.c_str(), remotePort.c_str());
|
|
m_dextraPool->getIncomingHandler()->traverseNat(address, remotePortInt);
|
|
}
|
|
else {
|
|
CLog::logInfo("%s wants to DExtra connect to us, punching UDP Holes through NAT, remote port %s, but DExtra is Disabled", address.c_str(), remotePort.c_str());
|
|
}
|
|
}
|
|
break;
|
|
case IDRT_NATTRAVERSAL_DPLUS: {
|
|
std::string address, remotePort;
|
|
bool res = m_irc->receiveNATTraversalDPlus(address, remotePort);
|
|
if(!res)
|
|
return;
|
|
|
|
auto remotePortInt = CStringUtils::stringToPort(remotePort);
|
|
if(m_dplusEnabled && remotePortInt > 0U && m_dplusPool != nullptr && m_dplusPool->getIncomingHandler() != nullptr) {
|
|
CLog::logInfo("%s wants to DPlus connect to us, punching UDP Holes through NAT, remote port %s", address.c_str(), remotePort.c_str());
|
|
m_dplusPool->getIncomingHandler()->traverseNat(address, remotePortInt);
|
|
}
|
|
else {
|
|
CLog::logInfo("%s wants to DPlus connect to us, punching UDP Holes through NAT, remote port %s, but DPlus is Disabled", address.c_str(), remotePort.c_str());
|
|
}
|
|
}
|
|
break;
|
|
case IDRT_NONE:
|
|
return;
|
|
default:
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CDStarGatewayThread::processRepeater(IRepeaterProtocolHandler* handler)
|
|
{
|
|
for (;;) {
|
|
REPEATER_TYPE type = handler->read();
|
|
|
|
switch (type) {
|
|
case RT_POLL: {
|
|
CPollData* poll = handler->readPoll();
|
|
if (poll != NULL) {
|
|
CRepeaterHandler* handler = CRepeaterHandler::findRepeater(*poll);
|
|
if (handler != NULL)
|
|
handler->processRepeater(*poll);
|
|
else
|
|
CRepeaterHandler::pollAllIcom(*poll);
|
|
|
|
delete poll;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case RT_HEARD: {
|
|
CHeardData* heard = handler->readHeard();
|
|
if (heard != NULL) {
|
|
std::string user = heard->getUser();
|
|
std::string repeater = heard->getRepeater();
|
|
|
|
// Internal controller heard have identical user and repeater values
|
|
if (repeater != user) {
|
|
CRepeaterHandler* handler = CRepeaterHandler::findDVRepeater(repeater);
|
|
if (handler == NULL)
|
|
CLog::logInfo("Heard received from unknown repeater, %s", repeater.c_str());
|
|
else
|
|
handler->processRepeater(*heard);
|
|
|
|
delete heard;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case RT_HEADER: {
|
|
CHeaderData* header = handler->readHeader();
|
|
if (header != NULL) {
|
|
// CLog::logInfo("Repeater header - My: %s/%s Your: %s Rpt1: %s Rpt2: %s Flags: %02X %02X %02X", header->getMyCall1().c_str(), header->getMyCall2().c_str(), header->getYourCall().c_str(), header->getRptCall1().c_str(), header->getRptCall2().c_str(), header->getFlag1(), header->getFlag2(), header->getFlag3());
|
|
|
|
CRepeaterHandler* repeater = CRepeaterHandler::findDVRepeater(*header);
|
|
if (repeater == NULL)
|
|
CLog::logInfo("Header received from unknown repeater, %s", header->getRptCall1().c_str());
|
|
else
|
|
repeater->processRepeater(*header);
|
|
|
|
delete header;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case RT_AMBE: {
|
|
CAMBEData* data = handler->readAMBE();
|
|
if (data != NULL) {
|
|
CRepeaterHandler* repeater = CRepeaterHandler::findDVRepeater(*data, false);
|
|
if (repeater != NULL)
|
|
repeater->processRepeater(*data);
|
|
|
|
delete data;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case RT_BUSY_HEADER: {
|
|
CHeaderData* header = handler->readBusyHeader();
|
|
if (header != NULL) {
|
|
// CLog::logInfo("Repeater busy header - My: %s/%s Your: %s Rpt1: %s Rpt2: %s Flags: %02X %02X %02X", header->getMyCall1().c_str(), header->getMyCall2().c_str(), header->getYourCall().c_str(), header->getRptCall1().c_str(), header->getRptCall2().c_str(), header->getFlag1(), header->getFlag2(), header->getFlag3());
|
|
|
|
CRepeaterHandler* repeater = CRepeaterHandler::findDVRepeater(*header);
|
|
if (repeater == NULL)
|
|
CLog::logInfo("Busy header received from unknown repeater, %s", header->getRptCall1().c_str());
|
|
else
|
|
repeater->processBusy(*header);
|
|
|
|
delete header;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case RT_BUSY_AMBE: {
|
|
CAMBEData* data = handler->readBusyAMBE();
|
|
if (data != NULL) {
|
|
CRepeaterHandler* repeater = CRepeaterHandler::findDVRepeater(*data, true);
|
|
if (repeater != NULL)
|
|
repeater->processBusy(*data);
|
|
|
|
delete data;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case RT_DD: {
|
|
CDDData* data = handler->readDD();
|
|
if (data != NULL) {
|
|
// CLog::logInfo("DD header - My: %s/%s Your: %s Rpt1: %s Rpt2: %s Flags: %02X %02X %02X", data->getMyCall1().c_str(), data->getMyCall2().c_str(), data->getYourCall().c_str(), data->getRptCall1().c_str(), data->getRptCall2().c_str(), data->getFlag1(), data->getFlag2(), data->getFlag3());
|
|
|
|
CRepeaterHandler* repeater = CRepeaterHandler::findDDRepeater();
|
|
if (repeater == NULL)
|
|
CLog::logInfo("DD data received from unknown DD repeater, %s", data->getRptCall1().c_str());
|
|
else
|
|
repeater->processRepeater(*data);
|
|
|
|
delete data;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CDStarGatewayThread::processDExtra()
|
|
{
|
|
for (;;) {
|
|
DEXTRA_TYPE type = m_dextraPool->read();
|
|
|
|
switch (type) {
|
|
case DE_POLL: {
|
|
CPollData* poll = m_dextraPool->readPoll();
|
|
if (poll != NULL) {
|
|
CDExtraHandler::process(*poll);
|
|
delete poll;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case DE_CONNECT: {
|
|
CConnectData* connect = m_dextraPool->readConnect();
|
|
if (connect != NULL) {
|
|
CDExtraHandler::process(*connect);
|
|
delete connect;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case DE_HEADER: {
|
|
CHeaderData* header = m_dextraPool->readHeader();
|
|
if (header != NULL) {
|
|
// CLog::logInfo("DExtra header - My: %s/%s Your: %s Rpt1: %s Rpt2: %s", header->getMyCall1().c_str(), header->getMyCall2().c_str(), header->getYourCall().c_str(), header->getRptCall1().c_str(), header->getRptCall2().c_str());
|
|
CDExtraHandler::process(*header);
|
|
delete header;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case DE_AMBE: {
|
|
CAMBEData* data = m_dextraPool->readAMBE();
|
|
if (data != NULL) {
|
|
CDExtraHandler::process(*data);
|
|
delete data;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CDStarGatewayThread::processDPlus()
|
|
{
|
|
for (;;) {
|
|
DPLUS_TYPE type = m_dplusPool->read();
|
|
|
|
switch (type) {
|
|
case DP_POLL: {
|
|
CPollData* poll = m_dplusPool->readPoll();
|
|
if (poll != NULL) {
|
|
CDPlusHandler::process(*poll);
|
|
delete poll;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case DP_CONNECT: {
|
|
CConnectData* connect = m_dplusPool->readConnect();
|
|
if (connect != NULL) {
|
|
CDPlusHandler::process(*connect);
|
|
delete connect;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case DP_HEADER: {
|
|
CHeaderData* header = m_dplusPool->readHeader();
|
|
if (header != NULL) {
|
|
// CLog::logInfo("D-Plus header - My: %s/%s Your: %s Rpt1: %s Rpt2: %s", header->getMyCall1().c_str(), header->getMyCall2().c_str(), header->getYourCall().c_str(), header->getRptCall1().c_str(), header->getRptCall2().c_str());
|
|
CDPlusHandler::process(*header);
|
|
delete header;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case DP_AMBE: {
|
|
CAMBEData* data = m_dplusPool->readAMBE();
|
|
if (data != NULL) {
|
|
CDPlusHandler::process(*data);
|
|
delete data;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CDStarGatewayThread::processDCS()
|
|
{
|
|
for (;;) {
|
|
DCS_TYPE type = m_dcsPool->read();
|
|
|
|
switch (type) {
|
|
case DC_POLL: {
|
|
CPollData* poll = m_dcsPool->readPoll();
|
|
if (poll != NULL) {
|
|
CDCSHandler::process(*poll);
|
|
delete poll;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case DC_CONNECT: {
|
|
CConnectData* connect = m_dcsPool->readConnect();
|
|
if (connect != NULL) {
|
|
CDCSHandler::process(*connect);
|
|
delete connect;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case DC_DATA: {
|
|
CAMBEData* data = m_dcsPool->readData();
|
|
if (data != NULL) {
|
|
// CLog::logInfo("DCS header - My: %s/%s Your: %s Rpt1: %s Rpt2: %s", header->getMyCall1().c_str(), header->getMyCall2().c_str(), header->getYourCall().c_str(), header->getRptCall1().c_str(), header->getRptCall2().c_str());
|
|
CDCSHandler::process(*data);
|
|
delete data;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CDStarGatewayThread::processG2()
|
|
{
|
|
for (;;) {
|
|
G2_TYPE type = m_g2HandlerPool->read();
|
|
|
|
switch (type) {
|
|
case GT_HEADER: {
|
|
CHeaderData* header = m_g2HandlerPool->readHeader();
|
|
if (header != NULL) {
|
|
CLog::logDebug("G2 header - My: %s/%s Your: %s Rpt1: %s Rpt2: %s Flags: %02X %02X %02X", header->getMyCall1().c_str(), header->getMyCall2().c_str(), header->getYourCall().c_str(), header->getRptCall1().c_str(), header->getRptCall2().c_str(), header->getFlag1(), header->getFlag2(), header->getFlag3());
|
|
CG2Handler::process(*header);
|
|
delete header;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case GT_AMBE: {
|
|
CAMBEData* data = m_g2HandlerPool->readAMBE();
|
|
if (data != NULL) {
|
|
CG2Handler::process(*data);
|
|
delete data;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CDStarGatewayThread::processDD()
|
|
{
|
|
for (;;) {
|
|
CDDData* data = CDDHandler::read();
|
|
if (data == NULL)
|
|
return;
|
|
|
|
// CLog::logInfo("DD header - My: %s/%s Your: %s Rpt1: %s Rpt2: %s Flags: %02X %02X %02X", data->getMyCall1().c_str(), data->getMyCall2().c_str(), data->getYourCall().c_str(), data->getRptCall1().c_str(), data->getRptCall2().c_str(), data->getFlag1(), data->getFlag2(), data->getFlag3());
|
|
|
|
delete data;
|
|
}
|
|
}
|
|
|
|
void CDStarGatewayThread::writeStatus()
|
|
{
|
|
std::string fullName = LINKS_BASE_NAME;
|
|
|
|
if (!m_name.empty()) {
|
|
fullName += "_" + m_name;
|
|
}
|
|
|
|
fullName = m_logDir + "/" + LINKS_BASE_NAME + ".log";
|
|
|
|
std::ofstream file;
|
|
file.open(fullName, std::fstream::trunc);
|
|
if (!file.is_open()) {
|
|
CLog::logError("Unable to open %s for writing", fullName.c_str());
|
|
return;
|
|
}
|
|
|
|
CDExtraHandler::writeStatus(file);
|
|
CDPlusHandler::writeStatus(file);
|
|
CDCSHandler::writeStatus(file);
|
|
#ifdef USE_CCS
|
|
CCCSHandler::writeStatus(file);
|
|
#endif
|
|
|
|
file.close();
|
|
}
|
|
|
|
CDStarGatewayStatusData* CDStarGatewayThread::getStatus() const
|
|
{
|
|
bool aprsStatus = false;
|
|
if (m_outgoingAprsHandler != NULL)
|
|
aprsStatus = m_outgoingAprsHandler->isConnected();
|
|
|
|
CDStarGatewayStatusData* status = new CDStarGatewayStatusData(m_lastStatus, aprsStatus);
|
|
|
|
for (unsigned int i = 0U; i < 4U; i++) {
|
|
std::string callsign, linkCallsign;
|
|
LINK_STATUS linkStatus;
|
|
bool ret = CRepeaterHandler::getRepeater(i, callsign, linkStatus, linkCallsign);
|
|
if (ret) {
|
|
std::string incoming1 = CDExtraHandler::getIncoming(callsign);
|
|
std::string incoming2 = CDCSHandler::getIncoming(callsign);
|
|
#if USE_CCS
|
|
std::string incoming3 = CCCSHandler::getIncoming(callsign);
|
|
#endif
|
|
|
|
std::string incoming;
|
|
if (!incoming1.empty()) {
|
|
incoming = incoming1 + " ";
|
|
}
|
|
if (!incoming2.empty()) {
|
|
incoming = incoming2 + " ";
|
|
}
|
|
#if USE_CCS
|
|
if (!incoming3.empty()) {
|
|
incoming = incoming3 + " ";
|
|
}
|
|
#endif
|
|
|
|
status->setRepeater(i, callsign, linkStatus, linkCallsign, incoming);
|
|
}
|
|
}
|
|
|
|
std::string dongles;
|
|
dongles += CDExtraHandler::getDongles();
|
|
dongles += CDPlusHandler::getDongles();
|
|
status->setDongles(dongles);
|
|
|
|
return status;
|
|
}
|
|
|
|
void CDStarGatewayThread::readStatusFiles()
|
|
{
|
|
readStatusFile(STATUS1_FILE_NAME, 0U, m_status1);
|
|
readStatusFile(STATUS2_FILE_NAME, 1U, m_status2);
|
|
readStatusFile(STATUS3_FILE_NAME, 2U, m_status3);
|
|
readStatusFile(STATUS4_FILE_NAME, 3U, m_status4);
|
|
readStatusFile(STATUS5_FILE_NAME, 4U, m_status5);
|
|
}
|
|
|
|
void CDStarGatewayThread::readStatusFile(const std::string& filename, unsigned int n, std::string& var)
|
|
{
|
|
std::string fullFileName = m_dataDir + "/" + filename;
|
|
std::string text;
|
|
std::ifstream file;
|
|
|
|
file.open(fullFileName);
|
|
if(file.is_open()) {
|
|
std::getline(file, text);
|
|
file.close();
|
|
}
|
|
|
|
if(var != text) {
|
|
CLog::logInfo("Status %u message set to \"%s\"", n + 1U, text.c_str());
|
|
CStatusData statusData(text, n);
|
|
CRepeaterHandler::writeStatus(statusData);
|
|
var = text;
|
|
}
|
|
}
|