From adb4ab511d57ff6e4139b15ee9617407ebcd0508 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 26 Oct 2020 17:12:28 +0000 Subject: [PATCH] Allow for static and dynamic TGs. --- P25Gateway/Conf.cpp | 65 +++---- P25Gateway/Conf.h | 19 +- P25Gateway/P25Gateway.cpp | 373 +++++++++++++++----------------------- P25Gateway/P25Gateway.ini | 10 +- P25Gateway/Version.h | 2 +- 5 files changed, 196 insertions(+), 273 deletions(-) diff --git a/P25Gateway/Conf.cpp b/P25Gateway/Conf.cpp index 7dab28f..a565356 100644 --- a/P25Gateway/Conf.cpp +++ b/P25Gateway/Conf.cpp @@ -32,8 +32,7 @@ enum SECTION { SECTION_ID_LOOKUP, SECTION_VOICE, SECTION_LOG, - SECTION_NETWORK, - SECTION_REMOTE_COMMANDS + SECTION_NETWORK }; CConf::CConf(const std::string& file) : @@ -42,6 +41,7 @@ m_callsign(), m_rptAddress(), m_rptPort(0U), m_myPort(0U), +m_debug(false), m_daemon(false), m_lookupName(), m_lookupTime(0U), @@ -58,11 +58,10 @@ m_networkHosts2(), m_networkReloadTime(0U), m_networkParrotAddress("127.0.0.1"), m_networkParrotPort(0U), -m_networkStartup(9999U), -m_networkInactivityTimeout(0U), -m_networkDebug(false), -m_remoteCommandsEnabled(false), -m_remoteCommandsPort(6074U) +m_networkStatic(), +m_networkRFHangTime(120U), +m_networkNetHangTime(60U), +m_networkDebug(false) { } @@ -96,8 +95,6 @@ bool CConf::read() section = SECTION_LOG; else if (::strncmp(buffer, "[Network]", 9U) == 0) section = SECTION_NETWORK; - else if (::strncmp(buffer, "[Remote Commands]", 17U) == 0) - section = SECTION_REMOTE_COMMANDS; else section = SECTION_NONE; @@ -141,6 +138,8 @@ bool CConf::read() m_rptPort = (unsigned int)::atoi(value); else if (::strcmp(key, "LocalPort") == 0) m_myPort = (unsigned int)::atoi(value); + else if (::strcmp(key, "Debug") == 0) + m_debug = ::atoi(value) == 1; else if (::strcmp(key, "Daemon") == 0) m_daemon = ::atoi(value) == 1; } else if (section == SECTION_ID_LOOKUP) { @@ -181,17 +180,19 @@ bool CConf::read() m_networkP252DMRAddress = value; else if (::strcmp(key, "P252DMRPort") == 0) m_networkP252DMRPort = (unsigned int)::atoi(value); - else if (::strcmp(key, "Startup") == 0) - m_networkStartup = (unsigned int)::atoi(value); - else if (::strcmp(key, "InactivityTimeout") == 0) - m_networkInactivityTimeout = (unsigned int)::atoi(value); + else if (::strcmp(key, "Static") == 0) { + char* p = ::strtok(value, ",\r\n"); + while (p != NULL) { + unsigned int tg = (unsigned int)::atoi(p); + m_networkStatic.push_back(tg); + p = ::strtok(NULL, ",\r\n"); + } + } else if (::strcmp(key, "RFHangTime") == 0) + m_networkRFHangTime = (unsigned int)::atoi(value); + else if (::strcmp(key, "NetHangTime") == 0) + m_networkNetHangTime = (unsigned int)::atoi(value); else if (::strcmp(key, "Debug") == 0) m_networkDebug = ::atoi(value) == 1; - } else if (section == SECTION_REMOTE_COMMANDS) { - if (::strcmp(key, "Enable") == 0) - m_remoteCommandsEnabled = ::atoi(value) == 1; - else if (::strcmp(key, "Port") == 0) - m_remoteCommandsPort = (unsigned int)::atoi(value); } } @@ -220,6 +221,11 @@ unsigned int CConf::getMyPort() const return m_myPort; } +bool CConf::getDebug() const +{ + return m_debug; +} + bool CConf::getDaemon() const { return m_daemon; @@ -310,27 +316,22 @@ unsigned int CConf::getNetworkP252DMRPort() const return m_networkP252DMRPort; } -unsigned int CConf::getNetworkStartup() const +std::vector CConf::getNetworkStatic() const { - return m_networkStartup; + return m_networkStatic; } -unsigned int CConf::getNetworkInactivityTimeout() const +unsigned int CConf::getNetworkRFHangTime() const { - return m_networkInactivityTimeout; + return m_networkRFHangTime; +} + +unsigned int CConf::getNetworkNetHangTime() const +{ + return m_networkNetHangTime; } bool CConf::getNetworkDebug() const { return m_networkDebug; } - -bool CConf::getRemoteCommandsEnabled() const -{ - return m_remoteCommandsEnabled; -} - -unsigned int CConf::getRemoteCommandsPort() const -{ - return m_remoteCommandsPort; -} diff --git a/P25Gateway/Conf.h b/P25Gateway/Conf.h index 6541395..0b731d4 100644 --- a/P25Gateway/Conf.h +++ b/P25Gateway/Conf.h @@ -35,6 +35,7 @@ public: std::string getRptAddress() const; unsigned int getRptPort() const; unsigned int getMyPort() const; + bool getDebug() const; bool getDaemon() const; // The Id Lookup section @@ -61,20 +62,18 @@ public: unsigned int getNetworkParrotPort() const; std::string getNetworkP252DMRAddress() const; unsigned int getNetworkP252DMRPort() const; - unsigned int getNetworkStartup() const; - unsigned int getNetworkInactivityTimeout() const; + std::vector getNetworkStatic() const; + unsigned int getNetworkRFHangTime() const; + unsigned int getNetworkNetHangTime() const; bool getNetworkDebug() const; - // The Remote Commands section - bool getRemoteCommandsEnabled() const; - unsigned int getRemoteCommandsPort() const; - private: std::string m_file; std::string m_callsign; std::string m_rptAddress; unsigned int m_rptPort; unsigned int m_myPort; + bool m_debug; bool m_daemon; std::string m_lookupName; @@ -97,12 +96,10 @@ private: unsigned int m_networkParrotPort; std::string m_networkP252DMRAddress; unsigned int m_networkP252DMRPort; - unsigned int m_networkStartup; - unsigned int m_networkInactivityTimeout; + std::vector m_networkStatic;; + unsigned int m_networkRFHangTime; + unsigned int m_networkNetHangTime; bool m_networkDebug; - - bool m_remoteCommandsEnabled; - unsigned int m_remoteCommandsPort; }; #endif diff --git a/P25Gateway/P25Gateway.cpp b/P25Gateway/P25Gateway.cpp index 05bd1e0..b6635a7 100644 --- a/P25Gateway/P25Gateway.cpp +++ b/P25Gateway/P25Gateway.cpp @@ -57,6 +57,13 @@ const unsigned P25_VOICE_ID = 10999U; #include #include +class CStaticTG { +public: + unsigned int m_tg; + sockaddr_storage m_addr; + unsigned int m_addrLen; +}; + int main(int argc, char** argv) { const char* iniFile = DEFAULT_INI_FILE; @@ -181,17 +188,7 @@ void CP25Gateway::run() return; } - CUDPSocket* remoteSocket = NULL; - if (m_conf.getRemoteCommandsEnabled()) { - remoteSocket = new CUDPSocket(m_conf.getRemoteCommandsPort()); - ret = remoteSocket->open(); - if (!ret) { - delete remoteSocket; - remoteSocket = NULL; - } - } - - CNetwork localNetwork(m_conf.getMyPort(), m_conf.getCallsign(), false); + CNetwork localNetwork(m_conf.getMyPort(), m_conf.getCallsign(), m_conf.getDebug()); ret = localNetwork.open(); if (!ret) { ::LogFinalise(); @@ -216,9 +213,13 @@ void CP25Gateway::run() CDMRLookup* lookup = new CDMRLookup(m_conf.getLookupName(), m_conf.getLookupTime()); lookup->read(); - CTimer inactivityTimer(1000U, m_conf.getNetworkInactivityTimeout() * 60U); - CTimer lostTimer(1000U, 120U); + unsigned int rfHangTime = m_conf.getNetworkRFHangTime(); + unsigned int netHangTime = m_conf.getNetworkNetHangTime(); + + CTimer hangTimer(1000U); + CTimer pollTimer(1000U, 5U); + pollTimer.start(); CStopWatch stopWatch; stopWatch.start(); @@ -236,145 +237,189 @@ void CP25Gateway::run() LogMessage("Starting P25Gateway-%s", VERSION); unsigned int srcId = 0U; - unsigned int dstId = 0U; + unsigned int dstTG = 0U; - unsigned int currentId = 9999U; + bool currentIsStatic = false; + unsigned int currentTG = 0U; unsigned int currentAddrLen = 0U; sockaddr_storage currentAddr; - unsigned int startupId = m_conf.getNetworkStartup(); - bool p252dmr_enabled = (startupId == 20) ? true : false; - - if (startupId != 9999U) { - CP25Reflector* reflector = reflectors.find(startupId); + std::vector staticIds = m_conf.getNetworkStatic(); + + std::vector staticTGs; + for (std::vector::const_iterator it = staticIds.cbegin(); it != staticIds.cend(); ++it) { + CP25Reflector* reflector = reflectors.find(*it); if (reflector != NULL) { - currentId = startupId; - currentAddr = reflector->m_addr; - currentAddrLen = reflector->m_addrLen; + CStaticTG staticTG; + staticTG.m_tg = *it; + staticTG.m_addr = reflector->m_addr; + staticTG.m_addrLen = reflector->m_addrLen; + staticTGs.push_back(staticTG); - inactivityTimer.start(); - pollTimer.start(); - lostTimer.start(); + remoteNetwork.writePoll(staticTG.m_addr, staticTG.m_addrLen); + remoteNetwork.writePoll(staticTG.m_addr, staticTG.m_addrLen); + remoteNetwork.writePoll(staticTG.m_addr, staticTG.m_addrLen); - remoteNetwork.writePoll(currentAddr, currentAddrLen); - remoteNetwork.writePoll(currentAddr, currentAddrLen); - remoteNetwork.writePoll(currentAddr, currentAddrLen); - - LogMessage("Linked at startup to reflector %u", currentId); + LogMessage("Statically linked to reflector %u", *it); } } for (;;) { unsigned char buffer[200U]; sockaddr_storage addr; - unsigned int addrlen; + unsigned int addrLen; // From the reflector to the MMDVM - unsigned int len = remoteNetwork.readData(buffer, 200U, addr, addrlen); + unsigned int len = remoteNetwork.readData(buffer, 200U, addr, addrLen); if (len > 0U) { // If we're linked and it's from the right place, send it on - if (currentId != 9999U && CUDPSocket::match(currentAddr, addr)) { + if (currentTG > 0U && CUDPSocket::match(currentAddr, addr)) { // 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; + buffer[1U] = (currentTG >> 16) & 0xFFU; + buffer[2U] = (currentTG >> 8) & 0xFFU; + buffer[3U] = (currentTG >> 0) & 0xFFU; } localNetwork.writeData(buffer, len, rptAddr, rptAddrLen); - } - // Any network activity is proof that the reflector is alive - lostTimer.start(); + hangTimer.start(); + } + } else if (currentTG == 0U) { + // Don't pass reflector control data through to the MMDVM + if (buffer[0U] != 0xF0U && buffer[0U] != 0xF1U) { + // Find the static TG that this audio data belongs to + for (std::vector::const_iterator it = staticTGs.cbegin(); it != staticTGs.cend(); ++it) { + if (CUDPSocket::match(addr, (*it).m_addr)) { + currentTG = (*it).m_tg; + break; + } + } + + if (currentTG > 0U) { + currentAddr = addr; + currentAddrLen = addrLen; + currentIsStatic = true; + + // 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] = (currentTG >> 16) & 0xFFU; + buffer[2U] = (currentTG >> 8) & 0xFFU; + buffer[3U] = (currentTG >> 0) & 0xFFU; + } + + localNetwork.writeData(buffer, len, rptAddr, rptAddrLen); + + LogMessage("Switched to reflector %u due to network activity", currentTG); + + hangTimer.setTimeout(netHangTime); + hangTimer.start(); + } + } } } // From the MMDVM to the reflector or control data - len = localNetwork.readData(buffer, 200U, addr, addrlen); + len = localNetwork.readData(buffer, 200U, addr, addrLen); if (len > 0U) { if (buffer[0U] == 0x65U) { - dstId = (buffer[1U] << 16) & 0xFF0000U; - dstId |= (buffer[2U] << 8) & 0x00FF00U; - dstId |= (buffer[3U] << 0) & 0x0000FFU; + dstTG = (buffer[1U] << 16) & 0xFF0000U; + dstTG |= (buffer[2U] << 8) & 0x00FF00U; + dstTG |= (buffer[3U] << 0) & 0x0000FFU; } else if (buffer[0U] == 0x66U) { srcId = (buffer[1U] << 16) & 0xFF0000U; srcId |= (buffer[2U] << 8) & 0x00FF00U; srcId |= (buffer[3U] << 0) & 0x0000FFU; - if(p252dmr_enabled){ - currentId = dstId; - } - else if (dstId != currentId) { - CP25Reflector* reflector = NULL; - if (dstId != 9999U) - reflector = reflectors.find(dstId); - - // If we're unlinking or changing reflectors, unlink from the current one - if (dstId == 9999U || reflector != NULL) { + if (dstTG != currentTG) { + if (currentTG > 0U) { std::string callsign = lookup->find(srcId); + LogMessage("Unlinking from reflector %u by %s", currentTG, callsign.c_str()); - if (currentId != 9999U) { - LogMessage("Unlinked from reflector %u by %s", currentId, callsign.c_str()); - + if (!currentIsStatic) { remoteNetwork.writeUnlink(currentAddr, currentAddrLen); remoteNetwork.writeUnlink(currentAddr, currentAddrLen); remoteNetwork.writeUnlink(currentAddr, currentAddrLen); - - inactivityTimer.stop(); - pollTimer.stop(); - lostTimer.stop(); } - if (voice != NULL) { - if (dstId == 9999U) - voice->unlinked(); - else - voice->linkedTo(dstId); - } + hangTimer.stop(); + } - currentId = dstId; + const CStaticTG* found = NULL; + for (std::vector::const_iterator it = staticTGs.cbegin(); it != staticTGs.cend(); ++it) { + if (dstTG == (*it).m_tg) { + found = &(*it); + break; + } + } + + currentTG = 0U; + currentAddrLen = 0U; + + if (found == NULL) { + CP25Reflector* refl = reflectors.find(dstTG); + if (refl != NULL) { + currentTG = dstTG; + currentAddr = refl->m_addr; + currentAddrLen = refl->m_addrLen; + currentIsStatic = false; + } + } else { + currentTG = found->m_tg; + currentAddr = found->m_addr; + currentAddrLen = found->m_addrLen; + currentIsStatic = true; } // Link to the new reflector - if (reflector != NULL) { - currentId = dstId; - currentAddr = reflector->m_addr; - currentAddrLen = reflector->m_addrLen; - + if (currentAddrLen > 0U) { std::string callsign = lookup->find(srcId); - LogMessage("Linked to reflector %u by %s", currentId, callsign.c_str()); + LogMessage("Switched to reflector %u due to RF activity from %s", currentTG, callsign.c_str()); - remoteNetwork.writePoll(currentAddr, currentAddrLen); - remoteNetwork.writePoll(currentAddr, currentAddrLen); - remoteNetwork.writePoll(currentAddr, currentAddrLen); + if (!currentIsStatic) { + remoteNetwork.writePoll(currentAddr, currentAddrLen); + remoteNetwork.writePoll(currentAddr, currentAddrLen); + remoteNetwork.writePoll(currentAddr, currentAddrLen); + } - inactivityTimer.start(); - pollTimer.start(); - lostTimer.start(); + hangTimer.setTimeout(rfHangTime); + hangTimer.start(); } + + if (voice != NULL) { + if (currentTG == 0U) + voice->unlinked(); + else + voice->linkedTo(dstTG); + } + } - } else if (buffer[0U] == 0x80U) { + } + + if (buffer[0U] == 0x80U) { if (voice != NULL) voice->eof(); } // If we're linked and we have a network, send it on - if (currentId != 9999U) { + if (currentTG > 0U) { // 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; + buffer[1U] = (currentTG >> 16) & 0xFFU; + buffer[2U] = (currentTG >> 8) & 0xFFU; + buffer[3U] = (currentTG >> 0) & 0xFFU; } remoteNetwork.writeData(buffer, len, currentAddr, currentAddrLen); - inactivityTimer.start(); + hangTimer.start(); } } @@ -389,167 +434,49 @@ void CP25Gateway::run() reflectors.clock(ms); - if (remoteSocket != NULL) { - int res = remoteSocket->read(buffer, 200U, addr, addrlen); - if (res > 0) { - buffer[res] = '\0'; - if (::memcmp(buffer + 0U, "TalkGroup", 9U) == 0) { - unsigned int tg = (unsigned int)::atoi((char*)(buffer + 9U)); - - CP25Reflector* reflector = NULL; - if (tg != 9999U) - reflector = reflectors.find(tg); - - if (reflector == NULL && currentId != 9999U) { - LogMessage("Unlinked from reflector %u by remote command", currentId); - - if (voice != NULL) { - voice->unlinked(); - voice->eof(); - } - - remoteNetwork.writeUnlink(currentAddr, currentAddrLen); - remoteNetwork.writeUnlink(currentAddr, currentAddrLen); - remoteNetwork.writeUnlink(currentAddr, currentAddrLen); - - inactivityTimer.stop(); - pollTimer.stop(); - lostTimer.stop(); - - currentId = 9999U; - } else if (reflector != NULL && currentId == 9999U) { - currentId = tg; - currentAddr = reflector->m_addr; - currentAddrLen = reflector->m_addrLen; - - LogMessage("Linked to reflector %u by remote command", currentId); - - if (voice != NULL) { - voice->linkedTo(currentId); - voice->eof(); - } - - remoteNetwork.writePoll(currentAddr, currentAddrLen); - remoteNetwork.writePoll(currentAddr, currentAddrLen); - remoteNetwork.writePoll(currentAddr, currentAddrLen); - - inactivityTimer.start(); - pollTimer.start(); - lostTimer.start(); - } else if (reflector != NULL && currentId != 9999U) { - LogMessage("Unlinked from reflector %u by remote command", currentId); - - remoteNetwork.writeUnlink(currentAddr, currentAddrLen); - remoteNetwork.writeUnlink(currentAddr, currentAddrLen); - remoteNetwork.writeUnlink(currentAddr, currentAddrLen); - - currentId = tg; - currentAddr = reflector->m_addr; - currentAddrLen = reflector->m_addrLen; - - LogMessage("Linked to reflector %u by remote command", currentId); - - if (voice != NULL) { - voice->linkedTo(currentId); - voice->eof(); - } - - remoteNetwork.writePoll(currentAddr, currentAddrLen); - remoteNetwork.writePoll(currentAddr, currentAddrLen); - remoteNetwork.writePoll(currentAddr, currentAddrLen); - - inactivityTimer.start(); - pollTimer.start(); - lostTimer.start(); - } - } else { - CUtils::dump("Invalid remote command received", buffer, res); - } - } - } - if (voice != NULL) voice->clock(ms); - inactivityTimer.clock(ms); - if (inactivityTimer.isRunning() && inactivityTimer.hasExpired()) { - if (currentId != 9999U && startupId == 9999U) { - LogMessage("Unlinking from %u due to inactivity", currentId); + hangTimer.clock(ms); + if (hangTimer.isRunning() && hangTimer.hasExpired()) { + if (currentTG > 0U) { + LogMessage("Unlinking from %u due to inactivity", currentTG); - remoteNetwork.writeUnlink(currentAddr, currentAddrLen); - remoteNetwork.writeUnlink(currentAddr, currentAddrLen); - remoteNetwork.writeUnlink(currentAddr, currentAddrLen); + if (!currentIsStatic) { + remoteNetwork.writeUnlink(currentAddr, currentAddrLen); + remoteNetwork.writeUnlink(currentAddr, currentAddrLen); + remoteNetwork.writeUnlink(currentAddr, currentAddrLen); + } if (voice != NULL) voice->unlinked(); - currentId = 9999U; - pollTimer.stop(); - lostTimer.stop(); - inactivityTimer.stop(); - } else if (currentId != startupId) { - if (currentId != 9999U) { - remoteNetwork.writeUnlink(currentAddr, currentAddrLen); - remoteNetwork.writeUnlink(currentAddr, currentAddrLen); - remoteNetwork.writeUnlink(currentAddr, currentAddrLen); - } + currentTG = 0U; + currentAddrLen = 0U; - CP25Reflector* reflector = reflectors.find(startupId); - if (reflector != NULL) { - currentId = startupId; - currentAddr = reflector->m_addr; - currentAddrLen = reflector->m_addrLen; - - inactivityTimer.start(); - pollTimer.start(); - lostTimer.start(); - - LogMessage("Linked to reflector %u due to inactivity", currentId); - - if (voice != NULL) - voice->linkedTo(currentId); - - remoteNetwork.writePoll(currentAddr, currentAddrLen); - remoteNetwork.writePoll(currentAddr, currentAddrLen); - remoteNetwork.writePoll(currentAddr, currentAddrLen); - } else { - startupId = 9999U; - inactivityTimer.stop(); - pollTimer.stop(); - lostTimer.stop(); - } + hangTimer.stop(); } } pollTimer.clock(ms); if (pollTimer.isRunning() && pollTimer.hasExpired()) { - if (currentId != 9999U) + // Poll the static TGs + for (std::vector::const_iterator it = staticTGs.cbegin(); it != staticTGs.cend(); ++it) + remoteNetwork.writePoll((*it).m_addr, (*it).m_addrLen); + + // Poll the dynamic TG + if (!currentIsStatic && currentAddrLen > 0U) remoteNetwork.writePoll(currentAddr, currentAddrLen); + pollTimer.start(); } - lostTimer.clock(ms); - if (lostTimer.isRunning() && lostTimer.hasExpired()) { - if (currentId != 9999U) { - LogWarning("No response from %u, unlinking", currentId); - currentId = 9999U; - } - - inactivityTimer.stop(); - lostTimer.stop(); - } - if (ms < 5U) CThread::sleep(5U); } delete voice; - if (remoteSocket != NULL) { - remoteSocket->close(); - delete remoteSocket; - } - localNetwork.close(); remoteNetwork.close(); diff --git a/P25Gateway/P25Gateway.ini b/P25Gateway/P25Gateway.ini index 506cbfd..45557f9 100644 --- a/P25Gateway/P25Gateway.ini +++ b/P25Gateway/P25Gateway.ini @@ -3,6 +3,7 @@ Callsign=G4KLX RptAddress=127.0.0.1 RptPort=32010 LocalPort=42020 +Debug=0 Daemon=1 [Id Lookup] @@ -30,10 +31,7 @@ ParrotAddress=127.0.0.1 ParrotPort=42011 P252DMRAddress=127.0.0.1 P252DMRPort=42012 -# Startup=10100 -InactivityTimeout=10 +Static=10100,10200,10300,10400 +RFHangTime=120 +NetHangTime=60 Debug=0 - -[Remote Commands] -Enable=0 -Port=6074 diff --git a/P25Gateway/Version.h b/P25Gateway/Version.h index 3e08686..acc024f 100644 --- a/P25Gateway/Version.h +++ b/P25Gateway/Version.h @@ -19,6 +19,6 @@ #if !defined(VERSION_H) #define VERSION_H -const char* VERSION = "20200920"; +const char* VERSION = "20201026"; #endif