+
+ oid_data *data;
+ sw_result result = SW_E_UNKNOWN;
+ service_data *sdata;
+ AvahiStringList *txt = NULL;
+
+ assert(self);
+ assert(name);
+ assert(type);
+ assert(reply);
+ assert(oid);
+
+ AVAHI_WARN_LINKAGE;
+
+ if (text_record && text_record_len > 0)
+ if (avahi_string_list_parse(text_record, text_record_len, &txt) < 0)
+ return SW_E_UNKNOWN;
+
+ if ((*oid = oid_alloc(self, OID_ENTRY_GROUP)) == (sw_discovery_oid) -1) {
+ avahi_string_list_free(txt);
+ return SW_E_UNKNOWN;
+ }
+
+ if (!(sdata = service_data_new(self))) {
+ avahi_string_list_free(txt);
+ oid_release(self, *oid);
+ return SW_E_MEM;
+ }
+
+ data = oid_get(self, *oid);
+ assert(data);
+ data->reply = (sw_result (*)(void)) reply;
+ data->extra = extra;
+ data->service_data = sdata;
+
+ sdata->interface = interface_index == 0 ? AVAHI_IF_UNSPEC : (AvahiIfIndex) interface_index;
+ sdata->name = avahi_strdup(name);
+ sdata->regtype = type ? avahi_normalize_name_strdup(type) : NULL;
+ sdata->domain = domain ? avahi_normalize_name_strdup(domain) : NULL;
+ sdata->host = host ? avahi_normalize_name_strdup(host) : NULL;
+ sdata->port = port;
+ sdata->txt = txt;
+
+ /* Some OOM checking would be cool here */
+
+ ASSERT_SUCCESS(pthread_mutex_lock(&self->mutex));
+
+ if (!(data->object = avahi_entry_group_new(self->client, reg_entry_group_callback, data))) {
+ result = map_error(avahi_client_errno(self->client));
+ goto finish;
+ }
+
+ if (avahi_client_get_state(self->client) == AVAHI_CLIENT_S_RUNNING) {
+ int error;
+
+ if ((error = reg_create_service(data)) < 0) {
+ result = map_error(error);
+ goto finish;
+ }
+ }
+
+ result = SW_OKAY;
+
+finish:
+
+ ASSERT_SUCCESS(pthread_mutex_unlock(&self->mutex));
+
+ if (result != SW_OKAY)
+ if (*oid != (sw_discovery_oid) -1)
+ sw_discovery_cancel(self, *oid);
+
+ return result;
+}
+
+static void domain_browser_callback(
+ AvahiDomainBrowser *b,
+ AvahiIfIndex interface,
+ AVAHI_GCC_UNUSED AvahiProtocol protocol,
+ AvahiBrowserEvent event,
+ const char *domain,
+ AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
+ void *userdata) {
+
+ oid_data* data = userdata;
+ sw_discovery_browse_reply reply;
+ static char domain_fixed[AVAHI_DOMAIN_NAME_MAX];
+
+ assert(b);
+ assert(data);
+
+ reply = (sw_discovery_browse_reply) data->reply;
+
+ domain = add_trailing_dot(domain, domain_fixed, sizeof(domain_fixed));
+
+ switch (event) {
+ case AVAHI_BROWSER_NEW:
+ reply(data->discovery, OID_GET_INDEX(data), SW_DISCOVERY_BROWSE_ADD_DOMAIN, interface, NULL, NULL, domain, data->extra);
+ break;
+
+ case AVAHI_BROWSER_REMOVE:
+ reply(data->discovery, OID_GET_INDEX(data), SW_DISCOVERY_BROWSE_REMOVE_DOMAIN, interface, NULL, NULL, domain, data->extra);
+ break;
+
+ case AVAHI_BROWSER_FAILURE:
+ reply(data->discovery, OID_GET_INDEX(data), SW_DISCOVERY_BROWSE_INVALID, interface, NULL, NULL, domain, data->extra);
+ break;
+
+ case AVAHI_BROWSER_CACHE_EXHAUSTED:
+ case AVAHI_BROWSER_ALL_FOR_NOW:
+ break;
+ }