#include <avahi-common/simple-watch.h>
#include <avahi-common/error.h>
#include <avahi-common/llist.h>
+
#include <avahi-client/client.h>
+#include <avahi-client/publish.h>
+#include <avahi-client/lookup.h>
#include "howl.h"
#include "warn.h"
enum {
COMMAND_POLL = 'p',
COMMAND_QUIT = 'q',
- COMMAND_POLL_DONE = 'P'
+ COMMAND_POLL_DONE = 'P',
+ COMMAND_POLL_FAILED = 'F'
};
typedef enum {
pthread_t thread;
int thread_running;
- pthread_mutex_t mutex;
+ pthread_mutex_t mutex, salt_mutex;
AVAHI_LLIST_HEAD(service_data, services);
};
switch (command) {
- case COMMAND_POLL:
+ case COMMAND_POLL: {
+ int ret;
ASSERT_SUCCESS(pthread_mutex_lock(&self->mutex));
+
+ for (;;) {
+ errno = 0;
- if (avahi_simple_poll_run(self->simple_poll) < 0) {
- fprintf(stderr, __FILE__": avahi_simple_poll_run() failed.\n");
- ASSERT_SUCCESS(pthread_mutex_unlock(&self->mutex));
+ if ((ret = avahi_simple_poll_run(self->simple_poll)) < 0) {
+
+ if (errno == EINTR)
+ continue;
+
+ fprintf(stderr, __FILE__": avahi_simple_poll_run() failed: %s\n", strerror(errno));
+ }
+
break;
}
-
+
ASSERT_SUCCESS(pthread_mutex_unlock(&self->mutex));
- if (write_command(self->thread_fd, COMMAND_POLL_DONE) < 0)
+ if (write_command(self->thread_fd, ret < 0 ? COMMAND_POLL_FAILED : COMMAND_POLL_DONE) < 0)
break;
break;
+ }
case COMMAND_QUIT:
return NULL;
ASSERT_SUCCESS(pthread_mutexattr_init(&mutex_attr));
pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
ASSERT_SUCCESS(pthread_mutex_init(&(*self)->mutex, &mutex_attr));
+ ASSERT_SUCCESS(pthread_mutex_init(&(*self)->salt_mutex, &mutex_attr));
if (!((*self)->simple_poll = avahi_simple_poll_new()))
goto fail;
avahi_simple_poll_set_func((*self)->simple_poll, poll_func, *self);
- if (!((*self)->client = avahi_client_new(avahi_simple_poll_get((*self)->simple_poll), client_callback, *self, &error))) {
+ if (!((*self)->client = avahi_client_new(avahi_simple_poll_get((*self)->simple_poll), 0, client_callback, *self, &error))) {
result = map_error(error);
goto fail;
}
close(self->main_fd);
ASSERT_SUCCESS(pthread_mutex_destroy(&self->mutex));
+ ASSERT_SUCCESS(pthread_mutex_destroy(&self->salt_mutex));
while (self->services)
service_data_free(self, self->services);
sw_result sw_salt_run(sw_salt self) {
sw_result ret;
-
+
AVAHI_WARN_LINKAGE;
+
+ assert(self);
for (;;)
if ((ret = sw_salt_step(self, NULL)) != SW_OKAY)
sw_result sw_salt_stop_run(sw_salt self) {
AVAHI_WARN_LINKAGE;
+ assert(self);
+
if (stop_thread((sw_discovery) self) < 0)
return SW_E_UNKNOWN;
return SW_OKAY;
}
+sw_result sw_salt_lock(sw_salt self) {
+ AVAHI_WARN_LINKAGE;
+
+ assert(self);
+ ASSERT_SUCCESS(pthread_mutex_lock(&((sw_discovery) self)->salt_mutex));
+
+ return SW_OKAY;
+}
+
+sw_result sw_salt_unlock(sw_salt self) {
+ assert(self);
+
+ AVAHI_WARN_LINKAGE;
+
+ ASSERT_SUCCESS(pthread_mutex_unlock(&((sw_discovery) self)->salt_mutex));
+
+ return SW_OKAY;
+}
+
static void reg_report_status(oid_data *data, sw_discovery_publish_status status) {
sw_discovery_publish_reply reply;
return;
switch (state) {
- case AVAHI_CLIENT_DISCONNECTED:
+ case AVAHI_CLIENT_FAILURE:
reg_report_status(data, SW_DISCOVERY_PUBLISH_INVALID);
break;
}
case AVAHI_CLIENT_S_COLLISION:
+ case AVAHI_CLIENT_S_REGISTERING:
/* Remove our entry */
avahi_entry_group_reset(data->object);
break;
- case AVAHI_CLIENT_S_INVALID:
- case AVAHI_CLIENT_S_REGISTERING:
+ case AVAHI_CLIENT_CONNECTING:
/* Ignore */
break;
}
case AVAHI_ENTRY_GROUP_UNCOMMITED:
/* Ignore */
break;
+
+ case AVAHI_ENTRY_GROUP_FAILURE:
+ reg_report_status(data, SW_DISCOVERY_PUBLISH_INVALID);
+ break;
+
}
}
oid_data *data;
sw_result result = SW_E_UNKNOWN;
service_data *sdata;
+ AvahiStringList *txt = NULL;
assert(self);
assert(name);
AVAHI_WARN_LINKAGE;
- if ((*oid = oid_alloc(self, OID_ENTRY_GROUP)) == (sw_discovery_oid) -1)
+ 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;
}
sdata->domain = domain ? avahi_normalize_name_strdup(domain) : NULL;
sdata->host = host ? avahi_normalize_name_strdup(host) : NULL;
sdata->port = port;
- sdata->txt = text_record && text_record_len > 0 ? avahi_string_list_parse(text_record, text_record_len) : NULL;
+ sdata->txt = txt;
/* Some OOM checking would be cool here */
static void domain_browser_callback(
AvahiDomainBrowser *b,
AvahiIfIndex interface,
- AvahiProtocol protocol,
+ AVAHI_GCC_UNUSED AvahiProtocol protocol,
AvahiBrowserEvent event,
const char *domain,
- AvahiLookupResultFlags flags,
+ AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
void *userdata) {
oid_data* data = userdata;
static void service_resolver_callback(
AvahiServiceResolver *r,
AvahiIfIndex interface,
- AvahiProtocol protocol,
+ AVAHI_GCC_UNUSED AvahiProtocol protocol,
AvahiResolverEvent event,
const char *name,
const char *type,
const AvahiAddress *a,
uint16_t port,
AvahiStringList *txt,
- AvahiLookupResultFlags flags,
+ AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
void *userdata) {
oid_data* data = userdata;
static void service_browser_callback(
AvahiServiceBrowser *b,
AvahiIfIndex interface,
- AvahiProtocol protocol,
+ AVAHI_GCC_UNUSED AvahiProtocol protocol,
AvahiBrowserEvent event,
const char *name,
const char *type,
const char *domain,
- AvahiLookupResultFlags flags,
+ AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
void *userdata) {
oid_data* data = userdata;