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) 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
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -18,10 +17,15 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#include <cassert> #include "RepeaterHandler.h"
#include "DStarDefines.h"
#include "DCSHandler.h" #include "DCSHandler.h"
#include "Utils.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; CDCSProtocolHandlerPool* CDCSHandler::m_pool = NULL;
CDCSProtocolHandler* CDCSHandler::m_incoming = NULL; CDCSProtocolHandler* CDCSHandler::m_incoming = NULL;
@ -30,13 +34,16 @@ bool CDCSHandler::m_stateChange = false;
GATEWAY_TYPE CDCSHandler::m_gatewayType = GT_REPEATER; GATEWAY_TYPE CDCSHandler::m_gatewayType = GT_REPEATER;
CHeaderLogger* CDCSHandler::m_headerLogger = NULL;
CCallsignList* CDCSHandler::m_whiteList = NULL; CCallsignList* CDCSHandler::m_whiteList = NULL;
CCallsignList* CDCSHandler::m_blackList = NULL; CCallsignList* CDCSHandler::m_blackList = NULL;
std::list<CDCSHandler *> CDCSHandler::m_DCSHandlers;
CDCSHandler::CDCSHandler(IReflectorCallback *handler, const std::string &dcsHandler, const std::string &repeater, CDCSProtocolHandler *protoHandler, const in_addr &address, unsigned int port, DIRECTION direction) : 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(dcsHandler), m_reflector(reflector),
m_xlxReflector(),
m_isXlx(false),
m_repeater(repeater), m_repeater(repeater),
m_handler(protoHandler), m_handler(protoHandler),
m_yourAddress(address), m_yourAddress(address),
@ -76,6 +83,11 @@ m_rptCall2()
m_linkState = DCS_LINKED; m_linkState = DCS_LINKED;
} else { } else {
m_linkState = DCS_LINKING; 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(); m_tryTimer.start();
} }
} }
@ -86,6 +98,17 @@ CDCSHandler::~CDCSHandler()
m_pool->release(m_handler); m_pool->release(m_handler);
} }
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) void CDCSHandler::setDCSProtocolHandlerPool(CDCSProtocolHandlerPool* pool)
{ {
assert(pool != NULL); assert(pool != NULL);
@ -100,6 +123,11 @@ void CDCSHandler::setDCSProtocolIncoming(CDCSProtocolHandler *handler)
m_incoming = handler; m_incoming = handler;
} }
void CDCSHandler::setHeaderLogger(CHeaderLogger* logger)
{
m_headerLogger = logger;
}
void CDCSHandler::setGatewayType(GATEWAY_TYPE type) void CDCSHandler::setGatewayType(GATEWAY_TYPE type)
{ {
m_gatewayType = type; m_gatewayType = type;
@ -123,11 +151,11 @@ std::string CDCSHandler::getIncoming(const std::string &callsign)
{ {
std::string incoming; std::string incoming;
for (auto it=m_DCSHandlers.begin(); it!=m_DCSHandlers.end(); it++) { for (unsigned int i = 0U; i < m_maxReflectors; i++) {
CDCSHandler *dcsHandler = *it; CDCSHandler* reflector = m_reflectors[i];
if (dcsHandler->m_direction == DIR_INCOMING && 0==dcsHandler->m_repeater.compare(callsign)) { if (reflector != NULL && reflector->m_direction == DIR_INCOMING && reflector->m_repeater == callsign) {
incoming.append(dcsHandler->m_reflector); incoming += reflector->m_reflector;
incoming.append(" "); incoming += " ";
} }
} }
@ -138,15 +166,17 @@ void CDCSHandler::getInfo(IReflectorCallback *handler, CRemoteRepeaterData &data
{ {
assert(handler != NULL); assert(handler != NULL);
for (auto it=m_DCSHandlers.begin(); it!=m_DCSHandlers.end(); it++) { for (unsigned int i = 0U; i < m_maxReflectors; i++) {
CDCSHandler *dcsHandler = *it; CDCSHandler* reflector = m_reflectors[i];
if (dcsHandler->m_destination == handler) { if (reflector != NULL) {
if (dcsHandler->m_direction == DIR_INCOMING && 0==dcsHandler->m_repeater.size()) { if (reflector->m_destination == handler) {
if (dcsHandler->m_linkState != DCS_UNLINKING) if (reflector->m_direction == DIR_INCOMING && reflector->m_repeater.empty()) {
data.addLink(dcsHandler->m_reflector, PROTO_DCS, dcsHandler->m_linkState == DCS_LINKED, DIR_INCOMING, true); if (reflector->m_linkState != DCS_UNLINKING)
data.addLink(GET_DISP_REFLECTOR(reflector), PROTO_DCS, reflector->m_linkState == DCS_LINKED, DIR_INCOMING, true);
} else { } else {
if (dcsHandler->m_linkState != DCS_UNLINKING) if (reflector->m_linkState != DCS_UNLINKING)
data.addLink(dcsHandler->m_reflector, PROTO_DCS, dcsHandler->m_linkState == DCS_LINKED, dcsHandler->m_direction, false); data.addLink(GET_DISP_REFLECTOR(reflector), PROTO_DCS, reflector->m_linkState == DCS_LINKED, reflector->m_direction, false);
}
} }
} }
} }
@ -158,20 +188,22 @@ void CDCSHandler::process(CAMBEData &data)
unsigned int yourPort = data.getYourPort(); unsigned int yourPort = data.getYourPort();
unsigned int myPort = data.getMyPort(); unsigned int myPort = data.getMyPort();
for (auto it=m_DCSHandlers.begin(); it!=m_DCSHandlers.end(); it++) { for (unsigned int i = 0U; i < m_maxReflectors; i++) {
CDCSHandler *dcsHandler = *it; CDCSHandler* reflector = m_reflectors[i];
if ( dcsHandler->m_yourAddress.s_addr == yourAddress.s_addr && if (reflector != NULL) {
dcsHandler->m_yourPort == yourPort && if (reflector->m_yourAddress.s_addr == yourAddress.s_addr &&
dcsHandler->m_myPort == myPort) { reflector->m_yourPort == yourPort &&
dcsHandler->processInt(data); reflector->m_myPort == myPort) {
reflector->processInt(data);
return; 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(); std::string repeater = poll.getData2();
in_addr yourAddress = poll.getYourAddress(); in_addr yourAddress = poll.getYourAddress();
unsigned int yourPort = poll.getYourPort(); unsigned int yourPort = poll.getYourPort();
@ -179,10 +211,12 @@ void CDCSHandler::process(CPollData &poll)
unsigned int length = poll.getLength(); unsigned int length = poll.getLength();
// Check to see if we already have a link // Check to see if we already have a link
for (auto it=m_DCSHandlers.begin(); it!=m_DCSHandlers.end(); it++) { for (unsigned int i = 0U; i < m_maxReflectors; i++) {
CDCSHandler *handler = *it; CDCSHandler* handler = m_reflectors[i];
if ( 0==handler->m_reflector.compare(dcsHandler) &&
0==handler->m_repeater.compare(repeater) && if (handler != NULL) {
if (handler->m_reflector == reflector &&
handler->m_repeater == repeater &&
handler->m_yourAddress.s_addr == yourAddress.s_addr && handler->m_yourAddress.s_addr == yourAddress.s_addr &&
handler->m_yourPort == yourPort && handler->m_yourPort == yourPort &&
handler->m_myPort == myPort && handler->m_myPort == myPort &&
@ -193,7 +227,7 @@ void CDCSHandler::process(CPollData &poll)
CPollData reply(handler->m_repeater, handler->m_reflector, handler->m_direction, handler->m_yourAddress, handler->m_yourPort); CPollData reply(handler->m_repeater, handler->m_reflector, handler->m_direction, handler->m_yourAddress, handler->m_yourPort);
handler->m_handler->writePoll(reply); handler->m_handler->writePoll(reply);
return; return;
} else if (0==handler->m_reflector.compare(0, LONG_CALLSIGN_LENGTH - 1U, dcsHandler, 0, LONG_CALLSIGN_LENGTH - 1U) && } 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_yourAddress.s_addr == yourAddress.s_addr &&
handler->m_yourPort == yourPort && handler->m_yourPort == yourPort &&
handler->m_myPort == myPort && handler->m_myPort == myPort &&
@ -204,8 +238,9 @@ void CDCSHandler::process(CPollData &poll)
return; 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)
@ -213,78 +248,143 @@ void CDCSHandler::process(CConnectData &connect)
CD_TYPE type = connect.getType(); CD_TYPE type = connect.getType();
if (type == CT_ACK || type == CT_NAK || type == CT_UNLINK) { if (type == CT_ACK || type == CT_NAK || type == CT_UNLINK) {
for (auto it=m_DCSHandlers.begin(); it!=m_DCSHandlers.end(); ) { for (unsigned int i = 0U; i < m_maxReflectors; i++) {
CDCSHandler *dcsHandler = *it; if (m_reflectors[i] != NULL) {
bool res = dcsHandler->processInt(connect, type); bool res = m_reflectors[i]->processInt(connect, type);
if (res) { if (res) {
delete dcsHandler; delete m_reflectors[i];
it = m_DCSHandlers.erase(it); m_reflectors[i] = NULL;
} else }
it++; }
} }
return; return;
} }
// else if type == CT_LINK1 or type == CT_LINK2 // else if type == CT_LINK1 or type == CT_LINK2
// someone tried to link directly to a Smart Group! in_addr yourAddress = connect.getYourAddress();
printf("CDCSHandler::process(CConnectData) type=CT_LINK%c, from repeater=%s\n", (type==CT_LINK1) ? '1' : '2', connect.getRepeater().c_str()); 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 (unsigned int i = 0U; i < m_maxReflectors; i++) {
for (auto it=m_DCSHandlers.begin(); it!=m_DCSHandlers.end(); it++) { if (m_reflectors[i] != NULL) {
CDCSHandler *dcsHandler = *it; if (m_reflectors[i]->m_direction == DIR_OUTGOING && m_reflectors[i]->m_destination == handler && m_reflectors[i]->m_linkState != DCS_UNLINKING)
if (dcsHandler->m_direction == DIR_OUTGOING && dcsHandler->m_destination == handler && dcsHandler->m_linkState != DCS_UNLINKING)
return; return;
} }
}
CDCSProtocolHandler* protoHandler = m_pool->getHandler(); CDCSProtocolHandler* protoHandler = m_pool->getHandler();
if (protoHandler == NULL) if (protoHandler == NULL)
return; return;
CDCSHandler* dcs = new CDCSHandler(handler, gateway, repeater, protoHandler, address, DCS_PORT, DIR_OUTGOING); CDCSHandler* dcs = new CDCSHandler(handler, gateway, repeater, protoHandler, address, DCS_PORT, DIR_OUTGOING);
if (dcs) {
m_DCSHandlers.push_back(dcs); 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); CConnectData reply(m_gatewayType, repeater, gateway, CT_LINK1, address, DCS_PORT);
protoHandler->writeConnect(reply); 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++) { for (unsigned int i = 0U; i < m_maxReflectors; i++) {
CDCSHandler *dcsHandler = *it; CDCSHandler* reflector = m_reflectors[i];
if (dcsHandler != NULL) { if (reflector != NULL) {
bool found = false; bool found = false;
if (exclude) { if (exclude) {
if (dcsHandler->m_direction == DIR_OUTGOING && dcsHandler->m_destination == handler && dcsHandler->m_reflector.compare(callsign)) { if (reflector->m_direction == DIR_OUTGOING && reflector->m_destination == handler && reflector->m_reflector != callsign) {
printf("Removing outgoing DCS link %s, %s\n", dcsHandler->m_repeater.c_str(), dcsHandler->m_reflector.c_str()); 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) { if (reflector->m_linkState == DCS_LINKING || reflector->m_linkState == DCS_LINKED) {
CConnectData connect(dcsHandler->m_repeater, dcsHandler->m_reflector, CT_UNLINK, dcsHandler->m_yourAddress, dcsHandler->m_yourPort); CConnectData connect(reflector->m_repeater, reflector->m_reflector, CT_UNLINK, reflector->m_yourAddress, reflector->m_yourPort);
dcsHandler->m_handler->writeConnect(connect); reflector->m_handler->writeConnect(connect);
dcsHandler->m_linkState = DCS_UNLINKING; reflector->m_linkState = DCS_UNLINKING;
dcsHandler->m_tryTimer.start(1U); reflector->m_tryTimer.start(1U);
dcsHandler->m_tryCount = 0U; reflector->m_tryCount = 0U;
} }
found = true; found = true;
} }
} else { } else {
if (dcsHandler->m_destination == handler && 0==dcsHandler->m_reflector.compare(callsign)) { if (reflector->m_destination == handler && reflector->m_reflector == callsign) {
printf("Removing DCS link %s, %s\n", dcsHandler->m_repeater.c_str(), dcsHandler->m_reflector.c_str()); 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) { if (reflector->m_linkState == DCS_LINKING || reflector->m_linkState == DCS_LINKED) {
CConnectData connect(dcsHandler->m_repeater, dcsHandler->m_reflector, CT_UNLINK, dcsHandler->m_yourAddress, dcsHandler->m_yourPort); CConnectData connect(reflector->m_repeater, reflector->m_reflector, CT_UNLINK, reflector->m_yourAddress, reflector->m_yourPort);
dcsHandler->m_handler->writeConnect(connect); reflector->m_handler->writeConnect(connect);
dcsHandler->m_linkState = DCS_UNLINKING; reflector->m_linkState = DCS_UNLINKING;
dcsHandler->m_tryTimer.start(1U); reflector->m_tryTimer.start(1U);
dcsHandler->m_tryCount = 0U; reflector->m_tryCount = 0U;
} }
found = true; 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 an active link with incoming traffic, send an EOT to the repeater
if (found) { if (found) {
if (dcsHandler->m_dcsId != 0x00U) { if (reflector->m_dcsId != 0x00U) {
unsigned int seq = dcsHandler->m_dcsSeq + 1U; unsigned int seq = reflector->m_dcsSeq + 1U;
if (seq == 21U) if (seq == 21U)
seq = 0U; seq = 0U;
@ -302,9 +402,9 @@ void CDCSHandler::unlink(IReflectorCallback *handler, const std::string &callsig
data.setData(END_PATTERN_BYTES, DV_FRAME_LENGTH_BYTES); data.setData(END_PATTERN_BYTES, DV_FRAME_LENGTH_BYTES);
data.setSeq(seq); data.setSeq(seq);
data.setEnd(true); 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; m_stateChange = true;
@ -313,71 +413,67 @@ void CDCSHandler::unlink(IReflectorCallback *handler, const std::string &callsig
} }
} }
void CDCSHandler::unlink(CDCSHandler *dcsHandler) void CDCSHandler::unlink()
{ {
if (dcsHandler != NULL) { for (unsigned int i = 0U; i < m_maxReflectors; i++) {
if (dcsHandler->m_repeater.size()) { CDCSHandler* reflector = m_reflectors[i];
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); if (reflector != NULL) {
dcsHandler->m_handler->writeConnect(connect); if (!reflector->m_repeater.empty()) {
wxLogMessage("Unlinking from DCS reflector %s", reflector->m_reflector.c_str());
dcsHandler->m_linkState = DCS_UNLINKING; CConnectData connect(reflector->m_repeater, reflector->m_reflector, CT_UNLINK, reflector->m_yourAddress, reflector->m_yourPort);
dcsHandler->m_tryTimer.start(1U); reflector->m_handler->writeConnect(connect);
dcsHandler->m_tryCount = 0U;
}
}
reflector->m_linkState = DCS_UNLINKING;
reflector->m_tryTimer.start(1U);
reflector->m_tryCount = 0U;
}
} }
void CDCSHandler::unlink()
{
for (auto it=m_DCSHandlers.begin(); it!=m_DCSHandlers.end(); it++) {
CDCSHandler* dcsHandler = *it;
CDCSHandler::unlink(dcsHandler);
} }
} }
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++) { for (unsigned int i = 0U; i < m_maxReflectors; i++) {
CDCSHandler *dcsHandler = *it; if (m_reflectors[i] != NULL)
dcsHandler->writeHeaderInt(handler, header, direction); 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++) { for (unsigned int i = 0U; i < m_maxReflectors; i++) {
CDCSHandler *dcsHandler = *it; if (m_reflectors[i] != NULL)
dcsHandler->writeAMBEInt(handler, data, direction); 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; std::string gateway = reflector;
gateway.resize(LONG_CALLSIGN_LENGTH - 1U, ' '); gateway.resize(LONG_CALLSIGN_LENGTH - 1U);
for (auto it=m_DCSHandlers.begin(); it!=m_DCSHandlers.end(); it++) { for (unsigned int i = 0U; i < m_maxReflectors; i++) {
CDCSHandler *dcsHandler = *it; CDCSHandler* reflector = m_reflectors[i];
if (0 == dcsHandler->m_reflector.compare(0, LONG_CALLSIGN_LENGTH - 1U, gateway)) { if (reflector != NULL) {
if (address.size()) { if (reflector->m_reflector.substr(0, LONG_CALLSIGN_LENGTH - 1U) == gateway) {
if (!address.empty()) {
// A new address, change the value // 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()); wxLogMessage("Changing IP address of DCS gateway or reflector %s to %s", reflector->m_reflector.c_str(), address.c_str());
dcsHandler->m_yourAddress.s_addr = ::inet_addr(address.c_str()); reflector->m_yourAddress.s_addr = ::inet_addr(address.c_str());
} else { } else {
printf("IP address for DCS gateway or dcsHandler %s has been removed\n", dcsHandler->m_reflector.c_str()); wxLogMessage("IP address for DCS gateway or reflector %s has been removed", reflector->m_reflector.c_str());
// No address, this probably shouldn't happen.... // No address, this probably shouldn't happen....
if (dcsHandler->m_direction == DIR_OUTGOING && dcsHandler->m_destination != NULL) if (reflector->m_direction == DIR_OUTGOING && reflector->m_destination != NULL)
dcsHandler->m_destination->linkFailed(DP_DCS, dcsHandler->m_reflector, false); reflector->m_destination->linkFailed(DP_DCS, reflector->m_reflector, false);
m_stateChange = true; m_stateChange = true;
delete dcsHandler; delete m_reflectors[i];
it = m_DCSHandlers.erase(it); m_reflectors[i] = NULL;
it--; }
} }
} }
} }
@ -385,24 +481,23 @@ void CDCSHandler::gatewayUpdate(const std::string &dcsHandler, const std::string
void CDCSHandler::clock(unsigned int ms) void CDCSHandler::clock(unsigned int ms)
{ {
for (auto it=m_DCSHandlers.begin(); it!=m_DCSHandlers.end(); ) { for (unsigned int i = 0U; i < m_maxReflectors; i++) {
CDCSHandler *handler = *it; if (m_reflectors[i] != NULL) {
bool ret = handler->clockInt(ms); bool ret = m_reflectors[i]->clockInt(ms);
if (ret) { if (ret) {
delete handler; delete m_reflectors[i];
it = m_DCSHandlers.erase(it); m_reflectors[i] = NULL;
} else }
it++; }
} }
} }
void CDCSHandler::finalise() void CDCSHandler::finalise()
{ {
for (auto it=m_DCSHandlers.begin(); it!=m_DCSHandlers.end(); ) { for (unsigned int i = 0U; i < m_maxReflectors; i++)
CDCSHandler *handler = *it; delete m_reflectors[i];
delete handler;
it = m_DCSHandlers.erase(it); delete[] m_reflectors;
}
} }
void CDCSHandler::processInt(CAMBEData& data) void CDCSHandler::processInt(CAMBEData& data)
@ -420,7 +515,7 @@ void CDCSHandler::processInt(CAMBEData &data)
if (m_whiteList != NULL) { if (m_whiteList != NULL) {
bool res = m_whiteList->isInList(my); bool res = m_whiteList->isInList(my);
if (!res) { 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; m_dcsId = 0x00U;
return; return;
} }
@ -429,7 +524,7 @@ void CDCSHandler::processInt(CAMBEData &data)
if (m_blackList != NULL) { if (m_blackList != NULL) {
bool res = m_blackList->isInList(my); bool res = m_blackList->isInList(my);
if (res) { 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; m_dcsId = 0x00U;
return; return;
} }
@ -440,13 +535,17 @@ void CDCSHandler::processInt(CAMBEData &data)
switch (m_direction) { switch (m_direction) {
case DIR_OUTGOING: case DIR_OUTGOING:
if (m_reflector.compare(rpt2)) if (m_reflector != (rpt2))
return; return;
if (m_dcsId == 0x00U && seqNo != 0U) if (m_dcsId == 0x00U && seqNo != 0U)
return; return;
if (m_dcsId == 0x00U) { // && seqNo == 0U) { 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_dcsId = id;
m_dcsSeq = 0x00U; m_dcsSeq = 0x00U;
m_inactivityTimer.start(); m_inactivityTimer.start();
@ -482,13 +581,17 @@ void CDCSHandler::processInt(CAMBEData &data)
break; break;
case DIR_INCOMING: case DIR_INCOMING:
if (m_repeater.compare(rpt2)) if (m_repeater != rpt2)
return; return;
if (m_dcsId == 0x00U && seqNo != 0U) if (m_dcsId == 0x00U && seqNo != 0U)
return; return;
if (m_dcsId == 0x00U) { // && seqNo == 0U) { 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_dcsId = id;
m_dcsSeq = 0x00U; m_dcsSeq = 0x00U;
m_inactivityTimer.start(); m_inactivityTimer.start();
@ -537,14 +640,14 @@ bool CDCSHandler::processInt(CConnectData &connect, CD_TYPE type)
switch (type) { switch (type) {
case CT_ACK: case CT_ACK:
if (m_repeater.compare(repeater)) if (m_repeater != repeater)
return false; return false;
if (m_linkState == DCS_LINKING) { 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) 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_tryTimer.stop();
m_stateChange = true; m_stateChange = true;
@ -554,20 +657,20 @@ bool CDCSHandler::processInt(CConnectData &connect, CD_TYPE type)
return false; return false;
case CT_NAK: case CT_NAK:
if (m_repeater.compare(repeater)) if (m_repeater != repeater)
return false; return false;
if (m_linkState == DCS_LINKING) { 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) 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; return true;
} }
if (m_linkState == DCS_UNLINKING) { 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) if (m_direction == DIR_OUTGOING && m_destination != NULL)
m_destination->linkFailed(DP_DCS, m_reflector, false); m_destination->linkFailed(DP_DCS, m_reflector, false);
@ -578,14 +681,14 @@ bool CDCSHandler::processInt(CConnectData &connect, CD_TYPE type)
return false; return false;
case CT_UNLINK: case CT_UNLINK:
if (m_reflector.compare(repeater)) if (m_reflector != repeater)
return false; return false;
if (m_linkState == DCS_LINKED) { 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) 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; m_stateChange = true;
} }
@ -613,20 +716,20 @@ bool CDCSHandler::clockInt(unsigned int ms)
switch (m_linkState) { switch (m_linkState) {
case DCS_LINKING: 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; break;
case DCS_LINKED: 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; break;
case DCS_UNLINKING: 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; break;
default: default:
break; break;
} }
if (m_direction == DIR_OUTGOING) { 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) { if (reconnect) {
CConnectData reply(m_gatewayType, m_repeater, m_reflector, CT_LINK1, m_yourAddress, m_yourPort); CConnectData reply(m_gatewayType, m_repeater, m_reflector, CT_LINK1, m_yourAddress, m_yourPort);
m_handler->writeConnect(reply); m_handler->writeConnect(reply);
@ -738,31 +841,37 @@ bool CDCSHandler::stateChange()
return 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++) { for (unsigned int i = 0U; i < m_maxReflectors; i++) {
CDCSHandler *dcsHandler = *it; CDCSHandler* reflector = m_reflectors[i];
struct tm *tm = ::gmtime(&dcsHandler->m_time); if (reflector != NULL) {
struct tm* tm = ::gmtime(&reflector->m_time);
switch (dcsHandler->m_direction) { switch (reflector->m_direction) {
case DIR_OUTGOING: case DIR_OUTGOING:
if (dcsHandler->m_linkState == DCS_LINKED) { if (reflector->m_linkState == DCS_LINKED) {
fprintf(file, "%04d-%02d-%02d %02d:%02d:%02d: DCS link - Type: Repeater Rptr: %s Refl: %s Dir: Outgoing\n", 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, 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()); reflector->m_repeater.c_str(), GET_DISP_REFLECTOR(reflector).c_str());
file << text;
} }
break; break;
case DIR_INCOMING: case DIR_INCOMING:
if (dcsHandler->m_linkState == DCS_LINKED) { if (reflector->m_linkState == DCS_LINKED) {
fprintf(file, "%04d-%02d-%02d %02d:%02d:%02d: DCS link - Type: Repeater Rptr: %s Refl: %s Dir: Incoming\n", 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, 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()); reflector->m_repeater.c_str(), GET_DISP_REFLECTOR(reflector).c_str());
file << text;
} }
break; break;
} }
} }
} }
}
unsigned int CDCSHandler::calcBackoff() unsigned int CDCSHandler::calcBackoff()
{ {

@ -1,7 +1,6 @@
/* /*
* Copyright (C) 2012,2013,2015 by Jonathan Naylor G4KLX * 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 * 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 * 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. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#pragma once #ifndef DCSHandler_H
#define DCSHandler_H
#include <netinet/in.h> #include <netinet/in.h>
#include <string> #include <string>
#include <cstdio> #include <iostream>
#include <list> #include <fstream>
#include "DCSProtocolHandlerPool.h" #include "DCSProtocolHandlerPool.h"
#include "RemoteRepeaterData.h"
#include "ReflectorCallback.h" #include "ReflectorCallback.h"
#include "DStarDefines.h" #include "DStarDefines.h"
#include "HeaderLogger.h"
#include "CallsignList.h" #include "CallsignList.h"
#include "ConnectData.h" #include "ConnectData.h"
#include "AMBEData.h" #include "AMBEData.h"
@ -36,6 +36,8 @@
#include "Timer.h" #include "Timer.h"
#include "Defs.h" #include "Defs.h"
#define GET_DISP_REFLECTOR(refl) (refl->m_isXlx ? refl->m_xlxReflector : refl->m_reflector)
enum DCS_STATE { enum DCS_STATE {
DCS_LINKING, DCS_LINKING,
DCS_LINKED, DCS_LINKED,
@ -44,13 +46,15 @@ enum DCS_STATE {
class CDCSHandler { class CDCSHandler {
public: public:
static void initialise(unsigned int maxReflectors);
static void setDCSProtocolHandlerPool(CDCSProtocolHandlerPool* pool); static void setDCSProtocolHandlerPool(CDCSProtocolHandlerPool* pool);
static void setDCSProtocolIncoming(CDCSProtocolHandler* handler); static void setDCSProtocolIncoming(CDCSProtocolHandler* handler);
static void setHeaderLogger(CHeaderLogger* logger);
static void setGatewayType(GATEWAY_TYPE type); 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 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(IReflectorCallback* handler, const std::string& reflector = "", bool exclude = true);
static void unlink(CDCSHandler *reflector);
static void unlink(); static void unlink();
static void writeHeader(IReflectorCallback* handler, CHeaderData& header, DIRECTION direction); static void writeHeader(IReflectorCallback* handler, CHeaderData& header, DIRECTION direction);
@ -64,7 +68,7 @@ public:
static void clock(unsigned int ms); static void clock(unsigned int ms);
static bool stateChange(); static bool stateChange();
static void writeStatus(FILE *file); static void writeStatus(std::ofstream& file);
static void setWhiteList(CCallsignList* list); static void setWhiteList(CCallsignList* list);
static void setBlackList(CCallsignList* list); static void setBlackList(CCallsignList* list);
@ -88,7 +92,8 @@ protected:
bool clockInt(unsigned int ms); bool clockInt(unsigned int ms);
private: private:
static std::list<CDCSHandler *> m_DCSHandlers; static unsigned int m_maxReflectors;
static CDCSHandler** m_reflectors;
static CDCSProtocolHandlerPool* m_pool; static CDCSProtocolHandlerPool* m_pool;
static CDCSProtocolHandler* m_incoming; static CDCSProtocolHandler* m_incoming;
@ -97,10 +102,14 @@ private:
static GATEWAY_TYPE m_gatewayType; static GATEWAY_TYPE m_gatewayType;
static CHeaderLogger* m_headerLogger;
static CCallsignList* m_whiteList; static CCallsignList* m_whiteList;
static CCallsignList* m_blackList; static CCallsignList* m_blackList;
std::string m_reflector; std::string m_reflector;
std::string m_xlxReflector;
bool m_isXlx;
std::string m_repeater; std::string m_repeater;
CDCSProtocolHandler* m_handler; CDCSProtocolHandler* m_handler;
in_addr m_yourAddress; in_addr m_yourAddress;
@ -128,3 +137,5 @@ private:
unsigned int calcBackoff(); unsigned int calcBackoff();
}; };
#endif

@ -1,6 +1,5 @@
/* /*
* Copyright (C) 2010-2015 by Jonathan Naylor G4KLX * 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 * 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 * 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. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#include <cassert> #include "RepeaterHandler.h"
#include "DExtraHandler.h" #include "DExtraHandler.h"
#include "DStarDefines.h"
#include "Utils.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; std::string CDExtraHandler::m_callsign;
CDExtraProtocolHandlerPool* CDExtraHandler::m_pool = NULL; CDExtraProtocolHandlerPool* CDExtraHandler::m_pool = NULL;
CDExtraProtocolHandler* CDExtraHandler::m_incoming = NULL;
bool CDExtraHandler::m_stateChange = false; bool CDExtraHandler::m_stateChange = false;
CHeaderLogger* CDExtraHandler::m_headerLogger = NULL;
CCallsignList* CDExtraHandler::m_whiteList = NULL; CCallsignList* CDExtraHandler::m_whiteList = NULL;
CCallsignList* CDExtraHandler::m_blackList = 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) : 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(dextraHandler), m_reflector(reflector),
m_repeater(repeater), m_repeater(repeater),
m_handler(protoHandler), m_handler(protoHandler),
m_yourAddress(address), 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() CDExtraHandler::~CDExtraHandler()
{ {
if (m_direction == DIR_OUTGOING) if (m_direction == DIR_OUTGOING)
@ -78,13 +120,31 @@ CDExtraHandler::~CDExtraHandler()
delete m_header; 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) void CDExtraHandler::setCallsign(const std::string& callsign)
{ {
m_callsign.assign(callsign); m_callsign = callsign;
m_callsign.resize(LONG_CALLSIGN_LENGTH, ' '); m_callsign.resize(LONG_CALLSIGN_LENGTH, ' ');
m_callsign[LONG_CALLSIGN_LENGTH - 1U] = ' '; m_callsign[LONG_CALLSIGN_LENGTH - 1U] = ' ';
} }
void CDExtraHandler::setDExtraProtocolIncoming(CDExtraProtocolHandler* incoming)
{
assert(incoming != NULL);
m_incoming = incoming;
}
void CDExtraHandler::setDExtraProtocolHandlerPool(CDExtraProtocolHandlerPool* pool) void CDExtraHandler::setDExtraProtocolHandlerPool(CDExtraProtocolHandlerPool* pool)
{ {
assert(pool != NULL); assert(pool != NULL);
@ -92,6 +152,16 @@ void CDExtraHandler::setDExtraProtocolHandlerPool(CDExtraProtocolHandlerPool *po
m_pool = pool; m_pool = pool;
} }
void CDExtraHandler::setHeaderLogger(CHeaderLogger* logger)
{
m_headerLogger = logger;
}
void CDExtraHandler::setMaxDongles(unsigned int maxDongles)
{
m_maxDongles = maxDongles;
}
void CDExtraHandler::setWhiteList(CCallsignList* list) void CDExtraHandler::setWhiteList(CCallsignList* list)
{ {
assert(list != NULL); assert(list != NULL);
@ -110,11 +180,11 @@ std::string CDExtraHandler::getIncoming(const std::string &callsign)
{ {
std::string incoming; std::string incoming;
for (auto it=m_DExtraHandlers.begin(); it!=m_DExtraHandlers.end(); it++) { for (unsigned int i = 0U; i < m_maxReflectors; i++) {
CDExtraHandler *dextraHandler = *it; CDExtraHandler* reflector = m_reflectors[i];
if (dextraHandler->m_direction==DIR_INCOMING && 0==dextraHandler->m_repeater.compare(callsign)) { if (reflector != NULL && reflector->m_direction == DIR_INCOMING && reflector->m_repeater == callsign) {
incoming.append(dextraHandler->m_reflector); incoming += reflector->m_reflector;
incoming.append(" "); incoming += " ";
} }
} }
@ -125,15 +195,17 @@ void CDExtraHandler::getInfo(IReflectorCallback *handler, CRemoteRepeaterData &d
{ {
assert(handler != NULL); assert(handler != NULL);
for (auto it=m_DExtraHandlers.begin(); it!=m_DExtraHandlers.end(); it++) { for (unsigned int i = 0U; i < m_maxReflectors; i++) {
CDExtraHandler *dextraHandler = *it; CDExtraHandler* reflector = m_reflectors[i];
if (dextraHandler->m_destination == handler) { if (reflector != NULL) {
if (dextraHandler->m_direction == DIR_INCOMING && 0 == dextraHandler->m_repeater.size()) { if (reflector->m_destination == handler) {
if (dextraHandler->m_linkState != DEXTRA_UNLINKING) if (reflector->m_direction == DIR_INCOMING && reflector->m_repeater.empty()) {
data.addLink(dextraHandler->m_reflector, PROTO_DEXTRA, dextraHandler->m_linkState == DEXTRA_LINKED, DIR_INCOMING, true); if (reflector->m_linkState != DEXTRA_UNLINKING)
data.addLink(reflector->m_reflector, PROTO_DEXTRA, reflector->m_linkState == DEXTRA_LINKED, DIR_INCOMING, true);
} else { } else {
if (dextraHandler->m_linkState != DEXTRA_UNLINKING) if (reflector->m_linkState != DEXTRA_UNLINKING)
data.addLink(dextraHandler->m_reflector, PROTO_DEXTRA, dextraHandler->m_linkState == DEXTRA_LINKED, dextraHandler->m_direction, false); data.addLink(reflector->m_reflector, PROTO_DEXTRA, reflector->m_linkState == DEXTRA_LINKED, reflector->m_direction, false);
}
} }
} }
} }
@ -143,12 +215,12 @@ std::string CDExtraHandler::getDongles()
{ {
std::string dongles; std::string dongles;
for (auto it=m_DExtraHandlers.begin(); it!=m_DExtraHandlers.end(); it++) { for (unsigned int i = 0U; i < m_maxReflectors; i++) {
CDExtraHandler *dextraHandler = *it; CDExtraHandler* reflector = m_reflectors[i];
if (dextraHandler->m_direction==DIR_INCOMING && 0==dextraHandler->m_repeater.size()) { if (reflector != NULL && reflector->m_direction == DIR_INCOMING && reflector->m_repeater.empty()) {
dongles.append("X:"); dongles += "X:";
dongles.append(dextraHandler->m_reflector); dongles += reflector->m_reflector;
dongles.append(" "); dongles += " ";
} }
} }
@ -160,10 +232,13 @@ void CDExtraHandler::process(CHeaderData &header)
in_addr yourAddress = header.getYourAddress(); in_addr yourAddress = header.getYourAddress();
unsigned int yourPort = header.getYourPort(); unsigned int yourPort = header.getYourPort();
for (auto it=m_DExtraHandlers.begin(); it!=m_DExtraHandlers.end(); it++) { for (unsigned int i = 0U; i < m_maxReflectors; i++) {
CDExtraHandler *dextraHandler = *it; CDExtraHandler* reflector = m_reflectors[i];
if (dextraHandler->m_yourAddress.s_addr==yourAddress.s_addr && dextraHandler->m_yourPort==yourPort) if (reflector != NULL) {
dextraHandler->processInt(header); if (reflector->m_yourAddress.s_addr == yourAddress.s_addr &&
reflector->m_yourPort == yourPort)
reflector->processInt(header);
}
} }
} }
@ -172,51 +247,160 @@ void CDExtraHandler::process(CAMBEData &data)
in_addr yourAddress = data.getYourAddress(); in_addr yourAddress = data.getYourAddress();
unsigned int yourPort = data.getYourPort(); unsigned int yourPort = data.getYourPort();
for (auto it=m_DExtraHandlers.begin(); it!=m_DExtraHandlers.end(); it++) { for (unsigned int i = 0U; i < m_maxReflectors; i++) {
CDExtraHandler *dextraHandler = *it; CDExtraHandler* reflector = m_reflectors[i];
if (yourAddress.s_addr==dextraHandler->m_yourAddress.s_addr && yourPort==dextraHandler->m_yourPort) if (reflector != NULL) {
dextraHandler->processInt(data); 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)
{ {
bool found = false;
std::string reflector = poll.getData1(); std::string reflector = poll.getData1();
in_addr yourAddress = poll.getYourAddress(); in_addr yourAddress = poll.getYourAddress();
unsigned int yourPort = poll.getYourPort(); unsigned int yourPort = poll.getYourPort();
// reset all inactivity times from this reflector
for (auto it=m_DExtraHandlers.begin(); it!=m_DExtraHandlers.end(); it++) { // Check to see if we already have a link
CDExtraHandler *handler = *it; for (unsigned int i = 0U; i < m_maxReflectors; i++) {
if ( 0==handler->m_reflector.compare(0, LONG_CALLSIGN_LENGTH-1, reflector, 0, LONG_CALLSIGN_LENGTH-1) && if (m_reflectors[i] != NULL) {
handler->m_yourAddress.s_addr == yourAddress.s_addr && if (m_reflectors[i]->m_reflector.substr(0, LONG_CALLSIGN_LENGTH - 1U) == reflector.substr(0, LONG_CALLSIGN_LENGTH - 1U) &&
handler->m_yourPort == yourPort && m_reflectors[i]->m_yourAddress.s_addr == yourAddress.s_addr &&
handler->m_linkState == DEXTRA_LINKED) { m_reflectors[i]->m_yourPort == yourPort &&
handler->m_pollInactivityTimer.start(); 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(); CD_TYPE type = connect.getType();
if (type == CT_ACK || type == CT_NAK || type == CT_UNLINK) { if (type == CT_ACK || type == CT_NAK || type == CT_UNLINK) {
for (auto it=m_DExtraHandlers.begin(); it!=m_DExtraHandlers.end(); ) { for (unsigned int i = 0U; i < m_maxReflectors; i++) {
CDExtraHandler *dextraHandler = *it; if (m_reflectors[i] != NULL) {
bool res = dextraHandler->processInt(connect, type); bool res = m_reflectors[i]->processInt(connect, type);
if (res) { if (res) {
delete dextraHandler; delete m_reflectors[i];
it = m_DExtraHandlers.erase(it); m_reflectors[i] = NULL;
} else }
it++; }
} }
return; return;
} }
// else if type == CT_LINK1 or type == CT_LINK2 // else if type == CT_LINK1 or type == CT_LINK2
// someone tried to link directly to a Smart Group! in_addr yourAddress = connect.getYourAddress();
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()); 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)
@ -226,46 +410,60 @@ void CDExtraHandler::link(IReflectorCallback *handler, const std::string &repeat
return; return;
CDExtraHandler* dextra = new CDExtraHandler(handler, gateway, repeater, protoHandler, address, DEXTRA_PORT, DIR_OUTGOING); CDExtraHandler* dextra = new CDExtraHandler(handler, gateway, repeater, protoHandler, address, DEXTRA_PORT, DIR_OUTGOING);
if (dextra) {
m_DExtraHandlers.push_back(dextra); 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); CConnectData reply(repeater, gateway, CT_LINK1, address, DEXTRA_PORT);
protoHandler->writeConnect(reply); 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++) { for (unsigned int i = 0U; i < m_maxReflectors; i++) {
CDExtraHandler *dextraHandler = *it; CDExtraHandler* reflector = m_reflectors[i];
if (reflector != NULL) {
bool found = false; bool found = false;
if (exclude) { if (exclude) {
if (dextraHandler->m_direction == DIR_OUTGOING && dextraHandler->m_destination == handler && dextraHandler->m_reflector.compare(callsign)) { if (reflector->m_direction == DIR_OUTGOING && reflector->m_destination == handler && reflector->m_reflector != callsign) {
printf("Removing outgoing DExtra link %s, %s\n", dextraHandler->m_repeater.c_str(), dextraHandler->m_reflector.c_str()); wxLogMessage("Removing outgoing DExtra link %s, %s", reflector->m_repeater.c_str(), reflector->m_reflector.c_str());
if (dextraHandler->m_linkState == DEXTRA_LINKING || dextraHandler->m_linkState == DEXTRA_LINKED) { if (reflector->m_linkState == DEXTRA_LINKING || reflector->m_linkState == DEXTRA_LINKED) {
CConnectData connect(dextraHandler->m_repeater, dextraHandler->m_yourAddress, dextraHandler->m_yourPort); CConnectData connect(reflector->m_repeater, reflector->m_yourAddress, reflector->m_yourPort);
dextraHandler->m_handler->writeConnect(connect); reflector->m_handler->writeConnect(connect);
dextraHandler->m_linkState = DEXTRA_UNLINKING; reflector->m_linkState = DEXTRA_UNLINKING;
dextraHandler->m_destination->linkFailed(DP_DEXTRA, dextraHandler->m_reflector, false); reflector->m_destination->linkFailed(DP_DEXTRA, reflector->m_reflector, false);
} }
found = true; found = true;
} }
} else { } else {
if (dextraHandler->m_destination == handler && 0==dextraHandler->m_reflector.compare(callsign)) { if (reflector->m_destination == handler && reflector->m_reflector == callsign) {
printf("Removing DExtra link %s, %s\n", dextraHandler->m_repeater.c_str(), dextraHandler->m_reflector.c_str()); wxLogMessage("Removing DExtra link %s, %s", reflector->m_repeater.c_str(), reflector->m_reflector.c_str());
if (dextraHandler->m_linkState == DEXTRA_LINKING || dextraHandler->m_linkState == DEXTRA_LINKED) { if (reflector->m_linkState == DEXTRA_LINKING || reflector->m_linkState == DEXTRA_LINKED) {
CConnectData connect(dextraHandler->m_repeater, dextraHandler->m_yourAddress, dextraHandler->m_yourPort); CConnectData connect(reflector->m_repeater, reflector->m_yourAddress, reflector->m_yourPort);
dextraHandler->m_handler->writeConnect(connect); reflector->m_handler->writeConnect(connect);
dextraHandler->m_linkState = DEXTRA_UNLINKING; reflector->m_linkState = DEXTRA_UNLINKING;
dextraHandler->m_destination->linkFailed(DP_DEXTRA, dextraHandler->m_reflector, false); reflector->m_destination->linkFailed(DP_DEXTRA, reflector->m_reflector, false);
} }
found = true; found = true;
@ -274,8 +472,8 @@ void CDExtraHandler::unlink(IReflectorCallback *handler, const std::string &call
// If an active link with incoming traffic, send an EOT to the repeater // If an active link with incoming traffic, send an EOT to the repeater
if (found) { if (found) {
if (dextraHandler->m_dExtraId != 0x00U) { if (reflector->m_dExtraId != 0x00U) {
unsigned int seq = dextraHandler->m_dExtraSeq + 1U; unsigned int seq = reflector->m_dExtraSeq + 1U;
if (seq == 21U) if (seq == 21U)
seq = 0U; seq = 0U;
@ -283,82 +481,79 @@ void CDExtraHandler::unlink(IReflectorCallback *handler, const std::string &call
data.setData(END_PATTERN_BYTES, DV_FRAME_LENGTH_BYTES); data.setData(END_PATTERN_BYTES, DV_FRAME_LENGTH_BYTES);
data.setSeq(seq); data.setSeq(seq);
data.setEnd(true); data.setEnd(true);
data.setId(dextraHandler->m_dExtraId); data.setId(reflector->m_dExtraId);
dextraHandler->m_destination->process(data, dextraHandler->m_direction, AS_DEXTRA); reflector->m_destination->process(data, reflector->m_direction, AS_DEXTRA);
} }
m_stateChange = true; m_stateChange = true;
delete dextraHandler; delete m_reflectors[i];
it = m_DExtraHandlers.erase(it); m_reflectors[i] = NULL;
it--; }
} }
} }
} }
void CDExtraHandler::unlink(CDExtraHandler *dextraHandler) void CDExtraHandler::unlink()
{ {
if (dextraHandler != NULL) { for (unsigned int i = 0U; i < m_maxReflectors; i++) {
if (dextraHandler->m_repeater.size()) { CDExtraHandler* reflector = m_reflectors[i];
printf("Unlinking from DExtra dextraHandler %s\n", dextraHandler->m_reflector.c_str());
CConnectData connect(dextraHandler->m_repeater, dextraHandler->m_yourAddress, dextraHandler->m_yourPort); if (reflector != NULL) {
dextraHandler->m_handler->writeConnect(connect); 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);
reflector->m_linkState = DEXTRA_UNLINKING;
} }
} }
void CDExtraHandler::unlink()
{
for (auto it=m_DExtraHandlers.begin(); it!=m_DExtraHandlers.end(); it++) {
CDExtraHandler *dextraHandler = *it;
CDExtraHandler::unlink(dextraHandler);
} }
} }
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++) { for (unsigned int i = 0U; i < m_maxReflectors; i++) {
CDExtraHandler *dextraHandler = *it; if (m_reflectors[i] != NULL)
dextraHandler->writeHeaderInt(handler, header, direction); 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++) { for (unsigned int i = 0U; i < m_maxReflectors; i++) {
CDExtraHandler *dextraHandler = *it; if (m_reflectors[i] != NULL)
dextraHandler->writeAMBEInt(handler, data, direction); 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; std::string gateway = reflector;
gateway.resize(LONG_CALLSIGN_LENGTH - 1U, ' '); gateway.resize(LONG_CALLSIGN_LENGTH - 1U);
for (auto it=m_DExtraHandlers.begin(); it!=m_DExtraHandlers.end(); it++) { for (unsigned int i = 0U; i < m_maxReflectors; i++) {
CDExtraHandler *dextraHandler = *it; CDExtraHandler* reflector = m_reflectors[i];
if (0==dextraHandler->m_reflector.compare(0, LONG_CALLSIGN_LENGTH-1, gateway)) { if (reflector != NULL) {
if (address.size()) { if (reflector->m_reflector.substr(0, LONG_CALLSIGN_LENGTH - 1U) == gateway) {
if (!address.empty()) {
// A new address, change the value // 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()); wxLogMessage("Changing IP address of DExtra gateway or reflector %s to %s", reflector->m_reflector.c_str(), address.c_str());
dextraHandler->m_yourAddress.s_addr = ::inet_addr(address.c_str()); reflector->m_yourAddress.s_addr = ::inet_addr(address.c_str());
} else { } else {
printf("IP address for DExtra gateway or dextraHandler %s has been removed\n", dextraHandler->m_reflector.c_str()); wxLogMessage("IP address for DExtra gateway or reflector %s has been removed", reflector->m_reflector.c_str());
// No address, this probably shouldn't happen.... // No address, this probably shouldn't happen....
if (dextraHandler->m_direction == DIR_OUTGOING && dextraHandler->m_destination != NULL) if (reflector->m_direction == DIR_OUTGOING && reflector->m_destination != NULL)
dextraHandler->m_destination->linkFailed(DP_DEXTRA, dextraHandler->m_reflector, false); reflector->m_destination->linkFailed(DP_DEXTRA, reflector->m_reflector, false);
m_stateChange = true; m_stateChange = true;
delete dextraHandler; delete m_reflectors[i];
it = m_DExtraHandlers.erase(it); m_reflectors[i] = NULL;
it--; }
} }
} }
} }
@ -366,24 +561,23 @@ void CDExtraHandler::gatewayUpdate(const std::string &dextraHandler, const std::
void CDExtraHandler::clock(unsigned int ms) void CDExtraHandler::clock(unsigned int ms)
{ {
for (auto it=m_DExtraHandlers.begin(); it!=m_DExtraHandlers.end(); ) { for (unsigned int i = 0U; i < m_maxReflectors; i++) {
CDExtraHandler *dextraHandler = *it; if (m_reflectors[i] != NULL) {
bool ret = dextraHandler->clockInt(ms); bool ret = m_reflectors[i]->clockInt(ms);
if (ret) { if (ret) {
delete dextraHandler; delete m_reflectors[i];
it = m_DExtraHandlers.erase(it); m_reflectors[i] = NULL;
} else }
it++; }
} }
} }
void CDExtraHandler::finalise() void CDExtraHandler::finalise()
{ {
for (auto it=m_DExtraHandlers.begin(); it!=m_DExtraHandlers.end(); ) { for (unsigned int i = 0U; i < m_maxReflectors; i++)
CDExtraHandler *handler = *it; delete m_reflectors[i];
delete handler;
it = m_DExtraHandlers.erase(it); delete[] m_reflectors;
}
} }
void CDExtraHandler::processInt(CHeaderData& header) void CDExtraHandler::processInt(CHeaderData& header)
@ -396,7 +590,7 @@ void CDExtraHandler::processInt(CHeaderData& header)
if (m_whiteList != NULL) { if (m_whiteList != NULL) {
bool res = m_whiteList->isInList(my); bool res = m_whiteList->isInList(my);
if (!res) { 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; m_dExtraId = 0x00U;
return; return;
} }
@ -405,7 +599,7 @@ void CDExtraHandler::processInt(CHeaderData& header)
if (m_blackList != NULL) { if (m_blackList != NULL) {
bool res = m_blackList->isInList(my); bool res = m_blackList->isInList(my);
if (res) { 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; m_dExtraId = 0x00U;
return; return;
} }
@ -417,13 +611,17 @@ void CDExtraHandler::processInt(CHeaderData& header)
switch (m_direction) { switch (m_direction) {
case DIR_OUTGOING: { case DIR_OUTGOING: {
// Always a repeater connection // Always a repeater connection
if (m_reflector.compare(rpt2) && m_reflector.compare(rpt1)) if (m_reflector != rpt2 && m_reflector != rpt1)
return; return;
// If we're already processing, ignore the new header // If we're already processing, ignore the new header
if (m_dExtraId != 0x00U) if (m_dExtraId != 0x00U)
return; return;
// Write to Header.log if it's enabled
if (m_headerLogger != NULL)
m_headerLogger->write("DExtra", header);
m_dExtraId = id; m_dExtraId = id;
m_dExtraSeq = 0x00U; m_dExtraSeq = 0x00U;
m_inactivityTimer.start(); m_inactivityTimer.start();
@ -439,15 +637,48 @@ void CDExtraHandler::processInt(CHeaderData& header)
break; break;
case DIR_INCOMING: case DIR_INCOMING:
if (m_repeater.size()) { if (!m_repeater.empty()) {
// A repeater connection // A repeater connection
if (m_repeater.compare(rpt2) && m_repeater.compare(rpt1)) if (m_repeater != rpt2 && m_repeater != rpt1)
return; return;
// If we're already processing, ignore the new header // If we're already processing, ignore the new header
if (m_dExtraId != 0x00U) if (m_dExtraId != 0x00U)
return; 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_dExtraId = id;
m_dExtraSeq = 0x00U; m_dExtraSeq = 0x00U;
m_inactivityTimer.start(); m_inactivityTimer.start();
@ -508,11 +739,11 @@ bool CDExtraHandler::processInt(CConnectData &connect, CD_TYPE type)
switch (type) { switch (type) {
case CT_ACK: case CT_ACK:
if (m_repeater.compare(repeater)) if (m_repeater != repeater)
return false; return false;
if (m_linkState == DEXTRA_LINKING) { 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) if (m_direction == DIR_OUTGOING && m_destination != NULL)
m_destination->linkUp(DP_DEXTRA, m_reflector); m_destination->linkUp(DP_DEXTRA, m_reflector);
@ -526,11 +757,11 @@ bool CDExtraHandler::processInt(CConnectData &connect, CD_TYPE type)
return false; return false;
case CT_NAK: case CT_NAK:
if (m_repeater.compare(repeater)) if (m_repeater != repeater)
return false; return false;
if (m_linkState == DEXTRA_LINKING) { 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) if (m_direction == DIR_OUTGOING && m_destination != NULL)
m_destination->linkRefused(DP_DEXTRA, m_reflector); m_destination->linkRefused(DP_DEXTRA, m_reflector);
@ -541,11 +772,11 @@ bool CDExtraHandler::processInt(CConnectData &connect, CD_TYPE type)
return false; return false;
case CT_UNLINK: case CT_UNLINK:
if (m_reflector.compare(repeater)) if (m_reflector != repeater)
return false; return false;
if (m_linkState == DEXTRA_LINKED) { 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) if (m_direction == DIR_OUTGOING && m_destination != NULL)
m_destination->linkFailed(DP_DEXTRA, m_reflector, false); m_destination->linkFailed(DP_DEXTRA, m_reflector, false);
@ -579,13 +810,13 @@ bool CDExtraHandler::clockInt(unsigned int ms)
switch (m_linkState) { switch (m_linkState) {
case DEXTRA_LINKING: 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; break;
case DEXTRA_LINKED: 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; break;
case DEXTRA_UNLINKING: 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; break;
default: default:
break; break;
@ -608,7 +839,7 @@ bool CDExtraHandler::clockInt(unsigned int ms)
if (m_pollTimer.isRunning() && m_pollTimer.hasExpired()) { if (m_pollTimer.isRunning() && m_pollTimer.hasExpired()) {
if (m_linkState == DEXTRA_LINKED) { if (m_linkState == DEXTRA_LINKED) {
if (m_repeater.size()) { if (!m_repeater.empty()) {
std::string callsign = m_repeater; std::string callsign = m_repeater;
callsign[LONG_CALLSIGN_LENGTH - 1U] = ' '; callsign[LONG_CALLSIGN_LENGTH - 1U] = ' ';
CPollData poll(callsign, m_yourAddress, m_yourPort); CPollData poll(callsign, m_yourAddress, m_yourPort);
@ -667,7 +898,7 @@ void CDExtraHandler::writeHeaderInt(IReflectorCallback *handler, CHeaderData &he
break; break;
case DIR_INCOMING: case DIR_INCOMING:
if (0==m_repeater.size() || m_destination == handler) { if (m_repeater.empty() || m_destination == handler) {
header.setDestination(m_yourAddress, m_yourPort); header.setDestination(m_yourAddress, m_yourPort);
m_handler->writeHeader(header); m_handler->writeHeader(header);
} }
@ -697,7 +928,7 @@ void CDExtraHandler::writeAMBEInt(IReflectorCallback *handler, CAMBEData &data,
break; break;
case DIR_INCOMING: case DIR_INCOMING:
if (0==m_repeater.size() || m_destination == handler) { if (m_repeater.empty() || m_destination == handler) {
data.setDestination(m_yourAddress, m_yourPort); data.setDestination(m_yourAddress, m_yourPort);
m_handler->writeAMBE(data); m_handler->writeAMBE(data);
} }
@ -714,34 +945,43 @@ bool CDExtraHandler::stateChange()
return stateChange; return stateChange;
} }
void CDExtraHandler::writeStatus(FILE *file) void CDExtraHandler::writeStatus(ofstream& file)
{ {
for (auto it=m_DExtraHandlers.begin(); it!=m_DExtraHandlers.end(); it++) { for (unsigned int i = 0U; i < m_maxReflectors; i++) {
CDExtraHandler *dextraHandler = *it; CDExtraHandler* reflector = m_reflectors[i];
struct tm *tm = ::gmtime(&dextraHandler->m_time); if (reflector != NULL) {
std::string text;
struct tm* tm = ::gmtime(&reflector->m_time);
switch (dextraHandler->m_direction) { switch (reflector->m_direction) {
case DIR_OUTGOING: case DIR_OUTGOING:
if (dextraHandler->m_linkState == DEXTRA_LINKED) { if (reflector->m_linkState == DEXTRA_LINKED) {
fprintf(file, "%04d-%02d-%02d %02d:%02d:%02d: DExtra link - Type: Repeater Rptr: %s Refl: %s Dir: Outgoing\n", 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, 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()); reflector->m_repeater.c_str(), reflector->m_reflector.c_str());
file << text;
} }
break; break;
case DIR_INCOMING: case DIR_INCOMING:
if (dextraHandler->m_linkState == DEXTRA_LINKED) { if (reflector->m_linkState == DEXTRA_LINKED) {
if (0==dextraHandler->m_repeater.size()) if (reflector->m_repeater.empty())
fprintf(file, "%04d-%02d-%02d %02d:%02d:%02d: DExtra link - Type: Dongle User: %s Dir: Incoming\n", 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, 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()); reflector->m_reflector.c_str());
else else
fprintf(file, "%04d-%02d-%02d %02d:%02d:%02d: DExtra link - Type: Repeater Rptr: %s Refl: %s Dir: Incoming\n", 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, 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()); reflector->m_repeater.c_str(), reflector->m_reflector.c_str());
file << text;
} }
break; break;
} }
}
} }
} }

@ -1,6 +1,5 @@
/* /*
* Copyright (C) 2010-2013,2015 by Jonathan Naylor G4KLX * 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 * 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 * 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. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#pragma once #ifndef DExtraHander_H
#define DExtraHander_H
#include <netinet/in.h> #include <netinet/in.h>
#include <string> #include <string>
#include <list> #include <fstream>
#include <iostream>
#include "DExtraProtocolHandlerPool.h" #include "DExtraProtocolHandlerPool.h"
#include "RemoteRepeaterData.h"
#include "ReflectorCallback.h" #include "ReflectorCallback.h"
#include "DStarDefines.h" #include "DStarDefines.h"
#include "HeaderLogger.h"
#include "CallsignList.h" #include "CallsignList.h"
#include "ConnectData.h" #include "ConnectData.h"
#include "HeaderData.h" #include "HeaderData.h"
@ -43,12 +44,16 @@ enum DEXTRA_STATE {
class CDExtraHandler { class CDExtraHandler {
public: public:
static void initialise(unsigned int maxReflectors);
static void setCallsign(const std::string& callsign); static void setCallsign(const std::string& callsign);
static void setDExtraProtocolHandlerPool(CDExtraProtocolHandlerPool* pool); 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 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(IReflectorCallback* handler, const std::string& reflector = "", bool exclude = true);
static void unlink(CDExtraHandler *reflector);
static void unlink(); static void unlink();
static void writeHeader(IReflectorCallback* handler, CHeaderData& header, DIRECTION direction); static void writeHeader(IReflectorCallback* handler, CHeaderData& header, DIRECTION direction);
@ -63,7 +68,7 @@ public:
static void clock(unsigned int ms); static void clock(unsigned int ms);
static bool stateChange(); static bool stateChange();
static void writeStatus(FILE *file); static void writeStatus(std::ofstream& file);
static void setWhiteList(CCallsignList* list); static void setWhiteList(CCallsignList* list);
static void setBlackList(CCallsignList* list); static void setBlackList(CCallsignList* list);
@ -77,6 +82,7 @@ public:
protected: 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(); ~CDExtraHandler();
void processInt(CHeaderData& header); void processInt(CHeaderData& header);
@ -89,13 +95,18 @@ protected:
bool clockInt(unsigned int ms); bool clockInt(unsigned int ms);
private: 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 std::string m_callsign;
static CDExtraProtocolHandlerPool* m_pool; static CDExtraProtocolHandlerPool* m_pool;
static CDExtraProtocolHandler* m_incoming;
static bool m_stateChange; static bool m_stateChange;
static CHeaderLogger* m_headerLogger;
static CCallsignList* m_whiteList; static CCallsignList* m_whiteList;
static CCallsignList* m_blackList; static CCallsignList* m_blackList;
@ -119,3 +130,5 @@ private:
unsigned int calcBackoff(); unsigned int calcBackoff();
}; };
#endif

Loading…
Cancel
Save

Powered by TurnKey Linux.