summaryrefslogtreecommitdiffstats
path: root/avahi-client
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2005-11-16 19:30:11 +0000
committerLennart Poettering <lennart@poettering.net>2005-11-16 19:30:11 +0000
commit9e4237ebed07d00bf1176178d1358b475d749b27 (patch)
tree38b9fa5103733445ce69012a5c6ae65fdb043a91 /avahi-client
parentaffa11f5bb7309fa504624a3512dce5c88ce473b (diff)
* Implement client API for arbitrary record browsing
* Fix memory leak in avahi-client git-svn-id: file:///home/lennart/svn/public/avahi/trunk@984 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe
Diffstat (limited to 'avahi-client')
-rw-r--r--avahi-client/Makefile.am7
-rw-r--r--avahi-client/browser.c243
-rw-r--r--avahi-client/client.c22
-rw-r--r--avahi-client/entrygroup.c2
-rw-r--r--avahi-client/internal.h15
-rw-r--r--avahi-client/lookup.h65
-rw-r--r--avahi-client/rr-test.c113
7 files changed, 461 insertions, 6 deletions
diff --git a/avahi-client/Makefile.am b/avahi-client/Makefile.am
index 463ea39..aaa772a 100644
--- a/avahi-client/Makefile.am
+++ b/avahi-client/Makefile.am
@@ -34,7 +34,8 @@ if ENABLE_TESTS
noinst_PROGRAMS = \
client-test \
srv-test \
- xdg-config-test
+ xdg-config-test \
+ rr-test
endif
@@ -60,6 +61,10 @@ srv_test_SOURCES = srv-test.c
srv_test_CFLAGS = $(AM_CFLAGS)
srv_test_LDADD = $(AM_LDADD) libavahi-client.la ../avahi-common/libavahi-common.la
+rr_test_SOURCES = rr-test.c
+rr_test_CFLAGS = $(AM_CFLAGS)
+rr_test_LDADD = $(AM_LDADD) libavahi-client.la ../avahi-common/libavahi-common.la
+
xdg_config_test_SOURCES = xdg-config-test.c xdg-config.c xdg-config.h
xdg_config_test_CFLAGS = $(AM_CFLAGS)
xdg_config_test_LDADD = $(AM_LDADD)
diff --git a/avahi-client/browser.c b/avahi-client/browser.c
index c9af43f..a8a823e 100644
--- a/avahi-client/browser.c
+++ b/avahi-client/browser.c
@@ -348,6 +348,7 @@ fail:
}
/* AvahiServiceTypeBrowser */
+
AvahiServiceTypeBrowser* avahi_service_type_browser_new(
AvahiClient *client,
AvahiIfIndex interface,
@@ -782,4 +783,246 @@ fail:
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
+/* AvahiRecordBrowser */
+
+AvahiRecordBrowser* avahi_record_browser_new(
+ AvahiClient *client,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ const char *name,
+ uint16_t clazz,
+ uint16_t type,
+ AvahiLookupFlags flags,
+ AvahiRecordBrowserCallback callback,
+ void *userdata) {
+
+ AvahiRecordBrowser *b = NULL;
+ DBusMessage *message = NULL, *reply = NULL;
+ DBusError error;
+ char *path;
+ int32_t i_protocol, i_interface;
+ uint32_t u_flags;
+
+ assert(client);
+ assert(name);
+ assert(callback);
+
+ dbus_error_init(&error);
+
+ if (!avahi_client_is_connected(client)) {
+ avahi_client_set_errno(client, AVAHI_ERR_BAD_STATE);
+ goto fail;
+ }
+
+ if (!(b = avahi_new(AvahiRecordBrowser, 1))) {
+ avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
+ goto fail;
+ }
+
+ b->client = client;
+ b->callback = callback;
+ b->userdata = userdata;
+ b->path = NULL;
+ b->name = NULL;
+ b->clazz = clazz;
+ b->type = type;
+ b->interface = interface;
+ b->protocol = protocol;
+
+ AVAHI_LLIST_PREPEND(AvahiRecordBrowser, record_browsers, client->record_browsers, b);
+
+ if (!(b->name = avahi_strdup(name))) {
+ avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
+ goto fail;
+ }
+
+ if (!(message = dbus_message_new_method_call(AVAHI_DBUS_NAME, AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "RecordBrowserNew"))) {
+ 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_STRING, &name,
+ DBUS_TYPE_UINT16, &clazz,
+ DBUS_TYPE_UINT16, &type,
+ DBUS_TYPE_UINT32, &u_flags,
+ DBUS_TYPE_INVALID)) {
+ avahi_client_set_errno(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)) {
+ avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
+ goto fail;
+ }
+
+ if (!dbus_message_get_args (reply, &error, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID) ||
+ dbus_error_is_set(&error) ||
+ !path) {
+ avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
+ goto fail;
+ }
+
+ if (!(b->path = avahi_strdup(path))) {
+
+ /* FIXME: We don't remove the object on the server side */
+
+ avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
+ goto fail;
+ }
+
+ dbus_message_unref(message);
+ dbus_message_unref(reply);
+
+ return b;
+
+fail:
+ if (dbus_error_is_set(&error)) {
+ avahi_client_set_dbus_error(client, &error);
+ dbus_error_free(&error);
+ }
+
+ if (b)
+ avahi_record_browser_free(b);
+
+ if (message)
+ dbus_message_unref(message);
+
+ if (reply)
+ dbus_message_unref(reply);
+
+ return NULL;
+}
+
+AvahiClient* avahi_record_browser_get_client (AvahiRecordBrowser *b) {
+ assert(b);
+ return b->client;
+}
+
+int avahi_record_browser_free (AvahiRecordBrowser *b) {
+ AvahiClient *client;
+ int r = AVAHI_OK;
+
+ assert(b);
+ client = b->client;
+
+ if (b->path && avahi_client_is_connected(b->client))
+ r = avahi_client_simple_method_call(client, b->path, AVAHI_DBUS_INTERFACE_RECORD_BROWSER, "Free");
+
+ AVAHI_LLIST_REMOVE(AvahiRecordBrowser, record_browsers, b->client->record_browsers, b);
+
+ avahi_free(b->path);
+ avahi_free(b->name);
+ avahi_free(b);
+ return r;
+}
+
+DBusHandlerResult avahi_record_browser_event(AvahiClient *client, AvahiBrowserEvent event, DBusMessage *message) {
+ AvahiRecordBrowser *b = NULL;
+ DBusError error;
+ const char *path;
+ char *name;
+ int32_t interface, protocol;
+ uint32_t flags = 0;
+ uint16_t clazz, type;
+ void *rdata = NULL;
+ int rdata_size = 0;
+
+ dbus_error_init (&error);
+
+ if (!(path = dbus_message_get_path(message)))
+ goto fail;
+
+ for (b = client->record_browsers; b; b = b->record_browsers_next)
+ if (strcmp (b->path, path) == 0)
+ break;
+
+ if (!b)
+ goto fail;
+
+ interface = b->interface;
+ protocol = b->protocol;
+ clazz = b->clazz;
+ type = b->type;
+ name = b->name;
+
+ switch (event) {
+ case AVAHI_BROWSER_NEW:
+ case AVAHI_BROWSER_REMOVE: {
+ DBusMessageIter iter, sub;
+ int j;
+
+ if (!dbus_message_get_args (
+ message, &error,
+ DBUS_TYPE_INT32, &interface,
+ DBUS_TYPE_INT32, &protocol,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_UINT16, &clazz,
+ DBUS_TYPE_UINT16, &type,
+ DBUS_TYPE_INVALID) ||
+ dbus_error_is_set(&error)) {
+ fprintf(stderr, "Failed to parse browser event.\n");
+ goto fail;
+ }
+
+
+ dbus_message_iter_init(message, &iter);
+
+ for (j = 0; j < 5; 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_BYTE)
+ goto fail;
+
+ dbus_message_iter_recurse(&iter, &sub);
+ dbus_message_iter_get_fixed_array(&sub, &rdata, &rdata_size);
+
+ dbus_message_iter_next(&iter);
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32)
+ goto fail;
+
+ dbus_message_iter_get_basic(&iter, &flags);
+
+ break;
+ }
+
+ case AVAHI_BROWSER_CACHE_EXHAUSTED:
+ case AVAHI_BROWSER_ALL_FOR_NOW:
+ break;
+
+ case AVAHI_BROWSER_FAILURE: {
+ char *etxt;
+
+ if (!dbus_message_get_args(
+ message, &error,
+ DBUS_TYPE_STRING, &etxt,
+ DBUS_TYPE_INVALID) ||
+ dbus_error_is_set (&error)) {
+ fprintf(stderr, "Failed to parse browser event.\n");
+ goto fail;
+ }
+
+ avahi_client_set_errno(b->client, avahi_error_dbus_to_number(etxt));
+ break;
+ }
+ }
+
+ b->callback(b, (AvahiIfIndex) interface, (AvahiProtocol) protocol, event, name, clazz, type, rdata, (size_t) rdata_size, (AvahiLookupResultFlags) flags, b->userdata);
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+
+fail:
+ dbus_error_free (&error);
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
diff --git a/avahi-client/client.c b/avahi-client/client.c
index 2fd5123..54d19e5 100644
--- a/avahi-client/client.c
+++ b/avahi-client/client.c
@@ -260,6 +260,18 @@ static DBusHandlerResult filter_func(DBusConnection *bus, DBusMessage *message,
return avahi_address_resolver_event (client, AVAHI_RESOLVER_FOUND, message);
else if (dbus_message_is_signal(message, AVAHI_DBUS_INTERFACE_ADDRESS_RESOLVER, "Failure"))
return avahi_address_resolver_event (client, AVAHI_RESOLVER_FAILURE, message);
+
+ else if (dbus_message_is_signal(message, AVAHI_DBUS_INTERFACE_RECORD_BROWSER, "ItemNew"))
+ return avahi_record_browser_event (client, AVAHI_BROWSER_NEW, message);
+ else if (dbus_message_is_signal(message, AVAHI_DBUS_INTERFACE_RECORD_BROWSER, "ItemRemove"))
+ return avahi_record_browser_event (client, AVAHI_BROWSER_REMOVE, message);
+ else if (dbus_message_is_signal(message, AVAHI_DBUS_INTERFACE_RECORD_BROWSER, "CacheExhausted"))
+ return avahi_record_browser_event (client, AVAHI_BROWSER_CACHE_EXHAUSTED, message);
+ else if (dbus_message_is_signal(message, AVAHI_DBUS_INTERFACE_RECORD_BROWSER, "AllForNow"))
+ return avahi_record_browser_event (client, AVAHI_BROWSER_ALL_FOR_NOW, message);
+ else if (dbus_message_is_signal(message, AVAHI_DBUS_INTERFACE_RECORD_BROWSER, "Failure"))
+ return avahi_record_browser_event (client, AVAHI_BROWSER_FAILURE, message);
+
else {
fprintf(stderr, "WARNING: Unhandled message: interface=%s, path=%s, member=%s\n",
@@ -446,6 +458,7 @@ AvahiClient *avahi_client_new(const AvahiPoll *poll_api, AvahiClientFlags flags,
AVAHI_LLIST_HEAD_INIT(AvahiServiceResolver, client->service_resolvers);
AVAHI_LLIST_HEAD_INIT(AvahiHostNameResolver, client->host_name_resolvers);
AVAHI_LLIST_HEAD_INIT(AvahiAddressResolver, client->address_resolvers);
+ AVAHI_LLIST_HEAD_INIT(AvahiRecordBrowser, client->record_browsers);
if (!(client->bus = avahi_dbus_bus_get(&error)) || dbus_error_is_set(&error)) {
if (ret_error)
@@ -558,6 +571,15 @@ void avahi_client_free(AvahiClient *client) {
while (client->service_resolvers)
avahi_service_resolver_free(client->service_resolvers);
+ while (client->host_name_resolvers)
+ avahi_host_name_resolver_free(client->host_name_resolvers);
+
+ while (client->address_resolvers)
+ avahi_address_resolver_free(client->address_resolvers);
+
+ while (client->record_browsers)
+ avahi_record_browser_free(client->record_browsers);
+
if (client->bus) {
dbus_connection_disconnect(client->bus);
dbus_connection_unref(client->bus);
diff --git a/avahi-client/entrygroup.c b/avahi-client/entrygroup.c
index 003b17c..162f2c4 100644
--- a/avahi-client/entrygroup.c
+++ b/avahi-client/entrygroup.c
@@ -700,8 +700,6 @@ fail:
dbus_message_unref(reply);
return r;
-
-
}
/** Add a host/address pair */
diff --git a/avahi-client/internal.h b/avahi-client/internal.h
index ef629e6..7a79dd7 100644
--- a/avahi-client/internal.h
+++ b/avahi-client/internal.h
@@ -50,6 +50,7 @@ struct AvahiClient {
AVAHI_LLIST_HEAD(AvahiServiceResolver, service_resolvers);
AVAHI_LLIST_HEAD(AvahiHostNameResolver, host_name_resolvers);
AVAHI_LLIST_HEAD(AvahiAddressResolver, address_resolvers);
+ AVAHI_LLIST_HEAD(AvahiRecordBrowser, record_browsers);
};
struct AvahiEntryGroup {
@@ -138,6 +139,19 @@ struct AvahiAddressResolver {
AvahiProtocol protocol;
};
+struct AvahiRecordBrowser {
+ char *path;
+ AvahiClient *client;
+ AvahiRecordBrowserCallback callback;
+ void *userdata;
+ AVAHI_LLIST_FIELDS(AvahiRecordBrowser, record_browsers);
+
+ char *name;
+ uint16_t clazz, type;
+ AvahiIfIndex interface;
+ AvahiProtocol protocol;
+};
+
int avahi_client_set_errno (AvahiClient *client, int error);
int avahi_client_set_dbus_error(AvahiClient *client, DBusError *error);
@@ -146,6 +160,7 @@ void avahi_entry_group_set_state(AvahiEntryGroup *group, AvahiEntryGroupState st
DBusHandlerResult avahi_domain_browser_event (AvahiClient *client, AvahiBrowserEvent event, DBusMessage *message);
DBusHandlerResult avahi_service_type_browser_event (AvahiClient *client, AvahiBrowserEvent event, DBusMessage *message);
DBusHandlerResult avahi_service_browser_event (AvahiClient *client, AvahiBrowserEvent event, DBusMessage *message);
+DBusHandlerResult avahi_record_browser_event(AvahiClient *client, AvahiBrowserEvent event, DBusMessage *message);
DBusHandlerResult avahi_service_resolver_event (AvahiClient *client, AvahiResolverEvent event, DBusMessage *message);
DBusHandlerResult avahi_host_name_resolver_event (AvahiClient *client, AvahiResolverEvent event, DBusMessage *message);
diff --git a/avahi-client/lookup.h b/avahi-client/lookup.h
index f2db9ab..e96bcf7 100644
--- a/avahi-client/lookup.h
+++ b/avahi-client/lookup.h
@@ -58,14 +58,41 @@ typedef struct AvahiHostNameResolver AvahiHostNameResolver;
/** An address resolver object */
typedef struct AvahiAddressResolver AvahiAddressResolver;
+/** A record browser object */
+typedef struct AvahiRecordBrowser AvahiRecordBrowser;
+
/** 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);
+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);
+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);
+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) (
@@ -105,6 +132,20 @@ typedef void (*AvahiAddressResolverCallback) (
AvahiLookupResultFlags flags,
void *userdata);
+/** The function prototype for the callback of an AvahiRecordBrowser */
+typedef void (*AvahiRecordBrowserCallback) (
+ AvahiRecordBrowser *b,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ AvahiBrowserEvent event,
+ const char *name,
+ uint16_t clazz,
+ uint16_t type,
+ const void *rdata,
+ size_t size,
+ AvahiLookupResultFlags flags,
+ void *userdata);
+
/** Browse for domains on the local network */
AvahiDomainBrowser* avahi_domain_browser_new (
AvahiClient *client,
@@ -207,6 +248,24 @@ AvahiClient* avahi_address_resolver_get_client (AvahiAddressResolver *);
/** Free a AvahiAddressResolver resolver object */
int avahi_address_resolver_free(AvahiAddressResolver *r);
+/** Browse for records of a type on the local network */
+AvahiRecordBrowser* avahi_record_browser_new(
+ AvahiClient *client,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ const char *name,
+ uint16_t clazz,
+ uint16_t type,
+ AvahiLookupFlags flags,
+ AvahiRecordBrowserCallback callback,
+ void *userdata);
+
+/** Get the parent client of an AvahiRecordBrowser object */
+AvahiClient* avahi_record_browser_get_client(AvahiRecordBrowser *);
+
+/* Cleans up and frees an AvahiRecordBrowser object */
+int avahi_record_browser_free(AvahiRecordBrowser *);
+
AVAHI_C_DECL_END
#endif
diff --git a/avahi-client/rr-test.c b/avahi-client/rr-test.c
new file mode 100644
index 0000000..9fffa5d
--- /dev/null
+++ b/avahi-client/rr-test.c
@@ -0,0 +1,113 @@
+/* $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.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <assert.h>
+
+#include <avahi-client/client.h>
+#include <avahi-client/lookup.h>
+#include <avahi-common/error.h>
+#include <avahi-common/simple-watch.h>
+#include <avahi-common/malloc.h>
+
+static void hexdump(const void* p, size_t size) {
+ const uint8_t *c = p;
+ assert(p);
+
+ printf("Dumping %lu bytes from %p:\n", (unsigned long) size, p);
+
+ while (size > 0) {
+ unsigned i;
+
+ for (i = 0; i < 16; i++) {
+ if (i < size)
+ printf("%02x ", c[i]);
+ else
+ printf(" ");
+ }
+
+ for (i = 0; i < 16; i++) {
+ if (i < size)
+ printf("%c", c[i] >= 32 && c[i] < 127 ? c[i] : '.');
+ else
+ printf(" ");
+ }
+
+ printf("\n");
+
+ c += 16;
+
+ if (size <= 16)
+ break;
+
+ size -= 16;
+ }
+}
+
+static void callback(
+ AVAHI_GCC_UNUSED AvahiRecordBrowser *r,
+ AVAHI_GCC_UNUSED AvahiIfIndex interface,
+ AVAHI_GCC_UNUSED AvahiProtocol protocol,
+ AvahiBrowserEvent event,
+ const char *name,
+ uint16_t clazz,
+ uint16_t type,
+ const void *rdata,
+ size_t rdata_size,
+ AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
+ AVAHI_GCC_UNUSED void *userdata) {
+
+ fprintf(stderr, "%i name=%s class=%u type=%u\n", event, name, clazz, type);
+
+ if (rdata)
+ hexdump(rdata, rdata_size);
+}
+
+int main(AVAHI_GCC_UNUSED int argc, AVAHI_GCC_UNUSED char *argv[]) {
+
+ AvahiSimplePoll *simple_poll;
+ const AvahiPoll *poll_api;
+ AvahiClient *client;
+ AvahiRecordBrowser *r;
+
+ simple_poll = avahi_simple_poll_new();
+ assert(simple_poll);
+
+ poll_api = avahi_simple_poll_get(simple_poll);
+ assert(poll_api);
+
+ client = avahi_client_new(poll_api, 0, NULL, NULL, NULL);
+ assert(client);
+
+ r = avahi_record_browser_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "ecstasy.local", AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_HINFO, 0, callback, simple_poll);
+ assert(r);
+
+ avahi_simple_poll_loop(simple_poll);
+
+ avahi_client_free(client);
+ avahi_simple_poll_free(simple_poll);
+
+ return 0;
+}