correct issue where DFSI FSC control port wasn't living at the voice conveyance port + 1; refactor the proof of concept V24UDPport class to handle voice conveyance frames in their own thread (this is so the main clock doesn't get locked up); correct bad offsetting of data for V24UDPort causing weird overflow, underflow and buffer corruption;

82-dvmbridge---implement-notch-filter-for-2175hz-trc-guard-tone
Bryan Biedenkapp 1 year ago
parent 80542e246a
commit 14b749fff1

@ -590,6 +590,8 @@ system:
jitter: 200 jitter: 200
# Timer which will reset local/remote call flags if frames aren't received longer than this time in ms # Timer which will reset local/remote call flags if frames aren't received longer than this time in ms
callTimeout: 200 callTimeout: 200
# Flag indicating when operating in V.24 UDP mode should the FSC protocol be used to negotiate connection.
useFSC: false
# Sets received the signal offset from DC. # Sets received the signal offset from DC.
rxDCOffset: 0 # Valid values between -128 and 128 rxDCOffset: 0 # Valid values between -128 and 128

@ -594,7 +594,10 @@ bool Host::createModem()
if (modemMode == MODEM_MODE_DFSI) { if (modemMode == MODEM_MODE_DFSI) {
yaml::Node networkConf = m_conf["network"]; yaml::Node networkConf = m_conf["network"];
uint32_t id = networkConf["id"].as<uint32_t>(1000U); uint32_t id = networkConf["id"].as<uint32_t>(1000U);
modemPort = new port::specialized::V24UDPPort(id, g_remoteAddress, g_remotePort, g_remotePort, useFSCForUDP, debug); modemPort = new port::specialized::V24UDPPort(id, g_remoteAddress, g_remotePort, 0U, useFSCForUDP, debug);
if (useFSCForUDP) {
modemPort = new port::specialized::V24UDPPort(id, g_remoteAddress, g_remotePort + 1U, g_remotePort, useFSCForUDP, debug);
}
m_udpDSFIRemotePort = modemPort; m_udpDSFIRemotePort = modemPort;
} else { } else {
modemPort = new port::UDPPort(g_remoteAddress, g_remotePort); modemPort = new port::UDPPort(g_remoteAddress, g_remotePort);

@ -38,6 +38,12 @@ const uint32_t BUFFER_LENGTH = 2000U;
const char* V24_UDP_HARDWARE = "V.24 UDP Modem Controller"; const char* V24_UDP_HARDWARE = "V.24 UDP Modem Controller";
const uint8_t V24_UDP_PROTOCOL_VERSION = 4U; const uint8_t V24_UDP_PROTOCOL_VERSION = 4U;
// ---------------------------------------------------------------------------
// Static Class Members
// ---------------------------------------------------------------------------
std::mutex V24UDPPort::m_bufferMutex;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Public Class Members // Public Class Members
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -139,60 +145,7 @@ void V24UDPPort::clock(uint32_t ms)
processCtrlNetwork(); processCtrlNetwork();
} }
// if we have a RTP voice socket processVCNetwork();
if (m_socket != nullptr) {
uint8_t data[BUFFER_LENGTH];
::memset(data, 0x00U, BUFFER_LENGTH);
sockaddr_storage addr;
uint32_t addrLen;
int ret = m_socket->read(data, BUFFER_LENGTH, addr, addrLen);
if (ret != 0) {
// An error occurred on the socket
if (ret < 0)
return;
// Add new data to the ring buffer
if (ret > 0) {
RTPHeader rtpHeader = RTPHeader();
rtpHeader.decode(data);
// ensure payload type is correct
if (rtpHeader.getPayloadType() != DFSI_RTP_PAYLOAD_TYPE)
{
LogError(LOG_MODEM, "Invalid RTP header received from network");
return;
}
// copy message
uint32_t messageLength = ret - RTP_HEADER_LENGTH_BYTES;
UInt8Array __message = std::make_unique<uint8_t[]>(messageLength);
uint8_t* message = __message.get();
::memset(message, 0x00U, messageLength);
::memcpy(message, data + RTP_HEADER_LENGTH_BYTES, messageLength);
if (udp::Socket::match(addr, m_addr)) {
UInt8Array __reply = std::make_unique<uint8_t[]>(messageLength + 4U);
uint8_t* reply = __reply.get();
reply[0U] = DVM_SHORT_FRAME_START;
reply[1U] = messageLength & 0xFFU;
reply[2U] = CMD_P25_DATA;
reply[3U] = 0x00U;
::memcpy(reply + 4U, message, messageLength);
m_buffer.addData(reply, messageLength + 4U);
}
else {
std::string addrStr = udp::Socket::address(addr);
LogWarning(LOG_HOST, "SECURITY: Remote modem mode encountered invalid IP address; %s", addrStr.c_str());
}
}
}
}
} }
/* Resets the RTP packet sequence and stream ID. */ /* Resets the RTP packet sequence and stream ID. */
@ -231,6 +184,8 @@ int V24UDPPort::read(uint8_t* buffer, uint32_t length)
assert(buffer != nullptr); assert(buffer != nullptr);
assert(length > 0U); assert(length > 0U);
std::lock_guard<std::mutex> lock(m_bufferMutex);
// Get required data from the ring buffer // Get required data from the ring buffer
uint32_t avail = m_buffer.dataSize(); uint32_t avail = m_buffer.dataSize();
if (avail < length) if (avail < length)
@ -264,7 +219,10 @@ int V24UDPPort::write(const uint8_t* buffer, uint32_t length)
{ {
if (m_socket != nullptr) { if (m_socket != nullptr) {
uint32_t messageLen = 0U; uint32_t messageLen = 0U;
uint8_t* message = generateMessage(buffer + 3U, length - 3U, m_streamId, m_peerId, m_pktSeq, &messageLen); uint8_t* message = generateMessage(buffer + 4U, length - 4U, m_streamId, m_peerId, m_pktSeq, &messageLen);
if (m_debug)
Utils::dump(1U, "!!! Tx Outgoing DFSI UDP", buffer + 4U, length - 4U);
bool written = m_socket->write(message, messageLen, m_addr, m_addrLen); bool written = m_socket->write(message, messageLen, m_addr, m_addrLen);
if (written) if (written)
@ -458,6 +416,107 @@ void* V24UDPPort::threadedCtrlNetworkRx(void* arg)
return nullptr; return nullptr;
} }
/* Process voice conveyance frames from the network. */
void V24UDPPort::processVCNetwork()
{
// if we have a RTP voice socket
if (m_socket != nullptr) {
uint8_t data[BUFFER_LENGTH];
::memset(data, 0x00U, BUFFER_LENGTH);
sockaddr_storage addr;
uint32_t addrLen;
int ret = m_socket->read(data, BUFFER_LENGTH, addr, addrLen);
if (ret != 0) {
// An error occurred on the socket
if (ret < 0)
return;
// Add new data to the ring buffer
if (ret > 0) {
if (m_debug)
Utils::dump("!!! Rx Incoming DFSI UDP", data, ret);
V24PacketRequest* req = new V24PacketRequest();
req->address = addr;
req->addrLen = addrLen;
req->rtpHeader = RTPHeader();
req->rtpHeader.decode(data);
// ensure payload type is correct
if (req->rtpHeader.getPayloadType() != DFSI_RTP_PAYLOAD_TYPE) {
LogError(LOG_MODEM, "Invalid RTP header received from network");
delete req;
return;
}
// copy message
req->length = ret - RTP_HEADER_LENGTH_BYTES;
req->buffer = new uint8_t[req->length];
::memset(req->buffer, 0x00U, req->length);
::memcpy(req->buffer, data + RTP_HEADER_LENGTH_BYTES, req->length);
if (!Thread::runAsThread(this, threadedVCNetworkRx, req)) {
delete[] req->buffer;
delete req;
return;
}
}
}
}
}
/* Process a data frames from the network. */
void* V24UDPPort::threadedVCNetworkRx(void* arg)
{
V24PacketRequest* req = (V24PacketRequest*)arg;
if (req != nullptr) {
#if defined(_WIN32)
::CloseHandle(req->thread);
#else
::pthread_detach(req->thread);
#endif // defined(_WIN32)
V24UDPPort* network = static_cast<V24UDPPort*>(req->obj);
if (network == nullptr) {
delete req;
return nullptr;
}
if (req->length > 0) {
if (udp::Socket::match(req->address, network->m_addr)) {
UInt8Array __reply = std::make_unique<uint8_t[]>(req->length + 4U);
uint8_t* reply = __reply.get();
reply[0U] = DVM_SHORT_FRAME_START;
reply[1U] = (req->length + 4U) & 0xFFU;
reply[2U] = CMD_P25_DATA;
reply[3U] = 0x00U;
::memcpy(reply + 4U, req->buffer, req->length);
std::lock_guard<std::mutex> lock(m_bufferMutex);
network->m_buffer.addData(reply, req->length + 4U);
}
else {
std::string addrStr = udp::Socket::address(req->address);
LogWarning(LOG_HOST, "SECURITY: Remote modem mode encountered invalid IP address; %s", addrStr.c_str());
}
}
if (req->buffer != nullptr)
delete[] req->buffer;
delete req;
}
return nullptr;
}
/* Internal helper to setup the voice channel port. */ /* Internal helper to setup the voice channel port. */
void V24UDPPort::createVCPort(uint16_t port) void V24UDPPort::createVCPort(uint16_t port)
@ -580,6 +639,7 @@ void V24UDPPort::getVersion()
reply[1U] = count; reply[1U] = count;
std::lock_guard<std::mutex> lock(m_bufferMutex);
m_buffer.addData(reply, count); m_buffer.addData(reply, count);
} }
@ -612,6 +672,7 @@ void V24UDPPort::getStatus()
reply[11U] = 0U; reply[11U] = 0U;
std::lock_guard<std::mutex> lock(m_bufferMutex);
m_buffer.addData(reply, 12U); m_buffer.addData(reply, 12U);
} }
@ -626,6 +687,7 @@ void V24UDPPort::writeAck(uint8_t type)
reply[2U] = CMD_ACK; reply[2U] = CMD_ACK;
reply[3U] = type; reply[3U] = type;
std::lock_guard<std::mutex> lock(m_bufferMutex);
m_buffer.addData(reply, 4U); m_buffer.addData(reply, 4U);
} }
@ -641,5 +703,6 @@ void V24UDPPort::writeNAK(uint8_t opcode, uint8_t err)
reply[3U] = opcode; reply[3U] = opcode;
reply[4U] = err; reply[4U] = err;
std::lock_guard<std::mutex> lock(m_bufferMutex);
m_buffer.addData(reply, 5U); m_buffer.addData(reply, 5U);
} }

@ -31,6 +31,7 @@
#include <string> #include <string>
#include <random> #include <random>
#include <mutex>
namespace modem namespace modem
{ {
@ -150,6 +151,8 @@ namespace modem
bool m_debug; bool m_debug;
static std::mutex m_bufferMutex;
/** /**
* @brief Process FSC control frames from the network. * @brief Process FSC control frames from the network.
*/ */
@ -162,6 +165,18 @@ namespace modem
*/ */
static void* threadedCtrlNetworkRx(void* arg); static void* threadedCtrlNetworkRx(void* arg);
/**
* @brief Process voice conveyance frames from the network.
*/
void processVCNetwork();
/**
* @brief Entry point to process a given network packet.
* @param arg Instance of the NetPacketRequest structure.
* @returns void* (Ignore)
*/
static void* threadedVCNetworkRx(void* arg);
/** /**
* @brief Internal helper to setup the voice channel port. * @brief Internal helper to setup the voice channel port.
* @param port Port number. * @param port Port number.

Loading…
Cancel
Save

Powered by TurnKey Linux.