From 1de07e2a00a7a4340c63e328e485cb5ec4074ebd Mon Sep 17 00:00:00 2001 From: Bryan Biedenkapp Date: Sat, 22 Mar 2025 10:00:51 -0400 Subject: [PATCH] update fnecore submodule; properly shutdown wave recorder and disconnect from FNEs before just blowing ourselves away; stop using pktSeq() from fnecore to track packet sequence numbers, for multi-TG architecture we have to self track (this should fix OOS errors); --- dvmconsole/Controls/ChannelBox.xaml.cs | 2 + dvmconsole/FneSystemManager.cs | 3 +- dvmconsole/MainWindow.xaml.cs | 58 +++++++++++++++++++------- fnecore | 2 +- 4 files changed, 47 insertions(+), 18 deletions(-) diff --git a/dvmconsole/Controls/ChannelBox.xaml.cs b/dvmconsole/Controls/ChannelBox.xaml.cs index 123ab21..72bc60f 100644 --- a/dvmconsole/Controls/ChannelBox.xaml.cs +++ b/dvmconsole/Controls/ChannelBox.xaml.cs @@ -52,6 +52,8 @@ namespace dvmconsole.Controls public byte[] netLDU1 = new byte[9 * 25]; public byte[] netLDU2 = new byte[9 * 25]; + public ushort pktSeq = 0; // RTP packet sequence + public int p25N = 0; public int p25SeqNo = 0; public int p25Errs = 0; diff --git a/dvmconsole/FneSystemManager.cs b/dvmconsole/FneSystemManager.cs index cadceaf..97e6688 100644 --- a/dvmconsole/FneSystemManager.cs +++ b/dvmconsole/FneSystemManager.cs @@ -53,7 +53,8 @@ namespace dvmconsole if (peerHandlers.TryGetValue(systemId, out var handler)) return handler; - throw new KeyNotFoundException($"WebSocketHandler for system '{systemId}' not found."); + return null; + //throw new KeyNotFoundException($"WebSocketHandler for system '{systemId}' not found."); } /// diff --git a/dvmconsole/MainWindow.xaml.cs b/dvmconsole/MainWindow.xaml.cs index 9b7b14f..9a6dc29 100644 --- a/dvmconsole/MainWindow.xaml.cs +++ b/dvmconsole/MainWindow.xaml.cs @@ -14,7 +14,6 @@ * */ -using System.Diagnostics; using System.IO; using System.Timers; using System.Windows; @@ -38,7 +37,6 @@ using fnecore.DMR; using fnecore.P25; using fnecore.P25.KMM; using fnecore.P25.LC.TSBK; -using static dvmconsole.Codeplug; namespace dvmconsole { @@ -85,6 +83,7 @@ namespace dvmconsole private const string URI_RESOURCE_PATH = "pack://application:,,,/dvmconsole;component"; + private bool isShuttingDown = false; private bool globalPttState = false; private const int GridSize = 5; @@ -850,6 +849,12 @@ namespace dvmconsole /// protected override void OnClosing(System.ComponentModel.CancelEventArgs e) { + isShuttingDown = true; + + waveIn.StopRecording(); + + fneSystemManager.ClearAll(); + if (!noSaveSettingsOnClose) { if (WindowState == WindowState.Maximized) @@ -882,6 +887,8 @@ namespace dvmconsole private void WaveIn_DataAvailable(object sender, WaveInEventArgs e) { bool isAnyTgOn = false; + if (isShuttingDown) + return; foreach (ChannelBox channel in selectedChannelsManager.GetSelectedChannels()) { @@ -1607,12 +1614,15 @@ namespace dvmconsole else if (cpgChannel.GetChannelMode() == Codeplug.ChannelMode.DMR) fne.SendDMRTerminator(srcId, dstId, 1, e.dmrSeqNo, e.dmrN, e.embeddedData); + // reset values e.p25SeqNo = 0; e.p25N = 0; e.dmrSeqNo = 0; e.dmrN = 0; + e.pktSeq = 0; + e.TxStreamId = 0; } } @@ -1731,12 +1741,15 @@ namespace dvmconsole else if (cpgChannel.GetChannelMode() == Codeplug.ChannelMode.DMR) fne.SendDMRTerminator(srcId, dstId, 1, e.dmrSeqNo, e.dmrN, e.embeddedData); + // reset values e.p25SeqNo = 0; e.p25N = 0; e.dmrSeqNo = 0; e.dmrN = 0; + e.pktSeq = 0; + e.TxStreamId = 0; } } @@ -2321,11 +2334,17 @@ namespace dvmconsole // send P25 LDU1 if (channel.p25N == 8U) { - ushort pktSeq = 0; + // bryanb: in multi-TG architecture we cannot use the pktSeq helper singleton in the FNE peer class otherwise we won't + // maintain outgoing RTP packet sequences properly if (channel.p25SeqNo == 0U) - pktSeq = peer.pktSeq(true); + channel.pktSeq = 0; else - pktSeq = peer.pktSeq(); + { + ushort curr = channel.pktSeq; + ++channel.pktSeq; + if (channel.pktSeq > (Constants.RtpCallEndSeq - 1)) + channel.pktSeq = 0; + } Log.WriteLine($"({channel.SystemName}) P25D: Traffic *VOICE FRAME LDU1* PEER {fne.PeerId} SRC_ID {srcId} TGID {dstId} [STREAM ID {channel.TxStreamId} SEQ {channel.p25SeqNo}]"); @@ -2333,17 +2352,23 @@ namespace dvmconsole fne.CreateNewP25MessageHdr((byte)P25DUID.LDU1, callData, ref payload, cpgChannel.GetAlgoId(), cpgChannel.GetKeyId(), channel.mi); fne.CreateP25LDU1Message(channel.netLDU1, ref payload, srcId, dstId); - peer.SendMaster(new Tuple(Constants.NET_FUNC_PROTOCOL, Constants.NET_PROTOCOL_SUBFUNC_P25), payload, pktSeq, channel.TxStreamId); + peer.SendMaster(new Tuple(Constants.NET_FUNC_PROTOCOL, Constants.NET_PROTOCOL_SUBFUNC_P25), payload, channel.pktSeq, channel.TxStreamId); } // send P25 LDU2 if (channel.p25N == 17U) { - ushort pktSeq = 0; + // bryanb: in multi-TG architecture we cannot use the pktSeq helper singleton in the FNE peer class otherwise we won't + // maintain outgoing RTP packet sequences properly if (channel.p25SeqNo == 0U) - pktSeq = peer.pktSeq(true); + channel.pktSeq = 0; else - pktSeq = peer.pktSeq(); + { + ushort curr = channel.pktSeq; + ++channel.pktSeq; + if (channel.pktSeq > (Constants.RtpCallEndSeq - 1)) + channel.pktSeq = 0; + } Log.WriteLine($"({channel.SystemName}) P25D: Traffic *VOICE FRAME LDU2* PEER {fne.PeerId} SRC_ID {srcId} TGID {dstId} [STREAM ID {channel.TxStreamId} SEQ {channel.p25SeqNo}]"); @@ -2351,7 +2376,7 @@ namespace dvmconsole fne.CreateNewP25MessageHdr((byte)P25DUID.LDU2, callData, ref payload, cpgChannel.GetAlgoId(), cpgChannel.GetKeyId(), channel.mi); fne.CreateP25LDU2Message(channel.netLDU2, ref payload, new CryptoParams { AlgId = cpgChannel.GetAlgoId(), KeyId = cpgChannel.GetKeyId(), MI = channel.mi }); - peer.SendMaster(new Tuple(Constants.NET_FUNC_PROTOCOL, Constants.NET_PROTOCOL_SUBFUNC_P25), payload, pktSeq, channel.TxStreamId); + peer.SendMaster(new Tuple(Constants.NET_FUNC_PROTOCOL, Constants.NET_PROTOCOL_SUBFUNC_P25), payload, channel.pktSeq, channel.TxStreamId); } channel.p25SeqNo++; @@ -2496,12 +2521,10 @@ namespace dvmconsole channel.dmrN = (byte)(channel.dmrSeqNo % 6); if (channel.ambeCount == FneSystemBase.AMBE_PER_SLOT) { - ushort pktSeq = 0; - // is this the intitial sequence? if (channel.dmrSeqNo == 0) { - pktSeq = fne.peer.pktSeq(true); + channel.pktSeq = 0; // send DMR voice header data = new byte[FneSystemBase.DMR_FRAME_LENGTH_BYTES]; @@ -2525,12 +2548,15 @@ namespace dvmconsole fne.CreateDMRMessage(ref dmrpkt, uint.Parse(system.Rid), uint.Parse(cpgChannel.Tgid), slot, FrameType.VOICE_SYNC, (byte)channel.dmrSeqNo, 0); Buffer.BlockCopy(data, 0, dmrpkt, 20, FneSystemBase.DMR_FRAME_LENGTH_BYTES); - fne.peer.SendMaster(new Tuple(Constants.NET_FUNC_PROTOCOL, Constants.NET_PROTOCOL_SUBFUNC_DMR), dmrpkt, pktSeq, channel.TxStreamId); + fne.peer.SendMaster(new Tuple(Constants.NET_FUNC_PROTOCOL, Constants.NET_PROTOCOL_SUBFUNC_DMR), dmrpkt, channel.pktSeq, channel.TxStreamId); channel.dmrSeqNo++; } - pktSeq = fne.peer.pktSeq(); + ushort curr = channel.pktSeq; + ++channel.pktSeq; + if (channel.pktSeq > (Constants.RtpCallEndSeq - 1)) + channel.pktSeq = 0; // send DMR voice data = new byte[FneSystemBase.DMR_FRAME_LENGTH_BYTES]; @@ -2561,7 +2587,7 @@ namespace dvmconsole fne.CreateDMRMessage(ref dmrpkt, uint.Parse(system.Rid), uint.Parse(cpgChannel.Tgid), 1, frameType, (byte)channel.dmrSeqNo, channel.dmrN); Buffer.BlockCopy(data, 0, dmrpkt, 20, FneSystemBase.DMR_FRAME_LENGTH_BYTES); - fne.peer.SendMaster(new Tuple(Constants.NET_FUNC_PROTOCOL, Constants.NET_PROTOCOL_SUBFUNC_DMR), dmrpkt, pktSeq, channel.TxStreamId); + fne.peer.SendMaster(new Tuple(Constants.NET_FUNC_PROTOCOL, Constants.NET_PROTOCOL_SUBFUNC_DMR), dmrpkt, channel.pktSeq, channel.TxStreamId); channel.dmrSeqNo++; diff --git a/fnecore b/fnecore index 28ebb1a..e18fd0c 160000 --- a/fnecore +++ b/fnecore @@ -1 +1 @@ -Subproject commit 28ebb1a939ae297f5b95ee50644c3718e9fd7fab +Subproject commit e18fd0c00eb1e4bd0d836ec16a0625e256bd6850