[avahi] [PATCH 1/2] avahi-daemon: extend simple protocol to browse services

Thomas Petazzoni thomas.petazzoni at free-electrons.com
Fri May 18 06:08:06 PDT 2012


The Avahi simple protocol provides a way of accessing some of the
Avahi services over an Unix socket. Currently used by the nss-mdns
plugin for the glibc name resolution services, it provides a
lightweight and convenient way to access Avahi services.

This patch extends this simple protocol to support service
browsing. It is useful for embedded devices in which D-Bus is not
present and would be a too big addition: this simple protocol
extension extends the avahi-daemon binary size by 740 bytes, which is
several order of magnitudes smaller than adding D-Bus.

The new command added is BROWSE-SERVICE-TYPE, which takes as argument
the service type to browse.

Signed-off-by: Thomas Petazzoni <thomas.petazzoni at free-electrons.com>
---
 avahi-daemon/simple-protocol.c |   92 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 91 insertions(+), 1 deletion(-)

diff --git a/avahi-daemon/simple-protocol.c b/avahi-daemon/simple-protocol.c
index 3e0ebb1..3efb99a 100644
--- a/avahi-daemon/simple-protocol.c
+++ b/avahi-daemon/simple-protocol.c
@@ -67,6 +67,7 @@ typedef enum {
     CLIENT_RESOLVE_HOSTNAME,
     CLIENT_RESOLVE_ADDRESS,
     CLIENT_BROWSE_DNS_SERVERS,
+    CLIENT_BROWSE_SERVICE_TYPE,
     CLIENT_DEAD
 } ClientState;
 
@@ -84,6 +85,7 @@ struct Client {
     AvahiSHostNameResolver *host_name_resolver;
     AvahiSAddressResolver *address_resolver;
     AvahiSDNSServerBrowser *dns_server_browser;
+    AvahiSServiceBrowser *service_browser;
 
     AvahiProtocol afquery;
 
@@ -119,6 +121,9 @@ static void client_free(Client *c) {
     if (c->dns_server_browser)
         avahi_s_dns_server_browser_free(c->dns_server_browser);
 
+    if (c->service_browser)
+        avahi_s_service_browser_free(c->service_browser);
+
     c->server->poll_api->watch_free(c->watch);
     close(c->fd);
 
@@ -263,6 +268,87 @@ static void dns_server_browser_callback(
     }
 }
 
+static void service_resolver_callback(
+    AVAHI_GCC_UNUSED AvahiSServiceResolver *r,
+    AVAHI_GCC_UNUSED AvahiIfIndex interface,
+    AVAHI_GCC_UNUSED AvahiProtocol protocol,
+    AvahiResolverEvent event,
+    const char *name,
+    const char *type,
+    const char *domain,
+    const char *host_name,
+    const AvahiAddress *a,
+    uint16_t port,
+    AVAHI_GCC_UNUSED AvahiStringList *txt,
+    AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
+    void *userdata)
+{
+    char astr[AVAHI_ADDRESS_STR_MAX];
+    Client *c = userdata;
+
+    assert(c);
+
+    switch(event) {
+    case AVAHI_RESOLVER_FOUND:
+        avahi_address_snprint(astr, sizeof(astr), a);
+        client_output_printf(c, "> %s,%s,%s,%s,%s,%d\n",
+                             name, type, domain, host_name, astr, port);
+        break;
+    case AVAHI_RESOLVER_FAILURE:
+        client_output_printf(c, "%+i %s\n", avahi_server_errno(avahi_server), avahi_strerror(avahi_server_errno(avahi_server)));
+        c->state = CLIENT_DEAD;
+        break;
+    }
+
+    avahi_s_service_resolver_free(r);
+}
+
+static void service_browser_callback(
+    AVAHI_GCC_UNUSED AvahiSServiceBrowser *b,
+    AvahiIfIndex interface,
+    AvahiProtocol protocol,
+    AvahiBrowserEvent event,
+    const char *name,
+    const char *type,
+    const char *domain,
+    AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
+    void *userdata) {
+
+    Client *c = userdata;
+    AvahiSServiceResolver *r;
+
+    assert(c);
+
+    switch (event) {
+    case AVAHI_BROWSER_FAILURE:
+        client_output_printf(c, "%+i %s\n", avahi_server_errno(avahi_server), avahi_strerror(avahi_server_errno(avahi_server)));
+        c->state = CLIENT_DEAD;
+        break;
+
+    case AVAHI_BROWSER_ALL_FOR_NOW:
+        client_output_printf(c, "+ End\n");
+        c->state = CLIENT_DEAD;
+        break;
+
+    case AVAHI_BROWSER_CACHE_EXHAUSTED:
+        break;
+
+    case AVAHI_BROWSER_NEW:
+        r = avahi_s_service_resolver_new(avahi_server, interface, protocol, name,
+                                     type, domain, AVAHI_PROTO_UNSPEC, AVAHI_LOOKUP_USE_MULTICAST,
+                                     service_resolver_callback, c);
+        if (! r) {
+            c->state = CLIENT_DEAD;
+            break;
+        }
+
+        break;
+
+    case AVAHI_BROWSER_REMOVE:
+        break;
+    }
+}
+
 static void handle_line(Client *c, const char *s) {
     char cmd[64], arg[64];
     int n_args;
@@ -348,7 +434,11 @@ static void handle_line(Client *c, const char *s) {
         client_output_printf(c, "+ Browsing ...\n");
 
         avahi_log_debug(__FILE__": Got %s request.", cmd);
-
+    } else if (strcmp(cmd, "BROWSE-SERVICE-TYPE") == 0 && n_args == 2) {
+        c->state = CLIENT_BROWSE_SERVICE_TYPE;
+        if (!(c->service_browser = avahi_s_service_browser_new(avahi_server, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, arg, NULL, AVAHI_LOOKUP_USE_MULTICAST, service_browser_callback, c)))
+            goto fail;
+        client_output_printf(c, "+ Browsing ...\n");
     } else {
         client_output_printf(c, "%+i Invalid command \"%s\", try \"HELP\".\n", AVAHI_ERR_INVALID_OPERATION, cmd);
         c->state = CLIENT_DEAD;
-- 
1.7.9.5



More information about the avahi mailing list