diff --git a/Conf.cpp b/Conf.cpp index ee4034b..8d61b30 100644 --- a/Conf.cpp +++ b/Conf.cpp @@ -236,6 +236,7 @@ m_p25LocalPort(0U), m_p25NetworkModeHang(3U), m_p25NetworkDebug(false), m_nxdnNetworkEnabled(false), +m_nxdnNetworkProtocol("Icom"), m_nxdnGatewayAddress(), m_nxdnGatewayPort(0U), m_nxdnLocalAddress(), @@ -842,6 +843,8 @@ bool CConf::read() } else if (section == SECTION_NXDN_NETWORK) { if (::strcmp(key, "Enable") == 0) m_nxdnNetworkEnabled = ::atoi(value) == 1; + else if (::strcmp(key, "Protocol") == 0) + m_nxdnNetworkProtocol = value; else if (::strcmp(key, "LocalAddress") == 0) m_nxdnLocalAddress = value; else if (::strcmp(key, "LocalPort") == 0) @@ -1832,6 +1835,11 @@ bool CConf::getNXDNNetworkEnabled() const return m_nxdnNetworkEnabled; } +std::string CConf::getNXDNNetworkProtocol() const +{ + return m_nxdnNetworkProtocol; +} + std::string CConf::getNXDNGatewayAddress() const { return m_nxdnGatewayAddress; diff --git a/Conf.h b/Conf.h index 40e81a0..77cff6c 100644 --- a/Conf.h +++ b/Conf.h @@ -244,6 +244,7 @@ public: // The NXDN Network section bool getNXDNNetworkEnabled() const; + std::string getNXDNNetworkProtocol() const; std::string getNXDNGatewayAddress() const; unsigned int getNXDNGatewayPort() const; std::string getNXDNLocalAddress() const; @@ -509,6 +510,7 @@ private: bool m_p25NetworkDebug; bool m_nxdnNetworkEnabled; + std::string m_nxdnNetworkProtocol; std::string m_nxdnGatewayAddress; unsigned int m_nxdnGatewayPort; std::string m_nxdnLocalAddress; diff --git a/MMDVMHost.cpp b/MMDVMHost.cpp index d344409..3213959 100644 --- a/MMDVMHost.cpp +++ b/MMDVMHost.cpp @@ -17,6 +17,8 @@ */ #include "MMDVMHost.h" +#include "NXDNKenwoodNetwork.h" +#include "NXDNIcomNetwork.h" #include "RSSIInterpolator.h" #include "SerialController.h" #include "Version.h" @@ -1472,6 +1474,7 @@ bool CMMDVMHost::createP25Network() bool CMMDVMHost::createNXDNNetwork() { + std::string protocol = m_conf.getNXDNNetworkProtocol(); std::string gatewayAddress = m_conf.getNXDNGatewayAddress(); unsigned int gatewayPort = m_conf.getNXDNGatewayPort(); std::string localAddress = m_conf.getNXDNLocalAddress(); @@ -1480,13 +1483,17 @@ bool CMMDVMHost::createNXDNNetwork() bool debug = m_conf.getNXDNNetworkDebug(); LogInfo("NXDN Network Parameters"); + LogInfo(" Protocol: %s", protocol.c_str()); LogInfo(" Gateway Address: %s", gatewayAddress.c_str()); LogInfo(" Gateway Port: %u", gatewayPort); LogInfo(" Local Address: %s", localAddress.c_str()); LogInfo(" Local Port: %u", localPort); LogInfo(" Mode Hang: %us", m_nxdnNetModeHang); - m_nxdnNetwork = new CNXDNNetwork(localAddress, localPort, gatewayAddress, gatewayPort, debug); + if (protocol == "Kenwood") + m_nxdnNetwork = new CNXDNKenwoodNetwork(localAddress, localPort, gatewayAddress, gatewayPort, debug); + else + m_nxdnNetwork = new CNXDNIcomNetwork(localAddress, localPort, gatewayAddress, gatewayPort, debug); bool ret = m_nxdnNetwork->open(); if (!ret) { diff --git a/NXDNControl.cpp b/NXDNControl.cpp index 1f3fa4c..1e200c4 100644 --- a/NXDNControl.cpp +++ b/NXDNControl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2019 Jonathan Naylor, G4KLX + * Copyright (C) 2015-2020 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 @@ -39,7 +39,7 @@ const unsigned char BIT_MASK_TABLE[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04 #define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7]) #define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7]) -CNXDNControl::CNXDNControl(unsigned int ran, unsigned int id, bool selfOnly, CNXDNNetwork* network, CDisplay* display, unsigned int timeout, bool duplex, bool remoteGateway, CNXDNLookup* lookup, CRSSIInterpolator* rssiMapper) : +CNXDNControl::CNXDNControl(unsigned int ran, unsigned int id, bool selfOnly, INXDNNetwork* network, CDisplay* display, unsigned int timeout, bool duplex, bool remoteGateway, CNXDNLookup* lookup, CRSSIInterpolator* rssiMapper) : m_ran(ran), m_id(id), m_selfOnly(selfOnly), diff --git a/NXDNControl.h b/NXDNControl.h index 5c441e2..af2fba1 100644 --- a/NXDNControl.h +++ b/NXDNControl.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2019 by Jonathan Naylor G4KLX + * Copyright (C) 2015-2020 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 @@ -36,7 +36,7 @@ class CNXDNControl { public: - CNXDNControl(unsigned int ran, unsigned int id, bool selfOnly, CNXDNNetwork* network, CDisplay* display, unsigned int timeout, bool duplex, bool remoteGateway, CNXDNLookup* lookup, CRSSIInterpolator* rssiMapper); + CNXDNControl(unsigned int ran, unsigned int id, bool selfOnly, INXDNNetwork* network, CDisplay* display, unsigned int timeout, bool duplex, bool remoteGateway, CNXDNLookup* lookup, CRSSIInterpolator* rssiMapper); ~CNXDNControl(); bool writeModem(unsigned char* data, unsigned int len); @@ -53,7 +53,7 @@ private: unsigned int m_ran; unsigned int m_id; bool m_selfOnly; - CNXDNNetwork* m_network; + INXDNNetwork* m_network; CDisplay* m_display; bool m_duplex; bool m_remoteGateway; diff --git a/NXDNKenwoodNetwork.cpp b/NXDNKenwoodNetwork.cpp index c5a4a20..e294d96 100644 --- a/NXDNKenwoodNetwork.cpp +++ b/NXDNKenwoodNetwork.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "KenwoodNetwork.h" +#include "NXDNKenwoodNetwork.h" #include "NXDNCRC.h" #include "Utils.h" #include "Log.h" @@ -33,12 +33,12 @@ const unsigned char BIT_MASK_TABLE[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04 const unsigned int BUFFER_LENGTH = 200U; -CKenwoodNetwork::CKenwoodNetwork(unsigned int localPort, const std::string& rptAddress, unsigned int rptPort, bool debug) : -m_rtpSocket(localPort + 0U), -m_rtcpSocket(localPort + 1U), +CNXDNKenwoodNetwork::CNXDNKenwoodNetwork(const std::string& localAddress, unsigned int localPort, const std::string& gwyAddress, unsigned int gwyPort, bool debug) : +m_rtpSocket(localAddress, localPort + 0U), +m_rtcpSocket(localAddress, localPort + 1U), m_address(), -m_rtcpPort(rptPort + 1U), -m_rtpPort(rptPort + 0U), +m_rtcpPort(gwyPort + 1U), +m_rtpPort(gwyPort + 0U), m_headerSeen(false), m_seen1(false), m_seen2(false), @@ -58,20 +58,20 @@ m_hangSrc(0U), m_hangDst(0U) { assert(localPort > 0U); - assert(!rptAddress.empty()); - assert(rptPort > 0U); + assert(!gwyAddress.empty()); + assert(gwyPort > 0U); m_sacch = new unsigned char[10U]; - m_address = CUDPSocket::lookup(rptAddress); + m_address = CUDPSocket::lookup(gwyAddress); } -CKenwoodNetwork::~CKenwoodNetwork() +CNXDNKenwoodNetwork::~CNXDNKenwoodNetwork() { delete[] m_sacch; } -bool CKenwoodNetwork::open() +bool CNXDNKenwoodNetwork::open() { LogMessage("Opening Kenwood connection"); @@ -91,23 +91,27 @@ bool CKenwoodNetwork::open() return true; } -bool CKenwoodNetwork::write(const unsigned char* data, unsigned int length) +bool CNXDNKenwoodNetwork::write(const unsigned char* data, NXDN_NETWORK_MESSAGE_TYPE type) { assert(data != NULL); - switch (data[0U]) { - case 0x81U: // Voice header or trailer - case 0x83U: + switch (type) { + case NNMT_VOICE_HEADER: // Voice header or trailer + case NNMT_VOICE_TRAILER: + case NNMT_DATA_TRAILER: // Data trailer return processIcomVoiceHeader(data); - case 0xACU: // Voice data - case 0xAEU: + case NNMT_VOICE_BODY: // Voice data return processIcomVoiceData(data); + case NNMT_DATA_HEADER: // Voice header or trailer + return processIcomDataHeader(data); + case NNMT_DATA_BODY: // Voice data + return processIcomDataData(data); default: return false; } } -bool CKenwoodNetwork::processIcomVoiceHeader(const unsigned char* inData) +bool CNXDNKenwoodNetwork::processIcomVoiceHeader(const unsigned char* inData) { assert(inData != NULL); @@ -151,7 +155,7 @@ bool CKenwoodNetwork::processIcomVoiceHeader(const unsigned char* inData) } } -bool CKenwoodNetwork::processIcomVoiceData(const unsigned char* inData) +bool CNXDNKenwoodNetwork::processIcomVoiceData(const unsigned char* inData) { assert(inData != NULL); @@ -231,7 +235,7 @@ bool CKenwoodNetwork::processIcomVoiceData(const unsigned char* inData) return writeRTPVoiceData(outData); } -bool CKenwoodNetwork::writeRTPVoiceHeader(const unsigned char* data) +bool CNXDNKenwoodNetwork::writeRTPVoiceHeader(const unsigned char* data) { assert(data != NULL); @@ -278,7 +282,7 @@ bool CKenwoodNetwork::writeRTPVoiceHeader(const unsigned char* data) return m_rtpSocket.write(buffer, 47U, m_address, m_rtpPort); } -bool CKenwoodNetwork::writeRTPVoiceTrailer(const unsigned char* data) +bool CNXDNKenwoodNetwork::writeRTPVoiceTrailer(const unsigned char* data) { assert(data != NULL); @@ -324,7 +328,7 @@ bool CKenwoodNetwork::writeRTPVoiceTrailer(const unsigned char* data) return m_rtpSocket.write(buffer, 47U, m_address, m_rtpPort); } -bool CKenwoodNetwork::writeRTPVoiceData(const unsigned char* data) +bool CNXDNKenwoodNetwork::writeRTPVoiceData(const unsigned char* data) { assert(data != NULL); @@ -370,7 +374,7 @@ bool CKenwoodNetwork::writeRTPVoiceData(const unsigned char* data) return m_rtpSocket.write(buffer, 59U, m_address, m_rtpPort); } -bool CKenwoodNetwork::writeRTCPStart() +bool CNXDNKenwoodNetwork::writeRTCPStart() { #if defined(_WIN32) || defined(_WIN64) time_t now; @@ -430,7 +434,7 @@ bool CKenwoodNetwork::writeRTCPStart() return m_rtcpSocket.write(buffer, 28U, m_address, m_rtcpPort); } -bool CKenwoodNetwork::writeRTCPPing() +bool CNXDNKenwoodNetwork::writeRTCPPing() { unsigned char buffer[30U]; ::memset(buffer, 0x00U, 30U); @@ -472,7 +476,7 @@ bool CKenwoodNetwork::writeRTCPPing() return m_rtcpSocket.write(buffer, 28U, m_address, m_rtcpPort); } -bool CKenwoodNetwork::writeRTCPHang(unsigned char type, unsigned short src, unsigned short dst) +bool CNXDNKenwoodNetwork::writeRTCPHang(unsigned char type, unsigned short src, unsigned short dst) { m_hangType = type; m_hangSrc = src; @@ -481,7 +485,7 @@ bool CKenwoodNetwork::writeRTCPHang(unsigned char type, unsigned short src, unsi return writeRTCPHang(); } -bool CKenwoodNetwork::writeRTCPHang() +bool CNXDNKenwoodNetwork::writeRTCPHang() { unsigned char buffer[30U]; ::memset(buffer, 0x00U, 30U); @@ -515,7 +519,7 @@ bool CKenwoodNetwork::writeRTCPHang() return m_rtcpSocket.write(buffer, 20U, m_address, m_rtcpPort); } -unsigned int CKenwoodNetwork::read(unsigned char* data) +bool CNXDNKenwoodNetwork::read(unsigned char* data) { assert(data != NULL); @@ -525,7 +529,7 @@ unsigned int CKenwoodNetwork::read(unsigned char* data) unsigned int len = readRTP(data); switch (len) { case 0U: // Nothing received - return 0U; + return false; case 35U: // Voice header or trailer return processKenwoodVoiceHeader(data); case 47U: // Voice data @@ -537,11 +541,11 @@ unsigned int CKenwoodNetwork::read(unsigned char* data) return processKenwoodData(data); default: CUtils::dump(5U, "Unknown data received from the Kenwood network", data, len); - return 0U; + return false; } } -unsigned int CKenwoodNetwork::readRTP(unsigned char* data) +unsigned int CNXDNKenwoodNetwork::readRTP(unsigned char* data) { assert(data != NULL); @@ -567,7 +571,7 @@ unsigned int CKenwoodNetwork::readRTP(unsigned char* data) return length - 12U; } -unsigned int CKenwoodNetwork::readRTCP(unsigned char* data) +unsigned int CNXDNKenwoodNetwork::readRTCP(unsigned char* data) { assert(data != NULL); @@ -598,7 +602,11 @@ unsigned int CKenwoodNetwork::readRTCP(unsigned char* data) return length - 12U; } -void CKenwoodNetwork::close() +void CNXDNKenwoodNetwork::reset() +{ +} + +void CNXDNKenwoodNetwork::close() { m_rtcpSocket.close(); m_rtpSocket.close(); @@ -606,7 +614,7 @@ void CKenwoodNetwork::close() LogMessage("Closing Kenwood connection"); } -void CKenwoodNetwork::clock(unsigned int ms) +void CNXDNKenwoodNetwork::clock(unsigned int ms) { m_rtcpTimer.clock(ms); if (m_rtcpTimer.isRunning() && m_rtcpTimer.hasExpired()) { @@ -624,7 +632,7 @@ void CKenwoodNetwork::clock(unsigned int ms) } } -unsigned int CKenwoodNetwork::processKenwoodVoiceHeader(unsigned char* inData) +bool CNXDNKenwoodNetwork::processKenwoodVoiceHeader(unsigned char* inData) { assert(inData != NULL); @@ -667,7 +675,7 @@ unsigned int CKenwoodNetwork::processKenwoodVoiceHeader(unsigned char* inData) m_seen2 = false; m_seen3 = false; m_seen4 = false; - return 33U; + return true; case 0x08U: ::memcpy(inData, outData, 33U); m_headerSeen = false; @@ -675,13 +683,13 @@ unsigned int CKenwoodNetwork::processKenwoodVoiceHeader(unsigned char* inData) m_seen2 = false; m_seen3 = false; m_seen4 = false; - return 33U; + return true; default: - return 0U; + return false; } } -unsigned int CKenwoodNetwork::processKenwoodVoiceData(unsigned char* inData) +bool CNXDNKenwoodNetwork::processKenwoodVoiceData(unsigned char* inData) { assert(inData != NULL); @@ -764,17 +772,18 @@ unsigned int CKenwoodNetwork::processKenwoodVoiceData(unsigned char* inData) ::memcpy(inData, outData, 33U); - return 33U; + return true; } -unsigned int CKenwoodNetwork::processKenwoodData(unsigned char* inData) +bool CNXDNKenwoodNetwork::processKenwoodData(unsigned char* inData) { if (inData[7U] != 0x09U && inData[7U] != 0x0BU && inData[7U] != 0x08U) - return 0U; + return false; unsigned char outData[50U]; if (inData[7U] == 0x09U || inData[7U] == 0x08U) { + // XXX outData[0U] = 0x90U; outData[1U] = inData[8U]; outData[2U] = inData[7U]; @@ -783,7 +792,7 @@ unsigned int CKenwoodNetwork::processKenwoodData(unsigned char* inData) outData[5U] = inData[12U]; outData[6U] = inData[11U]; ::memcpy(inData, outData, 7U); - return 7U; + return true; } else { outData[0U] = 0x90U; outData[1U] = inData[8U]; @@ -810,11 +819,11 @@ unsigned int CKenwoodNetwork::processKenwoodData(unsigned char* inData) outData[22U] = inData[27U]; outData[23U] = inData[29U]; ::memcpy(inData, outData, 24U); - return 24U; + return true; } } -unsigned long CKenwoodNetwork::getTimeStamp() const +unsigned long CNXDNKenwoodNetwork::getTimeStamp() const { unsigned long timeStamp = 0UL; @@ -845,7 +854,7 @@ unsigned long CKenwoodNetwork::getTimeStamp() const return timeStamp; } -unsigned int CKenwoodNetwork::processKenwoodVoiceLateEntry(unsigned char* inData) +bool CNXDNKenwoodNetwork::processKenwoodVoiceLateEntry(unsigned char* inData) { assert(inData != NULL); @@ -899,7 +908,7 @@ unsigned int CKenwoodNetwork::processKenwoodVoiceLateEntry(unsigned char* inData } if (!m_seen1 || !m_seen2 || !m_seen3 || !m_seen4) - return 0U; + return false; // Create a dummy header // Header SACCH diff --git a/NXDNKenwoodNetwork.h b/NXDNKenwoodNetwork.h index aa52d64..96da4f3 100644 --- a/NXDNKenwoodNetwork.h +++ b/NXDNKenwoodNetwork.h @@ -16,28 +16,32 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef KenwoodNetwork_H -#define KenwoodNetwork_H +#ifndef NXDNKenwoodNetwork_H +#define NXDNKenwoodNetwork_H -#include "RptNetwork.h" +#include "NXDNNetwork.h" #include "UDPSocket.h" #include "Timer.h" #include #include -class CKenwoodNetwork : public IRptNetwork { +class CNXDNKenwoodNetwork : public INXDNNetwork { public: - CKenwoodNetwork(unsigned int localPort, const std::string& rptAddress, unsigned int rptPort, bool debug); - virtual ~CKenwoodNetwork(); + CNXDNKenwoodNetwork(const std::string& localAddress, unsigned int localPort, const std::string& gwyAddress, unsigned int gwyPort, bool debug); + virtual ~CNXDNKenwoodNetwork(); virtual bool open(); - virtual bool write(const unsigned char* data, unsigned int length); + virtual void enable(bool enabled); - virtual unsigned int read(unsigned char* data); + virtual bool write(const unsigned char* data, NXDN_NETWORK_MESSAGE_TYPE type); - virtual void close(); + virtual bool read(unsigned char* data); + + virtual void reset(); + + virtual void close(); virtual void clock(unsigned int ms); @@ -67,10 +71,12 @@ private: bool processIcomVoiceHeader(const unsigned char* data); bool processIcomVoiceData(const unsigned char* data); - unsigned int processKenwoodVoiceHeader(unsigned char* data); - unsigned int processKenwoodVoiceData(unsigned char* data); - unsigned int processKenwoodVoiceLateEntry(unsigned char* data); - unsigned int processKenwoodData(unsigned char* data); + bool processIcomDataHeader(const unsigned char* data); + bool processIcomDataData(const unsigned char* data); + bool processKenwoodVoiceHeader(unsigned char* data); + bool processKenwoodVoiceData(unsigned char* data); + bool processKenwoodVoiceLateEntry(unsigned char* data); + bool processKenwoodData(unsigned char* data); bool writeRTPVoiceHeader(const unsigned char* data); bool writeRTPVoiceData(const unsigned char* data); bool writeRTPVoiceTrailer(const unsigned char* data); diff --git a/UDPSocket.cpp b/UDPSocket.cpp index ba0e35f..2899faf 100644 --- a/UDPSocket.cpp +++ b/UDPSocket.cpp @@ -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 * it under the terms of the GNU General Public License as published by @@ -258,3 +258,31 @@ void CUDPSocket::close() ::close(m_fd); #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; +} diff --git a/UDPSocket.h b/UDPSocket.h index e0af272..4c21a43 100644 --- a/UDPSocket.h +++ b/UDPSocket.h @@ -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 * it under the terms of the GNU General Public License as published by @@ -47,7 +47,9 @@ public: void close(); - static in_addr lookup(const std::string& hostName); + unsigned long getLocalAddress() const; + + static in_addr lookup(const std::string& hostName); private: std::string m_address;