#5 Add Dplus NAT Traversal

pull/32/head
Geoffrey Merck 4 years ago
parent 0050ac116c
commit a1a783b64d

10
.vscode/tasks.json vendored

@ -12,7 +12,10 @@
"ENABLE_DEBUG=1",
"USE_GPSD=1"
],
"group": "build",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": []
},
{
@ -25,10 +28,7 @@
"ENABLE_DEBUG=1",
"USE_GPSD=1"
],
"group": {
"kind": "build",
"isDefault": true
},
"group": "build",
"problemMatcher": []
}
]

@ -357,8 +357,9 @@ void CDPlusHandler::process(CConnectData& connect)
}
}
void CDPlusHandler::link(IReflectorCallback* handler, const std::string& repeater, const std::string &gateway, const in_addr& address)
void CDPlusHandler::link(IReflectorCallback* handler, const std::string& repeater, const std::string &gateway, const in_addr& address, unsigned int& localPort)
{
localPort = 0U;
CDPlusProtocolHandler* protoHandler = m_pool->getHandler();
if (protoHandler == NULL)
return;
@ -377,6 +378,7 @@ void CDPlusHandler::link(IReflectorCallback* handler, const std::string& repeate
if (found) {
CConnectData connect(CT_LINK1, address, DPLUS_PORT);
localPort = protoHandler->getPort();
protoHandler->writeConnect(connect);
m_stateChange = true;
} else {

@ -58,7 +58,7 @@ public:
static void startAuthenticator(const std::string& address, CCacheManager* cache);
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, unsigned int& localPort);
static void relink(IReflectorCallback* handler, const std::string& reflector);
static void unlink(IReflectorCallback* handler, const std::string& reflector = "", bool exclude = true);
static void unlink();

@ -18,7 +18,7 @@
*/
#include "DPlusProtocolHandler.h"
#include "Log.h"
#include "DStarDefines.h"
#include "Utils.h"
@ -107,6 +107,17 @@ bool CDPlusProtocolHandler::writeConnect(const CConnectData& connect)
return m_socket.write(buffer, length, connect.getYourAddress(), connect.getYourPort());
}
void CDPlusProtocolHandler::traverseNat(const std::string& address, unsigned int remotePort)
{
unsigned char buffer = 0x00U;
in_addr addr = CUDPReaderWriter::lookup(address);
CLog::logInfo("DPlus Punching hole to %s:%u", address.c_str(), remotePort);
m_socket.write(&buffer, 1U, addr, remotePort);
}
DPLUS_TYPE CDPlusProtocolHandler::read()
{
bool res = true;

@ -27,6 +27,7 @@
#include "PollData.h"
#include <netinet/in.h>
#include <string>
enum DPLUS_TYPE {
DP_NONE,
@ -49,6 +50,7 @@ public:
bool writeAMBE(const CAMBEData& data);
bool writeConnect(const CConnectData& connect);
bool writePoll(const CPollData& poll);
void traverseNat(const std::string& address, unsigned int remotePort);
DPLUS_TYPE read();
CHeaderData* readHeader();

@ -799,7 +799,6 @@ void CDStarGatewayThread::processIrcDDB()
}
break;
case IDRT_NATTRAVERSAL_DEXTRA: {
std::string address, remotePort;
bool res = m_irc->receiveNATTraversalDextra(address, remotePort);
if(!res)
@ -814,6 +813,22 @@ void CDStarGatewayThread::processIrcDDB()
CLog::logInfo("%s wants to DExtra connect to us, punching UDP Holes through NAT, remote port %s, but DExtra is Disabled", address.c_str(), remotePort.c_str());
}
}
break;
case IDRT_NATTRAVERSAL_DPLUS: {
std::string address, remotePort;
bool res = m_irc->receiveNATTraversalDPlus(address, remotePort);
if(!res)
return;
if(m_dextraEnabled && m_dextraPool != nullptr && m_dplusPool->getIncomingHandler() != nullptr) {
CLog::logInfo("%s wants to DPlus connect to us, punching UDP Holes through NAT, remote port %s", address.c_str(), remotePort.c_str());
auto remotePortInt = boost::lexical_cast<unsigned int>(remotePort);
m_dplusPool->getIncomingHandler()->traverseNat(address, remotePortInt);
}
else {
CLog::logInfo("%s wants to DPlus connect to us, punching UDP Holes through NAT, remote port %s, but DExtra is Disabled", address.c_str(), remotePort.c_str());
}
}
break;
case IDRT_NONE:
return;

@ -34,6 +34,7 @@ enum IRCDDB_RESPONSE_TYPE {
IDRT_REPEATER,
IDRT_NATTRAVERSAL_G2,
IDRT_NATTRAVERSAL_DEXTRA,
IDRT_NATTRAVERSAL_DPLUS,
};
@ -117,6 +118,7 @@ public:
// notify another repeater for NAT Traversal, a false return implies a network error
virtual bool notifyRepeaterG2NatTraversal(const std::string& repeater) = 0;
virtual bool notifyRepeaterDextraNatTraversal(const std::string& repeater, unsigned int myport) = 0;
virtual bool notifyRepeaterDPlusNatTraversal(const std::string& repeater, unsigned int myport) = 0;
// Support for the Smart Group Server
virtual void sendDStarGatewayInfo(const std::string subcommand, const std::vector<std::string> parms) = 0;
@ -142,6 +144,7 @@ public:
virtual bool receiveNATTraversalG2(std::string& address) = 0;
virtual bool receiveNATTraversalDextra(std::string& address, std::string& remotePort) = 0;
virtual bool receiveNATTraversalDPlus(std::string& address, std::string& remotePort) = 0;
virtual void close() = 0; // Implictely kills any threads in the IRC code
};

