From 0c54764cf19428a0c52724a75ddf3368e3899209 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 17 Oct 2005 02:07:26 +0000 Subject: [PATCH] * split client.h into client.h, lookup.h and publish.h just like we did on the server side * Wrap avahi_server_update_txt() as DBUS function UpdateServiceTxt * Add client side API avahi_entry_group_update_service_txt() and friends * handle AVAHI_PUBLISH_UPDATE semantics in DBUS protocol * minor cleanups git-svn-id: file:///home/lennart/svn/public/avahi/trunk@791 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe --- Makefile.am | 2 + avahi-client/client-test.c | 13 ++ avahi-client/client.h | 263 ----------------------------- avahi-client/entrygroup.c | 211 ++++++++++++++++++----- avahi-client/internal.h | 3 + avahi-client/lookup.h | 229 +++++++++++++++++++++++++ avahi-client/publish.h | 160 ++++++++++++++++++ avahi-client/srv-test.c | 1 + avahi-compat-howl/compat.c | 3 + avahi-compat-libdns_sd/compat.c | 3 + avahi-core/lookup.h | 2 +- avahi-core/publish.h | 4 +- avahi-daemon/EntryGroup.introspect | 10 ++ avahi-daemon/dbus-protocol.c | 153 +++++++++++------ examples/client-browse-services.c | 2 + examples/client-publish-service.c | 2 + 16 files changed, 702 insertions(+), 359 deletions(-) create mode 100644 avahi-client/lookup.h create mode 100644 avahi-client/publish.h diff --git a/Makefile.am b/Makefile.am index bbe1cd7..9474d03 100644 --- a/Makefile.am +++ b/Makefile.am @@ -78,6 +78,8 @@ DX_INPUT = \ $(srcdir)/avahi-core/log.h \ $(srcdir)/avahi-common/defs.h \ $(srcdir)/avahi-client/client.h \ + $(srcdir)/avahi-client/lookup.h \ + $(srcdir)/avahi-client/publish.h \ $(srcdir)/avahi-common/error.h \ $(srcdir)/avahi-common/malloc.h \ $(srcdir)/avahi-common/domain.h \ diff --git a/avahi-client/client-test.c b/avahi-client/client-test.c index c7789ba..14b9e84 100644 --- a/avahi-client/client-test.c +++ b/avahi-client/client-test.c @@ -27,6 +27,9 @@ #include #include +#include +#include + #include #include #include @@ -191,6 +194,14 @@ static void test_entry_group_reset (AvahiTimeout *timeout, void* userdata) avahi_entry_group_commit (g); } +static void test_entry_group_update(AvahiTimeout *timeout, void* userdata) { + AvahiEntryGroup *g = userdata; + + printf ("Updating entry group\n"); + + avahi_entry_group_update_service_txt(g, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, "Lathiat's Site", "_http._tcp", NULL, "foo=bar3", NULL); +} + static void terminate(AvahiTimeout *timeout, void *userdata) { avahi_simple_poll_quit(simple_poll); @@ -272,6 +283,8 @@ int main (int argc, char *argv[]) { avahi_elapse_time(&tv, 8000, 0); poll_api->timeout_new(poll_api, &tv, test_entry_group_reset, group); + avahi_elapse_time(&tv, 15000, 0); + poll_api->timeout_new(poll_api, &tv, test_entry_group_update, group); avahi_elapse_time(&tv, 20000, 0); poll_api->timeout_new(poll_api, &tv, test_free_entry_group, group); avahi_elapse_time(&tv, 25000, 0); diff --git a/avahi-client/client.h b/avahi-client/client.h index bad0789..8a59ca1 100644 --- a/avahi-client/client.h +++ b/avahi-client/client.h @@ -33,16 +33,8 @@ /** \file client.h Definitions and functions for the client API over D-Bus */ -/** \example client-publish-service.c Example how to register a DNS-SD - * service using the client interface to avahi-daemon. It behaves like a network - * printer registering both an IPP and a BSD LPR service. */ - -/** \example client-browse-services.c Example how to browse for DNS-SD - * services using the client interface to avahi-daemon. */ - /** \example glib-integration.c Example of how to integrate * avahi use with GLIB/GTK applications */ - #ifndef DOXYGEN_SHOULD_SKIP_THIS AVAHI_C_DECL_BEGIN @@ -51,27 +43,6 @@ AVAHI_C_DECL_BEGIN /** A connection context */ typedef struct AvahiClient AvahiClient; -/** An entry group object */ -typedef struct AvahiEntryGroup AvahiEntryGroup; - -/** A domain browser object */ -typedef struct AvahiDomainBrowser AvahiDomainBrowser; - -/** A service browser object */ -typedef struct AvahiServiceBrowser AvahiServiceBrowser; - -/** A service type browser object */ -typedef struct AvahiServiceTypeBrowser AvahiServiceTypeBrowser; - -/** A service resolver object */ -typedef struct AvahiServiceResolver AvahiServiceResolver; - -/** A service resolver object */ -typedef struct AvahiHostNameResolver AvahiHostNameResolver; - -/** An address resolver object */ -typedef struct AvahiAddressResolver AvahiAddressResolver; - /** States of a client object, a superset of AvahiServerState */ typedef enum { AVAHI_CLIENT_S_INVALID = AVAHI_SERVER_INVALID, @@ -84,57 +55,6 @@ typedef enum { /** The function prototype for the callback of an AvahiClient */ typedef void (*AvahiClientCallback) (AvahiClient *s, AvahiClientState state, void* userdata); -/** The function prototype for the callback of an AvahiEntryGroup */ -typedef void (*AvahiEntryGroupCallback) (AvahiEntryGroup *g, AvahiEntryGroupState state, void* userdata); - -/** The function prototype for the callback of an AvahiDomainBrowser */ -typedef void (*AvahiDomainBrowserCallback) (AvahiDomainBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *domain, AvahiLookupResultFlags flags, void *userdata); - -/** The function prototype for the callback of an AvahiServiceBrowser */ -typedef void (*AvahiServiceBrowserCallback) (AvahiServiceBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AvahiLookupResultFlags flags, void *userdata); - -/** The function prototype for the callback of an AvahiServiceTypeBrowser */ -typedef void (*AvahiServiceTypeBrowserCallback) (AvahiServiceTypeBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *type, const char *domain, AvahiLookupResultFlags flags, void *userdata); - -/** The function prototype for the callback of an AvahiServiceResolver */ -typedef void (*AvahiServiceResolverCallback) ( - AvahiServiceResolver *r, - AvahiIfIndex interface, - AvahiProtocol protocol, - AvahiResolverEvent event, - const char *name, - const char *type, - const char *domain, - const char *host_name, - const AvahiAddress *a, - uint16_t port, - AvahiStringList *txt, - AvahiLookupResultFlags flags, - void *userdata); - -/** The function prototype for the callback of an AvahiHostNameResolver */ -typedef void (*AvahiHostNameResolverCallback) ( - AvahiHostNameResolver *r, - AvahiIfIndex interface, - AvahiProtocol protocol, - AvahiResolverEvent event, - const char *name, - const AvahiAddress *a, - AvahiLookupResultFlags flags, - void *userdata); - -/** The function prototype for the callback of an AvahiAddressResolver */ -typedef void (*AvahiAddressResolverCallback) ( - AvahiAddressResolver *r, - AvahiIfIndex interface, - AvahiProtocol protocol, - AvahiResolverEvent event, - AvahiProtocol aprotocol, - const AvahiAddress *a, - const char *name, - AvahiLookupResultFlags flags, - void *userdata); - /** Creates a new client instance */ AvahiClient* avahi_client_new (const AvahiPoll *poll_api, AvahiClientCallback callback, void *userdata, int *error); @@ -159,189 +79,6 @@ AvahiClientState avahi_client_get_state(AvahiClient *client); /** Get the last error number */ int avahi_client_errno (AvahiClient*); -/** Create a new AvahiEntryGroup object */ -AvahiEntryGroup* avahi_entry_group_new (AvahiClient*, AvahiEntryGroupCallback callback, void *userdata); - -/** Clean up and free an AvahiEntryGroup object */ -int avahi_entry_group_free (AvahiEntryGroup *); - -/** Commit an AvahiEntryGroup */ -int avahi_entry_group_commit (AvahiEntryGroup*); - -/** Reset an AvahiEntryGroup */ -int avahi_entry_group_reset (AvahiEntryGroup*); - -/** Get an AvahiEntryGroup's state */ -int avahi_entry_group_get_state (AvahiEntryGroup*); - -/** Check if an AvahiEntryGroup is empty */ -int avahi_entry_group_is_empty (AvahiEntryGroup*); - -/** Get an AvahiEntryGroup's owning client instance */ -AvahiClient* avahi_entry_group_get_client (AvahiEntryGroup*); - -/** Add a service, takes a variable NULL terminated list of text records */ -int avahi_entry_group_add_service( - AvahiEntryGroup *group, - AvahiIfIndex interface, - AvahiProtocol protocol, - AvahiPublishFlags flags, - const char *name, - const char *type, - const char *domain, - const char *host, - uint16_t port, - ...) AVAHI_GCC_SENTINEL; - -/** Add a service, takes an AvahiStringList for text records */ -int avahi_entry_group_add_service_strlst( - AvahiEntryGroup *group, - AvahiIfIndex interface, - AvahiProtocol protocol, - AvahiPublishFlags flags, - const char *name, - const char *type, - const char *domain, - const char *host, - uint16_t port, - AvahiStringList *txt); - -/** Add a service, takes a NULL terminated va_list for text records */ -int avahi_entry_group_add_service_va( - AvahiEntryGroup *group, - AvahiIfIndex interface, - AvahiProtocol protocol, - AvahiPublishFlags flags, - const char *name, - const char *type, - const char *domain, - const char *host, - uint16_t port, - va_list va); - -/** Add a subtype for a service */ -int avahi_entry_group_add_service_subtype( - AvahiEntryGroup *group, - AvahiIfIndex interface, - AvahiProtocol protocol, - AvahiPublishFlags flags, - const char *name, - const char *type, - const char *domain, - const char *subtype); - -/** Browse for domains on the local network */ -AvahiDomainBrowser* avahi_domain_browser_new ( - AvahiClient *client, - AvahiIfIndex interface, - AvahiProtocol protocol, - const char *domain, - AvahiDomainBrowserType btype, - AvahiLookupFlags flags, - AvahiDomainBrowserCallback callback, - void *userdata); - -/** Get the parent client of an AvahiDomainBrowser object */ -AvahiClient* avahi_domain_browser_get_client (AvahiDomainBrowser *); - -/** Cleans up and frees an AvahiDomainBrowser object */ -int avahi_domain_browser_free (AvahiDomainBrowser *); - -/** Browse for service types on the local network */ -AvahiServiceTypeBrowser* avahi_service_type_browser_new ( - AvahiClient *client, - AvahiIfIndex interface, - AvahiProtocol protocol, - const char *domain, - AvahiLookupFlags flags, - AvahiServiceTypeBrowserCallback callback, - void *userdata); - -/** Get the parent client of an AvahiServiceTypeBrowser object */ -AvahiClient* avahi_service_type_browser_get_client (AvahiServiceTypeBrowser *); - -/** Cleans up and frees an AvahiServiceTypeBrowser object */ -int avahi_service_type_browser_free (AvahiServiceTypeBrowser *); - -/** Browse for services of a type on the local network */ -AvahiServiceBrowser* avahi_service_browser_new ( - AvahiClient *client, - AvahiIfIndex interface, - AvahiProtocol protocol, - const char *type, - const char *domain, - AvahiLookupFlags flags, - AvahiServiceBrowserCallback callback, - void *userdata); - -/** Get the parent client of an AvahiServiceBrowser object */ -AvahiClient* avahi_service_browser_get_client (AvahiServiceBrowser *); - -/* Cleans up and frees an AvahiServiceBrowser object */ -int avahi_service_browser_free (AvahiServiceBrowser *); - -/** Create a new service resolver object */ -AvahiServiceResolver * avahi_service_resolver_new( - AvahiClient *client, - AvahiIfIndex interface, - AvahiProtocol protocol, - const char *name, - const char *type, - const char *domain, - AvahiProtocol aprotocol, - AvahiLookupFlags flags, - AvahiServiceResolverCallback callback, - void *userdata); - -/** Get the parent client of an AvahiServiceResolver object */ -AvahiClient* avahi_service_resolver_get_client (AvahiServiceResolver *); - -/** Free a service resolver object */ -int avahi_service_resolver_free(AvahiServiceResolver *r); - -/** Create a new hostname resolver object */ -AvahiHostNameResolver * avahi_host_name_resolver_new( - AvahiClient *client, - AvahiIfIndex interface, - AvahiProtocol protocol, - const char *name, - AvahiProtocol aprotocol, - AvahiLookupFlags flags, - AvahiHostNameResolverCallback callback, - void *userdata); - -/** Get the parent client of an AvahiHostNameResolver object */ -AvahiClient* avahi_host_name_resolver_get_client (AvahiHostNameResolver *); - -/** Free a hostname resolver object */ -int avahi_host_name_resolver_free(AvahiHostNameResolver *r); - -/** Create a new address resolver object from an address string. Set aprotocol to AF_UNSPEC for protocol detection. */ -AvahiAddressResolver * avahi_address_resolver_new( - AvahiClient *client, - AvahiIfIndex interface, - AvahiProtocol protocol, - const char *address, - AvahiLookupFlags flags, - AvahiAddressResolverCallback callback, - void *userdata); - -/** Create a new address resolver object from an AvahiAddress object */ -AvahiAddressResolver* avahi_address_resolver_new_a( - AvahiClient *client, - AvahiIfIndex interface, - AvahiProtocol protocol, - const AvahiAddress *a, - AvahiLookupFlags flags, - AvahiAddressResolverCallback callback, - void *userdata); - -/** Get the parent client of an AvahiAddressResolver object */ -AvahiClient* avahi_address_resolver_get_client (AvahiAddressResolver *); - -/** Free a AvahiAddressResolver resolver object */ -int avahi_address_resolver_free(AvahiAddressResolver *r); - /** Return the local service cookie. returns AVAHI_SERVICE_COOKIE_INVALID on failure. */ uint32_t avahi_client_get_local_service_cookie(AvahiClient *client); diff --git a/avahi-client/entrygroup.c b/avahi-client/entrygroup.c index d2526e0..2d882e6 100644 --- a/avahi-client/entrygroup.c +++ b/avahi-client/entrygroup.c @@ -330,6 +330,46 @@ fail: return r; } +static int append_string_list(DBusMessage *message, AvahiStringList *txt) { + DBusMessageIter iter, sub; + int r = -1; + AvahiStringList *p; + + assert(message); + assert(txt); + + dbus_message_iter_init_append(message, &iter); + + /* Reverse the string list, so that we can pass it in-order to the server */ + txt = avahi_string_list_reverse(txt); + + if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "ay", &sub)) + goto fail; + + /* Assemble the AvahiStringList into an Array of Array of Bytes to send over dbus */ + for (p = txt; p != NULL; p = p->next) { + DBusMessageIter sub2; + const uint8_t *data = p->text; + + if (!(dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "y", &sub2)) || + !(dbus_message_iter_append_fixed_array(&sub2, DBUS_TYPE_BYTE, &data, p->size)) || + !(dbus_message_iter_close_container(&sub, &sub2))) + goto fail; + } + + if (!dbus_message_iter_close_container(&iter, &sub)) + goto fail; + + r = 0; + +fail: + + /* Reverse the string list to the original state */ + txt = avahi_string_list_reverse(txt); + + return r; +} + int avahi_entry_group_add_service_strlst( AvahiEntryGroup *group, AvahiIfIndex interface, @@ -343,9 +383,7 @@ int avahi_entry_group_add_service_strlst( AvahiStringList *txt) { DBusMessage *message = NULL, *reply = NULL; - DBusMessageIter iter, sub; - AvahiStringList *p; - int reverse = 0, r = AVAHI_OK; + int r = AVAHI_OK; DBusError error; AvahiClient *client; int32_t i_interface, i_protocol; @@ -387,44 +425,12 @@ int avahi_entry_group_add_service_strlst( DBUS_TYPE_STRING, &domain, DBUS_TYPE_STRING, &host, DBUS_TYPE_UINT16, &port, - DBUS_TYPE_INVALID)) { + DBUS_TYPE_INVALID) || + append_string_list(message, txt) < 0) { r = avahi_client_set_errno(group->client, AVAHI_ERR_NO_MEMORY); goto fail; } - dbus_message_iter_init_append(message, &iter); - - /* Reverse the string list, so that we can pass it in-order to the server */ - txt = avahi_string_list_reverse(txt); - reverse = 1; - - if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "ay", &sub)) { - r = avahi_client_set_errno(group->client, AVAHI_ERR_NO_MEMORY); - goto fail; - } - - /* Assemble the AvahiStringList into an Array of Array of Bytes to send over dbus */ - for (p = txt; p != NULL; p = p->next) { - DBusMessageIter sub2; - const uint8_t *data = p->text; - - if (!(dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "y", &sub2)) || - !(dbus_message_iter_append_fixed_array(&sub2, DBUS_TYPE_BYTE, &data, p->size)) || - !(dbus_message_iter_close_container(&sub, &sub2))) { - r = avahi_client_set_errno(group->client, AVAHI_ERR_NO_MEMORY); - goto fail; - } - } - - if (!dbus_message_iter_close_container(&iter, &sub)) { - r = avahi_client_set_errno(group->client, AVAHI_ERR_NO_MEMORY); - goto fail; - } - - /* Reverse the string list to the original state */ - txt = avahi_string_list_reverse(txt); - reverse = 0; - if (!(reply = dbus_connection_send_with_reply_and_block(client->bus, message, -1, &error)) || dbus_error_is_set (&error)) { r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR); @@ -443,8 +449,6 @@ int avahi_entry_group_add_service_strlst( return AVAHI_OK; fail: - if (reverse) - txt = avahi_string_list_reverse(txt); if (dbus_error_is_set(&error)) { r = avahi_client_set_dbus_error(client, &error); @@ -595,3 +599,132 @@ fail: return r; } + +int avahi_entry_group_update_service_txt( + AvahiEntryGroup *group, + AvahiIfIndex interface, + AvahiProtocol protocol, + AvahiPublishFlags flags, + const char *name, + const char *type, + const char *domain, + ...) { + + va_list va; + int r; + + va_start(va, domain); + r = avahi_entry_group_update_service_txt_va(group, interface, protocol, flags, name, type, domain, va); + va_end(va); + return r; +} + +int avahi_entry_group_update_service_txt_va( + AvahiEntryGroup *group, + AvahiIfIndex interface, + AvahiProtocol protocol, + AvahiPublishFlags flags, + const char *name, + const char *type, + const char *domain, + va_list va) { + + int r; + AvahiStringList *txt; + + txt = avahi_string_list_new_va(va); + r = avahi_entry_group_update_service_txt_strlst(group, interface, protocol, flags, name, type, domain, txt); + avahi_string_list_free(txt); + + return r; +} + +int avahi_entry_group_update_service_txt_strlst( + AvahiEntryGroup *group, + AvahiIfIndex interface, + AvahiProtocol protocol, + AvahiPublishFlags flags, + const char *name, + const char *type, + const char *domain, + AvahiStringList *txt) { + + DBusMessage *message = NULL, *reply = NULL; + int r = AVAHI_OK; + DBusError error; + AvahiClient *client; + int32_t i_interface, i_protocol; + uint32_t u_flags; + + assert(group); + assert(name); + assert(type); + + client = group->client; + + if (!group->path || group->client->state == AVAHI_CLIENT_DISCONNECTED) + return avahi_client_set_errno(group->client, AVAHI_ERR_BAD_STATE); + + if (!domain) + domain = ""; + + dbus_error_init(&error); + + if (!(message = dbus_message_new_method_call (AVAHI_DBUS_NAME, group->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "UpdateServiceTxt"))) { + r = avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY); + goto fail; + } + + i_interface = (int32_t) interface; + i_protocol = (int32_t) protocol; + u_flags = (uint32_t) flags; + + if (!dbus_message_append_args( + message, + DBUS_TYPE_INT32, &i_interface, + DBUS_TYPE_INT32, &i_protocol, + DBUS_TYPE_UINT32, &u_flags, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_STRING, &type, + DBUS_TYPE_STRING, &domain, + DBUS_TYPE_INVALID) || + append_string_list(message, txt) < 0) { + r = avahi_client_set_errno(group->client, AVAHI_ERR_NO_MEMORY); + goto fail; + } + + if (!(reply = dbus_connection_send_with_reply_and_block(client->bus, message, -1, &error)) || + dbus_error_is_set (&error)) { + r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR); + goto fail; + } + + if (!dbus_message_get_args(reply, &error, DBUS_TYPE_INVALID) || + dbus_error_is_set (&error)) { + r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR); + goto fail; + } + + dbus_message_unref(message); + dbus_message_unref(reply); + + return AVAHI_OK; + +fail: + + if (dbus_error_is_set(&error)) { + r = avahi_client_set_dbus_error(client, &error); + dbus_error_free(&error); + } + + if (message) + dbus_message_unref(message); + + if (reply) + dbus_message_unref(reply); + + return r; + + +} + diff --git a/avahi-client/internal.h b/avahi-client/internal.h index b05835f..56aaaae 100644 --- a/avahi-client/internal.h +++ b/avahi-client/internal.h @@ -23,7 +23,10 @@ ***/ #include + #include "client.h" +#include "lookup.h" +#include "publish.h" struct AvahiClient { const AvahiPoll *poll_api; diff --git a/avahi-client/lookup.h b/avahi-client/lookup.h new file mode 100644 index 0000000..659700e --- /dev/null +++ b/avahi-client/lookup.h @@ -0,0 +1,229 @@ +#ifndef fooclientlookuphfoo +#define fooclientlookuphfoo + +/* $Id$ */ + +/*** + This file is part of avahi. + + avahi 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. + + avahi 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. + + You should have received a copy of the GNU Lesser General Public + License along with avahi; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include + +#include +#include +#include +#include +#include +#include + +#include + +/** \file avahi-client/lookup.h Lookup Client API */ + +/** \example client-browse-services.c Example how to browse for DNS-SD + * services using the client interface to avahi-daemon. */ + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +AVAHI_C_DECL_BEGIN +#endif + +/** A domain browser object */ +typedef struct AvahiDomainBrowser AvahiDomainBrowser; + +/** A service browser object */ +typedef struct AvahiServiceBrowser AvahiServiceBrowser; + +/** A service type browser object */ +typedef struct AvahiServiceTypeBrowser AvahiServiceTypeBrowser; + +/** A service resolver object */ +typedef struct AvahiServiceResolver AvahiServiceResolver; + +/** A service resolver object */ +typedef struct AvahiHostNameResolver AvahiHostNameResolver; + +/** An address resolver object */ +typedef struct AvahiAddressResolver AvahiAddressResolver; + +/** The function prototype for the callback of an AvahiDomainBrowser */ +typedef void (*AvahiDomainBrowserCallback) (AvahiDomainBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *domain, AvahiLookupResultFlags flags, void *userdata); + +/** The function prototype for the callback of an AvahiServiceBrowser */ +typedef void (*AvahiServiceBrowserCallback) (AvahiServiceBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AvahiLookupResultFlags flags, void *userdata); + +/** The function prototype for the callback of an AvahiServiceTypeBrowser */ +typedef void (*AvahiServiceTypeBrowserCallback) (AvahiServiceTypeBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *type, const char *domain, AvahiLookupResultFlags flags, void *userdata); + +/** The function prototype for the callback of an AvahiServiceResolver */ +typedef void (*AvahiServiceResolverCallback) ( + AvahiServiceResolver *r, + AvahiIfIndex interface, + AvahiProtocol protocol, + AvahiResolverEvent event, + const char *name, + const char *type, + const char *domain, + const char *host_name, + const AvahiAddress *a, + uint16_t port, + AvahiStringList *txt, + AvahiLookupResultFlags flags, + void *userdata); + +/** The function prototype for the callback of an AvahiHostNameResolver */ +typedef void (*AvahiHostNameResolverCallback) ( + AvahiHostNameResolver *r, + AvahiIfIndex interface, + AvahiProtocol protocol, + AvahiResolverEvent event, + const char *name, + const AvahiAddress *a, + AvahiLookupResultFlags flags, + void *userdata); + +/** The function prototype for the callback of an AvahiAddressResolver */ +typedef void (*AvahiAddressResolverCallback) ( + AvahiAddressResolver *r, + AvahiIfIndex interface, + AvahiProtocol protocol, + AvahiResolverEvent event, + AvahiProtocol aprotocol, + const AvahiAddress *a, + const char *name, + AvahiLookupResultFlags flags, + void *userdata); + + +/** Browse for domains on the local network */ +AvahiDomainBrowser* avahi_domain_browser_new ( + AvahiClient *client, + AvahiIfIndex interface, + AvahiProtocol protocol, + const char *domain, + AvahiDomainBrowserType btype, + AvahiLookupFlags flags, + AvahiDomainBrowserCallback callback, + void *userdata); + +/** Get the parent client of an AvahiDomainBrowser object */ +AvahiClient* avahi_domain_browser_get_client (AvahiDomainBrowser *); + +/** Cleans up and frees an AvahiDomainBrowser object */ +int avahi_domain_browser_free (AvahiDomainBrowser *); + +/** Browse for service types on the local network */ +AvahiServiceTypeBrowser* avahi_service_type_browser_new ( + AvahiClient *client, + AvahiIfIndex interface, + AvahiProtocol protocol, + const char *domain, + AvahiLookupFlags flags, + AvahiServiceTypeBrowserCallback callback, + void *userdata); + +/** Get the parent client of an AvahiServiceTypeBrowser object */ +AvahiClient* avahi_service_type_browser_get_client (AvahiServiceTypeBrowser *); + +/** Cleans up and frees an AvahiServiceTypeBrowser object */ +int avahi_service_type_browser_free (AvahiServiceTypeBrowser *); + +/** Browse for services of a type on the local network */ +AvahiServiceBrowser* avahi_service_browser_new ( + AvahiClient *client, + AvahiIfIndex interface, + AvahiProtocol protocol, + const char *type, + const char *domain, + AvahiLookupFlags flags, + AvahiServiceBrowserCallback callback, + void *userdata); + +/** Get the parent client of an AvahiServiceBrowser object */ +AvahiClient* avahi_service_browser_get_client (AvahiServiceBrowser *); + +/* Cleans up and frees an AvahiServiceBrowser object */ +int avahi_service_browser_free (AvahiServiceBrowser *); + +/** Create a new service resolver object */ +AvahiServiceResolver * avahi_service_resolver_new( + AvahiClient *client, + AvahiIfIndex interface, + AvahiProtocol protocol, + const char *name, + const char *type, + const char *domain, + AvahiProtocol aprotocol, + AvahiLookupFlags flags, + AvahiServiceResolverCallback callback, + void *userdata); + +/** Get the parent client of an AvahiServiceResolver object */ +AvahiClient* avahi_service_resolver_get_client (AvahiServiceResolver *); + +/** Free a service resolver object */ +int avahi_service_resolver_free(AvahiServiceResolver *r); + +/** Create a new hostname resolver object */ +AvahiHostNameResolver * avahi_host_name_resolver_new( + AvahiClient *client, + AvahiIfIndex interface, + AvahiProtocol protocol, + const char *name, + AvahiProtocol aprotocol, + AvahiLookupFlags flags, + AvahiHostNameResolverCallback callback, + void *userdata); + +/** Get the parent client of an AvahiHostNameResolver object */ +AvahiClient* avahi_host_name_resolver_get_client (AvahiHostNameResolver *); + +/** Free a hostname resolver object */ +int avahi_host_name_resolver_free(AvahiHostNameResolver *r); + +/** Create a new address resolver object from an address string. Set aprotocol to AF_UNSPEC for protocol detection. */ +AvahiAddressResolver * avahi_address_resolver_new( + AvahiClient *client, + AvahiIfIndex interface, + AvahiProtocol protocol, + const char *address, + AvahiLookupFlags flags, + AvahiAddressResolverCallback callback, + void *userdata); + +/** Create a new address resolver object from an AvahiAddress object */ +AvahiAddressResolver* avahi_address_resolver_new_a( + AvahiClient *client, + AvahiIfIndex interface, + AvahiProtocol protocol, + const AvahiAddress *a, + AvahiLookupFlags flags, + AvahiAddressResolverCallback callback, + void *userdata); + +/** Get the parent client of an AvahiAddressResolver object */ +AvahiClient* avahi_address_resolver_get_client (AvahiAddressResolver *); + +/** Free a AvahiAddressResolver resolver object */ +int avahi_address_resolver_free(AvahiAddressResolver *r); + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +AVAHI_C_DECL_END +#endif + + +#endif diff --git a/avahi-client/publish.h b/avahi-client/publish.h new file mode 100644 index 0000000..7c678a9 --- /dev/null +++ b/avahi-client/publish.h @@ -0,0 +1,160 @@ +#ifndef fooclientpublishhfoo +#define fooclientpublishhfoo + +/* $Id$ */ + +/*** + This file is part of avahi. + + avahi 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. + + avahi 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. + + You should have received a copy of the GNU Lesser General Public + License along with avahi; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include + +#include +#include +#include +#include +#include +#include + +#include + +/** \file avahi-client/publish.h Publishing Client API */ + +/** \example client-publish-service.c Example how to register a DNS-SD + * service using the client interface to avahi-daemon. It behaves like a network + * printer registering both an IPP and a BSD LPR service. */ + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +AVAHI_C_DECL_BEGIN +#endif + +/** An entry group object */ +typedef struct AvahiEntryGroup AvahiEntryGroup; + +/** The function prototype for the callback of an AvahiEntryGroup */ +typedef void (*AvahiEntryGroupCallback) (AvahiEntryGroup *g, AvahiEntryGroupState state, void* userdata); + +/** Create a new AvahiEntryGroup object */ +AvahiEntryGroup* avahi_entry_group_new (AvahiClient*, AvahiEntryGroupCallback callback, void *userdata); + +/** Clean up and free an AvahiEntryGroup object */ +int avahi_entry_group_free (AvahiEntryGroup *); + +/** Commit an AvahiEntryGroup */ +int avahi_entry_group_commit (AvahiEntryGroup*); + +/** Reset an AvahiEntryGroup */ +int avahi_entry_group_reset (AvahiEntryGroup*); + +/** Get an AvahiEntryGroup's state */ +int avahi_entry_group_get_state (AvahiEntryGroup*); + +/** Check if an AvahiEntryGroup is empty */ +int avahi_entry_group_is_empty (AvahiEntryGroup*); + +/** Get an AvahiEntryGroup's owning client instance */ +AvahiClient* avahi_entry_group_get_client (AvahiEntryGroup*); + +/** Add a service, takes a variable NULL terminated list of text records */ +int avahi_entry_group_add_service( + AvahiEntryGroup *group, + AvahiIfIndex interface, + AvahiProtocol protocol, + AvahiPublishFlags flags, + const char *name, + const char *type, + const char *domain, + const char *host, + uint16_t port, + ...) AVAHI_GCC_SENTINEL; + +/** Add a service, takes an AvahiStringList for text records */ +int avahi_entry_group_add_service_strlst( + AvahiEntryGroup *group, + AvahiIfIndex interface, + AvahiProtocol protocol, + AvahiPublishFlags flags, + const char *name, + const char *type, + const char *domain, + const char *host, + uint16_t port, + AvahiStringList *txt); + +/** Add a service, takes a NULL terminated va_list for text records */ +int avahi_entry_group_add_service_va( + AvahiEntryGroup *group, + AvahiIfIndex interface, + AvahiProtocol protocol, + AvahiPublishFlags flags, + const char *name, + const char *type, + const char *domain, + const char *host, + uint16_t port, + va_list va); + +/** Add a subtype for a service */ +int avahi_entry_group_add_service_subtype( + AvahiEntryGroup *group, + AvahiIfIndex interface, + AvahiProtocol protocol, + AvahiPublishFlags flags, + const char *name, + const char *type, + const char *domain, + const char *subtype); + +/** Update a TXT record for an existing service */ +int avahi_entry_group_update_service_txt( + AvahiEntryGroup *g, + AvahiIfIndex interface, + AvahiProtocol protocol, + AvahiPublishFlags flags, + const char *name, + const char *type, + const char *domain, + ...) AVAHI_GCC_SENTINEL; + +/** Update a TXT record for an existing service */ +int avahi_entry_group_update_service_txt_strlst( + AvahiEntryGroup *g, + AvahiIfIndex interface, + AvahiProtocol protocol, + AvahiPublishFlags flags, + const char *name, + const char *type, + const char *domain, + AvahiStringList *strlst); + +/** Update a TXT record for an existing service */ +int avahi_entry_group_update_service_txt_va( + AvahiEntryGroup *g, + AvahiIfIndex interface, + AvahiProtocol protocol, + AvahiPublishFlags flags, + const char *name, + const char *type, + const char *domain, + va_list va); + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +AVAHI_C_DECL_END +#endif + +#endif diff --git a/avahi-client/srv-test.c b/avahi-client/srv-test.c index 1a453bc..4e0959e 100644 --- a/avahi-client/srv-test.c +++ b/avahi-client/srv-test.c @@ -27,6 +27,7 @@ #include #include +#include #include #include #include diff --git a/avahi-compat-howl/compat.c b/avahi-compat-howl/compat.c index d9a1bda..1663af0 100644 --- a/avahi-compat-howl/compat.c +++ b/avahi-compat-howl/compat.c @@ -33,7 +33,10 @@ #include #include #include + #include +#include +#include #include "howl.h" #include "warn.h" diff --git a/avahi-compat-libdns_sd/compat.c b/avahi-compat-libdns_sd/compat.c index 9b399d2..984e288 100644 --- a/avahi-compat-libdns_sd/compat.c +++ b/avahi-compat-libdns_sd/compat.c @@ -37,7 +37,10 @@ #include #include #include + #include +#include +#include #include "warn.h" #include "dns_sd.h" diff --git a/avahi-core/lookup.h b/avahi-core/lookup.h index 518a4c9..50f7631 100644 --- a/avahi-core/lookup.h +++ b/avahi-core/lookup.h @@ -22,7 +22,7 @@ USA. ***/ -/** \file lookup.h Functions for browsing/resolving services and other RRs */ +/** \file avahi-core/lookup.h Functions for browsing/resolving services and other RRs */ /** \example core-browse-services.c Example how to browse for DNS-SD * services using an embedded mDNS stack. */ diff --git a/avahi-core/publish.h b/avahi-core/publish.h index 36c29cf..9d72874 100644 --- a/avahi-core/publish.h +++ b/avahi-core/publish.h @@ -22,13 +22,12 @@ USA. ***/ -/** \file publish.h Functions for publising local services and RRs */ +/** \file core/publish.h Functions for publising local services and RRs */ /** \example core-publish-service.c Example how to register a DNS-SD * service using an embedded mDNS stack. It behaves like a network * printer registering both an IPP and a BSD LPR service. */ - #include #ifndef DOXYGEN_SHOULD_SKIP_THIS @@ -220,7 +219,6 @@ int avahi_server_add_service_subtype( const char *domain, /**< Specify the main type of the service you already added here */ const char *subtype /**< The new subtype for the specified service */ ); - /** Update the TXT record for a service with the data from the specified string list */ int avahi_server_update_service_txt_strlst( AvahiServer *s, diff --git a/avahi-daemon/EntryGroup.introspect b/avahi-daemon/EntryGroup.introspect index ef3fb5f..b5c2382 100644 --- a/avahi-daemon/EntryGroup.introspect +++ b/avahi-daemon/EntryGroup.introspect @@ -49,6 +49,16 @@ + + + + + + + + + + diff --git a/avahi-daemon/dbus-protocol.c b/avahi-daemon/dbus-protocol.c index ce21521..3b2c76a 100644 --- a/avahi-daemon/dbus-protocol.c +++ b/avahi-daemon/dbus-protocol.c @@ -697,6 +697,58 @@ static void entry_group_callback(AvahiServer *s, AvahiSEntryGroup *g, AvahiEntry dbus_message_unref(m); } +static int read_strlst(DBusMessage *m, int idx, AvahiStringList **l) { + DBusMessageIter iter, sub; + int j; + AvahiStringList *strlst = NULL; + + assert(m); + assert(l); + + dbus_message_iter_init(m, &iter); + + for (j = 0; j < idx; j++) + dbus_message_iter_next(&iter); + + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY || + dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_ARRAY) + goto fail; + + dbus_message_iter_recurse(&iter, &sub); + + for (;;) { + DBusMessageIter sub2; + int at, n; + uint8_t *k; + + if ((at = dbus_message_iter_get_arg_type(&sub)) == DBUS_TYPE_INVALID) + break; + + assert(at == DBUS_TYPE_ARRAY); + + if (dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_BYTE) + goto fail; + + dbus_message_iter_recurse(&sub, &sub2); + dbus_message_iter_get_fixed_array(&sub2, &k, &n); + strlst = avahi_string_list_add_arbitrary(strlst, k, n); + + dbus_message_iter_next(&sub); + } + + *l = strlst; + + return 0; + +fail: + avahi_log_warn("Error parsing TXT data"); + + avahi_string_list_free(strlst); + *l = NULL; + return -1; +} + + static DBusHandlerResult msg_entry_group_impl(DBusConnection *c, DBusMessage *m, void *userdata) { DBusError error; EntryGroupInfo *i = userdata; @@ -786,9 +838,7 @@ static DBusHandlerResult msg_entry_group_impl(DBusConnection *c, DBusMessage *m, uint32_t flags; char *type, *name, *domain, *host; uint16_t port; - AvahiStringList *strlst; - DBusMessageIter iter, sub; - int j; + AvahiStringList *strlst = NULL; if (!dbus_message_get_args( m, &error, @@ -800,50 +850,15 @@ static DBusHandlerResult msg_entry_group_impl(DBusConnection *c, DBusMessage *m, DBUS_TYPE_STRING, &domain, DBUS_TYPE_STRING, &host, DBUS_TYPE_UINT16, &port, - DBUS_TYPE_INVALID) || !type || !name) { + DBUS_TYPE_INVALID) || + !type || !name || + read_strlst(m, 8, &strlst) < 0) { avahi_log_warn("Error parsing EntryGroup::AddService message"); goto fail; } - dbus_message_iter_init(m, &iter); - - for (j = 0; j < 8; j++) - dbus_message_iter_next(&iter); - - if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY || - dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_ARRAY) { - avahi_log_warn("Error parsing EntryGroup::AddService message 2"); - goto fail; - } - - strlst = NULL; - dbus_message_iter_recurse(&iter, &sub); - - for (;;) { - DBusMessageIter sub2; - int at, n; - uint8_t *k; - - if ((at = dbus_message_iter_get_arg_type(&sub)) == DBUS_TYPE_INVALID) - break; - - assert(at == DBUS_TYPE_ARRAY); - - if (dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_BYTE) { - avahi_log_warn("Error parsing EntryGroup::AddService message"); - goto fail; - } - - dbus_message_iter_recurse(&sub, &sub2); - dbus_message_iter_get_fixed_array(&sub2, &k, &n); - strlst = avahi_string_list_add_arbitrary(strlst, k, n); - - dbus_message_iter_next(&sub); - } - - if (i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) { + if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) { avahi_string_list_free(strlst); - avahi_log_warn("Too many entries per entry group, client request failed."); return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL); } @@ -858,7 +873,9 @@ static DBusHandlerResult msg_entry_group_impl(DBusConnection *c, DBusMessage *m, return respond_error(c, m, avahi_server_errno(avahi_server), NULL); } - i->n_entries ++; + if (!(flags & AVAHI_PUBLISH_UPDATE)) + i->n_entries ++; + avahi_string_list_free(strlst); return respond_ok(c, m); @@ -883,10 +900,8 @@ static DBusHandlerResult msg_entry_group_impl(DBusConnection *c, DBusMessage *m, goto fail; } - if (i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) { - avahi_log_warn("Too many entries per entry group, client request failed."); + if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL); - } if (domain && !*domain) domain = NULL; @@ -894,7 +909,41 @@ static DBusHandlerResult msg_entry_group_impl(DBusConnection *c, DBusMessage *m, if (avahi_server_add_service_subtype(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, type, domain, subtype) < 0) return respond_error(c, m, avahi_server_errno(avahi_server), NULL); - i->n_entries ++; + if (!(flags & AVAHI_PUBLISH_UPDATE)) + i->n_entries ++; + + return respond_ok(c, m); + + } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "UpdateServiceTxt")) { + int32_t interface, protocol; + uint32_t flags; + char *type, *name, *domain; + AvahiStringList *strlst; + + if (!dbus_message_get_args( + m, &error, + DBUS_TYPE_INT32, &interface, + DBUS_TYPE_INT32, &protocol, + DBUS_TYPE_UINT32, &flags, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_STRING, &type, + DBUS_TYPE_STRING, &domain, + DBUS_TYPE_INVALID) || + !type || !name || + read_strlst(m, 6, &strlst)) { + avahi_log_warn("Error parsing EntryGroup::UpdateServiceTxt message"); + goto fail; + } + + if (domain && !*domain) + domain = NULL; + + if (avahi_server_update_service_txt_strlst(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, type, domain, strlst) < 0) { + avahi_string_list_free(strlst); + return respond_error(c, m, avahi_server_errno(avahi_server), NULL); + } + + avahi_string_list_free(strlst); return respond_ok(c, m); @@ -916,19 +965,17 @@ static DBusHandlerResult msg_entry_group_impl(DBusConnection *c, DBusMessage *m, goto fail; } - if (i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) { - avahi_log_warn("Too many entries per entry group, client request failed."); + if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL); - } - if (!(avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))) { + if (!(avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))) return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL); - } if (avahi_server_add_address(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, &a) < 0) return respond_error(c, m, avahi_server_errno(avahi_server), NULL); - i->n_entries ++; + if (!(flags & AVAHI_PUBLISH_UPDATE)) + i->n_entries ++; return respond_ok(c, m); } diff --git a/examples/client-browse-services.c b/examples/client-browse-services.c index 7a6940b..7918cad 100644 --- a/examples/client-browse-services.c +++ b/examples/client-browse-services.c @@ -29,6 +29,8 @@ #include #include +#include + #include #include #include diff --git a/examples/client-publish-service.c b/examples/client-publish-service.c index efc1f2b..e9dcffc 100644 --- a/examples/client-publish-service.c +++ b/examples/client-publish-service.c @@ -29,6 +29,8 @@ #include #include +#include + #include #include #include -- 2.39.5