diff --git a/NXDNGateway/Conf.cpp b/NXDNGateway/Conf.cpp index 5eec9ae..63117d9 100644 --- a/NXDNGateway/Conf.cpp +++ b/NXDNGateway/Conf.cpp @@ -35,8 +35,7 @@ enum SECTION { SECTION_LOG, SECTION_APRS, SECTION_NETWORK, - SECTION_GPSD, - SECTION_REMOTE_COMMANDS + SECTION_GPSD }; CConf::CConf(const std::string& file) : @@ -79,14 +78,13 @@ m_networkParrotAddress("127.0.0.1"), m_networkParrotPort(0U), m_networkNXDN2DMRAddress("127.0.0.1"), m_networkNXDN2DMRPort(0U), -m_networkStartup(9999U), -m_networkInactivityTimeout(0U), +m_networkStatic(), +m_networkRFHangTime(120U), +m_networkNetHangTime(60U), m_networkDebug(false), m_gpsdEnabled(false), m_gpsdAddress(), -m_gpsdPort(), -m_remoteCommandsEnabled(false), -m_remoteCommandsPort(6075U) +m_gpsdPort() { } @@ -126,8 +124,6 @@ bool CConf::read() section = SECTION_NETWORK; else if (::strncmp(buffer, "[GPSD]", 6U) == 0) section = SECTION_GPSD; - else if (::strncmp(buffer, "[Remote Commands]", 17U) == 0) - section = SECTION_REMOTE_COMMANDS; else section = SECTION_NONE; @@ -248,10 +244,17 @@ bool CConf::read() m_networkNXDN2DMRAddress = value; else if (::strcmp(key, "NXDN2DMRPort") == 0) m_networkNXDN2DMRPort = (unsigned int)::atoi(value); - else if (::strcmp(key, "Startup") == 0) - m_networkStartup = (unsigned short)::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 short tg = (unsigned short)::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_GPSD) { @@ -261,11 +264,6 @@ bool CConf::read() m_gpsdAddress = value; else if (::strcmp(key, "Port") == 0) m_gpsdPort = value; - } 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); } } @@ -464,14 +462,19 @@ unsigned int CConf::getNetworkNXDN2DMRPort() const return m_networkNXDN2DMRPort; } -unsigned short 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 @@ -493,13 +496,3 @@ std::string CConf::getGPSDPort() const { return m_gpsdPort; } - -bool CConf::getRemoteCommandsEnabled() const -{ - return m_remoteCommandsEnabled; -} - -unsigned int CConf::getRemoteCommandsPort() const -{ - return m_remoteCommandsPort; -} diff --git a/NXDNGateway/Conf.h b/NXDNGateway/Conf.h index 6d8ebd3..1d97c79 100644 --- a/NXDNGateway/Conf.h +++ b/NXDNGateway/Conf.h @@ -81,8 +81,9 @@ public: unsigned int getNetworkParrotPort() const; std::string getNetworkNXDN2DMRAddress() const; unsigned int getNetworkNXDN2DMRPort() const; - unsigned short getNetworkStartup() const; - unsigned int getNetworkInactivityTimeout() const; + std::vector getNetworkStatic() const; + unsigned int getNetworkRFHangTime() const; + unsigned int getNetworkNetHangTime() const; bool getNetworkDebug() const; // The GPSD section @@ -90,10 +91,6 @@ public: std::string getGPSDAddress() const; std::string getGPSDPort() const; - // The Remote Commands section - bool getRemoteCommandsEnabled() const; - unsigned int getRemoteCommandsPort() const; - private: std::string m_file; std::string m_callsign; @@ -140,16 +137,14 @@ private: unsigned int m_networkParrotPort; std::string m_networkNXDN2DMRAddress; unsigned int m_networkNXDN2DMRPort; - unsigned short m_networkStartup; - unsigned int m_networkInactivityTimeout; + std::vector m_networkStatic; + unsigned int m_networkRFHangTime; + unsigned int m_networkNetHangTime; bool m_networkDebug; bool m_gpsdEnabled; std::string m_gpsdAddress; std::string m_gpsdPort; - - bool m_remoteCommandsEnabled; - unsigned int m_remoteCommandsPort; }; #endif diff --git a/NXDNGateway/NXDNGateway.cpp b/NXDNGateway/NXDNGateway.cpp index e2df0b0..e1c47ac 100644 --- a/NXDNGateway/NXDNGateway.cpp +++ b/NXDNGateway/NXDNGateway.cpp @@ -64,6 +64,13 @@ const unsigned char NXDN_TYPE_TX_REL = 0x08U; const unsigned short NXDN_VOICE_ID = 9999U; +class CStaticTG { +public: + unsigned short m_tg; + sockaddr_storage m_addr; + unsigned int m_addrLen; +}; + int main(int argc, char** argv) { const char* iniFile = DEFAULT_INI_FILE; @@ -209,16 +216,6 @@ void CNXDNGateway::run() return; } - CUDPSocket* remoteSocket = NULL; - if (m_conf.getRemoteCommandsEnabled()) { - remoteSocket = new CUDPSocket(m_conf.getRemoteCommandsPort()); - ret = remoteSocket->open(); - if (!ret) { - delete remoteSocket; - remoteSocket = NULL; - } - } - CReflectors reflectors(m_conf.getNetworkHosts1(), m_conf.getNetworkHosts2(), m_conf.getNetworkReloadTime()); if (m_conf.getNetworkParrotPort() > 0U) reflectors.setParrot(m_conf.getNetworkParrotAddress(), m_conf.getNetworkParrotPort()); @@ -229,9 +226,13 @@ void CNXDNGateway::run() CNXDNLookup* lookup = new CNXDNLookup(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(); @@ -249,32 +250,31 @@ void CNXDNGateway::run() LogMessage("Starting NXDNGateway-%s", VERSION); unsigned short srcId = 0U; - unsigned short dstId = 0U; + unsigned short dstTG = 0U; bool grp = false; - unsigned short currentId = 9999U; - sockaddr_storage currentAddr; + bool currentIsStatic = false; + unsigned short currentTG = 0U; unsigned int currentAddrLen = 0U; + sockaddr_storage currentAddr; - unsigned short startupId = m_conf.getNetworkStartup(); - if (startupId != 9999U) { - CNXDNReflector* 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) { + CNXDNReflector* 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, staticTG.m_tg); + remoteNetwork.writePoll(staticTG.m_addr, staticTG.m_addrLen, staticTG.m_tg); + remoteNetwork.writePoll(staticTG.m_addr, staticTG.m_addrLen, staticTG.m_tg); - remoteNetwork.writePoll(currentAddr, currentAddrLen, currentId); - remoteNetwork.writePoll(currentAddr, currentAddrLen, currentId); - remoteNetwork.writePoll(currentAddr, currentAddrLen, currentId); - - LogMessage("Linked at startup to reflector %u", currentId); - } else { - startupId = 9999U; + LogMessage("Statically linked to reflector %u", *it); } } @@ -287,21 +287,51 @@ void CNXDNGateway::run() 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 (::memcmp(buffer, "NXDND", 5U) == 0) { - unsigned short dstId = 0U; - dstId |= (buffer[7U] << 8) & 0xFF00U; - dstId |= (buffer[8U] << 0) & 0x00FFU; + unsigned short dstTG = 0U; + dstTG |= (buffer[7U] << 8) & 0xFF00U; + dstTG |= (buffer[8U] << 0) & 0x00FFU; bool grp = (buffer[9U] & 0x01U) == 0x01U; - if (grp && currentId == dstId) + if (grp && currentTG == dstTG) localNetwork->write(buffer + 10U, len - 10U); - } - // 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 (::memcmp(buffer, "NXDND", 5U) == 0) { + // 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; + + unsigned short dstTG = 0U; + dstTG |= (buffer[7U] << 8) & 0xFF00U; + dstTG |= (buffer[8U] << 0) & 0x00FFU; + + bool grp = (buffer[9U] & 0x01U) == 0x01U; + + if (grp && currentTG == dstTG) + localNetwork->write(buffer + 10U, len - 10U); + + LogMessage("Switched to reflector %u due to network activity", currentTG); + + hangTimer.setTimeout(netHangTime); + hangTimer.start(); + } + } } } @@ -312,57 +342,72 @@ void CNXDNGateway::run() if ((buffer[0U] == 0x81U || buffer[0U] == 0x83U) && (buffer[5U] == 0x01U || buffer[5U] == 0x08U)) { grp = (buffer[7U] & 0x20U) == 0x20U; - srcId = (buffer[8U] << 8) & 0xFF00U; + srcId = (buffer[8U] << 8) & 0xFF00U; srcId |= (buffer[9U] << 0) & 0x00FFU; - dstId = (buffer[10U] << 8) & 0xFF00U; - dstId |= (buffer[11U] << 0) & 0x00FFU; + dstTG = (buffer[10U] << 8) & 0xFF00U; + dstTG |= (buffer[11U] << 0) & 0x00FFU; - if (dstId != currentId) { - CNXDNReflector* reflector = NULL; - if (dstId != 9999U) - reflector = reflectors.find(dstId); + if (dstTG != currentTG) { + if (currentTG > 0U) { + std::string callsign = lookup->find(srcId); + LogMessage("Unlinking from reflector %u by %s", currentTG, callsign.c_str()); - // If we're unlinking or changing reflectors, unlink from the current one - if (dstId == 9999U || reflector != NULL) { - if (currentId != 9999U) { - std::string callsign = lookup->find(srcId); - LogMessage("Unlinked from reflector %u by %s", currentId, callsign.c_str()); - - if (voice != NULL && dstId == 9999U) - voice->unlinked(); - - remoteNetwork.writeUnlink(currentAddr, currentAddrLen, currentId); - remoteNetwork.writeUnlink(currentAddr, currentAddrLen, currentId); - remoteNetwork.writeUnlink(currentAddr, currentAddrLen, currentId); - - inactivityTimer.stop(); - pollTimer.stop(); - lostTimer.stop(); + if (!currentIsStatic) { + remoteNetwork.writeUnlink(currentAddr, currentAddrLen, currentTG); + remoteNetwork.writeUnlink(currentAddr, currentAddrLen, currentTG); + remoteNetwork.writeUnlink(currentAddr, currentAddrLen, currentTG); } - currentId = dstId; + hangTimer.stop(); + } + + 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) { + CNXDNReflector* 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()); - if (voice != NULL) - voice->linkedTo(currentId); + if (!currentIsStatic) { + remoteNetwork.writePoll(currentAddr, currentAddrLen, currentTG); + remoteNetwork.writePoll(currentAddr, currentAddrLen, currentTG); + remoteNetwork.writePoll(currentAddr, currentAddrLen, currentTG); + } - remoteNetwork.writePoll(currentAddr, currentAddrLen, currentId); - remoteNetwork.writePoll(currentAddr, currentAddrLen, currentId); - remoteNetwork.writePoll(currentAddr, currentAddrLen, currentId); + hangTimer.setTimeout(rfHangTime); + hangTimer.start(); + } - inactivityTimer.start(); - pollTimer.start(); - lostTimer.start(); + if (voice != NULL) { + if (currentTG == 0U) + voice->unlinked(); + else + voice->linkedTo(currentTG); } } @@ -397,9 +442,9 @@ void CNXDNGateway::run() } // If we're linked and we have a network, send it on - if (currentId != 9999U) { - remoteNetwork.writeData(buffer, len, srcId, dstId, grp, currentAddr, currentAddrLen); - inactivityTimer.start(); + if (currentTG > 0U) { + remoteNetwork.writeData(buffer, len, srcId, dstTG, grp, currentAddr, currentAddrLen); + hangTimer.start(); } } @@ -409,85 +454,6 @@ void CNXDNGateway::run() localNetwork->write(buffer, length); } - 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)); - - CNXDNReflector* 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, currentId); - remoteNetwork.writeUnlink(currentAddr, currentAddrLen, currentId); - remoteNetwork.writeUnlink(currentAddr, currentAddrLen, currentId); - - 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, currentId); - remoteNetwork.writePoll(currentAddr, currentAddrLen, currentId); - remoteNetwork.writePoll(currentAddr, currentAddrLen, currentId); - - 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, currentId); - remoteNetwork.writeUnlink(currentAddr, currentAddrLen, currentId); - remoteNetwork.writeUnlink(currentAddr, currentAddrLen, currentId); - - 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, currentId); - remoteNetwork.writePoll(currentAddr, currentAddrLen, currentId); - remoteNetwork.writePoll(currentAddr, currentAddrLen, currentId); - - inactivityTimer.start(); - pollTimer.start(); - lostTimer.start(); - } - } else { - CUtils::dump("Invalid remote command received", buffer, res); - } - } - } - unsigned int ms = stopWatch.elapsed(); stopWatch.start(); @@ -498,74 +464,40 @@ void CNXDNGateway::run() 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, currentId); - remoteNetwork.writeUnlink(currentAddr, currentAddrLen, currentId); - remoteNetwork.writeUnlink(currentAddr, currentAddrLen, currentId); + if (!currentIsStatic) { + remoteNetwork.writeUnlink(currentAddr, currentAddrLen, currentTG); + remoteNetwork.writeUnlink(currentAddr, currentAddrLen, currentTG); + remoteNetwork.writeUnlink(currentAddr, currentAddrLen, currentTG); + } if (voice != NULL) voice->unlinked(); - currentId = 9999U; - inactivityTimer.stop(); - pollTimer.stop(); - lostTimer.stop(); - } else if (currentId != startupId) { - if (currentId != 9999U) { - remoteNetwork.writeUnlink(currentAddr, currentAddrLen, currentId); - remoteNetwork.writeUnlink(currentAddr, currentAddrLen, currentId); - remoteNetwork.writeUnlink(currentAddr, currentAddrLen, currentId); - } + currentTG = 0U; + currentAddrLen = 0U; - CNXDNReflector* reflector = reflectors.find(startupId); - if (reflector != NULL) { - currentId = startupId; - currentAddr = reflector->m_addr; - currentAddrLen = reflector->m_addrLen; - - inactivityTimer.start(); - pollTimer.start(); - lostTimer.start(); - - LogMessage("Relinked to reflector %u due to inactivity", currentId); - - if (voice != NULL) - voice->linkedTo(currentId); - - remoteNetwork.writePoll(currentAddr, currentAddrLen, currentId); - remoteNetwork.writePoll(currentAddr, currentAddrLen, currentId); - remoteNetwork.writePoll(currentAddr, currentAddrLen, currentId); - } else { - startupId = 9999U; - inactivityTimer.stop(); - pollTimer.stop(); - lostTimer.stop(); - } + hangTimer.stop(); } } pollTimer.clock(ms); if (pollTimer.isRunning() && pollTimer.hasExpired()) { - if (currentId != 9999U) - remoteNetwork.writePoll(currentAddr, currentAddrLen, currentId); + // Poll the static TGs + for (std::vector::const_iterator it = staticTGs.cbegin(); it != staticTGs.cend(); ++it) + remoteNetwork.writePoll((*it).m_addr, (*it).m_addrLen, (*it).m_tg); + + // Poll the dynamic TG + if (!currentIsStatic && currentAddrLen > 0U) + remoteNetwork.writePoll(currentAddr, currentAddrLen, currentTG); + 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 (m_writer != NULL) m_writer->clock(ms); @@ -578,11 +510,6 @@ void CNXDNGateway::run() localNetwork->close(); delete localNetwork; - if (remoteSocket != NULL) { - remoteSocket->close(); - delete remoteSocket; - } - remoteNetwork.close(); lookup->stop(); diff --git a/NXDNGateway/NXDNGateway.ini b/NXDNGateway/NXDNGateway.ini index 19ce4b4..2fb36ac 100644 --- a/NXDNGateway/NXDNGateway.ini +++ b/NXDNGateway/NXDNGateway.ini @@ -61,15 +61,12 @@ ParrotAddress=127.0.0.1 ParrotPort=42021 NXDN2DMRAddress=127.0.0.1 NXDN2DMRPort=42022 -Startup=10200 -InactivityTimeout=10 +Static=10200,65000 +RFHangTime=120 +NetHangTime=60 Debug=0 [GPSD] Enable=0 Address=127.0.0.1 Port=2947 - -[Remote Commands] -Enable=0 -Port=6075 diff --git a/NXDNGateway/Version.h b/NXDNGateway/Version.h index 5e2b52b..481c715 100644 --- a/NXDNGateway/Version.h +++ b/NXDNGateway/Version.h @@ -19,6 +19,6 @@ #if !defined(VERSION_H) #define VERSION_H -const char* VERSION = "20200920"; +const char* VERSION = "20201026"; #endif