diff --git a/src/fne/network/FNENetwork.cpp b/src/fne/network/FNENetwork.cpp index 40de4709..0da4ceb5 100644 --- a/src/fne/network/FNENetwork.cpp +++ b/src/fne/network/FNENetwork.cpp @@ -91,6 +91,7 @@ FNENetwork::FNENetwork(HostFNE* host, const std::string& address, uint16_t port, m_status(NET_STAT_INVALID), m_peers(), m_peerAffiliations(), + m_ccPeerMap(), m_maintainenceTimer(1000U, pingTime), m_updateLookupTime(updateLookupTime * 60U), m_softConnLimit(0U), @@ -1156,6 +1157,8 @@ void* FNENetwork::threadedNetworkRx(void* arg) // validate peer (simple validation really) if (connection->connected() && connection->address() == ip) { + std::vector vcPeers; + // update peer association uint32_t len = __GET_UINT32(req->buffer, 0U); uint32_t offs = 4U; @@ -1165,11 +1168,13 @@ void* FNENetwork::threadedNetworkRx(void* arg) FNEPeerConnection* vcConnection = network->m_peers[vcPeerId]; if (vcConnection != nullptr) { vcConnection->ccPeerId(peerId); + vcPeers.push_back(vcPeerId); } } offs += 4U; } LogMessage(LOG_NET, "PEER %u (%s) announced %u VCs", peerId, connection->identity().c_str(), len); + network->m_ccPeerMap[peerId] = vcPeers; } else { network->writePeerNAK(peerId, TAG_ANNOUNCE, NET_CONN_NAK_FNE_UNAUTHORIZED); @@ -1263,10 +1268,21 @@ bool FNENetwork::erasePeerAffiliations(uint32_t peerId) bool FNENetwork::erasePeer(uint32_t peerId) { std::lock_guard lock(m_peerMutex); - auto it = std::find_if(m_peers.begin(), m_peers.end(), [&](PeerMapPair x) { return x.first == peerId; }); - if (it != m_peers.end()) { - m_peers.erase(peerId); - return true; + { + auto it = std::find_if(m_peers.begin(), m_peers.end(), [&](PeerMapPair x) { return x.first == peerId; }); + if (it != m_peers.end()) { + m_peers.erase(peerId); + return true; + } + } + + // erase any CC maps for this peer + { + auto it = std::find_if(m_ccPeerMap.begin(), m_ccPeerMap.end(), [&](auto x) { return x.first == peerId; }); + if (it != m_ccPeerMap.end()) { + m_ccPeerMap.erase(peerId); + return true; + } } return false; diff --git a/src/fne/network/FNENetwork.h b/src/fne/network/FNENetwork.h index 35f58acf..d1a8238c 100644 --- a/src/fne/network/FNENetwork.h +++ b/src/fne/network/FNENetwork.h @@ -299,6 +299,7 @@ namespace network std::unordered_map m_peers; typedef std::pair PeerAffiliationMapPair; std::unordered_map m_peerAffiliations; + std::unordered_map> m_ccPeerMap; Timer m_maintainenceTimer; diff --git a/src/fne/network/RESTAPI.cpp b/src/fne/network/RESTAPI.cpp index 0232da54..2cdadfa4 100644 --- a/src/fne/network/RESTAPI.cpp +++ b/src/fne/network/RESTAPI.cpp @@ -829,12 +829,24 @@ void RESTAPI::restAPI_GetPeerQuery(const HTTPPayload& request, HTTPPayload& repl peerObj["pingsReceived"].set(pingsReceived); uint64_t lastPing = peer->lastPing(); peerObj["lastPing"].set(lastPing); + uint32_t ccPeerId = peer->ccPeerId(); + peerObj["controlChannel"].set(ccPeerId); json::object peerConfig = peer->config(); if (peerConfig["rcon"].is()) peerConfig.erase("rcon"); peerObj["config"].set(peerConfig); + json::array voiceChannels = json::array(); + auto it = std::find_if(m_network->m_ccPeerMap.begin(), m_network->m_ccPeerMap.end(), [&](auto x) { return x.first == peerId; }); + if (it != m_network->m_ccPeerMap.end()) { + std::vector vcPeers = m_network->m_ccPeerMap[peerId]; + for (uint32_t vcEntry : vcPeers) { + voiceChannels.push_back(json::value((double)vcEntry)); + } + } + peerObj["voiceChannels"].set(voiceChannels); + peers.push_back(json::value(peerObj)); } } diff --git a/src/host/Host.cpp b/src/host/Host.cpp index cbcc02c6..31b9f25c 100644 --- a/src/host/Host.cpp +++ b/src/host/Host.cpp @@ -1126,7 +1126,8 @@ int Host::run() // CC -> FNE registered VC announcement if (m_dmrCtrlChannel || m_p25CtrlChannel || m_nxdnCtrlChannel) { - if (presenceNotifyTimer.isRunning() && presenceNotifyTimer.hasExpired()) { + if ((presenceNotifyTimer.isRunning() && presenceNotifyTimer.hasExpired()) || g_fireCCVCNotification) { + g_fireCCVCNotification = false; if (m_network != nullptr && m_voiceChPeerId.size() > 0) { LogMessage(LOG_HOST, "notifying FNE of VC registrations, peerId = %u", m_network->getPeerId()); diff --git a/src/host/HostMain.cpp b/src/host/HostMain.cpp index 90836b57..30b05c94 100644 --- a/src/host/HostMain.cpp +++ b/src/host/HostMain.cpp @@ -58,6 +58,8 @@ bool g_fireDMRBeacon = false; bool g_fireP25Control = false; bool g_fireNXDNControl = false; +bool g_fireCCVCNotification = false; + uint8_t* g_gitHashBytes = nullptr; bool g_modemDebug = false; diff --git a/src/host/HostMain.h b/src/host/HostMain.h index a5e4de0d..729c0f29 100644 --- a/src/host/HostMain.h +++ b/src/host/HostMain.h @@ -39,6 +39,8 @@ extern bool g_fireDMRBeacon; extern bool g_fireP25Control; extern bool g_fireNXDNControl; +extern bool g_fireCCVCNotification; + extern uint8_t* g_gitHashBytes; extern bool g_modemDebug; diff --git a/src/host/network/RESTAPI.cpp b/src/host/network/RESTAPI.cpp index d3be0ae6..0e413c9b 100644 --- a/src/host/network/RESTAPI.cpp +++ b/src/host/network/RESTAPI.cpp @@ -1101,6 +1101,8 @@ void RESTAPI::restAPI_PutRegisterCCVC(const HTTPPayload& request, HTTPPayload& r m_host->m_voiceChPeerId[channelNo] = peerId; LogMessage(LOG_REST, "VC %s:%u, registration notice, peerId = %u, chId = %u, chNo = %u", voiceCh.address().c_str(), voiceCh.port(), peerId, voiceCh.chId(), channelNo); LogInfoEx(LOG_HOST, "Voice Channel Id %u Channel No $%04X REST API Address %s:%u SSL %u", voiceCh.chId(), channelNo, voiceCh.address().c_str(), voiceCh.port(), voiceCh.ssl()); + + g_fireCCVCNotification = true; // announce this registration immediately to the FNE } else { LogMessage(LOG_REST, "VC, registration rejected, peerId = %u, chNo = %u, VC wasn't a defined member of the CC voice channel list", peerId, channelNo); }