diff --git a/.vscode/settings.json b/.vscode/settings.json index 246b6b6..0597c44 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -20,7 +20,8 @@ "ostream": "cpp", "sstream": "cpp", "stop_token": "cpp", - "streambuf": "cpp" + "streambuf": "cpp", + "chrono": "cpp" }, "editor.tokenColorCustomizations": { "textMateRules": [ diff --git a/DStarGatewayThread.cpp b/DStarGatewayThread.cpp index 550e19f..442439d 100644 --- a/DStarGatewayThread.cpp +++ b/DStarGatewayThread.cpp @@ -795,7 +795,8 @@ void CDStarGatewayThread::processIrcDDB() } } break; - + case IDRT_NATTRAVERSAL_G2: + break; default: return; } diff --git a/IRCDDB.h b/IRCDDB.h index 72e8c9a..d55538d 100644 --- a/IRCDDB.h +++ b/IRCDDB.h @@ -31,7 +31,8 @@ enum IRCDDB_RESPONSE_TYPE { IDRT_NONE, IDRT_USER, IDRT_GATEWAY, - IDRT_REPEATER + IDRT_REPEATER, + IDRT_NATTRAVERSAL_G2 }; @@ -111,6 +112,9 @@ public: // Send query for a user, a false return implies a network error 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; // Support for the Smart Group Server virtual void sendDStarGatewayInfo(const std::string subcommand, const std::vector parms) = 0; @@ -135,8 +139,6 @@ public: virtual bool receiveUser(std::string& userCallsign, std::string& repeaterCallsign, std::string& gatewayCallsign, std::string& address, std::string& timeStamp) = 0; virtual void close() = 0; // Implictely kills any threads in the IRC code - - virtual void queryUsers() = 0; }; typedef std::vector CIRCDDB_Array; diff --git a/IRCDDBApp.cpp b/IRCDDBApp.cpp index bd4a51a..cb9eacb 100644 --- a/IRCDDBApp.cpp +++ b/IRCDDBApp.cpp @@ -27,6 +27,7 @@ along with this program. If not, see . #include #include #include +#include #include "IRCDDBApp.h" #include "Utils.h" @@ -129,27 +130,27 @@ public: }; IRCDDBApp::IRCDDBApp(const std::string& u_chan) - : d(new IRCDDBAppPrivate) + : m_d(new IRCDDBAppPrivate) , m_maxTime((time_t)950000000) //februray 2000 { - d->m_sendQ = NULL; - d->m_initReady = false; + m_d->m_sendQ = NULL; + m_d->m_initReady = false; userListReset(); - d->m_state = 0; - d->m_timer = 0; - d->m_myNick = std::string("none"); + m_d->m_state = 0; + m_d->m_timer = 0; + m_d->m_myNick = std::string("none"); - d->m_updateChannel = u_chan; + m_d->m_updateChannel = u_chan; - d->m_terminateThread = false; + m_d->m_terminateThread = false; } IRCDDBApp::~IRCDDBApp() { - delete d->m_sendQ; - delete d; + delete m_d->m_sendQ; + delete m_d; } void IRCDDBApp::rptrQTH(const std::string& callsign, double latitude, double longitude, const std::string& desc1, const std::string& desc2, const std::string& infoURL) @@ -177,11 +178,11 @@ void IRCDDBApp::rptrQTH(const std::string& callsign, double latitude, double lon CUtils::ReplaceChar(d2, ' ', '_'); CUtils::ReplaceChar(cs, ' ', '_'); - std::lock_guard lochQTHURL(d->m_moduleQTHURLMutex); + std::lock_guard lochQTHURL(m_d->m_moduleQTHURLMutex); - d->m_moduleQTH[cs] = cs + std::string(" ") + pos + std::string(" ") + d1 + std::string(" ") + d2; + m_d->m_moduleQTH[cs] = cs + std::string(" ") + pos + std::string(" ") + d1 + std::string(" ") + d2; - CLog::logInfo("QTH: %s\n", d->m_moduleQTH[cs].c_str()); + CLog::logInfo("QTH: %s\n", m_d->m_moduleQTH[cs].c_str()); std::string url = infoURL; @@ -190,11 +191,11 @@ void IRCDDBApp::rptrQTH(const std::string& callsign, double latitude, double lon url.erase(sm.position(0), sm.length()); if (url.size()) { - d->m_moduleURL[cs] = cs + std::string(" ") + url; - CLog::logInfo("URL: %s\n", d->m_moduleURL[cs].c_str()); + m_d->m_moduleURL[cs] = cs + std::string(" ") + url; + CLog::logInfo("URL: %s\n", m_d->m_moduleURL[cs].c_str()); } - d->m_infoTimer = 5; // send info in 5 seconds + m_d->m_infoTimer = 5; // send info in 5 seconds } void IRCDDBApp::rptrQRG(const std::string& callsign, double txFrequency, double duplexShift, double range, double agl) @@ -207,11 +208,11 @@ void IRCDDBApp::rptrQRG(const std::string& callsign, double txFrequency, double std::string f(fstr); CUtils::ReplaceChar(f, ',', '.'); - std::lock_guard lockModuleQRG(d->m_moduleQRGMutex); - d->m_moduleQRG[cs] = cs + std::string(" ") + f; - CLog::logInfo("QRG: %s\n", d->m_moduleQRG[cs].c_str()); + std::lock_guard lockModuleQRG(m_d->m_moduleQRGMutex); + m_d->m_moduleQRG[cs] = cs + std::string(" ") + f; + CLog::logInfo("QRG: %s\n", m_d->m_moduleQRG[cs].c_str()); - d->m_infoTimer = 5; // send info in 5 seconds + m_d->m_infoTimer = 5; // send info in 5 seconds } void IRCDDBApp::kickWatchdog(const std::string& callsign, const std::string& s) @@ -227,20 +228,20 @@ void IRCDDBApp::kickWatchdog(const std::string& callsign, const std::string& s) std::string cs = callsign; CUtils::ReplaceChar(cs, ' ', '_'); - std::lock_guard lockModuleWD(d->m_moduleWDMutex); - d->m_moduleWD[cs] = cs + std::string(" ") + text; - d->m_wdTimer = 60; + std::lock_guard lockModuleWD(m_d->m_moduleWDMutex); + m_d->m_moduleWD[cs] = cs + std::string(" ") + text; + m_d->m_wdTimer = 60; } } int IRCDDBApp::getConnectionState() { - return d->m_state; + return m_d->m_state; } IRCDDB_RESPONSE_TYPE IRCDDBApp::getReplyMessageType() { - IRCMessage *m = d->m_replyQ.peekFirst(); + IRCMessage *m = m_d->m_replyQ.peekFirst(); if (m == NULL) return IDRT_NONE; @@ -255,6 +256,9 @@ IRCDDB_RESPONSE_TYPE IRCDDBApp::getReplyMessageType() if (0 == msgType.compare("IDRT_GATEWAY")) return IDRT_GATEWAY; + if(msgType.compare("NATTRAVERSAL_G2") == 0) + return IDRT_NATTRAVERSAL_G2; + CLog::logWarning("IRCDDBApp::getMessageType: unknown msg type: %s\n", msgType.c_str()); return IDRT_NONE; @@ -262,18 +266,18 @@ IRCDDB_RESPONSE_TYPE IRCDDBApp::getReplyMessageType() IRCMessage *IRCDDBApp::getReplyMessage() { - return d->m_replyQ.getMessage(); + return m_d->m_replyQ.getMessage(); } void IRCDDBApp::startWork() { - d->m_terminateThread = false; + m_d->m_terminateThread = false; m_future = std::async(std::launch::async, &IRCDDBApp::Entry, this); } void IRCDDBApp::stopWork() { - d->m_terminateThread = true; + m_d->m_terminateThread = true; m_future.get(); } @@ -286,8 +290,8 @@ unsigned int IRCDDBApp::calculateUsn(const std::string& nick) for (int i = 1; i <= 4; i++) { std::string ircUser = lnick + std::to_string(i); - if (d->m_userMap.count(ircUser) == 1) { - IRCDDBAppUserObject obj = d->m_userMap[ircUser]; + if (m_d->m_userMap.count(ircUser) == 1) { + IRCDDBAppUserObject obj = m_d->m_userMap[ircUser]; if (obj.m_usn > maxUsn) maxUsn = obj.m_usn; } @@ -297,7 +301,7 @@ unsigned int IRCDDBApp::calculateUsn(const std::string& nick) void IRCDDBApp::userJoin(const std::string& nick, const std::string& name, const std::string& host) { - std::lock_guard lockUserMap(d->m_userMapMutex); + std::lock_guard lockUserMap(m_d->m_userMapMutex); std::string lnick = nick; CUtils::ToLower(lnick); @@ -305,9 +309,9 @@ void IRCDDBApp::userJoin(const std::string& nick, const std::string& name, const IRCDDBAppUserObject u(lnick, name, host); u.m_usn = calculateUsn(lnick); - d->m_userMap[lnick] = u; + m_d->m_userMap[lnick] = u; - if (d->m_initReady) { + if (m_d->m_initReady) { std::string::size_type hyphenPos = nick.find('-'); if ((hyphenPos >= 4) && (hyphenPos <= 6)) { @@ -319,7 +323,7 @@ void IRCDDBApp::userJoin(const std::string& nick, const std::string& name, const IRCMessage *m2 = new IRCMessage("IDRT_GATEWAY"); m2->addParam(gatewayCallsign); m2->addParam(host); - d->m_replyQ.putMessage(m2); + m_d->m_replyQ.putMessage(m2); } } } @@ -329,25 +333,25 @@ void IRCDDBApp::userLeave(const std::string& nick) std::string lnick = nick; CUtils::ToLower(lnick); - std::lock_guard lockUserMap(d->m_userMapMutex); - d->m_userMap.erase(lnick); + std::lock_guard lockUserMap(m_d->m_userMapMutex); + m_d->m_userMap.erase(lnick); - if (d->m_currentServer.size()) { - if (d->m_userMap.count(d->m_myNick) != 1) { + if (m_d->m_currentServer.size()) { + if (m_d->m_userMap.count(m_d->m_myNick) != 1) { CLog::logInfo("IRCDDBApp::userLeave: could not find own nick\n"); return; } - IRCDDBAppUserObject me = d->m_userMap[d->m_myNick]; + IRCDDBAppUserObject me = m_d->m_userMap[m_d->m_myNick]; if (me.m_op == false) { // if I am not op, then look for new server - if (0 == d->m_currentServer.compare(lnick)) { + if (0 == m_d->m_currentServer.compare(lnick)) { // m_currentServer = null; - d->m_state = 2; // choose new server - d->m_timer = 200; - d->m_initReady = false; + m_d->m_state = 2; // choose new server + m_d->m_timer = 200; + m_d->m_initReady = false; } } } @@ -355,39 +359,39 @@ void IRCDDBApp::userLeave(const std::string& nick) void IRCDDBApp::userListReset() { - std::lock_guard lockUserMap(d->m_userMapMutex); - d->m_userMap.clear(); + std::lock_guard lockUserMap(m_d->m_userMapMutex); + m_d->m_userMap.clear(); } void IRCDDBApp::setCurrentNick(const std::string& nick) { - d->m_myNick = nick; + m_d->m_myNick = nick; CLog::logInfo("IRCDDBApp::setCurrentNick %s\n", nick.c_str()); } void IRCDDBApp::setBestServer(const std::string& ircUser) { - d->m_bestServer = ircUser; + m_d->m_bestServer = ircUser; CLog::logInfo("IRCDDBApp::setBestServer %s\n", ircUser.c_str()); } void IRCDDBApp::setTopic(const std::string& topic) { - d->m_channelTopic = topic; + m_d->m_channelTopic = topic; } bool IRCDDBApp::findServerUser() { bool found = false; - std::lock_guard lockUserMap(d->m_userMapMutex); + std::lock_guard lockUserMap(m_d->m_userMapMutex); std::map::iterator it; - for (it = d->m_userMap.begin(); it != d->m_userMap.end(); ++it) { + for (it = m_d->m_userMap.begin(); it != m_d->m_userMap.end(); ++it) { IRCDDBAppUserObject u = it->second; - if (0==u.m_nick.compare(0, 2, "s-") && u.m_op && d->m_myNick.compare(u.m_nick) && 0==u.m_nick.compare(d->m_bestServer)) { - d->m_currentServer = u.m_nick; + if (0==u.m_nick.compare(0, 2, "s-") && u.m_op && m_d->m_myNick.compare(u.m_nick) && 0==u.m_nick.compare(m_d->m_bestServer)) { + m_d->m_currentServer = u.m_nick; found = true; break; } @@ -397,12 +401,12 @@ bool IRCDDBApp::findServerUser() return true; } - if (8 == d->m_bestServer.size()) { - for (it = d->m_userMap.begin(); it != d->m_userMap.end(); ++it) { + if (8 == m_d->m_bestServer.size()) { + for (it = m_d->m_userMap.begin(); it != m_d->m_userMap.end(); ++it) { IRCDDBAppUserObject u = it->second; - if (0==u.m_nick.compare(d->m_bestServer.substr(0,7)) && u.m_op && d->m_myNick.compare(u.m_nick) ) { - d->m_currentServer = u.m_nick; + if (0==u.m_nick.compare(m_d->m_bestServer.substr(0,7)) && u.m_op && m_d->m_myNick.compare(u.m_nick) ) { + m_d->m_currentServer = u.m_nick; found = true; break; } @@ -413,10 +417,10 @@ bool IRCDDBApp::findServerUser() return true; } - for (it = d->m_userMap.begin(); it != d->m_userMap.end(); ++it) { + for (it = m_d->m_userMap.begin(); it != m_d->m_userMap.end(); ++it) { IRCDDBAppUserObject u = it->second; - if (0==u.m_nick.compare(0, 2, "s-") && u.m_op && d->m_myNick.compare(u.m_nick)) { - d->m_currentServer = u.m_nick; + if (0==u.m_nick.compare(0, 2, "s-") && u.m_op && m_d->m_myNick.compare(u.m_nick)) { + m_d->m_currentServer = u.m_nick; found = true; break; } @@ -426,13 +430,13 @@ bool IRCDDBApp::findServerUser() void IRCDDBApp::userChanOp(const std::string& nick, bool op) { - std::lock_guard lockUserMap(d->m_userMapMutex); + std::lock_guard lockUserMap(m_d->m_userMapMutex); std::string lnick = nick; CUtils::ToLower(lnick); - if (d->m_userMap.count(lnick) == 1) - d->m_userMap[lnick].m_op = op; + if (m_d->m_userMap.count(lnick) == 1) + m_d->m_userMap[lnick].m_op = op; } static const int numberOfTables = 2; @@ -446,12 +450,12 @@ std::string IRCDDBApp::getIPAddress(std::string& zonerp_cs) CUtils::ToLower(gw); CUtils::Trim(gw); - std::lock_guard lockUserMap(d->m_userMapMutex); + std::lock_guard lockUserMap(m_d->m_userMapMutex); for (int j=1; j <= 4; j++) { std::string ircUser = gw + std::string("-") + std::to_string(j); - if (d->m_userMap.count(ircUser) == 1) { - IRCDDBAppUserObject o = d->m_userMap[ircUser]; + if (m_d->m_userMap.count(ircUser) == 1) { + IRCDDBAppUserObject o = m_d->m_userMap[ircUser]; if (o.m_usn >= max_usn) { max_usn = o.m_usn; @@ -469,7 +473,7 @@ bool IRCDDBApp::findGateway(const std::string& gwCall) IRCMessage *m2 = new IRCMessage("IDRT_GATEWAY"); m2->addParam(gwCall); m2->addParam(getIPAddress(s)); - d->m_replyQ.putMessage(m2); + m_d->m_replyQ.putMessage(m2); return true; } @@ -510,7 +514,7 @@ static void findReflector(const std::string& rptrCall, IRCDDBAppPrivate *d) bool IRCDDBApp::findRepeater(const std::string& rptrCall) { if (0==rptrCall.compare(0, 3, "XRF") || 0==rptrCall.compare(0, 3, "REF") || 0==rptrCall.compare(0, 3, "DCS") || 0==rptrCall.compare(0, 3, "XLX") ) { - findReflector(rptrCall, d); + findReflector(rptrCall, m_d); return true; } @@ -519,10 +523,10 @@ bool IRCDDBApp::findRepeater(const std::string& rptrCall) std::string s("NONE"); std::string zonerp_cs; - std::lock_guard lockRptrMap(d->m_rptrMapMutex); + std::lock_guard lockRptrMap(m_d->m_rptrMapMutex); - if (1 == d->m_rptrMap.count(arearp_cs)) { - IRCDDBAppRptrObject o = d->m_rptrMap[arearp_cs]; + if (1 == m_d->m_rptrMap.count(arearp_cs)) { + IRCDDBAppRptrObject o = m_d->m_rptrMap[arearp_cs]; zonerp_cs = o.m_zonerp_cs; CUtils::ReplaceChar(zonerp_cs, '_', ' '); zonerp_cs.resize(7, ' '); @@ -534,7 +538,7 @@ bool IRCDDBApp::findRepeater(const std::string& rptrCall) m2->addParam(rptrCall); m2->addParam(zonerp_cs); m2->addParam(getIPAddress(s)); - d->m_replyQ.putMessage(m2); + m_d->m_replyQ.putMessage(m2); return true; } @@ -542,8 +546,8 @@ bool IRCDDBApp::findRepeater(const std::string& rptrCall) void IRCDDBApp::sendDStarGatewayInfo(const std::string &subcommand, const std::vector &pars) { IRCMessageQueue *q = getSendQ(); - std::string srv(d->m_currentServer); - if (srv.size() && d->m_state>=6 && q) { + std::string srv(m_d->m_currentServer); + if (srv.size() && m_d->m_state>=6 && q) { std::string command("DStarGateway "); command.append(subcommand); for (auto it=pars.begin(); it!=pars.end(); it++) { @@ -582,10 +586,10 @@ bool IRCDDBApp::sendHeard(const std::string& myCall, const std::string& myCallEx bool statsMsg = (tx_stats.size() > 0); - std::string srv(d->m_currentServer); + std::string srv(m_d->m_currentServer); IRCMessageQueue *q = getSendQ(); - if (srv.size() && d->m_state>=6 && q) { + if (srv.size() && m_d->m_state>=6 && q) { std::string cmd("UPDATE "); cmd += CUtils::getCurrentTime(); @@ -616,10 +620,10 @@ bool IRCDDBApp::sendHeard(const std::string& myCall, const std::string& myCallEx bool IRCDDBApp::findUser(const std::string& usrCall) { - std::string srv(d->m_currentServer); + std::string srv(m_d->m_currentServer); IRCMessageQueue *q = getSendQ(); - if (srv.size()>0 && d->m_state>=6 && q) { + if (srv.size()>0 && m_d->m_state>=6 && q) { std::string usr(usrCall); CUtils::ReplaceChar(usr, ' ', '_'); IRCMessage * m =new IRCMessage(srv, std::string("FIND ") + usr); @@ -629,12 +633,40 @@ bool IRCDDBApp::findUser(const std::string& usrCall) m2->addParam(usrCall); for (int i=0; i<4; i++) m2->addParam(std::string("")); - d->m_replyQ.putMessage(m2); + m_d->m_replyQ.putMessage(m2); } return true; } +bool IRCDDBApp::notifyRepeaterNatTraversal(const std::string& repeater) +{ + 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_G2"); + m_d->m_sendQ->putMessage(ircMessage); + + return true; +} void IRCDDBApp::msgChannel(IRCMessage *m) { @@ -653,7 +685,7 @@ void IRCDDBApp::doNotFound(std::string& msg, std::string& retval) std::string tk = tkz.front(); tkz.erase(tkz.begin()); - if (std::regex_match(tk, d->m_tablePattern)) { + if (std::regex_match(tk, m_d->m_tablePattern)) { tableID = std::stoi(tk); if (tableID<0 || tableID>=numberOfTables) { @@ -669,7 +701,7 @@ void IRCDDBApp::doNotFound(std::string& msg, std::string& retval) } if (0 == tableID) { - if (! std::regex_match(tk, d->m_dbPattern)) + if (! std::regex_match(tk, m_d->m_dbPattern)) return; // no valid key retval = tk; } @@ -685,7 +717,7 @@ void IRCDDBApp::doUpdate(std::string& msg) std::string tk = tkz.front(); tkz.erase(tkz.begin()); - if (std::regex_match(tk, d->m_tablePattern)) { + if (std::regex_match(tk, m_d->m_tablePattern)) { tableID = std::stoi(tk); if ((tableID < 0) || (tableID >= numberOfTables)) { CLog::logInfo("invalid table ID %d\n", tableID); @@ -699,13 +731,13 @@ void IRCDDBApp::doUpdate(std::string& msg) tkz.erase(tkz.begin()); } - if (std::regex_match(tk, d->m_datePattern)) { + if (std::regex_match(tk, m_d->m_datePattern)) { if (tkz.empty()) return; // nothing after date string std::string timeToken = tkz.front(); // time token tkz.erase(tkz.begin()); - if (! std::regex_match(timeToken, d->m_timePattern)) + if (! std::regex_match(timeToken, m_d->m_timePattern)) return; // no time string after date string time_t dt = CUtils::parseTime(tk + std::string(" ") + timeToken); @@ -717,7 +749,7 @@ void IRCDDBApp::doUpdate(std::string& msg) std::string key = tkz.front(); tkz.erase(tkz.begin()); - if (! std::regex_match(key, d->m_dbPattern)) + if (! std::regex_match(key, m_d->m_dbPattern)) return; // no valid key if (tkz.empty()) @@ -726,15 +758,15 @@ void IRCDDBApp::doUpdate(std::string& msg) std::string value = tkz.front(); tkz.erase(tkz.begin()); - if (! std::regex_match(value, d->m_dbPattern)) + if (! std::regex_match(value, m_d->m_dbPattern)) return; // no valid key if (tableID == 1) { - std::lock_guard lockRptrMap(d->m_rptrMapMutex); + std::lock_guard lockRptrMap(m_d->m_rptrMapMutex); IRCDDBAppRptrObject newRptr(dt, key, value, m_maxTime); - d->m_rptrMap[key] = newRptr; + m_d->m_rptrMap[key] = newRptr; - if (d->m_initReady) { + if (m_d->m_initReady) { std::string arearp_cs(key); std::string zonerp_cs(value); CUtils::ReplaceChar(arearp_cs, '_', ' '); @@ -746,10 +778,10 @@ void IRCDDBApp::doUpdate(std::string& msg) m2->addParam(arearp_cs); m2->addParam(zonerp_cs); m2->addParam(getIPAddress(value)); - d->m_replyQ.putMessage(m2); + m_d->m_replyQ.putMessage(m2); } - } else if (0==tableID && d->m_initReady) { - std::lock_guard lockRptrMap(d->m_rptrMapMutex); + } else if (0==tableID && m_d->m_initReady) { + std::lock_guard lockRptrMap(m_d->m_rptrMapMutex); std::string userCallsign(key); std::string arearp_cs(value); std::string zonerp_cs; @@ -757,8 +789,8 @@ void IRCDDBApp::doUpdate(std::string& msg) CUtils::ReplaceChar(userCallsign, '_', ' '); CUtils::ReplaceChar(arearp_cs, '_', ' '); - if (1 == d->m_rptrMap.count(value)) { - IRCDDBAppRptrObject o = d->m_rptrMap[value]; + if (1 == m_d->m_rptrMap.count(value)) { + IRCDDBAppRptrObject o = m_d->m_rptrMap[value]; zonerp_cs = o.m_zonerp_cs; CUtils::ReplaceChar(zonerp_cs, '_', ' '); zonerp_cs.resize(7, ' '); @@ -772,7 +804,7 @@ void IRCDDBApp::doUpdate(std::string& msg) m2->addParam(zonerp_cs); m2->addParam(ip_addr); m2->addParam(tk + std::string(" ") + timeToken); - d->m_replyQ.putMessage(m2); + m_d->m_replyQ.putMessage(m2); } } } @@ -794,7 +826,7 @@ static std::string getTableIDString(int tableID, bool spaceBeforeNumber) void IRCDDBApp::msgQuery(IRCMessage *m) { - if (0==m->getPrefixNick().compare(0, 2, "s-") && m->numParams>=2) { // server msg + if (0 == m->getPrefixNick().compare(0, 2, "s-") && m->numParams >=2 ) { // server msg std::string msg(m->m_params[1]); std::vector tkz = CUtils::stringTokenizer(msg); @@ -814,11 +846,11 @@ void IRCDDBApp::msgQuery(IRCMessage *m) } doUpdate(restOfLine); } else if (0 == cmd.compare("LIST_END")) { - if (5 == d->m_state) // if in sendlist processing state - d->m_state = 3; // get next table + if (5 == m_d->m_state) // if in sendlist processing state + m_d->m_state = 3; // get next table } else if (0 == cmd.compare("LIST_MORE")) { - if (5 == d->m_state) // if in sendlist processing state - d->m_state = 4; // send next SENDLIST + if (5 == m_d->m_state) // if in sendlist processing state + m_d->m_state = 4; // send next SENDLIST } else if (0 == cmd.compare("NOT_FOUND")) { std::string callsign; std::string restOfLine; @@ -836,20 +868,27 @@ void IRCDDBApp::msgQuery(IRCMessage *m) m2->addParam(callsign); for (int i=0; i<4; i++) m2->addParam(std::string("")); - d->m_replyQ.putMessage(m2); + m_d->m_replyQ.putMessage(m2); } } } + else if(m->m_params[0] == m_d->m_myNick) { + if(boost::starts_with(m->m_params[1], "NATTRAVERSAL_")) { + IRCMessage * m2 = new IRCMessage(m->m_params[1]); + m2->addParam(m->getPrefixHost()); + m_d->m_replyQ.putMessage(m2); + } + } } void IRCDDBApp::setSendQ(IRCMessageQueue *s) { - d->m_sendQ = s; + m_d->m_sendQ = s; } IRCMessageQueue *IRCDDBApp::getSendQ() { - return d->m_sendQ; + return m_d->m_sendQ; } std::string IRCDDBApp::getLastEntryTime(int tableID) @@ -872,30 +911,30 @@ static bool needsDatabaseUpdate(int tableID) void IRCDDBApp::Entry() { int sendlistTableID = 0; - while (!d->m_terminateThread) { - if (d->m_timer > 0) - d->m_timer--; - switch(d->m_state) { + while (!m_d->m_terminateThread) { + if (m_d->m_timer > 0) + m_d->m_timer--; + switch(m_d->m_state) { case 0: // wait for network to start if (getSendQ()) - d->m_state = 1; + m_d->m_state = 1; break; case 1: // connect to db - d->m_state = 2; - d->m_timer = 200; + m_d->m_state = 2; + m_d->m_timer = 200; break; case 2: // choose server CLog::logInfo("IRCDDBApp: state=2 choose new 's-'-user\n"); if (NULL == getSendQ()) - d->m_state = 10; + m_d->m_state = 10; else { if (findServerUser()) { sendlistTableID = numberOfTables; - d->m_state = 3; // next: send "SENDLIST" - } else if (0 == d->m_timer) { - d->m_state = 10; + m_d->m_state = 3; // next: send "SENDLIST" + } else if (0 == m_d->m_timer) { + m_d->m_state = 10; IRCMessage *m = new IRCMessage("QUIT"); m->addParam("no op user with 's-' found."); IRCMessageQueue *q = getSendQ(); @@ -907,39 +946,39 @@ void IRCDDBApp::Entry() case 3: if (NULL == getSendQ()) - d->m_state = 10; // disconnect DB + m_d->m_state = 10; // disconnect DB else { sendlistTableID--; if (sendlistTableID < 0) - d->m_state = 6; // end of sendlist + m_d->m_state = 6; // end of sendlist else { CLog::logInfo("IRCDDBApp: state=3 tableID=%d\n", sendlistTableID); - d->m_state = 4; // send "SENDLIST" - d->m_timer = 900; // 15 minutes max for update + m_d->m_state = 4; // send "SENDLIST" + m_d->m_timer = 900; // 15 minutes max for update } } break; case 4: if (NULL == getSendQ()) - d->m_state = 10; // disconnect DB + m_d->m_state = 10; // disconnect DB else { if (needsDatabaseUpdate(sendlistTableID)) { - IRCMessage *m = new IRCMessage(d->m_currentServer, std::string("SENDLIST") + getTableIDString(sendlistTableID, true) + std::string(" ") + getLastEntryTime(sendlistTableID)); + IRCMessage *m = new IRCMessage(m_d->m_currentServer, std::string("SENDLIST") + getTableIDString(sendlistTableID, true) + std::string(" ") + getLastEntryTime(sendlistTableID)); IRCMessageQueue *q = getSendQ(); if (q) q->putMessage(m); - d->m_state = 5; // wait for answers + m_d->m_state = 5; // wait for answers } else - d->m_state = 3; // don't send SENDLIST for this table, go to next table + m_d->m_state = 3; // don't send SENDLIST for this table, go to next table } break; case 5: // sendlist processing if (NULL == getSendQ()) - d->m_state = 10; // disconnect DB - else if (0 == d->m_timer) { - d->m_state = 10; // disconnect DB + m_d->m_state = 10; // disconnect DB + else if (0 == m_d->m_timer) { + m_d->m_state = 10; // disconnect DB IRCMessage *m = new IRCMessage("QUIT"); m->addParam("timeout SENDLIST"); IRCMessageQueue *q = getSendQ(); @@ -950,79 +989,79 @@ void IRCDDBApp::Entry() case 6: if (NULL == getSendQ()) - d->m_state = 10; // disconnect DB + m_d->m_state = 10; // disconnect DB else { CLog::logInfo( "IRCDDBApp: state=6 initialization completed\n"); - d->m_infoTimer = 2; - d->m_initReady = true; - d->m_state = 7; + m_d->m_infoTimer = 2; + m_d->m_initReady = true; + m_d->m_state = 7; } break; case 7: // standby state after initialization if (NULL == getSendQ()) - d->m_state = 10; // disconnect DB + m_d->m_state = 10; // disconnect DB - if (d->m_infoTimer > 0) { - d->m_infoTimer--; + if (m_d->m_infoTimer > 0) { + m_d->m_infoTimer--; - if (0 == d->m_infoTimer) { + if (0 == m_d->m_infoTimer) { { // Scope for mutext locking - std::lock_guard lochQTHURL(d->m_moduleQTHURLMutex); - for (auto it = d->m_moduleQTH.begin(); it != d->m_moduleQTH.end(); ++it) { + std::lock_guard lochQTHURL(m_d->m_moduleQTHURLMutex); + for (auto it = m_d->m_moduleQTH.begin(); it != m_d->m_moduleQTH.end(); ++it) { std::string value = it->second; - IRCMessage *m = new IRCMessage(d->m_currentServer, std::string("IRCDDB RPTRQTH: ") + value); + IRCMessage *m = new IRCMessage(m_d->m_currentServer, std::string("IRCDDB RPTRQTH: ") + value); IRCMessageQueue *q = getSendQ(); if (q != NULL) q->putMessage(m); } - d->m_moduleQTH.clear(); + m_d->m_moduleQTH.clear(); - for (auto it = d->m_moduleURL.begin(); it != d->m_moduleURL.end(); ++it) { + for (auto it = m_d->m_moduleURL.begin(); it != m_d->m_moduleURL.end(); ++it) { std::string value = it->second; - IRCMessage *m = new IRCMessage(d->m_currentServer, std::string("IRCDDB RPTRURL: ") + value); + IRCMessage *m = new IRCMessage(m_d->m_currentServer, std::string("IRCDDB RPTRURL: ") + value); IRCMessageQueue *q = getSendQ(); if (q != NULL) q->putMessage(m); } - d->m_moduleURL.clear(); + m_d->m_moduleURL.clear(); } - std::lock_guard lockModuleQRG(d->m_moduleQRGMutex); - for (auto it = d->m_moduleQRG.begin(); it != d->m_moduleQRG.end(); ++it) { + std::lock_guard lockModuleQRG(m_d->m_moduleQRGMutex); + for (auto it = m_d->m_moduleQRG.begin(); it != m_d->m_moduleQRG.end(); ++it) { std::string value = it->second; - IRCMessage* m = new IRCMessage(d->m_currentServer, std::string("IRCDDB RPTRQRG: ") + value); + IRCMessage* m = new IRCMessage(m_d->m_currentServer, std::string("IRCDDB RPTRQRG: ") + value); IRCMessageQueue* q = getSendQ(); if (q != NULL) q->putMessage(m); } - d->m_moduleQRG.clear(); + m_d->m_moduleQRG.clear(); } } - if (d->m_wdTimer > 0) { - d->m_wdTimer--; + if (m_d->m_wdTimer > 0) { + m_d->m_wdTimer--; - if (0 == d->m_wdTimer) { - std::lock_guard lockModuleWD(d->m_moduleWDMutex); + if (0 == m_d->m_wdTimer) { + std::lock_guard lockModuleWD(m_d->m_moduleWDMutex); - for (auto it = d->m_moduleWD.begin(); it != d->m_moduleWD.end(); ++it) { + for (auto it = m_d->m_moduleWD.begin(); it != m_d->m_moduleWD.end(); ++it) { std::string value = it->second; - IRCMessage *m = new IRCMessage(d->m_currentServer, std::string("IRCDDB RPTRSW: ") + value); + IRCMessage *m = new IRCMessage(m_d->m_currentServer, std::string("IRCDDB RPTRSW: ") + value); IRCMessageQueue *q = getSendQ(); if (q) q->putMessage(m); } - d->m_moduleWD.clear(); + m_d->m_moduleWD.clear(); } } break; case 10: // disconnect db - d->m_state = 0; - d->m_timer = 0; - d->m_initReady = false; + m_d->m_state = 0; + m_d->m_timer = 0; + m_d->m_initReady = false; break; } std::this_thread::sleep_for(std::chrono::seconds(1)); diff --git a/IRCDDBApp.h b/IRCDDBApp.h index 7c2575a..8a3066d 100644 --- a/IRCDDBApp.h +++ b/IRCDDBApp.h @@ -92,7 +92,7 @@ private: bool findServerUser(); unsigned int calculateUsn(const std::string& nick); std::string getLastEntryTime(int tableID); - IRCDDBAppPrivate *d; + IRCDDBAppPrivate *m_d; time_t m_maxTime; std::future m_future; }; diff --git a/IRCDDBClient.cpp b/IRCDDBClient.cpp index 433c0b4..e95f4b4 100644 --- a/IRCDDBClient.cpp +++ b/IRCDDBClient.cpp @@ -28,23 +28,23 @@ along with this program. If not, see . struct CIRCDDBClientPrivate { IRCClient *client; - IRCDDBApp *app; + IRCDDBApp *m_app; }; CIRCDDBClient::CIRCDDBClient(const std::string& hostName, unsigned int port, const std::string& callsign, const std::string& password, const std::string& versionInfo, const std::string& localAddr, bool isQuadNet ) : -d(new CIRCDDBClientPrivate), +m_d(new CIRCDDBClientPrivate), m_isQuadNet(isQuadNet) { std::string update_channel("#dstar"); - d->app = new IRCDDBApp(update_channel); - d->client = new IRCClient(d->app, update_channel, hostName, port, callsign, password, versionInfo, localAddr); + m_d->m_app = new IRCDDBApp(update_channel); + m_d->client = new IRCClient(m_d->m_app, update_channel, hostName, port, callsign, password, versionInfo, localAddr); } CIRCDDBClient::~CIRCDDBClient() { - delete d->client; - delete d->app; - delete d; + delete m_d->client; + delete m_d->m_app; + delete m_d; } @@ -52,33 +52,33 @@ CIRCDDBClient::~CIRCDDBClient() bool CIRCDDBClient::open() { CLog::logInfo("start client and app\n"); - d->client->startWork(); - d->app->startWork(); + m_d->client->startWork(); + m_d->m_app->startWork(); return true; } int CIRCDDBClient::getConnectionState() { - return d->app->getConnectionState(); + return m_d->m_app->getConnectionState(); } void CIRCDDBClient::rptrQTH(const std::string& callsign, double latitude, double longitude, const std::string& desc1, const std::string& desc2, const std::string& infoURL) { - d->app->rptrQTH(callsign, latitude, longitude, desc1, desc2, infoURL); + m_d->m_app->rptrQTH(callsign, latitude, longitude, desc1, desc2, infoURL); } void CIRCDDBClient::rptrQRG(const std::string& callsign, double txFrequency, double duplexShift, double range, double agl) { - d->app->rptrQRG(callsign, txFrequency, duplexShift, range, agl); + m_d->m_app->rptrQRG(callsign, txFrequency, duplexShift, range, agl); } void CIRCDDBClient::kickWatchdog(const std::string& callsign, const std::string& wdInfo) { - d->app->kickWatchdog(callsign, wdInfo); + m_d->m_app->kickWatchdog(callsign, wdInfo); } @@ -112,7 +112,7 @@ bool CIRCDDBClient::sendHeard( const std::string& myCall, const std::string& myC return false; } - return d->app->sendHeard(myCall, myCallExt, yourCall, rpt1, rpt2, flag1, flag2, flag3, std::string(" "), std::string(""), std::string("")); + return m_d->m_app->sendHeard(myCall, myCallExt, yourCall, rpt1, rpt2, flag1, flag2, flag3, std::string(" "), std::string(""), std::string("")); } void CIRCDDBClient::sendDStarGatewayInfo(const std::string subcommand, const std::vector parms) @@ -123,7 +123,7 @@ void CIRCDDBClient::sendDStarGatewayInfo(const std::string subcommand, const std CLog::logInfo("\n"); if(m_isQuadNet) { - d->app->sendDStarGatewayInfo(subcommand, parms); + m_d->m_app->sendDStarGatewayInfo(subcommand, parms); } } @@ -175,7 +175,7 @@ bool CIRCDDBClient::sendHeardWithTXMsg(const std::string& myCall, const std::str msg.push_back('_'); } } - return d->app->sendHeard(myCall, myCallExt, yourCall, rpt1, rpt2, flag1, flag2, flag3, dest, msg, std::string("")); + return m_d->m_app->sendHeard(myCall, myCallExt, yourCall, rpt1, rpt2, flag1, flag2, flag3, dest, msg, std::string("")); } @@ -238,7 +238,7 @@ bool CIRCDDBClient::sendHeardWithTXStats( const std::string& myCall, const std:: } stats.resize(20, '_'); - return d->app->sendHeard(myCall, myCallExt, yourCall, rpt1, rpt2, flag1, flag2, flag3, std::string(" "), std::string(""), stats); + return m_d->m_app->sendHeard(myCall, myCallExt, yourCall, rpt1, rpt2, flag1, flag2, flag3, std::string(" "), std::string(""), stats); } // Send query for a gateway/reflector, a false return implies a network error @@ -250,7 +250,7 @@ bool CIRCDDBClient::findGateway(const std::string& gatewayCallsign) } std::string gw(gatewayCallsign); CUtils::ToUpper(gw); - return d->app->findGateway(gw); + return m_d->m_app->findGateway(gw); } @@ -262,7 +262,7 @@ bool CIRCDDBClient::findRepeater(const std::string& repeaterCallsign) } std::string rptr(repeaterCallsign); CUtils::ToUpper(rptr); - return d->app->findRepeater(rptr); + return m_d->m_app->findRepeater(rptr); } // Send query for a user, a false return implies a network error @@ -275,7 +275,12 @@ bool CIRCDDBClient::findUser(const std::string& userCallsign) CLog::logTrace("IRC Find user %s", userCallsign.c_str()); std::string usr(userCallsign); CUtils::ToUpper(usr); - return d->app->findUser(usr); + return m_d->m_app->findUser(usr); +} + +bool CIRCDDBClient::notifyRepeaterNatTraversal(const std::string& repeater) +{ + return m_d->m_app->notifyRepeaterNatTraversal(repeater); } // The following functions are for processing received messages @@ -283,21 +288,21 @@ bool CIRCDDBClient::findUser(const std::string& userCallsign) // Get the waiting message type IRCDDB_RESPONSE_TYPE CIRCDDBClient::getMessageType() { - return d->app->getReplyMessageType(); + return m_d->m_app->getReplyMessageType(); } // Get a gateway message, as a result of IDRT_REPEATER returned from getMessageType() // A false return implies a network error bool CIRCDDBClient::receiveRepeater(std::string& repeaterCallsign, std::string& gatewayCallsign, std::string& address) { - IRCDDB_RESPONSE_TYPE rt = d->app->getReplyMessageType(); + IRCDDB_RESPONSE_TYPE rt = m_d->m_app->getReplyMessageType(); if (rt != IDRT_REPEATER) { CLog::logDebug("CIRCDDBClient::receiveRepeater: unexpected response type=%d\n", rt); return false; } - IRCMessage *m = d->app->getReplyMessage(); + IRCMessage *m = m_d->m_app->getReplyMessage(); if (m == NULL) { CLog::logDebug("CIRCDDBClient::receiveRepeater: no message\n"); return false; @@ -326,14 +331,14 @@ bool CIRCDDBClient::receiveRepeater(std::string& repeaterCallsign, std::string& // A false return implies a network error bool CIRCDDBClient::receiveGateway(std::string& gatewayCallsign, std::string& address) { - IRCDDB_RESPONSE_TYPE rt = d->app->getReplyMessageType(); + IRCDDB_RESPONSE_TYPE rt = m_d->m_app->getReplyMessageType(); if (rt != IDRT_GATEWAY) { CLog::logDebug("CIRCDDBClient::receiveGateway: unexpected response type=%d\n", rt); return false; } - IRCMessage *m = d->app->getReplyMessage(); + IRCMessage *m = m_d->m_app->getReplyMessage(); if (m == NULL) { CLog::logDebug("CIRCDDBClient::receiveGateway: no message\n"); @@ -368,14 +373,14 @@ bool CIRCDDBClient::receiveUser(std::string& userCallsign, std::string& repeater bool CIRCDDBClient::receiveUser(std::string& userCallsign, std::string& repeaterCallsign, std::string& gatewayCallsign, std::string& address, std::string& timeStamp) { - IRCDDB_RESPONSE_TYPE rt = d->app->getReplyMessageType(); + IRCDDB_RESPONSE_TYPE rt = m_d->m_app->getReplyMessageType(); if (rt != IDRT_USER) { CLog::logDebug("CIRCDDBClient::receiveUser: unexpected response type=%d\n", rt); return false; } - IRCMessage * m = d->app->getReplyMessage(); + IRCMessage * m = m_d->m_app->getReplyMessage(); if (m == NULL) { CLog::logDebug("CIRCDDBClient::receiveUser: no message\n"); @@ -406,13 +411,42 @@ bool CIRCDDBClient::receiveUser(std::string& userCallsign, std::string& repeater return true; } -void CIRCDDBClient::close() // Implictely kills any threads in the IRC code +bool CIRCDDBClient::receiveNATTraversalG2(std::string& address) { - d->client -> stopWork(); - d->app -> stopWork(); -} + IRCDDB_RESPONSE_TYPE rt = m_d->m_app->getReplyMessageType(); + + if(rt != IDRT_NATTRAVERSAL_G2) { + CLog::logDebug("CIRCDDBClient::receiveNATTraversalG2: unexpected response type=%d\n", rt); + return false; + } + IRCMessage * m = m_d->m_app->getReplyMessage(); -void CIRCDDBClient::queryUsers() + if (m == NULL) { + CLog::logDebug("CIRCDDBClient::receiveUser: no message\n"); + return false; + } + + if (m->getCommand().compare("NATTRAVERSAL_G2")) { + CLog::logDebug("CIRCDDBClient::receiveNATTraversalG2: wrong message type, expected 'NATTRAVERSAL_G2', got '%s'\n", m->getCommand().c_str()); + delete m; + return false; + } + + if (1 != m->getParamCount()) { + CLog::logDebug("CIRCDDBClient::receiveNATTraversalG2: unexpected number of message parameters, expected 1, got %d\n", m->getParamCount()); + delete m; + return false; + } + + address = m->m_params[0]; + delete m; + + return true; +} + +void CIRCDDBClient::close() // Implictely kills any threads in the IRC code { + m_d->client -> stopWork(); + m_d->m_app -> stopWork(); } diff --git a/IRCDDBClient.h b/IRCDDBClient.h index e33a3f0..7160b66 100644 --- a/IRCDDBClient.h +++ b/IRCDDBClient.h @@ -106,6 +106,9 @@ public: // Send query for a user, a false return implies a network error 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); + // Support for the Smart Group Server void sendDStarGatewayInfo(const std::string subcommand, const std::vector parms); @@ -128,12 +131,12 @@ public: bool receiveUser(std::string& userCallsign, std::string& repeaterCallsign, std::string& gatewayCallsign, std::string& address, std::string& timeStamp); - void close(); // Implictely kills any threads in the IRC code + bool receiveNATTraversalG2(std::string& address); - void queryUsers(); + void close(); // Implictely kills any threads in the IRC code private: - struct CIRCDDBClientPrivate * const d; + struct CIRCDDBClientPrivate * const m_d; bool m_isQuadNet; }; diff --git a/IRCDDBMultiClient.cpp b/IRCDDBMultiClient.cpp index d4f2ead..5c13b77 100644 --- a/IRCDDBMultiClient.cpp +++ b/IRCDDBMultiClient.cpp @@ -181,6 +181,16 @@ bool CIRCDDBMultiClient::findUser(const std::string & userCallsign) return result; } +bool CIRCDDBMultiClient::notifyRepeaterNatTraversal(const std::string& repeater) +{ + bool result = true; + for (unsigned int i = 0; i < m_clients.size(); i++) { + result = m_clients[i]->notifyRepeaterNatTraversal(repeater) && result; + } + + return result; +} + IRCDDB_RESPONSE_TYPE CIRCDDBMultiClient::getMessageType() { //procees the inner clients at each call @@ -370,9 +380,3 @@ CIRCDDBMultiClientQuery_HashMap * CIRCDDBMultiClient::getQueriesHashMap(IRCDDB_R return NULL; } } - - -void CIRCDDBMultiClient::queryUsers() -{ - -} \ No newline at end of file diff --git a/IRCDDBMultiClient.h b/IRCDDBMultiClient.h index 44a18cd..f9fcbb7 100644 --- a/IRCDDBMultiClient.h +++ b/IRCDDBMultiClient.h @@ -150,6 +150,7 @@ 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 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); @@ -157,7 +158,6 @@ public: virtual bool receiveUser(std::string & userCallsign, std::string & repeaterCallsign, std::string & gatewayCallsign, std::string & address, std::string & timeStamp); virtual void sendDStarGatewayInfo(const std::string subcommand, const std::vector parms); virtual void close(); - virtual void queryUsers(); // diff --git a/RepeaterHandler.cpp b/RepeaterHandler.cpp index 13635b3..2529eaf 100644 --- a/RepeaterHandler.cpp +++ b/RepeaterHandler.cpp @@ -2022,7 +2022,7 @@ void CRepeaterHandler::g2CommandHandler(const std::string& callsign, const std:: if (m_linkStatus == LS_LINKING_CCS || m_linkStatus == LS_LINKED_CCS) return; - if (callsign.substr(0,1) == "/") { + if (!callsign.empty() && callsign[0] == '/') { if (m_irc == NULL) { CLog::logInfo("%s is trying to G2 route with ircDDB disabled", user.c_str()); m_g2Status = G2_LOCAL; @@ -2053,6 +2053,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); if (data == NULL) { m_g2Status = G2_REPEATER;