mirror of
https://github.com/g4klx/ircDDBGateway.git
synced 2025-12-06 05:32:02 +01:00
952 lines
24 KiB
C++
952 lines
24 KiB
C++
/*
|
|
* Copyright (C) 2010-2014 by Jonathan Naylor G4KLX
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
|
|
#include "HeaderData.h"
|
|
|
|
#include <wx/datetime.h>
|
|
|
|
#include "CCITTChecksum.h"
|
|
#include "DStarDefines.h"
|
|
#include "Utils.h"
|
|
|
|
void CHeaderData::initialise()
|
|
{
|
|
wxDateTime now = wxDateTime::UNow();
|
|
::srand(now.GetMillisecond());
|
|
}
|
|
|
|
void CHeaderData::finalise()
|
|
{
|
|
}
|
|
|
|
unsigned int CHeaderData::createId()
|
|
{
|
|
return (::rand() % 65535U) + 1U;
|
|
}
|
|
|
|
CHeaderData::CHeaderData() :
|
|
m_rptSeq(0U),
|
|
m_id(0U),
|
|
m_band1(0x00U),
|
|
m_band2(0x02U),
|
|
m_band3(0x01U),
|
|
m_flag1(0U),
|
|
m_flag2(0U),
|
|
m_flag3(0U),
|
|
m_myCall1(NULL),
|
|
m_myCall2(NULL),
|
|
m_yourCall(NULL),
|
|
m_rptCall1(NULL),
|
|
m_rptCall2(NULL),
|
|
m_yourAddress(),
|
|
m_yourPort(0U),
|
|
m_myPort(0U),
|
|
m_errors(0U)
|
|
{
|
|
m_myCall1 = new unsigned char[LONG_CALLSIGN_LENGTH];
|
|
m_myCall2 = new unsigned char[SHORT_CALLSIGN_LENGTH];
|
|
m_yourCall = new unsigned char[LONG_CALLSIGN_LENGTH];
|
|
m_rptCall1 = new unsigned char[LONG_CALLSIGN_LENGTH];
|
|
m_rptCall2 = new unsigned char[LONG_CALLSIGN_LENGTH];
|
|
|
|
::memset(m_rptCall1, ' ', LONG_CALLSIGN_LENGTH);
|
|
::memset(m_rptCall2, ' ', LONG_CALLSIGN_LENGTH);
|
|
::memset(m_yourCall, ' ', LONG_CALLSIGN_LENGTH);
|
|
::memset(m_myCall1, ' ', LONG_CALLSIGN_LENGTH);
|
|
::memset(m_myCall2, ' ', SHORT_CALLSIGN_LENGTH);
|
|
}
|
|
|
|
CHeaderData::CHeaderData(const CHeaderData& header) :
|
|
m_rptSeq(header.m_rptSeq),
|
|
m_id(header.m_id),
|
|
m_band1(header.m_band1),
|
|
m_band2(header.m_band2),
|
|
m_band3(header.m_band3),
|
|
m_flag1(header.m_flag1),
|
|
m_flag2(header.m_flag2),
|
|
m_flag3(header.m_flag3),
|
|
m_myCall1(NULL),
|
|
m_myCall2(NULL),
|
|
m_yourCall(NULL),
|
|
m_rptCall1(NULL),
|
|
m_rptCall2(NULL),
|
|
m_yourAddress(header.m_yourAddress),
|
|
m_yourPort(header.m_yourPort),
|
|
m_myPort(header.m_myPort),
|
|
m_errors(header.m_errors)
|
|
{
|
|
m_myCall1 = new unsigned char[LONG_CALLSIGN_LENGTH];
|
|
m_myCall2 = new unsigned char[SHORT_CALLSIGN_LENGTH];
|
|
m_yourCall = new unsigned char[LONG_CALLSIGN_LENGTH];
|
|
m_rptCall1 = new unsigned char[LONG_CALLSIGN_LENGTH];
|
|
m_rptCall2 = new unsigned char[LONG_CALLSIGN_LENGTH];
|
|
|
|
::memcpy(m_myCall1, header.m_myCall1, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(m_myCall2, header.m_myCall2, SHORT_CALLSIGN_LENGTH);
|
|
::memcpy(m_yourCall, header.m_yourCall, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(m_rptCall1, header.m_rptCall1, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(m_rptCall2, header.m_rptCall2, LONG_CALLSIGN_LENGTH);
|
|
}
|
|
|
|
CHeaderData::CHeaderData(const wxString& myCall1, const wxString& myCall2, const wxString& yourCall,
|
|
const wxString& rptCall1, const wxString& rptCall2, unsigned char flag1,
|
|
unsigned char flag2, unsigned char flag3) :
|
|
m_rptSeq(0U),
|
|
m_id(0U),
|
|
m_band1(0U),
|
|
m_band2(0U),
|
|
m_band3(0U),
|
|
m_flag1(flag1),
|
|
m_flag2(flag2),
|
|
m_flag3(flag3),
|
|
m_myCall1(NULL),
|
|
m_myCall2(NULL),
|
|
m_yourCall(NULL),
|
|
m_rptCall1(NULL),
|
|
m_rptCall2(NULL),
|
|
m_yourAddress(),
|
|
m_yourPort(0U),
|
|
m_myPort(0U),
|
|
m_errors(0U)
|
|
{
|
|
m_myCall1 = new unsigned char[LONG_CALLSIGN_LENGTH];
|
|
m_myCall2 = new unsigned char[SHORT_CALLSIGN_LENGTH];
|
|
m_yourCall = new unsigned char[LONG_CALLSIGN_LENGTH];
|
|
m_rptCall1 = new unsigned char[LONG_CALLSIGN_LENGTH];
|
|
m_rptCall2 = new unsigned char[LONG_CALLSIGN_LENGTH];
|
|
|
|
::memset(m_myCall1, ' ', LONG_CALLSIGN_LENGTH);
|
|
::memset(m_myCall2, ' ', SHORT_CALLSIGN_LENGTH);
|
|
::memset(m_yourCall, ' ', LONG_CALLSIGN_LENGTH);
|
|
::memset(m_rptCall1, ' ', LONG_CALLSIGN_LENGTH);
|
|
::memset(m_rptCall2, ' ', LONG_CALLSIGN_LENGTH);
|
|
|
|
for (unsigned int i = 0U; i < myCall1.Len() && i < LONG_CALLSIGN_LENGTH; i++)
|
|
m_myCall1[i] = myCall1.GetChar(i);
|
|
|
|
for (unsigned int i = 0U; i < myCall2.Len() && i < SHORT_CALLSIGN_LENGTH; i++)
|
|
m_myCall2[i] = myCall2.GetChar(i);
|
|
|
|
for (unsigned int i = 0U; i < yourCall.Len() && i < LONG_CALLSIGN_LENGTH; i++)
|
|
m_yourCall[i] = yourCall.GetChar(i);
|
|
|
|
for (unsigned int i = 0U; i < rptCall1.Len() && i < LONG_CALLSIGN_LENGTH; i++)
|
|
m_rptCall1[i] = rptCall1.GetChar(i);
|
|
|
|
for (unsigned int i = 0U; i < rptCall2.Len() && i < LONG_CALLSIGN_LENGTH; i++)
|
|
m_rptCall2[i] = rptCall2.GetChar(i);
|
|
}
|
|
|
|
CHeaderData::~CHeaderData()
|
|
{
|
|
delete[] m_myCall1;
|
|
delete[] m_myCall2;
|
|
delete[] m_yourCall;
|
|
delete[] m_rptCall1;
|
|
delete[] m_rptCall2;
|
|
}
|
|
|
|
bool CHeaderData::setIcomRepeaterData(const unsigned char *data, unsigned int length, bool check, const in_addr& yourAddress, unsigned int yourPort)
|
|
{
|
|
wxASSERT(data != NULL);
|
|
wxASSERT(length >= 58U);
|
|
|
|
m_rptSeq = data[4] * 256U + data[5];
|
|
m_band1 = data[11];
|
|
m_band2 = data[12];
|
|
m_band3 = data[13];
|
|
m_id = data[14] * 256U + data[15];
|
|
|
|
m_flag1 = data[17U];
|
|
m_flag2 = data[18U];
|
|
m_flag3 = data[19U];
|
|
|
|
::memcpy(m_rptCall2, data + 20U, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(m_rptCall1, data + 28U, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(m_yourCall, data + 36U, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(m_myCall1, data + 44U, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(m_myCall2, data + 52U, SHORT_CALLSIGN_LENGTH);
|
|
|
|
m_yourAddress = yourAddress;
|
|
m_yourPort = yourPort;
|
|
|
|
if (check) {
|
|
CCCITTChecksum cksum;
|
|
cksum.update(data + 17U, RADIO_HEADER_LENGTH_BYTES - 2U);
|
|
bool valid = cksum.check(data + 17U + RADIO_HEADER_LENGTH_BYTES - 2U);
|
|
|
|
if (!valid)
|
|
CUtils::dump(wxT("Header checksum failure from the repeater"), data + 17U, RADIO_HEADER_LENGTH_BYTES);
|
|
|
|
return valid;
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
bool CHeaderData::setHBRepeaterData(const unsigned char *data, unsigned int length, bool check, const in_addr& yourAddress, unsigned int yourPort)
|
|
{
|
|
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_yourAddress = yourAddress;
|
|
m_yourPort = yourPort;
|
|
|
|
if (check) {
|
|
CCCITTChecksum cksum;
|
|
cksum.update(data + 8U, RADIO_HEADER_LENGTH_BYTES - 2U);
|
|
bool valid = cksum.check(data + 8U + RADIO_HEADER_LENGTH_BYTES - 2U);
|
|
|
|
if (!valid)
|
|
CUtils::dump(wxT("Header checksum failure from the repeater"), data + 8U, RADIO_HEADER_LENGTH_BYTES);
|
|
|
|
return valid;
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
void CHeaderData::setDCSData(const unsigned char *data, unsigned int length, const in_addr& yourAddress, unsigned int yourPort, unsigned int myPort)
|
|
{
|
|
wxASSERT(data != NULL);
|
|
wxASSERT(length >= 100U);
|
|
|
|
m_id = data[44U] * 256U + data[43U];
|
|
|
|
m_flag1 = data[4U];
|
|
m_flag2 = data[5U];
|
|
m_flag3 = data[6U];
|
|
|
|
::memcpy(m_rptCall2, data + 7U, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(m_rptCall1, data + 15U, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(m_yourCall, data + 23U, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(m_myCall1, data + 31U, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(m_myCall2, data + 39U, SHORT_CALLSIGN_LENGTH);
|
|
|
|
m_yourAddress = yourAddress;
|
|
m_yourPort = yourPort;
|
|
m_myPort = myPort;
|
|
}
|
|
|
|
void CHeaderData::setCCSData(const unsigned char *data, unsigned int length, const in_addr& yourAddress, unsigned int yourPort, unsigned int myPort)
|
|
{
|
|
wxASSERT(data != NULL);
|
|
wxASSERT(length >= 100U);
|
|
|
|
m_id = data[44U] * 256U + data[43U];
|
|
|
|
::memcpy(m_rptCall2, data + 7U, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(m_rptCall1, data + 15U, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(m_yourCall, data + 23U, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(m_myCall1, data + 31U, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(m_myCall2, data + 39U, SHORT_CALLSIGN_LENGTH);
|
|
|
|
m_yourAddress = yourAddress;
|
|
m_yourPort = yourPort;
|
|
m_myPort = myPort;
|
|
}
|
|
|
|
bool CHeaderData::setG2Data(const unsigned char *data, unsigned int length, bool check, const in_addr& yourAddress, unsigned int yourPort)
|
|
{
|
|
wxASSERT(data != NULL);
|
|
wxASSERT(length >= 56U);
|
|
|
|
m_band1 = data[9];
|
|
m_band2 = data[10];
|
|
m_band3 = data[11];
|
|
m_id = data[12] * 256U + data[13];
|
|
|
|
m_flag1 = data[15U];
|
|
m_flag2 = data[16U];
|
|
m_flag3 = data[17U];
|
|
|
|
::memcpy(m_rptCall2, data + 18U, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(m_rptCall1, data + 26U, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(m_yourCall, data + 34U, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(m_myCall1, data + 42U, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(m_myCall2, data + 50U, SHORT_CALLSIGN_LENGTH);
|
|
|
|
m_yourAddress = yourAddress;
|
|
m_yourPort = yourPort;
|
|
|
|
if (check) {
|
|
CCCITTChecksum cksum;
|
|
cksum.update(data + 15U, RADIO_HEADER_LENGTH_BYTES - 2U);
|
|
bool valid = cksum.check(data + 15U + RADIO_HEADER_LENGTH_BYTES - 2U);
|
|
|
|
if (!valid)
|
|
CUtils::dump(wxT("Header checksum failure from G2"), data + 15U, RADIO_HEADER_LENGTH_BYTES);
|
|
|
|
return valid;
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
bool CHeaderData::setDExtraData(const unsigned char *data, unsigned int length, bool check, const in_addr& yourAddress, unsigned int yourPort, unsigned int myPort)
|
|
{
|
|
wxASSERT(data != NULL);
|
|
wxASSERT(length >= 56U);
|
|
|
|
m_band1 = data[9];
|
|
m_band2 = data[10];
|
|
m_band3 = data[11];
|
|
m_id = data[12] * 256U + data[13];
|
|
|
|
m_flag1 = data[15U];
|
|
m_flag2 = data[16U];
|
|
m_flag3 = data[17U];
|
|
|
|
::memcpy(m_rptCall2, data + 18U, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(m_rptCall1, data + 26U, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(m_yourCall, data + 34U, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(m_myCall1, data + 42U, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(m_myCall2, data + 50U, SHORT_CALLSIGN_LENGTH);
|
|
|
|
m_yourAddress = yourAddress;
|
|
m_yourPort = yourPort;
|
|
m_myPort = myPort;
|
|
|
|
if (check) {
|
|
CCCITTChecksum cksum;
|
|
cksum.update(data + 15U, RADIO_HEADER_LENGTH_BYTES - 2U);
|
|
bool valid = cksum.check(data + 15U + RADIO_HEADER_LENGTH_BYTES - 2U);
|
|
|
|
if (!valid)
|
|
CUtils::dump(wxT("Header checksum failure from DExtra"), data + 15U, RADIO_HEADER_LENGTH_BYTES);
|
|
|
|
return valid;
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
bool CHeaderData::setDPlusData(const unsigned char *data, unsigned int length, bool check, const in_addr& yourAddress, unsigned int yourPort, unsigned int myPort)
|
|
{
|
|
wxASSERT(data != NULL);
|
|
wxASSERT(length >= 58U);
|
|
|
|
if (data[0] != 0x3A || data[1] != 0x80) {
|
|
CUtils::dump(wxT("Invalid header length from D-Plus"), data, length);
|
|
return false;
|
|
}
|
|
|
|
m_band1 = data[11];
|
|
m_band2 = data[12];
|
|
m_band3 = data[13];
|
|
m_id = data[14] * 256U + data[15];
|
|
|
|
m_flag1 = data[17U];
|
|
m_flag2 = data[18U];
|
|
m_flag3 = data[19U];
|
|
|
|
::memcpy(m_rptCall2, data + 20U, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(m_rptCall1, data + 28U, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(m_yourCall, data + 36U, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(m_myCall1, data + 44U, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(m_myCall2, data + 52U, SHORT_CALLSIGN_LENGTH);
|
|
|
|
m_yourAddress = yourAddress;
|
|
m_yourPort = yourPort;
|
|
m_myPort = myPort;
|
|
|
|
if (check) {
|
|
CCCITTChecksum cksum;
|
|
cksum.update(data + 17U, RADIO_HEADER_LENGTH_BYTES - 2U);
|
|
bool valid = cksum.check(data + 17U + RADIO_HEADER_LENGTH_BYTES - 2U);
|
|
|
|
if (!valid)
|
|
CUtils::dump(wxT("Header checksum failure from D-Plus"), data + 17U, RADIO_HEADER_LENGTH_BYTES);
|
|
|
|
return valid;
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
bool CHeaderData::setDVTOOLData(const unsigned char* data, unsigned int length, bool check)
|
|
{
|
|
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);
|
|
|
|
if (check) {
|
|
CCCITTChecksum cksum;
|
|
cksum.update(data, RADIO_HEADER_LENGTH_BYTES - 2U);
|
|
bool valid = cksum.check(data + RADIO_HEADER_LENGTH_BYTES - 2U);
|
|
|
|
if (!valid)
|
|
CUtils::dump(wxT("Header checksum failure from DVTOOL"), data, RADIO_HEADER_LENGTH_BYTES);
|
|
|
|
return valid;
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
unsigned int CHeaderData::getIcomRepeaterData(unsigned char *data, unsigned int length, bool check) const
|
|
{
|
|
wxASSERT(data != NULL);
|
|
wxASSERT(length >= 58U);
|
|
|
|
data[0] = 'D';
|
|
data[1] = 'S';
|
|
data[2] = 'T';
|
|
data[3] = 'R';
|
|
|
|
data[4] = m_rptSeq / 256U; // Packet sequence number
|
|
data[5] = m_rptSeq % 256U;
|
|
|
|
data[6] = 0x73; // Not a response
|
|
data[7] = 0x12; // Data type
|
|
|
|
data[8] = 0x00; // Length of 48 bytes following
|
|
data[9] = 0x30;
|
|
|
|
data[10] = 0x20; // AMBE plus Slow Data following
|
|
|
|
data[11] = m_band1;
|
|
data[12] = m_band2;
|
|
data[13] = m_band3;
|
|
|
|
data[14] = m_id / 256U; // Unique session id
|
|
data[15] = m_id % 256U;
|
|
|
|
data[16] = 0x80;
|
|
|
|
data[17] = m_flag1; // Flags 1, 2, and 3
|
|
data[18] = m_flag2;
|
|
data[19] = m_flag3;
|
|
|
|
::memcpy(data + 20U, m_rptCall2, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(data + 28U, m_rptCall1, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(data + 36U, m_yourCall, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(data + 44U, m_myCall1, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(data + 52U, m_myCall2, SHORT_CALLSIGN_LENGTH);
|
|
|
|
if (check) {
|
|
CCCITTChecksum csum;
|
|
csum.update(data + 17, 4U * LONG_CALLSIGN_LENGTH + SHORT_CALLSIGN_LENGTH + 3U);
|
|
csum.result(data + 56);
|
|
} else {
|
|
data[56] = 0xFF;
|
|
data[57] = 0xFF;
|
|
}
|
|
|
|
return 58U;
|
|
}
|
|
|
|
unsigned int CHeaderData::getHBRepeaterData(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) {
|
|
CCCITTChecksum 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;
|
|
}
|
|
|
|
void CHeaderData::getDCSData(unsigned char *data, unsigned int length) const
|
|
{
|
|
wxASSERT(data != NULL);
|
|
wxASSERT(length >= 100U);
|
|
|
|
data[4] = m_flag1; // Flags 1, 2, and 3
|
|
data[5] = m_flag2;
|
|
data[6] = m_flag3;
|
|
|
|
::memcpy(data + 7U, m_rptCall2, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(data + 15U, m_rptCall1, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(data + 23U, m_yourCall, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(data + 31U, m_myCall1, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(data + 39U, m_myCall2, SHORT_CALLSIGN_LENGTH);
|
|
}
|
|
|
|
void CHeaderData::getCCSData(unsigned char *data, unsigned int length) const
|
|
{
|
|
wxASSERT(data != NULL);
|
|
wxASSERT(length >= 100U);
|
|
|
|
::memcpy(data + 7U, m_rptCall2, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(data + 15U, m_rptCall1, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(data + 23U, m_yourCall, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(data + 31U, m_myCall1, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(data + 39U, m_myCall2, SHORT_CALLSIGN_LENGTH);
|
|
}
|
|
|
|
unsigned int CHeaderData::getG2Data(unsigned char *data, unsigned int length, bool check) const
|
|
{
|
|
wxASSERT(data != NULL);
|
|
wxASSERT(length >= 56U);
|
|
|
|
data[0] = 'D';
|
|
data[1] = 'S';
|
|
data[2] = 'V';
|
|
data[3] = 'T';
|
|
|
|
data[4] = 0x10;
|
|
data[5] = 0x00;
|
|
data[6] = 0x15;
|
|
data[7] = 0x09;
|
|
data[8] = 0x20;
|
|
|
|
data[9] = m_band1;
|
|
data[10] = m_band2;
|
|
data[11] = m_band3;
|
|
|
|
data[12] = m_id / 256U; // Unique session id
|
|
data[13] = m_id % 256U;
|
|
|
|
data[14] = 0x80;
|
|
|
|
data[15] = m_flag1; // Flags 1, 2, and 3
|
|
data[16] = m_flag2;
|
|
data[17] = m_flag3;
|
|
|
|
::memcpy(data + 18U, m_rptCall2, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(data + 26U, m_rptCall1, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(data + 34U, m_yourCall, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(data + 42U, m_myCall1, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(data + 50U, m_myCall2, SHORT_CALLSIGN_LENGTH);
|
|
|
|
if (check) {
|
|
CCCITTChecksum csum;
|
|
csum.update(data + 15, 4U * LONG_CALLSIGN_LENGTH + SHORT_CALLSIGN_LENGTH + 3U);
|
|
csum.result(data + 54);
|
|
} else {
|
|
data[54] = 0xFF;
|
|
data[55] = 0xFF;
|
|
}
|
|
|
|
return 56U;
|
|
}
|
|
|
|
unsigned int CHeaderData::getDExtraData(unsigned char* data, unsigned int length, bool check) const
|
|
{
|
|
wxASSERT(data != NULL);
|
|
wxASSERT(length >= 56U);
|
|
|
|
data[0] = 'D';
|
|
data[1] = 'S';
|
|
data[2] = 'V';
|
|
data[3] = 'T';
|
|
|
|
data[4] = 0x10;
|
|
data[5] = 0x00;
|
|
data[6] = 0x00;
|
|
data[7] = 0x00;
|
|
data[8] = 0x20;
|
|
|
|
data[9] = m_band1;
|
|
data[10] = m_band2;
|
|
data[11] = m_band3;
|
|
|
|
data[12] = m_id % 256U; // Unique session id
|
|
data[13] = m_id / 256U;
|
|
|
|
data[14] = 0x80;
|
|
|
|
data[15] = 0x00; // Flags 1, 2, and 3
|
|
data[16] = 0x00;
|
|
data[17] = 0x00;
|
|
|
|
::memcpy(data + 18U, m_rptCall2, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(data + 26U, m_rptCall1, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(data + 34U, m_yourCall, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(data + 42U, m_myCall1, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(data + 50U, m_myCall2, SHORT_CALLSIGN_LENGTH);
|
|
|
|
if (check) {
|
|
CCCITTChecksum csum;
|
|
csum.update(data + 15, 4U * LONG_CALLSIGN_LENGTH + SHORT_CALLSIGN_LENGTH + 3U);
|
|
csum.result(data + 54);
|
|
} else {
|
|
data[54] = 0xFF;
|
|
data[55] = 0xFF;
|
|
}
|
|
|
|
return 56U;
|
|
}
|
|
|
|
unsigned int CHeaderData::getDPlusData(unsigned char* data, unsigned int length, bool check) const
|
|
{
|
|
wxASSERT(data != NULL);
|
|
wxASSERT(length >= 58U);
|
|
|
|
data[0] = 0x3A;
|
|
data[1] = 0x80;
|
|
|
|
data[2] = 'D';
|
|
data[3] = 'S';
|
|
data[4] = 'V';
|
|
data[5] = 'T';
|
|
|
|
data[6] = 0x10;
|
|
data[7] = 0x00;
|
|
data[8] = 0x00;
|
|
data[9] = 0x00;
|
|
data[10] = 0x20;
|
|
|
|
data[11] = m_band1;
|
|
data[12] = m_band2;
|
|
data[13] = m_band3;
|
|
|
|
data[14] = m_id % 256U; // Unique session id
|
|
data[15] = m_id / 256U;
|
|
|
|
data[16] = 0x80;
|
|
|
|
data[17] = 0x00; // Flags 1, 2, and 3
|
|
data[18] = 0x00;
|
|
data[19] = 0x00;
|
|
|
|
::memcpy(data + 20U, m_rptCall2, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(data + 28U, m_rptCall1, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(data + 36U, m_yourCall, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(data + 44U, m_myCall1, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(data + 52U, m_myCall2, SHORT_CALLSIGN_LENGTH);
|
|
|
|
if (check) {
|
|
CCCITTChecksum csum;
|
|
csum.update(data + 17, 4U * LONG_CALLSIGN_LENGTH + SHORT_CALLSIGN_LENGTH + 3U);
|
|
csum.result(data + 56);
|
|
} else {
|
|
data[56] = 0xFF;
|
|
data[57] = 0xFF;
|
|
}
|
|
|
|
return 58U;
|
|
}
|
|
|
|
unsigned int CHeaderData::getId() const
|
|
{
|
|
return m_id;
|
|
}
|
|
|
|
void CHeaderData::setId(unsigned int id)
|
|
{
|
|
m_id = id;
|
|
}
|
|
|
|
unsigned char CHeaderData::getBand1() const
|
|
{
|
|
return m_band1;
|
|
}
|
|
|
|
unsigned char CHeaderData::getBand2() const
|
|
{
|
|
return m_band2;
|
|
}
|
|
|
|
unsigned char CHeaderData::getBand3() const
|
|
{
|
|
return m_band3;
|
|
}
|
|
|
|
void CHeaderData::setBand1(unsigned char band)
|
|
{
|
|
m_band1 = band;
|
|
}
|
|
|
|
void CHeaderData::setBand2(unsigned char band)
|
|
{
|
|
m_band2 = band;
|
|
}
|
|
|
|
void CHeaderData::setBand3(unsigned char band)
|
|
{
|
|
m_band3 = band;
|
|
}
|
|
|
|
unsigned int CHeaderData::getRptSeq() const
|
|
{
|
|
return m_rptSeq;
|
|
}
|
|
|
|
void CHeaderData::setRptSeq(unsigned int seqNo)
|
|
{
|
|
m_rptSeq = seqNo;
|
|
}
|
|
|
|
unsigned char CHeaderData::getFlag1() const
|
|
{
|
|
return m_flag1;
|
|
}
|
|
|
|
unsigned char CHeaderData::getFlag2() const
|
|
{
|
|
return m_flag2;
|
|
}
|
|
|
|
unsigned char CHeaderData::getFlag3() const
|
|
{
|
|
return m_flag3;
|
|
}
|
|
|
|
void CHeaderData::setFlags(unsigned char flag1, unsigned char flag2, unsigned char flag3)
|
|
{
|
|
m_flag1 = flag1;
|
|
m_flag2 = flag2;
|
|
m_flag3 = flag3;
|
|
}
|
|
|
|
wxString CHeaderData::getMyCall1() const
|
|
{
|
|
return wxString((const char*)m_myCall1, wxConvLocal, LONG_CALLSIGN_LENGTH);
|
|
}
|
|
|
|
wxString CHeaderData::getMyCall2() const
|
|
{
|
|
return wxString((const char*)m_myCall2, wxConvLocal, SHORT_CALLSIGN_LENGTH);
|
|
}
|
|
|
|
wxString CHeaderData::getYourCall() const
|
|
{
|
|
return wxString((const char*)m_yourCall, wxConvLocal, LONG_CALLSIGN_LENGTH);
|
|
}
|
|
|
|
wxString CHeaderData::getRptCall1() const
|
|
{
|
|
return wxString((const char*)m_rptCall1, wxConvLocal, LONG_CALLSIGN_LENGTH);
|
|
}
|
|
|
|
wxString CHeaderData::getRptCall2() const
|
|
{
|
|
return wxString((const char*)m_rptCall2, wxConvLocal, LONG_CALLSIGN_LENGTH);
|
|
}
|
|
|
|
void CHeaderData::setFlag1(unsigned char flag)
|
|
{
|
|
m_flag1 = flag;
|
|
}
|
|
|
|
void CHeaderData::setFlag2(unsigned char flag)
|
|
{
|
|
m_flag2 = flag;
|
|
}
|
|
|
|
void CHeaderData::setFlag3(unsigned char flag)
|
|
{
|
|
m_flag3 = flag;
|
|
}
|
|
|
|
void CHeaderData::setMyCall1(const wxString& my1)
|
|
{
|
|
::memset(m_myCall1, ' ', LONG_CALLSIGN_LENGTH);
|
|
|
|
for (unsigned int i = 0U; i < my1.Len(); i++)
|
|
m_myCall1[i] = my1.GetChar(i);
|
|
}
|
|
|
|
void CHeaderData::setMyCall2(const wxString& my2)
|
|
{
|
|
::memset(m_myCall2, ' ', SHORT_CALLSIGN_LENGTH);
|
|
|
|
for (unsigned int i = 0U; i < my2.Len(); i++)
|
|
m_myCall2[i] = my2.GetChar(i);
|
|
}
|
|
|
|
void CHeaderData::setYourCall(const wxString& your)
|
|
{
|
|
::memset(m_yourCall, ' ', LONG_CALLSIGN_LENGTH);
|
|
|
|
for (unsigned int i = 0U; i < your.Len(); i++)
|
|
m_yourCall[i] = your.GetChar(i);
|
|
}
|
|
|
|
void CHeaderData::setRptCall1(const wxString& rpt1)
|
|
{
|
|
::memset(m_rptCall1, ' ', LONG_CALLSIGN_LENGTH);
|
|
|
|
for (unsigned int i = 0U; i < rpt1.Len(); i++)
|
|
m_rptCall1[i] = rpt1.GetChar(i);
|
|
}
|
|
|
|
void CHeaderData::setRptCall2(const wxString& rpt2)
|
|
{
|
|
::memset(m_rptCall2, ' ', LONG_CALLSIGN_LENGTH);
|
|
|
|
for (unsigned int i = 0U; i < rpt2.Len(); i++)
|
|
m_rptCall2[i] = rpt2.GetChar(i);
|
|
}
|
|
|
|
void CHeaderData::setRepeaters(const wxString& rpt1, const wxString& rpt2)
|
|
{
|
|
::memset(m_rptCall1, ' ', LONG_CALLSIGN_LENGTH);
|
|
::memset(m_rptCall2, ' ', LONG_CALLSIGN_LENGTH);
|
|
|
|
for (unsigned int i = 0U; i < rpt1.Len(); i++)
|
|
m_rptCall1[i] = rpt1.GetChar(i);
|
|
|
|
for (unsigned int i = 0U; i < rpt2.Len(); i++)
|
|
m_rptCall2[i] = rpt2.GetChar(i);
|
|
}
|
|
|
|
void CHeaderData::setCQCQCQ()
|
|
{
|
|
::memcpy(m_yourCall, "CQCQCQ ", LONG_CALLSIGN_LENGTH);
|
|
}
|
|
|
|
bool CHeaderData::setData(const unsigned char *data, unsigned int length, bool check)
|
|
{
|
|
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);
|
|
|
|
if (check) {
|
|
CCCITTChecksum cksum;
|
|
cksum.update(data, RADIO_HEADER_LENGTH_BYTES - 2U);
|
|
return cksum.check(data + RADIO_HEADER_LENGTH_BYTES - 2U);
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
unsigned int CHeaderData::getData(unsigned char *data, unsigned int length, bool check) 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);
|
|
|
|
if (check) {
|
|
CCCITTChecksum csum;
|
|
csum.update(data, RADIO_HEADER_LENGTH_BYTES - 2U);
|
|
csum.result(data + RADIO_HEADER_LENGTH_BYTES - 2U);
|
|
|
|
return RADIO_HEADER_LENGTH_BYTES;
|
|
} else {
|
|
return RADIO_HEADER_LENGTH_BYTES - 2U;
|
|
}
|
|
}
|
|
|
|
void CHeaderData::setDestination(const in_addr& address, unsigned int port)
|
|
{
|
|
m_yourAddress = address;
|
|
m_yourPort = port;
|
|
}
|
|
|
|
in_addr CHeaderData::getYourAddress() const
|
|
{
|
|
return m_yourAddress;
|
|
}
|
|
|
|
unsigned int CHeaderData::getYourPort() const
|
|
{
|
|
return m_yourPort;
|
|
}
|
|
|
|
unsigned int CHeaderData::getMyPort() const
|
|
{
|
|
return m_myPort;
|
|
}
|
|
|
|
CHeaderData& CHeaderData::operator =(const CHeaderData& header)
|
|
{
|
|
if (&header != this) {
|
|
m_rptSeq = header.m_rptSeq;
|
|
m_id = header.m_id;
|
|
m_band1 = header.m_band1;
|
|
m_band2 = header.m_band2;
|
|
m_band3 = header.m_band3;
|
|
m_flag1 = header.m_flag1;
|
|
m_flag2 = header.m_flag2;
|
|
m_flag3 = header.m_flag3;
|
|
m_yourAddress = header.m_yourAddress;
|
|
m_yourPort = header.m_yourPort;
|
|
m_myPort = header.m_myPort;
|
|
m_errors = header.m_errors;
|
|
|
|
::memcpy(m_myCall1, header.m_myCall1, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(m_myCall2, header.m_myCall2, SHORT_CALLSIGN_LENGTH);
|
|
::memcpy(m_yourCall, header.m_yourCall, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(m_rptCall1, header.m_rptCall1, LONG_CALLSIGN_LENGTH);
|
|
::memcpy(m_rptCall2, header.m_rptCall2, LONG_CALLSIGN_LENGTH);
|
|
}
|
|
|
|
return *this;
|
|
}
|