From 93c66029cefea8edd781abd507197e178fe58e27 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Tue, 3 Dec 2024 09:05:49 -0700 Subject: [PATCH 01/11] fixed dashboard install problems --- DASHBOARD.README | 18 ++++++++++++++---- Makefile | 14 ++++---------- README.md | 11 ++++++++--- dashboardV2/jsonData/README | 1 + 4 files changed, 27 insertions(+), 17 deletions(-) create mode 100644 dashboardV2/jsonData/README diff --git a/DASHBOARD.README b/DASHBOARD.README index 7dc32b7..b4730c6 100644 --- a/DASHBOARD.README +++ b/DASHBOARD.README @@ -1,5 +1,15 @@ ##### DASHBOARD.README ##### +-------------------------------------------------------------------------- + IMPORTANT! +This document describes how to install a dashboard server based on a php +mini-server and should not be used to publish a QnetGateway dashboard on +the world-wide-web. This mini-server for operating behind a firewall on +a local network. If you need your QnetGateway dashboard on the WWW, install +a real web server, like apache2. The mini-server described here is not +suitable for the WWW! +-------------------------------------------------------------------------- + A web-based dashboard can be enabled. The dashboard has several sections that you can display in any order. You can also control the refresh rate and how many rows you want in the Last Heard section. You can configure these @@ -13,6 +23,10 @@ cp system/qndash.service.80 system/qndash.service and edit your new file *before* installing the dashboard. +You also need several php libraries: + +sudo apt install -y php-common php-fpm sqlite3 php-sqlite3 dnsutils + To install the dashboard system, run the following command: sudo make installdash @@ -53,7 +67,3 @@ The responsive dashboard currently has the following features hidden, however, simply rotate your mobile device to landscape view and they should appear * QnRemote section (aka URCall section) has improved design for mobile device use - -Future improvements will be made to - * The layout to respect order of the dash_show_order configuration item - * Misc performance enhancements diff --git a/Makefile b/Makefile index 0da5bd5..cb2fcdb 100644 --- a/Makefile +++ b/Makefile @@ -99,8 +99,6 @@ installbase : $(BASE_PROGRAMS) gwys.txt qn.cfg /bin/cp -f qngateway $(BINDIR) /bin/cp -f qnremote qnvoice $(BINDIR) /bin/ln -f -s $(shell pwd)/qn.cfg $(CFGDIR) - /bin/ln -f -s $(shell pwd)/index.php $(WWWDIR) - /bin/ln -f -s $(shell pwd)/dashboardV2 $(WWWDIR) /bin/cp -f defaults $(CFGDIR) /bin/cp -f system/qngateway.service $(SYSDIR) systemctl enable qngateway.service @@ -205,11 +203,9 @@ installdtmf : qndtmf installdash : index.php /usr/bin/apt update - /usr/bin/apt install -y php-common php-fpm sqlite3 php-sqlite3 dnsutils mkdir -p $(WWWDIR) - mkdir -p dashboardV2/jsonData - /bin/ln -f -s $(shell pwd)/index.php $(WWWDIR) - /bin/ln -f -s $(shell pwd)/dashboardV2 $(WWWDIR) + /bin/rm -f $(WWWDIR)/* + /bin/ln -f -s $(shell pwd)/index.php $(shell pwd)/dashboardV2 $(WWWDIR) if [ ! -e system/qndash.service ]; then cp system/qndash.service.80 system/qndash.service; fi /bin/cp -f system/qndash.service $(SYSDIR) systemctl enable qndash.service @@ -328,7 +324,5 @@ uninstalldash : systemctl disable qndash.service /bin/rm -f $(SYSDIR)/qndash.service systemctl daemon-reload - /bin/rm -f $(WWWDIR)/index.php - /bin/rm -f $(WWWDIR)/dashboardV2 - /bin/rm -f $(CFGDIR)/qn.db - /bin/rm -rf dashboardV2/jsonData + /bin/rm -f $(WWWDIR)/* + /bin/rm -f dashboardV2/jsonData/*.json diff --git a/README.md b/README.md index cb1256a..0d6d056 100644 --- a/README.md +++ b/README.md @@ -3,12 +3,19 @@ QnetGateway The QnetGateway is an D-Star IRCDDB gateway application that supports MMDVMHost (and all of its supported repeater modems) as well as the DVAP Dongle, the DVRPTR_V1. It is *incredibly easy* to build and install the system. -QnetGateway now includes a dashboard with a last heard section. The lastheard section uses SQLite3, a light-weight database, so you will need a package to compile the gateway: +QnetGateway includes a dashboard with a last heard section. The lastheard section uses SQLite3, a light-weight database, so you will need a package to compile the gateway: ```bash sudo apt install libsqlite3-dev ``` +If you are going to install the dashboard, you need several libraries for php: + +```bash +sudo apt install -y php-common php-fpm sqlite3 php-sqlite3 dnsutils + +Be sure to read the DASHBOARD.README for more information. + QnetGateway is dual-stack capable. This means it can simultaneously connect to ircv4.openquad.net, which is IPv4 based (using 32-bit internet addresses) and to ircv6.openquad.net which is IPv6 based (using 128-bit internet address). If your hot-spot/reapeater has IPv6 access you can enable dual-stack operation (it's IPv4-only by default) and then take advantage of direct world-routable address. The potential benefit of IPv6 to routing is significant. The QnetGateway program includes support for Icom's Terminal Mode and Access Point mode. For more information, Terminal Mode turns off the RF portion of you radio and just uses the AMBE vocoder to convert between audio and AMBE data and then sends and receives that data through a USB serial cable. Access Point mode turns your Icom radio into a high power, simplex hot-spot. @@ -39,8 +46,6 @@ QnetGateway is free software; you can redistribute it and/or modify it under the Many thanks go to **Colby W1BSB**, **Will W4WWM** and **Carty KA2Y** for recent help, suggestions, discussion and criticisms of the Qnet*/MMDVMHost phase of this long-term project! Also thanks to Jonathan G4KLX for MMDVMHost. It gave QnetGateway access to a large number of D-Star compatible modems! -Finally, QnetGateway is brought to you by the folks at **QuadNet2 USA IRC Network**, but it should work on *any* IRCDDB network. - 73 Tom diff --git a/dashboardV2/jsonData/README b/dashboardV2/jsonData/README new file mode 100644 index 0000000..9731ecc --- /dev/null +++ b/dashboardV2/jsonData/README @@ -0,0 +1 @@ +This folder is for temporary data used by dashboardV2 From 2e3f3608ad1b76ed5b406dfdc2996d625ec3d5c0 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Tue, 3 Dec 2024 09:28:58 -0700 Subject: [PATCH 02/11] dcs link qndb bug --- Makefile | 1 - QnetLink.cpp | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Makefile b/Makefile index cb2fcdb..f125a77 100644 --- a/Makefile +++ b/Makefile @@ -202,7 +202,6 @@ installdtmf : qndtmf systemctl start qndtmf.service installdash : index.php - /usr/bin/apt update mkdir -p $(WWWDIR) /bin/rm -f $(WWWDIR)/* /bin/ln -f -s $(shell pwd)/index.php $(shell pwd)/dashboardV2 $(WWWDIR) diff --git a/QnetLink.cpp b/QnetLink.cpp index b12a935..b85ad3e 100644 --- a/QnetLink.cpp +++ b/QnetLink.cpp @@ -1831,7 +1831,7 @@ void CQnetLink::ProcessDCS(unsigned char *dcs_buf, const int length) to_remote_g2[i].is_connected = true; printf("Connected from: %.*s\n", 8, to_remote_g2[i].cs); - qnDB.UpdateLS(to_remote_g2[i].addr.GetAddress(), to_remote_g2[i].from_mod, to_remote_g2[i].cs, to_remote_g2[i].from_mod, tracing[i].last_time); + qnDB.UpdateLS(to_remote_g2[i].addr.GetAddress(), to_remote_g2[i].from_mod, to_remote_g2[i].cs, to_remote_g2[i].to_mod, tracing[i].last_time); char linked_remote_system[CALL_SIZE + 1]; strcpy(linked_remote_system, to_remote_g2[i].cs); From 01df29d053f927bcd7b4239417cc0e2b55542ca9 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Tue, 3 Dec 2024 09:58:35 -0700 Subject: [PATCH 03/11] bumped qnlink version --- QnetLink.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QnetLink.cpp b/QnetLink.cpp index b85ad3e..613c652 100644 --- a/QnetLink.cpp +++ b/QnetLink.cpp @@ -54,7 +54,7 @@ #include "QnetLink.h" #include "Utilities.h" -#define LINK_VERSION "QnetLink-40411" +#define LINK_VERSION "QnetLink-41203" CQnetLink::CQnetLink() : CBase() { From d363e3ce80f9a364491104463e30e9a99606a9df Mon Sep 17 00:00:00 2001 From: Tom Early Date: Tue, 14 Jan 2025 06:36:34 -0700 Subject: [PATCH 04/11] README --- README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 0d6d056..280666e 100644 --- a/README.md +++ b/README.md @@ -5,14 +5,15 @@ The QnetGateway is an D-Star IRCDDB gateway application that supports MMDVMHost QnetGateway includes a dashboard with a last heard section. The lastheard section uses SQLite3, a light-weight database, so you will need a package to compile the gateway: -```bash +``` sudo apt install libsqlite3-dev ``` If you are going to install the dashboard, you need several libraries for php: -```bash +``` sudo apt install -y php-common php-fpm sqlite3 php-sqlite3 dnsutils +``` Be sure to read the DASHBOARD.README for more information. @@ -26,7 +27,7 @@ For building a QnetGateway + MMDVMHost system, see the MMDVM.README file. To bui To get started with an MMDVM-modem, DVAP, DVRPTR or Icom Terminal and/or Access Point system, clone this software to your Linux device: -```bash +``` git clone https://github.com/n7tae/QnetGateway.git ``` @@ -36,10 +37,10 @@ QnetGateway includes a "remote control" program, called `qnremote`. After you bu For other details of interesting things QnetGatway can do, see the OPERATING file. For example, with QnetGateway, you can execute up to 36 different Linux scripts from you radio. Two scripts are include: -```text +``` YourCall = " HX" will halt your system. YourCall = " RX" will reboot your system. -YourCall - " GX" will restart QnetGateway +YourCall = " GX" will restart QnetGateway. ``` QnetGateway is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. QnetGateway is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the LICENSE file for more details. From 3e3a4d9c8a668d589183d9d002ef2daeabfbdaff Mon Sep 17 00:00:00 2001 From: Colby Ross Date: Sat, 15 Mar 2025 11:51:01 -0400 Subject: [PATCH 05/11] Fix dongle connection bug. (#20) --- QnetLink.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QnetLink.cpp b/QnetLink.cpp index 613c652..9a1624c 100644 --- a/QnetLink.cpp +++ b/QnetLink.cpp @@ -2411,7 +2411,7 @@ void CQnetLink::ProcessREF(unsigned char *buf, const int length) printf("new CALL=%s, DONGLE-p, ip=%s, users=%d\n", inbound->call, ip.c_str(), (int)inbound_list.size()); buf[0] = 8; - memcpy(buf+4, "OKAY", 4); + memcpy(buf+4, "OKRW", 4); REFWrite(buf, 8, fromDst4); qnDB.UpdateLS(ip.c_str(), 'p', inbound->call, 'p', time(NULL)); From 425e007aa1115a2a778e3ffddf0a63d19ef7b972 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Sun, 16 Mar 2025 07:00:16 -0700 Subject: [PATCH 06/11] added ircddb menu item for Quadnet dual-stack operation --- qnconfig | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/qnconfig b/qnconfig index 2c7d0a9..8b3f3e8 100755 --- a/qnconfig +++ b/qnconfig @@ -251,6 +251,9 @@ IrcddbMenu () { 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 + echo "d : Setup dual-stack (IPv4 & IPv6) QuadNet irc servers for me!" + echo 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} @@ -264,6 +267,10 @@ IrcddbMenu () { EndMenu if [[ "$key" == l* ]]; then ircddb_login="${value^^}" + elif [[ "$key" == d* ]]; then + ircddb0_host='ircv6.openquad.net' + ircddb1_host='ircv4.openquad.net' + unset ircddb{0,1}_port ircddb{0,1}_password elif [[ "$key" == ha* ]]; then if [ -z "$value"]; then if [ -z "${ircddb1_host+x}" ]; then From 91cb2d5ce1d912028f981f19f9cbf321d4d6aebb Mon Sep 17 00:00:00 2001 From: Colby Ross Date: Sun, 30 Mar 2025 10:38:18 -0400 Subject: [PATCH 07/11] Correct RPT2 sent to linked reflectors. --- QnetLink.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/QnetLink.cpp b/QnetLink.cpp index 9a1624c..64fcc4b 100644 --- a/QnetLink.cpp +++ b/QnetLink.cpp @@ -3176,8 +3176,8 @@ void CQnetLink::Run() memcpy(rdsvt.dsvt.hdr.rpt1, to_remote_g2[i].cs, strlen(to_remote_g2[i].cs)); rdsvt.dsvt.hdr.rpt1[7] = to_remote_g2[i].to_mod; memset(rdsvt.dsvt.hdr.rpt2, ' ', CALL_SIZE); - memcpy(rdsvt.dsvt.hdr.rpt2, to_remote_g2[i].cs, strlen(to_remote_g2[i].cs)); - rdsvt.dsvt.hdr.rpt2[7] = 'G'; + memcpy(rdsvt.dsvt.hdr.rpt2, owner.c_str(), 7); + rdsvt.dsvt.hdr.rpt2[7] = dsvt.hdr.rpt1[7]; memcpy(rdsvt.dsvt.hdr.urcall, "CQCQCQ ", CALL_SIZE); calcPFCS(rdsvt.dsvt.title, 56); From 78248cab5f45d7ad165998977907886b216010c7 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Sun, 30 Mar 2025 08:03:58 -0700 Subject: [PATCH 08/11] log LINKSTATUS table updates --- QnetDB.cpp | 2 +- QnetLink.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/QnetDB.cpp b/QnetDB.cpp index f76c81e..ae03ff1 100644 --- a/QnetDB.cpp +++ b/QnetDB.cpp @@ -178,7 +178,7 @@ bool CQnetDB::UpdateLS(const char *address, const char from_mod, const char *to_ return false; std::stringstream sql; sql << "INSERT OR REPLACE INTO LINKSTATUS (ip_address, from_mod, to_callsign, to_mod, linked_time) VALUES ('" << address << "', '" << from_mod << "', '" << to_callsign << "', '" << to_mod << "', " << linked_time << ");"; - + printf("%s\n", sql.str().c_str()); // log these updates char *eMsg; if (SQLITE_OK != sqlite3_exec(db, sql.str().c_str(), NULL, 0, &eMsg)) { diff --git a/QnetLink.cpp b/QnetLink.cpp index 64fcc4b..254cc92 100644 --- a/QnetLink.cpp +++ b/QnetLink.cpp @@ -54,7 +54,7 @@ #include "QnetLink.h" #include "Utilities.h" -#define LINK_VERSION "QnetLink-41203" +#define LINK_VERSION "QnetLink-50330" CQnetLink::CQnetLink() : CBase() { From 4d8cc8bd9de62a50d4e3b0583319f19d451bf5e6 Mon Sep 17 00:00:00 2001 From: Colby Ross Date: Sun, 30 Mar 2025 14:15:14 -0400 Subject: [PATCH 09/11] Move DPlus disconnect debug statement and disconnect packet. --- QnetLink.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/QnetLink.cpp b/QnetLink.cpp index 254cc92..409d960 100644 --- a/QnetLink.cpp +++ b/QnetLink.cpp @@ -2183,15 +2183,15 @@ void CQnetLink::ProcessREF(unsigned char *buf, const int length) } else if (length==5 && buf[0]==5 && buf[1]==0 && buf[2]==24 && buf[3]==0 && buf[4]==0) { - if (log_debug) - printf("Got a disconnect request!!\n"); - /* reply with the same DISCONNECT */ - REFWrite(buf, 5, fromDst4); - for (int i=0; i<3; i++) { if (fromDst4==to_remote_g2[i].addr && to_remote_g2[i].addr.GetPort()==rmt_ref_port) { + if (log_debug) + printf("Got a disconnect request!!\n"); + /* reply with the same DISCONNECT */ + REFWrite(buf, 5, fromDst4); + printf("Call %s disconnected\n", to_remote_g2[i].cs); to_remote_g2[i].cs[0] = '\0'; From f4fcc355bfeb2a0a71d36db0521ea045889d381b Mon Sep 17 00:00:00 2001 From: nullobsi Date: Tue, 8 Jul 2025 20:36:53 +0000 Subject: [PATCH 10/11] fix: only query valid FDs (#21) On hardened glibc, calling FD_ISSET with an FD <0 or >FD_SETSIZE causes a SIGABRT. Only query FDs that are associated with enabled repeater modules to work around this crash. --- QnetGateway.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QnetGateway.cpp b/QnetGateway.cpp index 6801304..f08f0e3 100644 --- a/QnetGateway.cpp +++ b/QnetGateway.cpp @@ -2127,7 +2127,7 @@ void CQnetGateway::Run() // process packets coming from local repeater module(s) for (int i=0; i<3; i++) { - if (keep_running && FD_ISSET(FromModem[i].GetFD(), &fdset)) + if (keep_running && Rptr.mod[i].defined && FD_ISSET(FromModem[i].GetFD(), &fdset)) { SDSVT dsvt; const ssize_t len = FromModem[i].Read(dsvt.title, 56); From f1c455711507afec01da5f894e9103e581f910ca Mon Sep 17 00:00:00 2001 From: Tom Early Date: Mon, 11 May 2026 15:51:13 -0700 Subject: [PATCH 11/11] minor update --- DStarDecode.h | 4 ++-- QnetLink.cpp | 8 ++++---- defaults | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/DStarDecode.h b/DStarDecode.h index 13a2e57..91c7185 100644 --- a/DStarDecode.h +++ b/DStarDecode.h @@ -30,8 +30,8 @@ public: private: // functions long get_syndrome(long pattern); - long arr2int(int a[], int r); - void nextcomb(int n, int r, int a[]); + long arr2int(int *a, int r); + void nextcomb(int n, int r, int *a); int golay2412(int data, int *decoded); // data diff --git a/QnetLink.cpp b/QnetLink.cpp index 409d960..ae9ac17 100644 --- a/QnetLink.cpp +++ b/QnetLink.cpp @@ -2187,10 +2187,10 @@ void CQnetLink::ProcessREF(unsigned char *buf, const int length) { if (fromDst4==to_remote_g2[i].addr && to_remote_g2[i].addr.GetPort()==rmt_ref_port) { - if (log_debug) - printf("Got a disconnect request!!\n"); - /* reply with the same DISCONNECT */ - REFWrite(buf, 5, fromDst4); + if (log_debug) + printf("Got a disconnect request!!\n"); + /* reply with the same DISCONNECT */ + REFWrite(buf, 5, fromDst4); printf("Call %s disconnected\n", to_remote_g2[i].cs); diff --git a/defaults b/defaults index d6c2cf2..54b41b3 100644 --- a/defaults +++ b/defaults @@ -28,7 +28,7 @@ # This file should not contain any tab characters. Use spaces instead. # # if a definition is commented out, it means that key has no default value. And it is -# include here just as a reference. The 'ircddb_login' value is requred for every +# include here just as a reference. The 'ircddb_login' value is required for every # configure file ########################################################################################################################## @@ -52,7 +52,7 @@ gateway_send_qrgs_maps_d=true # send frequency, offset, coordinates and u gateway_ip_d='ANY_PORT' # the g2 port gateway_port_d=40000 # don't change gateway_ipv6_ip_d='ANY_PORT' -gateway_ipv6_port_d=9011 # IANA-approved DStar rouing port +gateway_ipv6_port_d=9011 # IANA-approved DStar routing port gateway_latitude_d=0 # you can leave this unspecified for a mobile rig gateway_longitude_d=0 # like the latitude gateway_desc1_d='' # maximum of 20 characters, most special symbols are not allowed @@ -93,7 +93,7 @@ module_x_link_at_start='' # For example, set to 'REF001 C' to link module to 1- module_x_auto_link=true # attempt to automatically re-link if the link should time out. module_x_inactivity=0 # if no activity for this many minutes unlink reflector. Zero means no timer. module_x_callsign='' # if you operate in a 'restriction mode', use your personal callsign. Usually leave this empty. -module_x_packet_wait=25 # how many milliseconds to wait on packets in a voicestream +module_x_packet_wait=25 # how many milliseconds to wait on packets in a voice-stream module_x_acknowledge=false # Do you want an ACK back? module_x_ack_delay=250 # millisecond delay before acknowledgment module_x_range=0 # the range of this repeater, in meters 1609.344 meters is 1.0 miles