fixed deletes on invalid pointers, cleaned up serial initialization, added timeouts for call flags, other small QoL tweaks

pull/61/head
W3AXL 2 years ago
parent e5e5462473
commit ba8067c55c

@ -74,6 +74,9 @@ dfsi:
# Trace logging (prints lots of data) # Trace logging (prints lots of data)
trace: false trace: false
# Timer which will reset local/remote call flags if frames aren't received longer than this time in ms
callTimeout: 200
# #
# Logging Configuration # Logging Configuration
# Logging Levels: # Logging Levels:

@ -33,4 +33,8 @@
#undef DEFAULT_LOCK_FILE #undef DEFAULT_LOCK_FILE
#define DEFAULT_LOCK_FILE "/tmp/dvmdfsi.lock" #define DEFAULT_LOCK_FILE "/tmp/dvmdfsi.lock"
#define DFSI_MODE_UDP_FNE 1
#define DFSI_MODE_V24_FNE 2
#define DFSI_MODE_UDP_V24 3
#endif // __DEFINES_H__ #endif // __DEFINES_H__

@ -150,6 +150,12 @@ int Dfsi::run()
if (!ret) if (!ret)
return EXIT_FAILURE; return EXIT_FAILURE;
// Read DFSI config
yaml::Node dfsi_conf = m_conf["dfsi"];
uint16_t dfsiMode = dfsi_conf["mode"].as<uint16_t>();
uint32_t p25BufferSize = dfsi_conf["p25BufferSize"].as<uint32_t>();
uint16_t callTimeout = dfsi_conf["callTimeout"].as<uint16_t>();
// initialize peer networking // initialize peer networking
ret = createPeerNetwork(); ret = createPeerNetwork();
if (!ret) if (!ret)
@ -157,36 +163,43 @@ int Dfsi::run()
::LogInfoEx(LOG_HOST, "DFSI peer network is up and running"); ::LogInfoEx(LOG_HOST, "DFSI peer network is up and running");
// Read DFSI config std::string dfsiModeStr = "Unknown";
yaml::Node dfsi_conf = m_conf["dfsi"];
uint32_t p25BufferSize = dfsi_conf["p25BufferSize"].as<uint32_t>();
// Read serial config
yaml::Node serial_conf = dfsi_conf["serial"];
std::string port = serial_conf["port"].as<std::string>();
uint32_t baudrate = serial_conf["baudrate"].as<uint32_t>();
bool rtrt = serial_conf["rtrt"].as<bool>();
bool diu = serial_conf["diu"].as<bool>();
uint16_t jitter = serial_conf["jitter"].as<uint16_t>();
bool serial_debug = serial_conf["debug"].as<bool>();
bool serial_trace = serial_conf["trace"].as<bool>();
LogInfo("Serial Parameters"); switch (dfsiMode) {
LogInfo(" Port: %s", port.c_str()); case DFSI_MODE_UDP_FNE:
LogInfo(" Baudrate: %u", baudrate); {
LogInfo(" RT/RT: %s", rtrt ? "Enabled" : "Disabled"); dfsiModeStr = "UDP DFSI to FNE";
LogInfo(" DIU Flag: %s", diu ? "Enabled" : "Disabled"); LogError(LOG_HOST, "UDP DFSI mode not yet supported, sorry!");
LogInfo(" Jitter Size: %u ms", jitter); return EXIT_FAILURE;
LogInfo(" Debug: %s", serial_debug ? "Enabled" : "Disabled"); }
LogInfo(" Trace: %s", serial_trace ? "Enabled" : "Disabled"); break;
case DFSI_MODE_V24_FNE:
// Create serial service {
m_serial = new SerialService(port, baudrate, rtrt, diu, jitter, m_network, p25BufferSize, p25BufferSize, serial_debug, serial_trace); dfsiModeStr = "V24 DFSI to FNE";
ret = createSerialNetwork(p25BufferSize, callTimeout);
// Open serial
ret = m_serial->open();
if (!ret) if (!ret)
return EXIT_FAILURE; return EXIT_FAILURE;
}
break;
case DFSI_MODE_UDP_V24:
{
dfsiModeStr = "UDP DFSI to V24 DFSI";
LogError(LOG_HOST, "UDP to V24 mode not yet supported, sorry!");
return EXIT_FAILURE;
}
break;
default:
{
LogError(LOG_HOST, "Invalid DFSI mode specified: %d", dfsiMode);
return EXIT_FAILURE;
}
break;
}
LogInfo("DFSI Parameters");
LogInfo(" Mode: %u (%s)", dfsiMode, dfsiModeStr.c_str());
LogInfo(" P25 Buffer Size: %u bytes", p25BufferSize);
LogInfo(" Call Timeout: %u ms", callTimeout);
StopWatch stopWatch; StopWatch stopWatch;
stopWatch.start(); stopWatch.start();
@ -223,11 +236,12 @@ int Dfsi::run()
if (!g_hideMessages) if (!g_hideMessages)
LogMessage(LOG_NET, "P25, duid = $%02X, lco = $%02X, MFId = $%02X, srcId = %u, dstId = %u, len = %u", duid, lco, MFId, srcId, dstId, length); LogMessage(LOG_NET, "P25, duid = $%02X, lco = $%02X, MFId = $%02X, srcId = %u, dstId = %u, len = %u", duid, lco, MFId, srcId, dstId, length);
// Send the data to the serial handler // Send the data to the serial handler if serial is up
if (m_serial != nullptr)
m_serial->processP25FromNet(std::move(p25Buffer), length); m_serial->processP25FromNet(std::move(p25Buffer), length);
} }
// We keep DMR & NXDN in so nothing breaks, even though DFSI doesn't do DMR or NXDNS // We keep DMR & NXDN in so nothing breaks, even though DFSI doesn't do DMR or NXDN
UInt8Array dmrBuffer = m_network->readDMR(netReadRet, length); UInt8Array dmrBuffer = m_network->readDMR(netReadRet, length);
if (netReadRet) { if (netReadRet) {
uint8_t seqNo = dmrBuffer[4U]; uint8_t seqNo = dmrBuffer[4U];
@ -258,7 +272,7 @@ int Dfsi::run()
// -- Network TX Clocking -- // -- Network TX Clocking --
// ------------------------------------------------------ // ------------------------------------------------------
// Processes data in the serial rx P25 buffer and sends it to the network buffer for sending // Processes data in the serial rx P25 buffer and sends it to the network buffer for sending, if serial is up
if (m_serial != nullptr) { if (m_serial != nullptr) {
m_serial->processP25ToNet(); m_serial->processP25ToNet();
} }
@ -399,3 +413,40 @@ bool Dfsi::createPeerNetwork()
return true; return true;
} }
bool Dfsi::createSerialNetwork(uint32_t p25BufferSize, uint16_t callTimeout)
{
// Read serial config
yaml::Node dfsi_conf = m_conf["dfsi"];
yaml::Node serial_conf = dfsi_conf["serial"];
std::string port = serial_conf["port"].as<std::string>();
uint32_t baudrate = serial_conf["baudrate"].as<uint32_t>();
bool rtrt = serial_conf["rtrt"].as<bool>();
bool diu = serial_conf["diu"].as<bool>();
uint16_t jitter = serial_conf["jitter"].as<uint16_t>();
bool serial_debug = serial_conf["debug"].as<bool>();
bool serial_trace = serial_conf["trace"].as<bool>();
LogInfo("Serial Parameters");
LogInfo(" Port: %s", port.c_str());
LogInfo(" Baudrate: %u", baudrate);
LogInfo(" RT/RT: %s", rtrt ? "Enabled" : "Disabled");
LogInfo(" DIU Flag: %s", diu ? "Enabled" : "Disabled");
LogInfo(" Jitter Size: %u ms", jitter);
LogInfo(" Debug: %s", serial_debug ? "Enabled" : "Disabled");
LogInfo(" Trace: %s", serial_trace ? "Enabled" : "Disabled");
// Create serial service
m_serial = new SerialService(port, baudrate, rtrt, diu, jitter, m_network, p25BufferSize, p25BufferSize, callTimeout, serial_debug, serial_trace);
// Open serial
bool ret = m_serial->open();
if (!ret) {
delete m_serial;
m_serial = nullptr;
LogError(LOG_HOST, "failed to initialied serial V24 interface");
return false;
}
return true;
}

