Esempio n. 1
0
void _mdns_retrieve_buddy_icon(BonjourBuddy* buddy) {
	PurpleConnection *conn = purple_account_get_connection(buddy->account);
	BonjourData *bd = conn->proto_data;
	AvahiSessionImplData *session_idata = bd->dns_sd_data->mdns_impl_data;
	AvahiBuddyImplData *idata = buddy->mdns_impl_data;
	gchar *name;

	g_return_if_fail(idata != NULL);

	if (idata->buddy_icon_rec_browser != NULL)
		avahi_record_browser_free(idata->buddy_icon_rec_browser);

	purple_debug_info("bonjour", "Retrieving buddy icon for '%s'.\n", buddy->name);

	name = g_strdup_printf("%s." ICHAT_SERVICE "local", buddy->name);
	idata->buddy_icon_rec_browser = avahi_record_browser_new(session_idata->client, AVAHI_IF_UNSPEC,
		AVAHI_PROTO_UNSPEC, name, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_NULL, 0,
		_buddy_icon_record_cb, buddy);
	g_free(name);

	if (!idata->buddy_icon_rec_browser) {
		purple_debug_error("bonjour",
			"Unable to initialize buddy icon record browser.  Error: %s\n.",
			avahi_strerror(avahi_client_errno(session_idata->client)));
	}

}
Esempio n. 2
0
void QxtMDNSPrivate::avahiClientCallback(AvahiClient *s, AvahiClientState state, void *userdata)
{
	QxtMDNSPrivate* self = static_cast<QxtMDNSPrivate*>(userdata);
	self->client = s;
	if (state == AVAHI_CLIENT_S_RUNNING)
	{
		self->recordbrowser = avahi_record_browser_new(
		                          s,
		                          AVAHI_IF_UNSPEC,
		                          AVAHI_PROTO_INET,
		                          self->name.toAscii().constData(),
		                          AVAHI_DNS_CLASS_IN,
		                          AVAHI_DNS_TYPE_A,
		                          (AvahiLookupFlags)0,
					   QxtMDNSPrivate::avahiRecordBrowserCallback,
		                          self);
		if (self->recordbrowser == NULL)
		{
			self->info.setError(QHostInfo::UnknownError);
			self->info.setErrorString(avahi_strerror(avahi_client_errno(self->client)));
			QMetaObject::invokeMethod(self->receiver, self->member, Q_ARG(QHostInfo, self->info));
			self->sent = true;
			self->qxt_p().cancelLookup();
		}
	}
}
int main(AVAHI_GCC_UNUSED int argc, AVAHI_GCC_UNUSED char *argv[]) {

    AvahiSimplePoll *simple_poll;
    const AvahiPoll *poll_api;
    AvahiClient *client;
    AvahiRecordBrowser *r;
    
    simple_poll = avahi_simple_poll_new();
    assert(simple_poll);
    
    poll_api = avahi_simple_poll_get(simple_poll);
    assert(poll_api);
    
    client = avahi_client_new(poll_api, 0, NULL, NULL, NULL);
    assert(client);

    r = avahi_record_browser_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "ecstasy.local", AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_HINFO, 0, callback, simple_poll);
    assert(r);

    avahi_simple_poll_loop(simple_poll);

    avahi_client_free(client);
    avahi_simple_poll_free(simple_poll);

    return 0;
}
Esempio n. 4
0
static void browse_callback(
        AvahiRecordBrowser *b,
        AvahiIfIndex interface,
        AvahiProtocol protocol,
        AvahiBrowserEvent event,
        const char *name,
        uint16_t clazz,
        uint16_t type, const void *rdata, size_t size,
        AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
        void* userdata) {

    AvahiClient *c = userdata;
    assert(b);

    /* Called whenever a new services becomes available on the LAN or is removed from the LAN */

    switch (event) {
        case AVAHI_BROWSER_FAILURE:

            fprintf(stderr, "(Browser) %s\n", 
                    avahi_strerror(avahi_client_errno(avahi_record_browser_get_client(b))));
            avahi_simple_poll_quit(simple_poll);
            return;

        case AVAHI_BROWSER_NEW:
            fprintf(stderr, "(Browser) NEW: service '%s' '\n", name);

            /* We ignore the returned resolver object. In the callback
               function we free it. If the server is terminated before
               the callback function is called the server will free
               the resolver for us. */

            if (!(avahi_record_browser_new(c, interface, protocol, name, clazz, type, 
                            flags, resolve_callback, userdata)))
                fprintf(stderr, "Failed to resolve service '%s': %s\n", 
                        name, avahi_strerror(avahi_client_errno(c)));

            break;

        case AVAHI_BROWSER_REMOVE:
            fprintf(stderr, "(Browser) REMOVE: service '%s'\n", name);
            break;

        case AVAHI_BROWSER_ALL_FOR_NOW:
        case AVAHI_BROWSER_CACHE_EXHAUSTED:
            fprintf(stderr, "(Browser) %s\n", event == AVAHI_BROWSER_CACHE_EXHAUSTED ? 
                    "CACHE_EXHAUSTED" : "ALL_FOR_NOW");
            break;
    }
}
Esempio n. 5
0
File: dnssd.c Progetto: zdohnal/cups
int					/* O - Exit status */
main(int  argc,				/* I - Number of command-line args */
     char *argv[])			/* I - Command-line arguments */
{
  const char	*name;			/* Backend name */
  cups_array_t	*devices;		/* Device array */
  cups_device_t	*device;		/* Current device */
  char		uriName[1024];		/* Unquoted fullName for URI */
#ifdef HAVE_DNSSD
  int		fd;			/* Main file descriptor */
  fd_set	input;			/* Input set for select() */
  struct timeval timeout;		/* Timeout for select() */
  DNSServiceRef	main_ref,		/* Main service reference */
		fax_ipp_ref,		/* IPP fax service reference */
		ipp_ref,		/* IPP service reference */
		ipp_tls_ref,		/* IPP w/TLS service reference */
		ipps_ref,		/* IPP service reference */
		local_fax_ipp_ref,	/* Local IPP fax service reference */
		local_ipp_ref,		/* Local IPP service reference */
		local_ipp_tls_ref,	/* Local IPP w/TLS service reference */
		local_ipps_ref,		/* Local IPP service reference */
		local_printer_ref,	/* Local LPD service reference */
		pdl_datastream_ref,	/* AppSocket service reference */
		printer_ref,		/* LPD service reference */
		riousbprint_ref;	/* Remote IO service reference */
#endif /* HAVE_DNSSD */
#ifdef HAVE_AVAHI
  AvahiClient	*client;		/* Client information */
  int		error;			/* Error code, if any */
#endif /* HAVE_AVAHI */
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
  struct sigaction action;		/* Actions for POSIX signals */
#endif /* HAVE_SIGACTION && !HAVE_SIGSET */


 /*
  * Don't buffer stderr, and catch SIGTERM...
  */

  setbuf(stderr, NULL);

#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
  sigset(SIGTERM, sigterm_handler);
#elif defined(HAVE_SIGACTION)
  memset(&action, 0, sizeof(action));

  sigemptyset(&action.sa_mask);
  action.sa_handler = sigterm_handler;
  sigaction(SIGTERM, &action, NULL);
#else
  signal(SIGTERM, sigterm_handler);
#endif /* HAVE_SIGSET */

 /*
  * Check command-line...
  */

  if (argc >= 6)
    exec_backend(argv);
  else if (argc != 1)
  {
    _cupsLangPrintf(stderr,
                    _("Usage: %s job-id user title copies options [file]"),
		    argv[0]);
    return (1);
  }

 /*
  * Only do discovery when run as "dnssd"...
  */

  if ((name = strrchr(argv[0], '/')) != NULL)
    name ++;
  else
    name = argv[0];

  if (strcmp(name, "dnssd"))
    return (0);

 /*
  * Create an array to track devices...
  */

  devices = cupsArrayNew((cups_array_func_t)compare_devices, NULL);

 /*
  * Browse for different kinds of printers...
  */

#ifdef HAVE_DNSSD
  if (DNSServiceCreateConnection(&main_ref) != kDNSServiceErr_NoError)
  {
    perror("ERROR: Unable to create service connection");
    return (1);
  }

  fd = DNSServiceRefSockFD(main_ref);

  fax_ipp_ref = main_ref;
  DNSServiceBrowse(&fax_ipp_ref, kDNSServiceFlagsShareConnection, 0,
                   "_fax-ipp._tcp", NULL, browse_callback, devices);

  ipp_ref = main_ref;
  DNSServiceBrowse(&ipp_ref, kDNSServiceFlagsShareConnection, 0,
                   "_ipp._tcp", NULL, browse_callback, devices);

  ipp_tls_ref = main_ref;
  DNSServiceBrowse(&ipp_tls_ref, kDNSServiceFlagsShareConnection, 0,
                   "_ipp-tls._tcp", NULL, browse_callback, devices);

  ipps_ref = main_ref;
  DNSServiceBrowse(&ipps_ref, kDNSServiceFlagsShareConnection, 0,
                   "_ipps._tcp", NULL, browse_callback, devices);

  local_fax_ipp_ref = main_ref;
  DNSServiceBrowse(&local_fax_ipp_ref, kDNSServiceFlagsShareConnection,
                   kDNSServiceInterfaceIndexLocalOnly,
		   "_fax-ipp._tcp", NULL, browse_local_callback, devices);

  local_ipp_ref = main_ref;
  DNSServiceBrowse(&local_ipp_ref, kDNSServiceFlagsShareConnection,
                   kDNSServiceInterfaceIndexLocalOnly,
		   "_ipp._tcp", NULL, browse_local_callback, devices);

  local_ipp_tls_ref = main_ref;
  DNSServiceBrowse(&local_ipp_tls_ref, kDNSServiceFlagsShareConnection,
                   kDNSServiceInterfaceIndexLocalOnly,
                   "_ipp-tls._tcp", NULL, browse_local_callback, devices);

  local_ipps_ref = main_ref;
  DNSServiceBrowse(&local_ipps_ref, kDNSServiceFlagsShareConnection,
                   kDNSServiceInterfaceIndexLocalOnly,
		   "_ipps._tcp", NULL, browse_local_callback, devices);

  local_printer_ref = main_ref;
  DNSServiceBrowse(&local_printer_ref, kDNSServiceFlagsShareConnection,
                   kDNSServiceInterfaceIndexLocalOnly,
                   "_printer._tcp", NULL, browse_local_callback, devices);

  pdl_datastream_ref = main_ref;
  DNSServiceBrowse(&pdl_datastream_ref, kDNSServiceFlagsShareConnection, 0,
                   "_pdl-datastream._tcp", NULL, browse_callback, devices);

  printer_ref = main_ref;
  DNSServiceBrowse(&printer_ref, kDNSServiceFlagsShareConnection, 0,
                   "_printer._tcp", NULL, browse_callback, devices);

  riousbprint_ref = main_ref;
  DNSServiceBrowse(&riousbprint_ref, kDNSServiceFlagsShareConnection, 0,
                   "_riousbprint._tcp", NULL, browse_callback, devices);
#endif /* HAVE_DNSSD */

#ifdef HAVE_AVAHI
  if ((simple_poll = avahi_simple_poll_new()) == NULL)
  {
    fputs("DEBUG: Unable to create Avahi simple poll object.\n", stderr);
    return (0);
  }

  avahi_simple_poll_set_func(simple_poll, poll_callback, NULL);

  client = avahi_client_new(avahi_simple_poll_get(simple_poll),
			    0, client_callback, simple_poll, &error);
  if (!client)
  {
    fputs("DEBUG: Unable to create Avahi client.\n", stderr);
    return (0);
  }

  browsers = 6;
  avahi_service_browser_new(client, AVAHI_IF_UNSPEC,
			    AVAHI_PROTO_UNSPEC,
			    "_fax-ipp._tcp", NULL, 0,
			    browse_callback, devices);
  avahi_service_browser_new(client, AVAHI_IF_UNSPEC,
			    AVAHI_PROTO_UNSPEC,
			    "_ipp._tcp", NULL, 0,
			    browse_callback, devices);
  avahi_service_browser_new(client, AVAHI_IF_UNSPEC,
			    AVAHI_PROTO_UNSPEC,
			    "_ipp-tls._tcp", NULL, 0,
			    browse_callback, devices);
  avahi_service_browser_new(client, AVAHI_IF_UNSPEC,
			    AVAHI_PROTO_UNSPEC,
			    "_ipps._tcp", NULL, 0,
			    browse_callback, devices);
  avahi_service_browser_new(client, AVAHI_IF_UNSPEC,
			    AVAHI_PROTO_UNSPEC,
			    "_pdl-datastream._tcp",
			    NULL, 0,
			    browse_callback,
			    devices);
  avahi_service_browser_new(client, AVAHI_IF_UNSPEC,
			    AVAHI_PROTO_UNSPEC,
			    "_printer._tcp", NULL, 0,
			    browse_callback, devices);
#endif /* HAVE_AVAHI */

 /*
  * Loop until we are killed...
  */

  while (!job_canceled)
  {
    int announce = 0;			/* Announce printers? */

#ifdef HAVE_DNSSD
    FD_ZERO(&input);
    FD_SET(fd, &input);

    timeout.tv_sec  = 0;
    timeout.tv_usec = 500000;

    if (select(fd + 1, &input, NULL, NULL, &timeout) < 0)
      continue;

    if (FD_ISSET(fd, &input))
    {
     /*
      * Process results of our browsing...
      */

      DNSServiceProcessResult(main_ref);
    }
    else
      announce = 1;

#elif defined(HAVE_AVAHI)
    got_data = 0;

    if ((error = avahi_simple_poll_iterate(simple_poll, 500)) > 0)
    {
     /*
      * We've been told to exit the loop.  Perhaps the connection to
      * Avahi failed.
      */

      break;
    }

    if (!got_data)
      announce = 1;
#endif /* HAVE_DNSSD */

/*    fprintf(stderr, "DEBUG: announce=%d\n", announce);*/

    if (announce)
    {
     /*
      * Announce any devices we've found...
      */

#ifdef HAVE_DNSSD
      DNSServiceErrorType status;	/* DNS query status */
#endif /* HAVE_DNSSD */
      cups_device_t *best;		/* Best matching device */
      char	device_uri[1024];	/* Device URI */
      int	count;			/* Number of queries */
      int	sent;			/* Number of sent */

      for (device = (cups_device_t *)cupsArrayFirst(devices),
               best = NULL, count = 0, sent = 0;
           device;
	   device = (cups_device_t *)cupsArrayNext(devices))
      {
        if (device->sent)
	  sent ++;

        if (device->ref)
	  count ++;

        if (!device->ref && !device->sent)
	{
	 /*
	  * Found the device, now get the TXT record(s) for it...
	  */

          if (count < 50)
	  {
	    fprintf(stderr, "DEBUG: Querying \"%s\"...\n", device->fullName);

#ifdef HAVE_DNSSD
	    device->ref = main_ref;

	    status = DNSServiceQueryRecord(&(device->ref),
				           kDNSServiceFlagsShareConnection,
				           0, device->fullName,
					   kDNSServiceType_TXT,
				           kDNSServiceClass_IN, query_callback,
				           device);
            if (status != kDNSServiceErr_NoError)
	      fprintf(stderr,
	              "ERROR: Unable to query \"%s\" for TXT records: %d\n",
	              device->fullName, status);
	              			/* Users never see this */
	    else
	      count ++;

#else
	    if ((device->ref = avahi_record_browser_new(client, AVAHI_IF_UNSPEC,
	                                                AVAHI_PROTO_UNSPEC,
	                                                device->fullName,
	                                                AVAHI_DNS_CLASS_IN,
	                                                AVAHI_DNS_TYPE_TXT,
	                                                0,
				                        query_callback,
				                        device)) == NULL)
	      fprintf(stderr,
	              "ERROR: Unable to query \"%s\" for TXT records: %s\n",
	              device->fullName,
	              avahi_strerror(avahi_client_errno(client)));
	              			/* Users never see this */
	    else
	      count ++;
#endif /* HAVE_AVAHI */
          }
	}
	else if (!device->sent)
	{
#ifdef HAVE_DNSSD
	 /*
	  * Got the TXT records, now report the device...
	  */

	  DNSServiceRefDeallocate(device->ref);
#else
          avahi_record_browser_free(device->ref);
#endif /* HAVE_DNSSD */

	  device->ref = NULL;

          if (!best)
	    best = device;
	  else if (_cups_strcasecmp(best->name, device->name) ||
	           _cups_strcasecmp(best->domain, device->domain))
          {
	    unquote(uriName, best->fullName, sizeof(uriName));

            if (best->uuid)
	      httpAssembleURIf(HTTP_URI_CODING_ALL, device_uri,
	                       sizeof(device_uri), "dnssd", NULL, uriName, 0,
			       best->cups_shared ? "/cups?uuid=%s" : "/?uuid=%s",
			       best->uuid);
	    else
	      httpAssembleURI(HTTP_URI_CODING_ALL, device_uri,
	                      sizeof(device_uri), "dnssd", NULL, uriName, 0,
			      best->cups_shared ? "/cups" : "/");

	    cupsBackendReport("network", device_uri, best->make_and_model,
	                      best->name, best->device_id, NULL);
	    best->sent = 1;
	    best       = device;

	    sent ++;
	  }
	  else if (best->priority > device->priority ||
	           (best->priority == device->priority &&
		    best->type < device->type))
          {
	    best->sent = 1;
	    best       = device;

	    sent ++;
	  }
	  else
	  {
	    device->sent = 1;

	    sent ++;
	  }
        }
      }

      if (best)
      {
	unquote(uriName, best->fullName, sizeof(uriName));

	if (best->uuid)
	  httpAssembleURIf(HTTP_URI_CODING_ALL, device_uri,
			   sizeof(device_uri), "dnssd", NULL, uriName, 0,
			   best->cups_shared ? "/cups?uuid=%s" : "/?uuid=%s",
			   best->uuid);
	else
	  httpAssembleURI(HTTP_URI_CODING_ALL, device_uri,
			  sizeof(device_uri), "dnssd", NULL, uriName, 0,
			  best->cups_shared ? "/cups" : "/");

	cupsBackendReport("network", device_uri, best->make_and_model,
			  best->name, best->device_id, NULL);
	best->sent = 1;
	sent ++;
      }

      fprintf(stderr, "DEBUG: sent=%d, count=%d\n", sent, count);

#ifdef HAVE_AVAHI
      if (sent == cupsArrayCount(devices) && browsers == 0)
#else
      if (sent == cupsArrayCount(devices))
#endif /* HAVE_AVAHI */
	break;
    }
  }

  return (CUPS_BACKEND_OK);
}
JNIEXPORT jlong JNICALL Java_avahi4j_RecordBrowser_initBrowser(JNIEnv *e,
		jobject t, jlong ptr, jint jif_idx, jint jproto, jstring jname,
		jint jclazz, jint jtype, jint jflags){

	dprint("[LOG] Entering %s\n", __PRETTY_FUNCTION__);

	struct avahi4j_client *client = (struct avahi4j_client *) (uintptr_t) ptr;
	struct avahi4j_record_browser *browser = NULL;
	jclass ourClass;
	const char *name=NULL;
	int if_idx, proto, clazz, type, flags;

	// get utf string
	GET_UTF_STR_JUMP(name, jname, e, bail);

	// tranlsate ints
	GET_AVAHI_IF_IDX(if_idx,jif_idx);
	GET_AVAHI_PROTO(proto, jproto);
	J2A_DNS_CLASS(clazz, jclazz);
	J2A_DNS_RR_TYPE(type, jtype);
	GET_AVAHI_LOOKUP_FLAGS(flags, jflags);


	// create struct record browser
	XMALLOC(browser, struct avahi4j_record_browser *, sizeof(struct avahi4j_record_browser));
	if (browser==NULL) {
		THROW_EXCEPTION(e, JNI_EXCP, "Not enough memory");
		goto bail;
	}

	// save JavaVM ref
	if ((*e)->GetJavaVM(e, &browser->jvm)!=0){
		THROW_EXCEPTION(e, JNI_EXCP, "Cant get hold of a JavaVM pointer");
		goto bail;
	}

	// cache methodID to java group callback method
	ourClass = (*e)->GetObjectClass(e, t);
	browser->browserCallbackDispatch = (*e)->GetMethodID(e, ourClass,
			"dispatchCallback",	"(IIILjava/lang/String;II[BI)V");
    if (browser->browserCallbackDispatch == NULL) {
		THROW_EXCEPTION(e, JNI_EXCP, "Unable to get callback dispatch method ID");
		goto bail;
    }

    // create global ref to our object
    browser->browserObject = (*e)->NewGlobalRef(e, t);
    if (browser->browserObject==NULL) {
        THROW_EXCEPTION(e, JNI_EXCP, "Unable to create global ref to browser object");
        goto bail;
    }

	// create browser
	AVAHI_LOCK(client);
	if (!(browser->browser=avahi_record_browser_new(client->client, if_idx,
			proto, name, clazz, type, flags, browser_callback, browser))) {
		AVAHI_UNLOCK(client);
		THROW_EXCEPTION(e, GENERIC_EXCP, "Error creating avahi record browser");
		goto bail;
	}
	AVAHI_UNLOCK(client);

	// free utf string
	PUT_UTF_STR(name, jname, e);

	return (uintptr_t) browser;


bail:
	if(browser->browserObject)
		(*e)->DeleteGlobalRef(e, browser->browserObject);

	XFREE(browser);

	PUT_UTF_STR(name, jname, e);

	return 0;
}
Esempio n. 7
0
static int
spawn_record_browser(AvahiClient *c, AvahiIfIndex intf, AvahiProtocol proto, const char *hostname, const char *domain,
		     uint16_t type, struct mdns_browser *mb, const char *name, uint16_t port, AvahiStringList *txt)
{
  AvahiRecordBrowser *rb;
  struct mdns_record_browser *rb_data;
  char *key;
  char *value;
  char *ptr;
  size_t len;
  int ret;

  rb_data = (struct mdns_record_browser *)malloc(sizeof(struct mdns_record_browser));
  if (!rb_data)
    {
      DPRINTF(E_LOG, L_MDNS, "Out of memory for record browser data\n");

      return -1;
    }

  memset(rb_data, 0, sizeof(struct mdns_record_browser));

  rb_data->mb = mb;
  rb_data->port = port;

  rb_data->name = strdup(name);
  if (!rb_data->name)
    {
      DPRINTF(E_LOG, L_MDNS, "Out of memory for service name\n");

      goto out_free_rb;
    }

  rb_data->domain = strdup(domain);
  if (!rb_data->domain)
    {
      DPRINTF(E_LOG, L_MDNS, "Out of memory for service domain\n");

      goto out_free_name;
    }

  while (txt)
    {
      len = avahi_string_list_get_size(txt);
      key = (char *)avahi_string_list_get_text(txt);

      ptr = memchr(key, '=', len);
      if (!ptr)
	{
	  value = "";
	  len = 0;
	}
      else
	{
	  *ptr = '\0';
	  value = ptr + 1;

	  len -= strlen(key) + 1;
	}

      ret = keyval_add_size(&rb_data->txt_kv, key, value, len);

      if (ptr)
	*ptr = '=';

      if (ret < 0)
	{
	  DPRINTF(E_LOG, L_MDNS, "Could not build TXT record keyval\n");

	  goto out_free_keyval;
	}

      txt = avahi_string_list_get_next(txt);
    }

  rb = NULL;
  switch (type)
    {
      case AVAHI_DNS_TYPE_A:
	rb = avahi_record_browser_new(c, intf, proto, hostname,
				      AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_A, 0,
				      browse_record_callback_v4, rb_data);
	if (!rb)
	  DPRINTF(E_LOG, L_MDNS, "Could not create v4 record browser for host %s: %s\n",
		  hostname, avahi_strerror(avahi_client_errno(c)));
	break;

      case AVAHI_DNS_TYPE_AAAA:
	rb = avahi_record_browser_new(c, intf, proto, hostname,
				      AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_AAAA, 0,
				      browse_record_callback_v6, rb_data);
	if (!rb)
	  DPRINTF(E_LOG, L_MDNS, "Could not create v4 record browser for host %s: %s\n",
		  hostname, avahi_strerror(avahi_client_errno(c)));
	break;
    }

  if (!rb)
    goto out_free_keyval;

  return 0;

 out_free_keyval:
  keyval_clear(&rb_data->txt_kv);
  free(rb_data->domain);
 out_free_name:
  free(rb_data->name);
 out_free_rb:
  free(rb_data);

  return -1;
}
Esempio n. 8
0
static void
browse_resolve_callback(AvahiServiceResolver *r, AvahiIfIndex intf, AvahiProtocol proto, AvahiResolverEvent event,
			const char *name, const char *type, const char *domain, const char *hostname, const AvahiAddress *addr,
			uint16_t port, AvahiStringList *txt, AvahiLookupResultFlags flags, void *userdata)
{
  AvahiRecordBrowser *rb;
  struct mdns_browser *mb;
  struct mdns_record_browser *rb_data;
  char *key;
  char *value;
  uint16_t dns_type;
  int family;
  int ret;

  mb = (struct mdns_browser *)userdata;

  if (event != AVAHI_RESOLVER_FOUND)
    {
      if (event == AVAHI_RESOLVER_FAILURE)
	DPRINTF(E_LOG, L_MDNS, "Avahi Resolver failure: service '%s' type '%s' proto %d: %s\n", name, type, proto, MDNSERR);
      else
	DPRINTF(E_LOG, L_MDNS, "Avahi Resolver empty callback\n");

      family = avahi_proto_to_af(proto);
      if (family != AF_UNSPEC)
	mb->cb(name, type, domain, NULL, family, NULL, -1, NULL);

      // We don't clean up resolvers because we want a notification from them if
      // the service reappears (e.g. if device was switched off and then on)

      return;
    }

  DPRINTF(E_DBG, L_MDNS, "Avahi Resolver: resolved service '%s' type '%s' proto %d, host %s\n", name, type, proto, hostname);

  CHECK_NULL(L_MDNS, rb_data = calloc(1, sizeof(struct mdns_record_browser)));

  rb_data->name = strdup(name);
  rb_data->domain = strdup(domain);
  rb_data->mb = mb;
  rb_data->port = port;

  while (txt)
    {
      ret = avahi_string_list_get_pair(txt, &key, &value, NULL);
      txt = avahi_string_list_get_next(txt);

      if (ret < 0)
	continue;

      if (value)
	{
	  keyval_add(&rb_data->txt_kv, key, value);
	  avahi_free(value);
	}

      avahi_free(key);
    }

  if (proto == AVAHI_PROTO_INET6)
    dns_type = AVAHI_DNS_TYPE_AAAA;
  else
    dns_type = AVAHI_DNS_TYPE_A;

  // We need to implement a record browser because the announcement from some
  // devices (e.g. ApEx 1 gen) will include multiple records, and we need to
  // filter out those records that won't work (notably link-local). The value of
  // *addr given by browse_resolve_callback is just the first record.
  rb = avahi_record_browser_new(mdns_client, intf, proto, hostname, AVAHI_DNS_CLASS_IN, dns_type, 0, browse_record_callback, rb_data);
  if (!rb)
    DPRINTF(E_LOG, L_MDNS, "Could not create record browser for host %s: %s\n", hostname, MDNSERR);
}