From 76d068019ba155c5916819e9c0a8c68306130508 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Fri, 3 Apr 2020 21:28:45 +0100 Subject: [PATCH] Add remote commands. --- P25Gateway/Conf.cpp | 26 +++++++++-- P25Gateway/Conf.h | 9 +++- P25Gateway/P25Gateway.cpp | 94 ++++++++++++++++++++++++++++++++++++++- P25Gateway/P25Gateway.ini | 4 ++ P25Gateway/Version.h | 4 +- 5 files changed, 130 insertions(+), 7 deletions(-) diff --git a/P25Gateway/Conf.cpp b/P25Gateway/Conf.cpp index 43ef1d4..5b430bf 100644 --- a/P25Gateway/Conf.cpp +++ b/P25Gateway/Conf.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2019 by Jonathan Naylor G4KLX + * Copyright (C) 2015-2020 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 @@ -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) : @@ -57,7 +58,9 @@ m_networkParrotAddress("127.0.0.1"), m_networkParrotPort(0U), m_networkStartup(9999U), m_networkInactivityTimeout(0U), -m_networkDebug(false) +m_networkDebug(false), +m_remoteCommandsEnabled(false), +m_remoteCommandsPort(6074U) { } @@ -91,6 +94,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; @@ -152,6 +157,11 @@ bool CConf::read() m_networkInactivityTimeout = (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); } } @@ -264,3 +274,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 a274afd..798e04b 100644 --- a/P25Gateway/Conf.h +++ b/P25Gateway/Conf.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2019 by Jonathan Naylor G4KLX + * Copyright (C) 2015-2020 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 @@ -61,6 +61,10 @@ public: unsigned int getNetworkInactivityTimeout() const; bool getNetworkDebug() const; + // The Remote Commands section + bool getRemoteCommandsEnabled() const; + unsigned int getRemoteCommandsPort() const; + private: std::string m_file; std::string m_callsign; @@ -88,6 +92,9 @@ private: unsigned int m_networkStartup; unsigned int m_networkInactivityTimeout; bool m_networkDebug; + + bool m_remoteCommandsEnabled; + unsigned int m_remoteCommandsPort; }; #endif diff --git a/P25Gateway/P25Gateway.cpp b/P25Gateway/P25Gateway.cpp index b9e9c16..8c8b8fe 100644 --- a/P25Gateway/P25Gateway.cpp +++ b/P25Gateway/P25Gateway.cpp @@ -1,5 +1,5 @@ /* -* Copyright (C) 2016-2019 by Jonathan Naylor G4KLX +* Copyright (C) 2016-2020 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 @@ -25,6 +25,7 @@ #include "Thread.h" #include "Voice.h" #include "Timer.h" +#include "Utils.h" #include "Log.h" #if defined(_WIN32) || defined(_WIN64) @@ -169,6 +170,16 @@ void CP25Gateway::run() in_addr rptAddr = CUDPSocket::lookup(m_conf.getRptAddress()); unsigned int rptPort = m_conf.getRptPort(); + 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); ret = localNetwork.open(); if (!ret) { @@ -360,6 +371,82 @@ void CP25Gateway::run() reflectors.clock(ms); + if (remoteSocket != NULL) { + int res = remoteSocket->read(buffer, 200U, address, port); + 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(); + + remoteNetwork.writeUnlink(currentAddr, currentPort); + remoteNetwork.writeUnlink(currentAddr, currentPort); + remoteNetwork.writeUnlink(currentAddr, currentPort); + + inactivityTimer.stop(); + pollTimer.stop(); + lostTimer.stop(); + + currentId = 9999U; + } + else if (reflector != NULL && currentId == 9999U) { + currentId = tg; + currentAddr = reflector->m_address; + currentPort = reflector->m_port; + + LogMessage("Linked to reflector %u by remote command", currentId); + + if (voice != NULL) + voice->linkedTo(currentId); + + remoteNetwork.writePoll(currentAddr, currentPort); + remoteNetwork.writePoll(currentAddr, currentPort); + remoteNetwork.writePoll(currentAddr, currentPort); + + inactivityTimer.start(); + pollTimer.start(); + lostTimer.start(); + } + else if (reflector != NULL && currentId != 9999U) { + LogMessage("Unlinked from reflector %u by remote command", currentId); + + remoteNetwork.writeUnlink(currentAddr, currentPort); + remoteNetwork.writeUnlink(currentAddr, currentPort); + remoteNetwork.writeUnlink(currentAddr, currentPort); + + currentId = tg; + currentAddr = reflector->m_address; + currentPort = reflector->m_port; + + LogMessage("Linked to reflector %u by remote command", currentId); + + if (voice != NULL) + voice->linkedTo(currentId); + + remoteNetwork.writePoll(currentAddr, currentPort); + remoteNetwork.writePoll(currentAddr, currentPort); + remoteNetwork.writePoll(currentAddr, currentPort); + + inactivityTimer.start(); + pollTimer.start(); + lostTimer.start(); + } + } + else { + CUtils::dump("Invalid remote command received", buffer, res); + } + } + } + if (voice != NULL) voice->clock(ms); @@ -437,6 +524,11 @@ void CP25Gateway::run() delete voice; + if (remoteSocket != NULL) { + remoteSocket->close(); + delete remoteSocket; + } + localNetwork.close(); remoteNetwork.close(); diff --git a/P25Gateway/P25Gateway.ini b/P25Gateway/P25Gateway.ini index 459abc3..501718f 100644 --- a/P25Gateway/P25Gateway.ini +++ b/P25Gateway/P25Gateway.ini @@ -28,3 +28,7 @@ ParrotPort=42011 # Startup=10100 InactivityTimeout=10 Debug=0 + +[Remote Commands] +Enable=0 +Port=6074 diff --git a/P25Gateway/Version.h b/P25Gateway/Version.h index ed379f1..54b6d54 100644 --- a/P25Gateway/Version.h +++ b/P25Gateway/Version.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2019 by Jonathan Naylor G4KLX + * Copyright (C) 2015-2020 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,6 +19,6 @@ #if !defined(VERSION_H) #define VERSION_H -const char* VERSION = "20190304"; +const char* VERSION = "20200403"; #endif