bool CDVAPController::writeHeader(const CHeaderData& header) { m_streamId++; unsigned char buffer[50U]; ::memcpy(buffer, DVAP_HEADER, DVAP_HEADER_LEN); wxUint16 sid = wxUINT16_SWAP_ON_BE(m_streamId); ::memcpy(buffer + 2U, &sid, sizeof(wxUint16)); buffer[4U] = 0x80U; buffer[5U] = 0U; ::memset(buffer + 6U, ' ', RADIO_HEADER_LENGTH_BYTES); buffer[6U] = header.getFlag1(); buffer[7U] = header.getFlag2(); buffer[8U] = header.getFlag3(); wxString rpt2 = header.getRptCall2(); for (unsigned int i = 0U; i < rpt2.Len() && i < LONG_CALLSIGN_LENGTH; i++) buffer[i + 9U] = rpt2.GetChar(i); wxString rpt1 = header.getRptCall1(); for (unsigned int i = 0U; i < rpt1.Len() && i < LONG_CALLSIGN_LENGTH; i++) buffer[i + 17U] = rpt1.GetChar(i); wxString your = header.getYourCall(); for (unsigned int i = 0U; i < your.Len() && i < LONG_CALLSIGN_LENGTH; i++) buffer[i + 25U] = your.GetChar(i); wxString my1 = header.getMyCall1(); for (unsigned int i = 0U; i < my1.Len() && i < LONG_CALLSIGN_LENGTH; i++) buffer[i + 33U] = my1.GetChar(i); wxString my2 = header.getMyCall2(); for (unsigned int i = 0U; i < my2.Len() && i < SHORT_CALLSIGN_LENGTH; i++) buffer[i + 41U] = my2.GetChar(i); CCCITTChecksumReverse cksum; cksum.update(buffer + 6U, RADIO_HEADER_LENGTH_BYTES - 2U); cksum.result(buffer + 45U); m_framePos = 0U; m_seq = 0U; wxMutexLocker locker(m_mutex); unsigned int space = m_txData.freeSpace(); if (space < 48U) return false; unsigned char len = DVAP_HEADER_LEN; m_txData.addData(&len, 1U); m_txData.addData(buffer, DVAP_HEADER_LEN); return true; }
bool CGatewayProtocolHandler::writeHeader(const unsigned char* header, wxUint16 id, const in_addr& address, unsigned int port) { unsigned char buffer[50U]; buffer[0] = 'D'; buffer[1] = 'S'; buffer[2] = 'R'; buffer[3] = 'P'; buffer[4] = 0x20U; buffer[5] = id / 256U; // Unique session id buffer[6] = id % 256U; buffer[7] = 0U; ::memcpy(buffer + 8U, header + 0U, RADIO_HEADER_LENGTH_BYTES - 2U); // Get the checksum for the header CCCITTChecksumReverse csum; csum.update(buffer + 8U, RADIO_HEADER_LENGTH_BYTES - 2U); csum.result(buffer + 8U + RADIO_HEADER_LENGTH_BYTES - 2U); #if defined(DUMP_TX) CUtils::dump(wxT("Sending Header"), buffer, 49U); #endif for (unsigned int i = 0U; i < 4U; i++) { bool ret = m_socket.write(buffer, 49U, address, port); if (!ret) return false; } return true; }
bool CSplitRepeaterHeaderData::setRepeaterData(const unsigned char *data, unsigned int length, bool check, const in_addr& address, unsigned int port) { wxASSERT(data != NULL); wxASSERT(length >= 49U); m_id = data[5U] * 256U + data[6U]; m_errors = data[7U]; m_flag1 = data[8U]; m_flag2 = data[9U]; m_flag3 = data[10U]; ::memcpy(m_rptCall2, data + 11U, LONG_CALLSIGN_LENGTH); ::memcpy(m_rptCall1, data + 19U, LONG_CALLSIGN_LENGTH); ::memcpy(m_yourCall, data + 27U, LONG_CALLSIGN_LENGTH); ::memcpy(m_myCall1, data + 35U, LONG_CALLSIGN_LENGTH); ::memcpy(m_myCall2, data + 43U, SHORT_CALLSIGN_LENGTH); m_address = address; m_port = port; if (check) { CCCITTChecksumReverse cksum; cksum.update(data + 8U, RADIO_HEADER_LENGTH_BYTES - 2U); bool valid = cksum.check(data + 8U + RADIO_HEADER_LENGTH_BYTES - 2U); return valid; } else { return true; } }
unsigned int CGatewayProtocolHandler::readHeader(unsigned char* buffer, unsigned int length) { if (m_type != NETWORK_HEADER) return 0U; // If the checksum is 0xFFFF then we accept the header without testing the checksum if (m_buffer[47U] == 0xFFU && m_buffer[48U] == 0xFFU) { ::memcpy(buffer, m_buffer + 8U, RADIO_HEADER_LENGTH_BYTES); return RADIO_HEADER_LENGTH_BYTES; } // Get the checksum for the header CCCITTChecksumReverse csum; csum.update(m_buffer + 8U, RADIO_HEADER_LENGTH_BYTES - 2U); bool check = csum.check(m_buffer + 8U + RADIO_HEADER_LENGTH_BYTES - 2U); if (!check) { CUtils::dump(wxT("Header checksum failure from the Repeater"), m_buffer + 8U, RADIO_HEADER_LENGTH_BYTES); return 0U; } ::memcpy(buffer, m_buffer + 8U, RADIO_HEADER_LENGTH_BYTES); return RADIO_HEADER_LENGTH_BYTES; }
bool CRepeaterProtocolHandler::writeHeader(const CHeaderData& header) { unsigned char buffer[50U]; buffer[0] = 'D'; buffer[1] = 'S'; buffer[2] = 'R'; buffer[3] = 'P'; buffer[4] = 0x20U; // Create a random id for this transmission m_outId = (::rand() % 65535U) + 1U; buffer[5] = m_outId / 256U; // Unique session id buffer[6] = m_outId % 256U; buffer[7] = 0U; buffer[8] = header.getFlag1(); buffer[9] = header.getFlag2(); buffer[10] = header.getFlag3(); for (unsigned int i = 0U; i < LONG_CALLSIGN_LENGTH; i++) buffer[11 + i] = header.getRptCall1().GetChar(i); for (unsigned int i = 0U; i < LONG_CALLSIGN_LENGTH; i++) buffer[19 + i] = header.getRptCall2().GetChar(i); for (unsigned int i = 0U; i < LONG_CALLSIGN_LENGTH; i++) buffer[27 + i] = header.getYourCall().GetChar(i); for (unsigned int i = 0U; i < LONG_CALLSIGN_LENGTH; i++) buffer[35 + i] = header.getMyCall1().GetChar(i); for (unsigned int i = 0U; i < SHORT_CALLSIGN_LENGTH; i++) buffer[43 + i] = header.getMyCall2().GetChar(i); // Get the checksum for the header CCCITTChecksumReverse csum; csum.update(buffer + 8U, 4U * LONG_CALLSIGN_LENGTH + SHORT_CALLSIGN_LENGTH + 3U); csum.result(buffer + 47U); m_outSeq = 0U; #if defined(DUMP_TX) CUtils::dump(wxT("Sending Header"), buffer, 49U); return true; #else for (unsigned int i = 0U; i < 2U; i++) { bool ret = m_socket.write(buffer, 49U); if (!ret) return false; } return true; #endif }
bool CSplitRepeaterHeaderData::setData(const unsigned char *data, unsigned int length) { wxASSERT(data != NULL); wxASSERT(length >= RADIO_HEADER_LENGTH_BYTES); m_flag1 = data[0U]; m_flag2 = data[1U]; m_flag3 = data[2U]; ::memcpy(m_rptCall2, data + 3U, LONG_CALLSIGN_LENGTH); ::memcpy(m_rptCall1, data + 11U, LONG_CALLSIGN_LENGTH); ::memcpy(m_yourCall, data + 19U, LONG_CALLSIGN_LENGTH); ::memcpy(m_myCall1, data + 27U, LONG_CALLSIGN_LENGTH); ::memcpy(m_myCall2, data + 35U, SHORT_CALLSIGN_LENGTH); CCCITTChecksumReverse cksum; cksum.update(data, RADIO_HEADER_LENGTH_BYTES - 2U); return cksum.check(data + RADIO_HEADER_LENGTH_BYTES - 2U); }
unsigned int CSplitRepeaterHeaderData::getData(unsigned char *data, unsigned int length) const { wxASSERT(data != NULL); wxASSERT(length >= RADIO_HEADER_LENGTH_BYTES); data[0] = m_flag1; // Flags 1, 2, and 3 data[1] = m_flag2; data[2] = m_flag3; ::memcpy(data + 3U, m_rptCall2, LONG_CALLSIGN_LENGTH); ::memcpy(data + 11U, m_rptCall1, LONG_CALLSIGN_LENGTH); ::memcpy(data + 19U, m_yourCall, LONG_CALLSIGN_LENGTH); ::memcpy(data + 27U, m_myCall1, LONG_CALLSIGN_LENGTH); ::memcpy(data + 35U, m_myCall2, SHORT_CALLSIGN_LENGTH); CCCITTChecksumReverse csum; csum.update(data, RADIO_HEADER_LENGTH_BYTES - 2U); csum.result(data + RADIO_HEADER_LENGTH_BYTES - 2U); return RADIO_HEADER_LENGTH_BYTES; }
bool CSlowDataDecoder::processHeader(const unsigned char* bytes) { unsigned char buffer[RADIO_HEADER_LENGTH_BYTES]; // Clean up the header data for (unsigned int n = 0U; n < RADIO_HEADER_LENGTH_BYTES; n++) { switch (n) { case 0U: // Flag 1 // Only allow BK and EMR bits and always assert the repeater bit buffer[n] = (bytes[n] & (INTERRUPTED_MASK | URGENT_MASK)) | REPEATER_MASK; break; case 1U: // Flag 2 case 2U: // Flag 3 // Always 0x00 in current implementations buffer[n] = 0x00; break; case 39U: // Checksum 1 case 40U: // Checksum 2 // These bytes can be any value buffer[n] = bytes[n]; break; default: // Callsign text // Only ASCII text so MSB is always clear buffer[n] = bytes[n] & 0x7F; break; } } CCCITTChecksumReverse cksum; cksum.update(buffer, RADIO_HEADER_LENGTH_BYTES - 2U); bool valid = cksum.check(buffer + RADIO_HEADER_LENGTH_BYTES - 2U); if (!valid) return false; // The checksum has already been checked m_header = new CHeaderData(buffer, RADIO_HEADER_LENGTH_BYTES, false); return true; }
unsigned int CSplitRepeaterHeaderData::getRepeaterData(unsigned char *data, unsigned int length, bool check) const { wxASSERT(data != NULL); wxASSERT(length >= 49U); data[0] = 'D'; data[1] = 'S'; data[2] = 'R'; data[3] = 'P'; data[4] = 0x20U; data[5] = m_id / 256U; // Unique session id data[6] = m_id % 256U; data[7] = 0U; data[8] = m_flag1; // Flags 1, 2, and 3 data[9] = m_flag2; data[10] = m_flag3; ::memcpy(data + 11U, m_rptCall2, LONG_CALLSIGN_LENGTH); ::memcpy(data + 19U, m_rptCall1, LONG_CALLSIGN_LENGTH); ::memcpy(data + 27U, m_yourCall, LONG_CALLSIGN_LENGTH); ::memcpy(data + 35U, m_myCall1, LONG_CALLSIGN_LENGTH); ::memcpy(data + 43U, m_myCall2, SHORT_CALLSIGN_LENGTH); if (check) { CCCITTChecksumReverse csum; csum.update(data + 8U, 4U * LONG_CALLSIGN_LENGTH + SHORT_CALLSIGN_LENGTH + 3U); csum.result(data + 47U); } else { data[47] = 0xFF; data[48] = 0xFF; } return 49U; }
CRadioHeaderEncoder::CRadioHeaderEncoder(const CHeaderData& header) : m_header(NULL) { m_header = new bool[FEC_SECTION_LENGTH_BITS]; bool* buffer1 = new bool[700U]; bool* buffer2 = new bool[700U]; // Clear everything ::memset(buffer1, 0x00, 700U * sizeof(bool)); // Flag 1 unsigned char flag1 = header.getFlag1(); buffer1[0] = (flag1 & 0x80U) == 0x80U; buffer1[1] = (flag1 & 0x40U) == 0x40U; buffer1[2] = (flag1 & 0x20U) == 0x20U; buffer1[3] = (flag1 & 0x10U) == 0x10U; buffer1[4] = (flag1 & 0x08U) == 0x08U; buffer1[5] = (flag1 & 0x04U) == 0x04U; buffer1[6] = (flag1 & 0x02U) == 0x02U; buffer1[7] = (flag1 & 0x01U) == 0x01U; // Flag 2 unsigned char flag2 = header.getFlag2(); buffer1[8] = (flag2 & 0x80U) == 0x80U; buffer1[9] = (flag2 & 0x40U) == 0x40U; buffer1[10] = (flag2 & 0x20U) == 0x20U; buffer1[11] = (flag2 & 0x10U) == 0x10U; buffer1[12] = (flag2 & 0x08U) == 0x08U; buffer1[13] = (flag2 & 0x04U) == 0x04U; buffer1[14] = (flag2 & 0x02U) == 0x02U; buffer1[15] = (flag2 & 0x01U) == 0x01U; // Flag 3 unsigned char flag3 = header.getFlag3(); buffer1[16] = (flag3 & 0x80U) == 0x80U; buffer1[17] = (flag3 & 0x40U) == 0x40U; buffer1[18] = (flag3 & 0x20U) == 0x20U; buffer1[19] = (flag3 & 0x10U) == 0x10U; buffer1[20] = (flag3 & 0x08U) == 0x08U; buffer1[21] = (flag3 & 0x04U) == 0x04U; buffer1[22] = (flag3 & 0x02U) == 0x02U; buffer1[23] = (flag3 & 0x01U) == 0x01U; unsigned int n = 24U; stringToBits(header.getRptCall2(), buffer1 + n, LONG_CALLSIGN_LENGTH); n += LONG_CALLSIGN_LENGTH * 8U; stringToBits(header.getRptCall1(), buffer1 + n, LONG_CALLSIGN_LENGTH); n += LONG_CALLSIGN_LENGTH * 8U; stringToBits(header.getYourCall(), buffer1 + n, LONG_CALLSIGN_LENGTH); n += LONG_CALLSIGN_LENGTH * 8U; stringToBits(header.getMyCall1(), buffer1 + n, LONG_CALLSIGN_LENGTH); n += LONG_CALLSIGN_LENGTH * 8U; stringToBits(header.getMyCall2(), buffer1 + n, SHORT_CALLSIGN_LENGTH); n += SHORT_CALLSIGN_LENGTH * 8U; CCCITTChecksumReverse cksum; for (unsigned int i = 0U; i < n; i += 8U) cksum.update(buffer1 + i); cksum.result(buffer1 + n); // CUtils::dump(wxT("TX Raw Data"), buffer1, n + 16U); unsigned int length; CDStarFECEncoder fec; fec.encode(buffer1, buffer2, RADIO_HEADER_LENGTH_BITS, length); // CUtils::dump(wxT("TX After FEC"), buffer2, FEC_SECTION_LENGTH_BITS); CDStarInterleaver interleaver; interleaver.interleave(buffer2, m_header, FEC_SECTION_LENGTH_BITS); // CUtils::dump(wxT("TX After Interleaver"), m_header, FEC_SECTION_LENGTH_BITS); CDStarScrambler scrambler; scrambler.process(m_header, FEC_SECTION_LENGTH_BITS); // CUtils::dump(wxT("TX After Scrambler"), m_header, FEC_SECTION_LENGTH_BITS); delete[] buffer1; delete[] buffer2; }