summaryrefslogtreecommitdiffstats
path: root/avahi-core
diff options
context:
space:
mode:
Diffstat (limited to 'avahi-core')
-rw-r--r--avahi-core/Makefile.am9
-rw-r--r--avahi-core/announce.c134
-rw-r--r--avahi-core/announce.h9
-rw-r--r--avahi-core/avahi-test.c4
-rw-r--r--avahi-core/iface.c4
-rw-r--r--avahi-core/publish.h37
-rw-r--r--avahi-core/server.c216
-rw-r--r--avahi-core/update-test.c88
8 files changed, 421 insertions, 80 deletions
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 <config.h>
+#endif
+
+#include <assert.h>
+
+#include <avahi-common/error.h>
+#include <avahi-common/watch.h>
+#include <avahi-common/simple-watch.h>
+#include <avahi-common/malloc.h>
+#include <avahi-common/alternative.h>
+
+#include <avahi-core/core.h>
+#include <avahi-core/log.h>
+#include <avahi-core/publish.h>
+#include <avahi-core/lookup.h>
+
+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);
+}