mirror of
https://github.com/ShaYmez/NXDNClients.git
synced 2025-07-31 04:02:25 -04:00
Latest changes for Kenwood repeater support.
This commit is contained in:
parent
d6e28630ff
commit
bfa1118726
@ -45,17 +45,19 @@ m_seqNo(0U),
|
|||||||
m_timeStamp(0U),
|
m_timeStamp(0U),
|
||||||
m_ssrc(0U),
|
m_ssrc(0U),
|
||||||
m_debug(debug),
|
m_debug(debug),
|
||||||
m_timer(1000U, 0U, 200U),
|
|
||||||
m_startSecs(0U),
|
m_startSecs(0U),
|
||||||
m_startMSecs(0U)
|
m_startMSecs(0U),
|
||||||
|
m_rtcpTimer(1000U, 0U, 200U),
|
||||||
|
m_hangTimer(1000U, 5U),
|
||||||
|
m_hangType(0U),
|
||||||
|
m_hangSrc(0U),
|
||||||
|
m_hangDst(0U)
|
||||||
{
|
{
|
||||||
assert(localPort > 0U);
|
assert(localPort > 0U);
|
||||||
assert(!rptAddress.empty());
|
assert(!rptAddress.empty());
|
||||||
assert(rptPort > 0U);
|
assert(rptPort > 0U);
|
||||||
|
|
||||||
m_address = CUDPSocket::lookup(rptAddress);
|
m_address = CUDPSocket::lookup(rptAddress);
|
||||||
|
|
||||||
::srand((unsigned int)m_stopWatch.time());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CKenwoodNetwork::~CKenwoodNetwork()
|
CKenwoodNetwork::~CKenwoodNetwork()
|
||||||
@ -77,7 +79,7 @@ bool CKenwoodNetwork::open()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_ssrc = ::rand();
|
m_ssrc = m_rtpSocket.getLocalAddress();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -127,11 +129,12 @@ bool CKenwoodNetwork::processIcomVoiceHeader(const unsigned char* inData)
|
|||||||
|
|
||||||
switch (inData[5U] & 0x3FU) {
|
switch (inData[5U] & 0x3FU) {
|
||||||
case 0x01U:
|
case 0x01U:
|
||||||
m_timer.start();
|
m_hangTimer.stop();
|
||||||
|
m_rtcpTimer.start();
|
||||||
writeRTCPStart();
|
writeRTCPStart();
|
||||||
return writeRTPVoiceHeader(outData);
|
return writeRTPVoiceHeader(outData);
|
||||||
case 0x08U:
|
case 0x08U:
|
||||||
m_timer.stop();
|
m_hangTimer.start();
|
||||||
writeRTCPHang(type, src, dst);
|
writeRTCPHang(type, src, dst);
|
||||||
return writeRTPVoiceTrailer(outData);
|
return writeRTPVoiceTrailer(outData);
|
||||||
default:
|
default:
|
||||||
@ -152,6 +155,10 @@ bool CKenwoodNetwork::processIcomVoiceData(const unsigned char* inData)
|
|||||||
outData[2U] = inData[4U] & 0xC0U;
|
outData[2U] = inData[4U] & 0xC0U;
|
||||||
outData[3U] = inData[3U];
|
outData[3U] = inData[3U];
|
||||||
|
|
||||||
|
CUtils::dump(4U, "Icom Audio 1 + 2 + 3 + 4", inData + 5U, 28U);
|
||||||
|
|
||||||
|
CUtils::dump(4U, "Icom Audio 1 + 2", inData + 5U, 14U);
|
||||||
|
|
||||||
// Audio 1
|
// Audio 1
|
||||||
::memset(temp, 0x00U, 10U);
|
::memset(temp, 0x00U, 10U);
|
||||||
for (unsigned int i = 0U; i < 49U; i++) {
|
for (unsigned int i = 0U; i < 49U; i++) {
|
||||||
@ -168,6 +175,8 @@ bool CKenwoodNetwork::processIcomVoiceData(const unsigned char* inData)
|
|||||||
outData[10U] = temp[7U];
|
outData[10U] = temp[7U];
|
||||||
outData[11U] = temp[6U];
|
outData[11U] = temp[6U];
|
||||||
|
|
||||||
|
CUtils::dump(4U, "Kenwood unswapped Audio 1", temp, 8U);
|
||||||
|
|
||||||
// Audio 2
|
// Audio 2
|
||||||
::memset(temp, 0x00U, 10U);
|
::memset(temp, 0x00U, 10U);
|
||||||
for (unsigned int i = 0U; i < 49U; i++) {
|
for (unsigned int i = 0U; i < 49U; i++) {
|
||||||
@ -184,6 +193,10 @@ bool CKenwoodNetwork::processIcomVoiceData(const unsigned char* inData)
|
|||||||
outData[18U] = temp[7U];
|
outData[18U] = temp[7U];
|
||||||
outData[19U] = temp[6U];
|
outData[19U] = temp[6U];
|
||||||
|
|
||||||
|
CUtils::dump(4U, "Kenwood unswapped Audio 2", temp, 8U);
|
||||||
|
|
||||||
|
CUtils::dump(4U, "Icom Audio 3 + 4", inData + 19U, 14U);
|
||||||
|
|
||||||
// Audio 3
|
// Audio 3
|
||||||
::memset(temp, 0x00U, 10U);
|
::memset(temp, 0x00U, 10U);
|
||||||
for (unsigned int i = 0U; i < 49U; i++) {
|
for (unsigned int i = 0U; i < 49U; i++) {
|
||||||
@ -200,6 +213,8 @@ bool CKenwoodNetwork::processIcomVoiceData(const unsigned char* inData)
|
|||||||
outData[26U] = temp[7U];
|
outData[26U] = temp[7U];
|
||||||
outData[27U] = temp[6U];
|
outData[27U] = temp[6U];
|
||||||
|
|
||||||
|
CUtils::dump(4U, "Kenwood unswapped Audio 3", temp, 8U);
|
||||||
|
|
||||||
// Audio 4
|
// Audio 4
|
||||||
::memset(temp, 0x00U, 10U);
|
::memset(temp, 0x00U, 10U);
|
||||||
for (unsigned int i = 0U; i < 49U; i++) {
|
for (unsigned int i = 0U; i < 49U; i++) {
|
||||||
@ -216,6 +231,8 @@ bool CKenwoodNetwork::processIcomVoiceData(const unsigned char* inData)
|
|||||||
outData[34U] = temp[7U];
|
outData[34U] = temp[7U];
|
||||||
outData[35U] = temp[6U];
|
outData[35U] = temp[6U];
|
||||||
|
|
||||||
|
CUtils::dump(4U, "Kenwood unswapped Audio 4", temp, 8U);
|
||||||
|
|
||||||
return writeRTPVoiceData(outData);
|
return writeRTPVoiceData(outData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -461,6 +478,15 @@ bool CKenwoodNetwork::writeRTCPPing()
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool CKenwoodNetwork::writeRTCPHang(unsigned char type, unsigned short src, unsigned short dst)
|
bool CKenwoodNetwork::writeRTCPHang(unsigned char type, unsigned short src, unsigned short dst)
|
||||||
|
{
|
||||||
|
m_hangType = type;
|
||||||
|
m_hangSrc = src;
|
||||||
|
m_hangDst = dst;
|
||||||
|
|
||||||
|
return writeRTCPHang();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CKenwoodNetwork::writeRTCPHang()
|
||||||
{
|
{
|
||||||
unsigned char buffer[30U];
|
unsigned char buffer[30U];
|
||||||
::memset(buffer, 0x00U, 30U);
|
::memset(buffer, 0x00U, 30U);
|
||||||
@ -480,13 +506,13 @@ bool CKenwoodNetwork::writeRTCPHang(unsigned char type, unsigned short src, unsi
|
|||||||
buffer[10U] = 'N';
|
buffer[10U] = 'N';
|
||||||
buffer[11U] = 'E';
|
buffer[11U] = 'E';
|
||||||
|
|
||||||
buffer[12U] = (src >> 8) & 0xFFU;
|
buffer[12U] = (m_hangSrc >> 8) & 0xFFU;
|
||||||
buffer[13U] = (src >> 0) & 0xFFU;
|
buffer[13U] = (m_hangSrc >> 0) & 0xFFU;
|
||||||
|
|
||||||
buffer[14U] = (dst >> 8) & 0xFFU;
|
buffer[14U] = (m_hangDst >> 8) & 0xFFU;
|
||||||
buffer[15U] = (dst >> 0) & 0xFFU;
|
buffer[15U] = (m_hangDst >> 0) & 0xFFU;
|
||||||
|
|
||||||
buffer[16U] = type;
|
buffer[16U] = m_hangType;
|
||||||
|
|
||||||
buffer[17U] = 0x00U;
|
buffer[17U] = 0x00U;
|
||||||
buffer[18U] = 0x00U;
|
buffer[18U] = 0x00U;
|
||||||
@ -590,10 +616,19 @@ void CKenwoodNetwork::close()
|
|||||||
|
|
||||||
void CKenwoodNetwork::clock(unsigned int ms)
|
void CKenwoodNetwork::clock(unsigned int ms)
|
||||||
{
|
{
|
||||||
m_timer.clock(ms);
|
m_rtcpTimer.clock(ms);
|
||||||
if (m_timer.isRunning() && m_timer.hasExpired()) {
|
if (m_rtcpTimer.isRunning() && m_rtcpTimer.hasExpired()) {
|
||||||
writeRTCPPing();
|
if (m_hangTimer.isRunning())
|
||||||
m_timer.start();
|
writeRTCPHang();
|
||||||
|
else
|
||||||
|
writeRTCPPing();
|
||||||
|
m_rtcpTimer.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_hangTimer.clock(ms);
|
||||||
|
if (m_hangTimer.isRunning() && m_hangTimer.hasExpired()) {
|
||||||
|
m_rtcpTimer.stop();
|
||||||
|
m_hangTimer.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -675,6 +710,8 @@ void CKenwoodNetwork::processKenwoodVoiceData(unsigned char* inData)
|
|||||||
temp[6U] = inData[22U];
|
temp[6U] = inData[22U];
|
||||||
temp[7U] = inData[21U];
|
temp[7U] = inData[21U];
|
||||||
|
|
||||||
|
CUtils::dump(4U, "Kenwood unswapped Audio 1", temp, 8U);
|
||||||
|
|
||||||
for (unsigned int i = 0U; i < 49U; i++, n++) {
|
for (unsigned int i = 0U; i < 49U; i++, n++) {
|
||||||
bool b = READ_BIT(temp, i);
|
bool b = READ_BIT(temp, i);
|
||||||
WRITE_BIT(outData, n, b);
|
WRITE_BIT(outData, n, b);
|
||||||
@ -689,11 +726,15 @@ void CKenwoodNetwork::processKenwoodVoiceData(unsigned char* inData)
|
|||||||
temp[6U] = inData[30U];
|
temp[6U] = inData[30U];
|
||||||
temp[7U] = inData[29U];
|
temp[7U] = inData[29U];
|
||||||
|
|
||||||
|
CUtils::dump(4U, "Kenwood unswapped Audio 2", temp, 8U);
|
||||||
|
|
||||||
for (unsigned int i = 0U; i < 49U; i++, n++) {
|
for (unsigned int i = 0U; i < 49U; i++, n++) {
|
||||||
bool b = READ_BIT(temp, i);
|
bool b = READ_BIT(temp, i);
|
||||||
WRITE_BIT(outData, n, b);
|
WRITE_BIT(outData, n, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CUtils::dump(4U, "Icom Audio 1 + 2", outData + 5U, 14U);
|
||||||
|
|
||||||
// AMBE 3+4
|
// AMBE 3+4
|
||||||
n = 19U * 8U;
|
n = 19U * 8U;
|
||||||
|
|
||||||
@ -706,6 +747,8 @@ void CKenwoodNetwork::processKenwoodVoiceData(unsigned char* inData)
|
|||||||
temp[6U] = inData[38U];
|
temp[6U] = inData[38U];
|
||||||
temp[7U] = inData[37U];
|
temp[7U] = inData[37U];
|
||||||
|
|
||||||
|
CUtils::dump(4U, "Kenwood unswapped Audio 3", temp, 8U);
|
||||||
|
|
||||||
for (unsigned int i = 0U; i < 49U; i++, n++) {
|
for (unsigned int i = 0U; i < 49U; i++, n++) {
|
||||||
bool b = READ_BIT(temp, i);
|
bool b = READ_BIT(temp, i);
|
||||||
WRITE_BIT(outData, n, b);
|
WRITE_BIT(outData, n, b);
|
||||||
@ -720,11 +763,17 @@ void CKenwoodNetwork::processKenwoodVoiceData(unsigned char* inData)
|
|||||||
temp[6U] = inData[46U];
|
temp[6U] = inData[46U];
|
||||||
temp[7U] = inData[45U];
|
temp[7U] = inData[45U];
|
||||||
|
|
||||||
|
CUtils::dump(4U, "Kenwood unswapped Audio 4", temp, 8U);
|
||||||
|
|
||||||
for (unsigned int i = 0U; i < 49U; i++, n++) {
|
for (unsigned int i = 0U; i < 49U; i++, n++) {
|
||||||
bool b = READ_BIT(temp, i);
|
bool b = READ_BIT(temp, i);
|
||||||
WRITE_BIT(outData, n, b);
|
WRITE_BIT(outData, n, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CUtils::dump(4U, "Icom Audio 3 + 4", outData + 19U, 14U);
|
||||||
|
|
||||||
|
CUtils::dump(4U, "Icom Audio 1 + 2 + 3 + 4", outData + 5U, 28U);
|
||||||
|
|
||||||
::memcpy(inData, outData, 33U);
|
::memcpy(inData, outData, 33U);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,9 +54,13 @@ private:
|
|||||||
unsigned long m_timeStamp;
|
unsigned long m_timeStamp;
|
||||||
unsigned int m_ssrc;
|
unsigned int m_ssrc;
|
||||||
bool m_debug;
|
bool m_debug;
|
||||||
CTimer m_timer;
|
|
||||||
uint32_t m_startSecs;
|
uint32_t m_startSecs;
|
||||||
uint32_t m_startMSecs;
|
uint32_t m_startMSecs;
|
||||||
|
CTimer m_rtcpTimer;
|
||||||
|
CTimer m_hangTimer;
|
||||||
|
unsigned char m_hangType;
|
||||||
|
unsigned short m_hangSrc;
|
||||||
|
unsigned short m_hangDst;
|
||||||
|
|
||||||
bool processIcomVoiceHeader(const unsigned char* data);
|
bool processIcomVoiceHeader(const unsigned char* data);
|
||||||
bool processIcomVoiceData(const unsigned char* data);
|
bool processIcomVoiceData(const unsigned char* data);
|
||||||
@ -69,6 +73,7 @@ private:
|
|||||||
bool writeRTCPStart();
|
bool writeRTCPStart();
|
||||||
bool writeRTCPPing();
|
bool writeRTCPPing();
|
||||||
bool writeRTCPHang(unsigned char type, unsigned short src, unsigned short dst);
|
bool writeRTCPHang(unsigned char type, unsigned short src, unsigned short dst);
|
||||||
|
bool writeRTCPHang();
|
||||||
unsigned int readRTP(unsigned char* data);
|
unsigned int readRTP(unsigned char* data);
|
||||||
unsigned int readRTCP(unsigned char* data);
|
unsigned int readRTCP(unsigned char* data);
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2006-2016 by Jonathan Naylor G4KLX
|
* Copyright (C) 2006-2016,2020 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -24,6 +24,7 @@
|
|||||||
#if !defined(_WIN32) && !defined(_WIN64)
|
#if !defined(_WIN32) && !defined(_WIN64)
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <ifaddrs.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -260,3 +261,31 @@ void CUDPSocket::close()
|
|||||||
::close(m_fd);
|
::close(m_fd);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned long CUDPSocket::getLocalAddress() const
|
||||||
|
{
|
||||||
|
unsigned long address = 0UL;
|
||||||
|
|
||||||
|
char hostname[80U];
|
||||||
|
int ret = ::gethostname(hostname, 80);
|
||||||
|
if (ret == -1)
|
||||||
|
return 0UL;
|
||||||
|
|
||||||
|
struct hostent* phe = ::gethostbyname(hostname);
|
||||||
|
if (phe == NULL)
|
||||||
|
return 0UL;
|
||||||
|
|
||||||
|
if (phe->h_addrtype != AF_INET)
|
||||||
|
return 0UL;
|
||||||
|
|
||||||
|
for (unsigned int i = 0U; phe->h_addr_list[i] != NULL; i++) {
|
||||||
|
struct in_addr addr;
|
||||||
|
::memcpy(&addr, phe->h_addr_list[i], sizeof(struct in_addr));
|
||||||
|
if (addr.s_addr != INADDR_LOOPBACK) {
|
||||||
|
address = addr.s_addr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2009-2011,2013,2015,2016 by Jonathan Naylor G4KLX
|
* Copyright (C) 2009-2011,2013,2015,2016,2020 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -47,6 +47,8 @@ public:
|
|||||||
|
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
|
unsigned long getLocalAddress() const;
|
||||||
|
|
||||||
static in_addr lookup(const std::string& hostName);
|
static in_addr lookup(const std::string& hostName);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -19,6 +19,6 @@
|
|||||||
#if !defined(VERSION_H)
|
#if !defined(VERSION_H)
|
||||||
#define VERSION_H
|
#define VERSION_H
|
||||||
|
|
||||||
const char* VERSION = "20200505";
|
const char* VERSION = "20200509";
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user