diff --git a/QnetGateway.cpp b/QnetGateway.cpp index 0497c6f..ae25e2e 100644 --- a/QnetGateway.cpp +++ b/QnetGateway.cpp @@ -452,7 +452,8 @@ void CQnetGateway::GetIRCDataThread() } while (((type = ii->getMessageType()) != IDRT_NONE) && keep_running) { - if (type == IDRT_USER) { + switch (type) { + case IDRT_USER: ii->receiveUser(user, rptr, gateway, ipaddr); if (!user.empty()) { if (!rptr.empty() && !gateway.empty() && !ipaddr.empty()) { @@ -471,7 +472,8 @@ void CQnetGateway::GetIRCDataThread() } } - } else if (type == IDRT_REPEATER) { + break; + case IDRT_REPEATER: ii->receiveRepeater(rptr, gateway, ipaddr, proto); if (!rptr.empty()) { if (!gateway.empty() && !ipaddr.empty()) { @@ -489,7 +491,8 @@ void CQnetGateway::GetIRCDataThread() } } - } else if (type == IDRT_GATEWAY) { + break; + case IDRT_GATEWAY: ii->receiveGateway(gateway, ipaddr, proto); if (!gateway.empty() && !ipaddr.empty()) { if (LOG_IRC) @@ -504,8 +507,28 @@ void CQnetGateway::GetIRCDataThread() // printf("%d gateways\n", gwy2ip_map.size()); } - } - } + break; + case IDRT_PING: + ii->receivePing(rptr); + if (! rptr.empty()) { + pthread_mutex_lock(&irc_data_mutex); + auto git = rptr2gwy_map.find(rptr); + if (rptr2gwy_map.end() == git) + break; + gateway = git->second; + auto ait = gwy2ip_map.find(gateway); + if (gwy2ip_map.end() != ait) + break; + ipaddr = ait->second; + pthread_mutex_unlock(&irc_data_mutex); + CSockAddress to(af_family, (unsigned short)g2_external.port, ipaddr.c_str()); + sendto(g2_sock, "PONG", 4, 0, to.GetPointer(), to.GetSize()); + } + break; + default: + break; + } // switch (type) + } // while (keep_running) std::this_thread::sleep_for(std::chrono::milliseconds(500)); } printf("GetIRCDataThread exiting...\n"); @@ -572,7 +595,7 @@ bool CQnetGateway::get_yrcall_rptr(const std::string &call, std::string &arearp_ int rc = get_yrcall_rptr_from_cache(call, arearp_cs, zonerp_cs, mod, ip, RoU); pthread_mutex_unlock(&irc_data_mutex); if (rc == 0) { - //printf("get_yrcall_rptr_from_cache: call='%s' arearp_cs='%s' zonerp_cs='%s', mod=%c ip='%s' RoU=%c\n", call.c_str(), arearp_cs.c_str(), zonerp_cs.c_str(), *mod, ip.c_str(), RoU); + printf("get_yrcall_rptr_from_cache: call='%s' arearp_cs='%s' zonerp_cs='%s', mod=%c ip='%s' RoU=%c\n", call.c_str(), arearp_cs.c_str(), zonerp_cs.c_str(), *mod, ip.c_str(), RoU); return true; } else if (rc == 2) return false; @@ -1872,7 +1895,10 @@ void CQnetGateway::Process() SDSVT dsvt; socklen_t fromlen = sizeof(struct sockaddr_storage); ssize_t g2buflen = recvfrom(g2_sock, dsvt.title, 56, 0, fromDstar.GetPointer(), &fromlen); - ProcessG2(g2buflen, dsvt, true); + if (4==g2buflen && 0==memcmp(dsvt.title, "PONG", 4)) + printf("Got a pong from [%s]:%u\n", fromDstar.GetAddress(), fromDstar.GetPort()); + else + ProcessG2(g2buflen, dsvt, true); FD_CLR(g2_sock, &fdset); } diff --git a/ircddb/IRCApplication.h b/ircddb/IRCApplication.h index 92b7018..5e7d6c2 100644 --- a/ircddb/IRCApplication.h +++ b/ircddb/IRCApplication.h @@ -23,6 +23,9 @@ public: virtual void setSendQ(IRCMessageQueue *s) = 0; virtual IRCMessageQueue *getSendQ(void) = 0; + virtual void putReplyMessage(IRCMessage *m) = 0; + virtual void sendPing(const std::string &to, const std::string &from) = 0; + virtual ~IRCApplication() {} }; diff --git a/ircddb/IRCDDB.cpp b/ircddb/IRCDDB.cpp index 7d3d47f..9c076b7 100644 --- a/ircddb/IRCDDB.cpp +++ b/ircddb/IRCDDB.cpp @@ -150,8 +150,6 @@ bool CIRCDDB::sendHeardWithTXMsg(const std::string &myCall, const std::string &m return d->app->sendHeard( myCall, myCallExt, yourCall, rpt1, rpt2, flag1, flag2, flag3, dest, msg, ""); } - - bool CIRCDDB::sendHeardWithTXStats(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, int num_dv_frames, int num_dv_silent_frames, int num_bit_errors) { @@ -218,8 +216,6 @@ bool CIRCDDB::sendHeardWithTXStats(const std::string &myCall, const std::string return d->app->sendHeard( myCall, myCallExt, yourCall, rpt1, rpt2, flag1, flag2, flag3, " ", "", stats); } - - // Send query for a gateway/reflector, a false return implies a network error bool CIRCDDB::findGateway(const std::string &gatewayCallsign) { @@ -232,7 +228,6 @@ bool CIRCDDB::findGateway(const std::string &gatewayCallsign) return d->app->findGateway(gcs); } - bool CIRCDDB::findRepeater(const std::string &repeaterCallsign) { if (repeaterCallsign.size() != 8) { @@ -275,7 +270,7 @@ bool CIRCDDB::receiveRepeater(std::string &repeaterCallsign, std::string &gatewa return false; } - IRCMessage * m = d->app->getReplyMessage(); + IRCMessage *m = d->app->getReplyMessage(); if (m == NULL) { printf("CIRCDDB::receiveRepeater: no message\n"); @@ -312,7 +307,7 @@ bool CIRCDDB::receiveGateway(std::string &gatewayCallsign, std::string &address, return false; } - IRCMessage * m = d->app->getReplyMessage(); + IRCMessage *m = d->app->getReplyMessage(); if (m == NULL) { printf("CIRCDDB::receiveGateway: no message\n"); @@ -354,7 +349,7 @@ bool CIRCDDB::receiveUser(std::string &userCallsign, std::string &repeaterCallsi return false; } - IRCMessage * m = d->app->getReplyMessage(); + IRCMessage *m = d->app->getReplyMessage(); if (m == NULL) { printf("CIRCDDB::receiveUser: no message\n"); @@ -382,6 +377,44 @@ bool CIRCDDB::receiveUser(std::string &userCallsign, std::string &repeaterCallsi return true; } +bool CIRCDDB::receivePing(std::string &repeaterCallsign) +{ + IRCDDB_RESPONSE_TYPE rt = d->app->getReplyMessageType(); + + if (rt != IDRT_PING) { + printf("CIRCDDB::receivePing: unexpected response type\n"); + return false; + } + + IRCMessage *m = d->app->getReplyMessage(); + + if (NULL == m) { + printf("CIRCDDB::receivePing: no message\n"); + return false; + } + + if (m->getCommand().compare("IDRT_PING")) { + printf("CIRCDDB::receivePing: wrong messsage type\n"); + return false; + } + + if (1 != m->getParamCount()) { + printf("CIRCDDB::receivePing: unexpected number of message parameters\n"); + return false; + } + + repeaterCallsign = m->getParam(0); + + delete m; + + return true; +} + +void CIRCDDB::sendPing(const std::string &to, const std::string &from) +{ + d->app->sendPing(to, from); +} + void CIRCDDB::close() // Implictely kills any threads in the IRC code { d->client->stopWork(); diff --git a/ircddb/IRCDDB.h b/ircddb/IRCDDB.h index e06460b..4ba7858 100644 --- a/ircddb/IRCDDB.h +++ b/ircddb/IRCDDB.h @@ -6,7 +6,8 @@ enum IRCDDB_RESPONSE_TYPE { IDRT_NONE, IDRT_USER, IDRT_GATEWAY, - IDRT_REPEATER + IDRT_REPEATER, + IDRT_PING }; enum DSTAR_PROTOCOL { @@ -15,7 +16,6 @@ enum DSTAR_PROTOCOL { DP_DPLUS }; - struct CIRCDDBPrivate; class CIRCDDB @@ -24,12 +24,12 @@ public: CIRCDDB(const std::string &hostName, unsigned int port, const std::string &callsign, const std::string &password, const std::string &versionInfo); ~CIRCDDB(); + // returns the socket family type int GetFamily(); // A false return implies a network error, or unable to log in bool open(); - // rptrQTH can be called multiple times if necessary // rptrcall callsign of the repeater // latitude WGS84 position of antenna in degrees, positive value -> NORTH @@ -38,8 +38,6 @@ public: void rptrQTH(const std::string &rptrcall, double latitude, double longitude, const std::string &desc1, const std::string &desc2, const std::string &infoURL, const std::string &swVersion); - - // rptrQRG can be called multiple times if necessary // module letter of the module, valid values: "A", "B", "C", "D", "AD", "BD", "CD", "DD" // txFrequency repeater TX frequency in MHz @@ -49,7 +47,6 @@ public: void rptrQRG(const std::string &rptrcall, double txFrequency, double duplexShift, double range, double agl); - // If you call this method once, watchdog messages will be sent to the // to the ircDDB network every 15 minutes. Invoke this method every 1-2 minutes to indicate // that the gateway is working properly. After activating the watchdog, a red LED will be displayed @@ -60,8 +57,6 @@ public: void kickWatchdog(const std::string &wdInfo); - - // get internal network status int getConnectionState(); // one of these values is returned: @@ -74,14 +69,12 @@ public: // Send heard data, a false return implies a network error 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); - // same as sendHeard with two new fields: // network_destination: empty string or 8-char call sign of the repeater // or reflector, where this transmission is relayed to. // tx_message: 20-char TX message or empty string, if the user did not // send a TX message - bool sendHeardWithTXMsg(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 &network_destination, const std::string &tx_message); + bool sendHeardWithTXMsg(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 &network_destination, const std::string &tx_message); // this method should be called at the end of a transmission // num_dv_frames: number of DV frames sent out (96 bit frames, 20ms) @@ -93,8 +86,7 @@ public: // So, the overall bit error rate is calculated like this: // BER = num_bit_errors / (num_dv_frames * 24) // Set num_bit_errors = -1, if the error information is not available. - bool sendHeardWithTXStats(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, int num_dv_frames, int num_dv_silent_frames, int num_bit_errors); + bool sendHeardWithTXStats(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, int num_dv_frames, int num_dv_silent_frames, int num_bit_errors); // The following three functions don't block waiting for a reply, they just send the data @@ -126,10 +118,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 receivePing(std::string &repeaterCallsign); + void sendPing(const std::string &to, const std::string &from); + + void close(); // Implictely kills any threads in the IRC code private: struct CIRCDDBPrivate * const d; - }; diff --git a/ircddb/IRCDDBApp.cpp b/ircddb/IRCDDBApp.cpp index 83a49b5..aaee3e5 100644 --- a/ircddb/IRCDDBApp.cpp +++ b/ircddb/IRCDDBApp.cpp @@ -265,6 +265,11 @@ IRCMessage *IRCDDBApp::getReplyMessage() return d->replyQ.getMessage(); } +void IRCDDBApp::putReplyMessage(IRCMessage *m) +{ + d->replyQ.putMessage(m); +} + bool IRCDDBApp::startWork() { d->terminateThread = false; @@ -428,6 +433,30 @@ void IRCDDBApp::userChanOp(const std::string &nick, bool op) d->userMapMutex.unlock(); } +void IRCDDBApp::sendPing(const std::string &to, const std::string &from) +{ + std::string t = to.substr(0, 7); + + ReplaceChar(t, '_', ' '); + while (isspace(t[t.length()-1])) + t.pop_back(); + ToLower(t); + + d->userMapMutex.lock(); + for (int j=1; j <= 4; j++) { + std::string ircUser = t + std::string("-") + std::to_string(j); + + if (1 == d->user.count(ircUser)) { + IRCMessage *rm = new IRCMessage(t, "IDRT_PING"); + rm->addParam(from); + d->sendQ->putMessage(rm); + break; + } + } + d->userMapMutex.unlock(); + +} + static const int numberOfTables = 2; std::string IRCDDBApp::getIPAddress(std::string &zonerp_cs) diff --git a/ircddb/IRCDDBApp.h b/ircddb/IRCDDBApp.h index 09bdf7c..1be0ffd 100644 --- a/ircddb/IRCDDBApp.h +++ b/ircddb/IRCDDBApp.h @@ -33,6 +33,9 @@ public: virtual void setSendQ(IRCMessageQueue *s); virtual IRCMessageQueue *getSendQ(); + virtual void putReplyMessage(IRCMessage *m); + virtual void sendPing(const std::string &to, const std::string &from); + bool startWork(); void stopWork(); @@ -44,9 +47,7 @@ public: bool findRepeater(const std::string &s); bool findGateway(const std::string &s); - 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); + 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); int getConnectionState(); diff --git a/ircddb/IRCProtocol.cpp b/ircddb/IRCProtocol.cpp index e85ba29..8b09931 100644 --- a/ircddb/IRCProtocol.cpp +++ b/ircddb/IRCProtocol.cpp @@ -176,11 +176,19 @@ bool IRCProtocol::processQueues(IRCMessageQueue *recvQ, IRCMessageQueue *sendQ) } } } else if (0 == m->command.compare("PRIVMSG")) { - if ((m->numParams == 2) && (app != NULL)) { - if (0 == m->params[0].compare(channel)) { - app->msgChannel(m); - } else if (0 == m->params[0].compare(currentNick)) { - app->msgQuery(m); + if (app) { + if (2 == m->numParams) { + if (0 == m->params[0].compare(channel)) { + app->msgChannel(m); + } else if (0 == m->params[0].compare(currentNick)) { + app->msgQuery(m); + } + } else if (3 == m->numParams) { + // pass this on to the replyQ so the gateway can PONG the sender + if (0==m->params[0].compare(currentNick) && 0==m->params[1].compare("IDRT_PING")) { + IRCMessage *rm = new IRCMessage(m->params[1], m->params[2]); + app->putReplyMessage(rm); + } } } } else if (0 == m->command.compare("352")) { // WHO list @@ -343,5 +351,3 @@ bool IRCProtocol::processQueues(IRCMessageQueue *recvQ, IRCMessageQueue *sendQ) return true; } - -