Rewrote blacklist, whitelist and interlink classes

pull/2/head
Tom Early 3 years ago
parent 9465842bf3
commit 1ed0ab2971

@ -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:
# <URF callsign> <ip> <list of modules shared>
# example:
# URF270 158.64.26.132 ACD
#
# note: the remote URFD must list this in its interlink file
# for the link to be established
# <URF-Callsign> <IP-Address> <Shared-Mdoules> <Port>
# 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.
#############################################################################

@ -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_ptr<CPeer>peer = 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();
}

@ -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 <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#include <iostream>
#include <fstream>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#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;
}

@ -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 <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#pragma once
#include <set>
#include <string>
#include <mutex>
////////////////////////////////////////////////////////////////////////////////////////
// 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<std::string> m_Callsigns;
};

@ -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

@ -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<uint64_t> 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);

@ -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 <https://www.gnu.org/licenses/>.
#include <fstream>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#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;
}

@ -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 <https://www.gnu.org/licenses/>.
#pragma once
#include <list>
#include <mutex>
#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<CCallsignListItem>::iterator begin() { return m_Callsigns.begin(); }
std::list<CCallsignListItem>::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<CCallsignListItem> m_Callsigns;
};

@ -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 <https://www.gnu.org/licenses/>.
#include <string.h>
#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<n; i++)
{
if (std::string::npos != mods.find(modules[i]))
{
m_Modules[j++] = modules[i];
}
}
}
}
}
CCallsignListItem::CCallsignListItem(const CCallsign &callsign, const char *url, const char *modules)
{
const std::string mods(g_Configure.GetString(g_Keys.modules.modules));
m_Callsign = callsign;
::strncpy(m_szUrl, url, URL_MAXLEN);
m_Ip = CIp(m_szUrl);
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<n; i++)
{
if (std::string::npos != mods.find(modules[i]))
{
m_Modules[j++] = modules[i];
}
}
}
}
}
CCallsignListItem::CCallsignListItem(const CCallsignListItem &item)
{
m_Callsign = item.m_Callsign;
memcpy(m_szUrl, item.m_szUrl, sizeof(m_szUrl));
m_Ip = item.m_Ip;
memcpy(m_Modules, item.m_Modules, sizeof(m_Modules));
}
////////////////////////////////////////////////////////////////////////////////////////
// compare
bool CCallsignListItem::HasSameCallsign(const CCallsign &callsign) const
{
return m_Callsign.HasSameCallsign(callsign);
}
bool CCallsignListItem::HasSameCallsignWithWildcard(const CCallsign &callsign) const
{
return m_Callsign.HasSameCallsignWithWildcard(callsign);
}
bool CCallsignListItem::HasModuleListed(char module) const
{
return (::strchr(m_Modules, (int)module) != nullptr);
}
bool CCallsignListItem::CheckListedModules(char *Modules) const
{
bool listed = false;
if ( Modules != nullptr )
{
// build a list of common modules
char list[27];
list[0] = 0;
//
for ( unsigned i = 0; i < ::strlen(Modules); i++ )
{
if ( HasModuleListed(Modules[i]) )
{
::strncat(list, &(Modules[i]), 1);
listed = true;
}
}
::strcpy(Modules, list);
}
return listed;
}

@ -1,65 +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 <https://www.gnu.org/licenses/>.
#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];
};

@ -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,19 +89,17 @@ 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;
@ -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

@ -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<bool> keep_running;

@ -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 <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#include <fstream>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#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

@ -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 <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#pragma once
#include <mutex>
#include <map>
#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<std::string, CInterlinkMapItem>::iterator begin() { return m_InterlinkMap.begin(); }
std::map<std::string, CInterlinkMapItem>::iterator end() { return m_InterlinkMap.end(); }
std::map<std::string, CInterlinkMapItem>::const_iterator cbegin() { return m_InterlinkMap.cbegin(); }
std::map<std::string, CInterlinkMapItem>::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<std::string, CInterlinkMapItem> m_InterlinkMap;
};

@ -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 <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#include <string.h>
#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<count; i++)
found[i] = false;
for (auto p=mods; *p; p++)
{
auto pos = m_Mods.find(*p);
if (pos == m_Mods.npos)
return false;
else
found[pos] = true;
}
for (unsigned i=0; i<count; i++)
{
if (! found[i])
return false;
}
return true;
}
#ifndef NO_DHT
void CInterlinkMapItem::UpdateItem(const std::string &cmods, const std::string &ipv4, const std::string &ipv6, uint16_t port, const std::string &tcmods)
{
if (m_CMods.compare(cmods))
{
m_CMods.assign(cmods);
m_Updated = true;
}
if (m_IPv4.compare(ipv4))
{
m_IPv4.assign(ipv4);
m_Updated = true;
}
if (m_IPv6.compare(ipv6))
{
m_IPv6.assign(ipv6);
m_Updated = true;
}
if (m_Port != port)
{
m_Port = port;
m_Updated = true;
}
if (m_TCMods.compare(tcmods))
{
m_TCMods.assign(tcmods);
m_Updated = true;
}
}
void CInterlinkMapItem::UpdateIP(bool IPv6NotConfigured)
{
if (m_Updated)
{
if (IPv6NotConfigured || m_IPv6.empty())
m_Ip.Initialize(AF_INET, m_Port, m_IPv4.c_str());
else
m_Ip.Initialize(AF_INET6, m_Port, m_IPv6.c_str());
m_Updated = false;
}
}
#endif

@ -0,0 +1,74 @@
//
// Created by Jean-Luc Deltombe (LX3JL) on 31/01/2016.
// 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 <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#pragma once
#include <string>
#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
};

@ -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<uint64_t> hash;
return hash(ucs.l);
}
};
struct CCallsignEqual
{
bool operator() (const UCallsign &ucs1, const UCallsign &ucs2) const
{
return ucs1.l == ucs2.l;
}
};
////////////////////////////////////////////////////////////////////////////////////////
class CLookup

@ -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 <https://www.gnu.org/licenses/>.
#include <fstream>
#include <string.h>
#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;
}

@ -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 <https://www.gnu.org/licenses/>.
#pragma once
#include "CallsignList.h"
////////////////////////////////////////////////////////////////////////////////////////
// class
class CPeerCallsignList : public CCallsignList
{
public:
// constructor
CPeerCallsignList() {}
// destructor
virtual ~CPeerCallsignList() {}
// file io
bool LoadFromFile(const std::string &filename);
};

@ -642,7 +642,6 @@ void CReflector::PutDHTConfig()
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);
@ -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

@ -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_ptr<CPeer>peer = 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();
}

Loading…
Cancel
Save

Powered by TurnKey Linux.