#5 first implementaion of Dextra NatTraversal

pull/32/head
Geoffrey Merck 4 years ago
parent bff3232911
commit 13335e4924

@ -71,7 +71,8 @@
"system_error": "cpp",
"thread": "cpp",
"typeindex": "cpp",
"variant": "cpp"
"variant": "cpp",
"iostream": "cpp"
},
"editor.tokenColorCustomizations": {
"textMateRules": [

@ -19,7 +19,7 @@
*/
#include "DExtraProtocolHandler.h"
#include "Log.h"
#include "Utils.h"
// #define DUMP_TX
@ -113,6 +113,17 @@ bool CDExtraProtocolHandler::writeConnect(const CConnectData& connect)
return true;
}
void CDExtraProtocolHandler::traverseNat(const std::string& address, unsigned int remotePort)
{
unsigned char buffer = 0x00U;
in_addr addr = CUDPReaderWriter::lookup(address);
CLog::logInfo("DExtra Punching hole to %s:%u", address.c_str(), remotePort);
m_socket.write(&buffer, 1U, addr, remotePort);
}
DEXTRA_TYPE CDExtraProtocolHandler::read()
{
bool res = true;

@ -51,6 +51,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);
DEXTRA_TYPE read();
CHeaderData* readHeader();

@ -22,6 +22,7 @@
#include <chrono>
#include <iostream>
#include <fstream>
#include <boost/lexical_cast.hpp>
#include "DStarGatewayThread.h"
#include "DStarGatewayDefs.h"
@ -788,9 +789,31 @@ void CDStarGatewayThread::processIrcDDB()
if(!res)
return;
if(m_g2Handler != nullptr) {
CLog::logInfo("%s wants to G2 route to us, punching UDP Holes through NAT", address.c_str());
m_g2Handler->traverseNat(address);
}
else {
CLog::logInfo("%s wants to G2 route to us, but G2 is disabled", address.c_str());
}
}
break;
case IDRT_NATTRAVERSAL_DEXTRA: {
std::string address, remotePort;
bool res = m_irc->receiveNATTraversalDextra(address, remotePort);
if(!res)
return;
if(m_dextraEnabled && m_dextraPool != nullptr && m_dextraPool->getIncomingHandler() != nullptr) {
CLog::logInfo("%s wants to DExtra 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_dextraPool->getIncomingHandler()->traverseNat(address, remotePortInt);
}
else {
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_NONE:
return;

@ -32,7 +32,8 @@ enum IRCDDB_RESPONSE_TYPE {
IDRT_USER,
IDRT_GATEWAY,
IDRT_REPEATER,
IDRT_NATTRAVERSAL_G2
IDRT_NATTRAVERSAL_G2,
IDRT_NATTRAVERSAL_DEXTRA,
};
@ -114,7 +115,8 @@ public:
virtual bool findUser(const std::string& userCallsign) = 0;
// notify another repeater for NAT Traversal, a false return implies a network error
virtual bool notifyRepeaterNatTraversal(const std::string& repeater) = 0;
virtual bool notifyRepeaterG2NatTraversal(const std::string& repeater) = 0;
virtual bool notifyRepeaterDextraNatTraversal(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;
@ -139,6 +141,7 @@ public:
virtual bool receiveUser(std::string& userCallsign, std::string& repeaterCallsign, std::string& gatewayCallsign, std::string& address, std::string& timeStamp) = 0;
virtual bool receiveNATTraversalG2(std::string& address) = 0;
virtual bool receiveNATTraversalDextra(std::string& address, std::string& remotePort) = 0;
virtual void close() = 0; // Implictely kills any threads in the IRC code
};

@ -259,6 +259,9 @@ IRCDDB_RESPONSE_TYPE IRCDDBApp::getReplyMessageType()
if(msgType.compare("NATTRAVERSAL_G2") == 0)
return IDRT_NATTRAVERSAL_G2;
if(msgType.compare("NATTRAVERSAL_DEXTRA") == 0)
return IDRT_NATTRAVERSAL_DEXTRA;
CLog::logWarning("IRCDDBApp::getMessageType: unknown msg type: %s\n", msgType.c_str());
return IDRT_NONE;
@ -638,7 +641,7 @@ bool IRCDDBApp::findUser(const std::string& usrCall)
return true;
}
bool IRCDDBApp::notifyRepeaterNatTraversal(const std::string& repeater)
bool IRCDDBApp::notifyRepeaterG2NatTraversal(const std::string& repeater)
{
auto firstSpacePos = repeater.find_first_of(' ');
if(firstSpacePos == std::string::npos)
@ -668,6 +671,37 @@ bool IRCDDBApp::notifyRepeaterNatTraversal(const std::string& repeater)
return true;
}
bool IRCDDBApp::notifyRepeaterDextraNatTraversal(const std::string& repeater, unsigned int myLocalPort)
{
auto firstSpacePos = repeater.find_first_of(' ');
if(firstSpacePos == std::string::npos)
return true;
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;
}
nick.clear();
}
if(nick.empty()) {
CLog::logDebug("Unable to dind 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;
}
void IRCDDBApp::msgChannel(IRCMessage *m)
{
if (0==m->getPrefixNick().compare(0, 2, "s-") && m->m_numParams>=2) // server msg
@ -873,11 +907,18 @@ void IRCDDBApp::msgQuery(IRCMessage *m)
}
}
else if(m->m_params[0] == m_d->m_myNick) {
if(boost::starts_with(m->m_params[1], "NATTRAVERSAL_")) {
if(m->m_params.size() >= 2U && m->m_params[1] == "NATTRAVERSAL_G2") {
IRCMessage * m2 = new IRCMessage(m->m_params[1]);
m2->addParam(m->getPrefixHost());
m_d->m_replyQ.putMessage(m2);
}
else if(m->m_params.size() >= 2U && boost::starts_with(m->m_params[1], "NATTRAVERSAL_DEXTRA")) {
IRCMessage * m2 = new IRCMessage(m->m_params[1].substr(0, (std::string("NATTRAVERSAL_DEXTRA")).length()));
m2->addParam(m->getPrefixHost());
std::string remotePort = boost::trim_copy(boost::replace_all_copy(m->m_params[1], "NATTRAVERSAL_DEXTRA", ""));
m2->addParam(remotePort);
m_d->m_replyQ.putMessage(m2);
}
}
}

@ -67,7 +67,8 @@ public:
bool findRepeater(const std::string& s);
bool findGateway(const std::string& s);
bool notifyRepeaterNatTraversal(const std::string& repeater);
bool notifyRepeaterG2NatTraversal(const std::string& repeater);
bool notifyRepeaterDextraNatTraversal(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);

@ -278,9 +278,14 @@ bool CIRCDDBClient::findUser(const std::string& userCallsign)
return m_d->m_app->findUser(usr);
}
bool CIRCDDBClient::notifyRepeaterNatTraversal(const std::string& repeater)
bool CIRCDDBClient::notifyRepeaterG2NatTraversal(const std::string& repeater)
{
return m_d->m_app->notifyRepeaterNatTraversal(repeater);
return m_d->m_app->notifyRepeaterG2NatTraversal(repeater);
}
bool CIRCDDBClient::notifyRepeaterDextraNatTraversal(const std::string& repeater, unsigned int myPort)
{
return m_d->m_app->notifyRepeaterDextraNatTraversal(repeater, myPort);
}
// The following functions are for processing received messages
@ -423,7 +428,7 @@ bool CIRCDDBClient::receiveNATTraversalG2(std::string& address)
IRCMessage * m = m_d->m_app->getReplyMessage();
if (m == NULL) {
CLog::logDebug("CIRCDDBClient::receiveUser: no message\n");
CLog::logDebug("CIRCDDBClient::receiveNATTraversalG2: no message\n");
return false;
}
@ -445,6 +450,41 @@ bool CIRCDDBClient::receiveNATTraversalG2(std::string& address)
return true;
}
bool CIRCDDBClient::receiveNATTraversalDextra(std::string& address, std::string& remotePort)
{
IRCDDB_RESPONSE_TYPE rt = m_d->m_app->getReplyMessageType();
if(rt != IDRT_NATTRAVERSAL_DEXTRA) {
CLog::logDebug("CIRCDDBClient::receiveNATTraversalDextra: unexpected response type=%d\n", rt);
return false;
}
IRCMessage * m = m_d->m_app->getReplyMessage();
if (m == NULL) {
CLog::logDebug("CIRCDDBClient::receiveNATTraversalDextra: no message\n");
return false;
}
if (m->getCommand().compare("NATTRAVERSAL_DEXTRA")) {
CLog::logDebug("CIRCDDBClient::receiveNATTraversalDextra: wrong message type, expected 'NATTRAVERSAL_G2', got '%s'\n", m->getCommand().c_str());
delete m;
return false;
}
if (2 != m->getParamCount()) {
CLog::logDebug("CIRCDDBClient::receiveNATTraversalDextra: 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();

@ -107,7 +107,8 @@ public:
bool findUser(const std::string& userCallsign);
// notify another repeater for NAT Traversal, a false return implies a network error
bool notifyRepeaterNatTraversal(const std::string& repeater);
bool notifyRepeaterG2NatTraversal(const std::string& repeater);
bool notifyRepeaterDextraNatTraversal(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);
@ -132,6 +133,7 @@ public:
bool receiveUser(std::string& userCallsign, std::string& repeaterCallsign, std::string& gatewayCallsign, std::string& address, std::string& timeStamp);
bool receiveNATTraversalG2(std::string& address);
bool receiveNATTraversalDextra(std::string& address, std::string& remotePort);
void close(); // Implictely kills any threads in the IRC code

@ -150,7 +150,7 @@ void CIRCDDBMultiClient::sendDStarGatewayInfo(const std::string subcommand, cons
bool CIRCDDBMultiClient::findGateway(const std::string & gatewayCallsign)
{
pushQuery(IDRT_GATEWAY, gatewayCallsign, new CIRCDDBMultiClientQuery("", "", gatewayCallsign, "", "", IDRT_GATEWAY));
pushQuery(IDRT_GATEWAY, gatewayCallsign, new CIRCDDBMultiClientQuery("", "", gatewayCallsign, "", "", "", IDRT_GATEWAY));
bool result = true;
for (unsigned int i = 0; i < m_clients.size(); i++) {
result = m_clients[i]->findGateway(gatewayCallsign) && result;
@ -161,7 +161,7 @@ bool CIRCDDBMultiClient::findGateway(const std::string & gatewayCallsign)
bool CIRCDDBMultiClient::findRepeater(const std::string & repeaterCallsign)
{
pushQuery(IDRT_REPEATER, repeaterCallsign, new CIRCDDBMultiClientQuery("", repeaterCallsign, "", "", "", IDRT_REPEATER));
pushQuery(IDRT_REPEATER, repeaterCallsign, new CIRCDDBMultiClientQuery("", repeaterCallsign, "", "", "", "", IDRT_REPEATER));
bool result = true;
for (unsigned int i = 0; i < m_clients.size(); i++) {
result = m_clients[i]->findRepeater(repeaterCallsign) && result;
@ -172,7 +172,7 @@ bool CIRCDDBMultiClient::findRepeater(const std::string & repeaterCallsign)
bool CIRCDDBMultiClient::findUser(const std::string & userCallsign)
{
pushQuery(IDRT_USER, userCallsign, new CIRCDDBMultiClientQuery(userCallsign, "", "", "", "", IDRT_USER));
pushQuery(IDRT_USER, userCallsign, new CIRCDDBMultiClientQuery(userCallsign, "", "", "", "", "", IDRT_USER));
bool result = true;
for (unsigned int i = 0; i < m_clients.size(); i++) {
result = m_clients[i]->findUser(userCallsign) && result;
@ -181,17 +181,30 @@ bool CIRCDDBMultiClient::findUser(const std::string & userCallsign)
return result;
}
bool CIRCDDBMultiClient::notifyRepeaterNatTraversal(const std::string& repeater)
bool CIRCDDBMultiClient::notifyRepeaterG2NatTraversal(const std::string& repeater)
{
// 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]->notifyRepeaterNatTraversal(repeater) && result;
result = m_clients[i]->notifyRepeaterG2NatTraversal(repeater) && result;
}
return result;
}
bool CIRCDDBMultiClient::notifyRepeaterDextraNatTraversal(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]->notifyRepeaterDextraNatTraversal(repeater, myPort) && result;
}
return result;
}
bool CIRCDDBMultiClient::receiveNATTraversalG2(std::string& address)
{
CIRCDDBMultiClientQuery * item = checkAndGetNextResponse(IDRT_NATTRAVERSAL_G2, "CIRCDDBMultiClient::receiveNATTraversalG2: unexpected response type");
@ -203,11 +216,23 @@ bool CIRCDDBMultiClient::receiveNATTraversalG2(std::string& address)
return true;
}
bool CIRCDDBMultiClient::receiveNATTraversalDextra(std::string& address, std::string& remotePort)
{
CIRCDDBMultiClientQuery * item = checkAndGetNextResponse(IDRT_NATTRAVERSAL_DEXTRA, "CIRCDDBMultiClient::receiveNATTraversalDextra: unexpected response type");
if (item == NULL)
return false;
address = item->getAddress();
remotePort = item->getRemotePort();
return true;
}
IRCDDB_RESPONSE_TYPE CIRCDDBMultiClient::getMessageType()
{
//procees the inner clients at each call
//process the inner clients at each call
for (unsigned int i = 0; i < m_clients.size(); i++) {
std::string user = "", repeater = "", gateway = "", address = "", timestamp = "", key = "";
std::string user = "", repeater = "", gateway = "", address = "", timestamp = "", key = "", port ="";
IRCDDB_RESPONSE_TYPE type = m_clients[i]->getMessageType();
@ -234,6 +259,13 @@ IRCDDB_RESPONSE_TYPE CIRCDDBMultiClient::getMessageType()
if (!m_clients[i]->receiveNATTraversalG2(address))
type = IDRT_NATTRAVERSAL_G2;
key = "NAT_TRAVERSAL_G2";
break;
}
case IDRT_NATTRAVERSAL_DEXTRA: {
if (!m_clients[i]->receiveNATTraversalDextra(address, port))
type = IDRT_NATTRAVERSAL_DEXTRA;
key = "NAT_TRAVERSAL_DEXTRA";
break;
}
case IDRT_NONE: {
default:
@ -250,12 +282,12 @@ IRCDDB_RESPONSE_TYPE CIRCDDBMultiClient::getMessageType()
CIRCDDBMultiClientQuery * item = popQuery(type, key);
if (item != NULL) {//is this a response to a query we've sent ?
item->Update(user, repeater, gateway, address, timestamp);//update item (if needed)
item->Update(user, repeater, gateway, address, timestamp, port);//update item (if needed)
canAddToQueue = (item->incrementResponseCount() >= m_clients.size()); //did all the clients respond or did we have an answer ?
wasQuery = true;
}
else {
item = new CIRCDDBMultiClientQuery(user, repeater, gateway, address, timestamp, type);
item = new CIRCDDBMultiClientQuery(user, repeater, gateway, address, timestamp, port, type);
canAddToQueue = true;
}

@ -40,12 +40,14 @@ public:
const std::string& gateway,
const std::string& address,
const std::string& timestamp,
const std::string& remotePort,
IRCDDB_RESPONSE_TYPE type) :
m_user(user),
m_repeater(repeater),
m_gateway(gateway),
m_address(address),
m_timestamp(timestamp),
m_remotePort(remotePort),
m_type(type),
m_responseCount(0)
{
@ -77,6 +79,11 @@ public:
return m_timestamp;
}
std::string getRemotePort() const
{
return m_remotePort;
}
unsigned int getResponseCount()
{
return m_responseCount;
@ -92,7 +99,7 @@ public:
/*
Updates the entry, but only if the timestamp is newer. if an address was already specified it is kept.
*/
void Update(const std::string& user, const std::string& repeater, const std::string& gateway, const std::string& address, const std::string& timestamp)
void Update(const std::string& user, const std::string& repeater, const std::string& gateway, const std::string& address, const std::string& timestamp, const std::string& remotePort)
{
//wxLogMessage("Before : %s"), toString());
if (timestamp.empty() || timestamp.compare(m_timestamp) >= 0) {
@ -100,6 +107,7 @@ public:
m_repeater = repeater;
m_gateway = gateway;
m_timestamp = timestamp;
m_remotePort = remotePort;
if(m_address.empty() && !address.empty())
m_address = address;
@ -125,6 +133,7 @@ private:
std::string m_gateway;
std::string m_address;
std::string m_timestamp;
std::string m_remotePort;
IRCDDB_RESPONSE_TYPE m_type;
unsigned int m_responseCount;
};
@ -150,13 +159,15 @@ public:
virtual bool findGateway(const std::string & gatewayCallsign);
virtual bool findRepeater(const std::string & repeaterCallsign);
virtual bool findUser(const std::string & userCallsign);
virtual bool notifyRepeaterNatTraversal(const std::string& repeater);
virtual bool notifyRepeaterG2NatTraversal(const std::string& repeater);
virtual bool notifyRepeaterDextraNatTraversal(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);
virtual bool receiveUser(std::string & userCallsign, std::string & repeaterCallsign, std::string & gatewayCallsign, std::string & address);
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 void sendDStarGatewayInfo(const std::string subcommand, const std::vector<std::string> parms);
virtual void close();

@ -2057,7 +2057,7 @@ void CRepeaterHandler::g2CommandHandler(const std::string& callsign, const std::
m_g2User = "CQCQCQ ";
CRepeaterData* data = m_cache->findRepeater(m_g2Repeater);
m_irc->notifyRepeaterNatTraversal(m_g2Repeater);
m_irc->notifyRepeaterG2NatTraversal(m_g2Repeater);
if (data == NULL) {
m_g2Status = G2_REPEATER;
@ -2109,7 +2109,7 @@ void CRepeaterHandler::g2CommandHandler(const std::string& callsign, const std::
m_g2User = callsign;
m_g2Address = data->getAddress();
m_g2Repeater = data->getRepeater();
m_irc->notifyRepeaterNatTraversal(m_g2Repeater);
m_irc->notifyRepeaterG2NatTraversal(m_g2Repeater);
m_g2Gateway = data->getGateway();
header.setDestination(m_g2Address, G2_DV_PORT);
header.setRepeaters(m_g2Gateway, m_g2Repeater);

Loading…
Cancel
Save

Powered by TurnKey Linux.