dual IRC clients

pull/14/head
Tom Early 7 years ago
parent 74fd8cade2
commit be7b5a0ea7

@ -216,14 +216,18 @@ bool CQnetGateway::ReadConfig(char *cfgFile)
printf("OWNER='%s'\n", OWNER.c_str()); printf("OWNER='%s'\n", OWNER.c_str());
OWNER.resize(CALL_SIZE, ' '); OWNER.resize(CALL_SIZE, ' ');
if (cfg.GetValue(path+"host", estr, ircddb.ip, 3, MAXHOSTNAMELEN)) for (int i=0; i<2; i++) {
return true; std::string p(path + std::to_string(i) + "_");
if (cfg.KeyExists(p+"host")) {
if (cfg.GetValue(path+"port", estr, ircddb.port, 1000, 65535)) cfg.GetValue(path+"host", estr, ircddb[i].ip, 3, MAXHOSTNAMELEN);
return true; cfg.GetValue(path+"port", estr, ircddb[i].port, 1000, 65535);
cfg.GetValue(path+"password", estr, IRCDDB_PASSWORD[i], 0, 512);
if (cfg.GetValue(path+"password", estr, IRCDDB_PASSWORD, 0, 512)) }
}
if (0 == ircddb[0].ip.compare(ircddb[1].ip)) {
fprintf(stderr, "IRC networks must be different\n");
return true; return true;
}
// module // module
for (int m=0; m<3; m++) { for (int m=0; m<3; m++) {
@ -336,11 +340,11 @@ bool CQnetGateway::ReadConfig(char *cfgFile)
} }
// Create ports // Create ports
int CQnetGateway::open_port(const SPORTIP &pip) int CQnetGateway::open_port(const SPORTIP &pip, int family)
{ {
CSockAddress sin(af_family, pip.port, pip.ip.c_str()); CSockAddress sin(family, pip.port, pip.ip.c_str());
int sock = socket(af_family, SOCK_DGRAM, 0); int sock = socket(family, SOCK_DGRAM, 0);
if (0 > sock) { if (0 > sock) {
printf("Failed to create socket on %s:%d, errno=%d, %s\n", pip.ip.c_str(), pip.port, errno, strerror(errno)); printf("Failed to create socket on %s:%d, errno=%d, %s\n", pip.ip.c_str(), pip.port, errno, strerror(errno));
return -1; return -1;
@ -363,7 +367,7 @@ int CQnetGateway::open_port(const SPORTIP &pip)
} }
/* receive data from the irc server and save it */ /* receive data from the irc server and save it */
void CQnetGateway::GetIRCDataThread() void CQnetGateway::GetIRCDataThread(int i)
{ {
std::string user, rptr, gateway, ipaddr; std::string user, rptr, gateway, ipaddr;
DSTAR_PROTOCOL proto; DSTAR_PROTOCOL proto;
@ -394,10 +398,10 @@ void CQnetGateway::GetIRCDataThread()
bool not_announced[3]; bool not_announced[3];
for (int i=0; i<3; i++) for (int i=0; i<3; i++)
not_announced[i] = this->rptr.mod[i].defined; // announce to all modules that are defined! not_announced[i] = this->rptr.mod[i].defined; // announce to all modules that are defined!
bool is_quadnet = (std::string::npos != ircddb.ip.find(".openquad.net")); bool is_quadnet = (std::string::npos != ircddb[i].ip.find(".openquad.net"));
bool doFind = true; bool doFind = true;
while (keep_running) { while (keep_running) {
int rc = ii->getConnectionState(); int rc = ii[i]->getConnectionState();
if (rc > 5 && rc < 8 && is_quadnet) { if (rc > 5 && rc < 8 && is_quadnet) {
char ch = '\0'; char ch = '\0';
if (not_announced[0]) if (not_announced[0])
@ -425,7 +429,7 @@ void CQnetGateway::GetIRCDataThread()
for (auto it=findRoute.begin(); it!=findRoute.end(); it++) { for (auto it=findRoute.begin(); it!=findRoute.end(); it++) {
std::this_thread::sleep_for(std::chrono::milliseconds(800)); std::this_thread::sleep_for(std::chrono::milliseconds(800));
printf("\t'%s'\n", it->c_str()); printf("\t'%s'\n", it->c_str());
ii->findUser(*it); ii[i]->findUser(*it);
} }
doFind = false; doFind = false;
} }
@ -451,22 +455,22 @@ void CQnetGateway::GetIRCDataThread()
threshold = 0; threshold = 0;
} }
while (((type = ii->getMessageType()) != IDRT_NONE) && keep_running) { while (((type = ii[i]->getMessageType()) != IDRT_NONE) && keep_running) {
switch (type) { switch (type) {
case IDRT_USER: case IDRT_USER:
ii->receiveUser(user, rptr, gateway, ipaddr); ii[i]->receiveUser(user, rptr, gateway, ipaddr);
if (!user.empty()) { if (!user.empty()) {
if (!rptr.empty() && !gateway.empty() && !ipaddr.empty()) { if (!rptr.empty() && !gateway.empty() && !ipaddr.empty()) {
if (LOG_IRC) if (LOG_IRC)
printf("C-u:%s,%s,%s,%s\n", user.c_str(), rptr.c_str(), gateway.c_str(), ipaddr.c_str()); printf("C-u:%s,%s,%s,%s\n", user.c_str(), rptr.c_str(), gateway.c_str(), ipaddr.c_str());
pthread_mutex_lock(&irc_data_mutex); pthread_mutex_lock(&irc_data_mutex[i]);
user2rptr_map[user] = rptr; user2rptr_map[i][user] = rptr;
rptr2gwy_map[rptr] = gateway; rptr2gwy_map[i][rptr] = gateway;
gwy2ip_map[gateway] = ipaddr; gwy2ip_map[i][gateway] = ipaddr;
pthread_mutex_unlock(&irc_data_mutex); pthread_mutex_unlock(&irc_data_mutex[i]);
// printf("%d users, %d repeaters, %d gateways\n", user2rptr_map.size(), rptr2gwy_map.size(), gwy2ip_map.size()); // printf("%d users, %d repeaters, %d gateways\n", user2rptr_map.size(), rptr2gwy_map.size(), gwy2ip_map.size());
@ -474,18 +478,18 @@ void CQnetGateway::GetIRCDataThread()
} }
break; break;
case IDRT_REPEATER: case IDRT_REPEATER:
ii->receiveRepeater(rptr, gateway, ipaddr, proto); ii[i]->receiveRepeater(rptr, gateway, ipaddr, proto);
if (!rptr.empty()) { if (!rptr.empty()) {
if (!gateway.empty() && !ipaddr.empty()) { if (!gateway.empty() && !ipaddr.empty()) {
if (LOG_IRC) if (LOG_IRC)
printf("C-r:%s,%s,%s\n", rptr.c_str(), gateway.c_str(), ipaddr.c_str()); printf("C-r:%s,%s,%s\n", rptr.c_str(), gateway.c_str(), ipaddr.c_str());
pthread_mutex_lock(&irc_data_mutex); pthread_mutex_lock(&irc_data_mutex[i]);
rptr2gwy_map[rptr] = gateway; rptr2gwy_map[i][rptr] = gateway;
gwy2ip_map[gateway] = ipaddr; gwy2ip_map[i][gateway] = ipaddr;
pthread_mutex_unlock(&irc_data_mutex); pthread_mutex_unlock(&irc_data_mutex[i]);
// printf("%d repeaters, %d gateways\n", rptr2gwy_map.size(), gwy2ip_map.size()); // printf("%d repeaters, %d gateways\n", rptr2gwy_map.size(), gwy2ip_map.size());
@ -493,34 +497,34 @@ void CQnetGateway::GetIRCDataThread()
} }
break; break;
case IDRT_GATEWAY: case IDRT_GATEWAY:
ii->receiveGateway(gateway, ipaddr, proto); ii[i]->receiveGateway(gateway, ipaddr, proto);
if (!gateway.empty() && !ipaddr.empty()) { if (!gateway.empty() && !ipaddr.empty()) {
if (LOG_IRC) if (LOG_IRC)
printf("C-g:%s,%s\n", gateway.c_str(),ipaddr.c_str()); printf("C-g:%s,%s\n", gateway.c_str(),ipaddr.c_str());
pthread_mutex_lock(&irc_data_mutex); pthread_mutex_lock(&irc_data_mutex[i]);
gwy2ip_map[gateway] = ipaddr; gwy2ip_map[i][gateway] = ipaddr;
pthread_mutex_unlock(&irc_data_mutex); pthread_mutex_unlock(&irc_data_mutex[i]);
// printf("%d gateways\n", gwy2ip_map.size()); // printf("%d gateways\n", gwy2ip_map.size());
} }
break; break;
case IDRT_PING: case IDRT_PING:
ii->receivePing(rptr); ii[i]->receivePing(rptr);
ReplaceChar(rptr, '_', ' '); ReplaceChar(rptr, '_', ' ');
if (! rptr.empty()) { if (! rptr.empty()) {
pthread_mutex_lock(&irc_data_mutex); pthread_mutex_lock(&irc_data_mutex[i]);
auto git = rptr2gwy_map.find(rptr); auto git = rptr2gwy_map[i].find(rptr);
if (rptr2gwy_map.end() != git) { if (rptr2gwy_map[i].end() != git) {
gateway = git->second; gateway = git->second;
auto ait = gwy2ip_map.find(gateway); auto ait = gwy2ip_map[i].find(gateway);
if (gwy2ip_map.end() != ait) { if (gwy2ip_map[i].end() != ait) {
ipaddr = ait->second; ipaddr = ait->second;
CSockAddress to(af_family, (unsigned short)g2_external.port, ipaddr.c_str()); CSockAddress to(af_family[i], (unsigned short)g2_external.port, ipaddr.c_str());
sendto(g2_sock, "PONG", 4, 0, to.GetPointer(), to.GetSize()); sendto(g2_sock[i], "PONG", 4, 0, to.GetPointer(), to.GetSize());
if (LOG_QSO) if (LOG_QSO)
printf("Sent 'PONG' to %s\n", ipaddr.c_str()); printf("Sent 'PONG' to %s\n", ipaddr.c_str());
} else { } else {
@ -529,7 +533,7 @@ void CQnetGateway::GetIRCDataThread()
} else { } else {
printf("Can't respond to PING, repeater %s not in rptr2gwy_map\n", rptr.c_str()); printf("Can't respond to PING, repeater %s not in rptr2gwy_map\n", rptr.c_str());
} }
pthread_mutex_unlock(&irc_data_mutex); pthread_mutex_unlock(&irc_data_mutex[i]);
} }
break; break;
default: default:
@ -543,7 +547,7 @@ void CQnetGateway::GetIRCDataThread()
} }
/* return codes: 0=OK(found it), 1=TRY AGAIN, 2=FAILED(bad data) */ /* return codes: 0=OK(found it), 1=TRY AGAIN, 2=FAILED(bad data) */
int CQnetGateway::get_yrcall_rptr_from_cache(const std::string &call, std::string &arearp_cs, std::string &zonerp_cs, char *mod, std::string &ip, char RoU) int CQnetGateway::get_yrcall_rptr_from_cache(const int i, const std::string &call, std::string &arearp_cs, std::string &zonerp_cs, char *mod, std::string &ip, char RoU)
{ {
std::string temp; std::string temp;
@ -553,8 +557,8 @@ int CQnetGateway::get_yrcall_rptr_from_cache(const std::string &call, std::strin
/* find the user in the CACHE */ /* find the user in the CACHE */
if (RoU == 'U') { if (RoU == 'U') {
auto user_pos = user2rptr_map.find(call); auto user_pos = user2rptr_map[i].find(call);
if (user_pos != user2rptr_map.end()) { if (user_pos != user2rptr_map[i].end()) {
arearp_cs = user_pos->second.substr(0, 7); arearp_cs = user_pos->second.substr(0, 7);
*mod = user_pos->second.at(7); *mod = user_pos->second.at(7);
} else { } else {
@ -578,12 +582,12 @@ int CQnetGateway::get_yrcall_rptr_from_cache(const std::string &call, std::strin
temp.append(1, *mod); temp.append(1, *mod);
arearp_cs.resize(8, ' '); arearp_cs.resize(8, ' ');
auto rptr_pos = rptr2gwy_map.find(temp); auto rptr_pos = rptr2gwy_map[i].find(temp);
if (rptr_pos != rptr2gwy_map.end()) { if (rptr_pos != rptr2gwy_map[i].end()) {
zonerp_cs.assign(rptr_pos->second); zonerp_cs.assign(rptr_pos->second);
auto gwy_pos = gwy2ip_map.find(zonerp_cs); auto gwy_pos = gwy2ip_map[i].find(zonerp_cs);
if (gwy_pos != gwy2ip_map.end()) { if (gwy_pos != gwy2ip_map[i].end()) {
ip.assign(gwy_pos->second); ip.assign(gwy_pos->second);
return 0; return 0;
} else { } else {
@ -596,46 +600,55 @@ int CQnetGateway::get_yrcall_rptr_from_cache(const std::string &call, std::strin
} }
} }
bool CQnetGateway::get_yrcall_rptr(const std::string &call, std::string &arearp_cs, std::string &zonerp_cs, char *mod, std::string &ip, char RoU) int CQnetGateway::get_yrcall_rptr(const std::string &call, std::string &arearp_cs, std::string &zonerp_cs, char *mod, std::string &ip, char RoU)
// returns zero if unsuccessful, otherwise returns ii index plus one
{ {
pthread_mutex_lock(&irc_data_mutex); for (int i=0; i<2; i++) {
int rc = get_yrcall_rptr_from_cache(call, arearp_cs, zonerp_cs, mod, ip, RoU); if (NULL == ii[i])
pthread_mutex_unlock(&irc_data_mutex); continue;
if (rc == 0) { int rc;
//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); if (ii[i]) {
return true; pthread_mutex_lock(&irc_data_mutex[i]);
} else if (rc == 2) rc = get_yrcall_rptr_from_cache(i, call, arearp_cs, zonerp_cs, mod, ip, RoU);
return false; pthread_mutex_unlock(&irc_data_mutex[i]);
/* at this point, the data is not in cache */
/* report the irc status */
int status = ii->getConnectionState();
// printf("irc status=%d\n", status);
if (status != 7) {
printf("Remote irc database not ready, irc status is not 7, try again\n");
return false;
}
/* request data from irc server */
if (RoU == 'U') {
printf("User [%s] not in local cache, try again\n", call.c_str());
/*** YRCALL=KJ4NHFBL ***/
if (((call.at(6) == 'A') || (call.at(6) == 'B') || (call.at(6) == 'C')) && (call.at(7) == 'L'))
printf("If this was a gateway link request, that is ok\n");
if (!ii->findUser(call)) {
printf("findUser(%s): Network error\n", call.c_str());
return false;
} }
} else if (RoU == 'R') { if (rc == 0) {
printf("Repeater [%s] not in local cache, try again\n", call.c_str()); //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);
if (!ii->findRepeater(call)) { return i+1;
printf("findRepeater(%s): Network error\n", call.c_str()); } else if (rc == 2)
return false; return 0;
}
for (int i=0; i<2; i++) {
if (NULL == ii[i])
continue;
/* at this point, the data is not in cache */
/* report the irc status */
int status = ii[i]->getConnectionState();
// printf("irc status=%d\n", status);
if (7 == status) {
/* request data from irc server */
if (RoU == 'U') {
printf("User [%s] not in local cache, try again\n", call.c_str());
/*** YRCALL=KJ4NHFBL ***/
if (((call.at(6) == 'A') || (call.at(6) == 'B') || (call.at(6) == 'C')) && (call.at(7) == 'L'))
printf("If this was a gateway link request, that is ok\n");
if (!ii[i]->findUser(call)) {
printf("findUser(%s): Network error\n", call.c_str());
return 0;
}
} else if (RoU == 'R') {
printf("Repeater [%s] not in local cache, try again\n", call.c_str());
if (!ii[i]->findRepeater(call)) {
printf("findRepeater(%s): Network error\n", call.c_str());
return 0;
}
}
} }
} }
return false; return 0;
} }
bool CQnetGateway::Flag_is_ok(unsigned char flag) bool CQnetGateway::Flag_is_ok(unsigned char flag)
@ -746,7 +759,7 @@ void CQnetGateway::ProcessTimeouts()
if ((t_now - to_remote_g2[i].last_time) > TIMING_TIMEOUT_LOCAL_RPTR) { if ((t_now - to_remote_g2[i].last_time) > TIMING_TIMEOUT_LOCAL_RPTR) {
printf("Inactivity from local rptr mod %c, removing stream id %04x\n", 'A'+i, ntohs(to_remote_g2[i].streamid)); printf("Inactivity from local rptr mod %c, removing stream id %04x\n", 'A'+i, ntohs(to_remote_g2[i].streamid));
to_remote_g2[i].toDstar.Initialize(af_family); to_remote_g2[i].toDstar.Initialize(AF_UNSPEC);
to_remote_g2[i].streamid = 0; to_remote_g2[i].streamid = 0;
to_remote_g2[i].last_time = 0; to_remote_g2[i].last_time = 0;
} }
@ -906,7 +919,10 @@ void CQnetGateway::ProcessSlowData(unsigned char *data, unsigned short sid)
band_txt[i].dest_rptr[0] = '\0'; band_txt[i].dest_rptr[0] = '\0';
} }
// we have the 20-character message, send it to the server... // we have the 20-character message, send it to the server...
ii->sendHeardWithTXMsg(band_txt[i].lh_mycall, band_txt[i].lh_sfx, (strstr(band_txt[i].lh_yrcall,"REF") == NULL)?band_txt[i].lh_yrcall:"CQCQCQ ", band_txt[i].lh_rpt1, band_txt[i].lh_rpt2, band_txt[i].flags[0], band_txt[i].flags[1], band_txt[i].flags[2], band_txt[i].dest_rptr, band_txt[i].txt); for (int x=0; x<2; x++) {
if (ii[x])
ii[x]->sendHeardWithTXMsg(band_txt[i].lh_mycall, band_txt[i].lh_sfx, (strstr(band_txt[i].lh_yrcall,"REF") == NULL)?band_txt[i].lh_yrcall:"CQCQCQ ", band_txt[i].lh_rpt1, band_txt[i].lh_rpt2, band_txt[i].flags[0], band_txt[i].flags[1], band_txt[i].flags[2], band_txt[i].dest_rptr, band_txt[i].txt);
}
band_txt[i].sent_key_on_msg = true; band_txt[i].sent_key_on_msg = true;
} }
if (to_print[i] == 3) { if (to_print[i] == 3) {
@ -939,7 +955,10 @@ void CQnetGateway::ProcessSlowData(unsigned char *data, unsigned short sid)
band_txt[i].dest_rptr[0] = '\0'; band_txt[i].dest_rptr[0] = '\0';
} }
// we have the 20-character message, send it to the server... // we have the 20-character message, send it to the server...
ii->sendHeardWithTXMsg(band_txt[i].lh_mycall, band_txt[i].lh_sfx, (strstr(band_txt[i].lh_yrcall,"REF") == NULL)?band_txt[i].lh_yrcall:"CQCQCQ ", band_txt[i].lh_rpt1, band_txt[i].lh_rpt2, band_txt[i].flags[0], band_txt[i].flags[1], band_txt[i].flags[2], band_txt[i].dest_rptr, band_txt[i].txt); for (int x=0; x<2; x++) {
if (ii[x])
ii[x]->sendHeardWithTXMsg(band_txt[i].lh_mycall, band_txt[i].lh_sfx, (strstr(band_txt[i].lh_yrcall,"REF") == NULL)?band_txt[i].lh_yrcall:"CQCQCQ ", band_txt[i].lh_rpt1, band_txt[i].lh_rpt2, band_txt[i].flags[0], band_txt[i].flags[1], band_txt[i].flags[2], band_txt[i].dest_rptr, band_txt[i].txt);
}
band_txt[i].sent_key_on_msg = true; band_txt[i].sent_key_on_msg = true;
} }
band_txt[i].txt_cnt = 0; band_txt[i].txt_cnt = 0;
@ -1061,9 +1080,8 @@ void CQnetGateway::ProcessSlowData(unsigned char *data, unsigned short sid)
} }
} }
void CQnetGateway::ProcessG2(const ssize_t g2buflen, const SDSVT &g2buf, const bool is_from_g2) void CQnetGateway::ProcessG2(const ssize_t g2buflen, const SDSVT &g2buf, const int source_sock)
// is_from_g2==true means it's coming from external port 40000 // source_sock is the socket number of the incoming data, or -1 if it's a unix socket
// is_from_g2==false means it's coming from the link2gate Unix socket
{ {
static unsigned char lastctrl = 20U; static unsigned char lastctrl = 20U;
static std::string superframe[3]; static std::string superframe[3];
@ -1079,7 +1097,7 @@ void CQnetGateway::ProcessG2(const ssize_t g2buflen, const SDSVT &g2buf, const b
superframe[i].clear(); superframe[i].clear();
if (LOG_QSO) { if (LOG_QSO) {
printf("id=%04x flags=%02x:%02x:%02x ur=%.8s r1=%.8s r2=%.8s my=%.8s/%.4s ", ntohs(g2buf.streamid), g2buf.hdr.flag[0], g2buf.hdr.flag[1], g2buf.hdr.flag[2], g2buf.hdr.urcall, g2buf.hdr.rpt1, g2buf.hdr.rpt2, g2buf.hdr.mycall, g2buf.hdr.sfx); printf("id=%04x flags=%02x:%02x:%02x ur=%.8s r1=%.8s r2=%.8s my=%.8s/%.4s ", ntohs(g2buf.streamid), g2buf.hdr.flag[0], g2buf.hdr.flag[1], g2buf.hdr.flag[2], g2buf.hdr.urcall, g2buf.hdr.rpt1, g2buf.hdr.rpt2, g2buf.hdr.mycall, g2buf.hdr.sfx);
if (is_from_g2) if (source_sock >= 0)
printf("IP=[%s]:%u\n", fromDstar.GetAddress(), fromDstar.GetPort()); printf("IP=[%s]:%u\n", fromDstar.GetAddress(), fromDstar.GetPort());
else else
printf("UnixSock=%s\n", link2gate.c_str()); printf("UnixSock=%s\n", link2gate.c_str());
@ -1089,16 +1107,16 @@ void CQnetGateway::ProcessG2(const ssize_t g2buflen, const SDSVT &g2buf, const b
lastctrl = 20U; lastctrl = 20U;
/* save the header */ /* save the header */
if (! is_from_g2) { if (source_sock < 0) {
if (AF_INET == af_family) { //if (AF_INET == af_family) {
char address[16]; char address[16];
snprintf(address, 16, "%d.0.0.0", i); snprintf(address, 16, "%d.0.0.0", i);
fromDstar.Initialize(AF_INET, 40000U, address); fromDstar.Initialize(AF_INET, 40000U, address);
} else { //} else {
char address[8]; // char address[8];
snprintf(address, 8, "%d::", i); // snprintf(address, 8, "%d::", i);
fromDstar.Initialize(AF_INET6, 40000U, address); // fromDstar.Initialize(AF_INET6, 40000U, address);
} //}
} }
memcpy(toRptr[i].saved_hdr.title, g2buf.title, 56); memcpy(toRptr[i].saved_hdr.title, g2buf.title, 56);
toRptr[i].saved_addr = fromDstar; toRptr[i].saved_addr = fromDstar;
@ -1120,7 +1138,7 @@ void CQnetGateway::ProcessG2(const ssize_t g2buflen, const SDSVT &g2buf, const b
if (rptr.mod[i].defined) { if (rptr.mod[i].defined) {
/* streamid match ? */ /* streamid match ? */
bool match = (toRptr[i].streamid == g2buf.streamid); bool match = (toRptr[i].streamid == g2buf.streamid);
if (is_from_g2) if (source_sock >= 0)
match = match && (toRptr[i].addr == fromDstar); match = match && (toRptr[i].addr == fromDstar);
if (match) { if (match) {
if (LOG_DEBUG) { if (LOG_DEBUG) {
@ -1208,7 +1226,7 @@ void CQnetGateway::ProcessG2(const ssize_t g2buflen, const SDSVT &g2buf, const b
continue; continue;
/* match saved stream ? */ /* match saved stream ? */
bool match = (toRptr[i].saved_hdr.streamid == g2buf.streamid); bool match = (toRptr[i].saved_hdr.streamid == g2buf.streamid);
if (is_from_g2) if (source_sock >= 0)
match = match && (toRptr[i].saved_addr == fromDstar); match = match && (toRptr[i].saved_addr == fromDstar);
if (match) { if (match) {
/* repeater module is inactive ? */ /* repeater module is inactive ? */
@ -1242,6 +1260,7 @@ void CQnetGateway::ProcessG2(const ssize_t g2buflen, const SDSVT &g2buf, const b
void CQnetGateway::ProcessModem() void CQnetGateway::ProcessModem()
{ {
static int result = -1;
char temp_mod; char temp_mod;
char temp_radio_user[9]; char temp_radio_user[9];
char tempfile[FILENAME_MAX]; char tempfile[FILENAME_MAX];
@ -1253,7 +1272,6 @@ void CQnetGateway::ProcessModem()
if (0 == memcmp(dsvt.title, "DSVT", 4)) { if (0 == memcmp(dsvt.title, "DSVT", 4)) {
if ( (recvlen==56 || recvlen==27) && dsvt.id==0x20U && (dsvt.config==0x10U || dsvt.config==0x20U) ) { if ( (recvlen==56 || recvlen==27) && dsvt.id==0x20U && (dsvt.config==0x10U || dsvt.config==0x20U) ) {
if (recvlen == 56) { if (recvlen == 56) {
vPacketCount = 0U; vPacketCount = 0U;
if (LOG_QSO) if (LOG_QSO)
@ -1364,13 +1382,13 @@ void CQnetGateway::ProcessModem()
temp_radio_user[7] = 'A'; temp_radio_user[7] = 'A';
temp_radio_user[CALL_SIZE] = '\0'; temp_radio_user[CALL_SIZE] = '\0';
bool result = get_yrcall_rptr(temp_radio_user, arearp_cs, zonerp_cs, &temp_mod, ip, 'R'); result = get_yrcall_rptr(temp_radio_user, arearp_cs, zonerp_cs, &temp_mod, ip, 'R');
if (result) { /* it is a repeater */ if (result--) { /* it is a repeater */
std::string from = OWNER.substr(0, 7); std::string from = OWNER.substr(0, 7);
from.append(1, i+'A'); from.append(1, i+'A');
ii->sendPing(temp_radio_user, from); ii[result]->sendPing(temp_radio_user, from);
to_remote_g2[i].streamid = dsvt.streamid; to_remote_g2[i].streamid = dsvt.streamid;
to_remote_g2[i].toDstar.Initialize(af_family, (uint16_t)g2_external.port, ip.c_str()); to_remote_g2[i].toDstar.Initialize(af_family[result], (uint16_t)g2_external.port, ip.c_str());
/* set rpt1 */ /* set rpt1 */
memset(dsvt.hdr.rpt1, ' ', 8); memset(dsvt.hdr.rpt1, ' ', 8);
@ -1393,7 +1411,7 @@ void CQnetGateway::ProcessModem()
// send to remote gateway // send to remote gateway
for (int j=0; j<5; j++) for (int j=0; j<5; j++)
sendto(g2_sock, dsvt.title, 56, 0, to_remote_g2[i].toDstar.GetPointer(), to_remote_g2[i].toDstar.GetSize()); sendto(g2_sock[result], dsvt.title, 56, 0, to_remote_g2[i].toDstar.GetPointer(), to_remote_g2[i].toDstar.GetSize());
printf("id=%04x zone route to [%s]:%u ur=%.8s r1=%.8s r2=%.8s my=%.8s/%.4s\n", printf("id=%04x zone route to [%s]:%u ur=%.8s r1=%.8s r2=%.8s my=%.8s/%.4s\n",
ntohs(dsvt.streamid), to_remote_g2[i].toDstar.GetAddress(), to_remote_g2[i].toDstar.GetPort(), ntohs(dsvt.streamid), to_remote_g2[i].toDstar.GetAddress(), to_remote_g2[i].toDstar.GetPort(),
@ -1416,8 +1434,8 @@ void CQnetGateway::ProcessModem()
memset(temp_radio_user, ' ', 8); memset(temp_radio_user, ' ', 8);
memcpy(temp_radio_user, dsvt.hdr.urcall, 8); memcpy(temp_radio_user, dsvt.hdr.urcall, 8);
temp_radio_user[8] = '\0'; temp_radio_user[8] = '\0';
bool result = get_yrcall_rptr(temp_radio_user, arearp_cs, zonerp_cs, &temp_mod, ip, 'U'); result = get_yrcall_rptr(temp_radio_user, arearp_cs, zonerp_cs, &temp_mod, ip, 'U');
if (result) { if (result--) {
/* destination is a remote system */ /* destination is a remote system */
if (0 != zonerp_cs.compare(0, 7, OWNER, 0, 7)) { if (0 != zonerp_cs.compare(0, 7, OWNER, 0, 7)) {
int i = dsvt.hdr.rpt1[7] - 'A'; int i = dsvt.hdr.rpt1[7] - 'A';
@ -1428,9 +1446,9 @@ void CQnetGateway::ProcessModem()
/* set the destination */ /* set the destination */
std::string from = OWNER.substr(0, 7); std::string from = OWNER.substr(0, 7);
from.append(1, i+'A'); from.append(1, i+'A');
ii->sendPing(temp_radio_user, from); ii[result]->sendPing(temp_radio_user, from);
to_remote_g2[i].streamid = dsvt.streamid; to_remote_g2[i].streamid = dsvt.streamid;
to_remote_g2[i].toDstar.Initialize(af_family, (uint16_t)g2_external.port, ip.c_str()); to_remote_g2[i].toDstar.Initialize(af_family[result], (uint16_t)g2_external.port, ip.c_str());
/* set rpt1 */ /* set rpt1 */
memset(dsvt.hdr.rpt1, ' ', 8); memset(dsvt.hdr.rpt1, ' ', 8);
@ -1450,7 +1468,7 @@ void CQnetGateway::ProcessModem()
/* send to remote gateway */ /* send to remote gateway */
for (int j=0; j<5; j++) for (int j=0; j<5; j++)
sendto(g2_sock, dsvt.title, 56, 0, to_remote_g2[i].toDstar.GetPointer(), to_remote_g2[i].toDstar.GetSize()); sendto(g2_sock[result], dsvt.title, 56, 0, to_remote_g2[i].toDstar.GetPointer(), to_remote_g2[i].toDstar.GetSize());
printf("Callsign route to [%s]:%u id=%04x my=%.8s/%.4s ur=%.8s rpt1=%.8s rpt2=%.8s\n", to_remote_g2[i].toDstar.GetAddress(), to_remote_g2[i].toDstar.GetPort(), ntohs(dsvt.streamid), dsvt.hdr.mycall, dsvt.hdr.sfx, dsvt.hdr.urcall, dsvt.hdr.rpt1, dsvt.hdr.rpt2); printf("Callsign route to [%s]:%u id=%04x my=%.8s/%.4s ur=%.8s rpt1=%.8s rpt2=%.8s\n", to_remote_g2[i].toDstar.GetAddress(), to_remote_g2[i].toDstar.GetPort(), ntohs(dsvt.streamid), dsvt.hdr.mycall, dsvt.hdr.sfx, dsvt.hdr.urcall, dsvt.hdr.rpt1, dsvt.hdr.rpt2);
@ -1690,11 +1708,13 @@ void CQnetGateway::ProcessModem()
band_txt[i].dest_rptr[0] = '\0'; band_txt[i].dest_rptr[0] = '\0';
} }
// we have the 20-character message, send it to the server... // we have the 20-character message, send it to the server...
ii->sendHeardWithTXMsg(band_txt[i].lh_mycall, band_txt[i].lh_sfx, (strstr(band_txt[i].lh_yrcall,"REF") == NULL)?band_txt[i].lh_yrcall:"CQCQCQ ", band_txt[i].lh_rpt1, band_txt[i].lh_rpt2, band_txt[i].flags[0], band_txt[i].flags[1], band_txt[i].flags[2], band_txt[i].dest_rptr, band_txt[i].txt); if (result >= 0)
ii[result]->sendHeardWithTXMsg(band_txt[i].lh_mycall, band_txt[i].lh_sfx, (strstr(band_txt[i].lh_yrcall,"REF") == NULL)?band_txt[i].lh_yrcall:"CQCQCQ ", band_txt[i].lh_rpt1, band_txt[i].lh_rpt2, band_txt[i].flags[0], band_txt[i].flags[1], band_txt[i].flags[2], band_txt[i].dest_rptr, band_txt[i].txt);
band_txt[i].sent_key_on_msg = true; band_txt[i].sent_key_on_msg = true;
} }
// send the "key off" message, this will end up in the openquad.net Last Heard webpage. // send the "key off" message, this will end up in the openquad.net Last Heard webpage.
ii->sendHeardWithTXStats(band_txt[i].lh_mycall, band_txt[i].lh_sfx, band_txt[i].lh_yrcall, band_txt[i].lh_rpt1, band_txt[i].lh_rpt2, band_txt[i].flags[0], band_txt[i].flags[1], band_txt[i].flags[2], band_txt[i].num_dv_frames, band_txt[i].num_dv_silent_frames, band_txt[i].num_bit_errors); if (result >= 0)
ii[result]->sendHeardWithTXStats(band_txt[i].lh_mycall, band_txt[i].lh_sfx, band_txt[i].lh_yrcall, band_txt[i].lh_rpt1, band_txt[i].lh_rpt2, band_txt[i].flags[0], band_txt[i].flags[1], band_txt[i].flags[2], band_txt[i].num_dv_frames, band_txt[i].num_dv_silent_frames, band_txt[i].num_bit_errors);
if (playNotInCache) { if (playNotInCache) {
// Not in cache, please try again! // Not in cache, please try again!
@ -1770,14 +1790,14 @@ void CQnetGateway::ProcessModem()
for (int i=0; i<3; i++) { for (int i=0; i<3; i++) {
/* find out if data must go to the remote G2 */ /* find out if data must go to the remote G2 */
if (to_remote_g2[i].streamid == dsvt.streamid) { if (to_remote_g2[i].streamid==dsvt.streamid && result>=0) {
sendto(g2_sock, dsvt.title, 27, 0, to_remote_g2[i].toDstar.GetPointer(), to_remote_g2[i].toDstar.GetSize()); sendto(g2_sock[result], dsvt.title, 27, 0, to_remote_g2[i].toDstar.GetPointer(), to_remote_g2[i].toDstar.GetSize());
time(&(to_remote_g2[i].last_time)); time(&(to_remote_g2[i].last_time));
/* Is this the end-of-stream */ /* Is this the end-of-stream */
if (dsvt.ctrl & 0x40) { if (dsvt.ctrl & 0x40) {
to_remote_g2[i].toDstar.Initialize(af_family); to_remote_g2[i].toDstar.Initialize(AF_UNSPEC);
to_remote_g2[i].streamid = 0; to_remote_g2[i].streamid = 0;
to_remote_g2[i].last_time = 0; to_remote_g2[i].last_time = 0;
} }
@ -1833,7 +1853,7 @@ void CQnetGateway::ProcessModem()
if (dsvt.ctrl & 0x40) { if (dsvt.ctrl & 0x40) {
toRptr[i].last_time = 0; toRptr[i].last_time = 0;
toRptr[i].streamid = 0; toRptr[i].streamid = 0;
toRptr[i].addr.Initialize(af_family); toRptr[i].addr.Initialize(AF_UNSPEC);
} }
break; break;
} }
@ -1866,7 +1886,7 @@ void CQnetGateway::Process()
dstar_dv_init(); dstar_dv_init();
std::future<void> aprs_future, irc_data_future; std::future<void> aprs_future, irc_data_future[2];
if (APRS_ENABLE) { // start the beacon thread if (APRS_ENABLE) { // start the beacon thread
try { try {
aprs_future = std::async(std::launch::async, &CQnetGateway::APRSBeaconThread, this); aprs_future = std::async(std::launch::async, &CQnetGateway::APRSBeaconThread, this);
@ -1877,16 +1897,20 @@ void CQnetGateway::Process()
printf("APRS beacon thread started\n"); printf("APRS beacon thread started\n");
} }
try { // start the IRC read thread for (int i=0; i<2; i++) {
irc_data_future = std::async(std::launch::async, &CQnetGateway::GetIRCDataThread, this); if (ii[i]) {
} catch (const std::exception &e) { try { // start the IRC read thread
printf("Failed to start GetIRCDataThread. Exception: %s\n", e.what()); irc_data_future[i] = std::async(std::launch::async, &CQnetGateway::GetIRCDataThread, this, i);
keep_running = false; } catch (const std::exception &e) {
} printf("Failed to start GetIRCDataThread[%d]. Exception: %s\n", i, e.what());
if (keep_running) keep_running = false;
printf("get_irc_data thread started\n"); }
if (keep_running)
printf("get_irc_data thread[%d] started\n", i);
ii->kickWatchdog(IRCDDB_VERSION); ii[i]->kickWatchdog(IRCDDB_VERSION);
}
}
while (keep_running) { while (keep_running) {
ProcessTimeouts(); ProcessTimeouts();
@ -1895,7 +1919,10 @@ void CQnetGateway::Process()
int max_nfds = 0; int max_nfds = 0;
fd_set fdset; fd_set fdset;
FD_ZERO(&fdset); FD_ZERO(&fdset);
AddFDSet(max_nfds, g2_sock, &fdset); if (g2_sock[0] >= 0)
AddFDSet(max_nfds, g2_sock[0], &fdset);
if (g2_sock[1] >= 0)
AddFDSet(max_nfds, g2_sock[1], &fdset);
AddFDSet(max_nfds, Link2Gate.GetFD(), &fdset); AddFDSet(max_nfds, Link2Gate.GetFD(), &fdset);
AddFDSet(max_nfds, Modem2Gate.GetFD(), &fdset); AddFDSet(max_nfds, Modem2Gate.GetFD(), &fdset);
struct timeval tv; struct timeval tv;
@ -1904,15 +1931,19 @@ void CQnetGateway::Process()
(void)select(max_nfds + 1, &fdset, 0, 0, &tv); (void)select(max_nfds + 1, &fdset, 0, 0, &tv);
// process packets coming from remote G2 // process packets coming from remote G2
if (keep_running && FD_ISSET(g2_sock, &fdset)) { for (int i=0; i<2; i++) {
SDSVT dsvt; if (g2_sock[i] < 0)
socklen_t fromlen = sizeof(struct sockaddr_storage); continue;
ssize_t g2buflen = recvfrom(g2_sock, dsvt.title, 56, 0, fromDstar.GetPointer(), &fromlen); if (keep_running && FD_ISSET(g2_sock[i], &fdset)) {
if (LOG_QSO && 4==g2buflen && 0==memcmp(dsvt.title, "PONG", 4)) SDSVT dsvt;
printf("Got a pong from [%s]:%u\n", fromDstar.GetAddress(), fromDstar.GetPort()); socklen_t fromlen = sizeof(struct sockaddr_storage);
else ssize_t g2buflen = recvfrom(g2_sock[i], dsvt.title, 56, 0, fromDstar.GetPointer(), &fromlen);
ProcessG2(g2buflen, dsvt, true); if (LOG_QSO && 4==g2buflen && 0==memcmp(dsvt.title, "PONG", 4))
FD_CLR(g2_sock, &fdset); printf("Got a pong from [%s]:%u\n", fromDstar.GetAddress(), fromDstar.GetPort());
else
ProcessG2(g2buflen, dsvt, true);
FD_CLR(g2_sock[i], &fdset);
}
} }
// process packets from qnlink // process packets from qnlink
@ -1935,7 +1966,10 @@ void CQnetGateway::Process()
if (aprs_future.valid()) if (aprs_future.valid())
aprs_future.get(); aprs_future.get();
} }
irc_data_future.get(); for (int i=0; i<2; i++) {
if (ii[i])
irc_data_future[i].get();
}
return; return;
} }
@ -2285,10 +2319,14 @@ void CQnetGateway::qrgs_and_maps()
std::string rptrcall = OWNER; std::string rptrcall = OWNER;
rptrcall.resize(CALL_SIZE-1); rptrcall.resize(CALL_SIZE-1);
rptrcall += i + 'A'; rptrcall += i + 'A';
if (rptr.mod[i].latitude || rptr.mod[i].longitude || rptr.mod[i].desc1.length() || rptr.mod[i].url.length()) for (int j=0; j<2; j++) {
ii->rptrQTH(rptrcall, rptr.mod[i].latitude, rptr.mod[i].longitude, rptr.mod[i].desc1, rptr.mod[i].desc2, rptr.mod[i].url, rptr.mod[i].package_version); if (ii[j]) {
if (rptr.mod[i].frequency) if (rptr.mod[i].latitude || rptr.mod[i].longitude || rptr.mod[i].desc1.length() || rptr.mod[i].url.length())
ii->rptrQRG(rptrcall, rptr.mod[i].frequency, rptr.mod[i].offset, rptr.mod[i].range, rptr.mod[i].agl); ii[j]->rptrQTH(rptrcall, rptr.mod[i].latitude, rptr.mod[i].longitude, rptr.mod[i].desc1, rptr.mod[i].desc2, rptr.mod[i].url, rptr.mod[i].package_version);
if (rptr.mod[i].frequency)
ii[j]->rptrQRG(rptrcall, rptr.mod[i].frequency, rptr.mod[i].offset, rptr.mod[i].range, rptr.mod[i].agl);
}
}
} }
return; return;
@ -2396,52 +2434,70 @@ bool CQnetGateway::Init(char *cfgfile)
} }
compute_aprs_hash(); compute_aprs_hash();
ii = new CIRCDDB(ircddb.ip, ircddb.port, owner, IRCDDB_PASSWORD, IRCDDB_VERSION.c_str()); for (int j=0; j<2; j++) {
bool ok = ii->open(); if (ircddb[j].ip.empty())
if (!ok) { continue;
printf("irc open failed\n"); ii[j] = new CIRCDDB(ircddb[j].ip, ircddb[j].port, owner, IRCDDB_PASSWORD[j], IRCDDB_VERSION.c_str());
return true; bool ok = ii[j]->open();
} if (!ok) {
printf("%s open failed\n", ircddb[j].ip.c_str());
return true;
}
int rc = ii->getConnectionState(); int rc = ii[j]->getConnectionState();
printf("Waiting for irc connection status of 2\n"); printf("Waiting for %s connection status of 2\n", ircddb[j].ip.c_str());
i = 0; i = 0;
while (rc < 2) { while (rc < 2) {
printf("irc status=%d\n", rc); printf("%s status=%d\n", ircddb[j].ip.c_str(), rc);
if (rc < 2) { if (rc < 2) {
i++; i++;
sleep(5); sleep(5);
} else } else
break; break;
if (!keep_running) if (!keep_running)
break; break;
if (i > 5) { if (i > 5) {
printf("We can not wait any longer...\n"); printf("We can not wait any longer for %s...\n", ircddb[j].ip.c_str());
break; break;
}
rc = ii[j]->getConnectionState();
} }
rc = ii->getConnectionState(); switch (ii[j]->GetFamily()) {
}
switch (ii->GetFamily()) {
case AF_INET: case AF_INET:
printf("IRC server is using IPV4\n"); printf("IRC server is using IPV4\n");
af_family = AF_INET; af_family[j] = AF_INET;
break; break;
case AF_INET6: case AF_INET6:
printf("IRC server is using IPV6\n"); printf("IRC server is using IPV6\n");
af_family = AF_INET6; af_family[j] = AF_INET6;
break; break;
default: default:
printf("IRC server is using unknown protocol! Shutting down...\n"); printf("%s server is using unknown protocol! Shutting down...\n", ircddb[j].ip.c_str());
return true; return true;
}
} }
/* udp port 40000 must open first */
/* udp port 40000 must open first */ if (ii[0]) {
g2_sock = open_port(g2_external); g2_sock[0] = open_port(g2_external, af_family[0]);
if (0 > g2_sock) { if (0 > g2_sock[0]) {
printf("Can't open %s:%d\n", g2_external.ip.c_str(), g2_external.port); printf("Can't open %s:%d for %s\n", g2_external.ip.c_str(), g2_external.port, ircddb[i].ip.c_str());
return true; return true;
}
if (ii[1] && (af_family[0] != af_family[1])) { // we only need to open a second port if the family for the irc server is different!
g2_sock[1] = open_port(g2_external, af_family[1]);
if (0 > g2_sock[1]) {
printf("Can't open %s:%d for %s\n", g2_external.ip.c_str(), g2_external.port, ircddb[1].ip.c_str());
return true;
}
}
} else if (ii[1]) {
g2_sock[1] = open_port(g2_external, af_family[1]);
if (0 > g2_sock[1]) {
printf("Can't open %s:%d for %s\n", g2_external.ip.c_str(), g2_external.port, ircddb[1].ip.c_str());
return true;
}
} }
// Open unix sockets between qngateway and qnlink // Open unix sockets between qngateway and qnlink
@ -2476,10 +2532,10 @@ bool CQnetGateway::Init(char *cfgfile)
// the repeater modules run on these ports // the repeater modules run on these ports
memset(toRptr[i].saved_hdr.title, 0, 56); memset(toRptr[i].saved_hdr.title, 0, 56);
toRptr[i].saved_addr.Initialize(af_family); toRptr[i].saved_addr.Initialize(AF_UNSPEC);
toRptr[i].streamid = 0; toRptr[i].streamid = 0;
toRptr[i].addr.Initialize(af_family); toRptr[i].addr.Initialize(AF_UNSPEC);
toRptr[i].last_time = 0; toRptr[i].last_time = 0;
@ -2496,7 +2552,7 @@ bool CQnetGateway::Init(char *cfgfile)
/* to remote systems */ /* to remote systems */
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
to_remote_g2[i].toDstar.Initialize(af_family); to_remote_g2[i].toDstar.Initialize(AF_UNSPEC);
to_remote_g2[i].streamid = 0; to_remote_g2[i].streamid = 0;
to_remote_g2[i].last_time = 0; to_remote_g2[i].last_time = 0;
} }
@ -2510,7 +2566,7 @@ bool CQnetGateway::Init(char *cfgfile)
CQnetGateway::CQnetGateway() CQnetGateway::CQnetGateway()
{ {
ii = NULL; ii[0] = ii[1] = NULL;
} }
CQnetGateway::~CQnetGateway() CQnetGateway::~CQnetGateway()
@ -2518,11 +2574,6 @@ CQnetGateway::~CQnetGateway()
Link2Gate.Close(); Link2Gate.Close();
Modem2Gate.Close(); Modem2Gate.Close();
if (g2_sock != -1) {
close(g2_sock);
printf("Closed G2_EXTERNAL_PORT\n");
}
if (APRS_ENABLE) { if (APRS_ENABLE) {
if (aprs->aprs_sock.GetFD() != -1) { if (aprs->aprs_sock.GetFD() != -1) {
aprs->aprs_sock.Close(); aprs->aprs_sock.Close();
@ -2540,9 +2591,15 @@ CQnetGateway::~CQnetGateway()
} }
} }
if (ii) { for (int i=0; i<2; i++) {
ii->close(); if (g2_sock[i] >= 0) {
delete ii; close(g2_sock[i]);
printf("Closed G2_EXTERNAL_PORT %d\n", i);
}
if (ii[i]) {
ii[i]->close();
delete ii[i];
}
} }
printf("QnetGateway exiting\n"); printf("QnetGateway exiting\n");

@ -83,7 +83,7 @@ public:
private: private:
// network type // network type
int af_family; int af_family[2] = { AF_UNSPEC, AF_UNSPEC };
// text stuff // text stuff
bool new_group[3] = { true, true, true }; bool new_group[3] = { true, true, true };
unsigned char header_type = 0; unsigned char header_type = 0;
@ -91,14 +91,14 @@ private:
bool ABC_grp[3] = { false, false, false }; bool ABC_grp[3] = { false, false, false };
bool C_seen[3] = { false, false, false }; bool C_seen[3] = { false, false, false };
SPORTIP g2_external, ircddb; SPORTIP g2_external, ircddb[2];
CUnixDgramReader Link2Gate, Modem2Gate; CUnixDgramReader Link2Gate, Modem2Gate;
CUnixDgramWriter Gate2Link, Gate2Modem[3]; CUnixDgramWriter Gate2Link, Gate2Modem[3];
std::string gate2link, link2gate, gate2modem[3], modem2gate; std::string gate2link, link2gate, gate2modem[3], modem2gate;
std::string OWNER, owner, FILE_STATUS, FILE_DTMF, FILE_ECHOTEST, IRCDDB_PASSWORD, FILE_QNVOICE_FILE; std::string OWNER, owner, FILE_STATUS, FILE_DTMF, FILE_ECHOTEST, IRCDDB_PASSWORD[2], FILE_QNVOICE_FILE;
bool GATEWAY_SEND_QRGS_MAP, GATEWAY_HEADER_REGEN, APRS_ENABLE, playNotInCache; bool GATEWAY_SEND_QRGS_MAP, GATEWAY_HEADER_REGEN, APRS_ENABLE, playNotInCache;
bool LOG_DEBUG, LOG_IRC, LOG_DTMF, LOG_QSO; bool LOG_DEBUG, LOG_IRC, LOG_DTMF, LOG_QSO;
@ -122,7 +122,7 @@ private:
STOREMOTEG2 to_remote_g2[3]; // 0=A, 1=B, 2=C STOREMOTEG2 to_remote_g2[3]; // 0=A, 1=B, 2=C
// input from remote G2 gateway // input from remote G2 gateway
int g2_sock = -1; int g2_sock[2] = { -1, -1 };
CSockAddress fromDstar; CSockAddress fromDstar;
// Incoming data from remote systems // Incoming data from remote systems
@ -135,7 +135,7 @@ private:
struct sockaddr_in plug; struct sockaddr_in plug;
// for talking with the irc server // for talking with the irc server
CIRCDDB *ii; CIRCDDB *ii[2];
// for handling APRS stuff // for handling APRS stuff
CAPRS *aprs; CAPRS *aprs;
@ -148,9 +148,9 @@ private:
// CACHE used to cache users, repeaters, // CACHE used to cache users, repeaters,
// gateways, IP numbers coming from the irc server // gateways, IP numbers coming from the irc server
std::map<std::string, std::string> user2rptr_map, rptr2gwy_map, gwy2ip_map; std::map<std::string, std::string> user2rptr_map[2], rptr2gwy_map[2], gwy2ip_map[2];
pthread_mutex_t irc_data_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t irc_data_mutex[2] = PTHREAD_MUTEX_INITIALIZER;
// dtmf stuff // dtmf stuff
int dtmf_buf_count[3]; int dtmf_buf_count[3];
@ -160,17 +160,17 @@ private:
bool VoicePacketIsSync(const unsigned char *text); bool VoicePacketIsSync(const unsigned char *text);
void AddFDSet(int &max, int newfd, fd_set *set); void AddFDSet(int &max, int newfd, fd_set *set);
int open_port(const SPORTIP &pip); int open_port(const SPORTIP &pip, int family);
void calcPFCS(unsigned char *packet, int len); void calcPFCS(unsigned char *packet, int len);
void GetIRCDataThread(); void GetIRCDataThread(int i);
int get_yrcall_rptr_from_cache(const std::string &call, std::string &arearp_cs, std::string &zonerp_cs, char *mod, std::string &ip, char RoU); int get_yrcall_rptr_from_cache(const int i, const std::string &call, std::string &arearp_cs, std::string &zonerp_cs, char *mod, std::string &ip, char RoU);
bool get_yrcall_rptr(const std::string &call, std::string &arearp_cs, std::string &zonerp_cs, char *mod, std::string &ip, char RoU); int get_yrcall_rptr(const std::string &call, std::string &arearp_cs, std::string &zonerp_cs, char *mod, std::string &ip, char RoU);
void PlayFileThread(SECHO &edata); void PlayFileThread(SECHO &edata);
void compute_aprs_hash(); void compute_aprs_hash();
void APRSBeaconThread(); void APRSBeaconThread();
void ProcessTimeouts(); void ProcessTimeouts();
void ProcessSlowData(unsigned char *data, unsigned short sid); void ProcessSlowData(unsigned char *data, unsigned short sid);
void ProcessG2(const ssize_t g2buflen, const SDSVT &g2buf, const bool is_from_g2); void ProcessG2(const ssize_t g2buflen, const SDSVT &g2buf, const int sock_source);
void ProcessModem(); void ProcessModem();
bool Flag_is_ok(unsigned char flag); bool Flag_is_ok(unsigned char flag);
void UnpackCallsigns(const std::string &str, std::set<std::string> &set, const std::string &delimiters = ","); void UnpackCallsigns(const std::string &str, std::set<std::string> &set, const std::string &delimiters = ",");

@ -63,6 +63,8 @@ public:
inet_pton(AF_INET6, "::", &(addr6->sin6_addr)); inet_pton(AF_INET6, "::", &(addr6->sin6_addr));
else else
inet_pton(AF_INET6, address, &(addr6->sin6_addr)); inet_pton(AF_INET6, address, &(addr6->sin6_addr));
} else if (AF_UNSPEC == family) {
memset(&addr, 0, sizeof(struct sockaddr_storage));
} }
} }

@ -33,10 +33,13 @@
# #
# IRCDDB - You MUST use a legal callsign for logging into any IRC network # IRCDDB - You MUST use a legal callsign for logging into any IRC network
# #
#ircddb_login_d='' # login callsign for the ircDDB network #ircddb_login_d='' # login callsign for the ircDDB network
ircddb_host_d='rr.openquad.net' # other irc networks include group1-irc.ircddb.net ircddb0_host_d='rr.openquad.net' # other irc networks include group1-irc.ircddb.net
ircddb_port_d=9007 # not a good idea to change! ircddb0_port_d=9007 # not a good idea to change!
ircddb_password_d='1111111111111' # not needed for rr.openquad.net ircddb0_password_d='' # not needed for rr.openquad.net
ircddb1_host_d='' # second irc network
ircddb1_port_d=9007 # not a good idea to change!
ircddb1_password_d='' # not needed for rr.openquad.net
########################################################################################################################## ##########################################################################################################################
# #

@ -210,22 +210,35 @@ IrcddbMenu () {
echo echo
echo " IRCDDB Menu" echo " IRCDDB Menu"
echo echo
echo "Routes to other clients using IRC Server A will be searched first"
echo
echo "l : Login - must be a legal callsign = '${ircddb_login}'" echo "l : Login - must be a legal callsign = '${ircddb_login}'"
echo -n "h : Hostname for IRC Server = "; EvaluateVar ircddb_host{,_d} echo -n "ha : Hostname for IRC Server A = "; EvaluateVar ircddb0_host{,_d}
if [ -n "$em" ]; then
echo -n "oa : IRC TCP port A = "; EvaluateVar ircddb0_port{,_d}
echo -n "aa : IRC Password A = "; EvaluateVar ircddb0_password{,_d}
fi
echo -n "hb : Hostname for IRC Server B = "; EvaluateVar ircddb0_host{,_d}
if [ -n "$em" ]; then if [ -n "$em" ]; then
echo -n "po : IRC TCP port = "; EvaluateVar ircddb_port{,_d} echo -n "ob : IRC TCP port B = "; EvaluateVar ircddb0_port{,_d}
echo -n "pa : IRC Password = "; EvaluateVar ircddb_password{,_d} echo -n "ab : IRC Password B = "; EvaluateVar ircddb0_password{,_d}
fi fi
EndMenu EndMenu
if [[ "$key" == l* ]]; then ircddb_login="${value^^}" if [[ "$key" == l* ]]; then ircddb_login="${value^^}"
elif [[ "$key" == h* ]]; then ircddb_host="$value" elif [[ "$key" == ha* ]]; then ircddb0_host="$value"
elif [[ "$key" == po* ]]; then ircddb_port="$value" elif [[ "$key" == oa* ]]; then ircddb0_port="$value"
elif [[ "$key" == pa* ]]; then ircddb_password="$value" elif [[ "$key" == aa* ]]; then ircddb0_password="$value"
elif [[ "$key" == hb* ]]; then ircddb1_host="$value"
elif [[ "$key" == ob* ]]; then ircddb1_port="$value"
elif [[ "$key" == ab* ]]; then ircddb1_password="$value"
elif [[ "$key" == u* ]]; then elif [[ "$key" == u* ]]; then
if [[ "$value" == h* ]]; then unset ircddb_host if [[ "$value" == ha* ]]; then unset ircddb0_host
elif [[ "$value" == po* ]]; then unset ircddb_port elif [[ "$value" == oa* ]]; then unset ircddb0_port
elif [[ "$value" == pa* ]]; then unset ircddb_password elif [[ "$value" == aa* ]]; then unset ircddb0_password
elif [[ "$value" == hb* ]]; then unset ircddb1_host
elif [[ "$value" == ob* ]]; then unset ircddb1_port
elif [[ "$value" == ab* ]]; then unset ircddb1_password
fi fi
fi fi
done done
@ -499,11 +512,14 @@ WriteCFGFile () {
fi fi
outFile='./qn.cfg' outFile='./qn.cfg'
echo "# Created on `date`" > $outFile echo "# Created on `date`" > $outFile
# gateway_ section # ircddb_ section
echo "ircddb_login='$ircddb_login'" >> $outFile echo "ircddb_login='$ircddb_login'" >> $outFile
[ -z "${ircddb_host+x}" ] || echo "ircddb_host='${ircddb_host}'" >> $outFile [ -z "${ircddb0_host+x}" ] || echo "ircddb0_host='${ircddb0_host}'" >> $outFile
[ -z "${ircddb_port+x}" ] || echo "ircddb_host=${ircddb_port}" >> $outFile [ -z "${ircddb0_port+x}" ] || echo "ircddb0_host=${ircddb0_port}" >> $outFile
[ -z "${ircddb_password+x}" ] || echo "ircddb_password='${ircddb_password}'" >> $outFile [ -z "${ircddb0_password+x}" ] || echo "ircddb0_password='${ircddb0_password}'" >> $outFile
[ -z "${ircddb1_host+x}" ] || echo "ircddb1_host='${ircddb1_host}'" >> $outFile
[ -z "${ircddb1_port+x}" ] || echo "ircddb1_host=${ircddb1_port}" >> $outFile
[ -z "${ircddb1_password+x}" ] || echo "ircddb1_password='${ircddb1_password}'" >> $outFile
# module_?_ section # module_?_ section
for m in a b c for m in a b c
@ -653,7 +669,7 @@ while [[ "$ans" != q* ]]
do do
clear clear
echo echo
echo " Main Menu" echo " QnConfig Main Menu V#190424"
echo echo
echo -n "a : Module A - "; if [ -z $module_a ]; then echo "<EMPTY>"; else echo "${module_a^^}"; fi echo -n "a : Module A - "; if [ -z $module_a ]; then echo "<EMPTY>"; else echo "${module_a^^}"; fi
echo -n "b : Module B - "; if [ -z $module_b ]; then echo "<EMPTY>"; else echo "${module_b^^}"; fi echo -n "b : Module B - "; if [ -z $module_b ]; then echo "<EMPTY>"; else echo "${module_b^^}"; fi

Loading…
Cancel
Save

Powered by TurnKey Linux.