#5 implement message for G2 NATT

pull/32/head
Geoffrey Merck 4 years ago
parent 0d0efba655
commit 47b7ec54ab

@ -20,7 +20,8 @@
"ostream": "cpp",
"sstream": "cpp",
"stop_token": "cpp",
"streambuf": "cpp"
"streambuf": "cpp",
"chrono": "cpp"
},
"editor.tokenColorCustomizations": {
"textMateRules": [

@ -795,7 +795,8 @@ void CDStarGatewayThread::processIrcDDB()
}
}
break;
case IDRT_NATTRAVERSAL_G2:
break;
default:
return;
}

@ -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<std::string> 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*> CIRCDDB_Array;

@ -27,6 +27,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <cstdio>
#include <chrono>
#include <thread>
#include <boost/algorithm/string.hpp>
#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<std::string, IRCDDBAppUserObject>::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<std::string> &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<std::string> 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));

@ -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<void> m_future;
};

@ -28,23 +28,23 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
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<std::string> 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();
}

@ -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<std::string> 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;
};

@ -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()
{
}

@ -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<std::string> parms);
virtual void close();
virtual void queryUsers();
//

@ -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;

Loading…
Cancel
Save

Powered by TurnKey Linux.