From e24909926d52224fe0c3a0bafec136dc583944b5 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 11 Oct 2016 17:43:37 +0100 Subject: [PATCH] Add extra reflector control data to the gateway. --- P25Gateway/Conf.cpp | 16 --- P25Gateway/Conf.h | 4 - P25Gateway/Network.cpp | 38 ++++++- P25Gateway/Network.h | 7 +- P25Gateway/P25Gateway.cpp | 67 ++++++++++-- P25Gateway/P25Gateway.ini | 3 - P25Gateway/P25Gateway.vcxproj | 1 - P25Gateway/P25Gateway.vcxproj.filters | 3 - P25Gateway/Reflectors.cpp | 2 - P25Gateway/RingBuffer.h | 147 -------------------------- 10 files changed, 99 insertions(+), 189 deletions(-) delete mode 100644 P25Gateway/RingBuffer.h diff --git a/P25Gateway/Conf.cpp b/P25Gateway/Conf.cpp index 542bd5e..b0f3d6b 100644 --- a/P25Gateway/Conf.cpp +++ b/P25Gateway/Conf.cpp @@ -43,8 +43,6 @@ m_myPort(0U), m_daemon(false), m_lookupName(), m_lookupTime(0U), -m_logDisplayLevel(0U), -m_logFileLevel(0U), m_logFilePath(), m_logFileRoot(), m_networkEnabled(false), @@ -121,10 +119,6 @@ bool CConf::read() m_logFilePath = value; else if (::strcmp(key, "FileRoot") == 0) m_logFileRoot = value; - else if (::strcmp(key, "FileLevel") == 0) - m_logFileLevel = (unsigned int)::atoi(value); - else if (::strcmp(key, "DisplayLevel") == 0) - m_logDisplayLevel = (unsigned int)::atoi(value); } else if (section == SECTION_NETWORK) { if (::strcmp(key, "Enable") == 0) m_networkEnabled = ::atoi(value) == 1; @@ -185,16 +179,6 @@ unsigned int CConf::getLookupTime() const return m_lookupTime; } -unsigned int CConf::getLogDisplayLevel() const -{ - return m_logDisplayLevel; -} - -unsigned int CConf::getLogFileLevel() const -{ - return m_logFileLevel; -} - std::string CConf::getLogFilePath() const { return m_logFilePath; diff --git a/P25Gateway/Conf.h b/P25Gateway/Conf.h index e311d79..879e6ba 100644 --- a/P25Gateway/Conf.h +++ b/P25Gateway/Conf.h @@ -42,8 +42,6 @@ public: unsigned int getLookupTime() const; // The Log section - unsigned int getLogDisplayLevel() const; - unsigned int getLogFileLevel() const; std::string getLogFilePath() const; std::string getLogFileRoot() const; @@ -68,8 +66,6 @@ private: std::string m_lookupName; unsigned int m_lookupTime; - unsigned int m_logDisplayLevel; - unsigned int m_logFileLevel; std::string m_logFilePath; std::string m_logFileRoot; diff --git a/P25Gateway/Network.cpp b/P25Gateway/Network.cpp index 84d925e..f02fc09 100644 --- a/P25Gateway/Network.cpp +++ b/P25Gateway/Network.cpp @@ -24,10 +24,12 @@ #include #include -CNetwork::CNetwork(unsigned int port, bool debug) : +CNetwork::CNetwork(unsigned int port, const std::string& callsign, bool debug) : +m_callsign(callsign), m_socket(port), m_debug(debug) { + m_callsign.resize(10U, ' '); } CNetwork::~CNetwork() @@ -53,6 +55,40 @@ bool CNetwork::writeData(const unsigned char* data, unsigned int length, const i return m_socket.write(data, length, address, port); } +bool CNetwork::writePoll(const in_addr& address, unsigned int port) +{ + assert(port > 0U); + + unsigned char data[15U]; + + data[0U] = 0xF0U; + + for (unsigned int i = 0U; i < 10U; i++) + data[i + 1U] = m_callsign.at(i); + + if (m_debug) + CUtils::dump(1U, "P25 Network Poll Sent", data, 11U); + + return m_socket.write(data, 11U, address, port); +} + +bool CNetwork::writeUnlink(const in_addr& address, unsigned int port) +{ + assert(port > 0U); + + unsigned char data[15U]; + + data[0U] = 0xF1U; + + for (unsigned int i = 0U; i < 10U; i++) + data[i + 1U] = m_callsign.at(i); + + if (m_debug) + CUtils::dump(1U, "P25 Network Unlink Sent", data, 11U); + + return m_socket.write(data, 11U, address, port); +} + unsigned int CNetwork::readData(unsigned char* data, unsigned int length, in_addr& address, unsigned int& port) { assert(data != NULL); diff --git a/P25Gateway/Network.h b/P25Gateway/Network.h index 2081999..ab78bc4 100644 --- a/P25Gateway/Network.h +++ b/P25Gateway/Network.h @@ -26,7 +26,7 @@ class CNetwork { public: - CNetwork(unsigned int port, bool debug); + CNetwork(unsigned int port, const std::string& callsign, bool debug); ~CNetwork(); bool open(); @@ -35,9 +35,14 @@ public: unsigned int readData(unsigned char* data, unsigned int length, in_addr& address, unsigned int& port); + bool writePoll(const in_addr& address, unsigned int port); + + bool writeUnlink(const in_addr& address, unsigned int port); + void close(); private: + std::string m_callsign; CUDPSocket m_socket; bool m_debug; }; diff --git a/P25Gateway/P25Gateway.cpp b/P25Gateway/P25Gateway.cpp index 1bd30d9..3327cf9 100644 --- a/P25Gateway/P25Gateway.cpp +++ b/P25Gateway/P25Gateway.cpp @@ -92,7 +92,7 @@ void CP25Gateway::run() return; } - ret = ::LogInitialise(m_conf.getLogFilePath(), m_conf.getLogFileRoot(), m_conf.getLogFileLevel(), m_conf.getLogDisplayLevel()); + ret = ::LogInitialise(m_conf.getLogFilePath(), m_conf.getLogFileRoot(), 1U, 1U); if (!ret) { ::fprintf(stderr, "P25Gateway: unable to open the log file\n"); return; @@ -160,7 +160,7 @@ void CP25Gateway::run() in_addr rptAddr = CUDPSocket::lookup(m_conf.getRptAddress()); unsigned int rptPort = m_conf.getRptPort(); - CNetwork localNetwork(m_conf.getMyPort(), false); + CNetwork localNetwork(m_conf.getMyPort(), m_conf.getCallsign(), false); ret = localNetwork.open(); if (!ret) { @@ -170,7 +170,7 @@ void CP25Gateway::run() CNetwork* remoteNetwork = NULL; if (m_conf.getNetworkEnabled()) { - remoteNetwork = new CNetwork(m_conf.getNetworkDataPort(), m_conf.getNetworkDebug()); + remoteNetwork = new CNetwork(m_conf.getNetworkDataPort(), m_conf.getCallsign(), m_conf.getNetworkDebug()); ret = remoteNetwork->open(); if (!ret) { localNetwork.close(); @@ -187,6 +187,9 @@ void CP25Gateway::run() CDMRLookup* lookup = new CDMRLookup(m_conf.getLookupName(), m_conf.getLookupTime()); lookup->read(); + CTimer lostTimer(1000U, 120U); + CTimer pollTimer(1000U, 20U); + CStopWatch stopWatch; stopWatch.start(); @@ -207,6 +210,10 @@ void CP25Gateway::run() currentId = id; currentAddr = reflector->m_address; currentPort = reflector->m_port; + + pollTimer.start(); + lostTimer.start(); + LogMessage("Linked at startup to reflector %u", currentId); } } @@ -223,16 +230,22 @@ void CP25Gateway::run() if (len > 0U) { // If we're linked and it's from the right place, send it on if (currentId != 9999U && currentAddr.s_addr == address.s_addr && currentPort == port) { - // Rewrite the LCF and the destination TG - if (buffer[0U] == 0x64U) { - buffer[1U] = 0x00U; // LCF is for TGs - } else if (buffer[0U] == 0x65U) { - buffer[1U] = (currentId >> 16) & 0xFFU; - buffer[2U] = (currentId >> 8) & 0xFFU; - buffer[3U] = (currentId >> 0) & 0xFFU; + // Don't pass reflector control data through to the MMDVM + if (buffer[0U] != 0xF0U && buffer[0U] != 0xF1U) { + // Rewrite the LCF and the destination TG + if (buffer[0U] == 0x64U) { + buffer[1U] = 0x00U; // LCF is for TGs + } else if (buffer[0U] == 0x65U) { + buffer[1U] = (currentId >> 16) & 0xFFU; + buffer[2U] = (currentId >> 8) & 0xFFU; + buffer[3U] = (currentId >> 0) & 0xFFU; + } + + localNetwork.writeData(buffer, len, rptAddr, rptPort); } - localNetwork.writeData(buffer, len, rptAddr, rptPort); + // Any network activity is proof that the reflector is alive + lostTimer.start(); } } } @@ -254,6 +267,14 @@ void CP25Gateway::run() std::string callsign = lookup->find(srcId); LogMessage("Unlinked from reflector %u by %s", currentId, callsign.c_str()); currentId = dstId; + + if (remoteNetwork != NULL) { + remoteNetwork->writeUnlink(currentAddr, currentPort); + remoteNetwork->writeUnlink(currentAddr, currentPort); + remoteNetwork->writeUnlink(currentAddr, currentPort); + pollTimer.stop(); + lostTimer.stop(); + } } else { CP25Reflector* reflector = reflectors.find(dstId); if (reflector != NULL) { @@ -263,6 +284,14 @@ void CP25Gateway::run() std::string callsign = lookup->find(srcId); LogMessage("Linked to reflector %u by %s", currentId, callsign.c_str()); + + if (remoteNetwork != NULL) { + remoteNetwork->writePoll(currentAddr, currentPort); + remoteNetwork->writePoll(currentAddr, currentPort); + remoteNetwork->writePoll(currentAddr, currentPort); + pollTimer.start(); + lostTimer.start(); + } } } } @@ -288,6 +317,22 @@ void CP25Gateway::run() reflectors.clock(ms); + pollTimer.clock(ms); + if (pollTimer.isRunning() && pollTimer.hasExpired()) { + if (currentId != 9999U && remoteNetwork != NULL) + remoteNetwork->writePoll(currentAddr, currentPort); + pollTimer.start(); + } + + lostTimer.clock(ms); + if (lostTimer.isRunning() && lostTimer.hasExpired()) { + if (currentId != 9999U) { + LogWarning("No response from %u, unlinking", currentId); + currentId = 9999U; + } + lostTimer.stop(); + } + if (ms < 5U) { #if defined(_WIN32) || defined(_WIN64) ::Sleep(5UL); // 5ms diff --git a/P25Gateway/P25Gateway.ini b/P25Gateway/P25Gateway.ini index 9a8e394..99ddd35 100644 --- a/P25Gateway/P25Gateway.ini +++ b/P25Gateway/P25Gateway.ini @@ -10,9 +10,6 @@ Name=DMRIds.dat Time=24 [Log] -# Logging levels, 0=No logging -DisplayLevel=1 -FileLevel=1 FilePath=. FileRoot=P25Gateway diff --git a/P25Gateway/P25Gateway.vcxproj b/P25Gateway/P25Gateway.vcxproj index 4cdc5b2..9d3a934 100644 --- a/P25Gateway/P25Gateway.vcxproj +++ b/P25Gateway/P25Gateway.vcxproj @@ -153,7 +153,6 @@ - diff --git a/P25Gateway/P25Gateway.vcxproj.filters b/P25Gateway/P25Gateway.vcxproj.filters index 3f99fb9..9719a60 100644 --- a/P25Gateway/P25Gateway.vcxproj.filters +++ b/P25Gateway/P25Gateway.vcxproj.filters @@ -29,9 +29,6 @@ Header Files - - Header Files - Header Files diff --git a/P25Gateway/Reflectors.cpp b/P25Gateway/Reflectors.cpp index 33a0614..d2c26f5 100644 --- a/P25Gateway/Reflectors.cpp +++ b/P25Gateway/Reflectors.cpp @@ -113,8 +113,6 @@ CP25Reflector* CReflectors::find(unsigned int id) return *it; } - LogMessage("Trying to find non existent reflector with an id of %u", id); - return NULL; } diff --git a/P25Gateway/RingBuffer.h b/P25Gateway/RingBuffer.h deleted file mode 100644 index 186709d..0000000 --- a/P25Gateway/RingBuffer.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (C) 2006-2009,2012,2013,2015,2016 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. - */ - -#ifndef RingBuffer_H -#define RingBuffer_H - -#include -#include -#include - -template class CRingBuffer { -public: - CRingBuffer(unsigned int length, const char* name) : - m_length(length), - m_name(name), - m_buffer(NULL), - m_iPtr(0U), - m_oPtr(0U) - { - assert(length > 0U); - assert(name != NULL); - - m_buffer = new T[length]; - - ::memset(m_buffer, 0x00, m_length * sizeof(T)); - } - - ~CRingBuffer() - { - delete[] m_buffer; - } - - bool addData(const T* buffer, unsigned int nSamples) - { - if (nSamples >= freeSpace()) { - ::fprintf(stderr, "**** Overflow in %s ring buffer, %u >= %u\n", m_name, nSamples, freeSpace()); - return false; - } - - for (unsigned int i = 0U; i < nSamples; i++) { - m_buffer[m_iPtr++] = buffer[i]; - - if (m_iPtr == m_length) - m_iPtr = 0U; - } - - return true; - } - - bool getData(T* buffer, unsigned int nSamples) - { - if (dataSize() < nSamples) { - ::fprintf(stderr, "**** Underflow in %s ring buffer, %u < %u\n", m_name, dataSize(), nSamples); - return false; - } - - for (unsigned int i = 0U; i < nSamples; i++) { - buffer[i] = m_buffer[m_oPtr++]; - - if (m_oPtr == m_length) - m_oPtr = 0U; - } - - return true; - } - - bool peek(T* buffer, unsigned int nSamples) - { - if (dataSize() < nSamples) { - ::fprintf(stderr, "**** Underflow peek in %s ring buffer, %u < %u\n", m_name, dataSize(), nSamples); - return false; - } - - unsigned int ptr = m_oPtr; - for (unsigned int i = 0U; i < nSamples; i++) { - buffer[i] = m_buffer[ptr++]; - - if (ptr == m_length) - ptr = 0U; - } - - return true; - } - - void clear() - { - m_iPtr = 0U; - m_oPtr = 0U; - - ::memset(m_buffer, 0x00, m_length * sizeof(T)); - } - - unsigned int freeSpace() const - { - if (m_oPtr == m_iPtr) - return m_length; - - if (m_oPtr > m_iPtr) - return m_oPtr - m_iPtr; - - return (m_length + m_oPtr) - m_iPtr; - } - - unsigned int dataSize() const - { - return m_length - freeSpace(); - } - - bool hasSpace(unsigned int length) const - { - return freeSpace() > length; - } - - bool hasData() const - { - return m_oPtr != m_iPtr; - } - - bool isEmpty() const - { - return m_oPtr == m_iPtr; - } - -private: - unsigned int m_length; - const char* m_name; - T* m_buffer; - unsigned int m_iPtr; - unsigned int m_oPtr; -}; - -#endif