mirror of
https://github.com/ShaYmez/NXDNClients.git
synced 2024-11-21 15:11:47 -05:00
Initial commit.
This commit is contained in:
commit
e3abbaa85f
15
.gitignore
vendored
Normal file
15
.gitignore
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
Debug
|
||||
Release
|
||||
x64
|
||||
*.o
|
||||
*.opendb
|
||||
*.bak
|
||||
*.obj
|
||||
*~
|
||||
*.sdf
|
||||
*.log
|
||||
*.zip
|
||||
*.exe
|
||||
*.user
|
||||
*.VC.db
|
||||
.vs
|
340
LICENCE
Normal file
340
LICENCE
Normal file
@ -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.
|
51
NXDNClients.sln
Normal file
51
NXDNClients.sln
Normal file
@ -0,0 +1,51 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.27130.2010
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NXDNParrot", "NXDNParrot\NXDNParrot.vcxproj", "{2AE94EAA-FD57-45C9-8555-6425CFA777A3}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NXDNGateway", "NXDNGateway\NXDNGateway.vcxproj", "{8B7A5406-8560-4B40-ADDA-9B8EBF93E232}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NXDNReflector", "NXDNReflector\NXDNReflector.vcxproj", "{C68ABEB3-5CDD-4B26-8D66-77FE81EC6BB5}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{2AE94EAA-FD57-45C9-8555-6425CFA777A3}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{2AE94EAA-FD57-45C9-8555-6425CFA777A3}.Debug|x64.Build.0 = Debug|x64
|
||||
{2AE94EAA-FD57-45C9-8555-6425CFA777A3}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{2AE94EAA-FD57-45C9-8555-6425CFA777A3}.Debug|x86.Build.0 = Debug|Win32
|
||||
{2AE94EAA-FD57-45C9-8555-6425CFA777A3}.Release|x64.ActiveCfg = Release|x64
|
||||
{2AE94EAA-FD57-45C9-8555-6425CFA777A3}.Release|x64.Build.0 = Release|x64
|
||||
{2AE94EAA-FD57-45C9-8555-6425CFA777A3}.Release|x86.ActiveCfg = Release|Win32
|
||||
{2AE94EAA-FD57-45C9-8555-6425CFA777A3}.Release|x86.Build.0 = Release|Win32
|
||||
{8B7A5406-8560-4B40-ADDA-9B8EBF93E232}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{8B7A5406-8560-4B40-ADDA-9B8EBF93E232}.Debug|x64.Build.0 = Debug|x64
|
||||
{8B7A5406-8560-4B40-ADDA-9B8EBF93E232}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{8B7A5406-8560-4B40-ADDA-9B8EBF93E232}.Debug|x86.Build.0 = Debug|Win32
|
||||
{8B7A5406-8560-4B40-ADDA-9B8EBF93E232}.Release|x64.ActiveCfg = Release|x64
|
||||
{8B7A5406-8560-4B40-ADDA-9B8EBF93E232}.Release|x64.Build.0 = Release|x64
|
||||
{8B7A5406-8560-4B40-ADDA-9B8EBF93E232}.Release|x86.ActiveCfg = Release|Win32
|
||||
{8B7A5406-8560-4B40-ADDA-9B8EBF93E232}.Release|x86.Build.0 = Release|Win32
|
||||
{C68ABEB3-5CDD-4B26-8D66-77FE81EC6BB5}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{C68ABEB3-5CDD-4B26-8D66-77FE81EC6BB5}.Debug|x64.Build.0 = Debug|x64
|
||||
{C68ABEB3-5CDD-4B26-8D66-77FE81EC6BB5}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{C68ABEB3-5CDD-4B26-8D66-77FE81EC6BB5}.Debug|x86.Build.0 = Debug|Win32
|
||||
{C68ABEB3-5CDD-4B26-8D66-77FE81EC6BB5}.Release|x64.ActiveCfg = Release|x64
|
||||
{C68ABEB3-5CDD-4B26-8D66-77FE81EC6BB5}.Release|x64.Build.0 = Release|x64
|
||||
{C68ABEB3-5CDD-4B26-8D66-77FE81EC6BB5}.Release|x86.ActiveCfg = Release|Win32
|
||||
{C68ABEB3-5CDD-4B26-8D66-77FE81EC6BB5}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {02935C01-6975-4CA6-81D3-505FFB8A432C}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
282
NXDNGateway/Conf.cpp
Normal file
282
NXDNGateway/Conf.cpp
Normal file
@ -0,0 +1,282 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016,2017,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "Conf.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cctype>
|
||||
|
||||
const int BUFFER_SIZE = 500;
|
||||
|
||||
enum SECTION {
|
||||
SECTION_NONE,
|
||||
SECTION_GENERAL,
|
||||
SECTION_ID_LOOKUP,
|
||||
SECTION_VOICE,
|
||||
SECTION_LOG,
|
||||
SECTION_NETWORK
|
||||
};
|
||||
|
||||
CConf::CConf(const std::string& file) :
|
||||
m_file(file),
|
||||
m_callsign(),
|
||||
m_rptAddress(),
|
||||
m_rptPort(0U),
|
||||
m_myAddress(),
|
||||
m_myPort(0U),
|
||||
m_announcements(true),
|
||||
m_daemon(false),
|
||||
m_lookupName(),
|
||||
m_lookupTime(0U),
|
||||
m_voiceEnabled(true),
|
||||
m_voiceLanguage("en_GB"),
|
||||
m_voiceDirectory(),
|
||||
m_logFilePath(),
|
||||
m_logFileRoot(),
|
||||
m_networkPort(0U),
|
||||
m_networkHosts1(),
|
||||
m_networkHosts2(),
|
||||
m_networkReloadTime(0U),
|
||||
m_networkParrotAddress("127.0.0.1"),
|
||||
m_networkParrotPort(0U),
|
||||
m_networkStartup(9999U),
|
||||
m_networkInactivityTimeout(0U),
|
||||
m_networkDebug(false)
|
||||
{
|
||||
}
|
||||
|
||||
CConf::~CConf()
|
||||
{
|
||||
}
|
||||
|
||||
bool CConf::read()
|
||||
{
|
||||
FILE* fp = ::fopen(m_file.c_str(), "rt");
|
||||
if (fp == NULL) {
|
||||
::fprintf(stderr, "Couldn't open the .ini file - %s\n", m_file.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
SECTION section = SECTION_NONE;
|
||||
|
||||
char buffer[BUFFER_SIZE];
|
||||
while (::fgets(buffer, BUFFER_SIZE, fp) != NULL) {
|
||||
if (buffer[0U] == '#')
|
||||
continue;
|
||||
|
||||
if (buffer[0U] == '[') {
|
||||
if (::strncmp(buffer, "[General]", 9U) == 0)
|
||||
section = SECTION_GENERAL;
|
||||
else if (::strncmp(buffer, "[Id Lookup]", 11U) == 0)
|
||||
section = SECTION_ID_LOOKUP;
|
||||
else if (::strncmp(buffer, "[Voice]", 7U) == 0)
|
||||
section = SECTION_VOICE;
|
||||
else if (::strncmp(buffer, "[Log]", 5U) == 0)
|
||||
section = SECTION_LOG;
|
||||
else if (::strncmp(buffer, "[Network]", 9U) == 0)
|
||||
section = SECTION_NETWORK;
|
||||
else
|
||||
section = SECTION_NONE;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
char* key = ::strtok(buffer, " \t=\r\n");
|
||||
if (key == NULL)
|
||||
continue;
|
||||
|
||||
char* value = ::strtok(NULL, "\r\n");
|
||||
if (section == SECTION_GENERAL) {
|
||||
if (::strcmp(key, "Callsign") == 0) {
|
||||
// Convert the callsign to upper case
|
||||
for (unsigned int i = 0U; value[i] != 0; i++)
|
||||
value[i] = ::toupper(value[i]);
|
||||
m_callsign = value;
|
||||
} else if (::strcmp(key, "RptAddress") == 0)
|
||||
m_rptAddress = value;
|
||||
else if (::strcmp(key, "RptPort") == 0)
|
||||
m_rptPort = (unsigned int)::atoi(value);
|
||||
else if (::strcmp(key, "LocalAddress") == 0)
|
||||
m_myAddress = value;
|
||||
else if (::strcmp(key, "LocalPort") == 0)
|
||||
m_myPort = (unsigned int)::atoi(value);
|
||||
else if (::strcmp(key, "Announcements") == 0)
|
||||
m_announcements = ::atoi(value) == 1;
|
||||
else if (::strcmp(key, "Daemon") == 0)
|
||||
m_daemon = ::atoi(value) == 1;
|
||||
} else if (section == SECTION_ID_LOOKUP) {
|
||||
if (::strcmp(key, "Name") == 0)
|
||||
m_lookupName = value;
|
||||
else if (::strcmp(key, "Time") == 0)
|
||||
m_lookupTime = (unsigned int)::atoi(value);
|
||||
} else if (section == SECTION_VOICE) {
|
||||
if (::strcmp(key, "Enabled") == 0)
|
||||
m_voiceEnabled = ::atoi(value) == 1;
|
||||
else if (::strcmp(key, "Language") == 0)
|
||||
m_voiceLanguage = value;
|
||||
else if (::strcmp(key, "Directory") == 0)
|
||||
m_voiceDirectory = value;
|
||||
} else if (section == SECTION_LOG) {
|
||||
if (::strcmp(key, "FilePath") == 0)
|
||||
m_logFilePath = value;
|
||||
else if (::strcmp(key, "FileRoot") == 0)
|
||||
m_logFileRoot = value;
|
||||
} else if (section == SECTION_NETWORK) {
|
||||
if (::strcmp(key, "Port") == 0)
|
||||
m_networkPort = (unsigned int)::atoi(value);
|
||||
else if (::strcmp(key, "HostsFile1") == 0)
|
||||
m_networkHosts1 = value;
|
||||
else if (::strcmp(key, "HostsFile2") == 0)
|
||||
m_networkHosts2 = value;
|
||||
else if (::strcmp(key, "ReloadTime") == 0)
|
||||
m_networkReloadTime = (unsigned int)::atoi(value);
|
||||
else if (::strcmp(key, "ParrotAddress") == 0)
|
||||
m_networkParrotAddress = value;
|
||||
else if (::strcmp(key, "ParrotPort") == 0)
|
||||
m_networkParrotPort = (unsigned int)::atoi(value);
|
||||
else if (::strcmp(key, "Startup") == 0)
|
||||
m_networkStartup = (unsigned int)::atoi(value);
|
||||
else if (::strcmp(key, "InactivityTimeout") == 0)
|
||||
m_networkInactivityTimeout = (unsigned int)::atoi(value);
|
||||
else if (::strcmp(key, "Debug") == 0)
|
||||
m_networkDebug = ::atoi(value) == 1;
|
||||
}
|
||||
}
|
||||
|
||||
::fclose(fp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string CConf::getCallsign() const
|
||||
{
|
||||
return m_callsign;
|
||||
}
|
||||
|
||||
std::string CConf::getRptAddress() const
|
||||
{
|
||||
return m_rptAddress;
|
||||
}
|
||||
|
||||
unsigned int CConf::getRptPort() const
|
||||
{
|
||||
return m_rptPort;
|
||||
}
|
||||
|
||||
std::string CConf::getMyAddress() const
|
||||
{
|
||||
return m_myAddress;
|
||||
}
|
||||
|
||||
unsigned int CConf::getMyPort() const
|
||||
{
|
||||
return m_myPort;
|
||||
}
|
||||
|
||||
bool CConf::getAnnouncements() const
|
||||
{
|
||||
return m_announcements;
|
||||
}
|
||||
|
||||
bool CConf::getDaemon() const
|
||||
{
|
||||
return m_daemon;
|
||||
}
|
||||
|
||||
std::string CConf::getLookupName() const
|
||||
{
|
||||
return m_lookupName;
|
||||
}
|
||||
|
||||
unsigned int CConf::getLookupTime() const
|
||||
{
|
||||
return m_lookupTime;
|
||||
}
|
||||
|
||||
bool CConf::getVoiceEnabled() const
|
||||
{
|
||||
return m_voiceEnabled;
|
||||
}
|
||||
|
||||
std::string CConf::getVoiceLanguage() const
|
||||
{
|
||||
return m_voiceLanguage;
|
||||
}
|
||||
|
||||
std::string CConf::getVoiceDirectory() const
|
||||
{
|
||||
return m_voiceDirectory;
|
||||
}
|
||||
|
||||
std::string CConf::getLogFilePath() const
|
||||
{
|
||||
return m_logFilePath;
|
||||
}
|
||||
|
||||
std::string CConf::getLogFileRoot() const
|
||||
{
|
||||
return m_logFileRoot;
|
||||
}
|
||||
|
||||
unsigned int CConf::getNetworkPort() const
|
||||
{
|
||||
return m_networkPort;
|
||||
}
|
||||
|
||||
std::string CConf::getNetworkHosts1() const
|
||||
{
|
||||
return m_networkHosts1;
|
||||
}
|
||||
|
||||
std::string CConf::getNetworkHosts2() const
|
||||
{
|
||||
return m_networkHosts2;
|
||||
}
|
||||
|
||||
unsigned int CConf::getNetworkReloadTime() const
|
||||
{
|
||||
return m_networkReloadTime;
|
||||
}
|
||||
|
||||
std::string CConf::getNetworkParrotAddress() const
|
||||
{
|
||||
return m_networkParrotAddress;
|
||||
}
|
||||
|
||||
unsigned int CConf::getNetworkParrotPort() const
|
||||
{
|
||||
return m_networkParrotPort;
|
||||
}
|
||||
|
||||
unsigned int CConf::getNetworkStartup() const
|
||||
{
|
||||
return m_networkStartup;
|
||||
}
|
||||
|
||||
unsigned int CConf::getNetworkInactivityTimeout() const
|
||||
{
|
||||
return m_networkInactivityTimeout;
|
||||
}
|
||||
|
||||
bool CConf::getNetworkDebug() const
|
||||
{
|
||||
return m_networkDebug;
|
||||
}
|
97
NXDNGateway/Conf.h
Normal file
97
NXDNGateway/Conf.h
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016,2017,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if !defined(CONF_H)
|
||||
#define CONF_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class CConf
|
||||
{
|
||||
public:
|
||||
CConf(const std::string& file);
|
||||
~CConf();
|
||||
|
||||
bool read();
|
||||
|
||||
// The General section
|
||||
std::string getCallsign() const;
|
||||
std::string getRptAddress() const;
|
||||
unsigned int getRptPort() const;
|
||||
std::string getMyAddress() const;
|
||||
unsigned int getMyPort() const;
|
||||
bool getAnnouncements() const;
|
||||
bool getDaemon() const;
|
||||
|
||||
// The Id Lookup section
|
||||
std::string getLookupName() const;
|
||||
unsigned int getLookupTime() const;
|
||||
|
||||
// The Voice section
|
||||
bool getVoiceEnabled() const;
|
||||
std::string getVoiceLanguage() const;
|
||||
std::string getVoiceDirectory() const;
|
||||
|
||||
// The Log section
|
||||
std::string getLogFilePath() const;
|
||||
std::string getLogFileRoot() const;
|
||||
|
||||
// The Network section
|
||||
unsigned int getNetworkPort() const;
|
||||
std::string getNetworkHosts1() const;
|
||||
std::string getNetworkHosts2() const;
|
||||
unsigned int getNetworkReloadTime() const;
|
||||
std::string getNetworkParrotAddress() const;
|
||||
unsigned int getNetworkParrotPort() const;
|
||||
unsigned int getNetworkStartup() const;
|
||||
unsigned int getNetworkInactivityTimeout() const;
|
||||
bool getNetworkDebug() const;
|
||||
|
||||
private:
|
||||
std::string m_file;
|
||||
std::string m_callsign;
|
||||
std::string m_rptAddress;
|
||||
unsigned int m_rptPort;
|
||||
std::string m_myAddress;
|
||||
unsigned int m_myPort;
|
||||
bool m_announcements;
|
||||
bool m_daemon;
|
||||
|
||||
std::string m_lookupName;
|
||||
unsigned int m_lookupTime;
|
||||
|
||||
bool m_voiceEnabled;
|
||||
std::string m_voiceLanguage;
|
||||
std::string m_voiceDirectory;
|
||||
|
||||
std::string m_logFilePath;
|
||||
std::string m_logFileRoot;
|
||||
|
||||
unsigned int m_networkPort;
|
||||
std::string m_networkHosts1;
|
||||
std::string m_networkHosts2;
|
||||
unsigned int m_networkReloadTime;
|
||||
std::string m_networkParrotAddress;
|
||||
unsigned int m_networkParrotPort;
|
||||
unsigned int m_networkStartup;
|
||||
unsigned int m_networkInactivityTimeout;
|
||||
bool m_networkDebug;
|
||||
};
|
||||
|
||||
#endif
|
140
NXDNGateway/IcomNetwork.cpp
Normal file
140
NXDNGateway/IcomNetwork.cpp
Normal file
@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2014,2016,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "IcomNetwork.h"
|
||||
#include "Utils.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
const unsigned int BUFFER_LENGTH = 200U;
|
||||
|
||||
CIcomNetwork::CIcomNetwork(const std::string& localAddress, unsigned int localPort, const std::string& gatewayAddress, unsigned int gatewayPort, bool debug) :
|
||||
m_socket(localAddress, localPort),
|
||||
m_address(),
|
||||
m_port(gatewayPort),
|
||||
m_debug(debug),
|
||||
m_buffer(1000U, "Icom")
|
||||
{
|
||||
assert(gatewayPort > 0U);
|
||||
assert(!gatewayAddress.empty());
|
||||
|
||||
m_address = CUDPSocket::lookup(gatewayAddress);
|
||||
}
|
||||
|
||||
CIcomNetwork::~CIcomNetwork()
|
||||
{
|
||||
}
|
||||
|
||||
bool CIcomNetwork::open()
|
||||
{
|
||||
LogMessage("Opening Icom connection");
|
||||
|
||||
if (m_address.s_addr == INADDR_NONE)
|
||||
return false;
|
||||
|
||||
return m_socket.open();
|
||||
}
|
||||
|
||||
bool CIcomNetwork::write(const unsigned char* data, unsigned int length)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
unsigned char buffer[110U];
|
||||
::memset(buffer, 0x00U, 110U);
|
||||
|
||||
buffer[0U] = 'I';
|
||||
buffer[1U] = 'C';
|
||||
buffer[2U] = 'O';
|
||||
buffer[3U] = 'M';
|
||||
buffer[4U] = 0x01U;
|
||||
buffer[5U] = 0x01U;
|
||||
buffer[6U] = 0x08U;
|
||||
buffer[7U] = 0xE0U;
|
||||
|
||||
buffer[37U] = 0x23U;
|
||||
buffer[38U] = (data[0U] == 0x81U || data[0U] == 0x83U) ? 0x1CU : 0x10U;
|
||||
buffer[39U] = 0x21U;
|
||||
|
||||
::memcpy(buffer + 40U, data, length);
|
||||
|
||||
if (m_debug)
|
||||
CUtils::dump(1U, "Icom Data Sent", buffer, 102U);
|
||||
|
||||
return m_socket.write(buffer, 102U, m_address, m_port);
|
||||
}
|
||||
|
||||
void CIcomNetwork::clock(unsigned int ms)
|
||||
{
|
||||
unsigned char buffer[BUFFER_LENGTH];
|
||||
|
||||
in_addr address;
|
||||
unsigned int port;
|
||||
int length = m_socket.read(buffer, BUFFER_LENGTH, address, port);
|
||||
if (length <= 0)
|
||||
return;
|
||||
|
||||
// Check if the data is for us
|
||||
if (m_address.s_addr != address.s_addr || port != m_port) {
|
||||
LogMessage("Icom packet received from an invalid source, %08X != %08X and/or %u != %u", m_address.s_addr, address.s_addr, m_port, port);
|
||||
return;
|
||||
}
|
||||
|
||||
// Invalid packet type?
|
||||
if (::memcmp(buffer, "ICOM", 4U) != 0)
|
||||
return;
|
||||
|
||||
// An Icom repeater connect request
|
||||
if (buffer[4U] == 0x01U && buffer[5U] == 0x61U) {
|
||||
buffer[5U] = 0x62U;
|
||||
buffer[37U] = 0x02U;
|
||||
buffer[38U] = 0x4FU;
|
||||
buffer[39U] = 0x4BU;
|
||||
m_socket.write(buffer, length, m_address, m_port);
|
||||
return;
|
||||
}
|
||||
|
||||
if (length != 102)
|
||||
return;
|
||||
|
||||
if (m_debug)
|
||||
CUtils::dump(1U, "Icom Data Received", buffer, length);
|
||||
|
||||
m_buffer.addData(buffer + 40U, 33U);
|
||||
}
|
||||
|
||||
bool CIcomNetwork::read(unsigned char* data)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
if (m_buffer.isEmpty())
|
||||
return false;
|
||||
|
||||
m_buffer.getData(data, 33U);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CIcomNetwork::close()
|
||||
{
|
||||
m_socket.close();
|
||||
|
||||
LogMessage("Closing Icom connection");
|
||||
}
|
52
NXDNGateway/IcomNetwork.h
Normal file
52
NXDNGateway/IcomNetwork.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2014,2016,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef IcomNetwork_H
|
||||
#define IcomNetwork_H
|
||||
|
||||
#include "RingBuffer.h"
|
||||
#include "UDPSocket.h"
|
||||
#include "Timer.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
class CIcomNetwork {
|
||||
public:
|
||||
CIcomNetwork(const std::string& localAddress, unsigned int localPort, const std::string& gatewayAddress, unsigned int gatewayPort, bool debug);
|
||||
~CIcomNetwork();
|
||||
|
||||
bool open();
|
||||
|
||||
bool write(const unsigned char* data, unsigned int length);
|
||||
|
||||
bool read(unsigned char* data);
|
||||
|
||||
void close();
|
||||
|
||||
void clock(unsigned int ms);
|
||||
|
||||
private:
|
||||
CUDPSocket m_socket;
|
||||
in_addr m_address;
|
||||
unsigned int m_port;
|
||||
bool m_debug;
|
||||
CRingBuffer<unsigned char> m_buffer;
|
||||
};
|
||||
|
||||
#endif
|
136
NXDNGateway/Log.cpp
Normal file
136
NXDNGateway/Log.cpp
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "Log.h"
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#include <Windows.h>
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstdarg>
|
||||
#include <ctime>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
static unsigned int m_fileLevel = 2U;
|
||||
static std::string m_filePath;
|
||||
static std::string m_fileRoot;
|
||||
|
||||
static FILE* m_fpLog = NULL;
|
||||
|
||||
static unsigned int m_displayLevel = 2U;
|
||||
|
||||
static struct tm m_tm;
|
||||
|
||||
static char LEVELS[] = " DMIWEF";
|
||||
|
||||
static bool LogOpen()
|
||||
{
|
||||
if (m_fileLevel == 0U)
|
||||
return true;
|
||||
|
||||
time_t now;
|
||||
::time(&now);
|
||||
|
||||
struct tm* tm = ::gmtime(&now);
|
||||
|
||||
if (tm->tm_mday == m_tm.tm_mday && tm->tm_mon == m_tm.tm_mon && tm->tm_year == m_tm.tm_year) {
|
||||
if (m_fpLog != NULL)
|
||||
return true;
|
||||
} else {
|
||||
if (m_fpLog != NULL)
|
||||
::fclose(m_fpLog);
|
||||
}
|
||||
|
||||
char filename[100U];
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
::sprintf(filename, "%s\\%s-%04d-%02d-%02d.log", m_filePath.c_str(), m_fileRoot.c_str(), tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday);
|
||||
#else
|
||||
::sprintf(filename, "%s/%s-%04d-%02d-%02d.log", m_filePath.c_str(), m_fileRoot.c_str(), tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday);
|
||||
#endif
|
||||
|
||||
m_fpLog = ::fopen(filename, "a+t");
|
||||
m_tm = *tm;
|
||||
|
||||
return m_fpLog != NULL;
|
||||
}
|
||||
|
||||
bool LogInitialise(const std::string& filePath, const std::string& fileRoot, unsigned int fileLevel, unsigned int displayLevel)
|
||||
{
|
||||
m_filePath = filePath;
|
||||
m_fileRoot = fileRoot;
|
||||
m_fileLevel = fileLevel;
|
||||
m_displayLevel = displayLevel;
|
||||
return ::LogOpen();
|
||||
}
|
||||
|
||||
void LogFinalise()
|
||||
{
|
||||
if (m_fpLog != NULL)
|
||||
::fclose(m_fpLog);
|
||||
}
|
||||
|
||||
void Log(unsigned int level, const char* fmt, ...)
|
||||
{
|
||||
assert(fmt != NULL);
|
||||
|
||||
char buffer[300U];
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
SYSTEMTIME st;
|
||||
::GetSystemTime(&st);
|
||||
|
||||
::sprintf(buffer, "%c: %04u-%02u-%02u %02u:%02u:%02u.%03u ", LEVELS[level], st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
|
||||
#else
|
||||
struct timeval now;
|
||||
::gettimeofday(&now, NULL);
|
||||
|
||||
struct tm* tm = ::gmtime(&now.tv_sec);
|
||||
|
||||
::sprintf(buffer, "%c: %04d-%02d-%02d %02d:%02d:%02d.%03lu ", LEVELS[level], tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, now.tv_usec / 1000U);
|
||||
#endif
|
||||
|
||||
va_list vl;
|
||||
va_start(vl, fmt);
|
||||
|
||||
::vsprintf(buffer + ::strlen(buffer), fmt, vl);
|
||||
|
||||
va_end(vl);
|
||||
|
||||
if (level >= m_fileLevel && m_fileLevel != 0U) {
|
||||
bool ret = ::LogOpen();
|
||||
if (!ret)
|
||||
return;
|
||||
|
||||
::fprintf(m_fpLog, "%s\n", buffer);
|
||||
::fflush(m_fpLog);
|
||||
}
|
||||
|
||||
if (level >= m_displayLevel && m_displayLevel != 0U) {
|
||||
::fprintf(stdout, "%s\n", buffer);
|
||||
::fflush(stdout);
|
||||
}
|
||||
|
||||
if (level == 6U) { // Fatal
|
||||
::fclose(m_fpLog);
|
||||
exit(1);
|
||||
}
|
||||
}
|
36
NXDNGateway/Log.h
Normal file
36
NXDNGateway/Log.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if !defined(LOG_H)
|
||||
#define LOG_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#define LogDebug(fmt, ...) Log(1U, fmt, ##__VA_ARGS__)
|
||||
#define LogMessage(fmt, ...) Log(2U, fmt, ##__VA_ARGS__)
|
||||
#define LogInfo(fmt, ...) Log(3U, fmt, ##__VA_ARGS__)
|
||||
#define LogWarning(fmt, ...) Log(4U, fmt, ##__VA_ARGS__)
|
||||
#define LogError(fmt, ...) Log(5U, fmt, ##__VA_ARGS__)
|
||||
#define LogFatal(fmt, ...) Log(6U, fmt, ##__VA_ARGS__)
|
||||
|
||||
extern void Log(unsigned int level, const char* fmt, ...);
|
||||
|
||||
extern bool LogInitialise(const std::string& filePath, const std::string& fileRoot, unsigned int fileLevel, unsigned int displayLevel);
|
||||
extern void LogFinalise();
|
||||
|
||||
#endif
|
19
NXDNGateway/Makefile
Normal file
19
NXDNGateway/Makefile
Normal file
@ -0,0 +1,19 @@
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
CFLAGS = -g -O3 -Wall -std=c++0x -pthread
|
||||
LIBS = -lpthread
|
||||
LDFLAGS = -g
|
||||
|
||||
OBJECTS = Conf.o IcomNetwork.o Log.o Mutex.o NXDNCRC.o NXDNGateway.o NXDNLookup.o NXDNNetwork.o Reflectors.o StopWatch.o Thread.o Timer.o UDPSocket.o Utils.o Voice.o
|
||||
|
||||
all: NXDNGateway
|
||||
|
||||
NXDNGateway: $(OBJECTS)
|
||||
$(CXX) $(OBJECTS) $(CFLAGS) $(LIBS) -o NXDNGateway
|
||||
|
||||
%.o: %.cpp
|
||||
$(CXX) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
$(RM) NXDNGateway *.o *.d *.bak *~
|
||||
|
65
NXDNGateway/Mutex.cpp
Normal file
65
NXDNGateway/Mutex.cpp
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "Mutex.h"
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
|
||||
CMutex::CMutex() :
|
||||
m_handle()
|
||||
{
|
||||
m_handle = ::CreateMutex(NULL, FALSE, NULL);
|
||||
}
|
||||
|
||||
CMutex::~CMutex()
|
||||
{
|
||||
::CloseHandle(m_handle);
|
||||
}
|
||||
|
||||
void CMutex::lock()
|
||||
{
|
||||
::WaitForSingleObject(m_handle, INFINITE);
|
||||
}
|
||||
|
||||
void CMutex::unlock()
|
||||
{
|
||||
::ReleaseMutex(m_handle);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
CMutex::CMutex() :
|
||||
m_mutex(PTHREAD_MUTEX_INITIALIZER)
|
||||
{
|
||||
}
|
||||
|
||||
CMutex::~CMutex()
|
||||
{
|
||||
}
|
||||
|
||||
void CMutex::lock()
|
||||
{
|
||||
::pthread_mutex_lock(&m_mutex);
|
||||
}
|
||||
|
||||
void CMutex::unlock()
|
||||
{
|
||||
::pthread_mutex_unlock(&m_mutex);
|
||||
}
|
||||
|
||||
#endif
|
45
NXDNGateway/Mutex.h
Normal file
45
NXDNGateway/Mutex.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if !defined(MUTEX_H)
|
||||
#define MUTEX_H
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
class CMutex
|
||||
{
|
||||
public:
|
||||
CMutex();
|
||||
~CMutex();
|
||||
|
||||
void lock();
|
||||
void unlock();
|
||||
|
||||
private:
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
HANDLE m_handle;
|
||||
#else
|
||||
pthread_mutex_t m_mutex;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
405
NXDNGateway/NXDN.csv
Normal file
405
NXDNGateway/NXDN.csv
Normal file
@ -0,0 +1,405 @@
|
||||
UID,Call,Name,Location,Notes
|
||||
2,W2FLY/M,Harry,Southern NJ,UHF NX-800 mobile
|
||||
3,WB2OOM/M,Tina,Southern NJ,UHF NX-800 Mobile
|
||||
4,W2FLY/M,Harry,Southern NJ,UHF NX-800 Van
|
||||
7,F1PRY,Emmanuel,BEAUVAIS FR,
|
||||
8,W2FLY/P,Harry,Southern NJ,UHF NX-820 Port 2
|
||||
9,KE8BGA,Lowell Katz,"Cleveland, Ohio","on the north shore, NX-800"
|
||||
17,KC2SNI,Jim Hannon,"West Berlin, New Jersey",My Radio is an Icom IC-3161DT
|
||||
25,WB2RUH/P,Bruce,Southern NJ,UHF NX-320
|
||||
26,WB2RUH/M,Bruce,Southern NJ,UHF NX-800 mobile
|
||||
30,KD4MOJ,Doug,,Doug
|
||||
74,N2IXC,Ed,Chatsworth NJ,
|
||||
76,W2FLY/P,Harry,Southern NJ,UFH NX5300 Port 1
|
||||
77,W2FLY/P,Harry,"Somers Point, NJ",UHF NX-800 Shore Base
|
||||
78,W2FLY,Harry,"Mullica Hill, NJ",UHF NX-800
|
||||
79,W2FLY/M,Harry,Southern NJ,UHF NX-5800
|
||||
80,W2FLY/M,Harry,Southern NJ,VHF NX-5700 mobile
|
||||
82,W2FLY/P,Harry,"Somers Point, NJ",VHF NX-700 Shore Base
|
||||
85,W2FLY/M,Harry,Southern NJ,VHF NX_700 van
|
||||
86,W2FLY,Harry,"Mullica Hill, NJ",VHF NX-700 base
|
||||
87,W2FLY/M,Harry,Southern NJ,VHF NX-700 mobile
|
||||
88,W2FLY/P,Harry,Southern NJ,VHF NX-220 portable
|
||||
89,WB2RUH,Bruce,Vineland NJ,VHF NX-700 base
|
||||
99,K1ZSG,Don,,Mobile
|
||||
134,N2SRO,Mike,Pitman,Mobile Radio
|
||||
134,N2SRO,Mike,NJ,
|
||||
141,KF2M,Greg Popovich,"Mt Laurel, NJ",IC-F4161DT
|
||||
401,W1KFR,Bill,,Bill
|
||||
901,K1IFF,Cliff,CT,Cliff NX320
|
||||
902,K1IFF,Cliff,CT,Cliff NX320 - demo
|
||||
903,K1IFF,Cliff,CT,Cliff NX800H
|
||||
905,WA1LMV,Rick,,Rick NX320
|
||||
906,K1IFF,Cliff,CT,Cliff NX200
|
||||
907,K1IFF,Cliff,CT,Future
|
||||
908,W4CLL,Chuck,,CHUCK
|
||||
909,AB1UB V,Woody,"Bristol, CT",
|
||||
909,AB1UB,Woody,"Bristol, CT",
|
||||
909,AB1UB,Woody,,Woody NX300
|
||||
909,W4CCL,Chuck,,CHUCK
|
||||
910,W4CLL,Chuck,,CHUCK
|
||||
911,W4CLL,Chuck,,CHUCK
|
||||
912,W4CCL,Chuck,,CHUCK
|
||||
920,N1XDN,Bob,CT,Bob P1 UHF NX300
|
||||
921,N1XDN,Bob,CT,Bob P1 VHF NX220
|
||||
922,N1XDN,Bob,CT,Bob P2 UHF NX300
|
||||
923,N1XDN,Bob,CT,Bob M1 VHF NX700
|
||||
924,N1XDN,Bob,CT,Bob P3 UHF NX-5300
|
||||
925,N1XDN,Bob,CT,Bob P2 VHF NX-5200
|
||||
926,N1XDN,Bob,CT,Bob M1 UHF NX-5800
|
||||
928,N1XDN,Bob,CT,Icom portable
|
||||
930,K1IFF,Cliff,CT,NX300
|
||||
931,K1IFF,Cliff,CT,NX300
|
||||
936,W1GPO,John,,NX300
|
||||
951,K1KGQ,Joel,,Joel NX800H
|
||||
952,K1KGQ,Joel,CT,Truck radio
|
||||
952,K1GML,Gail,,Gail NX800H
|
||||
953,K1KGQ,Joel,,Joel NX320-1
|
||||
954,K1KGQ,Joel,,
|
||||
955,K1KGQ,Joel,,
|
||||
956,K1KGQ,Joel,,
|
||||
957,K1KGQ,Joel,,
|
||||
958,K1KGQ,Joel,,Joel F4161
|
||||
959,K1KGQ,Joel,,Future
|
||||
960,K1ZXX,Gary,,Gary - Icom All radios
|
||||
961,WA1SSB,Joe,,Joe NX800H
|
||||
962,N1MAT,Dennis,,Dennis F4161
|
||||
963,N1MAT,Dennis,,Dennis F4161
|
||||
970,KB1VRI,Nick,CT,
|
||||
970,KB1VRI,Nick,,Nick
|
||||
971,N1ELE,Paul,CT,
|
||||
972,N1ODJ,Kenny Schmitz,Middletown,
|
||||
973,W1VLF,Paul,CT,
|
||||
980,W1RHS,Rick,Connecticut,
|
||||
995,K1IFF/Base,Cliff,"Brsitol, CT",NXR710 link radio
|
||||
1001,KE4GWW,James,AL,NX200 Portable #1
|
||||
1002,KE4GWW,James,AL,NX200 Portable #2
|
||||
1003,KE4GWW,James,AL,NX300 Portable #1
|
||||
1004,KE4GWW,James,AL,NX300 Portable #2
|
||||
1005,KE4GWW,James,AL,NX700 Base
|
||||
1006,KE4GWW,James,AL,NX800 Base
|
||||
1007,KE4GWW,James M. Nelson,"Dothan, AL",NX700 Mobile#1
|
||||
1008,DK6PX,Stefan,Germany nr Bad Toelz,Coming up FR6000
|
||||
1008,KE4GWW,James,AL,NX700 Mobile#2
|
||||
1009,KE4GWW,James,AL,NX800 Mobile#1
|
||||
1010,KE4GWW,James,AL,NX800 Mobile#2
|
||||
1066,KM4JXP,Peter Tasker,Longboat Key,NX5300
|
||||
1954,W4BPT,BILLY TAYLOR,"RINGGOLD,GA.",
|
||||
1956,KC7SDD,Dana Hanford,"Bainbridge Island, WA","Member BARC, W7NPC.org"
|
||||
1963,N5JRN,David Barts,"Bainbridge Island, WA","Handheld, Icom 4161"
|
||||
1966,ZS6IIX,Henry,Petit South Africa,
|
||||
1997,KC1AJR,Giovanni,East Hampton CT,kenwood NX800 K2
|
||||
3070,W4ORL,Ralph,,Ralph - Mobile
|
||||
3071,W4LOV,Mike,,Mike - NX800
|
||||
3072,N4JTK,John,,John - NX800
|
||||
3074,W4MCA,Michael,,Michael - NX300
|
||||
3075,W4LOV,Mike,,Mike - NX800
|
||||
3079,NN4TT,Dave,Orlando,NX300
|
||||
3079,W4ORL,Ralph,,Ralph - Portable
|
||||
3081,W4MCA,Michael,,Michael - NX800
|
||||
3082,W4LOV,Mike,,Mike - Portable
|
||||
3083,KD4TWJ,Dean,,Dean - Mobile NX800
|
||||
3271,N4KEG,Richard,,RICHARD - Mobile and or ht's N4KEG (UHF)
|
||||
3274,KD4EFM,Evans,FL,
|
||||
3275,KD4EFM,Evans,FL,
|
||||
3278,KD4EFM,Evans,FL,
|
||||
3279,N4KEG,Richard,,
|
||||
3280,KD4EFM,Evans,"Lakeland, Florida",work radio
|
||||
3280,KD4EFM,Evans,FL,Evans Mobile(s)
|
||||
3280,KD4EFM,Evans,FL,
|
||||
3281,N4KEG,Richard,,
|
||||
3450,K0KAD,CHAD TAYLOR,"SPOKANE VALLEY, WA",My Portable
|
||||
3451,K0KAD,CHAD TAYLOR,"SPOKANE VALLEY, WA",My Base Station
|
||||
3452,K0KAD,CHAD TAYLOR,"SPOKANE VALLEY, WA",Mobile Radio
|
||||
4020,K4XXX,Ed,"London, KY",NX820 Base
|
||||
4802,hb3yrb,Alex,Verbier,nx5300
|
||||
4804,hb9fmf,Didier,Rougemont,NX5300
|
||||
5001,N5QZ,Ryan,AR,"N5QZ, Ryan McAfee, Searcy, AR - Kenwood NX-820"
|
||||
5002,N5QZ,Ryan,AR,"N5QZ, Ryan McAfee, Searcy, AR - Kenwood NX-720"
|
||||
5003,N5QS,Roger,AR,"N5QS, Roger Gray, Searcy, AR - Kenwood NX-820"
|
||||
5004,N5QS,Roger,AR,"N5QS, Roger Gray, Searcy, AR - Kenwood NX-720"
|
||||
5005,AC5AV,Larry,AR,"AC5AV, Larry Sicks, Searcy, AR"
|
||||
5006,AC5AV,Larry,AR,"AC5AV, Larry Sicks, Searcy, AR"
|
||||
5007,N5LKE,James,AR,"N5LKE, James Ferguson, Searcy, AR - Kenwood NX-800"
|
||||
5008,AF5WN,Mason,AR,"AF5WN, Mason Creager, Cabot, AR - Kenwood NX-700H"
|
||||
5009,KJ5SF,Stan,AR,"KJ5SF, Stan Rongey, Searcy, AR - Kenwood NX-800"
|
||||
5100,K5SRS,Michael Smith,"Fayetteville, AR",NX-5800 Mobile
|
||||
5101,KC5YQB,Paul Blair,"Fayetteville, AR",
|
||||
5125,AE5OQ,Armstead,"Higden, AR",
|
||||
5125,AE5OQ,Armstead,AR,entered by k1iff
|
||||
5134,AE5OQ,Armstead,AR,"AE5OQ, Armstead M Feland, IV, Higdon, AR - Kenwood NX-200"
|
||||
5150,WY6NN,Doug,"Los Angeles, CA",NX-300/5300
|
||||
5151,KC6HFJ,Tamara,"Los Angeles, CA",NX-300
|
||||
5170,K5WMZ,Gary,AR,"K5WMZ, Gary D Partlow, Ward, AR - Kenwood NX-700"
|
||||
5599,W1ZM,Ryan,,"W1ZM, Ryan Nelson, NX-5300"
|
||||
5987,W5ZN,Joel,AR,"W5ZN, Joel Harrison, Judsonia, AR - Kenwood NX-800"
|
||||
6430,K4GFD,Norm,FL,Norm Greensboro Fla
|
||||
6431,K4GFD,Norm,,
|
||||
6432,K4GFD,Norm,,
|
||||
6439,N4NKV,George,,George
|
||||
6801,hb9vsd,relais de verbier,verbier,
|
||||
6802,HB9YRB,Alex,Verbier,
|
||||
6804,HB9FMF,Didier,Rougemont,
|
||||
7737,N4NKV,George,,George
|
||||
9834,VA7NY,PJ,,PJ
|
||||
12002,W4KJP,Kevin,,KEVIN
|
||||
12005,KD4TWJ,Dean,,Dean - Portable IC-F4161
|
||||
12006,W4MO,Stewart,,STEWART NX300 / 320
|
||||
12007,W4MO,Stewart,,STEWART NX800
|
||||
12010,kd4dwp,Ben,Orlando,
|
||||
12013,K4NBC,Miguel Orama,"Palm Bay, Florida",Icom F4146DS UHF Portable
|
||||
12014,K4NBC,Miguel Orama,"Palm Bay, Florida",Kenwood NX200 VHF HT
|
||||
12015,K4NBC,K4NBC-Miguel UHF Mobile,"Palm Bay, Florida",Future UHF Mobile
|
||||
12016,K4NBC,Miguel,"Palm Bay, Florida",M2 Icom F6061D
|
||||
12017,N4JFZ,,,
|
||||
12021,W4PJT,Paul,,Paul
|
||||
12023,KD4NWL,John,,JOHN
|
||||
12127,W4KDM,Rick,,Rick - Portable NX300
|
||||
12136,WA4KWK,John,,John F6121
|
||||
12200,NB9X,Paul,FL,
|
||||
12201,NB9X,Paul,FL,PAUL
|
||||
12202,NB9X,Paul,FL,
|
||||
12203,NB9X,Paul,FL,
|
||||
12204,WX3C,Juan Arias,Florida,Orlando metro
|
||||
12204,NB9X,Paul,FL,
|
||||
12210,N4APG,Bill,,Bill Pfost
|
||||
12211,N4APG,Bill,,Bill Pfost
|
||||
12212,N4APG,Bill,,Bill Pfost
|
||||
12213,N4APG,Bill,,Bill Pfost
|
||||
12214,N4APG,Bill,,Bill Pfost
|
||||
12215,WA4ISB,Ed,,ED Mobile
|
||||
12216,WA4ISB,Ed,,
|
||||
12220,N4PK,Paul,,PAUK K.
|
||||
12221,N4PK,Paul,,
|
||||
12222,W4PJT,Paul,,
|
||||
12223,W4PJT,Paul,,
|
||||
12226,KI4SWY,William,,
|
||||
12230,KQ4KX,Richard,,Richard Sharp
|
||||
12231,KQ4KX,Richard,,
|
||||
12234,KD4TWJ,Dean,EL98,
|
||||
12235,N1IC,Nick,,Nic
|
||||
12236,N1IC,Nick,,
|
||||
12240,KR4X,Larry,,
|
||||
12241,KR4X,Larry,,
|
||||
12245,KD4ACG,Jason,"Hudson, FL",Icom Mobile
|
||||
12245,KD4ACG,Jason,,JASON
|
||||
12246,KD4ACG,Jason,"Hudson, FL",Icom Portable
|
||||
12246,KD4ACG,Jason,,JASON
|
||||
12247,K2MCI,,,
|
||||
12250,KE4GYX,,,
|
||||
12272,KE4OSL,,,
|
||||
12273,KE4OSL,,,
|
||||
12374,KF4I,Thom,,Thom Base
|
||||
12375,KF4I,Thom,,Thom Mobile
|
||||
12523,KM4JVE,Ana,,Ana - IC-F4161
|
||||
12577,N2DLX,Richard,,Rich Dunajewski NX-5800
|
||||
12604,K4CBN,Greg,,GREG
|
||||
12605,K4CBN,Greg,,
|
||||
12606,K4CBN,Greg,,
|
||||
12607,K4CBN,Greg,,
|
||||
12608,K4CBN,Greg,,
|
||||
12666,KI4SWY,William,,William Stillwel ( All Radios )
|
||||
12691,KE3WDW,Sam,,Sam
|
||||
12780,KC4YUA,Brett,,BRETT
|
||||
13105,W7QO,Alan,,
|
||||
13106,W7QO,Alan,,
|
||||
13107,W7QO,Alan,,
|
||||
13121,W4CML,Chuck,,
|
||||
13122,W4CML,Chuck,,
|
||||
13125,KD4APP,Don,,Don - NX300
|
||||
13126,KD4APP,Don,,Don - F6061D
|
||||
13127,KD4APP,Don,,Don - NX200
|
||||
13131,W5JR,Mike,,
|
||||
13132,W5JR,Mike,,
|
||||
13401,W1KFR,Bill,,Bill
|
||||
13815,KG4BKO,Bill,GA,nx320
|
||||
14020,K4XXX,Ed,"London, KY",NX5300
|
||||
14021,K4XXX,Ed,"London, KY",NX5200
|
||||
15001,N5QZ,Ryan,AR,"N5QZ, Ryan McAfee, Searcy, AR - Kenwood NX-800H (Vehicle 1)"
|
||||
15002,N5QZ,Ryan,AR,"N5QZ, Ryan McAfee, Searcy, AR - Kenwood NX-700 (Vehicle 1)"
|
||||
15003,N5QZ,Ryan,AR,"N5QZ, Ryan McAfee, Searcy, AR - Kenwood NX-800 (Vehicle 2)"
|
||||
15004,N5QZ,Ryan,AR,"N5QZ, Ryan McAfee, Searcy, AR - Kenwood NX-700 (Vehicle 2)"
|
||||
15005,N5QS,Roger,AR,"N5QS, Roger Gray, Searcy, AR - Kenwood NX-800 (Vehicle 1)"
|
||||
15006,N5QS,Roger,AR,"N5QS, Roger Gray, Searcy, AR - Kenwood NX-700 (Vehicle 1)"
|
||||
15007,N5QS,Roger,AR,"N5QS, Roger Gray, Searcy, AR - Kenwood NX-800 (Vehicle 2)"
|
||||
15008,N5QS,Roger,AR,"N5QS, Roger Gray, Searcy, AR - Kenwood NX-700 (Vehicle 2)"
|
||||
15009,N5QS,Roger,AR,"N5QS, Roger Gray, Searcy, AR - Kenwood NX-800 (Vehicle 3)"
|
||||
15010,N5QS,Roger,AR,"N5QS, Roger Gray, Searcy, AR - Kenwood NX-700 (Vehicle 3)"
|
||||
15011,N5QT,Dawn,AR,"N5QT, Dawn Gray, Searcy, AR - Kenwood NX-800"
|
||||
15012,AC5AV,Larry,AR,"AC5AV, Larry Sicks, Searcy, AR - Kenwood NX-800"
|
||||
15013,AC5AV,Larry,AR,"AC5AV, Larry Sicks, Searcy, AR - Kenwood NX-700"
|
||||
15014,N5QT,Dawn,AR,"N5QT, Dawn Gray, Searcy, AR - Kenwood NX-700"
|
||||
15015,N5QS,Roger,AR,"N5QS, Roger Gray, Searcy, AR Motorcycle Mobile"
|
||||
15016,KG5KS,Kenny,,"KG5KS, Kenny Thompson - Kenwood NX-700HK"
|
||||
15017,KG5KS,Kenny,,"KG5KS, Kenny Thompson - Kenwood NX-800HK"
|
||||
15018,N5QS,Roger,AR,"N5QS, Roger Gray, Searcy, AR ATV Mobile"
|
||||
15019,N5QS,Roger,AR,"N5QS, Roger Gray, Searcy, AR ATV Mobile"
|
||||
15020,WA8UBL,Allen,AR,"WA8UBL, Allen Herrick, Beebe, AR, Kenwood NX-700"
|
||||
15021,KD5HRT,Heath,AR,"KD5HRT, Heath Taylor, McRae, AR, Kenwood NX-800"
|
||||
15022,WA8UBL,Allen,AR,"WA8UBL, Allen Herrick, Beebe, AR - Kenwood NX-800"
|
||||
15023,N5ZA,Joel,AR,"N5ZA, Joe Belew, Beebe, AR - Kenwood NX-700"
|
||||
15024,KF5TPF,Ryan,AR,"KF5TPF, Ryan Nelson, Edgemont, AR NX-700"
|
||||
15025,KE5YZP,Ryan,AR,"KE5YZP, Ryan Schwarck, Batesville, AR NX-700"
|
||||
15026,AF5OD,Landon,AR,"AF5OD, Landon McCord, Searcy, AR"
|
||||
15027,KB5RFF,Scott,AR,"KB5RFF, Scott Gray, Searcy, AR - Kenwood NX-800"
|
||||
17002,KC9GMX,Stephen,,Stephen - Base F6121D
|
||||
17004,KC9GMX,Stephen,,Stephen - F6061D
|
||||
17005,KC9NPJ,Jarrett,,Jarrett F6121D
|
||||
17006,KC9GMX,Stephen,,Stephen - F4161DS
|
||||
17007,KC9NPJ,Jarrett,,Jarrett F4231DS
|
||||
17008,KC9RHH,Jesse,,F4101D
|
||||
17009,KC9PHK,Michael,,F4061DS
|
||||
17011,N9BRG,Dan,,Dan kenwood nx800k2
|
||||
17855,AG6RN,Demian,CA,NX-210
|
||||
21007,WA1LMV,Rick,,Rick
|
||||
21014,K2BUI,Eric,,Eric
|
||||
24020,K4XXX,Ed,"London, KY",NX5800
|
||||
24021,K4XXX,Ed,"London, KY",NX5700
|
||||
25001,N5QZ,Ryan,AR,"N5QZ, Ryan McAfee, Searcy, AR - Kenwood NX-300"
|
||||
25002,N5QZ,Ryan,AR,"N5QZ, Ryan McAfee, Searcy, AR - Kenwood NX-200"
|
||||
25003,N5QS,Roger,AR,"N5QS, Roger Gray, Searcy, AR - Kenwood NX-300"
|
||||
25004,N5QS,Roger,AR,"N5QS, Roger Gray, Searcy, AR - Kenwood NX-200"
|
||||
25005,N5QS,Roger,AR,"N5QS, Roger Gray, Searcy, AR - Kenwood NX-320"
|
||||
25006,N5QS,Roger,AR,"N5QS, Roger Gray, Searcy, AR - Kenwood NX-340U"
|
||||
25007,N5QT,Dawn,AR,"N5QT, Dawn Gray, Searcy, AR - Kenwood NX-300"
|
||||
25008,N5QT,Dawn,AR,"N5QT, Dawn Gray, Searcy, AR - Kenwood NX-200"
|
||||
25009,AC5AV,Larry,AR,"AC5AV, Larry Sicks, Searcy, AR - Kenwood NX-300"
|
||||
25010,KD5OOW,Tom,AR,"KD5OOW, Tom McGee, Searcy, AR - Kenwood NX-300"
|
||||
25011,W5ZN,Joel,AR,"W5ZN, Joel Harrison, Judsonia, AR - Kenwood NX-300"
|
||||
25012,KD5HRT,Heath,AR,"KD5HRT, Heath Taylor, McRae, AR - Kenwood NX-300"
|
||||
25013,KK5WA,Darin,AR,"KK5WA, Darin Dykes, Beebe, AR - Kenwood NX-320"
|
||||
25014,N5LKE,James,AR,"N5LKE, James Ferguson, Searcy, AR - Kenwood NX-5300"
|
||||
25015,KJ5ORD,John,AR,"KJ5ORD, John Ord, Searcy, AR - Kenwood NX-300"
|
||||
25016,KB5RFF,Scott,AR,"KB5RFF, Scott Gray, Searcy, AR - Kenwood NX-300"
|
||||
25017,KB5ZUH,Todd,AR,"KB5ZUH, Todd Williams, Searcy, AR - Kenwood NX-320"
|
||||
25018,KB5ZUH,Todd,AR,"KB5ZUH, Todd Williams, Searcy, AR - Kenwood NX-340"
|
||||
25019,KB5ZUH,Todd,AR,"KB5ZUH, Todd Williams, Searcy, AR - Kenwood NX-340"
|
||||
25020,KB5ZUH,Todd,AR,"KB5ZUH, Todd Williams, Searcy, AR - Kenwood NX-320"
|
||||
25021,KE5UZU,Raymond Prince,"England, AR",Kenwood Handheld
|
||||
25021,AF5OD,Landon,AR,"AF5OD, Landon McCord, Searcy, AR"
|
||||
25022,KE5UZU,Raymond Prince,"England, AR",Icom Handheld
|
||||
25022,KE5YZP,Ryan,AR,"KE5YZP, Ryan A Schwarck, Batesville, AR - Icom"
|
||||
25023,KE5YZP,Ryan,AR,"KE5YZP, Ryan A Schwarck, Batesville, AR - Icom"
|
||||
25024,KG5CHM,Colt,AR,"KG5CHM, Colt Boyd, Searcy, AR - Kenwood NX-300"
|
||||
25025,KJ5ORD,John,AR,"KJ5ORD, John Ord, Searcy, AR - Kenwood NX-xxx VHF"
|
||||
25026,WA8UBL,Allen,AR,"WA8UBL, Allen Herrick, Beebe, AR - Kenwood NX-320"
|
||||
25027,KF5TPF,Ryan,AR,"KF5TPF, Ryan Nelson, Edgemont, AR - Kenwood NX-200"
|
||||
25028,WA8UBL,Allen,AR,"WA8UBL, Allen Herrick, Beebe, AR - Kenwood NX-220"
|
||||
25029,KF5WHX,Trey,AR,"KF5WHX, Trey Ferguson, Searcy, AR - Kenwood NX-320"
|
||||
25030,AC5AV,Larry,AR,"AC5AV, Larry Sicks, Searcy, AR"
|
||||
25031,KJ5SF,Stan,AR,"KJ5SF, Stan Rongey, Searcy, AR - Kenwood NX-340"
|
||||
25032,KC5DFH,Kirk,AR,"KC5DFH, Kirk Williams, Searcy, AR - Kenwood NX-340"
|
||||
25033,AF5OD,Landon,AR,"AF5OD, Landon McCord, Searcy, AR, Icom F4161DS"
|
||||
25034,KF5TPF,Ryan,AR,"KF5TPF, Ryan Nelson, Edgemont, AR - ICOM 4161"
|
||||
25035,KG5BMB,Glenda,AR,"KG5BMB, Glenda McCord, Searcy, AR, Icom F4161DS"
|
||||
25039,KC1JET,Jim,,JIM (BASE)
|
||||
25068,N1QD,Joe,,
|
||||
25069,N1COP,Bob,,Bob
|
||||
25070,WD1L,John,,John
|
||||
25125,N1TI,Tim,"Mattapoisett, MA",
|
||||
25125,N1TI,Tim,"Mattapoisett, MA",
|
||||
25144,W1WCF,Walter,,Walter
|
||||
25221,N0XIA,James,,James - Kenwood Mobile and Portable
|
||||
25222,KE4SDC,Ron,,Ron - Portable NX300
|
||||
25246,WG1U,Ken,"Assonet, MA",
|
||||
25333,W1AKN,Jack,,Jack Mobile
|
||||
25390,KC1JET,Jim,,JIM (MOBILE)
|
||||
25390,KC1JET,Jim,,JIM
|
||||
25444,W1TAV,Steve,,Steve
|
||||
25555,WA1MNQ,Mike,,Mike
|
||||
25582,N1KXJ,Ray,"E. Bridgewater, MA.",Port.
|
||||
25582,N1KXJ,Ray Wall,East Bridgewater,
|
||||
25585,N1AVA,Ken Howland,"DARTMOUTH,MA",
|
||||
25700,NN1D,Tony Souza,"Swansea, MA",
|
||||
25740,WG1U,Kenny,,KEN
|
||||
25743,WG1U,Kenny,,KEN
|
||||
25746,N1OTY,John,,JOHN
|
||||
25777,W1BON,Bump,,Bump
|
||||
25830,KB1CHU,Steve,MA,
|
||||
25863,N1ZZN,Jeff,,JEFF
|
||||
25874,KB1KVD,Jason,,Jason - Icom Mob & Port
|
||||
25888,K1WGU,Bob,,Bob
|
||||
25889,AB1CQ,Gary,,Gary
|
||||
25900,N1ZZR,Matt,,Matt - mobile
|
||||
25901,N1MRC,Matt,"Bridgewater, MA",N1MRC P-1
|
||||
25901,N1ZZR,Matt,,Matt
|
||||
25957,KC1HO,Steve,,STEVE
|
||||
27101,KI4SWB,Mark,"Melbourne Beach, FL",Icom Portable
|
||||
27102,KP4OO,Carlos,"Palm Bay, FL",Icom Portable
|
||||
27201,KI4SWB,Mark,"Melbourne Beach, FL",Icom Mobile
|
||||
27202,KP4OO,Carlos,"Palm Bay, FL",Icom Mobile
|
||||
28001,K3KRS,rYAN,CLEVLAND,OHIO
|
||||
30505,KG6MQE,Jim,MT,
|
||||
30571,WX4RCF,Ryan F.,"Tampa, FL",
|
||||
31117,K4QHR,Pete,,Pete
|
||||
31124,KM4JXP,Peter,,NX5300
|
||||
31146,KD2KWD,Michael Santamaria,"Brandon, FL",Kenwood
|
||||
33000,N1PA-R,Paul,NH,PAUL - NEW HAMPSHIRE REPEATER
|
||||
33001,N1PA,Paul,NH,PAUL - NEW HAMPSHIRE
|
||||
33002,N1PA,Paul,NH,PAUL - NEW HAMPSHIRE
|
||||
34001,N2WNS,Bill,NJ,N2WNS Portable
|
||||
34002,N2WNS,Bill,NJ,N2WNS Base
|
||||
36001,W2CCR,Chris,NY,"Chris, Galway, NY NX300"
|
||||
36002,KC2VOB,Asad,NY,"Asad, NYC, NX-5800"
|
||||
36003,KC2VOB,Asad,NY,"Asad, NYC, NX-300GK"
|
||||
36134,N2SRO,Mike,"Pitman, NJ",Portable
|
||||
37001,KA4YMY,Steve,NC,"Steve, Charlotte, NC NX320"
|
||||
37009,KA4YMY,Steve,"Charlotte, NC",
|
||||
37010,KA4YMY,Steve,"Charlotte, NC",
|
||||
37010,KA4YMY,Steve,"Charlotte, NC",
|
||||
40024,N5YEI,Jeff Dalrymple,"Jay, Oklahoma",NX-5800 Mobile
|
||||
40124,N5YEI,Jeff Dalrymple,"Jay, Oklahoma",NX-5300 Portable
|
||||
43751,N4IRS,Steve,,Steve
|
||||
44001,K2BUI,Eric,RI,
|
||||
44002,K2BUI,Eric,"Providence, RI",
|
||||
44007,W2DAN,Dave,,Dave - NX700
|
||||
44298,N1JBC,Jed,,JED
|
||||
49101,WX7Y-1,Bret Mills,Castle Dale Utah,WX7y-1 Hand Held 1
|
||||
49102,WX7Y-2,Bret Mills,"Caslte Dale, Utah",WX7Y-2 Hand held
|
||||
49104,WX7Y-4,Bret Mills,"Castle Dale, Utah",WX7Y-4 Mobile
|
||||
49106,WX7Y-6,Bret Mills,Castle Dale,WX7Y-6 Mobile
|
||||
55700,WB9HKE,Rick,WI,
|
||||
55704,WB9HKE,Rick,WI,
|
||||
57000,VE3SP,Andre,"Toronto, ON",mobile
|
||||
57001,VE3SP,Andre,"Toronto, ON",handheld
|
||||
57001,VE3EI,Eric,,Eric - Portable
|
||||
57002,VE3OKZ,Janusz,"Toronto, ON",mobile
|
||||
57002,VE3EI,Eric,,Eric - Dongle
|
||||
57003,VE3OKZ,Janusz,"Toronto, ON",handheld
|
||||
57004,VE3CCD,Curtis,"Scarborough, ON",handheld
|
||||
57005,VE3NBI,Anoop,"Scarborough, ON",handheld
|
||||
57006,VE3JLU,Sherwin,"Scarborough, ON",handheld
|
||||
57007,va3rq,Jon,"Oakville, ON",handheld
|
||||
57008,ve3ogb,Randy,"Toronto, ON",handheld
|
||||
57009,va3mk,Mark,"Oakville, ON",handheld
|
||||
57010,va3mk,Mark,"Oakville, ON",mobile
|
||||
57011,VA3WZW,Andre,"Durham, ON",mobile
|
||||
57012,VA3WZW,Andre,"Durham, ON",mobile
|
||||
57013,VA3AGV,cottage,"Toronto, ON",mobile
|
||||
57014,VE3BWP,Brian,"Caledon, ON",handheld
|
||||
57015,VE3HY,Frank,"Caledon, ON",handheld
|
||||
57016,VE3UBI,Paul,"Scarborough, ON",mobile
|
||||
57017,VE3UBI,Paul,"Scarborough, ON",handheld
|
||||
57018,VE3RZR,Richard,"Toronto, ON",handheld
|
||||
57019,VE3AEP,Dom,"Toronto, ON",mobile
|
||||
57020,VA3PEO,Adrian,"Toronto, ON",handheld
|
||||
57021,va3wjo,Walter,"Toronto, ON",handheld
|
||||
57022,ve3fkn,Tom,"Stoney Creek, ON",handheld
|
||||
57023,ve3ips,John,"Toronto, ON",handheld
|
||||
57024,VA3CQA,Brian,"Scarborough, ON",handheld
|
||||
57025,VA3PAD,Andrew,"Scarborough, ON",mobile
|
||||
57026,VA3PAD,Andrew,"Scarborough, ON",handheld
|
||||
57027,VA3VAD,Arpad,"Hamilton, ON",handheld
|
||||
57028,VA3KY,Shelly,"Thornhill, ON",mobile
|
||||
57029,VA3KY,Shelly,"Thornhill, ON",handheld
|
||||
57030,VE3KFQ,Doug,"Toronto, ON",mobile
|
||||
57031,VE3KFQ,Doug,"Toronto, ON",handheld
|
||||
57032,VE3AEP,Dom 2,"Toronto, ON",handheld
|
||||
57033,VE3DJZ,Huey,"Hamilton, ON",mobile
|
||||
57034,VE3DJZ,Huey,"Hamilton, ON",handheld
|
||||
57035,VA3RQ,Jon,Oakville ON,Mobile
|
||||
3106418,N5ICK,Nicholas Nixon,"Rialto, Ca",
|
||||
3112205,N2HUC,Phil Roberts,"Port St. Lucie, FL",DV4MINI AMBE voice
|
||||
3118365,NA9VY,Chris Gilbert,"New Palestine, IN",
|
||||
3118366,N9UMJ,Rick Nicholson,Buddha Indiana,
|
||||
3142058,N3BAH,L. Abraham Smith,Southwestern Pennsylvania,
|
|
185
NXDNGateway/NXDNCRC.cpp
Normal file
185
NXDNGateway/NXDNCRC.cpp
Normal file
@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Copyright (C) 2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "NXDNCRC.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
|
||||
const uint8_t BIT_MASK_TABLE1[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U };
|
||||
|
||||
#define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE1[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE1[(i)&7])
|
||||
#define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE1[(i)&7])
|
||||
|
||||
bool CNXDNCRC::checkCRC6(const unsigned char* in, unsigned int length)
|
||||
{
|
||||
assert(in != NULL);
|
||||
|
||||
uint8_t crc = createCRC6(in, length);
|
||||
|
||||
uint8_t temp[1U];
|
||||
temp[0U] = 0x00U;
|
||||
unsigned int j = length;
|
||||
for (unsigned int i = 2U; i < 8U; i++, j++) {
|
||||
bool b = READ_BIT1(in, j);
|
||||
WRITE_BIT1(temp, i, b);
|
||||
}
|
||||
|
||||
return crc == temp[0U];
|
||||
}
|
||||
|
||||
void CNXDNCRC::encodeCRC6(unsigned char* in, unsigned int length)
|
||||
{
|
||||
assert(in != NULL);
|
||||
|
||||
uint8_t crc[1U];
|
||||
crc[0U] = createCRC6(in, length);
|
||||
|
||||
unsigned int n = length;
|
||||
for (unsigned int i = 2U; i < 8U; i++, n++) {
|
||||
bool b = READ_BIT1(crc, i);
|
||||
WRITE_BIT1(in, n, b);
|
||||
}
|
||||
}
|
||||
|
||||
bool CNXDNCRC::checkCRC12(const unsigned char* in, unsigned int length)
|
||||
{
|
||||
assert(in != NULL);
|
||||
|
||||
uint16_t crc = createCRC12(in, length);
|
||||
uint8_t temp1[2U];
|
||||
temp1[0U] = (crc >> 8) & 0xFFU;
|
||||
temp1[1U] = (crc >> 0) & 0xFFU;
|
||||
|
||||
uint8_t temp2[2U];
|
||||
temp2[0U] = 0x00U;
|
||||
temp2[1U] = 0x00U;
|
||||
unsigned int j = length;
|
||||
for (unsigned int i = 4U; i < 16U; i++, j++) {
|
||||
bool b = READ_BIT1(in, j);
|
||||
WRITE_BIT1(temp2, i, b);
|
||||
}
|
||||
|
||||
return temp1[0U] == temp2[0U] && temp1[1U] == temp2[1U];
|
||||
}
|
||||
|
||||
void CNXDNCRC::encodeCRC12(unsigned char* in, unsigned int length)
|
||||
{
|
||||
assert(in != NULL);
|
||||
|
||||
uint16_t crc = createCRC12(in, length);
|
||||
|
||||
uint8_t temp[2U];
|
||||
temp[0U] = (crc >> 8) & 0xFFU;
|
||||
temp[1U] = (crc >> 0) & 0xFFU;
|
||||
|
||||
unsigned int n = length;
|
||||
for (unsigned int i = 4U; i < 16U; i++, n++) {
|
||||
bool b = READ_BIT1(temp, i);
|
||||
WRITE_BIT1(in, n, b);
|
||||
}
|
||||
}
|
||||
|
||||
bool CNXDNCRC::checkCRC15(const unsigned char* in, unsigned int length)
|
||||
{
|
||||
assert(in != NULL);
|
||||
|
||||
uint16_t crc = createCRC15(in, length);
|
||||
uint8_t temp1[2U];
|
||||
temp1[0U] = (crc >> 8) & 0xFFU;
|
||||
temp1[1U] = (crc >> 0) & 0xFFU;
|
||||
|
||||
uint8_t temp2[2U];
|
||||
temp2[0U] = 0x00U;
|
||||
temp2[1U] = 0x00U;
|
||||
unsigned int j = length;
|
||||
for (unsigned int i = 1U; i < 16U; i++, j++) {
|
||||
bool b = READ_BIT1(in, j);
|
||||
WRITE_BIT1(temp2, i, b);
|
||||
}
|
||||
|
||||
return temp1[0U] == temp2[0U] && temp1[1U] == temp2[1U];
|
||||
}
|
||||
|
||||
void CNXDNCRC::encodeCRC15(unsigned char* in, unsigned int length)
|
||||
{
|
||||
assert(in != NULL);
|
||||
|
||||
uint16_t crc = createCRC15(in, length);
|
||||
|
||||
uint8_t temp[2U];
|
||||
temp[0U] = (crc >> 8) & 0xFFU;
|
||||
temp[1U] = (crc >> 0) & 0xFFU;
|
||||
|
||||
unsigned int n = length;
|
||||
for (unsigned int i = 1U; i < 16U; i++, n++) {
|
||||
bool b = READ_BIT1(temp, i);
|
||||
WRITE_BIT1(in, n, b);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t CNXDNCRC::createCRC6(const unsigned char* in, unsigned int length)
|
||||
{
|
||||
uint8_t crc = 0x3FU;
|
||||
|
||||
for (unsigned int i = 0U; i < length; i++) {
|
||||
bool bit1 = READ_BIT1(in, i) != 0x00U;
|
||||
bool bit2 = (crc & 0x20U) == 0x20U;
|
||||
|
||||
crc <<= 1;
|
||||
|
||||
if (bit1 ^ bit2)
|
||||
crc ^= 0x27U;
|
||||
}
|
||||
|
||||
return crc & 0x3FU;
|
||||
}
|
||||
|
||||
uint16_t CNXDNCRC::createCRC12(const unsigned char* in, unsigned int length)
|
||||
{
|
||||
uint16_t crc = 0x0FFFU;
|
||||
|
||||
for (unsigned int i = 0U; i < length; i++) {
|
||||
bool bit1 = READ_BIT1(in, i) != 0x00U;
|
||||
bool bit2 = (crc & 0x0800U) == 0x0800U;
|
||||
|
||||
crc <<= 1;
|
||||
|
||||
if (bit1 ^ bit2)
|
||||
crc ^= 0x080FU;
|
||||
}
|
||||
|
||||
return crc & 0x0FFFU;
|
||||
}
|
||||
|
||||
uint16_t CNXDNCRC::createCRC15(const unsigned char* in, unsigned int length)
|
||||
{
|
||||
uint16_t crc = 0x7FFFU;
|
||||
|
||||
for (unsigned int i = 0U; i < length; i++) {
|
||||
bool bit1 = READ_BIT1(in, i) != 0x00U;
|
||||
bool bit2 = (crc & 0x4000U) == 0x4000U;
|
||||
|
||||
crc <<= 1;
|
||||
|
||||
if (bit1 ^ bit2)
|
||||
crc ^= 0x4CC5U;
|
||||
}
|
||||
|
||||
return crc & 0x7FFFU;
|
||||
}
|
42
NXDNGateway/NXDNCRC.h
Normal file
42
NXDNGateway/NXDNCRC.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if !defined(NXDNCRC_H)
|
||||
#define NXDNCRC_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class CNXDNCRC
|
||||
{
|
||||
public:
|
||||
static bool checkCRC6(const unsigned char* in, unsigned int length);
|
||||
static void encodeCRC6(unsigned char* in, unsigned int length);
|
||||
|
||||
static bool checkCRC12(const unsigned char* in, unsigned int length);
|
||||
static void encodeCRC12(unsigned char* in, unsigned int length);
|
||||
|
||||
static bool checkCRC15(const unsigned char* in, unsigned int length);
|
||||
static void encodeCRC15(unsigned char* in, unsigned int length);
|
||||
|
||||
private:
|
||||
static uint8_t createCRC6(const unsigned char* in, unsigned int length);
|
||||
static uint16_t createCRC12(const unsigned char* in, unsigned int length);
|
||||
static uint16_t createCRC15(const unsigned char* in, unsigned int length);
|
||||
};
|
||||
|
||||
#endif
|
380
NXDNGateway/NXDNGateway.cpp
Normal file
380
NXDNGateway/NXDNGateway.cpp
Normal file
@ -0,0 +1,380 @@
|
||||
/*
|
||||
* Copyright (C) 2016,2017,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "IcomNetwork.h"
|
||||
#include "NXDNNetwork.h"
|
||||
#include "NXDNGateway.h"
|
||||
#include "NXDNLookup.h"
|
||||
#include "Reflectors.h"
|
||||
#include "StopWatch.h"
|
||||
#include "Version.h"
|
||||
#include "Thread.h"
|
||||
#include "Voice.h"
|
||||
#include "Timer.h"
|
||||
#include "Log.h"
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#include <Windows.h>
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <pwd.h>
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
const char* DEFAULT_INI_FILE = "NXDNGateway.ini";
|
||||
#else
|
||||
const char* DEFAULT_INI_FILE = "/etc/NXDNGateway.ini";
|
||||
#endif
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstdarg>
|
||||
#include <ctime>
|
||||
#include <cstring>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
const char* iniFile = DEFAULT_INI_FILE;
|
||||
if (argc > 1) {
|
||||
for (int currentArg = 1; currentArg < argc; ++currentArg) {
|
||||
std::string arg = argv[currentArg];
|
||||
if ((arg == "-v") || (arg == "--version")) {
|
||||
::fprintf(stdout, "NXDNGateway version %s\n", VERSION);
|
||||
return 0;
|
||||
} else if (arg.substr(0, 1) == "-") {
|
||||
::fprintf(stderr, "Usage: NXDNGateway [-v|--version] [filename]\n");
|
||||
return 1;
|
||||
} else {
|
||||
iniFile = argv[currentArg];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CNXDNGateway* gateway = new CNXDNGateway(std::string(iniFile));
|
||||
gateway->run();
|
||||
delete gateway;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CNXDNGateway::CNXDNGateway(const std::string& file) :
|
||||
m_conf(file)
|
||||
{
|
||||
}
|
||||
|
||||
CNXDNGateway::~CNXDNGateway()
|
||||
{
|
||||
}
|
||||
|
||||
void CNXDNGateway::run()
|
||||
{
|
||||
bool ret = m_conf.read();
|
||||
if (!ret) {
|
||||
::fprintf(stderr, "NXDNGateway: cannot read the .ini file\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ret = ::LogInitialise(m_conf.getLogFilePath(), m_conf.getLogFileRoot(), 1U, 1U);
|
||||
if (!ret) {
|
||||
::fprintf(stderr, "NXDNGateway: unable to open the log file\n");
|
||||
return;
|
||||
}
|
||||
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
bool m_daemon = m_conf.getDaemon();
|
||||
if (m_daemon) {
|
||||
// Create new process
|
||||
pid_t pid = ::fork();
|
||||
if (pid == -1) {
|
||||
::LogWarning("Couldn't fork() , exiting");
|
||||
return;
|
||||
}
|
||||
else if (pid != 0)
|
||||
exit(EXIT_SUCCESS);
|
||||
|
||||
// Create new session and process group
|
||||
if (::setsid() == -1) {
|
||||
::LogWarning("Couldn't setsid(), exiting");
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the working directory to the root directory
|
||||
if (::chdir("/") == -1) {
|
||||
::LogWarning("Couldn't cd /, exiting");
|
||||
return;
|
||||
}
|
||||
|
||||
::close(STDIN_FILENO);
|
||||
::close(STDOUT_FILENO);
|
||||
::close(STDERR_FILENO);
|
||||
|
||||
//If we are currently root...
|
||||
if (getuid() == 0) {
|
||||
struct passwd* user = ::getpwnam("mmdvm");
|
||||
if (user == NULL) {
|
||||
::LogError("Could not get the mmdvm user, exiting");
|
||||
return;
|
||||
}
|
||||
|
||||
uid_t mmdvm_uid = user->pw_uid;
|
||||
gid_t mmdvm_gid = user->pw_gid;
|
||||
|
||||
//Set user and group ID's to mmdvm:mmdvm
|
||||
if (setgid(mmdvm_gid) != 0) {
|
||||
::LogWarning("Could not set mmdvm GID, exiting");
|
||||
return;
|
||||
}
|
||||
|
||||
if (setuid(mmdvm_uid) != 0) {
|
||||
::LogWarning("Could not set mmdvm UID, exiting");
|
||||
return;
|
||||
}
|
||||
|
||||
//Double check it worked (AKA Paranoia)
|
||||
if (setuid(0) != -1) {
|
||||
::LogWarning("It's possible to regain root - something is wrong!, exiting");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
CIcomNetwork localNetwork(m_conf.getMyAddress(), m_conf.getMyPort(), m_conf.getRptAddress(), m_conf.getRptPort(), false);
|
||||
ret = localNetwork.open();
|
||||
if (!ret) {
|
||||
::LogFinalise();
|
||||
return;
|
||||
}
|
||||
|
||||
CNXDNNetwork remoteNetwork(m_conf.getNetworkPort(), m_conf.getCallsign(), m_conf.getNetworkDebug());
|
||||
ret = remoteNetwork.open();
|
||||
if (!ret) {
|
||||
localNetwork.close();
|
||||
::LogFinalise();
|
||||
return;
|
||||
}
|
||||
|
||||
CReflectors reflectors(m_conf.getNetworkHosts1(), m_conf.getNetworkHosts2(), m_conf.getNetworkReloadTime());
|
||||
if (m_conf.getNetworkParrotPort() > 0U)
|
||||
reflectors.setParrot(m_conf.getNetworkParrotAddress(), m_conf.getNetworkParrotPort());
|
||||
reflectors.load();
|
||||
|
||||
CNXDNLookup* lookup = new CNXDNLookup(m_conf.getLookupName(), m_conf.getLookupTime());
|
||||
lookup->read();
|
||||
|
||||
CTimer inactivityTimer(1000U, m_conf.getNetworkInactivityTimeout() * 60U);
|
||||
CTimer lostTimer(1000U, 120U);
|
||||
CTimer pollTimer(1000U, 5U);
|
||||
|
||||
CStopWatch stopWatch;
|
||||
stopWatch.start();
|
||||
|
||||
CVoice* voice = NULL;
|
||||
if (m_conf.getVoiceEnabled())
|
||||
voice = new CVoice(m_conf.getVoiceDirectory(), m_conf.getVoiceLanguage(), 1U);
|
||||
|
||||
LogMessage("Starting NXDNGateway-%s", VERSION);
|
||||
|
||||
unsigned short srcId = 0U;
|
||||
unsigned short dstId = 0U;
|
||||
bool grp = false;
|
||||
|
||||
unsigned int currentId = 9999U;
|
||||
in_addr currentAddr;
|
||||
unsigned int currentPort = 0U;
|
||||
|
||||
unsigned int id = m_conf.getNetworkStartup();
|
||||
if (id != 9999U) {
|
||||
CNXDNReflector* reflector = reflectors.find(id);
|
||||
if (reflector != NULL) {
|
||||
currentId = id;
|
||||
currentAddr = reflector->m_address;
|
||||
currentPort = reflector->m_port;
|
||||
|
||||
inactivityTimer.start();
|
||||
pollTimer.start();
|
||||
lostTimer.start();
|
||||
|
||||
remoteNetwork.writePoll(currentAddr, currentPort);
|
||||
remoteNetwork.writePoll(currentAddr, currentPort);
|
||||
remoteNetwork.writePoll(currentAddr, currentPort);
|
||||
|
||||
LogMessage("Linked at startup to reflector %u", currentId);
|
||||
}
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
unsigned char buffer[200U];
|
||||
in_addr address;
|
||||
unsigned int port;
|
||||
|
||||
// From the reflector to the MMDVM
|
||||
unsigned int len = remoteNetwork.readData(buffer, 200U, address, port);
|
||||
if (len > 0U) {
|
||||
// If we're linked and it's from the right place, send it on
|
||||
if (currentId != 9999U && currentAddr.s_addr == address.s_addr && currentPort == port) {
|
||||
// Don't pass reflector control data through to the MMDVM
|
||||
if (::memcmp(buffer, "NXDND", 5U) == 0)
|
||||
localNetwork.write(buffer + 10U, len - 10U);
|
||||
|
||||
// Any network activity is proof that the reflector is alive
|
||||
lostTimer.start();
|
||||
}
|
||||
}
|
||||
|
||||
// From the MMDVM to the reflector or control data
|
||||
len = localNetwork.read(buffer);
|
||||
if (len > 0U) {
|
||||
if (buffer[0U] == 0x81U || buffer[0U] == 0x83U) {
|
||||
grp = (buffer[7U] & 0x20U) == 0x20U;
|
||||
|
||||
srcId = (buffer[8U] << 8) & 0xFF00U;
|
||||
srcId |= (buffer[9U] << 0) & 0x00FFU;
|
||||
|
||||
dstId = (buffer[10U] << 8) & 0xFF00U;
|
||||
dstId |= (buffer[11U] << 0) & 0x00FFU;
|
||||
|
||||
if (dstId != currentId) {
|
||||
CNXDNReflector* reflector = NULL;
|
||||
if (dstId != 9999U)
|
||||
reflector = reflectors.find(dstId);
|
||||
|
||||
// If we're unlinking or changing reflectors, unlink from the current one
|
||||
if (dstId == 9999U || reflector != NULL) {
|
||||
std::string callsign = lookup->find(srcId);
|
||||
|
||||
if (currentId != 9999U) {
|
||||
LogMessage("Unlinked from reflector %u by %s", currentId, callsign.c_str());
|
||||
|
||||
remoteNetwork.writeUnlink(currentAddr, currentPort);
|
||||
remoteNetwork.writeUnlink(currentAddr, currentPort);
|
||||
remoteNetwork.writeUnlink(currentAddr, currentPort);
|
||||
|
||||
inactivityTimer.stop();
|
||||
pollTimer.stop();
|
||||
lostTimer.stop();
|
||||
}
|
||||
|
||||
if (voice != NULL)
|
||||
voice->linkedTo(dstId);
|
||||
|
||||
currentId = dstId;
|
||||
}
|
||||
|
||||
// Link to the new reflector
|
||||
if (reflector != NULL) {
|
||||
currentId = dstId;
|
||||
currentAddr = reflector->m_address;
|
||||
currentPort = reflector->m_port;
|
||||
|
||||
std::string callsign = lookup->find(srcId);
|
||||
LogMessage("Linked to reflector %u by %s", currentId, callsign.c_str());
|
||||
|
||||
remoteNetwork.writePoll(currentAddr, currentPort);
|
||||
remoteNetwork.writePoll(currentAddr, currentPort);
|
||||
remoteNetwork.writePoll(currentAddr, currentPort);
|
||||
|
||||
inactivityTimer.start();
|
||||
pollTimer.start();
|
||||
lostTimer.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we're linked and we have a network, send it on
|
||||
if (currentId != 9999U) {
|
||||
remoteNetwork.writeData(buffer, len, srcId, dstId, grp, currentAddr, currentPort);
|
||||
inactivityTimer.start();
|
||||
}
|
||||
}
|
||||
|
||||
if (voice != NULL) {
|
||||
unsigned int length = voice->read(buffer);
|
||||
if (length > 0U)
|
||||
localNetwork.write(buffer, length);
|
||||
}
|
||||
|
||||
unsigned int ms = stopWatch.elapsed();
|
||||
stopWatch.start();
|
||||
|
||||
reflectors.clock(ms);
|
||||
|
||||
if (voice != NULL)
|
||||
voice->clock(ms);
|
||||
|
||||
inactivityTimer.clock(ms);
|
||||
if (inactivityTimer.isRunning() && inactivityTimer.hasExpired()) {
|
||||
if (currentId != 9999U) {
|
||||
LogMessage("Unlinking from %u due to inactivity", currentId);
|
||||
|
||||
remoteNetwork.writeUnlink(currentAddr, currentPort);
|
||||
remoteNetwork.writeUnlink(currentAddr, currentPort);
|
||||
remoteNetwork.writeUnlink(currentAddr, currentPort);
|
||||
|
||||
if (voice != NULL)
|
||||
voice->unlinked();
|
||||
currentId = 9999U;
|
||||
|
||||
pollTimer.stop();
|
||||
lostTimer.stop();
|
||||
}
|
||||
|
||||
inactivityTimer.stop();
|
||||
}
|
||||
|
||||
pollTimer.clock(ms);
|
||||
if (pollTimer.isRunning() && pollTimer.hasExpired()) {
|
||||
if (currentId != 9999U)
|
||||
remoteNetwork.writePoll(currentAddr, currentPort);
|
||||
pollTimer.start();
|
||||
}
|
||||
|
||||
lostTimer.clock(ms);
|
||||
if (lostTimer.isRunning() && lostTimer.hasExpired()) {
|
||||
if (currentId != 9999U) {
|
||||
LogWarning("No response from %u, unlinking", currentId);
|
||||
currentId = 9999U;
|
||||
}
|
||||
|
||||
inactivityTimer.stop();
|
||||
lostTimer.stop();
|
||||
}
|
||||
|
||||
localNetwork.clock(ms);
|
||||
|
||||
if (ms < 5U)
|
||||
CThread::sleep(5U);
|
||||
}
|
||||
|
||||
delete voice;
|
||||
|
||||
localNetwork.close();
|
||||
|
||||
remoteNetwork.close();
|
||||
|
||||
lookup->stop();
|
||||
|
||||
::LogFinalise();
|
||||
}
|
53
NXDNGateway/NXDNGateway.h
Normal file
53
NXDNGateway/NXDNGateway.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 2016,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if !defined(NXDNGateway_H)
|
||||
#define NXDNGateway_H
|
||||
|
||||
#include "Timer.h"
|
||||
#include "Conf.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
#include <netdb.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#else
|
||||
#include <winsock.h>
|
||||
#endif
|
||||
|
||||
class CNXDNGateway
|
||||
{
|
||||
public:
|
||||
CNXDNGateway(const std::string& file);
|
||||
~CNXDNGateway();
|
||||
|
||||
void run();
|
||||
|
||||
private:
|
||||
CConf m_conf;
|
||||
};
|
||||
|
||||
#endif
|
31
NXDNGateway/NXDNGateway.ini
Normal file
31
NXDNGateway/NXDNGateway.ini
Normal file
@ -0,0 +1,31 @@
|
||||
[General]
|
||||
Callsign=G4KLX
|
||||
RptAddress=127.0.0.1
|
||||
RptPort=14021
|
||||
LocalAddress=127.0.0.1
|
||||
LocalPort=14020
|
||||
Daemon=1
|
||||
|
||||
[Voice]
|
||||
Enabled=1
|
||||
Language=en_GB
|
||||
Directory=./Audio
|
||||
|
||||
[Id Lookup]
|
||||
Name=NXDN.csv
|
||||
Time=24
|
||||
|
||||
[Log]
|
||||
FilePath=.
|
||||
FileRoot=NXDNGateway
|
||||
|
||||
[Network]
|
||||
Port=14050
|
||||
HostsFile1=./NXDNHosts.txt
|
||||
HostsFile2=./private/NXDNHosts.txt
|
||||
ReloadTime=60
|
||||
ParrotAddress=127.0.0.1
|
||||
ParrotPort=42011
|
||||
Startup=10200
|
||||
InactivityTimeout=10
|
||||
Debug=0
|
187
NXDNGateway/NXDNGateway.vcxproj
Normal file
187
NXDNGateway/NXDNGateway.vcxproj
Normal file
@ -0,0 +1,187 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{8B7A5406-8560-4B40-ADDA-9B8EBF93E232}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>NXDNGateway</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Conf.h" />
|
||||
<ClInclude Include="IcomNetwork.h" />
|
||||
<ClInclude Include="Log.h" />
|
||||
<ClInclude Include="Mutex.h" />
|
||||
<ClInclude Include="NXDNCRC.h" />
|
||||
<ClInclude Include="NXDNGateway.h" />
|
||||
<ClInclude Include="NXDNLookup.h" />
|
||||
<ClInclude Include="NXDNNetwork.h" />
|
||||
<ClInclude Include="Reflectors.h" />
|
||||
<ClInclude Include="RingBuffer.h" />
|
||||
<ClInclude Include="StopWatch.h" />
|
||||
<ClInclude Include="Thread.h" />
|
||||
<ClInclude Include="Timer.h" />
|
||||
<ClInclude Include="UDPSocket.h" />
|
||||
<ClInclude Include="Utils.h" />
|
||||
<ClInclude Include="Version.h" />
|
||||
<ClInclude Include="Voice.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Conf.cpp" />
|
||||
<ClCompile Include="IcomNetwork.cpp" />
|
||||
<ClCompile Include="Log.cpp" />
|
||||
<ClCompile Include="Mutex.cpp" />
|
||||
<ClCompile Include="NXDNCRC.cpp" />
|
||||
<ClCompile Include="NXDNGateway.cpp" />
|
||||
<ClCompile Include="NXDNLookup.cpp" />
|
||||
<ClCompile Include="NXDNNetwork.cpp" />
|
||||
<ClCompile Include="Reflectors.cpp" />
|
||||
<ClCompile Include="StopWatch.cpp" />
|
||||
<ClCompile Include="Thread.cpp" />
|
||||
<ClCompile Include="Timer.cpp" />
|
||||
<ClCompile Include="UDPSocket.cpp" />
|
||||
<ClCompile Include="Utils.cpp" />
|
||||
<ClCompile Include="Voice.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
113
NXDNGateway/NXDNGateway.vcxproj.filters
Normal file
113
NXDNGateway/NXDNGateway.vcxproj.filters
Normal file
@ -0,0 +1,113 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Conf.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Log.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Mutex.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NXDNGateway.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="StopWatch.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Thread.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Timer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="UDPSocket.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Utils.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Version.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Reflectors.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NXDNLookup.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="IcomNetwork.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NXDNNetwork.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="RingBuffer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Voice.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NXDNCRC.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Conf.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Log.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Mutex.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="NXDNGateway.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="StopWatch.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Thread.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Timer.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="UDPSocket.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Utils.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Reflectors.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="NXDNLookup.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="IcomNetwork.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="NXDNNetwork.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Voice.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="NXDNCRC.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
7
NXDNGateway/NXDNHosts.txt
Normal file
7
NXDNGateway/NXDNHosts.txt
Normal file
@ -0,0 +1,7 @@
|
||||
# NXDNHosts.txt
|
||||
#
|
||||
# The format of this file is the number of the Talk Group followed by the host name or address and port
|
||||
#
|
||||
|
||||
# World Wide, 65000
|
||||
65000 176.9.1.168 41008
|
160
NXDNGateway/NXDNLookup.cpp
Normal file
160
NXDNGateway/NXDNLookup.cpp
Normal file
@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright (C) 2016,2017,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "NXDNLookup.h"
|
||||
#include "Timer.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cctype>
|
||||
|
||||
CNXDNLookup::CNXDNLookup(const std::string& filename, unsigned int reloadTime) :
|
||||
CThread(),
|
||||
m_filename(filename),
|
||||
m_reloadTime(reloadTime),
|
||||
m_table(),
|
||||
m_mutex(),
|
||||
m_stop(false)
|
||||
{
|
||||
}
|
||||
|
||||
CNXDNLookup::~CNXDNLookup()
|
||||
{
|
||||
}
|
||||
|
||||
bool CNXDNLookup::read()
|
||||
{
|
||||
bool ret = load();
|
||||
|
||||
if (m_reloadTime > 0U)
|
||||
run();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CNXDNLookup::entry()
|
||||
{
|
||||
LogInfo("Started the NXDN Id lookup reload thread");
|
||||
|
||||
CTimer timer(1U, 3600U * m_reloadTime);
|
||||
timer.start();
|
||||
|
||||
while (!m_stop) {
|
||||
sleep(1000U);
|
||||
|
||||
timer.clock();
|
||||
if (timer.hasExpired()) {
|
||||
load();
|
||||
timer.start();
|
||||
}
|
||||
}
|
||||
|
||||
LogInfo("Stopped the NXDN Id lookup reload thread");
|
||||
}
|
||||
|
||||
void CNXDNLookup::stop()
|
||||
{
|
||||
if (m_reloadTime == 0U) {
|
||||
delete this;
|
||||
return;
|
||||
}
|
||||
|
||||
m_stop = true;
|
||||
|
||||
wait();
|
||||
}
|
||||
|
||||
std::string CNXDNLookup::find(unsigned int id)
|
||||
{
|
||||
std::string callsign;
|
||||
|
||||
if (id == 0xFFFFU)
|
||||
return std::string("ALL");
|
||||
|
||||
m_mutex.lock();
|
||||
|
||||
try {
|
||||
callsign = m_table.at(id);
|
||||
} catch (...) {
|
||||
char text[10U];
|
||||
::sprintf(text, "%u", id);
|
||||
callsign = std::string(text);
|
||||
}
|
||||
|
||||
m_mutex.unlock();
|
||||
|
||||
return callsign;
|
||||
}
|
||||
|
||||
bool CNXDNLookup::exists(unsigned int id)
|
||||
{
|
||||
m_mutex.lock();
|
||||
|
||||
bool found = m_table.count(id) == 1U;
|
||||
|
||||
m_mutex.unlock();
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
bool CNXDNLookup::load()
|
||||
{
|
||||
FILE* fp = ::fopen(m_filename.c_str(), "rt");
|
||||
if (fp == NULL) {
|
||||
LogWarning("Cannot open the NXDN Id lookup file - %s", m_filename.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
m_mutex.lock();
|
||||
|
||||
// Remove the old entries
|
||||
m_table.clear();
|
||||
|
||||
char buffer[100U];
|
||||
while (::fgets(buffer, 100U, fp) != NULL) {
|
||||
if (buffer[0U] == '#')
|
||||
continue;
|
||||
|
||||
char* p1 = ::strtok(buffer, ",\t\r\n");
|
||||
char* p2 = ::strtok(NULL, ",\t\r\n");
|
||||
|
||||
if (p1 != NULL && p2 != NULL) {
|
||||
unsigned int id = (unsigned int)::atoi(p1);
|
||||
if (id > 0U) {
|
||||
for (char* p = p2; *p != 0x00U; p++)
|
||||
*p = ::toupper(*p);
|
||||
|
||||
m_table[id] = std::string(p2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_mutex.unlock();
|
||||
|
||||
::fclose(fp);
|
||||
|
||||
size_t size = m_table.size();
|
||||
if (size == 0U)
|
||||
return false;
|
||||
|
||||
LogInfo("Loaded %u Ids to the NXDN callsign lookup table", size);
|
||||
|
||||
return true;
|
||||
}
|
53
NXDNGateway/NXDNLookup.h
Normal file
53
NXDNGateway/NXDNLookup.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 2016,2017,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef NXDNLookup_H
|
||||
#define NXDNLookup_H
|
||||
|
||||
#include "Thread.h"
|
||||
#include "Mutex.h"
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
class CNXDNLookup : public CThread {
|
||||
public:
|
||||
CNXDNLookup(const std::string& filename, unsigned int reloadTime);
|
||||
virtual ~CNXDNLookup();
|
||||
|
||||
bool read();
|
||||
|
||||
virtual void entry();
|
||||
|
||||
std::string find(unsigned int id);
|
||||
|
||||
bool exists(unsigned int id);
|
||||
|
||||
void stop();
|
||||
|
||||
private:
|
||||
std::string m_filename;
|
||||
unsigned int m_reloadTime;
|
||||
std::unordered_map<unsigned int, std::string> m_table;
|
||||
CMutex m_mutex;
|
||||
bool m_stop;
|
||||
|
||||
bool load();
|
||||
};
|
||||
|
||||
#endif
|
144
NXDNGateway/NXDNNetwork.cpp
Normal file
144
NXDNGateway/NXDNNetwork.cpp
Normal file
@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2014,2016,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "NXDNNetwork.h"
|
||||
#include "Utils.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
CNXDNNetwork::CNXDNNetwork(unsigned int port, const std::string& callsign, bool debug) :
|
||||
m_callsign(callsign),
|
||||
m_socket(port),
|
||||
m_debug(debug)
|
||||
{
|
||||
m_callsign.resize(10U, ' ');
|
||||
}
|
||||
|
||||
CNXDNNetwork::~CNXDNNetwork()
|
||||
{
|
||||
}
|
||||
|
||||
bool CNXDNNetwork::open()
|
||||
{
|
||||
LogInfo("Opening NXDN network connection");
|
||||
|
||||
return m_socket.open();
|
||||
}
|
||||
|
||||
bool CNXDNNetwork::writeData(const unsigned char* data, unsigned int length, unsigned short srcId, unsigned short dstId, bool grp, const in_addr& address, unsigned int port)
|
||||
{
|
||||
assert(data != NULL);
|
||||
assert(length > 0U);
|
||||
assert(port > 0U);
|
||||
|
||||
unsigned char buffer[20U];
|
||||
|
||||
buffer[0U] = 'N';
|
||||
buffer[1U] = 'X';
|
||||
buffer[2U] = 'D';
|
||||
buffer[3U] = 'N';
|
||||
buffer[4U] = 'D';
|
||||
|
||||
buffer[5U] = (srcId >> 8) & 0xFFU;
|
||||
buffer[6U] = (srcId >> 0) & 0xFFU;
|
||||
|
||||
buffer[7U] = (dstId >> 8) & 0xFFU;
|
||||
buffer[8U] = (dstId >> 0) & 0xFFU;
|
||||
|
||||
buffer[9U] = 0x00U;
|
||||
buffer[9U] |= grp ? 0x01U : 0x00U;
|
||||
|
||||
if (data[0U] == 0x81U || data[0U] == 0x83U) {
|
||||
buffer[9U] |= buffer[5U] == 0x01U ? 0x04U : 0x00U;
|
||||
buffer[9U] |= buffer[5U] == 0x08U ? 0x08U : 0x00U;
|
||||
}
|
||||
|
||||
::memcpy(buffer + 10U, data, 33U);
|
||||
|
||||
if (m_debug)
|
||||
CUtils::dump(1U, "NXDN Network Data Sent", buffer, 43U);
|
||||
|
||||
return m_socket.write(buffer, 43U, address, port);
|
||||
}
|
||||
|
||||
bool CNXDNNetwork::writePoll(const in_addr& address, unsigned int port)
|
||||
{
|
||||
assert(port > 0U);
|
||||
|
||||
unsigned char data[20U];
|
||||
|
||||
data[0U] = 'N';
|
||||
data[1U] = 'X';
|
||||
data[2U] = 'D';
|
||||
data[3U] = 'N';
|
||||
data[4U] = 'P';
|
||||
|
||||
for (unsigned int i = 0U; i < 10U; i++)
|
||||
data[i + 5U] = m_callsign.at(i);
|
||||
|
||||
if (m_debug)
|
||||
CUtils::dump(1U, "NXDN Network Poll Sent", data, 15U);
|
||||
|
||||
return m_socket.write(data, 15U, address, port);
|
||||
}
|
||||
|
||||
bool CNXDNNetwork::writeUnlink(const in_addr& address, unsigned int port)
|
||||
{
|
||||
assert(port > 0U);
|
||||
|
||||
unsigned char data[20U];
|
||||
|
||||
data[0U] = 'N';
|
||||
data[1U] = 'X';
|
||||
data[2U] = 'D';
|
||||
data[3U] = 'N';
|
||||
data[4U] = 'U';
|
||||
|
||||
for (unsigned int i = 0U; i < 10U; i++)
|
||||
data[i + 5U] = m_callsign.at(i);
|
||||
|
||||
if (m_debug)
|
||||
CUtils::dump(1U, "NXDN Network Unlink Sent", data, 15U);
|
||||
|
||||
return m_socket.write(data, 15U, address, port);
|
||||
}
|
||||
|
||||
unsigned int CNXDNNetwork::readData(unsigned char* data, unsigned int length, in_addr& address, unsigned int& port)
|
||||
{
|
||||
assert(data != NULL);
|
||||
assert(length > 0U);
|
||||
|
||||
int len = m_socket.read(data, length, address, port);
|
||||
if (len <= 0)
|
||||
return 0U;
|
||||
|
||||
if (m_debug)
|
||||
CUtils::dump(1U, "NXDN Network Data Received", data, len);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
void CNXDNNetwork::close()
|
||||
{
|
||||
m_socket.close();
|
||||
|
||||
LogInfo("Closing NXDN network connection");
|
||||
}
|
50
NXDNGateway/NXDNNetwork.h
Normal file
50
NXDNGateway/NXDNNetwork.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2014,2016,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef NXDNNetwork_H
|
||||
#define NXDNNetwork_H
|
||||
|
||||
#include "UDPSocket.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
class CNXDNNetwork {
|
||||
public:
|
||||
CNXDNNetwork(unsigned int port, const std::string& callsign, bool debug);
|
||||
~CNXDNNetwork();
|
||||
|
||||
bool open();
|
||||
|
||||
bool writeData(const unsigned char* data, unsigned int length, unsigned short srcId, unsigned short dstId, bool grp, const in_addr& address, unsigned int port);
|
||||
|
||||
bool writePoll(const in_addr& address, unsigned int port);
|
||||
|
||||
bool writeUnlink(const in_addr& address, unsigned int port);
|
||||
|
||||
unsigned int readData(unsigned char* data, unsigned int length, in_addr& address, unsigned int& port);
|
||||
|
||||
void close();
|
||||
|
||||
private:
|
||||
std::string m_callsign;
|
||||
CUDPSocket m_socket;
|
||||
bool m_debug;
|
||||
};
|
||||
|
||||
#endif
|
159
NXDNGateway/Reflectors.cpp
Normal file
159
NXDNGateway/Reflectors.cpp
Normal file
@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright (C) 2016,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "Reflectors.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <cctype>
|
||||
|
||||
CReflectors::CReflectors(const std::string& hostsFile1, const std::string& hostsFile2, unsigned int reloadTime) :
|
||||
m_hostsFile1(hostsFile1),
|
||||
m_hostsFile2(hostsFile2),
|
||||
m_parrotAddress(),
|
||||
m_parrotPort(0U),
|
||||
m_reflectors(),
|
||||
m_timer(1000U, reloadTime * 60U)
|
||||
{
|
||||
if (reloadTime > 0U)
|
||||
m_timer.start();
|
||||
}
|
||||
|
||||
CReflectors::~CReflectors()
|
||||
{
|
||||
for (std::vector<CNXDNReflector*>::iterator it = m_reflectors.begin(); it != m_reflectors.end(); ++it)
|
||||
delete *it;
|
||||
|
||||
m_reflectors.clear();
|
||||
}
|
||||
|
||||
void CReflectors::setParrot(const std::string& address, unsigned int port)
|
||||
{
|
||||
m_parrotAddress = address;
|
||||
m_parrotPort = port;
|
||||
}
|
||||
|
||||
bool CReflectors::load()
|
||||
{
|
||||
// Clear out the old reflector list
|
||||
for (std::vector<CNXDNReflector*>::iterator it = m_reflectors.begin(); it != m_reflectors.end(); ++it)
|
||||
delete *it;
|
||||
|
||||
m_reflectors.clear();
|
||||
|
||||
FILE* fp = ::fopen(m_hostsFile1.c_str(), "rt");
|
||||
if (fp != NULL) {
|
||||
char buffer[100U];
|
||||
while (::fgets(buffer, 100U, fp) != NULL) {
|
||||
if (buffer[0U] == '#')
|
||||
continue;
|
||||
|
||||
char* p1 = ::strtok(buffer, " \t\r\n");
|
||||
char* p2 = ::strtok(NULL, " \t\r\n");
|
||||
char* p3 = ::strtok(NULL, " \t\r\n");
|
||||
|
||||
if (p1 != NULL && p2 != NULL && p3 != NULL) {
|
||||
std::string host = std::string(p2);
|
||||
|
||||
in_addr address = CUDPSocket::lookup(host);
|
||||
if (address.s_addr != INADDR_NONE) {
|
||||
CNXDNReflector* refl = new CNXDNReflector;
|
||||
refl->m_id = (unsigned int)::atoi(p1);
|
||||
refl->m_address = address;
|
||||
refl->m_port = (unsigned int)::atoi(p3);
|
||||
|
||||
m_reflectors.push_back(refl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
::fclose(fp);
|
||||
}
|
||||
|
||||
fp = ::fopen(m_hostsFile2.c_str(), "rt");
|
||||
if (fp != NULL) {
|
||||
char buffer[100U];
|
||||
while (::fgets(buffer, 100U, fp) != NULL) {
|
||||
if (buffer[0U] == '#')
|
||||
continue;
|
||||
|
||||
char* p1 = ::strtok(buffer, " \t\r\n");
|
||||
char* p2 = ::strtok(NULL, " \t\r\n");
|
||||
char* p3 = ::strtok(NULL, " \t\r\n");
|
||||
|
||||
if (p1 != NULL && p2 != NULL && p3 != NULL) {
|
||||
std::string host = std::string(p2);
|
||||
|
||||
in_addr address = CUDPSocket::lookup(host);
|
||||
if (address.s_addr != INADDR_NONE) {
|
||||
CNXDNReflector* refl = new CNXDNReflector;
|
||||
refl->m_id = (unsigned int)::atoi(p1);
|
||||
refl->m_address = address;
|
||||
refl->m_port = (unsigned int)::atoi(p3);
|
||||
|
||||
m_reflectors.push_back(refl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
::fclose(fp);
|
||||
}
|
||||
|
||||
size_t size = m_reflectors.size();
|
||||
LogInfo("Loaded %u NXDN reflectors", size);
|
||||
|
||||
// Add the Parrot entry
|
||||
if (m_parrotPort > 0U) {
|
||||
CNXDNReflector* refl = new CNXDNReflector;
|
||||
refl->m_id = 10U;
|
||||
refl->m_address = CUDPSocket::lookup(m_parrotAddress);
|
||||
refl->m_port = m_parrotPort;
|
||||
m_reflectors.push_back(refl);
|
||||
LogInfo("Loaded NXDN parrot (TG%u)", refl->m_id);
|
||||
}
|
||||
|
||||
size = m_reflectors.size();
|
||||
if (size == 0U)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CNXDNReflector* CReflectors::find(unsigned int id)
|
||||
{
|
||||
for (std::vector<CNXDNReflector*>::iterator it = m_reflectors.begin(); it != m_reflectors.end(); ++it) {
|
||||
if (id == (*it)->m_id)
|
||||
return *it;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CReflectors::clock(unsigned int ms)
|
||||
{
|
||||
m_timer.clock(ms);
|
||||
|
||||
if (m_timer.isRunning() && m_timer.hasExpired()) {
|
||||
load();
|
||||
m_timer.start();
|
||||
}
|
||||
}
|
64
NXDNGateway/Reflectors.h
Normal file
64
NXDNGateway/Reflectors.h
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 2016,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if !defined(Reflectors_H)
|
||||
#define Reflectors_H
|
||||
|
||||
#include "UDPSocket.h"
|
||||
#include "Timer.h"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
class CNXDNReflector {
|
||||
public:
|
||||
CNXDNReflector() :
|
||||
m_id(),
|
||||
m_address(),
|
||||
m_port(0U)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned int m_id;
|
||||
in_addr m_address;
|
||||
unsigned int m_port;
|
||||
};
|
||||
|
||||
class CReflectors {
|
||||
public:
|
||||
CReflectors(const std::string& hostsFile1, const std::string& hostsFile2, unsigned int reloadTime);
|
||||
~CReflectors();
|
||||
|
||||
void setParrot(const std::string& address, unsigned int port);
|
||||
|
||||
bool load();
|
||||
|
||||
CNXDNReflector* find(unsigned int id);
|
||||
|
||||
void clock(unsigned int ms);
|
||||
|
||||
private:
|
||||
std::string m_hostsFile1;
|
||||
std::string m_hostsFile2;
|
||||
std::string m_parrotAddress;
|
||||
unsigned int m_parrotPort;
|
||||
std::vector<CNXDNReflector*> m_reflectors;
|
||||
CTimer m_timer;
|
||||
};
|
||||
|
||||
#endif
|
147
NXDNGateway/RingBuffer.h
Normal file
147
NXDNGateway/RingBuffer.h
Normal file
@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright (C) 2006-2009,2012,2013,2015,2016,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef RingBuffer_H
|
||||
#define RingBuffer_H
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
template<class T> class CRingBuffer {
|
||||
public:
|
||||
CRingBuffer(unsigned int length, const char* name) :
|
||||
m_length(length),
|
||||
m_name(name),
|
||||
m_buffer(NULL),
|
||||
m_iPtr(0U),
|
||||
m_oPtr(0U)
|
||||
{
|
||||
assert(length > 0U);
|
||||
assert(name != NULL);
|
||||
|
||||
m_buffer = new T[length];
|
||||
|
||||
::memset(m_buffer, 0x00, m_length * sizeof(T));
|
||||
}
|
||||
|
||||
~CRingBuffer()
|
||||
{
|
||||
delete[] m_buffer;
|
||||
}
|
||||
|
||||
bool addData(const T* buffer, unsigned int nSamples)
|
||||
{
|
||||
if (nSamples >= freeSpace()) {
|
||||
::fprintf(stderr, "**** Overflow in %s ring buffer, %u >= %u\n", m_name, nSamples, freeSpace());
|
||||
return false;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0U; i < nSamples; i++) {
|
||||
m_buffer[m_iPtr++] = buffer[i];
|
||||
|
||||
if (m_iPtr == m_length)
|
||||
m_iPtr = 0U;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool getData(T* buffer, unsigned int nSamples)
|
||||
{
|
||||
if (dataSize() < nSamples) {
|
||||
::fprintf(stderr, "**** Underflow in %s ring buffer, %u < %u\n", m_name, dataSize(), nSamples);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0U; i < nSamples; i++) {
|
||||
buffer[i] = m_buffer[m_oPtr++];
|
||||
|
||||
if (m_oPtr == m_length)
|
||||
m_oPtr = 0U;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool peek(T* buffer, unsigned int nSamples)
|
||||
{
|
||||
if (dataSize() < nSamples) {
|
||||
::fprintf(stderr, "**** Underflow peek in %s ring buffer, %u < %u\n", m_name, dataSize(), nSamples);
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int ptr = m_oPtr;
|
||||
for (unsigned int i = 0U; i < nSamples; i++) {
|
||||
buffer[i] = m_buffer[ptr++];
|
||||
|
||||
if (ptr == m_length)
|
||||
ptr = 0U;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_iPtr = 0U;
|
||||
m_oPtr = 0U;
|
||||
|
||||
::memset(m_buffer, 0x00, m_length * sizeof(T));
|
||||
}
|
||||
|
||||
unsigned int freeSpace() const
|
||||
{
|
||||
if (m_oPtr == m_iPtr)
|
||||
return m_length;
|
||||
|
||||
if (m_oPtr > m_iPtr)
|
||||
return m_oPtr - m_iPtr;
|
||||
|
||||
return (m_length + m_oPtr) - m_iPtr;
|
||||
}
|
||||
|
||||
unsigned int dataSize() const
|
||||
{
|
||||
return m_length - freeSpace();
|
||||
}
|
||||
|
||||
bool hasSpace(unsigned int length) const
|
||||
{
|
||||
return freeSpace() > length;
|
||||
}
|
||||
|
||||
bool hasData() const
|
||||
{
|
||||
return m_oPtr != m_iPtr;
|
||||
}
|
||||
|
||||
bool isEmpty() const
|
||||
{
|
||||
return m_oPtr == m_iPtr;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned int m_length;
|
||||
const char* m_name;
|
||||
T* m_buffer;
|
||||
unsigned int m_iPtr;
|
||||
unsigned int m_oPtr;
|
||||
};
|
||||
|
||||
#endif
|
84
NXDNGateway/StopWatch.cpp
Normal file
84
NXDNGateway/StopWatch.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "StopWatch.h"
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
|
||||
CStopWatch::CStopWatch() :
|
||||
m_frequency(),
|
||||
m_start()
|
||||
{
|
||||
::QueryPerformanceFrequency(&m_frequency);
|
||||
}
|
||||
|
||||
CStopWatch::~CStopWatch()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned long CStopWatch::start()
|
||||
{
|
||||
::QueryPerformanceCounter(&m_start);
|
||||
|
||||
return (unsigned long)(m_start.QuadPart / m_frequency.QuadPart);
|
||||
}
|
||||
|
||||
unsigned int CStopWatch::elapsed()
|
||||
{
|
||||
LARGE_INTEGER now;
|
||||
::QueryPerformanceCounter(&now);
|
||||
|
||||
LARGE_INTEGER temp;
|
||||
temp.QuadPart = (now.QuadPart - m_start.QuadPart) * 1000;
|
||||
|
||||
return (unsigned int)(temp.QuadPart / m_frequency.QuadPart);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
CStopWatch::CStopWatch() :
|
||||
m_start()
|
||||
{
|
||||
}
|
||||
|
||||
CStopWatch::~CStopWatch()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned long CStopWatch::start()
|
||||
{
|
||||
::gettimeofday(&m_start, NULL);
|
||||
|
||||
return m_start.tv_usec;
|
||||
}
|
||||
|
||||
unsigned int CStopWatch::elapsed()
|
||||
{
|
||||
struct timeval now;
|
||||
::gettimeofday(&now, NULL);
|
||||
|
||||
unsigned int elapsed = (now.tv_sec - m_start.tv_sec) * 1000U;
|
||||
elapsed += now.tv_usec / 1000U;
|
||||
elapsed -= m_start.tv_usec / 1000U;
|
||||
|
||||
return elapsed;
|
||||
}
|
||||
|
||||
#endif
|
46
NXDNGateway/StopWatch.h
Normal file
46
NXDNGateway/StopWatch.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if !defined(STOPWATCH_H)
|
||||
#define STOPWATCH_H
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
class CStopWatch
|
||||
{
|
||||
public:
|
||||
CStopWatch();
|
||||
~CStopWatch();
|
||||
|
||||
unsigned long start();
|
||||
unsigned int elapsed();
|
||||
|
||||
private:
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
LARGE_INTEGER m_frequency;
|
||||
LARGE_INTEGER m_start;
|
||||
#else
|
||||
struct timeval m_start;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
101
NXDNGateway/Thread.cpp
Normal file
101
NXDNGateway/Thread.cpp
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "Thread.h"
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
|
||||
CThread::CThread() :
|
||||
m_handle()
|
||||
{
|
||||
}
|
||||
|
||||
CThread::~CThread()
|
||||
{
|
||||
}
|
||||
|
||||
bool CThread::run()
|
||||
{
|
||||
m_handle = ::CreateThread(NULL, 0, &helper, this, 0, NULL);
|
||||
|
||||
return m_handle != NULL;
|
||||
}
|
||||
|
||||
|
||||
void CThread::wait()
|
||||
{
|
||||
::WaitForSingleObject(m_handle, INFINITE);
|
||||
|
||||
::CloseHandle(m_handle);
|
||||
}
|
||||
|
||||
|
||||
DWORD CThread::helper(LPVOID arg)
|
||||
{
|
||||
CThread* p = (CThread*)arg;
|
||||
|
||||
p->entry();
|
||||
|
||||
return 0UL;
|
||||
}
|
||||
|
||||
void CThread::sleep(unsigned int ms)
|
||||
{
|
||||
::Sleep(ms);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
CThread::CThread() :
|
||||
m_thread()
|
||||
{
|
||||
}
|
||||
|
||||
CThread::~CThread()
|
||||
{
|
||||
}
|
||||
|
||||
bool CThread::run()
|
||||
{
|
||||
return ::pthread_create(&m_thread, NULL, helper, this) == 0;
|
||||
}
|
||||
|
||||
|
||||
void CThread::wait()
|
||||
{
|
||||
::pthread_join(m_thread, NULL);
|
||||
}
|
||||
|
||||
|
||||
void* CThread::helper(void* arg)
|
||||
{
|
||||
CThread* p = (CThread*)arg;
|
||||
|
||||
p->entry();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CThread::sleep(unsigned int ms)
|
||||
{
|
||||
::usleep(ms * 1000);
|
||||
}
|
||||
|
||||
#endif
|
56
NXDNGateway/Thread.h
Normal file
56
NXDNGateway/Thread.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if !defined(THREAD_H)
|
||||
#define THREAD_H
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
class CThread
|
||||
{
|
||||
public:
|
||||
CThread();
|
||||
virtual ~CThread();
|
||||
|
||||
virtual bool run();
|
||||
|
||||
virtual void entry() = 0;
|
||||
|
||||
virtual void wait();
|
||||
|
||||
static void sleep(unsigned int ms);
|
||||
|
||||
private:
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
HANDLE m_handle;
|
||||
#else
|
||||
pthread_t m_thread;
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
static DWORD __stdcall helper(LPVOID arg);
|
||||
#else
|
||||
static void* helper(void* arg);
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
68
NXDNGateway/Timer.cpp
Normal file
68
NXDNGateway/Timer.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (C) 2009,2010,2015 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "Timer.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
|
||||
CTimer::CTimer(unsigned int ticksPerSec, unsigned int secs, unsigned int msecs) :
|
||||
m_ticksPerSec(ticksPerSec),
|
||||
m_timeout(0U),
|
||||
m_timer(0U)
|
||||
{
|
||||
assert(ticksPerSec > 0U);
|
||||
|
||||
if (secs > 0U || msecs > 0U) {
|
||||
// m_timeout = ((secs * 1000U + msecs) * m_ticksPerSec) / 1000U + 1U;
|
||||
unsigned long long temp = (secs * 1000ULL + msecs) * m_ticksPerSec;
|
||||
m_timeout = (unsigned int)(temp / 1000ULL + 1ULL);
|
||||
}
|
||||
}
|
||||
|
||||
CTimer::~CTimer()
|
||||
{
|
||||
}
|
||||
|
||||
void CTimer::setTimeout(unsigned int secs, unsigned int msecs)
|
||||
{
|
||||
if (secs > 0U || msecs > 0U) {
|
||||
// m_timeout = ((secs * 1000U + msecs) * m_ticksPerSec) / 1000U + 1U;
|
||||
unsigned long long temp = (secs * 1000ULL + msecs) * m_ticksPerSec;
|
||||
m_timeout = (unsigned int)(temp / 1000ULL + 1ULL);
|
||||
} else {
|
||||
m_timeout = 0U;
|
||||
m_timer = 0U;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int CTimer::getTimeout() const
|
||||
{
|
||||
if (m_timeout == 0U)
|
||||
return 0U;
|
||||
|
||||
return (m_timeout - 1U) / m_ticksPerSec;
|
||||
}
|
||||
|
||||
unsigned int CTimer::getTimer() const
|
||||
{
|
||||
if (m_timer == 0U)
|
||||
return 0U;
|
||||
|
||||
return (m_timer - 1U) / m_ticksPerSec;
|
||||
}
|
89
NXDNGateway/Timer.h
Normal file
89
NXDNGateway/Timer.h
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (C) 2009,2010,2011,2014 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef Timer_H
|
||||
#define Timer_H
|
||||
|
||||
class CTimer {
|
||||
public:
|
||||
CTimer(unsigned int ticksPerSec, unsigned int secs = 0U, unsigned int msecs = 0U);
|
||||
~CTimer();
|
||||
|
||||
void setTimeout(unsigned int secs, unsigned int msecs = 0U);
|
||||
|
||||
unsigned int getTimeout() const;
|
||||
unsigned int getTimer() const;
|
||||
|
||||
unsigned int getRemaining()
|
||||
{
|
||||
if (m_timeout == 0U || m_timer == 0U)
|
||||
return 0U;
|
||||
|
||||
if (m_timer >= m_timeout)
|
||||
return 0U;
|
||||
|
||||
return (m_timeout - m_timer) / m_ticksPerSec;
|
||||
}
|
||||
|
||||
bool isRunning()
|
||||
{
|
||||
return m_timer > 0U;
|
||||
}
|
||||
|
||||
void start(unsigned int secs, unsigned int msecs = 0U)
|
||||
{
|
||||
setTimeout(secs, msecs);
|
||||
|
||||
start();
|
||||
}
|
||||
|
||||
void start()
|
||||
{
|
||||
if (m_timeout > 0U)
|
||||
m_timer = 1U;
|
||||
}
|
||||
|
||||
void stop()
|
||||
{
|
||||
m_timer = 0U;
|
||||
}
|
||||
|
||||
bool hasExpired()
|
||||
{
|
||||
if (m_timeout == 0U || m_timer == 0U)
|
||||
return false;
|
||||
|
||||
if (m_timer >= m_timeout)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void clock(unsigned int ticks = 1U)
|
||||
{
|
||||
if (m_timer > 0U && m_timeout > 0U)
|
||||
m_timer += ticks;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned int m_ticksPerSec;
|
||||
unsigned int m_timeout;
|
||||
unsigned int m_timer;
|
||||
};
|
||||
|
||||
#endif
|
262
NXDNGateway/UDPSocket.cpp
Normal file
262
NXDNGateway/UDPSocket.cpp
Normal file
@ -0,0 +1,262 @@
|
||||
/*
|
||||
* Copyright (C) 2006-2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "UDPSocket.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
#endif
|
||||
|
||||
|
||||
CUDPSocket::CUDPSocket(const std::string& address, unsigned int port) :
|
||||
m_address(address),
|
||||
m_port(port),
|
||||
m_fd(-1)
|
||||
{
|
||||
assert(!address.empty());
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
WSAData data;
|
||||
int wsaRet = ::WSAStartup(MAKEWORD(2, 2), &data);
|
||||
if (wsaRet != 0)
|
||||
LogError("Error from WSAStartup");
|
||||
#endif
|
||||
}
|
||||
|
||||
CUDPSocket::CUDPSocket(unsigned int port) :
|
||||
m_address(),
|
||||
m_port(port),
|
||||
m_fd(-1)
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
WSAData data;
|
||||
int wsaRet = ::WSAStartup(MAKEWORD(2, 2), &data);
|
||||
if (wsaRet != 0)
|
||||
LogError("Error from WSAStartup");
|
||||
#endif
|
||||
}
|
||||
|
||||
CUDPSocket::~CUDPSocket()
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
::WSACleanup();
|
||||
#endif
|
||||
}
|
||||
|
||||
in_addr CUDPSocket::lookup(const std::string& hostname)
|
||||
{
|
||||
in_addr addr;
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
unsigned long address = ::inet_addr(hostname.c_str());
|
||||
if (address != INADDR_NONE && address != INADDR_ANY) {
|
||||
addr.s_addr = address;
|
||||
return addr;
|
||||
}
|
||||
|
||||
struct hostent* hp = ::gethostbyname(hostname.c_str());
|
||||
if (hp != NULL) {
|
||||
::memcpy(&addr, hp->h_addr_list[0], sizeof(struct in_addr));
|
||||
return addr;
|
||||
}
|
||||
|
||||
LogError("Cannot find address for host %s", hostname.c_str());
|
||||
|
||||
addr.s_addr = INADDR_NONE;
|
||||
return addr;
|
||||
#else
|
||||
in_addr_t address = ::inet_addr(hostname.c_str());
|
||||
if (address != in_addr_t(-1)) {
|
||||
addr.s_addr = address;
|
||||
return addr;
|
||||
}
|
||||
|
||||
struct hostent* hp = ::gethostbyname(hostname.c_str());
|
||||
if (hp != NULL) {
|
||||
::memcpy(&addr, hp->h_addr_list[0], sizeof(struct in_addr));
|
||||
return addr;
|
||||
}
|
||||
|
||||
LogError("Cannot find address for host %s", hostname.c_str());
|
||||
|
||||
addr.s_addr = INADDR_NONE;
|
||||
return addr;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool CUDPSocket::open()
|
||||
{
|
||||
m_fd = ::socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (m_fd < 0) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
LogError("Cannot create the UDP socket, err: %lu", ::GetLastError());
|
||||
#else
|
||||
LogError("Cannot create the UDP socket, err: %d", errno);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_port > 0U) {
|
||||
sockaddr_in addr;
|
||||
::memset(&addr, 0x00, sizeof(sockaddr_in));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(m_port);
|
||||
addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
|
||||
if (!m_address.empty()) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
addr.sin_addr.s_addr = ::inet_addr(m_address.c_str());
|
||||
#else
|
||||
addr.sin_addr.s_addr = ::inet_addr(m_address.c_str());
|
||||
#endif
|
||||
if (addr.sin_addr.s_addr == INADDR_NONE) {
|
||||
LogError("The local address is invalid - %s", m_address.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int reuse = 1;
|
||||
if (::setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) == -1) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
LogError("Cannot set the UDP socket option, err: %lu", ::GetLastError());
|
||||
#else
|
||||
LogError("Cannot set the UDP socket option, err: %d", errno);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
if (::bind(m_fd, (sockaddr*)&addr, sizeof(sockaddr_in)) == -1) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
LogError("Cannot bind the UDP address, err: %lu", ::GetLastError());
|
||||
#else
|
||||
LogError("Cannot bind the UDP address, err: %d", errno);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int CUDPSocket::read(unsigned char* buffer, unsigned int length, in_addr& address, unsigned int& port)
|
||||
{
|
||||
assert(buffer != NULL);
|
||||
assert(length > 0U);
|
||||
|
||||
// Check that the readfrom() won't block
|
||||
fd_set readFds;
|
||||
FD_ZERO(&readFds);
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
FD_SET((unsigned int)m_fd, &readFds);
|
||||
#else
|
||||
FD_SET(m_fd, &readFds);
|
||||
#endif
|
||||
|
||||
// Return immediately
|
||||
timeval tv;
|
||||
tv.tv_sec = 0L;
|
||||
tv.tv_usec = 0L;
|
||||
|
||||
int ret = ::select(m_fd + 1, &readFds, NULL, NULL, &tv);
|
||||
if (ret < 0) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
LogError("Error returned from UDP select, err: %lu", ::GetLastError());
|
||||
#else
|
||||
LogError("Error returned from UDP select, err: %d", errno);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
return 0;
|
||||
|
||||
sockaddr_in addr;
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
int size = sizeof(sockaddr_in);
|
||||
#else
|
||||
socklen_t size = sizeof(sockaddr_in);
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
int len = ::recvfrom(m_fd, (char*)buffer, length, 0, (sockaddr *)&addr, &size);
|
||||
#else
|
||||
ssize_t len = ::recvfrom(m_fd, (char*)buffer, length, 0, (sockaddr *)&addr, &size);
|
||||
#endif
|
||||
if (len <= 0) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
LogError("Error returned from recvfrom, err: %lu", ::GetLastError());
|
||||
#else
|
||||
LogError("Error returned from recvfrom, err: %d", errno);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
address = addr.sin_addr;
|
||||
port = ntohs(addr.sin_port);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
bool CUDPSocket::write(const unsigned char* buffer, unsigned int length, const in_addr& address, unsigned int port)
|
||||
{
|
||||
assert(buffer != NULL);
|
||||
assert(length > 0U);
|
||||
|
||||
sockaddr_in addr;
|
||||
::memset(&addr, 0x00, sizeof(sockaddr_in));
|
||||
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr = address;
|
||||
addr.sin_port = htons(port);
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
int ret = ::sendto(m_fd, (char *)buffer, length, 0, (sockaddr *)&addr, sizeof(sockaddr_in));
|
||||
#else
|
||||
ssize_t ret = ::sendto(m_fd, (char *)buffer, length, 0, (sockaddr *)&addr, sizeof(sockaddr_in));
|
||||
#endif
|
||||
if (ret < 0) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
LogError("Error returned from sendto, err: %lu", ::GetLastError());
|
||||
#else
|
||||
LogError("Error returned from sendto, err: %d", errno);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
if (ret != int(length))
|
||||
return false;
|
||||
#else
|
||||
if (ret != ssize_t(length))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CUDPSocket::close()
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
::closesocket(m_fd);
|
||||
#else
|
||||
::close(m_fd);
|
||||
#endif
|
||||
}
|
58
NXDNGateway/UDPSocket.h
Normal file
58
NXDNGateway/UDPSocket.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2011,2013,2015,2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef UDPSocket_H
|
||||
#define UDPSocket_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
#include <netdb.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#else
|
||||
#include <winsock.h>
|
||||
#endif
|
||||
|
||||
class CUDPSocket {
|
||||
public:
|
||||
CUDPSocket(const std::string& address, unsigned int port = 0U);
|
||||
CUDPSocket(unsigned int port = 0U);
|
||||
~CUDPSocket();
|
||||
|
||||
bool open();
|
||||
|
||||
int read(unsigned char* buffer, unsigned int length, in_addr& address, unsigned int& port);
|
||||
bool write(const unsigned char* buffer, unsigned int length, const in_addr& address, unsigned int port);
|
||||
|
||||
void close();
|
||||
|
||||
static in_addr lookup(const std::string& hostName);
|
||||
|
||||
private:
|
||||
std::string m_address;
|
||||
unsigned short m_port;
|
||||
int m_fd;
|
||||
};
|
||||
|
||||
#endif
|
146
NXDNGateway/Utils.cpp
Normal file
146
NXDNGateway/Utils.cpp
Normal file
@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright (C) 2009,2014,2015,2016 Jonathan Naylor, G4KLX
|
||||
*
|
||||
* 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; version 2 of the License.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "Utils.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
|
||||
void CUtils::dump(const std::string& title, const unsigned char* data, unsigned int length)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
dump(2U, title, data, length);
|
||||
}
|
||||
|
||||
void CUtils::dump(int level, const std::string& title, const unsigned char* data, unsigned int length)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
::Log(level, "%s", title.c_str());
|
||||
|
||||
unsigned int offset = 0U;
|
||||
|
||||
while (length > 0U) {
|
||||
std::string output;
|
||||
|
||||
unsigned int bytes = (length > 16U) ? 16U : length;
|
||||
|
||||
for (unsigned i = 0U; i < bytes; i++) {
|
||||
char temp[10U];
|
||||
::sprintf(temp, "%02X ", data[offset + i]);
|
||||
output += temp;
|
||||
}
|
||||
|
||||
for (unsigned int i = bytes; i < 16U; i++)
|
||||
output += " ";
|
||||
|
||||
output += " *";
|
||||
|
||||
for (unsigned i = 0U; i < bytes; i++) {
|
||||
unsigned char c = data[offset + i];
|
||||
|
||||
if (::isprint(c))
|
||||
output += c;
|
||||
else
|
||||
output += '.';
|
||||
}
|
||||
|
||||
output += '*';
|
||||
|
||||
::Log(level, "%04X: %s", offset, output.c_str());
|
||||
|
||||
offset += 16U;
|
||||
|
||||
if (length >= 16U)
|
||||
length -= 16U;
|
||||
else
|
||||
length = 0U;
|
||||
}
|
||||
}
|
||||
|
||||
void CUtils::dump(const std::string& title, const bool* bits, unsigned int length)
|
||||
{
|
||||
assert(bits != NULL);
|
||||
|
||||
dump(2U, title, bits, length);
|
||||
}
|
||||
|
||||
void CUtils::dump(int level, const std::string& title, const bool* bits, unsigned int length)
|
||||
{
|
||||
assert(bits != NULL);
|
||||
|
||||
unsigned char bytes[100U];
|
||||
unsigned int nBytes = 0U;
|
||||
for (unsigned int n = 0U; n < length; n += 8U, nBytes++)
|
||||
bitsToByteBE(bits + n, bytes[nBytes]);
|
||||
|
||||
dump(level, title, bytes, nBytes);
|
||||
}
|
||||
|
||||
void CUtils::byteToBitsBE(unsigned char byte, bool* bits)
|
||||
{
|
||||
assert(bits != NULL);
|
||||
|
||||
bits[0U] = (byte & 0x80U) == 0x80U;
|
||||
bits[1U] = (byte & 0x40U) == 0x40U;
|
||||
bits[2U] = (byte & 0x20U) == 0x20U;
|
||||
bits[3U] = (byte & 0x10U) == 0x10U;
|
||||
bits[4U] = (byte & 0x08U) == 0x08U;
|
||||
bits[5U] = (byte & 0x04U) == 0x04U;
|
||||
bits[6U] = (byte & 0x02U) == 0x02U;
|
||||
bits[7U] = (byte & 0x01U) == 0x01U;
|
||||
}
|
||||
|
||||
void CUtils::byteToBitsLE(unsigned char byte, bool* bits)
|
||||
{
|
||||
assert(bits != NULL);
|
||||
|
||||
bits[0U] = (byte & 0x01U) == 0x01U;
|
||||
bits[1U] = (byte & 0x02U) == 0x02U;
|
||||
bits[2U] = (byte & 0x04U) == 0x04U;
|
||||
bits[3U] = (byte & 0x08U) == 0x08U;
|
||||
bits[4U] = (byte & 0x10U) == 0x10U;
|
||||
bits[5U] = (byte & 0x20U) == 0x20U;
|
||||
bits[6U] = (byte & 0x40U) == 0x40U;
|
||||
bits[7U] = (byte & 0x80U) == 0x80U;
|
||||
}
|
||||
|
||||
void CUtils::bitsToByteBE(const bool* bits, unsigned char& byte)
|
||||
{
|
||||
assert(bits != NULL);
|
||||
|
||||
byte = bits[0U] ? 0x80U : 0x00U;
|
||||
byte |= bits[1U] ? 0x40U : 0x00U;
|
||||
byte |= bits[2U] ? 0x20U : 0x00U;
|
||||
byte |= bits[3U] ? 0x10U : 0x00U;
|
||||
byte |= bits[4U] ? 0x08U : 0x00U;
|
||||
byte |= bits[5U] ? 0x04U : 0x00U;
|
||||
byte |= bits[6U] ? 0x02U : 0x00U;
|
||||
byte |= bits[7U] ? 0x01U : 0x00U;
|
||||
}
|
||||
|
||||
void CUtils::bitsToByteLE(const bool* bits, unsigned char& byte)
|
||||
{
|
||||
assert(bits != NULL);
|
||||
|
||||
byte = bits[0U] ? 0x01U : 0x00U;
|
||||
byte |= bits[1U] ? 0x02U : 0x00U;
|
||||
byte |= bits[2U] ? 0x04U : 0x00U;
|
||||
byte |= bits[3U] ? 0x08U : 0x00U;
|
||||
byte |= bits[4U] ? 0x10U : 0x00U;
|
||||
byte |= bits[5U] ? 0x20U : 0x00U;
|
||||
byte |= bits[6U] ? 0x40U : 0x00U;
|
||||
byte |= bits[7U] ? 0x80U : 0x00U;
|
||||
}
|
36
NXDNGateway/Utils.h
Normal file
36
NXDNGateway/Utils.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2009,2014,2015 by Jonathan Naylor, G4KLX
|
||||
*
|
||||
* 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; version 2 of the License.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef Utils_H
|
||||
#define Utils_H
|
||||
|
||||
#include <string>
|
||||
|
||||
class CUtils {
|
||||
public:
|
||||
static void dump(const std::string& title, const unsigned char* data, unsigned int length);
|
||||
static void dump(int level, const std::string& title, const unsigned char* data, unsigned int length);
|
||||
|
||||
static void dump(const std::string& title, const bool* bits, unsigned int length);
|
||||
static void dump(int level, const std::string& title, const bool* bits, unsigned int length);
|
||||
|
||||
static void byteToBitsBE(unsigned char byte, bool* bits);
|
||||
static void byteToBitsLE(unsigned char byte, bool* bits);
|
||||
|
||||
static void bitsToByteBE(const bool* bits, unsigned char& byte);
|
||||
static void bitsToByteLE(const bool* bits, unsigned char& byte);
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif
|
24
NXDNGateway/Version.h
Normal file
24
NXDNGateway/Version.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if !defined(VERSION_H)
|
||||
#define VERSION_H
|
||||
|
||||
const char* VERSION = "20170719";
|
||||
|
||||
#endif
|
343
NXDNGateway/Voice.cpp
Normal file
343
NXDNGateway/Voice.cpp
Normal file
@ -0,0 +1,343 @@
|
||||
/*
|
||||
* Copyright (C) 2017,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "NXDNCRC.h"
|
||||
#include "Voice.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
const unsigned char HEADER[] = { 0x83U, 0x01U, 0x10U, 0x00U, 0x0FU, 0x01U, 0x00U, 0x20U };
|
||||
const unsigned char TRAILER[] = { 0x83U, 0x01U, 0x10U, 0x00U, 0x0FU, 0x08U, 0x00U, 0x20U };
|
||||
|
||||
const unsigned char SILENCE[] = {0xACU, 0xAAU, 0x40U, 0x20U, 0x00U, 0x44U, 0x40U, 0x80U, 0x80U};
|
||||
|
||||
const unsigned char NXDN_FRAME_LENGTH = 33U;
|
||||
|
||||
const unsigned int NXDN_FRAME_TIME = 80U;
|
||||
|
||||
const unsigned int SILENCE_LENGTH = 9U;
|
||||
const unsigned int AMBE_LENGTH = 9U;
|
||||
|
||||
const unsigned char BIT_MASK_TABLE[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U };
|
||||
|
||||
#define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7])
|
||||
#define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7])
|
||||
|
||||
CVoice::CVoice(const std::string& directory, const std::string& language, unsigned int srcId) :
|
||||
m_indxFile(),
|
||||
m_ambeFile(),
|
||||
m_srcId(srcId),
|
||||
m_status(VS_NONE),
|
||||
m_timer(1000U, 1U),
|
||||
m_stopWatch(),
|
||||
m_sent(0U),
|
||||
m_ambe(NULL),
|
||||
m_positions(),
|
||||
m_voiceData(NULL),
|
||||
m_voiceLength(0U)
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
m_indxFile = directory + "\\" + language + ".indx";
|
||||
m_ambeFile = directory + "\\" + language + ".ambe";
|
||||
#else
|
||||
m_indxFile = directory + "/" + language + ".indx";
|
||||
m_ambeFile = directory + "/" + language + ".ambe";
|
||||
#endif
|
||||
|
||||
// Approximately 10 seconds worth
|
||||
m_voiceData = new unsigned char[120U * NXDN_FRAME_LENGTH];
|
||||
}
|
||||
|
||||
CVoice::~CVoice()
|
||||
{
|
||||
for (std::unordered_map<std::string, CPositions*>::iterator it = m_positions.begin(); it != m_positions.end(); ++it)
|
||||
delete it->second;
|
||||
|
||||
m_positions.clear();
|
||||
|
||||
delete[] m_ambe;
|
||||
delete[] m_voiceData;
|
||||
}
|
||||
|
||||
bool CVoice::open()
|
||||
{
|
||||
FILE* fpindx = ::fopen(m_indxFile.c_str(), "rt");
|
||||
if (fpindx == NULL) {
|
||||
LogError("Unable to open the index file - %s", m_indxFile.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
struct stat statStruct;
|
||||
int ret = ::stat(m_ambeFile.c_str(), &statStruct);
|
||||
if (ret != 0) {
|
||||
LogError("Unable to stat the AMBE file - %s", m_ambeFile.c_str());
|
||||
::fclose(fpindx);
|
||||
return false;
|
||||
}
|
||||
|
||||
FILE* fpambe = ::fopen(m_ambeFile.c_str(), "rb");
|
||||
if (fpambe == NULL) {
|
||||
LogError("Unable to open the AMBE file - %s", m_ambeFile.c_str());
|
||||
::fclose(fpindx);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_ambe = new unsigned char[statStruct.st_size];
|
||||
|
||||
size_t sizeRead = ::fread(m_ambe, 1U, statStruct.st_size, fpambe);
|
||||
if (sizeRead != 0U) {
|
||||
char buffer[80U];
|
||||
while (::fgets(buffer, 80, fpindx) != NULL) {
|
||||
char* p1 = ::strtok(buffer, "\t\r\n");
|
||||
char* p2 = ::strtok(NULL, "\t\r\n");
|
||||
char* p3 = ::strtok(NULL, "\t\r\n");
|
||||
|
||||
if (p1 != NULL && p2 != NULL && p3 != NULL) {
|
||||
std::string symbol = std::string(p1);
|
||||
unsigned int start = ::atoi(p2) * AMBE_LENGTH;
|
||||
unsigned int length = ::atoi(p3) * AMBE_LENGTH;
|
||||
|
||||
CPositions* pos = new CPositions;
|
||||
pos->m_start = start;
|
||||
pos->m_length = length;
|
||||
|
||||
m_positions[symbol] = pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
::fclose(fpindx);
|
||||
::fclose(fpambe);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CVoice::linkedTo(unsigned int tg)
|
||||
{
|
||||
char letters[10U];
|
||||
::sprintf(letters, "%u", tg);
|
||||
|
||||
std::vector<std::string> words;
|
||||
if (m_positions.count("linkedto") == 0U) {
|
||||
words.push_back("linked");
|
||||
words.push_back("2");
|
||||
} else {
|
||||
words.push_back("linkedto");
|
||||
}
|
||||
|
||||
for (unsigned int i = 0U; letters[i] != 0x00U; i++)
|
||||
words.push_back(std::string(1U, letters[i]));
|
||||
|
||||
createVoice(tg, words);
|
||||
}
|
||||
|
||||
void CVoice::unlinked()
|
||||
{
|
||||
std::vector<std::string> words;
|
||||
words.push_back("notlinked");
|
||||
|
||||
createVoice(9999U, words);
|
||||
}
|
||||
|
||||
void CVoice::createVoice(unsigned int tg, const std::vector<std::string>& words)
|
||||
{
|
||||
unsigned int ambeLength = 0U;
|
||||
for (std::vector<std::string>::const_iterator it = words.begin(); it != words.end(); ++it) {
|
||||
if (m_positions.count(*it) > 0U) {
|
||||
CPositions* position = m_positions.at(*it);
|
||||
ambeLength += position->m_length;
|
||||
} else {
|
||||
LogWarning("Unable to find character/phrase \"%s\" in the index", (*it).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the AMBE is an integer number of DMR frames
|
||||
if ((ambeLength % (4U * AMBE_LENGTH)) != 0U) {
|
||||
unsigned int frames = ambeLength / (4U * AMBE_LENGTH);
|
||||
frames++;
|
||||
ambeLength = frames * (4U * AMBE_LENGTH);
|
||||
}
|
||||
|
||||
// Add space for silence before and after the voice
|
||||
ambeLength += SILENCE_LENGTH * AMBE_LENGTH;
|
||||
ambeLength += SILENCE_LENGTH * AMBE_LENGTH;
|
||||
|
||||
unsigned char* ambeData = new unsigned char[ambeLength];
|
||||
|
||||
// Fill the AMBE data with silence
|
||||
for (unsigned int i = 0U; i < ambeLength; i += AMBE_LENGTH)
|
||||
::memcpy(ambeData + i, SILENCE, AMBE_LENGTH);
|
||||
|
||||
// Put offset in for silence at the beginning
|
||||
unsigned int pos = SILENCE_LENGTH * AMBE_LENGTH;
|
||||
for (std::vector<std::string>::const_iterator it = words.begin(); it != words.end(); ++it) {
|
||||
if (m_positions.count(*it) > 0U) {
|
||||
CPositions* position = m_positions.at(*it);
|
||||
unsigned int start = position->m_start;
|
||||
unsigned int length = position->m_length;
|
||||
::memcpy(ambeData + pos, m_ambe + start, length);
|
||||
pos += length;
|
||||
}
|
||||
}
|
||||
|
||||
m_voiceLength = 0U;
|
||||
|
||||
createHeader(true, tg);
|
||||
|
||||
unsigned char sacch[12U];
|
||||
::memset(sacch, 0x00U, 12U);
|
||||
|
||||
sacch[2U] = 0x20U;
|
||||
|
||||
sacch[3U] = (m_srcId >> 8) & 0xFFU;
|
||||
sacch[4U] = (m_srcId >> 0) & 0xFFU;
|
||||
|
||||
sacch[5U] = (tg >> 8) & 0xFFU;
|
||||
sacch[6U] = (tg >> 0) & 0xFFU;
|
||||
|
||||
unsigned int n = 0U;
|
||||
for (unsigned int i = 0U; i < ambeLength; i += (4U * AMBE_LENGTH)) {
|
||||
unsigned char* p = ambeData + i;
|
||||
|
||||
unsigned char buffer[NXDN_FRAME_LENGTH];
|
||||
::memset(buffer, 0x00U, NXDN_FRAME_LENGTH);
|
||||
|
||||
buffer[0U] = 0xAEU;
|
||||
|
||||
switch (n) {
|
||||
case 0U: buffer[1U] = 0xC1U; break;
|
||||
case 1U: buffer[1U] = 0x81U; break;
|
||||
case 2U: buffer[1U] = 0x41U; break;
|
||||
default: buffer[1U] = 0x01U; break;
|
||||
}
|
||||
|
||||
for (unsigned int j = 0U; j < 18U; j++) {
|
||||
bool b = READ_BIT1(sacch, j + n * 18U);
|
||||
WRITE_BIT1(buffer, j + 16U, b);
|
||||
}
|
||||
|
||||
CNXDNCRC::encodeCRC6(buffer + 1U, 26U);
|
||||
|
||||
::memcpy(buffer + 5U + 0U, p + 0U, 13U);
|
||||
::memcpy(buffer + 5U + 14U, p + 13U, 13U);
|
||||
|
||||
n = (n + 1U) % 4U;
|
||||
|
||||
::memcpy(m_voiceData + m_voiceLength, buffer, NXDN_FRAME_LENGTH);
|
||||
m_voiceLength += NXDN_FRAME_LENGTH;
|
||||
}
|
||||
|
||||
createTrailer(true, tg);
|
||||
|
||||
delete[] ambeData;
|
||||
|
||||
m_status = VS_WAITING;
|
||||
m_timer.start();
|
||||
}
|
||||
|
||||
bool CVoice::read(unsigned char* data)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
if (m_status != VS_SENDING)
|
||||
return false;
|
||||
|
||||
unsigned int count = m_stopWatch.elapsed() / NXDN_FRAME_TIME;
|
||||
|
||||
if (m_sent < count) {
|
||||
unsigned int offset = m_sent * NXDN_FRAME_LENGTH;
|
||||
::memcpy(data, m_voiceData + offset, NXDN_FRAME_LENGTH);
|
||||
m_sent++;
|
||||
|
||||
if (offset >= m_voiceLength) {
|
||||
m_timer.stop();
|
||||
m_voiceLength = 0U;
|
||||
m_status = VS_NONE;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CVoice::clock(unsigned int ms)
|
||||
{
|
||||
m_timer.clock(ms);
|
||||
if (m_timer.isRunning() && m_timer.hasExpired()) {
|
||||
if (m_status == VS_WAITING) {
|
||||
m_stopWatch.start();
|
||||
m_status = VS_SENDING;
|
||||
m_sent = 0U;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CVoice::createHeader(bool grp, unsigned int dstId)
|
||||
{
|
||||
unsigned char buffer[NXDN_FRAME_LENGTH];
|
||||
|
||||
::memset(buffer, 0x00U, NXDN_FRAME_LENGTH);
|
||||
::memcpy(buffer, HEADER, 8U);
|
||||
|
||||
if (grp)
|
||||
buffer[7U] = 0x20U;
|
||||
|
||||
buffer[8U] = (m_srcId >> 8) & 0xFFU;
|
||||
buffer[9U] = (m_srcId >> 0) & 0xFFU;
|
||||
|
||||
buffer[10U] = (dstId >> 8) & 0xFFU;
|
||||
buffer[11U] = (dstId >> 0) & 0xFFU;
|
||||
|
||||
CNXDNCRC::encodeCRC12(buffer + 5U, 80U);
|
||||
|
||||
::memcpy(buffer + 19U, buffer + 5U, 12U);
|
||||
|
||||
::memcpy(m_voiceData + m_voiceLength, buffer, NXDN_FRAME_LENGTH);
|
||||
m_voiceLength += NXDN_FRAME_LENGTH;
|
||||
}
|
||||
|
||||
void CVoice::createTrailer(bool grp, unsigned int dstId)
|
||||
{
|
||||
unsigned char buffer[NXDN_FRAME_LENGTH];
|
||||
|
||||
::memset(buffer, 0x00U, NXDN_FRAME_LENGTH);
|
||||
::memcpy(buffer, TRAILER, 8U);
|
||||
|
||||
if (grp)
|
||||
buffer[7U] = 0x20U;
|
||||
|
||||
buffer[8U] = (m_srcId >> 8) & 0xFFU;
|
||||
buffer[9U] = (m_srcId >> 0) & 0xFFU;
|
||||
|
||||
buffer[10U] = (dstId >> 8) & 0xFFU;
|
||||
buffer[11U] = (dstId >> 0) & 0xFFU;
|
||||
|
||||
CNXDNCRC::encodeCRC12(buffer + 5U, 80U);
|
||||
|
||||
::memcpy(buffer + 19U, buffer + 5U, 12U);
|
||||
|
||||
::memcpy(m_voiceData + m_voiceLength, buffer, NXDN_FRAME_LENGTH);
|
||||
m_voiceLength += NXDN_FRAME_LENGTH;
|
||||
}
|
72
NXDNGateway/Voice.h
Normal file
72
NXDNGateway/Voice.h
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2017 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if !defined(Voice_H)
|
||||
#define Voice_H
|
||||
|
||||
#include "StopWatch.h"
|
||||
#include "Timer.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
enum VOICE_STATUS {
|
||||
VS_NONE,
|
||||
VS_WAITING,
|
||||
VS_SENDING
|
||||
};
|
||||
|
||||
struct CPositions {
|
||||
unsigned int m_start;
|
||||
unsigned int m_length;
|
||||
};
|
||||
|
||||
class CVoice {
|
||||
public:
|
||||
CVoice(const std::string& directory, const std::string& language, unsigned int srcId);
|
||||
~CVoice();
|
||||
|
||||
bool open();
|
||||
|
||||
void linkedTo(unsigned int tg);
|
||||
void unlinked();
|
||||
|
||||
bool read(unsigned char* data);
|
||||
|
||||
void clock(unsigned int ms);
|
||||
|
||||
private:
|
||||
std::string m_indxFile;
|
||||
std::string m_ambeFile;
|
||||
unsigned int m_srcId;
|
||||
VOICE_STATUS m_status;
|
||||
CTimer m_timer;
|
||||
CStopWatch m_stopWatch;
|
||||
unsigned int m_sent;
|
||||
unsigned char* m_ambe;
|
||||
unsigned char* m_voiceData;
|
||||
unsigned int m_voiceLength;
|
||||
std::unordered_map<std::string, CPositions*> m_positions;
|
||||
|
||||
void createHeader(bool grp, unsigned int dstId);
|
||||
void createTrailer(bool grp, unsigned int dstId);
|
||||
void createVoice(unsigned int tg, const std::vector<std::string>& words);
|
||||
};
|
||||
|
||||
#endif
|
18
NXDNParrot/Makefile
Normal file
18
NXDNParrot/Makefile
Normal file
@ -0,0 +1,18 @@
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
CFLAGS = -g -O3 -Wall -std=c++0x -pthread
|
||||
LIBS = -lpthread
|
||||
LDFLAGS = -g
|
||||
|
||||
OBJECTS = Network.o NXDNParrot.o Parrot.o StopWatch.o Thread.o Timer.o UDPSocket.o
|
||||
|
||||
all: NXDNParrot
|
||||
|
||||
NXDNParrot: $(OBJECTS)
|
||||
$(CXX) $(OBJECTS) $(CFLAGS) $(LIBS) -o NXDNParrot
|
||||
|
||||
%.o: %.cpp
|
||||
$(CXX) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
$(RM) NXDNParrot *.o *.d *.bak *~
|
138
NXDNParrot/NXDNParrot.cpp
Normal file
138
NXDNParrot/NXDNParrot.cpp
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright (C) 2016,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "StopWatch.h"
|
||||
#include "NXDNParrot.h"
|
||||
#include "Parrot.h"
|
||||
#include "Network.h"
|
||||
#include "Version.h"
|
||||
#include "Thread.h"
|
||||
#include "Timer.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
if (argc == 1) {
|
||||
::fprintf(stderr, "Usage: NXDNParrot <port>\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned int port = ::atoi(argv[1U]);
|
||||
if (port == 0U) {
|
||||
::fprintf(stderr, "NXDNParrot: invalid port number - %s\n", argv[1U]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
CNXDNParrot parrot(port);
|
||||
parrot.run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CNXDNParrot::CNXDNParrot(unsigned int port) :
|
||||
m_port(port)
|
||||
{
|
||||
}
|
||||
|
||||
CNXDNParrot::~CNXDNParrot()
|
||||
{
|
||||
}
|
||||
|
||||
void CNXDNParrot::run()
|
||||
{
|
||||
CParrot parrot(180U);
|
||||
CNetwork network(m_port);
|
||||
|
||||
bool ret = network.open();
|
||||
if (!ret)
|
||||
return;
|
||||
|
||||
CStopWatch stopWatch;
|
||||
stopWatch.start();
|
||||
|
||||
CTimer watchdogTimer(1000U, 0U, 1500U);
|
||||
CTimer turnaroundTimer(1000U, 2U);
|
||||
|
||||
CStopWatch playoutTimer;
|
||||
unsigned int count = 0U;
|
||||
bool playing = false;
|
||||
|
||||
::fprintf(stdout, "Starting NXDNParrot-%s\n", VERSION);
|
||||
|
||||
for (;;) {
|
||||
unsigned char buffer[200U];
|
||||
|
||||
unsigned int len = network.read(buffer);
|
||||
if (len > 0U) {
|
||||
parrot.write(buffer, len);
|
||||
watchdogTimer.start();
|
||||
|
||||
if ((buffer[9U] & 0x04U) == 0x04U) {
|
||||
::fprintf(stdout, "Received end of transmission\n");
|
||||
turnaroundTimer.start();
|
||||
watchdogTimer.stop();
|
||||
parrot.end();
|
||||
}
|
||||
}
|
||||
|
||||
if (turnaroundTimer.isRunning() && turnaroundTimer.hasExpired()) {
|
||||
if (!playing) {
|
||||
playoutTimer.start();
|
||||
playing = true;
|
||||
count = 0U;
|
||||
}
|
||||
|
||||
// A frame every 80ms
|
||||
unsigned int wanted = playoutTimer.elapsed() / 80U;
|
||||
while (count < wanted) {
|
||||
len = parrot.read(buffer);
|
||||
if (len > 0U) {
|
||||
network.write(buffer, len);
|
||||
count++;
|
||||
} else {
|
||||
parrot.clear();
|
||||
network.end();
|
||||
turnaroundTimer.stop();
|
||||
playing = false;
|
||||
count = wanted;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int ms = stopWatch.elapsed();
|
||||
stopWatch.start();
|
||||
|
||||
network.clock(ms);
|
||||
watchdogTimer.clock(ms);
|
||||
turnaroundTimer.clock(ms);
|
||||
|
||||
if (watchdogTimer.isRunning() && watchdogTimer.hasExpired()) {
|
||||
turnaroundTimer.start();
|
||||
watchdogTimer.stop();
|
||||
parrot.end();
|
||||
}
|
||||
|
||||
if (ms < 5U)
|
||||
CThread::sleep(5U);
|
||||
}
|
||||
|
||||
network.close();
|
||||
}
|
34
NXDNParrot/NXDNParrot.h
Normal file
34
NXDNParrot/NXDNParrot.h
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2016,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if !defined(NXDNParrot_H)
|
||||
#define NXDNParrot_H
|
||||
|
||||
class CNXDNParrot
|
||||
{
|
||||
public:
|
||||
CNXDNParrot(unsigned int port);
|
||||
~CNXDNParrot();
|
||||
|
||||
void run();
|
||||
|
||||
private:
|
||||
unsigned int m_port;
|
||||
};
|
||||
|
||||
#endif
|
171
NXDNParrot/NXDNParrot.vcxproj
Normal file
171
NXDNParrot/NXDNParrot.vcxproj
Normal file
@ -0,0 +1,171 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{2AE94EAA-FD57-45C9-8555-6425CFA777A3}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>NXDNParrot</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Network.h" />
|
||||
<ClInclude Include="NXDNParrot.h" />
|
||||
<ClInclude Include="Parrot.h" />
|
||||
<ClInclude Include="RingBuffer.h" />
|
||||
<ClInclude Include="StopWatch.h" />
|
||||
<ClInclude Include="Thread.h" />
|
||||
<ClInclude Include="Timer.h" />
|
||||
<ClInclude Include="UDPSocket.h" />
|
||||
<ClInclude Include="Version.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Network.cpp" />
|
||||
<ClCompile Include="NXDNParrot.cpp" />
|
||||
<ClCompile Include="Parrot.cpp" />
|
||||
<ClCompile Include="StopWatch.cpp" />
|
||||
<ClCompile Include="Thread.cpp" />
|
||||
<ClCompile Include="Timer.cpp" />
|
||||
<ClCompile Include="UDPSocket.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
65
NXDNParrot/NXDNParrot.vcxproj.filters
Normal file
65
NXDNParrot/NXDNParrot.vcxproj.filters
Normal file
@ -0,0 +1,65 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Network.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NXDNParrot.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Parrot.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="RingBuffer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="StopWatch.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Timer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="UDPSocket.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Version.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Thread.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Network.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="NXDNParrot.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Parrot.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="StopWatch.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Timer.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="UDPSocket.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Thread.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
103
NXDNParrot/Network.cpp
Normal file
103
NXDNParrot/Network.cpp
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2014,2016,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "Network.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
const unsigned int BUFFER_LENGTH = 200U;
|
||||
|
||||
CNetwork::CNetwork(unsigned int port) :
|
||||
m_socket(port),
|
||||
m_address(),
|
||||
m_port(0U),
|
||||
m_buffer(1000U, "NXDN Network")
|
||||
{
|
||||
}
|
||||
|
||||
CNetwork::~CNetwork()
|
||||
{
|
||||
}
|
||||
|
||||
bool CNetwork::open()
|
||||
{
|
||||
::fprintf(stdout, "Opening NXDN network connection\n");
|
||||
|
||||
return m_socket.open();
|
||||
}
|
||||
|
||||
bool CNetwork::write(const unsigned char* data, unsigned int length)
|
||||
{
|
||||
if (m_port == 0U)
|
||||
return true;
|
||||
|
||||
assert(data != NULL);
|
||||
|
||||
return m_socket.write(data, length, m_address, m_port);
|
||||
}
|
||||
|
||||
void CNetwork::clock(unsigned int ms)
|
||||
{
|
||||
unsigned char buffer[BUFFER_LENGTH];
|
||||
|
||||
in_addr address;
|
||||
unsigned int port;
|
||||
int length = m_socket.read(buffer, BUFFER_LENGTH, address, port);
|
||||
if (length <= 0)
|
||||
return;
|
||||
|
||||
m_address.s_addr = address.s_addr;
|
||||
m_port = port;
|
||||
|
||||
if (::memcmp(buffer, "NXDNP", 5U) == 0) { // A poll
|
||||
write(buffer, length);
|
||||
} else if (::memcmp(buffer, "NXDND", 5U) == 0) {
|
||||
unsigned char l = length;
|
||||
m_buffer.addData(&l, 1U);
|
||||
m_buffer.addData(buffer, length);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int CNetwork::read(unsigned char* data)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
if (m_buffer.isEmpty())
|
||||
return 0U;
|
||||
|
||||
unsigned char len = 0U;
|
||||
m_buffer.getData(&len, 1U);
|
||||
|
||||
m_buffer.getData(data, len);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
void CNetwork::end()
|
||||
{
|
||||
m_port = 0U;
|
||||
}
|
||||
|
||||
void CNetwork::close()
|
||||
{
|
||||
m_socket.close();
|
||||
|
||||
::fprintf(stdout, "Closing NXDN network connection\n");
|
||||
}
|
52
NXDNParrot/Network.h
Normal file
52
NXDNParrot/Network.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2014,2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef Network_H
|
||||
#define Network_H
|
||||
|
||||
#include "RingBuffer.h"
|
||||
#include "UDPSocket.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
class CNetwork {
|
||||
public:
|
||||
CNetwork(unsigned int port);
|
||||
~CNetwork();
|
||||
|
||||
bool open();
|
||||
|
||||
bool write(const unsigned char* data, unsigned int length);
|
||||
|
||||
unsigned int read(unsigned char* data);
|
||||
|
||||
void end();
|
||||
|
||||
void close();
|
||||
|
||||
void clock(unsigned int ms);
|
||||
|
||||
private:
|
||||
CUDPSocket m_socket;
|
||||
in_addr m_address;
|
||||
unsigned int m_port;
|
||||
CRingBuffer<unsigned char> m_buffer;
|
||||
};
|
||||
|
||||
#endif
|
81
NXDNParrot/Parrot.cpp
Normal file
81
NXDNParrot/Parrot.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "Parrot.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
CParrot::CParrot(unsigned int timeout) :
|
||||
m_data(NULL),
|
||||
m_length(timeout * 1000U + 1000U),
|
||||
m_used(0U),
|
||||
m_ptr(0U)
|
||||
{
|
||||
assert(timeout > 0U);
|
||||
|
||||
m_data = new unsigned char[m_length];
|
||||
}
|
||||
|
||||
CParrot::~CParrot()
|
||||
{
|
||||
delete[] m_data;
|
||||
}
|
||||
|
||||
bool CParrot::write(const unsigned char* data, unsigned int length)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
if ((m_length - m_used) < (length + 2U))
|
||||
return false;
|
||||
|
||||
m_data[m_used] = length;
|
||||
::memcpy(m_data + m_used + 1U, data, length);
|
||||
m_used += length + 1U;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CParrot::end()
|
||||
{
|
||||
m_ptr = 0U;
|
||||
}
|
||||
|
||||
void CParrot::clear()
|
||||
{
|
||||
m_used = 0U;
|
||||
m_ptr = 0U;
|
||||
}
|
||||
|
||||
unsigned int CParrot::read(unsigned char* data)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
if (m_used == 0U)
|
||||
return 0U;
|
||||
|
||||
unsigned int length = m_data[m_ptr];
|
||||
::memcpy(data, m_data + m_ptr + 1U, length);
|
||||
m_ptr += length + 1U;
|
||||
|
||||
if (m_ptr >= m_used)
|
||||
m_used = 0U;
|
||||
|
||||
return length;
|
||||
}
|
43
NXDNParrot/Parrot.h
Normal file
43
NXDNParrot/Parrot.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) 2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if !defined(Parrot_H)
|
||||
#define Parrot_H
|
||||
|
||||
class CParrot
|
||||
{
|
||||
public:
|
||||
CParrot(unsigned int timeout);
|
||||
~CParrot();
|
||||
|
||||
bool write(const unsigned char* data, unsigned int length);
|
||||
|
||||
unsigned int read(unsigned char* data);
|
||||
|
||||
void end();
|
||||
|
||||
void clear();
|
||||
|
||||
private:
|
||||
unsigned char* m_data;
|
||||
unsigned int m_length;
|
||||
unsigned int m_used;
|
||||
unsigned int m_ptr;
|
||||
};
|
||||
|
||||
#endif
|
147
NXDNParrot/RingBuffer.h
Normal file
147
NXDNParrot/RingBuffer.h
Normal file
@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright (C) 2006-2009,2012,2013,2015,2016,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef RingBuffer_H
|
||||
#define RingBuffer_H
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
template<class T> class CRingBuffer {
|
||||
public:
|
||||
CRingBuffer(unsigned int length, const char* name) :
|
||||
m_length(length),
|
||||
m_name(name),
|
||||
m_buffer(NULL),
|
||||
m_iPtr(0U),
|
||||
m_oPtr(0U)
|
||||
{
|
||||
assert(length > 0U);
|
||||
assert(name != NULL);
|
||||
|
||||
m_buffer = new T[length];
|
||||
|
||||
::memset(m_buffer, 0x00, m_length * sizeof(T));
|
||||
}
|
||||
|
||||
~CRingBuffer()
|
||||
{
|
||||
delete[] m_buffer;
|
||||
}
|
||||
|
||||
bool addData(const T* buffer, unsigned int nSamples)
|
||||
{
|
||||
if (nSamples >= freeSpace()) {
|
||||
::fprintf(stderr, "**** Overflow in %s ring buffer, %u >= %u\n", m_name, nSamples, freeSpace());
|
||||
return false;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0U; i < nSamples; i++) {
|
||||
m_buffer[m_iPtr++] = buffer[i];
|
||||
|
||||
if (m_iPtr == m_length)
|
||||
m_iPtr = 0U;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool getData(T* buffer, unsigned int nSamples)
|
||||
{
|
||||
if (dataSize() < nSamples) {
|
||||
::fprintf(stderr, "**** Underflow in %s ring buffer, %u < %u\n", m_name, dataSize(), nSamples);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0U; i < nSamples; i++) {
|
||||
buffer[i] = m_buffer[m_oPtr++];
|
||||
|
||||
if (m_oPtr == m_length)
|
||||
m_oPtr = 0U;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool peek(T* buffer, unsigned int nSamples)
|
||||
{
|
||||
if (dataSize() < nSamples) {
|
||||
::fprintf(stderr, "**** Underflow peek in %s ring buffer, %u < %u\n", m_name, dataSize(), nSamples);
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int ptr = m_oPtr;
|
||||
for (unsigned int i = 0U; i < nSamples; i++) {
|
||||
buffer[i] = m_buffer[ptr++];
|
||||
|
||||
if (ptr == m_length)
|
||||
ptr = 0U;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_iPtr = 0U;
|
||||
m_oPtr = 0U;
|
||||
|
||||
::memset(m_buffer, 0x00, m_length * sizeof(T));
|
||||
}
|
||||
|
||||
unsigned int freeSpace() const
|
||||
{
|
||||
if (m_oPtr == m_iPtr)
|
||||
return m_length;
|
||||
|
||||
if (m_oPtr > m_iPtr)
|
||||
return m_oPtr - m_iPtr;
|
||||
|
||||
return (m_length + m_oPtr) - m_iPtr;
|
||||
}
|
||||
|
||||
unsigned int dataSize() const
|
||||
{
|
||||
return m_length - freeSpace();
|
||||
}
|
||||
|
||||
bool hasSpace(unsigned int length) const
|
||||
{
|
||||
return freeSpace() > length;
|
||||
}
|
||||
|
||||
bool hasData() const
|
||||
{
|
||||
return m_oPtr != m_iPtr;
|
||||
}
|
||||
|
||||
bool isEmpty() const
|
||||
{
|
||||
return m_oPtr == m_iPtr;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned int m_length;
|
||||
const char* m_name;
|
||||
T* m_buffer;
|
||||
unsigned int m_iPtr;
|
||||
unsigned int m_oPtr;
|
||||
};
|
||||
|
||||
#endif
|
84
NXDNParrot/StopWatch.cpp
Normal file
84
NXDNParrot/StopWatch.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "StopWatch.h"
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
|
||||
CStopWatch::CStopWatch() :
|
||||
m_frequency(),
|
||||
m_start()
|
||||
{
|
||||
::QueryPerformanceFrequency(&m_frequency);
|
||||
}
|
||||
|
||||
CStopWatch::~CStopWatch()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned long CStopWatch::start()
|
||||
{
|
||||
::QueryPerformanceCounter(&m_start);
|
||||
|
||||
return (unsigned long)(m_start.QuadPart / m_frequency.QuadPart);
|
||||
}
|
||||
|
||||
unsigned int CStopWatch::elapsed()
|
||||
{
|
||||
LARGE_INTEGER now;
|
||||
::QueryPerformanceCounter(&now);
|
||||
|
||||
LARGE_INTEGER temp;
|
||||
temp.QuadPart = (now.QuadPart - m_start.QuadPart) * 1000;
|
||||
|
||||
return (unsigned int)(temp.QuadPart / m_frequency.QuadPart);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
CStopWatch::CStopWatch() :
|
||||
m_start()
|
||||
{
|
||||
}
|
||||
|
||||
CStopWatch::~CStopWatch()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned long CStopWatch::start()
|
||||
{
|
||||
::gettimeofday(&m_start, NULL);
|
||||
|
||||
return m_start.tv_usec;
|
||||
}
|
||||
|
||||
unsigned int CStopWatch::elapsed()
|
||||
{
|
||||
struct timeval now;
|
||||
::gettimeofday(&now, NULL);
|
||||
|
||||
unsigned int elapsed = (now.tv_sec - m_start.tv_sec) * 1000U;
|
||||
elapsed += now.tv_usec / 1000U;
|
||||
elapsed -= m_start.tv_usec / 1000U;
|
||||
|
||||
return elapsed;
|
||||
}
|
||||
|
||||
#endif
|
46
NXDNParrot/StopWatch.h
Normal file
46
NXDNParrot/StopWatch.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if !defined(STOPWATCH_H)
|
||||
#define STOPWATCH_H
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
class CStopWatch
|
||||
{
|
||||
public:
|
||||
CStopWatch();
|
||||
~CStopWatch();
|
||||
|
||||
unsigned long start();
|
||||
unsigned int elapsed();
|
||||
|
||||
private:
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
LARGE_INTEGER m_frequency;
|
||||
LARGE_INTEGER m_start;
|
||||
#else
|
||||
struct timeval m_start;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
101
NXDNParrot/Thread.cpp
Normal file
101
NXDNParrot/Thread.cpp
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "Thread.h"
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
|
||||
CThread::CThread() :
|
||||
m_handle()
|
||||
{
|
||||
}
|
||||
|
||||
CThread::~CThread()
|
||||
{
|
||||
}
|
||||
|
||||
bool CThread::run()
|
||||
{
|
||||
m_handle = ::CreateThread(NULL, 0, &helper, this, 0, NULL);
|
||||
|
||||
return m_handle != NULL;
|
||||
}
|
||||
|
||||
|
||||
void CThread::wait()
|
||||
{
|
||||
::WaitForSingleObject(m_handle, INFINITE);
|
||||
|
||||
::CloseHandle(m_handle);
|
||||
}
|
||||
|
||||
|
||||
DWORD CThread::helper(LPVOID arg)
|
||||
{
|
||||
CThread* p = (CThread*)arg;
|
||||
|
||||
p->entry();
|
||||
|
||||
return 0UL;
|
||||
}
|
||||
|
||||
void CThread::sleep(unsigned int ms)
|
||||
{
|
||||
::Sleep(ms);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
CThread::CThread() :
|
||||
m_thread()
|
||||
{
|
||||
}
|
||||
|
||||
CThread::~CThread()
|
||||
{
|
||||
}
|
||||
|
||||
bool CThread::run()
|
||||
{
|
||||
return ::pthread_create(&m_thread, NULL, helper, this) == 0;
|
||||
}
|
||||
|
||||
|
||||
void CThread::wait()
|
||||
{
|
||||
::pthread_join(m_thread, NULL);
|
||||
}
|
||||
|
||||
|
||||
void* CThread::helper(void* arg)
|
||||
{
|
||||
CThread* p = (CThread*)arg;
|
||||
|
||||
p->entry();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CThread::sleep(unsigned int ms)
|
||||
{
|
||||
::usleep(ms * 1000);
|
||||
}
|
||||
|
||||
#endif
|
56
NXDNParrot/Thread.h
Normal file
56
NXDNParrot/Thread.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if !defined(THREAD_H)
|
||||
#define THREAD_H
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
class CThread
|
||||
{
|
||||
public:
|
||||
CThread();
|
||||
virtual ~CThread();
|
||||
|
||||
virtual bool run();
|
||||
|
||||
virtual void entry() = 0;
|
||||
|
||||
virtual void wait();
|
||||
|
||||
static void sleep(unsigned int ms);
|
||||
|
||||
private:
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
HANDLE m_handle;
|
||||
#else
|
||||
pthread_t m_thread;
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
static DWORD __stdcall helper(LPVOID arg);
|
||||
#else
|
||||
static void* helper(void* arg);
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
68
NXDNParrot/Timer.cpp
Normal file
68
NXDNParrot/Timer.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (C) 2009,2010,2015 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "Timer.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
|
||||
CTimer::CTimer(unsigned int ticksPerSec, unsigned int secs, unsigned int msecs) :
|
||||
m_ticksPerSec(ticksPerSec),
|
||||
m_timeout(0U),
|
||||
m_timer(0U)
|
||||
{
|
||||
assert(ticksPerSec > 0U);
|
||||
|
||||
if (secs > 0U || msecs > 0U) {
|
||||
// m_timeout = ((secs * 1000U + msecs) * m_ticksPerSec) / 1000U + 1U;
|
||||
unsigned long long temp = (secs * 1000ULL + msecs) * m_ticksPerSec;
|
||||
m_timeout = (unsigned int)(temp / 1000ULL + 1ULL);
|
||||
}
|
||||
}
|
||||
|
||||
CTimer::~CTimer()
|
||||
{
|
||||
}
|
||||
|
||||
void CTimer::setTimeout(unsigned int secs, unsigned int msecs)
|
||||
{
|
||||
if (secs > 0U || msecs > 0U) {
|
||||
// m_timeout = ((secs * 1000U + msecs) * m_ticksPerSec) / 1000U + 1U;
|
||||
unsigned long long temp = (secs * 1000ULL + msecs) * m_ticksPerSec;
|
||||
m_timeout = (unsigned int)(temp / 1000ULL + 1ULL);
|
||||
} else {
|
||||
m_timeout = 0U;
|
||||
m_timer = 0U;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int CTimer::getTimeout() const
|
||||
{
|
||||
if (m_timeout == 0U)
|
||||
return 0U;
|
||||
|
||||
return (m_timeout - 1U) / m_ticksPerSec;
|
||||
}
|
||||
|
||||
unsigned int CTimer::getTimer() const
|
||||
{
|
||||
if (m_timer == 0U)
|
||||
return 0U;
|
||||
|
||||
return (m_timer - 1U) / m_ticksPerSec;
|
||||
}
|
89
NXDNParrot/Timer.h
Normal file
89
NXDNParrot/Timer.h
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (C) 2009,2010,2011,2014 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef Timer_H
|
||||
#define Timer_H
|
||||
|
||||
class CTimer {
|
||||
public:
|
||||
CTimer(unsigned int ticksPerSec, unsigned int secs = 0U, unsigned int msecs = 0U);
|
||||
~CTimer();
|
||||
|
||||
void setTimeout(unsigned int secs, unsigned int msecs = 0U);
|
||||
|
||||
unsigned int getTimeout() const;
|
||||
unsigned int getTimer() const;
|
||||
|
||||
unsigned int getRemaining()
|
||||
{
|
||||
if (m_timeout == 0U || m_timer == 0U)
|
||||
return 0U;
|
||||
|
||||
if (m_timer >= m_timeout)
|
||||
return 0U;
|
||||
|
||||
return (m_timeout - m_timer) / m_ticksPerSec;
|
||||
}
|
||||
|
||||
bool isRunning()
|
||||
{
|
||||
return m_timer > 0U;
|
||||
}
|
||||
|
||||
void start(unsigned int secs, unsigned int msecs = 0U)
|
||||
{
|
||||
setTimeout(secs, msecs);
|
||||
|
||||
start();
|
||||
}
|
||||
|
||||
void start()
|
||||
{
|
||||
if (m_timeout > 0U)
|
||||
m_timer = 1U;
|
||||
}
|
||||
|
||||
void stop()
|
||||
{
|
||||
m_timer = 0U;
|
||||
}
|
||||
|
||||
bool hasExpired()
|
||||
{
|
||||
if (m_timeout == 0U || m_timer == 0U)
|
||||
return false;
|
||||
|
||||
if (m_timer >= m_timeout)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void clock(unsigned int ticks = 1U)
|
||||
{
|
||||
if (m_timer > 0U && m_timeout > 0U)
|
||||
m_timer += ticks;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned int m_ticksPerSec;
|
||||
unsigned int m_timeout;
|
||||
unsigned int m_timer;
|
||||
};
|
||||
|
||||
#endif
|
263
NXDNParrot/UDPSocket.cpp
Normal file
263
NXDNParrot/UDPSocket.cpp
Normal file
@ -0,0 +1,263 @@
|
||||
/*
|
||||
* Copyright (C) 2006-2016,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "UDPSocket.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
#endif
|
||||
|
||||
|
||||
CUDPSocket::CUDPSocket(const std::string& address, unsigned int port) :
|
||||
m_address(address),
|
||||
m_port(port),
|
||||
m_fd(-1)
|
||||
{
|
||||
assert(!address.empty());
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
WSAData data;
|
||||
int wsaRet = ::WSAStartup(MAKEWORD(2, 2), &data);
|
||||
if (wsaRet != 0)
|
||||
::fprintf(stderr, "Error from WSAStartup\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
CUDPSocket::CUDPSocket(unsigned int port) :
|
||||
m_address(),
|
||||
m_port(port),
|
||||
m_fd(-1)
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
WSAData data;
|
||||
int wsaRet = ::WSAStartup(MAKEWORD(2, 2), &data);
|
||||
if (wsaRet != 0)
|
||||
::fprintf(stderr, "Error from WSAStartup\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
CUDPSocket::~CUDPSocket()
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
::WSACleanup();
|
||||
#endif
|
||||
}
|
||||
|
||||
in_addr CUDPSocket::lookup(const std::string& hostname)
|
||||
{
|
||||
in_addr addr;
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
unsigned long address = ::inet_addr(hostname.c_str());
|
||||
if (address != INADDR_NONE && address != INADDR_ANY) {
|
||||
addr.s_addr = address;
|
||||
return addr;
|
||||
}
|
||||
|
||||
struct hostent* hp = ::gethostbyname(hostname.c_str());
|
||||
if (hp != NULL) {
|
||||
::memcpy(&addr, hp->h_addr_list[0], sizeof(struct in_addr));
|
||||
return addr;
|
||||
}
|
||||
|
||||
::fprintf(stderr, "Cannot find address for host %s\n", hostname.c_str());
|
||||
|
||||
addr.s_addr = INADDR_NONE;
|
||||
return addr;
|
||||
#else
|
||||
in_addr_t address = ::inet_addr(hostname.c_str());
|
||||
if (address != in_addr_t(-1)) {
|
||||
addr.s_addr = address;
|
||||
return addr;
|
||||
}
|
||||
|
||||
struct hostent* hp = ::gethostbyname(hostname.c_str());
|
||||
if (hp != NULL) {
|
||||
::memcpy(&addr, hp->h_addr_list[0], sizeof(struct in_addr));
|
||||
return addr;
|
||||
}
|
||||
|
||||
::fprintf(stderr, "Cannot find address for host %s\n", hostname.c_str());
|
||||
|
||||
addr.s_addr = INADDR_NONE;
|
||||
return addr;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool CUDPSocket::open()
|
||||
{
|
||||
m_fd = ::socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (m_fd < 0) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
::fprintf(stderr, "Cannot create the UDP socket, err: %lu\n", ::GetLastError());
|
||||
#else
|
||||
::fprintf(stderr, "Cannot create the UDP socket, err: %d\n", errno);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_port > 0U) {
|
||||
sockaddr_in addr;
|
||||
::memset(&addr, 0x00, sizeof(sockaddr_in));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(m_port);
|
||||
addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
|
||||
if (!m_address.empty()) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
addr.sin_addr.s_addr = ::inet_addr(m_address.c_str());
|
||||
#else
|
||||
addr.sin_addr.s_addr = ::inet_addr(m_address.c_str());
|
||||
#endif
|
||||
if (addr.sin_addr.s_addr == INADDR_NONE) {
|
||||
::fprintf(stderr, "The local address is invalid - %s\n", m_address.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int reuse = 1;
|
||||
if (::setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) == -1) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
::fprintf(stderr, "Cannot set the UDP socket option, err: %lu\n", ::GetLastError());
|
||||
#else
|
||||
::fprintf(stderr, "Cannot set the UDP socket option, err: %d\n", errno);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
if (::bind(m_fd, (sockaddr*)&addr, sizeof(sockaddr_in)) == -1) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
::fprintf(stderr, "Cannot bind the UDP address, err: %lu\n", ::GetLastError());
|
||||
#else
|
||||
::fprintf(stderr, "Cannot bind the UDP address, err: %d\n", errno);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
::fprintf(stdout, "Opening UDP port on %u\n", m_port);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int CUDPSocket::read(unsigned char* buffer, unsigned int length, in_addr& address, unsigned int& port)
|
||||
{
|
||||
assert(buffer != NULL);
|
||||
assert(length > 0U);
|
||||
|
||||
// Check that the readfrom() won't block
|
||||
fd_set readFds;
|
||||
FD_ZERO(&readFds);
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
FD_SET((unsigned int)m_fd, &readFds);
|
||||
#else
|
||||
FD_SET(m_fd, &readFds);
|
||||
#endif
|
||||
|
||||
// Return immediately
|
||||
timeval tv;
|
||||
tv.tv_sec = 0L;
|
||||
tv.tv_usec = 0L;
|
||||
|
||||
int ret = ::select(m_fd + 1, &readFds, NULL, NULL, &tv);
|
||||
if (ret < 0) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
::fprintf(stderr, "Error returned from UDP select, err: %lu\n", ::GetLastError());
|
||||
#else
|
||||
::fprintf(stderr, "Error returned from UDP select, err: %d\n", errno);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
return 0;
|
||||
|
||||
sockaddr_in addr;
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
int size = sizeof(sockaddr_in);
|
||||
#else
|
||||
socklen_t size = sizeof(sockaddr_in);
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
int len = ::recvfrom(m_fd, (char*)buffer, length, 0, (sockaddr *)&addr, &size);
|
||||
#else
|
||||
ssize_t len = ::recvfrom(m_fd, (char*)buffer, length, 0, (sockaddr *)&addr, &size);
|
||||
#endif
|
||||
if (len <= 0) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
::fprintf(stderr, "Error returned from recvfrom, err: %lu\n", ::GetLastError());
|
||||
#else
|
||||
::fprintf(stderr, "Error returned from recvfrom, err: %d\n", errno);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
address = addr.sin_addr;
|
||||
port = ntohs(addr.sin_port);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
bool CUDPSocket::write(const unsigned char* buffer, unsigned int length, const in_addr& address, unsigned int port)
|
||||
{
|
||||
assert(buffer != NULL);
|
||||
assert(length > 0U);
|
||||
|
||||
sockaddr_in addr;
|
||||
::memset(&addr, 0x00, sizeof(sockaddr_in));
|
||||
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr = address;
|
||||
addr.sin_port = htons(port);
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
int ret = ::sendto(m_fd, (char *)buffer, length, 0, (sockaddr *)&addr, sizeof(sockaddr_in));
|
||||
#else
|
||||
ssize_t ret = ::sendto(m_fd, (char *)buffer, length, 0, (sockaddr *)&addr, sizeof(sockaddr_in));
|
||||
#endif
|
||||
if (ret < 0) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
::fprintf(stderr, "Error returned from sendto, err: %lu\n", ::GetLastError());
|
||||
#else
|
||||
::fprintf(stderr, "Error returned from sendto, err: %d\n", errno);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
if (ret != int(length))
|
||||
return false;
|
||||
#else
|
||||
if (ret != ssize_t(length))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CUDPSocket::close()
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
::closesocket(m_fd);
|
||||
#else
|
||||
::close(m_fd);
|
||||
#endif
|
||||
}
|
58
NXDNParrot/UDPSocket.h
Normal file
58
NXDNParrot/UDPSocket.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2011,2013,2015,2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef UDPSocket_H
|
||||
#define UDPSocket_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
#include <netdb.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#else
|
||||
#include <winsock.h>
|
||||
#endif
|
||||
|
||||
class CUDPSocket {
|
||||
public:
|
||||
CUDPSocket(const std::string& address, unsigned int port = 0U);
|
||||
CUDPSocket(unsigned int port = 0U);
|
||||
~CUDPSocket();
|
||||
|
||||
bool open();
|
||||
|
||||
int read(unsigned char* buffer, unsigned int length, in_addr& address, unsigned int& port);
|
||||
bool write(const unsigned char* buffer, unsigned int length, const in_addr& address, unsigned int port);
|
||||
|
||||
void close();
|
||||
|
||||
static in_addr lookup(const std::string& hostName);
|
||||
|
||||
private:
|
||||
std::string m_address;
|
||||
unsigned short m_port;
|
||||
int m_fd;
|
||||
};
|
||||
|
||||
#endif
|
24
NXDNParrot/Version.h
Normal file
24
NXDNParrot/Version.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if !defined(VERSION_H)
|
||||
#define VERSION_H
|
||||
|
||||
const char* VERSION = "20180206";
|
||||
|
||||
#endif
|
191
NXDNReflector/Conf.cpp
Normal file
191
NXDNReflector/Conf.cpp
Normal file
@ -0,0 +1,191 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "Conf.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cctype>
|
||||
|
||||
const int BUFFER_SIZE = 500;
|
||||
|
||||
enum SECTION {
|
||||
SECTION_NONE,
|
||||
SECTION_GENERAL,
|
||||
SECTION_ID_LOOKUP,
|
||||
SECTION_LOG,
|
||||
SECTION_NETWORK,
|
||||
SECTION_NXCORE
|
||||
};
|
||||
|
||||
CConf::CConf(const std::string& file) :
|
||||
m_file(file),
|
||||
m_daemon(false),
|
||||
m_lookupName(),
|
||||
m_lookupTime(0U),
|
||||
m_logDisplayLevel(0U),
|
||||
m_logFileLevel(0U),
|
||||
m_logFilePath(),
|
||||
m_logFileRoot(),
|
||||
m_networkPort(0U),
|
||||
m_networkDebug(false),
|
||||
m_nxCoreEnabled(false),
|
||||
m_nxCoreAddress(),
|
||||
m_nxCoreDebug(false)
|
||||
{
|
||||
}
|
||||
|
||||
CConf::~CConf()
|
||||
{
|
||||
}
|
||||
|
||||
bool CConf::read()
|
||||
{
|
||||
FILE* fp = ::fopen(m_file.c_str(), "rt");
|
||||
if (fp == NULL) {
|
||||
::fprintf(stderr, "Couldn't open the .ini file - %s\n", m_file.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
SECTION section = SECTION_NONE;
|
||||
|
||||
char buffer[BUFFER_SIZE];
|
||||
while (::fgets(buffer, BUFFER_SIZE, fp) != NULL) {
|
||||
if (buffer[0U] == '#')
|
||||
continue;
|
||||
|
||||
if (buffer[0U] == '[') {
|
||||
if (::strncmp(buffer, "[General]", 9U) == 0)
|
||||
section = SECTION_GENERAL;
|
||||
else if (::strncmp(buffer, "[Id Lookup]", 11U) == 0)
|
||||
section = SECTION_ID_LOOKUP;
|
||||
else if (::strncmp(buffer, "[Log]", 5U) == 0)
|
||||
section = SECTION_LOG;
|
||||
else if (::strncmp(buffer, "[Network]", 9U) == 0)
|
||||
section = SECTION_NETWORK;
|
||||
else if (::strncmp(buffer, "[NXCore]", 8U) == 0)
|
||||
section = SECTION_NXCORE;
|
||||
else
|
||||
section = SECTION_NONE;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
char* key = ::strtok(buffer, " \t=\r\n");
|
||||
if (key == NULL)
|
||||
continue;
|
||||
|
||||
char* value = ::strtok(NULL, "\r\n");
|
||||
if (section == SECTION_GENERAL) {
|
||||
if (::strcmp(key, "Daemon") == 0)
|
||||
m_daemon = ::atoi(value) == 1;
|
||||
} else if (section == SECTION_ID_LOOKUP) {
|
||||
if (::strcmp(key, "Name") == 0)
|
||||
m_lookupName = value;
|
||||
else if (::strcmp(key, "Time") == 0)
|
||||
m_lookupTime = (unsigned int)::atoi(value);
|
||||
} else if (section == SECTION_LOG) {
|
||||
if (::strcmp(key, "FilePath") == 0)
|
||||
m_logFilePath = value;
|
||||
else if (::strcmp(key, "FileRoot") == 0)
|
||||
m_logFileRoot = value;
|
||||
else if (::strcmp(key, "FileLevel") == 0)
|
||||
m_logFileLevel = (unsigned int)::atoi(value);
|
||||
else if (::strcmp(key, "DisplayLevel") == 0)
|
||||
m_logDisplayLevel = (unsigned int)::atoi(value);
|
||||
} else if (section == SECTION_NETWORK) {
|
||||
if (::strcmp(key, "Port") == 0)
|
||||
m_networkPort = (unsigned int)::atoi(value);
|
||||
else if (::strcmp(key, "Debug") == 0)
|
||||
m_networkDebug = ::atoi(value) == 1;
|
||||
} else if (section == SECTION_NXCORE) {
|
||||
if (::strcmp(key, "Enabled") == 0)
|
||||
m_nxCoreEnabled = ::atoi(value) == 1;
|
||||
else if (::strcmp(key, "Address") == 0)
|
||||
m_nxCoreAddress = value;
|
||||
else if (::strcmp(key, "Debug") == 0)
|
||||
m_nxCoreDebug = ::atoi(value) == 1;
|
||||
}
|
||||
}
|
||||
|
||||
::fclose(fp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CConf::getDaemon() const
|
||||
{
|
||||
return m_daemon;
|
||||
}
|
||||
|
||||
std::string CConf::getLookupName() const
|
||||
{
|
||||
return m_lookupName;
|
||||
}
|
||||
|
||||
unsigned int CConf::getLookupTime() const
|
||||
{
|
||||
return m_lookupTime;
|
||||
}
|
||||
|
||||
unsigned int CConf::getLogDisplayLevel() const
|
||||
{
|
||||
return m_logDisplayLevel;
|
||||
}
|
||||
|
||||
unsigned int CConf::getLogFileLevel() const
|
||||
{
|
||||
return m_logFileLevel;
|
||||
}
|
||||
|
||||
std::string CConf::getLogFilePath() const
|
||||
{
|
||||
return m_logFilePath;
|
||||
}
|
||||
|
||||
std::string CConf::getLogFileRoot() const
|
||||
{
|
||||
return m_logFileRoot;
|
||||
}
|
||||
|
||||
unsigned int CConf::getNetworkPort() const
|
||||
{
|
||||
return m_networkPort;
|
||||
}
|
||||
|
||||
bool CConf::getNetworkDebug() const
|
||||
{
|
||||
return m_networkDebug;
|
||||
}
|
||||
|
||||
bool CConf::getNXCoreEnabled() const
|
||||
{
|
||||
return m_nxCoreEnabled;
|
||||
}
|
||||
|
||||
std::string CConf::getNXCoreAddress() const
|
||||
{
|
||||
return m_nxCoreAddress;
|
||||
}
|
||||
|
||||
bool CConf::getNXCoreDebug() const
|
||||
{
|
||||
return m_nxCoreDebug;
|
||||
}
|
75
NXDNReflector/Conf.h
Normal file
75
NXDNReflector/Conf.h
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if !defined(CONF_H)
|
||||
#define CONF_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class CConf
|
||||
{
|
||||
public:
|
||||
CConf(const std::string& file);
|
||||
~CConf();
|
||||
|
||||
bool read();
|
||||
|
||||
// The General section
|
||||
bool getDaemon() const;
|
||||
|
||||
// The Id Lookup section
|
||||
std::string getLookupName() const;
|
||||
unsigned int getLookupTime() const;
|
||||
|
||||
// The Log section
|
||||
unsigned int getLogDisplayLevel() const;
|
||||
unsigned int getLogFileLevel() const;
|
||||
std::string getLogFilePath() const;
|
||||
std::string getLogFileRoot() const;
|
||||
|
||||
// The Network section
|
||||
unsigned int getNetworkPort() const;
|
||||
bool getNetworkDebug() const;
|
||||
|
||||
// The NXCore section
|
||||
bool getNXCoreEnabled() const;
|
||||
std::string getNXCoreAddress() const;
|
||||
bool getNXCoreDebug() const;
|
||||
|
||||
private:
|
||||
std::string m_file;
|
||||
bool m_daemon;
|
||||
|
||||
std::string m_lookupName;
|
||||
unsigned int m_lookupTime;
|
||||
|
||||
unsigned int m_logDisplayLevel;
|
||||
unsigned int m_logFileLevel;
|
||||
std::string m_logFilePath;
|
||||
std::string m_logFileRoot;
|
||||
|
||||
unsigned int m_networkPort;
|
||||
bool m_networkDebug;
|
||||
|
||||
bool m_nxCoreEnabled;
|
||||
std::string m_nxCoreAddress;
|
||||
bool m_nxCoreDebug;
|
||||
};
|
||||
|
||||
#endif
|
136
NXDNReflector/Log.cpp
Normal file
136
NXDNReflector/Log.cpp
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "Log.h"
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#include <Windows.h>
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstdarg>
|
||||
#include <ctime>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
static unsigned int m_fileLevel = 2U;
|
||||
static std::string m_filePath;
|
||||
static std::string m_fileRoot;
|
||||
|
||||
static FILE* m_fpLog = NULL;
|
||||
|
||||
static unsigned int m_displayLevel = 2U;
|
||||
|
||||
static struct tm m_tm;
|
||||
|
||||
static char LEVELS[] = " DMIWEF";
|
||||
|
||||
static bool LogOpen()
|
||||
{
|
||||
if (m_fileLevel == 0U)
|
||||
return true;
|
||||
|
||||
time_t now;
|
||||
::time(&now);
|
||||
|
||||
struct tm* tm = ::gmtime(&now);
|
||||
|
||||
if (tm->tm_mday == m_tm.tm_mday && tm->tm_mon == m_tm.tm_mon && tm->tm_year == m_tm.tm_year) {
|
||||
if (m_fpLog != NULL)
|
||||
return true;
|
||||
} else {
|
||||
if (m_fpLog != NULL)
|
||||
::fclose(m_fpLog);
|
||||
}
|
||||
|
||||
char filename[100U];
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
::sprintf(filename, "%s\\%s-%04d-%02d-%02d.log", m_filePath.c_str(), m_fileRoot.c_str(), tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday);
|
||||
#else
|
||||
::sprintf(filename, "%s/%s-%04d-%02d-%02d.log", m_filePath.c_str(), m_fileRoot.c_str(), tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday);
|
||||
#endif
|
||||
|
||||
m_fpLog = ::fopen(filename, "a+t");
|
||||
m_tm = *tm;
|
||||
|
||||
return m_fpLog != NULL;
|
||||
}
|
||||
|
||||
bool LogInitialise(const std::string& filePath, const std::string& fileRoot, unsigned int fileLevel, unsigned int displayLevel)
|
||||
{
|
||||
m_filePath = filePath;
|
||||
m_fileRoot = fileRoot;
|
||||
m_fileLevel = fileLevel;
|
||||
m_displayLevel = displayLevel;
|
||||
return ::LogOpen();
|
||||
}
|
||||
|
||||
void LogFinalise()
|
||||
{
|
||||
if (m_fpLog != NULL)
|
||||
::fclose(m_fpLog);
|
||||
}
|
||||
|
||||
void Log(unsigned int level, const char* fmt, ...)
|
||||
{
|
||||
assert(fmt != NULL);
|
||||
|
||||
char buffer[300U];
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
SYSTEMTIME st;
|
||||
::GetSystemTime(&st);
|
||||
|
||||
::sprintf(buffer, "%c: %04u-%02u-%02u %02u:%02u:%02u.%03u ", LEVELS[level], st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
|
||||
#else
|
||||
struct timeval now;
|
||||
::gettimeofday(&now, NULL);
|
||||
|
||||
struct tm* tm = ::gmtime(&now.tv_sec);
|
||||
|
||||
::sprintf(buffer, "%c: %04d-%02d-%02d %02d:%02d:%02d.%03lu ", LEVELS[level], tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, now.tv_usec / 1000U);
|
||||
#endif
|
||||
|
||||
va_list vl;
|
||||
va_start(vl, fmt);
|
||||
|
||||
::vsprintf(buffer + ::strlen(buffer), fmt, vl);
|
||||
|
||||
va_end(vl);
|
||||
|
||||
if (level >= m_fileLevel && m_fileLevel != 0U) {
|
||||
bool ret = ::LogOpen();
|
||||
if (!ret)
|
||||
return;
|
||||
|
||||
::fprintf(m_fpLog, "%s\n", buffer);
|
||||
::fflush(m_fpLog);
|
||||
}
|
||||
|
||||
if (level >= m_displayLevel && m_displayLevel != 0U) {
|
||||
::fprintf(stdout, "%s\n", buffer);
|
||||
::fflush(stdout);
|
||||
}
|
||||
|
||||
if (level == 6U) { // Fatal
|
||||
::fclose(m_fpLog);
|
||||
exit(1);
|
||||
}
|
||||
}
|
36
NXDNReflector/Log.h
Normal file
36
NXDNReflector/Log.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if !defined(LOG_H)
|
||||
#define LOG_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#define LogDebug(fmt, ...) Log(1U, fmt, ##__VA_ARGS__)
|
||||
#define LogMessage(fmt, ...) Log(2U, fmt, ##__VA_ARGS__)
|
||||
#define LogInfo(fmt, ...) Log(3U, fmt, ##__VA_ARGS__)
|
||||
#define LogWarning(fmt, ...) Log(4U, fmt, ##__VA_ARGS__)
|
||||
#define LogError(fmt, ...) Log(5U, fmt, ##__VA_ARGS__)
|
||||
#define LogFatal(fmt, ...) Log(6U, fmt, ##__VA_ARGS__)
|
||||
|
||||
extern void Log(unsigned int level, const char* fmt, ...);
|
||||
|
||||
extern bool LogInitialise(const std::string& filePath, const std::string& fileRoot, unsigned int fileLevel, unsigned int displayLevel);
|
||||
extern void LogFinalise();
|
||||
|
||||
#endif
|
19
NXDNReflector/Makefile
Normal file
19
NXDNReflector/Makefile
Normal file
@ -0,0 +1,19 @@
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
CFLAGS = -g -O3 -Wall -std=c++0x -pthread
|
||||
LIBS = -lpthread
|
||||
LDFLAGS = -g
|
||||
|
||||
OBJECTS = Conf.o Log.o Mutex.o NXCoreNetwork.o NXDNLookup.o NXDNNetwork.o NXDNReflector.o StopWatch.o Thread.o Timer.o UDPSocket.o Utils.o
|
||||
|
||||
all: NXDNReflector
|
||||
|
||||
NXDNReflector: $(OBJECTS)
|
||||
$(CXX) $(OBJECTS) $(CFLAGS) $(LIBS) -o NXDNReflector
|
||||
|
||||
%.o: %.cpp
|
||||
$(CXX) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
$(RM) NXDNReflector *.o *.d *.bak *~
|
||||
|
65
NXDNReflector/Mutex.cpp
Normal file
65
NXDNReflector/Mutex.cpp
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "Mutex.h"
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
|
||||
CMutex::CMutex() :
|
||||
m_handle()
|
||||
{
|
||||
m_handle = ::CreateMutex(NULL, FALSE, NULL);
|
||||
}
|
||||
|
||||
CMutex::~CMutex()
|
||||
{
|
||||
::CloseHandle(m_handle);
|
||||
}
|
||||
|
||||
void CMutex::lock()
|
||||
{
|
||||
::WaitForSingleObject(m_handle, INFINITE);
|
||||
}
|
||||
|
||||
void CMutex::unlock()
|
||||
{
|
||||
::ReleaseMutex(m_handle);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
CMutex::CMutex() :
|
||||
m_mutex(PTHREAD_MUTEX_INITIALIZER)
|
||||
{
|
||||
}
|
||||
|
||||
CMutex::~CMutex()
|
||||
{
|
||||
}
|
||||
|
||||
void CMutex::lock()
|
||||
{
|
||||
::pthread_mutex_lock(&m_mutex);
|
||||
}
|
||||
|
||||
void CMutex::unlock()
|
||||
{
|
||||
::pthread_mutex_unlock(&m_mutex);
|
||||
}
|
||||
|
||||
#endif
|
45
NXDNReflector/Mutex.h
Normal file
45
NXDNReflector/Mutex.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if !defined(MUTEX_H)
|
||||
#define MUTEX_H
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
class CMutex
|
||||
{
|
||||
public:
|
||||
CMutex();
|
||||
~CMutex();
|
||||
|
||||
void lock();
|
||||
void unlock();
|
||||
|
||||
private:
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
HANDLE m_handle;
|
||||
#else
|
||||
pthread_mutex_t m_mutex;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
130
NXDNReflector/NXCoreNetwork.cpp
Normal file
130
NXDNReflector/NXCoreNetwork.cpp
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2014,2016,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "NXCoreNetwork.h"
|
||||
#include "Utils.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
const unsigned int BUFFER_LENGTH = 200U;
|
||||
|
||||
const unsigned int NXCORE_PORT = 41300U;
|
||||
|
||||
CNXCoreNetwork::CNXCoreNetwork(const std::string& address, bool debug) :
|
||||
m_socket("", NXCORE_PORT),
|
||||
m_address(),
|
||||
m_debug(debug),
|
||||
m_buffer(1000U, "NXCore Network")
|
||||
{
|
||||
assert(!address.empty());
|
||||
|
||||
m_address = CUDPSocket::lookup(address);
|
||||
}
|
||||
|
||||
CNXCoreNetwork::~CNXCoreNetwork()
|
||||
{
|
||||
}
|
||||
|
||||
bool CNXCoreNetwork::open()
|
||||
{
|
||||
LogMessage("Opening NXCore network connection");
|
||||
|
||||
if (m_address.s_addr == INADDR_NONE)
|
||||
return false;
|
||||
|
||||
return m_socket.open();
|
||||
}
|
||||
|
||||
bool CNXCoreNetwork::write(const unsigned char* data, unsigned int len)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
unsigned char buffer[110U];
|
||||
::memset(buffer, 0x00U, 110U);
|
||||
|
||||
buffer[0U] = 'I';
|
||||
buffer[1U] = 'C';
|
||||
buffer[2U] = 'O';
|
||||
buffer[3U] = 'M';
|
||||
buffer[4U] = 0x01U;
|
||||
buffer[5U] = 0x01U;
|
||||
buffer[6U] = 0x08U;
|
||||
buffer[7U] = 0xE0U;
|
||||
|
||||
buffer[37U] = 0x23U;
|
||||
buffer[38U] = (data[9U] & 0x0CU) != 0x00U ? 0x1CU : 0x10U;
|
||||
buffer[39U] = 0x21U;
|
||||
|
||||
::memcpy(buffer + 40U, data + 10U, 33U);
|
||||
|
||||
if (m_debug)
|
||||
CUtils::dump(1U, "NXCore Network Data Sent", buffer, 102U);
|
||||
|
||||
return m_socket.write(buffer, 102U, m_address, NXCORE_PORT);
|
||||
}
|
||||
|
||||
void CNXCoreNetwork::clock(unsigned int ms)
|
||||
{
|
||||
unsigned char buffer[BUFFER_LENGTH];
|
||||
|
||||
in_addr address;
|
||||
unsigned int port;
|
||||
int length = m_socket.read(buffer, BUFFER_LENGTH, address, port);
|
||||
if (length <= 0)
|
||||
return;
|
||||
|
||||
// Check if the data is for us
|
||||
if (m_address.s_addr != address.s_addr || port != NXCORE_PORT) {
|
||||
LogMessage("NXCore packet received from an invalid source, %08X != %08X and/or %u != %u", m_address.s_addr, address.s_addr, NXCORE_PORT, port);
|
||||
return;
|
||||
}
|
||||
|
||||
// Invalid packet type?
|
||||
if (::memcmp(buffer, "ICOM", 4U) != 0)
|
||||
return;
|
||||
|
||||
if (length != 102)
|
||||
return;
|
||||
|
||||
if (m_debug)
|
||||
CUtils::dump(1U, "NXCore Network Data Received", buffer, length);
|
||||
|
||||
m_buffer.addData(buffer + 40U, 33U);
|
||||
}
|
||||
|
||||
bool CNXCoreNetwork::read(unsigned char* data, unsigned int len)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
if (m_buffer.isEmpty())
|
||||
return false;
|
||||
|
||||
m_buffer.getData(data, 33U);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CNXCoreNetwork::close()
|
||||
{
|
||||
m_socket.close();
|
||||
|
||||
LogMessage("Closing NXCore network connection");
|
||||
}
|
51
NXDNReflector/NXCoreNetwork.h
Normal file
51
NXDNReflector/NXCoreNetwork.h
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2014,2016,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef NXCoreNetwork_H
|
||||
#define NXCoreNetwork_H
|
||||
|
||||
#include "RingBuffer.h"
|
||||
#include "UDPSocket.h"
|
||||
#include "Timer.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
class CNXCoreNetwork {
|
||||
public:
|
||||
CNXCoreNetwork(const std::string& address, bool debug);
|
||||
~CNXCoreNetwork();
|
||||
|
||||
bool open();
|
||||
|
||||
bool write(const unsigned char* data, unsigned int len);
|
||||
|
||||
bool read(unsigned char* data, unsigned int len);
|
||||
|
||||
void close();
|
||||
|
||||
void clock(unsigned int ms);
|
||||
|
||||
private:
|
||||
CUDPSocket m_socket;
|
||||
in_addr m_address;
|
||||
bool m_debug;
|
||||
CRingBuffer<unsigned char> m_buffer;
|
||||
};
|
||||
|
||||
#endif
|
405
NXDNReflector/NXDN.csv
Normal file
405
NXDNReflector/NXDN.csv
Normal file
@ -0,0 +1,405 @@
|
||||
UID,Call,Name,Location,Notes
|
||||
2,W2FLY/M,Harry,Southern NJ,UHF NX-800 mobile
|
||||
3,WB2OOM/M,Tina,Southern NJ,UHF NX-800 Mobile
|
||||
4,W2FLY/M,Harry,Southern NJ,UHF NX-800 Van
|
||||
7,F1PRY,Emmanuel,BEAUVAIS FR,
|
||||
8,W2FLY/P,Harry,Southern NJ,UHF NX-820 Port 2
|
||||
9,KE8BGA,Lowell Katz,"Cleveland, Ohio","on the north shore, NX-800"
|
||||
17,KC2SNI,Jim Hannon,"West Berlin, New Jersey",My Radio is an Icom IC-3161DT
|
||||
25,WB2RUH/P,Bruce,Southern NJ,UHF NX-320
|
||||
26,WB2RUH/M,Bruce,Southern NJ,UHF NX-800 mobile
|
||||
30,KD4MOJ,Doug,,Doug
|
||||
74,N2IXC,Ed,Chatsworth NJ,
|
||||
76,W2FLY/P,Harry,Southern NJ,UFH NX5300 Port 1
|
||||
77,W2FLY/P,Harry,"Somers Point, NJ",UHF NX-800 Shore Base
|
||||
78,W2FLY,Harry,"Mullica Hill, NJ",UHF NX-800
|
||||
79,W2FLY/M,Harry,Southern NJ,UHF NX-5800
|
||||
80,W2FLY/M,Harry,Southern NJ,VHF NX-5700 mobile
|
||||
82,W2FLY/P,Harry,"Somers Point, NJ",VHF NX-700 Shore Base
|
||||
85,W2FLY/M,Harry,Southern NJ,VHF NX_700 van
|
||||
86,W2FLY,Harry,"Mullica Hill, NJ",VHF NX-700 base
|
||||
87,W2FLY/M,Harry,Southern NJ,VHF NX-700 mobile
|
||||
88,W2FLY/P,Harry,Southern NJ,VHF NX-220 portable
|
||||
89,WB2RUH,Bruce,Vineland NJ,VHF NX-700 base
|
||||
99,K1ZSG,Don,,Mobile
|
||||
134,N2SRO,Mike,Pitman,Mobile Radio
|
||||
134,N2SRO,Mike,NJ,
|
||||
141,KF2M,Greg Popovich,"Mt Laurel, NJ",IC-F4161DT
|
||||
401,W1KFR,Bill,,Bill
|
||||
901,K1IFF,Cliff,CT,Cliff NX320
|
||||
902,K1IFF,Cliff,CT,Cliff NX320 - demo
|
||||
903,K1IFF,Cliff,CT,Cliff NX800H
|
||||
905,WA1LMV,Rick,,Rick NX320
|
||||
906,K1IFF,Cliff,CT,Cliff NX200
|
||||
907,K1IFF,Cliff,CT,Future
|
||||
908,W4CLL,Chuck,,CHUCK
|
||||
909,AB1UB V,Woody,"Bristol, CT",
|
||||
909,AB1UB,Woody,"Bristol, CT",
|
||||
909,AB1UB,Woody,,Woody NX300
|
||||
909,W4CCL,Chuck,,CHUCK
|
||||
910,W4CLL,Chuck,,CHUCK
|
||||
911,W4CLL,Chuck,,CHUCK
|
||||
912,W4CCL,Chuck,,CHUCK
|
||||
920,N1XDN,Bob,CT,Bob P1 UHF NX300
|
||||
921,N1XDN,Bob,CT,Bob P1 VHF NX220
|
||||
922,N1XDN,Bob,CT,Bob P2 UHF NX300
|
||||
923,N1XDN,Bob,CT,Bob M1 VHF NX700
|
||||
924,N1XDN,Bob,CT,Bob P3 UHF NX-5300
|
||||
925,N1XDN,Bob,CT,Bob P2 VHF NX-5200
|
||||
926,N1XDN,Bob,CT,Bob M1 UHF NX-5800
|
||||
928,N1XDN,Bob,CT,Icom portable
|
||||
930,K1IFF,Cliff,CT,NX300
|
||||
931,K1IFF,Cliff,CT,NX300
|
||||
936,W1GPO,John,,NX300
|
||||
951,K1KGQ,Joel,,Joel NX800H
|
||||
952,K1KGQ,Joel,CT,Truck radio
|
||||
952,K1GML,Gail,,Gail NX800H
|
||||
953,K1KGQ,Joel,,Joel NX320-1
|
||||
954,K1KGQ,Joel,,
|
||||
955,K1KGQ,Joel,,
|
||||
956,K1KGQ,Joel,,
|
||||
957,K1KGQ,Joel,,
|
||||
958,K1KGQ,Joel,,Joel F4161
|
||||
959,K1KGQ,Joel,,Future
|
||||
960,K1ZXX,Gary,,Gary - Icom All radios
|
||||
961,WA1SSB,Joe,,Joe NX800H
|
||||
962,N1MAT,Dennis,,Dennis F4161
|
||||
963,N1MAT,Dennis,,Dennis F4161
|
||||
970,KB1VRI,Nick,CT,
|
||||
970,KB1VRI,Nick,,Nick
|
||||
971,N1ELE,Paul,CT,
|
||||
972,N1ODJ,Kenny Schmitz,Middletown,
|
||||
973,W1VLF,Paul,CT,
|
||||
980,W1RHS,Rick,Connecticut,
|
||||
995,K1IFF/Base,Cliff,"Brsitol, CT",NXR710 link radio
|
||||
1001,KE4GWW,James,AL,NX200 Portable #1
|
||||
1002,KE4GWW,James,AL,NX200 Portable #2
|
||||
1003,KE4GWW,James,AL,NX300 Portable #1
|
||||
1004,KE4GWW,James,AL,NX300 Portable #2
|
||||
1005,KE4GWW,James,AL,NX700 Base
|
||||
1006,KE4GWW,James,AL,NX800 Base
|
||||
1007,KE4GWW,James M. Nelson,"Dothan, AL",NX700 Mobile#1
|
||||
1008,DK6PX,Stefan,Germany nr Bad Toelz,Coming up FR6000
|
||||
1008,KE4GWW,James,AL,NX700 Mobile#2
|
||||
1009,KE4GWW,James,AL,NX800 Mobile#1
|
||||
1010,KE4GWW,James,AL,NX800 Mobile#2
|
||||
1066,KM4JXP,Peter Tasker,Longboat Key,NX5300
|
||||
1954,W4BPT,BILLY TAYLOR,"RINGGOLD,GA.",
|
||||
1956,KC7SDD,Dana Hanford,"Bainbridge Island, WA","Member BARC, W7NPC.org"
|
||||
1963,N5JRN,David Barts,"Bainbridge Island, WA","Handheld, Icom 4161"
|
||||
1966,ZS6IIX,Henry,Petit South Africa,
|
||||
1997,KC1AJR,Giovanni,East Hampton CT,kenwood NX800 K2
|
||||
3070,W4ORL,Ralph,,Ralph - Mobile
|
||||
3071,W4LOV,Mike,,Mike - NX800
|
||||
3072,N4JTK,John,,John - NX800
|
||||
3074,W4MCA,Michael,,Michael - NX300
|
||||
3075,W4LOV,Mike,,Mike - NX800
|
||||
3079,NN4TT,Dave,Orlando,NX300
|
||||
3079,W4ORL,Ralph,,Ralph - Portable
|
||||
3081,W4MCA,Michael,,Michael - NX800
|
||||
3082,W4LOV,Mike,,Mike - Portable
|
||||
3083,KD4TWJ,Dean,,Dean - Mobile NX800
|
||||
3271,N4KEG,Richard,,RICHARD - Mobile and or ht's N4KEG (UHF)
|
||||
3274,KD4EFM,Evans,FL,
|
||||
3275,KD4EFM,Evans,FL,
|
||||
3278,KD4EFM,Evans,FL,
|
||||
3279,N4KEG,Richard,,
|
||||
3280,KD4EFM,Evans,"Lakeland, Florida",work radio
|
||||
3280,KD4EFM,Evans,FL,Evans Mobile(s)
|
||||
3280,KD4EFM,Evans,FL,
|
||||
3281,N4KEG,Richard,,
|
||||
3450,K0KAD,CHAD TAYLOR,"SPOKANE VALLEY, WA",My Portable
|
||||
3451,K0KAD,CHAD TAYLOR,"SPOKANE VALLEY, WA",My Base Station
|
||||
3452,K0KAD,CHAD TAYLOR,"SPOKANE VALLEY, WA",Mobile Radio
|
||||
4020,K4XXX,Ed,"London, KY",NX820 Base
|
||||
4802,hb3yrb,Alex,Verbier,nx5300
|
||||
4804,hb9fmf,Didier,Rougemont,NX5300
|
||||
5001,N5QZ,Ryan,AR,"N5QZ, Ryan McAfee, Searcy, AR - Kenwood NX-820"
|
||||
5002,N5QZ,Ryan,AR,"N5QZ, Ryan McAfee, Searcy, AR - Kenwood NX-720"
|
||||
5003,N5QS,Roger,AR,"N5QS, Roger Gray, Searcy, AR - Kenwood NX-820"
|
||||
5004,N5QS,Roger,AR,"N5QS, Roger Gray, Searcy, AR - Kenwood NX-720"
|
||||
5005,AC5AV,Larry,AR,"AC5AV, Larry Sicks, Searcy, AR"
|
||||
5006,AC5AV,Larry,AR,"AC5AV, Larry Sicks, Searcy, AR"
|
||||
5007,N5LKE,James,AR,"N5LKE, James Ferguson, Searcy, AR - Kenwood NX-800"
|
||||
5008,AF5WN,Mason,AR,"AF5WN, Mason Creager, Cabot, AR - Kenwood NX-700H"
|
||||
5009,KJ5SF,Stan,AR,"KJ5SF, Stan Rongey, Searcy, AR - Kenwood NX-800"
|
||||
5100,K5SRS,Michael Smith,"Fayetteville, AR",NX-5800 Mobile
|
||||
5101,KC5YQB,Paul Blair,"Fayetteville, AR",
|
||||
5125,AE5OQ,Armstead,"Higden, AR",
|
||||
5125,AE5OQ,Armstead,AR,entered by k1iff
|
||||
5134,AE5OQ,Armstead,AR,"AE5OQ, Armstead M Feland, IV, Higdon, AR - Kenwood NX-200"
|
||||
5150,WY6NN,Doug,"Los Angeles, CA",NX-300/5300
|
||||
5151,KC6HFJ,Tamara,"Los Angeles, CA",NX-300
|
||||
5170,K5WMZ,Gary,AR,"K5WMZ, Gary D Partlow, Ward, AR - Kenwood NX-700"
|
||||
5599,W1ZM,Ryan,,"W1ZM, Ryan Nelson, NX-5300"
|
||||
5987,W5ZN,Joel,AR,"W5ZN, Joel Harrison, Judsonia, AR - Kenwood NX-800"
|
||||
6430,K4GFD,Norm,FL,Norm Greensboro Fla
|
||||
6431,K4GFD,Norm,,
|
||||
6432,K4GFD,Norm,,
|
||||
6439,N4NKV,George,,George
|
||||
6801,hb9vsd,relais de verbier,verbier,
|
||||
6802,HB9YRB,Alex,Verbier,
|
||||
6804,HB9FMF,Didier,Rougemont,
|
||||
7737,N4NKV,George,,George
|
||||
9834,VA7NY,PJ,,PJ
|
||||
12002,W4KJP,Kevin,,KEVIN
|
||||
12005,KD4TWJ,Dean,,Dean - Portable IC-F4161
|
||||
12006,W4MO,Stewart,,STEWART NX300 / 320
|
||||
12007,W4MO,Stewart,,STEWART NX800
|
||||
12010,kd4dwp,Ben,Orlando,
|
||||
12013,K4NBC,Miguel Orama,"Palm Bay, Florida",Icom F4146DS UHF Portable
|
||||
12014,K4NBC,Miguel Orama,"Palm Bay, Florida",Kenwood NX200 VHF HT
|
||||
12015,K4NBC,K4NBC-Miguel UHF Mobile,"Palm Bay, Florida",Future UHF Mobile
|
||||
12016,K4NBC,Miguel,"Palm Bay, Florida",M2 Icom F6061D
|
||||
12017,N4JFZ,,,
|
||||
12021,W4PJT,Paul,,Paul
|
||||
12023,KD4NWL,John,,JOHN
|
||||
12127,W4KDM,Rick,,Rick - Portable NX300
|
||||
12136,WA4KWK,John,,John F6121
|
||||
12200,NB9X,Paul,FL,
|
||||
12201,NB9X,Paul,FL,PAUL
|
||||
12202,NB9X,Paul,FL,
|
||||
12203,NB9X,Paul,FL,
|
||||
12204,WX3C,Juan Arias,Florida,Orlando metro
|
||||
12204,NB9X,Paul,FL,
|
||||
12210,N4APG,Bill,,Bill Pfost
|
||||
12211,N4APG,Bill,,Bill Pfost
|
||||
12212,N4APG,Bill,,Bill Pfost
|
||||
12213,N4APG,Bill,,Bill Pfost
|
||||
12214,N4APG,Bill,,Bill Pfost
|
||||
12215,WA4ISB,Ed,,ED Mobile
|
||||
12216,WA4ISB,Ed,,
|
||||
12220,N4PK,Paul,,PAUK K.
|
||||
12221,N4PK,Paul,,
|
||||
12222,W4PJT,Paul,,
|
||||
12223,W4PJT,Paul,,
|
||||
12226,KI4SWY,William,,
|
||||
12230,KQ4KX,Richard,,Richard Sharp
|
||||
12231,KQ4KX,Richard,,
|
||||
12234,KD4TWJ,Dean,EL98,
|
||||
12235,N1IC,Nick,,Nic
|
||||
12236,N1IC,Nick,,
|
||||
12240,KR4X,Larry,,
|
||||
12241,KR4X,Larry,,
|
||||
12245,KD4ACG,Jason,"Hudson, FL",Icom Mobile
|
||||
12245,KD4ACG,Jason,,JASON
|
||||
12246,KD4ACG,Jason,"Hudson, FL",Icom Portable
|
||||
12246,KD4ACG,Jason,,JASON
|
||||
12247,K2MCI,,,
|
||||
12250,KE4GYX,,,
|
||||
12272,KE4OSL,,,
|
||||
12273,KE4OSL,,,
|
||||
12374,KF4I,Thom,,Thom Base
|
||||
12375,KF4I,Thom,,Thom Mobile
|
||||
12523,KM4JVE,Ana,,Ana - IC-F4161
|
||||
12577,N2DLX,Richard,,Rich Dunajewski NX-5800
|
||||
12604,K4CBN,Greg,,GREG
|
||||
12605,K4CBN,Greg,,
|
||||
12606,K4CBN,Greg,,
|
||||
12607,K4CBN,Greg,,
|
||||
12608,K4CBN,Greg,,
|
||||
12666,KI4SWY,William,,William Stillwel ( All Radios )
|
||||
12691,KE3WDW,Sam,,Sam
|
||||
12780,KC4YUA,Brett,,BRETT
|
||||
13105,W7QO,Alan,,
|
||||
13106,W7QO,Alan,,
|
||||
13107,W7QO,Alan,,
|
||||
13121,W4CML,Chuck,,
|
||||
13122,W4CML,Chuck,,
|
||||
13125,KD4APP,Don,,Don - NX300
|
||||
13126,KD4APP,Don,,Don - F6061D
|
||||
13127,KD4APP,Don,,Don - NX200
|
||||
13131,W5JR,Mike,,
|
||||
13132,W5JR,Mike,,
|
||||
13401,W1KFR,Bill,,Bill
|
||||
13815,KG4BKO,Bill,GA,nx320
|
||||
14020,K4XXX,Ed,"London, KY",NX5300
|
||||
14021,K4XXX,Ed,"London, KY",NX5200
|
||||
15001,N5QZ,Ryan,AR,"N5QZ, Ryan McAfee, Searcy, AR - Kenwood NX-800H (Vehicle 1)"
|
||||
15002,N5QZ,Ryan,AR,"N5QZ, Ryan McAfee, Searcy, AR - Kenwood NX-700 (Vehicle 1)"
|
||||
15003,N5QZ,Ryan,AR,"N5QZ, Ryan McAfee, Searcy, AR - Kenwood NX-800 (Vehicle 2)"
|
||||
15004,N5QZ,Ryan,AR,"N5QZ, Ryan McAfee, Searcy, AR - Kenwood NX-700 (Vehicle 2)"
|
||||
15005,N5QS,Roger,AR,"N5QS, Roger Gray, Searcy, AR - Kenwood NX-800 (Vehicle 1)"
|
||||
15006,N5QS,Roger,AR,"N5QS, Roger Gray, Searcy, AR - Kenwood NX-700 (Vehicle 1)"
|
||||
15007,N5QS,Roger,AR,"N5QS, Roger Gray, Searcy, AR - Kenwood NX-800 (Vehicle 2)"
|
||||
15008,N5QS,Roger,AR,"N5QS, Roger Gray, Searcy, AR - Kenwood NX-700 (Vehicle 2)"
|
||||
15009,N5QS,Roger,AR,"N5QS, Roger Gray, Searcy, AR - Kenwood NX-800 (Vehicle 3)"
|
||||
15010,N5QS,Roger,AR,"N5QS, Roger Gray, Searcy, AR - Kenwood NX-700 (Vehicle 3)"
|
||||
15011,N5QT,Dawn,AR,"N5QT, Dawn Gray, Searcy, AR - Kenwood NX-800"
|
||||
15012,AC5AV,Larry,AR,"AC5AV, Larry Sicks, Searcy, AR - Kenwood NX-800"
|
||||
15013,AC5AV,Larry,AR,"AC5AV, Larry Sicks, Searcy, AR - Kenwood NX-700"
|
||||
15014,N5QT,Dawn,AR,"N5QT, Dawn Gray, Searcy, AR - Kenwood NX-700"
|
||||
15015,N5QS,Roger,AR,"N5QS, Roger Gray, Searcy, AR Motorcycle Mobile"
|
||||
15016,KG5KS,Kenny,,"KG5KS, Kenny Thompson - Kenwood NX-700HK"
|
||||
15017,KG5KS,Kenny,,"KG5KS, Kenny Thompson - Kenwood NX-800HK"
|
||||
15018,N5QS,Roger,AR,"N5QS, Roger Gray, Searcy, AR ATV Mobile"
|
||||
15019,N5QS,Roger,AR,"N5QS, Roger Gray, Searcy, AR ATV Mobile"
|
||||
15020,WA8UBL,Allen,AR,"WA8UBL, Allen Herrick, Beebe, AR, Kenwood NX-700"
|
||||
15021,KD5HRT,Heath,AR,"KD5HRT, Heath Taylor, McRae, AR, Kenwood NX-800"
|
||||
15022,WA8UBL,Allen,AR,"WA8UBL, Allen Herrick, Beebe, AR - Kenwood NX-800"
|
||||
15023,N5ZA,Joel,AR,"N5ZA, Joe Belew, Beebe, AR - Kenwood NX-700"
|
||||
15024,KF5TPF,Ryan,AR,"KF5TPF, Ryan Nelson, Edgemont, AR NX-700"
|
||||
15025,KE5YZP,Ryan,AR,"KE5YZP, Ryan Schwarck, Batesville, AR NX-700"
|
||||
15026,AF5OD,Landon,AR,"AF5OD, Landon McCord, Searcy, AR"
|
||||
15027,KB5RFF,Scott,AR,"KB5RFF, Scott Gray, Searcy, AR - Kenwood NX-800"
|
||||
17002,KC9GMX,Stephen,,Stephen - Base F6121D
|
||||
17004,KC9GMX,Stephen,,Stephen - F6061D
|
||||
17005,KC9NPJ,Jarrett,,Jarrett F6121D
|
||||
17006,KC9GMX,Stephen,,Stephen - F4161DS
|
||||
17007,KC9NPJ,Jarrett,,Jarrett F4231DS
|
||||
17008,KC9RHH,Jesse,,F4101D
|
||||
17009,KC9PHK,Michael,,F4061DS
|
||||
17011,N9BRG,Dan,,Dan kenwood nx800k2
|
||||
17855,AG6RN,Demian,CA,NX-210
|
||||
21007,WA1LMV,Rick,,Rick
|
||||
21014,K2BUI,Eric,,Eric
|
||||
24020,K4XXX,Ed,"London, KY",NX5800
|
||||
24021,K4XXX,Ed,"London, KY",NX5700
|
||||
25001,N5QZ,Ryan,AR,"N5QZ, Ryan McAfee, Searcy, AR - Kenwood NX-300"
|
||||
25002,N5QZ,Ryan,AR,"N5QZ, Ryan McAfee, Searcy, AR - Kenwood NX-200"
|
||||
25003,N5QS,Roger,AR,"N5QS, Roger Gray, Searcy, AR - Kenwood NX-300"
|
||||
25004,N5QS,Roger,AR,"N5QS, Roger Gray, Searcy, AR - Kenwood NX-200"
|
||||
25005,N5QS,Roger,AR,"N5QS, Roger Gray, Searcy, AR - Kenwood NX-320"
|
||||
25006,N5QS,Roger,AR,"N5QS, Roger Gray, Searcy, AR - Kenwood NX-340U"
|
||||
25007,N5QT,Dawn,AR,"N5QT, Dawn Gray, Searcy, AR - Kenwood NX-300"
|
||||
25008,N5QT,Dawn,AR,"N5QT, Dawn Gray, Searcy, AR - Kenwood NX-200"
|
||||
25009,AC5AV,Larry,AR,"AC5AV, Larry Sicks, Searcy, AR - Kenwood NX-300"
|
||||
25010,KD5OOW,Tom,AR,"KD5OOW, Tom McGee, Searcy, AR - Kenwood NX-300"
|
||||
25011,W5ZN,Joel,AR,"W5ZN, Joel Harrison, Judsonia, AR - Kenwood NX-300"
|
||||
25012,KD5HRT,Heath,AR,"KD5HRT, Heath Taylor, McRae, AR - Kenwood NX-300"
|
||||
25013,KK5WA,Darin,AR,"KK5WA, Darin Dykes, Beebe, AR - Kenwood NX-320"
|
||||
25014,N5LKE,James,AR,"N5LKE, James Ferguson, Searcy, AR - Kenwood NX-5300"
|
||||
25015,KJ5ORD,John,AR,"KJ5ORD, John Ord, Searcy, AR - Kenwood NX-300"
|
||||
25016,KB5RFF,Scott,AR,"KB5RFF, Scott Gray, Searcy, AR - Kenwood NX-300"
|
||||
25017,KB5ZUH,Todd,AR,"KB5ZUH, Todd Williams, Searcy, AR - Kenwood NX-320"
|
||||
25018,KB5ZUH,Todd,AR,"KB5ZUH, Todd Williams, Searcy, AR - Kenwood NX-340"
|
||||
25019,KB5ZUH,Todd,AR,"KB5ZUH, Todd Williams, Searcy, AR - Kenwood NX-340"
|
||||
25020,KB5ZUH,Todd,AR,"KB5ZUH, Todd Williams, Searcy, AR - Kenwood NX-320"
|
||||
25021,KE5UZU,Raymond Prince,"England, AR",Kenwood Handheld
|
||||
25021,AF5OD,Landon,AR,"AF5OD, Landon McCord, Searcy, AR"
|
||||
25022,KE5UZU,Raymond Prince,"England, AR",Icom Handheld
|
||||
25022,KE5YZP,Ryan,AR,"KE5YZP, Ryan A Schwarck, Batesville, AR - Icom"
|
||||
25023,KE5YZP,Ryan,AR,"KE5YZP, Ryan A Schwarck, Batesville, AR - Icom"
|
||||
25024,KG5CHM,Colt,AR,"KG5CHM, Colt Boyd, Searcy, AR - Kenwood NX-300"
|
||||
25025,KJ5ORD,John,AR,"KJ5ORD, John Ord, Searcy, AR - Kenwood NX-xxx VHF"
|
||||
25026,WA8UBL,Allen,AR,"WA8UBL, Allen Herrick, Beebe, AR - Kenwood NX-320"
|
||||
25027,KF5TPF,Ryan,AR,"KF5TPF, Ryan Nelson, Edgemont, AR - Kenwood NX-200"
|
||||
25028,WA8UBL,Allen,AR,"WA8UBL, Allen Herrick, Beebe, AR - Kenwood NX-220"
|
||||
25029,KF5WHX,Trey,AR,"KF5WHX, Trey Ferguson, Searcy, AR - Kenwood NX-320"
|
||||
25030,AC5AV,Larry,AR,"AC5AV, Larry Sicks, Searcy, AR"
|
||||
25031,KJ5SF,Stan,AR,"KJ5SF, Stan Rongey, Searcy, AR - Kenwood NX-340"
|
||||
25032,KC5DFH,Kirk,AR,"KC5DFH, Kirk Williams, Searcy, AR - Kenwood NX-340"
|
||||
25033,AF5OD,Landon,AR,"AF5OD, Landon McCord, Searcy, AR, Icom F4161DS"
|
||||
25034,KF5TPF,Ryan,AR,"KF5TPF, Ryan Nelson, Edgemont, AR - ICOM 4161"
|
||||
25035,KG5BMB,Glenda,AR,"KG5BMB, Glenda McCord, Searcy, AR, Icom F4161DS"
|
||||
25039,KC1JET,Jim,,JIM (BASE)
|
||||
25068,N1QD,Joe,,
|
||||
25069,N1COP,Bob,,Bob
|
||||
25070,WD1L,John,,John
|
||||
25125,N1TI,Tim,"Mattapoisett, MA",
|
||||
25125,N1TI,Tim,"Mattapoisett, MA",
|
||||
25144,W1WCF,Walter,,Walter
|
||||
25221,N0XIA,James,,James - Kenwood Mobile and Portable
|
||||
25222,KE4SDC,Ron,,Ron - Portable NX300
|
||||
25246,WG1U,Ken,"Assonet, MA",
|
||||
25333,W1AKN,Jack,,Jack Mobile
|
||||
25390,KC1JET,Jim,,JIM (MOBILE)
|
||||
25390,KC1JET,Jim,,JIM
|
||||
25444,W1TAV,Steve,,Steve
|
||||
25555,WA1MNQ,Mike,,Mike
|
||||
25582,N1KXJ,Ray,"E. Bridgewater, MA.",Port.
|
||||
25582,N1KXJ,Ray Wall,East Bridgewater,
|
||||
25585,N1AVA,Ken Howland,"DARTMOUTH,MA",
|
||||
25700,NN1D,Tony Souza,"Swansea, MA",
|
||||
25740,WG1U,Kenny,,KEN
|
||||
25743,WG1U,Kenny,,KEN
|
||||
25746,N1OTY,John,,JOHN
|
||||
25777,W1BON,Bump,,Bump
|
||||
25830,KB1CHU,Steve,MA,
|
||||
25863,N1ZZN,Jeff,,JEFF
|
||||
25874,KB1KVD,Jason,,Jason - Icom Mob & Port
|
||||
25888,K1WGU,Bob,,Bob
|
||||
25889,AB1CQ,Gary,,Gary
|
||||
25900,N1ZZR,Matt,,Matt - mobile
|
||||
25901,N1MRC,Matt,"Bridgewater, MA",N1MRC P-1
|
||||
25901,N1ZZR,Matt,,Matt
|
||||
25957,KC1HO,Steve,,STEVE
|
||||
27101,KI4SWB,Mark,"Melbourne Beach, FL",Icom Portable
|
||||
27102,KP4OO,Carlos,"Palm Bay, FL",Icom Portable
|
||||
27201,KI4SWB,Mark,"Melbourne Beach, FL",Icom Mobile
|
||||
27202,KP4OO,Carlos,"Palm Bay, FL",Icom Mobile
|
||||
28001,K3KRS,rYAN,CLEVLAND,OHIO
|
||||
30505,KG6MQE,Jim,MT,
|
||||
30571,WX4RCF,Ryan F.,"Tampa, FL",
|
||||
31117,K4QHR,Pete,,Pete
|
||||
31124,KM4JXP,Peter,,NX5300
|
||||
31146,KD2KWD,Michael Santamaria,"Brandon, FL",Kenwood
|
||||
33000,N1PA-R,Paul,NH,PAUL - NEW HAMPSHIRE REPEATER
|
||||
33001,N1PA,Paul,NH,PAUL - NEW HAMPSHIRE
|
||||
33002,N1PA,Paul,NH,PAUL - NEW HAMPSHIRE
|
||||
34001,N2WNS,Bill,NJ,N2WNS Portable
|
||||
34002,N2WNS,Bill,NJ,N2WNS Base
|
||||
36001,W2CCR,Chris,NY,"Chris, Galway, NY NX300"
|
||||
36002,KC2VOB,Asad,NY,"Asad, NYC, NX-5800"
|
||||
36003,KC2VOB,Asad,NY,"Asad, NYC, NX-300GK"
|
||||
36134,N2SRO,Mike,"Pitman, NJ",Portable
|
||||
37001,KA4YMY,Steve,NC,"Steve, Charlotte, NC NX320"
|
||||
37009,KA4YMY,Steve,"Charlotte, NC",
|
||||
37010,KA4YMY,Steve,"Charlotte, NC",
|
||||
37010,KA4YMY,Steve,"Charlotte, NC",
|
||||
40024,N5YEI,Jeff Dalrymple,"Jay, Oklahoma",NX-5800 Mobile
|
||||
40124,N5YEI,Jeff Dalrymple,"Jay, Oklahoma",NX-5300 Portable
|
||||
43751,N4IRS,Steve,,Steve
|
||||
44001,K2BUI,Eric,RI,
|
||||
44002,K2BUI,Eric,"Providence, RI",
|
||||
44007,W2DAN,Dave,,Dave - NX700
|
||||
44298,N1JBC,Jed,,JED
|
||||
49101,WX7Y-1,Bret Mills,Castle Dale Utah,WX7y-1 Hand Held 1
|
||||
49102,WX7Y-2,Bret Mills,"Caslte Dale, Utah",WX7Y-2 Hand held
|
||||
49104,WX7Y-4,Bret Mills,"Castle Dale, Utah",WX7Y-4 Mobile
|
||||
49106,WX7Y-6,Bret Mills,Castle Dale,WX7Y-6 Mobile
|
||||
55700,WB9HKE,Rick,WI,
|
||||
55704,WB9HKE,Rick,WI,
|
||||
57000,VE3SP,Andre,"Toronto, ON",mobile
|
||||
57001,VE3SP,Andre,"Toronto, ON",handheld
|
||||
57001,VE3EI,Eric,,Eric - Portable
|
||||
57002,VE3OKZ,Janusz,"Toronto, ON",mobile
|
||||
57002,VE3EI,Eric,,Eric - Dongle
|
||||
57003,VE3OKZ,Janusz,"Toronto, ON",handheld
|
||||
57004,VE3CCD,Curtis,"Scarborough, ON",handheld
|
||||
57005,VE3NBI,Anoop,"Scarborough, ON",handheld
|
||||
57006,VE3JLU,Sherwin,"Scarborough, ON",handheld
|
||||
57007,va3rq,Jon,"Oakville, ON",handheld
|
||||
57008,ve3ogb,Randy,"Toronto, ON",handheld
|
||||
57009,va3mk,Mark,"Oakville, ON",handheld
|
||||
57010,va3mk,Mark,"Oakville, ON",mobile
|
||||
57011,VA3WZW,Andre,"Durham, ON",mobile
|
||||
57012,VA3WZW,Andre,"Durham, ON",mobile
|
||||
57013,VA3AGV,cottage,"Toronto, ON",mobile
|
||||
57014,VE3BWP,Brian,"Caledon, ON",handheld
|
||||
57015,VE3HY,Frank,"Caledon, ON",handheld
|
||||
57016,VE3UBI,Paul,"Scarborough, ON",mobile
|
||||
57017,VE3UBI,Paul,"Scarborough, ON",handheld
|
||||
57018,VE3RZR,Richard,"Toronto, ON",handheld
|
||||
57019,VE3AEP,Dom,"Toronto, ON",mobile
|
||||
57020,VA3PEO,Adrian,"Toronto, ON",handheld
|
||||
57021,va3wjo,Walter,"Toronto, ON",handheld
|
||||
57022,ve3fkn,Tom,"Stoney Creek, ON",handheld
|
||||
57023,ve3ips,John,"Toronto, ON",handheld
|
||||
57024,VA3CQA,Brian,"Scarborough, ON",handheld
|
||||
57025,VA3PAD,Andrew,"Scarborough, ON",mobile
|
||||
57026,VA3PAD,Andrew,"Scarborough, ON",handheld
|
||||
57027,VA3VAD,Arpad,"Hamilton, ON",handheld
|
||||
57028,VA3KY,Shelly,"Thornhill, ON",mobile
|
||||
57029,VA3KY,Shelly,"Thornhill, ON",handheld
|
||||
57030,VE3KFQ,Doug,"Toronto, ON",mobile
|
||||
57031,VE3KFQ,Doug,"Toronto, ON",handheld
|
||||
57032,VE3AEP,Dom 2,"Toronto, ON",handheld
|
||||
57033,VE3DJZ,Huey,"Hamilton, ON",mobile
|
||||
57034,VE3DJZ,Huey,"Hamilton, ON",handheld
|
||||
57035,VA3RQ,Jon,Oakville ON,Mobile
|
||||
3106418,N5ICK,Nicholas Nixon,"Rialto, Ca",
|
||||
3112205,N2HUC,Phil Roberts,"Port St. Lucie, FL",DV4MINI AMBE voice
|
||||
3118365,NA9VY,Chris Gilbert,"New Palestine, IN",
|
||||
3118366,N9UMJ,Rick Nicholson,Buddha Indiana,
|
||||
3142058,N3BAH,L. Abraham Smith,Southwestern Pennsylvania,
|
|
160
NXDNReflector/NXDNLookup.cpp
Normal file
160
NXDNReflector/NXDNLookup.cpp
Normal file
@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright (C) 2016,2017,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "NXDNLookup.h"
|
||||
#include "Timer.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cctype>
|
||||
|
||||
CNXDNLookup::CNXDNLookup(const std::string& filename, unsigned int reloadTime) :
|
||||
CThread(),
|
||||
m_filename(filename),
|
||||
m_reloadTime(reloadTime),
|
||||
m_table(),
|
||||
m_mutex(),
|
||||
m_stop(false)
|
||||
{
|
||||
}
|
||||
|
||||
CNXDNLookup::~CNXDNLookup()
|
||||
{
|
||||
}
|
||||
|
||||
bool CNXDNLookup::read()
|
||||
{
|
||||
bool ret = load();
|
||||
|
||||
if (m_reloadTime > 0U)
|
||||
run();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CNXDNLookup::entry()
|
||||
{
|
||||
LogInfo("Started the NXDN Id lookup reload thread");
|
||||
|
||||
CTimer timer(1U, 3600U * m_reloadTime);
|
||||
timer.start();
|
||||
|
||||
while (!m_stop) {
|
||||
sleep(1000U);
|
||||
|
||||
timer.clock();
|
||||
if (timer.hasExpired()) {
|
||||
load();
|
||||
timer.start();
|
||||
}
|
||||
}
|
||||
|
||||
LogInfo("Stopped the NXDN Id lookup reload thread");
|
||||
}
|
||||
|
||||
void CNXDNLookup::stop()
|
||||
{
|
||||
if (m_reloadTime == 0U) {
|
||||
delete this;
|
||||
return;
|
||||
}
|
||||
|
||||
m_stop = true;
|
||||
|
||||
wait();
|
||||
}
|
||||
|
||||
std::string CNXDNLookup::find(unsigned int id)
|
||||
{
|
||||
std::string callsign;
|
||||
|
||||
if (id == 0xFFFFU)
|
||||
return std::string("ALL");
|
||||
|
||||
m_mutex.lock();
|
||||
|
||||
try {
|
||||
callsign = m_table.at(id);
|
||||
} catch (...) {
|
||||
char text[10U];
|
||||
::sprintf(text, "%u", id);
|
||||
callsign = std::string(text);
|
||||
}
|
||||
|
||||
m_mutex.unlock();
|
||||
|
||||
return callsign;
|
||||
}
|
||||
|
||||
bool CNXDNLookup::exists(unsigned int id)
|
||||
{
|
||||
m_mutex.lock();
|
||||
|
||||
bool found = m_table.count(id) == 1U;
|
||||
|
||||
m_mutex.unlock();
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
bool CNXDNLookup::load()
|
||||
{
|
||||
FILE* fp = ::fopen(m_filename.c_str(), "rt");
|
||||
if (fp == NULL) {
|
||||
LogWarning("Cannot open the NXDN Id lookup file - %s", m_filename.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
m_mutex.lock();
|
||||
|
||||
// Remove the old entries
|
||||
m_table.clear();
|
||||
|
||||
char buffer[100U];
|
||||
while (::fgets(buffer, 100U, fp) != NULL) {
|
||||
if (buffer[0U] == '#')
|
||||
continue;
|
||||
|
||||
char* p1 = ::strtok(buffer, ",\t\r\n");
|
||||
char* p2 = ::strtok(NULL, ",\t\r\n");
|
||||
|
||||
if (p1 != NULL && p2 != NULL) {
|
||||
unsigned int id = (unsigned int)::atoi(p1);
|
||||
if (id > 0U) {
|
||||
for (char* p = p2; *p != 0x00U; p++)
|
||||
*p = ::toupper(*p);
|
||||
|
||||
m_table[id] = std::string(p2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_mutex.unlock();
|
||||
|
||||
::fclose(fp);
|
||||
|
||||
size_t size = m_table.size();
|
||||
if (size == 0U)
|
||||
return false;
|
||||
|
||||
LogInfo("Loaded %u Ids to the NXDN callsign lookup table", size);
|
||||
|
||||
return true;
|
||||
}
|
53
NXDNReflector/NXDNLookup.h
Normal file
53
NXDNReflector/NXDNLookup.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 2016,2017,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef NXDNLookup_H
|
||||
#define NXDNLookup_H
|
||||
|
||||
#include "Thread.h"
|
||||
#include "Mutex.h"
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
class CNXDNLookup : public CThread {
|
||||
public:
|
||||
CNXDNLookup(const std::string& filename, unsigned int reloadTime);
|
||||
virtual ~CNXDNLookup();
|
||||
|
||||
bool read();
|
||||
|
||||
virtual void entry();
|
||||
|
||||
std::string find(unsigned int id);
|
||||
|
||||
bool exists(unsigned int id);
|
||||
|
||||
void stop();
|
||||
|
||||
private:
|
||||
std::string m_filename;
|
||||
unsigned int m_reloadTime;
|
||||
std::unordered_map<unsigned int, std::string> m_table;
|
||||
CMutex m_mutex;
|
||||
bool m_stop;
|
||||
|
||||
bool load();
|
||||
};
|
||||
|
||||
#endif
|
76
NXDNReflector/NXDNNetwork.cpp
Normal file
76
NXDNReflector/NXDNNetwork.cpp
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2014,2016,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "NXDNNetwork.h"
|
||||
#include "Utils.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
CNXDNNetwork::CNXDNNetwork(unsigned int port, bool debug) :
|
||||
m_socket(port),
|
||||
m_debug(debug)
|
||||
{
|
||||
}
|
||||
|
||||
CNXDNNetwork::~CNXDNNetwork()
|
||||
{
|
||||
}
|
||||
|
||||
bool CNXDNNetwork::open()
|
||||
{
|
||||
LogInfo("Opening NXDN network connection");
|
||||
|
||||
return m_socket.open();
|
||||
}
|
||||
|
||||
bool CNXDNNetwork::write(const unsigned char* data, unsigned int length, const in_addr& address, unsigned int port)
|
||||
{
|
||||
assert(data != NULL);
|
||||
assert(length > 0U);
|
||||
assert(port > 0U);
|
||||
|
||||
if (m_debug)
|
||||
CUtils::dump(1U, "NXDN Network Data Sent", data, length);
|
||||
|
||||
return m_socket.write(data, length, address, port);
|
||||
}
|
||||
|
||||
unsigned int CNXDNNetwork::read(unsigned char* data, unsigned int length, in_addr& address, unsigned int& port)
|
||||
{
|
||||
assert(data != NULL);
|
||||
assert(length > 0U);
|
||||
|
||||
int len = m_socket.read(data, length, address, port);
|
||||
if (len <= 0)
|
||||
return 0U;
|
||||
|
||||
if (m_debug)
|
||||
CUtils::dump(1U, "NXDN Network Data Received", data, len);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
void CNXDNNetwork::close()
|
||||
{
|
||||
m_socket.close();
|
||||
|
||||
LogInfo("Closing NXDN network connection");
|
||||
}
|
45
NXDNReflector/NXDNNetwork.h
Normal file
45
NXDNReflector/NXDNNetwork.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2014,2016,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef NXDNNetwork_H
|
||||
#define NXDNNetwork_H
|
||||
|
||||
#include "UDPSocket.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
class CNXDNNetwork {
|
||||
public:
|
||||
CNXDNNetwork(unsigned int port, bool debug);
|
||||
~CNXDNNetwork();
|
||||
|
||||
bool open();
|
||||
|
||||
bool write(const unsigned char* data, unsigned int length, const in_addr& address, unsigned int port);
|
||||
|
||||
unsigned int read(unsigned char* data, unsigned int length, in_addr& address, unsigned int& port);
|
||||
|
||||
void close();
|
||||
|
||||
private:
|
||||
CUDPSocket m_socket;
|
||||
bool m_debug;
|
||||
};
|
||||
|
||||
#endif
|
396
NXDNReflector/NXDNReflector.cpp
Normal file
396
NXDNReflector/NXDNReflector.cpp
Normal file
@ -0,0 +1,396 @@
|
||||
/*
|
||||
* Copyright (C) 2016,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "NXCoreNetwork.h"
|
||||
#include "NXDNReflector.h"
|
||||
#include "NXDNNetwork.h"
|
||||
#include "NXDNLookup.h"
|
||||
#include "StopWatch.h"
|
||||
#include "Version.h"
|
||||
#include "Thread.h"
|
||||
#include "Utils.h"
|
||||
#include "Log.h"
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#include <Windows.h>
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <pwd.h>
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
const char* DEFAULT_INI_FILE = "NXDNReflector.ini";
|
||||
#else
|
||||
const char* DEFAULT_INI_FILE = "/etc/NXDNReflector.ini";
|
||||
#endif
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstdarg>
|
||||
#include <ctime>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
const char* iniFile = DEFAULT_INI_FILE;
|
||||
if (argc > 1) {
|
||||
for (int currentArg = 1; currentArg < argc; ++currentArg) {
|
||||
std::string arg = argv[currentArg];
|
||||
if ((arg == "-v") || (arg == "--version")) {
|
||||
::fprintf(stdout, "NXDNReflector version %s\n", VERSION);
|
||||
return 0;
|
||||
} else if (arg.substr(0, 1) == "-") {
|
||||
::fprintf(stderr, "Usage: NXDNReflector [-v|--version] [filename]\n");
|
||||
return 1;
|
||||
} else {
|
||||
iniFile = argv[currentArg];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CNXDNReflector* reflector = new CNXDNReflector(std::string(iniFile));
|
||||
reflector->run();
|
||||
delete reflector;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CNXDNReflector::CNXDNReflector(const std::string& file) :
|
||||
m_conf(file),
|
||||
m_repeaters()
|
||||
{
|
||||
}
|
||||
|
||||
CNXDNReflector::~CNXDNReflector()
|
||||
{
|
||||
}
|
||||
|
||||
void CNXDNReflector::run()
|
||||
{
|
||||
bool ret = m_conf.read();
|
||||
if (!ret) {
|
||||
::fprintf(stderr, "NXDNReflector: cannot read the .ini file\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ret = ::LogInitialise(m_conf.getLogFilePath(), m_conf.getLogFileRoot(), m_conf.getLogFileLevel(), m_conf.getLogDisplayLevel());
|
||||
if (!ret) {
|
||||
::fprintf(stderr, "NXDNReflector: unable to open the log file\n");
|
||||
return;
|
||||
}
|
||||
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
bool m_daemon = m_conf.getDaemon();
|
||||
if (m_daemon) {
|
||||
// Create new process
|
||||
pid_t pid = ::fork();
|
||||
if (pid == -1) {
|
||||
::LogWarning("Couldn't fork() , exiting");
|
||||
return;
|
||||
}
|
||||
else if (pid != 0)
|
||||
exit(EXIT_SUCCESS);
|
||||
|
||||
// Create new session and process group
|
||||
if (::setsid() == -1) {
|
||||
::LogWarning("Couldn't setsid(), exiting");
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the working directory to the root directory
|
||||
if (::chdir("/") == -1) {
|
||||
::LogWarning("Couldn't cd /, exiting");
|
||||
return;
|
||||
}
|
||||
|
||||
::close(STDIN_FILENO);
|
||||
::close(STDOUT_FILENO);
|
||||
::close(STDERR_FILENO);
|
||||
|
||||
//If we are currently root...
|
||||
if (getuid() == 0) {
|
||||
struct passwd* user = ::getpwnam("mmdvm");
|
||||
if (user == NULL) {
|
||||
::LogError("Could not get the mmdvm user, exiting");
|
||||
return;
|
||||
}
|
||||
|
||||
uid_t mmdvm_uid = user->pw_uid;
|
||||
gid_t mmdvm_gid = user->pw_gid;
|
||||
|
||||
//Set user and group ID's to mmdvm:mmdvm
|
||||
if (setgid(mmdvm_gid) != 0) {
|
||||
::LogWarning("Could not set mmdvm GID, exiting");
|
||||
return;
|
||||
}
|
||||
|
||||
if (setuid(mmdvm_uid) != 0) {
|
||||
::LogWarning("Could not set mmdvm UID, exiting");
|
||||
return;
|
||||
}
|
||||
|
||||
//Double check it worked (AKA Paranoia)
|
||||
if (setuid(0) != -1) {
|
||||
::LogWarning("It's possible to regain root - something is wrong!, exiting");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
CNXDNNetwork nxdnNetwork(m_conf.getNetworkPort(), m_conf.getNetworkDebug());
|
||||
ret = nxdnNetwork.open();
|
||||
if (!ret) {
|
||||
::LogFinalise();
|
||||
return;
|
||||
}
|
||||
|
||||
CNXCoreNetwork* nxCoreNetwork = NULL;
|
||||
if (m_conf.getNXCoreEnabled()) {
|
||||
nxCoreNetwork = new CNXCoreNetwork(m_conf.getNXCoreAddress(), m_conf.getNXCoreDebug());
|
||||
ret = nxCoreNetwork->open();
|
||||
if (!ret) {
|
||||
nxdnNetwork.close();
|
||||
delete nxCoreNetwork;
|
||||
::LogFinalise();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
CNXDNLookup* lookup = new CNXDNLookup(m_conf.getLookupName(), m_conf.getLookupTime());
|
||||
lookup->read();
|
||||
|
||||
CStopWatch stopWatch;
|
||||
stopWatch.start();
|
||||
|
||||
CTimer dumpTimer(1000U, 120U);
|
||||
dumpTimer.start();
|
||||
|
||||
LogMessage("Starting NXDNReflector-%s", VERSION);
|
||||
|
||||
CNXDNRepeater* current = NULL;
|
||||
bool nxCore = false;
|
||||
|
||||
CTimer watchdogTimer(1000U, 0U, 1500U);
|
||||
|
||||
for (;;) {
|
||||
unsigned char buffer[200U];
|
||||
in_addr address;
|
||||
unsigned int port;
|
||||
|
||||
unsigned int len = nxdnNetwork.read(buffer, 200U, address, port);
|
||||
if (len > 0U) {
|
||||
CNXDNRepeater* rpt = findRepeater(address, port);
|
||||
|
||||
if (::memcmp(buffer, "NXDNP", 5U) == 0) {
|
||||
if (rpt == NULL) {
|
||||
rpt = new CNXDNRepeater;
|
||||
rpt->m_timer.start();
|
||||
rpt->m_address = address;
|
||||
rpt->m_port = port;
|
||||
rpt->m_callsign = std::string((char*)(buffer + 5U), 10U);
|
||||
m_repeaters.push_back(rpt);
|
||||
|
||||
LogMessage("Adding %s (%s:%u)", rpt->m_callsign.c_str(), ::inet_ntoa(address), port);
|
||||
}
|
||||
else {
|
||||
rpt->m_timer.start();
|
||||
}
|
||||
|
||||
// Return the poll
|
||||
nxdnNetwork.write(buffer, len, address, port);
|
||||
} else if (::memcmp(buffer, "NXDNU", 5U) == 0) {
|
||||
if (rpt != NULL) {
|
||||
std::string callsign = std::string((char*)(buffer + 5U), 10U);
|
||||
LogMessage("Removing %s (%s:%u)", callsign.c_str(), ::inet_ntoa(address), port);
|
||||
|
||||
for (std::vector<CNXDNRepeater*>::iterator it = m_repeaters.begin(); it != m_repeaters.end(); ++it) {
|
||||
if (*it == rpt) {
|
||||
m_repeaters.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
delete rpt;
|
||||
}
|
||||
} else if (::memcmp(buffer, "NXDND", 5U) == 0) {
|
||||
if (rpt != NULL) {
|
||||
rpt->m_timer.start();
|
||||
|
||||
if (current == NULL && !nxCore) {
|
||||
current = rpt;
|
||||
|
||||
unsigned short srcId = (buffer[5U] << 8) | buffer[6U];
|
||||
unsigned short dstId = (buffer[7U] << 8) | buffer[8U];
|
||||
bool grp = (buffer[9U] & 0x01U) == 0x01U;
|
||||
|
||||
std::string callsign = lookup->find(srcId);
|
||||
LogMessage("Transmission from %s at %s to %s%u", callsign.c_str(), current->m_callsign.c_str(), grp ? "TG " : "", dstId);
|
||||
}
|
||||
|
||||
if (current == rpt) {
|
||||
watchdogTimer.start();
|
||||
|
||||
for (std::vector<CNXDNRepeater*>::const_iterator it = m_repeaters.begin(); it != m_repeaters.end(); ++it) {
|
||||
in_addr addr = (*it)->m_address;
|
||||
unsigned int prt = (*it)->m_port;
|
||||
if (addr.s_addr != address.s_addr || prt != port)
|
||||
nxdnNetwork.write(buffer, len, addr, prt);
|
||||
|
||||
if (nxCoreNetwork != NULL)
|
||||
nxCoreNetwork->write(buffer, len);
|
||||
}
|
||||
|
||||
if ((buffer[9U] & 0x04U) == 0x04U) {
|
||||
LogMessage("Received end of transmission");
|
||||
watchdogTimer.stop();
|
||||
current = NULL;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LogMessage("Data received from an unknown source - %s:%u", ::inet_ntoa(address), port);
|
||||
CUtils::dump(2U, "Data", buffer, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nxCoreNetwork != NULL) {
|
||||
len = nxCoreNetwork->read(buffer, 200U);
|
||||
if (len > 0U) {
|
||||
if (current == NULL) {
|
||||
if (!nxCore) {
|
||||
if ((buffer[0U] == 0x81U || buffer[0U] == 0x83U) && buffer[5U] == 0x01U) {
|
||||
bool grp = (buffer[7U] & 0x20U) == 0x20U;
|
||||
unsigned short srcId = (buffer[8U] << 8) | buffer[9U];
|
||||
unsigned short dstId = (buffer[10U] << 8) | buffer[11U];
|
||||
|
||||
std::string callsign = lookup->find(srcId);
|
||||
LogMessage("Transmission from %s at NXCore to %s%u", callsign.c_str(), grp ? "TG " : "", dstId);
|
||||
|
||||
nxCore = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (nxCore) {
|
||||
watchdogTimer.start();
|
||||
|
||||
for (std::vector<CNXDNRepeater*>::const_iterator it = m_repeaters.begin(); it != m_repeaters.end(); ++it) {
|
||||
in_addr addr = (*it)->m_address;
|
||||
unsigned int prt = (*it)->m_port;
|
||||
nxdnNetwork.write(buffer, len, addr, prt);
|
||||
}
|
||||
|
||||
if ((buffer[0U] == 0x81U || buffer[0U] == 0x83U) && buffer[5U] == 0x08U) {
|
||||
LogMessage("Received end of transmission");
|
||||
nxCore = false;
|
||||
watchdogTimer.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int ms = stopWatch.elapsed();
|
||||
stopWatch.start();
|
||||
|
||||
// Remove any repeaters that haven't reported for a while
|
||||
for (std::vector<CNXDNRepeater*>::iterator it = m_repeaters.begin(); it != m_repeaters.end(); ++it)
|
||||
(*it)->m_timer.clock(ms);
|
||||
|
||||
for (std::vector<CNXDNRepeater*>::iterator it = m_repeaters.begin(); it != m_repeaters.end(); ++it) {
|
||||
CNXDNRepeater* itRpt = *it;
|
||||
if (itRpt->m_timer.hasExpired()) {
|
||||
in_addr address = itRpt->m_address;
|
||||
unsigned int port = itRpt->m_port;
|
||||
std::string callsign = itRpt->m_callsign;
|
||||
LogMessage("Removing %s (%s:%u) disappeared", callsign.c_str(), ::inet_ntoa(address), port);
|
||||
m_repeaters.erase(it);
|
||||
delete itRpt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
watchdogTimer.clock(ms);
|
||||
if (watchdogTimer.isRunning() && watchdogTimer.hasExpired()) {
|
||||
LogMessage("Network watchdog has expired");
|
||||
watchdogTimer.stop();
|
||||
current = NULL;
|
||||
nxCore = false;
|
||||
}
|
||||
|
||||
dumpTimer.clock(ms);
|
||||
if (dumpTimer.hasExpired()) {
|
||||
dumpRepeaters();
|
||||
dumpTimer.start();
|
||||
}
|
||||
|
||||
if (nxCoreNetwork != NULL)
|
||||
nxCoreNetwork->clock(ms);
|
||||
|
||||
if (ms < 5U)
|
||||
CThread::sleep(5U);
|
||||
}
|
||||
|
||||
nxdnNetwork.close();
|
||||
|
||||
if (nxCoreNetwork != NULL) {
|
||||
nxCoreNetwork->close();
|
||||
delete nxCoreNetwork;
|
||||
}
|
||||
|
||||
lookup->stop();
|
||||
|
||||
::LogFinalise();
|
||||
}
|
||||
|
||||
CNXDNRepeater* CNXDNReflector::findRepeater(const in_addr& address, unsigned int port) const
|
||||
{
|
||||
for (std::vector<CNXDNRepeater*>::const_iterator it = m_repeaters.begin(); it != m_repeaters.end(); ++it) {
|
||||
if (address.s_addr == (*it)->m_address.s_addr && (*it)->m_port == port)
|
||||
return *it;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CNXDNReflector::dumpRepeaters() const
|
||||
{
|
||||
if (m_repeaters.size() == 0U) {
|
||||
LogMessage("No repeaters linked");
|
||||
return;
|
||||
}
|
||||
|
||||
LogMessage("Currently linked repeaters:");
|
||||
|
||||
for (std::vector<CNXDNRepeater*>::const_iterator it = m_repeaters.begin(); it != m_repeaters.end(); ++it) {
|
||||
in_addr address = (*it)->m_address;
|
||||
unsigned int port = (*it)->m_port;
|
||||
std::string callsign = (*it)->m_callsign;
|
||||
unsigned int timer = (*it)->m_timer.getTimer();
|
||||
unsigned int timeout = (*it)->m_timer.getTimeout();
|
||||
LogMessage(" %s (%s:%u) %u/%u", callsign.c_str(), ::inet_ntoa(address), port, timer, timeout);
|
||||
}
|
||||
}
|
73
NXDNReflector/NXDNReflector.h
Normal file
73
NXDNReflector/NXDNReflector.h
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (C) 2016,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if !defined(NXDNReflector_H)
|
||||
#define NXDNReflector_H
|
||||
|
||||
#include "Timer.h"
|
||||
#include "Conf.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
#include <netdb.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#else
|
||||
#include <winsock.h>
|
||||
#endif
|
||||
|
||||
class CNXDNRepeater {
|
||||
public:
|
||||
CNXDNRepeater() :
|
||||
m_address(),
|
||||
m_port(0U),
|
||||
m_callsign(),
|
||||
m_timer(1000U, 120U)
|
||||
{
|
||||
}
|
||||
|
||||
in_addr m_address;
|
||||
unsigned int m_port;
|
||||
std::string m_callsign;
|
||||
CTimer m_timer;
|
||||
};
|
||||
|
||||
class CNXDNReflector
|
||||
{
|
||||
public:
|
||||
CNXDNReflector(const std::string& file);
|
||||
~CNXDNReflector();
|
||||
|
||||
void run();
|
||||
|
||||
private:
|
||||
CConf m_conf;
|
||||
std::vector<CNXDNRepeater*> m_repeaters;
|
||||
|
||||
CNXDNRepeater* findRepeater(const in_addr& address, unsigned int port) const;
|
||||
void dumpRepeaters() const;
|
||||
};
|
||||
|
||||
#endif
|
22
NXDNReflector/NXDNReflector.ini
Normal file
22
NXDNReflector/NXDNReflector.ini
Normal file
@ -0,0 +1,22 @@
|
||||
[General]
|
||||
Daemon=1
|
||||
|
||||
[Id Lookup]
|
||||
Name=NXDN.csv
|
||||
Time=24
|
||||
|
||||
[Log]
|
||||
# Logging levels, 0=No logging
|
||||
DisplayLevel=1
|
||||
FileLevel=1
|
||||
FilePath=.
|
||||
FileRoot=NXDNReflector
|
||||
|
||||
[Network]
|
||||
Port=41007
|
||||
Debug=0
|
||||
|
||||
[NXCore]
|
||||
Enabled=0
|
||||
Address=127.0.0.1
|
||||
Debug=0
|
76
NXDNReflector/NXDNReflector.sh
Normal file
76
NXDNReflector/NXDNReflector.sh
Normal file
@ -0,0 +1,76 @@
|
||||
#!/bin/bash
|
||||
### BEGIN INIT INFO
|
||||
#
|
||||
# Provides: NXDNReflector
|
||||
# Required-Start: $all
|
||||
# Required-Stop:
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: Example startscript NXDNReflector
|
||||
|
||||
#
|
||||
### END INIT INFO
|
||||
## Fill in name of program here.
|
||||
PROG="NXDNReflector"
|
||||
PROG_PATH="/usr/local/bin/"
|
||||
PROG_ARGS="/etc/NXDNReflector.ini"
|
||||
PIDFILE="/var/run/NXDNReflector.pid"
|
||||
USER="root"
|
||||
|
||||
start() {
|
||||
if [ -e $PIDFILE ]; then
|
||||
## Program is running, exit with error.
|
||||
echo "Error! $PROG is currently running!" 1>&2
|
||||
exit 1
|
||||
else
|
||||
cd $PROG_PATH
|
||||
./$PROG $PROG_ARGS
|
||||
echo "$PROG started"
|
||||
touch $PIDFILE
|
||||
fi
|
||||
}
|
||||
|
||||
stop() {
|
||||
if [ -e $PIDFILE ]; then
|
||||
## Program is running, so stop it
|
||||
echo "$PROG is running"
|
||||
rm -f $PIDFILE
|
||||
killall $PROG
|
||||
echo "$PROG stopped"
|
||||
else
|
||||
## Program is not running, exit with error.
|
||||
echo "Error! $PROG not started!" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
## Check to see if we are running as root first.
|
||||
## Found at
|
||||
## http://www.cyberciti.biz/tips/shell-root-user-check-script.html
|
||||
if [ "$(id -u)" != "0" ]; then
|
||||
echo "This script must be run as root" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
start
|
||||
exit 0
|
||||
;;
|
||||
stop)
|
||||
stop
|
||||
exit 0
|
||||
;;
|
||||
reload|restart|force-reload)
|
||||
stop
|
||||
sleep 5
|
||||
start
|
||||
exit 0
|
||||
;;
|
||||
**)
|
||||
echo "Usage: $0 {start|stop|reload}" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
exit 0
|
||||
### END
|
31
NXDNReflector/NXDNReflector.sln
Normal file
31
NXDNReflector/NXDNReflector.sln
Normal file
@ -0,0 +1,31 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.27130.2026
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NXDNReflector", "NXDNReflector.vcxproj", "{C68ABEB3-5CDD-4B26-8D66-77FE81EC6BB5}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{C68ABEB3-5CDD-4B26-8D66-77FE81EC6BB5}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{C68ABEB3-5CDD-4B26-8D66-77FE81EC6BB5}.Debug|x64.Build.0 = Debug|x64
|
||||
{C68ABEB3-5CDD-4B26-8D66-77FE81EC6BB5}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{C68ABEB3-5CDD-4B26-8D66-77FE81EC6BB5}.Debug|x86.Build.0 = Debug|Win32
|
||||
{C68ABEB3-5CDD-4B26-8D66-77FE81EC6BB5}.Release|x64.ActiveCfg = Release|x64
|
||||
{C68ABEB3-5CDD-4B26-8D66-77FE81EC6BB5}.Release|x64.Build.0 = Release|x64
|
||||
{C68ABEB3-5CDD-4B26-8D66-77FE81EC6BB5}.Release|x86.ActiveCfg = Release|Win32
|
||||
{C68ABEB3-5CDD-4B26-8D66-77FE81EC6BB5}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {32F19C39-C6E7-44AB-BE4C-EA8DD3C57231}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
186
NXDNReflector/NXDNReflector.vcxproj
Normal file
186
NXDNReflector/NXDNReflector.vcxproj
Normal file
@ -0,0 +1,186 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Conf.h" />
|
||||
<ClInclude Include="NXCoreNetwork.h" />
|
||||
<ClInclude Include="NXDNLookup.h" />
|
||||
<ClInclude Include="Log.h" />
|
||||
<ClInclude Include="Mutex.h" />
|
||||
<ClInclude Include="NXDNNetwork.h" />
|
||||
<ClInclude Include="NXDNReflector.h" />
|
||||
<ClInclude Include="RingBuffer.h" />
|
||||
<ClInclude Include="StopWatch.h" />
|
||||
<ClInclude Include="Thread.h" />
|
||||
<ClInclude Include="Timer.h" />
|
||||
<ClInclude Include="UDPSocket.h" />
|
||||
<ClInclude Include="Utils.h" />
|
||||
<ClInclude Include="Version.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Conf.cpp" />
|
||||
<ClCompile Include="NXCoreNetwork.cpp" />
|
||||
<ClCompile Include="NXDNLookup.cpp" />
|
||||
<ClCompile Include="Log.cpp" />
|
||||
<ClCompile Include="Mutex.cpp" />
|
||||
<ClCompile Include="NXDNNetwork.cpp" />
|
||||
<ClCompile Include="NXDNReflector.cpp" />
|
||||
<ClCompile Include="StopWatch.cpp" />
|
||||
<ClCompile Include="Thread.cpp" />
|
||||
<ClCompile Include="Timer.cpp" />
|
||||
<ClCompile Include="UDPSocket.cpp" />
|
||||
<ClCompile Include="Utils.cpp" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<ProjectGuid>{C68ABEB3-5CDD-4B26-8D66-77FE81EC6BB5}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>NXDNReflector</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
95
NXDNReflector/NXDNReflector.vcxproj.filters
Normal file
95
NXDNReflector/NXDNReflector.vcxproj.filters
Normal file
@ -0,0 +1,95 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Conf.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NXDNLookup.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Log.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Mutex.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NXDNReflector.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="RingBuffer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="StopWatch.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Thread.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Timer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="UDPSocket.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Utils.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Version.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NXDNNetwork.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NXCoreNetwork.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Conf.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="NXDNLookup.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Log.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Mutex.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="NXDNReflector.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="StopWatch.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Thread.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Timer.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="UDPSocket.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Utils.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="NXDNNetwork.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="NXCoreNetwork.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
147
NXDNReflector/RingBuffer.h
Normal file
147
NXDNReflector/RingBuffer.h
Normal file
@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright (C) 2006-2009,2012,2013,2015,2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef RingBuffer_H
|
||||
#define RingBuffer_H
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
template<class T> class CRingBuffer {
|
||||
public:
|
||||
CRingBuffer(unsigned int length, const char* name) :
|
||||
m_length(length),
|
||||
m_name(name),
|
||||
m_buffer(NULL),
|
||||
m_iPtr(0U),
|
||||
m_oPtr(0U)
|
||||
{
|
||||
assert(length > 0U);
|
||||
assert(name != NULL);
|
||||
|
||||
m_buffer = new T[length];
|
||||
|
||||
::memset(m_buffer, 0x00, m_length * sizeof(T));
|
||||
}
|
||||
|
||||
~CRingBuffer()
|
||||
{
|
||||
delete[] m_buffer;
|
||||
}
|
||||
|
||||
bool addData(const T* buffer, unsigned int nSamples)
|
||||
{
|
||||
if (nSamples >= freeSpace()) {
|
||||
::fprintf(stderr, "**** Overflow in %s ring buffer, %u >= %u\n", m_name, nSamples, freeSpace());
|
||||
return false;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0U; i < nSamples; i++) {
|
||||
m_buffer[m_iPtr++] = buffer[i];
|
||||
|
||||
if (m_iPtr == m_length)
|
||||
m_iPtr = 0U;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool getData(T* buffer, unsigned int nSamples)
|
||||
{
|
||||
if (dataSize() < nSamples) {
|
||||
::fprintf(stderr, "**** Underflow in %s ring buffer, %u < %u\n", m_name, dataSize(), nSamples);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0U; i < nSamples; i++) {
|
||||
buffer[i] = m_buffer[m_oPtr++];
|
||||
|
||||
if (m_oPtr == m_length)
|
||||
m_oPtr = 0U;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool peek(T* buffer, unsigned int nSamples)
|
||||
{
|
||||
if (dataSize() < nSamples) {
|
||||
::fprintf(stderr, "**** Underflow peek in %s ring buffer, %u < %u\n", m_name, dataSize(), nSamples);
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int ptr = m_oPtr;
|
||||
for (unsigned int i = 0U; i < nSamples; i++) {
|
||||
buffer[i] = m_buffer[ptr++];
|
||||
|
||||
if (ptr == m_length)
|
||||
ptr = 0U;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_iPtr = 0U;
|
||||
m_oPtr = 0U;
|
||||
|
||||
::memset(m_buffer, 0x00, m_length * sizeof(T));
|
||||
}
|
||||
|
||||
unsigned int freeSpace() const
|
||||
{
|
||||
if (m_oPtr == m_iPtr)
|
||||
return m_length;
|
||||
|
||||
if (m_oPtr > m_iPtr)
|
||||
return m_oPtr - m_iPtr;
|
||||
|
||||
return (m_length + m_oPtr) - m_iPtr;
|
||||
}
|
||||
|
||||
unsigned int dataSize() const
|
||||
{
|
||||
return m_length - freeSpace();
|
||||
}
|
||||
|
||||
bool hasSpace(unsigned int length) const
|
||||
{
|
||||
return freeSpace() > length;
|
||||
}
|
||||
|
||||
bool hasData() const
|
||||
{
|
||||
return m_oPtr != m_iPtr;
|
||||
}
|
||||
|
||||
bool isEmpty() const
|
||||
{
|
||||
return m_oPtr == m_iPtr;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned int m_length;
|
||||
const char* m_name;
|
||||
T* m_buffer;
|
||||
unsigned int m_iPtr;
|
||||
unsigned int m_oPtr;
|
||||
};
|
||||
|
||||
#endif
|
84
NXDNReflector/StopWatch.cpp
Normal file
84
NXDNReflector/StopWatch.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "StopWatch.h"
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
|
||||
CStopWatch::CStopWatch() :
|
||||
m_frequency(),
|
||||
m_start()
|
||||
{
|
||||
::QueryPerformanceFrequency(&m_frequency);
|
||||
}
|
||||
|
||||
CStopWatch::~CStopWatch()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned long CStopWatch::start()
|
||||
{
|
||||
::QueryPerformanceCounter(&m_start);
|
||||
|
||||
return (unsigned long)(m_start.QuadPart / m_frequency.QuadPart);
|
||||
}
|
||||
|
||||
unsigned int CStopWatch::elapsed()
|
||||
{
|
||||
LARGE_INTEGER now;
|
||||
::QueryPerformanceCounter(&now);
|
||||
|
||||
LARGE_INTEGER temp;
|
||||
temp.QuadPart = (now.QuadPart - m_start.QuadPart) * 1000;
|
||||
|
||||
return (unsigned int)(temp.QuadPart / m_frequency.QuadPart);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
CStopWatch::CStopWatch() :
|
||||
m_start()
|
||||
{
|
||||
}
|
||||
|
||||
CStopWatch::~CStopWatch()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned long CStopWatch::start()
|
||||
{
|
||||
::gettimeofday(&m_start, NULL);
|
||||
|
||||
return m_start.tv_usec;
|
||||
}
|
||||
|
||||
unsigned int CStopWatch::elapsed()
|
||||
{
|
||||
struct timeval now;
|
||||
::gettimeofday(&now, NULL);
|
||||
|
||||
unsigned int elapsed = (now.tv_sec - m_start.tv_sec) * 1000U;
|
||||
elapsed += now.tv_usec / 1000U;
|
||||
elapsed -= m_start.tv_usec / 1000U;
|
||||
|
||||
return elapsed;
|
||||
}
|
||||
|
||||
#endif
|
46
NXDNReflector/StopWatch.h
Normal file
46
NXDNReflector/StopWatch.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if !defined(STOPWATCH_H)
|
||||
#define STOPWATCH_H
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
class CStopWatch
|
||||
{
|
||||
public:
|
||||
CStopWatch();
|
||||
~CStopWatch();
|
||||
|
||||
unsigned long start();
|
||||
unsigned int elapsed();
|
||||
|
||||
private:
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
LARGE_INTEGER m_frequency;
|
||||
LARGE_INTEGER m_start;
|
||||
#else
|
||||
struct timeval m_start;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
101
NXDNReflector/Thread.cpp
Normal file
101
NXDNReflector/Thread.cpp
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "Thread.h"
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
|
||||
CThread::CThread() :
|
||||
m_handle()
|
||||
{
|
||||
}
|
||||
|
||||
CThread::~CThread()
|
||||
{
|
||||
}
|
||||
|
||||
bool CThread::run()
|
||||
{
|
||||
m_handle = ::CreateThread(NULL, 0, &helper, this, 0, NULL);
|
||||
|
||||
return m_handle != NULL;
|
||||
}
|
||||
|
||||
|
||||
void CThread::wait()
|
||||
{
|
||||
::WaitForSingleObject(m_handle, INFINITE);
|
||||
|
||||
::CloseHandle(m_handle);
|
||||
}
|
||||
|
||||
|
||||
DWORD CThread::helper(LPVOID arg)
|
||||
{
|
||||
CThread* p = (CThread*)arg;
|
||||
|
||||
p->entry();
|
||||
|
||||
return 0UL;
|
||||
}
|
||||
|
||||
void CThread::sleep(unsigned int ms)
|
||||
{
|
||||
::Sleep(ms);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
CThread::CThread() :
|
||||
m_thread()
|
||||
{
|
||||
}
|
||||
|
||||
CThread::~CThread()
|
||||
{
|
||||
}
|
||||
|
||||
bool CThread::run()
|
||||
{
|
||||
return ::pthread_create(&m_thread, NULL, helper, this) == 0;
|
||||
}
|
||||
|
||||
|
||||
void CThread::wait()
|
||||
{
|
||||
::pthread_join(m_thread, NULL);
|
||||
}
|
||||
|
||||
|
||||
void* CThread::helper(void* arg)
|
||||
{
|
||||
CThread* p = (CThread*)arg;
|
||||
|
||||
p->entry();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CThread::sleep(unsigned int ms)
|
||||
{
|
||||
::usleep(ms * 1000);
|
||||
}
|
||||
|
||||
#endif
|
56
NXDNReflector/Thread.h
Normal file
56
NXDNReflector/Thread.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if !defined(THREAD_H)
|
||||
#define THREAD_H
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
class CThread
|
||||
{
|
||||
public:
|
||||
CThread();
|
||||
virtual ~CThread();
|
||||
|
||||
virtual bool run();
|
||||
|
||||
virtual void entry() = 0;
|
||||
|
||||
virtual void wait();
|
||||
|
||||
static void sleep(unsigned int ms);
|
||||
|
||||
private:
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
HANDLE m_handle;
|
||||
#else
|
||||
pthread_t m_thread;
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
static DWORD __stdcall helper(LPVOID arg);
|
||||
#else
|
||||
static void* helper(void* arg);
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
68
NXDNReflector/Timer.cpp
Normal file
68
NXDNReflector/Timer.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (C) 2009,2010,2015 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "Timer.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
|
||||
CTimer::CTimer(unsigned int ticksPerSec, unsigned int secs, unsigned int msecs) :
|
||||
m_ticksPerSec(ticksPerSec),
|
||||
m_timeout(0U),
|
||||
m_timer(0U)
|
||||
{
|
||||
assert(ticksPerSec > 0U);
|
||||
|
||||
if (secs > 0U || msecs > 0U) {
|
||||
// m_timeout = ((secs * 1000U + msecs) * m_ticksPerSec) / 1000U + 1U;
|
||||
unsigned long long temp = (secs * 1000ULL + msecs) * m_ticksPerSec;
|
||||
m_timeout = (unsigned int)(temp / 1000ULL + 1ULL);
|
||||
}
|
||||
}
|
||||
|
||||
CTimer::~CTimer()
|
||||
{
|
||||
}
|
||||
|
||||
void CTimer::setTimeout(unsigned int secs, unsigned int msecs)
|
||||
{
|
||||
if (secs > 0U || msecs > 0U) {
|
||||
// m_timeout = ((secs * 1000U + msecs) * m_ticksPerSec) / 1000U + 1U;
|
||||
unsigned long long temp = (secs * 1000ULL + msecs) * m_ticksPerSec;
|
||||
m_timeout = (unsigned int)(temp / 1000ULL + 1ULL);
|
||||
} else {
|
||||
m_timeout = 0U;
|
||||
m_timer = 0U;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int CTimer::getTimeout() const
|
||||
{
|
||||
if (m_timeout == 0U)
|
||||
return 0U;
|
||||
|
||||
return (m_timeout - 1U) / m_ticksPerSec;
|
||||
}
|
||||
|
||||
unsigned int CTimer::getTimer() const
|
||||
{
|
||||
if (m_timer == 0U)
|
||||
return 0U;
|
||||
|
||||
return (m_timer - 1U) / m_ticksPerSec;
|
||||
}
|
89
NXDNReflector/Timer.h
Normal file
89
NXDNReflector/Timer.h
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (C) 2009,2010,2011,2014 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef Timer_H
|
||||
#define Timer_H
|
||||
|
||||
class CTimer {
|
||||
public:
|
||||
CTimer(unsigned int ticksPerSec, unsigned int secs = 0U, unsigned int msecs = 0U);
|
||||
~CTimer();
|
||||
|
||||
void setTimeout(unsigned int secs, unsigned int msecs = 0U);
|
||||
|
||||
unsigned int getTimeout() const;
|
||||
unsigned int getTimer() const;
|
||||
|
||||
unsigned int getRemaining()
|
||||
{
|
||||
if (m_timeout == 0U || m_timer == 0U)
|
||||
return 0U;
|
||||
|
||||
if (m_timer >= m_timeout)
|
||||
return 0U;
|
||||
|
||||
return (m_timeout - m_timer) / m_ticksPerSec;
|
||||
}
|
||||
|
||||
bool isRunning()
|
||||
{
|
||||
return m_timer > 0U;
|
||||
}
|
||||
|
||||
void start(unsigned int secs, unsigned int msecs = 0U)
|
||||
{
|
||||
setTimeout(secs, msecs);
|
||||
|
||||
start();
|
||||
}
|
||||
|
||||
void start()
|
||||
{
|
||||
if (m_timeout > 0U)
|
||||
m_timer = 1U;
|
||||
}
|
||||
|
||||
void stop()
|
||||
{
|
||||
m_timer = 0U;
|
||||
}
|
||||
|
||||
bool hasExpired()
|
||||
{
|
||||
if (m_timeout == 0U || m_timer == 0U)
|
||||
return false;
|
||||
|
||||
if (m_timer >= m_timeout)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void clock(unsigned int ticks = 1U)
|
||||
{
|
||||
if (m_timer > 0U && m_timeout > 0U)
|
||||
m_timer += ticks;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned int m_ticksPerSec;
|
||||
unsigned int m_timeout;
|
||||
unsigned int m_timer;
|
||||
};
|
||||
|
||||
#endif
|
262
NXDNReflector/UDPSocket.cpp
Normal file
262
NXDNReflector/UDPSocket.cpp
Normal file
@ -0,0 +1,262 @@
|
||||
/*
|
||||
* Copyright (C) 2006-2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "UDPSocket.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
#endif
|
||||
|
||||
|
||||
CUDPSocket::CUDPSocket(const std::string& address, unsigned int port) :
|
||||
m_address(address),
|
||||
m_port(port),
|
||||
m_fd(-1)
|
||||
{
|
||||
assert(!address.empty());
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
WSAData data;
|
||||
int wsaRet = ::WSAStartup(MAKEWORD(2, 2), &data);
|
||||
if (wsaRet != 0)
|
||||
LogError("Error from WSAStartup");
|
||||
#endif
|
||||
}
|
||||
|
||||
CUDPSocket::CUDPSocket(unsigned int port) :
|
||||
m_address(),
|
||||
m_port(port),
|
||||
m_fd(-1)
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
WSAData data;
|
||||
int wsaRet = ::WSAStartup(MAKEWORD(2, 2), &data);
|
||||
if (wsaRet != 0)
|
||||
LogError("Error from WSAStartup");
|
||||
#endif
|
||||
}
|
||||
|
||||
CUDPSocket::~CUDPSocket()
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
::WSACleanup();
|
||||
#endif
|
||||
}
|
||||
|
||||
in_addr CUDPSocket::lookup(const std::string& hostname)
|
||||
{
|
||||
in_addr addr;
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
unsigned long address = ::inet_addr(hostname.c_str());
|
||||
if (address != INADDR_NONE && address != INADDR_ANY) {
|
||||
addr.s_addr = address;
|
||||
return addr;
|
||||
}
|
||||
|
||||
struct hostent* hp = ::gethostbyname(hostname.c_str());
|
||||
if (hp != NULL) {
|
||||
::memcpy(&addr, hp->h_addr_list[0], sizeof(struct in_addr));
|
||||
return addr;
|
||||
}
|
||||
|
||||
LogError("Cannot find address for host %s", hostname.c_str());
|
||||
|
||||
addr.s_addr = INADDR_NONE;
|
||||
return addr;
|
||||
#else
|
||||
in_addr_t address = ::inet_addr(hostname.c_str());
|
||||
if (address != in_addr_t(-1)) {
|
||||
addr.s_addr = address;
|
||||
return addr;
|
||||
}
|
||||
|
||||
struct hostent* hp = ::gethostbyname(hostname.c_str());
|
||||
if (hp != NULL) {
|
||||
::memcpy(&addr, hp->h_addr_list[0], sizeof(struct in_addr));
|
||||
return addr;
|
||||
}
|
||||
|
||||
LogError("Cannot find address for host %s", hostname.c_str());
|
||||
|
||||
addr.s_addr = INADDR_NONE;
|
||||
return addr;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool CUDPSocket::open()
|
||||
{
|
||||
m_fd = ::socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (m_fd < 0) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
LogError("Cannot create the UDP socket, err: %lu", ::GetLastError());
|
||||
#else
|
||||
LogError("Cannot create the UDP socket, err: %d", errno);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_port > 0U) {
|
||||
sockaddr_in addr;
|
||||
::memset(&addr, 0x00, sizeof(sockaddr_in));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(m_port);
|
||||
addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
|
||||
if (!m_address.empty()) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
addr.sin_addr.s_addr = ::inet_addr(m_address.c_str());
|
||||
#else
|
||||
addr.sin_addr.s_addr = ::inet_addr(m_address.c_str());
|
||||
#endif
|
||||
if (addr.sin_addr.s_addr == INADDR_NONE) {
|
||||
LogError("The local address is invalid - %s", m_address.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int reuse = 1;
|
||||
if (::setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) == -1) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
LogError("Cannot set the UDP socket option, err: %lu", ::GetLastError());
|
||||
#else
|
||||
LogError("Cannot set the UDP socket option, err: %d", errno);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
if (::bind(m_fd, (sockaddr*)&addr, sizeof(sockaddr_in)) == -1) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
LogError("Cannot bind the UDP address, err: %lu", ::GetLastError());
|
||||
#else
|
||||
LogError("Cannot bind the UDP address, err: %d", errno);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int CUDPSocket::read(unsigned char* buffer, unsigned int length, in_addr& address, unsigned int& port)
|
||||
{
|
||||
assert(buffer != NULL);
|
||||
assert(length > 0U);
|
||||
|
||||
// Check that the readfrom() won't block
|
||||
fd_set readFds;
|
||||
FD_ZERO(&readFds);
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
FD_SET((unsigned int)m_fd, &readFds);
|
||||
#else
|
||||
FD_SET(m_fd, &readFds);
|
||||
#endif
|
||||
|
||||
// Return immediately
|
||||
timeval tv;
|
||||
tv.tv_sec = 0L;
|
||||
tv.tv_usec = 0L;
|
||||
|
||||
int ret = ::select(m_fd + 1, &readFds, NULL, NULL, &tv);
|
||||
if (ret < 0) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
LogError("Error returned from UDP select, err: %lu", ::GetLastError());
|
||||
#else
|
||||
LogError("Error returned from UDP select, err: %d", errno);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
return 0;
|
||||
|
||||
sockaddr_in addr;
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
int size = sizeof(sockaddr_in);
|
||||
#else
|
||||
socklen_t size = sizeof(sockaddr_in);
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
int len = ::recvfrom(m_fd, (char*)buffer, length, 0, (sockaddr *)&addr, &size);
|
||||
#else
|
||||
ssize_t len = ::recvfrom(m_fd, (char*)buffer, length, 0, (sockaddr *)&addr, &size);
|
||||
#endif
|
||||
if (len <= 0) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
LogError("Error returned from recvfrom, err: %lu", ::GetLastError());
|
||||
#else
|
||||
LogError("Error returned from recvfrom, err: %d", errno);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
address = addr.sin_addr;
|
||||
port = ntohs(addr.sin_port);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
bool CUDPSocket::write(const unsigned char* buffer, unsigned int length, const in_addr& address, unsigned int port)
|
||||
{
|
||||
assert(buffer != NULL);
|
||||
assert(length > 0U);
|
||||
|
||||
sockaddr_in addr;
|
||||
::memset(&addr, 0x00, sizeof(sockaddr_in));
|
||||
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr = address;
|
||||
addr.sin_port = htons(port);
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
int ret = ::sendto(m_fd, (char *)buffer, length, 0, (sockaddr *)&addr, sizeof(sockaddr_in));
|
||||
#else
|
||||
ssize_t ret = ::sendto(m_fd, (char *)buffer, length, 0, (sockaddr *)&addr, sizeof(sockaddr_in));
|
||||
#endif
|
||||
if (ret < 0) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
LogError("Error returned from sendto, err: %lu", ::GetLastError());
|
||||
#else
|
||||
LogError("Error returned from sendto, err: %d", errno);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
if (ret != int(length))
|
||||
return false;
|
||||
#else
|
||||
if (ret != ssize_t(length))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CUDPSocket::close()
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
::closesocket(m_fd);
|
||||
#else
|
||||
::close(m_fd);
|
||||
#endif
|
||||
}
|
58
NXDNReflector/UDPSocket.h
Normal file
58
NXDNReflector/UDPSocket.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2011,2013,2015,2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef UDPSocket_H
|
||||
#define UDPSocket_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
#include <netdb.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#else
|
||||
#include <winsock.h>
|
||||
#endif
|
||||
|
||||
class CUDPSocket {
|
||||
public:
|
||||
CUDPSocket(const std::string& address, unsigned int port = 0U);
|
||||
CUDPSocket(unsigned int port = 0U);
|
||||
~CUDPSocket();
|
||||
|
||||
bool open();
|
||||
|
||||
int read(unsigned char* buffer, unsigned int length, in_addr& address, unsigned int& port);
|
||||
bool write(const unsigned char* buffer, unsigned int length, const in_addr& address, unsigned int port);
|
||||
|
||||
void close();
|
||||
|
||||
static in_addr lookup(const std::string& hostName);
|
||||
|
||||
private:
|
||||
std::string m_address;
|
||||
unsigned short m_port;
|
||||
int m_fd;
|
||||
};
|
||||
|
||||
#endif
|
146
NXDNReflector/Utils.cpp
Normal file
146
NXDNReflector/Utils.cpp
Normal file
@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright (C) 2009,2014,2015,2016 Jonathan Naylor, G4KLX
|
||||
*
|
||||
* 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; version 2 of the License.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "Utils.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
|
||||
void CUtils::dump(const std::string& title, const unsigned char* data, unsigned int length)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
dump(2U, title, data, length);
|
||||
}
|
||||
|
||||
void CUtils::dump(int level, const std::string& title, const unsigned char* data, unsigned int length)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
::Log(level, "%s", title.c_str());
|
||||
|
||||
unsigned int offset = 0U;
|
||||
|
||||
while (length > 0U) {
|
||||
std::string output;
|
||||
|
||||
unsigned int bytes = (length > 16U) ? 16U : length;
|
||||
|
||||
for (unsigned i = 0U; i < bytes; i++) {
|
||||
char temp[10U];
|
||||
::sprintf(temp, "%02X ", data[offset + i]);
|
||||
output += temp;
|
||||
}
|
||||
|
||||
for (unsigned int i = bytes; i < 16U; i++)
|
||||
output += " ";
|
||||
|
||||
output += " *";
|
||||
|
||||
for (unsigned i = 0U; i < bytes; i++) {
|
||||
unsigned char c = data[offset + i];
|
||||
|
||||
if (::isprint(c))
|
||||
output += c;
|
||||
else
|
||||
output += '.';
|
||||
}
|
||||
|
||||
output += '*';
|
||||
|
||||
::Log(level, "%04X: %s", offset, output.c_str());
|
||||
|
||||
offset += 16U;
|
||||
|
||||
if (length >= 16U)
|
||||
length -= 16U;
|
||||
else
|
||||
length = 0U;
|
||||
}
|
||||
}
|
||||
|
||||
void CUtils::dump(const std::string& title, const bool* bits, unsigned int length)
|
||||
{
|
||||
assert(bits != NULL);
|
||||
|
||||
dump(2U, title, bits, length);
|
||||
}
|
||||
|
||||
void CUtils::dump(int level, const std::string& title, const bool* bits, unsigned int length)
|
||||
{
|
||||
assert(bits != NULL);
|
||||
|
||||
unsigned char bytes[100U];
|
||||
unsigned int nBytes = 0U;
|
||||
for (unsigned int n = 0U; n < length; n += 8U, nBytes++)
|
||||
bitsToByteBE(bits + n, bytes[nBytes]);
|
||||
|
||||
dump(level, title, bytes, nBytes);
|
||||
}
|
||||
|
||||
void CUtils::byteToBitsBE(unsigned char byte, bool* bits)
|
||||
{
|
||||
assert(bits != NULL);
|
||||
|
||||
bits[0U] = (byte & 0x80U) == 0x80U;
|
||||
bits[1U] = (byte & 0x40U) == 0x40U;
|
||||
bits[2U] = (byte & 0x20U) == 0x20U;
|
||||
bits[3U] = (byte & 0x10U) == 0x10U;
|
||||
bits[4U] = (byte & 0x08U) == 0x08U;
|
||||
bits[5U] = (byte & 0x04U) == 0x04U;
|
||||
bits[6U] = (byte & 0x02U) == 0x02U;
|
||||
bits[7U] = (byte & 0x01U) == 0x01U;
|
||||
}
|
||||
|
||||
void CUtils::byteToBitsLE(unsigned char byte, bool* bits)
|
||||
{
|
||||
assert(bits != NULL);
|
||||
|
||||
bits[0U] = (byte & 0x01U) == 0x01U;
|
||||
bits[1U] = (byte & 0x02U) == 0x02U;
|
||||
bits[2U] = (byte & 0x04U) == 0x04U;
|
||||
bits[3U] = (byte & 0x08U) == 0x08U;
|
||||
bits[4U] = (byte & 0x10U) == 0x10U;
|
||||
bits[5U] = (byte & 0x20U) == 0x20U;
|
||||
bits[6U] = (byte & 0x40U) == 0x40U;
|
||||
bits[7U] = (byte & 0x80U) == 0x80U;
|
||||
}
|
||||
|
||||
void CUtils::bitsToByteBE(const bool* bits, unsigned char& byte)
|
||||
{
|
||||
assert(bits != NULL);
|
||||
|
||||
byte = bits[0U] ? 0x80U : 0x00U;
|
||||
byte |= bits[1U] ? 0x40U : 0x00U;
|
||||
byte |= bits[2U] ? 0x20U : 0x00U;
|
||||
byte |= bits[3U] ? 0x10U : 0x00U;
|
||||
byte |= bits[4U] ? 0x08U : 0x00U;
|
||||
byte |= bits[5U] ? 0x04U : 0x00U;
|
||||
byte |= bits[6U] ? 0x02U : 0x00U;
|
||||
byte |= bits[7U] ? 0x01U : 0x00U;
|
||||
}
|
||||
|
||||
void CUtils::bitsToByteLE(const bool* bits, unsigned char& byte)
|
||||
{
|
||||
assert(bits != NULL);
|
||||
|
||||
byte = bits[0U] ? 0x01U : 0x00U;
|
||||
byte |= bits[1U] ? 0x02U : 0x00U;
|
||||
byte |= bits[2U] ? 0x04U : 0x00U;
|
||||
byte |= bits[3U] ? 0x08U : 0x00U;
|
||||
byte |= bits[4U] ? 0x10U : 0x00U;
|
||||
byte |= bits[5U] ? 0x20U : 0x00U;
|
||||
byte |= bits[6U] ? 0x40U : 0x00U;
|
||||
byte |= bits[7U] ? 0x80U : 0x00U;
|
||||
}
|
36
NXDNReflector/Utils.h
Normal file
36
NXDNReflector/Utils.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2009,2014,2015 by Jonathan Naylor, G4KLX
|
||||
*
|
||||
* 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; version 2 of the License.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef Utils_H
|
||||
#define Utils_H
|
||||
|
||||
#include <string>
|
||||
|
||||
class CUtils {
|
||||
public:
|
||||
static void dump(const std::string& title, const unsigned char* data, unsigned int length);
|
||||
static void dump(int level, const std::string& title, const unsigned char* data, unsigned int length);
|
||||
|
||||
static void dump(const std::string& title, const bool* bits, unsigned int length);
|
||||
static void dump(int level, const std::string& title, const bool* bits, unsigned int length);
|
||||
|
||||
static void byteToBitsBE(unsigned char byte, bool* bits);
|
||||
static void byteToBitsLE(unsigned char byte, bool* bits);
|
||||
|
||||
static void bitsToByteBE(const bool* bits, unsigned char& byte);
|
||||
static void bitsToByteLE(const bool* bits, unsigned char& byte);
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif
|
24
NXDNReflector/Version.h
Normal file
24
NXDNReflector/Version.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if !defined(VERSION_H)
|
||||
#define VERSION_H
|
||||
|
||||
const char* VERSION = "20180206";
|
||||
|
||||
#endif
|
13
README.md
Normal file
13
README.md
Normal file
@ -0,0 +1,13 @@
|
||||
These programs are clients for the NXDN networking now built into the MMDVM Host.
|
||||
|
||||
The Parrot is very simple minded and can only handle one client at a time and is therefore not suitable for use as a shared resource via the Internet.
|
||||
|
||||
The Gateway allows for use of NXDN Talk Groups to control the access to the various NXDN reflectors.
|
||||
|
||||
The Gateway has an ini file that contain the parameters for running the software. The filename of the ini file is passed as a parameter on the command line. The Parrot takes the UDP port number to listen on as an argument.
|
||||
|
||||
The MMDVM .ini file should have the IP address and port number of the client in the [NXDN Network] settings.
|
||||
|
||||
They build on 32-bit and 64-bit Linux as well as on Windows using Visual Studio 2017 on x86 and x64.
|
||||
|
||||
This software is licenced under the GPL v2 and is intended for amateur and educational use only. Use of this software for commercial purposes is strictly forbidden.
|
Loading…
Reference in New Issue
Block a user