From 41f2725b37437a585ce285051bdae06f4919dc3b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 17 Oct 2005 00:20:33 +0000 Subject: [PATCH] * implement record updating through the new flags AVAHI_PUBLISH_UPDATE * add new helper function avahi_server_update_service_txt() to ease TXT record updating for services * other minor cleanups git-svn-id: file:///home/lennart/svn/public/avahi/trunk@790 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe --- avahi-common/defs.h | 3 +- avahi-core/Makefile.am | 9 +- avahi-core/announce.c | 134 ++++++++++++++++++------ avahi-core/announce.h | 9 +- avahi-core/avahi-test.c | 4 +- avahi-core/iface.c | 4 +- avahi-core/publish.h | 37 +++++++ avahi-core/server.c | 216 ++++++++++++++++++++++++++++++++------- avahi-core/update-test.c | 88 ++++++++++++++++ 9 files changed, 423 insertions(+), 81 deletions(-) create mode 100644 avahi-core/update-test.c diff --git a/avahi-common/defs.h b/avahi-common/defs.h index d12ed64..41e4daa 100644 --- a/avahi-common/defs.h +++ b/avahi-common/defs.h @@ -161,7 +161,8 @@ typedef enum { AVAHI_PUBLISH_ALLOW_MULTIPLE = 8, /**< For raw records: Allow multiple local records of this type, even if they are intended to be unique */ AVAHI_PUBLISH_NO_REVERSE = 16, /**< For address records: don't create a reverse (PTR) entry */ AVAHI_PUBLISH_NO_COOKIE = 32, /**< For service records: do not implicitly add the local service cookie to TXT data */ - AVAHI_PUBLISH_IS_PROXY = 64 /**< For service records: this is a proxy for another host. This modifies behaviour of avahi_server_is_service_local() */ + AVAHI_PUBLISH_IS_PROXY = 64, /**< For service records: this is a proxy for another host. This modifies behaviour of avahi_server_is_service_local() */ + AVAHI_PUBLISH_UPDATE = 128 /**< Update existing records instead of adding new ones */ } AvahiPublishFlags; /** Some flags for lookup functions */ diff --git a/avahi-core/Makefile.am b/avahi-core/Makefile.am index 14b161a..b62a4d5 100644 --- a/avahi-core/Makefile.am +++ b/avahi-core/Makefile.am @@ -42,7 +42,8 @@ noinst_PROGRAMS = \ dns-test \ timeeventq-test \ hashmap-test \ - querier-test + querier-test \ + update-test libavahi_core_la_SOURCES = \ timeeventq.c timeeventq.h\ @@ -74,7 +75,7 @@ libavahi_core_la_SOURCES = \ wide-area.c wide-area.h \ multicast-lookup.c multicast-lookup.h \ querier.c querier.h - + if HAVE_NETLINK libavahi_core_la_SOURCES += \ iface-linux.c iface-linux.h \ @@ -96,6 +97,10 @@ avahi_test_SOURCES = \ avahi_test_CFLAGS = $(AM_CFLAGS) avahi_test_LDADD = $(AM_LDADD) ../avahi-common/libavahi-common.la libavahi-core.la +update_test_SOURCES = \ + update-test.c +update_test_CFLAGS = $(AM_CFLAGS) +update_test_LDADD = $(AM_LDADD) ../avahi-common/libavahi-common.la libavahi-core.la querier_test_SOURCES = \ querier-test.c diff --git a/avahi-core/announce.c b/avahi-core/announce.c index 8796621..d1e5995 100644 --- a/avahi-core/announce.c +++ b/avahi-core/announce.c @@ -230,13 +230,11 @@ static void go_to_initial_state(AvahiAnnouncement *a, int immediately) { if (a->state == AVAHI_PROBING && e->group) e->group->n_probing++; - if (a->state == AVAHI_PROBING) { - avahi_elapse_time(&tv, 0, immediately ? 0 : AVAHI_PROBE_JITTER_MSEC); - set_timeout(a, &tv); - } else if (a->state == AVAHI_ANNOUNCING) { - avahi_elapse_time(&tv, 0, immediately ? 0 : AVAHI_ANNOUNCEMENT_JITTER_MSEC); - set_timeout(a, &tv); - } else + if (a->state == AVAHI_PROBING) + set_timeout(a, avahi_elapse_time(&tv, 0, AVAHI_PROBE_JITTER_MSEC)); + else if (a->state == AVAHI_ANNOUNCING) + set_timeout(a, avahi_elapse_time(&tv, 0, AVAHI_ANNOUNCEMENT_JITTER_MSEC)); + else set_timeout(a, NULL); } @@ -438,55 +436,123 @@ static void send_goodbye_callback(AvahiInterfaceMonitor *m, AvahiInterface *i, v avahi_interface_post_response(i, g, e->flags & AVAHI_PUBLISH_UNIQUE, NULL, 1); avahi_record_unref(g); } + +static void reannounce(AvahiAnnouncement *a) { + AvahiEntry *e; + struct timeval tv; + + assert(a); + e = a->entry; + + /* If the group this entry belongs to is not even commited, there's nothing to reannounce */ + if (e->group && (e->group->state == AVAHI_ENTRY_GROUP_UNCOMMITED || e->group->state == AVAHI_ENTRY_GROUP_COLLISION)) + return; + + /* Because we might change state we decrease the probing counter first */ + if (a->state == AVAHI_PROBING && a->entry->group) + a->entry->group->n_probing--; -void avahi_goodbye_interface(AvahiServer *s, AvahiInterface *i, int goodbye) { - assert(s); - assert(i); + if (a->state == AVAHI_PROBING || + (a->state == AVAHI_WAITING && (e->flags & AVAHI_PUBLISH_UNIQUE) && !(e->flags & AVAHI_PUBLISH_NO_PROBE))) -/* avahi_log_debug("goodbye interface: %s.%u", i->hardware->name, i->protocol); */ + /* We were probing or waiting after probe, so we restart probing from the beginning here */ + + a->state = AVAHI_PROBING; + else if (a->state == AVAHI_WAITING) - if (goodbye && avahi_interface_is_relevant(i)) { - AvahiEntry *e; + /* We were waiting, but were not probing before, so we continue waiting */ + a->state = AVAHI_WAITING; + + else if (e->flags & AVAHI_PUBLISH_NO_ANNOUNCE) - for (e = s->entries; e; e = e->entries_next) - if (!e->dead) - send_goodbye_callback(s->monitor, i, e); - } + /* No announcement needed */ + a->state = AVAHI_ESTABLISHED; + + else { + + /* Ok, let's restart announcing */ + a->state = AVAHI_ANNOUNCING; + } + + /* Now let's increase the probing counter again */ + if (a->state == AVAHI_PROBING && e->group) + e->group->n_probing++; + + a->n_iteration = 1; + a->sec_delay = 1; + + if (a->state == AVAHI_PROBING) + set_timeout(a, avahi_elapse_time(&tv, 0, AVAHI_PROBE_JITTER_MSEC)); + else if (a->state == AVAHI_ANNOUNCING) + set_timeout(a, avahi_elapse_time(&tv, 0, AVAHI_ANNOUNCEMENT_JITTER_MSEC)); + else + set_timeout(a, NULL); +} - while (i->announcements) - remove_announcement(s, i->announcements); -/* avahi_log_debug("goodbye interface done: %s.%u", i->hardware->name, i->protocol); */ +static void reannounce_walk_callback(AvahiInterfaceMonitor *m, AvahiInterface *i, void* userdata) { + AvahiEntry *e = userdata; + AvahiAnnouncement *a; + + assert(m); + assert(i); + assert(e); + assert(!e->dead); + + if (!(a = avahi_get_announcement(m->server, e, i))) + return; + + reannounce(a); } -void avahi_goodbye_entry(AvahiServer *s, AvahiEntry *e, int goodbye) { +void avahi_reannounce_entry(AvahiServer *s, AvahiEntry *e) { + assert(s); assert(e); + assert(!e->dead); + + avahi_interface_monitor_walk(s->monitor, e->interface, e->protocol, reannounce_walk_callback, e); +} -/* avahi_log_debug("goodbye entry: %p", e); */ - - if (goodbye && !e->dead) - avahi_interface_monitor_walk(s->monitor, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, send_goodbye_callback, e); +void avahi_goodbye_interface(AvahiServer *s, AvahiInterface *i, int send_goodbye, int remove) { + assert(s); + assert(i); + + if (send_goodbye) + if (avahi_interface_is_relevant(i)) { + AvahiEntry *e; + + for (e = s->entries; e; e = e->entries_next) + if (!e->dead) + send_goodbye_callback(s->monitor, i, e); + } - while (e->announcements) - remove_announcement(s, e->announcements); + if (remove) + while (i->announcements) + remove_announcement(s, i->announcements); +} -/* avahi_log_debug("goodbye entry done: %p", e); */ +void avahi_goodbye_entry(AvahiServer *s, AvahiEntry *e, int send_goodbye, int remove) { + assert(s); + assert(e); + + if (send_goodbye) + if (!e->dead) + avahi_interface_monitor_walk(s->monitor, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, send_goodbye_callback, e); + if (remove) + while (e->announcements) + remove_announcement(s, e->announcements); } -void avahi_goodbye_all(AvahiServer *s, int goodbye) { +void avahi_goodbye_all(AvahiServer *s, int send_goodbye, int remove) { AvahiEntry *e; assert(s); -/* avahi_log_debug("goodbye all"); */ - for (e = s->entries; e; e = e->entries_next) if (!e->dead) - avahi_goodbye_entry(s, e, goodbye); - -/* avahi_log_debug("goodbye all done"); */ + avahi_goodbye_entry(s, e, send_goodbye, remove); } diff --git a/avahi-core/announce.h b/avahi-core/announce.h index 9183258..21dd148 100644 --- a/avahi-core/announce.h +++ b/avahi-core/announce.h @@ -63,11 +63,12 @@ void avahi_s_entry_group_check_probed(AvahiSEntryGroup *g, int immediately); int avahi_entry_is_registered(AvahiServer *s, AvahiEntry *e, AvahiInterface *i); int avahi_entry_is_probing(AvahiServer *s, AvahiEntry *e, AvahiInterface *i); -void avahi_goodbye_interface(AvahiServer *s, AvahiInterface *i, int send_goodbye); -void avahi_goodbye_entry(AvahiServer *s, AvahiEntry *e, int send_goodbye); - -void avahi_goodbye_all(AvahiServer *s, int send_goodbye); +void avahi_goodbye_interface(AvahiServer *s, AvahiInterface *i, int send_goodbye, int rem); +void avahi_goodbye_entry(AvahiServer *s, AvahiEntry *e, int send_goodbye, int rem); +void avahi_goodbye_all(AvahiServer *s, int send_goodbye, int rem); AvahiAnnouncement *avahi_get_announcement(AvahiServer *s, AvahiEntry *e, AvahiInterface *i); +void avahi_reannounce_entry(AvahiServer *s, AvahiEntry *e); + #endif diff --git a/avahi-core/avahi-test.c b/avahi-core/avahi-test.c index 46e68d5..cf8bd3b 100644 --- a/avahi-core/avahi-test.c +++ b/avahi-core/avahi-test.c @@ -361,9 +361,7 @@ int main(int argc, char *argv[]) { avahi_elapse_time(&tv, 1000*60, 0); poll_api->timeout_new(poll_api, &tv, quit_timeout_callback, simple_poll); - for (;;) - if (avahi_simple_poll_iterate(simple_poll, -1) != 0) - break; + avahi_simple_poll_loop(simple_poll); avahi_s_record_browser_free(r); avahi_s_host_name_resolver_free(hnr); diff --git a/avahi-core/iface.c b/avahi-core/iface.c index e27f489..b2e8161 100644 --- a/avahi-core/iface.c +++ b/avahi-core/iface.c @@ -186,7 +186,7 @@ void avahi_interface_free(AvahiInterface *i, int send_goodbye) { assert(i); /* Handle goodbyes and remove announcers */ - avahi_goodbye_interface(i->monitor->server, i, send_goodbye); + avahi_goodbye_interface(i->monitor->server, i, send_goodbye, 1); avahi_response_scheduler_force(i->response_scheduler); assert(!i->announcements); @@ -358,7 +358,7 @@ void avahi_interface_check_relevant(AvahiInterface *i) { if (i->protocol == AVAHI_PROTO_INET6) avahi_mdns_mcast_leave_ipv6(m->server->fd_ipv6, i->hardware->index); - avahi_goodbye_interface(m->server, i, 0); + avahi_goodbye_interface(m->server, i, 0, 1); avahi_querier_free_all(i); avahi_response_scheduler_clear(i->response_scheduler); diff --git a/avahi-core/publish.h b/avahi-core/publish.h index aa9eae0..36c29cf 100644 --- a/avahi-core/publish.h +++ b/avahi-core/publish.h @@ -220,6 +220,43 @@ int avahi_server_add_service_subtype( const char *domain, /**< Specify the main type of the service you already added here */ const char *subtype /**< The new subtype for the specified service */ ); + +/** Update the TXT record for a service with the data from the specified string list */ +int avahi_server_update_service_txt_strlst( + AvahiServer *s, + AvahiSEntryGroup *g, + AvahiIfIndex interface, + AvahiProtocol protocol, + AvahiPublishFlags flags, + const char *name, + const char *type, + const char *domain, + AvahiStringList *strlst); + +/** Update the TXT record for a service with the NULL terminated list of strings of the va_list. */ +int avahi_server_update_service_txt_va( + AvahiServer *s, + AvahiSEntryGroup *g, + AvahiIfIndex interface, + AvahiProtocol protocol, + AvahiPublishFlags flags, + const char *name, + const char *type, + const char *domain, + va_list va); + +/** Update the TXT record for a service with the NULL termonate list of strings */ +int avahi_server_update_service_txt( + AvahiServer *s, + AvahiSEntryGroup *g, + AvahiIfIndex interface, + AvahiProtocol protocol, + AvahiPublishFlags flags, + const char *name, + const char *type, + const char *domain, + ...) AVAHI_GCC_SENTINEL; + /** The type of DNS server */ typedef enum { AVAHI_DNS_SERVER_RESOLVE, /**< Unicast DNS servers for normal resolves (_domain._udp)*/ diff --git a/avahi-core/server.c b/avahi-core/server.c index f23ef39..dd3adcd 100644 --- a/avahi-core/server.c +++ b/avahi-core/server.c @@ -55,7 +55,7 @@ static void free_entry(AvahiServer*s, AvahiEntry *e) { assert(s); assert(e); - avahi_goodbye_entry(s, e, 1); + avahi_goodbye_entry(s, e, 1, 1); /* Remove from linked list */ AVAHI_LLIST_REMOVE(AvahiEntry, entries, s->entries, e); @@ -207,7 +207,7 @@ static void withdraw_entry(AvahiServer *s, AvahiEntry *e) { for (k = e->group->entries; k; k = k->by_group_next) { if (!k->dead) { - avahi_goodbye_entry(s, k, 0); + avahi_goodbye_entry(s, k, 0, 1); k->dead = 1; } } @@ -216,7 +216,7 @@ static void withdraw_entry(AvahiServer *s, AvahiEntry *e) { avahi_s_entry_group_change_state(e->group, AVAHI_ENTRY_GROUP_COLLISION); } else { - avahi_goodbye_entry(s, e, 0); + avahi_goodbye_entry(s, e, 0, 1); e->dead = 1; } @@ -1571,8 +1571,6 @@ int avahi_server_add( AvahiPublishFlags flags, AvahiRecord *r) { - AvahiEntry *e, *t; - assert(s); assert(r); @@ -1582,7 +1580,14 @@ int avahi_server_add( if (!AVAHI_PROTO_VALID(protocol)) return avahi_server_set_errno(s, AVAHI_ERR_INVALID_PROTOCOL); - if (!AVAHI_FLAGS_VALID(flags, AVAHI_PUBLISH_NO_ANNOUNCE|AVAHI_PUBLISH_NO_PROBE|AVAHI_PUBLISH_UNIQUE|AVAHI_PUBLISH_ALLOW_MULTIPLE|AVAHI_PUBLISH_IS_PROXY)) + if (!AVAHI_FLAGS_VALID( + flags, + AVAHI_PUBLISH_NO_ANNOUNCE| + AVAHI_PUBLISH_NO_PROBE| + AVAHI_PUBLISH_UNIQUE| + AVAHI_PUBLISH_ALLOW_MULTIPLE| + AVAHI_PUBLISH_IS_PROXY| + AVAHI_PUBLISH_UPDATE)) return avahi_server_set_errno(s, AVAHI_ERR_INVALID_FLAGS); if (!avahi_is_valid_domain_name(r->key->name)) @@ -1597,36 +1602,83 @@ int avahi_server_add( if (!avahi_record_is_valid(r)) return avahi_server_set_errno(s, AVAHI_ERR_INVALID_RECORD); - if (check_record_conflict(s, interface, protocol, r, flags) < 0) - return avahi_server_set_errno(s, AVAHI_ERR_LOCAL_COLLISION); - - if (!(e = avahi_new(AvahiEntry, 1))) - return avahi_server_set_errno(s, AVAHI_ERR_NO_MEMORY); + if (flags & AVAHI_PUBLISH_UPDATE) { + AvahiEntry *e; + AvahiRecord *old_record; + int is_first = 1; - e->server = s; - e->record = avahi_record_ref(r); - e->group = g; - e->interface = interface; - e->protocol = protocol; - e->flags = flags; - e->dead = 0; + /* Update and existing record */ - AVAHI_LLIST_HEAD_INIT(AvahiAnnouncement, e->announcements); + /* Find the first matching entry */ + for (e = avahi_hashmap_lookup(s->entries_by_key, r->key); e; e = e->by_key_next) { + if (!e->dead && e->group == g && e->interface == interface && e->protocol == protocol) + break; - AVAHI_LLIST_PREPEND(AvahiEntry, entries, s->entries, e); + is_first = 0; + } - /* Insert into hash table indexed by name */ - t = avahi_hashmap_lookup(s->entries_by_key, e->record->key); - AVAHI_LLIST_PREPEND(AvahiEntry, by_key, t, e); - avahi_hashmap_replace(s->entries_by_key, e->record->key, t); + /* Hmm, nothing found? */ + if (!e) + return avahi_server_set_errno(s, AVAHI_ERR_NOT_FOUND); - /* Insert into group list */ - if (g) - AVAHI_LLIST_PREPEND(AvahiEntry, by_group, g->entries, e); + /* Update the entry */ + old_record = e->record; + e->record = avahi_record_ref(r); + e->flags = flags; - avahi_announce_entry(s, e); + /* Announce our changes when needed */ + if (!avahi_record_equal_no_ttl(old_record, r) && (!g || g->state != AVAHI_ENTRY_GROUP_UNCOMMITED)) { - return 0; + /* Remove the old entry from all caches, if needed */ + if (!(e->flags & AVAHI_PUBLISH_UNIQUE)) + avahi_goodbye_entry(s, e, 1, 0); + + /* Reannounce our updated entry */ + avahi_reannounce_entry(s, e); + } + + /* If we were the first entry in the list, we need to update the key */ + if (is_first) + avahi_hashmap_replace(s->entries_by_key, e->record->key, e); + + avahi_record_unref(old_record); + + } else { + AvahiEntry *e, *t; + + /* Add a new record */ + + if (check_record_conflict(s, interface, protocol, r, flags) < 0) + return avahi_server_set_errno(s, AVAHI_ERR_LOCAL_COLLISION); + + if (!(e = avahi_new(AvahiEntry, 1))) + return avahi_server_set_errno(s, AVAHI_ERR_NO_MEMORY); + + e->server = s; + e->record = avahi_record_ref(r); + e->group = g; + e->interface = interface; + e->protocol = protocol; + e->flags = flags; + e->dead = 0; + + AVAHI_LLIST_HEAD_INIT(AvahiAnnouncement, e->announcements); + + AVAHI_LLIST_PREPEND(AvahiEntry, entries, s->entries, e); + + /* Insert into hash table indexed by name */ + t = avahi_hashmap_lookup(s->entries_by_key, e->record->key); + AVAHI_LLIST_PREPEND(AvahiEntry, by_key, t, e); + avahi_hashmap_replace(s->entries_by_key, e->record->key, t); + + /* Insert into group list */ + if (g) + AVAHI_LLIST_PREPEND(AvahiEntry, by_group, g->entries, e); + + avahi_announce_entry(s, e); + } + + return AVAHI_OK; } const AvahiRecord *avahi_server_iterate(AvahiServer *s, AvahiSEntryGroup *g, void **state) { @@ -1729,7 +1781,7 @@ int avahi_server_add_address( if (!AVAHI_PROTO_VALID(protocol) || !AVAHI_PROTO_VALID(a->proto)) return avahi_server_set_errno(s, AVAHI_ERR_INVALID_PROTOCOL); - if (!AVAHI_FLAGS_VALID(flags, AVAHI_PUBLISH_NO_REVERSE|AVAHI_PUBLISH_NO_ANNOUNCE|AVAHI_PUBLISH_NO_PROBE)) + if (!AVAHI_FLAGS_VALID(flags, AVAHI_PUBLISH_NO_REVERSE|AVAHI_PUBLISH_NO_ANNOUNCE|AVAHI_PUBLISH_NO_PROBE|AVAHI_PUBLISH_UPDATE)) return avahi_server_set_errno(s, AVAHI_ERR_INVALID_FLAGS); if (name && !avahi_is_valid_domain_name(name)) @@ -1937,7 +1989,7 @@ static int server_add_service_strlst_nocopy( AVAHI_CHECK_VALIDITY_SET_RET_GOTO_FAIL(s, AVAHI_IF_VALID(interface), AVAHI_ERR_INVALID_INTERFACE); AVAHI_CHECK_VALIDITY_SET_RET_GOTO_FAIL(s, AVAHI_PROTO_VALID(protocol), AVAHI_ERR_INVALID_PROTOCOL); - AVAHI_CHECK_VALIDITY_SET_RET_GOTO_FAIL(s, AVAHI_FLAGS_VALID(flags, AVAHI_PUBLISH_NO_COOKIE|AVAHI_PUBLISH_IS_PROXY), AVAHI_ERR_INVALID_FLAGS); + AVAHI_CHECK_VALIDITY_SET_RET_GOTO_FAIL(s, AVAHI_FLAGS_VALID(flags, AVAHI_PUBLISH_NO_COOKIE|AVAHI_PUBLISH_IS_PROXY|AVAHI_PUBLISH_UPDATE), AVAHI_ERR_INVALID_FLAGS); AVAHI_CHECK_VALIDITY_SET_RET_GOTO_FAIL(s, avahi_is_valid_service_name(name), AVAHI_ERR_INVALID_SERVICE_NAME); AVAHI_CHECK_VALIDITY_SET_RET_GOTO_FAIL(s, avahi_is_valid_service_type_strict(type), AVAHI_ERR_INVALID_SERVICE_TYPE); AVAHI_CHECK_VALIDITY_SET_RET_GOTO_FAIL(s, !domain || avahi_is_valid_domain_name(domain), AVAHI_ERR_INVALID_DOMAIN_NAME); @@ -2063,12 +2115,106 @@ int avahi_server_add_service( va_list va; int ret; + va_start(va, port); + ret = avahi_server_add_service_va(s, g, interface, protocol, flags, name, type, domain, host, port, va); + va_end(va); + + return ret; +} + +static int server_update_service_txt_strlst_nocopy( + AvahiServer *s, + AvahiSEntryGroup *g, + AvahiIfIndex interface, + AvahiProtocol protocol, + AvahiPublishFlags flags, + const char *name, + const char *type, + const char *domain, + AvahiStringList *strlst) { + + char svc_name[AVAHI_DOMAIN_NAME_MAX]; + int ret = AVAHI_OK; + assert(s); assert(type); assert(name); - va_start(va, port); - ret = avahi_server_add_service_va(s, g, interface, protocol, flags, name, type, domain, host, port, va); + AVAHI_CHECK_VALIDITY_SET_RET_GOTO_FAIL(s, AVAHI_IF_VALID(interface), AVAHI_ERR_INVALID_INTERFACE); + AVAHI_CHECK_VALIDITY_SET_RET_GOTO_FAIL(s, AVAHI_PROTO_VALID(protocol), AVAHI_ERR_INVALID_PROTOCOL); + AVAHI_CHECK_VALIDITY_SET_RET_GOTO_FAIL(s, AVAHI_FLAGS_VALID(flags, AVAHI_PUBLISH_IS_PROXY|AVAHI_PUBLISH_NO_COOKIE), AVAHI_ERR_INVALID_FLAGS); + AVAHI_CHECK_VALIDITY_SET_RET_GOTO_FAIL(s, avahi_is_valid_service_name(name), AVAHI_ERR_INVALID_SERVICE_NAME); + AVAHI_CHECK_VALIDITY_SET_RET_GOTO_FAIL(s, avahi_is_valid_service_type_strict(type), AVAHI_ERR_INVALID_SERVICE_TYPE); + AVAHI_CHECK_VALIDITY_SET_RET_GOTO_FAIL(s, !domain || avahi_is_valid_domain_name(domain), AVAHI_ERR_INVALID_DOMAIN_NAME); + + if (!domain) + domain = s->domain_name; + + if ((ret = avahi_service_name_join(svc_name, sizeof(svc_name), name, type, domain)) < 0) { + avahi_server_set_errno(s, ret); + goto fail; + } + + /* Add TXT record */ + if (!(flags & AVAHI_PUBLISH_NO_COOKIE)) + strlst = add_magic_cookie(s, strlst); + + ret = server_add_txt_strlst_nocopy(s, g, interface, protocol, (flags & AVAHI_PUBLISH_IS_PROXY) | AVAHI_PUBLISH_UNIQUE | AVAHI_PUBLISH_UPDATE, AVAHI_DEFAULT_TTL, svc_name, strlst); + strlst = NULL; + +fail: + + avahi_string_list_free(strlst); + + return ret; +} + +int avahi_server_update_service_txt_strlst( + AvahiServer *s, + AvahiSEntryGroup *g, + AvahiIfIndex interface, + AvahiProtocol protocol, + AvahiPublishFlags flags, + const char *name, + const char *type, + const char *domain, + AvahiStringList *strlst) { + + return server_update_service_txt_strlst_nocopy(s, g, interface, protocol, flags, name, type, domain, avahi_string_list_copy(strlst)); +} + +/** Update the TXT record for a service with the NULL terminated list of strings of the va_list. */ +int avahi_server_update_service_txt_va( + AvahiServer *s, + AvahiSEntryGroup *g, + AvahiIfIndex interface, + AvahiProtocol protocol, + AvahiPublishFlags flags, + const char *name, + const char *type, + const char *domain, + va_list va) { + + return server_update_service_txt_strlst_nocopy(s, g, interface, protocol, flags, name, type, domain, avahi_string_list_new_va(va)); +} + +/** Update the TXT record for a service with the NULL termonate list of strings */ +int avahi_server_update_service_txt( + AvahiServer *s, + AvahiSEntryGroup *g, + AvahiIfIndex interface, + AvahiProtocol protocol, + AvahiPublishFlags flags, + const char *name, + const char *type, + const char *domain, + ...) { + + va_list va; + int ret; + + va_start(va, domain); + ret = avahi_server_update_service_txt_va(s, g, interface, protocol, flags, name, type, domain, va); va_end(va); return ret; @@ -2344,7 +2490,7 @@ void avahi_s_entry_group_free(AvahiSEntryGroup *g) { for (e = g->entries; e; e = e->by_group_next) { if (!e->dead) { - avahi_goodbye_entry(g->server, e, 1); + avahi_goodbye_entry(g->server, e, 1, 1); e->dead = 1; } } @@ -2428,7 +2574,7 @@ void avahi_s_entry_group_reset(AvahiSEntryGroup *g) { for (e = g->entries; e; e = e->by_group_next) { if (!e->dead) { - avahi_goodbye_entry(g->server, e, 1); + avahi_goodbye_entry(g->server, e, 1, 1); e->dead = 1; } } diff --git a/avahi-core/update-test.c b/avahi-core/update-test.c new file mode 100644 index 0000000..8c5b5ed --- /dev/null +++ b/avahi-core/update-test.c @@ -0,0 +1,88 @@ +/* $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. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +static AvahiSEntryGroup *group = NULL; + +static void server_callback(AvahiServer *s, AvahiServerState state, void* userdata) { + + avahi_log_debug("server state: %i", state); + + if (state == AVAHI_SERVER_RUNNING) { + int ret; + + group = avahi_s_entry_group_new(s, NULL, NULL); + assert(group); + + ret = avahi_server_add_service(s, group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, "foo", "_http._tcp", NULL, NULL, 80, "test1", NULL); + assert(ret == AVAHI_OK); + + avahi_s_entry_group_commit(group); + } +} + +static void modify_txt_callback(AvahiTimeout *e, void *userdata) { + int ret; + AvahiServer *s = userdata; + + ret = avahi_server_update_service_txt(s, group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, "foo", "_http._tcp", NULL, "test2", NULL); + assert(ret == AVAHI_OK); +} + +int main(int argc, char *argv[]) { + AvahiSimplePoll *simple_poll; + const AvahiPoll *poll_api; + AvahiServer *server; + struct timeval tv; + AvahiServerConfig config; + + simple_poll = avahi_simple_poll_new(); + assert(simple_poll); + + poll_api = avahi_simple_poll_get(simple_poll); + assert(poll_api); + + avahi_server_config_init(&config); + config.publish_domain = config.publish_workstation = config.use_ipv6 = config.publish_hinfo = 0; + server = avahi_server_new(poll_api, &config, server_callback, NULL, NULL); + assert(server); + avahi_server_config_free(&config); + + poll_api->timeout_new(poll_api, avahi_elapse_time(&tv, 1000*20, 0), modify_txt_callback, server); + + avahi_simple_poll_loop(simple_poll); +} -- 2.39.5