commit
3f480a923f
@ -0,0 +1,66 @@
|
||||
Creating a DVAP hotspot based on Scott Lawson KI4LKF software is easy.
|
||||
|
||||
I highly recommend doing this with Debian on a Raspberry Pi or a BeagleBone Black, but it should
|
||||
also work on virtually an hardware platform with any Debian-based OS. UBUNTU should work, but
|
||||
make no guarantees!
|
||||
|
||||
The first order of business is to get the RasPi or the BBB up and running on a Debian image.
|
||||
There is plenty of room on the interal 2GB memory of the BBB to install all of what follows.
|
||||
(Unless you need a GUI, it that case you will need a lot more packages than I list below and
|
||||
a big enough external uSD card to hold the image.)
|
||||
|
||||
Look to http://raspberrypi.org for the RasPi Raspbian hard float image and to
|
||||
http://www.armhf.com for the BBB Debian image.
|
||||
|
||||
The RasPi should have all the needed packages but the BBB will not.
|
||||
On the BBB you will have:
|
||||
sudo su
|
||||
apt-get update
|
||||
apt-get upgrade
|
||||
agt-get install make g++ unzip
|
||||
|
||||
and maybe a few more.
|
||||
|
||||
The first order of business (after you expand the archvive this file came in) is to build the
|
||||
wxBase-2.8.12 library. There is a script to do all of this for you called "build_wsBase",
|
||||
but if you want to do this by hand, cat this script and type the command manually.
|
||||
|
||||
Come back to this directory and type "make" to build all the executables. If you need DTMFS
|
||||
then also "build g2link_test".
|
||||
|
||||
Now you should edit all the *.cfg files, g2_ircddb.cfg, g2_link.cfg and dvap_rptr.cfg.
|
||||
These files contain detailed comments. Just read through them and edit accordingly.
|
||||
Additional information about the configuration as well as other important and useful
|
||||
features are also in the CONFIGURING file.
|
||||
|
||||
The gwys.txt file is the internet address and port numbers for any gateway you would
|
||||
like g2_link to be able to connect to. The one delivered with this package is special:
|
||||
It has only XReflectors and DStar reflectors and the XReflectors are configures
|
||||
with the 20001 port. This will allow you to connect to everybody without opening any
|
||||
ports on your router. If you want to set up a repeater or access point, you will need
|
||||
to port forward several ports to your RasPi or BBB. Of course you will need to lock
|
||||
down the local address of the device with a static IP or reserving an address from
|
||||
your router. Executing get_gwys_list.sh will download a HUGE list of reflectors and
|
||||
repeaters with port address that my need forwarding to your sytem.
|
||||
|
||||
If you plan on using DTMFS, you can also edit proc_g2_ircddb_dtmfs.sh to add new dtmfs
|
||||
commands.
|
||||
|
||||
Then install everything by typing "sudo make install". If you want DTMFS, type
|
||||
"sudo make installdtmfs".
|
||||
|
||||
Everything will install in /usr/local. The executables will be in /usr/local/bin and
|
||||
the *.cfg files will be in /usr/local/etc. If you need to modify a configuration file,
|
||||
do it in /usr/local/etc.
|
||||
|
||||
At this point, you can either reboot to start the three or four services, or start them
|
||||
manually with the "service" command. (See the man page for service.)
|
||||
|
||||
You can clean up the intermediate *.o files with "make clean" and remove the intermediate
|
||||
*.o files and binary executables with "make realclean".
|
||||
|
||||
If you want to uninstall everything return to the build directory and type
|
||||
"sudo make uninstall" and possibly "sudo make uninstalldtmfs". This will shutdown the
|
||||
service scripts, remove everything from /usr/local and remove the service scripts.
|
||||
|
||||
Tom Early, ac2ie@arrl.net
|
||||
@ -0,0 +1,359 @@
|
||||
You need to configure three software programs, g2_ircddb, g2_link, dvap_rptr
|
||||
by setting values in their *.cfg text files. Use your favorite text editor
|
||||
to do this. Scott's comments within those files are mostly self explainatory.
|
||||
|
||||
Some other features are discussed below in Scott's own edited words.
|
||||
|
||||
Tom Early, ac2ie@arrl.net
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010, 2011, 2012 by Scott Lawson KI4LKF
|
||||
*
|
||||
* This program 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; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
G2_ircDDB adapted from the OpenG2
|
||||
|
||||
DESCRIPTION
|
||||
=================
|
||||
|
||||
g2_ircddb is a Dstar G2 gateway for the Dstar network with ircDDB routing
|
||||
and USroot routing. It runs on Linux(as a Linux service).
|
||||
ircddb originated from the OpenG2 with only one change.
|
||||
Instead of using the local Postgres database server,
|
||||
we use the remote IRC database server.(group2 or group1)
|
||||
So, the difference between OpenG2 and ircddb is 0.01%
|
||||
This new software g2_ircddb has been approved for use on the ircDDB network.
|
||||
|
||||
IRC Gateways such as g2_ircdb (other IRC gateways copied from our OpenG2)
|
||||
connect to group2 server(USA/Canada) or group1 server(Europe).
|
||||
What are these group1, group2 servers? Group1 and group2 servers are really
|
||||
the combination of 2 programs running together:
|
||||
|
||||
These are:
|
||||
---- An IRC (Internet Relay Chat) program, in this case it is the inspIRCd
|
||||
program
|
||||
---- the LDAP (Light Directory Access Protocol) program
|
||||
|
||||
So, ircDDB database servers are NOTHING new, they were designed by groups
|
||||
of people 20-30 years ago, before even the ICOM Dstar came out.
|
||||
The German IRC team, copied the above programs (IRC, LDAP) from those groups,
|
||||
and they called it group1 and group2.
|
||||
|
||||
The reason for that was that an IRC(Internet Relay Chat) server, sends data
|
||||
immediately, while the ICOM dstar network sends data 5 minutes later after a
|
||||
user keyed up a Dstar repeater. So, IRC is faster, but it overloads your
|
||||
home-network.
|
||||
|
||||
Using a PERSONAL callsign to set up an ircDBB gateway
|
||||
=====================================================
|
||||
In g2_ircddb.cfg, set OWNER equal to your personal callsign.
|
||||
In g2_link.cfg, set OWNER equal to your personal callsign.
|
||||
In your repeater config file, set OWNER equal to your personal callsign.
|
||||
|
||||
Using a REPEATER callsign to set up an ircDBB gateway
|
||||
=====================================================
|
||||
In g2_ircddb.cfg, set OWNER equal to a REPEATER callsign (that you received
|
||||
from the ham authority of your Country).
|
||||
In g2_link.cfg, set OWNER equal to a REPEATER callsign (that you received
|
||||
from the ham authority of your Country) In your repeater config file, set
|
||||
OWNER equal to a REPEATER callsign (that you received from the ham authority
|
||||
of your Country).
|
||||
|
||||
However, since the IRC database servers(group2 in Canada/USA, group1 in
|
||||
Europe) do NOT allow personal callsigns to be used as gateways, then you may
|
||||
be asking what is the point?
|
||||
|
||||
Here is the logic:
|
||||
In some Countries, it is very difficult to receive a GATEWAY (club/group)
|
||||
callsign, sometimes it takes years. In cases such as these, hams only have
|
||||
their own personal callsign to use. So, how do we get around the problem when
|
||||
the IRC servers group1, group2 require a GATEWAY callsign, but the user only
|
||||
has a PERSONAL callsign?
|
||||
|
||||
Some groups of hams got together and installed their own IRC database server.
|
||||
An IRC database server (like group1, group2) is really these 2 basic programs:
|
||||
|
||||
---- inspIRCd server software which is an IRC server (Internet Relay Chat)
|
||||
which was designed in 1988. One such IRC program is inspIRCd which was
|
||||
chosen by the German IRC team for use in their group1, group2 installations.
|
||||
|
||||
--- LDAP server software, which is the Light Directory Access Protocol server,
|
||||
that was written in 1993.
|
||||
|
||||
These 2 programs inspIRCd + LDAP make up the the IRC database servers as we know
|
||||
them today and were installed together by the IRC team on group1, group2
|
||||
installations.
|
||||
|
||||
That is all there is to it.
|
||||
|
||||
When LDAP runs, it checks the Gateway password as listed in g2_ircddb.cfg:
|
||||
IRC_PASS=... When LDAP does NOT run, then the IRC_PASS is NOT checked.
|
||||
|
||||
So, some groups of hams, have installed the inspIRCd server, without installing
|
||||
the LDAP server. In such an installation, then the IRC_PASS is NOT checked, so
|
||||
you can use your personal callsign.
|
||||
|
||||
g2_ircDDB supports the following commands in YRCALL
|
||||
|
||||
Note: In the commands that folow, _ is a SPACE.
|
||||
|
||||
1)
|
||||
For Echotest/playback.
|
||||
YRCALL=_ _ _ _ _ _ _E
|
||||
|
||||
2)
|
||||
For Voice Mail:
|
||||
YRCALL=_ _ _ _ _ _ S0
|
||||
The above command will Store/create voice mail in the dvtool file
|
||||
x_voicemail.dat.
|
||||
YRCALL=_ _ _ _ _ _ R0
|
||||
The above command will Recall/playback voice mail from the dvtool file
|
||||
x_voicemail.dat.
|
||||
YRCALL=_ _ _ _ _ _ C0
|
||||
The above command will Clear/delete voice mail. File x_voicemail.dat will be
|
||||
deleted. In all cases, the letter x in the file name x_voicemail is the
|
||||
module A,B or C.
|
||||
|
||||
3)
|
||||
For inquiring the status of the link:
|
||||
YRCALL=_ _ _ _ _ _ _I
|
||||
|
||||
4)
|
||||
For unlinking:
|
||||
YRCALL=_ _ _ _ _ _ _U
|
||||
|
||||
5)
|
||||
For linking:
|
||||
YRCALL=XXNYYYML
|
||||
Where XXNYYY is a friendly gateway, M is the gateways's module and L is the
|
||||
LINK command.
|
||||
YRCALL=XRFNNNML
|
||||
Where XRFNNN is a friendly reflector, M is the reflector's module and L is
|
||||
the LINK command.
|
||||
|
||||
Note about linking:
|
||||
After linking succeeds, set YRCALL=CQCQCQ because your audio will go to the
|
||||
remote reflector ONLY if YRCALL=CQCQCQ.
|
||||
|
||||
6)
|
||||
For executing scripts:
|
||||
YRCALL=_ _ _ _ _ _ nX
|
||||
where n can be from 0-9 or A-Z.
|
||||
Example: YRCALL=_ _ _ _ _ _1X
|
||||
Then the script exec_1.sh will be executed.
|
||||
<<AC2IE comment: Two scripts, exec_R.sh and exec_H.sh are included to reboot
|
||||
and halt your system, respectively. Also note that the MYCALL is passed to
|
||||
these scripts so you can use this as an input parameter for your scripts.>>
|
||||
|
||||
7)
|
||||
Enabling and disabling INCOMING HotSpotNode connections:
|
||||
To Enable:
|
||||
YRCALL=_ _ _ _ _ _ D1
|
||||
To Disable:
|
||||
YRCALL=_ _ _ _ _ _ D0
|
||||
|
||||
Required software to run the g2_ircddb gateway correctly:
|
||||
--- g2_ircddb: The G2 audio gateway.
|
||||
--- g2_link: This communicates with g2_ircddb to link the local G2 gateway
|
||||
to reflectors. Note: g2_link is NOT required if you only make
|
||||
routing calls or talk locally on the repeater.
|
||||
--- rptr: This is our dstar repeater software that uses a GMSK adapter/modem.
|
||||
Instead of rptr, you can use our dvap_rptr dstar repeater software
|
||||
which uses a DVAP device. Intead of rptr, you can use our dvrptr
|
||||
dstar repeater software which uses the DV-RPTR modem(dg1ht). Intead
|
||||
of rptr, you can use our snd_rptr dstar repeater software which
|
||||
uses a SOUND CARD. You can also use the ICOM's RP2C repeater
|
||||
hardware box.
|
||||
|
||||
ROUTING methods
|
||||
===============
|
||||
Some Dstar routing examples follow. Please do not use the same data because
|
||||
KJ4NHF is one of our own Dstar repeaters, and KI4LKF is a personal callsign
|
||||
in our group.
|
||||
|
||||
Example of ZONE routing:
|
||||
Lets say that your repeater is KJ4NHF, and you are currently on
|
||||
your local repeater module B, your callsign is KI4LKF
|
||||
and you want to reach remote gateway XXNYYY module C
|
||||
In this case, your radio should be programmed like this:
|
||||
MYCALL=KI4LKF
|
||||
YRCALL=/XXNYYYC
|
||||
RPT1=KJ4NHF B
|
||||
RPT2=KJ4NHF G
|
||||
|
||||
Example of CALLSIGN routing:
|
||||
Lets say that your repeater is KJ4NHF, and you are currently on
|
||||
your local repeater module B, your callsign is KI4LKF
|
||||
and you want to talk to user XX0XXX
|
||||
In this case, your radio should be programmed like this:
|
||||
MYCALL=KI4LKF
|
||||
YRCALL=XX0XXX
|
||||
RPT1=KJ4NHF B
|
||||
RPT2=KJ4NHF G
|
||||
|
||||
Example of Cross-Band routing:
|
||||
Lets say that your repeater is KJ4NHF, and you are currently on
|
||||
your local repeater module B, your callsign is KI4LKF
|
||||
and you want to talk from your local module B to your local module C
|
||||
In this case, your radio should be programmed like this:
|
||||
MYCALL=KI4LKF
|
||||
YRCALL=CQCQCQ
|
||||
RPT1=KJ4NHF B
|
||||
RPT2=KJ4NHF C
|
||||
|
||||
DTMF decoding and processing
|
||||
=============================
|
||||
Prepare the software to decode and process DTMF tones
|
||||
-----------------------------------------------------
|
||||
Edit the Shell script proc_g2_ircddb_dtmfs.sh
|
||||
Correct the value for G2 to be the local G2 gateway
|
||||
callsign(same value in g2_ircddb.cfg ----> OWNER)
|
||||
Edit G2_INT_IP as follows:
|
||||
If your g2_ircddb.cfg, says "G2_INTERNAL_IP=0.0.0.0" then set
|
||||
G2_INT_IP=127.0.0.1.
|
||||
If your g2_ircddb, says G2_INTERNAL_IP=<real local IP address>
|
||||
then set G2_INT_IP equal to the exact value of G2_INTERNAL_IP.
|
||||
Edit G2_INT_PORT to be equal to G2_INTERNAL_PORT in g2_ircddb.cfg.
|
||||
|
||||
Note: When local RF user has entered dtmf tones on the Dstar HT
|
||||
and then PTT is released, g2_ircddb will print the whole
|
||||
sequence in the g2_ircddb.log just before it creates the
|
||||
dtmf file under /tmp.
|
||||
|
||||
How to enter DTMF tones correctly on your Dstar HT
|
||||
--------------------------------------------------
|
||||
If you want to have perfect DTMF decoding/processing in g2_ircddb,
|
||||
follow these suggestions:
|
||||
|
||||
1) Hold down each dtmf key for at least 150 milliseconds.
|
||||
2) Leave at least 250 milliseconds of "silence", when you go from
|
||||
one dtmf key to the next dtmf key.
|
||||
|
||||
If you use a DTMF autodialer on your Dstar radio, you can program
|
||||
the above numbers easily into the ICOM's radio "auto-dialer".
|
||||
|
||||
Note: MAXIMUM dtmf sequence is up to 32 dtmf tones.
|
||||
|
||||
What dtmf tones are being decoded and processed
|
||||
-----------------------------------------------
|
||||
To link to an XRF reflector: Example: #02102
|
||||
That says: link to XRF021 module B. So, we use the # dtmf key
|
||||
to mean that we're interested in linking to an XRF reflector. The
|
||||
last two digits are the remote module 01 thru 05 (which is
|
||||
translated to A thru E).
|
||||
|
||||
To link to a DCS reflector: Example: D00126
|
||||
That says: link to DCS001 module Z. So, we use the D dtmf key
|
||||
to mean that we're interested in linking to a DCS reflector. The
|
||||
last two digits are the remote module 01 thru 26 (which is
|
||||
translated to A thru Z).
|
||||
|
||||
To link to REF: Example: *01601
|
||||
That says: link to REF016 module A. So, we use the * dtmf key
|
||||
to mean that we're interested in linking to a REF reflector. The
|
||||
last two digits are the remote module 01 thru 05 (which is
|
||||
translated to A thru E).
|
||||
|
||||
To unlink (from any reflector xrf or ref): 73
|
||||
|
||||
To get the "link status": 99
|
||||
|
||||
Note:
|
||||
You can extend the shell ascript to do more things. like force
|
||||
your repeater to ID itself. Any YRCALL command that can be executed
|
||||
by g2link_test, can be added to the shell script. Basically, the
|
||||
Linux shell script proc_g2_ircddb_dtmfs.sh converts the decoded
|
||||
dtmf tones into YRCALL commands using g2link_test program.
|
||||
|
||||
===========
|
||||
g2_link is a small program that is used to link a local RF repeater
|
||||
band to a remote reflector. g2_link software is used by our g2_ircddb
|
||||
(an IRCddb gateway) and by our g2_ccs (a CCS gateway).
|
||||
|
||||
Before we begin, there are some dat files included in the g2_link
|
||||
ZIP package. These dat files are:
|
||||
|
||||
already_linked.dat
|
||||
already_unlinked.dat
|
||||
failed_linked.dat
|
||||
linked.dat
|
||||
unlinked.dat
|
||||
id.dat
|
||||
|
||||
All of the above dat files are dvtool format files and they are used
|
||||
when certain events take place. For example, when the link between your
|
||||
gateway and a reflector is established, then the file "linked.dat" will
|
||||
be played over RF, so anyone listening on your repeater, will hear the
|
||||
announcement that the link has been established. You do not have to
|
||||
change these files, unless you want to have your own personal voice
|
||||
played over RF. These dat files were created using a computer and they
|
||||
are NOT anyone's voice.
|
||||
|
||||
The only dat file that you should really change is id.dat. The file
|
||||
id.dat contains the audio "UNLINKED" and nothing else. When the gateway
|
||||
is not linked and the RF user sets YRCALL=_______I to request the
|
||||
status of the link, the file id.dat will be played back over RF. But
|
||||
you should create your own id.dat file that should identify your own
|
||||
repeater with extra information if you like.
|
||||
|
||||
For example, you could create your own dvtool audio file that contains
|
||||
the audio: "This is repeater ...". A simple way to create your own
|
||||
recorded "repeater identification file" id.dat is to use your Dstar HT
|
||||
and set YRCALL command: YRCALL=______S0 and key up your repeater.
|
||||
Start talking, and the gateway will record your audio into the file
|
||||
x_voicemail.dat where x is one of A.B or C. Now copy that file into
|
||||
id.dat.
|
||||
|
||||
Open the file g2_link.cfg:
|
||||
Edit the values for LOGIN_CALL, OWNER and ADMIN. LOGIN_CALL is
|
||||
always your PERSONAL callsign. It is used to connect to REF
|
||||
reflectors. (REF reflectors check if the value of LOGIN_CALL is a
|
||||
user callsign registered with UStrust.)
|
||||
|
||||
OWNER is your GATEWAY/club/Repeater callsign. If you do not have a
|
||||
GATEWAY/club/Repeater callsign, you can set OWNER equal to your
|
||||
PERSONAL callsign.
|
||||
|
||||
If you set OWNER to a PERSONAL callsign, then the Gateway config
|
||||
file(g2_ircddb.cfg, g2_ccs.cfg) must also use the same PERSONAL
|
||||
callsign. If you set OWNER to your GATEWAY/club/Repeater callsign,
|
||||
then the Gateway config file(g2_ircddb.cfg, g2_ccs.cfg) must also
|
||||
use the same GATEWAY/club/Repeater callsign.
|
||||
|
||||
You can add as many lines to gwys.txt, if you know of any other
|
||||
reflectors that you want to be able to connect to. REF reflectors
|
||||
use port 20001(for USER connections), DCS reflectors use port
|
||||
30051 and XRF reflectors use either 30001(for Repeater linking)
|
||||
or 20001(for USER connections).
|
||||
|
||||
You can have as many ADMIN lines as you want. ADMIN is user
|
||||
callsign that can connect to your own gateway(g2_link) using
|
||||
DVTool, ...
|
||||
|
||||
Note:
|
||||
The zip file g2_lh conatain a small program that you can run to create
|
||||
the Dashboard for your gateway.
|
||||
|
||||
Note:
|
||||
You may be thinking why did we put all this source code inside g2_link
|
||||
instead of putting it all inside the Gateway software g2_ircddb (or
|
||||
g2_ccs CCS gateway software). Because it is NOT a good design to burden
|
||||
the G2 gateway with code that is not DSTAR protocol and reflectors are
|
||||
NOT part of Dstar and they are not Dstar protocol.
|
||||
|
||||
The only code that should be in a gateway, is G2 protocol code. This way
|
||||
we keep the gateways (g2_ircddb, g2_ccs) clean of any unneccesary source
|
||||
code logic and containing only pure G2/dstar logic.
|
||||
@ -0,0 +1,54 @@
|
||||
/*
|
||||
|
||||
CIRCDDB - ircDDB client library in C++
|
||||
|
||||
Copyright (C) 2010 Michael Dirska, DL1BFF (dl1bff@mdx.de)
|
||||
|
||||
This program 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, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#if !defined(_IRCAPPLICATION_H)
|
||||
#define _IRCAPPLICATION_H
|
||||
|
||||
#include <wx/wx.h>
|
||||
|
||||
#include "IRCMessageQueue.h"
|
||||
|
||||
class IRCApplication
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void userJoin (const wxString& nick, const wxString& name, const wxString& host) = 0;
|
||||
virtual void userLeave (const wxString& nick) = 0;
|
||||
virtual void userChanOp (const wxString& nick, bool op) = 0;
|
||||
virtual void userListReset(void) = 0;
|
||||
|
||||
virtual void msgChannel (IRCMessage * m) = 0;
|
||||
virtual void msgQuery (IRCMessage * m) = 0;
|
||||
|
||||
virtual void setCurrentNick(const wxString& nick) = 0;
|
||||
virtual void setTopic(const wxString& topic) = 0;
|
||||
|
||||
virtual void setBestServer(const wxString& ircUser) = 0;
|
||||
|
||||
virtual void setSendQ( IRCMessageQueue * s ) = 0;
|
||||
virtual IRCMessageQueue * getSendQ (void) = 0;
|
||||
|
||||
virtual ~IRCApplication() {}
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,512 @@
|
||||
/*
|
||||
|
||||
CIRCDDB - ircDDB client library in C++
|
||||
|
||||
Copyright (C) 2010-2011 Michael Dirska, DL1BFF (dl1bff@mdx.de)
|
||||
|
||||
This program 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, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#if defined(WIN32)
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
#else
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include "IRCClient.h"
|
||||
#include "IRCutils.h"
|
||||
|
||||
#include <wx/wx.h>
|
||||
|
||||
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
IRCClient::IRCClient( IRCApplication * app, const wxString& update_channel,
|
||||
const wxString& hostName, unsigned int port, const wxString& callsign, const wxString& password,
|
||||
const wxString& versionInfo, const wxString& localAddr )
|
||||
: wxThread(wxTHREAD_JOINABLE)
|
||||
{
|
||||
safeStringCopy(host_name, hostName.mb_str(), sizeof host_name);
|
||||
|
||||
this -> callsign = callsign.Lower();
|
||||
this -> port = port;
|
||||
this -> password = password;
|
||||
|
||||
this -> app = app;
|
||||
|
||||
if (localAddr.IsEmpty())
|
||||
{
|
||||
safeStringCopy(local_addr, "0.0.0.0", sizeof local_addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
safeStringCopy(local_addr, localAddr.mb_str(), sizeof local_addr);
|
||||
}
|
||||
|
||||
proto = new IRCProtocol ( app, this->callsign, password, update_channel, versionInfo );
|
||||
|
||||
recvQ = NULL;
|
||||
sendQ = NULL;
|
||||
|
||||
recv = NULL;
|
||||
}
|
||||
|
||||
IRCClient::~IRCClient()
|
||||
{
|
||||
delete proto;
|
||||
}
|
||||
|
||||
bool IRCClient::startWork()
|
||||
{
|
||||
|
||||
if (Create() != wxTHREAD_NO_ERROR)
|
||||
{
|
||||
wxLogError(wxT("IRCClient::startWork: Could not create the worker thread!"));
|
||||
return false;
|
||||
}
|
||||
|
||||
terminateThread = false;
|
||||
|
||||
if (Run() != wxTHREAD_NO_ERROR)
|
||||
{
|
||||
wxLogError(wxT("IRCClient::startWork: Could not run the worker thread!"));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void IRCClient::stopWork()
|
||||
{
|
||||
terminateThread = true;
|
||||
|
||||
Wait();
|
||||
}
|
||||
|
||||
wxThread::ExitCode IRCClient::Entry ()
|
||||
{
|
||||
|
||||
unsigned int numAddr;
|
||||
|
||||
#define MAXIPV4ADDR 10
|
||||
struct sockaddr_in addr[MAXIPV4ADDR];
|
||||
|
||||
struct sockaddr_in myaddr;
|
||||
|
||||
int state = 0;
|
||||
int timer = 0;
|
||||
int sock = 0;
|
||||
unsigned int currentAddr = 0;
|
||||
|
||||
int result;
|
||||
|
||||
|
||||
numAddr = 0;
|
||||
|
||||
result = getAllIPV4Addresses(local_addr, 0, &numAddr, &myaddr, 1);
|
||||
|
||||
if ((result != 0) || (numAddr != 1))
|
||||
{
|
||||
wxLogVerbose(wxT("IRCClient::Entry: local address not parseable, using 0.0.0.0"));
|
||||
memset(&myaddr, 0x00, sizeof(struct sockaddr_in));
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
|
||||
if (timer > 0)
|
||||
{
|
||||
timer --;
|
||||
}
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case 0:
|
||||
if (terminateThread)
|
||||
{
|
||||
wxLogVerbose(wxT("IRCClient::Entry: thread terminated at state=%d"), state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (timer == 0)
|
||||
{
|
||||
timer = 30;
|
||||
|
||||
if (getAllIPV4Addresses(host_name, port, &numAddr, addr, MAXIPV4ADDR) == 0)
|
||||
{
|
||||
wxLogVerbose(wxT("IRCClient::Entry: number of DNS entries %d"), numAddr);
|
||||
if (numAddr > 0)
|
||||
{
|
||||
currentAddr = 0;
|
||||
state = 1;
|
||||
timer = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if (terminateThread)
|
||||
{
|
||||
wxLogVerbose(wxT("IRCClient::Entry: thread terminated at state=%d"), state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (timer == 0)
|
||||
{
|
||||
sock = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
|
||||
if (sock < 0)
|
||||
{
|
||||
wxLogSysError(wxT("IRCClient::Entry: socket"));
|
||||
timer = 30;
|
||||
state = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined(__WINDOWS__)
|
||||
u_long nonBlock = 1UL;
|
||||
if (ioctlsocket( sock, FIONBIO, &nonBlock ) != 0)
|
||||
{
|
||||
wxLogSysError(wxT("IRCClient::Entry: ioctlsocket"));
|
||||
closesocket(sock);
|
||||
timer = 30;
|
||||
state = 0;
|
||||
}
|
||||
#else
|
||||
if (fcntl( sock, F_SETFL, O_NONBLOCK ) < 0)
|
||||
{
|
||||
wxLogSysError(wxT("IRCClient::Entry: fcntl"));
|
||||
close(sock);
|
||||
timer = 30;
|
||||
state = 0;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
unsigned char * h = (unsigned char *) &(myaddr.sin_addr);
|
||||
int res;
|
||||
|
||||
if ((h[0] != 0) || (h[1] != 0) || (h[2] != 0) || (h[3] != 0))
|
||||
{
|
||||
wxLogVerbose(wxT("IRCClient::Entry: bind: local address %d.%d.%d.%d"),
|
||||
h[0], h[1], h[2], h[3]);
|
||||
}
|
||||
|
||||
res = bind(sock, (struct sockaddr *) &myaddr, sizeof (struct sockaddr_in));
|
||||
|
||||
if (res != 0)
|
||||
{
|
||||
|
||||
wxLogSysError(wxT("IRCClient::Entry: bind"));
|
||||
#if defined(__WINDOWS__)
|
||||
closesocket(sock);
|
||||
#else
|
||||
close(sock);
|
||||
#endif
|
||||
state = 0;
|
||||
timer = 30;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
h = (unsigned char *) &(addr[currentAddr].sin_addr);
|
||||
wxLogVerbose(wxT("IRCClient::Entry: trying to connect to %d.%d.%d.%d"),
|
||||
h[0], h[1], h[2], h[3]);
|
||||
|
||||
res = connect(sock, (struct sockaddr *) (addr + currentAddr), sizeof (struct sockaddr_in));
|
||||
|
||||
if (res == 0)
|
||||
{
|
||||
wxLogVerbose(wxT("IRCClient::Entry: connected"));
|
||||
state = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined(__WINDOWS__)
|
||||
if (WSAGetLastError() == WSAEWOULDBLOCK)
|
||||
#else
|
||||
if (errno == EINPROGRESS)
|
||||
#endif
|
||||
{
|
||||
wxLogVerbose(wxT("IRCClient::Entry: connect in progress"));
|
||||
state = 3;
|
||||
timer = 10; // 5 second timeout
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogSysError(wxT("IRCClient::Entry: connect"));
|
||||
#if defined(__WINDOWS__)
|
||||
closesocket(sock);
|
||||
#else
|
||||
close(sock);
|
||||
#endif
|
||||
currentAddr ++;
|
||||
if (currentAddr >= numAddr)
|
||||
{
|
||||
state = 0;
|
||||
timer = 30;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = 1;
|
||||
timer = 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // connect
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
{
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
fd_set myset;
|
||||
FD_ZERO(&myset);
|
||||
FD_SET(sock, &myset);
|
||||
int res;
|
||||
res = select(sock+1, NULL, &myset, NULL, &tv);
|
||||
|
||||
if (res < 0)
|
||||
{
|
||||
wxLogSysError(wxT("IRCClient::Entry: select"));
|
||||
#if defined(__WINDOWS__)
|
||||
closesocket(sock);
|
||||
#else
|
||||
close(sock);
|
||||
#endif
|
||||
state = 0;
|
||||
timer = 30;
|
||||
}
|
||||
else if (res > 0) // connect is finished
|
||||
{
|
||||
#if defined(__WINDOWS__)
|
||||
int val_len;
|
||||
#else
|
||||
socklen_t val_len;
|
||||
#endif
|
||||
int value;
|
||||
|
||||
val_len = sizeof value;
|
||||
|
||||
if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *) &value, &val_len) < 0)
|
||||
{
|
||||
wxLogSysError(wxT("IRCClient::Entry: getsockopt"));
|
||||
#if defined(__WINDOWS__)
|
||||
closesocket(sock);
|
||||
#else
|
||||
close(sock);
|
||||
#endif
|
||||
state = 0;
|
||||
timer = 30;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (value != 0)
|
||||
{
|
||||
wxLogWarning(wxT("IRCClient::Entry: SO_ERROR=%d"), value);
|
||||
#if defined(__WINDOWS__)
|
||||
closesocket(sock);
|
||||
#else
|
||||
close(sock);
|
||||
#endif
|
||||
currentAddr ++;
|
||||
if (currentAddr >= numAddr)
|
||||
{
|
||||
state = 0;
|
||||
timer = 30;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = 1;
|
||||
timer = 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogVerbose(wxT("IRCClient::Entry: connected2"));
|
||||
state = 4;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else if (timer == 0)
|
||||
{ // select timeout and timer timeout
|
||||
wxLogVerbose(wxT("IRCClient::Entry: connect timeout"));
|
||||
#if defined(__WINDOWS__)
|
||||
closesocket(sock);
|
||||
#else
|
||||
close(sock);
|
||||
#endif
|
||||
currentAddr ++;
|
||||
if (currentAddr >= numAddr)
|
||||
{
|
||||
state = 0;
|
||||
timer = 30;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = 1; // open new socket
|
||||
timer = 2;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
{
|
||||
recvQ = new IRCMessageQueue();
|
||||
sendQ = new IRCMessageQueue();
|
||||
|
||||
recv = new IRCReceiver(sock, recvQ);
|
||||
recv->startWork();
|
||||
|
||||
proto->setNetworkReady(true);
|
||||
state = 5;
|
||||
timer = 0;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 5:
|
||||
if (terminateThread)
|
||||
{
|
||||
state = 6;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if (recvQ -> isEOF())
|
||||
{
|
||||
timer = 0;
|
||||
state = 6;
|
||||
}
|
||||
else if (proto -> processQueues(recvQ, sendQ) == false)
|
||||
{
|
||||
timer = 0;
|
||||
state = 6;
|
||||
}
|
||||
|
||||
while ((state == 5) && sendQ->messageAvailable())
|
||||
{
|
||||
IRCMessage * m = sendQ -> getMessage();
|
||||
|
||||
wxString out;
|
||||
|
||||
m -> composeMessage ( out );
|
||||
|
||||
char buf[200];
|
||||
safeStringCopy(buf, out.mb_str(wxConvUTF8), sizeof buf);
|
||||
int len = strlen(buf);
|
||||
|
||||
if (buf[len - 1] == 10) // is there a NL char at the end?
|
||||
{
|
||||
int r = send(sock, buf, len, 0);
|
||||
|
||||
if (r != len)
|
||||
{
|
||||
wxLogVerbose(wxT("IRCClient::Entry: short write %d < %d"), r, len);
|
||||
|
||||
timer = 0;
|
||||
state = 6;
|
||||
}
|
||||
/* else
|
||||
{
|
||||
wxLogVerbose(wxT("write %d bytes (") + out + wxT(")"), len );
|
||||
} */
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogVerbose(wxT("IRCClient::Entry: no NL at end, len=%d"), len);
|
||||
|
||||
timer = 0;
|
||||
state = 6;
|
||||
}
|
||||
|
||||
delete m;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 6:
|
||||
{
|
||||
if (app != NULL)
|
||||
{
|
||||
app->setSendQ(NULL);
|
||||
app->userListReset();
|
||||
}
|
||||
|
||||
proto->setNetworkReady(false);
|
||||
recv->stopWork();
|
||||
|
||||
wxThread::Sleep(2000);
|
||||
|
||||
delete recv;
|
||||
delete recvQ;
|
||||
delete sendQ;
|
||||
|
||||
#if defined(__WINDOWS__)
|
||||
closesocket(sock);
|
||||
#else
|
||||
close(sock);
|
||||
#endif
|
||||
|
||||
if (terminateThread) // request to end the thread
|
||||
{
|
||||
wxLogVerbose(wxT("IRCClient::Entry: thread terminated at state=%d"), state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
timer = 30;
|
||||
state = 0; // reconnect to IRC server
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
wxThread::Sleep(500);
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,76 @@
|
||||
/*
|
||||
|
||||
CIRCDDB - ircDDB client library in C++
|
||||
|
||||
Copyright (C) 2010-2011 Michael Dirska, DL1BFF (dl1bff@mdx.de)
|
||||
|
||||
This program 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, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#if !defined(_IRCCLIENT_H)
|
||||
#define _IRCCLIENT_H
|
||||
|
||||
#include "IRCReceiver.h"
|
||||
#include "IRCMessageQueue.h"
|
||||
#include "IRCProtocol.h"
|
||||
#include "IRCApplication.h"
|
||||
|
||||
#include <wx/wx.h>
|
||||
|
||||
|
||||
class IRCClient : public wxThread
|
||||
{
|
||||
public:
|
||||
|
||||
IRCClient( IRCApplication * app, const wxString& update_channel,
|
||||
const wxString& hostName, unsigned int port, const wxString& callsign, const wxString& password,
|
||||
const wxString& versionInfo, const wxString& localAddr );
|
||||
|
||||
~IRCClient();
|
||||
|
||||
|
||||
bool startWork();
|
||||
|
||||
void stopWork();
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
virtual wxThread::ExitCode Entry();
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
char host_name[100];
|
||||
char local_addr[100];
|
||||
unsigned int port;
|
||||
wxString callsign;
|
||||
wxString password;
|
||||
|
||||
bool terminateThread;
|
||||
|
||||
IRCReceiver * recv;
|
||||
IRCMessageQueue * recvQ;
|
||||
IRCMessageQueue * sendQ;
|
||||
IRCProtocol * proto;
|
||||
|
||||
IRCApplication * app;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,478 @@
|
||||
/*
|
||||
|
||||
CIRCDDB - ircDDB client library in C++
|
||||
|
||||
Copyright (C) 2010-2011 Michael Dirska, DL1BFF (dl1bff@mdx.de)
|
||||
|
||||
This program 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, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "IRCDDB.h"
|
||||
|
||||
#include "IRCClient.h"
|
||||
#include "IRCDDBApp.h"
|
||||
|
||||
#include <wx/wx.h>
|
||||
|
||||
|
||||
struct CIRCDDBPrivate
|
||||
{
|
||||
IRCClient * client;
|
||||
IRCDDBApp * app;
|
||||
};
|
||||
|
||||
|
||||
CIRCDDB::CIRCDDB(const wxString& hostName, unsigned int port,
|
||||
const wxString& callsign, const wxString& password,
|
||||
const wxString& versionInfo, const wxString& localAddr ) : d( new CIRCDDBPrivate )
|
||||
|
||||
{
|
||||
wxString update_channel = wxT("#dstar");
|
||||
|
||||
d->app = new IRCDDBApp(update_channel);
|
||||
|
||||
d->client = new IRCClient( d->app, update_channel, hostName, port, callsign,
|
||||
password, versionInfo, localAddr );
|
||||
}
|
||||
|
||||
CIRCDDB::~CIRCDDB()
|
||||
{
|
||||
delete d->client;
|
||||
delete d->app;
|
||||
delete d;
|
||||
}
|
||||
|
||||
|
||||
// A false return implies a network error, or unable to log in
|
||||
bool CIRCDDB::open()
|
||||
{
|
||||
wxLogVerbose(wxT("start"));
|
||||
return d->client -> startWork() && d->app->startWork();
|
||||
}
|
||||
|
||||
|
||||
int CIRCDDB::getConnectionState()
|
||||
{
|
||||
return d->app->getConnectionState();
|
||||
}
|
||||
|
||||
|
||||
void CIRCDDB::rptrQTH( double latitude, double longitude, const wxString& desc1,
|
||||
const wxString& desc2, const wxString& infoURL )
|
||||
{
|
||||
d->app->rptrQTH(latitude, longitude, desc1, desc2, infoURL);
|
||||
}
|
||||
|
||||
|
||||
void CIRCDDB::rptrQRG( const wxString& module, double txFrequency, double duplexShift,
|
||||
double range, double agl )
|
||||
{
|
||||
d->app->rptrQRG(module, txFrequency, duplexShift, range, agl);
|
||||
}
|
||||
|
||||
|
||||
void CIRCDDB::kickWatchdog ( const wxString& wdInfo )
|
||||
{
|
||||
d->app->kickWatchdog( wdInfo );
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Send heard data, a false return implies a network error
|
||||
bool CIRCDDB::sendHeard( const wxString& myCall, const wxString& myCallExt,
|
||||
const wxString& yourCall, const wxString& rpt1,
|
||||
const wxString& rpt2, unsigned char flag1,
|
||||
unsigned char flag2, unsigned char flag3 )
|
||||
{
|
||||
if (myCall.Len() != 8)
|
||||
{
|
||||
wxLogVerbose(wxT("CIRCDDB::sendHeard:myCall: len != 8"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (myCallExt.Len() != 4)
|
||||
{
|
||||
wxLogVerbose(wxT("CIRCDDB::sendHeard:myCallExt: len != 4"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (yourCall.Len() != 8)
|
||||
{
|
||||
wxLogVerbose(wxT("CIRCDDB::sendHeard:yourCall: len != 8"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rpt1.Len() != 8)
|
||||
{
|
||||
wxLogVerbose(wxT("CIRCDDB::sendHeard:rpt1: len != 8"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rpt2.Len() != 8)
|
||||
{
|
||||
wxLogVerbose(wxT("CIRCDDB::sendHeard:rpt2: len != 8"));
|
||||
return false;
|
||||
}
|
||||
|
||||
return d->app->sendHeard( myCall, myCallExt, yourCall, rpt1, rpt2, flag1, flag2, flag3,
|
||||
wxT(" "), wxT(""), wxT(""));
|
||||
}
|
||||
|
||||
|
||||
// Send heard data, a false return implies a network error
|
||||
bool CIRCDDB::sendHeardWithTXMsg( const wxString& myCall, const wxString& myCallExt,
|
||||
const wxString& yourCall, const wxString& rpt1,
|
||||
const wxString& rpt2, unsigned char flag1,
|
||||
unsigned char flag2, unsigned char flag3,
|
||||
const wxString& network_destination,
|
||||
const wxString& tx_message )
|
||||
{
|
||||
if (myCall.Len() != 8)
|
||||
{
|
||||
wxLogVerbose(wxT("CIRCDDB::sendHeard:myCall: len != 8"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (myCallExt.Len() != 4)
|
||||
{
|
||||
wxLogVerbose(wxT("CIRCDDB::sendHeard:myCallExt: len != 4"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (yourCall.Len() != 8)
|
||||
{
|
||||
wxLogVerbose(wxT("CIRCDDB::sendHeard:yourCall: len != 8"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rpt1.Len() != 8)
|
||||
{
|
||||
wxLogVerbose(wxT("CIRCDDB::sendHeard:rpt1: len != 8"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rpt2.Len() != 8)
|
||||
{
|
||||
wxLogVerbose(wxT("CIRCDDB::sendHeard:rpt2: len != 8"));
|
||||
return false;
|
||||
}
|
||||
|
||||
wxString dest = network_destination;
|
||||
|
||||
if (dest.Len() == 0)
|
||||
{
|
||||
dest = wxT(" ");
|
||||
}
|
||||
|
||||
if (dest.Len() != 8)
|
||||
{
|
||||
wxLogVerbose(wxT("CIRCDDB::sendHeard:network_destination: len != 8"));
|
||||
return false;
|
||||
}
|
||||
|
||||
wxString msg;
|
||||
|
||||
if (tx_message.Len() == 20)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i=0; i < tx_message.Len(); i++)
|
||||
{
|
||||
wxChar ch = tx_message.GetChar(i);
|
||||
|
||||
if ((ch > 32) && (ch < 127))
|
||||
{
|
||||
msg.Append(ch);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg.Append(wxT('_'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return d->app->sendHeard( myCall, myCallExt, yourCall, rpt1, rpt2, flag1, flag2, flag3,
|
||||
dest, msg, wxT(""));
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool CIRCDDB::sendHeardWithTXStats( const wxString& myCall, const wxString& myCallExt,
|
||||
const wxString& yourCall, const wxString& rpt1,
|
||||
const wxString& rpt2, unsigned char flag1,
|
||||
unsigned char flag2, unsigned char flag3,
|
||||
int num_dv_frames,
|
||||
int num_dv_silent_frames,
|
||||
int num_bit_errors )
|
||||
{
|
||||
if ((num_dv_frames <= 0) || (num_dv_frames > 65535))
|
||||
{
|
||||
wxLogVerbose(wxT("CIRCDDB::sendHeard:num_dv_frames not in range 1-65535"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (num_dv_silent_frames > num_dv_frames)
|
||||
{
|
||||
wxLogVerbose(wxT("CIRCDDB::sendHeard:num_dv_silent_frames > num_dv_frames"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (num_bit_errors > (4*num_dv_frames)) // max 4 bit errors per frame
|
||||
{
|
||||
wxLogVerbose(wxT("CIRCDDB::sendHeard:num_bit_errors > (4*num_dv_frames)"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (myCall.Len() != 8)
|
||||
{
|
||||
wxLogVerbose(wxT("CIRCDDB::sendHeard:myCall: len != 8"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (myCallExt.Len() != 4)
|
||||
{
|
||||
wxLogVerbose(wxT("CIRCDDB::sendHeard:myCallExt: len != 4"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (yourCall.Len() != 8)
|
||||
{
|
||||
wxLogVerbose(wxT("CIRCDDB::sendHeard:yourCall: len != 8"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rpt1.Len() != 8)
|
||||
{
|
||||
wxLogVerbose(wxT("CIRCDDB::sendHeard:rpt1: len != 8"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rpt2.Len() != 8)
|
||||
{
|
||||
wxLogVerbose(wxT("CIRCDDB::sendHeard:rpt2: len != 8"));
|
||||
return false;
|
||||
}
|
||||
|
||||
wxString stats = wxString::Format(wxT("%04x"), num_dv_frames);
|
||||
|
||||
if (num_dv_silent_frames >= 0)
|
||||
{
|
||||
wxString s = wxString::Format(wxT("%02x"), (num_dv_silent_frames * 100) / num_dv_frames);
|
||||
stats.Append(s);
|
||||
|
||||
if (num_bit_errors >= 0)
|
||||
{
|
||||
s = wxString::Format(wxT("%02x"), (num_bit_errors * 125) / (num_dv_frames * 3));
|
||||
stats.Append(s);
|
||||
}
|
||||
else
|
||||
{
|
||||
stats.Append(wxT("__"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
stats.Append(wxT("____"));
|
||||
}
|
||||
|
||||
stats.Append(wxT("____________")); // stats string should have 20 chars
|
||||
|
||||
return d->app->sendHeard( myCall, myCallExt, yourCall, rpt1, rpt2, flag1, flag2, flag3,
|
||||
wxT(" "), wxT(""), stats);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Send query for a gateway/reflector, a false return implies a network error
|
||||
bool CIRCDDB::findGateway(const wxString& gatewayCallsign)
|
||||
{
|
||||
if (gatewayCallsign.Len() != 8)
|
||||
{
|
||||
wxLogVerbose(wxT("CIRCDDB::findGateway: len != 8"));
|
||||
return false;
|
||||
}
|
||||
|
||||
return d->app->findGateway( gatewayCallsign.Upper());
|
||||
}
|
||||
|
||||
|
||||
bool CIRCDDB::findRepeater(const wxString& repeaterCallsign)
|
||||
{
|
||||
if (repeaterCallsign.Len() != 8)
|
||||
{
|
||||
wxLogVerbose(wxT("CIRCDDB::findRepeater: len != 8"));
|
||||
return false;
|
||||
}
|
||||
|
||||
return d->app->findRepeater( repeaterCallsign.Upper());
|
||||
}
|
||||
|
||||
// Send query for a user, a false return implies a network error
|
||||
bool CIRCDDB::findUser(const wxString& userCallsign)
|
||||
{
|
||||
if (userCallsign.Len() != 8)
|
||||
{
|
||||
wxLogVerbose(wxT("CIRCDDB::findUser: len != 8"));
|
||||
return false;
|
||||
}
|
||||
|
||||
return d->app->findUser( userCallsign.Upper());
|
||||
}
|
||||
|
||||
// The following functions are for processing received messages
|
||||
|
||||
// Get the waiting message type
|
||||
IRCDDB_RESPONSE_TYPE CIRCDDB::getMessageType()
|
||||
{
|
||||
return d->app->getReplyMessageType();
|
||||
}
|
||||
|
||||
// Get a gateway message, as a result of IDRT_REPEATER returned from getMessageType()
|
||||
// A false return implies a network error
|
||||
bool CIRCDDB::receiveRepeater(wxString& repeaterCallsign, wxString& gatewayCallsign, wxString& address, DSTAR_PROTOCOL& protocol)
|
||||
{
|
||||
IRCDDB_RESPONSE_TYPE rt = d->app->getReplyMessageType();
|
||||
|
||||
if (rt != IDRT_REPEATER)
|
||||
{
|
||||
wxLogError(wxT("CIRCDDB::receiveRepeater: unexpected response type"));
|
||||
return false;
|
||||
}
|
||||
|
||||
IRCMessage * m = d->app->getReplyMessage();
|
||||
|
||||
if (m == NULL)
|
||||
{
|
||||
wxLogError(wxT("CIRCDDB::receiveRepeater: no message"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m->getCommand().IsSameAs(wxT("IDRT_REPEATER")))
|
||||
{
|
||||
wxLogError(wxT("CIRCDDB::receiveRepeater: wrong message type"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m->getParamCount() != 3)
|
||||
{
|
||||
wxLogError(wxT("CIRCDDB::receiveRepeater: unexpected number of message parameters"));
|
||||
return false;
|
||||
}
|
||||
|
||||
repeaterCallsign = m->getParam(0);
|
||||
gatewayCallsign = m->getParam(1);
|
||||
address = m->getParam(2);
|
||||
|
||||
delete m;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get a gateway message, as a result of IDRT_GATEWAY returned from getMessageType()
|
||||
// A false return implies a network error
|
||||
bool CIRCDDB::receiveGateway(wxString& gatewayCallsign, wxString& address, DSTAR_PROTOCOL& protocol)
|
||||
{
|
||||
IRCDDB_RESPONSE_TYPE rt = d->app->getReplyMessageType();
|
||||
|
||||
if (rt != IDRT_GATEWAY)
|
||||
{
|
||||
wxLogError(wxT("CIRCDDB::receiveGateway: unexpected response type"));
|
||||
return false;
|
||||
}
|
||||
|
||||
IRCMessage * m = d->app->getReplyMessage();
|
||||
|
||||
if (m == NULL)
|
||||
{
|
||||
wxLogError(wxT("CIRCDDB::receiveGateway: no message"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m->getCommand().IsSameAs(wxT("IDRT_GATEWAY")))
|
||||
{
|
||||
wxLogError(wxT("CIRCDDB::receiveGateway: wrong message type"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m->getParamCount() != 2)
|
||||
{
|
||||
wxLogError(wxT("CIRCDDB::receiveGateway: unexpected number of message parameters"));
|
||||
return false;
|
||||
}
|
||||
|
||||
gatewayCallsign = m->getParam(0);
|
||||
address = m->getParam(1);
|
||||
|
||||
delete m;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get a user message, as a result of IDRT_USER returned from getMessageType()
|
||||
// A false return implies a network error
|
||||
bool CIRCDDB::receiveUser(wxString& userCallsign, wxString& repeaterCallsign, wxString& gatewayCallsign, wxString& address)
|
||||
{
|
||||
wxString dummy;
|
||||
return receiveUser(userCallsign, repeaterCallsign, gatewayCallsign, address, dummy);
|
||||
}
|
||||
|
||||
bool CIRCDDB::receiveUser(wxString& userCallsign, wxString& repeaterCallsign, wxString& gatewayCallsign, wxString& address,
|
||||
wxString& timeStamp)
|
||||
{
|
||||
IRCDDB_RESPONSE_TYPE rt = d->app->getReplyMessageType();
|
||||
|
||||
if (rt != IDRT_USER)
|
||||
{
|
||||
wxLogError(wxT("CIRCDDB::receiveUser: unexpected response type"));
|
||||
return false;
|
||||
}
|
||||
|
||||
IRCMessage * m = d->app->getReplyMessage();
|
||||
|
||||
if (m == NULL)
|
||||
{
|
||||
wxLogError(wxT("CIRCDDB::receiveUser: no message"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m->getCommand().IsSameAs(wxT("IDRT_USER")))
|
||||
{
|
||||
wxLogError(wxT("CIRCDDB::receiveUser: wrong message type"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m->getParamCount() != 5)
|
||||
{
|
||||
wxLogError(wxT("CIRCDDB::receiveUser: unexpected number of message parameters"));
|
||||
return false;
|
||||
}
|
||||
|
||||
userCallsign = m->getParam(0);
|
||||
repeaterCallsign = m->getParam(1);
|
||||
gatewayCallsign = m->getParam(2);
|
||||
address = m->getParam(3);
|
||||
timeStamp = m->getParam(4);
|
||||
|
||||
delete m;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CIRCDDB::close() // Implictely kills any threads in the IRC code
|
||||
{
|
||||
d->client -> stopWork();
|
||||
d->app -> stopWork();
|
||||
}
|
||||
|
||||
@ -0,0 +1,173 @@
|
||||
/*
|
||||
|
||||
CIRCDDB - ircDDB client library in C++
|
||||
|
||||
Copyright (C) 2010-2011 Michael Dirska, DL1BFF (dl1bff@mdx.de)
|
||||
|
||||
This program 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, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#if !defined(_IRCDDB_H)
|
||||
#define _IRCDDB_H
|
||||
|
||||
#include <wx/wx.h>
|
||||
|
||||
enum IRCDDB_RESPONSE_TYPE {
|
||||
IDRT_NONE,
|
||||
IDRT_USER,
|
||||
IDRT_GATEWAY,
|
||||
IDRT_REPEATER
|
||||
};
|
||||
|
||||
enum DSTAR_PROTOCOL {
|
||||
DP_UNKNOWN,
|
||||
DP_DEXTRA,
|
||||
DP_DPLUS
|
||||
};
|
||||
|
||||
|
||||
struct CIRCDDBPrivate;
|
||||
|
||||
class CIRCDDB {
|
||||
public:
|
||||
CIRCDDB(const wxString& hostName, unsigned int port, const wxString& callsign, const wxString& password,
|
||||
const wxString& versionInfo, const wxString& localAddr = wxEmptyString );
|
||||
~CIRCDDB();
|
||||
|
||||
// A false return implies a network error, or unable to log in
|
||||
bool open();
|
||||
|
||||
|
||||
// rptrQTH can be called multiple times if necessary
|
||||
// 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 );
|
||||
|
||||
|
||||
|
||||
// rptrQRG can be called multiple times if necessary
|
||||
// module letter of the module, valid values: "A", "B", "C", "D", "AD", "BD", "CD", "DD"
|
||||
// txFrequency repeater TX frequency in MHz
|
||||
// duplexShift duplex shift in MHz (positive or negative value): RX_freq = txFrequency + duplexShift
|
||||
// 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 );
|
||||
|
||||
|
||||
// If you call this method once, watchdog messages will be sent to the
|
||||
// to the ircDDB network every 15 minutes. Invoke this method every 1-2 minutes to indicate
|
||||
// that the gateway is working properly. After activating the watchdog, a red LED will be displayed
|
||||
// on the ircDDB web page if this method is not called within a period of about 30 minutes.
|
||||
// The string wdInfo should contain information about the source of the alive messages, e.g.,
|
||||
// version of the RF decoding software. For example, the ircDDB java software sets this
|
||||
// to "rpm_ircddbmhd-x.z-z". The string wdInfo must contain at least one non-space character.
|
||||
|
||||
void kickWatchdog(const wxString& wdInfo);
|
||||
|
||||
|
||||
|
||||
// get internal network status
|
||||
int getConnectionState();
|
||||
// one of these values is returned:
|
||||
// 0 = not (yet) connected to the IRC server
|
||||
// 1-6 = a new connection was established, download of repeater info etc. is
|
||||
// in progress
|
||||
// 7 = the ircDDB connection is fully operational
|
||||
// 10 = some network error occured, next state is "0" (new connection attempt)
|
||||
|
||||
// Send heard data, a false return implies a network error
|
||||
bool sendHeard(const wxString& myCall, const wxString& myCallExt,
|
||||
const wxString& yourCall, const wxString& rpt1,
|
||||
const wxString& rpt2, unsigned char flag1,
|
||||
unsigned char flag2, unsigned char flag3 );
|
||||
|
||||
|
||||
// same as sendHeard with two new fields:
|
||||
// network_destination: empty string or 8-char call sign of the repeater
|
||||
// or reflector, where this transmission is relayed to.
|
||||
// tx_message: 20-char TX message or empty string, if the user did not
|
||||
// send a TX message
|
||||
bool sendHeardWithTXMsg(const wxString& myCall, const wxString& myCallExt,
|
||||
const wxString& yourCall, const wxString& rpt1,
|
||||
const wxString& rpt2, unsigned char flag1,
|
||||
unsigned char flag2, unsigned char flag3,
|
||||
const wxString& network_destination,
|
||||
const wxString& tx_message );
|
||||
|
||||
// this method should be called at the end of a transmission
|
||||
// num_dv_frames: number of DV frames sent out (96 bit frames, 20ms)
|
||||
// num_dv_silent_frames: number of DV silence frames sent out in the
|
||||
// last transmission, or -1 if the information is not available
|
||||
// num_bit_errors: number of bit errors of the received data. This should
|
||||
// be the derived from the first Golay block of the voice data. This
|
||||
// error correction code only looks at 24 bits of the 96 bit frame.
|
||||
// So, the overall bit error rate is calculated like this:
|
||||
// BER = num_bit_errors / (num_dv_frames * 24)
|
||||
// Set num_bit_errors = -1, if the error information is not available.
|
||||
bool sendHeardWithTXStats(const wxString& myCall, const wxString& myCallExt,
|
||||
const wxString& yourCall, const wxString& rpt1,
|
||||
const wxString& rpt2, unsigned char flag1,
|
||||
unsigned char flag2, unsigned char flag3,
|
||||
int num_dv_frames,
|
||||
int num_dv_silent_frames,
|
||||
int num_bit_errors );
|
||||
|
||||
// The following three functions don't block waiting for a reply, they just send the data
|
||||
|
||||
// Send query for a gateway/reflector, a false return implies a network error
|
||||
bool findGateway(const wxString& gatewayCallsign);
|
||||
|
||||
// Send query for a repeater module, a false return implies a network error
|
||||
bool findRepeater(const wxString& repeaterCallsign);
|
||||
|
||||
// Send query for a user, a false return implies a network error
|
||||
bool findUser(const wxString& userCallsign);
|
||||
|
||||
// The following functions are for processing received messages
|
||||
|
||||
// Get the waiting message type
|
||||
IRCDDB_RESPONSE_TYPE getMessageType();
|
||||
|
||||
// Get a gateway message, as a result of IDRT_REPEATER returned from getMessageType()
|
||||
// A false return implies a network error
|
||||
bool receiveRepeater(wxString& repeaterCallsign, wxString& gatewayCallsign, wxString& address, DSTAR_PROTOCOL& protocol);
|
||||
|
||||
// Get a gateway message, as a result of IDRT_GATEWAY returned from getMessageType()
|
||||
// A false return implies a network error
|
||||
bool receiveGateway(wxString& gatewayCallsign, wxString& address, DSTAR_PROTOCOL& protocol);
|
||||
|
||||
// Get a user message, as a result of IDRT_USER returned from getMessageType()
|
||||
// A false return implies a network error
|
||||
bool receiveUser(wxString& userCallsign, wxString& repeaterCallsign, wxString& gatewayCallsign, wxString& address);
|
||||
|
||||
bool receiveUser(wxString& userCallsign, wxString& repeaterCallsign, wxString& gatewayCallsign, wxString& address,
|
||||
wxString& timeStamp );
|
||||
|
||||
void close(); // Implictely kills any threads in the IRC code
|
||||
|
||||
|
||||
private:
|
||||
struct CIRCDDBPrivate * const d;
|
||||
|
||||
};
|
||||
|
||||
#endif // _IRCDDB_H
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,98 @@
|
||||
/*
|
||||
|
||||
CIRCDDB - ircDDB client library in C++
|
||||
|
||||
Copyright (C) 2010-2011 Michael Dirska, DL1BFF (dl1bff@mdx.de)
|
||||
|
||||
This program 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, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#if !defined(_IRCDDBAPP_H)
|
||||
#define _IRCDDBAPP_H
|
||||
|
||||
|
||||
#include "IRCDDB.h"
|
||||
#include "IRCApplication.h"
|
||||
|
||||
#include <wx/wx.h>
|
||||
|
||||
class IRCDDBAppPrivate;
|
||||
|
||||
class IRCDDBApp : public IRCApplication, wxThread
|
||||
{
|
||||
public:
|
||||
IRCDDBApp(const wxString& update_channel);
|
||||
|
||||
virtual ~IRCDDBApp();
|
||||
|
||||
virtual void userJoin (const wxString& nick, const wxString& name, const wxString& host);
|
||||
|
||||
virtual void userLeave (const wxString& nick);
|
||||
|
||||
virtual void userChanOp (const wxString& nick, bool op);
|
||||
virtual void userListReset();
|
||||
|
||||
virtual void msgChannel (IRCMessage * m);
|
||||
virtual void msgQuery (IRCMessage * m);
|
||||
|
||||
virtual void setCurrentNick(const wxString& nick);
|
||||
virtual void setTopic(const wxString& topic);
|
||||
|
||||
virtual void setBestServer(const wxString& ircUser);
|
||||
|
||||
virtual void setSendQ( IRCMessageQueue * s );
|
||||
virtual IRCMessageQueue * getSendQ ();
|
||||
|
||||
bool startWork();
|
||||
void stopWork();
|
||||
|
||||
IRCDDB_RESPONSE_TYPE getReplyMessageType();
|
||||
|
||||
IRCMessage * getReplyMessage();
|
||||
|
||||
bool findUser ( const wxString& s );
|
||||
bool findRepeater ( const wxString& s );
|
||||
bool findGateway ( const wxString& s );
|
||||
|
||||
bool sendHeard(const wxString& myCall, const wxString& myCallExt,
|
||||
const wxString& yourCall, const wxString& rpt1,
|
||||
const wxString& rpt2, unsigned char flag1,
|
||||
unsigned char flag2, unsigned char flag3,
|
||||
const wxString& destination, const wxString& tx_msg,
|
||||
const wxString& tx_stats);
|
||||
|
||||
int getConnectionState();
|
||||
|
||||
void rptrQRG( const wxString& module, double txFrequency, double duplexShift,
|
||||
double range, double agl );
|
||||
|
||||
void rptrQTH( double latitude, double longitude, const wxString& desc1,
|
||||
const wxString& desc2, const wxString& infoURL );
|
||||
|
||||
void kickWatchdog( const wxString& wdInfo );
|
||||
|
||||
protected:
|
||||
virtual wxThread::ExitCode Entry();
|
||||
|
||||
private:
|
||||
void doUpdate ( wxString& msg );
|
||||
void doNotFound ( wxString& msg, wxString& retval );
|
||||
wxString getIPAddress( wxString& zonerp_cs );
|
||||
bool findServerUser();
|
||||
IRCDDBAppPrivate * d;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,177 @@
|
||||
/*
|
||||
|
||||
CIRCDDB - ircDDB client library in C++
|
||||
|
||||
Copyright (C) 2010-2011 Michael Dirska, DL1BFF (dl1bff@mdx.de)
|
||||
|
||||
This program 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, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "IRCMessage.h"
|
||||
|
||||
|
||||
|
||||
IRCMessage::IRCMessage ()
|
||||
{
|
||||
numParams = 0;
|
||||
prefixParsed = false;
|
||||
}
|
||||
|
||||
IRCMessage::IRCMessage ( const wxString& toNick, const wxString& msg )
|
||||
{
|
||||
command = wxT("PRIVMSG");
|
||||
numParams = 2;
|
||||
params.Add( toNick );
|
||||
params.Add( msg );
|
||||
prefixParsed = false;
|
||||
}
|
||||
|
||||
IRCMessage::IRCMessage ( const wxString& cmd )
|
||||
{
|
||||
command = cmd;
|
||||
numParams = 0;
|
||||
prefixParsed = false;
|
||||
}
|
||||
|
||||
IRCMessage::~IRCMessage()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void IRCMessage::addParam( const wxString& p )
|
||||
{
|
||||
params.Add( p );
|
||||
numParams = params.GetCount();
|
||||
}
|
||||
|
||||
int IRCMessage::getParamCount()
|
||||
{
|
||||
return params.GetCount();
|
||||
}
|
||||
|
||||
wxString IRCMessage::getParam( int pos )
|
||||
{
|
||||
return params[pos];
|
||||
}
|
||||
|
||||
wxString IRCMessage::getCommand()
|
||||
{
|
||||
return command;
|
||||
}
|
||||
|
||||
|
||||
void IRCMessage::parsePrefix()
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i=0; i < 3; i++)
|
||||
{
|
||||
prefixComponents.Add(wxT(""));
|
||||
}
|
||||
|
||||
int state = 0;
|
||||
|
||||
for (i=0; i < prefix.Len(); i++)
|
||||
{
|
||||
wxChar c = prefix.GetChar(i);
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case wxT('!'):
|
||||
state = 1; // next is name
|
||||
break;
|
||||
|
||||
case wxT('@'):
|
||||
state = 2; // next is host
|
||||
break;
|
||||
|
||||
default:
|
||||
prefixComponents[state].Append(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
prefixParsed = true;
|
||||
}
|
||||
|
||||
wxString& IRCMessage::getPrefixNick()
|
||||
{
|
||||
if (!prefixParsed)
|
||||
{
|
||||
parsePrefix();
|
||||
}
|
||||
|
||||
return prefixComponents[0];
|
||||
}
|
||||
|
||||
wxString& IRCMessage::getPrefixName()
|
||||
{
|
||||
if (!prefixParsed)
|
||||
{
|
||||
parsePrefix();
|
||||
}
|
||||
|
||||
return prefixComponents[1];
|
||||
}
|
||||
|
||||
wxString& IRCMessage::getPrefixHost()
|
||||
{
|
||||
if (!prefixParsed)
|
||||
{
|
||||
parsePrefix();
|
||||
}
|
||||
|
||||
return prefixComponents[2];
|
||||
}
|
||||
|
||||
void IRCMessage::composeMessage ( wxString& output )
|
||||
{
|
||||
#if defined(DEBUG_IRC)
|
||||
wxString d = wxT("T [") + prefix + wxT("] [") + command + wxT("]");
|
||||
for (int i=0; i < numParams; i++)
|
||||
{
|
||||
d.Append(wxT(" [") + params[i] + wxT("]") );
|
||||
}
|
||||
d.Replace(wxT("%"), wxT("%%"), true);
|
||||
d.Replace(wxT("\\"), wxT("\\\\"), true);
|
||||
wxLogVerbose(d);
|
||||
#endif
|
||||
|
||||
wxString o;
|
||||
|
||||
if (prefix.Len() > 0)
|
||||
{
|
||||
o = wxT(":") + prefix + wxT(" ");
|
||||
}
|
||||
|
||||
o.Append(command);
|
||||
|
||||
for (int i=0; i < numParams; i++)
|
||||
{
|
||||
if (i == (numParams - 1))
|
||||
{
|
||||
o.Append(wxT(" :") + params[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
o.Append(wxT(" ") + params[i]);
|
||||
}
|
||||
}
|
||||
|
||||
o.Append(wxT("\r\n"));
|
||||
|
||||
output = o;
|
||||
}
|
||||
|
||||
@ -0,0 +1,71 @@
|
||||
/*
|
||||
|
||||
CIRCDDB - ircDDB client library in C++
|
||||
|
||||
Copyright (C) 2010 Michael Dirska, DL1BFF (dl1bff@mdx.de)
|
||||
|
||||
This program 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, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#if !defined(_IRC_MESSAGE_H)
|
||||
#define _IRC_MESSAGE_H
|
||||
|
||||
#include <wx/wx.h>
|
||||
|
||||
|
||||
class IRCMessage
|
||||
{
|
||||
public:
|
||||
|
||||
IRCMessage();
|
||||
|
||||
IRCMessage( const wxString& toNick, const wxString& msg );
|
||||
|
||||
IRCMessage( const wxString& command );
|
||||
|
||||
~IRCMessage();
|
||||
|
||||
|
||||
|
||||
wxString prefix;
|
||||
wxString command;
|
||||
wxArrayString params;
|
||||
|
||||
int numParams;
|
||||
|
||||
wxString& getPrefixNick();
|
||||
wxString& getPrefixName();
|
||||
wxString& getPrefixHost();
|
||||
|
||||
void composeMessage ( wxString& output );
|
||||
|
||||
void addParam( const wxString& p );
|
||||
|
||||
wxString getCommand();
|
||||
|
||||
wxString getParam( int pos );
|
||||
|
||||
int getParamCount();
|
||||
|
||||
private:
|
||||
|
||||
void parsePrefix();
|
||||
|
||||
wxArrayString prefixComponents;
|
||||
bool prefixParsed;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,137 @@
|
||||
/*
|
||||
|
||||
CIRCDDB - ircDDB client library in C++
|
||||
|
||||
Copyright (C) 2010 Michael Dirska, DL1BFF (dl1bff@mdx.de)
|
||||
|
||||
This program 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, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "IRCMessageQueue.h"
|
||||
|
||||
|
||||
IRCMessageQueue::IRCMessageQueue()
|
||||
{
|
||||
eof = false;
|
||||
first = NULL;
|
||||
last = NULL;
|
||||
|
||||
}
|
||||
|
||||
IRCMessageQueue::~IRCMessageQueue()
|
||||
{
|
||||
while (messageAvailable())
|
||||
{
|
||||
IRCMessage * m = getMessage();
|
||||
|
||||
delete m;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool IRCMessageQueue::isEOF()
|
||||
{
|
||||
return eof;
|
||||
}
|
||||
|
||||
|
||||
void IRCMessageQueue::signalEOF()
|
||||
{
|
||||
eof = true;
|
||||
}
|
||||
|
||||
|
||||
bool IRCMessageQueue::messageAvailable()
|
||||
{
|
||||
wxMutexLocker lock(accessMutex);
|
||||
|
||||
return (first != NULL);
|
||||
}
|
||||
|
||||
|
||||
IRCMessage * IRCMessageQueue::peekFirst()
|
||||
{
|
||||
wxMutexLocker lock(accessMutex);
|
||||
|
||||
IRCMessageQueueItem * k = first;
|
||||
|
||||
if ( k == NULL )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return k->msg;
|
||||
}
|
||||
|
||||
|
||||
IRCMessage * IRCMessageQueue::getMessage()
|
||||
{
|
||||
wxMutexLocker lock(accessMutex);
|
||||
|
||||
IRCMessageQueueItem * k;
|
||||
|
||||
if (first == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
k = first;
|
||||
|
||||
first = k -> next;
|
||||
|
||||
if (k -> next == NULL)
|
||||
{
|
||||
last = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
k -> next -> prev = NULL;
|
||||
}
|
||||
|
||||
|
||||
IRCMessage * msg = k -> msg;
|
||||
|
||||
delete k;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
||||
void IRCMessageQueue::putMessage( IRCMessage * m )
|
||||
{
|
||||
wxMutexLocker lock(accessMutex);
|
||||
|
||||
// wxLogVerbose(wxT("IRCMessageQueue::putMessage"));
|
||||
|
||||
IRCMessageQueueItem * k = new IRCMessageQueueItem(m);
|
||||
|
||||
k -> prev = last;
|
||||
k -> next = NULL;
|
||||
|
||||
if (last == NULL)
|
||||
{
|
||||
first = k;
|
||||
}
|
||||
else
|
||||
{
|
||||
last -> next = k;
|
||||
}
|
||||
|
||||
last = k;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,79 @@
|
||||
/*
|
||||
|
||||
CIRCDDB - ircDDB client library in C++
|
||||
|
||||
Copyright (C) 2010 Michael Dirska, DL1BFF (dl1bff@mdx.de)
|
||||
|
||||
This program 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, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#if !defined(_IRCMESSAGEQUEUE_H)
|
||||
#define _IRCMESSAGEQUEUE_H
|
||||
|
||||
#include <wx/wx.h>
|
||||
|
||||
#include "IRCMessage.h"
|
||||
|
||||
|
||||
class IRCMessageQueueItem
|
||||
{
|
||||
public:
|
||||
IRCMessageQueueItem( IRCMessage * m )
|
||||
{
|
||||
msg = m;
|
||||
}
|
||||
|
||||
~IRCMessageQueueItem()
|
||||
{
|
||||
}
|
||||
|
||||
IRCMessage * msg;
|
||||
|
||||
IRCMessageQueueItem * prev;
|
||||
IRCMessageQueueItem * next;
|
||||
};
|
||||
|
||||
|
||||
class IRCMessageQueue
|
||||
{
|
||||
public:
|
||||
IRCMessageQueue();
|
||||
|
||||
~IRCMessageQueue();
|
||||
|
||||
bool isEOF();
|
||||
|
||||
void signalEOF();
|
||||
|
||||
bool messageAvailable();
|
||||
|
||||
IRCMessage * getMessage();
|
||||
|
||||
IRCMessage * peekFirst();
|
||||
|
||||
void putMessage ( IRCMessage * m );
|
||||
|
||||
private:
|
||||
|
||||
bool eof;
|
||||
|
||||
IRCMessageQueueItem * first;
|
||||
IRCMessageQueueItem * last;
|
||||
|
||||
wxMutex accessMutex;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,447 @@
|
||||
/*
|
||||
|
||||
CIRCDDB - ircDDB client library in C++
|
||||
|
||||
Copyright (C) 2010-2011 Michael Dirska, DL1BFF (dl1bff@mdx.de)
|
||||
|
||||
This program 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, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "IRCProtocol.h"
|
||||
|
||||
#include <wx/regex.h>
|
||||
|
||||
#define CIRCDDB_VERSION "1.2.4"
|
||||
|
||||
IRCProtocol::IRCProtocol ( IRCApplication * app,
|
||||
const wxString& callsign, const wxString& password, const wxString& channel,
|
||||
const wxString& versionInfo )
|
||||
{
|
||||
this -> password = password;
|
||||
this -> channel = channel;
|
||||
this -> app = app;
|
||||
|
||||
this->versionInfo = wxT("CIRCDDB:");
|
||||
this->versionInfo.Append(wxT(CIRCDDB_VERSION));
|
||||
|
||||
if (versionInfo.Len() > 0)
|
||||
{
|
||||
this->versionInfo.Append(wxT(" "));
|
||||
this->versionInfo.Append(versionInfo);
|
||||
}
|
||||
|
||||
|
||||
int hyphenPos = callsign.find(wxT('-'));
|
||||
|
||||
if (hyphenPos == wxNOT_FOUND)
|
||||
{
|
||||
wxString n;
|
||||
|
||||
n = callsign + wxT("-1");
|
||||
nicks.Add(n);
|
||||
n = callsign + wxT("-2");
|
||||
nicks.Add(n);
|
||||
n = callsign + wxT("-3");
|
||||
nicks.Add(n);
|
||||
n = callsign + wxT("-4");
|
||||
nicks.Add(n);
|
||||
}
|
||||
else
|
||||
{
|
||||
nicks.Add(callsign);
|
||||
}
|
||||
|
||||
name = callsign;
|
||||
|
||||
pingTimer = 60; // 30 seconds
|
||||
state = 0;
|
||||
timer = 0;
|
||||
|
||||
|
||||
chooseNewNick();
|
||||
}
|
||||
|
||||
IRCProtocol::~IRCProtocol()
|
||||
{
|
||||
}
|
||||
|
||||
void IRCProtocol::chooseNewNick()
|
||||
{
|
||||
int r = rand() % nicks.GetCount();
|
||||
|
||||
currentNick = nicks[r];
|
||||
}
|
||||
|
||||
void IRCProtocol::setNetworkReady( bool b )
|
||||
{
|
||||
if (b == true)
|
||||
{
|
||||
if (state != 0)
|
||||
{
|
||||
wxLogError(wxT("IRCProtocol::setNetworkReady: unexpected state"));
|
||||
}
|
||||
|
||||
state = 1;
|
||||
chooseNewNick();
|
||||
}
|
||||
else
|
||||
{
|
||||
state = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool IRCProtocol::processQueues ( IRCMessageQueue * recvQ, IRCMessageQueue * sendQ )
|
||||
{
|
||||
if (timer > 0)
|
||||
{
|
||||
timer --;
|
||||
}
|
||||
|
||||
while (recvQ->messageAvailable())
|
||||
{
|
||||
IRCMessage * m = recvQ -> getMessage();
|
||||
|
||||
#if defined(DEBUG_IRC)
|
||||
wxString d = wxT("R [") + m->prefix + wxT("] [") + m->command + wxT("]");
|
||||
for (int i=0; i < m->numParams; i++)
|
||||
{
|
||||
d.Append(wxT(" [") + m->params[i] + wxT("]") );
|
||||
}
|
||||
d.Replace(wxT("%"), wxT("%%"), true);
|
||||
d.Replace(wxT("\\"), wxT("\\\\"), true);
|
||||
wxLogVerbose(d);
|
||||
#endif
|
||||
|
||||
if (m->command.IsSameAs(wxT("004")))
|
||||
{
|
||||
if (state == 4)
|
||||
{
|
||||
if (m->params.GetCount() > 1)
|
||||
{
|
||||
wxRegEx serverNamePattern(wxT("^grp[1-9]s[1-9].ircDDB$"));
|
||||
|
||||
if (serverNamePattern.Matches( m->params[1] ))
|
||||
{
|
||||
app->setBestServer(wxT("s-") + m->params[1].Mid(0,6));
|
||||
}
|
||||
}
|
||||
state = 5; // next: JOIN
|
||||
app->setCurrentNick(currentNick);
|
||||
}
|
||||
}
|
||||
else if (m->command.IsSameAs(wxT("PING")))
|
||||
{
|
||||
IRCMessage * m2 = new IRCMessage();
|
||||
m2->command = wxT("PONG");
|
||||
if (m->params.GetCount() > 0)
|
||||
{
|
||||
m2->numParams = 1;
|
||||
m2->params.Add( m->params[0] );
|
||||
}
|
||||
sendQ -> putMessage(m2);
|
||||
}
|
||||
else if (m->command.IsSameAs(wxT("JOIN")))
|
||||
{
|
||||
if ((m->numParams >= 1) && m->params[0].IsSameAs(channel))
|
||||
{
|
||||
if (m->getPrefixNick().IsSameAs(currentNick) && (state == 6))
|
||||
{
|
||||
if (debugChannel.Len() > 0)
|
||||
{
|
||||
state = 7; // next: join debug_channel
|
||||
}
|
||||
else
|
||||
{
|
||||
state = 10; // next: WHO *
|
||||
}
|
||||
}
|
||||
else if (app != NULL)
|
||||
{
|
||||
app->userJoin( m->getPrefixNick(), m->getPrefixName(), m->getPrefixHost());
|
||||
}
|
||||
}
|
||||
|
||||
if ((m->numParams >= 1) && m->params[0].IsSameAs(debugChannel))
|
||||
{
|
||||
if (m->getPrefixNick().IsSameAs(currentNick) && (state == 8))
|
||||
{
|
||||
state = 10; // next: WHO *
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (m->command.IsSameAs(wxT("PONG")))
|
||||
{
|
||||
if (state == 12)
|
||||
{
|
||||
timer = pingTimer;
|
||||
state = 11;
|
||||
}
|
||||
}
|
||||
else if (m->command.IsSameAs(wxT("PART")))
|
||||
{
|
||||
if ((m->numParams >= 1) && m->params[0].IsSameAs(channel))
|
||||
{
|
||||
if (app != NULL)
|
||||
{
|
||||
app->userLeave( m->getPrefixNick() );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (m->command.IsSameAs(wxT("KICK")))
|
||||
{
|
||||
if ((m->numParams >= 2) && m->params[0].IsSameAs(channel))
|
||||
{
|
||||
if (m->params[1].IsSameAs(currentNick))
|
||||
{
|
||||
// i was kicked!!
|
||||
delete m;
|
||||
return false;
|
||||
}
|
||||
else if (app != NULL)
|
||||
{
|
||||
app->userLeave( m->params[1] );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (m->command.IsSameAs(wxT("QUIT")))
|
||||
{
|
||||
if (app != NULL)
|
||||
{
|
||||
app->userLeave( m->getPrefixNick() );
|
||||
}
|
||||
}
|
||||
else if (m->command.IsSameAs(wxT("MODE")))
|
||||
{
|
||||
if ((m->numParams >= 3) && m->params[0].IsSameAs(channel))
|
||||
{
|
||||
if (app != NULL)
|
||||
{
|
||||
size_t i;
|
||||
wxString mode = m->params[1];
|
||||
|
||||
for (i = 1; (i < mode.Len()) && ((size_t) m->numParams >= (i+2)); i++)
|
||||
{
|
||||
if ( mode[i] == wxT('o') )
|
||||
{
|
||||
if ( mode[0] == wxT('+') )
|
||||
{
|
||||
app->userChanOp(m->params[i+1], true);
|
||||
}
|
||||
else if ( mode[0] == wxT('-') )
|
||||
{
|
||||
app->userChanOp(m->params[i+1], false);
|
||||
}
|
||||
}
|
||||
} // for
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (m->command.IsSameAs(wxT("PRIVMSG")))
|
||||
{
|
||||
if ((m->numParams == 2) && (app != NULL))
|
||||
{
|
||||
if (m->params[0].IsSameAs(channel))
|
||||
{
|
||||
app->msgChannel(m);
|
||||
}
|
||||
else if (m->params[0].IsSameAs(currentNick))
|
||||
{
|
||||
app->msgQuery(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (m->command.IsSameAs(wxT("352"))) // WHO list
|
||||
{
|
||||
if ((m->numParams >= 7) && m->params[0].IsSameAs(currentNick)
|
||||
&& m->params[1].IsSameAs(channel))
|
||||
{
|
||||
if (app != NULL)
|
||||
{
|
||||
app->userJoin( m->params[5], m->params[2], m->params[3]);
|
||||
app->userChanOp ( m->params[5], m->params[6].IsSameAs(wxT("H@")));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (m->command.IsSameAs(wxT("433"))) // nick collision
|
||||
{
|
||||
if (state == 2)
|
||||
{
|
||||
state = 3; // nick collision, choose new nick
|
||||
timer = 10; // wait 5 seconds..
|
||||
}
|
||||
}
|
||||
else if (m->command.IsSameAs(wxT("332")) ||
|
||||
m->command.IsSameAs(wxT("TOPIC"))) // topic
|
||||
{
|
||||
if ((m->numParams == 2) && (app != NULL) &&
|
||||
m->params[0].IsSameAs(channel) )
|
||||
{
|
||||
app->setTopic(m->params[1]);
|
||||
}
|
||||
}
|
||||
|
||||
delete m;
|
||||
}
|
||||
|
||||
IRCMessage * m;
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case 1:
|
||||
m = new IRCMessage();
|
||||
m->command = wxT("PASS");
|
||||
m->numParams = 1;
|
||||
m->params.Add(password);
|
||||
sendQ->putMessage(m);
|
||||
|
||||
m = new IRCMessage();
|
||||
m->command = wxT("NICK");
|
||||
m->numParams = 1;
|
||||
m->params.Add(currentNick);
|
||||
sendQ->putMessage(m);
|
||||
|
||||
timer = 10; // wait for possible nick collision message
|
||||
state = 2;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (timer == 0)
|
||||
{
|
||||
m = new IRCMessage();
|
||||
m->command = wxT("USER");
|
||||
m->numParams = 4;
|
||||
m->params.Add(name);
|
||||
m->params.Add(wxT("0"));
|
||||
m->params.Add(wxT("*"));
|
||||
m->params.Add(versionInfo);
|
||||
sendQ->putMessage(m);
|
||||
|
||||
timer = 30;
|
||||
state = 4; // wait for login message
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if (timer == 0)
|
||||
{
|
||||
chooseNewNick();
|
||||
m = new IRCMessage();
|
||||
m->command = wxT("NICK");
|
||||
m->numParams = 1;
|
||||
m->params.Add(currentNick);
|
||||
sendQ->putMessage(m);
|
||||
|
||||
timer = 10; // wait for possible nick collision message
|
||||
state = 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
if (timer == 0)
|
||||
{
|
||||
// no login message received -> disconnect
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case 5:
|
||||
m = new IRCMessage();
|
||||
m->command = wxT("JOIN");
|
||||
m->numParams = 1;
|
||||
m->params.Add(channel);
|
||||
sendQ->putMessage(m);
|
||||
|
||||
timer = 30;
|
||||
state = 6; // wait for join message
|
||||
break;
|
||||
|
||||
case 6:
|
||||
if (timer == 0)
|
||||
{
|
||||
// no join message received -> disconnect
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case 7:
|
||||
if (debugChannel.Len() == 0)
|
||||
{
|
||||
return false; // this state cannot be processed if there is no debug_channel
|
||||
}
|
||||
|
||||
m = new IRCMessage();
|
||||
m->command = wxT("JOIN");
|
||||
m->numParams = 1;
|
||||
m->params.Add(debugChannel);
|
||||
sendQ->putMessage(m);
|
||||
|
||||
timer = 30;
|
||||
state = 8; // wait for join message
|
||||
break;
|
||||
|
||||
case 8:
|
||||
if (timer == 0)
|
||||
{
|
||||
// no join message received -> disconnect
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case 10:
|
||||
m = new IRCMessage();
|
||||
m->command = wxT("WHO");
|
||||
m->numParams = 2;
|
||||
m->params.Add(channel);
|
||||
m->params.Add(wxT("*"));
|
||||
sendQ->putMessage(m);
|
||||
|
||||
timer = pingTimer;
|
||||
state = 11; // wait for timer and then send ping
|
||||
|
||||
if (app != NULL)
|
||||
{
|
||||
app->setSendQ(sendQ); // this switches the application on
|
||||
}
|
||||
break;
|
||||
|
||||
case 11:
|
||||
if (timer == 0)
|
||||
{
|
||||
m = new IRCMessage();
|
||||
m->command = wxT("PING");
|
||||
m->numParams = 1;
|
||||
m->params.Add(currentNick);
|
||||
sendQ->putMessage(m);
|
||||
|
||||
timer = pingTimer;
|
||||
state = 12; // wait for pong
|
||||
}
|
||||
break;
|
||||
|
||||
case 12:
|
||||
if (timer == 0)
|
||||
{
|
||||
// no pong message received -> disconnect
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,65 @@
|
||||
/*
|
||||
|
||||
CIRCDDB - ircDDB client library in C++
|
||||
|
||||
Copyright (C) 2010 Michael Dirska, DL1BFF (dl1bff@mdx.de)
|
||||
|
||||
This program 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, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#if !defined(_IRCPROTOCOL_H)
|
||||
#define _IRCPROTOCOL_H
|
||||
|
||||
#include <wx/wx.h>
|
||||
|
||||
#include "IRCMessageQueue.h"
|
||||
#include "IRCApplication.h"
|
||||
|
||||
|
||||
class IRCProtocol
|
||||
{
|
||||
public:
|
||||
IRCProtocol ( IRCApplication * app,
|
||||
const wxString& callsign, const wxString& password, const wxString& channel,
|
||||
const wxString& versionInfo );
|
||||
|
||||
~IRCProtocol();
|
||||
|
||||
void setNetworkReady( bool state );
|
||||
|
||||
bool processQueues ( IRCMessageQueue * recvQ, IRCMessageQueue * sendQ );
|
||||
|
||||
private:
|
||||
void chooseNewNick();
|
||||
|
||||
wxArrayString nicks;
|
||||
wxString password;
|
||||
wxString channel;
|
||||
wxString name;
|
||||
wxString currentNick;
|
||||
wxString versionInfo;
|
||||
|
||||
int state;
|
||||
int timer;
|
||||
int pingTimer;
|
||||
|
||||
wxString debugChannel;
|
||||
|
||||
IRCApplication * app;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,249 @@
|
||||
/*
|
||||
|
||||
CIRCDDB - ircDDB client library in C++
|
||||
|
||||
Copyright (C) 2010 Michael Dirska, DL1BFF (dl1bff@mdx.de)
|
||||
|
||||
This program 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, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#if defined(WIN32)
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
#else
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#include "IRCReceiver.h"
|
||||
|
||||
#include <wx/wx.h>
|
||||
|
||||
IRCReceiver::IRCReceiver(int sock, IRCMessageQueue * q )
|
||||
: wxThread(wxTHREAD_JOINABLE)
|
||||
{
|
||||
this->sock = sock;
|
||||
|
||||
recvQ = q;
|
||||
}
|
||||
|
||||
IRCReceiver::~IRCReceiver()
|
||||
{
|
||||
}
|
||||
|
||||
bool IRCReceiver::startWork()
|
||||
{
|
||||
|
||||
if (Create() != wxTHREAD_NO_ERROR)
|
||||
{
|
||||
wxLogError(wxT("IRCReceiver::startWork: Could not create the worker thread!"));
|
||||
return false;
|
||||
}
|
||||
|
||||
terminateThread = false;
|
||||
|
||||
if (Run() != wxTHREAD_NO_ERROR)
|
||||
{
|
||||
wxLogError(wxT("IRCReceiver::startWork: Could not run the worker thread!"));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void IRCReceiver::stopWork()
|
||||
{
|
||||
terminateThread = true;
|
||||
|
||||
Wait();
|
||||
}
|
||||
|
||||
static int doRead( int sock, char * buf, int buf_size )
|
||||
{
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
fd_set rdset;
|
||||
fd_set errset;
|
||||
|
||||
FD_ZERO(&rdset);
|
||||
FD_ZERO(&errset);
|
||||
FD_SET(sock, &rdset);
|
||||
FD_SET(sock, &errset);
|
||||
|
||||
int res;
|
||||
|
||||
res = select(sock+1, &rdset, NULL, &errset, &tv);
|
||||
|
||||
if ( res < 0 )
|
||||
{
|
||||
wxLogSysError(wxT("IRCReceiver::doRead: select"));
|
||||
return -1;
|
||||
}
|
||||
else if ( res > 0 )
|
||||
{
|
||||
if (FD_ISSET(sock, &errset))
|
||||
{
|
||||
wxLogVerbose(wxT("IRCReceiver::doRead: select (FD_ISSET(sock, exceptfds))"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (FD_ISSET(sock, &rdset))
|
||||
{
|
||||
res = recv(sock, buf, buf_size, 0);
|
||||
|
||||
if (res < 0)
|
||||
{
|
||||
wxLogSysError(wxT("IRCReceiver::doRead: read"));
|
||||
return -1;
|
||||
}
|
||||
else if (res == 0)
|
||||
{
|
||||
wxLogVerbose(wxT("IRCReceiver::doRead: EOF read==0"));
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
wxThread::ExitCode IRCReceiver::Entry ()
|
||||
{
|
||||
IRCMessage * m = new IRCMessage();
|
||||
|
||||
int i;
|
||||
int state = 0;
|
||||
|
||||
while (!terminateThread)
|
||||
{
|
||||
|
||||
// wxLogVerbose(wxT("IRCReceiver: tick"));
|
||||
|
||||
char buf[200];
|
||||
int r = doRead( sock, buf, sizeof buf );
|
||||
|
||||
if (r < 0)
|
||||
{
|
||||
recvQ -> signalEOF();
|
||||
delete m; // delete unfinished IRCMessage
|
||||
break;
|
||||
}
|
||||
|
||||
for (i=0; i < r; i++)
|
||||
{
|
||||
char b = buf[i];
|
||||
|
||||
if (b > 0)
|
||||
{
|
||||
if (b == 10)
|
||||
{
|
||||
recvQ -> putMessage(m);
|
||||
m = new IRCMessage();
|
||||
state = 0;
|
||||
}
|
||||
else if (b == 13)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
else switch (state)
|
||||
{
|
||||
case 0:
|
||||
if (b == ':')
|
||||
{
|
||||
state = 1; // prefix
|
||||
}
|
||||
else if (b == 32)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
else
|
||||
{
|
||||
m -> command.Append(wxChar(b));
|
||||
state = 2; // command
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if (b == 32)
|
||||
{
|
||||
state = 2; // command is next
|
||||
}
|
||||
else
|
||||
{
|
||||
m -> prefix.Append(wxChar(b));
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (b == 32)
|
||||
{
|
||||
state = 3; // params
|
||||
m -> numParams = 1;
|
||||
m -> params.Add(wxT(""));
|
||||
}
|
||||
else
|
||||
{
|
||||
m -> command.Append(wxChar(b));
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if (b == 32)
|
||||
{
|
||||
m -> numParams ++;
|
||||
if (m -> numParams >= 15)
|
||||
{
|
||||
state = 5; // ignore the rest
|
||||
}
|
||||
|
||||
m -> params.Add(wxT(""));
|
||||
}
|
||||
else if ((b == ':') && (m -> params[ m -> numParams-1 ].Len() == 0))
|
||||
{
|
||||
state = 4; // rest of line is this param
|
||||
}
|
||||
else
|
||||
{
|
||||
m -> params[ m -> numParams-1 ].Append(wxChar(b));
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
m -> params[ m -> numParams-1 ].Append(wxChar(b));
|
||||
break;
|
||||
|
||||
|
||||
} // switch
|
||||
} // if
|
||||
} // for
|
||||
} // while
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -0,0 +1,62 @@
|
||||
/*
|
||||
|
||||
CIRCDDB - ircDDB client library in C++
|
||||
|
||||
Copyright (C) 2010 Michael Dirska, DL1BFF (dl1bff@mdx.de)
|
||||
|
||||
This program 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, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#if !defined(_IRCRECEIVER_H)
|
||||
#define _IRCRECEIVER_H
|
||||
|
||||
#include <wx/wx.h>
|
||||
|
||||
#include "IRCMessageQueue.h"
|
||||
|
||||
|
||||
class IRCReceiver : public wxThread
|
||||
{
|
||||
public:
|
||||
|
||||
IRCReceiver(int sock, IRCMessageQueue * q);
|
||||
|
||||
~IRCReceiver();
|
||||
|
||||
|
||||
bool startWork();
|
||||
|
||||
void stopWork();
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
virtual wxThread::ExitCode Entry();
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
bool terminateThread;
|
||||
int sock;
|
||||
IRCMessageQueue * recvQ;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,180 @@
|
||||
/*
|
||||
|
||||
CIRCDDB - ircDDB client library in C++
|
||||
|
||||
Copyright (C) 2010-2011 Michael Dirska, DL1BFF (dl1bff@mdx.de)
|
||||
|
||||
This program 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, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#if defined(WIN32)
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
#else
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#include <wx/wx.h>
|
||||
|
||||
#include "IRCutils.h"
|
||||
|
||||
|
||||
int getAllIPV4Addresses ( const char * name, unsigned short port,
|
||||
unsigned int * num, struct sockaddr_in * addr, unsigned int max_addr )
|
||||
{
|
||||
|
||||
struct addrinfo hints;
|
||||
struct addrinfo * res;
|
||||
|
||||
memset(&hints, 0x00, sizeof(struct addrinfo));
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
int r = getaddrinfo( name, NULL, &hints, &res );
|
||||
|
||||
if (r == 0)
|
||||
{
|
||||
struct addrinfo * rp;
|
||||
unsigned int numAddr = 0;
|
||||
|
||||
for (rp = res; rp != NULL; rp = rp->ai_next)
|
||||
{
|
||||
if (rp->ai_family == AF_INET)
|
||||
{
|
||||
numAddr ++;
|
||||
}
|
||||
}
|
||||
|
||||
if (numAddr > 0)
|
||||
{
|
||||
if (numAddr > max_addr)
|
||||
{
|
||||
numAddr = max_addr;
|
||||
}
|
||||
|
||||
int * shuffle = new int[numAddr];
|
||||
|
||||
unsigned int i;
|
||||
|
||||
for (i=0; i < numAddr; i++)
|
||||
{
|
||||
shuffle[i] = i;
|
||||
}
|
||||
|
||||
for (i=0; i < (numAddr - 1); i++)
|
||||
{
|
||||
if (rand() & 1)
|
||||
{
|
||||
int tmp;
|
||||
tmp = shuffle[i];
|
||||
shuffle[i] = shuffle[i+1];
|
||||
shuffle[i+1] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=(numAddr - 1); i > 0; i--)
|
||||
{
|
||||
if (rand() & 1)
|
||||
{
|
||||
int tmp;
|
||||
tmp = shuffle[i];
|
||||
shuffle[i] = shuffle[i-1];
|
||||
shuffle[i-1] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
for (rp = res, i=0 ; (rp != NULL) && (i < numAddr); rp = rp->ai_next)
|
||||
{
|
||||
if (rp->ai_family == AF_INET)
|
||||
{
|
||||
memcpy( addr+shuffle[i], rp->ai_addr, sizeof (struct sockaddr_in) );
|
||||
|
||||
addr[shuffle[i]].sin_port = htons(port);
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
delete[] shuffle;
|
||||
}
|
||||
|
||||
*num = numAddr;
|
||||
|
||||
freeaddrinfo(res);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
wxString e( gai_strerror(r), wxConvUTF8);
|
||||
|
||||
wxLogWarning(wxT("getaddrinfo: ") + e );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void safeStringCopy (char * dest, const char * src, unsigned int buf_size)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
|
||||
while (i < (buf_size - 1) && (src[i] != 0))
|
||||
{
|
||||
dest[i] = src[i];
|
||||
i++;
|
||||
}
|
||||
|
||||
dest[i] = 0;
|
||||
}
|
||||
|
||||
|
||||
wxString getCurrentTime(void)
|
||||
{
|
||||
time_t now = time(NULL);
|
||||
struct tm* tm;
|
||||
struct tm tm_buf;
|
||||
char buffer[25];
|
||||
|
||||
#if defined(__WINDOWS__)
|
||||
gmtime_s(&tm_buf, &now);
|
||||
tm = &tm_buf;
|
||||
#else
|
||||
gmtime_r(&now, &tm_buf);
|
||||
tm = &tm_buf;
|
||||
#endif
|
||||
|
||||
strftime(buffer, sizeof buffer, "%Y-%m-%d %H:%M:%S", tm);
|
||||
|
||||
return wxString(buffer, wxConvLocal);
|
||||
}
|
||||
|
||||
@ -0,0 +1,31 @@
|
||||
/*
|
||||
|
||||
CIRCDDB - ircDDB client library in C++
|
||||
|
||||
Copyright (C) 2010 Michael Dirska, DL1BFF (dl1bff@mdx.de)
|
||||
|
||||
This program 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, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
int getAllIPV4Addresses ( const char * name, unsigned short port,
|
||||
unsigned int * num, struct sockaddr_in * addr, unsigned int max_addr );
|
||||
|
||||
|
||||
void safeStringCopy (char * dest, const char * src, unsigned int buf_size);
|
||||
|
||||
wxString getCurrentTime(void);
|
||||
|
||||
@ -0,0 +1,153 @@
|
||||
#
|
||||
# This program 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, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program 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
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
# locations for the executibles and other files are set here
|
||||
# NOTE: IF YOU CHANGE THESE, YOU WILL NEED TO UPDATE THE service.* FILES AND
|
||||
# SOME OF THE *.sh FILES TOO!
|
||||
BINDIR=/usr/local/bin
|
||||
CFGDIR=/usr/local/etc
|
||||
LOGDIR=/var/log
|
||||
|
||||
CPPFLAGS=-W -Wall -I/usr/include `wx-config --cppflags base`
|
||||
LDFLAGS=-L/usr/lib `wx-config --libs base`
|
||||
|
||||
PROGRAMS=g2_ircddb g2_link dvap_rptr
|
||||
|
||||
IRCDDBOBJS = IRCDDB.o IRCClient.o IRCReceiver.o IRCMessageQueue.o IRCProtocol.o IRCMessage.o IRCDDBApp.o IRCutils.o golay23.o dstar_dv.o
|
||||
|
||||
all : $(PROGRAMS)
|
||||
|
||||
g2_ircddb : g2_ircddb.cpp $(IRCDDBOBJS)
|
||||
g++ $(CPPFLAGS) -o g2_ircddb g2_ircddb.cpp $(IRCDDBOBJS) $(LDFLAGS)
|
||||
|
||||
g2_link : g2_link.cpp
|
||||
g++ -W -Wall -o g2_link g2_link.cpp -lrt -pthread
|
||||
|
||||
dvap_rptr : dvap_rptr.cpp dstar_dv.o golay23.o
|
||||
g++ -W -Wall -g -o dvap_rptr dvap_rptr.cpp golay23.o dstar_dv.o -I/usr/include -L/usr/lib -lrt
|
||||
|
||||
IRCDDB.o : IRCDDB.cpp IRCDDB.h
|
||||
g++ $(CPPFLAGS) -c $(CPPFLAGS) IRCDDB.cpp
|
||||
|
||||
IRCClient.o : IRCClient.cpp IRCClient.h IRCutils.h
|
||||
g++ -c $(CPPFLAGS) IRCClient.cpp
|
||||
|
||||
IRCReceiver.o : IRCReceiver.cpp IRCReceiver.h IRCMessageQueue.h
|
||||
g++ -c $(CPPFLAGS) IRCReceiver.cpp
|
||||
|
||||
IRCMessageQueue.o : IRCMessageQueue.cpp IRCMessageQueue.h IRCMessage.h
|
||||
g++ -c $(CPPFLAGS) IRCMessageQueue.cpp
|
||||
|
||||
IRCProtocol.o : IRCProtocol.cpp IRCProtocol.h
|
||||
g++ -c $(CPPFLAGS) IRCProtocol.cpp
|
||||
|
||||
IRCMessage.o : IRCMessage.cpp IRCMessage.h
|
||||
g++ -c $(CPPFLAGS) IRCMessage.cpp
|
||||
|
||||
IRCDDBApp.o : IRCDDBApp.cpp IRCDDBApp.h IRCutils.h
|
||||
g++ -c $(CPPFLAGS) IRCDDBApp.cpp
|
||||
|
||||
golay23.o : golay23.cpp golay23.h
|
||||
g++ -c $(CPPFLAGS) golay23.cpp
|
||||
|
||||
dstar_dv.o : dstar_dv.cpp dstar_dv.h golay23.h
|
||||
g++ -c $(CPPFLAGS) dstar_dv.cpp
|
||||
|
||||
g2link_test : g2link_test.cpp
|
||||
g++ -W -Wall -o g2link_test g2link_test.cpp -lrt
|
||||
|
||||
g2link_test_audio : g2link_test_audio.cpp
|
||||
g++ -W -Wall -o g2link_test_audio g2link_test_audio.cpp -lrt
|
||||
|
||||
IRCApplication.h : IRCMessageQueue.h
|
||||
IRCClient.h : IRCReceiver.h IRCMessageQueue.h IRCProtocol.h IRCApplication.h
|
||||
IRCDDBApp.h : IRCDDB.h IRCApplication.h
|
||||
IRCMessageQueue.h : IRCMessage.h
|
||||
IRCProtocol.h : IRCMessageQueue.h IRCApplication.h
|
||||
IRCReceiver.h : IRCMessageQueue.h
|
||||
|
||||
clean :
|
||||
/bin/rm -f *.o
|
||||
|
||||
realclean :
|
||||
/bin/rm -f *.o $(PROGRAMS) g2link_test g2link_text_audio
|
||||
|
||||
install:
|
||||
######### g2_ircddb #########
|
||||
/bin/cp -f g2_ircddb $(BINDIR)
|
||||
/bin/cp -f g2_ircddb.cfg $(CFGDIR)
|
||||
/bin/cp -f service.g2_ircddb /etc/init.d/g2_ircddb
|
||||
/usr/sbin/update-rc.d g2_ircddb defaults
|
||||
/usr/sbin/update-rc.d g2_ircddb enable
|
||||
######### g2_link #########
|
||||
/bin/cp -f g2_link $(BINDIR)
|
||||
/bin/cp -f g2_link.cfg $(CFGDIR)
|
||||
/bin/cp -f announce/*.dat $(CFGDIR)
|
||||
/bin/cp -f gwys.txt $(CFGDIR)
|
||||
/bin/cp -f exec_?.sh $(CFGDIR)
|
||||
/bin/cp -f service.g2_link /etc/init.d/g2_link
|
||||
/usr/sbin/update-rc.d g2_link defaults
|
||||
/usr/sbin/update-rc.d g2_link enable
|
||||
######### dvap_rptr #########
|
||||
/bin/cp -f dvap_rptr $(BINDIR)
|
||||
/bin/cp -f dvap_rptr.sh $(BINDIR)
|
||||
/bin/cp -f dvap_rptr.cfg $(CFGDIR)
|
||||
/bin/cp -f service.dvap_rptr /etc/init.d/dvap_rptr
|
||||
/usr/sbin/update-rc.d dvap_rptr defaults
|
||||
/usr/sbin/update-rc.d dvap_rptr enable
|
||||
|
||||
installdtmfs : g2link_test
|
||||
/bin/cp -f g2link_test $(BINDIR)
|
||||
/bin/cp -f proc_g2_ircddb_dtmfs.sh $(BINDIR)
|
||||
/bin/cp -f service.proc_g2_ircddb_dtmfs /etc/init.d/proc_g2_ircddb_dtmfs
|
||||
/usr/sbin/update-rc.d proc_g2_ircddb_dtmfs defaults
|
||||
/usr/sbin/update-rc.d proc_g2_ircddb_dtmfs enable
|
||||
|
||||
uninstalldtmfs:
|
||||
/usr/sbin/service proc_g2_ircddb_dtmfs stop
|
||||
/bin/rm -f /etc/init.d/proc_g2_ircddb_dtmfs
|
||||
/usr/sbin/update-rc.d proc_g2_ircddb_dtmfs remove
|
||||
/bin/rm -f $(BINDIR)/proc_g2_ircddb_dtmfs.sh
|
||||
/bin/rm -f $(BINDIR)/g2link_test
|
||||
|
||||
uninstall:
|
||||
######### g2_ircddb #########
|
||||
/usr/sbin/service g2_ircddb stop
|
||||
/bin/rm -f /etc/init.d/g2_ircddb
|
||||
/usr/sbin/update-rc.d g2_ircddb remove
|
||||
/bin/rm -f $(BINDIR)/g2_ircddb
|
||||
/bin/rm -f $(CFGDIR)/g2_ircddb.cfg
|
||||
######### g2_link #########
|
||||
/usr/sbin/service g2_link stop
|
||||
/bin/rm -f /etc/init.d/g2_link
|
||||
/usr/sbin/update-rc.d g2_link remove
|
||||
/bin/rm -f $(BINDIR)/g2_link
|
||||
/bin/rm -f $(CFGDIR)/g2_link.cfg
|
||||
/bin/rm -f $(CFGDIR)/already_linked.dat
|
||||
/bin/rm -f $(CFGDIR)/already_unlinked.dat
|
||||
/bin/rm -f $(CFGDIR)/failed_linked.dat
|
||||
/bin/rm -f $(CFGDIR)/id.dat
|
||||
/bin/rm -f $(CFGDIR)/linked.dat
|
||||
/bin/rm -f $(CFGDIR)/unlinked.dat
|
||||
/bin/rm -f $(CFGDIR)/RPT_STATUS.txt
|
||||
/bin/rm -f $(CFGDIR)/gwys.txt
|
||||
/bin/rm -f $(CFGDIR)/exec_?.sh
|
||||
/bin/rm -f /var/log/g2_link.log
|
||||
######### dvap_rptr #########
|
||||
/usr/sbin/service dvap_rptr stop
|
||||
/bin/rm -f $(BINDIR)/dvap_rptr
|
||||
/bin/rm -f $(BINDIR)/dvap_rptr.sh
|
||||
/usr/sbin/update-rc.d dvap_rptr remove
|
||||
/bin/rm -r $(CFGDIR)/dvap_rptr.cfg
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,33 @@
|
||||
#!/bin/bash
|
||||
|
||||
BAKEFILES=$(PWD)/bakefiles.zip
|
||||
|
||||
if [ -e $BAKEFILES ]
|
||||
then
|
||||
# move to the home directory and get the source comressed archive for wxBase
|
||||
cd ~
|
||||
wget http://sourceforge.net/projects/wxwindows/files/2.8.12/wxBase-2.8.12.tar.gz
|
||||
tar -xzvf wxBase-2.8.12.tar.gz
|
||||
|
||||
# move into the directory, configure and build it
|
||||
cd wxBase-2.8.12
|
||||
./configure --disable-gui --without-expat
|
||||
make
|
||||
|
||||
# add the bakefiles and install wxBase
|
||||
cd build
|
||||
unzip $BAKEFILES
|
||||
cd ..
|
||||
sudo make install
|
||||
|
||||
# add /usr/local/lib to /etc/ld.so.conf, if needed and relink the libraries
|
||||
grep -q /usr/local/lib /etc/ld.so.conf
|
||||
RETVAL=$?
|
||||
if [ $RETVAL -eq 1 ]
|
||||
then
|
||||
sudo echo /usr/local/lib >> /etc/ld.so.conf
|
||||
fi
|
||||
sudo ldconfig
|
||||
else
|
||||
echo "$BAKEFILES not found, aborting!"
|
||||
fi
|
||||
@ -0,0 +1,253 @@
|
||||
/*
|
||||
|
||||
ircDDB-mheard
|
||||
|
||||
Copyright (C) 2010 Michael Dirska, DL1BFF (dl1bff@mdx.de)
|
||||
|
||||
This program 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, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "dstar_dv.h"
|
||||
#include "golay23.h"
|
||||
|
||||
int bit_pos1[] =
|
||||
{
|
||||
0, 0, 1, 1, 2, 2,
|
||||
0, 0, 1, 1, 2, 2,
|
||||
0, 0, 1, 1, 2, 2,
|
||||
0, 0, 1, 1, 2, 2,
|
||||
0, 0, 1, 1, 2, 2,
|
||||
0, 0, 1, 1, 2, 2,
|
||||
|
||||
0, 0, 1, 1, 2, 2,
|
||||
0, 0, 1, 1, 2, 2,
|
||||
0, 0, 1, 1, 2, 2,
|
||||
0, 0, 1, 1, 2, 2,
|
||||
0, 0, 1, 1, 2, 2,
|
||||
0, 0, 1, 1, 2, 2
|
||||
};
|
||||
|
||||
int bit_pos2[] =
|
||||
{
|
||||
23, 11,
|
||||
23, 11,
|
||||
23, 11,
|
||||
|
||||
22, 10,
|
||||
22, 10,
|
||||
22, 10,
|
||||
|
||||
21, 9,
|
||||
21, 9,
|
||||
21, 9,
|
||||
|
||||
20, 8,
|
||||
20, 8,
|
||||
20, 8,
|
||||
|
||||
19, 7,
|
||||
19, 7,
|
||||
19, 7,
|
||||
|
||||
18, 6,
|
||||
18, 6,
|
||||
18, 6,
|
||||
|
||||
17, 5,
|
||||
17, 5,
|
||||
17, 5,
|
||||
|
||||
16, 4,
|
||||
16, 4,
|
||||
16, 4,
|
||||
|
||||
15, 3,
|
||||
15, 3,
|
||||
15, 3,
|
||||
|
||||
14, 2,
|
||||
14, 2,
|
||||
14, 2,
|
||||
|
||||
13, 1,
|
||||
13, 1,
|
||||
13, 1,
|
||||
|
||||
12, 0,
|
||||
12, 0,
|
||||
12, 0
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
static long decoding_table[2048];
|
||||
static int prng[4096];
|
||||
|
||||
static void init_prng(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i < 4096; i++)
|
||||
{
|
||||
int mask = 0x800000;
|
||||
int j;
|
||||
int pr;
|
||||
|
||||
prng[i] = 0;
|
||||
pr = i << 4;
|
||||
|
||||
for (j=0; j < 24; j++)
|
||||
{
|
||||
pr = ((173 * pr) + 13849) & 0xFFFF;
|
||||
|
||||
if ((pr & 0x8000) != 0)
|
||||
{
|
||||
prng[i] |= mask;
|
||||
}
|
||||
|
||||
mask = mask >> 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void dstar_dv_init(void)
|
||||
{
|
||||
long temp;
|
||||
int i;
|
||||
int a[4];
|
||||
|
||||
decoding_table[0] = 0;
|
||||
decoding_table[1] = 1;
|
||||
temp = 1;
|
||||
for (i=2; i<= 23; i++)
|
||||
{
|
||||
temp = temp << 1;
|
||||
decoding_table[get_syndrome(temp)] = temp;
|
||||
}
|
||||
|
||||
a[1] = 1;
|
||||
a[2] = 2;
|
||||
temp = arr2int(a,2);
|
||||
decoding_table[get_syndrome(temp)] = temp;
|
||||
for (i=1; i<253; i++)
|
||||
{
|
||||
nextcomb(23,2,a);
|
||||
temp = arr2int(a,2);
|
||||
decoding_table[get_syndrome(temp)] = temp;
|
||||
}
|
||||
|
||||
a[1] = 1;
|
||||
a[2] = 2;
|
||||
a[3] = 3;
|
||||
temp = arr2int(a,3);
|
||||
decoding_table[get_syndrome(temp)] = temp;
|
||||
for (i=1; i<1771; i++)
|
||||
{
|
||||
nextcomb(23,3,a);
|
||||
temp = arr2int(a,3);
|
||||
decoding_table[get_syndrome(temp)] = temp;
|
||||
}
|
||||
|
||||
init_prng();
|
||||
}
|
||||
|
||||
|
||||
static int golay2412 (int data, int *decoded)
|
||||
{
|
||||
int block = (data >> 1) & 0x07fffff;
|
||||
int corrected_block = block ^ decoding_table[get_syndrome(block)];
|
||||
|
||||
int errs = 0;
|
||||
int parity_corr = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 23; i++)
|
||||
{
|
||||
int mask = 1 << i;
|
||||
|
||||
int bit_rcvd = block & mask;
|
||||
int bit_corr = corrected_block & mask;
|
||||
|
||||
if (bit_corr != 0)
|
||||
{
|
||||
parity_corr ++;
|
||||
}
|
||||
|
||||
if (bit_rcvd != bit_corr)
|
||||
{
|
||||
errs ++;
|
||||
}
|
||||
}
|
||||
|
||||
if ((parity_corr & 0x01) != (data & 0x01))
|
||||
{
|
||||
errs ++;
|
||||
}
|
||||
|
||||
*decoded = corrected_block >> 11;
|
||||
|
||||
return errs;
|
||||
}
|
||||
|
||||
|
||||
int dstar_dv_decode_first_block (const unsigned char * d, int * errs)
|
||||
{
|
||||
int bits[3];
|
||||
int i;
|
||||
int data;
|
||||
|
||||
for (i=0; i < 3; i++)
|
||||
{
|
||||
bits[i] = 0;
|
||||
}
|
||||
|
||||
for (i=0; i < 72; i++)
|
||||
{
|
||||
bits[ bit_pos1[i] ] |= (d[ i >> 3 ] & (0x80 >> (i & 0x07))) ? (1 << bit_pos2[i]) : 0;
|
||||
}
|
||||
|
||||
*errs = golay2412( bits[0], & data );
|
||||
|
||||
return data;
|
||||
|
||||
}
|
||||
|
||||
int dstar_dv_decode (const unsigned char * d, int data[3])
|
||||
{
|
||||
int bits[3];
|
||||
int i;
|
||||
int errs;
|
||||
|
||||
for (i=0; i < 3; i++)
|
||||
{
|
||||
bits[i] = 0;
|
||||
}
|
||||
|
||||
for (i=0; i < 72; i++)
|
||||
{
|
||||
bits[ bit_pos1[i] ] |= (d[ i >> 3 ] & (0x80 >> (i & 0x07))) ? (1 << bit_pos2[i]) : 0;
|
||||
}
|
||||
|
||||
errs = golay2412( bits[0], data );
|
||||
|
||||
errs += golay2412( bits[1] ^ prng[ data[0] & 0x0fff ], data + 1 );
|
||||
|
||||
data[2] = bits[2];
|
||||
|
||||
return errs;
|
||||
}
|
||||
|
||||
@ -0,0 +1,48 @@
|
||||
/*
|
||||
|
||||
ircDDB-mheard
|
||||
|
||||
Copyright (C) 2010 Michael Dirska, DL1BFF (dl1bff@mdx.de)
|
||||
|
||||
This program 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, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
/* Call this function first before using any of the other functions */
|
||||
void dstar_dv_init(void);
|
||||
|
||||
/*
|
||||
This function decodes the first and most important Golay block
|
||||
of a DSTAR Digital Voice frame. The function is provided with a
|
||||
pointer to the 9-byte voice data. Result is the decoded
|
||||
first block. The number of decoding errors is reported in the
|
||||
variable errs and ranges from 0 to 4. Only 24 bits are
|
||||
checked, the BER therefore is: BER = errs / 24
|
||||
*/
|
||||
int dstar_dv_decode_first_block (const unsigned char * d, int * errs);
|
||||
|
||||
/*
|
||||
This function decodes the both Golay blocks
|
||||
of a DSTAR Digital Voice frame. The function is provided with a
|
||||
pointer to the 9-byte voice data. Function result is
|
||||
the number of decoding errors (0 to 8). Only 48 bits are
|
||||
checked, the BER therefore is: BER = errs / 48
|
||||
|
||||
The return value data[0] contains the first decoded golay block
|
||||
(12 bits). The return value data[1] contains the second decoded
|
||||
golay block (12 bits). The return value data[2] contains the
|
||||
unprotected rest of the frame (24 bits).
|
||||
*/
|
||||
int dstar_dv_decode (const unsigned char * d, int data[3]);
|
||||
|
||||
@ -0,0 +1,81 @@
|
||||
|
||||
# This is the configuration file for the DVAP device(2m dongle with antenna)
|
||||
|
||||
# This is Dstar repeater callsign
|
||||
# Use a correct repeater call.
|
||||
# If you set RPTR different from the OWNER
|
||||
# then only the RF user identified by RPTR callsign can talk on this repeater.
|
||||
# This mode is called "restriction" mode and in some countries(UK,...)
|
||||
# it is the only valid mode that you can use, while waiting for a repeater license.
|
||||
# In a case like this, set RPTR to be your personal callsign
|
||||
RPTR=AC2IE
|
||||
|
||||
# This is the Gateway callsign
|
||||
# This must be equal to the OWNER value in the gateway software(g2_ircddb.cfg)
|
||||
OWNER=AC2IE
|
||||
|
||||
# To protect the repeater owners from bad STN programs out there
|
||||
# and to also protect the repeater owners from RF users that abuse the STN stuff
|
||||
# Reject values in YRCALL that start with STN
|
||||
# If you want to allow the local RF users to subscribe to remote STN groups,
|
||||
# then set it to XXX or something that is invalid like 123
|
||||
INVALID_YRCALL_KEY=STN
|
||||
|
||||
# This is the module of the Dstar repeater
|
||||
# Please read the comments about RPTR_PORT below
|
||||
RPTR_MOD=C
|
||||
|
||||
# This identifies the IP for the repeater(controler)
|
||||
# The DVAP device will run here
|
||||
# For repeater module A: RPTR_PORT=19998
|
||||
# For repeater module B: RPTR_PORT=19999
|
||||
# For repeater module C: RPTR_PORT=20000
|
||||
RPTR_VIRTUAL_IP=0.0.0.0
|
||||
RPTR_PORT=20000
|
||||
|
||||
# This is the INTERNAL IP and PORT of your local G2 gateway
|
||||
G2_INTERNAL_IP=127.0.0.1
|
||||
G2_PORT=19000
|
||||
|
||||
# This is the serial number of your DVAP device
|
||||
DVP_SERIAL=AP052344
|
||||
|
||||
# This is your 2m frequency for the DVAP device, Between 144000000 and 148000000
|
||||
DVP_FREQ=146550000;
|
||||
|
||||
# This is the power level for the DVAP device, Between -12 and 10
|
||||
DVP_PWR=10;
|
||||
|
||||
# This is the squelch setting for the DVAP device, between -128 and -45
|
||||
DVP_SQL=-80;
|
||||
|
||||
# This is the offset frequency for the DVAP device, between -2000 and 2000
|
||||
DVP_OFF=0;
|
||||
|
||||
# How long before we say that the local gateway has stopped sending packets to our repeater.
|
||||
# This value is in seconds.
|
||||
# Lets say that you set REMOTE_TIMEOUT=2 seconds and WAIT_FOR_PACKETS=25 milliseconds
|
||||
# The program does a small calculation: ( (REMOTE_TIMEOUT * 1000) / WAIT_FOR_PACKETS))
|
||||
# So that is (2000 / 25) = 80 = number_of_times_to_loop
|
||||
# This calculated value of 80 is the number of times we will loop waiting for
|
||||
# packets from the remote system.
|
||||
# A value of 2 is sufficient. Minimum is 1 seconds.
|
||||
REMOTE_TIMEOUT=2
|
||||
|
||||
# This is used in a loop to wait for packets from your local gateway
|
||||
# This is in milliseconds
|
||||
WAIT_FOR_PACKETS=25
|
||||
|
||||
# This is in seconds,
|
||||
# It allows the dvap to re-initialize before we send the repeater ack back to it
|
||||
DELAY_BEFORE=2
|
||||
|
||||
# This is in milliseconds
|
||||
# Dstar packets should reach the dvap at a rate of about 17-23 milliseconds
|
||||
# We use that when we send a repeater ack back to the DVAP
|
||||
DELAY_BETWEEN=19
|
||||
|
||||
# Do you want a repeater ack sent to dvap, after the local RF radio user releases PTT ?
|
||||
# Valid values are Y or N
|
||||
RPTR_ACK=Y
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,177 @@
|
||||
#
|
||||
# Copyright (C) 2010, 2011, 2012 by Scott Lawson KI4LKF
|
||||
#
|
||||
# This program 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; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program 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
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
#
|
||||
# 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
|
||||
# Must be in UPPERCASE, use the correct callsign of your Gateway
|
||||
OWNER=AC2IE
|
||||
|
||||
# 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
|
||||
|
||||
# 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.88451,-73.78889,1,DVAP
|
||||
|
||||
# Which local address on your Linux box will be used
|
||||
# to report to the remote IRC database server(group2, group1,...)
|
||||
# For most installations it is 0.0.0.0 (which binds to all local IP addresses)
|
||||
# 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
|
||||
|
||||
# This is for the Live IRC site
|
||||
SEND_QRGS_MAPS=N
|
||||
# LATITUDE, LONGITUDE, description1, description2, url
|
||||
QTH=42.88, -73.79, Dstar-rptr C, g2-ircddb
|
||||
# Frequency, shift, range, antenna's height above ground(agl)
|
||||
QRG_A=
|
||||
QRG_B=
|
||||
QRG_C=146.55, 0.0, 1, 10
|
||||
|
||||
# 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
|
||||
# How often to report the aprs beacon, in minutes, Do NOT make it less than 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
|
||||
|
||||
# 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
|
||||
|
||||
# Where is the g2_link running ?
|
||||
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_B=127.0.0.1
|
||||
TO_RPTR_PORT_B=19999
|
||||
|
||||
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.
|
||||
# Of course it can get lost, because everything about Dstar is on UDP
|
||||
# UDP is notorious for losing packets.
|
||||
# Each packet arrives normally 20ms after previous packet,
|
||||
# so giving it 1 second is more than enough.
|
||||
# This 1-second timeout was used internally in the g2_ircddb software,
|
||||
# but now the user has a chance to change it.
|
||||
# We do not believe that it should be changed,
|
||||
# As mentioned before, more than 1 second is more than
|
||||
# enough to make sure that we should stop waiting for more packets.
|
||||
|
||||
# Echotest-recording timeout:
|
||||
# If after 1 second, audio stops coming in for echotest-recording,
|
||||
# we will stop recording for ECHOTEST
|
||||
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
|
||||
|
||||
# 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
|
||||
|
||||
# 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
|
||||
|
||||
# print QSO details
|
||||
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
|
||||
|
||||
# Do you want to re-generate the HEADER if there is a timeout from
|
||||
# messages arriving from remote systems(reflectors, gateways, ...)
|
||||
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
|
||||
|
||||
DTMF_DIR=/tmp
|
||||
|
||||
# Directory of recorded files created in ECHOTEST/playback mode
|
||||
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
|
||||
# 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
|
||||
|
||||
# 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=stn570.dydns.org
|
||||
|
||||
# The remote ircDDB port
|
||||
IRC_DDB_PORT=9007
|
||||
|
||||
# Your ircDDB password given to you by the German ircDDB team.
|
||||
# Put your correct password here.
|
||||
IRC_PASS=1111111111111111
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,96 @@
|
||||
|
||||
# The ONLY values to change are: LOGIN_CALL, OWNER and ADMIN
|
||||
#
|
||||
|
||||
# Callsign to use to login to remote REF reflector
|
||||
# This is your personal user callsign
|
||||
# Remove the # sign and set your callsign correctly
|
||||
#
|
||||
LOGIN_CALL=AC2IE
|
||||
|
||||
# Because ONLY_ADMIN_LOGIN=Y
|
||||
# only these 3 users can connect to your gateway
|
||||
ADMIN=AC2IE
|
||||
ONLY_ADMIN_LOGIN=Y
|
||||
|
||||
# If you set ONLY_LINK_UNLINK=Y
|
||||
# then ONLY user callsigns identified by the option LINK_UNLINK_USER
|
||||
# can link or unlink your repeater.
|
||||
# If you set ONLY_LINK_UNLINK=N
|
||||
# then ANY user callsign can link or unlink your repeater.
|
||||
#
|
||||
ONLY_LINK_UNLINK=N
|
||||
LINK_UNLINK_USER=XX0XXX
|
||||
LINK_UNLINK_USER=YY0YYY
|
||||
LINK_UNLINK_USER=ZZ0ZZZ
|
||||
|
||||
# Local gateway callsign
|
||||
# This is your local G2 Gateway callsign
|
||||
# You should register this with the remote irc database server
|
||||
# Remove the # sign and set the gateway callsign correctly.
|
||||
#
|
||||
OWNER=AC2IE
|
||||
|
||||
# remote friends
|
||||
RMT_XRF_PORT=30001
|
||||
RMT_REF_PORT=20001
|
||||
RMT_DCS_PORT=30051
|
||||
|
||||
# Our server port so that the local g2 gateway can contact us
|
||||
# our g2_link will create/open this UDP port as a server
|
||||
MY_G2_LINK_IP=0.0.0.0
|
||||
MY_G2_LINK_PORT=18997
|
||||
|
||||
# The external g2 port of the local G2
|
||||
TO_G2_EXTERNAL_IP=127.0.0.1
|
||||
TO_G2_EXTERNAL_PORT=40000
|
||||
|
||||
QSO_DETAILS=N
|
||||
|
||||
# The reflectors
|
||||
GWYS=/usr/local/etc/gwys.txt
|
||||
|
||||
#LINK STATUS file
|
||||
STATUS_FILE=/usr/local/etc/RPT_STATUS.txt
|
||||
|
||||
# SEND an AUDIO announcements on LINK/UNLINK/INFO ?
|
||||
ANNOUNCE=Y
|
||||
# The directory where the "*.dat" files are located
|
||||
ANNOUNCE_DIR=/usr/local/etc
|
||||
|
||||
# Send a TEXT announcement on every key-up ?
|
||||
RPTR_ACK=N
|
||||
|
||||
# While sending back the announcement,
|
||||
# what is the delay in MILLISECONDS between each packet
|
||||
DELAY_BETWEEN=19
|
||||
|
||||
# How many seconds to delay before sending the announcement
|
||||
# Set it to 1
|
||||
# If your local repeater requires more time to initialize after releasing PTT, then set it to 2
|
||||
DELAY_BEFORE=1
|
||||
|
||||
# Try to link to this system after initialization
|
||||
# Leave the option blank, if you do not want automatic linking at startup
|
||||
#
|
||||
# Link your local repeater mod B to the remote reflector XRF005 mod A
|
||||
#
|
||||
LINK_AT_STARTUP=CXRF901A
|
||||
|
||||
# Maximum number of incoming hotspotNode or dongle connections(r2g2_p, r2g2_x, HotSpotNode,...)
|
||||
# If you do NOT want incoming HotSpotNode or dongle connections, set this to 0
|
||||
MAX_DONGLES=5
|
||||
|
||||
# Each RF band has an inactivity timer, in minutes.
|
||||
# If the timer is 0, then there is NO timer at all.
|
||||
# If the timer is greater than 0 and that RF band is linked
|
||||
# to a remote system, and no local RF activity has taken place
|
||||
# in the last minutes as set in the timer, then
|
||||
# automatically the RF band will unlink from the remote system.
|
||||
# This is done to protect the owner from local RF users that
|
||||
# link the RF band to a remote system,
|
||||
# and then go away.
|
||||
RF_INACTIVITY_TIMER_A=0
|
||||
RF_INACTIVITY_TIMER_B=0
|
||||
RF_INACTIVITY_TIMER_C=0
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,406 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010 by Scott Lawson KI4LKF
|
||||
*
|
||||
* This program 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; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/* by KI4LKF */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <time.h>
|
||||
|
||||
#define VERSION "v3.2"
|
||||
|
||||
static int sockDst = -1;
|
||||
static struct sockaddr_in toDst;
|
||||
static void dst_close();
|
||||
static bool dst_open(char *ip, int port);
|
||||
static void calcPFCS(unsigned char rawbytes[58]);
|
||||
|
||||
static time_t tNow = 0;
|
||||
static short streamid_raw = 0;
|
||||
|
||||
/***
|
||||
static char silence[12] =
|
||||
{
|
||||
0x4e,0x8d,0x32,0x88,0x26,0x1a,0x3f,0x61,0xe8,
|
||||
0x70,0x4f,0x93
|
||||
};
|
||||
***/
|
||||
|
||||
static char silence[12] =
|
||||
{
|
||||
0xfa,0x87,0x1e,0x32,0x30,0x2f,0xea,0x45,0x66,
|
||||
0x70,0x4f,0x93
|
||||
};
|
||||
|
||||
|
||||
static unsigned short crc_tabccitt[256] =
|
||||
{
|
||||
0x0000,0x1189,0x2312,0x329b,0x4624,0x57ad,0x6536,0x74bf,
|
||||
0x8c48,0x9dc1,0xaf5a,0xbed3,0xca6c,0xdbe5,0xe97e,0xf8f7,
|
||||
0x1081,0x0108,0x3393,0x221a,0x56a5,0x472c,0x75b7,0x643e,
|
||||
0x9cc9,0x8d40,0xbfdb,0xae52,0xdaed,0xcb64,0xf9ff,0xe876,
|
||||
0x2102,0x308b,0x0210,0x1399,0x6726,0x76af,0x4434,0x55bd,
|
||||
0xad4a,0xbcc3,0x8e58,0x9fd1,0xeb6e,0xfae7,0xc87c,0xd9f5,
|
||||
0x3183,0x200a,0x1291,0x0318,0x77a7,0x662e,0x54b5,0x453c,
|
||||
0xbdcb,0xac42,0x9ed9,0x8f50,0xfbef,0xea66,0xd8fd,0xc974,
|
||||
0x4204,0x538d,0x6116,0x709f,0x0420,0x15a9,0x2732,0x36bb,
|
||||
0xce4c,0xdfc5,0xed5e,0xfcd7,0x8868,0x99e1,0xab7a,0xbaf3,
|
||||
0x5285,0x430c,0x7197,0x601e,0x14a1,0x0528,0x37b3,0x263a,
|
||||
0xdecd,0xcf44,0xfddf,0xec56,0x98e9,0x8960,0xbbfb,0xaa72,
|
||||
0x6306,0x728f,0x4014,0x519d,0x2522,0x34ab,0x0630,0x17b9,
|
||||
0xef4e,0xfec7,0xcc5c,0xddd5,0xa96a,0xb8e3,0x8a78,0x9bf1,
|
||||
0x7387,0x620e,0x5095,0x411c,0x35a3,0x242a,0x16b1,0x0738,
|
||||
0xffcf,0xee46,0xdcdd,0xcd54,0xb9eb,0xa862,0x9af9,0x8b70,
|
||||
0x8408,0x9581,0xa71a,0xb693,0xc22c,0xd3a5,0xe13e,0xf0b7,
|
||||
0x0840,0x19c9,0x2b52,0x3adb,0x4e64,0x5fed,0x6d76,0x7cff,
|
||||
0x9489,0x8500,0xb79b,0xa612,0xd2ad,0xc324,0xf1bf,0xe036,
|
||||
0x18c1,0x0948,0x3bd3,0x2a5a,0x5ee5,0x4f6c,0x7df7,0x6c7e,
|
||||
0xa50a,0xb483,0x8618,0x9791,0xe32e,0xf2a7,0xc03c,0xd1b5,
|
||||
0x2942,0x38cb,0x0a50,0x1bd9,0x6f66,0x7eef,0x4c74,0x5dfd,
|
||||
0xb58b,0xa402,0x9699,0x8710,0xf3af,0xe226,0xd0bd,0xc134,
|
||||
0x39c3,0x284a,0x1ad1,0x0b58,0x7fe7,0x6e6e,0x5cf5,0x4d7c,
|
||||
0xc60c,0xd785,0xe51e,0xf497,0x8028,0x91a1,0xa33a,0xb2b3,
|
||||
0x4a44,0x5bcd,0x6956,0x78df,0x0c60,0x1de9,0x2f72,0x3efb,
|
||||
0xd68d,0xc704,0xf59f,0xe416,0x90a9,0x8120,0xb3bb,0xa232,
|
||||
0x5ac5,0x4b4c,0x79d7,0x685e,0x1ce1,0x0d68,0x3ff3,0x2e7a,
|
||||
0xe70e,0xf687,0xc41c,0xd595,0xa12a,0xb0a3,0x8238,0x93b1,
|
||||
0x6b46,0x7acf,0x4854,0x59dd,0x2d62,0x3ceb,0x0e70,0x1ff9,
|
||||
0xf78f,0xe606,0xd49d,0xc514,0xb1ab,0xa022,0x92b9,0x8330,
|
||||
0x7bc7,0x6a4e,0x58d5,0x495c,0x3de3,0x2c6a,0x1ef1,0x0f78
|
||||
};
|
||||
|
||||
static void calcPFCS(unsigned char rawbytes[58])
|
||||
{
|
||||
|
||||
unsigned short crc_dstar_ffff = 0xffff;
|
||||
unsigned short tmp, short_c;
|
||||
short int i;
|
||||
|
||||
for (i = 17; i < 56 ; i++)
|
||||
{
|
||||
short_c = 0x00ff & (unsigned short)rawbytes[i];
|
||||
tmp = (crc_dstar_ffff & 0x00ff) ^ short_c;
|
||||
crc_dstar_ffff = (crc_dstar_ffff >> 8) ^ crc_tabccitt[tmp];
|
||||
}
|
||||
crc_dstar_ffff = ~crc_dstar_ffff;
|
||||
tmp = crc_dstar_ffff;
|
||||
|
||||
rawbytes[56] = (unsigned char)(crc_dstar_ffff & 0xff);
|
||||
rawbytes[57] = (unsigned char)((tmp >> 8) & 0xff);
|
||||
return;
|
||||
}
|
||||
|
||||
static bool dst_open(char *ip, int port)
|
||||
{
|
||||
int reuse = 1;
|
||||
|
||||
sockDst = socket(PF_INET,SOCK_DGRAM,0);
|
||||
if (sockDst == -1)
|
||||
{
|
||||
printf("Failed to create DSTAR socket\n");
|
||||
return false;
|
||||
}
|
||||
if (setsockopt(sockDst,SOL_SOCKET,SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) == -1)
|
||||
{
|
||||
close(sockDst); sockDst = -1;
|
||||
printf("setsockopt DSTAR REUSE failed\n");
|
||||
return false;
|
||||
}
|
||||
memset(&toDst,0,sizeof(struct sockaddr_in));
|
||||
toDst.sin_family = AF_INET;
|
||||
toDst.sin_port = htons(port);
|
||||
toDst.sin_addr.s_addr = inet_addr(ip);
|
||||
|
||||
fcntl(sockDst,F_SETFL,O_NONBLOCK);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void dst_close()
|
||||
{
|
||||
if (sockDst != -1)
|
||||
{
|
||||
close(sockDst);
|
||||
sockDst = -1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
unsigned char dstar_buf[58];
|
||||
static unsigned short G2_COUNTER = 0;
|
||||
unsigned long delay;
|
||||
char RADIO_ID[21];
|
||||
short int i;
|
||||
|
||||
if (argc != 10)
|
||||
{
|
||||
printf("Usage: g2link_test <IPaddress> <port> <textMessage> <repeaterCallsign> <module> <delay_between> <delay_before> <MYCALL> <YRCALL>\n");
|
||||
printf("Example: g2link_test 127.0.0.1 19000 \"HELLO\" KJ4NHF B 20 2 KI4LKF XRF005AL\n");
|
||||
printf("Where...\n\n");
|
||||
printf(" 127.0.0.1 is the G2 INTERNAL IP of the G2 gateway\n");
|
||||
printf(" 19000 is the the G2 INTERNAL port of the G2 gateway\n");
|
||||
printf(" HELLO is the text message that we will send, no more than 20 characters\n");
|
||||
printf(" Note: the text message will be converted to UPPERCASE\n");
|
||||
printf(" KJ4NHF is your dstar repeater callsign\n");
|
||||
printf(" B is the local repeater module\n");
|
||||
printf(" 20 millisecond delay before each packet is sent\n");
|
||||
printf(" 2 second delay before the program starts processing your input \n");
|
||||
printf(" KI4LKF is the value of mycall\n");
|
||||
printf(" XRF005AL is the value of yrcall, in this case this is a Link command\n\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strlen(argv[4]) > 6)
|
||||
{
|
||||
printf("repeaterCallsign can not be more than 6 characters, %s is invalid\n", argv[4]);
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < 6; i++)
|
||||
argv[4][i] = toupper(argv[4][i]);
|
||||
|
||||
|
||||
if (strlen(argv[8]) > 8)
|
||||
{
|
||||
printf("MYCALL can not be nore than 8 characters, %s is invalid\n", argv[8]);
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < 8; i++)
|
||||
argv[8][i] = toupper(argv[8][i]);
|
||||
|
||||
|
||||
if (strlen(argv[9]) > 8)
|
||||
{
|
||||
printf("YRCALL can not be nore than 8 characters, %s is invalid\n", argv[9]);
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < 8; i++)
|
||||
argv[9][i] = toupper(argv[9][i]);
|
||||
|
||||
if ((argv[5][0] != 'A') && (argv[5][0] != 'B') && (argv[5][0] != 'C'))
|
||||
{
|
||||
printf("module must be one of A B C\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
delay = atol(argv[6]) * 1000L;
|
||||
sleep(atoi(argv[7]));
|
||||
|
||||
memset(RADIO_ID, ' ', 20);
|
||||
RADIO_ID[20] = '\0';
|
||||
memcpy(RADIO_ID, argv[3], (strlen(argv[3]) > 20)?20:strlen(argv[3]));
|
||||
|
||||
/***
|
||||
for (i = 0; i < 20; i++)
|
||||
RADIO_ID[i] = toupper(RADIO_ID[i]);
|
||||
***/
|
||||
|
||||
time(&tNow);
|
||||
srand(tNow + getpid());
|
||||
|
||||
if (dst_open(argv[1], atoi(argv[2])))
|
||||
{
|
||||
streamid_raw = (short)(::rand() & 0xFFFF);
|
||||
memcpy(dstar_buf,"DSTR", 4);
|
||||
dstar_buf[5] = (unsigned char)(G2_COUNTER & 0xff);
|
||||
dstar_buf[4] = (unsigned char)((G2_COUNTER >> 8) & 0xff);
|
||||
dstar_buf[6] = 0x73;
|
||||
dstar_buf[7] = 0x12;
|
||||
dstar_buf[8] = 0x00;
|
||||
dstar_buf[9] = 0x30;
|
||||
dstar_buf[10] = 0x20;
|
||||
|
||||
dstar_buf[11] = 0x00;
|
||||
dstar_buf[12] = 0x01;
|
||||
if (argv[5][0] == 'A')
|
||||
dstar_buf[13] = 0x03;
|
||||
else
|
||||
if (argv[5][0] == 'B')
|
||||
dstar_buf[13] = 0x01;
|
||||
else
|
||||
if (argv[5][0] == 'C')
|
||||
dstar_buf[13] = 0x02;
|
||||
else
|
||||
dstar_buf[13] = 0x00;
|
||||
|
||||
dstar_buf[14] = (unsigned char)(streamid_raw & 0xFF);
|
||||
dstar_buf[15] = (unsigned char)((streamid_raw >> 8) & 0xFF);
|
||||
dstar_buf[16] = 0x80;
|
||||
dstar_buf[17] = 0x00;
|
||||
dstar_buf[18] = 0x00;
|
||||
dstar_buf[19] = 0x00;
|
||||
|
||||
/* RPT2 */
|
||||
memcpy(dstar_buf + 20, argv[4], strlen(argv[4]));
|
||||
if (strlen(argv[4]) < 6)
|
||||
memset(dstar_buf + 20 + strlen(argv[4]), ' ', 6 - strlen(argv[4]));
|
||||
dstar_buf[26] = ' ';
|
||||
dstar_buf[27] = 'G';
|
||||
|
||||
/* RPT1 */
|
||||
memcpy(dstar_buf + 28, argv[4], strlen(argv[4]));
|
||||
if (strlen(argv[4]) < 6)
|
||||
memset(dstar_buf + 28 + strlen(argv[4]), ' ', 6 - strlen(argv[4]));
|
||||
dstar_buf[34] = ' ';
|
||||
dstar_buf[35] = argv[5][0];
|
||||
|
||||
/* YRCALL */
|
||||
memcpy(dstar_buf + 36, argv[9], strlen(argv[9]));
|
||||
if (strlen(argv[9]) < 8)
|
||||
memset(dstar_buf + 36 + strlen(argv[9]), ' ', 8 - strlen(argv[9]));
|
||||
|
||||
/* MYCALL */
|
||||
memcpy(dstar_buf + 44, argv[8], strlen(argv[8]));
|
||||
if (strlen(argv[8]) < 8)
|
||||
memset(dstar_buf + 44 + strlen(argv[8]), ' ', 8 - strlen(argv[8]));
|
||||
|
||||
/* suffix */
|
||||
memcpy(dstar_buf + 52, " ", 4);
|
||||
calcPFCS(dstar_buf);
|
||||
(void)sendto(sockDst,(char *)dstar_buf,58,0,(struct sockaddr *)&toDst,sizeof(toDst));
|
||||
G2_COUNTER ++;
|
||||
usleep(delay);
|
||||
|
||||
dstar_buf[9] = 0x13;
|
||||
memcpy((char *)dstar_buf + 17, silence, 9);
|
||||
|
||||
/* start sending silence + text */
|
||||
|
||||
/* SYNC */
|
||||
dstar_buf[5] = (unsigned char)(G2_COUNTER & 0xff);
|
||||
dstar_buf[4] = (unsigned char)((G2_COUNTER >> 8) & 0xff);
|
||||
dstar_buf[16] = 0x00;
|
||||
dstar_buf[26] = 0x55;
|
||||
dstar_buf[27] = 0x2d;
|
||||
dstar_buf[28] = 0x16;
|
||||
(void)sendto(sockDst,(char *)dstar_buf,29,0,(struct sockaddr *)&toDst,sizeof(toDst));
|
||||
G2_COUNTER ++;
|
||||
usleep(delay);
|
||||
|
||||
dstar_buf[5] = (unsigned char)(G2_COUNTER & 0xff);
|
||||
dstar_buf[4] = (unsigned char)((G2_COUNTER >> 8) & 0xff);
|
||||
dstar_buf[16] = 0x01;
|
||||
dstar_buf[26] = '@' ^ 0x70;
|
||||
dstar_buf[27] = RADIO_ID[0] ^ 0x4f;
|
||||
dstar_buf[28] = RADIO_ID[1] ^ 0x93;
|
||||
(void)sendto(sockDst,(char *)dstar_buf,29,0,(struct sockaddr *)&toDst,sizeof(toDst));
|
||||
G2_COUNTER ++;
|
||||
usleep(delay);
|
||||
|
||||
dstar_buf[5] = (unsigned char)(G2_COUNTER & 0xff);
|
||||
dstar_buf[4] = (unsigned char)((G2_COUNTER >> 8) & 0xff);
|
||||
dstar_buf[16] = 0x02;
|
||||
dstar_buf[26] = RADIO_ID[2] ^ 0x70;
|
||||
dstar_buf[27] = RADIO_ID[3] ^ 0x4f;
|
||||
dstar_buf[28] = RADIO_ID[4] ^ 0x93;
|
||||
(void)sendto(sockDst,(char *)dstar_buf,29,0,(struct sockaddr *)&toDst,sizeof(toDst));
|
||||
G2_COUNTER ++;
|
||||
usleep(delay);
|
||||
|
||||
dstar_buf[5] = (unsigned char)(G2_COUNTER & 0xff);
|
||||
dstar_buf[4] = (unsigned char)((G2_COUNTER >> 8) & 0xff);
|
||||
dstar_buf[16] = 0x03;
|
||||
dstar_buf[26] = 'A' ^ 0x70;
|
||||
dstar_buf[27] = RADIO_ID[5] ^ 0x4f;
|
||||
dstar_buf[28] = RADIO_ID[6] ^ 0x93;
|
||||
(void)sendto(sockDst,(char *)dstar_buf,29,0,(struct sockaddr *)&toDst,sizeof(toDst));
|
||||
G2_COUNTER ++;
|
||||
usleep(delay);
|
||||
|
||||
dstar_buf[5] = (unsigned char)(G2_COUNTER & 0xff);
|
||||
dstar_buf[4] = (unsigned char)((G2_COUNTER >> 8) & 0xff);
|
||||
dstar_buf[16] = 0x04;
|
||||
dstar_buf[26] = RADIO_ID[7] ^ 0x70;
|
||||
dstar_buf[27] = RADIO_ID[8] ^ 0x4f;
|
||||
dstar_buf[28] = RADIO_ID[9] ^ 0x93;
|
||||
(void)sendto(sockDst,(char *)dstar_buf,29,0,(struct sockaddr *)&toDst,sizeof(toDst));
|
||||
G2_COUNTER ++;
|
||||
usleep(delay);
|
||||
|
||||
dstar_buf[5] = (unsigned char)(G2_COUNTER & 0xff);
|
||||
dstar_buf[4] = (unsigned char)((G2_COUNTER >> 8) & 0xff);
|
||||
dstar_buf[16] = 0x05;
|
||||
dstar_buf[26] = 'B' ^ 0x70;
|
||||
dstar_buf[27] = RADIO_ID[10] ^ 0x4f;
|
||||
dstar_buf[28] = RADIO_ID[11] ^ 0x93;
|
||||
(void)sendto(sockDst,(char *)dstar_buf,29,0,(struct sockaddr *)&toDst,sizeof(toDst));
|
||||
G2_COUNTER ++;
|
||||
usleep(delay);
|
||||
|
||||
dstar_buf[5] = (unsigned char)(G2_COUNTER & 0xff);
|
||||
dstar_buf[4] = (unsigned char)((G2_COUNTER >> 8) & 0xff);
|
||||
dstar_buf[16] = 0x06;
|
||||
dstar_buf[26] = RADIO_ID[12] ^ 0x70;
|
||||
dstar_buf[27] = RADIO_ID[13] ^ 0x4f;
|
||||
dstar_buf[28] = RADIO_ID[14] ^ 0x93;
|
||||
(void)sendto(sockDst,(char *)dstar_buf,29,0,(struct sockaddr *)&toDst,sizeof(toDst));
|
||||
G2_COUNTER ++;
|
||||
usleep(delay);
|
||||
|
||||
dstar_buf[5] = (unsigned char)(G2_COUNTER & 0xff);
|
||||
dstar_buf[4] = (unsigned char)((G2_COUNTER >> 8) & 0xff);
|
||||
dstar_buf[16] = 0x07;
|
||||
dstar_buf[26] = 'C' ^ 0x70;
|
||||
dstar_buf[27] = RADIO_ID[15] ^ 0x4f;
|
||||
dstar_buf[28] = RADIO_ID[16] ^ 0x93;
|
||||
(void)sendto(sockDst,(char *)dstar_buf,29,0,(struct sockaddr *)&toDst,sizeof(toDst));
|
||||
G2_COUNTER ++;
|
||||
usleep(delay);
|
||||
|
||||
dstar_buf[5] = (unsigned char)(G2_COUNTER & 0xff);
|
||||
dstar_buf[4] = (unsigned char)((G2_COUNTER >> 8) & 0xff);
|
||||
dstar_buf[16] = 0x08;
|
||||
dstar_buf[26] = RADIO_ID[17] ^ 0x70;
|
||||
dstar_buf[27] = RADIO_ID[18] ^ 0x4f;
|
||||
dstar_buf[28] = RADIO_ID[19] ^ 0x93;
|
||||
(void)sendto(sockDst,(char *)dstar_buf,29,0,(struct sockaddr *)&toDst,sizeof(toDst));
|
||||
G2_COUNTER ++;
|
||||
usleep(delay);
|
||||
|
||||
dstar_buf[5] = (unsigned char)(G2_COUNTER & 0xff);
|
||||
dstar_buf[4] = (unsigned char)((G2_COUNTER >> 8) & 0xff);
|
||||
dstar_buf[16] = 0x09 | 0x40;
|
||||
|
||||
memset((char *)dstar_buf + 17, '\0', 9);
|
||||
|
||||
dstar_buf[26] = 0x70;
|
||||
dstar_buf[27] = 0x4f;
|
||||
dstar_buf[28] = 0x93;
|
||||
(void)sendto(sockDst,(char *)dstar_buf,29,0,(struct sockaddr *)&toDst,sizeof(toDst));
|
||||
G2_COUNTER ++;
|
||||
usleep(delay);
|
||||
|
||||
dst_close();
|
||||
}
|
||||
|
||||
printf("g2link_test exiting...\n");
|
||||
return 0;
|
||||
}
|
||||
@ -0,0 +1,399 @@
|
||||
|
||||
/* by KI4LKF */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <time.h>
|
||||
|
||||
#define VERSION "v3.1"
|
||||
|
||||
static int sockDst = -1;
|
||||
static struct sockaddr_in toDst;
|
||||
static void dst_close();
|
||||
static bool dst_open(char *ip, int port);
|
||||
static void calcPFCS(unsigned char rawbytes[58]);
|
||||
|
||||
static FILE *fp = NULL;
|
||||
static time_t tNow = 0;
|
||||
static short streamid_raw = 0;
|
||||
|
||||
static unsigned short crc_tabccitt[256] =
|
||||
{
|
||||
0x0000,0x1189,0x2312,0x329b,0x4624,0x57ad,0x6536,0x74bf,
|
||||
0x8c48,0x9dc1,0xaf5a,0xbed3,0xca6c,0xdbe5,0xe97e,0xf8f7,
|
||||
0x1081,0x0108,0x3393,0x221a,0x56a5,0x472c,0x75b7,0x643e,
|
||||
0x9cc9,0x8d40,0xbfdb,0xae52,0xdaed,0xcb64,0xf9ff,0xe876,
|
||||
0x2102,0x308b,0x0210,0x1399,0x6726,0x76af,0x4434,0x55bd,
|
||||
0xad4a,0xbcc3,0x8e58,0x9fd1,0xeb6e,0xfae7,0xc87c,0xd9f5,
|
||||
0x3183,0x200a,0x1291,0x0318,0x77a7,0x662e,0x54b5,0x453c,
|
||||
0xbdcb,0xac42,0x9ed9,0x8f50,0xfbef,0xea66,0xd8fd,0xc974,
|
||||
0x4204,0x538d,0x6116,0x709f,0x0420,0x15a9,0x2732,0x36bb,
|
||||
0xce4c,0xdfc5,0xed5e,0xfcd7,0x8868,0x99e1,0xab7a,0xbaf3,
|
||||
0x5285,0x430c,0x7197,0x601e,0x14a1,0x0528,0x37b3,0x263a,
|
||||
0xdecd,0xcf44,0xfddf,0xec56,0x98e9,0x8960,0xbbfb,0xaa72,
|
||||
0x6306,0x728f,0x4014,0x519d,0x2522,0x34ab,0x0630,0x17b9,
|
||||
0xef4e,0xfec7,0xcc5c,0xddd5,0xa96a,0xb8e3,0x8a78,0x9bf1,
|
||||
0x7387,0x620e,0x5095,0x411c,0x35a3,0x242a,0x16b1,0x0738,
|
||||
0xffcf,0xee46,0xdcdd,0xcd54,0xb9eb,0xa862,0x9af9,0x8b70,
|
||||
0x8408,0x9581,0xa71a,0xb693,0xc22c,0xd3a5,0xe13e,0xf0b7,
|
||||
0x0840,0x19c9,0x2b52,0x3adb,0x4e64,0x5fed,0x6d76,0x7cff,
|
||||
0x9489,0x8500,0xb79b,0xa612,0xd2ad,0xc324,0xf1bf,0xe036,
|
||||
0x18c1,0x0948,0x3bd3,0x2a5a,0x5ee5,0x4f6c,0x7df7,0x6c7e,
|
||||
0xa50a,0xb483,0x8618,0x9791,0xe32e,0xf2a7,0xc03c,0xd1b5,
|
||||
0x2942,0x38cb,0x0a50,0x1bd9,0x6f66,0x7eef,0x4c74,0x5dfd,
|
||||
0xb58b,0xa402,0x9699,0x8710,0xf3af,0xe226,0xd0bd,0xc134,
|
||||
0x39c3,0x284a,0x1ad1,0x0b58,0x7fe7,0x6e6e,0x5cf5,0x4d7c,
|
||||
0xc60c,0xd785,0xe51e,0xf497,0x8028,0x91a1,0xa33a,0xb2b3,
|
||||
0x4a44,0x5bcd,0x6956,0x78df,0x0c60,0x1de9,0x2f72,0x3efb,
|
||||
0xd68d,0xc704,0xf59f,0xe416,0x90a9,0x8120,0xb3bb,0xa232,
|
||||
0x5ac5,0x4b4c,0x79d7,0x685e,0x1ce1,0x0d68,0x3ff3,0x2e7a,
|
||||
0xe70e,0xf687,0xc41c,0xd595,0xa12a,0xb0a3,0x8238,0x93b1,
|
||||
0x6b46,0x7acf,0x4854,0x59dd,0x2d62,0x3ceb,0x0e70,0x1ff9,
|
||||
0xf78f,0xe606,0xd49d,0xc514,0xb1ab,0xa022,0x92b9,0x8330,
|
||||
0x7bc7,0x6a4e,0x58d5,0x495c,0x3de3,0x2c6a,0x1ef1,0x0f78
|
||||
};
|
||||
|
||||
|
||||
|
||||
static void calcPFCS(unsigned char rawbytes[58])
|
||||
{
|
||||
unsigned short crc_dstar_ffff = 0xffff;
|
||||
unsigned short tmp, short_c;
|
||||
short int i;
|
||||
|
||||
for (i = 17; i < 56 ; i++)
|
||||
{
|
||||
short_c = 0x00ff & (unsigned short)rawbytes[i];
|
||||
tmp = (crc_dstar_ffff & 0x00ff) ^ short_c;
|
||||
crc_dstar_ffff = (crc_dstar_ffff >> 8) ^ crc_tabccitt[tmp];
|
||||
}
|
||||
crc_dstar_ffff = ~crc_dstar_ffff;
|
||||
tmp = crc_dstar_ffff;
|
||||
|
||||
rawbytes[56] = (unsigned char)(crc_dstar_ffff & 0xff);
|
||||
rawbytes[57] = (unsigned char)((tmp >> 8) & 0xff);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
static bool dst_open(char *ip, int port)
|
||||
{
|
||||
int reuse = 1;
|
||||
|
||||
sockDst = socket(PF_INET,SOCK_DGRAM,0);
|
||||
if (sockDst == -1)
|
||||
{
|
||||
printf("Failed to create DSTAR socket\n");
|
||||
return false;
|
||||
}
|
||||
if (setsockopt(sockDst,SOL_SOCKET,SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) == -1)
|
||||
{
|
||||
close(sockDst); sockDst = -1;
|
||||
printf("setsockopt DSTAR REUSE failed\n");
|
||||
return false;
|
||||
}
|
||||
memset(&toDst,0,sizeof(struct sockaddr_in));
|
||||
toDst.sin_family = AF_INET;
|
||||
toDst.sin_port = htons(port);
|
||||
toDst.sin_addr.s_addr = inet_addr(ip);
|
||||
|
||||
fcntl(sockDst,F_SETFL,O_NONBLOCK);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void dst_close()
|
||||
{
|
||||
if (sockDst != -1)
|
||||
{
|
||||
close(sockDst);
|
||||
sockDst = -1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
unsigned short rlen = 0;
|
||||
static unsigned short G2_COUNTER = 0;
|
||||
size_t nread = 0;
|
||||
unsigned char dstar_buf[56];
|
||||
unsigned char rptr_buf[58];
|
||||
unsigned long delay;
|
||||
unsigned short i;
|
||||
char RADIO_ID[21];
|
||||
short int TEXT_idx = 0;
|
||||
|
||||
if (argc != 10)
|
||||
{
|
||||
printf("Usage: g2link_test_audio <IPaddress> <port> <dvtoolFile> <repeaterCallsign> <module> <delay_between> <delay_before> <MYCALL> <YRCALL>\n");
|
||||
printf("Example: g2link_test_audio 127.0.0.1 19000 somefile.dvtool KJ4NHF B 19 2 KI4LKF CQCQCQ\n");
|
||||
printf("Where...\n");
|
||||
printf(" 127.0.0.1 is the IP address of the local G2\n");
|
||||
printf(" 19000 is the port of the INTERNAL G2\n");
|
||||
printf(" somefile.dvtool is a dvtool file\n");
|
||||
printf(" KJ4NHF is your G2 callsign, dont use KJ4NHF\n");
|
||||
printf(" B is one of your modules\n");
|
||||
printf(" 19 millisecond delay between each packet\n");
|
||||
printf(" 2 second delay before we begin this test\n");
|
||||
printf(" mycall is KI4LKF, your personal callsign, do not use KI4LKF\n");
|
||||
printf(" yrcall is CQCQCQ\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strlen(argv[4]) > 6)
|
||||
{
|
||||
printf("repeaterCallsign can not be more than 6 characters, %s is invalid\n", argv[4]);
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < strlen(argv[4]); i++)
|
||||
argv[4][i] = toupper(argv[4][i]);
|
||||
|
||||
if ((argv[5][0] != 'A') && (argv[5][0] != 'B') && (argv[5][0] != 'C'))
|
||||
{
|
||||
printf("module must be one of A B C\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strlen(argv[8]) > 8)
|
||||
{
|
||||
printf("No more than 8 characters in MYCALL\n");
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < strlen(argv[8]); i++)
|
||||
argv[8][i] = toupper(argv[8][i]);
|
||||
|
||||
if (strlen(argv[9]) > 8)
|
||||
{
|
||||
printf("No more than 8 characters in YRCALL\n");
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < strlen(argv[9]); i++)
|
||||
argv[9][i] = toupper(argv[9][i]);
|
||||
|
||||
|
||||
fp = fopen(argv[3], "rb");
|
||||
if (!fp)
|
||||
{
|
||||
printf("Failed to open file %s for reading\n", argv[3]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* stupid DVTOOL + 4 byte num_of_records */
|
||||
nread = fread(dstar_buf, 10, 1, fp);
|
||||
if (nread != 1)
|
||||
{
|
||||
printf("Cant read first 10 bytes\n");
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
if (memcmp(dstar_buf, "DVTOOL", 6) != 0)
|
||||
{
|
||||
printf("DVTOOL not found\n");
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(RADIO_ID, ' ', 20);
|
||||
RADIO_ID[20] = '\0';
|
||||
|
||||
memcpy(RADIO_ID, "TEST", 4);
|
||||
|
||||
delay = atol(argv[6]) * 1000L;
|
||||
sleep(atoi(argv[7]));
|
||||
|
||||
time(&tNow);
|
||||
srand(tNow + getpid());
|
||||
|
||||
if (dst_open(argv[1], atoi(argv[2])))
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
/* 2 byte length */
|
||||
nread = fread(&rlen, 2, 1, fp);
|
||||
if (nread != 1)
|
||||
{
|
||||
printf("End-Of-File\n");
|
||||
break;
|
||||
}
|
||||
if (rlen == 56)
|
||||
streamid_raw = (short)(::rand() & 0xFFFF);
|
||||
else
|
||||
if (rlen == 27)
|
||||
;
|
||||
else
|
||||
{
|
||||
printf("Not 56-byte and not 27-byte\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/* read the packet */
|
||||
nread = fread(dstar_buf, rlen, 1, fp);
|
||||
if (nread == 1)
|
||||
{
|
||||
if (memcmp(dstar_buf, "DSVT", 4) != 0)
|
||||
{
|
||||
printf("DVST not found\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (dstar_buf[8] != 0x20)
|
||||
{
|
||||
printf("Not Voice type\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (dstar_buf[4] == 0x10)
|
||||
;
|
||||
else
|
||||
if (dstar_buf[4] == 0x20)
|
||||
;
|
||||
else
|
||||
{
|
||||
printf("Not a valid record type\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (rlen == 56)
|
||||
{
|
||||
memcpy(rptr_buf, "DSTR", 4);
|
||||
rptr_buf[5] = (unsigned char)(G2_COUNTER & 0xff);
|
||||
rptr_buf[4] = (unsigned char)((G2_COUNTER >> 8) & 0xff);
|
||||
rptr_buf[6] = 0x73;
|
||||
rptr_buf[7] = 0x12;
|
||||
rptr_buf[8] = 0x00;
|
||||
rptr_buf[9] = 0x30;
|
||||
rptr_buf[10] = 0x20;
|
||||
memcpy(rptr_buf + 11, dstar_buf + 9, 47);
|
||||
|
||||
rptr_buf[14] = (unsigned char)(streamid_raw & 0xFF);
|
||||
rptr_buf[15] = (unsigned char)((streamid_raw >> 8) & 0xFF);
|
||||
|
||||
memcpy(rptr_buf + 20, argv[4], strlen(argv[4]));
|
||||
if (strlen(argv[4]) < 6)
|
||||
memset(rptr_buf + 20 + strlen(argv[4]), ' ', 6 - strlen(argv[4]));
|
||||
rptr_buf[26] = ' ';
|
||||
rptr_buf[27] = 'G';
|
||||
|
||||
memcpy(rptr_buf + 28, argv[4], strlen(argv[4]));
|
||||
if (strlen(argv[4]) < 6)
|
||||
memset(rptr_buf + 28 + strlen(argv[4]), ' ', 6 - strlen(argv[4]));
|
||||
rptr_buf[34] = ' ';
|
||||
rptr_buf[35] = argv[5][0];
|
||||
|
||||
/* yrcall */
|
||||
memcpy(rptr_buf + 36, argv[9], strlen(argv[9]));
|
||||
if (strlen(argv[9]) < 8)
|
||||
memset(rptr_buf + 36 + strlen(argv[9]), ' ', 8 - strlen(argv[9]));
|
||||
|
||||
/* mycall */
|
||||
memcpy(rptr_buf + 44, argv[8], strlen(argv[8]));
|
||||
if (strlen(argv[8]) < 8)
|
||||
memset(rptr_buf + 44 + strlen(argv[8]), ' ', 8 - strlen(argv[8]));
|
||||
|
||||
memcpy(rptr_buf + 52, "TEST", 4);
|
||||
|
||||
calcPFCS(rptr_buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
rptr_buf[5] = (unsigned char)(G2_COUNTER & 0xff);
|
||||
rptr_buf[4] = (unsigned char)((G2_COUNTER >> 8) & 0xff);
|
||||
rptr_buf[9] = 0x13;
|
||||
|
||||
if ((dstar_buf[24] != 0x55) ||
|
||||
(dstar_buf[25] != 0x2d) ||
|
||||
(dstar_buf[26] != 0x16))
|
||||
{
|
||||
if (TEXT_idx == 0)
|
||||
{
|
||||
dstar_buf[24] = '@' ^ 0x70;
|
||||
dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f;
|
||||
dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93;
|
||||
}
|
||||
else
|
||||
if (TEXT_idx == 2)
|
||||
{
|
||||
dstar_buf[24] = RADIO_ID[TEXT_idx++] ^ 0x70;
|
||||
dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f;
|
||||
dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93;
|
||||
}
|
||||
else
|
||||
if (TEXT_idx == 5)
|
||||
{
|
||||
dstar_buf[24] = 'A' ^ 0x70;
|
||||
dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f;
|
||||
dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93;
|
||||
}
|
||||
else
|
||||
if (TEXT_idx == 7)
|
||||
{
|
||||
dstar_buf[24] = RADIO_ID[TEXT_idx++] ^ 0x70;
|
||||
dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f;
|
||||
dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93;
|
||||
}
|
||||
else
|
||||
if (TEXT_idx == 10)
|
||||
{
|
||||
dstar_buf[24] = 'B' ^ 0x70;
|
||||
dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f;
|
||||
dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93;
|
||||
}
|
||||
else
|
||||
if (TEXT_idx == 12)
|
||||
{
|
||||
dstar_buf[24] = RADIO_ID[TEXT_idx++] ^ 0x70;
|
||||
dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f;
|
||||
dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93;
|
||||
}
|
||||
else
|
||||
if (TEXT_idx == 15)
|
||||
{
|
||||
dstar_buf[24] = 'C' ^ 0x70;
|
||||
dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f;
|
||||
dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93;
|
||||
}
|
||||
else
|
||||
if (TEXT_idx == 17)
|
||||
{
|
||||
dstar_buf[24] = RADIO_ID[TEXT_idx++] ^ 0x70;
|
||||
dstar_buf[25] = RADIO_ID[TEXT_idx++] ^ 0x4f;
|
||||
dstar_buf[26] = RADIO_ID[TEXT_idx++] ^ 0x93;
|
||||
}
|
||||
else
|
||||
{
|
||||
dstar_buf[24] = 0x70;
|
||||
dstar_buf[25] = 0x4f;
|
||||
dstar_buf[26] = 0x93;
|
||||
}
|
||||
}
|
||||
memcpy(rptr_buf + 11, dstar_buf + 9, 18);
|
||||
rptr_buf[14] = (unsigned char)(streamid_raw & 0xFF);
|
||||
rptr_buf[15] = (unsigned char)((streamid_raw >> 8) & 0xFF);
|
||||
}
|
||||
|
||||
sendto(sockDst,(char *)rptr_buf,rlen + 2,0,
|
||||
(struct sockaddr *)&toDst,sizeof(toDst));
|
||||
G2_COUNTER ++;
|
||||
|
||||
}
|
||||
usleep(delay);
|
||||
}
|
||||
dst_close();
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
printf("g2link_test_audio exiting...\n");
|
||||
return 0;
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
#/bin/bash
|
||||
|
||||
/bin/cp ./gwys.txt ./gwys.txt.bak
|
||||
/bin/rm -rf ./gwys.txt
|
||||
|
||||
wget http://www.va3uv.com/gwys.txt
|
||||
|
||||
#/sbin/service g2_link restart
|
||||
|
||||
exit 0
|
||||
@ -0,0 +1,280 @@
|
||||
/*
|
||||
This file was downloaded from this URL:
|
||||
|
||||
http://www.eccpage.com/golay23.c
|
||||
|
||||
Some source code lines were commented out.
|
||||
|
||||
2010-12-01 DL1BFF
|
||||
*/
|
||||
|
||||
/* File: golay23.c
|
||||
* Title: Encoder/decoder for a binary (23,12,7) Golay code
|
||||
* Author: Robert Morelos-Zaragoza (robert@spectra.eng.hawaii.edu)
|
||||
* Date: August 1994
|
||||
*
|
||||
* The binary (23,12,7) Golay code is an example of a perfect code, that is,
|
||||
* the number of syndromes equals the number of correctable error patterns.
|
||||
* The minimum distance is 7, so all error patterns of Hamming weight up to
|
||||
* 3 can be corrected. The total number of these error patterns is:
|
||||
*
|
||||
* Number of errors Number of patterns
|
||||
* ---------------- ------------------
|
||||
* 0 1
|
||||
* 1 23
|
||||
* 2 253
|
||||
* 3 1771
|
||||
* ----
|
||||
* Total number of error patterns = 2048 = 2^{11} = number of syndromes
|
||||
* --
|
||||
* number of redundant bits -------^
|
||||
*
|
||||
* Because of its relatively low length (23), dimension (12) and number of
|
||||
* redundant bits (11), the binary (23,12,7) Golay code can be encoded and
|
||||
* decoded simply by using look-up tables. The program below uses a 16K
|
||||
* encoding table and an 8K decoding table.
|
||||
*
|
||||
* For more information, suggestions, or other ideas on implementing error
|
||||
* correcting codes, please contact me at (I'm temporarily in Japan, but
|
||||
* below is my U.S. address):
|
||||
*
|
||||
* Robert Morelos-Zaragoza
|
||||
* 770 S. Post Oak Ln. #200
|
||||
* Houston, Texas 77056
|
||||
*
|
||||
* email: robert@spectra.eng.hawaii.edu
|
||||
*
|
||||
* Homework: Add an overall parity-check bit to get the (24,12,8)
|
||||
* extended Golay code.
|
||||
*
|
||||
* COPYRIGHT NOTICE: This computer program is free for non-commercial purposes.
|
||||
* You may implement this program for any non-commercial application. You may
|
||||
* also implement this program for commercial purposes, provided that you
|
||||
* obtain my written permission. Any modification of this program is covered
|
||||
* by this copyright.
|
||||
*
|
||||
* == Copyright (c) 1994 Robert Morelos-Zaragoza. All rights reserved. ==
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#define X22 0x00400000 /* vector representation of X^{22} */
|
||||
#define X11 0x00000800 /* vector representation of X^{11} */
|
||||
#define MASK12 0xfffff800 /* auxiliary vector for testing */
|
||||
#define GENPOL 0x00000c75 /* generator polinomial, g(x) */
|
||||
|
||||
/* Global variables:
|
||||
*
|
||||
* pattern = error pattern, or information, or received vector
|
||||
* encoding_table[] = encoding table
|
||||
* decoding_table[] = decoding table
|
||||
* data = information bits, i(x)
|
||||
* codeword = code bits = x^{11}i(x) + (x^{11}i(x) mod g(x))
|
||||
* numerr = number of errors = Hamming weight of error polynomial e(x)
|
||||
* position[] = error positions in the vector representation of e(x)
|
||||
* recd = representation of corrupted received polynomial r(x) = c(x) + e(x)
|
||||
* decerror = number of decoding errors
|
||||
* a[] = auxiliary array to generate correctable error patterns
|
||||
*/
|
||||
|
||||
// long pattern;
|
||||
// long encoding_table[4096], decoding_table[2048];
|
||||
// long data, codeword, recd;
|
||||
// long position[23] = { 0x00000001, 0x00000002, 0x00000004, 0x00000008,
|
||||
// 0x00000010, 0x00000020, 0x00000040, 0x00000080,
|
||||
// 0x00000100, 0x00000200, 0x00000400, 0x00000800,
|
||||
// 0x00001000, 0x00002000, 0x00004000, 0x00008000,
|
||||
// 0x00010000, 0x00020000, 0x00040000, 0x00080000,
|
||||
// 0x00100000, 0x00200000, 0x00400000 };
|
||||
// long numerr, errpos[23], decerror = 0;
|
||||
// int a[4];
|
||||
|
||||
long arr2int(int *a, int r)
|
||||
/*
|
||||
* Convert a binary vector of Hamming weight r, and nonzero positions in
|
||||
* array a[1]...a[r], to a long integer \sum_{i=1}^r 2^{a[i]-1}.
|
||||
*/
|
||||
{
|
||||
int i;
|
||||
long mul, result = 0, temp;
|
||||
|
||||
for (i=1; i<=r; i++) {
|
||||
mul = 1;
|
||||
temp = a[i]-1;
|
||||
while (temp--)
|
||||
mul = mul << 1;
|
||||
result += mul;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
void nextcomb(int n, int r, int *a)
|
||||
/*
|
||||
* Calculate next r-combination of an n-set.
|
||||
*/
|
||||
{
|
||||
int i, j;
|
||||
|
||||
a[r]++;
|
||||
if (a[r] <= n)
|
||||
return;
|
||||
j = r - 1;
|
||||
while (a[j] == n - r + j)
|
||||
j--;
|
||||
for (i = r; i >= j; i--)
|
||||
a[i] = a[j] + i - j + 1;
|
||||
return;
|
||||
}
|
||||
|
||||
long get_syndrome(long pattern)
|
||||
/*
|
||||
* Compute the syndrome corresponding to the given pattern, i.e., the
|
||||
* remainder after dividing the pattern (when considering it as the vector
|
||||
* representation of a polynomial) by the generator polynomial, GENPOL.
|
||||
* In the program this pattern has several meanings: (1) pattern = infomation
|
||||
* bits, when constructing the encoding table; (2) pattern = error pattern,
|
||||
* when constructing the decoding table; and (3) pattern = received vector, to
|
||||
* obtain its syndrome in decoding.
|
||||
*/
|
||||
{
|
||||
// long aux = X22, aux2;
|
||||
long aux = X22;
|
||||
|
||||
if (pattern >= X11)
|
||||
while (pattern & MASK12) {
|
||||
while (!(aux & pattern))
|
||||
aux = aux >> 1;
|
||||
pattern ^= (aux/X11) * GENPOL;
|
||||
}
|
||||
return(pattern);
|
||||
}
|
||||
|
||||
// main()
|
||||
// {
|
||||
// register int i,j;
|
||||
// long temp;
|
||||
// int seed = 133757;
|
||||
//
|
||||
// /*
|
||||
// * ---------------------------------------------------------------------
|
||||
// * Generate ENCODING TABLE
|
||||
// *
|
||||
// * An entry to the table is an information vector, a 32-bit integer,
|
||||
// * whose 12 least significant positions are the information bits. The
|
||||
// * resulting value is a codeword in the (23,12,7) Golay code: A 32-bit
|
||||
// * integer whose 23 least significant bits are coded bits: Of these, the
|
||||
// * 12 most significant bits are information bits and the 11 least
|
||||
// * significant bits are redundant bits (systematic encoding).
|
||||
// * ---------------------------------------------------------------------
|
||||
// */
|
||||
// for (pattern = 0; pattern < 4096; pattern++) {
|
||||
// temp = pattern << 11; /* multiply information by X^{11} */
|
||||
// encoding_table[pattern] = temp + get_syndrome(temp);/* add redundancy */
|
||||
// }
|
||||
//
|
||||
// /*
|
||||
// * ---------------------------------------------------------------------
|
||||
// * Generate DECODING TABLE
|
||||
// *
|
||||
// * An entry to the decoding table is a syndrome and the resulting value
|
||||
// * is the most likely error pattern. First an error pattern is generated.
|
||||
// * Then its syndrome is calculated and used as a pointer to the table
|
||||
// * where the error pattern value is stored.
|
||||
// * ---------------------------------------------------------------------
|
||||
// *
|
||||
// * (1) Error patterns of WEIGHT 1 (SINGLE ERRORS)
|
||||
// */
|
||||
// decoding_table[0] = 0;
|
||||
// decoding_table[1] = 1;
|
||||
// temp = 1;
|
||||
// for (i=2; i<= 23; i++) {
|
||||
// temp *= 2;
|
||||
// decoding_table[get_syndrome(temp)] = temp;
|
||||
// }
|
||||
// /*
|
||||
// * (2) Error patterns of WEIGHT 2 (DOUBLE ERRORS)
|
||||
// */
|
||||
// a[1] = 1; a[2] = 2;
|
||||
// temp = arr2int(a,2);
|
||||
// decoding_table[get_syndrome(temp)] = temp;
|
||||
// for (i=1; i<253; i++) {
|
||||
// nextcomb(23,2,a);
|
||||
// temp = arr2int(a,2);
|
||||
// decoding_table[get_syndrome(temp)] = temp;
|
||||
// }
|
||||
// /*
|
||||
// * (3) Error patterns of WEIGHT 3 (TRIPLE ERRORS)
|
||||
// */
|
||||
// a[1] = 1; a[2] = 2; a[3] = 3;
|
||||
// temp = arr2int(a,3);
|
||||
// decoding_table[get_syndrome(temp)] = temp;
|
||||
// for (i=1; i<1771; i++) {
|
||||
// nextcomb(23,3,a);
|
||||
// temp = arr2int(a,3);
|
||||
// decoding_table[get_syndrome(temp)] = temp;
|
||||
// }
|
||||
//
|
||||
// /* ---------------------------------------------------------------------
|
||||
// * Generate DATA
|
||||
// * ---------------------------------------------------------------------
|
||||
// */
|
||||
// srandom(seed);
|
||||
// /*
|
||||
// * data = 12 information bits, an information polynomial i(x)
|
||||
// */
|
||||
// data = random() & 0x00000fff;
|
||||
// printf("data = %#012x\n", data);
|
||||
//
|
||||
// /*
|
||||
// * ---------------------------------------------------------------------
|
||||
// * ENCODING
|
||||
// * ---------------------------------------------------------------------
|
||||
// */
|
||||
// codeword = encoding_table[data];
|
||||
// printf("codeword = %#012x\n", codeword);
|
||||
//
|
||||
// /*
|
||||
// * ---------------------------------------------------------------------
|
||||
// * ERRORS
|
||||
// * ---------------------------------------------------------------------
|
||||
// */
|
||||
// printf("Enter the number of errors and their positions (0...22): ");
|
||||
// scanf("%d", &numerr);
|
||||
// for (i = 0; i < numerr; i++)
|
||||
// scanf("%d", &errpos[i]);
|
||||
//
|
||||
// /*
|
||||
// * ---------------------------------------------------------------------
|
||||
// * RECEIVED VECTOR
|
||||
// * ---------------------------------------------------------------------
|
||||
// */
|
||||
// recd = codeword;
|
||||
// if (numerr)
|
||||
// for (i = 0; i < numerr; i++)
|
||||
// recd ^= position[errpos[i]];
|
||||
// printf("received vector = %#012x\n", recd);
|
||||
//
|
||||
// /*
|
||||
// * ---------------------------------------------------------------------
|
||||
// * DECODING
|
||||
// * ---------------------------------------------------------------------
|
||||
// */
|
||||
// printf("syndrome = %#012x\n", get_syndrome(recd));
|
||||
// printf("error pattern = %#012x\n", decoding_table[get_syndrome(recd)]);
|
||||
// /*
|
||||
// * Calculate the syndrome, look up the corresponding error pattern and
|
||||
// * add it to the received vector.
|
||||
// */
|
||||
// recd ^= decoding_table[get_syndrome(recd)];
|
||||
// printf("decoded vector = %#012x\n", recd);
|
||||
// printf("recovered data = %#012x\n", (recd>>11));
|
||||
// printf("original data = %#012x\n", data);
|
||||
// /*
|
||||
// * DECODING ERRORS? Only the data portion is compared. Note that this
|
||||
// * is only possible in a simulation!
|
||||
// */
|
||||
// pattern = (recd ^ codeword) >> 11;
|
||||
// for (i=0; i<12; i++)
|
||||
// if (pattern&position[i])
|
||||
// decerror++;
|
||||
// printf("there were %d decoding errors\n", decerror);
|
||||
// }
|
||||
@ -0,0 +1,5 @@
|
||||
|
||||
long get_syndrome(long pattern);
|
||||
long arr2int(int a[], int r);
|
||||
void nextcomb(int n, int r, int a[]);
|
||||
|
||||
@ -0,0 +1,99 @@
|
||||
REF001 109.69.104.195 20001
|
||||
REF002 129.93.2.132 20001
|
||||
REF003 203.194.18.195 20001
|
||||
REF004 74.204.50.19 20001
|
||||
REF005 109.69.104.193 20001
|
||||
REF006 78.158.56.61 20001
|
||||
REF007 208.111.3.180 20001
|
||||
REF008 58.1.235.43 20001
|
||||
REF009 204.89.198.18 20001
|
||||
REF010 70.233.76.110 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
|
||||
REF016 204.244.106.103 20001
|
||||
REF017 80.69.86.233 20001
|
||||
REF018 187.50.254.20 20001
|
||||
REF019 208.87.120.144 20001
|
||||
REF020 50.199.88.20 20001
|
||||
REF023 202.191.108.226 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
|
||||
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
|
||||
REF041 129.105.15.195 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
|
||||
REF051 50.57.153.17 20001
|
||||
REF052 216.207.94.13 20001
|
||||
REF053 69.67.29.232 20001
|
||||
REF054 216.249.104.190 20001
|
||||
REF055 207.251.62.205 20001
|
||||
REF058 131.204.255.253 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
|
||||
XRF000 141.22.15.29 20001
|
||||
XRF001 75.76.90.90 20001
|
||||
XRF002 91.201.57.233 20001
|
||||
XRF003 95.110.226.76 20001
|
||||
XRF004 96.36.58.9 20001
|
||||
XRF005 216.16.240.236 20001
|
||||
XRF006 80.62.20.151 20001
|
||||
XRF007 84.232.6.94 20001
|
||||
XRF008 95.110.231.219 20001
|
||||
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
|
||||
XRF017 87.253.159.114 20001
|
||||
XRF018 199.167.129.166 20001
|
||||
XRF019 66.30.81.236 20001
|
||||
XRF020 204.244.106.101 20001
|
||||
XRF021 74.204.50.67 20001
|
||||
XRF023 141.75.245.225 20001
|
||||
XRF025 63.133.189.2 20001
|
||||
XRF026 139.13.100.34 20001
|
||||
XRF027 194.116.29.66 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
|
||||
XRF044 82.1.185.173 20001
|
||||
XRF055 95.110.229.195 20001
|
||||
XRF069 91.142.221.75 20001
|
||||
XRF073 147.102.7.34 20001
|
||||
XRF090 46.37.185.184 20001
|
||||
XRF099 76.71.89.114 20001
|
||||
XRF119 192.210.137.151 20001
|
||||
XRF121 192.254.139.186 20001
|
||||
XRF123 213.126.90.100 20001
|
||||
XRF310 199.167.193.147 20001
|
||||
XRF333 37.187.103.98 20001
|
||||
XRF353 94.173.206.53 20001
|
||||
XRF444 71.40.84.59 20001
|
||||
XRF555 199.167.193.205 20001
|
||||
XRF719 199.227.117.121 20001
|
||||
XRF727 108.33.72.83 20001
|
||||
XRF777 62.167.15.53 20001
|
||||
XRF780 96.53.97.22 20001
|
||||
XRF858 198.57.255.30 20001
|
||||
XRF901 199.167.193.219 20001
|
||||
XRF905 199.212.121.20 20001
|
||||
@ -0,0 +1,150 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This script finds files in the /tmp directory
|
||||
# The files have a name like x_mod_DTMF_NOTIFY, where x is one of 0 1 2
|
||||
# 0=A module,
|
||||
# 1=B module,
|
||||
# 2=C module
|
||||
# The contents of these files can be as follows:
|
||||
|
||||
# Example: 73 will unlink local module
|
||||
# Example: #02102 will link local module to XRF021 B
|
||||
# Example: D00126 will link local module to DCS001 Z
|
||||
# Example: *01601 will link local module to REF016 A
|
||||
# Example: 99 will report status of the link
|
||||
|
||||
# We set this to spaces, it will be set later
|
||||
LUSER=" "
|
||||
|
||||
# The G2 INTERNAL IP/Port
|
||||
G2_INT_IP=127.0.0.1
|
||||
G2_INT_PORT=19000
|
||||
|
||||
# This is the callsign of your Gateway, set it correctly
|
||||
G2=
|
||||
|
||||
cd /tmp
|
||||
echo started at `date`
|
||||
|
||||
while [ 1 ]
|
||||
do
|
||||
for i in `ls ?_mod_DTMF_NOTIFY 2>/dev/null`
|
||||
do
|
||||
echo found file $i at `date`
|
||||
x=${i:0:1}
|
||||
if [ "$x" = "0" ] ; then
|
||||
LOCAL_BAND=A
|
||||
elif [ "$x" = "1" ] ; then
|
||||
LOCAL_BAND=B
|
||||
elif [ "$x" = "2" ] ; then
|
||||
LOCAL_BAND=C
|
||||
else
|
||||
LOCAL_BAND=garbage
|
||||
fi
|
||||
|
||||
if [[ "$LOCAL_BAND" == "garbage" ]]
|
||||
then
|
||||
echo garbage value for local band
|
||||
else
|
||||
CMD=`head -n 1 $i 2>/dev/null`
|
||||
LUSER=`tail -n 1 $i 2>/dev/null`
|
||||
echo "... with these contents: " $CMD " " $LUSER
|
||||
if [ "$CMD" = "73" ] ; then
|
||||
echo Unlinking local band $LOCAL_BAND requested by $LUSER
|
||||
/usr/local/bin/g2link_test ${G2_INT_IP} ${G2_INT_PORT} "" $G2 ${LOCAL_BAND} 20 1 "$LUSER" " U" >/dev/null 2>&1
|
||||
echo
|
||||
elif [ "$CMD" = "99" ] ; then
|
||||
echo Link Status on local band $LOCAL_BAND requested by $LUSER
|
||||
/usr/local/bin/g2link_test ${G2_INT_IP} ${G2_INT_PORT} "" $G2 ${LOCAL_BAND} 20 1 "$LUSER" " I" >/dev/null 2>&1
|
||||
echo
|
||||
else
|
||||
LEN=${#CMD}
|
||||
if [ "$LEN" = "6" ] ; then
|
||||
PFX=${CMD:0:1}
|
||||
REMOTE_NODE=${CMD:1:3}
|
||||
REMOTE_BAND=${CMD:4:2}
|
||||
|
||||
if [ "$REMOTE_BAND" = "01" ] ; then
|
||||
REMOTE_BAND=A
|
||||
elif [ "$REMOTE_BAND" = "02" ] ; then
|
||||
REMOTE_BAND=B
|
||||
elif [ "$REMOTE_BAND" = "03" ] ; then
|
||||
REMOTE_BAND=C
|
||||
elif [ "$REMOTE_BAND" = "04" ] ; then
|
||||
REMOTE_BAND=D
|
||||
elif [ "$REMOTE_BAND" = "05" ] ; then
|
||||
REMOTE_BAND=E
|
||||
elif [ "$REMOTE_BAND" = "06" ] ; then
|
||||
REMOTE_BAND=F
|
||||
elif [ "$REMOTE_BAND" = "07" ] ; then
|
||||
REMOTE_BAND=G
|
||||
elif [ "$REMOTE_BAND" = "08" ] ; then
|
||||
REMOTE_BAND=H
|
||||
elif [ "$REMOTE_BAND" = "09" ] ; then
|
||||
REMOTE_BAND=I
|
||||
elif [ "$REMOTE_BAND" = "10" ] ; then
|
||||
REMOTE_BAND=J
|
||||
elif [ "$REMOTE_BAND" = "11" ] ; then
|
||||
REMOTE_BAND=K
|
||||
elif [ "$REMOTE_BAND" = "12" ] ; then
|
||||
REMOTE_BAND=L
|
||||
elif [ "$REMOTE_BAND" = "13" ] ; then
|
||||
REMOTE_BAND=M
|
||||
elif [ "$REMOTE_BAND" = "14" ] ; then
|
||||
REMOTE_BAND=N
|
||||
elif [ "$REMOTE_BAND" = "15" ] ; then
|
||||
REMOTE_BAND=O
|
||||
elif [ "$REMOTE_BAND" = "16" ] ; then
|
||||
REMOTE_BAND=P
|
||||
elif [ "$REMOTE_BAND" = "17" ] ; then
|
||||
REMOTE_BAND=Q
|
||||
elif [ "$REMOTE_BAND" = "18" ] ; then
|
||||
REMOTE_BAND=R
|
||||
elif [ "$REMOTE_BAND" = "19" ] ; then
|
||||
REMOTE_BAND=S
|
||||
elif [ "$REMOTE_BAND" = "20" ] ; then
|
||||
REMOTE_BAND=T
|
||||
elif [ "$REMOTE_BAND" = "21" ] ; then
|
||||
REMOTE_BAND=U
|
||||
elif [ "$REMOTE_BAND" = "22" ] ; then
|
||||
REMOTE_BAND=V
|
||||
elif [ "$REMOTE_BAND" = "23" ] ; then
|
||||
REMOTE_BAND=W
|
||||
elif [ "$REMOTE_BAND" = "24" ] ; then
|
||||
REMOTE_BAND=X
|
||||
elif [ "$REMOTE_BAND" = "25" ] ; then
|
||||
REMOTE_BAND=Y
|
||||
elif [ "$REMOTE_BAND" = "26" ] ; then
|
||||
REMOTE_BAND=Z
|
||||
else
|
||||
REMOTE_BAND=Z
|
||||
fi
|
||||
|
||||
if [ "$PFX" = "#" ] ; then
|
||||
RMT=XRF
|
||||
elif [ "$PFX" = "D" ] ; then
|
||||
RMT=DCS
|
||||
elif [ "$PFX" = "*" ] ; then
|
||||
RMT=REF
|
||||
else
|
||||
RMT=garbage
|
||||
fi
|
||||
|
||||
if [[ "$RMT" == "garbage" ]]
|
||||
then
|
||||
echo garbage value in prefix
|
||||
else
|
||||
echo linking local band $LOCAL_BAND to remote node ${RMT}${REMOTE_NODE} $REMOTE_BAND requested by $LUSER
|
||||
/usr/local/bin/g2link_test ${G2_INT_IP} ${G2_INT_PORT} "" $G2 ${LOCAL_BAND} 20 1 "$LUSER" ${RMT}${REMOTE_NODE}${REMOTE_BAND}L >/dev/null 2>&1
|
||||
echo
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
rm -f $i
|
||||
done
|
||||
sleep 3
|
||||
done
|
||||
|
||||
exit 0
|
||||
|
||||
@ -0,0 +1,60 @@
|
||||
#!/bin/sh
|
||||
# Start/stop the dstar dvap_rptr
|
||||
#
|
||||
### BEGIN INIT INFO
|
||||
# Provides: dvap_rptr
|
||||
# Required-Start: $null
|
||||
# Required-Stop: $null
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: dvap_rptr
|
||||
# Description: dvap_rptr
|
||||
### END INIT INFO
|
||||
|
||||
. /lib/lsb/init-functions
|
||||
|
||||
DVAP_RPTR_EXE=/usr/local/bin/dvap_rptr
|
||||
DVAP_RPTR_CFG=/usr/local/etc/dvap_rptr.cfg
|
||||
DVAP_RPTR_LOG-/var/log/dvap_rptr.log
|
||||
|
||||
start()
|
||||
{
|
||||
status_of_proc dvap_rptr >/dev/null
|
||||
RETVAL=$?
|
||||
if [ "$RETVAL" = "0" ] ; then
|
||||
echo "dvap_rptr already running"
|
||||
else
|
||||
echo -n "Starting dvap_rptr"
|
||||
start-stop-daemon --exec $DVAP_RPTR_EXE -S $DVAP_RPTR_CFG > $DVAP_RPTR_LOG 2>&1 &
|
||||
log_end_msg $?
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
stop() {
|
||||
start-stop-daemon --exec $DVAP_RPTR_EXE --retry 5 -K
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
start
|
||||
;;
|
||||
stop)
|
||||
stop
|
||||
;;
|
||||
restart)
|
||||
stop
|
||||
start
|
||||
;;
|
||||
status)
|
||||
echo -n "dvap_rptr "
|
||||
status_of_proc dvap_rptr
|
||||
;;
|
||||
|
||||
*) log_action_msg "Usage: /etc/init.d/dvap_rptr {start|stop|restart|status}"
|
||||
exit 2
|
||||
;;
|
||||
|
||||
esac
|
||||
exit 0
|
||||
|
||||
@ -0,0 +1,60 @@
|
||||
#!/bin/sh
|
||||
# Start/stop g2_ircddb
|
||||
#
|
||||
### BEGIN INIT INFO
|
||||
# Provides: g2_ircddb
|
||||
# Required-Start: $null
|
||||
# Required-Stop: $null
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: g2_ircddb
|
||||
# Description: g2_ircddb
|
||||
### END INIT INFO
|
||||
|
||||
. /lib/lsb/init-functions
|
||||
IRCDDB_EXE=/usr/local/bin/g2_ircddb
|
||||
IRCDDB_CFG=/usr/local/etc/g2_ircddb.cfg
|
||||
IRCDDB_LOG=/var/log/g2_ircddb.log
|
||||
|
||||
start() {
|
||||
|
||||
status_of_proc g2_ircddb >/dev/null
|
||||
RETVAL=$?
|
||||
if [ "$RETVAL" = "0" ] ; then
|
||||
echo "g2_ircddb already running"
|
||||
else
|
||||
echo -n "Starting g2_ircddb"
|
||||
start-stop-daemon --exec $IRCDDB_EXE -S $IRCDDB_CFG > $IRCDDB_LOG 2>&1 &
|
||||
log_end_msg $?
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
stop() {
|
||||
start-stop-daemon --exec $IRCDDB_EXE --retry 5 -K
|
||||
}
|
||||
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
start
|
||||
;;
|
||||
stop)
|
||||
stop
|
||||
;;
|
||||
restart)
|
||||
stop
|
||||
start
|
||||
;;
|
||||
|
||||
status)
|
||||
echo -n "g2_ircddb "
|
||||
status_of_proc g2_ircddb
|
||||
;;
|
||||
|
||||
*) log_action_msg "Usage: /etc/init.d/g2_ircddb {start|stop|restart|status}"
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
exit 0
|
||||
|
||||
@ -0,0 +1,61 @@
|
||||
|
||||
#!/bin/sh
|
||||
# Start/stop g2_link
|
||||
#
|
||||
### BEGIN INIT INFO
|
||||
# Provides: g2_link
|
||||
# Required-Start: $null
|
||||
# Required-Stop: $null
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: g2_link
|
||||
# Description: g2_link
|
||||
### END INIT INFO
|
||||
|
||||
. /lib/lsb/init-functions
|
||||
|
||||
G2_LINK_EXE=/usr/local/bin/g2_link
|
||||
G2_LINK_CFG=/usr/local/etc/g2_link.cfg
|
||||
G2_LINK_LOG=/var/log/g2_link.log
|
||||
|
||||
start() {
|
||||
|
||||
status_of_proc g2_link >/dev/null
|
||||
RETVAL=$?
|
||||
if [ "$RETVAL" = "0" ] ; then
|
||||
echo "g2_link already running"
|
||||
else
|
||||
echo -n "Starting g2_link"
|
||||
start-stop-daemon --exec $G2_LINK_EXE -S $G2_LINK_CFG > $G2_LINK_LOG 2>&1 &
|
||||
log_end_msg $?
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
stop() {
|
||||
start-stop-daemon --exec $G2_LINK_EXE --retry 5 -K
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
start
|
||||
;;
|
||||
stop)
|
||||
stop
|
||||
;;
|
||||
restart)
|
||||
stop
|
||||
start
|
||||
;;
|
||||
|
||||
status)
|
||||
echo -n "g2_link "
|
||||
status_of_proc g2_link
|
||||
;;
|
||||
|
||||
*) log_action_msg "Usage: /etc/init.d/g2_link {start|stop|restart|status}"
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
exit 0
|
||||
|
||||
@ -0,0 +1,63 @@
|
||||
#!/bin/sh
|
||||
# proc_g2_ircddb_dtmfs
|
||||
#
|
||||
|
||||
### BEGIN INIT INFO
|
||||
# Provides: proc_g2_ircddb_dtmfs
|
||||
# Required-Start: $syslog $network
|
||||
# Required-Stop: $syslog $network
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: proc_g2_ircddb_dtmfs
|
||||
# Description: proc_g2_ircddb_dtmfs
|
||||
### END INIT INFO
|
||||
|
||||
. /lib/lsb/init-functions
|
||||
|
||||
SHFILE=/usr/local/bin/proc_g2_ircddb_dtmfs.sh
|
||||
PIDFILE=/usr/local/bin/proc_g2_ircddb_dtmfs.sh_pidfile
|
||||
LOG=/var/log/proc_g2_ircddb_dtmfs.log
|
||||
|
||||
start() {
|
||||
|
||||
status_of_proc $SHFILE >/dev/null
|
||||
RETVAL=$?
|
||||
if [ "$RETVAL" = "0" ] ; then
|
||||
echo $SHFILE already running
|
||||
else
|
||||
echo -n Starting $SHFILE
|
||||
start-stop-daemon --make-pidfile --pidfile $PIDFILE --exec $SHFILE -S > $LOG 2>&1 &
|
||||
log_end_msg $?
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
stop() {
|
||||
start-stop-daemon --pidfile $PIDFILE --retry 5 -K
|
||||
/bin/rm -rf $PIDFILE
|
||||
}
|
||||
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
start
|
||||
;;
|
||||
stop)
|
||||
stop
|
||||
;;
|
||||
restart)
|
||||
stop
|
||||
start
|
||||
;;
|
||||
|
||||
status)
|
||||
echo -n $SHFILE
|
||||
status_of_proc $SHFILE
|
||||
;;
|
||||
|
||||
*) log_action_msg "Usage: /etc/init.d/proc_g2_ircddb_dtmfs {start|stop|restart|status}"
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
exit 0
|
||||
|
||||
Loading…
Reference in new issue