]> git.meshlink.io Git - catta/commitdiff
* update avahi_address_parse() to work with AF_UNSPEC address family
authorLennart Poettering <lennart@poettering.net>
Thu, 16 Jun 2005 16:32:27 +0000 (16:32 +0000)
committerLennart Poettering <lennart@poettering.net>
Thu, 16 Jun 2005 16:32:27 +0000 (16:32 +0000)
* complete simple protocol
* defer scanning already cached RRs when browsing into its own main loop job

git-svn-id: file:///home/lennart/svn/public/avahi/trunk@114 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe

avahi-common/address.c
avahi-core/browse.c
avahi-core/resolve-host-name.c
avahi-daemon/main.c
avahi-daemon/main.h [new file with mode: 0644]
avahi-daemon/simple-protocol.c

index 34847070aa30e7ff4ba79c9c63eed5a4b9722873..3e6fc9754c438ea6a2f08c7b7136919ae430734a 100644 (file)
@@ -115,10 +115,20 @@ AvahiAddress *avahi_address_parse(const char *s, guchar family, AvahiAddress *re
     g_assert(ret_addr);
     g_assert(s);
 
-    if (inet_pton(family, s, ret_addr->data.data) < 0)
-        return NULL;
-
-    ret_addr->family = family;
+    if (family == AF_UNSPEC) {
+        if (inet_pton(AF_INET, s, ret_addr->data.data) <= 0) {
+            if (inet_pton(AF_INET6, s, ret_addr->data.data) <= 0)
+                return NULL;
+            else
+                ret_addr->family = AF_INET6;
+        } else
+            ret_addr->family = AF_INET;
+    } else {
+        if (inet_pton(family, s, ret_addr->data.data) <= 0)
+            return NULL;
+        
+        ret_addr->family = family;
+    }
     
     return ret_addr;
 }
