Merge branch 'hessu-feature/dns-sd' into dev

This commit is contained in:
wb2osz 2021-01-01 19:57:06 -05:00
commit 14d6eed205
14 changed files with 545 additions and 21 deletions

View File

@ -157,6 +157,10 @@ elseif(APPLE)
set(CMAKE_MACOSX_RPATH ON) set(CMAKE_MACOSX_RPATH ON)
message(STATUS "RPATH support: ${CMAKE_MACOSX_RPATH}") message(STATUS "RPATH support: ${CMAKE_MACOSX_RPATH}")
# just blindly enable dns-sd
set(USE_MACOS_DNSSD ON)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUSE_MACOS_DNSSD")
elseif (WIN32) elseif (WIN32)
if(NOT VS2015 AND NOT VS2017) if(NOT VS2015 AND NOT VS2017)
message(FATAL_ERROR "You must use Microsoft Visual Studio 2015 or 2017 as compiler") message(FATAL_ERROR "You must use Microsoft Visual Studio 2015 or 2017 as compiler")
@ -277,6 +281,11 @@ if(LINUX)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUSE_CM108") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUSE_CM108")
endif() endif()
find_package(Avahi)
if(AVAHI_CLIENT_FOUND)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUSE_AVAHI_CLIENT")
endif()
elseif (NOT WIN32 AND NOT CYGWIN) elseif (NOT WIN32 AND NOT CYGWIN)
find_package(Portaudio REQUIRED) find_package(Portaudio REQUIRED)
if(PORTAUDIO_FOUND) if(PORTAUDIO_FOUND)

View File

@ -1,4 +1,4 @@

