diff --git a/DStarGateway/DStarGatewayApp.cpp b/DStarGateway/DStarGatewayApp.cpp index da8f50e..7ee437e 100644 --- a/DStarGateway/DStarGatewayApp.cpp +++ b/DStarGateway/DStarGatewayApp.cpp @@ -35,7 +35,6 @@ #include "DStarGatewayConfig.h" #include "DStarGatewayApp.h" #include "Version.h" -#include "HostsFileDownloader.h" #include "IRCDDBMultiClient.h" #include "IRCDDBClient.h" #include "Utils.h" @@ -50,6 +49,7 @@ #include "Daemon.h" #include "APRSISHandlerThread.h" #include "DummyAPRSHandlerThread.h" +#include "HostsFilesManager.h" CDStarGatewayApp * CDStarGatewayApp::g_app = nullptr; const std::string BANNER_1 = CStringUtils::string_format("%s Copyright (C) %s\n", FULL_PRODUCT_NAME.c_str(), VENDOR_NAME.c_str()); @@ -325,30 +325,33 @@ bool CDStarGatewayApp::createThread() TDextra dextraConfig; m_config->getDExtra(dextraConfig); CLog::logInfo("DExtra enabled: %d, max. dongles: %u, url: %s", int(dextraConfig.enabled), dextraConfig.maxDongles, dextraConfig.hostfileUrl.c_str()); - if(dextraConfig.enabled) CHostsFileDownloader::download(dextraConfig.hostfileUrl, paths.dataDir + "/" + DEXTRA_HOSTS_FILE_NAME); m_thread->setDExtra(dextraConfig.enabled, dextraConfig.maxDongles); // Setup DCS TDCS dcsConfig; m_config->getDCS(dcsConfig); CLog::logInfo("DCS enabled: %d, url: %s", int(dcsConfig.enabled), dcsConfig.hostfileUrl.c_str()); - if(dextraConfig.enabled) CHostsFileDownloader::download(dcsConfig.hostfileUrl, paths.dataDir + "/" + DCS_HOSTS_FILE_NAME); m_thread->setDCS(dcsConfig.enabled); // Setup DPlus TDplus dplusConfig; m_config->getDPlus(dplusConfig); CLog::logInfo("D-Plus enabled: %d, max. dongles: %u, login: %s, url: %s", int(dplusConfig.enabled), dplusConfig.maxDongles, dplusConfig.login.c_str(), dplusConfig.hostfileUrl.c_str()); - if(dplusConfig.enabled) CHostsFileDownloader::download(dplusConfig.hostfileUrl, paths.dataDir + "/" + DPLUS_HOSTS_FILE_NAME); m_thread->setDPlus(dplusConfig.enabled, dplusConfig.maxDongles, dplusConfig.login); // Setup XLX TXLX xlxConfig; m_config->getXLX(xlxConfig); CLog::logInfo("XLX enabled: %d, Hosts file url: %s", int(xlxConfig.enabled), xlxConfig.hostfileUrl.c_str()); - if(xlxConfig.enabled) CHostsFileDownloader::download(xlxConfig.hostfileUrl, paths.dataDir + "/" + XLX_HOSTS_FILE_NAME); m_thread->setXLX(xlxConfig.enabled); + // Setup hostsfiles + CHostsFilesManager::setHostFilesDirectories(paths.dataDir, paths.customHostsFiles); + CHostsFilesManager::setDextra(dextraConfig.enabled, dextraConfig.hostfileUrl); + CHostsFilesManager::setDCS (dcsConfig.enabled, dcsConfig.hostfileUrl); + CHostsFilesManager::setDPlus (dplusConfig.enabled, dplusConfig.hostfileUrl); + CHostsFilesManager::setXLX (xlxConfig.enabled, xlxConfig.hostfileUrl); + // Setup Remote TRemote remoteConfig; m_config->getRemote(remoteConfig); diff --git a/DStarGateway/DStarGatewayConfig.cpp b/DStarGateway/DStarGatewayConfig.cpp index eade624..2438e87 100644 --- a/DStarGateway/DStarGatewayConfig.cpp +++ b/DStarGateway/DStarGatewayConfig.cpp @@ -195,11 +195,16 @@ bool CDStarGatewayConfig::loadLog(const CConfig & cfg) bool CDStarGatewayConfig::loadPaths(const CConfig & cfg) { bool ret = cfg.getValue("paths", "data", m_paths.dataDir, 0, 2048, "/usr/local/share/dstargateway.d/"); + ret = cfg.getValue("customHostfiles", "data", m_paths.customHostsFiles, 0, 2048, "/usr/local/share/dstargateway.d/hostfiles.d/") && ret; if(ret && m_paths.dataDir[m_paths.dataDir.length() - 1] != '/') { m_paths.dataDir.push_back('/'); } + if(ret && m_paths.dataDir[m_paths.customHostsFiles.length() - 1] != '/') { + m_paths.customHostsFiles.push_back('/'); + } + //TODO 20211226 check if directory are accessible return ret; diff --git a/DStarGateway/DStarGatewayConfig.h b/DStarGateway/DStarGatewayConfig.h index 016df97..6a620e5 100644 --- a/DStarGateway/DStarGatewayConfig.h +++ b/DStarGateway/DStarGatewayConfig.h @@ -80,6 +80,7 @@ typedef struct { typedef struct { std::string dataDir; + std::string customHostsFiles; } Tpaths; typedef struct { diff --git a/DStarGateway/DStarGatewayThread.cpp b/DStarGateway/DStarGatewayThread.cpp index def3e12..0a65d90 100644 --- a/DStarGateway/DStarGatewayThread.cpp +++ b/DStarGateway/DStarGatewayThread.cpp @@ -54,6 +54,7 @@ #include "Defs.h" #include "Log.h" #include "StringUtils.h" +#include "HostsFilesManager.h" const std::string LOOPBACK_ADDRESS("127.0.0.1"); @@ -136,6 +137,9 @@ CDStarGatewayThread::~CDStarGatewayThread() void* CDStarGatewayThread::Entry() { + CHostsFilesManager::setCache(&m_cache); + auto hostFut = CHostsFilesManager::UpdateHostsAsync(); // Do this in a separate thread + // Truncate the old Links.log file std::string fullName = m_logDir + "/" + LINKS_BASE_NAME + ".log"; if (!m_name.empty()) { @@ -195,6 +199,7 @@ void* CDStarGatewayThread::Entry() } // Wait here until we have the essentials to run + hostFut.get(); 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 @@ -217,9 +222,6 @@ void* CDStarGatewayThread::Entry() } } - loadGateways(); - loadAllReflectors(); - CG2Handler::setG2ProtocolHandlerPool(m_g2HandlerPool); CG2Handler::setHeaderLogger(headerLogger); @@ -1139,82 +1141,6 @@ void CDStarGatewayThread::processDD() } } -void CDStarGatewayThread::loadGateways() -{ - std::string fileName = m_dataDir + "/" + GATEWAY_HOSTS_FILE_NAME; - loadReflectors(fileName, DP_DEXTRA); -} - -void CDStarGatewayThread::loadAllReflectors() -{ - if (m_xlxEnabled) { - std::string fileName = m_dataDir + "/" + DPLUS_HOSTS_FILE_NAME; - loadReflectors(fileName, DP_DCS); - } - - if (m_dplusEnabled) { - std::string fileName = m_dataDir + "/" + DPLUS_HOSTS_FILE_NAME; - loadReflectors(fileName, DP_DPLUS); - } - - if (m_dextraEnabled) { - std::string fileName = m_dataDir + "/" + DEXTRA_HOSTS_FILE_NAME; - loadReflectors(fileName, DP_DEXTRA); - } - - if (m_dcsEnabled) { - std::string fileName = m_dataDir + "/" + DCS_HOSTS_FILE_NAME; - loadReflectors(fileName, DP_DCS); - } -} - -void CDStarGatewayThread::loadReflectors(std::string hostFileName, DSTAR_PROTOCOL proto) -{ - unsigned int count = 0U; - - CHostFile hostFile(hostFileName, false); - for (unsigned int i = 0U; i < hostFile.getCount(); i++) { - std::string reflector = hostFile.getName(i); - in_addr address = CUDPReaderWriter::lookup(hostFile.getAddress(i)); - bool lock = hostFile.getLock(i); - - if (address.s_addr != INADDR_NONE) { - unsigned char* ucp = (unsigned char*)&address; - - std::string addrText; - addrText = CStringUtils::string_format("%u.%u.%u.%u", ucp[0U] & 0xFFU, ucp[1U] & 0xFFU, ucp[2U] & 0xFFU, ucp[3U] & 0xFFU); - - if (lock) - CLog::logInfo("Locking %s to %s", reflector.c_str(), addrText.c_str()); - - reflector.resize(LONG_CALLSIGN_LENGTH - 1U, ' '); - reflector += "G"; - m_cache.updateGateway(reflector, addrText, proto, lock, true); - - count++; - } - } - - std::string protoString; - switch (proto) - { - case DP_DEXTRA: - protoString = "DExtra"; - break; - case DP_DCS: - protoString = "DCS"; - break; - case DP_DPLUS: - protoString = "DPlus"; - break; - default: - // ??? - break; - } - - CLog::logInfo("Loaded %u of %u %s hosts from %s", count, hostFile.getCount(), protoString.c_str() , hostFileName.c_str()); -} - void CDStarGatewayThread::writeStatus() { std::string fullName = LINKS_BASE_NAME; diff --git a/DStarGateway/DStarGatewayThread.h b/DStarGateway/DStarGatewayThread.h index f279b6f..68b9591 100644 --- a/DStarGateway/DStarGatewayThread.h +++ b/DStarGateway/DStarGatewayThread.h @@ -146,14 +146,6 @@ private: void processG2(); void processDD(); - void loadGateways(); - void loadAllReflectors(); - void loadReflectors(std::string hostFileName, DSTAR_PROTOCOL proto); - void loadDExtraReflectors(const std::string& fileName); - void loadDPlusReflectors(const std::string& fileName); - void loadDCSReflectors(const std::string& fileName); - void loadXLXReflectors(); - void writeStatus(); void readStatusFiles(); diff --git a/DStarGateway/HostsFilesManager.cpp b/DStarGateway/HostsFilesManager.cpp new file mode 100644 index 0000000..60805d0 --- /dev/null +++ b/DStarGateway/HostsFilesManager.cpp @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2024 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 + +#include "HostsFilesManager.h" +#include "HostsFileDownloader.h" +#include "HostFile.h" +#include "StringUtils.h" +#include "UDPReaderWriter.h" +#include "Log.h" + +std::string CHostsFilesManager::m_hostFilesDirectory(""); +std::string CHostsFilesManager::m_customFilesDirectory(""); + +bool CHostsFilesManager::m_dextraEnabled = false; +bool CHostsFilesManager::m_dcsEnabled = false; +bool CHostsFilesManager::m_dplusEnabled = false; +bool CHostsFilesManager::m_xlxEnabled = false; + +std::string CHostsFilesManager::m_dextraUrl(""); +std::string CHostsFilesManager::m_dcsUrl(""); +std::string CHostsFilesManager::m_dplusUrl(""); +std::string CHostsFilesManager::m_xlxUrl(""); + +CCacheManager * CHostsFilesManager::m_cache = nullptr; +CTimer CHostsFilesManager::m_downloadTimer(1000U, 60 * 60 * 24); + +void CHostsFilesManager::setHostFilesDirectories(const std::string & hostFilesDir, const std::string & customHostFilesDir) +{ + m_hostFilesDirectory.assign(hostFilesDir); + m_customFilesDirectory.assign(customHostFilesDir); +} + +void CHostsFilesManager::setDextra(bool enabled, const std::string & url) +{ + m_dextraEnabled = enabled; + m_dextraUrl.assign(url); +} + +void CHostsFilesManager::setDPlus(bool enabled, const std::string & url) +{ + m_dplusEnabled = enabled; + m_dplusUrl.assign(url); +} + +void CHostsFilesManager::setDCS(bool enabled, const std::string & url) +{ + m_dcsEnabled = enabled; + m_dcsUrl.assign(url); +} + +void CHostsFilesManager::setXLX(bool enabled, const std::string & url) +{ + m_xlxEnabled = enabled; + m_xlxUrl.assign(url); +} + +void CHostsFilesManager::setCache(CCacheManager * cache) +{ + assert(cache != nullptr); + m_cache = cache; +} + +void CHostsFilesManager::clock(unsigned int ms) +{ + m_downloadTimer.clock(ms); + + if(m_downloadTimer.hasExpired()) { + UpdateHostsAsync(); // call and forget + } +} + +void CHostsFilesManager::setDownloadTimeout(unsigned int seconds) +{ + m_downloadTimer.setTimeout(seconds); +} + +bool CHostsFilesManager::UpdateHostsFromInternet() +{ + CLog::logInfo("Updating hosts files from internet"); + bool ret = true; + if(m_dextraEnabled && !m_dextraUrl.empty()) ret = CHostsFileDownloader::download(m_dextraUrl, m_hostFilesDirectory + "/" + DEXTRA_HOSTS_FILE_NAME) && ret; + if(m_dcsEnabled && !m_dcsUrl.empty()) ret = CHostsFileDownloader::download(m_dcsUrl, m_hostFilesDirectory + "/" + DCS_HOSTS_FILE_NAME) && ret; + if(m_dplusEnabled && !m_dplusUrl.empty()) ret = CHostsFileDownloader::download(m_dplusUrl, m_hostFilesDirectory + "/" + DPLUS_HOSTS_FILE_NAME) && ret; + if(m_xlxEnabled && !m_xlxUrl.empty()) ret = CHostsFileDownloader::download(m_xlxUrl, m_hostFilesDirectory + "/" + XLX_HOSTS_FILE_NAME) && ret; + + if(!ret) CLog::logWarning("Some hosts files failed to downlaod"); + + CHostsFilesManager::loadReflectors(m_hostFilesDirectory); + + return ret; +} + +bool CHostsFilesManager::UpdateHostsFromLocal() +{ + CHostsFilesManager::loadReflectors(m_customFilesDirectory); + return true; +} + +bool CHostsFilesManager::UpdateHosts() +{ + bool ret = UpdateHostsFromInternet(); + UpdateHostsFromLocal() && ret; + + return ret; +} + +std::future CHostsFilesManager::UpdateHostsAsync() +{ + auto fut = std::async(std::launch::async, UpdateHosts); + return fut; +} + +void CHostsFilesManager::loadReflectors(const std::string & directory) +{ + if (m_xlxEnabled) { + std::string fileName = directory + "/" + DPLUS_HOSTS_FILE_NAME; + loadReflectors(fileName, DP_DCS); + } + + if (m_dplusEnabled) { + std::string fileName = directory + "/" + DPLUS_HOSTS_FILE_NAME; + loadReflectors(fileName, DP_DPLUS); + } + + if (m_dextraEnabled) { + std::string fileName = directory + "/" + DEXTRA_HOSTS_FILE_NAME; + loadReflectors(fileName, DP_DEXTRA); + } + + if (m_dcsEnabled) { + std::string fileName = directory + "/" + DCS_HOSTS_FILE_NAME; + loadReflectors(fileName, DP_DCS); + } +} + +void CHostsFilesManager::loadReflectors(const std::string & hostFileName, DSTAR_PROTOCOL proto) +{ + if(m_cache == nullptr) { + CLog::logDebug("HostsFilesManager cache not initilized"); + return; + } + + unsigned int count = 0U; + + CHostFile hostFile(hostFileName, false); + for (unsigned int i = 0U; i < hostFile.getCount(); i++) { + std::string reflector = hostFile.getName(i); + in_addr address = CUDPReaderWriter::lookup(hostFile.getAddress(i)); + bool lock = hostFile.getLock(i); + + if (address.s_addr != INADDR_NONE) { + unsigned char* ucp = (unsigned char*)&address; + + std::string addrText; + addrText = CStringUtils::string_format("%u.%u.%u.%u", ucp[0U] & 0xFFU, ucp[1U] & 0xFFU, ucp[2U] & 0xFFU, ucp[3U] & 0xFFU); + + if (lock) + CLog::logInfo("Locking %s to %s", reflector.c_str(), addrText.c_str()); + + reflector.resize(LONG_CALLSIGN_LENGTH - 1U, ' '); + reflector += "G"; + m_cache->updateGateway(reflector, addrText, proto, lock, true); + + count++; + } + } + + std::string protoString; + switch (proto) + { + case DP_DEXTRA: + protoString = "DExtra"; + break; + case DP_DCS: + protoString = "DCS"; + break; + case DP_DPLUS: + protoString = "DPlus"; + break; + default: + // ??? + break; + } + + CLog::logInfo("Loaded %u of %u %s hosts from %s", count, hostFile.getCount(), protoString.c_str() , hostFileName.c_str()); +} \ No newline at end of file diff --git a/DStarGateway/HostsFilesManager.h b/DStarGateway/HostsFilesManager.h new file mode 100644 index 0000000..6e624f4 --- /dev/null +++ b/DStarGateway/HostsFilesManager.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2024 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. + */ + +#ifndef HostsFilesManager_H +#define HostsFilesManager_H + +#include +#include + +#include "CacheManager.h" +#include "Timer.h" +#include "DStarDefines.h" + +class CHostsFilesManager { +public: + static void setHostFilesDirectories(const std::string & hostFilesDir, const std::string & customHostFilesDir); + static void setDextra(bool enabled, const std::string & dextraUrl); + static void setDCS(bool enabled, const std::string & dcsUrl); + static void setDPlus(bool enabled, const std::string & dplusUrl); + static void setXLX(bool enabled, const std::string & xlxUrl); + static void setCache(CCacheManager * cache); + static void clock(unsigned int ms); + static void setDownloadTimeout(unsigned int seconds); + static bool UpdateHostsFromInternet(); + static bool UpdateHostsFromLocal(); + static bool UpdateHosts(); + static std::future UpdateHostsAsync(); + +private: + static std::string m_hostFilesDirectory; + static std::string m_customFilesDirectory; + + static bool m_dextraEnabled; + static bool m_dcsEnabled; + static bool m_dplusEnabled; + static bool m_xlxEnabled; + + static std::string m_dextraUrl; + static std::string m_dcsUrl; + static std::string m_dplusUrl; + static std::string m_xlxUrl; + + static CCacheManager * m_cache; + static CTimer m_downloadTimer; + + static void loadReflectors(const std::string & directory); + static void loadReflectors(const std::string & hostFileName, DSTAR_PROTOCOL proto); +}; + +#endif \ No newline at end of file