From 6e7ba8c5a0c49961cfd7e87f5d7996903ec8394a Mon Sep 17 00:00:00 2001 From: Tom Early Date: Sat, 11 Feb 2023 09:53:39 -0700 Subject: [PATCH 01/44] starting to use json --- .gitignore | 3 +- reflector/BMClient.cpp | 2 +- reflector/BMPeer.cpp | 2 +- reflector/BMProtocol.cpp | 46 +- reflector/Buffer.h | 1 - reflector/Callsign.cpp | 78 +- reflector/CallsignList.cpp | 2 +- reflector/CallsignList.h | 2 +- reflector/CallsignListItem.cpp | 2 +- reflector/CallsignListItem.h | 2 +- reflector/Client.cpp | 2 +- reflector/Clients.cpp | 6 +- reflector/CodecStream.cpp | 46 +- reflector/CodecStream.h | 12 +- reflector/Configure.cpp | 928 +++++++++++++++++++++ reflector/Configure.h | 106 +++ reflector/DCSClient.cpp | 2 +- reflector/DCSProtocol.cpp | 38 +- reflector/DExtraClient.cpp | 2 +- reflector/DExtraPeer.cpp | 2 +- reflector/DExtraProtocol.cpp | 66 +- reflector/DMRIdDir.cpp | 145 ---- reflector/DMRIdDirFile.cpp | 159 ---- reflector/DMRIdDirHttp.cpp | 177 ---- reflector/DMRMMDVMClient.cpp | 2 +- reflector/DMRMMDVMProtocol.cpp | 54 +- reflector/DMRPlusClient.cpp | 2 +- reflector/DMRPlusProtocol.cpp | 40 +- reflector/DPlusClient.cpp | 2 +- reflector/DPlusProtocol.cpp | 38 +- reflector/DVFramePacket.cpp | 2 +- reflector/DVHeaderPacket.cpp | 6 +- reflector/Defines.h | 125 +++ reflector/G3Client.cpp | 2 +- reflector/G3Protocol.cpp | 44 +- reflector/GateKeeper.cpp | 2 +- reflector/GateKeeper.h | 2 +- reflector/{DMRIdDirHttp.h => Global.h} | 39 +- reflector/Lookup.cpp | 95 +++ reflector/{DMRIdDir.h => Lookup.h} | 64 +- reflector/LookupDmr.cpp | 262 ++++++ reflector/{NXDNIdDirHttp.h => LookupDmr.h} | 31 +- reflector/LookupNxdn.cpp | 264 ++++++ reflector/{DMRIdDirFile.h => LookupNxdn.h} | 41 +- reflector/LookupYsf.cpp | 256 ++++++ reflector/{NXDNIdDirFile.h => LookupYsf.h} | 38 +- reflector/M17Client.cpp | 2 +- reflector/M17Protocol.cpp | 40 +- reflector/Main.cpp | 44 +- reflector/Main.h | 276 ------ reflector/NXDNClient.cpp | 2 +- reflector/NXDNIdDir.cpp | 145 ---- reflector/NXDNIdDir.h | 86 -- reflector/NXDNIdDirFile.cpp | 159 ---- reflector/NXDNIdDirHttp.cpp | 177 ---- reflector/NXDNProtocol.cpp | 73 +- reflector/Notification.cpp | 2 +- reflector/P25Client.cpp | 2 +- reflector/P25Protocol.cpp | 45 +- reflector/Packet.cpp | 2 +- reflector/PacketStream.cpp | 30 +- reflector/PacketStream.h | 12 +- reflector/Peer.cpp | 2 +- reflector/PeerCallsignList.cpp | 2 +- reflector/PeerCallsignList.h | 2 +- reflector/Peers.cpp | 14 +- reflector/Protocol.cpp | 6 +- reflector/Protocols.cpp | 8 +- reflector/RawSocket.cpp | 2 +- reflector/Reflector.cpp | 339 ++------ reflector/Reflector.h | 49 +- reflector/Semaphore.cpp | 2 +- reflector/Semaphore.h | 2 +- reflector/UDPMsgSocket.cpp | 2 +- reflector/UDPSocket.cpp | 2 +- reflector/URFClient.cpp | 2 +- reflector/URFPeer.cpp | 2 +- reflector/URFProtocol.cpp | 56 +- reflector/USRPClient.cpp | 2 +- reflector/USRPProtocol.cpp | 37 +- reflector/User.cpp | 2 +- reflector/User.h | 4 +- reflector/Users.cpp | 6 +- reflector/Users.h | 3 + reflector/Version.cpp | 122 +-- reflector/Version.h | 64 +- reflector/WiresXCmd.cpp | 2 +- reflector/WiresXCmdHandler.cpp | 24 +- reflector/WiresXInfo.cpp | 2 +- reflector/YSFClient.cpp | 2 +- reflector/YSFNode.cpp | 2 +- reflector/YSFNode.h | 2 +- reflector/YSFNodeDir.cpp | 176 ---- reflector/YSFNodeDir.h | 94 --- reflector/YSFNodeDirFile.cpp | 161 ---- reflector/YSFNodeDirFile.h | 47 -- reflector/YSFNodeDirHttp.cpp | 179 ---- reflector/YSFNodeDirHttp.h | 40 - reflector/YSFProtocol.cpp | 52 +- reflector/YSFUtils.cpp | 2 +- reflector/example.ini | 121 +++ 101 files changed, 2931 insertions(+), 3046 deletions(-) create mode 100644 reflector/Configure.cpp create mode 100644 reflector/Configure.h delete mode 100644 reflector/DMRIdDir.cpp delete mode 100644 reflector/DMRIdDirFile.cpp delete mode 100644 reflector/DMRIdDirHttp.cpp create mode 100644 reflector/Defines.h rename reflector/{DMRIdDirHttp.h => Global.h} (58%) create mode 100644 reflector/Lookup.cpp rename reflector/{DMRIdDir.h => Lookup.h} (54%) create mode 100644 reflector/LookupDmr.cpp rename reflector/{NXDNIdDirHttp.h => LookupDmr.h} (56%) create mode 100644 reflector/LookupNxdn.cpp rename reflector/{DMRIdDirFile.h => LookupNxdn.h} (56%) create mode 100644 reflector/LookupYsf.cpp rename reflector/{NXDNIdDirFile.h => LookupYsf.h} (59%) delete mode 100644 reflector/Main.h delete mode 100644 reflector/NXDNIdDir.cpp delete mode 100644 reflector/NXDNIdDir.h delete mode 100644 reflector/NXDNIdDirFile.cpp delete mode 100644 reflector/NXDNIdDirHttp.cpp delete mode 100644 reflector/YSFNodeDir.cpp delete mode 100644 reflector/YSFNodeDir.h delete mode 100644 reflector/YSFNodeDirFile.cpp delete mode 100644 reflector/YSFNodeDirFile.h delete mode 100644 reflector/YSFNodeDirHttp.cpp delete mode 100644 reflector/YSFNodeDirHttp.h create mode 100644 reflector/example.ini 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////// +// defines + +//// Module configuration +#define DSTAR_IPV4 true +#define DMR_IPV4 true +#define YSF_IPV4 true +#define BM_IPV4 true +#define M17_IPV4 true +#define URF_IPV4 true + +#define DSTAR_IPV6 true +#define DMR_IPV6 false +#define YSF_IPV6 false +#define BM_IPV6 false +#define M17_IPV6 true +#define URF_IPV6 true + +// protocols --------------------------------------------------- + +enum class EProtocol { any, none, dextra, dplus, dcs, bm, urf, dmrplus, dmrmmdvm, ysf, m17 }; + +// DExtra +#define DEXTRA_KEEPALIVE_PERIOD 3 // in seconds +#define DEXTRA_KEEPALIVE_TIMEOUT (DEXTRA_KEEPALIVE_PERIOD*10) // in seconds +#define DEXTRA_RECONNECT_PERIOD 5 // in seconds + +// DPlus +#define DPLUS_KEEPALIVE_PERIOD 1 // in seconds +#define DPLUS_KEEPALIVE_TIMEOUT (DPLUS_KEEPALIVE_PERIOD*10) // in seconds +#define DPLUS_DEFAULT_RPTR1_SUFFIX 'Y' + +// DCS +#define DCS_KEEPALIVE_PERIOD 1 // in seconds +#define DCS_KEEPALIVE_TIMEOUT (DCS_KEEPALIVE_PERIOD*30) // in seconds + +// XLX, used for BM +#define BM_KEEPALIVE_PERIOD 1 // in seconds +#define BM_KEEPALIVE_TIMEOUT (XLX_KEEPALIVE_PERIOD*30) // in seconds +#define BM_RECONNECT_PERIOD 5 // in seconds + +// URF +#define URF_KEEPALIVE_PERIOD 1 // in seconds +#define URF_KEEPALIVE_TIMEOUT (URF_KEEPALIVE_PERIOD*30) // in seconds +#define URF_RECONNECT_PERIOD 5 // in seconds + +// DMRPlus (dongle) +#define DMRPLUS_KEEPALIVE_PERIOD 1 // in seconds +#define DMRPLUS_KEEPALIVE_TIMEOUT (DMRPLUS_KEEPALIVE_PERIOD*10) // in seconds +#define DMRPLUS_REFLECTOR_SLOT DMR_SLOT2 + +// DMRMmdvm +#define DMRMMDVM_KEEPALIVE_PERIOD 10 // in seconds +#define DMRMMDVM_KEEPALIVE_TIMEOUT (DMRMMDVM_KEEPALIVE_PERIOD*10) // in seconds +#define DMRMMDVM_REFLECTOR_SLOT DMR_SLOT2 +#define DMRMMDVM_REFLECTOR_COLOUR 1 + +// YSF +#define YSF_KEEPALIVE_PERIOD 3 // in seconds +#define YSF_KEEPALIVE_TIMEOUT (YSF_KEEPALIVE_PERIOD*10) // in seconds + +// M17 +#define M17_KEEPALIVE_PERIOD 3 +#define M17_KEEPALIVE_TIMEOUT (M17_KEEPALIVE_PERIOD*10) + +// G3 Terminal +#define G3_PRESENCE_PORT 12346 // UDP port +#define G3_CONFIG_PORT 12345 // UDP port +#define G3_DV_PORT 40000 // UDP port +#define G3_KEEPALIVE_PERIOD 10 // in seconds +#define G3_KEEPALIVE_TIMEOUT 3600 // in seconds, 1 hour + + +//////////////////////////////////////////////////////////////////////////////////////// +// macros + +#define MIN(a,b) ((a)<(b))?(a):(b) +#define MAX(a,b) ((a)>(b))?(a):(b) +#define MAKEWORD(low, high) ((uint16_t)(((uint8_t)(low)) | (((uint16_t)((uint8_t)(high))) << 8))) +#define MAKEDWORD(low, high) ((uint32_t)(((uint16_t)(low)) | (((uint32_t)((uint16_t)(high))) << 16))) +#define LOBYTE(w) ((uint8_t)(uint16_t)(w & 0x00FF)) +#define HIBYTE(w) ((uint8_t)((((uint16_t)(w)) >> 8) & 0xFF)) +#define LOWORD(dw) ((uint16_t)(uint32_t)(dw & 0x0000FFFF)) +#define HIWORD(dw) ((uint16_t)((((uint32_t)(dw)) >> 16) & 0xFFFF)) diff --git a/reflector/G3Client.cpp b/reflector/G3Client.cpp index 9b6cbc5..f69e6fc 100644 --- a/reflector/G3Client.cpp +++ b/reflector/G3Client.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 "G3Client.h" diff --git a/reflector/G3Protocol.cpp b/reflector/G3Protocol.cpp index 1368e54..0d5f62c 100644 --- a/reflector/G3Protocol.cpp +++ b/reflector/G3Protocol.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 "G3Client.h" @@ -37,7 +37,7 @@ bool CG3Protocol::Initialize(const char */*type*/, const EProtocol /*type*/, con ReadOptions(); // init reflector apparent callsign - m_ReflectorCallsign = g_Reflector.GetCallsign(); + m_ReflectorCallsign = g_Refl..GetCallsign(); // reset stop flag keep_running = true; @@ -177,7 +177,7 @@ void CG3Protocol::PresenceTask(void) Buffer.Append(m_GwAddress); } - CClients *clients = g_Reflector.GetClients(); + CClients *clients = g_Refl..GetClients(); auto it = clients->begin(); std::shared_ptrextant = nullptr; while ( (extant = clients->FindNextClient(EProtocol::g3, it)) != nullptr ) @@ -219,7 +219,7 @@ void CG3Protocol::PresenceTask(void) clients->AddClient(std::make_shared(Terminal, Ip)); } } - g_Reflector.ReleaseClients(); + g_Refl..ReleaseClients(); m_PresenceSocket.Send(Buffer, ReqIp); } @@ -260,7 +260,7 @@ void CG3Protocol::ConfigTask(void) if (isRepeaterCall) { - if ((Call.HasSameCallsign(GetReflectorCallsign())) && (g_Reflector.IsValidModule(Call.GetCSModule()))) + if ((Call.HasSameCallsign(GetReflectorCallsign())) && (g_Refl..IsValidModule(Call.GetCSModule()))) { Buffer.data()[3] = 0x00; // ok } @@ -343,7 +343,7 @@ void CG3Protocol::IcmpTask(void) { if (iIcmpType == ICMP_DEST_UNREACH) { - CClients *clients = g_Reflector.GetClients(); + CClients *clients = g_Refl..GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::g3, it)) != nullptr ) @@ -354,7 +354,7 @@ void CG3Protocol::IcmpTask(void) clients->RemoveClient(client); } } - g_Reflector.ReleaseClients(); + g_Refl..ReleaseClients(); } } } @@ -378,7 +378,7 @@ void CG3Protocol::Task(void) { CIp ClIp; CIp *BaseIp = nullptr; - CClients *clients = g_Reflector.GetClients(); + CClients *clients = g_Refl..GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::g3, it)) != nullptr ) @@ -394,7 +394,7 @@ void CG3Protocol::Task(void) break; } } - g_Reflector.ReleaseClients(); + g_Refl..ReleaseClients(); if (BaseIp != nullptr) { @@ -406,7 +406,7 @@ void CG3Protocol::Task(void) else if ( IsValidDvHeaderPacket(Buffer, Header) ) { // callsign muted? - if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::g3, Header->GetRpt2Module()) ) + if ( g_Gate.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::g3, Header->GetRpt2Module()) ) { // handle it OnDvHeaderPacketIn(Header, *BaseIp); @@ -454,7 +454,7 @@ void CG3Protocol::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::g3, it)) != nullptr ) @@ -470,7 +470,7 @@ void CG3Protocol::HandleQueue(void) } } } - g_Reflector.ReleaseClients(); + g_Refl..ReleaseClients(); } } m_Queue.Unlock(); @@ -487,7 +487,7 @@ void CG3Protocol::HandleKeepalives(void) CBuffer keepalive((uint8_t *)"PING", 4); // 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::g3, it)) != nullptr ) @@ -502,7 +502,7 @@ void CG3Protocol::HandleKeepalives(void) Send(keepalive, client->GetIp()); } } - g_Reflector.ReleaseClients(); + g_Refl..ReleaseClients(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -527,7 +527,7 @@ void CG3Protocol::OnDvHeaderPacketIn(std::unique_ptr &Header, c CCallsign rpt2(Header->GetRpt2Callsign()); // find this client - CClients *clients = g_Reflector.GetClients(); + CClients *clients = g_Refl..GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::g3, it)) != nullptr ) @@ -554,7 +554,7 @@ void CG3Protocol::OnDvHeaderPacketIn(std::unique_ptr &Header, c } else { - g_Reflector.ReleaseClients(); + g_Refl..ReleaseClients(); return; } } @@ -563,19 +563,19 @@ void CG3Protocol::OnDvHeaderPacketIn(std::unique_ptr &Header, c 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; } // update last heard - g_Reflector.GetUsers()->Hearing(my, rpt1, rpt2); - g_Reflector.ReleaseUsers(); + g_Refl..GetUsers()->Hearing(my, rpt1, rpt2); + g_Refl..ReleaseUsers(); } } // release - g_Reflector.ReleaseClients(); + g_Refl..ReleaseClients(); } } @@ -679,7 +679,7 @@ void CG3Protocol::NeedReload(void) ReadOptions(); // we have new options - iterate on clients for potential removal - CClients *clients = g_Reflector.GetClients(); + CClients *clients = g_Refl..GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::g3, it)) != nullptr ) @@ -690,7 +690,7 @@ void CG3Protocol::NeedReload(void) clients->RemoveClient(client); } } - g_Reflector.ReleaseClients(); + g_Refl..ReleaseClients(); } } } diff --git a/reflector/GateKeeper.cpp b/reflector/GateKeeper.cpp index e00043a..2e96e04 100644 --- a/reflector/GateKeeper.cpp +++ b/reflector/GateKeeper.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 "Timer.h" #include "GateKeeper.h" diff --git a/reflector/GateKeeper.h b/reflector/GateKeeper.h index a35316f..4b5814d 100644 --- a/reflector/GateKeeper.h +++ b/reflector/GateKeeper.h @@ -19,7 +19,7 @@ #pragma once -#include "Main.h" +#include "Defines.h" #include "Callsign.h" #include "IP.h" #include "CallsignList.h" diff --git a/reflector/DMRIdDirHttp.h b/reflector/Global.h similarity index 58% rename from reflector/DMRIdDirHttp.h rename to reflector/Global.h index 54d2577..39c515d 100644 --- a/reflector/DMRIdDirHttp.h +++ b/reflector/Global.h @@ -1,7 +1,5 @@ -// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. - // urfd -- The universal reflector -// Copyright © 2021 Thomas A. Early N7TAE +// Copyright © 2023 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 @@ -16,25 +14,18 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -#pragma once - -#include "DMRIdDir.h" - -class CDmridDirHttp : public CDmridDir -{ -public: - // constructor - CDmridDirHttp() {} - - // destructor - ~CDmridDirHttp() {} - - // refresh - bool LoadContent(CBuffer *); - bool RefreshContent(const CBuffer &); +#include "Reflector.h" +#include "GateKeeper.h" +#include "Configure.h" +#include "Version.h" +#include "LookupDmr.h" +#include "LookupNxdn.h" +#include "LookupYsf.h" -protected: - // reload helpers - bool NeedReload(void) { return true; } - bool HttpGet(const char *, const char *, int, CBuffer *); -}; +extern CReflector g_Refl; +extern CGateKeeper g_Gate; +extern CConfigure g_Conf; +extern CVersion g_Vers; +extern CLookupDmr g_LDid; +extern CLookupNxdn g_LNid; +extern CLookupYsf g_LYtr; diff --git a/reflector/Lookup.cpp b/reflector/Lookup.cpp new file mode 100644 index 0000000..fa85586 --- /dev/null +++ b/reflector/Lookup.cpp @@ -0,0 +1,95 @@ +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. + +// urfd -- The universal reflector +// Copyright © 2023 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 "Lookup.h" + +CLookup::~CLookup() +{ + LookupClose(); +} + +void CLookup::LookupClose() +{ + keep_running = false; + if (m_Future.valid()) + m_Future.get(); +} + +std::time_t CLookup::GetLastModTime() +{ + struct stat fileStat; + if(0 == stat(m_Path.c_str(), &fileStat)) + { + return fileStat.st_mtime; + } + return 0; +} + +void CLookup::LookupInit() +{ + LoadParameters(); + + m_Future = std::async(std::launch::async, &CLookup::Thread, this); +} + +void CLookup::Thread() +{ + while (keep_running) + { + bool loaded = false; + + if (m_Type != ERefreshType::file) // get the HTTP contents + { + CBuffer buf; + loaded = LoadContentHttp(buf); + if (loaded) + { + Lock(); + ClearContents(); + RefreshContentHttp(buf); + Unlock(); + } + } + + + if (m_Type != ERefreshType::http) // get the file contents + { + auto lastTime = GetLastModTime(); + if (lastTime > m_LastModTime) + { + CBuffer buf; + if (LoadContentFile(buf)) + { + Lock(); + if (! loaded) + ClearContents(); + RefreshContentFile(buf); + Unlock(); + m_LastModTime = lastTime; + } + } + } + + // now wait for a while... + for (unsigned i=0; i<20u*m_Refresh && keep_running; i++) + std::this_thread::sleep_for(std::chrono::seconds(3)); + } +} diff --git a/reflector/DMRIdDir.h b/reflector/Lookup.h similarity index 54% rename from reflector/DMRIdDir.h rename to reflector/Lookup.h index e4b8935..86ef905 100644 --- a/reflector/DMRIdDir.h +++ b/reflector/Lookup.h @@ -1,7 +1,7 @@ // Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. // urfd -- The universal reflector -// Copyright © 2021 Thomas A. Early N7TAE +// Copyright © 2023 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 @@ -18,68 +18,60 @@ #pragma once -#include -#include -#include -#include +#include +#include +#include #include "Buffer.h" #include "Callsign.h" +#include "Configure.h" // compare function for std::map::find -struct CDmridDirCallsignCompare +struct CCallsignCompare { bool operator() (const CCallsign &cs1, const CCallsign &cs2) const - { return cs1.HasLowerCallsign(cs2);} + { + return cs1.HasLowerCallsign(cs2); + } }; //////////////////////////////////////////////////////////////////////////////////////// -class CDmridDir +class CLookup { public: // constructor - CDmridDir(); + CLookup() : keep_running(true), m_LastModTime(0) {} // destructor - ~CDmridDir(); + virtual ~CLookup(); - // init & close - virtual bool Init(void); - virtual void Close(void); + void LookupInit(); + void LookupClose(); // locks - void Lock(void) { m_Mutex.lock(); } - void Unlock(void) { m_Mutex.unlock(); } - - // refresh - virtual bool LoadContent(CBuffer *) { return false; } - virtual bool RefreshContent(const CBuffer &) { return false; } - - // find - const CCallsign *FindCallsign(uint32_t); - uint32_t FindDmrid(const CCallsign &); + void Lock(void) { m_Mutex.lock(); } + void Unlock(void) { m_Mutex.unlock(); } protected: - // thread + std::time_t GetLastModTime(); + virtual void LoadParameters() = 0; + virtual void ClearContents() = 0; void Thread(); - // reload helpers - bool Reload(void); - virtual bool NeedReload(void) { return false; } - bool IsValidDmrid(const char *); - -protected: - // data - std::map m_CallsignMap; - std::map m_DmridMap; + // refresh + virtual bool LoadContentFile(CBuffer &buf) = 0; + virtual bool LoadContentHttp(CBuffer &buf) = 0; + virtual void RefreshContentFile(const CBuffer &) = 0; + virtual void RefreshContentHttp(const CBuffer &) = 0; - // Lock() std::mutex m_Mutex; + ERefreshType m_Type; + unsigned m_Refresh; + std::string m_Path, m_Host, m_Suffix; + std::time_t m_LastModTime; - // thread std::atomic keep_running; std::future m_Future; - }; diff --git a/reflector/LookupDmr.cpp b/reflector/LookupDmr.cpp new file mode 100644 index 0000000..af61349 --- /dev/null +++ b/reflector/LookupDmr.cpp @@ -0,0 +1,262 @@ +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. + +// urfd -- The universal reflector +// Copyright © 2023 Thomas A. Early N7TAE +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include +#include +#include +#include + +#include "Reflector.h" +#include "LookupDmr.h" + +extern CReflector g_ref; +extern CConfigure g_cfg; + +void CLookupDmr::ClearContents() +{ + m_CallsignMap.clear(); + m_DmridMap.clear(); +} + +void CLookupDmr::LoadParameters() +{ + g_cfg.GetRefreshType(g_cfg.j.dmriddb.mode, m_Type); + g_cfg.GetUnsigned(g_cfg.j.dmriddb.refreshmin, m_Refresh); + g_cfg.GetString(g_cfg.j.dmriddb.filepath, m_Path); + g_cfg.GetString(g_cfg.j.dmriddb.hostname, m_Host); + g_cfg.GetString(g_cfg.j.dmriddb.suffix, m_Suffix); +} + +uint32_t CLookupDmr::FindDmrid(const CCallsign &callsign) +{ + + auto found = m_DmridMap.find(callsign); + if ( found != m_DmridMap.end() ) + { + return (found->second); + } + return 0; +} + +const CCallsign *CLookupDmr::FindCallsign(uint32_t dmrid) +{ + auto found = m_CallsignMap.find(dmrid); + if ( found != m_CallsignMap.end() ) + { + return &(found->second); + } + return nullptr; +} + +bool CLookupDmr::LoadContentFile(CBuffer &buffer) +{ + buffer.clear(); + std::ifstream file; + std::streampos size; + + // open file + file.open(m_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(); + } + } + + // done + return buffer.size() > 0; +} + +bool CLookupDmr::LoadContentHttp(CBuffer &buf) +{ + // get file from xlxapi server + return HttpGet(m_Host.c_str(), m_Suffix.c_str(), 80, buf); +} + +void CLookupDmr::RefreshContentFile(const CBuffer &buffer) +{ + // 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; + } + + std::cout << "Read " << m_DmridMap.size() << " DMR ids from file " << m_Refresh << std::endl; +} + +void CLookupDmr::RefreshContentHttp(const CBuffer &buffer) +{ + 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; + } + + std::cout << "Read " << m_DmridMap.size() << " DMR ids from " << m_Host << " database " << std::endl; +} + +bool CLookupDmr::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 = ok && isdigit(sz[i]); + } + } + return ok; +} + +#define DMRID_HTTPGET_SIZEMAX (256) + +bool CLookupDmr::HttpGet(const char *hostname, const char *filename, int port, CBuffer &buffer) +{ + buffer.clear(); + 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, g_ref.GetCallsign().GetCS().c_str()); + ::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 + 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); + } + //} + 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 buffer.size() > 1; +} diff --git a/reflector/NXDNIdDirHttp.h b/reflector/LookupDmr.h similarity index 56% rename from reflector/NXDNIdDirHttp.h rename to reflector/LookupDmr.h index c26311c..d0e478b 100644 --- a/reflector/NXDNIdDirHttp.h +++ b/reflector/LookupDmr.h @@ -1,7 +1,7 @@ // Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. // urfd -- The universal reflector -// Copyright © 2021 Thomas A. Early N7TAE +// Copyright © 2023 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 @@ -18,23 +18,26 @@ #pragma once -#include "NXDNIdDir.h" +#include "Lookup.h" -class CNXDNidDirHttp : public CNXDNidDir +class CLookupDmr : public CLookup { public: - // constructor - CNXDNidDirHttp() {} + uint32_t FindDmrid(const CCallsign &cs); + const CCallsign *FindCallsign(uint32_t dmrid); - // destructor - ~CNXDNidDirHttp() {} +protected: + void ClearContents(); + void LoadParameters(); + bool LoadContentFile(CBuffer &buf); + bool LoadContentHttp(CBuffer &buf); + void RefreshContentFile(const CBuffer &); + void RefreshContentHttp(const CBuffer &); - // refresh - bool LoadContent(CBuffer *); - bool RefreshContent(const CBuffer &); +private: + std::map m_CallsignMap; + std::map m_DmridMap; -protected: - // reload helpers - bool NeedReload(void) { return true; } - bool HttpGet(const char *, const char *, int, CBuffer *); + bool IsValidDmrId(const char *); + bool HttpGet(const char *, const char *, int, CBuffer &); }; diff --git a/reflector/LookupNxdn.cpp b/reflector/LookupNxdn.cpp new file mode 100644 index 0000000..624cdbd --- /dev/null +++ b/reflector/LookupNxdn.cpp @@ -0,0 +1,264 @@ +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. + +// urfd -- The universal reflector +// Copyright © 2023 Thomas A. Early N7TAE +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include +#include +#include +#include + +#include "Reflector.h" +#include "LookupNxdn.h" + +extern CReflector g_ref; +extern CConfigure g_cfg; + +void CLookupNxdn::ClearContents() +{ + m_CallsignMap.clear(); + m_NxdnidMap.clear(); +} + +void CLookupNxdn::LoadParameters() +{ + g_cfg.GetRefreshType(g_cfg.j.nxdniddb.mode, m_Type); + g_cfg.GetUnsigned(g_cfg.j.nxdniddb.refreshmin, m_Refresh); + g_cfg.GetString(g_cfg.j.nxdniddb.filepath, m_Path); + g_cfg.GetString(g_cfg.j.dmriddb.hostname, m_Host); + g_cfg.GetString(g_cfg.j.nxdniddb.suffix, m_Suffix); +} + +const CCallsign *CLookupNxdn::FindCallsign(uint16_t nxdnid) +{ + auto found = m_CallsignMap.find(nxdnid); + if ( found != m_CallsignMap.end() ) + { + return &(found->second); + } + return nullptr; +} + +uint16_t CLookupNxdn::FindNXDNid(const CCallsign &callsign) +{ + auto found = m_NxdnidMap.find(callsign); + if ( found != m_NxdnidMap.end() ) + { + return (found->second); + } + return 0; +} + +bool CLookupNxdn::LoadContentFile(CBuffer &buffer) +{ + buffer.clear(); + std::ifstream file; + std::streampos size; + + // open file + file.open(m_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(); + + // done + } + } + + // done + return buffer.size() > 0; +} + +bool CLookupNxdn::LoadContentHttp(CBuffer &buffer) +{ + // get file from xlxapi server + return HttpGet(m_Host.c_str(), m_Suffix.c_str(), 80, buffer); +} + +void CLookupNxdn::RefreshContentFile(const CBuffer &buffer) +{ + // crack it + char *ptr1 = (char *)buffer.data(); + char *ptr2; + + // get next line + while ( (ptr2 = ::strchr(ptr1, '\n')) != nullptr ) + { + *ptr2 = 0; + // get items + char *nxdnid; + char *callsign; + if ( ((nxdnid = ::strtok(ptr1, ",")) != nullptr) && IsValidNxdnId(nxdnid) ) + { + if ( ((callsign = ::strtok(nullptr, ",")) != nullptr) ) + { + // new entry + uint16_t us = atoi(nxdnid); + CCallsign cs(callsign, 0, us); + if ( cs.IsValid() ) + { + m_CallsignMap.insert(std::pair(us, cs)); + m_NxdnidMap.insert(std::pair(cs,us)); + } + } + } + // next line + ptr1 = ptr2+1; + } + + std::cout << "Read " << m_NxdnidMap.size() << " NXDN ids from file " << m_Path << std::endl; +} + +void CLookupNxdn::RefreshContentHttp(const CBuffer &buffer) +{ + char *ptr1 = (char *)buffer.data(); + char *ptr2; + // get next line + while ( (ptr2 = strchr(ptr1, '\n')) != nullptr ) + { + std::cout << "newline: " << std::string(ptr2) << std::endl; + *ptr2 = 0; + // get items + char *nxdnid; + char *callsign; + if ( ((nxdnid = ::strtok(ptr1, ",")) != nullptr) && IsValidNxdnId(nxdnid) ) + { + if ( ((callsign = ::strtok(nullptr, ",")) != nullptr) ) + { + // new entry + uint16_t us = atoi(nxdnid); + CCallsign cs(callsign, 0, us); + if ( cs.IsValid() ) + { + m_CallsignMap.insert(std::pair(us, cs)); + m_NxdnidMap.insert(std::pair(cs,us)); + } + } + } + // next line + ptr1 = ptr2+1; + } + + std::cout << "Read " << m_NxdnidMap.size() << " NXDN ids from " << m_Host << std::endl; +} + +bool CLookupNxdn::IsValidNxdnId(const char *sz) +{ + bool ok = false; + size_t n = ::strlen(sz); + if ( (n > 0) && (n <= 5) ) + { + ok = true; + for ( size_t i = 0; (i < n) && ok; i++ ) + { + ok = ok && isdigit(sz[i]); + } + } + return ok; +} + +#define NXDNID_HTTPGET_SIZEMAX (256) + +bool CLookupNxdn::HttpGet(const char *hostname, const char *filename, int port, CBuffer &buffer) +{ + int sock_id; + buffer.clear(); + + // 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[NXDNID_HTTPGET_SIZEMAX]; + ::sprintf(request, "GET /%s HTTP/1.0\r\nFrom: %s\r\nUser-Agent: urfd\r\n\r\n", filename, (const char *)g_ref.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 + 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); + } + //} + 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 buffer.size() > 1; +} diff --git a/reflector/DMRIdDirFile.h b/reflector/LookupNxdn.h similarity index 56% rename from reflector/DMRIdDirFile.h rename to reflector/LookupNxdn.h index e4f4054..36f2be6 100644 --- a/reflector/DMRIdDirFile.h +++ b/reflector/LookupNxdn.h @@ -1,7 +1,7 @@ // Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. // urfd -- The universal reflector -// Copyright © 2021 Thomas A. Early N7TAE +// Copyright © 2023 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 @@ -18,30 +18,25 @@ #pragma once -#include "DMRIdDir.h" +#include "Lookup.h" -class CDmridDirFile : public CDmridDir +class CLookupNxdn : public CLookup { public: - // constructor - CDmridDirFile(); - - // destructor - ~CDmridDirFile() {} - - // init & close - bool Init(void); - - // refresh - bool LoadContent(CBuffer *); - bool RefreshContent(const CBuffer &); - -protected: - // reload helpers - bool NeedReload(void); - bool GetLastModTime(time_t *); - + uint16_t FindNXDNid(const CCallsign &callsign); + const CCallsign *FindCallsign(uint16_t id); protected: - // data - time_t m_LastModTime; + void ClearContents(); + void LoadParameters(); + bool LoadContentFile(CBuffer &buf); + bool LoadContentHttp(CBuffer &buf); + void RefreshContentFile(const CBuffer &); + void RefreshContentHttp(const CBuffer &); + +private: + std::map m_CallsignMap; + std::map m_NxdnidMap; + + bool IsValidNxdnId(const char *); + bool HttpGet(const char *, const char *, int, CBuffer &); }; diff --git a/reflector/LookupYsf.cpp b/reflector/LookupYsf.cpp new file mode 100644 index 0000000..96e556c --- /dev/null +++ b/reflector/LookupYsf.cpp @@ -0,0 +1,256 @@ +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. + +// urfd -- The universal reflector +// Copyright © 2023 Thomas A. Early N7TAE +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include +#include +#include +#include +#include + +#include "Reflector.h" +#include "LookupYsf.h" + +extern CReflector g_ref; +extern CConfigure g_cfg; + +void CLookupYsf::ClearContents() +{ + m_map.clear(); +} + +void CLookupYsf::LoadParameters() +{ + g_cfg.GetRefreshType(g_cfg.j.ysftxrxdb.mode, m_Type); + g_cfg.GetUnsigned(g_cfg.j.ysftxrxdb.refreshmin, m_Refresh); + g_cfg.GetString(g_cfg.j.ysftxrxdb.filepath, m_Path); + g_cfg.GetString(g_cfg.j.ysftxrxdb.hostname, m_Host); + g_cfg.GetString(g_cfg.j.ysftxrxdb.suffix, m_Suffix); + g_cfg.GetUnsigned(g_cfg.j.ysf.defaulttxfreq, m_DefaultTx); + g_cfg.GetUnsigned(g_cfg.j.ysf.defaultrxfreq, m_DefaultRx); +} + +bool CLookupYsf::LoadContentFile(CBuffer &buffer) +{ + buffer.clear(); + std::ifstream file; + std::streampos size; + + // open file + file.open(m_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(); + } + } + return buffer.size() > 0; +} + +bool CLookupYsf::LoadContentHttp(CBuffer &buffer) +{ + // get file from http://xlxapi.rlx.lu/api/exportysfrepeaters.php + return HttpGet(m_Host.c_str(), m_Suffix.c_str(), 80, buffer); +} + +void CLookupYsf::RefreshContentFile(const CBuffer &buffer) +{ + // 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 *callsign; + char *txfreq; + char *rxfreq; + if (((callsign = ::strtok(ptr1, ";")) != nullptr)) + { + if (((txfreq = ::strtok(nullptr, ";")) != nullptr)) + { + if (((rxfreq = ::strtok(nullptr, ";")) != nullptr)) + { + // new entry + CCallsign cs(callsign); + CYsfNode node(atoi(txfreq), atoi(rxfreq)); + if (cs.IsValid() && node.IsValid()) + { + m_map.insert(std::pair(cs, node)); + } + } + } + } + // next line + ptr1 = ptr2 + 1; + } + } + + // report + std::cout << "Read " << m_map.size() << " YSF nodes from file " << m_Path << std::endl; +} + +void CLookupYsf::RefreshContentHttp(const CBuffer &buffer) +{ + // crack it + char *ptr1 = (char *)buffer.data(); + char *ptr2; + + // get next line + while ((ptr2 = ::strchr(ptr1, '\n')) != nullptr) + { + *ptr2 = 0; + // get items + char *callsign; + char *txfreq; + char *rxfreq; + if (((callsign = ::strtok(ptr1, ";")) != nullptr)) + { + if (((txfreq = ::strtok(nullptr, ";")) != nullptr)) + { + if (((rxfreq = ::strtok(nullptr, ";")) != nullptr)) + { + // new entry + CCallsign cs(callsign); + CYsfNode node(atoi(txfreq), atoi(rxfreq)); + if (cs.IsValid() && node.IsValid()) + { + m_map.insert(std::pair(cs, node)); + } + } + } + } + // next line + ptr1 = ptr2 + 1; + } + + // report + std::cout << "Read " << m_map.size() << " YSF nodes from " << m_Host << " database " << std::endl; +} + +#define YSFNODE_HTTPGET_SIZEMAX (256) + +bool CLookupYsf::HttpGet(const char *hostname, const char *filename, int port, CBuffer &buffer) +{ + buffer.clear(); + 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[YSFNODE_HTTPGET_SIZEMAX]; + sprintf(request, "GET /%s HTTP/1.0\r\nFrom: %s\r\nUser-Agent: urfd\r\n\r\n", filename, g_ref.GetCallsign().GetCS().c_str()); + 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 + 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); + } + //} + 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 buffer.size() > 1; +} + +bool CLookupYsf::FindFrequencies(const CCallsign &callsign, uint32_t *txfreq, uint32_t *rxfreq) +{ + auto found = m_map.find(callsign); + if (found != m_map.end()) + { + *txfreq = found->second.GetTxFrequency(); + *rxfreq = found->second.GetRxFrequency(); + return true; + } + else + { + *txfreq = m_DefaultTx; + *rxfreq = m_DefaultRx; + return false; + } +} diff --git a/reflector/NXDNIdDirFile.h b/reflector/LookupYsf.h similarity index 59% rename from reflector/NXDNIdDirFile.h rename to reflector/LookupYsf.h index f4fe8c9..3501309 100644 --- a/reflector/NXDNIdDirFile.h +++ b/reflector/LookupYsf.h @@ -1,7 +1,7 @@ // Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. // urfd -- The universal reflector -// Copyright © 2021 Thomas A. Early N7TAE +// Copyright © 2023 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 @@ -18,30 +18,26 @@ #pragma once -#include "NXDNIdDir.h" +#include "YSFNode.h" +#include "Lookup.h" -class CNXDNidDirFile : public CNXDNidDir +using CsNodeMap = std::map; + +class CLookupYsf : public CLookup { public: - // constructor - CNXDNidDirFile(); - - // destructor - ~CNXDNidDirFile() {} - - // init & close - bool Init(void); - - // refresh - bool LoadContent(CBuffer *); - bool RefreshContent(const CBuffer &); + bool FindFrequencies(const CCallsign &, uint32_t *, uint32_t *); protected: - // reload helpers - bool NeedReload(void); - bool GetLastModTime(time_t *); + void ClearContents(); + void LoadParameters(); + bool LoadContentFile(CBuffer &buf); + bool LoadContentHttp(CBuffer &buf); + void RefreshContentFile(const CBuffer &); + void RefreshContentHttp(const CBuffer &); -protected: - // data - time_t m_LastModTime; +private: + CsNodeMap m_map; + + bool HttpGet(const char *, const char *, int, CBuffer &); }; diff --git a/reflector/M17Client.cpp b/reflector/M17Client.cpp index c4cb8c4..888e469 100644 --- a/reflector/M17Client.cpp +++ b/reflector/M17Client.cpp @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -#include "Main.h" + #include "M17Client.h" diff --git a/reflector/M17Protocol.cpp b/reflector/M17Protocol.cpp index df228f9..ce3b1b8 100644 --- a/reflector/M17Protocol.cpp +++ b/reflector/M17Protocol.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 "M17Client.h" #include "M17Protocol.h" @@ -69,7 +69,7 @@ void CM17Protocol::Task(void) if ( IsValidDvPacket(Buffer, Header, Frame) ) { // callsign muted? - if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::m17, Header->GetRpt2Module()) ) + if ( g_Gate.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::m17, Header->GetRpt2Module()) ) { OnDvHeaderPacketIn(Header, Ip); @@ -93,17 +93,17 @@ void CM17Protocol::Task(void) std::cout << "M17 connect packet for module " << ToLinkModule << " from " << Callsign << " at " << Ip << std::endl; // callsign authorized? - if ( g_GateKeeper.MayLink(Callsign, Ip, EProtocol::m17) && g_Reflector.IsValidModule(ToLinkModule) ) + if ( g_Gate.MayLink(Callsign, Ip, EProtocol::m17) && g_Refl..IsValidModule(ToLinkModule) ) { // valid module ? - if ( g_Reflector.IsValidModule(ToLinkModule) ) + if ( g_Refl..IsValidModule(ToLinkModule) ) { // acknowledge the request Send("ACKN", 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 { @@ -125,7 +125,7 @@ void CM17Protocol::Task(void) std::cout << "M17 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::m17); if ( client != nullptr ) { @@ -134,19 +134,19 @@ void CM17Protocol::Task(void) // and acknowledge the disconnect Send("DISC", Ip); } - g_Reflector.ReleaseClients(); + g_Refl..ReleaseClients(); } else if ( IsValidKeepAlivePacket(Buffer, Callsign) ) { // 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::m17, it)) != nullptr ) { client->Alive(); } - g_Reflector.ReleaseClients(); + g_Refl..ReleaseClients(); } else { @@ -196,24 +196,24 @@ void CM17Protocol::OnDvHeaderPacketIn(std::unique_ptr &Header, CCallsign rpt2(Header->GetRpt2Callsign()); // find this client - std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, EProtocol::m17); + std::shared_ptrclient = g_Refl..GetClients()->FindClient(Ip, EProtocol::m17); 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(); } } @@ -249,7 +249,7 @@ void CM17Protocol::HandleQueue(void) EncodeM17Packet(frame, m_StreamsCache[module].m_dvHeader, (CDvFramePacket *)packet.get(), m_StreamsCache[module].m_iSeqCounter); // 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::m17, it)) != nullptr ) @@ -266,7 +266,7 @@ void CM17Protocol::HandleQueue(void) } } - g_Reflector.ReleaseClients(); + g_Refl..ReleaseClients(); } m_StreamsCache[module].m_iSeqCounter++; } @@ -286,7 +286,7 @@ void CM17Protocol::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::m17, it)) != nullptr ) @@ -312,7 +312,7 @@ void CM17Protocol::HandleKeepalives(void) } } - g_Reflector.ReleaseClients(); + g_Refl..ReleaseClients(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -389,7 +389,7 @@ void CM17Protocol::EncodeKeepAlivePacket(CBuffer &Buffer) { Buffer.resize(10); memcpy(Buffer.data(), "PING", 4); - g_Reflector.GetCallsign().CodeOut(Buffer.data() + 4); + g_Refl..GetCallsign().CodeOut(Buffer.data() + 4); } void CM17Protocol::EncodeM17Packet(SM17Frame &frame, const CDvHeaderPacket &Header, const CDvFramePacket *DvFrame, uint32_t iSeq) const diff --git a/reflector/Main.cpp b/reflector/Main.cpp index 8a19a5d..556c2ab 100644 --- a/reflector/Main.cpp +++ b/reflector/Main.cpp @@ -16,59 +16,59 @@ // 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 +#include "Global.h" //////////////////////////////////////////////////////////////////////////////////////// // global objects -CReflector g_Reflector; +CReflector g_Refl; +CGateKeeper g_Gate; +CConfigure g_Conf; +CVersion g_Vers(3,0,0); // The major byte should only change if the interlink packet changes! +CLookupDmr g_LDid; +CLookupNxdn g_LNid; +CLookupYsf g_LYtr; //////////////////////////////////////////////////////////////////////////////////////// -// function declaration - -#include "Users.h" -int main() +int main(int argc, char *argv[]) { - const std::string cs(CALLSIGN); - if ((cs.size() != 6) || cs.compare(0, 3, "URF")) + if (argc != 2) { - std::cerr << "Malformed reflector callsign: '" << cs << "', aborting!" << std::endl; + std::cerr << "No configuration file specifed! Usage: " << argv[0] << " /pathname/to/configuration/file" << std::endl; return EXIT_FAILURE; } + if (g_Conf.ReadData(argv[1])) + return EXIT_FAILURE; + // remove pidfile - remove(PIDFILE_PATH); + const std::string pidpath(g_Conf.GetString(g_Conf.j.files.pid)); + const std::string callsign(g_Conf.GetString(g_Conf.j.names.cs)); + remove(pidpath.c_str()); // splash - std::cout << "Starting " << cs << " " << VERSION_MAJOR << "." << VERSION_MINOR << "." << VERSION_REVISION << std::endl << std::endl; - -#ifdef TRANSCODER_IS_REMOTE - g_Reflector.SetTranscoderIp(TRANSCODER_IP, INET6_ADDRSTRLEN); -#endif - + std::cout << "Starting " << callsign << " " << g_Vers << std::endl; // and let it run - if ( !g_Reflector.Start() ) + if (g_Refl.Start()) { std::cout << "Error starting reflector" << std::endl; return EXIT_FAILURE; } - std::cout << "Reflector " << g_Reflector.GetCallsign() << "started and listening" << std::endl; + std::cout << "Reflector " << callsign << "started and listening" << std::endl; // write new pid file - std::ofstream ofs(PIDFILE_PATH, std::ofstream::out); + std::ofstream ofs(pidpath, std::ofstream::out); ofs << getpid() << std::endl; ofs.close(); pause(); // wait for any signal - g_Reflector.Stop(); + g_Refl.Stop(); std::cout << "Reflector stopped" << std::endl; // done diff --git a/reflector/Main.h b/reflector/Main.h deleted file mode 100644 index 0392c5a..0000000 --- a/reflector/Main.h +++ /dev/null @@ -1,276 +0,0 @@ -// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. - -// urfd -- The universal reflector -// Copyright © 2021 Thomas A. Early N7TAE -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "configure.h" - -//////////////////////////////////////////////////////////////////////////////////////// -// defines - -//// Module configuration -#define DSTAR_IPV4 true -#define DMR_IPV4 true -#define YSF_IPV4 true -#define XLX_IPV4 true -#define M17_IPV4 true -#define P25_IPV4 true -#define NXDN_IPV4 true -#define USRP_IPV4 true -#define URF_IPV4 true - -#define DSTAR_IPV6 false -#define DMR_IPV6 false -#define YSF_IPV6 false -#define XLX_IPV6 false -#define M17_IPV6 true -#define P25_IPV6 false -#define NXDN_IPV6 false -#define USRP_IPV6 false -#define URF_IPV6 true - -// version ----------------------------------------------------- - -#define VERSION_MAJOR 0 -#define VERSION_MINOR 0 -#define VERSION_REVISION 7 - -// global ------------------------------------------------------ - -//#define JSON_MONITOR - -// debug ------------------------------------------------------- - -//#define DEBUG_NO_ERROR_ON_XML_OPEN_FAIL -//#define DEBUG_DUMPFILE - -// protocols --------------------------------------------------- - -#ifndef NO_G3 -enum class EProtocol { any, none, dextra, dplus, dcs, bm, urf, dmrplus, dmrmmdvm, ysf, m17, g3, p25, nxdn, usrp }; -#else -enum class EProtocol { any, none, dextra, dplus, dcs, bm, urf, dmrplus, dmrmmdvm, ysf, m17, p25, nxdn, usrp }; -#endif - -// DExtra -#define DEXTRA_PORT 30001 // UDP port -#define DEXTRA_KEEPALIVE_PERIOD 3 // in seconds -#define DEXTRA_KEEPALIVE_TIMEOUT (DEXTRA_KEEPALIVE_PERIOD*10) // in seconds -#define DEXTRA_RECONNECT_PERIOD 5 // in seconds - -// DPlus -#define DPLUS_PORT 20001 // UDP port -#define DPLUS_KEEPALIVE_PERIOD 1 // in seconds -#define DPLUS_KEEPALIVE_TIMEOUT (DPLUS_KEEPALIVE_PERIOD*10) // in seconds -#define DPLUS_DEFAULT_RPTR1_SUFFIX 'Y' - -// DCS -#define DCS_PORT 30051 // UDP port -#define DCS_KEEPALIVE_PERIOD 1 // in seconds -#define DCS_KEEPALIVE_TIMEOUT (DCS_KEEPALIVE_PERIOD*30) // in seconds - -// XLX, used for BM -#define XLX_PORT 10002 // UDP port -#define XLX_KEEPALIVE_PERIOD 1 // in seconds -#define XLX_KEEPALIVE_TIMEOUT (XLX_KEEPALIVE_PERIOD*30) // in seconds -#define XLX_RECONNECT_PERIOD 5 // in seconds - -// URF -#define URF_PORT 10017 // UDP port -#define URF_KEEPALIVE_PERIOD 1 // in seconds -#define URF_KEEPALIVE_TIMEOUT (URF_KEEPALIVE_PERIOD*30) // in seconds -#define URF_RECONNECT_PERIOD 5 // in seconds - -// DMRPlus (dongle) -#define DMRPLUS_PORT 8880 // UDP port -#define DMRPLUS_KEEPALIVE_PERIOD 1 // in seconds -#define DMRPLUS_KEEPALIVE_TIMEOUT (DMRPLUS_KEEPALIVE_PERIOD*10) // in seconds -#define DMRPLUS_REFLECTOR_SLOT DMR_SLOT2 -#define DMRPLUS_REFLECTOR_COLOUR 1 - -// DMRMmdvm -#define DMRMMDVM_PORT 62030 // UDP port -#define DMRMMDVM_KEEPALIVE_PERIOD 10 // in seconds -#define DMRMMDVM_KEEPALIVE_TIMEOUT (DMRMMDVM_KEEPALIVE_PERIOD*10) // in seconds -#define DMRMMDVM_REFLECTOR_SLOT DMR_SLOT2 -#define DMRMMDVM_REFLECTOR_COLOUR 1 -#define DMRMMDVM_DEFAULTID 0 - -// YSF -#define YSF_PORT 42000 // UDP port -#define YSF_KEEPALIVE_PERIOD 3 // in seconds -#define YSF_KEEPALIVE_TIMEOUT (YSF_KEEPALIVE_PERIOD*10) // in seconds -#define YSF_DEFAULT_NODE_TX_FREQ 445500000 // in Hz -#define YSF_DEFAULT_NODE_RX_FREQ 445500000 // in Hz -//#define YSF_REFLECTOR_ID 12345 // 5 digit YSF ID, assigned by registry when not defined -// the following 4 defines are now in configure.h -//#define YSF_REFLECTOR_NAME "URF000" // Max 16 characters, use reflector callsign when not defined -//#define YSF_REFLECTOR_DESCRIPTION "XLX reflector" // Max 14 characters -// #define YSF_AUTOLINK_ENABLE 0 // 1 = enable, 0 = disable auto-link -// #define YSF_AUTOLINK_MODULE 'B' // module for client to auto-link to - -// M17 -#define M17_PORT 17000 -#define M17_KEEPALIVE_PERIOD 3 -#define M17_KEEPALIVE_TIMEOUT (M17_KEEPALIVE_PERIOD*10) -#define M17_RECONNECT_PERIOD 5 - -// P25 -#define P25_REFID 12345 // Reflector ID -#define P25_PORT 41000 // UDP port -#define P25_KEEPALIVE_PERIOD 3 // in seconds -#define P25_KEEPALIVE_TIMEOUT (P25_KEEPALIVE_PERIOD*10) // in seconds -#define P25_AUTOLINK_ENABLE 1 // 1 = enable, 0 = disable auto-link -#define P25_AUTOLINK_MODULE 'A' // module for client to auto-link to - -// NXDN -#define NXDN_REFID 12345 // Reflector ID -#define NXDN_PORT 41400 // UDP port -#define NXDN_KEEPALIVE_PERIOD 3 // in seconds -#define NXDN_KEEPALIVE_TIMEOUT (NXDN_KEEPALIVE_PERIOD*10) // in seconds -#define NXDN_AUTOLINK_ENABLE 1 // 1 = enable, 0 = disable auto-link -#define NXDN_AUTOLINK_MODULE 'A' // module for client to auto-link to - -// USRP -#define USRP_PORT 34001 // UDP port -#define USRP_KEEPALIVE_PERIOD 1 // in seconds -#define USRP_KEEPALIVE_TIMEOUT (USRP_KEEPALIVE_PERIOD*10) // in seconds -#define USRP_AUTOLINK_ENABLE 1 // 1 = enable, 0 = disable auto-link -#define USRP_AUTOLINK_MODULE 'A' // module for client to auto-link to -#define USRP_DEFAULT_CALLSIGN "ALLSTAR" -#define USRPCLIENTS_PATH "/home/pi/USRPClients.txt" // format ip;port; per line for each ALLSTAR/USRP node - -#ifndef NO_G3 -// G3 Terminal -#define G3_PRESENCE_PORT 12346 // UDP port -#define G3_CONFIG_PORT 12345 // UDP port -#define G3_DV_PORT 40000 // UDP port -#define G3_KEEPALIVE_PERIOD 10 // in seconds -#define G3_KEEPALIVE_TIMEOUT 3600 // in seconds, 1 hour -#endif - -// Transcoder server -------------------------------------------- - -#ifdef TRANSCODER_IP -#define TRANSCODER_PORT 10100 // UDP port -#endif -#define TRANSCODER_KEEPALIVE_PERIOD 5 // in seconds -#define TRANSCODER_KEEPALIVE_TIMEOUT 30 // in seconds -#define TRANSCODER_AMBEPACKET_TIMEOUT 400 // in ms - -// DMRid database ----------------------------------------------- - -// these values are now set in configure.h by ./rconfig -//#define DMRIDDB_USE_RLX_SERVER 1 // 1 = use http, 0 = use local file -//#define DMRIDDB_PATH "/usr/local/etc/dmrid.dat" // local file path -//#define DMRIDDB_REFRESH_RATE 180 // in minutes - -//NXDNid database -#define NXDNIDDB_USE_RLX_SERVER 0 // 1 = use http, 0 = use local file -#define NXDNIDDB_PATH "/home/pi/NXDN.csv" // local file path -#define NXDNIDDB_REFRESH_RATE 180 // in minutes - -// Wires-X node database ---------------------------------------- - -#define YSFNODEDB_USE_RLX_SERVER 1 // 1 = use http, 0 = use local file -#define YSFNODEDB_PATH "/usr/local/etc/ysfnode.dat" // local file path -#define YSFNODEDB_REFRESH_RATE 180 // in minutes - -// xml & json reporting ----------------------------------------- - -#define LASTHEARD_USERS_MAX_SIZE 100 -#define XML_UPDATE_PERIOD 10 // in seconds -#ifdef JSON_MONITOR -#define JSON_UPDATE_PERIOD 10 // in seconds -#define JSON_PORT 10001 -#endif - -// system paths ------------------------------------------------- -#define XML_PATH "/var/log/xlxd.xml" -#define WHITELIST_PATH "/usr/local/etc/urfd.whitelist" -#define BLACKLIST_PATH "/usr/local/etc/urfd.blacklist" -#define INTERLINKLIST_PATH "/usr/local/etc/urfd.interlink" -#define TERMINALOPTIONS_PATH "/usr/local/etc/urfd.terminal" -#define PIDFILE_PATH "/var/run/xlxd.pid" - - -//////////////////////////////////////////////////////////////////////////////////////// -// macros - -#define MIN(a,b) ((a)<(b))?(a):(b) -#define MAX(a,b) ((a)>(b))?(a):(b) -#define MAKEWORD(low, high) ((uint16_t)(((uint8_t)(low)) | (((uint16_t)((uint8_t)(high))) << 8))) -#define MAKEDWORD(low, high) ((uint32_t)(((uint16_t)(low)) | (((uint32_t)((uint16_t)(high))) << 16))) -#define LOBYTE(w) ((uint8_t)(uint16_t)(w & 0x00FF)) -#define HIBYTE(w) ((uint8_t)((((uint16_t)(w)) >> 8) & 0xFF)) -#define LOWORD(dw) ((uint16_t)(uint32_t)(dw & 0x0000FFFF)) -#define HIWORD(dw) ((uint16_t)((((uint32_t)(dw)) >> 16) & 0xFFFF)) - -//////////////////////////////////////////////////////////////////////////////////////// -// global objects - -class CReflector; -extern CReflector g_Reflector; - -class CGateKeeper; -extern CGateKeeper g_GateKeeper; - -#if (DMRIDDB_USE_RLX_SERVER == 1) -class CDmridDirHttp; -extern CDmridDirHttp g_DmridDir; -#else -class CDmridDirFile; -extern CDmridDirFile g_DmridDir; -#endif - -#if (NXDNIDDB_USE_RLX_SERVER == 1) -class CNXDNidDirHttp; -extern CNXDNidDirHttp g_NXDNidDir; -#else -class CNXDNidDirFile; -extern CNXDNidDirFile g_NXDNidDir; -#endif - -#if (YSFNODEDB_USE_RLX_SERVER == 1) -class CYsfNodeDirHttp; -extern CYsfNodeDirHttp g_YsfNodeDir; -#else -class CYsfNodeDirFile; -extern CYsfNodeDirFile g_YsfNodeDir; -#endif diff --git a/reflector/NXDNClient.cpp b/reflector/NXDNClient.cpp index 64cb428..37b933e 100644 --- a/reflector/NXDNClient.cpp +++ b/reflector/NXDNClient.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 "NXDNClient.h" diff --git a/reflector/NXDNIdDir.cpp b/reflector/NXDNIdDir.cpp deleted file mode 100644 index 2d5d8d3..0000000 --- a/reflector/NXDNIdDir.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 "NXDNIdDir.h" -#include "NXDNIdDirFile.h" -#include "NXDNIdDirHttp.h" - -//////////////////////////////////////////////////////////////////////////////////////// -// constructor & destructor - -CNXDNidDir::CNXDNidDir() -{ - keep_running = true; -} - -CNXDNidDir::~CNXDNidDir() -{ - Close(); -} - - -//////////////////////////////////////////////////////////////////////////////////////// -// init & close - -bool CNXDNidDir::Init(void) -{ - // load content - Reload(); - - // reset run flag - keep_running = true; - - // start thread; - m_Future = std::async(std::launch::async, &CNXDNidDir::Thread, this); - - return true; -} - -void CNXDNidDir::Close(void) -{ - keep_running = false; - if ( m_Future.valid() ) - { - m_Future.get(); - } -} - -//////////////////////////////////////////////////////////////////////////////////////// -// thread - -void CNXDNidDir::Thread() -{ - while (keep_running) - { - // Wait DMRIDDB_REFRESH_RATE minutes - for (int i=0; i<30*NXDNIDDB_REFRESH_RATE && keep_running; i++) - std::this_thread::sleep_for(std::chrono::milliseconds(2000)); - - // have lists files changed ? - if ( NeedReload() ) - { - Reload(); - } - } -} - -//////////////////////////////////////////////////////////////////////////////////////// -// Reload - -bool CNXDNidDir::Reload(void) -{ - CBuffer buffer; - bool ok = false; - - if ( LoadContent(&buffer) ) - { - Lock(); - { - ok = RefreshContent(buffer); - } - Unlock(); - } - return ok; -} - - -//////////////////////////////////////////////////////////////////////////////////////// -// find - -const CCallsign *CNXDNidDir::FindCallsign(uint16_t nxdnid) -{ - auto found = m_CallsignMap.find(nxdnid); - if ( found != m_CallsignMap.end() ) - { - return &(found->second); - } - return nullptr; -} - -uint16_t CNXDNidDir::FindNXDNid(const CCallsign &callsign) -{ - auto found = m_NXDNidMap.find(callsign); - if ( found != m_NXDNidMap.end() ) - { - return (found->second); - } - return 0; -} - - -//////////////////////////////////////////////////////////////////////////////////////// -// syntax helpers - -bool CNXDNidDir::IsValidNXDNid(const char *sz) -{ - bool ok = false; - size_t n = ::strlen(sz); - if ( (n > 0) && (n <= 5) ) - { - ok = true; - for ( size_t i = 0; (i < n) && ok; i++ ) - { - ok &= ::isdigit(sz[i]); - } - } - return ok; -} diff --git a/reflector/NXDNIdDir.h b/reflector/NXDNIdDir.h deleted file mode 100644 index 4d9a8af..0000000 --- a/reflector/NXDNIdDir.h +++ /dev/null @@ -1,86 +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 . - -#pragma once - -#include -#include -#include -#include -#include "Buffer.h" -#include "Callsign.h" - -// compare function for std::map::find - -struct CNXDNidDirCallsignCompare -{ - bool operator() (const CCallsign &cs1, const CCallsign &cs2) const - { return cs1.HasLowerCallsign(cs2);} -}; - - -//////////////////////////////////////////////////////////////////////////////////////// - -class CNXDNidDir -{ -public: - // constructor - CNXDNidDir(); - - // destructor - ~CNXDNidDir(); - - // init & close - virtual bool Init(void); - virtual void Close(void); - - // locks - void Lock(void) { m_Mutex.lock(); } - void Unlock(void) { m_Mutex.unlock(); } - - // refresh - virtual bool LoadContent(CBuffer *) { return false; } - virtual bool RefreshContent(const CBuffer &) { return false; } - - // find - const CCallsign *FindCallsign(uint16_t); - uint16_t FindNXDNid(const CCallsign &); - -protected: - // thread - void Thread(); - - // reload helpers - bool Reload(void); - virtual bool NeedReload(void) { return false; } - bool IsValidNXDNid(const char *); - -protected: - // data - std::map m_CallsignMap; - std::map m_NXDNidMap; - - // Lock() - std::mutex m_Mutex; - - // thread - std::atomic keep_running; - std::future m_Future; - -}; diff --git a/reflector/NXDNIdDirFile.cpp b/reflector/NXDNIdDirFile.cpp deleted file mode 100644 index 73b4d95..0000000 --- a/reflector/NXDNIdDirFile.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 "NXDNIdDirFile.h" - - -#if (NXDNIDDB_USE_RLX_SERVER == 0) -CNXDNidDirFile g_NXDNidDir; -#endif - -//////////////////////////////////////////////////////////////////////////////////////// -// constructor & destructor - -CNXDNidDirFile::CNXDNidDirFile() -{ - memset(&m_LastModTime, 0, sizeof(time_t)); -} - - -//////////////////////////////////////////////////////////////////////////////////////// -// init & close - -bool CNXDNidDirFile::Init(void) -{ - return CNXDNidDir::Init(); -} - -//////////////////////////////////////////////////////////////////////////////////////// -// refresh - -bool CNXDNidDirFile::NeedReload(void) -{ - bool needReload = false; - - time_t time; - if ( GetLastModTime(&time) ) - { - needReload = time != m_LastModTime; - } - return needReload; -} - -bool CNXDNidDirFile::LoadContent(CBuffer *buffer) -{ - bool ok = false; - std::ifstream file; - std::streampos size; - - // open file - file.open(NXDNIDDB_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 CNXDNidDirFile::RefreshContent(const CBuffer &buffer) -{ - bool ok = false; - - // clear directory - m_CallsignMap.clear(); - m_NXDNidMap.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 *nxdnid; - char *callsign; - if ( ((nxdnid = ::strtok(ptr1, ",")) != nullptr) && IsValidNXDNid(nxdnid) ) - { - if ( ((callsign = ::strtok(nullptr, ",")) != nullptr) ) - { - // new entry - uint16_t us = atoi(nxdnid); - CCallsign cs(callsign, 0, us); - if ( cs.IsValid() ) - { - m_CallsignMap.insert(std::pair(us, cs)); - m_NXDNidMap.insert(std::pair(cs,us)); - } - } - } - // next line - ptr1 = ptr2+1; - } - - // done - ok = true; - } - - // report - std::cout << "Read " << m_NXDNidMap.size() << " NXDN ids from file " << NXDNIDDB_PATH << std::endl; - - // done - return ok; -} - - -bool CNXDNidDirFile::GetLastModTime(time_t *time) -{ - bool ok = false; - - struct stat fileStat; - if( ::stat(NXDNIDDB_PATH, &fileStat) != -1 ) - { - *time = fileStat.st_mtime; - ok = true; - } - return ok; -} diff --git a/reflector/NXDNIdDirHttp.cpp b/reflector/NXDNIdDirHttp.cpp deleted file mode 100644 index 94bbc22..0000000 --- a/reflector/NXDNIdDirHttp.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 -// -// 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 "NXDNIdDirHttp.h" - -#if (NXDNIDDB_USE_RLX_SERVER == 1) -CNXDNidDirHttp g_NXDNidDir; -#endif - - - - -//////////////////////////////////////////////////////////////////////////////////////// -// refresh - -bool CNXDNidDirHttp::LoadContent(CBuffer *buffer) -{ - // get file from xlxapi server - return HttpGet("www.dudetronics.com", "ar-dns/NXDN.csv", 80, buffer); -} - -bool CNXDNidDirHttp::RefreshContent(const CBuffer &buffer) -{ - bool ok = false; - - // clear directory - m_CallsignMap.clear(); - m_NXDNidMap.clear(); - - // scan file - if ( buffer.size() > 0 ) - { - char *ptr1 = (char *)buffer.data(); - char *ptr2; - // get next line - while ( (ptr2 = ::strchr(ptr1, '\n')) != nullptr ) - { - std::cout << "newline: " << std::string(ptr2) << std::endl; - *ptr2 = 0; - // get items - char *nxdnid; - char *callsign; - if ( ((nxdnid = ::strtok(ptr1, ",")) != nullptr) && IsValidNXDNid(nxdnid) ) - { - if ( ((callsign = ::strtok(nullptr, ",")) != nullptr) ) - { - // new entry - uint16_t us = atoi(nxdnid); - CCallsign cs(callsign, 0, us); - if ( cs.IsValid() ) - { - m_CallsignMap.insert(std::pair(us, cs)); - m_NXDNidMap.insert(std::pair(cs,us)); - } - } - } - // next line - ptr1 = ptr2+1; - } - // done - ok = true; - } - - // report - std::cout << "Read " << m_NXDNidMap.size() << " NXDN ids from xlxapi.rlx.lu database " << std::endl; - - // done - return ok; -} - - -//////////////////////////////////////////////////////////////////////////////////////// -// httpd helpers - -#define NXDNID_HTTPGET_SIZEMAX (256) - -bool CNXDNidDirHttp::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[NXDNID_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/NXDNProtocol.cpp b/reflector/NXDNProtocol.cpp index e26135c..8b2fcfc 100644 --- a/reflector/NXDNProtocol.cpp +++ b/reflector/NXDNProtocol.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 "NXDNClient.h" #include "NXDNProtocol.h" @@ -103,7 +103,7 @@ void CNXDNProtocol::Task(void) else if ( IsValidDvHeaderPacket(Ip, Buffer, Header) ) { // node linked and callsign muted? - if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::nxdn, Header->GetRpt2Module()) ) + if ( g_Gate.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::nxdn, Header->GetRpt2Module()) ) { // handle it OnDvHeaderPacketIn(Header, Ip); @@ -116,10 +116,10 @@ void CNXDNProtocol::Task(void) else if ( IsValidConnectPacket(Buffer, &Callsign) ) { // callsign authorized? - if ( g_GateKeeper.MayLink(Callsign, Ip, EProtocol::nxdn) ) + if ( g_Gate.MayLink(Callsign, Ip, EProtocol::nxdn) ) { // add client if needed - CClients *clients = g_Reflector.GetClients(); + CClients *clients = g_Refl..GetClients(); std::shared_ptrclient = clients->FindClient(Callsign, Ip, EProtocol::nxdn); // client already connected ? if ( client == nullptr ) @@ -141,11 +141,11 @@ void CNXDNProtocol::Task(void) { client->Alive(); } - + // acknowledge the request -- NXDNReflector simply echoes the packet Send(Buffer, Ip); // and done - g_Reflector.ReleaseClients(); + g_Refl..ReleaseClients(); } } else if ( IsValidDisconnectPacket(Buffer) ) @@ -153,14 +153,14 @@ void CNXDNProtocol::Task(void) std::cout << "NXDN 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::nxdn); if ( client != nullptr ) { // remove it clients->RemoveClient(client); } - g_Reflector.ReleaseClients(); + g_Refl..ReleaseClients(); } else { @@ -210,7 +210,7 @@ void CNXDNProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header, CCallsign rpt2(Header->GetRpt2Callsign()); // find this client - std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, EProtocol::nxdn); + std::shared_ptrclient = g_Refl..GetClients()->FindClient(Ip, EProtocol::nxdn); if ( client ) { // get client callsign @@ -221,20 +221,20 @@ void CNXDNProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header, 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 - if ( g_Reflector.IsValidModule(rpt2.GetCSModule()) ) + if ( g_Refl..IsValidModule(rpt2.GetCSModule()) ) { - g_Reflector.GetUsers()->Hearing(my, rpt1, rpt2); - g_Reflector.ReleaseUsers(); + g_Refl..GetUsers()->Hearing(my, rpt1, rpt2); + g_Refl..ReleaseUsers(); } } } @@ -292,7 +292,7 @@ void CNXDNProtocol::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::nxdn, it)) != nullptr ) @@ -305,7 +305,7 @@ void CNXDNProtocol::HandleQueue(void) } } - g_Reflector.ReleaseClients(); + g_Refl..ReleaseClients(); } } m_Queue.Unlock(); @@ -321,7 +321,7 @@ void CNXDNProtocol::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::nxdn, it)) != nullptr ) @@ -341,7 +341,7 @@ void CNXDNProtocol::HandleKeepalives(void) } } - g_Reflector.ReleaseClients(); + g_Refl..ReleaseClients(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -408,24 +408,24 @@ bool CNXDNProtocol::IsValidDvFramePacket(const CIp &Ip, const CBuffer &Buffer, s rpt1.SetCSModule(NXDN_MODULE_ID); rpt2.SetCSModule(' '); header = std::unique_ptr(new CDvHeaderPacket(csMY, CCallsign("CQCQCQ"), rpt1, rpt2, m_uiStreamId, false)); - - if ( g_GateKeeper.MayTransmit(header->GetMyCallsign(), Ip, EProtocol::nxdn, header->GetRpt2Module()) ) + + if ( g_Gate.MayTransmit(header->GetMyCallsign(), Ip, EProtocol::nxdn, header->GetRpt2Module()) ) { - OnDvHeaderPacketIn(header, Ip); + OnDvHeaderPacketIn(header, Ip); } } // get DV frames uint8_t ambe49[7]; - + uint8_t ambe0[9]; uint8_t ambe1[9]; uint8_t ambe2[9]; uint8_t ambe3[9]; - + memcpy(ambe49, Buffer.data() + 15, 7); encode(ambe49, ambe0); - + uint8_t t[7]; const uint8_t *d = &(Buffer.data()[21]); for(int i = 0; i < 6; ++i){ @@ -436,10 +436,10 @@ bool CNXDNProtocol::IsValidDvFramePacket(const CIp &Ip, const CBuffer &Buffer, s memcpy(ambe49, t, 7); encode(ambe49, ambe1); - + memcpy(ambe49, Buffer.data() + 29, 7); encode(ambe49, ambe2); - + d = &(Buffer.data()[35]); for(int i = 0; i < 6; ++i){ t[i] = d[i] << 1; @@ -480,14 +480,14 @@ bool CNXDNProtocol::EncodeNXDNHeaderPacket(const CDvHeaderPacket &Header, CBuffe Buffer.resize(43); uint16_t NXDNId = Header.GetMyCallsign().GetNXDNid(); uint16_t RptrId = NXDN_REFID; - + memcpy(Buffer.data(), "NXDND", 5); Buffer.data()[5U] = (NXDNId >> 8) & 0xFFU; Buffer.data()[6U] = (NXDNId >> 0) & 0xFFU; Buffer.data()[7U] = (RptrId >> 8) & 0xFFU; Buffer.data()[8U] = (RptrId >> 0) & 0xFFU; Buffer.data()[9U] = 0x01U; - + const uint8_t idle[3U] = {0x10, 0x00, 0x00}; m_lich = 0; memset(m_sacch, 0, 5U); @@ -514,7 +514,7 @@ bool CNXDNProtocol::EncodeNXDNHeaderPacket(const CDvHeaderPacket &Header, CBuffe set_layer3_blks(0U); memcpy(&Buffer.data()[15U], m_layer3, 14U); memcpy(&Buffer.data()[29U], m_layer3, 14U); - + if (Buffer.data()[10U] == 0x81U || Buffer.data()[10U] == 0x83U) { Buffer.data()[9U] |= Buffer.data()[15U] == 0x01U ? 0x04U : 0x00U; Buffer.data()[9U] |= Buffer.data()[15U] == 0x08U ? 0x08U : 0x00U; @@ -526,7 +526,7 @@ bool CNXDNProtocol::EncodeNXDNHeaderPacket(const CDvHeaderPacket &Header, CBuffe Buffer.data()[9U] |= Buffer.data()[12U] == 0x08U ? 0x08U : 0x00U; } } - + return true; } @@ -536,14 +536,14 @@ bool CNXDNProtocol::EncodeNXDNPacket(const CDvHeaderPacket &Header, uint32_t seq Buffer.resize(43); uint16_t NXDNId = Header.GetMyCallsign().GetNXDNid(); uint16_t RptrId = NXDN_REFID; - + memcpy(Buffer.data(), "NXDND", 5); Buffer.data()[5U] = (NXDNId >> 8) & 0xFFU; Buffer.data()[6U] = (NXDNId >> 0) & 0xFFU; Buffer.data()[7U] = (RptrId >> 8) & 0xFFU; Buffer.data()[8U] = (RptrId >> 0) & 0xFFU; Buffer.data()[9U] = 0x01U; - + uint8_t msg[3U]; m_lich = 0; memset(m_sacch, 0, 5U); @@ -590,7 +590,7 @@ bool CNXDNProtocol::EncodeNXDNPacket(const CDvHeaderPacket &Header, uint32_t seq for(int i = 0; i < 4; ++i){ decode(DvFrames[i].GetCodecData(ECodecType::dmr), ambe+(i*7)); } - + memcpy(&Buffer.data()[15], ambe, 7); for(int i = 0; i < 7; ++i){ Buffer.data()[21+i] |= (ambe[7+i] >> 1); @@ -604,7 +604,7 @@ bool CNXDNProtocol::EncodeNXDNPacket(const CDvHeaderPacket &Header, uint32_t seq Buffer.data()[36+i] = (ambe[21+i] & 1) << 7; } Buffer.data()[41] |= (ambe[27] >> 2); - + return true; } @@ -657,11 +657,11 @@ void CNXDNProtocol::decode(const unsigned char* in, unsigned char* out) const void CNXDNProtocol::encode(const unsigned char* in, unsigned char* out) const { - + unsigned int aOrig = 0U; unsigned int bOrig = 0U; unsigned int cOrig = 0U; - + unsigned int MASK = 0x000800U; for (unsigned int i = 0U; i < 12U; i++, MASK >>= 1) { unsigned int n1 = i + 0U; @@ -838,4 +838,3 @@ void CNXDNProtocol::encode_crc6(uint8_t *d, uint8_t len) WRITE_BIT(d, n, b); } } - diff --git a/reflector/Notification.cpp b/reflector/Notification.cpp index 71208e3..6808a02 100644 --- a/reflector/Notification.cpp +++ b/reflector/Notification.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 "Notification.h" CNotification::CNotification() diff --git a/reflector/P25Client.cpp b/reflector/P25Client.cpp index 18a0bcb..91c8041 100644 --- a/reflector/P25Client.cpp +++ b/reflector/P25Client.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 "P25Client.h" diff --git a/reflector/P25Protocol.cpp b/reflector/P25Protocol.cpp index 9cbe14a..e50e007 100644 --- a/reflector/P25Protocol.cpp +++ b/reflector/P25Protocol.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 "P25Client.h" #include "P25Protocol.h" @@ -93,7 +93,7 @@ void CP25Protocol::Task(void) if( !m_uiStreamId && IsValidDvHeaderPacket(Ip, Buffer, Header) ) { // callsign muted? - if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::p25) ) + if ( g_Gate.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::p25) ) { OnDvHeaderPacketIn(Header, Ip); } @@ -104,10 +104,10 @@ void CP25Protocol::Task(void) else if ( IsValidConnectPacket(Buffer, &Callsign) ) { // callsign authorized? - if ( g_GateKeeper.MayLink(Callsign, Ip, EProtocol::p25) ) + if ( g_Gate.MayLink(Callsign, Ip, EProtocol::p25) ) { // add client if needed - CClients *clients = g_Reflector.GetClients(); + CClients *clients = g_Refl..GetClients(); std::shared_ptrclient = clients->FindClient(Callsign, Ip, EProtocol::p25); // client already connected ? if ( client == nullptr ) @@ -129,11 +129,11 @@ void CP25Protocol::Task(void) { client->Alive(); } - + // acknowledge the request -- P25Reflector simply echoes the packet Send(Buffer, Ip); // and done - g_Reflector.ReleaseClients(); + g_Refl..ReleaseClients(); } } else if ( IsValidDisconnectPacket(Buffer, &Callsign) ) @@ -141,14 +141,14 @@ void CP25Protocol::Task(void) std::cout << "P25 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::p25); if ( client != nullptr ) { // remove it clients->RemoveClient(client); } - g_Reflector.ReleaseClients(); + g_Refl..ReleaseClients(); } else { @@ -197,7 +197,7 @@ void CP25Protocol::OnDvHeaderPacketIn(std::unique_ptr &Header, CCallsign rpt2(Header->GetRpt2Callsign()); // find this client - std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, EProtocol::p25); + std::shared_ptrclient = g_Refl..GetClients()->FindClient(Ip, EProtocol::p25); if ( client ) { // get client callsign @@ -206,18 +206,18 @@ void CP25Protocol::OnDvHeaderPacketIn(std::unique_ptr &Header, Header->SetRpt2Module(m); 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(); } } @@ -256,7 +256,7 @@ void CP25Protocol::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::p25, it)) != nullptr ) @@ -269,7 +269,7 @@ void CP25Protocol::HandleQueue(void) } } - g_Reflector.ReleaseClients(); + g_Refl..ReleaseClients(); } } } @@ -308,7 +308,7 @@ bool CP25Protocol::IsValidDvPacket(const CIp &Ip, const CBuffer &Buffer, std::un { int offset = 0; bool last = false; - + switch (Buffer.data()[0U]) { case 0x62U: offset = 10U; @@ -357,7 +357,7 @@ bool CP25Protocol::IsValidDvPacket(const CIp &Ip, const CBuffer &Buffer, std::un default: break; } - + frame = std::unique_ptr(new CDvFramePacket(&(Buffer.data()[offset]), m_uiStreamId, last)); return true; } @@ -388,18 +388,18 @@ void CP25Protocol::EncodeP25Packet(const CDvHeaderPacket &Header, const CDvFrame { uint32_t uiSrcId = Header.GetMyCallsign().GetDmrid(); uint32_t uiRptrId = P25_REFID; - + if(uiSrcId == 0){ uiSrcId = DMRMMDVM_DEFAULTID; } - + if(islast) { Buffer.resize(17); ::memcpy(Buffer.data(), REC80, 17U); return; } - + switch (iSeq % 18) { case 0x00U: Buffer.resize(22); @@ -506,7 +506,7 @@ void CP25Protocol::EncodeP25Packet(const CDvHeaderPacket &Header, const CDvFrame void CP25Protocol::HandleKeepalives(void) { // 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::p25, it)) != nullptr ) @@ -526,6 +526,5 @@ void CP25Protocol::HandleKeepalives(void) } } - g_Reflector.ReleaseClients(); + g_Refl..ReleaseClients(); } - diff --git a/reflector/Packet.cpp b/reflector/Packet.cpp index 9ca9b10..c77208b 100644 --- a/reflector/Packet.cpp +++ b/reflector/Packet.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 "Packet.h" // default constructor diff --git a/reflector/PacketStream.cpp b/reflector/PacketStream.cpp index bcd2ef5..7253218 100644 --- a/reflector/PacketStream.cpp +++ b/reflector/PacketStream.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 "PacketStream.h" //////////////////////////////////////////////////////////////////////////////////////// @@ -32,10 +32,15 @@ CPacketStream::CPacketStream() m_uiStreamId = 0; m_uiPacketCntr = 0; m_OwnerClient = nullptr; -#ifdef TRANSCODED_MODULES m_CodecStream = nullptr; - m_TCReader = reader; -#endif +} + +bool CPacketStream::InitPacketStream(bool is_transcoded) +{ + if (is_transcoded) + m_CodecStream = std::unique_ptr(new CCodecStream(this)); + + return nullptr == m_CodecStream; } //////////////////////////////////////////////////////////////////////////////////////// @@ -53,16 +58,6 @@ bool CPacketStream::OpenPacketStream(const CDvHeaderPacket &DvHeader, std::share m_DvHeader = DvHeader; m_OwnerClient = client; m_LastPacketTime.start(); -#ifdef TRANSCODED_MODULES - if (DvHeader.IsLocalOrigin()) // we only need transcoding if the source is local - { - auto mod = DvHeader.GetRpt2Module(); - if (std::string::npos != std::string(TRANSCODED_MODULES).find(mod)) - { - m_CodecStream = std::unique_ptr(new CCodecStream(this, m_uiStreamId, DvHeader.GetCodecIn(), m_TCReader)); - } - } -#endif return true; } @@ -75,9 +70,8 @@ void CPacketStream::ClosePacketStream(void) m_bOpen = false; m_uiStreamId = 0; m_OwnerClient.reset(); -#ifdef TRANSCODED_MODULES - m_CodecStream.reset(); -#endif + if (m_CodecStream) + m_CodecStream.reset(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -92,7 +86,6 @@ void CPacketStream::Push(std::unique_ptr Packet) Packet->UpdatePids(m_uiPacketCntr++); } // transcoder avaliable ? -#ifdef TRANSCODED_MODULES if ( m_CodecStream ) { // todo: verify no possibilty of double lock here @@ -115,7 +108,6 @@ void CPacketStream::Push(std::unique_ptr Packet) m_CodecStream->Unlock(); } else -#endif { // otherwise, push direct push push(Packet); diff --git a/reflector/PacketStream.h b/reflector/PacketStream.h index d35fad4..ac067b3 100644 --- a/reflector/PacketStream.h +++ b/reflector/PacketStream.h @@ -22,10 +22,7 @@ #include "Timer.h" #include "DVHeaderPacket.h" #include "Client.h" -#ifdef TRANSCODED_MODULES -#include "UnixDgramSocket.h" #include "CodecStream.h" -#endif //////////////////////////////////////////////////////////////////////////////////////// @@ -38,12 +35,8 @@ class CPacketStream : public CPacketQueue { public: - // constructor -#ifdef TRANSCODED_MODULES - CPacketStream(std::shared_ptr); -#else CPacketStream(); -#endif + bool InitPacketStream(bool is_transcoded); // open / close bool OpenPacketStream(const CDvHeaderPacket &, std::shared_ptr); @@ -70,8 +63,5 @@ protected: CTimer m_LastPacketTime; CDvHeaderPacket m_DvHeader; std::shared_ptr m_OwnerClient; -#ifdef TRANSCODED_MODULES - std::shared_ptr m_TCReader; std::unique_ptr m_CodecStream; -#endif }; diff --git a/reflector/Peer.cpp b/reflector/Peer.cpp index e4b7c86..9b24722 100644 --- a/reflector/Peer.cpp +++ b/reflector/Peer.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 "Reflector.h" #include "Peer.h" diff --git a/reflector/PeerCallsignList.cpp b/reflector/PeerCallsignList.cpp index 7b70951..af07d5d 100644 --- a/reflector/PeerCallsignList.cpp +++ b/reflector/PeerCallsignList.cpp @@ -17,7 +17,7 @@ // along with this program. If not, see . #include -#include "Main.h" + #include "PeerCallsignList.h" bool CPeerCallsignList::LoadFromFile(const char *filename) diff --git a/reflector/PeerCallsignList.h b/reflector/PeerCallsignList.h index 2ec8da6..8ef827e 100644 --- a/reflector/PeerCallsignList.h +++ b/reflector/PeerCallsignList.h @@ -18,7 +18,7 @@ #pragma once -#include "Main.h" + #include "CallsignList.h" //////////////////////////////////////////////////////////////////////////////////////// diff --git a/reflector/Peers.cpp b/reflector/Peers.cpp index 475602e..a371c8f 100644 --- a/reflector/Peers.cpp +++ b/reflector/Peers.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 "Peers.h" @@ -60,15 +60,15 @@ void CPeers::AddPeer(std::shared_ptr peer) std::cout << "New peer " << peer->GetCallsign() << " at " << peer->GetIp() << " added with protocol " << peer->GetProtocolName() << std::endl; // and append all peer's client to reflector client list // it is double lock safe to lock Clients list after Peers list - CClients *clients = g_Reflector.GetClients(); + CClients *clients = g_Refl..GetClients(); for ( auto cit=peer->cbegin(); cit!=peer->cend(); cit++ ) { clients->AddClient(*cit); } - g_Reflector.ReleaseClients(); + g_Refl..ReleaseClients(); // notify - g_Reflector.OnPeersChanged(); + g_Refl..OnPeersChanged(); } void CPeers::RemovePeer(std::shared_ptr peer) @@ -81,7 +81,7 @@ void CPeers::RemovePeer(std::shared_ptr peer) { // remove all clients from reflector client list // it is double lock safe to lock Clients list after Peers list - CClients *clients = g_Reflector.GetClients(); + CClients *clients = g_Refl..GetClients(); for ( auto cit=peer->begin(); cit!=peer->end(); cit++ ) { // this also delete the client object @@ -89,13 +89,13 @@ void CPeers::RemovePeer(std::shared_ptr peer) } // so clear it then (*pit)->ClearClients(); - g_Reflector.ReleaseClients(); + g_Refl..ReleaseClients(); // remove it std::cout << "Peer " << (*pit)->GetCallsign() << " at " << (*pit)->GetIp() << " removed" << std::endl; pit = m_Peers.erase(pit); // notify - g_Reflector.OnPeersChanged(); + g_Refl..OnPeersChanged(); } else { diff --git a/reflector/Protocol.cpp b/reflector/Protocol.cpp index 99b75fa..817f5b5 100644 --- a/reflector/Protocol.cpp +++ b/reflector/Protocol.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 "Protocol.h" #include "Clients.h" #include "Reflector.h" @@ -52,7 +52,7 @@ CProtocol::~CProtocol() bool CProtocol::Initialize(const char *type, const EProtocol ptype, const uint16_t port, const bool has_ipv4, const bool has_ipv6) { // init reflector apparent callsign - m_ReflectorCallsign = g_Reflector.GetCallsign(); + m_ReflectorCallsign = g_Refl..GetCallsign(); // reset stop flag keep_running = true; @@ -179,7 +179,7 @@ void CProtocol::CheckStreamsTimeout(void) { // yes, close it it->second->Unlock(); - g_Reflector.CloseStream(it->second); + g_Refl..CloseStream(it->second); // and remove it from the m_Streams map it = m_Streams.erase(it); } diff --git a/reflector/Protocols.cpp b/reflector/Protocols.cpp index c2f10c1..6dec2ff 100644 --- a/reflector/Protocols.cpp +++ b/reflector/Protocols.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 "DExtraProtocol.h" #include "DPlusProtocol.h" #include "DCSProtocol.h" @@ -80,15 +80,15 @@ bool CProtocols::Init(void) m_Protocols.emplace_back(std::unique_ptr(new CM17Protocol)); if (! m_Protocols.back()->Initialize("URF", EProtocol::m17, M17_PORT, M17_IPV4, M17_IPV6)) return false; - + m_Protocols.emplace_back(std::unique_ptr(new CP25Protocol)); if (! m_Protocols.back()->Initialize("P25", EProtocol::p25, P25_PORT, P25_IPV4, P25_IPV6)) return false; - + m_Protocols.emplace_back(std::unique_ptr(new CNXDNProtocol)); if (! m_Protocols.back()->Initialize("NXDN", EProtocol::nxdn, NXDN_PORT, NXDN_IPV4, NXDN_IPV6)) return false; - + m_Protocols.emplace_back(std::unique_ptr(new CUSRPProtocol)); if (! m_Protocols.back()->Initialize("USRP", EProtocol::usrp, USRP_PORT, USRP_IPV4, USRP_IPV6)) return false; diff --git a/reflector/RawSocket.cpp b/reflector/RawSocket.cpp index c8ee654..615786f 100644 --- a/reflector/RawSocket.cpp +++ b/reflector/RawSocket.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 "Reflector.h" #include "RawSocket.h" diff --git a/reflector/Reflector.cpp b/reflector/Reflector.cpp index fdfa792..a5605ba 100644 --- a/reflector/Reflector.cpp +++ b/reflector/Reflector.cpp @@ -16,26 +16,10 @@ // 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 "GateKeeper.h" -#include "DMRIdDirFile.h" -#include "DMRIdDirHttp.h" -#include "NXDNIdDirFile.h" -#include "NXDNIdDirHttp.h" -#include "YSFNodeDirFile.h" -#include "YSFNodeDirHttp.h" - - -//////////////////////////////////////////////////////////////////////////////////////// -// constructor - -CReflector::CReflector() : m_Callsign(CALLSIGN), m_Modules(ACTIVE_MODULES), keep_running(true) -{ -} +#include +#include "Global.h" //////////////////////////////////////////////////////////////////////////////////////// // destructor @@ -46,12 +30,7 @@ CReflector::~CReflector() { m_XmlReportFuture.get(); } -#ifdef JSON_MONITOR - if ( m_JsonReportFuture.valid() ) - { - m_JsonReportFuture.get(); - } -#endif + for (auto it=m_Modules.cbegin(); it!=m_Modules.cend(); it++) { if (m_RouterFuture[*it].valid()) @@ -59,11 +38,6 @@ CReflector::~CReflector() } m_RouterFuture.clear(); m_Stream.clear(); - -#ifdef TRANSCODED_MODULES - m_TCReader.clear(); -#endif - } @@ -72,55 +46,68 @@ CReflector::~CReflector() bool CReflector::Start(void) { + // get config stuff + m_Callsign = CCallsign(g_Conf.GetString(g_Conf.j.names.cs).c_str(), false); + m_Modules.assign(g_Conf.GetString(g_Conf.j.modules.modules)); + std::string tcmods(g_Conf.GetString(g_Conf.j.modules.tcmodules)); + // let's go! keep_running = true; // init gate keeper. It can only return true! - g_GateKeeper.Init(); + g_Gate.Init(); // init dmrid directory. No need to check the return value. - g_DmridDir.Init(); - + g_LDid.LookupInit(); + // init dmrid directory. No need to check the return value. - g_NXDNidDir.Init(); + g_LNid.LookupInit(); // init wiresx node directory. Likewise with the return vale. - g_YsfNodeDir.Init(); + g_LYtr.LookupInit(); // create protocols if (! m_Protocols.Init()) { m_Protocols.Close(); - return false; + return true; } // start one thread per reflector module - for (auto it=m_Modules.cbegin(); it!=m_Modules.cend(); it++) + for (auto c : m_Modules) { -#ifdef TRANSCODED_MODULES - m_TCReader[*it] = std::make_shared(); - std::string readername(TC2REF); - readername.append(1, *it); - if (m_TCReader[*it]->Open(readername.c_str())) + auto stream = std::make_shared(); + if (stream) + { + stream->InitPacketStream(std::string::npos != tcmods.find(c)); + } + else { - std::cerr << "ERROR: Reflector can't open " << readername << std::endl; - m_TCReader[*it].reset(); - return false; + return true; + } + try + { + m_RouterFuture[c] = std::async(std::launch::async, &CReflector::RouterThread, this, c); + } + catch(const std::exception& e) + { + std::cerr << "Cannot start module '" << c << "' thread: " << e.what() << '\n'; + keep_running = false; + return true; } - m_Stream[*it] = std::make_shared(m_TCReader[*it]); -#else - m_Stream[*it] = std::make_shared(); -#endif - m_RouterFuture[*it] = std::async(std::launch::async, &CReflector::RouterThread, this, *it); } // start the reporting threads - m_XmlReportFuture = std::async(std::launch::async, &CReflector::XmlReportThread, this); -#ifdef JSON_MONITOR - m_JsonReportFuture = std::async(std::launch::async, &CReflector::JsonReportThread, this); -#endif + try + { + m_XmlReportFuture = std::async(std::launch::async, &CReflector::XmlReportThread, this); + } + catch(const std::exception& e) + { + std::cerr << "Cannot start the dashboard data report thread: " << e.what() << '\n'; + } - return true; + return false; } void CReflector::Stop(void) @@ -133,30 +120,24 @@ void CReflector::Stop(void) { m_XmlReportFuture.get(); } -#ifdef JSON_MONITOR - if ( m_JsonReportFuture.valid() ) - { - m_JsonReportFuture.get(); - } -#endif // stop & delete all router thread - for (auto it=m_Modules.cbegin(); it!=m_Modules.cend(); it++) + for (auto c : m_Modules) { - if (m_RouterFuture[*it].valid()) - m_RouterFuture[*it].get(); + if (m_RouterFuture[c].valid()) + m_RouterFuture[c].get(); } // close protocols m_Protocols.Close(); // close gatekeeper - g_GateKeeper.Close(); + g_Gate.Close(); // close databases - g_DmridDir.Close(); - g_NXDNidDir.Close(); - g_YsfNodeDir.Close(); + g_LDid.LookupClose(); + g_LNid.LookupClose(); + g_LYtr.LookupClose(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -338,13 +319,16 @@ void CReflector::RouterThread(const char ThisModule) //////////////////////////////////////////////////////////////////////////////////////// // report threads +#define XML_UPDATE_PERIOD 10 + void CReflector::XmlReportThread() { + const std::string path(g_Conf.GetString(g_Conf.j.files.json)); while (keep_running) { // report to xml file std::ofstream xmlFile; - xmlFile.open(XML_PATH, std::ios::out | std::ios::trunc); + xmlFile.open(path, std::ios::out | std::ios::trunc); if ( xmlFile.is_open() ) { // write xml file @@ -353,12 +337,10 @@ void CReflector::XmlReportThread() // and close file xmlFile.close(); } -#ifndef DEBUG_NO_ERROR_ON_XML_OPEN_FAIL else { - std::cout << "Failed to open " << XML_PATH << std::endl; + std::cout << "Failed to open " << path << std::endl; } -#endif // and wait a bit for (int i=0; i< XML_UPDATE_PERIOD && keep_running; i++) @@ -366,100 +348,6 @@ void CReflector::XmlReportThread() } } -#ifdef JSON_MONITOR -void CReflector::JsonReportThread() -{ - CUdpSocket Socket; - CBuffer Buffer; - CIp Ip; - bool bOn; - - // init variable - bOn = false; - - // create listening socket - if ( Socket.Open(JSON_PORT) ) - { - // and loop - while (keep_running) - { - // any command ? - if ( Socket.Receive(Buffer, Ip, 50) ) - { - // check verb - if ( Buffer.Compare((uint8_t *)"hello", 5) == 0 ) - { - std::cout << "Monitor socket connected with " << Ip << std::endl; - - // connected - bOn = true; - - // announce ourselves - SendJsonReflectorObject(Socket, Ip); - - // dump tables - SendJsonNodesObject(Socket, Ip); - SendJsonStationsObject(Socket, Ip); - } - else if ( Buffer.Compare((uint8_t *)"bye", 3) == 0 ) - { - std::cout << "Monitor socket disconnected" << std::endl; - - // diconnected - bOn = false; - } - } - - // any notifications ? - CNotification notification; - m_Notifications.Lock(); - if ( !m_Notifications.empty() ) - { - // get the packet - notification = m_Notifications.front(); - m_Notifications.pop(); - } - m_Notifications.Unlock(); - - // handle it - if ( bOn ) - { - switch ( notification.GetId() ) - { - case NOTIFICATION_CLIENTS: - case NOTIFICATION_PEERS: - //std::cout << "Monitor updating nodes table" << std::endl; - SendJsonNodesObject(Socket, Ip); - break; - case NOTIFICATION_USERS: - //std::cout << "Monitor updating stations table" << std::endl; - SendJsonStationsObject(Socket, Ip); - break; - case NOTIFICATION_STREAM_OPEN: - //std::cout << "Monitor notify station " << notification.GetCallsign() << "going ON air" << std::endl; - SendJsonStationsObject(Socket, Ip); - SendJsonOnairObject(Socket, Ip, notification.GetCallsign()); - break; - case NOTIFICATION_STREAM_CLOSE: - //std::cout << "Monitor notify station " << notification.GetCallsign() << "going OFF air" << std::endl; - SendJsonOffairObject(Socket, Ip, notification.GetCallsign()); - break; - case NOTIFICATION_NONE: - default: - // nothing to do, just sleep a bit - std::this_thread::sleep_for(std::chrono::milliseconds(250); - break; - } - } - } - } - else - { - std::cout << "Error creating monitor socket" << std::endl; - } -} -#endif - //////////////////////////////////////////////////////////////////////////////////////// // notifications @@ -549,9 +437,7 @@ void CReflector::WriteXmlFile(std::ofstream &xmlFile) xmlFile << "" << std::endl; // software version - char sz[64]; - ::sprintf(sz, "%d.%d.%d", VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION); - xmlFile << "" << sz << "" << std::endl; + xmlFile << "" << g_Vers << "" << std::endl; CCallsign cs = m_Callsign; cs.PatchCallsign(0, "XLX", 3); @@ -598,120 +484,3 @@ void CReflector::WriteXmlFile(std::ofstream &xmlFile) ReleaseUsers(); xmlFile << "" << std::endl; } - - -#ifdef JSON_MONITOR -//////////////////////////////////////////////////////////////////////////////////////// -// json helpers - -void CReflector::SendJsonReflectorObject(CUdpSocket &Socket, CIp &Ip) -{ - char Buffer[1024]; - char cs[CALLSIGN_LEN+1]; - char mod[8] = "\"A\""; - - // get reflector callsign - m_Callsign.GetCallsign((uint8_t *)cs); - cs[CALLSIGN_LEN] = 0; - - // build string - ::sprintf(Buffer, "{\"reflector\":\"%s\",\"modules\":[", cs); - for ( int i = 0; i < NB_OF_MODULES; i++ ) - { - ::strcat(Buffer, mod); - mod[1]++; - if ( i < NB_OF_MODULES-1 ) - { - ::strcat(Buffer, ","); - } - } - ::strcat(Buffer, "]}"); - - // and send - Socket.Send(Buffer, Ip); -} - -#define JSON_NBMAX_NODES 250 - -void CReflector::SendJsonNodesObject(CUdpSocket &Socket, CIp &Ip) -{ - char Buffer[12+(JSON_NBMAX_NODES*94)]; - - // nodes object table - ::sprintf(Buffer, "{\"nodes\":["); - // lock - CClients *clients = GetClients(); - // iterate on clients - for ( auto it=clients->cbegin(); it!=clients->cend(); ) - { - (*it++)->GetJsonObject(Buffer); - if ( it != clients->cend() ) - { - ::strcat(Buffer, ","); - } - } - // unlock - ReleaseClients(); - ::strcat(Buffer, "]}"); - - // and send - //std::cout << Buffer << std::endl; - Socket.Send(Buffer, Ip); -} - -void CReflector::SendJsonStationsObject(CUdpSocket &Socket, CIp &Ip) -{ - char Buffer[15+(LASTHEARD_USERS_MAX_SIZE*94)]; - - // stations object table - ::sprintf(Buffer, "{\"stations\":["); - - // lock - CUsers *users = GetUsers(); - // iterate on users - for ( auto it=users->begin(); it!=users->end(); ) - { - (*it++).GetJsonObject(Buffer); - if ( it != users->end() ) - { - ::strcat(Buffer, ","); - } - } - // unlock - ReleaseUsers(); - - ::strcat(Buffer, "]}"); - - // and send - //std::cout << Buffer << std::endl; - Socket.Send(Buffer, Ip); -} - -void CReflector::SendJsonOnairObject(CUdpSocket &Socket, CIp &Ip, const CCallsign &Callsign) -{ - char Buffer[128]; - char sz[CALLSIGN_LEN+1]; - - // onair object - Callsign.GetCallsignString(sz); - ::sprintf(Buffer, "{\"onair\":\"%s\"}", sz); - - // and send - //std::cout << Buffer << std::endl; - Socket.Send(Buffer, Ip); -} - -void CReflector::SendJsonOffairObject(CUdpSocket &Socket, CIp &Ip, const CCallsign &Callsign) -{ - char Buffer[128]; - char sz[CALLSIGN_LEN+1]; - - // offair object - Callsign.GetCallsignString(sz); - ::sprintf(Buffer, "{\"offair\":\"%s\"}", sz); - - // and send - //std::cout << Buffer << std::endl; - Socket.Send(Buffer, Ip); -} -#endif diff --git a/reflector/Reflector.h b/reflector/Reflector.h index 4e7d233..30fce3c 100644 --- a/reflector/Reflector.h +++ b/reflector/Reflector.h @@ -18,6 +18,8 @@ #pragma once +#include + #include "Users.h" #include "Clients.h" #include "Peers.h" @@ -40,19 +42,8 @@ class CReflector { public: - // constructor - CReflector(); - // destructor - virtual ~CReflector(); - - // - const CCallsign &GetCallsign(void) const { return m_Callsign; } - -#ifdef TRANSCODER_IP - void SetTranscoderIp(const char *a, const int n) { memset(m_AmbedIp, 0, n); strncpy(m_AmbedIp, a, n-1); } - const char *GetTranscoderIp(void) const { return m_AmbedIp; } -#endif + ~CReflector(); // operation bool Start(void); @@ -71,7 +62,8 @@ public: bool IsStreaming(char); void CloseStream(std::shared_ptr); - // users + // get + const CCallsign &GetCallsign(void) const { return m_Callsign; } CUsers *GetUsers(void) { m_Users.Lock(); return &m_Users; } void ReleaseUsers(void) { m_Users.Unlock(); } @@ -90,9 +82,6 @@ protected: // threads void RouterThread(const char); void XmlReportThread(void); -#ifdef JSON_MONITOR - void JsonReportThread(void); -#endif // streams std::shared_ptr GetStream(char); @@ -102,22 +91,10 @@ protected: // xml helpers void WriteXmlFile(std::ofstream &); -#ifdef JSON_MONITOR - // json helpers - void SendJsonReflectorObject(CUdpSocket &, CIp &); - void SendJsonNodesObject(CUdpSocket &, CIp &); - void SendJsonStationsObject(CUdpSocket &, CIp &); - void SendJsonOnairObject(CUdpSocket &, CIp &, const CCallsign &); - void SendJsonOffairObject(CUdpSocket &, CIp &, const CCallsign &); -#endif - protected: // identity - const CCallsign m_Callsign; - const std::string m_Modules; -#ifdef TRANSCODER_IP - char m_AmbedIp[INET6_ADDRSTRLEN]; -#endif + CCallsign m_Callsign; + std::string m_Modules, m_TCmodules; // objects CUsers m_Users; // sorted list of lastheard stations @@ -127,22 +104,12 @@ protected: // queues std::unordered_map> m_Stream; -#ifdef TRANSCODED_MODULES - std::unordered_map> m_TCReader; -#endif // threads std::atomic keep_running; std::unordered_map> m_RouterFuture; std::future m_XmlReportFuture; -#ifdef JSON_MONITOR - std::future m_JsonReportFuture; -#endif + // notifications CNotificationQueue m_Notifications; - -public: -#ifdef DEBUG_DUMPFILE - std::ofstream m_DebugFile; -#endif }; diff --git a/reflector/Semaphore.cpp b/reflector/Semaphore.cpp index 00c20a6..76c4b84 100644 --- a/reflector/Semaphore.cpp +++ b/reflector/Semaphore.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 "Semaphore.h" //////////////////////////////////////////////////////////////////////////////////////// diff --git a/reflector/Semaphore.h b/reflector/Semaphore.h index d7356a4..f3e324f 100644 --- a/reflector/Semaphore.h +++ b/reflector/Semaphore.h @@ -18,7 +18,7 @@ #pragma once -#include "Main.h" + class CSemaphore { diff --git a/reflector/UDPMsgSocket.cpp b/reflector/UDPMsgSocket.cpp index b2b0f29..5571a06 100644 --- a/reflector/UDPMsgSocket.cpp +++ b/reflector/UDPMsgSocket.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 "UDPMsgSocket.h" diff --git a/reflector/UDPSocket.cpp b/reflector/UDPSocket.cpp index 9787cff..1b078b6 100644 --- a/reflector/UDPSocket.cpp +++ b/reflector/UDPSocket.cpp @@ -17,7 +17,7 @@ // along with this program. If not, see . #include -#include "Main.h" + #include "UDPSocket.h" diff --git a/reflector/URFClient.cpp b/reflector/URFClient.cpp index b9605b1..dd9feee 100644 --- a/reflector/URFClient.cpp +++ b/reflector/URFClient.cpp @@ -17,7 +17,7 @@ // along with this program. If not, see . #include -#include "Main.h" + #include "URFClient.h" diff --git a/reflector/URFPeer.cpp b/reflector/URFPeer.cpp index 34747c1..fcf5df5 100644 --- a/reflector/URFPeer.cpp +++ b/reflector/URFPeer.cpp @@ -18,7 +18,7 @@ #include -#include "Main.h" + #include "Reflector.h" #include "URFPeer.h" #include "URFClient.h" diff --git a/reflector/URFProtocol.cpp b/reflector/URFProtocol.cpp index 0c5dfa7..f3fda2e 100644 --- a/reflector/URFProtocol.cpp +++ b/reflector/URFProtocol.cpp @@ -17,7 +17,7 @@ // along with this program. If not, see . #include -#include "Main.h" + #include "URFPeer.h" #include "URFProtocol.h" #include "Reflector.h" @@ -73,19 +73,19 @@ void CURFProtocol::Task(void) else if ( IsValidKeepAlivePacket(Buffer, &Callsign) ) { // find peer - CPeers *peers = g_Reflector.GetPeers(); + CPeers *peers = g_Refl..GetPeers(); std::shared_ptrpeer = peers->FindPeer(Ip, EProtocol::urf); if ( peer != nullptr ) { // keep it alive peer->Alive(); } - g_Reflector.ReleasePeers(); + g_Refl..ReleasePeers(); } else if ( IsValidDvHeaderPacket(Buffer, Header) ) { // callsign allowed? - if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip) ) + if ( g_Gate.MayTransmit(Header->GetMyCallsign(), Ip) ) { OnDvHeaderPacketIn(Header, Ip); } @@ -95,7 +95,7 @@ void CURFProtocol::Task(void) std::cout << "URF (" << 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::urf, Modules) ) + if ( g_Gate.MayLink(Callsign, Ip, EProtocol::urf, Modules) ) { // acknowledge connecting request // following is version dependent @@ -123,10 +123,10 @@ void CURFProtocol::Task(void) std::cout << "URF ack packet for modules " << Modules << " from " << Callsign << " at " << Ip << std::endl; // callsign authorized? - if ( g_GateKeeper.MayLink(Callsign, Ip, EProtocol::urf, Modules) ) + if ( g_Gate.MayLink(Callsign, Ip, EProtocol::urf, Modules) ) { // already connected ? - CPeers *peers = g_Reflector.GetPeers(); + CPeers *peers = g_Refl..GetPeers(); if ( peers->FindPeer(Callsign, Ip, EProtocol::urf) == nullptr ) { // create the new peer @@ -137,7 +137,7 @@ void CURFProtocol::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) ) @@ -145,7 +145,7 @@ void CURFProtocol::Task(void) std::cout << "URF 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::urf); if ( peer != nullptr ) { @@ -154,7 +154,7 @@ void CURFProtocol::Task(void) // and delete them peers->RemovePeer(peer); } - g_Reflector.ReleasePeers(); + g_Refl..ReleasePeers(); } else if ( IsValidNackPacket(Buffer, &Callsign) ) { @@ -216,7 +216,7 @@ void CURFProtocol::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::urf, it)) != nullptr ) @@ -232,7 +232,7 @@ void CURFProtocol::HandleQueue(void) } } } - g_Reflector.ReleaseClients(); + g_Refl..ReleaseClients(); } } } @@ -251,7 +251,7 @@ void CURFProtocol::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::urf, pit)) != nullptr ) @@ -278,7 +278,7 @@ void CURFProtocol::HandleKeepalives(void) peers->RemovePeer(peer); } } - g_Reflector.ReleasePeers(); + g_Refl..ReleasePeers(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -289,8 +289,8 @@ void CURFProtocol::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 CURFProtocol::HandlePeerLinks(void) } // done - g_Reflector.ReleasePeers(); - g_GateKeeper.ReleasePeerList(); + g_Refl..ReleasePeers(); + g_Gate.ReleasePeerList(); } @@ -363,11 +363,11 @@ void CURFProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header, CCallsign rpt2(Header->GetRpt2Callsign()); // no stream open yet, open a new one // find this client - std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, EProtocol::urf, Header->GetRpt2Module()); + std::shared_ptrclient = g_Refl..GetClients()->FindClient(Ip, EProtocol::urf, 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; @@ -376,10 +376,10 @@ void CURFProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header, 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(); } } @@ -521,7 +521,7 @@ void CURFProtocol::EncodeKeepAlivePacket(CBuffer *Buffer) { Buffer->Set("PING"); Buffer->resize(10); - g_Reflector.GetCallsign().CodeOut(Buffer->data()+4); + g_Refl..GetCallsign().CodeOut(Buffer->data()+4); } void CURFProtocol::EncodeConnectPacket(CBuffer *Buffer, const char *Modules) @@ -530,7 +530,7 @@ void CURFProtocol::EncodeConnectPacket(CBuffer *Buffer, const char *Modules) Buffer->Set("CONN"); // our callsign Buffer->resize(37); - g_Reflector.GetCallsign().CodeOut(Buffer->data()+4); + g_Refl..GetCallsign().CodeOut(Buffer->data()+4); // our version Buffer->ReplaceAt(10, (uint8_t *)Modules, strlen(Modules)); Buffer->Append((uint8_t)VERSION_MAJOR); @@ -543,7 +543,7 @@ void CURFProtocol::EncodeDisconnectPacket(CBuffer *Buffer) Buffer->Set("DISC"); // our callsign Buffer->resize(10); - g_Reflector.GetCallsign().CodeOut(Buffer->data()+4); + g_Refl..GetCallsign().CodeOut(Buffer->data()+4); } void CURFProtocol::EncodeConnectAckPacket(CBuffer *Buffer, const char *Modules) @@ -551,7 +551,7 @@ void CURFProtocol::EncodeConnectAckPacket(CBuffer *Buffer, const char *Modules) Buffer->Set("ACKN"); // our callsign Buffer->resize(37); - g_Reflector.GetCallsign().CodeOut(Buffer->data()+4); + g_Refl..GetCallsign().CodeOut(Buffer->data()+4); // the shared modules Buffer->ReplaceAt(10, (uint8_t *)Modules, strlen(Modules)); // our version @@ -564,5 +564,5 @@ void CURFProtocol::EncodeConnectNackPacket(CBuffer *Buffer) { Buffer->Set("NACK"); Buffer->resize(10); - g_Reflector.GetCallsign().CodeOut(Buffer->data()+4); + g_Refl..GetCallsign().CodeOut(Buffer->data()+4); } diff --git a/reflector/USRPClient.cpp b/reflector/USRPClient.cpp index f75c866..a94619f 100644 --- a/reflector/USRPClient.cpp +++ b/reflector/USRPClient.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 "USRPClient.h" diff --git a/reflector/USRPProtocol.cpp b/reflector/USRPProtocol.cpp index 75ebdbf..076d7ff 100644 --- a/reflector/USRPProtocol.cpp +++ b/reflector/USRPProtocol.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 "USRPClient.h" #include "USRPProtocol.h" @@ -41,14 +41,14 @@ bool CUSRPProtocol::Initialize(const char *type, const EProtocol ptype, const ui CBuffer buffer; m_uiStreamId = 0; CCallsign cs(USRP_DEFAULT_CALLSIGN); - CClients *clients = g_Reflector.GetClients(); + CClients *clients = g_Refl..GetClients(); std::ifstream file; std::streampos size; - + // base class if (! CProtocol::Initialize(type, ptype, port, has_ipv4, has_ipv6)) return false; - + file.open(USRPCLIENTS_PATH, std::ios::in | std::ios::binary | std::ios::ate); if ( file.is_open() ) { @@ -93,7 +93,7 @@ bool CUSRPProtocol::Initialize(const char *type, const EProtocol ptype, const ui } } - g_Reflector.ReleaseClients(); + g_Refl..ReleaseClients(); // update time m_LastKeepaliveTime.start(); @@ -135,7 +135,7 @@ void CUSRPProtocol::Task(void) else if( IsValidDvHeaderPacket(Ip, Buffer, Header) ) { // callsign muted? - if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::usrp) ) + if ( g_Gate.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::usrp) ) { OnDvHeaderPacketIn(Header, Ip); } @@ -192,7 +192,7 @@ void CUSRPProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header, CCallsign rpt2(Header->GetRpt2Callsign()); // find this client - std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, EProtocol::usrp); + std::shared_ptrclient = g_Refl..GetClients()->FindClient(Ip, EProtocol::usrp); if ( client ) { // get client callsign @@ -201,18 +201,18 @@ void CUSRPProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header, Header->SetRpt2Module(m); 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(); } } @@ -249,7 +249,7 @@ void CUSRPProtocol::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::usrp, it)) != nullptr ) @@ -261,7 +261,7 @@ void CUSRPProtocol::HandleQueue(void) Send(buffer, client->GetIp()); } } - g_Reflector.ReleaseClients(); + g_Refl..ReleaseClients(); } } m_Queue.Unlock(); @@ -285,14 +285,14 @@ bool CUSRPProtocol::IsValidDvPacket(const CIp &Ip, const CBuffer &Buffer, std::u rpt1.SetCSModule(USRP_MODULE_ID); rpt2.SetCSModule(' '); header = std::unique_ptr(new CDvHeaderPacket(csMY, CCallsign("CQCQCQ"), rpt1, rpt2, m_uiStreamId, true)); - OnDvHeaderPacketIn(header, Ip); + OnDvHeaderPacketIn(header, Ip); } int16_t pcm[160]; for(int i = 0; i < 160; ++i){ pcm[i] = (Buffer.data()[32+(i*2)+1] << 8) | Buffer.data()[32+(i*2)]; } - + frame = std::unique_ptr(new CDvFramePacket(pcm, m_uiStreamId, false)); return true; } @@ -354,7 +354,7 @@ void CUSRPProtocol::EncodeUSRPPacket(const CDvHeaderPacket &Header, const CDvFra memcpy(Buffer.data(), "USRP", 4); memcpy(Buffer.data() + 4, &cnt, 4); Buffer.data()[15] = USRP_KEYUP_FALSE; - + } else { @@ -375,7 +375,7 @@ void CUSRPProtocol::EncodeUSRPPacket(const CDvHeaderPacket &Header, const CDvFra void CUSRPProtocol::HandleKeepalives(void) { // 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::usrp, it)) != nullptr ) @@ -395,6 +395,5 @@ void CUSRPProtocol::HandleKeepalives(void) //} } - g_Reflector.ReleaseClients(); + g_Refl..ReleaseClients(); } - diff --git a/reflector/User.cpp b/reflector/User.cpp index 105cd94..c42729e 100644 --- a/reflector/User.cpp +++ b/reflector/User.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 "User.h" diff --git a/reflector/User.h b/reflector/User.h index c9869fa..c7e6897 100644 --- a/reflector/User.h +++ b/reflector/User.h @@ -33,7 +33,7 @@ public: ~CUser() {} // operation - void HeardNow(void) { m_LastHeardTime = std::time(nullptr); } + void HeardNow(void) { m_LastHeardTime = time(nullptr); } // operators bool operator ==(const CUser &) const; @@ -49,5 +49,5 @@ protected: CCallsign m_Rpt1; CCallsign m_Rpt2; CCallsign m_Xlx; - std::time_t m_LastHeardTime; + time_t m_LastHeardTime; }; diff --git a/reflector/Users.cpp b/reflector/Users.cpp index 1406e18..beb2106 100644 --- a/reflector/Users.cpp +++ b/reflector/Users.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 "Users.h" #include "Reflector.h" @@ -40,7 +40,7 @@ void CUsers::AddUser(const CUser &user) } // notify - g_Reflector.OnUsersChanged(); + g_Refl..OnUsersChanged(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -48,7 +48,7 @@ void CUsers::AddUser(const CUser &user) void CUsers::Hearing(const CCallsign &my, const CCallsign &rpt1, const CCallsign &rpt2) { - Hearing(my, rpt1, rpt2, g_Reflector.GetCallsign()); + Hearing(my, rpt1, rpt2, g_Refl..GetCallsign()); } void CUsers::Hearing(const CCallsign &my, const CCallsign &rpt1, const CCallsign &rpt2, const CCallsign &xlx) diff --git a/reflector/Users.h b/reflector/Users.h index 6216269..f4e3343 100644 --- a/reflector/Users.h +++ b/reflector/Users.h @@ -18,6 +18,9 @@ #pragma once +#include +#include + #include "User.h" class CUsers diff --git a/reflector/Version.cpp b/reflector/Version.cpp index 96d296d..35d3c9d 100644 --- a/reflector/Version.cpp +++ b/reflector/Version.cpp @@ -1,73 +1,89 @@ -// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. - -// urfd -- The universal reflector -// Copyright © 2021 Thomas A. Early N7TAE +// Copyright © 2023 Thomas A. Early N7TAE. +// +// ---------------------------------------------------------------------------- +// This file is part of m17ref. // -// 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. +// m17ref is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. // -// 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. +// m17ref is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. // -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . +// You should have received a copy of the GNU General Public License +// with this software. If not, see . +// ---------------------------------------------------------------------------- -#include "Main.h" #include "Version.h" -//////////////////////////////////////////////////////////////////////////////////////// -// constructor +CVersion::CVersion() : version(0) {} + +CVersion::CVersion(uint8_t maj, uint8_t min, uint8_t rev) +{ + Set(maj, min, rev); +} + +int CVersion::GetMajor(void) const +{ + return version / 0x10000; +} + +int CVersion::GetMinor(void) const +{ + return version / 0x100 % 0x100; +} + +int CVersion::GetRevision(void) const +{ + return version % 0x100; +} -CVersion::CVersion() +int CVersion::GetVersion(void) const { - m_iMajor = 0; - m_iMinor = 0; - m_iRevision = 0; + return version; } -CVersion::CVersion(int iMajor, int iMinor, int iRevision) +void CVersion::Set(uint8_t maj, uint8_t min, uint8_t rev) { - m_iMajor = iMajor; - m_iMinor = iMinor; - m_iRevision = iRevision; + version = 0x10000*maj + 0x100*min + rev; } -//////////////////////////////////////////////////////////////////////////////////////// -// comparaison +bool CVersion::operator ==(const CVersion &v) const +{ + return v.version == version; +}; + +bool CVersion::operator !=(const CVersion &v) const +{ + return v.version != version; +}; + +bool CVersion::operator >=(const CVersion &v) const +{ + return v.version >= version; +} -bool CVersion::IsEqualOrHigherTo(const CVersion &version) const +bool CVersion::operator <=(const CVersion &v) const { - if ( m_iMajor > version.m_iMajor ) - { - return true; - } - else if ( m_iMajor == version.m_iMajor ) - { - if ( m_iMinor > version.m_iMinor ) - { - return true; - } - else if ( m_iMinor == version.m_iMinor ) - { - if ( m_iRevision >= version.m_iRevision ) - { - return true; - } - } - } - return false; + return v.version <= version; } -//////////////////////////////////////////////////////////////////////////////////////// -// operator +bool CVersion::operator >(const CVersion &v) const +{ + return v.version > version; +} -bool CVersion::operator ==(const CVersion &Version) const +bool CVersion::operator <(const CVersion &v) const { - return ( (Version.m_iMajor == m_iMajor) && - (Version.m_iMinor == m_iMinor) && - (Version.m_iRevision == m_iRevision )) ; + return v.version < version; } + +// output +std::ostream &operator <<(std::ostream &os, const CVersion &v) +{ + os << v.GetMajor() << '.' << v.GetMinor() << '.' << v.GetRevision(); + return os; +}; diff --git a/reflector/Version.h b/reflector/Version.h index 256bfd8..84aa8d4 100644 --- a/reflector/Version.h +++ b/reflector/Version.h @@ -1,44 +1,56 @@ -// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. - -// urfd -- The universal reflector -// Copyright © 2021 Thomas A. Early N7TAE +// Copyright © 2023 Thomas A. Early N7TAE. +// +// ---------------------------------------------------------------------------- +// This file is part of m17ref. // -// 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. +// m17ref is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. // -// 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. +// m17ref is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. // -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . +// You should have received a copy of the GNU General Public License +// with this software. If not, see . +// ---------------------------------------------------------------------------- #pragma once +#include +#include + class CVersion { public: - // constructor + // constructors CVersion(); - CVersion(int, int, int); + CVersion(uint8_t maj, uint8_t min, uint8_t rev); // get - int GetMajor(void) const { return m_iMajor; } - int GetMinor(void) const { return m_iMinor; } - int GetRevision(void) const { return m_iRevision; } + int GetMajor(void) const; + int GetMinor(void) const; + int GetRevision(void) const; + int GetVersion(void) const; + + // set + void Set(uint8_t, uint8_t, uint8_t); + + // comparaison operators + bool operator ==(const CVersion &v) const; + bool operator !=(const CVersion &v) const; + bool operator >=(const CVersion &v) const; + bool operator <=(const CVersion &v) const; + bool operator >(const CVersion &v) const; + bool operator <(const CVersion &v) const; - // comparaison - bool IsEqualOrHigherTo(const CVersion &) const; + // output + friend std::ostream &operator <<(std::ostream &os, const CVersion &v); - // operator - bool operator ==(const CVersion &) const; protected: // data - int m_iMajor; - int m_iMinor; - int m_iRevision; + int version; }; diff --git a/reflector/WiresXCmd.cpp b/reflector/WiresXCmd.cpp index 225538f..d94616f 100644 --- a/reflector/WiresXCmd.cpp +++ b/reflector/WiresXCmd.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 "WiresXCmd.h" diff --git a/reflector/WiresXCmdHandler.cpp b/reflector/WiresXCmdHandler.cpp index ab1360e..e90b0a3 100644 --- a/reflector/WiresXCmdHandler.cpp +++ b/reflector/WiresXCmdHandler.cpp @@ -17,7 +17,7 @@ // along with this program. If not, see . #include -#include "Main.h" + #include "CRC.h" #include "YSFFich.h" #include "YSFPayload.h" @@ -61,8 +61,8 @@ CWiresxCmdHandler::~CWiresxCmdHandler() bool CWiresxCmdHandler::Init(void) { // fill our wiresx info - m_ReflectorWiresxInfo.SetCallsign(g_Reflector.GetCallsign()); - m_ReflectorWiresxInfo.SetNode(g_Reflector.GetCallsign()); + m_ReflectorWiresxInfo.SetCallsign(g_Refl..GetCallsign()); + m_ReflectorWiresxInfo.SetNode(g_Refl..GetCallsign()); m_ReflectorWiresxInfo.SetName("Reflector"); // reset stop flag @@ -144,18 +144,18 @@ void CWiresxCmdHandler::Task(void) const char *modules = ACTIVE_MODULES; // fill our info object Info = m_ReflectorWiresxInfo; - g_YsfNodeDir.FindFrequencies(Cmd.GetCallsign(), &uiNodeTxFreq, &uiNodeRxFreq); + g_LYtr.FindFrequencies(Cmd.GetCallsign(), &uiNodeTxFreq, &uiNodeRxFreq); Info.SetFrequencies(uiNodeTxFreq, uiNodeRxFreq); // find our client and the module it's currentlink linked to cModule = ' '; - CClients *clients = g_Reflector.GetClients(); + CClients *clients = g_Refl..GetClients(); std::shared_ptrclient = clients->FindClient(Cmd.GetCallsign(), Cmd.GetIp(), EProtocol::ysf); if ( client ) { cModule = client->GetReflectorModule(); } - g_Reflector.ReleaseClients(); + g_Refl..ReleaseClients(); // and crack the cmd switch ( Cmd.GetCmd() ) @@ -179,13 +179,13 @@ void CWiresxCmdHandler::Task(void) // acknowledge ReplyToWiresxConnReqPacket(Cmd.GetIp(), Info, cModule); // change client's module - CClients *clients = g_Reflector.GetClients(); + CClients *clients = g_Refl..GetClients(); std::shared_ptrclient = clients->FindClient(Cmd.GetCallsign(), Cmd.GetIp(), EProtocol::ysf); if ( client ) { client->SetReflectorModule(cModule); } - g_Reflector.ReleaseClients(); + g_Refl..ReleaseClients(); } else { @@ -198,13 +198,13 @@ void CWiresxCmdHandler::Task(void) ReplyToWiresxDiscReqPacket(Cmd.GetIp(), Info); // change client's module { - CClients *clients = g_Reflector.GetClients(); + CClients *clients = g_Refl..GetClients(); std::shared_ptrclient = clients->FindClient(Cmd.GetCallsign(), Cmd.GetIp(), EProtocol::ysf); if ( client != nullptr ) { client->SetReflectorModule(' '); } - g_Reflector.ReleaseClients(); + g_Refl..ReleaseClients(); } break; case WIRESX_CMD_UNKNOWN: @@ -741,8 +741,8 @@ bool CWiresxCmdHandler::DebugTestDecodePacket(const CBuffer &Buffer) std::cout << "Trailer" << std::endl; std::cout << "length of payload : " << len << std::endl; dump.Set(command, len); - dump.DebugDump(g_Reflector.m_DebugFile); - dump.DebugDumpAscii(g_Reflector.m_DebugFile); + dump.DebugDump(g_Refl..m_DebugFile); + dump.DebugDumpAscii(g_Refl..m_DebugFile); break; case YSF_FI_COMMUNICATIONS: if ( Fich.getDT() == YSF_DT_DATA_FR_MODE ) diff --git a/reflector/WiresXInfo.cpp b/reflector/WiresXInfo.cpp index 3da1fb6..6fd11c9 100644 --- a/reflector/WiresXInfo.cpp +++ b/reflector/WiresXInfo.cpp @@ -17,7 +17,7 @@ // along with this program. If not, see . #include -#include "Main.h" + #include "Callsign.h" #include "WiresXInfo.h" diff --git a/reflector/YSFClient.cpp b/reflector/YSFClient.cpp index 58c3b47..7f6fc60 100644 --- a/reflector/YSFClient.cpp +++ b/reflector/YSFClient.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 "YSFClient.h" diff --git a/reflector/YSFNode.cpp b/reflector/YSFNode.cpp index 2b4d626..badd37b 100644 --- a/reflector/YSFNode.cpp +++ b/reflector/YSFNode.cpp @@ -17,7 +17,7 @@ // along with this program. If not, see . #include -#include "Main.h" + #include "YSFNode.h" diff --git a/reflector/YSFNode.h b/reflector/YSFNode.h index dd5ca81..ba4889d 100644 --- a/reflector/YSFNode.h +++ b/reflector/YSFNode.h @@ -18,7 +18,7 @@ #pragma once -#include "Main.h" + class CYsfNode { diff --git a/reflector/YSFNodeDir.cpp b/reflector/YSFNodeDir.cpp deleted file mode 100644 index 7f11b34..0000000 --- a/reflector/YSFNodeDir.cpp +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright © 2019 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 "Main.h" -#include "Reflector.h" -#include "YSFNodeDir.h" - - -//////////////////////////////////////////////////////////////////////////////////////// -// constructor & destructor - -CYsfNodeDir::CYsfNodeDir() -{ - keep_running = true; -} - -CYsfNodeDir::~CYsfNodeDir() -{ - // kill threads - Close(); -} - - -//////////////////////////////////////////////////////////////////////////////////////// -// init & close - -bool CYsfNodeDir::Init(void) -{ - // load content - Reload(); - - // reset run flag - keep_running = true; - - // start thread; - m_Future = std::async(std::launch::async, &CYsfNodeDir::Thread, this); - - return true; -} - -void CYsfNodeDir::Close(void) -{ - keep_running = false; - if ( m_Future.valid() ) - { - m_Future.get(); - } -} - -//////////////////////////////////////////////////////////////////////////////////////// -// thread - -void CYsfNodeDir::Thread() -{ - while (keep_running) - { - // Wait YSFNODEDB_REFRESH_RATE minutes - for (int i=0; keep_running && (i < 30*YSFNODEDB_REFRESH_RATE); i++) - { - std::this_thread::sleep_for(std::chrono::milliseconds(2000)); -#if YSF_DB_SUPPORT==true - if (keep_running && (0 == i % 450)) - { - ReadDb(); // update from the db every 15 minutes - } -#endif - } - // have lists files changed ? - if (keep_running && NeedReload()) - { - Reload(); - } - } -} - -//////////////////////////////////////////////////////////////////////////////////////// -// Reload - -bool CYsfNodeDir::Reload(void) -{ - CBuffer buffer; - bool ok = false; - - if ( LoadContent(&buffer) ) - { - Lock(); - ok = RefreshContent(buffer); - Unlock(); - } - return ok; -} - -//////////////////////////////////////////////////////////////////////////////////////// -// find - -bool CYsfNodeDir::FindFrequencies(const CCallsign &callsign, uint32_t *txfreq, uint32_t *rxfreq) -{ - auto found = find(callsign); - if ( found != end() ) - { - *txfreq = found->second.GetTxFrequency(); - *rxfreq = found->second.GetRxFrequency(); - return true; - } - else - { - *txfreq = YSF_DEFAULT_NODE_TX_FREQ; - *rxfreq = YSF_DEFAULT_NODE_RX_FREQ; - return false; - } -} - -#if YSF_DB_SUPPORT==true -void CYsfNodeDir::ReadDb() -{ - MYSQL *con = mysql_init(NULL); - if (con) - { - if (mysql_real_connect(con, "localhost", YSF_DB_USER, YSF_DB_PASSWORD, YSF_DB_NAME, 0, NULL, 0)) - { - if (0 == mysql_query(con, "SELECT callsign,txfreq,rxfreq FROM ysfnodes")) - { - MYSQL_RES *result = mysql_store_result(con); - if (result) - { - std::cout << "Adding " << mysql_num_rows(result) << " registered YSF stations from database " << YSF_DB_NAME << std::endl; - MYSQL_ROW row; - - while ((row = mysql_fetch_row(result))) - { - CCallsign cs(row[0]); - CYsfNode node(atoi(row[1]), atoi(row[2])); - m_map[cs] = node; - } - - mysql_free_result(result); - } - else - { - std::cerr << "Could not fetch MySQL rows" << std::endl; - } - } - else - { - std::cerr << "MySQL query failed: " << mysql_error(con) << std::endl; - } - } - else - { - std::cerr << "Could not connect to database " << YSF_DB_NAME << ": " << mysql_error(con) << std::endl; - } - mysql_close(con); - } - else - { - std::cerr << "Could not init mysql." << std::endl;; - } -} -#endif diff --git a/reflector/YSFNodeDir.h b/reflector/YSFNodeDir.h deleted file mode 100644 index 26b5911..0000000 --- a/reflector/YSFNodeDir.h +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright © 2019 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 "Buffer.h" -#include "Callsign.h" -#include "YSFNode.h" - -//////////////////////////////////////////////////////////////////////////////////////// -// compare function for std::map::find - -struct CYsfNodeDirCallsignCompare -{ - bool operator() (const CCallsign &cs1, const CCallsign &cs2) const - { return cs1.HasLowerCallsign(cs2);} -}; - -//////////////////////////////////////////////////////////////////////////////////////// -// class - -using CsNodeMap = std::map; - -class CYsfNodeDir -{ -public: - // constructor - CYsfNodeDir(); - // destructor - virtual ~CYsfNodeDir(); - - // init & close - virtual bool Init(void); - virtual void Close(void); - - // locks - void Lock(void) { m_Mutex.lock(); } - void Unlock(void) { m_Mutex.unlock(); } - - // refresh - virtual bool LoadContent(CBuffer *) { return false; } - virtual bool RefreshContent(const CBuffer &) { return false; } - - // find - bool FindFrequencies(const CCallsign &, uint32_t *, uint32_t *); - - // pass-thru - void clear() { m_map.clear(); } - size_t size() { return m_map.size(); } - CsNodeMap::iterator find(const CCallsign &cs) { return m_map.find(cs); } - CsNodeMap::iterator end() { return m_map.end(); } - std::pair insert(const std::pair &pair) { return m_map.insert(pair); } - -protected: - // thread - void Thread(); - - // reload helpers - bool Reload(void); - virtual bool NeedReload(void) { return false; } -#if YSF_DB_SUPPORT==true - void ReadDb(void); -#endif - //bool IsValidDmrid(const char *); - - -protected: - // Lock() - std::mutex m_Mutex; - - // thread - std::atomic keep_running; - std::future m_Future; - CsNodeMap m_map; -}; diff --git a/reflector/YSFNodeDirFile.cpp b/reflector/YSFNodeDirFile.cpp deleted file mode 100644 index 5879c5e..0000000 --- a/reflector/YSFNodeDirFile.cpp +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright © 2019 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 "YSFNodeDirFile.h" - - -#if (YSFNODEDB_USE_RLX_SERVER == 0) -CYsfNodeDirFile g_YsfNodeDir; -#endif - -//////////////////////////////////////////////////////////////////////////////////////// -// constructor & destructor - -CYsfNodeDirFile::CYsfNodeDirFile() -{ - memset(&m_LastModTime, 0, sizeof(time_t)); -} - -//////////////////////////////////////////////////////////////////////////////////////// -// init & close - -bool CYsfNodeDirFile::Init(void) -{ - return CYsfNodeDir::Init(); -} - -//////////////////////////////////////////////////////////////////////////////////////// -// refresh - -bool CYsfNodeDirFile::NeedReload(void) -{ - bool needReload = false; - - time_t time; - if ( GetLastModTime(&time) ) - { - needReload = time != m_LastModTime; - } - return needReload; -} - -bool CYsfNodeDirFile::LoadContent(CBuffer *buffer) -{ - bool ok = false; - std::ifstream file; - std::streampos size; - - // open file - file.open(YSFNODEDB_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 CYsfNodeDirFile::RefreshContent(const CBuffer &buffer) -{ - bool ok = false; - - // clear directory - 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 *callsign; - char *txfreq; - char *rxfreq; - if ( ((callsign = ::strtok(ptr1, ";")) != nullptr) ) - { - if ( ((txfreq = ::strtok(nullptr, ";")) != nullptr) ) - { - if ( ((rxfreq = ::strtok(nullptr, ";")) != nullptr) ) - { - // new entry - CCallsign cs(callsign); - CYsfNode node(atoi(txfreq), atoi(rxfreq)); - if ( cs.IsValid() && node.IsValid() ) - { - insert(std::pair(cs, node)); - } - } - } - } - // next line - ptr1 = ptr2+1; - } - - // done - ok = true; - } - - - // report - std::cout << "Read " << size() << " YSF nodes from file " << YSFNODEDB_PATH << std::endl; - - // done - return ok; -} - - -bool CYsfNodeDirFile::GetLastModTime(time_t *time) -{ - bool ok = false; - - struct stat fileStat; - if( ::stat(YSFNODEDB_PATH, &fileStat) != -1 ) - { - *time = fileStat.st_mtime; - ok = true; - } - return ok; -} diff --git a/reflector/YSFNodeDirFile.h b/reflector/YSFNodeDirFile.h deleted file mode 100644 index 8b15993..0000000 --- a/reflector/YSFNodeDirFile.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright © 2019 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 "YSFNodeDir.h" - -class CYsfNodeDirFile : public CYsfNodeDir -{ -public: - // constructor - CYsfNodeDirFile(); - - // destructor - ~CYsfNodeDirFile() {} - - // init & close - bool Init(void); - - // refresh - bool LoadContent(CBuffer *); - bool RefreshContent(const CBuffer &); - -protected: - // reload helpers - bool NeedReload(void); - bool GetLastModTime(time_t *); - -protected: - // data - time_t m_LastModTime; -}; diff --git a/reflector/YSFNodeDirHttp.cpp b/reflector/YSFNodeDirHttp.cpp deleted file mode 100644 index f5fb8f3..0000000 --- a/reflector/YSFNodeDirHttp.cpp +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright © 2019 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 "YSFNodeDirHttp.h" - -#if (YSFNODEDB_USE_RLX_SERVER == 1) -CYsfNodeDirHttp g_YsfNodeDir; -#endif - - -//////////////////////////////////////////////////////////////////////////////////////// -// refresh - -bool CYsfNodeDirHttp::LoadContent(CBuffer *buffer) -{ - // get file from xlxapi server - return HttpGet("xlxapi.rlx.lu", "api/exportysfrepeaters.php", 80, buffer); -} - -bool CYsfNodeDirHttp::RefreshContent(const CBuffer &buffer) -{ - bool ok = false; - - // clear directory - 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 *callsign; - char *txfreq; - char *rxfreq; - if ( ((callsign = ::strtok(ptr1, ";")) != nullptr) ) - { - if ( ((txfreq = ::strtok(nullptr, ";")) != nullptr) ) - { - if ( ((rxfreq = ::strtok(nullptr, ";")) != nullptr) ) - { - // new entry - CCallsign cs(callsign); - CYsfNode node(atoi(txfreq), atoi(rxfreq)); - if ( cs.IsValid() && node.IsValid() ) - { - insert(std::pair(cs, node)); - } - } - } - } - // next line - ptr1 = ptr2+1; - } - - // done - ok = true; - } - - // report - std::cout << "Read " << size() << " YSF nodes from xlxapi.rlx.lu database " << std::endl; - - // done - return ok; -} - - -//////////////////////////////////////////////////////////////////////////////////////// -// httpd helpers - -#define YSFNODE_HTTPGET_SIZEMAX (256) - -bool CYsfNodeDirHttp::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[YSFNODE_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/YSFNodeDirHttp.h b/reflector/YSFNodeDirHttp.h deleted file mode 100644 index c697f91..0000000 --- a/reflector/YSFNodeDirHttp.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright © 2019 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 "YSFNodeDir.h" - -class CYsfNodeDirHttp : public CYsfNodeDir -{ -public: - // constructor - CYsfNodeDirHttp() {} - - // destructor - ~CYsfNodeDirHttp() {} - - // refresh - bool LoadContent(CBuffer *); - bool RefreshContent(const CBuffer &); - -protected: - // reload helpers - bool NeedReload(void) { return true; } - bool HttpGet(const char *, const char *, int, CBuffer *); -}; diff --git a/reflector/YSFProtocol.cpp b/reflector/YSFProtocol.cpp index 462f691..15e9149 100644 --- a/reflector/YSFProtocol.cpp +++ b/reflector/YSFProtocol.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 "CRC.h" #include "YSFPayload.h" @@ -119,7 +119,7 @@ void CYsfProtocol::Task(void) else if ( IsValidDvHeaderPacket(Ip, Fich, Buffer, Header, Frames) ) { // node linked and callsign muted? - if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::ysf, Header->GetRpt2Module()) ) + if ( g_Gate.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::ysf, Header->GetRpt2Module()) ) { // handle it OnDvHeaderPacketIn(Header, Ip); @@ -138,14 +138,14 @@ void CYsfProtocol::Task(void) //std::cout << "YSF keepalive/connect packet from " << Callsign << " at " << Ip << std::endl; // callsign authorized? - if ( g_GateKeeper.MayLink(Callsign, Ip, EProtocol::ysf) ) + if ( g_Gate.MayLink(Callsign, Ip, EProtocol::ysf) ) { // 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::ysf); // client already connected ? if ( client == nullptr ) @@ -168,7 +168,7 @@ void CYsfProtocol::Task(void) client->Alive(); } // and done - g_Reflector.ReleaseClients(); + g_Refl..ReleaseClients(); } } else if ( IsValidDisconnectPacket(Buffer) ) @@ -176,7 +176,7 @@ void CYsfProtocol::Task(void) std::cout << "YSF 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::ysf); if ( client != nullptr ) { @@ -186,7 +186,7 @@ void CYsfProtocol::Task(void) //EncodeDisconnectPacket(&Buffer); //Send(Buffer, Ip); } - g_Reflector.ReleaseClients(); + g_Refl..ReleaseClients(); } else if ( IsValidwirexPacket(Buffer, &Fich, &Callsign, &iWiresxCmd, &iWiresxArg) ) { @@ -263,7 +263,7 @@ void CYsfProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header, CCallsign rpt2(Header->GetRpt2Callsign()); // find this client - std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, EProtocol::ysf); + std::shared_ptrclient = g_Refl..GetClients()->FindClient(Ip, EProtocol::ysf); if ( client ) { // get client callsign @@ -274,20 +274,20 @@ void CYsfProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header, 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 - if ( g_Reflector.IsValidModule(rpt2.GetCSModule()) ) + if ( g_Refl..IsValidModule(rpt2.GetCSModule()) ) { - g_Reflector.GetUsers()->Hearing(my, rpt1, rpt2); - g_Reflector.ReleaseUsers(); + g_Refl..GetUsers()->Hearing(my, rpt1, rpt2); + g_Refl..ReleaseUsers(); } } } @@ -346,7 +346,7 @@ void CYsfProtocol::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::ysf, it)) != nullptr ) @@ -359,7 +359,7 @@ void CYsfProtocol::HandleQueue(void) } } - g_Reflector.ReleaseClients(); + g_Refl..ReleaseClients(); } } m_Queue.Unlock(); @@ -375,7 +375,7 @@ void CYsfProtocol::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::ysf, it)) != nullptr ) @@ -395,7 +395,7 @@ void CYsfProtocol::HandleKeepalives(void) } } - g_Reflector.ReleaseClients(); + g_Refl..ReleaseClients(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -506,7 +506,7 @@ bool CYsfProtocol::IsValidDvFramePacket(const CIp &Ip, const CYSFFICH &Fich, con { // get stream id //uint32_t uiStreamId = IpToStreamId(Ip); - + auto stream = GetStream(m_uiStreamId, &Ip); if ( !stream ) { @@ -531,10 +531,10 @@ bool CYsfProtocol::IsValidDvFramePacket(const CIp &Ip, const CYSFFICH &Fich, con CCallsign rpt2 = m_ReflectorCallsign; rpt2.SetCSModule(' '); header = std::unique_ptr(new CDvHeaderPacket(csMY, CCallsign("CQCQCQ"), rpt1, rpt2, m_uiStreamId, Fich.getFN())); - - if ( g_GateKeeper.MayTransmit(header->GetMyCallsign(), Ip, EProtocol::ysf, header->GetRpt2Module()) ) + + if ( g_Gate.MayTransmit(header->GetMyCallsign(), Ip, EProtocol::ysf, header->GetRpt2Module()) ) { - OnDvHeaderPacketIn(header, Ip); + OnDvHeaderPacketIn(header, Ip); } } @@ -998,7 +998,7 @@ bool CYsfProtocol::EncodeServerStatusPacket(CBuffer *Buffer) const const std::string cs = YSF_REFLECTOR_NAME; memcpy(callsign, cs.c_str(), cs.size() > 16 ? 16 : cs.size()); #else - g_Reflector.GetCallsign().GetCallsign(callsign); + g_Refl..GetCallsign().GetCallsign(callsign); #endif char sz[16]; ::sprintf(sz, "%05u", CalcHash(callsign, 16) % 100000U); @@ -1010,9 +1010,9 @@ bool CYsfProtocol::EncodeServerStatusPacket(CBuffer *Buffer) const memcpy(description, desc.c_str(), desc.size() > 14 ? 14 : desc.size()); Buffer->Append(description, 14); // connected clients - CClients *clients = g_Reflector.GetClients(); + CClients *clients = g_Refl..GetClients(); int count = MIN(999, clients->GetSize()); - g_Reflector.ReleaseClients(); + g_Refl..ReleaseClients(); ::sprintf(sz, "%03u", count); Buffer->Append((uint8_t *)sz, 3); @@ -1090,8 +1090,8 @@ bool CYsfProtocol::DebugTestDecodePacket(const CBuffer &Buffer) std::cout << "Trailer" << std::endl; std::cout << "length of payload : " << len << std::endl; dump.Set(command, len); - dump.DebugDump(g_Reflector.m_DebugFile); - dump.DebugDumpAscii(g_Reflector.m_DebugFile); + dump.DebugDump(g_Refl..m_DebugFile); + dump.DebugDumpAscii(g_Refl..m_DebugFile); break; case YSF_FI_COMMUNICATIONS: if ( Fich.getDT() == YSF_DT_DATA_FR_MODE ) diff --git a/reflector/YSFUtils.cpp b/reflector/YSFUtils.cpp index a3788ce..32349a9 100644 --- a/reflector/YSFUtils.cpp +++ b/reflector/YSFUtils.cpp @@ -19,7 +19,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 "YSFDefines.h" #include "YSFUtils.h" diff --git a/reflector/example.ini b/reflector/example.ini new file mode 100644 index 0000000..87913d1 --- /dev/null +++ b/reflector/example.ini @@ -0,0 +1,121 @@ +###### URFD CONFIGURATION Example ###### +# Do not use quotes, unless in a comment! + +[Names] +Callsign = URF??? # where ? is A-Z or 0-9 + +SysopEmail = you@somewhere.com + +# 2-letter country codes are listed at https://www.iban.com/country-codes +Country = US + +Sponsor = My Ham Club + +[IpAddresses] +# Binding addresses are usually the 'any' address +IPv4Binding = 0.0.0.0 + +# define IPv6 if you want a "dual-stack" reflector +# IPv6Binding = :: + +# define if you want to override what urfd finds using ipv4.icanhazip.com +# IPv4External = 1.2.3.4 + +# define if you want to override what urfd finds using ipv6.icanhazip.com +# IPv6External = a:b:c:e:f:0:1:2 + +Transcoder = local # SORRY, but only local TC's are supported right now! + +[Modules] +Modules = ADMSZ +# Modules = ABCDEFGHIJKLMNOPQRSTUVWXYZ +Transcoded = A # comment out if you don't have transcoding hardware +# Create Descriptions as needed... +DescriptionA = Transcoded +DescriptionD = DMR Chat +DescriptionM = M17 Chat +DescriptionS = DStar Chat +DescriptionZ = Temp Meeting + +# Protocols +[Brandmeister] +Port = 10002 + +[DCS] +Port = 30051 + +[DExtra] +Port = 30001 + +[DMRPlus] +Port = 8880 + +[DPlus] +Port = 20001 + +[M17] +Port = 17000 + +[MMDVM] +Port = 62030 +DefaultId = 0 + +[NXDN] +Port = 41400 +AutoLinkModule = A # comment out if you want to disable AL +ReflectorID = 12345 + +[P25] +Port = 41000 +AutoLinkModule = A # comment out if you want to disable AL +ReflectorID = 12345 + +[URF] +Port = 10017 + +[USRP] +Port = 34001 +AutoLinkModule = A # comment out if you want to disable AL +DefaultCallsign = ALLSTAR +ClientFilePath = /usr/local/etc/USRPClients.txt + +[YSF] +Port = 42000 +AutoLinkModule = A # comment out if you want to disable AL +DefaultTxFreq = 446500000 +DefaultRxFreq = 446500000 +# if you've registered your reflector at register.ysfreflector.de: +RegistrationID = 12345 +RegistrationName = US URF??? +RegistrationDescription = URF Reflector + +######## Database files +[DMR ID DB] +Hostname = xlxapi.rlx.lu +Suffix = api/exportdmr.php +Mode = http +RefreshMin = 179 +FilePath = /usr/local/etc/dmrid.dat + +[NXDN ID DB] +Hostname = www.dudetronics.com +Suffix = ar-dns/NXDN.csv +Mode = http +RefreshMin = 181 +FilePath = /usr/local/etc/nxdn.dat + +[YSF TX/RX DB] +Hostname = xlxapi.rlx.lu +Suffix = api/exportysfrepeaters.php +Mode = http +RefreshMin = 191 +FilePath = /usr/local/etc/ysfnode.dat + +######### Other File locations +[Files] +PidPath = /var/run/urfd.pid +JsonPath = /var/log/urfd.json +WhitelistPath = /usr/local/etc/urfd.whitelist +BlacklistPath = /usr/local/etc/urfd.blacklist +InterlinkPath = /usr/local/etc/urfd.interlink +G3TerminalPath = /usr/local/etc/urfd.terminal From 72e64ec80181839e7e14a6673549618ad1c1c8b1 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Sun, 12 Feb 2023 06:10:33 -0700 Subject: [PATCH 02/44] it compiles --- config/urfd.interlink | 4 +- reflector/BMClient.cpp | 2 +- reflector/BMClient.h | 1 + reflector/BMPeer.cpp | 2 +- reflector/BMProtocol.cpp | 45 +++++----- reflector/BMProtocol.h | 1 + reflector/Buffer.cpp | 1 + reflector/CNotificationQueue.h | 6 -- reflector/Callsign.cpp | 7 +- reflector/CallsignList.cpp | 11 +-- reflector/CallsignList.h | 10 +-- reflector/CallsignListItem.cpp | 12 ++- reflector/Client.h | 7 +- reflector/Clients.cpp | 8 +- reflector/Configure.cpp | 10 +-- reflector/DCSClient.h | 1 + reflector/DCSProtocol.cpp | 39 +++++---- reflector/DCSProtocol.h | 1 + reflector/DExtraClient.cpp | 2 - reflector/DExtraClient.h | 8 +- reflector/DExtraPeer.cpp | 67 --------------- reflector/DExtraPeer.h | 42 ---------- reflector/DExtraProtocol.cpp | 145 +++++++-------------------------- reflector/DExtraProtocol.h | 4 +- reflector/DMRMMDVMClient.h | 1 + reflector/DMRMMDVMProtocol.cpp | 50 ++++++------ reflector/DMRMMDVMProtocol.h | 4 + reflector/DMRPlusClient.h | 1 + reflector/DMRPlusProtocol.cpp | 41 +++++----- reflector/DMRPlusProtocol.h | 1 + reflector/DPlusClient.h | 1 + reflector/DPlusProtocol.cpp | 37 ++++----- reflector/DPlusProtocol.h | 1 + reflector/DVFramePacket.cpp | 2 +- reflector/DVHeaderPacket.cpp | 6 +- reflector/Defines.h | 31 +++++-- reflector/G3Client.h | 1 + reflector/G3Protocol.cpp | 64 ++++++++------- reflector/G3Protocol.h | 3 + reflector/GateKeeper.cpp | 8 +- reflector/LookupDmr.cpp | 18 ++-- reflector/LookupNxdn.cpp | 18 ++-- reflector/LookupYsf.cpp | 22 ++--- reflector/LookupYsf.h | 2 + reflector/M17Client.h | 8 +- reflector/M17Protocol.cpp | 39 +++++---- reflector/M17Protocol.h | 1 + reflector/Makefile | 48 ++++------- reflector/NXDNClient.h | 2 + reflector/NXDNProtocol.cpp | 44 +++++----- reflector/NXDNProtocol.h | 8 +- reflector/NotificationQueue.h | 6 -- reflector/P25Client.h | 3 +- reflector/P25Protocol.cpp | 48 +++++------ reflector/P25Protocol.h | 8 +- reflector/Packet.cpp | 2 +- reflector/PacketQueue.h | 2 + reflector/PacketStream.cpp | 5 +- reflector/PeerCallsignList.cpp | 3 +- reflector/PeerCallsignList.h | 2 +- reflector/Peers.cpp | 16 ++-- reflector/Protocol.cpp | 38 +++++---- reflector/Protocol.h | 6 +- reflector/Protocols.cpp | 29 +++---- reflector/Semaphore.h | 5 +- reflector/URFClient.h | 1 + reflector/URFProtocol.cpp | 64 +++++++-------- reflector/URFProtocol.h | 1 + reflector/USRPClient.h | 2 + reflector/USRPProtocol.cpp | 42 +++++----- reflector/USRPProtocol.h | 7 +- reflector/User.cpp | 2 +- reflector/Users.cpp | 7 +- reflector/WiresXCmdHandler.cpp | 31 ++++--- reflector/WiresXInfo.cpp | 2 +- reflector/YSFClient.h | 2 + reflector/YSFNode.h | 2 +- reflector/YSFProtocol.cpp | 51 ++++++------ reflector/YSFProtocol.h | 4 + reflector/YSFUtils.cpp | 9 -- reflector/YSFUtils.h | 2 + reflector/example.ini | 2 +- 82 files changed, 552 insertions(+), 750 deletions(-) delete mode 100644 reflector/DExtraPeer.cpp delete mode 100644 reflector/DExtraPeer.h diff --git a/config/urfd.interlink b/config/urfd.interlink index b895a7d..3232cc2 100644 --- a/config/urfd.interlink +++ b/config/urfd.interlink @@ -5,12 +5,10 @@ # each entry specifies a remote XLX or XRF to peer with # format: # -# # example: # URF270 158.64.26.132 ACD -# XRF270 158.64.26.132 BB # -# note: the remote XLX must list this XLX in its interlink file +# note: the remote URFD must list this in its interlink file # for the link to be established # ############################################################################# diff --git a/reflector/BMClient.cpp b/reflector/BMClient.cpp index 59b037c..9e621da 100644 --- a/reflector/BMClient.cpp +++ b/reflector/BMClient.cpp @@ -43,5 +43,5 @@ CBmClient::CBmClient(const CBmClient &client) bool CBmClient::IsAlive(void) const { - return (m_LastKeepaliveTime.time() < XLX_KEEPALIVE_TIMEOUT); + return (m_LastKeepaliveTime.time() < BM_KEEPALIVE_TIMEOUT); } diff --git a/reflector/BMClient.h b/reflector/BMClient.h index 1708bf6..4328afc 100644 --- a/reflector/BMClient.h +++ b/reflector/BMClient.h @@ -18,6 +18,7 @@ #pragma once +#include "Defines.h" #include "Client.h" class CBmClient : public CClient diff --git a/reflector/BMPeer.cpp b/reflector/BMPeer.cpp index 6bcd756..fa03e3c 100644 --- a/reflector/BMPeer.cpp +++ b/reflector/BMPeer.cpp @@ -50,7 +50,7 @@ CBmPeer::CBmPeer(const CCallsign &callsign, const CIp &ip, const char *modules, bool CBmPeer::IsAlive(void) const { - return (m_LastKeepaliveTime.time() < XLX_KEEPALIVE_TIMEOUT); + return (m_LastKeepaliveTime.time() < BM_KEEPALIVE_TIMEOUT); } //////////////////////////////////////////////////////////////////////////////////////// diff --git a/reflector/BMProtocol.cpp b/reflector/BMProtocol.cpp index dae8b90..3d848ce 100644 --- a/reflector/BMProtocol.cpp +++ b/reflector/BMProtocol.cpp @@ -18,12 +18,9 @@ #include - #include "BMPeer.h" #include "BMProtocol.h" -#include "Reflector.h" -#include "GateKeeper.h" - +#include "Global.h" //////////////////////////////////////////////////////////////////////////////////////// // operation @@ -104,7 +101,7 @@ void CBMProtocol::Task(void) if ( g_Gate.MayLink(Callsign, Ip, EProtocol::bm, Modules) ) { // already connected ? - CPeers *peers = g_Refl..GetPeers(); + CPeers *peers = g_Refl.GetPeers(); if ( peers->FindPeer(Callsign, Ip, EProtocol::bm) == nullptr ) { // create the new peer @@ -115,7 +112,7 @@ void CBMProtocol::Task(void) // this also add all new clients to reflector client list peers->AddPeer(peer); } - g_Refl..ReleasePeers(); + g_Refl.ReleasePeers(); } } else if ( IsValidDisconnectPacket(Buffer, &Callsign) ) @@ -123,7 +120,7 @@ void CBMProtocol::Task(void) std::cout << "XLX disconnect packet from " << Callsign << " at " << Ip << std::endl; // find peer - CPeers *peers = g_Refl..GetPeers(); + CPeers *peers = g_Refl.GetPeers(); std::shared_ptrpeer = peers->FindPeer(Ip, EProtocol::bm); if ( peer != nullptr ) { @@ -132,7 +129,7 @@ void CBMProtocol::Task(void) // and delete them peers->RemovePeer(peer); } - g_Refl..ReleasePeers(); + g_Refl.ReleasePeers(); } else if ( IsValidNackPacket(Buffer, &Callsign) ) { @@ -143,14 +140,14 @@ void CBMProtocol::Task(void) //std::cout << "XLX keepalive packet from " << Callsign << " at " << Ip << std::endl; // find peer - CPeers *peers = g_Refl..GetPeers(); + CPeers *peers = g_Refl.GetPeers(); std::shared_ptrpeer = peers->FindPeer(Ip, EProtocol::bm); if ( peer != nullptr ) { // keep it alive peer->Alive(); } - g_Refl..ReleasePeers(); + g_Refl.ReleasePeers(); } else { @@ -167,7 +164,7 @@ void CBMProtocol::Task(void) HandleQueue(); // keep alive - if ( m_LastKeepaliveTime.time() > XLX_KEEPALIVE_PERIOD ) + if ( m_LastKeepaliveTime.time() > BM_KEEPALIVE_PERIOD ) { // handle keep alives HandleKeepalives(); @@ -177,7 +174,7 @@ void CBMProtocol::Task(void) } // peer connections - if ( m_LastPeersLinkTime.time() > XLX_RECONNECT_PERIOD ) + if ( m_LastPeersLinkTime.time() > BM_RECONNECT_PERIOD ) { // handle remote peers connections HandlePeerLinks(); @@ -210,7 +207,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_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::bm, it)) != nullptr ) @@ -237,7 +234,7 @@ void CBMProtocol::HandleQueue(void) } } } - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); } } m_Queue.Unlock(); @@ -255,7 +252,7 @@ void CBMProtocol::HandleKeepalives(void) EncodeKeepAlivePacket(&keepalive); // iterate on peers - CPeers *peers = g_Refl..GetPeers(); + CPeers *peers = g_Refl.GetPeers(); auto pit = peers->begin(); std::shared_ptrpeer = nullptr; while ( (peer = peers->FindNextPeer(EProtocol::bm, pit)) != nullptr ) @@ -282,7 +279,7 @@ void CBMProtocol::HandleKeepalives(void) peers->RemovePeer(peer); } } - g_Refl..ReleasePeers(); + g_Refl.ReleasePeers(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -294,7 +291,7 @@ void CBMProtocol::HandlePeerLinks(void) // get the list of peers CPeerCallsignList *list = g_Gate.GetPeerList(); - CPeers *peers = g_Refl..GetPeers(); + CPeers *peers = g_Refl.GetPeers(); // check if all our connected peers are still listed by gatekeeper // if not, disconnect @@ -324,13 +321,13 @@ void CBMProtocol::HandlePeerLinks(void) it->ResolveIp(); // send connect packet to re-initiate peer link EncodeConnectPacket(&buffer, it->GetModules()); - Send(buffer, it->GetIp(), XLX_PORT); + Send(buffer, it->GetIp(), m_Port); std::cout << "Sending connect packet to BM peer " << cs << " @ " << it->GetIp() << " for modules " << it->GetModules() << std::endl; } } // done - g_Refl..ReleasePeers(); + g_Refl.ReleasePeers(); g_Gate.ReleasePeerList(); } @@ -360,11 +357,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_Refl..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_Refl..OpenStream(Header, client)) != nullptr ) + if ( (stream = g_Refl.OpenStream(Header, client)) != nullptr ) { // keep the handle m_Streams[stream->GetStreamId()] = stream; @@ -373,10 +370,10 @@ void CBMProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header, c peer = client->GetCallsign(); } // release - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); // update last heard - g_Refl..GetUsers()->Hearing(my, rpt1, rpt2, peer); - g_Refl..ReleaseUsers(); + g_Refl.GetUsers()->Hearing(my, rpt1, rpt2, peer); + g_Refl.ReleaseUsers(); } } diff --git a/reflector/BMProtocol.h b/reflector/BMProtocol.h index fa36b2d..74dfe15 100644 --- a/reflector/BMProtocol.h +++ b/reflector/BMProtocol.h @@ -18,6 +18,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +#include "Defines.h" #include "Version.h" #include "Timer.h" #include "SEProtocol.h" diff --git a/reflector/Buffer.cpp b/reflector/Buffer.cpp index 544ba84..8aa57a5 100644 --- a/reflector/Buffer.cpp +++ b/reflector/Buffer.cpp @@ -16,6 +16,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +#include #include #include "Buffer.h" diff --git a/reflector/CNotificationQueue.h b/reflector/CNotificationQueue.h index 57839ad..f0bc210 100644 --- a/reflector/CNotificationQueue.h +++ b/reflector/CNotificationQueue.h @@ -23,12 +23,6 @@ #include "Notification.h" - -//////////////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////////////// -// class - class CNotificationQueue { public: diff --git a/reflector/Callsign.cpp b/reflector/Callsign.cpp index c8749b3..b0312e3 100644 --- a/reflector/Callsign.cpp +++ b/reflector/Callsign.cpp @@ -19,10 +19,7 @@ #include #include -#include "DMRIdDirFile.h" -#include "DMRIdDirHttp.h" -#include "NXDNIdDirFile.h" -#include "NXDNIdDirHttp.h" +#include "Global.h" #include "Callsign.h" // if a client is using special characters '.', '-' or '/', he's out of luck! @@ -277,7 +274,7 @@ void CCallsign::SetNXDNid(uint16_t nxdnid, bool UpdateCallsign) m_uiNXDNid = nxdnid; if ( UpdateCallsign ) { - g_LDid.Lock(); + g_LNid.Lock(); { const CCallsign *callsign = g_LNid.FindCallsign(nxdnid); if ( callsign != nullptr ) diff --git a/reflector/CallsignList.cpp b/reflector/CallsignList.cpp index 2fff96b..e1d4a0d 100644 --- a/reflector/CallsignList.cpp +++ b/reflector/CallsignList.cpp @@ -16,6 +16,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +#include #include #include #include @@ -34,7 +35,7 @@ CCallsignList::CCallsignList() //////////////////////////////////////////////////////////////////////////////////////// // file io -bool CCallsignList::LoadFromFile(const char *filename) +bool CCallsignList::LoadFromFile(const std::string &filename) { bool ok = false; char sz[256]; @@ -77,7 +78,7 @@ bool CCallsignList::LoadFromFile(const char *filename) file.close(); // keep file path - m_Filename = filename; + m_Filename.assign(filename); // update time GetLastModTime(&m_LastModTime); @@ -99,7 +100,7 @@ bool CCallsignList::ReloadFromFile(void) { bool ok = false; - if ( m_Filename != nullptr ) + if (! m_Filename.empty()) { ok = LoadFromFile(m_Filename); } @@ -210,10 +211,10 @@ bool CCallsignList::GetLastModTime(time_t *time) { bool ok = false; - if ( m_Filename != nullptr ) + if (! m_Filename.empty()) { struct stat fileStat; - if( ::stat(m_Filename, &fileStat) != -1 ) + if( ::stat(m_Filename.c_str(), &fileStat) != -1 ) { *time = fileStat.st_mtime; ok = true; diff --git a/reflector/CallsignList.h b/reflector/CallsignList.h index c9ba29a..df1d153 100644 --- a/reflector/CallsignList.h +++ b/reflector/CallsignList.h @@ -18,6 +18,9 @@ #pragma once +#include +#include + #include "CallsignListItem.h" //////////////////////////////////////////////////////////////////////////////////////// @@ -29,15 +32,12 @@ public: // constructor CCallsignList(); - // destructor - virtual ~CCallsignList() {} - // locks void Lock(void) { m_Mutex.lock(); } void Unlock(void) { m_Mutex.unlock(); } // file io - virtual bool LoadFromFile(const char *); + virtual bool LoadFromFile(const std::string &str); bool ReloadFromFile(void); bool NeedReload(void); @@ -61,7 +61,7 @@ protected: // data std::mutex m_Mutex; - const char * m_Filename; + std::string m_Filename; time_t m_LastModTime; std::list m_Callsigns; }; diff --git a/reflector/CallsignListItem.cpp b/reflector/CallsignListItem.cpp index c6a5808..01bebab 100644 --- a/reflector/CallsignListItem.cpp +++ b/reflector/CallsignListItem.cpp @@ -18,6 +18,8 @@ #include +#include "Global.h" + #include "CallsignListItem.h" //////////////////////////////////////////////////////////////////////////////////////// @@ -31,6 +33,7 @@ CCallsignListItem::CCallsignListItem() CCallsignListItem::CCallsignListItem(const CCallsign &callsign, const CIp &ip, const char *modules) { + const std::string mods(g_Conf.GetString(g_Conf.j.modules.modules)); m_Callsign = callsign; memset(m_szUrl, 0, sizeof(m_szUrl)); m_Ip = ip; @@ -39,14 +42,14 @@ CCallsignListItem::CCallsignListItem(const CCallsign &callsign, const CIp &ip, c memset(m_Modules, 0, sizeof(m_Modules)); if ( modules[0] == '*' ) { - memcpy(m_Modules, ACTIVE_MODULES, sizeof(ACTIVE_MODULES)); + memcpy(m_Modules, mods.c_str(), mods.size()); } else { int n = MIN(::strlen(modules), sizeof(m_Modules)-1); for (int i=0, j=0; i. -#include "Reflector.h" +#include "Global.h" #include "Clients.h" - //////////////////////////////////////////////////////////////////////////////////////// // constructor - CClients::CClients() { } @@ -66,7 +64,7 @@ void CClients::AddClient(std::shared_ptr client) } std::cout << std::endl; // notify - g_Refl..OnClientsChanged(); + g_Refl.OnClientsChanged(); } void CClients::RemoveClient(std::shared_ptr client) @@ -90,7 +88,7 @@ void CClients::RemoveClient(std::shared_ptr client) std::cout << std::endl; m_Clients.erase(it); // notify - g_Refl..OnClientsChanged(); + g_Refl.OnClientsChanged(); break; } } diff --git a/reflector/Configure.cpp b/reflector/Configure.cpp index 968c722..de6b31f 100644 --- a/reflector/Configure.cpp +++ b/reflector/Configure.cpp @@ -441,7 +441,7 @@ bool CConfigure::ReadData(const std::string &path) data[j.usrp.defaultcallsign] = cs; } else if (0 == key.compare(JCLIENTSPATH)) - data[j.usrp.clientfilepath] == value; + data[j.usrp.clientfilepath] = value; else badParam(key); break; @@ -915,14 +915,14 @@ bool CConfigure::IsString(const std::string &key) const #ifdef INICHECK int main(int argc, char *argv[]) { - if (argc == 2) + if (argc == 2 || argc == 3) { CConfigure d; - auto rval = d.ReadData(argv[1]); - d.Dump(true); + auto rval = d.ReadData(argv[argc-1]); + d.Dump((2==argc) ? false : true); return rval ? EXIT_FAILURE : EXIT_SUCCESS; } - std::cerr << "Usage: " << argv[0] << " FILENAME" << std::endl; + std::cerr << "Usage: " << argv[0] << " FILENAME\nWhere is anything.\nThis option only shows values whose key begins with an uppercase letter." << std::endl; return EXIT_SUCCESS; } #endif diff --git a/reflector/DCSClient.h b/reflector/DCSClient.h index 09d00dd..d22cd04 100644 --- a/reflector/DCSClient.h +++ b/reflector/DCSClient.h @@ -18,6 +18,7 @@ #pragma once +#include "Defines.h" #include "Client.h" class CDcsClient : public CClient diff --git a/reflector/DCSProtocol.cpp b/reflector/DCSProtocol.cpp index 0a3f5b6..90eb419 100644 --- a/reflector/DCSProtocol.cpp +++ b/reflector/DCSProtocol.cpp @@ -16,12 +16,11 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . - #include + +#include "Global.h" #include "DCSClient.h" #include "DCSProtocol.h" -#include "Reflector.h" -#include "GateKeeper.h" //////////////////////////////////////////////////////////////////////////////////////// // operation @@ -80,18 +79,18 @@ void CDcsProtocol::Task(void) std::cout << "DCS connect packet for module " << ToLinkModule << " from " << Callsign << " at " << Ip << std::endl; // callsign authorized? - if ( g_Gate.MayLink(Callsign, Ip, EProtocol::dcs) && g_Refl..IsValidModule(ToLinkModule) ) + if ( g_Gate.MayLink(Callsign, Ip, EProtocol::dcs) && g_Refl.IsValidModule(ToLinkModule) ) { // valid module ? - if ( g_Refl..IsValidModule(ToLinkModule) ) + if ( g_Refl.IsValidModule(ToLinkModule) ) { // acknowledge the request EncodeConnectAckPacket(Callsign, ToLinkModule, &Buffer); Send(Buffer, Ip); // create the client and append - g_Refl..GetClients()->AddClient(std::make_shared(Callsign, Ip, ToLinkModule)); - g_Refl..ReleaseClients(); + g_Refl.GetClients()->AddClient(std::make_shared(Callsign, Ip, ToLinkModule)); + g_Refl.ReleaseClients(); } else { @@ -115,7 +114,7 @@ void CDcsProtocol::Task(void) std::cout << "DCS disconnect packet from " << Callsign << " at " << Ip << std::endl; // find client - CClients *clients = g_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); std::shared_ptrclient = clients->FindClient(Ip, EProtocol::dcs); if ( client != nullptr ) { @@ -125,21 +124,21 @@ void CDcsProtocol::Task(void) EncodeConnectNackPacket(Callsign, ' ', &Buffer); Send(Buffer, Ip); } - g_Refl..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_Refl..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_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); } else if ( IsIgnorePacket(Buffer) ) { @@ -193,24 +192,24 @@ void CDcsProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header, CCallsign rpt2(Header->GetRpt2Callsign()); // find this client - std::shared_ptrclient = g_Refl..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_Refl..OpenStream(Header, client)) != nullptr ) + if ( (stream = g_Refl.OpenStream(Header, client)) != nullptr ) { // keep the handle m_Streams[stream->GetStreamId()] = stream; } } // release - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); // update last heard - g_Refl..GetUsers()->Hearing(my, rpt1, rpt2); - g_Refl..ReleaseUsers(); + g_Refl.GetUsers()->Hearing(my, rpt1, rpt2); + g_Refl.ReleaseUsers(); } } @@ -253,7 +252,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_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::dcs, it)) != nullptr ) @@ -266,7 +265,7 @@ void CDcsProtocol::HandleQueue(void) } } - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); } } } @@ -285,7 +284,7 @@ void CDcsProtocol::HandleKeepalives(void) EncodeKeepAlivePacket(&keepalive1); // iterate on clients - CClients *clients = g_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::dcs, it)) != nullptr ) @@ -318,7 +317,7 @@ void CDcsProtocol::HandleKeepalives(void) } } - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); } //////////////////////////////////////////////////////////////////////////////////////// diff --git a/reflector/DCSProtocol.h b/reflector/DCSProtocol.h index d064dc1..49bbfbc 100644 --- a/reflector/DCSProtocol.h +++ b/reflector/DCSProtocol.h @@ -18,6 +18,7 @@ #pragma once +#include "Defines.h" #include "Timer.h" #include "Protocol.h" #include "DVHeaderPacket.h" diff --git a/reflector/DExtraClient.cpp b/reflector/DExtraClient.cpp index fc6b008..560ff66 100644 --- a/reflector/DExtraClient.cpp +++ b/reflector/DExtraClient.cpp @@ -16,10 +16,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . - #include "DExtraClient.h" - //////////////////////////////////////////////////////////////////////////////////////// // constructors diff --git a/reflector/DExtraClient.h b/reflector/DExtraClient.h index dd6dab1..f91f941 100644 --- a/reflector/DExtraClient.h +++ b/reflector/DExtraClient.h @@ -18,15 +18,9 @@ #pragma once +#include "Defines.h" #include "Client.h" -//////////////////////////////////////////////////////////////////////////////////////// -// define - - -//////////////////////////////////////////////////////////////////////////////////////// -// class - class CDextraClient : public CClient { public: diff --git a/reflector/DExtraPeer.cpp b/reflector/DExtraPeer.cpp deleted file mode 100644 index 1a72a60..0000000 --- a/reflector/DExtraPeer.cpp +++ /dev/null @@ -1,67 +0,0 @@ -// Created by Antony Chazapis (SV9OAN) on 25/2/2018. -// Copyright © 2016 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 "Reflector.h" -#include "DExtraPeer.h" -#include "DExtraClient.h" - - -//////////////////////////////////////////////////////////////////////////////////////// -// constructor - - -CDextraPeer::CDextraPeer() -{ -} - -CDextraPeer::CDextraPeer(const CCallsign &callsign, const CIp &ip, const char *modules, const CVersion &version) - : CPeer(callsign, ip, modules, version) -{ - std::cout << "Adding DExtra peer" << std::endl; - - // and construct the DExtra clients - for ( unsigned i = 0; i < ::strlen(modules); i++ ) - { - // create and append to list - m_Clients.push_back(std::make_shared(callsign, ip, modules[i], EProtoRev::ambe)); - } -} - -//////////////////////////////////////////////////////////////////////////////////////// -// status - -bool CDextraPeer::IsAlive(void) const -{ - for ( auto it=cbegin(); it!=cend(); it++ ) - { - if (! (*it)->IsAlive()) - return false; - } - return true; -} - -//////////////////////////////////////////////////////////////////////////////////////// -// revision helper - -int CDextraPeer::GetProtocolRevision(const CVersion &version) -{ - return version.GetMajor(); -} diff --git a/reflector/DExtraPeer.h b/reflector/DExtraPeer.h deleted file mode 100644 index ac6d538..0000000 --- a/reflector/DExtraPeer.h +++ /dev/null @@ -1,42 +0,0 @@ -// Created by Antony Chazapis (SV9OAN) on 25/2/2018. -// Copyright © 2016 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 "Peer.h" -#include "DExtraClient.h" - -class CDextraPeer : public CPeer -{ -public: - // constructors - CDextraPeer(); - CDextraPeer(const CCallsign &, const CIp &, const char *, const CVersion &); - CDextraPeer(const CDextraPeer &) = delete; - - // status - bool IsAlive(void) const; - - // identity - EProtocol GetProtocol(void) const { return EProtocol::dextra; } - const char *GetProtocolName(void) const { return "DExtra"; } - - // revision helper - static int GetProtocolRevision(const CVersion &); -}; diff --git a/reflector/DExtraProtocol.cpp b/reflector/DExtraProtocol.cpp index 9b47e2b..8a4b046 100644 --- a/reflector/DExtraProtocol.cpp +++ b/reflector/DExtraProtocol.cpp @@ -18,12 +18,11 @@ #include -#include "DExtraPeer.h" + +#include "Global.h" #include "DExtraClient.h" #include "DExtraProtocol.h" -#include "Reflector.h" -#include "GateKeeper.h" - +# //////////////////////////////////////////////////////////////////////////////////////// // operation @@ -36,7 +35,6 @@ bool CDextraProtocol::Initialize(const char *type, const EProtocol ptype, const // update time m_LastKeepaliveTime.start(); - m_LastPeersLinkTime.start(); // done return true; @@ -101,38 +99,15 @@ void CDextraProtocol::Task(void) if ( g_Gate.MayLink(Callsign, Ip, EProtocol::dextra) ) { // valid module ? - if ( g_Refl..IsValidModule(ToLinkModule) ) + if ( g_Refl.IsValidModule(ToLinkModule) ) { - // is this an ack for a link request? - 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_Refl..GetPeers(); - if ( peers->FindPeer(Callsign, Ip, EProtocol::dextra) == nullptr ) - { - // create the new peer - // this also create one client per module - // append the peer to reflector peer list - // 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_Refl..ReleasePeers(); - } - else - { - // acknowledge the request - EncodeConnectAckPacket(&Buffer, ProtRev); - Send(Buffer, Ip); + // acknowledge the request + EncodeConnectAckPacket(&Buffer, ProtRev); + Send(Buffer, Ip); - // create the client and append - g_Refl..GetClients()->AddClient(std::make_shared(Callsign, Ip, ToLinkModule, ProtRev)); - g_Refl..ReleaseClients(); - } - g_Gate.ReleasePeerList(); + // create the client and append + g_Refl.GetClients()->AddClient(std::make_shared(Callsign, Ip, ToLinkModule, ProtRev)); + g_Refl.ReleaseClients(); } else { @@ -155,7 +130,7 @@ void CDextraProtocol::Task(void) std::cout << "DExtra disconnect packet from " << Callsign << " at " << Ip << std::endl; // find client & remove it - CClients *clients = g_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); std::shared_ptrclient = clients->FindClient(Ip, EProtocol::dextra); if ( client != nullptr ) { @@ -172,21 +147,21 @@ void CDextraProtocol::Task(void) // and remove it clients->RemoveClient(client); } - g_Refl..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_Refl..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_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); } else { @@ -211,16 +186,6 @@ void CDextraProtocol::Task(void) // update time m_LastKeepaliveTime.start(); } - - // peer connections - if ( m_LastPeersLinkTime.time() > DEXTRA_RECONNECT_PERIOD ) - { - // handle remote peers connections - HandlePeerLinks(); - - // update time - m_LastPeersLinkTime.start(); - } } //////////////////////////////////////////////////////////////////////////////////////// @@ -239,7 +204,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_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::dextra, it)) != nullptr ) @@ -255,7 +220,7 @@ void CDextraProtocol::HandleQueue(void) } } } - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); } } m_Queue.Unlock(); @@ -273,7 +238,7 @@ void CDextraProtocol::HandleKeepalives(void) EncodeKeepAlivePacket(&keepalive); // iterate on clients - CClients *clients = g_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::dextra, it)) != nullptr ) @@ -290,7 +255,7 @@ void CDextraProtocol::HandleKeepalives(void) // otherwise check if still with us else if ( !client->IsAlive() ) { - CPeers *peers = g_Refl..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 +272,14 @@ void CDextraProtocol::HandleKeepalives(void) std::cout << "DExtra client " << client->GetCallsign() << " keepalive timeout" << std::endl; clients->RemoveClient(client); } - g_Refl..ReleasePeers(); + g_Refl.ReleasePeers(); } } - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); // iterate on peers - CPeers *peers = g_Refl..GetPeers(); + CPeers *peers = g_Refl.GetPeers(); auto pit = peers->begin(); std::shared_ptrpeer = nullptr; while ( (peer = peers->FindNextPeer(EProtocol::dextra, pit)) != nullptr ) @@ -327,71 +292,19 @@ void CDextraProtocol::HandleKeepalives(void) // no, disconnect all clients CBuffer disconnect; EncodeDisconnectPacket(&disconnect, peer->GetReflectorModules()[0]); - CClients *clients = g_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); for ( auto cit=peer->cbegin(); cit!=peer->cend(); cit++ ) { Send(disconnect, (*cit)->GetIp()); } - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); // remove it std::cout << "DExtra peer " << peer->GetCallsign() << " keepalive timeout" << std::endl; peers->RemovePeer(peer); } } - g_Refl..ReleasePeers(); -} - -//////////////////////////////////////////////////////////////////////////////////////// -// Peers helpers - -void CDextraProtocol::HandlePeerLinks(void) -{ - CBuffer buffer; - - // get the list of peers - CPeerCallsignList *list = g_Gate.GetPeerList(); - CPeers *peers = g_Refl..GetPeers(); - - // check if all our connected peers are still listed by gatekeeper - // if not, disconnect - auto pit = peers->begin(); - std::shared_ptrpeer = nullptr; - while ( (peer = peers->FindNextPeer(EProtocol::dextra, pit)) != nullptr ) - { - if ( list->FindListItem(peer->GetCallsign()) == nullptr ) - { - // send disconnect packet - EncodeDisconnectPacket(&buffer, peer->GetReflectorModules()[0]); - Send(buffer, peer->GetIp()); - std::cout << "Sending disconnect packet to XRF peer " << peer->GetCallsign() << " at " << peer->GetIp() << std::endl; - // remove client - peers->RemovePeer(peer); - } - } - - // check if all ours peers listed by gatekeeper are connected - // if not, connect or reconnect - for ( auto it=list->begin(); it!=list->end(); it++ ) - { - if ( !it->GetCallsign().HasSameCallsignWithWildcard(CCallsign("XRF*")) ) - continue; - if ( strlen(it->GetModules()) != 2 ) - continue; - if ( peers->FindPeer(it->GetCallsign(), EProtocol::dextra) == nullptr ) - { - // resolve again peer's IP in case it's a dynamic IP - it->ResolveIp(); - // send connect packet to re-initiate peer link - EncodeConnectPacket(&buffer, it->GetModules()); - Send(buffer, it->GetIp(), DEXTRA_PORT); - std::cout << "Sending connect packet to XRF peer " << it->GetCallsign() << " @ " << it->GetIp() << " for module " << it->GetModules()[1] << " (module " << it->GetModules()[0] << ")" << std::endl; - } - } - - // done - g_Refl..ReleasePeers(); - g_Gate.ReleasePeerList(); + g_Refl.ReleasePeers(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -415,7 +328,7 @@ void CDextraProtocol::OnDvHeaderPacketIn(std::unique_ptr &Heade CCallsign rpt2(Header->GetRpt2Callsign()); // find this client - std::shared_ptrclient = g_Refl..GetClients()->FindClient(Ip, EProtocol::dextra); + std::shared_ptrclient = g_Refl.GetClients()->FindClient(Ip, EProtocol::dextra); if ( client ) { // get client callsign @@ -430,18 +343,18 @@ void CDextraProtocol::OnDvHeaderPacketIn(std::unique_ptr &Heade rpt2.SetCSModule(m); } // and try to open the stream - if ( (stream = g_Refl..OpenStream(Header, client)) != nullptr ) + if ( (stream = g_Refl.OpenStream(Header, client)) != nullptr ) { // keep the handle m_Streams[stream->GetStreamId()] = stream; } } // release - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); // update last heard - g_Refl..GetUsers()->Hearing(my, rpt1, rpt2); - g_Refl..ReleaseUsers(); + g_Refl.GetUsers()->Hearing(my, rpt1, rpt2); + g_Refl.ReleaseUsers(); } } diff --git a/reflector/DExtraProtocol.h b/reflector/DExtraProtocol.h index 69f329d..4434ddd 100644 --- a/reflector/DExtraProtocol.h +++ b/reflector/DExtraProtocol.h @@ -18,6 +18,7 @@ #pragma once +#include "Defines.h" #include "Timer.h" #include "SEProtocol.h" #include "DVHeaderPacket.h" @@ -61,7 +62,6 @@ protected: void HandleQueue(void); // keepalive helpers - void HandlePeerLinks(void); void HandleKeepalives(void); // stream helpers @@ -84,8 +84,6 @@ protected: bool EncodeDvHeaderPacket(const CDvHeaderPacket &, CBuffer &) const; bool EncodeDvFramePacket(const CDvFramePacket &, CBuffer &) const; -protected: // time CTimer m_LastKeepaliveTime; - CTimer m_LastPeersLinkTime; }; diff --git a/reflector/DMRMMDVMClient.h b/reflector/DMRMMDVMClient.h index d3c7cec..31c7fac 100644 --- a/reflector/DMRMMDVMClient.h +++ b/reflector/DMRMMDVMClient.h @@ -18,6 +18,7 @@ #pragma once +#include "Defines.h" #include "Client.h" class CDmrmmdvmClient : public CClient diff --git a/reflector/DMRMMDVMProtocol.cpp b/reflector/DMRMMDVMProtocol.cpp index c3f8acd..ec0b60e 100644 --- a/reflector/DMRMMDVMProtocol.cpp +++ b/reflector/DMRMMDVMProtocol.cpp @@ -18,16 +18,15 @@ #include + +#include "Global.h" #include "DMRMMDVMClient.h" #include "DMRMMDVMProtocol.h" -#include "Reflector.h" -#include "GateKeeper.h" #include "BPTC19696.h" #include "RS129.h" #include "Golay2087.h" #include "QR1676.h" - //////////////////////////////////////////////////////////////////////////////////////// // define @@ -49,6 +48,7 @@ static uint8_t g_DmrSyncMSData[] = { 0x0D,0x5D,0x7F,0x77,0xFD,0x75,0x70 }; bool CDmrmmdvmProtocol::Initialize(const char *type, const EProtocol ptype, const uint16_t port, const bool has_ipv4, const bool has_ipv6) { + m_DefaultId = g_Conf.GetUnsigned(g_Conf.j.mmdvm.defaultid); // base class if (! CProtocol::Initialize(type, ptype, port, has_ipv4, has_ipv6)) return false; @@ -93,7 +93,7 @@ void CDmrmmdvmProtocol::Task(void) if ( Receive4(Buffer, Ip, 20) ) #endif { - //Buffer.DebugDump(g_Refl..m_DebugFile); + //Buffer.DebugDump(g_Refl.m_DebugFile); // crack the packet if ( IsValidDvFramePacket(Buffer, Frames) ) { @@ -146,7 +146,7 @@ void CDmrmmdvmProtocol::Task(void) Send(Buffer, Ip); // add client if needed - CClients *clients = g_Refl..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_Refl..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_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); std::shared_ptrclient = clients->FindClient(Ip, EProtocol::dmrmmdvm); if ( client != nullptr ) { clients->RemoveClient(client); } - g_Refl..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_Refl..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_Refl..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_Refl..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_Refl..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_Refl..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_Refl..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_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); // update last heard if ( lastheard ) { - g_Refl..GetUsers()->Hearing(my, rpt1, rpt2); - g_Refl..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_Refl..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_Refl..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_Refl..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_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -696,7 +696,7 @@ bool CDmrmmdvmProtocol::IsValidDvFramePacket(const CBuffer &Buffer, std::arraydata()[33]), 7); - //dump.DebugDump(g_Refl..m_DebugFile); + //dump.DebugDump(g_Refl.m_DebugFile); // BER Buffer->Append((uint8_t)0); @@ -982,7 +982,7 @@ char CDmrmmdvmProtocol::DmrDstIdToModule(uint32_t tg) const if (tg > 4000 && tg < 4027) { const char mod = 'A' + (tg - 4001U); - if (strchr(ACTIVE_MODULES, mod)) + if (g_Refl.IsValidModule(mod)) { return mod; } diff --git a/reflector/DMRMMDVMProtocol.h b/reflector/DMRMMDVMProtocol.h index da8086b..17864c7 100644 --- a/reflector/DMRMMDVMProtocol.h +++ b/reflector/DMRMMDVMProtocol.h @@ -18,6 +18,7 @@ #pragma once +#include "Defines.h" #include "Timer.h" #include "Protocol.h" #include "DVHeaderPacket.h" @@ -117,4 +118,7 @@ protected: // for authentication uint32_t m_uiAuthSeed; + + // config data + unsigned m_DefaultId; }; diff --git a/reflector/DMRPlusClient.h b/reflector/DMRPlusClient.h index e0e284c..6cf6868 100644 --- a/reflector/DMRPlusClient.h +++ b/reflector/DMRPlusClient.h @@ -18,6 +18,7 @@ #pragma once +#include "Defines.h" #include "Client.h" class CDmrplusClient : public CClient diff --git a/reflector/DMRPlusProtocol.cpp b/reflector/DMRPlusProtocol.cpp index db96a50..224635f 100644 --- a/reflector/DMRPlusProtocol.cpp +++ b/reflector/DMRPlusProtocol.cpp @@ -18,11 +18,10 @@ #include + +#include "Global.h" #include "DMRPlusClient.h" #include "DMRPlusProtocol.h" -#include "Reflector.h" -#include "GateKeeper.h" -#include "DMRIdDir.h" #include "BPTC19696.h" #include "RS129.h" #include "Golay2087.h" @@ -111,7 +110,7 @@ void CDmrplusProtocol::Task(void) Send(Buffer, Ip); // add client if needed - CClients *clients = g_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); std::shared_ptrclient = clients->FindClient(Callsign, Ip, EProtocol::dmrplus); // client already connected ? if ( client == nullptr ) @@ -126,7 +125,7 @@ void CDmrplusProtocol::Task(void) client->Alive(); } // and done - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); } else { @@ -141,13 +140,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_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); std::shared_ptrclient = clients->FindClient(Ip, EProtocol::dmrplus); if ( client != nullptr ) { clients->RemoveClient(client); } - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); } else { @@ -196,21 +195,21 @@ void CDmrplusProtocol::OnDvHeaderPacketIn(std::unique_ptr &Head // no stream open yet, open a new one // find this client - std::shared_ptrclient = g_Refl..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_Refl..OpenStream(Header, client)) != nullptr ) + if ( (stream = g_Refl.OpenStream(Header, client)) != nullptr ) { // keep the handle m_Streams[stream->GetStreamId()] = stream; } } // release - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); // update last heard - g_Refl..GetUsers()->Hearing(my, rpt1, rpt2); - g_Refl..ReleaseUsers(); + g_Refl.GetUsers()->Hearing(my, rpt1, rpt2); + g_Refl.ReleaseUsers(); } } @@ -268,7 +267,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_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::dmrplus, it)) != nullptr ) @@ -280,10 +279,10 @@ void CDmrplusProtocol::HandleQueue(void) Send(buffer, client->GetIp()); } } - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); // debug - //buffer.DebugDump(g_Refl..m_DebugFile); + //buffer.DebugDump(g_Refl.m_DebugFile); } } m_Queue.Unlock(); @@ -294,7 +293,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_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::dmrplus, it)) != nullptr ) @@ -306,10 +305,10 @@ void CDmrplusProtocol::SendBufferToClients(const CBuffer &buffer, uint8_t module Send(buffer, client->GetIp()); } } - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); // debug - //buffer.DebugDump(g_Refl..m_DebugFile); + //buffer.DebugDump(g_Refl.m_DebugFile); } } @@ -324,7 +323,7 @@ void CDmrplusProtocol::HandleKeepalives(void) // and disconnect them if not // iterate on clients - CClients *clients = g_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::dmrplus, it)) != nullptr ) @@ -349,7 +348,7 @@ void CDmrplusProtocol::HandleKeepalives(void) } } - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -642,7 +641,7 @@ char CDmrplusProtocol::DmrDstIdToModule(uint32_t tg) const // is it a 4xxx ? if (tg > 4000 && tg < 4027) { char mod = 'A' + (tg - 4001U); - if (strchr(ACTIVE_MODULES, mod)) + if (g_Refl.IsValidModule(mod)) { return mod; } diff --git a/reflector/DMRPlusProtocol.h b/reflector/DMRPlusProtocol.h index 83113d9..bf0cca9 100644 --- a/reflector/DMRPlusProtocol.h +++ b/reflector/DMRPlusProtocol.h @@ -18,6 +18,7 @@ #pragma once +#include "Defines.h" #include "Timer.h" #include "Protocol.h" #include "DVHeaderPacket.h" diff --git a/reflector/DPlusClient.h b/reflector/DPlusClient.h index 4c7bb6e..5e68171 100644 --- a/reflector/DPlusClient.h +++ b/reflector/DPlusClient.h @@ -18,6 +18,7 @@ #pragma once +#include "Defines.h" #include "Client.h" class CDplusClient : public CClient diff --git a/reflector/DPlusProtocol.cpp b/reflector/DPlusProtocol.cpp index a162229..bf00561 100644 --- a/reflector/DPlusProtocol.cpp +++ b/reflector/DPlusProtocol.cpp @@ -18,11 +18,10 @@ #include + +#include "Global.h" #include "DPlusClient.h" #include "DPlusProtocol.h" -#include "Reflector.h" -#include "GateKeeper.h" - //////////////////////////////////////////////////////////////////////////////////////// // operation @@ -97,8 +96,8 @@ void CDplusProtocol::Task(void) Send(Buffer, Ip); // create the client and append - g_Refl..GetClients()->AddClient(std::make_shared(Callsign, Ip)); - g_Refl..ReleaseClients(); + g_Refl.GetClients()->AddClient(std::make_shared(Callsign, Ip)); + g_Refl.ReleaseClients(); } else { @@ -113,7 +112,7 @@ void CDplusProtocol::Task(void) std::cout << "DPlus disconnect packet from " << Ip << std::endl; // find client - CClients *clients = g_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); std::shared_ptrclient = clients->FindClient(Ip, EProtocol::dplus); if ( client != nullptr ) { @@ -123,21 +122,21 @@ void CDplusProtocol::Task(void) EncodeDisconnectPacket(&Buffer); Send(Buffer, Ip); } - g_Refl..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_Refl..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_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); } else { @@ -185,10 +184,10 @@ void CDplusProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header CCallsign rpt2(Header->GetRpt2Callsign()); // first, check module is valid - if ( g_Refl..IsValidModule(rpt2.GetCSModule()) ) + if ( g_Refl.IsValidModule(rpt2.GetCSModule()) ) { // find this client - std::shared_ptrclient = g_Refl..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 +203,18 @@ void CDplusProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header // get client callsign rpt1 = client->GetCallsign(); // and try to open the stream - if ( (stream = g_Refl..OpenStream(Header, client)) != nullptr ) + if ( (stream = g_Refl.OpenStream(Header, client)) != nullptr ) { // keep the handle m_Streams[stream->GetStreamId()] = stream; } } // release - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); // update last heard - g_Refl..GetUsers()->Hearing(my, rpt1, rpt2); - g_Refl..ReleaseUsers(); + g_Refl.GetUsers()->Hearing(my, rpt1, rpt2); + g_Refl.ReleaseUsers(); } else { @@ -253,7 +252,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_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::dplus, it)) != nullptr ) @@ -290,7 +289,7 @@ void CDplusProtocol::HandleQueue(void) } } } - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); } } m_Queue.Unlock(); @@ -343,7 +342,7 @@ void CDplusProtocol::HandleKeepalives(void) EncodeKeepAlivePacket(&keepalive); // iterate on clients - CClients *clients = g_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::dplus, it)) != nullptr ) @@ -371,7 +370,7 @@ void CDplusProtocol::HandleKeepalives(void) clients->RemoveClient(client); } } - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); } //////////////////////////////////////////////////////////////////////////////////////// diff --git a/reflector/DPlusProtocol.h b/reflector/DPlusProtocol.h index 8b151e5..47a3ff1 100644 --- a/reflector/DPlusProtocol.h +++ b/reflector/DPlusProtocol.h @@ -18,6 +18,7 @@ #pragma once +#include "Defines.h" #include "Timer.h" #include "SEProtocol.h" #include "DVHeaderPacket.h" diff --git a/reflector/DVFramePacket.cpp b/reflector/DVFramePacket.cpp index 86f1d61..3bf7a94 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 #include #include "DVFramePacket.h" diff --git a/reflector/DVHeaderPacket.cpp b/reflector/DVHeaderPacket.cpp index 7bf6082..0e09db0 100644 --- a/reflector/DVHeaderPacket.cpp +++ b/reflector/DVHeaderPacket.cpp @@ -18,10 +18,10 @@ #include -#include -#include "DMRIdDir.h" -#include "DVHeaderPacket.h" +#include +#include "Defines.h" +#include "DVHeaderPacket.h" //////////////////////////////////////////////////////////////////////////////////////// // constructor diff --git a/reflector/Defines.h b/reflector/Defines.h index 690b01f..862451d 100644 --- a/reflector/Defines.h +++ b/reflector/Defines.h @@ -46,25 +46,31 @@ #define DSTAR_IPV4 true #define DMR_IPV4 true #define YSF_IPV4 true -#define BM_IPV4 true +#define XLX_IPV4 true #define M17_IPV4 true +#define P25_IPV4 true +#define NXDN_IPV4 true +#define USRP_IPV4 true #define URF_IPV4 true -#define DSTAR_IPV6 true + +#define DSTAR_IPV6 true // QnetGateway can use IPv6 #define DMR_IPV6 false #define YSF_IPV6 false -#define BM_IPV6 false +#define XLX_IPV6 false #define M17_IPV6 true +#define P25_IPV6 false +#define NXDN_IPV6 false +#define USRP_IPV6 false #define URF_IPV6 true // protocols --------------------------------------------------- -enum class EProtocol { any, none, dextra, dplus, dcs, bm, urf, dmrplus, dmrmmdvm, ysf, m17 }; +enum class EProtocol { any, none, dextra, dplus, dcs, g3, bm, urf, dmrplus, dmrmmdvm, nxdn, p25, usrp, ysf, m17 }; // DExtra #define DEXTRA_KEEPALIVE_PERIOD 3 // in seconds #define DEXTRA_KEEPALIVE_TIMEOUT (DEXTRA_KEEPALIVE_PERIOD*10) // in seconds -#define DEXTRA_RECONNECT_PERIOD 5 // in seconds // DPlus #define DPLUS_KEEPALIVE_PERIOD 1 // in seconds @@ -77,7 +83,7 @@ enum class EProtocol { any, none, dextra, dplus, dcs, bm, urf, dmrplus, dmrmmdvm // XLX, used for BM #define BM_KEEPALIVE_PERIOD 1 // in seconds -#define BM_KEEPALIVE_TIMEOUT (XLX_KEEPALIVE_PERIOD*30) // in seconds +#define BM_KEEPALIVE_TIMEOUT (BM_KEEPALIVE_PERIOD*30) // in seconds #define BM_RECONNECT_PERIOD 5 // in seconds // URF @@ -89,6 +95,7 @@ enum class EProtocol { any, none, dextra, dplus, dcs, bm, urf, dmrplus, dmrmmdvm #define DMRPLUS_KEEPALIVE_PERIOD 1 // in seconds #define DMRPLUS_KEEPALIVE_TIMEOUT (DMRPLUS_KEEPALIVE_PERIOD*10) // in seconds #define DMRPLUS_REFLECTOR_SLOT DMR_SLOT2 +#define DMRPLUS_REFLECTOR_COLOUR 1 // DMRMmdvm #define DMRMMDVM_KEEPALIVE_PERIOD 10 // in seconds @@ -104,6 +111,18 @@ enum class EProtocol { any, none, dextra, dplus, dcs, bm, urf, dmrplus, dmrmmdvm #define M17_KEEPALIVE_PERIOD 3 #define M17_KEEPALIVE_TIMEOUT (M17_KEEPALIVE_PERIOD*10) +// P25 +#define P25_KEEPALIVE_PERIOD 3 // in seconds +#define P25_KEEPALIVE_TIMEOUT (P25_KEEPALIVE_PERIOD*10) // in seconds + +// NXDN +#define NXDN_KEEPALIVE_PERIOD 3 // in seconds +#define NXDN_KEEPALIVE_TIMEOUT (NXDN_KEEPALIVE_PERIOD*10) // in seconds + +// USRP +#define USRP_KEEPALIVE_PERIOD 1 // in seconds +#define USRP_KEEPALIVE_TIMEOUT (USRP_KEEPALIVE_PERIOD*10) // in seconds + // G3 Terminal #define G3_PRESENCE_PORT 12346 // UDP port #define G3_CONFIG_PORT 12345 // UDP port diff --git a/reflector/G3Client.h b/reflector/G3Client.h index d5c313d..07b2454 100644 --- a/reflector/G3Client.h +++ b/reflector/G3Client.h @@ -18,6 +18,7 @@ #pragma once +#include "Defines.h" #include "Client.h" class CG3Client : public CClient diff --git a/reflector/G3Protocol.cpp b/reflector/G3Protocol.cpp index 0d5f62c..46bcb0f 100644 --- a/reflector/G3Protocol.cpp +++ b/reflector/G3Protocol.cpp @@ -16,16 +16,14 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . - +#include +#include #include #include + +#include "Global.h" #include "G3Client.h" #include "G3Protocol.h" -#include "Reflector.h" -#include "GateKeeper.h" - -#include -#include //////////////////////////////////////////////////////////////////////////////////////// @@ -34,10 +32,14 @@ bool CG3Protocol::Initialize(const char */*type*/, const EProtocol /*type*/, const uint16_t /*port*/, const bool /*has_ipv4*/, const bool /*has_ipv6*/) // everything is hard coded until ICOM gets their act together and start supporting IPv6 { + //config data + m_TerminalPath.assign(g_Conf.GetString(g_Conf.j.files.terminal)); + const std::string ipv4address(g_Conf.GetString(g_Conf.j.ip.ipv4bind)); + ReadOptions(); // init reflector apparent callsign - m_ReflectorCallsign = g_Refl..GetCallsign(); + m_ReflectorCallsign = g_Refl.GetCallsign(); // reset stop flag keep_running = true; @@ -46,7 +48,7 @@ bool CG3Protocol::Initialize(const char */*type*/, const EProtocol /*type*/, con //m_ReflectorCallsign.PatchCallsign(0, "XLX", 3); // create our sockets - CIp ip(AF_INET, G3_DV_PORT, LISTEN_IPV4); + CIp ip(AF_INET, G3_DV_PORT, ipv4address.c_str()); if ( ip.IsSet() ) { if (! m_Socket4.Open(ip)) @@ -177,7 +179,7 @@ void CG3Protocol::PresenceTask(void) Buffer.Append(m_GwAddress); } - CClients *clients = g_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); auto it = clients->begin(); std::shared_ptrextant = nullptr; while ( (extant = clients->FindNextClient(EProtocol::g3, it)) != nullptr ) @@ -219,7 +221,7 @@ void CG3Protocol::PresenceTask(void) clients->AddClient(std::make_shared(Terminal, Ip)); } } - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); m_PresenceSocket.Send(Buffer, ReqIp); } @@ -260,7 +262,7 @@ void CG3Protocol::ConfigTask(void) if (isRepeaterCall) { - if ((Call.HasSameCallsign(GetReflectorCallsign())) && (g_Refl..IsValidModule(Call.GetCSModule()))) + if ((Call.HasSameCallsign(GetReflectorCallsign())) && (g_Refl.IsValidModule(Call.GetCSModule()))) { Buffer.data()[3] = 0x00; // ok } @@ -343,7 +345,7 @@ void CG3Protocol::IcmpTask(void) { if (iIcmpType == ICMP_DEST_UNREACH) { - CClients *clients = g_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::g3, it)) != nullptr ) @@ -354,7 +356,7 @@ void CG3Protocol::IcmpTask(void) clients->RemoveClient(client); } } - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); } } } @@ -378,7 +380,7 @@ void CG3Protocol::Task(void) { CIp ClIp; CIp *BaseIp = nullptr; - CClients *clients = g_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::g3, it)) != nullptr ) @@ -394,7 +396,7 @@ void CG3Protocol::Task(void) break; } } - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); if (BaseIp != nullptr) { @@ -454,7 +456,7 @@ void CG3Protocol::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_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::g3, it)) != nullptr ) @@ -470,7 +472,7 @@ void CG3Protocol::HandleQueue(void) } } } - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); } } m_Queue.Unlock(); @@ -487,7 +489,7 @@ void CG3Protocol::HandleKeepalives(void) CBuffer keepalive((uint8_t *)"PING", 4); // iterate on clients - CClients *clients = g_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::g3, it)) != nullptr ) @@ -502,7 +504,7 @@ void CG3Protocol::HandleKeepalives(void) Send(keepalive, client->GetIp()); } } - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -527,7 +529,7 @@ void CG3Protocol::OnDvHeaderPacketIn(std::unique_ptr &Header, c CCallsign rpt2(Header->GetRpt2Callsign()); // find this client - CClients *clients = g_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::g3, it)) != nullptr ) @@ -554,7 +556,7 @@ void CG3Protocol::OnDvHeaderPacketIn(std::unique_ptr &Header, c } else { - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); return; } } @@ -563,19 +565,19 @@ void CG3Protocol::OnDvHeaderPacketIn(std::unique_ptr &Header, c rpt1 = client->GetCallsign(); // and try to open the stream - if ( (stream = g_Refl..OpenStream(Header, client)) != nullptr ) + if ( (stream = g_Refl.OpenStream(Header, client)) != nullptr ) { // keep the handle m_Streams[stream->GetStreamId()] = stream; } // update last heard - g_Refl..GetUsers()->Hearing(my, rpt1, rpt2); - g_Refl..ReleaseUsers(); + g_Refl.GetUsers()->Hearing(my, rpt1, rpt2); + g_Refl.ReleaseUsers(); } } // release - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); } } @@ -672,14 +674,14 @@ void CG3Protocol::NeedReload(void) { struct stat fileStat; - if (::stat(TERMINALOPTIONS_PATH, &fileStat) != -1) + if (::stat(m_TerminalPath.c_str(), &fileStat) != -1) { if (m_LastModTime != fileStat.st_mtime) { ReadOptions(); // we have new options - iterate on clients for potential removal - CClients *clients = g_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::g3, it)) != nullptr ) @@ -690,7 +692,7 @@ void CG3Protocol::NeedReload(void) clients->RemoveClient(client); } } - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); } } } @@ -701,7 +703,7 @@ void CG3Protocol::ReadOptions(void) int opts = 0; - std::ifstream file(TERMINALOPTIONS_PATH); + std::ifstream file(m_TerminalPath.c_str()); if (file.is_open()) { m_GwAddress = 0u; @@ -742,12 +744,12 @@ void CG3Protocol::ReadOptions(void) } } } - std::cout << "G3 handler loaded " << opts << " options from file " << TERMINALOPTIONS_PATH << std::endl; + std::cout << "G3 handler loaded " << opts << " options from file " << m_TerminalPath << std::endl; file.close(); struct stat fileStat; - if (::stat(TERMINALOPTIONS_PATH, &fileStat) != -1) + if (::stat(m_TerminalPath.c_str(), &fileStat) != -1) { m_LastModTime = fileStat.st_mtime; } diff --git a/reflector/G3Protocol.h b/reflector/G3Protocol.h index 193e529..d9c6b73 100644 --- a/reflector/G3Protocol.h +++ b/reflector/G3Protocol.h @@ -19,6 +19,8 @@ #pragma once #include + +#include "Defines.h" #include "Timer.h" #include "SEProtocol.h" #include "DVHeaderPacket.h" @@ -117,4 +119,5 @@ protected: uint32_t m_GwAddress; std::string m_Modules; time_t m_LastModTime; + std::string m_TerminalPath; }; diff --git a/reflector/GateKeeper.cpp b/reflector/GateKeeper.cpp index 2e96e04..ce357dd 100644 --- a/reflector/GateKeeper.cpp +++ b/reflector/GateKeeper.cpp @@ -18,7 +18,7 @@ #include "Timer.h" -#include "GateKeeper.h" +#include "Global.h" //////////////////////////////////////////////////////////////////////////////////////// @@ -49,9 +49,9 @@ bool CGateKeeper::Init(void) { // load lists from files - m_NodeWhiteList.LoadFromFile(WHITELIST_PATH); - m_NodeBlackList.LoadFromFile(BLACKLIST_PATH); - m_PeerList.LoadFromFile(INTERLINKLIST_PATH); + m_NodeWhiteList.LoadFromFile(g_Conf.GetString(g_Conf.j.files.white)); + m_NodeBlackList.LoadFromFile(g_Conf.GetString(g_Conf.j.files.black)); + m_PeerList.LoadFromFile(g_Conf.GetString(g_Conf.j.files.interlink)); // reset run flag keep_running = true; diff --git a/reflector/LookupDmr.cpp b/reflector/LookupDmr.cpp index af61349..2e64812 100644 --- a/reflector/LookupDmr.cpp +++ b/reflector/LookupDmr.cpp @@ -21,11 +21,7 @@ #include #include -#include "Reflector.h" -#include "LookupDmr.h" - -extern CReflector g_ref; -extern CConfigure g_cfg; +#include "Global.h" void CLookupDmr::ClearContents() { @@ -35,11 +31,11 @@ void CLookupDmr::ClearContents() void CLookupDmr::LoadParameters() { - g_cfg.GetRefreshType(g_cfg.j.dmriddb.mode, m_Type); - g_cfg.GetUnsigned(g_cfg.j.dmriddb.refreshmin, m_Refresh); - g_cfg.GetString(g_cfg.j.dmriddb.filepath, m_Path); - g_cfg.GetString(g_cfg.j.dmriddb.hostname, m_Host); - g_cfg.GetString(g_cfg.j.dmriddb.suffix, m_Suffix); + m_Type = g_Conf.GetRefreshType(g_Conf.j.dmriddb.mode); + m_Refresh = g_Conf.GetUnsigned(g_Conf.j.dmriddb.refreshmin); + m_Path.assign(g_Conf.GetString(g_Conf.j.dmriddb.filepath)); + m_Host.assign(g_Conf.GetString(g_Conf.j.dmriddb.hostname)); + m_Suffix.assign(g_Conf.GetString(g_Conf.j.dmriddb.suffix)); } uint32_t CLookupDmr::FindDmrid(const CCallsign &callsign) @@ -204,7 +200,7 @@ bool CLookupDmr::HttpGet(const char *hostname, const char *filename, int port, C { // 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, g_ref.GetCallsign().GetCS().c_str()); + ::sprintf(request, "GET /%s HTTP/1.0\r\nFrom: %s\r\nUser-Agent: urfd\r\n\r\n", filename, g_Conf.GetString(g_Conf.j.names.cs).c_str()); ::write(sock_id, request, strlen(request)); // config receive timeouts diff --git a/reflector/LookupNxdn.cpp b/reflector/LookupNxdn.cpp index 624cdbd..ee0da2a 100644 --- a/reflector/LookupNxdn.cpp +++ b/reflector/LookupNxdn.cpp @@ -21,11 +21,7 @@ #include #include -#include "Reflector.h" -#include "LookupNxdn.h" - -extern CReflector g_ref; -extern CConfigure g_cfg; +#include "Global.h" void CLookupNxdn::ClearContents() { @@ -35,11 +31,11 @@ void CLookupNxdn::ClearContents() void CLookupNxdn::LoadParameters() { - g_cfg.GetRefreshType(g_cfg.j.nxdniddb.mode, m_Type); - g_cfg.GetUnsigned(g_cfg.j.nxdniddb.refreshmin, m_Refresh); - g_cfg.GetString(g_cfg.j.nxdniddb.filepath, m_Path); - g_cfg.GetString(g_cfg.j.dmriddb.hostname, m_Host); - g_cfg.GetString(g_cfg.j.nxdniddb.suffix, m_Suffix); + m_Type = g_Conf.GetRefreshType(g_Conf.j.nxdniddb.mode); + m_Refresh = g_Conf.GetUnsigned(g_Conf.j.nxdniddb.refreshmin); + m_Path.assign(g_Conf.GetString(g_Conf.j.nxdniddb.filepath)); + m_Host.assign(g_Conf.GetString(g_Conf.j.nxdniddb.hostname)); + m_Suffix.assign(g_Conf.GetString(g_Conf.j.nxdniddb.suffix)); } const CCallsign *CLookupNxdn::FindCallsign(uint16_t nxdnid) @@ -206,7 +202,7 @@ bool CLookupNxdn::HttpGet(const char *hostname, const char *filename, int port, { // send the GET request char request[NXDNID_HTTPGET_SIZEMAX]; - ::sprintf(request, "GET /%s HTTP/1.0\r\nFrom: %s\r\nUser-Agent: urfd\r\n\r\n", filename, (const char *)g_ref.GetCallsign()); + ::sprintf(request, "GET /%s HTTP/1.0\r\nFrom: %s\r\nUser-Agent: urfd\r\n\r\n", filename, g_Conf.GetString(g_Conf.j.names.cs).c_str()); ::write(sock_id, request, strlen(request)); // config receive timeouts diff --git a/reflector/LookupYsf.cpp b/reflector/LookupYsf.cpp index 96e556c..7b389e4 100644 --- a/reflector/LookupYsf.cpp +++ b/reflector/LookupYsf.cpp @@ -22,11 +22,7 @@ #include #include -#include "Reflector.h" -#include "LookupYsf.h" - -extern CReflector g_ref; -extern CConfigure g_cfg; +#include "Global.h" void CLookupYsf::ClearContents() { @@ -35,13 +31,13 @@ void CLookupYsf::ClearContents() void CLookupYsf::LoadParameters() { - g_cfg.GetRefreshType(g_cfg.j.ysftxrxdb.mode, m_Type); - g_cfg.GetUnsigned(g_cfg.j.ysftxrxdb.refreshmin, m_Refresh); - g_cfg.GetString(g_cfg.j.ysftxrxdb.filepath, m_Path); - g_cfg.GetString(g_cfg.j.ysftxrxdb.hostname, m_Host); - g_cfg.GetString(g_cfg.j.ysftxrxdb.suffix, m_Suffix); - g_cfg.GetUnsigned(g_cfg.j.ysf.defaulttxfreq, m_DefaultTx); - g_cfg.GetUnsigned(g_cfg.j.ysf.defaultrxfreq, m_DefaultRx); + m_Type = g_Conf.GetRefreshType(g_Conf.j.ysftxrxdb.mode); + m_Refresh = g_Conf.GetUnsigned(g_Conf.j.ysftxrxdb.refreshmin); + m_Path.assign(g_Conf.GetString(g_Conf.j.ysftxrxdb.filepath)); + m_Host.assign(g_Conf.GetString(g_Conf.j.ysftxrxdb.hostname)); + m_Suffix.assign(g_Conf.GetString(g_Conf.j.ysftxrxdb.suffix)); + m_DefaultTx = g_Conf.GetUnsigned(g_Conf.j.ysf.defaulttxfreq); + m_DefaultRx = g_Conf.GetUnsigned(g_Conf.j.ysf.defaultrxfreq); } bool CLookupYsf::LoadContentFile(CBuffer &buffer) @@ -182,7 +178,7 @@ bool CLookupYsf::HttpGet(const char *hostname, const char *filename, int port, C { // send the GET request char request[YSFNODE_HTTPGET_SIZEMAX]; - sprintf(request, "GET /%s HTTP/1.0\r\nFrom: %s\r\nUser-Agent: urfd\r\n\r\n", filename, g_ref.GetCallsign().GetCS().c_str()); + sprintf(request, "GET /%s HTTP/1.0\r\nFrom: %s\r\nUser-Agent: urfd\r\n\r\n", filename, g_Conf.GetString(g_Conf.j.names.cs).c_str()); write(sock_id, request, strlen(request)); // config receive timeouts diff --git a/reflector/LookupYsf.h b/reflector/LookupYsf.h index 3501309..265511a 100644 --- a/reflector/LookupYsf.h +++ b/reflector/LookupYsf.h @@ -40,4 +40,6 @@ private: CsNodeMap m_map; bool HttpGet(const char *, const char *, int, CBuffer &); + + unsigned m_DefaultTx, m_DefaultRx; }; diff --git a/reflector/M17Client.h b/reflector/M17Client.h index 407090e..2186fa0 100644 --- a/reflector/M17Client.h +++ b/reflector/M17Client.h @@ -16,15 +16,9 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +#include "Defines.h" #include "Client.h" -//////////////////////////////////////////////////////////////////////////////////////// -// define - - -//////////////////////////////////////////////////////////////////////////////////////// -// class - class CM17Client : public CClient { public: diff --git a/reflector/M17Protocol.cpp b/reflector/M17Protocol.cpp index ce3b1b8..fcbfce9 100644 --- a/reflector/M17Protocol.cpp +++ b/reflector/M17Protocol.cpp @@ -21,8 +21,7 @@ #include "M17Client.h" #include "M17Protocol.h" #include "M17Packet.h" -#include "Reflector.h" -#include "GateKeeper.h" +#include "Global.h" //////////////////////////////////////////////////////////////////////////////////////// // operation @@ -93,17 +92,17 @@ void CM17Protocol::Task(void) std::cout << "M17 connect packet for module " << ToLinkModule << " from " << Callsign << " at " << Ip << std::endl; // callsign authorized? - if ( g_Gate.MayLink(Callsign, Ip, EProtocol::m17) && g_Refl..IsValidModule(ToLinkModule) ) + if ( g_Gate.MayLink(Callsign, Ip, EProtocol::m17) && g_Refl.IsValidModule(ToLinkModule) ) { // valid module ? - if ( g_Refl..IsValidModule(ToLinkModule) ) + if ( g_Refl.IsValidModule(ToLinkModule) ) { // acknowledge the request Send("ACKN", Ip); // create the client and append - g_Refl..GetClients()->AddClient(std::make_shared(Callsign, Ip, ToLinkModule)); - g_Refl..ReleaseClients(); + g_Refl.GetClients()->AddClient(std::make_shared(Callsign, Ip, ToLinkModule)); + g_Refl.ReleaseClients(); } else { @@ -125,7 +124,7 @@ void CM17Protocol::Task(void) std::cout << "M17 disconnect packet from " << Callsign << " at " << Ip << std::endl; // find client - CClients *clients = g_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); std::shared_ptrclient = clients->FindClient(Ip, EProtocol::m17); if ( client != nullptr ) { @@ -134,19 +133,19 @@ void CM17Protocol::Task(void) // and acknowledge the disconnect Send("DISC", Ip); } - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); } else if ( IsValidKeepAlivePacket(Buffer, Callsign) ) { // find all clients with that callsign & ip and keep them alive - CClients *clients = g_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(Callsign, Ip, EProtocol::m17, it)) != nullptr ) { client->Alive(); } - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); } else { @@ -196,24 +195,24 @@ void CM17Protocol::OnDvHeaderPacketIn(std::unique_ptr &Header, CCallsign rpt2(Header->GetRpt2Callsign()); // find this client - std::shared_ptrclient = g_Refl..GetClients()->FindClient(Ip, EProtocol::m17); + std::shared_ptrclient = g_Refl.GetClients()->FindClient(Ip, EProtocol::m17); if ( client ) { // get client callsign rpt1 = client->GetCallsign(); // and try to open the stream - if ( (stream = g_Refl..OpenStream(Header, client)) != nullptr ) + if ( (stream = g_Refl.OpenStream(Header, client)) != nullptr ) { // keep the handle m_Streams[stream->GetStreamId()] = stream; } } // release - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); // update last heard - g_Refl..GetUsers()->Hearing(my, rpt1, rpt2); - g_Refl..ReleaseUsers(); + g_Refl.GetUsers()->Hearing(my, rpt1, rpt2); + g_Refl.ReleaseUsers(); } } @@ -249,7 +248,7 @@ void CM17Protocol::HandleQueue(void) EncodeM17Packet(frame, m_StreamsCache[module].m_dvHeader, (CDvFramePacket *)packet.get(), m_StreamsCache[module].m_iSeqCounter); // push it to all our clients linked to the module and who are not streaming in - CClients *clients = g_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::m17, it)) != nullptr ) @@ -266,7 +265,7 @@ void CM17Protocol::HandleQueue(void) } } - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); } m_StreamsCache[module].m_iSeqCounter++; } @@ -286,7 +285,7 @@ void CM17Protocol::HandleKeepalives(void) EncodeKeepAlivePacket(keepalive); // iterate on clients - CClients *clients = g_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::m17, it)) != nullptr ) @@ -312,7 +311,7 @@ void CM17Protocol::HandleKeepalives(void) } } - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -389,7 +388,7 @@ void CM17Protocol::EncodeKeepAlivePacket(CBuffer &Buffer) { Buffer.resize(10); memcpy(Buffer.data(), "PING", 4); - g_Refl..GetCallsign().CodeOut(Buffer.data() + 4); + g_Refl.GetCallsign().CodeOut(Buffer.data() + 4); } void CM17Protocol::EncodeM17Packet(SM17Frame &frame, const CDvHeaderPacket &Header, const CDvFramePacket *DvFrame, uint32_t iSeq) const diff --git a/reflector/M17Protocol.h b/reflector/M17Protocol.h index 5e9e2c7..61c21ea 100644 --- a/reflector/M17Protocol.h +++ b/reflector/M17Protocol.h @@ -18,6 +18,7 @@ #pragma once +#include "Defines.h" #include "Timer.h" #include "Protocol.h" #include "DVHeaderPacket.h" diff --git a/reflector/Makefile b/reflector/Makefile index ea751fa..8a2a1f8 100644 --- a/reflector/Makefile +++ b/reflector/Makefile @@ -18,55 +18,37 @@ # if you change these locations, make sure the sgs.service file is updated! # you will also break hard coded paths in the dashboard file, index.php. -include configure.mk +EXE = urfd -# if you make changed in these two variable, you'll need to change things -# in the main.h file as well as the systemd service file. -BINDIR = /usr/local/bin -CFGDIR = /usr/local/etc +INICHECK = inicheck -CC = g++ +include configure.mk ifeq ($(debug), true) -CFLAGS = -ggdb3 -W -Werror -Wno-psabi -c -std=c++11 -MMD -MD -c +CFLAGS = -ggdb3 -W -Werror -c -std=c++11 -MMD -MD else -CFLAGS = -c -W -Werror -Wno-psabi -std=c++11 -MMD -MD -c +CFLAGS = -W -Werror -std=c++11 -MMD -MD endif -LDFLAGS=-pthread - -URFSRCS = Buffer.cpp Callsign.cpp CallsignList.cpp CallsignListItem.cpp Client.cpp Clients.cpp DCSClient.cpp DCSProtocol.cpp DExtraClient.cpp DExtraPeer.cpp DExtraProtocol.cpp DPlusClient.cpp DPlusProtocol.cpp DVFramePacket.cpp DVHeaderPacket.cpp GateKeeper.cpp IP.cpp Notification.cpp Packet.cpp PacketStream.cpp PeerCallsignList.cpp Peer.cpp Peers.cpp Protocol.cpp Protocols.cpp Reflector.cpp SEProtocol.cpp UDPSocket.cpp User.cpp Users.cpp Version.cpp Main.cpp BMClient.cpp BMPeer.cpp BMProtocol.cpp BPTC19696.cpp CRC.cpp DMRIdDir.cpp DMRIdDirFile.cpp DMRIdDirHttp.cpp NXDNIdDir.cpp NXDNIdDirFile.cpp NXDNIdDirHttp.cpp DMRMMDVMClient.cpp DMRMMDVMProtocol.cpp DMRPlusClient.cpp DMRPlusProtocol.cpp Golay2087.cpp Golay24128.cpp Hamming.cpp M17Client.cpp M17CRC.cpp M17Packet.cpp M17Client.cpp M17Protocol.cpp NXDNClient.cpp NXDNProtocol.cpp P25Client.cpp P25Protocol.cpp QR1676.cpp RS129.cpp Semaphore.cpp USRPClient.cpp USRPProtocol.cpp Utils.cpp WiresXCmd.cpp WiresXCmdHandler.cpp WiresXInfo.cpp URFClient.cpp URFProtocol.cpp URFPeer.cpp YSFClient.cpp YSFConvolution.cpp YSFFich.cpp YSFNode.cpp YSFNodeDir.cpp YSFNodeDirFile.cpp YSFNodeDirHttp.cpp YSFPayload.cpp YSFProtocol.cpp YSFUtils.cpp - -G3SRCS = G3Client.cpp G3Protocol.cpp RawSocket.cpp UDPMsgSocket.cpp - -SRCS = $(URFSRCS) -ifeq ($(use_g3), true) -SRCS += $(G3SRCS) -endif - -ifeq ($(ysf_db), true) -LDFLAGS += `mysql_config --libs` -endif - -ifdef tc_ip -SRCS += CodecStream.cpp UnixDgramSocket.cpp -endif +LDFLAGS=-pthread -lcurl +SRCS = $(wildcard *.cpp) OBJS = $(SRCS:.cpp=.o) DEPS = $(SRCS:.cpp=.d) -EXE=urfd - -all : $(EXE) +all : $(EXE) $(INICHECK) $(EXE) : $(OBJS) - $(CC) $^ -o $@ $(LDFLAGS) + $(CXX) $^ -o $@ $(LDFLAGS) + +$(INICHECK) : Configure.cpp Configure.h + $(CXX) -DINICHECK $(CFLAGS) $< -o $(INICHECK) -lcurl %.o : %.cpp - g++ $(CFLAGS) $< -o $@ + $(CXX) $(CFLAGS) -c $< -o $@ clean : - $(RM) *.o *.d urfd + $(RM) *.o *.d $(EXE) $(INICHECK) -include $(DEPS) @@ -74,9 +56,7 @@ install : ln -f -s $(shell pwd)/$(EXE).blacklist $(CFGDIR)/$(EXE).blacklist ln -f -s $(shell pwd)/$(EXE).whitelist $(CFGDIR)/$(EXE).whitelist ln -f -s $(shell pwd)/$(EXE).interlink $(CFGDIR)/$(EXE).interlink -ifeq ($(use_g3), true) ln -f -s $(shell pwd)/$(EXE).terminal $(CFGDIR)/$(EXE).terminal -endif cp -f ../systemd/$(EXE).service /etc/systemd/system/ cp -f $(EXE) $(BINDIR) systemctl enable $(EXE).service diff --git a/reflector/NXDNClient.h b/reflector/NXDNClient.h index e75c118..fb809cb 100644 --- a/reflector/NXDNClient.h +++ b/reflector/NXDNClient.h @@ -19,7 +19,9 @@ #pragma once +#include "Defines.h" #include "Client.h" + class CNXDNClient : public CClient { public: diff --git a/reflector/NXDNProtocol.cpp b/reflector/NXDNProtocol.cpp index 8b2fcfc..66f43ce 100644 --- a/reflector/NXDNProtocol.cpp +++ b/reflector/NXDNProtocol.cpp @@ -22,9 +22,8 @@ #include "NXDNClient.h" #include "NXDNProtocol.h" #include "YSFDefines.h" -#include "Reflector.h" -#include "GateKeeper.h" #include "Golay24128.h" +#include "Global.h" const uint8_t NXDN_LICH_RFCT_RDCH = 2U; const uint8_t NXDN_LICH_USC_SACCH_NS = 0U; @@ -53,6 +52,10 @@ CNXDNProtocol::CNXDNProtocol() bool CNXDNProtocol::Initialize(const char *type, const EProtocol ptype, const uint16_t port, const bool has_ipv4, const bool has_ipv6) { + // config value + m_ReflectorId = g_Conf.GetUnsigned(g_Conf.j.nxdn.reflectorid); + m_AutolinkModule = g_Conf.GetAutolinkModule(g_Conf.j.nxdn.autolinkmod); + // base class if (! CProtocol::Initialize(type, ptype, port, has_ipv4, has_ipv6)) return false; @@ -119,7 +122,7 @@ void CNXDNProtocol::Task(void) if ( g_Gate.MayLink(Callsign, Ip, EProtocol::nxdn) ) { // add client if needed - CClients *clients = g_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); std::shared_ptrclient = clients->FindClient(Callsign, Ip, EProtocol::nxdn); // client already connected ? if ( client == nullptr ) @@ -130,9 +133,8 @@ void CNXDNProtocol::Task(void) auto newclient = std::make_shared(Callsign, Ip); // aautolink, if enabled -#if NXDN_AUTOLINK_ENABLE - newclient->SetReflectorModule(NXDN_AUTOLINK_MODULE); -#endif + if (m_AutolinkModule) + newclient->SetReflectorModule(m_AutolinkModule); // and append clients->AddClient(newclient); @@ -145,7 +147,7 @@ void CNXDNProtocol::Task(void) // acknowledge the request -- NXDNReflector simply echoes the packet Send(Buffer, Ip); // and done - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); } } else if ( IsValidDisconnectPacket(Buffer) ) @@ -153,14 +155,14 @@ void CNXDNProtocol::Task(void) std::cout << "NXDN disconnect packet from " << Ip << std::endl; // find client - CClients *clients = g_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); std::shared_ptrclient = clients->FindClient(Ip, EProtocol::nxdn); if ( client != nullptr ) { // remove it clients->RemoveClient(client); } - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); } else { @@ -210,7 +212,7 @@ void CNXDNProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header, CCallsign rpt2(Header->GetRpt2Callsign()); // find this client - std::shared_ptrclient = g_Refl..GetClients()->FindClient(Ip, EProtocol::nxdn); + std::shared_ptrclient = g_Refl.GetClients()->FindClient(Ip, EProtocol::nxdn); if ( client ) { // get client callsign @@ -221,20 +223,20 @@ void CNXDNProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header, rpt2.SetCSModule(m); // and try to open the stream - if ( (stream = g_Refl..OpenStream(Header, client)) != nullptr ) + if ( (stream = g_Refl.OpenStream(Header, client)) != nullptr ) { // keep the handle m_Streams[stream->GetStreamId()] = stream; } } // release - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); // update last heard - if ( g_Refl..IsValidModule(rpt2.GetCSModule()) ) + if ( g_Refl.IsValidModule(rpt2.GetCSModule()) ) { - g_Refl..GetUsers()->Hearing(my, rpt1, rpt2); - g_Refl..ReleaseUsers(); + g_Refl.GetUsers()->Hearing(my, rpt1, rpt2); + g_Refl.ReleaseUsers(); } } } @@ -292,7 +294,7 @@ void CNXDNProtocol::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_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::nxdn, it)) != nullptr ) @@ -305,7 +307,7 @@ void CNXDNProtocol::HandleQueue(void) } } - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); } } m_Queue.Unlock(); @@ -321,7 +323,7 @@ void CNXDNProtocol::HandleKeepalives(void) // and disconnect them if not // iterate on clients - CClients *clients = g_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::nxdn, it)) != nullptr ) @@ -341,7 +343,7 @@ void CNXDNProtocol::HandleKeepalives(void) } } - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -479,7 +481,7 @@ bool CNXDNProtocol::EncodeNXDNHeaderPacket(const CDvHeaderPacket &Header, CBuffe { Buffer.resize(43); uint16_t NXDNId = Header.GetMyCallsign().GetNXDNid(); - uint16_t RptrId = NXDN_REFID; + uint16_t RptrId = m_ReflectorId; memcpy(Buffer.data(), "NXDND", 5); Buffer.data()[5U] = (NXDNId >> 8) & 0xFFU; @@ -535,7 +537,7 @@ bool CNXDNProtocol::EncodeNXDNPacket(const CDvHeaderPacket &Header, uint32_t seq uint8_t ambe[28]; Buffer.resize(43); uint16_t NXDNId = Header.GetMyCallsign().GetNXDNid(); - uint16_t RptrId = NXDN_REFID; + uint16_t RptrId = m_ReflectorId; memcpy(Buffer.data(), "NXDND", 5); Buffer.data()[5U] = (NXDNId >> 8) & 0xFFU; diff --git a/reflector/NXDNProtocol.h b/reflector/NXDNProtocol.h index 66c6896..ceb5dd6 100644 --- a/reflector/NXDNProtocol.h +++ b/reflector/NXDNProtocol.h @@ -19,6 +19,7 @@ #pragma once +#include "Defines.h" #include "Timer.h" #include "Protocol.h" #include "DVHeaderPacket.h" @@ -80,10 +81,10 @@ protected: // uiStreamId helpers uint32_t IpToStreamId(const CIp &) const; - + void encode(const unsigned char*, unsigned char*) const; void decode(const unsigned char*, unsigned char*) const; - + uint8_t get_lich_fct(uint8_t); void set_lich_rfct(uint8_t); void set_lich_fct(uint8_t); @@ -121,4 +122,7 @@ protected: uint8_t m_lich; uint8_t m_sacch[5]; uint8_t m_layer3[22]; + + uint16_t m_ReflectorId; + char m_AutolinkModule; }; diff --git a/reflector/NotificationQueue.h b/reflector/NotificationQueue.h index 57839ad..70b894a 100644 --- a/reflector/NotificationQueue.h +++ b/reflector/NotificationQueue.h @@ -32,12 +32,6 @@ class CNotificationQueue { public: - // constructor - CNotificationQueue() {} - - // destructor - ~CNotificationQueue() {} - // lock void Lock() { m_Mutex.lock(); } void Unlock() { m_Mutex.unlock(); } diff --git a/reflector/P25Client.h b/reflector/P25Client.h index 7532a92..aafce95 100644 --- a/reflector/P25Client.h +++ b/reflector/P25Client.h @@ -18,8 +18,9 @@ // along with this program. If not, see . #pragma once - +#include "Defines.h" #include "Client.h" + class CP25Client : public CClient { public: diff --git a/reflector/P25Protocol.cpp b/reflector/P25Protocol.cpp index e50e007..38f86b6 100644 --- a/reflector/P25Protocol.cpp +++ b/reflector/P25Protocol.cpp @@ -22,8 +22,7 @@ #include "P25Client.h" #include "P25Protocol.h" -#include "Reflector.h" -#include "GateKeeper.h" +#include "Global.h" const uint8_t REC62[] = {0x62U, 0x02U, 0x02U, 0x0CU, 0x0BU, 0x12U, 0x64U, 0x00U, 0x00U, 0x80U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,0x00U, 0x00U, 0x00U, 0x00U, 0x00U}; const uint8_t REC63[] = {0x63U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x02U}; @@ -50,6 +49,11 @@ const uint8_t REC80[] = {0x80U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, bool CP25Protocol::Initialize(const char *type, const EProtocol ptype, const uint16_t port, const bool has_ipv4, const bool has_ipv6) { + // config data + m_ReflectorId = g_Conf.GetUnsigned(g_Conf.j.p25.reflectorid); + m_DefaultId = g_Conf.GetUnsigned(g_Conf.j.mmdvm.defaultid); + m_AutolinkModule = g_Conf.GetAutolinkModule(g_Conf.j.p25.autolinkmod); + m_uiStreamId = 0; // base class if (! CProtocol::Initialize(type, ptype, port, has_ipv4, has_ipv6)) @@ -107,7 +111,7 @@ void CP25Protocol::Task(void) if ( g_Gate.MayLink(Callsign, Ip, EProtocol::p25) ) { // add client if needed - CClients *clients = g_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); std::shared_ptrclient = clients->FindClient(Callsign, Ip, EProtocol::p25); // client already connected ? if ( client == nullptr ) @@ -118,9 +122,8 @@ void CP25Protocol::Task(void) auto newclient = std::make_shared(Callsign, Ip); // aautolink, if enabled -#if P25_AUTOLINK_ENABLE - newclient->SetReflectorModule(P25_AUTOLINK_MODULE); -#endif + if (m_AutolinkModule) + newclient->SetReflectorModule(m_AutolinkModule); // and append clients->AddClient(newclient); @@ -133,7 +136,7 @@ void CP25Protocol::Task(void) // acknowledge the request -- P25Reflector simply echoes the packet Send(Buffer, Ip); // and done - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); } } else if ( IsValidDisconnectPacket(Buffer, &Callsign) ) @@ -141,14 +144,14 @@ void CP25Protocol::Task(void) std::cout << "P25 disconnect packet from " << Callsign << " at " << Ip << std::endl; // find client - CClients *clients = g_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); std::shared_ptrclient = clients->FindClient(Ip, EProtocol::p25); if ( client != nullptr ) { // remove it clients->RemoveClient(client); } - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); } else { @@ -197,7 +200,7 @@ void CP25Protocol::OnDvHeaderPacketIn(std::unique_ptr &Header, CCallsign rpt2(Header->GetRpt2Callsign()); // find this client - std::shared_ptrclient = g_Refl..GetClients()->FindClient(Ip, EProtocol::p25); + std::shared_ptrclient = g_Refl.GetClients()->FindClient(Ip, EProtocol::p25); if ( client ) { // get client callsign @@ -206,18 +209,18 @@ void CP25Protocol::OnDvHeaderPacketIn(std::unique_ptr &Header, Header->SetRpt2Module(m); rpt2.SetCSModule(m); // and try to open the stream - if ( (stream = g_Refl..OpenStream(Header, client)) != nullptr ) + if ( (stream = g_Refl.OpenStream(Header, client)) != nullptr ) { // keep the handle m_Streams[stream->GetStreamId()] = stream; } } // release - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); // update last heard - g_Refl..GetUsers()->Hearing(my, rpt1, rpt2); - g_Refl..ReleaseUsers(); + g_Refl.GetUsers()->Hearing(my, rpt1, rpt2); + g_Refl.ReleaseUsers(); } } @@ -256,7 +259,7 @@ void CP25Protocol::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_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::p25, it)) != nullptr ) @@ -269,7 +272,7 @@ void CP25Protocol::HandleQueue(void) } } - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); } } } @@ -387,10 +390,9 @@ bool CP25Protocol::IsValidDvHeaderPacket(const CIp &Ip, const CBuffer &Buffer, s void CP25Protocol::EncodeP25Packet(const CDvHeaderPacket &Header, const CDvFramePacket &DvFrame, uint32_t iSeq, CBuffer &Buffer, bool islast) const { uint32_t uiSrcId = Header.GetMyCallsign().GetDmrid(); - uint32_t uiRptrId = P25_REFID; if(uiSrcId == 0){ - uiSrcId = DMRMMDVM_DEFAULTID; + uiSrcId = m_DefaultId; } if(islast) @@ -420,9 +422,9 @@ void CP25Protocol::EncodeP25Packet(const CDvHeaderPacket &Header, const CDvFrame Buffer.resize(17); ::memcpy(Buffer.data(), REC65, 17U); ::memcpy(Buffer.data() + 5U, DvFrame.GetCodecData(ECodecType::p25), 11U); - Buffer.data()[1U] = (uiRptrId >> 16) & 0xFFU; - Buffer.data()[2U] = (uiRptrId >> 8) & 0xFFU; - Buffer.data()[3U] = (uiRptrId >> 0) & 0xFFU; + Buffer.data()[1U] = (m_ReflectorId >> 16) & 0xFFU; + Buffer.data()[2U] = (m_ReflectorId >> 8) & 0xFFU; + Buffer.data()[3U] = (m_ReflectorId >> 0) & 0xFFU; break; case 0x04U: Buffer.resize(17); @@ -506,7 +508,7 @@ void CP25Protocol::EncodeP25Packet(const CDvHeaderPacket &Header, const CDvFrame void CP25Protocol::HandleKeepalives(void) { // iterate on clients - CClients *clients = g_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::p25, it)) != nullptr ) @@ -526,5 +528,5 @@ void CP25Protocol::HandleKeepalives(void) } } - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); } diff --git a/reflector/P25Protocol.h b/reflector/P25Protocol.h index 38f7a36..7829fe9 100644 --- a/reflector/P25Protocol.h +++ b/reflector/P25Protocol.h @@ -19,6 +19,7 @@ #pragma once +#include "Defines.h" #include "Timer.h" #include "Protocol.h" #include "DVHeaderPacket.h" @@ -53,7 +54,7 @@ protected: // queue helper void HandleQueue(void); void HandleKeepalives(void); - + // stream helpers void OnDvHeaderPacketIn(std::unique_ptr &, const CIp &); @@ -72,4 +73,9 @@ protected: // for queue header caches std::unordered_map m_StreamsCache; uint32_t m_uiStreamId; + + // config data + uint32_t m_ReflectorId; + uint32_t m_DefaultId; + char m_AutolinkModule; }; diff --git a/reflector/Packet.cpp b/reflector/Packet.cpp index c77208b..ed4d3a1 100644 --- a/reflector/Packet.cpp +++ b/reflector/Packet.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 #include "Packet.h" // default constructor diff --git a/reflector/PacketQueue.h b/reflector/PacketQueue.h index 8851cd5..e53881c 100644 --- a/reflector/PacketQueue.h +++ b/reflector/PacketQueue.h @@ -18,6 +18,8 @@ #pragma once +#include +#include #include "Packet.h" class CClient; diff --git a/reflector/PacketStream.cpp b/reflector/PacketStream.cpp index 7253218..a5df4a8 100644 --- a/reflector/PacketStream.cpp +++ b/reflector/PacketStream.cpp @@ -60,7 +60,8 @@ bool CPacketStream::OpenPacketStream(const CDvHeaderPacket &DvHeader, std::share m_LastPacketTime.start(); return true; } - + if (m_CodecStream) + m_CodecStream->ResetStats(m_uiStreamId, m_DvHeader.GetCodecIn()); return false; } @@ -71,7 +72,7 @@ void CPacketStream::ClosePacketStream(void) m_uiStreamId = 0; m_OwnerClient.reset(); if (m_CodecStream) - m_CodecStream.reset(); + m_CodecStream->ReportStats(); } //////////////////////////////////////////////////////////////////////////////////////// diff --git a/reflector/PeerCallsignList.cpp b/reflector/PeerCallsignList.cpp index af07d5d..5729d0a 100644 --- a/reflector/PeerCallsignList.cpp +++ b/reflector/PeerCallsignList.cpp @@ -16,11 +16,12 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +#include #include #include "PeerCallsignList.h" -bool CPeerCallsignList::LoadFromFile(const char *filename) +bool CPeerCallsignList::LoadFromFile(const std::string &filename) { bool ok = false; char sz[256]; diff --git a/reflector/PeerCallsignList.h b/reflector/PeerCallsignList.h index 8ef827e..b4cd2b9 100644 --- a/reflector/PeerCallsignList.h +++ b/reflector/PeerCallsignList.h @@ -34,5 +34,5 @@ public: virtual ~CPeerCallsignList() {} // file io - bool LoadFromFile(const char *); + bool LoadFromFile(const std::string &filename); }; diff --git a/reflector/Peers.cpp b/reflector/Peers.cpp index a371c8f..df3497b 100644 --- a/reflector/Peers.cpp +++ b/reflector/Peers.cpp @@ -16,11 +16,9 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . - -#include "Reflector.h" +#include "Global.h" #include "Peers.h" - //////////////////////////////////////////////////////////////////////////////////////// // constructor @@ -60,15 +58,15 @@ void CPeers::AddPeer(std::shared_ptr peer) std::cout << "New peer " << peer->GetCallsign() << " at " << peer->GetIp() << " added with protocol " << peer->GetProtocolName() << std::endl; // and append all peer's client to reflector client list // it is double lock safe to lock Clients list after Peers list - CClients *clients = g_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); for ( auto cit=peer->cbegin(); cit!=peer->cend(); cit++ ) { clients->AddClient(*cit); } - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); // notify - g_Refl..OnPeersChanged(); + g_Refl.OnPeersChanged(); } void CPeers::RemovePeer(std::shared_ptr peer) @@ -81,7 +79,7 @@ void CPeers::RemovePeer(std::shared_ptr peer) { // remove all clients from reflector client list // it is double lock safe to lock Clients list after Peers list - CClients *clients = g_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); for ( auto cit=peer->begin(); cit!=peer->end(); cit++ ) { // this also delete the client object @@ -89,13 +87,13 @@ void CPeers::RemovePeer(std::shared_ptr peer) } // so clear it then (*pit)->ClearClients(); - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); // remove it std::cout << "Peer " << (*pit)->GetCallsign() << " at " << (*pit)->GetIp() << " removed" << std::endl; pit = m_Peers.erase(pit); // notify - g_Refl..OnPeersChanged(); + g_Refl.OnPeersChanged(); } else { diff --git a/reflector/Protocol.cpp b/reflector/Protocol.cpp index 817f5b5..7792901 100644 --- a/reflector/Protocol.cpp +++ b/reflector/Protocol.cpp @@ -16,11 +16,10 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . - +#include "Defines.h" +#include "Global.h" #include "Protocol.h" #include "Clients.h" -#include "Reflector.h" - //////////////////////////////////////////////////////////////////////////////////////// // constructor @@ -51,8 +50,9 @@ CProtocol::~CProtocol() bool CProtocol::Initialize(const char *type, const EProtocol ptype, const uint16_t port, const bool has_ipv4, const bool has_ipv6) { + m_Port = port; // init reflector apparent callsign - m_ReflectorCallsign = g_Refl..GetCallsign(); + m_ReflectorCallsign = g_Refl.GetCallsign(); // reset stop flag keep_running = true; @@ -62,10 +62,10 @@ bool CProtocol::Initialize(const char *type, const EProtocol ptype, const uint16 m_ReflectorCallsign.PatchCallsign(0, type, 3); // create our sockets -#ifdef LISTEN_IPV4 if (has_ipv4) { - CIp ip4(AF_INET, port, LISTEN_IPV4); + const std::string ipv4binding(g_Conf.GetString(g_Conf.j.ip.ipv4bind)); + CIp ip4(AF_INET, port, ipv4binding.c_str()); if ( ip4.IsSet() ) { if (! m_Socket4.Open(ip4)) @@ -73,25 +73,27 @@ bool CProtocol::Initialize(const char *type, const EProtocol ptype, const uint16 } std::cout << "Listening on " << ip4 << std::endl; } -#endif -#ifdef LISTEN_IPV6 - if (has_ipv6) + if (g_Conf.IsString(g_Conf.j.ip.ipv6bind)) { - CIp ip6(AF_INET6, port, LISTEN_IPV6); - if ( ip6.IsSet() ) + if (has_ipv6) { - if (! m_Socket6.Open(ip6)) + const std::string ipv6binding(g_Conf.j.ip.ipv6bind); + CIp ip6(AF_INET6, port, ipv6binding.c_str()); + if ( ip6.IsSet() ) { - m_Socket4.Close(); - return false; + if (! m_Socket6.Open(ip6)) + { + m_Socket4.Close(); + return false; + } + std::cout << "Listening on " << ip6 << std::endl; } - std::cout << "Listening on " << ip6 << std::endl; } } -#endif - try { + try + { m_Future = std::async(std::launch::async, &CProtocol::Thread, this); } catch (const std::exception &e) @@ -179,7 +181,7 @@ void CProtocol::CheckStreamsTimeout(void) { // yes, close it it->second->Unlock(); - g_Refl..CloseStream(it->second); + g_Refl.CloseStream(it->second); // and remove it from the m_Streams map it = m_Streams.erase(it); } diff --git a/reflector/Protocol.h b/reflector/Protocol.h index 6d0c37c..799ca76 100644 --- a/reflector/Protocol.h +++ b/reflector/Protocol.h @@ -132,10 +132,8 @@ protected: // identity CCallsign m_ReflectorCallsign; + // data + uint8_t m_Port; // debug CTimer m_DebugTimer; - -#ifdef DEBUG - void Dump(const char *title, const uint8_t *pointer, int length); -#endif }; diff --git a/reflector/Protocols.cpp b/reflector/Protocols.cpp index 6dec2ff..b52c801 100644 --- a/reflector/Protocols.cpp +++ b/reflector/Protocols.cpp @@ -29,10 +29,9 @@ #include "P25Protocol.h" #include "NXDNProtocol.h" #include "USRPProtocol.h" -#ifndef NO_G3 #include "G3Protocol.h" -#endif #include "Protocols.h" +#include "Global.h" //////////////////////////////////////////////////////////////////////////////////////// // destructor @@ -50,58 +49,56 @@ bool CProtocols::Init(void) m_Mutex.lock(); { m_Protocols.emplace_back(std::unique_ptr(new CDextraProtocol)); - if (! m_Protocols.back()->Initialize("XRF", EProtocol::dextra, DEXTRA_PORT, DSTAR_IPV4, DSTAR_IPV6)) + if (! m_Protocols.back()->Initialize("XRF", EProtocol::dextra, uint16_t(g_Conf.GetUnsigned(g_Conf.j.dextra.port)), DSTAR_IPV4, DSTAR_IPV6)) return false; m_Protocols.emplace_back(std::unique_ptr(new CDplusProtocol)); - if (! m_Protocols.back()->Initialize("REF", EProtocol::dplus, DPLUS_PORT, DSTAR_IPV4, DSTAR_IPV6)) + if (! m_Protocols.back()->Initialize("REF", EProtocol::dplus, uint16_t(g_Conf.GetUnsigned(g_Conf.j.dplus.port)), DSTAR_IPV4, DSTAR_IPV6)) return false; m_Protocols.emplace_back(std::unique_ptr(new CDcsProtocol)); - if (! m_Protocols.back()->Initialize("DCS", EProtocol::dcs, DCS_PORT, DSTAR_IPV4, DSTAR_IPV6)) + if (! m_Protocols.back()->Initialize("DCS", EProtocol::dcs, uint16_t(g_Conf.GetUnsigned(g_Conf.j.dcs.port)), DSTAR_IPV4, DSTAR_IPV6)) return false; m_Protocols.emplace_back(std::unique_ptr(new CDmrmmdvmProtocol)); - if (! m_Protocols.back()->Initialize(nullptr, EProtocol::dmrmmdvm, DMRMMDVM_PORT, DMR_IPV4, DMR_IPV6)) + if (! m_Protocols.back()->Initialize(nullptr, EProtocol::dmrmmdvm, uint16_t(g_Conf.GetUnsigned(g_Conf.j.mmdvm.port)), DMR_IPV4, DMR_IPV6)) return false; m_Protocols.emplace_back(std::unique_ptr(new CBMProtocol)); - if (! m_Protocols.back()->Initialize("XLX", EProtocol::bm, XLX_PORT, DMR_IPV4, DMR_IPV6)) + if (! m_Protocols.back()->Initialize("XLX", EProtocol::bm, uint16_t(g_Conf.GetUnsigned(g_Conf.j.bm.port)), DMR_IPV4, DMR_IPV6)) return false; m_Protocols.emplace_back(std::unique_ptr(new CDmrplusProtocol)); - if (! m_Protocols.back()->Initialize(nullptr, EProtocol::dmrplus, DMRPLUS_PORT, DMR_IPV4, DMR_IPV6)) + if (! m_Protocols.back()->Initialize(nullptr, EProtocol::dmrplus, uint16_t(g_Conf.GetUnsigned(g_Conf.j.dmrplus.port)), DMR_IPV4, DMR_IPV6)) return false; m_Protocols.emplace_back(std::unique_ptr(new CYsfProtocol)); - if (! m_Protocols.back()->Initialize("YSF", EProtocol::ysf, YSF_PORT, YSF_IPV4, YSF_IPV6)) + if (! m_Protocols.back()->Initialize("YSF", EProtocol::ysf, uint16_t(g_Conf.GetUnsigned(g_Conf.j.ysf.port)), YSF_IPV4, YSF_IPV6)) return false; m_Protocols.emplace_back(std::unique_ptr(new CM17Protocol)); - if (! m_Protocols.back()->Initialize("URF", EProtocol::m17, M17_PORT, M17_IPV4, M17_IPV6)) + if (! m_Protocols.back()->Initialize("URF", EProtocol::m17, uint16_t(g_Conf.GetUnsigned(g_Conf.j.m17.port)), M17_IPV4, M17_IPV6)) return false; m_Protocols.emplace_back(std::unique_ptr(new CP25Protocol)); - if (! m_Protocols.back()->Initialize("P25", EProtocol::p25, P25_PORT, P25_IPV4, P25_IPV6)) + if (! m_Protocols.back()->Initialize("P25", EProtocol::p25, uint16_t(g_Conf.GetUnsigned(g_Conf.j.p25.port)), P25_IPV4, P25_IPV6)) return false; m_Protocols.emplace_back(std::unique_ptr(new CNXDNProtocol)); - if (! m_Protocols.back()->Initialize("NXDN", EProtocol::nxdn, NXDN_PORT, NXDN_IPV4, NXDN_IPV6)) + if (! m_Protocols.back()->Initialize("NXDN", EProtocol::nxdn, uint16_t(g_Conf.GetUnsigned(g_Conf.j.nxdn.port)), NXDN_IPV4, NXDN_IPV6)) return false; m_Protocols.emplace_back(std::unique_ptr(new CUSRPProtocol)); - if (! m_Protocols.back()->Initialize("USRP", EProtocol::usrp, USRP_PORT, USRP_IPV4, USRP_IPV6)) + if (! m_Protocols.back()->Initialize("USRP", EProtocol::usrp, uint16_t(g_Conf.GetUnsigned(g_Conf.j.usrp.port)), USRP_IPV4, USRP_IPV6)) return false; m_Protocols.emplace_back(std::unique_ptr(new CURFProtocol)); - if (! m_Protocols.back()->Initialize("URF", EProtocol::urf, URF_PORT, URF_IPV4, URF_IPV6)) + if (! m_Protocols.back()->Initialize("URF", EProtocol::urf, uint16_t(g_Conf.GetUnsigned(g_Conf.j.urf.port)), URF_IPV4, URF_IPV6)) return false; -#ifndef NO_G3 m_Protocols.emplace_back(std::unique_ptr(new CG3Protocol)); if (! m_Protocols.back()->Initialize("XLX", EProtocol::g3, G3_DV_PORT, DMR_IPV4, DMR_IPV6)) return false; -#endif } m_Mutex.unlock(); diff --git a/reflector/Semaphore.h b/reflector/Semaphore.h index f3e324f..e8f8dcf 100644 --- a/reflector/Semaphore.h +++ b/reflector/Semaphore.h @@ -18,7 +18,8 @@ #pragma once - +#include +#include class CSemaphore { @@ -39,6 +40,6 @@ protected: // data std::mutex m_Mutex; std::condition_variable m_Condition; - size_t m_Count; + std::size_t m_Count; }; diff --git a/reflector/URFClient.h b/reflector/URFClient.h index d0a2a9b..5f43145 100644 --- a/reflector/URFClient.h +++ b/reflector/URFClient.h @@ -18,6 +18,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +#include "Defines.h" #include "Client.h" class CURFClient : public CClient diff --git a/reflector/URFProtocol.cpp b/reflector/URFProtocol.cpp index f3fda2e..ce7cbaf 100644 --- a/reflector/URFProtocol.cpp +++ b/reflector/URFProtocol.cpp @@ -22,7 +22,7 @@ #include "URFProtocol.h" #include "Reflector.h" #include "GateKeeper.h" - +#include "Global.h" //////////////////////////////////////////////////////////////////////////////////////// // operation @@ -73,14 +73,14 @@ void CURFProtocol::Task(void) else if ( IsValidKeepAlivePacket(Buffer, &Callsign) ) { // find peer - CPeers *peers = g_Refl..GetPeers(); + CPeers *peers = g_Refl.GetPeers(); std::shared_ptrpeer = peers->FindPeer(Ip, EProtocol::urf); if ( peer != nullptr ) { // keep it alive peer->Alive(); } - g_Refl..ReleasePeers(); + g_Refl.ReleasePeers(); } else if ( IsValidDvHeaderPacket(Buffer, Header) ) { @@ -126,7 +126,7 @@ void CURFProtocol::Task(void) if ( g_Gate.MayLink(Callsign, Ip, EProtocol::urf, Modules) ) { // already connected ? - CPeers *peers = g_Refl..GetPeers(); + CPeers *peers = g_Refl.GetPeers(); if ( peers->FindPeer(Callsign, Ip, EProtocol::urf) == nullptr ) { // create the new peer @@ -137,7 +137,7 @@ void CURFProtocol::Task(void) // this also add all new clients to reflector client list peers->AddPeer(peer); } - g_Refl..ReleasePeers(); + g_Refl.ReleasePeers(); } } else if ( IsValidDisconnectPacket(Buffer, &Callsign) ) @@ -145,7 +145,7 @@ void CURFProtocol::Task(void) std::cout << "URF disconnect packet from " << Callsign << " at " << Ip << std::endl; // find peer - CPeers *peers = g_Refl..GetPeers(); + CPeers *peers = g_Refl.GetPeers(); std::shared_ptrpeer = peers->FindPeer(Ip, EProtocol::urf); if ( peer != nullptr ) { @@ -154,7 +154,7 @@ void CURFProtocol::Task(void) // and delete them peers->RemovePeer(peer); } - g_Refl..ReleasePeers(); + g_Refl.ReleasePeers(); } else if ( IsValidNackPacket(Buffer, &Callsign) ) { @@ -216,7 +216,7 @@ void CURFProtocol::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_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::urf, it)) != nullptr ) @@ -232,7 +232,7 @@ void CURFProtocol::HandleQueue(void) } } } - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); } } } @@ -251,7 +251,7 @@ void CURFProtocol::HandleKeepalives(void) EncodeKeepAlivePacket(&keepalive); // iterate on peers - CPeers *peers = g_Refl..GetPeers(); + CPeers *peers = g_Refl.GetPeers(); auto pit = peers->begin(); std::shared_ptrpeer = nullptr; while ( (peer = peers->FindNextPeer(EProtocol::urf, pit)) != nullptr ) @@ -278,7 +278,7 @@ void CURFProtocol::HandleKeepalives(void) peers->RemovePeer(peer); } } - g_Refl..ReleasePeers(); + g_Refl.ReleasePeers(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -290,7 +290,7 @@ void CURFProtocol::HandlePeerLinks(void) // get the list of peers CPeerCallsignList *list = g_Gate.GetPeerList(); - CPeers *peers = g_Refl..GetPeers(); + CPeers *peers = g_Refl.GetPeers(); // check if all our connected peers are still listed by gatekeeper // if not, disconnect @@ -324,13 +324,13 @@ void CURFProtocol::HandlePeerLinks(void) it->ResolveIp(); // send connect packet to re-initiate peer link EncodeConnectPacket(&buffer, it->GetModules()); - Send(buffer, it->GetIp(), URF_PORT); + Send(buffer, it->GetIp(), m_Port); std::cout << "Sending connect packet to URF peer " << cs << " @ " << it->GetIp() << " for modules " << it->GetModules() << std::endl; } } // done - g_Refl..ReleasePeers(); + g_Refl.ReleasePeers(); g_Gate.ReleasePeerList(); } @@ -363,11 +363,11 @@ void CURFProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header, CCallsign rpt2(Header->GetRpt2Callsign()); // no stream open yet, open a new one // find this client - std::shared_ptrclient = g_Refl..GetClients()->FindClient(Ip, EProtocol::urf, Header->GetRpt2Module()); + std::shared_ptrclient = g_Refl.GetClients()->FindClient(Ip, EProtocol::urf, Header->GetRpt2Module()); if ( client ) { // and try to open the stream - if ( (stream = g_Refl..OpenStream(Header, client)) != nullptr ) + if ( (stream = g_Refl.OpenStream(Header, client)) != nullptr ) { // keep the handle m_Streams[stream->GetStreamId()] = stream; @@ -376,10 +376,10 @@ void CURFProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header, peer = client->GetCallsign(); } // release - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); // update last heard - g_Refl..GetUsers()->Hearing(my, rpt1, rpt2, peer); - g_Refl..ReleaseUsers(); + g_Refl.GetUsers()->Hearing(my, rpt1, rpt2, peer); + g_Refl.ReleaseUsers(); } } @@ -420,7 +420,7 @@ bool CURFProtocol::IsValidConnectPacket(const CBuffer &Buffer, CCallsign *callsi memcpy(modules, Buffer.data()+10, 27); for ( unsigned i = 0; i < strlen(modules); i++ ) { - valid &= (nullptr != strchr(ACTIVE_MODULES, modules[i])); + valid = valid && (g_Refl.IsValidModule (modules[i])); } } return valid; @@ -450,7 +450,7 @@ bool CURFProtocol::IsValidAckPacket(const CBuffer &Buffer, CCallsign *callsign, memcpy(modules, Buffer.data()+10, 27); for ( unsigned i = 0; i < strlen(modules); i++ ) { - valid &= (nullptr != strchr(ACTIVE_MODULES, modules[i])); + valid = valid && (g_Refl.IsValidModule(modules[i])); } } return valid; @@ -521,7 +521,7 @@ void CURFProtocol::EncodeKeepAlivePacket(CBuffer *Buffer) { Buffer->Set("PING"); Buffer->resize(10); - g_Refl..GetCallsign().CodeOut(Buffer->data()+4); + g_Refl.GetCallsign().CodeOut(Buffer->data()+4); } void CURFProtocol::EncodeConnectPacket(CBuffer *Buffer, const char *Modules) @@ -530,12 +530,12 @@ void CURFProtocol::EncodeConnectPacket(CBuffer *Buffer, const char *Modules) Buffer->Set("CONN"); // our callsign Buffer->resize(37); - g_Refl..GetCallsign().CodeOut(Buffer->data()+4); + g_Refl.GetCallsign().CodeOut(Buffer->data()+4); // our version Buffer->ReplaceAt(10, (uint8_t *)Modules, strlen(Modules)); - Buffer->Append((uint8_t)VERSION_MAJOR); - Buffer->Append((uint8_t)VERSION_MINOR); - Buffer->Append((uint8_t)VERSION_REVISION); + Buffer->Append((uint8_t)g_Vers.GetMajor()); + Buffer->Append((uint8_t)g_Vers.GetMinor()); + Buffer->Append((uint8_t)g_Vers.GetRevision()); } void CURFProtocol::EncodeDisconnectPacket(CBuffer *Buffer) @@ -543,7 +543,7 @@ void CURFProtocol::EncodeDisconnectPacket(CBuffer *Buffer) Buffer->Set("DISC"); // our callsign Buffer->resize(10); - g_Refl..GetCallsign().CodeOut(Buffer->data()+4); + g_Refl.GetCallsign().CodeOut(Buffer->data()+4); } void CURFProtocol::EncodeConnectAckPacket(CBuffer *Buffer, const char *Modules) @@ -551,18 +551,18 @@ void CURFProtocol::EncodeConnectAckPacket(CBuffer *Buffer, const char *Modules) Buffer->Set("ACKN"); // our callsign Buffer->resize(37); - g_Refl..GetCallsign().CodeOut(Buffer->data()+4); + g_Refl.GetCallsign().CodeOut(Buffer->data()+4); // the shared modules Buffer->ReplaceAt(10, (uint8_t *)Modules, strlen(Modules)); // our version - Buffer->Append((uint8_t)VERSION_MAJOR); - Buffer->Append((uint8_t)VERSION_MINOR); - Buffer->Append((uint8_t)VERSION_REVISION); + Buffer->Append((uint8_t)g_Vers.GetMajor()); + Buffer->Append((uint8_t)g_Vers.GetMinor()); + Buffer->Append((uint8_t)g_Vers.GetRevision()); } void CURFProtocol::EncodeConnectNackPacket(CBuffer *Buffer) { Buffer->Set("NACK"); Buffer->resize(10); - g_Refl..GetCallsign().CodeOut(Buffer->data()+4); + g_Refl.GetCallsign().CodeOut(Buffer->data()+4); } diff --git a/reflector/URFProtocol.h b/reflector/URFProtocol.h index 5418a0e..482d8e6 100644 --- a/reflector/URFProtocol.h +++ b/reflector/URFProtocol.h @@ -18,6 +18,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +#include "Defines.h" #include "Version.h" #include "Timer.h" #include "SEProtocol.h" diff --git a/reflector/USRPClient.h b/reflector/USRPClient.h index 2157d2b..bb5e307 100644 --- a/reflector/USRPClient.h +++ b/reflector/USRPClient.h @@ -19,7 +19,9 @@ #pragma once +#include "Defines.h" #include "Client.h" + class CUSRPClient : public CClient { public: diff --git a/reflector/USRPProtocol.cpp b/reflector/USRPProtocol.cpp index 076d7ff..9a559fb 100644 --- a/reflector/USRPProtocol.cpp +++ b/reflector/USRPProtocol.cpp @@ -22,8 +22,7 @@ #include "USRPClient.h" #include "USRPProtocol.h" -#include "Reflector.h" -#include "GateKeeper.h" +#include "Global.h" const uint8_t USRP_TYPE_VOICE = 0; const uint8_t USRP_TYPE_TEXT = 2; @@ -38,10 +37,13 @@ const uint8_t TLV_TAG_SET_INFO = 8; bool CUSRPProtocol::Initialize(const char *type, const EProtocol ptype, const uint16_t port, const bool has_ipv4, const bool has_ipv6) { + // config data + m_DefaultCallsign.assign(g_Conf.GetString(g_Conf.j.usrp.defaultcallsign)); + m_AutolinkModule = g_Conf.GetAutolinkModule(g_Conf.j.usrp.autolinkmod); CBuffer buffer; m_uiStreamId = 0; - CCallsign cs(USRP_DEFAULT_CALLSIGN); - CClients *clients = g_Refl..GetClients(); + CCallsign cs(m_DefaultCallsign.c_str()); + CClients *clients = g_Refl.GetClients(); std::ifstream file; std::streampos size; @@ -49,7 +51,7 @@ bool CUSRPProtocol::Initialize(const char *type, const EProtocol ptype, const ui if (! CProtocol::Initialize(type, ptype, port, has_ipv4, has_ipv6)) return false; - file.open(USRPCLIENTS_PATH, std::ios::in | std::ios::binary | std::ios::ate); + file.open(g_Conf.GetString(g_Conf.j.usrp.clientfilepath), std::ios::in | std::ios::binary | std::ios::ate); if ( file.is_open() ) { // read file @@ -83,9 +85,9 @@ bool CUSRPProtocol::Initialize(const char *type, const EProtocol ptype, const ui uint32_t ui = atoi(port); CIp Ip(AF_INET, ui, ip); auto newclient = std::make_shared(cs, Ip); -#if USRP_AUTOLINK_ENABLE - newclient->SetReflectorModule(USRP_AUTOLINK_MODULE); -#endif + if (m_AutolinkModule) + newclient->SetReflectorModule(m_AutolinkModule); + clients->AddClient(newclient); } } @@ -93,7 +95,7 @@ bool CUSRPProtocol::Initialize(const char *type, const EProtocol ptype, const ui } } - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); // update time m_LastKeepaliveTime.start(); @@ -192,7 +194,7 @@ void CUSRPProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header, CCallsign rpt2(Header->GetRpt2Callsign()); // find this client - std::shared_ptrclient = g_Refl..GetClients()->FindClient(Ip, EProtocol::usrp); + std::shared_ptrclient = g_Refl.GetClients()->FindClient(Ip, EProtocol::usrp); if ( client ) { // get client callsign @@ -201,18 +203,18 @@ void CUSRPProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header, Header->SetRpt2Module(m); rpt2.SetCSModule(m); // and try to open the stream - if ( (stream = g_Refl..OpenStream(Header, client)) != nullptr ) + if ( (stream = g_Refl.OpenStream(Header, client)) != nullptr ) { // keep the handle m_Streams[stream->GetStreamId()] = stream; } } // release - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); // update last heard - g_Refl..GetUsers()->Hearing(my, rpt1, rpt2); - g_Refl..ReleaseUsers(); + g_Refl.GetUsers()->Hearing(my, rpt1, rpt2); + g_Refl.ReleaseUsers(); } } @@ -249,7 +251,7 @@ void CUSRPProtocol::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_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::usrp, it)) != nullptr ) @@ -261,7 +263,7 @@ void CUSRPProtocol::HandleQueue(void) Send(buffer, client->GetIp()); } } - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); } } m_Queue.Unlock(); @@ -279,8 +281,8 @@ bool CUSRPProtocol::IsValidDvPacket(const CIp &Ip, const CBuffer &Buffer, std::u if ( !stream ) { m_uiStreamId = static_cast(::rand()); - CCallsign csMY = CCallsign(USRP_DEFAULT_CALLSIGN); - CCallsign rpt1 = CCallsign(USRP_DEFAULT_CALLSIGN); + CCallsign csMY = CCallsign(m_DefaultCallsign.c_str()); + CCallsign rpt1 = CCallsign(m_DefaultCallsign.c_str()); CCallsign rpt2 = m_ReflectorCallsign; rpt1.SetCSModule(USRP_MODULE_ID); rpt2.SetCSModule(' '); @@ -375,7 +377,7 @@ void CUSRPProtocol::EncodeUSRPPacket(const CDvHeaderPacket &Header, const CDvFra void CUSRPProtocol::HandleKeepalives(void) { // iterate on clients - CClients *clients = g_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::usrp, it)) != nullptr ) @@ -395,5 +397,5 @@ void CUSRPProtocol::HandleKeepalives(void) //} } - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); } diff --git a/reflector/USRPProtocol.h b/reflector/USRPProtocol.h index b4b2877..6362a77 100644 --- a/reflector/USRPProtocol.h +++ b/reflector/USRPProtocol.h @@ -19,6 +19,7 @@ #pragma once +#include "Defines.h" #include "Timer.h" #include "Protocol.h" #include "DVHeaderPacket.h" @@ -53,7 +54,7 @@ protected: // queue helper void HandleQueue(void); void HandleKeepalives(void); - + // stream helpers void OnDvHeaderPacketIn(std::unique_ptr &, const CIp &); @@ -72,4 +73,8 @@ protected: // for queue header caches std::unordered_map m_StreamsCache; uint32_t m_uiStreamId; + + // config data + std::string m_DefaultCallsign; + char m_AutolinkModule; }; diff --git a/reflector/User.cpp b/reflector/User.cpp index c42729e..cfac5ae 100644 --- a/reflector/User.cpp +++ b/reflector/User.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 #include #include "User.h" diff --git a/reflector/Users.cpp b/reflector/Users.cpp index beb2106..8027503 100644 --- a/reflector/Users.cpp +++ b/reflector/Users.cpp @@ -18,7 +18,7 @@ #include "Users.h" -#include "Reflector.h" +#include "Global.h" //////////////////////////////////////////////////////////////////////////////////////// // constructor @@ -28,6 +28,7 @@ CUsers::CUsers() {} //////////////////////////////////////////////////////////////////////////////////////// // users management +#define LASTHEARD_USERS_MAX_SIZE 20 void CUsers::AddUser(const CUser &user) { // add @@ -40,7 +41,7 @@ void CUsers::AddUser(const CUser &user) } // notify - g_Refl..OnUsersChanged(); + g_Refl.OnUsersChanged(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -48,7 +49,7 @@ void CUsers::AddUser(const CUser &user) void CUsers::Hearing(const CCallsign &my, const CCallsign &rpt1, const CCallsign &rpt2) { - Hearing(my, rpt1, rpt2, g_Refl..GetCallsign()); + Hearing(my, rpt1, rpt2, g_Refl.GetCallsign()); } void CUsers::Hearing(const CCallsign &my, const CCallsign &rpt1, const CCallsign &rpt2, const CCallsign &xlx) diff --git a/reflector/WiresXCmdHandler.cpp b/reflector/WiresXCmdHandler.cpp index e90b0a3..e2c8d63 100644 --- a/reflector/WiresXCmdHandler.cpp +++ b/reflector/WiresXCmdHandler.cpp @@ -22,11 +22,9 @@ #include "YSFFich.h" #include "YSFPayload.h" #include "YSFClient.h" -#include "YSFNodeDirFile.h" -#include "YSFNodeDirHttp.h" #include "YSFUtils.h" -#include "Reflector.h" #include "WiresXCmdHandler.h" +#include "Global.h" //////////////////////////////////////////////////////////////////////////////////////// // constructor @@ -61,8 +59,8 @@ CWiresxCmdHandler::~CWiresxCmdHandler() bool CWiresxCmdHandler::Init(void) { // fill our wiresx info - m_ReflectorWiresxInfo.SetCallsign(g_Refl..GetCallsign()); - m_ReflectorWiresxInfo.SetNode(g_Refl..GetCallsign()); + m_ReflectorWiresxInfo.SetCallsign(g_Refl.GetCallsign()); + m_ReflectorWiresxInfo.SetNode(g_Refl.GetCallsign()); m_ReflectorWiresxInfo.SetName("Reflector"); // reset stop flag @@ -141,7 +139,6 @@ void CWiresxCmdHandler::Task(void) // handle it if ( bCmd ) { - const char *modules = ACTIVE_MODULES; // fill our info object Info = m_ReflectorWiresxInfo; g_LYtr.FindFrequencies(Cmd.GetCallsign(), &uiNodeTxFreq, &uiNodeRxFreq); @@ -149,13 +146,13 @@ void CWiresxCmdHandler::Task(void) // find our client and the module it's currentlink linked to cModule = ' '; - CClients *clients = g_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); std::shared_ptrclient = clients->FindClient(Cmd.GetCallsign(), Cmd.GetIp(), EProtocol::ysf); if ( client ) { cModule = client->GetReflectorModule(); } - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); // and crack the cmd switch ( Cmd.GetCmd() ) @@ -173,19 +170,19 @@ void CWiresxCmdHandler::Task(void) break; case WIRESX_CMD_CONN_REQ: cModule = 'A' + (char)(Cmd.GetArg() - 1); - if (::strchr(modules, cModule)) + if (g_Refl.IsValidModule(cModule)) { std::cout << "Wires-X CONN_REQ command to link on module " << cModule << " from " << Cmd.GetCallsign() << " at " << Cmd.GetIp() << std::endl; // acknowledge ReplyToWiresxConnReqPacket(Cmd.GetIp(), Info, cModule); // change client's module - CClients *clients = g_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); std::shared_ptrclient = clients->FindClient(Cmd.GetCallsign(), Cmd.GetIp(), EProtocol::ysf); if ( client ) { client->SetReflectorModule(cModule); } - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); } else { @@ -198,13 +195,13 @@ void CWiresxCmdHandler::Task(void) ReplyToWiresxDiscReqPacket(Cmd.GetIp(), Info); // change client's module { - CClients *clients = g_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); std::shared_ptrclient = clients->FindClient(Cmd.GetCallsign(), Cmd.GetIp(), EProtocol::ysf); if ( client != nullptr ) { client->SetReflectorModule(' '); } - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); } break; case WIRESX_CMD_UNKNOWN: @@ -337,8 +334,8 @@ bool CWiresxCmdHandler::ReplyToWiresxAllReqPacket(const CIp &Ip, const CWiresxIn memcpy(data + 12U, WiresxInfo.GetNode(), 10U); // number of entries - const char *modules = ACTIVE_MODULES; - uint NB_OF_MODULES = ::strlen(modules); + const std::string modules(g_Conf.GetString(g_Conf.j.modules.modules)); + uint NB_OF_MODULES = modules.size(); uint total = NB_OF_MODULES; uint n = NB_OF_MODULES - Start; if (n > 20U) @@ -741,8 +738,8 @@ bool CWiresxCmdHandler::DebugTestDecodePacket(const CBuffer &Buffer) std::cout << "Trailer" << std::endl; std::cout << "length of payload : " << len << std::endl; dump.Set(command, len); - dump.DebugDump(g_Refl..m_DebugFile); - dump.DebugDumpAscii(g_Refl..m_DebugFile); + dump.DebugDump(g_Refl.m_DebugFile); + dump.DebugDumpAscii(g_Refl.m_DebugFile); break; case YSF_FI_COMMUNICATIONS: if ( Fich.getDT() == YSF_DT_DATA_FR_MODE ) diff --git a/reflector/WiresXInfo.cpp b/reflector/WiresXInfo.cpp index 6fd11c9..3069a32 100644 --- a/reflector/WiresXInfo.cpp +++ b/reflector/WiresXInfo.cpp @@ -18,10 +18,10 @@ #include +#include "Defines.h" #include "Callsign.h" #include "WiresXInfo.h" - //////////////////////////////////////////////////////////////////////////////////////// // constructor diff --git a/reflector/YSFClient.h b/reflector/YSFClient.h index 08ff034..9b662b4 100644 --- a/reflector/YSFClient.h +++ b/reflector/YSFClient.h @@ -18,7 +18,9 @@ #pragma once +#include "Defines.h" #include "Client.h" + class CYsfClient : public CClient { public: diff --git a/reflector/YSFNode.h b/reflector/YSFNode.h index ba4889d..202c940 100644 --- a/reflector/YSFNode.h +++ b/reflector/YSFNode.h @@ -18,7 +18,7 @@ #pragma once - +#include class CYsfNode { diff --git a/reflector/YSFProtocol.cpp b/reflector/YSFProtocol.cpp index 15e9149..30fbf46 100644 --- a/reflector/YSFProtocol.cpp +++ b/reflector/YSFProtocol.cpp @@ -21,12 +21,9 @@ #include "CRC.h" #include "YSFPayload.h" #include "YSFClient.h" -#include "YSFNodeDirFile.h" -#include "YSFNodeDirHttp.h" #include "YSFUtils.h" #include "YSFProtocol.h" -#include "Reflector.h" -#include "GateKeeper.h" +#include "Global.h" //////////////////////////////////////////////////////////////////////////////////////// // constructor @@ -40,6 +37,9 @@ CYsfProtocol::CYsfProtocol() bool CYsfProtocol::Initialize(const char *type, const EProtocol ptype, const uint16_t port, const bool has_ipv4, const bool has_ipv6) { + // config data + m_AutolinkModule = g_Conf.GetAutolinkModule(g_Conf.j.ysf.autolinkmod); + // base class if (! CProtocol::Initialize(type, ptype, port, has_ipv4, has_ipv6)) return false; @@ -145,7 +145,7 @@ void CYsfProtocol::Task(void) Send(Buffer, Ip); // add client if needed - CClients *clients = g_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); std::shared_ptrclient = clients->FindClient(Callsign, Ip, EProtocol::ysf); // client already connected ? if ( client == nullptr ) @@ -156,9 +156,8 @@ void CYsfProtocol::Task(void) auto newclient = std::make_shared(Callsign, Ip); // aautolink, if enabled -#if YSF_AUTOLINK_ENABLE - newclient->SetReflectorModule(YSF_AUTOLINK_MODULE); -#endif + if (m_AutolinkModule) + newclient->SetReflectorModule(m_AutolinkModule); // and append clients->AddClient(newclient); @@ -168,7 +167,7 @@ void CYsfProtocol::Task(void) client->Alive(); } // and done - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); } } else if ( IsValidDisconnectPacket(Buffer) ) @@ -176,7 +175,7 @@ void CYsfProtocol::Task(void) std::cout << "YSF disconnect packet from " << Ip << std::endl; // find client - CClients *clients = g_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); std::shared_ptrclient = clients->FindClient(Ip, EProtocol::ysf); if ( client != nullptr ) { @@ -186,7 +185,7 @@ void CYsfProtocol::Task(void) //EncodeDisconnectPacket(&Buffer); //Send(Buffer, Ip); } - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); } else if ( IsValidwirexPacket(Buffer, &Fich, &Callsign, &iWiresxCmd, &iWiresxArg) ) { @@ -263,7 +262,7 @@ void CYsfProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header, CCallsign rpt2(Header->GetRpt2Callsign()); // find this client - std::shared_ptrclient = g_Refl..GetClients()->FindClient(Ip, EProtocol::ysf); + std::shared_ptrclient = g_Refl.GetClients()->FindClient(Ip, EProtocol::ysf); if ( client ) { // get client callsign @@ -274,20 +273,20 @@ void CYsfProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header, rpt2.SetCSModule(m); // and try to open the stream - if ( (stream = g_Refl..OpenStream(Header, client)) != nullptr ) + if ( (stream = g_Refl.OpenStream(Header, client)) != nullptr ) { // keep the handle m_Streams[stream->GetStreamId()] = stream; } } // release - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); // update last heard - if ( g_Refl..IsValidModule(rpt2.GetCSModule()) ) + if ( g_Refl.IsValidModule(rpt2.GetCSModule()) ) { - g_Refl..GetUsers()->Hearing(my, rpt1, rpt2); - g_Refl..ReleaseUsers(); + g_Refl.GetUsers()->Hearing(my, rpt1, rpt2); + g_Refl.ReleaseUsers(); } } } @@ -346,7 +345,7 @@ void CYsfProtocol::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_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::ysf, it)) != nullptr ) @@ -359,7 +358,7 @@ void CYsfProtocol::HandleQueue(void) } } - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); } } m_Queue.Unlock(); @@ -375,7 +374,7 @@ void CYsfProtocol::HandleKeepalives(void) // and disconnect them if not // iterate on clients - CClients *clients = g_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::ysf, it)) != nullptr ) @@ -395,7 +394,7 @@ void CYsfProtocol::HandleKeepalives(void) } } - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -998,7 +997,7 @@ bool CYsfProtocol::EncodeServerStatusPacket(CBuffer *Buffer) const const std::string cs = YSF_REFLECTOR_NAME; memcpy(callsign, cs.c_str(), cs.size() > 16 ? 16 : cs.size()); #else - g_Refl..GetCallsign().GetCallsign(callsign); + g_Refl.GetCallsign().GetCallsign(callsign); #endif char sz[16]; ::sprintf(sz, "%05u", CalcHash(callsign, 16) % 100000U); @@ -1010,9 +1009,9 @@ bool CYsfProtocol::EncodeServerStatusPacket(CBuffer *Buffer) const memcpy(description, desc.c_str(), desc.size() > 14 ? 14 : desc.size()); Buffer->Append(description, 14); // connected clients - CClients *clients = g_Refl..GetClients(); + CClients *clients = g_Refl.GetClients(); int count = MIN(999, clients->GetSize()); - g_Refl..ReleaseClients(); + g_Refl.ReleaseClients(); ::sprintf(sz, "%03u", count); Buffer->Append((uint8_t *)sz, 3); @@ -1090,8 +1089,8 @@ bool CYsfProtocol::DebugTestDecodePacket(const CBuffer &Buffer) std::cout << "Trailer" << std::endl; std::cout << "length of payload : " << len << std::endl; dump.Set(command, len); - dump.DebugDump(g_Refl..m_DebugFile); - dump.DebugDumpAscii(g_Refl..m_DebugFile); + dump.DebugDump(g_Refl.m_DebugFile); + dump.DebugDumpAscii(g_Refl.m_DebugFile); break; case YSF_FI_COMMUNICATIONS: if ( Fich.getDT() == YSF_DT_DATA_FR_MODE ) diff --git a/reflector/YSFProtocol.h b/reflector/YSFProtocol.h index 6e0534d..da1eee4 100644 --- a/reflector/YSFProtocol.h +++ b/reflector/YSFProtocol.h @@ -18,6 +18,7 @@ #pragma once +#include "Defines.h" #include "Timer.h" #include "Protocol.h" #include "DVHeaderPacket.h" @@ -129,4 +130,7 @@ protected: CWiresxCmdHandler m_WiresxCmdHandler; unsigned char m_seqNo; uint32_t m_uiStreamId; + + // config data + char m_AutolinkModule; }; diff --git a/reflector/YSFUtils.cpp b/reflector/YSFUtils.cpp index 32349a9..b47cf8d 100644 --- a/reflector/YSFUtils.cpp +++ b/reflector/YSFUtils.cpp @@ -19,20 +19,11 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . - #include #include "YSFDefines.h" #include "YSFUtils.h" #include "Golay24128.h" -//////////////////////////////////////////////////////////////////////////////////////// -// constants & defines - - - -//////////////////////////////////////////////////////////////////////////////////////// -// - void CYsfUtils::DecodeVD2Vchs(uint8_t *data, uint8_t **ambe) { int frame = 0; diff --git a/reflector/YSFUtils.h b/reflector/YSFUtils.h index 6805c66..6191a7f 100644 --- a/reflector/YSFUtils.h +++ b/reflector/YSFUtils.h @@ -21,6 +21,8 @@ #pragma once +#include + //////////////////////////////////////////////////////////////////////////////////////// // class diff --git a/reflector/example.ini b/reflector/example.ini index 87913d1..98e24be 100644 --- a/reflector/example.ini +++ b/reflector/example.ini @@ -58,7 +58,7 @@ Port = 17000 [MMDVM] Port = 62030 -DefaultId = 0 +DefaultId = 0 # if the DMR id is zero, this will be used (also used for P25) [NXDN] Port = 41400 From c21521eb10f10df43830992d2b6343fe6ba3bbbd Mon Sep 17 00:00:00 2001 From: Tom Early Date: Sun, 12 Feb 2023 09:54:05 -0700 Subject: [PATCH 03/44] restuctured json key string constants --- reflector/CallsignListItem.cpp | 4 +- reflector/Configure.cpp | 244 +++++++++++++++++---------------- reflector/Configure.h | 48 ------- reflector/DMRMMDVMProtocol.cpp | 2 +- reflector/Defines.h | 1 - reflector/G3Protocol.cpp | 4 +- reflector/GateKeeper.cpp | 6 +- reflector/Global.h | 2 + reflector/JsonKeys.h | 57 ++++++++ reflector/LookupDmr.cpp | 12 +- reflector/LookupNxdn.cpp | 12 +- reflector/LookupYsf.cpp | 16 +-- reflector/Main.cpp | 5 +- reflector/NXDNProtocol.cpp | 4 +- reflector/P25Protocol.cpp | 6 +- reflector/Protocol.cpp | 6 +- reflector/Protocols.cpp | 24 ++-- reflector/Reflector.cpp | 8 +- reflector/USRPProtocol.cpp | 6 +- reflector/WiresXCmdHandler.cpp | 2 +- reflector/YSFProtocol.cpp | 2 +- 21 files changed, 242 insertions(+), 229 deletions(-) create mode 100644 reflector/JsonKeys.h diff --git a/reflector/CallsignListItem.cpp b/reflector/CallsignListItem.cpp index 01bebab..27cfba8 100644 --- a/reflector/CallsignListItem.cpp +++ b/reflector/CallsignListItem.cpp @@ -33,7 +33,7 @@ CCallsignListItem::CCallsignListItem() CCallsignListItem::CCallsignListItem(const CCallsign &callsign, const CIp &ip, const char *modules) { - const std::string mods(g_Conf.GetString(g_Conf.j.modules.modules)); + const std::string mods(g_Conf.GetString(g_Keys.modules.modules)); m_Callsign = callsign; memset(m_szUrl, 0, sizeof(m_szUrl)); m_Ip = ip; @@ -60,7 +60,7 @@ CCallsignListItem::CCallsignListItem(const CCallsign &callsign, const CIp &ip, c CCallsignListItem::CCallsignListItem(const CCallsign &callsign, const char *url, const char *modules) { - const std::string mods(g_Conf.GetString(g_Conf.j.modules.modules)); + const std::string mods(g_Conf.GetString(g_Keys.modules.modules)); m_Callsign = callsign; ::strncpy(m_szUrl, url, URL_MAXLEN); m_Ip = CIp(m_szUrl); diff --git a/reflector/Configure.cpp b/reflector/Configure.cpp index de6b31f..73b46f6 100644 --- a/reflector/Configure.cpp +++ b/reflector/Configure.cpp @@ -27,7 +27,7 @@ #include #include -#include "Configure.h" +#include "Global.h" // ini file keywords #define JAUTOLINKMODULE "AutoLinkModule" @@ -183,7 +183,7 @@ bool CConfigure::ReadData(const std::string &path) bool rval = false; ESection section = ESection::none; counter = 0; - REFLECTOR::DB *pdb; + SJsonKeys::DB *pdb; //data.ysfalmodule = 0; //data.DPlusPort = data.DCSPort = data.DExtraPort = data.BMPort = data.DMRPlusPort = 0; @@ -287,32 +287,32 @@ bool CConfigure::ReadData(const std::string &path) { case ESection::names: if (0 == key.compare(JCALLSIGN)) - data[j.names.cs] = value; + data[g_Keys.names.cs] = value; else if (0 == key.compare(JSYSOPEMAIL)) - data[j.names.email] = value; + data[g_Keys.names.email] = value; else if (0 == key.compare(JCOUNTRY)) - data[j.names.country] = value.substr(0,2); + data[g_Keys.names.country] = value.substr(0,2); else if (0 == key.compare(JSPONSOR)) - data[j.names.sponsor] = value; + data[g_Keys.names.sponsor] = value; else badParam(key); break; case ESection::ip: if (0 == key.compare(JIPV4BINDING)) { - data[j.ip.ipv4bind] = value; + data[g_Keys.ip.ipv4bind] = value; } else if (0 == key.compare(JIPV6BINDING)) { - data[j.ip.ipv6bind] = value; + data[g_Keys.ip.ipv6bind] = value; } else if (0 == key.compare(JIPV4EXTERNAL)) { - data[j.ip.ipv4address] = value; + data[g_Keys.ip.ipv4address] = value; } else if (0 == key.compare(JIPV6EXTERNAL)) { - data[j.ip.ipv6address] = value; + data[g_Keys.ip.ipv6address] = value; } else if (0 == key.compare(JTRANSCODER)) { @@ -320,7 +320,7 @@ bool CConfigure::ReadData(const std::string &path) { std::cout << "WARNING: Line #" << counter << ": malformed transcoder address, '" << value << "', resetting..." << std::endl; } - data[j.ip.transcoder] = "local"; + data[g_Keys.ip.transcoder] = "local"; } else badParam(key); @@ -334,7 +334,7 @@ bool CConfigure::ReadData(const std::string &path) std::cerr << "ERROR: line #" << counter << ": no letters found in Modules: '" << m << "'" << std::endl; rval = true; } else - data[j.modules.modules] = m; + data[g_Keys.modules.modules] = m; } else if (0 == key.compare(JTRANSCODED)) { @@ -344,7 +344,7 @@ bool CConfigure::ReadData(const std::string &path) std::cerr << "ERROR: line #" << counter << ": no letters found in Transcoded: '" << m << "'" << std::endl; rval = true; } else - data[j.modules.tcmodules] = m; + data[g_Keys.modules.tcmodules] = m; } else if (0 == key.compare(0, 11, "Description")) { @@ -358,79 +358,79 @@ bool CConfigure::ReadData(const std::string &path) break; case ESection::bm: if (0 == key.compare(JPORT)) - data[j.bm.port] = getUnsigned(value, "Brandmeister Port", 1024, 65535, 10002); + data[g_Keys.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); + data[g_Keys.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); + data[g_Keys.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); + data[g_Keys.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); + data[g_Keys.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); + data[g_Keys.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); + data[g_Keys.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); + data[g_Keys.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); + data[g_Keys.nxdn.port] = getUnsigned(value, "NDXN Port", 1024, 65535, 41400); else if (0 == key.compare(JAUTOLINKMODULE)) - setAutolink(JNXDN, j.nxdn.autolinkmod, value); + setAutolink(JNXDN, g_Keys.nxdn.autolinkmod, value); else if (0 == key.compare(JREFLECTORID)) - data[j.nxdn.reflectorid] = getUnsigned(value, "NXDN ReflectorID", 0, 65535, 0); + data[g_Keys.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); + data[g_Keys.p25.port] = getUnsigned(value, "P25 Port", 1024, 65535, 41000); else if (0 == key.compare(JAUTOLINKMODULE)) - setAutolink(JP25, j.p25.autolinkmod, value); + setAutolink(JP25, g_Keys.p25.autolinkmod, value); else if (0 == key.compare(JREFLECTORID)) - data[j.p25.reflectorid] = getUnsigned(value, "P25 ReflectorID", 0, 16777215, 0); + data[g_Keys.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); + data[g_Keys.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); + data[g_Keys.usrp.port] = getUnsigned(value, "USRP Port", 1024, 65535, 34001); else if (0 == key.compare(JAUTOLINKMODULE)) - setAutolink(JUSRP, j.usrp.autolinkmod, value); + setAutolink(JUSRP, g_Keys.usrp.autolinkmod, value); else if (0 == key.compare(JDEFAULTCALLSIGN)) { std::string cs; @@ -438,35 +438,35 @@ bool CConfigure::ReadData(const std::string &path) if (isalnum(c)) cs.append(1, toupper(c)); if (cs.size() > 7) cs.resize(7); - data[j.usrp.defaultcallsign] = cs; + data[g_Keys.usrp.defaultcallsign] = cs; } else if (0 == key.compare(JCLIENTSPATH)) - data[j.usrp.clientfilepath] = value; + data[g_Keys.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); + data[g_Keys.ysf.port] = getUnsigned(value, "YSF Port", 1024, 65535, 42000); else if (0 == key.compare(JAUTOLINKMODULE)) - setAutolink(JYSF, j.ysf.autolinkmod, value); + setAutolink(JYSF, g_Keys.ysf.autolinkmod, value); else if (0 == key.compare(JDEFAULTTXFREQ)) - data[j.ysf.defaulttxfreq] = getUnsigned(value, "YSF DefaultTxFreq", 40000000, 2600000000, 439000000); + data[g_Keys.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); + data[g_Keys.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); + data[g_Keys.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; + data[g_Keys.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; + data[g_Keys.ysf.ysfreflectordb.description] = desc; } else badParam(key); @@ -476,9 +476,9 @@ bool CConfigure::ReadData(const std::string &path) 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; + case ESection::dmrid: pdb = &g_Keys.dmriddb; break; + case ESection::nxdnid: pdb = &g_Keys.nxdniddb; break; + case ESection::ysffreq: pdb = &g_Keys.ysftxrxdb; break; } if (0 == key.compare(JHOSTNAME)) data[pdb->hostname] = value; @@ -503,17 +503,17 @@ bool CConfigure::ReadData(const std::string &path) break; case ESection::files: if (0 == key.compare(JPIDPATH)) - data[j.files.pid] = value; + data[g_Keys.files.pid] = value; else if (0 == key.compare(JJSONPATH)) - data[j.files.json] = value; + data[g_Keys.files.json] = value; else if (0 == key.compare(JWHITELISTPATH)) - data[j.files.white] = value; + data[g_Keys.files.white] = value; else if (0 == key.compare(JBLACKLISTPATH)) - data[j.files.black] = value; + data[g_Keys.files.black] = value; else if (0 == key.compare(JINTERLINKPATH)) - data[j.files.interlink] = value; + data[g_Keys.files.interlink] = value; else if (0 == key.compare(JG3TERMINALPATH)) - data[j.files.terminal] = value; + data[g_Keys.files.terminal] = value; else badParam(key); break; @@ -526,9 +526,9 @@ bool CConfigure::ReadData(const std::string &path) ////////////////////////////// check the input // Names section - if (isDefined(ErrorLevel::fatal, JNAMES, JCALLSIGN, j.names.cs, rval)) + if (isDefined(ErrorLevel::fatal, JNAMES, JCALLSIGN, g_Keys.names.cs, rval)) { - const auto cs = data[j.names.cs].get(); + const auto cs = data[g_Keys.names.cs].get(); auto RefRegEx = std::regex("^URF([A-Z0-9]){3,3}$", std::regex::extended); if (! std::regex_match(cs, RefRegEx)) { @@ -537,19 +537,19 @@ bool CConfigure::ReadData(const std::string &path) } } - 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); + isDefined(ErrorLevel::mild, JNAMES, JSYSOPEMAIL, g_Keys.names.email, rval); + isDefined(ErrorLevel::mild, JNAMES, JCOUNTRY, g_Keys.names.country, rval); + isDefined(ErrorLevel::mild, JNAMES, JSPONSOR, g_Keys.names.sponsor, rval); // IP Address section // ipv4 bind and external - if (isDefined(ErrorLevel::fatal, JIPADDRESSES, JIPV4BINDING, j.ip.ipv4bind, rval)) + if (isDefined(ErrorLevel::fatal, JIPADDRESSES, JIPV4BINDING, g_Keys.ip.ipv4bind, rval)) { - if (std::regex_match(data[j.ip.ipv4bind].get(), IPv4RegEx)) + if (std::regex_match(data[g_Keys.ip.ipv4bind].get(), IPv4RegEx)) { - if (data.contains(j.ip.ipv4address)) + if (data.contains(g_Keys.ip.ipv4address)) { - auto v4 = data[j.ip.ipv4address].get(); + auto v4 = data[g_Keys.ip.ipv4address].get(); if (std::regex_match(v4, IPv4RegEx)) { if (ipv4.compare(v4)) @@ -565,7 +565,7 @@ bool CConfigure::ReadData(const std::string &path) { // make sure curl worked! if (std::regex_match(ipv4, IPv4RegEx)) - data[j.ip.ipv4address] = ipv4; + data[g_Keys.ip.ipv4address] = ipv4; else { std::cerr << "ERROR: could not detect IPv4 address at this time" << std::endl; @@ -575,19 +575,19 @@ bool CConfigure::ReadData(const std::string &path) } else { - std::cerr << "ERROR: IPv4 binding address, " << data[j.ip.ipv4address].get() << ", is malformed" << std::endl; + std::cerr << "ERROR: IPv4 binding address, " << data[g_Keys.ip.ipv4address].get() << ", is malformed" << std::endl; rval = true; } } // ipv6 bind and external - if (data.contains(j.ip.ipv6bind)) + if (data.contains(g_Keys.ip.ipv6bind)) { - if (std::regex_match(data[j.ip.ipv6bind].get(), IPv6RegEx)) + if (std::regex_match(data[g_Keys.ip.ipv6bind].get(), IPv6RegEx)) { - if (data.contains(j.ip.ipv6address)) + if (data.contains(g_Keys.ip.ipv6address)) { - auto v6 = data[j.ip.ipv6address].get(); + auto v6 = data[g_Keys.ip.ipv6address].get(); if (std::regex_match(v6, IPv6RegEx)) { if (ipv6.compare(v6)) @@ -603,7 +603,7 @@ bool CConfigure::ReadData(const std::string &path) { // make sure curl worked! if (std::regex_match(ipv6, IPv6RegEx)) - data[j.ip.ipv6address] = ipv6; + data[g_Keys.ip.ipv6address] = ipv6; else { std::cerr << "ERROR: could not detect IPv6 address at this time" << std::endl; @@ -613,23 +613,23 @@ bool CConfigure::ReadData(const std::string &path) } else { - std::cerr << "ERROR: IPv6 binding address, " << data[j.ip.ipv6address].get() << ", is malformed" << std::endl; + std::cerr << "ERROR: IPv6 binding address, " << data[g_Keys.ip.ipv6address].get() << ", is malformed" << std::endl; rval = true; } } else { - data[j.ip.ipv4bind] = nullptr; - data[j.ip.ipv6address] = nullptr; + data[g_Keys.ip.ipv4bind] = nullptr; + data[g_Keys.ip.ipv6address] = nullptr; } // Modules section - if (isDefined(ErrorLevel::fatal, JMODULES, JMODULES, j.modules.modules, rval)) + if (isDefined(ErrorLevel::fatal, JMODULES, JMODULES, g_Keys.modules.modules, rval)) { - const auto mods(data[j.modules.modules].get()); - if (data.contains(j.modules.tcmodules)) + const auto mods(data[g_Keys.modules.modules].get()); + if (data.contains(g_Keys.modules.tcmodules)) { - const auto tcmods(data[j.modules.tcmodules].get()); + const auto tcmods(data[g_Keys.modules.tcmodules].get()); // how many transcoded modules auto size = tcmods.size(); @@ -637,7 +637,7 @@ bool CConfigure::ReadData(const std::string &path) 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]) + for (auto c : data[g_Keys.modules.tcmodules]) { if (std::string::npos == mods.find(c)) { @@ -647,69 +647,69 @@ bool CConfigure::ReadData(const std::string &path) } } else - data[j.modules.tcmodules] = nullptr; + data[g_Keys.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])) + if (data.contains(g_Keys.modules.descriptor[i])) { - std::cout << "WARNING: " << j.modules.descriptor[i] << " defined for an unconfigured module. Deleting..." << std::endl; - data.erase(j.modules.descriptor[i]); + std::cout << "WARNING: " << g_Keys.modules.descriptor[i] << " defined for an unconfigured module. Deleting..." << std::endl; + data.erase(g_Keys.modules.descriptor[i]); } } else { - if (! data.contains(j.modules.descriptor[i])) + if (! data.contains(g_Keys.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; + std::cout << "WARNING: " << g_Keys.modules.descriptor[i] << " not found. Setting to " << value << std::endl; + data[g_Keys.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); + isDefined(ErrorLevel::fatal, JBRANDMEISTER, JPORT, g_Keys.bm.port, rval); + isDefined(ErrorLevel::fatal, JDCS, JPORT, g_Keys.dcs.port, rval); + isDefined(ErrorLevel::fatal, JDEXTRA, JPORT, g_Keys.dextra.port, rval); + isDefined(ErrorLevel::fatal, JDMRPLUS, JPORT, g_Keys.dmrplus.port, rval); + isDefined(ErrorLevel::fatal, JDPLUS, JPORT, g_Keys.dplus.port, rval); + isDefined(ErrorLevel::fatal, JM17, JPORT, g_Keys.m17.port, rval); + isDefined(ErrorLevel::fatal, JURF, JPORT, g_Keys.urf.port, rval); // MMDVM - isDefined(ErrorLevel::fatal, JMMDVM, JPORT, j.mmdvm.port, rval); - isDefined(ErrorLevel::fatal, JMMDVM, JDEFAULTID, j.mmdvm.defaultid, rval); + isDefined(ErrorLevel::fatal, JMMDVM, JPORT, g_Keys.mmdvm.port, rval); + isDefined(ErrorLevel::fatal, JMMDVM, JDEFAULTID, g_Keys.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); + isDefined(ErrorLevel::fatal, JNXDN, JPORT, g_Keys.nxdn.port, rval); + checkAutoLink(JNXDN, JAUTOLINKMODULE, g_Keys.nxdn.autolinkmod, rval); + isDefined(ErrorLevel::fatal, JNXDN, JREFLECTORID, g_Keys.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); + isDefined(ErrorLevel::fatal, JP25, JPORT, g_Keys.p25.port, rval); + checkAutoLink(JP25, JAUTOLINKMODULE, g_Keys.p25.autolinkmod, rval); + isDefined(ErrorLevel::fatal, JP25, JREFLECTORID, g_Keys.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); + isDefined(ErrorLevel::fatal, JUSRP, JPORT, g_Keys.usrp.port, rval); + checkAutoLink(JUSRP, JAUTOLINKMODULE, g_Keys.usrp.autolinkmod, rval); + isDefined(ErrorLevel::fatal, JUSRP, JDEFAULTCALLSIGN, g_Keys.usrp.defaultcallsign, rval); + isDefined(ErrorLevel::fatal, JUSRP, JCLIENTSPATH, g_Keys.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); + isDefined(ErrorLevel::fatal, JYSF, JPORT, g_Keys.ysf.port, rval); + checkAutoLink(JYSF, JAUTOLINKMODULE, g_Keys.ysf.autolinkmod, rval); + isDefined(ErrorLevel::fatal, JYSF, JDEFAULTRXFREQ, g_Keys.ysf.defaultrxfreq, rval); + isDefined(ErrorLevel::fatal, JYSF, JDEFAULTTXFREQ, g_Keys.ysf.defaulttxfreq, rval); + isDefined(ErrorLevel::mild, JYSF, JREGISTRATIONID, g_Keys.ysf.ysfreflectordb.id, rval); + isDefined(ErrorLevel::mild, JYSF, JREGISTRATIONNAME, g_Keys.ysf.ysfreflectordb.name, rval); + isDefined(ErrorLevel::mild, JYSF, JREGISTRATIONDESCRIPTION, g_Keys.ysf.ysfreflectordb.description, rval); // Databases - std::list> dbs = { - { JDMRIDDB, &j.dmriddb }, - { JNXDNIDDB, &j.nxdniddb }, - { JYSFTXRXDB, &j.ysftxrxdb } + std::list> dbs = { + { JDMRIDDB, &g_Keys.dmriddb }, + { JNXDNIDDB, &g_Keys.nxdniddb }, + { JYSFTXRXDB, &g_Keys.ysftxrxdb } }; for ( auto &item : dbs ) { @@ -720,12 +720,12 @@ bool CConfigure::ReadData(const std::string &path) 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); + isDefined(ErrorLevel::fatal, JFILES, JPIDPATH, g_Keys.files.pid, rval); + isDefined(ErrorLevel::fatal, JFILES, JJSONPATH, g_Keys.files.json, rval); + isDefined(ErrorLevel::fatal, JFILES, JWHITELISTPATH, g_Keys.files.white, rval); + isDefined(ErrorLevel::fatal, JFILES, JBLACKLISTPATH, g_Keys.files.black, rval); + isDefined(ErrorLevel::fatal, JFILES, JINTERLINKPATH, g_Keys.files.interlink, rval); + isDefined(ErrorLevel::fatal, JFILES, JG3TERMINALPATH, g_Keys.files.terminal, rval); return rval; } @@ -752,8 +752,8 @@ void CConfigure::checkAutoLink(const std::string §ion, const std::string &pn { if (data.contains(key)) { - auto ismods = data.contains(j.modules.modules); - const auto mods(ismods ? data[j.modules.modules].get() : ""); + auto ismods = data.contains(g_Keys.modules.modules); + const auto mods(ismods ? data[g_Keys.modules.modules].get() : ""); const auto c = data[key].get().at(0); if (std::string::npos == mods.find(c)) { @@ -913,16 +913,18 @@ bool CConfigure::IsString(const std::string &key) const } #ifdef INICHECK +SJsonKeys g_Keys; int main(int argc, char *argv[]) { - if (argc == 2 || argc == 3) + if (3 == argc && strlen(argv[1]) > 1 && '-' == argv[1][0]) { CConfigure d; - auto rval = d.ReadData(argv[argc-1]); - d.Dump((2==argc) ? false : true); + auto rval = d.ReadData(argv[2]); + if ('q' != argv[1][1]) + d.Dump(('n' == argv[1][1]) ? true : false); return rval ? EXIT_FAILURE : EXIT_SUCCESS; } - std::cerr << "Usage: " << argv[0] << " FILENAME\nWhere is anything.\nThis option only shows values whose key begins with an uppercase letter." << std::endl; + std::cerr << "Usage: " << argv[0] << " -(q|n|v) FILENAME\nWhere:\n\t-q just prints warnings and errors.\n\t-n also prints keys that begin with an uppercase letter.\n\t-v prints all keys, warnings and errors." << std::endl; return EXIT_SUCCESS; } #endif diff --git a/reflector/Configure.h b/reflector/Configure.h index dee5086..9686ed9 100644 --- a/reflector/Configure.h +++ b/reflector/Configure.h @@ -32,54 +32,6 @@ enum class ESection { none, names, ip, modules, urf, dplus, dextra, dcs, dmrplus 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; diff --git a/reflector/DMRMMDVMProtocol.cpp b/reflector/DMRMMDVMProtocol.cpp index ec0b60e..0515537 100644 --- a/reflector/DMRMMDVMProtocol.cpp +++ b/reflector/DMRMMDVMProtocol.cpp @@ -48,7 +48,7 @@ static uint8_t g_DmrSyncMSData[] = { 0x0D,0x5D,0x7F,0x77,0xFD,0x75,0x70 }; bool CDmrmmdvmProtocol::Initialize(const char *type, const EProtocol ptype, const uint16_t port, const bool has_ipv4, const bool has_ipv6) { - m_DefaultId = g_Conf.GetUnsigned(g_Conf.j.mmdvm.defaultid); + m_DefaultId = g_Conf.GetUnsigned(g_Keys.mmdvm.defaultid); // base class if (! CProtocol::Initialize(type, ptype, port, has_ipv4, has_ipv6)) return false; diff --git a/reflector/Defines.h b/reflector/Defines.h index 862451d..8d28a4a 100644 --- a/reflector/Defines.h +++ b/reflector/Defines.h @@ -135,7 +135,6 @@ enum class EProtocol { any, none, dextra, dplus, dcs, g3, bm, urf, dmrplus, dmrm // macros #define MIN(a,b) ((a)<(b))?(a):(b) -#define MAX(a,b) ((a)>(b))?(a):(b) #define MAKEWORD(low, high) ((uint16_t)(((uint8_t)(low)) | (((uint16_t)((uint8_t)(high))) << 8))) #define MAKEDWORD(low, high) ((uint32_t)(((uint16_t)(low)) | (((uint32_t)((uint16_t)(high))) << 16))) #define LOBYTE(w) ((uint8_t)(uint16_t)(w & 0x00FF)) diff --git a/reflector/G3Protocol.cpp b/reflector/G3Protocol.cpp index 46bcb0f..c49ffc1 100644 --- a/reflector/G3Protocol.cpp +++ b/reflector/G3Protocol.cpp @@ -33,8 +33,8 @@ bool CG3Protocol::Initialize(const char */*type*/, const EProtocol /*type*/, con // everything is hard coded until ICOM gets their act together and start supporting IPv6 { //config data - m_TerminalPath.assign(g_Conf.GetString(g_Conf.j.files.terminal)); - const std::string ipv4address(g_Conf.GetString(g_Conf.j.ip.ipv4bind)); + m_TerminalPath.assign(g_Conf.GetString(g_Keys.files.terminal)); + const std::string ipv4address(g_Conf.GetString(g_Keys.ip.ipv4bind)); ReadOptions(); diff --git a/reflector/GateKeeper.cpp b/reflector/GateKeeper.cpp index ce357dd..1ec17e9 100644 --- a/reflector/GateKeeper.cpp +++ b/reflector/GateKeeper.cpp @@ -49,9 +49,9 @@ bool CGateKeeper::Init(void) { // load lists from files - m_NodeWhiteList.LoadFromFile(g_Conf.GetString(g_Conf.j.files.white)); - m_NodeBlackList.LoadFromFile(g_Conf.GetString(g_Conf.j.files.black)); - m_PeerList.LoadFromFile(g_Conf.GetString(g_Conf.j.files.interlink)); + m_NodeWhiteList.LoadFromFile(g_Conf.GetString(g_Keys.files.white)); + m_NodeBlackList.LoadFromFile(g_Conf.GetString(g_Keys.files.black)); + m_PeerList.LoadFromFile(g_Conf.GetString(g_Keys.files.interlink)); // reset run flag keep_running = true; diff --git a/reflector/Global.h b/reflector/Global.h index 39c515d..611f347 100644 --- a/reflector/Global.h +++ b/reflector/Global.h @@ -21,6 +21,7 @@ #include "LookupDmr.h" #include "LookupNxdn.h" #include "LookupYsf.h" +#include "JsonKeys.h" extern CReflector g_Refl; extern CGateKeeper g_Gate; @@ -29,3 +30,4 @@ extern CVersion g_Vers; extern CLookupDmr g_LDid; extern CLookupNxdn g_LNid; extern CLookupYsf g_LYtr; +extern SJsonKeys g_Keys; diff --git a/reflector/JsonKeys.h b/reflector/JsonKeys.h new file mode 100644 index 0000000..02921bc --- /dev/null +++ b/reflector/JsonKeys.h @@ -0,0 +1,57 @@ +/* + * 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 + +#pragma once + +// configuration key names +struct SJsonKeys { + struct PORTONLY { const std::string port; } + bm { "BrandMeisterPort" }, + dcs { "DCSPort" }, + dextra { "DExtraPort" }, + dmrplus { "DMRPlusPort" }, + dplus { "DPlusPort" }, + m17 { "M17Port" }, + urf { "URFPort" }; + struct MMDVM { const std::string port, defaultid; } + mmdvm { "MMDVMPort", "mmdvmdefaultid" }; + struct NAMES { const std::string cs, email, country, sponsor; } + names { "Callsign", "SysopEmail", "Country", "Sponsor" }; + struct IP { const std::string ipv4bind, ipv4address, ipv6bind, ipv6address, transcoder; } + ip { "ipv4bind", "IPv4Address", "ipv6bind", "IPv6Address", "tcaddress" }; + struct MODULES { const std::string modules, tcmodules, descriptor[26]; } + modules { "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" }; + struct USRP { const std::string port, autolinkmod, defaultcallsign, clientfilepath; } + usrp { "USRPPort", "USRPAutolinkMod", "usrpDefaultCallsign", "usrpClientfilePath" }; + struct P25NXDN { const std::string port, autolinkmod, reflectorid; } + p25 { "P25Port", "P25AutolinkMod", "P25ReflectorID" }, + nxdn { "NXDNPort", "NXDNAutolinkMod", "NXDNReflectorID" }; + struct YSF { const std::string port, autolinkmod, defaulttxfreq, defaultrxfreq; + struct YSLREG { const std::string id, name, description; } ysfreflectordb; } + ysf { "YSFPort", "YSFAutoLinkMod", "YSFDefaultTxFreq", "YSFDefaultRxFreq", + { "ysfrefdbid", "ysfrefdbname", "ysfrefdbdesc" } }; + struct DB { const std::string hostname, suffix, mode, refreshmin, filepath; } + dmriddb { "dmrIdDbHost", "dmrIdDbSuffix", "dmrIdDbMode", "dmrIdDbRefresh", "dmrIdDbFilePath" }, + nxdniddb { "nxdnIdDbHost", "nxdnIdDbSuffix", "nxdnIdDbMode", "nxdnIdDbRefresh", "nxdnIdDbFilePath" }, + ysftxrxdb { "ysfIdDbHost", "ysfIdDbSuffix", "ysfIdDbMode", "ysfIdDbRefresh", "ysfIdDbFilePath" }; + struct FILES { const std::string pid, json, white, black, interlink, terminal; } + files { "pidFilePath", "jsonFilePath", "whitelistFilePath", "blacklistFilePath", "interlinkFilePath", "g3TerminalFilePath" }; +}; diff --git a/reflector/LookupDmr.cpp b/reflector/LookupDmr.cpp index 2e64812..14c7363 100644 --- a/reflector/LookupDmr.cpp +++ b/reflector/LookupDmr.cpp @@ -31,11 +31,11 @@ void CLookupDmr::ClearContents() void CLookupDmr::LoadParameters() { - m_Type = g_Conf.GetRefreshType(g_Conf.j.dmriddb.mode); - m_Refresh = g_Conf.GetUnsigned(g_Conf.j.dmriddb.refreshmin); - m_Path.assign(g_Conf.GetString(g_Conf.j.dmriddb.filepath)); - m_Host.assign(g_Conf.GetString(g_Conf.j.dmriddb.hostname)); - m_Suffix.assign(g_Conf.GetString(g_Conf.j.dmriddb.suffix)); + m_Type = g_Conf.GetRefreshType(g_Keys.dmriddb.mode); + m_Refresh = g_Conf.GetUnsigned(g_Keys.dmriddb.refreshmin); + m_Path.assign(g_Conf.GetString(g_Keys.dmriddb.filepath)); + m_Host.assign(g_Conf.GetString(g_Keys.dmriddb.hostname)); + m_Suffix.assign(g_Conf.GetString(g_Keys.dmriddb.suffix)); } uint32_t CLookupDmr::FindDmrid(const CCallsign &callsign) @@ -200,7 +200,7 @@ bool CLookupDmr::HttpGet(const char *hostname, const char *filename, int port, C { // 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, g_Conf.GetString(g_Conf.j.names.cs).c_str()); + ::sprintf(request, "GET /%s HTTP/1.0\r\nFrom: %s\r\nUser-Agent: urfd\r\n\r\n", filename, g_Conf.GetString(g_Keys.names.cs).c_str()); ::write(sock_id, request, strlen(request)); // config receive timeouts diff --git a/reflector/LookupNxdn.cpp b/reflector/LookupNxdn.cpp index ee0da2a..1aac8fa 100644 --- a/reflector/LookupNxdn.cpp +++ b/reflector/LookupNxdn.cpp @@ -31,11 +31,11 @@ void CLookupNxdn::ClearContents() void CLookupNxdn::LoadParameters() { - m_Type = g_Conf.GetRefreshType(g_Conf.j.nxdniddb.mode); - m_Refresh = g_Conf.GetUnsigned(g_Conf.j.nxdniddb.refreshmin); - m_Path.assign(g_Conf.GetString(g_Conf.j.nxdniddb.filepath)); - m_Host.assign(g_Conf.GetString(g_Conf.j.nxdniddb.hostname)); - m_Suffix.assign(g_Conf.GetString(g_Conf.j.nxdniddb.suffix)); + m_Type = g_Conf.GetRefreshType(g_Keys.nxdniddb.mode); + m_Refresh = g_Conf.GetUnsigned(g_Keys.nxdniddb.refreshmin); + m_Path.assign(g_Conf.GetString(g_Keys.nxdniddb.filepath)); + m_Host.assign(g_Conf.GetString(g_Keys.nxdniddb.hostname)); + m_Suffix.assign(g_Conf.GetString(g_Keys.nxdniddb.suffix)); } const CCallsign *CLookupNxdn::FindCallsign(uint16_t nxdnid) @@ -202,7 +202,7 @@ bool CLookupNxdn::HttpGet(const char *hostname, const char *filename, int port, { // send the GET request char request[NXDNID_HTTPGET_SIZEMAX]; - ::sprintf(request, "GET /%s HTTP/1.0\r\nFrom: %s\r\nUser-Agent: urfd\r\n\r\n", filename, g_Conf.GetString(g_Conf.j.names.cs).c_str()); + ::sprintf(request, "GET /%s HTTP/1.0\r\nFrom: %s\r\nUser-Agent: urfd\r\n\r\n", filename, g_Conf.GetString(g_Keys.names.cs).c_str()); ::write(sock_id, request, strlen(request)); // config receive timeouts diff --git a/reflector/LookupYsf.cpp b/reflector/LookupYsf.cpp index 7b389e4..bb45b69 100644 --- a/reflector/LookupYsf.cpp +++ b/reflector/LookupYsf.cpp @@ -31,13 +31,13 @@ void CLookupYsf::ClearContents() void CLookupYsf::LoadParameters() { - m_Type = g_Conf.GetRefreshType(g_Conf.j.ysftxrxdb.mode); - m_Refresh = g_Conf.GetUnsigned(g_Conf.j.ysftxrxdb.refreshmin); - m_Path.assign(g_Conf.GetString(g_Conf.j.ysftxrxdb.filepath)); - m_Host.assign(g_Conf.GetString(g_Conf.j.ysftxrxdb.hostname)); - m_Suffix.assign(g_Conf.GetString(g_Conf.j.ysftxrxdb.suffix)); - m_DefaultTx = g_Conf.GetUnsigned(g_Conf.j.ysf.defaulttxfreq); - m_DefaultRx = g_Conf.GetUnsigned(g_Conf.j.ysf.defaultrxfreq); + m_Type = g_Conf.GetRefreshType(g_Keys.ysftxrxdb.mode); + m_Refresh = g_Conf.GetUnsigned(g_Keys.ysftxrxdb.refreshmin); + m_Path.assign(g_Conf.GetString(g_Keys.ysftxrxdb.filepath)); + m_Host.assign(g_Conf.GetString(g_Keys.ysftxrxdb.hostname)); + m_Suffix.assign(g_Conf.GetString(g_Keys.ysftxrxdb.suffix)); + m_DefaultTx = g_Conf.GetUnsigned(g_Keys.ysf.defaulttxfreq); + m_DefaultRx = g_Conf.GetUnsigned(g_Keys.ysf.defaultrxfreq); } bool CLookupYsf::LoadContentFile(CBuffer &buffer) @@ -178,7 +178,7 @@ bool CLookupYsf::HttpGet(const char *hostname, const char *filename, int port, C { // send the GET request char request[YSFNODE_HTTPGET_SIZEMAX]; - sprintf(request, "GET /%s HTTP/1.0\r\nFrom: %s\r\nUser-Agent: urfd\r\n\r\n", filename, g_Conf.GetString(g_Conf.j.names.cs).c_str()); + sprintf(request, "GET /%s HTTP/1.0\r\nFrom: %s\r\nUser-Agent: urfd\r\n\r\n", filename, g_Conf.GetString(g_Keys.names.cs).c_str()); write(sock_id, request, strlen(request)); // config receive timeouts diff --git a/reflector/Main.cpp b/reflector/Main.cpp index 556c2ab..21d8205 100644 --- a/reflector/Main.cpp +++ b/reflector/Main.cpp @@ -30,6 +30,7 @@ CVersion g_Vers(3,0,0); // The major byte should only change if the interlink CLookupDmr g_LDid; CLookupNxdn g_LNid; CLookupYsf g_LYtr; +SJsonKeys g_Keys; //////////////////////////////////////////////////////////////////////////////////////// @@ -45,8 +46,8 @@ int main(int argc, char *argv[]) return EXIT_FAILURE; // remove pidfile - const std::string pidpath(g_Conf.GetString(g_Conf.j.files.pid)); - const std::string callsign(g_Conf.GetString(g_Conf.j.names.cs)); + const std::string pidpath(g_Conf.GetString(g_Keys.files.pid)); + const std::string callsign(g_Conf.GetString(g_Keys.names.cs)); remove(pidpath.c_str()); // splash diff --git a/reflector/NXDNProtocol.cpp b/reflector/NXDNProtocol.cpp index 66f43ce..a46f488 100644 --- a/reflector/NXDNProtocol.cpp +++ b/reflector/NXDNProtocol.cpp @@ -53,8 +53,8 @@ CNXDNProtocol::CNXDNProtocol() bool CNXDNProtocol::Initialize(const char *type, const EProtocol ptype, const uint16_t port, const bool has_ipv4, const bool has_ipv6) { // config value - m_ReflectorId = g_Conf.GetUnsigned(g_Conf.j.nxdn.reflectorid); - m_AutolinkModule = g_Conf.GetAutolinkModule(g_Conf.j.nxdn.autolinkmod); + m_ReflectorId = g_Conf.GetUnsigned(g_Keys.nxdn.reflectorid); + m_AutolinkModule = g_Conf.GetAutolinkModule(g_Keys.nxdn.autolinkmod); // base class if (! CProtocol::Initialize(type, ptype, port, has_ipv4, has_ipv6)) diff --git a/reflector/P25Protocol.cpp b/reflector/P25Protocol.cpp index 38f86b6..f93da67 100644 --- a/reflector/P25Protocol.cpp +++ b/reflector/P25Protocol.cpp @@ -50,9 +50,9 @@ const uint8_t REC80[] = {0x80U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, bool CP25Protocol::Initialize(const char *type, const EProtocol ptype, const uint16_t port, const bool has_ipv4, const bool has_ipv6) { // config data - m_ReflectorId = g_Conf.GetUnsigned(g_Conf.j.p25.reflectorid); - m_DefaultId = g_Conf.GetUnsigned(g_Conf.j.mmdvm.defaultid); - m_AutolinkModule = g_Conf.GetAutolinkModule(g_Conf.j.p25.autolinkmod); + m_ReflectorId = g_Conf.GetUnsigned(g_Keys.p25.reflectorid); + m_DefaultId = g_Conf.GetUnsigned(g_Keys.mmdvm.defaultid); + m_AutolinkModule = g_Conf.GetAutolinkModule(g_Keys.p25.autolinkmod); m_uiStreamId = 0; // base class diff --git a/reflector/Protocol.cpp b/reflector/Protocol.cpp index 7792901..c5fa213 100644 --- a/reflector/Protocol.cpp +++ b/reflector/Protocol.cpp @@ -64,7 +64,7 @@ bool CProtocol::Initialize(const char *type, const EProtocol ptype, const uint16 // create our sockets if (has_ipv4) { - const std::string ipv4binding(g_Conf.GetString(g_Conf.j.ip.ipv4bind)); + const std::string ipv4binding(g_Conf.GetString(g_Keys.ip.ipv4bind)); CIp ip4(AF_INET, port, ipv4binding.c_str()); if ( ip4.IsSet() ) { @@ -74,11 +74,11 @@ bool CProtocol::Initialize(const char *type, const EProtocol ptype, const uint16 std::cout << "Listening on " << ip4 << std::endl; } - if (g_Conf.IsString(g_Conf.j.ip.ipv6bind)) + if (g_Conf.IsString(g_Keys.ip.ipv6bind)) { if (has_ipv6) { - const std::string ipv6binding(g_Conf.j.ip.ipv6bind); + const std::string ipv6binding(g_Keys.ip.ipv6bind); CIp ip6(AF_INET6, port, ipv6binding.c_str()); if ( ip6.IsSet() ) { diff --git a/reflector/Protocols.cpp b/reflector/Protocols.cpp index b52c801..b14a1d4 100644 --- a/reflector/Protocols.cpp +++ b/reflector/Protocols.cpp @@ -49,51 +49,51 @@ bool CProtocols::Init(void) m_Mutex.lock(); { m_Protocols.emplace_back(std::unique_ptr(new CDextraProtocol)); - if (! m_Protocols.back()->Initialize("XRF", EProtocol::dextra, uint16_t(g_Conf.GetUnsigned(g_Conf.j.dextra.port)), DSTAR_IPV4, DSTAR_IPV6)) + if (! m_Protocols.back()->Initialize("XRF", EProtocol::dextra, uint16_t(g_Conf.GetUnsigned(g_Keys.dextra.port)), DSTAR_IPV4, DSTAR_IPV6)) return false; m_Protocols.emplace_back(std::unique_ptr(new CDplusProtocol)); - if (! m_Protocols.back()->Initialize("REF", EProtocol::dplus, uint16_t(g_Conf.GetUnsigned(g_Conf.j.dplus.port)), DSTAR_IPV4, DSTAR_IPV6)) + if (! m_Protocols.back()->Initialize("REF", EProtocol::dplus, uint16_t(g_Conf.GetUnsigned(g_Keys.dplus.port)), DSTAR_IPV4, DSTAR_IPV6)) return false; m_Protocols.emplace_back(std::unique_ptr(new CDcsProtocol)); - if (! m_Protocols.back()->Initialize("DCS", EProtocol::dcs, uint16_t(g_Conf.GetUnsigned(g_Conf.j.dcs.port)), DSTAR_IPV4, DSTAR_IPV6)) + if (! m_Protocols.back()->Initialize("DCS", EProtocol::dcs, uint16_t(g_Conf.GetUnsigned(g_Keys.dcs.port)), DSTAR_IPV4, DSTAR_IPV6)) return false; m_Protocols.emplace_back(std::unique_ptr(new CDmrmmdvmProtocol)); - if (! m_Protocols.back()->Initialize(nullptr, EProtocol::dmrmmdvm, uint16_t(g_Conf.GetUnsigned(g_Conf.j.mmdvm.port)), DMR_IPV4, DMR_IPV6)) + if (! m_Protocols.back()->Initialize(nullptr, EProtocol::dmrmmdvm, uint16_t(g_Conf.GetUnsigned(g_Keys.mmdvm.port)), DMR_IPV4, DMR_IPV6)) return false; m_Protocols.emplace_back(std::unique_ptr(new CBMProtocol)); - if (! m_Protocols.back()->Initialize("XLX", EProtocol::bm, uint16_t(g_Conf.GetUnsigned(g_Conf.j.bm.port)), DMR_IPV4, DMR_IPV6)) + if (! m_Protocols.back()->Initialize("XLX", EProtocol::bm, uint16_t(g_Conf.GetUnsigned(g_Keys.bm.port)), DMR_IPV4, DMR_IPV6)) return false; m_Protocols.emplace_back(std::unique_ptr(new CDmrplusProtocol)); - if (! m_Protocols.back()->Initialize(nullptr, EProtocol::dmrplus, uint16_t(g_Conf.GetUnsigned(g_Conf.j.dmrplus.port)), DMR_IPV4, DMR_IPV6)) + if (! m_Protocols.back()->Initialize(nullptr, EProtocol::dmrplus, uint16_t(g_Conf.GetUnsigned(g_Keys.dmrplus.port)), DMR_IPV4, DMR_IPV6)) return false; m_Protocols.emplace_back(std::unique_ptr(new CYsfProtocol)); - if (! m_Protocols.back()->Initialize("YSF", EProtocol::ysf, uint16_t(g_Conf.GetUnsigned(g_Conf.j.ysf.port)), YSF_IPV4, YSF_IPV6)) + if (! m_Protocols.back()->Initialize("YSF", EProtocol::ysf, uint16_t(g_Conf.GetUnsigned(g_Keys.ysf.port)), YSF_IPV4, YSF_IPV6)) return false; m_Protocols.emplace_back(std::unique_ptr(new CM17Protocol)); - if (! m_Protocols.back()->Initialize("URF", EProtocol::m17, uint16_t(g_Conf.GetUnsigned(g_Conf.j.m17.port)), M17_IPV4, M17_IPV6)) + if (! m_Protocols.back()->Initialize("URF", EProtocol::m17, uint16_t(g_Conf.GetUnsigned(g_Keys.m17.port)), M17_IPV4, M17_IPV6)) return false; m_Protocols.emplace_back(std::unique_ptr(new CP25Protocol)); - if (! m_Protocols.back()->Initialize("P25", EProtocol::p25, uint16_t(g_Conf.GetUnsigned(g_Conf.j.p25.port)), P25_IPV4, P25_IPV6)) + if (! m_Protocols.back()->Initialize("P25", EProtocol::p25, uint16_t(g_Conf.GetUnsigned(g_Keys.p25.port)), P25_IPV4, P25_IPV6)) return false; m_Protocols.emplace_back(std::unique_ptr(new CNXDNProtocol)); - if (! m_Protocols.back()->Initialize("NXDN", EProtocol::nxdn, uint16_t(g_Conf.GetUnsigned(g_Conf.j.nxdn.port)), NXDN_IPV4, NXDN_IPV6)) + if (! m_Protocols.back()->Initialize("NXDN", EProtocol::nxdn, uint16_t(g_Conf.GetUnsigned(g_Keys.nxdn.port)), NXDN_IPV4, NXDN_IPV6)) return false; m_Protocols.emplace_back(std::unique_ptr(new CUSRPProtocol)); - if (! m_Protocols.back()->Initialize("USRP", EProtocol::usrp, uint16_t(g_Conf.GetUnsigned(g_Conf.j.usrp.port)), USRP_IPV4, USRP_IPV6)) + if (! m_Protocols.back()->Initialize("USRP", EProtocol::usrp, uint16_t(g_Conf.GetUnsigned(g_Keys.usrp.port)), USRP_IPV4, USRP_IPV6)) return false; m_Protocols.emplace_back(std::unique_ptr(new CURFProtocol)); - if (! m_Protocols.back()->Initialize("URF", EProtocol::urf, uint16_t(g_Conf.GetUnsigned(g_Conf.j.urf.port)), URF_IPV4, URF_IPV6)) + if (! m_Protocols.back()->Initialize("URF", EProtocol::urf, uint16_t(g_Conf.GetUnsigned(g_Keys.urf.port)), URF_IPV4, URF_IPV6)) return false; m_Protocols.emplace_back(std::unique_ptr(new CG3Protocol)); diff --git a/reflector/Reflector.cpp b/reflector/Reflector.cpp index a5605ba..2bebf44 100644 --- a/reflector/Reflector.cpp +++ b/reflector/Reflector.cpp @@ -47,9 +47,9 @@ CReflector::~CReflector() bool CReflector::Start(void) { // get config stuff - m_Callsign = CCallsign(g_Conf.GetString(g_Conf.j.names.cs).c_str(), false); - m_Modules.assign(g_Conf.GetString(g_Conf.j.modules.modules)); - std::string tcmods(g_Conf.GetString(g_Conf.j.modules.tcmodules)); + m_Callsign = CCallsign(g_Conf.GetString(g_Keys.names.cs).c_str(), false); + m_Modules.assign(g_Conf.GetString(g_Keys.modules.modules)); + std::string tcmods(g_Conf.GetString(g_Keys.modules.tcmodules)); // let's go! keep_running = true; @@ -323,7 +323,7 @@ void CReflector::RouterThread(const char ThisModule) void CReflector::XmlReportThread() { - const std::string path(g_Conf.GetString(g_Conf.j.files.json)); + const std::string path(g_Conf.GetString(g_Keys.files.json)); while (keep_running) { // report to xml file diff --git a/reflector/USRPProtocol.cpp b/reflector/USRPProtocol.cpp index 9a559fb..0c6c794 100644 --- a/reflector/USRPProtocol.cpp +++ b/reflector/USRPProtocol.cpp @@ -38,8 +38,8 @@ const uint8_t TLV_TAG_SET_INFO = 8; bool CUSRPProtocol::Initialize(const char *type, const EProtocol ptype, const uint16_t port, const bool has_ipv4, const bool has_ipv6) { // config data - m_DefaultCallsign.assign(g_Conf.GetString(g_Conf.j.usrp.defaultcallsign)); - m_AutolinkModule = g_Conf.GetAutolinkModule(g_Conf.j.usrp.autolinkmod); + m_DefaultCallsign.assign(g_Conf.GetString(g_Keys.usrp.defaultcallsign)); + m_AutolinkModule = g_Conf.GetAutolinkModule(g_Keys.usrp.autolinkmod); CBuffer buffer; m_uiStreamId = 0; CCallsign cs(m_DefaultCallsign.c_str()); @@ -51,7 +51,7 @@ bool CUSRPProtocol::Initialize(const char *type, const EProtocol ptype, const ui if (! CProtocol::Initialize(type, ptype, port, has_ipv4, has_ipv6)) return false; - file.open(g_Conf.GetString(g_Conf.j.usrp.clientfilepath), std::ios::in | std::ios::binary | std::ios::ate); + file.open(g_Conf.GetString(g_Keys.usrp.clientfilepath), std::ios::in | std::ios::binary | std::ios::ate); if ( file.is_open() ) { // read file diff --git a/reflector/WiresXCmdHandler.cpp b/reflector/WiresXCmdHandler.cpp index e2c8d63..919c886 100644 --- a/reflector/WiresXCmdHandler.cpp +++ b/reflector/WiresXCmdHandler.cpp @@ -334,7 +334,7 @@ bool CWiresxCmdHandler::ReplyToWiresxAllReqPacket(const CIp &Ip, const CWiresxIn memcpy(data + 12U, WiresxInfo.GetNode(), 10U); // number of entries - const std::string modules(g_Conf.GetString(g_Conf.j.modules.modules)); + const std::string modules(g_Conf.GetString(g_Keys.modules.modules)); uint NB_OF_MODULES = modules.size(); uint total = NB_OF_MODULES; uint n = NB_OF_MODULES - Start; diff --git a/reflector/YSFProtocol.cpp b/reflector/YSFProtocol.cpp index 30fbf46..6869148 100644 --- a/reflector/YSFProtocol.cpp +++ b/reflector/YSFProtocol.cpp @@ -38,7 +38,7 @@ CYsfProtocol::CYsfProtocol() bool CYsfProtocol::Initialize(const char *type, const EProtocol ptype, const uint16_t port, const bool has_ipv4, const bool has_ipv6) { // config data - m_AutolinkModule = g_Conf.GetAutolinkModule(g_Conf.j.ysf.autolinkmod); + m_AutolinkModule = g_Conf.GetAutolinkModule(g_Keys.ysf.autolinkmod); // base class if (! CProtocol::Initialize(type, ptype, port, has_ipv4, has_ipv6)) From f4aab8cfc109ee44d8ba3f627640d9d275861af5 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Sun, 12 Feb 2023 10:57:56 -0700 Subject: [PATCH 04/44] removed all possible configure.h defined values --- reflector/BMProtocol.cpp | 10 +++++----- reflector/BMProtocol.h | 2 ++ reflector/GateKeeper.cpp | 6 ------ reflector/Makefile | 2 +- reflector/PacketStream.cpp | 4 ---- reflector/YSFProtocol.cpp | 40 +++++++++++++++----------------------- reflector/YSFProtocol.h | 2 ++ 7 files changed, 26 insertions(+), 40 deletions(-) diff --git a/reflector/BMProtocol.cpp b/reflector/BMProtocol.cpp index 3d848ce..d733977 100644 --- a/reflector/BMProtocol.cpp +++ b/reflector/BMProtocol.cpp @@ -27,6 +27,7 @@ bool CBMProtocol::Initialize(const char *type, const EProtocol ptype, const uint16_t port, const bool has_ipv4, const bool has_ipv6) { + m_HasTranscoder = g_Conf.IsString(g_Keys.modules.tcmodules); if (! CProtocol::Initialize(type, ptype, port, has_ipv4, has_ipv6)) return false; @@ -225,11 +226,10 @@ void CBMProtocol::HandleQueue(void) break; case EProtoRev::ambe: default: -#ifdef TRANSCODED_MODULES - Send(buffer, client->GetIp()); -#else - Send(bufferLegacy, client->GetIp()); -#endif + if (m_HasTranscoder) + Send(buffer, client->GetIp()); + else + Send(bufferLegacy, client->GetIp()); break; } } diff --git a/reflector/BMProtocol.h b/reflector/BMProtocol.h index 74dfe15..08c0593 100644 --- a/reflector/BMProtocol.h +++ b/reflector/BMProtocol.h @@ -73,4 +73,6 @@ protected: // time CTimer m_LastKeepaliveTime; CTimer m_LastPeersLinkTime; + // config data; + bool m_HasTranscoder; }; diff --git a/reflector/GateKeeper.cpp b/reflector/GateKeeper.cpp index 1ec17e9..8949377 100644 --- a/reflector/GateKeeper.cpp +++ b/reflector/GateKeeper.cpp @@ -92,9 +92,7 @@ bool CGateKeeper::MayLink(const CCallsign &callsign, const CIp &ip, EProtocol pr case EProtocol::p25: case EProtocol::usrp: case EProtocol::nxdn: -#ifndef NO_G3 case EProtocol::g3: -#endif // first check is IP & callsigned listed OK ok &= IsNodeListedOk(callsign, ip); // todo: then apply any protocol specific authorisation for the operation @@ -141,9 +139,7 @@ bool CGateKeeper::MayTransmit(const CCallsign &callsign, const CIp &ip, const EP case EProtocol::p25: case EProtocol::nxdn: case EProtocol::usrp: -#ifndef NO_G3 case EProtocol::g3: -#endif // first check is IP & callsigned listed OK ok = ok && IsNodeListedOk(callsign, ip, module); // todo: then apply any protocol specific authorisation for the operation @@ -300,10 +296,8 @@ const std::string CGateKeeper::ProtocolName(const EProtocol p) const return "USRP"; case EProtocol::bm: return "Brandmeister"; -#ifndef NO_G3 case EProtocol::g3: return "Icom G3"; -#endif default: return "NONE"; } diff --git a/reflector/Makefile b/reflector/Makefile index 8a2a1f8..7930dff 100644 --- a/reflector/Makefile +++ b/reflector/Makefile @@ -25,7 +25,7 @@ INICHECK = inicheck include configure.mk ifeq ($(debug), true) -CFLAGS = -ggdb3 -W -Werror -c -std=c++11 -MMD -MD +CFLAGS = -ggdb3 -DDEBUG -W -Werror -c -std=c++11 -MMD -MD else CFLAGS = -W -Werror -std=c++11 -MMD -MD endif diff --git a/reflector/PacketStream.cpp b/reflector/PacketStream.cpp index a5df4a8..2f6ea53 100644 --- a/reflector/PacketStream.cpp +++ b/reflector/PacketStream.cpp @@ -22,11 +22,7 @@ //////////////////////////////////////////////////////////////////////////////////////// // constructor -#ifdef TRANSCODED_MODULES -CPacketStream::CPacketStream(std::shared_ptr reader) -#else CPacketStream::CPacketStream() -#endif { m_bOpen = false; m_uiStreamId = 0; diff --git a/reflector/YSFProtocol.cpp b/reflector/YSFProtocol.cpp index 6869148..68fcfe9 100644 --- a/reflector/YSFProtocol.cpp +++ b/reflector/YSFProtocol.cpp @@ -25,6 +25,9 @@ #include "YSFProtocol.h" #include "Global.h" +#define REG_NAME_SIZE 16 +#define REG_DESC_SIZE 14 + //////////////////////////////////////////////////////////////////////////////////////// // constructor CYsfProtocol::CYsfProtocol() @@ -39,6 +42,11 @@ bool CYsfProtocol::Initialize(const char *type, const EProtocol ptype, const uin { // config data m_AutolinkModule = g_Conf.GetAutolinkModule(g_Keys.ysf.autolinkmod); + m_RegistrationId = g_Conf.GetUnsigned(g_Keys.ysf.ysfreflectordb.id); + m_RegistrationName.assign(g_Conf.GetString(g_Keys.ysf.ysfreflectordb.name)); + m_RegistrationDesc.assign(g_Conf.GetString(g_Keys.ysf.ysfreflectordb.description)); + m_RegistrationName.resize(REG_NAME_SIZE, ' '); + m_RegistrationDesc.resize(REG_DESC_SIZE, ' '); // base class if (! CProtocol::Initialize(type, ptype, port, has_ipv4, has_ipv6)) @@ -982,32 +990,20 @@ bool CYsfProtocol::IsValidOptionsPacket(const CBuffer &Buffer) const bool CYsfProtocol::EncodeServerStatusPacket(CBuffer *Buffer) const { uint8_t tag[] = { 'Y','S','F','S' }; - uint8_t description[14]; - uint8_t callsign[16]; -#ifdef YSF_REFLECTOR_DESCRIPTION - const std::string desc = YSF_REFLECTOR_DESCRIPTION; -#else - const std::string desc("URF Reflector"); -#endif + uint8_t description[REG_DESC_SIZE]; + uint8_t callsign[REG_NAME_SIZE]; // tag Buffer->Set(tag, sizeof(tag)); // hash - memset(callsign, ' ', sizeof(callsign)); -#ifdef YSF_REFLECTOR_NAME - const std::string cs = YSF_REFLECTOR_NAME; - memcpy(callsign, cs.c_str(), cs.size() > 16 ? 16 : cs.size()); -#else - g_Refl.GetCallsign().GetCallsign(callsign); -#endif + memcpy(callsign, m_RegistrationName.c_str(), 16); char sz[16]; - ::sprintf(sz, "%05u", CalcHash(callsign, 16) % 100000U); + ::sprintf(sz, "%05u", CalcHash(callsign, REG_NAME_SIZE) % 100000U); Buffer->Append((uint8_t *)sz, 5); // name - Buffer->Append(callsign, 16); + Buffer->Append(callsign, REG_NAME_SIZE); // description - memset(description, ' ', sizeof(description)); - memcpy(description, desc.c_str(), desc.size() > 14 ? 14 : desc.size()); - Buffer->Append(description, 14); + memcpy(description, m_RegistrationDesc.c_str(), REG_DESC_SIZE); + Buffer->Append(description, REG_DESC_SIZE); // connected clients CClients *clients = g_Refl.GetClients(); int count = MIN(999, clients->GetSize()); @@ -1021,10 +1017,7 @@ bool CYsfProtocol::EncodeServerStatusPacket(CBuffer *Buffer) const uint32_t CYsfProtocol::CalcHash(const uint8_t *buffer, int len) const { -#ifdef YSF_REFLECTOR_ID - uint32_t hash = YSF_REFLECTOR_ID; -#else - uint32_t hash = 0U; + uint32_t hash = m_RegistrationId; for ( int i = 0; i < len; i++) { @@ -1032,7 +1025,6 @@ uint32_t CYsfProtocol::CalcHash(const uint8_t *buffer, int len) const hash += (hash << 10); hash ^= (hash >> 6); } -#endif hash += (hash << 3); hash ^= (hash >> 11); diff --git a/reflector/YSFProtocol.h b/reflector/YSFProtocol.h index da1eee4..4c30da9 100644 --- a/reflector/YSFProtocol.h +++ b/reflector/YSFProtocol.h @@ -133,4 +133,6 @@ protected: // config data char m_AutolinkModule; + unsigned m_RegistrationId; + std::string m_RegistrationName, m_RegistrationDesc; }; From 153aeb5c732c80598ebd62236e8a0fc1e7631352 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Tue, 14 Feb 2023 10:37:05 -0700 Subject: [PATCH 05/44] curl in a class --- reflector/Callsign.cpp | 2 + reflector/Callsign.h | 1 - reflector/Configure.cpp | 81 ++++++++++------------------------------- reflector/Configure.h | 1 - reflector/CurlGet.cpp | 68 ++++++++++++++++++++++++++++++++++ reflector/CurlGet.h | 34 +++++++++++++++++ reflector/Lookup.cpp | 10 +++++ reflector/Lookup.h | 1 + reflector/LookupDmr.cpp | 6 +-- reflector/LookupYsf.cpp | 4 +- reflector/Makefile | 4 +- reflector/example.ini | 18 ++++----- reflector/example.mk | 6 +++ 13 files changed, 154 insertions(+), 82 deletions(-) create mode 100644 reflector/CurlGet.cpp create mode 100644 reflector/CurlGet.h create mode 100644 reflector/example.mk diff --git a/reflector/Callsign.cpp b/reflector/Callsign.cpp index b0312e3..74a83d9 100644 --- a/reflector/Callsign.cpp +++ b/reflector/Callsign.cpp @@ -408,6 +408,8 @@ bool CCallsign::operator ==(const CCallsign &callsign) const CCallsign::operator const char *() const { + static char m_sz[CALLSIGN_LEN+CALLSUFFIX_LEN+5]; + // empty memset(m_sz, 0, sizeof(m_sz)); // callsign diff --git a/reflector/Callsign.h b/reflector/Callsign.h index e436891..6e5d734 100644 --- a/reflector/Callsign.h +++ b/reflector/Callsign.h @@ -95,7 +95,6 @@ protected: char m_Callsign[CALLSIGN_LEN]; char m_Suffix[CALLSUFFIX_LEN]; char m_Module; - mutable char m_sz[CALLSIGN_LEN+CALLSUFFIX_LEN+5]; uint32_t m_uiDmrid; uint16_t m_uiNXDNid; uint64_t m_coded; // M17 encoded callsign diff --git a/reflector/Configure.cpp b/reflector/Configure.cpp index 73b46f6..b59db6d 100644 --- a/reflector/Configure.cpp +++ b/reflector/Configure.cpp @@ -16,7 +16,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include #include @@ -28,6 +27,7 @@ #include #include "Global.h" +#include "CurlGet.h" // ini file keywords #define JAUTOLINKMODULE "AutoLinkModule" @@ -111,66 +111,6 @@ static inline void trim(std::string &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); @@ -194,7 +134,23 @@ bool CConfigure::ReadData(const std::string &path) } std::string ipv4, ipv6; - CurlAddresses(ipv4, ipv6); + + { + CCurlGet curl; + std::stringstream ss; + if (CURLE_OK == curl.GetURL("https://ipv4.icanhazip.com", ss)) + { + ipv4.assign(ss.str()); + trim(ipv4); + ss.clear(); + } + if (CURLE_OK == curl.GetURL("https://ipv6.icanhazip.com", ss)) + { + std::cout << ss.str(); + ipv6.assign(ss.str()); + trim(ipv6); + } + } std::string line; while (std::getline(cfgfile, line)) @@ -606,6 +562,7 @@ bool CConfigure::ReadData(const std::string &path) data[g_Keys.ip.ipv6address] = ipv6; else { + std::cout << ipv6; std::cerr << "ERROR: could not detect IPv6 address at this time" << std::endl; rval = true; } diff --git a/reflector/Configure.h b/reflector/Configure.h index 9686ed9..7395918 100644 --- a/reflector/Configure.h +++ b/reflector/Configure.h @@ -47,7 +47,6 @@ private: 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; diff --git a/reflector/CurlGet.cpp b/reflector/CurlGet.cpp new file mode 100644 index 0000000..5b11794 --- /dev/null +++ b/reflector/CurlGet.cpp @@ -0,0 +1,68 @@ +/* + * 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 "CurlGet.h" + +CCurlGet::CCurlGet() +{ + curl_global_init(CURL_GLOBAL_ALL); +} + +CCurlGet::~CCurlGet() +{ + curl_global_cleanup(); +} + +// callback function writes data to a std::ostream +size_t CCurlGet::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; +} + +CURLcode CCurlGet::GetURL(const std::string &url, std::stringstream &ss, long timeout) +{ + 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, &ss)) + && 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); + } + if (code != CURLE_OK) + { + std::cout << "ERROR: was not able retrieve data at '" << url << "'\nCurl returned: " << code << std::endl; + } + return code; +} diff --git a/reflector/CurlGet.h b/reflector/CurlGet.h new file mode 100644 index 0000000..29aff4e --- /dev/null +++ b/reflector/CurlGet.h @@ -0,0 +1,34 @@ +/* + * 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 + +class CCurlGet +{ +public: + CCurlGet(); + ~CCurlGet(); + // the contents of the URL will be appended to the stringstream. + CURLcode GetURL(const std::string &url, std::stringstream &ss, long timeout = 30); +private: + static size_t data_write(void* buf, size_t size, size_t nmemb, void* userp); +}; diff --git a/reflector/Lookup.cpp b/reflector/Lookup.cpp index fa85586..dcb8599 100644 --- a/reflector/Lookup.cpp +++ b/reflector/Lookup.cpp @@ -93,3 +93,13 @@ void CLookup::Thread() std::this_thread::sleep_for(std::chrono::seconds(3)); } } + +bool CLookup::Dump() +{ + CBuffer buf; + LoadParameters(); + auto rval = LoadContentHttp(buf); + if (rval) + std::cout << (const char *)buf.data(); + return rval; +} diff --git a/reflector/Lookup.h b/reflector/Lookup.h index 86ef905..db52d2e 100644 --- a/reflector/Lookup.h +++ b/reflector/Lookup.h @@ -53,6 +53,7 @@ public: // locks void Lock(void) { m_Mutex.lock(); } void Unlock(void) { m_Mutex.unlock(); } + bool Dump(void); protected: std::time_t GetLastModTime(); diff --git a/reflector/LookupDmr.cpp b/reflector/LookupDmr.cpp index 14c7363..3b6097f 100644 --- a/reflector/LookupDmr.cpp +++ b/reflector/LookupDmr.cpp @@ -77,10 +77,8 @@ bool CLookupDmr::LoadContentFile(CBuffer &buffer) buffer.resize((int)size+1); file.seekg(0, std::ios::beg); file.read((char *)buffer.data(), (int)size); - - // close file - file.close(); } + file.close(); } // done @@ -89,7 +87,7 @@ bool CLookupDmr::LoadContentFile(CBuffer &buffer) bool CLookupDmr::LoadContentHttp(CBuffer &buf) { - // get file from xlxapi server + // get file from http://xlxapi.rlx.lu/api/exportdmr.php return HttpGet(m_Host.c_str(), m_Suffix.c_str(), 80, buf); } diff --git a/reflector/LookupYsf.cpp b/reflector/LookupYsf.cpp index bb45b69..382229f 100644 --- a/reflector/LookupYsf.cpp +++ b/reflector/LookupYsf.cpp @@ -58,10 +58,8 @@ bool CLookupYsf::LoadContentFile(CBuffer &buffer) buffer.resize((int)size + 1); file.seekg(0, std::ios::beg); file.read((char *)buffer.data(), (int)size); - - // close file - file.close(); } + file.close(); } return buffer.size() > 0; } diff --git a/reflector/Makefile b/reflector/Makefile index 7930dff..333d07a 100644 --- a/reflector/Makefile +++ b/reflector/Makefile @@ -41,8 +41,8 @@ all : $(EXE) $(INICHECK) $(EXE) : $(OBJS) $(CXX) $^ -o $@ $(LDFLAGS) -$(INICHECK) : Configure.cpp Configure.h - $(CXX) -DINICHECK $(CFLAGS) $< -o $(INICHECK) -lcurl +$(INICHECK) : Configure.cpp CurlGet.cpp + $(CXX) -DINICHECK $(CFLAGS) Configure.cpp CurlGet.cpp -o $(INICHECK) -lcurl %.o : %.cpp $(CXX) $(CFLAGS) -c $< -o $@ diff --git a/reflector/example.ini b/reflector/example.ini index 98e24be..b404452 100644 --- a/reflector/example.ini +++ b/reflector/example.ini @@ -77,7 +77,7 @@ Port = 10017 Port = 34001 AutoLinkModule = A # comment out if you want to disable AL DefaultCallsign = ALLSTAR -ClientFilePath = /usr/local/etc/USRPClients.txt +ClientFilePath = /home/user/urfd/USRPClients.txt [YSF] Port = 42000 @@ -95,27 +95,27 @@ Hostname = xlxapi.rlx.lu Suffix = api/exportdmr.php Mode = http RefreshMin = 179 -FilePath = /usr/local/etc/dmrid.dat +FilePath = /home/user/urfd/dmrid.dat [NXDN ID DB] Hostname = www.dudetronics.com Suffix = ar-dns/NXDN.csv Mode = http RefreshMin = 181 -FilePath = /usr/local/etc/nxdn.dat +FilePath = /home/user/urfd/nxdn.dat [YSF TX/RX DB] Hostname = xlxapi.rlx.lu Suffix = api/exportysfrepeaters.php Mode = http RefreshMin = 191 -FilePath = /usr/local/etc/ysfnode.dat +FilePath = /home/user/urfd/ysfnode.dat ######### Other File locations [Files] -PidPath = /var/run/urfd.pid +PidPath = /var/run/urfd.pid JsonPath = /var/log/urfd.json -WhitelistPath = /usr/local/etc/urfd.whitelist -BlacklistPath = /usr/local/etc/urfd.blacklist -InterlinkPath = /usr/local/etc/urfd.interlink -G3TerminalPath = /usr/local/etc/urfd.terminal +WhitelistPath = /home/user/urfd/urfd.whitelist +BlacklistPath = /home/user/urfd/urfd.blacklist +InterlinkPath = /home/user/urfd/urfd.interlink +G3TerminalPath = /home/user/urfd/urfd.terminal diff --git a/reflector/example.mk b/reflector/example.mk new file mode 100644 index 0000000..641bc68 --- /dev/null +++ b/reflector/example.mk @@ -0,0 +1,6 @@ +# this is where the binary will be installed +BINDIR = /usr/local/bin + +# besides making an executable that gdb can use, +# this will also provide some additional log messsage +debug = false From 7664b7305c4b1c5172a2671e384f3a520e210b8c Mon Sep 17 00:00:00 2001 From: Tom Early Date: Wed, 15 Feb 2023 14:20:38 -0700 Subject: [PATCH 06/44] rewrote databases --- reflector/Configure.cpp | 16 +-- reflector/JsonKeys.h | 8 +- reflector/Lookup.cpp | 95 +++++++++------ reflector/Lookup.h | 26 ++-- reflector/LookupDmr.cpp | 206 +++---------------------------- reflector/LookupDmr.h | 13 +- reflector/LookupNxdn.cpp | 209 +++----------------------------- reflector/LookupNxdn.h | 12 +- reflector/LookupYsf.cpp | 215 ++++----------------------------- reflector/LookupYsf.h | 11 +- reflector/WiresXCmdHandler.cpp | 2 +- 11 files changed, 144 insertions(+), 669 deletions(-) diff --git a/reflector/Configure.cpp b/reflector/Configure.cpp index b59db6d..c6546c5 100644 --- a/reflector/Configure.cpp +++ b/reflector/Configure.cpp @@ -49,7 +49,6 @@ #define JFILES "Files" #define JFILEPATH "FilePath" #define JG3TERMINALPATH "G3TerminalPath" -#define JHOSTNAME "Hostname" #define JINTERLINKPATH "InterlinkPath" #define JIPADDRESSES "IpAddresses" #define JIPV4BINDING "IPv4Binding" @@ -73,11 +72,11 @@ #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 JURL "URL" #define JUSRP "USRP" #define JWHITELISTPATH "WhitelistPath" #define JYSF "YSF" @@ -142,11 +141,10 @@ bool CConfigure::ReadData(const std::string &path) { ipv4.assign(ss.str()); trim(ipv4); - ss.clear(); } + ss.str(std::string()); if (CURLE_OK == curl.GetURL("https://ipv6.icanhazip.com", ss)) { - std::cout << ss.str(); ipv6.assign(ss.str()); trim(ipv6); } @@ -436,10 +434,8 @@ bool CConfigure::ReadData(const std::string &path) case ESection::nxdnid: pdb = &g_Keys.nxdniddb; break; case ESection::ysffreq: pdb = &g_Keys.ysftxrxdb; break; } - if (0 == key.compare(JHOSTNAME)) - data[pdb->hostname] = value; - else if (0 == key.compare(JSUFFIX)) - data[pdb->suffix] = value; + if (0 == key.compare(JURL)) + data[pdb->url] = value; else if (0 == key.compare(JMODE)) { if ((0==value.compare("file")) || (0==value.compare("http")) || (0==value.compare("both"))) @@ -562,7 +558,6 @@ bool CConfigure::ReadData(const std::string &path) data[g_Keys.ip.ipv6address] = ipv6; else { - std::cout << ipv6; std::cerr << "ERROR: could not detect IPv6 address at this time" << std::endl; rval = true; } @@ -670,8 +665,7 @@ bool CConfigure::ReadData(const std::string &path) }; 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, JURL, item.second->url, 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); diff --git a/reflector/JsonKeys.h b/reflector/JsonKeys.h index 02921bc..83a2b03 100644 --- a/reflector/JsonKeys.h +++ b/reflector/JsonKeys.h @@ -48,10 +48,10 @@ struct SJsonKeys { struct YSLREG { const std::string id, name, description; } ysfreflectordb; } ysf { "YSFPort", "YSFAutoLinkMod", "YSFDefaultTxFreq", "YSFDefaultRxFreq", { "ysfrefdbid", "ysfrefdbname", "ysfrefdbdesc" } }; - struct DB { const std::string hostname, suffix, mode, refreshmin, filepath; } - dmriddb { "dmrIdDbHost", "dmrIdDbSuffix", "dmrIdDbMode", "dmrIdDbRefresh", "dmrIdDbFilePath" }, - nxdniddb { "nxdnIdDbHost", "nxdnIdDbSuffix", "nxdnIdDbMode", "nxdnIdDbRefresh", "nxdnIdDbFilePath" }, - ysftxrxdb { "ysfIdDbHost", "ysfIdDbSuffix", "ysfIdDbMode", "ysfIdDbRefresh", "ysfIdDbFilePath" }; + struct DB { const std::string url, mode, refreshmin, filepath; } + dmriddb { "dmrIdDbUrl", "dmrIdDbMode", "dmrIdDbRefresh", "dmrIdDbFilePath" }, + nxdniddb { "nxdnIdDbUrl", "nxdnIdDbMode", "nxdnIdDbRefresh", "nxdnIdDbFilePath" }, + ysftxrxdb { "ysfIdDbUrl", "ysfIdDbMode", "ysfIdDbRefresh", "ysfIdDbFilePath" }; struct FILES { const std::string pid, json, white, black, interlink, terminal; } files { "pidFilePath", "jsonFilePath", "whitelistFilePath", "blacklistFilePath", "interlinkFilePath", "g3TerminalFilePath" }; }; diff --git a/reflector/Lookup.cpp b/reflector/Lookup.cpp index dcb8599..5d4d07e 100644 --- a/reflector/Lookup.cpp +++ b/reflector/Lookup.cpp @@ -16,16 +16,13 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -#include +#include +#include #include #include +#include "CurlGet.h" #include "Lookup.h" -CLookup::~CLookup() -{ - LookupClose(); -} - void CLookup::LookupClose() { keep_running = false; @@ -52,54 +49,78 @@ void CLookup::LookupInit() void CLookup::Thread() { + const unsigned long wait_cycles = m_Refresh * 6u; // the number of while loops in m_Refresh + unsigned long count = 0; while (keep_running) { - bool loaded = false; + std::stringstream ss; + bool http_loaded = false; + bool file_loaded = false; - if (m_Type != ERefreshType::file) // get the HTTP contents + // load http section first, if configured and m_Refresh minutes have lapsed + // on the first pass through this while loop (count == 0) + if (ERefreshType::file != m_Type && 0ul == count++ % wait_cycles) { - CBuffer buf; - loaded = LoadContentHttp(buf); - if (loaded) - { - Lock(); - ClearContents(); - RefreshContentHttp(buf); - Unlock(); - } + // if SIG_INT was received at this point in time, + // in might take a bit more than 10 seconds to soft close + http_loaded = LoadContentHttp(ss); } - - if (m_Type != ERefreshType::http) // get the file contents + // load the file if http was loaded or if we haven't loaded since the last mod time + if (ERefreshType::http != m_Type) { - auto lastTime = GetLastModTime(); - if (lastTime > m_LastModTime) + GetLastModTime(); + if (http_loaded || m_LastLoadTime < m_LastModTime) { - CBuffer buf; - if (LoadContentFile(buf)) - { - Lock(); - if (! loaded) - ClearContents(); - RefreshContentFile(buf); - Unlock(); - m_LastModTime = lastTime; - } + file_loaded = LoadContentFile(ss); + time(&m_LastLoadTime); } } - // now wait for a while... - for (unsigned i=0; i<20u*m_Refresh && keep_running; i++) - std::this_thread::sleep_for(std::chrono::seconds(3)); + // now update the map(s) if anything was loaded + if (http_loaded || file_loaded) + { + Lock(); + // if m_Type == ERefreshType::both, and if something was deleted from the file, + // it won't be purged from the map(s) until http is loaded + // It would be a lot of work (iterating on an unordered_map) to do otherwise! + if (http_loaded || ERefreshType::file == m_Type) + ClearContents(); + UpdateContent(ss); + Unlock(); + } + + // now wait for 10 seconds + std::this_thread::sleep_for(std::chrono::seconds(10)); } } +bool CLookup::LoadContentHttp(std::stringstream &ss) +{ + CCurlGet get; + auto code = get.GetURL(m_Url, ss); + return CURLE_OK == code; +} + +bool CLookup::LoadContentFile(std::stringstream &ss) +{ + bool rval = false; + std::ifstream file(m_Path); + if ( file ) + { + ss << file.rdbuf(); + file.close(); + rval = true; + } + return rval; +} + bool CLookup::Dump() { - CBuffer buf; + std::stringstream ss; LoadParameters(); - auto rval = LoadContentHttp(buf); + auto rval = LoadContentHttp(ss); if (rval) - std::cout << (const char *)buf.data(); + std::cout << ss.str() << std::endl; return rval; } diff --git a/reflector/Lookup.h b/reflector/Lookup.h index db52d2e..f921c81 100644 --- a/reflector/Lookup.h +++ b/reflector/Lookup.h @@ -18,20 +18,20 @@ #pragma once -#include #include #include -#include "Buffer.h" +#include #include "Callsign.h" #include "Configure.h" // compare function for std::map::find -struct CCallsignCompare +struct CCallsignHash { - bool operator() (const CCallsign &cs1, const CCallsign &cs2) const + std::size_t operator() (const CCallsign &cs) const { - return cs1.HasLowerCallsign(cs2); + std::hash hash; + return hash(cs.GetCS()); } }; @@ -42,10 +42,7 @@ class CLookup { public: // constructor - CLookup() : keep_running(true), m_LastModTime(0) {} - - // destructor - virtual ~CLookup(); + CLookup() : keep_running(true), m_LastModTime(0), m_LastLoadTime(0) {} void LookupInit(); void LookupClose(); @@ -62,16 +59,15 @@ protected: void Thread(); // refresh - virtual bool LoadContentFile(CBuffer &buf) = 0; - virtual bool LoadContentHttp(CBuffer &buf) = 0; - virtual void RefreshContentFile(const CBuffer &) = 0; - virtual void RefreshContentHttp(const CBuffer &) = 0; + bool LoadContentHttp(std::stringstream &ss); + bool LoadContentFile(std::stringstream &ss); + virtual void UpdateContent(std::stringstream &ss) = 0; std::mutex m_Mutex; ERefreshType m_Type; unsigned m_Refresh; - std::string m_Path, m_Host, m_Suffix; - std::time_t m_LastModTime; + std::string m_Path, m_Url; + std::time_t m_LastModTime, m_LastLoadTime; std::atomic keep_running; std::future m_Future; diff --git a/reflector/LookupDmr.cpp b/reflector/LookupDmr.cpp index 3b6097f..14b3a0f 100644 --- a/reflector/LookupDmr.cpp +++ b/reflector/LookupDmr.cpp @@ -17,7 +17,7 @@ // along with this program. If not, see . #include -#include +#include #include #include @@ -34,8 +34,7 @@ void CLookupDmr::LoadParameters() m_Type = g_Conf.GetRefreshType(g_Keys.dmriddb.mode); m_Refresh = g_Conf.GetUnsigned(g_Keys.dmriddb.refreshmin); m_Path.assign(g_Conf.GetString(g_Keys.dmriddb.filepath)); - m_Host.assign(g_Conf.GetString(g_Keys.dmriddb.hostname)); - m_Suffix.assign(g_Conf.GetString(g_Keys.dmriddb.suffix)); + m_Url.assign(g_Conf.GetString(g_Keys.dmriddb.url)); } uint32_t CLookupDmr::FindDmrid(const CCallsign &callsign) @@ -59,198 +58,27 @@ const CCallsign *CLookupDmr::FindCallsign(uint32_t dmrid) return nullptr; } -bool CLookupDmr::LoadContentFile(CBuffer &buffer) +void CLookupDmr::UpdateContent(std::stringstream &ss) { - buffer.clear(); - std::ifstream file; - std::streampos size; - - // open file - file.open(m_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); - } - file.close(); - } - - // done - return buffer.size() > 0; -} - -bool CLookupDmr::LoadContentHttp(CBuffer &buf) -{ - // get file from http://xlxapi.rlx.lu/api/exportdmr.php - return HttpGet(m_Host.c_str(), m_Suffix.c_str(), 80, buf); -} - -void CLookupDmr::RefreshContentFile(const CBuffer &buffer) -{ - // 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; - } - - std::cout << "Read " << m_DmridMap.size() << " DMR ids from file " << m_Refresh << std::endl; -} - -void CLookupDmr::RefreshContentHttp(const CBuffer &buffer) -{ - char *ptr1 = (char *)buffer.data(); - char *ptr2; - // get next line - while ( (ptr2 = strchr(ptr1, '\n')) != nullptr ) + std::string line; + while (std::getline(ss, line)) { - *ptr2 = 0; - // get items - char *dmrid; - char *callsign; - if ( ((dmrid = strtok(ptr1, ";")) != nullptr) && IsValidDmrId(dmrid) ) + std::string cs_str, id_str; + std::istringstream iss(line); + std::getline(iss, id_str, ';'); + std::getline(iss, cs_str, ';'); + auto lid = stol(id_str); + if (lid > 0 && lid < 0x1000000 && cs_str.size() < CALLSIGN_LEN) { - 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; - } - - std::cout << "Read " << m_DmridMap.size() << " DMR ids from " << m_Host << " database " << std::endl; -} - -bool CLookupDmr::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 = ok && isdigit(sz[i]); - } - } - return ok; -} - -#define DMRID_HTTPGET_SIZEMAX (256) - -bool CLookupDmr::HttpGet(const char *hostname, const char *filename, int port, CBuffer &buffer) -{ - buffer.clear(); - 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, g_Conf.GetString(g_Keys.names.cs).c_str()); - ::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 - 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); - } - //} - 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; - } + auto id = uint32_t(lid); + CCallsign cs(cs_str.c_str(), id); + m_DmridMap[cs] = id; + m_CallsignMap[id] = cs; } else { - std::cout << "Host " << hostname << " not found" << std::endl; + std::cout << "DMR Id '" << id_str << ';' << cs_str << ";' is malformed" << std::endl; } - } - else - { - std::cout << "Failed to open wget socket" << std::endl; - } - - // done - return buffer.size() > 1; + std::cout << "DMR Id database size now is " << m_DmridMap.size() << std::endl; } diff --git a/reflector/LookupDmr.h b/reflector/LookupDmr.h index d0e478b..360262f 100644 --- a/reflector/LookupDmr.h +++ b/reflector/LookupDmr.h @@ -23,21 +23,16 @@ class CLookupDmr : public CLookup { public: + ~CLookupDmr() {} uint32_t FindDmrid(const CCallsign &cs); const CCallsign *FindCallsign(uint32_t dmrid); protected: void ClearContents(); void LoadParameters(); - bool LoadContentFile(CBuffer &buf); - bool LoadContentHttp(CBuffer &buf); - void RefreshContentFile(const CBuffer &); - void RefreshContentHttp(const CBuffer &); + void UpdateContent(std::stringstream &ss); private: - std::map m_CallsignMap; - std::map m_DmridMap; - - bool IsValidDmrId(const char *); - bool HttpGet(const char *, const char *, int, CBuffer &); + std::unordered_map m_CallsignMap; + std::unordered_map m_DmridMap; }; diff --git a/reflector/LookupNxdn.cpp b/reflector/LookupNxdn.cpp index 1aac8fa..6f5e7d9 100644 --- a/reflector/LookupNxdn.cpp +++ b/reflector/LookupNxdn.cpp @@ -34,8 +34,7 @@ void CLookupNxdn::LoadParameters() m_Type = g_Conf.GetRefreshType(g_Keys.nxdniddb.mode); m_Refresh = g_Conf.GetUnsigned(g_Keys.nxdniddb.refreshmin); m_Path.assign(g_Conf.GetString(g_Keys.nxdniddb.filepath)); - m_Host.assign(g_Conf.GetString(g_Keys.nxdniddb.hostname)); - m_Suffix.assign(g_Conf.GetString(g_Keys.nxdniddb.suffix)); + m_Url.assign(g_Conf.GetString(g_Keys.nxdniddb.url)); } const CCallsign *CLookupNxdn::FindCallsign(uint16_t nxdnid) @@ -58,203 +57,27 @@ uint16_t CLookupNxdn::FindNXDNid(const CCallsign &callsign) return 0; } -bool CLookupNxdn::LoadContentFile(CBuffer &buffer) +void CLookupNxdn::UpdateContent(std::stringstream &ss) { - buffer.clear(); - std::ifstream file; - std::streampos size; - - // open file - file.open(m_Path, std::ios::in | std::ios::binary | std::ios::ate); - if ( file.is_open() ) + std::string line; + while (std::getline(ss, line)) { - // read file - size = file.tellg(); - if ( size > 0 ) + std::string cs_str, id_str; + std::istringstream iss(line); + std::getline(iss, id_str, ','); + std::getline(iss, cs_str, ','); + auto lid = stol(id_str); + if (lid > 0 && lid < 0x10000 && cs_str.size() < CALLSIGN_LEN) { - // 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(); - - // done - } - } - - // done - return buffer.size() > 0; -} - -bool CLookupNxdn::LoadContentHttp(CBuffer &buffer) -{ - // get file from xlxapi server - return HttpGet(m_Host.c_str(), m_Suffix.c_str(), 80, buffer); -} - -void CLookupNxdn::RefreshContentFile(const CBuffer &buffer) -{ - // crack it - char *ptr1 = (char *)buffer.data(); - char *ptr2; - - // get next line - while ( (ptr2 = ::strchr(ptr1, '\n')) != nullptr ) - { - *ptr2 = 0; - // get items - char *nxdnid; - char *callsign; - if ( ((nxdnid = ::strtok(ptr1, ",")) != nullptr) && IsValidNxdnId(nxdnid) ) - { - if ( ((callsign = ::strtok(nullptr, ",")) != nullptr) ) - { - // new entry - uint16_t us = atoi(nxdnid); - CCallsign cs(callsign, 0, us); - if ( cs.IsValid() ) - { - m_CallsignMap.insert(std::pair(us, cs)); - m_NxdnidMap.insert(std::pair(cs,us)); - } - } - } - // next line - ptr1 = ptr2+1; - } - - std::cout << "Read " << m_NxdnidMap.size() << " NXDN ids from file " << m_Path << std::endl; -} - -void CLookupNxdn::RefreshContentHttp(const CBuffer &buffer) -{ - char *ptr1 = (char *)buffer.data(); - char *ptr2; - // get next line - while ( (ptr2 = strchr(ptr1, '\n')) != nullptr ) - { - std::cout << "newline: " << std::string(ptr2) << std::endl; - *ptr2 = 0; - // get items - char *nxdnid; - char *callsign; - if ( ((nxdnid = ::strtok(ptr1, ",")) != nullptr) && IsValidNxdnId(nxdnid) ) - { - if ( ((callsign = ::strtok(nullptr, ",")) != nullptr) ) - { - // new entry - uint16_t us = atoi(nxdnid); - CCallsign cs(callsign, 0, us); - if ( cs.IsValid() ) - { - m_CallsignMap.insert(std::pair(us, cs)); - m_NxdnidMap.insert(std::pair(cs,us)); - } - } - } - // next line - ptr1 = ptr2+1; - } - - std::cout << "Read " << m_NxdnidMap.size() << " NXDN ids from " << m_Host << std::endl; -} - -bool CLookupNxdn::IsValidNxdnId(const char *sz) -{ - bool ok = false; - size_t n = ::strlen(sz); - if ( (n > 0) && (n <= 5) ) - { - ok = true; - for ( size_t i = 0; (i < n) && ok; i++ ) - { - ok = ok && isdigit(sz[i]); - } - } - return ok; -} - -#define NXDNID_HTTPGET_SIZEMAX (256) - -bool CLookupNxdn::HttpGet(const char *hostname, const char *filename, int port, CBuffer &buffer) -{ - int sock_id; - buffer.clear(); - - // 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[NXDNID_HTTPGET_SIZEMAX]; - ::sprintf(request, "GET /%s HTTP/1.0\r\nFrom: %s\r\nUser-Agent: urfd\r\n\r\n", filename, g_Conf.GetString(g_Keys.names.cs).c_str()); - ::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 - 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); - } - //} - 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; - } + auto id = uint16_t(lid); + CCallsign cs(cs_str.c_str(), 0, id); + m_NxdnidMap[cs] = id; + m_CallsignMap[id] = cs; } else { - std::cout << "Host " << hostname << " not found" << std::endl; + std::cout << "NXDN Id '" << id_str << ',' << cs_str << ",' is malformed" << std::endl; } - } - else - { - std::cout << "Failed to open wget socket" << std::endl; - } - - // done - return buffer.size() > 1; + std::cout << "NXDN Id database size now is " << m_NxdnidMap.size() << std::endl; } diff --git a/reflector/LookupNxdn.h b/reflector/LookupNxdn.h index 36f2be6..946ab9a 100644 --- a/reflector/LookupNxdn.h +++ b/reflector/LookupNxdn.h @@ -28,15 +28,9 @@ public: protected: void ClearContents(); void LoadParameters(); - bool LoadContentFile(CBuffer &buf); - bool LoadContentHttp(CBuffer &buf); - void RefreshContentFile(const CBuffer &); - void RefreshContentHttp(const CBuffer &); + void UpdateContent(std::stringstream &ss); private: - std::map m_CallsignMap; - std::map m_NxdnidMap; - - bool IsValidNxdnId(const char *); - bool HttpGet(const char *, const char *, int, CBuffer &); + std::unordered_map m_CallsignMap; + std::unordered_map m_NxdnidMap; }; diff --git a/reflector/LookupYsf.cpp b/reflector/LookupYsf.cpp index 382229f..2b45a12 100644 --- a/reflector/LookupYsf.cpp +++ b/reflector/LookupYsf.cpp @@ -17,7 +17,7 @@ // along with this program. If not, see . #include -#include +#include #include #include #include @@ -34,217 +34,46 @@ void CLookupYsf::LoadParameters() m_Type = g_Conf.GetRefreshType(g_Keys.ysftxrxdb.mode); m_Refresh = g_Conf.GetUnsigned(g_Keys.ysftxrxdb.refreshmin); m_Path.assign(g_Conf.GetString(g_Keys.ysftxrxdb.filepath)); - m_Host.assign(g_Conf.GetString(g_Keys.ysftxrxdb.hostname)); - m_Suffix.assign(g_Conf.GetString(g_Keys.ysftxrxdb.suffix)); + m_Url.assign(g_Conf.GetString(g_Keys.ysftxrxdb.url)); m_DefaultTx = g_Conf.GetUnsigned(g_Keys.ysf.defaulttxfreq); m_DefaultRx = g_Conf.GetUnsigned(g_Keys.ysf.defaultrxfreq); } -bool CLookupYsf::LoadContentFile(CBuffer &buffer) +void CLookupYsf::UpdateContent(std::stringstream &ss) { - buffer.clear(); - std::ifstream file; - std::streampos size; - - // open file - file.open(m_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); - } - file.close(); - } - return buffer.size() > 0; -} - -bool CLookupYsf::LoadContentHttp(CBuffer &buffer) -{ - // get file from http://xlxapi.rlx.lu/api/exportysfrepeaters.php - return HttpGet(m_Host.c_str(), m_Suffix.c_str(), 80, buffer); -} - -void CLookupYsf::RefreshContentFile(const CBuffer &buffer) -{ - // 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 *callsign; - char *txfreq; - char *rxfreq; - if (((callsign = ::strtok(ptr1, ";")) != nullptr)) - { - if (((txfreq = ::strtok(nullptr, ";")) != nullptr)) - { - if (((rxfreq = ::strtok(nullptr, ";")) != nullptr)) - { - // new entry - CCallsign cs(callsign); - CYsfNode node(atoi(txfreq), atoi(rxfreq)); - if (cs.IsValid() && node.IsValid()) - { - m_map.insert(std::pair(cs, node)); - } - } - } - } - // next line - ptr1 = ptr2 + 1; - } - } - - // report - std::cout << "Read " << m_map.size() << " YSF nodes from file " << m_Path << std::endl; -} - -void CLookupYsf::RefreshContentHttp(const CBuffer &buffer) -{ - // crack it - char *ptr1 = (char *)buffer.data(); - char *ptr2; - - // get next line - while ((ptr2 = ::strchr(ptr1, '\n')) != nullptr) + std::string line; + while (std::getline(ss, line)) { - *ptr2 = 0; - // get items - char *callsign; - char *txfreq; - char *rxfreq; - if (((callsign = ::strtok(ptr1, ";")) != nullptr)) + std::string cs_str, tx_str, rx_str; + std::istringstream iss(line); + std::getline(iss, cs_str, ';'); + std::getline(iss, tx_str, ';'); + std::getline(iss, rx_str, ';'); + auto ltx = stol(tx_str); + auto lrx = stol(rx_str); + if (ltx > 40000000 && ltx < 0x100000000 && lrx > 40000000 && lrx < 0x100000000 && CCallsign(cs_str.c_str()).IsValid()) { - if (((txfreq = ::strtok(nullptr, ";")) != nullptr)) - { - if (((rxfreq = ::strtok(nullptr, ";")) != nullptr)) - { - // new entry - CCallsign cs(callsign); - CYsfNode node(atoi(txfreq), atoi(rxfreq)); - if (cs.IsValid() && node.IsValid()) - { - m_map.insert(std::pair(cs, node)); - } - } - } - } - // next line - ptr1 = ptr2 + 1; - } - - // report - std::cout << "Read " << m_map.size() << " YSF nodes from " << m_Host << " database " << std::endl; -} - -#define YSFNODE_HTTPGET_SIZEMAX (256) - -bool CLookupYsf::HttpGet(const char *hostname, const char *filename, int port, CBuffer &buffer) -{ - buffer.clear(); - 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[YSFNODE_HTTPGET_SIZEMAX]; - sprintf(request, "GET /%s HTTP/1.0\r\nFrom: %s\r\nUser-Agent: urfd\r\n\r\n", filename, g_Conf.GetString(g_Keys.names.cs).c_str()); - 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 - 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); - } - //} - 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; - } + m_map.emplace(CCallsign(cs_str.c_str()), CYsfNode(uint32_t(ltx), uint32_t(lrx))); } else { - std::cout << "Host " << hostname << " not found" << std::endl; + std::cout << "YSF value '" << cs_str << ';' << tx_str << ';' << rx_str << ";' is malformed" << std::endl; } } - else - { - std::cout << "Failed to open wget socket" << std::endl; - } - - // done - return buffer.size() > 1; + std::cout << "DMR Id database size now is " << m_map.size() << std::endl; } -bool CLookupYsf::FindFrequencies(const CCallsign &callsign, uint32_t *txfreq, uint32_t *rxfreq) +void CLookupYsf::FindFrequencies(const CCallsign &callsign, uint32_t &txfreq, uint32_t &rxfreq) { auto found = m_map.find(callsign); - if (found != m_map.end()) + if ( found != m_map.end() ) { - *txfreq = found->second.GetTxFrequency(); - *rxfreq = found->second.GetRxFrequency(); - return true; + txfreq = found->second.GetTxFrequency(); + rxfreq = found->second.GetRxFrequency(); } else { - *txfreq = m_DefaultTx; - *rxfreq = m_DefaultRx; - return false; + txfreq = m_DefaultTx; + rxfreq = m_DefaultRx; } } diff --git a/reflector/LookupYsf.h b/reflector/LookupYsf.h index 265511a..8c8fa90 100644 --- a/reflector/LookupYsf.h +++ b/reflector/LookupYsf.h @@ -21,25 +21,20 @@ #include "YSFNode.h" #include "Lookup.h" -using CsNodeMap = std::map; +using CsNodeMap = std::unordered_map; class CLookupYsf : public CLookup { public: - bool FindFrequencies(const CCallsign &, uint32_t *, uint32_t *); + void FindFrequencies(const CCallsign &, uint32_t &, uint32_t &); protected: void ClearContents(); void LoadParameters(); - bool LoadContentFile(CBuffer &buf); - bool LoadContentHttp(CBuffer &buf); - void RefreshContentFile(const CBuffer &); - void RefreshContentHttp(const CBuffer &); + void UpdateContent(std::stringstream &ss); private: CsNodeMap m_map; - bool HttpGet(const char *, const char *, int, CBuffer &); - unsigned m_DefaultTx, m_DefaultRx; }; diff --git a/reflector/WiresXCmdHandler.cpp b/reflector/WiresXCmdHandler.cpp index 919c886..d02bdc5 100644 --- a/reflector/WiresXCmdHandler.cpp +++ b/reflector/WiresXCmdHandler.cpp @@ -141,7 +141,7 @@ void CWiresxCmdHandler::Task(void) { // fill our info object Info = m_ReflectorWiresxInfo; - g_LYtr.FindFrequencies(Cmd.GetCallsign(), &uiNodeTxFreq, &uiNodeRxFreq); + g_LYtr.FindFrequencies(Cmd.GetCallsign(), uiNodeTxFreq, uiNodeRxFreq); Info.SetFrequencies(uiNodeTxFreq, uiNodeRxFreq); // find our client and the module it's currentlink linked to From 991d4899a010bcbe7533c78ae4beccc211d55520 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Sat, 18 Feb 2023 12:37:29 -0700 Subject: [PATCH 07/44] Databases have switched to unordered_map, based on a new union in CCallsign --- .gitignore | 1 + reflector/Callsign.cpp | 253 ++++++++++++++++++++++----------------- reflector/Callsign.h | 36 ++++-- reflector/Lookup.cpp | 4 +- reflector/Lookup.h | 12 +- reflector/LookupDmr.cpp | 55 ++++++--- reflector/LookupDmr.h | 10 +- reflector/LookupNxdn.cpp | 56 ++++++--- reflector/LookupNxdn.h | 10 +- reflector/LookupYsf.cpp | 29 +++-- reflector/LookupYsf.h | 4 +- reflector/Main.cpp | 149 ++++++++++++++++++++++- reflector/Makefile | 9 +- reflector/example.ini | 51 ++++---- 14 files changed, 462 insertions(+), 217 deletions(-) diff --git a/.gitignore b/.gitignore index df15a05..6e6d5ab 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ reflector.cfg wiresx/configure.php urfd* inicheck +dbutil diff --git a/reflector/Callsign.cpp b/reflector/Callsign.cpp index 74a83d9..79d3065 100644 --- a/reflector/Callsign.cpp +++ b/reflector/Callsign.cpp @@ -31,98 +31,113 @@ CCallsign::CCallsign() { // blank all - memset(m_Callsign, ' ', CALLSIGN_LEN); - memset(m_Suffix, ' ', CALLSUFFIX_LEN); + memset(m_Callsign.c, ' ', CALLSIGN_LEN); + memset(m_Suffix.c, ' ', CALLSUFFIX_LEN); m_Module = ' '; m_uiDmrid = 0; m_coded = 0; } -CCallsign::CCallsign(const char *sz, uint32_t dmrid, uint16_t nxdnid) +CCallsign::CCallsign(const CCallsign &cs) { - // blank all - memset(m_Callsign, ' ', CALLSIGN_LEN); - memset(m_Suffix, ' ', CALLSUFFIX_LEN); - m_Module = ' '; - m_uiDmrid = dmrid; - m_uiNXDNid = nxdnid; + m_Callsign.l = cs.m_Callsign.l; + m_Suffix.u = cs.m_Suffix.u; + m_Module = cs.m_Module; + if (m_Callsign.l) + CSIn(); +} +CCallsign::CCallsign(const std::string &cs, uint32_t dmrid, uint16_t nxdnid) : CCallsign() +{ // and populate - auto len = strlen(sz); + m_uiDmrid = dmrid; + m_uiNXDNid = nxdnid; + auto len = cs.size(); if ( len > 0 ) { // callsign valid - memcpy(m_Callsign, sz, MIN(len, CALLSIGN_LEN-1)); - if ( len > CALLSIGN_LEN ) + memcpy(m_Callsign.c, cs.c_str(), MIN(len, CALLSIGN_LEN-1)); + if ( len >= CALLSIGN_LEN ) { - m_Module = sz[len-1]; + m_Module = cs.back(); } - // Calculate the M17 coded callsign - CSIn(); - - // dmrid ok ? - if ( m_uiDmrid == 0 ) + auto key = GetKey(); + if (0 == m_uiDmrid) { g_LDid.Lock(); - { - m_uiDmrid = g_LDid.FindDmrid(*this); - } + m_uiDmrid = g_LDid.FindDmrid(key); g_LDid.Unlock(); } - if ( m_uiNXDNid == 0 ) + + if (0 == m_uiNXDNid) { g_LNid.Lock(); - { - m_uiNXDNid = g_LNid.FindNXDNid(*this); - } + m_uiNXDNid = g_LNid.FindNXDNid(key); g_LNid.Unlock(); } } - else if ( m_uiDmrid != 0 ) + else if (dmrid) { g_LDid.Lock(); - { - const CCallsign *callsign = g_LDid.FindCallsign(m_uiDmrid); - if ( callsign != nullptr ) - { - memcpy(m_Callsign, callsign->m_Callsign, CALLSIGN_LEN); - } - } + auto pItem = g_LDid.FindCallsign(dmrid); + if (pItem) + m_Callsign = *pItem; g_LDid.Unlock(); - if ( m_uiNXDNid == 0 ) + if (m_Callsign.l && 0 == nxdnid) { g_LNid.Lock(); - { - m_uiNXDNid = g_LNid.FindNXDNid(*this); - } + m_uiNXDNid = g_LNid.FindNXDNid(GetKey()); g_LNid.Unlock(); } - CSIn(); } - else if ( m_uiNXDNid != 0 ) + else if (nxdnid) { g_LNid.Lock(); - { - const CCallsign *callsign = g_LNid.FindCallsign(m_uiNXDNid); - if ( callsign != nullptr ) - { - memcpy(m_Callsign, callsign->m_Callsign, CALLSIGN_LEN); - } - } + auto pItem = g_LNid.FindCallsign(nxdnid); + if (pItem) + m_Callsign = *pItem; g_LNid.Unlock(); - if ( m_uiDmrid == 0 ) + if (m_Callsign.l && 0 == dmrid) { g_LDid.Lock(); - { - m_uiDmrid = g_LDid.FindDmrid(*this); - } + m_uiDmrid = g_LDid.FindDmrid(GetKey()); g_LDid.Unlock(); } + } + if (m_Callsign.l) CSIn(); +} + +CCallsign::CCallsign(const CCallsign &cs) +{ + m_Callsign.l = cs.m_Callsign.l; + m_Suffix.u = cs.m_Suffix.u; + m_Module = cs.m_Module; + m_uiDmrid = cs.m_uiDmrid; + m_uiNXDNid = cs.m_uiNXDNid; + m_coded = cs.m_coded; +} + +CCallsign::CCallsign(const UCallsign &ucs) : CCallsign() +{ + m_Callsign.l = ucs.l; +} + +CCallsign &CCallsign::operator = (const CCallsign &cs) +{ + if (this != &cs) + { + m_Callsign.l = cs.m_Callsign.l; + m_Suffix.u = cs.m_Suffix.u; + m_Module = cs.m_Module; + m_uiDmrid = cs.m_uiDmrid; + m_uiNXDNid = cs.m_uiNXDNid; + m_coded = cs.m_coded; } + return *this; } //////////////////////////////////////////////////////////////////////////////////////// @@ -138,8 +153,8 @@ bool CCallsign::IsValid(void) const int iNum = 0; for ( i = 0; i < 3; i++ ) { - valid &= IsLetter(m_Callsign[i]) || IsNumber(m_Callsign[i]); - if ( IsNumber(m_Callsign[i]) ) + valid = valid && (IsLetter(m_Callsign.c[i]) || IsNumber(m_Callsign.c[i])); + if ( IsNumber(m_Callsign.c[i]) ) { iNum++; } @@ -148,19 +163,19 @@ bool CCallsign::IsValid(void) const // all remaining char are letter, number or space for ( ; i < CALLSIGN_LEN; i++) { - valid &= IsLetter(m_Callsign[i]) || IsNumber(m_Callsign[i]) || IsSpace(m_Callsign[i]); + valid = valid && (IsLetter(m_Callsign.c[i]) || IsNumber(m_Callsign.c[i]) || IsSpace(m_Callsign.c[i])); } // prefix // all chars are number, letter, special char, or space for ( i = 0; i < CALLSUFFIX_LEN; i++ ) { - valid &= IsLetter(m_Suffix[i]) || IsNumber(m_Suffix[i]) || IsSpace(m_Suffix[i]) || IsLetterLC(m_Suffix[i]) || IsSpecialChar(m_Suffix[i]); + valid = valid && (IsLetter(m_Suffix.c[i]) || IsNumber(m_Suffix.c[i]) || IsSpace(m_Suffix.c[i]) || IsLetterLC(m_Suffix.c[i]) || IsSpecialChar(m_Suffix.c[i])); } // module // is an letter or space - valid &= IsLetter(m_Module) || IsSpace(m_Module); + valid = valid && (IsLetter(m_Module) || IsSpace(m_Module)); // dmrid is not tested, as it can be nullptr // if station does is not dmr registered @@ -171,41 +186,37 @@ bool CCallsign::IsValid(void) const bool CCallsign::HasSuffix(void) const { - bool has = false; - for ( int i = 0; i < CALLSUFFIX_LEN; i++ ) - { - has |= (m_Suffix[i] != ' '); - } - return has; + return 0 == memcmp(m_Suffix.c, " ", 4); } //////////////////////////////////////////////////////////////////////////////////////// // set -void CCallsign::SetCallsign(const char *sz, bool UpdateDmrid) +void CCallsign::SetCallsign(const std::string &s, bool updateids) { // set callsign - memset(m_Callsign, ' ', CALLSIGN_LEN); + memset(m_Callsign.c, ' ', CALLSIGN_LEN); m_Module = ' '; - auto len = strlen(sz); - memcpy(m_Callsign, sz, MIN(len, CALLSIGN_LEN-1)); - if ( len > CALLSIGN_LEN ) + auto len = s.size(); + memcpy(m_Callsign.c, s.c_str(), MIN(len, CALLSIGN_LEN-1)); + if ( len >= CALLSIGN_LEN ) { - m_Module = sz[len-1]; + m_Module = s.back(); } // update M17 coded callsign CSIn(); // and update dmrid - if ( UpdateDmrid ) + if (updateids) { + auto key = GetKey(); g_LDid.Lock(); { - m_uiDmrid = g_LDid.FindDmrid(*this); + m_uiDmrid = g_LDid.FindDmrid(key); } g_LDid.Unlock(); g_LNid.Lock(); { - m_uiNXDNid = g_LNid.FindNXDNid(*this); + m_uiNXDNid = g_LNid.FindNXDNid(key); } g_LNid.Unlock(); } @@ -214,14 +225,14 @@ void CCallsign::SetCallsign(const char *sz, bool UpdateDmrid) void CCallsign::SetCallsign(const uint8_t *buffer, int len, bool UpdateDmrid) { // set callsign - memset(m_Callsign, ' ', CALLSIGN_LEN); + memset(m_Callsign.c, ' ', CALLSIGN_LEN); m_Module = ' '; - memcpy(m_Callsign, buffer, MIN(len, (int)CALLSIGN_LEN-1)); + memcpy(m_Callsign.c, buffer, MIN(len, (int)CALLSIGN_LEN-1)); for ( unsigned i = 0; i < CALLSIGN_LEN; i++ ) { - if ( m_Callsign[i] == 0 ) + if ( m_Callsign.c[i] == 0 ) { - m_Callsign[i] = ' '; + m_Callsign.c[i] = ' '; } } if ( (len >= (int)CALLSIGN_LEN) && ((char)buffer[CALLSIGN_LEN-1] != 0) ) @@ -231,14 +242,15 @@ void CCallsign::SetCallsign(const uint8_t *buffer, int len, bool UpdateDmrid) CSIn(); if ( UpdateDmrid ) { + auto key = GetKey(); g_LDid.Lock(); { - m_uiDmrid = g_LDid.FindDmrid(*this); + m_uiDmrid = g_LDid.FindDmrid(key); } g_LDid.Unlock(); g_LNid.Lock(); { - m_uiNXDNid = g_LNid.FindNXDNid(*this); + m_uiNXDNid = g_LNid.FindNXDNid(key); } g_LNid.Unlock(); } @@ -251,13 +263,14 @@ void CCallsign::SetDmrid(uint32_t dmrid, bool UpdateCallsign) { g_LDid.Lock(); { - const CCallsign *callsign = g_LDid.FindCallsign(dmrid); + auto callsign = g_LDid.FindCallsign(dmrid); if ( callsign != nullptr ) { - memcpy(m_Callsign, callsign->m_Callsign, CALLSIGN_LEN); + m_Callsign.l = callsign->l; } } g_LDid.Unlock(); + CSIn(); } } @@ -276,13 +289,14 @@ void CCallsign::SetNXDNid(uint16_t nxdnid, bool UpdateCallsign) { g_LNid.Lock(); { - const CCallsign *callsign = g_LNid.FindCallsign(nxdnid); + auto callsign = g_LNid.FindCallsign(nxdnid); if ( callsign != nullptr ) { - memcpy(m_Callsign, callsign->m_Callsign, CALLSIGN_LEN); + m_Callsign.l = callsign->l; } } g_LNid.Unlock(); + CSIn(); } } @@ -301,17 +315,17 @@ void CCallsign::SetCSModule(char c) } -void CCallsign::SetSuffix(const char *sz) +void CCallsign::SetSuffix(const std::string &s) { - memset(m_Suffix, ' ', CALLSUFFIX_LEN); - memcpy(m_Suffix, sz, MIN(strlen(sz), CALLSUFFIX_LEN)); + memset(m_Suffix.c, ' ', CALLSUFFIX_LEN); + memcpy(m_Suffix.c, s.c_str(), MIN(s.size(), CALLSUFFIX_LEN)); } void CCallsign::SetSuffix(const uint8_t *buffer, int len) { len = MIN(len, (int)CALLSUFFIX_LEN); - memset(m_Suffix, ' ', CALLSUFFIX_LEN); - memcpy(m_Suffix, buffer, len); + memset(m_Suffix.c, ' ', CALLSUFFIX_LEN); + memcpy(m_Suffix.c, buffer, len); } //////////////////////////////////////////////////////////////////////////////////////// @@ -321,7 +335,7 @@ void CCallsign::PatchCallsign(int off, const char *patch, int len) { if ( off < CALLSIGN_LEN ) { - memcpy(m_Callsign, patch, MIN(len, (int)CALLSIGN_LEN - off)); + memcpy(m_Callsign.c, patch, MIN(len, (int)CALLSIGN_LEN - off)); } CSIn(); } @@ -330,9 +344,24 @@ void CCallsign::PatchCallsign(int off, const char *patch, int len) //////////////////////////////////////////////////////////////////////////////////////// // get +const UCallsign CCallsign::GetKey() const +{ + UCallsign rval; + rval.l = 0; + for (unsigned i=0; i=0; i-- ) { - pos = m17_alphabet.find(m_Callsign[i]); + pos = m17_alphabet.find(m_Callsign.c[i]); if (pos == std::string::npos) { pos = 0; } diff --git a/reflector/Callsign.h b/reflector/Callsign.h index 6e5d734..c0a6901 100644 --- a/reflector/Callsign.h +++ b/reflector/Callsign.h @@ -27,6 +27,18 @@ #define CALLSIGN_LEN 8 #define CALLSUFFIX_LEN 4 +union UCallsign +{ + char c[CALLSIGN_LEN]; + uint64_t l; +}; + +union USuffix +{ + char c[CALLSUFFIX_LEN]; + uint32_t u; +}; + //////////////////////////////////////////////////////////////////////////////////////// // class @@ -36,7 +48,9 @@ class CCallsign public: // contructors CCallsign(); - CCallsign(const char *, uint32_t = 0, uint16_t = 0); + CCallsign(const UCallsign &cs); // no id lookup + CCallsign(const CCallsign &cs); + CCallsign(const std::string &cs, uint32_t dmrid = 0, uint16_t nxdnid = 0); // status bool IsValid(void) const; @@ -44,23 +58,24 @@ public: bool HasModule(void) const { return m_Module != ' '; } // set - void SetCallsign(const char *, bool = true); + void SetCallsign(const std::string &s, bool updateids = true); void SetCallsign(const uint8_t *, int, bool = true); void SetDmrid(uint32_t, bool = true); void SetDmrid(const uint8_t *, bool = true); void SetNXDNid(uint16_t, bool = true); void SetNXDNid(const uint8_t *, bool = true); void SetCSModule(char); - void SetSuffix(const char *); + void SetSuffix(const std::string &s); void SetSuffix(const uint8_t *, int); // modify void PatchCallsign(int, const char *, int); // get + const UCallsign GetKey() const; void GetCallsign(uint8_t *) const; void GetCallsignString(char *) const; - const std::string GetCS(unsigned len = 9) const; + const std::string GetCS() const; uint32_t GetDmrid(void) const { return m_uiDmrid; } uint16_t GetNXDNid(void) const { return m_uiNXDNid; } void GetSuffix(uint8_t *) const; @@ -73,6 +88,7 @@ public: bool HasSameModule(const CCallsign &) const; // operators + CCallsign &operator = (const CCallsign &cs); bool operator ==(const CCallsign &) const; operator const char *() const; @@ -92,10 +108,10 @@ protected: protected: // data - char m_Callsign[CALLSIGN_LEN]; - char m_Suffix[CALLSUFFIX_LEN]; - char m_Module; - uint32_t m_uiDmrid; - uint16_t m_uiNXDNid; - uint64_t m_coded; // M17 encoded callsign + UCallsign m_Callsign; + USuffix m_Suffix; + char m_Module; + uint32_t m_uiDmrid; + uint16_t m_uiNXDNid; + uint64_t m_coded; // M17 encoded callsign }; diff --git a/reflector/Lookup.cpp b/reflector/Lookup.cpp index 5d4d07e..f70bfa3 100644 --- a/reflector/Lookup.cpp +++ b/reflector/Lookup.cpp @@ -86,7 +86,7 @@ void CLookup::Thread() // It would be a lot of work (iterating on an unordered_map) to do otherwise! if (http_loaded || ERefreshType::file == m_Type) ClearContents(); - UpdateContent(ss); + UpdateContent(ss, Eaction::normal); Unlock(); } @@ -115,7 +115,7 @@ bool CLookup::LoadContentFile(std::stringstream &ss) return rval; } -bool CLookup::Dump() +bool CLookup::Utility(Eaction action) { std::stringstream ss; LoadParameters(); diff --git a/reflector/Lookup.h b/reflector/Lookup.h index f921c81..bbc86bb 100644 --- a/reflector/Lookup.h +++ b/reflector/Lookup.h @@ -24,14 +24,16 @@ #include "Callsign.h" #include "Configure.h" +enum class Eaction { normal, parse, error_only }; + // compare function for std::map::find struct CCallsignHash { - std::size_t operator() (const CCallsign &cs) const + std::size_t operator() (const UCallsign &ucs) const { - std::hash hash; - return hash(cs.GetCS()); + std::hash hash; + return hash(ucs.l); } }; @@ -50,7 +52,7 @@ public: // locks void Lock(void) { m_Mutex.lock(); } void Unlock(void) { m_Mutex.unlock(); } - bool Dump(void); + bool Utility(Eaction action); protected: std::time_t GetLastModTime(); @@ -61,7 +63,7 @@ protected: // refresh bool LoadContentHttp(std::stringstream &ss); bool LoadContentFile(std::stringstream &ss); - virtual void UpdateContent(std::stringstream &ss) = 0; + virtual void UpdateContent(std::stringstream &ss, Eaction action) = 0; std::mutex m_Mutex; ERefreshType m_Type; diff --git a/reflector/LookupDmr.cpp b/reflector/LookupDmr.cpp index 14b3a0f..e71a7de 100644 --- a/reflector/LookupDmr.cpp +++ b/reflector/LookupDmr.cpp @@ -37,10 +37,9 @@ void CLookupDmr::LoadParameters() m_Url.assign(g_Conf.GetString(g_Keys.dmriddb.url)); } -uint32_t CLookupDmr::FindDmrid(const CCallsign &callsign) +const uint32_t CLookupDmr::FindDmrid(const UCallsign &ucs) const { - - auto found = m_DmridMap.find(callsign); + auto found = m_DmridMap.find(ucs); if ( found != m_DmridMap.end() ) { return (found->second); @@ -48,7 +47,7 @@ uint32_t CLookupDmr::FindDmrid(const CCallsign &callsign) return 0; } -const CCallsign *CLookupDmr::FindCallsign(uint32_t dmrid) +const UCallsign *CLookupDmr::FindCallsign(const uint32_t dmrid) const { auto found = m_CallsignMap.find(dmrid); if ( found != m_CallsignMap.end() ) @@ -58,27 +57,47 @@ const CCallsign *CLookupDmr::FindCallsign(uint32_t dmrid) return nullptr; } -void CLookupDmr::UpdateContent(std::stringstream &ss) +void CLookupDmr::UpdateContent(std::stringstream &ss, Eaction action) { std::string line; while (std::getline(ss, line)) { - std::string cs_str, id_str; - std::istringstream iss(line); - std::getline(iss, id_str, ';'); - std::getline(iss, cs_str, ';'); - auto lid = stol(id_str); - if (lid > 0 && lid < 0x1000000 && cs_str.size() < CALLSIGN_LEN) + bool failed = true; + auto l = atol(line.c_str()); // no throw guarantee + if (0L < l && l <= 9999999L) { - auto id = uint32_t(lid); - CCallsign cs(cs_str.c_str(), id); - m_DmridMap[cs] = id; - m_CallsignMap[id] = cs; + auto id = uint32_t(l); + auto p1 = line.find(';'); + if (std::string::npos != p1) + { + auto p2 = line.find(';', ++p1); + if (std::string::npos != p2) + { + const auto cs_str(line.substr(p1, p2-p1)); + CCallsign cs; + cs.SetCallsign(cs_str, false); + if (cs.IsValid()) + { + failed = false; + if (Eaction::normal == action) + { + auto key = cs.GetKey(); + m_DmridMap[key] = id; + m_CallsignMap[id] = key; + } + else if (Eaction::parse == action) + { + std::cout << id << ';' << cs_str << ";\n"; + } + } + } + } } - else + if (Eaction::error_only == action && failed) { - std::cout << "DMR Id '" << id_str << ';' << cs_str << ";' is malformed" << std::endl; + std::cout << "Bad syntax at line '" << line << "'\n"; } } - std::cout << "DMR Id database size now is " << m_DmridMap.size() << std::endl; + if (Eaction::normal == action) + std::cout << "DMR Id database size: " << m_DmridMap.size() << std::endl; } diff --git a/reflector/LookupDmr.h b/reflector/LookupDmr.h index 360262f..a0f1851 100644 --- a/reflector/LookupDmr.h +++ b/reflector/LookupDmr.h @@ -24,15 +24,15 @@ class CLookupDmr : public CLookup { public: ~CLookupDmr() {} - uint32_t FindDmrid(const CCallsign &cs); - const CCallsign *FindCallsign(uint32_t dmrid); + const uint32_t FindDmrid(const UCallsign &ucs) const; + const UCallsign *FindCallsign(uint32_t dmrid) const; protected: void ClearContents(); void LoadParameters(); - void UpdateContent(std::stringstream &ss); + void UpdateContent(std::stringstream &ss, Eaction action); private: - std::unordered_map m_CallsignMap; - std::unordered_map m_DmridMap; + std::unordered_map m_CallsignMap; + std::unordered_map m_DmridMap; }; diff --git a/reflector/LookupNxdn.cpp b/reflector/LookupNxdn.cpp index 6f5e7d9..7379c8f 100644 --- a/reflector/LookupNxdn.cpp +++ b/reflector/LookupNxdn.cpp @@ -37,7 +37,7 @@ void CLookupNxdn::LoadParameters() m_Url.assign(g_Conf.GetString(g_Keys.nxdniddb.url)); } -const CCallsign *CLookupNxdn::FindCallsign(uint16_t nxdnid) +const UCallsign *CLookupNxdn::FindCallsign(uint16_t nxdnid) const { auto found = m_CallsignMap.find(nxdnid); if ( found != m_CallsignMap.end() ) @@ -47,37 +47,57 @@ const CCallsign *CLookupNxdn::FindCallsign(uint16_t nxdnid) return nullptr; } -uint16_t CLookupNxdn::FindNXDNid(const CCallsign &callsign) +const uint16_t CLookupNxdn::FindNXDNid(const UCallsign &ucs) const { - auto found = m_NxdnidMap.find(callsign); + auto found = m_NxdnidMap.find(ucs); if ( found != m_NxdnidMap.end() ) { - return (found->second); + return found->second; } return 0; } -void CLookupNxdn::UpdateContent(std::stringstream &ss) +void CLookupNxdn::UpdateContent(std::stringstream &ss, Eaction action) { std::string line; while (std::getline(ss, line)) { - std::string cs_str, id_str; - std::istringstream iss(line); - std::getline(iss, id_str, ','); - std::getline(iss, cs_str, ','); - auto lid = stol(id_str); - if (lid > 0 && lid < 0x10000 && cs_str.size() < CALLSIGN_LEN) + bool failed = true; + auto l = atol(line.c_str()); // no throw guarantee + if (0 < l && l < 0x10000UL) { - auto id = uint16_t(lid); - CCallsign cs(cs_str.c_str(), 0, id); - m_NxdnidMap[cs] = id; - m_CallsignMap[id] = cs; + auto id = uint32_t(l); + auto p1 = line.find(','); + if (std::string::npos != p1) + { + auto p2 = line.find(',', ++p1); + if (std::string::npos != p2) + { + const auto cs_str = line.substr(p1, p2-p1); + CCallsign cs; + cs.SetCallsign(cs_str, false); + if (cs.IsValid()) + { + failed = false; + if (Eaction::normal == action) + { + auto key = cs.GetKey(); + m_NxdnidMap[key] = id; + m_CallsignMap[id] = key; + } + else if (Eaction::parse == action) + { + std::cout << id << ',' << cs_str << ",\n"; + } + } + } + } } - else + if (Eaction::error_only == action && failed) { - std::cout << "NXDN Id '" << id_str << ',' << cs_str << ",' is malformed" << std::endl; + std::cout << "Bad syntax at line '" << line << "'\n"; } } - std::cout << "NXDN Id database size now is " << m_NxdnidMap.size() << std::endl; + if (Eaction::normal == action) + std::cout << "NXDN Id database size: " << m_NxdnidMap.size() << std::endl; } diff --git a/reflector/LookupNxdn.h b/reflector/LookupNxdn.h index 946ab9a..ca503f6 100644 --- a/reflector/LookupNxdn.h +++ b/reflector/LookupNxdn.h @@ -23,14 +23,14 @@ class CLookupNxdn : public CLookup { public: - uint16_t FindNXDNid(const CCallsign &callsign); - const CCallsign *FindCallsign(uint16_t id); + const uint16_t FindNXDNid(const UCallsign &ucs) const; + const UCallsign *FindCallsign(const uint16_t id) const; protected: void ClearContents(); void LoadParameters(); - void UpdateContent(std::stringstream &ss); + void UpdateContent(std::stringstream &ss, Eaction action); private: - std::unordered_map m_CallsignMap; - std::unordered_map m_NxdnidMap; + std::unordered_map m_CallsignMap; + std::unordered_map m_NxdnidMap; }; diff --git a/reflector/LookupYsf.cpp b/reflector/LookupYsf.cpp index 2b45a12..6964bb6 100644 --- a/reflector/LookupYsf.cpp +++ b/reflector/LookupYsf.cpp @@ -39,34 +39,43 @@ void CLookupYsf::LoadParameters() m_DefaultRx = g_Conf.GetUnsigned(g_Keys.ysf.defaultrxfreq); } -void CLookupYsf::UpdateContent(std::stringstream &ss) +void CLookupYsf::UpdateContent(std::stringstream &ss, Eaction action) { std::string line; while (std::getline(ss, line)) { + CCallsign cs; std::string cs_str, tx_str, rx_str; std::istringstream iss(line); std::getline(iss, cs_str, ';'); std::getline(iss, tx_str, ';'); std::getline(iss, rx_str, ';'); - auto ltx = stol(tx_str); - auto lrx = stol(rx_str); - if (ltx > 40000000 && ltx < 0x100000000 && lrx > 40000000 && lrx < 0x100000000 && CCallsign(cs_str.c_str()).IsValid()) + cs.SetCallsign(cs_str, false); + auto ltx = atol(tx_str.c_str()); + auto lrx = atol(rx_str.c_str()); + if (ltx > 40000000 && ltx < 0x100000000 && lrx > 40000000 && lrx < 0x100000000 && cs.IsValid()) { - m_map.emplace(CCallsign(cs_str.c_str()), CYsfNode(uint32_t(ltx), uint32_t(lrx))); + if (Eaction::parse == action) + { + std::cout << cs_str << ';' << tx_str << ';' << rx_str << ";\n"; + } + else if (Eaction::normal == action) + { + m_map[cs.GetKey()] = CYsfNode(ltx, lrx); + } } - else + else if (Eaction::error_only == action) { - std::cout << "YSF value '" << cs_str << ';' << tx_str << ';' << rx_str << ";' is malformed" << std::endl; + std::cout << "YSF value '" << line << ";' is malformed" << std::endl; } } std::cout << "DMR Id database size now is " << m_map.size() << std::endl; } -void CLookupYsf::FindFrequencies(const CCallsign &callsign, uint32_t &txfreq, uint32_t &rxfreq) +void CLookupYsf::FindFrequencies(const CCallsign &cs, uint32_t &txfreq, uint32_t &rxfreq) { - auto found = m_map.find(callsign); - if ( found != m_map.end() ) + auto found = m_map.find(cs.GetKey()); + if (found != m_map.end()) { txfreq = found->second.GetTxFrequency(); rxfreq = found->second.GetRxFrequency(); diff --git a/reflector/LookupYsf.h b/reflector/LookupYsf.h index 8c8fa90..2efc11f 100644 --- a/reflector/LookupYsf.h +++ b/reflector/LookupYsf.h @@ -21,7 +21,7 @@ #include "YSFNode.h" #include "Lookup.h" -using CsNodeMap = std::unordered_map; +using CsNodeMap = std::unordered_map; class CLookupYsf : public CLookup { @@ -31,7 +31,7 @@ public: protected: void ClearContents(); void LoadParameters(); - void UpdateContent(std::stringstream &ss); + void UpdateContent(std::stringstream &ss, Eaction action); private: CsNodeMap m_map; diff --git a/reflector/Main.cpp b/reflector/Main.cpp index 21d8205..d1b82b0 100644 --- a/reflector/Main.cpp +++ b/reflector/Main.cpp @@ -20,9 +20,11 @@ #include "Global.h" +#ifndef UTILITY //////////////////////////////////////////////////////////////////////////////////////// // global objects +SJsonKeys g_Keys; CReflector g_Refl; CGateKeeper g_Gate; CConfigure g_Conf; @@ -30,7 +32,6 @@ CVersion g_Vers(3,0,0); // The major byte should only change if the interlink CLookupDmr g_LDid; CLookupNxdn g_LNid; CLookupYsf g_LYtr; -SJsonKeys g_Keys; //////////////////////////////////////////////////////////////////////////////////////// @@ -75,3 +76,149 @@ int main(int argc, char *argv[]) // done return EXIT_SUCCESS; } + +#else // UTILITY is defined + +#include + +//////////////////////////////////////////////////////////////////////////////////////// +// global objects + +SJsonKeys g_Keys; +CConfigure g_Conf; +CLookupDmr g_LDid; +CLookupNxdn g_LNid; +CLookupYsf g_LYtr; + +static void usage(std::ostream &os, const char *name) +{ + os << "Usage: " << name << " [-d | -n | -y] [-p | -q] inifile\n"; + os << "Where:\n" + " -d - read the DMR Id http source (default)\n" + " -n - read the NXDN Id http source\n" + " -y - read the YSF Tx/Tx http source\n" + " -p - parse the input, removing bad lines\n" + " -q - parse the input, but only output problem lines in the http source\n" + " infile - an error-free urfd ini file (check it first with inicheck)\n" + "Without -p or -q, no parsing is done and the raw http source is output\n" + << std::endl; +} + +enum class Edb { none, dmr, nxdn, ysf }; + +int main(int argc, char *argv[]) +{ + Edb db = Edb::none; + Eaction action = Eaction::normal; + while (1) + { + auto c = getopt(argc, argv, "dnypq"); + if (c < 0) + { + if (1 == argc) + { + usage(std::cout, argv[0]); + return EXIT_SUCCESS; + } + break; + } + else + { + switch (c) + { + // define the input souce + case 'd': + if (Edb::none == db) + db = Edb::dmr; + else + { + std::cerr << "You can only select one database!\n"; + usage(std::cerr, argv[0]); + return EXIT_FAILURE; + } + break; + + case 'n': + if (Edb::none == db) + db = Edb::nxdn; + else + { + std::cerr << "You can only select one database!\n"; + usage(std::cerr, argv[0]); + return EXIT_FAILURE; + } + break; + case 'y': + if (Edb::none == db) + db = Edb::ysf; + else + { + std::cerr << "You can only select one database!\n"; + usage(std::cerr, argv[0]); + return EXIT_FAILURE; + } + break; + + // define the action + case 'p': + if (Eaction::err_only == action) + { + std::cerr << "You can't specify both -p and -q!\n"; + usage(std::cerr, argv[0]); + return EXIT_FAILURE; + } + else + action = Eaction::parse; + break; + + case 'q': + if (Eaction::parse == action) + { + std::cerr << "You can't specify both -p and -q!\n"; + usage(std::cerr, argv[0]); + return EXIT_FAILURE; + } + else + action = Eaction::err_only; + break; + + // finally + default: + usage(std::cerr, argv[0]); + return EXIT_FAILURE; + break; + } + } + } + + if (optind + 1 != argc) + { + std::cerr << argv[0] << ": " << ((optind==argc) ? "No ini file specified!" : "Too many arguments!") << std::endl; + usage(std::cerr, argv[0]); + exit(EXIT_FAILURE); + } + + if (g_Conf.ReadData(argv[optind])) + return EXIT_FAILURE; + + if (Edb::none == db) + db = Edb::dmr; + + switch (db) + { + case Edb::dmr: + g_LDid.Utility(action); + break; + + case Edb::nxdn: + g_LNid.Utility(action); + break; + + case Edb::ysf: + g_LYtr.Utility(action); + break; + } + + return EXIT_SUCCESS; +} +#endif diff --git a/reflector/Makefile b/reflector/Makefile index 333d07a..0ce66d6 100644 --- a/reflector/Makefile +++ b/reflector/Makefile @@ -22,6 +22,8 @@ EXE = urfd INICHECK = inicheck +DBUTIL = dbutil + include configure.mk ifeq ($(debug), true) @@ -36,7 +38,7 @@ SRCS = $(wildcard *.cpp) OBJS = $(SRCS:.cpp=.o) DEPS = $(SRCS:.cpp=.d) -all : $(EXE) $(INICHECK) +all : $(EXE) $(INICHECK) $(DBUTIL) $(EXE) : $(OBJS) $(CXX) $^ -o $@ $(LDFLAGS) @@ -44,11 +46,14 @@ $(EXE) : $(OBJS) $(INICHECK) : Configure.cpp CurlGet.cpp $(CXX) -DINICHECK $(CFLAGS) Configure.cpp CurlGet.cpp -o $(INICHECK) -lcurl +$(DBUTIL) : Main.cpp Configure.cpp CurlGet.cpp Lookup.cpp LookupDmr.cpp LookupNxdn.cpp LookupYsf.cpp YSFNode.cpp Callsign.cpp + $(CXX) -DUTILITY $(CFLAGS) -o dbutil Main.cpp Configure.cpp CurlGet.cpp Lookup.cpp LookupDmr.cpp LookupNxdn.cpp LookupYsf.cpp YSFNode.cpp Callsign.cpp -lcurl + %.o : %.cpp $(CXX) $(CFLAGS) -c $< -o $@ clean : - $(RM) *.o *.d $(EXE) $(INICHECK) + $(RM) *.o *.d $(EXE) $(INICHECK) $(DBUTIL) -include $(DEPS) diff --git a/reflector/example.ini b/reflector/example.ini index b404452..a8d69a2 100644 --- a/reflector/example.ini +++ b/reflector/example.ini @@ -1,15 +1,16 @@ ###### URFD CONFIGURATION Example ###### +# comments begin with '#' # Do not use quotes, unless in a comment! [Names] Callsign = URF??? # where ? is A-Z or 0-9 -SysopEmail = you@somewhere.com +SysopEmail = me@somewhere.com # 2-letter country codes are listed at https://www.iban.com/country-codes -Country = US +Country = GB -Sponsor = My Ham Club +Sponsor = My Home Club [IpAddresses] # Binding addresses are usually the 'any' address @@ -19,16 +20,15 @@ IPv4Binding = 0.0.0.0 # IPv6Binding = :: # define if you want to override what urfd finds using ipv4.icanhazip.com -# IPv4External = 1.2.3.4 - +# IPv4External = 4.3.2.1 # define if you want to override what urfd finds using ipv6.icanhazip.com -# IPv6External = a:b:c:e:f:0:1:2 +# IPv6External = f:e:d:c:b:a:9:0 Transcoder = local # SORRY, but only local TC's are supported right now! [Modules] -Modules = ADMSZ # Modules = ABCDEFGHIJKLMNOPQRSTUVWXYZ +Modules = ADMSZ Transcoded = A # comment out if you don't have transcoding hardware # Create Descriptions as needed... DescriptionA = Transcoded @@ -58,7 +58,7 @@ Port = 17000 [MMDVM] Port = 62030 -DefaultId = 0 # if the DMR id is zero, this will be used (also used for P25) +DefaultId = 0 [NXDN] Port = 41400 @@ -77,7 +77,7 @@ Port = 10017 Port = 34001 AutoLinkModule = A # comment out if you want to disable AL DefaultCallsign = ALLSTAR -ClientFilePath = /home/user/urfd/USRPClients.txt +ClientFilePath = /usr/local/etc/USRPClients.txt [YSF] Port = 42000 @@ -91,31 +91,30 @@ RegistrationDescription = URF Reflector ######## Database files [DMR ID DB] -Hostname = xlxapi.rlx.lu -Suffix = api/exportdmr.php -Mode = http -RefreshMin = 179 -FilePath = /home/user/urfd/dmrid.dat +Mode = http #### Mode is "http", "file", or "both" + #### if "both", the url will be read first +FilePath = /usr/local/etc/dmrid.dat # for you to add your own values + # will be reloaded quickly, about 10s +URL = http://xlxapi.rlx.lu/api/exportdmr.php # if Mode "http" or "both" +RefreshMin = 179 # RefreshMin will only be used if the Mode is "file" [NXDN ID DB] -Hostname = www.dudetronics.com -Suffix = ar-dns/NXDN.csv Mode = http -RefreshMin = 181 -FilePath = /home/user/urfd/nxdn.dat +FilePath = /usr/local/etc/nxdn.dat +URL = https://radioid.net/static/nxdn.csv +RefreshMin = 1440 # radioid.net says this file is updated once/day [YSF TX/RX DB] -Hostname = xlxapi.rlx.lu -Suffix = api/exportysfrepeaters.php Mode = http +FilePath = /usr/local/etc/ysfnode.dat +URL = http://xlxapi.rlx.lu/api/exportysfrepeaters.php RefreshMin = 191 -FilePath = /home/user/urfd/ysfnode.dat ######### Other File locations [Files] -PidPath = /var/run/urfd.pid +PidPath = /var/run/urfd.pid JsonPath = /var/log/urfd.json -WhitelistPath = /home/user/urfd/urfd.whitelist -BlacklistPath = /home/user/urfd/urfd.blacklist -InterlinkPath = /home/user/urfd/urfd.interlink -G3TerminalPath = /home/user/urfd/urfd.terminal +WhitelistPath = /usr/local/etc/urfd.whitelist +BlacklistPath = /usr/local/etc/urfd.blacklist +InterlinkPath = /usr/local/etc/urfd.interlink +G3TerminalPath = /usr/local/etc/urfd.terminal From ee0664dab7dd89ce3c99b2ccb014d11070e9843d Mon Sep 17 00:00:00 2001 From: Tom Early Date: Sun, 19 Feb 2023 04:13:58 -0700 Subject: [PATCH 08/44] it compiles --- reflector/Callsign.cpp | 15 +++------------ reflector/Callsign.h | 2 +- reflector/Lookup.h | 8 ++++++++ reflector/LookupDmr.cpp | 2 +- reflector/LookupDmr.h | 4 ++-- reflector/LookupNxdn.cpp | 4 ++-- reflector/LookupNxdn.h | 4 ++-- reflector/LookupYsf.h | 2 +- reflector/Main.cpp | 4 ++-- 9 files changed, 22 insertions(+), 23 deletions(-) diff --git a/reflector/Callsign.cpp b/reflector/Callsign.cpp index 79d3065..328c5e1 100644 --- a/reflector/Callsign.cpp +++ b/reflector/Callsign.cpp @@ -38,15 +38,6 @@ CCallsign::CCallsign() m_coded = 0; } -CCallsign::CCallsign(const CCallsign &cs) -{ - m_Callsign.l = cs.m_Callsign.l; - m_Suffix.u = cs.m_Suffix.u; - m_Module = cs.m_Module; - if (m_Callsign.l) - CSIn(); -} - CCallsign::CCallsign(const std::string &cs, uint32_t dmrid, uint16_t nxdnid) : CCallsign() { // and populate @@ -222,7 +213,7 @@ void CCallsign::SetCallsign(const std::string &s, bool updateids) } } -void CCallsign::SetCallsign(const uint8_t *buffer, int len, bool UpdateDmrid) +void CCallsign::SetCallsign(const uint8_t *buffer, int len, bool updateids) { // set callsign memset(m_Callsign.c, ' ', CALLSIGN_LEN); @@ -240,7 +231,7 @@ void CCallsign::SetCallsign(const uint8_t *buffer, int len, bool UpdateDmrid) m_Module = (char)buffer[CALLSIGN_LEN-1]; } CSIn(); - if ( UpdateDmrid ) + if (updateids) { auto key = GetKey(); g_LDid.Lock(); @@ -344,7 +335,7 @@ void CCallsign::PatchCallsign(int off, const char *patch, int len) //////////////////////////////////////////////////////////////////////////////////////// // get -const UCallsign CCallsign::GetKey() const +UCallsign CCallsign::GetKey() const { UCallsign rval; rval.l = 0; diff --git a/reflector/Callsign.h b/reflector/Callsign.h index c0a6901..49bb6d9 100644 --- a/reflector/Callsign.h +++ b/reflector/Callsign.h @@ -72,7 +72,7 @@ public: void PatchCallsign(int, const char *, int); // get - const UCallsign GetKey() const; + UCallsign GetKey() const; void GetCallsign(uint8_t *) const; void GetCallsignString(char *) const; const std::string GetCS() const; diff --git a/reflector/Lookup.h b/reflector/Lookup.h index bbc86bb..541204e 100644 --- a/reflector/Lookup.h +++ b/reflector/Lookup.h @@ -37,6 +37,14 @@ struct CCallsignHash } }; +struct CCallsignEqual +{ + bool operator() (const UCallsign &ucs1, const UCallsign &ucs2) const + { + return ucs1.l == ucs2.l; + } +}; + //////////////////////////////////////////////////////////////////////////////////////// diff --git a/reflector/LookupDmr.cpp b/reflector/LookupDmr.cpp index e71a7de..e239a62 100644 --- a/reflector/LookupDmr.cpp +++ b/reflector/LookupDmr.cpp @@ -37,7 +37,7 @@ void CLookupDmr::LoadParameters() m_Url.assign(g_Conf.GetString(g_Keys.dmriddb.url)); } -const uint32_t CLookupDmr::FindDmrid(const UCallsign &ucs) const +uint32_t CLookupDmr::FindDmrid(const UCallsign &ucs) const { auto found = m_DmridMap.find(ucs); if ( found != m_DmridMap.end() ) diff --git a/reflector/LookupDmr.h b/reflector/LookupDmr.h index a0f1851..b5a6d09 100644 --- a/reflector/LookupDmr.h +++ b/reflector/LookupDmr.h @@ -24,7 +24,7 @@ class CLookupDmr : public CLookup { public: ~CLookupDmr() {} - const uint32_t FindDmrid(const UCallsign &ucs) const; + uint32_t FindDmrid(const UCallsign &ucs) const; const UCallsign *FindCallsign(uint32_t dmrid) const; protected: @@ -34,5 +34,5 @@ protected: private: std::unordered_map m_CallsignMap; - std::unordered_map m_DmridMap; + std::unordered_map m_DmridMap; }; diff --git a/reflector/LookupNxdn.cpp b/reflector/LookupNxdn.cpp index 7379c8f..a6a3abe 100644 --- a/reflector/LookupNxdn.cpp +++ b/reflector/LookupNxdn.cpp @@ -47,7 +47,7 @@ const UCallsign *CLookupNxdn::FindCallsign(uint16_t nxdnid) const return nullptr; } -const uint16_t CLookupNxdn::FindNXDNid(const UCallsign &ucs) const +uint16_t CLookupNxdn::FindNXDNid(const UCallsign &ucs) const { auto found = m_NxdnidMap.find(ucs); if ( found != m_NxdnidMap.end() ) @@ -64,7 +64,7 @@ void CLookupNxdn::UpdateContent(std::stringstream &ss, Eaction action) { bool failed = true; auto l = atol(line.c_str()); // no throw guarantee - if (0 < l && l < 0x10000UL) + if (0 < l && l < 0x10000) { auto id = uint32_t(l); auto p1 = line.find(','); diff --git a/reflector/LookupNxdn.h b/reflector/LookupNxdn.h index ca503f6..9310f5e 100644 --- a/reflector/LookupNxdn.h +++ b/reflector/LookupNxdn.h @@ -23,7 +23,7 @@ class CLookupNxdn : public CLookup { public: - const uint16_t FindNXDNid(const UCallsign &ucs) const; + uint16_t FindNXDNid(const UCallsign &ucs) const; const UCallsign *FindCallsign(const uint16_t id) const; protected: void ClearContents(); @@ -32,5 +32,5 @@ protected: private: std::unordered_map m_CallsignMap; - std::unordered_map m_NxdnidMap; + std::unordered_map m_NxdnidMap; }; diff --git a/reflector/LookupYsf.h b/reflector/LookupYsf.h index 2efc11f..00d9f53 100644 --- a/reflector/LookupYsf.h +++ b/reflector/LookupYsf.h @@ -21,7 +21,7 @@ #include "YSFNode.h" #include "Lookup.h" -using CsNodeMap = std::unordered_map; +using CsNodeMap = std::unordered_map; class CLookupYsf : public CLookup { diff --git a/reflector/Main.cpp b/reflector/Main.cpp index d1b82b0..ac73d9e 100644 --- a/reflector/Main.cpp +++ b/reflector/Main.cpp @@ -161,7 +161,7 @@ int main(int argc, char *argv[]) // define the action case 'p': - if (Eaction::err_only == action) + if (Eaction::error_only == action) { std::cerr << "You can't specify both -p and -q!\n"; usage(std::cerr, argv[0]); @@ -179,7 +179,7 @@ int main(int argc, char *argv[]) return EXIT_FAILURE; } else - action = Eaction::err_only; + action = Eaction::error_only; break; // finally From 99dd9543a389e0465ba8678316c943866c3a8f93 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Mon, 20 Feb 2023 10:22:44 -0700 Subject: [PATCH 09/44] improved CLookup::Utility --- reflector/Lookup.cpp | 6 +- reflector/Lookup.h | 3 +- reflector/LookupDmr.cpp | 2 +- reflector/LookupNxdn.cpp | 2 +- reflector/LookupYsf.cpp | 5 +- reflector/Main.cpp | 187 ++++++++++++++++++--------------------- reflector/Makefile | 9 +- 7 files changed, 100 insertions(+), 114 deletions(-) diff --git a/reflector/Lookup.cpp b/reflector/Lookup.cpp index f70bfa3..27bc6af 100644 --- a/reflector/Lookup.cpp +++ b/reflector/Lookup.cpp @@ -115,12 +115,12 @@ bool CLookup::LoadContentFile(std::stringstream &ss) return rval; } -bool CLookup::Utility(Eaction action) +bool CLookup::Utility(Eaction action, Esource source) { std::stringstream ss; LoadParameters(); - auto rval = LoadContentHttp(ss); + auto rval = (Esource::http == source) ? LoadContentHttp(ss) : LoadContentFile(ss); if (rval) - std::cout << ss.str() << std::endl; + UpdateContent(ss, action); return rval; } diff --git a/reflector/Lookup.h b/reflector/Lookup.h index 541204e..d4638d0 100644 --- a/reflector/Lookup.h +++ b/reflector/Lookup.h @@ -25,6 +25,7 @@ #include "Configure.h" enum class Eaction { normal, parse, error_only }; +enum class Esource { http, file }; // compare function for std::map::find @@ -60,7 +61,7 @@ public: // locks void Lock(void) { m_Mutex.lock(); } void Unlock(void) { m_Mutex.unlock(); } - bool Utility(Eaction action); + bool Utility(Eaction action, Esource source); protected: std::time_t GetLastModTime(); diff --git a/reflector/LookupDmr.cpp b/reflector/LookupDmr.cpp index e239a62..a3c202c 100644 --- a/reflector/LookupDmr.cpp +++ b/reflector/LookupDmr.cpp @@ -95,7 +95,7 @@ void CLookupDmr::UpdateContent(std::stringstream &ss, Eaction action) } if (Eaction::error_only == action && failed) { - std::cout << "Bad syntax at line '" << line << "'\n"; + std::cout << line << '\n'; } } if (Eaction::normal == action) diff --git a/reflector/LookupNxdn.cpp b/reflector/LookupNxdn.cpp index a6a3abe..95b4f00 100644 --- a/reflector/LookupNxdn.cpp +++ b/reflector/LookupNxdn.cpp @@ -95,7 +95,7 @@ void CLookupNxdn::UpdateContent(std::stringstream &ss, Eaction action) } if (Eaction::error_only == action && failed) { - std::cout << "Bad syntax at line '" << line << "'\n"; + std::cout << line << '\n'; } } if (Eaction::normal == action) diff --git a/reflector/LookupYsf.cpp b/reflector/LookupYsf.cpp index 6964bb6..6150ea7 100644 --- a/reflector/LookupYsf.cpp +++ b/reflector/LookupYsf.cpp @@ -66,10 +66,11 @@ void CLookupYsf::UpdateContent(std::stringstream &ss, Eaction action) } else if (Eaction::error_only == action) { - std::cout << "YSF value '" << line << ";' is malformed" << std::endl; + std::cout << line << '\n'; } } - std::cout << "DMR Id database size now is " << m_map.size() << std::endl; + if (Eaction::normal == action) + std::cout << "DMR Id database size now is " << m_map.size() << std::endl; } void CLookupYsf::FindFrequencies(const CCallsign &cs, uint32_t &txfreq, uint32_t &rxfreq) diff --git a/reflector/Main.cpp b/reflector/Main.cpp index ac73d9e..c6af52f 100644 --- a/reflector/Main.cpp +++ b/reflector/Main.cpp @@ -79,8 +79,6 @@ int main(int argc, char *argv[]) #else // UTILITY is defined -#include - //////////////////////////////////////////////////////////////////////////////////////// // global objects @@ -92,130 +90,115 @@ CLookupYsf g_LYtr; static void usage(std::ostream &os, const char *name) { - os << "Usage: " << name << " [-d | -n | -y] [-p | -q] inifile\n"; - os << "Where:\n" - " -d - read the DMR Id http source (default)\n" - " -n - read the NXDN Id http source\n" - " -y - read the YSF Tx/Tx http source\n" - " -p - parse the input, removing bad lines\n" - " -q - parse the input, but only output problem lines in the http source\n" - " infile - an error-free urfd ini file (check it first with inicheck)\n" - "Without -p or -q, no parsing is done and the raw http source is output\n" - << std::endl; + os << "\nUsage: " << name << " DATABASE SOURCE ACTION INIFILE\n"; + os << "DATABASE (choose one)\n" + " dmr : The DmrId <==> Callsign databases.\n" + " nxdn : The NxdnId <==> Callsign databases.\n" + " ysf : The Callsign => Tx/Rx frequency database.\n" + "SOURCE (choose one)\n" + " file : The file specified by the FilePath ini parameter.\n" + " http : The URL specified by the URL ini paramater.\n" + "ACTION (choose one)\n" + " print : Print all lines from the SOURCE that are syntactically correct.\n" + " error : Print only the lines with failed syntax.\n" + "INIFILE : an error-free urfd ini file (check it first with inicheck).\n\n" + "Only the first character of DATABASE, SOURCE and ACTION is read.\n" + "Example: " << name << " y f e urfd.ini # Check your YSF Tx/Rx database file specifed in urfd.ini for syntax errors.\n\n"; } enum class Edb { none, dmr, nxdn, ysf }; int main(int argc, char *argv[]) { - Edb db = Edb::none; - Eaction action = Eaction::normal; - while (1) + Edb db; + Eaction action; + Esource source; + + if (5 != argc) { - auto c = getopt(argc, argv, "dnypq"); - if (c < 0) - { - if (1 == argc) - { - usage(std::cout, argv[0]); - return EXIT_SUCCESS; - } - break; - } - else - { - switch (c) - { - // define the input souce - case 'd': - if (Edb::none == db) - db = Edb::dmr; - else - { - std::cerr << "You can only select one database!\n"; - usage(std::cerr, argv[0]); - return EXIT_FAILURE; - } - break; - - case 'n': - if (Edb::none == db) - db = Edb::nxdn; - else - { - std::cerr << "You can only select one database!\n"; - usage(std::cerr, argv[0]); - return EXIT_FAILURE; - } - break; - case 'y': - if (Edb::none == db) - db = Edb::ysf; - else - { - std::cerr << "You can only select one database!\n"; - usage(std::cerr, argv[0]); - return EXIT_FAILURE; - } - break; - - // define the action - case 'p': - if (Eaction::error_only == action) - { - std::cerr << "You can't specify both -p and -q!\n"; - usage(std::cerr, argv[0]); - return EXIT_FAILURE; - } - else - action = Eaction::parse; - break; - - case 'q': - if (Eaction::parse == action) - { - std::cerr << "You can't specify both -p and -q!\n"; - usage(std::cerr, argv[0]); - return EXIT_FAILURE; - } - else - action = Eaction::error_only; - break; - - // finally - default: - usage(std::cerr, argv[0]); - return EXIT_FAILURE; - break; - } - } + usage(std::cerr, argv[0]); + return EXIT_FAILURE; } - if (optind + 1 != argc) + switch (argv[1][0]) { - std::cerr << argv[0] << ": " << ((optind==argc) ? "No ini file specified!" : "Too many arguments!") << std::endl; - usage(std::cerr, argv[0]); - exit(EXIT_FAILURE); + case 'd': + case 'D': + db = Edb::dmr; + break; + case 'n': + case 'N': + db = Edb::nxdn; + break; + + case 'y': + case 'Y': + db = Edb::ysf; + break; + + default: + std::cout << "Unrecognized DATABASE: " << argv[1]; + db = Edb::none; + break; } - if (g_Conf.ReadData(argv[optind])) + switch (argv[2][0]) + { + case 'h': + case 'H': + source = Esource::http; + break; + + case 'f': + case 'F': + source = Esource::file; + break; + + default: + std::cerr << "Unrecognized SOURCE: " << argv[2] << std::endl; + db = Edb::none; + break; + } + + switch (argv[3][0]) + { + case 'p': + case 'P': + action = Eaction::parse; + break; + + case 'e': + case 'E': + action = Eaction::error_only; + break; + + default: + std::cerr << "Unrecognized ACTION: " << argv[3] << std::endl; + db = Edb::none; + break; + } + + if (db == Edb::none) + { + usage(std::cerr, argv[0]); return EXIT_FAILURE; + } - if (Edb::none == db) - db = Edb::dmr; + if (g_Conf.ReadData(argv[4])) + return EXIT_FAILURE; switch (db) { case Edb::dmr: - g_LDid.Utility(action); + g_LDid.Utility(action, source); break; case Edb::nxdn: - g_LNid.Utility(action); + g_LNid.Utility(action, source); break; case Edb::ysf: - g_LYtr.Utility(action); + g_LYtr.Utility(action, source); break; } diff --git a/reflector/Makefile b/reflector/Makefile index 0ce66d6..292bf49 100644 --- a/reflector/Makefile +++ b/reflector/Makefile @@ -37,17 +37,18 @@ LDFLAGS=-pthread -lcurl SRCS = $(wildcard *.cpp) OBJS = $(SRCS:.cpp=.o) DEPS = $(SRCS:.cpp=.d) +DBUTILOBJS = Configure.o CurlGet.o Lookup.o LookupDmr.o LookupNxdn.o LookupYsf.o YSFNode.o Callsign.o all : $(EXE) $(INICHECK) $(DBUTIL) $(EXE) : $(OBJS) $(CXX) $^ -o $@ $(LDFLAGS) -$(INICHECK) : Configure.cpp CurlGet.cpp - $(CXX) -DINICHECK $(CFLAGS) Configure.cpp CurlGet.cpp -o $(INICHECK) -lcurl +$(INICHECK) : Configure.cpp CurlGet.o + $(CXX) -DINICHECK $(CFLAGS) $< CurlGet.o -o $@ -lcurl -$(DBUTIL) : Main.cpp Configure.cpp CurlGet.cpp Lookup.cpp LookupDmr.cpp LookupNxdn.cpp LookupYsf.cpp YSFNode.cpp Callsign.cpp - $(CXX) -DUTILITY $(CFLAGS) -o dbutil Main.cpp Configure.cpp CurlGet.cpp Lookup.cpp LookupDmr.cpp LookupNxdn.cpp LookupYsf.cpp YSFNode.cpp Callsign.cpp -lcurl +$(DBUTIL) : Main.cpp $(DBUTILOBJS) + $(CXX) -DUTILITY $(CFLAGS) $< $(DBUTILOBJS) -o $@ -lcurl %.o : %.cpp $(CXX) $(CFLAGS) -c $< -o $@ From b2e35d79088207017a73ac30e84b57d69852742a Mon Sep 17 00:00:00 2001 From: Tom Early Date: Tue, 21 Feb 2023 09:34:11 -0700 Subject: [PATCH 10/44] rename to ReflStateFile --- .gitignore | 3 --- reflector/Configure.cpp | 8 ++++---- reflector/JsonKeys.h | 4 ++-- reflector/Makefile | 18 +++++------------- reflector/example.ini | 2 +- 5 files changed, 12 insertions(+), 23 deletions(-) diff --git a/.gitignore b/.gitignore index 6e6d5ab..fcb78c0 100644 --- a/.gitignore +++ b/.gitignore @@ -6,9 +6,6 @@ reflector/urfd.whitelist reflector/urfd.interlink reflector/urfd.terminal configure.mk -configure.h -configure.sql -reflector.cfg wiresx/configure.php urfd* inicheck diff --git a/reflector/Configure.cpp b/reflector/Configure.cpp index c6546c5..886dce4 100644 --- a/reflector/Configure.cpp +++ b/reflector/Configure.cpp @@ -55,7 +55,6 @@ #define JIPV4EXTERNAL "IPv4External" #define JIPV6BINDING "IPv6Binding" #define JIPV6EXTERNAL "IPv6External" -#define JJSONPATH "JsonPath" #define JM17 "M17" #define JMMDVM "MMDVM" #define JMODE "Mode" @@ -72,6 +71,7 @@ #define JREGISTRATIONID "RegistrationID" #define JREGISTRATIONNAME "RegistrationName" #define JSPONSOR "Sponsor" +#define JREFLSTATEPATH "ReflStatePath" #define JSYSOPEMAIL "SysopEmail" #define JTRANSCODED "Transcoded" #define JTRANSCODER "Transcoder" @@ -456,8 +456,8 @@ bool CConfigure::ReadData(const std::string &path) case ESection::files: if (0 == key.compare(JPIDPATH)) data[g_Keys.files.pid] = value; - else if (0 == key.compare(JJSONPATH)) - data[g_Keys.files.json] = value; + else if (0 == key.compare(JREFLSTATEPATH)) + data[g_Keys.files.state] = value; else if (0 == key.compare(JWHITELISTPATH)) data[g_Keys.files.white] = value; else if (0 == key.compare(JBLACKLISTPATH)) @@ -672,7 +672,7 @@ bool CConfigure::ReadData(const std::string &path) } // Other files isDefined(ErrorLevel::fatal, JFILES, JPIDPATH, g_Keys.files.pid, rval); - isDefined(ErrorLevel::fatal, JFILES, JJSONPATH, g_Keys.files.json, rval); + isDefined(ErrorLevel::fatal, JFILES, JREFLSTATEPATH, g_Keys.files.state, rval); isDefined(ErrorLevel::fatal, JFILES, JWHITELISTPATH, g_Keys.files.white, rval); isDefined(ErrorLevel::fatal, JFILES, JBLACKLISTPATH, g_Keys.files.black, rval); isDefined(ErrorLevel::fatal, JFILES, JINTERLINKPATH, g_Keys.files.interlink, rval); diff --git a/reflector/JsonKeys.h b/reflector/JsonKeys.h index 83a2b03..38b06b6 100644 --- a/reflector/JsonKeys.h +++ b/reflector/JsonKeys.h @@ -52,6 +52,6 @@ struct SJsonKeys { dmriddb { "dmrIdDbUrl", "dmrIdDbMode", "dmrIdDbRefresh", "dmrIdDbFilePath" }, nxdniddb { "nxdnIdDbUrl", "nxdnIdDbMode", "nxdnIdDbRefresh", "nxdnIdDbFilePath" }, ysftxrxdb { "ysfIdDbUrl", "ysfIdDbMode", "ysfIdDbRefresh", "ysfIdDbFilePath" }; - struct FILES { const std::string pid, json, white, black, interlink, terminal; } - files { "pidFilePath", "jsonFilePath", "whitelistFilePath", "blacklistFilePath", "interlinkFilePath", "g3TerminalFilePath" }; + struct FILES { const std::string pid, state, white, black, interlink, terminal; } + files { "pidFilePath", "stateFilePath", "whitelistFilePath", "blacklistFilePath", "interlinkFilePath", "g3TerminalFilePath" }; }; diff --git a/reflector/Makefile b/reflector/Makefile index 292bf49..ef6b2b6 100644 --- a/reflector/Makefile +++ b/reflector/Makefile @@ -48,7 +48,7 @@ $(INICHECK) : Configure.cpp CurlGet.o $(CXX) -DINICHECK $(CFLAGS) $< CurlGet.o -o $@ -lcurl $(DBUTIL) : Main.cpp $(DBUTILOBJS) - $(CXX) -DUTILITY $(CFLAGS) $< $(DBUTILOBJS) -o $@ -lcurl + $(CXX) -DUTILITY $(CFLAGS) $< $(DBUTILOBJS) -o $@ -pthread -lcurl %.o : %.cpp $(CXX) $(CFLAGS) -c $< -o $@ @@ -59,23 +59,15 @@ clean : -include $(DEPS) install : - ln -f -s $(shell pwd)/$(EXE).blacklist $(CFGDIR)/$(EXE).blacklist - ln -f -s $(shell pwd)/$(EXE).whitelist $(CFGDIR)/$(EXE).whitelist - ln -f -s $(shell pwd)/$(EXE).interlink $(CFGDIR)/$(EXE).interlink - ln -f -s $(shell pwd)/$(EXE).terminal $(CFGDIR)/$(EXE).terminal - cp -f ../systemd/$(EXE).service /etc/systemd/system/ - cp -f $(EXE) $(BINDIR) + $(CP) ../$(EXE).service /etc/systemd/system/ + $(CP) $(EXE) $(BINDIR) systemctl enable $(EXE).service systemctl daemon-reload systemctl start $(EXE) uninstall : - rm -f $(CFGDIR)/$(EXE).blacklist - rm -f $(CFGDIR)/$(EXE).whitelist - rm -f $(CFGDIR)/$(EXE).interlink - rm -f $(CFGDIR)/$(EXE).terminal systemctl stop $(EXE).service - rm -f $(CFGDIR)/dmrid.dat systemctl disable $(EXE).service - rm -f /etc/systemd/system/$(EXE).service + $(RM) /etc/systemd/system/$(EXE).service systemctl daemon-reload + $(RM) $(BINDIR)/$(EXE) diff --git a/reflector/example.ini b/reflector/example.ini index a8d69a2..cf9ab4b 100644 --- a/reflector/example.ini +++ b/reflector/example.ini @@ -113,7 +113,7 @@ RefreshMin = 191 ######### Other File locations [Files] PidPath = /var/run/urfd.pid -JsonPath = /var/log/urfd.json +ReflStatePath = /var/log/urfd.xml WhitelistPath = /usr/local/etc/urfd.whitelist BlacklistPath = /usr/local/etc/urfd.blacklist InterlinkPath = /usr/local/etc/urfd.interlink From 41200bf293c463c556ead258c809df994bc7cae8 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Tue, 21 Feb 2023 09:41:24 -0700 Subject: [PATCH 11/44] moved state def --- reflector/Reflector.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reflector/Reflector.cpp b/reflector/Reflector.cpp index 2bebf44..9686361 100644 --- a/reflector/Reflector.cpp +++ b/reflector/Reflector.cpp @@ -323,7 +323,7 @@ void CReflector::RouterThread(const char ThisModule) void CReflector::XmlReportThread() { - const std::string path(g_Conf.GetString(g_Keys.files.json)); + const std::string path(g_Conf.GetString(g_Keys.files.state)); while (keep_running) { // report to xml file From 908460b977cc8d262eadc18e8e7a8eb286bbf60d Mon Sep 17 00:00:00 2001 From: Tom Early Date: Tue, 21 Feb 2023 10:24:31 -0700 Subject: [PATCH 12/44] radmin tweeks --- radmin | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/radmin b/radmin index 1a136e3..13655a0 100755 --- a/radmin +++ b/radmin @@ -50,7 +50,7 @@ InstallReflector () { if [ ! -e urfd.interlink ]; then cp ../config/urfd.interlink . fi - if [[ "$g3support" == true ]] && [ ! -e urfd.terminal ]; then + if [ ! -e urfd.terminal ]; then cp ../config/urfd.terminal . fi sudo make install || read -p " to continue: " ans @@ -87,12 +87,18 @@ tcdserv='/etc/systemd/system/tcd.service' # default values, we only need a few tcaddress='none' -g3support=false -if [ -e reflector.cfg ]; then - source reflector.cfg +if [[ $# -eq 1 ]]; then + if [ -e $1 ]; then + echo $1 found + callsign=$(awk '$1 == "Callsign"{print $3}' $1) + tcaddress=$(awk '$1 == "Transcoder"{print $3}' $1) + else + echo "$1 not found" + exit 1 + fi else - echo 'No configuration file found...' + echo "Usage: ./radmin inifilename" exit 1 fi key='x' @@ -104,10 +110,10 @@ do if [ "$pcount" -gt 1 ]; then echo ps -aux | head -1 - ps -aux | grep -e urfd -e tcd | grep -v grep + ps -aux | grep -e urfd -e tcd | grep -v grep | grep -v radmin fi echo - echo " Reflector Administration, Version #211204" + echo " Reflector Administration, Version #230221" echo git status | head -1 echo From d3b24379bfd766c9a487c5c428501febf6771bb8 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Tue, 21 Feb 2023 10:30:42 -0700 Subject: [PATCH 13/44] change loc of .service file --- reflector/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reflector/Makefile b/reflector/Makefile index ef6b2b6..80ccceb 100644 --- a/reflector/Makefile +++ b/reflector/Makefile @@ -59,7 +59,7 @@ clean : -include $(DEPS) install : - $(CP) ../$(EXE).service /etc/systemd/system/ + $(CP) $(EXE).service /etc/systemd/system/ $(CP) $(EXE) $(BINDIR) systemctl enable $(EXE).service systemctl daemon-reload From 22ca3768520ab46fb391c0a95592c9e98efb080f Mon Sep 17 00:00:00 2001 From: Tom Early Date: Tue, 21 Feb 2023 10:43:05 -0700 Subject: [PATCH 14/44] there is no $(CP) --- reflector/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reflector/Makefile b/reflector/Makefile index 80ccceb..88a545d 100644 --- a/reflector/Makefile +++ b/reflector/Makefile @@ -59,8 +59,8 @@ clean : -include $(DEPS) install : - $(CP) $(EXE).service /etc/systemd/system/ - $(CP) $(EXE) $(BINDIR) + cp -f $(EXE).service /etc/systemd/system/ + cp -f $(EXE) $(BINDIR) systemctl enable $(EXE).service systemctl daemon-reload systemctl start $(EXE) From 939773f54b4bf69b8f224752b22fb8729511f46f Mon Sep 17 00:00:00 2001 From: Tom Early Date: Wed, 22 Feb 2023 03:08:44 -0700 Subject: [PATCH 15/44] still some problems with CPacketQueue locking --- reflector/CallsignList.cpp | 1 - reflector/CodecStream.cpp | 7 +++++-- reflector/Configure.cpp | 2 +- reflector/GateKeeper.cpp | 5 ----- reflector/LookupYsf.cpp | 2 +- reflector/Main.cpp | 3 ++- reflector/Makefile | 2 +- reflector/PacketStream.cpp | 13 +++++++------ reflector/PacketStream.h | 5 +++-- reflector/Protocol.h | 4 ++++ reflector/Reflector.cpp | 9 +++++++-- 11 files changed, 31 insertions(+), 22 deletions(-) diff --git a/reflector/CallsignList.cpp b/reflector/CallsignList.cpp index e1d4a0d..954bb5a 100644 --- a/reflector/CallsignList.cpp +++ b/reflector/CallsignList.cpp @@ -28,7 +28,6 @@ CCallsignList::CCallsignList() { - m_Filename = nullptr; memset(&m_LastModTime, 0, sizeof(time_t)); } diff --git a/reflector/CodecStream.cpp b/reflector/CodecStream.cpp index a1f641f..a6258e0 100644 --- a/reflector/CodecStream.cpp +++ b/reflector/CodecStream.cpp @@ -18,9 +18,9 @@ #include -#include "CodecStream.h" #include "DVFramePacket.h" -#include "Reflector.h" +#include "PacketStream.h" +#include "CodecStream.h" //////////////////////////////////////////////////////////////////////////////////////// // constructor @@ -78,6 +78,9 @@ void CCodecStream::ReportStats() bool CCodecStream::InitCodecStream(char module) { +#ifdef DEBUG + std::cout << "Initializing codec stream for module '" << module << "'" << std::endl; +#endif m_TCWriter.SetUp(REF2TC); std::string name(TC2REF); name.append(1, module); diff --git a/reflector/Configure.cpp b/reflector/Configure.cpp index 886dce4..c832377 100644 --- a/reflector/Configure.cpp +++ b/reflector/Configure.cpp @@ -571,7 +571,7 @@ bool CConfigure::ReadData(const std::string &path) } else { - data[g_Keys.ip.ipv4bind] = nullptr; + data[g_Keys.ip.ipv6bind] = nullptr; data[g_Keys.ip.ipv6address] = nullptr; } diff --git a/reflector/GateKeeper.cpp b/reflector/GateKeeper.cpp index 8949377..28065fc 100644 --- a/reflector/GateKeeper.cpp +++ b/reflector/GateKeeper.cpp @@ -20,11 +20,6 @@ #include "Timer.h" #include "Global.h" -//////////////////////////////////////////////////////////////////////////////////////// - -CGateKeeper g_GateKeeper; - - //////////////////////////////////////////////////////////////////////////////////////// // constructor diff --git a/reflector/LookupYsf.cpp b/reflector/LookupYsf.cpp index 6150ea7..e2fc5a3 100644 --- a/reflector/LookupYsf.cpp +++ b/reflector/LookupYsf.cpp @@ -70,7 +70,7 @@ void CLookupYsf::UpdateContent(std::stringstream &ss, Eaction action) } } if (Eaction::normal == action) - std::cout << "DMR Id database size now is " << m_map.size() << std::endl; + std::cout << "YSF frequency database size now is " << m_map.size() << std::endl; } void CLookupYsf::FindFrequencies(const CCallsign &cs, uint32_t &txfreq, uint32_t &rxfreq) diff --git a/reflector/Main.cpp b/reflector/Main.cpp index c6af52f..c309ed8 100644 --- a/reflector/Main.cpp +++ b/reflector/Main.cpp @@ -46,6 +46,7 @@ int main(int argc, char *argv[]) if (g_Conf.ReadData(argv[1])) return EXIT_FAILURE; + std::cout << "IPv4 binding address is '" << g_Conf.GetString(g_Keys.ip.ipv4bind) << "'" << std::endl; // remove pidfile const std::string pidpath(g_Conf.GetString(g_Keys.files.pid)); const std::string callsign(g_Conf.GetString(g_Keys.names.cs)); @@ -61,7 +62,7 @@ int main(int argc, char *argv[]) return EXIT_FAILURE; } - std::cout << "Reflector " << callsign << "started and listening" << std::endl; + std::cout << "Reflector " << callsign << " started and listening" << std::endl; // write new pid file std::ofstream ofs(pidpath, std::ofstream::out); diff --git a/reflector/Makefile b/reflector/Makefile index 88a545d..8bf07f7 100644 --- a/reflector/Makefile +++ b/reflector/Makefile @@ -27,7 +27,7 @@ DBUTIL = dbutil include configure.mk ifeq ($(debug), true) -CFLAGS = -ggdb3 -DDEBUG -W -Werror -c -std=c++11 -MMD -MD +CFLAGS = -ggdb3 -DDEBUG -W -Werror -std=c++11 -MMD -MD else CFLAGS = -W -Werror -std=c++11 -MMD -MD endif diff --git a/reflector/PacketStream.cpp b/reflector/PacketStream.cpp index 2f6ea53..7774020 100644 --- a/reflector/PacketStream.cpp +++ b/reflector/PacketStream.cpp @@ -22,7 +22,7 @@ //////////////////////////////////////////////////////////////////////////////////////// // constructor -CPacketStream::CPacketStream() +CPacketStream::CPacketStream(char module) : m_PSModule(module) { m_bOpen = false; m_uiStreamId = 0; @@ -31,12 +31,13 @@ CPacketStream::CPacketStream() m_CodecStream = nullptr; } -bool CPacketStream::InitPacketStream(bool is_transcoded) +bool CPacketStream::InitCodecStream() { - if (is_transcoded) - m_CodecStream = std::unique_ptr(new CCodecStream(this)); - - return nullptr == m_CodecStream; + m_CodecStream = std::unique_ptr(new CCodecStream(this)); + if (m_CodecStream) + return m_CodecStream->InitCodecStream(m_PSModule); + else + return true; } //////////////////////////////////////////////////////////////////////////////////////// diff --git a/reflector/PacketStream.h b/reflector/PacketStream.h index ac067b3..607d918 100644 --- a/reflector/PacketStream.h +++ b/reflector/PacketStream.h @@ -35,8 +35,8 @@ class CPacketStream : public CPacketQueue { public: - CPacketStream(); - bool InitPacketStream(bool is_transcoded); + CPacketStream(char module); + bool InitCodecStream(); // open / close bool OpenPacketStream(const CDvHeaderPacket &, std::shared_ptr); @@ -57,6 +57,7 @@ public: protected: // data + const char m_PSModule; bool m_bOpen; uint16_t m_uiStreamId; uint32_t m_uiPacketCntr; diff --git a/reflector/Protocol.h b/reflector/Protocol.h index 799ca76..201764a 100644 --- a/reflector/Protocol.h +++ b/reflector/Protocol.h @@ -114,6 +114,10 @@ protected: void Send(const CBuffer &buf, const CIp &Ip, uint16_t port) const; void Send(const char *buf, const CIp &Ip, uint16_t port) const; void Send(const SM17Frame &frame, const CIp &Ip) const; +#ifdef DEBUG + void Dump(const char *title, const uint8_t *data, int length); +#endif + // socket CUdpSocket m_Socket4; diff --git a/reflector/Reflector.cpp b/reflector/Reflector.cpp index 9686361..032984f 100644 --- a/reflector/Reflector.cpp +++ b/reflector/Reflector.cpp @@ -76,10 +76,15 @@ bool CReflector::Start(void) // start one thread per reflector module for (auto c : m_Modules) { - auto stream = std::make_shared(); + auto stream = std::make_shared(c); if (stream) { - stream->InitPacketStream(std::string::npos != tcmods.find(c)); + // if it's a transcoded module, then we need to initialize the codec stream + if (std::string::npos != tcmods.find(c)) + { + if (stream->InitCodecStream()) + return true; + } } else { From 10e49720406fa00b4c10281a0d18d87e31344dcb Mon Sep 17 00:00:00 2001 From: Tom Early Date: Wed, 22 Feb 2023 12:36:59 -0700 Subject: [PATCH 16/44] works (in idle) without crashing --- reflector/BMProtocol.cpp | 6 +-- reflector/CodecStream.cpp | 26 +++++------ reflector/CodecStream.h | 10 ++-- reflector/DCSProtocol.cpp | 6 +-- reflector/DExtraProtocol.cpp | 6 +-- reflector/DMRMMDVMProtocol.cpp | 7 +-- reflector/DMRPlusProtocol.cpp | 7 +-- reflector/DPlusProtocol.cpp | 6 +-- reflector/DVFramePacket.cpp | 8 ---- reflector/DVFramePacket.h | 3 -- reflector/DVHeaderPacket.cpp | 8 ---- reflector/DVHeaderPacket.h | 5 +- reflector/G3Protocol.cpp | 6 +-- reflector/M17Packet.cpp | 5 -- reflector/M17Packet.h | 1 - reflector/M17Protocol.cpp | 6 +-- reflector/NXDNProtocol.cpp | 6 +-- reflector/P25Protocol.cpp | 6 +-- reflector/Packet.h | 6 --- reflector/PacketQueue.h | 70 ---------------------------- reflector/PacketStream.cpp | 30 ++++-------- reflector/PacketStream.h | 10 +++- reflector/Protocol.cpp | 11 +---- reflector/Protocol.h | 10 ++-- reflector/Reflector.cpp | 84 ++++++++++------------------------ reflector/SafePacketQueue.h | 76 ++++++++++++++++++++++++++++++ reflector/URFProtocol.cpp | 6 +-- reflector/USRPProtocol.cpp | 6 +-- reflector/YSFProtocol.cpp | 6 +-- 29 files changed, 166 insertions(+), 277 deletions(-) delete mode 100644 reflector/PacketQueue.h create mode 100644 reflector/SafePacketQueue.h diff --git a/reflector/BMProtocol.cpp b/reflector/BMProtocol.cpp index d733977..0b6018b 100644 --- a/reflector/BMProtocol.cpp +++ b/reflector/BMProtocol.cpp @@ -190,11 +190,10 @@ void CBMProtocol::Task(void) void CBMProtocol::HandleQueue(void) { - m_Queue.Lock(); - while ( !m_Queue.empty() ) + while (! m_Queue.IsEmpty()) { // get the packet - auto packet = m_Queue.pop(); + auto packet = m_Queue.Pop(); // encode it CBuffer buffer; @@ -237,7 +236,6 @@ void CBMProtocol::HandleQueue(void) g_Refl.ReleaseClients(); } } - m_Queue.Unlock(); } //////////////////////////////////////////////////////////////////////////////////////// diff --git a/reflector/CodecStream.cpp b/reflector/CodecStream.cpp index a6258e0..914d72d 100644 --- a/reflector/CodecStream.cpp +++ b/reflector/CodecStream.cpp @@ -134,14 +134,14 @@ void CCodecStream::Task(void) m_RTSum += rt; m_RTCount++; - if ( m_LocalQueue.empty() ) + if ( m_LocalQueue.IsEmpty() ) { std::cout << "Unexpected transcoded packet received from transcoder" << std::endl; } else { // pop the original packet - auto Packet = m_LocalQueue.pop(); + auto Packet = m_LocalQueue.Pop(); auto Frame = (CDvFramePacket *)Packet.get(); // do things look okay? @@ -160,31 +160,27 @@ void CCodecStream::Task(void) } // and push it back to client - m_PacketStream->Lock(); - m_PacketStream->push(Packet); - m_PacketStream->Unlock(); + m_PacketStream->ReturnPacket(std::move(Packet)); } } // anything in our queue - while ( !empty() ) + auto Packet = m_Queue.Pop(); + while (Packet) { - // yes, pop it from queue - auto Packet = pop(); - // we need a CDvFramePacket pointer to access Frame stuff auto Frame = (CDvFramePacket *)Packet.get(); - // push to our local queue so it can wait for the transcoder - m_LocalQueue.push(Packet); + // push to our local queue where it can wait for the transcoder + m_LocalQueue.Push(std::move(Packet)); // update important stuff in Frame->m_TCPack for the transcoder - Frame->SetTCParams(m_uiTotalPackets++); + Frame->SetTCParams(m_uiTotalPackets++); // Frame still points to the packet // now send to transcoder - // this assume that thread pushing the Packet - // have verified that the CodecStream is connected - // and that the packet needs transcoding m_TCWriter.Send(Frame->GetCodecPacket()); + + // get the next packet + Packet = m_Queue.Pop(); } } diff --git a/reflector/CodecStream.h b/reflector/CodecStream.h index e4652c4..3b5f3b9 100644 --- a/reflector/CodecStream.h +++ b/reflector/CodecStream.h @@ -21,15 +21,16 @@ #include #include +#include "DVFramePacket.h" #include "UnixDgramSocket.h" -#include "PacketQueue.h" +#include "SafePacketQueue.h" //////////////////////////////////////////////////////////////////////////////////////// // class class CPacketStream; -class CCodecStream : public CPacketQueue +class CCodecStream { public: // constructor @@ -49,6 +50,9 @@ public: void Thread(void); void Task(void); + // pass-thru + void Push(std::unique_ptr p) { m_Queue.Push(std::move(p)); } + protected: // initialization // data @@ -63,7 +67,7 @@ protected: // associated packet stream CPacketStream *m_PacketStream; - CPacketQueue m_LocalQueue; + CSafePacketQueue> m_LocalQueue, m_Queue; // thread std::atomic keep_running; diff --git a/reflector/DCSProtocol.cpp b/reflector/DCSProtocol.cpp index 90eb419..0efecfe 100644 --- a/reflector/DCSProtocol.cpp +++ b/reflector/DCSProtocol.cpp @@ -218,11 +218,10 @@ void CDcsProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header, void CDcsProtocol::HandleQueue(void) { - m_Queue.Lock(); - while ( !m_Queue.empty() ) + while (! m_Queue.IsEmpty()) { // get the packet - auto packet = m_Queue.pop(); + auto packet = m_Queue.Pop(); // get our sender's id const auto module = packet->GetPacketModule(); @@ -269,7 +268,6 @@ void CDcsProtocol::HandleQueue(void) } } } - m_Queue.Unlock(); } //////////////////////////////////////////////////////////////////////////////////////// diff --git a/reflector/DExtraProtocol.cpp b/reflector/DExtraProtocol.cpp index 8a4b046..9e4c64b 100644 --- a/reflector/DExtraProtocol.cpp +++ b/reflector/DExtraProtocol.cpp @@ -193,11 +193,10 @@ void CDextraProtocol::Task(void) void CDextraProtocol::HandleQueue(void) { - m_Queue.Lock(); - while ( !m_Queue.empty() ) + while (! m_Queue.IsEmpty() ) { // get the packet - auto packet = m_Queue.pop(); + auto packet = m_Queue.Pop(); // encode it CBuffer buffer; @@ -223,7 +222,6 @@ void CDextraProtocol::HandleQueue(void) g_Refl.ReleaseClients(); } } - m_Queue.Unlock(); } //////////////////////////////////////////////////////////////////////////////////////// diff --git a/reflector/DMRMMDVMProtocol.cpp b/reflector/DMRMMDVMProtocol.cpp index 0515537..e50a943 100644 --- a/reflector/DMRMMDVMProtocol.cpp +++ b/reflector/DMRMMDVMProtocol.cpp @@ -346,12 +346,10 @@ void CDmrmmdvmProtocol::OnDvHeaderPacketIn(std::unique_ptr &Hea void CDmrmmdvmProtocol::HandleQueue(void) { - - m_Queue.Lock(); - while ( !m_Queue.empty() ) + while (! m_Queue.IsEmpty()) { // get the packet - auto packet = m_Queue.pop(); + auto packet = m_Queue.Pop(); // get our sender's id const auto mod = packet->GetPacketModule(); @@ -419,7 +417,6 @@ void CDmrmmdvmProtocol::HandleQueue(void) g_Refl.ReleaseClients(); } } - m_Queue.Unlock(); } //////////////////////////////////////////////////////////////////////////////////////// diff --git a/reflector/DMRPlusProtocol.cpp b/reflector/DMRPlusProtocol.cpp index 224635f..a625a74 100644 --- a/reflector/DMRPlusProtocol.cpp +++ b/reflector/DMRPlusProtocol.cpp @@ -218,12 +218,10 @@ void CDmrplusProtocol::OnDvHeaderPacketIn(std::unique_ptr &Head void CDmrplusProtocol::HandleQueue(void) { - - m_Queue.Lock(); - while ( !m_Queue.empty() ) + while (! m_Queue.IsEmpty()) { // get the packet - auto packet = m_Queue.pop(); + auto packet = m_Queue.Pop(); // get our sender's id const auto mod = packet->GetPacketModule(); @@ -285,7 +283,6 @@ void CDmrplusProtocol::HandleQueue(void) //buffer.DebugDump(g_Refl.m_DebugFile); } } - m_Queue.Unlock(); } void CDmrplusProtocol::SendBufferToClients(const CBuffer &buffer, uint8_t module) diff --git a/reflector/DPlusProtocol.cpp b/reflector/DPlusProtocol.cpp index bf00561..cd7ac07 100644 --- a/reflector/DPlusProtocol.cpp +++ b/reflector/DPlusProtocol.cpp @@ -228,11 +228,10 @@ void CDplusProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header void CDplusProtocol::HandleQueue(void) { - m_Queue.Lock(); - while ( !m_Queue.empty() ) + while (! m_Queue.IsEmpty()) { // get the packet - auto packet = m_Queue.pop(); + auto packet = m_Queue.Pop(); // get our sender's id const auto mod = packet->GetPacketModule(); @@ -292,7 +291,6 @@ void CDplusProtocol::HandleQueue(void) g_Refl.ReleaseClients(); } } - m_Queue.Unlock(); } void CDplusProtocol::SendDvHeader(CDvHeaderPacket *packet, CDplusClient *client) diff --git a/reflector/DVFramePacket.cpp b/reflector/DVFramePacket.cpp index 3bf7a94..6260270 100644 --- a/reflector/DVFramePacket.cpp +++ b/reflector/DVFramePacket.cpp @@ -213,14 +213,6 @@ void CDvFramePacket::EncodeInterlinkPacket(CBuffer &buf) const memcpy(data+off, m_TCPack.m17, 16); } -//////////////////////////////////////////////////////////////////////////////////////// -// virtual duplication - -std::unique_ptr CDvFramePacket::Duplicate(void) const -{ - return std::unique_ptr(new CDvFramePacket(*this)); -} - //////////////////////////////////////////////////////////////////////////////////////// // get diff --git a/reflector/DVFramePacket.h b/reflector/DVFramePacket.h index 10e5eed..bc91aed 100644 --- a/reflector/DVFramePacket.h +++ b/reflector/DVFramePacket.h @@ -62,9 +62,6 @@ public: static unsigned int GetNetworkSize(); void EncodeInterlinkPacket(CBuffer &buf) const; - // virtual duplication - std::unique_ptr Duplicate(void) const; - // identity bool IsDvHeader(void) const { return false; } bool IsDvFrame(void) const { return true; } diff --git a/reflector/DVHeaderPacket.cpp b/reflector/DVHeaderPacket.cpp index 0e09db0..356d2c6 100644 --- a/reflector/DVHeaderPacket.cpp +++ b/reflector/DVHeaderPacket.cpp @@ -165,14 +165,6 @@ CDvHeaderPacket::CDvHeaderPacket(const CM17Packet &m17) : CPacket(m17) m_csRPT1.SetCSModule('G'); } -//////////////////////////////////////////////////////////////////////////////////////// -// virtual duplication - -std::unique_ptr CDvHeaderPacket::Duplicate(void) const -{ - return std::unique_ptr(new CDvHeaderPacket(*this)); -} - //////////////////////////////////////////////////////////////////////////////////////// // conversion diff --git a/reflector/DVHeaderPacket.h b/reflector/DVHeaderPacket.h index 2a6a8cd..7ffd25c 100644 --- a/reflector/DVHeaderPacket.h +++ b/reflector/DVHeaderPacket.h @@ -20,7 +20,7 @@ #include "Callsign.h" #include "Packet.h" - + //////////////////////////////////////////////////////////////////////////////////////// // implementation details @@ -65,9 +65,6 @@ public: static unsigned int GetNetworkSize(); void EncodeInterlinkPacket(CBuffer &buf) const; - // virtual duplication - std::unique_ptr Duplicate(void) const; - // identity bool IsDvHeader(void) const { return true; } bool IsDvFrame(void) const { return false; } diff --git a/reflector/G3Protocol.cpp b/reflector/G3Protocol.cpp index c49ffc1..c075c14 100644 --- a/reflector/G3Protocol.cpp +++ b/reflector/G3Protocol.cpp @@ -442,14 +442,13 @@ void CG3Protocol::Task(void) void CG3Protocol::HandleQueue(void) { - m_Queue.Lock(); - while ( !m_Queue.empty() ) + while (! m_Queue.IsEmpty()) { // supress host checks m_LastKeepaliveTime.start(); // get the packet - auto packet = m_Queue.pop(); + auto packet = m_Queue.Pop(); // encode it CBuffer buffer; @@ -475,7 +474,6 @@ void CG3Protocol::HandleQueue(void) g_Refl.ReleaseClients(); } } - m_Queue.Unlock(); } //////////////////////////////////////////////////////////////////////////////////////// diff --git a/reflector/M17Packet.cpp b/reflector/M17Packet.cpp index 94e9510..7ed45a8 100644 --- a/reflector/M17Packet.cpp +++ b/reflector/M17Packet.cpp @@ -84,11 +84,6 @@ void CM17Packet::SetCRC(uint16_t crc) m17.crc = htons(crc); } -std::unique_ptr CM17Packet::Duplicate(void) const -{ - return std::unique_ptr(new CM17Packet(*this)); -} - bool CM17Packet::IsLastPacket() const { return ((0x8000u & ntohs(m17.framenumber)) == 0x8000u); diff --git a/reflector/M17Packet.h b/reflector/M17Packet.h index 2b0fb83..3d58ffd 100644 --- a/reflector/M17Packet.h +++ b/reflector/M17Packet.h @@ -69,7 +69,6 @@ public: uint16_t GetStreamId() const; uint16_t GetCRC() const; void SetCRC(uint16_t crc); - std::unique_ptr Duplicate(void) const; bool IsLastPacket() const; private: diff --git a/reflector/M17Protocol.cpp b/reflector/M17Protocol.cpp index fcbfce9..cbbfe74 100644 --- a/reflector/M17Protocol.cpp +++ b/reflector/M17Protocol.cpp @@ -221,11 +221,10 @@ void CM17Protocol::OnDvHeaderPacketIn(std::unique_ptr &Header, void CM17Protocol::HandleQueue(void) { - m_Queue.Lock(); - while ( !m_Queue.empty() ) + while (! m_Queue.IsEmpty()) { // get the packet - auto packet = m_Queue.pop(); + auto packet = m_Queue.Pop(); // get our sender's id const auto module = packet->GetPacketModule(); @@ -270,7 +269,6 @@ void CM17Protocol::HandleQueue(void) m_StreamsCache[module].m_iSeqCounter++; } } - m_Queue.Unlock(); } //////////////////////////////////////////////////////////////////////////////////////// diff --git a/reflector/NXDNProtocol.cpp b/reflector/NXDNProtocol.cpp index a46f488..9bb4434 100644 --- a/reflector/NXDNProtocol.cpp +++ b/reflector/NXDNProtocol.cpp @@ -246,11 +246,10 @@ void CNXDNProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header, void CNXDNProtocol::HandleQueue(void) { - m_Queue.Lock(); - while ( !m_Queue.empty() ) + while (! m_Queue.IsEmpty()) { // get the packet - auto packet = m_Queue.pop(); + auto packet = m_Queue.Pop(); // get our sender's id const auto mod = packet->GetPacketModule(); @@ -310,7 +309,6 @@ void CNXDNProtocol::HandleQueue(void) g_Refl.ReleaseClients(); } } - m_Queue.Unlock(); } //////////////////////////////////////////////////////////////////////////////////////// diff --git a/reflector/P25Protocol.cpp b/reflector/P25Protocol.cpp index f93da67..449e2e3 100644 --- a/reflector/P25Protocol.cpp +++ b/reflector/P25Protocol.cpp @@ -229,11 +229,10 @@ void CP25Protocol::OnDvHeaderPacketIn(std::unique_ptr &Header, void CP25Protocol::HandleQueue(void) { - m_Queue.Lock(); - while ( !m_Queue.empty() ) + while (! m_Queue.IsEmpty()) { // get the packet - auto packet = m_Queue.pop(); + auto packet = m_Queue.Pop(); // get our sender's id const auto module = packet->GetPacketModule(); @@ -276,7 +275,6 @@ void CP25Protocol::HandleQueue(void) } } } - m_Queue.Unlock(); } diff --git a/reflector/Packet.h b/reflector/Packet.h index c09e419..94e6ab5 100644 --- a/reflector/Packet.h +++ b/reflector/Packet.h @@ -40,12 +40,6 @@ public: CPacket(uint16_t sid, uint8_t dstarpid, uint8_t dmrpid, uint8_t dmrsubpid, uint8_t ysfpid, uint8_t ysfsubpid, uint8_t ysfsubpidmax, ECodecType, bool lastpacket); CPacket(const CM17Packet &); - // destructor - virtual ~CPacket() {} - - // virtual duplication - virtual std::unique_ptr Duplicate(void) const = 0; - // identity virtual bool IsDvHeader(void) const = 0; virtual bool IsDvFrame(void) const = 0; diff --git a/reflector/PacketQueue.h b/reflector/PacketQueue.h deleted file mode 100644 index e53881c..0000000 --- a/reflector/PacketQueue.h +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. - -// urfd -- The universal reflector -// Copyright © 2021 Thomas A. Early N7TAE -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -#pragma once - -#include -#include -#include "Packet.h" - -class CClient; - -class CPacketQueue -{ -public: - // destructor - virtual ~CPacketQueue() {} - - // lock - void Lock() - { - m_Mutex.lock(); - } - - void Unlock() - { - m_Mutex.unlock(); - } - - // pass thru - std::unique_ptr pop() - { - auto pack = std::move(queue.front()); - queue.pop(); - return std::move(pack); - } - - bool empty() const - { - return queue.empty(); - } - - void push(std::unique_ptr &packet) - { - queue.push(std::move(packet)); - } - -protected: - // status - bool m_bOpen; - uint16_t m_uiStreamId; - std::mutex m_Mutex; - - // the queue - std::queue> queue; -}; diff --git a/reflector/PacketStream.cpp b/reflector/PacketStream.cpp index 7774020..3e17cb5 100644 --- a/reflector/PacketStream.cpp +++ b/reflector/PacketStream.cpp @@ -83,32 +83,18 @@ void CPacketStream::Push(std::unique_ptr Packet) { Packet->UpdatePids(m_uiPacketCntr++); } - // transcoder avaliable ? - if ( m_CodecStream ) + // transcoder avaliable and is this a DvFramePacket? + if ( m_CodecStream && Packet->IsDvFrame()) { - // todo: verify no possibilty of double lock here - m_CodecStream->Lock(); - { - // transcoder ready & frame need transcoding ? - if (Packet->IsDvFrame()) - { - // yes, push packet to trancoder queue - // trancoder will push it after transcoding - // is completed - m_CodecStream->push(Packet); - } - else - { - // no, just bypass transcoder - push(Packet); - } - } - m_CodecStream->Unlock(); + // yes, push packet to trancoder queue + // trancoder will push it after transcoding + // is completed + m_CodecStream->Push(std::move(Packet)); } else { - // otherwise, push direct push - push(Packet); + // no, just bypass transcoder + Push(std::move(Packet)); } } diff --git a/reflector/PacketStream.h b/reflector/PacketStream.h index 607d918..e7b7581 100644 --- a/reflector/PacketStream.h +++ b/reflector/PacketStream.h @@ -18,7 +18,6 @@ #pragma once -#include "PacketQueue.h" #include "Timer.h" #include "DVHeaderPacket.h" #include "Client.h" @@ -32,7 +31,7 @@ //////////////////////////////////////////////////////////////////////////////////////// // class -class CPacketStream : public CPacketQueue +class CPacketStream { public: CPacketStream(char module); @@ -43,6 +42,7 @@ public: void ClosePacketStream(void); // push & pop + void ReturnPacket(std::unique_ptr p) { m_Queue.Push(std::move(p)); } void Push(std::unique_ptr packet); void Tickle(void) { m_LastPacketTime.start(); } @@ -55,8 +55,14 @@ public: const CCallsign &GetUserCallsign(void) const { return m_DvHeader.GetMyCallsign(); } char GetRpt2Module(void) const { return m_DvHeader.GetRpt2Module(); } + // pass-through + std::unique_ptr Pop() { return m_Queue.Pop(); } + std::unique_ptr PopWait() { return m_Queue.PopWait(); } + bool IsEmpty() { return m_Queue.IsEmpty(); } + protected: // data + CSafePacketQueue> m_Queue; const char m_PSModule; bool m_bOpen; uint16_t m_uiStreamId; diff --git a/reflector/Protocol.cpp b/reflector/Protocol.cpp index c5fa213..5998127 100644 --- a/reflector/Protocol.cpp +++ b/reflector/Protocol.cpp @@ -37,12 +37,10 @@ CProtocol::~CProtocol() Close(); // empty queue - m_Queue.Lock(); - while ( !m_Queue.empty() ) + while ( !m_Queue.IsEmpty() ) { - m_Queue.pop(); + m_Queue.Pop(); } - m_Queue.Unlock(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -138,9 +136,7 @@ void CProtocol::OnDvFramePacketIn(std::unique_ptr &Frame, const // set the packet module, the transcoder needs this Frame->SetPacketModule(stream->GetOwnerClient()->GetReflectorModule()); // and push - stream->Lock(); stream->Push(std::move(Frame)); - stream->Unlock(); } #ifdef DEBUG else @@ -176,18 +172,15 @@ void CProtocol::CheckStreamsTimeout(void) for ( auto it=m_Streams.begin(); it!=m_Streams.end(); ) { // time out ? - it->second->Lock(); if ( it->second->IsExpired() ) { // yes, close it - it->second->Unlock(); g_Refl.CloseStream(it->second); // and remove it from the m_Streams map it = m_Streams.erase(it); } else { - it->second->Unlock(); it++; } } diff --git a/reflector/Protocol.h b/reflector/Protocol.h index 201764a..415d98c 100644 --- a/reflector/Protocol.h +++ b/reflector/Protocol.h @@ -71,10 +71,6 @@ public: virtual bool Initialize(const char *type, const EProtocol ptype, const uint16_t port, const bool has_ipv4, const bool has_ipv6); virtual void Close(void); - // queue - CPacketQueue *GetQueue(void) { m_Queue.Lock(); return &m_Queue; } - void ReleaseQueue(void) { m_Queue.Unlock(); } - // get const CCallsign &GetReflectorCallsign(void)const { return m_ReflectorCallsign; } @@ -82,6 +78,9 @@ public: void Thread(void); virtual void Task(void) = 0; + // pass-through + void Push(std::shared_ptr p) { m_Queue.Push(p); } + protected: // stream helpers virtual void OnDvFramePacketIn(std::unique_ptr &, const CIp * = nullptr); @@ -118,7 +117,6 @@ protected: void Dump(const char *title, const uint8_t *data, int length); #endif - // socket CUdpSocket m_Socket4; CUdpSocket m_Socket6; @@ -127,7 +125,7 @@ protected: std::unordered_map> m_Streams; // queue - CPacketQueue m_Queue; + CSafePacketQueue> m_Queue; // thread std::atomic keep_running; diff --git a/reflector/Reflector.cpp b/reflector/Reflector.cpp index 032984f..4c235cb 100644 --- a/reflector/Reflector.cpp +++ b/reflector/Reflector.cpp @@ -188,7 +188,6 @@ std::shared_ptr CReflector::OpenStream(std::unique_ptrLock(); // is it available ? if ( stream->OpenPacketStream(*DvHeader, client) ) { @@ -211,7 +210,6 @@ std::shared_ptr CReflector::OpenStream(std::unique_ptrGetUserCallsign()); } - stream->Unlock(); return stream; } @@ -220,22 +218,14 @@ void CReflector::CloseStream(std::shared_ptr stream) if ( stream != nullptr ) { // wait queue is empty. this waits forever - bool bEmpty = false; - do + bool bEmpty = stream->IsEmpty(); + while (! bEmpty) { - stream->Lock(); - // do not use stream->IsEmpty() has this "may" never succeed - // and anyway, the DvLastFramPacket short-circuit the transcoder - // loop queues - bEmpty = stream->empty(); - stream->Unlock(); - if ( !bEmpty ) - std::this_thread::sleep_for(std::chrono::milliseconds(10)); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + bEmpty = stream->IsEmpty(); } - while (!bEmpty); GetClients(); // lock clients - stream->Lock(); // lock stream // get and check the master std::shared_ptrclient = stream->GetOwnerClient(); @@ -253,11 +243,6 @@ void CReflector::CloseStream(std::shared_ptr stream) // release clients ReleaseClients(); - // unlock before closing - // to avoid double lock in assiociated - // codecstream close/thread-join - stream->Unlock(); - // and stop the queue stream->ClosePacketStream(); } @@ -270,54 +255,31 @@ void CReflector::RouterThread(const char ThisModule) { while (keep_running) { - std::unique_ptr packet; auto streamIn = m_Stream[ThisModule]; - // any packet in our input queue ? - streamIn->Lock(); - if ( !streamIn->empty() ) - { - // get the packet - packet = streamIn->pop(); - } - else - { - packet = nullptr; - } - streamIn->Unlock(); - // route it - if ( packet != nullptr ) - { - // set origin - packet->SetPacketModule(ThisModule); + // convert the incoming packet to a shared_ptr + // wait until s + std::shared_ptr packet = std::move(streamIn->PopWait()); - // iterate on all protocols - m_Protocols.Lock(); - for ( auto it=m_Protocols.begin(); it!=m_Protocols.end(); it++ ) + // set origin + packet->SetPacketModule(ThisModule); + + // iterate on all protocols + m_Protocols.Lock(); + for ( auto it=m_Protocols.begin(); it!=m_Protocols.end(); it++ ) + { + // if packet is header, update RPT2 according to protocol + if ( packet->IsDvHeader() ) { - // duplicate packet - auto packetClone = packet->Duplicate(); - - // if packet is header, update RPT2 according to protocol - if ( packetClone->IsDvHeader() ) - { - // get our callsign - CCallsign csRPT = (*it)->GetReflectorCallsign(); - csRPT.SetCSModule(ThisModule); - (dynamic_cast(packetClone.get()))->SetRpt2Callsign(csRPT); - } - - // and push it - CPacketQueue *queue = (*it)->GetQueue(); - queue->push(packetClone); - (*it)->ReleaseQueue(); + // get our callsign + CCallsign csRPT = (*it)->GetReflectorCallsign(); + csRPT.SetCSModule(ThisModule); + (dynamic_cast(packet.get()))->SetRpt2Callsign(csRPT); } - m_Protocols.Unlock(); - } - else - { - std::this_thread::sleep_for(std::chrono::milliseconds(10)); + + (*it)->Push(packet); } + m_Protocols.Unlock(); } } diff --git a/reflector/SafePacketQueue.h b/reflector/SafePacketQueue.h new file mode 100644 index 0000000..f2a89bb --- /dev/null +++ b/reflector/SafePacketQueue.h @@ -0,0 +1,76 @@ +// urfd -- The universal reflector +// Copyright © 2023 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 + +// A threadsafe-queue. +template +class CSafePacketQueue +{ +public: + CSafePacketQueue(void) : q() , m() , c() {} + + ~CSafePacketQueue(void) {} + + void Push(T t) + { + std::lock_guard lock(m); + q.push(std::move(t)); + c.notify_one(); + } + + T Pop(void) + { + std::lock_guard lock(m); + if (q.empty()) + return nullptr; + else + { + T val = std::move(q.front()); + q.pop(); + return val; + } + } + + // If the queue is empty, wait till a element is avaiable. + T PopWait(void) + { + std::unique_lock lock(m); + while(q.empty()) + { + // release lock as long as the wait and reaquire it afterwards. + c.wait(lock); + } + T val = std::move(q.front()); + q.pop(); + return val; + } + + bool IsEmpty(void) + { + std::unique_lock lock(m); + return q.empty(); + } + +private: + std::queue q; + mutable std::mutex m; + std::condition_variable c; +}; diff --git a/reflector/URFProtocol.cpp b/reflector/URFProtocol.cpp index ce7cbaf..c9d4f12 100644 --- a/reflector/URFProtocol.cpp +++ b/reflector/URFProtocol.cpp @@ -200,11 +200,10 @@ void CURFProtocol::Task(void) void CURFProtocol::HandleQueue(void) { - m_Queue.Lock(); - while ( !m_Queue.empty() ) + while (! m_Queue.IsEmpty()) { // get the packet - auto packet = m_Queue.pop(); + auto packet = m_Queue.Pop(); // check if origin of packet is local // if not, do not stream it out as it will cause @@ -236,7 +235,6 @@ void CURFProtocol::HandleQueue(void) } } } - m_Queue.Unlock(); } //////////////////////////////////////////////////////////////////////////////////////// diff --git a/reflector/USRPProtocol.cpp b/reflector/USRPProtocol.cpp index 0c6c794..4a17ea9 100644 --- a/reflector/USRPProtocol.cpp +++ b/reflector/USRPProtocol.cpp @@ -223,11 +223,10 @@ void CUSRPProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header, void CUSRPProtocol::HandleQueue(void) { - m_Queue.Lock(); - while ( !m_Queue.empty() ) + while (! m_Queue.IsEmpty()) { // get the packet - auto packet = m_Queue.pop(); + auto packet = m_Queue.Pop(); // get our sender's id const auto module = packet->GetPacketModule(); @@ -266,7 +265,6 @@ void CUSRPProtocol::HandleQueue(void) g_Refl.ReleaseClients(); } } - m_Queue.Unlock(); } diff --git a/reflector/YSFProtocol.cpp b/reflector/YSFProtocol.cpp index 68fcfe9..20190e0 100644 --- a/reflector/YSFProtocol.cpp +++ b/reflector/YSFProtocol.cpp @@ -304,11 +304,10 @@ void CYsfProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header, void CYsfProtocol::HandleQueue(void) { - m_Queue.Lock(); - while ( !m_Queue.empty() ) + while (! m_Queue.IsEmpty()) { // get the packet - auto packet = m_Queue.pop(); + auto packet = m_Queue.Pop(); // get our sender's id const auto mod = packet->GetPacketModule(); @@ -369,7 +368,6 @@ void CYsfProtocol::HandleQueue(void) g_Refl.ReleaseClients(); } } - m_Queue.Unlock(); } //////////////////////////////////////////////////////////////////////////////////////// From a0123ceca90c55228de397328e171c4a41446721 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Thu, 23 Feb 2023 11:08:54 -0700 Subject: [PATCH 17/44] a few more msgs --- reflector/CodecStream.cpp | 6 +++--- reflector/PacketStream.cpp | 3 +++ reflector/Reflector.cpp | 22 +++++++++++++++------- reflector/SafePacketQueue.h | 11 +++++++++-- 4 files changed, 30 insertions(+), 12 deletions(-) diff --git a/reflector/CodecStream.cpp b/reflector/CodecStream.cpp index 914d72d..0c30791 100644 --- a/reflector/CodecStream.cpp +++ b/reflector/CodecStream.cpp @@ -78,14 +78,14 @@ void CCodecStream::ReportStats() bool CCodecStream::InitCodecStream(char module) { -#ifdef DEBUG - std::cout << "Initializing codec stream for module '" << module << "'" << std::endl; -#endif m_TCWriter.SetUp(REF2TC); std::string name(TC2REF); name.append(1, module); if (m_TCReader.Open(name.c_str())) return true; +#ifdef DEBUG + std::cout << "Initialized unix socket " << name << std::endl; +#endif keep_running = true; try { diff --git a/reflector/PacketStream.cpp b/reflector/PacketStream.cpp index 3e17cb5..7e2043f 100644 --- a/reflector/PacketStream.cpp +++ b/reflector/PacketStream.cpp @@ -37,7 +37,10 @@ bool CPacketStream::InitCodecStream() if (m_CodecStream) return m_CodecStream->InitCodecStream(m_PSModule); else + { + std::cerr << "Could not create a CCodecStream for module '" << m_PSModule << "'" << std::endl; return true; + } } //////////////////////////////////////////////////////////////////////////////////////// diff --git a/reflector/Reflector.cpp b/reflector/Reflector.cpp index 4c235cb..23637a1 100644 --- a/reflector/Reflector.cpp +++ b/reflector/Reflector.cpp @@ -85,9 +85,11 @@ bool CReflector::Start(void) if (stream->InitCodecStream()) return true; } + m_Stream[c] = stream; } else { + std::cerr << "Could not make a CPacketStream for module '" << c << "'" << std::endl; return true; } try @@ -253,14 +255,19 @@ void CReflector::CloseStream(std::shared_ptr stream) void CReflector::RouterThread(const char ThisModule) { + auto pitem = m_Stream.find(ThisModule); + if (m_Stream.end() == pitem) + { + std::cerr << "Module '" << ThisModule << " CPacketStream doesn't exist! aborting RouterThread()" << std::endl; + return; + } + const auto streamIn = pitem->second; while (keep_running) { - auto streamIn = m_Stream[ThisModule]; - + // wait until something shows up + auto uptmp = streamIn->PopWait(); // convert the incoming packet to a shared_ptr - // wait until s - std::shared_ptr packet = std::move(streamIn->PopWait()); - + std::shared_ptr packet = std::move(uptmp); // set origin packet->SetPacketModule(ThisModule); @@ -276,8 +283,9 @@ void CReflector::RouterThread(const char ThisModule) csRPT.SetCSModule(ThisModule); (dynamic_cast(packet.get()))->SetRpt2Callsign(csRPT); } - - (*it)->Push(packet); + // make a copy! after the Push(tmp), tmp will be nullptr! + auto tmp = packet; + (*it)->Push(tmp); } m_Protocols.Unlock(); } diff --git a/reflector/SafePacketQueue.h b/reflector/SafePacketQueue.h index f2a89bb..fd51b40 100644 --- a/reflector/SafePacketQueue.h +++ b/reflector/SafePacketQueue.h @@ -20,7 +20,14 @@ #include #include -// A threadsafe-queue. +/************************************************************ + * THIS IS IMPORTANT + * This template is primarly designed for std::unique_ptr! + * If you are going to use it for std::shared_ptr, then + * please consider that when you Push(), what you pushed + * from will be nullptr after the Push()! +\************************************************************/ + template class CSafePacketQueue { @@ -49,7 +56,7 @@ public: } } - // If the queue is empty, wait till a element is avaiable. + // If the queue is empty, wait until an element is avaiable. T PopWait(void) { std::unique_lock lock(m); From e52911700655f63f0542c8fcd308e6b59d5354b1 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Thu, 23 Feb 2023 12:20:31 -0700 Subject: [PATCH 18/44] fixed recursion --- reflector/PacketStream.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reflector/PacketStream.cpp b/reflector/PacketStream.cpp index 7e2043f..18c3d33 100644 --- a/reflector/PacketStream.cpp +++ b/reflector/PacketStream.cpp @@ -97,7 +97,7 @@ void CPacketStream::Push(std::unique_ptr Packet) else { // no, just bypass transcoder - Push(std::move(Packet)); + m_Queue.Push(std::move(Packet)); } } From a483b9086b5f8fb4eca3007f8e3e2e90a935c40e Mon Sep 17 00:00:00 2001 From: Tom Early Date: Thu, 23 Feb 2023 14:22:12 -0700 Subject: [PATCH 19/44] tracing some problems --- reflector/CodecStream.cpp | 40 +++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/reflector/CodecStream.cpp b/reflector/CodecStream.cpp index 0c30791..70e6b39 100644 --- a/reflector/CodecStream.cpp +++ b/reflector/CodecStream.cpp @@ -30,19 +30,6 @@ CCodecStream::CCodecStream(CPacketStream *PacketStream) m_PacketStream = PacketStream; } -void CCodecStream::ResetStats(uint16_t streamid, ECodecType type) -{ - keep_running = true; - m_uiStreamId = streamid; - m_uiPid = 0; - m_eCodecIn = type; - m_RTMin = -1; - m_RTMax = -1; - m_RTSum = 0; - m_RTCount = 0; - m_uiTotalPackets = 0; -} - //////////////////////////////////////////////////////////////////////////////////////// // destructor @@ -58,6 +45,19 @@ CCodecStream::~CCodecStream() m_TCReader.Close(); } +void CCodecStream::ResetStats(uint16_t streamid, ECodecType type) +{ + keep_running = true; + m_uiStreamId = streamid; + m_uiPid = 0; + m_eCodecIn = type; + m_RTMin = -1; + m_RTMax = -1; + m_RTSum = 0; + m_RTCount = 0; + m_uiTotalPackets = 0; +} + void CCodecStream::ReportStats() { // display stats @@ -133,6 +133,10 @@ void CCodecStream::Task(void) } m_RTSum += rt; m_RTCount++; +#ifdef DEBUG + if (0 == m_RTCount % 50) + ReportStats(); +#endif if ( m_LocalQueue.IsEmpty() ) { @@ -171,16 +175,16 @@ void CCodecStream::Task(void) // we need a CDvFramePacket pointer to access Frame stuff auto Frame = (CDvFramePacket *)Packet.get(); - // push to our local queue where it can wait for the transcoder - m_LocalQueue.Push(std::move(Packet)); - // update important stuff in Frame->m_TCPack for the transcoder - Frame->SetTCParams(m_uiTotalPackets++); // Frame still points to the packet + Frame->SetTCParams(m_uiTotalPackets++); // now send to transcoder m_TCWriter.Send(Frame->GetCodecPacket()); - // get the next packet + // push to our local queue where it can wait for the transcoder + m_LocalQueue.Push(std::move(Packet)); + + // get the next packet, if there is one Packet = m_Queue.Pop(); } } From 864d834ddba9b6213d4f9b4008fa07d2038b39e0 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Thu, 23 Feb 2023 14:41:40 -0700 Subject: [PATCH 20/44] fixed stat reset problem --- reflector/PacketStream.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reflector/PacketStream.cpp b/reflector/PacketStream.cpp index 18c3d33..a81c90e 100644 --- a/reflector/PacketStream.cpp +++ b/reflector/PacketStream.cpp @@ -58,10 +58,10 @@ bool CPacketStream::OpenPacketStream(const CDvHeaderPacket &DvHeader, std::share m_DvHeader = DvHeader; m_OwnerClient = client; m_LastPacketTime.start(); + if (m_CodecStream) + m_CodecStream->ResetStats(m_uiStreamId, m_DvHeader.GetCodecIn()); return true; } - if (m_CodecStream) - m_CodecStream->ResetStats(m_uiStreamId, m_DvHeader.GetCodecIn()); return false; } From 4890472c50a0d8bd0e0e198293278e099a980c75 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Fri, 24 Feb 2023 06:00:26 -0700 Subject: [PATCH 21/44] got rid of const_cast in CGateKeeper with a mutable mutex --- reflector/Buffer.cpp | 2 +- reflector/CallsignList.h | 10 +++++----- reflector/CodecStream.cpp | 4 ---- reflector/GateKeeper.cpp | 21 ++++++++++++--------- 4 files changed, 18 insertions(+), 19 deletions(-) diff --git a/reflector/Buffer.cpp b/reflector/Buffer.cpp index 8aa57a5..c99d290 100644 --- a/reflector/Buffer.cpp +++ b/reflector/Buffer.cpp @@ -176,7 +176,7 @@ CBuffer::operator const char *() const void CBuffer::DebugDump(std::ofstream &debugout) const { - // dump an hex line + // dump a hex line for ( unsigned int i = 0; i < m_data.size(); i++ ) { char sz[16]; diff --git a/reflector/CallsignList.h b/reflector/CallsignList.h index df1d153..3a221a1 100644 --- a/reflector/CallsignList.h +++ b/reflector/CallsignList.h @@ -33,8 +33,8 @@ public: CCallsignList(); // locks - void Lock(void) { m_Mutex.lock(); } - void Unlock(void) { m_Mutex.unlock(); } + void Lock(void) const { m_Mutex.lock(); } + void Unlock(void) const { m_Mutex.unlock(); } // file io virtual bool LoadFromFile(const std::string &str); @@ -60,8 +60,8 @@ protected: char *TrimWhiteSpaces(char *); // data - std::mutex m_Mutex; - std::string m_Filename; - time_t m_LastModTime; + mutable std::mutex m_Mutex; + std::string m_Filename; + time_t m_LastModTime; std::list m_Callsigns; }; diff --git a/reflector/CodecStream.cpp b/reflector/CodecStream.cpp index 70e6b39..6109fc0 100644 --- a/reflector/CodecStream.cpp +++ b/reflector/CodecStream.cpp @@ -133,10 +133,6 @@ void CCodecStream::Task(void) } m_RTSum += rt; m_RTCount++; -#ifdef DEBUG - if (0 == m_RTCount % 50) - ReportStats(); -#endif if ( m_LocalQueue.IsEmpty() ) { diff --git a/reflector/GateKeeper.cpp b/reflector/GateKeeper.cpp index 28065fc..f91db6e 100644 --- a/reflector/GateKeeper.cpp +++ b/reflector/GateKeeper.cpp @@ -204,17 +204,20 @@ bool CGateKeeper::IsNodeListedOk(const CCallsign &callsign, const CIp &ip, char { // first check if callsign is in white list // note if white list is empty, everybody is authorized - const_cast(m_NodeWhiteList).Lock(); + m_NodeWhiteList.Lock(); if ( !m_NodeWhiteList.empty() ) { ok = m_NodeWhiteList.IsCallsignListedWithWildcard(callsign, module); } - const_cast(m_NodeWhiteList).Unlock(); + m_NodeWhiteList.Unlock(); // then check if not blacklisted - const_cast(m_NodeBlackList).Lock(); - ok &= !m_NodeBlackList.IsCallsignListedWithWildcard(callsign); - const_cast(m_NodeBlackList).Unlock(); + if (ok) + { + m_NodeBlackList.Lock(); + ok = !m_NodeBlackList.IsCallsignListedWithWildcard(callsign); + m_NodeBlackList.Unlock(); + } } // done @@ -232,12 +235,12 @@ bool CGateKeeper::IsPeerListedOk(const CCallsign &callsign, const CIp &ip, char if ( ok ) { // look for an exact match in the list - const_cast(m_PeerList).Lock(); + m_PeerList.Lock(); if ( !m_PeerList.empty() ) { ok = m_PeerList.IsCallsignListed(callsign, module); } - const_cast(m_PeerList).Unlock(); + m_PeerList.Unlock(); } // done @@ -254,12 +257,12 @@ bool CGateKeeper::IsPeerListedOk(const CCallsign &callsign, const CIp &ip, char if ( ok ) { // look for an exact match in the list - const_cast(m_PeerList).Lock(); + m_PeerList.Lock(); if ( !m_PeerList.empty() ) { ok = m_PeerList.IsCallsignListed(callsign, modules); } - const_cast(m_PeerList).Unlock(); + m_PeerList.Unlock(); } // done From d40bb4f94b62e26fbf751fc33550373fa8741780 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Fri, 24 Feb 2023 09:52:30 -0700 Subject: [PATCH 22/44] fixed HasSuffix --- reflector/Callsign.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/reflector/Callsign.cpp b/reflector/Callsign.cpp index 328c5e1..940c334 100644 --- a/reflector/Callsign.cpp +++ b/reflector/Callsign.cpp @@ -168,8 +168,7 @@ bool CCallsign::IsValid(void) const // is an letter or space valid = valid && (IsLetter(m_Module) || IsSpace(m_Module)); - // dmrid is not tested, as it can be nullptr - // if station does is not dmr registered + // dmr and nxdn id is not tested, as it can be 0 if station is not registered // done return valid; @@ -177,7 +176,7 @@ bool CCallsign::IsValid(void) const bool CCallsign::HasSuffix(void) const { - return 0 == memcmp(m_Suffix.c, " ", 4); + return 0x20202020u != m_Suffix.u; } //////////////////////////////////////////////////////////////////////////////////////// From afa30d7c8ec8a3f2d19d50fbee1bd4c59727c0cf Mon Sep 17 00:00:00 2001 From: Tom Early Date: Fri, 24 Feb 2023 15:07:13 -0700 Subject: [PATCH 23/44] port is 16-bit --- reflector/Protocol.h | 3 ++- reflector/Reflector.cpp | 11 +++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/reflector/Protocol.h b/reflector/Protocol.h index 415d98c..8dafe08 100644 --- a/reflector/Protocol.h +++ b/reflector/Protocol.h @@ -73,6 +73,7 @@ public: // get const CCallsign &GetReflectorCallsign(void)const { return m_ReflectorCallsign; } + uint16_t GetPort(void) const { return m_Port; } // task void Thread(void); @@ -135,7 +136,7 @@ protected: CCallsign m_ReflectorCallsign; // data - uint8_t m_Port; + uint16_t m_Port; // debug CTimer m_DebugTimer; }; diff --git a/reflector/Reflector.cpp b/reflector/Reflector.cpp index 23637a1..0cc04f0 100644 --- a/reflector/Reflector.cpp +++ b/reflector/Reflector.cpp @@ -275,16 +275,19 @@ void CReflector::RouterThread(const char ThisModule) m_Protocols.Lock(); for ( auto it=m_Protocols.begin(); it!=m_Protocols.end(); it++ ) { + // make a copy! after the Push(tmp), tmp will be nullptr! + auto tmp = packet; + // if packet is header, update RPT2 according to protocol - if ( packet->IsDvHeader() ) + if ( tmp->IsDvHeader() ) { // get our callsign CCallsign csRPT = (*it)->GetReflectorCallsign(); csRPT.SetCSModule(ThisModule); - (dynamic_cast(packet.get()))->SetRpt2Callsign(csRPT); + std::cout << "For protocol on port " << (*it)->GetPort() << ", Rpt2Callsign is " << csRPT << std::endl; + (dynamic_cast(tmp.get()))->SetRpt2Callsign(csRPT); } - // make a copy! after the Push(tmp), tmp will be nullptr! - auto tmp = packet; + (*it)->Push(tmp); } m_Protocols.Unlock(); From 01596c9784c9a68895ef25c2f3a8b27d1131202e Mon Sep 17 00:00:00 2001 From: Tom Early Date: Fri, 24 Feb 2023 15:16:37 -0700 Subject: [PATCH 24/44] remove a msg --- reflector/Reflector.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/reflector/Reflector.cpp b/reflector/Reflector.cpp index 0cc04f0..256ffd4 100644 --- a/reflector/Reflector.cpp +++ b/reflector/Reflector.cpp @@ -284,7 +284,6 @@ void CReflector::RouterThread(const char ThisModule) // get our callsign CCallsign csRPT = (*it)->GetReflectorCallsign(); csRPT.SetCSModule(ThisModule); - std::cout << "For protocol on port " << (*it)->GetPort() << ", Rpt2Callsign is " << csRPT << std::endl; (dynamic_cast(tmp.get()))->SetRpt2Callsign(csRPT); } From 308bed4509c6dfae84c7dbd1e828e8e56c9d78e3 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Fri, 24 Feb 2023 15:34:13 -0700 Subject: [PATCH 25/44] Add another debug message --- reflector/DExtraProtocol.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/reflector/DExtraProtocol.cpp b/reflector/DExtraProtocol.cpp index 9e4c64b..f104690 100644 --- a/reflector/DExtraProtocol.cpp +++ b/reflector/DExtraProtocol.cpp @@ -211,6 +211,11 @@ void CDextraProtocol::HandleQueue(void) // is this client busy ? if ( !client->IsAMaster() && (client->GetReflectorModule() == packet->GetPacketModule()) ) { + if (packet->IsDvHeader()) + { + buffer.Dump("Header packet"); + std::cout << "Is going to " << client->GetCallsign() << " at " << client->GetIp() << std::endl; + } // no, send the packet int n = packet->IsDvHeader() ? 5 : 1; for ( int i = 0; i < n; i++ ) From cb56ec2245607a340454ca99c5437bcbd54f3760 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Fri, 24 Feb 2023 16:59:53 -0700 Subject: [PATCH 26/44] another msg --- reflector/Reflector.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/reflector/Reflector.cpp b/reflector/Reflector.cpp index 256ffd4..f3b9839 100644 --- a/reflector/Reflector.cpp +++ b/reflector/Reflector.cpp @@ -284,7 +284,11 @@ void CReflector::RouterThread(const char ThisModule) // get our callsign CCallsign csRPT = (*it)->GetReflectorCallsign(); csRPT.SetCSModule(ThisModule); - (dynamic_cast(tmp.get()))->SetRpt2Callsign(csRPT); + //(dynamic_cast(tmp.get()))->SetRpt2Callsign(csRPT); + auto x = dynamic_cast(tmp.get()); + x->SetRpt2Callsign(csRPT); + if ((*it)->GetPort() == 30001) + std::cout << (*it)->GetReflectorCallsign() << ": " << csRPT << " == " << x->GetRpt2Callsign() << std::endl; } (*it)->Push(tmp); From fd9ddd718185573a589d0818675b32b62e64835a Mon Sep 17 00:00:00 2001 From: Tom Early Date: Sat, 25 Feb 2023 06:22:47 -0700 Subject: [PATCH 27/44] packets need a copy function --- reflector/DExtraProtocol.cpp | 5 ----- reflector/DVFramePacket.cpp | 5 +++++ reflector/DVFramePacket.h | 1 + reflector/DVHeaderPacket.cpp | 5 +++++ reflector/DVHeaderPacket.h | 1 + reflector/Packet.h | 1 + reflector/Protocol.h | 4 ++-- reflector/Reflector.cpp | 18 ++++++------------ 8 files changed, 21 insertions(+), 19 deletions(-) diff --git a/reflector/DExtraProtocol.cpp b/reflector/DExtraProtocol.cpp index f104690..9e4c64b 100644 --- a/reflector/DExtraProtocol.cpp +++ b/reflector/DExtraProtocol.cpp @@ -211,11 +211,6 @@ void CDextraProtocol::HandleQueue(void) // is this client busy ? if ( !client->IsAMaster() && (client->GetReflectorModule() == packet->GetPacketModule()) ) { - if (packet->IsDvHeader()) - { - buffer.Dump("Header packet"); - std::cout << "Is going to " << client->GetCallsign() << " at " << client->GetIp() << std::endl; - } // no, send the packet int n = packet->IsDvHeader() ? 5 : 1; for ( int i = 0; i < n; i++ ) diff --git a/reflector/DVFramePacket.cpp b/reflector/DVFramePacket.cpp index 6260270..eaab0a5 100644 --- a/reflector/DVFramePacket.cpp +++ b/reflector/DVFramePacket.cpp @@ -167,6 +167,11 @@ CDvFramePacket::CDvFramePacket(const int16_t *usrp, uint16_t streamid, bool isla m_TCPack.codec_in = ECodecType::usrp; } +std::unique_ptr CDvFramePacket::Copy(void) +{ + return std::unique_ptr(new CDvFramePacket(*this)); +} + // Network unsigned int CDvFramePacket::GetNetworkSize() { diff --git a/reflector/DVFramePacket.h b/reflector/DVFramePacket.h index bc91aed..21bbcd8 100644 --- a/reflector/DVFramePacket.h +++ b/reflector/DVFramePacket.h @@ -63,6 +63,7 @@ public: void EncodeInterlinkPacket(CBuffer &buf) const; // identity + std::unique_ptr Copy(void); bool IsDvHeader(void) const { return false; } bool IsDvFrame(void) const { return true; } diff --git a/reflector/DVHeaderPacket.cpp b/reflector/DVHeaderPacket.cpp index 356d2c6..bc23760 100644 --- a/reflector/DVHeaderPacket.cpp +++ b/reflector/DVHeaderPacket.cpp @@ -165,6 +165,11 @@ CDvHeaderPacket::CDvHeaderPacket(const CM17Packet &m17) : CPacket(m17) m_csRPT1.SetCSModule('G'); } +std::unique_ptr CDvHeaderPacket::Copy(void) +{ + return std::unique_ptr(new CDvHeaderPacket(*this)); +} + //////////////////////////////////////////////////////////////////////////////////////// // conversion diff --git a/reflector/DVHeaderPacket.h b/reflector/DVHeaderPacket.h index 7ffd25c..7bbfd29 100644 --- a/reflector/DVHeaderPacket.h +++ b/reflector/DVHeaderPacket.h @@ -66,6 +66,7 @@ public: void EncodeInterlinkPacket(CBuffer &buf) const; // identity + std::unique_ptr Copy(void); bool IsDvHeader(void) const { return true; } bool IsDvFrame(void) const { return false; } diff --git a/reflector/Packet.h b/reflector/Packet.h index 94e6ab5..0ee7012 100644 --- a/reflector/Packet.h +++ b/reflector/Packet.h @@ -41,6 +41,7 @@ public: CPacket(const CM17Packet &); // identity + virtual std::unique_ptr Copy(void) = 0; virtual bool IsDvHeader(void) const = 0; virtual bool IsDvFrame(void) const = 0; bool IsLastPacket(void) const { return m_bLastPacket; } diff --git a/reflector/Protocol.h b/reflector/Protocol.h index 8dafe08..678b533 100644 --- a/reflector/Protocol.h +++ b/reflector/Protocol.h @@ -80,7 +80,7 @@ public: virtual void Task(void) = 0; // pass-through - void Push(std::shared_ptr p) { m_Queue.Push(p); } + void Push(std::unique_ptr p) { m_Queue.Push(std::move(p)); } protected: // stream helpers @@ -126,7 +126,7 @@ protected: std::unordered_map> m_Streams; // queue - CSafePacketQueue> m_Queue; + CSafePacketQueue> m_Queue; // thread std::atomic keep_running; diff --git a/reflector/Reflector.cpp b/reflector/Reflector.cpp index f3b9839..39cf577 100644 --- a/reflector/Reflector.cpp +++ b/reflector/Reflector.cpp @@ -265,10 +265,8 @@ void CReflector::RouterThread(const char ThisModule) while (keep_running) { // wait until something shows up - auto uptmp = streamIn->PopWait(); - // convert the incoming packet to a shared_ptr - std::shared_ptr packet = std::move(uptmp); - // set origin + auto packet = streamIn->PopWait(); + packet->SetPacketModule(ThisModule); // iterate on all protocols @@ -276,22 +274,18 @@ void CReflector::RouterThread(const char ThisModule) for ( auto it=m_Protocols.begin(); it!=m_Protocols.end(); it++ ) { // make a copy! after the Push(tmp), tmp will be nullptr! - auto tmp = packet; + auto copy = packet->Copy(); // if packet is header, update RPT2 according to protocol - if ( tmp->IsDvHeader() ) + if ( copy->IsDvHeader() ) { // get our callsign CCallsign csRPT = (*it)->GetReflectorCallsign(); csRPT.SetCSModule(ThisModule); - //(dynamic_cast(tmp.get()))->SetRpt2Callsign(csRPT); - auto x = dynamic_cast(tmp.get()); - x->SetRpt2Callsign(csRPT); - if ((*it)->GetPort() == 30001) - std::cout << (*it)->GetReflectorCallsign() << ": " << csRPT << " == " << x->GetRpt2Callsign() << std::endl; + (dynamic_cast(copy.get()))->SetRpt2Callsign(csRPT); } - (*it)->Push(tmp); + (*it)->Push(std::move(copy)); } m_Protocols.Unlock(); } From cd30b7f771f2a47f940369fba9df98ff792fa8d6 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Mon, 27 Feb 2023 07:51:53 -0700 Subject: [PATCH 28/44] USRP redo --- README.md | 2 +- reflector/Configure.cpp | 159 ++++++++++++++++++++++++++++--------- reflector/Configure.h | 4 +- reflector/JsonKeys.h | 22 ++++- reflector/Main.cpp | 2 +- reflector/Protocols.cpp | 25 ++++-- reflector/Reflector.cpp | 6 +- reflector/USRPProtocol.cpp | 57 +++++++------ reflector/USRPProtocol.h | 19 ++--- reflector/example.ini | 38 +++++---- 10 files changed, 221 insertions(+), 113 deletions(-) diff --git a/README.md b/README.md index 3957bbb..51aefc9 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ The rest of this README is unchanged from the original. ## Introduction -This will build a new kind of digital voice reflector. Based on N7TAE's [new-xlxd](https://github.com/n7tae/new-xlxd), which, in turn, is based on the first multi-protocol reflector, [xlxd](https://github.com/LX3JL/xlxd), **urfd** supports all protocols of it's predecessors, as well as both M17 protocols, **voice-only** and **voice+data**! A key part of this is the hybrid transcoder, [tcd](https://github.com/n7tae/tcd), which is in a seperate repository. URFd is not compatible with either new-xlxd or xlxd. You can't interlink urfd with xlxd. This reflector can be built without a transcoder, but clients will only hear other clients using the same protocol. Please note that currently, urfd only supports the tcd transcoder when run locally. For best performance, urfd and tcd uses UNIX DGRAM sockets for interprocess communications. These kernal-base sockets are signifantly faster than conventional UDP/IP sockets. It should be noted that tcd supports DVSI-3003 nad DVSI-3000 devices, which it uses for AMBE vocoding. +This will build a new kind of digital voice reflector. Based on N7TAE's [new-xlxd](https://github.com/n7tae/new-xlxd), which, in turn, is based on the first multi-protocol reflector, [xlxd](https://github.com/LX3JL/xlxd), **urfd** supports all protocols of it's predecessors, as well as both M17 protocols, **voice-only** and **voice+data**! A key part of this is the hybrid transcoder, [tcd](https://github.com/n7tae/tcd), which is in a seperate repository. URFd is not compatible with either new-xlxd or xlxd. You can't interlink urfd with xlxd. This reflector can be built without a transcoder, but clients will only hear other clients using the same protocol. Please note that currently, urfd only supports the tcd transcoder when run locally. For best performance, urfd and tcd uses UNIX DGRAM sockets for interprocess communications. These kernel-base sockets are signifantly faster than conventional UDP/IP sockets. It should be noted that tcd supports DVSI-3003 nad DVSI-3000 devices, which it uses for AMBE vocoding. This build support *dual-stack* operation, so the server on which it's running, must have both an IPv4 and IPv6 routable address if you are going to configure a dual-stack reflector. URF can support out-going DExtra links, by adding a new DExtra Peer type *and* it has many changes designed to increase reliability and stability. diff --git a/reflector/Configure.cpp b/reflector/Configure.cpp index c832377..b13cf12 100644 --- a/reflector/Configure.cpp +++ b/reflector/Configure.cpp @@ -16,6 +16,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include #include #include #include @@ -34,10 +35,8 @@ #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" @@ -46,8 +45,10 @@ #define JDMRIDDB "DMR ID DB" #define JDMRPLUS "DMRPlus" #define JDPLUS "DPlus" +#define JENABLE "Enable" #define JFILES "Files" #define JFILEPATH "FilePath" +#define JG3 "G3" #define JG3TERMINALPATH "G3TerminalPath" #define JINTERLINKPATH "InterlinkPath" #define JIPADDRESSES "IpAddresses" @@ -58,6 +59,7 @@ #define JM17 "M17" #define JMMDVM "MMDVM" #define JMODE "Mode" +#define JMODULE "Module" #define JMODULES "Modules" #define JNAMES "Names" #define JNXDNIDDB "NXDN ID DB" @@ -178,6 +180,8 @@ bool CConfigure::ReadData(const std::string &path) section = ESection::dplus; else if (0 == hname.compare(JDEXTRA)) section = ESection::dextra; + else if (0 == hname.compare(JG3)) + section = ESection::g3; else if (0 == hname.compare(JDMRPLUS)) section = ESection::dmrplus; else if (0 == hname.compare(JMMDVM)) @@ -241,7 +245,7 @@ bool CConfigure::ReadData(const std::string &path) { case ESection::names: if (0 == key.compare(JCALLSIGN)) - data[g_Keys.names.cs] = value; + data[g_Keys.names.callsign] = value; else if (0 == key.compare(JSYSOPEMAIL)) data[g_Keys.names.email] = value; else if (0 == key.compare(JCOUNTRY)) @@ -313,6 +317,8 @@ bool CConfigure::ReadData(const std::string &path) case ESection::bm: if (0 == key.compare(JPORT)) data[g_Keys.bm.port] = getUnsigned(value, "Brandmeister Port", 1024, 65535, 10002); + else if (0 == key.compare(JENABLE)) + data[g_Keys.bm.enable] = IS_TRUE(value[0]); else badParam(key); break; @@ -328,6 +334,12 @@ bool CConfigure::ReadData(const std::string &path) else badParam(key); break; + case ESection::g3: + if (0 == key.compare(JENABLE)) + data[g_Keys.g3.enable] = IS_TRUE(value[0]); + else + badParam(key); + break; case ESection::dmrplus: if (0 == key.compare(JPORT)) data[g_Keys.dmrplus.port] = getUnsigned(value, "DMRPlus Port", 1024, 65535, 8880); @@ -381,21 +393,16 @@ bool CConfigure::ReadData(const std::string &path) badParam(key); break; case ESection::usrp: - if (0 == key.compare(JPORT)) - data[g_Keys.usrp.port] = getUnsigned(value, "USRP Port", 1024, 65535, 34001); - else if (0 == key.compare(JAUTOLINKMODULE)) - setAutolink(JUSRP, g_Keys.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[g_Keys.usrp.defaultcallsign] = cs; - } - else if (0 == key.compare(JCLIENTSPATH)) - data[g_Keys.usrp.clientfilepath] = value; + if (0 == key.compare(JENABLE)) + data[g_Keys.usrp.enable] = IS_TRUE(value[0]); + else if (0 == key.compare(JPORT)) + data[g_Keys.usrp.port] = getUnsigned(value, "USRP Port", 1024, 65535, 32000); + else if (0 == key.compare(JMODULE)) + data[g_Keys.usrp.module] = value.substr(0, 1); + else if (0 == key.compare(JCALLSIGN)) + data[g_Keys.usrp.callsign] = value; + else if (0 == key.compare(JFILEPATH)) + data[g_Keys.usrp.filepath] = value; else badParam(key); break; @@ -478,13 +485,13 @@ bool CConfigure::ReadData(const std::string &path) ////////////////////////////// check the input // Names section - if (isDefined(ErrorLevel::fatal, JNAMES, JCALLSIGN, g_Keys.names.cs, rval)) + if (isDefined(ErrorLevel::fatal, JNAMES, JCALLSIGN, g_Keys.names.callsign, rval)) { - const auto cs = data[g_Keys.names.cs].get(); + const auto cs = data[g_Keys.names.callsign].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; + std::cerr << "ERROR: [" << JNAMES << ']' << JCALLSIGN << " '" << cs << "' is malformed" << std::endl; rval = true; } } @@ -586,7 +593,7 @@ bool CConfigure::ReadData(const std::string &path) // 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; + 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[g_Keys.modules.tcmodules]) @@ -626,29 +633,68 @@ bool CConfigure::ReadData(const std::string &path) } // "simple" protocols with only a Port - isDefined(ErrorLevel::fatal, JBRANDMEISTER, JPORT, g_Keys.bm.port, rval); isDefined(ErrorLevel::fatal, JDCS, JPORT, g_Keys.dcs.port, rval); isDefined(ErrorLevel::fatal, JDEXTRA, JPORT, g_Keys.dextra.port, rval); isDefined(ErrorLevel::fatal, JDMRPLUS, JPORT, g_Keys.dmrplus.port, rval); isDefined(ErrorLevel::fatal, JDPLUS, JPORT, g_Keys.dplus.port, rval); isDefined(ErrorLevel::fatal, JM17, JPORT, g_Keys.m17.port, rval); isDefined(ErrorLevel::fatal, JURF, JPORT, g_Keys.urf.port, rval); + + // BM + if (isDefined(ErrorLevel::fatal, JBRANDMEISTER, JENABLE, g_Keys.bm.enable, rval)) + { + if (GetBoolean(g_Keys.bm.enable)) + { + isDefined(ErrorLevel::fatal, JBRANDMEISTER, JPORT, g_Keys.bm.port, rval); + } + } + + // G3 + isDefined(ErrorLevel::fatal, JG3, JENABLE, g_Keys.g3.enable, rval); + // MMDVM isDefined(ErrorLevel::fatal, JMMDVM, JPORT, g_Keys.mmdvm.port, rval); isDefined(ErrorLevel::fatal, JMMDVM, JDEFAULTID, g_Keys.mmdvm.defaultid, rval); + // NXDN isDefined(ErrorLevel::fatal, JNXDN, JPORT, g_Keys.nxdn.port, rval); checkAutoLink(JNXDN, JAUTOLINKMODULE, g_Keys.nxdn.autolinkmod, rval); isDefined(ErrorLevel::fatal, JNXDN, JREFLECTORID, g_Keys.nxdn.reflectorid, rval); + // P25 isDefined(ErrorLevel::fatal, JP25, JPORT, g_Keys.p25.port, rval); checkAutoLink(JP25, JAUTOLINKMODULE, g_Keys.p25.autolinkmod, rval); isDefined(ErrorLevel::fatal, JP25, JREFLECTORID, g_Keys.p25.reflectorid, rval); + // USRP - isDefined(ErrorLevel::fatal, JUSRP, JPORT, g_Keys.usrp.port, rval); - checkAutoLink(JUSRP, JAUTOLINKMODULE, g_Keys.usrp.autolinkmod, rval); - isDefined(ErrorLevel::fatal, JUSRP, JDEFAULTCALLSIGN, g_Keys.usrp.defaultcallsign, rval); - isDefined(ErrorLevel::fatal, JUSRP, JCLIENTSPATH, g_Keys.usrp.clientfilepath, rval); + if (isDefined(ErrorLevel::fatal, JUSRP, JENABLE, g_Keys.usrp.enable, rval)) + { + if (GetBoolean(g_Keys.usrp.enable)) + { + if (IsString(g_Keys.modules.tcmodules)) + { + if (isDefined(ErrorLevel::fatal, JUSRP, JMODULE, g_Keys.usrp.module, rval)) + { + if (std::string::npos == GetString(g_Keys.modules.tcmodules).find(GetString(g_Keys.usrp.module).at(0))) + { + std::cerr << "ERROR: [" << JUSRP << ']' << JMODULE << " is not a transcoded module" << std::endl; + rval = true; + } + } + isDefined(ErrorLevel::fatal, JUSRP, JPORT, g_Keys.usrp.port, rval); + isDefined(ErrorLevel::fatal, JUSRP, JCALLSIGN, g_Keys.usrp.callsign, rval); + //if (isDefined(ErrorLevel::fatal, JUSRP, JFILEPATH, g_Keys.usrp.filepath, rval)) + if (data.contains(g_Keys.usrp.filepath)) + checkFile(JUSRP, JFILEPATH, data[g_Keys.usrp.filepath]); + } + else + { + std::cerr << "ERROR: " << JUSRP << " requires a transoder" << std::endl; + rval = true; + } + } + } + // YSF isDefined(ErrorLevel::fatal, JYSF, JPORT, g_Keys.ysf.port, rval); checkAutoLink(JYSF, JAUTOLINKMODULE, g_Keys.ysf.autolinkmod, rval); @@ -657,6 +703,7 @@ bool CConfigure::ReadData(const std::string &path) isDefined(ErrorLevel::mild, JYSF, JREGISTRATIONID, g_Keys.ysf.ysfreflectordb.id, rval); isDefined(ErrorLevel::mild, JYSF, JREGISTRATIONNAME, g_Keys.ysf.ysfreflectordb.name, rval); isDefined(ErrorLevel::mild, JYSF, JREGISTRATIONDESCRIPTION, g_Keys.ysf.ysfreflectordb.description, rval); + // Databases std::list> dbs = { { JDMRIDDB, &g_Keys.dmriddb }, @@ -665,18 +712,36 @@ bool CConfigure::ReadData(const std::string &path) }; for ( auto &item : dbs ) { - isDefined(ErrorLevel::fatal, item.first, JURL, item.second->url, 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); + if (isDefined(ErrorLevel::fatal, item.first, JMODE, item.second->mode, rval)) + { + if (ERefreshType::file != GetRefreshType(item.second->mode)) + { + isDefined(ErrorLevel::fatal, item.first, JURL, item.second->url, rval); + isDefined(ErrorLevel::fatal, item.first, JREFRESHMIN, item.second->refreshmin, rval); + } + if (ERefreshType::http != GetRefreshType(item.second->mode)) + { + if (isDefined(ErrorLevel::fatal, item.first, JFILEPATH, item.second->filepath, rval)) + checkFile(item.first, JFILEPATH, data[item.second->filepath]); + } + } } + // Other files isDefined(ErrorLevel::fatal, JFILES, JPIDPATH, g_Keys.files.pid, rval); isDefined(ErrorLevel::fatal, JFILES, JREFLSTATEPATH, g_Keys.files.state, rval); - isDefined(ErrorLevel::fatal, JFILES, JWHITELISTPATH, g_Keys.files.white, rval); - isDefined(ErrorLevel::fatal, JFILES, JBLACKLISTPATH, g_Keys.files.black, rval); - isDefined(ErrorLevel::fatal, JFILES, JINTERLINKPATH, g_Keys.files.interlink, rval); - isDefined(ErrorLevel::fatal, JFILES, JG3TERMINALPATH, g_Keys.files.terminal, rval); + if (isDefined(ErrorLevel::fatal, JFILES, JWHITELISTPATH, g_Keys.files.white, rval)) + checkFile(JFILES, JWHITELISTPATH, data[g_Keys.files.white]); + if (isDefined(ErrorLevel::fatal, JFILES, JBLACKLISTPATH, g_Keys.files.black, rval)) + checkFile(JFILES, JBLACKLISTPATH, data[g_Keys.files.black]); + if (isDefined(ErrorLevel::fatal, JFILES, JINTERLINKPATH, g_Keys.files.interlink, rval)) + checkFile(JFILES, JINTERLINKPATH, data[g_Keys.files.interlink]); + if (data.contains(g_Keys.g3.enable) && GetBoolean(g_Keys.g3.enable)) + { + if (isDefined(ErrorLevel::fatal, JFILES, JG3TERMINALPATH, g_Keys.files.terminal, rval)) + checkFile(JFILES, JG3TERMINALPATH, data[g_Keys.files.terminal]); + } + return rval; } @@ -688,12 +753,12 @@ bool CConfigure::isDefined(ErrorLevel level, const std::string §ion, const s if (ErrorLevel::mild == level) { - std::cout << "WARNING: [" << section << "] " << pname << " is not defined" << std::endl; + std::cout << "WARNING: [" << section << ']' << pname << " is not defined" << std::endl; data[key] = nullptr; } else { - std::cerr << "ERROR: [" << section << "] " << pname << " is not defined" << std::endl; + std::cerr << "ERROR: [" << section << ']' << pname << " is not defined" << std::endl; rval = true; } return false; @@ -708,7 +773,7 @@ void CConfigure::checkAutoLink(const std::string §ion, const std::string &pn 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; + std::cerr << "ERROR: [" << section << ']' << pname << " module '" << c << "' not a configured module" << std::endl; rval = true; } } @@ -767,6 +832,16 @@ void CConfigure::setAutolink(const std::string §ion, const std::string &key, std::cout << "WARNING: line #" << counter << ": " << section << " AutoLinkModule is invalid: '" << value.substr(0, 1) << "'" << std::endl; } +void CConfigure::checkFile(const std::string §ion, const std::string &key, const std::string &filepath) const +{ + struct stat sstat; + auto rval = stat(filepath.c_str(), &sstat); + if (rval) + { + std::cout << "WARNING: [" << section << ']' << key << " \"" << filepath << "\": " << strerror(errno) << std::endl; + } +} + void CConfigure::Dump(bool justpublic) const { nlohmann::json tmpjson = data; @@ -843,6 +918,14 @@ unsigned CConfigure::GetUnsigned(const std::string &key) const return u; } +bool CConfigure::GetBoolean(const std::string &key) const +{ + if (data[key].is_boolean()) + return data[key]; + else + return false; +} + char CConfigure::GetAutolinkModule(const std::string &key) const { char c = 0; diff --git a/reflector/Configure.h b/reflector/Configure.h index 7395918..bb52d3f 100644 --- a/reflector/Configure.h +++ b/reflector/Configure.h @@ -25,7 +25,7 @@ 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 }; +enum class ESection { none, names, ip, modules, urf, dplus, dextra, dcs, g3, dmrplus, mmdvm, nxdn, bm, ysf, p25, m17, usrp, dmrid, nxdnid, ysffreq, files }; #define IS_TRUE(a) ((a)=='t' || (a)=='T' || (a)=='1') @@ -37,6 +37,7 @@ public: void Dump(bool justpublic) const; std::string GetString(const std::string &key) const; unsigned GetUnsigned(const std::string &key) const; + bool GetBoolean(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; @@ -51,6 +52,7 @@ private: 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 checkFile(const std::string §ion, const std::string &key, const std::string &filepath) 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/JsonKeys.h b/reflector/JsonKeys.h index 38b06b6..719ecba 100644 --- a/reflector/JsonKeys.h +++ b/reflector/JsonKeys.h @@ -23,35 +23,49 @@ // configuration key names struct SJsonKeys { struct PORTONLY { const std::string port; } - bm { "BrandMeisterPort" }, dcs { "DCSPort" }, dextra { "DExtraPort" }, dmrplus { "DMRPlusPort" }, dplus { "DPlusPort" }, m17 { "M17Port" }, urf { "URFPort" }; + + struct G3 { const std::string enable; } + g3 { "G3Enable" }; + + struct BM { const std::string enable, port; } + bm { "bmEnable", "bmPort" }; + struct MMDVM { const std::string port, defaultid; } mmdvm { "MMDVMPort", "mmdvmdefaultid" }; - struct NAMES { const std::string cs, email, country, sponsor; } + + struct NAMES { const std::string callsign, email, country, sponsor; } names { "Callsign", "SysopEmail", "Country", "Sponsor" }; + struct IP { const std::string ipv4bind, ipv4address, ipv6bind, ipv6address, transcoder; } ip { "ipv4bind", "IPv4Address", "ipv6bind", "IPv6Address", "tcaddress" }; + struct MODULES { const std::string modules, tcmodules, descriptor[26]; } modules { "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" }; - struct USRP { const std::string port, autolinkmod, defaultcallsign, clientfilepath; } - usrp { "USRPPort", "USRPAutolinkMod", "usrpDefaultCallsign", "usrpClientfilePath" }; + + struct USRP { const std::string enable, port, module, callsign, filepath; } + usrp { "usrpEnable", "urspPort", "usrpModule", "usrpCallsign", "usrpFilePath" }; + struct P25NXDN { const std::string port, autolinkmod, reflectorid; } p25 { "P25Port", "P25AutolinkMod", "P25ReflectorID" }, nxdn { "NXDNPort", "NXDNAutolinkMod", "NXDNReflectorID" }; + struct YSF { const std::string port, autolinkmod, defaulttxfreq, defaultrxfreq; struct YSLREG { const std::string id, name, description; } ysfreflectordb; } ysf { "YSFPort", "YSFAutoLinkMod", "YSFDefaultTxFreq", "YSFDefaultRxFreq", { "ysfrefdbid", "ysfrefdbname", "ysfrefdbdesc" } }; + struct DB { const std::string url, mode, refreshmin, filepath; } dmriddb { "dmrIdDbUrl", "dmrIdDbMode", "dmrIdDbRefresh", "dmrIdDbFilePath" }, nxdniddb { "nxdnIdDbUrl", "nxdnIdDbMode", "nxdnIdDbRefresh", "nxdnIdDbFilePath" }, ysftxrxdb { "ysfIdDbUrl", "ysfIdDbMode", "ysfIdDbRefresh", "ysfIdDbFilePath" }; + struct FILES { const std::string pid, state, white, black, interlink, terminal; } files { "pidFilePath", "stateFilePath", "whitelistFilePath", "blacklistFilePath", "interlinkFilePath", "g3TerminalFilePath" }; }; diff --git a/reflector/Main.cpp b/reflector/Main.cpp index c309ed8..a2fe4d4 100644 --- a/reflector/Main.cpp +++ b/reflector/Main.cpp @@ -49,7 +49,7 @@ int main(int argc, char *argv[]) std::cout << "IPv4 binding address is '" << g_Conf.GetString(g_Keys.ip.ipv4bind) << "'" << std::endl; // remove pidfile const std::string pidpath(g_Conf.GetString(g_Keys.files.pid)); - const std::string callsign(g_Conf.GetString(g_Keys.names.cs)); + const std::string callsign(g_Conf.GetString(g_Keys.names.callsign)); remove(pidpath.c_str()); // splash diff --git a/reflector/Protocols.cpp b/reflector/Protocols.cpp index b14a1d4..f79b683 100644 --- a/reflector/Protocols.cpp +++ b/reflector/Protocols.cpp @@ -64,9 +64,12 @@ bool CProtocols::Init(void) if (! m_Protocols.back()->Initialize(nullptr, EProtocol::dmrmmdvm, uint16_t(g_Conf.GetUnsigned(g_Keys.mmdvm.port)), DMR_IPV4, DMR_IPV6)) return false; - m_Protocols.emplace_back(std::unique_ptr(new CBMProtocol)); - if (! m_Protocols.back()->Initialize("XLX", EProtocol::bm, uint16_t(g_Conf.GetUnsigned(g_Keys.bm.port)), DMR_IPV4, DMR_IPV6)) - return false; + if (g_Conf.GetBoolean(g_Keys.bm.enable)) + { + m_Protocols.emplace_back(std::unique_ptr(new CBMProtocol)); + if (! m_Protocols.back()->Initialize("XLX", EProtocol::bm, uint16_t(g_Conf.GetUnsigned(g_Keys.bm.port)), DMR_IPV4, DMR_IPV6)) + return false; + } m_Protocols.emplace_back(std::unique_ptr(new CDmrplusProtocol)); if (! m_Protocols.back()->Initialize(nullptr, EProtocol::dmrplus, uint16_t(g_Conf.GetUnsigned(g_Keys.dmrplus.port)), DMR_IPV4, DMR_IPV6)) @@ -88,17 +91,23 @@ bool CProtocols::Init(void) if (! m_Protocols.back()->Initialize("NXDN", EProtocol::nxdn, uint16_t(g_Conf.GetUnsigned(g_Keys.nxdn.port)), NXDN_IPV4, NXDN_IPV6)) return false; - m_Protocols.emplace_back(std::unique_ptr(new CUSRPProtocol)); - if (! m_Protocols.back()->Initialize("USRP", EProtocol::usrp, uint16_t(g_Conf.GetUnsigned(g_Keys.usrp.port)), USRP_IPV4, USRP_IPV6)) - return false; + if (g_Conf.GetBoolean(g_Keys.usrp.enable)) + { + m_Protocols.emplace_back(std::unique_ptr(new CUSRPProtocol)); + if (! m_Protocols.back()->Initialize("USRP", EProtocol::usrp, uint16_t(g_Conf.GetUnsigned(g_Keys.usrp.port)), USRP_IPV4, USRP_IPV6)) + return false; + } m_Protocols.emplace_back(std::unique_ptr(new CURFProtocol)); if (! m_Protocols.back()->Initialize("URF", EProtocol::urf, uint16_t(g_Conf.GetUnsigned(g_Keys.urf.port)), URF_IPV4, URF_IPV6)) return false; - m_Protocols.emplace_back(std::unique_ptr(new CG3Protocol)); - if (! m_Protocols.back()->Initialize("XLX", EProtocol::g3, G3_DV_PORT, DMR_IPV4, DMR_IPV6)) + if (g_Conf.GetBoolean(g_Keys.g3.enable)) + { + m_Protocols.emplace_back(std::unique_ptr(new CG3Protocol)); + if (! m_Protocols.back()->Initialize("XLX", EProtocol::g3, G3_DV_PORT, DMR_IPV4, DMR_IPV6)) return false; + } } m_Mutex.unlock(); diff --git a/reflector/Reflector.cpp b/reflector/Reflector.cpp index 39cf577..f68791c 100644 --- a/reflector/Reflector.cpp +++ b/reflector/Reflector.cpp @@ -47,7 +47,7 @@ CReflector::~CReflector() bool CReflector::Start(void) { // get config stuff - m_Callsign = CCallsign(g_Conf.GetString(g_Keys.names.cs).c_str(), false); + m_Callsign = CCallsign(g_Conf.GetString(g_Keys.names.callsign).c_str(), false); m_Modules.assign(g_Conf.GetString(g_Keys.modules.modules)); std::string tcmods(g_Conf.GetString(g_Keys.modules.tcmodules)); @@ -273,15 +273,15 @@ void CReflector::RouterThread(const char ThisModule) m_Protocols.Lock(); for ( auto it=m_Protocols.begin(); it!=m_Protocols.end(); it++ ) { - // make a copy! after the Push(tmp), tmp will be nullptr! auto copy = packet->Copy(); // if packet is header, update RPT2 according to protocol if ( copy->IsDvHeader() ) { - // get our callsign + // make the protocol-patched reflector callsign CCallsign csRPT = (*it)->GetReflectorCallsign(); csRPT.SetCSModule(ThisModule); + // and put it in the copy (dynamic_cast(copy.get()))->SetRpt2Callsign(csRPT); } diff --git a/reflector/USRPProtocol.cpp b/reflector/USRPProtocol.cpp index 4a17ea9..f9b49cd 100644 --- a/reflector/USRPProtocol.cpp +++ b/reflector/USRPProtocol.cpp @@ -1,8 +1,5 @@ -// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. - // urfd -- The universal reflector -// Copyright © 2021 Thomas A. Early N7TAE -// Copyright © 2021 Doug McLain AD8DP +// Copyright © 2023 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 @@ -37,13 +34,8 @@ const uint8_t TLV_TAG_SET_INFO = 8; bool CUSRPProtocol::Initialize(const char *type, const EProtocol ptype, const uint16_t port, const bool has_ipv4, const bool has_ipv6) { - // config data - m_DefaultCallsign.assign(g_Conf.GetString(g_Keys.usrp.defaultcallsign)); - m_AutolinkModule = g_Conf.GetAutolinkModule(g_Keys.usrp.autolinkmod); CBuffer buffer; m_uiStreamId = 0; - CCallsign cs(m_DefaultCallsign.c_str()); - CClients *clients = g_Refl.GetClients(); std::ifstream file; std::streampos size; @@ -51,7 +43,10 @@ bool CUSRPProtocol::Initialize(const char *type, const EProtocol ptype, const ui if (! CProtocol::Initialize(type, ptype, port, has_ipv4, has_ipv6)) return false; - file.open(g_Conf.GetString(g_Keys.usrp.clientfilepath), std::ios::in | std::ios::binary | std::ios::ate); + m_CStr.assign(g_Conf.GetString(g_Keys.usrp.callsign)); + m_Module = g_Conf.GetString(g_Keys.usrp.module).at(0); + + file.open(g_Conf.GetString(g_Keys.usrp.filepath), std::ios::in | std::ios::binary | std::ios::ate); if ( file.is_open() ) { // read file @@ -78,24 +73,24 @@ bool CUSRPProtocol::Initialize(const char *type, const EProtocol ptype, const ui *ptr2 = 0; char *ip; char *port; - if ((ip = ::strtok(ptr1, ";")) != nullptr) - { - if ( ((port = ::strtok(nullptr, ";")) != nullptr) ) - { - uint32_t ui = atoi(port); - CIp Ip(AF_INET, ui, ip); - auto newclient = std::make_shared(cs, Ip); - if (m_AutolinkModule) - newclient->SetReflectorModule(m_AutolinkModule); + char *clientcs; - clients->AddClient(newclient); - } + if ( ((ip = ::strtok(ptr1, ";")) != nullptr) && + ((port = ::strtok(nullptr, ";")) != nullptr) && + ((clientcs = ::strtok(nullptr, ";")) != nullptr) ) + { + uint32_t ui = atoi(port); + CIp Ip(AF_INET, ui, ip); + CCallsign cs(clientcs); + auto newclient = std::make_shared(cs, Ip); + newclient->SetReflectorModule(m_Module); + g_Refl.GetClients()->AddClient(newclient); + g_Refl.ReleaseClients(); } ptr1 = ptr2+1; } } - g_Refl.ReleaseClients(); // update time m_LastKeepaliveTime.start(); @@ -279,12 +274,14 @@ bool CUSRPProtocol::IsValidDvPacket(const CIp &Ip, const CBuffer &Buffer, std::u if ( !stream ) { m_uiStreamId = static_cast(::rand()); - CCallsign csMY = CCallsign(m_DefaultCallsign.c_str()); - CCallsign rpt1 = CCallsign(m_DefaultCallsign.c_str()); - CCallsign rpt2 = m_ReflectorCallsign; - rpt1.SetCSModule(USRP_MODULE_ID); + CCallsign csMY, rpt1, rpt2, csUR; + csMY.SetCallsign(m_CStr, false); + rpt1.SetCallsign(m_CStr, false); + rpt2 = m_ReflectorCallsign; + csUR.SetCallsign("CQCQCQ", false); + rpt1.SetCSModule(m_Module); rpt2.SetCSModule(' '); - header = std::unique_ptr(new CDvHeaderPacket(csMY, CCallsign("CQCQCQ"), rpt1, rpt2, m_uiStreamId, true)); + header = std::unique_ptr(new CDvHeaderPacket(csMY, csUR, rpt1, rpt2, m_uiStreamId, true)); OnDvHeaderPacketIn(header, Ip); } @@ -310,9 +307,11 @@ bool CUSRPProtocol::IsValidDvHeaderPacket(const CIp &Ip, const CBuffer &Buffer, CCallsign csMY = CCallsign("", uiSrcId); CCallsign rpt1 = CCallsign("", uiSrcId); CCallsign rpt2 = m_ReflectorCallsign; - rpt1.SetCSModule(USRP_MODULE_ID); + CCallsign csUR; + csUR.SetCallsign("CQCQCQ", false); + rpt1.SetCSModule(m_Module); rpt2.SetCSModule(' '); - header = std::unique_ptr(new CDvHeaderPacket(csMY, CCallsign("CQCQCQ"), rpt1, rpt2, m_uiStreamId, true)); + header = std::unique_ptr(new CDvHeaderPacket(csMY, csUR, rpt1, rpt2, m_uiStreamId, true)); } return true; } diff --git a/reflector/USRPProtocol.h b/reflector/USRPProtocol.h index 6362a77..1509ca6 100644 --- a/reflector/USRPProtocol.h +++ b/reflector/USRPProtocol.h @@ -1,8 +1,5 @@ -// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. - // urfd -- The universal reflector -// Copyright © 2021 Thomas A. Early N7TAE -// Copyright © 2021 Doug McLain AD8DP +// Copyright © 2023 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 @@ -24,12 +21,9 @@ #include "Protocol.h" #include "DVHeaderPacket.h" #include "DVFramePacket.h" +#include "Timer.h" +#include "Clients.h" -//////////////////////////////////////////////////////////////////////////////////////// -// define - -#define USRP_MODULE_ID 'B' -//////////////////////////////////////////////////////////////////////////////////////// // class class CUSRPStreamCacheItem @@ -74,7 +68,8 @@ protected: std::unordered_map m_StreamsCache; uint32_t m_uiStreamId; - // config data - std::string m_DefaultCallsign; - char m_AutolinkModule; +private: + // CConfigure data + std::string m_CStr; + char m_Module; }; diff --git a/reflector/example.ini b/reflector/example.ini index cf9ab4b..b87af44 100644 --- a/reflector/example.ini +++ b/reflector/example.ini @@ -21,6 +21,7 @@ IPv4Binding = 0.0.0.0 # define if you want to override what urfd finds using ipv4.icanhazip.com # IPv4External = 4.3.2.1 + # define if you want to override what urfd finds using ipv6.icanhazip.com # IPv6External = f:e:d:c:b:a:9:0 @@ -39,6 +40,7 @@ DescriptionZ = Temp Meeting # Protocols [Brandmeister] +Enable = false # Set to true if you've configured BM connections in your urfd.interlink file. Port = 10002 [DCS] @@ -47,12 +49,15 @@ Port = 30051 [DExtra] Port = 30001 -[DMRPlus] -Port = 8880 - [DPlus] Port = 20001 +[G3] +Enable = true + +[DMRPlus] +Port = 8880 + [M17] Port = 17000 @@ -74,10 +79,11 @@ ReflectorID = 12345 Port = 10017 [USRP] -Port = 34001 -AutoLinkModule = A # comment out if you want to disable AL -DefaultCallsign = ALLSTAR -ClientFilePath = /usr/local/etc/USRPClients.txt +Enable = false +Port = 32000 +Module = A # this has to be a transcoded module! +Callsign = ALLSTAR +#FilePath = /home/usr/Clients.txt # An experimental area of development [YSF] Port = 42000 @@ -93,20 +99,20 @@ RegistrationDescription = URF Reflector [DMR ID DB] Mode = http #### Mode is "http", "file", or "both" #### if "both", the url will be read first -FilePath = /usr/local/etc/dmrid.dat # for you to add your own values - # will be reloaded quickly, about 10s +FilePath = /home/user/dmrid.dat # for you to add your own values + # will be reloaded within 10s URL = http://xlxapi.rlx.lu/api/exportdmr.php # if Mode "http" or "both" -RefreshMin = 179 # RefreshMin will only be used if the Mode is "file" +RefreshMin = 179 [NXDN ID DB] Mode = http -FilePath = /usr/local/etc/nxdn.dat +FilePath = /home/user/nxdn.dat URL = https://radioid.net/static/nxdn.csv RefreshMin = 1440 # radioid.net says this file is updated once/day [YSF TX/RX DB] Mode = http -FilePath = /usr/local/etc/ysfnode.dat +FilePath = /home/user/ysfnode.dat URL = http://xlxapi.rlx.lu/api/exportysfrepeaters.php RefreshMin = 191 @@ -114,7 +120,7 @@ RefreshMin = 191 [Files] PidPath = /var/run/urfd.pid ReflStatePath = /var/log/urfd.xml -WhitelistPath = /usr/local/etc/urfd.whitelist -BlacklistPath = /usr/local/etc/urfd.blacklist -InterlinkPath = /usr/local/etc/urfd.interlink -G3TerminalPath = /usr/local/etc/urfd.terminal +WhitelistPath = /home/user/urfd.whitelist +BlacklistPath = /home/user/urfd.blacklist +InterlinkPath = /home/user/urfd.interlink +G3TerminalPath = /home/user/urfd.terminal From 95e8c4d07a7bff536ec7dff5423c8af2eb186d20 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Tue, 28 Feb 2023 10:48:01 -0700 Subject: [PATCH 29/44] added a json file to CConfigure --- .gitignore | 9 +- README.md | 153 +- reflector/example.ini => config/urfd.ini | 5 +- reflector/example.mk => config/urfd.mk | 0 {systemd => config}/urfd.service | 0 radmin | 48 - rconfig | 653 --- reflector/Client.cpp | 19 - reflector/Client.h | 1 - reflector/Configure.cpp | 21 +- reflector/JsonKeys.h | 4 +- reflector/Makefile | 2 +- reflector/Peer.cpp | 18 - reflector/Peer.h | 1 - reflector/Reflector.cpp | 2 +- reflector/User.cpp | 21 - reflector/User.h | 1 - wiresx/bootstrap.css | 6757 ---------------------- wiresx/finish.php | 73 - wiresx/frequency.php | 126 - wiresx/login.php | 123 - wiresx/logout.php | 14 - wiresx/register.php | 148 - wiresx/reset-password.php | 106 - 24 files changed, 89 insertions(+), 8216 deletions(-) rename reflector/example.ini => config/urfd.ini (96%) rename reflector/example.mk => config/urfd.mk (100%) rename {systemd => config}/urfd.service (100%) delete mode 100755 rconfig delete mode 100644 wiresx/bootstrap.css delete mode 100644 wiresx/finish.php delete mode 100644 wiresx/frequency.php delete mode 100644 wiresx/login.php delete mode 100644 wiresx/logout.php delete mode 100644 wiresx/register.php delete mode 100644 wiresx/reset-password.php diff --git a/.gitignore b/.gitignore index fcb78c0..949061f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,7 @@ *.o *.d .vscode -reflector/urfd.blacklist -reflector/urfd.whitelist -reflector/urfd.interlink -reflector/urfd.terminal -configure.mk -wiresx/configure.php -urfd* +reflector/urfd.* +urfd inicheck dbutil diff --git a/README.md b/README.md index 51aefc9..f902664 100644 --- a/README.md +++ b/README.md @@ -2,43 +2,25 @@ The URF Multiprotocol Gateway Reflector Server, ***urfd***, is part of the software system for a Digital Voice Network. The sources are published under GPL Licenses. -# Information about this fork -This fork of URFD supports *all* modes currently used in ham radio: D-Star, DMR, YSF, P25, NXDN, M17, and USRP (for connections to AllStar nodes, etc). All transcoding is centralized so there is no double transcoding to/from any mode. This fork of urfd, along with the swambe2 branch of my tcd repo, contains many changes from the original: - -Integraded P25 Reflector with software imbe vocoder. - -Integrated NXDN Reflector - -Inegrated USRP Reflector - -Optional software vocoding of AMBE+2(DMR/YSF/NXDN) can be done using md380_vocoder library. This means that only 1 USB dv dongle is required per module. This also makes an ARM platform (like Rpi) a reqirement. See the tcd README for details. - -Numerous fixes like late entry recognition from modes like YSF that are otherwise ignored by the original reflector when no header has been received. - -The USRP Clients are read from a file defined in Main.h. The format of this file is ipaddr;port; one host per line, ex: - -```bash -192.168.1.100;32000; -192.168.1.101;32001; -``` - -The rest of this README is unchanged from the original. - ## Introduction -This will build a new kind of digital voice reflector. Based on N7TAE's [new-xlxd](https://github.com/n7tae/new-xlxd), which, in turn, is based on the first multi-protocol reflector, [xlxd](https://github.com/LX3JL/xlxd), **urfd** supports all protocols of it's predecessors, as well as both M17 protocols, **voice-only** and **voice+data**! A key part of this is the hybrid transcoder, [tcd](https://github.com/n7tae/tcd), which is in a seperate repository. URFd is not compatible with either new-xlxd or xlxd. You can't interlink urfd with xlxd. This reflector can be built without a transcoder, but clients will only hear other clients using the same protocol. Please note that currently, urfd only supports the tcd transcoder when run locally. For best performance, urfd and tcd uses UNIX DGRAM sockets for interprocess communications. These kernel-base sockets are signifantly faster than conventional UDP/IP sockets. It should be noted that tcd supports DVSI-3003 nad DVSI-3000 devices, which it uses for AMBE vocoding. +This will build a new kind of digital voice reflector. A *urfd* supports DStar protocols (DPlus, DCS, DExtra and G3) DMR protocols (MMDVMHost, DMR+ and NXDN), M17, YSF, P25 (using IMBE) and USRP (Allstar). A key part of this is the hybrid transcoder, [tcd](https://github.com/n7tae/tcd), which is in a seperate repository. You can't interlink urfd with xlxd. This reflector can be built without a transcoder, but clients will only hear other clients using the same codec. Please note that currently, urfd only supports the tcd transcoder when run locally. As a local device, urfd and tcd uses UNIX DGRAM sockets for interprocess communications. These kernel-base sockets are signifantly faster than conventional UDP/IP sockets. It should be noted that tcd supports DVSI-3003 nad DVSI-3000 devices, which it uses for AMBE vocoding. + +This build support *dual-stack* operation, so the server on which it's running, must have both an IPv4 and IPv6 routable address if you are going to configure a dual-stack reflector. -This build support *dual-stack* operation, so the server on which it's running, must have both an IPv4 and IPv6 routable address if you are going to configure a dual-stack reflector. URF can support out-going DExtra links, by adding a new DExtra Peer type *and* it has many changes designed to increase reliability and stability. +There are many improvements previous multi-mode reflectors: -There are many improvements of urfd over xlxd, some of which were inherited from new-xlxd: - Nearly all std::vector containers have been replaced with more appropriate containers. - No classes are derived from any standard containers. - For concurancy, *i.e.*, thread management, the standard thread (std::thread) library calls have been replaced with std::future. - Managed memory, std::unique_ptr and std::shared_ptr, is used replacing the need for calls to *new* and *delete*. - Your reflector can be configured with up to 26 modules, *A* through *Z* and as few as one module. For other choices, the configure modules don't have to be contigious. For example, you could configure modules A, B, C and E. +- An integraded P25 Reflector with software imbe vocoder. +- An integrated NXDN Reflector +- An inegrated USRP Reflector -Only systemd-based operating systems are supported. Debian or Ubuntu is recommended. If you want to install this on a non-systemd based OS, you are on your own. Also, by default, tcd and urfd are built without gdb support. You can add debugging support in the configuration script, `./rconfig`. Finally, this repository is designed so that you don't have to modify any file in the repository when you build your system. Any file you need to modify to properly configure your reflector will be a file you copy from you locally cloned repo. This makes it easier to update the source code when this repository is updated. Follow the instructions below to build your transcoding URF reflector. +Only systemd-based operating systems are supported. Debian or Ubuntu is recommended. If you want to install this on a non-systemd based OS, you are on your own. Finally, this repository is designed so that you don't have to modify any file in the repository when you build your system. Any file you need to modify to properly configure your reflector will be a file you copy from you locally cloned repo. This makes it easier to update the source code when this repository is updated. Follow the instructions below to build your transcoding URF reflector. ## Usage @@ -66,47 +48,44 @@ sudo apt upgrade sudo apt install git sudo apt install apache2 php5 sudo apt install build-essential -sudo apt install libmariadb-dev-compat +sudo apt install nlohman-json3-dev ``` -### YSF direct connection support - -The following is needed if you plan on supporting local YSF frequency registration database for those YSF-clients that want to directly connect to URF. You will also need to install the client frequency registration pages on your web server. This is because the WiresX protocol supplies the operational frequency to connecting clients. - -```bash -sudo apt install php-mysql mariadb-server mariadb-client -``` - -### Download the repository(s) +### Download and build the repository and ```bash git clone https://github.com/n7tae/urfd.git +cd urfd/reflector ``` -And, if needed, the hybrid transcoder: +You'll need to set two compile-time options: ```bash -git clone https://github.com/n7tae/tcd.git +cp example.mk configure.mk ``` -### Create and edit your blacklist, whitelist and linking files +This will disable debugging and define where the Makefile will install *urfd*. +If you want to change this, edit the configure.mk file with your favorite text editor. Then do a `make` to build *urfd*. -First, move to the reflector build directory: +### Create and edit your configuration files + +First, move to the reflector build directory and create your configuration file: ```bash cd urfd/reflector -``` - -The blacklist file defines callsigns that are blocked from linking or transmitting. The whitelist file defines callsigns that are allowed to link and transmit. Both of these files support the astrisk as a wild-card. The supplied blacklist file is empty and the supplied whitelist file contains a single definition, \*, which will allow any callsign to link and transmit, blocking no one. The interlink file defines possible Brandmeister, XRF and URF linking. The terminal file defines operations for Icom's Terminal and Access Point mode, sometimes called *G3*. This protocol requires significantly higher connection resources than any other mode, so it is possible to build a URF reflector without G3 support. -```bash -cp ../config/urfd.blacklist . -cp ../config/urfd.whitelist . -cp ../config/urfd.interlink . -cp ../config/urfd.terminal . +cp ../config/* . ``` -If you are not going to support G3 linking, you don't need to copy the .terminal file. Use your favorite editor to modify each of these files. If you want a totally open network, the blacklist and whitelist files are ready to go. The blacklist determine which callsigns can't use the reflector. The whitelist determines which callsigns can use the reflector. The interlink file sets up the URF<--->URF inter-linking and/or out-going XRF peer linking. +This will create seven files: +1. The `urfd.blacklist` file defines callsigns that are blocked from linking or transmitting. +2. The `urfd.whitelist` file defines callsigns that are allowed to link and transmit. Both of these files support the astrisk as a wild-card. The supplied blacklist and whitelist file are empty, which will allow any callsign to link and transmit, blocking no one. +3. The `urfd.interlink` file defines possible Brandmeister and URF linking. +4. The `urfd.terminal` file defines operations for Icom's Terminal and Access Point mode, sometimes called *G3*. This protocol requires significantly higher connection resources than any other mode, so it is possible to build a URF reflector without G3 support. +5. The `urfd.service` file is a systemd file that will start and stop *urfd*. Importantly, it contains the only reference to where the *urfd* initialization file is located. +6. The `urfd.mk` file contains compile-time options for *urfd*. If you change the `BINDIR`, you'll need to update how `urfd.service` starts *urfd*. +7. The `urfd.ini` file contains the run-time options for *urfd* and will be discussed below. + When you are done with the configuration files and ready to start the installation process, you can return to the main repository directory: @@ -114,31 +93,48 @@ When you are done with the configuration files and ready to start the installati cd .. ``` +### Build *urfd* + +After possibly editing `urfd.mk`, you can build your reflector: `make` . Besides building *urfd*, this will also build two helper applications that will be discussed below. + ### Configuring your reflector -Configuring, compiling and maintaining your reflector build is easy! Start the configuration script in the base directory of you cloned repo: +Use your favorite text editor to set your run-time configuration in your copy of `urfd.ini`. -```bash -./rconfig -``` +There are only a few things that need to be specified. Most important are, the reflector callsign and the IP addresses for the IPv4 and IPv6 listen ports and a transcoder port, if there is a transcoder. Dual-stack operation is enabled by specifying both an IPv4 and IPv6 address. IPv4-only single stack can be specified by leaving the IPv6 address undefined. + +You can configure any modules, from **A** to **Z**. They don't have to be contigious. If your reflector is configured with a transcoder, you can specify which configured modules will be transcoded. Up to three modules can be transcoded if you have the necessary hardware. + +Three protocols, BrandMeister, G3 and USRP should be disabled if you aren't going to use them. -There are only a few things that need to be specified. Most important are, the reflector callsign and the IP addresses for the IPv4 and IPv6 listen ports and a transcoder port, if there is a transcoder. Dual-stack operation is enabled by specifying both an IPv4 and IPv6 address. IPv4-only single stack can be specified by leaving the IPv6 address set to `none`. It's even possible to operate in an IPv6-only configuration by leaving the IPv4 address to the default `none`. For most users, you can define the IP addresses as "any", but you can specify specific IPv4 and IPv6 addresses, if this is required for you installation site. +There are three databases needed by *urfd*: +1. The *DMR ID* database maps a DMR ID to a callsign and *vis versa*. +2. The *NXDN ID* database maps an NXDN ID to a callsign and *vis versa*. +3. The *YSF Tx/Rx* database maps a callsign to a transmit/receive RF frequencies. +These databases can come from a URL or a file, or both. If you specify "both", then the file will be read after the URL. -You can configure any modules, from **A** to **Z**. They don't have to be contigious. If your reflector is configured with a transcoder, you can specify which configured modules will be transcoded. Up to three modules can be transcoded. There are also true/false flags to prevent G3 support and so that you can build executables that will support gdb debugging. +### Helper apps -You can support your own YSF frequency database. This is very useful for hot-spots that use YSF linking. These linked hot-spots can then use the *WiresX* command on their radios to be able to connect to any configured URF module. Users can register their TX and RX frequency (typically the same for most hot-spot configurations) on http:<*urf url*>/wiresx/login.php. Once their hot-spot is registered, URF will return the correct frequency for their hot-spot when a *WiresX* command is sent to the reflector. You'll need to enable YSF auto-linking, specify a default module and define a database name, user and user password. When you write you URF configuration, a database **configure.sql** script will be built to not only create the database and database user, but also the table for the hot-spot frequency data. +There are two, very useful helper applications, *inicheck* and *dbutil*. Both apps will show you a usage message if you execuate them without any arguments. -Be sure to write out the configuration files and look over the up to seven different configration files that are created. The first file, reflector.cfg is the memory file for rconfig so that if you start that script again, it will remember how you left things. There are one or two `.h` files for the reflector and tcd and there are one or two `.mk` files for the reflector and tcd makefiles. You should **not** modify these files by hand unless you really know exactly how they work. The rconfig script will not start if it detects that an URF server is already running. You can override this behavior in expert mode: `./rconfig expert`. If you do change the configuration after you have already compiled the code, it is safest if you clean the repo and then recompile. +The *inicheck* app will use the exact same code that urfd uses to validate your `urfd.ini` file. Do `./inicheck -q mrefd.ini` to check your infile for errors. If you see any messages containing `ERROR`, that means that *urfd* won't start. You'll have to fix the errors described in the message(s). If you only see messages containing `WARNING`, *urfd* will start, but it may not perform as expected. You will have to decide if the warning should be fixed. If you don't see any messages, it means that your ini file is syntactly correct. -### Compling and installing your system +The *dbutil* app can be used for serveral tasks relating to the three databases that *urfd* uses. The usage is: `./dbutil DATABASE SOURCE ACTION INIFILE`, where: +- DATABASE is "dmr", "nxdn" or "ysf" +- SOURCE is "html" or "file" +- ACTION is "parse" or "errors" +- INIFLILE is the path to the infile that defines the location of the http and file sources for these three databases. +One at a time, *dbutil* can work with any of the three DATABASEs. It can read either the http or the file SOURCE. It can either show you the data entries that are syntactically correct or incorrect (ACTION). -After you have written your configutation files, you can build and install your system: +### installing your system + +After you have written your configutation files, you can install your system: ```bash -./radmin +./radmin ``` -Use this command to compile and install your system. It can also be used to uninstall your system. It will use the information in reflector.cfg to perform each task. This radmin menu can also perform other tasks like restarting the reflector or transcoder process. It can also be used to update the software, if the system is uninstalled. +Use can use this interactive shell script to install and uninstall your system. This can also perform other tasks like restarting the reflector or transcoder process, or be used to view the reflector or transcoder log in real time. ### Stoping and starting the services manually @@ -163,39 +159,26 @@ Please note that your www root directory might be some place else. There is one **DO NOT** enable the "calling home" feature unless you are sure that you will not be infringing on an existing XLX or XRF reflector with the same callsign suffix. If you don't understand what this means, don't set `$CallingHome['Active']` to true! -If you have configured support of hot-spot frequency registation, recursively copy the **wiresx** directory where the index.php file is for your dashboard. Also from the build directory, create the database and database user and hot-spot frequency table: - -```bash -sudo mysql < configure.sql -``` - -The configure.sql file will be generated automatically by the rconfig script **if** you have enabled the **YSF Local Database**. - -## Updating urfd and tcd - -Updating can be performed entirely in the radmin script, but just in case there is a new version of the radmin script, you can start first with a simple `git pull`. If any .h or .cpp fiiles have updates, you can then start radmin and do a clean and compile and then uninstall and install: `cl, co, us, is`. Follow that with a `rl` to watch the reflector log, or an `rt` to watch the transcoder while it comes up. - -If rconfig was updated with the `git pull`, it might be wise to run it first to see if there have been any new options added to the code base. If so, be sure to write out the new configuration files before exiting rconfig. THen you can rebuild and reinstall your reflector. - -If you change any configuration after your reflector has been compiled, be sure to do a clean/compile/uninstall/reinstall to sync your system to the new configuration. - ## Firewall settings -URF Server requires the following ports to be open and forwarded properly for in- and outgoing network traffic: +URF Server requires the following ports to be open and forwarded properly for in- and outgoing network traffic. Obviously you don't need to open ports for G3, USRP and BrandMeister if they are not enabled: ```text TCP port 80 (http) optional TCP port 443 (https) +UDP port 8880 (DMR+ DMO mode) UDP port 10002 (BM connection) UDP port 10017 (URF interlinking) -UDP port 42000 (YSF protocol) +UDP port 12345 - 12346 (G3 Icom Terminal presence and request port) UDP port 17000 (M17 protocol) -UDP port 30001 (DExtra protocol) UPD port 20001 (DPlus protocol) +UDP port 30001 (DExtra protocol) UDP port 30051 (DCS protocol) -UDP port 8880 (DMR+ DMO mode) +UDP port 32000 (USRP protocol) +UDP port 40000 (G3 Icom Terminal port) +UDP port 41000 (P25 port) +UDP port 41400 (NXDN port) +UDP port 42000 (YSF protocol) UDP port 62030 (MMDVM protocol) -UDP port 12345 - 12346 (Icom Terminal presence and request port) -UDP port 40000 (Icom Terminal dv port) ``` ## YSF Master Server @@ -207,9 +190,9 @@ It has nothing to do with the regular YSFReflector network, hence you don’t ne I will eventually support a remote transcoder option, so that you can, for example, run urfd in a data center, and then run the transcoder somewhere you have physical access to it so you can plug in your AMBE vocoders. I don't recommend this as it will add unnessary and variable latency to your reflector. -The M17 team will be working on big changes for the dashboard. I can't wait to see what they come up with! +The M17 team will be working on big changes for the dashboard! ## Copyright - Copyright © 2016 Jean-Luc Deltombe LX3JL and Luc Engelmann LX1IQ -- Copyright © 2021 Thomas A. Early N7TAE +- Copyright © 2022 Doug McLain AD8DP and Thomas A. Early N7TAE diff --git a/reflector/example.ini b/config/urfd.ini similarity index 96% rename from reflector/example.ini rename to config/urfd.ini index b87af44..94d3da6 100644 --- a/reflector/example.ini +++ b/config/urfd.ini @@ -118,8 +118,9 @@ RefreshMin = 191 ######### Other File locations [Files] -PidPath = /var/run/urfd.pid -ReflStatePath = /var/log/urfd.xml +PidPath = /var/run/xlxd.pid +XmlPath = /var/log/xlxd.xml +#JsonPath = /var/tmp/urfd.json # for future development WhitelistPath = /home/user/urfd.whitelist BlacklistPath = /home/user/urfd.blacklist InterlinkPath = /home/user/urfd.interlink diff --git a/reflector/example.mk b/config/urfd.mk similarity index 100% rename from reflector/example.mk rename to config/urfd.mk diff --git a/systemd/urfd.service b/config/urfd.service similarity index 100% rename from systemd/urfd.service rename to config/urfd.service diff --git a/radmin b/radmin index 13655a0..60f6591 100755 --- a/radmin +++ b/radmin @@ -57,28 +57,6 @@ InstallReflector () { popd } -Clean () { - pushd reflector - make clean - popd - pushd ../tcd - make clean - popd -} - -Compile () { - local np - np=`getconf _NPROCESSORS_ONLN` - pushd reflector - make -j$np || read -p "" - echo "co : Compile the system executable(s)" if [ -e $urfserv ]; then if [ -e $urfserv ]; then echo "us : Uninstall the URF reflector" @@ -164,33 +138,11 @@ do if [ -e reflector/urfd ] && [ ! -e $urfserv ]; then InstallReflector fi - elif [[ "$key" == gp* ]]; then - echo - git pull - echo - read -p " to continue: " ans - pushd ../tcd - git pull - echo - read -p " to continue: " ans - popd - elif [[ "$key" == br* ]]; then - echo - git checkout "$value" - echo - read -p " to continue: " ans - pushd ../tcd - git checkout "$value" - echo - read -p " to continue: " ans - popd elif [[ "$key" == rr* ]]; then if [ -e $urfserv ]; then sudo systemctl restart urfd fi elif [[ "$key" == tr* ]] && [ -e $tcdserv ]; then sudo systemctl restart tcd - elif [[ "$key" == cl* ]]; then Clean - elif [[ "$key" == co* ]]; then Compile elif [[ "$key" == tl* ]] && [ -e $tcdserv ]; then sudo journalctl -u tcd -f elif [[ "$key" == rl* ]] && [ -e $urfserv ]; then sudo journalctl -u urfd -f fi diff --git a/rconfig b/rconfig deleted file mode 100755 index 11a2216..0000000 --- a/rconfig +++ /dev/null @@ -1,653 +0,0 @@ -#!/bin/bash -# -# Copyright (c) 2021 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 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 . -#!/bin/bash - -CharCount () { - local haystack=$1 - local test="\${haystack//[^$2]}" - eval local result=$test - return ${#result} -} - -RemoveDupes () { - local -n s=$1 - local i j - for (( i=0; i<${#s}-1; i++)); do - for (( j=$i+1; j<${#s}; j++)); do - if [[ ${s:$i:1} != "." ]]; then - if [[ ${s:$i:1} == ${s:$j:1} ]]; then - local l=$(($j + 1)) - s="${s:0:$j}.${s:$l}" - fi - fi - done - done - s=${s//.} -} - -CheckModules () { - # only A through Z - modules=${1//[^A-Z]} - if (( ${#modules} < 1 )); then - unset modules - clear - echo "ERROR: You must specify at least one module, A to Z!" - echo - read -p " to continue: " ans - return - fi - - RemoveDupes modules - tcmodules=${modules:0:1} -} - -CheckTranscodedModules () { - local tc=${1//[^A-Z]} - local tcorig=$tc - if (( ${#tc} < 1 )); then - tcmodules=${modules:0:1} - clear - echo "ERROR: You must specify at least one module!" - echo "If you aren't using a transcoder, set the transcoder" - echo "address value to the default 'none'!" - echo - read -p " to continue: " ans - return - fi - - RemoveDupes tc - - local m=$modules_d - if [ ! -z ${modules+x} ]; then - m=$modules - fi - - local i - for ((i=0; i<${#tc}; i++)); do - CharCount $m ${tc:$i:1} - local count=$? - if (( $count < 1 )); then - local j=$((i+1)) - tc="${tc:0:$i}.${tc:$j}" - fi - done - tc=${tc//.} - - if (( ${#tc} < 1 )); then - echo "ERROR: Module(s), '$tcorig', are not in the configure modules, '$m'!" - echo - read -p " to continue: " ans - tcmodules=${modules:0:1} - return - fi - tcmodules=$tc -} - -SetBooleanValue () -{ - local dvname - local cv - if [ -z $2 ]; then - if [ -z ${!1+x} ]; then - if [[ "$1" == module_[abc]_* ]]; then - echo matches - dvname=${1//_[abc]_/_x_} - else - echo does not match - dvname=${1}_d - fi - cv=${!dvname} - else - cv=${!1} - fi - if [[ $cv == [tT]* ]]; then - eval ${1}=false - else - eval ${1}=true - fi - elif [[ "$2" == [tT]* ]]; then - eval ${1}=true - else - eval ${1}=false - fi -} - -EvaluateVar () -{ - if [ -z ${!1+x} ]; then - if [ -z "${!2}" ]; then - echo "'' " - else - echo "${!2} " - fi - else - if [ -z "${!1}" ]; then - echo "''" - else - echo "${!1}" - fi - fi -} - -TestGainValue () -{ - if [[ "$1" =~ ^[-]?[0-9]+$ ]]; then - if (( $1 >= -24 && $1 <= 24 )); then - return 0 - else - return 1 - fi - else - return 1 - fi -} - -AudioGainMenu () -{ -while [[ "$key" != q* ]] -do - clear - echo - echo " DVSI AMBE Chip Audio Gain Menu" - echo - echo " All values are in dB and can be from -24 to 24" - echo " 'input' means the audio amplitude is adjusted before encoding" - echo " 'output' means the audio amplitude is adjusted after decoding" - echo - echo " Non-zero values are generally not required!" - echo " USE AT YOUR OWN RISK!" - echo - echo -n "si : D-Star audio input = "; EvaluateVar dstar_in_gain{,_d} - echo -n "so : D-Star audio output = "; EvaluateVar dstar_out_gain{,_d} - echo -n "mi : DMR/YSF audio input = "; EvaluateVar dmr_in_gain{,_d} - echo -n "mo : DMR/YSF audio output = "; EvaluateVar dmr_out_gain{,_d} - echo - echo "q : Return to Main Menu" - echo "u : Unset the value of (revert to the default value)." - echo - read -p "Please input : " key value - if [[ "$key" == si* ]]; then - TestGainValue "$value" && dstar_in_gain="$value" - elif [[ "$key" == so* ]]; then - TestGainValue "$value" && dstar_out_gain="$value" - elif [[ "$key" == mi* ]]; then - TestGainValue "$value" && dmr_in_gain="$value" - elif [[ "$key" == mo* ]]; then - TestGainValue "$value" && dmr_out_gain="$value" - elif [[ "$key" == u* ]]; then - if [[ "$value" == si* ]]; then - unset dstar_in_gain - elif [[ "$value" == so* ]]; then - unset dstar_out_gain - elif [[ "$value" == mi* ]]; then - unset dmr_in_gain - elif [[ "$value" == mo* ]]; then - unset dmr_out_gain - fi - fi -done -} - -WriteMemFile () -{ - local file - file="$rcfg" - echo "# created on `date`" > $file - [ -z ${callsign+x} ] || echo "callsign='$callsign'" >> $file - [ -z ${modules+x} ] || echo "modules='$modules'" >> $file - [ -z ${ip4addr+x} ] || echo "ip4addr='$ip4addr'" >> $file - [ -z ${ip6addr+x} ] || echo "ip6addr='$ip6addr'" >> $file - [ -z ${tcaddress+x} ] || echo "tcaddress='$tcaddress'" >> $file - [ -z ${tcmodules+x} ] || echo "tcmodules='$tcmodules'" >> $file - [ -z ${dstar_in_gain+x} ] || echo "dstar_in_gain=$dstar_in_gain" >> $file - [ -z ${dstar_out_gain+x} ] || echo "dstar_out_gain=$dstar_out_gain" >> $file - [ -z ${dmr_in_gain+x} ] || echo "dmr_in_gain=$dmr_in_gain" >> $file - [ -z ${dmr_out_gain+x} ] || echo "dmr_out_gain=$dmr_out_gain" >> $file - [ -z ${dmrdbuseserver+x} ] || echo "dmrdbuseserver=$dmrdbuseserver" >> $file - [ -z ${dmrdbrefresh+x} ] || echo "dmrdbrefresh=$dmrdbrefresh" >> $file - [ -z ${dmrdbpath+x} ] || echo "dmrdbpath='$dmrdbpath'" >> $file - [ -z ${ysfautolink+x} ] || echo "ysfautolink=$ysfautolink" >> $file - [ -z ${ysfmodule+x} ] || echo "ysfmodule='$ysfmodule'" >> $file - [ -z ${ysflocaldb+x} ] || echo "ysflocaldb=$ysflocaldb" >> $file - [ -z ${ysfdbname+x} ] || echo "ysfdbname='$ysfdbname'" >> $file - [ -z ${ysfdbuser+x} ] || echo "ysfdbuser='$ysfdbuser'" >> $file - [ -z ${ysfrname+x} ] || echo "ysfrname='$ysfrname'" >> $file - [ -z ${ysfrdesc+x} ] || echo "ysfrdesc='$ysfrdesc'" >> $file - [ -z ${ysfdbpw+x} ] || echo "ysfdbpw='$ysfdbpw'" >> $file - [ -z ${g3support+x} ] || echo "g3support=$g3support" >> $file - [ -z ${dbsupport+x} ] || echo "dbsupport=$dbsupport" >> $file -} - -WriteSRCHFile () -{ - local file m - file="$srch" - echo "// Created on `date`" > $file - echo "#define CALLSIGN \"${callsign}\"" >> $file - if [[ "$callsign" == XRF* ]]; then - echo "#define NO_XLX" >> $file - fi - if [ -z ${modules+x} ]; then - echo "#define ACTIVE_MODULES \"${modules_d}\"" >> $file - else - echo "#define ACTIVE_MODULES \"${modules}\"" >> $file - fi - if [ ! -z ${ip4addr+x} ]; then - echo "#define LISTEN_IPV4 \"${ip4addr}\"" >> $file - fi - if [ ! -z ${ip6addr+x} ]; then - echo "#define LISTEN_IPV6 \"${ip6addr}\"" >> $file - fi - if [ -z ${ysfautolink+x} ]; then - echo "#define YSF_AUTOLINK_ENABLE ${ysfautolink_d}" >> $file - else - echo "#define YSF_AUTOLINK_ENABLE ${ysfautolink}" >> $file - fi - if [ -z ${ysfmodule+x} ]; then - echo "#define YSF_AUTOLINK_MODULE '${ysfmodule_d}'" >> $file - else - echo "#define YSF_AUTOLINK_MODULE '${ysfmodule}'" >> $file - fi - if [ ! -z ${dmrdbuseserver+x} ]; then - if [[ "$dmrdbuseserver" == true ]]; then - m=1 - else - m=0 - fi - else - m=1 - fi - echo "#define DMRIDDB_USE_RLX_SERVER $m" >> $file - if [ ! -z ${dmrdbrefresh+x} ]; then - echo "#define DMRIDDB_REFRESH_RATE $dmrdbrefresh" >> $file - else - echo "#define DMRIDDB_REFRESH_RATE $dmrdbrefresh_d" >> $file - fi - if [ ! -z ${dmrdbpath+x} ]; then - echo "#define DMRIDDB_PATH \"$dmrdbpath\"" >> $file - else - echo "#define DMRIDDB_PATH \"$dmrdbpath_d\"" >> $file - fi - if [[ "$ysflocaldb" == true ]]; then - echo '#define YSF_DB_SUPPORT true' >> $file - echo "#define YSF_DB_NAME \"$ysfdbname\"" >> $file - echo "#define YSF_DB_USER \"$ysfdbuser\"" >> $file - echo "#define YSF_DB_PASSWORD \"$ysfdbpw\"" >> $file - else - echo '#define YSF_DB_SUPPORT false' >> $file - fi - if [ ! -z ${ysfrname+x} ]; then - echo "#define YSF_REFLECTOR_NAME \"$ysfrname\"" >> $file - fi - if [ ! -z ${ysfrdesc+x} ]; then - echo "#define YSF_REFLECTOR_DESCRIPTION \"$ysfrdesc\"" >> $file - fi - if [ ! -z ${tcaddress+x} ]; then - echo "#define TRANSCODER_IP \"${tcaddress}\"" >> $file - echo "#define TRANSCODED_MODULES \"${tcmodules}\"" >> $file - fi - if [ -z ${g3support+x} ]; then - m=${g3support_d} - else - m=${g3support} - fi - if [[ "$m" != true ]]; then - echo "#define NO_G3" >> $file - fi - if [ -n ${dbsupport+x} ]; then - if [ "$dbsupport" == true ]; then - echo "#define DEBUG" >> $file - fi - fi -} - -WriteSRCMKFile () -{ - local file - file="$srcm" - echo "# Created on `date`" > $file - [ -z ${ip4addr+x} ] || echo "ipv4 = $ip4addr" >> $file - [ -z ${ip6addr+x} ] || echo "ipv6 = $ip6addr" >> $file - [ -z ${tcaddress+x} ] || echo "tc_ip = $tcaddress" >> $file - if [ -z ${g3support+x} ]; then - echo "use_g3 = $g3support_d" >> $file - else - echo "use_g3 = $g3support" >> $file - fi - if [ -z ${dbsupport+x} ]; then - echo "debug = $dbsupport_d" >> $file - else - echo "debug = $dbsupport" >> $file - fi - if [ -z ${ysflocaldb+x} ]; then - echo "ysf_db = $ysflocaldb_d" >> $file - else - echo "ysf_db = $ysflocaldb" >> $file - fi -} - -WriteTranscoderHFile () -{ - local file - file="$tcdh" - echo "// Created on `date`" > $file - if [ -n ${tcaddress+x} ] && [[ "$tcaddress" != "local" ]]; then - echo "#define TRANSCODER_IP \"${tcaddress}\"" >> $file - fi - if [ -n ${tcmodules+x} ]; then - echo "#define TRANSCODED_MODULES \"${tcmodules}\"" >> $file - fi - if [ -z ${dstar_in_gain+x} ]; then - echo "#define DSTAR_IN_GAIN $dstar_in_gain_d" >> $file - else - echo "#define DSTAR_IN_GAIN $dstar_in_gain" >> $file - fi - if [ -z ${dstar_out_gain+x} ]; then - echo "#define DSTAR_OUT_GAIN $dstar_out_gain_d" >> $file - else - echo "#define DSTAR_OUT_GAIN $dstar_out_gain" >> $file - fi - if [ -z ${dmr_in_gain+x} ]; then - echo "#define DMR_IN_GAIN $dmr_in_gain_d" >> $file - else - echo "#define DMR_IN_GAIN $dmr_in_gain" >> $file - fi - if [ -z ${dmr_out_gain+x} ]; then - echo "#define DMR_OUT_GAIN $dmr_out_gain_d" >> $file - else - echo "#define DMR_OUT_GAIN $dmr_out_gain" >> $file - fi - if [ -n ${dbsupport+x} ]; then - if [ "$dbsupport" == true ]; then - echo "#define DEBUG" >> $file - fi - fi -} - -WriteTranscoderMKFile () -{ - local file - file="$tcdm" - echo "# created on `date`" > $file - if [ -z ${dbsupport+x} ]; then - echo "debug = $dbsupport_d" >> $file - else - echo "debug = $dbsupport" >> $file - fi -} - -WriteCfgPhpFile () -{ - cat << EOF > $ysfs - -EOF -} - -WriteDBCreateFile () -{ - cat << EOF > $dbcr -CREATE DATABASE IF NOT EXISTS ${ysfdbname}; -USE ${ysfdbname}; -CREATE TABLE IF NOT EXISTS ysfnodes ( - callsign VARCHAR(7) PRIMARY KEY, - password VARCHAR(255) NOT NULL, - txfreq INT NOT NULL DEFAULT 446500000, - rxfreq INT NOT NULL DEFAULT 446500000, - created_at DATETIME DEFAULT CURRENT_TIMESTAMP -); -CREATE USER IF NOT EXISTS '${ysfdbuser}'@'localhost' IDENTIFIED BY '${ysfdbpw}'; -GRANT ALL PRIVILEGES ON $ysfdbname . ysfnodes TO '${ysfdbuser}'@'localhost'; -FLUSH PRIVILEGES; -EOF -} - -WriteCFGFiles () -{ - WriteMemFile - WriteSRCHFile - WriteSRCMKFile - if [ -z ${tcaddress+x} ]; then - rm -f $tcdh $tcdm - else - WriteTranscoderHFile - WriteTranscoderMKFile - fi - if [[ "$ysflocaldb" == true ]]; then - WriteCfgPhpFile - WriteDBCreateFile - else - rm -f $ysfs $dbcr - fi -} - -ListCFGFiles () -{ - echo "===========${rcfg}=============" - cat $rcfg - echo "===========${srch}=============" - cat $srch - echo "===========${srcm}=============" - cat $srcm - if [ ! -z ${tcaddress+x} ]; then - echo "===========${tcdh}=============" - cat $tcdh - echo "===========${tcdm}=============" - cat $tcdm - fi - if [[ "$ysflocaldb" == true ]]; then - echo "===========${ysfs}=============" - cat $ysfs - echo "===========${dbcr}=============" - cat $dbcr - fi -} - -# Execution starts here! -# file locations -rcfg='reflector.cfg' -srch='reflector/configure.h' -srcm='reflector/configure.mk' -tcdh='../tcd/configure.h' -tcdm='../tcd/configure.mk' -ysfs='wiresx/configure.php' -dbcr='configure.sql' -urfserv='/etc/systemd/system/urfd.service' - -# expert mode -if [[ "$1" == ex* ]]; then - expertmode="expertMode" -fi - -if [ -e reflector.cfg ]; then - source reflector.cfg -else - echo 'No configuration file found...' - sleep 1 -fi - -# default values -callsign_d='CHNGME' -modules_d='ABCF' -ip4addr_d='none' -ip6addr_d='none' -tcaddress_d='none' -ysfautolink_d=false -ysfmodule_d='D' -g3support_d=false -dbsupport_d=false -dmrdbuseserver_d=true -dmrdbrefresh_d=180 -dmrdbpath_d='/usr/local/etc/dmrid.dat' -ysflocaldb_d=false -ysfdbname_d='' -ysfdbuser_d='' -ysfdbpw_d='' -dstar_in_gain_d=0 -dstar_out_gain_d=0 -dmr_in_gain_d=0 -dmr_out_gain_d=0 -if [ -z ${callsign+x} ];then - ysfrname_d="$callsign_d" -else - ysfrname_d="$callsign" -fi -ysfrdesc_d='URF Reflector' - -if [ -z ${expertmode+x} ]; then - if [ -e $urfserv ]; then - echo -n "You cannot change the configuration right now beacuse there is an " - if [ -e $urfserv ]; then - echo "URFD server running." - fi; - echo "===========${rcfg}=============" - cat $rcfg - echo - echo "Please use radmin to uninstall the running server before attempting to modify the configuration." - exit 1 - fi -fi - -key='x' -# main loop -while [[ "$key" != q* ]] -do - clear - echo - echo " Reflector Configuration, Version #220326" - echo - echo " ******* REFLECTOR ********" - echo -n "cs : Reflector Callsign = "; EvaluateVar callsign{,_d} - echo -n "am : Active Modules = "; EvaluateVar modules{,_d} - echo -n "g3 : Icom G3 Support = "; EvaluateVar g3support{,_d} - echo " ******* ADDRESSES ********" - echo -n "i4 : IPv4 Listen Address = "; EvaluateVar ip4addr{,_d} - echo -n "i6 : IPv6 Listen Address = "; EvaluateVar ip6addr{,_d} - echo " ******* TRANSCODER ********" - echo " The only TC address supported is 'local' or the default 'none'" - echo -n "tc : Transcoder Address = "; EvaluateVar tcaddress{,_d} - if [ ! -z ${tcaddress+x} ]; then - echo -n "tm : Transcoder Modules = "; EvaluateVar tcmodules{,_d} - echo "ag : AMBE Audio Gain Sub-Menu" - if [ ! -z ${dstar_in_gain+x} ]; then - echo -n " D-Star Input gain = "; EvaluateVar dstar_in_gain{,_d} - fi - if [ ! -z ${dstar_out_gain+x} ]; then - echo -n " D-Star Output gain = "; EvaluateVar dstar_out_gain{,_d} - fi - if [ ! -z ${dmr_in_gain+x} ]; then - echo -n " DMR Input gain = "; EvaluateVar dmr_in_gain{,_d} - fi - if [ ! -z ${dmr_out_gain+x} ]; then - echo -n " DMR Output gain = "; EvaluateVar dmr_out_gain{,_d} - fi - fi - echo " ******* DMR Database ********" - echo -n "ds : Use RLX Server = "; EvaluateVar dmrdbuseserver{,_d} - echo -n "dt : Refresh time (in min) = "; EvaluateVar dmrdbrefresh{,_d} - echo -n "dp : Database path = "; EvaluateVar dmrdbpath{,_d} - echo " ******* SYSTEM FUSION ********" - echo -n "ye : YSF Autolink Enable = "; EvaluateVar ysfautolink{,_d} - if [ ! -z ${ysfautolink+x} ]; then - if [[ "$ysfautolink" == true ]]; then - echo -n "ym : YSF Autolink Module = "; EvaluateVar ysfmodule{,_d} - fi - fi - echo -n "yl : YSF Local Database = "; EvaluateVar ysflocaldb{,_d} - if [[ "$ysflocaldb" == true ]]; then - echo -n "yd : YSF Database Name = "; EvaluateVar ysfdbname{,_d} - echo -n "yu : YSF Database User = "; EvaluateVar ysfdbuser{,_d} - echo -n "yp : YSF Database Password = "; EvaluateVar ysfdbpw{,_d} - fi - echo " ******* YSFReflector Registry *******" - echo -n "rn : Registry Name = "; EvaluateVar ysfrname{,_d} - echo -n "rd : Registry Description = "; EvaluateVar ysfrdesc{,_d} - echo " ******* DEBUGGING ********" - echo -n "db : Debugging Support = "; EvaluateVar dbsupport{,_d} - echo - if [[ "$callsign" == URF* ]]; then - echo "w : Write configuration files (overwrites any existing files) and quit" - fi - echo "q : Quit without saving" - echo "u : Unset the value of (revert to the default value)." - echo - read -p "Please input - omit value to toggle a true/false : " key value - - if [[ "$key" == cs* && ${value^^} == URF* ]]; then - callsign="${value^^}" - callsign="${callsign:0:6}" - ysfrname_d="${callsign}" - unset tcaddress tcmodules ysf{autolink,module,localdb,dbname,dbuser,dbpw} - elif [[ "$key" == am* ]]; then CheckModules "${value^^}" - elif [[ "$key" == i4* ]]; then ip4addr="$value" - elif [[ "$key" == i6* ]]; then ip6addr="$value" - elif [[ "$key" == tc* ]]; then tcaddress="local" - elif [[ "$key" == tm* ]]; then CheckTranscodedModules "${value^^}" - elif [[ "$key" == ag* ]]; then - AudioGainMenu - key=x - elif [[ "$key" == ds* ]]; then SetBooleanValue dmrdbuseserver "$value" - elif [[ "$key" == dt* ]]; then dmrdbrefresh="$value" - elif [[ "$key" == dp* ]]; then dmrdbpath="$value" - elif [[ "$key" == ye* ]]; then SetBooleanValue ysfautolink "$value" - elif [[ "$key" == ym* ]]; then - ysfmodule="${value^^}" - ysfmodule="${ysfmodule:0:1}" - elif [[ "$key" == g3* ]]; then SetBooleanValue g3support "$value" - elif [[ "$key" == db* ]]; then SetBooleanValue dbsupport "$value" - elif [[ "$key" == yl* ]]; then SetBooleanValue ysflocaldb "$value" - elif [[ "$key" == yd* ]]; then ysfdbname="$value" - elif [[ "$key" == yu* ]]; then ysfdbuser="$value" - elif [[ "$key" == yp* ]]; then ysfdbpw="$value" - elif [[ "$key" == rn* ]]; then ysfrname="${value:0:16}" - elif [[ "$key" == rd* ]]; then ysfrdesc="${value:0:14}" - elif [[ "$key" == w* ]]; then - WriteCFGFiles - ListCFGFiles - exit 0 - elif [[ "$key" == u* ]]; then - if [[ "$value" == cs* ]]; then unset callsign - elif [[ "$value" == am* ]]; then unset modules - elif [[ "$value" == i4* ]]; then unset ip4addr - elif [[ "$value" == i6* ]]; then unset ip6addr - elif [[ "$value" == tc* ]]; then unset tcaddress - elif [[ "$value" == tm* ]]; then tcmodules=${modules:0:1} - elif [[ "$value" == ds* ]]; then unset dmrdbuseserver - elif [[ "$value" == dt* ]]; then unset dmrdbrefresh - elif [[ "$value" == dp* ]]; then unset dmrdbpath - elif [[ "$value" == ye* ]]; then unset ysfautolink ysfmodule - elif [[ "$value" == ym* ]]; then unset ysfmodule - elif [[ "$value" == g3* ]]; then unset g3support - elif [[ "$value" == db* ]]; then unset dbsupport - elif [[ "$value" == yl* ]]; then unset ysflocaldb ysfdbname ysfdbuser ysfdbpw - elif [[ "$value" == yd* ]]; then unset ysfdbname - elif [[ "$value" == yu* ]]; then unset ysfdbuser - elif [[ "$value" == yp* ]]; then unset ysfdbpw - elif [[ "$value" == rn* ]]; then unset ysfrname - elif [[ "$value" == rd* ]]; then unset ysfrdesc - fi - fi -done -exit 0 diff --git a/reflector/Client.cpp b/reflector/Client.cpp index 93f27ad..4f6c9c7 100644 --- a/reflector/Client.cpp +++ b/reflector/Client.cpp @@ -95,22 +95,3 @@ void CClient::WriteXml(std::ofstream &xmlFile) } xmlFile << "" << std::endl; } - -void CClient::GetJsonObject(char *Buffer) -{ - char sz[512]; - char mbstr[100]; - char cs[16]; - - if (std::strftime(mbstr, sizeof(mbstr), "%A %c", std::localtime(&m_LastHeardTime))) - { - m_Callsign.GetCallsignString(cs); - - ::sprintf(sz, "{\"callsign\":\"%s\",\"module\":\"%c\",\"linkedto\":\"%c\",\"time\":\"%s\"}", - cs, - m_Callsign.GetCSModule(), - m_ReflectorModule, - mbstr); - ::strcat(Buffer, sz); - } -} diff --git a/reflector/Client.h b/reflector/Client.h index 893ae98..28a3e4b 100644 --- a/reflector/Client.h +++ b/reflector/Client.h @@ -72,7 +72,6 @@ public: // reporting virtual void WriteXml(std::ofstream &); - virtual void GetJsonObject(char *); protected: // data diff --git a/reflector/Configure.cpp b/reflector/Configure.cpp index b13cf12..68e9513 100644 --- a/reflector/Configure.cpp +++ b/reflector/Configure.cpp @@ -56,6 +56,7 @@ #define JIPV4EXTERNAL "IPv4External" #define JIPV6BINDING "IPv6Binding" #define JIPV6EXTERNAL "IPv6External" +#define JJSONPATH "JsonPath" #define JM17 "M17" #define JMMDVM "MMDVM" #define JMODE "Mode" @@ -73,7 +74,6 @@ #define JREGISTRATIONID "RegistrationID" #define JREGISTRATIONNAME "RegistrationName" #define JSPONSOR "Sponsor" -#define JREFLSTATEPATH "ReflStatePath" #define JSYSOPEMAIL "SysopEmail" #define JTRANSCODED "Transcoded" #define JTRANSCODER "Transcoder" @@ -81,6 +81,7 @@ #define JURL "URL" #define JUSRP "USRP" #define JWHITELISTPATH "WhitelistPath" +#define JXMLPATH "XmlPath" #define JYSF "YSF" #define JYSFTXRXDB "YSF TX/RX DB" @@ -463,8 +464,10 @@ bool CConfigure::ReadData(const std::string &path) case ESection::files: if (0 == key.compare(JPIDPATH)) data[g_Keys.files.pid] = value; - else if (0 == key.compare(JREFLSTATEPATH)) - data[g_Keys.files.state] = value; + else if (0 == key.compare(JXMLPATH)) + data[g_Keys.files.xml] = value; + else if (0 == key.compare(JJSONPATH)) + data[g_Keys.files.json] = value; else if (0 == key.compare(JWHITELISTPATH)) data[g_Keys.files.white] = value; else if (0 == key.compare(JBLACKLISTPATH)) @@ -728,17 +731,17 @@ bool CConfigure::ReadData(const std::string &path) } // Other files - isDefined(ErrorLevel::fatal, JFILES, JPIDPATH, g_Keys.files.pid, rval); - isDefined(ErrorLevel::fatal, JFILES, JREFLSTATEPATH, g_Keys.files.state, rval); - if (isDefined(ErrorLevel::fatal, JFILES, JWHITELISTPATH, g_Keys.files.white, rval)) + isDefined(ErrorLevel::fatal, JFILES, JPIDPATH, g_Keys.files.pid, rval); + isDefined(ErrorLevel::fatal, JFILES, JXMLPATH, g_Keys.files.xml, rval); + if (isDefined(ErrorLevel::fatal, JFILES, JWHITELISTPATH, g_Keys.files.white, rval)) checkFile(JFILES, JWHITELISTPATH, data[g_Keys.files.white]); - if (isDefined(ErrorLevel::fatal, JFILES, JBLACKLISTPATH, g_Keys.files.black, rval)) + if (isDefined(ErrorLevel::fatal, JFILES, JBLACKLISTPATH, g_Keys.files.black, rval)) checkFile(JFILES, JBLACKLISTPATH, data[g_Keys.files.black]); - if (isDefined(ErrorLevel::fatal, JFILES, JINTERLINKPATH, g_Keys.files.interlink, rval)) + if (isDefined(ErrorLevel::fatal, JFILES, JINTERLINKPATH, g_Keys.files.interlink, rval)) checkFile(JFILES, JINTERLINKPATH, data[g_Keys.files.interlink]); if (data.contains(g_Keys.g3.enable) && GetBoolean(g_Keys.g3.enable)) { - if (isDefined(ErrorLevel::fatal, JFILES, JG3TERMINALPATH, g_Keys.files.terminal, rval)) + if (isDefined(ErrorLevel::fatal, JFILES, JG3TERMINALPATH, g_Keys.files.terminal, rval)) checkFile(JFILES, JG3TERMINALPATH, data[g_Keys.files.terminal]); } diff --git a/reflector/JsonKeys.h b/reflector/JsonKeys.h index 719ecba..77a7cae 100644 --- a/reflector/JsonKeys.h +++ b/reflector/JsonKeys.h @@ -66,6 +66,6 @@ struct SJsonKeys { nxdniddb { "nxdnIdDbUrl", "nxdnIdDbMode", "nxdnIdDbRefresh", "nxdnIdDbFilePath" }, ysftxrxdb { "ysfIdDbUrl", "ysfIdDbMode", "ysfIdDbRefresh", "ysfIdDbFilePath" }; - struct FILES { const std::string pid, state, white, black, interlink, terminal; } - files { "pidFilePath", "stateFilePath", "whitelistFilePath", "blacklistFilePath", "interlinkFilePath", "g3TerminalFilePath" }; + struct FILES { const std::string pid, xml, json, white, black, interlink, terminal; } + files { "pidFilePath", "xmlFilePath", "jsonFilePath", "whitelistFilePath", "blacklistFilePath", "interlinkFilePath", "g3TerminalFilePath" }; }; diff --git a/reflector/Makefile b/reflector/Makefile index 8bf07f7..c9c8272 100644 --- a/reflector/Makefile +++ b/reflector/Makefile @@ -24,7 +24,7 @@ INICHECK = inicheck DBUTIL = dbutil -include configure.mk +include urfd.mk ifeq ($(debug), true) CFLAGS = -ggdb3 -DDEBUG -W -Werror -std=c++11 -MMD -MD diff --git a/reflector/Peer.cpp b/reflector/Peer.cpp index 9b24722..dca36cd 100644 --- a/reflector/Peer.cpp +++ b/reflector/Peer.cpp @@ -124,21 +124,3 @@ void CPeer::WriteXml(std::ofstream &xmlFile) } xmlFile << "" << std::endl; } - -void CPeer::GetJsonObject(char *Buffer) -{ - char sz[512]; - char mbstr[100]; - char cs[16]; - - if (std::strftime(mbstr, sizeof(mbstr), "%A %c", std::localtime(&m_LastHeardTime))) - { - m_Callsign.GetCallsignString(cs); - - ::sprintf(sz, "{\"callsign\":\"%s\",\"linkedto\":\"%s\",\"time\":\"%s\"}", - cs, - m_ReflectorModules, - mbstr); - ::strcat(Buffer, sz); - } -} diff --git a/reflector/Peer.h b/reflector/Peer.h index d39a146..e91dfb4 100644 --- a/reflector/Peer.h +++ b/reflector/Peer.h @@ -68,7 +68,6 @@ public: // reporting virtual void WriteXml(std::ofstream &); - virtual void GetJsonObject(char *); protected: // data diff --git a/reflector/Reflector.cpp b/reflector/Reflector.cpp index f68791c..11dc4dc 100644 --- a/reflector/Reflector.cpp +++ b/reflector/Reflector.cpp @@ -298,7 +298,7 @@ void CReflector::RouterThread(const char ThisModule) void CReflector::XmlReportThread() { - const std::string path(g_Conf.GetString(g_Keys.files.state)); + const std::string path(g_Conf.GetString(g_Keys.files.xml)); while (keep_running) { // report to xml file diff --git a/reflector/User.cpp b/reflector/User.cpp index cfac5ae..e9b54ce 100644 --- a/reflector/User.cpp +++ b/reflector/User.cpp @@ -76,24 +76,3 @@ void CUser::WriteXml(std::ofstream &xmlFile) } xmlFile << "" << std::endl; } - -void CUser::GetJsonObject(char *Buffer) -{ - char sz[512]; - char mbstr[100]; - char my[16]; - char rpt1[16]; - - if (std::strftime(mbstr, sizeof(mbstr), "%A %c", std::localtime(&m_LastHeardTime))) - { - m_My.GetCallsignString(my); - m_Rpt1.GetCallsignString(rpt1); - - ::sprintf(sz, "{\"callsign\":\"%s\",\"node\":\"%s\",\"module\":\"%c\",\"time\":\"%s\"}", - my, - rpt1, - m_Rpt1.GetCSModule(), - mbstr); - ::strcat(Buffer, sz); - } -} diff --git a/reflector/User.h b/reflector/User.h index c7e6897..617db1c 100644 --- a/reflector/User.h +++ b/reflector/User.h @@ -41,7 +41,6 @@ public: // reporting void WriteXml(std::ofstream &); - void GetJsonObject(char *); protected: // data diff --git a/wiresx/bootstrap.css b/wiresx/bootstrap.css deleted file mode 100644 index 6167622..0000000 --- a/wiresx/bootstrap.css +++ /dev/null @@ -1,6757 +0,0 @@ -/*! - * Bootstrap v3.3.7 (http://getbootstrap.com) - * Copyright 2011-2016 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */ -/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */ -html { - font-family: sans-serif; - -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; -} -body { - margin: 0; -} -article, -aside, -details, -figcaption, -figure, -footer, -header, -hgroup, -main, -menu, -nav, -section, -summary { - display: block; -} -audio, -canvas, -progress, -video { - display: inline-block; - vertical-align: baseline; -} -audio:not([controls]) { - display: none; - height: 0; -} -[hidden], -template { - display: none; -} -a { - background-color: transparent; -} -a:active, -a:hover { - outline: 0; -} -abbr[title] { - border-bottom: 1px dotted; -} -b, -strong { - font-weight: bold; -} -dfn { - font-style: italic; -} -h1 { - margin: .67em 0; - font-size: 2em; -} -mark { - color: #000; - background: #ff0; -} -small { - font-size: 80%; -} -sub, -sup { - position: relative; - font-size: 75%; - line-height: 0; - vertical-align: baseline; -} -sup { - top: -.5em; -} -sub { - bottom: -.25em; -} -img { - border: 0; -} -svg:not(:root) { - overflow: hidden; -} -figure { - margin: 1em 40px; -} -hr { - height: 0; - -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - box-sizing: content-box; -} -pre { - overflow: auto; -} -code, -kbd, -pre, -samp { - font-family: monospace, monospace; - font-size: 1em; -} -button, -input, -optgroup, -select, -textarea { - margin: 0; - font: inherit; - color: inherit; -} -button { - overflow: visible; -} -button, -select { - text-transform: none; -} -button, -html input[type="button"], -input[type="reset"], -input[type="submit"] { - -webkit-appearance: button; - cursor: pointer; -} -button[disabled], -html input[disabled] { - cursor: default; -} -button::-moz-focus-inner, -input::-moz-focus-inner { - padding: 0; - border: 0; -} -input { - line-height: normal; -} -input[type="checkbox"], -input[type="radio"] { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - padding: 0; -} -input[type="number"]::-webkit-inner-spin-button, -input[type="number"]::-webkit-outer-spin-button { - height: auto; -} -input[type="search"] { - -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - box-sizing: content-box; - -webkit-appearance: textfield; -} -input[type="search"]::-webkit-search-cancel-button, -input[type="search"]::-webkit-search-decoration { - -webkit-appearance: none; -} -fieldset { - padding: .35em .625em .75em; - margin: 0 2px; - border: 1px solid #c0c0c0; -} -legend { - padding: 0; - border: 0; -} -textarea { - overflow: auto; -} -optgroup { - font-weight: bold; -} -table { - border-spacing: 0; - border-collapse: collapse; -} -td, -th { - padding: 0; -} -/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */ -@media print { - *, - *:before, - *:after { - color: #000 !important; - text-shadow: none !important; - background: transparent !important; - -webkit-box-shadow: none !important; - box-shadow: none !important; - } - a, - a:visited { - text-decoration: underline; - } - a[href]:after { - content: " (" attr(href) ")"; - } - abbr[title]:after { - content: " (" attr(title) ")"; - } - a[href^="#"]:after, - a[href^="javascript:"]:after { - content: ""; - } - pre, - blockquote { - border: 1px solid #999; - - page-break-inside: avoid; - } - thead { - display: table-header-group; - } - tr, - img { - page-break-inside: avoid; - } - img { - max-width: 100% !important; - } - p, - h2, - h3 { - orphans: 3; - widows: 3; - } - h2, - h3 { - page-break-after: avoid; - } - .navbar { - display: none; - } - .btn > .caret, - .dropup > .btn > .caret { - border-top-color: #000 !important; - } - .label { - border: 1px solid #000; - } - .table { - border-collapse: collapse !important; - } - .table td, - .table th { - background-color: #fff !important; - } - .table-bordered th, - .table-bordered td { - border: 1px solid #ddd !important; - } -} -@font-face { - font-family: 'Glyphicons Halflings'; - - src: url('../fonts/glyphicons-halflings-regular.eot'); - src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg'); -} -.glyphicon { - position: relative; - top: 1px; - display: inline-block; - font-family: 'Glyphicons Halflings'; - font-style: normal; - font-weight: normal; - line-height: 1; - - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} -.glyphicon-asterisk:before { - content: "\002a"; -} -.glyphicon-plus:before { - content: "\002b"; -} -.glyphicon-euro:before, -.glyphicon-eur:before { - content: "\20ac"; -} -.glyphicon-minus:before { - content: "\2212"; -} -.glyphicon-cloud:before { - content: "\2601"; -} -.glyphicon-envelope:before { - content: "\2709"; -} -.glyphicon-pencil:before { - content: "\270f"; -} -.glyphicon-glass:before { - content: "\e001"; -} -.glyphicon-music:before { - content: "\e002"; -} -.glyphicon-search:before { - content: "\e003"; -} -.glyphicon-heart:before { - content: "\e005"; -} -.glyphicon-star:before { - content: "\e006"; -} -.glyphicon-star-empty:before { - content: "\e007"; -} -.glyphicon-user:before { - content: "\e008"; -} -.glyphicon-film:before { - content: "\e009"; -} -.glyphicon-th-large:before { - content: "\e010"; -} -.glyphicon-th:before { - content: "\e011"; -} -.glyphicon-th-list:before { - content: "\e012"; -} -.glyphicon-ok:before { - content: "\e013"; -} -.glyphicon-remove:before { - content: "\e014"; -} -.glyphicon-zoom-in:before { - content: "\e015"; -} -.glyphicon-zoom-out:before { - content: "\e016"; -} -.glyphicon-off:before { - content: "\e017"; -} -.glyphicon-signal:before { - content: "\e018"; -} -.glyphicon-cog:before { - content: "\e019"; -} -.glyphicon-trash:before { - content: "\e020"; -} -.glyphicon-home:before { - content: "\e021"; -} -.glyphicon-file:before { - content: "\e022"; -} -.glyphicon-time:before { - content: "\e023"; -} -.glyphicon-road:before { - content: "\e024"; -} -.glyphicon-download-alt:before { - content: "\e025"; -} -.glyphicon-download:before { - content: "\e026"; -} -.glyphicon-upload:before { - content: "\e027"; -} -.glyphicon-inbox:before { - content: "\e028"; -} -.glyphicon-play-circle:before { - content: "\e029"; -} -.glyphicon-repeat:before { - content: "\e030"; -} -.glyphicon-refresh:before { - content: "\e031"; -} -.glyphicon-list-alt:before { - content: "\e032"; -} -.glyphicon-lock:before { - content: "\e033"; -} -.glyphicon-flag:before { - content: "\e034"; -} -.glyphicon-headphones:before { - content: "\e035"; -} -.glyphicon-volume-off:before { - content: "\e036"; -} -.glyphicon-volume-down:before { - content: "\e037"; -} -.glyphicon-volume-up:before { - content: "\e038"; -} -.glyphicon-qrcode:before { - content: "\e039"; -} -.glyphicon-barcode:before { - content: "\e040"; -} -.glyphicon-tag:before { - content: "\e041"; -} -.glyphicon-tags:before { - content: "\e042"; -} -.glyphicon-book:before { - content: "\e043"; -} -.glyphicon-bookmark:before { - content: "\e044"; -} -.glyphicon-print:before { - content: "\e045"; -} -.glyphicon-camera:before { - content: "\e046"; -} -.glyphicon-font:before { - content: "\e047"; -} -.glyphicon-bold:before { - content: "\e048"; -} -.glyphicon-italic:before { - content: "\e049"; -} -.glyphicon-text-height:before { - content: "\e050"; -} -.glyphicon-text-width:before { - content: "\e051"; -} -.glyphicon-align-left:before { - content: "\e052"; -} -.glyphicon-align-center:before { - content: "\e053"; -} -.glyphicon-align-right:before { - content: "\e054"; -} -.glyphicon-align-justify:before { - content: "\e055"; -} -.glyphicon-list:before { - content: "\e056"; -} -.glyphicon-indent-left:before { - content: "\e057"; -} -.glyphicon-indent-right:before { - content: "\e058"; -} -.glyphicon-facetime-video:before { - content: "\e059"; -} -.glyphicon-picture:before { - content: "\e060"; -} -.glyphicon-map-marker:before { - content: "\e062"; -} -.glyphicon-adjust:before { - content: "\e063"; -} -.glyphicon-tint:before { - content: "\e064"; -} -.glyphicon-edit:before { - content: "\e065"; -} -.glyphicon-share:before { - content: "\e066"; -} -.glyphicon-check:before { - content: "\e067"; -} -.glyphicon-move:before { - content: "\e068"; -} -.glyphicon-step-backward:before { - content: "\e069"; -} -.glyphicon-fast-backward:before { - content: "\e070"; -} -.glyphicon-backward:before { - content: "\e071"; -} -.glyphicon-play:before { - content: "\e072"; -} -.glyphicon-pause:before { - content: "\e073"; -} -.glyphicon-stop:before { - content: "\e074"; -} -.glyphicon-forward:before { - content: "\e075"; -} -.glyphicon-fast-forward:before { - content: "\e076"; -} -.glyphicon-step-forward:before { - content: "\e077"; -} -.glyphicon-eject:before { - content: "\e078"; -} -.glyphicon-chevron-left:before { - content: "\e079"; -} -.glyphicon-chevron-right:before { - content: "\e080"; -} -.glyphicon-plus-sign:before { - content: "\e081"; -} -.glyphicon-minus-sign:before { - content: "\e082"; -} -.glyphicon-remove-sign:before { - content: "\e083"; -} -.glyphicon-ok-sign:before { - content: "\e084"; -} -.glyphicon-question-sign:before { - content: "\e085"; -} -.glyphicon-info-sign:before { - content: "\e086"; -} -.glyphicon-screenshot:before { - content: "\e087"; -} -.glyphicon-remove-circle:before { - content: "\e088"; -} -.glyphicon-ok-circle:before { - content: "\e089"; -} -.glyphicon-ban-circle:before { - content: "\e090"; -} -.glyphicon-arrow-left:before { - content: "\e091"; -} -.glyphicon-arrow-right:before { - content: "\e092"; -} -.glyphicon-arrow-up:before { - content: "\e093"; -} -.glyphicon-arrow-down:before { - content: "\e094"; -} -.glyphicon-share-alt:before { - content: "\e095"; -} -.glyphicon-resize-full:before { - content: "\e096"; -} -.glyphicon-resize-small:before { - content: "\e097"; -} -.glyphicon-exclamation-sign:before { - content: "\e101"; -} -.glyphicon-gift:before { - content: "\e102"; -} -.glyphicon-leaf:before { - content: "\e103"; -} -.glyphicon-fire:before { - content: "\e104"; -} -.glyphicon-eye-open:before { - content: "\e105"; -} -.glyphicon-eye-close:before { - content: "\e106"; -} -.glyphicon-warning-sign:before { - content: "\e107"; -} -.glyphicon-plane:before { - content: "\e108"; -} -.glyphicon-calendar:before { - content: "\e109"; -} -.glyphicon-random:before { - content: "\e110"; -} -.glyphicon-comment:before { - content: "\e111"; -} -.glyphicon-magnet:before { - content: "\e112"; -} -.glyphicon-chevron-up:before { - content: "\e113"; -} -.glyphicon-chevron-down:before { - content: "\e114"; -} -.glyphicon-retweet:before { - content: "\e115"; -} -.glyphicon-shopping-cart:before { - content: "\e116"; -} -.glyphicon-folder-close:before { - content: "\e117"; -} -.glyphicon-folder-open:before { - content: "\e118"; -} -.glyphicon-resize-vertical:before { - content: "\e119"; -} -.glyphicon-resize-horizontal:before { - content: "\e120"; -} -.glyphicon-hdd:before { - content: "\e121"; -} -.glyphicon-bullhorn:before { - content: "\e122"; -} -.glyphicon-bell:before { - content: "\e123"; -} -.glyphicon-certificate:before { - content: "\e124"; -} -.glyphicon-thumbs-up:before { - content: "\e125"; -} -.glyphicon-thumbs-down:before { - content: "\e126"; -} -.glyphicon-hand-right:before { - content: "\e127"; -} -.glyphicon-hand-left:before { - content: "\e128"; -} -.glyphicon-hand-up:before { - content: "\e129"; -} -.glyphicon-hand-down:before { - content: "\e130"; -} -.glyphicon-circle-arrow-right:before { - content: "\e131"; -} -.glyphicon-circle-arrow-left:before { - content: "\e132"; -} -.glyphicon-circle-arrow-up:before { - content: "\e133"; -} -.glyphicon-circle-arrow-down:before { - content: "\e134"; -} -.glyphicon-globe:before { - content: "\e135"; -} -.glyphicon-wrench:before { - content: "\e136"; -} -.glyphicon-tasks:before { - content: "\e137"; -} -.glyphicon-filter:before { - content: "\e138"; -} -.glyphicon-briefcase:before { - content: "\e139"; -} -.glyphicon-fullscreen:before { - content: "\e140"; -} -.glyphicon-dashboard:before { - content: "\e141"; -} -.glyphicon-paperclip:before { - content: "\e142"; -} -.glyphicon-heart-empty:before { - content: "\e143"; -} -.glyphicon-link:before { - content: "\e144"; -} -.glyphicon-phone:before { - content: "\e145"; -} -.glyphicon-pushpin:before { - content: "\e146"; -} -.glyphicon-usd:before { - content: "\e148"; -} -.glyphicon-gbp:before { - content: "\e149"; -} -.glyphicon-sort:before { - content: "\e150"; -} -.glyphicon-sort-by-alphabet:before { - content: "\e151"; -} -.glyphicon-sort-by-alphabet-alt:before { - content: "\e152"; -} -.glyphicon-sort-by-order:before { - content: "\e153"; -} -.glyphicon-sort-by-order-alt:before { - content: "\e154"; -} -.glyphicon-sort-by-attributes:before { - content: "\e155"; -} -.glyphicon-sort-by-attributes-alt:before { - content: "\e156"; -} -.glyphicon-unchecked:before { - content: "\e157"; -} -.glyphicon-expand:before { - content: "\e158"; -} -.glyphicon-collapse-down:before { - content: "\e159"; -} -.glyphicon-collapse-up:before { - content: "\e160"; -} -.glyphicon-log-in:before { - content: "\e161"; -} -.glyphicon-flash:before { - content: "\e162"; -} -.glyphicon-log-out:before { - content: "\e163"; -} -.glyphicon-new-window:before { - content: "\e164"; -} -.glyphicon-record:before { - content: "\e165"; -} -.glyphicon-save:before { - content: "\e166"; -} -.glyphicon-open:before { - content: "\e167"; -} -.glyphicon-saved:before { - content: "\e168"; -} -.glyphicon-import:before { - content: "\e169"; -} -.glyphicon-export:before { - content: "\e170"; -} -.glyphicon-send:before { - content: "\e171"; -} -.glyphicon-floppy-disk:before { - content: "\e172"; -} -.glyphicon-floppy-saved:before { - content: "\e173"; -} -.glyphicon-floppy-remove:before { - content: "\e174"; -} -.glyphicon-floppy-save:before { - content: "\e175"; -} -.glyphicon-floppy-open:before { - content: "\e176"; -} -.glyphicon-credit-card:before { - content: "\e177"; -} -.glyphicon-transfer:before { - content: "\e178"; -} -.glyphicon-cutlery:before { - content: "\e179"; -} -.glyphicon-header:before { - content: "\e180"; -} -.glyphicon-compressed:before { - content: "\e181"; -} -.glyphicon-earphone:before { - content: "\e182"; -} -.glyphicon-phone-alt:before { - content: "\e183"; -} -.glyphicon-tower:before { - content: "\e184"; -} -.glyphicon-stats:before { - content: "\e185"; -} -.glyphicon-sd-video:before { - content: "\e186"; -} -.glyphicon-hd-video:before { - content: "\e187"; -} -.glyphicon-subtitles:before { - content: "\e188"; -} -.glyphicon-sound-stereo:before { - content: "\e189"; -} -.glyphicon-sound-dolby:before { - content: "\e190"; -} -.glyphicon-sound-5-1:before { - content: "\e191"; -} -.glyphicon-sound-6-1:before { - content: "\e192"; -} -.glyphicon-sound-7-1:before { - content: "\e193"; -} -.glyphicon-copyright-mark:before { - content: "\e194"; -} -.glyphicon-registration-mark:before { - content: "\e195"; -} -.glyphicon-cloud-download:before { - content: "\e197"; -} -.glyphicon-cloud-upload:before { - content: "\e198"; -} -.glyphicon-tree-conifer:before { - content: "\e199"; -} -.glyphicon-tree-deciduous:before { - content: "\e200"; -} -.glyphicon-cd:before { - content: "\e201"; -} -.glyphicon-save-file:before { - content: "\e202"; -} -.glyphicon-open-file:before { - content: "\e203"; -} -.glyphicon-level-up:before { - content: "\e204"; -} -.glyphicon-copy:before { - content: "\e205"; -} -.glyphicon-paste:before { - content: "\e206"; -} -.glyphicon-alert:before { - content: "\e209"; -} -.glyphicon-equalizer:before { - content: "\e210"; -} -.glyphicon-king:before { - content: "\e211"; -} -.glyphicon-queen:before { - content: "\e212"; -} -.glyphicon-pawn:before { - content: "\e213"; -} -.glyphicon-bishop:before { - content: "\e214"; -} -.glyphicon-knight:before { - content: "\e215"; -} -.glyphicon-baby-formula:before { - content: "\e216"; -} -.glyphicon-tent:before { - content: "\26fa"; -} -.glyphicon-blackboard:before { - content: "\e218"; -} -.glyphicon-bed:before { - content: "\e219"; -} -.glyphicon-apple:before { - content: "\f8ff"; -} -.glyphicon-erase:before { - content: "\e221"; -} -.glyphicon-hourglass:before { - content: "\231b"; -} -.glyphicon-lamp:before { - content: "\e223"; -} -.glyphicon-duplicate:before { - content: "\e224"; -} -.glyphicon-piggy-bank:before { - content: "\e225"; -} -.glyphicon-scissors:before { - content: "\e226"; -} -.glyphicon-bitcoin:before { - content: "\e227"; -} -.glyphicon-btc:before { - content: "\e227"; -} -.glyphicon-xbt:before { - content: "\e227"; -} -.glyphicon-yen:before { - content: "\00a5"; -} -.glyphicon-jpy:before { - content: "\00a5"; -} -.glyphicon-ruble:before { - content: "\20bd"; -} -.glyphicon-rub:before { - content: "\20bd"; -} -.glyphicon-scale:before { - content: "\e230"; -} -.glyphicon-ice-lolly:before { - content: "\e231"; -} -.glyphicon-ice-lolly-tasted:before { - content: "\e232"; -} -.glyphicon-education:before { - content: "\e233"; -} -.glyphicon-option-horizontal:before { - content: "\e234"; -} -.glyphicon-option-vertical:before { - content: "\e235"; -} -.glyphicon-menu-hamburger:before { - content: "\e236"; -} -.glyphicon-modal-window:before { - content: "\e237"; -} -.glyphicon-oil:before { - content: "\e238"; -} -.glyphicon-grain:before { - content: "\e239"; -} -.glyphicon-sunglasses:before { - content: "\e240"; -} -.glyphicon-text-size:before { - content: "\e241"; -} -.glyphicon-text-color:before { - content: "\e242"; -} -.glyphicon-text-background:before { - content: "\e243"; -} -.glyphicon-object-align-top:before { - content: "\e244"; -} -.glyphicon-object-align-bottom:before { - content: "\e245"; -} -.glyphicon-object-align-horizontal:before { - content: "\e246"; -} -.glyphicon-object-align-left:before { - content: "\e247"; -} -.glyphicon-object-align-vertical:before { - content: "\e248"; -} -.glyphicon-object-align-right:before { - content: "\e249"; -} -.glyphicon-triangle-right:before { - content: "\e250"; -} -.glyphicon-triangle-left:before { - content: "\e251"; -} -.glyphicon-triangle-bottom:before { - content: "\e252"; -} -.glyphicon-triangle-top:before { - content: "\e253"; -} -.glyphicon-console:before { - content: "\e254"; -} -.glyphicon-superscript:before { - content: "\e255"; -} -.glyphicon-subscript:before { - content: "\e256"; -} -.glyphicon-menu-left:before { - content: "\e257"; -} -.glyphicon-menu-right:before { - content: "\e258"; -} -.glyphicon-menu-down:before { - content: "\e259"; -} -.glyphicon-menu-up:before { - content: "\e260"; -} -* { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} -*:before, -*:after { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} -html { - font-size: 10px; - - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); -} -body { - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 14px; - line-height: 1.42857143; - color: #333; - background-color: #fff; -} -input, -button, -select, -textarea { - font-family: inherit; - font-size: inherit; - line-height: inherit; -} -a { - color: #337ab7; - text-decoration: none; -} -a:hover, -a:focus { - color: #23527c; - text-decoration: underline; -} -a:focus { - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} -figure { - margin: 0; -} -img { - vertical-align: middle; -} -.img-responsive, -.thumbnail > img, -.thumbnail a > img, -.carousel-inner > .item > img, -.carousel-inner > .item > a > img { - display: block; - max-width: 100%; - height: auto; -} -.img-rounded { - border-radius: 6px; -} -.img-thumbnail { - display: inline-block; - max-width: 100%; - height: auto; - padding: 4px; - line-height: 1.42857143; - background-color: #fff; - border: 1px solid #ddd; - border-radius: 4px; - -webkit-transition: all .2s ease-in-out; - -o-transition: all .2s ease-in-out; - transition: all .2s ease-in-out; -} -.img-circle { - border-radius: 50%; -} -hr { - margin-top: 20px; - margin-bottom: 20px; - border: 0; - border-top: 1px solid #eee; -} -.sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - border: 0; -} -.sr-only-focusable:active, -.sr-only-focusable:focus { - position: static; - width: auto; - height: auto; - margin: 0; - overflow: visible; - clip: auto; -} -[role="button"] { - cursor: pointer; -} -h1, -h2, -h3, -h4, -h5, -h6, -.h1, -.h2, -.h3, -.h4, -.h5, -.h6 { - font-family: inherit; - font-weight: 500; - line-height: 1.1; - color: inherit; -} -h1 small, -h2 small, -h3 small, -h4 small, -h5 small, -h6 small, -.h1 small, -.h2 small, -.h3 small, -.h4 small, -.h5 small, -.h6 small, -h1 .small, -h2 .small, -h3 .small, -h4 .small, -h5 .small, -h6 .small, -.h1 .small, -.h2 .small, -.h3 .small, -.h4 .small, -.h5 .small, -.h6 .small { - font-weight: normal; - line-height: 1; - color: #777; -} -h1, -.h1, -h2, -.h2, -h3, -.h3 { - margin-top: 20px; - margin-bottom: 10px; -} -h1 small, -.h1 small, -h2 small, -.h2 small, -h3 small, -.h3 small, -h1 .small, -.h1 .small, -h2 .small, -.h2 .small, -h3 .small, -.h3 .small { - font-size: 65%; -} -h4, -.h4, -h5, -.h5, -h6, -.h6 { - margin-top: 10px; - margin-bottom: 10px; -} -h4 small, -.h4 small, -h5 small, -.h5 small, -h6 small, -.h6 small, -h4 .small, -.h4 .small, -h5 .small, -.h5 .small, -h6 .small, -.h6 .small { - font-size: 75%; -} -h1, -.h1 { - font-size: 36px; -} -h2, -.h2 { - font-size: 30px; -} -h3, -.h3 { - font-size: 24px; -} -h4, -.h4 { - font-size: 18px; -} -h5, -.h5 { - font-size: 14px; -} -h6, -.h6 { - font-size: 12px; -} -p { - margin: 0 0 10px; -} -.lead { - margin-bottom: 20px; - font-size: 16px; - font-weight: 300; - line-height: 1.4; -} -@media (min-width: 768px) { - .lead { - font-size: 21px; - } -} -small, -.small { - font-size: 85%; -} -mark, -.mark { - padding: .2em; - background-color: #fcf8e3; -} -.text-left { - text-align: left; -} -.text-right { - text-align: right; -} -.text-center { - text-align: center; -} -.text-justify { - text-align: justify; -} -.text-nowrap { - white-space: nowrap; -} -.text-lowercase { - text-transform: lowercase; -} -.text-uppercase { - text-transform: uppercase; -} -.text-capitalize { - text-transform: capitalize; -} -.text-muted { - color: #777; -} -.text-primary { - color: #337ab7; -} -a.text-primary:hover, -a.text-primary:focus { - color: #286090; -} -.text-success { - color: #3c763d; -} -a.text-success:hover, -a.text-success:focus { - color: #2b542c; -} -.text-info { - color: #31708f; -} -a.text-info:hover, -a.text-info:focus { - color: #245269; -} -.text-warning { - color: #8a6d3b; -} -a.text-warning:hover, -a.text-warning:focus { - color: #66512c; -} -.text-danger { - color: #a94442; -} -a.text-danger:hover, -a.text-danger:focus { - color: #843534; -} -.bg-primary { - color: #fff; - background-color: #337ab7; -} -a.bg-primary:hover, -a.bg-primary:focus { - background-color: #286090; -} -.bg-success { - background-color: #dff0d8; -} -a.bg-success:hover, -a.bg-success:focus { - background-color: #c1e2b3; -} -.bg-info { - background-color: #d9edf7; -} -a.bg-info:hover, -a.bg-info:focus { - background-color: #afd9ee; -} -.bg-warning { - background-color: #fcf8e3; -} -a.bg-warning:hover, -a.bg-warning:focus { - background-color: #f7ecb5; -} -.bg-danger { - background-color: #f2dede; -} -a.bg-danger:hover, -a.bg-danger:focus { - background-color: #e4b9b9; -} -.page-header { - padding-bottom: 9px; - margin: 40px 0 20px; - border-bottom: 1px solid #eee; -} -ul, -ol { - margin-top: 0; - margin-bottom: 10px; -} -ul ul, -ol ul, -ul ol, -ol ol { - margin-bottom: 0; -} -.list-unstyled { - padding-left: 0; - list-style: none; -} -.list-inline { - padding-left: 0; - margin-left: -5px; - list-style: none; -} -.list-inline > li { - display: inline-block; - padding-right: 5px; - padding-left: 5px; -} -dl { - margin-top: 0; - margin-bottom: 20px; -} -dt, -dd { - line-height: 1.42857143; -} -dt { - font-weight: bold; -} -dd { - margin-left: 0; -} -@media (min-width: 768px) { - .dl-horizontal dt { - float: left; - width: 160px; - overflow: hidden; - clear: left; - text-align: right; - text-overflow: ellipsis; - white-space: nowrap; - } - .dl-horizontal dd { - margin-left: 180px; - } -} -abbr[title], -abbr[data-original-title] { - cursor: help; - border-bottom: 1px dotted #777; -} -.initialism { - font-size: 90%; - text-transform: uppercase; -} -blockquote { - padding: 10px 20px; - margin: 0 0 20px; - font-size: 17.5px; - border-left: 5px solid #eee; -} -blockquote p:last-child, -blockquote ul:last-child, -blockquote ol:last-child { - margin-bottom: 0; -} -blockquote footer, -blockquote small, -blockquote .small { - display: block; - font-size: 80%; - line-height: 1.42857143; - color: #777; -} -blockquote footer:before, -blockquote small:before, -blockquote .small:before { - content: '\2014 \00A0'; -} -.blockquote-reverse, -blockquote.pull-right { - padding-right: 15px; - padding-left: 0; - text-align: right; - border-right: 5px solid #eee; - border-left: 0; -} -.blockquote-reverse footer:before, -blockquote.pull-right footer:before, -.blockquote-reverse small:before, -blockquote.pull-right small:before, -.blockquote-reverse .small:before, -blockquote.pull-right .small:before { - content: ''; -} -.blockquote-reverse footer:after, -blockquote.pull-right footer:after, -.blockquote-reverse small:after, -blockquote.pull-right small:after, -.blockquote-reverse .small:after, -blockquote.pull-right .small:after { - content: '\00A0 \2014'; -} -address { - margin-bottom: 20px; - font-style: normal; - line-height: 1.42857143; -} -code, -kbd, -pre, -samp { - font-family: Menlo, Monaco, Consolas, "Courier New", monospace; -} -code { - padding: 2px 4px; - font-size: 90%; - color: #c7254e; - background-color: #f9f2f4; - border-radius: 4px; -} -kbd { - padding: 2px 4px; - font-size: 90%; - color: #fff; - background-color: #333; - border-radius: 3px; - -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); - box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); -} -kbd kbd { - padding: 0; - font-size: 100%; - font-weight: bold; - -webkit-box-shadow: none; - box-shadow: none; -} -pre { - display: block; - padding: 9.5px; - margin: 0 0 10px; - font-size: 13px; - line-height: 1.42857143; - color: #333; - word-break: break-all; - word-wrap: break-word; - background-color: #f5f5f5; - border: 1px solid #ccc; - border-radius: 4px; -} -pre code { - padding: 0; - font-size: inherit; - color: inherit; - white-space: pre-wrap; - background-color: transparent; - border-radius: 0; -} -.pre-scrollable { - max-height: 340px; - overflow-y: scroll; -} -.container { - padding-right: 15px; - padding-left: 15px; - margin-right: auto; - margin-left: auto; -} -@media (min-width: 768px) { - .container { - width: 750px; - } -} -@media (min-width: 992px) { - .container { - width: 970px; - } -} -@media (min-width: 1200px) { - .container { - width: 1170px; - } -} -.container-fluid { - padding-right: 15px; - padding-left: 15px; - margin-right: auto; - margin-left: auto; -} -.row { - margin-right: -15px; - margin-left: -15px; -} -.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { - position: relative; - min-height: 1px; - padding-right: 15px; - padding-left: 15px; -} -.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { - float: left; -} -.col-xs-12 { - width: 100%; -} -.col-xs-11 { - width: 91.66666667%; -} -.col-xs-10 { - width: 83.33333333%; -} -.col-xs-9 { - width: 75%; -} -.col-xs-8 { - width: 66.66666667%; -} -.col-xs-7 { - width: 58.33333333%; -} -.col-xs-6 { - width: 50%; -} -.col-xs-5 { - width: 41.66666667%; -} -.col-xs-4 { - width: 33.33333333%; -} -.col-xs-3 { - width: 25%; -} -.col-xs-2 { - width: 16.66666667%; -} -.col-xs-1 { - width: 8.33333333%; -} -.col-xs-pull-12 { - right: 100%; -} -.col-xs-pull-11 { - right: 91.66666667%; -} -.col-xs-pull-10 { - right: 83.33333333%; -} -.col-xs-pull-9 { - right: 75%; -} -.col-xs-pull-8 { - right: 66.66666667%; -} -.col-xs-pull-7 { - right: 58.33333333%; -} -.col-xs-pull-6 { - right: 50%; -} -.col-xs-pull-5 { - right: 41.66666667%; -} -.col-xs-pull-4 { - right: 33.33333333%; -} -.col-xs-pull-3 { - right: 25%; -} -.col-xs-pull-2 { - right: 16.66666667%; -} -.col-xs-pull-1 { - right: 8.33333333%; -} -.col-xs-pull-0 { - right: auto; -} -.col-xs-push-12 { - left: 100%; -} -.col-xs-push-11 { - left: 91.66666667%; -} -.col-xs-push-10 { - left: 83.33333333%; -} -.col-xs-push-9 { - left: 75%; -} -.col-xs-push-8 { - left: 66.66666667%; -} -.col-xs-push-7 { - left: 58.33333333%; -} -.col-xs-push-6 { - left: 50%; -} -.col-xs-push-5 { - left: 41.66666667%; -} -.col-xs-push-4 { - left: 33.33333333%; -} -.col-xs-push-3 { - left: 25%; -} -.col-xs-push-2 { - left: 16.66666667%; -} -.col-xs-push-1 { - left: 8.33333333%; -} -.col-xs-push-0 { - left: auto; -} -.col-xs-offset-12 { - margin-left: 100%; -} -.col-xs-offset-11 { - margin-left: 91.66666667%; -} -.col-xs-offset-10 { - margin-left: 83.33333333%; -} -.col-xs-offset-9 { - margin-left: 75%; -} -.col-xs-offset-8 { - margin-left: 66.66666667%; -} -.col-xs-offset-7 { - margin-left: 58.33333333%; -} -.col-xs-offset-6 { - margin-left: 50%; -} -.col-xs-offset-5 { - margin-left: 41.66666667%; -} -.col-xs-offset-4 { - margin-left: 33.33333333%; -} -.col-xs-offset-3 { - margin-left: 25%; -} -.col-xs-offset-2 { - margin-left: 16.66666667%; -} -.col-xs-offset-1 { - margin-left: 8.33333333%; -} -.col-xs-offset-0 { - margin-left: 0; -} -@media (min-width: 768px) { - .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { - float: left; - } - .col-sm-12 { - width: 100%; - } - .col-sm-11 { - width: 91.66666667%; - } - .col-sm-10 { - width: 83.33333333%; - } - .col-sm-9 { - width: 75%; - } - .col-sm-8 { - width: 66.66666667%; - } - .col-sm-7 { - width: 58.33333333%; - } - .col-sm-6 { - width: 50%; - } - .col-sm-5 { - width: 41.66666667%; - } - .col-sm-4 { - width: 33.33333333%; - } - .col-sm-3 { - width: 25%; - } - .col-sm-2 { - width: 16.66666667%; - } - .col-sm-1 { - width: 8.33333333%; - } - .col-sm-pull-12 { - right: 100%; - } - .col-sm-pull-11 { - right: 91.66666667%; - } - .col-sm-pull-10 { - right: 83.33333333%; - } - .col-sm-pull-9 { - right: 75%; - } - .col-sm-pull-8 { - right: 66.66666667%; - } - .col-sm-pull-7 { - right: 58.33333333%; - } - .col-sm-pull-6 { - right: 50%; - } - .col-sm-pull-5 { - right: 41.66666667%; - } - .col-sm-pull-4 { - right: 33.33333333%; - } - .col-sm-pull-3 { - right: 25%; - } - .col-sm-pull-2 { - right: 16.66666667%; - } - .col-sm-pull-1 { - right: 8.33333333%; - } - .col-sm-pull-0 { - right: auto; - } - .col-sm-push-12 { - left: 100%; - } - .col-sm-push-11 { - left: 91.66666667%; - } - .col-sm-push-10 { - left: 83.33333333%; - } - .col-sm-push-9 { - left: 75%; - } - .col-sm-push-8 { - left: 66.66666667%; - } - .col-sm-push-7 { - left: 58.33333333%; - } - .col-sm-push-6 { - left: 50%; - } - .col-sm-push-5 { - left: 41.66666667%; - } - .col-sm-push-4 { - left: 33.33333333%; - } - .col-sm-push-3 { - left: 25%; - } - .col-sm-push-2 { - left: 16.66666667%; - } - .col-sm-push-1 { - left: 8.33333333%; - } - .col-sm-push-0 { - left: auto; - } - .col-sm-offset-12 { - margin-left: 100%; - } - .col-sm-offset-11 { - margin-left: 91.66666667%; - } - .col-sm-offset-10 { - margin-left: 83.33333333%; - } - .col-sm-offset-9 { - margin-left: 75%; - } - .col-sm-offset-8 { - margin-left: 66.66666667%; - } - .col-sm-offset-7 { - margin-left: 58.33333333%; - } - .col-sm-offset-6 { - margin-left: 50%; - } - .col-sm-offset-5 { - margin-left: 41.66666667%; - } - .col-sm-offset-4 { - margin-left: 33.33333333%; - } - .col-sm-offset-3 { - margin-left: 25%; - } - .col-sm-offset-2 { - margin-left: 16.66666667%; - } - .col-sm-offset-1 { - margin-left: 8.33333333%; - } - .col-sm-offset-0 { - margin-left: 0; - } -} -@media (min-width: 992px) { - .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { - float: left; - } - .col-md-12 { - width: 100%; - } - .col-md-11 { - width: 91.66666667%; - } - .col-md-10 { - width: 83.33333333%; - } - .col-md-9 { - width: 75%; - } - .col-md-8 { - width: 66.66666667%; - } - .col-md-7 { - width: 58.33333333%; - } - .col-md-6 { - width: 50%; - } - .col-md-5 { - width: 41.66666667%; - } - .col-md-4 { - width: 33.33333333%; - } - .col-md-3 { - width: 25%; - } - .col-md-2 { - width: 16.66666667%; - } - .col-md-1 { - width: 8.33333333%; - } - .col-md-pull-12 { - right: 100%; - } - .col-md-pull-11 { - right: 91.66666667%; - } - .col-md-pull-10 { - right: 83.33333333%; - } - .col-md-pull-9 { - right: 75%; - } - .col-md-pull-8 { - right: 66.66666667%; - } - .col-md-pull-7 { - right: 58.33333333%; - } - .col-md-pull-6 { - right: 50%; - } - .col-md-pull-5 { - right: 41.66666667%; - } - .col-md-pull-4 { - right: 33.33333333%; - } - .col-md-pull-3 { - right: 25%; - } - .col-md-pull-2 { - right: 16.66666667%; - } - .col-md-pull-1 { - right: 8.33333333%; - } - .col-md-pull-0 { - right: auto; - } - .col-md-push-12 { - left: 100%; - } - .col-md-push-11 { - left: 91.66666667%; - } - .col-md-push-10 { - left: 83.33333333%; - } - .col-md-push-9 { - left: 75%; - } - .col-md-push-8 { - left: 66.66666667%; - } - .col-md-push-7 { - left: 58.33333333%; - } - .col-md-push-6 { - left: 50%; - } - .col-md-push-5 { - left: 41.66666667%; - } - .col-md-push-4 { - left: 33.33333333%; - } - .col-md-push-3 { - left: 25%; - } - .col-md-push-2 { - left: 16.66666667%; - } - .col-md-push-1 { - left: 8.33333333%; - } - .col-md-push-0 { - left: auto; - } - .col-md-offset-12 { - margin-left: 100%; - } - .col-md-offset-11 { - margin-left: 91.66666667%; - } - .col-md-offset-10 { - margin-left: 83.33333333%; - } - .col-md-offset-9 { - margin-left: 75%; - } - .col-md-offset-8 { - margin-left: 66.66666667%; - } - .col-md-offset-7 { - margin-left: 58.33333333%; - } - .col-md-offset-6 { - margin-left: 50%; - } - .col-md-offset-5 { - margin-left: 41.66666667%; - } - .col-md-offset-4 { - margin-left: 33.33333333%; - } - .col-md-offset-3 { - margin-left: 25%; - } - .col-md-offset-2 { - margin-left: 16.66666667%; - } - .col-md-offset-1 { - margin-left: 8.33333333%; - } - .col-md-offset-0 { - margin-left: 0; - } -} -@media (min-width: 1200px) { - .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { - float: left; - } - .col-lg-12 { - width: 100%; - } - .col-lg-11 { - width: 91.66666667%; - } - .col-lg-10 { - width: 83.33333333%; - } - .col-lg-9 { - width: 75%; - } - .col-lg-8 { - width: 66.66666667%; - } - .col-lg-7 { - width: 58.33333333%; - } - .col-lg-6 { - width: 50%; - } - .col-lg-5 { - width: 41.66666667%; - } - .col-lg-4 { - width: 33.33333333%; - } - .col-lg-3 { - width: 25%; - } - .col-lg-2 { - width: 16.66666667%; - } - .col-lg-1 { - width: 8.33333333%; - } - .col-lg-pull-12 { - right: 100%; - } - .col-lg-pull-11 { - right: 91.66666667%; - } - .col-lg-pull-10 { - right: 83.33333333%; - } - .col-lg-pull-9 { - right: 75%; - } - .col-lg-pull-8 { - right: 66.66666667%; - } - .col-lg-pull-7 { - right: 58.33333333%; - } - .col-lg-pull-6 { - right: 50%; - } - .col-lg-pull-5 { - right: 41.66666667%; - } - .col-lg-pull-4 { - right: 33.33333333%; - } - .col-lg-pull-3 { - right: 25%; - } - .col-lg-pull-2 { - right: 16.66666667%; - } - .col-lg-pull-1 { - right: 8.33333333%; - } - .col-lg-pull-0 { - right: auto; - } - .col-lg-push-12 { - left: 100%; - } - .col-lg-push-11 { - left: 91.66666667%; - } - .col-lg-push-10 { - left: 83.33333333%; - } - .col-lg-push-9 { - left: 75%; - } - .col-lg-push-8 { - left: 66.66666667%; - } - .col-lg-push-7 { - left: 58.33333333%; - } - .col-lg-push-6 { - left: 50%; - } - .col-lg-push-5 { - left: 41.66666667%; - } - .col-lg-push-4 { - left: 33.33333333%; - } - .col-lg-push-3 { - left: 25%; - } - .col-lg-push-2 { - left: 16.66666667%; - } - .col-lg-push-1 { - left: 8.33333333%; - } - .col-lg-push-0 { - left: auto; - } - .col-lg-offset-12 { - margin-left: 100%; - } - .col-lg-offset-11 { - margin-left: 91.66666667%; - } - .col-lg-offset-10 { - margin-left: 83.33333333%; - } - .col-lg-offset-9 { - margin-left: 75%; - } - .col-lg-offset-8 { - margin-left: 66.66666667%; - } - .col-lg-offset-7 { - margin-left: 58.33333333%; - } - .col-lg-offset-6 { - margin-left: 50%; - } - .col-lg-offset-5 { - margin-left: 41.66666667%; - } - .col-lg-offset-4 { - margin-left: 33.33333333%; - } - .col-lg-offset-3 { - margin-left: 25%; - } - .col-lg-offset-2 { - margin-left: 16.66666667%; - } - .col-lg-offset-1 { - margin-left: 8.33333333%; - } - .col-lg-offset-0 { - margin-left: 0; - } -} -table { - background-color: transparent; -} -caption { - padding-top: 8px; - padding-bottom: 8px; - color: #777; - text-align: left; -} -th { - text-align: left; -} -.table { - width: 100%; - max-width: 100%; - margin-bottom: 20px; -} -.table > thead > tr > th, -.table > tbody > tr > th, -.table > tfoot > tr > th, -.table > thead > tr > td, -.table > tbody > tr > td, -.table > tfoot > tr > td { - padding: 8px; - line-height: 1.42857143; - vertical-align: top; - border-top: 1px solid #ddd; -} -.table > thead > tr > th { - vertical-align: bottom; - border-bottom: 2px solid #ddd; -} -.table > caption + thead > tr:first-child > th, -.table > colgroup + thead > tr:first-child > th, -.table > thead:first-child > tr:first-child > th, -.table > caption + thead > tr:first-child > td, -.table > colgroup + thead > tr:first-child > td, -.table > thead:first-child > tr:first-child > td { - border-top: 0; -} -.table > tbody + tbody { - border-top: 2px solid #ddd; -} -.table .table { - background-color: #fff; -} -.table-condensed > thead > tr > th, -.table-condensed > tbody > tr > th, -.table-condensed > tfoot > tr > th, -.table-condensed > thead > tr > td, -.table-condensed > tbody > tr > td, -.table-condensed > tfoot > tr > td { - padding: 5px; -} -.table-bordered { - border: 1px solid #ddd; -} -.table-bordered > thead > tr > th, -.table-bordered > tbody > tr > th, -.table-bordered > tfoot > tr > th, -.table-bordered > thead > tr > td, -.table-bordered > tbody > tr > td, -.table-bordered > tfoot > tr > td { - border: 1px solid #ddd; -} -.table-bordered > thead > tr > th, -.table-bordered > thead > tr > td { - border-bottom-width: 2px; -} -.table-striped > tbody > tr:nth-of-type(odd) { - background-color: #f9f9f9; -} -.table-hover > tbody > tr:hover { - background-color: #f5f5f5; -} -table col[class*="col-"] { - position: static; - display: table-column; - float: none; -} -table td[class*="col-"], -table th[class*="col-"] { - position: static; - display: table-cell; - float: none; -} -.table > thead > tr > td.active, -.table > tbody > tr > td.active, -.table > tfoot > tr > td.active, -.table > thead > tr > th.active, -.table > tbody > tr > th.active, -.table > tfoot > tr > th.active, -.table > thead > tr.active > td, -.table > tbody > tr.active > td, -.table > tfoot > tr.active > td, -.table > thead > tr.active > th, -.table > tbody > tr.active > th, -.table > tfoot > tr.active > th { - background-color: #f5f5f5; -} -.table-hover > tbody > tr > td.active:hover, -.table-hover > tbody > tr > th.active:hover, -.table-hover > tbody > tr.active:hover > td, -.table-hover > tbody > tr:hover > .active, -.table-hover > tbody > tr.active:hover > th { - background-color: #e8e8e8; -} -.table > thead > tr > td.success, -.table > tbody > tr > td.success, -.table > tfoot > tr > td.success, -.table > thead > tr > th.success, -.table > tbody > tr > th.success, -.table > tfoot > tr > th.success, -.table > thead > tr.success > td, -.table > tbody > tr.success > td, -.table > tfoot > tr.success > td, -.table > thead > tr.success > th, -.table > tbody > tr.success > th, -.table > tfoot > tr.success > th { - background-color: #dff0d8; -} -.table-hover > tbody > tr > td.success:hover, -.table-hover > tbody > tr > th.success:hover, -.table-hover > tbody > tr.success:hover > td, -.table-hover > tbody > tr:hover > .success, -.table-hover > tbody > tr.success:hover > th { - background-color: #d0e9c6; -} -.table > thead > tr > td.info, -.table > tbody > tr > td.info, -.table > tfoot > tr > td.info, -.table > thead > tr > th.info, -.table > tbody > tr > th.info, -.table > tfoot > tr > th.info, -.table > thead > tr.info > td, -.table > tbody > tr.info > td, -.table > tfoot > tr.info > td, -.table > thead > tr.info > th, -.table > tbody > tr.info > th, -.table > tfoot > tr.info > th { - background-color: #d9edf7; -} -.table-hover > tbody > tr > td.info:hover, -.table-hover > tbody > tr > th.info:hover, -.table-hover > tbody > tr.info:hover > td, -.table-hover > tbody > tr:hover > .info, -.table-hover > tbody > tr.info:hover > th { - background-color: #c4e3f3; -} -.table > thead > tr > td.warning, -.table > tbody > tr > td.warning, -.table > tfoot > tr > td.warning, -.table > thead > tr > th.warning, -.table > tbody > tr > th.warning, -.table > tfoot > tr > th.warning, -.table > thead > tr.warning > td, -.table > tbody > tr.warning > td, -.table > tfoot > tr.warning > td, -.table > thead > tr.warning > th, -.table > tbody > tr.warning > th, -.table > tfoot > tr.warning > th { - background-color: #fcf8e3; -} -.table-hover > tbody > tr > td.warning:hover, -.table-hover > tbody > tr > th.warning:hover, -.table-hover > tbody > tr.warning:hover > td, -.table-hover > tbody > tr:hover > .warning, -.table-hover > tbody > tr.warning:hover > th { - background-color: #faf2cc; -} -.table > thead > tr > td.danger, -.table > tbody > tr > td.danger, -.table > tfoot > tr > td.danger, -.table > thead > tr > th.danger, -.table > tbody > tr > th.danger, -.table > tfoot > tr > th.danger, -.table > thead > tr.danger > td, -.table > tbody > tr.danger > td, -.table > tfoot > tr.danger > td, -.table > thead > tr.danger > th, -.table > tbody > tr.danger > th, -.table > tfoot > tr.danger > th { - background-color: #f2dede; -} -.table-hover > tbody > tr > td.danger:hover, -.table-hover > tbody > tr > th.danger:hover, -.table-hover > tbody > tr.danger:hover > td, -.table-hover > tbody > tr:hover > .danger, -.table-hover > tbody > tr.danger:hover > th { - background-color: #ebcccc; -} -.table-responsive { - min-height: .01%; - overflow-x: auto; -} -@media screen and (max-width: 767px) { - .table-responsive { - width: 100%; - margin-bottom: 15px; - overflow-y: hidden; - -ms-overflow-style: -ms-autohiding-scrollbar; - border: 1px solid #ddd; - } - .table-responsive > .table { - margin-bottom: 0; - } - .table-responsive > .table > thead > tr > th, - .table-responsive > .table > tbody > tr > th, - .table-responsive > .table > tfoot > tr > th, - .table-responsive > .table > thead > tr > td, - .table-responsive > .table > tbody > tr > td, - .table-responsive > .table > tfoot > tr > td { - white-space: nowrap; - } - .table-responsive > .table-bordered { - border: 0; - } - .table-responsive > .table-bordered > thead > tr > th:first-child, - .table-responsive > .table-bordered > tbody > tr > th:first-child, - .table-responsive > .table-bordered > tfoot > tr > th:first-child, - .table-responsive > .table-bordered > thead > tr > td:first-child, - .table-responsive > .table-bordered > tbody > tr > td:first-child, - .table-responsive > .table-bordered > tfoot > tr > td:first-child { - border-left: 0; - } - .table-responsive > .table-bordered > thead > tr > th:last-child, - .table-responsive > .table-bordered > tbody > tr > th:last-child, - .table-responsive > .table-bordered > tfoot > tr > th:last-child, - .table-responsive > .table-bordered > thead > tr > td:last-child, - .table-responsive > .table-bordered > tbody > tr > td:last-child, - .table-responsive > .table-bordered > tfoot > tr > td:last-child { - border-right: 0; - } - .table-responsive > .table-bordered > tbody > tr:last-child > th, - .table-responsive > .table-bordered > tfoot > tr:last-child > th, - .table-responsive > .table-bordered > tbody > tr:last-child > td, - .table-responsive > .table-bordered > tfoot > tr:last-child > td { - border-bottom: 0; - } -} -fieldset { - min-width: 0; - padding: 0; - margin: 0; - border: 0; -} -legend { - display: block; - width: 100%; - padding: 0; - margin-bottom: 20px; - font-size: 21px; - line-height: inherit; - color: #333; - border: 0; - border-bottom: 1px solid #e5e5e5; -} -label { - display: inline-block; - max-width: 100%; - margin-bottom: 5px; - font-weight: bold; -} -input[type="search"] { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} -input[type="radio"], -input[type="checkbox"] { - margin: 4px 0 0; - margin-top: 1px \9; - line-height: normal; -} -input[type="file"] { - display: block; -} -input[type="range"] { - display: block; - width: 100%; -} -select[multiple], -select[size] { - height: auto; -} -input[type="file"]:focus, -input[type="radio"]:focus, -input[type="checkbox"]:focus { - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} -output { - display: block; - padding-top: 7px; - font-size: 14px; - line-height: 1.42857143; - color: #555; -} -.form-control { - display: block; - width: 100%; - height: 34px; - padding: 6px 12px; - font-size: 14px; - line-height: 1.42857143; - color: #555; - background-color: #fff; - background-image: none; - border: 1px solid #ccc; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; - -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; - transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; -} -.form-control:focus { - border-color: #66afe9; - outline: 0; - -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); - box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); -} -.form-control::-moz-placeholder { - color: #999; - opacity: 1; -} -.form-control:-ms-input-placeholder { - color: #999; -} -.form-control::-webkit-input-placeholder { - color: #999; -} -.form-control::-ms-expand { - background-color: transparent; - border: 0; -} -.form-control[disabled], -.form-control[readonly], -fieldset[disabled] .form-control { - background-color: #eee; - opacity: 1; -} -.form-control[disabled], -fieldset[disabled] .form-control { - cursor: not-allowed; -} -textarea.form-control { - height: auto; -} -input[type="search"] { - -webkit-appearance: none; -} -@media screen and (-webkit-min-device-pixel-ratio: 0) { - input[type="date"].form-control, - input[type="time"].form-control, - input[type="datetime-local"].form-control, - input[type="month"].form-control { - line-height: 34px; - } - input[type="date"].input-sm, - input[type="time"].input-sm, - input[type="datetime-local"].input-sm, - input[type="month"].input-sm, - .input-group-sm input[type="date"], - .input-group-sm input[type="time"], - .input-group-sm input[type="datetime-local"], - .input-group-sm input[type="month"] { - line-height: 30px; - } - input[type="date"].input-lg, - input[type="time"].input-lg, - input[type="datetime-local"].input-lg, - input[type="month"].input-lg, - .input-group-lg input[type="date"], - .input-group-lg input[type="time"], - .input-group-lg input[type="datetime-local"], - .input-group-lg input[type="month"] { - line-height: 46px; - } -} -.form-group { - margin-bottom: 15px; -} -.radio, -.checkbox { - position: relative; - display: block; - margin-top: 10px; - margin-bottom: 10px; -} -.radio label, -.checkbox label { - min-height: 20px; - padding-left: 20px; - margin-bottom: 0; - font-weight: normal; - cursor: pointer; -} -.radio input[type="radio"], -.radio-inline input[type="radio"], -.checkbox input[type="checkbox"], -.checkbox-inline input[type="checkbox"] { - position: absolute; - margin-top: 4px \9; - margin-left: -20px; -} -.radio + .radio, -.checkbox + .checkbox { - margin-top: -5px; -} -.radio-inline, -.checkbox-inline { - position: relative; - display: inline-block; - padding-left: 20px; - margin-bottom: 0; - font-weight: normal; - vertical-align: middle; - cursor: pointer; -} -.radio-inline + .radio-inline, -.checkbox-inline + .checkbox-inline { - margin-top: 0; - margin-left: 10px; -} -input[type="radio"][disabled], -input[type="checkbox"][disabled], -input[type="radio"].disabled, -input[type="checkbox"].disabled, -fieldset[disabled] input[type="radio"], -fieldset[disabled] input[type="checkbox"] { - cursor: not-allowed; -} -.radio-inline.disabled, -.checkbox-inline.disabled, -fieldset[disabled] .radio-inline, -fieldset[disabled] .checkbox-inline { - cursor: not-allowed; -} -.radio.disabled label, -.checkbox.disabled label, -fieldset[disabled] .radio label, -fieldset[disabled] .checkbox label { - cursor: not-allowed; -} -.form-control-static { - min-height: 34px; - padding-top: 7px; - padding-bottom: 7px; - margin-bottom: 0; -} -.form-control-static.input-lg, -.form-control-static.input-sm { - padding-right: 0; - padding-left: 0; -} -.input-sm { - height: 30px; - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} -select.input-sm { - height: 30px; - line-height: 30px; -} -textarea.input-sm, -select[multiple].input-sm { - height: auto; -} -.form-group-sm .form-control { - height: 30px; - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} -.form-group-sm select.form-control { - height: 30px; - line-height: 30px; -} -.form-group-sm textarea.form-control, -.form-group-sm select[multiple].form-control { - height: auto; -} -.form-group-sm .form-control-static { - height: 30px; - min-height: 32px; - padding: 6px 10px; - font-size: 12px; - line-height: 1.5; -} -.input-lg { - height: 46px; - padding: 10px 16px; - font-size: 18px; - line-height: 1.3333333; - border-radius: 6px; -} -select.input-lg { - height: 46px; - line-height: 46px; -} -textarea.input-lg, -select[multiple].input-lg { - height: auto; -} -.form-group-lg .form-control { - height: 46px; - padding: 10px 16px; - font-size: 18px; - line-height: 1.3333333; - border-radius: 6px; -} -.form-group-lg select.form-control { - height: 46px; - line-height: 46px; -} -.form-group-lg textarea.form-control, -.form-group-lg select[multiple].form-control { - height: auto; -} -.form-group-lg .form-control-static { - height: 46px; - min-height: 38px; - padding: 11px 16px; - font-size: 18px; - line-height: 1.3333333; -} -.has-feedback { - position: relative; -} -.has-feedback .form-control { - padding-right: 42.5px; -} -.form-control-feedback { - position: absolute; - top: 0; - right: 0; - z-index: 2; - display: block; - width: 34px; - height: 34px; - line-height: 34px; - text-align: center; - pointer-events: none; -} -.input-lg + .form-control-feedback, -.input-group-lg + .form-control-feedback, -.form-group-lg .form-control + .form-control-feedback { - width: 46px; - height: 46px; - line-height: 46px; -} -.input-sm + .form-control-feedback, -.input-group-sm + .form-control-feedback, -.form-group-sm .form-control + .form-control-feedback { - width: 30px; - height: 30px; - line-height: 30px; -} -.has-success .help-block, -.has-success .control-label, -.has-success .radio, -.has-success .checkbox, -.has-success .radio-inline, -.has-success .checkbox-inline, -.has-success.radio label, -.has-success.checkbox label, -.has-success.radio-inline label, -.has-success.checkbox-inline label { - color: #3c763d; -} -.has-success .form-control { - border-color: #3c763d; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); -} -.has-success .form-control:focus { - border-color: #2b542c; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; -} -.has-success .input-group-addon { - color: #3c763d; - background-color: #dff0d8; - border-color: #3c763d; -} -.has-success .form-control-feedback { - color: #3c763d; -} -.has-warning .help-block, -.has-warning .control-label, -.has-warning .radio, -.has-warning .checkbox, -.has-warning .radio-inline, -.has-warning .checkbox-inline, -.has-warning.radio label, -.has-warning.checkbox label, -.has-warning.radio-inline label, -.has-warning.checkbox-inline label { - color: #8a6d3b; -} -.has-warning .form-control { - border-color: #8a6d3b; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); -} -.has-warning .form-control:focus { - border-color: #66512c; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; -} -.has-warning .input-group-addon { - color: #8a6d3b; - background-color: #fcf8e3; - border-color: #8a6d3b; -} -.has-warning .form-control-feedback { - color: #8a6d3b; -} -.has-error .help-block, -.has-error .control-label, -.has-error .radio, -.has-error .checkbox, -.has-error .radio-inline, -.has-error .checkbox-inline, -.has-error.radio label, -.has-error.checkbox label, -.has-error.radio-inline label, -.has-error.checkbox-inline label { - color: #a94442; -} -.has-error .form-control { - border-color: #a94442; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); -} -.has-error .form-control:focus { - border-color: #843534; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; -} -.has-error .input-group-addon { - color: #a94442; - background-color: #f2dede; - border-color: #a94442; -} -.has-error .form-control-feedback { - color: #a94442; -} -.has-feedback label ~ .form-control-feedback { - top: 25px; -} -.has-feedback label.sr-only ~ .form-control-feedback { - top: 0; -} -.help-block { - display: block; - margin-top: 5px; - margin-bottom: 10px; - color: #737373; -} -@media (min-width: 768px) { - .form-inline .form-group { - display: inline-block; - margin-bottom: 0; - vertical-align: middle; - } - .form-inline .form-control { - display: inline-block; - width: auto; - vertical-align: middle; - } - .form-inline .form-control-static { - display: inline-block; - } - .form-inline .input-group { - display: inline-table; - vertical-align: middle; - } - .form-inline .input-group .input-group-addon, - .form-inline .input-group .input-group-btn, - .form-inline .input-group .form-control { - width: auto; - } - .form-inline .input-group > .form-control { - width: 100%; - } - .form-inline .control-label { - margin-bottom: 0; - vertical-align: middle; - } - .form-inline .radio, - .form-inline .checkbox { - display: inline-block; - margin-top: 0; - margin-bottom: 0; - vertical-align: middle; - } - .form-inline .radio label, - .form-inline .checkbox label { - padding-left: 0; - } - .form-inline .radio input[type="radio"], - .form-inline .checkbox input[type="checkbox"] { - position: relative; - margin-left: 0; - } - .form-inline .has-feedback .form-control-feedback { - top: 0; - } -} -.form-horizontal .radio, -.form-horizontal .checkbox, -.form-horizontal .radio-inline, -.form-horizontal .checkbox-inline { - padding-top: 7px; - margin-top: 0; - margin-bottom: 0; -} -.form-horizontal .radio, -.form-horizontal .checkbox { - min-height: 27px; -} -.form-horizontal .form-group { - margin-right: -15px; - margin-left: -15px; -} -@media (min-width: 768px) { - .form-horizontal .control-label { - padding-top: 7px; - margin-bottom: 0; - text-align: right; - } -} -.form-horizontal .has-feedback .form-control-feedback { - right: 15px; -} -@media (min-width: 768px) { - .form-horizontal .form-group-lg .control-label { - padding-top: 11px; - font-size: 18px; - } -} -@media (min-width: 768px) { - .form-horizontal .form-group-sm .control-label { - padding-top: 6px; - font-size: 12px; - } -} -.btn { - display: inline-block; - padding: 6px 12px; - margin-bottom: 0; - font-size: 14px; - font-weight: normal; - line-height: 1.42857143; - text-align: center; - white-space: nowrap; - vertical-align: middle; - -ms-touch-action: manipulation; - touch-action: manipulation; - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - background-image: none; - border: 1px solid transparent; - border-radius: 4px; -} -.btn:focus, -.btn:active:focus, -.btn.active:focus, -.btn.focus, -.btn:active.focus, -.btn.active.focus { - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} -.btn:hover, -.btn:focus, -.btn.focus { - color: #333; - text-decoration: none; -} -.btn:active, -.btn.active { - background-image: none; - outline: 0; - -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); - box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); -} -.btn.disabled, -.btn[disabled], -fieldset[disabled] .btn { - cursor: not-allowed; - filter: alpha(opacity=65); - -webkit-box-shadow: none; - box-shadow: none; - opacity: .65; -} -a.btn.disabled, -fieldset[disabled] a.btn { - pointer-events: none; -} -.btn-default { - color: #333; - background-color: #fff; - border-color: #ccc; -} -.btn-default:focus, -.btn-default.focus { - color: #333; - background-color: #e6e6e6; - border-color: #8c8c8c; -} -.btn-default:hover { - color: #333; - background-color: #e6e6e6; - border-color: #adadad; -} -.btn-default:active, -.btn-default.active, -.open > .dropdown-toggle.btn-default { - color: #333; - background-color: #e6e6e6; - border-color: #adadad; -} -.btn-default:active:hover, -.btn-default.active:hover, -.open > .dropdown-toggle.btn-default:hover, -.btn-default:active:focus, -.btn-default.active:focus, -.open > .dropdown-toggle.btn-default:focus, -.btn-default:active.focus, -.btn-default.active.focus, -.open > .dropdown-toggle.btn-default.focus { - color: #333; - background-color: #d4d4d4; - border-color: #8c8c8c; -} -.btn-default:active, -.btn-default.active, -.open > .dropdown-toggle.btn-default { - background-image: none; -} -.btn-default.disabled:hover, -.btn-default[disabled]:hover, -fieldset[disabled] .btn-default:hover, -.btn-default.disabled:focus, -.btn-default[disabled]:focus, -fieldset[disabled] .btn-default:focus, -.btn-default.disabled.focus, -.btn-default[disabled].focus, -fieldset[disabled] .btn-default.focus { - background-color: #fff; - border-color: #ccc; -} -.btn-default .badge { - color: #fff; - background-color: #333; -} -.btn-primary { - color: #fff; - background-color: #337ab7; - border-color: #2e6da4; -} -.btn-primary:focus, -.btn-primary.focus { - color: #fff; - background-color: #286090; - border-color: #122b40; -} -.btn-primary:hover { - color: #fff; - background-color: #286090; - border-color: #204d74; -} -.btn-primary:active, -.btn-primary.active, -.open > .dropdown-toggle.btn-primary { - color: #fff; - background-color: #286090; - border-color: #204d74; -} -.btn-primary:active:hover, -.btn-primary.active:hover, -.open > .dropdown-toggle.btn-primary:hover, -.btn-primary:active:focus, -.btn-primary.active:focus, -.open > .dropdown-toggle.btn-primary:focus, -.btn-primary:active.focus, -.btn-primary.active.focus, -.open > .dropdown-toggle.btn-primary.focus { - color: #fff; - background-color: #204d74; - border-color: #122b40; -} -.btn-primary:active, -.btn-primary.active, -.open > .dropdown-toggle.btn-primary { - background-image: none; -} -.btn-primary.disabled:hover, -.btn-primary[disabled]:hover, -fieldset[disabled] .btn-primary:hover, -.btn-primary.disabled:focus, -.btn-primary[disabled]:focus, -fieldset[disabled] .btn-primary:focus, -.btn-primary.disabled.focus, -.btn-primary[disabled].focus, -fieldset[disabled] .btn-primary.focus { - background-color: #337ab7; - border-color: #2e6da4; -} -.btn-primary .badge { - color: #337ab7; - background-color: #fff; -} -.btn-success { - color: #fff; - background-color: #5cb85c; - border-color: #4cae4c; -} -.btn-success:focus, -.btn-success.focus { - color: #fff; - background-color: #449d44; - border-color: #255625; -} -.btn-success:hover { - color: #fff; - background-color: #449d44; - border-color: #398439; -} -.btn-success:active, -.btn-success.active, -.open > .dropdown-toggle.btn-success { - color: #fff; - background-color: #449d44; - border-color: #398439; -} -.btn-success:active:hover, -.btn-success.active:hover, -.open > .dropdown-toggle.btn-success:hover, -.btn-success:active:focus, -.btn-success.active:focus, -.open > .dropdown-toggle.btn-success:focus, -.btn-success:active.focus, -.btn-success.active.focus, -.open > .dropdown-toggle.btn-success.focus { - color: #fff; - background-color: #398439; - border-color: #255625; -} -.btn-success:active, -.btn-success.active, -.open > .dropdown-toggle.btn-success { - background-image: none; -} -.btn-success.disabled:hover, -.btn-success[disabled]:hover, -fieldset[disabled] .btn-success:hover, -.btn-success.disabled:focus, -.btn-success[disabled]:focus, -fieldset[disabled] .btn-success:focus, -.btn-success.disabled.focus, -.btn-success[disabled].focus, -fieldset[disabled] .btn-success.focus { - background-color: #5cb85c; - border-color: #4cae4c; -} -.btn-success .badge { - color: #5cb85c; - background-color: #fff; -} -.btn-info { - color: #fff; - background-color: #5bc0de; - border-color: #46b8da; -} -.btn-info:focus, -.btn-info.focus { - color: #fff; - background-color: #31b0d5; - border-color: #1b6d85; -} -.btn-info:hover { - color: #fff; - background-color: #31b0d5; - border-color: #269abc; -} -.btn-info:active, -.btn-info.active, -.open > .dropdown-toggle.btn-info { - color: #fff; - background-color: #31b0d5; - border-color: #269abc; -} -.btn-info:active:hover, -.btn-info.active:hover, -.open > .dropdown-toggle.btn-info:hover, -.btn-info:active:focus, -.btn-info.active:focus, -.open > .dropdown-toggle.btn-info:focus, -.btn-info:active.focus, -.btn-info.active.focus, -.open > .dropdown-toggle.btn-info.focus { - color: #fff; - background-color: #269abc; - border-color: #1b6d85; -} -.btn-info:active, -.btn-info.active, -.open > .dropdown-toggle.btn-info { - background-image: none; -} -.btn-info.disabled:hover, -.btn-info[disabled]:hover, -fieldset[disabled] .btn-info:hover, -.btn-info.disabled:focus, -.btn-info[disabled]:focus, -fieldset[disabled] .btn-info:focus, -.btn-info.disabled.focus, -.btn-info[disabled].focus, -fieldset[disabled] .btn-info.focus { - background-color: #5bc0de; - border-color: #46b8da; -} -.btn-info .badge { - color: #5bc0de; - background-color: #fff; -} -.btn-warning { - color: #fff; - background-color: #f0ad4e; - border-color: #eea236; -} -.btn-warning:focus, -.btn-warning.focus { - color: #fff; - background-color: #ec971f; - border-color: #985f0d; -} -.btn-warning:hover { - color: #fff; - background-color: #ec971f; - border-color: #d58512; -} -.btn-warning:active, -.btn-warning.active, -.open > .dropdown-toggle.btn-warning { - color: #fff; - background-color: #ec971f; - border-color: #d58512; -} -.btn-warning:active:hover, -.btn-warning.active:hover, -.open > .dropdown-toggle.btn-warning:hover, -.btn-warning:active:focus, -.btn-warning.active:focus, -.open > .dropdown-toggle.btn-warning:focus, -.btn-warning:active.focus, -.btn-warning.active.focus, -.open > .dropdown-toggle.btn-warning.focus { - color: #fff; - background-color: #d58512; - border-color: #985f0d; -} -.btn-warning:active, -.btn-warning.active, -.open > .dropdown-toggle.btn-warning { - background-image: none; -} -.btn-warning.disabled:hover, -.btn-warning[disabled]:hover, -fieldset[disabled] .btn-warning:hover, -.btn-warning.disabled:focus, -.btn-warning[disabled]:focus, -fieldset[disabled] .btn-warning:focus, -.btn-warning.disabled.focus, -.btn-warning[disabled].focus, -fieldset[disabled] .btn-warning.focus { - background-color: #f0ad4e; - border-color: #eea236; -} -.btn-warning .badge { - color: #f0ad4e; - background-color: #fff; -} -.btn-danger { - color: #fff; - background-color: #d9534f; - border-color: #d43f3a; -} -.btn-danger:focus, -.btn-danger.focus { - color: #fff; - background-color: #c9302c; - border-color: #761c19; -} -.btn-danger:hover { - color: #fff; - background-color: #c9302c; - border-color: #ac2925; -} -.btn-danger:active, -.btn-danger.active, -.open > .dropdown-toggle.btn-danger { - color: #fff; - background-color: #c9302c; - border-color: #ac2925; -} -.btn-danger:active:hover, -.btn-danger.active:hover, -.open > .dropdown-toggle.btn-danger:hover, -.btn-danger:active:focus, -.btn-danger.active:focus, -.open > .dropdown-toggle.btn-danger:focus, -.btn-danger:active.focus, -.btn-danger.active.focus, -.open > .dropdown-toggle.btn-danger.focus { - color: #fff; - background-color: #ac2925; - border-color: #761c19; -} -.btn-danger:active, -.btn-danger.active, -.open > .dropdown-toggle.btn-danger { - background-image: none; -} -.btn-danger.disabled:hover, -.btn-danger[disabled]:hover, -fieldset[disabled] .btn-danger:hover, -.btn-danger.disabled:focus, -.btn-danger[disabled]:focus, -fieldset[disabled] .btn-danger:focus, -.btn-danger.disabled.focus, -.btn-danger[disabled].focus, -fieldset[disabled] .btn-danger.focus { - background-color: #d9534f; - border-color: #d43f3a; -} -.btn-danger .badge { - color: #d9534f; - background-color: #fff; -} -.btn-link { - font-weight: normal; - color: #337ab7; - border-radius: 0; -} -.btn-link, -.btn-link:active, -.btn-link.active, -.btn-link[disabled], -fieldset[disabled] .btn-link { - background-color: transparent; - -webkit-box-shadow: none; - box-shadow: none; -} -.btn-link, -.btn-link:hover, -.btn-link:focus, -.btn-link:active { - border-color: transparent; -} -.btn-link:hover, -.btn-link:focus { - color: #23527c; - text-decoration: underline; - background-color: transparent; -} -.btn-link[disabled]:hover, -fieldset[disabled] .btn-link:hover, -.btn-link[disabled]:focus, -fieldset[disabled] .btn-link:focus { - color: #777; - text-decoration: none; -} -.btn-lg, -.btn-group-lg > .btn { - padding: 10px 16px; - font-size: 18px; - line-height: 1.3333333; - border-radius: 6px; -} -.btn-sm, -.btn-group-sm > .btn { - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} -.btn-xs, -.btn-group-xs > .btn { - padding: 1px 5px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} -.btn-block { - display: block; - width: 100%; -} -.btn-block + .btn-block { - margin-top: 5px; -} -input[type="submit"].btn-block, -input[type="reset"].btn-block, -input[type="button"].btn-block { - width: 100%; -} -.fade { - opacity: 0; - -webkit-transition: opacity .15s linear; - -o-transition: opacity .15s linear; - transition: opacity .15s linear; -} -.fade.in { - opacity: 1; -} -.collapse { - display: none; -} -.collapse.in { - display: block; -} -tr.collapse.in { - display: table-row; -} -tbody.collapse.in { - display: table-row-group; -} -.collapsing { - position: relative; - height: 0; - overflow: hidden; - -webkit-transition-timing-function: ease; - -o-transition-timing-function: ease; - transition-timing-function: ease; - -webkit-transition-duration: .35s; - -o-transition-duration: .35s; - transition-duration: .35s; - -webkit-transition-property: height, visibility; - -o-transition-property: height, visibility; - transition-property: height, visibility; -} -.caret { - display: inline-block; - width: 0; - height: 0; - margin-left: 2px; - vertical-align: middle; - border-top: 4px dashed; - border-top: 4px solid \9; - border-right: 4px solid transparent; - border-left: 4px solid transparent; -} -.dropup, -.dropdown { - position: relative; -} -.dropdown-toggle:focus { - outline: 0; -} -.dropdown-menu { - position: absolute; - top: 100%; - left: 0; - z-index: 1000; - display: none; - float: left; - min-width: 160px; - padding: 5px 0; - margin: 2px 0 0; - font-size: 14px; - text-align: left; - list-style: none; - background-color: #fff; - -webkit-background-clip: padding-box; - background-clip: padding-box; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, .15); - border-radius: 4px; - -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175); - box-shadow: 0 6px 12px rgba(0, 0, 0, .175); -} -.dropdown-menu.pull-right { - right: 0; - left: auto; -} -.dropdown-menu .divider { - height: 1px; - margin: 9px 0; - overflow: hidden; - background-color: #e5e5e5; -} -.dropdown-menu > li > a { - display: block; - padding: 3px 20px; - clear: both; - font-weight: normal; - line-height: 1.42857143; - color: #333; - white-space: nowrap; -} -.dropdown-menu > li > a:hover, -.dropdown-menu > li > a:focus { - color: #262626; - text-decoration: none; - background-color: #f5f5f5; -} -.dropdown-menu > .active > a, -.dropdown-menu > .active > a:hover, -.dropdown-menu > .active > a:focus { - color: #fff; - text-decoration: none; - background-color: #337ab7; - outline: 0; -} -.dropdown-menu > .disabled > a, -.dropdown-menu > .disabled > a:hover, -.dropdown-menu > .disabled > a:focus { - color: #777; -} -.dropdown-menu > .disabled > a:hover, -.dropdown-menu > .disabled > a:focus { - text-decoration: none; - cursor: not-allowed; - background-color: transparent; - background-image: none; - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); -} -.open > .dropdown-menu { - display: block; -} -.open > a { - outline: 0; -} -.dropdown-menu-right { - right: 0; - left: auto; -} -.dropdown-menu-left { - right: auto; - left: 0; -} -.dropdown-header { - display: block; - padding: 3px 20px; - font-size: 12px; - line-height: 1.42857143; - color: #777; - white-space: nowrap; -} -.dropdown-backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 990; -} -.pull-right > .dropdown-menu { - right: 0; - left: auto; -} -.dropup .caret, -.navbar-fixed-bottom .dropdown .caret { - content: ""; - border-top: 0; - border-bottom: 4px dashed; - border-bottom: 4px solid \9; -} -.dropup .dropdown-menu, -.navbar-fixed-bottom .dropdown .dropdown-menu { - top: auto; - bottom: 100%; - margin-bottom: 2px; -} -@media (min-width: 768px) { - .navbar-right .dropdown-menu { - right: 0; - left: auto; - } - .navbar-right .dropdown-menu-left { - right: auto; - left: 0; - } -} -.btn-group, -.btn-group-vertical { - position: relative; - display: inline-block; - vertical-align: middle; -} -.btn-group > .btn, -.btn-group-vertical > .btn { - position: relative; - float: left; -} -.btn-group > .btn:hover, -.btn-group-vertical > .btn:hover, -.btn-group > .btn:focus, -.btn-group-vertical > .btn:focus, -.btn-group > .btn:active, -.btn-group-vertical > .btn:active, -.btn-group > .btn.active, -.btn-group-vertical > .btn.active { - z-index: 2; -} -.btn-group .btn + .btn, -.btn-group .btn + .btn-group, -.btn-group .btn-group + .btn, -.btn-group .btn-group + .btn-group { - margin-left: -1px; -} -.btn-toolbar { - margin-left: -5px; -} -.btn-toolbar .btn, -.btn-toolbar .btn-group, -.btn-toolbar .input-group { - float: left; -} -.btn-toolbar > .btn, -.btn-toolbar > .btn-group, -.btn-toolbar > .input-group { - margin-left: 5px; -} -.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { - border-radius: 0; -} -.btn-group > .btn:first-child { - margin-left: 0; -} -.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} -.btn-group > .btn:last-child:not(:first-child), -.btn-group > .dropdown-toggle:not(:first-child) { - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} -.btn-group > .btn-group { - float: left; -} -.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { - border-radius: 0; -} -.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child, -.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} -.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child { - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} -.btn-group .dropdown-toggle:active, -.btn-group.open .dropdown-toggle { - outline: 0; -} -.btn-group > .btn + .dropdown-toggle { - padding-right: 8px; - padding-left: 8px; -} -.btn-group > .btn-lg + .dropdown-toggle { - padding-right: 12px; - padding-left: 12px; -} -.btn-group.open .dropdown-toggle { - -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); - box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); -} -.btn-group.open .dropdown-toggle.btn-link { - -webkit-box-shadow: none; - box-shadow: none; -} -.btn .caret { - margin-left: 0; -} -.btn-lg .caret { - border-width: 5px 5px 0; - border-bottom-width: 0; -} -.dropup .btn-lg .caret { - border-width: 0 5px 5px; -} -.btn-group-vertical > .btn, -.btn-group-vertical > .btn-group, -.btn-group-vertical > .btn-group > .btn { - display: block; - float: none; - width: 100%; - max-width: 100%; -} -.btn-group-vertical > .btn-group > .btn { - float: none; -} -.btn-group-vertical > .btn + .btn, -.btn-group-vertical > .btn + .btn-group, -.btn-group-vertical > .btn-group + .btn, -.btn-group-vertical > .btn-group + .btn-group { - margin-top: -1px; - margin-left: 0; -} -.btn-group-vertical > .btn:not(:first-child):not(:last-child) { - border-radius: 0; -} -.btn-group-vertical > .btn:first-child:not(:last-child) { - border-top-left-radius: 4px; - border-top-right-radius: 4px; - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; -} -.btn-group-vertical > .btn:last-child:not(:first-child) { - border-top-left-radius: 0; - border-top-right-radius: 0; - border-bottom-right-radius: 4px; - border-bottom-left-radius: 4px; -} -.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { - border-radius: 0; -} -.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child, -.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle { - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; -} -.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { - border-top-left-radius: 0; - border-top-right-radius: 0; -} -.btn-group-justified { - display: table; - width: 100%; - table-layout: fixed; - border-collapse: separate; -} -.btn-group-justified > .btn, -.btn-group-justified > .btn-group { - display: table-cell; - float: none; - width: 1%; -} -.btn-group-justified > .btn-group .btn { - width: 100%; -} -.btn-group-justified > .btn-group .dropdown-menu { - left: auto; -} -[data-toggle="buttons"] > .btn input[type="radio"], -[data-toggle="buttons"] > .btn-group > .btn input[type="radio"], -[data-toggle="buttons"] > .btn input[type="checkbox"], -[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] { - position: absolute; - clip: rect(0, 0, 0, 0); - pointer-events: none; -} -.input-group { - position: relative; - display: table; - border-collapse: separate; -} -.input-group[class*="col-"] { - float: none; - padding-right: 0; - padding-left: 0; -} -.input-group .form-control { - position: relative; - z-index: 2; - float: left; - width: 100%; - margin-bottom: 0; -} -.input-group .form-control:focus { - z-index: 3; -} -.input-group-lg > .form-control, -.input-group-lg > .input-group-addon, -.input-group-lg > .input-group-btn > .btn { - height: 46px; - padding: 10px 16px; - font-size: 18px; - line-height: 1.3333333; - border-radius: 6px; -} -select.input-group-lg > .form-control, -select.input-group-lg > .input-group-addon, -select.input-group-lg > .input-group-btn > .btn { - height: 46px; - line-height: 46px; -} -textarea.input-group-lg > .form-control, -textarea.input-group-lg > .input-group-addon, -textarea.input-group-lg > .input-group-btn > .btn, -select[multiple].input-group-lg > .form-control, -select[multiple].input-group-lg > .input-group-addon, -select[multiple].input-group-lg > .input-group-btn > .btn { - height: auto; -} -.input-group-sm > .form-control, -.input-group-sm > .input-group-addon, -.input-group-sm > .input-group-btn > .btn { - height: 30px; - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} -select.input-group-sm > .form-control, -select.input-group-sm > .input-group-addon, -select.input-group-sm > .input-group-btn > .btn { - height: 30px; - line-height: 30px; -} -textarea.input-group-sm > .form-control, -textarea.input-group-sm > .input-group-addon, -textarea.input-group-sm > .input-group-btn > .btn, -select[multiple].input-group-sm > .form-control, -select[multiple].input-group-sm > .input-group-addon, -select[multiple].input-group-sm > .input-group-btn > .btn { - height: auto; -} -.input-group-addon, -.input-group-btn, -.input-group .form-control { - display: table-cell; -} -.input-group-addon:not(:first-child):not(:last-child), -.input-group-btn:not(:first-child):not(:last-child), -.input-group .form-control:not(:first-child):not(:last-child) { - border-radius: 0; -} -.input-group-addon, -.input-group-btn { - width: 1%; - white-space: nowrap; - vertical-align: middle; -} -.input-group-addon { - padding: 6px 12px; - font-size: 14px; - font-weight: normal; - line-height: 1; - color: #555; - text-align: center; - background-color: #eee; - border: 1px solid #ccc; - border-radius: 4px; -} -.input-group-addon.input-sm { - padding: 5px 10px; - font-size: 12px; - border-radius: 3px; -} -.input-group-addon.input-lg { - padding: 10px 16px; - font-size: 18px; - border-radius: 6px; -} -.input-group-addon input[type="radio"], -.input-group-addon input[type="checkbox"] { - margin-top: 0; -} -.input-group .form-control:first-child, -.input-group-addon:first-child, -.input-group-btn:first-child > .btn, -.input-group-btn:first-child > .btn-group > .btn, -.input-group-btn:first-child > .dropdown-toggle, -.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), -.input-group-btn:last-child > .btn-group:not(:last-child) > .btn { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} -.input-group-addon:first-child { - border-right: 0; -} -.input-group .form-control:last-child, -.input-group-addon:last-child, -.input-group-btn:last-child > .btn, -.input-group-btn:last-child > .btn-group > .btn, -.input-group-btn:last-child > .dropdown-toggle, -.input-group-btn:first-child > .btn:not(:first-child), -.input-group-btn:first-child > .btn-group:not(:first-child) > .btn { - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} -.input-group-addon:last-child { - border-left: 0; -} -.input-group-btn { - position: relative; - font-size: 0; - white-space: nowrap; -} -.input-group-btn > .btn { - position: relative; -} -.input-group-btn > .btn + .btn { - margin-left: -1px; -} -.input-group-btn > .btn:hover, -.input-group-btn > .btn:focus, -.input-group-btn > .btn:active { - z-index: 2; -} -.input-group-btn:first-child > .btn, -.input-group-btn:first-child > .btn-group { - margin-right: -1px; -} -.input-group-btn:last-child > .btn, -.input-group-btn:last-child > .btn-group { - z-index: 2; - margin-left: -1px; -} -.nav { - padding-left: 0; - margin-bottom: 0; - list-style: none; -} -.nav > li { - position: relative; - display: block; -} -.nav > li > a { - position: relative; - display: block; - padding: 10px 15px; -} -.nav > li > a:hover, -.nav > li > a:focus { - text-decoration: none; - background-color: #eee; -} -.nav > li.disabled > a { - color: #777; -} -.nav > li.disabled > a:hover, -.nav > li.disabled > a:focus { - color: #777; - text-decoration: none; - cursor: not-allowed; - background-color: transparent; -} -.nav .open > a, -.nav .open > a:hover, -.nav .open > a:focus { - background-color: #eee; - border-color: #337ab7; -} -.nav .nav-divider { - height: 1px; - margin: 9px 0; - overflow: hidden; - background-color: #e5e5e5; -} -.nav > li > a > img { - max-width: none; -} -.nav-tabs { - border-bottom: 1px solid #ddd; -} -.nav-tabs > li { - float: left; - margin-bottom: -1px; -} -.nav-tabs > li > a { - margin-right: 2px; - line-height: 1.42857143; - border: 1px solid transparent; - border-radius: 4px 4px 0 0; -} -.nav-tabs > li > a:hover { - border-color: #eee #eee #ddd; -} -.nav-tabs > li.active > a, -.nav-tabs > li.active > a:hover, -.nav-tabs > li.active > a:focus { - color: #555; - cursor: default; - background-color: #fff; - border: 1px solid #ddd; - border-bottom-color: transparent; -} -.nav-tabs.nav-justified { - width: 100%; - border-bottom: 0; -} -.nav-tabs.nav-justified > li { - float: none; -} -.nav-tabs.nav-justified > li > a { - margin-bottom: 5px; - text-align: center; -} -.nav-tabs.nav-justified > .dropdown .dropdown-menu { - top: auto; - left: auto; -} -@media (min-width: 768px) { - .nav-tabs.nav-justified > li { - display: table-cell; - width: 1%; - } - .nav-tabs.nav-justified > li > a { - margin-bottom: 0; - } -} -.nav-tabs.nav-justified > li > a { - margin-right: 0; - border-radius: 4px; -} -.nav-tabs.nav-justified > .active > a, -.nav-tabs.nav-justified > .active > a:hover, -.nav-tabs.nav-justified > .active > a:focus { - border: 1px solid #ddd; -} -@media (min-width: 768px) { - .nav-tabs.nav-justified > li > a { - border-bottom: 1px solid #ddd; - border-radius: 4px 4px 0 0; - } - .nav-tabs.nav-justified > .active > a, - .nav-tabs.nav-justified > .active > a:hover, - .nav-tabs.nav-justified > .active > a:focus { - border-bottom-color: #fff; - } -} -.nav-pills > li { - float: left; -} -.nav-pills > li > a { - border-radius: 4px; -} -.nav-pills > li + li { - margin-left: 2px; -} -.nav-pills > li.active > a, -.nav-pills > li.active > a:hover, -.nav-pills > li.active > a:focus { - color: #fff; - background-color: #337ab7; -} -.nav-stacked > li { - float: none; -} -.nav-stacked > li + li { - margin-top: 2px; - margin-left: 0; -} -.nav-justified { - width: 100%; -} -.nav-justified > li { - float: none; -} -.nav-justified > li > a { - margin-bottom: 5px; - text-align: center; -} -.nav-justified > .dropdown .dropdown-menu { - top: auto; - left: auto; -} -@media (min-width: 768px) { - .nav-justified > li { - display: table-cell; - width: 1%; - } - .nav-justified > li > a { - margin-bottom: 0; - } -} -.nav-tabs-justified { - border-bottom: 0; -} -.nav-tabs-justified > li > a { - margin-right: 0; - border-radius: 4px; -} -.nav-tabs-justified > .active > a, -.nav-tabs-justified > .active > a:hover, -.nav-tabs-justified > .active > a:focus { - border: 1px solid #ddd; -} -@media (min-width: 768px) { - .nav-tabs-justified > li > a { - border-bottom: 1px solid #ddd; - border-radius: 4px 4px 0 0; - } - .nav-tabs-justified > .active > a, - .nav-tabs-justified > .active > a:hover, - .nav-tabs-justified > .active > a:focus { - border-bottom-color: #fff; - } -} -.tab-content > .tab-pane { - display: none; -} -.tab-content > .active { - display: block; -} -.nav-tabs .dropdown-menu { - margin-top: -1px; - border-top-left-radius: 0; - border-top-right-radius: 0; -} -.navbar { - position: relative; - min-height: 50px; - margin-bottom: 20px; - border: 1px solid transparent; -} -@media (min-width: 768px) { - .navbar { - border-radius: 4px; - } -} -@media (min-width: 768px) { - .navbar-header { - float: left; - } -} -.navbar-collapse { - padding-right: 15px; - padding-left: 15px; - overflow-x: visible; - -webkit-overflow-scrolling: touch; - border-top: 1px solid transparent; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); -} -.navbar-collapse.in { - overflow-y: auto; -} -@media (min-width: 768px) { - .navbar-collapse { - width: auto; - border-top: 0; - -webkit-box-shadow: none; - box-shadow: none; - } - .navbar-collapse.collapse { - display: block !important; - height: auto !important; - padding-bottom: 0; - overflow: visible !important; - } - .navbar-collapse.in { - overflow-y: visible; - } - .navbar-fixed-top .navbar-collapse, - .navbar-static-top .navbar-collapse, - .navbar-fixed-bottom .navbar-collapse { - padding-right: 0; - padding-left: 0; - } -} -.navbar-fixed-top .navbar-collapse, -.navbar-fixed-bottom .navbar-collapse { - max-height: 340px; -} -@media (max-device-width: 480px) and (orientation: landscape) { - .navbar-fixed-top .navbar-collapse, - .navbar-fixed-bottom .navbar-collapse { - max-height: 200px; - } -} -.container > .navbar-header, -.container-fluid > .navbar-header, -.container > .navbar-collapse, -.container-fluid > .navbar-collapse { - margin-right: -15px; - margin-left: -15px; -} -@media (min-width: 768px) { - .container > .navbar-header, - .container-fluid > .navbar-header, - .container > .navbar-collapse, - .container-fluid > .navbar-collapse { - margin-right: 0; - margin-left: 0; - } -} -.navbar-static-top { - z-index: 1000; - border-width: 0 0 1px; -} -@media (min-width: 768px) { - .navbar-static-top { - border-radius: 0; - } -} -.navbar-fixed-top, -.navbar-fixed-bottom { - position: fixed; - right: 0; - left: 0; - z-index: 1030; -} -@media (min-width: 768px) { - .navbar-fixed-top, - .navbar-fixed-bottom { - border-radius: 0; - } -} -.navbar-fixed-top { - top: 0; - border-width: 0 0 1px; -} -.navbar-fixed-bottom { - bottom: 0; - margin-bottom: 0; - border-width: 1px 0 0; -} -.navbar-brand { - float: left; - height: 50px; - padding: 15px 15px; - font-size: 18px; - line-height: 20px; -} -.navbar-brand:hover, -.navbar-brand:focus { - text-decoration: none; -} -.navbar-brand > img { - display: block; -} -@media (min-width: 768px) { - .navbar > .container .navbar-brand, - .navbar > .container-fluid .navbar-brand { - margin-left: -15px; - } -} -.navbar-toggle { - position: relative; - float: right; - padding: 9px 10px; - margin-top: 8px; - margin-right: 15px; - margin-bottom: 8px; - background-color: transparent; - background-image: none; - border: 1px solid transparent; - border-radius: 4px; -} -.navbar-toggle:focus { - outline: 0; -} -.navbar-toggle .icon-bar { - display: block; - width: 22px; - height: 2px; - border-radius: 1px; -} -.navbar-toggle .icon-bar + .icon-bar { - margin-top: 4px; -} -@media (min-width: 768px) { - .navbar-toggle { - display: none; - } -} -.navbar-nav { - margin: 7.5px -15px; -} -.navbar-nav > li > a { - padding-top: 10px; - padding-bottom: 10px; - line-height: 20px; -} -@media (max-width: 767px) { - .navbar-nav .open .dropdown-menu { - position: static; - float: none; - width: auto; - margin-top: 0; - background-color: transparent; - border: 0; - -webkit-box-shadow: none; - box-shadow: none; - } - .navbar-nav .open .dropdown-menu > li > a, - .navbar-nav .open .dropdown-menu .dropdown-header { - padding: 5px 15px 5px 25px; - } - .navbar-nav .open .dropdown-menu > li > a { - line-height: 20px; - } - .navbar-nav .open .dropdown-menu > li > a:hover, - .navbar-nav .open .dropdown-menu > li > a:focus { - background-image: none; - } -} -@media (min-width: 768px) { - .navbar-nav { - float: left; - margin: 0; - } - .navbar-nav > li { - float: left; - } - .navbar-nav > li > a { - padding-top: 15px; - padding-bottom: 15px; - } -} -.navbar-form { - padding: 10px 15px; - margin-top: 8px; - margin-right: -15px; - margin-bottom: 8px; - margin-left: -15px; - border-top: 1px solid transparent; - border-bottom: 1px solid transparent; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); -} -@media (min-width: 768px) { - .navbar-form .form-group { - display: inline-block; - margin-bottom: 0; - vertical-align: middle; - } - .navbar-form .form-control { - display: inline-block; - width: auto; - vertical-align: middle; - } - .navbar-form .form-control-static { - display: inline-block; - } - .navbar-form .input-group { - display: inline-table; - vertical-align: middle; - } - .navbar-form .input-group .input-group-addon, - .navbar-form .input-group .input-group-btn, - .navbar-form .input-group .form-control { - width: auto; - } - .navbar-form .input-group > .form-control { - width: 100%; - } - .navbar-form .control-label { - margin-bottom: 0; - vertical-align: middle; - } - .navbar-form .radio, - .navbar-form .checkbox { - display: inline-block; - margin-top: 0; - margin-bottom: 0; - vertical-align: middle; - } - .navbar-form .radio label, - .navbar-form .checkbox label { - padding-left: 0; - } - .navbar-form .radio input[type="radio"], - .navbar-form .checkbox input[type="checkbox"] { - position: relative; - margin-left: 0; - } - .navbar-form .has-feedback .form-control-feedback { - top: 0; - } -} -@media (max-width: 767px) { - .navbar-form .form-group { - margin-bottom: 5px; - } - .navbar-form .form-group:last-child { - margin-bottom: 0; - } -} -@media (min-width: 768px) { - .navbar-form { - width: auto; - padding-top: 0; - padding-bottom: 0; - margin-right: 0; - margin-left: 0; - border: 0; - -webkit-box-shadow: none; - box-shadow: none; - } -} -.navbar-nav > li > .dropdown-menu { - margin-top: 0; - border-top-left-radius: 0; - border-top-right-radius: 0; -} -.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { - margin-bottom: 0; - border-top-left-radius: 4px; - border-top-right-radius: 4px; - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; -} -.navbar-btn { - margin-top: 8px; - margin-bottom: 8px; -} -.navbar-btn.btn-sm { - margin-top: 10px; - margin-bottom: 10px; -} -.navbar-btn.btn-xs { - margin-top: 14px; - margin-bottom: 14px; -} -.navbar-text { - margin-top: 15px; - margin-bottom: 15px; -} -@media (min-width: 768px) { - .navbar-text { - float: left; - margin-right: 15px; - margin-left: 15px; - } -} -@media (min-width: 768px) { - .navbar-left { - float: left !important; - } - .navbar-right { - float: right !important; - margin-right: -15px; - } - .navbar-right ~ .navbar-right { - margin-right: 0; - } -} -.navbar-default { - background-color: #f8f8f8; - border-color: #e7e7e7; -} -.navbar-default .navbar-brand { - color: #777; -} -.navbar-default .navbar-brand:hover, -.navbar-default .navbar-brand:focus { - color: #5e5e5e; - background-color: transparent; -} -.navbar-default .navbar-text { - color: #777; -} -.navbar-default .navbar-nav > li > a { - color: #777; -} -.navbar-default .navbar-nav > li > a:hover, -.navbar-default .navbar-nav > li > a:focus { - color: #333; - background-color: transparent; -} -.navbar-default .navbar-nav > .active > a, -.navbar-default .navbar-nav > .active > a:hover, -.navbar-default .navbar-nav > .active > a:focus { - color: #555; - background-color: #e7e7e7; -} -.navbar-default .navbar-nav > .disabled > a, -.navbar-default .navbar-nav > .disabled > a:hover, -.navbar-default .navbar-nav > .disabled > a:focus { - color: #ccc; - background-color: transparent; -} -.navbar-default .navbar-toggle { - border-color: #ddd; -} -.navbar-default .navbar-toggle:hover, -.navbar-default .navbar-toggle:focus { - background-color: #ddd; -} -.navbar-default .navbar-toggle .icon-bar { - background-color: #888; -} -.navbar-default .navbar-collapse, -.navbar-default .navbar-form { - border-color: #e7e7e7; -} -.navbar-default .navbar-nav > .open > a, -.navbar-default .navbar-nav > .open > a:hover, -.navbar-default .navbar-nav > .open > a:focus { - color: #555; - background-color: #e7e7e7; -} -@media (max-width: 767px) { - .navbar-default .navbar-nav .open .dropdown-menu > li > a { - color: #777; - } - .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, - .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { - color: #333; - background-color: transparent; - } - .navbar-default .navbar-nav .open .dropdown-menu > .active > a, - .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, - .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { - color: #555; - background-color: #e7e7e7; - } - .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, - .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, - .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { - color: #ccc; - background-color: transparent; - } -} -.navbar-default .navbar-link { - color: #777; -} -.navbar-default .navbar-link:hover { - color: #333; -} -.navbar-default .btn-link { - color: #777; -} -.navbar-default .btn-link:hover, -.navbar-default .btn-link:focus { - color: #333; -} -.navbar-default .btn-link[disabled]:hover, -fieldset[disabled] .navbar-default .btn-link:hover, -.navbar-default .btn-link[disabled]:focus, -fieldset[disabled] .navbar-default .btn-link:focus { - color: #ccc; -} -.navbar-inverse { - background-color: #222; - border-color: #080808; -} -.navbar-inverse .navbar-brand { - color: #9d9d9d; -} -.navbar-inverse .navbar-brand:hover, -.navbar-inverse .navbar-brand:focus { - color: #fff; - background-color: transparent; -} -.navbar-inverse .navbar-text { - color: #9d9d9d; -} -.navbar-inverse .navbar-nav > li > a { - color: #9d9d9d; -} -.navbar-inverse .navbar-nav > li > a:hover, -.navbar-inverse .navbar-nav > li > a:focus { - color: #fff; - background-color: transparent; -} -.navbar-inverse .navbar-nav > .active > a, -.navbar-inverse .navbar-nav > .active > a:hover, -.navbar-inverse .navbar-nav > .active > a:focus { - color: #fff; - background-color: #080808; -} -.navbar-inverse .navbar-nav > .disabled > a, -.navbar-inverse .navbar-nav > .disabled > a:hover, -.navbar-inverse .navbar-nav > .disabled > a:focus { - color: #444; - background-color: transparent; -} -.navbar-inverse .navbar-toggle { - border-color: #333; -} -.navbar-inverse .navbar-toggle:hover, -.navbar-inverse .navbar-toggle:focus { - background-color: #333; -} -.navbar-inverse .navbar-toggle .icon-bar { - background-color: #fff; -} -.navbar-inverse .navbar-collapse, -.navbar-inverse .navbar-form { - border-color: #101010; -} -.navbar-inverse .navbar-nav > .open > a, -.navbar-inverse .navbar-nav > .open > a:hover, -.navbar-inverse .navbar-nav > .open > a:focus { - color: #fff; - background-color: #080808; -} -@media (max-width: 767px) { - .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { - border-color: #080808; - } - .navbar-inverse .navbar-nav .open .dropdown-menu .divider { - background-color: #080808; - } - .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { - color: #9d9d9d; - } - .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, - .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { - color: #fff; - background-color: transparent; - } - .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, - .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, - .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { - color: #fff; - background-color: #080808; - } - .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, - .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, - .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { - color: #444; - background-color: transparent; - } -} -.navbar-inverse .navbar-link { - color: #9d9d9d; -} -.navbar-inverse .navbar-link:hover { - color: #fff; -} -.navbar-inverse .btn-link { - color: #9d9d9d; -} -.navbar-inverse .btn-link:hover, -.navbar-inverse .btn-link:focus { - color: #fff; -} -.navbar-inverse .btn-link[disabled]:hover, -fieldset[disabled] .navbar-inverse .btn-link:hover, -.navbar-inverse .btn-link[disabled]:focus, -fieldset[disabled] .navbar-inverse .btn-link:focus { - color: #444; -} -.breadcrumb { - padding: 8px 15px; - margin-bottom: 20px; - list-style: none; - background-color: #f5f5f5; - border-radius: 4px; -} -.breadcrumb > li { - display: inline-block; -} -.breadcrumb > li + li:before { - padding: 0 5px; - color: #ccc; - content: "/\00a0"; -} -.breadcrumb > .active { - color: #777; -} -.pagination { - display: inline-block; - padding-left: 0; - margin: 20px 0; - border-radius: 4px; -} -.pagination > li { - display: inline; -} -.pagination > li > a, -.pagination > li > span { - position: relative; - float: left; - padding: 6px 12px; - margin-left: -1px; - line-height: 1.42857143; - color: #337ab7; - text-decoration: none; - background-color: #fff; - border: 1px solid #ddd; -} -.pagination > li:first-child > a, -.pagination > li:first-child > span { - margin-left: 0; - border-top-left-radius: 4px; - border-bottom-left-radius: 4px; -} -.pagination > li:last-child > a, -.pagination > li:last-child > span { - border-top-right-radius: 4px; - border-bottom-right-radius: 4px; -} -.pagination > li > a:hover, -.pagination > li > span:hover, -.pagination > li > a:focus, -.pagination > li > span:focus { - z-index: 2; - color: #23527c; - background-color: #eee; - border-color: #ddd; -} -.pagination > .active > a, -.pagination > .active > span, -.pagination > .active > a:hover, -.pagination > .active > span:hover, -.pagination > .active > a:focus, -.pagination > .active > span:focus { - z-index: 3; - color: #fff; - cursor: default; - background-color: #337ab7; - border-color: #337ab7; -} -.pagination > .disabled > span, -.pagination > .disabled > span:hover, -.pagination > .disabled > span:focus, -.pagination > .disabled > a, -.pagination > .disabled > a:hover, -.pagination > .disabled > a:focus { - color: #777; - cursor: not-allowed; - background-color: #fff; - border-color: #ddd; -} -.pagination-lg > li > a, -.pagination-lg > li > span { - padding: 10px 16px; - font-size: 18px; - line-height: 1.3333333; -} -.pagination-lg > li:first-child > a, -.pagination-lg > li:first-child > span { - border-top-left-radius: 6px; - border-bottom-left-radius: 6px; -} -.pagination-lg > li:last-child > a, -.pagination-lg > li:last-child > span { - border-top-right-radius: 6px; - border-bottom-right-radius: 6px; -} -.pagination-sm > li > a, -.pagination-sm > li > span { - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; -} -.pagination-sm > li:first-child > a, -.pagination-sm > li:first-child > span { - border-top-left-radius: 3px; - border-bottom-left-radius: 3px; -} -.pagination-sm > li:last-child > a, -.pagination-sm > li:last-child > span { - border-top-right-radius: 3px; - border-bottom-right-radius: 3px; -} -.pager { - padding-left: 0; - margin: 20px 0; - text-align: center; - list-style: none; -} -.pager li { - display: inline; -} -.pager li > a, -.pager li > span { - display: inline-block; - padding: 5px 14px; - background-color: #fff; - border: 1px solid #ddd; - border-radius: 15px; -} -.pager li > a:hover, -.pager li > a:focus { - text-decoration: none; - background-color: #eee; -} -.pager .next > a, -.pager .next > span { - float: right; -} -.pager .previous > a, -.pager .previous > span { - float: left; -} -.pager .disabled > a, -.pager .disabled > a:hover, -.pager .disabled > a:focus, -.pager .disabled > span { - color: #777; - cursor: not-allowed; - background-color: #fff; -} -.label { - display: inline; - padding: .2em .6em .3em; - font-size: 75%; - font-weight: bold; - line-height: 1; - color: #fff; - text-align: center; - white-space: nowrap; - vertical-align: baseline; - border-radius: .25em; -} -a.label:hover, -a.label:focus { - color: #fff; - text-decoration: none; - cursor: pointer; -} -.label:empty { - display: none; -} -.btn .label { - position: relative; - top: -1px; -} -.label-default { - background-color: #777; -} -.label-default[href]:hover, -.label-default[href]:focus { - background-color: #5e5e5e; -} -.label-primary { - background-color: #337ab7; -} -.label-primary[href]:hover, -.label-primary[href]:focus { - background-color: #286090; -} -.label-success { - background-color: #5cb85c; -} -.label-success[href]:hover, -.label-success[href]:focus { - background-color: #449d44; -} -.label-info { - background-color: #5bc0de; -} -.label-info[href]:hover, -.label-info[href]:focus { - background-color: #31b0d5; -} -.label-warning { - background-color: #f0ad4e; -} -.label-warning[href]:hover, -.label-warning[href]:focus { - background-color: #ec971f; -} -.label-danger { - background-color: #d9534f; -} -.label-danger[href]:hover, -.label-danger[href]:focus { - background-color: #c9302c; -} -.badge { - display: inline-block; - min-width: 10px; - padding: 3px 7px; - font-size: 12px; - font-weight: bold; - line-height: 1; - color: #fff; - text-align: center; - white-space: nowrap; - vertical-align: middle; - background-color: #777; - border-radius: 10px; -} -.badge:empty { - display: none; -} -.btn .badge { - position: relative; - top: -1px; -} -.btn-xs .badge, -.btn-group-xs > .btn .badge { - top: 0; - padding: 1px 5px; -} -a.badge:hover, -a.badge:focus { - color: #fff; - text-decoration: none; - cursor: pointer; -} -.list-group-item.active > .badge, -.nav-pills > .active > a > .badge { - color: #337ab7; - background-color: #fff; -} -.list-group-item > .badge { - float: right; -} -.list-group-item > .badge + .badge { - margin-right: 5px; -} -.nav-pills > li > a > .badge { - margin-left: 3px; -} -.jumbotron { - padding-top: 30px; - padding-bottom: 30px; - margin-bottom: 30px; - color: inherit; - background-color: #eee; -} -.jumbotron h1, -.jumbotron .h1 { - color: inherit; -} -.jumbotron p { - margin-bottom: 15px; - font-size: 21px; - font-weight: 200; -} -.jumbotron > hr { - border-top-color: #d5d5d5; -} -.container .jumbotron, -.container-fluid .jumbotron { - padding-right: 15px; - padding-left: 15px; - border-radius: 6px; -} -.jumbotron .container { - max-width: 100%; -} -@media screen and (min-width: 768px) { - .jumbotron { - padding-top: 48px; - padding-bottom: 48px; - } - .container .jumbotron, - .container-fluid .jumbotron { - padding-right: 60px; - padding-left: 60px; - } - .jumbotron h1, - .jumbotron .h1 { - font-size: 63px; - } -} -.thumbnail { - display: block; - padding: 4px; - margin-bottom: 20px; - line-height: 1.42857143; - background-color: #fff; - border: 1px solid #ddd; - border-radius: 4px; - -webkit-transition: border .2s ease-in-out; - -o-transition: border .2s ease-in-out; - transition: border .2s ease-in-out; -} -.thumbnail > img, -.thumbnail a > img { - margin-right: auto; - margin-left: auto; -} -a.thumbnail:hover, -a.thumbnail:focus, -a.thumbnail.active { - border-color: #337ab7; -} -.thumbnail .caption { - padding: 9px; - color: #333; -} -.alert { - padding: 15px; - margin-bottom: 20px; - border: 1px solid transparent; - border-radius: 4px; -} -.alert h4 { - margin-top: 0; - color: inherit; -} -.alert .alert-link { - font-weight: bold; -} -.alert > p, -.alert > ul { - margin-bottom: 0; -} -.alert > p + p { - margin-top: 5px; -} -.alert-dismissable, -.alert-dismissible { - padding-right: 35px; -} -.alert-dismissable .close, -.alert-dismissible .close { - position: relative; - top: -2px; - right: -21px; - color: inherit; -} -.alert-success { - color: #3c763d; - background-color: #dff0d8; - border-color: #d6e9c6; -} -.alert-success hr { - border-top-color: #c9e2b3; -} -.alert-success .alert-link { - color: #2b542c; -} -.alert-info { - color: #31708f; - background-color: #d9edf7; - border-color: #bce8f1; -} -.alert-info hr { - border-top-color: #a6e1ec; -} -.alert-info .alert-link { - color: #245269; -} -.alert-warning { - color: #8a6d3b; - background-color: #fcf8e3; - border-color: #faebcc; -} -.alert-warning hr { - border-top-color: #f7e1b5; -} -.alert-warning .alert-link { - color: #66512c; -} -.alert-danger { - color: #a94442; - background-color: #f2dede; - border-color: #ebccd1; -} -.alert-danger hr { - border-top-color: #e4b9c0; -} -.alert-danger .alert-link { - color: #843534; -} -@-webkit-keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} -@-o-keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} -@keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} -.progress { - height: 20px; - margin-bottom: 20px; - overflow: hidden; - background-color: #f5f5f5; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); -} -.progress-bar { - float: left; - width: 0; - height: 100%; - font-size: 12px; - line-height: 20px; - color: #fff; - text-align: center; - background-color: #337ab7; - -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); - box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); - -webkit-transition: width .6s ease; - -o-transition: width .6s ease; - transition: width .6s ease; -} -.progress-striped .progress-bar, -.progress-bar-striped { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - -webkit-background-size: 40px 40px; - background-size: 40px 40px; -} -.progress.active .progress-bar, -.progress-bar.active { - -webkit-animation: progress-bar-stripes 2s linear infinite; - -o-animation: progress-bar-stripes 2s linear infinite; - animation: progress-bar-stripes 2s linear infinite; -} -.progress-bar-success { - background-color: #5cb85c; -} -.progress-striped .progress-bar-success { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); -} -.progress-bar-info { - background-color: #5bc0de; -} -.progress-striped .progress-bar-info { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); -} -.progress-bar-warning { - background-color: #f0ad4e; -} -.progress-striped .progress-bar-warning { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); -} -.progress-bar-danger { - background-color: #d9534f; -} -.progress-striped .progress-bar-danger { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); -} -.media { - margin-top: 15px; -} -.media:first-child { - margin-top: 0; -} -.media, -.media-body { - overflow: hidden; - zoom: 1; -} -.media-body { - width: 10000px; -} -.media-object { - display: block; -} -.media-object.img-thumbnail { - max-width: none; -} -.media-right, -.media > .pull-right { - padding-left: 10px; -} -.media-left, -.media > .pull-left { - padding-right: 10px; -} -.media-left, -.media-right, -.media-body { - display: table-cell; - vertical-align: top; -} -.media-middle { - vertical-align: middle; -} -.media-bottom { - vertical-align: bottom; -} -.media-heading { - margin-top: 0; - margin-bottom: 5px; -} -.media-list { - padding-left: 0; - list-style: none; -} -.list-group { - padding-left: 0; - margin-bottom: 20px; -} -.list-group-item { - position: relative; - display: block; - padding: 10px 15px; - margin-bottom: -1px; - background-color: #fff; - border: 1px solid #ddd; -} -.list-group-item:first-child { - border-top-left-radius: 4px; - border-top-right-radius: 4px; -} -.list-group-item:last-child { - margin-bottom: 0; - border-bottom-right-radius: 4px; - border-bottom-left-radius: 4px; -} -a.list-group-item, -button.list-group-item { - color: #555; -} -a.list-group-item .list-group-item-heading, -button.list-group-item .list-group-item-heading { - color: #333; -} -a.list-group-item:hover, -button.list-group-item:hover, -a.list-group-item:focus, -button.list-group-item:focus { - color: #555; - text-decoration: none; - background-color: #f5f5f5; -} -button.list-group-item { - width: 100%; - text-align: left; -} -.list-group-item.disabled, -.list-group-item.disabled:hover, -.list-group-item.disabled:focus { - color: #777; - cursor: not-allowed; - background-color: #eee; -} -.list-group-item.disabled .list-group-item-heading, -.list-group-item.disabled:hover .list-group-item-heading, -.list-group-item.disabled:focus .list-group-item-heading { - color: inherit; -} -.list-group-item.disabled .list-group-item-text, -.list-group-item.disabled:hover .list-group-item-text, -.list-group-item.disabled:focus .list-group-item-text { - color: #777; -} -.list-group-item.active, -.list-group-item.active:hover, -.list-group-item.active:focus { - z-index: 2; - color: #fff; - background-color: #337ab7; - border-color: #337ab7; -} -.list-group-item.active .list-group-item-heading, -.list-group-item.active:hover .list-group-item-heading, -.list-group-item.active:focus .list-group-item-heading, -.list-group-item.active .list-group-item-heading > small, -.list-group-item.active:hover .list-group-item-heading > small, -.list-group-item.active:focus .list-group-item-heading > small, -.list-group-item.active .list-group-item-heading > .small, -.list-group-item.active:hover .list-group-item-heading > .small, -.list-group-item.active:focus .list-group-item-heading > .small { - color: inherit; -} -.list-group-item.active .list-group-item-text, -.list-group-item.active:hover .list-group-item-text, -.list-group-item.active:focus .list-group-item-text { - color: #c7ddef; -} -.list-group-item-success { - color: #3c763d; - background-color: #dff0d8; -} -a.list-group-item-success, -button.list-group-item-success { - color: #3c763d; -} -a.list-group-item-success .list-group-item-heading, -button.list-group-item-success .list-group-item-heading { - color: inherit; -} -a.list-group-item-success:hover, -button.list-group-item-success:hover, -a.list-group-item-success:focus, -button.list-group-item-success:focus { - color: #3c763d; - background-color: #d0e9c6; -} -a.list-group-item-success.active, -button.list-group-item-success.active, -a.list-group-item-success.active:hover, -button.list-group-item-success.active:hover, -a.list-group-item-success.active:focus, -button.list-group-item-success.active:focus { - color: #fff; - background-color: #3c763d; - border-color: #3c763d; -} -.list-group-item-info { - color: #31708f; - background-color: #d9edf7; -} -a.list-group-item-info, -button.list-group-item-info { - color: #31708f; -} -a.list-group-item-info .list-group-item-heading, -button.list-group-item-info .list-group-item-heading { - color: inherit; -} -a.list-group-item-info:hover, -button.list-group-item-info:hover, -a.list-group-item-info:focus, -button.list-group-item-info:focus { - color: #31708f; - background-color: #c4e3f3; -} -a.list-group-item-info.active, -button.list-group-item-info.active, -a.list-group-item-info.active:hover, -button.list-group-item-info.active:hover, -a.list-group-item-info.active:focus, -button.list-group-item-info.active:focus { - color: #fff; - background-color: #31708f; - border-color: #31708f; -} -.list-group-item-warning { - color: #8a6d3b; - background-color: #fcf8e3; -} -a.list-group-item-warning, -button.list-group-item-warning { - color: #8a6d3b; -} -a.list-group-item-warning .list-group-item-heading, -button.list-group-item-warning .list-group-item-heading { - color: inherit; -} -a.list-group-item-warning:hover, -button.list-group-item-warning:hover, -a.list-group-item-warning:focus, -button.list-group-item-warning:focus { - color: #8a6d3b; - background-color: #faf2cc; -} -a.list-group-item-warning.active, -button.list-group-item-warning.active, -a.list-group-item-warning.active:hover, -button.list-group-item-warning.active:hover, -a.list-group-item-warning.active:focus, -button.list-group-item-warning.active:focus { - color: #fff; - background-color: #8a6d3b; - border-color: #8a6d3b; -} -.list-group-item-danger { - color: #a94442; - background-color: #f2dede; -} -a.list-group-item-danger, -button.list-group-item-danger { - color: #a94442; -} -a.list-group-item-danger .list-group-item-heading, -button.list-group-item-danger .list-group-item-heading { - color: inherit; -} -a.list-group-item-danger:hover, -button.list-group-item-danger:hover, -a.list-group-item-danger:focus, -button.list-group-item-danger:focus { - color: #a94442; - background-color: #ebcccc; -} -a.list-group-item-danger.active, -button.list-group-item-danger.active, -a.list-group-item-danger.active:hover, -button.list-group-item-danger.active:hover, -a.list-group-item-danger.active:focus, -button.list-group-item-danger.active:focus { - color: #fff; - background-color: #a94442; - border-color: #a94442; -} -.list-group-item-heading { - margin-top: 0; - margin-bottom: 5px; -} -.list-group-item-text { - margin-bottom: 0; - line-height: 1.3; -} -.panel { - margin-bottom: 20px; - background-color: #fff; - border: 1px solid transparent; - border-radius: 4px; - -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05); - box-shadow: 0 1px 1px rgba(0, 0, 0, .05); -} -.panel-body { - padding: 15px; -} -.panel-heading { - padding: 10px 15px; - border-bottom: 1px solid transparent; - border-top-left-radius: 3px; - border-top-right-radius: 3px; -} -.panel-heading > .dropdown .dropdown-toggle { - color: inherit; -} -.panel-title { - margin-top: 0; - margin-bottom: 0; - font-size: 16px; - color: inherit; -} -.panel-title > a, -.panel-title > small, -.panel-title > .small, -.panel-title > small > a, -.panel-title > .small > a { - color: inherit; -} -.panel-footer { - padding: 10px 15px; - background-color: #f5f5f5; - border-top: 1px solid #ddd; - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px; -} -.panel > .list-group, -.panel > .panel-collapse > .list-group { - margin-bottom: 0; -} -.panel > .list-group .list-group-item, -.panel > .panel-collapse > .list-group .list-group-item { - border-width: 1px 0; - border-radius: 0; -} -.panel > .list-group:first-child .list-group-item:first-child, -.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child { - border-top: 0; - border-top-left-radius: 3px; - border-top-right-radius: 3px; -} -.panel > .list-group:last-child .list-group-item:last-child, -.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child { - border-bottom: 0; - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px; -} -.panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child { - border-top-left-radius: 0; - border-top-right-radius: 0; -} -.panel-heading + .list-group .list-group-item:first-child { - border-top-width: 0; -} -.list-group + .panel-footer { - border-top-width: 0; -} -.panel > .table, -.panel > .table-responsive > .table, -.panel > .panel-collapse > .table { - margin-bottom: 0; -} -.panel > .table caption, -.panel > .table-responsive > .table caption, -.panel > .panel-collapse > .table caption { - padding-right: 15px; - padding-left: 15px; -} -.panel > .table:first-child, -.panel > .table-responsive:first-child > .table:first-child { - border-top-left-radius: 3px; - border-top-right-radius: 3px; -} -.panel > .table:first-child > thead:first-child > tr:first-child, -.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child, -.panel > .table:first-child > tbody:first-child > tr:first-child, -.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child { - border-top-left-radius: 3px; - border-top-right-radius: 3px; -} -.panel > .table:first-child > thead:first-child > tr:first-child td:first-child, -.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child, -.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child, -.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child, -.panel > .table:first-child > thead:first-child > tr:first-child th:first-child, -.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child, -.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child, -.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child { - border-top-left-radius: 3px; -} -.panel > .table:first-child > thead:first-child > tr:first-child td:last-child, -.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child, -.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child, -.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child, -.panel > .table:first-child > thead:first-child > tr:first-child th:last-child, -.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child, -.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child, -.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child { - border-top-right-radius: 3px; -} -.panel > .table:last-child, -.panel > .table-responsive:last-child > .table:last-child { - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px; -} -.panel > .table:last-child > tbody:last-child > tr:last-child, -.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child, -.panel > .table:last-child > tfoot:last-child > tr:last-child, -.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child { - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px; -} -.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child, -.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child, -.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child, -.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child, -.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child, -.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child, -.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child, -.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child { - border-bottom-left-radius: 3px; -} -.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child, -.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child, -.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child, -.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child, -.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child, -.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child, -.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child, -.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child { - border-bottom-right-radius: 3px; -} -.panel > .panel-body + .table, -.panel > .panel-body + .table-responsive, -.panel > .table + .panel-body, -.panel > .table-responsive + .panel-body { - border-top: 1px solid #ddd; -} -.panel > .table > tbody:first-child > tr:first-child th, -.panel > .table > tbody:first-child > tr:first-child td { - border-top: 0; -} -.panel > .table-bordered, -.panel > .table-responsive > .table-bordered { - border: 0; -} -.panel > .table-bordered > thead > tr > th:first-child, -.panel > .table-responsive > .table-bordered > thead > tr > th:first-child, -.panel > .table-bordered > tbody > tr > th:first-child, -.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child, -.panel > .table-bordered > tfoot > tr > th:first-child, -.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child, -.panel > .table-bordered > thead > tr > td:first-child, -.panel > .table-responsive > .table-bordered > thead > tr > td:first-child, -.panel > .table-bordered > tbody > tr > td:first-child, -.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, -.panel > .table-bordered > tfoot > tr > td:first-child, -.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { - border-left: 0; -} -.panel > .table-bordered > thead > tr > th:last-child, -.panel > .table-responsive > .table-bordered > thead > tr > th:last-child, -.panel > .table-bordered > tbody > tr > th:last-child, -.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child, -.panel > .table-bordered > tfoot > tr > th:last-child, -.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child, -.panel > .table-bordered > thead > tr > td:last-child, -.panel > .table-responsive > .table-bordered > thead > tr > td:last-child, -.panel > .table-bordered > tbody > tr > td:last-child, -.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, -.panel > .table-bordered > tfoot > tr > td:last-child, -.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { - border-right: 0; -} -.panel > .table-bordered > thead > tr:first-child > td, -.panel > .table-responsive > .table-bordered > thead > tr:first-child > td, -.panel > .table-bordered > tbody > tr:first-child > td, -.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td, -.panel > .table-bordered > thead > tr:first-child > th, -.panel > .table-responsive > .table-bordered > thead > tr:first-child > th, -.panel > .table-bordered > tbody > tr:first-child > th, -.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th { - border-bottom: 0; -} -.panel > .table-bordered > tbody > tr:last-child > td, -.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, -.panel > .table-bordered > tfoot > tr:last-child > td, -.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td, -.panel > .table-bordered > tbody > tr:last-child > th, -.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, -.panel > .table-bordered > tfoot > tr:last-child > th, -.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th { - border-bottom: 0; -} -.panel > .table-responsive { - margin-bottom: 0; - border: 0; -} -.panel-group { - margin-bottom: 20px; -} -.panel-group .panel { - margin-bottom: 0; - border-radius: 4px; -} -.panel-group .panel + .panel { - margin-top: 5px; -} -.panel-group .panel-heading { - border-bottom: 0; -} -.panel-group .panel-heading + .panel-collapse > .panel-body, -.panel-group .panel-heading + .panel-collapse > .list-group { - border-top: 1px solid #ddd; -} -.panel-group .panel-footer { - border-top: 0; -} -.panel-group .panel-footer + .panel-collapse .panel-body { - border-bottom: 1px solid #ddd; -} -.panel-default { - border-color: #ddd; -} -.panel-default > .panel-heading { - color: #333; - background-color: #f5f5f5; - border-color: #ddd; -} -.panel-default > .panel-heading + .panel-collapse > .panel-body { - border-top-color: #ddd; -} -.panel-default > .panel-heading .badge { - color: #f5f5f5; - background-color: #333; -} -.panel-default > .panel-footer + .panel-collapse > .panel-body { - border-bottom-color: #ddd; -} -.panel-primary { - border-color: #337ab7; -} -.panel-primary > .panel-heading { - color: #fff; - background-color: #337ab7; - border-color: #337ab7; -} -.panel-primary > .panel-heading + .panel-collapse > .panel-body { - border-top-color: #337ab7; -} -.panel-primary > .panel-heading .badge { - color: #337ab7; - background-color: #fff; -} -.panel-primary > .panel-footer + .panel-collapse > .panel-body { - border-bottom-color: #337ab7; -} -.panel-success { - border-color: #d6e9c6; -} -.panel-success > .panel-heading { - color: #3c763d; - background-color: #dff0d8; - border-color: #d6e9c6; -} -.panel-success > .panel-heading + .panel-collapse > .panel-body { - border-top-color: #d6e9c6; -} -.panel-success > .panel-heading .badge { - color: #dff0d8; - background-color: #3c763d; -} -.panel-success > .panel-footer + .panel-collapse > .panel-body { - border-bottom-color: #d6e9c6; -} -.panel-info { - border-color: #bce8f1; -} -.panel-info > .panel-heading { - color: #31708f; - background-color: #d9edf7; - border-color: #bce8f1; -} -.panel-info > .panel-heading + .panel-collapse > .panel-body { - border-top-color: #bce8f1; -} -.panel-info > .panel-heading .badge { - color: #d9edf7; - background-color: #31708f; -} -.panel-info > .panel-footer + .panel-collapse > .panel-body { - border-bottom-color: #bce8f1; -} -.panel-warning { - border-color: #faebcc; -} -.panel-warning > .panel-heading { - color: #8a6d3b; - background-color: #fcf8e3; - border-color: #faebcc; -} -.panel-warning > .panel-heading + .panel-collapse > .panel-body { - border-top-color: #faebcc; -} -.panel-warning > .panel-heading .badge { - color: #fcf8e3; - background-color: #8a6d3b; -} -.panel-warning > .panel-footer + .panel-collapse > .panel-body { - border-bottom-color: #faebcc; -} -.panel-danger { - border-color: #ebccd1; -} -.panel-danger > .panel-heading { - color: #a94442; - background-color: #f2dede; - border-color: #ebccd1; -} -.panel-danger > .panel-heading + .panel-collapse > .panel-body { - border-top-color: #ebccd1; -} -.panel-danger > .panel-heading .badge { - color: #f2dede; - background-color: #a94442; -} -.panel-danger > .panel-footer + .panel-collapse > .panel-body { - border-bottom-color: #ebccd1; -} -.embed-responsive { - position: relative; - display: block; - height: 0; - padding: 0; - overflow: hidden; -} -.embed-responsive .embed-responsive-item, -.embed-responsive iframe, -.embed-responsive embed, -.embed-responsive object, -.embed-responsive video { - position: absolute; - top: 0; - bottom: 0; - left: 0; - width: 100%; - height: 100%; - border: 0; -} -.embed-responsive-16by9 { - padding-bottom: 56.25%; -} -.embed-responsive-4by3 { - padding-bottom: 75%; -} -.well { - min-height: 20px; - padding: 19px; - margin-bottom: 20px; - background-color: #f5f5f5; - border: 1px solid #e3e3e3; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); -} -.well blockquote { - border-color: #ddd; - border-color: rgba(0, 0, 0, .15); -} -.well-lg { - padding: 24px; - border-radius: 6px; -} -.well-sm { - padding: 9px; - border-radius: 3px; -} -.close { - float: right; - font-size: 21px; - font-weight: bold; - line-height: 1; - color: #000; - text-shadow: 0 1px 0 #fff; - filter: alpha(opacity=20); - opacity: .2; -} -.close:hover, -.close:focus { - color: #000; - text-decoration: none; - cursor: pointer; - filter: alpha(opacity=50); - opacity: .5; -} -button.close { - -webkit-appearance: none; - padding: 0; - cursor: pointer; - background: transparent; - border: 0; -} -.modal-open { - overflow: hidden; -} -.modal { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1050; - display: none; - overflow: hidden; - -webkit-overflow-scrolling: touch; - outline: 0; -} -.modal.fade .modal-dialog { - -webkit-transition: -webkit-transform .3s ease-out; - -o-transition: -o-transform .3s ease-out; - transition: transform .3s ease-out; - -webkit-transform: translate(0, -25%); - -ms-transform: translate(0, -25%); - -o-transform: translate(0, -25%); - transform: translate(0, -25%); -} -.modal.in .modal-dialog { - -webkit-transform: translate(0, 0); - -ms-transform: translate(0, 0); - -o-transform: translate(0, 0); - transform: translate(0, 0); -} -.modal-open .modal { - overflow-x: hidden; - overflow-y: auto; -} -.modal-dialog { - position: relative; - width: auto; - margin: 10px; -} -.modal-content { - position: relative; - background-color: #fff; - -webkit-background-clip: padding-box; - background-clip: padding-box; - border: 1px solid #999; - border: 1px solid rgba(0, 0, 0, .2); - border-radius: 6px; - outline: 0; - -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5); - box-shadow: 0 3px 9px rgba(0, 0, 0, .5); -} -.modal-backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1040; - background-color: #000; -} -.modal-backdrop.fade { - filter: alpha(opacity=0); - opacity: 0; -} -.modal-backdrop.in { - filter: alpha(opacity=50); - opacity: .5; -} -.modal-header { - padding: 15px; - border-bottom: 1px solid #e5e5e5; -} -.modal-header .close { - margin-top: -2px; -} -.modal-title { - margin: 0; - line-height: 1.42857143; -} -.modal-body { - position: relative; - padding: 15px; -} -.modal-footer { - padding: 15px; - text-align: right; - border-top: 1px solid #e5e5e5; -} -.modal-footer .btn + .btn { - margin-bottom: 0; - margin-left: 5px; -} -.modal-footer .btn-group .btn + .btn { - margin-left: -1px; -} -.modal-footer .btn-block + .btn-block { - margin-left: 0; -} -.modal-scrollbar-measure { - position: absolute; - top: -9999px; - width: 50px; - height: 50px; - overflow: scroll; -} -@media (min-width: 768px) { - .modal-dialog { - width: 600px; - margin: 30px auto; - } - .modal-content { - -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5); - box-shadow: 0 5px 15px rgba(0, 0, 0, .5); - } - .modal-sm { - width: 300px; - } -} -@media (min-width: 992px) { - .modal-lg { - width: 900px; - } -} -.tooltip { - position: absolute; - z-index: 1070; - display: block; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 12px; - font-style: normal; - font-weight: normal; - line-height: 1.42857143; - text-align: left; - text-align: start; - text-decoration: none; - text-shadow: none; - text-transform: none; - letter-spacing: normal; - word-break: normal; - word-spacing: normal; - word-wrap: normal; - white-space: normal; - filter: alpha(opacity=0); - opacity: 0; - - line-break: auto; -} -.tooltip.in { - filter: alpha(opacity=90); - opacity: .9; -} -.tooltip.top { - padding: 5px 0; - margin-top: -3px; -} -.tooltip.right { - padding: 0 5px; - margin-left: 3px; -} -.tooltip.bottom { - padding: 5px 0; - margin-top: 3px; -} -.tooltip.left { - padding: 0 5px; - margin-left: -3px; -} -.tooltip-inner { - max-width: 200px; - padding: 3px 8px; - color: #fff; - text-align: center; - background-color: #000; - border-radius: 4px; -} -.tooltip-arrow { - position: absolute; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; -} -.tooltip.top .tooltip-arrow { - bottom: 0; - left: 50%; - margin-left: -5px; - border-width: 5px 5px 0; - border-top-color: #000; -} -.tooltip.top-left .tooltip-arrow { - right: 5px; - bottom: 0; - margin-bottom: -5px; - border-width: 5px 5px 0; - border-top-color: #000; -} -.tooltip.top-right .tooltip-arrow { - bottom: 0; - left: 5px; - margin-bottom: -5px; - border-width: 5px 5px 0; - border-top-color: #000; -} -.tooltip.right .tooltip-arrow { - top: 50%; - left: 0; - margin-top: -5px; - border-width: 5px 5px 5px 0; - border-right-color: #000; -} -.tooltip.left .tooltip-arrow { - top: 50%; - right: 0; - margin-top: -5px; - border-width: 5px 0 5px 5px; - border-left-color: #000; -} -.tooltip.bottom .tooltip-arrow { - top: 0; - left: 50%; - margin-left: -5px; - border-width: 0 5px 5px; - border-bottom-color: #000; -} -.tooltip.bottom-left .tooltip-arrow { - top: 0; - right: 5px; - margin-top: -5px; - border-width: 0 5px 5px; - border-bottom-color: #000; -} -.tooltip.bottom-right .tooltip-arrow { - top: 0; - left: 5px; - margin-top: -5px; - border-width: 0 5px 5px; - border-bottom-color: #000; -} -.popover { - position: absolute; - top: 0; - left: 0; - z-index: 1060; - display: none; - max-width: 276px; - padding: 1px; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 14px; - font-style: normal; - font-weight: normal; - line-height: 1.42857143; - text-align: left; - text-align: start; - text-decoration: none; - text-shadow: none; - text-transform: none; - letter-spacing: normal; - word-break: normal; - word-spacing: normal; - word-wrap: normal; - white-space: normal; - background-color: #fff; - -webkit-background-clip: padding-box; - background-clip: padding-box; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, .2); - border-radius: 6px; - -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2); - box-shadow: 0 5px 10px rgba(0, 0, 0, .2); - - line-break: auto; -} -.popover.top { - margin-top: -10px; -} -.popover.right { - margin-left: 10px; -} -.popover.bottom { - margin-top: 10px; -} -.popover.left { - margin-left: -10px; -} -.popover-title { - padding: 8px 14px; - margin: 0; - font-size: 14px; - background-color: #f7f7f7; - border-bottom: 1px solid #ebebeb; - border-radius: 5px 5px 0 0; -} -.popover-content { - padding: 9px 14px; -} -.popover > .arrow, -.popover > .arrow:after { - position: absolute; - display: block; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; -} -.popover > .arrow { - border-width: 11px; -} -.popover > .arrow:after { - content: ""; - border-width: 10px; -} -.popover.top > .arrow { - bottom: -11px; - left: 50%; - margin-left: -11px; - border-top-color: #999; - border-top-color: rgba(0, 0, 0, .25); - border-bottom-width: 0; -} -.popover.top > .arrow:after { - bottom: 1px; - margin-left: -10px; - content: " "; - border-top-color: #fff; - border-bottom-width: 0; -} -.popover.right > .arrow { - top: 50%; - left: -11px; - margin-top: -11px; - border-right-color: #999; - border-right-color: rgba(0, 0, 0, .25); - border-left-width: 0; -} -.popover.right > .arrow:after { - bottom: -10px; - left: 1px; - content: " "; - border-right-color: #fff; - border-left-width: 0; -} -.popover.bottom > .arrow { - top: -11px; - left: 50%; - margin-left: -11px; - border-top-width: 0; - border-bottom-color: #999; - border-bottom-color: rgba(0, 0, 0, .25); -} -.popover.bottom > .arrow:after { - top: 1px; - margin-left: -10px; - content: " "; - border-top-width: 0; - border-bottom-color: #fff; -} -.popover.left > .arrow { - top: 50%; - right: -11px; - margin-top: -11px; - border-right-width: 0; - border-left-color: #999; - border-left-color: rgba(0, 0, 0, .25); -} -.popover.left > .arrow:after { - right: 1px; - bottom: -10px; - content: " "; - border-right-width: 0; - border-left-color: #fff; -} -.carousel { - position: relative; -} -.carousel-inner { - position: relative; - width: 100%; - overflow: hidden; -} -.carousel-inner > .item { - position: relative; - display: none; - -webkit-transition: .6s ease-in-out left; - -o-transition: .6s ease-in-out left; - transition: .6s ease-in-out left; -} -.carousel-inner > .item > img, -.carousel-inner > .item > a > img { - line-height: 1; -} -@media all and (transform-3d), (-webkit-transform-3d) { - .carousel-inner > .item { - -webkit-transition: -webkit-transform .6s ease-in-out; - -o-transition: -o-transform .6s ease-in-out; - transition: transform .6s ease-in-out; - - -webkit-backface-visibility: hidden; - backface-visibility: hidden; - -webkit-perspective: 1000px; - perspective: 1000px; - } - .carousel-inner > .item.next, - .carousel-inner > .item.active.right { - left: 0; - -webkit-transform: translate3d(100%, 0, 0); - transform: translate3d(100%, 0, 0); - } - .carousel-inner > .item.prev, - .carousel-inner > .item.active.left { - left: 0; - -webkit-transform: translate3d(-100%, 0, 0); - transform: translate3d(-100%, 0, 0); - } - .carousel-inner > .item.next.left, - .carousel-inner > .item.prev.right, - .carousel-inner > .item.active { - left: 0; - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - } -} -.carousel-inner > .active, -.carousel-inner > .next, -.carousel-inner > .prev { - display: block; -} -.carousel-inner > .active { - left: 0; -} -.carousel-inner > .next, -.carousel-inner > .prev { - position: absolute; - top: 0; - width: 100%; -} -.carousel-inner > .next { - left: 100%; -} -.carousel-inner > .prev { - left: -100%; -} -.carousel-inner > .next.left, -.carousel-inner > .prev.right { - left: 0; -} -.carousel-inner > .active.left { - left: -100%; -} -.carousel-inner > .active.right { - left: 100%; -} -.carousel-control { - position: absolute; - top: 0; - bottom: 0; - left: 0; - width: 15%; - font-size: 20px; - color: #fff; - text-align: center; - text-shadow: 0 1px 2px rgba(0, 0, 0, .6); - background-color: rgba(0, 0, 0, 0); - filter: alpha(opacity=50); - opacity: .5; -} -.carousel-control.left { - background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); - background-image: -o-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); - background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .5)), to(rgba(0, 0, 0, .0001))); - background-image: linear-gradient(to right, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); - background-repeat: repeat-x; -} -.carousel-control.right { - right: 0; - left: auto; - background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); - background-image: -o-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); - background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .0001)), to(rgba(0, 0, 0, .5))); - background-image: linear-gradient(to right, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); - background-repeat: repeat-x; -} -.carousel-control:hover, -.carousel-control:focus { - color: #fff; - text-decoration: none; - filter: alpha(opacity=90); - outline: 0; - opacity: .9; -} -.carousel-control .icon-prev, -.carousel-control .icon-next, -.carousel-control .glyphicon-chevron-left, -.carousel-control .glyphicon-chevron-right { - position: absolute; - top: 50%; - z-index: 5; - display: inline-block; - margin-top: -10px; -} -.carousel-control .icon-prev, -.carousel-control .glyphicon-chevron-left { - left: 50%; - margin-left: -10px; -} -.carousel-control .icon-next, -.carousel-control .glyphicon-chevron-right { - right: 50%; - margin-right: -10px; -} -.carousel-control .icon-prev, -.carousel-control .icon-next { - width: 20px; - height: 20px; - font-family: serif; - line-height: 1; -} -.carousel-control .icon-prev:before { - content: '\2039'; -} -.carousel-control .icon-next:before { - content: '\203a'; -} -.carousel-indicators { - position: absolute; - bottom: 10px; - left: 50%; - z-index: 15; - width: 60%; - padding-left: 0; - margin-left: -30%; - text-align: center; - list-style: none; -} -.carousel-indicators li { - display: inline-block; - width: 10px; - height: 10px; - margin: 1px; - text-indent: -999px; - cursor: pointer; - background-color: #000 \9; - background-color: rgba(0, 0, 0, 0); - border: 1px solid #fff; - border-radius: 10px; -} -.carousel-indicators .active { - width: 12px; - height: 12px; - margin: 0; - background-color: #fff; -} -.carousel-caption { - position: absolute; - right: 15%; - bottom: 20px; - left: 15%; - z-index: 10; - padding-top: 20px; - padding-bottom: 20px; - color: #fff; - text-align: center; - text-shadow: 0 1px 2px rgba(0, 0, 0, .6); -} -.carousel-caption .btn { - text-shadow: none; -} -@media screen and (min-width: 768px) { - .carousel-control .glyphicon-chevron-left, - .carousel-control .glyphicon-chevron-right, - .carousel-control .icon-prev, - .carousel-control .icon-next { - width: 30px; - height: 30px; - margin-top: -10px; - font-size: 30px; - } - .carousel-control .glyphicon-chevron-left, - .carousel-control .icon-prev { - margin-left: -10px; - } - .carousel-control .glyphicon-chevron-right, - .carousel-control .icon-next { - margin-right: -10px; - } - .carousel-caption { - right: 20%; - left: 20%; - padding-bottom: 30px; - } - .carousel-indicators { - bottom: 20px; - } -} -.clearfix:before, -.clearfix:after, -.dl-horizontal dd:before, -.dl-horizontal dd:after, -.container:before, -.container:after, -.container-fluid:before, -.container-fluid:after, -.row:before, -.row:after, -.form-horizontal .form-group:before, -.form-horizontal .form-group:after, -.btn-toolbar:before, -.btn-toolbar:after, -.btn-group-vertical > .btn-group:before, -.btn-group-vertical > .btn-group:after, -.nav:before, -.nav:after, -.navbar:before, -.navbar:after, -.navbar-header:before, -.navbar-header:after, -.navbar-collapse:before, -.navbar-collapse:after, -.pager:before, -.pager:after, -.panel-body:before, -.panel-body:after, -.modal-header:before, -.modal-header:after, -.modal-footer:before, -.modal-footer:after { - display: table; - content: " "; -} -.clearfix:after, -.dl-horizontal dd:after, -.container:after, -.container-fluid:after, -.row:after, -.form-horizontal .form-group:after, -.btn-toolbar:after, -.btn-group-vertical > .btn-group:after, -.nav:after, -.navbar:after, -.navbar-header:after, -.navbar-collapse:after, -.pager:after, -.panel-body:after, -.modal-header:after, -.modal-footer:after { - clear: both; -} -.center-block { - display: block; - margin-right: auto; - margin-left: auto; -} -.pull-right { - float: right !important; -} -.pull-left { - float: left !important; -} -.hide { - display: none !important; -} -.show { - display: block !important; -} -.invisible { - visibility: hidden; -} -.text-hide { - font: 0/0 a; - color: transparent; - text-shadow: none; - background-color: transparent; - border: 0; -} -.hidden { - display: none !important; -} -.affix { - position: fixed; -} -@-ms-viewport { - width: device-width; -} -.visible-xs, -.visible-sm, -.visible-md, -.visible-lg { - display: none !important; -} -.visible-xs-block, -.visible-xs-inline, -.visible-xs-inline-block, -.visible-sm-block, -.visible-sm-inline, -.visible-sm-inline-block, -.visible-md-block, -.visible-md-inline, -.visible-md-inline-block, -.visible-lg-block, -.visible-lg-inline, -.visible-lg-inline-block { - display: none !important; -} -@media (max-width: 767px) { - .visible-xs { - display: block !important; - } - table.visible-xs { - display: table !important; - } - tr.visible-xs { - display: table-row !important; - } - th.visible-xs, - td.visible-xs { - display: table-cell !important; - } -} -@media (max-width: 767px) { - .visible-xs-block { - display: block !important; - } -} -@media (max-width: 767px) { - .visible-xs-inline { - display: inline !important; - } -} -@media (max-width: 767px) { - .visible-xs-inline-block { - display: inline-block !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .visible-sm { - display: block !important; - } - table.visible-sm { - display: table !important; - } - tr.visible-sm { - display: table-row !important; - } - th.visible-sm, - td.visible-sm { - display: table-cell !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .visible-sm-block { - display: block !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .visible-sm-inline { - display: inline !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .visible-sm-inline-block { - display: inline-block !important; - } -} -@media (min-width: 992px) and (max-width: 1199px) { - .visible-md { - display: block !important; - } - table.visible-md { - display: table !important; - } - tr.visible-md { - display: table-row !important; - } - th.visible-md, - td.visible-md { - display: table-cell !important; - } -} -@media (min-width: 992px) and (max-width: 1199px) { - .visible-md-block { - display: block !important; - } -} -@media (min-width: 992px) and (max-width: 1199px) { - .visible-md-inline { - display: inline !important; - } -} -@media (min-width: 992px) and (max-width: 1199px) { - .visible-md-inline-block { - display: inline-block !important; - } -} -@media (min-width: 1200px) { - .visible-lg { - display: block !important; - } - table.visible-lg { - display: table !important; - } - tr.visible-lg { - display: table-row !important; - } - th.visible-lg, - td.visible-lg { - display: table-cell !important; - } -} -@media (min-width: 1200px) { - .visible-lg-block { - display: block !important; - } -} -@media (min-width: 1200px) { - .visible-lg-inline { - display: inline !important; - } -} -@media (min-width: 1200px) { - .visible-lg-inline-block { - display: inline-block !important; - } -} -@media (max-width: 767px) { - .hidden-xs { - display: none !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .hidden-sm { - display: none !important; - } -} -@media (min-width: 992px) and (max-width: 1199px) { - .hidden-md { - display: none !important; - } -} -@media (min-width: 1200px) { - .hidden-lg { - display: none !important; - } -} -.visible-print { - display: none !important; -} -@media print { - .visible-print { - display: block !important; - } - table.visible-print { - display: table !important; - } - tr.visible-print { - display: table-row !important; - } - th.visible-print, - td.visible-print { - display: table-cell !important; - } -} -.visible-print-block { - display: none !important; -} -@media print { - .visible-print-block { - display: block !important; - } -} -.visible-print-inline { - display: none !important; -} -@media print { - .visible-print-inline { - display: inline !important; - } -} -.visible-print-inline-block { - display: none !important; -} -@media print { - .visible-print-inline-block { - display: inline-block !important; - } -} -@media print { - .hidden-print { - display: none !important; - } -} -/*# sourceMappingURL=bootstrap.css.map */ diff --git a/wiresx/finish.php b/wiresx/finish.php deleted file mode 100644 index 261cdc7..0000000 --- a/wiresx/finish.php +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - Set Frequency - - - - - -
-

Hot-Spot Frequencies Summary

-

Hot-spot Callsign:

-

Transmit Frequency: MHz

-

Receive Frequency: MHz

-

It can take up to 15 minutes for the frequency data to be available to the reflector. Please be patient.

-
-

- Reset Frequencies - Reset Your Password - Sign Out of Your Account -

- - diff --git a/wiresx/frequency.php b/wiresx/frequency.php deleted file mode 100644 index d89a42d..0000000 --- a/wiresx/frequency.php +++ /dev/null @@ -1,126 +0,0 @@ - 1000.0 || $txfreq < 10.0) { - $txfreq_err = "TX out of range."; - } - // Validate confirm password - if ($rxfreq > 1000.0 || $rxfreq < 10.0) { - $rxfreq_err = "RX out of range."; - } - - // Check input errors before updating the database - if (empty($txfreq_err) && empty($rxfreq_err)) { - // Prepare an update statement - $sql = "UPDATE ysfnodes SET txfreq = ?, rxfreq = ? WHERE callsign = ?"; - - if($stmt = mysqli_prepare($link, $sql)){ - // Bind variables to the prepared statement as parameters - $tx_freq_hz = $_POST["txfreq"] * 1000000; - $rx_freq_hz = $_POST["rxfreq"] * 1000000; - mysqli_stmt_bind_param($stmt, "iis", $tx_freq_hz, $rx_freq_hz, $_SESSION["callsign"]); - - // Attempt to execute the prepared statement - if(mysqli_stmt_execute($stmt)){ - // Frequencies updated successfully, go to summary - header("location: finish.php"); - exit(); - } else{ - echo "Oops! Something went wrong. Please try again later."; - } - - // Close statement - mysqli_stmt_close($stmt); - } - } - - // Close connection - mysqli_close($link); -} -?> - - - - - - Set Frequency - - - - - -
-

Hot-Spot Frequencies

-

Set your hot-spot frequencies (in MHz) here.

-
" method="post"> -
- - - -
-
- - - -
-
- - Cancel -
-
-
-

- Reset Your Password - Sign Out of Your Account -

- - diff --git a/wiresx/login.php b/wiresx/login.php deleted file mode 100644 index ba7038a..0000000 --- a/wiresx/login.php +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - Login - - - - -
-

Login

-

Login with your hot-spot callsign.

-
" method="post"> -
- - - -
-
- - - -
-
- -
-

Don't have an account? Sign up now.

-
-
- - diff --git a/wiresx/logout.php b/wiresx/logout.php deleted file mode 100644 index 8fc70a3..0000000 --- a/wiresx/logout.php +++ /dev/null @@ -1,14 +0,0 @@ - diff --git a/wiresx/register.php b/wiresx/register.php deleted file mode 100644 index b92bba5..0000000 --- a/wiresx/register.php +++ /dev/null @@ -1,148 +0,0 @@ - 7) { - $callsign_err = "Callsign is too long."; - } else if (! IsValidCallsign(strtoupper(trim($_POST["callsign"])))) { - $callsign_err = "Not a valid callsign."; - } else { - // Prepare a select statement - $sql = "SELECT * FROM ysfnodes WHERE callsign = ?"; - - if ($stmt = mysqli_prepare($link, $sql)) { - // Bind variables to the prepared statement as parameters - mysqli_stmt_bind_param($stmt, "s", $param_callsign); - - // Set parameters - $param_callsign = strtoupper(trim($_POST["callsign"])); - - // Attempt to execute the prepared statement - if (mysqli_stmt_execute($stmt)) { - /* store result */ - mysqli_stmt_store_result($stmt); - - if (mysqli_stmt_num_rows($stmt) == 1) { - $callsign_err = "This callsign is already taken."; - } else { - $callsign = strtoupper(trim($_POST["callsign"])); - } - } else { - echo "Oops! Something went wrong. Please try again later."; - } - - // Close statement - mysqli_stmt_close($stmt); - } - } - - // Validate password - if (empty(trim($_POST["password"]))) { - $password_err = "Please enter a password."; - } elseif (strlen(trim($_POST["password"])) < 6) { - $password_err = "Password must have atleast 6 characters."; - } else { - $password = trim($_POST["password"]); - } - - // Validate confirm password - if (empty(trim($_POST["confirm_password"]))) { - $confirm_password_err = "Please confirm password."; - } else { - $confirm_password = trim($_POST["confirm_password"]); - if(empty($password_err) && ($password != $confirm_password)){ - $confirm_password_err = "Password did not match."; - } - } - - // Check input errors before inserting in database - if (empty($callsign_err) && empty($password_err) && empty($confirm_password_err)) { - - // Prepare an insert statement - $sql = "INSERT INTO ysfnodes (callsign, password) VALUES (?, ?)"; - - if ($stmt = mysqli_prepare($link, $sql)) { - // Bind variables to the prepared statement as parameters - mysqli_stmt_bind_param($stmt, "ss", $param_callsign, $param_password); - - // Set parameters - $param_callsign = $callsign; - $param_password = password_hash($password, PASSWORD_DEFAULT); // Creates a password hash - - // Attempt to execute the prepared statement - if (mysqli_stmt_execute($stmt)) { - // Redirect to login page - header("location: login.php"); - } else { - echo "Something went wrong. Please try again later."; - } - - // Close statement - mysqli_stmt_close($stmt); - } - } - - // Close connection - mysqli_close($link); -} -?> - - - - - - Hot-Spot Frequency for WiresX Registration - - - - -
-

Sign Up

-

Please fill this form to create an account. Use your hot-spot callsign to register.

-
" method="post"> -
- - - -
-
- - - -
-
- - - -
-
- - -
-

Already have an account? Login here.

-
-
- - diff --git a/wiresx/reset-password.php b/wiresx/reset-password.php deleted file mode 100644 index 94f5569..0000000 --- a/wiresx/reset-password.php +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - - Reset Password - - - - -
-

Reset Password

-

Please fill out this form to reset your password.

-
" method="post"> -
- - - -
-
- - - -
-
- - Cancel -
-
-
- - From 9b1df226a4b17f4428ecaaf03dba7a6fed555f73 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Thu, 2 Mar 2023 09:21:01 -0700 Subject: [PATCH 30/44] USRP parameters for two-way client --- config/urfd.ini | 7 ++++--- reflector/Configure.cpp | 13 +++++++++---- reflector/JsonKeys.h | 4 ++-- reflector/Protocols.cpp | 2 +- reflector/USRPProtocol.cpp | 38 +++++++++++++++++++++++--------------- reflector/USRPProtocol.h | 3 ++- 6 files changed, 41 insertions(+), 26 deletions(-) diff --git a/config/urfd.ini b/config/urfd.ini index 94d3da6..dcc5b73 100644 --- a/config/urfd.ini +++ b/config/urfd.ini @@ -12,7 +12,7 @@ Country = GB Sponsor = My Home Club -[IpAddresses] +[IP Addresses] # Binding addresses are usually the 'any' address IPv4Binding = 0.0.0.0 @@ -80,10 +80,11 @@ Port = 10017 [USRP] Enable = false -Port = 32000 +RxPort = 34000 +TxPort = 32000 Module = A # this has to be a transcoded module! Callsign = ALLSTAR -#FilePath = /home/usr/Clients.txt # An experimental area of development +#FilePath = /home/usr/Clients.txt [YSF] Port = 42000 diff --git a/reflector/Configure.cpp b/reflector/Configure.cpp index 68e9513..84efc86 100644 --- a/reflector/Configure.cpp +++ b/reflector/Configure.cpp @@ -51,7 +51,7 @@ #define JG3 "G3" #define JG3TERMINALPATH "G3TerminalPath" #define JINTERLINKPATH "InterlinkPath" -#define JIPADDRESSES "IpAddresses" +#define JIPADDRESSES "IP Addresses" #define JIPV4BINDING "IPv4Binding" #define JIPV4EXTERNAL "IPv4External" #define JIPV6BINDING "IPv6Binding" @@ -73,10 +73,12 @@ #define JREGISTRATIONDESCRIPTION "RegistrationDescription" #define JREGISTRATIONID "RegistrationID" #define JREGISTRATIONNAME "RegistrationName" +#define JRXPORT "RxPort" #define JSPONSOR "Sponsor" #define JSYSOPEMAIL "SysopEmail" #define JTRANSCODED "Transcoded" #define JTRANSCODER "Transcoder" +#define JTXPORT "TxPort" #define JURF "URF" #define JURL "URL" #define JUSRP "USRP" @@ -396,8 +398,10 @@ bool CConfigure::ReadData(const std::string &path) case ESection::usrp: if (0 == key.compare(JENABLE)) data[g_Keys.usrp.enable] = IS_TRUE(value[0]); - else if (0 == key.compare(JPORT)) - data[g_Keys.usrp.port] = getUnsigned(value, "USRP Port", 1024, 65535, 32000); + else if (0 == key.compare(JTXPORT)) + data[g_Keys.usrp.txport] = getUnsigned(value, "USRP TxPort", 1024, 65535, 32000); + else if (0 == key.compare(JRXPORT)) + data[g_Keys.usrp.rxport] = getUnsigned(value, "USRP RxPort", 1024, 65535, 34000); else if (0 == key.compare(JMODULE)) data[g_Keys.usrp.module] = value.substr(0, 1); else if (0 == key.compare(JCALLSIGN)) @@ -684,7 +688,8 @@ bool CConfigure::ReadData(const std::string &path) rval = true; } } - isDefined(ErrorLevel::fatal, JUSRP, JPORT, g_Keys.usrp.port, rval); + isDefined(ErrorLevel::fatal, JUSRP, JTXPORT, g_Keys.usrp.txport, rval); + isDefined(ErrorLevel::fatal, JUSRP, JRXPORT, g_Keys.usrp.rxport, rval); isDefined(ErrorLevel::fatal, JUSRP, JCALLSIGN, g_Keys.usrp.callsign, rval); //if (isDefined(ErrorLevel::fatal, JUSRP, JFILEPATH, g_Keys.usrp.filepath, rval)) if (data.contains(g_Keys.usrp.filepath)) diff --git a/reflector/JsonKeys.h b/reflector/JsonKeys.h index 77a7cae..105e700 100644 --- a/reflector/JsonKeys.h +++ b/reflector/JsonKeys.h @@ -49,8 +49,8 @@ struct SJsonKeys { modules { "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" }; - struct USRP { const std::string enable, port, module, callsign, filepath; } - usrp { "usrpEnable", "urspPort", "usrpModule", "usrpCallsign", "usrpFilePath" }; + struct USRP { const std::string enable, txport,rxport, module, callsign, filepath; } + usrp { "usrpEnable", "urspTxPort", "usrpRxPort", "usrpModule", "usrpCallsign", "usrpFilePath" }; struct P25NXDN { const std::string port, autolinkmod, reflectorid; } p25 { "P25Port", "P25AutolinkMod", "P25ReflectorID" }, diff --git a/reflector/Protocols.cpp b/reflector/Protocols.cpp index f79b683..6781573 100644 --- a/reflector/Protocols.cpp +++ b/reflector/Protocols.cpp @@ -94,7 +94,7 @@ bool CProtocols::Init(void) if (g_Conf.GetBoolean(g_Keys.usrp.enable)) { m_Protocols.emplace_back(std::unique_ptr(new CUSRPProtocol)); - if (! m_Protocols.back()->Initialize("USRP", EProtocol::usrp, uint16_t(g_Conf.GetUnsigned(g_Keys.usrp.port)), USRP_IPV4, USRP_IPV6)) + if (! m_Protocols.back()->Initialize("USRP", EProtocol::usrp, uint16_t(g_Conf.GetUnsigned(g_Keys.usrp.rxport)), USRP_IPV4, USRP_IPV6)) return false; } diff --git a/reflector/USRPProtocol.cpp b/reflector/USRPProtocol.cpp index f9b49cd..7738680 100644 --- a/reflector/USRPProtocol.cpp +++ b/reflector/USRPProtocol.cpp @@ -1,4 +1,7 @@ +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. + // urfd -- The universal reflector +// Copyright © 2023 Thomas A. Early N7TAE // Copyright © 2023 Doug McLain AD8DP // // This program is free software: you can redistribute it and/or modify @@ -14,7 +17,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . - +#include "Defines.h" #include #include "USRPClient.h" #include "USRPProtocol.h" @@ -39,13 +42,21 @@ bool CUSRPProtocol::Initialize(const char *type, const EProtocol ptype, const ui std::ifstream file; std::streampos size; - // base class + // base class, create the listing port for the read-write client if (! CProtocol::Initialize(type, ptype, port, has_ipv4, has_ipv6)) return false; - m_CStr.assign(g_Conf.GetString(g_Keys.usrp.callsign)); - m_Module = g_Conf.GetString(g_Keys.usrp.module).at(0); + m_Module = g_Conf.GetAutolinkModule(g_Keys.usrp.module); + // create the one special USRP Tx/Rx client + m_Callsign.SetCallsign(g_Conf.GetString(g_Keys.usrp.callsign), false); + CIp ip(AF_INET, uint16_t(g_Conf.GetUnsigned(g_Keys.usrp.txport)), g_Conf.GetString(g_Keys.ip.ipv4bind).c_str()); + auto newclient = std::make_shared(m_Callsign, ip); + newclient->SetReflectorModule(m_Module); + g_Refl.GetClients()->AddClient(newclient); + g_Refl.ReleaseClients(); + + // now create "listen-only" clients, as many as specified file.open(g_Conf.GetString(g_Keys.usrp.filepath), std::ios::in | std::ios::binary | std::ios::ate); if ( file.is_open() ) { @@ -79,9 +90,10 @@ bool CUSRPProtocol::Initialize(const char *type, const EProtocol ptype, const ui ((port = ::strtok(nullptr, ";")) != nullptr) && ((clientcs = ::strtok(nullptr, ";")) != nullptr) ) { - uint32_t ui = atoi(port); + uint16_t ui = atoi(port); CIp Ip(AF_INET, ui, ip); - CCallsign cs(clientcs); + CCallsign cs; + cs.SetCallsign(clientcs, false); auto newclient = std::make_shared(cs, Ip); newclient->SetReflectorModule(m_Module); g_Refl.GetClients()->AddClient(newclient); @@ -274,14 +286,12 @@ bool CUSRPProtocol::IsValidDvPacket(const CIp &Ip, const CBuffer &Buffer, std::u if ( !stream ) { m_uiStreamId = static_cast(::rand()); - CCallsign csMY, rpt1, rpt2, csUR; - csMY.SetCallsign(m_CStr, false); - rpt1.SetCallsign(m_CStr, false); - rpt2 = m_ReflectorCallsign; - csUR.SetCallsign("CQCQCQ", false); + CCallsign csMY; + CCallsign rpt1 = m_Callsign; + CCallsign rpt2 = m_ReflectorCallsign; rpt1.SetCSModule(m_Module); rpt2.SetCSModule(' '); - header = std::unique_ptr(new CDvHeaderPacket(csMY, csUR, rpt1, rpt2, m_uiStreamId, true)); + header = std::unique_ptr(new CDvHeaderPacket(csMY, CCallsign("CQCQCQ"), rpt1, rpt2, m_uiStreamId, true)); OnDvHeaderPacketIn(header, Ip); } @@ -307,11 +317,9 @@ bool CUSRPProtocol::IsValidDvHeaderPacket(const CIp &Ip, const CBuffer &Buffer, CCallsign csMY = CCallsign("", uiSrcId); CCallsign rpt1 = CCallsign("", uiSrcId); CCallsign rpt2 = m_ReflectorCallsign; - CCallsign csUR; - csUR.SetCallsign("CQCQCQ", false); rpt1.SetCSModule(m_Module); rpt2.SetCSModule(' '); - header = std::unique_ptr(new CDvHeaderPacket(csMY, csUR, rpt1, rpt2, m_uiStreamId, true)); + header = std::unique_ptr(new CDvHeaderPacket(csMY, CCallsign("CQCQCQ"), rpt1, rpt2, m_uiStreamId, true)); } return true; } diff --git a/reflector/USRPProtocol.h b/reflector/USRPProtocol.h index 1509ca6..9420971 100644 --- a/reflector/USRPProtocol.h +++ b/reflector/USRPProtocol.h @@ -70,6 +70,7 @@ protected: private: // CConfigure data - std::string m_CStr; + CCallsign m_Callsign; char m_Module; + uint16_t m_txPort; }; From f245d4299dad3ec76e2f2b5d85b264bca13d5dc8 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Fri, 3 Mar 2023 07:42:42 -0700 Subject: [PATCH 31/44] rename globals & fix Lookup file logic --- reflector/BMProtocol.cpp | 46 +++++++++++----------- reflector/CallsignListItem.cpp | 4 +- reflector/Clients.cpp | 4 +- reflector/DCSProtocol.cpp | 36 ++++++++--------- reflector/DExtraProtocol.cpp | 48 +++++++++++------------ reflector/DMRMMDVMProtocol.cpp | 50 ++++++++++++------------ reflector/DMRPlusProtocol.cpp | 40 +++++++++---------- reflector/DPlusProtocol.cpp | 36 ++++++++--------- reflector/G3Protocol.cpp | 46 +++++++++++----------- reflector/GateKeeper.cpp | 6 +-- reflector/Global.h | 8 ++-- reflector/Lookup.cpp | 3 +- reflector/Lookup.h | 4 +- reflector/LookupDmr.cpp | 8 ++-- reflector/LookupNxdn.cpp | 8 ++-- reflector/LookupYsf.cpp | 12 +++--- reflector/M17Protocol.cpp | 38 +++++++++--------- reflector/Main.cpp | 26 ++++++------- reflector/NXDNProtocol.cpp | 38 +++++++++--------- reflector/P25Protocol.cpp | 36 ++++++++--------- reflector/Peers.cpp | 12 +++--- reflector/Protocol.cpp | 8 ++-- reflector/Protocols.cpp | 30 +++++++-------- reflector/Reflector.cpp | 14 +++---- reflector/URFProtocol.cpp | 70 +++++++++++++++++----------------- reflector/USRPProtocol.cpp | 36 ++++++++--------- reflector/Users.cpp | 4 +- reflector/WiresXCmdHandler.cpp | 24 ++++++------ reflector/YSFProtocol.cpp | 50 ++++++++++++------------ 29 files changed, 372 insertions(+), 373 deletions(-) diff --git a/reflector/BMProtocol.cpp b/reflector/BMProtocol.cpp index 0b6018b..f16752d 100644 --- a/reflector/BMProtocol.cpp +++ b/reflector/BMProtocol.cpp @@ -27,7 +27,7 @@ bool CBMProtocol::Initialize(const char *type, const EProtocol ptype, const uint16_t port, const bool has_ipv4, const bool has_ipv6) { - m_HasTranscoder = g_Conf.IsString(g_Keys.modules.tcmodules); + m_HasTranscoder = g_Configure.IsString(g_Keys.modules.tcmodules); if (! CProtocol::Initialize(type, ptype, port, has_ipv4, has_ipv6)) return false; @@ -71,7 +71,7 @@ void CBMProtocol::Task(void) else if ( IsValidDvHeaderPacket(Buffer, Header) ) { // callsign allowed? - if ( g_Gate.MayTransmit(Header->GetMyCallsign(), Ip) ) + if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip) ) { OnDvHeaderPacketIn(Header, Ip); } @@ -81,7 +81,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_Gate.MayLink(Callsign, Ip, EProtocol::bm, Modules) ) + if ( g_GateKeeper.MayLink(Callsign, Ip, EProtocol::bm, Modules) ) { // acknowledge the request EncodeConnectAckPacket(&Buffer, Modules); @@ -99,10 +99,10 @@ void CBMProtocol::Task(void) std::cout << "XLX ack packet for modules " << Modules << " from " << Callsign << " at " << Ip << std::endl; // callsign authorized? - if ( g_Gate.MayLink(Callsign, Ip, EProtocol::bm, Modules) ) + if ( g_GateKeeper.MayLink(Callsign, Ip, EProtocol::bm, Modules) ) { // already connected ? - CPeers *peers = g_Refl.GetPeers(); + CPeers *peers = g_Reflector.GetPeers(); if ( peers->FindPeer(Callsign, Ip, EProtocol::bm) == nullptr ) { // create the new peer @@ -113,7 +113,7 @@ void CBMProtocol::Task(void) // this also add all new clients to reflector client list peers->AddPeer(peer); } - g_Refl.ReleasePeers(); + g_Reflector.ReleasePeers(); } } else if ( IsValidDisconnectPacket(Buffer, &Callsign) ) @@ -121,7 +121,7 @@ void CBMProtocol::Task(void) std::cout << "XLX disconnect packet from " << Callsign << " at " << Ip << std::endl; // find peer - CPeers *peers = g_Refl.GetPeers(); + CPeers *peers = g_Reflector.GetPeers(); std::shared_ptrpeer = peers->FindPeer(Ip, EProtocol::bm); if ( peer != nullptr ) { @@ -130,7 +130,7 @@ void CBMProtocol::Task(void) // and delete them peers->RemovePeer(peer); } - g_Refl.ReleasePeers(); + g_Reflector.ReleasePeers(); } else if ( IsValidNackPacket(Buffer, &Callsign) ) { @@ -141,14 +141,14 @@ void CBMProtocol::Task(void) //std::cout << "XLX keepalive packet from " << Callsign << " at " << Ip << std::endl; // find peer - CPeers *peers = g_Refl.GetPeers(); + CPeers *peers = g_Reflector.GetPeers(); std::shared_ptrpeer = peers->FindPeer(Ip, EProtocol::bm); if ( peer != nullptr ) { // keep it alive peer->Alive(); } - g_Refl.ReleasePeers(); + g_Reflector.ReleasePeers(); } else { @@ -207,7 +207,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_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::bm, it)) != nullptr ) @@ -233,7 +233,7 @@ void CBMProtocol::HandleQueue(void) } } } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } } } @@ -250,7 +250,7 @@ void CBMProtocol::HandleKeepalives(void) EncodeKeepAlivePacket(&keepalive); // iterate on peers - CPeers *peers = g_Refl.GetPeers(); + CPeers *peers = g_Reflector.GetPeers(); auto pit = peers->begin(); std::shared_ptrpeer = nullptr; while ( (peer = peers->FindNextPeer(EProtocol::bm, pit)) != nullptr ) @@ -277,7 +277,7 @@ void CBMProtocol::HandleKeepalives(void) peers->RemovePeer(peer); } } - g_Refl.ReleasePeers(); + g_Reflector.ReleasePeers(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -288,8 +288,8 @@ void CBMProtocol::HandlePeerLinks(void) CBuffer buffer; // get the list of peers - CPeerCallsignList *list = g_Gate.GetPeerList(); - CPeers *peers = g_Refl.GetPeers(); + CPeerCallsignList *list = g_GateKeeper.GetPeerList(); + CPeers *peers = g_Reflector.GetPeers(); // check if all our connected peers are still listed by gatekeeper // if not, disconnect @@ -325,8 +325,8 @@ void CBMProtocol::HandlePeerLinks(void) } // done - g_Refl.ReleasePeers(); - g_Gate.ReleasePeerList(); + g_Reflector.ReleasePeers(); + g_GateKeeper.ReleasePeerList(); } @@ -355,11 +355,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_Refl.GetClients()->FindClient(Ip, EProtocol::bm, Header->GetRpt2Module()); + std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, EProtocol::bm, Header->GetRpt2Module()); if ( client ) { // and try to open the stream - if ( (stream = g_Refl.OpenStream(Header, client)) != nullptr ) + if ( (stream = g_Reflector.OpenStream(Header, client)) != nullptr ) { // keep the handle m_Streams[stream->GetStreamId()] = stream; @@ -368,10 +368,10 @@ void CBMProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header, c peer = client->GetCallsign(); } // release - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); // update last heard - g_Refl.GetUsers()->Hearing(my, rpt1, rpt2, peer); - g_Refl.ReleaseUsers(); + g_Reflector.GetUsers()->Hearing(my, rpt1, rpt2, peer); + g_Reflector.ReleaseUsers(); } } diff --git a/reflector/CallsignListItem.cpp b/reflector/CallsignListItem.cpp index 27cfba8..40328bf 100644 --- a/reflector/CallsignListItem.cpp +++ b/reflector/CallsignListItem.cpp @@ -33,7 +33,7 @@ CCallsignListItem::CCallsignListItem() CCallsignListItem::CCallsignListItem(const CCallsign &callsign, const CIp &ip, const char *modules) { - const std::string mods(g_Conf.GetString(g_Keys.modules.modules)); + const std::string mods(g_Configure.GetString(g_Keys.modules.modules)); m_Callsign = callsign; memset(m_szUrl, 0, sizeof(m_szUrl)); m_Ip = ip; @@ -60,7 +60,7 @@ CCallsignListItem::CCallsignListItem(const CCallsign &callsign, const CIp &ip, c CCallsignListItem::CCallsignListItem(const CCallsign &callsign, const char *url, const char *modules) { - const std::string mods(g_Conf.GetString(g_Keys.modules.modules)); + const std::string mods(g_Configure.GetString(g_Keys.modules.modules)); m_Callsign = callsign; ::strncpy(m_szUrl, url, URL_MAXLEN); m_Ip = CIp(m_szUrl); diff --git a/reflector/Clients.cpp b/reflector/Clients.cpp index b53455e..fcddd63 100644 --- a/reflector/Clients.cpp +++ b/reflector/Clients.cpp @@ -64,7 +64,7 @@ void CClients::AddClient(std::shared_ptr client) } std::cout << std::endl; // notify - g_Refl.OnClientsChanged(); + g_Reflector.OnClientsChanged(); } void CClients::RemoveClient(std::shared_ptr client) @@ -88,7 +88,7 @@ void CClients::RemoveClient(std::shared_ptr client) std::cout << std::endl; m_Clients.erase(it); // notify - g_Refl.OnClientsChanged(); + g_Reflector.OnClientsChanged(); break; } } diff --git a/reflector/DCSProtocol.cpp b/reflector/DCSProtocol.cpp index 0efecfe..29dc576 100644 --- a/reflector/DCSProtocol.cpp +++ b/reflector/DCSProtocol.cpp @@ -67,7 +67,7 @@ void CDcsProtocol::Task(void) if ( IsValidDvPacket(Buffer, Header, Frame) ) { // callsign muted? - if ( g_Gate.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::dcs, Header->GetRpt2Module()) ) + if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::dcs, Header->GetRpt2Module()) ) { OnDvHeaderPacketIn(Header, Ip); @@ -79,18 +79,18 @@ void CDcsProtocol::Task(void) std::cout << "DCS connect packet for module " << ToLinkModule << " from " << Callsign << " at " << Ip << std::endl; // callsign authorized? - if ( g_Gate.MayLink(Callsign, Ip, EProtocol::dcs) && g_Refl.IsValidModule(ToLinkModule) ) + if ( g_GateKeeper.MayLink(Callsign, Ip, EProtocol::dcs) && g_Reflector.IsValidModule(ToLinkModule) ) { // valid module ? - if ( g_Refl.IsValidModule(ToLinkModule) ) + if ( g_Reflector.IsValidModule(ToLinkModule) ) { // acknowledge the request EncodeConnectAckPacket(Callsign, ToLinkModule, &Buffer); Send(Buffer, Ip); // create the client and append - g_Refl.GetClients()->AddClient(std::make_shared(Callsign, Ip, ToLinkModule)); - g_Refl.ReleaseClients(); + g_Reflector.GetClients()->AddClient(std::make_shared(Callsign, Ip, ToLinkModule)); + g_Reflector.ReleaseClients(); } else { @@ -114,7 +114,7 @@ void CDcsProtocol::Task(void) std::cout << "DCS disconnect packet from " << Callsign << " at " << Ip << std::endl; // find client - CClients *clients = g_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); std::shared_ptrclient = clients->FindClient(Ip, EProtocol::dcs); if ( client != nullptr ) { @@ -124,21 +124,21 @@ void CDcsProtocol::Task(void) EncodeConnectNackPacket(Callsign, ' ', &Buffer); Send(Buffer, Ip); } - g_Refl.ReleaseClients(); + g_Reflector.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_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(Callsign, Ip, EProtocol::dcs, it)) != nullptr ) { client->Alive(); } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } else if ( IsIgnorePacket(Buffer) ) { @@ -192,24 +192,24 @@ void CDcsProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header, CCallsign rpt2(Header->GetRpt2Callsign()); // find this client - std::shared_ptrclient = g_Refl.GetClients()->FindClient(Ip, EProtocol::dcs); + std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, EProtocol::dcs); if ( client ) { // get client callsign rpt1 = client->GetCallsign(); // and try to open the stream - if ( (stream = g_Refl.OpenStream(Header, client)) != nullptr ) + if ( (stream = g_Reflector.OpenStream(Header, client)) != nullptr ) { // keep the handle m_Streams[stream->GetStreamId()] = stream; } } // release - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); // update last heard - g_Refl.GetUsers()->Hearing(my, rpt1, rpt2); - g_Refl.ReleaseUsers(); + g_Reflector.GetUsers()->Hearing(my, rpt1, rpt2); + g_Reflector.ReleaseUsers(); } } @@ -251,7 +251,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_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::dcs, it)) != nullptr ) @@ -264,7 +264,7 @@ void CDcsProtocol::HandleQueue(void) } } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } } } @@ -282,7 +282,7 @@ void CDcsProtocol::HandleKeepalives(void) EncodeKeepAlivePacket(&keepalive1); // iterate on clients - CClients *clients = g_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::dcs, it)) != nullptr ) @@ -315,7 +315,7 @@ void CDcsProtocol::HandleKeepalives(void) } } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } //////////////////////////////////////////////////////////////////////////////////////// diff --git a/reflector/DExtraProtocol.cpp b/reflector/DExtraProtocol.cpp index 9e4c64b..88ed7ef 100644 --- a/reflector/DExtraProtocol.cpp +++ b/reflector/DExtraProtocol.cpp @@ -72,7 +72,7 @@ void CDextraProtocol::Task(void) else if ( IsValidDvHeaderPacket(Buffer, Header) ) { // callsign muted? - if ( g_Gate.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::dextra, Header->GetRpt2Module()) ) + if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::dextra, Header->GetRpt2Module()) ) { OnDvHeaderPacketIn(Header, Ip); } @@ -96,18 +96,18 @@ void CDextraProtocol::Task(void) } // callsign authorized? - if ( g_Gate.MayLink(Callsign, Ip, EProtocol::dextra) ) + if ( g_GateKeeper.MayLink(Callsign, Ip, EProtocol::dextra) ) { // valid module ? - if ( g_Refl.IsValidModule(ToLinkModule) ) + if ( g_Reflector.IsValidModule(ToLinkModule) ) { // acknowledge the request EncodeConnectAckPacket(&Buffer, ProtRev); Send(Buffer, Ip); // create the client and append - g_Refl.GetClients()->AddClient(std::make_shared(Callsign, Ip, ToLinkModule, ProtRev)); - g_Refl.ReleaseClients(); + g_Reflector.GetClients()->AddClient(std::make_shared(Callsign, Ip, ToLinkModule, ProtRev)); + g_Reflector.ReleaseClients(); } else { @@ -130,7 +130,7 @@ void CDextraProtocol::Task(void) std::cout << "DExtra disconnect packet from " << Callsign << " at " << Ip << std::endl; // find client & remove it - CClients *clients = g_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); std::shared_ptrclient = clients->FindClient(Ip, EProtocol::dextra); if ( client != nullptr ) { @@ -147,21 +147,21 @@ void CDextraProtocol::Task(void) // and remove it clients->RemoveClient(client); } - g_Refl.ReleaseClients(); + g_Reflector.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_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(Callsign, Ip, EProtocol::dextra, it)) != nullptr ) { client->Alive(); } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } else { @@ -203,7 +203,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_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::dextra, it)) != nullptr ) @@ -219,7 +219,7 @@ void CDextraProtocol::HandleQueue(void) } } } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } } } @@ -236,7 +236,7 @@ void CDextraProtocol::HandleKeepalives(void) EncodeKeepAlivePacket(&keepalive); // iterate on clients - CClients *clients = g_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::dextra, it)) != nullptr ) @@ -253,7 +253,7 @@ void CDextraProtocol::HandleKeepalives(void) // otherwise check if still with us else if ( !client->IsAlive() ) { - CPeers *peers = g_Refl.GetPeers(); + CPeers *peers = g_Reflector.GetPeers(); std::shared_ptrpeer = peers->FindPeer(client->GetCallsign(), client->GetIp(), EProtocol::dextra); if ( peer != nullptr && peer->GetReflectorModules()[0] == client->GetReflectorModule() ) { @@ -270,14 +270,14 @@ void CDextraProtocol::HandleKeepalives(void) std::cout << "DExtra client " << client->GetCallsign() << " keepalive timeout" << std::endl; clients->RemoveClient(client); } - g_Refl.ReleasePeers(); + g_Reflector.ReleasePeers(); } } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); // iterate on peers - CPeers *peers = g_Refl.GetPeers(); + CPeers *peers = g_Reflector.GetPeers(); auto pit = peers->begin(); std::shared_ptrpeer = nullptr; while ( (peer = peers->FindNextPeer(EProtocol::dextra, pit)) != nullptr ) @@ -290,19 +290,19 @@ void CDextraProtocol::HandleKeepalives(void) // no, disconnect all clients CBuffer disconnect; EncodeDisconnectPacket(&disconnect, peer->GetReflectorModules()[0]); - CClients *clients = g_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); for ( auto cit=peer->cbegin(); cit!=peer->cend(); cit++ ) { Send(disconnect, (*cit)->GetIp()); } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); // remove it std::cout << "DExtra peer " << peer->GetCallsign() << " keepalive timeout" << std::endl; peers->RemovePeer(peer); } } - g_Refl.ReleasePeers(); + g_Reflector.ReleasePeers(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -326,7 +326,7 @@ void CDextraProtocol::OnDvHeaderPacketIn(std::unique_ptr &Heade CCallsign rpt2(Header->GetRpt2Callsign()); // find this client - std::shared_ptrclient = g_Refl.GetClients()->FindClient(Ip, EProtocol::dextra); + std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, EProtocol::dextra); if ( client ) { // get client callsign @@ -341,18 +341,18 @@ void CDextraProtocol::OnDvHeaderPacketIn(std::unique_ptr &Heade rpt2.SetCSModule(m); } // and try to open the stream - if ( (stream = g_Refl.OpenStream(Header, client)) != nullptr ) + if ( (stream = g_Reflector.OpenStream(Header, client)) != nullptr ) { // keep the handle m_Streams[stream->GetStreamId()] = stream; } } // release - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); // update last heard - g_Refl.GetUsers()->Hearing(my, rpt1, rpt2); - g_Refl.ReleaseUsers(); + g_Reflector.GetUsers()->Hearing(my, rpt1, rpt2); + g_Reflector.ReleaseUsers(); } } diff --git a/reflector/DMRMMDVMProtocol.cpp b/reflector/DMRMMDVMProtocol.cpp index e50a943..12bbe38 100644 --- a/reflector/DMRMMDVMProtocol.cpp +++ b/reflector/DMRMMDVMProtocol.cpp @@ -48,7 +48,7 @@ static uint8_t g_DmrSyncMSData[] = { 0x0D,0x5D,0x7F,0x77,0xFD,0x75,0x70 }; bool CDmrmmdvmProtocol::Initialize(const char *type, const EProtocol ptype, const uint16_t port, const bool has_ipv4, const bool has_ipv6) { - m_DefaultId = g_Conf.GetUnsigned(g_Keys.mmdvm.defaultid); + m_DefaultId = g_Configure.GetUnsigned(g_Keys.mmdvm.defaultid); // base class if (! CProtocol::Initialize(type, ptype, port, has_ipv4, has_ipv6)) return false; @@ -93,7 +93,7 @@ void CDmrmmdvmProtocol::Task(void) if ( Receive4(Buffer, Ip, 20) ) #endif { - //Buffer.DebugDump(g_Refl.m_DebugFile); + //Buffer.DebugDump(g_Reflector.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_Gate.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::dmrmmdvm) ) + if ( g_GateKeeper.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_Gate.MayLink(Callsign, Ip, EProtocol::dmrmmdvm) ) + if ( g_GateKeeper.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_Gate.MayLink(Callsign, Ip, EProtocol::dmrmmdvm) ) + if ( g_GateKeeper.MayLink(Callsign, Ip, EProtocol::dmrmmdvm) ) { // acknowledge the request EncodeAckPacket(&Buffer, Callsign); Send(Buffer, Ip); // add client if needed - CClients *clients = g_Refl.GetClients(); + CClients *clients = g_Reflector.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_Refl.ReleaseClients(); + g_Reflector.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_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); std::shared_ptrclient = clients->FindClient(Ip, EProtocol::dmrmmdvm); if ( client != nullptr ) { clients->RemoveClient(client); } - g_Refl.ReleaseClients(); + g_Reflector.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_Refl.GetClients(); + CClients *clients = g_Reflector.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_Refl.ReleaseClients(); + g_Reflector.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_Refl.GetClients()->FindClient(Ip, EProtocol::dmrmmdvm); + std::shared_ptrclient = g_Reflector.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_Refl.IsValidModule(rpt2.GetCSModule()) ) + if ( g_Reflector.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_Refl.IsValidModule(rpt2.GetCSModule()) && (CallType == DMR_GROUP_CALL) ) + if ( g_Reflector.IsValidModule(rpt2.GetCSModule()) && (CallType == DMR_GROUP_CALL) ) { // yes, try to open the stream - if ( (stream = g_Refl.OpenStream(Header, client)) != nullptr ) + if ( (stream = g_Reflector.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_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); // update last heard if ( lastheard ) { - g_Refl.GetUsers()->Hearing(my, rpt1, rpt2); - g_Refl.ReleaseUsers(); + g_Reflector.GetUsers()->Hearing(my, rpt1, rpt2); + g_Reflector.ReleaseUsers(); } } } @@ -401,7 +401,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_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::dmrmmdvm, it)) != nullptr ) @@ -414,7 +414,7 @@ void CDmrmmdvmProtocol::HandleQueue(void) } } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } } } @@ -429,7 +429,7 @@ void CDmrmmdvmProtocol::HandleKeepalives(void) // and disconnect them if not // iterate on clients - CClients *clients = g_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::dmrmmdvm, it)) != nullptr ) @@ -453,7 +453,7 @@ void CDmrmmdvmProtocol::HandleKeepalives(void) } } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -693,7 +693,7 @@ bool CDmrmmdvmProtocol::IsValidDvFramePacket(const CBuffer &Buffer, std::arraydata()[33]), 7); - //dump.DebugDump(g_Refl.m_DebugFile); + //dump.DebugDump(g_Reflector.m_DebugFile); // BER Buffer->Append((uint8_t)0); @@ -979,7 +979,7 @@ char CDmrmmdvmProtocol::DmrDstIdToModule(uint32_t tg) const if (tg > 4000 && tg < 4027) { const char mod = 'A' + (tg - 4001U); - if (g_Refl.IsValidModule(mod)) + if (g_Reflector.IsValidModule(mod)) { return mod; } diff --git a/reflector/DMRPlusProtocol.cpp b/reflector/DMRPlusProtocol.cpp index a625a74..4de295f 100644 --- a/reflector/DMRPlusProtocol.cpp +++ b/reflector/DMRPlusProtocol.cpp @@ -92,7 +92,7 @@ void CDmrplusProtocol::Task(void) else if ( IsValidDvHeaderPacket(Ip, Buffer, Header) ) { // callsign muted? - if ( g_Gate.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::dmrplus) ) + if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::dmrplus) ) { // handle it OnDvHeaderPacketIn(Header, Ip); @@ -103,14 +103,14 @@ void CDmrplusProtocol::Task(void) //std::cout << "DMRplus keepalive/connect packet for module " << ToLinkModule << " from " << Callsign << " at " << Ip << std::endl; // callsign authorized? - if ( g_Gate.MayLink(Callsign, Ip, EProtocol::dmrplus) ) + if ( g_GateKeeper.MayLink(Callsign, Ip, EProtocol::dmrplus) ) { // acknowledge the request EncodeConnectAckPacket(&Buffer); Send(Buffer, Ip); // add client if needed - CClients *clients = g_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); std::shared_ptrclient = clients->FindClient(Callsign, Ip, EProtocol::dmrplus); // client already connected ? if ( client == nullptr ) @@ -125,7 +125,7 @@ void CDmrplusProtocol::Task(void) client->Alive(); } // and done - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } else { @@ -140,13 +140,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_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); std::shared_ptrclient = clients->FindClient(Ip, EProtocol::dmrplus); if ( client != nullptr ) { clients->RemoveClient(client); } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } else { @@ -195,21 +195,21 @@ void CDmrplusProtocol::OnDvHeaderPacketIn(std::unique_ptr &Head // no stream open yet, open a new one // find this client - std::shared_ptrclient = g_Refl.GetClients()->FindClient(Ip, EProtocol::dmrplus); + std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, EProtocol::dmrplus); if ( client ) { // and try to open the stream - if ( (stream = g_Refl.OpenStream(Header, client)) != nullptr ) + if ( (stream = g_Reflector.OpenStream(Header, client)) != nullptr ) { // keep the handle m_Streams[stream->GetStreamId()] = stream; } } // release - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); // update last heard - g_Refl.GetUsers()->Hearing(my, rpt1, rpt2); - g_Refl.ReleaseUsers(); + g_Reflector.GetUsers()->Hearing(my, rpt1, rpt2); + g_Reflector.ReleaseUsers(); } } @@ -265,7 +265,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_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::dmrplus, it)) != nullptr ) @@ -277,10 +277,10 @@ void CDmrplusProtocol::HandleQueue(void) Send(buffer, client->GetIp()); } } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); // debug - //buffer.DebugDump(g_Refl.m_DebugFile); + //buffer.DebugDump(g_Reflector.m_DebugFile); } } } @@ -290,7 +290,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_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::dmrplus, it)) != nullptr ) @@ -302,10 +302,10 @@ void CDmrplusProtocol::SendBufferToClients(const CBuffer &buffer, uint8_t module Send(buffer, client->GetIp()); } } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); // debug - //buffer.DebugDump(g_Refl.m_DebugFile); + //buffer.DebugDump(g_Reflector.m_DebugFile); } } @@ -320,7 +320,7 @@ void CDmrplusProtocol::HandleKeepalives(void) // and disconnect them if not // iterate on clients - CClients *clients = g_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::dmrplus, it)) != nullptr ) @@ -345,7 +345,7 @@ void CDmrplusProtocol::HandleKeepalives(void) } } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -638,7 +638,7 @@ char CDmrplusProtocol::DmrDstIdToModule(uint32_t tg) const // is it a 4xxx ? if (tg > 4000 && tg < 4027) { char mod = 'A' + (tg - 4001U); - if (g_Refl.IsValidModule(mod)) + if (g_Reflector.IsValidModule(mod)) { return mod; } diff --git a/reflector/DPlusProtocol.cpp b/reflector/DPlusProtocol.cpp index cd7ac07..14682fe 100644 --- a/reflector/DPlusProtocol.cpp +++ b/reflector/DPlusProtocol.cpp @@ -71,7 +71,7 @@ void CDplusProtocol::Task(void) else if ( IsValidDvHeaderPacket(Buffer, Header) ) { // is muted? - if ( g_Gate.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::dplus, Header->GetRpt2Module()) ) + if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::dplus, Header->GetRpt2Module()) ) { // handle it OnDvHeaderPacketIn(Header, Ip); @@ -89,15 +89,15 @@ void CDplusProtocol::Task(void) std::cout << "DPlus login packet from " << Callsign << " at " << Ip << std::endl; // callsign authorized? - if ( g_Gate.MayLink(Callsign, Ip, EProtocol::dplus) ) + if ( g_GateKeeper.MayLink(Callsign, Ip, EProtocol::dplus) ) { // acknowledge the request EncodeLoginAckPacket(&Buffer); Send(Buffer, Ip); // create the client and append - g_Refl.GetClients()->AddClient(std::make_shared(Callsign, Ip)); - g_Refl.ReleaseClients(); + g_Reflector.GetClients()->AddClient(std::make_shared(Callsign, Ip)); + g_Reflector.ReleaseClients(); } else { @@ -112,7 +112,7 @@ void CDplusProtocol::Task(void) std::cout << "DPlus disconnect packet from " << Ip << std::endl; // find client - CClients *clients = g_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); std::shared_ptrclient = clients->FindClient(Ip, EProtocol::dplus); if ( client != nullptr ) { @@ -122,21 +122,21 @@ void CDplusProtocol::Task(void) EncodeDisconnectPacket(&Buffer); Send(Buffer, Ip); } - g_Refl.ReleaseClients(); + g_Reflector.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_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(Ip, EProtocol::dplus, it)) != nullptr ) { client->Alive(); } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } else { @@ -184,10 +184,10 @@ void CDplusProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header CCallsign rpt2(Header->GetRpt2Callsign()); // first, check module is valid - if ( g_Refl.IsValidModule(rpt2.GetCSModule()) ) + if ( g_Reflector.IsValidModule(rpt2.GetCSModule()) ) { // find this client - std::shared_ptrclient = g_Refl.GetClients()->FindClient(Ip, EProtocol::dplus); + std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, EProtocol::dplus); if ( client ) { // now we know if it's a dextra dongle or a genuine dplus node @@ -203,18 +203,18 @@ void CDplusProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header // get client callsign rpt1 = client->GetCallsign(); // and try to open the stream - if ( (stream = g_Refl.OpenStream(Header, client)) != nullptr ) + if ( (stream = g_Reflector.OpenStream(Header, client)) != nullptr ) { // keep the handle m_Streams[stream->GetStreamId()] = stream; } } // release - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); // update last heard - g_Refl.GetUsers()->Hearing(my, rpt1, rpt2); - g_Refl.ReleaseUsers(); + g_Reflector.GetUsers()->Hearing(my, rpt1, rpt2); + g_Reflector.ReleaseUsers(); } else { @@ -251,7 +251,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_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::dplus, it)) != nullptr ) @@ -288,7 +288,7 @@ void CDplusProtocol::HandleQueue(void) } } } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } } } @@ -340,7 +340,7 @@ void CDplusProtocol::HandleKeepalives(void) EncodeKeepAlivePacket(&keepalive); // iterate on clients - CClients *clients = g_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::dplus, it)) != nullptr ) @@ -368,7 +368,7 @@ void CDplusProtocol::HandleKeepalives(void) clients->RemoveClient(client); } } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } //////////////////////////////////////////////////////////////////////////////////////// diff --git a/reflector/G3Protocol.cpp b/reflector/G3Protocol.cpp index c075c14..7c15ca8 100644 --- a/reflector/G3Protocol.cpp +++ b/reflector/G3Protocol.cpp @@ -33,13 +33,13 @@ bool CG3Protocol::Initialize(const char */*type*/, const EProtocol /*type*/, con // everything is hard coded until ICOM gets their act together and start supporting IPv6 { //config data - m_TerminalPath.assign(g_Conf.GetString(g_Keys.files.terminal)); - const std::string ipv4address(g_Conf.GetString(g_Keys.ip.ipv4bind)); + m_TerminalPath.assign(g_Configure.GetString(g_Keys.files.terminal)); + const std::string ipv4address(g_Configure.GetString(g_Keys.ip.ipv4bind)); ReadOptions(); // init reflector apparent callsign - m_ReflectorCallsign = g_Refl.GetCallsign(); + m_ReflectorCallsign = g_Reflector.GetCallsign(); // reset stop flag keep_running = true; @@ -179,7 +179,7 @@ void CG3Protocol::PresenceTask(void) Buffer.Append(m_GwAddress); } - CClients *clients = g_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); auto it = clients->begin(); std::shared_ptrextant = nullptr; while ( (extant = clients->FindNextClient(EProtocol::g3, it)) != nullptr ) @@ -221,7 +221,7 @@ void CG3Protocol::PresenceTask(void) clients->AddClient(std::make_shared(Terminal, Ip)); } } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); m_PresenceSocket.Send(Buffer, ReqIp); } @@ -262,7 +262,7 @@ void CG3Protocol::ConfigTask(void) if (isRepeaterCall) { - if ((Call.HasSameCallsign(GetReflectorCallsign())) && (g_Refl.IsValidModule(Call.GetCSModule()))) + if ((Call.HasSameCallsign(GetReflectorCallsign())) && (g_Reflector.IsValidModule(Call.GetCSModule()))) { Buffer.data()[3] = 0x00; // ok } @@ -345,7 +345,7 @@ void CG3Protocol::IcmpTask(void) { if (iIcmpType == ICMP_DEST_UNREACH) { - CClients *clients = g_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::g3, it)) != nullptr ) @@ -356,7 +356,7 @@ void CG3Protocol::IcmpTask(void) clients->RemoveClient(client); } } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } } } @@ -380,7 +380,7 @@ void CG3Protocol::Task(void) { CIp ClIp; CIp *BaseIp = nullptr; - CClients *clients = g_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::g3, it)) != nullptr ) @@ -396,7 +396,7 @@ void CG3Protocol::Task(void) break; } } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); if (BaseIp != nullptr) { @@ -408,7 +408,7 @@ void CG3Protocol::Task(void) else if ( IsValidDvHeaderPacket(Buffer, Header) ) { // callsign muted? - if ( g_Gate.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::g3, Header->GetRpt2Module()) ) + if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::g3, Header->GetRpt2Module()) ) { // handle it OnDvHeaderPacketIn(Header, *BaseIp); @@ -455,7 +455,7 @@ void CG3Protocol::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_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::g3, it)) != nullptr ) @@ -471,7 +471,7 @@ void CG3Protocol::HandleQueue(void) } } } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } } } @@ -487,7 +487,7 @@ void CG3Protocol::HandleKeepalives(void) CBuffer keepalive((uint8_t *)"PING", 4); // iterate on clients - CClients *clients = g_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::g3, it)) != nullptr ) @@ -502,7 +502,7 @@ void CG3Protocol::HandleKeepalives(void) Send(keepalive, client->GetIp()); } } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -527,7 +527,7 @@ void CG3Protocol::OnDvHeaderPacketIn(std::unique_ptr &Header, c CCallsign rpt2(Header->GetRpt2Callsign()); // find this client - CClients *clients = g_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::g3, it)) != nullptr ) @@ -554,7 +554,7 @@ void CG3Protocol::OnDvHeaderPacketIn(std::unique_ptr &Header, c } else { - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); return; } } @@ -563,19 +563,19 @@ void CG3Protocol::OnDvHeaderPacketIn(std::unique_ptr &Header, c rpt1 = client->GetCallsign(); // and try to open the stream - if ( (stream = g_Refl.OpenStream(Header, client)) != nullptr ) + if ( (stream = g_Reflector.OpenStream(Header, client)) != nullptr ) { // keep the handle m_Streams[stream->GetStreamId()] = stream; } // update last heard - g_Refl.GetUsers()->Hearing(my, rpt1, rpt2); - g_Refl.ReleaseUsers(); + g_Reflector.GetUsers()->Hearing(my, rpt1, rpt2); + g_Reflector.ReleaseUsers(); } } // release - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } } @@ -679,7 +679,7 @@ void CG3Protocol::NeedReload(void) ReadOptions(); // we have new options - iterate on clients for potential removal - CClients *clients = g_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::g3, it)) != nullptr ) @@ -690,7 +690,7 @@ void CG3Protocol::NeedReload(void) clients->RemoveClient(client); } } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } } } diff --git a/reflector/GateKeeper.cpp b/reflector/GateKeeper.cpp index f91db6e..8afb9f3 100644 --- a/reflector/GateKeeper.cpp +++ b/reflector/GateKeeper.cpp @@ -44,9 +44,9 @@ bool CGateKeeper::Init(void) { // load lists from files - m_NodeWhiteList.LoadFromFile(g_Conf.GetString(g_Keys.files.white)); - m_NodeBlackList.LoadFromFile(g_Conf.GetString(g_Keys.files.black)); - m_PeerList.LoadFromFile(g_Conf.GetString(g_Keys.files.interlink)); + m_NodeWhiteList.LoadFromFile(g_Configure.GetString(g_Keys.files.white)); + m_NodeBlackList.LoadFromFile(g_Configure.GetString(g_Keys.files.black)); + m_PeerList.LoadFromFile(g_Configure.GetString(g_Keys.files.interlink)); // reset run flag keep_running = true; diff --git a/reflector/Global.h b/reflector/Global.h index 611f347..0a3c43c 100644 --- a/reflector/Global.h +++ b/reflector/Global.h @@ -23,10 +23,10 @@ #include "LookupYsf.h" #include "JsonKeys.h" -extern CReflector g_Refl; -extern CGateKeeper g_Gate; -extern CConfigure g_Conf; -extern CVersion g_Vers; +extern CReflector g_Reflector; +extern CGateKeeper g_GateKeeper; +extern CConfigure g_Configure; +extern CVersion g_Version; extern CLookupDmr g_LDid; extern CLookupNxdn g_LNid; extern CLookupYsf g_LYtr; diff --git a/reflector/Lookup.cpp b/reflector/Lookup.cpp index 27bc6af..9d1fbc6 100644 --- a/reflector/Lookup.cpp +++ b/reflector/Lookup.cpp @@ -69,8 +69,7 @@ void CLookup::Thread() // load the file if http was loaded or if we haven't loaded since the last mod time if (ERefreshType::http != m_Type) { - GetLastModTime(); - if (http_loaded || m_LastLoadTime < m_LastModTime) + if (http_loaded || m_LastLoadTime < GetLastModTime()) { file_loaded = LoadContentFile(ss); time(&m_LastLoadTime); diff --git a/reflector/Lookup.h b/reflector/Lookup.h index d4638d0..e7edd78 100644 --- a/reflector/Lookup.h +++ b/reflector/Lookup.h @@ -53,7 +53,7 @@ class CLookup { public: // constructor - CLookup() : keep_running(true), m_LastModTime(0), m_LastLoadTime(0) {} + CLookup() : keep_running(true), m_LastLoadTime(0) {} void LookupInit(); void LookupClose(); @@ -78,7 +78,7 @@ protected: ERefreshType m_Type; unsigned m_Refresh; std::string m_Path, m_Url; - std::time_t m_LastModTime, m_LastLoadTime; + std::time_t m_LastLoadTime; std::atomic keep_running; std::future m_Future; diff --git a/reflector/LookupDmr.cpp b/reflector/LookupDmr.cpp index a3c202c..04ab0e1 100644 --- a/reflector/LookupDmr.cpp +++ b/reflector/LookupDmr.cpp @@ -31,10 +31,10 @@ void CLookupDmr::ClearContents() void CLookupDmr::LoadParameters() { - m_Type = g_Conf.GetRefreshType(g_Keys.dmriddb.mode); - m_Refresh = g_Conf.GetUnsigned(g_Keys.dmriddb.refreshmin); - m_Path.assign(g_Conf.GetString(g_Keys.dmriddb.filepath)); - m_Url.assign(g_Conf.GetString(g_Keys.dmriddb.url)); + m_Type = g_Configure.GetRefreshType(g_Keys.dmriddb.mode); + m_Refresh = g_Configure.GetUnsigned(g_Keys.dmriddb.refreshmin); + m_Path.assign(g_Configure.GetString(g_Keys.dmriddb.filepath)); + m_Url.assign(g_Configure.GetString(g_Keys.dmriddb.url)); } uint32_t CLookupDmr::FindDmrid(const UCallsign &ucs) const diff --git a/reflector/LookupNxdn.cpp b/reflector/LookupNxdn.cpp index 95b4f00..7189b8f 100644 --- a/reflector/LookupNxdn.cpp +++ b/reflector/LookupNxdn.cpp @@ -31,10 +31,10 @@ void CLookupNxdn::ClearContents() void CLookupNxdn::LoadParameters() { - m_Type = g_Conf.GetRefreshType(g_Keys.nxdniddb.mode); - m_Refresh = g_Conf.GetUnsigned(g_Keys.nxdniddb.refreshmin); - m_Path.assign(g_Conf.GetString(g_Keys.nxdniddb.filepath)); - m_Url.assign(g_Conf.GetString(g_Keys.nxdniddb.url)); + m_Type = g_Configure.GetRefreshType(g_Keys.nxdniddb.mode); + m_Refresh = g_Configure.GetUnsigned(g_Keys.nxdniddb.refreshmin); + m_Path.assign(g_Configure.GetString(g_Keys.nxdniddb.filepath)); + m_Url.assign(g_Configure.GetString(g_Keys.nxdniddb.url)); } const UCallsign *CLookupNxdn::FindCallsign(uint16_t nxdnid) const diff --git a/reflector/LookupYsf.cpp b/reflector/LookupYsf.cpp index e2fc5a3..b30f6b6 100644 --- a/reflector/LookupYsf.cpp +++ b/reflector/LookupYsf.cpp @@ -31,12 +31,12 @@ void CLookupYsf::ClearContents() void CLookupYsf::LoadParameters() { - m_Type = g_Conf.GetRefreshType(g_Keys.ysftxrxdb.mode); - m_Refresh = g_Conf.GetUnsigned(g_Keys.ysftxrxdb.refreshmin); - m_Path.assign(g_Conf.GetString(g_Keys.ysftxrxdb.filepath)); - m_Url.assign(g_Conf.GetString(g_Keys.ysftxrxdb.url)); - m_DefaultTx = g_Conf.GetUnsigned(g_Keys.ysf.defaulttxfreq); - m_DefaultRx = g_Conf.GetUnsigned(g_Keys.ysf.defaultrxfreq); + m_Type = g_Configure.GetRefreshType(g_Keys.ysftxrxdb.mode); + m_Refresh = g_Configure.GetUnsigned(g_Keys.ysftxrxdb.refreshmin); + m_Path.assign(g_Configure.GetString(g_Keys.ysftxrxdb.filepath)); + m_Url.assign(g_Configure.GetString(g_Keys.ysftxrxdb.url)); + m_DefaultTx = g_Configure.GetUnsigned(g_Keys.ysf.defaulttxfreq); + m_DefaultRx = g_Configure.GetUnsigned(g_Keys.ysf.defaultrxfreq); } void CLookupYsf::UpdateContent(std::stringstream &ss, Eaction action) diff --git a/reflector/M17Protocol.cpp b/reflector/M17Protocol.cpp index cbbfe74..2516389 100644 --- a/reflector/M17Protocol.cpp +++ b/reflector/M17Protocol.cpp @@ -68,7 +68,7 @@ void CM17Protocol::Task(void) if ( IsValidDvPacket(Buffer, Header, Frame) ) { // callsign muted? - if ( g_Gate.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::m17, Header->GetRpt2Module()) ) + if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::m17, Header->GetRpt2Module()) ) { OnDvHeaderPacketIn(Header, Ip); @@ -92,17 +92,17 @@ void CM17Protocol::Task(void) std::cout << "M17 connect packet for module " << ToLinkModule << " from " << Callsign << " at " << Ip << std::endl; // callsign authorized? - if ( g_Gate.MayLink(Callsign, Ip, EProtocol::m17) && g_Refl.IsValidModule(ToLinkModule) ) + if ( g_GateKeeper.MayLink(Callsign, Ip, EProtocol::m17) && g_Reflector.IsValidModule(ToLinkModule) ) { // valid module ? - if ( g_Refl.IsValidModule(ToLinkModule) ) + if ( g_Reflector.IsValidModule(ToLinkModule) ) { // acknowledge the request Send("ACKN", Ip); // create the client and append - g_Refl.GetClients()->AddClient(std::make_shared(Callsign, Ip, ToLinkModule)); - g_Refl.ReleaseClients(); + g_Reflector.GetClients()->AddClient(std::make_shared(Callsign, Ip, ToLinkModule)); + g_Reflector.ReleaseClients(); } else { @@ -124,7 +124,7 @@ void CM17Protocol::Task(void) std::cout << "M17 disconnect packet from " << Callsign << " at " << Ip << std::endl; // find client - CClients *clients = g_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); std::shared_ptrclient = clients->FindClient(Ip, EProtocol::m17); if ( client != nullptr ) { @@ -133,19 +133,19 @@ void CM17Protocol::Task(void) // and acknowledge the disconnect Send("DISC", Ip); } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } else if ( IsValidKeepAlivePacket(Buffer, Callsign) ) { // find all clients with that callsign & ip and keep them alive - CClients *clients = g_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(Callsign, Ip, EProtocol::m17, it)) != nullptr ) { client->Alive(); } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } else { @@ -195,24 +195,24 @@ void CM17Protocol::OnDvHeaderPacketIn(std::unique_ptr &Header, CCallsign rpt2(Header->GetRpt2Callsign()); // find this client - std::shared_ptrclient = g_Refl.GetClients()->FindClient(Ip, EProtocol::m17); + std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, EProtocol::m17); if ( client ) { // get client callsign rpt1 = client->GetCallsign(); // and try to open the stream - if ( (stream = g_Refl.OpenStream(Header, client)) != nullptr ) + if ( (stream = g_Reflector.OpenStream(Header, client)) != nullptr ) { // keep the handle m_Streams[stream->GetStreamId()] = stream; } } // release - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); // update last heard - g_Refl.GetUsers()->Hearing(my, rpt1, rpt2); - g_Refl.ReleaseUsers(); + g_Reflector.GetUsers()->Hearing(my, rpt1, rpt2); + g_Reflector.ReleaseUsers(); } } @@ -247,7 +247,7 @@ void CM17Protocol::HandleQueue(void) EncodeM17Packet(frame, m_StreamsCache[module].m_dvHeader, (CDvFramePacket *)packet.get(), m_StreamsCache[module].m_iSeqCounter); // push it to all our clients linked to the module and who are not streaming in - CClients *clients = g_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::m17, it)) != nullptr ) @@ -264,7 +264,7 @@ void CM17Protocol::HandleQueue(void) } } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } m_StreamsCache[module].m_iSeqCounter++; } @@ -283,7 +283,7 @@ void CM17Protocol::HandleKeepalives(void) EncodeKeepAlivePacket(keepalive); // iterate on clients - CClients *clients = g_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::m17, it)) != nullptr ) @@ -309,7 +309,7 @@ void CM17Protocol::HandleKeepalives(void) } } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -386,7 +386,7 @@ void CM17Protocol::EncodeKeepAlivePacket(CBuffer &Buffer) { Buffer.resize(10); memcpy(Buffer.data(), "PING", 4); - g_Refl.GetCallsign().CodeOut(Buffer.data() + 4); + g_Reflector.GetCallsign().CodeOut(Buffer.data() + 4); } void CM17Protocol::EncodeM17Packet(SM17Frame &frame, const CDvHeaderPacket &Header, const CDvFramePacket *DvFrame, uint32_t iSeq) const diff --git a/reflector/Main.cpp b/reflector/Main.cpp index a2fe4d4..afa2209 100644 --- a/reflector/Main.cpp +++ b/reflector/Main.cpp @@ -25,10 +25,10 @@ // global objects SJsonKeys g_Keys; -CReflector g_Refl; -CGateKeeper g_Gate; -CConfigure g_Conf; -CVersion g_Vers(3,0,0); // The major byte should only change if the interlink packet changes! +CReflector g_Reflector; +CGateKeeper g_GateKeeper; +CConfigure g_Configure; +CVersion g_Version(3,0,0); // The major byte should only change if the interlink packet changes! CLookupDmr g_LDid; CLookupNxdn g_LNid; CLookupYsf g_LYtr; @@ -43,20 +43,20 @@ int main(int argc, char *argv[]) return EXIT_FAILURE; } - if (g_Conf.ReadData(argv[1])) + if (g_Configure.ReadData(argv[1])) return EXIT_FAILURE; - std::cout << "IPv4 binding address is '" << g_Conf.GetString(g_Keys.ip.ipv4bind) << "'" << std::endl; + std::cout << "IPv4 binding address is '" << g_Configure.GetString(g_Keys.ip.ipv4bind) << "'" << std::endl; // remove pidfile - const std::string pidpath(g_Conf.GetString(g_Keys.files.pid)); - const std::string callsign(g_Conf.GetString(g_Keys.names.callsign)); + const std::string pidpath(g_Configure.GetString(g_Keys.files.pid)); + const std::string callsign(g_Configure.GetString(g_Keys.names.callsign)); remove(pidpath.c_str()); // splash - std::cout << "Starting " << callsign << " " << g_Vers << std::endl; + std::cout << "Starting " << callsign << " " << g_Version << std::endl; // and let it run - if (g_Refl.Start()) + if (g_Reflector.Start()) { std::cout << "Error starting reflector" << std::endl; return EXIT_FAILURE; @@ -71,7 +71,7 @@ int main(int argc, char *argv[]) pause(); // wait for any signal - g_Refl.Stop(); + g_Reflector.Stop(); std::cout << "Reflector stopped" << std::endl; // done @@ -84,7 +84,7 @@ int main(int argc, char *argv[]) // global objects SJsonKeys g_Keys; -CConfigure g_Conf; +CConfigure g_Configure; CLookupDmr g_LDid; CLookupNxdn g_LNid; CLookupYsf g_LYtr; @@ -185,7 +185,7 @@ int main(int argc, char *argv[]) return EXIT_FAILURE; } - if (g_Conf.ReadData(argv[4])) + if (g_Configure.ReadData(argv[4])) return EXIT_FAILURE; switch (db) diff --git a/reflector/NXDNProtocol.cpp b/reflector/NXDNProtocol.cpp index 9bb4434..fb2381d 100644 --- a/reflector/NXDNProtocol.cpp +++ b/reflector/NXDNProtocol.cpp @@ -53,8 +53,8 @@ CNXDNProtocol::CNXDNProtocol() bool CNXDNProtocol::Initialize(const char *type, const EProtocol ptype, const uint16_t port, const bool has_ipv4, const bool has_ipv6) { // config value - m_ReflectorId = g_Conf.GetUnsigned(g_Keys.nxdn.reflectorid); - m_AutolinkModule = g_Conf.GetAutolinkModule(g_Keys.nxdn.autolinkmod); + m_ReflectorId = g_Configure.GetUnsigned(g_Keys.nxdn.reflectorid); + m_AutolinkModule = g_Configure.GetAutolinkModule(g_Keys.nxdn.autolinkmod); // base class if (! CProtocol::Initialize(type, ptype, port, has_ipv4, has_ipv6)) @@ -106,7 +106,7 @@ void CNXDNProtocol::Task(void) else if ( IsValidDvHeaderPacket(Ip, Buffer, Header) ) { // node linked and callsign muted? - if ( g_Gate.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::nxdn, Header->GetRpt2Module()) ) + if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::nxdn, Header->GetRpt2Module()) ) { // handle it OnDvHeaderPacketIn(Header, Ip); @@ -119,10 +119,10 @@ void CNXDNProtocol::Task(void) else if ( IsValidConnectPacket(Buffer, &Callsign) ) { // callsign authorized? - if ( g_Gate.MayLink(Callsign, Ip, EProtocol::nxdn) ) + if ( g_GateKeeper.MayLink(Callsign, Ip, EProtocol::nxdn) ) { // add client if needed - CClients *clients = g_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); std::shared_ptrclient = clients->FindClient(Callsign, Ip, EProtocol::nxdn); // client already connected ? if ( client == nullptr ) @@ -147,7 +147,7 @@ void CNXDNProtocol::Task(void) // acknowledge the request -- NXDNReflector simply echoes the packet Send(Buffer, Ip); // and done - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } } else if ( IsValidDisconnectPacket(Buffer) ) @@ -155,14 +155,14 @@ void CNXDNProtocol::Task(void) std::cout << "NXDN disconnect packet from " << Ip << std::endl; // find client - CClients *clients = g_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); std::shared_ptrclient = clients->FindClient(Ip, EProtocol::nxdn); if ( client != nullptr ) { // remove it clients->RemoveClient(client); } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } else { @@ -212,7 +212,7 @@ void CNXDNProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header, CCallsign rpt2(Header->GetRpt2Callsign()); // find this client - std::shared_ptrclient = g_Refl.GetClients()->FindClient(Ip, EProtocol::nxdn); + std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, EProtocol::nxdn); if ( client ) { // get client callsign @@ -223,20 +223,20 @@ void CNXDNProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header, rpt2.SetCSModule(m); // and try to open the stream - if ( (stream = g_Refl.OpenStream(Header, client)) != nullptr ) + if ( (stream = g_Reflector.OpenStream(Header, client)) != nullptr ) { // keep the handle m_Streams[stream->GetStreamId()] = stream; } } // release - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); // update last heard - if ( g_Refl.IsValidModule(rpt2.GetCSModule()) ) + if ( g_Reflector.IsValidModule(rpt2.GetCSModule()) ) { - g_Refl.GetUsers()->Hearing(my, rpt1, rpt2); - g_Refl.ReleaseUsers(); + g_Reflector.GetUsers()->Hearing(my, rpt1, rpt2); + g_Reflector.ReleaseUsers(); } } } @@ -293,7 +293,7 @@ void CNXDNProtocol::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_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::nxdn, it)) != nullptr ) @@ -306,7 +306,7 @@ void CNXDNProtocol::HandleQueue(void) } } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } } } @@ -321,7 +321,7 @@ void CNXDNProtocol::HandleKeepalives(void) // and disconnect them if not // iterate on clients - CClients *clients = g_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::nxdn, it)) != nullptr ) @@ -341,7 +341,7 @@ void CNXDNProtocol::HandleKeepalives(void) } } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -409,7 +409,7 @@ bool CNXDNProtocol::IsValidDvFramePacket(const CIp &Ip, const CBuffer &Buffer, s rpt2.SetCSModule(' '); header = std::unique_ptr(new CDvHeaderPacket(csMY, CCallsign("CQCQCQ"), rpt1, rpt2, m_uiStreamId, false)); - if ( g_Gate.MayTransmit(header->GetMyCallsign(), Ip, EProtocol::nxdn, header->GetRpt2Module()) ) + if ( g_GateKeeper.MayTransmit(header->GetMyCallsign(), Ip, EProtocol::nxdn, header->GetRpt2Module()) ) { OnDvHeaderPacketIn(header, Ip); } diff --git a/reflector/P25Protocol.cpp b/reflector/P25Protocol.cpp index 449e2e3..c83e33c 100644 --- a/reflector/P25Protocol.cpp +++ b/reflector/P25Protocol.cpp @@ -50,9 +50,9 @@ const uint8_t REC80[] = {0x80U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, bool CP25Protocol::Initialize(const char *type, const EProtocol ptype, const uint16_t port, const bool has_ipv4, const bool has_ipv6) { // config data - m_ReflectorId = g_Conf.GetUnsigned(g_Keys.p25.reflectorid); - m_DefaultId = g_Conf.GetUnsigned(g_Keys.mmdvm.defaultid); - m_AutolinkModule = g_Conf.GetAutolinkModule(g_Keys.p25.autolinkmod); + m_ReflectorId = g_Configure.GetUnsigned(g_Keys.p25.reflectorid); + m_DefaultId = g_Configure.GetUnsigned(g_Keys.mmdvm.defaultid); + m_AutolinkModule = g_Configure.GetAutolinkModule(g_Keys.p25.autolinkmod); m_uiStreamId = 0; // base class @@ -97,7 +97,7 @@ void CP25Protocol::Task(void) if( !m_uiStreamId && IsValidDvHeaderPacket(Ip, Buffer, Header) ) { // callsign muted? - if ( g_Gate.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::p25) ) + if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::p25) ) { OnDvHeaderPacketIn(Header, Ip); } @@ -108,10 +108,10 @@ void CP25Protocol::Task(void) else if ( IsValidConnectPacket(Buffer, &Callsign) ) { // callsign authorized? - if ( g_Gate.MayLink(Callsign, Ip, EProtocol::p25) ) + if ( g_GateKeeper.MayLink(Callsign, Ip, EProtocol::p25) ) { // add client if needed - CClients *clients = g_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); std::shared_ptrclient = clients->FindClient(Callsign, Ip, EProtocol::p25); // client already connected ? if ( client == nullptr ) @@ -136,7 +136,7 @@ void CP25Protocol::Task(void) // acknowledge the request -- P25Reflector simply echoes the packet Send(Buffer, Ip); // and done - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } } else if ( IsValidDisconnectPacket(Buffer, &Callsign) ) @@ -144,14 +144,14 @@ void CP25Protocol::Task(void) std::cout << "P25 disconnect packet from " << Callsign << " at " << Ip << std::endl; // find client - CClients *clients = g_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); std::shared_ptrclient = clients->FindClient(Ip, EProtocol::p25); if ( client != nullptr ) { // remove it clients->RemoveClient(client); } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } else { @@ -200,7 +200,7 @@ void CP25Protocol::OnDvHeaderPacketIn(std::unique_ptr &Header, CCallsign rpt2(Header->GetRpt2Callsign()); // find this client - std::shared_ptrclient = g_Refl.GetClients()->FindClient(Ip, EProtocol::p25); + std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, EProtocol::p25); if ( client ) { // get client callsign @@ -209,18 +209,18 @@ void CP25Protocol::OnDvHeaderPacketIn(std::unique_ptr &Header, Header->SetRpt2Module(m); rpt2.SetCSModule(m); // and try to open the stream - if ( (stream = g_Refl.OpenStream(Header, client)) != nullptr ) + if ( (stream = g_Reflector.OpenStream(Header, client)) != nullptr ) { // keep the handle m_Streams[stream->GetStreamId()] = stream; } } // release - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); // update last heard - g_Refl.GetUsers()->Hearing(my, rpt1, rpt2); - g_Refl.ReleaseUsers(); + g_Reflector.GetUsers()->Hearing(my, rpt1, rpt2); + g_Reflector.ReleaseUsers(); } } @@ -258,7 +258,7 @@ void CP25Protocol::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_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::p25, it)) != nullptr ) @@ -271,7 +271,7 @@ void CP25Protocol::HandleQueue(void) } } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } } } @@ -506,7 +506,7 @@ void CP25Protocol::EncodeP25Packet(const CDvHeaderPacket &Header, const CDvFrame void CP25Protocol::HandleKeepalives(void) { // iterate on clients - CClients *clients = g_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::p25, it)) != nullptr ) @@ -526,5 +526,5 @@ void CP25Protocol::HandleKeepalives(void) } } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } diff --git a/reflector/Peers.cpp b/reflector/Peers.cpp index df3497b..9be9c04 100644 --- a/reflector/Peers.cpp +++ b/reflector/Peers.cpp @@ -58,15 +58,15 @@ void CPeers::AddPeer(std::shared_ptr peer) std::cout << "New peer " << peer->GetCallsign() << " at " << peer->GetIp() << " added with protocol " << peer->GetProtocolName() << std::endl; // and append all peer's client to reflector client list // it is double lock safe to lock Clients list after Peers list - CClients *clients = g_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); for ( auto cit=peer->cbegin(); cit!=peer->cend(); cit++ ) { clients->AddClient(*cit); } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); // notify - g_Refl.OnPeersChanged(); + g_Reflector.OnPeersChanged(); } void CPeers::RemovePeer(std::shared_ptr peer) @@ -79,7 +79,7 @@ void CPeers::RemovePeer(std::shared_ptr peer) { // remove all clients from reflector client list // it is double lock safe to lock Clients list after Peers list - CClients *clients = g_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); for ( auto cit=peer->begin(); cit!=peer->end(); cit++ ) { // this also delete the client object @@ -87,13 +87,13 @@ void CPeers::RemovePeer(std::shared_ptr peer) } // so clear it then (*pit)->ClearClients(); - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); // remove it std::cout << "Peer " << (*pit)->GetCallsign() << " at " << (*pit)->GetIp() << " removed" << std::endl; pit = m_Peers.erase(pit); // notify - g_Refl.OnPeersChanged(); + g_Reflector.OnPeersChanged(); } else { diff --git a/reflector/Protocol.cpp b/reflector/Protocol.cpp index 5998127..47b948b 100644 --- a/reflector/Protocol.cpp +++ b/reflector/Protocol.cpp @@ -50,7 +50,7 @@ bool CProtocol::Initialize(const char *type, const EProtocol ptype, const uint16 { m_Port = port; // init reflector apparent callsign - m_ReflectorCallsign = g_Refl.GetCallsign(); + m_ReflectorCallsign = g_Reflector.GetCallsign(); // reset stop flag keep_running = true; @@ -62,7 +62,7 @@ bool CProtocol::Initialize(const char *type, const EProtocol ptype, const uint16 // create our sockets if (has_ipv4) { - const std::string ipv4binding(g_Conf.GetString(g_Keys.ip.ipv4bind)); + const std::string ipv4binding(g_Configure.GetString(g_Keys.ip.ipv4bind)); CIp ip4(AF_INET, port, ipv4binding.c_str()); if ( ip4.IsSet() ) { @@ -72,7 +72,7 @@ bool CProtocol::Initialize(const char *type, const EProtocol ptype, const uint16 std::cout << "Listening on " << ip4 << std::endl; } - if (g_Conf.IsString(g_Keys.ip.ipv6bind)) + if (g_Configure.IsString(g_Keys.ip.ipv6bind)) { if (has_ipv6) { @@ -175,7 +175,7 @@ void CProtocol::CheckStreamsTimeout(void) if ( it->second->IsExpired() ) { // yes, close it - g_Refl.CloseStream(it->second); + g_Reflector.CloseStream(it->second); // and remove it from the m_Streams map it = m_Streams.erase(it); } diff --git a/reflector/Protocols.cpp b/reflector/Protocols.cpp index 6781573..5109b93 100644 --- a/reflector/Protocols.cpp +++ b/reflector/Protocols.cpp @@ -49,60 +49,60 @@ bool CProtocols::Init(void) m_Mutex.lock(); { m_Protocols.emplace_back(std::unique_ptr(new CDextraProtocol)); - if (! m_Protocols.back()->Initialize("XRF", EProtocol::dextra, uint16_t(g_Conf.GetUnsigned(g_Keys.dextra.port)), DSTAR_IPV4, DSTAR_IPV6)) + if (! m_Protocols.back()->Initialize("XRF", EProtocol::dextra, uint16_t(g_Configure.GetUnsigned(g_Keys.dextra.port)), DSTAR_IPV4, DSTAR_IPV6)) return false; m_Protocols.emplace_back(std::unique_ptr(new CDplusProtocol)); - if (! m_Protocols.back()->Initialize("REF", EProtocol::dplus, uint16_t(g_Conf.GetUnsigned(g_Keys.dplus.port)), DSTAR_IPV4, DSTAR_IPV6)) + if (! m_Protocols.back()->Initialize("REF", EProtocol::dplus, uint16_t(g_Configure.GetUnsigned(g_Keys.dplus.port)), DSTAR_IPV4, DSTAR_IPV6)) return false; m_Protocols.emplace_back(std::unique_ptr(new CDcsProtocol)); - if (! m_Protocols.back()->Initialize("DCS", EProtocol::dcs, uint16_t(g_Conf.GetUnsigned(g_Keys.dcs.port)), DSTAR_IPV4, DSTAR_IPV6)) + if (! m_Protocols.back()->Initialize("DCS", EProtocol::dcs, uint16_t(g_Configure.GetUnsigned(g_Keys.dcs.port)), DSTAR_IPV4, DSTAR_IPV6)) return false; m_Protocols.emplace_back(std::unique_ptr(new CDmrmmdvmProtocol)); - if (! m_Protocols.back()->Initialize(nullptr, EProtocol::dmrmmdvm, uint16_t(g_Conf.GetUnsigned(g_Keys.mmdvm.port)), DMR_IPV4, DMR_IPV6)) + if (! m_Protocols.back()->Initialize(nullptr, EProtocol::dmrmmdvm, uint16_t(g_Configure.GetUnsigned(g_Keys.mmdvm.port)), DMR_IPV4, DMR_IPV6)) return false; - if (g_Conf.GetBoolean(g_Keys.bm.enable)) + if (g_Configure.GetBoolean(g_Keys.bm.enable)) { m_Protocols.emplace_back(std::unique_ptr(new CBMProtocol)); - if (! m_Protocols.back()->Initialize("XLX", EProtocol::bm, uint16_t(g_Conf.GetUnsigned(g_Keys.bm.port)), DMR_IPV4, DMR_IPV6)) + if (! m_Protocols.back()->Initialize("XLX", EProtocol::bm, uint16_t(g_Configure.GetUnsigned(g_Keys.bm.port)), DMR_IPV4, DMR_IPV6)) return false; } m_Protocols.emplace_back(std::unique_ptr(new CDmrplusProtocol)); - if (! m_Protocols.back()->Initialize(nullptr, EProtocol::dmrplus, uint16_t(g_Conf.GetUnsigned(g_Keys.dmrplus.port)), DMR_IPV4, DMR_IPV6)) + if (! m_Protocols.back()->Initialize(nullptr, EProtocol::dmrplus, uint16_t(g_Configure.GetUnsigned(g_Keys.dmrplus.port)), DMR_IPV4, DMR_IPV6)) return false; m_Protocols.emplace_back(std::unique_ptr(new CYsfProtocol)); - if (! m_Protocols.back()->Initialize("YSF", EProtocol::ysf, uint16_t(g_Conf.GetUnsigned(g_Keys.ysf.port)), YSF_IPV4, YSF_IPV6)) + if (! m_Protocols.back()->Initialize("YSF", EProtocol::ysf, uint16_t(g_Configure.GetUnsigned(g_Keys.ysf.port)), YSF_IPV4, YSF_IPV6)) return false; m_Protocols.emplace_back(std::unique_ptr(new CM17Protocol)); - if (! m_Protocols.back()->Initialize("URF", EProtocol::m17, uint16_t(g_Conf.GetUnsigned(g_Keys.m17.port)), M17_IPV4, M17_IPV6)) + if (! m_Protocols.back()->Initialize("URF", EProtocol::m17, uint16_t(g_Configure.GetUnsigned(g_Keys.m17.port)), M17_IPV4, M17_IPV6)) return false; m_Protocols.emplace_back(std::unique_ptr(new CP25Protocol)); - if (! m_Protocols.back()->Initialize("P25", EProtocol::p25, uint16_t(g_Conf.GetUnsigned(g_Keys.p25.port)), P25_IPV4, P25_IPV6)) + if (! m_Protocols.back()->Initialize("P25", EProtocol::p25, uint16_t(g_Configure.GetUnsigned(g_Keys.p25.port)), P25_IPV4, P25_IPV6)) return false; m_Protocols.emplace_back(std::unique_ptr(new CNXDNProtocol)); - if (! m_Protocols.back()->Initialize("NXDN", EProtocol::nxdn, uint16_t(g_Conf.GetUnsigned(g_Keys.nxdn.port)), NXDN_IPV4, NXDN_IPV6)) + if (! m_Protocols.back()->Initialize("NXDN", EProtocol::nxdn, uint16_t(g_Configure.GetUnsigned(g_Keys.nxdn.port)), NXDN_IPV4, NXDN_IPV6)) return false; - if (g_Conf.GetBoolean(g_Keys.usrp.enable)) + if (g_Configure.GetBoolean(g_Keys.usrp.enable)) { m_Protocols.emplace_back(std::unique_ptr(new CUSRPProtocol)); - if (! m_Protocols.back()->Initialize("USRP", EProtocol::usrp, uint16_t(g_Conf.GetUnsigned(g_Keys.usrp.rxport)), USRP_IPV4, USRP_IPV6)) + if (! m_Protocols.back()->Initialize("USRP", EProtocol::usrp, uint16_t(g_Configure.GetUnsigned(g_Keys.usrp.rxport)), USRP_IPV4, USRP_IPV6)) return false; } m_Protocols.emplace_back(std::unique_ptr(new CURFProtocol)); - if (! m_Protocols.back()->Initialize("URF", EProtocol::urf, uint16_t(g_Conf.GetUnsigned(g_Keys.urf.port)), URF_IPV4, URF_IPV6)) + if (! m_Protocols.back()->Initialize("URF", EProtocol::urf, uint16_t(g_Configure.GetUnsigned(g_Keys.urf.port)), URF_IPV4, URF_IPV6)) return false; - if (g_Conf.GetBoolean(g_Keys.g3.enable)) + if (g_Configure.GetBoolean(g_Keys.g3.enable)) { m_Protocols.emplace_back(std::unique_ptr(new CG3Protocol)); if (! m_Protocols.back()->Initialize("XLX", EProtocol::g3, G3_DV_PORT, DMR_IPV4, DMR_IPV6)) diff --git a/reflector/Reflector.cpp b/reflector/Reflector.cpp index 11dc4dc..956758c 100644 --- a/reflector/Reflector.cpp +++ b/reflector/Reflector.cpp @@ -47,15 +47,15 @@ CReflector::~CReflector() bool CReflector::Start(void) { // get config stuff - m_Callsign = CCallsign(g_Conf.GetString(g_Keys.names.callsign).c_str(), false); - m_Modules.assign(g_Conf.GetString(g_Keys.modules.modules)); - std::string tcmods(g_Conf.GetString(g_Keys.modules.tcmodules)); + m_Callsign = CCallsign(g_Configure.GetString(g_Keys.names.callsign).c_str(), false); + m_Modules.assign(g_Configure.GetString(g_Keys.modules.modules)); + std::string tcmods(g_Configure.GetString(g_Keys.modules.tcmodules)); // let's go! keep_running = true; // init gate keeper. It can only return true! - g_Gate.Init(); + g_GateKeeper.Init(); // init dmrid directory. No need to check the return value. g_LDid.LookupInit(); @@ -139,7 +139,7 @@ void CReflector::Stop(void) m_Protocols.Close(); // close gatekeeper - g_Gate.Close(); + g_GateKeeper.Close(); // close databases g_LDid.LookupClose(); @@ -298,7 +298,7 @@ void CReflector::RouterThread(const char ThisModule) void CReflector::XmlReportThread() { - const std::string path(g_Conf.GetString(g_Keys.files.xml)); + const std::string path(g_Configure.GetString(g_Keys.files.xml)); while (keep_running) { // report to xml file @@ -412,7 +412,7 @@ void CReflector::WriteXmlFile(std::ofstream &xmlFile) xmlFile << "" << std::endl; // software version - xmlFile << "" << g_Vers << "" << std::endl; + xmlFile << "" << g_Version << "" << std::endl; CCallsign cs = m_Callsign; cs.PatchCallsign(0, "XLX", 3); diff --git a/reflector/URFProtocol.cpp b/reflector/URFProtocol.cpp index c9d4f12..673f21d 100644 --- a/reflector/URFProtocol.cpp +++ b/reflector/URFProtocol.cpp @@ -73,19 +73,19 @@ void CURFProtocol::Task(void) else if ( IsValidKeepAlivePacket(Buffer, &Callsign) ) { // find peer - CPeers *peers = g_Refl.GetPeers(); + CPeers *peers = g_Reflector.GetPeers(); std::shared_ptrpeer = peers->FindPeer(Ip, EProtocol::urf); if ( peer != nullptr ) { // keep it alive peer->Alive(); } - g_Refl.ReleasePeers(); + g_Reflector.ReleasePeers(); } else if ( IsValidDvHeaderPacket(Buffer, Header) ) { // callsign allowed? - if ( g_Gate.MayTransmit(Header->GetMyCallsign(), Ip) ) + if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip) ) { OnDvHeaderPacketIn(Header, Ip); } @@ -95,7 +95,7 @@ void CURFProtocol::Task(void) std::cout << "URF (" << Version.GetMajor() << "." << Version.GetMinor() << "." << Version.GetRevision() << ") connect packet for modules " << Modules << " from " << Callsign << " at " << Ip << std::endl; // callsign authorized? - if ( g_Gate.MayLink(Callsign, Ip, EProtocol::urf, Modules) ) + if ( g_GateKeeper.MayLink(Callsign, Ip, EProtocol::urf, Modules) ) { // acknowledge connecting request // following is version dependent @@ -123,10 +123,10 @@ void CURFProtocol::Task(void) std::cout << "URF ack packet for modules " << Modules << " from " << Callsign << " at " << Ip << std::endl; // callsign authorized? - if ( g_Gate.MayLink(Callsign, Ip, EProtocol::urf, Modules) ) + if ( g_GateKeeper.MayLink(Callsign, Ip, EProtocol::urf, Modules) ) { // already connected ? - CPeers *peers = g_Refl.GetPeers(); + CPeers *peers = g_Reflector.GetPeers(); if ( peers->FindPeer(Callsign, Ip, EProtocol::urf) == nullptr ) { // create the new peer @@ -137,7 +137,7 @@ void CURFProtocol::Task(void) // this also add all new clients to reflector client list peers->AddPeer(peer); } - g_Refl.ReleasePeers(); + g_Reflector.ReleasePeers(); } } else if ( IsValidDisconnectPacket(Buffer, &Callsign) ) @@ -145,7 +145,7 @@ void CURFProtocol::Task(void) std::cout << "URF disconnect packet from " << Callsign << " at " << Ip << std::endl; // find peer - CPeers *peers = g_Refl.GetPeers(); + CPeers *peers = g_Reflector.GetPeers(); std::shared_ptrpeer = peers->FindPeer(Ip, EProtocol::urf); if ( peer != nullptr ) { @@ -154,7 +154,7 @@ void CURFProtocol::Task(void) // and delete them peers->RemovePeer(peer); } - g_Refl.ReleasePeers(); + g_Reflector.ReleasePeers(); } else if ( IsValidNackPacket(Buffer, &Callsign) ) { @@ -215,7 +215,7 @@ void CURFProtocol::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_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::urf, it)) != nullptr ) @@ -231,7 +231,7 @@ void CURFProtocol::HandleQueue(void) } } } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } } } @@ -249,7 +249,7 @@ void CURFProtocol::HandleKeepalives(void) EncodeKeepAlivePacket(&keepalive); // iterate on peers - CPeers *peers = g_Refl.GetPeers(); + CPeers *peers = g_Reflector.GetPeers(); auto pit = peers->begin(); std::shared_ptrpeer = nullptr; while ( (peer = peers->FindNextPeer(EProtocol::urf, pit)) != nullptr ) @@ -276,7 +276,7 @@ void CURFProtocol::HandleKeepalives(void) peers->RemovePeer(peer); } } - g_Refl.ReleasePeers(); + g_Reflector.ReleasePeers(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -287,8 +287,8 @@ void CURFProtocol::HandlePeerLinks(void) CBuffer buffer; // get the list of peers - CPeerCallsignList *list = g_Gate.GetPeerList(); - CPeers *peers = g_Refl.GetPeers(); + CPeerCallsignList *list = g_GateKeeper.GetPeerList(); + CPeers *peers = g_Reflector.GetPeers(); // check if all our connected peers are still listed by gatekeeper // if not, disconnect @@ -328,8 +328,8 @@ void CURFProtocol::HandlePeerLinks(void) } // done - g_Refl.ReleasePeers(); - g_Gate.ReleasePeerList(); + g_Reflector.ReleasePeers(); + g_GateKeeper.ReleasePeerList(); } @@ -361,11 +361,11 @@ void CURFProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header, CCallsign rpt2(Header->GetRpt2Callsign()); // no stream open yet, open a new one // find this client - std::shared_ptrclient = g_Refl.GetClients()->FindClient(Ip, EProtocol::urf, Header->GetRpt2Module()); + std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, EProtocol::urf, Header->GetRpt2Module()); if ( client ) { // and try to open the stream - if ( (stream = g_Refl.OpenStream(Header, client)) != nullptr ) + if ( (stream = g_Reflector.OpenStream(Header, client)) != nullptr ) { // keep the handle m_Streams[stream->GetStreamId()] = stream; @@ -374,10 +374,10 @@ void CURFProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header, peer = client->GetCallsign(); } // release - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); // update last heard - g_Refl.GetUsers()->Hearing(my, rpt1, rpt2, peer); - g_Refl.ReleaseUsers(); + g_Reflector.GetUsers()->Hearing(my, rpt1, rpt2, peer); + g_Reflector.ReleaseUsers(); } } @@ -418,7 +418,7 @@ bool CURFProtocol::IsValidConnectPacket(const CBuffer &Buffer, CCallsign *callsi memcpy(modules, Buffer.data()+10, 27); for ( unsigned i = 0; i < strlen(modules); i++ ) { - valid = valid && (g_Refl.IsValidModule (modules[i])); + valid = valid && (g_Reflector.IsValidModule (modules[i])); } } return valid; @@ -448,7 +448,7 @@ bool CURFProtocol::IsValidAckPacket(const CBuffer &Buffer, CCallsign *callsign, memcpy(modules, Buffer.data()+10, 27); for ( unsigned i = 0; i < strlen(modules); i++ ) { - valid = valid && (g_Refl.IsValidModule(modules[i])); + valid = valid && (g_Reflector.IsValidModule(modules[i])); } } return valid; @@ -519,7 +519,7 @@ void CURFProtocol::EncodeKeepAlivePacket(CBuffer *Buffer) { Buffer->Set("PING"); Buffer->resize(10); - g_Refl.GetCallsign().CodeOut(Buffer->data()+4); + g_Reflector.GetCallsign().CodeOut(Buffer->data()+4); } void CURFProtocol::EncodeConnectPacket(CBuffer *Buffer, const char *Modules) @@ -528,12 +528,12 @@ void CURFProtocol::EncodeConnectPacket(CBuffer *Buffer, const char *Modules) Buffer->Set("CONN"); // our callsign Buffer->resize(37); - g_Refl.GetCallsign().CodeOut(Buffer->data()+4); + g_Reflector.GetCallsign().CodeOut(Buffer->data()+4); // our version Buffer->ReplaceAt(10, (uint8_t *)Modules, strlen(Modules)); - Buffer->Append((uint8_t)g_Vers.GetMajor()); - Buffer->Append((uint8_t)g_Vers.GetMinor()); - Buffer->Append((uint8_t)g_Vers.GetRevision()); + Buffer->Append((uint8_t)g_Version.GetMajor()); + Buffer->Append((uint8_t)g_Version.GetMinor()); + Buffer->Append((uint8_t)g_Version.GetRevision()); } void CURFProtocol::EncodeDisconnectPacket(CBuffer *Buffer) @@ -541,7 +541,7 @@ void CURFProtocol::EncodeDisconnectPacket(CBuffer *Buffer) Buffer->Set("DISC"); // our callsign Buffer->resize(10); - g_Refl.GetCallsign().CodeOut(Buffer->data()+4); + g_Reflector.GetCallsign().CodeOut(Buffer->data()+4); } void CURFProtocol::EncodeConnectAckPacket(CBuffer *Buffer, const char *Modules) @@ -549,18 +549,18 @@ void CURFProtocol::EncodeConnectAckPacket(CBuffer *Buffer, const char *Modules) Buffer->Set("ACKN"); // our callsign Buffer->resize(37); - g_Refl.GetCallsign().CodeOut(Buffer->data()+4); + g_Reflector.GetCallsign().CodeOut(Buffer->data()+4); // the shared modules Buffer->ReplaceAt(10, (uint8_t *)Modules, strlen(Modules)); // our version - Buffer->Append((uint8_t)g_Vers.GetMajor()); - Buffer->Append((uint8_t)g_Vers.GetMinor()); - Buffer->Append((uint8_t)g_Vers.GetRevision()); + Buffer->Append((uint8_t)g_Version.GetMajor()); + Buffer->Append((uint8_t)g_Version.GetMinor()); + Buffer->Append((uint8_t)g_Version.GetRevision()); } void CURFProtocol::EncodeConnectNackPacket(CBuffer *Buffer) { Buffer->Set("NACK"); Buffer->resize(10); - g_Refl.GetCallsign().CodeOut(Buffer->data()+4); + g_Reflector.GetCallsign().CodeOut(Buffer->data()+4); } diff --git a/reflector/USRPProtocol.cpp b/reflector/USRPProtocol.cpp index 7738680..a5beab8 100644 --- a/reflector/USRPProtocol.cpp +++ b/reflector/USRPProtocol.cpp @@ -46,18 +46,18 @@ bool CUSRPProtocol::Initialize(const char *type, const EProtocol ptype, const ui if (! CProtocol::Initialize(type, ptype, port, has_ipv4, has_ipv6)) return false; - m_Module = g_Conf.GetAutolinkModule(g_Keys.usrp.module); + m_Module = g_Configure.GetAutolinkModule(g_Keys.usrp.module); // create the one special USRP Tx/Rx client - m_Callsign.SetCallsign(g_Conf.GetString(g_Keys.usrp.callsign), false); - CIp ip(AF_INET, uint16_t(g_Conf.GetUnsigned(g_Keys.usrp.txport)), g_Conf.GetString(g_Keys.ip.ipv4bind).c_str()); + m_Callsign.SetCallsign(g_Configure.GetString(g_Keys.usrp.callsign), false); + CIp ip(AF_INET, uint16_t(g_Configure.GetUnsigned(g_Keys.usrp.txport)), g_Configure.GetString(g_Keys.ip.ipv4bind).c_str()); auto newclient = std::make_shared(m_Callsign, ip); newclient->SetReflectorModule(m_Module); - g_Refl.GetClients()->AddClient(newclient); - g_Refl.ReleaseClients(); + g_Reflector.GetClients()->AddClient(newclient); + g_Reflector.ReleaseClients(); // now create "listen-only" clients, as many as specified - file.open(g_Conf.GetString(g_Keys.usrp.filepath), std::ios::in | std::ios::binary | std::ios::ate); + file.open(g_Configure.GetString(g_Keys.usrp.filepath), std::ios::in | std::ios::binary | std::ios::ate); if ( file.is_open() ) { // read file @@ -96,8 +96,8 @@ bool CUSRPProtocol::Initialize(const char *type, const EProtocol ptype, const ui cs.SetCallsign(clientcs, false); auto newclient = std::make_shared(cs, Ip); newclient->SetReflectorModule(m_Module); - g_Refl.GetClients()->AddClient(newclient); - g_Refl.ReleaseClients(); + g_Reflector.GetClients()->AddClient(newclient); + g_Reflector.ReleaseClients(); } ptr1 = ptr2+1; } @@ -144,7 +144,7 @@ void CUSRPProtocol::Task(void) else if( IsValidDvHeaderPacket(Ip, Buffer, Header) ) { // callsign muted? - if ( g_Gate.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::usrp) ) + if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::usrp) ) { OnDvHeaderPacketIn(Header, Ip); } @@ -201,7 +201,7 @@ void CUSRPProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header, CCallsign rpt2(Header->GetRpt2Callsign()); // find this client - std::shared_ptrclient = g_Refl.GetClients()->FindClient(Ip, EProtocol::usrp); + std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, EProtocol::usrp); if ( client ) { // get client callsign @@ -210,18 +210,18 @@ void CUSRPProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header, Header->SetRpt2Module(m); rpt2.SetCSModule(m); // and try to open the stream - if ( (stream = g_Refl.OpenStream(Header, client)) != nullptr ) + if ( (stream = g_Reflector.OpenStream(Header, client)) != nullptr ) { // keep the handle m_Streams[stream->GetStreamId()] = stream; } } // release - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); // update last heard - g_Refl.GetUsers()->Hearing(my, rpt1, rpt2); - g_Refl.ReleaseUsers(); + g_Reflector.GetUsers()->Hearing(my, rpt1, rpt2); + g_Reflector.ReleaseUsers(); } } @@ -257,7 +257,7 @@ void CUSRPProtocol::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_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::usrp, it)) != nullptr ) @@ -269,7 +269,7 @@ void CUSRPProtocol::HandleQueue(void) Send(buffer, client->GetIp()); } } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } } } @@ -382,7 +382,7 @@ void CUSRPProtocol::EncodeUSRPPacket(const CDvHeaderPacket &Header, const CDvFra void CUSRPProtocol::HandleKeepalives(void) { // iterate on clients - CClients *clients = g_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::usrp, it)) != nullptr ) @@ -402,5 +402,5 @@ void CUSRPProtocol::HandleKeepalives(void) //} } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } diff --git a/reflector/Users.cpp b/reflector/Users.cpp index 8027503..ac7d774 100644 --- a/reflector/Users.cpp +++ b/reflector/Users.cpp @@ -41,7 +41,7 @@ void CUsers::AddUser(const CUser &user) } // notify - g_Refl.OnUsersChanged(); + g_Reflector.OnUsersChanged(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -49,7 +49,7 @@ void CUsers::AddUser(const CUser &user) void CUsers::Hearing(const CCallsign &my, const CCallsign &rpt1, const CCallsign &rpt2) { - Hearing(my, rpt1, rpt2, g_Refl.GetCallsign()); + Hearing(my, rpt1, rpt2, g_Reflector.GetCallsign()); } void CUsers::Hearing(const CCallsign &my, const CCallsign &rpt1, const CCallsign &rpt2, const CCallsign &xlx) diff --git a/reflector/WiresXCmdHandler.cpp b/reflector/WiresXCmdHandler.cpp index d02bdc5..195eca2 100644 --- a/reflector/WiresXCmdHandler.cpp +++ b/reflector/WiresXCmdHandler.cpp @@ -59,8 +59,8 @@ CWiresxCmdHandler::~CWiresxCmdHandler() bool CWiresxCmdHandler::Init(void) { // fill our wiresx info - m_ReflectorWiresxInfo.SetCallsign(g_Refl.GetCallsign()); - m_ReflectorWiresxInfo.SetNode(g_Refl.GetCallsign()); + m_ReflectorWiresxInfo.SetCallsign(g_Reflector.GetCallsign()); + m_ReflectorWiresxInfo.SetNode(g_Reflector.GetCallsign()); m_ReflectorWiresxInfo.SetName("Reflector"); // reset stop flag @@ -146,13 +146,13 @@ void CWiresxCmdHandler::Task(void) // find our client and the module it's currentlink linked to cModule = ' '; - CClients *clients = g_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); std::shared_ptrclient = clients->FindClient(Cmd.GetCallsign(), Cmd.GetIp(), EProtocol::ysf); if ( client ) { cModule = client->GetReflectorModule(); } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); // and crack the cmd switch ( Cmd.GetCmd() ) @@ -170,19 +170,19 @@ void CWiresxCmdHandler::Task(void) break; case WIRESX_CMD_CONN_REQ: cModule = 'A' + (char)(Cmd.GetArg() - 1); - if (g_Refl.IsValidModule(cModule)) + if (g_Reflector.IsValidModule(cModule)) { std::cout << "Wires-X CONN_REQ command to link on module " << cModule << " from " << Cmd.GetCallsign() << " at " << Cmd.GetIp() << std::endl; // acknowledge ReplyToWiresxConnReqPacket(Cmd.GetIp(), Info, cModule); // change client's module - CClients *clients = g_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); std::shared_ptrclient = clients->FindClient(Cmd.GetCallsign(), Cmd.GetIp(), EProtocol::ysf); if ( client ) { client->SetReflectorModule(cModule); } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } else { @@ -195,13 +195,13 @@ void CWiresxCmdHandler::Task(void) ReplyToWiresxDiscReqPacket(Cmd.GetIp(), Info); // change client's module { - CClients *clients = g_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); std::shared_ptrclient = clients->FindClient(Cmd.GetCallsign(), Cmd.GetIp(), EProtocol::ysf); if ( client != nullptr ) { client->SetReflectorModule(' '); } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } break; case WIRESX_CMD_UNKNOWN: @@ -334,7 +334,7 @@ bool CWiresxCmdHandler::ReplyToWiresxAllReqPacket(const CIp &Ip, const CWiresxIn memcpy(data + 12U, WiresxInfo.GetNode(), 10U); // number of entries - const std::string modules(g_Conf.GetString(g_Keys.modules.modules)); + const std::string modules(g_Configure.GetString(g_Keys.modules.modules)); uint NB_OF_MODULES = modules.size(); uint total = NB_OF_MODULES; uint n = NB_OF_MODULES - Start; @@ -738,8 +738,8 @@ bool CWiresxCmdHandler::DebugTestDecodePacket(const CBuffer &Buffer) std::cout << "Trailer" << std::endl; std::cout << "length of payload : " << len << std::endl; dump.Set(command, len); - dump.DebugDump(g_Refl.m_DebugFile); - dump.DebugDumpAscii(g_Refl.m_DebugFile); + dump.DebugDump(g_Reflector.m_DebugFile); + dump.DebugDumpAscii(g_Reflector.m_DebugFile); break; case YSF_FI_COMMUNICATIONS: if ( Fich.getDT() == YSF_DT_DATA_FR_MODE ) diff --git a/reflector/YSFProtocol.cpp b/reflector/YSFProtocol.cpp index 20190e0..1a40ba4 100644 --- a/reflector/YSFProtocol.cpp +++ b/reflector/YSFProtocol.cpp @@ -41,10 +41,10 @@ CYsfProtocol::CYsfProtocol() bool CYsfProtocol::Initialize(const char *type, const EProtocol ptype, const uint16_t port, const bool has_ipv4, const bool has_ipv6) { // config data - m_AutolinkModule = g_Conf.GetAutolinkModule(g_Keys.ysf.autolinkmod); - m_RegistrationId = g_Conf.GetUnsigned(g_Keys.ysf.ysfreflectordb.id); - m_RegistrationName.assign(g_Conf.GetString(g_Keys.ysf.ysfreflectordb.name)); - m_RegistrationDesc.assign(g_Conf.GetString(g_Keys.ysf.ysfreflectordb.description)); + m_AutolinkModule = g_Configure.GetAutolinkModule(g_Keys.ysf.autolinkmod); + m_RegistrationId = g_Configure.GetUnsigned(g_Keys.ysf.ysfreflectordb.id); + m_RegistrationName.assign(g_Configure.GetString(g_Keys.ysf.ysfreflectordb.name)); + m_RegistrationDesc.assign(g_Configure.GetString(g_Keys.ysf.ysfreflectordb.description)); m_RegistrationName.resize(REG_NAME_SIZE, ' '); m_RegistrationDesc.resize(REG_DESC_SIZE, ' '); @@ -127,7 +127,7 @@ void CYsfProtocol::Task(void) else if ( IsValidDvHeaderPacket(Ip, Fich, Buffer, Header, Frames) ) { // node linked and callsign muted? - if ( g_Gate.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::ysf, Header->GetRpt2Module()) ) + if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, EProtocol::ysf, Header->GetRpt2Module()) ) { // handle it OnDvHeaderPacketIn(Header, Ip); @@ -146,14 +146,14 @@ void CYsfProtocol::Task(void) //std::cout << "YSF keepalive/connect packet from " << Callsign << " at " << Ip << std::endl; // callsign authorized? - if ( g_Gate.MayLink(Callsign, Ip, EProtocol::ysf) ) + if ( g_GateKeeper.MayLink(Callsign, Ip, EProtocol::ysf) ) { // acknowledge the request EncodeConnectAckPacket(&Buffer); Send(Buffer, Ip); // add client if needed - CClients *clients = g_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); std::shared_ptrclient = clients->FindClient(Callsign, Ip, EProtocol::ysf); // client already connected ? if ( client == nullptr ) @@ -175,7 +175,7 @@ void CYsfProtocol::Task(void) client->Alive(); } // and done - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } } else if ( IsValidDisconnectPacket(Buffer) ) @@ -183,7 +183,7 @@ void CYsfProtocol::Task(void) std::cout << "YSF disconnect packet from " << Ip << std::endl; // find client - CClients *clients = g_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); std::shared_ptrclient = clients->FindClient(Ip, EProtocol::ysf); if ( client != nullptr ) { @@ -193,7 +193,7 @@ void CYsfProtocol::Task(void) //EncodeDisconnectPacket(&Buffer); //Send(Buffer, Ip); } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } else if ( IsValidwirexPacket(Buffer, &Fich, &Callsign, &iWiresxCmd, &iWiresxArg) ) { @@ -270,7 +270,7 @@ void CYsfProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header, CCallsign rpt2(Header->GetRpt2Callsign()); // find this client - std::shared_ptrclient = g_Refl.GetClients()->FindClient(Ip, EProtocol::ysf); + std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, EProtocol::ysf); if ( client ) { // get client callsign @@ -281,20 +281,20 @@ void CYsfProtocol::OnDvHeaderPacketIn(std::unique_ptr &Header, rpt2.SetCSModule(m); // and try to open the stream - if ( (stream = g_Refl.OpenStream(Header, client)) != nullptr ) + if ( (stream = g_Reflector.OpenStream(Header, client)) != nullptr ) { // keep the handle m_Streams[stream->GetStreamId()] = stream; } } // release - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); // update last heard - if ( g_Refl.IsValidModule(rpt2.GetCSModule()) ) + if ( g_Reflector.IsValidModule(rpt2.GetCSModule()) ) { - g_Refl.GetUsers()->Hearing(my, rpt1, rpt2); - g_Refl.ReleaseUsers(); + g_Reflector.GetUsers()->Hearing(my, rpt1, rpt2); + g_Reflector.ReleaseUsers(); } } } @@ -352,7 +352,7 @@ void CYsfProtocol::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_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::ysf, it)) != nullptr ) @@ -365,7 +365,7 @@ void CYsfProtocol::HandleQueue(void) } } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } } } @@ -380,7 +380,7 @@ void CYsfProtocol::HandleKeepalives(void) // and disconnect them if not // iterate on clients - CClients *clients = g_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); auto it = clients->begin(); std::shared_ptrclient = nullptr; while ( (client = clients->FindNextClient(EProtocol::ysf, it)) != nullptr ) @@ -400,7 +400,7 @@ void CYsfProtocol::HandleKeepalives(void) } } - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -537,7 +537,7 @@ bool CYsfProtocol::IsValidDvFramePacket(const CIp &Ip, const CYSFFICH &Fich, con rpt2.SetCSModule(' '); header = std::unique_ptr(new CDvHeaderPacket(csMY, CCallsign("CQCQCQ"), rpt1, rpt2, m_uiStreamId, Fich.getFN())); - if ( g_Gate.MayTransmit(header->GetMyCallsign(), Ip, EProtocol::ysf, header->GetRpt2Module()) ) + if ( g_GateKeeper.MayTransmit(header->GetMyCallsign(), Ip, EProtocol::ysf, header->GetRpt2Module()) ) { OnDvHeaderPacketIn(header, Ip); } @@ -1003,9 +1003,9 @@ bool CYsfProtocol::EncodeServerStatusPacket(CBuffer *Buffer) const memcpy(description, m_RegistrationDesc.c_str(), REG_DESC_SIZE); Buffer->Append(description, REG_DESC_SIZE); // connected clients - CClients *clients = g_Refl.GetClients(); + CClients *clients = g_Reflector.GetClients(); int count = MIN(999, clients->GetSize()); - g_Refl.ReleaseClients(); + g_Reflector.ReleaseClients(); ::sprintf(sz, "%03u", count); Buffer->Append((uint8_t *)sz, 3); @@ -1079,8 +1079,8 @@ bool CYsfProtocol::DebugTestDecodePacket(const CBuffer &Buffer) std::cout << "Trailer" << std::endl; std::cout << "length of payload : " << len << std::endl; dump.Set(command, len); - dump.DebugDump(g_Refl.m_DebugFile); - dump.DebugDumpAscii(g_Refl.m_DebugFile); + dump.DebugDump(g_Reflector.m_DebugFile); + dump.DebugDumpAscii(g_Reflector.m_DebugFile); break; case YSF_FI_COMMUNICATIONS: if ( Fich.getDT() == YSF_DT_DATA_FR_MODE ) From 0926767a6044ec3bfaae50176d1e032eeb01429d Mon Sep 17 00:00:00 2001 From: Tom Early Date: Fri, 3 Mar 2023 09:17:03 -0700 Subject: [PATCH 32/44] GetKey() returns space-padded value --- reflector/Callsign.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/reflector/Callsign.cpp b/reflector/Callsign.cpp index 940c334..765b6cb 100644 --- a/reflector/Callsign.cpp +++ b/reflector/Callsign.cpp @@ -31,8 +31,8 @@ CCallsign::CCallsign() { // blank all - memset(m_Callsign.c, ' ', CALLSIGN_LEN); - memset(m_Suffix.c, ' ', CALLSUFFIX_LEN); + m_Callsign.l = 0x2020202020202020ul; + m_Suffix.u = 0x20202020u; m_Module = ' '; m_uiDmrid = 0; m_coded = 0; @@ -150,7 +150,7 @@ bool CCallsign::IsValid(void) const iNum++; } } - valid &= (iNum < 3); + valid = valid && (iNum < 3); // all remaining char are letter, number or space for ( ; i < CALLSIGN_LEN; i++) { @@ -337,7 +337,7 @@ void CCallsign::PatchCallsign(int off, const char *patch, int len) UCallsign CCallsign::GetKey() const { UCallsign rval; - rval.l = 0; + rval.l = 0x2020202020202020ul; for (unsigned i=0; i Date: Sat, 4 Mar 2023 12:15:35 -0700 Subject: [PATCH 33/44] optional json report --- reflector/Client.cpp | 12 ++++++++ reflector/Client.h | 3 ++ reflector/Configure.h | 1 + reflector/Peer.cpp | 16 ++++++++++- reflector/Peer.h | 1 + reflector/Reflector.cpp | 64 ++++++++++++++++++++++++++++++++++------- reflector/Reflector.h | 1 + reflector/User.cpp | 15 ++++++++++ reflector/User.h | 3 ++ 9 files changed, 104 insertions(+), 12 deletions(-) diff --git a/reflector/Client.cpp b/reflector/Client.cpp index 4f6c9c7..f026463 100644 --- a/reflector/Client.cpp +++ b/reflector/Client.cpp @@ -95,3 +95,15 @@ void CClient::WriteXml(std::ofstream &xmlFile) } xmlFile << "" << std::endl; } + +void CClient::JsonReport(nlohmann::json &report) +{ + nlohmann::json jclient; + jclient["Callsign"] = m_Callsign.GetCS(); + jclient["OnModule"] = std::string(1, m_ReflectorModule); + jclient["Protocol"] = GetProtocolName(); + char s[100]; + if (std::strftime(s, sizeof(s), "%FT%TZ", std::gmtime(&m_ConnectTime))) + jclient["ConnectTime"] = s; + report["Clients"].push_back(jclient); +} diff --git a/reflector/Client.h b/reflector/Client.h index 28a3e4b..48fb022 100644 --- a/reflector/Client.h +++ b/reflector/Client.h @@ -18,6 +18,8 @@ #pragma once +#include + #include "Defines.h" #include "Timer.h" #include "IP.h" @@ -72,6 +74,7 @@ public: // reporting virtual void WriteXml(std::ofstream &); + void JsonReport(nlohmann::json &report); protected: // data diff --git a/reflector/Configure.h b/reflector/Configure.h index bb52d3f..1ae056a 100644 --- a/reflector/Configure.h +++ b/reflector/Configure.h @@ -41,6 +41,7 @@ public: ERefreshType GetRefreshType(const std::string &key) const; bool IsString(const std::string &key) const; char GetAutolinkModule(const std::string &key) const; + const nlohmann::json &GetData() { return data; } private: // CFGDATA data; diff --git a/reflector/Peer.cpp b/reflector/Peer.cpp index dca36cd..3a1638e 100644 --- a/reflector/Peer.cpp +++ b/reflector/Peer.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 #include #include "Reflector.h" #include "Peer.h" @@ -124,3 +124,17 @@ void CPeer::WriteXml(std::ofstream &xmlFile) } xmlFile << "" << std::endl; } + +void CPeer::JsonReport(nlohmann::json &report) +{ + nlohmann::json jpeer; + jpeer["Callsign"] = m_Callsign.GetCS(); + jpeer["Modules"] = m_ReflectorModules; + jpeer["Protocol"] = GetProtocolName(); + char s[100]; + if (std::strftime(s, sizeof(s), "%FT%TZ", std::gmtime(&m_ConnectTime))) + { + jpeer["ConnectTime"] = s; + } + report["Peers"].push_back(jpeer); +} diff --git a/reflector/Peer.h b/reflector/Peer.h index e91dfb4..bc1ddf9 100644 --- a/reflector/Peer.h +++ b/reflector/Peer.h @@ -68,6 +68,7 @@ public: // reporting virtual void WriteXml(std::ofstream &); + void JsonReport(nlohmann::json &report); protected: // data diff --git a/reflector/Reflector.cpp b/reflector/Reflector.cpp index 956758c..be99277 100644 --- a/reflector/Reflector.cpp +++ b/reflector/Reflector.cpp @@ -298,23 +298,41 @@ void CReflector::RouterThread(const char ThisModule) void CReflector::XmlReportThread() { - const std::string path(g_Configure.GetString(g_Keys.files.xml)); + const std::string xmlpath(g_Configure.GetString(g_Keys.files.xml)); + const std::string jsnpath(g_Configure.GetString(g_Keys.files.json)); while (keep_running) { // report to xml file - std::ofstream xmlFile; - xmlFile.open(path, std::ios::out | std::ios::trunc); - if ( xmlFile.is_open() ) + if (! xmlpath.empty()) { - // write xml file - WriteXmlFile(xmlFile); + std::ofstream xmlFile; + xmlFile.open(xmlpath, std::ios::out | std::ios::trunc); + if ( xmlFile.is_open() ) + { + // write xml file + WriteXmlFile(xmlFile); - // and close file - xmlFile.close(); + // and close file + xmlFile.close(); + } + else + { + std::cout << "Failed to open " << xmlpath << std::endl; + } } - else + + // json report + if (! jsnpath.empty()) { - std::cout << "Failed to open " << path << std::endl; + nlohmann::json jreport; + JsonReport(jreport); + std::ofstream jsonFile; + jsonFile.open(jsnpath, std::ios::out | std::ios::trunc); + if (jsonFile.is_open()) + { + jsonFile << jreport.dump(4); + jsonFile.close(); + } } // and wait a bit @@ -404,7 +422,31 @@ char CReflector::GetStreamModule(std::shared_ptr stream) } //////////////////////////////////////////////////////////////////////////////////////// -// xml helpers +// report helpers + +void CReflector::JsonReport(nlohmann::json &report) +{ + for (auto &item : g_Configure.GetData().items()) + { + if (isupper(item.key().at(0))) + report["Configure"][item.key()] = item.value(); + } + + auto peers = GetPeers(); + for (auto pit=peers->cbegin(); pit!=peers->cend(); pit++) + (*pit)->JsonReport(report); + ReleasePeers(); + + auto clients = GetClients(); + for (auto cit=clients->cbegin(); cit!=clients->cend(); cit++) + (*cit)->JsonReport(report); + ReleaseClients(); + + auto users = GetUsers(); + for (auto uid=users->begin(); uid!=users->end(); uid++) + (*uid).JsonReport(report); + ReleaseUsers(); +} void CReflector::WriteXmlFile(std::ofstream &xmlFile) { diff --git a/reflector/Reflector.h b/reflector/Reflector.h index 30fce3c..efe22ea 100644 --- a/reflector/Reflector.h +++ b/reflector/Reflector.h @@ -90,6 +90,7 @@ protected: // xml helpers void WriteXmlFile(std::ofstream &); + void JsonReport(nlohmann::json &report); protected: // identity diff --git a/reflector/User.cpp b/reflector/User.cpp index e9b54ce..2110fdc 100644 --- a/reflector/User.cpp +++ b/reflector/User.cpp @@ -76,3 +76,18 @@ void CUser::WriteXml(std::ofstream &xmlFile) } xmlFile << "" << std::endl; } + +void CUser::JsonReport(nlohmann::json &report) +{ + nlohmann::json juser; + juser["Callsign"] = m_My.GetCS(); + juser["Repeater"] = m_Rpt1.GetCS(); + juser["OnModule"] = std::string(1, m_Rpt2.GetCSModule()); + juser["ViaPeer"] = m_Xlx.GetCS(); + char s[100]; + if (std::strftime(s, sizeof(s), "%FT%TZ", std::gmtime(&m_LastHeardTime))) + { + juser["LastHeard"] = s; + } + report["Users"].push_back(juser); +} diff --git a/reflector/User.h b/reflector/User.h index 617db1c..d5ed1d2 100644 --- a/reflector/User.h +++ b/reflector/User.h @@ -18,6 +18,8 @@ #pragma once +#include + #include "Callsign.h" #include "Buffer.h" @@ -41,6 +43,7 @@ public: // reporting void WriteXml(std::ofstream &); + void JsonReport(nlohmann::json &report); protected: // data From 217db1c3764b6065a674a49bb97d8cab40d9ec55 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Sun, 5 Mar 2023 05:40:09 -0700 Subject: [PATCH 34/44] create empty Clients, Peers, Users arrays in json --- README.md | 4 ++-- config/urfd.service | 2 +- reflector/Reflector.cpp | 5 ++++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index f902664..9ef0b79 100644 --- a/README.md +++ b/README.md @@ -79,10 +79,10 @@ cp ../config/* . This will create seven files: 1. The `urfd.blacklist` file defines callsigns that are blocked from linking or transmitting. -2. The `urfd.whitelist` file defines callsigns that are allowed to link and transmit. Both of these files support the astrisk as a wild-card. The supplied blacklist and whitelist file are empty, which will allow any callsign to link and transmit, blocking no one. +2. The `urfd.whitelist` file defines callsigns that are allowed to link and transmit. Both of these files support the astrisk as a wild-card. The supplied blacklist and whitelist file are empty, which will allow any callsign to link and transmit, blocking no one. Both files support a limited wildcard feature. 3. The `urfd.interlink` file defines possible Brandmeister and URF linking. 4. The `urfd.terminal` file defines operations for Icom's Terminal and Access Point mode, sometimes called *G3*. This protocol requires significantly higher connection resources than any other mode, so it is possible to build a URF reflector without G3 support. -5. The `urfd.service` file is a systemd file that will start and stop *urfd*. Importantly, it contains the only reference to where the *urfd* initialization file is located. +5. The `urfd.service` file is a systemd file that will start and stop *urfd*. Importantly, it contains the only reference to where the *urfd* initialization file is located. Be sure to set a fully qualified path to your urfd.ini file on the `ExecStart` line. 6. The `urfd.mk` file contains compile-time options for *urfd*. If you change the `BINDIR`, you'll need to update how `urfd.service` starts *urfd*. 7. The `urfd.ini` file contains the run-time options for *urfd* and will be discussed below. diff --git a/config/urfd.service b/config/urfd.service index ada4503..0109457 100644 --- a/config/urfd.service +++ b/config/urfd.service @@ -5,7 +5,7 @@ After=systemd-user-session.service network.target [Service] Type=simple -ExecStart=/usr/local/bin/urfd +ExecStart=/usr/local/bin/urfd /PATH_TO_INI_FILE Restart=always [Install] diff --git a/reflector/Reflector.cpp b/reflector/Reflector.cpp index be99277..5b03a07 100644 --- a/reflector/Reflector.cpp +++ b/reflector/Reflector.cpp @@ -330,7 +330,7 @@ void CReflector::XmlReportThread() jsonFile.open(jsnpath, std::ios::out | std::ios::trunc); if (jsonFile.is_open()) { - jsonFile << jreport.dump(4); + jsonFile << jreport.dump(); jsonFile.close(); } } @@ -432,16 +432,19 @@ void CReflector::JsonReport(nlohmann::json &report) report["Configure"][item.key()] = item.value(); } + report["Peers"] = nlohmann::json::array(); auto peers = GetPeers(); for (auto pit=peers->cbegin(); pit!=peers->cend(); pit++) (*pit)->JsonReport(report); ReleasePeers(); + report["Clients"] = nlohmann::json::array(); auto clients = GetClients(); for (auto cit=clients->cbegin(); cit!=clients->cend(); cit++) (*cit)->JsonReport(report); ReleaseClients(); + report["Users"] = nlohmann::json::array(); auto users = GetUsers(); for (auto uid=users->begin(); uid!=users->end(); uid++) (*uid).JsonReport(report); From 67fad002d3849e9c9699036675e3cc5beb39df23 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Mon, 6 Mar 2023 09:47:30 -0700 Subject: [PATCH 35/44] fixed some problems Doug found --- README.md | 17 ++++++++++++++++- config/urfd.ini | 1 + reflector/Configure.cpp | 22 +++++++++++++++++++--- reflector/Configure.h | 1 + reflector/JsonKeys.h | 4 ++-- reflector/LookupYsf.cpp | 5 +++-- reflector/Reflector.cpp | 18 +++++++++++++----- reflector/USRPProtocol.cpp | 19 ++++++++++++------- 8 files changed, 67 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 9ef0b79..b56e9d3 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,8 @@ This will create seven files: 6. The `urfd.mk` file contains compile-time options for *urfd*. If you change the `BINDIR`, you'll need to update how `urfd.service` starts *urfd*. 7. The `urfd.ini` file contains the run-time options for *urfd* and will be discussed below. +You can acutally put the blacklist, whitelist, interlink, terminal and ini file anyplace and even rename them. Just make sure your ini file and service file have the proper, fully-qualified paths. The service file and the mk file need to be in your `urfd/Reflector` directory. + When you are done with the configuration files and ready to start the installation process, you can return to the main repository directory: @@ -113,6 +115,19 @@ There are three databases needed by *urfd*: 3. The *YSF Tx/Rx* database maps a callsign to a transmit/receive RF frequencies. These databases can come from a URL or a file, or both. If you specify "both", then the file will be read after the URL. +#### Special *USRP* configuration + +If configured, a *USRP* client is very unique. A *USRP* client (an AllStar node) doesn't support any connect or disconnect protocol. The USRP client simply sends and receives *USRP* voice packets. That means, if *USRP* is enabled, the client is created during initialization using the configured callsign, IP address and Tx/Rx ports. + +If `FilePath` is defined, this should point to a text file listing special, listen-only client(s), one per line. Each line defining a read-only client contains an IP address, a port number, and a callsign. Here is an example: + +```bash +1.2.3.1;34001;ALLSTR1; +1.2.3.4;34004;ALLSTR4; +``` + +If you want to create listen-only clients, but you don't need a configured read/write client, then set its `Callsign` to `NONE`. + ### Helper apps There are two, very useful helper applications, *inicheck* and *dbutil*. Both apps will show you a usage message if you execuate them without any arguments. @@ -126,7 +141,7 @@ The *dbutil* app can be used for serveral tasks relating to the three databases - INIFLILE is the path to the infile that defines the location of the http and file sources for these three databases. One at a time, *dbutil* can work with any of the three DATABASEs. It can read either the http or the file SOURCE. It can either show you the data entries that are syntactically correct or incorrect (ACTION). -### installing your system +### Installing your system After you have written your configutation files, you can install your system: diff --git a/config/urfd.ini b/config/urfd.ini index dcc5b73..4782175 100644 --- a/config/urfd.ini +++ b/config/urfd.ini @@ -80,6 +80,7 @@ Port = 10017 [USRP] Enable = false +IPAddress = 1.2.3.4 # the IP address of the USRP client (the Allstar node) RxPort = 34000 TxPort = 32000 Module = A # this has to be a transcoded module! diff --git a/reflector/Configure.cpp b/reflector/Configure.cpp index 84efc86..4664839 100644 --- a/reflector/Configure.cpp +++ b/reflector/Configure.cpp @@ -51,6 +51,7 @@ #define JG3 "G3" #define JG3TERMINALPATH "G3TerminalPath" #define JINTERLINKPATH "InterlinkPath" +#define JIPADDRESS "IPAddress" #define JIPADDRESSES "IP Addresses" #define JIPV4BINDING "IPv4Binding" #define JIPV4EXTERNAL "IPv4External" @@ -398,6 +399,8 @@ bool CConfigure::ReadData(const std::string &path) case ESection::usrp: if (0 == key.compare(JENABLE)) data[g_Keys.usrp.enable] = IS_TRUE(value[0]); + else if (0 == key.compare(JIPADDRESS)) + data[g_Keys.usrp.ip] = value; else if (0 == key.compare(JTXPORT)) data[g_Keys.usrp.txport] = getUnsigned(value, "USRP TxPort", 1024, 65535, 32000); else if (0 == key.compare(JRXPORT)) @@ -688,6 +691,15 @@ bool CConfigure::ReadData(const std::string &path) rval = true; } } + if (isDefined(ErrorLevel::fatal, JUSRP, JIPADDRESS, g_Keys.usrp.ip, rval)) + { + // check for syntax + if (! std::regex_match(data[g_Keys.usrp.ip].get(), IPv4RegEx)) + { + std::cerr << "ERROR: [" << JUSRP << ']' << JIPADDRESS " '" << data[g_Keys.usrp.ip] << "' is malformed" << std::endl; + rval = true; + } + } isDefined(ErrorLevel::fatal, JUSRP, JTXPORT, g_Keys.usrp.txport, rval); isDefined(ErrorLevel::fatal, JUSRP, JRXPORT, g_Keys.usrp.rxport, rval); isDefined(ErrorLevel::fatal, JUSRP, JCALLSIGN, g_Keys.usrp.callsign, rval); @@ -750,7 +762,6 @@ bool CConfigure::ReadData(const std::string &path) checkFile(JFILES, JG3TERMINALPATH, data[g_Keys.files.terminal]); } - return rval; } @@ -883,6 +894,11 @@ ERefreshType CConfigure::GetRefreshType(const std::string &key) const return type; } +bool CConfigure::Contains(const std::string &key) const +{ + return data.contains(key); +} + std::string CConfigure::GetString(const std::string &key) const { std::string str; @@ -917,11 +933,11 @@ unsigned CConfigure::GetUnsigned(const std::string &key) const u = data[key].get(); } else - std::cerr << "ERROR: GetString(): '" << key << "' is not an unsigned value" << std::endl; + std::cerr << "ERROR: GetUnsigned(): '" << key << "' is not an unsigned value" << std::endl; } else { - std::cerr << "ERROR: GetString(): item at '" << key << "' is not defined" << std::endl; + std::cerr << "ERROR: GetUnsigned(): item at '" << key << "' is not defined" << std::endl; } return u; } diff --git a/reflector/Configure.h b/reflector/Configure.h index 1ae056a..18e6161 100644 --- a/reflector/Configure.h +++ b/reflector/Configure.h @@ -34,6 +34,7 @@ class CConfigure public: CConfigure(); bool ReadData(const std::string &path); + bool Contains(const std::string &key) const; void Dump(bool justpublic) const; std::string GetString(const std::string &key) const; unsigned GetUnsigned(const std::string &key) const; diff --git a/reflector/JsonKeys.h b/reflector/JsonKeys.h index 105e700..f604e30 100644 --- a/reflector/JsonKeys.h +++ b/reflector/JsonKeys.h @@ -49,8 +49,8 @@ struct SJsonKeys { modules { "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" }; - struct USRP { const std::string enable, txport,rxport, module, callsign, filepath; } - usrp { "usrpEnable", "urspTxPort", "usrpRxPort", "usrpModule", "usrpCallsign", "usrpFilePath" }; + struct USRP { const std::string enable, ip, txport, rxport, module, callsign, filepath; } + usrp { "usrpEnable", "usrpIpAddress", "urspTxPort", "usrpRxPort", "usrpModule", "usrpCallsign", "usrpFilePath" }; struct P25NXDN { const std::string port, autolinkmod, reflectorid; } p25 { "P25Port", "P25AutolinkMod", "P25ReflectorID" }, diff --git a/reflector/LookupYsf.cpp b/reflector/LookupYsf.cpp index b30f6b6..962c93e 100644 --- a/reflector/LookupYsf.cpp +++ b/reflector/LookupYsf.cpp @@ -51,8 +51,9 @@ void CLookupYsf::UpdateContent(std::stringstream &ss, Eaction action) std::getline(iss, tx_str, ';'); std::getline(iss, rx_str, ';'); cs.SetCallsign(cs_str, false); - auto ltx = atol(tx_str.c_str()); - auto lrx = atol(rx_str.c_str()); + auto ltx = atoll(tx_str.c_str()); + auto lrx = atoll(rx_str.c_str()); + unsigned x = sizeof(lrx); if (ltx > 40000000 && ltx < 0x100000000 && lrx > 40000000 && lrx < 0x100000000 && cs.IsValid()) { if (Eaction::parse == action) diff --git a/reflector/Reflector.cpp b/reflector/Reflector.cpp index 5b03a07..fac7dd7 100644 --- a/reflector/Reflector.cpp +++ b/reflector/Reflector.cpp @@ -104,7 +104,7 @@ bool CReflector::Start(void) } } - // start the reporting threads + // start the reporting thread try { m_XmlReportFuture = std::async(std::launch::async, &CReflector::XmlReportThread, this); @@ -298,8 +298,16 @@ void CReflector::RouterThread(const char ThisModule) void CReflector::XmlReportThread() { - const std::string xmlpath(g_Configure.GetString(g_Keys.files.xml)); - const std::string jsnpath(g_Configure.GetString(g_Keys.files.json)); + std::string xmlpath, jsonpath; + + if (g_Configure.Contains(g_Keys.files.xml)) + xmlpath.assign(g_Configure.GetString(g_Keys.files.xml)); + if (g_Configure.Contains(g_Keys.files.json)) + jsonpath.assign(g_Configure.GetString(g_Keys.files.json)); + + if (xmlpath.empty() && jsonpath.empty()) + return; // nothing to do + while (keep_running) { // report to xml file @@ -322,12 +330,12 @@ void CReflector::XmlReportThread() } // json report - if (! jsnpath.empty()) + if (! jsonpath.empty()) { nlohmann::json jreport; JsonReport(jreport); std::ofstream jsonFile; - jsonFile.open(jsnpath, std::ios::out | std::ios::trunc); + jsonFile.open(jsonpath, std::ios::out | std::ios::trunc); if (jsonFile.is_open()) { jsonFile << jreport.dump(); diff --git a/reflector/USRPProtocol.cpp b/reflector/USRPProtocol.cpp index a5beab8..9ef8153 100644 --- a/reflector/USRPProtocol.cpp +++ b/reflector/USRPProtocol.cpp @@ -49,15 +49,20 @@ bool CUSRPProtocol::Initialize(const char *type, const EProtocol ptype, const ui m_Module = g_Configure.GetAutolinkModule(g_Keys.usrp.module); // create the one special USRP Tx/Rx client - m_Callsign.SetCallsign(g_Configure.GetString(g_Keys.usrp.callsign), false); - CIp ip(AF_INET, uint16_t(g_Configure.GetUnsigned(g_Keys.usrp.txport)), g_Configure.GetString(g_Keys.ip.ipv4bind).c_str()); - auto newclient = std::make_shared(m_Callsign, ip); - newclient->SetReflectorModule(m_Module); - g_Reflector.GetClients()->AddClient(newclient); - g_Reflector.ReleaseClients(); + auto scs = g_Configure.GetString(g_Keys.usrp.callsign); + if (scs.compare("NONE")) + { + m_Callsign.SetCallsign(scs, false); + CIp ip(AF_INET, uint16_t(g_Configure.GetUnsigned(g_Keys.usrp.txport)), g_Configure.GetString(g_Keys.usrp.ip).c_str()); + auto newclient = std::make_shared(m_Callsign, ip); + newclient->SetReflectorModule(m_Module); + g_Reflector.GetClients()->AddClient(newclient); + g_Reflector.ReleaseClients(); + } // now create "listen-only" clients, as many as specified - file.open(g_Configure.GetString(g_Keys.usrp.filepath), std::ios::in | std::ios::binary | std::ios::ate); + if (g_Configure.Contains(g_Keys.usrp.filepath)) + file.open(g_Configure.GetString(g_Keys.usrp.filepath), std::ios::in | std::ios::binary | std::ios::ate); if ( file.is_open() ) { // read file From 1f41d8b3ea9285087a8d41654830e17994cdbd78 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Mon, 6 Mar 2023 10:25:22 -0700 Subject: [PATCH 36/44] added comments to [USRP] section --- config/urfd.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/urfd.ini b/config/urfd.ini index 4782175..e476ab6 100644 --- a/config/urfd.ini +++ b/config/urfd.ini @@ -80,12 +80,12 @@ Port = 10017 [USRP] Enable = false +Callsign = ALLSTAR # set to NONE if you don't want to create this client IPAddress = 1.2.3.4 # the IP address of the USRP client (the Allstar node) RxPort = 34000 TxPort = 32000 Module = A # this has to be a transcoded module! -Callsign = ALLSTAR -#FilePath = /home/usr/Clients.txt +#FilePath = /home/usr/clients.txt # a list of listen-only clients [YSF] Port = 42000 From b73aa1290d1bab7f29d7eba12a739e2ad59e6e87 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Tue, 7 Mar 2023 05:06:17 -0700 Subject: [PATCH 37/44] README --- README.md | 33 +++++++++++---------------------- 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index b56e9d3..633c679 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ sudo apt upgrade sudo apt install git sudo apt install apache2 php5 sudo apt install build-essential -sudo apt install nlohman-json3-dev +sudo apt install nlohmann-json3-dev ``` ### Download and build the repository and @@ -58,35 +58,24 @@ git clone https://github.com/n7tae/urfd.git cd urfd/reflector ``` -You'll need to set two compile-time options: - -```bash -cp example.mk configure.mk -``` - -This will disable debugging and define where the Makefile will install *urfd*. -If you want to change this, edit the configure.mk file with your favorite text editor. Then do a `make` to build *urfd*. - ### Create and edit your configuration files First, move to the reflector build directory and create your configuration file: ```bash -cd urfd/reflector - cp ../config/* . ``` This will create seven files: -1. The `urfd.blacklist` file defines callsigns that are blocked from linking or transmitting. -2. The `urfd.whitelist` file defines callsigns that are allowed to link and transmit. Both of these files support the astrisk as a wild-card. The supplied blacklist and whitelist file are empty, which will allow any callsign to link and transmit, blocking no one. Both files support a limited wildcard feature. -3. The `urfd.interlink` file defines possible Brandmeister and URF linking. -4. The `urfd.terminal` file defines operations for Icom's Terminal and Access Point mode, sometimes called *G3*. This protocol requires significantly higher connection resources than any other mode, so it is possible to build a URF reflector without G3 support. -5. The `urfd.service` file is a systemd file that will start and stop *urfd*. Importantly, it contains the only reference to where the *urfd* initialization file is located. Be sure to set a fully qualified path to your urfd.ini file on the `ExecStart` line. -6. The `urfd.mk` file contains compile-time options for *urfd*. If you change the `BINDIR`, you'll need to update how `urfd.service` starts *urfd*. -7. The `urfd.ini` file contains the run-time options for *urfd* and will be discussed below. +1. The `urfd.mk` file contains compile-time options for *urfd*. If you change the `BINDIR`, you'll need to update how `urfd.service` starts *urfd*. +2. The `urfd.ini` file contains the run-time options for *urfd* and will be discussed below. +3. The `urfd.blacklist` file defines callsigns that are blocked from linking or transmitting. +4. The `urfd.whitelist` file defines callsigns that are allowed to link and transmit. Both of these files support the astrisk as a wild-card. The supplied blacklist and whitelist file are empty, which will allow any callsign to link and transmit, blocking no one. Both files support a limited wildcard feature. +5. The `urfd.interlink` file defines possible Brandmeister and URF linking. +6. The `urfd.terminal` file defines operations for Icom's Terminal and Access Point mode, sometimes called *G3*. This protocol requires significantly higher connection resources than any other mode, so it is possible to build a URF reflector without G3 support. +7. The `urfd.service` file is a systemd file that will start and stop *urfd*. Importantly, it contains the only reference to where the *urfd* ini file is located. Be sure to set a fully qualified path to your urfd.ini file on the `ExecStart` line. -You can acutally put the blacklist, whitelist, interlink, terminal and ini file anyplace and even rename them. Just make sure your ini file and service file have the proper, fully-qualified paths. The service file and the mk file need to be in your `urfd/Reflector` directory. +You can acutally put the blacklist, whitelist, interlink, terminal and ini file anyplace and even rename them. Just make sure your ini file and service file have the proper, fully-qualified paths. The service file and the mk file need to remain in your `urfd/reflector` directory. When you are done with the configuration files and ready to start the installation process, you can return to the main repository directory: @@ -203,9 +192,9 @@ It has nothing to do with the regular YSFReflector network, hence you don’t ne ## To-dos -I will eventually support a remote transcoder option, so that you can, for example, run urfd in a data center, and then run the transcoder somewhere you have physical access to it so you can plug in your AMBE vocoders. I don't recommend this as it will add unnessary and variable latency to your reflector. +I will eventually support a remote transcoder option, so that you can, for example, run *urfd* in a data center, and then run the transcoder somewhere you have physical access so you can plug in your AMBE vocoders. I don't recommend this as it will add unnessary and variable latency to your reflector. -The M17 team will be working on big changes for the dashboard! +A new dashboard is on the to-do list! ## Copyright From f63c290b4dfa9ec7e20a9140de20f1aba8e037ef Mon Sep 17 00:00:00 2001 From: Tom Early Date: Tue, 7 Mar 2023 08:06:24 -0700 Subject: [PATCH 38/44] fixes a problem when there are three transcoded modules --- reflector/Configure.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reflector/Configure.cpp b/reflector/Configure.cpp index 4664839..35dfa3a 100644 --- a/reflector/Configure.cpp +++ b/reflector/Configure.cpp @@ -603,10 +603,10 @@ bool CConfigure::ReadData(const std::string &path) // 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; + std::cout << "WARNING: [" << JMODULES << ']' << JTRANSCODED << " doesn't define one (or three) modules" << std::endl; // make sure each transcoded module is configured - for (auto c : data[g_Keys.modules.tcmodules]) + for (auto c : tcmods) { if (std::string::npos == mods.find(c)) { From 73ac08e34b752df9c07fa4b346273c3815429a27 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Tue, 7 Mar 2023 13:03:20 -0700 Subject: [PATCH 39/44] fixed IPv6 binding --- reflector/Protocol.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reflector/Protocol.cpp b/reflector/Protocol.cpp index 47b948b..fb9db9e 100644 --- a/reflector/Protocol.cpp +++ b/reflector/Protocol.cpp @@ -76,7 +76,7 @@ bool CProtocol::Initialize(const char *type, const EProtocol ptype, const uint16 { if (has_ipv6) { - const std::string ipv6binding(g_Keys.ip.ipv6bind); + const std::string ipv6binding(g_Configure.GetString(g_Keys.ip.ipv6bind)); CIp ip6(AF_INET6, port, ipv6binding.c_str()); if ( ip6.IsSet() ) { From f6138584e01944cb70494f98340adca76f4bae1d Mon Sep 17 00:00:00 2001 From: Tom Early Date: Wed, 8 Mar 2023 08:41:00 -0700 Subject: [PATCH 40/44] added open boolean to control the CodecStream Task() --- reflector/CodecStream.cpp | 43 ++++++++++++++++++++++++-------------- reflector/CodecStream.h | 11 +++++++--- reflector/PacketStream.cpp | 4 ++-- 3 files changed, 37 insertions(+), 21 deletions(-) diff --git a/reflector/CodecStream.cpp b/reflector/CodecStream.cpp index 6109fc0..afd7334 100644 --- a/reflector/CodecStream.cpp +++ b/reflector/CodecStream.cpp @@ -25,7 +25,7 @@ //////////////////////////////////////////////////////////////////////////////////////// // constructor -CCodecStream::CCodecStream(CPacketStream *PacketStream) +CCodecStream::CCodecStream(CPacketStream *PacketStream, char module) : m_CSModule(module), m_IsOpen(false) { m_PacketStream = PacketStream; } @@ -47,6 +47,7 @@ CCodecStream::~CCodecStream() void CCodecStream::ResetStats(uint16_t streamid, ECodecType type) { + m_IsOpen = true; keep_running = true; m_uiStreamId = streamid; m_uiPid = 0; @@ -60,6 +61,7 @@ void CCodecStream::ResetStats(uint16_t streamid, ECodecType type) void CCodecStream::ReportStats() { + m_IsOpen = false; // display stats if (m_RTCount > 0) { @@ -68,7 +70,7 @@ void CCodecStream::ReportStats() double ave = 1000.0 * m_RTSum / double(m_RTCount); auto prec = std::cout.precision(); std::cout.precision(1); - std::cout << std::fixed << "TC round-trip time(ms): " << min << "/" << ave << "/" << max << ", " << m_RTCount << " total packets" << std::endl; + std::cout << std::fixed << "TC round-trip time(ms): " << min << '/' << ave << '/' << max << ", " << m_RTCount << " total packets" << std::endl; std::cout.precision(prec); } } @@ -76,16 +78,14 @@ void CCodecStream::ReportStats() //////////////////////////////////////////////////////////////////////////////////////// // initialization -bool CCodecStream::InitCodecStream(char module) +bool CCodecStream::InitCodecStream() { m_TCWriter.SetUp(REF2TC); std::string name(TC2REF); - name.append(1, module); + name.append(1, m_CSModule); if (m_TCReader.Open(name.c_str())) return true; -#ifdef DEBUG - std::cout << "Initialized unix socket " << name << std::endl; -#endif + std::cout << "Initialized CodecStream receive socket " << name << std::endl; keep_running = true; try { @@ -93,7 +93,8 @@ bool CCodecStream::InitCodecStream(char module) } catch(const std::exception& e) { - std::cerr << "Could not start Codec processing on module '" << module << "': " << e.what() << std::endl; + std::cerr << "Could not start Codec processing on module '" << m_CSModule << "': " << e.what() << std::endl; + m_TCReader.Close(); return true; } return false; @@ -136,15 +137,17 @@ void CCodecStream::Task(void) if ( m_LocalQueue.IsEmpty() ) { - std::cout << "Unexpected transcoded packet received from transcoder" << std::endl; + std::cout << "Unexpected transcoded packet received from transcoder: Module='" << pack.module << "' StreamID=" << std::hex << std::showbase << ntohs(pack.streamid) << std::endl; } - else + else if (m_IsOpen) { // pop the original packet auto Packet = m_LocalQueue.Pop(); auto Frame = (CDvFramePacket *)Packet.get(); // do things look okay? + if (pack.module != m_CSModule) + std::cerr << "CodecStream '" << m_CSModule << "' received a transcoded packet from module '" << pack.module << "'" << std::dec << std::noshowbase << std::endl; if (pack.sequence != Frame->GetCodecPacket()->sequence) std::cerr << "Sequence mismatch: this voice frame=" << Frame->GetCodecPacket()->sequence << " returned transcoder packet=" << pack.sequence << std::endl; if (pack.streamid != Frame->GetCodecPacket()->streamid) @@ -162,6 +165,10 @@ void CCodecStream::Task(void) // and push it back to client m_PacketStream->ReturnPacket(std::move(Packet)); } + else + { + std::cout << "Transcoder packet received but CodecStream[" << m_CSModule << "] is closed: Module='" << pack.module << "' StreamID=" << std::hex << std::showbase << ntohs(pack.streamid) << std::endl; + } } // anything in our queue @@ -171,14 +178,18 @@ void CCodecStream::Task(void) // we need a CDvFramePacket pointer to access Frame stuff auto Frame = (CDvFramePacket *)Packet.get(); - // update important stuff in Frame->m_TCPack for the transcoder - Frame->SetTCParams(m_uiTotalPackets++); + if (m_IsOpen) + { + // update important stuff in Frame->m_TCPack for the transcoder + // sets the packet counter, stream id, last_packet, module and start the trip timer + Frame->SetTCParams(m_uiTotalPackets++); - // now send to transcoder - m_TCWriter.Send(Frame->GetCodecPacket()); + // now send to transcoder + m_TCWriter.Send(Frame->GetCodecPacket()); - // push to our local queue where it can wait for the transcoder - m_LocalQueue.Push(std::move(Packet)); + // push to our local queue where it can wait for the transcoder + m_LocalQueue.Push(std::move(Packet)); + } // get the next packet, if there is one Packet = m_Queue.Pop(); diff --git a/reflector/CodecStream.h b/reflector/CodecStream.h index 3b5f3b9..74db476 100644 --- a/reflector/CodecStream.h +++ b/reflector/CodecStream.h @@ -34,8 +34,8 @@ class CCodecStream { public: // constructor - CCodecStream(CPacketStream *packetstream); - bool InitCodecStream(char module); + CCodecStream(CPacketStream *packetstream, char module); + bool InitCodecStream(); void ResetStats(uint16_t streamid, ECodecType codectype); void ReportStats(); @@ -54,7 +54,10 @@ public: void Push(std::unique_ptr p) { m_Queue.Push(std::move(p)); } protected: - // initialization + // identity + const char m_CSModule; + // state + std::atomic m_IsOpen; // data uint16_t m_uiStreamId; uint16_t m_uiPort; @@ -67,6 +70,8 @@ protected: // associated packet stream CPacketStream *m_PacketStream; + + // queues CSafePacketQueue> m_LocalQueue, m_Queue; // thread diff --git a/reflector/PacketStream.cpp b/reflector/PacketStream.cpp index a81c90e..15fb4b5 100644 --- a/reflector/PacketStream.cpp +++ b/reflector/PacketStream.cpp @@ -33,9 +33,9 @@ CPacketStream::CPacketStream(char module) : m_PSModule(module) bool CPacketStream::InitCodecStream() { - m_CodecStream = std::unique_ptr(new CCodecStream(this)); + m_CodecStream = std::unique_ptr(new CCodecStream(this, m_PSModule)); if (m_CodecStream) - return m_CodecStream->InitCodecStream(m_PSModule); + return m_CodecStream->InitCodecStream(); else { std::cerr << "Could not create a CCodecStream for module '" << m_PSModule << "'" << std::endl; From a6e07d27c29cba4bdaa510a4d792f1e0b0a2878f Mon Sep 17 00:00:00 2001 From: Tom Early Date: Wed, 8 Mar 2023 10:28:13 -0700 Subject: [PATCH 41/44] there are 3 reqs to push a packet to the CodecStream --- reflector/PacketStream.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/reflector/PacketStream.cpp b/reflector/PacketStream.cpp index 15fb4b5..7582c28 100644 --- a/reflector/PacketStream.cpp +++ b/reflector/PacketStream.cpp @@ -86,8 +86,10 @@ void CPacketStream::Push(std::unique_ptr Packet) { Packet->UpdatePids(m_uiPacketCntr++); } - // transcoder avaliable and is this a DvFramePacket? - if ( m_CodecStream && Packet->IsDvFrame()) + // ... Is there a CodecStream (is this module transcoded)? + // AND Is this voice data? + // AND Is this from a local client and not from an interlinked URF + if ( m_CodecStream && Packet->IsDvFrame() && Packet->IsLocalOrigin()) { // yes, push packet to trancoder queue // trancoder will push it after transcoding From ae1e686e8fdbbc8c2d15d8baad1f26cc0b8fbe92 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Wed, 8 Mar 2023 11:54:14 -0700 Subject: [PATCH 42/44] improved radmin --- README.md | 4 ++-- radmin | 24 +++++++++++------------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 633c679..95dbb5c 100644 --- a/README.md +++ b/README.md @@ -135,10 +135,10 @@ One at a time, *dbutil* can work with any of the three DATABASEs. It can read ei After you have written your configutation files, you can install your system: ```bash -./radmin +./radmin ``` -Use can use this interactive shell script to install and uninstall your system. This can also perform other tasks like restarting the reflector or transcoder process, or be used to view the reflector or transcoder log in real time. +You can use this interactive shell script to install and uninstall your system. This can also perform other tasks like restarting the reflector or transcoder process, or be used to view the reflector or transcoder log in real time. ### Stoping and starting the services manually diff --git a/radmin b/radmin index 60f6591..ba8f9be 100755 --- a/radmin +++ b/radmin @@ -76,8 +76,14 @@ if [[ $# -eq 1 ]]; then exit 1 fi else - echo "Usage: ./radmin inifilename" - exit 1 + if [[ -e reflector/urfd.ini ]]; then + callsign=$(awk '$1 == "Callsign"{print $3}' reflector/urfd.ini) + tcaddress=$(awk '$1 == "Transcoder"{print $3}' reflector/urfd.ini) + else + echo "ERROR: could not find reflector/urfd.ini! You'll have to specify it." + echo "Usage: ./radmin PATH-TO-INI-FILE" + exit 1 + fi fi key='x' # main loop @@ -91,11 +97,10 @@ do ps -aux | grep -e urfd -e tcd | grep -v grep | grep -v radmin fi echo - echo " Reflector Administration, Version #230221" + echo " Reflector Administration, Version #230308" echo git status | head -1 echo - echo "ls : List the configuration file" if [ -e $urfserv ]; then if [ -e $urfserv ]; then echo "us : Uninstall the URF reflector" @@ -126,11 +131,7 @@ do echo read -p "Please input - omit value to toggle a true/false : " key value garbage - if [[ "$key" == ls* ]]; then - cat reflector.cfg; - echo - read -p " to return to main menu: " ans - elif [[ "$key" == us* ]]; then + if [[ "$key" == us* ]]; then if [ -e $urfserv ]; then UninstallReflector fi @@ -138,10 +139,7 @@ do if [ -e reflector/urfd ] && [ ! -e $urfserv ]; then InstallReflector fi - elif [[ "$key" == rr* ]]; then - if [ -e $urfserv ]; then - sudo systemctl restart urfd - fi + elif [[ "$key" == rr* ]] && [ -e $urfserv ]; then sudo systemctl restart urfd elif [[ "$key" == tr* ]] && [ -e $tcdserv ]; then sudo systemctl restart tcd elif [[ "$key" == tl* ]] && [ -e $tcdserv ]; then sudo journalctl -u tcd -f elif [[ "$key" == rl* ]] && [ -e $urfserv ]; then sudo journalctl -u urfd -f From 79445b9c0a5b4f0ecd1bb31a714b2a81188bf180 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Mon, 13 Mar 2023 06:24:36 -0700 Subject: [PATCH 43/44] removed mysql include --- reflector/LookupYsf.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/reflector/LookupYsf.cpp b/reflector/LookupYsf.cpp index 962c93e..5e1ca96 100644 --- a/reflector/LookupYsf.cpp +++ b/reflector/LookupYsf.cpp @@ -19,7 +19,6 @@ #include #include #include -#include #include #include "Global.h" From 375464c1cc82849bb40170e980ad5c12bd3059c8 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Tue, 14 Mar 2023 10:55:42 -0700 Subject: [PATCH 44/44] added p25 and usrp data to DVFramePacket(), bumped version --- reflector/DVFramePacket.cpp | 20 ++++++-------------- reflector/DVFramePacket.h | 3 --- reflector/DVHeaderPacket.cpp | 31 ------------------------------- reflector/DVHeaderPacket.h | 3 --- reflector/Main.cpp | 2 +- 5 files changed, 7 insertions(+), 52 deletions(-) diff --git a/reflector/DVFramePacket.cpp b/reflector/DVFramePacket.cpp index eaab0a5..0dfc2b1 100644 --- a/reflector/DVFramePacket.cpp +++ b/reflector/DVFramePacket.cpp @@ -175,7 +175,7 @@ std::unique_ptr CDvFramePacket::Copy(void) // Network unsigned int CDvFramePacket::GetNetworkSize() { - return CPacket::GetNetworkSize() + 4 + 3 + 7 + 14 + 9 + 9 + 16; + return CPacket::GetNetworkSize() + 4 + 3 + 7 + 14 + 9 + 9 + 16 + 11 + 320; } CDvFramePacket::CDvFramePacket(const CBuffer &buf) : CPacket(buf) @@ -194,6 +194,8 @@ CDvFramePacket::CDvFramePacket(const CBuffer &buf) : CPacket(buf) memcpy(m_TCPack.dstar, data+off, 9); off += 9; memcpy(m_TCPack.dmr, data+off, 9); off += 9; memcpy(m_TCPack.m17, data+off, 16); off += 16; + memcpy(m_TCPack.p25, data+off, 11); off += 11; + memcpy(m_TCPack.usrp, data+off, 320); SetTCParams(seq); } else @@ -215,7 +217,9 @@ void CDvFramePacket::EncodeInterlinkPacket(CBuffer &buf) const memcpy(data+off, m_Nonce, 14); off += 14; memcpy(data+off, m_TCPack.dstar, 9); off += 9; memcpy(data+off, m_TCPack.dmr, 9); off += 9; - memcpy(data+off, m_TCPack.m17, 16); + memcpy(data+off, m_TCPack.m17, 16); off += 16; + memcpy(data+off, m_TCPack.p25, 11); off += 11; + memcpy(data+off, m_TCPack.usrp, 320); } //////////////////////////////////////////////////////////////////////////////////////// @@ -262,15 +266,3 @@ void CDvFramePacket::SetTCParams(uint32_t seq) m_TCPack.module = m_cModule; m_TCPack.rt_timer.start(); } - -//////////////////////////////////////////////////////////////////////////////////////// -// operators - -bool CDvFramePacket::operator ==(const CDvFramePacket &DvFrame) const -{ - return ( (memcmp(m_TCPack.dstar, DvFrame.m_TCPack.dstar, 9) == 0) - && (memcmp(m_uiDvData, DvFrame.m_uiDvData, 3) == 0) - && (memcmp(m_TCPack.dmr, DvFrame.m_TCPack.dmr, 9) == 0) - && (memcmp(m_uiDvSync, DvFrame.m_uiDvSync, 7) == 0) - ); -} diff --git a/reflector/DVFramePacket.h b/reflector/DVFramePacket.h index 21bbcd8..d4c964a 100644 --- a/reflector/DVFramePacket.h +++ b/reflector/DVFramePacket.h @@ -80,9 +80,6 @@ public: void SetCodecData(const STCPacket *pack); void SetTCParams(uint32_t seq); - // operators - bool operator ==(const CDvFramePacket &) const; - protected: // data (dstar) uint8_t m_uiDvData[3]; diff --git a/reflector/DVHeaderPacket.cpp b/reflector/DVHeaderPacket.cpp index bc23760..d037faa 100644 --- a/reflector/DVHeaderPacket.cpp +++ b/reflector/DVHeaderPacket.cpp @@ -201,34 +201,3 @@ bool CDvHeaderPacket::IsValid(void) const return valid; } - - -//////////////////////////////////////////////////////////////////////////////////////// -// operators - -bool CDvHeaderPacket::operator ==(const CDvHeaderPacket &Header) const -{ - return ( (m_uiFlag1 == Header.m_uiFlag1) && - (m_uiFlag2 == Header.m_uiFlag2) && - (m_uiFlag3 == Header.m_uiFlag3) && - (m_csUR == Header.m_csUR) && - (m_csRPT1 == Header.m_csRPT1) && - (m_csRPT2 == Header.m_csRPT2) && - (m_csMY == Header.m_csMY) ); -} - -#ifdef IMPLEMENT_CDVHEADERPACKET_CONST_CHAR_OPERATOR -CDvHeaderPacket::operator const char *() const -{ - char *sz = (char *)(const char *)m_sz; - - std::sprintf(sz, "%02X %02X %02X\n%s\n%s\n%s\n%s", - m_uiFlag1, m_uiFlag2, m_uiFlag3, - (const char *)m_csUR, - (const char *)m_csRPT1, - (const char *)m_csRPT2, - (const char *)m_csMY); - - return m_sz; -} -#endif diff --git a/reflector/DVHeaderPacket.h b/reflector/DVHeaderPacket.h index 7bbfd29..63793be 100644 --- a/reflector/DVHeaderPacket.h +++ b/reflector/DVHeaderPacket.h @@ -92,9 +92,6 @@ public: void SetRpt2Callsign(const CCallsign &cs) { m_csRPT2 = cs; } void SetRpt2Module(char c) { m_csRPT2.SetCSModule(c); } - // operators - bool operator ==(const CDvHeaderPacket &) const; - protected: // data uint8_t m_uiFlag1; diff --git a/reflector/Main.cpp b/reflector/Main.cpp index afa2209..098d35a 100644 --- a/reflector/Main.cpp +++ b/reflector/Main.cpp @@ -28,7 +28,7 @@ SJsonKeys g_Keys; CReflector g_Reflector; CGateKeeper g_GateKeeper; CConfigure g_Configure; -CVersion g_Version(3,0,0); // The major byte should only change if the interlink packet changes! +CVersion g_Version(3,0,1); // The major byte should only change if the interlink packet changes! CLookupDmr g_LDid; CLookupNxdn g_LNid; CLookupYsf g_LYtr;