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;
}
Beispiel #8
0
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;
}