@ -262,6 +262,9 @@ IRCDDB_RESPONSE_TYPE IRCDDBApp::getReplyMessageType()
if(msgType.compare("NATTRAVERSAL_DEXTRA") == 0)
return IDRT_NATTRAVERSAL_DEXTRA;
if(msgType.compare("NATTRAVERSAL_DPLUS") == 0)
return IDRT_NATTRAVERSAL_DPLUS;
CLog::logWarning("IRCDDBApp::getMessageType: unknown msg type: %s\n", msgType.c_str());
return IDRT_NONE;
@ -643,63 +646,66 @@ bool IRCDDBApp::findUser(const std::string& usrCall)
bool IRCDDBApp::notifyRepeaterG2NatTraversal(const std::string& repeater)
{
auto firstSpacePos = repeater.find_first_of(' ');
if(firstSpacePos == std::string::npos)
std::string nick;
if(!getNickForRepeater(repeater, nick))
return true; //return true because this return value is handled as a network error, whoch is actually uncleve
IRCMessage * ircMessage = new IRCMessage(nick, "NATTRAVERSAL_G2");
m_d->m_sendQ->putMessage(ircMessage);
return true;
}
auto lrepeater = repeater.substr(0, firstSpacePos);
CUtils::ToLower(lrepeater);
bool IRCDDBApp::notifyRepeaterDextraNatTraversal(const std::string& repeater, unsigned int myLocalPort)
{
std::string nick;
std::lock_guard loclUserMap(m_d->m_userMapMutex);
for(unsigned int i = 1; i <= 4U; i++) {
nick = lrepeater + "-" + std::to_string(i);
if(m_d->m_userMap.count(nick) == 1) {
break;
}
nick.clear();
}
if(!getNickForRepeater(repeater, nick))
return true; //return true because this return value is handled as a network error, whoch is actually uncleve
IRCMessage * ircMessage = new IRCMessage(nick, "NATTRAVERSAL_DEXTRA");
ircMessage->addParam(std::to_string(myLocalPort));
m_d->m_sendQ->putMessage(ircMessage);
if(nick.empty()) {
CLog::logDebug("Unable to find IRC nick for repeater %s", repeater.c_str());
return true;
}
}
IRCMessage * ircMessage = new IRCMessage(nick, "NATTRAVERSAL_G2");
bool IRCDDBApp::notifyRepeaterDPlusNatTraversal(const std::string& repeater, unsigned int myLocalPort)
{
std::string nick;
if(!getNickForRepeater(repeater, nick))
return true; //return true because this return value is handled as a network error, whoch is actually unclever
IRCMessage * ircMessage = new IRCMessage(nick, "NATTRAVERSAL_DPLUS");
ircMessage->addParam(std::to_string(myLocalPort));
m_d->m_sendQ->putMessage(ircMessage);
return true;
}
bool IRCDDBApp::notifyRepeaterDextraNatTraversal(const std::string& repeater, unsigned int myLocalPort)
bool IRCDDBApp::getNickForRepeater(const std::string& repeater, std::string& nick) const
{
std::lock_guard lockUserMap(m_d->m_userMapMutex);
auto firstSpacePos = repeater.find_first_of(' ');
if(firstSpacePos == std::string::npos)
return true;
return false;
auto lrepeater = repeater.substr(0, firstSpacePos);
CUtils::ToLower(lrepeater);
std::string nick;
std::lock_guard loclUserMap(m_d->m_userMapMutex);
for(unsigned int i = 1; i <= 4U; i++) {
nick = lrepeater + "-" + std::to_string(i);
if(m_d->m_userMap.count(nick) == 1) {
break;
return true;
}
nick.clear();
}
if(nick.empty()) {
nick.clear();
CLog::logDebug("Unable to find IRC nick for repeater %s", repeater.c_str());
return true;
}
IRCMessage * ircMessage = new IRCMessage(nick, "NATTRAVERSAL_DEXTRA");
ircMessage->addParam(std::to_string(myLocalPort));
m_d->m_sendQ->putMessage(ircMessage);
return true;
return false;
}
void IRCDDBApp::msgChannel(IRCMessage *m)
@ -919,6 +925,13 @@ void IRCDDBApp::msgQuery(IRCMessage *m)
m2->addParam(remotePort);
m_d->m_replyQ.putMessage(m2);
}
else if(m->m_params.size() >= 2U && boost::starts_with(m->m_params[1], "NATTRAVERSAL_DPLUS")) {
IRCMessage * m2 = new IRCMessage(m->m_params[1].substr(0, (std::string("NATTRAVERSAL_DPLUS")).length()));
m2->addParam(m->getPrefixHost());
std::string remotePort = boost::trim_copy(boost::replace_all_copy(m->m_params[1], "NATTRAVERSAL_DPLUS", ""));
m2->addParam(remotePort);
m_d->m_replyQ.putMessage(m2);
}
}
}

