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,25 +17,33 @@
* 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;
bool CDCSHandler::m_stateChange = false; bool CDCSHandler::m_stateChange = false;
GATEWAY_TYPE CDCSHandler::m_gatewayType = GT_REPEATER; GATEWAY_TYPE CDCSHandler::m_gatewayType = GT_REPEATER;
CCallsignList *CDCSHandler::m_whiteList = NULL; CHeaderLogger* CDCSHandler::m_headerLogger = NULL;
CCallsignList *CDCSHandler::m_blackList = NULL;
std::list<CDCSHandler *> CDCSHandler::m_DCSHandlers; 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) : 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,92 +98,112 @@ CDCSHandler::~CDCSHandler()
m_pool->release(m_handler); 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); assert(pool != NULL);
m_pool = pool; m_pool = pool;
} }
void CDCSHandler::setDCSProtocolIncoming(CDCSProtocolHandler *handler) void CDCSHandler::setDCSProtocolIncoming(CDCSProtocolHandler* handler)
{ {
assert(handler != NULL); assert(handler != NULL);
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;
} }
void CDCSHandler::setWhiteList(CCallsignList *list) void CDCSHandler::setWhiteList(CCallsignList* list)
{ {
assert(list != NULL); assert(list != NULL);
m_whiteList = list; m_whiteList = list;
} }
void CDCSHandler::setBlackList(CCallsignList *list) void CDCSHandler::setBlackList(CCallsignList* list)
{ {
assert(list != NULL); assert(list != NULL);
m_blackList = list; m_blackList = list;
} }
std::string CDCSHandler::getIncoming(const std::string &callsign) 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 += " ";
} }
} }
return incoming; return incoming;
} }
void CDCSHandler::getInfo(IReflectorCallback *handler, CRemoteRepeaterData &data) 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)
} else { data.addLink(GET_DISP_REFLECTOR(reflector), PROTO_DCS, reflector->m_linkState == DCS_LINKED, DIR_INCOMING, true);
if (dcsHandler->m_linkState != DCS_UNLINKING) } else {
data.addLink(dcsHandler->m_reflector, PROTO_DCS, dcsHandler->m_linkState == DCS_LINKED, dcsHandler->m_direction, false); 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(); in_addr yourAddress = data.getYourAddress();
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) {
return; 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(); 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,112 +211,180 @@ 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) {
handler->m_yourAddress.s_addr == yourAddress.s_addr && if (handler->m_reflector == reflector &&
handler->m_yourPort == yourPort && handler->m_repeater == repeater &&
handler->m_myPort == myPort && handler->m_yourAddress.s_addr == yourAddress.s_addr &&
handler->m_direction == DIR_OUTGOING && handler->m_yourPort == yourPort &&
handler->m_linkState == DCS_LINKED && handler->m_myPort == myPort &&
length == 22U) { handler->m_direction == DIR_OUTGOING &&
handler->m_pollInactivityTimer.start(); handler->m_linkState == DCS_LINKED &&
CPollData reply(handler->m_repeater, handler->m_reflector, handler->m_direction, handler->m_yourAddress, handler->m_yourPort); length == 22U) {
handler->m_handler->writePoll(reply); handler->m_pollInactivityTimer.start();
return; CPollData reply(handler->m_repeater, handler->m_reflector, handler->m_direction, handler->m_yourAddress, handler->m_yourPort);
} else if (0==handler->m_reflector.compare(0, LONG_CALLSIGN_LENGTH - 1U, dcsHandler, 0, LONG_CALLSIGN_LENGTH - 1U) && handler->m_handler->writePoll(reply);
handler->m_yourAddress.s_addr == yourAddress.s_addr && return;
handler->m_yourPort == yourPort && } else if (handler->m_reflector.substr(0, LONG_CALLSIGN_LENGTH - 1U) == reflector.substr(0, LONG_CALLSIGN_LENGTH - 1U) &&
handler->m_myPort == myPort && handler->m_yourAddress.s_addr == yourAddress.s_addr &&
handler->m_direction == DIR_INCOMING && handler->m_yourPort == yourPort &&
handler->m_linkState == DCS_LINKED && handler->m_myPort == myPort &&
length == 17U) { handler->m_direction == DIR_INCOMING &&
handler->m_pollInactivityTimer.start(); handler->m_linkState == DCS_LINKED &&
return; 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(); 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,82 +402,78 @@ 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;
} }
} }
} }
} }
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);
dcsHandler->m_handler->writeConnect(connect);
dcsHandler->m_linkState = DCS_UNLINKING; if (reflector != NULL) {
dcsHandler->m_tryTimer.start(1U); if (!reflector->m_repeater.empty()) {
dcsHandler->m_tryCount = 0U; 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() reflector->m_linkState = DCS_UNLINKING;
{ reflector->m_tryTimer.start(1U);
for (auto it=m_DCSHandlers.begin(); it!=m_DCSHandlers.end(); it++) { reflector->m_tryCount = 0U;
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) {
// A new address, change the value if (!address.empty()) {
printf("Changing IP address of DCS gateway or dcsHandler %s to %s\n", dcsHandler->m_reflector.c_str(), address.c_str()); // A new address, change the value
dcsHandler->m_yourAddress.s_addr = ::inet_addr(address.c_str()); wxLogMessage("Changing IP address of DCS gateway or reflector %s to %s", reflector->m_reflector.c_str(), address.c_str());
} else { reflector->m_yourAddress.s_addr = ::inet_addr(address.c_str());
printf("IP address for DCS gateway or dcsHandler %s has been removed\n", dcsHandler->m_reflector.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 (dcsHandler->m_direction == DIR_OUTGOING && dcsHandler->m_destination != NULL) // No address, this probably shouldn't happen....
dcsHandler->m_destination->linkFailed(DP_DCS, dcsHandler->m_reflector, false); if (reflector->m_direction == DIR_OUTGOING && reflector->m_destination != NULL)
reflector->m_destination->linkFailed(DP_DCS, reflector->m_reflector, false);
m_stateChange = true;
m_stateChange = true;
delete dcsHandler;
it = m_DCSHandlers.erase(it); delete m_reflectors[i];
it--; m_reflectors[i] = NULL;
}
} }
} }
} }
@ -385,27 +481,26 @@ 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)
{ {
// Make a copy of the AMBE data so that any changes made here don't modify the original // Make a copy of the AMBE data so that any changes made here don't modify the original
CAMBEData temp(data); CAMBEData temp(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();
@ -456,7 +555,7 @@ void CDCSHandler::processInt(CAMBEData &data)
m_destination->process(header, m_direction, AS_DCS); m_destination->process(header, m_direction, AS_DCS);
} }
if (id == m_dcsId) { if (id == m_dcsId) {
m_pollInactivityTimer.start(); m_pollInactivityTimer.start();
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();
@ -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(); in_addr yourAddress = connect.getYourAddress();
unsigned int yourPort = connect.getYourPort(); unsigned int yourPort = connect.getYourPort();
unsigned int myPort = connect.getMyPort(); 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) if (m_yourAddress.s_addr != yourAddress.s_addr || m_yourPort != yourPort || m_myPort != myPort)
return false; return false;
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);
@ -676,7 +779,7 @@ bool CDCSHandler::clockInt(unsigned int ms)
return false; 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) if (m_linkState != DCS_LINKED)
return; return;
@ -701,7 +804,7 @@ void CDCSHandler::writeHeaderInt(IReflectorCallback *handler, CHeaderData& heade
m_rptCall2 = header.getRptCall2(); 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) if (m_linkState != DCS_LINKED)
return; return;
@ -738,28 +841,34 @@ 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) {
case DIR_OUTGOING: switch (reflector->m_direction) {
if (dcsHandler->m_linkState == DCS_LINKED) { case DIR_OUTGOING:
fprintf(file, "%04d-%02d-%02d %02d:%02d:%02d: DCS link - Type: Repeater Rptr: %s Refl: %s Dir: Outgoing\n", if (reflector->m_linkState == DCS_LINKED) {
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, std::string text;
dcsHandler->m_repeater.c_str(), dcsHandler->m_reflector.c_str()); 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,
break; reflector->m_repeater.c_str(), GET_DISP_REFLECTOR(reflector).c_str());
file << text;
case DIR_INCOMING: }
if (dcsHandler->m_linkState == DCS_LINKED) { break;
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, case DIR_INCOMING:
dcsHandler->m_repeater.c_str(), dcsHandler->m_reflector.c_str()); if (reflector->m_linkState == DCS_LINKED) {
} std::string text;
break; 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) 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,71 +46,78 @@ enum DCS_STATE {
class CDCSHandler { class CDCSHandler {
public: public:
static void setDCSProtocolHandlerPool(CDCSProtocolHandlerPool *pool); static void initialise(unsigned int maxReflectors);
static void setDCSProtocolIncoming(CDCSProtocolHandler *handler);
static void setDCSProtocolHandlerPool(CDCSProtocolHandlerPool* pool);
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);
static void writeAMBE(IReflectorCallback *handler, CAMBEData &data, DIRECTION direction); static void writeAMBE(IReflectorCallback* handler, CAMBEData& data, DIRECTION direction);
static void process(CAMBEData &header); static void process(CAMBEData& header);
static void process(CPollData &data); static void process(CPollData& data);
static void process(CConnectData &connect); 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 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);
static void finalise(); 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: 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(); ~CDCSHandler();
void processInt(CAMBEData &data); void processInt(CAMBEData& data);
bool processInt(CConnectData &connect, CD_TYPE type); bool processInt(CConnectData& connect, CD_TYPE type);
void writeHeaderInt(IReflectorCallback *handler, CHeaderData &header, DIRECTION direction); void writeHeaderInt(IReflectorCallback* handler, CHeaderData& header, DIRECTION direction);
void writeAMBEInt(IReflectorCallback *handler, CAMBEData &data, DIRECTION direction); void writeAMBEInt(IReflectorCallback* handler, CAMBEData& data, DIRECTION direction);
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;
static bool m_stateChange; static bool m_stateChange;
static GATEWAY_TYPE m_gatewayType; static GATEWAY_TYPE m_gatewayType;
static CCallsignList *m_whiteList; static CHeaderLogger* m_headerLogger;
static CCallsignList *m_blackList;
std::string m_reflector; static CCallsignList* m_whiteList;
std::string m_repeater; static CCallsignList* m_blackList;
CDCSProtocolHandler *m_handler;
std::string m_reflector;
std::string m_xlxReflector;
bool m_isXlx;
std::string m_repeater;
CDCSProtocolHandler* m_handler;
in_addr m_yourAddress; in_addr m_yourAddress;
unsigned int m_yourPort; unsigned int m_yourPort;
unsigned int m_myPort; unsigned int m_myPort;
DIRECTION m_direction; DIRECTION m_direction;
DCS_STATE m_linkState; DCS_STATE m_linkState;
IReflectorCallback *m_destination; IReflectorCallback* m_destination;
time_t m_time; time_t m_time;
CTimer m_pollTimer; CTimer m_pollTimer;
CTimer m_pollInactivityTimer; CTimer m_pollInactivityTimer;
@ -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;
CCallsignList *CDExtraHandler::m_whiteList = NULL; CHeaderLogger* CDExtraHandler::m_headerLogger = NULL;
CCallsignList *CDExtraHandler::m_blackList = 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) : 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,62 +120,92 @@ 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::setDExtraProtocolHandlerPool(CDExtraProtocolHandlerPool *pool) void CDExtraHandler::setDExtraProtocolIncoming(CDExtraProtocolHandler* incoming)
{
assert(incoming != NULL);
m_incoming = incoming;
}
void CDExtraHandler::setDExtraProtocolHandlerPool(CDExtraProtocolHandlerPool* pool)
{ {
assert(pool != NULL); assert(pool != NULL);
m_pool = pool; 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); assert(list != NULL);
m_whiteList = list; m_whiteList = list;
} }
void CDExtraHandler::setBlackList(CCallsignList *list) void CDExtraHandler::setBlackList(CCallsignList* list)
{ {
assert(list != NULL); assert(list != NULL);
m_blackList = list; m_blackList = list;
} }
std::string CDExtraHandler::getIncoming(const std::string &callsign) 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 += " ";
} }
} }
return incoming; return incoming;
} }
void CDExtraHandler::getInfo(IReflectorCallback *handler, CRemoteRepeaterData &data) void CDExtraHandler::getInfo(IReflectorCallback* handler, CRemoteRepeaterData& data)
{ {
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)
} else { data.addLink(reflector->m_reflector, PROTO_DEXTRA, reflector->m_linkState == DEXTRA_LINKED, DIR_INCOMING, true);
if (dextraHandler->m_linkState != DEXTRA_UNLINKING) } else {
data.addLink(dextraHandler->m_reflector, PROTO_DEXTRA, dextraHandler->m_linkState == DEXTRA_LINKED, dextraHandler->m_direction, false); 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; 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 += " ";
} }
} }
return dongles; return dongles;
} }
void CDExtraHandler::process(CHeaderData &header) 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);
}
}
} }
void CDExtraHandler::process(CAMBEData &data) 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)
{ {
std::string reflector = poll.getData1(); bool found = false;
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)
{ {
CDExtraProtocolHandler *protoHandler = m_pool->getHandler(); CDExtraProtocolHandler* protoHandler = m_pool->getHandler();
if (protoHandler == NULL) if (protoHandler == NULL)
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 (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 (reflector->m_linkState == DEXTRA_LINKING || reflector->m_linkState == DEXTRA_LINKED) {
if (dextraHandler->m_direction == DIR_OUTGOING && dextraHandler->m_destination == handler && dextraHandler->m_reflector.compare(callsign)) { CConnectData connect(reflector->m_repeater, reflector->m_yourAddress, reflector->m_yourPort);
printf("Removing outgoing DExtra link %s, %s\n", dextraHandler->m_repeater.c_str(), dextraHandler->m_reflector.c_str()); reflector->m_handler->writeConnect(connect);
if (dextraHandler->m_linkState == DEXTRA_LINKING || dextraHandler->m_linkState == DEXTRA_LINKED) { reflector->m_linkState = DEXTRA_UNLINKING;
CConnectData connect(dextraHandler->m_repeater, dextraHandler->m_yourAddress, dextraHandler->m_yourPort);
dextraHandler->m_handler->writeConnect(connect);
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; if (reflector->m_linkState == DEXTRA_LINKING || reflector->m_linkState == DEXTRA_LINKED) {
} CConnectData connect(reflector->m_repeater, reflector->m_yourAddress, reflector->m_yourPort);
} else { reflector->m_handler->writeConnect(connect);
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 (dextraHandler->m_linkState == DEXTRA_LINKING || dextraHandler->m_linkState == DEXTRA_LINKED) { reflector->m_linkState = DEXTRA_UNLINKING;
CConnectData connect(dextraHandler->m_repeater, dextraHandler->m_yourAddress, dextraHandler->m_yourPort);
dextraHandler->m_handler->writeConnect(connect);
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 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;
CAMBEData data; CAMBEData data;
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);
}
}
void CDExtraHandler::unlink() reflector->m_linkState = DEXTRA_UNLINKING;
{ }
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) {
// A new address, change the value if (!address.empty()) {
printf("Changing IP address of DExtra gateway or dextraHandler %s to %s\n", dextraHandler->m_reflector.c_str(), address.c_str()); // A new address, change the value
dextraHandler->m_yourAddress.s_addr = ::inet_addr(address.c_str()); wxLogMessage("Changing IP address of DExtra gateway or reflector %s to %s", reflector->m_reflector.c_str(), address.c_str());
} else { reflector->m_yourAddress.s_addr = ::inet_addr(address.c_str());
printf("IP address for DExtra gateway or dextraHandler %s has been removed\n", dextraHandler->m_reflector.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 (dextraHandler->m_direction == DIR_OUTGOING && dextraHandler->m_destination != NULL) // No address, this probably shouldn't happen....
dextraHandler->m_destination->linkFailed(DP_DEXTRA, dextraHandler->m_reflector, false); if (reflector->m_direction == DIR_OUTGOING && reflector->m_destination != NULL)
reflector->m_destination->linkFailed(DP_DEXTRA, reflector->m_reflector, false);
m_stateChange = true;
m_stateChange = true;
delete dextraHandler;
it = m_DExtraHandlers.erase(it); delete m_reflectors[i];
it--; m_reflectors[i] = NULL;
}
} }
} }
} }
@ -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();
@ -464,7 +695,7 @@ void CDExtraHandler::processInt(CHeaderData& header)
} }
} }
void CDExtraHandler::processInt(CAMBEData &data) void CDExtraHandler::processInt(CAMBEData& data)
{ {
if (m_linkState != DEXTRA_LINKED) if (m_linkState != DEXTRA_LINKED)
return; 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(); in_addr yourAddress = connect.getYourAddress();
unsigned int yourPort = connect.getYourPort(); 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) if (m_yourAddress.s_addr != yourAddress.s_addr || m_yourPort != yourPort)
return false; return false;
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,9 +839,9 @@ 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);
m_handler->writePoll(poll); m_handler->writePoll(poll);
} else { } else {
@ -645,7 +876,7 @@ bool CDExtraHandler::clockInt(unsigned int ms)
return false; 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) if (m_linkState != DEXTRA_LINKED)
return; return;
@ -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);
} }
@ -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) if (m_linkState != DEXTRA_LINKED)
return; return;
@ -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,33 +945,42 @@ 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;
switch (dextraHandler->m_direction) {
case DIR_OUTGOING: struct tm* tm = ::gmtime(&reflector->m_time);
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", switch (reflector->m_direction) {
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, case DIR_OUTGOING:
dextraHandler->m_repeater.c_str(), dextraHandler->m_reflector.c_str()); 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",
break; 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) 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,70 +44,80 @@ enum DEXTRA_STATE {
class CDExtraHandler { class CDExtraHandler {
public: public:
static void setCallsign(const std::string &callsign); static void initialise(unsigned int maxReflectors);
static void setDExtraProtocolHandlerPool(CDExtraProtocolHandlerPool *pool);
static void link(IReflectorCallback *handler, const std::string &repeater, const std::string &reflector, const in_addr &address); static void setCallsign(const std::string& callsign);
static void unlink(IReflectorCallback *handler, const std::string &reflector = std::string(""), bool exclude = true); static void setDExtraProtocolHandlerPool(CDExtraProtocolHandlerPool* pool);
static void unlink(CDExtraHandler *reflector); 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 unlink();
static void writeHeader(IReflectorCallback *handler, CHeaderData &header, DIRECTION direction); static void writeHeader(IReflectorCallback* handler, CHeaderData& header, DIRECTION direction);
static void writeAMBE(IReflectorCallback *handler, CAMBEData &data, DIRECTION direction); static void writeAMBE(IReflectorCallback* handler, CAMBEData& data, DIRECTION direction);
static void process(CHeaderData &header); static void process(CHeaderData& header);
static void process(CAMBEData &data); static void process(CAMBEData& data);
static void process(const CPollData &poll); static void process(const CPollData& poll);
static void process(CConnectData &connect); 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 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);
static void finalise(); 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(); static std::string getDongles();
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);
void processInt(CAMBEData &data); void processInt(CAMBEData& data);
bool processInt(CConnectData &connect, CD_TYPE type); bool processInt(CConnectData& connect, CD_TYPE type);
void writeHeaderInt(IReflectorCallback *handler, CHeaderData &header, DIRECTION direction); void writeHeaderInt(IReflectorCallback* handler, CHeaderData& header, DIRECTION direction);
void writeAMBEInt(IReflectorCallback *handler, CAMBEData &data, DIRECTION direction); void writeAMBEInt(IReflectorCallback* handler, CAMBEData& data, DIRECTION direction);
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 CCallsignList *m_whiteList; static CHeaderLogger* m_headerLogger;
static CCallsignList *m_blackList;
static CCallsignList* m_whiteList;
static CCallsignList* m_blackList;
std::string m_reflector; std::string m_reflector;
std::string m_repeater; std::string m_repeater;
CDExtraProtocolHandler *m_handler; CDExtraProtocolHandler* m_handler;
in_addr m_yourAddress; in_addr m_yourAddress;
unsigned int m_yourPort; unsigned int m_yourPort;
DIRECTION m_direction; DIRECTION m_direction;
DEXTRA_STATE m_linkState; DEXTRA_STATE m_linkState;
IReflectorCallback *m_destination; IReflectorCallback* m_destination;
time_t m_time; time_t m_time;
CTimer m_pollTimer; CTimer m_pollTimer;
CTimer m_pollInactivityTimer; CTimer m_pollInactivityTimer;
@ -115,7 +126,9 @@ private:
unsigned int m_dExtraId; unsigned int m_dExtraId;
unsigned int m_dExtraSeq; unsigned int m_dExtraSeq;
CTimer m_inactivityTimer; CTimer m_inactivityTimer;
CHeaderData *m_header; CHeaderData* m_header;
unsigned int calcBackoff(); unsigned int calcBackoff();
}; };
#endif

Loading…
Cancel
Save

Powered by TurnKey Linux.