Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DNS SD implementation for macOS (Bonjour) #388

Merged
merged 3 commits into from
Feb 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 38 additions & 24 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -148,12 +148,12 @@ endif()

if(WITH_LOCAL_BACKEND)
add_definitions(-DLOCAL_BACKEND=1)
set(LIBIIO_CFILES ${LIBIIO_CFILES} local.c)
list(APPEND LIBIIO_CFILES local.c)

# Link with librt if present
find_library(LIBRT_LIBRARIES rt)
if (LIBRT_LIBRARIES)
set(LIBS_TO_LINK ${LIBS_TO_LINK} ${LIBRT_LIBRARIES})
list(APPEND LIBS_TO_LINK ${LIBRT_LIBRARIES})
endif()

option(WITH_LOCAL_CONFIG "Read local context attributes from /etc/libiio.ini" OFF)
Expand All @@ -164,7 +164,7 @@ if(WITH_LOCAL_BACKEND)
message(SEND_ERROR "WITH_LOCAL_CONFIG option requires libini to be installed")
else()
include_directories(${LIBINI_INCLUDE_DIR})
set(LIBS_TO_LINK ${LIBS_TO_LINK} ${LIBINI_LIBRARIES})
list(APPEND LIBS_TO_LINK ${LIBINI_LIBRARIES})
endif()
endif()
endif()
Expand All @@ -178,8 +178,8 @@ if (LIBUSB_LIBRARIES AND LIBUSB_INCLUDE_DIR)

if(WITH_USB_BACKEND)
add_definitions(-DUSB_BACKEND=1)
set(LIBIIO_CFILES ${LIBIIO_CFILES} usb.c)
set(LIBS_TO_LINK ${LIBS_TO_LINK} ${LIBUSB_LIBRARIES})
list(APPEND LIBIIO_CFILES usb.c)
list(APPEND LIBS_TO_LINK ${LIBUSB_LIBRARIES})
set(IIOD_CLIENT 1)
set(NEED_LIBXML2 1)
set(NEED_THREADS 1)
Expand All @@ -188,10 +188,8 @@ if (LIBUSB_LIBRARIES AND LIBUSB_INCLUDE_DIR)

set(TEMP ${CMAKE_REQUIRED_LIBRARIES})
set(TEMP1 ${CMAKE_REQUIRED_INCLUDES})
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}
${LIBUSB_LIBRARIES})
set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES}
${LIBUSB_INCLUDE_DIR})
list(APPEND CMAKE_REQUIRED_LIBRARIES ${LIBUSB_LIBRARIES})
list(APPEND CMAKE_REQUIRED_INCLUDES ${LIBUSB_INCLUDE_DIR})
check_symbol_exists(libusb_get_version libusb.h
HAS_LIBUSB_GETVERSION)
set(CMAKE_REQUIRED_LIBRARIES ${TEMP})
Expand All @@ -214,8 +212,8 @@ if (LIBSERIALPORT_LIBRARIES AND LIBSERIALPORT_INCLUDE_DIR)
SET(WITH_SERIAL_BACKEND OFF)
else()
add_definitions(-DSERIAL_BACKEND=1)
set(LIBIIO_CFILES ${LIBIIO_CFILES} serial.c)
set(LIBS_TO_LINK ${LIBS_TO_LINK} ${LIBSERIALPORT_LIBRARIES})
list(APPEND LIBIIO_CFILES serial.c)
list(APPEND LIBS_TO_LINK ${LIBSERIALPORT_LIBRARIES})

set(NEED_THREADS 1)
set(IIOD_CLIENT 1)
Expand All @@ -231,7 +229,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
if(WITH_NETWORK_BACKEND)
message(STATUS "Building with Network back end support")
if (WIN32)
set(LIBS_TO_LINK ${LIBS_TO_LINK} wsock32 ws2_32)
list(APPEND LIBS_TO_LINK wsock32 ws2_32)
endif()

if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
Expand All @@ -251,18 +249,33 @@ if(WITH_NETWORK_BACKEND)
endif()

