diff --git a/configs/fne-config.example.yml b/configs/fne-config.example.yml
index bd320fe7..2d2c9ad0 100644
--- a/configs/fne-config.example.yml
+++ b/configs/fne-config.example.yml
@@ -144,6 +144,10 @@ system:
# Flag indicating the TGID information for this master will be sent to its peers.
sendTalkgroups: true
+ # Flag indicating the FNE should use an alternate port dedicated to diagnostic and activity
+ # log processing. This port number is always: master port + 1 (so for example, a master port
+ # of 62031 will use 62032 for diagnostic and activity messages.)
+ useAlternatePortForDiagnostics: false
# Flag indicating whether or not the host activity log will be sent to the network.
allowActivityTransfer: true
# Flag indicating whether or not the host diagnostic log will be sent to the network.
diff --git a/src/common/network/BaseNetwork.cpp b/src/common/network/BaseNetwork.cpp
index 64f03c4f..bec1b0f4 100644
--- a/src/common/network/BaseNetwork.cpp
+++ b/src/common/network/BaseNetwork.cpp
@@ -48,6 +48,7 @@ BaseNetwork::BaseNetwork(uint32_t peerId, bool duplex, bool debug, bool slot1, b
m_slot1(slot1),
m_slot2(slot2),
m_duplex(duplex),
+ m_useAlternatePortForDiagnostics(false),
m_allowActivityTransfer(allowActivityTransfer),
m_allowDiagnosticTransfer(allowDiagnosticTransfer),
m_debug(debug),
@@ -128,6 +129,7 @@ bool BaseNetwork::writeGrantReq(const uint8_t mode, const uint32_t srcId, const
/// Writes the local activity log to the network.
///
///
+///
///
bool BaseNetwork::writeActLog(const char* message)
{
@@ -145,13 +147,14 @@ bool BaseNetwork::writeActLog(const char* message)
::strcpy(buffer + 11U, message);
return writeMaster({ NET_FUNC_TRANSFER, NET_TRANSFER_SUBFUNC_ACTIVITY }, (uint8_t*)buffer, (uint32_t)len + 12U,
- 0U, 0U);
+ 0U, 0U, false, m_useAlternatePortForDiagnostics);
}
///
/// Writes the local diagnostics log to the network.
///
///
+///
///
bool BaseNetwork::writeDiagLog(const char* message)
{
@@ -169,7 +172,7 @@ bool BaseNetwork::writeDiagLog(const char* message)
::strcpy(buffer + 11U, message);
return writeMaster({ NET_FUNC_TRANSFER, NET_TRANSFER_SUBFUNC_DIAG }, (uint8_t*)buffer, (uint32_t)len + 12U,
- 0U, 0U);
+ 0U, 0U, false, m_useAlternatePortForDiagnostics);
}
///
@@ -312,9 +315,25 @@ uint32_t BaseNetwork::getDMRStreamId(uint32_t slotNo) const
///
///
///
-bool BaseNetwork::writeMaster(FrameQueue::OpcodePair opcode, const uint8_t* data, uint32_t length, uint16_t pktSeq, uint32_t streamId, bool queueOnly)
+///
+bool BaseNetwork::writeMaster(FrameQueue::OpcodePair opcode, const uint8_t* data, uint32_t length, uint16_t pktSeq, uint32_t streamId,
+ bool queueOnly, bool useAlternatePort)
{
- m_frameQueue->enqueueMessage(data, length, streamId, m_peerId, opcode, pktSeq, m_addr, m_addrLen);
+ if (useAlternatePort) {
+ sockaddr_storage addr;
+ uint32_t addrLen;
+
+ std::string address = udp::Socket::address(m_addr);
+ uint16_t port = udp::Socket::port(m_addr) + 1U;
+
+ if (udp::Socket::lookup(address, port, addr, addrLen) == 0) {
+ m_frameQueue->enqueueMessage(data, length, streamId, m_peerId, opcode, pktSeq, addr, addrLen);
+ }
+ }
+ else {
+ m_frameQueue->enqueueMessage(data, length, streamId, m_peerId, opcode, pktSeq, m_addr, m_addrLen);
+ }
+
if (queueOnly)
return true;
return m_frameQueue->flushQueue();
diff --git a/src/common/network/BaseNetwork.h b/src/common/network/BaseNetwork.h
index b0a60f90..a88f87a6 100644
--- a/src/common/network/BaseNetwork.h
+++ b/src/common/network/BaseNetwork.h
@@ -209,7 +209,7 @@ namespace network
/// Helper to send a data message to the master.
bool writeMaster(FrameQueue::OpcodePair opcode, const uint8_t* data, uint32_t length,
- uint16_t pktSeq, uint32_t streamId, bool queueOnly = false);
+ uint16_t pktSeq, uint32_t streamId, bool queueOnly = false, bool useAlternatePort = false);
/** Digital Mobile Radio */
/// Reads DMR raw frame data from the DMR ring buffer.
@@ -268,6 +268,8 @@ namespace network
__PROTECTED_READONLY_PROPERTY(bool, duplex, Duplex);
protected:
+ bool m_useAlternatePortForDiagnostics;
+
bool m_allowActivityTransfer;
bool m_allowDiagnosticTransfer;
diff --git a/src/fne/HostFNE.cpp b/src/fne/HostFNE.cpp
index f7fc1ca4..c725927a 100644
--- a/src/fne/HostFNE.cpp
+++ b/src/fne/HostFNE.cpp
@@ -51,6 +51,7 @@ HostFNE::HostFNE(const std::string& confFile) :
m_confFile(confFile),
m_conf(),
m_network(nullptr),
+ m_diagNetwork(nullptr),
m_dmrEnabled(false),
m_p25Enabled(false),
m_nxdnEnabled(false),
@@ -60,6 +61,7 @@ HostFNE::HostFNE(const std::string& confFile) :
m_pingTime(5U),
m_maxMissedPings(5U),
m_updateLookupTime(10U),
+ m_useAlternatePortForDiagnostics(false),
m_allowActivityTransfer(false),
m_allowDiagnosticTransfer(false),
m_RESTAPI(nullptr)
@@ -196,6 +198,22 @@ int HostFNE::run()
networkLoop.run();
networkLoop.setName("dvmfne:network-loop");
+ ThreadFunc diagNetworkLoop([&, this]() {
+ if (g_killed)
+ return;
+
+ if (m_diagNetwork != nullptr) {
+ while (!g_killed) {
+ m_diagNetwork->processNetwork();
+ Thread::sleep(5U);
+ }
+ }
+ });
+ if (m_useAlternatePortForDiagnostics) {
+ diagNetworkLoop.run();
+ diagNetworkLoop.setName("dvmfne:diag-network-loop");
+ }
+
// main execution loop
while (!g_killed) {
uint32_t ms = stopWatch.elapsed();
@@ -210,6 +228,8 @@ int HostFNE::run()
// clock master
if (m_network != nullptr)
m_network->clock(ms);
+ if (m_diagNetwork != nullptr)
+ m_diagNetwork->clock(ms);
// clock peers
for (auto network : m_peerNetworks) {
@@ -228,12 +248,20 @@ int HostFNE::run()
// shutdown threads
networkLoop.wait();
+ if (m_useAlternatePortForDiagnostics) {
+ diagNetworkLoop.wait();
+ }
if (m_network != nullptr) {
m_network->close();
delete m_network;
}
+ if (m_diagNetwork != nullptr) {
+ m_diagNetwork->close();
+ delete m_diagNetwork;
+ }
+
for (auto network : m_peerNetworks) {
network::Network* peerNetwork = network.second;
if (peerNetwork != nullptr)
@@ -286,6 +314,7 @@ bool HostFNE::readParams()
m_updateLookupTime = 10U;
}
+ m_useAlternatePortForDiagnostics = systemConf["useAlternatePortForDiagnostics"].as(false);
m_allowActivityTransfer = systemConf["allowActivityTransfer"].as(true);
m_allowDiagnosticTransfer = systemConf["allowDiagnosticTransfer"].as(true);
@@ -296,6 +325,7 @@ bool HostFNE::readParams()
LogInfo(" Send Talkgroups: %s", sendTalkgroups ? "yes" : "no");
+ LogInfo(" Use Alternate Port for Diagnostics: %s", m_useAlternatePortForDiagnostics ? "yes" : "no");
LogInfo(" Allow Activity Log Transfer: %s", m_allowActivityTransfer ? "yes" : "no");
LogInfo(" Allow Diagnostic Log Transfer: %s", m_allowDiagnosticTransfer ? "yes" : "no");
@@ -487,6 +517,23 @@ bool HostFNE::createMasterNetwork()
m_network->setPresharedKey(presharedKey);
}
+ // setup alternate port for diagnostics/activity logging
+ if (m_useAlternatePortForDiagnostics) {
+ m_diagNetwork = new DiagNetwork(this, m_network, address, port + 1U);
+
+ bool ret = m_diagNetwork->open();
+ if (!ret) {
+ delete m_diagNetwork;
+ m_diagNetwork = nullptr;
+ LogError(LOG_HOST, "failed to initialize diagnostic log networking!");
+ m_useAlternatePortForDiagnostics = false; // this isn't fatal so just disable alternate port
+ }
+
+ if (encrypted) {
+ m_diagNetwork->setPresharedKey(presharedKey);
+ }
+ }
+
return true;
}
diff --git a/src/fne/HostFNE.h b/src/fne/HostFNE.h
index 965fb0bf..a7e8ec29 100644
--- a/src/fne/HostFNE.h
+++ b/src/fne/HostFNE.h
@@ -19,6 +19,7 @@
#include "common/yaml/Yaml.h"
#include "common/Timer.h"
#include "network/FNENetwork.h"
+#include "network/DiagNetwork.h"
#include "network/PeerNetwork.h"
#include "network/RESTAPI.h"
@@ -58,6 +59,7 @@ private:
friend class network::fne::TagP25Data;
friend class network::fne::TagNXDNData;
network::FNENetwork* m_network;
+ network::DiagNetwork* m_diagNetwork;
bool m_dmrEnabled;
bool m_p25Enabled;
@@ -72,6 +74,8 @@ private:
uint32_t m_maxMissedPings;
uint32_t m_updateLookupTime;
+ bool m_useAlternatePortForDiagnostics;
+
bool m_allowActivityTransfer;
bool m_allowDiagnosticTransfer;
diff --git a/src/fne/network/DiagNetwork.cpp b/src/fne/network/DiagNetwork.cpp
new file mode 100644
index 00000000..b8889a20
--- /dev/null
+++ b/src/fne/network/DiagNetwork.cpp
@@ -0,0 +1,273 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/**
+* Digital Voice Modem - Converged FNE Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Converged FNE Software
+* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
+*
+* Copyright (C) 2023-2024 Bryan Biedenkapp, N2PLL
+*
+*/
+#include "fne/Defines.h"
+#include "common/Log.h"
+#include "common/Utils.h"
+#include "network/DiagNetwork.h"
+#include "fne/ActivityLog.h"
+#include "HostFNE.h"
+
+using namespace network;
+using namespace network::fne;
+
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the DiagNetwork class.
+///
+///
+///
+/// Network Hostname/IP address to listen on.
+/// Network port number.
+DiagNetwork::DiagNetwork(HostFNE* host, FNENetwork* fneNetwork, const std::string& address, uint16_t port) :
+ BaseNetwork(fneNetwork->m_peerId, true, fneNetwork->m_debug, true, true, fneNetwork->m_allowActivityTransfer, fneNetwork->m_allowDiagnosticTransfer),
+ m_fneNetwork(fneNetwork),
+ m_host(host),
+ m_address(address),
+ m_port(port)
+{
+ assert(fneNetwork != nullptr);
+ assert(host != nullptr);
+ assert(!address.empty());
+ assert(port > 0U);
+}
+
+///
+/// Finalizes a instance of the DiagNetwork class.
+///
+DiagNetwork::~DiagNetwork() = default;
+
+///
+/// Sets endpoint preshared encryption key.
+///
+void DiagNetwork::setPresharedKey(const uint8_t* presharedKey)
+{
+ m_socket->setPresharedKey(presharedKey);
+}
+
+///
+/// Process a data frames from the network.
+///
+void DiagNetwork::processNetwork()
+{
+ if (m_status != NET_STAT_MST_RUNNING) {
+ return;
+ }
+
+ sockaddr_storage address;
+ uint32_t addrLen;
+ frame::RTPHeader rtpHeader;
+ frame::RTPFNEHeader fneHeader;
+ int length = 0U;
+
+ // read message
+ UInt8Array buffer = m_frameQueue->read(length, address, addrLen, &rtpHeader, &fneHeader);
+ if (length > 0) {
+ if (m_debug)
+ Utils::dump(1U, "Network Message", buffer.get(), length);
+
+ uint32_t peerId = fneHeader.getPeerId();
+
+ NetPacketRequest* req = new NetPacketRequest();
+ req->network = m_fneNetwork;
+ req->peerId = peerId;
+
+ req->address = address;
+ req->addrLen = addrLen;
+ req->rtpHeader = rtpHeader;
+ req->fneHeader = fneHeader;
+
+ req->length = length;
+ req->buffer = new uint8_t[length];
+ ::memcpy(req->buffer, buffer.get(), length);
+
+ ::pthread_create(&req->thread, NULL, threadedNetworkRx, req);
+ }
+}
+
+///
+/// Updates the timer by the passed number of milliseconds.
+///
+///
+void DiagNetwork::clock(uint32_t ms)
+{
+ if (m_status != NET_STAT_MST_RUNNING) {
+ return;
+ }
+}
+
+///
+/// Opens connection to the network.
+///
+///
+bool DiagNetwork::open()
+{
+ if (m_debug)
+ LogMessage(LOG_NET, "Opening Network");
+
+ m_status = NET_STAT_MST_RUNNING;
+
+ m_socket = new udp::Socket(m_address, m_port);
+
+ // reinitialize the frame queue
+ if (m_frameQueue != nullptr) {
+ delete m_frameQueue;
+ m_frameQueue = new FrameQueue(m_socket, m_peerId, m_debug);
+ }
+
+ bool ret = m_socket->open();
+ if (!ret) {
+ m_status = NET_STAT_INVALID;
+ }
+
+ return ret;
+}
+
+///
+/// Closes connection to the network.
+///
+void DiagNetwork::close()
+{
+ if (m_debug)
+ LogMessage(LOG_NET, "Closing Network");
+
+ m_socket->close();
+
+ m_status = NET_STAT_INVALID;
+}
+
+// ---------------------------------------------------------------------------
+// Private Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Process a data frames from the network.
+///
+void* DiagNetwork::threadedNetworkRx(void* arg)
+{
+ NetPacketRequest* req = (NetPacketRequest*)arg;
+ if (req != nullptr) {
+ FNENetwork* network = req->network;
+ if (req->length > 0) {
+ uint32_t peerId = req->fneHeader.getPeerId();
+ uint32_t streamId = req->fneHeader.getStreamId();
+
+ std::stringstream peerName;
+ peerName << peerId << ":diag-rx-pckt";
+ if (pthread_kill(req->thread, 0) == 0) {
+ ::pthread_setname_np(req->thread, peerName.str().c_str());
+ }
+
+ // update current peer packet sequence and stream ID
+ if (peerId > 0 && (network->m_peers.find(peerId) != network->m_peers.end()) && streamId != 0U) {
+ FNEPeerConnection* connection = network->m_peers[peerId];
+ uint16_t pktSeq = req->rtpHeader.getSequence();
+
+ if (connection != nullptr) {
+ if (pktSeq == RTP_END_OF_CALL_SEQ) {
+ connection->pktLastSeq(pktSeq);
+ connection->pktNextSeq(0U);
+ } else {
+ if ((connection->currStreamId() == streamId) && (pktSeq != connection->pktNextSeq())) {
+ LogWarning(LOG_NET, "PEER %u stream %u out-of-sequence; %u != %u", peerId, streamId, pktSeq, connection->pktNextSeq());
+ }
+
+ connection->currStreamId(streamId);
+ connection->pktLastSeq(pktSeq);
+ connection->pktNextSeq(pktSeq + 1);
+ if (connection->pktNextSeq() > UINT16_MAX) {
+ connection->pktNextSeq(0U);
+ }
+ }
+ }
+
+ network->m_peers[peerId] = connection;
+ }
+
+ // process incoming message frame opcodes
+ switch (req->fneHeader.getFunction()) {
+ case NET_FUNC_TRANSFER:
+ {
+ if (req->fneHeader.getSubFunction() == NET_TRANSFER_SUBFUNC_ACTIVITY) { // Peer Activity Log Transfer
+ if (network->m_allowActivityTransfer) {
+ if (peerId > 0 && (network->m_peers.find(peerId) != network->m_peers.end())) {
+ FNEPeerConnection* connection = network->m_peers[peerId];
+ if (connection != nullptr) {
+ std::string ip = udp::Socket::address(req->address);
+
+ // validate peer (simple validation really)
+ if (connection->connected() && connection->address() == ip) {
+ uint8_t rawPayload[req->length - 11U];
+ ::memset(rawPayload, 0x00U, req->length - 11U);
+ ::memcpy(rawPayload, req->buffer + 11U, req->length - 11U);
+ std::string payload(rawPayload, rawPayload + (req->length - 11U));
+
+ ::ActivityLog("%u %s", peerId, payload.c_str());
+ }
+ else {
+ network->writePeerNAK(peerId, TAG_TRANSFER_ACT_LOG, NET_CONN_NAK_FNE_UNAUTHORIZED);
+ }
+ }
+ }
+ }
+ }
+ else if (req->fneHeader.getSubFunction() == NET_TRANSFER_SUBFUNC_DIAG) { // Peer Diagnostic Log Transfer
+ if (network->m_allowDiagnosticTransfer) {
+ if (peerId > 0 && (network->m_peers.find(peerId) != network->m_peers.end())) {
+ FNEPeerConnection* connection = network->m_peers[peerId];
+ if (connection != nullptr) {
+ std::string ip = udp::Socket::address(req->address);
+
+ // validate peer (simple validation really)
+ if (connection->connected() && connection->address() == ip) {
+ uint8_t rawPayload[req->length - 11U];
+ ::memset(rawPayload, 0x00U, req->length - 11U);
+ ::memcpy(rawPayload, req->buffer + 11U, req->length - 11U);
+ std::string payload(rawPayload, rawPayload + (req->length - 11U));
+
+ bool currState = g_disableTimeDisplay;
+ g_disableTimeDisplay = true;
+ ::Log(9999U, nullptr, "%u %s", peerId, payload.c_str());
+ g_disableTimeDisplay = currState;
+ }
+ else {
+ network->writePeerNAK(peerId, TAG_TRANSFER_DIAG_LOG, NET_CONN_NAK_FNE_UNAUTHORIZED);
+ }
+ }
+ }
+ }
+ }
+ else {
+ network->writePeerNAK(peerId, TAG_TRANSFER, NET_CONN_NAK_ILLEGAL_PACKET);
+ Utils::dump("unknown transfer opcode from the peer", req->buffer, req->length);
+ }
+ }
+ break;
+
+ default:
+ // diagostic network ignores unknowns for everything else...
+ break;
+ }
+ }
+
+ if (req->buffer != nullptr)
+ delete req->buffer;
+ delete req;
+ }
+
+ return nullptr;
+}
\ No newline at end of file
diff --git a/src/fne/network/DiagNetwork.h b/src/fne/network/DiagNetwork.h
new file mode 100644
index 00000000..5886d01b
--- /dev/null
+++ b/src/fne/network/DiagNetwork.h
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/**
+* Digital Voice Modem - Converged FNE Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Converged FNE Software
+* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
+*
+* Copyright (C) 2024 Bryan Biedenkapp, N2PLL
+*
+*/
+#if !defined(__DIAG_NETWORK_H__)
+#define __DIAG_NETWORK_H__
+
+#include "fne/Defines.h"
+#include "common/network/BaseNetwork.h"
+#include "fne/network/FNENetwork.h"
+
+#include
+
+#include
+
+// ---------------------------------------------------------------------------
+// Class Prototypes
+// ---------------------------------------------------------------------------
+
+class HOST_SW_API HostFNE;
+
+namespace network
+{
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements the diagnostic/activity log networking logic.
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API DiagNetwork : public BaseNetwork {
+ public:
+ /// Initializes a new instance of the DiagNetwork class.
+ DiagNetwork(HostFNE* host, FNENetwork* fneNetwork, const std::string& address, uint16_t port);
+ /// Finalizes a instance of the DiagNetwork class.
+ ~DiagNetwork() override;
+
+ /// Gets the current status of the network.
+ NET_CONN_STATUS getStatus() { return m_status; }
+
+ /// Sets endpoint preshared encryption key.
+ void setPresharedKey(const uint8_t* presharedKey);
+
+ /// Process a data frames from the network.
+ void processNetwork();
+
+ /// Updates the timer by the passed number of milliseconds.
+ void clock(uint32_t ms) override;
+
+ /// Opens connection to the network.
+ bool open() override;
+
+ /// Closes connection to the network.
+ void close() override;
+
+ private:
+ friend class FNENetwork;
+ FNENetwork* m_fneNetwork;
+ HostFNE* m_host;
+
+ std::string m_address;
+ uint16_t m_port;
+
+ NET_CONN_STATUS m_status;
+
+ /// Entry point to process a given network packet.
+ static void* threadedNetworkRx(void* arg);
+ };
+} // namespace network
+
+#endif // __FNE_NETWORK_H__
diff --git a/src/fne/network/FNENetwork.cpp b/src/fne/network/FNENetwork.cpp
index eaba1a4d..1c28e77c 100644
--- a/src/fne/network/FNENetwork.cpp
+++ b/src/fne/network/FNENetwork.cpp
@@ -613,7 +613,15 @@ void* FNENetwork::threadedNetworkRx(void* arg)
connection->lastACLUpdate(now);
network->m_peers[peerId] = connection;
- network->writePeerACK(peerId);
+ // attach extra notification data to the RPTC ACK to notify the peer of
+ // the use of the alternate diagnostic port
+ uint8_t buffer[1U];
+ buffer[0U] = 0x00U;
+ if (network->m_host->m_useAlternatePortForDiagnostics) {
+ buffer[0U] = 0x80U;
+ }
+
+ network->writePeerACK(peerId, buffer, 1U);
LogInfoEx(LOG_NET, "PEER %u RPTC ACK, completed the configuration exchange", peerId);
json::object peerConfig = connection->config();
@@ -766,6 +774,12 @@ void* FNENetwork::threadedNetworkRx(void* arg)
case NET_FUNC_TRANSFER:
{
+ // are activity/diagnostic transfers occurring from the alternate port?
+ if (network->m_host->m_useAlternatePortForDiagnostics) {
+ break; // for performance and other reasons -- simply ignore the entire NET_FUNC_TRANSFER at this point
+ // since they should be coming from the alternate port anyway
+ }
+
if (req->fneHeader.getSubFunction() == NET_TRANSFER_SUBFUNC_ACTIVITY) { // Peer Activity Log Transfer
if (network->m_allowActivityTransfer) {
if (peerId > 0 && (network->m_peers.find(peerId) != network->m_peers.end())) {
@@ -1398,6 +1412,8 @@ bool FNENetwork::writePeerACK(uint32_t peerId, const uint8_t* data, uint32_t len
uint8_t buffer[DATA_PACKET_LENGTH];
::memset(buffer, 0x00U, DATA_PACKET_LENGTH);
+ __SET_UINT32(peerId, buffer, 0U); // Peer ID
+
if (data != nullptr && length > 0U) {
::memcpy(buffer + 6U, data, length);
}
diff --git a/src/fne/network/FNENetwork.h b/src/fne/network/FNENetwork.h
index 32869fae..37a03a86 100644
--- a/src/fne/network/FNENetwork.h
+++ b/src/fne/network/FNENetwork.h
@@ -58,6 +58,7 @@ namespace network
// Class Prototypes
// ---------------------------------------------------------------------------
+ class HOST_SW_API DiagNetwork;
class HOST_SW_API FNENetwork;
// ---------------------------------------------------------------------------
@@ -236,6 +237,7 @@ namespace network
void close() override;
private:
+ friend class DiagNetwork;
friend class fne::TagDMRData;
fne::TagDMRData* m_tagDMR;
friend class fne::TagP25Data;
@@ -324,8 +326,6 @@ namespace network
bool writePeerNAK(uint32_t peerId, const char* tag, NET_CONN_NAK_REASON reason = NET_CONN_NAK_GENERAL_FAILURE);
/// Helper to send a NAK response to the specified peer.
bool writePeerNAK(uint32_t peerId, const char* tag, NET_CONN_NAK_REASON reason, sockaddr_storage& addr, uint32_t addrLen);
-
-
};
} // namespace network
diff --git a/src/host/network/Network.cpp b/src/host/network/Network.cpp
index a8b2b135..485be961 100644
--- a/src/host/network/Network.cpp
+++ b/src/host/network/Network.cpp
@@ -531,15 +531,19 @@ void Network::clock(uint32_t ms)
switch (m_status) {
case NET_STAT_WAITING_LOGIN:
LogDebug(LOG_NET, "PEER %u RPTL ACK, performing login exchange, remotePeerId = %u", m_peerId, rtpHeader.getSSRC());
+
::memcpy(m_salt, buffer.get() + 6U, sizeof(uint32_t));
writeAuthorisation();
+
m_status = NET_STAT_WAITING_AUTHORISATION;
m_timeoutTimer.start();
m_retryTimer.start();
break;
case NET_STAT_WAITING_AUTHORISATION:
LogDebug(LOG_NET, "PEER %u RPTK ACK, performing configuration exchange, remotePeerId = %u", m_peerId, rtpHeader.getSSRC());
+
writeConfig();
+
m_status = NET_STAT_WAITING_CONFIG;
m_timeoutTimer.start();
m_retryTimer.start();
@@ -548,10 +552,21 @@ void Network::clock(uint32_t ms)
LogMessage(LOG_NET, "PEER %u RPTC ACK, logged into the master successfully, remotePeerId = %u", m_peerId, rtpHeader.getSSRC());
m_loginStreamId = 0U;
m_remotePeerId = rtpHeader.getSSRC();
+
pktSeq(true);
+
m_status = NET_STAT_RUNNING;
m_timeoutTimer.start();
m_retryTimer.start();
+
+ Utils::dump(1U, "buffer", buffer.get(), length);
+
+ if (length > 6) {
+ m_useAlternatePortForDiagnostics = (buffer[6U] & 0x80U) == 0x80U;
+ if (m_useAlternatePortForDiagnostics) {
+ LogMessage(LOG_NET, "PEER %u RPTC ACK, master commanded alternate port for diagnostics and activity logging, remotePeerId = %u", m_peerId, rtpHeader.getSSRC());
+ }
+ }
break;
default:
break;