From 391e382a7b0078e33b095ed76ef216e6feb75918 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 5 Jun 2023 17:30:39 +0100 Subject: [PATCH] Remove the direct network access to DMR Masters. --- Conf.cpp | 46 +-- Conf.h | 16 +- DMRControl.cpp | 4 +- DMRControl.h | 6 +- DMRDirectNetwork.cpp | 644 -------------------------------------- DMRDirectNetwork.h | 121 ------- DMRGatewayNetwork.cpp | 450 -------------------------- DMRGatewayNetwork.h | 94 ------ DMRNetwork.cpp | 427 ++++++++++++++++++++++++- DMRNetwork.h | 65 +++- DMRSlot.cpp | 4 +- DMRSlot.h | 4 +- MMDVM.ini | 9 +- MMDVMHost.cpp | 52 +-- MMDVMHost.h | 2 +- MMDVMHost.vcxproj | 6 +- MMDVMHost.vcxproj.filters | 14 +- Makefile | 2 +- Makefile.Pi.Adafruit | 2 +- Makefile.Pi.HD44780 | 2 +- Makefile.Pi.I2C | 2 +- Makefile.Pi.OLED | 2 +- Makefile.Pi.PCF8574 | 2 +- 23 files changed, 519 insertions(+), 1457 deletions(-) delete mode 100644 DMRDirectNetwork.cpp delete mode 100644 DMRDirectNetwork.h delete mode 100644 DMRGatewayNetwork.cpp delete mode 100644 DMRGatewayNetwork.h diff --git a/Conf.cpp b/Conf.cpp index fd3c0b0..bd34e44 100644 --- a/Conf.cpp +++ b/Conf.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2022 by Jonathan Naylor G4KLX + * Copyright (C) 2015-2022,2023 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 @@ -246,13 +246,10 @@ m_dstarLocalPort(0U), m_dstarNetworkModeHang(3U), m_dstarNetworkDebug(false), m_dmrNetworkEnabled(false), -m_dmrNetworkType("Gateway"), -m_dmrNetworkRemoteAddress(), -m_dmrNetworkRemotePort(0U), +m_dmrNetworkGatewayAddress(), +m_dmrNetworkGatewayPort(0U), m_dmrNetworkLocalAddress(), m_dmrNetworkLocalPort(0U), -m_dmrNetworkPassword(), -m_dmrNetworkOptions(), m_dmrNetworkDebug(false), m_dmrNetworkJitter(360U), m_dmrNetworkSlot1(true), @@ -948,20 +945,14 @@ bool CConf::read() } else if (section == SECTION_DMR_NETWORK) { if (::strcmp(key, "Enable") == 0) m_dmrNetworkEnabled = ::atoi(value) == 1; - else if (::strcmp(key, "Type") == 0) - m_dmrNetworkType = value; - else if (::strcmp(key, "RemoteAddress") == 0) - m_dmrNetworkRemoteAddress = value; - else if (::strcmp(key, "RemotePort") == 0) - m_dmrNetworkRemotePort = (unsigned short)::atoi(value); + else if (::strcmp(key, "GatewayAddress") == 0) + m_dmrNetworkGatewayAddress = value; + else if (::strcmp(key, "GatewayPort") == 0) + m_dmrNetworkGatewayPort = (unsigned short)::atoi(value); else if (::strcmp(key, "LocalAddress") == 0) m_dmrNetworkLocalAddress = value; else if (::strcmp(key, "LocalPort") == 0) m_dmrNetworkLocalPort = (unsigned short)::atoi(value); - else if (::strcmp(key, "Password") == 0) - m_dmrNetworkPassword = value; - else if (::strcmp(key, "Options") == 0) - m_dmrNetworkOptions = value; else if (::strcmp(key, "Debug") == 0) m_dmrNetworkDebug = ::atoi(value) == 1; else if (::strcmp(key, "Jitter") == 0) @@ -2067,19 +2058,14 @@ bool CConf::getDMRNetworkEnabled() const return m_dmrNetworkEnabled; } -std::string CConf::getDMRNetworkType() const +std::string CConf::getDMRNetworkGatewayAddress() const { - return m_dmrNetworkType; + return m_dmrNetworkGatewayAddress; } -std::string CConf::getDMRNetworkRemoteAddress() const +unsigned short CConf::getDMRNetworkGatewayPort() const { - return m_dmrNetworkRemoteAddress; -} - -unsigned short CConf::getDMRNetworkRemotePort() const -{ - return m_dmrNetworkRemotePort; + return m_dmrNetworkGatewayPort; } std::string CConf::getDMRNetworkLocalAddress() const @@ -2092,16 +2078,6 @@ unsigned short CConf::getDMRNetworkLocalPort() const return m_dmrNetworkLocalPort; } -std::string CConf::getDMRNetworkPassword() const -{ - return m_dmrNetworkPassword; -} - -std::string CConf::getDMRNetworkOptions() const -{ - return m_dmrNetworkOptions; -} - unsigned int CConf::getDMRNetworkModeHang() const { return m_dmrNetworkModeHang; diff --git a/Conf.h b/Conf.h index f7de0b3..1071dcc 100644 --- a/Conf.h +++ b/Conf.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2022 by Jonathan Naylor G4KLX + * Copyright (C) 2015-2023 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 @@ -248,13 +248,10 @@ public: // The DMR Network section bool getDMRNetworkEnabled() const; - std::string getDMRNetworkType() const; - std::string getDMRNetworkRemoteAddress() const; - unsigned short getDMRNetworkRemotePort() const; + std::string getDMRNetworkGatewayAddress() const; + unsigned short getDMRNetworkGatewayPort() const; std::string getDMRNetworkLocalAddress() const; unsigned short getDMRNetworkLocalPort() const; - std::string getDMRNetworkPassword() const; - std::string getDMRNetworkOptions() const; bool getDMRNetworkDebug() const; unsigned int getDMRNetworkJitter() const; bool getDMRNetworkSlot1() const; @@ -577,13 +574,10 @@ private: bool m_dstarNetworkDebug; bool m_dmrNetworkEnabled; - std::string m_dmrNetworkType; - std::string m_dmrNetworkRemoteAddress; - unsigned short m_dmrNetworkRemotePort; + std::string m_dmrNetworkGatewayAddress; + unsigned short m_dmrNetworkGatewayPort; std::string m_dmrNetworkLocalAddress; unsigned short m_dmrNetworkLocalPort; - std::string m_dmrNetworkPassword; - std::string m_dmrNetworkOptions; bool m_dmrNetworkDebug; unsigned int m_dmrNetworkJitter; bool m_dmrNetworkSlot1; diff --git a/DMRControl.cpp b/DMRControl.cpp index 5761080..34f080c 100644 --- a/DMRControl.cpp +++ b/DMRControl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2021 Jonathan Naylor, G4KLX + * Copyright (C) 2015-2021,2023 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 @@ -21,7 +21,7 @@ #include #include -CDMRControl::CDMRControl(unsigned int id, unsigned int colorCode, unsigned int callHang, bool selfOnly, bool embeddedLCOnly, bool dumpTAData, const std::vector& prefixes, const std::vector& blacklist, const std::vector& whitelist, const std::vector& slot1TGWhitelist, const std::vector& slot2TGWhitelist, unsigned int timeout, CModem* modem, IDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssi, unsigned int jitter, DMR_OVCM_TYPES ovcm) : +CDMRControl::CDMRControl(unsigned int id, unsigned int colorCode, unsigned int callHang, bool selfOnly, bool embeddedLCOnly, bool dumpTAData, const std::vector& prefixes, const std::vector& blacklist, const std::vector& whitelist, const std::vector& slot1TGWhitelist, const std::vector& slot2TGWhitelist, unsigned int timeout, CModem* modem, CDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssi, unsigned int jitter, DMR_OVCM_TYPES ovcm) : m_colorCode(colorCode), m_modem(modem), m_network(network), diff --git a/DMRControl.h b/DMRControl.h index 9144194..040fe92 100644 --- a/DMRControl.h +++ b/DMRControl.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2021 by Jonathan Naylor G4KLX + * Copyright (C) 2015-2021,2023 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 @@ -31,7 +31,7 @@ class CDMRControl { public: - CDMRControl(unsigned int id, unsigned int colorCode, unsigned int callHang, bool selfOnly, bool embeddedLCOnly, bool dumpTAData, const std::vector& prefixes, const std::vector& blacklist, const std::vector& whitelist, const std::vector& slot1TGWhitelist, const std::vector& slot2TGWhitelist, unsigned int timeout, CModem* modem, IDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssi, unsigned int jitter, DMR_OVCM_TYPES ovcm); + CDMRControl(unsigned int id, unsigned int colorCode, unsigned int callHang, bool selfOnly, bool embeddedLCOnly, bool dumpTAData, const std::vector& prefixes, const std::vector& blacklist, const std::vector& whitelist, const std::vector& slot1TGWhitelist, const std::vector& slot2TGWhitelist, unsigned int timeout, CModem* modem, CDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssi, unsigned int jitter, DMR_OVCM_TYPES ovcm); ~CDMRControl(); bool processWakeup(const unsigned char* data); @@ -51,7 +51,7 @@ public: private: unsigned int m_colorCode; CModem* m_modem; - IDMRNetwork* m_network; + CDMRNetwork* m_network; CDMRSlot m_slot1; CDMRSlot m_slot2; CDMRLookup* m_lookup; diff --git a/DMRDirectNetwork.cpp b/DMRDirectNetwork.cpp deleted file mode 100644 index ba36a69..0000000 --- a/DMRDirectNetwork.cpp +++ /dev/null @@ -1,644 +0,0 @@ -/* - * Copyright (C) 2015,2016,2017,2018,2020,2021 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 "DMRDirectNetwork.h" - -#include "SHA256.h" -#include "Utils.h" -#include "Log.h" - -#include -#include - -const unsigned int BUFFER_LENGTH = 500U; - -const unsigned int HOMEBREW_DATA_PACKET_LENGTH = 55U; - - -CDMRDirectNetwork::CDMRDirectNetwork(const std::string& address, unsigned short port, const std::string& localAddress, unsigned short localPort, unsigned int id, const std::string& password, bool duplex, const char* version, bool slot1, bool slot2, HW_TYPE hwType, bool debug) : -m_address(address), -m_port(port), -m_addr(), -m_addrLen(0U), -m_id(NULL), -m_password(password), -m_duplex(duplex), -m_version(version), -m_debug(debug), -m_socket(localAddress, localPort), -m_enabled(false), -m_slot1(slot1), -m_slot2(slot2), -m_hwType(hwType), -m_status(WAITING_CONNECT), -m_retryTimer(1000U, 10U), -m_timeoutTimer(1000U, 60U), -m_buffer(NULL), -m_streamId(NULL), -m_salt(NULL), -m_rxData(1000U, "DMR Network"), -m_options(), -m_random(), -m_callsign(), -m_rxFrequency(0U), -m_txFrequency(0U), -m_power(0U), -m_colorCode(0U), -m_latitude(0.0F), -m_longitude(0.0F), -m_height(0), -m_location(), -m_description(), -m_url(), -m_beacon(false) -{ - assert(!address.empty()); - assert(port > 0U); - assert(id > 1000U); - assert(!password.empty()); - - m_buffer = new unsigned char[BUFFER_LENGTH]; - m_salt = new unsigned char[sizeof(uint32_t)]; - m_id = new uint8_t[4U]; - m_streamId = new uint32_t[2U]; - - m_id[0U] = id >> 24; - m_id[1U] = id >> 16; - m_id[2U] = id >> 8; - m_id[3U] = id >> 0; - - std::random_device rd; - std::mt19937 mt(rd()); - m_random = mt; - - std::uniform_int_distribution dist(0x00000001, 0xfffffffe); - m_streamId[0U] = dist(m_random); - m_streamId[1U] = dist(m_random); -} - -CDMRDirectNetwork::~CDMRDirectNetwork() -{ - delete[] m_streamId; - delete[] m_buffer; - delete[] m_salt; - delete[] m_id; -} - -void CDMRDirectNetwork::setOptions(const std::string& options) -{ - m_options = options; -} - -void CDMRDirectNetwork::setConfig(const std::string& callsign, unsigned int rxFrequency, unsigned int txFrequency, unsigned int power, unsigned int colorCode, float latitude, float longitude, int height, const std::string& location, const std::string& description, const std::string& url) -{ - m_callsign = callsign; - m_rxFrequency = rxFrequency; - m_txFrequency = txFrequency; - m_power = power; - m_colorCode = colorCode; - m_latitude = latitude; - m_longitude = longitude; - m_height = height; - m_location = location; - m_description = description; - m_url = url; -} - -bool CDMRDirectNetwork::open() -{ - if (CUDPSocket::lookup(m_address, m_port, m_addr, m_addrLen) != 0) { - LogError("DMR, Could not lookup the address of the DMR Network"); - return false; - } - - LogMessage("Opening DMR Network"); - - m_status = WAITING_CONNECT; - m_timeoutTimer.stop(); - m_retryTimer.start(); - - return true; -} - -void CDMRDirectNetwork::enable(bool enabled) -{ - if (!enabled && m_enabled) - m_rxData.clear(); - - m_enabled = enabled; -} - -bool CDMRDirectNetwork::read(CDMRData& data) -{ - if (m_status != RUNNING) - return false; - - if (m_rxData.isEmpty()) - return false; - - unsigned char length = 0U; - m_rxData.getData(&length, 1U); - m_rxData.getData(m_buffer, length); - - // Is this a data packet? - if (::memcmp(m_buffer, "DMRD", 4U) != 0) - return false; - - unsigned char seqNo = m_buffer[4U]; - - unsigned int srcId = (m_buffer[5U] << 16) | (m_buffer[6U] << 8) | (m_buffer[7U] << 0); - - unsigned int dstId = (m_buffer[8U] << 16) | (m_buffer[9U] << 8) | (m_buffer[10U] << 0); - - unsigned int slotNo = (m_buffer[15U] & 0x80U) == 0x80U ? 2U : 1U; - - // DMO mode slot disabling - if (slotNo == 1U && !m_duplex) - return false; - - // Individual slot disabling - if (slotNo == 1U && !m_slot1) - return false; - if (slotNo == 2U && !m_slot2) - return false; - - FLCO flco = (m_buffer[15U] & 0x40U) == 0x40U ? FLCO_USER_USER : FLCO_GROUP; - - data.setSeqNo(seqNo); - data.setSlotNo(slotNo); - data.setSrcId(srcId); - data.setDstId(dstId); - data.setFLCO(flco); - - bool dataSync = (m_buffer[15U] & 0x20U) == 0x20U; - bool voiceSync = (m_buffer[15U] & 0x10U) == 0x10U; - - if (dataSync) { - unsigned char dataType = m_buffer[15U] & 0x0FU; - data.setData(m_buffer + 20U); - data.setDataType(dataType); - data.setN(0U); - } else if (voiceSync) { - data.setData(m_buffer + 20U); - data.setDataType(DT_VOICE_SYNC); - data.setN(0U); - } else { - unsigned char n = m_buffer[15U] & 0x0FU; - data.setData(m_buffer + 20U); - data.setDataType(DT_VOICE); - data.setN(n); - } - - return true; -} - -bool CDMRDirectNetwork::write(const CDMRData& data) -{ - if (m_status != RUNNING) - return false; - - unsigned char buffer[HOMEBREW_DATA_PACKET_LENGTH]; - ::memset(buffer, 0x00U, HOMEBREW_DATA_PACKET_LENGTH); - - buffer[0U] = 'D'; - buffer[1U] = 'M'; - buffer[2U] = 'R'; - buffer[3U] = 'D'; - - unsigned int srcId = data.getSrcId(); - buffer[5U] = srcId >> 16; - buffer[6U] = srcId >> 8; - buffer[7U] = srcId >> 0; - - unsigned int dstId = data.getDstId(); - buffer[8U] = dstId >> 16; - buffer[9U] = dstId >> 8; - buffer[10U] = dstId >> 0; - - ::memcpy(buffer + 11U, m_id, 4U); - - unsigned int slotNo = data.getSlotNo(); - - // Individual slot disabling - if (slotNo == 1U && !m_slot1) - return false; - if (slotNo == 2U && !m_slot2) - return false; - - buffer[15U] = slotNo == 1U ? 0x00U : 0x80U; - - FLCO flco = data.getFLCO(); - buffer[15U] |= flco == FLCO_GROUP ? 0x00U : 0x40U; - - unsigned int slotIndex = slotNo - 1U; - - std::uniform_int_distribution dist(0x00000001, 0xfffffffe); - unsigned char dataType = data.getDataType(); - if (dataType == DT_VOICE_SYNC) { - buffer[15U] |= 0x10U; - } else if (dataType == DT_VOICE) { - buffer[15U] |= data.getN(); - } else { - if (dataType == DT_VOICE_LC_HEADER) - m_streamId[slotIndex] = dist(m_random); - - if (dataType == DT_CSBK || dataType == DT_DATA_HEADER) - m_streamId[slotIndex] = dist(m_random); - - buffer[15U] |= (0x20U | dataType); - } - - buffer[4U] = data.getSeqNo(); - - ::memcpy(buffer + 16U, m_streamId + slotIndex, 4U); - - data.getData(buffer + 20U); - - buffer[53U] = data.getBER(); - - buffer[54U] = data.getRSSI(); - - write(buffer, HOMEBREW_DATA_PACKET_LENGTH); - - return true; -} - -bool CDMRDirectNetwork::writeRadioPosition(unsigned int id, const unsigned char* data) -{ - if (m_status != RUNNING) - return false; - - unsigned char buffer[20U]; - - ::memcpy(buffer + 0U, "DMRG", 4U); - - buffer[4U] = id >> 16; - buffer[5U] = id >> 8; - buffer[6U] = id >> 0; - - ::memcpy(buffer + 7U, data + 2U, 7U); - - return write(buffer, 14U); -} - -bool CDMRDirectNetwork::writeTalkerAlias(unsigned int id, unsigned char type, const unsigned char* data) -{ - if (m_status != RUNNING) - return false; - - unsigned char buffer[20U]; - - ::memcpy(buffer + 0U, "DMRA", 4U); - - buffer[4U] = id >> 16; - buffer[5U] = id >> 8; - buffer[6U] = id >> 0; - - buffer[7U] = type; - - ::memcpy(buffer + 8U, data + 2U, 7U); - - return write(buffer, 15U); -} - -bool CDMRDirectNetwork::isConnected() const -{ - return (m_status == RUNNING); -} - -void CDMRDirectNetwork::close(bool sayGoodbye) -{ - LogMessage("Closing DMR Network"); - - if (sayGoodbye && (m_status == RUNNING)) { - unsigned char buffer[9U]; - ::memcpy(buffer + 0U, "RPTCL", 5U); - ::memcpy(buffer + 5U, m_id, 4U); - write(buffer, 9U); - } - - m_socket.close(); - - m_retryTimer.stop(); - m_timeoutTimer.stop(); -} - -void CDMRDirectNetwork::clock(unsigned int ms) -{ - m_retryTimer.clock(ms); - if (m_retryTimer.isRunning() && m_retryTimer.hasExpired()) { - switch (m_status) { - case WAITING_CONNECT: - if (m_socket.open(m_addr.ss_family)) { - if (writeLogin()) { - m_status = WAITING_LOGIN; - } - } - break; - case WAITING_LOGIN: - writeLogin(); - break; - case WAITING_AUTHORISATION: - writeAuthorisation(); - break; - case WAITING_OPTIONS: - writeOptions(); - break; - case WAITING_CONFIG: - writeConfig(); - break; - case RUNNING: - writePing(); - break; - default: - break; - } - - m_retryTimer.start(); - } - - sockaddr_storage address; - unsigned int addrlen; - int length = m_socket.read(m_buffer, BUFFER_LENGTH, address, addrlen); - if (length < 0) { - LogError("DMR, Socket has failed, retrying connection to the master"); - close(false); - open(); - return; - } - - if (length > 0) { - if (!CUDPSocket::match(m_addr, address)) { - LogMessage("DMR, packet received from an invalid source"); - return; - } - - if (m_debug) - CUtils::dump(1U, "DMR, Network Received", m_buffer, length); - - if (::memcmp(m_buffer, "DMRD", 4U) == 0) { - if (m_enabled) { - unsigned char len = length; - m_rxData.addData(&len, 1U); - m_rxData.addData(m_buffer, len); - } - } else if (::memcmp(m_buffer, "MSTNAK", 6U) == 0) { - if (m_status == RUNNING) { - LogWarning("DMR, Login to the master has failed, retrying login ..."); - m_status = WAITING_LOGIN; - m_timeoutTimer.start(); - m_retryTimer.start(); - } else { - /* Once the modem death spiral has been prevented in Modem.cpp - the Network sometimes times out and reaches here. - We want it to reconnect so... */ - LogError("DMR, Login to the master has failed, retrying network ..."); - close(false); - open(); - return; - } - } else if (::memcmp(m_buffer, "RPTACK", 6U) == 0) { - switch (m_status) { - case WAITING_LOGIN: - LogDebug("DMR, Sending authorisation"); - ::memcpy(m_salt, m_buffer + 6U, sizeof(uint32_t)); - writeAuthorisation(); - m_status = WAITING_AUTHORISATION; - m_timeoutTimer.start(); - m_retryTimer.start(); - break; - case WAITING_AUTHORISATION: - LogDebug("DMR, Sending configuration"); - writeConfig(); - m_status = WAITING_CONFIG; - m_timeoutTimer.start(); - m_retryTimer.start(); - break; - case WAITING_CONFIG: - if (m_options.empty()) { - LogMessage("DMR, Logged into the master successfully"); - m_status = RUNNING; - } else { - LogDebug("DMR, Sending options"); - writeOptions(); - m_status = WAITING_OPTIONS; - } - m_timeoutTimer.start(); - m_retryTimer.start(); - break; - case WAITING_OPTIONS: - LogMessage("DMR, Logged into the master successfully"); - m_status = RUNNING; - m_timeoutTimer.start(); - m_retryTimer.start(); - break; - default: - break; - } - } else if (::memcmp(m_buffer, "MSTCL", 5U) == 0) { - LogError("DMR, Master is closing down"); - close(false); - open(); - } else if (::memcmp(m_buffer, "MSTPONG", 7U) == 0) { - m_timeoutTimer.start(); - } else if (::memcmp(m_buffer, "RPTSBKN", 7U) == 0) { - m_beacon = true; - } else { - CUtils::dump("DMR, Unknown packet from the master", m_buffer, length); - } - } - - m_timeoutTimer.clock(ms); - if (m_timeoutTimer.isRunning() && m_timeoutTimer.hasExpired()) { - LogError("DMR, Connection to the master has timed out, retrying connection"); - close(false); - open(); - } -} - -bool CDMRDirectNetwork::writeLogin() -{ - unsigned char buffer[8U]; - - ::memcpy(buffer + 0U, "RPTL", 4U); - ::memcpy(buffer + 4U, m_id, 4U); - - return write(buffer, 8U); -} - -bool CDMRDirectNetwork::writeAuthorisation() -{ - size_t size = m_password.size(); - - unsigned char* in = new unsigned char[size + sizeof(uint32_t)]; - ::memcpy(in, m_salt, sizeof(uint32_t)); - for (size_t i = 0U; i < size; i++) - in[i + sizeof(uint32_t)] = m_password.at(i); - - unsigned char out[40U]; - ::memcpy(out + 0U, "RPTK", 4U); - ::memcpy(out + 4U, m_id, 4U); - - CSHA256 sha256; - sha256.buffer(in, (unsigned int)(size + sizeof(uint32_t)), out + 8U); - - delete[] in; - - return write(out, 40U); -} - -bool CDMRDirectNetwork::writeOptions() -{ - char buffer[300U]; - - ::memcpy(buffer + 0U, "RPTO", 4U); - ::memcpy(buffer + 4U, m_id, 4U); - ::strcpy(buffer + 8U, m_options.c_str()); - - return write((unsigned char*)buffer, (unsigned int)m_options.length() + 8U); -} - -bool CDMRDirectNetwork::writeConfig() -{ - const char* software; - char slots = '0'; - if (m_duplex) { - if (m_slot1 && m_slot2) - slots = '3'; - else if (m_slot1 && !m_slot2) - slots = '1'; - else if (!m_slot1 && m_slot2) - slots = '2'; - - switch (m_hwType) { - case HWT_MMDVM: - software = "MMDVM"; - break; - case HWT_MMDVM_HS: - software = "MMDVM_MMDVM_HS"; - break; - case HWT_MMDVM_HS_DUAL_HAT: - software = "MMDVM_MMDVM_HS_Dual_Hat"; - break; - case HWT_NANO_HOTSPOT: - software = "MMDVM_Nano_hotSPOT"; - break; - default: - software = "MMDVM_Unknown"; - break; - } - } else { - slots = '4'; - - switch (m_hwType) { - case HWT_MMDVM: - software = "MMDVM_DMO"; - break; - case HWT_DVMEGA: - software = "MMDVM_DVMega"; - break; - case HWT_MMDVM_ZUMSPOT: - software = "MMDVM_ZUMspot"; - break; - case HWT_MMDVM_HS_HAT: - software = "MMDVM_MMDVM_HS_Hat"; - break; - case HWT_MMDVM_HS_DUAL_HAT: - software = "MMDVM_MMDVM_HS_Dual_Hat"; - break; - case HWT_NANO_HOTSPOT: - software = "MMDVM_Nano_hotSPOT"; - break; - case HWT_NANO_DV: - software = "MMDVM_Nano_DV"; - break; - case HWT_D2RG_MMDVM_HS: - software = "MMDVM_D2RG_MMDVM_HS"; - break; - case HWT_MMDVM_HS: - software = "MMDVM_MMDVM_HS"; - break; - default: - software = "MMDVM_Unknown"; - break; - } - } - - char buffer[400U]; - - ::memcpy(buffer + 0U, "RPTC", 4U); - ::memcpy(buffer + 4U, m_id, 4U); - - char latitude[20U]; - ::sprintf(latitude, "%08f", m_latitude); - - char longitude[20U]; - ::sprintf(longitude, "%09f", m_longitude); - - unsigned int power = m_power; - if (power > 99U) - power = 99U; - - int height = m_height; - if (height > 999) - height = 999; - - ::sprintf(buffer + 8U, "%-8.8s%09u%09u%02u%02u%8.8s%9.9s%03d%-20.20s%-19.19s%c%-124.124s%-40.40s%-40.40s", m_callsign.c_str(), - m_rxFrequency, m_txFrequency, power, m_colorCode, latitude, longitude, height, m_location.c_str(), - m_description.c_str(), slots, m_url.c_str(), m_version, software); - - return write((unsigned char*)buffer, 302U); -} - -bool CDMRDirectNetwork::writePing() -{ - unsigned char buffer[11U]; - - ::memcpy(buffer + 0U, "RPTPING", 7U); - ::memcpy(buffer + 7U, m_id, 4U); - - return write(buffer, 11U); -} - -bool CDMRDirectNetwork::wantsBeacon() -{ - bool beacon = m_beacon; - - m_beacon = false; - - return beacon; -} - -bool CDMRDirectNetwork::write(const unsigned char* data, unsigned int length) -{ - assert(data != NULL); - assert(length > 0U); - - if (m_debug) - CUtils::dump(1U, "DMR Network Transmitted", data, length); - - bool ret = m_socket.write(data, length, m_addr, m_addrLen); - if (!ret) { - LogError("DMR, Socket has failed when writing data to the master, retrying connection"); - close(false); - open(); - return false; - } - - return true; -} diff --git a/DMRDirectNetwork.h b/DMRDirectNetwork.h deleted file mode 100644 index 5d6a959..0000000 --- a/DMRDirectNetwork.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (C) 2015,2016,2017,2018,2020,2021 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. - */ - -#if !defined(DMRDirectNetwork_H) -#define DMRDirectNetwork_H - -#include "DMRNetwork.h" -#include "UDPSocket.h" -#include "Timer.h" -#include "RingBuffer.h" -#include "DMRData.h" - -#include -#include -#include - -class CDMRDirectNetwork : public IDMRNetwork -{ -public: - CDMRDirectNetwork(const std::string& remoteAddress, unsigned short remotePort, const std::string& localAddress, unsigned short localPort, unsigned int id, const std::string& password, bool duplex, const char* version, bool slot1, bool slot2, HW_TYPE hwType, bool debug); - virtual ~CDMRDirectNetwork(); - - virtual void setOptions(const std::string& options); - - virtual void setConfig(const std::string& callsign, unsigned int rxFrequency, unsigned int txFrequency, unsigned int power, unsigned int colorCode, float latitude, float longitude, int height, const std::string& location, const std::string& description, const std::string& url); - - virtual bool open(); - - virtual void enable(bool enabled); - - virtual bool read(CDMRData& data); - - virtual bool write(const CDMRData& data); - - virtual bool writeRadioPosition(unsigned int id, const unsigned char* data); - - virtual bool writeTalkerAlias(unsigned int id, unsigned char type, const unsigned char* data); - - virtual bool wantsBeacon(); - - virtual void clock(unsigned int ms); - - virtual bool isConnected() const; - - virtual void close(bool sayGoodbye); - -private: - std::string m_address; - unsigned short m_port; - sockaddr_storage m_addr; - unsigned int m_addrLen; - uint8_t* m_id; - std::string m_password; - bool m_duplex; - const char* m_version; - bool m_debug; - CUDPSocket m_socket; - bool m_enabled; - bool m_slot1; - bool m_slot2; - HW_TYPE m_hwType; - - enum STATUS { - WAITING_CONNECT, - WAITING_LOGIN, - WAITING_AUTHORISATION, - WAITING_CONFIG, - WAITING_OPTIONS, - RUNNING - }; - - STATUS m_status; - CTimer m_retryTimer; - CTimer m_timeoutTimer; - unsigned char* m_buffer; - uint32_t* m_streamId; - unsigned char* m_salt; - - CRingBuffer m_rxData; - - std::string m_options; - - std::mt19937 m_random; - std::string m_callsign; - unsigned int m_rxFrequency; - unsigned int m_txFrequency; - unsigned int m_power; - unsigned int m_colorCode; - float m_latitude; - float m_longitude; - int m_height; - std::string m_location; - std::string m_description; - std::string m_url; - bool m_beacon; - - bool writeLogin(); - bool writeAuthorisation(); - bool writeOptions(); - bool writeConfig(); - bool writePing(); - - bool write(const unsigned char* data, unsigned int length); -}; - -#endif diff --git a/DMRGatewayNetwork.cpp b/DMRGatewayNetwork.cpp deleted file mode 100644 index 5dd55b5..0000000 --- a/DMRGatewayNetwork.cpp +++ /dev/null @@ -1,450 +0,0 @@ -/* - * Copyright (C) 2015-2021 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 "DMRGatewayNetwork.h" - -#include "Utils.h" -#include "Log.h" - -#include -#include -#include -#include - -const unsigned int BUFFER_LENGTH = 500U; - -const unsigned int HOMEBREW_DATA_PACKET_LENGTH = 55U; - - -CDMRGatewayNetwork::CDMRGatewayNetwork(const std::string& address, unsigned short port, const std::string& localAddress, unsigned short localPort, unsigned int id, bool duplex, const char* version, bool slot1, bool slot2, HW_TYPE hwType, bool debug) : -m_addressStr(address), -m_addr(), -m_addrLen(0U), -m_port(port), -m_id(NULL), -m_duplex(duplex), -m_version(version), -m_debug(debug), -m_socket(localAddress, localPort), -m_enabled(false), -m_slot1(slot1), -m_slot2(slot2), -m_hwType(hwType), -m_buffer(NULL), -m_streamId(NULL), -m_rxData(1000U, "DMR Network"), -m_beacon(false), -m_random(), -m_callsign(), -m_rxFrequency(0U), -m_txFrequency(0U), -m_power(0U), -m_colorCode(0U), -m_pingTimer(1000U, 10U) -{ - assert(!address.empty()); - assert(port > 0U); - assert(id > 1000U); - - if (CUDPSocket::lookup(m_addressStr, m_port, m_addr, m_addrLen) != 0) - m_addrLen = 0U; - - m_buffer = new unsigned char[BUFFER_LENGTH]; - m_id = new uint8_t[4U]; - m_streamId = new uint32_t[2U]; - - m_id[0U] = id >> 24; - m_id[1U] = id >> 16; - m_id[2U] = id >> 8; - m_id[3U] = id >> 0; - - std::random_device rd; - std::mt19937 mt(rd()); - m_random = mt; - - std::uniform_int_distribution dist(0x00000001, 0xfffffffe); - m_streamId[0U] = dist(m_random); - m_streamId[1U] = dist(m_random); -} - -CDMRGatewayNetwork::~CDMRGatewayNetwork() -{ - delete[] m_buffer; - delete[] m_streamId; - delete[] m_id; -} - -void CDMRGatewayNetwork::setConfig(const std::string & callsign, unsigned int rxFrequency, unsigned int txFrequency, unsigned int power, unsigned int colorCode, float latitude, float longitude, int height, const std::string& location, const std::string& description, const std::string& url) -{ - m_callsign = callsign; - m_rxFrequency = rxFrequency; - m_txFrequency = txFrequency; - m_power = power; - m_colorCode = colorCode; -} - -void CDMRGatewayNetwork::setOptions(const std::string& options) -{ -} - -bool CDMRGatewayNetwork::open() -{ - if (m_addrLen == 0U) { - LogError("Unable to resolve the address of the DMR Network"); - return false; - } - - LogMessage("DMR, Opening DMR Network"); - - bool ret = m_socket.open(m_addr); - if (ret) - m_pingTimer.start(); - - return ret; -} - -void CDMRGatewayNetwork::enable(bool enabled) -{ - if (!enabled && m_enabled) - m_rxData.clear(); - - m_enabled = enabled; -} - -bool CDMRGatewayNetwork::read(CDMRData& data) -{ - if (m_rxData.isEmpty()) - return false; - - unsigned char length = 0U; - m_rxData.getData(&length, 1U); - m_rxData.getData(m_buffer, length); - - // Is this a data packet? - if (::memcmp(m_buffer, "DMRD", 4U) != 0) - return false; - - unsigned char seqNo = m_buffer[4U]; - - unsigned int srcId = (m_buffer[5U] << 16) | (m_buffer[6U] << 8) | (m_buffer[7U] << 0); - - unsigned int dstId = (m_buffer[8U] << 16) | (m_buffer[9U] << 8) | (m_buffer[10U] << 0); - - unsigned int slotNo = (m_buffer[15U] & 0x80U) == 0x80U ? 2U : 1U; - - // DMO mode slot disabling - if (slotNo == 1U && !m_duplex) - return false; - - // Individual slot disabling - if (slotNo == 1U && !m_slot1) - return false; - if (slotNo == 2U && !m_slot2) - return false; - - FLCO flco = (m_buffer[15U] & 0x40U) == 0x40U ? FLCO_USER_USER : FLCO_GROUP; - - data.setSeqNo(seqNo); - data.setSlotNo(slotNo); - data.setSrcId(srcId); - data.setDstId(dstId); - data.setFLCO(flco); - - bool dataSync = (m_buffer[15U] & 0x20U) == 0x20U; - bool voiceSync = (m_buffer[15U] & 0x10U) == 0x10U; - - if (dataSync) { - unsigned char dataType = m_buffer[15U] & 0x0FU; - data.setData(m_buffer + 20U); - data.setDataType(dataType); - data.setN(0U); - } else if (voiceSync) { - data.setData(m_buffer + 20U); - data.setDataType(DT_VOICE_SYNC); - data.setN(0U); - } else { - unsigned char n = m_buffer[15U] & 0x0FU; - data.setData(m_buffer + 20U); - data.setDataType(DT_VOICE); - data.setN(n); - } - - return true; -} - -bool CDMRGatewayNetwork::write(const CDMRData& data) -{ - unsigned char buffer[HOMEBREW_DATA_PACKET_LENGTH]; - ::memset(buffer, 0x00U, HOMEBREW_DATA_PACKET_LENGTH); - - buffer[0U] = 'D'; - buffer[1U] = 'M'; - buffer[2U] = 'R'; - buffer[3U] = 'D'; - - unsigned int srcId = data.getSrcId(); - buffer[5U] = srcId >> 16; - buffer[6U] = srcId >> 8; - buffer[7U] = srcId >> 0; - - unsigned int dstId = data.getDstId(); - buffer[8U] = dstId >> 16; - buffer[9U] = dstId >> 8; - buffer[10U] = dstId >> 0; - - ::memcpy(buffer + 11U, m_id, 4U); - - unsigned int slotNo = data.getSlotNo(); - - // Individual slot disabling - if (slotNo == 1U && !m_slot1) - return false; - if (slotNo == 2U && !m_slot2) - return false; - - buffer[15U] = slotNo == 1U ? 0x00U : 0x80U; - - FLCO flco = data.getFLCO(); - buffer[15U] |= flco == FLCO_GROUP ? 0x00U : 0x40U; - - unsigned int slotIndex = slotNo - 1U; - - std::uniform_int_distribution dist(0x00000001, 0xfffffffe); - unsigned char dataType = data.getDataType(); - if (dataType == DT_VOICE_SYNC) { - buffer[15U] |= 0x10U; - } else if (dataType == DT_VOICE) { - buffer[15U] |= data.getN(); - } else { - if (dataType == DT_VOICE_LC_HEADER) - m_streamId[slotIndex] = dist(m_random); - - if (dataType == DT_CSBK || dataType == DT_DATA_HEADER) - m_streamId[slotIndex] = dist(m_random); - - buffer[15U] |= (0x20U | dataType); - } - - buffer[4U] = data.getSeqNo(); - - ::memcpy(buffer + 16U, m_streamId + slotIndex, 4U); - - data.getData(buffer + 20U); - - buffer[53U] = data.getBER(); - - buffer[54U] = data.getRSSI(); - - write(buffer, HOMEBREW_DATA_PACKET_LENGTH); - - return true; -} - -bool CDMRGatewayNetwork::writeRadioPosition(unsigned int id, const unsigned char* data) -{ - unsigned char buffer[20U]; - - ::memcpy(buffer + 0U, "DMRG", 4U); - - buffer[4U] = id >> 16; - buffer[5U] = id >> 8; - buffer[6U] = id >> 0; - - ::memcpy(buffer + 7U, data + 2U, 7U); - - return write(buffer, 14U); -} - -bool CDMRGatewayNetwork::writeTalkerAlias(unsigned int id, unsigned char type, const unsigned char* data) -{ - unsigned char buffer[20U]; - - ::memcpy(buffer + 0U, "DMRA", 4U); - - buffer[4U] = id >> 16; - buffer[5U] = id >> 8; - buffer[6U] = id >> 0; - - buffer[7U] = type; - - ::memcpy(buffer + 8U, data + 2U, 7U); - - return write(buffer, 15U); -} - -bool CDMRGatewayNetwork::isConnected() const -{ - return (m_addrLen != 0); -} - -void CDMRGatewayNetwork::close(bool sayGoodbye) -{ - LogMessage("DMR, Closing DMR Network"); - - m_socket.close(); -} - -void CDMRGatewayNetwork::clock(unsigned int ms) -{ - m_pingTimer.clock(ms); - if (m_pingTimer.isRunning() && m_pingTimer.hasExpired()) { - writeConfig(); - m_pingTimer.start(); - } - - sockaddr_storage address; - unsigned int addrLen; - int length = m_socket.read(m_buffer, BUFFER_LENGTH, address, addrLen); - if (length <= 0) - return; - - if (!CUDPSocket::match(m_addr, address)) { - LogMessage("DMR, packet received from an invalid source"); - return; - } - - if (m_debug) - CUtils::dump(1U, "DMR Network Received", m_buffer, length); - - if (::memcmp(m_buffer, "DMRD", 4U) == 0) { - if (m_enabled) { - unsigned char len = length; - m_rxData.addData(&len, 1U); - m_rxData.addData(m_buffer, len); - } - } else if (::memcmp(m_buffer, "DMRP", 4U) == 0) { - ; - } else if (::memcmp(m_buffer, "DMRB", 4U) == 0) { - m_beacon = true; - } else { - CUtils::dump("DMR, unknown packet from the DMR Network", m_buffer, length); - } -} - -bool CDMRGatewayNetwork::writeConfig() -{ - const char* software; - char slots = '0'; - if (m_duplex) { - if (m_slot1 && m_slot2) - slots = '3'; - else if (m_slot1 && !m_slot2) - slots = '1'; - else if (!m_slot1 && m_slot2) - slots = '2'; - - switch (m_hwType) { - case HWT_MMDVM: - software = "MMDVM"; - break; - case HWT_MMDVM_HS: - software = "MMDVM_MMDVM_HS"; - break; - case HWT_MMDVM_HS_DUAL_HAT: - software = "MMDVM_MMDVM_HS_Dual_Hat"; - break; - case HWT_NANO_HOTSPOT: - software = "MMDVM_Nano_hotSPOT"; - break; - default: - software = "MMDVM_Unknown"; - break; - } - } else { - slots = '4'; - - switch (m_hwType) { - case HWT_MMDVM: - software = "MMDVM_DMO"; - break; - case HWT_DVMEGA: - software = "MMDVM_DVMega"; - break; - case HWT_MMDVM_ZUMSPOT: - software = "MMDVM_ZUMspot"; - break; - case HWT_MMDVM_HS_HAT: - software = "MMDVM_MMDVM_HS_Hat"; - break; - case HWT_MMDVM_HS_DUAL_HAT: - software = "MMDVM_MMDVM_HS_Dual_Hat"; - break; - case HWT_NANO_HOTSPOT: - software = "MMDVM_Nano_hotSPOT"; - break; - case HWT_NANO_DV: - software = "MMDVM_Nano_DV"; - break; - case HWT_D2RG_MMDVM_HS: - software = "MMDVM_D2RG_MMDVM_HS"; - break; - case HWT_MMDVM_HS: - software = "MMDVM_MMDVM_HS"; - break; - case HWT_OPENGD77_HS: - software = "MMDVM_OpenGD77_HS"; - break; - case HWT_SKYBRIDGE: - software = "MMDVM_SkyBridge"; - break; - default: - software = "MMDVM_Unknown"; - break; - } - } - - unsigned int power = m_power; - if (power > 99U) - power = 99U; - - char buffer[150U]; - - ::memcpy(buffer + 0U, "DMRC", 4U); - ::memcpy(buffer + 4U, m_id, 4U); - ::sprintf(buffer + 8U, "%-8.8s%09u%09u%02u%02u%c%-40.40s%-40.40s", - m_callsign.c_str(), m_rxFrequency, m_txFrequency, power, m_colorCode, slots, m_version, - software); - - return write((unsigned char*)buffer, 119U); -} - -bool CDMRGatewayNetwork::wantsBeacon() -{ - bool beacon = m_beacon; - - m_beacon = false; - - return beacon; -} - -bool CDMRGatewayNetwork::write(const unsigned char* data, unsigned int length) -{ - assert(data != NULL); - assert(length > 0U); - - if (m_debug) - CUtils::dump(1U, "DMR Network Transmitted", data, length); - - bool ret = m_socket.write(data, length, m_addr, m_addrLen); - if (!ret) { - LogError("DMR, socket error when writing to the DMR Network"); - return false; - } - - return true; -} diff --git a/DMRGatewayNetwork.h b/DMRGatewayNetwork.h deleted file mode 100644 index 160dc51..0000000 --- a/DMRGatewayNetwork.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2015,2016,2017,2018,2020,2021 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. - */ - -#if !defined(DMRGatewayNetwork_H) -#define DMRGatewayNetwork_H - -#include "DMRNetwork.h" -#include "UDPSocket.h" -#include "Timer.h" -#include "RingBuffer.h" -#include "DMRData.h" -#include "Defines.h" - -#include -#include -#include - -class CDMRGatewayNetwork : public IDMRNetwork -{ -public: - CDMRGatewayNetwork(const std::string& remoteAddress, unsigned short remotePort, const std::string& localAddress, unsigned short localPort, unsigned int id, bool duplex, const char* version, bool slot1, bool slot2, HW_TYPE hwType, bool debug); - virtual ~CDMRGatewayNetwork(); - - virtual void setOptions(const std::string& options); - - virtual void setConfig(const std::string& callsign, unsigned int rxFrequency, unsigned int txFrequency, unsigned int power, unsigned int colorCode, float latitude, float longitude, int height, const std::string& location, const std::string& description, const std::string& url); - - virtual bool open(); - - virtual void enable(bool enabled); - - virtual bool read(CDMRData& data); - - virtual bool write(const CDMRData& data); - - virtual bool writeRadioPosition(unsigned int id, const unsigned char* data); - - virtual bool writeTalkerAlias(unsigned int id, unsigned char type, const unsigned char* data); - - virtual bool wantsBeacon(); - - virtual void clock(unsigned int ms); - - virtual bool isConnected() const; - - virtual void close(bool sayGoodbye); - -private: - std::string m_addressStr; - sockaddr_storage m_addr; - unsigned int m_addrLen; - unsigned short m_port; - uint8_t* m_id; - bool m_duplex; - const char* m_version; - bool m_debug; - CUDPSocket m_socket; - bool m_enabled; - bool m_slot1; - bool m_slot2; - HW_TYPE m_hwType; - unsigned char* m_buffer; - uint32_t* m_streamId; - CRingBuffer m_rxData; - bool m_beacon; - std::mt19937 m_random; - std::string m_callsign; - unsigned int m_rxFrequency; - unsigned int m_txFrequency; - unsigned int m_power; - unsigned int m_colorCode; - CTimer m_pingTimer; - - bool writeConfig(); - - bool write(const unsigned char* data, unsigned int length); -}; - -#endif diff --git a/DMRNetwork.cpp b/DMRNetwork.cpp index 4b1b77c..8846147 100644 --- a/DMRNetwork.cpp +++ b/DMRNetwork.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2020 by Jonathan Naylor G4KLX + * Copyright (C) 2015-2021,2023 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 @@ -18,6 +18,429 @@ #include "DMRNetwork.h" -IDMRNetwork::~IDMRNetwork() +#include "Utils.h" +#include "Log.h" + +#include +#include +#include +#include + +const unsigned int BUFFER_LENGTH = 500U; + +const unsigned int HOMEBREW_DATA_PACKET_LENGTH = 55U; + + +CDMRNetwork::CDMRNetwork(const std::string& address, unsigned short port, const std::string& localAddress, unsigned short localPort, unsigned int id, bool duplex, const char* version, bool slot1, bool slot2, HW_TYPE hwType, bool debug) : +m_addressStr(address), +m_addr(), +m_addrLen(0U), +m_port(port), +m_id(NULL), +m_duplex(duplex), +m_version(version), +m_debug(debug), +m_socket(localAddress, localPort), +m_enabled(false), +m_slot1(slot1), +m_slot2(slot2), +m_hwType(hwType), +m_buffer(NULL), +m_streamId(NULL), +m_rxData(1000U, "DMR Network"), +m_beacon(false), +m_random(), +m_callsign(), +m_rxFrequency(0U), +m_txFrequency(0U), +m_power(0U), +m_colorCode(0U), +m_pingTimer(1000U, 10U) { + assert(!address.empty()); + assert(port > 0U); + assert(id > 1000U); + + if (CUDPSocket::lookup(m_addressStr, m_port, m_addr, m_addrLen) != 0) + m_addrLen = 0U; + + m_buffer = new unsigned char[BUFFER_LENGTH]; + m_id = new uint8_t[4U]; + m_streamId = new uint32_t[2U]; + + m_id[0U] = id >> 24; + m_id[1U] = id >> 16; + m_id[2U] = id >> 8; + m_id[3U] = id >> 0; + + std::random_device rd; + std::mt19937 mt(rd()); + m_random = mt; + + std::uniform_int_distribution dist(0x00000001, 0xfffffffe); + m_streamId[0U] = dist(m_random); + m_streamId[1U] = dist(m_random); +} + +CDMRNetwork::~CDMRNetwork() +{ + delete[] m_buffer; + delete[] m_streamId; + delete[] m_id; +} + +void CDMRNetwork::setConfig(const std::string & callsign, unsigned int rxFrequency, unsigned int txFrequency, unsigned int power, unsigned int colorCode) +{ + m_callsign = callsign; + m_rxFrequency = rxFrequency; + m_txFrequency = txFrequency; + m_power = power; + m_colorCode = colorCode; +} + +bool CDMRNetwork::open() +{ + if (m_addrLen == 0U) { + LogError("Unable to resolve the address of the DMR Network"); + return false; + } + + LogMessage("DMR, Opening DMR Network"); + + bool ret = m_socket.open(m_addr); + if (ret) + m_pingTimer.start(); + + return ret; +} + +void CDMRNetwork::enable(bool enabled) +{ + if (!enabled && m_enabled) + m_rxData.clear(); + + m_enabled = enabled; +} + +bool CDMRNetwork::read(CDMRData& data) +{ + if (m_rxData.isEmpty()) + return false; + + unsigned char length = 0U; + m_rxData.getData(&length, 1U); + m_rxData.getData(m_buffer, length); + + // Is this a data packet? + if (::memcmp(m_buffer, "DMRD", 4U) != 0) + return false; + + unsigned char seqNo = m_buffer[4U]; + + unsigned int srcId = (m_buffer[5U] << 16) | (m_buffer[6U] << 8) | (m_buffer[7U] << 0); + + unsigned int dstId = (m_buffer[8U] << 16) | (m_buffer[9U] << 8) | (m_buffer[10U] << 0); + + unsigned int slotNo = (m_buffer[15U] & 0x80U) == 0x80U ? 2U : 1U; + + // DMO mode slot disabling + if (slotNo == 1U && !m_duplex) + return false; + + // Individual slot disabling + if (slotNo == 1U && !m_slot1) + return false; + if (slotNo == 2U && !m_slot2) + return false; + + FLCO flco = (m_buffer[15U] & 0x40U) == 0x40U ? FLCO_USER_USER : FLCO_GROUP; + + data.setSeqNo(seqNo); + data.setSlotNo(slotNo); + data.setSrcId(srcId); + data.setDstId(dstId); + data.setFLCO(flco); + + bool dataSync = (m_buffer[15U] & 0x20U) == 0x20U; + bool voiceSync = (m_buffer[15U] & 0x10U) == 0x10U; + + if (dataSync) { + unsigned char dataType = m_buffer[15U] & 0x0FU; + data.setData(m_buffer + 20U); + data.setDataType(dataType); + data.setN(0U); + } else if (voiceSync) { + data.setData(m_buffer + 20U); + data.setDataType(DT_VOICE_SYNC); + data.setN(0U); + } else { + unsigned char n = m_buffer[15U] & 0x0FU; + data.setData(m_buffer + 20U); + data.setDataType(DT_VOICE); + data.setN(n); + } + + return true; +} + +bool CDMRNetwork::write(const CDMRData& data) +{ + unsigned char buffer[HOMEBREW_DATA_PACKET_LENGTH]; + ::memset(buffer, 0x00U, HOMEBREW_DATA_PACKET_LENGTH); + + buffer[0U] = 'D'; + buffer[1U] = 'M'; + buffer[2U] = 'R'; + buffer[3U] = 'D'; + + unsigned int srcId = data.getSrcId(); + buffer[5U] = srcId >> 16; + buffer[6U] = srcId >> 8; + buffer[7U] = srcId >> 0; + + unsigned int dstId = data.getDstId(); + buffer[8U] = dstId >> 16; + buffer[9U] = dstId >> 8; + buffer[10U] = dstId >> 0; + + ::memcpy(buffer + 11U, m_id, 4U); + + unsigned int slotNo = data.getSlotNo(); + + // Individual slot disabling + if (slotNo == 1U && !m_slot1) + return false; + if (slotNo == 2U && !m_slot2) + return false; + + buffer[15U] = slotNo == 1U ? 0x00U : 0x80U; + + FLCO flco = data.getFLCO(); + buffer[15U] |= flco == FLCO_GROUP ? 0x00U : 0x40U; + + unsigned int slotIndex = slotNo - 1U; + + std::uniform_int_distribution dist(0x00000001, 0xfffffffe); + unsigned char dataType = data.getDataType(); + if (dataType == DT_VOICE_SYNC) { + buffer[15U] |= 0x10U; + } else if (dataType == DT_VOICE) { + buffer[15U] |= data.getN(); + } else { + if (dataType == DT_VOICE_LC_HEADER) + m_streamId[slotIndex] = dist(m_random); + + if (dataType == DT_CSBK || dataType == DT_DATA_HEADER) + m_streamId[slotIndex] = dist(m_random); + + buffer[15U] |= (0x20U | dataType); + } + + buffer[4U] = data.getSeqNo(); + + ::memcpy(buffer + 16U, m_streamId + slotIndex, 4U); + + data.getData(buffer + 20U); + + buffer[53U] = data.getBER(); + + buffer[54U] = data.getRSSI(); + + write(buffer, HOMEBREW_DATA_PACKET_LENGTH); + + return true; +} + +bool CDMRNetwork::writeRadioPosition(unsigned int id, const unsigned char* data) +{ + unsigned char buffer[20U]; + + ::memcpy(buffer + 0U, "DMRG", 4U); + + buffer[4U] = id >> 16; + buffer[5U] = id >> 8; + buffer[6U] = id >> 0; + + ::memcpy(buffer + 7U, data + 2U, 7U); + + return write(buffer, 14U); +} + +bool CDMRNetwork::writeTalkerAlias(unsigned int id, unsigned char type, const unsigned char* data) +{ + unsigned char buffer[20U]; + + ::memcpy(buffer + 0U, "DMRA", 4U); + + buffer[4U] = id >> 16; + buffer[5U] = id >> 8; + buffer[6U] = id >> 0; + + buffer[7U] = type; + + ::memcpy(buffer + 8U, data + 2U, 7U); + + return write(buffer, 15U); +} + +bool CDMRNetwork::isConnected() const +{ + return (m_addrLen != 0); +} + +void CDMRNetwork::close(bool sayGoodbye) +{ + LogMessage("DMR, Closing DMR Network"); + + m_socket.close(); +} + +void CDMRNetwork::clock(unsigned int ms) +{ + m_pingTimer.clock(ms); + if (m_pingTimer.isRunning() && m_pingTimer.hasExpired()) { + writeConfig(); + m_pingTimer.start(); + } + + sockaddr_storage address; + unsigned int addrLen; + int length = m_socket.read(m_buffer, BUFFER_LENGTH, address, addrLen); + if (length <= 0) + return; + + if (!CUDPSocket::match(m_addr, address)) { + LogMessage("DMR, packet received from an invalid source"); + return; + } + + if (m_debug) + CUtils::dump(1U, "DMR Network Received", m_buffer, length); + + if (::memcmp(m_buffer, "DMRD", 4U) == 0) { + if (m_enabled) { + unsigned char len = length; + m_rxData.addData(&len, 1U); + m_rxData.addData(m_buffer, len); + } + } else if (::memcmp(m_buffer, "DMRP", 4U) == 0) { + ; + } else if (::memcmp(m_buffer, "DMRB", 4U) == 0) { + m_beacon = true; + } else { + CUtils::dump("DMR, unknown packet from the DMR Network", m_buffer, length); + } +} + +bool CDMRNetwork::writeConfig() +{ + const char* software; + char slots = '0'; + if (m_duplex) { + if (m_slot1 && m_slot2) + slots = '3'; + else if (m_slot1 && !m_slot2) + slots = '1'; + else if (!m_slot1 && m_slot2) + slots = '2'; + + switch (m_hwType) { + case HWT_MMDVM: + software = "MMDVM"; + break; + case HWT_MMDVM_HS: + software = "MMDVM_MMDVM_HS"; + break; + case HWT_MMDVM_HS_DUAL_HAT: + software = "MMDVM_MMDVM_HS_Dual_Hat"; + break; + case HWT_NANO_HOTSPOT: + software = "MMDVM_Nano_hotSPOT"; + break; + default: + software = "MMDVM_Unknown"; + break; + } + } else { + slots = '4'; + + switch (m_hwType) { + case HWT_MMDVM: + software = "MMDVM_DMO"; + break; + case HWT_DVMEGA: + software = "MMDVM_DVMega"; + break; + case HWT_MMDVM_ZUMSPOT: + software = "MMDVM_ZUMspot"; + break; + case HWT_MMDVM_HS_HAT: + software = "MMDVM_MMDVM_HS_Hat"; + break; + case HWT_MMDVM_HS_DUAL_HAT: + software = "MMDVM_MMDVM_HS_Dual_Hat"; + break; + case HWT_NANO_HOTSPOT: + software = "MMDVM_Nano_hotSPOT"; + break; + case HWT_NANO_DV: + software = "MMDVM_Nano_DV"; + break; + case HWT_D2RG_MMDVM_HS: + software = "MMDVM_D2RG_MMDVM_HS"; + break; + case HWT_MMDVM_HS: + software = "MMDVM_MMDVM_HS"; + break; + case HWT_OPENGD77_HS: + software = "MMDVM_OpenGD77_HS"; + break; + case HWT_SKYBRIDGE: + software = "MMDVM_SkyBridge"; + break; + default: + software = "MMDVM_Unknown"; + break; + } + } + + unsigned int power = m_power; + if (power > 99U) + power = 99U; + + char buffer[150U]; + + ::memcpy(buffer + 0U, "DMRC", 4U); + ::memcpy(buffer + 4U, m_id, 4U); + ::sprintf(buffer + 8U, "%-8.8s%09u%09u%02u%02u%c%-40.40s%-40.40s", + m_callsign.c_str(), m_rxFrequency, m_txFrequency, power, m_colorCode, slots, m_version, + software); + + return write((unsigned char*)buffer, 119U); +} + +bool CDMRNetwork::wantsBeacon() +{ + bool beacon = m_beacon; + + m_beacon = false; + + return beacon; +} + +bool CDMRNetwork::write(const unsigned char* data, unsigned int length) +{ + assert(data != NULL); + assert(length > 0U); + + if (m_debug) + CUtils::dump(1U, "DMR Network Transmitted", data, length); + + bool ret = m_socket.write(data, length, m_addr, m_addrLen); + if (!ret) { + LogError("DMR, socket error when writing to the DMR Network"); + return false; + } + + return true; } diff --git a/DMRNetwork.h b/DMRNetwork.h index 006e097..dfca5da 100644 --- a/DMRNetwork.h +++ b/DMRNetwork.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015,2016,2017,2018,2020,2021 by Jonathan Naylor G4KLX + * Copyright (C) 2015,2016,2017,2018,2020,2021,2023 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 @@ -19,40 +19,73 @@ #if !defined(DMRNetwork_H) #define DMRNetwork_H +#include "UDPSocket.h" +#include "Timer.h" +#include "RingBuffer.h" #include "DMRData.h" +#include "Defines.h" #include +#include +#include -class IDMRNetwork +class CDMRNetwork { public: - virtual ~IDMRNetwork() = 0; + CDMRNetwork(const std::string& gatewayAddress, unsigned short gatewayPort, const std::string& localAddress, unsigned short localPort, unsigned int id, bool duplex, const char* version, bool slot1, bool slot2, HW_TYPE hwType, bool debug); + ~CDMRNetwork(); - virtual void setOptions(const std::string& options) = 0; + void setConfig(const std::string& callsign, unsigned int rxFrequency, unsigned int txFrequency, unsigned int power, unsigned int colorCode); - virtual void setConfig(const std::string& callsign, unsigned int rxFrequency, unsigned int txFrequency, unsigned int power, unsigned int colorCode, float latitude, float longitude, int height, const std::string& location, const std::string& description, const std::string& url) = 0; + bool open(); - virtual bool open() = 0; + void enable(bool enabled); - virtual void enable(bool enabled) = 0; + bool read(CDMRData& data); - virtual bool read(CDMRData& data) = 0; + bool write(const CDMRData& data); - virtual bool write(const CDMRData& data) = 0; + bool writeRadioPosition(unsigned int id, const unsigned char* data); - virtual bool writeRadioPosition(unsigned int id, const unsigned char* data) = 0; + bool writeTalkerAlias(unsigned int id, unsigned char type, const unsigned char* data); - virtual bool writeTalkerAlias(unsigned int id, unsigned char type, const unsigned char* data) = 0; + bool wantsBeacon(); - virtual bool wantsBeacon() = 0; + void clock(unsigned int ms); - virtual void clock(unsigned int ms) = 0; + bool isConnected() const; - virtual bool isConnected() const = 0; - - virtual void close(bool sayGoodbye) = 0; + void close(bool sayGoodbye); private: + std::string m_addressStr; + sockaddr_storage m_addr; + unsigned int m_addrLen; + unsigned short m_port; + uint8_t* m_id; + bool m_duplex; + const char* m_version; + bool m_debug; + CUDPSocket m_socket; + bool m_enabled; + bool m_slot1; + bool m_slot2; + HW_TYPE m_hwType; + unsigned char* m_buffer; + uint32_t* m_streamId; + CRingBuffer m_rxData; + bool m_beacon; + std::mt19937 m_random; + std::string m_callsign; + unsigned int m_rxFrequency; + unsigned int m_txFrequency; + unsigned int m_power; + unsigned int m_colorCode; + CTimer m_pingTimer; + + bool writeConfig(); + + bool write(const unsigned char* data, unsigned int length); }; #endif diff --git a/DMRSlot.cpp b/DMRSlot.cpp index 268619e..df47c0a 100644 --- a/DMRSlot.cpp +++ b/DMRSlot.cpp @@ -38,7 +38,7 @@ bool CDMRSlot::m_embeddedLCOnly = false; bool CDMRSlot::m_dumpTAData = true; CModem* CDMRSlot::m_modem = NULL; -IDMRNetwork* CDMRSlot::m_network = NULL; +CDMRNetwork* CDMRSlot::m_network = NULL; CDisplay* CDMRSlot::m_display = NULL; bool CDMRSlot::m_duplex = true; CDMRLookup* CDMRSlot::m_lookup = NULL; @@ -2015,7 +2015,7 @@ void CDMRSlot::writeQueueNet(const unsigned char *data) m_queue.addData(data, len); } -void CDMRSlot::init(unsigned int colorCode, bool embeddedLCOnly, bool dumpTAData, unsigned int callHang, CModem* modem, IDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssiMapper, unsigned int jitter, DMR_OVCM_TYPES ovcm) +void CDMRSlot::init(unsigned int colorCode, bool embeddedLCOnly, bool dumpTAData, unsigned int callHang, CModem* modem, CDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssiMapper, unsigned int jitter, DMR_OVCM_TYPES ovcm) { assert(modem != NULL); assert(display != NULL); diff --git a/DMRSlot.h b/DMRSlot.h index b791613..dfc16c0 100644 --- a/DMRSlot.h +++ b/DMRSlot.h @@ -64,7 +64,7 @@ public: void enable(bool enabled); - static void init(unsigned int colorCode, bool embeddedLCOnly, bool dumpTAData, unsigned int callHang, CModem* modem, IDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssiMapper, unsigned int jitter, DMR_OVCM_TYPES ovcm); + static void init(unsigned int colorCode, bool embeddedLCOnly, bool dumpTAData, unsigned int callHang, CModem* modem, CDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssiMapper, unsigned int jitter, DMR_OVCM_TYPES ovcm); private: unsigned int m_slotNo; @@ -120,7 +120,7 @@ private: static bool m_dumpTAData; static CModem* m_modem; - static IDMRNetwork* m_network; + static CDMRNetwork* m_network; static CDisplay* m_display; static bool m_duplex; static CDMRLookup* m_lookup; diff --git a/MMDVM.ini b/MMDVM.ini index 31a8a59..17c564b 100644 --- a/MMDVM.ini +++ b/MMDVM.ini @@ -231,18 +231,13 @@ Debug=0 [DMR Network] Enable=1 -# Type may be either 'Direct' or 'Gateway'. When Direct you must provide the Master's -# address as well as the Password, and for DMR+, Options also. -Type=Gateway LocalAddress=127.0.0.1 LocalPort=62032 -RemoteAddress=127.0.0.1 -RemotePort=62031 -# Password=P@ssw0rd1234 +GatewayAddress=127.0.0.1 +GatewayPort=62031 Jitter=360 Slot1=1 Slot2=1 -# Options= # ModeHang=3 Debug=0 diff --git a/MMDVMHost.cpp b/MMDVMHost.cpp index b00fc5d..160e28a 100644 --- a/MMDVMHost.cpp +++ b/MMDVMHost.cpp @@ -17,8 +17,6 @@ */ #include "MMDVMHost.h" -#include "DMRDirectNetwork.h" -#include "DMRGatewayNetwork.h" #include "NXDNKenwoodNetwork.h" #include "NXDNIcomNetwork.h" #include "RSSIInterpolator.h" @@ -82,7 +80,7 @@ static void sigHandler2(int signum) const char* HEADER1 = "This software is for use on amateur radio networks only,"; const char* HEADER2 = "it is to be used for educational purposes only. Its use on"; const char* HEADER3 = "commercial networks is strictly prohibited."; -const char* HEADER4 = "Copyright(C) 2015-2021 by Jonathan Naylor, G4KLX and others"; +const char* HEADER4 = "Copyright(C) 2015-2023 by Jonathan Naylor, G4KLX and others"; int main(int argc, char** argv) { @@ -1648,26 +1646,21 @@ bool CMMDVMHost::createDStarNetwork() bool CMMDVMHost::createDMRNetwork() { - std::string remoteAddress = m_conf.getDMRNetworkRemoteAddress(); - unsigned short remotePort = m_conf.getDMRNetworkRemotePort(); + std::string gatewayAddress = m_conf.getDMRNetworkGatewayAddress(); + unsigned short gatewayPort = m_conf.getDMRNetworkGatewayPort(); std::string localAddress = m_conf.getDMRNetworkLocalAddress(); unsigned short localPort = m_conf.getDMRNetworkLocalPort(); unsigned int id = m_conf.getDMRId(); - std::string password = m_conf.getDMRNetworkPassword(); bool debug = m_conf.getDMRNetworkDebug(); unsigned int jitter = m_conf.getDMRNetworkJitter(); bool slot1 = m_conf.getDMRNetworkSlot1(); bool slot2 = m_conf.getDMRNetworkSlot2(); HW_TYPE hwType = m_modem->getHWType(); m_dmrNetModeHang = m_conf.getDMRNetworkModeHang(); - std::string options = m_conf.getDMRNetworkOptions(); - - std::string type = m_conf.getDMRNetworkType(); LogInfo("DMR Network Parameters"); - LogInfo(" Type: %s", type.c_str()); - LogInfo(" Remote Address: %s", remoteAddress.c_str()); - LogInfo(" Remote Port: %hu", remotePort); + LogInfo(" Gateway Address: %s", gatewayAddress.c_str()); + LogInfo(" Gateway Port: %hu", gatewayPort); LogInfo(" Local Address: %s", localAddress.c_str()); LogInfo(" Local Port: %hu", localPort); LogInfo(" Jitter: %ums", jitter); @@ -1675,10 +1668,7 @@ bool CMMDVMHost::createDMRNetwork() LogInfo(" Slot 2: %s", slot2 ? "enabled" : "disabled"); LogInfo(" Mode Hang: %us", m_dmrNetModeHang); - if (type == "Direct") - m_dmrNetwork = new CDMRDirectNetwork(remoteAddress, remotePort, localAddress, localPort, id, password, m_duplex, VERSION, slot1, slot2, hwType, debug); - else - m_dmrNetwork = new CDMRGatewayNetwork(remoteAddress, remotePort, localAddress, localPort, id, m_duplex, VERSION, slot1, slot2, hwType, debug); + m_dmrNetwork = new CDMRNetwork(gatewayAddress, gatewayPort, localAddress, localPort, id, m_duplex, VERSION, slot1, slot2, hwType, debug); unsigned int rxFrequency = m_conf.getRXFrequency(); unsigned int txFrequency = m_conf.getTXFrequency(); @@ -1691,32 +1681,8 @@ bool CMMDVMHost::createDMRNetwork() LogInfo(" TX Frequency: %uHz", txFrequency); LogInfo(" Power: %uW", power); - if (type == "Direct") { - float latitude = m_conf.getLatitude(); - float longitude = m_conf.getLongitude(); - int height = m_conf.getHeight(); - std::string location = m_conf.getLocation(); - std::string description = m_conf.getDescription(); - std::string url = m_conf.getURL(); - - LogInfo(" Latitude: %fdeg N", latitude); - LogInfo(" Longitude: %fdeg E", longitude); - LogInfo(" Height: %um", height); - LogInfo(" Location: \"%s\"", location.c_str()); - LogInfo(" Description: \"%s\"", description.c_str()); - LogInfo(" URL: \"%s\"", url.c_str()); - - m_dmrNetwork->setConfig(m_callsign, rxFrequency, txFrequency, power, colorCode, latitude, longitude, height, location, description, url); - } else { - m_dmrNetwork->setConfig(m_callsign, rxFrequency, txFrequency, power, colorCode, 0.0F, 0.0F, 0, "", "", ""); - } + m_dmrNetwork->setConfig(m_callsign, rxFrequency, txFrequency, power, colorCode); - if (!options.empty()) { - LogInfo(" Options: %s", options.c_str()); - - m_dmrNetwork->setOptions(options); - } - bool ret = m_dmrNetwork->open(); if (!ret) { delete m_dmrNetwork; @@ -2747,7 +2713,7 @@ void CMMDVMHost::processModeCommand(unsigned char mode, unsigned int timeout) void CMMDVMHost::processEnableCommand(bool& mode, bool enabled) { - LogDebug("Setting mode current=%s new=%s",mode ? "true" : "false",enabled ? "true" : "false"); + LogDebug("Setting mode current=%s new=%s", mode ? "true" : "false", enabled ? "true" : "false"); mode = enabled; @@ -2794,7 +2760,7 @@ void CMMDVMHost::buildNetworkHostsString(std::string &str) } } str += std::string("dstar:\"") + ((dstarReflector.length() == 0) ? "NONE" : dstarReflector) + "\""; - str += std::string(" dmr:\"") + ((m_dmrEnabled && (m_dmrNetwork != NULL)) ? m_conf.getDMRNetworkRemoteAddress() : "NONE") + "\""; + str += std::string(" dmr:\"") + ((m_dmrEnabled && (m_dmrNetwork != NULL)) ? m_conf.getDMRNetworkGatewayAddress() : "NONE") + "\""; str += std::string(" ysf:\"") + ((m_ysfEnabled && (m_ysfNetwork != NULL)) ? m_conf.getFusionNetworkGatewayAddress() : "NONE") + "\""; str += std::string(" p25:\"") + ((m_p25Enabled && (m_p25Network != NULL)) ? m_conf.getP25GatewayAddress() : "NONE") + "\""; str += std::string(" nxdn:\"") + ((m_nxdnEnabled && (m_nxdnNetwork != NULL)) ? m_conf.getNXDNGatewayAddress() : "NONE") + "\""; diff --git a/MMDVMHost.h b/MMDVMHost.h index a6cb437..98eb75c 100644 --- a/MMDVMHost.h +++ b/MMDVMHost.h @@ -71,7 +71,7 @@ private: CFMControl* m_fm; CAX25Control* m_ax25; CDStarNetwork* m_dstarNetwork; - IDMRNetwork* m_dmrNetwork; + CDMRNetwork* m_dmrNetwork; CYSFNetwork* m_ysfNetwork; CP25Network* m_p25Network; INXDNNetwork* m_nxdnNetwork; diff --git a/MMDVMHost.vcxproj b/MMDVMHost.vcxproj index dc7a76b..8ccad16 100644 --- a/MMDVMHost.vcxproj +++ b/MMDVMHost.vcxproj @@ -169,11 +169,9 @@ - - @@ -281,11 +279,9 @@ - - @@ -373,4 +369,4 @@ - \ No newline at end of file + diff --git a/MMDVMHost.vcxproj.filters b/MMDVMHost.vcxproj.filters index 3b74c31..b64bfd1 100644 --- a/MMDVMHost.vcxproj.filters +++ b/MMDVMHost.vcxproj.filters @@ -323,12 +323,6 @@ Header Files - - Header Files - - - Header Files - Header Files @@ -631,12 +625,6 @@ Source Files - - Source Files - - - Source Files - Source Files @@ -659,4 +647,4 @@ Source Files - \ No newline at end of file + diff --git a/Makefile b/Makefile index f9dcb4b..df255e1 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ LDFLAGS = -g -L/usr/local/lib OBJECTS = \ AMBEFEC.o BCH.o AX25Control.o AX25Network.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o \ - DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \ + DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \ DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o \ Hamming.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o M17LSF.o M17Network.o M17Utils.o MMDVMHost.o \ MQTTPublisher.o Modem.o ModemPort.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullController.o NullDisplay.o NXDNAudio.o NXDNControl.o \ diff --git a/Makefile.Pi.Adafruit b/Makefile.Pi.Adafruit index 7e86204..127eb7e 100644 --- a/Makefile.Pi.Adafruit +++ b/Makefile.Pi.Adafruit @@ -9,7 +9,7 @@ LDFLAGS = -g -L/usr/local/lib OBJECTS = \ AMBEFEC.o AX25Control.o AX25Network.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o \ - DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \ + DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \ DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o \ Hamming.o HD44780.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o M17LSF.o M17Network.o M17Utils.o \ MMDVMHost.o MQTTPublisher.o Modem.o ModemPort.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullController.o NullDisplay.o NXDNAudio.o \ diff --git a/Makefile.Pi.HD44780 b/Makefile.Pi.HD44780 index f61e77b..fb42d1e 100644 --- a/Makefile.Pi.HD44780 +++ b/Makefile.Pi.HD44780 @@ -8,7 +8,7 @@ LDFLAGS = -g -L/usr/local/lib OBJECTS = \ AMBEFEC.o AX25Control.o AX25Network.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o \ - DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \ + DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \ DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o \ Hamming.o HD44780.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o M17LSF.o M17Network.o M17Utils.o \ MMDVMHost.o MQTTPublisher.o Modem.o ModemPort.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullController.o NullDisplay.o NXDNAudio.o \ diff --git a/Makefile.Pi.I2C b/Makefile.Pi.I2C index fde1c41..0c5275a 100644 --- a/Makefile.Pi.I2C +++ b/Makefile.Pi.I2C @@ -8,7 +8,7 @@ LDFLAGS = -g -L/usr/local/lib OBJECTS = \ AMBEFEC.o AX25Control.o AX25Network.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o \ - DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \ + DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \ DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o \ Hamming.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o M17LSF.o M17Network.o M17Utils.o MMDVMHost.o \ MQTTPublisher.o Modem.o ModemPort.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullController.o NullDisplay.o NXDNAudio.o NXDNControl.o \ diff --git a/Makefile.Pi.OLED b/Makefile.Pi.OLED index 39ba604..75721ea 100644 --- a/Makefile.Pi.OLED +++ b/Makefile.Pi.OLED @@ -12,7 +12,7 @@ LDFLAGS = -g -L/usr/local/lib OBJECTS = \ AMBEFEC.o AX25Control.o AX25Network.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o \ - DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \ + DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \ DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o \ Hamming.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o M17LSF.o M17Network.o M17Utils.o MMDVMHost.o \ MQTTPublisher.o Modem.o ModemPort.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullController.o NullDisplay.o NXDNAudio.o NXDNControl.o \ diff --git a/Makefile.Pi.PCF8574 b/Makefile.Pi.PCF8574 index 1207ccc..3bdf856 100644 --- a/Makefile.Pi.PCF8574 +++ b/Makefile.Pi.PCF8574 @@ -9,7 +9,7 @@ LDFLAGS = -g -L/usr/local/lib OBJECTS = \ AMBEFEC.o AX25Control.o AX25Network.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o \ - DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \ + DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \ DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o \ Hamming.o HD44780.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o M17LSF.o M17Network.o M17Utils.o \ MMDVMHost.o MQTTPublisher.o Modem.o ModemPort.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullController.o NullDisplay.o NXDNAudio.o \