summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2005-06-16 16:32:27 +0000
committerLennart Poettering <lennart@poettering.net>2005-06-16 16:32:27 +0000
commitf334deaf9d630782be3f7f535265ff7488162f85 (patch)
treeab26174979fd549479b58013e73aec8fe9efdade
parent969d343114a3ad07e9f1617ec1df465ca501d222 (diff)
* update avahi_address_parse() to work with AF_UNSPEC address family
* 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
-rw-r--r--avahi-common/address.c18
-rw-r--r--avahi-core/browse.c26
-rw-r--r--avahi-core/resolve-host-name.c1
-rw-r--r--avahi-daemon/main.c33
-rw-r--r--avahi-daemon/main.h29
-rw-r--r--avahi-daemon/simple-protocol.c119
6 files changed, 213 insertions, 13 deletions
diff --git a/avahi-common/address.c b/avahi-common/address.c
index 3484707..3e6fc97 100644
--- a/avahi-common/address.c
+++ b/avahi-common/address.c
@@ -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;
}
diff --git a/avahi-core/browse.c b/avahi-core/browse.c
index deeb465..10d71cb 100644
--- a/avahi-core/browse.c
+++ b/avahi-core/browse.c
@@ -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);
}
diff --git a/avahi-core/resolve-host-name.c b/avahi-core/resolve-host-name.c
index f29b575..2cfd435 100644
--- a/avahi-core/resolve-host-name.c
+++ b/avahi-core/resolve-host-name.c
@@ -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);
diff --git a/avahi-daemon/main.c b/avahi-daemon/main.c
index 3875865..7b3f209 100644
--- a/avahi-daemon/main.c
+++ b/avahi-daemon/main.c
@@ -29,10 +29,13 @@
#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
index 0000000..8db60e4
--- /dev/null
+++ b/avahi-daemon/main.h
@@ -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
diff --git a/avahi-daemon/simple-protocol.c b/avahi-daemon/simple-protocol.c
index 71dd639..91a8287 100644
--- a/avahi-daemon/simple-protocol.c
+++ b/avahi-daemon/simple-protocol.c
@@ -36,6 +36,7 @@
#include <avahi-core/llist.h>
#include "simple-protocol.h"
+#include "main.h"
#define BUFFER_SIZE (10*1024)
@@ -47,14 +48,26 @@
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 =