+
+void avahi_server_add_text_strlst(
+ AvahiServer *s,
+ AvahiEntryGroup *g,
+ gint interface,
+ guchar protocol,
+ AvahiEntryFlags flags,
+ const gchar *name,
+ AvahiStringList *strlst) {
+
+ AvahiRecord *r;
+
+ g_assert(s);
+
+ r = avahi_record_new_full(name ? name : s->hostname, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_TXT);
+ r->data.txt.string_list = strlst;
+ avahi_server_add(s, g, interface, protocol, flags, r);
+ avahi_record_unref(r);
+}
+
+void avahi_server_add_text_va(
+ AvahiServer *s,
+ AvahiEntryGroup *g,
+ gint interface,
+ guchar protocol,
+ AvahiEntryFlags flags,
+ const gchar *name,
+ va_list va) {
+
+ g_assert(s);
+
+ avahi_server_add_text_strlst(s, g, interface, protocol, flags, name, avahi_string_list_new_va(va));
+}
+
+void avahi_server_add_text(
+ AvahiServer *s,
+ AvahiEntryGroup *g,
+ gint interface,
+ guchar protocol,
+ AvahiEntryFlags flags,
+ const gchar *name,
+ ...) {
+
+ va_list va;
+
+ g_assert(s);
+
+ va_start(va, name);
+ avahi_server_add_text_va(s, g, interface, protocol, flags, name, va);
+ va_end(va);
+}
+
+static void escape_service_name(gchar *d, guint size, const gchar *s) {
+ g_assert(d);
+ g_assert(size);
+ g_assert(s);
+
+ while (*s && size >= 2) {
+ if (*s == '.' || *s == '\\') {
+ if (size < 3)
+ break;
+
+ *(d++) = '\\';
+ size--;
+ }
+
+ *(d++) = *(s++);
+ size--;
+ }
+
+ g_assert(size > 0);
+ *(d++) = 0;
+}
+
+void avahi_server_add_service_strlst(
+ AvahiServer *s,
+ AvahiEntryGroup *g,
+ gint interface,
+ guchar protocol,
+ const gchar *type,
+ const gchar *name,
+ const gchar *domain,
+ const gchar *host,
+ guint16 port,
+ AvahiStringList *strlst) {
+
+ gchar ptr_name[256], svc_name[256], ename[64], enum_ptr[256];
+ AvahiRecord *r;
+
+ g_assert(s);
+ g_assert(type);
+ g_assert(name);
+
+ escape_service_name(ename, sizeof(ename), name);
+
+ if (domain) {
+ while (domain[0] == '.')
+ domain++;
+ } else
+ domain = "local";
+
+ if (!host)
+ host = s->hostname;
+
+ snprintf(ptr_name, sizeof(ptr_name), "%s.%s", type, domain);
+ snprintf(svc_name, sizeof(svc_name), "%s.%s.%s", ename, type, domain);
+
+ avahi_server_add_ptr(s, g, interface, protocol, AVAHI_ENTRY_NULL, ptr_name, svc_name);
+
+ r = avahi_record_new_full(svc_name, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_SRV);
+ r->data.srv.priority = 0;
+ r->data.srv.weight = 0;
+ r->data.srv.port = port;
+ r->data.srv.name = avahi_normalize_name(host);
+ avahi_server_add(s, g, interface, protocol, AVAHI_ENTRY_UNIQUE, r);
+ avahi_record_unref(r);
+
+ avahi_server_add_text_strlst(s, g, interface, protocol, AVAHI_ENTRY_UNIQUE, svc_name, strlst);
+
+ snprintf(enum_ptr, sizeof(enum_ptr), "_services._dns-sd._udp.%s", domain);
+ avahi_server_add_ptr(s, g, interface, protocol, AVAHI_ENTRY_NULL, enum_ptr, ptr_name);
+}
+
+void avahi_server_add_service_va(
+ AvahiServer *s,
+ AvahiEntryGroup *g,
+ gint interface,
+ guchar protocol,
+ const gchar *type,
+ const gchar *name,
+ const gchar *domain,
+ const gchar *host,
+ guint16 port,
+ va_list va){
+
+ g_assert(s);
+ g_assert(type);
+ g_assert(name);
+
+ avahi_server_add_service(s, g, interface, protocol, type, name, domain, host, port, avahi_string_list_new_va(va));
+}
+
+void avahi_server_add_service(
+ AvahiServer *s,
+ AvahiEntryGroup *g,
+ gint interface,
+ guchar protocol,
+ const gchar *type,
+ const gchar *name,
+ const gchar *domain,
+ const gchar *host,
+ guint16 port,
+ ... ){
+
+ va_list va;
+
+ g_assert(s);
+ g_assert(type);
+ g_assert(name);
+
+ va_start(va, port);
+ avahi_server_add_service_va(s, g, interface, protocol, type, name, domain, host, port, va);
+ va_end(va);
+}
+
+static void post_query_callback(AvahiInterfaceMonitor *m, AvahiInterface *i, gpointer userdata) {
+ AvahiKey *k = userdata;
+
+ g_assert(m);
+ g_assert(i);
+ g_assert(k);
+
+ avahi_interface_post_query(i, k, FALSE);
+}
+
+void avahi_server_post_query(AvahiServer *s, gint interface, guchar protocol, AvahiKey *key) {
+ g_assert(s);
+ g_assert(key);
+
+ avahi_interface_monitor_walk(s->monitor, interface, protocol, post_query_callback, key);
+}
+
+struct tmpdata {
+ AvahiRecord *record;
+ gboolean flush_cache;
+};
+
+static void post_response_callback(AvahiInterfaceMonitor *m, AvahiInterface *i, gpointer userdata) {
+ struct tmpdata *tmpdata = userdata;
+
+ g_assert(m);
+ g_assert(i);
+ g_assert(tmpdata);
+
+ avahi_interface_post_response(i, NULL, tmpdata->record, tmpdata->flush_cache, FALSE);
+}
+
+void avahi_server_post_response(AvahiServer *s, gint interface, guchar protocol, AvahiRecord *record, gboolean flush_cache) {
+ struct tmpdata tmpdata;
+
+ g_assert(s);
+ g_assert(record);
+
+ tmpdata.record = record;
+ tmpdata.flush_cache = flush_cache;
+
+ avahi_interface_monitor_walk(s->monitor, interface, protocol, post_response_callback, &tmpdata);
+}
+
+void avahi_entry_group_change_state(AvahiEntryGroup *g, AvahiEntryGroupState state) {
+ g_assert(g);
+
+ g->state = state;
+
+ if (g->callback) {
+ g->callback(g->server, g, state, g->userdata);
+ return;
+ }
+}
+
+AvahiEntryGroup *avahi_entry_group_new(AvahiServer *s, AvahiEntryGroupCallback callback, gpointer userdata) {
+ AvahiEntryGroup *g;
+
+ g_assert(s);
+
+ g = g_new(AvahiEntryGroup, 1);
+ g->server = s;
+ g->callback = callback;
+ g->userdata = userdata;
+ g->dead = FALSE;
+ g->state = AVAHI_ENTRY_GROUP_UNCOMMITED;
+ g->n_probing = 0;
+ AVAHI_LLIST_HEAD_INIT(AvahiEntry, g->entries);
+
+ AVAHI_LLIST_PREPEND(AvahiEntryGroup, groups, s->groups, g);
+ return g;
+}
+
+void avahi_entry_group_free(AvahiEntryGroup *g) {
+ g_assert(g);
+ g_assert(g->server);
+
+ g->dead = TRUE;
+ g->server->need_group_cleanup = TRUE;
+}
+
+void avahi_entry_group_commit(AvahiEntryGroup *g) {
+ AvahiEntry *e;
+
+ g_assert(g);
+ g_assert(!g->dead);
+
+ if (g->state != AVAHI_ENTRY_GROUP_UNCOMMITED)
+ return;
+
+ avahi_entry_group_change_state(g, AVAHI_ENTRY_GROUP_REGISTERING);
+ avahi_announce_group(g->server, g);
+ avahi_entry_group_check_probed(g, FALSE);
+}
+
+gboolean avahi_entry_commited(AvahiEntry *e) {
+ g_assert(e);
+ g_assert(!e->dead);
+
+ return !e->group ||
+ e->group->state == AVAHI_ENTRY_GROUP_REGISTERING ||
+ e->group->state == AVAHI_ENTRY_GROUP_ESTABLISHED;
+}
+
+AvahiEntryGroupState avahi_entry_group_get_state(AvahiEntryGroup *g) {
+ g_assert(g);
+ g_assert(!g->dead);
+
+ return g->state;
+}