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());
OWNER.resize(CALL_SIZE, ' ');
if (cfg.GetValue(path+"host", estr, ircddb.ip, 3, MAXHOSTNAMELEN))
return true;
if (cfg.GetValue(path+"port", estr, ircddb.port, 1000, 65535))
return true;
if (cfg.GetValue(path+"password", estr, IRCDDB_PASSWORD, 0, 512))
for (int i=0; i<2; i++) {
std::string p(path + std::to_string(i) + "_");
if (cfg.KeyExists(p+"host")) {
cfg.GetValue(path+"host", estr, ircddb[i].ip, 3, MAXHOSTNAMELEN);
cfg.GetValue(path+"port", estr, ircddb[i].port, 1000, 65535);
cfg.GetValue(path+"password", estr, IRCDDB_PASSWORD[i], 0, 512);
}
}
if (0 == ircddb[0].ip.compare(ircddb[1].ip)) {
fprintf(stderr, "IRC networks must be different\n");
return true;
}
// module
for (int m=0; m<3; m++) {
@ -336,11 +340,11 @@ bool CQnetGateway::ReadConfig(char *cfgFile)
}
// 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) {
printf("Failed to create socket on %s:%d, errno=%d, %s\n", pip.ip.c_str(), pip.port, errno, strerror(errno));
return -1;
@ -363,7 +367,7 @@ int CQnetGateway::open_port(const SPORTIP &pip)
}
/* receive data from the irc server and save it */
void CQnetGateway::GetIRCDataThread()
void CQnetGateway::GetIRCDataThread(int i)
{
std::string user, rptr, gateway, ipaddr;
DSTAR_PROTOCOL proto;
@ -394,10 +398,10 @@ void CQnetGateway::GetIRCDataThread()
bool not_announced[3];
for (int i=0; i<3; i++)
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;
while (keep_running) {
int rc = ii->getConnectionState();
int rc = ii[i]->getConnectionState();
if (rc > 5 && rc < 8 && is_quadnet) {
char ch = '\0';
if (not_announced[0])
@ -425,7 +429,7 @@ void CQnetGateway::GetIRCDataThread()
for (auto it=findRoute.begin(); it!=findRoute.end(); it++) {
std::this_thread::sleep_for(std::chrono::milliseconds(800));
printf("\t'%s'\n", it->c_str());
ii->findUser(*it);
ii[i]->findUser(*it);
}
doFind = false;
}
@ -451,22 +455,22 @@ void CQnetGateway::GetIRCDataThread()
threshold = 0;
}
while (((type = ii->getMessageType()) != IDRT_NONE) && keep_running) {
while (((type = ii[i]->getMessageType()) != IDRT_NONE) && keep_running) {
switch (type) {
case IDRT_USER:
ii->receiveUser(user, rptr, gateway, ipaddr);
ii[i]->receiveUser(user, rptr, gateway, ipaddr);
if (!user.empty()) {
if (!rptr.empty() && !gateway.empty() && !ipaddr.empty()) {
if (LOG_IRC)
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;
rptr2gwy_map[rptr] = gateway;
gwy2ip_map[gateway] = ipaddr;
user2rptr_map[i][user] = rptr;
rptr2gwy_map[i][rptr] = gateway;
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());
@ -474,18 +478,18 @@ void CQnetGateway::GetIRCDataThread()
}
break;
case IDRT_REPEATER:
ii->receiveRepeater(rptr, gateway, ipaddr, proto);
ii[i]->receiveRepeater(rptr, gateway, ipaddr, proto);
if (!rptr.empty()) {
if (!gateway.empty() && !ipaddr.empty()) {
if (LOG_IRC)
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;
gwy2ip_map[gateway] = ipaddr;
rptr2gwy_map[i][rptr] = gateway;
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());
@ -493,34 +497,34 @@ void CQnetGateway::GetIRCDataThread()
}
break;
case IDRT_GATEWAY:
ii->receiveGateway(gateway, ipaddr, proto);
ii[i]->receiveGateway(gateway, ipaddr, proto);
if (!gateway.empty() && !ipaddr.empty()) {
if (LOG_IRC)
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());
}
break;
case IDRT_PING:
ii->receivePing(rptr);
ii[i]->receivePing(rptr);
ReplaceChar(rptr, '_', ' ');
if (! rptr.empty()) {
pthread_mutex_lock(&irc_data_mutex);
auto git = rptr2gwy_map.find(rptr);
if (rptr2gwy_map.end() != git) {
pthread_mutex_lock(&irc_data_mutex[i]);
auto git = rptr2gwy_map[i].find(rptr);
if (rptr2gwy_map[i].end() != git) {
gateway = git->second;
auto ait = gwy2ip_map.find(gateway);
if (gwy2ip_map.end() != ait) {
auto ait = gwy2ip_map[i].find(gateway);
if (gwy2ip_map[i].end() != ait) {
ipaddr = ait->second;
CSockAddress to(af_family, (unsigned short)g2_external.port, ipaddr.c_str());
sendto(g2_sock, "PONG", 4, 0, to.GetPointer(), to.GetSize());
CSockAddress to(af_family[i], (unsigned short)g2_external.port, ipaddr.c_str());
sendto(g2_sock[i], "PONG", 4, 0, to.GetPointer(), to.GetSize());
if (LOG_QSO)
printf("Sent 'PONG' to %s\n", ipaddr.c_str());
} else {
@ -529,7 +533,7 @@ void CQnetGateway::GetIRCDataThread()
} else {
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;
default:
@ -543,7 +547,7 @@ void CQnetGateway::GetIRCDataThread()
}
/* 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;
@ -553,8 +557,8 @@ int CQnetGateway::get_yrcall_rptr_from_cache(const std::string &call, std::strin
/* find the user in the CACHE */
if (RoU == 'U') {
auto user_pos = user2rptr_map.find(call);
if (user_pos != user2rptr_map.end()) {
auto user_pos = user2rptr_map[i].find(call);
if (user_pos != user2rptr_map[i].end()) {
arearp_cs = user_pos->second.substr(0, 7);
*mod = user_pos->second.at(7);
} else {
@ -578,12 +582,12 @@ int CQnetGateway::get_yrcall_rptr_from_cache(const std::string &call, std::strin
temp.append(1, *mod);
arearp_cs.resize(8, ' ');
auto rptr_pos = rptr2gwy_map.find(temp);
if (rptr_pos != rptr2gwy_map.end()) {
auto rptr_pos = rptr2gwy_map[i].find(temp);
if (rptr_pos != rptr2gwy_map[i].end()) {
zonerp_cs.assign(rptr_pos->second);
auto gwy_pos = gwy2ip_map.find(zonerp_cs);
if (gwy_pos != gwy2ip_map.end()) {
auto gwy_pos = gwy2ip_map[i].find(zonerp_cs);
if (gwy_pos != gwy2ip_map[i].end()) {
ip.assign(gwy_pos->second);
return 0;
} else {
@ -596,26 +600,33 @@ 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);
int rc = get_yrcall_rptr_from_cache(call, arearp_cs, zonerp_cs, mod, ip, RoU);
pthread_mutex_unlock(&irc_data_mutex);
for (int i=0; i<2; i++) {
if (NULL == ii[i])
continue;
int rc;
if (ii[i]) {
pthread_mutex_lock(&irc_data_mutex[i]);
rc = get_yrcall_rptr_from_cache(i, call, arearp_cs, zonerp_cs, mod, ip, RoU);
pthread_mutex_unlock(&irc_data_mutex[i]);
}
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);
return true;
return i+1;
} 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->getConnectionState();
int status = ii[i]->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;
}
if (7 == status) {
/* request data from irc server */
if (RoU == 'U') {
printf("User [%s] not in local cache, try again\n", call.c_str());
@ -623,19 +634,21 @@ bool CQnetGateway::get_yrcall_rptr(const std::string &call, std::string &arearp_
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)) {
if (!ii[i]->findUser(call)) {
printf("findUser(%s): Network error\n", call.c_str());
return false;
return 0;
}
} else if (RoU == 'R') {
printf("Repeater [%s] not in local cache, try again\n", call.c_str());
if (!ii->findRepeater(call)) {
if (!ii[i]->findRepeater(call)) {
printf("findRepeater(%s): Network error\n", call.c_str());
return false;
return 0;
}
}
}
}
return false;
return 0;
}
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) {
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].last_time = 0;
}
@ -906,7 +919,10 @@ void CQnetGateway::ProcessSlowData(unsigned char *data, unsigned short sid)
band_txt[i].dest_rptr[0] = '\0';
}
// 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;
}
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';
}
// 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].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)
// is_from_g2==true means it's coming from external port 40000
// is_from_g2==false means it's coming from the link2gate Unix socket
void CQnetGateway::ProcessG2(const ssize_t g2buflen, const SDSVT &g2buf, const int source_sock)
// source_sock is the socket number of the incoming data, or -1 if it's a unix socket
{
static unsigned char lastctrl = 20U;
static std::string superframe[3];
@ -1079,7 +1097,7 @@ void CQnetGateway::ProcessG2(const ssize_t g2buflen, const SDSVT &g2buf, const b
superframe[i].clear();
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);
if (is_from_g2)
if (source_sock >= 0)
printf("IP=[%s]:%u\n", fromDstar.GetAddress(), fromDstar.GetPort());
else
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;
/* save the header */
if (! is_from_g2) {
if (AF_INET == af_family) {
if (source_sock < 0) {
//if (AF_INET == af_family) {
char address[16];
snprintf(address, 16, "%d.0.0.0", i);
fromDstar.Initialize(AF_INET, 40000U, address);
} else {
char address[8];
snprintf(address, 8, "%d::", i);
fromDstar.Initialize(AF_INET6, 40000U, address);
}
//} else {
// char address[8];
// snprintf(address, 8, "%d::", i);
// fromDstar.Initialize(AF_INET6, 40000U, address);
//}
}
memcpy(toRptr[i].saved_hdr.title, g2buf.title, 56);
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) {
/* streamid match ? */
bool match = (toRptr[i].streamid == g2buf.streamid);
if (is_from_g2)
if (source_sock >= 0)
match = match && (toRptr[i].addr == fromDstar);
if (match) {
if (LOG_DEBUG) {
@ -1208,7 +1226,7 @@ void CQnetGateway::ProcessG2(const ssize_t g2buflen, const SDSVT &g2buf, const b
continue;
/* match saved stream ? */
bool match = (toRptr[i].saved_hdr.streamid == g2buf.streamid);
if (is_from_g2)
if (source_sock >= 0)
match = match && (toRptr[i].saved_addr == fromDstar);
if (match) {
/* repeater module is inactive ? */
@ -1242,6 +1260,7 @@ void CQnetGateway::ProcessG2(const ssize_t g2buflen, const SDSVT &g2buf, const b
void CQnetGateway::ProcessModem()
{
static int result = -1;
char temp_mod;
char temp_radio_user[9];
char tempfile[FILENAME_MAX];
@ -1253,7 +1272,6 @@ void CQnetGateway::ProcessModem()
if (0 == memcmp(dsvt.title, "DSVT", 4)) {
if ( (recvlen==56 || recvlen==27) && dsvt.id==0x20U && (dsvt.config==0x10U || dsvt.config==0x20U) ) {
if (recvlen == 56) {
vPacketCount = 0U;
if (LOG_QSO)
@ -1364,13 +1382,13 @@ void CQnetGateway::ProcessModem()
temp_radio_user[7] = 'A';
temp_radio_user[CALL_SIZE] = '\0';
bool result = get_yrcall_rptr(temp_radio_user, arearp_cs, zonerp_cs, &temp_mod, ip, 'R');
if (result) { /* it is a repeater */
result = get_yrcall_rptr(temp_radio_user, arearp_cs, zonerp_cs, &temp_mod, ip, 'R');
if (result--) { /* it is a repeater */
std::string from = OWNER.substr(0, 7);
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].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 */
memset(dsvt.hdr.rpt1, ' ', 8);
@ -1393,7 +1411,7 @@ void CQnetGateway::ProcessModem()
// send to remote gateway
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",
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);
memcpy(temp_radio_user, dsvt.hdr.urcall, 8);
temp_radio_user[8] = '\0';
bool result = get_yrcall_rptr(temp_radio_user, arearp_cs, zonerp_cs, &temp_mod, ip, 'U');
if (result) {
result = get_yrcall_rptr(temp_radio_user, arearp_cs, zonerp_cs, &temp_mod, ip, 'U');
if (result--) {
/* destination is a remote system */
if (0 != zonerp_cs.compare(0, 7, OWNER, 0, 7)) {
int i = dsvt.hdr.rpt1[7] - 'A';
@ -1428,9 +1446,9 @@ void CQnetGateway::ProcessModem()
/* set the destination */
std::string from = OWNER.substr(0, 7);
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].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 */
memset(dsvt.hdr.rpt1, ' ', 8);
@ -1450,7 +1468,7 @@ void CQnetGateway::ProcessModem()
/* send to remote gateway */
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);
@ -1690,11 +1708,13 @@ void CQnetGateway::ProcessModem()
band_txt[i].dest_rptr[0] = '\0';
}
// 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;
}
// 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) {
// Not in cache, please try again!
@ -1770,14 +1790,14 @@ void CQnetGateway::ProcessModem()
for (int i=0; i<3; i++) {
/* find out if data must go to the remote G2 */
if (to_remote_g2[i].streamid == dsvt.streamid) {
sendto(g2_sock, dsvt.title, 27, 0, to_remote_g2[i].toDstar.GetPointer(), to_remote_g2[i].toDstar.GetSize());
if (to_remote_g2[i].streamid==dsvt.streamid && result>=0) {
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));
/* Is this the end-of-stream */
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].last_time = 0;
}
@ -1833,7 +1853,7 @@ void CQnetGateway::ProcessModem()
if (dsvt.ctrl & 0x40) {
toRptr[i].last_time = 0;
toRptr[i].streamid = 0;
toRptr[i].addr.Initialize(af_family);
toRptr[i].addr.Initialize(AF_UNSPEC);
}
break;
}
@ -1866,7 +1886,7 @@ void CQnetGateway::Process()
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
try {
aprs_future = std::async(std::launch::async, &CQnetGateway::APRSBeaconThread, this);
@ -1877,16 +1897,20 @@ void CQnetGateway::Process()
printf("APRS beacon thread started\n");
}
for (int i=0; i<2; i++) {
if (ii[i]) {
try { // start the IRC read thread
irc_data_future = std::async(std::launch::async, &CQnetGateway::GetIRCDataThread, this);
irc_data_future[i] = std::async(std::launch::async, &CQnetGateway::GetIRCDataThread, this, i);
} catch (const std::exception &e) {
printf("Failed to start GetIRCDataThread. Exception: %s\n", e.what());
printf("Failed to start GetIRCDataThread[%d]. Exception: %s\n", i, e.what());
keep_running = false;
}
if (keep_running)
printf("get_irc_data thread started\n");
printf("get_irc_data thread[%d] started\n", i);
ii->kickWatchdog(IRCDDB_VERSION);
ii[i]->kickWatchdog(IRCDDB_VERSION);
}
}
while (keep_running) {
ProcessTimeouts();
@ -1895,7 +1919,10 @@ void CQnetGateway::Process()
int max_nfds = 0;
fd_set 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, Modem2Gate.GetFD(), &fdset);
struct timeval tv;
@ -1904,15 +1931,19 @@ void CQnetGateway::Process()
(void)select(max_nfds + 1, &fdset, 0, 0, &tv);
// process packets coming from remote G2
if (keep_running && FD_ISSET(g2_sock, &fdset)) {
for (int i=0; i<2; i++) {
if (g2_sock[i] < 0)
continue;
if (keep_running && FD_ISSET(g2_sock[i], &fdset)) {
SDSVT dsvt;
socklen_t fromlen = sizeof(struct sockaddr_storage);
ssize_t g2buflen = recvfrom(g2_sock, dsvt.title, 56, 0, fromDstar.GetPointer(), &fromlen);
ssize_t g2buflen = recvfrom(g2_sock[i], dsvt.title, 56, 0, fromDstar.GetPointer(), &fromlen);
if (LOG_QSO && 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);
FD_CLR(g2_sock[i], &fdset);
}
}
// process packets from qnlink
@ -1935,7 +1966,10 @@ void CQnetGateway::Process()
if (aprs_future.valid())
aprs_future.get();
}
irc_data_future.get();
for (int i=0; i<2; i++) {
if (ii[i])
irc_data_future[i].get();
}
return;
}
@ -2285,10 +2319,14 @@ void CQnetGateway::qrgs_and_maps()
std::string rptrcall = OWNER;
rptrcall.resize(CALL_SIZE-1);
rptrcall += i + 'A';
for (int j=0; j<2; j++) {
if (ii[j]) {
if (rptr.mod[i].latitude || rptr.mod[i].longitude || rptr.mod[i].desc1.length() || rptr.mod[i].url.length())
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);
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->rptrQRG(rptrcall, rptr.mod[i].frequency, rptr.mod[i].offset, rptr.mod[i].range, rptr.mod[i].agl);
ii[j]->rptrQRG(rptrcall, rptr.mod[i].frequency, rptr.mod[i].offset, rptr.mod[i].range, rptr.mod[i].agl);
}
}
}
return;
@ -2396,18 +2434,21 @@ bool CQnetGateway::Init(char *cfgfile)
}
compute_aprs_hash();
ii = new CIRCDDB(ircddb.ip, ircddb.port, owner, IRCDDB_PASSWORD, IRCDDB_VERSION.c_str());
bool ok = ii->open();
for (int j=0; j<2; j++) {
if (ircddb[j].ip.empty())
continue;
ii[j] = new CIRCDDB(ircddb[j].ip, ircddb[j].port, owner, IRCDDB_PASSWORD[j], IRCDDB_VERSION.c_str());
bool ok = ii[j]->open();
if (!ok) {
printf("irc open failed\n");
printf("%s open failed\n", ircddb[j].ip.c_str());
return true;
}
int rc = ii->getConnectionState();
printf("Waiting for irc connection status of 2\n");
int rc = ii[j]->getConnectionState();
printf("Waiting for %s connection status of 2\n", ircddb[j].ip.c_str());
i = 0;
while (rc < 2) {
printf("irc status=%d\n", rc);
printf("%s status=%d\n", ircddb[j].ip.c_str(), rc);
if (rc < 2) {
i++;
sleep(5);
@ -2418,31 +2459,46 @@ bool CQnetGateway::Init(char *cfgfile)
break;
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;
}
rc = ii->getConnectionState();
rc = ii[j]->getConnectionState();
}
switch (ii->GetFamily()) {
switch (ii[j]->GetFamily()) {
case AF_INET:
printf("IRC server is using IPV4\n");
af_family = AF_INET;
af_family[j] = AF_INET;
break;
case AF_INET6:
printf("IRC server is using IPV6\n");
af_family = AF_INET6;
af_family[j] = AF_INET6;
break;
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;
}
}
/* udp port 40000 must open first */
g2_sock = open_port(g2_external);
if (0 > g2_sock) {
printf("Can't open %s:%d\n", g2_external.ip.c_str(), g2_external.port);
if (ii[0]) {
g2_sock[0] = open_port(g2_external, af_family[0]);
if (0 > g2_sock[0]) {
printf("Can't open %s:%d for %s\n", g2_external.ip.c_str(), g2_external.port, ircddb[i].ip.c_str());
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
Gate2Link.SetUp(gate2link.c_str());
@ -2476,10 +2532,10 @@ bool CQnetGateway::Init(char *cfgfile)
// the repeater modules run on these ports
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].addr.Initialize(af_family);
toRptr[i].addr.Initialize(AF_UNSPEC);
toRptr[i].last_time = 0;
@ -2496,7 +2552,7 @@ bool CQnetGateway::Init(char *cfgfile)
/* to remote systems */
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].last_time = 0;
}
@ -2510,7 +2566,7 @@ bool CQnetGateway::Init(char *cfgfile)
CQnetGateway::CQnetGateway()
{
ii = NULL;
ii[0] = ii[1] = NULL;
}
CQnetGateway::~CQnetGateway()
@ -2518,11 +2574,6 @@ CQnetGateway::~CQnetGateway()
Link2Gate.Close();
Modem2Gate.Close();
if (g2_sock != -1) {
close(g2_sock);
printf("Closed G2_EXTERNAL_PORT\n");
}
if (APRS_ENABLE) {
if (aprs->aprs_sock.GetFD() != -1) {
aprs->aprs_sock.Close();
@ -2540,9 +2591,15 @@ CQnetGateway::~CQnetGateway()
}
}
if (ii) {
ii->close();
delete ii;
for (int i=0; i<2; i++) {
if (g2_sock[i] >= 0) {
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");

@ -83,7 +83,7 @@ public:
private:
// network type
int af_family;
int af_family[2] = { AF_UNSPEC, AF_UNSPEC };
// text stuff
bool new_group[3] = { true, true, true };
unsigned char header_type = 0;
@ -91,14 +91,14 @@ private:
bool ABC_grp[3] = { false, false, false };
bool C_seen[3] = { false, false, false };
SPORTIP g2_external, ircddb;
SPORTIP g2_external, ircddb[2];
CUnixDgramReader Link2Gate, Modem2Gate;
CUnixDgramWriter Gate2Link, Gate2Modem[3];
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 LOG_DEBUG, LOG_IRC, LOG_DTMF, LOG_QSO;
@ -122,7 +122,7 @@ private:
STOREMOTEG2 to_remote_g2[3]; // 0=A, 1=B, 2=C
// input from remote G2 gateway
int g2_sock = -1;
int g2_sock[2] = { -1, -1 };
CSockAddress fromDstar;
// Incoming data from remote systems
@ -135,7 +135,7 @@ private:
struct sockaddr_in plug;
// for talking with the irc server
CIRCDDB *ii;
CIRCDDB *ii[2];
// for handling APRS stuff
CAPRS *aprs;
@ -148,9 +148,9 @@ private:
// CACHE used to cache users, repeaters,
// 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
int dtmf_buf_count[3];
@ -160,17 +160,17 @@ private:
bool VoicePacketIsSync(const unsigned char *text);
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 GetIRCDataThread();
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);
bool get_yrcall_rptr(const std::string &call, std::string &arearp_cs, std::string &zonerp_cs, char *mod, std::string &ip, char RoU);
void GetIRCDataThread(int i);
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);
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 compute_aprs_hash();
void APRSBeaconThread();
void ProcessTimeouts();
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();
bool Flag_is_ok(unsigned char flag);
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));
else
inet_pton(AF_INET6, address, &(addr6->sin6_addr));
} else if (AF_UNSPEC == family) {
memset(&addr, 0, sizeof(struct sockaddr_storage));
}
}

@ -34,9 +34,12 @@
# IRCDDB - You MUST use a legal callsign for logging into any IRC network
#
#ircddb_login_d='' # login callsign for the ircDDB network
ircddb_host_d='rr.openquad.net' # other irc networks include group1-irc.ircddb.net
ircddb_port_d=9007 # not a good idea to change!
ircddb_password_d='1111111111111' # not needed for rr.openquad.net
ircddb0_host_d='rr.openquad.net' # other irc networks include group1-irc.ircddb.net
ircddb0_port_d=9007 # not a good idea to change!
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 " IRCDDB Menu"
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 -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
echo -n "po : IRC TCP port = "; EvaluateVar ircddb_port{,_d}
echo -n "pa : IRC Password = "; EvaluateVar ircddb_password{,_d}
echo -n "ob : IRC TCP port B = "; EvaluateVar ircddb0_port{,_d}
echo -n "ab : IRC Password B = "; EvaluateVar ircddb0_password{,_d}
fi
EndMenu
if [[ "$key" == l* ]]; then ircddb_login="${value^^}"
elif [[ "$key" == h* ]]; then ircddb_host="$value"
elif [[ "$key" == po* ]]; then ircddb_port="$value"
elif [[ "$key" == pa* ]]; then ircddb_password="$value"
elif [[ "$key" == ha* ]]; then ircddb0_host="$value"
elif [[ "$key" == oa* ]]; then ircddb0_port="$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
if [[ "$value" == h* ]]; then unset ircddb_host
elif [[ "$value" == po* ]]; then unset ircddb_port
elif [[ "$value" == pa* ]]; then unset ircddb_password
if [[ "$value" == ha* ]]; then unset ircddb0_host
elif [[ "$value" == oa* ]]; then unset ircddb0_port
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
done
@ -499,11 +512,14 @@ WriteCFGFile () {
fi
outFile='./qn.cfg'
echo "# Created on `date`" > $outFile
# gateway_ section
# ircddb_ section
echo "ircddb_login='$ircddb_login'" >> $outFile
[ -z "${ircddb_host+x}" ] || echo "ircddb_host='${ircddb_host}'" >> $outFile
[ -z "${ircddb_port+x}" ] || echo "ircddb_host=${ircddb_port}" >> $outFile
[ -z "${ircddb_password+x}" ] || echo "ircddb_password='${ircddb_password}'" >> $outFile
[ -z "${ircddb0_host+x}" ] || echo "ircddb0_host='${ircddb0_host}'" >> $outFile
[ -z "${ircddb0_port+x}" ] || echo "ircddb0_host=${ircddb0_port}" >> $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
for m in a b c
@ -653,7 +669,7 @@ while [[ "$ans" != q* ]]
do
clear
echo
echo " Main Menu"
echo " QnConfig Main Menu V#190424"
echo
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

Loading…
Cancel
Save

Powered by TurnKey Linux.