diff --git a/M17Control.cpp b/M17Control.cpp index a2495f6..74cd114 100644 --- a/M17Control.cpp +++ b/M17Control.cpp @@ -89,9 +89,9 @@ bool CM17Control::writeModem(unsigned char *data, unsigned int len) std::string source = m_lookup->find(m_rfLayer3.getSourceUnitId()); if (m_rssi != 0U) - LogMessage("M17, transmission lost from %s to %s%u, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", source.c_str(), grp ? "TG " : "", dstId, float(m_rfFrames) / 12.5F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); + LogMessage("M17, transmission lost from %s to %s%u, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", source.c_str(), grp ? "TG " : "", dstId, 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%u, %.1f seconds, BER: %.1f%%", source.c_str(), grp ? "TG " : "", dstId, float(m_rfFrames) / 12.5F, float(m_rfErrs * 100U) / float(m_rfBits)); + LogMessage("M17, transmission lost from %s to %s%u, %.1f seconds, BER: %.1f%%", source.c_str(), grp ? "TG " : "", dstId, float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits)); writeEndRF(); return false; } @@ -139,31 +139,9 @@ bool CM17Control::writeModem(unsigned char *data, unsigned int len) if (valid) m_rfLastLICH = lich; - // Stop repeater packets coming through, unless we're acting as a remote gateway - if (m_remoteGateway) { - unsigned char direction = m_rfLastLICH.getDirection(); - if (direction == M17_LICH_DIRECTION_INBOUND) - return false; - } else { - unsigned char direction = m_rfLastLICH.getDirection(); - if (direction == M17_LICH_DIRECTION_OUTBOUND) - return false; - } - unsigned char usc = m_rfLastLICH.getFCT(); unsigned char option = m_rfLastLICH.getOption(); - bool ret; - if (usc == M17_LICH_USC_UDCH) - ret = processData(option, data); - else - ret = processVoice(usc, option, data); - - return ret; -} - -bool CM17Control::processVoice(unsigned char usc, unsigned char option, unsigned char *data) -{ CM17SACCH sacch; bool valid = sacch.decode(data + 2U); if (valid) { @@ -260,9 +238,9 @@ bool CM17Control::processVoice(unsigned char usc, unsigned char option, unsigned m_rfFrames++; if (m_rssi != 0U) - LogMessage("M17, received RF end of transmission from %s to %s%u, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", source.c_str(), grp ? "TG " : "", dstId, float(m_rfFrames) / 12.5F, 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%u, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", source.c_str(), grp ? "TG " : "", dstId, 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%u, %.1f seconds, BER: %.1f%%", source.c_str(), grp ? "TG " : "", dstId, float(m_rfFrames) / 12.5F, float(m_rfErrs * 100U) / float(m_rfBits)); + LogMessage("M17, received RF end of transmission from %s to %s%u, %.1f seconds, BER: %.1f%%", source.c_str(), grp ? "TG " : "", dstId, float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits)); writeEndRF(); } else { m_rfFrames = 0U; @@ -552,127 +530,6 @@ bool CM17Control::processVoice(unsigned char usc, unsigned char option, unsigned return true; } -bool CM17Control::processData(unsigned char option, unsigned char *data) -{ - CM17UDCH udch; - bool validUDCH = udch.decode(data + 2U); - if (m_rfState == RS_RF_LISTENING && !validUDCH) - return false; - - if (validUDCH) { - unsigned char ran = udch.getRAN(); - if (ran != m_ran && ran != 0U) - return false; - } - - unsigned char netData[40U]; - ::memset(netData, 0x00U, 40U); - - // The layer3 data will only be correct if valid is true - unsigned char buffer[23U]; - udch.getData(buffer); - - CM17Layer3 layer3; - layer3.decode(buffer, 184U); - - if (m_rfState == RS_RF_LISTENING) { - unsigned char type = layer3.getMessageType(); - if (type != M17_MESSAGE_TYPE_DCALL_HDR) - return false; - - unsigned short srcId = layer3.getSourceUnitId(); - unsigned short dstId = layer3.getDestinationGroupId(); - bool grp = layer3.getIsGroup(); - - if (m_selfOnly) { - if (srcId != m_id) - return false; - } - - unsigned char frames = layer3.getDataBlocks(); - - std::string source = m_lookup->find(srcId); - - m_display->writeM17(source.c_str(), grp, dstId, "R"); - m_display->writeM17RSSI(m_rssi); - - LogMessage("M17, received RF data header from %s to %s%u, %u blocks", source.c_str(), grp ? "TG " : "", dstId, frames); - - m_rfLayer3 = layer3; - m_rfFrames = 0U; - - m_rfState = RS_RF_DATA; - -#if defined(DUMP_M17) - openFile(); -#endif - } - - if (m_rfState != RS_RF_DATA) - return false; - - CSync::addM17Sync(data + 2U); - - CM17LICH lich; - lich.setRFCT(M17_LICH_RFCT_RDCH); - lich.setFCT(M17_LICH_USC_UDCH); - lich.setOption(option); - lich.setDirection(m_remoteGateway || !m_duplex ? M17_LICH_DIRECTION_INBOUND : M17_LICH_DIRECTION_OUTBOUND); - lich.encode(data + 2U); - - lich.setDirection(M17_LICH_DIRECTION_INBOUND); - netData[0U] = lich.getRaw(); - - udch.getRaw(netData + 1U); - - unsigned char type = M17_MESSAGE_TYPE_DCALL_DATA; - - if (validUDCH) { - type = layer3.getMessageType(); - data[0U] = type == M17_MESSAGE_TYPE_TX_REL ? TAG_EOT : TAG_DATA; - - udch.setRAN(m_ran); - udch.encode(data + 2U); - } else { - data[0U] = TAG_DATA; - data[1U] = 0x00U; - } - - scrambler(data + 2U); - - switch (type) { - case M17_MESSAGE_TYPE_DCALL_HDR: - writeNetwork(netData, NNMT_DATA_HEADER); - break; - case M17_MESSAGE_TYPE_TX_REL: - writeNetwork(netData, NNMT_DATA_TRAILER); - break; - default: - writeNetwork(netData, NNMT_DATA_BODY); - break; - } - - if (m_duplex) - writeQueueRF(data); - - m_rfFrames++; - -#if defined(DUMP_M17) - writeFile(data + 2U); -#endif - - if (data[0U] == TAG_EOT) { - unsigned short dstId = m_rfLayer3.getDestinationGroupId(); - bool grp = m_rfLayer3.getIsGroup(); - std::string source = m_lookup->find(m_rfLayer3.getSourceUnitId()); - - LogMessage("M17, ended RF data transmission from %s to %s%u", source.c_str(), grp ? "TG " : "", dstId); - writeEndRF(); - } - - return true; -} - unsigned int CM17Control::readModem(unsigned char* data) { assert(data != NULL); @@ -728,7 +585,7 @@ void CM17Control::writeEndNet() void CM17Control::writeNetwork() { - unsigned char netData[40U]; + unsigned char netData[100U]; bool exists = m_network->read(netData); if (!exists) return; @@ -749,7 +606,6 @@ void CM17Control::writeNetwork() lich.setRaw(netData[0U]); unsigned char usc = lich.getFCT(); unsigned char option = lich.getOption(); - lich.setDirection(m_remoteGateway || !m_duplex ? M17_LICH_DIRECTION_INBOUND : M17_LICH_DIRECTION_OUTBOUND); lich.encode(data + 2U); if (usc == M17_LICH_USC_UDCH) { @@ -831,7 +687,7 @@ void CM17Control::writeNetwork() if (type == M17_MESSAGE_TYPE_TX_REL) { m_netFrames++; - LogMessage("M17, received network end of transmission from %s to %s%u, %.1f seconds", source.get(keyCALLSIGN).c_str(), grp ? "TG " : "", dstId, float(m_netFrames) / 12.5F); + LogMessage("M17, received network end of transmission from %s to %s%u, %.1f seconds", source.get(keyCALLSIGN).c_str(), grp ? "TG " : "", dstId, float(m_netFrames) / 25.0F); writeEndNet(); } else if (type == M17_MESSAGE_TYPE_VCALL) { LogMessage("M17, received network transmission from %s to %s%u", source.get(keyCALLSIGN).c_str(), grp ? "TG " : "", dstId); @@ -987,7 +843,7 @@ void CM17Control::clock(unsigned int ms) m_networkWatchdog.clock(ms); if (m_networkWatchdog.hasExpired()) { - LogMessage("M17, network watchdog has expired, %.1f seconds", float(m_netFrames) / 12.5F); + LogMessage("M17, network watchdog has expired, %.1f seconds", float(m_netFrames) / 25.0F); writeEndNet(); } } diff --git a/M17Control.h b/M17Control.h index de7bc45..97828a1 100644 --- a/M17Control.h +++ b/M17Control.h @@ -78,11 +78,8 @@ private: bool m_enabled; FILE* m_fp; - bool processVoice(unsigned char usc, unsigned char option, unsigned char* data); - void writeQueueRF(const unsigned char* data); void writeQueueNet(const unsigned char* data); - void writeNetwork(const unsigned char* data); void writeNetwork(); void scrambler(unsigned char* data) const; diff --git a/M17Network.cpp b/M17Network.cpp index 3a21373..20ee736 100644 --- a/M17Network.cpp +++ b/M17Network.cpp @@ -34,8 +34,15 @@ m_addr(), m_addrLen(0U), m_debug(debug), m_enabled(false), -m_buffer(1000U, "M17 Network") +m_outId(0U), +m_inId(0U), +m_buffer(1000U, "M17 Network"), +m_random() { + std::random_device rd; + std::mt19937 mt(rd()); + m_random = mt; + if (CUDPSocket::lookup(gatewayAddress, gatewayPort, m_addr, m_addrLen) != 0) m_addrLen = 0U; } @@ -65,6 +72,16 @@ bool CM17Network::write(const unsigned char* data) buffer[0U] = 'M'; buffer[1U] = '1'; buffer[2U] = '7'; + buffer[3U] = ' '; + + // Create a random id for this transmission if needed + if (m_outId == 0U) { + std::uniform_int_distribution dist(0x0001, 0xFFFE); + m_outId = dist(m_random); + } + + buffer[4U] = m_outId / 256U; // Unique session id + buffer[5U] = m_outId % 256U; if (m_debug) CUtils::dump(1U, "M17 data transmitted", buffer, 36U); @@ -93,9 +110,22 @@ void CM17Network::clock(unsigned int ms) if (m_debug) CUtils::dump(1U, "M17 Network Data Received", buffer, length); - if (::memcmp(buffer + 0U, "M17", 3U) != 0) + if (::memcmp(buffer + 0U, "M17 ", 4U) != 0) return; + uint16_t id = (buffer[4U] << 8) + (buffer[5U] << 0); + if (m_inId == 0U) { + m_inId = id; + } else { + if (id != m_inId) + return; + } + + // EOT? + uint16_t fn = (buffer[38U] << 8) + (buffer[39U] << 0); + if ((fn & 0x8000U) == 0x8000U) + m_inId = 0U; + unsigned char c = length; m_buffer.addData(&c, 1U); @@ -124,6 +154,12 @@ void CM17Network::close() LogMessage("Closing M17 network connection"); } +void CM17Network::reset() +{ + m_outId = 0U; + m_inId = 0U; +} + void CM17Network::enable(bool enabled) { if (!enabled && m_enabled) diff --git a/M17Network.h b/M17Network.h index d0ef7b5..697cb1a 100644 --- a/M17Network.h +++ b/M17Network.h @@ -23,6 +23,7 @@ #include "RingBuffer.h" #include "UDPSocket.h" +#include #include class CM17Network { @@ -50,7 +51,10 @@ private: unsigned int m_addrLen; bool m_debug; bool m_enabled; + uint16_t m_outId; + uint16_t m_inId; CRingBuffer m_buffer; + std::mt19937 m_random; }; #endif diff --git a/MMDVM.ini b/MMDVM.ini index 6f51621..83eb5fb 100644 --- a/MMDVM.ini +++ b/MMDVM.ini @@ -225,8 +225,8 @@ Debug=0 [M17 Network] Enable=1 GatewayAddress=127.0.0.1 -GatewayPort=11657 -LocalPort=11657 +GatewayPort=17000 +LocalPort=17000 # ModeHang=3 Debug=0 diff --git a/NXDNControl.cpp b/NXDNControl.cpp index 1e200c4..119fad6 100644 --- a/NXDNControl.cpp +++ b/NXDNControl.cpp @@ -737,7 +737,7 @@ void CNXDNControl::writeEndNet() void CNXDNControl::writeNetwork() { - unsigned char netData[40U]; + unsigned char netData[100U]; bool exists = m_network->read(netData); if (!exists) return;