initial commit

ki4klf
ac2ie 12 years ago
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,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

@ -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,2 @@
#!/bin/sh
halt

@ -0,0 +1,2 @@
#!/bin/sh
reboot

@ -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…
Cancel
Save

Powered by TurnKey Linux.