171 lines
4.1 KiB
C++
171 lines
4.1 KiB
C++
/*
|
|
* Copyright (C) 2022 Robin Gareus <robin@gareus.org>
|
|
*
|
|
* 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*/
|
|
|
|
#include "pbd/compose.h"
|
|
#include "pbd/error.h"
|
|
#include "pbd/file_utils.h"
|
|
|
|
#include "ardour/filesystem_paths.h"
|
|
#include "ardour/zeroconf.h"
|
|
|
|
#include "pbd/i18n.h"
|
|
|
|
using namespace ARDOUR;
|
|
|
|
ZeroConf::ZeroConf (std::string const& type, uint16_t port, std::string const& host)
|
|
: _type (type)
|
|
, _port (port)
|
|
, _host (host)
|
|
#ifdef __APPLE__
|
|
, _source_id (0)
|
|
, _gio_channel (NULL)
|
|
#else
|
|
, _avahi (NULL)
|
|
#endif
|
|
{
|
|
start ();
|
|
}
|
|
|
|
ZeroConf::~ZeroConf ()
|
|
{
|
|
stop ();
|
|
}
|
|
|
|
#ifdef __APPLE__
|
|
|
|
void
|
|
ZeroConf::stop ()
|
|
{
|
|
if (_gio_channel) {
|
|
g_source_remove (_source_id);
|
|
g_io_channel_unref (_gio_channel);
|
|
}
|
|
DNSServiceRefDeallocate (_ref);
|
|
}
|
|
|
|
static void
|
|
dns_callback (DNSServiceRef sdref,
|
|
DNSServiceFlags flags,
|
|
DNSServiceErrorType errorCode,
|
|
const char* name,
|
|
const char* regtype,
|
|
const char* domain, void* context)
|
|
{
|
|
if (errorCode == kDNSServiceErr_NoError) {
|
|
PBD::info << string_compose (_("ZeroConf registered: %1 %2 %3"), name, regtype, domain) << endmsg;
|
|
} else {
|
|
PBD::info << _("ZeroConf registration failed") << endmsg;
|
|
}
|
|
}
|
|
|
|
gboolean
|
|
ZeroConf::event (GIOChannel* source,
|
|
GIOCondition condition,
|
|
gpointer data)
|
|
{
|
|
ZeroConf* self = reinterpret_cast<ZeroConf*> (data);
|
|
// assert (_fd == g_io_channel_unix_get_fd (source));
|
|
|
|
if (condition & ~G_IO_IN) {
|
|
/* remove on error */
|
|
return false;
|
|
} else {
|
|
if (DNSServiceProcessResult (self->_ref) != kDNSServiceErr_NoError) {
|
|
/* ZeroConf Error in data callback */
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
|
|
bool
|
|
ZeroConf::start ()
|
|
{
|
|
if (kDNSServiceErr_NoError != DNSServiceRegister (&_ref, /*flags*/ 0, /*interfaceIndex*/ 0, /*name*/ NULL, _type.c_str (),
|
|
/*domain*/ NULL, _host.empty () ? NULL : _host.c_str (), g_htons (_port),
|
|
/*txtlen*/ 0, /*TXT*/ NULL, dns_callback, this)) {
|
|
return false;
|
|
}
|
|
|
|
int fd = DNSServiceRefSockFD (_ref);
|
|
_gio_channel = g_io_channel_unix_new (fd);
|
|
_source_id = g_io_add_watch (_gio_channel, (GIOCondition) (G_IO_IN | G_IO_ERR | G_IO_HUP), ZeroConf::event, this);
|
|
return true;
|
|
}
|
|
|
|
#elif defined PLATFORM_WINDOWS
|
|
|
|
/* in theory dns_sd API also works on Windows 10+
|
|
* windns.h and dnsapi.dll (mingw does not currently support this),
|
|
* besides we still offer windows 7 compatible binaries.
|
|
*
|
|
* alternatively https://github.com/videolabs/libmicrodns
|
|
* (which will also be handy on Linux, rather than using a shell script)
|
|
*/
|
|
|
|
bool
|
|
ZeroConf::start ()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
void
|
|
ZeroConf::stop ()
|
|
{
|
|
}
|
|
|
|
#else
|
|
|
|
bool
|
|
ZeroConf::start ()
|
|
{
|
|
std::string avahi_exec;
|
|
|
|
PBD::Searchpath sp (ARDOUR::ardour_dll_directory ());
|
|
if (!PBD::find_file (sp, "ardour-avahi", avahi_exec)) {
|
|
PBD::warning << _("ardour-avahi tool was not found.") << endmsg;
|
|
return false;
|
|
}
|
|
|
|
char** argp;
|
|
char tmp[128];
|
|
argp = (char**)calloc (5, sizeof (char*));
|
|
argp[0] = strdup (avahi_exec.c_str ());
|
|
snprintf (tmp, sizeof (tmp), "%d", _port);
|
|
argp[1] = strdup (tmp);
|
|
argp[2] = strdup (_type.c_str ());
|
|
snprintf (tmp, sizeof (tmp), "%d", getpid ());
|
|
argp[3] = strdup (tmp);
|
|
argp[4] = 0;
|
|
|
|
_avahi = new ARDOUR::SystemExec (avahi_exec, argp);
|
|
if (_avahi->start (SystemExec::ShareWithParent)) {
|
|
return false;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void
|
|
ZeroConf::stop ()
|
|
{
|
|
ARDOUR::SystemExec* tmp = _avahi;
|
|
_avahi = 0;
|
|
delete tmp;
|
|
}
|
|
#endif
|