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 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;
	}
}
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);
}
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;
}