# Dire Wolf # # Dire Wolf #
### Decoded Information from Radio Emissions for Windows Or Linux Fans ### ### Decoded Information from Radio Emissions for Windows Or Linux Fans ###
@ -39,6 +39,7 @@ It can also be used as a virtual TNC for other applications such as [APRSIS32](h
Send periodic beacons to provide information to others. For tracking the location is provided by a GPS receiver. Send periodic beacons to provide information to others. For tracking the location is provided by a GPS receiver.
Build your own telemetry applications with the toolkit. Build your own telemetry applications with the toolkit.
- **APRStt Gateway.** - **APRStt Gateway.**
Very few hams have portable equipment for APRS but nearly everyone has a handheld radio that can send DTMF tones. APRStt allows a user, equipped with only DTMF (commonly known as Touch Tone) generation capability, to enter information into the global APRS data network. Responses can be sent by Morse Code or synthesized speech. Very few hams have portable equipment for APRS but nearly everyone has a handheld radio that can send DTMF tones. APRStt allows a user, equipped with only DTMF (commonly known as Touch Tone) generation capability, to enter information into the global APRS data network. Responses can be sent by Morse Code or synthesized speech.
@ -130,15 +131,17 @@ On Debian / Ubuntu / Raspbian / Raspberry Pi OS:
sudo apt-get install cmake sudo apt-get install cmake
sudo apt-get install libasound2-dev sudo apt-get install libasound2-dev
sudo apt-get install libudev-dev sudo apt-get install libudev-dev
sudo apt-get install libavahi-client-dev
Or on Red Hat / Fedora / CentOS: Or on Red Hat / Fedora / CentOS:
sudo yum install git sudo yum install git
sudo yum install gcc sudo yum install gcc
sudo yum install gcc-c++ sudo yum install gcc-c++
sudo yum install make sudo yum install make
sudo yum install alsa-lib-devel sudo yum install alsa-lib-devel
sudo yum install libudev-devel sudo yum install libudev-devel
sudo yum install avahi-devel
CentOS 6 & 7 currently have cmake 2.8 but we need 3.1 or later. CentOS 6 & 7 currently have cmake 2.8 but we need 3.1 or later.
First you need to enable the EPEL repository. Add a symlink if you don't already have the older version and want to type cmake rather than cmake3. First you need to enable the EPEL repository. Add a symlink if you don't already have the older version and want to type cmake rather than cmake3.

View File

@ -0,0 +1,19 @@
find_library(AVAHI_COMMON_LIBRARY NAMES avahi-common PATHS ${PC_AVAHI_CLIENT_LIBRARY_DIRS})
if(AVAHI_COMMON_LIBRARY)
set(AVAHI_COMMON_FOUND TRUE)
endif()
find_library(AVAHI_CLIENT_LIBRARY NAMES avahi-client PATHS ${PC_AVAHI_CLIENT_LIBRARY_DIRS})
if(AVAHI_CLIENT_LIBRARY)
set(AVAHI_CLIENT_FOUND TRUE)
endif()
FIND_PACKAGE_HANDLE_STANDARD_ARGS(AVAHI DEFAULT_MSG AVAHI_COMMON_FOUND AVAHI_CLIENT_FOUND)
if (AVAHI_FOUND)
set(AVAHI_INCLUDE_DIRS ${AVAHI_UI_INCLUDE_DIR})
set(AVAHI_LIBRARIES ${AVAHI_COMMON_LIBRARY} ${AVAHI_CLIENT_LIBRARY})
endif()
mark_as_advanced(AVAHI_INCLUDE_DIRS AVAHI_LIBRARIES)

View File

@ -1,4 +1,4 @@
# Documentation for Dire Wolf # # Documentation for Dire Wolf #
Click on the document name to view in your web browser or the link following to download the PDF file. Click on the document name to view in your web browser or the link following to download the PDF file.
@ -11,11 +11,11 @@ Brief summary of packet radio / APRS history and the capbilities of Dire Wolf.
## Essential Reading ## ## Essential Reading ##
- [**User Guide**](User-Guide.pdf) [ [*download*](../../../raw/dev/doc/User-Guide.pdf) ] - [**User Guide**](User-Guide.pdf) [ [*download*](../../../raw/master/doc/User-Guide.pdf) ]
This is your primary source of information about installation, operation, and configuration. This is your primary source of information about installation, operation, and configuration.
- [**Raspberry Pi APRS**](Raspberry-Pi-APRS.pdf) [ [*download*](../../../raw/dev/doc/Raspberry-Pi-APRS.pdf) ] - [**Raspberry Pi APRS**](Raspberry-Pi-APRS.pdf) [ [*download*](../../../raw/master/doc/Raspberry-Pi-APRS.pdf) ]
The Raspberry Pi has some special considerations that The Raspberry Pi has some special considerations that
make it different from other generic Linux systems. make it different from other generic Linux systems.
@ -46,38 +46,40 @@ These dive into more detail for specialized topics or typical usage scenarios.
- [**Successful APRS IGate Operation**](Successful-APRS-IGate-Operation.pdf) [ [*download*](../../../raw/dev/doc/Successful-APRS-IGate-Operation.pdf) ] - [**Successful APRS IGate Operation**](Successful-APRS-IGate-Operation.pdf) [ [*download*](../../../raw/dev/doc/Successful-APRS-IGate-Operation.pdf) ]
Dire Wolf can serve as a gateway between the APRS radio network and APRS-IS servers on the Internet. Dire Wolf can serve as a gateway between the APRS radio network and APRS-IS servers on the Internet.
This explains how it all works, proper configuration, and troubleshooting. This explains how it all works, proper configuration, and troubleshooting.
- [**Bluetooth KISS TNC**](Bluetooth-KISS-TNC.pdf) [ [*download*](../../../raw/dev/doc/Bluetooth-KISS-TNC.pdf) ] - [**Bluetooth KISS TNC**](Bluetooth-KISS-TNC.pdf) [ [*download*](../../../raw/master/doc/Bluetooth-KISS-TNC.pdf) ]
Eliminate the cable between your TNC and application. Use Bluetooth instead. Eliminate the cable between your TNC and application. Use Bluetooth instead.
- [**APRStt Implementation Notes**](APRStt-Implementation-Notes.pdf) [ [*download*](../../../raw/dev/doc/APRStt-Implementation-Notes.pdf) ] - [**APRStt Implementation Notes**](APRStt-Implementation-Notes.pdf) [ [*download*](../../../raw/master/doc/APRStt-Implementation-Notes.pdf) ]
Very few hams have portable equipment for APRS but nearly everyone has a handheld radio that can send DTMF tones. APRStt allows a user, equipped with only DTMF (commonly known as Touch Tone) generation capability, to enter information into the global APRS data network. Very few hams have portable equipment for APRS but nearly everyone has a handheld radio that can send DTMF tones. APRStt allows a user, equipped with only DTMF (commonly known as Touch Tone) generation capability, to enter information into the global APRS data network.
This document explains how the APRStt concept was implemented in the Dire Wolf application. This document explains how the APRStt concept was implemented in the Dire Wolf application.
- [**APRStt Interface for SARTrack**](APRStt-interface-for-SARTrack.pdf) [ [*download*](../../../raw/dev/doc/APRStt-interface-for-SARTrack.pdf) ]
- [**APRStt Interface for SARTrack**](APRStt-interface-for-SARTrack.pdf) [ [*download*](../../../raw/master/doc/APRStt-interface-for-SARTrack.pdf) ]
This example illustrates how APRStt can be integrated with other applications such as SARTrack, APRSISCE/32, YAAC, or Xastir. This example illustrates how APRStt can be integrated with other applications such as SARTrack, APRSISCE/32, YAAC, or Xastir.
- [**APRStt Listening Example**](APRStt-Listening-Example.pdf) [ [*download*](../../../raw/dev/doc/APRStt-Listening-Example.pdf) ] - [**APRStt Listening Example**](APRStt-Listening-Example.pdf) [ [*download*](../../../raw/master/doc/APRStt-Listening-Example.pdf) ]
WB4APR described a useful application for the [QIKCOM-2 Satallite Transponder](http://www.tapr.org/pipermail/aprssig/2015-November/045035.html). WB4APR described a useful application for the [QIKCOM-2 Satallite Transponder](http://www.tapr.org/pipermail/aprssig/2015-November/045035.html).
Dont have your own QIKCOM-2 Satellite Transponder? No Problem. You can do the same thing with an ordinary computer and the APRStt gateway built into Dire Wolf. Heres how. Dont have your own QIKCOM-2 Satellite Transponder? No Problem. You can do the same thing with an ordinary computer and the APRStt gateway built into Dire Wolf. Heres how.
- [**Raspberry Pi APRS Tracker**](Raspberry-Pi-APRS-Tracker.pdf) [ [*download*](../../../raw/dev/doc/Raspberry-Pi-APRS-Tracker.pdf) ] - [**Raspberry Pi APRS Tracker**](Raspberry-Pi-APRS-Tracker.pdf) [ [*download*](../../../raw/master/doc/Raspberry-Pi-APRS-Tracker.pdf) ]
Build a tracking device which transmits position from a GPS receiver. Build a tracking device which transmits position from a GPS receiver.
- [**Raspberry Pi SDR IGate**](Raspberry-Pi-SDR-IGate.pdf) [ [*download*](../../../raw/dev/doc/Raspberry-Pi-SDR-IGate.pdf) ] - [**Raspberry Pi SDR IGate**](Raspberry-Pi-SDR-IGate.pdf) [ [*download*](../../../raw/master/doc/Raspberry-Pi-SDR-IGate.pdf) ]
It's easy to build a receive-only APRS Internet Gateway (IGate) with only a Raspberry Pi and a software defined radio (RTL-SDR) dongle. Heres how. It's easy to build a receive-only APRS Internet Gateway (IGate) with only a Raspberry Pi and a software defined radio (RTL-SDR) dongle. Heres how.
- [**APRS Telemetry Toolkit**](APRS-Telemetry-Toolkit.pdf) [ [*download*](../../../raw/dev/doc/APRS-Telemetry-Toolkit.pdf) ] - [**APRS Telemetry Toolkit**](APRS-Telemetry-Toolkit.pdf) [ [*download*](../../../raw/master/doc/APRS-Telemetry-Toolkit.pdf) ]
Describes scripts and methods to generate telemetry. Describes scripts and methods to generate telemetry.
Includes a complete example of attaching an analog to Includes a complete example of attaching an analog to
@ -86,12 +88,12 @@ These dive into more detail for specialized topics or typical usage scenarios.
- [**2400 & 4800 bps PSK for APRS / Packet Radio**](2400-4800-PSK-for-APRS-Packet-Radio.pdf) [ [*download*](../../../raw/dev/doc/2400-4800-PSK-for-APRS-Packet-Radio.pdf) ] - [**2400 & 4800 bps PSK for APRS / Packet Radio**](2400-4800-PSK-for-APRS-Packet-Radio.pdf) [ [*download*](../../../raw/master/doc/2400-4800-PSK-for-APRS-Packet-Radio.pdf) ]
Double or quadruple your data rate by sending multiple bits at the same time. Double or quadruple your data rate by sending multiple bits at the same time.
- [**Going beyond 9600 baud**](Going-beyond-9600-baud.pdf) [ [*download*](../../../raw/dev/doc/Going-beyond-9600-baud.pdf) ] - [**Going beyond 9600 baud**](Going-beyond-9600-baud.pdf) [ [*download*](../../../raw/master/doc/Going-beyond-9600-baud.pdf) ]
Why stop at 9600 baud? Go faster if your soundcard and radio can handle it. Why stop at 9600 baud? Go faster if your soundcard and radio can handle it.
@ -120,7 +122,7 @@ These dive into more detail for specialized topics or typical usage scenarios.
There have been other occasional mentions of merging Ham Radio with the Internet of Things but only ad hoc incompatible narrowly focused applications. Here is a proposal for a standardized more flexible method so different systems can communicate with each other. There have been other occasional mentions of merging Ham Radio with the Internet of Things but only ad hoc incompatible narrowly focused applications. Here is a proposal for a standardized more flexible method so different systems can communicate with each other.
- [**A Better APRS Packet Demodulator, part 1, 1200 baud**](A-Better-APRS-Packet-Demodulator-Part-1-1200-baud.pdf) [ [*download*](../../../raw/dev/doc/A-Better-APRS-Packet-Demodulator-Part-1-1200-baud.pdf) ] - [**A Better APRS Packet Demodulator, part 1, 1200 baud**](A-Better-APRS-Packet-Demodulator-Part-1-1200-baud.pdf) [ [*download*](../../../raw/master/doc/A-Better-APRS-Packet-Demodulator-Part-1-1200-baud.pdf) ]
Sometimes it's a little mystifying why an Sometimes it's a little mystifying why an
APRS / AX.25 Packet TNC will decode some signals APRS / AX.25 Packet TNC will decode some signals
@ -132,7 +134,7 @@ and a couple things that can be done about it.
- [**A Better APRS Packet Demodulator, part 2, 9600 baud**](A-Better-APRS-Packet-Demodulator-Part-2-9600-baud.pdf) [ [*download*](../../../raw/dev/doc/A-Better-APRS-Packet-Demodulator-Part-2-9600-baud.pdf) ] - [**A Better APRS Packet Demodulator, part 2, 9600 baud**](A-Better-APRS-Packet-Demodulator-Part-2-9600-baud.pdf) [ [*download*](../../../raw/master/doc/A-Better-APRS-Packet-Demodulator-Part-2-9600-baud.pdf) ]
In the first part of this series we discussed 1200 baud audio frequency shift keying (AFSK). The mismatch In the first part of this series we discussed 1200 baud audio frequency shift keying (AFSK). The mismatch
between FM transmitter pre-emphasis and the between FM transmitter pre-emphasis and the
@ -141,13 +143,13 @@ and a couple things that can be done about it.
This makes it more difficult to demodulate them accurately. This makes it more difficult to demodulate them accurately.
9600 baud operation is an entirely different animal. ... 9600 baud operation is an entirely different animal. ...
- [**WA8LMF TNC Test CD Results a.k.a. Battle of the TNCs**](WA8LMF-TNC-Test-CD-Results.pdf) [ [*download*](../../../raw/dev/doc/WA8LMF-TNC-Test-CD-Results.pdf) ] - [**WA8LMF TNC Test CD Results a.k.a. Battle of the TNCs**](WA8LMF-TNC-Test-CD-Results.pdf) [ [*download*](../../../raw/master/doc/WA8LMF-TNC-Test-CD-Results.pdf) ]
How can we compare how well the TNCs perform under real world conditions? How can we compare how well the TNCs perform under real world conditions?
The de facto standard of measurement is the number of packets decoded from [WA8LMFs TNC Test CD](http://wa8lmf.net/TNCtest/index.htm). The de facto standard of measurement is the number of packets decoded from [WA8LMFs TNC Test CD](http://wa8lmf.net/TNCtest/index.htm).
Many have published the number of packets they have been able to decode from this test. Here they are, all gathered in one place, for your reading pleasure. Many have published the number of packets they have been able to decode from this test. Here they are, all gathered in one place, for your reading pleasure.
- [**A Closer Look at the WA8LMF TNC Test CD**](A-Closer-Look-at-the-WA8LMF-TNC-Test-CD.pdf) [ [*download*](../../../raw/dev/doc/A-Closer-Look-at-the-WA8LMF-TNC-Test-CD.pdf) ] - [**A Closer Look at the WA8LMF TNC Test CD**](A-Closer-Look-at-the-WA8LMF-TNC-Test-CD.pdf) [ [*download*](../../../raw/master/doc/A-Closer-Look-at-the-WA8LMF-TNC-Test-CD.pdf) ]
Here, we take a closer look at some of the frames on the TNC Test CD in hopes of gaining some insights into why some are easily decoded and others are more difficult. Here, we take a closer look at some of the frames on the TNC Test CD in hopes of gaining some insights into why some are easily decoded and others are more difficult.
There are a lot of ugly signals out there. Many can be improved by decreasing the transmit volume. Others are just plain weird and you have to wonder how they are being generated. There are a lot of ugly signals out there. Many can be improved by decreasing the transmit volume. Others are just plain weird and you have to wonder how they are being generated.

View File

@ -109,6 +109,12 @@ if(LINUX)
cm108.c cm108.c
) )
endif() endif()
if(AVAHI_CLIENT_FOUND)
list(APPEND direwolf_SOURCES
dns_sd_common.c
dns_sd_avahi.c
)
endif()
elseif(WIN32 OR CYGWIN) # windows elseif(WIN32 OR CYGWIN) # windows
list(APPEND direwolf_SOURCES list(APPEND direwolf_SOURCES
audio_win.c audio_win.c
@ -124,6 +130,12 @@ if(LINUX)
list(APPEND direwolf_SOURCES list(APPEND direwolf_SOURCES
audio_portaudio.c audio_portaudio.c
) )
if(USE_MACOS_DNSSD)
list(APPEND direwolf_SOURCES
dns_sd_common.c
dns_sd_macos.c
)
endif()
endif() endif()
add_executable(direwolf add_executable(direwolf
@ -140,6 +152,7 @@ target_link_libraries(direwolf
${ALSA_LIBRARIES} ${ALSA_LIBRARIES}
${UDEV_LIBRARIES} ${UDEV_LIBRARIES}
${PORTAUDIO_LIBRARIES} ${PORTAUDIO_LIBRARIES}
${AVAHI_LIBRARIES}
) )
if(WIN32 OR CYGWIN) if(WIN32 OR CYGWIN)

View File

@ -856,6 +856,8 @@ void config_init (char *fname, struct audio_s *p_audio_config,
p_misc_config->enable_kiss_pt = 0; /* -p option */ p_misc_config->enable_kiss_pt = 0; /* -p option */
p_misc_config->kiss_copy = 0; p_misc_config->kiss_copy = 0;
p_misc_config->dns_sd_enabled = 1;
/* Defaults from http://info.aprs.net/index.php?title=SmartBeaconing */ /* Defaults from http://info.aprs.net/index.php?title=SmartBeaconing */
p_misc_config->sb_configured = 0; /* TRUE if SmartBeaconing is configured. */ p_misc_config->sb_configured = 0; /* TRUE if SmartBeaconing is configured. */
@ -4564,6 +4566,43 @@ void config_init (char *fname, struct audio_s *p_audio_config,
} }
/*
* DNSSD - Enable or disable (1/0) dns-sd, DNS Service Discovery announcements
* DNSSDNAME - Set DNS-SD service name, defaults to "Dire Wolf on <hostname>"
*/
else if (strcasecmp(t, "DNSSD") == 0) {
int n;
t = split(NULL,0);
if (t == NULL) {
text_color_set(DW_COLOR_ERROR);
dw_printf ("Line %d: Missing integer value for DNSSD command.\n", line);
continue;
}
n = atoi(t);
if (n == 0 || n == 1) {
p_misc_config->dns_sd_enabled = n;
} else {
p_misc_config->dns_sd_enabled = 0;
text_color_set(DW_COLOR_ERROR);
dw_printf ("Line %d: Invalid integer value for DNSSD. Disabling dns-sd.\n", line);
}
}
else if (strcasecmp(t, "DNSSDNAME") == 0) {
t = split(NULL, 1);
if (t == NULL) {
text_color_set(DW_COLOR_ERROR);
dw_printf ("Line %d: Missing service name for DNSSDNAME.\n", line);
continue;
}
else {
strlcpy(p_misc_config->dns_sd_name, t, sizeof(p_misc_config->dns_sd_name));
}
}
/* /*
* GPSNMEA - Device name for reading from GPS receiver. * GPSNMEA - Device name for reading from GPS receiver.
*/ */

View File

@ -88,6 +88,9 @@ struct misc_config_s {
char log_path[80]; /* Either directory or full file name depending on above. */ char log_path[80]; /* Either directory or full file name depending on above. */
int dns_sd_enabled; /* DNS Service Discovery announcement enabled. */
char dns_sd_name[64]; /* Name announced on dns-sd; defaults to "Dire Wolf on <hostname>" */
int sb_configured; /* TRUE if SmartBeaconing is configured. */ int sb_configured; /* TRUE if SmartBeaconing is configured. */
int sb_fast_speed; /* MPH */ int sb_fast_speed; /* MPH */
int sb_fast_rate; /* seconds */ int sb_fast_rate; /* seconds */

View File

@ -125,6 +125,7 @@
#include "dtime_now.h" #include "dtime_now.h"
#include "fx25.h" #include "fx25.h"
#include "dwsock.h" #include "dwsock.h"
#include "dns_sd_dw.h"
//static int idx_decoded = 0; //static int idx_decoded = 0;
@ -1029,6 +1030,11 @@ int main (int argc, char *argv[])
server_init (&audio_config, &misc_config); server_init (&audio_config, &misc_config);
kissnet_init (&misc_config); kissnet_init (&misc_config);
#if (USE_AVAHI_CLIENT|USE_MACOS_DNSSD)
if (misc_config.kiss_port > 0 && misc_config.dns_sd_enabled)
dns_sd_announce(&misc_config);
#endif
/* /*
* Create a pseudo terminal and KISS TNC emulator. * Create a pseudo terminal and KISS TNC emulator.
*/ */

259
src/dns_sd_avahi.c Normal file
View File

@ -0,0 +1,259 @@
//
// This file is part of Dire Wolf, an amateur radio packet TNC.
//
// Copyright (C) 2020 Heikki Hannikainen, OH7LZB
//
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
/*------------------------------------------------------------------
*
* Module: dns_sd_avahi.c
*
* Purpose: Announce the KISS over TCP service using DNS-SD via Avahi
*
* Description:
*
* Most people have typed in enough IP addresses and ports by now, and
* would rather just select an available TNC that is automatically
* discovered on the local network. Even more so on a mobile device
* such an Android or iOS phone or tablet.
*
* On Linux, the announcement can be made through Avahi, the mDNS
* framework commonly deployed on Linux systems.
*
* This is largely based on the publishing example of the Avahi library.
*/
#ifdef USE_AVAHI_CLIENT
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <avahi-client/client.h>
#include <avahi-client/publish.h>
#include <avahi-common/simple-watch.h>
#include <avahi-common/alternative.h>
#include <avahi-common/malloc.h>
#include <avahi-common/error.h>
#include "dns_sd_dw.h"
#include "dns_sd_common.h"
#include "textcolor.h"
static AvahiEntryGroup *group = NULL;
static AvahiSimplePoll *simple_poll = NULL;
static AvahiClient *client = NULL;
static char *name = NULL;
static int kiss_port = 0;
pthread_t avahi_thread;
static void create_services(AvahiClient *c);
#define PRINT_PREFIX "DNS-SD: Avahi: "
static void entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state, AVAHI_GCC_UNUSED void *userdata)
{
assert(g == group || group == NULL);
group = g;
/* Called whenever the entry group state changes */
switch (state) {
case AVAHI_ENTRY_GROUP_ESTABLISHED :
/* The entry group has been established successfully */
text_color_set(DW_COLOR_INFO);
dw_printf(PRINT_PREFIX "Service '%s' successfully registered.\n", name);
break;
case AVAHI_ENTRY_GROUP_COLLISION: {
char *n;
/* A service name collision with a remote service
* happened. Let's pick a new name. */
n = avahi_alternative_service_name(name);
avahi_free(name);
name = n;
text_color_set(DW_COLOR_INFO);
dw_printf(PRINT_PREFIX "Service name collision, renaming service to '%s'\n", name);
/* And recreate the services */
create_services(avahi_entry_group_get_client(g));
break;
}
case AVAHI_ENTRY_GROUP_FAILURE:
text_color_set(DW_COLOR_ERROR);
dw_printf(PRINT_PREFIX "Entry group failure: %s\n", avahi_strerror(avahi_client_errno(avahi_entry_group_get_client(g))));
/* Some kind of failure happened while we were registering our services */
avahi_simple_poll_quit(simple_poll);
break;
case AVAHI_ENTRY_GROUP_UNCOMMITED:
case AVAHI_ENTRY_GROUP_REGISTERING:
;
}
}
static void create_services(AvahiClient *c)
{
char *n;
int ret;
assert(c);
/* If this is the first time we're called, let's create a new
* entry group if necessary */
if (!group) {
if (!(group = avahi_entry_group_new(c, entry_group_callback, NULL))) {
text_color_set(DW_COLOR_ERROR);
dw_printf(PRINT_PREFIX "avahi_entry_group_new() failed: %s\n", avahi_strerror(avahi_client_errno(c)));
goto fail;
}
} else {
avahi_entry_group_reset(group);
}
/* If the group is empty (either because it was just created, or
* because it was reset previously, add our entries. */
if (avahi_entry_group_is_empty(group)) {
text_color_set(DW_COLOR_INFO);
dw_printf(PRINT_PREFIX "Announcing KISS TCP on port %d as '%s'\n", kiss_port, name);
/* Announce with AVAHI_PROTO_INET instead of AVAHI_PROTO_UNSPEC, since Dire Wolf currently
* only listens on IPv4.
*/
if ((ret = avahi_entry_group_add_service(group, AVAHI_IF_UNSPEC, AVAHI_PROTO_INET, 0, name, DNS_SD_SERVICE, NULL, NULL, kiss_port, NULL)) < 0) {
if (ret == AVAHI_ERR_COLLISION)
goto collision;
text_color_set(DW_COLOR_ERROR);
dw_printf(PRINT_PREFIX "Failed to add _kiss-tnc._tcp service: %s\n", avahi_strerror(ret));
goto fail;
}
/* Tell the server to register the service */
if ((ret = avahi_entry_group_commit(group)) < 0) {
text_color_set(DW_COLOR_ERROR);
dw_printf(PRINT_PREFIX "Failed to commit entry group: %s\n", avahi_strerror(ret));
goto fail;
}
}
return;
collision:
/* A service name collision with a local service happened. Let's
* pick a new name */
n = avahi_alternative_service_name(name);
avahi_free(name);
name = n;
text_color_set(DW_COLOR_INFO);
dw_printf(PRINT_PREFIX "Service name collision, renaming service to '%s'\n", name);
avahi_entry_group_reset(group);
create_services(c);
return;
fail:
avahi_simple_poll_quit(simple_poll);
}
static void client_callback(AvahiClient *c, AvahiClientState state, AVAHI_GCC_UNUSED void * userdata)
{
assert(c);
/* Called whenever the client or server state changes */
switch (state) {
case AVAHI_CLIENT_S_RUNNING:
/* The server has startup successfully and registered its host
* name on the network, so it's time to create our services */
create_services(c);
break;
case AVAHI_CLIENT_FAILURE:
text_color_set(DW_COLOR_ERROR);
dw_printf(PRINT_PREFIX "Client failure: %s\n", avahi_strerror(avahi_client_errno(c)));
avahi_simple_poll_quit(simple_poll);
break;
case AVAHI_CLIENT_S_COLLISION:
/* Let's drop our registered services. When the server is back
* in AVAHI_SERVER_RUNNING state we will register them
* again with the new host name. */
case AVAHI_CLIENT_S_REGISTERING:
/* The server records are now being established. This
* might be caused by a host name change. We need to wait
* for our own records to register until the host name is
* properly esatblished. */
if (group)
avahi_entry_group_reset(group);
break;
case AVAHI_CLIENT_CONNECTING:
;
}
}
static void cleanup(void)
{
/* Cleanup things */
if (client)
avahi_client_free(client);
if (simple_poll)
avahi_simple_poll_free(simple_poll);
avahi_free(name);
}
static void *avahi_mainloop(void *arg)
{
/* Run the main loop */
avahi_simple_poll_loop(simple_poll);
cleanup();
return NULL;
}
void dns_sd_announce (struct misc_config_s *mc)
{
text_color_set(DW_COLOR_DEBUG);
kiss_port = mc->kiss_port;
int error;
/* Allocate main loop object */
if (!(simple_poll = avahi_simple_poll_new())) {
text_color_set(DW_COLOR_ERROR);
dw_printf(PRINT_PREFIX "Failed to create Avahi simple poll object.\n");
goto fail;
}
if (mc->dns_sd_name[0]) {
name = avahi_strdup(mc->dns_sd_name);
} else {
name = dns_sd_default_service_name();
}
/* Allocate a new client */
client = avahi_client_new(avahi_simple_poll_get(simple_poll), 0, client_callback, NULL, &error);
/* Check wether creating the client object succeeded */
if (!client) {
text_color_set(DW_COLOR_ERROR);
dw_printf(PRINT_PREFIX "Failed to create Avahi client: %s\n", avahi_strerror(error));
goto fail;
}
pthread_create(&avahi_thread, NULL, &avahi_mainloop, NULL);
return;
fail:
cleanup();
}
#endif // USE_AVAHI_CLIENT

65
src/dns_sd_common.c Normal file
View File

@ -0,0 +1,65 @@
//
// This file is part of Dire Wolf, an amateur radio packet TNC.
//
// Copyright (C) 2020 Heikki Hannikainen, OH7LZB
//
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
/*------------------------------------------------------------------
*
* Module: dns_sd_common.c
*
* Purpose: Announce the KISS over TCP service using DNS-SD, common functions
*
* Description:
*
* Most people have typed in enough IP addresses and ports by now, and
* would rather just select an available TNC that is automatically
* discovered on the local network. Even more so on a mobile device
* such an Android or iOS phone or tablet.
*
* This module contains common functions needed on Linux and MacOS.
*/
#include <stdio.h>
#include <unistd.h>
#include <string.h>
/* Get a default service name to publish. By default,
* "Dire Wolf on <hostname>", or just "Dire Wolf" if hostname cannot
* be obtained.
*/
char *dns_sd_default_service_name(void)
{
char hostname[51];
char sname[64];
int i = gethostname(hostname, sizeof(hostname));
if (i == 0) {
hostname[sizeof(hostname)-1] = 0;
// on some systems, an FQDN is returned; remove domain part
char *dot = strchr(hostname, '.');
if (dot)
*dot = 0;
snprintf(sname, sizeof(sname), "Dire Wolf on %s", hostname);
return strdup(sname);
}
return strdup("Dire Wolf");
}

7
src/dns_sd_common.h Normal file
View File

@ -0,0 +1,7 @@
#if (USE_AVAHI_CLIENT|USE_MACOS_DNSSD)
char *dns_sd_default_service_name(void);
#endif

10
src/dns_sd_dw.h Normal file
View File

@ -0,0 +1,10 @@
#if (USE_AVAHI_CLIENT|USE_MACOS_DNSSD)
#include "config.h"
#define DNS_SD_SERVICE "_kiss-tnc._tcp"
void dns_sd_announce (struct misc_config_s *mc);
#endif // USE_AVAHI_CLIENT

88
src/dns_sd_macos.c Normal file
View File

@ -0,0 +1,88 @@
//
// This file is part of Dire Wolf, an amateur radio packet TNC.
//
// Copyright (C) 2020 Heikki Hannikainen, OH7LZB
//
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
/*------------------------------------------------------------------
*
* Module: dns_sd_macos.c
*
* Purpose: Announce the KISS over TCP service using MacOS dns-sd
*
* Description:
*
* Most people have typed in enough IP addresses and ports by now, and
* would rather just select an available TNC that is automatically
* discovered on the local network. Even more so on a mobile device
* such an Android or iOS phone or tablet.
*
* On MacOs, the announcement can be made through dns-sd.
*/
#ifdef USE_MACOS_DNSSD
#include <string.h>
#include <dns_sd.h>
#include <arpa/inet.h>
#include "dns_sd_dw.h"
#include "dns_sd_common.h"
#include "textcolor.h"
static char *name = NULL;
static void registerServiceCallBack(DNSServiceRef sdRef, DNSServiceFlags flags, DNSServiceErrorType errorCode,
const char* name, const char* regType, const char* domain, void* context)
{
if (errorCode == kDNSServiceErr_NoError) {
text_color_set(DW_COLOR_INFO);
dw_printf("DNS-SD: Successfully registered '%s'\n", name);
} else {
text_color_set(DW_COLOR_ERROR);
dw_printf("DNS-SD: Failed to register '%s': %d\n", name, errorCode);
}
}
void dns_sd_announce (struct misc_config_s *mc)
{
int kiss_port = mc->kiss_port;
if (mc->dns_sd_name[0]) {
name = strdup(mc->dns_sd_name);
} else {
name = dns_sd_default_service_name();
}
uint16_t port_nw = htons(kiss_port);
DNSServiceRef registerRef;
DNSServiceErrorType err = DNSServiceRegister(
&registerRef, 0, 0, name, DNS_SD_SERVICE, NULL, NULL,
port_nw, 0, NULL, registerServiceCallBack, NULL);
if (err == kDNSServiceErr_NoError) {
text_color_set(DW_COLOR_INFO);
dw_printf("DNS-SD: Announcing KISS TCP on port %d as '%s'\n", kiss_port, name);
} else {
text_color_set(DW_COLOR_ERROR);
dw_printf("DNS-SD: Failed to announce '%s': %d\n", name, err);
}
}
#endif // USE_MACOS_DNSSD

View File

@ -56,6 +56,7 @@
#include <gps.h> #include <gps.h>
// An incompatibility was introduced with version 7 // An incompatibility was introduced with version 7
// and again with 9 and again with 10. // and again with 9 and again with 10.