@ -69,6 +69,7 @@ public:
bool notifyRepeaterG2NatTraversal(const std::string& repeater);
bool notifyRepeaterDextraNatTraversal(const std::string& repeater, unsigned int myLocalPort);
bool notifyRepeaterDPlusNatTraversal(const std::string& repeater, unsigned int myLocalPort);
bool sendHeard(const std::string& myCall, const std::string& myCallExt, const std::string& yourCall, const std::string& rpt1, const std::string& rpt2, unsigned char flag1,
unsigned char flag2, unsigned char flag3, const std::string& destination, const std::string& tx_msg, const std::string& tx_stats);
@ -93,6 +94,8 @@ private:
bool findServerUser();
unsigned int calculateUsn(const std::string& nick);
std::string getLastEntryTime(int tableID);
bool getNickForRepeater(const std::string& repeater, std::string& user) const;
IRCDDBAppPrivate *m_d;
time_t m_maxTime;
std::future<void> m_future;

@ -288,6 +288,11 @@ bool CIRCDDBClient::notifyRepeaterDextraNatTraversal(const std::string& repeater
return m_d->m_app->notifyRepeaterDextraNatTraversal(repeater, myPort);
}
bool CIRCDDBClient::notifyRepeaterDPlusNatTraversal(const std::string& repeater, unsigned int myPort)
{
return m_d->m_app->notifyRepeaterDPlusNatTraversal(repeater, myPort);
}
// The following functions are for processing received messages
// Get the waiting message type
@ -467,7 +472,7 @@ bool CIRCDDBClient::receiveNATTraversalDextra(std::string& address, std::string&
}
if (m->getCommand().compare("NATTRAVERSAL_DEXTRA")) {
CLog::logDebug("CIRCDDBClient::receiveNATTraversalDextra: wrong message type, expected 'NATTRAVERSAL_G2', got '%s'\n", m->getCommand().c_str());
CLog::logDebug("CIRCDDBClient::receiveNATTraversalDextra: wrong message type, expected 'NATTRAVERSAL_DEXTRA', got '%s'\n", m->getCommand().c_str());
delete m;
return false;
}
@ -485,6 +490,41 @@ bool CIRCDDBClient::receiveNATTraversalDextra(std::string& address, std::string&
return true;
}
bool CIRCDDBClient::receiveNATTraversalDPlus(std::string& address, std::string& remotePort)
{
IRCDDB_RESPONSE_TYPE rt = m_d->m_app->getReplyMessageType();
if(rt != IDRT_NATTRAVERSAL_DPLUS) {
CLog::logDebug("CIRCDDBClient::receiveNATTraversalDPlus: unexpected response type=%d\n", rt);
return false;
}
IRCMessage * m = m_d->m_app->getReplyMessage();
if (m == NULL) {
CLog::logDebug("CIRCDDBClient::receiveNATTraversalDPlus: no message\n");
return false;
}
if (m->getCommand().compare("NATTRAVERSAL_DPLUS")) {
CLog::logDebug("CIRCDDBClient::receiveNATTraversalDPlus: wrong message type, expected 'NATTRAVERSAL_DPLUS', got '%s'\n", m->getCommand().c_str());
delete m;
return false;
}
if (2 != m->getParamCount()) {
CLog::logDebug("CIRCDDBClient::receiveNATTraversalDPlus: unexpected number of message parameters, expected 2, got %d\n", m->getParamCount());
delete m;
return false;
}
address = m->m_params[0];
remotePort = m->m_params[1];
delete m;
return true;
}
void CIRCDDBClient::close() // Implictely kills any threads in the IRC code
{
m_d->client -> stopWork();

@ -109,6 +109,7 @@ public:
// notify another repeater for NAT Traversal, a false return implies a network error
bool notifyRepeaterG2NatTraversal(const std::string& repeater);
bool notifyRepeaterDextraNatTraversal(const std::string& repeater, unsigned int myport);
bool notifyRepeaterDPlusNatTraversal(const std::string& repeater, unsigned int myport);
// Support for the Smart Group Server
void sendDStarGatewayInfo(const std::string subcommand, const std::vector<std::string> parms);
@ -134,6 +135,7 @@ public:
bool receiveNATTraversalG2(std::string& address);
bool receiveNATTraversalDextra(std::string& address, std::string& remotePort);
bool receiveNATTraversalDPlus(std::string& address, std::string& remotePort);
void close(); // Implictely kills any threads in the IRC code

@ -203,7 +203,16 @@ bool CIRCDDBMultiClient::notifyRepeaterDextraNatTraversal(const std::string& rep
return result;
}
bool CIRCDDBMultiClient::notifyRepeaterDPlusNatTraversal(const std::string& repeater, unsigned int myPort)
{
// NAT traversal message does not expect a response over IRC
bool result = true;
for (unsigned int i = 0; i < m_clients.size(); i++) {
result = m_clients[i]->notifyRepeaterDPlusNatTraversal(repeater, myPort) && result;
}
return result;
}
bool CIRCDDBMultiClient::receiveNATTraversalG2(std::string& address)
{
@ -228,6 +237,18 @@ bool CIRCDDBMultiClient::receiveNATTraversalDextra(std::string& address, std::st
return true;
}
bool CIRCDDBMultiClient::receiveNATTraversalDPlus(std::string& address, std::string& remotePort)
{
CIRCDDBMultiClientQuery * item = checkAndGetNextResponse(IDRT_NATTRAVERSAL_DPLUS, "CIRCDDBMultiClient::receiveNATTraversalDextra: unexpected response type");
if (item == NULL)
return false;
address = item->getAddress();
remotePort = item->getRemotePort();
return true;
}
IRCDDB_RESPONSE_TYPE CIRCDDBMultiClient::getMessageType()
{
//process the inner clients at each call

@ -161,6 +161,7 @@ public:
virtual bool findUser(const std::string & userCallsign);
virtual bool notifyRepeaterG2NatTraversal(const std::string& repeater);
virtual bool notifyRepeaterDextraNatTraversal(const std::string& repeater, unsigned int myPort);
virtual bool notifyRepeaterDPlusNatTraversal(const std::string& repeater, unsigned int myPort);
virtual IRCDDB_RESPONSE_TYPE getMessageType();
virtual bool receiveRepeater(std::string & repeaterCallsign, std::string & gatewayCallsign, std::string & address);
virtual bool receiveGateway(std::string & gatewayCallsign, std::string & address);
@ -168,6 +169,7 @@ public:
virtual bool receiveUser(std::string & userCallsign, std::string & repeaterCallsign, std::string & gatewayCallsign, std::string & address, std::string & timeStamp);
virtual bool receiveNATTraversalG2(std::string& address);
virtual bool receiveNATTraversalDextra(std::string& address, std::string& remotePort);
virtual bool receiveNATTraversalDPlus(std::string& address, std::string& remotePort);
virtual void sendDStarGatewayInfo(const std::string subcommand, const std::vector<std::string> parms);
virtual void close();

@ -1342,8 +1342,9 @@ void CRepeaterHandler::resolveRepeaterInt(const std::string& repeater, const std
case DP_DPLUS:
if (m_dplusEnabled) {
m_linkGateway = gateway;
unsigned int localPort = 0U;
addr.s_addr = ::inet_addr(address.c_str());
CDPlusHandler::link(this, m_rptCallsign, m_linkRepeater, addr);
CDPlusHandler::link(this, m_rptCallsign, m_linkRepeater, addr, localPort);
m_linkStatus = LS_LINKING_DPLUS;
} else {
CLog::logInfo("Require D-Plus for linking to %s, but D-Plus is disabled", repeater.c_str());
@ -2287,8 +2288,11 @@ void CRepeaterHandler::linkInt(const std::string& callsign)
switch (data->getProtocol()) {
case DP_DPLUS:
if (m_dplusEnabled) {
unsigned int localPort = 0U;
m_linkStatus = LS_LINKING_DPLUS;
CDPlusHandler::link(this, m_rptCallsign, m_linkRepeater, data->getAddress());
CDPlusHandler::link(this, m_rptCallsign, m_linkRepeater, data->getAddress(), localPort);
if(m_irc != nullptr && localPort > 0U)
m_irc->notifyRepeaterDPlusNatTraversal(m_linkRepeater, localPort);
writeLinkingTo(m_linkRepeater);
triggerInfo();
} else {
@ -2462,8 +2466,11 @@ void CRepeaterHandler::startupInt()
switch (protocol) {
case DP_DPLUS:
if (m_dplusEnabled) {
unsigned int localPort = 0U;
m_linkStatus = LS_LINKING_DPLUS;
CDPlusHandler::link(this, m_rptCallsign, m_linkRepeater, data->getAddress());
CDPlusHandler::link(this, m_rptCallsign, m_linkRepeater, data->getAddress(), localPort);
if(m_irc != nullptr && localPort > 0U)
m_irc->notifyRepeaterDPlusNatTraversal(m_linkRepeater, localPort);
writeLinkingTo(m_linkRepeater);
triggerInfo();
} else {

Loading…
Cancel
Save

Powered by TurnKey Linux.