From: Lennart Poettering Date: Sat, 30 Jul 2005 01:13:56 +0000 (+0000) Subject: * add new tool avahi-publish-address X-Git-Url: https://git.meshlink.io/?a=commitdiff_plain;h=48cfb3c876636d79dace3ebc8e82c946bc0b7ebf;p=catta * add new tool avahi-publish-address * avahi-publish-service: fail after 12 collisions * avahi-daemon: dump record data on SIGUSR1 to syslog * avahi-core: * improve dumping API * shorten response history time to 500ms, infriniging the RFC but fixing ping-pong behaviour on RR registration * remove gcc warning git-svn-id: file:///home/lennart/svn/public/avahi/trunk@195 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe --- diff --git a/avahi-core/announce.c b/avahi-core/announce.c index 0b7af8d..fe461de 100644 --- a/avahi-core/announce.c +++ b/avahi-core/announce.c @@ -208,7 +208,7 @@ static void go_to_initial_state(AvahiAnnouncement *a, gboolean immediately) { g_assert(a); e = a->entry; - + if ((e->flags & AVAHI_ENTRY_UNIQUE) && !(e->flags & AVAHI_ENTRY_NOPROBE)) a->state = AVAHI_PROBING; else if (!(e->flags & AVAHI_ENTRY_NOANNOUNCE)) { @@ -342,6 +342,8 @@ gboolean avahi_entry_probing(AvahiServer *s, AvahiEntry *e, AvahiInterface *i) { if (!(a = avahi_get_announcement(s, e, i))) return FALSE; + +/* avahi_log_debug("state: %i", a->state); */ return a->state == AVAHI_PROBING || diff --git a/avahi-core/avahi-test.c b/avahi-core/avahi-test.c index 669ca5b..5953937 100644 --- a/avahi-core/avahi-test.c +++ b/avahi-core/avahi-test.c @@ -40,9 +40,13 @@ static gboolean quit_timeout(gpointer data) { return FALSE; } +static void dump_line(const gchar *text, gpointer userdata) { + printf("%s\n", text); +} + static gboolean dump_timeout(gpointer data) { AvahiServer *Avahi = data; - avahi_server_dump(Avahi, stdout); + avahi_server_dump(Avahi, dump_line, NULL); return TRUE; } diff --git a/avahi-core/browse-domain.c b/avahi-core/browse-domain.c index 7a95611..30745f6 100644 --- a/avahi-core/browse-domain.c +++ b/avahi-core/browse-domain.c @@ -83,6 +83,10 @@ AvahiDomainBrowser *avahi_domain_browser_new(AvahiServer *server, gint interface case AVAHI_DOMAIN_BROWSER_BROWSE_LEGACY: n = g_strdup_printf("lb._dns-sd._udp.%s", b->domain_name); break; + + case AVAHI_DOMAIN_BROWSER_MAX: + g_assert(FALSE); + break; } g_assert(n); diff --git a/avahi-core/cache.c b/avahi-core/cache.c index 0a39194..7060433 100644 --- a/avahi-core/cache.c +++ b/avahi-core/cache.c @@ -342,26 +342,39 @@ void avahi_cache_update(AvahiCache *c, AvahiRecord *r, gboolean cache_flush, con /* g_free(txt); */ } +struct dump_data { + AvahiDumpCallback callback; + gpointer userdata; +}; + static void dump_callback(gpointer key, gpointer data, gpointer userdata) { AvahiCacheEntry *e = data; AvahiKey *k = key; + struct dump_data *dump_data = userdata; g_assert(k); g_assert(e); + g_assert(data); for (; e; e = e->by_key_next) { gchar *t = avahi_record_to_string(e->record); - fprintf((FILE*) userdata, "%s\n", t); + dump_data->callback(t, dump_data->userdata); g_free(t); } } -void avahi_cache_dump(AvahiCache *c, FILE *f) { +void avahi_cache_dump(AvahiCache *c, AvahiDumpCallback callback, gpointer userdata) { + struct dump_data data; + g_assert(c); - g_assert(f); + g_assert(callback); + + callback(";;; CACHE DUMP FOLLOWS ;;;", userdata); + + data.callback = callback; + data.userdata = userdata; - fprintf(f, ";;; CACHE DUMP FOLLOWS ;;;\n"); - g_hash_table_foreach(c->hash_table, dump_callback, f); + g_hash_table_foreach(c->hash_table, dump_callback, &data); } gboolean avahi_cache_entry_half_ttl(AvahiCache *c, AvahiCacheEntry *e) { diff --git a/avahi-core/cache.h b/avahi-core/cache.h index e4bdbc4..b6e3e8a 100644 --- a/avahi-core/cache.h +++ b/avahi-core/cache.h @@ -77,7 +77,7 @@ AvahiCacheEntry *avahi_cache_lookup_record(AvahiCache *c, AvahiRecord *r); void avahi_cache_update(AvahiCache *c, AvahiRecord *r, gboolean cache_flush, const AvahiAddress *a); -void avahi_cache_dump(AvahiCache *c, FILE *f); +void avahi_cache_dump(AvahiCache *c, AvahiDumpCallback callback, gpointer userdata); typedef gpointer AvahiCacheWalkCallback(AvahiCache *c, AvahiKey *pattern, AvahiCacheEntry *e, gpointer userdata); gpointer avahi_cache_walk(AvahiCache *c, AvahiKey *pattern, AvahiCacheWalkCallback cb, gpointer userdata); diff --git a/avahi-core/conformance-test.c b/avahi-core/conformance-test.c index e830982..f7eba12 100644 --- a/avahi-core/conformance-test.c +++ b/avahi-core/conformance-test.c @@ -39,8 +39,12 @@ static AvahiEntryGroup *group = NULL; static int try = 0; static AvahiServer *avahi = NULL; +static void dump_line(const gchar *text, gpointer userdata) { + printf("%s\n", text); +} + static gboolean dump_timeout(gpointer data) { - avahi_server_dump(avahi, stdout); + avahi_server_dump(avahi, dump_line, NULL); return TRUE; } @@ -96,7 +100,7 @@ int main(int argc, char *argv[]) { avahi = avahi_server_new(NULL, NULL, server_callback, NULL); create_service("gurke"); - avahi_server_dump(avahi, stdout); + avahi_server_dump(avahi, dump_line, NULL); loop = g_main_loop_new(NULL, FALSE); g_timeout_add(1000*5, dump_timeout, avahi); diff --git a/avahi-core/core.h b/avahi-core/core.h index 39a1db6..dbbd555 100644 --- a/avahi-core/core.h +++ b/avahi-core/core.h @@ -171,8 +171,11 @@ AvahiServerState avahi_server_get_state(AvahiServer *s); * has been read, NULL is returned. */ const AvahiRecord *avahi_server_iterate(AvahiServer *s, AvahiEntryGroup *g, void **state); -/** Dump the current server status to the specified FILE object */ -void avahi_server_dump(AvahiServer *s, FILE *f); +/** Callback prototype for avahi_server_dump() */ +typedef void (*AvahiDumpCallback)(const gchar *text, gpointer userdata); + +/** Dump the current server status by calling "callback" for each line. */ +void avahi_server_dump(AvahiServer *s, AvahiDumpCallback callback, gpointer userdata); /** Create a new entry group. The specified callback function is * called whenever the state of the group changes. Use entry group diff --git a/avahi-core/iface.c b/avahi-core/iface.c index 070ef6a..d068f28 100644 --- a/avahi-core/iface.c +++ b/avahi-core/iface.c @@ -600,17 +600,18 @@ gboolean avahi_interface_post_probe(AvahiInterface *i, AvahiRecord *record, gboo return FALSE; } -void avahi_dump_caches(AvahiInterfaceMonitor *m, FILE *f) { +void avahi_dump_caches(AvahiInterfaceMonitor *m, AvahiDumpCallback callback, gpointer userdata) { AvahiInterface *i; g_assert(m); for (i = m->interfaces; i; i = i->interface_next) { if (avahi_interface_relevant(i)) { - fprintf(f, "\n;;; INTERFACE %s.%i ;;;\n", i->hardware->name, i->protocol); - avahi_cache_dump(i->cache, f); + char ln[256]; + snprintf(ln, sizeof(ln), ";;; INTERFACE %s.%i ;;;", i->hardware->name, i->protocol); + callback(ln, userdata); + avahi_cache_dump(i->cache, callback, userdata); } } - fprintf(f, "\n"); } gboolean avahi_interface_relevant(AvahiInterface *i) { diff --git a/avahi-core/iface.h b/avahi-core/iface.h index 486207e..33d20f0 100644 --- a/avahi-core/iface.h +++ b/avahi-core/iface.h @@ -122,7 +122,7 @@ gboolean avahi_interface_post_query(AvahiInterface *i, AvahiKey *k, gboolean imm gboolean avahi_interface_post_response(AvahiInterface *i, AvahiRecord *record, gboolean flush_cache, const AvahiAddress *querier, gboolean immediately); gboolean avahi_interface_post_probe(AvahiInterface *i, AvahiRecord *p, gboolean immediately); -void avahi_dump_caches(AvahiInterfaceMonitor *m, FILE *f); +void avahi_dump_caches(AvahiInterfaceMonitor *m, AvahiDumpCallback callback, gpointer userdata); gboolean avahi_interface_relevant(AvahiInterface *i); gboolean avahi_interface_address_relevant(AvahiInterfaceAddress *a); diff --git a/avahi-core/probe-sched.c b/avahi-core/probe-sched.c index 0e36bb4..d9c6599 100644 --- a/avahi-core/probe-sched.c +++ b/avahi-core/probe-sched.c @@ -352,7 +352,7 @@ gboolean avahi_probe_scheduler_post(AvahiProbeScheduler *s, AvahiRecord *record, if ((pj = find_history_job(s, record))) return FALSE; - + avahi_elapse_time(&tv, immediately ? 0 : AVAHI_PROBE_DEFER_MSEC, 0); if ((pj = find_scheduled_job(s, record))) { diff --git a/avahi-core/response-sched.c b/avahi-core/response-sched.c index 1e763e6..6d1269e 100644 --- a/avahi-core/response-sched.c +++ b/avahi-core/response-sched.c @@ -27,7 +27,7 @@ #include "util.h" #include "log.h" -#define AVAHI_RESPONSE_HISTORY_MSEC 700 +#define AVAHI_RESPONSE_HISTORY_MSEC 500 #define AVAHI_RESPONSE_DEFER_MSEC 20 #define AVAHI_RESPONSE_JITTER_MSEC 100 #define AVAHI_RESPONSE_SUPPRESS_MSEC 700 @@ -284,7 +284,9 @@ static AvahiResponseJob* find_history_job(AvahiResponseScheduler *s, AvahiRecord if (avahi_record_equal_no_ttl(rj->record, record)) { /* Check whether this entry is outdated */ - if (avahi_age(&rj->delivery) > AVAHI_RESPONSE_HISTORY_MSEC*1000) { +/* avahi_log_debug("history age: %u", (unsigned) (avahi_age(&rj->delivery)/1000)); */ + + if (avahi_age(&rj->delivery)/1000 > AVAHI_RESPONSE_HISTORY_MSEC) { /* it is outdated, so let's remove it */ job_free(s, rj); return NULL; @@ -328,19 +330,24 @@ static AvahiResponseJob* find_suppressed_job(AvahiResponseScheduler *s, AvahiRec gboolean avahi_response_scheduler_post(AvahiResponseScheduler *s, AvahiRecord *record, gboolean flush_cache, const AvahiAddress *querier, gboolean immediately) { AvahiResponseJob *rj; GTimeVal tv; +/* gchar *t; */ g_assert(s); g_assert(record); g_assert(!avahi_key_is_pattern(record->key)); +/* t = avahi_record_to_string(record); */ +/* avahi_log_debug("post %i %s", immediately, t); */ +/* g_free(t); */ + /* Check whether this response is suppressed */ if (querier && (rj = find_suppressed_job(s, record, querier)) && avahi_record_is_goodbye(record) == avahi_record_is_goodbye(rj->record) && rj->record->ttl >= record->ttl/2) { -/* avahi_log_debug("Response suppressed by known answer suppression."); */ +/* avahi_log_debug("Response suppressed by known answer suppression."); */ return FALSE; } @@ -350,7 +357,7 @@ gboolean avahi_response_scheduler_post(AvahiResponseScheduler *s, AvahiRecord *r if (avahi_record_is_goodbye(record) == avahi_record_is_goodbye(rj->record) && rj->record->ttl >= record->ttl/2 && (rj->flush_cache || !flush_cache)) { -/* avahi_log_debug("Response suppressed by local duplicate suppression (history)"); */ +/* avahi_log_debug("Response suppressed by local duplicate suppression (history)"); */ return FALSE; } @@ -361,7 +368,7 @@ gboolean avahi_response_scheduler_post(AvahiResponseScheduler *s, AvahiRecord *r avahi_elapse_time(&tv, immediately ? 0 : AVAHI_RESPONSE_DEFER_MSEC, immediately ? 0 : AVAHI_RESPONSE_JITTER_MSEC); if ((rj = find_scheduled_job(s, record))) { -/* avahi_log_debug("Response suppressed by local duplicate suppression (scheduled)"); */ +/* avahi_log_debug("Response suppressed by local duplicate suppression (scheduled)"); */ /* Update a little ... */ @@ -385,7 +392,7 @@ gboolean avahi_response_scheduler_post(AvahiResponseScheduler *s, AvahiRecord *r return TRUE; } else { -/* avahi_log_debug("Accepted new response job."); */ +/* avahi_log_debug("Accepted new response job."); */ /* Create a new job and schedule it */ rj = job_new(s, record, AVAHI_SCHEDULED); diff --git a/avahi-core/server.c b/avahi-core/server.c index b3ab009..d63f5ec 100644 --- a/avahi-core/server.c +++ b/avahi-core/server.c @@ -223,6 +223,10 @@ static void incoming_probe(AvahiServer *s, AvahiRecord *record, AvahiInterface * g_assert(record); g_assert(i); + t = avahi_record_to_string(record); + +/* avahi_log_debug("incoming_probe()"); */ + for (e = g_hash_table_lookup(s->entries_by_key, record->key); e; e = n) { gint cmp; n = e->by_key_next; @@ -244,8 +248,6 @@ static void incoming_probe(AvahiServer *s, AvahiRecord *record, AvahiInterface * } } - t = avahi_record_to_string(record); - if (!ours) { if (won) @@ -253,7 +255,8 @@ static void incoming_probe(AvahiServer *s, AvahiRecord *record, AvahiInterface * else if (lost) { avahi_log_debug("Recieved conflicting probe [%s]. Local host lost. Withdrawing.", t); withdraw_rrset(s, record->key); - } + }/* else */ +/* avahi_log_debug("Not conflicting probe"); */ } g_free(t); @@ -334,7 +337,7 @@ static gboolean handle_conflict(AvahiServer *s, AvahiInterface *i, AvahiRecord * avahi_log_debug("Recieved conflicting record [%s]. Resetting our record.", t); avahi_entry_return_to_initial_state(s, conflicting_entry, i); - /* Local unique records are returned to probin + /* Local unique records are returned to probing * state. Local shared records are reannounced. */ } @@ -1527,25 +1530,29 @@ const AvahiRecord *avahi_server_iterate(AvahiServer *s, AvahiEntryGroup *g, void return avahi_record_ref((*e)->record); } -void avahi_server_dump(AvahiServer *s, FILE *f) { +void avahi_server_dump(AvahiServer *s, AvahiDumpCallback callback, gpointer userdata) { AvahiEntry *e; + g_assert(s); - g_assert(f); + g_assert(callback); - fprintf(f, "\n;;; ZONE DUMP FOLLOWS ;;;\n"); + callback(";;; ZONE DUMP FOLLOWS ;;;", userdata); for (e = s->entries; e; e = e->entries_next) { gchar *t; + gchar ln[256]; if (e->dead) continue; t = avahi_record_to_string(e->record); - fprintf(f, "%s ; iface=%i proto=%i\n", t, e->interface, e->protocol); + snprintf(ln, sizeof(ln), "%s ; iface=%i proto=%i", t, e->interface, e->protocol); g_free(t); + + callback(ln, userdata); } - avahi_dump_caches(s->monitor, f); + avahi_dump_caches(s->monitor, callback, userdata); } gint avahi_server_add_ptr( diff --git a/avahi-daemon/main.c b/avahi-daemon/main.c index bc99926..059ebe5 100644 --- a/avahi-daemon/main.c +++ b/avahi-daemon/main.c @@ -443,6 +443,10 @@ static void log_function(AvahiLogLevel level, const gchar *txt) { daemon_log(log_level_map[level], "%s", txt); } +static void dump(const gchar *text, gpointer userdata) { + avahi_log_info("%s", text); +} + static gboolean signal_callback(GIOChannel *source, GIOCondition condition, gpointer data) { gint sig; GMainLoop *loop = data; @@ -483,6 +487,11 @@ static gboolean signal_callback(GIOChannel *source, GIOCondition condition, gpoi break; + case SIGUSR1: + avahi_log_info("Got SIGUSR1, dumping record data."); + avahi_server_dump(avahi_server, dump, NULL); + break; + default: avahi_log_warn("Got spurious signal, ignoring."); break; @@ -501,7 +510,7 @@ static gint run_server(DaemonConfig *config) { loop = g_main_loop_new(NULL, FALSE); - if (daemon_signal_init(SIGINT, SIGQUIT, SIGHUP, SIGTERM, 0) < 0) { + if (daemon_signal_init(SIGINT, SIGQUIT, SIGHUP, SIGTERM, SIGUSR1, 0) < 0) { avahi_log_error("Could not register signal handlers (%s).", strerror(errno)); goto finish; } diff --git a/avahi-utils/avahi-publish-address b/avahi-utils/avahi-publish-address new file mode 100755 index 0000000..dce00bd --- /dev/null +++ b/avahi-utils/avahi-publish-address @@ -0,0 +1,73 @@ +#!/usr/bin/python2.4 +# -*-python-*- +# $Id$ + +import avahi, dbus, gobject, sys, getopt, string + +try: + import dbus.glib +except ImportError, e: + pass + +def usage(retval = 0): + print "%s
" % sys.argv[0] + sys.exit(retval) + +if len(sys.argv) != 3: + usage(2) + +name = sys.argv[1] +address = sys.argv[2] + +group = None +n_rename = 0 + +def remove_address(): + global group + + if not (group is None): + group.Free() + group = None + +def add_address(): + global server, group, name, address + assert group is None + + print "Adding address '%s' for '%s' ..." % (name, address) + group = dbus.Interface(bus.get_object("org.freedesktop.Avahi", server.EntryGroupNew()), 'org.freedesktop.Avahi.EntryGroup') + group.connect_to_signal('StateChanged', entry_group_state_changed) + group.AddAddress(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, name, address) + group.Commit() + +def entry_group_state_changed(state): + global name, server, n_rename, main_loop + + if state == avahi.ENTRY_GROUP_ESTABLISHED: + print "Address established." + elif state == avahi.ENTRY_GROUP_COLLISION: + + n_rename = n_rename + 1 + if n_rename >= 12: + print "ERROR: No suitable name found after %i retries, exiting." % n_rename + main_loop.quit() + else: + hn = name.split('.') + hn[0] = server.GetAlternativeHostName(hn[0]) + name = string.join(hn, '.') + print "WARNING: Address/host name collision, changing name to '%s' ..." % name + remove_address() + add_address() + +main_loop = gobject.MainLoop() + +bus = dbus.SystemBus() +server = dbus.Interface(bus.get_object("org.freedesktop.Avahi", '/org/freedesktop/Avahi/Server'), 'org.freedesktop.Avahi.Server') + +add_address() + +try: + main_loop.run() +except KeyboardInterrupt, k: + pass + +remove_address() diff --git a/avahi-utils/avahi-publish-service b/avahi-utils/avahi-publish-service index 4375d1a..376df34 100755 --- a/avahi-utils/avahi-publish-service +++ b/avahi-utils/avahi-publish-service @@ -48,6 +48,7 @@ if len(txt) == 0: txt.append("python-dbus=brain-damage") group = None +n_rename = 0 def remove_service(): global group @@ -57,27 +58,31 @@ def remove_service(): group = None def add_service(): - global group, name, stype, domain, host, port, txt - + global server, group, name, stype, domain, host, port, txt assert group is None - print "Adding service '%s' of type '%s' ..." % (name, args[1]) - + print "Adding service '%s' of type '%s' ..." % (name, stype) group = dbus.Interface(bus.get_object("org.freedesktop.Avahi", server.EntryGroupNew()), 'org.freedesktop.Avahi.EntryGroup') group.connect_to_signal('StateChanged', entry_group_state_changed) group.AddService(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, name, stype, domain, host, dbus.UInt16(port), txt) group.Commit() def entry_group_state_changed(state): - global name, server + global name, server, n_rename if state == avahi.ENTRY_GROUP_ESTABLISHED: print "Service established." elif state == avahi.ENTRY_GROUP_COLLISION: - name = server.GetAlternativeServiceName(name) - print "WARNING: Service name collision, changing name to '%s' ..." % name - remove_service() - add_service() + + n_rename = n_rename + 1 + if n_rename >= 12: + print "ERROR: No suitable service name found after %i retries, exiting." % n_rename + main_loop.quit() + else: + name = server.GetAlternativeServiceName(name) + print "WARNING: Service name collision, changing name to '%s' ..." % name + remove_service() + add_service() def server_state_changed(state): if state == avahi.SERVER_COLLISION: @@ -86,13 +91,15 @@ def server_state_changed(state): elif state == avahi.SERVER_RUNNING: add_service() +main_loop = gobject.MainLoop() + bus = dbus.SystemBus() server = dbus.Interface(bus.get_object("org.freedesktop.Avahi", '/org/freedesktop/Avahi/Server'), 'org.freedesktop.Avahi.Server') server.connect_to_signal("StateChanged", server_state_changed) server_state_changed(server.GetState()) try: - gobject.MainLoop().run() + main_loop.run() except KeyboardInterrupt, k: pass