for performance reasons on very noisy/busy setups that may have *lots* of peers, use of an alternate port to service diagnostic and activity log transfers helps ensure the traffic port doesn't become overloaded with data;
parent
8ca4ed5a40
commit
c4ca72581f
@ -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 <cassert>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Public Class Members
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the DiagNetwork class.
|
||||
/// </summary>
|
||||
/// <param name="host"></param>
|
||||
/// <param name="network"></param>
|
||||
/// <param name="address">Network Hostname/IP address to listen on.</param>
|
||||
/// <param name="port">Network port number.</param>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finalizes a instance of the DiagNetwork class.
|
||||
/// </summary>
|
||||
DiagNetwork::~DiagNetwork() = default;
|
||||
|
||||
/// <summary>
|
||||
/// Sets endpoint preshared encryption key.
|
||||
/// </summary>
|
||||
void DiagNetwork::setPresharedKey(const uint8_t* presharedKey)
|
||||
{
|
||||
m_socket->setPresharedKey(presharedKey);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process a data frames from the network.
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the timer by the passed number of milliseconds.
|
||||
/// </summary>
|
||||
/// <param name="ms"></param>
|
||||
void DiagNetwork::clock(uint32_t ms)
|
||||
{
|
||||
if (m_status != NET_STAT_MST_RUNNING) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens connection to the network.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes connection to the network.
|
||||
/// </summary>
|
||||
void DiagNetwork::close()
|
||||
{
|
||||
if (m_debug)
|
||||
LogMessage(LOG_NET, "Closing Network");
|
||||
|
||||
m_socket->close();
|
||||
|
||||
m_status = NET_STAT_INVALID;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Private Class Members
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Process a data frames from the network.
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
@ -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 <string>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// 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:
|
||||
/// <summary>Initializes a new instance of the DiagNetwork class.</summary>
|
||||
DiagNetwork(HostFNE* host, FNENetwork* fneNetwork, const std::string& address, uint16_t port);
|
||||
/// <summary>Finalizes a instance of the DiagNetwork class.</summary>
|
||||
~DiagNetwork() override;
|
||||
|
||||
/// <summary>Gets the current status of the network.</summary>
|
||||
NET_CONN_STATUS getStatus() { return m_status; }
|
||||
|
||||
/// <summary>Sets endpoint preshared encryption key.</summary>
|
||||
void setPresharedKey(const uint8_t* presharedKey);
|
||||
|
||||
/// <summary>Process a data frames from the network.</summary>
|
||||
void processNetwork();
|
||||
|
||||
/// <summary>Updates the timer by the passed number of milliseconds.</summary>
|
||||
void clock(uint32_t ms) override;
|
||||
|
||||
/// <summary>Opens connection to the network.</summary>
|
||||
bool open() override;
|
||||
|
||||
/// <summary>Closes connection to the network.</summary>
|
||||
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;
|
||||
|
||||
/// <summary>Entry point to process a given network packet.</summary>
|
||||
static void* threadedNetworkRx(void* arg);
|
||||
};
|
||||
} // namespace network
|
||||
|
||||
#endif // __FNE_NETWORK_H__
|
||||
Loading…
Reference in new issue