From 25cb3edeb0060d7d418e954d1d298cd48d14b6fd Mon Sep 17 00:00:00 2001 From: Tom Early Date: Fri, 24 Mar 2023 21:21:08 -0700 Subject: [PATCH 01/28] added bootstrap string to config --- config/urfd.ini | 5 +++++ config/urfd.mk | 3 +++ reflector/Configure.cpp | 6 ++++++ reflector/JsonKeys.h | 4 ++-- reflector/Makefile | 6 ++++++ 5 files changed, 22 insertions(+), 2 deletions(-) diff --git a/config/urfd.ini b/config/urfd.ini index e476ab6..aa6a251 100644 --- a/config/urfd.ini +++ b/config/urfd.ini @@ -12,6 +12,11 @@ Country = GB Sponsor = My Home Club +# Bootstrap is the internet address of any existing DHT client. +# Usually, choose a frequented, or close, reflector if it's already a DHT +# client. If that's not possible, you can use xrf757.openquad.net +Bootstrap = xrf757.openquad.net + [IP Addresses] # Binding addresses are usually the 'any' address IPv4Binding = 0.0.0.0 diff --git a/config/urfd.mk b/config/urfd.mk index 641bc68..3e4ad1a 100644 --- a/config/urfd.mk +++ b/config/urfd.mk @@ -4,3 +4,6 @@ BINDIR = /usr/local/bin # besides making an executable that gdb can use, # this will also provide some additional log messsage debug = false + +# To disable DHT support, set DHT to false. +DHT = true diff --git a/reflector/Configure.cpp b/reflector/Configure.cpp index 35dfa3a..b3444eb 100644 --- a/reflector/Configure.cpp +++ b/reflector/Configure.cpp @@ -33,6 +33,7 @@ // ini file keywords #define JAUTOLINKMODULE "AutoLinkModule" #define JBLACKLISTPATH "BlacklistPath" +#define JBOOTSTRAP "Bootstrap" #define JBRANDMEISTER "Brandmeister" #define JCALLSIGN "Callsign" #define JCOUNTRY "Country" @@ -250,6 +251,8 @@ bool CConfigure::ReadData(const std::string &path) case ESection::names: if (0 == key.compare(JCALLSIGN)) data[g_Keys.names.callsign] = value; + else if (0 == key.compare(JBOOTSTRAP)) + data[g_Keys.names.bootstrap] = value; else if (0 == key.compare(JSYSOPEMAIL)) data[g_Keys.names.email] = value; else if (0 == key.compare(JCOUNTRY)) @@ -506,6 +509,9 @@ bool CConfigure::ReadData(const std::string &path) } } +#ifndef NO_DHT + isDefined(ErrorLevel::fatal, JNAMES, JBOOTSTRAP, g_Keys.names.bootstrap, rval); +#endif isDefined(ErrorLevel::mild, JNAMES, JSYSOPEMAIL, g_Keys.names.email, rval); isDefined(ErrorLevel::mild, JNAMES, JCOUNTRY, g_Keys.names.country, rval); isDefined(ErrorLevel::mild, JNAMES, JSPONSOR, g_Keys.names.sponsor, rval); diff --git a/reflector/JsonKeys.h b/reflector/JsonKeys.h index f604e30..29e96b5 100644 --- a/reflector/JsonKeys.h +++ b/reflector/JsonKeys.h @@ -39,8 +39,8 @@ struct SJsonKeys { struct MMDVM { const std::string port, defaultid; } mmdvm { "MMDVMPort", "mmdvmdefaultid" }; - struct NAMES { const std::string callsign, email, country, sponsor; } - names { "Callsign", "SysopEmail", "Country", "Sponsor" }; + struct NAMES { const std::string callsign, bootstrap, email, country, sponsor; } + names { "Callsign", "bootstrap", "SysopEmail", "Country", "Sponsor" }; struct IP { const std::string ipv4bind, ipv4address, ipv6bind, ipv6address, transcoder; } ip { "ipv4bind", "IPv4Address", "ipv6bind", "IPv6Address", "tcaddress" }; diff --git a/reflector/Makefile b/reflector/Makefile index c9c8272..86a9d26 100644 --- a/reflector/Makefile +++ b/reflector/Makefile @@ -34,6 +34,12 @@ endif LDFLAGS=-pthread -lcurl +ifeq ($(DHT), true) +LDFLAGS += -lopendht +else +CFLAGS += -DNO_DHT +endif + SRCS = $(wildcard *.cpp) OBJS = $(SRCS:.cpp=.o) DEPS = $(SRCS:.cpp=.d) From 09a80406c1652adcb2fb416a3f50828c45d20ad5 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Fri, 24 Mar 2023 23:51:14 -0700 Subject: [PATCH 02/28] DHT data --- reflector/Makefile | 4 +- reflector/Reflector.h | 22 +++++++++- reflector/urfd-dht-values.h | 86 +++++++++++++++++++++++++++++++++++++ 3 files changed, 109 insertions(+), 3 deletions(-) create mode 100644 reflector/urfd-dht-values.h diff --git a/reflector/Makefile b/reflector/Makefile index 86a9d26..3116642 100644 --- a/reflector/Makefile +++ b/reflector/Makefile @@ -27,9 +27,9 @@ DBUTIL = dbutil include urfd.mk ifeq ($(debug), true) -CFLAGS = -ggdb3 -DDEBUG -W -Werror -std=c++11 -MMD -MD +CFLAGS = -ggdb3 -DDEBUG -W -Werror -std=c++17 -MMD -MD else -CFLAGS = -W -Werror -std=c++11 -MMD -MD +CFLAGS = -W -Werror -std=c++17 -MMD -MD endif LDFLAGS=-pthread -lcurl diff --git a/reflector/Reflector.h b/reflector/Reflector.h index efe22ea..432ce68 100644 --- a/reflector/Reflector.h +++ b/reflector/Reflector.h @@ -27,6 +27,10 @@ #include "PacketStream.h" #include "NotificationQueue.h" +#ifndef NO_DHT +#include "urfd-dht-values.h" +#endif + //////////////////////////////////////////////////////////////////////////////////////// // define @@ -78,6 +82,15 @@ public: void OnStreamOpen(const CCallsign &); void OnStreamClose(const CCallsign &); +#ifndef NO_DHT + // Publish DHT + void PutDHTConfig(); + void PutDHTPeers(); + void PutDHTClients(); + void PutDHTUsers(); + void GetDHTConfig(const std::string &cs); +#endif + protected: // threads void RouterThread(const char); @@ -92,7 +105,6 @@ protected: void WriteXmlFile(std::ofstream &); void JsonReport(nlohmann::json &report); -protected: // identity CCallsign m_Callsign; std::string m_Modules, m_TCmodules; @@ -113,4 +125,12 @@ protected: // notifications CNotificationQueue m_Notifications; + +#ifndef NO_DHT + // Distributed Hash Table + dht::DhtRunner node; + dht::InfoHash refhash; + unsigned int peers_put_count, clients_put_count, users_put_count; +#endif + }; diff --git a/reflector/urfd-dht-values.h b/reflector/urfd-dht-values.h new file mode 100644 index 0000000..50a4438 --- /dev/null +++ b/reflector/urfd-dht-values.h @@ -0,0 +1,86 @@ +// Copyright © 2023 Thomas A. Early, N7TAE +// +// ---------------------------------------------------------------------------- +// This file is part of urfd. +// +// M17Refd 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 3 of the License, or +// (at your option) any later version. +// +// M17Refd 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 +// with this software. If not, see . +// ---------------------------------------------------------------------------- + +#pragma once + +#include + +/* HELPERS */ +template constexpr auto toUType(E enumerator) noexcept +{ + return static_cast>(enumerator); +} // Item #10 in "Effective Modern C++", by Scott Meyers, O'REILLY + +enum class EUrfdValueID : uint64_t { Config=1, Peers=2, Clients=3, Users=4 }; + +/* PEERS */ +using PeerTuple = std::tuple; +enum class EUrfdPeerFields { Callsign, Modules, ConnectTime }; +struct SUrfdPeers0 +{ + std::time_t timestamp; + unsigned int sequence; + std::list list; + + MSGPACK_DEFINE(timestamp, sequence, list) +}; + +/* CLIENTS */ +using ClientTuple = std::tuple; +enum class EUrfdClientFields { Callsign, Ip, Module, ConnectTime, LastHeardTime }; +struct SUrfdClients0 +{ + std::time_t timestamp; + unsigned int sequence; + std::list list; + + MSGPACK_DEFINE(timestamp, sequence, list) +}; + +/* USERS */ +using UserTuple = std::tuple; +enum class EUrfdUserFields { Source, Destination, Reflector, LastHeardTime }; +struct SUrfdUsers0 +{ + std::time_t timestamp; + unsigned int sequence; + std::list list; + + MSGPACK_DEFINE(timestamp, sequence, list) +}; + +/* CONFIGURATION */ +// 'SIZE' has to be last!! +enum class EUrfdPorts : unsigned { dcs, dextra, dmrplus, dplus, m17, mmdvm, nxdn, p25, urf, usrprx, usrptx, ysf, SIZE }; +enum class EUrfdAlMod : unsigned { nxdn, p25, ysf, SIZE }; +enum class EUrfdTxRx : unsigned { rx, tx, SIZE }; +enum class EUrfdRefId : unsigned { nxdn, p25, SIZE }; +struct SUrfdConfig0 +{ + std::time_t timestamp; + std::string cs, ipv4, ipv6, mods, url, email, sponsor, country, version; + std::array port; + std::array almod; + std::array ysffreq; + std::array refid; + std::unordered_map description; + bool g3enabled; + + MSGPACK_DEFINE(timestamp, cs, ipv4, ipv6, mods, url, email, sponsor, country, version, almod, ysffreq, refid, g3enabled, port, description) +}; From 9465842bf34c60bcd0a4ad671eaab581b68d5d3f Mon Sep 17 00:00:00 2001 From: Tom Early Date: Sun, 26 Mar 2023 08:34:11 -0700 Subject: [PATCH 03/28] Version 0.7.2 --- config/urfd.ini | 3 + reflector/Client.h | 2 + reflector/Configure.cpp | 4 + reflector/JsonKeys.h | 4 +- reflector/Peer.h | 1 + reflector/Reflector.cpp | 216 +++++++++++++++++++++++++++++++++++- reflector/Reflector.h | 1 + reflector/User.h | 7 ++ reflector/Users.h | 2 + reflector/urfd-dht-values.h | 14 +-- 10 files changed, 242 insertions(+), 12 deletions(-) diff --git a/config/urfd.ini b/config/urfd.ini index aa6a251..f16d228 100644 --- a/config/urfd.ini +++ b/config/urfd.ini @@ -12,6 +12,9 @@ Country = GB Sponsor = My Home Club +# DashboardURL is where your dashboard for this reflector is avaiable on the WWW. +DashboardUrl = https://YourDashboard.net + # Bootstrap is the internet address of any existing DHT client. # Usually, choose a frequented, or close, reflector if it's already a DHT # client. If that's not possible, you can use xrf757.openquad.net diff --git a/reflector/Client.h b/reflector/Client.h index 48fb022..75dd416 100644 --- a/reflector/Client.h +++ b/reflector/Client.h @@ -50,6 +50,8 @@ public: char GetCSModule(void) const { return m_Callsign.GetCSModule(); } bool HasReflectorModule(void) const { return m_ReflectorModule != ' '; } char GetReflectorModule(void) const { return m_ReflectorModule; } + std::time_t GetConnectTime(void) const { return m_ConnectTime; } + std::time_t GetLastHeardTime(void) const { return m_LastHeardTime; } // set void SetCSModule(char c) { m_Callsign.SetCSModule(c); } diff --git a/reflector/Configure.cpp b/reflector/Configure.cpp index b3444eb..9736b50 100644 --- a/reflector/Configure.cpp +++ b/reflector/Configure.cpp @@ -37,6 +37,7 @@ #define JBRANDMEISTER "Brandmeister" #define JCALLSIGN "Callsign" #define JCOUNTRY "Country" +#define JDASHBOARDURL "DashboardUrl" #define JDCS "DCS" #define JDEFAULTID "DefaultId" #define JDEFAULTRXFREQ "DefaultRxFreq" @@ -253,6 +254,8 @@ bool CConfigure::ReadData(const std::string &path) data[g_Keys.names.callsign] = value; else if (0 == key.compare(JBOOTSTRAP)) data[g_Keys.names.bootstrap] = value; + else if (0 == key.compare(JDASHBOARDURL)) + data[g_Keys.names.url] = value; else if (0 == key.compare(JSYSOPEMAIL)) data[g_Keys.names.email] = value; else if (0 == key.compare(JCOUNTRY)) @@ -512,6 +515,7 @@ bool CConfigure::ReadData(const std::string &path) #ifndef NO_DHT isDefined(ErrorLevel::fatal, JNAMES, JBOOTSTRAP, g_Keys.names.bootstrap, rval); #endif + isDefined(ErrorLevel::fatal, JNAMES, JDASHBOARDURL, g_Keys.names.url, rval); isDefined(ErrorLevel::mild, JNAMES, JSYSOPEMAIL, g_Keys.names.email, rval); isDefined(ErrorLevel::mild, JNAMES, JCOUNTRY, g_Keys.names.country, rval); isDefined(ErrorLevel::mild, JNAMES, JSPONSOR, g_Keys.names.sponsor, rval); diff --git a/reflector/JsonKeys.h b/reflector/JsonKeys.h index 29e96b5..ab19407 100644 --- a/reflector/JsonKeys.h +++ b/reflector/JsonKeys.h @@ -39,8 +39,8 @@ struct SJsonKeys { struct MMDVM { const std::string port, defaultid; } mmdvm { "MMDVMPort", "mmdvmdefaultid" }; - struct NAMES { const std::string callsign, bootstrap, email, country, sponsor; } - names { "Callsign", "bootstrap", "SysopEmail", "Country", "Sponsor" }; + struct NAMES { const std::string callsign, bootstrap, url, email, country, sponsor; } + names { "Callsign", "bootstrap", "DashboardUrl", "SysopEmail", "Country", "Sponsor" }; struct IP { const std::string ipv4bind, ipv4address, ipv6bind, ipv6address, transcoder; } ip { "ipv4bind", "IPv4Address", "ipv6bind", "IPv6Address", "tcaddress" }; diff --git a/reflector/Peer.h b/reflector/Peer.h index bc1ddf9..89c96d0 100644 --- a/reflector/Peer.h +++ b/reflector/Peer.h @@ -42,6 +42,7 @@ public: const CCallsign &GetCallsign(void) const { return m_Callsign; } const CIp &GetIp(void) const { return m_Ip; } char *GetReflectorModules(void) { return m_ReflectorModules; } + std::time_t GetConnectTime(void) const { return m_ConnectTime; } // set diff --git a/reflector/Reflector.cpp b/reflector/Reflector.cpp index fac7dd7..ec53e1d 100644 --- a/reflector/Reflector.cpp +++ b/reflector/Reflector.cpp @@ -20,8 +20,13 @@ #include #include "Global.h" -//////////////////////////////////////////////////////////////////////////////////////// -// destructor + +CReflector::CReflector() +{ +#ifndef NO_DHT + peers_put_count = clients_put_count = users_put_count = 0; +#endif +} CReflector::~CReflector() { @@ -47,10 +52,18 @@ CReflector::~CReflector() bool CReflector::Start(void) { // get config stuff - m_Callsign = CCallsign(g_Configure.GetString(g_Keys.names.callsign).c_str(), false); + const auto cs(g_Configure.GetString(g_Keys.names.callsign)); + m_Callsign.SetCallsign(cs, false); m_Modules.assign(g_Configure.GetString(g_Keys.modules.modules)); std::string tcmods(g_Configure.GetString(g_Keys.modules.tcmodules)); +#ifndef NO_DHT + // start the dht instance + refhash = dht::InfoHash::get(cs); + node.run(17171, dht::crypto::generateIdentity(cs), true); + node.bootstrap(g_Configure.GetString(g_Keys.names.bootstrap), "17171"); +#endif + // let's go! keep_running = true; @@ -114,6 +127,10 @@ bool CReflector::Start(void) std::cerr << "Cannot start the dashboard data report thread: " << e.what() << '\n'; } +#ifndef NO_DHT + PutDHTConfig(); +#endif + return false; } @@ -145,6 +162,16 @@ void CReflector::Stop(void) g_LDid.LookupClose(); g_LNid.LookupClose(); g_LYtr.LookupClose(); + +#ifndef NO_DHT + // kill the DHT + node.cancelPut(refhash, toUType(EUrfdValueID::Config)); + node.cancelPut(refhash, toUType(EUrfdValueID::Peers)); + node.cancelPut(refhash, toUType(EUrfdValueID::Clients)); + node.cancelPut(refhash, toUType(EUrfdValueID::Users)); + node.shutdown({}, true); + node.join(); +#endif } //////////////////////////////////////////////////////////////////////////////////////// @@ -512,3 +539,186 @@ void CReflector::WriteXmlFile(std::ofstream &xmlFile) ReleaseUsers(); xmlFile << "" << std::endl; } + +#ifndef NO_DHT +// DHT put() and get() +void CReflector::PutDHTPeers() +{ + const std::string cs(g_Configure.GetString(g_Keys.names.callsign)); + // load it up + SUrfdPeers0 p; + time(&p.timestamp); + p.sequence = peers_put_count++; + auto peers = GetPeers(); + for (auto pit=peers->cbegin(); pit!=peers->cend(); pit++) + { + p.list.emplace_back((*pit)->GetCallsign().GetCS(), (*pit)->GetReflectorModules(), (*pit)->GetConnectTime()); + } + ReleasePeers(); + + auto nv = std::make_shared(p); + nv->user_type.assign("urfd-peers-0"); + nv->id = toUType(EUrfdValueID::Peers); + + node.putSigned( + refhash, + nv, + [](bool success){ std::cout << "PutDHTPeers() " << (success ? "successful" : "unsuccessful") << std::endl; }, + true // permanent! + ); +} + +void CReflector::PutDHTClients() +{ + const std::string cs(g_Configure.GetString(g_Keys.names.callsign)); + SUrfdClients0 c; + time(&c.timestamp); + c.sequence = clients_put_count++; + auto clients = GetClients(); + for (auto cit=clients->cbegin(); cit!=clients->cend(); cit++) + { + c.list.emplace_back((*cit)->GetCallsign().GetCS(), std::string((*cit)->GetIp().GetAddress()), (*cit)->GetReflectorModule(), (*cit)->GetConnectTime(), (*cit)->GetLastHeardTime()); + } + ReleaseClients(); + + auto nv = std::make_shared(c); + nv->user_type.assign("urfd-clients-0"); + nv->id = toUType(EUrfdValueID::Clients); + + node.putSigned( + refhash, + nv, + [](bool success){ std::cout << "PutDHTClients() " << (success ? "successful" : "unsuccessful") << std::endl; }, + true // permanent! + ); +} + +void CReflector::PutDHTUsers() +{ + const std::string cs(g_Configure.GetString(g_Keys.names.callsign)); + SUrfdUsers0 u; + time(&u.timestamp); + u.sequence = users_put_count++; + auto users = GetUsers(); + for (auto uit=users->cbegin(); uit!=users->cend(); uit++) + { + u.list.emplace_back((*uit).GetCallsign(), std::string((*uit).GetViaNode()), (*uit).GetOnModule(), (*uit).GetViaPeer(), (*uit).GetLastHeardTime()); + } + ReleaseUsers(); + + auto nv = std::make_shared(u); + nv->user_type.assign("urfd-users-0"); + nv->id = toUType(EUrfdValueID::Users); + + node.putSigned( + refhash, + nv, + [](bool success){ std::cout << "PutDHTUsers() " << (success ? "successful" : "unsuccessful") << std::endl; }, + true // permanent! + ); +} + +void CReflector::PutDHTConfig() +{ + const std::string cs(g_Configure.GetString(g_Keys.names.callsign)); + SUrfdConfig0 cfg; + time(&cfg.timestamp); + cfg.cs.assign(cs); + cfg.ipv4.assign(g_Configure.GetString(g_Keys.ip.ipv4address)); + cfg.ipv6.assign(g_Configure.GetString(g_Keys.ip.ipv6address)); + cfg.mods.assign(g_Configure.GetString(g_Keys.modules.modules)); + cfg.tcmods.assign(g_Configure.GetString(g_Keys.modules.tcmodules)); + cfg.url.assign(g_Configure.GetString(g_Keys.names.url)); + cfg.email.assign(g_Configure.GetString(g_Keys.names.email)); + cfg.country.assign(g_Configure.GetString(g_Keys.names.country)); + cfg.sponsor.assign(g_Configure.GetString(g_Keys.names.sponsor)); + std::ostringstream ss; + ss << g_Version; + cfg.version.assign(ss.str()); + cfg.almod[toUType(EUrfdAlMod::nxdn)] = g_Configure.GetString(g_Keys.nxdn.autolinkmod).at(0); + cfg.almod[toUType(EUrfdAlMod::p25)] = g_Configure.GetString(g_Keys.p25.autolinkmod).at(0); + cfg.almod[toUType(EUrfdAlMod::ysf)] = g_Configure.GetString(g_Keys.ysf.autolinkmod).at(0); + cfg.ysffreq[toUType(EUrfdTxRx::rx)] = g_Configure.GetUnsigned(g_Keys.ysf.defaultrxfreq); + cfg.ysffreq[toUType(EUrfdTxRx::tx)] = g_Configure.GetUnsigned(g_Keys.ysf.defaulttxfreq); + cfg.refid[toUType(EUrfdRefId::nxdn)] = g_Configure.GetUnsigned(g_Keys.nxdn.reflectorid); + cfg.refid[toUType(EUrfdRefId::p25)] = g_Configure.GetUnsigned(g_Keys.p25.reflectorid); + cfg.g3enabled = g_Configure.GetBoolean(g_Keys.g3.enable); + cfg.port[toUType(EUrfdPorts::dcs)] = (uint16_t)g_Configure.GetUnsigned(g_Keys.dcs.port); + cfg.port[toUType(EUrfdPorts::dextra)] = (uint16_t)g_Configure.GetUnsigned(g_Keys.dextra.port); + cfg.port[toUType(EUrfdPorts::dmrplus)] = (uint16_t)g_Configure.GetUnsigned(g_Keys.dmrplus.port); + cfg.port[toUType(EUrfdPorts::dplus)] = (uint16_t)g_Configure.GetUnsigned(g_Keys.dplus.port); + cfg.port[toUType(EUrfdPorts::m17)] = (uint16_t)g_Configure.GetUnsigned(g_Keys.m17.port); + cfg.port[toUType(EUrfdPorts::mmdvm)] = (uint16_t)g_Configure.GetUnsigned(g_Keys.mmdvm.port); + cfg.port[toUType(EUrfdPorts::nxdn)] = (uint16_t)g_Configure.GetUnsigned(g_Keys.nxdn.port); + cfg.port[toUType(EUrfdPorts::p25)] = (uint16_t)g_Configure.GetUnsigned(g_Keys.p25.port); + cfg.port[toUType(EUrfdPorts::urf)] = (uint16_t)g_Configure.GetUnsigned(g_Keys.urf.port); + cfg.port[toUType(EUrfdPorts::ysf)] = (uint16_t)g_Configure.GetUnsigned(g_Keys.ysf.port); + for (const auto m : cfg.mods) + cfg.description[m] = g_Configure.GetString(g_Keys.modules.descriptor[m-'A']); + + auto nv = std::make_shared(cfg); + nv->user_type.assign("urfd-config-0"); + nv->id = toUType(EUrfdValueID::Config); + + node.putSigned( + refhash, + nv, + [](bool success){ std::cout << "PutDHTConfig() " << (success ? "successful" : "unsuccessful") << std::endl; }, + true + ); +} + +void CReflector::GetDHTConfig(const std::string &cs) +{ + static SUrfdConfig0 cfg; + cfg.timestamp = 0; // everytime this is called, zero the timestamp + auto item = g_IFile.FindMapItem(cs); + if (nullptr == item) + { + std::cerr << "Can't Get() for " << cs << " because it doesn't exist" << std::endl; + return; + } + std::cout << "Getting " << cs << " connection info..." << std::endl; + + // we only want the configuration section of the reflector's document + dht::Where w; + w.id(toUType(EUrfdValueID::Config)); + + node.get( + dht::InfoHash::get(cs), + [](const std::shared_ptr &v) { + if (0 == v->user_type.compare("mrefd-config-1")) + { + auto rdat = dht::Value::unpack(*v); + if (rdat.timestamp > cfg.timestamp) + { + // the time stamp is the newest so far, so put it in the static cfg struct + cfg = dht::Value::unpack(*v); + } + } + else + { + std::cerr << "Get() returned unknown user_type: '" << v->user_type << "'" << std::endl; + } + return true; // check all the values returned + }, + [](bool success) { + if (success) + { + if (cfg.timestamp) + { + // if the get() call was successful and there is a nonzero timestamp, then do the update + g_IFile.Update(cfg.cs, cfg.mods, cfg.ipv4, cfg.ipv6, cfg.port, cfg.emods); + } + } + else + { + std::cout << "Get() was unsuccessful" << std::endl; + } + }, + {}, // empty filter + w // just the configuration section + ); +} + +#endif diff --git a/reflector/Reflector.h b/reflector/Reflector.h index 432ce68..5292713 100644 --- a/reflector/Reflector.h +++ b/reflector/Reflector.h @@ -46,6 +46,7 @@ class CReflector { public: + CReflector(); // destructor ~CReflector(); diff --git a/reflector/User.h b/reflector/User.h index d5ed1d2..7207660 100644 --- a/reflector/User.h +++ b/reflector/User.h @@ -34,6 +34,13 @@ public: // destructor ~CUser() {} + // get + const std::string GetCallsign(void) const { return m_My.GetCS(); } + const std::string GetViaNode(void) const { return m_Rpt1.GetCS(); } + char GetOnModule(void) const { return m_Rpt2.GetCSModule(); } + const std::string GetViaPeer(void) const { return m_Xlx.GetCS(); } + std::time_t GetLastHeardTime(void) const { return m_LastHeardTime; } + // operation void HeardNow(void) { m_LastHeardTime = time(nullptr); } diff --git a/reflector/Users.h b/reflector/Users.h index f4e3343..85061bf 100644 --- a/reflector/Users.h +++ b/reflector/Users.h @@ -43,6 +43,8 @@ public: // pass-thru std::list::iterator begin() { return m_Users.begin(); } std::list::iterator end() { return m_Users.end(); } + std::list::const_iterator cbegin() { return m_Users.cbegin(); } + std::list::const_iterator cend() { return m_Users.cend(); } // operation void Hearing(const CCallsign &, const CCallsign &, const CCallsign &); diff --git a/reflector/urfd-dht-values.h b/reflector/urfd-dht-values.h index 50a4438..210c391 100644 --- a/reflector/urfd-dht-values.h +++ b/reflector/urfd-dht-values.h @@ -54,8 +54,8 @@ struct SUrfdClients0 }; /* USERS */ -using UserTuple = std::tuple; -enum class EUrfdUserFields { Source, Destination, Reflector, LastHeardTime }; +using UserTuple = std::tuple; +enum class EUrfdUserFields { Callsign, ViaNode, OnModule, ViaPeer, LastHeardTime }; struct SUrfdUsers0 { std::time_t timestamp; @@ -66,21 +66,21 @@ struct SUrfdUsers0 }; /* CONFIGURATION */ -// 'SIZE' has to be last!! -enum class EUrfdPorts : unsigned { dcs, dextra, dmrplus, dplus, m17, mmdvm, nxdn, p25, urf, usrprx, usrptx, ysf, SIZE }; +// 'SIZE' has to be last for these scoped enums +enum class EUrfdPorts : unsigned { dcs, dextra, dmrplus, dplus, m17, mmdvm, nxdn, p25, urf, ysf, SIZE }; enum class EUrfdAlMod : unsigned { nxdn, p25, ysf, SIZE }; enum class EUrfdTxRx : unsigned { rx, tx, SIZE }; enum class EUrfdRefId : unsigned { nxdn, p25, SIZE }; struct SUrfdConfig0 { std::time_t timestamp; - std::string cs, ipv4, ipv6, mods, url, email, sponsor, country, version; - std::array port; + std::string cs, ipv4, ipv6, mods, tcmods, url, email, sponsor, country, version; + std::array port; std::array almod; std::array ysffreq; std::array refid; std::unordered_map description; bool g3enabled; - MSGPACK_DEFINE(timestamp, cs, ipv4, ipv6, mods, url, email, sponsor, country, version, almod, ysffreq, refid, g3enabled, port, description) + MSGPACK_DEFINE(timestamp, cs, ipv4, ipv6, mods, tcmods, url, email, sponsor, country, version, almod, ysffreq, refid, g3enabled, port, description) }; From 1ed0ab297134f2feec50e34f79687b2a3122929c Mon Sep 17 00:00:00 2001 From: Tom Early Date: Thu, 30 Mar 2023 13:35:37 -0700 Subject: [PATCH 04/28] Rewrote blacklist, whitelist and interlink classes --- config/urfd.interlink | 19 ++- reflector/BMProtocol.cpp | 22 ++- reflector/BlackWhiteSet.cpp | 193 ++++++++++++++++++++++++ reflector/BlackWhiteSet.h | 61 ++++++++ reflector/Callsign.cpp | 20 +-- reflector/Callsign.h | 20 ++- reflector/CallsignList.cpp | 223 ---------------------------- reflector/CallsignList.h | 67 --------- reflector/CallsignListItem.cpp | 136 ----------------- reflector/CallsignListItem.h | 65 --------- reflector/GateKeeper.cpp | 77 +++++----- reflector/GateKeeper.h | 22 ++- reflector/InterlinkMap.cpp | 258 +++++++++++++++++++++++++++++++++ reflector/InterlinkMap.h | 79 ++++++++++ reflector/InterlinkMapItem.cpp | 143 ++++++++++++++++++ reflector/InterlinkMapItem.h | 74 ++++++++++ reflector/Lookup.h | 20 --- reflector/PeerCallsignList.cpp | 84 ----------- reflector/PeerCallsignList.h | 38 ----- reflector/Reflector.cpp | 21 +-- reflector/URFProtocol.cpp | 28 ++-- 21 files changed, 927 insertions(+), 743 deletions(-) create mode 100644 reflector/BlackWhiteSet.cpp create mode 100644 reflector/BlackWhiteSet.h delete mode 100644 reflector/CallsignList.cpp delete mode 100644 reflector/CallsignList.h delete mode 100644 reflector/CallsignListItem.cpp delete mode 100644 reflector/CallsignListItem.h create mode 100644 reflector/InterlinkMap.cpp create mode 100644 reflector/InterlinkMap.h create mode 100644 reflector/InterlinkMapItem.cpp create mode 100644 reflector/InterlinkMapItem.h delete mode 100644 reflector/PeerCallsignList.cpp delete mode 100644 reflector/PeerCallsignList.h diff --git a/config/urfd.interlink b/config/urfd.interlink index 3232cc2..cdb7213 100644 --- a/config/urfd.interlink +++ b/config/urfd.interlink @@ -1,14 +1,17 @@ ############################################################################## # URFD interlink file # -# one line per entry -# each entry specifies a remote XLX or XRF to peer with +# One line per entry. +# Each entry specifies a remote URF to peer with. +# If no Port is specified, 17000 will be used. +# If DHT is enabled and the target is also DHT-enabled, then you only +# need to specify the URF-Callsign and the Shared-Modules # format: -# -# example: -# URF270 158.64.26.132 ACD -# -# note: the remote URFD must list this in its interlink file -# for the link to be established +# +# examples: +# URF270 158.64.26.132 EF +# URF280 ABC # +# note: The remote URFD must list this in its interlink file +# for the link to be established. ############################################################################# diff --git a/reflector/BMProtocol.cpp b/reflector/BMProtocol.cpp index f16752d..bc0663a 100644 --- a/reflector/BMProtocol.cpp +++ b/reflector/BMProtocol.cpp @@ -288,16 +288,16 @@ void CBMProtocol::HandlePeerLinks(void) CBuffer buffer; // get the list of peers - CPeerCallsignList *list = g_GateKeeper.GetPeerList(); + auto ilmap = g_GateKeeper.GetInterlinkMap(); CPeers *peers = g_Reflector.GetPeers(); // check if all our connected peers are still listed by gatekeeper // if not, disconnect auto pit = peers->begin(); std::shared_ptrpeer = nullptr; - while ( (peer = peers->FindNextPeer(EProtocol::bm, pit)) != nullptr ) + while ( nullptr != (peer = peers->FindNextPeer(EProtocol::bm, pit)) ) { - if ( list->FindListItem(peer->GetCallsign()) == nullptr ) + if ( nullptr == ilmap->FindMapItem(peer->GetCallsign().GetBase()) ) { // send disconnect packet EncodeDisconnectPacket(&buffer); @@ -310,23 +310,21 @@ void CBMProtocol::HandlePeerLinks(void) // check if all ours peers listed by gatekeeper are connected // if not, connect or reconnect - for ( auto it=list->begin(); it!=list->end(); it++ ) + for ( auto it=ilmap->begin(); it!=ilmap->end(); it++ ) { - CCallsign cs = it->GetCallsign(); - if (cs.HasSameCallsignWithWildcard(CCallsign("BM*")) && (nullptr==peers->FindPeer(cs, EProtocol::bm))) + const auto cs = it->first; + if (0 == cs.substr(0, 2).compare("BM") && (nullptr==peers->FindPeer(CCallsign(cs), EProtocol::bm))) { - // resolve again peer's IP in case it's a dynamic IP - it->ResolveIp(); // send connect packet to re-initiate peer link - EncodeConnectPacket(&buffer, it->GetModules()); - Send(buffer, it->GetIp(), m_Port); - std::cout << "Sending connect packet to BM peer " << cs << " @ " << it->GetIp() << " for modules " << it->GetModules() << std::endl; + EncodeConnectPacket(&buffer, it->second.GetModules().c_str()); + Send(buffer, it->second.GetIp(), m_Port); + std::cout << "Sending connect packet to BM peer " << cs << " @ " << it->second.GetIp() << " for modules " << it->second.GetModules() << std::endl; } } // done g_Reflector.ReleasePeers(); - g_GateKeeper.ReleasePeerList(); + g_GateKeeper.ReleaseInterlinkMap(); } diff --git a/reflector/BlackWhiteSet.cpp b/reflector/BlackWhiteSet.cpp new file mode 100644 index 0000000..911df48 --- /dev/null +++ b/reflector/BlackWhiteSet.cpp @@ -0,0 +1,193 @@ +// +// ccallsignlist.cpp +// m17ref +// +// Created by Jean-Luc Deltombe (LX3JL) on 30/12/2015. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// Copyright © 2020 Thomas A. Early, N7TAE +// +// ---------------------------------------------------------------------------- +// This file is part of m17ref. +// +// m17ref 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 3 of the License, or +// (at your option) any later version. +// +// m17ref 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 +// with this software. If not, see . +// ---------------------------------------------------------------------------- + +#include +#include +#include +#include +#include + +#include "BlackWhiteSet.h" + +//////////////////////////////////////////////////////////////////////////////////////// +// file io + +bool CBlackWhiteSet::LoadFromFile(const std::string &filename) +{ + bool ok = false; + char sz[256]; + + // and load + std::ifstream file(filename); + if ( file.is_open() ) + { + Lock(); + + // empty list + m_Callsigns.clear(); + // fill with file content + while ( file.getline(sz, sizeof(sz)).good() ) + { + // remove leading & trailing spaces + char *szt = TrimWhiteSpaces(sz); + + // crack it + if ( (strlen(szt) > 0) && (szt[0] != '#') ) + { + // 1st token is callsign + if ( (szt = strtok(szt, " ,\t")) != nullptr ) + { + std::string cs(ToUpper(szt)); + if (m_Callsigns.end() == m_Callsigns.find(cs)) + { + m_Callsigns.insert(cs); + } + else + { + std::cerr << "Duplicate ," << cs << " in " << filename << " will be ignored." << std::endl; + } + } + } + } + // close file + file.close(); + + // keep file path + m_Filename = filename; + + // update time + GetLastModTime(&m_LastModTime); + + // and done + Unlock(); + ok = true; + std::cout << "Gatekeeper loaded " << m_Callsigns.size() << " lines from " << filename << std::endl; + } + else + { + std::cout << "Gatekeeper cannot find " << filename << std::endl; + } + + return ok; +} + +bool CBlackWhiteSet::ReloadFromFile(void) +{ + bool ok = false; + + if ( m_Filename.empty() ) + { + ok = LoadFromFile(m_Filename); + } + return ok; +} + +bool CBlackWhiteSet::NeedReload(void) +{ + bool needReload = false; + + time_t time; + if ( GetLastModTime(&time) ) + { + needReload = time != m_LastModTime; + } + return needReload; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// compare + +bool CBlackWhiteSet::IsMatched(const std::string &cs) const +{ + for ( const auto &item : m_Callsigns ) + { + auto pos = item.find('*'); + switch (pos) + { + case 0: + return true; + case std::string::npos: + if (0 == item.compare(cs)) + return true; + break; + default: + if (0 == item.compare(0, pos, cs, 0, pos)) + return true; + break; + } + } + return false; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// helpers + +char *CBlackWhiteSet::TrimWhiteSpaces(char *str) +{ + char *end; + + // Trim leading space & tabs + while((*str == ' ') || (*str == '\t')) str++; + + // All spaces? + if(*str == 0) + return str; + + // Trim trailing space, tab or lf + end = str + ::strlen(str) - 1; + while((end > str) && ((*end == ' ') || (*end == '\t') || (*end == '\r'))) end--; + + // Write new null terminator + *(end+1) = 0; + + return str; +} + +bool CBlackWhiteSet::GetLastModTime(time_t *time) +{ + bool ok = false; + + if ( !m_Filename.empty() ) + { + struct stat fileStat; + if( ::stat(m_Filename.c_str(), &fileStat) != -1 ) + { + *time = fileStat.st_mtime; + ok = true; + } + } + return ok; +} + +char *CBlackWhiteSet::ToUpper(char *str) +{ + constexpr auto diff = 'a' - 'A'; + for (char *p=str; *p; p++) + { + if (*p >= 'a' && *p <= 'z') + *p -= diff; + } + return str; +} diff --git a/reflector/BlackWhiteSet.h b/reflector/BlackWhiteSet.h new file mode 100644 index 0000000..3ec0421 --- /dev/null +++ b/reflector/BlackWhiteSet.h @@ -0,0 +1,61 @@ +// +// Copyright © 2020 Thomas A. Early, N7TAE +// +// ---------------------------------------------------------------------------- +// This file is part of m17ref. +// +// m17ref 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 3 of the License, or +// (at your option) any later version. +// +// m17ref 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 +// with this software. If not, see . +// ---------------------------------------------------------------------------- + +#pragma once + +#include +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////// +// class + +class CBlackWhiteSet +{ +public: + // constructor + CBlackWhiteSet() : m_Filename(nullptr), m_LastModTime(0) {} + + // locks + void Lock(void) const { m_Mutex.lock(); } + void Unlock(void) const { m_Mutex.unlock(); } + + // file io + bool LoadFromFile(const std::string &filename); + bool ReloadFromFile(void); + bool NeedReload(void); + + // pass-thru + bool empty() const { return m_Callsigns.empty(); } + + // compare + bool IsMatched(const std::string &) const; + +protected: + bool GetLastModTime(time_t *); + char *TrimWhiteSpaces(char *); + char *ToUpper(char *str); + + // data + mutable std::mutex m_Mutex; + std::string m_Filename; + time_t m_LastModTime; + std::set m_Callsigns; +}; diff --git a/reflector/Callsign.cpp b/reflector/Callsign.cpp index 765b6cb..84184b8 100644 --- a/reflector/Callsign.cpp +++ b/reflector/Callsign.cpp @@ -349,6 +349,16 @@ UCallsign CCallsign::GetKey() const return rval; } +std::string CCallsign::GetBase() const +{ + auto u = GetKey(); + std::string rval(u.c, CALLSIGN_LEN); + auto pos = rval.find(' '); + if (std::string::npos == rval.find(' ')) + rval.resize(pos); + return rval; +} + void CCallsign::GetCallsign(uint8_t *buffer) const { memcpy(buffer, m_Callsign.c, CALLSIGN_LEN); @@ -404,16 +414,6 @@ bool CCallsign::HasSameCallsignWithWildcard(const CCallsign &cs) const return same; } -bool CCallsign::HasLowerCallsign(const CCallsign &cs) const -{ - return (memcmp(m_Callsign.c, cs.m_Callsign.c, CALLSIGN_LEN) < 0); -} - -bool CCallsign::HasSameModule(const CCallsign &Callsign) const -{ - return (m_Module == Callsign.m_Module); -} - //////////////////////////////////////////////////////////////////////////////////////// // operators diff --git a/reflector/Callsign.h b/reflector/Callsign.h index 49bb6d9..4ad3c29 100644 --- a/reflector/Callsign.h +++ b/reflector/Callsign.h @@ -39,6 +39,23 @@ union USuffix uint32_t u; }; +// functions for unordered containers +struct CCallsignHash +{ + std::size_t operator() (const UCallsign &ucs) const + { + std::hash hash; + return hash(ucs.l); + } +}; + +struct CCallsignEqual +{ + bool operator() (const UCallsign &ucs1, const UCallsign &ucs2) const + { + return ucs1.l == ucs2.l; + } +}; //////////////////////////////////////////////////////////////////////////////////////// // class @@ -73,6 +90,7 @@ public: // get UCallsign GetKey() const; + std::string GetBase() const; void GetCallsign(uint8_t *) const; void GetCallsignString(char *) const; const std::string GetCS() const; @@ -84,8 +102,6 @@ public: // compare bool HasSameCallsign(const CCallsign &) const; bool HasSameCallsignWithWildcard(const CCallsign &) const; - bool HasLowerCallsign(const CCallsign &) const; - bool HasSameModule(const CCallsign &) const; // operators CCallsign &operator = (const CCallsign &cs); diff --git a/reflector/CallsignList.cpp b/reflector/CallsignList.cpp deleted file mode 100644 index 954bb5a..0000000 --- a/reflector/CallsignList.cpp +++ /dev/null @@ -1,223 +0,0 @@ -// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. - -// urfd -- The universal reflector -// Copyright © 2021 Thomas A. Early N7TAE -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 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, see . - -#include -#include -#include -#include - -#include "CallsignList.h" - -//////////////////////////////////////////////////////////////////////////////////////// -// constructor - -CCallsignList::CCallsignList() -{ - memset(&m_LastModTime, 0, sizeof(time_t)); -} - -//////////////////////////////////////////////////////////////////////////////////////// -// file io - -bool CCallsignList::LoadFromFile(const std::string &filename) -{ - bool ok = false; - char sz[256]; - char szStar[2] = "*"; - - // and load - std::ifstream file (filename); - if ( file.is_open() ) - { - Lock(); - - // empty list - m_Callsigns.clear(); - // fill with file content - while ( file.getline(sz, sizeof(sz)).good() ) - { - // remove leading & trailing spaces - char *szt = TrimWhiteSpaces(sz); - - // crack it - if ( (::strlen(szt) > 0) && (szt[0] != '#') ) - { - // 1st token is callsign - if ( (szt = ::strtok(szt, " ,\t")) != nullptr ) - { - CCallsign callsign(szt); - // 2nd token is modules list - szt = ::strtok(nullptr, " ,\t"); - // if token absent, use wildcard - if ( szt == nullptr ) - { - szt = szStar; - } - // and add to list - m_Callsigns.push_back(CCallsignListItem(callsign, CIp(), szt)); - } - } - } - // close file - file.close(); - - // keep file path - m_Filename.assign(filename); - - // update time - GetLastModTime(&m_LastModTime); - - // and done - Unlock(); - ok = true; - std::cout << "Gatekeeper loaded " << m_Callsigns.size() << " lines from " << filename << std::endl; - } - else - { - std::cout << "Gatekeeper cannot find " << filename << std::endl; - } - - return ok; -} - -bool CCallsignList::ReloadFromFile(void) -{ - bool ok = false; - - if (! m_Filename.empty()) - { - ok = LoadFromFile(m_Filename); - } - return ok; -} - -bool CCallsignList::NeedReload(void) -{ - bool needReload = false; - - time_t time; - if ( GetLastModTime(&time) ) - { - needReload = time != m_LastModTime; - } - return needReload; -} - -//////////////////////////////////////////////////////////////////////////////////////// -// compare - -bool CCallsignList::IsCallsignListedWithWildcard(const CCallsign &callsign) const -{ - for ( const auto &item : m_Callsigns ) - { - if (item.HasSameCallsignWithWildcard(callsign)) - return true; - } - - return false; -} - -bool CCallsignList::IsCallsignListedWithWildcard(const CCallsign &callsign, char module) const -{ - for ( const auto &item : m_Callsigns ) - { - if (item.HasSameCallsignWithWildcard(callsign) && ((module == ' ') || item.HasModuleListed(module)) ) - return true; - } - - return false; -} - -bool CCallsignList::IsCallsignListed(const CCallsign &callsign, char module) const -{ - for ( const auto &item : m_Callsigns ) - { - if (item.HasSameCallsign(callsign) && item.HasModuleListed(module)) - return true; - } - - return false; -} - -bool CCallsignList::IsCallsignListed(const CCallsign &callsign, char *modules) const -{ - for ( const auto &item : m_Callsigns ) - { - if (item.HasSameCallsign(callsign) && item.CheckListedModules(modules)) - return true; - } - - return false; -} - -//////////////////////////////////////////////////////////////////////////////////////// -// find - -CCallsignListItem *CCallsignList::FindListItem(const CCallsign &Callsign) -{ - for ( auto &item : m_Callsigns ) - { - if ( item.GetCallsign().HasSameCallsign(Callsign) ) - { - return &item; - } - } - - return nullptr; - -} - -//////////////////////////////////////////////////////////////////////////////////////// -// helpers - -char *CCallsignList::TrimWhiteSpaces(char *str) -{ - char *end; - - // Trim leading space & tabs - while((*str == ' ') || (*str == '\t')) str++; - - // All spaces? - if(*str == 0) - return str; - - // Trim trailing space, tab or lf - end = str + ::strlen(str) - 1; - while((end > str) && ((*end == ' ') || (*end == '\t') || (*end == '\r'))) end--; - - // Write new null terminator - *(end+1) = 0; - - return str; -} - -bool CCallsignList::GetLastModTime(time_t *time) -{ - bool ok = false; - - if (! m_Filename.empty()) - { - struct stat fileStat; - if( ::stat(m_Filename.c_str(), &fileStat) != -1 ) - { - *time = fileStat.st_mtime; - ok = true; - } - } - return ok; -} diff --git a/reflector/CallsignList.h b/reflector/CallsignList.h deleted file mode 100644 index 3a221a1..0000000 --- a/reflector/CallsignList.h +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. - -// urfd -- The universal reflector -// Copyright © 2021 Thomas A. Early N7TAE -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 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, see . - -#pragma once - -#include -#include - -#include "CallsignListItem.h" - -//////////////////////////////////////////////////////////////////////////////////////// -// class - -class CCallsignList -{ -public: - // constructor - CCallsignList(); - - // locks - void Lock(void) const { m_Mutex.lock(); } - void Unlock(void) const { m_Mutex.unlock(); } - - // file io - virtual bool LoadFromFile(const std::string &str); - bool ReloadFromFile(void); - bool NeedReload(void); - - // compare - bool IsCallsignListedWithWildcard(const CCallsign &) const; - bool IsCallsignListedWithWildcard(const CCallsign &, char) const; - bool IsCallsignListed(const CCallsign &, char) const; - bool IsCallsignListed(const CCallsign &, char*) const; - - // pass-thru - bool empty() const { return m_Callsigns.empty(); } - std::list::iterator begin() { return m_Callsigns.begin(); } - std::list::iterator end() { return m_Callsigns.end(); } - - // find - CCallsignListItem *FindListItem(const CCallsign &); - -protected: - bool GetLastModTime(time_t *); - char *TrimWhiteSpaces(char *); - - // data - mutable std::mutex m_Mutex; - std::string m_Filename; - time_t m_LastModTime; - std::list m_Callsigns; -}; diff --git a/reflector/CallsignListItem.cpp b/reflector/CallsignListItem.cpp deleted file mode 100644 index 40328bf..0000000 --- a/reflector/CallsignListItem.cpp +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. - -// urfd -- The universal reflector -// Copyright © 2021 Thomas A. Early N7TAE -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 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, see . - -#include - -#include "Global.h" - -#include "CallsignListItem.h" - -//////////////////////////////////////////////////////////////////////////////////////// -// constructor - -CCallsignListItem::CCallsignListItem() -{ - memset(m_Modules, 0, sizeof(m_Modules)); - memset(m_szUrl, 0, sizeof(m_szUrl)); -} - -CCallsignListItem::CCallsignListItem(const CCallsign &callsign, const CIp &ip, const char *modules) -{ - const std::string mods(g_Configure.GetString(g_Keys.modules.modules)); - m_Callsign = callsign; - memset(m_szUrl, 0, sizeof(m_szUrl)); - m_Ip = ip; - if ( modules != nullptr ) - { - memset(m_Modules, 0, sizeof(m_Modules)); - if ( modules[0] == '*' ) - { - memcpy(m_Modules, mods.c_str(), mods.size()); - } - else - { - int n = MIN(::strlen(modules), sizeof(m_Modules)-1); - for (int i=0, j=0; i. - -#pragma once - - -#include "Callsign.h" -#include "IP.h" - -//////////////////////////////////////////////////////////////////////////////////////// -// define - -#define URL_MAXLEN 256 - -//////////////////////////////////////////////////////////////////////////////////////// -// class - -class CCallsignListItem -{ -public: - // constructor - CCallsignListItem(); - CCallsignListItem(const CCallsign &, const CIp &, const char *); - CCallsignListItem(const CCallsign &, const char *, const char *); - CCallsignListItem(const CCallsignListItem &); - - // destructor - virtual ~CCallsignListItem() {} - - // compare - bool HasSameCallsign(const CCallsign &) const; - bool HasSameCallsignWithWildcard(const CCallsign &) const; - bool HasModuleListed(char) const; - bool CheckListedModules(char*) const; - - // get - const CCallsign &GetCallsign(void) const { return m_Callsign; } - const CIp &GetIp(void) const { return m_Ip; } - const char *GetModules(void) { return m_Modules; } - - // update - void ResolveIp(void) { m_Ip = CIp(m_szUrl); } - -protected: - // data - CCallsign m_Callsign; - char m_szUrl[URL_MAXLEN+1]; - CIp m_Ip; - char m_Modules[27]; -}; diff --git a/reflector/GateKeeper.cpp b/reflector/GateKeeper.cpp index 8afb9f3..b663592 100644 --- a/reflector/GateKeeper.cpp +++ b/reflector/GateKeeper.cpp @@ -44,9 +44,9 @@ bool CGateKeeper::Init(void) { // load lists from files - m_NodeWhiteList.LoadFromFile(g_Configure.GetString(g_Keys.files.white)); - m_NodeBlackList.LoadFromFile(g_Configure.GetString(g_Keys.files.black)); - m_PeerList.LoadFromFile(g_Configure.GetString(g_Keys.files.interlink)); + m_WhiteSet.LoadFromFile(g_Configure.GetString(g_Keys.files.white)); + m_BlackSet.LoadFromFile(g_Configure.GetString(g_Keys.files.black)); + m_InterlinkMap.LoadFromFile(g_Configure.GetString(g_Keys.files.interlink)); // reset run flag keep_running = true; @@ -72,7 +72,8 @@ void CGateKeeper::Close(void) bool CGateKeeper::MayLink(const CCallsign &callsign, const CIp &ip, EProtocol protocol, char *modules) const { - bool ok = true; + bool ok; + const std::string base(callsign.GetBase()); switch (protocol) { @@ -88,26 +89,24 @@ bool CGateKeeper::MayLink(const CCallsign &callsign, const CIp &ip, EProtocol pr case EProtocol::usrp: case EProtocol::nxdn: case EProtocol::g3: - // first check is IP & callsigned listed OK - ok &= IsNodeListedOk(callsign, ip); - // todo: then apply any protocol specific authorisation for the operation + // is callsign listed OK + ok = IsNodeListedOk(base); break; // URF and BM interlinks case EProtocol::bm: case EProtocol::urf: - ok &= IsPeerListedOk(callsign, ip, modules); + ok = IsPeerListedOk(base, ip, modules); break; // unsupported - case EProtocol::none: default: ok = false; break; } // report - if ( !ok ) + if ( ! ok ) { std::cout << "Gatekeeper blocking linking of " << callsign << " @ " << ip << " using protocol " << ProtocolName(protocol) << std::endl; } @@ -118,7 +117,9 @@ bool CGateKeeper::MayLink(const CCallsign &callsign, const CIp &ip, EProtocol pr bool CGateKeeper::MayTransmit(const CCallsign &callsign, const CIp &ip, const EProtocol protocol, char module) const { - bool ok = true; + bool ok; + + const std::string base(callsign.GetBase()); switch (protocol) { @@ -136,14 +137,14 @@ bool CGateKeeper::MayTransmit(const CCallsign &callsign, const CIp &ip, const EP case EProtocol::usrp: case EProtocol::g3: // first check is IP & callsigned listed OK - ok = ok && IsNodeListedOk(callsign, ip, module); + ok = IsNodeListedOk(base); // todo: then apply any protocol specific authorisation for the operation break; // URF interlinks case EProtocol::urf: case EProtocol::bm: - ok = ok && IsPeerListedOk(callsign, ip, module); + ok = IsPeerListedOk(base, module); break; // unsupported @@ -175,17 +176,17 @@ void CGateKeeper::Thread() std::this_thread::sleep_for(std::chrono::milliseconds(2000)); // have lists files changed ? - if ( m_NodeWhiteList.NeedReload() ) + if ( m_WhiteSet.NeedReload() ) { - m_NodeWhiteList.ReloadFromFile(); + m_WhiteSet.ReloadFromFile(); } - if ( m_NodeBlackList.NeedReload() ) + if ( m_BlackSet.NeedReload() ) { - m_NodeBlackList.ReloadFromFile(); + m_BlackSet.ReloadFromFile(); } - if ( m_PeerList.NeedReload() ) + if ( m_InterlinkMap.NeedReload() ) { - m_PeerList.ReloadFromFile(); + m_InterlinkMap.ReloadFromFile(); } } } @@ -193,30 +194,28 @@ void CGateKeeper::Thread() //////////////////////////////////////////////////////////////////////////////////////// // operation helpers -bool CGateKeeper::IsNodeListedOk(const CCallsign &callsign, const CIp &ip, char module) const +bool CGateKeeper::IsNodeListedOk(const std::string &callsign) const { bool ok = true; - // first check IP - // next, check callsign if ( ok ) { // first check if callsign is in white list // note if white list is empty, everybody is authorized - m_NodeWhiteList.Lock(); - if ( !m_NodeWhiteList.empty() ) + m_WhiteSet.Lock(); + if ( ! m_WhiteSet.empty() ) { - ok = m_NodeWhiteList.IsCallsignListedWithWildcard(callsign, module); + ok = m_WhiteSet.IsMatched(callsign); } - m_NodeWhiteList.Unlock(); + m_WhiteSet.Unlock(); // then check if not blacklisted if (ok) { - m_NodeBlackList.Lock(); - ok = !m_NodeBlackList.IsCallsignListedWithWildcard(callsign); - m_NodeBlackList.Unlock(); + m_BlackSet.Lock(); + ok = ! m_BlackSet.IsMatched(callsign); + m_BlackSet.Unlock(); } } @@ -225,7 +224,7 @@ bool CGateKeeper::IsNodeListedOk(const CCallsign &callsign, const CIp &ip, char } -bool CGateKeeper::IsPeerListedOk(const CCallsign &callsign, const CIp &ip, char module) const +bool CGateKeeper::IsPeerListedOk(const std::string &callsign, char module) const { bool ok = true; @@ -235,19 +234,19 @@ bool CGateKeeper::IsPeerListedOk(const CCallsign &callsign, const CIp &ip, char if ( ok ) { // look for an exact match in the list - m_PeerList.Lock(); - if ( !m_PeerList.empty() ) + m_InterlinkMap.Lock(); + if ( !m_InterlinkMap.empty() ) { - ok = m_PeerList.IsCallsignListed(callsign, module); + ok = m_InterlinkMap.IsCallsignListed(callsign, module); } - m_PeerList.Unlock(); + m_InterlinkMap.Unlock(); } // done return ok; } -bool CGateKeeper::IsPeerListedOk(const CCallsign &callsign, const CIp &ip, char *modules) const +bool CGateKeeper::IsPeerListedOk(const std::string &callsign, const CIp &ip, char *modules) const { bool ok = true; @@ -257,12 +256,12 @@ bool CGateKeeper::IsPeerListedOk(const CCallsign &callsign, const CIp &ip, char if ( ok ) { // look for an exact match in the list - m_PeerList.Lock(); - if ( !m_PeerList.empty() ) + m_InterlinkMap.Lock(); + if ( ! m_InterlinkMap.empty() ) { - ok = m_PeerList.IsCallsignListed(callsign, modules); + ok = m_InterlinkMap.IsCallsignListed(callsign, ip, modules); } - m_PeerList.Unlock(); + m_InterlinkMap.Unlock(); } // done diff --git a/reflector/GateKeeper.h b/reflector/GateKeeper.h index 4b5814d..619dd86 100644 --- a/reflector/GateKeeper.h +++ b/reflector/GateKeeper.h @@ -22,8 +22,8 @@ #include "Defines.h" #include "Callsign.h" #include "IP.h" -#include "CallsignList.h" -#include "PeerCallsignList.h" +#include "BlackWhiteSet.h" +#include "InterlinkMap.h" //////////////////////////////////////////////////////////////////////////////////////// // class @@ -41,29 +41,27 @@ public: bool Init(void); void Close(void); + CInterlinkMap *GetInterlinkMap(void) { m_InterlinkMap.Lock(); return &m_InterlinkMap; } + void ReleaseInterlinkMap(void) { m_InterlinkMap.Unlock(); } + // authorizations bool MayLink(const CCallsign &, const CIp &, const EProtocol, char * = nullptr) const; bool MayTransmit(const CCallsign &, const CIp &, EProtocol = EProtocol::any, char = ' ') const; - // peer list handeling - CPeerCallsignList *GetPeerList(void) { m_PeerList.Lock(); return &m_PeerList; } - void ReleasePeerList(void) { m_PeerList.Unlock(); } - protected: // thread void Thread(); // operation helpers - bool IsNodeListedOk(const CCallsign &, const CIp &, char = ' ') const; - bool IsPeerListedOk(const CCallsign &, const CIp &, char) const; - bool IsPeerListedOk(const CCallsign &, const CIp &, char *) const; + bool IsNodeListedOk(const std::string &) const; + bool IsPeerListedOk(const std::string &, char) const; + bool IsPeerListedOk(const std::string &, const CIp &, char *) const; const std::string ProtocolName(EProtocol) const; protected: // data - CCallsignList m_NodeWhiteList; - CCallsignList m_NodeBlackList; - CPeerCallsignList m_PeerList; + CBlackWhiteSet m_WhiteSet, m_BlackSet; + CInterlinkMap m_InterlinkMap; // thread std::atomic keep_running; diff --git a/reflector/InterlinkMap.cpp b/reflector/InterlinkMap.cpp new file mode 100644 index 0000000..8466f90 --- /dev/null +++ b/reflector/InterlinkMap.cpp @@ -0,0 +1,258 @@ +// +// ccallsignlist.cpp +// m17ref +// +// Created by Jean-Luc Deltombe (LX3JL) on 30/12/2015. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// Copyright © 2020,2022 Thomas A. Early, N7TAE +// +// ---------------------------------------------------------------------------- +// This file is part of m17ref. +// +// m17ref 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 3 of the License, or +// (at your option) any later version. +// +// m17ref 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 +// with this software. If not, see . +// ---------------------------------------------------------------------------- + +#include +#include +#include +#include + +#include "Global.h" +#include "InterlinkMap.h" + +CInterlinkMap::CInterlinkMap() +{ + m_Filename = nullptr; + ::memset(&m_LastModTime, 0, sizeof(time_t)); +} + +bool CInterlinkMap::LoadFromFile(const std::string &filename) +{ + bool ok = false; + char line[256]; + + // and load + std::ifstream file(filename); + if ( file.is_open() ) + { + Lock(); + + // empty list + m_InterlinkMap.clear(); + // fill with file content + while ( file.getline(line, sizeof(line)).good() ) + { + char *token[4]; + // remove leading & trailing spaces + token[0] = ToUpper(TrimWhiteSpaces(line)); + // crack it + if ( (strlen(token[0]) > 0) && (token[0][0] != '#') ) + { + const char *delim = " \t\r"; + // 1st token is callsign + if ( (token[0] = strtok(token[0], delim)) != nullptr ) + { + if (strcmp(token[0], g_Configure.GetString(g_Keys.names.callsign).c_str())) + { + if (m_InterlinkMap.end() == m_InterlinkMap.find(token[0])) + { + CCallsign callsign(token[0]); + // read remaining tokens + for (int i=1; i<4; i++) + { + token[i] = strtok(nullptr, delim); + } + + if (token[2]) + { + int port = 17000; + if (token[3]) + { + port = std::atoi(token[2]); + if (port < 1024 || port > 49000) + { + std::cout << token[0] << " Port " << port << " is out of range, resetting to 17000." << std::endl; + port = 17000; + } + m_InterlinkMap[token[0]] = CInterlinkMapItem(token[1], token[3], (uint16_t)port); + } + else + { + m_InterlinkMap[token[0]] = CInterlinkMapItem(token[1], token[2], (uint16_t)port); + } + } +#ifndef NO_DHT + else if (token[1]) + { + m_InterlinkMap[token[0]] = CInterlinkMapItem(token[1]); + } +#endif + else + { + std::cout << token[0] << " has insufficient parameters!" << std::endl; + } + } + else + { + std::cerr << "Duplicate found: " << token[0] << " in " << filename << std::endl; + } + } + else + { + std::cerr << "Self linking is not allowed! You cannot use " << token[0] << " in " << filename << std::endl; + } + } + } + } + // close file + file.close(); + + // keep file path + m_Filename = filename; + + // update time + GetLastModTime(&m_LastModTime); + + // and done + Unlock(); + ok = true; + std::cout << "Gatekeeper loaded " << m_InterlinkMap.size() << " lines from " << filename << std::endl; + } + else + { + std::cout << "Gatekeeper cannot find " << filename << std::endl; + } + + return ok; +} + +bool CInterlinkMap::ReloadFromFile(void) +{ + bool ok = false; + + if ( ! m_Filename.empty() ) + { + ok = LoadFromFile(m_Filename); + } + return ok; +} + +bool CInterlinkMap::NeedReload(void) +{ + bool needReload = false; + + time_t time; + if ( GetLastModTime(&time) ) + { + needReload = time != m_LastModTime; + } + return needReload; +} + +bool CInterlinkMap::IsCallsignListed(const std::string &callsign, char module) const +{ + const auto item = m_InterlinkMap.find(callsign); + if (m_InterlinkMap.cend() == item) + return false; + else + return item->second.HasModuleListed(module); +} + +bool CInterlinkMap::IsCallsignListed(const std::string &callsign, const CIp &ip, const char *modules) const +{ + const auto item = m_InterlinkMap.find(callsign); + if (m_InterlinkMap.cend() != item) + { + if ( item->second.CheckListedModules(modules) ) + { + if ( ip == item->second.GetIp() ) + { + return true; + } + } + } + + return false; +} + +CInterlinkMapItem *CInterlinkMap::FindMapItem(const std::string &cs) +{ + auto it = m_InterlinkMap.find(cs); + if (m_InterlinkMap.end() == it) + return nullptr; + return &it->second; +} + +char *CInterlinkMap::TrimWhiteSpaces(char *str) +{ + char *end; + + // Trim leading space & tabs + while((*str == ' ') || (*str == '\t')) str++; + + // All spaces? + if(*str == 0) + return str; + + // Trim trailing space, tab or lf + end = str + ::strlen(str) - 1; + while((end > str) && ((*end == ' ') || (*end == '\t') || (*end == '\r'))) end--; + + // Write new null terminator + *(end+1) = 0; + + return str; +} + +bool CInterlinkMap::GetLastModTime(time_t *time) +{ + bool ok = false; + + if ( ! m_Filename.empty() ) + { + struct stat fileStat; + if( ::stat(m_Filename.c_str(), &fileStat) != -1 ) + { + *time = fileStat.st_mtime; + ok = true; + } + } + return ok; +} + +char *CInterlinkMap::ToUpper(char *str) +{ + constexpr auto diff = 'a' - 'A'; + for (char *p=str; *p; p++) + { + if (*p >= 'a' && *p <= 'z') + *p -= diff; + } + return str; +} + +#ifndef NO_DHT +void CInterlinkMap::Update(const std::string &cs, const std::string &cmods, const std::string &ipv4, const std::string &ipv6, uint16_t port, const std::string &emods) +{ + auto it = m_InterlinkMap.find(cs); + if (m_InterlinkMap.end() == it) + { + std::cerr << "Can't Update CInterlinkMap item '" << cs << "' because it doesn't exist!"; + } + else + { + it->second.UpdateItem(cmods, ipv4, ipv6, port, emods); + } +} +#endif diff --git a/reflector/InterlinkMap.h b/reflector/InterlinkMap.h new file mode 100644 index 0000000..afa73c2 --- /dev/null +++ b/reflector/InterlinkMap.h @@ -0,0 +1,79 @@ +// +// Created by Jean-Luc Deltombe (LX3JL) on 30/12/2015. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// Copyright © 2020 Thomas A. Early, N7TAE +// +// ---------------------------------------------------------------------------- +// This file is part of m17ref. +// +// m17ref 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 3 of the License, or +// (at your option) any later version. +// +// m17ref 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 +// with this software. If not, see . +// ---------------------------------------------------------------------------- + +#pragma once + +#include +#include + +#include "InterlinkMapItem.h" + +//////////////////////////////////////////////////////////////////////////////////////// +// class + +class CInterlinkMap +{ +public: + // constructor + CInterlinkMap(); + + // destructor + virtual ~CInterlinkMap() {} + + // locks + void Lock(void) const { m_Mutex.lock(); } + void Unlock(void) const { m_Mutex.unlock(); } + + // file io + virtual bool LoadFromFile(const std::string &filename); + bool ReloadFromFile(void); + bool NeedReload(void); + +#ifndef NO_DHT + void Update(const std::string &cs, const std::string &mods, const std::string &ipv4, const std::string &ipv6, uint16_t port, const std::string &tcmods); +#endif + + // compare + bool IsCallsignListed(const std::string &, const char) const; + bool IsCallsignListed(const std::string &, const CIp &ip, const char*) const; + + // pass-thru + bool empty() const { return m_InterlinkMap.empty(); } + std::map::iterator begin() { return m_InterlinkMap.begin(); } + std::map::iterator end() { return m_InterlinkMap.end(); } + std::map::const_iterator cbegin() { return m_InterlinkMap.cbegin(); } + std::map::const_iterator cend() { return m_InterlinkMap.cend(); } + + // find + CInterlinkMapItem *FindMapItem(const std::string &); + +protected: + bool GetLastModTime(time_t *); + char *TrimWhiteSpaces(char *); + char *ToUpper(char *str); + + // data + mutable std::mutex m_Mutex; + std::string m_Filename; + time_t m_LastModTime; + std::map m_InterlinkMap; +}; diff --git a/reflector/InterlinkMapItem.cpp b/reflector/InterlinkMapItem.cpp new file mode 100644 index 0000000..237bff3 --- /dev/null +++ b/reflector/InterlinkMapItem.cpp @@ -0,0 +1,143 @@ +// +// ccallsignlistitem.cpp +// m17ref +// +// Created by Jean-Luc Deltombe (LX3JL) on 31/01/2016. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// Copyright © 2020,2022 Thomas A. Early N7TAE +// +// ---------------------------------------------------------------------------- +// This file is part of m17ref. +// +// m17ref 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 3 of the License, or +// (at your option) any later version. +// +// m17ref 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 +// with this software. If not, see . +// ---------------------------------------------------------------------------- + +#include + +#include "Configure.h" +#include "InterlinkMapItem.h" +#include "Reflector.h" + +//////////////////////////////////////////////////////////////////////////////////////// +// constructor +#ifdef NO_DHT +CInterlinkMapItem::CInterlinkMapItem() +{ + m_UsesDHT = false; +} +#else +CInterlinkMapItem::CInterlinkMapItem() +{ + m_UsesDHT = false; + m_Updated = false; +} +#endif + +#ifndef NO_DHT +CInterlinkMapItem::CInterlinkMapItem(const char *mods) +{ + m_UsesDHT = true; + m_Updated = false; + m_Mods.assign(mods); +} +#endif + +CInterlinkMapItem::CInterlinkMapItem(const char *addr, const char *mods, uint16_t port) : CInterlinkMapItem() +{ + m_Mods.assign(mods); + m_Ip.Initialize(strchr(addr, ':') ? AF_INET6 : AF_INET, port, addr); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// compare + +bool CInterlinkMapItem::HasModuleListed(char module) const +{ + return m_Mods.npos != m_Mods.find(module); +} + +bool CInterlinkMapItem::HasSameIp(const CIp &ip) +{ + return ip == m_Ip; +} + +bool CInterlinkMapItem::CheckListedModules(const char *mods) const +{ + if (mods == nullptr) + return false; + + // make sure every mods character is matched in m_Mods + const auto count = m_Mods.size(); + bool found[count]; + for (unsigned i=0; i. +// ---------------------------------------------------------------------------- + +#pragma once + +#include + +#include "Callsign.h" +#include "IP.h" + +class CInterlinkMapItem +{ +public: + // constructor + CInterlinkMapItem(); +#ifndef NO_DHT + CInterlinkMapItem(const char *mods); +#endif + CInterlinkMapItem(const char *addr, const char *mods, uint16_t port); + + // Update things + void UpdateIP(bool IPv6NotConfigured); +#ifndef NO_DHT + void UpdateItem(const std::string &cmods, const std::string &ipv4, const std::string &ipv6, uint16_t port, const std::string &tcmods); +#endif + + // compare + bool HasSameIp(const CIp &ip); + bool HasModuleListed(char) const; + bool CheckListedModules(const char*) const; + + // get + const CIp &GetIp(void) const { return m_Ip; } + const std::string &GetModules(void) const { return m_Mods; } + bool UsesDHT(void) const { return m_UsesDHT; } + uint16_t GetPort(void) const { return m_Port; } +#ifndef NO_DHT + const std::string &GetIPv4(void) const { return m_IPv4; } + const std::string &GetIPv6(void) const { return m_IPv6; } + const std::string &GetTCMods(void) const { return m_TCMods; } + const std::string &GetCMods(void) const { return m_CMods; } +#endif + +private: + // data + CIp m_Ip; + std::string m_Mods; + uint16_t m_Port; + bool m_UsesDHT; + +#ifndef NO_DHT + bool m_Updated; + std::string m_CMods, m_IPv4, m_IPv6, m_TCMods; +#endif +}; diff --git a/reflector/Lookup.h b/reflector/Lookup.h index e7edd78..3f9a46e 100644 --- a/reflector/Lookup.h +++ b/reflector/Lookup.h @@ -27,26 +27,6 @@ enum class Eaction { normal, parse, error_only }; enum class Esource { http, file }; -// compare function for std::map::find - -struct CCallsignHash -{ - std::size_t operator() (const UCallsign &ucs) const - { - std::hash hash; - return hash(ucs.l); - } -}; - -struct CCallsignEqual -{ - bool operator() (const UCallsign &ucs1, const UCallsign &ucs2) const - { - return ucs1.l == ucs2.l; - } -}; - - //////////////////////////////////////////////////////////////////////////////////////// class CLookup diff --git a/reflector/PeerCallsignList.cpp b/reflector/PeerCallsignList.cpp deleted file mode 100644 index 5729d0a..0000000 --- a/reflector/PeerCallsignList.cpp +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. - -// urfd -- The universal reflector -// Copyright © 2021 Thomas A. Early N7TAE -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 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, see . - -#include -#include - -#include "PeerCallsignList.h" - -bool CPeerCallsignList::LoadFromFile(const std::string &filename) -{ - bool ok = false; - char sz[256]; - - // and load - std::ifstream file (filename); - if ( file.is_open() ) - { - Lock(); - - // empty list - m_Callsigns.clear(); - // fill with file content - while ( file.getline(sz, sizeof(sz)).good() ) - { - // remove leading & trailing spaces - char *szt = TrimWhiteSpaces(sz); - - // crack it - if ( (::strlen(szt) > 0) && (szt[0] != '#') ) - { - // 1st token is callsign - if ( (szt = ::strtok(szt, " ,\t")) != nullptr ) - { - CCallsign callsign(szt); - // 2nd token is ip - char *szip; - if ( (szip = ::strtok(nullptr, " ,\t")) != nullptr ) - { - // 3rd token is modules list - if ( (szt = ::strtok(nullptr, " ,\t")) != nullptr ) - { - // and load - m_Callsigns.push_back(CCallsignListItem(callsign, szip, szt)); - } - } - } - } - } - // close file - file.close(); - - // keep file path - m_Filename = filename; - - // update time - GetLastModTime(&m_LastModTime); - - // and done - Unlock(); - ok = true; - std::cout << "Gatekeeper loaded " << m_Callsigns.size() << " lines from " << filename << std::endl; - } - else - { - std::cout << "Gatekeeper cannot find " << filename << std::endl; - } - - return ok; -} diff --git a/reflector/PeerCallsignList.h b/reflector/PeerCallsignList.h deleted file mode 100644 index b4cd2b9..0000000 --- a/reflector/PeerCallsignList.h +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. - -// urfd -- The universal reflector -// Copyright © 2021 Thomas A. Early N7TAE -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 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, see . - -#pragma once - - -#include "CallsignList.h" - -//////////////////////////////////////////////////////////////////////////////////////// -// class - -class CPeerCallsignList : public CCallsignList -{ -public: - // constructor - CPeerCallsignList() {} - - // destructor - virtual ~CPeerCallsignList() {} - - // file io - bool LoadFromFile(const std::string &filename); -}; diff --git a/reflector/Reflector.cpp b/reflector/Reflector.cpp index ec53e1d..6367126 100644 --- a/reflector/Reflector.cpp +++ b/reflector/Reflector.cpp @@ -635,14 +635,13 @@ void CReflector::PutDHTConfig() std::ostringstream ss; ss << g_Version; cfg.version.assign(ss.str()); - cfg.almod[toUType(EUrfdAlMod::nxdn)] = g_Configure.GetString(g_Keys.nxdn.autolinkmod).at(0); - cfg.almod[toUType(EUrfdAlMod::p25)] = g_Configure.GetString(g_Keys.p25.autolinkmod).at(0); - cfg.almod[toUType(EUrfdAlMod::ysf)] = g_Configure.GetString(g_Keys.ysf.autolinkmod).at(0); - cfg.ysffreq[toUType(EUrfdTxRx::rx)] = g_Configure.GetUnsigned(g_Keys.ysf.defaultrxfreq); - cfg.ysffreq[toUType(EUrfdTxRx::tx)] = g_Configure.GetUnsigned(g_Keys.ysf.defaulttxfreq); - cfg.refid[toUType(EUrfdRefId::nxdn)] = g_Configure.GetUnsigned(g_Keys.nxdn.reflectorid); - cfg.refid[toUType(EUrfdRefId::p25)] = g_Configure.GetUnsigned(g_Keys.p25.reflectorid); - cfg.g3enabled = g_Configure.GetBoolean(g_Keys.g3.enable); + cfg.almod[toUType(EUrfdAlMod::nxdn)] = g_Configure.GetString(g_Keys.nxdn.autolinkmod).at(0); + cfg.almod[toUType(EUrfdAlMod::p25)] = g_Configure.GetString(g_Keys.p25.autolinkmod).at(0); + cfg.almod[toUType(EUrfdAlMod::ysf)] = g_Configure.GetString(g_Keys.ysf.autolinkmod).at(0); + cfg.ysffreq[toUType(EUrfdTxRx::rx)] = g_Configure.GetUnsigned(g_Keys.ysf.defaultrxfreq); + cfg.ysffreq[toUType(EUrfdTxRx::tx)] = g_Configure.GetUnsigned(g_Keys.ysf.defaulttxfreq); + cfg.refid[toUType(EUrfdRefId::nxdn)] = g_Configure.GetUnsigned(g_Keys.nxdn.reflectorid); + cfg.refid[toUType(EUrfdRefId::p25)] = g_Configure.GetUnsigned(g_Keys.p25.reflectorid); cfg.port[toUType(EUrfdPorts::dcs)] = (uint16_t)g_Configure.GetUnsigned(g_Keys.dcs.port); cfg.port[toUType(EUrfdPorts::dextra)] = (uint16_t)g_Configure.GetUnsigned(g_Keys.dextra.port); cfg.port[toUType(EUrfdPorts::dmrplus)] = (uint16_t)g_Configure.GetUnsigned(g_Keys.dmrplus.port); @@ -653,6 +652,7 @@ void CReflector::PutDHTConfig() cfg.port[toUType(EUrfdPorts::p25)] = (uint16_t)g_Configure.GetUnsigned(g_Keys.p25.port); cfg.port[toUType(EUrfdPorts::urf)] = (uint16_t)g_Configure.GetUnsigned(g_Keys.urf.port); cfg.port[toUType(EUrfdPorts::ysf)] = (uint16_t)g_Configure.GetUnsigned(g_Keys.ysf.port); + cfg.g3enabled = g_Configure.GetBoolean(g_Keys.g3.enable); for (const auto m : cfg.mods) cfg.description[m] = g_Configure.GetString(g_Keys.modules.descriptor[m-'A']); @@ -672,7 +672,8 @@ void CReflector::GetDHTConfig(const std::string &cs) { static SUrfdConfig0 cfg; cfg.timestamp = 0; // everytime this is called, zero the timestamp - auto item = g_IFile.FindMapItem(cs); + auto item = g_GateKeeper.GetInterlinkMap()->FindMapItem(cs); + g_GateKeeper.ReleaseInterlinkMap(); if (nullptr == item) { std::cerr << "Can't Get() for " << cs << " because it doesn't exist" << std::endl; @@ -708,7 +709,7 @@ void CReflector::GetDHTConfig(const std::string &cs) if (cfg.timestamp) { // if the get() call was successful and there is a nonzero timestamp, then do the update - g_IFile.Update(cfg.cs, cfg.mods, cfg.ipv4, cfg.ipv6, cfg.port, cfg.emods); + g_GateKeeper.GetInterlinkMap()->Update(cfg.cs, cfg.mods, cfg.ipv4, cfg.ipv6, cfg.port[toUType(EUrfdPorts::urf)], cfg.tcmods); } } else diff --git a/reflector/URFProtocol.cpp b/reflector/URFProtocol.cpp index 673f21d..42db8d6 100644 --- a/reflector/URFProtocol.cpp +++ b/reflector/URFProtocol.cpp @@ -287,16 +287,16 @@ void CURFProtocol::HandlePeerLinks(void) CBuffer buffer; // get the list of peers - CPeerCallsignList *list = g_GateKeeper.GetPeerList(); + auto ilmap = g_GateKeeper.GetInterlinkMap(); CPeers *peers = g_Reflector.GetPeers(); // check if all our connected peers are still listed by gatekeeper // if not, disconnect auto pit = peers->begin(); std::shared_ptrpeer = nullptr; - while ( (peer = peers->FindNextPeer(EProtocol::urf, pit)) != nullptr ) + while (nullptr != (peer = peers->FindNextPeer(EProtocol::urf, pit))) { - if ( list->FindListItem(peer->GetCallsign()) == nullptr ) + if (nullptr == ilmap->FindMapItem(peer->GetCallsign().GetBase())) { // send disconnect packet EncodeDisconnectPacket(&buffer); @@ -307,29 +307,23 @@ void CURFProtocol::HandlePeerLinks(void) } } - // check if all ours peers listed by gatekeeper are connected + // check if all ours peers listed by interlink file are connected // if not, connect or reconnect - for ( auto it=list->begin(); it!=list->end(); it++ ) + for ( auto it=ilmap->begin(); it!=ilmap->end(); it++ ) { - if ( it->GetCallsign().HasSameCallsignWithWildcard(CCallsign("XRF*")) ) - continue; - if ( it->GetCallsign().HasSameCallsignWithWildcard(CCallsign("BM*")) ) - continue; - CCallsign cs = it->GetCallsign(); - if (cs.HasSameCallsignWithWildcard(CCallsign("URF*")) && (nullptr==peers->FindPeer(cs, EProtocol::urf))) + const auto cs = it->first; + if ((0 == cs.substr(0, 3).compare("URF")) && (nullptr==peers->FindPeer(CCallsign(cs), EProtocol::urf))) { - // resolve again peer's IP in case it's a dynamic IP - it->ResolveIp(); // send connect packet to re-initiate peer link - EncodeConnectPacket(&buffer, it->GetModules()); - Send(buffer, it->GetIp(), m_Port); - std::cout << "Sending connect packet to URF peer " << cs << " @ " << it->GetIp() << " for modules " << it->GetModules() << std::endl; + EncodeConnectPacket(&buffer, it->second.GetModules().c_str()); + Send(buffer, it->second.GetIp(), it->second.GetPort()); + std::cout << "Sending connect packet to URF peer " << cs << " @ " << it->second.GetIp() << " for modules " << it->second.GetModules() << std::endl; } } // done g_Reflector.ReleasePeers(); - g_GateKeeper.ReleasePeerList(); + g_GateKeeper.ReleaseInterlinkMap(); } From d11128df3a88fea91f9de9e36cb7daecfd11eee8 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Fri, 31 Mar 2023 10:20:23 -0700 Subject: [PATCH 05/28] dht support for interlinking --- reflector/CNotificationQueue.h | 49 ------------------------------- reflector/InterlinkMapItem.h | 4 +-- reflector/Notification.cpp | 37 ------------------------ reflector/Notification.h | 53 ---------------------------------- reflector/NotificationQueue.h | 49 ------------------------------- reflector/Reflector.cpp | 48 ++++++++++-------------------- reflector/Reflector.h | 8 ++--- reflector/URFProtocol.cpp | 47 +++++++++++++++++++++++++++--- reflector/Version.cpp | 3 ++ 9 files changed, 66 insertions(+), 232 deletions(-) delete mode 100644 reflector/CNotificationQueue.h delete mode 100644 reflector/Notification.cpp delete mode 100644 reflector/Notification.h delete mode 100644 reflector/NotificationQueue.h diff --git a/reflector/CNotificationQueue.h b/reflector/CNotificationQueue.h deleted file mode 100644 index f0bc210..0000000 --- a/reflector/CNotificationQueue.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright © 2015 Jean-Luc. All rights reserved. - -// urfd -- The universal reflector -// Copyright © 2021 Thomas A. Early N7TAE -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 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, see . - -#pragma once - -#include -#include - -#include "Notification.h" - -class CNotificationQueue -{ -public: - // constructor - CNotificationQueue() {} - - // destructor - ~CNotificationQueue() {} - - // lock - void Lock() { m_Mutex.lock(); } - void Unlock() { m_Mutex.unlock(); } - - // pass thru - CNotification front() { return queue.front(); } - void pop() { queue.pop(); } - void push(CNotification note) { queue.push(note); } - bool empty() const { return queue.empty(); } - -protected: - // data - std::mutex m_Mutex; - std::queue queue; -}; diff --git a/reflector/InterlinkMapItem.h b/reflector/InterlinkMapItem.h index d0973fe..560ed0a 100644 --- a/reflector/InterlinkMapItem.h +++ b/reflector/InterlinkMapItem.h @@ -38,8 +38,8 @@ public: CInterlinkMapItem(const char *addr, const char *mods, uint16_t port); // Update things - void UpdateIP(bool IPv6NotConfigured); #ifndef NO_DHT + void UpdateIP(bool IPv6NotConfigured); void UpdateItem(const std::string &cmods, const std::string &ipv4, const std::string &ipv6, uint16_t port, const std::string &tcmods); #endif @@ -69,6 +69,6 @@ private: #ifndef NO_DHT bool m_Updated; - std::string m_CMods, m_IPv4, m_IPv6, m_TCMods; + std::string m_CMods, m_TCMods, m_IPv4, m_IPv6; #endif }; diff --git a/reflector/Notification.cpp b/reflector/Notification.cpp deleted file mode 100644 index 6808a02..0000000 --- a/reflector/Notification.cpp +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright © 2015 Jean-Luc. All rights reserved. - -// urfd -- The universal reflector -// Copyright © 2021 Thomas A. Early N7TAE -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 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, see . - - -#include "Notification.h" - -CNotification::CNotification() -{ - // init variables - m_iId = NOTIFICATION_NONE; -} - -CNotification::CNotification(int iId) -{ - m_iId = iId; -} - -CNotification::CNotification(int iId, const CCallsign &Callsign) -{ - m_iId = iId; - m_Callsign = Callsign; -} diff --git a/reflector/Notification.h b/reflector/Notification.h deleted file mode 100644 index 3db4e0b..0000000 --- a/reflector/Notification.h +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright © 2015 Jean-Luc. All rights reserved. - -// urfd -- The universal reflector -// Copyright © 2021 Thomas A. Early N7TAE -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 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, see . - -#pragma once - -#include "Callsign.h" - -//////////////////////////////////////////////////////////////////////////////////////// - -// Id -#define NOTIFICATION_NONE 0 -#define NOTIFICATION_CLIENTS 1 -#define NOTIFICATION_USERS 2 -#define NOTIFICATION_STREAM_OPEN 3 -#define NOTIFICATION_STREAM_CLOSE 4 -#define NOTIFICATION_PEERS 5 - -//////////////////////////////////////////////////////////////////////////////////////// -// class - -class CNotification -{ -public: - // constructor - CNotification(); - CNotification(int); - CNotification(int, const CCallsign &); - - // get - int GetId(void) const { return m_iId; } - const CCallsign &GetCallsign(void) const { return m_Callsign; } - -protected: - // data - int m_iId; - CCallsign m_Callsign; - -}; diff --git a/reflector/NotificationQueue.h b/reflector/NotificationQueue.h deleted file mode 100644 index 70b894a..0000000 --- a/reflector/NotificationQueue.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright © 2015 Jean-Luc. All rights reserved. - -// urfd -- The universal reflector -// Copyright © 2021 Thomas A. Early N7TAE -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 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, see . - -#pragma once - -#include -#include - -#include "Notification.h" - - -//////////////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////////////// -// class - -class CNotificationQueue -{ -public: - // lock - void Lock() { m_Mutex.lock(); } - void Unlock() { m_Mutex.unlock(); } - - // pass thru - CNotification front() { return queue.front(); } - void pop() { queue.pop(); } - void push(CNotification note) { queue.push(note); } - bool empty() const { return queue.empty(); } - -protected: - // data - std::mutex m_Mutex; - std::queue queue; -}; diff --git a/reflector/Reflector.cpp b/reflector/Reflector.cpp index 6367126..8c9a1c8 100644 --- a/reflector/Reflector.cpp +++ b/reflector/Reflector.cpp @@ -236,7 +236,7 @@ std::shared_ptr CReflector::OpenStream(std::unique_ptrPush(std::move(DvHeader)); // notify - OnStreamOpen(stream->GetUserCallsign()); + //OnStreamOpen(stream->GetUserCallsign()); } return stream; @@ -264,7 +264,7 @@ void CReflector::CloseStream(std::shared_ptr stream) client->NotAMaster(); // notify - OnStreamClose(stream->GetUserCallsign()); + //OnStreamClose(stream->GetUserCallsign()); std::cout << "Closing stream of module " << GetStreamModule(stream) << std::endl; } @@ -381,48 +381,32 @@ void CReflector::XmlReportThread() void CReflector::OnPeersChanged(void) { - CNotification notification(NOTIFICATION_PEERS); - - m_Notifications.Lock(); - m_Notifications.push(notification); - m_Notifications.Unlock(); +#ifndef NO_DHT + PutDHTPeers(); +#endif } void CReflector::OnClientsChanged(void) { - CNotification notification(NOTIFICATION_CLIENTS); - - m_Notifications.Lock(); - m_Notifications.push(notification); - m_Notifications.Unlock(); +#ifndef NO_DHT + PutDHTClients(); +#endif } void CReflector::OnUsersChanged(void) { - CNotification notification(NOTIFICATION_USERS); - - m_Notifications.Lock(); - m_Notifications.push(notification); - m_Notifications.Unlock(); +#ifndef NO_DHT + PutDHTUsers(); +#endif } -void CReflector::OnStreamOpen(const CCallsign &callsign) -{ - CNotification notification(NOTIFICATION_STREAM_OPEN, callsign); +// void CReflector::OnStreamOpen(const CCallsign &callsign) +// { +// } - m_Notifications.Lock(); - m_Notifications.push(notification); - m_Notifications.Unlock(); -} +// void CReflector::OnStreamClose(const CCallsign &callsign) +// { -void CReflector::OnStreamClose(const CCallsign &callsign) -{ - CNotification notification(NOTIFICATION_STREAM_CLOSE, callsign); - - m_Notifications.Lock(); - m_Notifications.push(notification); - m_Notifications.Unlock(); -} //////////////////////////////////////////////////////////////////////////////////////// // modules & queues diff --git a/reflector/Reflector.h b/reflector/Reflector.h index 5292713..2f8376d 100644 --- a/reflector/Reflector.h +++ b/reflector/Reflector.h @@ -25,7 +25,6 @@ #include "Peers.h" #include "Protocols.h" #include "PacketStream.h" -#include "NotificationQueue.h" #ifndef NO_DHT #include "urfd-dht-values.h" @@ -80,8 +79,8 @@ public: void OnPeersChanged(void); void OnClientsChanged(void); void OnUsersChanged(void); - void OnStreamOpen(const CCallsign &); - void OnStreamClose(const CCallsign &); + // void OnStreamOpen(const CCallsign &); + // void OnStreamClose(const CCallsign &); #ifndef NO_DHT // Publish DHT @@ -124,9 +123,6 @@ protected: std::unordered_map> m_RouterFuture; std::future m_XmlReportFuture; - // notifications - CNotificationQueue m_Notifications; - #ifndef NO_DHT // Distributed Hash Table dht::DhtRunner node; diff --git a/reflector/URFProtocol.cpp b/reflector/URFProtocol.cpp index 42db8d6..35a6985 100644 --- a/reflector/URFProtocol.cpp +++ b/reflector/URFProtocol.cpp @@ -314,10 +314,49 @@ void CURFProtocol::HandlePeerLinks(void) const auto cs = it->first; if ((0 == cs.substr(0, 3).compare("URF")) && (nullptr==peers->FindPeer(CCallsign(cs), EProtocol::urf))) { - // send connect packet to re-initiate peer link - EncodeConnectPacket(&buffer, it->second.GetModules().c_str()); - Send(buffer, it->second.GetIp(), it->second.GetPort()); - std::cout << "Sending connect packet to URF peer " << cs << " @ " << it->second.GetIp() << " for modules " << it->second.GetModules() << std::endl; +#ifndef NO_DHT + it->second.UpdateIP(g_Configure.GetString(g_Keys.ip.ipv6address).empty()); + if (it->second.GetIp().IsSet()) + { + bool ok = true; + // does everything match up? + for (const auto c : it->second.GetModules()) + { + if (std::string::npos == g_Configure.GetString(g_Keys.modules.modules).find(c)) + { // is the local module not config'ed? + ok = false; + std::cerr << "This reflector has no module '" << c << "', so it can't interlink with " << it->first << std::endl; + } + else if (it->second.UsesDHT()) + { + if (std::string::npos == it->second.GetCMods().find(c)) + { // the remote module not config'ed! + ok = false; + std::cerr << it->first << " has no module '" << c << "'" << std::endl; + } + else if ((std::string::npos == it->second.GetTCMods().find(c)) != (std::string::npos == g_Configure.GetString(g_Keys.modules.tcmodules).find(c))) + { // are the transcoding states on both sides mismatched? + ok = false; + std::cerr << "The encryption states for module '" << c << "' don't match for this reflector and " << it->first << std::endl; + } + } + } + if (ok) + { + +#endif + // send connect packet to re-initiate peer link + EncodeConnectPacket(&buffer, it->second.GetModules().c_str()); + Send(buffer, it->second.GetIp(), it->second.GetPort()); + std::cout << "Sending connect packet to URF peer " << cs << " @ " << it->second.GetIp() << " for modules " << it->second.GetModules() << std::endl; +#ifndef NO_DHT + } + } + else // m_Ip is not set! + { + g_Reflector.GetDHTConfig(it->first); + } +#endif } } diff --git a/reflector/Version.cpp b/reflector/Version.cpp index 35d3c9d..4187f81 100644 --- a/reflector/Version.cpp +++ b/reflector/Version.cpp @@ -85,5 +85,8 @@ bool CVersion::operator <(const CVersion &v) const std::ostream &operator <<(std::ostream &os, const CVersion &v) { os << v.GetMajor() << '.' << v.GetMinor() << '.' << v.GetRevision(); +#ifndef NO_DHT + os << "-dht"; +#endif return os; }; From dc12fd748e2bdb37aca82946142afa05d62d1a26 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Sat, 1 Apr 2023 11:19:58 -0700 Subject: [PATCH 06/28] correct spelling errors --- reflector/BlackWhiteSet.h | 2 +- reflector/Callsign.h | 2 +- reflector/Clients.cpp | 2 +- reflector/Clients.h | 2 +- reflector/CodecStream.h | 2 +- reflector/Configure.cpp | 6 +++--- reflector/DMRPlusProtocol.cpp | 2 +- reflector/G3Protocol.cpp | 4 ++-- reflector/Golay2087.cpp | 2 +- reflector/Golay24128.cpp | 2 +- reflector/Hamming.cpp | 4 ++-- reflector/InterlinkMap.h | 2 +- reflector/M17CRC.cpp | 2 +- reflector/M17CRC.h | 2 +- reflector/Main.cpp | 6 +++--- reflector/Packet.cpp | 2 +- reflector/Peer.h | 2 +- reflector/Peers.h | 2 +- reflector/Protocols.h | 2 +- reflector/QR1676.cpp | 2 +- reflector/Reflector.cpp | 4 ++-- reflector/SafePacketQueue.h | 6 +++--- reflector/UDPSocket.cpp | 2 +- reflector/Users.h | 2 +- reflector/Version.h | 2 +- 25 files changed, 34 insertions(+), 34 deletions(-) diff --git a/reflector/BlackWhiteSet.h b/reflector/BlackWhiteSet.h index 3ec0421..5b2797e 100644 --- a/reflector/BlackWhiteSet.h +++ b/reflector/BlackWhiteSet.h @@ -42,7 +42,7 @@ public: bool ReloadFromFile(void); bool NeedReload(void); - // pass-thru + // pass-through bool empty() const { return m_Callsigns.empty(); } // compare diff --git a/reflector/Callsign.h b/reflector/Callsign.h index 4ad3c29..99ca10c 100644 --- a/reflector/Callsign.h +++ b/reflector/Callsign.h @@ -63,7 +63,7 @@ struct CCallsignEqual class CCallsign { public: - // contructors + // constructors CCallsign(); CCallsign(const UCallsign &cs); // no id lookup CCallsign(const CCallsign &cs); diff --git a/reflector/Clients.cpp b/reflector/Clients.cpp index fcddd63..4e0bca4 100644 --- a/reflector/Clients.cpp +++ b/reflector/Clients.cpp @@ -73,7 +73,7 @@ void CClients::RemoveClient(std::shared_ptr client) bool found = false; for ( auto it=begin(); it!=end(); it++ ) { - // compare objetc pointers + // compare object pointers if ( *it == client ) { // found it ! diff --git a/reflector/Clients.h b/reflector/Clients.h index e596076..322c3ef 100644 --- a/reflector/Clients.h +++ b/reflector/Clients.h @@ -47,7 +47,7 @@ public: void RemoveClient(std::shared_ptr); bool IsClient(std::shared_ptr) const; - // pass-thru + // pass-through std::list>::iterator begin() { return m_Clients.begin(); } std::list>::iterator end() { return m_Clients.end(); } std::list>::const_iterator cbegin() const { return m_Clients.cbegin(); } diff --git a/reflector/CodecStream.h b/reflector/CodecStream.h index 74db476..1576f1d 100644 --- a/reflector/CodecStream.h +++ b/reflector/CodecStream.h @@ -50,7 +50,7 @@ public: void Thread(void); void Task(void); - // pass-thru + // pass-through void Push(std::unique_ptr p) { m_Queue.Push(std::move(p)); } protected: diff --git a/reflector/Configure.cpp b/reflector/Configure.cpp index 9736b50..21b837e 100644 --- a/reflector/Configure.cpp +++ b/reflector/Configure.cpp @@ -493,7 +493,7 @@ bool CConfigure::ReadData(const std::string &path) badParam(key); break; default: - std::cout << "WARNING: parameter '" << line << "' defined befor any [section]" << std::endl; + std::cout << "WARNING: parameter '" << line << "' defined before any [section]" << std::endl; } } @@ -536,7 +536,7 @@ bool CConfigure::ReadData(const std::string &path) } else { - std::cerr << "ERROR: specifed IPv4 external address, " << v4 << ", is malformed" << std::endl; + std::cerr << "ERROR: specified IPv4 external address, " << v4 << ", is malformed" << std::endl; rval = true; } } @@ -574,7 +574,7 @@ bool CConfigure::ReadData(const std::string &path) } else { - std::cerr << "ERROR: the specifed IPv6 address [" << v6 << "] is malformed" << std::endl; + std::cerr << "ERROR: the specified IPv6 address [" << v6 << "] is malformed" << std::endl; rval = true; } } diff --git a/reflector/DMRPlusProtocol.cpp b/reflector/DMRPlusProtocol.cpp index 4de295f..fefc957 100644 --- a/reflector/DMRPlusProtocol.cpp +++ b/reflector/DMRPlusProtocol.cpp @@ -449,7 +449,7 @@ bool CDmrplusProtocol::IsValidDvFramePacket(const CIp &Ip, const CBuffer &Buffer uint8_t dmrsync[7]; // get the 33 bytes ambe memcpy(dmrframe, &(Buffer.data()[26]), 33); - // handle endianess + // handle endianness SwapEndianess(dmrframe, sizeof(dmrframe)); // extract the 3 ambe frames memcpy(dmr3ambe, dmrframe, 14); diff --git a/reflector/G3Protocol.cpp b/reflector/G3Protocol.cpp index 7c15ca8..8d5e24b 100644 --- a/reflector/G3Protocol.cpp +++ b/reflector/G3Protocol.cpp @@ -390,7 +390,7 @@ void CG3Protocol::Task(void) { BaseIp = &ClIp; client->Alive(); - // supress host checks - no ping needed to trigger potential ICMPs + // suppress host checks - no ping needed to trigger potential ICMPs // the regular data flow will do it m_LastKeepaliveTime.start(); break; @@ -444,7 +444,7 @@ void CG3Protocol::HandleQueue(void) { while (! m_Queue.IsEmpty()) { - // supress host checks + // suppress host checks m_LastKeepaliveTime.start(); // get the packet diff --git a/reflector/Golay2087.cpp b/reflector/Golay2087.cpp index 3e34543..c43e660 100644 --- a/reflector/Golay2087.cpp +++ b/reflector/Golay2087.cpp @@ -219,7 +219,7 @@ unsigned int CGolay2087::getSyndrome1987(unsigned int pattern) * Compute the syndrome corresponding to the given pattern, i.e., the * remainder after dividing the pattern (when considering it as the vector * representation of a polynomial) by the generator polynomial, GENPOL. - * In the program this pattern has several meanings: (1) pattern = infomation + * In the program this pattern has several meanings: (1) pattern = information * bits, when constructing the encoding table; (2) pattern = error pattern, * when constructing the decoding table; and (3) pattern = received vector, to * obtain its syndrome in decoding. diff --git a/reflector/Golay24128.cpp b/reflector/Golay24128.cpp index 6f810e6..fc1ed18 100644 --- a/reflector/Golay24128.cpp +++ b/reflector/Golay24128.cpp @@ -1055,7 +1055,7 @@ static unsigned int get_syndrome_23127(unsigned int pattern) * Compute the syndrome corresponding to the given pattern, i.e., the * remainder after dividing the pattern (when considering it as the vector * representation of a polynomial) by the generator polynomial, GENPOL. - * In the program this pattern has several meanings: (1) pattern = infomation + * In the program this pattern has several meanings: (1) pattern = information * bits, when constructing the encoding table; (2) pattern = error pattern, * when constructing the decoding table; and (3) pattern = received vector, to * obtain its syndrome in decoding. diff --git a/reflector/Hamming.cpp b/reflector/Hamming.cpp index 42636f0..1980a1f 100644 --- a/reflector/Hamming.cpp +++ b/reflector/Hamming.cpp @@ -224,7 +224,7 @@ bool CHamming::decode1393(bool* d) d[12] = !d[12]; return true; - // Data bit erros + // Data bit errors case 0x0FU: d[0] = !d[0]; return true; @@ -303,7 +303,7 @@ bool CHamming::decode1063(bool* d) d[9] = !d[9]; return true; - // Data bit erros + // Data bit errors case 0x07U: d[0] = !d[0]; return true; diff --git a/reflector/InterlinkMap.h b/reflector/InterlinkMap.h index afa73c2..3e78650 100644 --- a/reflector/InterlinkMap.h +++ b/reflector/InterlinkMap.h @@ -56,7 +56,7 @@ public: bool IsCallsignListed(const std::string &, const char) const; bool IsCallsignListed(const std::string &, const CIp &ip, const char*) const; - // pass-thru + // pass-through bool empty() const { return m_InterlinkMap.empty(); } std::map::iterator begin() { return m_InterlinkMap.begin(); } std::map::iterator end() { return m_InterlinkMap.end(); } diff --git a/reflector/M17CRC.cpp b/reflector/M17CRC.cpp index 6e4587a..fa46504 100644 --- a/reflector/M17CRC.cpp +++ b/reflector/M17CRC.cpp @@ -29,7 +29,7 @@ * Description * ----------- * The source file contains routines which calculate the CCITT CRC - * values for an incomming byte string. + * values for an incoming byte string. */ #include diff --git a/reflector/M17CRC.h b/reflector/M17CRC.h index c6113fb..adc3d9c 100644 --- a/reflector/M17CRC.h +++ b/reflector/M17CRC.h @@ -29,7 +29,7 @@ * Description * ----------- * The source file contains routines which calculate the CCITT CRC - * values for an incomming byte string. + * values for an incoming byte string. */ #pragma once diff --git a/reflector/Main.cpp b/reflector/Main.cpp index 098d35a..1bbd0d6 100644 --- a/reflector/Main.cpp +++ b/reflector/Main.cpp @@ -39,7 +39,7 @@ int main(int argc, char *argv[]) { if (argc != 2) { - std::cerr << "No configuration file specifed! Usage: " << argv[0] << " /pathname/to/configuration/file" << std::endl; + std::cerr << "No configuration file specified! Usage: " << argv[0] << " /pathname/to/configuration/file" << std::endl; return EXIT_FAILURE; } @@ -98,13 +98,13 @@ static void usage(std::ostream &os, const char *name) " ysf : The Callsign => Tx/Rx frequency database.\n" "SOURCE (choose one)\n" " file : The file specified by the FilePath ini parameter.\n" - " http : The URL specified by the URL ini paramater.\n" + " http : The URL specified by the URL ini parameter.\n" "ACTION (choose one)\n" " print : Print all lines from the SOURCE that are syntactically correct.\n" " error : Print only the lines with failed syntax.\n" "INIFILE : an error-free urfd ini file (check it first with inicheck).\n\n" "Only the first character of DATABASE, SOURCE and ACTION is read.\n" - "Example: " << name << " y f e urfd.ini # Check your YSF Tx/Rx database file specifed in urfd.ini for syntax errors.\n\n"; + "Example: " << name << " y f e urfd.ini # Check your YSF Tx/Rx database file specified in urfd.ini for syntax errors.\n\n"; } enum class Edb { none, dmr, nxdn, ysf }; diff --git a/reflector/Packet.cpp b/reflector/Packet.cpp index ed4d3a1..2700369 100644 --- a/reflector/Packet.cpp +++ b/reflector/Packet.cpp @@ -88,7 +88,7 @@ void CPacket::EncodeInterlinkPacket(const char *magic, CBuffer &buf) const data[19] = m_uiYsfPacketFrameId; } -// dstar contstructor +// dstar constructor CPacket::CPacket(uint16_t sid, uint8_t dstarpid) { m_uiStreamId = sid; diff --git a/reflector/Peer.h b/reflector/Peer.h index 89c96d0..4565493 100644 --- a/reflector/Peer.h +++ b/reflector/Peer.h @@ -61,7 +61,7 @@ public: int GetNbClients(void) const { return (int)m_Clients.size(); } void ClearClients(void) { m_Clients.clear(); } - // pass-thru + // pass-through std::list>::iterator begin() { return m_Clients.begin(); } std::list>::iterator end() { return m_Clients.end(); } std::list>::const_iterator cbegin() const { return m_Clients.cbegin(); } diff --git a/reflector/Peers.h b/reflector/Peers.h index 99512ca..81ff5fd 100644 --- a/reflector/Peers.h +++ b/reflector/Peers.h @@ -38,7 +38,7 @@ public: void AddPeer(std::shared_ptr); void RemovePeer(std::shared_ptr); - // pass-thru + // pass-through std::list>::iterator begin() { return m_Peers.begin(); } std::list>::iterator end() { return m_Peers.end(); } std::list>::const_iterator cbegin() const { return m_Peers.cbegin(); } diff --git a/reflector/Protocols.h b/reflector/Protocols.h index 32bbf1e..8de96ee 100644 --- a/reflector/Protocols.h +++ b/reflector/Protocols.h @@ -32,7 +32,7 @@ public: void Lock(void) { m_Mutex.lock(); } void Unlock(void) { m_Mutex.unlock(); } - // pass-thru + // pass-through std::list>::iterator begin() { return m_Protocols.begin(); } std::list>::iterator end() { return m_Protocols.end(); } diff --git a/reflector/QR1676.cpp b/reflector/QR1676.cpp index fe76c90..8f67a2f 100644 --- a/reflector/QR1676.cpp +++ b/reflector/QR1676.cpp @@ -72,7 +72,7 @@ unsigned int CQR1676::getSyndrome1576(unsigned int pattern) * Compute the syndrome corresponding to the given pattern, i.e., the * remainder after dividing the pattern (when considering it as the vector * representation of a polynomial) by the generator polynomial, GENPOL. - * In the program this pattern has several meanings: (1) pattern = infomation + * In the program this pattern has several meanings: (1) pattern = information * bits, when constructing the encoding table; (2) pattern = error pattern, * when constructing the decoding table; and (3) pattern = received vector, to * obtain its syndrome in decoding. diff --git a/reflector/Reflector.cpp b/reflector/Reflector.cpp index 8c9a1c8..7b240db 100644 --- a/reflector/Reflector.cpp +++ b/reflector/Reflector.cpp @@ -182,7 +182,7 @@ bool CReflector::IsStreaming(char module) return false; } -// clients MUST have bee locked by the caller so we can freely access it within the fuction +// clients MUST have bee locked by the caller so we can freely access it within the function std::shared_ptr CReflector::OpenStream(std::unique_ptr &DvHeader, std::shared_ptrclient) { // check sid is not zero @@ -655,7 +655,7 @@ void CReflector::PutDHTConfig() void CReflector::GetDHTConfig(const std::string &cs) { static SUrfdConfig0 cfg; - cfg.timestamp = 0; // everytime this is called, zero the timestamp + cfg.timestamp = 0; // every time this is called, zero the timestamp auto item = g_GateKeeper.GetInterlinkMap()->FindMapItem(cs); g_GateKeeper.ReleaseInterlinkMap(); if (nullptr == item) diff --git a/reflector/SafePacketQueue.h b/reflector/SafePacketQueue.h index fd51b40..5b5ec60 100644 --- a/reflector/SafePacketQueue.h +++ b/reflector/SafePacketQueue.h @@ -22,7 +22,7 @@ /************************************************************ * THIS IS IMPORTANT - * This template is primarly designed for std::unique_ptr! + * This template is primarily designed for std::unique_ptr! * If you are going to use it for std::shared_ptr, then * please consider that when you Push(), what you pushed * from will be nullptr after the Push()! @@ -56,13 +56,13 @@ public: } } - // If the queue is empty, wait until an element is avaiable. + // If the queue is empty, wait until an element is available. T PopWait(void) { std::unique_lock lock(m); while(q.empty()) { - // release lock as long as the wait and reaquire it afterwards. + // release lock as long as the wait and reacquire it afterwards. c.wait(lock); } T val = std::move(q.front()); diff --git a/reflector/UDPSocket.cpp b/reflector/UDPSocket.cpp index 1b078b6..45774ab 100644 --- a/reflector/UDPSocket.cpp +++ b/reflector/UDPSocket.cpp @@ -40,7 +40,7 @@ CUdpSocket::~CUdpSocket() // returns true on error bool CUdpSocket::Open(const CIp &Ip) { - // check for a vaild family + // check for a valid family if (AF_UNSPEC == Ip.GetFamily()) return true; diff --git a/reflector/Users.h b/reflector/Users.h index 85061bf..da8a680 100644 --- a/reflector/Users.h +++ b/reflector/Users.h @@ -40,7 +40,7 @@ public: int GetSize(void) const { return (int)m_Users.size(); } void AddUser(const CUser &); - // pass-thru + // pass-through std::list::iterator begin() { return m_Users.begin(); } std::list::iterator end() { return m_Users.end(); } std::list::const_iterator cbegin() { return m_Users.cbegin(); } diff --git a/reflector/Version.h b/reflector/Version.h index 84aa8d4..ef04078 100644 --- a/reflector/Version.h +++ b/reflector/Version.h @@ -38,7 +38,7 @@ public: // set void Set(uint8_t, uint8_t, uint8_t); - // comparaison operators + // comparison operators bool operator ==(const CVersion &v) const; bool operator !=(const CVersion &v) const; bool operator >=(const CVersion &v) const; From 86e4e4c9b26c76677d949295ccbf65e81737bdc0 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Sun, 2 Apr 2023 11:38:51 -0700 Subject: [PATCH 07/28] dht publication functions now called in StateReportThread --- reflector/Reflector.cpp | 44 +++++++++++++++++++++++++++-------------- reflector/Reflector.h | 12 +++++------ 2 files changed, 35 insertions(+), 21 deletions(-) diff --git a/reflector/Reflector.cpp b/reflector/Reflector.cpp index 7b240db..da5cb0b 100644 --- a/reflector/Reflector.cpp +++ b/reflector/Reflector.cpp @@ -120,7 +120,7 @@ bool CReflector::Start(void) // start the reporting thread try { - m_XmlReportFuture = std::async(std::launch::async, &CReflector::XmlReportThread, this); + m_XmlReportFuture = std::async(std::launch::async, &CReflector::StateReportThread, this); } catch(const std::exception& e) { @@ -323,10 +323,12 @@ void CReflector::RouterThread(const char ThisModule) #define XML_UPDATE_PERIOD 10 -void CReflector::XmlReportThread() +void CReflector::StateReportThread() { std::string xmlpath, jsonpath; - +#ifndef NO_DHT + peers_changed = clients_changed = users_changed = true; +#endif if (g_Configure.Contains(g_Keys.files.xml)) xmlpath.assign(g_Configure.GetString(g_Keys.files.xml)); if (g_Configure.Contains(g_Keys.files.json)) @@ -370,9 +372,29 @@ void CReflector::XmlReportThread() } } - // and wait a bit + // and wait a bit and do something useful at the same time for (int i=0; i< XML_UPDATE_PERIOD && keep_running; i++) + { +#ifndef NO_DHT + // update the dht data, if needed + if (peers_changed) + { + PutDHTPeers(); + peers_changed = false; + } + if (clients_changed) + { + PutDHTClients(); + clients_changed = false; + } + if (users_changed) + { + PutDHTUsers(); + users_changed = false; + } +#endif std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + } } } @@ -382,32 +404,24 @@ void CReflector::XmlReportThread() void CReflector::OnPeersChanged(void) { #ifndef NO_DHT - PutDHTPeers(); + peers_changed = true; #endif } void CReflector::OnClientsChanged(void) { #ifndef NO_DHT - PutDHTClients(); + clients_changed = true; #endif } void CReflector::OnUsersChanged(void) { #ifndef NO_DHT - PutDHTUsers(); + users_changed = true; #endif } -// void CReflector::OnStreamOpen(const CCallsign &callsign) -// { -// } - -// void CReflector::OnStreamClose(const CCallsign &callsign) -// { - - //////////////////////////////////////////////////////////////////////////////////////// // modules & queues diff --git a/reflector/Reflector.h b/reflector/Reflector.h index 2f8376d..9f3c925 100644 --- a/reflector/Reflector.h +++ b/reflector/Reflector.h @@ -79,22 +79,22 @@ public: void OnPeersChanged(void); void OnClientsChanged(void); void OnUsersChanged(void); - // void OnStreamOpen(const CCallsign &); - // void OnStreamClose(const CCallsign &); +#ifndef NO_DHT + void GetDHTConfig(const std::string &cs); +#endif +protected: #ifndef NO_DHT // Publish DHT void PutDHTConfig(); void PutDHTPeers(); void PutDHTClients(); void PutDHTUsers(); - void GetDHTConfig(const std::string &cs); #endif -protected: // threads void RouterThread(const char); - void XmlReportThread(void); + void StateReportThread(void); // streams std::shared_ptr GetStream(char); @@ -128,6 +128,6 @@ protected: dht::DhtRunner node; dht::InfoHash refhash; unsigned int peers_put_count, clients_put_count, users_put_count; + std::atomic peers_changed, clients_changed, users_changed; #endif - }; From ba2042a8e7c0ca16ec541ffe5af66ac1f939d77b Mon Sep 17 00:00:00 2001 From: Tom Early Date: Sun, 2 Apr 2023 13:23:40 -0700 Subject: [PATCH 08/28] fixed bugs in urfd.* file handlers --- reflector/BlackWhiteSet.cpp | 2 +- reflector/BlackWhiteSet.h | 2 +- reflector/InterlinkMap.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/reflector/BlackWhiteSet.cpp b/reflector/BlackWhiteSet.cpp index 911df48..6359c25 100644 --- a/reflector/BlackWhiteSet.cpp +++ b/reflector/BlackWhiteSet.cpp @@ -97,7 +97,7 @@ bool CBlackWhiteSet::ReloadFromFile(void) { bool ok = false; - if ( m_Filename.empty() ) + if ( ! m_Filename.empty() ) { ok = LoadFromFile(m_Filename); } diff --git a/reflector/BlackWhiteSet.h b/reflector/BlackWhiteSet.h index 5b2797e..cf3efa7 100644 --- a/reflector/BlackWhiteSet.h +++ b/reflector/BlackWhiteSet.h @@ -31,7 +31,7 @@ class CBlackWhiteSet { public: // constructor - CBlackWhiteSet() : m_Filename(nullptr), m_LastModTime(0) {} + CBlackWhiteSet() : m_LastModTime(0) {} // locks void Lock(void) const { m_Mutex.lock(); } diff --git a/reflector/InterlinkMap.cpp b/reflector/InterlinkMap.cpp index 8466f90..23e35ff 100644 --- a/reflector/InterlinkMap.cpp +++ b/reflector/InterlinkMap.cpp @@ -33,7 +33,7 @@ CInterlinkMap::CInterlinkMap() { - m_Filename = nullptr; + m_Filename.clear(); ::memset(&m_LastModTime, 0, sizeof(time_t)); } @@ -119,7 +119,7 @@ bool CInterlinkMap::LoadFromFile(const std::string &filename) file.close(); // keep file path - m_Filename = filename; + m_Filename.assign(filename); // update time GetLastModTime(&m_LastModTime); From 86dbce8f1500c629f10b196016024a88e874e507 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Mon, 3 Apr 2023 10:49:01 -0700 Subject: [PATCH 09/28] renamed several items in dht value data --- reflector/Reflector.cpp | 12 ++++++------ reflector/urfd-dht-values.h | 21 ++++++++++++--------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/reflector/Reflector.cpp b/reflector/Reflector.cpp index da5cb0b..2c1e30b 100644 --- a/reflector/Reflector.cpp +++ b/reflector/Reflector.cpp @@ -544,7 +544,7 @@ void CReflector::PutDHTPeers() { const std::string cs(g_Configure.GetString(g_Keys.names.callsign)); // load it up - SUrfdPeers0 p; + SUrfdPeers1 p; time(&p.timestamp); p.sequence = peers_put_count++; auto peers = GetPeers(); @@ -555,7 +555,7 @@ void CReflector::PutDHTPeers() ReleasePeers(); auto nv = std::make_shared(p); - nv->user_type.assign("urfd-peers-0"); + nv->user_type.assign("urfd-peers-1"); nv->id = toUType(EUrfdValueID::Peers); node.putSigned( @@ -569,7 +569,7 @@ void CReflector::PutDHTPeers() void CReflector::PutDHTClients() { const std::string cs(g_Configure.GetString(g_Keys.names.callsign)); - SUrfdClients0 c; + SUrfdClients1 c; time(&c.timestamp); c.sequence = clients_put_count++; auto clients = GetClients(); @@ -580,7 +580,7 @@ void CReflector::PutDHTClients() ReleaseClients(); auto nv = std::make_shared(c); - nv->user_type.assign("urfd-clients-0"); + nv->user_type.assign("urfd-clients-1"); nv->id = toUType(EUrfdValueID::Clients); node.putSigned( @@ -594,7 +594,7 @@ void CReflector::PutDHTClients() void CReflector::PutDHTUsers() { const std::string cs(g_Configure.GetString(g_Keys.names.callsign)); - SUrfdUsers0 u; + SUrfdUsers1 u; time(&u.timestamp); u.sequence = users_put_count++; auto users = GetUsers(); @@ -605,7 +605,7 @@ void CReflector::PutDHTUsers() ReleaseUsers(); auto nv = std::make_shared(u); - nv->user_type.assign("urfd-users-0"); + nv->user_type.assign("urfd-users-1"); nv->id = toUType(EUrfdValueID::Users); node.putSigned( diff --git a/reflector/urfd-dht-values.h b/reflector/urfd-dht-values.h index 210c391..7c79bab 100644 --- a/reflector/urfd-dht-values.h +++ b/reflector/urfd-dht-values.h @@ -22,45 +22,48 @@ #include /* HELPERS */ +#ifndef TO_U_TYPE_DEF +#define TO_U_TYPE_DEF template constexpr auto toUType(E enumerator) noexcept { return static_cast>(enumerator); } // Item #10 in "Effective Modern C++", by Scott Meyers, O'REILLY +#endif enum class EUrfdValueID : uint64_t { Config=1, Peers=2, Clients=3, Users=4 }; /* PEERS */ -using PeerTuple = std::tuple; +using UrfdPeerTuple = std::tuple; enum class EUrfdPeerFields { Callsign, Modules, ConnectTime }; -struct SUrfdPeers0 +struct SUrfdPeers1 { std::time_t timestamp; unsigned int sequence; - std::list list; + std::list list; MSGPACK_DEFINE(timestamp, sequence, list) }; /* CLIENTS */ -using ClientTuple = std::tuple; +using UrfdClientTuple = std::tuple; enum class EUrfdClientFields { Callsign, Ip, Module, ConnectTime, LastHeardTime }; -struct SUrfdClients0 +struct SUrfdClients1 { std::time_t timestamp; unsigned int sequence; - std::list list; + std::list list; MSGPACK_DEFINE(timestamp, sequence, list) }; /* USERS */ -using UserTuple = std::tuple; +using UrfdUserTuple = std::tuple; enum class EUrfdUserFields { Callsign, ViaNode, OnModule, ViaPeer, LastHeardTime }; -struct SUrfdUsers0 +struct SUrfdUsers1 { std::time_t timestamp; unsigned int sequence; - std::list list; + std::list list; MSGPACK_DEFINE(timestamp, sequence, list) }; From ce66f2e260a5e3a4c1b5c741276c706ec6e71e39 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Mon, 3 Apr 2023 11:11:25 -0700 Subject: [PATCH 10/28] another rename --- reflector/Reflector.cpp | 8 ++++---- reflector/urfd-dht-values.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/reflector/Reflector.cpp b/reflector/Reflector.cpp index 2c1e30b..dd75b10 100644 --- a/reflector/Reflector.cpp +++ b/reflector/Reflector.cpp @@ -619,7 +619,7 @@ void CReflector::PutDHTUsers() void CReflector::PutDHTConfig() { const std::string cs(g_Configure.GetString(g_Keys.names.callsign)); - SUrfdConfig0 cfg; + SUrfdConfig1 cfg; time(&cfg.timestamp); cfg.cs.assign(cs); cfg.ipv4.assign(g_Configure.GetString(g_Keys.ip.ipv4address)); @@ -668,7 +668,7 @@ void CReflector::PutDHTConfig() void CReflector::GetDHTConfig(const std::string &cs) { - static SUrfdConfig0 cfg; + static SUrfdConfig1 cfg; cfg.timestamp = 0; // every time this is called, zero the timestamp auto item = g_GateKeeper.GetInterlinkMap()->FindMapItem(cs); g_GateKeeper.ReleaseInterlinkMap(); @@ -688,11 +688,11 @@ void CReflector::GetDHTConfig(const std::string &cs) [](const std::shared_ptr &v) { if (0 == v->user_type.compare("mrefd-config-1")) { - auto rdat = dht::Value::unpack(*v); + auto rdat = dht::Value::unpack(*v); if (rdat.timestamp > cfg.timestamp) { // the time stamp is the newest so far, so put it in the static cfg struct - cfg = dht::Value::unpack(*v); + cfg = dht::Value::unpack(*v); } } else diff --git a/reflector/urfd-dht-values.h b/reflector/urfd-dht-values.h index 7c79bab..ee147e6 100644 --- a/reflector/urfd-dht-values.h +++ b/reflector/urfd-dht-values.h @@ -74,7 +74,7 @@ enum class EUrfdPorts : unsigned { dcs, dextra, dmrplus, dplus, m17, mmdvm, nxdn enum class EUrfdAlMod : unsigned { nxdn, p25, ysf, SIZE }; enum class EUrfdTxRx : unsigned { rx, tx, SIZE }; enum class EUrfdRefId : unsigned { nxdn, p25, SIZE }; -struct SUrfdConfig0 +struct SUrfdConfig1 { std::time_t timestamp; std::string cs, ipv4, ipv6, mods, tcmods, url, email, sponsor, country, version; From 3efd6f6c07c6d16701e15eda47c4381ffcbd3416 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Mon, 3 Apr 2023 13:09:32 -0700 Subject: [PATCH 11/28] forgot one def --- reflector/Reflector.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reflector/Reflector.cpp b/reflector/Reflector.cpp index dd75b10..dbf0072 100644 --- a/reflector/Reflector.cpp +++ b/reflector/Reflector.cpp @@ -655,7 +655,7 @@ void CReflector::PutDHTConfig() cfg.description[m] = g_Configure.GetString(g_Keys.modules.descriptor[m-'A']); auto nv = std::make_shared(cfg); - nv->user_type.assign("urfd-config-0"); + nv->user_type.assign("urfd-config-1"); nv->id = toUType(EUrfdValueID::Config); node.putSigned( From f86518aa53bf366ad8097fde4d8a7a865cc9c5c7 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Mon, 3 Apr 2023 13:30:52 -0700 Subject: [PATCH 12/28] less log msgs --- reflector/Reflector.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/reflector/Reflector.cpp b/reflector/Reflector.cpp index dbf0072..d8e49a4 100644 --- a/reflector/Reflector.cpp +++ b/reflector/Reflector.cpp @@ -561,7 +561,11 @@ void CReflector::PutDHTPeers() node.putSigned( refhash, nv, +#ifdef DEBUG [](bool success){ std::cout << "PutDHTPeers() " << (success ? "successful" : "unsuccessful") << std::endl; }, +#else + [](bool success){ if (! success) std::cout << "PutDHTPeers() unsuccessful" << std::endl; }, +#endif true // permanent! ); } @@ -586,7 +590,11 @@ void CReflector::PutDHTClients() node.putSigned( refhash, nv, +#ifdef DEBUG [](bool success){ std::cout << "PutDHTClients() " << (success ? "successful" : "unsuccessful") << std::endl; }, +#else + [](bool success){ if (! success) std::cout << "PutDHTClients() unsuccessful" << std::endl; }, +#endif true // permanent! ); } @@ -611,7 +619,11 @@ void CReflector::PutDHTUsers() node.putSigned( refhash, nv, +#ifdef DEBUG [](bool success){ std::cout << "PutDHTUsers() " << (success ? "successful" : "unsuccessful") << std::endl; }, +#else + [](bool success){ if (! success) std::cout << "PutDHTUsers() unsuccessful" << std::endl; }, +#endif true // permanent! ); } @@ -661,7 +673,11 @@ void CReflector::PutDHTConfig() node.putSigned( refhash, nv, +#ifdef DEBUG [](bool success){ std::cout << "PutDHTConfig() " << (success ? "successful" : "unsuccessful") << std::endl; }, +#else + [](bool success){ if(! success) std::cout << "PutDHTConfig() unsuccessful" << std::endl; }, +#endif true ); } From 0da401b814d4628a7cc658c18a9f0b6e00f01099 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Thu, 6 Apr 2023 10:50:36 -0700 Subject: [PATCH 13/28] version bump --- reflector/Main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reflector/Main.cpp b/reflector/Main.cpp index 1bbd0d6..2ebd59b 100644 --- a/reflector/Main.cpp +++ b/reflector/Main.cpp @@ -28,7 +28,7 @@ SJsonKeys g_Keys; CReflector g_Reflector; CGateKeeper g_GateKeeper; CConfigure g_Configure; -CVersion g_Version(3,0,1); // The major byte should only change if the interlink packet changes! +CVersion g_Version(3,1,0); // The major byte should only change if the interlink packet changes! CLookupDmr g_LDid; CLookupNxdn g_LNid; CLookupYsf g_LYtr; From 385da379ccc08e2cf9a3c1f6972aebfa6af33dec Mon Sep 17 00:00:00 2001 From: Tom Early Date: Mon, 10 Apr 2023 09:28:02 -0700 Subject: [PATCH 14/28] URF default port is 10017 --- reflector/InterlinkMap.cpp | 6 +++--- reflector/URFProtocol.cpp | 23 +++++++++++++++++------ 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/reflector/InterlinkMap.cpp b/reflector/InterlinkMap.cpp index 23e35ff..088e2ed 100644 --- a/reflector/InterlinkMap.cpp +++ b/reflector/InterlinkMap.cpp @@ -76,14 +76,14 @@ bool CInterlinkMap::LoadFromFile(const std::string &filename) if (token[2]) { - int port = 17000; + int port = 10017; if (token[3]) { port = std::atoi(token[2]); if (port < 1024 || port > 49000) { - std::cout << token[0] << " Port " << port << " is out of range, resetting to 17000." << std::endl; - port = 17000; + std::cout << token[0] << " Port " << port << " is out of range, resetting to 10017." << std::endl; + port = 10017; } m_InterlinkMap[token[0]] = CInterlinkMapItem(token[1], token[3], (uint16_t)port); } diff --git a/reflector/URFProtocol.cpp b/reflector/URFProtocol.cpp index 35a6985..b789c68 100644 --- a/reflector/URFProtocol.cpp +++ b/reflector/URFProtocol.cpp @@ -337,7 +337,7 @@ void CURFProtocol::HandlePeerLinks(void) else if ((std::string::npos == it->second.GetTCMods().find(c)) != (std::string::npos == g_Configure.GetString(g_Keys.modules.tcmodules).find(c))) { // are the transcoding states on both sides mismatched? ok = false; - std::cerr << "The encryption states for module '" << c << "' don't match for this reflector and " << it->first << std::endl; + std::cerr << "The transcode states for module '" << c << "' don't match for this reflector and " << it->first << std::endl; } } } @@ -348,7 +348,7 @@ void CURFProtocol::HandlePeerLinks(void) // send connect packet to re-initiate peer link EncodeConnectPacket(&buffer, it->second.GetModules().c_str()); Send(buffer, it->second.GetIp(), it->second.GetPort()); - std::cout << "Sending connect packet to URF peer " << cs << " @ " << it->second.GetIp() << " for modules " << it->second.GetModules() << std::endl; + std::cout << "Sent connect packet to URF peer " << cs << " @ " << it->second.GetIp() << " for modules " << it->second.GetModules() << std::endl; #ifndef NO_DHT } } @@ -441,17 +441,28 @@ bool CURFProtocol::IsValidKeepAlivePacket(const CBuffer &Buffer, CCallsign *call bool CURFProtocol::IsValidConnectPacket(const CBuffer &Buffer, CCallsign *callsign, char *modules, CVersion *version) { - bool valid = false; + std::cout << "Checking for valid CONN packet\n"; + bool valid; uint8_t magic[] = { 'C','O','N','N' }; if ((Buffer.size() == 40) && (0 == Buffer.Compare(magic, 4)) && (Buffer.data()[36] == 0)) { callsign->CodeIn(Buffer.data()+4); valid = callsign->IsValid(); + std::cout << "Callsign '" << callsign->GetCS() << " is " << (valid ? "valid" : "not valid") << std::endl; *version = CVersion(Buffer.at(37), Buffer.at(38), Buffer.at(39)); - memcpy(modules, Buffer.data()+10, 27); - for ( unsigned i = 0; i < strlen(modules); i++ ) + std::cout << *callsign << " version: " << *version << std::endl; + if (valid) { - valid = valid && (g_Reflector.IsValidModule (modules[i])); + memcpy(modules, Buffer.data()+10, 27); + for ( unsigned i = 0; i < strlen(modules); i++ ) + { + auto moduleok = g_Reflector.IsValidModule(modules[i]); + if (! moduleok) + { + valid = false; + std::cout << "Requested module '" << modules[i] << "' is not confgured\n"; + } + } } } return valid; From b3d2a00533a6c49f928df9cba93e39ecebfc9973 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Mon, 10 Apr 2023 10:09:41 -0700 Subject: [PATCH 15/28] more fixes with interlink --- config/urfd.interlink | 2 +- reflector/InterlinkMap.cpp | 8 +++----- reflector/URFProtocol.cpp | 3 ++- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/config/urfd.interlink b/config/urfd.interlink index cdb7213..cba9bfd 100644 --- a/config/urfd.interlink +++ b/config/urfd.interlink @@ -3,7 +3,7 @@ # # One line per entry. # Each entry specifies a remote URF to peer with. -# If no Port is specified, 17000 will be used. +# If no Port is specified, 10017 will be used. # If DHT is enabled and the target is also DHT-enabled, then you only # need to specify the URF-Callsign and the Shared-Modules # format: diff --git a/reflector/InterlinkMap.cpp b/reflector/InterlinkMap.cpp index 088e2ed..b51b416 100644 --- a/reflector/InterlinkMap.cpp +++ b/reflector/InterlinkMap.cpp @@ -69,6 +69,8 @@ bool CInterlinkMap::LoadFromFile(const std::string &filename) { CCallsign callsign(token[0]); // read remaining tokens + // 1=IP 2=Modules 3=Port Port is optional and defaults to 10017 + // OR... 1=Modules and the dht will be used for (int i=1; i<4; i++) { token[i] = strtok(nullptr, delim); @@ -85,12 +87,8 @@ bool CInterlinkMap::LoadFromFile(const std::string &filename) std::cout << token[0] << " Port " << port << " is out of range, resetting to 10017." << std::endl; port = 10017; } - m_InterlinkMap[token[0]] = CInterlinkMapItem(token[1], token[3], (uint16_t)port); - } - else - { - m_InterlinkMap[token[0]] = CInterlinkMapItem(token[1], token[2], (uint16_t)port); } + m_InterlinkMap[token[0]] = CInterlinkMapItem(token[1], token[2], (uint16_t)port); } #ifndef NO_DHT else if (token[1]) diff --git a/reflector/URFProtocol.cpp b/reflector/URFProtocol.cpp index b789c68..eaef23f 100644 --- a/reflector/URFProtocol.cpp +++ b/reflector/URFProtocol.cpp @@ -65,6 +65,7 @@ void CURFProtocol::Task(void) if ( Receive4(Buffer, Ip, 20) ) #endif { + Buffer.Dump("Received buffer"); // crack the packet if ( IsValidDvFramePacket(Buffer, Frame) ) { @@ -348,7 +349,7 @@ void CURFProtocol::HandlePeerLinks(void) // send connect packet to re-initiate peer link EncodeConnectPacket(&buffer, it->second.GetModules().c_str()); Send(buffer, it->second.GetIp(), it->second.GetPort()); - std::cout << "Sent connect packet to URF peer " << cs << " @ " << it->second.GetIp() << " for modules " << it->second.GetModules() << std::endl; + std::cout << "Sent connect packet to URF peer " << cs << " @ " << it->second.GetIp() << " for modules " << it->second.GetModules() << " to port " << it->second.GetPort() << std::endl; #ifndef NO_DHT } } From 312c8f5a2bf6c64db4b556fea15ceaaa7f357223 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Mon, 10 Apr 2023 11:28:02 -0700 Subject: [PATCH 16/28] port is token[3] --- reflector/InterlinkMap.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reflector/InterlinkMap.cpp b/reflector/InterlinkMap.cpp index b51b416..d1cb570 100644 --- a/reflector/InterlinkMap.cpp +++ b/reflector/InterlinkMap.cpp @@ -81,7 +81,7 @@ bool CInterlinkMap::LoadFromFile(const std::string &filename) int port = 10017; if (token[3]) { - port = std::atoi(token[2]); + port = std::atoi(token[3]); if (port < 1024 || port > 49000) { std::cout << token[0] << " Port " << port << " is out of range, resetting to 10017." << std::endl; From 42120f849f100a51d1522f0149e01b8fd91607d8 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Mon, 10 Apr 2023 11:43:48 -0700 Subject: [PATCH 17/28] Send doesn't need the port # --- reflector/InterlinkMap.cpp | 1 + reflector/URFProtocol.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/reflector/InterlinkMap.cpp b/reflector/InterlinkMap.cpp index d1cb570..64bb36d 100644 --- a/reflector/InterlinkMap.cpp +++ b/reflector/InterlinkMap.cpp @@ -88,6 +88,7 @@ bool CInterlinkMap::LoadFromFile(const std::string &filename) port = 10017; } } + std::cout << "USING PORT " << port << std::endl; m_InterlinkMap[token[0]] = CInterlinkMapItem(token[1], token[2], (uint16_t)port); } #ifndef NO_DHT diff --git a/reflector/URFProtocol.cpp b/reflector/URFProtocol.cpp index eaef23f..d7cd26b 100644 --- a/reflector/URFProtocol.cpp +++ b/reflector/URFProtocol.cpp @@ -348,7 +348,7 @@ void CURFProtocol::HandlePeerLinks(void) #endif // send connect packet to re-initiate peer link EncodeConnectPacket(&buffer, it->second.GetModules().c_str()); - Send(buffer, it->second.GetIp(), it->second.GetPort()); + Send(buffer, it->second.GetIp()); std::cout << "Sent connect packet to URF peer " << cs << " @ " << it->second.GetIp() << " for modules " << it->second.GetModules() << " to port " << it->second.GetPort() << std::endl; #ifndef NO_DHT } From 5d677fdd0e0ac7910279f9e9ca1d2a4444a21ffe Mon Sep 17 00:00:00 2001 From: Tom Early Date: Mon, 10 Apr 2023 11:44:51 -0700 Subject: [PATCH 18/28] change msg --- reflector/URFProtocol.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reflector/URFProtocol.cpp b/reflector/URFProtocol.cpp index d7cd26b..df0de7e 100644 --- a/reflector/URFProtocol.cpp +++ b/reflector/URFProtocol.cpp @@ -349,7 +349,7 @@ void CURFProtocol::HandlePeerLinks(void) // send connect packet to re-initiate peer link EncodeConnectPacket(&buffer, it->second.GetModules().c_str()); Send(buffer, it->second.GetIp()); - std::cout << "Sent connect packet to URF peer " << cs << " @ " << it->second.GetIp() << " for modules " << it->second.GetModules() << " to port " << it->second.GetPort() << std::endl; + std::cout << "Sent connect packet to URF peer " << cs << " @ " << it->second.GetIp() << " for modules " << it->second.GetModules() << std::endl; #ifndef NO_DHT } } From 4da009a3298ae9090ce466a5a1327e82c9ae72d9 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Mon, 10 Apr 2023 12:44:13 -0700 Subject: [PATCH 19/28] Fixed bug if GetBase --- reflector/Callsign.cpp | 2 +- reflector/InterlinkMap.cpp | 13 ++++++++++++- reflector/URFProtocol.cpp | 1 - 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/reflector/Callsign.cpp b/reflector/Callsign.cpp index 84184b8..b4b9666 100644 --- a/reflector/Callsign.cpp +++ b/reflector/Callsign.cpp @@ -354,7 +354,7 @@ std::string CCallsign::GetBase() const auto u = GetKey(); std::string rval(u.c, CALLSIGN_LEN); auto pos = rval.find(' '); - if (std::string::npos == rval.find(' ')) + if (std::string::npos != pos) rval.resize(pos); return rval; } diff --git a/reflector/InterlinkMap.cpp b/reflector/InterlinkMap.cpp index 64bb36d..4767dc0 100644 --- a/reflector/InterlinkMap.cpp +++ b/reflector/InterlinkMap.cpp @@ -67,7 +67,6 @@ bool CInterlinkMap::LoadFromFile(const std::string &filename) { if (m_InterlinkMap.end() == m_InterlinkMap.find(token[0])) { - CCallsign callsign(token[0]); // read remaining tokens // 1=IP 2=Modules 3=Port Port is optional and defaults to 10017 // OR... 1=Modules and the dht will be used @@ -179,8 +178,20 @@ bool CInterlinkMap::IsCallsignListed(const std::string &callsign, const CIp &ip, { return true; } + else + { + std::cout << ip << " is not equal to " << item->second.GetIp() << std::endl; + } + } + else + { + std::cout << "Problem with linking " << callsign << " modules '" << modules << "'\n"; } } + else + { + std::cout << "'" << callsign << "' not found in interlink map\n"; + } return false; } diff --git a/reflector/URFProtocol.cpp b/reflector/URFProtocol.cpp index df0de7e..59c5dc9 100644 --- a/reflector/URFProtocol.cpp +++ b/reflector/URFProtocol.cpp @@ -65,7 +65,6 @@ void CURFProtocol::Task(void) if ( Receive4(Buffer, Ip, 20) ) #endif { - Buffer.Dump("Received buffer"); // crack the packet if ( IsValidDvFramePacket(Buffer, Frame) ) { From e3a211b0a5bd1a6b796e806eff13f002de8230f9 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Mon, 10 Apr 2023 12:52:47 -0700 Subject: [PATCH 20/28] remove some msgs --- reflector/URFProtocol.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/reflector/URFProtocol.cpp b/reflector/URFProtocol.cpp index 59c5dc9..1fd8865 100644 --- a/reflector/URFProtocol.cpp +++ b/reflector/URFProtocol.cpp @@ -441,16 +441,13 @@ bool CURFProtocol::IsValidKeepAlivePacket(const CBuffer &Buffer, CCallsign *call bool CURFProtocol::IsValidConnectPacket(const CBuffer &Buffer, CCallsign *callsign, char *modules, CVersion *version) { - std::cout << "Checking for valid CONN packet\n"; bool valid; uint8_t magic[] = { 'C','O','N','N' }; if ((Buffer.size() == 40) && (0 == Buffer.Compare(magic, 4)) && (Buffer.data()[36] == 0)) { callsign->CodeIn(Buffer.data()+4); valid = callsign->IsValid(); - std::cout << "Callsign '" << callsign->GetCS() << " is " << (valid ? "valid" : "not valid") << std::endl; *version = CVersion(Buffer.at(37), Buffer.at(38), Buffer.at(39)); - std::cout << *callsign << " version: " << *version << std::endl; if (valid) { memcpy(modules, Buffer.data()+10, 27); From b8dc598e38043f163ff65868122b1f38f0e52e33 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Mon, 10 Apr 2023 13:53:32 -0700 Subject: [PATCH 21/28] init return value --- reflector/URFProtocol.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reflector/URFProtocol.cpp b/reflector/URFProtocol.cpp index 1fd8865..52d7cb5 100644 --- a/reflector/URFProtocol.cpp +++ b/reflector/URFProtocol.cpp @@ -441,7 +441,7 @@ bool CURFProtocol::IsValidKeepAlivePacket(const CBuffer &Buffer, CCallsign *call bool CURFProtocol::IsValidConnectPacket(const CBuffer &Buffer, CCallsign *callsign, char *modules, CVersion *version) { - bool valid; + bool valid = false; uint8_t magic[] = { 'C','O','N','N' }; if ((Buffer.size() == 40) && (0 == Buffer.Compare(magic, 4)) && (Buffer.data()[36] == 0)) { From 0090135843f02cae0762eb2a6830243138f81182 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Mon, 10 Apr 2023 15:20:39 -0700 Subject: [PATCH 22/28] don't check for existance --- reflector/Reflector.cpp | 8 +------- reflector/URFProtocol.cpp | 4 +++- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/reflector/Reflector.cpp b/reflector/Reflector.cpp index d8e49a4..8d4fc76 100644 --- a/reflector/Reflector.cpp +++ b/reflector/Reflector.cpp @@ -686,13 +686,7 @@ void CReflector::GetDHTConfig(const std::string &cs) { static SUrfdConfig1 cfg; cfg.timestamp = 0; // every time this is called, zero the timestamp - auto item = g_GateKeeper.GetInterlinkMap()->FindMapItem(cs); - g_GateKeeper.ReleaseInterlinkMap(); - if (nullptr == item) - { - std::cerr << "Can't Get() for " << cs << " because it doesn't exist" << std::endl; - return; - } + std::cout << "Getting " << cs << " connection info..." << std::endl; // we only want the configuration section of the reflector's document diff --git a/reflector/URFProtocol.cpp b/reflector/URFProtocol.cpp index 52d7cb5..d14d6a0 100644 --- a/reflector/URFProtocol.cpp +++ b/reflector/URFProtocol.cpp @@ -312,7 +312,9 @@ void CURFProtocol::HandlePeerLinks(void) for ( auto it=ilmap->begin(); it!=ilmap->end(); it++ ) { const auto cs = it->first; - if ((0 == cs.substr(0, 3).compare("URF")) && (nullptr==peers->FindPeer(CCallsign(cs), EProtocol::urf))) + CCallsign callsign; + callsign.SetCallsign(cs, false); + if ((0 == cs.substr(0, 3).compare("URF")) && (nullptr==peers->FindPeer(callsign, EProtocol::urf))) { #ifndef NO_DHT it->second.UpdateIP(g_Configure.GetString(g_Keys.ip.ipv6address).empty()); From 07e57dffb174994ef91fc3818bdda4991288a0eb Mon Sep 17 00:00:00 2001 From: Tom Early Date: Mon, 10 Apr 2023 15:25:02 -0700 Subject: [PATCH 23/28] fixed user_type check --- reflector/Reflector.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reflector/Reflector.cpp b/reflector/Reflector.cpp index 8d4fc76..9324504 100644 --- a/reflector/Reflector.cpp +++ b/reflector/Reflector.cpp @@ -696,7 +696,7 @@ void CReflector::GetDHTConfig(const std::string &cs) node.get( dht::InfoHash::get(cs), [](const std::shared_ptr &v) { - if (0 == v->user_type.compare("mrefd-config-1")) + if (0 == v->user_type.compare("urfd-config-1")) { auto rdat = dht::Value::unpack(*v); if (rdat.timestamp > cfg.timestamp) From 86abe51a6dada316ee7e9ef2e7ca6c10cc235a79 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Mon, 10 Apr 2023 15:33:34 -0700 Subject: [PATCH 24/28] release interlink lock --- reflector/Reflector.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/reflector/Reflector.cpp b/reflector/Reflector.cpp index 9324504..afe9505 100644 --- a/reflector/Reflector.cpp +++ b/reflector/Reflector.cpp @@ -718,6 +718,11 @@ void CReflector::GetDHTConfig(const std::string &cs) { // if the get() call was successful and there is a nonzero timestamp, then do the update g_GateKeeper.GetInterlinkMap()->Update(cfg.cs, cfg.mods, cfg.ipv4, cfg.ipv6, cfg.port[toUType(EUrfdPorts::urf)], cfg.tcmods); + g_GateKeeper.ReleaseInterlinkMap(); + } + else + { + std::cerr << "node.Get() was successful, but the timestamp was zero" << std::endl; } } else From 5972139ce837fa217a87e5f7efdcd3ee35195e81 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Mon, 10 Apr 2023 15:42:20 -0700 Subject: [PATCH 25/28] rm some msgs --- reflector/InterlinkMap.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/reflector/InterlinkMap.cpp b/reflector/InterlinkMap.cpp index 4767dc0..90d13dd 100644 --- a/reflector/InterlinkMap.cpp +++ b/reflector/InterlinkMap.cpp @@ -178,14 +178,6 @@ bool CInterlinkMap::IsCallsignListed(const std::string &callsign, const CIp &ip, { return true; } - else - { - std::cout << ip << " is not equal to " << item->second.GetIp() << std::endl; - } - } - else - { - std::cout << "Problem with linking " << callsign << " modules '" << modules << "'\n"; } } else From c017be2207a3bc0c4ac50cd48c38d4bd947c4562 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Wed, 12 Apr 2023 04:50:09 -0700 Subject: [PATCH 26/28] default port depenods on protocol --- config/urfd.interlink | 11 +++++++---- reflector/InterlinkMap.cpp | 9 +++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/config/urfd.interlink b/config/urfd.interlink index cba9bfd..b0c49a7 100644 --- a/config/urfd.interlink +++ b/config/urfd.interlink @@ -5,13 +5,16 @@ # Each entry specifies a remote URF to peer with. # If no Port is specified, 10017 will be used. # If DHT is enabled and the target is also DHT-enabled, then you only -# need to specify the URF-Callsign and the Shared-Modules -# format: +# need to specify the URF-Callsign and the Shared-Modules. +# Format: # -# examples: +# Examples: # URF270 158.64.26.132 EF # URF280 ABC # -# note: The remote URFD must list this in its interlink file +# Brandmeister links use three params, no port is specified. Example: +# BM3104 162.248.88.117 E +# +# note: Remote URFD must list this in its interlink file # for the link to be established. ############################################################################# diff --git a/reflector/InterlinkMap.cpp b/reflector/InterlinkMap.cpp index 90d13dd..4e32600 100644 --- a/reflector/InterlinkMap.cpp +++ b/reflector/InterlinkMap.cpp @@ -65,6 +65,8 @@ bool CInterlinkMap::LoadFromFile(const std::string &filename) { if (strcmp(token[0], g_Configure.GetString(g_Keys.names.callsign).c_str())) { + // the default port depends on the protocol type (URF or BM) + int default_port = (0 == memcmp(token[0], "URF", 3)) ? 10017 : 10002; if (m_InterlinkMap.end() == m_InterlinkMap.find(token[0])) { // read remaining tokens @@ -77,17 +79,16 @@ bool CInterlinkMap::LoadFromFile(const std::string &filename) if (token[2]) { - int port = 10017; + int port = default_port; if (token[3]) { port = std::atoi(token[3]); if (port < 1024 || port > 49000) { - std::cout << token[0] << " Port " << port << " is out of range, resetting to 10017." << std::endl; - port = 10017; + std::cout << token[0] << " Port " << port << " is out of range, resetting to " << default_port << std::endl; + port = default_port; } } - std::cout << "USING PORT " << port << std::endl; m_InterlinkMap[token[0]] = CInterlinkMapItem(token[1], token[2], (uint16_t)port); } #ifndef NO_DHT From 0ed942fbd76b2d137c429f716e567405ba01e44c Mon Sep 17 00:00:00 2001 From: Tom Early Date: Thu, 13 Apr 2023 05:55:57 -0700 Subject: [PATCH 27/28] Version 3.1.0 --- README.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/README.md b/README.md index 95dbb5c..9ec011b 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,29 @@ sudo apt install build-essential sudo apt install nlohmann-json3-dev ``` +### DVIN support (optional, but highly recommended) + +**DVIN**, the Digital Voice Information Network, is implemented using a distributed hash table provided by OpenDHT. + +OpenDHT is available [here](https://github./com/savoirfairelinux/opendht.git). Building and installing instructions are in the [OpenDHT Wiki](https://github.com/savoirfairelinux/opendht/wiki/Build-the-library). Pascal support and proxy-server support (RESTinio) is not required for mrefd and so can be considered optional. With this in mind, this should work on Debian/Ubuntu-based systems: + +```bash +# Install OpenDHT dependencies +sudo apt install libncurses5-dev libreadline-dev nettle-dev libgnutls28-dev libargon2-0-dev libmsgpack-dev libssl-dev libfmt-dev libjsoncpp-dev libhttp-parser-dev libasio-dev cmake pkg-config libcppunit-dev + +# clone the repo +git clone https://github.com/savoirfairelinux/opendht.git + +# build and install +cd opendht +mkdir build && cd build +cmake -DOPENDHT_PYTHON=OFF -DCMAKE_INSTALL_PREFIX=/usr .. +make +sudo make install +``` + +Please note that there is no easy way to uninstall OpenDHT once it's been installed. + ### Download and build the repository and ```bash From e5138a6f7291f1cdf2a9295a3f075beed0c47d51 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Thu, 13 Apr 2023 06:08:02 -0700 Subject: [PATCH 28/28] typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9ec011b..aaa502f 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ sudo apt install nlohmann-json3-dev **DVIN**, the Digital Voice Information Network, is implemented using a distributed hash table provided by OpenDHT. -OpenDHT is available [here](https://github./com/savoirfairelinux/opendht.git). Building and installing instructions are in the [OpenDHT Wiki](https://github.com/savoirfairelinux/opendht/wiki/Build-the-library). Pascal support and proxy-server support (RESTinio) is not required for mrefd and so can be considered optional. With this in mind, this should work on Debian/Ubuntu-based systems: +OpenDHT is available [here](https://github./com/savoirfairelinux/opendht.git). Building and installing instructions are in the [OpenDHT Wiki](https://github.com/savoirfairelinux/opendht/wiki/Build-the-library). Pascal support and proxy-server support (RESTinio) is not required for urfd and so can be considered optional. With this in mind, this should work on Debian/Ubuntu-based systems: ```bash # Install OpenDHT dependencies