diff --git a/DCSHandler.cpp b/DCSHandler.cpp index 86bae5f..7345112 100644 --- a/DCSHandler.cpp +++ b/DCSHandler.cpp @@ -1,7 +1,6 @@ /* - * Copyright (C) 2012-2015 by Jonathan Naylor G4KLX - * Copyright (c) 2017-2018 by Thomas A. Early N7TAE - * Copyright (c) 2021 by Geoffrey Merck F4FXL + * Copyright (C) 2012,2013,2015 by Jonathan Naylor G4KLX + * Copyright (C) 2021 by Geoffrey Merck F4FXL / KC3FRA * * 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 @@ -18,25 +17,33 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include - +#include "RepeaterHandler.h" +#include "DStarDefines.h" #include "DCSHandler.h" #include "Utils.h" +#include "StringUtils.h" +#include "Log.h" + +unsigned int CDCSHandler::m_maxReflectors = 0U; +CDCSHandler** CDCSHandler::m_reflectors = NULL; -CDCSProtocolHandlerPool *CDCSHandler::m_pool = NULL; -CDCSProtocolHandler *CDCSHandler::m_incoming = NULL; +CDCSProtocolHandlerPool* CDCSHandler::m_pool = NULL; +CDCSProtocolHandler* CDCSHandler::m_incoming = NULL; bool CDCSHandler::m_stateChange = false; GATEWAY_TYPE CDCSHandler::m_gatewayType = GT_REPEATER; -CCallsignList *CDCSHandler::m_whiteList = NULL; -CCallsignList *CDCSHandler::m_blackList = NULL; -std::list CDCSHandler::m_DCSHandlers; +CHeaderLogger* CDCSHandler::m_headerLogger = NULL; + +CCallsignList* CDCSHandler::m_whiteList = NULL; +CCallsignList* CDCSHandler::m_blackList = NULL; -CDCSHandler::CDCSHandler(IReflectorCallback *handler, const std::string &dcsHandler, const std::string &repeater, CDCSProtocolHandler *protoHandler, const in_addr &address, unsigned int port, DIRECTION direction) : -m_reflector(dcsHandler), +CDCSHandler::CDCSHandler(IReflectorCallback* handler, const std::string& reflector, const std::string& repeater, CDCSProtocolHandler* protoHandler, const in_addr& address, unsigned int port, DIRECTION direction) : +m_reflector(reflector), +m_xlxReflector(), +m_isXlx(false), m_repeater(repeater), m_handler(protoHandler), m_yourAddress(address), @@ -76,6 +83,11 @@ m_rptCall2() m_linkState = DCS_LINKED; } else { m_linkState = DCS_LINKING; + m_isXlx = m_reflector.substr(0,3) == "XLX"; + if (m_isXlx) { + m_xlxReflector = m_reflector; + m_reflector = "DCS" + m_reflector.substr(3); + } m_tryTimer.start(); } } @@ -86,92 +98,112 @@ CDCSHandler::~CDCSHandler() m_pool->release(m_handler); } -void CDCSHandler::setDCSProtocolHandlerPool(CDCSProtocolHandlerPool *pool) +void CDCSHandler::initialise(unsigned int maxReflectors) +{ + assert(maxReflectors > 0U); + + m_maxReflectors = maxReflectors; + + m_reflectors = new CDCSHandler*[m_maxReflectors]; + for (unsigned int i = 0U; i < m_maxReflectors; i++) + m_reflectors[i] = NULL; +} + +void CDCSHandler::setDCSProtocolHandlerPool(CDCSProtocolHandlerPool* pool) { assert(pool != NULL); m_pool = pool; } -void CDCSHandler::setDCSProtocolIncoming(CDCSProtocolHandler *handler) +void CDCSHandler::setDCSProtocolIncoming(CDCSProtocolHandler* handler) { assert(handler != NULL); m_incoming = handler; } +void CDCSHandler::setHeaderLogger(CHeaderLogger* logger) +{ + m_headerLogger = logger; +} + void CDCSHandler::setGatewayType(GATEWAY_TYPE type) { m_gatewayType = type; } -void CDCSHandler::setWhiteList(CCallsignList *list) +void CDCSHandler::setWhiteList(CCallsignList* list) { assert(list != NULL); m_whiteList = list; } -void CDCSHandler::setBlackList(CCallsignList *list) +void CDCSHandler::setBlackList(CCallsignList* list) { assert(list != NULL); m_blackList = list; } -std::string CDCSHandler::getIncoming(const std::string &callsign) +std::string CDCSHandler::getIncoming(const std::string& callsign) { std::string incoming; - for (auto it=m_DCSHandlers.begin(); it!=m_DCSHandlers.end(); it++) { - CDCSHandler *dcsHandler = *it; - if (dcsHandler->m_direction == DIR_INCOMING && 0==dcsHandler->m_repeater.compare(callsign)) { - incoming.append(dcsHandler->m_reflector); - incoming.append(" "); + for (unsigned int i = 0U; i < m_maxReflectors; i++) { + CDCSHandler* reflector = m_reflectors[i]; + if (reflector != NULL && reflector->m_direction == DIR_INCOMING && reflector->m_repeater == callsign) { + incoming += reflector->m_reflector; + incoming += " "; } } return incoming; } -void CDCSHandler::getInfo(IReflectorCallback *handler, CRemoteRepeaterData &data) +void CDCSHandler::getInfo(IReflectorCallback* handler, CRemoteRepeaterData& data) { assert(handler != NULL); - for (auto it=m_DCSHandlers.begin(); it!=m_DCSHandlers.end(); it++) { - CDCSHandler *dcsHandler = *it; - if (dcsHandler->m_destination == handler) { - if (dcsHandler->m_direction == DIR_INCOMING && 0==dcsHandler->m_repeater.size()) { - if (dcsHandler->m_linkState != DCS_UNLINKING) - data.addLink(dcsHandler->m_reflector, PROTO_DCS, dcsHandler->m_linkState == DCS_LINKED, DIR_INCOMING, true); - } else { - if (dcsHandler->m_linkState != DCS_UNLINKING) - data.addLink(dcsHandler->m_reflector, PROTO_DCS, dcsHandler->m_linkState == DCS_LINKED, dcsHandler->m_direction, false); + for (unsigned int i = 0U; i < m_maxReflectors; i++) { + CDCSHandler* reflector = m_reflectors[i]; + if (reflector != NULL) { + if (reflector->m_destination == handler) { + if (reflector->m_direction == DIR_INCOMING && reflector->m_repeater.empty()) { + if (reflector->m_linkState != DCS_UNLINKING) + data.addLink(GET_DISP_REFLECTOR(reflector), PROTO_DCS, reflector->m_linkState == DCS_LINKED, DIR_INCOMING, true); + } else { + if (reflector->m_linkState != DCS_UNLINKING) + data.addLink(GET_DISP_REFLECTOR(reflector), PROTO_DCS, reflector->m_linkState == DCS_LINKED, reflector->m_direction, false); + } } } } } -void CDCSHandler::process(CAMBEData &data) +void CDCSHandler::process(CAMBEData& data) { in_addr yourAddress = data.getYourAddress(); unsigned int yourPort = data.getYourPort(); unsigned int myPort = data.getMyPort(); - for (auto it=m_DCSHandlers.begin(); it!=m_DCSHandlers.end(); it++) { - CDCSHandler *dcsHandler = *it; - if ( dcsHandler->m_yourAddress.s_addr == yourAddress.s_addr && - dcsHandler->m_yourPort == yourPort && - dcsHandler->m_myPort == myPort) { - dcsHandler->processInt(data); - return; + for (unsigned int i = 0U; i < m_maxReflectors; i++) { + CDCSHandler* reflector = m_reflectors[i]; + if (reflector != NULL) { + if (reflector->m_yourAddress.s_addr == yourAddress.s_addr && + reflector->m_yourPort == yourPort && + reflector->m_myPort == myPort) { + reflector->processInt(data); + return; + } } - } + } } -void CDCSHandler::process(CPollData &poll) +void CDCSHandler::process(CPollData& poll) { - std::string dcsHandler = poll.getData1(); + std::string reflector = poll.getData1(); std::string repeater = poll.getData2(); in_addr yourAddress = poll.getYourAddress(); unsigned int yourPort = poll.getYourPort(); @@ -179,112 +211,180 @@ void CDCSHandler::process(CPollData &poll) unsigned int length = poll.getLength(); // Check to see if we already have a link - for (auto it=m_DCSHandlers.begin(); it!=m_DCSHandlers.end(); it++) { - CDCSHandler *handler = *it; - if ( 0==handler->m_reflector.compare(dcsHandler) && - 0==handler->m_repeater.compare(repeater) && - handler->m_yourAddress.s_addr == yourAddress.s_addr && - handler->m_yourPort == yourPort && - handler->m_myPort == myPort && - handler->m_direction == DIR_OUTGOING && - handler->m_linkState == DCS_LINKED && - length == 22U) { - handler->m_pollInactivityTimer.start(); - CPollData reply(handler->m_repeater, handler->m_reflector, handler->m_direction, handler->m_yourAddress, handler->m_yourPort); - handler->m_handler->writePoll(reply); - return; - } else if (0==handler->m_reflector.compare(0, LONG_CALLSIGN_LENGTH - 1U, dcsHandler, 0, LONG_CALLSIGN_LENGTH - 1U) && - handler->m_yourAddress.s_addr == yourAddress.s_addr && - handler->m_yourPort == yourPort && - handler->m_myPort == myPort && - handler->m_direction == DIR_INCOMING && - handler->m_linkState == DCS_LINKED && - length == 17U) { - handler->m_pollInactivityTimer.start(); - return; + for (unsigned int i = 0U; i < m_maxReflectors; i++) { + CDCSHandler* handler = m_reflectors[i]; + + if (handler != NULL) { + if (handler->m_reflector == reflector && + handler->m_repeater == repeater && + handler->m_yourAddress.s_addr == yourAddress.s_addr && + handler->m_yourPort == yourPort && + handler->m_myPort == myPort && + handler->m_direction == DIR_OUTGOING && + handler->m_linkState == DCS_LINKED && + length == 22U) { + handler->m_pollInactivityTimer.start(); + CPollData reply(handler->m_repeater, handler->m_reflector, handler->m_direction, handler->m_yourAddress, handler->m_yourPort); + handler->m_handler->writePoll(reply); + return; + } else if (handler->m_reflector.substr(0, LONG_CALLSIGN_LENGTH - 1U) == reflector.substr(0, LONG_CALLSIGN_LENGTH - 1U) && + handler->m_yourAddress.s_addr == yourAddress.s_addr && + handler->m_yourPort == yourPort && + handler->m_myPort == myPort && + handler->m_direction == DIR_INCOMING && + handler->m_linkState == DCS_LINKED && + length == 17U) { + handler->m_pollInactivityTimer.start(); + return; + } } } - printf("Unknown incoming DCS poll from %s\n", dcsHandler.c_str()); + wxLogMessage("Unknown incoming DCS poll from %s", reflector.c_str()); } -void CDCSHandler::process(CConnectData &connect) +void CDCSHandler::process(CConnectData& connect) { CD_TYPE type = connect.getType(); if (type == CT_ACK || type == CT_NAK || type == CT_UNLINK) { - for (auto it=m_DCSHandlers.begin(); it!=m_DCSHandlers.end(); ) { - CDCSHandler *dcsHandler = *it; - bool res = dcsHandler->processInt(connect, type); - if (res) { - delete dcsHandler; - it = m_DCSHandlers.erase(it); - } else - it++; + for (unsigned int i = 0U; i < m_maxReflectors; i++) { + if (m_reflectors[i] != NULL) { + bool res = m_reflectors[i]->processInt(connect, type); + if (res) { + delete m_reflectors[i]; + m_reflectors[i] = NULL; + } + } } + return; } // else if type == CT_LINK1 or type == CT_LINK2 - // someone tried to link directly to a Smart Group! - printf("CDCSHandler::process(CConnectData) type=CT_LINK%c, from repeater=%s\n", (type==CT_LINK1) ? '1' : '2', connect.getRepeater().c_str()); + in_addr yourAddress = connect.getYourAddress(); + unsigned int yourPort = connect.getYourPort(); + unsigned int myPort = connect.getMyPort(); + + std::string repeaterCallsign = connect.getRepeater(); + std::string reflectorCallsign = connect.getReflector(); + + // Check that it isn't a duplicate + for (unsigned int i = 0U; i < m_maxReflectors; i++) { + if (m_reflectors[i] != NULL) { + if (m_reflectors[i]->m_direction == DIR_INCOMING && + m_reflectors[i]->m_yourAddress.s_addr == yourAddress.s_addr && + m_reflectors[i]->m_yourPort == yourPort && + m_reflectors[i]->m_myPort == myPort && + m_reflectors[i]->m_repeater == reflectorCallsign && + m_reflectors[i]->m_reflector == repeaterCallsign) + return; + } + } + + // Check the validity of our repeater callsign + IReflectorCallback* handler = CRepeaterHandler::findDVRepeater(reflectorCallsign); + if (handler == NULL) { + wxLogMessage("DCS connect to unknown reflector %s from %s", reflectorCallsign.c_str(), repeaterCallsign.c_str()); + CConnectData reply(repeaterCallsign, reflectorCallsign, CT_NAK, connect.getYourAddress(), connect.getYourPort()); + m_incoming->writeConnect(reply); + return; + } + + // A new connect packet indicates the need for a new entry + wxLogMessage("New incoming DCS link to %s from %s", reflectorCallsign.c_str(), repeaterCallsign.c_str()); + + CDCSHandler* dcs = new CDCSHandler(handler, repeaterCallsign, reflectorCallsign, m_incoming, yourAddress, yourPort, DIR_INCOMING); + + bool found = false; + for (unsigned int i = 0U; i < m_maxReflectors; i++) { + if (m_reflectors[i] == NULL) { + m_reflectors[i] = dcs; + found = true; + break; + } + } + + if (found) { + CConnectData reply(repeaterCallsign, reflectorCallsign, CT_ACK, yourAddress, yourPort); + m_incoming->writeConnect(reply); + } else { + CConnectData reply(repeaterCallsign, reflectorCallsign, CT_NAK, yourAddress, yourPort); + m_incoming->writeConnect(reply); + + wxLogError("No space to add new DCS link, ignoring"); + delete dcs; + } } -void CDCSHandler::link(IReflectorCallback *handler, const std::string &repeater, const std::string &gateway, const in_addr &address) +void CDCSHandler::link(IReflectorCallback* handler, const std::string& repeater, const std::string &gateway, const in_addr& address) { - // if the handler is currently unlinking, quit! - for (auto it=m_DCSHandlers.begin(); it!=m_DCSHandlers.end(); it++) { - CDCSHandler *dcsHandler = *it; - if (dcsHandler->m_direction == DIR_OUTGOING && dcsHandler->m_destination == handler && dcsHandler->m_linkState != DCS_UNLINKING) - return; - } + for (unsigned int i = 0U; i < m_maxReflectors; i++) { + if (m_reflectors[i] != NULL) { + if (m_reflectors[i]->m_direction == DIR_OUTGOING && m_reflectors[i]->m_destination == handler && m_reflectors[i]->m_linkState != DCS_UNLINKING) + return; + } + } - CDCSProtocolHandler *protoHandler = m_pool->getHandler(); + CDCSProtocolHandler* protoHandler = m_pool->getHandler(); if (protoHandler == NULL) return; - CDCSHandler *dcs = new CDCSHandler(handler, gateway, repeater, protoHandler, address, DCS_PORT, DIR_OUTGOING); - if (dcs) { - m_DCSHandlers.push_back(dcs); + CDCSHandler* dcs = new CDCSHandler(handler, gateway, repeater, protoHandler, address, DCS_PORT, DIR_OUTGOING); + + bool found = false; + + for (unsigned int i = 0U; i < m_maxReflectors; i++) { + if (m_reflectors[i] == NULL) { + m_reflectors[i] = dcs; + found = true; + break; + } + } + + if (found) { CConnectData reply(m_gatewayType, repeater, gateway, CT_LINK1, address, DCS_PORT); protoHandler->writeConnect(reply); + } else { + wxLogError("No space to add new DCS link, ignoring"); + delete dcs; } } -void CDCSHandler::unlink(IReflectorCallback *handler, const std::string &callsign, bool exclude) +void CDCSHandler::unlink(IReflectorCallback* handler, const std::string& callsign, bool exclude) { - for (auto it=m_DCSHandlers.begin(); it!=m_DCSHandlers.end(); it++) { - CDCSHandler *dcsHandler = *it; + for (unsigned int i = 0U; i < m_maxReflectors; i++) { + CDCSHandler* reflector = m_reflectors[i]; - if (dcsHandler != NULL) { + if (reflector != NULL) { bool found = false; if (exclude) { - if (dcsHandler->m_direction == DIR_OUTGOING && dcsHandler->m_destination == handler && dcsHandler->m_reflector.compare(callsign)) { - printf("Removing outgoing DCS link %s, %s\n", dcsHandler->m_repeater.c_str(), dcsHandler->m_reflector.c_str()); + if (reflector->m_direction == DIR_OUTGOING && reflector->m_destination == handler && reflector->m_reflector != callsign) { + wxLogMessage("Removing outgoing DCS link %s, %s", reflector->m_repeater.c_str(), reflector->m_reflector.c_str()); - if (dcsHandler->m_linkState == DCS_LINKING || dcsHandler->m_linkState == DCS_LINKED) { - CConnectData connect(dcsHandler->m_repeater, dcsHandler->m_reflector, CT_UNLINK, dcsHandler->m_yourAddress, dcsHandler->m_yourPort); - dcsHandler->m_handler->writeConnect(connect); + if (reflector->m_linkState == DCS_LINKING || reflector->m_linkState == DCS_LINKED) { + CConnectData connect(reflector->m_repeater, reflector->m_reflector, CT_UNLINK, reflector->m_yourAddress, reflector->m_yourPort); + reflector->m_handler->writeConnect(connect); - dcsHandler->m_linkState = DCS_UNLINKING; - dcsHandler->m_tryTimer.start(1U); - dcsHandler->m_tryCount = 0U; + reflector->m_linkState = DCS_UNLINKING; + reflector->m_tryTimer.start(1U); + reflector->m_tryCount = 0U; } found = true; } } else { - if (dcsHandler->m_destination == handler && 0==dcsHandler->m_reflector.compare(callsign)) { - printf("Removing DCS link %s, %s\n", dcsHandler->m_repeater.c_str(), dcsHandler->m_reflector.c_str()); + if (reflector->m_destination == handler && reflector->m_reflector == callsign) { + wxLogMessage("Removing DCS link %s, %s", reflector->m_repeater.c_str(), reflector->m_reflector.c_str()); - if (dcsHandler->m_linkState == DCS_LINKING || dcsHandler->m_linkState == DCS_LINKED) { - CConnectData connect(dcsHandler->m_repeater, dcsHandler->m_reflector, CT_UNLINK, dcsHandler->m_yourAddress, dcsHandler->m_yourPort); - dcsHandler->m_handler->writeConnect(connect); + if (reflector->m_linkState == DCS_LINKING || reflector->m_linkState == DCS_LINKED) { + CConnectData connect(reflector->m_repeater, reflector->m_reflector, CT_UNLINK, reflector->m_yourAddress, reflector->m_yourPort); + reflector->m_handler->writeConnect(connect); - dcsHandler->m_linkState = DCS_UNLINKING; - dcsHandler->m_tryTimer.start(1U); - dcsHandler->m_tryCount = 0U; + reflector->m_linkState = DCS_UNLINKING; + reflector->m_tryTimer.start(1U); + reflector->m_tryCount = 0U; } found = true; @@ -293,8 +393,8 @@ void CDCSHandler::unlink(IReflectorCallback *handler, const std::string &callsig // If an active link with incoming traffic, send an EOT to the repeater if (found) { - if (dcsHandler->m_dcsId != 0x00U) { - unsigned int seq = dcsHandler->m_dcsSeq + 1U; + if (reflector->m_dcsId != 0x00U) { + unsigned int seq = reflector->m_dcsSeq + 1U; if (seq == 21U) seq = 0U; @@ -302,82 +402,78 @@ void CDCSHandler::unlink(IReflectorCallback *handler, const std::string &callsig data.setData(END_PATTERN_BYTES, DV_FRAME_LENGTH_BYTES); data.setSeq(seq); data.setEnd(true); - data.setId(dcsHandler->m_dcsId); + data.setId(reflector->m_dcsId); - dcsHandler->m_destination->process(data, dcsHandler->m_direction, AS_DCS); + reflector->m_destination->process(data, reflector->m_direction, AS_DCS); } m_stateChange = true; } } - } + } } -void CDCSHandler::unlink(CDCSHandler *dcsHandler) +void CDCSHandler::unlink() { - if (dcsHandler != NULL) { - if (dcsHandler->m_repeater.size()) { - printf("Unlinking from DCS dcsHandler %s\n", dcsHandler->m_reflector.c_str()); - - CConnectData connect(dcsHandler->m_repeater, dcsHandler->m_reflector, CT_UNLINK, dcsHandler->m_yourAddress, dcsHandler->m_yourPort); - dcsHandler->m_handler->writeConnect(connect); + for (unsigned int i = 0U; i < m_maxReflectors; i++) { + CDCSHandler* reflector = m_reflectors[i]; - dcsHandler->m_linkState = DCS_UNLINKING; - dcsHandler->m_tryTimer.start(1U); - dcsHandler->m_tryCount = 0U; - } - } + if (reflector != NULL) { + if (!reflector->m_repeater.empty()) { + wxLogMessage("Unlinking from DCS reflector %s", reflector->m_reflector.c_str()); -} + CConnectData connect(reflector->m_repeater, reflector->m_reflector, CT_UNLINK, reflector->m_yourAddress, reflector->m_yourPort); + reflector->m_handler->writeConnect(connect); -void CDCSHandler::unlink() -{ - for (auto it=m_DCSHandlers.begin(); it!=m_DCSHandlers.end(); it++) { - CDCSHandler* dcsHandler = *it; - CDCSHandler::unlink(dcsHandler); - } + reflector->m_linkState = DCS_UNLINKING; + reflector->m_tryTimer.start(1U); + reflector->m_tryCount = 0U; + } + } + } } -void CDCSHandler::writeHeader(IReflectorCallback *handler, CHeaderData &header, DIRECTION direction) +void CDCSHandler::writeHeader(IReflectorCallback* handler, CHeaderData& header, DIRECTION direction) { - for (auto it=m_DCSHandlers.begin(); it!=m_DCSHandlers.end(); it++) { - CDCSHandler *dcsHandler = *it; - dcsHandler->writeHeaderInt(handler, header, direction); - } + for (unsigned int i = 0U; i < m_maxReflectors; i++) { + if (m_reflectors[i] != NULL) + m_reflectors[i]->writeHeaderInt(handler, header, direction); + } } -void CDCSHandler::writeAMBE(IReflectorCallback *handler, CAMBEData &data, DIRECTION direction) +void CDCSHandler::writeAMBE(IReflectorCallback* handler, CAMBEData& data, DIRECTION direction) { - for (auto it=m_DCSHandlers.begin(); it!=m_DCSHandlers.end(); it++) { - CDCSHandler *dcsHandler = *it; - dcsHandler->writeAMBEInt(handler, data, direction); - } + for (unsigned int i = 0U; i < m_maxReflectors; i++) { + if (m_reflectors[i] != NULL) + m_reflectors[i]->writeAMBEInt(handler, data, direction); + } } -void CDCSHandler::gatewayUpdate(const std::string &dcsHandler, const std::string &address) +void CDCSHandler::gatewayUpdate(const std::string& reflector, const std::string& address) { - std::string gateway = dcsHandler; - gateway.resize(LONG_CALLSIGN_LENGTH - 1U, ' '); - - for (auto it=m_DCSHandlers.begin(); it!=m_DCSHandlers.end(); it++) { - CDCSHandler *dcsHandler = *it; - if (0 == dcsHandler->m_reflector.compare(0, LONG_CALLSIGN_LENGTH - 1U, gateway)) { - if (address.size()) { - // A new address, change the value - printf("Changing IP address of DCS gateway or dcsHandler %s to %s\n", dcsHandler->m_reflector.c_str(), address.c_str()); - dcsHandler->m_yourAddress.s_addr = ::inet_addr(address.c_str()); - } else { - printf("IP address for DCS gateway or dcsHandler %s has been removed\n", dcsHandler->m_reflector.c_str()); - - // No address, this probably shouldn't happen.... - if (dcsHandler->m_direction == DIR_OUTGOING && dcsHandler->m_destination != NULL) - dcsHandler->m_destination->linkFailed(DP_DCS, dcsHandler->m_reflector, false); - - m_stateChange = true; - - delete dcsHandler; - it = m_DCSHandlers.erase(it); - it--; + std::string gateway = reflector; + gateway.resize(LONG_CALLSIGN_LENGTH - 1U); + + for (unsigned int i = 0U; i < m_maxReflectors; i++) { + CDCSHandler* reflector = m_reflectors[i]; + if (reflector != NULL) { + if (reflector->m_reflector.substr(0, LONG_CALLSIGN_LENGTH - 1U) == gateway) { + if (!address.empty()) { + // A new address, change the value + wxLogMessage("Changing IP address of DCS gateway or reflector %s to %s", reflector->m_reflector.c_str(), address.c_str()); + reflector->m_yourAddress.s_addr = ::inet_addr(address.c_str()); + } else { + wxLogMessage("IP address for DCS gateway or reflector %s has been removed", reflector->m_reflector.c_str()); + + // No address, this probably shouldn't happen.... + if (reflector->m_direction == DIR_OUTGOING && reflector->m_destination != NULL) + reflector->m_destination->linkFailed(DP_DCS, reflector->m_reflector, false); + + m_stateChange = true; + + delete m_reflectors[i]; + m_reflectors[i] = NULL; + } } } } @@ -385,27 +481,26 @@ void CDCSHandler::gatewayUpdate(const std::string &dcsHandler, const std::string void CDCSHandler::clock(unsigned int ms) { - for (auto it=m_DCSHandlers.begin(); it!=m_DCSHandlers.end(); ) { - CDCSHandler *handler = *it; - bool ret = handler->clockInt(ms); - if (ret) { - delete handler; - it = m_DCSHandlers.erase(it); - } else - it++; + for (unsigned int i = 0U; i < m_maxReflectors; i++) { + if (m_reflectors[i] != NULL) { + bool ret = m_reflectors[i]->clockInt(ms); + if (ret) { + delete m_reflectors[i]; + m_reflectors[i] = NULL; + } + } } } void CDCSHandler::finalise() { - for (auto it=m_DCSHandlers.begin(); it!=m_DCSHandlers.end(); ) { - CDCSHandler *handler = *it; - delete handler; - it = m_DCSHandlers.erase(it); - } + for (unsigned int i = 0U; i < m_maxReflectors; i++) + delete m_reflectors[i]; + + delete[] m_reflectors; } -void CDCSHandler::processInt(CAMBEData &data) +void CDCSHandler::processInt(CAMBEData& data) { // Make a copy of the AMBE data so that any changes made here don't modify the original CAMBEData temp(data); @@ -420,7 +515,7 @@ void CDCSHandler::processInt(CAMBEData &data) if (m_whiteList != NULL) { bool res = m_whiteList->isInList(my); if (!res) { - printf("%s rejected from DCS as not found in the white list\n", my.c_str()); + wxLogMessage("%s rejected from DCS as not found in the white list", my.c_str()); m_dcsId = 0x00U; return; } @@ -429,7 +524,7 @@ void CDCSHandler::processInt(CAMBEData &data) if (m_blackList != NULL) { bool res = m_blackList->isInList(my); if (res) { - printf("%s rejected from DCS as found in the black list\n", my.c_str()); + wxLogMessage("%s rejected from DCS as found in the black list", my.c_str()); m_dcsId = 0x00U; return; } @@ -440,13 +535,17 @@ void CDCSHandler::processInt(CAMBEData &data) switch (m_direction) { case DIR_OUTGOING: - if (m_reflector.compare(rpt2)) + if (m_reflector != (rpt2)) return; if (m_dcsId == 0x00U && seqNo != 0U) return; if (m_dcsId == 0x00U) { // && seqNo == 0U) { + // Write to Header.log if it's enabled + if (m_headerLogger != NULL) + m_headerLogger->write("DCS", header); + m_dcsId = id; m_dcsSeq = 0x00U; m_inactivityTimer.start(); @@ -456,7 +555,7 @@ void CDCSHandler::processInt(CAMBEData &data) m_destination->process(header, m_direction, AS_DCS); } - + if (id == m_dcsId) { m_pollInactivityTimer.start(); m_inactivityTimer.start(); @@ -482,13 +581,17 @@ void CDCSHandler::processInt(CAMBEData &data) break; case DIR_INCOMING: - if (m_repeater.compare(rpt2)) + if (m_repeater != rpt2) return; if (m_dcsId == 0x00U && seqNo != 0U) return; if (m_dcsId == 0x00U) { // && seqNo == 0U) { + // Write to Header.log if it's enabled + if (m_headerLogger != NULL) + m_headerLogger->write(wxT("DCS"), header); + m_dcsId = id; m_dcsSeq = 0x00U; m_inactivityTimer.start(); @@ -525,26 +628,26 @@ void CDCSHandler::processInt(CAMBEData &data) } } -bool CDCSHandler::processInt(CConnectData &connect, CD_TYPE type) +bool CDCSHandler::processInt(CConnectData& connect, CD_TYPE type) { in_addr yourAddress = connect.getYourAddress(); unsigned int yourPort = connect.getYourPort(); unsigned int myPort = connect.getMyPort(); - std::string repeater = connect.getRepeater(); + std::string repeater = connect.getRepeater(); if (m_yourAddress.s_addr != yourAddress.s_addr || m_yourPort != yourPort || m_myPort != myPort) return false; switch (type) { case CT_ACK: - if (m_repeater.compare(repeater)) + if (m_repeater != repeater) return false; if (m_linkState == DCS_LINKING) { - printf("DCS ACK message received from %s\n", m_reflector.c_str()); + wxLogMessage("DCS ACK message received from %s", GET_DISP_REFLECTOR(this).c_str()); if (m_direction == DIR_OUTGOING && m_destination != NULL) - m_destination->linkUp(DP_DCS, m_reflector); + m_destination->linkUp(DP_DCS, GET_DISP_REFLECTOR(this)); m_tryTimer.stop(); m_stateChange = true; @@ -554,20 +657,20 @@ bool CDCSHandler::processInt(CConnectData &connect, CD_TYPE type) return false; case CT_NAK: - if (m_repeater.compare(repeater)) + if (m_repeater != repeater) return false; if (m_linkState == DCS_LINKING) { - printf("DCS NAK message received from %s\n", m_reflector.c_str()); + wxLogMessage("DCS NAK message received from %s", GET_DISP_REFLECTOR(this).c_str()); if (m_direction == DIR_OUTGOING && m_destination != NULL) - m_destination->linkRefused(DP_DCS, m_reflector); + m_destination->linkRefused(DP_DCS, GET_DISP_REFLECTOR(this)); return true; } if (m_linkState == DCS_UNLINKING) { - printf("DCS NAK message received from %s\n", m_reflector.c_str()); + wxLogMessage("DCS NAK message received from %s", GET_DISP_REFLECTOR(this).c_str()); if (m_direction == DIR_OUTGOING && m_destination != NULL) m_destination->linkFailed(DP_DCS, m_reflector, false); @@ -578,14 +681,14 @@ bool CDCSHandler::processInt(CConnectData &connect, CD_TYPE type) return false; case CT_UNLINK: - if (m_reflector.compare(repeater)) + if (m_reflector != repeater) return false; if (m_linkState == DCS_LINKED) { - printf("DCS disconnect message received from %s\n", m_reflector.c_str()); + wxLogMessage("DCS disconnect message received from %s", GET_DISP_REFLECTOR(this).c_str()); if (m_direction == DIR_OUTGOING && m_destination != NULL) - m_destination->linkFailed(DP_DCS, m_reflector, false); + m_destination->linkFailed(DP_DCS, GET_DISP_REFLECTOR(this), false); m_stateChange = true; } @@ -613,20 +716,20 @@ bool CDCSHandler::clockInt(unsigned int ms) switch (m_linkState) { case DCS_LINKING: - printf("DCS link to %s has failed to connect\n", m_reflector.c_str()); + wxLogMessage("DCS link to %s has failed to connect", GET_DISP_REFLECTOR(this).c_str()); break; case DCS_LINKED: - printf("DCS link to %s has failed (poll inactivity)\n", m_reflector.c_str()); + wxLogMessage("DCS link to %s has failed (poll inactivity)", GET_DISP_REFLECTOR(this).c_str()); break; case DCS_UNLINKING: - printf("DCS link to %s has failed to disconnect cleanly\n", m_reflector.c_str()); + wxLogMessage("DCS link to %s has failed to disconnect cleanly", GET_DISP_REFLECTOR(this).c_str()); break; default: break; } if (m_direction == DIR_OUTGOING) { - bool reconnect = m_destination->linkFailed(DP_DCS, m_reflector, true); + bool reconnect = m_destination->linkFailed(DP_DCS, GET_DISP_REFLECTOR(this), true); if (reconnect) { CConnectData reply(m_gatewayType, m_repeater, m_reflector, CT_LINK1, m_yourAddress, m_yourPort); m_handler->writeConnect(reply); @@ -676,7 +779,7 @@ bool CDCSHandler::clockInt(unsigned int ms) return false; } -void CDCSHandler::writeHeaderInt(IReflectorCallback *handler, CHeaderData& header, DIRECTION direction) +void CDCSHandler::writeHeaderInt(IReflectorCallback* handler, CHeaderData& header, DIRECTION direction) { if (m_linkState != DCS_LINKED) return; @@ -701,7 +804,7 @@ void CDCSHandler::writeHeaderInt(IReflectorCallback *handler, CHeaderData& heade m_rptCall2 = header.getRptCall2(); } -void CDCSHandler::writeAMBEInt(IReflectorCallback *handler, CAMBEData &data, DIRECTION direction) +void CDCSHandler::writeAMBEInt(IReflectorCallback* handler, CAMBEData& data, DIRECTION direction) { if (m_linkState != DCS_LINKED) return; @@ -738,28 +841,34 @@ bool CDCSHandler::stateChange() return stateChange; } -void CDCSHandler::writeStatus(FILE *file) +void CDCSHandler::writeStatus(std::ofstream& file) { - for (auto it=m_DCSHandlers.begin(); it!=m_DCSHandlers.end(); it++) { - CDCSHandler *dcsHandler = *it; - struct tm *tm = ::gmtime(&dcsHandler->m_time); - - switch (dcsHandler->m_direction) { - case DIR_OUTGOING: - if (dcsHandler->m_linkState == DCS_LINKED) { - fprintf(file, "%04d-%02d-%02d %02d:%02d:%02d: DCS link - Type: Repeater Rptr: %s Refl: %s Dir: Outgoing\n", - tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, - dcsHandler->m_repeater.c_str(), dcsHandler->m_reflector.c_str()); - } - break; - - case DIR_INCOMING: - if (dcsHandler->m_linkState == DCS_LINKED) { - fprintf(file, "%04d-%02d-%02d %02d:%02d:%02d: DCS link - Type: Repeater Rptr: %s Refl: %s Dir: Incoming\n", - tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, - dcsHandler->m_repeater.c_str(), dcsHandler->m_reflector.c_str()); - } - break; + for (unsigned int i = 0U; i < m_maxReflectors; i++) { + CDCSHandler* reflector = m_reflectors[i]; + if (reflector != NULL) { + struct tm* tm = ::gmtime(&reflector->m_time); + + switch (reflector->m_direction) { + case DIR_OUTGOING: + if (reflector->m_linkState == DCS_LINKED) { + std::string text; + text = string_format("%04d-%02d-%02d %02d:%02d:%02d: DCS link - Type: Repeater Rptr: %s Refl: %s Dir: Outgoing\n", + tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, + reflector->m_repeater.c_str(), GET_DISP_REFLECTOR(reflector).c_str()); + file << text; + } + break; + + case DIR_INCOMING: + if (reflector->m_linkState == DCS_LINKED) { + std::string text; + text = string_format("%04d-%02d-%02d %02d:%02d:%02d: DCS link - Type: Repeater Rptr: %s Refl: %s Dir: Incoming\n", + tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, + reflector->m_repeater.c_str(), GET_DISP_REFLECTOR(reflector).c_str()); + file << text; + } + break; + } } } } diff --git a/DCSHandler.h b/DCSHandler.h index 1be1b7b..bb50f5e 100644 --- a/DCSHandler.h +++ b/DCSHandler.h @@ -1,7 +1,6 @@ /* * Copyright (C) 2012,2013,2015 by Jonathan Naylor G4KLX - * Copyright (c) 2017-2018 by Thomas A. Early N7TAE - * Copyright (c) 2021 by Geoffrey Merck F4FXL / KC3FRA + * Copyright (C) 2021 by Geoffrey Merck F4FXL / KC3FRA * * 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 @@ -18,17 +17,18 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#pragma once +#ifndef DCSHandler_H +#define DCSHandler_H #include #include -#include -#include +#include +#include #include "DCSProtocolHandlerPool.h" -#include "RemoteRepeaterData.h" #include "ReflectorCallback.h" #include "DStarDefines.h" +#include "HeaderLogger.h" #include "CallsignList.h" #include "ConnectData.h" #include "AMBEData.h" @@ -36,6 +36,8 @@ #include "Timer.h" #include "Defs.h" +#define GET_DISP_REFLECTOR(refl) (refl->m_isXlx ? refl->m_xlxReflector : refl->m_reflector) + enum DCS_STATE { DCS_LINKING, DCS_LINKED, @@ -44,71 +46,78 @@ enum DCS_STATE { class CDCSHandler { public: - static void setDCSProtocolHandlerPool(CDCSProtocolHandlerPool *pool); - static void setDCSProtocolIncoming(CDCSProtocolHandler *handler); + static void initialise(unsigned int maxReflectors); + + static void setDCSProtocolHandlerPool(CDCSProtocolHandlerPool* pool); + static void setDCSProtocolIncoming(CDCSProtocolHandler* handler); + static void setHeaderLogger(CHeaderLogger* logger); static void setGatewayType(GATEWAY_TYPE type); - static void link(IReflectorCallback *handler, const std::string &repeater, const std::string &reflector, const in_addr &address); - static void unlink(IReflectorCallback *handler, const std::string &reflector = std::string(""), bool exclude = true); - static void unlink(CDCSHandler *reflector); + static void link(IReflectorCallback* handler, const std::string& repeater, const std::string& reflector, const in_addr& address); + static void unlink(IReflectorCallback* handler, const std::string& reflector = "", bool exclude = true); static void unlink(); - static void writeHeader(IReflectorCallback *handler, CHeaderData &header, DIRECTION direction); - static void writeAMBE(IReflectorCallback *handler, CAMBEData &data, DIRECTION direction); + static void writeHeader(IReflectorCallback* handler, CHeaderData& header, DIRECTION direction); + static void writeAMBE(IReflectorCallback* handler, CAMBEData& data, DIRECTION direction); - static void process(CAMBEData &header); - static void process(CPollData &data); - static void process(CConnectData &connect); + static void process(CAMBEData& header); + static void process(CPollData& data); + static void process(CConnectData& connect); - static void gatewayUpdate(const std::string &reflector, const std::string &address); + static void gatewayUpdate(const std::string& reflector, const std::string& address); static void clock(unsigned int ms); static bool stateChange(); - static void writeStatus(FILE *file); + static void writeStatus(std::ofstream& file); - static void setWhiteList(CCallsignList *list); - static void setBlackList(CCallsignList *list); + static void setWhiteList(CCallsignList* list); + static void setBlackList(CCallsignList* list); static void finalise(); - static void getInfo(IReflectorCallback *handler, CRemoteRepeaterData &data); + static void getInfo(IReflectorCallback* handler, CRemoteRepeaterData& data); - static std::string getIncoming(const std::string &callsign); + static std::string getIncoming(const std::string& callsign); protected: - CDCSHandler(IReflectorCallback *handler, const std::string &reflector, const std::string &repeater, CDCSProtocolHandler *protoHandler, const in_addr &address, unsigned int port, DIRECTION direction); + CDCSHandler(IReflectorCallback* handler, const std::string& reflector, const std::string& repeater, CDCSProtocolHandler* protoHandler, const in_addr& address, unsigned int port, DIRECTION direction); ~CDCSHandler(); - void processInt(CAMBEData &data); - bool processInt(CConnectData &connect, CD_TYPE type); + void processInt(CAMBEData& data); + bool processInt(CConnectData& connect, CD_TYPE type); - void writeHeaderInt(IReflectorCallback *handler, CHeaderData &header, DIRECTION direction); - void writeAMBEInt(IReflectorCallback *handler, CAMBEData &data, DIRECTION direction); + void writeHeaderInt(IReflectorCallback* handler, CHeaderData& header, DIRECTION direction); + void writeAMBEInt(IReflectorCallback* handler, CAMBEData& data, DIRECTION direction); bool clockInt(unsigned int ms); private: - static std::list m_DCSHandlers; + static unsigned int m_maxReflectors; + static CDCSHandler** m_reflectors; - static CDCSProtocolHandlerPool *m_pool; - static CDCSProtocolHandler *m_incoming; + static CDCSProtocolHandlerPool* m_pool; + static CDCSProtocolHandler* m_incoming; static bool m_stateChange; static GATEWAY_TYPE m_gatewayType; - static CCallsignList *m_whiteList; - static CCallsignList *m_blackList; + static CHeaderLogger* m_headerLogger; - std::string m_reflector; - std::string m_repeater; - CDCSProtocolHandler *m_handler; + static CCallsignList* m_whiteList; + static CCallsignList* m_blackList; + + std::string m_reflector; + std::string m_xlxReflector; + bool m_isXlx; + std::string m_repeater; + CDCSProtocolHandler* m_handler; in_addr m_yourAddress; unsigned int m_yourPort; unsigned int m_myPort; DIRECTION m_direction; DCS_STATE m_linkState; - IReflectorCallback *m_destination; + IReflectorCallback* m_destination; time_t m_time; CTimer m_pollTimer; CTimer m_pollInactivityTimer; @@ -128,3 +137,5 @@ private: unsigned int calcBackoff(); }; + +#endif diff --git a/DExtraHandler.cpp b/DExtraHandler.cpp index 3b1db53..0a472c7 100644 --- a/DExtraHandler.cpp +++ b/DExtraHandler.cpp @@ -1,6 +1,5 @@ /* * Copyright (C) 2010-2015 by Jonathan Naylor G4KLX - * Copyright (c) 2017-2018 by Thomas A. Early * * 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 @@ -17,24 +16,31 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include - +#include "RepeaterHandler.h" #include "DExtraHandler.h" +#include "DStarDefines.h" #include "Utils.h" +#include "Log.h" +#include "StringUtils.h" -std::list CDExtraHandler::m_DExtraHandlers; +unsigned int CDExtraHandler::m_maxReflectors = 0U; +unsigned int CDExtraHandler::m_maxDongles = 0U; +CDExtraHandler** CDExtraHandler::m_reflectors = NULL; -std::string CDExtraHandler::m_callsign; -CDExtraProtocolHandlerPool *CDExtraHandler::m_pool = NULL; +std::string CDExtraHandler::m_callsign; +CDExtraProtocolHandlerPool* CDExtraHandler::m_pool = NULL; +CDExtraProtocolHandler* CDExtraHandler::m_incoming = NULL; bool CDExtraHandler::m_stateChange = false; -CCallsignList *CDExtraHandler::m_whiteList = NULL; -CCallsignList *CDExtraHandler::m_blackList = NULL; +CHeaderLogger* CDExtraHandler::m_headerLogger = NULL; + +CCallsignList* CDExtraHandler::m_whiteList = NULL; +CCallsignList* CDExtraHandler::m_blackList = NULL; -CDExtraHandler::CDExtraHandler(IReflectorCallback *handler, const std::string &dextraHandler, const std::string &repeater, CDExtraProtocolHandler *protoHandler, const in_addr &address, unsigned int port, DIRECTION direction) : -m_reflector(dextraHandler), +CDExtraHandler::CDExtraHandler(IReflectorCallback* handler, const std::string& reflector, const std::string& repeater, CDExtraProtocolHandler* protoHandler, const in_addr& address, unsigned int port, DIRECTION direction) : +m_reflector(reflector), m_repeater(repeater), m_handler(protoHandler), m_yourAddress(address), @@ -70,6 +76,42 @@ m_header(NULL) } } +CDExtraHandler::CDExtraHandler(CDExtraProtocolHandler* protoHandler, const std::string& reflector, const in_addr& address, unsigned int port, DIRECTION direction) : +m_reflector(reflector), +m_repeater(), +m_handler(protoHandler), +m_yourAddress(address), +m_yourPort(port), +m_direction(direction), +m_linkState(DEXTRA_LINKING), +m_destination(NULL), +m_time(), +m_pollTimer(1000U, 10U), +m_pollInactivityTimer(1000U, 60U), +m_tryTimer(1000U, 1U), +m_tryCount(0U), +m_dExtraId(0x00U), +m_dExtraSeq(0x00U), +m_inactivityTimer(1000U, NETWORK_TIMEOUT), +m_header(NULL) +{ + assert(protoHandler != NULL); + assert(port > 0U); + + m_pollInactivityTimer.start(); + + m_time = ::time(NULL); + + if (direction == DIR_INCOMING) { + m_pollTimer.start(); + m_stateChange = true; + m_linkState = DEXTRA_LINKED; + } else { + m_linkState = DEXTRA_LINKING; + m_tryTimer.start(); + } +} + CDExtraHandler::~CDExtraHandler() { if (m_direction == DIR_OUTGOING) @@ -78,62 +120,92 @@ CDExtraHandler::~CDExtraHandler() delete m_header; } +void CDExtraHandler::initialise(unsigned int maxReflectors) +{ + assert(maxReflectors > 0U); + + m_maxReflectors = maxReflectors; + + m_reflectors = new CDExtraHandler*[m_maxReflectors]; + for (unsigned int i = 0U; i < m_maxReflectors; i++) + m_reflectors[i] = NULL; +} + void CDExtraHandler::setCallsign(const std::string& callsign) { - m_callsign.assign(callsign); + m_callsign = callsign; m_callsign.resize(LONG_CALLSIGN_LENGTH, ' '); m_callsign[LONG_CALLSIGN_LENGTH - 1U] = ' '; } -void CDExtraHandler::setDExtraProtocolHandlerPool(CDExtraProtocolHandlerPool *pool) +void CDExtraHandler::setDExtraProtocolIncoming(CDExtraProtocolHandler* incoming) +{ + assert(incoming != NULL); + + m_incoming = incoming; +} + +void CDExtraHandler::setDExtraProtocolHandlerPool(CDExtraProtocolHandlerPool* pool) { assert(pool != NULL); m_pool = pool; } -void CDExtraHandler::setWhiteList(CCallsignList *list) +void CDExtraHandler::setHeaderLogger(CHeaderLogger* logger) +{ + m_headerLogger = logger; +} + +void CDExtraHandler::setMaxDongles(unsigned int maxDongles) +{ + m_maxDongles = maxDongles; +} + +void CDExtraHandler::setWhiteList(CCallsignList* list) { assert(list != NULL); m_whiteList = list; } -void CDExtraHandler::setBlackList(CCallsignList *list) +void CDExtraHandler::setBlackList(CCallsignList* list) { assert(list != NULL); m_blackList = list; } -std::string CDExtraHandler::getIncoming(const std::string &callsign) +std::string CDExtraHandler::getIncoming(const std::string& callsign) { std::string incoming; - for (auto it=m_DExtraHandlers.begin(); it!=m_DExtraHandlers.end(); it++) { - CDExtraHandler *dextraHandler = *it; - if (dextraHandler->m_direction==DIR_INCOMING && 0==dextraHandler->m_repeater.compare(callsign)) { - incoming.append(dextraHandler->m_reflector); - incoming.append(" "); + for (unsigned int i = 0U; i < m_maxReflectors; i++) { + CDExtraHandler* reflector = m_reflectors[i]; + if (reflector != NULL && reflector->m_direction == DIR_INCOMING && reflector->m_repeater == callsign) { + incoming += reflector->m_reflector; + incoming += " "; } } return incoming; } -void CDExtraHandler::getInfo(IReflectorCallback *handler, CRemoteRepeaterData &data) +void CDExtraHandler::getInfo(IReflectorCallback* handler, CRemoteRepeaterData& data) { assert(handler != NULL); - for (auto it=m_DExtraHandlers.begin(); it!=m_DExtraHandlers.end(); it++) { - CDExtraHandler *dextraHandler = *it; - if (dextraHandler->m_destination == handler) { - if (dextraHandler->m_direction == DIR_INCOMING && 0 == dextraHandler->m_repeater.size()) { - if (dextraHandler->m_linkState != DEXTRA_UNLINKING) - data.addLink(dextraHandler->m_reflector, PROTO_DEXTRA, dextraHandler->m_linkState == DEXTRA_LINKED, DIR_INCOMING, true); - } else { - if (dextraHandler->m_linkState != DEXTRA_UNLINKING) - data.addLink(dextraHandler->m_reflector, PROTO_DEXTRA, dextraHandler->m_linkState == DEXTRA_LINKED, dextraHandler->m_direction, false); + for (unsigned int i = 0U; i < m_maxReflectors; i++) { + CDExtraHandler* reflector = m_reflectors[i]; + if (reflector != NULL) { + if (reflector->m_destination == handler) { + if (reflector->m_direction == DIR_INCOMING && reflector->m_repeater.empty()) { + if (reflector->m_linkState != DEXTRA_UNLINKING) + data.addLink(reflector->m_reflector, PROTO_DEXTRA, reflector->m_linkState == DEXTRA_LINKED, DIR_INCOMING, true); + } else { + if (reflector->m_linkState != DEXTRA_UNLINKING) + data.addLink(reflector->m_reflector, PROTO_DEXTRA, reflector->m_linkState == DEXTRA_LINKED, reflector->m_direction, false); + } } } } @@ -143,222 +215,345 @@ std::string CDExtraHandler::getDongles() { std::string dongles; - for (auto it=m_DExtraHandlers.begin(); it!=m_DExtraHandlers.end(); it++) { - CDExtraHandler *dextraHandler = *it; - if (dextraHandler->m_direction==DIR_INCOMING && 0==dextraHandler->m_repeater.size()) { - dongles.append("X:"); - dongles.append(dextraHandler->m_reflector); - dongles.append(" "); + for (unsigned int i = 0U; i < m_maxReflectors; i++) { + CDExtraHandler* reflector = m_reflectors[i]; + if (reflector != NULL && reflector->m_direction == DIR_INCOMING && reflector->m_repeater.empty()) { + dongles += "X:"; + dongles += reflector->m_reflector; + dongles += " "; } } return dongles; } -void CDExtraHandler::process(CHeaderData &header) +void CDExtraHandler::process(CHeaderData& header) { in_addr yourAddress = header.getYourAddress(); unsigned int yourPort = header.getYourPort(); - for (auto it=m_DExtraHandlers.begin(); it!=m_DExtraHandlers.end(); it++) { - CDExtraHandler *dextraHandler = *it; - if (dextraHandler->m_yourAddress.s_addr==yourAddress.s_addr && dextraHandler->m_yourPort==yourPort) - dextraHandler->processInt(header); - } + for (unsigned int i = 0U; i < m_maxReflectors; i++) { + CDExtraHandler* reflector = m_reflectors[i]; + if (reflector != NULL) { + if (reflector->m_yourAddress.s_addr == yourAddress.s_addr && + reflector->m_yourPort == yourPort) + reflector->processInt(header); + } + } } -void CDExtraHandler::process(CAMBEData &data) +void CDExtraHandler::process(CAMBEData& data) { in_addr yourAddress = data.getYourAddress(); unsigned int yourPort = data.getYourPort(); - for (auto it=m_DExtraHandlers.begin(); it!=m_DExtraHandlers.end(); it++) { - CDExtraHandler *dextraHandler = *it; - if (yourAddress.s_addr==dextraHandler->m_yourAddress.s_addr && yourPort==dextraHandler->m_yourPort) - dextraHandler->processInt(data); - } + for (unsigned int i = 0U; i < m_maxReflectors; i++) { + CDExtraHandler* reflector = m_reflectors[i]; + if (reflector != NULL) { + if (reflector->m_yourAddress.s_addr == yourAddress.s_addr && + reflector->m_yourPort == yourPort) + reflector->processInt(data); + } + } } -void CDExtraHandler::process(const CPollData &poll) +void CDExtraHandler::process(const CPollData& poll) { - std::string reflector = poll.getData1(); + bool found = false; + + std::string reflector = poll.getData1(); in_addr yourAddress = poll.getYourAddress(); unsigned int yourPort = poll.getYourPort(); - // reset all inactivity times from this reflector - for (auto it=m_DExtraHandlers.begin(); it!=m_DExtraHandlers.end(); it++) { - CDExtraHandler *handler = *it; - if ( 0==handler->m_reflector.compare(0, LONG_CALLSIGN_LENGTH-1, reflector, 0, LONG_CALLSIGN_LENGTH-1) && - handler->m_yourAddress.s_addr == yourAddress.s_addr && - handler->m_yourPort == yourPort && - handler->m_linkState == DEXTRA_LINKED) { - handler->m_pollInactivityTimer.start(); + + // Check to see if we already have a link + for (unsigned int i = 0U; i < m_maxReflectors; i++) { + if (m_reflectors[i] != NULL) { + if (m_reflectors[i]->m_reflector.substr(0, LONG_CALLSIGN_LENGTH - 1U) == reflector.substr(0, LONG_CALLSIGN_LENGTH - 1U) && + m_reflectors[i]->m_yourAddress.s_addr == yourAddress.s_addr && + m_reflectors[i]->m_yourPort == yourPort && + m_reflectors[i]->m_linkState == DEXTRA_LINKED) { + m_reflectors[i]->m_pollInactivityTimer.start(); + found = true; + } + } + } + + if (found) + return; + + // A repeater poll arriving here is an error + if (!poll.isDongle()) + return; + + // Check to see if we are allowed to accept it + unsigned int count = 0U; + for (unsigned int i = 0U; i < m_maxReflectors; i++) { + if (m_reflectors[i] != NULL && + m_reflectors[i]->m_direction == DIR_INCOMING && + m_reflectors[i]->m_repeater.empty()) + count++; + } + + if (count >= m_maxDongles) + return; + + // An unmatched poll indicates the need for a new entry + wxLogMessage("New incoming DExtra Dongle from %s", reflector.c_str()); + + CDExtraHandler* handler = new CDExtraHandler(m_incoming, reflector, yourAddress, yourPort, DIR_INCOMING); + + found = false; + + for (unsigned int i = 0U; i < m_maxReflectors; i++) { + if (m_reflectors[i] == NULL) { + m_reflectors[i] = handler; + found = true; + break; } } + + if (found) { + // Return the poll + CPollData poll(m_callsign, yourAddress, yourPort); + m_incoming->writePoll(poll); + } else { + wxLogError("No space to add new DExtra Dongle, ignoring"); + delete handler; + } } -void CDExtraHandler::process(CConnectData &connect) +void CDExtraHandler::process(CConnectData& connect) { CD_TYPE type = connect.getType(); if (type == CT_ACK || type == CT_NAK || type == CT_UNLINK) { - for (auto it=m_DExtraHandlers.begin(); it!=m_DExtraHandlers.end(); ) { - CDExtraHandler *dextraHandler = *it; - bool res = dextraHandler->processInt(connect, type); - if (res) { - delete dextraHandler; - it = m_DExtraHandlers.erase(it); - } else - it++; + for (unsigned int i = 0U; i < m_maxReflectors; i++) { + if (m_reflectors[i] != NULL) { + bool res = m_reflectors[i]->processInt(connect, type); + if (res) { + delete m_reflectors[i]; + m_reflectors[i] = NULL; + } + } } return; } // else if type == CT_LINK1 or type == CT_LINK2 - // someone tried to link directly to a Smart Group! - printf("CDExtraHandler::process(CConnectData) type=CT_LINK%c, DStarGatewaychannel=%s, from repeater=%s\n", (type==CT_LINK1) ? '1' : '2', m_callsign.c_str(), connect.getRepeater().c_str()); + in_addr yourAddress = connect.getYourAddress(); + unsigned int yourPort = connect.getYourPort(); + + std::string repeaterCallsign = connect.getRepeater(); + + auto band = connect.getReflector()[LONG_CALLSIGN_LENGTH - 1U]; + + std::string reflectorCallsign = m_callsign; + reflectorCallsign[LONG_CALLSIGN_LENGTH - 1U] = band; + + // Check that it isn't a duplicate + for (unsigned int i = 0U; i < m_maxReflectors; i++) { + if (m_reflectors[i] != NULL) { + if (m_reflectors[i]->m_direction == DIR_INCOMING && + m_reflectors[i]->m_yourAddress.s_addr == yourAddress.s_addr && + m_reflectors[i]->m_yourPort == yourPort && + m_reflectors[i]->m_repeater == reflectorCallsign && + m_reflectors[i]->m_reflector == repeaterCallsign) + return; + } + } + + // Check the validity of our repeater callsign + IReflectorCallback* handler = CRepeaterHandler::findDVRepeater(reflectorCallsign); + if (handler == NULL) { + wxLogMessage("DExtra connect to unknown reflector %s from %s", reflectorCallsign.c_str(), repeaterCallsign.c_str()); + CConnectData reply(repeaterCallsign, reflectorCallsign, CT_NAK, yourAddress, yourPort); + m_incoming->writeConnect(reply); + return; + } + + // A new connect packet indicates the need for a new entry + wxLogMessage("New incoming DExtra link to %s from %s", reflectorCallsign.c_str(), repeaterCallsign.c_str()); + + CDExtraHandler* dextra = new CDExtraHandler(handler, repeaterCallsign, reflectorCallsign, m_incoming, yourAddress, yourPort, DIR_INCOMING); + + bool found = false; + for (unsigned int i = 0U; i < m_maxReflectors; i++) { + if (m_reflectors[i] == NULL) { + m_reflectors[i] = dextra; + found = true; + break; + } + } + + if (found) { + CConnectData reply(repeaterCallsign, reflectorCallsign, CT_ACK, yourAddress, yourPort); + m_incoming->writeConnect(reply); + + std::string callsign = repeaterCallsign; + callsign[LONG_CALLSIGN_LENGTH - 1U] = ' '; + CPollData poll(callsign, yourAddress, yourPort); + m_incoming->writePoll(poll); + } else { + CConnectData reply(repeaterCallsign, reflectorCallsign, CT_NAK, yourAddress, yourPort); + m_incoming->writeConnect(reply); + + wxLogError("No space to add new DExtra repeater, ignoring"); + delete dextra; + } } -void CDExtraHandler::link(IReflectorCallback *handler, const std::string &repeater, const std::string &gateway, const in_addr &address) +void CDExtraHandler::link(IReflectorCallback* handler, const std::string& repeater, const std::string &gateway, const in_addr& address) { - CDExtraProtocolHandler *protoHandler = m_pool->getHandler(); + CDExtraProtocolHandler* protoHandler = m_pool->getHandler(); if (protoHandler == NULL) return; - CDExtraHandler *dextra = new CDExtraHandler(handler, gateway, repeater, protoHandler, address, DEXTRA_PORT, DIR_OUTGOING); - if (dextra) { - m_DExtraHandlers.push_back(dextra); + CDExtraHandler* dextra = new CDExtraHandler(handler, gateway, repeater, protoHandler, address, DEXTRA_PORT, DIR_OUTGOING); + + bool found = false; + + for (unsigned int i = 0U; i < m_maxReflectors; i++) { + if (m_reflectors[i] == NULL) { + m_reflectors[i] = dextra; + found = true; + break; + } + } + + if (found) { CConnectData reply(repeater, gateway, CT_LINK1, address, DEXTRA_PORT); protoHandler->writeConnect(reply); + } else { + wxLogError("No space to add new DExtra link, ignoring"); + delete dextra; } } -void CDExtraHandler::unlink(IReflectorCallback *handler, const std::string &callsign, bool exclude) +void CDExtraHandler::unlink(IReflectorCallback* handler, const std::string& callsign, bool exclude) { - for (auto it=m_DExtraHandlers.begin(); it!=m_DExtraHandlers.end(); it++) { - CDExtraHandler *dextraHandler = *it; + for (unsigned int i = 0U; i < m_maxReflectors; i++) { + CDExtraHandler* reflector = m_reflectors[i]; + + if (reflector != NULL) { + bool found = false; - bool found = false; + if (exclude) { + if (reflector->m_direction == DIR_OUTGOING && reflector->m_destination == handler && reflector->m_reflector != callsign) { + wxLogMessage("Removing outgoing DExtra link %s, %s", reflector->m_repeater.c_str(), reflector->m_reflector.c_str()); - if (exclude) { - if (dextraHandler->m_direction == DIR_OUTGOING && dextraHandler->m_destination == handler && dextraHandler->m_reflector.compare(callsign)) { - printf("Removing outgoing DExtra link %s, %s\n", dextraHandler->m_repeater.c_str(), dextraHandler->m_reflector.c_str()); + if (reflector->m_linkState == DEXTRA_LINKING || reflector->m_linkState == DEXTRA_LINKED) { + CConnectData connect(reflector->m_repeater, reflector->m_yourAddress, reflector->m_yourPort); + reflector->m_handler->writeConnect(connect); - if (dextraHandler->m_linkState == DEXTRA_LINKING || dextraHandler->m_linkState == DEXTRA_LINKED) { - CConnectData connect(dextraHandler->m_repeater, dextraHandler->m_yourAddress, dextraHandler->m_yourPort); - dextraHandler->m_handler->writeConnect(connect); + reflector->m_linkState = DEXTRA_UNLINKING; - dextraHandler->m_linkState = DEXTRA_UNLINKING; + reflector->m_destination->linkFailed(DP_DEXTRA, reflector->m_reflector, false); + } - dextraHandler->m_destination->linkFailed(DP_DEXTRA, dextraHandler->m_reflector, false); + found = true; } + } else { + if (reflector->m_destination == handler && reflector->m_reflector == callsign) { + wxLogMessage("Removing DExtra link %s, %s", reflector->m_repeater.c_str(), reflector->m_reflector.c_str()); - found = true; - } - } else { - if (dextraHandler->m_destination == handler && 0==dextraHandler->m_reflector.compare(callsign)) { - printf("Removing DExtra link %s, %s\n", dextraHandler->m_repeater.c_str(), dextraHandler->m_reflector.c_str()); + if (reflector->m_linkState == DEXTRA_LINKING || reflector->m_linkState == DEXTRA_LINKED) { + CConnectData connect(reflector->m_repeater, reflector->m_yourAddress, reflector->m_yourPort); + reflector->m_handler->writeConnect(connect); - if (dextraHandler->m_linkState == DEXTRA_LINKING || dextraHandler->m_linkState == DEXTRA_LINKED) { - CConnectData connect(dextraHandler->m_repeater, dextraHandler->m_yourAddress, dextraHandler->m_yourPort); - dextraHandler->m_handler->writeConnect(connect); + reflector->m_linkState = DEXTRA_UNLINKING; - dextraHandler->m_linkState = DEXTRA_UNLINKING; + reflector->m_destination->linkFailed(DP_DEXTRA, reflector->m_reflector, false); + } - dextraHandler->m_destination->linkFailed(DP_DEXTRA, dextraHandler->m_reflector, false); + found = true; } - - found = true; } - } // If an active link with incoming traffic, send an EOT to the repeater - if (found) { - if (dextraHandler->m_dExtraId != 0x00U) { - unsigned int seq = dextraHandler->m_dExtraSeq + 1U; - if (seq == 21U) - seq = 0U; - - CAMBEData data; - data.setData(END_PATTERN_BYTES, DV_FRAME_LENGTH_BYTES); - data.setSeq(seq); - data.setEnd(true); - data.setId(dextraHandler->m_dExtraId); - - dextraHandler->m_destination->process(data, dextraHandler->m_direction, AS_DEXTRA); - } + if (found) { + if (reflector->m_dExtraId != 0x00U) { + unsigned int seq = reflector->m_dExtraSeq + 1U; + if (seq == 21U) + seq = 0U; + + CAMBEData data; + data.setData(END_PATTERN_BYTES, DV_FRAME_LENGTH_BYTES); + data.setSeq(seq); + data.setEnd(true); + data.setId(reflector->m_dExtraId); + + reflector->m_destination->process(data, reflector->m_direction, AS_DEXTRA); + } - m_stateChange = true; + m_stateChange = true; - delete dextraHandler; - it = m_DExtraHandlers.erase(it); - it--; + delete m_reflectors[i]; + m_reflectors[i] = NULL; + } } - } + } } -void CDExtraHandler::unlink(CDExtraHandler *dextraHandler) +void CDExtraHandler::unlink() { - if (dextraHandler != NULL) { - if (dextraHandler->m_repeater.size()) { - printf("Unlinking from DExtra dextraHandler %s\n", dextraHandler->m_reflector.c_str()); + for (unsigned int i = 0U; i < m_maxReflectors; i++) { + CDExtraHandler* reflector = m_reflectors[i]; - CConnectData connect(dextraHandler->m_repeater, dextraHandler->m_yourAddress, dextraHandler->m_yourPort); - dextraHandler->m_handler->writeConnect(connect); + if (reflector != NULL) { + if (!reflector->m_repeater.empty()) { + wxLogMessage("Unlinking from DExtra reflector %s", reflector->m_reflector.c_str()); - dextraHandler->m_linkState = DEXTRA_UNLINKING; - } - } -} + CConnectData connect(reflector->m_repeater, reflector->m_yourAddress, reflector->m_yourPort); + reflector->m_handler->writeConnect(connect); -void CDExtraHandler::unlink() -{ - for (auto it=m_DExtraHandlers.begin(); it!=m_DExtraHandlers.end(); it++) { - CDExtraHandler *dextraHandler = *it; - CDExtraHandler::unlink(dextraHandler); - } + reflector->m_linkState = DEXTRA_UNLINKING; + } + } + } } -void CDExtraHandler::writeHeader(IReflectorCallback *handler, CHeaderData &header, DIRECTION direction) +void CDExtraHandler::writeHeader(IReflectorCallback* handler, CHeaderData& header, DIRECTION direction) { - for (auto it=m_DExtraHandlers.begin(); it!=m_DExtraHandlers.end(); it++) { - CDExtraHandler *dextraHandler = *it; - dextraHandler->writeHeaderInt(handler, header, direction); - } + for (unsigned int i = 0U; i < m_maxReflectors; i++) { + if (m_reflectors[i] != NULL) + m_reflectors[i]->writeHeaderInt(handler, header, direction); + } } -void CDExtraHandler::writeAMBE(IReflectorCallback *handler, CAMBEData &data, DIRECTION direction) +void CDExtraHandler::writeAMBE(IReflectorCallback* handler, CAMBEData& data, DIRECTION direction) { - for (auto it=m_DExtraHandlers.begin(); it!=m_DExtraHandlers.end(); it++) { - CDExtraHandler *dextraHandler = *it; - dextraHandler->writeAMBEInt(handler, data, direction); - } + for (unsigned int i = 0U; i < m_maxReflectors; i++) { + if (m_reflectors[i] != NULL) + m_reflectors[i]->writeAMBEInt(handler, data, direction); + } } -void CDExtraHandler::gatewayUpdate(const std::string &dextraHandler, const std::string &address) +void CDExtraHandler::gatewayUpdate(const std::string& reflector, const std::string& address) { - std::string gateway = dextraHandler; - gateway.resize(LONG_CALLSIGN_LENGTH - 1U, ' '); - - for (auto it=m_DExtraHandlers.begin(); it!=m_DExtraHandlers.end(); it++) { - CDExtraHandler *dextraHandler = *it; - if (0==dextraHandler->m_reflector.compare(0, LONG_CALLSIGN_LENGTH-1, gateway)) { - if (address.size()) { - // A new address, change the value - printf("Changing IP address of DExtra gateway or dextraHandler %s to %s\n", dextraHandler->m_reflector.c_str(), address.c_str()); - dextraHandler->m_yourAddress.s_addr = ::inet_addr(address.c_str()); - } else { - printf("IP address for DExtra gateway or dextraHandler %s has been removed\n", dextraHandler->m_reflector.c_str()); - - // No address, this probably shouldn't happen.... - if (dextraHandler->m_direction == DIR_OUTGOING && dextraHandler->m_destination != NULL) - dextraHandler->m_destination->linkFailed(DP_DEXTRA, dextraHandler->m_reflector, false); - - m_stateChange = true; - - delete dextraHandler; - it = m_DExtraHandlers.erase(it); - it--; + std::string gateway = reflector; + gateway.resize(LONG_CALLSIGN_LENGTH - 1U); + + for (unsigned int i = 0U; i < m_maxReflectors; i++) { + CDExtraHandler* reflector = m_reflectors[i]; + if (reflector != NULL) { + if (reflector->m_reflector.substr(0, LONG_CALLSIGN_LENGTH - 1U) == gateway) { + if (!address.empty()) { + // A new address, change the value + wxLogMessage("Changing IP address of DExtra gateway or reflector %s to %s", reflector->m_reflector.c_str(), address.c_str()); + reflector->m_yourAddress.s_addr = ::inet_addr(address.c_str()); + } else { + wxLogMessage("IP address for DExtra gateway or reflector %s has been removed", reflector->m_reflector.c_str()); + + // No address, this probably shouldn't happen.... + if (reflector->m_direction == DIR_OUTGOING && reflector->m_destination != NULL) + reflector->m_destination->linkFailed(DP_DEXTRA, reflector->m_reflector, false); + + m_stateChange = true; + + delete m_reflectors[i]; + m_reflectors[i] = NULL; + } } } } @@ -366,24 +561,23 @@ void CDExtraHandler::gatewayUpdate(const std::string &dextraHandler, const std:: void CDExtraHandler::clock(unsigned int ms) { - for (auto it=m_DExtraHandlers.begin(); it!=m_DExtraHandlers.end(); ) { - CDExtraHandler *dextraHandler = *it; - bool ret = dextraHandler->clockInt(ms); - if (ret) { - delete dextraHandler; - it = m_DExtraHandlers.erase(it); - } else - it++; + for (unsigned int i = 0U; i < m_maxReflectors; i++) { + if (m_reflectors[i] != NULL) { + bool ret = m_reflectors[i]->clockInt(ms); + if (ret) { + delete m_reflectors[i]; + m_reflectors[i] = NULL; + } + } } } void CDExtraHandler::finalise() { - for (auto it=m_DExtraHandlers.begin(); it!=m_DExtraHandlers.end(); ) { - CDExtraHandler *handler = *it; - delete handler; - it = m_DExtraHandlers.erase(it); - } + for (unsigned int i = 0U; i < m_maxReflectors; i++) + delete m_reflectors[i]; + + delete[] m_reflectors; } void CDExtraHandler::processInt(CHeaderData& header) @@ -396,7 +590,7 @@ void CDExtraHandler::processInt(CHeaderData& header) if (m_whiteList != NULL) { bool res = m_whiteList->isInList(my); if (!res) { - printf("%s rejected from DExtra as not found in the white list\n", my.c_str()); + wxLogMessage("%s rejected from DExtra as not found in the white list", my.c_str()); m_dExtraId = 0x00U; return; } @@ -405,7 +599,7 @@ void CDExtraHandler::processInt(CHeaderData& header) if (m_blackList != NULL) { bool res = m_blackList->isInList(my); if (res) { - printf("%s rejected from DExtra as found in the black list\n", my.c_str()); + wxLogMessage("%s rejected from DExtra as found in the black list", my.c_str()); m_dExtraId = 0x00U; return; } @@ -417,13 +611,17 @@ void CDExtraHandler::processInt(CHeaderData& header) switch (m_direction) { case DIR_OUTGOING: { // Always a repeater connection - if (m_reflector.compare(rpt2) && m_reflector.compare(rpt1)) + if (m_reflector != rpt2 && m_reflector != rpt1) return; // If we're already processing, ignore the new header if (m_dExtraId != 0x00U) return; + // Write to Header.log if it's enabled + if (m_headerLogger != NULL) + m_headerLogger->write("DExtra", header); + m_dExtraId = id; m_dExtraSeq = 0x00U; m_inactivityTimer.start(); @@ -439,15 +637,48 @@ void CDExtraHandler::processInt(CHeaderData& header) break; case DIR_INCOMING: - if (m_repeater.size()) { + if (!m_repeater.empty()) { // A repeater connection - if (m_repeater.compare(rpt2) && m_repeater.compare(rpt1)) + if (m_repeater != rpt2 && m_repeater != rpt1) return; // If we're already processing, ignore the new header if (m_dExtraId != 0x00U) return; + // Write to Header.log if it's enabled + if (m_headerLogger != NULL) + m_headerLogger->write("DExtra", header); + + m_dExtraId = id; + m_dExtraSeq = 0x00U; + m_inactivityTimer.start(); + + delete m_header; + + m_header = new CHeaderData(header); + m_header->setCQCQCQ(); + m_header->setFlags(0x00U, 0x00U, 0x00U); + + m_destination->process(*m_header, m_direction, AS_DEXTRA); + } else { + // A Dongle connection + // Check the destination callsign + m_destination = CRepeaterHandler::findDVRepeater(rpt2); + if (m_destination == NULL) { + m_destination = CRepeaterHandler::findDVRepeater(rpt1); + if (m_destination == NULL) + return; + } + + // If we're already processing, ignore the new header + if (m_dExtraId != 0x00U) + return; + + // Write to Header.log if it's enabled + if (m_headerLogger != NULL) + m_headerLogger->write("DExtra", header); + m_dExtraId = id; m_dExtraSeq = 0x00U; m_inactivityTimer.start(); @@ -464,7 +695,7 @@ void CDExtraHandler::processInt(CHeaderData& header) } } -void CDExtraHandler::processInt(CAMBEData &data) +void CDExtraHandler::processInt(CAMBEData& data) { if (m_linkState != DEXTRA_LINKED) return; @@ -497,22 +728,22 @@ void CDExtraHandler::processInt(CAMBEData &data) } } -bool CDExtraHandler::processInt(CConnectData &connect, CD_TYPE type) +bool CDExtraHandler::processInt(CConnectData& connect, CD_TYPE type) { in_addr yourAddress = connect.getYourAddress(); unsigned int yourPort = connect.getYourPort(); - std::string repeater = connect.getRepeater(); + std::string repeater = connect.getRepeater(); if (m_yourAddress.s_addr != yourAddress.s_addr || m_yourPort != yourPort) return false; switch (type) { case CT_ACK: - if (m_repeater.compare(repeater)) + if (m_repeater != repeater) return false; if (m_linkState == DEXTRA_LINKING) { - printf("DExtra ACK message received from %s\n", m_reflector.c_str()); + wxLogMessage("DExtra ACK message received from %s", m_reflector.c_str()); if (m_direction == DIR_OUTGOING && m_destination != NULL) m_destination->linkUp(DP_DEXTRA, m_reflector); @@ -526,11 +757,11 @@ bool CDExtraHandler::processInt(CConnectData &connect, CD_TYPE type) return false; case CT_NAK: - if (m_repeater.compare(repeater)) + if (m_repeater != repeater) return false; if (m_linkState == DEXTRA_LINKING) { - printf("DExtra NAK message received from %s\n", m_reflector.c_str()); + wxLogMessage("DExtra NAK message received from %s", m_reflector.c_str()); if (m_direction == DIR_OUTGOING && m_destination != NULL) m_destination->linkRefused(DP_DEXTRA, m_reflector); @@ -541,11 +772,11 @@ bool CDExtraHandler::processInt(CConnectData &connect, CD_TYPE type) return false; case CT_UNLINK: - if (m_reflector.compare(repeater)) + if (m_reflector != repeater) return false; if (m_linkState == DEXTRA_LINKED) { - printf("DExtra disconnect message received from %s\n", m_reflector.c_str()); + wxLogMessage("DExtra disconnect message received from %s", m_reflector.c_str()); if (m_direction == DIR_OUTGOING && m_destination != NULL) m_destination->linkFailed(DP_DEXTRA, m_reflector, false); @@ -579,13 +810,13 @@ bool CDExtraHandler::clockInt(unsigned int ms) switch (m_linkState) { case DEXTRA_LINKING: - printf("DExtra link to %s has failed to connect\n", m_reflector.c_str()); + wxLogMessage("DExtra link to %s has failed to connect", m_reflector.c_str()); break; case DEXTRA_LINKED: - printf("DExtra link to %s has failed (poll inactivity)\n", m_reflector.c_str()); + wxLogMessage("DExtra link to %s has failed (poll inactivity)", m_reflector.c_str()); break; case DEXTRA_UNLINKING: - printf("DExtra link to %s has failed to disconnect cleanly\n", m_reflector.c_str()); + wxLogMessage("DExtra link to %s has failed to disconnect cleanly", m_reflector.c_str()); break; default: break; @@ -608,9 +839,9 @@ bool CDExtraHandler::clockInt(unsigned int ms) if (m_pollTimer.isRunning() && m_pollTimer.hasExpired()) { if (m_linkState == DEXTRA_LINKED) { - if (m_repeater.size()) { + if (!m_repeater.empty()) { std::string callsign = m_repeater; - callsign[LONG_CALLSIGN_LENGTH - 1U] =' '; + callsign[LONG_CALLSIGN_LENGTH - 1U] = ' '; CPollData poll(callsign, m_yourAddress, m_yourPort); m_handler->writePoll(poll); } else { @@ -645,7 +876,7 @@ bool CDExtraHandler::clockInt(unsigned int ms) return false; } -void CDExtraHandler::writeHeaderInt(IReflectorCallback *handler, CHeaderData &header, DIRECTION direction) +void CDExtraHandler::writeHeaderInt(IReflectorCallback* handler, CHeaderData& header, DIRECTION direction) { if (m_linkState != DEXTRA_LINKED) return; @@ -667,7 +898,7 @@ void CDExtraHandler::writeHeaderInt(IReflectorCallback *handler, CHeaderData &he break; case DIR_INCOMING: - if (0==m_repeater.size() || m_destination == handler) { + if (m_repeater.empty() || m_destination == handler) { header.setDestination(m_yourAddress, m_yourPort); m_handler->writeHeader(header); } @@ -675,7 +906,7 @@ void CDExtraHandler::writeHeaderInt(IReflectorCallback *handler, CHeaderData &he } } -void CDExtraHandler::writeAMBEInt(IReflectorCallback *handler, CAMBEData &data, DIRECTION direction) +void CDExtraHandler::writeAMBEInt(IReflectorCallback* handler, CAMBEData& data, DIRECTION direction) { if (m_linkState != DEXTRA_LINKED) return; @@ -697,7 +928,7 @@ void CDExtraHandler::writeAMBEInt(IReflectorCallback *handler, CAMBEData &data, break; case DIR_INCOMING: - if (0==m_repeater.size() || m_destination == handler) { + if (m_repeater.empty() || m_destination == handler) { data.setDestination(m_yourAddress, m_yourPort); m_handler->writeAMBE(data); } @@ -714,33 +945,42 @@ bool CDExtraHandler::stateChange() return stateChange; } -void CDExtraHandler::writeStatus(FILE *file) +void CDExtraHandler::writeStatus(ofstream& file) { - for (auto it=m_DExtraHandlers.begin(); it!=m_DExtraHandlers.end(); it++) { - CDExtraHandler *dextraHandler = *it; - struct tm *tm = ::gmtime(&dextraHandler->m_time); - - switch (dextraHandler->m_direction) { - case DIR_OUTGOING: - if (dextraHandler->m_linkState == DEXTRA_LINKED) { - fprintf(file, "%04d-%02d-%02d %02d:%02d:%02d: DExtra link - Type: Repeater Rptr: %s Refl: %s Dir: Outgoing\n", - tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, - dextraHandler->m_repeater.c_str(), dextraHandler->m_reflector.c_str()); - } - break; + for (unsigned int i = 0U; i < m_maxReflectors; i++) { + CDExtraHandler* reflector = m_reflectors[i]; + if (reflector != NULL) { + std::string text; + + struct tm* tm = ::gmtime(&reflector->m_time); + + switch (reflector->m_direction) { + case DIR_OUTGOING: + if (reflector->m_linkState == DEXTRA_LINKED) { + text = string_format("%04d-%02d-%02d %02d:%02d:%02d: DExtra link - Type: Repeater Rptr: %s Refl: %s Dir: Outgoing\n", + tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, + reflector->m_repeater.c_str(), reflector->m_reflector.c_str()); + + file << text; + } + break; + + case DIR_INCOMING: + if (reflector->m_linkState == DEXTRA_LINKED) { + if (reflector->m_repeater.empty()) + text = string_format("%04d-%02d-%02d %02d:%02d:%02d: DExtra link - Type: Dongle User: %s Dir: Incoming\n", + tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, + reflector->m_reflector.c_str()); + else + text = string_format("%04d-%02d-%02d %02d:%02d:%02d: DExtra link - Type: Repeater Rptr: %s Refl: %s Dir: Incoming\n", + tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, + reflector->m_repeater.c_str(), reflector->m_reflector.c_str()); + + file << text; + } + break; + } - case DIR_INCOMING: - if (dextraHandler->m_linkState == DEXTRA_LINKED) { - if (0==dextraHandler->m_repeater.size()) - fprintf(file, "%04d-%02d-%02d %02d:%02d:%02d: DExtra link - Type: Dongle User: %s Dir: Incoming\n", - tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, - dextraHandler->m_reflector.c_str()); - else - fprintf(file, "%04d-%02d-%02d %02d:%02d:%02d: DExtra link - Type: Repeater Rptr: %s Refl: %s Dir: Incoming\n", - tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, - dextraHandler->m_repeater.c_str(), dextraHandler->m_reflector.c_str()); - } - break; } } } diff --git a/DExtraHandler.h b/DExtraHandler.h index a79e7fd..cd9ec0c 100644 --- a/DExtraHandler.h +++ b/DExtraHandler.h @@ -1,6 +1,5 @@ /* * Copyright (C) 2010-2013,2015 by Jonathan Naylor G4KLX - * Copyright (c) 2017-2018 by Thomas A. Early * * 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 @@ -17,16 +16,18 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#pragma once +#ifndef DExtraHander_H +#define DExtraHander_H #include #include -#include +#include +#include #include "DExtraProtocolHandlerPool.h" -#include "RemoteRepeaterData.h" #include "ReflectorCallback.h" #include "DStarDefines.h" +#include "HeaderLogger.h" #include "CallsignList.h" #include "ConnectData.h" #include "HeaderData.h" @@ -43,70 +44,80 @@ enum DEXTRA_STATE { class CDExtraHandler { public: - static void setCallsign(const std::string &callsign); - static void setDExtraProtocolHandlerPool(CDExtraProtocolHandlerPool *pool); + static void initialise(unsigned int maxReflectors); - static void link(IReflectorCallback *handler, const std::string &repeater, const std::string &reflector, const in_addr &address); - static void unlink(IReflectorCallback *handler, const std::string &reflector = std::string(""), bool exclude = true); - static void unlink(CDExtraHandler *reflector); + static void setCallsign(const std::string& callsign); + static void setDExtraProtocolHandlerPool(CDExtraProtocolHandlerPool* pool); + static void setDExtraProtocolIncoming(CDExtraProtocolHandler* handler); + static void setHeaderLogger(CHeaderLogger* logger); + static void setMaxDongles(unsigned int maxDongles); + + static void link(IReflectorCallback* handler, const std::string& repeater, const std::string& reflector, const in_addr& address); + static void unlink(IReflectorCallback* handler, const std::string& reflector = "", bool exclude = true); static void unlink(); - static void writeHeader(IReflectorCallback *handler, CHeaderData &header, DIRECTION direction); - static void writeAMBE(IReflectorCallback *handler, CAMBEData &data, DIRECTION direction); + static void writeHeader(IReflectorCallback* handler, CHeaderData& header, DIRECTION direction); + static void writeAMBE(IReflectorCallback* handler, CAMBEData& data, DIRECTION direction); - static void process(CHeaderData &header); - static void process(CAMBEData &data); - static void process(const CPollData &poll); - static void process(CConnectData &connect); + static void process(CHeaderData& header); + static void process(CAMBEData& data); + static void process(const CPollData& poll); + static void process(CConnectData& connect); - static void gatewayUpdate(const std::string &reflector, const std::string &address); + static void gatewayUpdate(const std::string& reflector, const std::string& address); static void clock(unsigned int ms); static bool stateChange(); - static void writeStatus(FILE *file); + static void writeStatus(std::ofstream& file); - static void setWhiteList(CCallsignList *list); - static void setBlackList(CCallsignList *list); + static void setWhiteList(CCallsignList* list); + static void setBlackList(CCallsignList* list); static void finalise(); - static void getInfo(IReflectorCallback *handler, CRemoteRepeaterData &data); + static void getInfo(IReflectorCallback* handler, CRemoteRepeaterData& data); - static std::string getIncoming(const std::string &callsign); + static std::string getIncoming(const std::string& callsign); static std::string getDongles(); protected: - CDExtraHandler(IReflectorCallback *handler, const std::string &reflector, const std::string &repeater, CDExtraProtocolHandler *protoHandler, const in_addr &address, unsigned int port, DIRECTION direction); + CDExtraHandler(IReflectorCallback* handler, const std::string& reflector, const std::string& repeater, CDExtraProtocolHandler* protoHandler, const in_addr& address, unsigned int port, DIRECTION direction); + CDExtraHandler(CDExtraProtocolHandler* protoHandler, const std::string& reflector, const in_addr& address, unsigned int port, DIRECTION direction); ~CDExtraHandler(); - void processInt(CHeaderData &header); - void processInt(CAMBEData &data); - bool processInt(CConnectData &connect, CD_TYPE type); + void processInt(CHeaderData& header); + void processInt(CAMBEData& data); + bool processInt(CConnectData& connect, CD_TYPE type); - void writeHeaderInt(IReflectorCallback *handler, CHeaderData &header, DIRECTION direction); - void writeAMBEInt(IReflectorCallback *handler, CAMBEData &data, DIRECTION direction); + void writeHeaderInt(IReflectorCallback* handler, CHeaderData& header, DIRECTION direction); + void writeAMBEInt(IReflectorCallback* handler, CAMBEData& data, DIRECTION direction); bool clockInt(unsigned int ms); private: - static std::list m_DExtraHandlers; + static unsigned int m_maxReflectors; + static unsigned int m_maxDongles; + static CDExtraHandler** m_reflectors; - static std::string m_callsign; - static CDExtraProtocolHandlerPool *m_pool; + static std::string m_callsign; + static CDExtraProtocolHandlerPool* m_pool; + static CDExtraProtocolHandler* m_incoming; static bool m_stateChange; - static CCallsignList *m_whiteList; - static CCallsignList *m_blackList; + static CHeaderLogger* m_headerLogger; + + static CCallsignList* m_whiteList; + static CCallsignList* m_blackList; - std::string m_reflector; - std::string m_repeater; - CDExtraProtocolHandler *m_handler; + std::string m_reflector; + std::string m_repeater; + CDExtraProtocolHandler* m_handler; in_addr m_yourAddress; unsigned int m_yourPort; DIRECTION m_direction; DEXTRA_STATE m_linkState; - IReflectorCallback *m_destination; + IReflectorCallback* m_destination; time_t m_time; CTimer m_pollTimer; CTimer m_pollInactivityTimer; @@ -115,7 +126,9 @@ private: unsigned int m_dExtraId; unsigned int m_dExtraSeq; CTimer m_inactivityTimer; - CHeaderData *m_header; + CHeaderData* m_header; unsigned int calcBackoff(); }; + +#endif