@ -65,6 +65,8 @@ private:
bool readParams(); bool readParams();
/// <summary>Initializes peer network connectivity.</summary> /// <summary>Initializes peer network connectivity.</summary>
bool createPeerNetwork(); bool createPeerNetwork();
/// <summary>Initializes serial V24 network.</summary>
bool createSerialNetwork(uint32_t p25BufferSize, uint16_t callTimeout);
}; };
#endif // __DFSI_H__ #endif // __DFSI_H__

@ -47,6 +47,10 @@ MotFullRateVoice::MotFullRateVoice() :
/// <param name="data"></param> /// <param name="data"></param>
MotFullRateVoice::MotFullRateVoice(uint8_t* data) MotFullRateVoice::MotFullRateVoice(uint8_t* data)
{ {
// set our pointers to null since it doesn't get initialized otherwise
imbeData = nullptr;
additionalData = nullptr;
// decode
decode(data); decode(data);
} }

@ -50,6 +50,10 @@ MotStartVoiceFrame::MotStartVoiceFrame() :
/// <param name="data"></param> /// <param name="data"></param>
MotStartVoiceFrame::MotStartVoiceFrame(uint8_t* data) MotStartVoiceFrame::MotStartVoiceFrame(uint8_t* data)
{ {
// set our pointers to null since we don't initialize them anywhere else
startOfStream = nullptr;
fullRateVoice = nullptr;
// decode
decode(data); decode(data);
} }

