From b7f55d932364a8c9811d1a0b21f5b61cf53c55f3 Mon Sep 17 00:00:00 2001 From: Bryan Biedenkapp Date: Fri, 8 May 2026 09:15:30 -0400 Subject: [PATCH] couple more code fixes, fix REST API initialization on FNE to prevent early REST calls from crashing the FNE; add locking support for network internals when REST APIs are called; fix memory leak for failed network logins; --- src/common/lookups/AffiliationLookup.cpp | 3 ++- src/fne/HostFNE.cpp | 21 +++++++++------------ src/fne/restapi/RESTAPI.cpp | 11 ++++++++++- src/host/restapi/RESTAPI.cpp | 1 + 4 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/common/lookups/AffiliationLookup.cpp b/src/common/lookups/AffiliationLookup.cpp index e5f29a8a..124382c5 100644 --- a/src/common/lookups/AffiliationLookup.cpp +++ b/src/common/lookups/AffiliationLookup.cpp @@ -108,8 +108,9 @@ bool AffiliationLookup::unitDereg(uint32_t srcId, bool automatic) m_unitRegTable.unlock(); m_unitRegTable.erase(it); ret = true; + } else { + m_unitRegTable.unlock(); } - m_unitRegTable.unlock(); if (ret) { if (m_unitDereg != nullptr) { diff --git a/src/fne/HostFNE.cpp b/src/fne/HostFNE.cpp index 2544de01..cb85d22f 100644 --- a/src/fne/HostFNE.cpp +++ b/src/fne/HostFNE.cpp @@ -186,14 +186,14 @@ int HostFNE::run() m_ridLookup = new RadioIdLookup(ridLookupFile, ridReloadTime, true); m_ridLookup->read(); - // initialize REST API - initializeRESTAPI(); - // initialize master networking ret = createMasterNetwork(); if (!ret) return EXIT_FAILURE; + // initialize REST API + initializeRESTAPI(); + // initialize peer networking ret = createPeerNetworks(); if (!ret) @@ -274,6 +274,11 @@ int HostFNE::run() } // shutdown threads + if (m_RESTAPI != nullptr) { + m_RESTAPI->close(); + delete m_RESTAPI; + } + if (m_network != nullptr) { m_network->close(); delete m_network; @@ -291,11 +296,6 @@ int HostFNE::run() } m_peerNetworks.clear(); - if (m_RESTAPI != nullptr) { - m_RESTAPI->close(); - delete m_RESTAPI; - } - if (m_tidLookup != nullptr) { m_tidLookup->setReloadTime(0U); // no reload m_tidLookup->stop(); @@ -519,6 +519,7 @@ bool HostFNE::initializeRESTAPI() if (restApiEnable) { m_RESTAPI = new RESTAPI(restApiAddress, restApiPort, restApiPassword, restApiSSLKey, restApiSSLCert, restApiEnableSSL, this, restApiDebug); m_RESTAPI->setLookups(m_ridLookup, m_tidLookup, m_peerListLookup, m_adjSiteMapLookup, m_cryptoLookup); + m_RESTAPI->setNetwork(m_network); bool ret = m_RESTAPI->open(); if (!ret) { delete m_RESTAPI; @@ -656,10 +657,6 @@ bool HostFNE::createMasterNetwork() m_network->setLookups(m_ridLookup, m_tidLookup, m_peerListLookup, m_cryptoLookup, m_adjSiteMapLookup); - if (m_RESTAPI != nullptr) { - m_RESTAPI->setNetwork(m_network); - } - bool ret = m_network->open(); if (!ret) { delete m_network; diff --git a/src/fne/restapi/RESTAPI.cpp b/src/fne/restapi/RESTAPI.cpp index 6ab8f166..bf196b53 100644 --- a/src/fne/restapi/RESTAPI.cpp +++ b/src/fne/restapi/RESTAPI.cpp @@ -805,6 +805,7 @@ void RESTAPI::restAPI_PutAuth(const HTTPPayload& request, HTTPPayload& reply, co invalidateHostToken(host); errorPayload(reply, "invalid password"); LogError(LOG_REST, "failed authentication attempt from host %s", host.c_str()); + delete[] passwordHash; return; } @@ -875,18 +876,20 @@ void RESTAPI::restAPI_GetPeerQuery(const HTTPPayload& request, HTTPPayload& repl json::array peers = json::array(); if (m_network != nullptr) { if (m_network->m_peers.size() > 0) { + m_network->m_peers.shared_lock(); for (auto entry : m_network->m_peers) { uint32_t peerId = entry.first; network::FNEPeerConnection* peer = entry.second; if (peer != nullptr) { if (m_debug) { - LogDebug(LOG_REST, "preparing Peer %u (%s) for REST API query", peerId, peer->address().c_str()); + LogDebug(LOG_REST, "preparing PEER %u (%s) for REST API query", peerId, peer->address().c_str()); } json::object peerObj = m_network->fneConnObject(peerId, peer); peers.push_back(json::value(peerObj)); } } + m_network->m_peers.shared_unlock(); } else { LogError(LOG_REST, "peer query failed, no peers connected to this FNE"); @@ -1798,6 +1801,7 @@ void RESTAPI::restAPI_GetStats(const HTTPPayload& request, HTTPPayload& reply, c // peer statistics (right now this is just a list of connected peers) json::array peerStats = json::array(); if (m_network->m_peers.size() > 0) { + m_network->m_peers.shared_lock(); for (auto entry : m_network->m_peers) { uint32_t peerId = entry.first; network::FNEPeerConnection* peer = entry.second; @@ -1847,6 +1851,7 @@ void RESTAPI::restAPI_GetStats(const HTTPPayload& request, HTTPPayload& reply, c peerStats.push_back(json::value(peerObj)); } } + m_network->m_peers.shared_unlock(); } response["peerStats"].set(peerStats); @@ -2078,6 +2083,8 @@ void RESTAPI::restAPI_GetAffList(const HTTPPayload& request, HTTPPayload& reply, if (m_network != nullptr) { uint32_t totalAffiliations = 0U; if (m_network->m_peers.size() > 0) { + m_network->m_peers.shared_lock(); + m_network->m_peerAffiliations.lock(false); for (auto entry : m_network->m_peers) { uint32_t peerId = entry.first; network::FNEPeerConnection* peer = entry.second; @@ -2108,6 +2115,8 @@ void RESTAPI::restAPI_GetAffList(const HTTPPayload& request, HTTPPayload& reply, } } } + m_network->m_peerAffiliations.unlock(); + m_network->m_peers.shared_unlock(); } response["totalAffiliations"].set(totalAffiliations); diff --git a/src/host/restapi/RESTAPI.cpp b/src/host/restapi/RESTAPI.cpp index 4bd117e3..f1b818f3 100644 --- a/src/host/restapi/RESTAPI.cpp +++ b/src/host/restapi/RESTAPI.cpp @@ -442,6 +442,7 @@ void RESTAPI::restAPI_PutAuth(const HTTPPayload& request, HTTPPayload& reply, co invalidateHostToken(host); errorPayload(reply, "invalid password"); LogError(LOG_REST, "failed authentication attempt from host %s", host.c_str()); + delete[] passwordHash; return; }