diff --git a/DMRGateway.cpp b/DMRGateway.cpp
index 0564932..5dd3080 100644
--- a/DMRGateway.cpp
+++ b/DMRGateway.cpp
@@ -16,6 +16,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include "MMDVMNetworkNew.h"
#include "RewriteType.h"
#include "DMRSlotType.h"
#include "RewriteSrc.h"
@@ -1315,7 +1316,7 @@ bool CDMRGateway::createMMDVM()
LogInfo(" Local Address: %s", localAddress.c_str());
LogInfo(" Local Port: %u", localPort);
- m_repeater = new CMMDVMNetwork(rptAddress, rptPort, localAddress, localPort, debug);
+ m_repeater = new CMMDVMNetworkNew(rptAddress, rptPort, localAddress, localPort, debug);
bool ret = m_repeater->open();
if (!ret) {
diff --git a/DMRGateway.h b/DMRGateway.h
index d872389..4beea4d 100644
--- a/DMRGateway.h
+++ b/DMRGateway.h
@@ -56,7 +56,7 @@ public:
private:
CConf m_conf;
DMRGW_STATUS* m_status;
- CMMDVMNetwork* m_repeater;
+ IMMDVMNetwork* m_repeater;
unsigned char* m_config;
unsigned int m_configLen;
CDMRNetwork* m_dmrNetwork1;
diff --git a/DMRGateway.vcxproj b/DMRGateway.vcxproj
index 6436d99..056b770 100644
--- a/DMRGateway.vcxproj
+++ b/DMRGateway.vcxproj
@@ -173,6 +173,8 @@
+
+
@@ -219,6 +221,8 @@
+
+
diff --git a/DMRGateway.vcxproj.filters b/DMRGateway.vcxproj.filters
index 3f9fdc3..6083433 100644
--- a/DMRGateway.vcxproj.filters
+++ b/DMRGateway.vcxproj.filters
@@ -146,6 +146,12 @@
Header Files
+
+ Header Files
+
+
+ Header Files
+
@@ -274,5 +280,11 @@
Source Files
+
+ Source Files
+
+
+ Source Files
+
\ No newline at end of file
diff --git a/MMDVMNetwork.cpp b/MMDVMNetwork.cpp
index 09d7303..6ff3d00 100644
--- a/MMDVMNetwork.cpp
+++ b/MMDVMNetwork.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015,2016,2017,2018,2020 by Jonathan Naylor G4KLX
+ * 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
@@ -18,280 +18,6 @@
#include "MMDVMNetwork.h"
-#include "StopWatch.h"
-#include "Utils.h"
-#include "Log.h"
-
-#include
-#include
-
-const unsigned int BUFFER_LENGTH = 500U;
-
-const unsigned int HOMEBREW_DATA_PACKET_LENGTH = 55U;
-
-
-CMMDVMNetwork::CMMDVMNetwork(const std::string& rptAddress, unsigned int rptPort, const std::string& localAddress, unsigned int localPort, bool debug) :
-m_rptAddr(),
-m_rptAddrLen(0U),
-m_id(0U),
-m_netId(NULL),
-m_debug(debug),
-m_socket(localAddress, localPort),
-m_buffer(NULL),
-m_rxData(1000U, "MMDVM Network"),
-m_configData(NULL),
-m_configLen(0U),
-m_radioPositionData(NULL),
-m_radioPositionLen(0U),
-m_talkerAliasData(NULL),
-m_talkerAliasLen(0U)
+IMMDVMNetwork::~IMMDVMNetwork()
{
- assert(!rptAddress.empty());
- assert(rptPort > 0U);
-
- if (CUDPSocket::lookup(rptAddress, rptPort, m_rptAddr, m_rptAddrLen) != 0)
- m_rptAddrLen = 0U;
-
- m_buffer = new unsigned char[BUFFER_LENGTH];
- m_netId = new unsigned char[4U];
-
- m_radioPositionData = new unsigned char[50U];
- m_talkerAliasData = new unsigned char[50U];
-
- CStopWatch stopWatch;
- ::srand(stopWatch.start());
-}
-
-CMMDVMNetwork::~CMMDVMNetwork()
-{
- delete[] m_netId;
- delete[] m_buffer;
- delete[] m_configData;
- delete[] m_radioPositionData;
- delete[] m_talkerAliasData;
-}
-
-unsigned int CMMDVMNetwork::getShortConfig(unsigned char* config) const
-{
- if (m_configData == 0U)
- return 0U;
-
- ::memcpy(config, m_configData, m_configLen);
-
- return m_configLen;
-}
-
-unsigned int CMMDVMNetwork::getId() const
-{
- return m_id;
-}
-
-bool CMMDVMNetwork::open()
-{
- if (m_rptAddrLen == 0U) {
- LogError("Could not lookup the address of the MMDVM Host");
- return false;
- }
-
- LogMessage("MMDVM Network, Opening");
-
- return m_socket.open(m_rptAddr);
-}
-
-bool CMMDVMNetwork::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;
-
- FLCO flco = (m_buffer[15U] & 0x40U) == 0x40U ? FLCO_USER_USER : FLCO_GROUP;
-
- unsigned int streamId;
- ::memcpy(&streamId, m_buffer + 16U, 4U);
-
- unsigned char ber = m_buffer[53U];
-
- unsigned char rssi = m_buffer[54U];
-
- data.setSeqNo(seqNo);
- data.setSlotNo(slotNo);
- data.setSrcId(srcId);
- data.setDstId(dstId);
- data.setFLCO(flco);
- data.setStreamId(streamId);
- data.setBER(ber);
- data.setRSSI(rssi);
-
- 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 CMMDVMNetwork::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_netId, 4U);
-
- unsigned int slotNo = data.getSlotNo();
-
- buffer[15U] = slotNo == 1U ? 0x00U : 0x80U;
-
- FLCO flco = data.getFLCO();
- buffer[15U] |= flco == FLCO_GROUP ? 0x00U : 0x40U;
-
- unsigned char dataType = data.getDataType();
- if (dataType == DT_VOICE_SYNC) {
- buffer[15U] |= 0x10U;
- } else if (dataType == DT_VOICE) {
- buffer[15U] |= data.getN();
- } else {
- buffer[15U] |= (0x20U | dataType);
- }
-
- buffer[4U] = data.getSeqNo();
-
- unsigned int streamId = data.getStreamId();
- ::memcpy(buffer + 16U, &streamId, 4U);
-
- data.getData(buffer + 20U);
-
- buffer[53U] = data.getBER();
-
- buffer[54U] = data.getRSSI();
-
- if (m_debug)
- CUtils::dump(1U, "Network Transmitted", buffer, HOMEBREW_DATA_PACKET_LENGTH);
-
- m_socket.write(buffer, HOMEBREW_DATA_PACKET_LENGTH, m_rptAddr, m_rptAddrLen);
-
- return true;
-}
-
-bool CMMDVMNetwork::readRadioPosition(unsigned char* data, unsigned int& length)
-{
- if (m_radioPositionLen == 0U)
- return false;
-
- ::memcpy(data, m_radioPositionData, m_radioPositionLen);
- length = m_radioPositionLen;
-
- m_radioPositionLen = 0U;
-
- return true;
-}
-
-bool CMMDVMNetwork::readTalkerAlias(unsigned char* data, unsigned int& length)
-{
- if (m_talkerAliasLen == 0U)
- return false;
-
- ::memcpy(data, m_talkerAliasData, m_talkerAliasLen);
- length = m_talkerAliasLen;
-
- m_talkerAliasLen = 0U;
-
- return true;
-}
-
-bool CMMDVMNetwork::writeBeacon()
-{
- return m_socket.write((unsigned char*)"DMRB", 4U, m_rptAddr, m_rptAddrLen);
-}
-
-void CMMDVMNetwork::close()
-{
- LogMessage("MMDVM Network, Closing");
-
- m_socket.close();
-}
-
-void CMMDVMNetwork::clock(unsigned int ms)
-{
- 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_rptAddr, address)) {
- LogMessage("MMDVM packet received from an invalid source");
- return;
- }
-
- if (m_debug)
- CUtils::dump(1U, "Network Received", m_buffer, length);
-
- if (::memcmp(m_buffer, "DMRD", 4U) == 0) {
- unsigned char len = length;
- m_rxData.addData(&len, 1U);
- m_rxData.addData(m_buffer, len);
- } else if (::memcmp(m_buffer, "DMRG", 4U) == 0) {
- ::memcpy(m_radioPositionData, m_buffer, length);
- m_radioPositionLen = length;
- } else if (::memcmp(m_buffer, "DMRA", 4U) == 0) {
- ::memcpy(m_talkerAliasData, m_buffer, length);
- m_talkerAliasLen = length;
- } else if (::memcmp(m_buffer, "DMRC", 4U) == 0) {
- m_id = (m_buffer[4U] << 24) | (m_buffer[5U] << 16) | (m_buffer[6U] << 8) | (m_buffer[7U] << 0);
-
- if (m_configData == NULL) {
- m_configLen = length - 8U;
- m_configData = new unsigned char[m_configLen];
- ::memcpy(m_configData, m_buffer + 8U, m_configLen);
- }
-
- m_socket.write((unsigned char*)"DMRP", 4U, m_rptAddr, m_rptAddrLen);
- } else {
- CUtils::dump("Unknown packet from the MMDVM", m_buffer, length);
- }
}
diff --git a/MMDVMNetwork.h b/MMDVMNetwork.h
index 89dc762..ec99790 100644
--- a/MMDVMNetwork.h
+++ b/MMDVMNetwork.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015,2016,2017,2018,2020 by Jonathan Naylor G4KLX
+ * 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
@@ -19,55 +19,36 @@
#if !defined(MMDVMNetwork_H)
#define MMDVMNetwork_H
-#include "UDPSocket.h"
-#include "Timer.h"
-#include "RingBuffer.h"
#include "DMRData.h"
-#include
#include
-class CMMDVMNetwork
+class IMMDVMNetwork
{
public:
- CMMDVMNetwork(const std::string& rptAddress, unsigned int rptPort, const std::string& localAddress, unsigned int localPort, bool debug);
- ~CMMDVMNetwork();
+ virtual ~IMMDVMNetwork() = 0;
- unsigned int getShortConfig(unsigned char* config) const;
+ virtual unsigned int getShortConfig(unsigned char* config) const = 0;
- unsigned int getId() const;
+ virtual unsigned int getId() const = 0;
- bool open();
+ virtual bool open() = 0;
- bool read(CDMRData& data);
+ virtual bool read(CDMRData& data) = 0;
- bool write(const CDMRData& data);
+ virtual bool write(const CDMRData& data) = 0;
- bool readRadioPosition(unsigned char* data, unsigned int& length);
+ virtual bool readRadioPosition(unsigned char* data, unsigned int& length) = 0;
- bool readTalkerAlias(unsigned char* data, unsigned int& length);
+ virtual bool readTalkerAlias(unsigned char* data, unsigned int& length) = 0;
- bool writeBeacon();
+ virtual bool writeBeacon() = 0;
- void clock(unsigned int ms);
+ virtual void clock(unsigned int ms) = 0;
- void close();
+ virtual void close() = 0;
private:
- sockaddr_storage m_rptAddr;
- unsigned int m_rptAddrLen;
- unsigned int m_id;
- unsigned char* m_netId;
- bool m_debug;
- CUDPSocket m_socket;
- unsigned char* m_buffer;
- CRingBuffer m_rxData;
- unsigned char* m_configData;
- unsigned int m_configLen;
- unsigned char* m_radioPositionData;
- unsigned int m_radioPositionLen;
- unsigned char* m_talkerAliasData;
- unsigned int m_talkerAliasLen;
};
#endif
diff --git a/MMDVMNetworkNew.cpp b/MMDVMNetworkNew.cpp
new file mode 100644
index 0000000..0e837f0
--- /dev/null
+++ b/MMDVMNetworkNew.cpp
@@ -0,0 +1,297 @@
+/*
+ * 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 "MMDVMNetworkNew.h"
+
+#include "StopWatch.h"
+#include "Utils.h"
+#include "Log.h"
+
+#include
+#include
+
+const unsigned int BUFFER_LENGTH = 500U;
+
+const unsigned int HOMEBREW_DATA_PACKET_LENGTH = 55U;
+
+
+CMMDVMNetworkNew::CMMDVMNetworkNew(const std::string& rptAddress, unsigned int rptPort, const std::string& localAddress, unsigned int localPort, bool debug) :
+m_rptAddr(),
+m_rptAddrLen(0U),
+m_id(0U),
+m_netId(NULL),
+m_debug(debug),
+m_socket(localAddress, localPort),
+m_buffer(NULL),
+m_rxData(1000U, "MMDVM Network"),
+m_configData(NULL),
+m_configLen(0U),
+m_radioPositionData(NULL),
+m_radioPositionLen(0U),
+m_talkerAliasData(NULL),
+m_talkerAliasLen(0U)
+{
+ assert(!rptAddress.empty());
+ assert(rptPort > 0U);
+
+ if (CUDPSocket::lookup(rptAddress, rptPort, m_rptAddr, m_rptAddrLen) != 0)
+ m_rptAddrLen = 0U;
+
+ m_buffer = new unsigned char[BUFFER_LENGTH];
+ m_netId = new unsigned char[4U];
+
+ m_radioPositionData = new unsigned char[50U];
+ m_talkerAliasData = new unsigned char[50U];
+
+ CStopWatch stopWatch;
+ ::srand(stopWatch.start());
+}
+
+CMMDVMNetworkNew::~CMMDVMNetworkNew()
+{
+ delete[] m_netId;
+ delete[] m_buffer;
+ delete[] m_configData;
+ delete[] m_radioPositionData;
+ delete[] m_talkerAliasData;
+}
+
+unsigned int CMMDVMNetworkNew::getShortConfig(unsigned char* config) const
+{
+ if (m_configData == 0U)
+ return 0U;
+
+ ::memcpy(config, m_configData, m_configLen);
+
+ return m_configLen;
+}
+
+unsigned int CMMDVMNetworkNew::getId() const
+{
+ return m_id;
+}
+
+bool CMMDVMNetworkNew::open()
+{
+ if (m_rptAddrLen == 0U) {
+ LogError("Could not lookup the address of the MMDVM Host");
+ return false;
+ }
+
+ LogMessage("MMDVM Network, Opening");
+
+ return m_socket.open(m_rptAddr);
+}
+
+bool CMMDVMNetworkNew::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;
+
+ FLCO flco = (m_buffer[15U] & 0x40U) == 0x40U ? FLCO_USER_USER : FLCO_GROUP;
+
+ unsigned int streamId;
+ ::memcpy(&streamId, m_buffer + 16U, 4U);
+
+ unsigned char ber = m_buffer[53U];
+
+ unsigned char rssi = m_buffer[54U];
+
+ data.setSeqNo(seqNo);
+ data.setSlotNo(slotNo);
+ data.setSrcId(srcId);
+ data.setDstId(dstId);
+ data.setFLCO(flco);
+ data.setStreamId(streamId);
+ data.setBER(ber);
+ data.setRSSI(rssi);
+
+ 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 CMMDVMNetworkNew::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_netId, 4U);
+
+ unsigned int slotNo = data.getSlotNo();
+
+ buffer[15U] = slotNo == 1U ? 0x00U : 0x80U;
+
+ FLCO flco = data.getFLCO();
+ buffer[15U] |= flco == FLCO_GROUP ? 0x00U : 0x40U;
+
+ unsigned char dataType = data.getDataType();
+ if (dataType == DT_VOICE_SYNC) {
+ buffer[15U] |= 0x10U;
+ } else if (dataType == DT_VOICE) {
+ buffer[15U] |= data.getN();
+ } else {
+ buffer[15U] |= (0x20U | dataType);
+ }
+
+ buffer[4U] = data.getSeqNo();
+
+ unsigned int streamId = data.getStreamId();
+ ::memcpy(buffer + 16U, &streamId, 4U);
+
+ data.getData(buffer + 20U);
+
+ buffer[53U] = data.getBER();
+
+ buffer[54U] = data.getRSSI();
+
+ if (m_debug)
+ CUtils::dump(1U, "Network Transmitted", buffer, HOMEBREW_DATA_PACKET_LENGTH);
+
+ m_socket.write(buffer, HOMEBREW_DATA_PACKET_LENGTH, m_rptAddr, m_rptAddrLen);
+
+ return true;
+}
+
+bool CMMDVMNetworkNew::readRadioPosition(unsigned char* data, unsigned int& length)
+{
+ if (m_radioPositionLen == 0U)
+ return false;
+
+ ::memcpy(data, m_radioPositionData, m_radioPositionLen);
+ length = m_radioPositionLen;
+
+ m_radioPositionLen = 0U;
+
+ return true;
+}
+
+bool CMMDVMNetworkNew::readTalkerAlias(unsigned char* data, unsigned int& length)
+{
+ if (m_talkerAliasLen == 0U)
+ return false;
+
+ ::memcpy(data, m_talkerAliasData, m_talkerAliasLen);
+ length = m_talkerAliasLen;
+
+ m_talkerAliasLen = 0U;
+
+ return true;
+}
+
+bool CMMDVMNetworkNew::writeBeacon()
+{
+ return m_socket.write((unsigned char*)"DMRB", 4U, m_rptAddr, m_rptAddrLen);
+}
+
+void CMMDVMNetworkNew::close()
+{
+ LogMessage("MMDVM Network, Closing");
+
+ m_socket.close();
+}
+
+void CMMDVMNetworkNew::clock(unsigned int ms)
+{
+ 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_rptAddr, address)) {
+ LogMessage("MMDVM packet received from an invalid source");
+ return;
+ }
+
+ if (m_debug)
+ CUtils::dump(1U, "Network Received", m_buffer, length);
+
+ if (::memcmp(m_buffer, "DMRD", 4U) == 0) {
+ unsigned char len = length;
+ m_rxData.addData(&len, 1U);
+ m_rxData.addData(m_buffer, len);
+ } else if (::memcmp(m_buffer, "DMRG", 4U) == 0) {
+ ::memcpy(m_radioPositionData, m_buffer, length);
+ m_radioPositionLen = length;
+ } else if (::memcmp(m_buffer, "DMRA", 4U) == 0) {
+ ::memcpy(m_talkerAliasData, m_buffer, length);
+ m_talkerAliasLen = length;
+ } else if (::memcmp(m_buffer, "DMRC", 4U) == 0) {
+ m_id = (m_buffer[4U] << 24) | (m_buffer[5U] << 16) | (m_buffer[6U] << 8) | (m_buffer[7U] << 0);
+
+ if (m_configData == NULL) {
+ m_configLen = length - 8U;
+ m_configData = new unsigned char[m_configLen];
+ ::memcpy(m_configData, m_buffer + 8U, m_configLen);
+ }
+
+ m_socket.write((unsigned char*)"DMRP", 4U, m_rptAddr, m_rptAddrLen);
+ } else {
+ CUtils::dump("Unknown packet from the MMDVM", m_buffer, length);
+ }
+}
diff --git a/MMDVMNetworkNew.h b/MMDVMNetworkNew.h
new file mode 100644
index 0000000..cad3bf3
--- /dev/null
+++ b/MMDVMNetworkNew.h
@@ -0,0 +1,73 @@
+/*
+ * 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(MMDVMNetworkNew_H)
+#define MMDVMNetworkNew_H
+
+#include "MMDVMNetwork.h"
+#include "UDPSocket.h"
+#include "Timer.h"
+#include "RingBuffer.h"
+
+#include
+#include
+
+class CMMDVMNetworkNew : public IMMDVMNetwork
+{
+public:
+ CMMDVMNetworkNew(const std::string& rptAddress, unsigned int rptPort, const std::string& localAddress, unsigned int localPort, bool debug);
+ virtual ~CMMDVMNetworkNew();
+
+ virtual unsigned int getShortConfig(unsigned char* config) const;
+
+ virtual unsigned int getId() const;
+
+ virtual bool open();
+
+ virtual bool read(CDMRData& data);
+
+ virtual bool write(const CDMRData& data);
+
+ virtual bool readRadioPosition(unsigned char* data, unsigned int& length);
+
+ virtual bool readTalkerAlias(unsigned char* data, unsigned int& length);
+
+ virtual bool writeBeacon();
+
+ virtual void clock(unsigned int ms);
+
+ virtual void close();
+
+private:
+ sockaddr_storage m_rptAddr;
+ unsigned int m_rptAddrLen;
+ unsigned int m_id;
+ unsigned char* m_netId;
+ bool m_debug;
+ CUDPSocket m_socket;
+ unsigned char* m_buffer;
+ CRingBuffer m_rxData;
+ unsigned char* m_configData;
+ unsigned int m_configLen;
+ unsigned char* m_radioPositionData;
+ unsigned int m_radioPositionLen;
+ unsigned char* m_talkerAliasData;
+ unsigned int m_talkerAliasLen;
+};
+
+#endif
diff --git a/MMDVMNetworkOld.cpp b/MMDVMNetworkOld.cpp
new file mode 100644
index 0000000..57fef0f
--- /dev/null
+++ b/MMDVMNetworkOld.cpp
@@ -0,0 +1,373 @@
+/*
+ * Copyright (C) 2015,2016,2017,2018,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 "MMDVMNetworkOld.h"
+
+#include "StopWatch.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;
+
+
+CMMDVMNetworkOld::CMMDVMNetworkOld(const std::string& rptAddress, unsigned int rptPort, const std::string& localAddress, unsigned int localPort, bool debug) :
+m_rptAddr(),
+m_rptAddrLen(0U),
+m_id(0U),
+m_netId(NULL),
+m_debug(debug),
+m_socket(localAddress, localPort),
+m_buffer(NULL),
+m_rxData(1000U, "MMDVM Network"),
+m_options(),
+m_configData(NULL),
+m_configLen(0U),
+m_radioPositionData(NULL),
+m_radioPositionLen(0U),
+m_talkerAliasData(NULL),
+m_talkerAliasLen(0U),
+m_homePositionData(NULL),
+m_homePositionLen(0U)
+{
+ assert(!rptAddress.empty());
+ assert(rptPort > 0U);
+
+ if (CUDPSocket::lookup(rptAddress, rptPort, m_rptAddr, m_rptAddrLen) != 0)
+ m_rptAddrLen = 0U;
+
+ m_buffer = new unsigned char[BUFFER_LENGTH];
+ m_netId = new unsigned char[4U];
+
+ m_radioPositionData = new unsigned char[50U];
+ m_talkerAliasData = new unsigned char[50U];
+ m_homePositionData = new unsigned char[50U];
+
+ CStopWatch stopWatch;
+ ::srand(stopWatch.start());
+}
+
+CMMDVMNetworkOld::~CMMDVMNetworkOld()
+{
+ delete[] m_netId;
+ delete[] m_buffer;
+ delete[] m_configData;
+ delete[] m_radioPositionData;
+ delete[] m_talkerAliasData;
+ delete[] m_homePositionData;
+}
+
+std::string CMMDVMNetworkOld::getOptions() const
+{
+ return m_options;
+}
+
+unsigned int CMMDVMNetworkOld::getConfig(unsigned char* config) const
+{
+ if (m_configData == 0U)
+ return 0U;
+
+ ::memcpy(config, m_configData, m_configLen);
+
+ return m_configLen;
+}
+
+unsigned int CMMDVMNetworkOld::getId() const
+{
+ return m_id;
+}
+
+bool CMMDVMNetworkOld::open()
+{
+ if (m_rptAddrLen == 0U) {
+ LogError("Could not lookup the address of the MMDVM Host");
+ return false;
+ }
+
+ LogMessage("MMDVM Network, Opening");
+
+ return m_socket.open();
+}
+
+bool CMMDVMNetworkOld::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;
+
+ FLCO flco = (m_buffer[15U] & 0x40U) == 0x40U ? FLCO_USER_USER : FLCO_GROUP;
+
+ unsigned int streamId;
+ ::memcpy(&streamId, m_buffer + 16U, 4U);
+
+ unsigned char ber = m_buffer[53U];
+
+ unsigned char rssi = m_buffer[54U];
+
+ data.setSeqNo(seqNo);
+ data.setSlotNo(slotNo);
+ data.setSrcId(srcId);
+ data.setDstId(dstId);
+ data.setFLCO(flco);
+ data.setStreamId(streamId);
+ data.setBER(ber);
+ data.setRSSI(rssi);
+
+ 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 CMMDVMNetworkOld::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_netId, 4U);
+
+ unsigned int slotNo = data.getSlotNo();
+
+ buffer[15U] = slotNo == 1U ? 0x00U : 0x80U;
+
+ FLCO flco = data.getFLCO();
+ buffer[15U] |= flco == FLCO_GROUP ? 0x00U : 0x40U;
+
+ unsigned char dataType = data.getDataType();
+ if (dataType == DT_VOICE_SYNC) {
+ buffer[15U] |= 0x10U;
+ } else if (dataType == DT_VOICE) {
+ buffer[15U] |= data.getN();
+ } else {
+ buffer[15U] |= (0x20U | dataType);
+ }
+
+ buffer[4U] = data.getSeqNo();
+
+ unsigned int streamId = data.getStreamId();
+ ::memcpy(buffer + 16U, &streamId, 4U);
+
+ data.getData(buffer + 20U);
+
+ buffer[53U] = data.getBER();
+
+ buffer[54U] = data.getRSSI();
+
+ if (m_debug)
+ CUtils::dump(1U, "Network Transmitted", buffer, HOMEBREW_DATA_PACKET_LENGTH);
+
+ m_socket.write(buffer, HOMEBREW_DATA_PACKET_LENGTH, m_rptAddr, m_rptAddrLen);
+
+ return true;
+}
+
+bool CMMDVMNetworkOld::readRadioPosition(unsigned char* data, unsigned int& length)
+{
+ if (m_radioPositionLen == 0U)
+ return false;
+
+ ::memcpy(data, m_radioPositionData, m_radioPositionLen);
+ length = m_radioPositionLen;
+
+ m_radioPositionLen = 0U;
+
+ return true;
+}
+
+bool CMMDVMNetworkOld::readTalkerAlias(unsigned char* data, unsigned int& length)
+{
+ if (m_talkerAliasLen == 0U)
+ return false;
+
+ ::memcpy(data, m_talkerAliasData, m_talkerAliasLen);
+ length = m_talkerAliasLen;
+
+ m_talkerAliasLen = 0U;
+
+ return true;
+}
+
+bool CMMDVMNetworkOld::readHomePosition(unsigned char* data, unsigned int& length)
+{
+ if (m_homePositionLen == 0U)
+ return false;
+
+ ::memcpy(data, m_homePositionData, m_homePositionLen);
+ length = m_homePositionLen;
+
+ m_homePositionLen = 0U;
+
+ return true;
+}
+
+bool CMMDVMNetworkOld::writeBeacon()
+{
+ unsigned char buffer[20U];
+ ::memcpy(buffer + 0U, "RPTSBKN", 7U);
+ ::memcpy(buffer + 7U, m_netId, 4U);
+
+ return m_socket.write(buffer, 11U, m_rptAddr, m_rptAddrLen);
+}
+
+void CMMDVMNetworkOld::close()
+{
+ unsigned char buffer[HOMEBREW_DATA_PACKET_LENGTH];
+ ::memset(buffer, 0x00U, HOMEBREW_DATA_PACKET_LENGTH);
+
+ LogMessage("MMDVM Network, Closing");
+
+ ::memcpy(buffer + 0U, "MSTCL", 5U);
+ ::memcpy(buffer + 5U, m_netId, 4U);
+
+ m_socket.write(buffer, HOMEBREW_DATA_PACKET_LENGTH, m_rptAddr, m_rptAddrLen);
+ m_socket.close();
+}
+
+void CMMDVMNetworkOld::clock(unsigned int ms)
+{
+ sockaddr_storage address;
+ unsigned int addrlen;
+ int length = m_socket.read(m_buffer, BUFFER_LENGTH, address, addrlen);
+ if (length < 0) {
+ LogError("MMDVM Network, Socket has failed, reopening");
+ close();
+ open();
+ return;
+ }
+
+ if (!CUDPSocket::match(m_rptAddr, address)) {
+ LogMessage("MMDVM packet received from an invalid source");
+ return;
+ }
+
+ if (m_debug && length > 0)
+ CUtils::dump(1U, "Network Received", m_buffer, length);
+
+ if (length > 0) {
+ if (::memcmp(m_buffer, "DMRD", 4U) == 0) {
+ if (m_debug)
+ CUtils::dump(1U, "Network Received", m_buffer, length);
+
+ unsigned char len = length;
+ m_rxData.addData(&len, 1U);
+ m_rxData.addData(m_buffer, len);
+ } else if (::memcmp(m_buffer, "DMRG", 4U) == 0) {
+ ::memcpy(m_radioPositionData, m_buffer, length);
+ m_radioPositionLen = length;
+ } else if (::memcmp(m_buffer, "DMRA", 4U) == 0) {
+ ::memcpy(m_talkerAliasData, m_buffer, length);
+ m_talkerAliasLen = length;
+ } else if (::memcmp(m_buffer, "RPTG", 4U) == 0) {
+ ::memcpy(m_homePositionData, m_buffer, length);
+ m_homePositionLen = length;
+ } else if (::memcmp(m_buffer, "RPTL", 4U) == 0) {
+ m_id = (m_buffer[4U] << 24) | (m_buffer[5U] << 16) | (m_buffer[6U] << 8) | (m_buffer[7U] << 0);
+ ::memcpy(m_netId, m_buffer + 4U, 4U);
+
+ unsigned char ack[10U];
+ ::memcpy(ack + 0U, "RPTACK", 6U);
+
+ uint32_t salt = 1U;
+ ::memcpy(ack + 6U, &salt, sizeof(uint32_t));
+
+ m_socket.write(ack, 10U, m_rptAddr, m_rptAddrLen);
+ } else if (::memcmp(m_buffer, "RPTK", 4U) == 0) {
+ unsigned char ack[10U];
+ ::memcpy(ack + 0U, "RPTACK", 6U);
+ ::memcpy(ack + 6U, m_netId, 4U);
+ m_socket.write(ack, 10U, m_rptAddr, m_rptAddrLen);
+ } else if (::memcmp(m_buffer, "RPTCL", 5U) == 0) {
+ ::LogMessage("MMDVM Network, The connected MMDVM is closing down");
+ } else if (::memcmp(m_buffer, "RPTC", 4U) == 0) {
+ m_configLen = length - 8U;
+ m_configData = new unsigned char[m_configLen];
+ ::memcpy(m_configData, m_buffer + 8U, m_configLen);
+
+ unsigned char ack[10U];
+ ::memcpy(ack + 0U, "RPTACK", 6U);
+ ::memcpy(ack + 6U, m_netId, 4U);
+ m_socket.write(ack, 10U, m_rptAddr, m_rptAddrLen);
+ } else if (::memcmp(m_buffer, "RPTO", 4U) == 0) {
+ m_options = std::string((char*)(m_buffer + 8U), length - 8U);
+
+ unsigned char ack[10U];
+ ::memcpy(ack + 0U, "RPTACK", 6U);
+ ::memcpy(ack + 6U, m_netId, 4U);
+ m_socket.write(ack, 10U, m_rptAddr, m_rptAddrLen);
+ } else if (::memcmp(m_buffer, "RPTPING", 7U) == 0) {
+ unsigned char pong[11U];
+ ::memcpy(pong + 0U, "MSTPONG", 7U);
+ ::memcpy(pong + 7U, m_netId, 4U);
+ m_socket.write(pong, 11U, m_rptAddr, m_rptAddrLen);
+ } else {
+ CUtils::dump("Unknown packet from the master", m_buffer, length);
+ }
+ }
+}
diff --git a/MMDVMNetworkOld.h b/MMDVMNetworkOld.h
new file mode 100644
index 0000000..27b1ee0
--- /dev/null
+++ b/MMDVMNetworkOld.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2015,2016,2017,2018,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(MMDVMNetworkOld_H)
+#define MMDVMNetworkOld_H
+
+#include "MMDVMNetwork.h"
+#include "UDPSocket.h"
+#include "Timer.h"
+#include "RingBuffer.h"
+
+#include
+#include
+
+class CMMDVMNetworkOld : public IMMDVMNetwork
+{
+public:
+ CMMDVMNetworkOld(const std::string& rptAddress, unsigned int rptPort, const std::string& localAddress, unsigned int localPort, bool debug);
+ virtual ~CMMDVMNetworkOld();
+
+ virtual std::string getOptions() const;
+
+ virtual unsigned int getConfig(unsigned char* config) const;
+
+ virtual unsigned int getId() const;
+
+ virtual bool open();
+
+ virtual bool read(CDMRData& data);
+
+ virtual bool write(const CDMRData& data);
+
+ virtual bool readRadioPosition(unsigned char* data, unsigned int& length);
+
+ virtual bool readTalkerAlias(unsigned char* data, unsigned int& length);
+
+ virtual bool readHomePosition(unsigned char* data, unsigned int& length);
+
+ virtual bool writeBeacon();
+
+ virtual void clock(unsigned int ms);
+
+ virtual void close();
+
+private:
+ sockaddr_storage m_rptAddr;
+ unsigned int m_rptAddrLen;
+ unsigned int m_id;
+ unsigned char* m_netId;
+ bool m_debug;
+ CUDPSocket m_socket;
+ unsigned char* m_buffer;
+ CRingBuffer m_rxData;
+ std::string m_options;
+ unsigned char* m_configData;
+ unsigned int m_configLen;
+ unsigned char* m_radioPositionData;
+ unsigned int m_radioPositionLen;
+ unsigned char* m_talkerAliasData;
+ unsigned int m_talkerAliasLen;
+ unsigned char* m_homePositionData;
+ unsigned int m_homePositionLen;
+};
+
+#endif
diff --git a/Makefile b/Makefile
index 06cd120..3f3b12b 100644
--- a/Makefile
+++ b/Makefile
@@ -12,9 +12,9 @@ LIBS = -lpthread
LDFLAGS = -g
OBJECTS = APRSWriter.o BPTC19696.o Conf.o CRC.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREmbeddedData.o DMREMB.o DMRFullLC.o DMRGateway.o \
- DMRLC.o DMRNetwork.o DMRSlotType.o DynVoice.o Golay2087.o GPSD.o Hamming.o Log.o MMDVMNetwork.o PassAllPC.o PassAllTG.o \
- QR1676.o Reflectors.o Rewrite.o RewriteDstId.o RewriteDynTGNet.o RewriteDynTGRF.o RewritePC.o RewriteSrc.o RewriteSrcId.o \
- RewriteTG.o RewriteType.o RS129.o SHA256.o StopWatch.o Sync.o Thread.o Timer.o UDPSocket.o Utils.o XLXVoice.o
+ DMRLC.o DMRNetwork.o DMRSlotType.o DynVoice.o Golay2087.o GPSD.o Hamming.o Log.o MMDVMNetwork.o MMDVMNetworkNew.o MMDVMNetworkOld.o \
+ PassAllPC.o PassAllTG.o QR1676.o Reflectors.o Rewrite.o RewriteDstId.o RewriteDynTGNet.o RewriteDynTGRF.o RewritePC.o RewriteSrc.o \
+ RewriteSrcId.o RewriteTG.o RewriteType.o RS129.o SHA256.o StopWatch.o Sync.o Thread.o Timer.o UDPSocket.o Utils.o XLXVoice.o
all: DMRGateway