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)) {
if (!(a = avahi_get_announcement(s, e, i)))
return FALSE;
+
+/* avahi_log_debug("state: %i", a->state); */
return
a->state == AVAHI_PROBING ||
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;
}
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);
/* 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) {
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);
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;
}
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);
* 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
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) {
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);
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))) {
#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
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;
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;
}
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;
}
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 ... */
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);
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;
}
}
- t = avahi_record_to_string(record);
-
if (!ours) {
if (won)
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);
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. */
}
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(
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;
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;
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;
}
--- /dev/null
+#!/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 <name> <address>" % 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()
txt.append("python-dbus=brain-damage")
group = None
+n_rename = 0
def remove_service():
global group
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:
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