index deeb465c14a1dbd6acfadd498e29a19ceecf37a8..10d71cbc514f9a9ba66c825989ec1ebedeae5a5d 100644 (file)
@@ -40,6 +40,7 @@ struct AvahiRecordBrowser {
 
     AvahiRecordBrowserCallback callback;
     gpointer userdata;
+    guint scan_idle_source;
 
     AVAHI_LLIST_FIELDS(AvahiRecordBrowser, browser);
     AVAHI_LLIST_FIELDS(AvahiRecordBrowser, by_key);
@@ -102,6 +103,17 @@ static void scan_interface_callback(AvahiInterfaceMonitor *m, AvahiInterface *i,
     avahi_cache_walk(i->cache, s->key, scan_cache_callback, &cbdata);
 }
 
+gboolean scan_idle_callback(gpointer data) {
+    AvahiRecordBrowser *b = data;
+    g_assert(b);
+
+    /* Scan the caches */
+    avahi_interface_monitor_walk(b->server->monitor, b->interface, b->protocol, scan_interface_callback, b);
+    b->scan_idle_source = (guint) -1;
+
+    return FALSE;
+}
+
 AvahiRecordBrowser *avahi_record_browser_new(AvahiServer *server, gint interface, guchar protocol, AvahiKey *key, AvahiRecordBrowserCallback callback, gpointer userdata) {
     AvahiRecordBrowser *b, *t;
     GTimeVal tv;
@@ -135,9 +147,8 @@ AvahiRecordBrowser *avahi_record_browser_new(AvahiServer *server, gint interface
     AVAHI_LLIST_PREPEND(AvahiRecordBrowser, by_key, t, b);
     g_hash_table_replace(server->record_browser_hashtable, key, t);
 
-    /* Scan the caches */
-    avahi_interface_monitor_walk(b->server->monitor, b->interface, b->protocol, scan_interface_callback, b);
-    
+    /* The currenlty cached entries are scanned a bit later */
+    b->scan_idle_source = g_idle_add_full(G_PRIORITY_HIGH, scan_idle_callback, b, NULL);
     return b;
 }
 
@@ -151,6 +162,12 @@ void avahi_record_browser_free(AvahiRecordBrowser *b) {
     if (b->time_event) {
         avahi_time_event_queue_remove(b->server->time_event_queue, b->time_event);
         b->time_event = NULL;
+
+        if (b->scan_idle_source != (guint) -1) {
+            g_source_remove(b->scan_idle_source);
+            b->scan_idle_source = (guint) -1;
+        }
+
     }
 }
 
@@ -171,6 +188,9 @@ void avahi_record_browser_destroy(AvahiRecordBrowser *b) {
     if (b->time_event)
         avahi_time_event_queue_remove(b->server->time_event_queue, b->time_event);
     avahi_key_unref(b->key);
+
+    if (b->scan_idle_source != (guint) -1)
+        g_source_remove(b->scan_idle_source);
     
     g_free(b);
 }
index f29b575f51b8b057c40a6d35a46268e964c5a735..2cfd43569b51fab43fb7e1cb1fd7df9ce16dec47 100644 (file)
@@ -125,7 +125,6 @@ AvahiHostNameResolver *avahi_host_name_resolver_new(AvahiServer *server, gint in
     r->time_event = avahi_time_event_queue_add(server->time_event_queue, &tv, time_event_callback, r);
 
     AVAHI_LLIST_PREPEND(AvahiHostNameResolver, resolver, server->host_name_resolvers, r);
-
     
     if (aprotocol == AF_INET || aprotocol == AF_UNSPEC) {
         k = avahi_key_new(host_name, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_A);
index 3875865c380441aa798e8cb8c221fef024a36b3b..7b3f209aae57d1a91f0617f50a6d29270cf55f55 100644 (file)
 #include <dbus/dbus.h>
 #include <dbus/dbus-glib-lowlevel.h>
 
+#include "main.h"
 #include "simple-protocol.h"
 
 #define DBUS_SERVICE_AVAHI "org.freedesktop.Avahi"
 
+AvahiServer *avahi_server = NULL;
+
 static DBusHandlerResult
 do_register (DBusConnection *conn, DBusMessage *message)
 {
@@ -112,12 +115,30 @@ signal_filter (DBusConnection *conn, DBusMessage *message, void *user_data)
 
     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 }
-                
+
+static void server_callback(AvahiServer *s, AvahiServerState state, gpointer userdata) {
+    g_assert(s);
+
+    if (state == AVAHI_SERVER_RUNNING)
+        g_message("Server startup complete.  Host name is <%s>", avahi_server_get_host_name_fqdn(s));
+    else if (state == AVAHI_SERVER_COLLISION) {
+        gchar *n;
+        n = avahi_alternative_host_name(avahi_server_get_host_name(s));
+        g_message("Host name conflict, retrying with <%s>", n);
+        avahi_server_set_host_name(s, n);
+        g_free(n);
+    }
+}
+
 int main(int argc, char *argv[]) {
     GMainLoop *loop = NULL;
     DBusConnection *bus = NULL;
     DBusError error;
-    gint r = -1;
+    gint r = 255;
+    AvahiServer *server = NULL;
+    AvahiServerConfig config;
+
+    avahi_server_config_init(&config);
 
     loop = g_main_loop_new(NULL, FALSE);
 
@@ -162,6 +183,9 @@ int main(int argc, char *argv[]) {
     if (simple_protocol_setup(NULL) < 0)
         goto finish;
 
+    if (!(avahi_server = avahi_server_new(NULL, &config, server_callback, NULL)))
+        goto finish;
+
     g_main_loop_run(loop);
 
     r = 0;
@@ -175,8 +199,13 @@ finish:
         dbus_connection_unref(bus);
     }
 
+    if (avahi_server)
+        avahi_server_free(avahi_server);
+    
     if (loop)
         g_main_loop_unref(loop);
 
+    avahi_server_config_free(&config);
+
     return r;
 }
diff --git a/avahi-daemon/main.h b/avahi-daemon/main.h
new file mode 100644 (file)
index 0000000..8db60e4
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef foomainhfoo
+#define foomainhfoo
+
+/* $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 <avahi-core/core.h>
+
+extern AvahiServer *avahi_server;
+
+#endif
index 71dd63918fd3055c4fa7ddc781e16326855d4ea2..91a8287e667ff833cc8702c09eb4a62a57a7d548 100644 (file)
@@ -36,6 +36,7 @@
 #include <avahi-core/llist.h>
 
 #include "simple-protocol.h"
+#include "main.h"
 
 #define BUFFER_SIZE (10*1024)
 
 typedef struct Client Client;
 typedef struct Server Server;
 
+typedef enum {
+    CLIENT_IDLE,
+    CLIENT_RESOLVE_HOSTNAME,
+    CLIENT_RESOLVE_ADDRESS,
+    CLIENT_DEAD
+} ClientState;
+
 struct Client {
     Server *server;
+
+    ClientState state;
     
     gint fd;
     GPollFD poll_fd;
 
     gchar inbuf[BUFFER_SIZE], outbuf[BUFFER_SIZE];
     guint inbuf_length, outbuf_length;
+
+    AvahiHostNameResolver *host_name_resolver;
+    AvahiAddressResolver *address_resolver;
     
     AVAHI_LLIST_FIELDS(Client, clients);
 };
@@ -76,6 +89,12 @@ static void client_free(Client *c) {
 
     g_assert(c->server->n_clients >= 1);
     c->server->n_clients--;
+
+    if (c->host_name_resolver)
+        avahi_host_name_resolver_free(c->host_name_resolver);
+
+    if (c->address_resolver)
+        avahi_address_resolver_free(c->address_resolver);
     
     g_source_remove_poll(&c->server->source, &c->poll_fd);
     close(c->fd);
@@ -91,9 +110,13 @@ static void client_new(Server *s, int fd) {
     c = g_new(Client, 1);
     c->server = s;
     c->fd = fd;
+    c->state = CLIENT_IDLE;
 
     c->inbuf_length = c->outbuf_length = 0;
 
+    c->host_name_resolver = NULL;
+    c->address_resolver = NULL;
+
     memset(&c->poll_fd, 0, sizeof(GPollFD));
     c->poll_fd.fd = fd;
     c->poll_fd.events = G_IO_IN|G_IO_ERR|G_IO_HUP;
@@ -117,16 +140,101 @@ static void client_output(Client *c, const guint8*data, guint size) {
 
     memcpy(c->outbuf + c->outbuf_length, data, m);
     c->outbuf_length += m;
+
+    c->poll_fd.events |= G_IO_OUT;
+}
+
+static void client_output_printf(Client *c, gchar *format, ...) {
+    gchar txt[256];
+    va_list ap;
+    
+    va_start(ap, format);
+    vsnprintf(txt, sizeof(txt), format, ap);
+    va_end(ap);
+
+    client_output(c, (guint8*) txt, strlen(txt));
+}
+
+static void host_name_resolver_callback(AvahiHostNameResolver *r, gint iface, guchar protocol, AvahiBrowserEvent event, const gchar *hostname, const AvahiAddress *a, gpointer userdata) {
+    Client *c = userdata;
+    
+    g_assert(c);
+
+
+    if (event == AVAHI_RESOLVER_TIMEOUT)
+        client_output_printf(c, "- Query timed out\n");
+    else {
+        gchar t[64];
+        avahi_address_snprint(t, sizeof(t), a);
+        client_output_printf(c, "+ %s\n", t);
+    }
+
+    c->state = CLIENT_DEAD;
+}
+
+static void address_resolver_callback(AvahiAddressResolver *r, gint iface, guchar protocol, AvahiBrowserEvent event, const AvahiAddress *a, const gchar *hostname, gpointer userdata) {
+    Client *c = userdata;
+    
+    g_assert(c);
+
+    if (event == AVAHI_RESOLVER_TIMEOUT)
+        client_output_printf(c, "- Query timed out\n");
+    else 
+        client_output_printf(c, "+ %s\n", hostname);
+
+    c->state = CLIENT_DEAD;
 }
 
 static void handle_line(Client *c, const gchar *s) {
-    gchar t[256];
+    gchar cmd[64], arg[64];
+    gint n_args;
 
     g_assert(c);
     g_assert(s);
 
-    snprintf(t, sizeof(t), "you said <%s>\n", s);
-    client_output(c, (guint8*) t, strlen(t));
+    if (c->state != CLIENT_IDLE)
+        return;
+
+    if ((n_args = sscanf(s, "%63s %63s", cmd, arg)) < 1 ) {
+        client_output_printf(c, "- Failed to parse command, try \"HELP\".\n");
+        c->state = CLIENT_DEAD;
+        return;
+    }
+
+    if (strcmp(cmd, "HELP") == 0) {
+        client_output_printf(c,
+                             "+ Available commands are:\n"
+                             "+      RESOLVE-HOSTNAME <hostname>\n"
+                             "+      RESOLVE-HOSTNAME-IPV6 <hostname>\n"
+                             "+      RESOLVE-HOSTNAME-IPV4 <hostname>\n"
+                             "+      RESOLVE-ADDRESS <address>\n");
+        c->state = CLIENT_DEAD; }
+    else if (strcmp(cmd, "FUCK") == 0 && n_args == 1) {
+        client_output_printf(c, "FUCK: Go fuck yourself!\n");
+        c->state = CLIENT_DEAD;
+    } else if (strcmp(cmd, "RESOLVE-HOSTNAME-IPV4") == 0 && n_args == 2) {
+        c->state = CLIENT_RESOLVE_HOSTNAME;
+        c->host_name_resolver = avahi_host_name_resolver_new(avahi_server, -1, AF_UNSPEC, arg, AF_INET, host_name_resolver_callback, c);
+    } else if (strcmp(cmd, "RESOLVE-HOSTNAME-IPV6") == 0 && n_args == 2) {
+        c->state = CLIENT_RESOLVE_HOSTNAME;
+        c->host_name_resolver = avahi_host_name_resolver_new(avahi_server, -1, AF_UNSPEC, arg, AF_INET6, host_name_resolver_callback, c);
+    } else if (strcmp(cmd, "RESOLVE-HOSTNAME") == 0 && n_args == 2) {
+        c->state = CLIENT_RESOLVE_HOSTNAME;
+        c->host_name_resolver = avahi_host_name_resolver_new(avahi_server, -1, AF_UNSPEC, arg, AF_UNSPEC, host_name_resolver_callback, c);
+    } else if (strcmp(cmd, "RESOLVE-ADDRESS") == 0 && n_args == 2) {
+        AvahiAddress addr;
+        
+        if (!(avahi_address_parse(arg, AF_UNSPEC, &addr))) {
+            client_output_printf(c, "- Failed to parse address \"%s\".\n", arg);
+            c->state = CLIENT_DEAD;
+        } else {
+            c->state = CLIENT_RESOLVE_ADDRESS;
+            c->address_resolver = avahi_address_resolver_new(avahi_server, -1, AF_UNSPEC, &addr, address_resolver_callback, c);
+        }
+    } else {
+        client_output_printf(c, "- Invalid command \"%s\", try \"HELP\".\n", cmd);
+        c->state = CLIENT_DEAD;
+    }
 }
 
 static void handle_input(Client *c) {
@@ -181,6 +289,11 @@ static void client_work(Client *c) {
         
         if (c->outbuf_length)
             memmove(c->outbuf, c->outbuf + r, c->outbuf_length - r);
+
+        if (c->outbuf_length == 0 && c->state == CLIENT_DEAD) {
+            client_free(c);
+            return;
+        }
     }
 
     c->poll_fd.events =