+ s = *((AvahiServer**) (((guint8*) source) + sizeof(GSource)));
+ g_assert(s);
+
+ work(s);
+ cleanup_dead(s);
+
+ return TRUE;
+}
+
+static void server_set_state(AvahiServer *s, AvahiServerState state) {
+ g_assert(s);
+
+ if (s->state == state)
+ return;
+
+ s->state = state;
+
+ if (s->callback)
+ s->callback(s, state, s->userdata);
+}
+
+static void withdraw_host_rrs(AvahiServer *s) {
+ g_assert(s);
+
+ if (s->hinfo_entry_group)
+ avahi_entry_group_reset(s->hinfo_entry_group);
+
+ if (s->browse_domain_entry_group)
+ avahi_entry_group_reset(s->browse_domain_entry_group);
+
+ avahi_update_host_rrs(s->monitor, TRUE);
+ s->n_host_rr_pending = 0;
+}
+
+void avahi_server_decrease_host_rr_pending(AvahiServer *s) {
+ g_assert(s);
+
+ g_assert(s->n_host_rr_pending > 0);
+
+ if (--s->n_host_rr_pending == 0)
+ server_set_state(s, AVAHI_SERVER_RUNNING);
+}
+
+void avahi_server_increase_host_rr_pending(AvahiServer *s) {
+ g_assert(s);
+
+ s->n_host_rr_pending ++;
+}
+
+void avahi_host_rr_entry_group_callback(AvahiServer *s, AvahiEntryGroup *g, AvahiEntryGroupState state, void *userdata) {
+ g_assert(s);
+ g_assert(g);
+
+ if (state == AVAHI_ENTRY_GROUP_REGISTERING &&
+ s->state == AVAHI_SERVER_REGISTERING)
+ avahi_server_increase_host_rr_pending(s);
+ else if (state == AVAHI_ENTRY_GROUP_COLLISION &&
+ (s->state == AVAHI_SERVER_REGISTERING || s->state == AVAHI_SERVER_RUNNING)) {
+ withdraw_host_rrs(s);
+ server_set_state(s, AVAHI_SERVER_COLLISION);
+ } else if (state == AVAHI_ENTRY_GROUP_ESTABLISHED &&
+ s->state == AVAHI_SERVER_REGISTERING)
+ avahi_server_decrease_host_rr_pending(s);
+}
+
+static void register_hinfo(AvahiServer *s) {
+ struct utsname utsname;
+ AvahiRecord *r;
+
+ g_assert(s);
+
+ if (!s->config.publish_hinfo)
+ return;
+
+ if (s->hinfo_entry_group)
+ g_assert(avahi_entry_group_is_empty(s->hinfo_entry_group));
+ else
+ s->hinfo_entry_group = avahi_entry_group_new(s, avahi_host_rr_entry_group_callback, NULL);
+
+ /* Fill in HINFO rr */
+ r = avahi_record_new_full(s->host_name_fqdn, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_HINFO, AVAHI_DEFAULT_TTL_HOST_NAME);
+ uname(&utsname);
+ r->data.hinfo.cpu = g_strdup(g_strup(utsname.machine));
+ r->data.hinfo.os = g_strdup(g_strup(utsname.sysname));
+ avahi_server_add(s, s->hinfo_entry_group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, AVAHI_ENTRY_UNIQUE, r);
+ avahi_record_unref(r);
+
+ avahi_entry_group_commit(s->hinfo_entry_group);
+}
+
+static void register_localhost(AvahiServer *s) {
+ AvahiAddress a;
+ g_assert(s);
+
+ /* Add localhost entries */
+ avahi_address_parse("127.0.0.1", AVAHI_PROTO_INET, &a);
+ avahi_server_add_address(s, NULL, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, AVAHI_ENTRY_NOPROBE|AVAHI_ENTRY_NOANNOUNCE, "localhost", &a);
+
+ avahi_address_parse("::1", AVAHI_PROTO_INET6, &a);
+ avahi_server_add_address(s, NULL, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, AVAHI_ENTRY_NOPROBE|AVAHI_ENTRY_NOANNOUNCE, "ip6-localhost", &a);
+}
+
+static void register_browse_domain(AvahiServer *s) {
+ g_assert(s);
+
+ if (!s->config.publish_domain)
+ return;
+
+ if (s->browse_domain_entry_group)
+ g_assert(avahi_entry_group_is_empty(s->browse_domain_entry_group));
+ else
+ s->browse_domain_entry_group = avahi_entry_group_new(s, NULL, NULL);
+
+ avahi_server_add_ptr(s, s->browse_domain_entry_group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, AVAHI_DEFAULT_TTL, "b._dns-sd._udp.local", s->domain_name);
+ avahi_entry_group_commit(s->browse_domain_entry_group);
+}
+
+static void register_stuff(AvahiServer *s) {
+ g_assert(s);
+
+ server_set_state(s, AVAHI_SERVER_REGISTERING);
+ register_hinfo(s);
+ register_browse_domain(s);
+ avahi_update_host_rrs(s->monitor, FALSE);
+
+ if (s->n_host_rr_pending == 0)
+ server_set_state(s, AVAHI_SERVER_RUNNING);
+}
+
+static void update_fqdn(AvahiServer *s) {
+ g_assert(s);
+
+ g_assert(s->host_name);
+ g_assert(s->domain_name);
+
+ g_free(s->host_name_fqdn);
+ s->host_name_fqdn = g_strdup_printf("%s.%s", s->host_name, s->domain_name);
+}
+
+gint avahi_server_set_host_name(AvahiServer *s, const gchar *host_name) {
+ g_assert(s);
+ g_assert(host_name);
+
+ withdraw_host_rrs(s);
+
+ g_free(s->host_name);
+ s->host_name = host_name ? avahi_normalize_name(host_name) : avahi_get_host_name();
+ s->host_name[strcspn(s->host_name, ".")] = 0;
+ update_fqdn(s);
+
+ register_stuff(s);
+ return AVAHI_OK;
+}
+
+gint avahi_server_set_domain_name(AvahiServer *s, const gchar *domain_name) {