add_definitions(-DNETWORK_BACKEND=1)
set(LIBIIO_CFILES ${LIBIIO_CFILES} network.c)
list(APPEND LIBIIO_CFILES network.c)

find_library(AVAHI_CLIENT_LIBRARIES avahi-client)
find_library(AVAHI_COMMON_LIBRARIES avahi-common)
if(AVAHI_CLIENT_LIBRARIES AND AVAHI_COMMON_LIBRARIES)
message(STATUS "Building with Avahi, a zero-configuration networking (zeroconf) implementation")
set(HAVE_AVAHI ON)
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
find_library(CORE_SERVICES CoreServices)

message(STATUS "Building with CFNetServices, an Apple DNS SD implementation")
set(HAVE_DNS_SD ON)

list(APPEND LIBIIO_CFILES dns_sd_bonjour.c)
list(APPEND LIBS_TO_LINK ${CORE_SERVICES} )

elseif(AVAHI_CLIENT_LIBRARIES AND AVAHI_COMMON_LIBRARIES)
message(STATUS "Building with Avahi, a DNS SD implementation")
set(HAVE_DNS_SD ON)

list(APPEND LIBIIO_CFILES dns_sd_avahi.c)
set(AVAHI_LIBRARIES ${AVAHI_CLIENT_LIBRARIES} ${AVAHI_COMMON_LIBRARIES})
set(LIBS_TO_LINK ${LIBS_TO_LINK} ${AVAHI_LIBRARIES})
list(APPEND LIBS_TO_LINK ${AVAHI_LIBRARIES})
set(AVAHI_SERVICE_INSTALL_DIR /etc/avahi/services/ CACHE PATH "default install path for Avahi service files")
else()
message(STATUS "Building without Avahi (zeroconf) support")
message(STATUS "Building without DNS-SD (Zeroconf) support")
endif()

if (HAVE_DNS_SD)
add_definitions(-DHAVE_DNS_SD=1)
endif()

set(NEED_THREADS 1)
Expand All @@ -289,10 +302,11 @@ if (LIBXML2_FOUND)
option(WITH_XML_BACKEND "Enable the XML backend" ON)

if (WITH_XML_BACKEND)
set(LIBIIO_CFILES ${LIBIIO_CFILES} xml.c)
list(APPEND LIBIIO_CFILES xml.c)

add_definitions(${LIBXML2_DEFINITIONS} -DXML_BACKEND=1)
include_directories(${LIBXML2_INCLUDE_DIR})
set(LIBS_TO_LINK ${LIBS_TO_LINK} ${LIBXML2_LIBRARIES})
list(APPEND LIBS_TO_LINK ${LIBXML2_LIBRARIES})
endif()
endif()

Expand All @@ -305,19 +319,19 @@ if (NEED_THREADS)
find_library(PTHREAD_LIBRARIES pthread)

if (PTHREAD_LIBRARIES)
set(LIBS_TO_LINK ${LIBS_TO_LINK} ${PTHREAD_LIBRARIES})
list(APPEND LIBS_TO_LINK ${PTHREAD_LIBRARIES})
else()
message(WARNING "pthread library not found; support for threads will be disabled")
set(NO_THREADS ON)
endif()
else()
endif()

set(LIBIIO_CFILES ${LIBIIO_CFILES} lock.c)
list(APPEND LIBIIO_CFILES lock.c)
endif()

if (IIOD_CLIENT)
set(LIBIIO_CFILES ${LIBIIO_CFILES} iiod-client.c)
list(APPEND LIBIIO_CFILES iiod-client.c)
if (HAVE_AVAHI)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/iio.service DESTINATION ${AVAHI_SERVICE_INSTALL_DIR})
endif()
Expand All @@ -341,7 +355,7 @@ option(MATLAB_BINDINGS "Build MATLAB bindings" OFF)
add_subdirectory(bindings)

if (WITH_MATLAB_BINDINGS_API)
set(LIBIIO_EXTRA_HEADERS ${LIBIIO_EXTRA_HEADERS} bindings/matlab/iio-wrapper.h)
list(APPEND LIBIIO_EXTRA_HEADERS bindings/matlab/iio-wrapper.h)
add_definitions(-DMATLAB_BINDINGS_API=1)
endif()

