diff --git a/YSFGateway/Conf.cpp b/YSFGateway/Conf.cpp index fa4378e..703f173 100644 --- a/YSFGateway/Conf.cpp +++ b/YSFGateway/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 @@ -35,7 +35,8 @@ enum SECTION { SECTION_NETWORK, SECTION_YSF_NETWORK, SECTION_FCS_NETWORK, - SECTION_MOBILE_GPS + SECTION_MOBILE_GPS, + SECTION_REMOTE_COMMANDS }; CConf::CConf(const std::string& file) : @@ -89,7 +90,9 @@ m_fcsNetworkFile(), m_fcsNetworkPort(0U), m_mobileGPSEnabled(false), m_mobileGPSAddress(), -m_mobileGPSPort(0U) +m_mobileGPSPort(0U), +m_remoteCommandsEnabled(false), +m_remoteCommandsPort(6073U) { } @@ -129,6 +132,8 @@ bool CConf::read() section = SECTION_FCS_NETWORK; else if (::strncmp(buffer, "[Mobile GPS]", 12U) == 0) section = SECTION_MOBILE_GPS; + else if (::strncmp(buffer, "[Remote Commands]", 17U) == 0) + section = SECTION_REMOTE_COMMANDS; else section = SECTION_NONE; @@ -254,6 +259,11 @@ bool CConf::read() m_mobileGPSAddress = value; else if (::strcmp(key, "Port") == 0) m_mobileGPSPort = (unsigned int)::atoi(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); } } @@ -512,3 +522,13 @@ unsigned int CConf::getMobileGPSPort() const { return m_mobileGPSPort; } + +bool CConf::getRemoteCommandsEnabled() const +{ + return m_remoteCommandsEnabled; +} + +unsigned int CConf::getRemoteCommandsPort() const +{ + return m_remoteCommandsPort; +} diff --git a/YSFGateway/Conf.h b/YSFGateway/Conf.h index 3a588ab..467eb06 100644 --- a/YSFGateway/Conf.h +++ b/YSFGateway/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 @@ -95,6 +95,10 @@ public: std::string getMobileGPSAddress() const; unsigned int getMobileGPSPort() const; + // The Remote Commands section + bool getRemoteCommandsEnabled() const; + unsigned int getRemoteCommandsPort() const; + private: std::string m_file; std::string m_callsign; @@ -154,6 +158,9 @@ private: bool m_mobileGPSEnabled; std::string m_mobileGPSAddress; unsigned int m_mobileGPSPort; + + bool m_remoteCommandsEnabled; + unsigned int m_remoteCommandsPort; }; #endif diff --git a/YSFGateway/Version.h b/YSFGateway/Version.h index bbe810c..6981bfa 100644 --- a/YSFGateway/Version.h +++ b/YSFGateway/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 = "20190131"; +const char* VERSION = "20200405"; #endif diff --git a/YSFGateway/YSFGateway.cpp b/YSFGateway/YSFGateway.cpp index 47d5717..bb27e55 100644 --- a/YSFGateway/YSFGateway.cpp +++ b/YSFGateway/YSFGateway.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 @@ -23,6 +23,7 @@ #include "YSFFICH.h" #include "Thread.h" #include "Timer.h" +#include "Utils.h" #include "Log.h" #if defined(_WIN32) || defined(_WIN64) @@ -91,7 +92,8 @@ m_startup(), m_exclude(false), m_inactivityTimer(1000U), m_lostTimer(1000U, 120U), -m_fcsNetworkEnabled(false) +m_fcsNetworkEnabled(false), +m_remoteSocket(NULL) { } @@ -242,6 +244,15 @@ int CYSFGateway::run() createGPS(); + if (m_conf.getRemoteCommandsEnabled()) { + m_remoteSocket = new CUDPSocket(m_conf.getRemoteCommandsPort()); + ret = m_remoteSocket->open(); + if (!ret) { + delete m_remoteSocket; + m_remoteSocket = NULL; + } + } + m_startup = m_conf.getNetworkStartup(); bool revert = m_conf.getNetworkRevert(); bool wiresXCommandPassthrough = m_conf.getWiresXCommandPassthrough(); @@ -327,6 +338,9 @@ int CYSFGateway::run() } } + if (m_remoteSocket != NULL) + processRemoteCommands(); + unsigned int ms = stopWatch.elapsed(); stopWatch.start(); @@ -423,6 +437,11 @@ int CYSFGateway::run() delete m_fcsNetwork; } + if (m_remoteSocket != NULL) { + m_remoteSocket->close(); + delete m_remoteSocket; + } + delete m_wiresX; ::LogFinalise(); @@ -839,3 +858,106 @@ void CYSFGateway::readFCSRoomsFile(const std::string& filename) LogInfo("Loaded %u FCS room descriptions", count); } + +void CYSFGateway::processRemoteCommands() +{ + unsigned char buffer[200U]; + in_addr address; + unsigned int port; + + int res = m_remoteSocket->read(buffer, 200U, address, port); + if (res > 0) { + buffer[res] = '\0'; + if (::memcmp(buffer + 0U, "LinkYSF", 7U) == 0) { + std::string id = std::string((char*)(buffer + 7U)); + CYSFReflector* reflector = m_reflectors->findById(id); + if (reflector == NULL) + reflector = m_reflectors->findByName(id); + if (reflector != NULL) { + m_wiresX->processConnect(reflector); + + if (m_linkType == LINK_YSF) + m_ysfNetwork->writeUnlink(3U); + + if (m_linkType == LINK_FCS) { + m_fcsNetwork->writeUnlink(3U); + m_fcsNetwork->clearDestination(); + } + + LogMessage("Connect by remote command to %5.5s - \"%s\"", reflector->m_id.c_str(), reflector->m_name.c_str()); + + m_ysfNetwork->setDestination(reflector->m_name, reflector->m_address, reflector->m_port); + m_ysfNetwork->writePoll(3U); + + m_current = id; + m_inactivityTimer.start(); + m_lostTimer.start(); + m_linkType = LINK_YSF; + } else { + LogWarning("Invalid YSF reflector id/name - \"%s\"", id.c_str()); + return; + } + } else if (::memcmp(buffer + 0U, "LinkFCS", 7U) == 0) { + std::string raw = std::string((char*)(buffer + 7U)); + std::string id = "FCS00"; + if (raw.length() == 3U) { + id += raw; + } else { + LogWarning("Invalid FCS reflector id - \"%s\"", raw.c_str()); + return; + } + + if (m_linkType == LINK_YSF) { + m_wiresX->processDisconnect(); + m_ysfNetwork->writeUnlink(3U); + m_ysfNetwork->clearDestination(); + } + if (m_linkType == LINK_FCS) + m_fcsNetwork->writeUnlink(3U); + + m_current.clear(); + m_inactivityTimer.stop(); + m_lostTimer.stop(); + m_linkType = LINK_NONE; + + LogMessage("Connect by remote command to %s", id.c_str()); + + bool ok = m_fcsNetwork->writeLink(id); + if (ok) { + m_current = id; + m_inactivityTimer.start(); + m_lostTimer.start(); + m_linkType = LINK_FCS; + } else { + LogMessage("Unknown reflector - %s", id.c_str()); + } + } else if (::memcmp(buffer + 0U, "UnLink", 6U) == 0) { + if (m_linkType == LINK_YSF) { + m_wiresX->processDisconnect(); + + LogMessage("Disconnect by remote command"); + + m_ysfNetwork->writeUnlink(3U); + m_ysfNetwork->clearDestination(); + + m_current.clear(); + m_inactivityTimer.stop(); + m_lostTimer.stop(); + m_linkType = LINK_NONE; + } + if (m_linkType == LINK_FCS) { + LogMessage("Disconnect by remote command"); + + m_fcsNetwork->writeUnlink(3U); + m_fcsNetwork->clearDestination(); + + m_current.clear(); + m_inactivityTimer.stop(); + m_lostTimer.stop(); + m_linkType = LINK_NONE; + } + } else { + CUtils::dump("Invalid remote command received", buffer, res); + } + } +} diff --git a/YSFGateway/YSFGateway.h b/YSFGateway/YSFGateway.h index aad13b9..dc7e0f2 100644 --- a/YSFGateway/YSFGateway.h +++ b/YSFGateway/YSFGateway.h @@ -1,5 +1,5 @@ /* -* Copyright (C) 2016,2017,2018 by Jonathan Naylor G4KLX +* Copyright (C) 2016,2017,2018,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 @@ -63,6 +63,7 @@ private: CTimer m_inactivityTimer; CTimer m_lostTimer; bool m_fcsNetworkEnabled; + CUDPSocket* m_remoteSocket; void startupLinking(); std::string calculateLocator(); @@ -71,6 +72,7 @@ private: void createWiresX(CYSFNetwork* rptNetwork); void createGPS(); void readFCSRoomsFile(const std::string& filename); + void processRemoteCommands(); }; #endif diff --git a/YSFGateway/YSFGateway.ini b/YSFGateway/YSFGateway.ini index 5352edd..2415445 100644 --- a/YSFGateway/YSFGateway.ini +++ b/YSFGateway/YSFGateway.ini @@ -67,3 +67,7 @@ Port=42001 Enable=0 Address=127.0.0.1 Port=7834 + +[Remote Commands] +Enable=0 +Port=6073