#include <string.h>
#include <signal.h>
#include <netinet/in.h>
+#include <fcntl.h>
#include <avahi-common/simple-watch.h>
#include <avahi-common/malloc.h>
#include <avahi-common/error.h>
#include <avahi-common/domain.h>
#include <avahi-common/alternative.h>
+
#include <avahi-client/client.h>
+#include <avahi-client/publish.h>
+#include <avahi-client/lookup.h>
#include "warn.h"
#include "dns_sd.h"
enum {
COMMAND_POLL = 'p',
COMMAND_QUIT = 'q',
- COMMAND_POLL_DONE = 'P'
+ COMMAND_POLL_DONE = 'P',
+ COMMAND_POLL_FAILED = 'F'
};
struct _DNSServiceRef_t {
int thread_running;
pthread_mutex_t mutex;
-
+
void *context;
DNSServiceBrowseReply service_browser_callback;
DNSServiceResolveReply service_resolver_callback;
return kDNSServiceErr_BadParam;
- case AVAHI_ERR_LOCAL_COLLISION:
+ case AVAHI_ERR_COLLISION:
return kDNSServiceErr_NameConflict;
case AVAHI_ERR_TOO_MANY_CLIENTS:
switch (command) {
- case COMMAND_POLL:
+ case COMMAND_POLL: {
+ int ret;
ASSERT_SUCCESS(pthread_mutex_lock(&sdref->mutex));
-
- if (avahi_simple_poll_run(sdref->simple_poll) < 0) {
- fprintf(stderr, __FILE__": avahi_simple_poll_run() failed.\n");
- ASSERT_SUCCESS(pthread_mutex_unlock(&sdref->mutex));
+
+ for (;;) {
+ errno = 0;
+
+ if ((ret = avahi_simple_poll_run(sdref->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(&sdref->mutex));
- if (write_command(sdref->thread_fd, COMMAND_POLL_DONE) < 0)
+ if (write_command(sdref->thread_fd, ret < 0 ? COMMAND_POLL_FAILED : COMMAND_POLL_DONE) < 0)
break;
break;
+ }
case COMMAND_QUIT:
return NULL;
if (sdref->simple_poll)
avahi_simple_poll_free(sdref->simple_poll);
-
if (sdref->thread_fd >= 0)
close(sdref->thread_fd);
AVAHI_WARN_LINKAGE;
- sdref_ref(sdref);
-
ASSERT_SUCCESS(pthread_mutex_lock(&sdref->mutex));
+
+ sdref_ref(sdref);
/* Cleanup notification socket */
if (read_command(sdref->main_fd) != COMMAND_POLL_DONE)
finish:
- ASSERT_SUCCESS(pthread_mutex_unlock(&sdref->mutex));
-
sdref_unref(sdref);
+
+ ASSERT_SUCCESS(pthread_mutex_unlock(&sdref->mutex));
return ret;
}
void DNSSD_API DNSServiceRefDeallocate(DNSServiceRef sdref) {
- assert(sdref);
- assert(sdref->n_ref >= 1);
-
AVAHI_WARN_LINKAGE;
- sdref_unref(sdref);
+ if (sdref)
+ sdref_unref(sdref);
}
static void service_browser_callback(
static void generic_client_callback(AvahiClient *s, AvahiClientState state, void* userdata) {
DNSServiceRef sdref = userdata;
-
+ int error = kDNSServiceErr_Unknown;
+
assert(s);
assert(sdref);
assert(sdref->n_ref >= 1);
switch (state) {
- case AVAHI_CLIENT_DISCONNECTED: {
+ case AVAHI_CLIENT_S_FAILURE:
+
+ error = map_error(avahi_client_errno(s));
+
+ /* Fall through */
+
+ case AVAHI_CLIENT_DISCONNECTED:
if (sdref->service_browser_callback)
- sdref->service_browser_callback(sdref, 0, 0, kDNSServiceErr_Unknown, NULL, NULL, NULL, sdref->context);
+ sdref->service_browser_callback(sdref, 0, 0, error, NULL, NULL, NULL, sdref->context);
else if (sdref->service_resolver_callback)
- sdref->service_resolver_callback(sdref, 0, 0, kDNSServiceErr_Unknown, NULL, NULL, 0, 0, NULL, sdref->context);
+ sdref->service_resolver_callback(sdref, 0, 0, error, NULL, NULL, 0, 0, NULL, sdref->context);
else if (sdref->domain_browser_callback)
- sdref->domain_browser_callback(sdref, 0, 0, kDNSServiceErr_Unknown, NULL, sdref->context);
+ sdref->domain_browser_callback(sdref, 0, 0, error, NULL, sdref->context);
break;
- }
case AVAHI_CLIENT_S_RUNNING:
case AVAHI_CLIENT_S_COLLISION:
return;
switch (state) {
- case AVAHI_CLIENT_DISCONNECTED: {
+ case AVAHI_CLIENT_DISCONNECTED:
+ reg_report_error(sdref, kDNSServiceErr_Unknown);
+ break;
- reg_report_error(sdref, kDNSServiceErr_NoError);
+ case AVAHI_CLIENT_S_FAILURE:
+ reg_report_error(sdref, map_error(avahi_client_errno(s)));
break;
- }
case AVAHI_CLIENT_S_RUNNING: {
int ret;
/* If the service name is taken from the host name, copy that */
avahi_free(sdref->service_name_chosen);
+ sdref->service_name_chosen = NULL;
if (!(n = avahi_client_get_host_name(sdref->client))) {
reg_report_error(sdref, map_error(avahi_client_errno(sdref->client)));
case AVAHI_ENTRY_GROUP_UNCOMMITED:
/* Ignore */
break;
+
+ case AVAHI_ENTRY_GROUP_FAILURE:
+ /* Inform the user */
+ reg_report_error(sdref, map_error(avahi_client_errno(sdref->client)));
+ break;
+
}
}
sdref->service_host = host ? avahi_normalize_name_strdup(host) : NULL;
sdref->service_interface = interface == kDNSServiceInterfaceIndexAny ? AVAHI_IF_UNSPEC : (AvahiIfIndex) interface;
sdref->service_port = ntohs(port);
- sdref->service_txt = txtRecord ? avahi_string_list_parse(txtRecord, txtLen) : NULL;
+ sdref->service_txt = txtRecord && txtLen > 0 ? avahi_string_list_parse(txtRecord, txtLen) : NULL;
+
+ /* Some OOM checking would be cool here */
ASSERT_SUCCESS(pthread_mutex_lock(&sdref->mutex));