Expand Down
142 changes: 142 additions & 0 deletions dns_sd_avahi.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/*
* libiio - Library for interfacing industrial I/O (IIO) devices
*
* Copyright (C) 2014-2020 Analog Devices, Inc.
* Author: Paul Cercueil <[email protected]>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* */

#include "iio.h"

#include <errno.h>
#include <stdbool.h>
#include <string.h>
#include <time.h>

#include <avahi-common/error.h>
#include <avahi-common/simple-watch.h>
#include <avahi-client/client.h>
#include <avahi-client/lookup.h>

#include "debug.h"

struct avahi_discovery_data {
AvahiSimplePoll *poll;
AvahiAddress *address;
uint16_t *port;
bool found, resolved;
};

static void __avahi_resolver_cb(AvahiServiceResolver *resolver,
__notused AvahiIfIndex iface, __notused AvahiProtocol proto,
__notused AvahiResolverEvent event, __notused const char *name,
__notused const char *type, __notused const char *domain,
__notused const char *host_name, const AvahiAddress *address,
uint16_t port, __notused AvahiStringList *txt,
__notused AvahiLookupResultFlags flags, void *d)
{
struct avahi_discovery_data *ddata = (struct avahi_discovery_data *) d;

memcpy(ddata->address, address, sizeof(*address));
*ddata->port = port;
ddata->resolved = true;
avahi_service_resolver_free(resolver);
}

static void __avahi_browser_cb(AvahiServiceBrowser *browser,
AvahiIfIndex iface, AvahiProtocol proto,
AvahiBrowserEvent event, const char *name,
const char *type, const char *domain,
__notused AvahiLookupResultFlags flags, void *d)
{
struct avahi_discovery_data *ddata = (struct avahi_discovery_data *) d;
struct AvahiClient *client = avahi_service_browser_get_client(browser);

switch (event) {
default:
case AVAHI_BROWSER_NEW:
ddata->found = !!avahi_service_resolver_new(client, iface,
proto, name, type, domain,
AVAHI_PROTO_UNSPEC, 0,
__avahi_resolver_cb, d);
break;
case AVAHI_BROWSER_ALL_FOR_NOW:
if (ddata->found) {
while (!ddata->resolved) {
struct timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = 4000000;
nanosleep(&ts, NULL);
}
}
/* fall-through */
case AVAHI_BROWSER_FAILURE:
avahi_simple_poll_quit(ddata->poll);
/* fall-through */
case AVAHI_BROWSER_CACHE_EXHAUSTED:
break;
}
}

int discover_host(char *addr_str, size_t addr_len, uint16_t *port)
{
struct avahi_discovery_data ddata;
int ret = 0;
AvahiAddress address;
AvahiClient *client;
AvahiServiceBrowser *browser;
AvahiSimplePoll *poll = avahi_simple_poll_new();

memset(&address, 0, sizeof(address));
if (!poll)
return -ENOMEM;

client = avahi_client_new(avahi_simple_poll_get(poll),
0, NULL, NULL, &ret);
if (!client) {
ERROR("Unable to create Avahi DNS-SD client :%s\n",
avahi_strerror(ret));
goto err_free_poll;
}

memset(&ddata, 0, sizeof(ddata));
ddata.poll = poll;
ddata.address = &address;
ddata.port = port;

browser = avahi_service_browser_new(client,
AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
"_iio._tcp", NULL, 0, __avahi_browser_cb, &ddata);
if (!browser) {
ret = avahi_client_errno(client);
ERROR("Unable to create Avahi DNS-SD browser: %s\n",
avahi_strerror(ret));
goto err_free_client;
}

DEBUG("Trying to discover host\n");
avahi_simple_poll_loop(poll);

if (!ddata.found)
ret = ENXIO;

if (ret == 0)
avahi_address_snprint(addr_str, addr_len, &address);

avahi_service_browser_free(browser);
err_free_client:
avahi_client_free(client);
err_free_poll:
avahi_simple_poll_free(poll);
return -ret; /* we want a negative error code */
}
Loading