From 582087386dede503003bb904a53cb308560cea74 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Sat, 22 Aug 2015 16:58:13 -0400 Subject: [PATCH] major rewrite of :IRCDDB commands --- IRCDDB.cpp | 10 +- IRCDDB.h | 7 +- IRCDDBApp.cpp | 146 +++++++++------- IRCDDBApp.h | 6 +- Makefile | 6 +- dvap_rptr.cpp | 5 +- dvrptr.cpp | 5 +- g2_ircddb.cfg | 118 ++++++------- g2_ircddb.cpp | 471 +++++++++++++++++++++++--------------------------- gwys.txt | 84 +++++++-- versions.h | 4 + 11 files changed, 446 insertions(+), 416 deletions(-) create mode 100644 versions.h diff --git a/IRCDDB.cpp b/IRCDDB.cpp index 4246362..761547c 100644 --- a/IRCDDB.cpp +++ b/IRCDDB.cpp @@ -69,17 +69,15 @@ int CIRCDDB::getConnectionState() } -void CIRCDDB::rptrQTH( double latitude, double longitude, const wxString& desc1, - const wxString& desc2, const wxString& infoURL ) +void CIRCDDB::rptrQTH(const wxString& rptrcall, double latitude, double longitude, const wxString& desc1, const wxString& desc2, const wxString& infoURL, const wxString &swVersion) { - d->app->rptrQTH(latitude, longitude, desc1, desc2, infoURL); + d->app->rptrQTH(rptrcall, latitude, longitude, desc1, desc2, infoURL, swVersion); } -void CIRCDDB::rptrQRG( const wxString& module, double txFrequency, double duplexShift, - double range, double agl ) +void CIRCDDB::rptrQRG(const wxString& rptrcall, double txFrequency, double duplexShift, double range, double agl) { - d->app->rptrQRG(module, txFrequency, duplexShift, range, agl); + d->app->rptrQRG(rptrcall, txFrequency, duplexShift, range, agl); } diff --git a/IRCDDB.h b/IRCDDB.h index 0f9dc56..7e1a91f 100644 --- a/IRCDDB.h +++ b/IRCDDB.h @@ -53,13 +53,12 @@ public: // rptrQTH can be called multiple times if necessary + // rptrcall callsign of the repeater // latitude WGS84 position of antenna in degrees, positive value -> NORTH // longitude WGS84 position of antenna in degrees, positive value -> EAST // desc1, desc2 20-character description of QTH - // infoURL URL of a web page with information about the repeater - void rptrQTH( double latitude, double longitude, const wxString& desc1, - const wxString& desc2, const wxString& infoURL ); + void rptrQTH(const wxString& rptrcall, double latitude, double longitude, const wxString& desc1, const wxString& desc2, const wxString& infoURL, const wxString &swVersion); @@ -70,7 +69,7 @@ public: // range range of the repeater in meters (meters = miles * 1609.344) // agl height of the antenna above ground in meters (meters = feet * 0.3048) - void rptrQRG( const wxString& module, double txFrequency, double duplexShift, double range, double agl ); + void rptrQRG(const wxString& rptrcall, double txFrequency, double duplexShift, double range, double agl); // If you call this method once, watchdog messages will be sent to the diff --git a/IRCDDBApp.cpp b/IRCDDBApp.cpp index 8ad58db..2793f25 100644 --- a/IRCDDBApp.cpp +++ b/IRCDDBApp.cpp @@ -104,19 +104,21 @@ wxDateTime IRCDDBAppRptrObject::maxTime((time_t) 950000000); // February 2000 WX_DECLARE_STRING_HASH_MAP( IRCDDBAppRptrObject, IRCDDBAppRptrMap ); WX_DECLARE_STRING_HASH_MAP( wxString, IRCDDBAppModuleMap ); +WX_DECLARE_STRING_HASH_MAP( wxString, IRCDDBAppLocationMap ); +WX_DECLARE_STRING_HASH_MAP( wxString, IRCDDBAppURLMap ); +WX_DECLARE_STRING_HASH_MAP( wxString, IRCDDBAppSWMap ); class IRCDDBAppPrivate { public: - IRCDDBAppPrivate() - : tablePattern(wxT("^[0-9]$")), - datePattern(wxT("^20[0-9][0-9]-((1[0-2])|(0[1-9]))-((3[01])|([12][0-9])|(0[1-9]))$")), - timePattern(wxT("^((2[0-3])|([01][0-9])):[0-5][0-9]:[0-5][0-9]$")), - dbPattern(wxT("^[0-9A-Z_]{8}$")), - modulePattern(wxT("^[ABCD]D?$")) { - wdTimer = 0; - wdCounter = 0; + IRCDDBAppPrivate() : tablePattern(wxT("^[0-9]$")), + datePattern(wxT("^20[0-9][0-9]-((1[0-2])|(0[1-9]))-((3[01])|([12][0-9])|(0[1-9]))$")), + timePattern(wxT("^((2[0-3])|([01][0-9])):[0-5][0-9]:[0-5][0-9]$")), + dbPattern(wxT("^[0-9A-Z_]{8}$")), + modulePattern(wxT("^.*[ABCD]D?$")) + { + wdTimer = -1; } IRCMessageQueue * sendQ; @@ -151,14 +153,16 @@ public: IRCMessageQueue replyQ; IRCDDBAppModuleMap moduleMap; + IRCDDBAppLocationMap locationMap; + IRCDDBAppURLMap urlMap; + IRCDDBAppSWMap swMap; wxMutex moduleMapMutex; - wxString rptrLocation; - wxString rptrInfoURL; +// wxString rptrLocation; +// wxString rptrInfoURL; wxString wdInfo; int wdTimer; - int wdCounter; }; @@ -191,14 +195,14 @@ IRCDDBApp::~IRCDDBApp() } -void IRCDDBApp::rptrQTH( double latitude, double longitude, const wxString& desc1, - const wxString& desc2, const wxString& infoURL ) +void IRCDDBApp::rptrQTH(const wxString& rptrcall, double latitude, double longitude, const wxString& desc1, const wxString& desc2, const wxString& infoURL, const wxString &swVersion) { wxString pos = wxString::Format(wxT("%+09.5f %+010.5f"), latitude, longitude); wxString d1 = desc1; wxString d2 = desc2; + wxString rcall = rptrcall; d1.Append(wxT(' '), 20); d2.Append(wxT(' '), 20); @@ -211,56 +215,70 @@ void IRCDDBApp::rptrQTH( double latitude, double longitude, const wxString& desc pos.Replace( wxT(","), wxT(".")); d1.Replace(wxT(" "), wxT("_")); d2.Replace(wxT(" "), wxT("_")); + rcall.Replace(wxT(" "), wxT("_")); - d->rptrLocation = pos + wxT(" ") + d1.Mid(0, 20) + wxT(" ") + d2.Mid(0, 20); + wxString f = rcall + wxT(" ") + pos + wxT(" ") + d1.Mid(0, 20) + wxT(" ") + d2.Mid(0, 20); - wxLogVerbose(wxT("QTH: ") + d->rptrLocation); + wxMutexLocker lock(d->moduleMapMutex); + d->locationMap[rptrcall] = f; + + wxLogVerbose(wxT("IRCDDB RPTRQTH: ") + f); wxRegEx urlNonValid(wxT("[^[:graph:]]")); - d->rptrInfoURL = infoURL; + wxString url = infoURL; + + urlNonValid.Replace( &url, wxEmptyString ); + wxString g = rcall + wxT(" ") + url; + + d->urlMap[rptrcall] = g; - urlNonValid.Replace( & d->rptrInfoURL, wxEmptyString ); + wxLogVerbose(wxT("IRCDDB RPTRURL: ") + g); - wxLogVerbose(wxT("URL: ") + d->rptrInfoURL.Mid(0, 120)); + wxString sw = swVersion; + urlNonValid.Replace( &sw, wxEmptyString ); + wxString h = rcall + wxT(" ") + sw; + d->swMap[rptrcall] = h; + + wxLogVerbose(wxT("IRCDDB RPTRSW: ") + h); d->infoTimer = 5; // send info in 5 seconds } -void IRCDDBApp::rptrQRG( const wxString& module, double txFrequency, double duplexShift, - double range, double agl ) +void IRCDDBApp::rptrQRG(const wxString& rptrcall, double txFrequency, double duplexShift, double range, double agl) { - if (d->modulePattern.Matches(module)) { - wxString f = module + wxT(" ") + wxString::Format(wxT("%011.5f %+010.5f %06.2f %06.1f"), - txFrequency, duplexShift, range / 1609.344, agl ); + if (d->modulePattern.Matches(rptrcall)) { + + wxString c = rptrcall; + c.Replace(wxT(" "), wxT("_")); + + wxString f = wxString::Format(wxT("%011.5f %+010.5f %06.2f %06.1f"), txFrequency, duplexShift, range / 1609.344, agl ); f.Replace( wxT(","), wxT(".")); + wxString g = c + wxT(" ") + f; wxMutexLocker lock(d->moduleMapMutex); - d->moduleMap[module] = f; + d->moduleMap[rptrcall] = g ; - wxLogVerbose(wxT("QRG: ") + f); + wxLogVerbose(wxT("IRCDDB RPTRQRG: ") + g); d->infoTimer = 5; // send info in 5 seconds } } -void IRCDDBApp::kickWatchdog( const wxString& s ) +void IRCDDBApp::kickWatchdog(const wxString& s) { if (s.Len() > 0) { - wxRegEx nonValid(wxT("[^[:graph:]]")); - d->wdInfo = s; - nonValid.Replace(& d->wdInfo, wxEmptyString); - if (d->wdInfo.Len() > 0) { - if (d->wdTimer == 0) { - d->wdTimer ++; - } + wxString u = s; + wxRegEx nonValid(wxT("[^[:graph:]]")); + nonValid.Replace(&u, wxEmptyString); + d->wdInfo = u; - d->wdCounter ++; - } + if (u.Len() > 0) + d->wdTimer = 1; } } @@ -991,7 +1009,7 @@ wxThread::ExitCode IRCDDBApp::Entry() while (!d->terminateThread) { if (d->timer > 0) { - d->timer --; + d->timer--; } switch(d->state) { @@ -1104,12 +1122,15 @@ wxThread::ExitCode IRCDDBApp::Entry() } if (d->infoTimer > 0) { - d->infoTimer --; + d->infoTimer--; if (d->infoTimer == 0) { - if (d->rptrLocation.Len() > 0) { - IRCMessage * m = new IRCMessage(d->currentServer, - wxT("IRCDDB QTH: ") + d->rptrLocation); + wxMutexLocker lock(d->moduleMapMutex); + + IRCDDBAppLocationMap::iterator itl; + for ( itl = d->locationMap.begin(); itl != d->locationMap.end(); itl++ ) { + wxString value = itl->second; + IRCMessage * m = new IRCMessage(d->currentServer, wxT("IRCDDB RPTRQTH: ") + value); IRCMessageQueue * q = getSendQ(); if (q != NULL) { @@ -1117,9 +1138,10 @@ wxThread::ExitCode IRCDDBApp::Entry() } } - if (d->rptrInfoURL.Len() > 0) { - IRCMessage * m = new IRCMessage(d->currentServer, - wxT("IRCDDB URL: ") + d->rptrInfoURL); + IRCDDBAppURLMap::iterator itu; + for ( itu = d->urlMap.begin(); itu != d->urlMap.end(); itu++) { + wxString value = itu->second; + IRCMessage * m = new IRCMessage(d->currentServer, wxT("IRCDDB RPTRURL: ") + value); IRCMessageQueue * q = getSendQ(); if (q != NULL) { @@ -1127,13 +1149,21 @@ wxThread::ExitCode IRCDDBApp::Entry() } } - wxMutexLocker lock(d->moduleMapMutex); + IRCDDBAppModuleMap::iterator itm; + for( itm = d->moduleMap.begin(); itm != d->moduleMap.end(); ++itm ) { + wxString value = itm->second; + IRCMessage * m = new IRCMessage(d->currentServer, wxT("IRCDDB RPTRQRG: ") + value); - IRCDDBAppModuleMap::iterator it; - for( it = d->moduleMap.begin(); it != d->moduleMap.end(); ++it ) { - wxString value = it->second; - IRCMessage * m = new IRCMessage(d->currentServer, - wxT("IRCDDB QRG: ") + value); + IRCMessageQueue * q = getSendQ(); + if (q != NULL) { + q->putMessage(m); + } + } + + IRCDDBAppSWMap::iterator its; + for( its = d->swMap.begin(); its != d->swMap.end(); ++its ) { + wxString value = its->second; + IRCMessage * m = new IRCMessage(d->currentServer, wxT("IRCDDB RPTRSW: ") + value); IRCMessageQueue * q = getSendQ(); if (q != NULL) { @@ -1144,20 +1174,18 @@ wxThread::ExitCode IRCDDBApp::Entry() } if (d->wdTimer > 0) { - d->wdTimer --; - if (d->wdTimer == 0) { + d->wdTimer--; + if (d->wdTimer <= 0) { d->wdTimer = 900; // 15 minutes - IRCMessage * m = new IRCMessage(d->currentServer, - wxT("IRCDDB WATCHDOG: ") + getCurrentTime() + - wxT(" ") + d->wdInfo.Mid(0,120) + - wxString::Format(wxT(" %d"), d->wdCounter )); + IRCMessage *m = new IRCMessage(d->currentServer, wxT("IRCDDB WATCHDOG: ") + + getCurrentTime() + wxT(" ") + d->wdInfo + wxT(" 1")); - IRCMessageQueue * q = getSendQ(); - if (q != NULL) { + IRCMessageQueue *q = getSendQ(); + if (q != NULL) q->putMessage(m); - d->wdCounter = 0; - } + else + delete m; } } break; diff --git a/IRCDDBApp.h b/IRCDDBApp.h index 2d3087a..90f54c3 100644 --- a/IRCDDBApp.h +++ b/IRCDDBApp.h @@ -75,11 +75,9 @@ public: int getConnectionState(); - void rptrQRG( const wxString& module, double txFrequency, double duplexShift, - double range, double agl ); + void rptrQRG(const wxString& rptrcall, double txFrequency, double duplexShift, double range, double agl); - void rptrQTH( double latitude, double longitude, const wxString& desc1, - const wxString& desc2, const wxString& infoURL ); + void rptrQTH(const wxString& rtprcall, double latitude, double longitude, const wxString& desc1, const wxString& desc2, const wxString& infoURL, const wxString &swVersion); void kickWatchdog( const wxString& wdInfo ); diff --git a/Makefile b/Makefile index 5527f3d..925640e 100644 --- a/Makefile +++ b/Makefile @@ -29,13 +29,13 @@ IRCDDBOBJS = IRCDDB.o IRCClient.o IRCReceiver.o IRCMessageQueue.o IRCProtocol.o all : $(PROGRAMS) -g2_ircddb : g2_ircddb.cpp $(IRCDDBOBJS) +g2_ircddb : g2_ircddb.cpp $(IRCDDBOBJS) versions.h g++ $(CPPFLAGS) -o g2_ircddb g2_ircddb.cpp $(IRCDDBOBJS) $(LDFLAGS) -pthread -g2_link : g2_link.cpp +g2_link : g2_link.cpp versions.h g++ -W -Wall -o g2_link g2_link.cpp -lrt -pthread -dvap_rptr : dvap_rptr.cpp dstar_dv.o golay23.o +dvap_rptr : dvap_rptr.cpp dstar_dv.o golay23.o versions.h g++ -W -Wall -o dvap_rptr dvap_rptr.cpp golay23.o dstar_dv.o -I/usr/include -L/usr/lib -lrt -pthread dvrptr : dvrptr.cpp dstar_dv.o golay23.o diff --git a/dvap_rptr.cpp b/dvap_rptr.cpp index 36fea00..3d0acd0 100644 --- a/dvap_rptr.cpp +++ b/dvap_rptr.cpp @@ -17,7 +17,7 @@ */ /*** - KI4LKF + KI4LKF, AC2IE ***/ #include @@ -37,8 +37,9 @@ #include #include #include +#include "versions.h" -#define VERSION "2.32" +#define VERSION DVAP_VERSION #define CALL_SIZE 8 #define RPTR_SIZE 8 #define IP_SIZE 15 diff --git a/dvrptr.cpp b/dvrptr.cpp index e24622d..a856c3d 100644 --- a/dvrptr.cpp +++ b/dvrptr.cpp @@ -1,6 +1,6 @@ /* * DVRPTR Repeater for Linux - * Autor: DG1HT DH2YBE KI4LKF + * Autor: DG1HT DH2YBE KI4LKF AC2IE * --------------------------------------------------------------------------------------------------------*/ #include @@ -21,8 +21,9 @@ #include #include #include +#include "versions.h" -#define VERSION "1.79" +#define VERSION DVRPTR_VERSION #define BAUD B115200 #define CALL_SIZE 8 #define RPTR_SIZE 8 diff --git a/g2_ircddb.cfg b/g2_ircddb.cfg index 4a8aff7..37ff04e 100644 --- a/g2_ircddb.cfg +++ b/g2_ircddb.cfg @@ -18,38 +18,29 @@ # # g2_ircddb.cfg configuration file for g2_ircddb gateway -# No SPACE before or after the EQUAL sign(=) -# That is true for all options. -# Example: -# You can NOT do this: OWNER = ... -# You can NOT do this: OWNER =... -# You can NOT do this: OWNER= ... -# VALID format is: OWNER=... - - # Your G2 Gateway callsign can be up to 6 characters # This will also be used to connect to the remote ircDDB server # and validate you on the DStar trust system -OWNER= -# PACKAGE_REV value will show on the German IRC status site under the column PACKAGE_REV -# Use the name of your repeater software or anything else you like -# Separate the name from the version using the underscore -# PACKAGE_REV=rptr_319 -# PACKAGE_REV=sound_116 -PACKAGE_REV=dvap-rptr_232 -# PACKAGE_REV=dvrptr_176 +OWNER = # This is for APRS/GPS -SEND_APRS=Y -# The repeater module specifications -# LATITUDE,LONGITUDE,RANGE,DESCRIPTION -# If you do NOT want to define the aprs parameters for a module, -# then leave the line BLANK - -RPTR_ID_A= -RPTR_ID_B= -RPTR_ID_C=42.0,-73.0,1,DVAP +SEND_APRS = Y + +# This is for the Live IRC site, or Quadnet +# if you don't want you frequency, location or url sent, set this to "N", or leave the "RPTR_X" fields empty. +SEND_QRGS_MAPS = Y + +# RPTR_X = Type | Frequency(MHz) | Offset(MHz) | Range(m) | above ground level(m) | latitude | longitude | description#1 | description#2 | URL +# If you do NOT want to define a parameter for a module, then leave the parameter BLANK, except... +# Type: 0 is DVAP, 1 is DVRPTR. YOU MUST SPECIFY THIS PARAMETER. +# only the first 20 characters of the descriptions and 64 characters of the URL will be used. +# Example for a 2m DVAP connected to an antenna 10 meters above ground level with a range of 1 mile +# (Yes, if you use good cable connected to an outside antenna, your dvap can go a mile! I've done it.) +# RPTR_C = 0 | 146.5 | 0 | 1609.344 | 10 | 42.0000 | -73.0000 | Mytown, MyState | MyGrid | github.com/ac2ie/g2_ircddb +RPTR_A = +RPTR_B = +RPTR_C = # Which local address on your Linux box will be used # to report to the remote IRC database server(group2, group1,...) @@ -57,50 +48,42 @@ RPTR_ID_C=42.0,-73.0,1,DVAP # If you have more than one ethernet card, then you may set it to a specific local IP # that is assigned to that specific ethernet card # If you have one ethernet card, you can use 0.0.0.0 -LOCAL_IRC_IP=0.0.0.0 +LOCAL_IRC_IP = 0.0.0.0 -# This is for the Live IRC site -SEND_QRGS_MAPS=N -# LATITUDE, LONGITUDE, description1, description2, url -QTH=42.0, -73.0, Dstar-rptr C, g2-ircddb -# Frequency, shift, range, antenna's height above ground(agl) -QRG_A= -QRG_B= -QRG_C= # You should NOT change the value for APRS_HOST # Leave it set to: rotate.aprs.net # The only time to change it is when you have your own APRS_HOST server # or when you have a server that is closer to your QTH -APRS_HOST=rotate.aprs.net -APRS_PORT=14580 +APRS_HOST = rotate.aprs.net +APRS_PORT = 14580 # How often to report the aprs beacon, in minutes, Do NOT make it less than 40 -APRS_INTERVAL=40 +APRS_INTERVAL = 40 APRS_FILTER= # The G2 external port of this Gateway server # Remote gateways will route data here -G2_EXTERNAL_IP=0.0.0.0 -G2_EXTERNAL_PORT=40000 +G2_EXTERNAL_IP = 0.0.0.0 +G2_EXTERNAL_PORT = 40000 # The G2 internal port of this Gateway server # Our local repeater modules will send data here -G2_INTERNAL_IP=0.0.0.0 -G2_INTERNAL_PORT=19000 +G2_INTERNAL_IP = 0.0.0.0 +G2_INTERNAL_PORT = 19000 # Where is the g2_link running ? -TO_G2_LINK_IP=127.0.0.1 -TO_G2_LINK_PORT=18997 +TO_G2_LINK_IP = 127.0.0.1 +TO_G2_LINK_PORT = 18997 # The repeater modules of this repeater -TO_RPTR_IP_A=127.0.0.1 -TO_RPTR_PORT_A=19998 +TO_RPTR_IP_A = 127.0.0.1 +TO_RPTR_PORT_A = 19998 -TO_RPTR_IP_B=127.0.0.1 -TO_RPTR_PORT_B=19999 +TO_RPTR_IP_B = 127.0.0.1 +TO_RPTR_PORT_B = 19999 -TO_RPTR_IP_C=127.0.0.1 -TO_RPTR_PORT_C=20000 +TO_RPTR_IP_C = 127.0.0.1 +TO_RPTR_PORT_C = 20000 # Timeouts in seconds # We need these timeouts because the END-OF-AUDIO packet can get lost. @@ -117,65 +100,64 @@ TO_RPTR_PORT_C=20000 # Echotest-recording timeout: # If after 1 second, audio stops coming in for echotest-recording, # we will stop recording for ECHOTEST -ECHOTEST_REC_TIMEOUT=1 +ECHOTEST_REC_TIMEOUT = 1 # Voicemail-recording timeout: # If after 1 second, audio stops coming in for voicemail-recording, # we will stop recording for voicemail -VOICEMAIL_REC_TIMEOUT=1 +VOICEMAIL_REC_TIMEOUT = 1 # If after 2 seconds, we do not receive any more packets from remote system, # we will assume that the remote QSO has stopped -FROM_REMOTE_G2_TIMEOUT=2 +FROM_REMOTE_G2_TIMEOUT = 2 # If after 1 second, we do not receive any more packets from # our local repeater, we will assume that the local RF user has stopped talking. -FROM_LOCAL_RPTR_TIMEOUT=1 +FROM_LOCAL_RPTR_TIMEOUT = 1 # print QSO details -QSO_DETAILS=Y +QSO_DETAILS = Y # These 2 options limit the lines in the log. # For production systems, we recommend: IRC_DEBUG=N -IRC_DEBUG=N -DTMF_DEBUG=N +IRC_DEBUG = N +DTMF_DEBUG = N # Do you want to re-generate the HEADER if there is a timeout from # messages arriving from remote systems(reflectors, gateways, ...) -REGEN_HDR=Y +REGEN_HDR = Y # LINK STATUS file # This file is created by g2_link # This gateway will ONLY read that status file # to determine if any module is linked to anything -STATUS_FILE=/usr/local/etc/RPT_STATUS.txt +STATUS_FILE = /usr/local/etc/RPT_STATUS.txt -DTMF_DIR=/tmp +DTMF_DIR = /tmp # Directory of recorded files created in ECHOTEST/playback mode -ECHOTEST_DIR=/tmp +ECHOTEST_DIR = /tmp # How many SECONDS to wait before starting to playback the recorded file. # 1 second is enough, some repeaters require 2 seconds to re-initialize # before they accept new streams again. -PLAY_WAIT=2 +PLAY_WAIT = 2 # How many MILLIseconds to delay when playing back each of the recorded packets # Normal VoIP is 20 milliseconds or a little less -PLAY_DELAY=19 +PLAY_DELAY = 19 -IRC_DDB_HOST= +IRC_DDB_HOST = rr.openquad.net # The remote ircDDB database # For US, Canada and North America # IRC_DDB_HOST=group2-irc.ircddb.net # For the German and EU # IRC_DDB_HOST=group1-irc.ircddb.net -# For registration free routing, use OpenQuad's round-robin: -# rr.openquad.net +# For registration free routing, use OpenQuad's round-robin, rr.openquad.net # The remote ircDDB port -IRC_DDB_PORT=9007 +IRC_DDB_PORT = 9007 # Your ircDDB password given to you by the German ircDDB team. # Put your correct password here. # you will only need this with a club call using group1-irc -IRC_PASS=1111111111111111 +IRC_PASS = 1111111111111111 diff --git a/g2_ircddb.cpp b/g2_ircddb.cpp index 373d7c6..b6075c4 100644 --- a/g2_ircddb.cpp +++ b/g2_ircddb.cpp @@ -17,7 +17,7 @@ */ -/* by KI4LKF */ +/* by KI4LKF, AC2IE */ /* g2_ircddb is a dstar G2 gateway, using irc routing adapted from the OpenG2 G2 gateway @@ -59,8 +59,8 @@ using namespace std; #include #include "IRCDDB.h" +#include "versions.h" -#define VERSION "AC2IE-g2_ircddb-1.0.0" #define IP_SIZE 15 #define MAXHOSTNAMELEN 64 #define CALL_SIZE 8 @@ -75,14 +75,10 @@ using namespace std; /* Gateway callsign */ static char OWNER[CALL_SIZE + 1]; static char owner[CALL_SIZE + 1]; -static char PACKAGE_REV[56]; +//static char PACKAGE_REV[56]; static char LOCAL_IRC_IP[IP_SIZE + 1]; static bool SEND_QRGS_MAPS = false; -static char QTH[257]; -static char QRG_A[257]; -static char QRG_B[257]; -static char QRG_C[257]; static char STATUS_FILE[FILENAME_MAX + 1]; @@ -109,7 +105,7 @@ static struct sockaddr_in aprs_addr; static socklen_t aprs_addr_len; /* data needed for aprs login and aprs beacon */ -static struct { +static struct rptr_struct{ char aprs_host[MAXHOSTNAMELEN + 1]; int aprs_port; int aprs_hash; @@ -117,13 +113,17 @@ static struct { char aprs_filter[512]; /* 0=A, 1=B, 2=C */ - char rptr[3][CALL_SIZE + 1]; /* KJ4NHF-B */ - char band[3][5]; /* 23cm ... */ - int range[3]; - double lat[3]; - double lon[3]; - char desc[3][64]; -} RPTR_ID; + struct mod_struct { + char call[CALL_SIZE + 1]; /* KJ4NHF-B */ + bool defined; + char band[5]; /* 23cm ... */ + double frequency, offset, latitude, longitude, range, agl; + char desc1[21], desc2[21]; + char desc[64]; + char url[65]; + char package_version[56]; + } mod[3]; +} rptr; /* Gateway external IP and port for remote G2 routing */ static char G2_EXTERNAL_IP[IP_SIZE + 1]; /* 0.0.0.0 */ @@ -231,7 +231,7 @@ static unsigned char end_of_audio[29]; static volatile bool keep_running = true; -static time_t wd_timer = 0; +//static time_t wd_timer = 0; /* send packets to g2_link */ static struct sockaddr_in plug; @@ -539,19 +539,45 @@ static void traceit(const char *fmt,...) return; } + +static char *trim(char *s) +{ + if (s) { + // remove trailing whitespace + while (strlen(s) && isspace(s[strlen(s)-1])) + s[strlen(s)-1] = (char)NULL; + // count leading whitespace + int i = 0; + while (isspace(s[i])) + i++; + // this could be used on malloc'ed char*, so we will not change where s points + // and this will keep free() working properly. + // Instead we will move the string to s and write over leading whitespace. + if (i) { + char *p1 = s - 1; + char *p2 = p1 + i; + do { + *++p1 = *++p2; + } while (*p1); + } + } + // the returned value doesn't have to be used. s didn't change! + return s; +} + /* process configuration file */ static int read_config(char *cfgFile) { - short int valid_params = 44; + short int valid_params = 39; short int params = 0; unsigned short i; FILE *cnf = NULL; char aline[1024]; char *tok = NULL; - const char *delim = ","; const char *Tstr = "TRUE"; const char *Fstr = "FALSE"; + char zero = (char)NULL; cnf = fopen(cfgFile, "r"); if (!cnf) { @@ -560,25 +586,25 @@ static int read_config(char *cfgFile) } traceit("Reading file %s\n", cfgFile); - while (fgets(aline, 1020, cnf) != NULL) { - char *param = strtok(aline, " =\t\r\n"); - if (NULL==param || '#'==param[0]) + while (fgets(aline, 1024, cnf) != NULL) { + (void)trim(aline); + if ('#'==aline[0] || NULL==strchr(aline, '=') || (char)NULL==aline[0]) continue; - char *value = strtok(NULL, "\r\n"); + char *param = strtok(aline, "="); + if (NULL == param) + continue; + (void)trim(param); + if (0 == strlen(param)) + continue; + char *value = trim(strtok(NULL, "=")); // get the rest of the line, i.e., the value // trim value - if (value) { - while (isspace(value[0])) - value++; - while (isspace(value[strlen(value)-1])) - value[strlen(value)-1] = (char)NULL; - } + (void)trim(value); if (NULL==value) - value = ""; + value = &zero; - if (0 == strcmp(param, "OWNER")) { if (3>strlen(value) || CALL_SIZE-2= 900) { - ii->kickWatchdog(PACKAGE_REV); - wd_timer = t_now; - } + ii->kickWatchdog(IRCDDB_VERSION); + while (keep_running) { for (i = 0; i < 3; i++) { /* echotest recording timed out? */ if (recd[i].last_time != 0) { @@ -2844,7 +2893,7 @@ static void compute_aprs_hash() i += 2; } traceit("aprs hash code=[%d] for %s\n", hash, OWNER); - RPTR_ID.aprs_hash = hash; + rptr.aprs_hash = hash; return; } @@ -2864,28 +2913,28 @@ static void aprs_open() int rc = 0; /* do some mimimal checking */ - if (RPTR_ID.aprs_host[0] == '\0') { + if (rptr.aprs_host[0] == '\0') { traceit("Invalid value for APRS_HOST\n"); return; } - if (RPTR_ID.aprs_port == 0) { + if (rptr.aprs_port == 0) { traceit("Invalid value for APRS_PORT\n"); return; } - if (RPTR_ID.aprs_interval == 0) { + if (rptr.aprs_interval == 0) { traceit("Invalid value for APRS_INTERVAL\n"); return; } - ok = resolve_rmt(RPTR_ID.aprs_host, SOCK_STREAM, &aprs_addr); + ok = resolve_rmt(rptr.aprs_host, SOCK_STREAM, &aprs_addr); if (!ok) { - traceit("Can not resolve APRS_HOST %s\n", RPTR_ID.aprs_host); + traceit("Can not resolve APRS_HOST %s\n", rptr.aprs_host); return; } /* fill it in */ aprs_addr.sin_family = AF_INET; - aprs_addr.sin_port = htons(RPTR_ID.aprs_port); + aprs_addr.sin_port = htons(rptr.aprs_port); aprs_addr_len = sizeof(aprs_addr); @@ -2952,16 +3001,16 @@ static void aprs_open() return; } } - traceit("Connected to APRS %s:%d\n", RPTR_ID.aprs_host, RPTR_ID.aprs_port); + traceit("Connected to APRS %s:%d\n", rptr.aprs_host, rptr.aprs_port); /* login to aprs */ sprintf(snd_buf, "user %s pass %d vers g2_ircddb 2.99 UDP 5 ", - OWNER, RPTR_ID.aprs_hash); + OWNER, rptr.aprs_hash); /* add the user's filter */ - if (RPTR_ID.aprs_filter[0] != '\0') { + if (rptr.aprs_filter[0] != '\0') { strcat(snd_buf, "filter "); - strcat(snd_buf, RPTR_ID.aprs_filter); + strcat(snd_buf, rptr.aprs_filter); } // traceit("APRS login command:[%s]\n", snd_buf); strcat(snd_buf, "\r\n"); @@ -3052,11 +3101,11 @@ void *send_aprs_beacon(void *arg) } time(&tnow); - if ((tnow - last_beacon_time) > (RPTR_ID.aprs_interval * 60)) { + if ((tnow - last_beacon_time) > (rptr.aprs_interval * 60)) { for (i = 0; i < 3; i++) { - if (RPTR_ID.desc[i][0] != '\0') { - tmp_lat = fabs(RPTR_ID.lat[i]); - tmp_lon = fabs(RPTR_ID.lon[i]); + if (rptr.mod[i].desc[0] != '\0') { + tmp_lat = fabs(rptr.mod[i].latitude); + tmp_lon = fabs(rptr.mod[i].longitude); lat = floor(tmp_lat); lon = floor(tmp_lon); lat = (tmp_lat - lat) * 60.0F + lat * 100.0F; @@ -3084,10 +3133,10 @@ void *send_aprs_beacon(void *arg) /* send to aprs */ sprintf(snd_buf, "%s>APJI23,TCPIP*,qAC,%sS:!%s%cD%s%c&RNG%04u %s %s", - RPTR_ID.rptr[i], RPTR_ID.rptr[i], - lat_s, (RPTR_ID.lat[i] < 0.0F) ? 'S' : 'N', - lon_s, (RPTR_ID.lon[i] < 0.0F) ? 'W' : 'E', - RPTR_ID.range[i], RPTR_ID.band[i], RPTR_ID.desc[i]); + rptr.mod[i].call, rptr.mod[i].call, + lat_s, (rptr.mod[i].latitude < 0.0F) ? 'S' : 'N', + lon_s, (rptr.mod[i].longitude < 0.0F) ? 'W' : 'E', + (unsigned int)rptr.mod[i].range, rptr.mod[i].band, rptr.mod[i].desc); // traceit("APRS Beacon =[%s]\n", snd_buf); strcat(snd_buf, "\r\n"); @@ -3332,100 +3381,14 @@ static void *echotest(void *arg) static void qrgs_and_maps() { - const char *delim = ","; - - char *lat_s = NULL; - double lat = 0.00; - char *lon_s = NULL; - double lon = 0.00; - char *desc1 = NULL; - char *desc2 = NULL; - char *url = NULL; - - char *freq_s = NULL; - double freq = 0.00; - char *shift_s = NULL; - double shift = 0.00; - char *range_s = NULL; - double range = 0.00; - char *agl_s = NULL; - double agl = 0.00; - - char *saveptr = NULL; - - if (QTH[0] != '\0') { - lat_s = strtok_r(QTH, delim, &saveptr); - lon_s = strtok_r(NULL, delim, &saveptr); - desc1 = strtok_r(NULL, delim, &saveptr); - desc2 = strtok_r(NULL, delim, &saveptr); - url = strtok_r(NULL, delim, &saveptr); - - if (lat_s) - lat = atof(lat_s); - if (lon_s) - lon = atof(lon_s); - - ii->rptrQTH(lat, lon, (desc1)?desc1:"", (desc2)?desc2:"", (url)?url:""); - } - - saveptr = NULL; - - if (QRG_A[0] != '\0') { - freq_s = strtok_r(QRG_A, delim, &saveptr); - shift_s = strtok_r(NULL, delim, &saveptr); - range_s = strtok_r(NULL, delim, &saveptr); - agl_s = strtok_r(NULL, delim, &saveptr); - - if (freq_s) - freq = atof(freq_s); - if (shift_s) - shift = atof(shift_s); - if (range_s) - range = atof(range_s); - if (agl_s) - agl = atof(agl_s); - - ii->rptrQRG("A", freq, shift, range, agl); - } - - saveptr = NULL; - - if (QRG_B[0] != '\0') { - freq_s = strtok_r(QRG_B, delim, &saveptr); - shift_s = strtok_r(NULL, delim, &saveptr); - range_s = strtok_r(NULL, delim, &saveptr); - agl_s = strtok_r(NULL, delim, &saveptr); - - if (freq_s) - freq = atof(freq_s); - if (shift_s) - shift = atof(shift_s); - if (range_s) - range = atof(range_s); - if (agl_s) - agl = atof(agl_s); - - ii->rptrQRG("B", freq, shift, range, agl); - } - - saveptr = NULL; - - if (QRG_C[0] != '\0') { - freq_s = strtok_r(QRG_C, delim, &saveptr); - shift_s = strtok_r(NULL, delim, &saveptr); - range_s = strtok_r(NULL, delim, &saveptr); - agl_s = strtok_r(NULL, delim, &saveptr); - - if (freq_s) - freq = atof(freq_s); - if (shift_s) - shift = atof(shift_s); - if (range_s) - range = atof(range_s); - if (agl_s) - agl = atof(agl_s); - - ii->rptrQRG("C", freq, shift, range, agl); + for(int i=0; i<3; i++) { + char rptrcall[CALL_SIZE+1]; + strcpy(rptrcall, OWNER); + rptrcall[CALL_SIZE-1] = 'A' + i; + if (rptr.mod[i].latitude || rptr.mod[i].longitude || strlen(rptr.mod[i].desc1) || strlen(rptr.mod[i].url)) + 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 (rptr.mod[i].frequency) + ii->rptrQRG(rptrcall, rptr.mod[i].frequency, rptr.mod[i].offset, rptr.mod[i].range, rptr.mod[i].agl); } return; @@ -3442,7 +3405,7 @@ int main(int argc, char **argv) setvbuf(stdout, (char *)NULL, _IOLBF, 0); - traceit("VERSION %s\n", VERSION); + traceit("VERSION %s\n", IRCDDB_VERSION); if (argc != 2) { traceit("Example: g2_ircddb g2_ircddb.cfg\n"); return 1; @@ -3473,20 +3436,20 @@ int main(int argc, char **argv) return 1; } - RPTR_ID.aprs_host[0] = '\0'; - RPTR_ID.aprs_port = 0; - RPTR_ID.aprs_hash = -1; - RPTR_ID.aprs_interval = 0; - RPTR_ID.aprs_filter[0] = '\0'; + rptr.aprs_host[0] = '\0'; + rptr.aprs_port = 0; + rptr.aprs_hash = -1; + rptr.aprs_interval = 0; + rptr.aprs_filter[0] = '\0'; for (i = 0; i < 3; i++) { - RPTR_ID.lat[i] = 0.00; - RPTR_ID.lon[i] = 0.00; - RPTR_ID.range[i] = 0; - RPTR_ID.desc[i][0] = '\0'; + rptr.mod[i].latitude = 0.00; + rptr.mod[i].longitude = 0.00; + rptr.mod[i].range = 0; + rptr.mod[i].desc[0] = '\0'; } - strcpy(RPTR_ID.band[0], "23cm"); - strcpy(RPTR_ID.band[1], "70cm"); - strcpy(RPTR_ID.band[2], "2m"); + strcpy(rptr.mod[0].band, "23cm"); + strcpy(rptr.mod[1].band, "70cm"); + strcpy(rptr.mod[2].band, "2m"); for (i = 0; i < 3; i++) { aprs_streamID[i].streamID[0] = 0x00; @@ -3534,20 +3497,20 @@ int main(int argc, char **argv) } /* build the repeater callsigns for aprs */ - strcpy(RPTR_ID.rptr[0], OWNER); - p = strchr(RPTR_ID.rptr[0], ' '); + strcpy(rptr.mod[0].call, OWNER); + p = strchr(rptr.mod[0].call, ' '); if (!p) { traceit("Failed to build repeater callsigns for aprs\n"); return 1; } *p = '\0'; - strcpy(RPTR_ID.rptr[1], RPTR_ID.rptr[0]); - strcpy(RPTR_ID.rptr[2], RPTR_ID.rptr[0]); - strcat(RPTR_ID.rptr[0], "-A"); - strcat(RPTR_ID.rptr[1], "-B"); - strcat(RPTR_ID.rptr[2], "-C"); + strcpy(rptr.mod[1].call, rptr.mod[0].call); + strcpy(rptr.mod[2].call, rptr.mod[0].call); + strcat(rptr.mod[0].call, "-A"); + strcat(rptr.mod[1].call, "-B"); + strcat(rptr.mod[2].call, "-C"); traceit("Repeater callsigns: [%s] [%s] [%s]\n", - RPTR_ID.rptr[0], RPTR_ID.rptr[1], RPTR_ID.rptr[2]); + rptr.mod[0].call, rptr.mod[1].call, rptr.mod[2].call); aprs_init(); compute_aprs_hash(); @@ -3558,7 +3521,7 @@ int main(int argc, char **argv) return 1; } - ii = new CIRCDDB(IRC_DDB_HOST, IRC_DDB_PORT, owner, IRC_PASS, VERSION, LOCAL_IRC_IP); + ii = new CIRCDDB(IRC_DDB_HOST, IRC_DDB_PORT, owner, IRC_PASS, IRCDDB_VERSION, LOCAL_IRC_IP); ok = ii->open(); if (!ok) { traceit("irc open failed\n"); @@ -3844,7 +3807,7 @@ static void aprs_process_text(unsigned char *streamID, p = strchr(aud, '\r'); *p = '\0'; - sprintf(aprs_buf, "%s,qAR,%s:%s\r\n", hdr, RPTR_ID.rptr[rptr_idx], aud); + sprintf(aprs_buf, "%s,qAR,%s:%s\r\n", hdr, rptr.mod[rptr_idx].call, aud); // traceit("GPS-A=%s", aprs_buf); rc = writen(aprs_buf, strlen(aprs_buf)); if (rc == -1) { @@ -4215,7 +4178,7 @@ static void build_aprs_from_gps_and_send(short int rptr_idx) strcat(buf, ">"); strcat(buf, "APDPRS,DSTAR*,qAR,"); - strcat(buf, RPTR_ID.rptr[rptr_idx]); + strcat(buf, rptr.mod[rptr_idx].call); strcat(buf, ":!"); //GPRMC = diff --git a/gwys.txt b/gwys.txt index 3b7ca0a..eda8b00 100644 --- a/gwys.txt +++ b/gwys.txt @@ -1,4 +1,4 @@ -REF001 109.69.104.195 20001 +REF001 192.3.202.54 20001 REF002 129.93.2.132 20001 REF003 203.194.18.195 20001 REF004 74.204.50.19 20001 @@ -10,26 +10,27 @@ REF010 12.178.74.6 20001 REF011 213.203.177.246 20001 REF012 209.112.244.26 20001 REF014 64.250.229.185 20001 -REF015 109.69.104.196 20001 REF017 80.69.86.233 20001 REF018 187.50.254.20 20001 -REF019 208.87.120.144 20001 +REF019 209.242.228.27 20001 REF020 50.199.88.20 20001 +REF023 103.1.213.18 20001 REF024 69.41.0.15 20001 REF025 173.10.178.226 20001 +REF026 206.12.104.8 20001 REF027 194.116.29.72 20001 REF028 193.190.240.229 20001 -REF029 129.123.7.138 20001 +REF029 129.123.7.23 20001 REF030 64.16.212.14 20001 REF031 212.112.188.111 20001 REF032 95.160.171.254 20001 REF033 208.67.255.202 20001 REF035 146.129.247.243 20001 -REF036 195.194.238.109 20001 REF037 208.111.3.181 20001 REF038 66.6.171.227 20001 REF039 208.93.191.20 20001 REF045 195.251.201.194 20001 +REF046 208.111.3.182 20001 REF047 157.7.142.13 20001 REF048 208.88.66.244 20001 REF050 75.147.26.195 20001 @@ -38,16 +39,27 @@ REF052 12.5.239.46 20001 REF053 69.67.29.232 20001 REF054 216.249.104.190 20001 REF055 207.251.62.205 20001 +REF056 12.166.228.165 20001 REF058 131.204.255.253 20001 +REF059 104.131.247.122 20001 REF060 50.194.6.1 20001 REF061 64.150.149.59 20001 REF062 70.88.145.165 20001 REF063 205.201.0.4 20001 -REF064 36.3.114.27 20001 -XRF000 141.22.15.29 20001 +REF064 61.195.99.81 20001 +REF066 173.255.196.45 20001 +REF067 44.34.128.167 20001 +REF068 92.222.145.197 20001 +REF069 70.91.220.113 20001 +REF070 65.50.211.156 20001 +REF071 61.195.97.218 20001 +REF072 168.103.98.244 20001 +REF073 68.67.124.145 20001 +REF074 68.67.124.146 20001 +XRF000 104.167.97.75 20001 XRF001 75.76.90.90 20001 XRF002 91.201.57.233 20001 -XRF003 95.110.157.13 20001 +XRF003 95.110.157.83 20001 XRF004 96.36.58.9 20001 XRF005 216.16.240.236 20001 XRF006 80.62.20.151 20001 @@ -57,49 +69,85 @@ XRF009 141.22.15.29 20001 XRF010 87.106.48.7 20001 XRF011 87.106.3.249 20001 XRF012 96.126.101.188 20001 -XRF013 202.191.108.233 20001 +XRF013 103.1.213.20 20001 +XRF015 176.126.243.212 20001 XRF017 87.253.159.114 20001 XRF018 199.167.129.166 20001 XRF019 66.30.81.236 20001 -XRF020 204.244.106.101 20001 +XRF020 67.210.212.144 20001 XRF021 74.204.50.67 20001 +XRF022 91.118.53.116 20001 XRF023 141.75.245.225 20001 XRF025 63.133.189.2 20001 XRF026 139.13.100.34 20001 -XRF027 194.116.29.78 20001 +XRF027 194.116.59.78 20001 XRF028 193.190.240.228 20001 XRF031 83.241.141.245 20001 XRF033 46.226.178.81 20001 XRF038 66.6.171.228 20001 +XRF041 167.88.37.80 20001 XRF044 82.1.185.173 20001 +XRF045 71.41.121.227 20001 XRF048 64.39.69.11 20001 +XRF050 104.167.119.24 20001 XRF055 95.110.229.195 20001 -XRF069 91.142.221.75 20001 +XRF067 91.121.136.94 20001 +XRF069 37.187.176.70 20001 +XRF070 182.161.156.13 20001 XRF073 147.102.7.34 20001 +XRF077 89.46.65.59 20001 XRF090 46.37.185.184 20001 XRF093 71.72.182.119 20001 XRF099 76.71.89.114 20001 +XRF117 207.218.152.20 20001 XRF119 149.154.158.170 20001 XRF121 23.238.226.253 20001 XRF123 213.126.90.100 20001 -XRF310 199.167.193.147 20001 +XRF133 191.233.96.77 20001 +XRF168 151.80.140.203 20001 +XRF185 104.167.117.71 20001 +XRF210 104.167.119.157 20001 +XRF228 88.149.164.218 20001 +XRF250 185.79.71.92 20001 +XRF295 104.167.96.2 20001 +XRF310 50.63.84.18 20001 +XRF321 vps.makeitrad.c 20001 XRF333 37.187.103.98 20001 XRF353 94.173.206.53 20001 +XRF400 5.196.8.77 20001 +XRF420 107.191.127.10 20001 XRF444 70.125.157.44 20001 +XRF450 104.167.119.28 20001 XRF500 125.63.57.138 20001 -XRF555 199.167.193.205 20001 +XRF555 54.191.67.121 20001 XRF559 98.239.113.175 20001 XRF580 67.20.31.79 20001 XRF603 74.104.179.159 20001 +XRF666 5.249.151.111 20001 +XRF669 72.16.17.137 20001 +XRF707 162.250.144.132 20001 XRF719 199.227.117.121 20001 +XRF720 204.45.107.21 20001 XRF727 108.33.72.83 20001 +XRF740 104.167.114.230 20001 +XRF748 104.167.109.27 20001 +XRF757 107.191.121.105 20001 XRF777 62.167.15.53 20001 XRF780 96.53.97.22 20001 XRF805 198.1.97.59 20001 +XRF851 213.165.96.150 20001 XRF858 198.57.255.30 20001 XRF901 199.167.196.109 20001 +XRF902 199.167.193.219 20001 XRF905 199.212.121.20 20001 +XRF906 185.50.196.134 20001 +XRF911 217.196.138.42 20001 +XRF929 162.248.165.185 20001 XRF978 74.104.179.159 20001 +XRF987 162.252.243.217 20001 +XRF988 46.105.27.191 20001 +XRF989 104.167.119.5 20001 +XRFWDX 71.110.107.100 20001 DCS001 dcs001.xreflector.net 30051 DCS002 dcs002.xreflector.net 30051 DCS003 dcs003.xreflector.net 30051 @@ -125,3 +173,11 @@ DCS022 dcs022.xreflector.net 30051 DCS023 dcs023.xreflector.net 30051 DCS024 dcs024.xreflector.net 30051 DCS025 dcs025.xreflector.net 30051 +DCS026 dcs026.xreflector.net 30051 +DCS027 dcs027.xreflector.net 30051 +DCS028 dcs028.xreflector.net 30051 +DCS029 dcs029.xreflector.net 30051 +DCS030 dcs030.xreflector.net 30051 +DCS031 dcs031.xreflector.net 30051 +DCS032 dcs032.xreflector.net 30051 +DCS033 dcs033.xreflector.net 30051 diff --git a/versions.h b/versions.h new file mode 100644 index 0000000..0729b03 --- /dev/null +++ b/versions.h @@ -0,0 +1,4 @@ +// version strings must be 55 characters or less! +#define IRCDDB_VERSION "linux-g2_ircddb-4.0.0" +#define DVAP_VERSION "linux-dvap_rptr-3.0.0" +#define DVRPTR_VERSION "linux-dvrptr-2.0.0"