Redo DCs/Dextra from scratch

master
Geoffrey Merck 4 years ago
parent 7bce487977
commit 1ee4bd3b7c

@ -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 <cassert>
#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 *> 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;
}
}
}
}

@ -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 <netinet/in.h>
#include <string>
#include <cstdio>
#include <list>
#include <iostream>
#include <fstream>
#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<CDCSHandler *> 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

@ -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 <cassert>
#include "RepeaterHandler.h"
#include "DExtraHandler.h"
#include "DStarDefines.h"
#include "Utils.h"
#include "Log.h"
#include "StringUtils.h"
std::list<CDExtraHandler *> 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;
}
}
}

@ -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 <netinet/in.h>
#include <string>
#include <list>
#include <fstream>
#include <iostream>
#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<CDExtraHandler *> 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

Loading…
Cancel
Save

Powered by TurnKey Linux.