From 6b18089d7582af4b16c5058ddc9c03369da77455 Mon Sep 17 00:00:00 2001 From: Bryan Biedenkapp Date: Tue, 9 Jan 2024 23:12:42 -0500 Subject: [PATCH] implement REST API stub for conference bridge FNE; --- configs/fne-config.example.yml | 11 + src/fne/HostFNE.cpp | 85 +++++- src/fne/HostFNE.h | 6 + src/fne/network/FNENetwork.cpp | 2 +- src/fne/network/FNENetwork.h | 2 +- src/fne/network/RESTAPI.cpp | 396 ++++++++++++++++++++++++++++ src/fne/network/RESTAPI.h | 107 ++++++++ src/fne/network/RESTDefines.h | 41 +++ src/fne/network/fne/TagDMRData.cpp | 2 +- src/fne/network/fne/TagDMRData.h | 2 +- src/fne/network/fne/TagNXDNData.cpp | 2 +- src/fne/network/fne/TagNXDNData.h | 2 +- src/fne/network/fne/TagP25Data.cpp | 2 +- src/fne/network/fne/TagP25Data.h | 2 +- src/host/network/RESTAPI.cpp | 4 - 15 files changed, 653 insertions(+), 13 deletions(-) create mode 100644 src/fne/network/RESTAPI.cpp create mode 100644 src/fne/network/RESTAPI.h create mode 100644 src/fne/network/RESTDefines.h diff --git a/configs/fne-config.example.yml b/configs/fne-config.example.yml index 36bb572f..0b7e7220 100644 --- a/configs/fne-config.example.yml +++ b/configs/fne-config.example.yml @@ -123,6 +123,17 @@ system: # Flag indicating whether or not the host diagnostic log will be sent to the network. allowDiagnosticTransfer: true + # Flag indicating whether or not REST API is enabled. + restEnable: false + # IP address of the network interface to listen for REST API on (or 0.0.0.0 for all). + restAddress: 127.0.0.1 + # Port number for REST API to listen on. + restPort: 9990 + # REST API authentication password. + restPassword: "PASSWORD" + # Flag indicating whether or not verbose REST API debug logging is enabled. + restDebug: false + # # Radio ID ACL Configuration # diff --git a/src/fne/HostFNE.cpp b/src/fne/HostFNE.cpp index 891000bc..663c73a8 100644 --- a/src/fne/HostFNE.cpp +++ b/src/fne/HostFNE.cpp @@ -78,7 +78,8 @@ HostFNE::HostFNE(const std::string& confFile) : m_maxMissedPings(5U), m_updateLookupTime(10U), m_allowActivityTransfer(false), - m_allowDiagnosticTransfer(false) + m_allowDiagnosticTransfer(false), + m_RESTAPI(nullptr) { /* stub */ } @@ -177,6 +178,9 @@ int HostFNE::run() m_ridLookup = new RadioIdLookup(ridLookupFile, ridReloadTime, true); m_ridLookup->read(); + // initialize REST API + initializeRESTAPI(); + // initialize master networking ret = createMasterNetwork(); if (!ret) @@ -234,6 +238,11 @@ int HostFNE::run() } m_peerNetworks.clear(); + if (m_RESTAPI != nullptr) { + m_RESTAPI->close(); + delete m_RESTAPI; + } + if (m_tidLookup != nullptr) { m_tidLookup->stop(); delete m_tidLookup; @@ -253,6 +262,7 @@ int HostFNE::run() /// /// Reads basic configuration parameters from the YAML configuration file. /// +/// bool HostFNE::readParams() { yaml::Node systemConf = m_conf["system"]; @@ -304,9 +314,71 @@ bool HostFNE::readParams() return true; } +/// +/// Initializes REST API serivces. +/// +/// +bool HostFNE::initializeRESTAPI() +{ + yaml::Node systemConf = m_conf["system"]; + bool restApiEnable = systemConf["restEnable"].as(false); + + // dump out if both networking and REST API are disabled + if (!restApiEnable) { + return true; + } + + std::string restApiAddress = systemConf["restAddress"].as("127.0.0.1"); + uint16_t restApiPort = (uint16_t)systemConf["restPort"].as(REST_API_DEFAULT_PORT); + std::string restApiPassword = systemConf["restPassword"].as(); + bool restApiDebug = systemConf["restDebug"].as(false); + + if (restApiPassword.length() > 64) { + std::string password = restApiPassword; + restApiPassword = password.substr(0, 64); + + ::LogWarning(LOG_HOST, "REST API password is too long; truncating to the first 64 characters."); + } + + if (restApiPassword.empty() && restApiEnable) { + ::LogWarning(LOG_HOST, "REST API password not provided; REST API disabled."); + restApiEnable = false; + } + + LogInfo("REST API Parameters"); + LogInfo(" REST API Enabled: %s", restApiEnable ? "yes" : "no"); + if (restApiEnable) { + LogInfo(" REST API Address: %s", restApiAddress.c_str()); + LogInfo(" REST API Port: %u", restApiPort); + + if (restApiDebug) { + LogInfo(" REST API Debug: yes"); + } + } + + // initialize network remote command + if (restApiEnable) { + m_RESTAPI = new RESTAPI(restApiAddress, restApiPort, restApiPassword, this, restApiDebug); + m_RESTAPI->setLookups(m_ridLookup, m_tidLookup); + bool ret = m_RESTAPI->open(); + if (!ret) { + delete m_RESTAPI; + m_RESTAPI = nullptr; + LogError(LOG_HOST, "failed to initialize REST API networking! REST API will be unavailable!"); + // REST API failing isn't fatal -- we'll allow this to return normally + } + } + else { + m_RESTAPI = nullptr; + } + + return true; +} + /// /// Initializes master FNE network connectivity. /// +/// bool HostFNE::createMasterNetwork() { yaml::Node masterConf = m_conf["master"]; @@ -317,6 +389,11 @@ bool HostFNE::createMasterNetwork() bool verbose = masterConf["verbose"].as(false); bool debug = masterConf["debug"].as(false); + if (id > 999999999U) { + ::LogError(LOG_HOST, "Network Peer ID cannot be greater then 999999999."); + return false; + } + m_dmrEnabled = masterConf["allowDMRTraffic"].as(true); m_p25Enabled = masterConf["allowP25Traffic"].as(true); m_nxdnEnabled = masterConf["allowNXDNTraffic"].as(true); @@ -366,6 +443,7 @@ bool HostFNE::createMasterNetwork() /// /// Initializes peer FNE network connectivity. /// +/// bool HostFNE::createPeerNetworks() { yaml::Node& peerList = m_conf["peers"]; @@ -389,6 +467,11 @@ bool HostFNE::createPeerNetworks() ::LogInfoEx(LOG_HOST, "Peer ID %u Master Address %s Master Port %u Identity %s Enabled %u", id, masterAddress.c_str(), masterPort, identity.c_str(), enabled); + if (id > 999999999U) { + ::LogError(LOG_HOST, "Network Peer ID cannot be greater then 999999999."); + continue; + } + // initialize networking network::Network* network = new Network(masterAddress, masterPort, 0U, id, password, true, debug, m_dmrEnabled, m_p25Enabled, m_nxdnEnabled, true, true, m_allowActivityTransfer, m_allowDiagnosticTransfer, false); network->setMetadata(identity, rxFrequency, txFrequency, 0.0F, 0.0F, 0, 0, 0, latitude, longitude, 0, location); diff --git a/src/fne/HostFNE.h b/src/fne/HostFNE.h index 0a6e86f8..755623dd 100644 --- a/src/fne/HostFNE.h +++ b/src/fne/HostFNE.h @@ -32,6 +32,7 @@ #include "common/yaml/Yaml.h" #include "common/Timer.h" #include "network/FNENetwork.h" +#include "network/RESTAPI.h" #include "host/network/Network.h" #include @@ -87,8 +88,13 @@ private: bool m_allowActivityTransfer; bool m_allowDiagnosticTransfer; + friend class RESTAPI; + RESTAPI* m_RESTAPI; + /// Reads basic configuration parameters from the INI. bool readParams(); + /// Initializes REST API serivces. + bool initializeRESTAPI(); /// Initializes master FNE network connectivity. bool createMasterNetwork(); /// Initializes peer FNE network connectivity. diff --git a/src/fne/network/FNENetwork.cpp b/src/fne/network/FNENetwork.cpp index 1092fc84..3f02dfad 100644 --- a/src/fne/network/FNENetwork.cpp +++ b/src/fne/network/FNENetwork.cpp @@ -23,7 +23,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "Defines.h" +#include "fne/Defines.h" #include "common/edac/SHA256.h" #include "common/network/json/json.h" #include "common/Log.h" diff --git a/src/fne/network/FNENetwork.h b/src/fne/network/FNENetwork.h index 24628d4d..056f9a37 100644 --- a/src/fne/network/FNENetwork.h +++ b/src/fne/network/FNENetwork.h @@ -26,7 +26,7 @@ #if !defined(__FNE_NETWORK_H__) #define __FNE_NETWORK_H__ -#include "Defines.h" +#include "fne/Defines.h" #include "common/network/BaseNetwork.h" #include "common/network/json/json.h" #include "common/lookups/RadioIdLookup.h" diff --git a/src/fne/network/RESTAPI.cpp b/src/fne/network/RESTAPI.cpp new file mode 100644 index 00000000..e3da6fb8 --- /dev/null +++ b/src/fne/network/RESTAPI.cpp @@ -0,0 +1,396 @@ +/** +* Digital Voice Modem - Conference FNE Software +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / Conference FNE Software +* +*/ +/* +* Copyright (C) 2024 by Bryan Biedenkapp N2PLL +* +* 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 "fne/Defines.h" +#include "common/edac/SHA256.h" +#include "common/lookups/AffiliationLookup.h" +#include "common/network/json/json.h" +#include "common/Log.h" +#include "common/Thread.h" +#include "common/Utils.h" +#include "fne/network/RESTAPI.h" +#include "HostFNE.h" +#include "FNEMain.h" + +using namespace network; +using namespace network::rest; +using namespace network::rest::http; + +#include +#include +#include +#include + +#include +#include +#include + +// --------------------------------------------------------------------------- +// Macros +// --------------------------------------------------------------------------- + +#define REST_API_BIND(funcAddr, classInstance) std::bind(&funcAddr, classInstance, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3) + +// --------------------------------------------------------------------------- +// Global Functions +// --------------------------------------------------------------------------- + +template +std::string string_format(const std::string& format, FormatArgs ... args) +{ + int size_s = std::snprintf(nullptr, 0, format.c_str(), args ...) + 1; // extra space for '\0' + if (size_s <= 0) + throw std::runtime_error("Error during string formatting."); + + auto size = static_cast(size_s); + std::unique_ptr buf(new char[ size ]); + std::snprintf(buf.get(), size, format.c_str(), args ...); + + return std::string(buf.get(), buf.get() + size - 1); +} + +/// +/// +/// +/// +void setResponseDefaultStatus(json::object& obj) +{ + int s = (int)HTTPPayload::OK; + obj["status"].set(s); +} + +/// +/// +/// +/// +/// +/// +void errorPayload(HTTPPayload& reply, std::string message, HTTPPayload::StatusType status = HTTPPayload::BAD_REQUEST) +{ + HTTPPayload rep; + rep.status = status; + + json::object response = json::object(); + + int s = (int)rep.status; + response["status"].set(s); + response["message"].set(message); + + reply.payload(response); +} + +/// +/// +/// +/// +/// +/// +/// +bool parseRequestBody(const HTTPPayload& request, HTTPPayload& reply, json::object& obj) +{ + std::string contentType = request.headers.find("Content-Type"); + if (contentType != "application/json") { + reply = HTTPPayload::statusPayload(HTTPPayload::BAD_REQUEST, "application/json"); + return false; + } + + // parse JSON body + json::value v; + std::string err = json::parse(v, request.content); + if (!err.empty()) { + errorPayload(reply, err); + return false; + } + + // ensure parsed JSON is an object + if (!v.is()) { + errorPayload(reply, "Request was not a valid JSON object."); + return false; + } + + obj = v.get(); + return true; +} + +// --------------------------------------------------------------------------- +// Public Class Members +// --------------------------------------------------------------------------- + +/// +/// Initializes a new instance of the RESTAPI class. +/// +/// Network Hostname/IP address to connect to. +/// Network port number. +/// Authentication password. +/// Instance of the Host class. +/// +RESTAPI::RESTAPI(const std::string& address, uint16_t port, const std::string& password, HostFNE* host, bool debug) : + m_dispatcher(debug), + m_restServer(address, port), + m_random(), + m_password(password), + m_passwordHash(nullptr), + m_debug(debug), + m_host(host), + m_ridLookup(nullptr), + m_tidLookup(nullptr), + m_authTokens() +{ + assert(!address.empty()); + assert(port > 0U); + assert(!password.empty()); + + size_t size = password.size(); + + uint8_t* in = new uint8_t[size]; + for (size_t i = 0U; i < size; i++) + in[i] = password.at(i); + + m_passwordHash = new uint8_t[32U]; + ::memset(m_passwordHash, 0x00U, 32U); + + edac::SHA256 sha256; + sha256.buffer(in, (uint32_t)(size), m_passwordHash); + + delete[] in; + + if (m_debug) { + Utils::dump("REST Password Hash", m_passwordHash, 32U); + } + + std::random_device rd; + std::mt19937 mt(rd()); + m_random = mt; +} + +/// +/// Finalizes a instance of the RESTAPI class. +/// +RESTAPI::~RESTAPI() +{ + /* stub */ +} + +/// +/// Sets the instances of the Radio ID and Talkgroup ID lookup tables. +/// +/// Radio ID Lookup Table Instance +/// Talkgroup Rules Lookup Table Instance +void RESTAPI::setLookups(lookups::RadioIdLookup* ridLookup, lookups::TalkgroupRulesLookup* tidLookup) +{ + m_ridLookup = ridLookup; + m_tidLookup = tidLookup; +} + +/// +/// Opens connection to the network. +/// +/// +bool RESTAPI::open() +{ + initializeEndpoints(); + m_restServer.setHandler(m_dispatcher); + + return run(); +} + +/// +/// Closes connection to the network. +/// +void RESTAPI::close() +{ + m_restServer.stop(); + wait(); +} + +// --------------------------------------------------------------------------- +// Private Class Members +// --------------------------------------------------------------------------- + +/// +/// +/// +void RESTAPI::entry() +{ + m_restServer.run(); +} + +/// +/// Helper to initialize REST API endpoints. +/// +void RESTAPI::initializeEndpoints() +{ + m_dispatcher.match(PUT_AUTHENTICATE).put(REST_API_BIND(RESTAPI::restAPI_PutAuth, this)); + + m_dispatcher.match(GET_VERSION).get(REST_API_BIND(RESTAPI::restAPI_GetVersion, this)); +} + +/// +/// +/// +/// +void RESTAPI::invalidateHostToken(const std::string host) +{ + auto token = std::find_if(m_authTokens.begin(), m_authTokens.end(), [&](const AuthTokenValueType& tok) { return tok.first == host; }); + if (token != m_authTokens.end()) { + m_authTokens.erase(host); + } +} + +/// +/// +/// +/// +bool RESTAPI::validateAuth(const HTTPPayload& request, HTTPPayload& reply) +{ + std::string host = request.headers.find("RemoteHost"); + std::string headerToken = request.headers.find("X-DVM-Auth-Token"); +#if DEBUG_HTTP_PAYLOAD + ::LogDebug(LOG_REST, "RESTAPI::validateAuth() token, host = %s, token = %s", host.c_str(), headerToken.c_str()); +#endif + if (headerToken == "") { + errorPayload(reply, "no authentication token", HTTPPayload::UNAUTHORIZED); + return false; + } + + for (auto& token : m_authTokens) { +#if DEBUG_HTTP_PAYLOAD + ::LogDebug(LOG_REST, "RESTAPI::validateAuth() valid list, host = %s, token = %s", token.first.c_str(), std::to_string(token.second).c_str()); +#endif + if (token.first.compare(host) == 0) { +#if DEBUG_HTTP_PAYLOAD + ::LogDebug(LOG_REST, "RESTAPI::validateAuth() storedToken = %s, passedToken = %s", std::to_string(token.second).c_str(), headerToken.c_str()); +#endif + if (std::to_string(token.second).compare(headerToken) == 0) { + return true; + } else { + m_authTokens.erase(host); // devalidate host + errorPayload(reply, "invalid authentication token", HTTPPayload::UNAUTHORIZED); + return false; + } + } + } + + errorPayload(reply, "illegal authentication token", HTTPPayload::UNAUTHORIZED); + return false; +} + +/// +/// +/// +/// +/// +/// +void RESTAPI::restAPI_PutAuth(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match) +{ + std::string host = request.headers.find("RemoteHost"); + json::object response = json::object(); + setResponseDefaultStatus(response); + + json::object req = json::object(); + if (!parseRequestBody(request, reply, req)) { + return; + } + + // validate auth is a string within the JSON blob + if (!req["auth"].is()) { + invalidateHostToken(host); + errorPayload(reply, "password was not a valid string"); + return; + } + + std::string auth = req["auth"].get(); + if (auth.empty()) { + invalidateHostToken(host); + errorPayload(reply, "auth cannot be empty"); + return; + } + + if (auth.size() > 64) { + invalidateHostToken(host); + errorPayload(reply, "auth cannot be longer than 64 characters"); + return; + } + + if (!(auth.find_first_not_of("0123456789abcdefABCDEF", 2) == std::string::npos)) { + invalidateHostToken(host); + errorPayload(reply, "auth contains invalid characters"); + return; + } + + if (m_debug) { + ::LogDebug(LOG_REST, "/auth auth = %s", auth.c_str()); + } + + const char* authPtr = auth.c_str(); + uint8_t* passwordHash = new uint8_t[32U]; + ::memset(passwordHash, 0x00U, 32U); + + for (uint8_t i = 0; i < 32U; i++) { + char t[4] = {authPtr[0], authPtr[1], 0}; + passwordHash[i] = (uint8_t)::strtoul(t, NULL, 16); + authPtr += 2 * sizeof(char); + } + + if (m_debug) { + Utils::dump("Password Hash", passwordHash, 32U); + } + + // compare hashes + if (::memcmp(m_passwordHash, passwordHash, 32U) != 0) { + invalidateHostToken(host); + errorPayload(reply, "invalid password"); + return; + } + + delete[] passwordHash; + + invalidateHostToken(host); + std::uniform_int_distribution dist(DVM_RAND_MIN, DVM_REST_RAND_MAX); + uint64_t salt = dist(m_random); + + m_authTokens[host] = salt; + response["token"].set(std::to_string(salt)); + reply.payload(response); +} + +/// +/// +/// +/// +/// +/// +void RESTAPI::restAPI_GetVersion(const HTTPPayload& request, HTTPPayload& reply, const RequestMatch& match) +{ + if (!validateAuth(request, reply)) { + return; + } + + json::object response = json::object(); + setResponseDefaultStatus(response); + response["version"].set(std::string((__PROG_NAME__ " " __VER__ " (built " __BUILD__ ")"))); + + reply.payload(response); +} diff --git a/src/fne/network/RESTAPI.h b/src/fne/network/RESTAPI.h new file mode 100644 index 00000000..3bedfad2 --- /dev/null +++ b/src/fne/network/RESTAPI.h @@ -0,0 +1,107 @@ +/** +* Digital Voice Modem - Conference FNE Software +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / Conference FNE Software +* +*/ +/* +* Copyright (C) 2024 by Bryan Biedenkapp N2PLL +* +* 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. +*/ +#if !defined(__REST_API_H__) +#define __REST_API_H__ + +#include "fne/Defines.h" +#include "common/network/UDPSocket.h" +#include "common/network/rest/RequestDispatcher.h" +#include "common/network/rest/http/HTTPServer.h" +#include "common/lookups/RadioIdLookup.h" +#include "common/lookups/TalkgroupRulesLookup.h" +#include "common/Thread.h" +#include "fne/network/RESTDefines.h" + +#include +#include +#include + +// --------------------------------------------------------------------------- +// Class Prototypes +// --------------------------------------------------------------------------- + +class HOST_SW_API HostFNE; + +// --------------------------------------------------------------------------- +// Class Declaration +// Implements the REST API server logic. +// --------------------------------------------------------------------------- + +class HOST_SW_API RESTAPI : private Thread { +public: + /// Initializes a new instance of the RESTAPI class. + RESTAPI(const std::string& address, uint16_t port, const std::string& password, HostFNE* host, bool debug); + /// Finalizes a instance of the RESTAPI class. + ~RESTAPI(); + + /// Sets the instances of the Radio ID and Talkgroup ID lookup tables. + void setLookups(::lookups::RadioIdLookup* ridLookup, ::lookups::TalkgroupRulesLookup* tidLookup); + + /// Opens connection to the network. + bool open(); + + /// Closes connection to the network. + void close(); + +private: + typedef network::rest::RequestDispatcher RESTDispatcherType; + typedef network::rest::http::HTTPPayload HTTPPayload; + RESTDispatcherType m_dispatcher; + network::rest::http::HTTPServer m_restServer; + + std::mt19937 m_random; + + std::string m_password; + uint8_t* m_passwordHash; + bool m_debug; + + HostFNE* m_host; + + ::lookups::RadioIdLookup* m_ridLookup; + ::lookups::TalkgroupRulesLookup* m_tidLookup; + + typedef std::unordered_map::value_type AuthTokenValueType; + std::unordered_map m_authTokens; + + /// + virtual void entry(); + + /// Helper to initialize REST API endpoints. + void initializeEndpoints(); + + /// + void invalidateHostToken(const std::string host); + /// + bool validateAuth(const HTTPPayload& request, HTTPPayload& reply); + + /// + void restAPI_PutAuth(const HTTPPayload& request, HTTPPayload& reply, const network::rest::RequestMatch& match); + + /// + void restAPI_GetVersion(const HTTPPayload& request, HTTPPayload& reply, const network::rest::RequestMatch& match); +}; + +#endif // __REST_API_H__ diff --git a/src/fne/network/RESTDefines.h b/src/fne/network/RESTDefines.h new file mode 100644 index 00000000..def01b94 --- /dev/null +++ b/src/fne/network/RESTDefines.h @@ -0,0 +1,41 @@ +/** +* Digital Voice Modem - Conference FNE Software +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / Conference FNE Software +* +*/ +/* +* Copyright (C) 2024 by Bryan Biedenkapp N2PLL +* +* 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. +*/ +#if !defined(__REST_DEFINES_H__) +#define __REST_DEFINES_H__ + +#include "fne/Defines.h" + +// --------------------------------------------------------------------------- +// Constants +// --------------------------------------------------------------------------- + +#define DVM_REST_RAND_MAX 0xfffffffffffffffe + +#define PUT_AUTHENTICATE "/auth" + +#define GET_VERSION "/version" + +#endif // __REST_API_H__ diff --git a/src/fne/network/fne/TagDMRData.cpp b/src/fne/network/fne/TagDMRData.cpp index 6eb7eb0c..e36ed882 100644 --- a/src/fne/network/fne/TagDMRData.cpp +++ b/src/fne/network/fne/TagDMRData.cpp @@ -23,7 +23,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "Defines.h" +#include "fne/Defines.h" #include "common/dmr/lc/LC.h" #include "common/dmr/lc/FullLC.h" #include "common/Clock.h" diff --git a/src/fne/network/fne/TagDMRData.h b/src/fne/network/fne/TagDMRData.h index ccf9444e..b2f46625 100644 --- a/src/fne/network/fne/TagDMRData.h +++ b/src/fne/network/fne/TagDMRData.h @@ -26,7 +26,7 @@ #if !defined(__FNE__TAG_DMR_DATA_H__) #define __FNE__TAG_DMR_DATA_H__ -#include "Defines.h" +#include "fne/Defines.h" #include "common/dmr/DMRDefines.h" #include "common/dmr/data/Data.h" #include "common/Clock.h" diff --git a/src/fne/network/fne/TagNXDNData.cpp b/src/fne/network/fne/TagNXDNData.cpp index b5326a73..26c7d658 100644 --- a/src/fne/network/fne/TagNXDNData.cpp +++ b/src/fne/network/fne/TagNXDNData.cpp @@ -23,7 +23,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "Defines.h" +#include "fne/Defines.h" #include "common/nxdn/NXDNDefines.h" #include "common/Clock.h" #include "common/Log.h" diff --git a/src/fne/network/fne/TagNXDNData.h b/src/fne/network/fne/TagNXDNData.h index 53145497..d49723ed 100644 --- a/src/fne/network/fne/TagNXDNData.h +++ b/src/fne/network/fne/TagNXDNData.h @@ -26,7 +26,7 @@ #if !defined(__FNE__TAG_NXDN_DATA_H__) #define __FNE__TAG_NXDN_DATA_H__ -#include "Defines.h" +#include "fne/Defines.h" #include "common/Clock.h" #include "common/nxdn/NXDNDefines.h" #include "common/nxdn/lc/RTCH.h" diff --git a/src/fne/network/fne/TagP25Data.cpp b/src/fne/network/fne/TagP25Data.cpp index 4e9c5d90..82320da9 100644 --- a/src/fne/network/fne/TagP25Data.cpp +++ b/src/fne/network/fne/TagP25Data.cpp @@ -23,7 +23,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "Defines.h" +#include "fne/Defines.h" #include "common/p25/lc/tsbk/TSBKFactory.h" #include "common/p25/Sync.h" #include "common/Clock.h" diff --git a/src/fne/network/fne/TagP25Data.h b/src/fne/network/fne/TagP25Data.h index a7380a29..f6299625 100644 --- a/src/fne/network/fne/TagP25Data.h +++ b/src/fne/network/fne/TagP25Data.h @@ -26,7 +26,7 @@ #if !defined(__FNE__TAG_P25_DATA_H__) #define __FNE__TAG_P25_DATA_H__ -#include "Defines.h" +#include "fne/Defines.h" #include "common/Clock.h" #include "common/p25/P25Defines.h" #include "common/p25/data/DataHeader.h" diff --git a/src/host/network/RESTAPI.cpp b/src/host/network/RESTAPI.cpp index a26c7657..2fb030e5 100644 --- a/src/host/network/RESTAPI.cpp +++ b/src/host/network/RESTAPI.cpp @@ -6,10 +6,6 @@ * @package DVM / Host Software * */ -// -// Based on code from the MMDVMHost project. (https://github.com/g4klx/MMDVMHost) -// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0) -// /* * Copyright (C) 2023 by Bryan Biedenkapp N2PLL *