@ -51,6 +51,10 @@ MotVoiceHeader1::MotVoiceHeader1() :
/// <param name="data"></param> /// <param name="data"></param>
MotVoiceHeader1::MotVoiceHeader1(uint8_t* data) MotVoiceHeader1::MotVoiceHeader1(uint8_t* data)
{ {
// set our pointers to null since we haven't initialized them yet
startOfStream = nullptr;
header = nullptr;
// decode
decode(data); decode(data);
} }

@ -45,6 +45,9 @@ MotVoiceHeader2::MotVoiceHeader2() :
/// <param name="data"></param> /// <param name="data"></param>
MotVoiceHeader2::MotVoiceHeader2(uint8_t* data) MotVoiceHeader2::MotVoiceHeader2(uint8_t* data)
{ {
// set pointer to null since it hasn't been initialized yet
header = nullptr;
// decode
decode(data); decode(data);
} }

@ -23,7 +23,7 @@ using namespace modem;
using namespace p25; using namespace p25;
using namespace dfsi; using namespace dfsi;
SerialService::SerialService(const std::string& portName, uint32_t baudrate, bool rtrt, bool diu, uint16_t jitter, DfsiPeerNetwork* network, uint32_t p25TxQueueSize, uint32_t p25RxQueueSize, bool debug, bool trace) : SerialService::SerialService(const std::string& portName, uint32_t baudrate, bool rtrt, bool diu, uint16_t jitter, DfsiPeerNetwork* network, uint32_t p25TxQueueSize, uint32_t p25RxQueueSize, uint16_t callTimeout, bool debug, bool trace) :
m_portName(portName), m_portName(portName),
m_baudrate(baudrate), m_baudrate(baudrate),
m_rtrt(rtrt), m_rtrt(rtrt),
@ -51,6 +51,7 @@ SerialService::SerialService(const std::string& portName, uint32_t baudrate, boo
m_rxP25LDUCounter(0U), m_rxP25LDUCounter(0U),
m_netCallInProgress(false), m_netCallInProgress(false),
m_lclCallInProgress(false), m_lclCallInProgress(false),
m_callTimeout(callTimeout),
m_rxVoiceControl(nullptr), m_rxVoiceControl(nullptr),
m_rxVoiceLsd(nullptr), m_rxVoiceLsd(nullptr),
m_rxVoiceCallData(nullptr) m_rxVoiceCallData(nullptr)
@ -87,6 +88,9 @@ SerialService::~SerialService()
void SerialService::clock(uint32_t ms) void SerialService::clock(uint32_t ms)
{ {
// Get now
uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
// Get data from serial port // Get data from serial port
RESP_TYPE_DVM type = readSerial(); RESP_TYPE_DVM type = readSerial();
@ -125,7 +129,7 @@ void SerialService::clock(uint32_t ms)
// Add P25 data to buffer // Add P25 data to buffer
m_rxP25Queue.addData(m_msgBuffer + (cmdOffset + 1U), m_msgLength - (cmdOffset + 1U)); m_rxP25Queue.addData(m_msgBuffer + (cmdOffset + 1U), m_msgLength - (cmdOffset + 1U));
if (m_debug) { if (m_debug && m_trace) {
LogDebug(LOG_SERIAL, "Got P25 data from V24 board (len: %u)", m_msgLength); LogDebug(LOG_SERIAL, "Got P25 data from V24 board (len: %u)", m_msgLength);
} }
} }
@ -175,6 +179,18 @@ void SerialService::clock(uint32_t ms)
} else if (out < 0) { } else if (out < 0) {
LogError(LOG_SERIAL, "Failed to write to serial port!"); LogError(LOG_SERIAL, "Failed to write to serial port!");
} }
// Clear a call in progress flag if we're longer than our timeout value
if (m_lclCallInProgress && (now - m_lastLclFrame > m_callTimeout)) {
m_lclCallInProgress = false;
if (m_debug)
LogDebug(LOG_SERIAL, "Local call activity timeout");
}
if (m_netCallInProgress && (now - m_lastNetFrame > m_callTimeout)) {
m_netCallInProgress = false;
if (m_debug)
LogDebug(LOG_SERIAL, "Net call activity timeout");
}
} }
bool SerialService::open() bool SerialService::open()
@ -210,6 +226,9 @@ void SerialService::processP25FromNet(UInt8Array p25Buffer, uint32_t length)
return; return;
} }
// Update our last frame time
m_lastNetFrame = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
// Decode grant info // Decode grant info
bool grantDemand = (p25Buffer[14U] & 0x80U) == 0x80U; bool grantDemand = (p25Buffer[14U] & 0x80U) == 0x80U;
@ -440,7 +459,7 @@ void SerialService::processP25FromNet(UInt8Array p25Buffer, uint32_t length)
count += dfsi::P25_DFSI_LDU2_VOICE18_FRAME_LENGTH_BYTES; count += dfsi::P25_DFSI_LDU2_VOICE18_FRAME_LENGTH_BYTES;
control = lc::LC(*dfsiLC.control()); control = lc::LC(*dfsiLC.control());
LogInfoEx(LOG_NET, P25_LDU2_STR " audio, algo = $%02X, kid = $%04X", control.getAlgId(), control.getKId()); LogInfoEx(LOG_SERIAL, P25_LDU2_STR " audio, algo = $%02X, kid = $%04X", control.getAlgId(), control.getKId());
//Utils::dump("P25 LDU2 from net", netLDU2, 9U * 25U); //Utils::dump("P25 LDU2 from net", netLDU2, 9U * 25U);
@ -550,6 +569,9 @@ void SerialService::processP25ToNet()
//LogDebug(LOG_SERIAL, "Handling DFSI frameType 0x%02X", frameType); //LogDebug(LOG_SERIAL, "Handling DFSI frameType 0x%02X", frameType);
// Update our last frame time
m_lastLclFrame = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
// Switch based on DFSI frame type // Switch based on DFSI frame type
switch (frameType) { switch (frameType) {
// Start/Stop Frame // Start/Stop Frame
@ -1248,19 +1270,19 @@ void SerialService::writeP25Frame(uint8_t duid, dfsi::LC& lc, uint8_t* ldu)
break; break;
} }
// Placeholder for last call timestamp retrieved below (not yet used) // Placeholder for last call timestamp retrieved below (Not used yet)
//int64_t lastHeard = 0U; int64_t lastHeard = 0U;
// Placeholder for sequence number retrieved below // Placeholder for sequence number retrieved below
uint32_t sequence = 0U; uint32_t sequence = 0U;
// Get the last heard value (not used currently, TODO: use this for covnentional TGID timeout purposes) // Get the last heard value
/*{ {
auto entry = m_lastHeard.find(control.getDstId()); auto entry = m_lastHeard.find(control.getDstId());
if (entry != m_lastHeard.end()) { if (entry != m_lastHeard.end()) {
lastHeard = m_lastHeard[control.getDstId()]; lastHeard = m_lastHeard[control.getDstId()];
} }
}*/ }
// Get the last sequence number // Get the last sequence number
{ {
@ -1274,8 +1296,7 @@ void SerialService::writeP25Frame(uint8_t duid, dfsi::LC& lc, uint8_t* ldu)
if (duid == P25_DUID_LDU1 && ((sequence == 0U) || (sequence == RTP_END_OF_CALL_SEQ))) { if (duid == P25_DUID_LDU1 && ((sequence == 0U) || (sequence == RTP_END_OF_CALL_SEQ))) {
// Start the new stream // Start the new stream
startOfStream(lc); startOfStream(lc);
// Update our call entries // Update our call entry
m_lastHeard[control.getDstId()] = now;
m_sequences[control.getDstId()] = ++sequence; m_sequences[control.getDstId()] = ++sequence;
// Log // Log
@ -1305,6 +1326,9 @@ void SerialService::writeP25Frame(uint8_t duid, dfsi::LC& lc, uint8_t* ldu)
m_sequences[control.getDstId()] = RTP_END_OF_CALL_SEQ; m_sequences[control.getDstId()] = RTP_END_OF_CALL_SEQ;
} }
// Update our last heard value (updated to now every time a new frame arrives)
m_lastHeard[control.getDstId()] = now;
// Break out the 9 individual P25 packets // Break out the 9 individual P25 packets
for (int n = 0; n < 9; n++) { for (int n = 0; n < 9; n++) {

@ -62,7 +62,7 @@ namespace network
class HOST_SW_API SerialService { class HOST_SW_API SerialService {
public: public:
SerialService(const std::string& portName, uint32_t baudrate, bool rtrt, bool diu, uint16_t jitter, DfsiPeerNetwork* network, uint32_t p25TxQueueSize, uint32_t p25RxQueueSize, bool debug, bool trace); SerialService(const std::string& portName, uint32_t baudrate, bool rtrt, bool diu, uint16_t jitter, DfsiPeerNetwork* network, uint32_t p25TxQueueSize, uint32_t p25RxQueueSize, uint16_t callTimeout, bool debug, bool trace);
~SerialService(); ~SerialService();
@ -111,6 +111,7 @@ namespace network
RingBuffer<uint8_t> m_rxP25Queue; RingBuffer<uint8_t> m_rxP25Queue;
RingBuffer<uint8_t> m_txP25Queue; RingBuffer<uint8_t> m_txP25Queue;
// Storage for V24 TX jitter buffer metering
uint64_t m_lastP25Tx; uint64_t m_lastP25Tx;
edac::RS634717 m_rs; edac::RS634717 m_rs;
@ -118,10 +119,17 @@ namespace network
// Counter for assembling a full LDU from individual frames in the RX queue // Counter for assembling a full LDU from individual frames in the RX queue
uint8_t m_rxP25LDUCounter; uint8_t m_rxP25LDUCounter;
// Flags to indicate if calls to/from the FNE are already in progress // "Mutex" flags to indicate if calls to/from the FNE are already in progress
bool m_netCallInProgress; bool m_netCallInProgress;
bool m_lclCallInProgress; bool m_lclCallInProgress;
// Time in ms to wait before considering a call in progress as "over" in case we miss the TDUs
uint16_t m_callTimeout;
// Storage for handling local/net call timeouts (for callInProgress mutexes)
uint64_t m_lastNetFrame;
uint64_t m_lastLclFrame;
// Control and LSD objects for current RX P25 data being built to send to the net // Control and LSD objects for current RX P25 data being built to send to the net
lc::LC* m_rxVoiceControl; lc::LC* m_rxVoiceControl;
data::LowSpeedData* m_rxVoiceLsd; data::LowSpeedData* m_rxVoiceLsd;

Loading…
Cancel
Save

Powered by TurnKey Linux.