From 8e2c6f65837eaf19500dbb50133319f813a9820e Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 1 Feb 2018 18:32:23 +0000 Subject: [PATCH] Fix crash in the SACCH and FACCH1 encoders. --- NXDNControl.cpp | 286 ++++++++++++++++++++++++------------------------ NXDNFACCH1.cpp | 9 +- NXDNLayer3.cpp | 9 ++ NXDNLayer3.h | 1 + NXDNSACCH.cpp | 6 +- NXDNUDCH.cpp | 9 +- 6 files changed, 162 insertions(+), 158 deletions(-) diff --git a/NXDNControl.cpp b/NXDNControl.cpp index fb02259..7b009aa 100644 --- a/NXDNControl.cpp +++ b/NXDNControl.cpp @@ -93,7 +93,7 @@ bool CNXDNControl::writeModem(unsigned char *data, unsigned int len) if (m_rssi != 0U) LogMessage("NXDN, transmission lost, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); else - LogMessage("NXDN, transmission lost, %.1f seconds, BER: %.1f%%", float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits)); + LogMessage("NXDN, transmission lost, %.1f seconds, BER: %.1f%%", float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits)); writeEndRF(); return false; } @@ -174,6 +174,8 @@ bool CNXDNControl::processVoice(unsigned char usc, unsigned char option, unsigne unsigned char ran = sacch.getRAN(); if (ran != m_ran && ran != 0U) return false; + } else if (m_rfState == RS_RF_LISTENING) { + // return false; } // XXX Reconstruct invalid LICH @@ -184,161 +186,159 @@ bool CNXDNControl::processVoice(unsigned char usc, unsigned char option, unsigne bool valid = facch.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS); if (!valid) valid = facch.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS + NXDN_FACCH1_LENGTH_BITS); - - if (valid) { - unsigned char buffer[10U]; - facch.getData(buffer); - - CNXDNLayer3 layer3; - layer3.decode(buffer, NXDN_FACCH1_LENGTH_BITS); - - unsigned char type = layer3.getMessageType(); - if (type == NXDN_MESSAGE_TYPE_TX_REL) { - if (m_rfState != RS_RF_AUDIO) { - m_rfState = RS_RF_LISTENING; - m_rfMask = 0x00U; - return false; - } - } else { - if (m_selfOnly) { - unsigned short srcId = layer3.getSourceUnitId(); - if (srcId != m_id) { - m_rfState = RS_RF_REJECTED; - return false; - } - } - } - - data[0U] = type == NXDN_MESSAGE_TYPE_TX_REL ? TAG_EOT : TAG_DATA; - data[1U] = 0x00U; - - CSync::addNXDNSync(data + 2U); - - CNXDNLICH lich = m_rfLastLICH; - lich.setDirection(m_remoteGateway ? NXDN_LICH_DIRECTION_INBOUND : NXDN_LICH_DIRECTION_OUTBOUND); - lich.encode(data + 2U); - - CNXDNSACCH sacch; - sacch.setRAN(m_ran); - sacch.setStructure(NXDN_SR_SINGLE); - sacch.setData(SACCH_IDLE); - sacch.encode(data + 2U); - - facch.encode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS); - facch.encode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS + NXDN_FACCH1_LENGTH_BITS); - - scrambler(data + 2U); - - // writeNetwork(data, m_rfFrames, ); - -#if defined(DUMP_NXDN) - writeFile(data + 2U); -#endif - if (m_duplex) - writeQueueRF(data); - - if (type == NXDN_MESSAGE_TYPE_TX_REL) { - m_rfFrames++; - if (m_rssi != 0U) - LogMessage("NXDN, received RF end of transmission, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); - else - LogMessage("NXDN, received RF end of transmission, %.1f seconds, BER: %.1f%%", float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits)); - writeEndRF(); - return true; - } else { - m_rfFrames = 0U; - m_rfErrs = 0U; - m_rfBits = 1U; - m_rfTimeoutTimer.start(); - m_rfState = RS_RF_AUDIO; - - m_minRSSI = m_rssi; - m_maxRSSI = m_rssi; - m_aveRSSI = m_rssi; - m_rssiCount = 1U; -#if defined(DUMP_NXDN) - openFile(); -#endif - m_rfLayer3 = layer3; - - unsigned short srcId = m_rfLayer3.getSourceUnitId(); - unsigned short dstId = m_rfLayer3.getDestinationGroupId(); - bool grp = m_rfLayer3.getIsGroup(); - - std::string source = m_lookup->find(srcId); - LogMessage("NXDN, received RF voice transmission from %s to %s%u", source.c_str(), grp ? "TG " : "", dstId); - m_display->writeNXDN(source.c_str(), grp, dstId, "R"); - - m_rfState = RS_RF_AUDIO; - - return true; - } - } - - return false; - } else { - unsigned char message[3U]; - sacch.getData(message); - - unsigned char structure = sacch.getStructure(); - switch (structure) { - case NXDN_SR_1_4: - m_rfMask |= 0x01U; - m_rfLayer3.decode(message, 18U, 0U); - break; - case NXDN_SR_2_4: - m_rfMask |= 0x02U; - m_rfLayer3.decode(message, 18U, 18U); - break; - case NXDN_SR_3_4: - m_rfMask |= 0x04U; - m_rfLayer3.decode(message, 18U, 36U); - break; - case NXDN_SR_4_4: - m_rfMask |= 0x08U; - m_rfLayer3.decode(message, 18U, 54U); - break; - default: - break; - } - - // if (m_rfMask != 0x0FU) + // if (!valid) // return false; - unsigned char messageType = m_rfLayer3.getMessageType(); - if (messageType != NXDN_MESSAGE_TYPE_VCALL) - return false; + unsigned char buffer[10U]; + facch.getData(buffer); - unsigned short srcId = m_rfLayer3.getSourceUnitId(); - unsigned short dstId = m_rfLayer3.getDestinationGroupId(); - bool grp = m_rfLayer3.getIsGroup(); + CNXDNLayer3 layer3; + layer3.decode(buffer, NXDN_FACCH1_LENGTH_BITS); - if (m_selfOnly) { - if (srcId != m_id) { - m_rfState = RS_RF_REJECTED; + unsigned char type = layer3.getMessageType(); + if (type == NXDN_MESSAGE_TYPE_TX_REL) { + if (m_rfState != RS_RF_AUDIO) { + m_rfState = RS_RF_LISTENING; + m_rfMask = 0x00U; return false; } + } else { + bool hasInfo = layer3.getHasInfo(); + if (m_rfState == RS_RF_LISTENING && m_selfOnly && hasInfo) { + unsigned short srcId = layer3.getSourceUnitId(); + if (srcId != m_id) { + m_rfState = RS_RF_REJECTED; + return false; + } + } } - m_rfFrames = 0U; - m_rfErrs = 0U; - m_rfBits = 1U; - m_rfTimeoutTimer.start(); - m_rfState = RS_RF_AUDIO; + data[0U] = type == NXDN_MESSAGE_TYPE_TX_REL ? TAG_EOT : TAG_DATA; + data[1U] = 0x00U; + + CSync::addNXDNSync(data + 2U); + + CNXDNLICH lich = m_rfLastLICH; + lich.setDirection(m_remoteGateway ? NXDN_LICH_DIRECTION_INBOUND : NXDN_LICH_DIRECTION_OUTBOUND); + lich.encode(data + 2U); + + CNXDNSACCH sacch; + sacch.setRAN(m_ran); + sacch.setStructure(NXDN_SR_SINGLE); + sacch.setData(SACCH_IDLE); + sacch.encode(data + 2U); + + facch.encode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS); + facch.encode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS + NXDN_FACCH1_LENGTH_BITS); + + scrambler(data + 2U); + + // writeNetwork(data, m_rfFrames, ); - m_minRSSI = m_rssi; - m_maxRSSI = m_rssi; - m_aveRSSI = m_rssi; - m_rssiCount = 1U; #if defined(DUMP_NXDN) - openFile(); + writeFile(data + 2U); #endif - std::string source = m_lookup->find(srcId); - LogMessage("NXDN, received RF voice transmission from %s to %s%u", source.c_str(), grp ? "TG " : "", dstId); - m_display->writeNXDN(source.c_str(), grp, dstId, "R"); + if (m_duplex) + writeQueueRF(data); - m_rfState = RS_RF_AUDIO; + if (type == NXDN_MESSAGE_TYPE_TX_REL) { + m_rfFrames++; + if (m_rssi != 0U) + LogMessage("NXDN, received RF end of transmission, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); + else + LogMessage("NXDN, received RF end of transmission, %.1f seconds, BER: %.1f%%", float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits)); + writeEndRF(); + } else { + m_rfFrames = 0U; + m_rfErrs = 0U; + m_rfBits = 1U; + m_rfTimeoutTimer.start(); + m_rfState = RS_RF_AUDIO; + m_minRSSI = m_rssi; + m_maxRSSI = m_rssi; + m_aveRSSI = m_rssi; + m_rssiCount = 1U; +#if defined(DUMP_NXDN) + openFile(); +#endif + m_rfLayer3 = layer3; + + unsigned short srcId = m_rfLayer3.getSourceUnitId(); + unsigned short dstId = m_rfLayer3.getDestinationGroupId(); + bool grp = m_rfLayer3.getIsGroup(); + + std::string source = m_lookup->find(srcId); + LogMessage("NXDN, received RF voice transmission from %s to %s%u", source.c_str(), grp ? "TG " : "", dstId); + m_display->writeNXDN(source.c_str(), grp, dstId, "R"); + } + + return true; } + else { + // if (valid) { + unsigned char message[3U]; + sacch.getData(message); + + unsigned char structure = sacch.getStructure(); + switch (structure) { + case NXDN_SR_1_4: + m_rfMask |= 0x01U; + m_rfLayer3.decode(message, 18U, 0U); + break; + case NXDN_SR_2_4: + m_rfMask |= 0x02U; + m_rfLayer3.decode(message, 18U, 18U); + break; + case NXDN_SR_3_4: + m_rfMask |= 0x04U; + m_rfLayer3.decode(message, 18U, 36U); + break; + case NXDN_SR_4_4: + m_rfMask |= 0x08U; + m_rfLayer3.decode(message, 18U, 54U); + break; + default: + break; + } + + // if (m_rfMask != 0x0FU) + // return false; + + unsigned char messageType = m_rfLayer3.getMessageType(); + if (messageType != NXDN_MESSAGE_TYPE_VCALL) + return false; + + unsigned short srcId = m_rfLayer3.getSourceUnitId(); + unsigned short dstId = m_rfLayer3.getDestinationGroupId(); + bool grp = m_rfLayer3.getIsGroup(); + + if (m_selfOnly) { + if (srcId != m_id) { + m_rfState = RS_RF_REJECTED; + return false; + } + } + + m_rfFrames = 0U; + m_rfErrs = 0U; + m_rfBits = 1U; + m_rfTimeoutTimer.start(); + m_rfState = RS_RF_AUDIO; + + m_minRSSI = m_rssi; + m_maxRSSI = m_rssi; + m_aveRSSI = m_rssi; + m_rssiCount = 1U; +#if defined(DUMP_NXDN) + openFile(); +#endif + std::string source = m_lookup->find(srcId); + LogMessage("NXDN, received RF voice transmission from %s to %s%u", source.c_str(), grp ? "TG " : "", dstId); + m_display->writeNXDN(source.c_str(), grp, dstId, "R"); + + m_rfState = RS_RF_AUDIO; + } + // } // if (m_rfState == RS_RF_AUDIO) { // Regenerate the sync diff --git a/NXDNFACCH1.cpp b/NXDNFACCH1.cpp index 48f4639..8d3ad45 100644 --- a/NXDNFACCH1.cpp +++ b/NXDNFACCH1.cpp @@ -42,7 +42,8 @@ const unsigned int INTERLEAVE_TABLE[] = { const unsigned int PUNCTURE_LIST[] = { 1U, 5U, 9U, 13U, 17U, 21U, 25U, 29U, 33U, 37U, 41U, 45U, 49U, 53U, 57U, 61U, 65U, 69U, 73U, 77U, 81U, 85U, 89U, 93U, 97U, 101U, 105U, 109U, 113U, 117U, - 121U, 125U, 129U, 133U, 137U, 141U}; + 121U, 125U, 129U, 133U, 137U, 141U, 145U, 149U, 153U, 157U, + 161U, 165U, 169U, 173U, 177U, 181U, 185U, 189U }; const unsigned char BIT_MASK_TABLE[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U }; @@ -121,11 +122,7 @@ void CNXDNFACCH1::encode(unsigned char* data, unsigned int offset) const unsigned char temp1[12U]; ::memset(temp1, 0x00U, 12U); - - for (unsigned int i = 0U; i < 80U; i++) { - bool b = READ_BIT1(m_data, i); - WRITE_BIT1(temp1, i, b); - } + ::memcpy(temp1, data, 10U); CNXDNCRC::encodeCRC12(temp1, 80U); diff --git a/NXDNLayer3.cpp b/NXDNLayer3.cpp index f4da16b..dce3d17 100644 --- a/NXDNLayer3.cpp +++ b/NXDNLayer3.cpp @@ -93,6 +93,15 @@ unsigned char CNXDNLayer3::getCallOptions() const return m_data[2U] & 0x1FU; } +bool CNXDNLayer3::getHasInfo() const +{ + unsigned char type = getMessageType(); + + return type != NXDN_MESSAGE_TYPE_IDLE && + type != NXDN_MESSAGE_TYPE_VCALL_IV && + type != NXDN_MESSAGE_TYPE_SDCALL_IV; +} + CNXDNLayer3& CNXDNLayer3::operator=(const CNXDNLayer3& layer3) { if (&layer3 != this) diff --git a/NXDNLayer3.h b/NXDNLayer3.h index 81aff2b..bd4ba6a 100644 --- a/NXDNLayer3.h +++ b/NXDNLayer3.h @@ -34,6 +34,7 @@ public: unsigned short getDestinationGroupId() const; bool getIsGroup() const; unsigned char getCallOptions() const; + bool getHasInfo() const; CNXDNLayer3& operator=(const CNXDNLayer3& layer3); diff --git a/NXDNSACCH.cpp b/NXDNSACCH.cpp index 304b20d..06d3e26 100755 --- a/NXDNSACCH.cpp +++ b/NXDNSACCH.cpp @@ -123,14 +123,14 @@ void CNXDNSACCH::encode(unsigned char* data) const CNXDNCRC::encodeCRC6(temp1, 26U); - CUtils::dump("NXDN, SACCH encoded with CRC", temp1, 4U); + CUtils::dump("NXDN, SACCH encoded with CRC", temp1, 5U); - unsigned char temp2[8U]; + unsigned char temp2[9U]; CNXDNConvolution conv; conv.encode(temp1, temp2, 36U); - // CUtils::dump("NXDN, SACCH convolved", temp2, 8U); + // CUtils::dump("NXDN, SACCH convolved", temp2, 9U); unsigned char temp3[8U]; diff --git a/NXDNUDCH.cpp b/NXDNUDCH.cpp index e58460e..6385edc 100644 --- a/NXDNUDCH.cpp +++ b/NXDNUDCH.cpp @@ -63,7 +63,8 @@ const unsigned int PUNCTURE_LIST[] = { 3U, 11U, 17U, 25U, 31U, 39U, 45U, 73U, 81U, 87U, 95U, 101U, 109U, 115U, 123U, 129U, 137U, 143U, 151U, 157U, 165U, 171U, 179U, 185U, 193U, 199U, 207U, 213U, 221U, 227U, 235U, 241U, 249U, 255U, 263U, 269U, 277U, - 283U, 291U, 297U, 305U, 311U, 319U, 325U, 333U, 339U, 347U }; + 283U, 291U, 297U, 305U, 311U, 319U, 325U, 333U, 339U, 347U, + 353U, 361U, 367U, 375U, 381U, 389U, 395U, 403U }; const unsigned char BIT_MASK_TABLE[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U }; @@ -142,11 +143,7 @@ void CNXDNUDCH::encode(unsigned char* data) const unsigned char temp1[25U]; ::memset(temp1, 0x00U, 25U); - - for (unsigned int i = 0U; i < 184U; i++) { - bool b = READ_BIT1(m_data, i); - WRITE_BIT1(temp1, i, b); - } + ::memcpy(temp1, data, 23U); CNXDNCRC::encodeCRC15(temp1, 184U);