diff --git a/P25Gateway/Conf.cpp b/P25Gateway/Conf.cpp index 063ce13..2828979 100644 --- a/P25Gateway/Conf.cpp +++ b/P25Gateway/Conf.cpp @@ -41,6 +41,7 @@ m_file(file), m_callsign(), m_rptAddress(), m_rptPort(0U), +m_myAddress(), m_myPort(0U), m_debug(false), m_daemon(false), @@ -142,6 +143,8 @@ bool CConf::read() m_rptAddress = value; else if (::strcmp(key, "RptPort") == 0) m_rptPort = (unsigned int)::atoi(value); + else if (::strcmp(key, "LocalAddress") == 0) + m_myAddress = value; else if (::strcmp(key, "LocalPort") == 0) m_myPort = (unsigned int)::atoi(value); else if (::strcmp(key, "Debug") == 0) @@ -229,6 +232,11 @@ unsigned int CConf::getRptPort() const return m_rptPort; } +std::string CConf::getMyAddress() const +{ + return m_myAddress; +} + unsigned int CConf::getMyPort() const { return m_myPort; diff --git a/P25Gateway/Conf.h b/P25Gateway/Conf.h index 23c2624..5e0d444 100644 --- a/P25Gateway/Conf.h +++ b/P25Gateway/Conf.h @@ -34,6 +34,7 @@ public: std::string getCallsign() const; std::string getRptAddress() const; unsigned int getRptPort() const; + std::string getMyAddress() const; unsigned int getMyPort() const; bool getDebug() const; bool getDaemon() const; @@ -77,6 +78,7 @@ private: std::string m_callsign; std::string m_rptAddress; unsigned int m_rptPort; + std::string m_myAddress; unsigned int m_myPort; bool m_debug; bool m_daemon; diff --git a/P25Gateway/Makefile b/P25Gateway/Makefile index da34eed..f774001 100644 --- a/P25Gateway/Makefile +++ b/P25Gateway/Makefile @@ -1,10 +1,10 @@ CC = cc CXX = c++ -CFLAGS = -g -O3 -Wall -DHAVE_LOG_H -std=c++0x -pthread +CFLAGS = -g -O3 -Wall -DHAVE_LOG_H -DUDP_SOCKET_MAX=2 -std=c++0x -pthread LIBS = -lpthread LDFLAGS = -g -OBJECTS = Conf.o DMRLookup.o Log.o Mutex.o Network.o P25Gateway.o Reflectors.o StopWatch.o Thread.o Timer.o UDPSocket.o Utils.o Voice.o +OBJECTS = Conf.o DMRLookup.o Log.o Mutex.o P25Gateway.o P25Network.o Reflectors.o RptNetwork.o StopWatch.o Thread.o Timer.o UDPSocket.o Utils.o Voice.o all: P25Gateway diff --git a/P25Gateway/P25Gateway.cpp b/P25Gateway/P25Gateway.cpp index 3fcf655..41f5707 100644 --- a/P25Gateway/P25Gateway.cpp +++ b/P25Gateway/P25Gateway.cpp @@ -17,10 +17,11 @@ */ #include "P25Gateway.h" +#include "RptNetwork.h" +#include "P25Network.h" #include "Reflectors.h" #include "StopWatch.h" #include "DMRLookup.h" -#include "Network.h" #include "Version.h" #include "Thread.h" #include "Voice.h" @@ -188,14 +189,14 @@ void CP25Gateway::run() return; } - CNetwork localNetwork(m_conf.getMyPort(), m_conf.getCallsign(), m_conf.getDebug()); + CRptNetwork localNetwork(m_conf.getMyAddress(), m_conf.getMyPort(), rptAddr, rptAddrLen, m_conf.getCallsign(), m_conf.getDebug()); ret = localNetwork.open(); if (!ret) { ::LogFinalise(); return; } - CNetwork remoteNetwork(m_conf.getNetworkPort(), m_conf.getCallsign(), m_conf.getNetworkDebug()); + CP25Network remoteNetwork(m_conf.getNetworkPort(), m_conf.getCallsign(), m_conf.getNetworkDebug()); ret = remoteNetwork.open(); if (!ret) { localNetwork.close(); @@ -266,9 +267,9 @@ void CP25Gateway::run() staticTG.m_addrLen = reflector->m_addrLen; staticTGs.push_back(staticTG); - 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.poll(staticTG.m_addr, staticTG.m_addrLen); + remoteNetwork.poll(staticTG.m_addr, staticTG.m_addrLen); + remoteNetwork.poll(staticTG.m_addr, staticTG.m_addrLen); LogMessage("Statically linked to reflector %u", *it); } @@ -280,7 +281,7 @@ void CP25Gateway::run() unsigned int addrLen; // From the reflector to the MMDVM - unsigned int len = remoteNetwork.readData(buffer, 200U, addr, addrLen); + unsigned int len = remoteNetwork.read(buffer, 200U, addr, addrLen); if (len > 0U) { // If we're linked and it's from the right place, send it on if (currentAddrLen > 0U && CUDPSocket::match(currentAddr, addr)) { @@ -295,7 +296,7 @@ void CP25Gateway::run() buffer[3U] = (currentTG >> 0) & 0xFFU; } - localNetwork.writeData(buffer, len, rptAddr, rptAddrLen); + localNetwork.write(buffer, len); hangTimer.start(); } @@ -324,7 +325,7 @@ void CP25Gateway::run() buffer[3U] = (currentTG >> 0) & 0xFFU; } - localNetwork.writeData(buffer, len, rptAddr, rptAddrLen); + localNetwork.write(buffer, len); LogMessage("Switched to reflector %u due to network activity", currentTG); @@ -336,7 +337,7 @@ void CP25Gateway::run() } // From the MMDVM to the reflector or control data - len = localNetwork.readData(buffer, 200U, addr, addrLen); + len = localNetwork.read(buffer, 200U); if (len > 0U) { if (buffer[0U] == 0x65U) { dstTG = (buffer[1U] << 16) & 0xFF0000U; @@ -353,9 +354,9 @@ void CP25Gateway::run() LogMessage("Unlinking from reflector %u by %s", currentTG, callsign.c_str()); if (!currentIsStatic) { - remoteNetwork.writeUnlink(currentAddr, currentAddrLen); - remoteNetwork.writeUnlink(currentAddr, currentAddrLen); - remoteNetwork.writeUnlink(currentAddr, currentAddrLen); + remoteNetwork.unlink(currentAddr, currentAddrLen); + remoteNetwork.unlink(currentAddr, currentAddrLen); + remoteNetwork.unlink(currentAddr, currentAddrLen); } hangTimer.stop(); @@ -394,9 +395,9 @@ void CP25Gateway::run() LogMessage("Switched to reflector %u due to RF activity from %s", currentTG, callsign.c_str()); if (!currentIsStatic) { - remoteNetwork.writePoll(currentAddr, currentAddrLen); - remoteNetwork.writePoll(currentAddr, currentAddrLen); - remoteNetwork.writePoll(currentAddr, currentAddrLen); + remoteNetwork.poll(currentAddr, currentAddrLen); + remoteNetwork.poll(currentAddr, currentAddrLen); + remoteNetwork.poll(currentAddr, currentAddrLen); } hangTimer.setTimeout(rfHangTime); @@ -430,7 +431,7 @@ void CP25Gateway::run() buffer[3U] = (currentTG >> 0) & 0xFFU; } - remoteNetwork.writeData(buffer, len, currentAddr, currentAddrLen); + remoteNetwork.write(buffer, len, currentAddr, currentAddrLen); hangTimer.start(); } } @@ -438,7 +439,7 @@ void CP25Gateway::run() if (voice != NULL) { unsigned int length = voice->read(buffer); if (length > 0U) - localNetwork.writeData(buffer, length, rptAddr, rptAddrLen); + localNetwork.write(buffer, length); } if (remoteSocket != NULL) { @@ -455,9 +456,9 @@ void CP25Gateway::run() LogMessage("Unlinked from reflector %u by remote command", currentTG); if (!currentIsStatic) { - remoteNetwork.writeUnlink(currentAddr, currentAddrLen); - remoteNetwork.writeUnlink(currentAddr, currentAddrLen); - remoteNetwork.writeUnlink(currentAddr, currentAddrLen); + remoteNetwork.unlink(currentAddr, currentAddrLen); + remoteNetwork.unlink(currentAddr, currentAddrLen); + remoteNetwork.unlink(currentAddr, currentAddrLen); } hangTimer.stop(); @@ -495,9 +496,9 @@ void CP25Gateway::run() LogMessage("Switched to reflector %u by remote command", currentTG); if (!currentIsStatic) { - remoteNetwork.writePoll(currentAddr, currentAddrLen); - remoteNetwork.writePoll(currentAddr, currentAddrLen); - remoteNetwork.writePoll(currentAddr, currentAddrLen); + remoteNetwork.poll(currentAddr, currentAddrLen); + remoteNetwork.poll(currentAddr, currentAddrLen); + remoteNetwork.poll(currentAddr, currentAddrLen); } hangTimer.setTimeout(rfHangTime); @@ -533,9 +534,9 @@ void CP25Gateway::run() LogMessage("Unlinking from %u due to inactivity", currentTG); if (!currentIsStatic) { - remoteNetwork.writeUnlink(currentAddr, currentAddrLen); - remoteNetwork.writeUnlink(currentAddr, currentAddrLen); - remoteNetwork.writeUnlink(currentAddr, currentAddrLen); + remoteNetwork.unlink(currentAddr, currentAddrLen); + remoteNetwork.unlink(currentAddr, currentAddrLen); + remoteNetwork.unlink(currentAddr, currentAddrLen); } if (voice != NULL) @@ -549,15 +550,17 @@ void CP25Gateway::run() currentTG = 0U; } + localNetwork.clock(ms); + pollTimer.clock(ms); if (pollTimer.isRunning() && pollTimer.hasExpired()) { // Poll the static TGs for (std::vector::const_iterator it = staticTGs.cbegin(); it != staticTGs.cend(); ++it) - remoteNetwork.writePoll((*it).m_addr, (*it).m_addrLen); + remoteNetwork.poll((*it).m_addr, (*it).m_addrLen); // Poll the dynamic TG if (!currentIsStatic && currentAddrLen > 0U) - remoteNetwork.writePoll(currentAddr, currentAddrLen); + remoteNetwork.poll(currentAddr, currentAddrLen); pollTimer.start(); } diff --git a/P25Gateway/P25Gateway.ini b/P25Gateway/P25Gateway.ini index 16ab7ba..51fb785 100644 --- a/P25Gateway/P25Gateway.ini +++ b/P25Gateway/P25Gateway.ini @@ -2,6 +2,7 @@ Callsign=G4KLX RptAddress=127.0.0.1 RptPort=32010 +LocalAddress=127.0.0.1 LocalPort=42020 Debug=0 Daemon=1 diff --git a/P25Gateway/P25Gateway.vcxproj b/P25Gateway/P25Gateway.vcxproj index bf8f368..5589d3b 100644 --- a/P25Gateway/P25Gateway.vcxproj +++ b/P25Gateway/P25Gateway.vcxproj @@ -87,7 +87,7 @@ Level3 Disabled - HAVE_LOG_H;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + HAVE_LOG_H;UDP_SOCKET_MAX=2;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) Console @@ -101,7 +101,7 @@ Level3 Disabled - HAVE_LOG_H;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + HAVE_LOG_H;UDP_SOCKET_MAX=2;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) Console @@ -117,7 +117,7 @@ MaxSpeed true true - HAVE_LOG_H;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + HAVE_LOG_H;UDP_SOCKET_MAX=2;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) Console @@ -135,7 +135,7 @@ MaxSpeed true true - HAVE_LOG_H;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + HAVE_LOG_H;UDP_SOCKET_MAX=2;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) Console @@ -150,9 +150,10 @@ - + + @@ -166,9 +167,10 @@ - + + diff --git a/P25Gateway/P25Gateway.vcxproj.filters b/P25Gateway/P25Gateway.vcxproj.filters index 2974070..01d9d7b 100644 --- a/P25Gateway/P25Gateway.vcxproj.filters +++ b/P25Gateway/P25Gateway.vcxproj.filters @@ -23,9 +23,6 @@ Header Files - - Header Files - Header Files @@ -53,6 +50,12 @@ Header Files + + Header Files + + + Header Files + @@ -67,9 +70,6 @@ Source Files - - Source Files - Source Files @@ -94,5 +94,11 @@ Source Files + + Source Files + + + Source Files + \ No newline at end of file diff --git a/P25Gateway/Network.cpp b/P25Gateway/P25Network.cpp similarity index 72% rename from P25Gateway/Network.cpp rename to P25Gateway/P25Network.cpp index d9d49ea..489df91 100644 --- a/P25Gateway/Network.cpp +++ b/P25Gateway/P25Network.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "Network.h" +#include "P25Network.h" #include "Utils.h" #include "Log.h" @@ -24,26 +24,33 @@ #include #include -CNetwork::CNetwork(unsigned int port, const std::string& callsign, bool debug) : +CP25Network::CP25Network(unsigned int port, const std::string& callsign, bool debug) : m_callsign(callsign), -m_socket(port), +m_socket(), +m_port(port), m_debug(debug) { + assert(port > 0U); + m_callsign.resize(10U, ' '); } -CNetwork::~CNetwork() +CP25Network::~CP25Network() { } -bool CNetwork::open() +bool CP25Network::open() { LogInfo("Opening P25 network connection"); - return m_socket.open(); + bool ret = m_socket.open(0, PF_INET, "", m_port); + if (!ret) + return false; + + return m_socket.open(1, PF_INET6, "", m_port); } -bool CNetwork::writeData(const unsigned char* data, unsigned int length, const sockaddr_storage& addr, unsigned int addrLen) +bool CP25Network::write(const unsigned char* data, unsigned int length, const sockaddr_storage& addr, unsigned int addrLen) { assert(data != NULL); assert(length > 0U); @@ -54,7 +61,7 @@ bool CNetwork::writeData(const unsigned char* data, unsigned int length, const s return m_socket.write(data, length, addr, addrLen); } -bool CNetwork::writePoll(const sockaddr_storage& addr, unsigned int addrLen) +bool CP25Network::poll(const sockaddr_storage& addr, unsigned int addrLen) { unsigned char data[15U]; @@ -69,7 +76,7 @@ bool CNetwork::writePoll(const sockaddr_storage& addr, unsigned int addrLen) return m_socket.write(data, 11U, addr, addrLen); } -bool CNetwork::writeUnlink(const sockaddr_storage& addr, unsigned int addrLen) +bool CP25Network::unlink(const sockaddr_storage& addr, unsigned int addrLen) { unsigned char data[15U]; @@ -84,7 +91,7 @@ bool CNetwork::writeUnlink(const sockaddr_storage& addr, unsigned int addrLen) return m_socket.write(data, 11U, addr, addrLen); } -unsigned int CNetwork::readData(unsigned char* data, unsigned int length, sockaddr_storage& addr, unsigned int& addrLen) +unsigned int CP25Network::read(unsigned char* data, unsigned int length, sockaddr_storage& addr, unsigned int& addrLen) { assert(data != NULL); assert(length > 0U); @@ -99,7 +106,7 @@ unsigned int CNetwork::readData(unsigned char* data, unsigned int length, sockad return len; } -void CNetwork::close() +void CP25Network::close() { m_socket.close(); diff --git a/P25Gateway/Network.h b/P25Gateway/P25Network.h similarity index 60% rename from P25Gateway/Network.h rename to P25Gateway/P25Network.h index bc44848..7d909b7 100644 --- a/P25Gateway/Network.h +++ b/P25Gateway/P25Network.h @@ -16,35 +16,36 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef Network_H -#define Network_H +#ifndef P25Network_H +#define P25Network_H #include "UDPSocket.h" #include #include -class CNetwork { +class CP25Network { public: - CNetwork(unsigned int port, const std::string& callsign, bool debug); - ~CNetwork(); + CP25Network(unsigned int port, const std::string& callsign, bool debug); + ~CP25Network(); bool open(); - bool writeData(const unsigned char* data, unsigned int length, const sockaddr_storage& addr, unsigned int addrLen); + bool write(const unsigned char* data, unsigned int length, const sockaddr_storage& addr, unsigned int addrLen); - unsigned int readData(unsigned char* data, unsigned int length, sockaddr_storage& addr, unsigned int& addrLen); + unsigned int read(unsigned char* data, unsigned int length, sockaddr_storage& addr, unsigned int& addrLen); - bool writePoll(const sockaddr_storage& addr, unsigned int addrLen); + bool poll(const sockaddr_storage& addr, unsigned int addrLen); - bool writeUnlink(const sockaddr_storage& addr, unsigned int addrLen); + bool unlink(const sockaddr_storage& addr, unsigned int addrLen); void close(); private: - std::string m_callsign; - CUDPSocket m_socket; - bool m_debug; + std::string m_callsign; + CUDPSocket m_socket; + unsigned int m_port; + bool m_debug; }; #endif diff --git a/P25Gateway/RptNetwork.cpp b/P25Gateway/RptNetwork.cpp new file mode 100644 index 0000000..c828133 --- /dev/null +++ b/P25Gateway/RptNetwork.cpp @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2009-2014,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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "RptNetwork.h" +#include "Utils.h" +#include "Log.h" + +#include +#include +#include + +CRptNetwork::CRptNetwork(const std::string& myAddr, unsigned int myPort, const sockaddr_storage& rptAddr, unsigned int rptAddrLen, const std::string& callsign, bool debug) : +m_myAddr(), +m_myAddrLen(0U), +m_rptAddr(rptAddr), +m_rptAddrLen(rptAddrLen), +m_callsign(callsign), +m_socket(myAddr, myPort), +m_debug(debug), +m_timer(1000U, 5U) +{ + assert(myPort > 0U); + assert(rptAddrLen > 0U); + + CUDPSocket::lookup(myAddr, myPort, m_myAddr, m_myAddrLen); + + m_callsign.resize(10U, ' '); +} + +CRptNetwork::~CRptNetwork() +{ +} + +bool CRptNetwork::open() +{ + if (m_myAddrLen == 0U) { + LogError("Unable to resolve the local address and port"); + return false; + } + + LogInfo("Opening Rpt network connection"); + + bool ret = m_socket.open(m_myAddr); + + if (ret) { + m_timer.start(); + return true; + } else { + return false; + } +} + +bool CRptNetwork::write(const unsigned char* data, unsigned int length) +{ + assert(data != NULL); + assert(length > 0U); + + if (m_debug) + CUtils::dump(1U, "Rpt Network Data Sent", data, length); + + return m_socket.write(data, length, m_rptAddr, m_rptAddrLen); +} + +bool CRptNetwork::writePoll() +{ + unsigned char data[15U]; + + data[0U] = 0xF0U; + + for (unsigned int i = 0U; i < 10U; i++) + data[i + 1U] = m_callsign.at(i); + + if (m_debug) + CUtils::dump(1U, "Rpt Network Poll Sent", data, 11U); + + return m_socket.write(data, 11U, m_rptAddr, m_rptAddrLen); +} + +unsigned int CRptNetwork::read(unsigned char* data, unsigned int length) +{ + assert(data != NULL); + assert(length > 0U); + + sockaddr_storage addr; + unsigned int addrLen = 0U; + int len = m_socket.read(data, length, addr, addrLen); + if (len <= 0) + return 0U; + + if (!CUDPSocket::match(addr, m_rptAddr)) + return 0U; + + if (m_debug) + CUtils::dump(1U, "Rpt Network Data Received", data, len); + + return len; +} + +void CRptNetwork::clock(unsigned int ms) +{ + m_timer.clock(ms); + if (m_timer.isRunning() && m_timer.hasExpired()) { + writePoll(); + m_timer.start(); + } +} + +void CRptNetwork::close() +{ + m_timer.stop(); + + m_socket.close(); + + LogInfo("Closing Rpt network connection"); +} diff --git a/P25Gateway/RptNetwork.h b/P25Gateway/RptNetwork.h new file mode 100644 index 0000000..b918e2d --- /dev/null +++ b/P25Gateway/RptNetwork.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2009-2014,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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef RptNetwork_H +#define RptNetwork_H + +#include "UDPSocket.h" +#include "Timer.h" + +#include +#include + +class CRptNetwork { +public: + CRptNetwork(const std::string& myAddr, unsigned int myPort, const sockaddr_storage& rptAddr, unsigned int rptAddrLen, const std::string& callsign, bool debug); + ~CRptNetwork(); + + bool open(); + + bool write(const unsigned char* data, unsigned int length); + + unsigned int read(unsigned char* data, unsigned int length); + + void clock(unsigned int ms); + + void close(); + +private: + sockaddr_storage m_myAddr; + unsigned int m_myAddrLen; + sockaddr_storage m_rptAddr; + unsigned int m_rptAddrLen; + std::string m_callsign; + CUDPSocket m_socket; + bool m_debug; + CTimer m_timer; + + bool writePoll(); +}; + +#endif diff --git a/P25Gateway/Version.h b/P25Gateway/Version.h index 0272115..1ac5058 100644 --- a/P25Gateway/Version.h +++ b/P25Gateway/Version.h @@ -19,6 +19,6 @@ #if !defined(VERSION_H) #define VERSION_H -const char* VERSION = "20201102"; +const char* VERSION = "20201104"; #endif