From 1ed0ab297134f2feec50e34f79687b2a3122929c Mon Sep 17 00:00:00 2001 From: Tom Early Date: Thu, 30 Mar 2023 13:35:37 -0700 Subject: [PATCH] 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(); }