From e966d355cd767c9ac75375c945a91c74ae42244c Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Sun, 22 Aug 2021 20:38:26 +0100 Subject: [PATCH 1/4] Change the internal network protocol. --- M17Control.cpp | 50 ++++++++++++++++++------------------- M17Network.cpp | 68 ++++++++++++++++++++++++++++++++++++++++---------- M17Network.h | 4 ++- Version.h | 2 +- 4 files changed, 84 insertions(+), 40 deletions(-) diff --git a/M17Control.cpp b/M17Control.cpp index 4b2cfdc..34bdd50 100644 --- a/M17Control.cpp +++ b/M17Control.cpp @@ -189,6 +189,9 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) m_rssiCount = 1U; m_rfLSFn = 0U; + if (m_network != NULL) + m_network->writeHeader(m_rfLSF.getSource(), m_rfLSF.getDest(), frame); + #if defined(DUMP_M17) openFile(); #endif @@ -237,6 +240,12 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) m_aveRSSI = m_rssi; m_rssiCount = 1U; + if (m_network != NULL) { + unsigned char lsf[M17_LSF_LENGTH_BYTES]; + m_rfLSF.getNetwork(lsf); + m_network->writeHeader(m_rfLSF.getSource(), m_rfLSF.getDest(), lsf); + } + #if defined(DUMP_M17) openFile(); #endif @@ -300,18 +309,8 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) writeQueueRF(rfData); } - if (m_network != NULL && m_rfTimeoutTimer.isRunning() && !m_rfTimeoutTimer.hasExpired()) { - unsigned char netData[M17_LSF_LENGTH_BYTES + M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES]; - - m_rfLSF.getNetwork(netData + 0U); - - // Copy the FN and payload from the frame - ::memcpy(netData + M17_LSF_LENGTH_BYTES - M17_CRC_LENGTH_BYTES, frame, M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES); - - // The CRC is added in the networking code - - m_network->write(netData); - } + if (m_network != NULL && m_rfTimeoutTimer.isRunning() && !m_rfTimeoutTimer.hasExpired()) + m_network->writeData(m_rfLSF.getSource(), m_rfLSF.getDest(), frame); m_rfFrames++; @@ -404,16 +403,18 @@ void CM17Control::writeNetwork() m_networkWatchdog.start(); - m_netLSF.setNetwork(netData); - m_netLSF.setCAN(m_can); + if (netData[0U] == TAG_HEADER) { + m_netLSF.setNetwork(netData + 25U); + m_netLSF.setCAN(m_can); - if (!m_allowEncryption) { - unsigned char type = m_netLSF.getEncryptionType(); - if (type != M17_ENCRYPTION_TYPE_NONE) - return; - } + if (!m_allowEncryption) { + unsigned char type = m_netLSF.getEncryptionType(); + if (type != M17_ENCRYPTION_TYPE_NONE) { + m_network->reset(); + return; + } + } - if (m_netState == RS_NET_IDLE) { std::string source = m_netLSF.getSource(); std::string dest = m_netLSF.getDest(); @@ -432,8 +433,7 @@ void CM17Control::writeNetwork() m_netState = RS_NET_DATA_AUDIO; break; default: - LogMessage("M17, received network unknown transmission from %s to %s", source.c_str(), dest.c_str()); - m_netState = RS_NET_DATA; + m_network->reset(); break; } @@ -467,7 +467,7 @@ void CM17Control::writeNetwork() writeQueueNet(start); } - if (m_netState == RS_NET_AUDIO || m_netState == RS_NET_DATA_AUDIO) { + if (netData[0U] == TAG_DATA) { unsigned char data[M17_FRAME_LENGTH_BYTES + 2U]; data[0U] = TAG_DATA; @@ -498,7 +498,7 @@ void CM17Control::writeNetwork() // Add the FN and the data/audio unsigned char payload[M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES]; - ::memcpy(payload, netData + 28U, M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES); + ::memcpy(payload, netData + 24U, M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES); // Add the Convolution FEC CM17Convolution conv; @@ -515,7 +515,7 @@ void CM17Control::writeNetwork() m_netLSFn = 0U; // EOT handling - uint16_t fn = (netData[28U] << 8) + (netData[29U] << 0); + uint16_t fn = (netData[24U] << 8) + (netData[25U] << 0); if ((fn & 0x8000U) == 0x8000U) { std::string source = m_netLSF.getSource(); std::string dest = m_netLSF.getDest(); diff --git a/M17Network.cpp b/M17Network.cpp index 9a3bf8d..62fcec2 100644 --- a/M17Network.cpp +++ b/M17Network.cpp @@ -74,19 +74,19 @@ bool CM17Network::open() } } -bool CM17Network::write(const unsigned char* data) +bool CM17Network::writeHeader(const std::string& source, const std::string& dest, const unsigned char* data) { if (m_addrLen == 0U) return false; assert(data != NULL); - unsigned char buffer[100U]; + unsigned char buffer[60U]; buffer[0U] = 'M'; buffer[1U] = '1'; buffer[2U] = '7'; - buffer[3U] = ' '; + buffer[3U] = 'H'; // Create a random id for this transmission if needed if (m_outId == 0U) { @@ -97,16 +97,49 @@ bool CM17Network::write(const unsigned char* data) buffer[4U] = m_outId / 256U; // Unique session id buffer[5U] = m_outId % 256U; - ::memcpy(buffer + 6U, data, 46U); + ::memset(buffer + 6U, ' ', 9U); + ::memcpy(buffer + 6U, source.c_str(), source.size()); - // Dummy CRC - buffer[52U] = 0x00U; - buffer[53U] = 0x00U; + ::memset(buffer + 15U, ' ', 9U); + ::memcpy(buffer + 15U, dest.c_str(), dest.size()); + + ::memcpy(buffer + 24U, data, 28U); if (m_debug) - CUtils::dump(1U, "M17 data transmitted", buffer, 54U); + CUtils::dump(1U, "M17 header transmitted", buffer, 52U); - return m_socket.write(buffer, 54U, m_addr, m_addrLen); + return m_socket.write(buffer, 52U, m_addr, m_addrLen); +} + +bool CM17Network::writeData(const std::string& source, const std::string& dest, const unsigned char* data) +{ + if (m_addrLen == 0U) + return false; + + assert(data != NULL); + + unsigned char buffer[50U]; + + buffer[0U] = 'M'; + buffer[1U] = '1'; + buffer[2U] = '7'; + buffer[3U] = 'D'; + + buffer[4U] = m_outId / 256U; // Unique session id + buffer[5U] = m_outId % 256U; + + ::memset(buffer + 6U, ' ', 9U); + ::memcpy(buffer + 6U, source.c_str(), source.size()); + + ::memset(buffer + 15U, ' ', 9U); + ::memcpy(buffer + 15U, dest.c_str(), dest.size()); + + ::memcpy(buffer + 24U, data, 18U); + + if (m_debug) + CUtils::dump(1U, "M17 data transmitted", buffer, 42U); + + return m_socket.write(buffer, 42U, m_addr, m_addrLen); } void CM17Network::clock(unsigned int ms) @@ -139,7 +172,7 @@ void CM17Network::clock(unsigned int ms) if (::memcmp(buffer + 0U, "PING", 4U) == 0) return; - if (::memcmp(buffer + 0U, "M17 ", 4U) != 0) { + if (::memcmp(buffer + 0U, "M17H", 4U) != 0 && ::memcmp(buffer + 0U, "M17D", 4U) != 0) { CUtils::dump(2U, "M17, received unknown packet", buffer, length); return; } @@ -152,10 +185,19 @@ void CM17Network::clock(unsigned int ms) return; } - unsigned char c = length - 6U; - m_buffer.addData(&c, 1U); + if (::memcmp(buffer + 0U, "M17H", 4U) == 0) { + unsigned char c = length - 5U; + m_buffer.addData(&c, 1U); - m_buffer.addData(buffer + 6U, length - 6U); + m_buffer.addData(&TAG_HEADER, 1U); + m_buffer.addData(buffer + 6U, length - 6U); + } else { + unsigned char c = length - 5U; + m_buffer.addData(&c, 1U); + + m_buffer.addData(&TAG_DATA, 1U); + m_buffer.addData(buffer + 6U, length - 6U); + } } bool CM17Network::read(unsigned char* data) diff --git a/M17Network.h b/M17Network.h index dbc2b2c..9dfe4b1 100644 --- a/M17Network.h +++ b/M17Network.h @@ -36,7 +36,9 @@ public: void enable(bool enabled); - bool write(const unsigned char* data); + bool writeHeader(const std::string& source, const std::string& dest, const unsigned char* data); + + bool writeData(const std::string& source, const std::string& dest, const unsigned char* data); bool read(unsigned char* data); diff --git a/Version.h b/Version.h index c4fd038..f819e78 100644 --- a/Version.h +++ b/Version.h @@ -19,6 +19,6 @@ #if !defined(VERSION_H) #define VERSION_H -const char* VERSION = "20210818"; +const char* VERSION = "20210822"; #endif From ef6ce0ef88987603cbb1a4ac49db7a9b91c32c25 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Sun, 22 Aug 2021 21:56:46 +0100 Subject: [PATCH 2/4] Include the fragment LICH in the network data. --- M17Control.cpp | 37 ++++++++++++++----------------------- M17Control.h | 1 - M17Network.cpp | 17 ++++++++++------- M17Network.h | 4 ++-- 4 files changed, 26 insertions(+), 33 deletions(-) diff --git a/M17Control.cpp b/M17Control.cpp index 34bdd50..23f4b07 100644 --- a/M17Control.cpp +++ b/M17Control.cpp @@ -79,7 +79,6 @@ m_rfBits(1U), m_rfLSF(), m_rfLSFn(0U), m_netLSF(), -m_netLSFn(0U), m_rssiMapper(rssiMapper), m_rssi(0U), m_maxRSSI(0U), @@ -309,8 +308,15 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) writeQueueRF(rfData); } - if (m_network != NULL && m_rfTimeoutTimer.isRunning() && !m_rfTimeoutTimer.hasExpired()) - m_network->writeData(m_rfLSF.getSource(), m_rfLSF.getDest(), frame); + if (m_network != NULL && m_rfTimeoutTimer.isRunning() && !m_rfTimeoutTimer.hasExpired()) { + unsigned char lich[M17_LICH_FRAGMENT_LENGTH_BYTES]; + m_rfLSF.getFragment(lich, m_rfLSFn); + + // Add the fragment number + lich[5U] = (m_rfLSFn & 0x07U) << 5; + + m_network->writeData(m_rfLSF.getSource(), m_rfLSF.getDest(), lich, frame); + } m_rfFrames++; @@ -404,7 +410,7 @@ void CM17Control::writeNetwork() m_networkWatchdog.start(); if (netData[0U] == TAG_HEADER) { - m_netLSF.setNetwork(netData + 25U); + m_netLSF.setNetwork(netData + 19U); m_netLSF.setCAN(m_can); if (!m_allowEncryption) { @@ -433,6 +439,7 @@ void CM17Control::writeNetwork() m_netState = RS_NET_DATA_AUDIO; break; default: + LogMessage("M17, received unknown network transmission from %s to %s", source.c_str(), dest.c_str()); m_network->reset(); break; } @@ -442,7 +449,6 @@ void CM17Control::writeNetwork() m_netTimeoutTimer.start(); m_elapsed.start(); m_netFrames = 0U; - m_netLSFn = 0U; // Create a dummy start message unsigned char start[M17_FRAME_LENGTH_BYTES + 2U]; @@ -478,15 +484,8 @@ void CM17Control::writeNetwork() m_netFrames++; - // Add the fragment LICH - unsigned char lich[M17_LICH_FRAGMENT_LENGTH_BYTES]; - m_netLSF.getFragment(lich, m_netLSFn); - - // Add the fragment number - lich[5U] = (m_netLSFn & 0x07U) << 5; - unsigned int frag1, frag2, frag3, frag4; - CM17Utils::splitFragmentLICH(lich, frag1, frag2, frag3, frag4); + CM17Utils::splitFragmentLICH(netData + 19U, frag1, frag2, frag3, frag4); // Add Golay to the LICH fragment here unsigned int lich1 = CGolay24128::encode24128(frag1); @@ -496,13 +495,9 @@ void CM17Control::writeNetwork() CM17Utils::combineFragmentLICHFEC(lich1, lich2, lich3, lich4, data + 2U + M17_SYNC_LENGTH_BYTES); - // Add the FN and the data/audio - unsigned char payload[M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES]; - ::memcpy(payload, netData + 24U, M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES); - // Add the Convolution FEC CM17Convolution conv; - conv.encodeData(payload, data + 2U + M17_SYNC_LENGTH_BYTES + M17_LICH_FRAGMENT_FEC_LENGTH_BYTES); + conv.encodeData(netData + 25U, data + 2U + M17_SYNC_LENGTH_BYTES + M17_LICH_FRAGMENT_FEC_LENGTH_BYTES); unsigned char temp[M17_FRAME_LENGTH_BYTES]; interleaver(data + 2U, temp); @@ -510,12 +505,8 @@ void CM17Control::writeNetwork() writeQueueNet(data); - m_netLSFn++; - if (m_netLSFn >= 6U) - m_netLSFn = 0U; - // EOT handling - uint16_t fn = (netData[24U] << 8) + (netData[25U] << 0); + uint16_t fn = (netData[25U] << 8) + (netData[26U] << 0); if ((fn & 0x8000U) == 0x8000U) { std::string source = m_netLSF.getSource(); std::string dest = m_netLSF.getDest(); diff --git a/M17Control.h b/M17Control.h index 5339d33..7d25faa 100644 --- a/M17Control.h +++ b/M17Control.h @@ -69,7 +69,6 @@ private: CM17LSF m_rfLSF; unsigned int m_rfLSFn; CM17LSF m_netLSF; - unsigned int m_netLSFn; CRSSIInterpolator* m_rssiMapper; unsigned char m_rssi; unsigned char m_maxRSSI; diff --git a/M17Network.cpp b/M17Network.cpp index 62fcec2..108ae38 100644 --- a/M17Network.cpp +++ b/M17Network.cpp @@ -74,12 +74,12 @@ bool CM17Network::open() } } -bool CM17Network::writeHeader(const std::string& source, const std::string& dest, const unsigned char* data) +bool CM17Network::writeHeader(const std::string& source, const std::string& dest, const unsigned char* lsf) { if (m_addrLen == 0U) return false; - assert(data != NULL); + assert(lsf != NULL); unsigned char buffer[60U]; @@ -103,7 +103,7 @@ bool CM17Network::writeHeader(const std::string& source, const std::string& dest ::memset(buffer + 15U, ' ', 9U); ::memcpy(buffer + 15U, dest.c_str(), dest.size()); - ::memcpy(buffer + 24U, data, 28U); + ::memcpy(buffer + 24U, lsf, 28U); if (m_debug) CUtils::dump(1U, "M17 header transmitted", buffer, 52U); @@ -111,12 +111,13 @@ bool CM17Network::writeHeader(const std::string& source, const std::string& dest return m_socket.write(buffer, 52U, m_addr, m_addrLen); } -bool CM17Network::writeData(const std::string& source, const std::string& dest, const unsigned char* data) +bool CM17Network::writeData(const std::string& source, const std::string& dest,const unsigned char* lsf, const unsigned char* data) { if (m_addrLen == 0U) return false; assert(data != NULL); + assert(lsf != NULL); unsigned char buffer[50U]; @@ -134,12 +135,14 @@ bool CM17Network::writeData(const std::string& source, const std::string& dest, ::memset(buffer + 15U, ' ', 9U); ::memcpy(buffer + 15U, dest.c_str(), dest.size()); - ::memcpy(buffer + 24U, data, 18U); + ::memcpy(buffer + 24U, lsf, 6U); + + ::memcpy(buffer + 30U, data, 18U); if (m_debug) - CUtils::dump(1U, "M17 data transmitted", buffer, 42U); + CUtils::dump(1U, "M17 data transmitted", buffer, 48U); - return m_socket.write(buffer, 42U, m_addr, m_addrLen); + return m_socket.write(buffer, 48U, m_addr, m_addrLen); } void CM17Network::clock(unsigned int ms) diff --git a/M17Network.h b/M17Network.h index 9dfe4b1..f04bf38 100644 --- a/M17Network.h +++ b/M17Network.h @@ -36,9 +36,9 @@ public: void enable(bool enabled); - bool writeHeader(const std::string& source, const std::string& dest, const unsigned char* data); + bool writeHeader(const std::string& source, const std::string& dest, const unsigned char* lsf); - bool writeData(const std::string& source, const std::string& dest, const unsigned char* data); + bool writeData(const std::string& source, const std::string& dest, const unsigned char* lsf, const unsigned char* data); bool read(unsigned char* data); From d1dc6bb7a01023eed5d9f22574e16348e7cf1937 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 26 Aug 2021 21:49:46 +0100 Subject: [PATCH 3/4] Simplify the LSF processing to allow changed META field data changed through. --- M17Control.cpp | 156 +++++++++++++++++++++++++++++++++---------------- M17Control.h | 5 +- M17LSF.cpp | 19 ++++++ M17LSF.h | 3 + M17Network.cpp | 73 +++++------------------ M17Network.h | 4 +- Version.h | 2 +- 7 files changed, 148 insertions(+), 114 deletions(-) diff --git a/M17Control.cpp b/M17Control.cpp index 23f4b07..db4c099 100644 --- a/M17Control.cpp +++ b/M17Control.cpp @@ -76,9 +76,12 @@ m_rfFrames(0U), m_netFrames(0U), m_rfErrs(0U), m_rfBits(1U), -m_rfLSF(), +m_rfLSF1(), +m_rfLSF2(), +m_rfLSF3(), m_rfLSFn(0U), m_netLSF(), +m_netLSFn(0U), m_rssiMapper(rssiMapper), m_rssi(0U), m_maxRSSI(0U), @@ -106,8 +109,8 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) unsigned char type = data[0U]; if (type == TAG_LOST && (m_rfState == RS_RF_AUDIO || m_rfState == RS_RF_DATA_AUDIO)) { - std::string source = m_rfLSF.getSource(); - std::string dest = m_rfLSF.getDest(); + std::string source = m_rfLSF1.getSource(); + std::string dest = m_rfLSF1.getDest(); if (m_rssi != 0U) LogMessage("M17, transmission lost from %s to %s, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", source.c_str(), dest.c_str(), float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); @@ -160,7 +163,7 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) interleaver(temp, data + 2U); if (m_rfState == RS_RF_LISTENING && data[0U] == TAG_HEADER) { - m_rfLSF.reset(); + m_rfLSF1.reset(); CM17Convolution conv; unsigned char frame[M17_LSF_LENGTH_BYTES]; @@ -168,11 +171,11 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) bool valid = CM17CRC::checkCRC16(frame, M17_LSF_LENGTH_BYTES); if (valid) { - m_rfLSF.setLinkSetup(frame); + m_rfLSF1.setLinkSetup(frame); bool ret = processRFHeader(false); if (!ret) { - m_rfLSF.reset(); + m_rfLSF1.reset(); return false; } @@ -181,6 +184,8 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) m_rfFrames = 0U; m_rfErrs = ber; m_rfBits = 368U; + m_rfLSF2.reset(); + m_rfLSF3.reset(); m_rfTimeoutTimer.start(); m_minRSSI = m_rssi; m_maxRSSI = m_rssi; @@ -188,9 +193,6 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) m_rssiCount = 1U; m_rfLSFn = 0U; - if (m_network != NULL) - m_network->writeHeader(m_rfLSF.getSource(), m_rfLSF.getDest(), frame); - #if defined(DUMP_M17) openFile(); #endif @@ -203,7 +205,7 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) if (m_rfState == RS_RF_LISTENING && data[0U] == TAG_DATA) { m_rfState = RS_RF_LATE_ENTRY; - m_rfLSF.reset(); + m_rfLSF1.reset(); } if (m_rfState == RS_RF_LATE_ENTRY && data[0U] == TAG_DATA) { @@ -220,31 +222,27 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) CM17Utils::combineFragmentLICH(lich1, lich2, lich3, lich4, lich); m_rfLSFn = (lich4 >> 5) & 0x07U; - m_rfLSF.setFragment(lich, m_rfLSFn); + m_rfLSF1.setFragment(lich, m_rfLSFn); - bool valid = m_rfLSF.isValid(); + bool valid = m_rfLSF1.isValid(); if (valid) { bool ret = processRFHeader(true); if (!ret) { - m_rfLSF.reset(); + m_rfLSF1.reset(); return false; } m_rfFrames = 0U; m_rfErrs = 0U; m_rfBits = 1U; + m_rfLSF2.reset(); + m_rfLSF3.reset(); m_rfTimeoutTimer.start(); m_minRSSI = m_rssi; m_maxRSSI = m_rssi; m_aveRSSI = m_rssi; m_rssiCount = 1U; - if (m_network != NULL) { - unsigned char lsf[M17_LSF_LENGTH_BYTES]; - m_rfLSF.getNetwork(lsf); - m_network->writeHeader(m_rfLSF.getSource(), m_rfLSF.getDest(), lsf); - } - #if defined(DUMP_M17) openFile(); #endif @@ -258,6 +256,37 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) #if defined(DUMP_M17) writeFile(data + 2U); #endif + // Keep looking at the running LSF in case of changed META field data + unsigned int lich1, lich2, lich3, lich4; + bool valid1 = CGolay24128::decode24128(data + 2U + M17_SYNC_LENGTH_BYTES + 0U, lich1); + bool valid2 = CGolay24128::decode24128(data + 2U + M17_SYNC_LENGTH_BYTES + 3U, lich2); + bool valid3 = CGolay24128::decode24128(data + 2U + M17_SYNC_LENGTH_BYTES + 6U, lich3); + bool valid4 = CGolay24128::decode24128(data + 2U + M17_SYNC_LENGTH_BYTES + 9U, lich4); + + if (valid1 && valid2 && valid3 && valid4) { + unsigned char lich[M17_LICH_FRAGMENT_LENGTH_BYTES]; + CM17Utils::combineFragmentLICH(lich1, lich2, lich3, lich4, lich); + + unsigned int n = (lich4 >> 5) & 0x07U; + m_rfLSF2.setFragment(lich, n); + + // If the latest LSF is valid, save it and start collecting the next one + bool valid = m_rfLSF2.isValid(); + if (valid) { + m_rfLSF3 = m_rfLSF2; + m_rfLSF2.reset(); + } + } + + // Update the currently transmitted LSF when the fragement number is zero + if (m_rfLSFn == 0U) { + bool valid = m_rfLSF3.isValid(); + if (valid) { + m_rfLSF1 = m_rfLSF3; + m_rfLSF3.reset(); + } + } + CM17Convolution conv; unsigned char frame[M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES]; unsigned int errors = conv.decodeData(data + 2U + M17_SYNC_LENGTH_BYTES + M17_LICH_FRAGMENT_FEC_LENGTH_BYTES, frame); @@ -282,7 +311,7 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) CSync::addM17StreamSync(rfData + 2U); unsigned char lich[M17_LICH_FRAGMENT_LENGTH_BYTES]; - m_rfLSF.getFragment(lich, m_rfLSFn); + m_rfLSF1.getFragment(lich, m_rfLSFn); // Add the fragment number lich[5U] = (m_rfLSFn & 0x07U) << 5; @@ -309,13 +338,16 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) } if (m_network != NULL && m_rfTimeoutTimer.isRunning() && !m_rfTimeoutTimer.hasExpired()) { - unsigned char lich[M17_LICH_FRAGMENT_LENGTH_BYTES]; - m_rfLSF.getFragment(lich, m_rfLSFn); + unsigned char netData[M17_LSF_LENGTH_BYTES + M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES]; - // Add the fragment number - lich[5U] = (m_rfLSFn & 0x07U) << 5; + m_rfLSF1.getNetwork(netData + 0U); - m_network->writeData(m_rfLSF.getSource(), m_rfLSF.getDest(), lich, frame); + // Copy the FN and payload from the frame + ::memcpy(netData + M17_LSF_LENGTH_BYTES - M17_CRC_LENGTH_BYTES, frame, M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES); + + // The CRC is added in the networking code + + m_network->write(netData); } m_rfFrames++; @@ -328,8 +360,8 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) bool bEnd = (fn & 0x8000U) == 0x8000U; if (bValid && bEnd) { - std::string source = m_rfLSF.getSource(); - std::string dest = m_rfLSF.getDest(); + std::string source = m_rfLSF1.getSource(); + std::string dest = m_rfLSF1.getDest(); if (m_rssi != 0U) LogMessage("M17, received RF end of transmission from %s to %s, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", source.c_str(), dest.c_str(), float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); @@ -365,7 +397,9 @@ void CM17Control::writeEndRF() m_rfTimeoutTimer.stop(); - m_rfLSF.reset(); + m_rfLSF1.reset(); + m_rfLSF2.reset(); + m_rfLSF3.reset(); if (m_netState == RS_NET_IDLE) { m_display->clearM17(); @@ -409,17 +443,17 @@ void CM17Control::writeNetwork() m_networkWatchdog.start(); - if (netData[0U] == TAG_HEADER) { - m_netLSF.setNetwork(netData + 19U); - m_netLSF.setCAN(m_can); - - if (!m_allowEncryption) { - unsigned char type = m_netLSF.getEncryptionType(); - if (type != M17_ENCRYPTION_TYPE_NONE) { - m_network->reset(); - return; - } + if (!m_allowEncryption) { + unsigned char type = m_netLSF.getEncryptionType(); + if (type != M17_ENCRYPTION_TYPE_NONE) { + m_network->reset(); + return; } + } + + if (m_netState == RS_NET_IDLE) { + m_netLSF.setNetwork(netData); + m_netLSF.setCAN(m_can); std::string source = m_netLSF.getSource(); std::string dest = m_netLSF.getDest(); @@ -439,7 +473,7 @@ void CM17Control::writeNetwork() m_netState = RS_NET_DATA_AUDIO; break; default: - LogMessage("M17, received unknown network transmission from %s to %s", source.c_str(), dest.c_str()); + LogMessage("M17, received network unknown transmission from %s to %s", source.c_str(), dest.c_str()); m_network->reset(); break; } @@ -449,6 +483,7 @@ void CM17Control::writeNetwork() m_netTimeoutTimer.start(); m_elapsed.start(); m_netFrames = 0U; + m_netLSFn = 0U; // Create a dummy start message unsigned char start[M17_FRAME_LENGTH_BYTES + 2U]; @@ -473,7 +508,13 @@ void CM17Control::writeNetwork() writeQueueNet(start); } - if (netData[0U] == TAG_DATA) { + if (m_netState == RS_NET_AUDIO || m_netState == RS_NET_DATA_AUDIO) { + // Refresh the LSF every six frames in case the META field changes + if (m_netLSFn == 0U) { + m_netLSF.setNetwork(netData); + m_netLSF.setCAN(m_can); + } + unsigned char data[M17_FRAME_LENGTH_BYTES + 2U]; data[0U] = TAG_DATA; @@ -484,8 +525,15 @@ void CM17Control::writeNetwork() m_netFrames++; + // Add the fragment LICH + unsigned char lich[M17_LICH_FRAGMENT_LENGTH_BYTES]; + m_netLSF.getFragment(lich, m_netLSFn); + + // Add the fragment number + lich[5U] = (m_netLSFn & 0x07U) << 5; + unsigned int frag1, frag2, frag3, frag4; - CM17Utils::splitFragmentLICH(netData + 19U, frag1, frag2, frag3, frag4); + CM17Utils::splitFragmentLICH(lich, frag1, frag2, frag3, frag4); // Add Golay to the LICH fragment here unsigned int lich1 = CGolay24128::encode24128(frag1); @@ -495,9 +543,13 @@ void CM17Control::writeNetwork() CM17Utils::combineFragmentLICHFEC(lich1, lich2, lich3, lich4, data + 2U + M17_SYNC_LENGTH_BYTES); + // Add the FN and the data/audio + unsigned char payload[M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES]; + ::memcpy(payload, netData + 28U, M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES); + // Add the Convolution FEC CM17Convolution conv; - conv.encodeData(netData + 25U, data + 2U + M17_SYNC_LENGTH_BYTES + M17_LICH_FRAGMENT_FEC_LENGTH_BYTES); + conv.encodeData(payload, data + 2U + M17_SYNC_LENGTH_BYTES + M17_LICH_FRAGMENT_FEC_LENGTH_BYTES); unsigned char temp[M17_FRAME_LENGTH_BYTES]; interleaver(data + 2U, temp); @@ -505,8 +557,12 @@ void CM17Control::writeNetwork() writeQueueNet(data); + m_netLSFn++; + if (m_netLSFn >= 6U) + m_netLSFn = 0U; + // EOT handling - uint16_t fn = (netData[25U] << 8) + (netData[26U] << 0); + uint16_t fn = (netData[28U] << 8) + (netData[29U] << 0); if ((fn & 0x8000U) == 0x8000U) { std::string source = m_netLSF.getSource(); std::string dest = m_netLSF.getDest(); @@ -518,19 +574,19 @@ void CM17Control::writeNetwork() bool CM17Control::processRFHeader(bool lateEntry) { - unsigned char packetStream = m_rfLSF.getPacketStream(); + unsigned char packetStream = m_rfLSF1.getPacketStream(); if (packetStream == M17_PACKET_TYPE) return false; - unsigned char can = m_rfLSF.getCAN(); + unsigned char can = m_rfLSF1.getCAN(); if (can != m_can) return false; - std::string source = m_rfLSF.getSource(); - std::string dest = m_rfLSF.getDest(); + std::string source = m_rfLSF1.getSource(); + std::string dest = m_rfLSF1.getDest(); if (!m_allowEncryption) { - unsigned char type = m_rfLSF.getEncryptionType(); + unsigned char type = m_rfLSF1.getEncryptionType(); if (type != M17_ENCRYPTION_TYPE_NONE) { LogMessage("M17, access attempt with encryption from %s to %s", source.c_str(), dest.c_str()); m_rfState = RS_RF_REJECTED; @@ -547,7 +603,7 @@ bool CM17Control::processRFHeader(bool lateEntry) } } - unsigned char dataType = m_rfLSF.getDataType(); + unsigned char dataType = m_rfLSF1.getDataType(); switch (dataType) { case M17_DATA_TYPE_DATA: LogMessage("M17, received RF%sdata transmission from %s to %s", lateEntry ? " late entry " : " ", source.c_str(), dest.c_str()); @@ -580,7 +636,7 @@ bool CM17Control::processRFHeader(bool lateEntry) CSync::addM17LinkSetupSync(data + 2U); unsigned char setup[M17_LSF_LENGTH_BYTES]; - m_rfLSF.getLinkSetup(setup); + m_rfLSF1.getLinkSetup(setup); // Add the convolution FEC CM17Convolution conv; diff --git a/M17Control.h b/M17Control.h index 7d25faa..e66c8ce 100644 --- a/M17Control.h +++ b/M17Control.h @@ -66,9 +66,12 @@ private: unsigned int m_netFrames; unsigned int m_rfErrs; unsigned int m_rfBits; - CM17LSF m_rfLSF; + CM17LSF m_rfLSF1; + CM17LSF m_rfLSF2; + CM17LSF m_rfLSF3; unsigned int m_rfLSFn; CM17LSF m_netLSF; + unsigned int m_netLSFn; CRSSIInterpolator* m_rssiMapper; unsigned char m_rssi; unsigned char m_maxRSSI; diff --git a/M17LSF.cpp b/M17LSF.cpp index 22b5a58..3034e26 100644 --- a/M17LSF.cpp +++ b/M17LSF.cpp @@ -24,6 +24,15 @@ #include #include +CM17LSF::CM17LSF(const CM17LSF& lsf) : +m_lsf(NULL), +m_valid(lsf.m_valid) +{ + m_lsf = new unsigned char[M17_LSF_LENGTH_BYTES]; + + ::memcpy(m_lsf, lsf.m_lsf, M17_LSF_LENGTH_BYTES); +} + CM17LSF::CM17LSF() : m_lsf(NULL), m_valid(false) @@ -197,3 +206,13 @@ void CM17LSF::setFragment(const unsigned char* data, unsigned int n) m_valid = CM17CRC::checkCRC16(m_lsf, M17_LSF_LENGTH_BYTES); } + +CM17LSF& CM17LSF::operator=(const CM17LSF& lsf) +{ + if (&lsf != this) { + ::memcpy(m_lsf, lsf.m_lsf, M17_LSF_LENGTH_BYTES); + m_valid = lsf.m_valid; + } + + return *this; +} diff --git a/M17LSF.h b/M17LSF.h index 47c3a29..92aaa2a 100644 --- a/M17LSF.h +++ b/M17LSF.h @@ -23,6 +23,7 @@ class CM17LSF { public: + CM17LSF(const CM17LSF& lsf); CM17LSF(); ~CM17LSF(); @@ -62,6 +63,8 @@ public: void getFragment(unsigned char* data, unsigned int n) const; void setFragment(const unsigned char* data, unsigned int n); + CM17LSF& operator=(const CM17LSF& lsf); + private: unsigned char* m_lsf; bool m_valid; diff --git a/M17Network.cpp b/M17Network.cpp index 108ae38..9a3bf8d 100644 --- a/M17Network.cpp +++ b/M17Network.cpp @@ -74,19 +74,19 @@ bool CM17Network::open() } } -bool CM17Network::writeHeader(const std::string& source, const std::string& dest, const unsigned char* lsf) +bool CM17Network::write(const unsigned char* data) { if (m_addrLen == 0U) return false; - assert(lsf != NULL); + assert(data != NULL); - unsigned char buffer[60U]; + unsigned char buffer[100U]; buffer[0U] = 'M'; buffer[1U] = '1'; buffer[2U] = '7'; - buffer[3U] = 'H'; + buffer[3U] = ' '; // Create a random id for this transmission if needed if (m_outId == 0U) { @@ -97,52 +97,16 @@ bool CM17Network::writeHeader(const std::string& source, const std::string& dest buffer[4U] = m_outId / 256U; // Unique session id buffer[5U] = m_outId % 256U; - ::memset(buffer + 6U, ' ', 9U); - ::memcpy(buffer + 6U, source.c_str(), source.size()); + ::memcpy(buffer + 6U, data, 46U); - ::memset(buffer + 15U, ' ', 9U); - ::memcpy(buffer + 15U, dest.c_str(), dest.size()); - - ::memcpy(buffer + 24U, lsf, 28U); + // Dummy CRC + buffer[52U] = 0x00U; + buffer[53U] = 0x00U; if (m_debug) - CUtils::dump(1U, "M17 header transmitted", buffer, 52U); + CUtils::dump(1U, "M17 data transmitted", buffer, 54U); - return m_socket.write(buffer, 52U, m_addr, m_addrLen); -} - -bool CM17Network::writeData(const std::string& source, const std::string& dest,const unsigned char* lsf, const unsigned char* data) -{ - if (m_addrLen == 0U) - return false; - - assert(data != NULL); - assert(lsf != NULL); - - unsigned char buffer[50U]; - - buffer[0U] = 'M'; - buffer[1U] = '1'; - buffer[2U] = '7'; - buffer[3U] = 'D'; - - buffer[4U] = m_outId / 256U; // Unique session id - buffer[5U] = m_outId % 256U; - - ::memset(buffer + 6U, ' ', 9U); - ::memcpy(buffer + 6U, source.c_str(), source.size()); - - ::memset(buffer + 15U, ' ', 9U); - ::memcpy(buffer + 15U, dest.c_str(), dest.size()); - - ::memcpy(buffer + 24U, lsf, 6U); - - ::memcpy(buffer + 30U, data, 18U); - - if (m_debug) - CUtils::dump(1U, "M17 data transmitted", buffer, 48U); - - return m_socket.write(buffer, 48U, m_addr, m_addrLen); + return m_socket.write(buffer, 54U, m_addr, m_addrLen); } void CM17Network::clock(unsigned int ms) @@ -175,7 +139,7 @@ void CM17Network::clock(unsigned int ms) if (::memcmp(buffer + 0U, "PING", 4U) == 0) return; - if (::memcmp(buffer + 0U, "M17H", 4U) != 0 && ::memcmp(buffer + 0U, "M17D", 4U) != 0) { + if (::memcmp(buffer + 0U, "M17 ", 4U) != 0) { CUtils::dump(2U, "M17, received unknown packet", buffer, length); return; } @@ -188,19 +152,10 @@ void CM17Network::clock(unsigned int ms) return; } - if (::memcmp(buffer + 0U, "M17H", 4U) == 0) { - unsigned char c = length - 5U; - m_buffer.addData(&c, 1U); + unsigned char c = length - 6U; + m_buffer.addData(&c, 1U); - m_buffer.addData(&TAG_HEADER, 1U); - m_buffer.addData(buffer + 6U, length - 6U); - } else { - unsigned char c = length - 5U; - m_buffer.addData(&c, 1U); - - m_buffer.addData(&TAG_DATA, 1U); - m_buffer.addData(buffer + 6U, length - 6U); - } + m_buffer.addData(buffer + 6U, length - 6U); } bool CM17Network::read(unsigned char* data) diff --git a/M17Network.h b/M17Network.h index f04bf38..dbc2b2c 100644 --- a/M17Network.h +++ b/M17Network.h @@ -36,9 +36,7 @@ public: void enable(bool enabled); - bool writeHeader(const std::string& source, const std::string& dest, const unsigned char* lsf); - - bool writeData(const std::string& source, const std::string& dest, const unsigned char* lsf, const unsigned char* data); + bool write(const unsigned char* data); bool read(unsigned char* data); diff --git a/Version.h b/Version.h index f819e78..5542f96 100644 --- a/Version.h +++ b/Version.h @@ -19,6 +19,6 @@ #if !defined(VERSION_H) #define VERSION_H -const char* VERSION = "20210822"; +const char* VERSION = "20210826"; #endif From 45e45da6e6da11678bff53d25ed1f3ee4aecee45 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 21 Sep 2021 20:56:11 +0100 Subject: [PATCH 4/4] Substitute the source with the repeaters callsign and add the extended callsign information on RF. --- M17Control.cpp | 202 ++++++++++++++++++++++++++++++------------------- M17Control.h | 12 ++- M17Defines.h | 5 +- Version.h | 2 +- 4 files changed, 136 insertions(+), 85 deletions(-) diff --git a/M17Control.cpp b/M17Control.cpp index b040c61..79def48 100644 --- a/M17Control.cpp +++ b/M17Control.cpp @@ -66,6 +66,8 @@ m_network(network), m_display(display), m_duplex(duplex), m_queue(5000U, "M17 Control"), +m_source(), +m_dest(), m_rfState(RS_RF_LISTENING), m_netState(RS_NET_IDLE), m_rfTimeoutTimer(1000U, timeout), @@ -76,9 +78,11 @@ m_rfFrames(0U), m_netFrames(0U), m_rfErrs(0U), m_rfBits(1U), -m_rfLSF1(), -m_rfLSF2(), -m_rfLSF3(), +m_rfLSFCount(0U), +m_rfCurrentRFLSF(), +m_rfCurrentNetLSF(), +m_rfCollectingLSF(), +m_rfCollectedLSF(), m_rfLSFn(0U), m_netLSF(), m_netLSFn(0U), @@ -109,13 +113,10 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) unsigned char type = data[0U]; if (type == TAG_LOST && (m_rfState == RS_RF_AUDIO || m_rfState == RS_RF_DATA_AUDIO)) { - std::string source = m_rfLSF1.getSource(); - std::string dest = m_rfLSF1.getDest(); - if (m_rssi != 0U) - LogMessage("M17, transmission lost from %s to %s, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", source.c_str(), dest.c_str(), float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); + LogMessage("M17, transmission lost from %s to %s, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", m_source.c_str(), m_dest.c_str(), float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); else - LogMessage("M17, transmission lost from %s to %s, %.1f seconds, BER: %.1f%%", source.c_str(), dest.c_str(), float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits)); + LogMessage("M17, transmission lost from %s to %s, %.1f seconds, BER: %.1f%%", m_source.c_str(), m_dest.c_str(), float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits)); writeEndRF(); return false; } @@ -163,7 +164,8 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) interleaver(temp, data + 2U); if (m_rfState == RS_RF_LISTENING && data[0U] == TAG_HEADER) { - m_rfLSF1.reset(); + m_rfCurrentRFLSF.reset(); + m_rfCurrentNetLSF.reset(); CM17Convolution conv; unsigned char frame[M17_LSF_LENGTH_BYTES]; @@ -171,27 +173,29 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) bool valid = CM17CRC::checkCRC16(frame, M17_LSF_LENGTH_BYTES); if (valid) { - m_rfLSF1.setLinkSetup(frame); + m_rfCurrentNetLSF.setLinkSetup(frame); bool ret = processRFHeader(false); if (!ret) { - m_rfLSF1.reset(); + m_rfCurrentRFLSF.reset(); + m_rfCurrentNetLSF.reset(); return false; } LogDebug("M17, link setup frame: errs: %u/368 (%.1f%%)", ber, float(ber) / 3.68F); - m_rfFrames = 0U; - m_rfErrs = ber; - m_rfBits = 368U; - m_rfLSF2.reset(); - m_rfLSF3.reset(); + m_rfFrames = 0U; + m_rfErrs = ber; + m_rfBits = 368U; + m_rfCollectingLSF.reset(); + m_rfCollectedLSF.reset(); m_rfTimeoutTimer.start(); - m_minRSSI = m_rssi; - m_maxRSSI = m_rssi; - m_aveRSSI = m_rssi; - m_rssiCount = 1U; - m_rfLSFn = 0U; + m_minRSSI = m_rssi; + m_maxRSSI = m_rssi; + m_aveRSSI = m_rssi; + m_rssiCount = 1U; + m_rfLSFn = 0U; + m_rfLSFCount = 0U; #if defined(DUMP_M17) openFile(); @@ -205,7 +209,8 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) if (m_rfState == RS_RF_LISTENING && data[0U] == TAG_DATA) { m_rfState = RS_RF_LATE_ENTRY; - m_rfLSF1.reset(); + m_rfCurrentRFLSF.reset(); + m_rfCurrentNetLSF.reset(); } if (m_rfState == RS_RF_LATE_ENTRY && data[0U] == TAG_DATA) { @@ -222,26 +227,28 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) CM17Utils::combineFragmentLICH(lich1, lich2, lich3, lich4, lich); m_rfLSFn = (lich4 >> 5) & 0x07U; - m_rfLSF1.setFragment(lich, m_rfLSFn); + m_rfCurrentNetLSF.setFragment(lich, m_rfLSFn); - bool valid = m_rfLSF1.isValid(); + bool valid = m_rfCurrentNetLSF.isValid(); if (valid) { bool ret = processRFHeader(true); if (!ret) { - m_rfLSF1.reset(); + m_rfCurrentRFLSF.reset(); + m_rfCurrentNetLSF.reset(); return false; } - m_rfFrames = 0U; - m_rfErrs = 0U; - m_rfBits = 1U; - m_rfLSF2.reset(); - m_rfLSF3.reset(); + m_rfFrames = 0U; + m_rfErrs = 0U; + m_rfBits = 1U; + m_rfCollectingLSF.reset(); + m_rfCollectedLSF.reset(); m_rfTimeoutTimer.start(); - m_minRSSI = m_rssi; - m_maxRSSI = m_rssi; - m_aveRSSI = m_rssi; - m_rssiCount = 1U; + m_minRSSI = m_rssi; + m_maxRSSI = m_rssi; + m_aveRSSI = m_rssi; + m_rssiCount = 1U; + m_rfLSFCount = 0U; #if defined(DUMP_M17) openFile(); @@ -268,22 +275,30 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) CM17Utils::combineFragmentLICH(lich1, lich2, lich3, lich4, lich); unsigned int n = (lich4 >> 5) & 0x07U; - m_rfLSF2.setFragment(lich, n); + m_rfCollectingLSF.setFragment(lich, n); // If the latest LSF is valid, save it and start collecting the next one - bool valid = m_rfLSF2.isValid(); + bool valid = m_rfCollectingLSF.isValid(); if (valid) { - m_rfLSF3 = m_rfLSF2; - m_rfLSF2.reset(); + m_rfCollectedLSF = m_rfCollectingLSF; + m_rfCollectingLSF.reset(); } } // Update the currently transmitted LSF when the fragement number is zero if (m_rfLSFn == 0U) { - bool valid = m_rfLSF3.isValid(); + bool valid = m_rfCollectedLSF.isValid(); if (valid) { - m_rfLSF1 = m_rfLSF3; - m_rfLSF3.reset(); + m_rfCurrentNetLSF = m_rfCollectedLSF; + m_rfCollectedLSF.reset(); + + m_rfLSFCount++; + if (m_rfLSFCount > 7U) { + createRFLSF(true); + m_rfLSFCount = 0U; + } else { + createRFLSF(false); + } } } @@ -311,7 +326,7 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) CSync::addM17StreamSync(rfData + 2U); unsigned char lich[M17_LICH_FRAGMENT_LENGTH_BYTES]; - m_rfLSF1.getFragment(lich, m_rfLSFn); + m_rfCurrentRFLSF.getFragment(lich, m_rfLSFn); // Add the fragment number lich[5U] = (m_rfLSFn & 0x07U) << 5; @@ -340,7 +355,7 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) if (m_network != NULL && m_rfTimeoutTimer.isRunning() && !m_rfTimeoutTimer.hasExpired()) { unsigned char netData[M17_LSF_LENGTH_BYTES + M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES]; - m_rfLSF1.getNetwork(netData + 0U); + m_rfCurrentNetLSF.getNetwork(netData + 0U); // Copy the FN and payload from the frame ::memcpy(netData + M17_LSF_LENGTH_BYTES - M17_CRC_LENGTH_BYTES, frame, M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES); @@ -382,7 +397,7 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) if (m_network != NULL && m_rfTimeoutTimer.isRunning() && !m_rfTimeoutTimer.hasExpired()) { unsigned char netData[M17_LSF_LENGTH_BYTES + M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES]; - m_rfLSF1.getNetwork(netData + 0U); + m_rfCurrentNetLSF.getNetwork(netData + 0U); // Add a EOF FN and silence for the EOF frame netData[M17_LSF_LENGTH_BYTES - M17_CRC_LENGTH_BYTES + 0U] = 0x80U; @@ -391,9 +406,12 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) if (m_rfState == RS_RF_AUDIO) { ::memcpy(netData + M17_LSF_LENGTH_BYTES - M17_CRC_LENGTH_BYTES + M17_FN_LENGTH_BYTES + 0U, M17_3200_SILENCE, 8U); ::memcpy(netData + M17_LSF_LENGTH_BYTES - M17_CRC_LENGTH_BYTES + M17_FN_LENGTH_BYTES + 8U, M17_3200_SILENCE, 8U); - } else { + } else if (m_rfState == RS_RF_DATA_AUDIO) { ::memcpy(netData + M17_LSF_LENGTH_BYTES - M17_CRC_LENGTH_BYTES + M17_FN_LENGTH_BYTES + 0U, M17_1600_SILENCE, 8U); ::memset(netData + M17_LSF_LENGTH_BYTES - M17_CRC_LENGTH_BYTES + M17_FN_LENGTH_BYTES + 8U, 0x00U, 8U); + } else { + ::memset(netData + M17_LSF_LENGTH_BYTES - M17_CRC_LENGTH_BYTES + M17_FN_LENGTH_BYTES + 0U, 0x00U, 8U); + ::memset(netData + M17_LSF_LENGTH_BYTES - M17_CRC_LENGTH_BYTES + M17_FN_LENGTH_BYTES + 8U, 0x00U, 8U); } // The CRC is added in the networking code @@ -401,13 +419,10 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) m_network->write(netData); } - std::string source = m_rfLSF1.getSource(); - std::string dest = m_rfLSF1.getDest(); - if (m_rssi != 0U) - LogMessage("M17, received RF end of transmission from %s to %s, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", source.c_str(), dest.c_str(), float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); + LogMessage("M17, received RF end of transmission from %s to %s, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", m_source.c_str(), m_dest.c_str(), float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); else - LogMessage("M17, received RF end of transmission from %s to %s, %.1f seconds, BER: %.1f%%", source.c_str(), dest.c_str(), float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits)); + LogMessage("M17, received RF end of transmission from %s to %s, %.1f seconds, BER: %.1f%%", m_source.c_str(), m_dest.c_str(), float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits)); writeEndRF(); return true; @@ -437,9 +452,13 @@ void CM17Control::writeEndRF() m_rfTimeoutTimer.stop(); - m_rfLSF1.reset(); - m_rfLSF2.reset(); - m_rfLSF3.reset(); + m_source.clear(); + m_dest.clear(); + + m_rfCurrentRFLSF.reset(); + m_rfCurrentNetLSF.reset(); + m_rfCollectingLSF.reset(); + m_rfCollectedLSF.reset(); if (m_netState == RS_NET_IDLE) { m_display->clearM17(); @@ -460,6 +479,9 @@ void CM17Control::writeEndNet() m_netTimeoutTimer.stop(); m_networkWatchdog.stop(); + m_source.clear(); + m_dest.clear(); + m_netLSF.reset(); m_display->clearM17(); @@ -495,32 +517,34 @@ void CM17Control::writeNetwork() if (m_netState == RS_NET_IDLE) { m_netLSF.setNetwork(netData); - m_netLSF.setCAN(m_can); - std::string source = m_netLSF.getSource(); - std::string dest = m_netLSF.getDest(); + m_source = m_netLSF.getSource(); + m_dest = m_netLSF.getDest(); + + m_netLSF.setSource(m_callsign); + m_netLSF.setCAN(m_can); unsigned char dataType = m_netLSF.getDataType(); switch (dataType) { case M17_DATA_TYPE_DATA: - LogMessage("M17, received network data transmission from %s to %s", source.c_str(), dest.c_str()); + LogMessage("M17, received network data transmission from %s to %s", m_source.c_str(), m_dest.c_str()); m_netState = RS_NET_DATA; break; case M17_DATA_TYPE_VOICE: - LogMessage("M17, received network voice transmission from %s to %s", source.c_str(), dest.c_str()); + LogMessage("M17, received network voice transmission from %s to %s", m_source.c_str(), m_dest.c_str()); m_netState = RS_NET_AUDIO; break; case M17_DATA_TYPE_VOICE_DATA: - LogMessage("M17, received network voice + data transmission from %s to %s", source.c_str(), dest.c_str()); + LogMessage("M17, received network voice + data transmission from %s to %s", m_source.c_str(), m_dest.c_str()); m_netState = RS_NET_DATA_AUDIO; break; default: - LogMessage("M17, received network unknown transmission from %s to %s", source.c_str(), dest.c_str()); + LogMessage("M17, received network unknown transmission from %s to %s", m_source.c_str(), m_dest.c_str()); m_network->reset(); return; } - m_display->writeM17(source.c_str(), dest.c_str(), "N"); + m_display->writeM17(m_source.c_str(), m_dest.c_str(), "N"); m_netTimeoutTimer.start(); m_elapsed.start(); @@ -554,6 +578,8 @@ void CM17Control::writeNetwork() // Refresh the LSF every six frames in case the META field changes if (m_netLSFn == 0U) { m_netLSF.setNetwork(netData); + + m_netLSF.setSource(m_callsign); m_netLSF.setCAN(m_can); } @@ -611,10 +637,7 @@ void CM17Control::writeNetwork() // EOT handling uint16_t fn = (netData[28U] << 8) + (netData[29U] << 0); if ((fn & 0x8000U) == 0x8000U) { - std::string source = m_netLSF.getSource(); - std::string dest = m_netLSF.getDest(); - - LogMessage("M17, received network end of transmission from %s to %s, %.1f seconds", source.c_str(), dest.c_str(), float(m_netFrames) / 25.0F); + LogMessage("M17, received network end of transmission from %s to %s, %.1f seconds", m_source.c_str(), m_dest.c_str(), float(m_netFrames) / 25.0F); unsigned char data[M17_FRAME_LENGTH_BYTES + 2U]; @@ -634,54 +657,56 @@ void CM17Control::writeNetwork() bool CM17Control::processRFHeader(bool lateEntry) { - unsigned char packetStream = m_rfLSF1.getPacketStream(); + unsigned char packetStream = m_rfCurrentNetLSF.getPacketStream(); if (packetStream == M17_PACKET_TYPE) return false; - unsigned char can = m_rfLSF1.getCAN(); + unsigned char can = m_rfCurrentNetLSF.getCAN(); if (can != m_can) return false; - std::string source = m_rfLSF1.getSource(); - std::string dest = m_rfLSF1.getDest(); + m_source = m_rfCurrentNetLSF.getSource(); + m_dest = m_rfCurrentNetLSF.getDest(); if (!m_allowEncryption) { - unsigned char type = m_rfLSF1.getEncryptionType(); + unsigned char type = m_rfCurrentNetLSF.getEncryptionType(); if (type != M17_ENCRYPTION_TYPE_NONE) { - LogMessage("M17, access attempt with encryption from %s to %s", source.c_str(), dest.c_str()); + LogMessage("M17, access attempt with encryption from %s to %s", m_source.c_str(), m_dest.c_str()); m_rfState = RS_RF_REJECTED; return true; } } if (m_selfOnly) { - bool ret = checkCallsign(source); + bool ret = checkCallsign(m_source); if (!ret) { - LogMessage("M17, invalid access attempt from %s to %s", source.c_str(), dest.c_str()); + LogMessage("M17, invalid access attempt from %s to %s", m_source.c_str(), m_dest.c_str()); m_rfState = RS_RF_REJECTED; return true; } } - unsigned char dataType = m_rfLSF1.getDataType(); + unsigned char dataType = m_rfCurrentNetLSF.getDataType(); switch (dataType) { case M17_DATA_TYPE_DATA: - LogMessage("M17, received RF%sdata transmission from %s to %s", lateEntry ? " late entry " : " ", source.c_str(), dest.c_str()); + LogMessage("M17, received RF%sdata transmission from %s to %s", lateEntry ? " late entry " : " ", m_source.c_str(), m_dest.c_str()); m_rfState = RS_RF_DATA; break; case M17_DATA_TYPE_VOICE: - LogMessage("M17, received RF%svoice transmission from %s to %s", lateEntry ? " late entry " : " ", source.c_str(), dest.c_str()); + LogMessage("M17, received RF%svoice transmission from %s to %s", lateEntry ? " late entry " : " ", m_source.c_str(), m_dest.c_str()); m_rfState = RS_RF_AUDIO; break; case M17_DATA_TYPE_VOICE_DATA: - LogMessage("M17, received RF%svoice + data transmission from %s to %s", lateEntry ? " late entry " : " ", source.c_str(), dest.c_str()); + LogMessage("M17, received RF%svoice + data transmission from %s to %s", lateEntry ? " late entry " : " ", m_source.c_str(), m_dest.c_str()); m_rfState = RS_RF_DATA_AUDIO; break; default: return false; } - m_display->writeM17(source.c_str(), dest.c_str(), "R"); + m_display->writeM17(m_source.c_str(), m_dest.c_str(), "R"); + + createRFLSF(true); if (m_duplex) { unsigned char data[M17_FRAME_LENGTH_BYTES + 2U]; @@ -694,7 +719,7 @@ bool CM17Control::processRFHeader(bool lateEntry) CSync::addM17LinkSetupSync(data + 2U); unsigned char setup[M17_LSF_LENGTH_BYTES]; - m_rfLSF1.getLinkSetup(setup); + m_rfCurrentRFLSF.getLinkSetup(setup); // Add the convolution FEC CM17Convolution conv; @@ -710,6 +735,25 @@ bool CM17Control::processRFHeader(bool lateEntry) return true; } +void CM17Control::createRFLSF(bool addCallsign) +{ + m_rfCurrentRFLSF = m_rfCurrentNetLSF; + + m_rfCurrentRFLSF.setSource(m_callsign); + + if (addCallsign) { + m_rfCurrentRFLSF.setEncryptionType(M17_ENCRYPTION_TYPE_NONE); + m_rfCurrentRFLSF.setEncryptionSubType(M17_ENCRYPTION_SUB_TYPE_CALLSIGNS); + + // Copy the encoded source into the META field + unsigned char meta[M17_META_LENGTH_BYTES]; + ::memset(meta, 0x00U, M17_META_LENGTH_BYTES); + CM17Utils::encodeCallsign(m_source, meta + 0U); + + m_rfCurrentRFLSF.setMeta(meta); + } +} + void CM17Control::clock(unsigned int ms) { if (m_network != NULL) diff --git a/M17Control.h b/M17Control.h index c5357d7..1e06a28 100644 --- a/M17Control.h +++ b/M17Control.h @@ -56,6 +56,8 @@ private: CDisplay* m_display; bool m_duplex; CRingBuffer m_queue; + std::string m_source; + std::string m_dest; RPT_RF_STATE m_rfState; RPT_NET_STATE m_netState; CTimer m_rfTimeoutTimer; @@ -66,9 +68,11 @@ private: unsigned int m_netFrames; unsigned int m_rfErrs; unsigned int m_rfBits; - CM17LSF m_rfLSF1; - CM17LSF m_rfLSF2; - CM17LSF m_rfLSF3; + unsigned int m_rfLSFCount; + CM17LSF m_rfCurrentRFLSF; + CM17LSF m_rfCurrentNetLSF; + CM17LSF m_rfCollectingLSF; + CM17LSF m_rfCollectedLSF; unsigned int m_rfLSFn; CM17LSF m_netLSF; unsigned int m_netLSFn; @@ -94,6 +98,8 @@ private: bool checkCallsign(const std::string& source) const; + void createRFLSF(bool addCallsign); + void writeEndRF(); void writeEndNet(); diff --git a/M17Defines.h b/M17Defines.h index 35fdc6b..0543d8e 100644 --- a/M17Defines.h +++ b/M17Defines.h @@ -73,7 +73,8 @@ const unsigned char M17_ENCRYPTION_TYPE_NONE = 0x00U; const unsigned char M17_ENCRYPTION_TYPE_AES = 0x01U; const unsigned char M17_ENCRYPTION_TYPE_SCRAMBLE = 0x02U; -const unsigned char M17_ENCRYPTION_SUB_TYPE_TEXT = 0x00U; -const unsigned char M17_ENCRYPTION_SUB_TYPE_GPS = 0x01U; +const unsigned char M17_ENCRYPTION_SUB_TYPE_TEXT = 0x00U; +const unsigned char M17_ENCRYPTION_SUB_TYPE_GPS = 0x01U; +const unsigned char M17_ENCRYPTION_SUB_TYPE_CALLSIGNS = 0x02U; #endif diff --git a/Version.h b/Version.h index aba5baa..9ff3456 100644 --- a/Version.h +++ b/Version.h @@ -19,6 +19,6 @@ #if !defined(VERSION_H) #define VERSION_H -const char* VERSION = "20210919"; +const char* VERSION = "20210921"; #endif