From cba48ae54a7b0f20d12fe0e1e5ab6db982cd89e4 Mon Sep 17 00:00:00 2001 From: firealarmss <99303085+firealarmss@users.noreply.github.com> Date: Fri, 14 Jun 2024 06:12:43 -0500 Subject: [PATCH] Add support for peer blacklist and whitelist (#55) * Initial work for a peer whitelist/blacklist * Remove forgotten debug log * Remove extra line * Use a dedicated file for white/blacklists * Add support to REST for managing the peer white/blacklist * Fix line spaces * Move to one example file --- configs/fne-config.example.yml | 14 +- configs/peer_list.example.dat | 3 + src/common/lookups/LookupTable.h | 2 +- src/common/lookups/PeerListLookup.cpp | 245 ++++++++++++++++++++++++++ src/common/lookups/PeerListLookup.h | 94 ++++++++++ src/fne/HostFNE.cpp | 34 +++- src/fne/HostFNE.h | 2 + src/fne/network/FNENetwork.cpp | 16 +- src/fne/network/FNENetwork.h | 4 +- src/fne/network/RESTAPI.cpp | 115 +++++++++++- src/fne/network/RESTAPI.h | 12 +- src/fne/network/RESTDefines.h | 5 + 12 files changed, 536 insertions(+), 10 deletions(-) create mode 100644 configs/peer_list.example.dat create mode 100644 src/common/lookups/PeerListLookup.cpp create mode 100644 src/common/lookups/PeerListLookup.h diff --git a/configs/fne-config.example.yml b/configs/fne-config.example.yml index 2199df2c..16d5f026 100644 --- a/configs/fne-config.example.yml +++ b/configs/fne-config.example.yml @@ -202,7 +202,17 @@ system: # Radio ID ACL Configuration # radio_id: - # Full path to the identity table file. + # Full path to the Radio ID ACL file. file: rid_acl.dat - # Amount of time between updates of identity table file. (minutes) + # Amount of time between updates of Radio ID ACL file. (minutes) time: 2 + + # Peer whitelist and blacklist configuration + peer_acl: + enabled: true + # whitelist or blacklist + mode: whitelist + # Full path to the White/Blacklist file. + file: peer_whitelist.dat + # Amount of time between updates of White/Blacklist file. (minutes) + time: 1 diff --git a/configs/peer_list.example.dat b/configs/peer_list.example.dat new file mode 100644 index 00000000..c522fb8e --- /dev/null +++ b/configs/peer_list.example.dat @@ -0,0 +1,3 @@ +# Example blacklist or whitelist +1234 +12345 diff --git a/src/common/lookups/LookupTable.h b/src/common/lookups/LookupTable.h index 58e0e97f..e846d7e9 100644 --- a/src/common/lookups/LookupTable.h +++ b/src/common/lookups/LookupTable.h @@ -152,4 +152,4 @@ namespace lookups }; } // namespace lookups -#endif // __LOOKUP_TABLE_H__ +#endif // __LOOKUP_TABLE_H__ \ No newline at end of file diff --git a/src/common/lookups/PeerListLookup.cpp b/src/common/lookups/PeerListLookup.cpp new file mode 100644 index 00000000..c26119f6 --- /dev/null +++ b/src/common/lookups/PeerListLookup.cpp @@ -0,0 +1,245 @@ +// SPDX-License-Identifier: GPL-2.0-only +/** +* Digital Voice Modem - Common Library +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / Common Library +* @derivedfrom MMDVMHost (https://github.com/g4klx/MMDVMHost) +* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) +* +* Copyright (C) 2016 Jonathan Naylor, G4KLX +* Copyright (C) 2017-2022 Bryan Biedenkapp, N2PLL +* Copyright (c) 2024 Patrick McDonnell, W3AXL +* Copyright (c) 2024 Caleb, KO4UYJ +* +*/ +#include "PeerListLookup.h" +#include "Log.h" + +using namespace lookups; + +#include +#include + +// --------------------------------------------------------------------------- +// Static Class Members +// --------------------------------------------------------------------------- + +std::mutex PeerListLookup::m_mutex; + +// --------------------------------------------------------------------------- +// Public Class Members +// --------------------------------------------------------------------------- + +/// +/// Initializes a new instance of the PeerListLookup class. +/// +/// Full-path to the list file. +/// Mode to operate in (WHITELIST or BLACKLIST). +/// Flag indicating if the lookup is enabled. +PeerListLookup::PeerListLookup(const std::string& listFile, Mode mode, uint32_t reloadTime, bool enabled) + : LookupTable(listFile, reloadTime), m_mode(mode), m_enabled(enabled) +{ + /* stub */ +} + +/// +/// Get the list of peers in the table. +/// +std::vector PeerListLookup::getPeerList() const +{ + std::lock_guard lock(m_mutex); + return m_list; +} + +/// +/// Clears all entries from the list. +/// +void PeerListLookup::clear() +{ + std::lock_guard lock(m_mutex); + m_list.clear(); +} + +/// +/// Adds a new entry to the list. +/// +/// Unique peer ID to add. +void PeerListLookup::addEntry(uint32_t peerId) +{ + std::lock_guard lock(m_mutex); + if (std::find(m_list.begin(), m_list.end(), peerId) == m_list.end()) { + m_list.push_back(peerId); + } +} + +/// +/// Removes an existing entry from the list. +/// +/// Unique peer ID to remove. +void PeerListLookup::removeEntry(uint32_t peerId) +{ + std::lock_guard lock(m_mutex); + m_list.erase(std::remove(m_list.begin(), m_list.end(), peerId), m_list.end()); +} + +/// +/// Checks if a peer ID is in the list. +/// +/// Unique peer ID to check. +/// True if the peer ID is in the list, otherwise false. +bool PeerListLookup::isPeerInList(uint32_t peerId) const +{ + std::lock_guard lock(m_mutex); + bool found = std::find(m_list.begin(), m_list.end(), peerId) != m_list.end(); + + return found; +} + +/// +/// Checks if a peer ID is allowed based on the mode and enabled flag. +/// +/// Unique peer ID to check. +/// True if the peer ID is allowed, otherwise false. +bool PeerListLookup::isPeerAllowed(uint32_t peerId) const +{ + if (!m_enabled) { + return true; // if not enabled, allow all peers + } + + bool allowed = false; + if (m_mode == WHITELIST) { + allowed = isPeerInList(peerId); + } else if (m_mode == BLACKLIST) { + allowed = !isPeerInList(peerId); + } + + return allowed; +} + +/// +/// Commit the table. +/// +/// The mode to set. +void PeerListLookup::commit() +{ + save(); +} + +/// +/// Sets the mode to either WHITELIST or BLACKLIST. +/// +/// The mode to set. +void PeerListLookup::setMode(Mode mode) +{ + std::lock_guard lock(m_mutex); + m_mode = mode; +} + +/// +/// Gets the current mode. +/// +PeerListLookup::Mode PeerListLookup::getMode() const +{ + return m_mode; +} + +/// +/// Sets whether the lookup is enabled. +/// +/// Flag indicating if the lookup is enabled. +void PeerListLookup::setEnabled(bool enabled) +{ + std::lock_guard lock(m_mutex); + m_enabled = enabled; +} + +/// +/// Finds a table entry in this lookup table. +/// +/// Unique identifier for table entry. +/// Table entry. +uint32_t PeerListLookup::find(uint32_t id) +{ + std::lock_guard lock(m_mutex); + if (isPeerInList(id)) { + return id; + } else { + return 0; + } +} + +// --------------------------------------------------------------------------- +// Private Class Members +// --------------------------------------------------------------------------- + +/// +/// Loads the table from the passed lookup table file. +/// +/// True, if lookup table was loaded, otherwise false. +bool PeerListLookup::load() +{ + if (m_filename.empty()) { + LogError(LOG_NET, "List file is empty"); + return false; + } + + std::ifstream file(m_filename, std::ifstream::in); + if (file.fail()) { + LogError("Cannot open the white/blacklist file: %s", m_filename.c_str()); + return false; + } + + m_list.clear(); + std::lock_guard lock(m_mutex); + + std::string line; + while (std::getline(file, line)) { + if (line.length() > 0) { + if (line.at(0) == '#') { + continue; + } + + uint32_t peerId = ::strtoul(line.c_str(), nullptr, 10); + if (peerId != 0) { + m_list.push_back(peerId); + LogDebug(LOG_HOST, "Loaded peer ID %u into list from file %s", peerId, m_filename.c_str()); + } + } + } + + file.close(); + + LogInfoEx(LOG_HOST, "Loaded %lu peers into list", m_list.size()); + return !m_list.empty(); +} + +/// +/// Saves the table to the passed lookup table file. +/// +/// True, if lookup table was saved, otherwise false. +bool PeerListLookup::save() +{ + if (m_filename.empty()) { + LogError(LOG_NET, "List file is empty"); + return false; + } + + std::ofstream file(m_filename, std::ofstream::out); + if (file.fail()) { + LogError("Cannot open the file: %s", m_filename.c_str()); + return false; + } + + std::lock_guard lock(m_mutex); + + for (auto& peerId : m_list) { + file << peerId << "\n"; + } + + file.close(); + + LogInfoEx(LOG_HOST, "Saved %lu peers to list", m_list.size()); + return true; +} \ No newline at end of file diff --git a/src/common/lookups/PeerListLookup.h b/src/common/lookups/PeerListLookup.h new file mode 100644 index 00000000..f13461cf --- /dev/null +++ b/src/common/lookups/PeerListLookup.h @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: GPL-2.0-only +/** +* Digital Voice Modem - Common Library +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / Common Library +* @derivedfrom MMDVMHost (https://github.com/g4klx/MMDVMHost) +* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) +* +* Copyright (C) 2016 Jonathan Naylor, G4KLX +* Copyright (C) 2017-2022 Bryan Biedenkapp, N2PLL +* Copyright (c) 2024 Patrick McDonnell, W3AXL +* Copyright (c) 2024 Caleb, KO4UYJ +* +*/ +#if !defined(__PEER_LIST_LOOKUP_H__) +#define __PEER_LIST_LOOKUP_H__ + +#include "common/Defines.h" +#include "common/lookups/LookupTable.h" + +#include +#include +#include + +namespace lookups +{ + // --------------------------------------------------------------------------- + // Class Declaration + // Implements a threading lookup table class that contains peer whitelist + // and blacklist. + // --------------------------------------------------------------------------- + + class HOST_SW_API PeerListLookup : public LookupTable { + public: + enum Mode { + WHITELIST, + BLACKLIST + }; + + /// Initializes a new instance of the PeerListLookup class. + PeerListLookup(const std::string& listFile, Mode mode, uint32_t reloadTime, bool enabled); + + /// Get the list of peers in the table. + std::vector getPeerList() const; + + /// Clears all entries from the list. + void clear() override; + + /// Adds a new entry to the list. + void addEntry(uint32_t peerId); + + /// Removes an existing entry from the list. + void removeEntry(uint32_t peerId); + + /// Checks if a peer ID is in the list. + bool isPeerInList(uint32_t peerId) const; + + /// Checks if a peer ID is allowed based on the mode and enabled flag. + bool isPeerAllowed(uint32_t peerId) const; + + /// Commit the table. + void commit(); + + /// Sets the mode to either WHITELIST or BLACKLIST. + void setMode(Mode mode); + + /// Gets the current mode. + Mode getMode() const; + + /// Sets whether the lookup is enabled. + void setEnabled(bool enabled); + + /// Finds a table entry in this lookup table. + uint32_t find(uint32_t id) override; + + protected: + bool load() override; + bool save() override; + + private: + std::string m_listFile; + Mode m_mode; + bool m_enabled; + std::vector m_list; + static std::mutex m_mutex; + + bool loadList(); + bool saveList() const; + }; +} // namespace lookups + +#endif // __PEER_LIST_LOOKUP_H__ \ No newline at end of file diff --git a/src/fne/HostFNE.cpp b/src/fne/HostFNE.cpp index ba3ddd28..cd820f8c 100644 --- a/src/fne/HostFNE.cpp +++ b/src/fne/HostFNE.cpp @@ -57,6 +57,7 @@ HostFNE::HostFNE(const std::string& confFile) : m_nxdnEnabled(false), m_ridLookup(nullptr), m_tidLookup(nullptr), + m_peerListLookup(nullptr), m_peerNetworks(), m_pingTime(5U), m_maxMissedPings(5U), @@ -283,11 +284,17 @@ int HostFNE::run() m_tidLookup->stop(); delete m_tidLookup; } + if (m_ridLookup != nullptr) { m_ridLookup->stop(); delete m_ridLookup; } + if (m_peerListLookup != nullptr) { + m_peerListLookup->stop(); + delete m_peerListLookup; + } + return EXIT_SUCCESS; } @@ -340,6 +347,18 @@ bool HostFNE::readParams() std::string talkgroupConfig = talkgroupRules["file"].as(); uint32_t talkgroupConfigReload = talkgroupRules["time"].as(30U); + std::string peerListLookupFile = systemConf["peer_acl"]["file"].as(); + bool peerListLookupEnable = systemConf["peer_acl"]["enabled"].as(); + std::string peerListModeStr = systemConf["peer_acl"]["mode"].as("whitelist"); + uint32_t peerListConfigReload = systemConf["peer_acl"]["time"].as(30U); + + lookups::PeerListLookup::Mode peerListMode; + if (peerListModeStr == "blacklist") { + peerListMode = lookups::PeerListLookup::BLACKLIST; + } else { + peerListMode = lookups::PeerListLookup::WHITELIST; + } + LogInfo("Talkgroup Rule Lookups"); LogInfo(" File: %s", talkgroupConfig.length() > 0U ? talkgroupConfig.c_str() : "None"); if (talkgroupConfigReload > 0U) @@ -349,6 +368,17 @@ bool HostFNE::readParams() m_tidLookup->sendTalkgroups(sendTalkgroups); m_tidLookup->read(); + // try to load peer whitelist/blacklist + LogInfo("Peer List Lookups"); + LogInfo(" Enabled: %s", peerListLookupEnable ? "Yes" : "No"); + LogInfo(" Mode: %s", peerListMode == lookups::PeerListLookup::BLACKLIST ? "Blacklist" : "Whitelist"); + LogInfo(" File: %s", peerListLookupFile.length() > 0U ? peerListLookupFile.c_str() : "None"); + if (peerListConfigReload > 0U) + LogInfo(" Reload: %u mins", peerListConfigReload); + + m_peerListLookup = new PeerListLookup(peerListLookupFile, peerListMode, peerListConfigReload, peerListLookupEnable); + m_peerListLookup->read(); + return true; } @@ -414,7 +444,7 @@ bool HostFNE::initializeRESTAPI() // initialize network remote command if (restApiEnable) { m_RESTAPI = new RESTAPI(restApiAddress, restApiPort, restApiPassword, restApiSSLKey, restApiSSLCert, restApiEnableSSL, this, restApiDebug); - m_RESTAPI->setLookups(m_ridLookup, m_tidLookup); + m_RESTAPI->setLookups(m_ridLookup, m_tidLookup, m_peerListLookup); bool ret = m_RESTAPI->open(); if (!ret) { delete m_RESTAPI; @@ -521,7 +551,7 @@ bool HostFNE::createMasterNetwork() parrotDelay, parrotGrantDemand, m_allowActivityTransfer, m_allowDiagnosticTransfer, m_pingTime, m_updateLookupTime); m_network->setOptions(masterConf, true); - m_network->setLookups(m_ridLookup, m_tidLookup); + m_network->setLookups(m_ridLookup, m_tidLookup, m_peerListLookup); if (m_RESTAPI != nullptr) { m_RESTAPI->setNetwork(m_network); diff --git a/src/fne/HostFNE.h b/src/fne/HostFNE.h index a7e8ec29..bb690dfe 100644 --- a/src/fne/HostFNE.h +++ b/src/fne/HostFNE.h @@ -16,6 +16,7 @@ #include "Defines.h" #include "common/lookups/RadioIdLookup.h" #include "common/lookups/TalkgroupRulesLookup.h" +#include "common/lookups/PeerListLookup.h" #include "common/yaml/Yaml.h" #include "common/Timer.h" #include "network/FNENetwork.h" @@ -67,6 +68,7 @@ private: lookups::RadioIdLookup* m_ridLookup; lookups::TalkgroupRulesLookup* m_tidLookup; + lookups::PeerListLookup* m_peerListLookup; std::unordered_map m_peerNetworks; diff --git a/src/fne/network/FNENetwork.cpp b/src/fne/network/FNENetwork.cpp index bdf9fb36..0fe19c45 100644 --- a/src/fne/network/FNENetwork.cpp +++ b/src/fne/network/FNENetwork.cpp @@ -87,6 +87,7 @@ FNENetwork::FNENetwork(HostFNE* host, const std::string& address, uint16_t port, m_parrotOnlyOriginating(false), m_ridLookup(nullptr), m_tidLookup(nullptr), + m_peerListLookup(nullptr), m_status(NET_STAT_INVALID), m_peers(), m_peerAffiliations(), @@ -207,14 +208,15 @@ void FNENetwork::setOptions(yaml::Node& conf, bool printOptions) } /// -/// Sets the instances of the Radio ID and Talkgroup Rules lookup tables. +/// Sets the instances of the Radio ID, Talkgroup Rules, and Peer List lookup tables. /// /// Radio ID Lookup Table Instance /// Talkgroup Rules Lookup Table Instance -void FNENetwork::setLookups(lookups::RadioIdLookup* ridLookup, lookups::TalkgroupRulesLookup* tidLookup) +void FNENetwork::setLookups(lookups::RadioIdLookup* ridLookup, lookups::TalkgroupRulesLookup* tidLookup, lookups::PeerListLookup* peerListLookup) { m_ridLookup = ridLookup; m_tidLookup = tidLookup; + m_peerListLookup = peerListLookup; } /// @@ -646,6 +648,16 @@ void* FNENetwork::threadedNetworkRx(void* arg) } } + // check if the peer is (not)whitelisted or blacklisted + if (!network->m_peerListLookup->isPeerAllowed(peerId)) { + if (network->m_peerListLookup->getMode() == lookups::PeerListLookup::BLACKLIST) { + LogWarning(LOG_NET, "PEER %u is blacklisted", peerId); + } else { + LogWarning(LOG_NET, "PEER %u is not whitelisted", peerId); + } + valid = false; + } + if (valid) { connection->connectionState(NET_STAT_WAITING_CONFIG); network->writePeerACK(peerId); diff --git a/src/fne/network/FNENetwork.h b/src/fne/network/FNENetwork.h index 2f4e8e1e..05ae37ca 100644 --- a/src/fne/network/FNENetwork.h +++ b/src/fne/network/FNENetwork.h @@ -19,6 +19,7 @@ #include "common/lookups/AffiliationLookup.h" #include "common/lookups/RadioIdLookup.h" #include "common/lookups/TalkgroupRulesLookup.h" +#include "common/lookups/PeerListLookup.h" #include "fne/network/influxdb/InfluxDB.h" #include "host/network/Network.h" @@ -242,7 +243,7 @@ namespace network fne::TagNXDNData* nxdnTrafficHandler() const { return m_tagNXDN; } /// Sets the instances of the Radio ID and Talkgroup Rules lookup tables. - void setLookups(lookups::RadioIdLookup* ridLookup, lookups::TalkgroupRulesLookup* tidLookup); + void setLookups(lookups::RadioIdLookup* ridLookup, lookups::TalkgroupRulesLookup* tidLookup, lookups::PeerListLookup* peerListLookup); /// Sets endpoint preshared encryption key. void setPresharedKey(const uint8_t* presharedKey); @@ -286,6 +287,7 @@ namespace network lookups::RadioIdLookup* m_ridLookup; lookups::TalkgroupRulesLookup* m_tidLookup; + lookups::PeerListLookup* m_peerListLookup; NET_CONN_STATUS m_status; diff --git a/src/fne/network/RESTAPI.cpp b/src/fne/network/RESTAPI.cpp index 5378c1ff..a046a1b6 100644 --- a/src/fne/network/RESTAPI.cpp +++ b/src/fne/network/RESTAPI.cpp @@ -435,6 +435,7 @@ RESTAPI::RESTAPI(const std::string& address, uint16_t port, const std::string& p m_network(nullptr), m_ridLookup(nullptr), m_tidLookup(nullptr), + m_peerListLookup(nullptr), m_authTokens() { assert(!address.empty()); @@ -483,10 +484,11 @@ RESTAPI::~RESTAPI() = default; /// /// Radio ID Lookup Table Instance /// Talkgroup Rules Lookup Table Instance -void RESTAPI::setLookups(lookups::RadioIdLookup* ridLookup, lookups::TalkgroupRulesLookup* tidLookup) +void RESTAPI::setLookups(lookups::RadioIdLookup* ridLookup, lookups::TalkgroupRulesLookup* tidLookup, ::lookups::PeerListLookup* peerListLookup) { m_ridLookup = ridLookup; m_tidLookup = tidLookup; + m_peerListLookup = peerListLookup; } /// @@ -580,6 +582,11 @@ void RESTAPI::initializeEndpoints() m_dispatcher.match(FNE_PUT_TGID_DELETE).put(REST_API_BIND(RESTAPI::restAPI_PutTGDelete, this)); m_dispatcher.match(FNE_GET_TGID_COMMIT).get(REST_API_BIND(RESTAPI::restAPI_GetTGCommit, this)); + m_dispatcher.match(FNE_GET_PEER_LIST).get(REST_API_BIND(RESTAPI::restAPI_GetPeerList, this)); + m_dispatcher.match(FNE_PUT_PEER_ADD).put(REST_API_BIND(RESTAPI::restAPI_PutPeerAdd, this)); + m_dispatcher.match(FNE_PUT_PEER_DELETE).put(REST_API_BIND(RESTAPI::restAPI_PutPeerDelete, this)); + m_dispatcher.match(FNE_GET_PEER_COMMIT).get(REST_API_BIND(RESTAPI::restAPI_GetPeerCommit, this)); + m_dispatcher.match(FNE_GET_FORCE_UPDATE).get(REST_API_BIND(RESTAPI::restAPI_GetForceUpdate, this)); m_dispatcher.match(FNE_GET_RELOAD_TGS).get(REST_API_BIND(RESTAPI::restAPI_GetReloadTGs, this)); @@ -1160,6 +1167,112 @@ void RESTAPI::restAPI_GetTGCommit(const HTTPPayload& request, HTTPPayload& reply reply.payload(response); } +/// +/// +/// +/// +/// +/// +void RESTAPI::restAPI_GetPeerList(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match) +{ + if (!validateAuth(request, reply)) { + return; + } + + json::object response = json::object(); + setResponseDefaultStatus(response); + + json::array peers = json::array(); + if (m_peerListLookup != nullptr) { + for (const auto& peerId : m_peerListLookup->getPeerList()) { + json::object peerObj = json::object(); + peerObj["peerId"].set(peerId); + peers.push_back(json::value(peerObj)); + } + } + + response["peers"].set(peers); + reply.payload(response); +} + +/// +/// +/// +/// +/// +/// +void RESTAPI::restAPI_PutPeerAdd(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match) +{ + if (!validateAuth(request, reply)) { + return; + } + + json::object req = json::object(); + if (!parseRequestBody(request, reply, req)) { + return; + } + + errorPayload(reply, "OK", HTTPPayload::OK); + + if (!req["peerId"].is()) { + errorPayload(reply, "peerId was not a valid integer"); + return; + } + + uint32_t peerId = req["peerId"].get(); + + m_peerListLookup->addEntry(peerId); +} + +/// +/// +/// +/// +/// +/// +void RESTAPI::restAPI_PutPeerDelete(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match) +{ + if (!validateAuth(request, reply)) { + return; + } + + json::object req = json::object(); + if (!parseRequestBody(request, reply, req)) { + return; + } + + errorPayload(reply, "OK", HTTPPayload::OK); + + if (!req["peerId"].is()) { + errorPayload(reply, "peerId was not a valid integer"); + return; + } + + uint32_t peerId = req["peerId"].get(); + + m_peerListLookup->removeEntry(peerId); +} + +/// +/// +/// +/// +/// +/// +void RESTAPI::restAPI_GetPeerCommit(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match) +{ + if (!validateAuth(request, reply)) { + return; + } + + json::object response = json::object(); + setResponseDefaultStatus(response); + + m_peerListLookup->commit(); + + reply.payload(response); +} + /// /// /// diff --git a/src/fne/network/RESTAPI.h b/src/fne/network/RESTAPI.h index db8c8bd9..4729edb1 100644 --- a/src/fne/network/RESTAPI.h +++ b/src/fne/network/RESTAPI.h @@ -47,7 +47,7 @@ public: ~RESTAPI() override; /// Sets the instances of the Radio ID and Talkgroup ID lookup tables. - void setLookups(::lookups::RadioIdLookup* ridLookup, ::lookups::TalkgroupRulesLookup* tidLookup); + void setLookups(::lookups::RadioIdLookup* ridLookup, ::lookups::TalkgroupRulesLookup* tidLookup, ::lookups::PeerListLookup* peerListLookup); /// Sets the instance of the FNE network. void setNetwork(::network::FNENetwork* network); @@ -78,6 +78,7 @@ private: ::lookups::RadioIdLookup* m_ridLookup; ::lookups::TalkgroupRulesLookup* m_tidLookup; + ::lookups::PeerListLookup* m_peerListLookup; typedef std::unordered_map::value_type AuthTokenValueType; std::unordered_map m_authTokens; @@ -124,6 +125,15 @@ private: /// void restAPI_GetTGCommit(const HTTPPayload& request, HTTPPayload& reply, const network::rest::RequestMatch& match); + /// + void restAPI_GetPeerList(const HTTPPayload& request, HTTPPayload& reply, const network::rest::RequestMatch& match); + /// + void restAPI_PutPeerAdd(const HTTPPayload& request, HTTPPayload& reply, const network::rest::RequestMatch& match); + /// + void restAPI_PutPeerDelete(const HTTPPayload& request, HTTPPayload& reply, const network::rest::RequestMatch& match); + /// + void restAPI_GetPeerCommit(const HTTPPayload& request, HTTPPayload& reply, const network::rest::RequestMatch& match); + /// void restAPI_GetForceUpdate(const HTTPPayload& request, HTTPPayload& reply, const network::rest::RequestMatch& match); diff --git a/src/fne/network/RESTDefines.h b/src/fne/network/RESTDefines.h index 0c851a77..51696957 100644 --- a/src/fne/network/RESTDefines.h +++ b/src/fne/network/RESTDefines.h @@ -33,6 +33,11 @@ #define FNE_PUT_TGID_DELETE "/tg/delete" #define FNE_GET_TGID_COMMIT "/tg/commit" +#define FNE_GET_PEER_LIST "/peer/list" +#define FNE_PUT_PEER_ADD "/peer/add" +#define FNE_PUT_PEER_DELETE "/peer/delete" +#define FNE_GET_PEER_COMMIT "/peer/commit" + #define FNE_GET_FORCE_UPDATE "/force-update" #define FNE_GET_RELOAD_TGS "/reload-tgs"