diff --git a/P25Gateway/Conf.cpp b/P25Gateway/Conf.cpp index a565356..8620a68 100644 --- a/P25Gateway/Conf.cpp +++ b/P25Gateway/Conf.cpp @@ -32,7 +32,8 @@ enum SECTION { SECTION_ID_LOOKUP, SECTION_VOICE, SECTION_LOG, - SECTION_NETWORK + SECTION_NETWORK, + SECTION_REMOTE_COMMANDS }; CConf::CConf(const std::string& file) : @@ -61,7 +62,9 @@ m_networkParrotPort(0U), m_networkStatic(), m_networkRFHangTime(120U), m_networkNetHangTime(60U), -m_networkDebug(false) +m_networkDebug(false), +m_remoteCommandsEnabled(false), +m_remoteCommandsPort(6074U) { } @@ -95,6 +98,8 @@ 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; @@ -193,6 +198,11 @@ bool CConf::read() 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); } } @@ -335,3 +345,13 @@ 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 0b731d4..f7e573e 100644 --- a/P25Gateway/Conf.h +++ b/P25Gateway/Conf.h @@ -67,6 +67,10 @@ public: 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; @@ -100,6 +104,9 @@ private: 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 073568b..3feec94 100644 --- a/P25Gateway/P25Gateway.cpp +++ b/P25Gateway/P25Gateway.cpp @@ -203,6 +203,16 @@ 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; + } + } + CReflectors reflectors(m_conf.getNetworkHosts1(), m_conf.getNetworkHosts2(), m_conf.getNetworkReloadTime()); if (m_conf.getNetworkParrotPort() > 0U) reflectors.setParrot(m_conf.getNetworkParrotAddress(), m_conf.getNetworkParrotPort()); @@ -391,6 +401,8 @@ void CP25Gateway::run() hangTimer.setTimeout(rfHangTime); hangTimer.start(); + } else { + hangTimer.stop(); } if (voice != NULL) { @@ -429,6 +441,84 @@ void CP25Gateway::run() localNetwork.writeData(buffer, length, rptAddr, rptAddrLen); } + if (remoteSocket != NULL) { + sockaddr_storage addr; + unsigned int addrLen; + 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)); + + if (tg != currentTG) { + if (currentAddrLen > 0U) { + LogMessage("Unlinked from reflector %u by remote command", currentTG); + + if (!currentIsStatic) { + remoteNetwork.writeUnlink(currentAddr, currentAddrLen); + remoteNetwork.writeUnlink(currentAddr, currentAddrLen); + remoteNetwork.writeUnlink(currentAddr, currentAddrLen); + } + + hangTimer.stop(); + } + + const CStaticTG* found = NULL; + for (std::vector::const_iterator it = staticTGs.cbegin(); it != staticTGs.cend(); ++it) { + if (tg == (*it).m_tg) { + found = &(*it); + break; + } + } + + if (found == NULL) { + CP25Reflector* refl = reflectors.find(tg); + if (refl != NULL) { + currentTG = tg; + currentAddr = refl->m_addr; + currentAddrLen = refl->m_addrLen; + currentIsStatic = false; + } else { + currentTG = tg; + currentAddrLen = 0U; + currentIsStatic = false; + } + } else { + currentTG = found->m_tg; + currentAddr = found->m_addr; + currentAddrLen = found->m_addrLen; + currentIsStatic = true; + } + + // Link to the new reflector + if (currentAddrLen > 0U) { + LogMessage("Switched to reflector %u by remote command", currentTG); + + if (!currentIsStatic) { + remoteNetwork.writePoll(currentAddr, currentAddrLen); + remoteNetwork.writePoll(currentAddr, currentAddrLen); + remoteNetwork.writePoll(currentAddr, currentAddrLen); + } + + hangTimer.setTimeout(rfHangTime); + hangTimer.start(); + } else { + hangTimer.stop(); + } + + if (voice != NULL) { + if (currentAddrLen == 0U) + voice->unlinked(); + else + voice->linkedTo(currentTG); + } + } + } else { + CUtils::dump("Invalid remote command received", buffer, res); + } + } + } + unsigned int ms = stopWatch.elapsed(); stopWatch.start(); @@ -480,6 +570,11 @@ void CP25Gateway::run() localNetwork.close(); + if (remoteSocket != NULL) { + remoteSocket->close(); + delete remoteSocket; + } + remoteNetwork.close(); lookup->stop(); diff --git a/P25Gateway/P25Gateway.ini b/P25Gateway/P25Gateway.ini index 45557f9..ff465ca 100644 --- a/P25Gateway/P25Gateway.ini +++ b/P25Gateway/P25Gateway.ini @@ -35,3 +35,7 @@ Static=10100,10200,10300,10400 RFHangTime=120 NetHangTime=60 Debug=0 + +[Remote Commands] +Enable=0 +Port=6074