diff --git a/Conf.cpp b/Conf.cpp index 065573e..4a21b9e 100644 --- a/Conf.cpp +++ b/Conf.cpp @@ -31,15 +31,14 @@ enum SECTION { SECTION_GENERAL, SECTION_LOG, SECTION_VOICE, - SECTION_DMR_NETWORK, + SECTION_DMR_NETWORK_1, + SECTION_DMR_NETWORK_2, SECTION_XLX_NETWORK }; CConf::CConf(const std::string& file) : m_file(file), m_daemon(false), -m_xlxSlot(2U), -m_xlxTG(9U), m_rptAddress("127.0.0.1"), m_rptPort(62032U), m_localAddress("127.0.0.1"), @@ -53,15 +52,31 @@ m_logFileRoot(), m_voiceEnabled(true), m_voiceLanguage("en_GB"), m_voiceDirectory(), -m_dmrNetworkAddress(), -m_dmrNetworkPort(0U), -m_dmrNetworkLocal(0U), -m_dmrNetworkPassword(), -m_dmrNetworkDebug(false), +m_dmrNetwork1Enabled(false), +m_dmrNetwork1Address(), +m_dmrNetwork1Port(0U), +m_dmrNetwork1Local(0U), +m_dmrNetwork1Password(), +m_dmrNetwork1Debug(false), +m_dmrNetwork1Rewrites(), +m_dmrNetwork1PrivateSlot1(false), +m_dmrNetwork1PrivateSlot2(false), +m_dmrNetwork2Enabled(false), +m_dmrNetwork2Address(), +m_dmrNetwork2Port(0U), +m_dmrNetwork2Local(0U), +m_dmrNetwork2Password(), +m_dmrNetwork2Debug(false), +m_dmrNetwork2Rewrites(), +m_dmrNetwork2PrivateSlot1(false), +m_dmrNetwork2PrivateSlot2(false), +m_xlxNetworkEnabled(false), m_xlxNetworkAddress(), m_xlxNetworkPort(0U), m_xlxNetworkLocal(0U), m_xlxNetworkPassword(), +m_xlxNetworkSlot(2U), +m_xlxNetworkTG(9U), m_xlxNetworkOptions(), m_xlxNetworkDebug(false) { @@ -95,8 +110,10 @@ bool CConf::read() section = SECTION_VOICE; else if (::strncmp(buffer, "[XLX Network]", 13U) == 0) section = SECTION_XLX_NETWORK; - else if (::strncmp(buffer, "[DMR Network]", 13U) == 0) - section = SECTION_DMR_NETWORK; + else if (::strncmp(buffer, "[DMR Network 1]", 15U) == 0) + section = SECTION_DMR_NETWORK_1; + else if (::strncmp(buffer, "[DMR Network 2]", 15U) == 0) + section = SECTION_DMR_NETWORK_2; else section = SECTION_NONE; @@ -114,10 +131,6 @@ bool CConf::read() if (section == SECTION_GENERAL) { if (::strcmp(key, "Daemon") == 0) m_daemon = ::atoi(value) == 1; - else if (::strcmp(key, "XLXSlot") == 0) - m_xlxSlot = (unsigned int)::atoi(value); - else if (::strcmp(key, "XLXTG") == 0) - m_xlxTG = (unsigned int)::atoi(value); else if (::strcmp(key, "Timeout") == 0) m_timeout = (unsigned int)::atoi(value); else if (::strcmp(key, "RptAddress") == 0) @@ -147,7 +160,9 @@ bool CConf::read() else if (::strcmp(key, "Directory") == 0) m_voiceDirectory = value; } else if (section == SECTION_XLX_NETWORK) { - if (::strcmp(key, "Address") == 0) + if (::strcmp(key, "Enabled") == 0) + m_xlxNetworkEnabled = ::atoi(value) == 1; + else if (::strcmp(key, "Address") == 0) m_xlxNetworkAddress = value; else if (::strcmp(key, "Port") == 0) m_xlxNetworkPort = (unsigned int)::atoi(value); @@ -155,21 +170,74 @@ bool CConf::read() m_xlxNetworkLocal = (unsigned int)::atoi(value); else if (::strcmp(key, "Password") == 0) m_xlxNetworkPassword = value; + else if (::strcmp(key, "Slot") == 0) + m_xlxNetworkSlot = (unsigned int)::atoi(value); + else if (::strcmp(key, "TG") == 0) + m_xlxNetworkTG = (unsigned int)::atoi(value); else if (::strcmp(key, "Options") == 0) m_xlxNetworkOptions = value; else if (::strcmp(key, "Debug") == 0) m_xlxNetworkDebug = ::atoi(value) == 1; - } else if (section == SECTION_DMR_NETWORK) { - if (::strcmp(key, "Address") == 0) - m_dmrNetworkAddress = value; + } else if (section == SECTION_DMR_NETWORK_1) { + if (::strcmp(key, "Enabled") == 0) + m_dmrNetwork1Enabled = ::atoi(value) == 1; + else if (::strcmp(key, "Address") == 0) + m_dmrNetwork1Address = value; else if (::strcmp(key, "Port") == 0) - m_dmrNetworkPort = (unsigned int)::atoi(value); + m_dmrNetwork1Port = (unsigned int)::atoi(value); else if (::strcmp(key, "Local") == 0) - m_dmrNetworkLocal = (unsigned int)::atoi(value); + m_dmrNetwork1Local = (unsigned int)::atoi(value); else if (::strcmp(key, "Password") == 0) - m_dmrNetworkPassword = value; + m_dmrNetwork1Password = value; else if (::strcmp(key, "Debug") == 0) - m_dmrNetworkDebug = ::atoi(value) == 1; + m_dmrNetwork1Debug = ::atoi(value) == 1; + else if (::strcmp(key, "Rewrites") == 0) { + char* p1 = ::strtok(value, ", "); + char* p2 = ::strtok(NULL, ", "); + char* p3 = ::strtok(NULL, ", "); + char* p4 = ::strtok(NULL, " \r\n"); + if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL) { + CRewriteStruct rewrite; + rewrite.m_fromSlot = ::atoi(p1); + rewrite.m_fromTG = ::atoi(p2); + rewrite.m_toSlot = ::atoi(p3); + rewrite.m_toTG = ::atoi(p4); + m_dmrNetwork1Rewrites.push_back(rewrite); + } + } else if (::strcmp(key, "PrivateSlot1") == 0) + m_dmrNetwork1PrivateSlot1 = ::atoi(value) == 1; + else if (::strcmp(key, "PrivateSlot2") == 0) + m_dmrNetwork1PrivateSlot2 = ::atoi(value) == 1; + } else if (section == SECTION_DMR_NETWORK_2) { + if (::strcmp(key, "Enabled") == 0) + m_dmrNetwork2Enabled = ::atoi(value) == 1; + else if (::strcmp(key, "Address") == 0) + m_dmrNetwork2Address = value; + else if (::strcmp(key, "Port") == 0) + m_dmrNetwork2Port = (unsigned int)::atoi(value); + else if (::strcmp(key, "Local") == 0) + m_dmrNetwork2Local = (unsigned int)::atoi(value); + else if (::strcmp(key, "Password") == 0) + m_dmrNetwork2Password = value; + else if (::strcmp(key, "Debug") == 0) + m_dmrNetwork2Debug = ::atoi(value) == 1; + else if (::strcmp(key, "Rewrites") == 0) { + char* p1 = ::strtok(value, ", "); + char* p2 = ::strtok(NULL, ", "); + char* p3 = ::strtok(NULL, ", "); + char* p4 = ::strtok(NULL, " \r\n"); + if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL) { + CRewriteStruct rewrite; + rewrite.m_fromSlot = ::atoi(p1); + rewrite.m_fromTG = ::atoi(p2); + rewrite.m_toSlot = ::atoi(p3); + rewrite.m_toTG = ::atoi(p4); + m_dmrNetwork2Rewrites.push_back(rewrite); + } + } else if (::strcmp(key, "PrivateSlot1") == 0) + m_dmrNetwork2PrivateSlot1 = ::atoi(value) == 1; + else if (::strcmp(key, "PrivateSlot2") == 0) + m_dmrNetwork2PrivateSlot2 = ::atoi(value) == 1; } } @@ -183,16 +251,6 @@ bool CConf::getDaemon() const return m_daemon; } -unsigned int CConf::getXLXSlot() const -{ - return m_xlxSlot; -} - -unsigned int CConf::getXLXTG() const -{ - return m_xlxTG; -} - std::string CConf::getRptAddress() const { return m_rptAddress; @@ -258,6 +316,11 @@ std::string CConf::getVoiceDirectory() const return m_voiceDirectory; } +bool CConf::getXLXNetworkEnabled() const +{ + return m_xlxNetworkEnabled; +} + std::string CConf::getXLXNetworkAddress() const { return m_xlxNetworkAddress; @@ -273,6 +336,16 @@ unsigned int CConf::getXLXNetworkLocal() const return m_xlxNetworkLocal; } +unsigned int CConf::getXLXNetworkSlot() const +{ + return m_xlxNetworkSlot; +} + +unsigned int CConf::getXLXNetworkTG() const +{ + return m_xlxNetworkTG; +} + std::string CConf::getXLXNetworkPassword() const { return m_xlxNetworkPassword; @@ -288,27 +361,92 @@ bool CConf::getXLXNetworkDebug() const return m_xlxNetworkDebug; } -std::string CConf::getDMRNetworkAddress() const +bool CConf::getDMRNetwork1Enabled() const { - return m_dmrNetworkAddress; + return m_dmrNetwork1Enabled; } -unsigned int CConf::getDMRNetworkPort() const +std::string CConf::getDMRNetwork1Address() const { - return m_dmrNetworkPort; + return m_dmrNetwork1Address; } -unsigned int CConf::getDMRNetworkLocal() const +unsigned int CConf::getDMRNetwork1Port() const { - return m_dmrNetworkLocal; + return m_dmrNetwork1Port; } -std::string CConf::getDMRNetworkPassword() const +unsigned int CConf::getDMRNetwork1Local() const { - return m_dmrNetworkPassword; + return m_dmrNetwork1Local; } -bool CConf::getDMRNetworkDebug() const +std::string CConf::getDMRNetwork1Password() const { - return m_dmrNetworkDebug; + return m_dmrNetwork1Password; +} + +bool CConf::getDMRNetwork1Debug() const +{ + return m_dmrNetwork1Debug; +} + +std::vector CConf::getDMRNetwork1Rewrites() const +{ + return m_dmrNetwork1Rewrites; +} + +bool CConf::getDMRNetwork1PrivateSlot1() const +{ + return m_dmrNetwork1PrivateSlot1; +} + +bool CConf::getDMRNetwork1PrivateSlot2() const +{ + return m_dmrNetwork1PrivateSlot2; +} + +bool CConf::getDMRNetwork2Enabled() const +{ + return m_dmrNetwork2Enabled; +} + +std::string CConf::getDMRNetwork2Address() const +{ + return m_dmrNetwork2Address; +} + +unsigned int CConf::getDMRNetwork2Port() const +{ + return m_dmrNetwork2Port; +} + +unsigned int CConf::getDMRNetwork2Local() const +{ + return m_dmrNetwork2Local; +} + +std::string CConf::getDMRNetwork2Password() const +{ + return m_dmrNetwork2Password; +} + +bool CConf::getDMRNetwork2Debug() const +{ + return m_dmrNetwork2Debug; +} + +std::vector CConf::getDMRNetwork2Rewrites() const +{ + return m_dmrNetwork2Rewrites; +} + +bool CConf::getDMRNetwork2PrivateSlot1() const +{ + return m_dmrNetwork2PrivateSlot1; +} + +bool CConf::getDMRNetwork2PrivateSlot2() const +{ + return m_dmrNetwork2PrivateSlot2; } diff --git a/Conf.h b/Conf.h index 525dda3..ad21ecd 100644 --- a/Conf.h +++ b/Conf.h @@ -22,6 +22,13 @@ #include #include +struct CRewriteStruct { + unsigned int m_fromSlot; + unsigned int m_fromTG; + unsigned int m_toSlot; + unsigned int m_toTG; +}; + class CConf { public: @@ -32,8 +39,6 @@ public: // The General section bool getDaemon() const; - unsigned int getXLXSlot() const; - unsigned int getXLXTG() const; unsigned int getTimeout() const; std::string getRptAddress() const; unsigned int getRptPort() const; @@ -52,26 +57,42 @@ public: std::string getVoiceLanguage() const; std::string getVoiceDirectory() const; - // The DMR Network section - std::string getDMRNetworkAddress() const; - unsigned int getDMRNetworkPort() const; - unsigned int getDMRNetworkLocal() const; - std::string getDMRNetworkPassword() const; - bool getDMRNetworkDebug() const; + // The DMR Network 1 section + bool getDMRNetwork1Enabled() const; + std::string getDMRNetwork1Address() const; + unsigned int getDMRNetwork1Port() const; + unsigned int getDMRNetwork1Local() const; + std::string getDMRNetwork1Password() const; + bool getDMRNetwork1Debug() const; + std::vector getDMRNetwork1Rewrites() const; + bool getDMRNetwork1PrivateSlot1() const; + bool getDMRNetwork1PrivateSlot2() const; + + // The DMR Network 2 section + bool getDMRNetwork2Enabled() const; + std::string getDMRNetwork2Address() const; + unsigned int getDMRNetwork2Port() const; + unsigned int getDMRNetwork2Local() const; + std::string getDMRNetwork2Password() const; + bool getDMRNetwork2Debug() const; + std::vector getDMRNetwork2Rewrites() const; + bool getDMRNetwork2PrivateSlot1() const; + bool getDMRNetwork2PrivateSlot2() const; // The XLX Network section + bool getXLXNetworkEnabled() const; std::string getXLXNetworkAddress() const; unsigned int getXLXNetworkPort() const; unsigned int getXLXNetworkLocal() const; std::string getXLXNetworkPassword() const; + unsigned int getXLXNetworkSlot() const; + unsigned int getXLXNetworkTG() const; std::string getXLXNetworkOptions() const; bool getXLXNetworkDebug() const; private: std::string m_file; bool m_daemon; - unsigned int m_xlxSlot; - unsigned int m_xlxTG; std::string m_rptAddress; unsigned int m_rptPort; std::string m_localAddress; @@ -88,18 +109,35 @@ private: std::string m_logFilePath; std::string m_logFileRoot; - std::string m_dmrNetworkAddress; - unsigned int m_dmrNetworkPort; - unsigned int m_dmrNetworkLocal; - std::string m_dmrNetworkPassword; - bool m_dmrNetworkDebug; + bool m_dmrNetwork1Enabled; + std::string m_dmrNetwork1Address; + unsigned int m_dmrNetwork1Port; + unsigned int m_dmrNetwork1Local; + std::string m_dmrNetwork1Password; + bool m_dmrNetwork1Debug; + bool m_dmrNetwork2Enabled; + std::string m_dmrNetwork2Address; + unsigned int m_dmrNetwork2Port; + unsigned int m_dmrNetwork2Local; + std::string m_dmrNetwork2Password; + bool m_dmrNetwork2Debug; + std::vector m_dmrNetwork1Rewrites; + bool m_dmrNetwork1PrivateSlot1; + bool m_dmrNetwork1PrivateSlot2; + + bool m_xlxNetworkEnabled; std::string m_xlxNetworkAddress; unsigned int m_xlxNetworkPort; unsigned int m_xlxNetworkLocal; std::string m_xlxNetworkPassword; + unsigned int m_xlxNetworkSlot; + unsigned int m_xlxNetworkTG; std::string m_xlxNetworkOptions; bool m_xlxNetworkDebug; + std::vector m_dmrNetwork2Rewrites; + bool m_dmrNetwork2PrivateSlot1; + bool m_dmrNetwork2PrivateSlot2; }; #endif diff --git a/DMRGateway.cpp b/DMRGateway.cpp index f508203..c9f1462 100644 --- a/DMRGateway.cpp +++ b/DMRGateway.cpp @@ -57,7 +57,8 @@ static void sigHandler(int signum) enum DMRGW_STATUS { DMRGWS_NONE, - DMRGWS_NETWORK, + DMRGWS_NETWORK1, + DMRGWS_NETWORK2, DMRGWS_REFLECTOR }; @@ -68,60 +69,83 @@ const char* HEADER4 = "Copyright(C) 2017 by Jonathan Naylor, G4KLX and others"; int main(int argc, char** argv) { - const char* iniFile = DEFAULT_INI_FILE; - if (argc > 1) { - for (int currentArg = 1; currentArg < argc; ++currentArg) { - std::string arg = argv[currentArg]; - if ((arg == "-v") || (arg == "--version")) { - ::fprintf(stdout, "DMRGateway version %s\n", VERSION); - return 0; - } else if (arg.substr(0,1) == "-") { - ::fprintf(stderr, "Usage: DMRGateway [-v|--version] [filename]\n"); - return 1; - } else { - iniFile = argv[currentArg]; - } - } - } + const char* iniFile = DEFAULT_INI_FILE; + + if (argc > 1) { + for (int currentArg = 1; currentArg < argc; ++currentArg) { + std::string arg = argv[currentArg]; + if ((arg == "-v") || (arg == "--version")) { + ::fprintf(stdout, "DMRGateway version %s\n", VERSION); + return 0; + } else if (arg.substr(0,1) == "-") { + ::fprintf(stderr, "Usage: DMRGateway [-v|--version] [filename]\n"); + return 1; + } else { + iniFile = argv[currentArg]; + } + } + } #if !defined(_WIN32) && !defined(_WIN64) - ::signal(SIGTERM, sigHandler); - ::signal(SIGHUP, sigHandler); + ::signal(SIGTERM, sigHandler); + ::signal(SIGHUP, sigHandler); #endif - int ret = 0; + int ret = 0; - do { - m_signal = 0; + do { + m_signal = 0; - CDMRGateway* host = new CDMRGateway(std::string(iniFile)); - ret = host->run(); + CDMRGateway* host = new CDMRGateway(std::string(iniFile)); + ret = host->run(); - delete host; + delete host; - if (m_signal == 15) - ::LogInfo("Caught SIGTERM, exiting"); + if (m_signal == 15) + ::LogInfo("Caught SIGTERM, exiting"); - if (m_signal == 1) - ::LogInfo("Caught SIGHUP, restarting"); - } while (m_signal == 1); + if (m_signal == 1) + ::LogInfo("Caught SIGHUP, restarting"); + } while (m_signal == 1); - ::LogFinalise(); + ::LogFinalise(); - return ret; + return ret; } CDMRGateway::CDMRGateway(const std::string& confFile) : m_conf(confFile), m_repeater(NULL), -m_dmrNetwork(NULL), +m_dmrNetwork1(NULL), +m_dmrNetwork2(NULL), m_xlxNetwork(NULL), -m_reflector(4000U) +m_reflector(4000U), +m_xlxSlot(0U), +m_xlxTG(0U), +m_dmr1NetRewrites(), +m_dmr1RFRewrites(), +m_dmr2NetRewrites(), +m_dmr2RFRewrites(), +m_dmr1PrivateSlot1(false), +m_dmr1PrivateSlot2(false), +m_dmr2PrivateSlot1(false), +m_dmr2PrivateSlot2(false) { } CDMRGateway::~CDMRGateway() { + for (std::vector::iterator it = m_dmr1NetRewrites.begin(); it != m_dmr1NetRewrites.end(); ++it) + delete *it; + + for (std::vector::iterator it = m_dmr1RFRewrites.begin(); it != m_dmr1RFRewrites.end(); ++it) + delete *it; + + for (std::vector::iterator it = m_dmr2NetRewrites.begin(); it != m_dmr2NetRewrites.end(); ++it) + delete *it; + + for (std::vector::iterator it = m_dmr2RFRewrites.begin(); it != m_dmr2RFRewrites.end(); ++it) + delete *it; } int CDMRGateway::run() @@ -144,28 +168,28 @@ int CDMRGateway::run() // Create new process pid_t pid = ::fork(); if (pid == -1) { - ::LogWarning("Couldn't fork() , exiting"); - return -1; - } - else if (pid != 0) + ::LogWarning("Couldn't fork() , exiting"); + return -1; + } else if (pid != 0) { exit(EXIT_SUCCESS); + } // Create new session and process group if (::setsid() == -1){ - ::LogWarning("Couldn't setsid(), exiting"); - return -1; - } + ::LogWarning("Couldn't setsid(), exiting"); + return -1; + } // Set the working directory to the root directory if (::chdir("/") == -1){ - ::LogWarning("Couldn't cd /, exiting"); - return -1; - } + ::LogWarning("Couldn't cd /, exiting"); + return -1; + } ::close(STDIN_FILENO); ::close(STDOUT_FILENO); ::close(STDERR_FILENO); -#if !defined(HD44780) && !defined(OLED) + //If we are currently root... if (getuid() == 0) { struct passwd* user = ::getpwnam("mmdvm"); @@ -196,10 +220,6 @@ int CDMRGateway::run() } } -#else - ::LogWarning("Dropping root permissions in daemon mode is disabled with HD44780 display"); - } -#endif #endif LogInfo(HEADER1); @@ -228,28 +248,33 @@ int CDMRGateway::run() LogMessage("MMDVM has connected"); - unsigned int xlxSlot = m_conf.getXLXSlot(); - unsigned int xlxTG = m_conf.getXLXTG(); unsigned int timeout = m_conf.getTimeout(); LogInfo("Id: %u", m_repeater->getId()); - LogInfo("XLX Local Slot: %u", xlxSlot); - LogInfo("XLX Local TG: %u", xlxTG); - LogInfo("Timeout: %us", timeout); - CRewrite rptRewrite(xlxSlot, xlxTG); - CRewrite xlxRewrite(XLX_SLOT, XLX_TG); + CRewrite rptRewrite(XLX_SLOT, XLX_TG, m_xlxSlot, m_xlxTG); + CRewrite xlxRewrite(m_xlxSlot, m_xlxTG, XLX_SLOT, XLX_TG); - ret = createDMRNetwork(); - if (!ret) - return 1; + if (m_conf.getDMRNetwork1Enabled()) { + ret = createDMRNetwork1(); + if (!ret) + return 1; + } - ret = createXLXNetwork(); - if (!ret) - return 1; + if (m_conf.getDMRNetwork2Enabled()) { + ret = createDMRNetwork2(); + if (!ret) + return 1; + } + + if (m_conf.getXLXNetworkEnabled()) { + ret = createXLXNetwork(); + if (!ret) + return 1; + } CVoice* voice = NULL; - if (m_conf.getVoiceEnabled()) { + if (m_conf.getVoiceEnabled() && m_xlxNetwork != NULL) { std::string language = m_conf.getVoiceLanguage(); std::string directory = m_conf.getVoiceDirectory(); @@ -258,7 +283,7 @@ int CDMRGateway::run() LogInfo(" Language: %s", language.c_str()); LogInfo(" Directory: %s", directory.c_str()); - voice = new CVoice(directory, language, m_repeater->getId(), xlxSlot, xlxTG); + voice = new CVoice(directory, language, m_repeater->getId(), m_xlxSlot, m_xlxTG); bool ret = voice->open(); if (!ret) { @@ -267,9 +292,13 @@ int CDMRGateway::run() } } - DMRGW_STATUS status = DMRGWS_NONE; + CTimer* timer[3U]; + timer[1U] = new CTimer(1000U, timeout); + timer[2U] = new CTimer(1000U, timeout); - CTimer timer(1000U, timeout); + DMRGW_STATUS status[3U]; + status[1U] = DMRGWS_NONE; + status[2U] = DMRGWS_NONE; CStopWatch stopWatch; stopWatch.start(); @@ -284,89 +313,205 @@ int CDMRGateway::run() bool ret = m_repeater->read(data); if (ret) { unsigned int slotNo = data.getSlotNo(); - if (slotNo == xlxSlot) { - FLCO flco = data.getFLCO(); - unsigned int id = data.getDstId(); + unsigned int dstId = data.getDstId(); + FLCO flco = data.getFLCO(); - if (flco == FLCO_GROUP && id == xlxTG) { - xlxRewrite.process(data); - m_xlxNetwork->write(data); - status = DMRGWS_REFLECTOR; - timer.start(); - } else if (flco == FLCO_USER_USER) { - unsigned int id = data.getDstId(); - if (id >= 4000U && id <= 4026U) { - if (id != m_reflector) { - if (id != 4000U) - LogMessage("Linking to reflector %u", id); + if (flco == FLCO_GROUP && slotNo == m_xlxSlot && dstId == m_xlxTG) { + xlxRewrite.process(data); + m_xlxNetwork->write(data); + status[slotNo] = DMRGWS_REFLECTOR; + timer[slotNo]->start(); + } else if (flco == FLCO_USER_USER && slotNo == m_xlxSlot && dstId >= 4000U && dstId <= 4026U) { + if (dstId != m_reflector) { + if (dstId == 4000U) + LogMessage("Unlinking"); + else + LogMessage("Linking to reflector %u", dstId); + + m_reflector = dstId; + changed = true; + } + + data.setSlotNo(XLX_SLOT); + m_xlxNetwork->write(data); + status[slotNo] = DMRGWS_REFLECTOR; + timer[slotNo]->start(); + + if (voice != NULL) { + unsigned char type = data.getDataType(); + if (type == DT_TERMINATOR_WITH_LC) { + if (changed) { + if (m_reflector == 4000U) + voice->unlinked(); else - LogMessage("Unlinking"); - - m_reflector = id; - changed = true; + voice->linkedTo(m_reflector); + changed = false; } - - xlxRewrite.process(data); - m_xlxNetwork->write(data); - status = DMRGWS_REFLECTOR; - timer.start(); - - if (voice != NULL) { - unsigned char type = data.getDataType(); - if (type == DT_TERMINATOR_WITH_LC) { - if (changed) { - if (m_reflector == 4000U) - voice->unlinked(); - else - voice->linkedTo(m_reflector); - changed = false; - } - } + } + } + } else if (flco = FLCO_USER_USER) { + if (m_dmrNetwork1 != NULL && slotNo == 1U && m_dmr1PrivateSlot1) { + m_dmrNetwork1->write(data); + status[slotNo] = DMRGWS_NETWORK1; + timer[slotNo]->start(); + } else if (m_dmrNetwork1 != NULL && slotNo == 2U && m_dmr1PrivateSlot2) { + m_dmrNetwork1->write(data); + status[slotNo] = DMRGWS_NETWORK1; + timer[slotNo]->start(); + } else if (m_dmrNetwork2 != NULL && slotNo == 1U && m_dmr2PrivateSlot1) { + m_dmrNetwork2->write(data); + status[slotNo] = DMRGWS_NETWORK2; + timer[slotNo]->start(); + } else if (m_dmrNetwork2 != NULL && slotNo == 2U && m_dmr2PrivateSlot2) { + m_dmrNetwork2->write(data); + status[slotNo] = DMRGWS_NETWORK2; + timer[slotNo]->start(); + } + } else { + if (m_dmrNetwork1 != NULL) { + // Rewrite the slot and/or TG or neither + bool rewritten = false; + for (std::vector::iterator it = m_dmr1RFRewrites.begin(); it != m_dmr1RFRewrites.end(); ++it) { + bool ret = (*it)->process(data); + if (ret) { + rewritten = true; + break; } - } else { - m_dmrNetwork->write(data); - status = DMRGWS_NETWORK; - timer.start(); + } + + if (rewritten) { + unsigned int slotNo = data.getSlotNo(); + if (status[slotNo] == DMRGWS_NONE || status[slotNo] == DMRGWS_NETWORK1) { + m_dmrNetwork1->write(data); + status[slotNo] = DMRGWS_NETWORK1; + timer[slotNo]->start(); + } + } + } + + if (m_dmrNetwork2 != NULL) { + // Rewrite the slot and/or TG or neither + bool rewritten = false; + for (std::vector::iterator it = m_dmr2RFRewrites.begin(); it != m_dmr2RFRewrites.end(); ++it) { + bool ret = (*it)->process(data); + if (ret) { + rewritten = true; + break; + } + } + + if (rewritten) { + unsigned int slotNo = data.getSlotNo(); + if (status[slotNo] == DMRGWS_NONE || status[slotNo] == DMRGWS_NETWORK2) { + m_dmrNetwork2->write(data); + status[slotNo] = DMRGWS_NETWORK2; + timer[slotNo]->start(); + } + } + } + } + } + + if (m_xlxNetwork != NULL) { + ret = m_xlxNetwork->read(data); + if (ret) { + if (status[m_xlxSlot] == DMRGWS_NONE || status[m_xlxSlot] == DMRGWS_REFLECTOR) { + unsigned int slotNo = data.getSlotNo(); + if (slotNo == XLX_SLOT) { + rptRewrite.process(data); + m_repeater->write(data); + status[m_xlxSlot] = DMRGWS_REFLECTOR; + timer[m_xlxSlot]->start(); + } + } + } + } + + if (m_dmrNetwork1 != NULL) { + ret = m_dmrNetwork1->read(data); + if (ret) { + FLCO flco = data.getFLCO(); + if (flco == FLCO_USER_USER) { + unsigned int slotNo = data.getSlotNo(); + + if (slotNo == 1U && m_dmr1PrivateSlot1) { + m_repeater->write(data); + status[slotNo] = DMRGWS_NETWORK1; + timer[slotNo]->start(); + } else if (slotNo == 2U && m_dmr1PrivateSlot2) { + m_repeater->write(data); + status[slotNo] = DMRGWS_NETWORK1; + timer[slotNo]->start(); } } else { - m_dmrNetwork->write(data); - status = DMRGWS_NETWORK; - timer.start(); - } - } else { - m_dmrNetwork->write(data); - } - } + // Rewrite the slot and/or TG or neither + bool rewritten = false; + for (std::vector::iterator it = m_dmr1NetRewrites.begin(); it != m_dmr1NetRewrites.end(); ++it) { + bool ret = (*it)->process(data); + if (ret) { + rewritten = true; + break; + } + } - ret = m_xlxNetwork->read(data); - if (ret) { - if (status == DMRGWS_NONE || status == DMRGWS_REFLECTOR) { - unsigned int slotNo = data.getSlotNo(); - if (slotNo == XLX_SLOT) { - rptRewrite.process(data); - m_repeater->write(data); - status = DMRGWS_REFLECTOR; - timer.start(); - } - } - } + if (rewritten) { + unsigned int slotNo = data.getSlotNo(); + unsigned int dstId = data.getDstId(); - ret = m_dmrNetwork->read(data); - if (ret) { - unsigned int slotNo = data.getSlotNo(); - if (slotNo == xlxSlot) { - // Stop the DMR network from using the same TG as XLX - unsigned int dstId = data.getDstId(); - FLCO flco = data.getFLCO(); - if (flco != FLCO_GROUP || dstId != xlxTG) { - if (status == DMRGWS_NONE || status == DMRGWS_NETWORK) { - m_repeater->write(data); - status = DMRGWS_NETWORK; - timer.start(); + // Stop the DMR network from using the same TG as XLX after rewriting + if (slotNo != m_xlxSlot || dstId != m_xlxTG) { + if (status[slotNo] == DMRGWS_NONE || status[slotNo] == DMRGWS_NETWORK1) { + m_repeater->write(data); + status[slotNo] = DMRGWS_NETWORK1; + timer[slotNo]->start(); + } + } + } + } + } + } + + if (m_dmrNetwork2 != NULL) { + ret = m_dmrNetwork2->read(data); + if (ret) { + FLCO flco = data.getFLCO(); + if (flco == FLCO_USER_USER) { + unsigned int slotNo = data.getSlotNo(); + + if (slotNo == 1U && m_dmr2PrivateSlot1) { + m_repeater->write(data); + status[slotNo] = DMRGWS_NETWORK2; + timer[slotNo]->start(); + } else if (slotNo == 2U && m_dmr2PrivateSlot2) { + m_repeater->write(data); + status[slotNo] = DMRGWS_NETWORK2; + timer[slotNo]->start(); + } + } else { + // Rewrite the slot and/or TG or neither + bool rewritten = false; + for (std::vector::iterator it = m_dmr2NetRewrites.begin(); it != m_dmr2NetRewrites.end(); ++it) { + bool ret = (*it)->process(data); + if (ret) { + rewritten = true; + break; + } + } + + if (rewritten) { + unsigned int slotNo = data.getSlotNo(); + unsigned int dstId = data.getDstId(); + + // Stop the DMR network from using the same TG as XLX after rewriting + if (slotNo != m_xlxSlot || dstId != m_xlxTG) { + if (status[slotNo] == DMRGWS_NONE || status[slotNo] == DMRGWS_NETWORK2) { + m_repeater->write(data); + status[slotNo] = DMRGWS_NETWORK2; + timer[slotNo]->start(); + } + } } } - } else { - m_repeater->write(data); } } @@ -374,8 +519,8 @@ int CDMRGateway::run() ret = voice->read(data); if (ret) { m_repeater->write(data); - status = DMRGWS_REFLECTOR; - timer.start(); + status[m_xlxSlot] = DMRGWS_REFLECTOR; + timer[m_xlxSlot]->start(); } } @@ -383,16 +528,25 @@ int CDMRGateway::run() stopWatch.start(); m_repeater->clock(ms); - m_dmrNetwork->clock(ms); - m_xlxNetwork->clock(ms); + + if (m_dmrNetwork1 != NULL) + m_dmrNetwork1->clock(ms); + + if (m_dmrNetwork2 != NULL) + m_dmrNetwork2->clock(ms); + + if (m_xlxNetwork != NULL) + m_xlxNetwork->clock(ms); if (voice != NULL) voice->clock(ms); - timer.clock(ms); - if (timer.isRunning() && timer.hasExpired()) { - status = DMRGWS_NONE; - timer.stop(); + for (unsigned int i = 1U; i < 3U; i++) { + timer[i]->clock(ms); + if (timer[i]->isRunning() && timer[i]->hasExpired()) { + status[i] = DMRGWS_NONE; + timer[i]->stop(); + } } if (ms < 10U) @@ -406,11 +560,20 @@ int CDMRGateway::run() m_repeater->close(); delete m_repeater; - m_dmrNetwork->close(); - delete m_dmrNetwork; + if (m_dmrNetwork1 != NULL) { + m_dmrNetwork1->close(); + delete m_dmrNetwork1; + } - m_xlxNetwork->close(); - delete m_xlxNetwork; + if (m_dmrNetwork2 != NULL) { + m_dmrNetwork2->close(); + delete m_dmrNetwork2; + } + + if (m_xlxNetwork != NULL) { + m_xlxNetwork->close(); + delete m_xlxNetwork; + } return 0; } @@ -441,16 +604,16 @@ bool CDMRGateway::createMMDVM() return true; } -bool CDMRGateway::createDMRNetwork() +bool CDMRGateway::createDMRNetwork1() { - std::string address = m_conf.getDMRNetworkAddress(); - unsigned int port = m_conf.getDMRNetworkPort(); - unsigned int local = m_conf.getDMRNetworkLocal(); + std::string address = m_conf.getDMRNetwork1Address(); + unsigned int port = m_conf.getDMRNetwork1Port(); + unsigned int local = m_conf.getDMRNetwork1Local(); unsigned int id = m_repeater->getId(); - std::string password = m_conf.getDMRNetworkPassword(); - bool debug = m_conf.getDMRNetworkDebug(); + std::string password = m_conf.getDMRNetwork1Password(); + bool debug = m_conf.getDMRNetwork1Debug(); - LogInfo("DMR Network Parameters"); + LogInfo("DMR Network 1 Parameters"); LogInfo(" Address: %s", address.c_str()); LogInfo(" Port: %u", port); if (local > 0U) @@ -458,26 +621,100 @@ bool CDMRGateway::createDMRNetwork() else LogInfo(" Local: random"); - m_dmrNetwork = new CDMRNetwork(address, port, local, id, password, "DMR", debug); + m_dmrNetwork1 = new CDMRNetwork(address, port, local, id, password, "DMR", debug); std::string options = m_repeater->getOptions(); if (!options.empty()) { LogInfo(" Options: %s", options.c_str()); - m_dmrNetwork->setOptions(options); + m_dmrNetwork1->setOptions(options); } unsigned char config[400U]; unsigned int len = m_repeater->getConfig(config); - m_dmrNetwork->setConfig(config, len); + m_dmrNetwork1->setConfig(config, len); - bool ret = m_dmrNetwork->open(); + bool ret = m_dmrNetwork1->open(); if (!ret) { - delete m_dmrNetwork; - m_dmrNetwork = NULL; + delete m_dmrNetwork1; + m_dmrNetwork1 = NULL; return false; } + std::vector rewrites = m_conf.getDMRNetwork1Rewrites(); + for (std::vector::const_iterator it = rewrites.begin(); it != rewrites.end(); ++it) { + LogInfo(" Rewrite: %u:%u -> %u:%u", (*it).m_fromSlot, (*it).m_fromTG, (*it).m_toSlot, (*it).m_toTG); + + CRewrite* netRewrite = new CRewrite((*it).m_toSlot, (*it).m_toTG, (*it).m_fromSlot, (*it).m_fromTG); + CRewrite* rfRewrite = new CRewrite((*it).m_fromSlot, (*it).m_fromTG, (*it).m_toSlot, (*it).m_toTG); + + m_dmr1NetRewrites.push_back(netRewrite); + m_dmr1RFRewrites.push_back(rfRewrite); + } + + m_dmr1PrivateSlot1 = m_conf.getDMRNetwork1PrivateSlot1(); + m_dmr1PrivateSlot2 = m_conf.getDMRNetwork1PrivateSlot2(); + + LogInfo(" Private slot 1: %s", m_dmr1PrivateSlot1 ? "yes" : "no"); + LogInfo(" Private slot 2: %s", m_dmr1PrivateSlot2 ? "yes" : "no"); + + return true; +} + +bool CDMRGateway::createDMRNetwork2() +{ + std::string address = m_conf.getDMRNetwork2Address(); + unsigned int port = m_conf.getDMRNetwork2Port(); + unsigned int local = m_conf.getDMRNetwork2Local(); + unsigned int id = m_repeater->getId(); + std::string password = m_conf.getDMRNetwork2Password(); + bool debug = m_conf.getDMRNetwork2Debug(); + + LogInfo("DMR Network 2 Parameters"); + LogInfo(" Address: %s", address.c_str()); + LogInfo(" Port: %u", port); + if (local > 0U) + LogInfo(" Local: %u", local); + else + LogInfo(" Local: random"); + + m_dmrNetwork2 = new CDMRNetwork(address, port, local, id, password, "DMR", debug); + + std::string options = m_repeater->getOptions(); + if (!options.empty()) { + LogInfo(" Options: %s", options.c_str()); + m_dmrNetwork2->setOptions(options); + } + + unsigned char config[400U]; + unsigned int len = m_repeater->getConfig(config); + + m_dmrNetwork2->setConfig(config, len); + + bool ret = m_dmrNetwork2->open(); + if (!ret) { + delete m_dmrNetwork2; + m_dmrNetwork2 = NULL; + return false; + } + + std::vector rewrites = m_conf.getDMRNetwork2Rewrites(); + for (std::vector::const_iterator it = rewrites.begin(); it != rewrites.end(); ++it) { + LogInfo(" Rewrite: %u:%u -> %u:%u", (*it).m_fromSlot, (*it).m_fromTG, (*it).m_toSlot, (*it).m_toTG); + + CRewrite* netRewrite = new CRewrite((*it).m_toSlot, (*it).m_toTG, (*it).m_fromSlot, (*it).m_fromTG); + CRewrite* rfRewrite = new CRewrite((*it).m_fromSlot, (*it).m_fromTG, (*it).m_toSlot, (*it).m_toTG); + + m_dmr2NetRewrites.push_back(netRewrite); + m_dmr2RFRewrites.push_back(rfRewrite); + } + + m_dmr2PrivateSlot1 = m_conf.getDMRNetwork2PrivateSlot1(); + m_dmr2PrivateSlot2 = m_conf.getDMRNetwork2PrivateSlot2(); + + LogInfo(" Private slot 1: %s", m_dmr2PrivateSlot1 ? "yes" : "no"); + LogInfo(" Private slot 2: %s", m_dmr2PrivateSlot2 ? "yes" : "no"); + return true; } @@ -518,5 +755,11 @@ bool CDMRGateway::createXLXNetwork() return false; } + m_xlxSlot = m_conf.getXLXNetworkSlot(); + m_xlxTG = m_conf.getXLXNetworkTG(); + + LogInfo(" Slot: %u", m_xlxSlot); + LogInfo(" TG: %u", m_xlxTG); + return true; } diff --git a/DMRGateway.h b/DMRGateway.h index 8461701..07d94c7 100644 --- a/DMRGateway.h +++ b/DMRGateway.h @@ -22,6 +22,7 @@ #include "RepeaterProtocol.h" #include "MMDVMNetwork.h" #include "DMRNetwork.h" +#include "Rewrite.h" #include "Conf.h" #include @@ -37,12 +38,24 @@ public: private: CConf m_conf; IRepeaterProtocol* m_repeater; - CDMRNetwork* m_dmrNetwork; + CDMRNetwork* m_dmrNetwork1; + CDMRNetwork* m_dmrNetwork2; CDMRNetwork* m_xlxNetwork; unsigned int m_reflector; + unsigned int m_xlxSlot; + unsigned int m_xlxTG; + std::vector m_dmr1NetRewrites; + std::vector m_dmr1RFRewrites; + std::vector m_dmr2NetRewrites; + std::vector m_dmr2RFRewrites; + bool m_dmr1PrivateSlot1; + bool m_dmr1PrivateSlot2; + bool m_dmr2PrivateSlot1; + bool m_dmr2PrivateSlot2; bool createMMDVM(); - bool createDMRNetwork(); + bool createDMRNetwork1(); + bool createDMRNetwork2(); bool createXLXNetwork(); }; diff --git a/DMRGateway.ini b/DMRGateway.ini index 4c6e82f..63d0ef5 100644 --- a/DMRGateway.ini +++ b/DMRGateway.ini @@ -1,6 +1,4 @@ [General] -XLXSlot=2 -XLXTG=9 Timeout=10 RptAddress=127.0.0.1 RptPort=62032 @@ -22,16 +20,34 @@ Language=en_GB Directory=./Audio [XLX Network] +Enabled=1 Address=xlx950.epf.lu Port=62030 # Local=3351 # Options= +Slot=2 +TG=9 Password=passw0rd Debug=0 -[DMR Network] +[DMR Network 1] +Enabled=1 Address=44.131.4.1 Port=62031 # Local=3352 +Rewrite=1,9,1,9 +PrivateSlot1=1 +PrivateSlot2=1 +Password=PASSWORD +Debug=0 + +[DMR Network 2] +Enabled=0 +Address=44.131.4.1 +Port=62031 +# Local=3352 +Rewrite=2,9,2,9 +PrivateSlot1=0 +PrivateSlot2=0 Password=PASSWORD Debug=0 diff --git a/Rewrite.cpp b/Rewrite.cpp index 7b98b8c..349004e 100644 --- a/Rewrite.cpp +++ b/Rewrite.cpp @@ -24,29 +24,38 @@ #include #include -CRewrite::CRewrite(unsigned int slot, unsigned int tg) : -m_slot(slot), -m_tg(tg), +CRewrite::CRewrite(unsigned int fromSlot, unsigned int fromTG, unsigned int toSlot, unsigned int toTG) : +m_fromSlot(fromSlot), +m_fromTG(fromTG), +m_toSlot(toSlot), +m_toTG(toTG), m_lc(NULL), m_embeddedLC() { - assert(slot == 1U || slot == 2U); - assert(tg < 16U); + assert(fromSlot == 1U || fromSlot == 2U); + assert(fromTG < 16U); + assert(toSlot == 1U || toSlot == 2U); + assert(toTG < 16U); } CRewrite::~CRewrite() { } -void CRewrite::process(CDMRData& data) +bool CRewrite::process(CDMRData& data) { - data.setSlotNo(m_slot); - FLCO flco = data.getFLCO(); unsigned int dstId = data.getDstId(); + unsigned int slotNo = data.getSlotNo(); - if (flco == FLCO_GROUP && dstId != m_tg) { - data.setDstId(m_tg); + if (flco != FLCO_GROUP || slotNo != m_fromSlot || dstId != m_fromTG) + return false; + + if (m_fromSlot != m_toSlot) + data.setSlotNo(m_toSlot); + + if (m_fromTG != m_toTG) { + data.setDstId(m_toTG); unsigned char dataType = data.getDataType(); @@ -66,6 +75,8 @@ void CRewrite::process(CDMRData& data) break; } } + + return true; } void CRewrite::processHeader(CDMRData& data, unsigned char dataType) @@ -81,7 +92,7 @@ void CRewrite::processHeader(CDMRData& data, unsigned char dataType) if (m_lc == NULL) return; - m_lc->setDstId(m_tg); + m_lc->setDstId(m_toTG); m_embeddedLC.setLC(*m_lc); @@ -93,7 +104,7 @@ void CRewrite::processHeader(CDMRData& data, unsigned char dataType) void CRewrite::processVoice(CDMRData& data) { if (m_lc == NULL) { - m_lc = new CDMRLC(FLCO_GROUP, data.getSrcId(), m_tg); + m_lc = new CDMRLC(FLCO_GROUP, data.getSrcId(), m_toTG); m_embeddedLC.setLC(*m_lc); } diff --git a/Rewrite.h b/Rewrite.h index cd1f551..a51d928 100644 --- a/Rewrite.h +++ b/Rewrite.h @@ -25,14 +25,16 @@ class CRewrite { public: - CRewrite(unsigned int slot, unsigned int tg); + CRewrite(unsigned int fromSLot, unsigned int fromTG, unsigned int toSlot, unsigned int toTG); ~CRewrite(); - void process(CDMRData& data); + bool process(CDMRData& data); private: - unsigned int m_slot; - unsigned int m_tg; + unsigned int m_fromSlot; + unsigned int m_fromTG; + unsigned int m_toSlot; + unsigned int m_toTG; CDMRLC* m_lc; CDMREmbeddedData m_embeddedLC; diff --git a/Version.h b/Version.h index d51b1f7..cb3e3b7 100644 --- a/Version.h +++ b/Version.h @@ -19,6 +19,6 @@ #if !defined(VERSION_H) #define VERSION_H -const char* VERSION = "20170502"; +const char* VERSION = "20170503"; #endif