diff --git a/.gitignore b/.gitignore
index 2971bab..df15a05 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,4 +10,5 @@ configure.h
configure.sql
reflector.cfg
wiresx/configure.php
-urfd
+urfd*
+inicheck
diff --git a/reflector/BMClient.cpp b/reflector/BMClient.cpp
index ed5caaa..59b037c 100644
--- a/reflector/BMClient.cpp
+++ b/reflector/BMClient.cpp
@@ -17,7 +17,7 @@
// along with this program. If not, see .
#include
-#include "Main.h"
+
#include "BMClient.h"
diff --git a/reflector/BMPeer.cpp b/reflector/BMPeer.cpp
index e688697..6bcd756 100644
--- a/reflector/BMPeer.cpp
+++ b/reflector/BMPeer.cpp
@@ -17,7 +17,7 @@
// along with this program. If not, see .
-#include "Main.h"
+
#include
#include "Reflector.h"
#include "BMPeer.h"
diff --git a/reflector/BMProtocol.cpp b/reflector/BMProtocol.cpp
index 13a2c09..dae8b90 100644
--- a/reflector/BMProtocol.cpp
+++ b/reflector/BMProtocol.cpp
@@ -18,7 +18,7 @@
#include
-#include "Main.h"
+
#include "BMPeer.h"
#include "BMProtocol.h"
#include "Reflector.h"
@@ -73,7 +73,7 @@ void CBMProtocol::Task(void)
else if ( IsValidDvHeaderPacket(Buffer, Header) )
{
// callsign allowed?
- if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip) )
+ if ( g_Gate.MayTransmit(Header->GetMyCallsign(), Ip) )
{
OnDvHeaderPacketIn(Header, Ip);
}
@@ -83,7 +83,7 @@ void CBMProtocol::Task(void)
std::cout << "XLX (" << Version.GetMajor() << "." << Version.GetMinor() << "." << Version.GetRevision() << ") connect packet for modules " << Modules << " from " << Callsign << " at " << Ip << std::endl;
// callsign authorized?
- if ( g_GateKeeper.MayLink(Callsign, Ip, EProtocol::bm, Modules) )
+ if ( g_Gate.MayLink(Callsign, Ip, EProtocol::bm, Modules) )
{
// acknowledge the request
EncodeConnectAckPacket(&Buffer, Modules);
@@ -101,10 +101,10 @@ void CBMProtocol::Task(void)
std::cout << "XLX ack packet for modules " << Modules << " from " << Callsign << " at " << Ip << std::endl;
// callsign authorized?
- if ( g_GateKeeper.MayLink(Callsign, Ip, EProtocol::bm, Modules) )
+ if ( g_Gate.MayLink(Callsign, Ip, EProtocol::bm, Modules) )
{
// already connected ?
- CPeers *peers = g_Reflector.GetPeers();
+ CPeers *peers = g_Refl..GetPeers();
if ( peers->FindPeer(Callsign, Ip, EProtocol::bm) == nullptr )
{
// create the new peer
@@ -115,7 +115,7 @@ void CBMProtocol::Task(void)
// this also add all new clients to reflector client list
peers->AddPeer(peer);
}
- g_Reflector.ReleasePeers();
+ g_Refl..ReleasePeers();
}
}
else if ( IsValidDisconnectPacket(Buffer, &Callsign) )
@@ -123,7 +123,7 @@ void CBMProtocol::Task(void)
std::cout << "XLX disconnect packet from " << Callsign << " at " << Ip << std::endl;
// find peer
- CPeers *peers = g_Reflector.GetPeers();
+ CPeers *peers = g_Refl..GetPeers();
std::shared_ptrpeer = peers->FindPeer(Ip, EProtocol::bm);
if ( peer != nullptr )
{
@@ -132,7 +132,7 @@ void CBMProtocol::Task(void)
// and delete them
peers->RemovePeer(peer);
}
- g_Reflector.ReleasePeers();
+ g_Refl..ReleasePeers();
}
else if ( IsValidNackPacket(Buffer, &Callsign) )
{
@@ -143,14 +143,14 @@ void CBMProtocol::Task(void)
//std::cout << "XLX keepalive packet from " << Callsign << " at " << Ip << std::endl;
// find peer
- CPeers *peers = g_Reflector.GetPeers();
+ CPeers *peers = g_Refl..GetPeers();
std::shared_ptrpeer = peers->FindPeer(Ip, EProtocol::bm);
if ( peer != nullptr )
{
// keep it alive
peer->Alive();
}
- g_Reflector.ReleasePeers();
+ g_Refl..ReleasePeers();
}
else
{
@@ -210,7 +210,7 @@ void CBMProtocol::HandleQueue(void)
}
// and push it to all our clients linked to the module and who are not streaming in
- CClients *clients = g_Reflector.GetClients();
+ CClients *clients = g_Refl..GetClients();
auto it = clients->begin();
std::shared_ptrclient = nullptr;
while ( (client = clients->FindNextClient(EProtocol::bm, it)) != nullptr )
@@ -237,7 +237,7 @@ void CBMProtocol::HandleQueue(void)
}
}
}
- g_Reflector.ReleaseClients();
+ g_Refl..ReleaseClients();
}
}
m_Queue.Unlock();
@@ -255,7 +255,7 @@ void CBMProtocol::HandleKeepalives(void)
EncodeKeepAlivePacket(&keepalive);
// iterate on peers
- CPeers *peers = g_Reflector.GetPeers();
+ CPeers *peers = g_Refl..GetPeers();
auto pit = peers->begin();
std::shared_ptrpeer = nullptr;
while ( (peer = peers->FindNextPeer(EProtocol::bm, pit)) != nullptr )
@@ -282,7 +282,7 @@ void CBMProtocol::HandleKeepalives(void)
peers->RemovePeer(peer);
}
}
- g_Reflector.ReleasePeers();
+ g_Refl..ReleasePeers();
}
////////////////////////////////////////////////////////////////////////////////////////
@@ -293,8 +293,8 @@ void CBMProtocol::HandlePeerLinks(void)
CBuffer buffer;
// get the list of peers
- CPeerCallsignList *list = g_GateKeeper.GetPeerList();
- CPeers *peers = g_Reflector.GetPeers();
+ CPeerCallsignList *list = g_Gate.GetPeerList();
+ CPeers *peers = g_Refl..GetPeers();
// check if all our connected peers are still listed by gatekeeper
// if not, disconnect
@@ -330,8 +330,8 @@ void CBMProtocol::HandlePeerLinks(void)
}
// done
- g_Reflector.ReleasePeers();
- g_GateKeeper.ReleasePeerList();
+ g_Refl..ReleasePeers();
+ g_Gate.ReleasePeerList();
}
@@ -360,11 +360,11 @@ void CBMProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header, c
CCallsign rpt2(Header->GetRpt2Callsign());
// no stream open yet, open a new one
// find this client
- std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, EProtocol::bm, Header->GetRpt2Module());
+ std::shared_ptrclient = g_Refl..GetClients()->FindClient(Ip, EProtocol::bm, Header->GetRpt2Module());
if ( client )
{
// and try to open the stream
- if ( (stream = g_Reflector.OpenStream(Header, client)) != nullptr )
+ if ( (stream = g_Refl..OpenStream(Header, client)) != nullptr )
{
// keep the handle
m_Streams[stream->GetStreamId()] = stream;
@@ -373,10 +373,10 @@ void CBMProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header, c
peer = client->GetCallsign();
}
// release
- g_Reflector.ReleaseClients();
+ g_Refl..ReleaseClients();
// update last heard
- g_Reflector.GetUsers()->Hearing(my, rpt1, rpt2, peer);
- g_Reflector.ReleaseUsers();
+ g_Refl..GetUsers()->Hearing(my, rpt1, rpt2, peer);
+ g_Refl..ReleaseUsers();
}
}
diff --git a/reflector/Buffer.h b/reflector/Buffer.h
index deec049..12eb495 100644
--- a/reflector/Buffer.h
+++ b/reflector/Buffer.h
@@ -20,7 +20,6 @@
#include
#include
-#include "Main.h"
////////////////////////////////////////////////////////////////////////////////////////
diff --git a/reflector/Callsign.cpp b/reflector/Callsign.cpp
index a1b256b..c8749b3 100644
--- a/reflector/Callsign.cpp
+++ b/reflector/Callsign.cpp
@@ -16,7 +16,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-#include "Main.h"
+
#include
#include
#include "DMRIdDirFile.h"
@@ -67,62 +67,62 @@ CCallsign::CCallsign(const char *sz, uint32_t dmrid, uint16_t nxdnid)
// dmrid ok ?
if ( m_uiDmrid == 0 )
{
- g_DmridDir.Lock();
+ g_LDid.Lock();
{
- m_uiDmrid = g_DmridDir.FindDmrid(*this);
+ m_uiDmrid = g_LDid.FindDmrid(*this);
}
- g_DmridDir.Unlock();
+ g_LDid.Unlock();
}
if ( m_uiNXDNid == 0 )
{
- g_NXDNidDir.Lock();
+ g_LNid.Lock();
{
- m_uiNXDNid = g_NXDNidDir.FindNXDNid(*this);
+ m_uiNXDNid = g_LNid.FindNXDNid(*this);
}
- g_NXDNidDir.Unlock();
+ g_LNid.Unlock();
}
}
else if ( m_uiDmrid != 0 )
{
- g_DmridDir.Lock();
+ g_LDid.Lock();
{
- const CCallsign *callsign = g_DmridDir.FindCallsign(m_uiDmrid);
+ const CCallsign *callsign = g_LDid.FindCallsign(m_uiDmrid);
if ( callsign != nullptr )
{
memcpy(m_Callsign, callsign->m_Callsign, CALLSIGN_LEN);
}
}
- g_DmridDir.Unlock();
-
+ g_LDid.Unlock();
+
if ( m_uiNXDNid == 0 )
{
- g_NXDNidDir.Lock();
+ g_LNid.Lock();
{
- m_uiNXDNid = g_NXDNidDir.FindNXDNid(*this);
+ m_uiNXDNid = g_LNid.FindNXDNid(*this);
}
- g_NXDNidDir.Unlock();
+ g_LNid.Unlock();
}
CSIn();
}
else if ( m_uiNXDNid != 0 )
{
- g_NXDNidDir.Lock();
+ g_LNid.Lock();
{
- const CCallsign *callsign = g_NXDNidDir.FindCallsign(m_uiNXDNid);
+ const CCallsign *callsign = g_LNid.FindCallsign(m_uiNXDNid);
if ( callsign != nullptr )
{
memcpy(m_Callsign, callsign->m_Callsign, CALLSIGN_LEN);
}
}
- g_NXDNidDir.Unlock();
-
+ g_LNid.Unlock();
+
if ( m_uiDmrid == 0 )
{
- g_DmridDir.Lock();
+ g_LDid.Lock();
{
- m_uiDmrid = g_DmridDir.FindDmrid(*this);
+ m_uiDmrid = g_LDid.FindDmrid(*this);
}
- g_DmridDir.Unlock();
+ g_LDid.Unlock();
}
CSIn();
}
@@ -201,16 +201,16 @@ void CCallsign::SetCallsign(const char *sz, bool UpdateDmrid)
// and update dmrid
if ( UpdateDmrid )
{
- g_DmridDir.Lock();
+ g_LDid.Lock();
{
- m_uiDmrid = g_DmridDir.FindDmrid(*this);
+ m_uiDmrid = g_LDid.FindDmrid(*this);
}
- g_DmridDir.Unlock();
- g_NXDNidDir.Lock();
+ g_LDid.Unlock();
+ g_LNid.Lock();
{
- m_uiNXDNid = g_NXDNidDir.FindNXDNid(*this);
+ m_uiNXDNid = g_LNid.FindNXDNid(*this);
}
- g_NXDNidDir.Unlock();
+ g_LNid.Unlock();
}
}
@@ -234,16 +234,16 @@ void CCallsign::SetCallsign(const uint8_t *buffer, int len, bool UpdateDmrid)
CSIn();
if ( UpdateDmrid )
{
- g_DmridDir.Lock();
+ g_LDid.Lock();
{
- m_uiDmrid = g_DmridDir.FindDmrid(*this);
+ m_uiDmrid = g_LDid.FindDmrid(*this);
}
- g_DmridDir.Unlock();
- g_NXDNidDir.Lock();
+ g_LDid.Unlock();
+ g_LNid.Lock();
{
- m_uiNXDNid = g_NXDNidDir.FindNXDNid(*this);
+ m_uiNXDNid = g_LNid.FindNXDNid(*this);
}
- g_NXDNidDir.Unlock();
+ g_LNid.Unlock();
}
}
@@ -252,15 +252,15 @@ void CCallsign::SetDmrid(uint32_t dmrid, bool UpdateCallsign)
m_uiDmrid = dmrid;
if ( UpdateCallsign )
{
- g_DmridDir.Lock();
+ g_LDid.Lock();
{
- const CCallsign *callsign = g_DmridDir.FindCallsign(dmrid);
+ const CCallsign *callsign = g_LDid.FindCallsign(dmrid);
if ( callsign != nullptr )
{
memcpy(m_Callsign, callsign->m_Callsign, CALLSIGN_LEN);
}
}
- g_DmridDir.Unlock();
+ g_LDid.Unlock();
}
}
@@ -277,15 +277,15 @@ void CCallsign::SetNXDNid(uint16_t nxdnid, bool UpdateCallsign)
m_uiNXDNid = nxdnid;
if ( UpdateCallsign )
{
- g_DmridDir.Lock();
+ g_LDid.Lock();
{
- const CCallsign *callsign = g_NXDNidDir.FindCallsign(nxdnid);
+ const CCallsign *callsign = g_LNid.FindCallsign(nxdnid);
if ( callsign != nullptr )
{
memcpy(m_Callsign, callsign->m_Callsign, CALLSIGN_LEN);
}
}
- g_NXDNidDir.Unlock();
+ g_LNid.Unlock();
}
}
diff --git a/reflector/CallsignList.cpp b/reflector/CallsignList.cpp
index cb4423b..2fff96b 100644
--- a/reflector/CallsignList.cpp
+++ b/reflector/CallsignList.cpp
@@ -19,7 +19,7 @@
#include
#include
#include
-#include "Main.h"
+
#include "CallsignList.h"
////////////////////////////////////////////////////////////////////////////////////////
diff --git a/reflector/CallsignList.h b/reflector/CallsignList.h
index 8ed2c9c..c9ba29a 100644
--- a/reflector/CallsignList.h
+++ b/reflector/CallsignList.h
@@ -17,7 +17,7 @@
// along with this program. If not, see .
#pragma once
-#include "Main.h"
+
#include "CallsignListItem.h"
////////////////////////////////////////////////////////////////////////////////////////
diff --git a/reflector/CallsignListItem.cpp b/reflector/CallsignListItem.cpp
index ac0034c..c6a5808 100644
--- a/reflector/CallsignListItem.cpp
+++ b/reflector/CallsignListItem.cpp
@@ -17,7 +17,7 @@
// along with this program. If not, see .
#include
-#include "Main.h"
+
#include "CallsignListItem.h"
////////////////////////////////////////////////////////////////////////////////////////
diff --git a/reflector/CallsignListItem.h b/reflector/CallsignListItem.h
index 2699567..daa5478 100644
--- a/reflector/CallsignListItem.h
+++ b/reflector/CallsignListItem.h
@@ -18,7 +18,7 @@
#pragma once
-#include "Main.h"
+
#include "Callsign.h"
#include "IP.h"
diff --git a/reflector/Client.cpp b/reflector/Client.cpp
index 71c6a84..93f27ad 100644
--- a/reflector/Client.cpp
+++ b/reflector/Client.cpp
@@ -16,7 +16,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-#include "Main.h"
+
#include
#include "Client.h"
diff --git a/reflector/Clients.cpp b/reflector/Clients.cpp
index e058070..eb83e53 100644
--- a/reflector/Clients.cpp
+++ b/reflector/Clients.cpp
@@ -16,7 +16,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-#include "Main.h"
+
#include "Reflector.h"
#include "Clients.h"
@@ -66,7 +66,7 @@ void CClients::AddClient(std::shared_ptr client)
}
std::cout << std::endl;
// notify
- g_Reflector.OnClientsChanged();
+ g_Refl..OnClientsChanged();
}
void CClients::RemoveClient(std::shared_ptr client)
@@ -90,7 +90,7 @@ void CClients::RemoveClient(std::shared_ptr client)
std::cout << std::endl;
m_Clients.erase(it);
// notify
- g_Reflector.OnClientsChanged();
+ g_Refl..OnClientsChanged();
break;
}
}
diff --git a/reflector/CodecStream.cpp b/reflector/CodecStream.cpp
index 3d7aa1e..a1f641f 100644
--- a/reflector/CodecStream.cpp
+++ b/reflector/CodecStream.cpp
@@ -16,7 +16,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-#include "Main.h"
+
#include
#include "CodecStream.h"
#include "DVFramePacket.h"
@@ -25,7 +25,12 @@
////////////////////////////////////////////////////////////////////////////////////////
// constructor
-CCodecStream::CCodecStream(CPacketStream *PacketStream, uint16_t streamid, ECodecType type, std::shared_ptr reader)
+CCodecStream::CCodecStream(CPacketStream *PacketStream)
+{
+ m_PacketStream = PacketStream;
+}
+
+void CCodecStream::ResetStats(uint16_t streamid, ECodecType type)
{
keep_running = true;
m_uiStreamId = streamid;
@@ -36,9 +41,6 @@ CCodecStream::CCodecStream(CPacketStream *PacketStream, uint16_t streamid, ECode
m_RTSum = 0;
m_RTCount = 0;
m_uiTotalPackets = 0;
- m_PacketStream = PacketStream;
- m_TCReader = reader;
- InitCodecStream();
}
////////////////////////////////////////////////////////////////////////////////////////
@@ -52,7 +54,12 @@ CCodecStream::~CCodecStream()
{
m_Future.get();
}
+ // and close the socket
+ m_TCReader.Close();
+}
+void CCodecStream::ReportStats()
+{
// display stats
if (m_RTCount > 0)
{
@@ -69,11 +76,24 @@ CCodecStream::~CCodecStream()
////////////////////////////////////////////////////////////////////////////////////////
// initialization
-void CCodecStream::InitCodecStream(void)
+bool CCodecStream::InitCodecStream(char module)
{
m_TCWriter.SetUp(REF2TC);
+ std::string name(TC2REF);
+ name.append(1, module);
+ if (m_TCReader.Open(name.c_str()))
+ return true;
keep_running = true;
- m_Future = std::async(std::launch::async, &CCodecStream::Thread, this);
+ try
+ {
+ m_Future = std::async(std::launch::async, &CCodecStream::Thread, this);
+ }
+ catch(const std::exception& e)
+ {
+ std::cerr << "Could not start Codec processing on module '" << module << "': " << e.what() << std::endl;
+ return true;
+ }
+ return false;
}
////////////////////////////////////////////////////////////////////////////////////////
@@ -92,21 +112,21 @@ void CCodecStream::Task(void)
STCPacket pack;
// any packet from transcoder
- if (m_TCReader->Receive(&pack, 5))
+ if (m_TCReader.Receive(&pack, 5))
{
// update statistics
double rt = pack.rt_timer.time(); // the round-trip time
- if ( m_RTMin == -1 )
+ if (0 == m_RTCount)
{
m_RTMin = rt;
m_RTMax = rt;
-
}
else
{
- m_RTMin = MIN(m_RTMin, rt);
- m_RTMax = MAX(m_RTMax, rt);
-
+ if (rt < m_RTMin)
+ m_RTMin = rt;
+ else if (rt > m_RTMax)
+ m_RTMax = rt;
}
m_RTSum += rt;
m_RTCount++;
diff --git a/reflector/CodecStream.h b/reflector/CodecStream.h
index 04e706f..e4652c4 100644
--- a/reflector/CodecStream.h
+++ b/reflector/CodecStream.h
@@ -18,6 +18,9 @@
#pragma once
+#include
+#include
+
#include "UnixDgramSocket.h"
#include "PacketQueue.h"
@@ -30,7 +33,11 @@ class CCodecStream : public CPacketQueue
{
public:
// constructor
- CCodecStream(CPacketStream *packetstream, uint16_t streamid, ECodecType codectype, std::shared_ptr reader);
+ CCodecStream(CPacketStream *packetstream);
+ bool InitCodecStream(char module);
+
+ void ResetStats(uint16_t streamid, ECodecType codectype);
+ void ReportStats();
// destructor
virtual ~CCodecStream();
@@ -44,7 +51,6 @@ public:
protected:
// initialization
- void InitCodecStream(void);
// data
uint16_t m_uiStreamId;
uint16_t m_uiPort;
@@ -52,7 +58,7 @@ protected:
ECodecType m_eCodecIn;
// sockets
- std::shared_ptr m_TCReader;
+ CUnixDgramReader m_TCReader;
CUnixDgramWriter m_TCWriter;
// associated packet stream
diff --git a/reflector/Configure.cpp b/reflector/Configure.cpp
new file mode 100644
index 0000000..968c722
--- /dev/null
+++ b/reflector/Configure.cpp
@@ -0,0 +1,928 @@
+/*
+ * Copyright (c) 2023 by 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "Configure.h"
+
+// ini file keywords
+#define JAUTOLINKMODULE "AutoLinkModule"
+#define JBLACKLISTPATH "BlacklistPath"
+#define JBRANDMEISTER "Brandmeister"
+#define JCALLSIGN "Callsign"
+#define JCLIENTSPATH "ClientFilePath"
+#define JCOUNTRY "Country"
+#define JDCS "DCS"
+#define JDEFAULTCALLSIGN "DefaultCallsign"
+#define JDEFAULTID "DefaultId"
+#define JDEFAULTRXFREQ "DefaultRxFreq"
+#define JDEFAULTTXFREQ "DefaultTxFreq"
+#define JDESCRIPTION "Description"
+#define JDEXTRA "DExtra"
+#define JDMRIDDB "DMR ID DB"
+#define JDMRPLUS "DMRPlus"
+#define JDPLUS "DPlus"
+#define JFILES "Files"
+#define JFILEPATH "FilePath"
+#define JG3TERMINALPATH "G3TerminalPath"
+#define JHOSTNAME "Hostname"
+#define JINTERLINKPATH "InterlinkPath"
+#define JIPADDRESSES "IpAddresses"
+#define JIPV4BINDING "IPv4Binding"
+#define JIPV4EXTERNAL "IPv4External"
+#define JIPV6BINDING "IPv6Binding"
+#define JIPV6EXTERNAL "IPv6External"
+#define JJSONPATH "JsonPath"
+#define JM17 "M17"
+#define JMMDVM "MMDVM"
+#define JMODE "Mode"
+#define JMODULES "Modules"
+#define JNAMES "Names"
+#define JNXDNIDDB "NXDN ID DB"
+#define JNXDN "NXDN"
+#define JP25 "P25"
+#define JPIDPATH "PidPath"
+#define JPORT "Port"
+#define JREFLECTORID "ReflectorID"
+#define JREFRESHMIN "RefreshMin"
+#define JREGISTRATIONDESCRIPTION "RegistrationDescription"
+#define JREGISTRATIONID "RegistrationID"
+#define JREGISTRATIONNAME "RegistrationName"
+#define JSPONSOR "Sponsor"
+#define JSUFFIX "Suffix"
+#define JSYSOPEMAIL "SysopEmail"
+#define JTRANSCODED "Transcoded"
+#define JTRANSCODER "Transcoder"
+#define JURF "URF"
+#define JUSRP "USRP"
+#define JWHITELISTPATH "WhitelistPath"
+#define JYSF "YSF"
+#define JYSFTXRXDB "YSF TX/RX DB"
+
+static inline void split(const std::string &s, char delim, std::vector &v)
+{
+ std::istringstream iss(s);
+ std::string item;
+ while (std::getline(iss, item, delim))
+ v.push_back(item);
+}
+
+// trim from start (in place)
+static inline void ltrim(std::string &s) {
+ s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch) {
+ return !std::isspace(ch);
+ }));
+}
+
+// trim from end (in place)
+static inline void rtrim(std::string &s) {
+ s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) {
+ return !std::isspace(ch);
+ }).base(), s.end());
+}
+
+// trim from both ends (in place)
+static inline void trim(std::string &s) {
+ ltrim(s);
+ rtrim(s);
+}
+
+// callback function writes data to a std::ostream
+static size_t data_write(void* buf, size_t size, size_t nmemb, void* userp)
+{
+ if(userp)
+ {
+ std::ostream& os = *static_cast(userp);
+ std::streamsize len = size * nmemb;
+ if(os.write(static_cast(buf), len))
+ return len;
+ }
+
+ return 0;
+}
+
+static CURLcode curl_read(const std::string& url, std::ostream& os, long timeout = 30)
+{
+ CURLcode code(CURLE_FAILED_INIT);
+ CURL* curl = curl_easy_init();
+
+ if(curl)
+ {
+ if(CURLE_OK == (code = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &data_write))
+ && CURLE_OK == (code = curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L))
+ && CURLE_OK == (code = curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L))
+ && CURLE_OK == (code = curl_easy_setopt(curl, CURLOPT_FILE, &os))
+ && CURLE_OK == (code = curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout))
+ && CURLE_OK == (code = curl_easy_setopt(curl, CURLOPT_URL, url.c_str())))
+ {
+ code = curl_easy_perform(curl);
+ }
+ curl_easy_cleanup(curl);
+ }
+ return code;
+}
+
+void CConfigure::CurlAddresses(std::string &ipv4, std::string &ipv6) const
+{
+ std::ostringstream oss;
+
+ curl_global_init(CURL_GLOBAL_ALL);
+
+ if(CURLE_OK == curl_read("https://ipv4.icanhazip.com", oss))
+ {
+ // Web page successfully written to string
+ ipv4.assign(oss.str());
+ trim(ipv4);
+ oss.str(std::string());
+ }
+
+ if(CURLE_OK == curl_read("https://ipv6.icanhazip.com", oss))
+ {
+ ipv6.assign(oss.str());
+ trim(ipv6);
+ }
+
+ curl_global_cleanup();
+
+// std::cout << "IPv4=" << ipv4 << " IPv6=" << ipv6 << std::endl;
+}
+
+CConfigure::CConfigure()
+{
+ IPv4RegEx = std::regex("^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3,3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9]){1,1}$", std::regex::extended);
+ IPv6RegEx = std::regex("^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}(:[0-9a-fA-F]{1,4}){1,1}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|([0-9a-fA-F]{1,4}:){1,1}(:[0-9a-fA-F]{1,4}){1,6}|:((:[0-9a-fA-F]{1,4}){1,7}|:))$", std::regex::extended);
+}
+
+bool CConfigure::ReadData(const std::string &path)
+// returns true on failure
+{
+ bool rval = false;
+ ESection section = ESection::none;
+ counter = 0;
+ REFLECTOR::DB *pdb;
+
+ //data.ysfalmodule = 0;
+ //data.DPlusPort = data.DCSPort = data.DExtraPort = data.BMPort = data.DMRPlusPort = 0;
+ std::ifstream cfgfile(path.c_str(), std::ifstream::in);
+ if (! cfgfile.is_open()) {
+ std::cerr << "ERROR: '" << path << "' was not found!" << std::endl;
+ return true;
+ }
+
+ std::string ipv4, ipv6;
+ CurlAddresses(ipv4, ipv6);
+
+ std::string line;
+ while (std::getline(cfgfile, line))
+ {
+ counter++;
+ trim(line);
+ if (3 > line.size())
+ continue; // can't be anything
+ if ('#' == line.at(0))
+ continue; // skip comments
+
+ // check for next section
+ if ('[' == line.at(0))
+ {
+ std::string hname(line.substr(1));
+ auto pos = hname.find(']');
+ if (std::string::npos != pos)
+ hname.resize(pos);
+ section = ESection::none;
+ if (0 == hname.compare(JNAMES))
+ section = ESection::names;
+ else if (0 == hname.compare(JIPADDRESSES))
+ section = ESection::ip;
+ else if (0 == hname.compare(JMODULES))
+ section = ESection::modules;
+ else if (0 == hname.compare(JDPLUS))
+ section = ESection::dplus;
+ else if (0 == hname.compare(JDEXTRA))
+ section = ESection::dextra;
+ else if (0 == hname.compare(JDMRPLUS))
+ section = ESection::dmrplus;
+ else if (0 == hname.compare(JMMDVM))
+ section = ESection::mmdvm;
+ else if (0 == hname.compare(JNXDN))
+ section = ESection::nxdn;
+ else if (0 == hname.compare(JBRANDMEISTER))
+ section = ESection::bm;
+ else if (0 == hname.compare(JYSF))
+ section = ESection::ysf;
+ else if (0 == hname.compare(JDCS))
+ section = ESection::dcs;
+ else if (0 == hname.compare(JP25))
+ section = ESection::p25;
+ else if (0 == hname.compare(JM17))
+ section = ESection::m17;
+ else if (0 == hname.compare(JUSRP))
+ section = ESection::usrp;
+ else if (0 == hname.compare(JURF))
+ section = ESection::urf;
+ else if (0 == hname.compare(JDMRIDDB))
+ section = ESection::dmrid;
+ else if (0 == hname.compare(JNXDNIDDB))
+ section = ESection::nxdnid;
+ else if (0 == hname.compare(JYSFTXRXDB))
+ section = ESection::ysffreq;
+ else if (0 == hname.compare(JFILES))
+ section = ESection::files;
+ else
+ {
+ std::cerr << "WARNING: unknown ini file section: " << line << std::endl;
+ }
+ continue;
+ }
+
+ std::vector tokens;
+ split(line, '=', tokens);
+ // check value for end-of-line comment
+ if (2 > tokens.size())
+ {
+ std::cout << "WARNING: line #" << counter << ": '" << line << "' does not contain an equal sign, skipping" << std::endl;
+ continue;
+ }
+ auto pos = tokens[1].find('#');
+ if (std::string::npos != pos)
+ {
+ tokens[1].assign(tokens[1].substr(0, pos));
+ rtrim(tokens[1]); // whitespace between the value and the end-of-line comment
+ }
+ // trim whitespace from around the '='
+ rtrim(tokens[0]);
+ ltrim(tokens[1]);
+ const std::string key(tokens[0]);
+ const std::string value(tokens[1]);
+ if (key.empty() || value.empty())
+ {
+ std::cout << "WARNING: line #" << counter << ": missing key or value: '" << line << "'" << std::endl;
+ continue;
+ }
+ switch (section)
+ {
+ case ESection::names:
+ if (0 == key.compare(JCALLSIGN))
+ data[j.names.cs] = value;
+ else if (0 == key.compare(JSYSOPEMAIL))
+ data[j.names.email] = value;
+ else if (0 == key.compare(JCOUNTRY))
+ data[j.names.country] = value.substr(0,2);
+ else if (0 == key.compare(JSPONSOR))
+ data[j.names.sponsor] = value;
+ else
+ badParam(key);
+ break;
+ case ESection::ip:
+ if (0 == key.compare(JIPV4BINDING))
+ {
+ data[j.ip.ipv4bind] = value;
+ }
+ else if (0 == key.compare(JIPV6BINDING))
+ {
+ data[j.ip.ipv6bind] = value;
+ }
+ else if (0 == key.compare(JIPV4EXTERNAL))
+ {
+ data[j.ip.ipv4address] = value;
+ }
+ else if (0 == key.compare(JIPV6EXTERNAL))
+ {
+ data[j.ip.ipv6address] = value;
+ }
+ else if (0 == key.compare(JTRANSCODER))
+ {
+ if (value.compare("local"))
+ {
+ std::cout << "WARNING: Line #" << counter << ": malformed transcoder address, '" << value << "', resetting..." << std::endl;
+ }
+ data[j.ip.transcoder] = "local";
+ }
+ else
+ badParam(key);
+ break;
+ case ESection::modules:
+ if (0 == key.compare(JMODULES))
+ {
+ std::string m(value);
+ if (checkModules(m))
+ {
+ std::cerr << "ERROR: line #" << counter << ": no letters found in Modules: '" << m << "'" << std::endl;
+ rval = true;
+ } else
+ data[j.modules.modules] = m;
+ }
+ else if (0 == key.compare(JTRANSCODED))
+ {
+ std::string m(value);
+ if (checkModules(m))
+ {
+ std::cerr << "ERROR: line #" << counter << ": no letters found in Transcoded: '" << m << "'" << std::endl;
+ rval = true;
+ } else
+ data[j.modules.tcmodules] = m;
+ }
+ else if (0 == key.compare(0, 11, "Description"))
+ {
+ if (12 == key.size() && isupper(key[11]))
+ data[key] = value;
+ else
+ badParam(key);
+ }
+ else
+ badParam(key);
+ break;
+ case ESection::bm:
+ if (0 == key.compare(JPORT))
+ data[j.bm.port] = getUnsigned(value, "Brandmeister Port", 1024, 65535, 10002);
+ else
+ badParam(key);
+ break;
+ case ESection::dcs:
+ if (0 == key.compare(JPORT))
+ data[j.dcs.port] = getUnsigned(value, "DCS Port", 1024, 65535, 30051);
+ else
+ badParam(key);
+ break;
+ case ESection::dextra:
+ if (0 == key.compare(JPORT))
+ data[j.dextra.port] = getUnsigned(value, "DExtra Port", 1024, 65535, 30001);
+ else
+ badParam(key);
+ break;
+ case ESection::dmrplus:
+ if (0 == key.compare(JPORT))
+ data[j.dmrplus.port] = getUnsigned(value, "DMRPlus Port", 1024, 65535, 8880);
+ else
+ badParam(key);
+ break;
+ case ESection::dplus:
+ if (0 == key.compare(JPORT))
+ data[j.dplus.port] = getUnsigned(value, "DPlus Port", 1024, 65535, 20001);
+ else
+ badParam(key);
+ break;
+ case ESection::m17:
+ if (0 == key.compare(JPORT))
+ data[j.m17.port] = getUnsigned(value, "M17 Port", 1024, 65535, 17000);
+ else
+ badParam(key);
+ break;
+ case ESection::mmdvm:
+ if (0 == key.compare(JPORT))
+ data[j.mmdvm.port] = getUnsigned(value, "MMDVM Port", 1024, 65535, 62030);
+ else if (0 == key.compare(JDEFAULTID))
+ data[j.mmdvm.defaultid] = getUnsigned(value, "MMDVM DefaultID", 0, 9999999, 0);
+ else
+ badParam(key);
+ break;
+ case ESection::nxdn:
+ if (0 == key.compare(JPORT))
+ data[j.nxdn.port] = getUnsigned(value, "NDXN Port", 1024, 65535, 41400);
+ else if (0 == key.compare(JAUTOLINKMODULE))
+ setAutolink(JNXDN, j.nxdn.autolinkmod, value);
+ else if (0 == key.compare(JREFLECTORID))
+ data[j.nxdn.reflectorid] = getUnsigned(value, "NXDN ReflectorID", 0, 65535, 0);
+ else
+ badParam(key);
+ break;
+ case ESection::p25:
+ if (0 == key.compare(JPORT))
+ data[j.p25.port] = getUnsigned(value, "P25 Port", 1024, 65535, 41000);
+ else if (0 == key.compare(JAUTOLINKMODULE))
+ setAutolink(JP25, j.p25.autolinkmod, value);
+ else if (0 == key.compare(JREFLECTORID))
+ data[j.p25.reflectorid] = getUnsigned(value, "P25 ReflectorID", 0, 16777215, 0);
+ else
+ badParam(key);
+ break;
+ case ESection::urf:
+ if (0 == key.compare(JPORT))
+ data[j.urf.port] = getUnsigned(value, "URF Port", 1024, 65535, 10017);
+ else
+ badParam(key);
+ break;
+ case ESection::usrp:
+ if (0 == key.compare(JPORT))
+ data[j.usrp.port] = getUnsigned(value, "USRP Port", 1024, 65535, 34001);
+ else if (0 == key.compare(JAUTOLINKMODULE))
+ setAutolink(JUSRP, j.usrp.autolinkmod, value);
+ else if (0 == key.compare(JDEFAULTCALLSIGN))
+ {
+ std::string cs;
+ for (auto &c : value)
+ if (isalnum(c))
+ cs.append(1, toupper(c));
+ if (cs.size() > 7) cs.resize(7);
+ data[j.usrp.defaultcallsign] = cs;
+ }
+ else if (0 == key.compare(JCLIENTSPATH))
+ data[j.usrp.clientfilepath] == value;
+ else
+ badParam(key);
+ break;
+ case ESection::ysf:
+ if (0 == key.compare(JPORT))
+ data[j.ysf.port] = getUnsigned(value, "YSF Port", 1024, 65535, 42000);
+ else if (0 == key.compare(JAUTOLINKMODULE))
+ setAutolink(JYSF, j.ysf.autolinkmod, value);
+ else if (0 == key.compare(JDEFAULTTXFREQ))
+ data[j.ysf.defaulttxfreq] = getUnsigned(value, "YSF DefaultTxFreq", 40000000, 2600000000, 439000000);
+ else if (0 == key.compare(JDEFAULTRXFREQ))
+ data[j.ysf.defaultrxfreq] = getUnsigned(value, "YSF DefaultRxFreq", 40000000, 2600000000, 439000000);
+ else if (0 == key.compare(JREGISTRATIONID))
+ data[j.ysf.ysfreflectordb.id] = getUnsigned(value, "YSF RegistrationID", 0, 9999999, 0);
+ else if (0 == key.compare(JREGISTRATIONNAME))
+ {
+ std::string name(value);
+ if (name.size() > 13) name.resize(13);
+ data[j.ysf.ysfreflectordb.name] = name;
+ }
+ else if (0 == key.compare(JREGISTRATIONDESCRIPTION))
+ {
+ std::string desc(value);
+ if (desc.size() > 16) desc.resize(16);
+ data[j.ysf.ysfreflectordb.description] = desc;
+ }
+ else
+ badParam(key);
+ break;
+ case ESection::dmrid:
+ case ESection::nxdnid:
+ case ESection::ysffreq:
+ switch (section)
+ {
+ case ESection::dmrid: pdb = &j.dmriddb; break;
+ case ESection::nxdnid: pdb = &j.nxdniddb; break;
+ case ESection::ysffreq: pdb = &j.ysftxrxdb; break;
+ }
+ if (0 == key.compare(JHOSTNAME))
+ data[pdb->hostname] = value;
+ else if (0 == key.compare(JSUFFIX))
+ data[pdb->suffix] = value;
+ else if (0 == key.compare(JMODE))
+ {
+ if ((0==value.compare("file")) || (0==value.compare("http")) || (0==value.compare("both")))
+ data[pdb->mode] = value;
+ else
+ {
+ std::cout << "WARNING: line #" << counter << ": Mode, '" << value << "' not recognized. Setting to 'http'" << std::endl;
+ data[pdb->mode] = "http";
+ }
+ }
+ else if (0 == key.compare(JREFRESHMIN))
+ data[pdb->refreshmin] = getUnsigned(value, JREFRESHMIN, 15, 14400, 180);
+ else if (0 == key.compare(JFILEPATH))
+ data[pdb->filepath] = value;
+ else
+ badParam(key);
+ break;
+ case ESection::files:
+ if (0 == key.compare(JPIDPATH))
+ data[j.files.pid] = value;
+ else if (0 == key.compare(JJSONPATH))
+ data[j.files.json] = value;
+ else if (0 == key.compare(JWHITELISTPATH))
+ data[j.files.white] = value;
+ else if (0 == key.compare(JBLACKLISTPATH))
+ data[j.files.black] = value;
+ else if (0 == key.compare(JINTERLINKPATH))
+ data[j.files.interlink] = value;
+ else if (0 == key.compare(JG3TERMINALPATH))
+ data[j.files.terminal] = value;
+ else
+ badParam(key);
+ break;
+ default:
+ std::cout << "WARNING: parameter '" << line << "' defined befor any [section]" << std::endl;
+ }
+
+ }
+ cfgfile.close();
+
+ ////////////////////////////// check the input
+ // Names section
+ if (isDefined(ErrorLevel::fatal, JNAMES, JCALLSIGN, j.names.cs, rval))
+ {
+ const auto cs = data[j.names.cs].get();
+ auto RefRegEx = std::regex("^URF([A-Z0-9]){3,3}$", std::regex::extended);
+ if (! std::regex_match(cs, RefRegEx))
+ {
+ std::cerr << "ERROR: [" << JNAMES << "] " << JCALLSIGN << " '" << cs << "' is malformed" << std::endl;
+ rval = true;
+ }
+ }
+
+ isDefined(ErrorLevel::mild, JNAMES, JSYSOPEMAIL, j.names.email, rval);
+ isDefined(ErrorLevel::mild, JNAMES, JCOUNTRY, j.names.country, rval);
+ isDefined(ErrorLevel::mild, JNAMES, JSPONSOR, j.names.sponsor, rval);
+
+ // IP Address section
+ // ipv4 bind and external
+ if (isDefined(ErrorLevel::fatal, JIPADDRESSES, JIPV4BINDING, j.ip.ipv4bind, rval))
+ {
+ if (std::regex_match(data[j.ip.ipv4bind].get(), IPv4RegEx))
+ {
+ if (data.contains(j.ip.ipv4address))
+ {
+ auto v4 = data[j.ip.ipv4address].get();
+ if (std::regex_match(v4, IPv4RegEx))
+ {
+ if (ipv4.compare(v4))
+ std::cout << "WARNING: specified IPv4 external address, " << v4 << ", is different than detected address, " << ipv4 << std::endl;
+ }
+ else
+ {
+ std::cerr << "ERROR: specifed IPv4 external address, " << v4 << ", is malformed" << std::endl;
+ rval = true;
+ }
+ }
+ else
+ {
+ // make sure curl worked!
+ if (std::regex_match(ipv4, IPv4RegEx))
+ data[j.ip.ipv4address] = ipv4;
+ else
+ {
+ std::cerr << "ERROR: could not detect IPv4 address at this time" << std::endl;
+ rval = true;
+ }
+ }
+ }
+ else
+ {
+ std::cerr << "ERROR: IPv4 binding address, " << data[j.ip.ipv4address].get() << ", is malformed" << std::endl;
+ rval = true;
+ }
+ }
+
+ // ipv6 bind and external
+ if (data.contains(j.ip.ipv6bind))
+ {
+ if (std::regex_match(data[j.ip.ipv6bind].get(), IPv6RegEx))
+ {
+ if (data.contains(j.ip.ipv6address))
+ {
+ auto v6 = data[j.ip.ipv6address].get();
+ if (std::regex_match(v6, IPv6RegEx))
+ {
+ if (ipv6.compare(v6))
+ std::cout << "WARNING: specified IPv6 external address [" << v6 << "], is different than detected address [" << ipv6 << ']' << std::endl;
+ }
+ else
+ {
+ std::cerr << "ERROR: the specifed IPv6 address [" << v6 << "] is malformed" << std::endl;
+ rval = true;
+ }
+ }
+ else
+ {
+ // make sure curl worked!
+ if (std::regex_match(ipv6, IPv6RegEx))
+ data[j.ip.ipv6address] = ipv6;
+ else
+ {
+ std::cerr << "ERROR: could not detect IPv6 address at this time" << std::endl;
+ rval = true;
+ }
+ }
+ }
+ else
+ {
+ std::cerr << "ERROR: IPv6 binding address, " << data[j.ip.ipv6address].get() << ", is malformed" << std::endl;
+ rval = true;
+ }
+ }
+ else
+ {
+ data[j.ip.ipv4bind] = nullptr;
+ data[j.ip.ipv6address] = nullptr;
+ }
+
+ // Modules section
+ if (isDefined(ErrorLevel::fatal, JMODULES, JMODULES, j.modules.modules, rval))
+ {
+ const auto mods(data[j.modules.modules].get());
+ if (data.contains(j.modules.tcmodules))
+ {
+ const auto tcmods(data[j.modules.tcmodules].get());
+
+ // how many transcoded modules
+ auto size = tcmods.size();
+ if (3 != size && 1 != size)
+ std::cout << "WARNING: [" << JMODULES << "] " << JTRANSCODED << " doesn't define three (or one) modules" << std::endl;
+
+ // make sure each transcoded module is configured
+ for (auto c : data[j.modules.tcmodules])
+ {
+ if (std::string::npos == mods.find(c))
+ {
+ std::cerr << "ERROR: transcoded module '" << c << "' not found in defined modules" << std::endl;
+ rval = true;
+ }
+ }
+ }
+ else
+ data[j.modules.tcmodules] = nullptr;
+
+ // finally, check the module descriptions
+ for (unsigned i=0; i<26; i++)
+ {
+ if (std::string::npos == mods.find('A'+i))
+ {
+ if (data.contains(j.modules.descriptor[i]))
+ {
+ std::cout << "WARNING: " << j.modules.descriptor[i] << " defined for an unconfigured module. Deleting..." << std::endl;
+ data.erase(j.modules.descriptor[i]);
+ }
+ }
+ else
+ {
+ if (! data.contains(j.modules.descriptor[i]))
+ {
+ std::string value("Module ");
+ value.append(1, 'A'+i);
+ std::cout << "WARNING: " << j.modules.descriptor[i] << " not found. Setting to " << value << std::endl;
+ data[j.modules.descriptor[i]] = value;
+ }
+ }
+ }
+ }
+
+ // "simple" protocols with only a Port
+ isDefined(ErrorLevel::fatal, JBRANDMEISTER, JPORT, j.bm.port, rval);
+ isDefined(ErrorLevel::fatal, JDCS, JPORT, j.dcs.port, rval);
+ isDefined(ErrorLevel::fatal, JDEXTRA, JPORT, j.dextra.port, rval);
+ isDefined(ErrorLevel::fatal, JDMRPLUS, JPORT, j.dmrplus.port, rval);
+ isDefined(ErrorLevel::fatal, JDPLUS, JPORT, j.dplus.port, rval);
+ isDefined(ErrorLevel::fatal, JM17, JPORT, j.m17.port, rval);
+ isDefined(ErrorLevel::fatal, JURF, JPORT, j.urf.port, rval);
+ // MMDVM
+ isDefined(ErrorLevel::fatal, JMMDVM, JPORT, j.mmdvm.port, rval);
+ isDefined(ErrorLevel::fatal, JMMDVM, JDEFAULTID, j.mmdvm.defaultid, rval);
+ // NXDN
+ isDefined(ErrorLevel::fatal, JNXDN, JPORT, j.nxdn.port, rval);
+ checkAutoLink(JNXDN, JAUTOLINKMODULE, j.nxdn.autolinkmod, rval);
+ isDefined(ErrorLevel::fatal, JNXDN, JREFLECTORID, j.nxdn.reflectorid, rval);
+ // P25
+ isDefined(ErrorLevel::fatal, JP25, JPORT, j.p25.port, rval);
+ checkAutoLink(JP25, JAUTOLINKMODULE, j.p25.autolinkmod, rval);
+ isDefined(ErrorLevel::fatal, JP25, JREFLECTORID, j.p25.reflectorid, rval);
+ // USRP
+ isDefined(ErrorLevel::fatal, JUSRP, JPORT, j.usrp.port, rval);
+ checkAutoLink(JUSRP, JAUTOLINKMODULE, j.usrp.autolinkmod, rval);
+ isDefined(ErrorLevel::fatal, JUSRP, JDEFAULTCALLSIGN, j.usrp.defaultcallsign, rval);
+ isDefined(ErrorLevel::fatal, JUSRP, JCLIENTSPATH, j.usrp.clientfilepath, rval);
+ // YSF
+ isDefined(ErrorLevel::fatal, JYSF, JPORT, j.ysf.port, rval);
+ checkAutoLink(JYSF, JAUTOLINKMODULE, j.ysf.autolinkmod, rval);
+ isDefined(ErrorLevel::fatal, JYSF, JDEFAULTRXFREQ, j.ysf.defaultrxfreq, rval);
+ isDefined(ErrorLevel::fatal, JYSF, JDEFAULTTXFREQ, j.ysf.defaulttxfreq, rval);
+ isDefined(ErrorLevel::mild, JYSF, JREGISTRATIONID, j.ysf.ysfreflectordb.id, rval);
+ isDefined(ErrorLevel::mild, JYSF, JREGISTRATIONNAME, j.ysf.ysfreflectordb.name, rval);
+ isDefined(ErrorLevel::mild, JYSF, JREGISTRATIONDESCRIPTION, j.ysf.ysfreflectordb.description, rval);
+ // Databases
+ std::list> dbs = {
+ { JDMRIDDB, &j.dmriddb },
+ { JNXDNIDDB, &j.nxdniddb },
+ { JYSFTXRXDB, &j.ysftxrxdb }
+ };
+ for ( auto &item : dbs )
+ {
+ isDefined(ErrorLevel::fatal, item.first, JHOSTNAME, item.second->hostname, rval);
+ isDefined(ErrorLevel::fatal, item.first, JSUFFIX, item.second->suffix, rval);
+ isDefined(ErrorLevel::fatal, item.first, JMODE, item.second->mode, rval);
+ isDefined(ErrorLevel::fatal, item.first, JREFRESHMIN, item.second->refreshmin, rval);
+ isDefined(ErrorLevel::fatal, item.first, JFILEPATH, item.second->filepath, rval);
+ }
+ // Other files
+ isDefined(ErrorLevel::fatal, JFILES, JPIDPATH, j.files.pid, rval);
+ isDefined(ErrorLevel::fatal, JFILES, JJSONPATH, j.files.json, rval);
+ isDefined(ErrorLevel::fatal, JFILES, JWHITELISTPATH, j.files.white, rval);
+ isDefined(ErrorLevel::fatal, JFILES, JBLACKLISTPATH, j.files.black, rval);
+ isDefined(ErrorLevel::fatal, JFILES, JINTERLINKPATH, j.files.interlink, rval);
+ isDefined(ErrorLevel::fatal, JFILES, JG3TERMINALPATH, j.files.terminal, rval);
+
+ return rval;
+}
+
+bool CConfigure::isDefined(ErrorLevel level, const std::string §ion, const std::string &pname, const std::string &key, bool &rval)
+{
+ if (data.contains(key))
+ return true;
+
+ if (ErrorLevel::mild == level)
+ {
+ std::cout << "WARNING: [" << section << "] " << pname << " is not defined" << std::endl;
+ data[key] = nullptr;
+ }
+ else
+ {
+ std::cerr << "ERROR: [" << section << "] " << pname << " is not defined" << std::endl;
+ rval = true;
+ }
+ return false;
+}
+
+void CConfigure::checkAutoLink(const std::string §ion, const std::string &pname, const std::string &key, bool &rval)
+{
+ if (data.contains(key))
+ {
+ auto ismods = data.contains(j.modules.modules);
+ const auto mods(ismods ? data[j.modules.modules].get() : "");
+ const auto c = data[key].get().at(0);
+ if (std::string::npos == mods.find(c))
+ {
+ std::cerr << "ERROR: [" << section << "] " << pname << " module '" << c << "' not a configured module" << std::endl;
+ rval = true;
+ }
+ }
+ else
+ data[key] = nullptr;
+}
+
+std::string CConfigure::getDataRefreshType(ERefreshType type) const
+{
+ if (ERefreshType::both == type)
+ return std::string("both");
+ else if (ERefreshType::file == type)
+ return std::string("file");
+ else
+ return std::string("http");
+}
+
+unsigned CConfigure::getUnsigned(const std::string &valuestr, const std::string &label, unsigned min, unsigned max, unsigned def) const
+{
+ auto i = unsigned(std::stoul(valuestr.c_str()));
+ if ( i < min || i > max )
+ {
+ std::cout << "WARNING: line #" << counter << ": " << label << " is out of range. Reset to " << def << std::endl;
+ i = def;
+ }
+ return (unsigned)i;
+}
+
+void CConfigure::badParam(const std::string &key) const
+{
+ std::cout << "WARNING: line #" << counter << ": Unexpected parameter: '" << key << "'" << std::endl;
+}
+
+bool CConfigure::checkModules(std::string &m) const
+{
+ bool rval = false; // return true on error
+ for(unsigned i=0; i();
+ if (0 == s.compare("both"))
+ type = ERefreshType::both;
+ else if (0 == s.compare("file"))
+ type = ERefreshType::file;
+ else
+ type = ERefreshType::http;
+ }
+ }
+ return type;
+}
+
+std::string CConfigure::GetString(const std::string &key) const
+{
+ std::string str;
+ if (data.contains(key))
+ {
+ if (data[key].is_null())
+ {
+ // null is the same thing as an empty string
+ return str;
+ }
+ else if (data[key].is_string())
+ {
+ str.assign(data[key].get());
+ }
+ else
+ std::cerr << "ERROR: GetString(): '" << key << "' is not a string" << std::endl;
+ }
+ else
+ {
+ std::cerr << "ERROR: GetString(): item at '" << key << "' is not defined" << std::endl;
+ }
+ return str;
+}
+
+unsigned CConfigure::GetUnsigned(const std::string &key) const
+{
+ unsigned u = 0;
+ if (data.contains(key))
+ {
+ if (data[key].is_number_unsigned())
+ {
+ u = data[key].get();
+ }
+ else
+ std::cerr << "ERROR: GetString(): '" << key << "' is not an unsigned value" << std::endl;
+ }
+ else
+ {
+ std::cerr << "ERROR: GetString(): item at '" << key << "' is not defined" << std::endl;
+ }
+ return u;
+}
+
+char CConfigure::GetAutolinkModule(const std::string &key) const
+{
+ char c = 0;
+ if (data.contains(key))
+ {
+ if (data[key].is_string())
+ {
+ c = data[key].get().at(0);
+ }
+ }
+ return c;
+}
+
+bool CConfigure::IsString(const std::string &key) const
+{
+ if (data.contains(key))
+ return data[key].is_string();
+ return false;
+}
+
+#ifdef INICHECK
+int main(int argc, char *argv[])
+{
+ if (argc == 2)
+ {
+ CConfigure d;
+ auto rval = d.ReadData(argv[1]);
+ d.Dump(true);
+ return rval ? EXIT_FAILURE : EXIT_SUCCESS;
+ }
+ std::cerr << "Usage: " << argv[0] << " FILENAME" << std::endl;
+ return EXIT_SUCCESS;
+}
+#endif
diff --git a/reflector/Configure.h b/reflector/Configure.h
new file mode 100644
index 0000000..dee5086
--- /dev/null
+++ b/reflector/Configure.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2023 by 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#pragma once
+
+#include
+#include
+#include
+#include
+
+enum class ErrorLevel { fatal, mild };
+enum class ERefreshType { file, http, both };
+enum class ESection { none, names, ip, modules, urf, dplus, dextra, dcs, dmrplus, mmdvm, nxdn, bm, ysf, p25, m17, usrp, dmrid, nxdnid, ysffreq, files };
+
+#define IS_TRUE(a) ((a)=='t' || (a)=='T' || (a)=='1')
+
+class CConfigure
+{
+public:
+ // json names
+ struct REFLECTOR {
+ struct BM { const std::string port; } bm;
+ struct DCS { const std::string port; } dcs;
+ struct DEXTRA { const std::string port; } dextra;
+ struct DMRPLUS { const std::string port; } dmrplus;
+ struct DPLUS { const std::string port; } dplus;
+ struct M17 { const std::string port; } m17;
+ struct URF { const std::string port; } urf;
+ struct NAMES { const std::string cs, email, country, sponsor; } names;
+ struct IP { const std::string ipv4bind, ipv4address, ipv6bind, ipv6address, transcoder; } ip;
+ struct MODULES { const std::string modules, tcmodules, descriptor[26]; } modules;
+ struct USRP { const std::string port, autolinkmod, defaultcallsign, clientfilepath; } usrp;
+ struct P25NXDN { const std::string port, autolinkmod, reflectorid; } p25, nxdn;
+ struct YSF {
+ const std::string port, autolinkmod, defaulttxfreq, defaultrxfreq;
+ struct YSLREG { const std::string id, name, description; } ysfreflectordb;
+ } ysf;
+ struct MMDVM { const std::string port, defaultid; } mmdvm;
+ struct DB { const std::string hostname, suffix, mode, refreshmin, filepath; } dmriddb, nxdniddb, ysftxrxdb;
+ struct FILES { const std::string pid, json, white, black, interlink, terminal; } files;
+ } j = {
+ { "BrandMeisterPort" },
+ { "DCSPort" },
+ { "DExtraPort" },
+ { "DMRPlusPort" },
+ { "DPlusPort" },
+ { "M17Port" },
+ { "URFPort" },
+ { "Callsign", "SysopEmail", "Country", "Sponsor" },
+ { "ipv4bind", "IPv4Address", "ipv6bind", "IPv6Address", "tcaddress" },
+ { "Modules", "TranscodedModules", "DescriptionA", "DescriptionB", "DescriptionC",
+ "DescriptionD", "DescriptionE", "DescriptionF", "DescriptionG", "DescriptionH",
+ "DescriptionI", "DescriptionJ", "DescriptionK", "DescriptionL", "DescriptionM",
+ "DescriptionN", "DescriptionO", "DescriptionP", "DescriptionQ", "DescriptionR",
+ "DescriptionS", "DescriptionT", "DescriptionU", "DescriptionV", "DescriptionW",
+ "DescriptionX", "DescriptionY", "DescriptionZ" },
+ { "USRPPort", "USRPAutolinkMod", "usrpDefaultCallsign", "usrpClientfilePath" },
+ { "P25Port", "P25AutolinkMod", "P25ReflectorID" },
+ { "NXDNPort", "NXDNAutolinkMod", "NXDNReflectorID" },
+ { "YSFPort", "YSFAutoLinkMod", "YSFDefaultTxFreq", "YSFDefaultRxFreq", { "ysfrefdbid", "ysfrefdbname", "ysfrefdbdesc" } },
+ { "MMDVMPort", "mmdvmdefaultid" },
+ { "dmrIdDbHost", "dmrIdDbSuffix", "dmrIdDbMode", "dmrIdDbRefresh", "dmrIdDbFilePath" },
+ { "nxdnIdDbHost", "nxdnIdDbSuffix", "nxdnIdDbMode", "nxdnIdDbRefresh", "nxdnIdDbFilePath" },
+ { "ysfIdDbHost", "ysfIdDbSuffix", "ysfIdDbMode", "ysfIdDbRefresh", "ysfIdDbFilePath" },
+ { "pidFilePath", "jsonFilePath", "whitelistFilePath", "blacklistFilePath", "interlinkFilePath", "g3TerminalFilePath" }
+ };
+
+ CConfigure();
+ bool ReadData(const std::string &path);
+ void Dump(bool justpublic) const;
+ std::string GetString(const std::string &key) const;
+ unsigned GetUnsigned(const std::string &key) const;
+ ERefreshType GetRefreshType(const std::string &key) const;
+ bool IsString(const std::string &key) const;
+ char GetAutolinkModule(const std::string &key) const;
+
+private:
+ // CFGDATA data;
+ unsigned counter;
+ nlohmann::json data;
+ std::regex IPv4RegEx, IPv6RegEx;
+
+ void CurlAddresses(std::string &v4, std::string &v6) const;
+ std::string getDataRefreshType(ERefreshType t) const;
+ unsigned getUnsigned(const std::string &value, const std::string &label, unsigned min, unsigned max, unsigned defaultvalue) const;
+ void badParam(const std::string ¶m) const;
+ bool checkModules(std::string &m) const;
+ void setAutolink(const std::string §ion, const std::string &key, const std::string &value);
+ bool isDefined(ErrorLevel level, const std::string §ion, const std::string &pname, const std::string &key, bool &rval);
+ void checkAutoLink(const std::string §ion, const std::string &pname, const std::string &key, bool &rval);
+};
diff --git a/reflector/DCSClient.cpp b/reflector/DCSClient.cpp
index a30f140..200c04e 100644
--- a/reflector/DCSClient.cpp
+++ b/reflector/DCSClient.cpp
@@ -16,7 +16,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-#include "Main.h"
+
#include "DCSClient.h"
diff --git a/reflector/DCSProtocol.cpp b/reflector/DCSProtocol.cpp
index 8bb54e0..0a3f5b6 100644
--- a/reflector/DCSProtocol.cpp
+++ b/reflector/DCSProtocol.cpp
@@ -16,7 +16,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-#include "Main.h"
+
#include
#include "DCSClient.h"
#include "DCSProtocol.h"
@@ -68,7 +68,7 @@ void CDcsProtocol::Task(void)
if ( IsValidDvPacket(Buffer, Header, Frame) )
{
// callsign muted?
- if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::dcs, Header->GetRpt2Module()) )
+ if ( g_Gate.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::dcs, Header->GetRpt2Module()) )
{
OnDvHeaderPacketIn(Header, Ip);
@@ -80,18 +80,18 @@ void CDcsProtocol::Task(void)
std::cout << "DCS connect packet for module " << ToLinkModule << " from " << Callsign << " at " << Ip << std::endl;
// callsign authorized?
- if ( g_GateKeeper.MayLink(Callsign, Ip, EProtocol::dcs) && g_Reflector.IsValidModule(ToLinkModule) )
+ if ( g_Gate.MayLink(Callsign, Ip, EProtocol::dcs) && g_Refl..IsValidModule(ToLinkModule) )
{
// valid module ?
- if ( g_Reflector.IsValidModule(ToLinkModule) )
+ if ( g_Refl..IsValidModule(ToLinkModule) )
{
// acknowledge the request
EncodeConnectAckPacket(Callsign, ToLinkModule, &Buffer);
Send(Buffer, Ip);
// create the client and append
- g_Reflector.GetClients()->AddClient(std::make_shared(Callsign, Ip, ToLinkModule));
- g_Reflector.ReleaseClients();
+ g_Refl..GetClients()->AddClient(std::make_shared(Callsign, Ip, ToLinkModule));
+ g_Refl..ReleaseClients();
}
else
{
@@ -115,7 +115,7 @@ void CDcsProtocol::Task(void)
std::cout << "DCS disconnect packet from " << Callsign << " at " << Ip << std::endl;
// find client
- CClients *clients = g_Reflector.GetClients();
+ CClients *clients = g_Refl..GetClients();
std::shared_ptrclient = clients->FindClient(Ip, EProtocol::dcs);
if ( client != nullptr )
{
@@ -125,21 +125,21 @@ void CDcsProtocol::Task(void)
EncodeConnectNackPacket(Callsign, ' ', &Buffer);
Send(Buffer, Ip);
}
- g_Reflector.ReleaseClients();
+ g_Refl..ReleaseClients();
}
else if ( IsValidKeepAlivePacket(Buffer, &Callsign) )
{
//std::cout << "DCS keepalive packet from " << Callsign << " at " << Ip << std::endl;
// find all clients with that callsign & ip and keep them alive
- CClients *clients = g_Reflector.GetClients();
+ CClients *clients = g_Refl..GetClients();
auto it = clients->begin();
std::shared_ptrclient = nullptr;
while ( (client = clients->FindNextClient(Callsign, Ip, EProtocol::dcs, it)) != nullptr )
{
client->Alive();
}
- g_Reflector.ReleaseClients();
+ g_Refl..ReleaseClients();
}
else if ( IsIgnorePacket(Buffer) )
{
@@ -193,24 +193,24 @@ void CDcsProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header,
CCallsign rpt2(Header->GetRpt2Callsign());
// find this client
- std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, EProtocol::dcs);
+ std::shared_ptrclient = g_Refl..GetClients()->FindClient(Ip, EProtocol::dcs);
if ( client )
{
// get client callsign
rpt1 = client->GetCallsign();
// and try to open the stream
- if ( (stream = g_Reflector.OpenStream(Header, client)) != nullptr )
+ if ( (stream = g_Refl..OpenStream(Header, client)) != nullptr )
{
// keep the handle
m_Streams[stream->GetStreamId()] = stream;
}
}
// release
- g_Reflector.ReleaseClients();
+ g_Refl..ReleaseClients();
// update last heard
- g_Reflector.GetUsers()->Hearing(my, rpt1, rpt2);
- g_Reflector.ReleaseUsers();
+ g_Refl..GetUsers()->Hearing(my, rpt1, rpt2);
+ g_Refl..ReleaseUsers();
}
}
@@ -253,7 +253,7 @@ void CDcsProtocol::HandleQueue(void)
if ( buffer.size() > 0 )
{
// and push it to all our clients linked to the module and who are not streaming in
- CClients *clients = g_Reflector.GetClients();
+ CClients *clients = g_Refl..GetClients();
auto it = clients->begin();
std::shared_ptrclient = nullptr;
while ( (client = clients->FindNextClient(EProtocol::dcs, it)) != nullptr )
@@ -266,7 +266,7 @@ void CDcsProtocol::HandleQueue(void)
}
}
- g_Reflector.ReleaseClients();
+ g_Refl..ReleaseClients();
}
}
}
@@ -285,7 +285,7 @@ void CDcsProtocol::HandleKeepalives(void)
EncodeKeepAlivePacket(&keepalive1);
// iterate on clients
- CClients *clients = g_Reflector.GetClients();
+ CClients *clients = g_Refl..GetClients();
auto it = clients->begin();
std::shared_ptrclient = nullptr;
while ( (client = clients->FindNextClient(EProtocol::dcs, it)) != nullptr )
@@ -318,7 +318,7 @@ void CDcsProtocol::HandleKeepalives(void)
}
}
- g_Reflector.ReleaseClients();
+ g_Refl..ReleaseClients();
}
////////////////////////////////////////////////////////////////////////////////////////
diff --git a/reflector/DExtraClient.cpp b/reflector/DExtraClient.cpp
index 579352b..fc6b008 100644
--- a/reflector/DExtraClient.cpp
+++ b/reflector/DExtraClient.cpp
@@ -16,7 +16,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-#include "Main.h"
+
#include "DExtraClient.h"
diff --git a/reflector/DExtraPeer.cpp b/reflector/DExtraPeer.cpp
index e8c04a5..1a72a60 100644
--- a/reflector/DExtraPeer.cpp
+++ b/reflector/DExtraPeer.cpp
@@ -17,7 +17,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-#include "Main.h"
+
#include
#include "Reflector.h"
#include "DExtraPeer.h"
diff --git a/reflector/DExtraProtocol.cpp b/reflector/DExtraProtocol.cpp
index 3b55594..9b47e2b 100644
--- a/reflector/DExtraProtocol.cpp
+++ b/reflector/DExtraProtocol.cpp
@@ -16,7 +16,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-#include "Main.h"
+
#include
#include "DExtraPeer.h"
#include "DExtraClient.h"
@@ -74,7 +74,7 @@ void CDextraProtocol::Task(void)
else if ( IsValidDvHeaderPacket(Buffer, Header) )
{
// callsign muted?
- if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::dextra, Header->GetRpt2Module()) )
+ if ( g_Gate.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::dextra, Header->GetRpt2Module()) )
{
OnDvHeaderPacketIn(Header, Ip);
}
@@ -98,20 +98,20 @@ void CDextraProtocol::Task(void)
}
// callsign authorized?
- if ( g_GateKeeper.MayLink(Callsign, Ip, EProtocol::dextra) )
+ if ( g_Gate.MayLink(Callsign, Ip, EProtocol::dextra) )
{
// valid module ?
- if ( g_Reflector.IsValidModule(ToLinkModule) )
+ if ( g_Refl..IsValidModule(ToLinkModule) )
{
// is this an ack for a link request?
- CPeerCallsignList *list = g_GateKeeper.GetPeerList();
+ CPeerCallsignList *list = g_Gate.GetPeerList();
CCallsignListItem *item = list->FindListItem(Callsign);
if ( item != nullptr && Callsign.GetCSModule() == item->GetModules()[1] && ToLinkModule == item->GetModules()[0] )
{
std::cout << "DExtra ack packet for module " << ToLinkModule << " from " << Callsign << " at " << Ip << std::endl;
// already connected ?
- CPeers *peers = g_Reflector.GetPeers();
+ CPeers *peers = g_Refl..GetPeers();
if ( peers->FindPeer(Callsign, Ip, EProtocol::dextra) == nullptr )
{
// create the new peer
@@ -120,7 +120,7 @@ void CDextraProtocol::Task(void)
// this also add all new clients to reflector client list
peers->AddPeer(std::make_shared(Callsign, Ip, std::string(1, ToLinkModule).c_str(), CVersion(2, 0, 0)));
}
- g_Reflector.ReleasePeers();
+ g_Refl..ReleasePeers();
}
else
{
@@ -129,10 +129,10 @@ void CDextraProtocol::Task(void)
Send(Buffer, Ip);
// create the client and append
- g_Reflector.GetClients()->AddClient(std::make_shared(Callsign, Ip, ToLinkModule, ProtRev));
- g_Reflector.ReleaseClients();
+ g_Refl..GetClients()->AddClient(std::make_shared(Callsign, Ip, ToLinkModule, ProtRev));
+ g_Refl..ReleaseClients();
}
- g_GateKeeper.ReleasePeerList();
+ g_Gate.ReleasePeerList();
}
else
{
@@ -155,7 +155,7 @@ void CDextraProtocol::Task(void)
std::cout << "DExtra disconnect packet from " << Callsign << " at " << Ip << std::endl;
// find client & remove it
- CClients *clients = g_Reflector.GetClients();
+ CClients *clients = g_Refl..GetClients();
std::shared_ptrclient = clients->FindClient(Ip, EProtocol::dextra);
if ( client != nullptr )
{
@@ -172,21 +172,21 @@ void CDextraProtocol::Task(void)
// and remove it
clients->RemoveClient(client);
}
- g_Reflector.ReleaseClients();
+ g_Refl..ReleaseClients();
}
else if ( IsValidKeepAlivePacket(Buffer, &Callsign) )
{
//std::cout << "DExtra keepalive packet from " << Callsign << " at " << Ip << std::endl;
// find all clients with that callsign & ip and keep them alive
- CClients *clients = g_Reflector.GetClients();
+ CClients *clients = g_Refl..GetClients();
auto it = clients->begin();
std::shared_ptrclient = nullptr;
while ( (client = clients->FindNextClient(Callsign, Ip, EProtocol::dextra, it)) != nullptr )
{
client->Alive();
}
- g_Reflector.ReleaseClients();
+ g_Refl..ReleaseClients();
}
else
{
@@ -239,7 +239,7 @@ void CDextraProtocol::HandleQueue(void)
if ( EncodeDvPacket(*packet, buffer) )
{
// and push it to all our clients linked to the module and who are not streaming in
- CClients *clients = g_Reflector.GetClients();
+ CClients *clients = g_Refl..GetClients();
auto it = clients->begin();
std::shared_ptrclient = nullptr;
while ( (client = clients->FindNextClient(EProtocol::dextra, it)) != nullptr )
@@ -255,7 +255,7 @@ void CDextraProtocol::HandleQueue(void)
}
}
}
- g_Reflector.ReleaseClients();
+ g_Refl..ReleaseClients();
}
}
m_Queue.Unlock();
@@ -273,7 +273,7 @@ void CDextraProtocol::HandleKeepalives(void)
EncodeKeepAlivePacket(&keepalive);
// iterate on clients
- CClients *clients = g_Reflector.GetClients();
+ CClients *clients = g_Refl..GetClients();
auto it = clients->begin();
std::shared_ptrclient = nullptr;
while ( (client = clients->FindNextClient(EProtocol::dextra, it)) != nullptr )
@@ -290,7 +290,7 @@ void CDextraProtocol::HandleKeepalives(void)
// otherwise check if still with us
else if ( !client->IsAlive() )
{
- CPeers *peers = g_Reflector.GetPeers();
+ CPeers *peers = g_Refl..GetPeers();
std::shared_ptrpeer = peers->FindPeer(client->GetCallsign(), client->GetIp(), EProtocol::dextra);
if ( peer != nullptr && peer->GetReflectorModules()[0] == client->GetReflectorModule() )
{
@@ -307,14 +307,14 @@ void CDextraProtocol::HandleKeepalives(void)
std::cout << "DExtra client " << client->GetCallsign() << " keepalive timeout" << std::endl;
clients->RemoveClient(client);
}
- g_Reflector.ReleasePeers();
+ g_Refl..ReleasePeers();
}
}
- g_Reflector.ReleaseClients();
+ g_Refl..ReleaseClients();
// iterate on peers
- CPeers *peers = g_Reflector.GetPeers();
+ CPeers *peers = g_Refl..GetPeers();
auto pit = peers->begin();
std::shared_ptrpeer = nullptr;
while ( (peer = peers->FindNextPeer(EProtocol::dextra, pit)) != nullptr )
@@ -327,19 +327,19 @@ void CDextraProtocol::HandleKeepalives(void)
// no, disconnect all clients
CBuffer disconnect;
EncodeDisconnectPacket(&disconnect, peer->GetReflectorModules()[0]);
- CClients *clients = g_Reflector.GetClients();
+ CClients *clients = g_Refl..GetClients();
for ( auto cit=peer->cbegin(); cit!=peer->cend(); cit++ )
{
Send(disconnect, (*cit)->GetIp());
}
- g_Reflector.ReleaseClients();
+ g_Refl..ReleaseClients();
// remove it
std::cout << "DExtra peer " << peer->GetCallsign() << " keepalive timeout" << std::endl;
peers->RemovePeer(peer);
}
}
- g_Reflector.ReleasePeers();
+ g_Refl..ReleasePeers();
}
////////////////////////////////////////////////////////////////////////////////////////
@@ -350,8 +350,8 @@ void CDextraProtocol::HandlePeerLinks(void)
CBuffer buffer;
// get the list of peers
- CPeerCallsignList *list = g_GateKeeper.GetPeerList();
- CPeers *peers = g_Reflector.GetPeers();
+ CPeerCallsignList *list = g_Gate.GetPeerList();
+ CPeers *peers = g_Refl..GetPeers();
// check if all our connected peers are still listed by gatekeeper
// if not, disconnect
@@ -390,8 +390,8 @@ void CDextraProtocol::HandlePeerLinks(void)
}
// done
- g_Reflector.ReleasePeers();
- g_GateKeeper.ReleasePeerList();
+ g_Refl..ReleasePeers();
+ g_Gate.ReleasePeerList();
}
////////////////////////////////////////////////////////////////////////////////////////
@@ -415,7 +415,7 @@ void CDextraProtocol::OnDvHeaderPacketIn(std::unique_ptr &Heade
CCallsign rpt2(Header->GetRpt2Callsign());
// find this client
- std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, EProtocol::dextra);
+ std::shared_ptrclient = g_Refl..GetClients()->FindClient(Ip, EProtocol::dextra);
if ( client )
{
// get client callsign
@@ -430,18 +430,18 @@ void CDextraProtocol::OnDvHeaderPacketIn(std::unique_ptr &Heade
rpt2.SetCSModule(m);
}
// and try to open the stream
- if ( (stream = g_Reflector.OpenStream(Header, client)) != nullptr )
+ if ( (stream = g_Refl..OpenStream(Header, client)) != nullptr )
{
// keep the handle
m_Streams[stream->GetStreamId()] = stream;
}
}
// release
- g_Reflector.ReleaseClients();
+ g_Refl..ReleaseClients();
// update last heard
- g_Reflector.GetUsers()->Hearing(my, rpt1, rpt2);
- g_Reflector.ReleaseUsers();
+ g_Refl..GetUsers()->Hearing(my, rpt1, rpt2);
+ g_Refl..ReleaseUsers();
}
}
diff --git a/reflector/DMRIdDir.cpp b/reflector/DMRIdDir.cpp
deleted file mode 100644
index 886a840..0000000
--- a/reflector/DMRIdDir.cpp
+++ /dev/null
@@ -1,145 +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 "Main.h"
-#include "Reflector.h"
-#include "DMRIdDir.h"
-#include "DMRIdDirFile.h"
-#include "DMRIdDirHttp.h"
-
-////////////////////////////////////////////////////////////////////////////////////////
-// constructor & destructor
-
-CDmridDir::CDmridDir()
-{
- keep_running = true;
-}
-
-CDmridDir::~CDmridDir()
-{
- Close();
-}
-
-
-////////////////////////////////////////////////////////////////////////////////////////
-// init & close
-
-bool CDmridDir::Init(void)
-{
- // load content
- Reload();
-
- // reset run flag
- keep_running = true;
-
- // start thread;
- m_Future = std::async(std::launch::async, &CDmridDir::Thread, this);
-
- return true;
-}
-
-void CDmridDir::Close(void)
-{
- keep_running = false;
- if ( m_Future.valid() )
- {
- m_Future.get();
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-// thread
-
-void CDmridDir::Thread()
-{
- while (keep_running)
- {
- // Wait DMRIDDB_REFRESH_RATE minutes
- for (int i=0; i<30*DMRIDDB_REFRESH_RATE && keep_running; i++)
- std::this_thread::sleep_for(std::chrono::milliseconds(2000));
-
- // have lists files changed ?
- if ( NeedReload() )
- {
- Reload();
- }
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-// Reload
-
-bool CDmridDir::Reload(void)
-{
- CBuffer buffer;
- bool ok = false;
-
- if ( LoadContent(&buffer) )
- {
- Lock();
- {
- ok = RefreshContent(buffer);
- }
- Unlock();
- }
- return ok;
-}
-
-
-////////////////////////////////////////////////////////////////////////////////////////
-// find
-
-const CCallsign *CDmridDir::FindCallsign(uint32_t dmrid)
-{
- auto found = m_CallsignMap.find(dmrid);
- if ( found != m_CallsignMap.end() )
- {
- return &(found->second);
- }
- return nullptr;
-}
-
-uint32_t CDmridDir::FindDmrid(const CCallsign &callsign)
-{
- auto found = m_DmridMap.find(callsign);
- if ( found != m_DmridMap.end() )
- {
- return (found->second);
- }
- return 0;
-}
-
-
-////////////////////////////////////////////////////////////////////////////////////////
-// syntax helpers
-
-bool CDmridDir::IsValidDmrid(const char *sz)
-{
- bool ok = false;
- size_t n = ::strlen(sz);
- if ( (n > 0) && (n <= 8) )
- {
- ok = true;
- for ( size_t i = 0; (i < n) && ok; i++ )
- {
- ok &= ::isdigit(sz[i]);
- }
- }
- return ok;
-}
diff --git a/reflector/DMRIdDirFile.cpp b/reflector/DMRIdDirFile.cpp
deleted file mode 100644
index d378ef5..0000000
--- a/reflector/DMRIdDirFile.cpp
+++ /dev/null
@@ -1,159 +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 "Main.h"
-#include "DMRIdDirFile.h"
-
-
-#if (DMRIDDB_USE_RLX_SERVER == 0)
-CDmridDirFile g_DmridDir;
-#endif
-
-////////////////////////////////////////////////////////////////////////////////////////
-// constructor & destructor
-
-CDmridDirFile::CDmridDirFile()
-{
- memset(&m_LastModTime, 0, sizeof(time_t));
-}
-
-
-////////////////////////////////////////////////////////////////////////////////////////
-// init & close
-
-bool CDmridDirFile::Init(void)
-{
- return CDmridDir::Init();
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-// refresh
-
-bool CDmridDirFile::NeedReload(void)
-{
- bool needReload = false;
-
- time_t time;
- if ( GetLastModTime(&time) )
- {
- needReload = time != m_LastModTime;
- }
- return needReload;
-}
-
-bool CDmridDirFile::LoadContent(CBuffer *buffer)
-{
- bool ok = false;
- std::ifstream file;
- std::streampos size;
-
- // open file
- file.open(DMRIDDB_PATH, std::ios::in | std::ios::binary | std::ios::ate);
- if ( file.is_open() )
- {
- // read file
- size = file.tellg();
- if ( size > 0 )
- {
- // read file into buffer
- buffer->resize((int)size+1);
- file.seekg (0, std::ios::beg);
- file.read((char *)buffer->data(), (int)size);
-
- // close file
- file.close();
-
- // update time
- GetLastModTime(&m_LastModTime);
-
- // done
- ok = true;
- }
- }
-
- // done
- return ok;
-}
-
-bool CDmridDirFile::RefreshContent(const CBuffer &buffer)
-{
- bool ok = false;
-
- // clear directory
- m_CallsignMap.clear();
- m_DmridMap.clear();
-
- // scan buffer
- if ( buffer.size() > 0 )
- {
- // crack it
- char *ptr1 = (char *)buffer.data();
- char *ptr2;
-
- // get next line
- while ( (ptr2 = ::strchr(ptr1, '\n')) != nullptr )
- {
- *ptr2 = 0;
- // get items
- char *dmrid;
- char *callsign;
- if ( ((dmrid = ::strtok(ptr1, ";")) != nullptr) && IsValidDmrid(dmrid) )
- {
- if ( ((callsign = ::strtok(nullptr, ";")) != nullptr) )
- {
- // new entry
- uint32_t ui = atoi(dmrid);
- CCallsign cs(callsign, ui);
- if ( cs.IsValid() )
- {
- m_CallsignMap.insert(std::pair(ui, cs));
- m_DmridMap.insert(std::pair(cs,ui));
- }
- }
- }
- // next line
- ptr1 = ptr2+1;
- }
-
- // done
- ok = true;
- }
-
- // report
- std::cout << "Read " << m_DmridMap.size() << " DMR ids from file " << DMRIDDB_PATH << std::endl;
-
- // done
- return ok;
-}
-
-
-bool CDmridDirFile::GetLastModTime(time_t *time)
-{
- bool ok = false;
-
- struct stat fileStat;
- if( ::stat(DMRIDDB_PATH, &fileStat) != -1 )
- {
- *time = fileStat.st_mtime;
- ok = true;
- }
- return ok;
-}
diff --git a/reflector/DMRIdDirHttp.cpp b/reflector/DMRIdDirHttp.cpp
deleted file mode 100644
index b0b4f36..0000000
--- a/reflector/DMRIdDirHttp.cpp
+++ /dev/null
@@ -1,177 +0,0 @@
-// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
-
-// urfd -- The universal reflector
-// Copyright © 2021 Thomas A. Early N7TAE
-// Copyright © 2021 Doug McLain AD8DP
-//
-// 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 "Main.h"
-#include "Reflector.h"
-#include "DMRIdDirHttp.h"
-
-#if (DMRIDDB_USE_RLX_SERVER == 1)
-CDmridDirHttp g_DmridDir;
-#endif
-
-
-
-
-////////////////////////////////////////////////////////////////////////////////////////
-// refresh
-
-bool CDmridDirHttp::LoadContent(CBuffer *buffer)
-{
- // get file from xlxapi server
- return HttpGet("xlxapi.rlx.lu", "api/exportdmr.php", 80, buffer);
-}
-
-bool CDmridDirHttp::RefreshContent(const CBuffer &buffer)
-{
- bool ok = false;
-
- // clear directory
- m_CallsignMap.clear();
- m_DmridMap.clear();
-
- // scan file
- if ( buffer.size() > 0 )
- {
- char *ptr1 = (char *)buffer.data();
- char *ptr2;
- // get next line
- while ( (ptr2 = ::strchr(ptr1, '\n')) != nullptr )
- {
- *ptr2 = 0;
- // get items
- char *dmrid;
- char *callsign;
- if ( ((dmrid = ::strtok(ptr1, ";")) != nullptr) && IsValidDmrid(dmrid) )
- {
- if ( ((callsign = ::strtok(nullptr, ";")) != nullptr) )
- {
- // new entry
- uint32_t ui = atoi(dmrid);
- CCallsign cs(callsign, ui);
- if ( cs.IsValid() )
- {
- m_CallsignMap.insert(std::pair(ui, cs));
- m_DmridMap.insert(std::pair(cs,ui));
- }
- }
- }
- // next line
- ptr1 = ptr2+1;
- }
- // done
- ok = true;
- }
-
- // report
- std::cout << "Read " << m_DmridMap.size() << " DMR ids from xlxapi.rlx.lu database " << std::endl;
-
- // done
- return ok;
-}
-
-
-////////////////////////////////////////////////////////////////////////////////////////
-// httpd helpers
-
-#define DMRID_HTTPGET_SIZEMAX (256)
-
-bool CDmridDirHttp::HttpGet(const char *hostname, const char *filename, int port, CBuffer *buffer)
-{
- bool ok = false;
- int sock_id;
-
- // open socket
- if ( (sock_id = ::socket(AF_INET, SOCK_STREAM, 0)) >= 0 )
- {
- // get hostname address
- struct sockaddr_in servaddr;
- struct hostent *hp;
- memset(&servaddr,0,sizeof(servaddr));
- if( (hp = gethostbyname(hostname)) != nullptr )
- {
- // dns resolved
- memcpy((char *)&servaddr.sin_addr.s_addr, (char *)hp->h_addr, hp->h_length);
- servaddr.sin_port = htons(port);
- servaddr.sin_family = AF_INET;
-
- // connect
- if ( ::connect(sock_id, (struct sockaddr *)&servaddr, sizeof(servaddr)) == 0)
- {
- // send the GET request
- char request[DMRID_HTTPGET_SIZEMAX];
- ::sprintf(request, "GET /%s HTTP/1.0\r\nFrom: %s\r\nUser-Agent: urfd\r\n\r\n",
- filename, (const char *)g_Reflector.GetCallsign());
- ::write(sock_id, request, strlen(request));
-
- // config receive timeouts
- fd_set read_set;
- struct timeval timeout;
- timeout.tv_sec = 5;
- timeout.tv_usec = 0;
- FD_ZERO(&read_set);
- FD_SET(sock_id, &read_set);
-
- // get the reply back
- buffer->clear();
- bool done = false;
- do
- {
- char buf[1440];
- ssize_t len = 0;
- select(sock_id+1, &read_set, nullptr, nullptr, &timeout);
- //if ( (ret > 0) || ((ret < 0) && (errno == EINPROGRESS)) )
- //if ( ret >= 0 )
- //{
- usleep(5000);
- len = read(sock_id, buf, 1440);
- if ( len > 0 )
- {
- buffer->Append((uint8_t *)buf, (int)len);
- ok = true;
- }
- //}
- done = (len <= 0);
-
- }
- while (!done);
- buffer->Append((uint8_t)0);
-
- // and disconnect
- close(sock_id);
- }
- else
- {
- std::cout << "Cannot establish connection with host " << hostname << std::endl;
- }
- }
- else
- {
- std::cout << "Host " << hostname << " not found" << std::endl;
- }
-
- }
- else
- {
- std::cout << "Failed to open wget socket" << std::endl;
- }
-
- // done
- return ok;
-}
diff --git a/reflector/DMRMMDVMClient.cpp b/reflector/DMRMMDVMClient.cpp
index 9f8b1f9..0c1cc1b 100644
--- a/reflector/DMRMMDVMClient.cpp
+++ b/reflector/DMRMMDVMClient.cpp
@@ -16,7 +16,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-#include "Main.h"
+
#include "DMRMMDVMClient.h"
diff --git a/reflector/DMRMMDVMProtocol.cpp b/reflector/DMRMMDVMProtocol.cpp
index a71d2b9..c3f8acd 100644
--- a/reflector/DMRMMDVMProtocol.cpp
+++ b/reflector/DMRMMDVMProtocol.cpp
@@ -16,7 +16,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-#include "Main.h"
+
#include
#include "DMRMMDVMClient.h"
#include "DMRMMDVMProtocol.h"
@@ -93,7 +93,7 @@ void CDmrmmdvmProtocol::Task(void)
if ( Receive4(Buffer, Ip, 20) )
#endif
{
- //Buffer.DebugDump(g_Reflector.m_DebugFile);
+ //Buffer.DebugDump(g_Refl..m_DebugFile);
// crack the packet
if ( IsValidDvFramePacket(Buffer, Frames) )
{
@@ -105,7 +105,7 @@ void CDmrmmdvmProtocol::Task(void)
else if ( IsValidDvHeaderPacket(Buffer, Header, &Cmd, &CallType) )
{
// callsign muted?
- if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::dmrmmdvm) )
+ if ( g_Gate.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::dmrmmdvm) )
{
// handle it
OnDvHeaderPacketIn(Header, Ip, Cmd, CallType);
@@ -120,7 +120,7 @@ void CDmrmmdvmProtocol::Task(void)
std::cout << "DMRmmdvm connect packet from " << Callsign << " at " << Ip << std::endl;
// callsign authorized?
- if ( g_GateKeeper.MayLink(Callsign, Ip, EProtocol::dmrmmdvm) )
+ if ( g_Gate.MayLink(Callsign, Ip, EProtocol::dmrmmdvm) )
{
// acknowledge the request
EncodeConnectAckPacket(&Buffer, Callsign, m_uiAuthSeed);
@@ -139,14 +139,14 @@ void CDmrmmdvmProtocol::Task(void)
std::cout << "DMRmmdvm authentication packet from " << Callsign << " at " << Ip << std::endl;
// callsign authorized?
- if ( g_GateKeeper.MayLink(Callsign, Ip, EProtocol::dmrmmdvm) )
+ if ( g_Gate.MayLink(Callsign, Ip, EProtocol::dmrmmdvm) )
{
// acknowledge the request
EncodeAckPacket(&Buffer, Callsign);
Send(Buffer, Ip);
// add client if needed
- CClients *clients = g_Reflector.GetClients();
+ CClients *clients = g_Refl..GetClients();
std::shared_ptrclient = clients->FindClient(Callsign, Ip, EProtocol::dmrmmdvm);
// client already connected ?
if ( client == nullptr )
@@ -161,7 +161,7 @@ void CDmrmmdvmProtocol::Task(void)
client->Alive();
}
// and done
- g_Reflector.ReleaseClients();
+ g_Refl..ReleaseClients();
}
else
{
@@ -176,13 +176,13 @@ void CDmrmmdvmProtocol::Task(void)
std::cout << "DMRmmdvm disconnect packet from " << Callsign << " at " << Ip << std::endl;
// find client & remove it
- CClients *clients = g_Reflector.GetClients();
+ CClients *clients = g_Refl..GetClients();
std::shared_ptrclient = clients->FindClient(Ip, EProtocol::dmrmmdvm);
if ( client != nullptr )
{
clients->RemoveClient(client);
}
- g_Reflector.ReleaseClients();
+ g_Refl..ReleaseClients();
}
else if ( IsValidConfigPacket(Buffer, &Callsign, Ip) )
{
@@ -197,7 +197,7 @@ void CDmrmmdvmProtocol::Task(void)
//std::cout << "DMRmmdvm keepalive packet from " << Callsign << " at " << Ip << std::endl;
// find all clients with that callsign & ip and keep them alive
- CClients *clients = g_Reflector.GetClients();
+ CClients *clients = g_Refl..GetClients();
auto it = clients->begin();
std::shared_ptrclient = nullptr;
while ( (client = clients->FindNextClient(Callsign, Ip, EProtocol::dmrmmdvm, it)) != nullptr )
@@ -209,7 +209,7 @@ void CDmrmmdvmProtocol::Task(void)
// and mark as alive
client->Alive();
}
- g_Reflector.ReleaseClients();
+ g_Refl..ReleaseClients();
}
else if ( IsValidRssiPacket(Buffer, &Callsign, &iRssi) )
{
@@ -273,7 +273,7 @@ void CDmrmmdvmProtocol::OnDvHeaderPacketIn(std::unique_ptr &Hea
CCallsign rpt2(Header->GetRpt2Callsign());
// no stream open yet, open a new one
// firstfind this client
- std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, EProtocol::dmrmmdvm);
+ std::shared_ptrclient = g_Refl..GetClients()->FindClient(Ip, EProtocol::dmrmmdvm);
if ( client )
{
// process cmd if any
@@ -282,7 +282,7 @@ void CDmrmmdvmProtocol::OnDvHeaderPacketIn(std::unique_ptr &Hea
// not linked yet
if ( cmd == CMD_LINK )
{
- if ( g_Reflector.IsValidModule(rpt2.GetCSModule()) )
+ if ( g_Refl..IsValidModule(rpt2.GetCSModule()) )
{
std::cout << "DMRmmdvm client " << client->GetCallsign() << " linking on module " << rpt2.GetCSModule() << std::endl;
// link
@@ -313,10 +313,10 @@ void CDmrmmdvmProtocol::OnDvHeaderPacketIn(std::unique_ptr &Hea
}
// and now, re-check module is valid && that it's not a private call
- if ( g_Reflector.IsValidModule(rpt2.GetCSModule()) && (CallType == DMR_GROUP_CALL) )
+ if ( g_Refl..IsValidModule(rpt2.GetCSModule()) && (CallType == DMR_GROUP_CALL) )
{
// yes, try to open the stream
- if ( (stream = g_Reflector.OpenStream(Header, client)) != nullptr )
+ if ( (stream = g_Refl..OpenStream(Header, client)) != nullptr )
{
// keep the handle
m_Streams[stream->GetStreamId()] = stream;
@@ -330,13 +330,13 @@ void CDmrmmdvmProtocol::OnDvHeaderPacketIn(std::unique_ptr &Hea
}
// release
- g_Reflector.ReleaseClients();
+ g_Refl..ReleaseClients();
// update last heard
if ( lastheard )
{
- g_Reflector.GetUsers()->Hearing(my, rpt1, rpt2);
- g_Reflector.ReleaseUsers();
+ g_Refl..GetUsers()->Hearing(my, rpt1, rpt2);
+ g_Refl..ReleaseUsers();
}
}
}
@@ -403,7 +403,7 @@ void CDmrmmdvmProtocol::HandleQueue(void)
if ( buffer.size() > 0 )
{
// and push it to all our clients linked to the module and who are not streaming in
- CClients *clients = g_Reflector.GetClients();
+ CClients *clients = g_Refl..GetClients();
auto it = clients->begin();
std::shared_ptrclient = nullptr;
while ( (client = clients->FindNextClient(EProtocol::dmrmmdvm, it)) != nullptr )
@@ -416,7 +416,7 @@ void CDmrmmdvmProtocol::HandleQueue(void)
}
}
- g_Reflector.ReleaseClients();
+ g_Refl..ReleaseClients();
}
}
m_Queue.Unlock();
@@ -432,7 +432,7 @@ void CDmrmmdvmProtocol::HandleKeepalives(void)
// and disconnect them if not
// iterate on clients
- CClients *clients = g_Reflector.GetClients();
+ CClients *clients = g_Refl..GetClients();
auto it = clients->begin();
std::shared_ptrclient = nullptr;
while ( (client = clients->FindNextClient(EProtocol::dmrmmdvm, it)) != nullptr )
@@ -456,7 +456,7 @@ void CDmrmmdvmProtocol::HandleKeepalives(void)
}
}
- g_Reflector.ReleaseClients();
+ g_Refl..ReleaseClients();
}
////////////////////////////////////////////////////////////////////////////////////////
@@ -696,7 +696,7 @@ bool CDmrmmdvmProtocol::IsValidDvFramePacket(const CBuffer &Buffer, std::arraySet(tag, sizeof(tag));
uint8_t cs[12];
-
+
// DMR header
// uiSeqId
Buffer->Append((uint8_t)seqid);
// uiSrcId
uint32_t uiSrcId = Header.GetMyCallsign().GetDmrid();
DvFrame0.GetMyCallsign().GetCallsign(cs);
-
+
if(uiSrcId == 0){
uiSrcId = DvFrame0.GetMyCallsign().GetDmrid();
}
@@ -880,7 +880,7 @@ void CDmrmmdvmProtocol::EncodeMMDVMPacket(const CDvHeaderPacket &Header, const C
if(uiSrcId == 0){
uiSrcId = DMRMMDVM_DEFAULTID;
}
-
+
AppendDmrIdToBuffer(Buffer, uiSrcId);
// uiDstId = TG9
uint32_t uiDstId = 9; // ModuleToDmrDestId(Header.GetRpt2Module());
@@ -924,7 +924,7 @@ void CDmrmmdvmProtocol::EncodeMMDVMPacket(const CDvHeaderPacket &Header, const C
// debug
//CBuffer dump;
//dump.Set(&(Buffer->data()[33]), 7);
- //dump.DebugDump(g_Reflector.m_DebugFile);
+ //dump.DebugDump(g_Refl..m_DebugFile);
// BER
Buffer->Append((uint8_t)0);
diff --git a/reflector/DMRPlusClient.cpp b/reflector/DMRPlusClient.cpp
index d5c709a..7ae4a63 100644
--- a/reflector/DMRPlusClient.cpp
+++ b/reflector/DMRPlusClient.cpp
@@ -16,7 +16,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-#include "Main.h"
+
#include "DMRPlusClient.h"
diff --git a/reflector/DMRPlusProtocol.cpp b/reflector/DMRPlusProtocol.cpp
index a6bb453..db96a50 100644
--- a/reflector/DMRPlusProtocol.cpp
+++ b/reflector/DMRPlusProtocol.cpp
@@ -16,7 +16,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-#include "Main.h"
+
#include
#include "DMRPlusClient.h"
#include "DMRPlusProtocol.h"
@@ -93,7 +93,7 @@ void CDmrplusProtocol::Task(void)
else if ( IsValidDvHeaderPacket(Ip, Buffer, Header) )
{
// callsign muted?
- if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::dmrplus) )
+ if ( g_Gate.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::dmrplus) )
{
// handle it
OnDvHeaderPacketIn(Header, Ip);
@@ -104,14 +104,14 @@ void CDmrplusProtocol::Task(void)
//std::cout << "DMRplus keepalive/connect packet for module " << ToLinkModule << " from " << Callsign << " at " << Ip << std::endl;
// callsign authorized?
- if ( g_GateKeeper.MayLink(Callsign, Ip, EProtocol::dmrplus) )
+ if ( g_Gate.MayLink(Callsign, Ip, EProtocol::dmrplus) )
{
// acknowledge the request
EncodeConnectAckPacket(&Buffer);
Send(Buffer, Ip);
// add client if needed
- CClients *clients = g_Reflector.GetClients();
+ CClients *clients = g_Refl..GetClients();
std::shared_ptrclient = clients->FindClient(Callsign, Ip, EProtocol::dmrplus);
// client already connected ?
if ( client == nullptr )
@@ -126,7 +126,7 @@ void CDmrplusProtocol::Task(void)
client->Alive();
}
// and done
- g_Reflector.ReleaseClients();
+ g_Refl..ReleaseClients();
}
else
{
@@ -141,13 +141,13 @@ void CDmrplusProtocol::Task(void)
std::cout << "DMRplus disconnect packet for module " << ToLinkModule << " from " << Callsign << " at " << Ip << std::endl;
// find client & remove it
- CClients *clients = g_Reflector.GetClients();
+ CClients *clients = g_Refl..GetClients();
std::shared_ptrclient = clients->FindClient(Ip, EProtocol::dmrplus);
if ( client != nullptr )
{
clients->RemoveClient(client);
}
- g_Reflector.ReleaseClients();
+ g_Refl..ReleaseClients();
}
else
{
@@ -196,21 +196,21 @@ void CDmrplusProtocol::OnDvHeaderPacketIn(std::unique_ptr &Head
// no stream open yet, open a new one
// find this client
- std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, EProtocol::dmrplus);
+ std::shared_ptrclient = g_Refl..GetClients()->FindClient(Ip, EProtocol::dmrplus);
if ( client )
{
// and try to open the stream
- if ( (stream = g_Reflector.OpenStream(Header, client)) != nullptr )
+ if ( (stream = g_Refl..OpenStream(Header, client)) != nullptr )
{
// keep the handle
m_Streams[stream->GetStreamId()] = stream;
}
}
// release
- g_Reflector.ReleaseClients();
+ g_Refl..ReleaseClients();
// update last heard
- g_Reflector.GetUsers()->Hearing(my, rpt1, rpt2);
- g_Reflector.ReleaseUsers();
+ g_Refl..GetUsers()->Hearing(my, rpt1, rpt2);
+ g_Refl..ReleaseUsers();
}
}
@@ -268,7 +268,7 @@ void CDmrplusProtocol::HandleQueue(void)
if ( buffer.size() > 0 )
{
// and push it to all our clients linked to the module and who are not streaming in
- CClients *clients = g_Reflector.GetClients();
+ CClients *clients = g_Refl..GetClients();
auto it = clients->begin();
std::shared_ptrclient = nullptr;
while ( (client = clients->FindNextClient(EProtocol::dmrplus, it)) != nullptr )
@@ -280,10 +280,10 @@ void CDmrplusProtocol::HandleQueue(void)
Send(buffer, client->GetIp());
}
}
- g_Reflector.ReleaseClients();
+ g_Refl..ReleaseClients();
// debug
- //buffer.DebugDump(g_Reflector.m_DebugFile);
+ //buffer.DebugDump(g_Refl..m_DebugFile);
}
}
m_Queue.Unlock();
@@ -294,7 +294,7 @@ void CDmrplusProtocol::SendBufferToClients(const CBuffer &buffer, uint8_t module
if ( buffer.size() > 0 )
{
// and push it to all our clients linked to the module and who are not streaming in
- CClients *clients = g_Reflector.GetClients();
+ CClients *clients = g_Refl..GetClients();
auto it = clients->begin();
std::shared_ptrclient = nullptr;
while ( (client = clients->FindNextClient(EProtocol::dmrplus, it)) != nullptr )
@@ -306,10 +306,10 @@ void CDmrplusProtocol::SendBufferToClients(const CBuffer &buffer, uint8_t module
Send(buffer, client->GetIp());
}
}
- g_Reflector.ReleaseClients();
+ g_Refl..ReleaseClients();
// debug
- //buffer.DebugDump(g_Reflector.m_DebugFile);
+ //buffer.DebugDump(g_Refl..m_DebugFile);
}
}
@@ -324,7 +324,7 @@ void CDmrplusProtocol::HandleKeepalives(void)
// and disconnect them if not
// iterate on clients
- CClients *clients = g_Reflector.GetClients();
+ CClients *clients = g_Refl..GetClients();
auto it = clients->begin();
std::shared_ptrclient = nullptr;
while ( (client = clients->FindNextClient(EProtocol::dmrplus, it)) != nullptr )
@@ -349,7 +349,7 @@ void CDmrplusProtocol::HandleKeepalives(void)
}
}
- g_Reflector.ReleaseClients();
+ g_Refl..ReleaseClients();
}
////////////////////////////////////////////////////////////////////////////////////////
diff --git a/reflector/DPlusClient.cpp b/reflector/DPlusClient.cpp
index 098b86a..8e62ecd 100644
--- a/reflector/DPlusClient.cpp
+++ b/reflector/DPlusClient.cpp
@@ -16,7 +16,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-#include "Main.h"
+
#include "DPlusClient.h"
diff --git a/reflector/DPlusProtocol.cpp b/reflector/DPlusProtocol.cpp
index 1f135dd..a162229 100644
--- a/reflector/DPlusProtocol.cpp
+++ b/reflector/DPlusProtocol.cpp
@@ -16,7 +16,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-#include "Main.h"
+
#include
#include "DPlusClient.h"
#include "DPlusProtocol.h"
@@ -72,7 +72,7 @@ void CDplusProtocol::Task(void)
else if ( IsValidDvHeaderPacket(Buffer, Header) )
{
// is muted?
- if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::dplus, Header->GetRpt2Module()) )
+ if ( g_Gate.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::dplus, Header->GetRpt2Module()) )
{
// handle it
OnDvHeaderPacketIn(Header, Ip);
@@ -90,15 +90,15 @@ void CDplusProtocol::Task(void)
std::cout << "DPlus login packet from " << Callsign << " at " << Ip << std::endl;
// callsign authorized?
- if ( g_GateKeeper.MayLink(Callsign, Ip, EProtocol::dplus) )
+ if ( g_Gate.MayLink(Callsign, Ip, EProtocol::dplus) )
{
// acknowledge the request
EncodeLoginAckPacket(&Buffer);
Send(Buffer, Ip);
// create the client and append
- g_Reflector.GetClients()->AddClient(std::make_shared(Callsign, Ip));
- g_Reflector.ReleaseClients();
+ g_Refl..GetClients()->AddClient(std::make_shared(Callsign, Ip));
+ g_Refl..ReleaseClients();
}
else
{
@@ -113,7 +113,7 @@ void CDplusProtocol::Task(void)
std::cout << "DPlus disconnect packet from " << Ip << std::endl;
// find client
- CClients *clients = g_Reflector.GetClients();
+ CClients *clients = g_Refl..GetClients();
std::shared_ptrclient = clients->FindClient(Ip, EProtocol::dplus);
if ( client != nullptr )
{
@@ -123,21 +123,21 @@ void CDplusProtocol::Task(void)
EncodeDisconnectPacket(&Buffer);
Send(Buffer, Ip);
}
- g_Reflector.ReleaseClients();
+ g_Refl..ReleaseClients();
}
else if ( IsValidKeepAlivePacket(Buffer) )
{
//std::cout << "DPlus keepalive packet from " << Ip << std::endl;
// find all clients with that callsign & ip and keep them alive
- CClients *clients = g_Reflector.GetClients();
+ CClients *clients = g_Refl..GetClients();
auto it = clients->begin();
std::shared_ptrclient = nullptr;
while ( (client = clients->FindNextClient(Ip, EProtocol::dplus, it)) != nullptr )
{
client->Alive();
}
- g_Reflector.ReleaseClients();
+ g_Refl..ReleaseClients();
}
else
{
@@ -185,10 +185,10 @@ void CDplusProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header
CCallsign rpt2(Header->GetRpt2Callsign());
// first, check module is valid
- if ( g_Reflector.IsValidModule(rpt2.GetCSModule()) )
+ if ( g_Refl..IsValidModule(rpt2.GetCSModule()) )
{
// find this client
- std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, EProtocol::dplus);
+ std::shared_ptrclient = g_Refl..GetClients()->FindClient(Ip, EProtocol::dplus);
if ( client )
{
// now we know if it's a dextra dongle or a genuine dplus node
@@ -204,18 +204,18 @@ void CDplusProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header
// get client callsign
rpt1 = client->GetCallsign();
// and try to open the stream
- if ( (stream = g_Reflector.OpenStream(Header, client)) != nullptr )
+ if ( (stream = g_Refl..OpenStream(Header, client)) != nullptr )
{
// keep the handle
m_Streams[stream->GetStreamId()] = stream;
}
}
// release
- g_Reflector.ReleaseClients();
+ g_Refl..ReleaseClients();
// update last heard
- g_Reflector.GetUsers()->Hearing(my, rpt1, rpt2);
- g_Reflector.ReleaseUsers();
+ g_Refl..GetUsers()->Hearing(my, rpt1, rpt2);
+ g_Refl..ReleaseUsers();
}
else
{
@@ -253,7 +253,7 @@ void CDplusProtocol::HandleQueue(void)
// and push it to all our clients who are not streaming in
// note that for dplus protocol, all stream of all modules are push to all clients
// it's client who decide which stream he's interrrested in
- CClients *clients = g_Reflector.GetClients();
+ CClients *clients = g_Refl..GetClients();
auto it = clients->begin();
std::shared_ptrclient = nullptr;
while ( (client = clients->FindNextClient(EProtocol::dplus, it)) != nullptr )
@@ -290,7 +290,7 @@ void CDplusProtocol::HandleQueue(void)
}
}
}
- g_Reflector.ReleaseClients();
+ g_Refl..ReleaseClients();
}
}
m_Queue.Unlock();
@@ -343,7 +343,7 @@ void CDplusProtocol::HandleKeepalives(void)
EncodeKeepAlivePacket(&keepalive);
// iterate on clients
- CClients *clients = g_Reflector.GetClients();
+ CClients *clients = g_Refl..GetClients();
auto it = clients->begin();
std::shared_ptrclient = nullptr;
while ( (client = clients->FindNextClient(EProtocol::dplus, it)) != nullptr )
@@ -371,7 +371,7 @@ void CDplusProtocol::HandleKeepalives(void)
clients->RemoveClient(client);
}
}
- g_Reflector.ReleaseClients();
+ g_Refl..ReleaseClients();
}
////////////////////////////////////////////////////////////////////////////////////////
diff --git a/reflector/DVFramePacket.cpp b/reflector/DVFramePacket.cpp
index 9db20b5..86f1d61 100644
--- a/reflector/DVFramePacket.cpp
+++ b/reflector/DVFramePacket.cpp
@@ -16,7 +16,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-#include "Main.h"
+
#include
#include "DVFramePacket.h"
diff --git a/reflector/DVHeaderPacket.cpp b/reflector/DVHeaderPacket.cpp
index ab47c3b..7bf6082 100644
--- a/reflector/DVHeaderPacket.cpp
+++ b/reflector/DVHeaderPacket.cpp
@@ -16,7 +16,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-#include "Main.h"
+
#include
#include
#include "DMRIdDir.h"
@@ -90,7 +90,7 @@ CDvHeaderPacket::CDvHeaderPacket(const struct dstar_header *buffer, uint16_t sid
m_uiFlag2 = buffer->Flag2;
m_uiFlag3 = buffer->Flag3;
m_csUR.SetCallsign(buffer->UR, CALLSIGN_LEN);
-
+
if((buffer->RPT1)[7] == 0x20){
char rptr1[8];
memcpy(rptr1, buffer->RPT1, 8);
@@ -100,7 +100,7 @@ CDvHeaderPacket::CDvHeaderPacket(const struct dstar_header *buffer, uint16_t sid
else{
m_csRPT1.SetCallsign(buffer->RPT1, CALLSIGN_LEN);
}
-
+
m_csRPT1.SetCallsign(buffer->RPT1, CALLSIGN_LEN);
m_csRPT2.SetCallsign(buffer->RPT2, CALLSIGN_LEN);
m_csMY.SetCallsign(buffer->MY, CALLSIGN_LEN);
diff --git a/reflector/Defines.h b/reflector/Defines.h
new file mode 100644
index 0000000..690b01f
--- /dev/null
+++ b/reflector/Defines.h
@@ -0,0 +1,125 @@
+// 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
+#include
+#include